diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 986d213..db8e0fb 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -296,6 +296,9 @@ void CubicSDR::removeRemote(std::string remoteAddr) { void CubicSDR::sdrThreadNotify(SDRThread::SDRThreadState state, std::string message) { notify_busy.lock(); + if (state == SDRThread::SDR_THREAD_INITIALIZED) { + appframe->initDeviceParams(getDevice()); + } if (state == SDRThread::SDR_THREAD_MESSAGE) { notifyMessage = message; } @@ -422,8 +425,6 @@ void CubicSDR::setDevice(SDRDeviceInfo *dev) { setOffset(devConfig->getOffset()); t_SDR = new std::thread(&SDRThread::threadMain, sdrThread); - - appframe->initDeviceParams(dev); } } @@ -463,6 +464,11 @@ SDRPostThread *CubicSDR::getSDRPostThread() { return sdrPostThread; } +SDRThread *CubicSDR::getSDRThread() { + return sdrThread; +} + + void CubicSDR::bindDemodulator(DemodulatorInstance *demod) { if (!demod) { return; diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 598b767..1946660 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -76,7 +76,8 @@ public: DemodulatorMgr &getDemodMgr(); SDRPostThread *getSDRPostThread(); - + SDRThread *getSDRThread(); + void bindDemodulator(DemodulatorInstance *demod); void removeDemodulator(DemodulatorInstance *demod); diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index 729df43..7502074 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -31,6 +31,7 @@ SDRThread::SDRThread() : IOThread() { agc_mode.store(true); agc_mode_changed.store(false); gain_value_changed.store(false); + setting_value_changed.store(false); } SDRThread::~SDRThread() { @@ -81,6 +82,30 @@ void SDRThread::init() { inpBuffer.data.resize(numElems.load()); buffs[0] = malloc(numElems * 2 * sizeof(float)); + + SoapySDR::ArgInfoList settingsInfo = device->getSettingInfo(); + SoapySDR::ArgInfoList::const_iterator settings_i; + + if (!setting_value_changed.load()) { + settings.erase(settings.begin(), settings.end()); + settingChanged.erase(settingChanged.begin(), settingChanged.end()); + } + + setting_busy.lock(); + for (settings_i = settingsInfo.begin(); settings_i != settingsInfo.end(); settings_i++) { + SoapySDR::ArgInfo setting = (*settings_i); + if ((settingChanged.find(setting.key) != settingChanged.end()) && (settings.find(setting.key) != settings.end())) { + device->writeSetting(setting.key, settings[setting.key]); + settingChanged[setting.key] = false; + } else { + settings[setting.key] = device->readSetting(setting.key); + settingChanged[setting.key] = false; + } + } + setting_value_changed.store(false); + setting_busy.unlock(); + + wxGetApp().sdrThreadNotify(SDRThread::SDR_THREAD_INITIALIZED, std::string("Device Initialized.")); } void SDRThread::deinit() { @@ -139,57 +164,10 @@ void SDRThread::readLoop() { updateGains(); while (!terminated.load()) { - if (offset_changed.load()) { - if (!freq_changed.load()) { - frequency.store(frequency.load()); - freq_changed.store(true); - } - offset_changed.store(false); - } - if (rate_changed.load()) { - device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load()); - sampleRate.store(device->getSampleRate(SOAPY_SDR_RX,0)); - numChannels.store(getOptimalChannelCount(sampleRate.load())); - numElems.store(getOptimalElementCount(sampleRate.load(), 60)); - inpBuffer.data.resize(numElems.load()); - free(buffs[0]); - buffs[0] = malloc(numElems.load() * 2 * sizeof(float)); - rate_changed.store(false); - } - if (ppm_changed.load() && hasPPM.load()) { - device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm.load()); - ppm_changed.store(false); - } - if (freq_changed.load()) { - device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency.load() - offset.load()); - freq_changed.store(false); - } - if (agc_mode_changed.load()) { - SDRDeviceInfo *devInfo = deviceInfo.load(); - - device->setGainMode(SOAPY_SDR_RX,devInfo->getRxChannel()->getChannel(),agc_mode.load()); - agc_mode_changed.store(false); - if (!agc_mode.load()) { - updateGains(); - } - } - if (gain_value_changed.load() && !agc_mode.load()) { - SDRDeviceInfo *devInfo = deviceInfo.load(); - - gain_busy.lock(); - for (std::map::iterator gci = gainChanged.begin(); gci != gainChanged.end(); gci++) { - if (gci->second) { - device->setGain(SOAPY_SDR_RX, devInfo->getRxChannel()->getChannel(), gci->first, gainValues[gci->first]); - gainChanged[gci->first] = false; - } - } - gain_busy.unlock(); - - gain_value_changed.store(false); - } - + updateSettings(); readStream(iqDataOutQueue); } + buffers.purge(); } @@ -208,6 +186,76 @@ void SDRThread::updateGains() { gain_value_changed.store(false); } +void SDRThread::updateSettings() { + if (offset_changed.load()) { + if (!freq_changed.load()) { + frequency.store(frequency.load()); + freq_changed.store(true); + } + offset_changed.store(false); + } + + if (rate_changed.load()) { + device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load()); + sampleRate.store(device->getSampleRate(SOAPY_SDR_RX,0)); + numChannels.store(getOptimalChannelCount(sampleRate.load())); + numElems.store(getOptimalElementCount(sampleRate.load(), 60)); + inpBuffer.data.resize(numElems.load()); + free(buffs[0]); + buffs[0] = malloc(numElems.load() * 2 * sizeof(float)); + rate_changed.store(false); + } + + if (ppm_changed.load() && hasPPM.load()) { + device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm.load()); + ppm_changed.store(false); + } + + if (freq_changed.load()) { + device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency.load() - offset.load()); + freq_changed.store(false); + } + + if (agc_mode_changed.load()) { + SDRDeviceInfo *devInfo = deviceInfo.load(); + + device->setGainMode(SOAPY_SDR_RX,devInfo->getRxChannel()->getChannel(),agc_mode.load()); + agc_mode_changed.store(false); + if (!agc_mode.load()) { + updateGains(); + } + } + + if (gain_value_changed.load() && !agc_mode.load()) { + SDRDeviceInfo *devInfo = deviceInfo.load(); + + gain_busy.lock(); + for (std::map::iterator gci = gainChanged.begin(); gci != gainChanged.end(); gci++) { + if (gci->second) { + device->setGain(SOAPY_SDR_RX, devInfo->getRxChannel()->getChannel(), gci->first, gainValues[gci->first]); + gainChanged[gci->first] = false; + } + } + gain_busy.unlock(); + + gain_value_changed.store(false); + } + + + if (setting_value_changed.load()) { + setting_busy.lock(); + + for (std::map::iterator sci = settingChanged.begin(); sci != settingChanged.end(); sci++) { + if (sci->second) { + device->writeSetting(sci->first, settings[sci->first]); + settingChanged[sci->first] = false; + } + } + + setting_value_changed.store(false); + setting_busy.unlock(); + } +} void SDRThread::run() { //#ifdef __APPLE__ @@ -341,3 +389,20 @@ float SDRThread::getGain(std::string name) { gain_busy.unlock(); return val; } + +void SDRThread::writeSetting(std::string name, std::string value) { + setting_busy.lock(); + settings[name] = value; + settingChanged[name] = true; + setting_value_changed.store(true); + setting_busy.unlock(); +} + +std::string SDRThread::readSetting(std::string name) { + std::string val; + setting_busy.lock(); + val = device->readSetting(name); + setting_busy.unlock(); + return val; +} + diff --git a/src/sdr/SoapySDRThread.h b/src/sdr/SoapySDRThread.h index 8cee44a..566422a 100644 --- a/src/sdr/SoapySDRThread.h +++ b/src/sdr/SoapySDRThread.h @@ -48,7 +48,7 @@ private: public: SDRThread(); ~SDRThread(); - enum SDRThreadState { SDR_THREAD_MESSAGE, SDR_THREAD_TERMINATED, SDR_THREAD_FAILED }; + enum SDRThreadState { SDR_THREAD_MESSAGE, SDR_THREAD_INITIALIZED, SDR_THREAD_TERMINATED, SDR_THREAD_FAILED }; void run(); @@ -75,9 +75,13 @@ public: void setGain(std::string name, float value); float getGain(std::string name); + void writeSetting(std::string name, std::string value); + std::string readSetting(std::string name); + protected: void updateGains(); - + void updateSettings(); + SoapySDR::Stream *stream; SoapySDR::Device *device; void *buffs[1]; @@ -85,13 +89,17 @@ protected: SDRThreadIQData inpBuffer; std::atomic deviceConfig; std::atomic deviceInfo; + + std::mutex setting_busy; + std::map settings; + std::map settingChanged; std::atomic sampleRate; std::atomic_llong frequency, offset; std::atomic_int ppm, numElems, numChannels; std::atomic_bool hasPPM, hasHardwareDC; std::atomic_bool agc_mode, rate_changed, freq_changed, offset_changed, - ppm_changed, device_changed, agc_mode_changed, gain_value_changed; + ppm_changed, device_changed, agc_mode_changed, gain_value_changed, setting_value_changed; std::mutex gain_busy; std::map gainValues;