diff --git a/CMakeLists.txt b/CMakeLists.txt index b7a11028..ad1754c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ option(OPT_BUILD_FILE_SOURCE "Wav file source" ON) option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Dependencies: libhackrf)" ON) option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Dependencies: liblimesuite)" OFF) option(OPT_BUILD_SDDC_SOURCE "Build SDDC Source Module (Dependencies: libusb-1.0)" OFF) -option(OPT_BUILD_RFSPACE_SOURCE "Build RFspace Source Module no dependencies required)" OFF) +option(OPT_BUILD_RFSPACE_SOURCE "Build RFspace Source Module (no dependencies required)" ON) option(OPT_BUILD_RTL_SDR_SOURCE "Build RTL-SDR Source Module (Dependencies: librtlsdr)" ON) option(OPT_BUILD_RTL_TCP_SOURCE "Build RTL-TCP Source Module (no dependencies required)" ON) option(OPT_BUILD_SDRPLAY_SOURCE "Build SDRplay Source Module (Dependencies: libsdrplay)" OFF) diff --git a/core/src/utils/optionlist.h b/core/src/utils/optionlist.h index e541786b..97f71da3 100644 --- a/core/src/utils/optionlist.h +++ b/core/src/utils/optionlist.h @@ -111,7 +111,7 @@ private: txt = _txt.c_str(); } - std::vector keys; + std::vector keys; std::vector names; std::vector values; std::string _txt; diff --git a/source_modules/rfspace_source/src/main.cpp b/source_modules/rfspace_source/src/main.cpp index 77236df4..d982fd42 100644 --- a/source_modules/rfspace_source/src/main.cpp +++ b/source_modules/rfspace_source/src/main.cpp @@ -9,7 +9,7 @@ #include #include #include - +#include #define CONCAT(a, b) ((std::string(a) + b).c_str()) @@ -23,9 +23,9 @@ SDRPP_MOD_INFO{ ConfigManager config; -class SpyServerSourceModule : public ModuleManager::Instance { +class RFSpaceSource : public ModuleManager::Instance { public: - SpyServerSourceModule(std::string name) { + RFSpaceSource(std::string name) { this->name = name; handler.ctx = this; @@ -42,7 +42,7 @@ public: sigpath::sourceManager.registerSource("RFspace", &handler); } - ~SpyServerSourceModule() { + ~RFSpaceSource() { stop(this); sigpath::sourceManager.unregisterSource("RFspace"); } @@ -77,49 +77,50 @@ private: } static void menuSelected(void* ctx) { - SpyServerSourceModule* _this = (SpyServerSourceModule*)ctx; + RFSpaceSource* _this = (RFSpaceSource*)ctx; core::setInputSampleRate(_this->sampleRate); gui::mainWindow.playButtonLocked = !(_this->client && _this->client->isOpen()); - spdlog::info("SpyServerSourceModule '{0}': Menu Select!", _this->name); + spdlog::info("RFSpaceSource '{0}': Menu Select!", _this->name); } static void menuDeselected(void* ctx) { - SpyServerSourceModule* _this = (SpyServerSourceModule*)ctx; + RFSpaceSource* _this = (RFSpaceSource*)ctx; gui::mainWindow.playButtonLocked = false; - spdlog::info("SpyServerSourceModule '{0}': Menu Deselect!", _this->name); + spdlog::info("RFSpaceSource '{0}': Menu Deselect!", _this->name); } static void start(void* ctx) { - SpyServerSourceModule* _this = (SpyServerSourceModule*)ctx; + RFSpaceSource* _this = (RFSpaceSource*)ctx; if (_this->running) { return; } - // TODO: Start + // TODO: Set configuration here + if (_this->client) { _this->client->start(rfspace::RFSPACE_SAMP_FORMAT_COMPLEX, rfspace::RFSPACE_SAMP_FORMAT_16BIT); } _this->running = true; - spdlog::info("SpyServerSourceModule '{0}': Start!", _this->name); + spdlog::info("RFSpaceSource '{0}': Start!", _this->name); } static void stop(void* ctx) { - SpyServerSourceModule* _this = (SpyServerSourceModule*)ctx; + RFSpaceSource* _this = (RFSpaceSource*)ctx; if (!_this->running) { return; } - // TODO: Stop + if (_this->client) { _this->client->stop(); } _this->running = false; - spdlog::info("SpyServerSourceModule '{0}': Stop!", _this->name); + spdlog::info("RFSpaceSource '{0}': Stop!", _this->name); } static void tune(double freq, void* ctx) { - SpyServerSourceModule* _this = (SpyServerSourceModule*)ctx; - if (_this->running) { - // TODO: Tune + RFSpaceSource* _this = (RFSpaceSource*)ctx; + if (_this->running && _this->client) { + _this->client->setFrequency(freq); } _this->freq = freq; - spdlog::info("SpyServerSourceModule '{0}': Tune: {1}!", _this->name, freq); + spdlog::info("RFSpaceSource '{0}': Tune: {1}!", _this->name, freq); } static void menuHandler(void* ctx) { - SpyServerSourceModule* _this = (SpyServerSourceModule*)ctx; + RFSpaceSource* _this = (RFSpaceSource*)ctx; float menuWidth = ImGui::GetContentRegionAvailWidth(); bool connected = (_this->client && _this->client->isOpen()); @@ -143,7 +144,9 @@ private: if (_this->running) { style::beginDisabled(); } if (!connected && ImGui::Button("Connect##rfspace_source", ImVec2(menuWidth, 0))) { try { + if (_this->client) { _this->client.reset(); } _this->client = rfspace::connect(_this->hostname, _this->port, &_this->stream); + _this->deviceInit(); } catch (std::exception e) { spdlog::error("Could not connect to SDR: {0}", e.what()); @@ -158,9 +161,36 @@ private: if (connected) { // TODO: Options here + if (_this->running) { style::beginDisabled(); } + + ImGui::LeftLabel("Samplerate"); + ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); + if (ImGui::Combo("##rfspace_source_samp_rate", &_this->srId, _this->sampleRates.txt)) { + _this->sampleRate = _this->sampleRates[_this->srId]; + _this->client->setSampleRate(_this->sampleRate); + core::setInputSampleRate(_this->sampleRate); + // TODO: Save config + } + + if (_this->running) { style::endDisabled(); } + + ImGui::LeftLabel("Antenna Port"); + ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); + if (ImGui::Combo("##rfspace_source_rf_port", &_this->rfPortId, _this->rfPorts.txt)) { + _this->client->setPort(_this->rfPorts[_this->rfPortId]); + // TODO: Save config + } + + ImGui::LeftLabel("Gain"); + ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); + if (ImGui::SliderFloatWithSteps("##rfspace_source_gain", &_this->gain, -30, 0, 10, "%.0f dB")) { + _this->client->setGain(_this->gain); + // TODO: Save config (as int, in case we have to switch to an option list) + } + ImGui::Text("Status:"); ImGui::SameLine(); - ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "Connected (DEV NAME HERE)"); + ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "Connected (%s)", _this->deviceName.c_str()); } else { ImGui::Text("Status:"); @@ -169,18 +199,53 @@ private: } } + void deviceInit() { + // Get device name + if (deviceNames.find(client->deviceId) != deviceNames.end()) { + deviceName = deviceNames[client->deviceId]; + } + else { + deviceName = "Unknown"; + } + + // Create samplerate list (TODO: Depends on model) + auto srs = client->getValidSampleRates(); + sampleRates.clear(); + for (auto& sr : srs) { + sampleRates.define(sr, getBandwdithScaled(sr), sr); + } + + // Create RF port list (TODO: Depends on model) + rfPorts.clear(); + rfPorts.define("Port 1", rfspace::RFSPACE_RF_PORT_1); + rfPorts.define("Port 2", rfspace::RFSPACE_RF_PORT_2); + + // TODO: Load config + } + std::string name; bool enabled = true; bool running = false; - double sampleRate = 1000000; + double sampleRate = 1228800; double freq; + OptionList sampleRates; + int srId = 0; + + OptionList rfPorts; + int rfPortId = 0; + + float gain = 0; + char hostname[1024]; int port = 50000; - int srId = 0; - std::vector sampleRates; - std::string sampleRatesTxt; + std::string deviceName = "Unknown"; + std::map deviceNames = { + { rfspace::RFSPACE_DEV_ID_CLOUD_SDR, "CloudSDR" }, + { rfspace::RFSPACE_DEV_ID_CLOUD_IQ, "CloudIQ" }, + { rfspace::RFSPACE_DEV_ID_NET_SDR, "NetSDR" } + }; dsp::stream stream; SourceManager::SourceHandler handler; @@ -208,11 +273,11 @@ MOD_EXPORT void _INIT_() { } MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) { - return new SpyServerSourceModule(name); + return new RFSpaceSource(name); } MOD_EXPORT void _DELETE_INSTANCE_(ModuleManager::Instance* instance) { - delete (SpyServerSourceModule*)instance; + delete (RFSpaceSource*)instance; } MOD_EXPORT void _END_() { diff --git a/source_modules/rfspace_source/src/rfspace_client.cpp b/source_modules/rfspace_source/src/rfspace_client.cpp index 82a328bc..28f1ffeb 100644 --- a/source_modules/rfspace_source/src/rfspace_client.cpp +++ b/source_modules/rfspace_source/src/rfspace_client.cpp @@ -10,22 +10,40 @@ namespace rfspace { client = std::move(conn); udpClient = std::move(udpConn); output = out; + + // Allocate buffers rbuffer = new uint8_t[RFSPACE_MAX_SIZE]; sbuffer = new uint8_t[RFSPACE_MAX_SIZE]; ubuffer = new uint8_t[RFSPACE_MAX_SIZE]; + // Clear write stop of stream just in case output->clearWriteStop(); - uint8_t test = 0x5A; - udpClient->write(1, &test); + // Send UDP packet so that a router opens the port + sendDummyUDP(); // Start readers client->readAsync(sizeof(tcpHeader), (uint8_t*)&tcpHeader, tcpHandler, this); - udpClient->readAsync(sizeof(udpHeader), (uint8_t*)&udpHeader, udpHandler, this); + udpClient->readAsync(RFSPACE_MAX_SIZE, ubuffer, udpHandler, this); - // Start SDR - uint8_t args[4] = { 0x70, 2, 0, 0 }; - setControlItem(0x18, args, 4); + // Get device ID and wait for response + getControlItem(RFSPACE_CTRL_ITEM_PROD_ID, NULL, 0); + { + std::unique_lock lck(devIdMtx); + if (!devIdCnd.wait_for(lck, std::chrono::milliseconds(RFSPACE_TIMEOUT_MS), [=](){ return devIdAvailable; })) { + throw std::runtime_error("Could not identify remote device"); + } + } + + // Default configuration + stop(); + setSampleRate(1228800); + setFrequency(8830000); + setGain(0); + setPort(RFSPACE_RF_PORT_1); + + // Start heartbeat + heartBeatThread = std::thread(&RFspaceClientClass::heartBeatWorker, this); } RFspaceClientClass::~RFspaceClientClass() { @@ -35,7 +53,12 @@ namespace rfspace { delete[] ubuffer; } - int RFspaceClientClass::getControlItem(uint16_t item, void* param, int len) { + void RFspaceClientClass::sendDummyUDP() { + uint8_t dummy = 0x5A; + udpClient->write(1, &dummy); + } + + int RFspaceClientClass::getControlItem(ControlItem item, void* param, int len) { // Build packet uint16_t* header = (uint16_t*)&sbuffer[0]; uint16_t* item_val = (uint16_t*)&sbuffer[2]; @@ -43,26 +66,12 @@ namespace rfspace { *item_val = item; // Send packet - SCIRRecv.release(); client->write(4, sbuffer); - // Wait for a response - if (!SCIRRecv.await(2000)) { - SCIRRecv.release(); - return -1; - } - - // Forward data - int toRead = ((SCIRSize - 4) < len) ? (SCIRSize - 4) : len; - memcpy(param, &rbuffer[4], toRead); - - // Release receiving thread - SCIRRecv.release(); - - return toRead; + return -1; } - void RFspaceClientClass::setControlItem(uint16_t item, void* param, int len) { + void RFspaceClientClass::setControlItem(ControlItem item, void* param, int len) { // Build packet uint16_t* header = (uint16_t*)&sbuffer[0]; uint16_t* item_val = (uint16_t*)&sbuffer[2]; @@ -74,10 +83,78 @@ namespace rfspace { client->write(len + 4, sbuffer); } + void RFspaceClientClass::setControlItemWithChanID(ControlItem item, uint8_t chanId, void* param, int len) { + // Build packet + uint16_t* header = (uint16_t*)&sbuffer[0]; + uint16_t* item_val = (uint16_t*)&sbuffer[2]; + uint8_t* chan = &sbuffer[4]; + *header = (len + 5) | (RFSPACE_MSG_TYPE_H2T_SET_CTRL_ITEM << 13); + *item_val = item; + *chan = chanId; + memcpy(&sbuffer[5], param, len); + + // Send packet + client->write(len + 5, sbuffer); + } + + std::vector RFspaceClientClass::getValidSampleRates() { + std::vector sr; + + switch (deviceId) { + case RFSPACE_DEV_ID_CLOUD_SDR: + case RFSPACE_DEV_ID_CLOUD_IQ: + for (int n = 122880000 / (4 * 25); n >= 32000; n /= 2) { + sr.push_back(n); + } + break; + case RFSPACE_DEV_ID_NET_SDR: + for (int n = 80000000 / (4 * 25); n >= 32000; n /= 2) { + sr.push_back(n); + } + break; + default: + break; + } + + return sr; + } + + void RFspaceClientClass::setFrequency(uint64_t freq) { + setControlItemWithChanID(RFSPACE_CTRL_ITEM_NCO_FREQUENCY, 0, &freq, 5); + } + + void RFspaceClientClass::setPort(RFPort port) { + uint8_t value = port; + spdlog::warn("{0}", value); + setControlItemWithChanID(RFSPACE_CTRL_ITEM_RF_PORT, 0, &value, sizeof(value)); + } + + void RFspaceClientClass::setGain(int8_t gain) { + setControlItemWithChanID(RFSPACE_CTRL_ITEM_RF_GAIN, 0, &gain, sizeof(gain)); + } + + void RFspaceClientClass::setSampleRate(uint32_t sampleRate) { + setControlItemWithChanID(RFSPACE_CTRL_ITEM_IQ_SAMP_RATE, 0, &sampleRate, sizeof(sampleRate)); + } + + void RFspaceClientClass::start(SampleFormat sampleFormat, SampleDepth sampleDepth) { + uint8_t args[4] = { sampleFormat, RFSPACE_STATE_RUN, sampleDepth, 0 }; + setControlItem(RFSPACE_CTRL_ITEM_STATE, args, sizeof(args)); + } + + void RFspaceClientClass::stop() { + uint8_t args[4] = { 0, RFSPACE_STATE_IDLE, 0, 0 }; + setControlItem(RFSPACE_CTRL_ITEM_STATE, args, sizeof(args)); + } + void RFspaceClientClass::close() { output->stopWriter(); + stopHeartBeat = true; + heartBeatCnd.notify_all(); + if (heartBeatThread.joinable()) { heartBeatThread.join(); } client->close(); udpClient->close(); + output->clearWriteStop(); } bool RFspaceClientClass::isOpen() { @@ -94,12 +171,17 @@ namespace rfspace { _this->client->read(size - 2, &_this->rbuffer[2]); } - spdlog::warn("TCP received: {0} {1}", type, size); + // spdlog::warn("TCP received: {0} {1}", type, size); - // Process data - if (type == RFSPACE_MSG_TYPE_T2H_SET_CTRL_ITEM_RESP) { - _this->SCIRSize = size; - _this->SCIRRecv.trigger(); + // Check for a device ID + uint16_t* controlItem = (uint16_t*)&_this->rbuffer[2]; + if (type == RFSPACE_MSG_TYPE_T2H_SET_CTRL_ITEM_RESP && *controlItem == RFSPACE_CTRL_ITEM_PROD_ID) { + { + std::lock_guard lck(_this->devIdMtx); + _this->deviceId = (DeviceID)*(uint32_t*)&_this->rbuffer[4]; + _this->devIdAvailable = true; + } + _this->devIdCnd.notify_all(); } // Restart an async read @@ -108,18 +190,31 @@ namespace rfspace { void RFspaceClientClass::udpHandler(int count, uint8_t* buf, void* ctx) { RFspaceClientClass* _this = (RFspaceClientClass*)ctx; - uint8_t type = _this->udpHeader >> 13; - uint16_t size = _this->udpHeader & 0b1111111111111; + uint16_t hdr = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8); + uint8_t type = hdr >> 13; + uint16_t size = hdr & 0b1111111111111; - spdlog::warn("UDP received: {0} {1}", type, size); - - // Read the rest of the data - if (size > 2) { - _this->client->read(size - 2, &_this->rbuffer[2]); + if (type == RFSPACE_MSG_TYPE_T2H_DATA_ITEM_0) { + int16_t* samples = (int16_t*)&buf[4]; + int sampCount = (size - 4) / (2 * sizeof(int16_t)); + volk_16i_s32f_convert_32f((float*)_this->output->writeBuf, samples, 32768.0f, sampCount * 2); + _this->output->swap(sampCount); } // Restart an async read - _this->client->readAsync(sizeof(_this->udpHeader), (uint8_t*)&_this->udpHeader, udpHandler, _this); + _this->udpClient->readAsync(RFSPACE_MAX_SIZE, _this->ubuffer, udpHandler, _this); + } + + void RFspaceClientClass::heartBeatWorker() { + uint8_t dummy[4]; + while (true) { + getControlItem(RFSPACE_CTRL_ITEM_STATE, dummy, sizeof(dummy)); + + std::unique_lock lck(heartBeatMtx); + bool to = heartBeatCnd.wait_for(lck, std::chrono::milliseconds(RFSPACE_HEARTBEAT_INTERVAL_MS), [=](){ return stopHeartBeat; }); + + if (to) { return; } + } } RFspaceClient connect(std::string host, uint16_t port, dsp::stream* out) { diff --git a/source_modules/rfspace_source/src/rfspace_client.h b/source_modules/rfspace_source/src/rfspace_client.h index 9903cfd4..fb927868 100644 --- a/source_modules/rfspace_source/src/rfspace_client.h +++ b/source_modules/rfspace_source/src/rfspace_client.h @@ -3,11 +3,14 @@ #include #include #include +#include -#define RFSPACE_MAX_SIZE 8192 +#define RFSPACE_MAX_SIZE 8192 +#define RFSPACE_HEARTBEAT_INTERVAL_MS 1000 +#define RFSPACE_TIMEOUT_MS 3000 namespace rfspace { - enum { + enum H2TMessageType { RFSPACE_MSG_TYPE_H2T_SET_CTRL_ITEM, RFSPACE_MSG_TYPE_H2T_REQ_CTRL_ITEM, RFSPACE_MSG_TYPE_H2T_REQ_CTRL_ITEM_RANGE, @@ -18,7 +21,7 @@ namespace rfspace { RFSPACE_MSG_TYPE_H2T_DATA_ITEM_3, }; - enum { + enum T2HMessageType { RFSPACE_MSG_TYPE_T2H_SET_CTRL_ITEM_RESP, RFSPACE_MSG_TYPE_T2H_UNSOL_CTRL_ITEM, RFSPACE_MSG_TYPE_T2H_REQ_CTRL_ITEM_RANGE_RESP, @@ -29,63 +32,67 @@ namespace rfspace { RFSPACE_MSG_TYPE_T2H_DATA_ITEM_3, }; - class SyncEvent { - public: - bool await(int timeoutMS) { - // Mark as waiting - { - std::lock_guard lck(waitingmtx); - waiting = true; - } + enum RFPort { + RFSPACE_RF_PORT_AUTO, + RFSPACE_RF_PORT_1, + RFSPACE_RF_PORT_2 + }; - // Wait for data - std::unique_lock lck(mtx); - return cnd.wait_for(lck, std::chrono::milliseconds(timeoutMS), [this]() { return triggered; }); + enum SampleFormat { + RFSPACE_SAMP_FORMAT_REAL = 0x00, + RFSPACE_SAMP_FORMAT_COMPLEX = 0x80 + }; - // Mark as not waiting - { - std::lock_guard lck(waitingmtx); - waiting = false; - } - } + enum State { + RFSPACE_STATE_IDLE = 1, + RFSPACE_STATE_RUN = 2 + }; - void release() { - // Mark as not waiting, and if last notify sender - { - std::lock_guard lck(mtx); - triggered = false; - } - cnd.notify_all(); - } + enum SampleDepth { + RFSPACE_SAMP_FORMAT_16BIT = 0x00, + RFSPACE_SAMP_FORMAT_24BIT = 0x80 + }; - void trigger() { - // Check if a waiter is waiting - { - std::lock_guard lck(waitingmtx); - if (waiting <= 0) { return; } - } + enum DeviceID { + RFSPACE_DEV_ID_CLOUD_SDR = 0x44534C43, + RFSPACE_DEV_ID_CLOUD_IQ = 0x51494C43, + RFSPACE_DEV_ID_NET_SDR = 0xDEADBEEF // TODO + }; - // Notify waiters - { - std::lock_guard lck(mtx); - triggered = true; - } - cnd.notify_all(); - - // Wait for waiter to handle - { - std::unique_lock lck(mtx); - cnd.wait(lck, [this]() { return !triggered; }); - } - } - - private: - bool triggered; - std::mutex mtx; - std::condition_variable cnd; - - bool waiting; - std::mutex waitingmtx; + enum ControlItem { + RFSPACE_CTRL_ITEM_MODEL_NAME = 0x0001, + RFSPACE_CTRL_ITEM_SERIAL = 0x0002, + RFSPACE_CTRL_ITEM_IFACE_VER = 0x0003, + RFSPACE_CTRL_ITEM_VERSION = 0x0004, + RFSPACE_CTRL_ITEM_STATUS = 0x0005, + RFSPACE_CTRL_ITEM_DEV_NAME = 0x0008, + RFSPACE_CTRL_ITEM_PROD_ID = 0x0009, + RFSPACE_CTRL_ITEM_OPTIONS = 0x000A, + RFSPACE_CTRL_ITEM_SECURE_CODE = 0x000B, + RFSPACE_CTRL_ITEM_FPGA_CONF = 0x000C, + RFSPACE_CTRL_ITEM_STATE = 0x0018, + RFSPACE_CTRL_ITEM_NCO_FREQUENCY = 0x0020, + RFSPACE_CTRL_ITEM_RF_PORT = 0x0030, + RFSPACE_CTRL_ITEM_PORT_RANGE = 0x0032, + RFSPACE_CTRL_ITEM_RF_GAIN = 0x0038, + RFSPACE_CTRL_ITEM_DOWNCONV_GAIN = 0x003A, + RFSPACE_CTRL_ITEM_RF_FILTER = 0x0044, + RFSPACE_CTRL_ITEM_AD_MODE = 0x008A, + RFSPACE_CTRL_ITEM_SAMP_RATE_CAL = 0x00B0, + RFSPACE_CTRL_ITEM_TRIG_FREQ = 0x00B2, + RFSPACE_CTRL_ITEM_TRIG_PHASE = 0x00B3, + RFSPACE_CTRL_ITEM_SYNC_MODE = 0x00B4, + RFSPACE_CTRL_ITEM_IQ_SAMP_RATE = 0x00B8, + RFSPACE_CTRL_ITEM_UDP_PKT_SIZE = 0x00C4, + RFSPACE_CTRL_ITEM_UDP_ADDR = 0x00C5, + RFSPACE_CTRL_ITEM_TX_STATE = 0x0118, + RFSPACE_CTRL_ITEM_TX_FREQUENCY = 0x0120, + RFSPACE_CTRL_ITEM_TX_SAMP_RATE = 0x01B8, + RFSPACE_CTRL_ITEM_SERIAL_OPEN = 0x0200, + RFSPACE_CTRL_ITEM_SERIAL_CLOSE = 0x0201, + RFSPACE_CTRL_ITEM_SER_BOOT_RATE = 0x0202, + RFSPACE_CTRL_ITEM_AUX_SIG_MODE = 0x0280, + RFSPACE_CTRL_ITEM_ERROR_LOG = 0x0410 }; class RFspaceClientClass { @@ -93,18 +100,31 @@ namespace rfspace { RFspaceClientClass(net::Conn conn, net::Conn udpConn, dsp::stream* out); ~RFspaceClientClass(); - int getControlItem(uint16_t item, void* param, int len); - void setControlItem(uint16_t item, void* param, int len); + void sendDummyUDP(); + + int getControlItem(ControlItem item, void* param, int len); + void setControlItem(ControlItem item, void* param, int len); + void setControlItemWithChanID(ControlItem item, uint8_t chanId, void* param, int len); + + std::vector getValidSampleRates(); + + void setFrequency(uint64_t freq); + void setPort(RFPort port); + void setGain(int8_t gain); + void setSampleRate(uint32_t sampleRate); + + void start(SampleFormat sampleFormat, SampleDepth sampleDepth); + void stop(); void close(); bool isOpen(); - private: - void sendCommand(uint32_t command, void* data, int len); - void sendHandshake(std::string appName); + DeviceID deviceId; + private: static void tcpHandler(int count, uint8_t* buf, void* ctx); static void udpHandler(int count, uint8_t* buf, void* ctx); + void heartBeatWorker(); net::Conn client; net::Conn udpClient; @@ -118,8 +138,14 @@ namespace rfspace { uint8_t* sbuffer = NULL; uint8_t* ubuffer = NULL; - SyncEvent SCIRRecv; - int SCIRSize; + std::thread heartBeatThread; + std::mutex heartBeatMtx; + std::condition_variable heartBeatCnd; + volatile bool stopHeartBeat = false; + + bool devIdAvailable = false; + std::condition_variable devIdCnd; + std::mutex devIdMtx; }; typedef std::unique_ptr RFspaceClient; diff --git a/source_modules/spyserver_source/src/main.cpp b/source_modules/spyserver_source/src/main.cpp index 3bbdaeea..48ababab 100644 --- a/source_modules/spyserver_source/src/main.cpp +++ b/source_modules/spyserver_source/src/main.cpp @@ -178,6 +178,7 @@ private: if (_this->running) { style::beginDisabled(); } if (!connected && ImGui::Button("Connect##spyserver_source", ImVec2(menuWidth, 0))) { try { + if (_this->client) { _this->client.reset(); } _this->client = spyserver::connect(_this->hostname, _this->port, &_this->stream); if (!_this->client->waitForDevInfo(3000)) {