diff --git a/src/AppConfig.cpp b/src/AppConfig.cpp index 176838b..2315883 100644 --- a/src/AppConfig.cpp +++ b/src/AppConfig.cpp @@ -39,6 +39,14 @@ long DeviceConfig::getSampleRate() { return sampleRate.load(); } +void DeviceConfig::setAntennaName(const std::string& name) { + antennaName = name; +} + +const std::string& DeviceConfig::getAntennaName() { + return antennaName; +} + void DeviceConfig::setAGCMode(bool agcMode) { this->agcMode.store(agcMode); } @@ -81,7 +89,9 @@ std::string DeviceConfig::getDeviceName() { } void DeviceConfig::save(DataNode *node) { + std::lock_guard < std::mutex > lock(busy_lock); + *node->newChild("id") = deviceId; *node->newChild("name") = deviceName; *node->newChild("ppm") = ppm.load(); @@ -89,6 +99,10 @@ void DeviceConfig::save(DataNode *node) { *node->newChild("sample_rate") = sampleRate.load(); *node->newChild("agc_mode") = agcMode.load()?1:0; + if (!antennaName.empty()) { + *node->newChild("antenna") = antennaName; + } + if (streamOpts.size()) { DataNode *streamOptsNode = node->newChild("streamOpts"); for (ConfigSettings::const_iterator opt_i = streamOpts.begin(); opt_i != streamOpts.end(); opt_i++) { @@ -149,6 +163,12 @@ void DeviceConfig::load(DataNode *node) { sample_rate_node->element()->get(sampleRateValue); setSampleRate(sampleRateValue); } + if (node->hasAnother("antenna")) { + DataNode *antenna_node = node->getNext("antenna"); + std::string antennaNameValue; + antenna_node->element()->get(antennaNameValue); + setAntennaName(antennaNameValue); + } if (node->hasAnother("streamOpts")) { DataNode *streamOptsNode = node->getNext("streamOpts"); for (int i = 0, iMax = streamOptsNode->numChildren(); i settings; diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 7907fb0..92c3c73 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -752,11 +752,13 @@ void AppFrame::updateDeviceParams() { newSettingsMenu->AppendSeparator(); - newSettingsMenu->Append(wxID_SET_DB_OFFSET, "Power Level Offset"); - newSettingsMenu->Append(wxID_SET_FREQ_OFFSET, "Frequency Offset"); + settingsMenuItems.clear(); + + settingsMenuItems[wxID_SET_DB_OFFSET] = newSettingsMenu->Append(wxID_SET_DB_OFFSET, wxT("Power Level Offset : ") + std::to_string(wxGetApp().getConfig()->getDBOffset()) + wxT(" dB")); + settingsMenuItems[wxID_SET_FREQ_OFFSET] = newSettingsMenu->Append(wxID_SET_FREQ_OFFSET, wxT("Frequency Offset : ") + std::to_string(wxGetApp().getOffset()) + wxT(" Hz")); if (devInfo->hasCORR(SOAPY_SDR_RX, 0)) { - newSettingsMenu->Append(wxID_SET_PPM, "Device PPM"); + settingsMenuItems[wxID_SET_PPM] = newSettingsMenu->Append(wxID_SET_PPM, wxT("Device PPM : ") + std::to_string(wxGetApp().getPPM()) + wxT(" ppm")); } if (devInfo->getDriver() != "rtlsdr") { @@ -771,7 +773,43 @@ void AppFrame::updateDeviceParams() { } else if (!wxGetApp().getAGCMode()) { wxGetApp().setAGCMode(true); } - + + //Add an Antenna menu if more than one (RX) antenna, to keep the UI free of useless entries + antennaNames.clear(); + antennaMenuItems.clear(); + std::vector availableAntennas = devInfo->getAntennaNames(SOAPY_SDR_RX, 0); + + if (availableAntennas.size() > 1) { + + newSettingsMenu->AppendSeparator(); + + antennaNames = availableAntennas; + + wxMenu *subMenu = new wxMenu; + + int i = 0; + std::string antennaChecked; + for (std::string currentAntenna : availableAntennas) { + + antennaMenuItems[wxID_ANTENNAS_BASE + i] = subMenu->AppendRadioItem(wxID_ANTENNAS_BASE + i, currentAntenna); + + if (wxGetApp().getAntennaName() == currentAntenna) { + antennaMenuItems[wxID_ANTENNAS_BASE + i]->Check(true); + antennaChecked = currentAntenna; + } + + i++; + } + antennaMenuItems[wxID_ANTENNA_CURRENT] = newSettingsMenu->AppendSubMenu(subMenu, "Antenna"); + + //Change the Antenna label to indicate the current antenna. + if (!antennaChecked.empty()) { + antennaMenuItems[wxID_ANTENNA_CURRENT]->SetItemLabel(wxT("Antenna : ") + antennaChecked); + } + } + + //Runtime settings part + SoapySDR::ArgInfoList::const_iterator args_i; settingArgs = soapyDev->getSettingInfo(); @@ -790,15 +828,17 @@ void AppFrame::updateDeviceParams() { item->Check(currentVal=="true"); i++; } else if (arg.type == SoapySDR::ArgInfo::INT) { - newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); + + settingsMenuItems[wxID_SETTINGS_BASE + i] = newSettingsMenu->Append(wxID_SETTINGS_BASE + i, wxString(arg.name) + " : " + currentVal, arg.description); i++; } else if (arg.type == SoapySDR::ArgInfo::FLOAT) { - newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); + settingsMenuItems[wxID_SETTINGS_BASE + i] = newSettingsMenu->Append(wxID_SETTINGS_BASE + i, wxString(arg.name) + " : " + currentVal, arg.description); i++; } else if (arg.type == SoapySDR::ArgInfo::STRING) { if (arg.options.size()) { wxMenu *subMenu = new wxMenu; int j = 0; + std::vector subItemsIds; //for each of this options for (std::string optName : arg.options) { //by default the option name is the same as the displayed name. @@ -808,15 +848,21 @@ void AppFrame::updateDeviceParams() { displayName = arg.optionNames[j]; } wxMenuItem *item = subMenu->AppendRadioItem(wxID_SETTINGS_BASE+i, displayName); + subItemsIds.push_back(wxID_SETTINGS_BASE + i); + if (currentVal == optName) { item->Check(true); } j++; i++; } - newSettingsMenu->AppendSubMenu(subMenu, arg.name, arg.description); + settingsMenuItems[wxID_SETTINGS_BASE + i] = newSettingsMenu->AppendSubMenu(subMenu, wxString(arg.name) + " : " + currentVal, arg.description); + //map subitems ids to their parent item ! + for (int currentSubId : subItemsIds) { + settingsMenuItems[currentSubId] = settingsMenuItems[wxID_SETTINGS_BASE + i]; + } } else { - newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); + settingsMenuItems[wxID_SETTINGS_BASE + i] = newSettingsMenu->Append(wxID_SETTINGS_BASE + i, wxString(arg.name) + " : " + currentVal, arg.description); i++; } } @@ -1104,7 +1150,14 @@ bool AppFrame::actionOnMenuAbout(wxCommandEvent& event) { bool AppFrame::actionOnMenuSettings(wxCommandEvent& event) { - if (event.GetId() >= wxID_SETTINGS_BASE && event.GetId() < settingsIdMax) { + if (event.GetId() >= wxID_ANTENNAS_BASE && event.GetId() < wxID_ANTENNAS_BASE + antennaNames.size()) { + + wxGetApp().setAntennaName(antennaNames[event.GetId() - wxID_ANTENNAS_BASE]); + + antennaMenuItems[wxID_ANTENNA_CURRENT]->SetItemLabel(wxT("Antenna : ") + wxGetApp().getAntennaName()); + return true; + } + else if (event.GetId() >= wxID_SETTINGS_BASE && event.GetId() < settingsIdMax) { int setIdx = event.GetId() - wxID_SETTINGS_BASE; int menuIdx = 0; @@ -1115,6 +1168,9 @@ bool AppFrame::actionOnMenuSettings(wxCommandEvent& event) { if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size() && setIdx >= menuIdx && setIdx < menuIdx + (int)arg.options.size()) { int optIdx = setIdx - menuIdx; wxGetApp().getSDRThread()->writeSetting(arg.key, arg.options[optIdx]); + //update parent menu item label to display the current value + settingsMenuItems[menuIdx + wxID_SETTINGS_BASE]->SetItemLabel(wxString(arg.name) + " : " + arg.options[optIdx]); + break; } else if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size()) { @@ -1127,6 +1183,9 @@ bool AppFrame::actionOnMenuSettings(wxCommandEvent& event) { } else if (arg.type == SoapySDR::ArgInfo::STRING) { wxString stringVal = wxGetTextFromUser(arg.description, arg.name, wxGetApp().getSDRThread()->readSetting(arg.key)); + + settingsMenuItems[menuIdx + wxID_SETTINGS_BASE]->SetItemLabel(wxString(arg.name) + " : " + stringVal); + if (stringVal.ToStdString() != "") { wxGetApp().getSDRThread()->writeSetting(arg.key, stringVal.ToStdString()); } @@ -1141,6 +1200,9 @@ bool AppFrame::actionOnMenuSettings(wxCommandEvent& event) { currentVal = 0; } int intVal = wxGetNumberFromUser(arg.description, arg.units, arg.name, currentVal, arg.range.minimum(), arg.range.maximum(), this); + + settingsMenuItems[menuIdx + wxID_SETTINGS_BASE]->SetItemLabel(wxString(arg.name) + " : " + std::to_string(intVal)); + if (intVal != -1) { wxGetApp().getSDRThread()->writeSetting(arg.key, std::to_string(intVal)); } @@ -1154,6 +1216,7 @@ bool AppFrame::actionOnMenuSettings(wxCommandEvent& event) { catch (std::invalid_argument e) { // ... } + settingsMenuItems[menuIdx + wxID_SETTINGS_BASE]->SetItemLabel(wxString(arg.name) + " : " + floatVal); break; } else { @@ -1508,6 +1571,8 @@ void AppFrame::OnMenu(wxCommandEvent& event) { "Frequency Offset", wxGetApp().getOffset(), -2000000000, 2000000000, this); if (ofs != -1) { wxGetApp().setOffset(ofs); + + settingsMenuItems[wxID_SET_FREQ_OFFSET]->SetItemLabel(wxT("Frequency Offset : ") + std::to_string(wxGetApp().getOffset()) + wxT(" Hz")); } } else if (event.GetId() == wxID_SET_DB_OFFSET) { @@ -1515,6 +1580,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) { "Power Level Offset", wxGetApp().getConfig()->getDBOffset(), -1000, 1000, this); if (ofs != -1) { wxGetApp().getConfig()->setDBOffset(ofs); + settingsMenuItems[wxID_SET_DB_OFFSET]->SetItemLabel(wxT("Power Level Offset : ") + std::to_string(wxGetApp().getConfig()->getDBOffset()) + wxT(" dB")); } } else if (actionOnMenuAGC(event)) { @@ -1527,6 +1593,8 @@ void AppFrame::OnMenu(wxCommandEvent& event) { long ofs = wxGetNumberFromUser("Frequency correction for device in PPM.\ni.e. -51 for -51 PPM\n\nNote: you can adjust PPM interactively\nby holding ALT over the frequency tuning bar.\n", "Parts per million (PPM)", "Frequency Correction", wxGetApp().getPPM(), -1000, 1000, this); wxGetApp().setPPM(ofs); + + settingsMenuItems[wxID_SET_PPM]->SetItemLabel(wxT("Device PPM : ") + std::to_string(wxGetApp().getPPM()) + wxT(" ppm")); } else if (actionOnMenuLoadSave(event)) { return; @@ -2019,13 +2087,14 @@ void AppFrame::OnAboutDialogClose(wxCommandEvent& event) { } void AppFrame::saveSession(std::string fileName) { + DataTree s("cubicsdr_session"); DataNode *header = s.rootNode()->newChild("header"); //save as wstring to prevent problems header->newChild("version")->element()->set(wxString(CUBICSDR_VERSION).ToStdWstring()); *header->newChild("center_freq") = wxGetApp().getFrequency(); - *header->newChild("sample_rate") = wxGetApp().getSampleRate(); + *header->newChild("sample_rate") = wxGetApp().getSampleRate(); *header->newChild("solo_mode") = wxGetApp().getSoloMode()?1:0; if (waterfallCanvas->getViewState()) { @@ -2061,6 +2130,7 @@ void AppFrame::saveSession(std::string fileName) { } bool AppFrame::loadSession(std::string fileName) { + DataTree l; if (!l.LoadFromFileXML(fileName)) { return false; diff --git a/src/AppFrame.h b/src/AppFrame.h index 336145b..e128c3b 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -64,6 +64,9 @@ #define wxID_SETTINGS_BASE 2300 +#define wxID_ANTENNA_CURRENT 2500 +#define wxID_ANTENNAS_BASE 2501 + #define wxID_DEVICE_ID 3500 #define wxID_AUDIO_BANDWIDTH_BASE 9000 @@ -192,6 +195,12 @@ private: std::map outputDevices; std::map outputDeviceMenuItems; std::map sampleRateMenuItems; + std::map antennaMenuItems; + + //depending on context, maps the item id to wxMenuItem*, + //OR the submenu item id to its parent wxMenuItem*. + std::map settingsMenuItems; + std::map audioSampleRateMenuItems; std::map directSamplingMenuItems; wxMenuBar *menuBar; @@ -207,6 +216,8 @@ private: int settingsIdMax; std::vector sampleRates; long manualSampleRate = -1; + + std::vector antennaNames; std::string currentSessionFile; diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 301c732..e58d821 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -629,9 +629,22 @@ long long CubicSDR::getOffset() { void CubicSDR::setOffset(long long ofs) { offset = ofs; - sdrThread->setOffset(offset); - SDRDeviceInfo *dev = getDevice(); - config.getDevice(dev->getDeviceId())->setOffset(ofs); + + if (sdrThread && !sdrThread->isTerminated()) { + sdrThread->setOffset(offset); + } +} + +void CubicSDR::setAntennaName(const std::string& name) { + antennaName = name; + + if (sdrThread && !sdrThread->isTerminated()) { + sdrThread->setAntenna(antennaName); + } +} + +const std::string& CubicSDR::getAntennaName() { + return antennaName; } long long CubicSDR::getFrequency() { @@ -654,12 +667,18 @@ bool CubicSDR::isFrequencyLocked() { void CubicSDR::unlockFrequency() { frequency_locked.store(false); - sdrThread->unlockFrequency(); + if (sdrThread && !sdrThread->isTerminated()) { + sdrThread->unlockFrequency(); + } } void CubicSDR::setSampleRate(long long rate_in) { sampleRate = rate_in; - sdrThread->setSampleRate(sampleRate); + + if (sdrThread && !sdrThread->isTerminated()) { + sdrThread->setSampleRate(sampleRate); + } + setFrequency(frequency); if (rate_in <= CHANNELIZER_RATE_MAX / 8) { @@ -750,13 +769,8 @@ void CubicSDR::setDevice(SDRDeviceInfo *dev, int waitMsForTermination) { setPPM(devConfig->getPPM()); setOffset(devConfig->getOffset()); - - - if (devConfig->getAGCMode()) { - setAGCMode(true); - } else { - setAGCMode(false); - } + setAGCMode(devConfig->getAGCMode()); + setAntennaName(devConfig->getAntennaName()); t_SDR = new std::thread(&SDRThread::threadMain, sdrThread); } @@ -859,11 +873,8 @@ void CubicSDR::saveConfig() { void CubicSDR::setPPM(int ppm_in) { ppm = ppm_in; - sdrThread->setPPM(ppm); - - SDRDeviceInfo *dev = getDevice(); - if (dev) { - config.getDevice(dev->getDeviceId())->setPPM(ppm_in); + if (sdrThread && !sdrThread->isTerminated()) { + sdrThread->setPPM(ppm); } } @@ -975,7 +986,10 @@ bool CubicSDR::isDeviceSelectorOpen() { void CubicSDR::setAGCMode(bool mode) { agcMode.store(mode); - sdrThread->setAGCMode(mode); + + if (sdrThread && !sdrThread->isTerminated()) { + sdrThread->setAGCMode(mode); + } } bool CubicSDR::getAGCMode() { diff --git a/src/CubicSDR.h b/src/CubicSDR.h index c688c53..7807097 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -91,6 +91,9 @@ public: void setOffset(long long ofs); long long getOffset(); + + void setAntennaName(const std::string& name); + const std::string& getAntennaName(); void setDBOffset(int ofs); int getDBOffset(); @@ -98,6 +101,7 @@ public: void setSampleRate(long long rate_in); long long getSampleRate(); + std::vector *getDevices(); void setDevice(SDRDeviceInfo *dev, int waitMsForTermination); void stopDevice(bool store, int waitMsForTermination); @@ -189,6 +193,7 @@ private: std::atomic_llong offset; std::atomic_int ppm, snap; std::atomic_llong sampleRate; + std::string antennaName; std::atomic_bool agcMode; SDRThread *sdrThread = nullptr; diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index 2f2960b..c2a35cb 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -8,6 +8,8 @@ #include "CubicSDR.h" +#include + #ifdef __linux__ #include "CubicSDR.xpm" #endif @@ -110,6 +112,7 @@ wxPGProperty *SDRDevicesDialog::addArgInfoProperty(wxPropertyGrid *pg, SoapySDR: } void SDRDevicesDialog::refreshDeviceProperties() { + SDRDeviceInfo *selDev = getSelectedDevice(devTree->GetSelection()); if (selDev && selDev->isAvailable()) { dev = selDev; @@ -120,13 +123,68 @@ void SDRDevicesDialog::refreshDeviceProperties() { SoapySDR::Device *soapyDev = dev->getSoapyDevice(); SoapySDR::ArgInfoList args = soapyDev->getSettingInfo(); + //A) General settings: name, offset, sample rate, agc, antennas (if > 1) m_propertyGrid->Append(new wxPropertyCategory("General Settings")); devSettings.clear(); + //A-1) Name devSettings["name"] = m_propertyGrid->Append( new wxStringProperty("Name", wxPG_LABEL, devConfig->getDeviceName()) ); + //A-2) Offset devSettings["offset"] = m_propertyGrid->Append( new wxIntProperty("Offset (Hz)", wxPG_LABEL, devConfig->getOffset()) ); - + //A-3) ppm + devSettings["ppm"] = m_propertyGrid->Append(new wxIntProperty("Frequency Correction (ppm)", wxPG_LABEL, devConfig->getPPM())); + + + //A-4) AGC control + SoapySDR::ArgInfo agcArg; + + agcArg.type = SoapySDR::ArgInfo::BOOL; + agcArg.units = ""; + agcArg.name = "Automatic Gain"; + agcArg.key = "agc_mode"; + agcArg.value = devConfig->getAGCMode()?"true":"false"; //must be lowercase for addArgInfoProperty + + devSettings["agc_mode"] = addArgInfoProperty(m_propertyGrid, agcArg); + + //A-5) Antennas, is there are more than 1 RX antenna, else do not expose the setting. + //get the saved setting + const std::string& currentSetAntenna = wxGetApp().getAntennaName(); + + //compare to the list of existing antennas + SoapySDR::ArgInfo antennasArg; + std::vector antennaOpts = selDev->getAntennaNames(SOAPY_SDR_RX, 0); + + //only do something if there is more than 1 antenna + if (antennaOpts.size() > 1) { + + //by default, choose the first of the list. + std::string antennaToSelect = antennaOpts.front(); + + auto found_i = std::find(antennaOpts.begin(), antennaOpts.end(), currentSetAntenna); + + if (found_i != antennaOpts.end()) { + antennaToSelect = currentSetAntenna; + } + + //build device settings + for (std::string antenna : antennaOpts) { + antennasArg.options.push_back(antenna); + antennasArg.optionNames.push_back(antenna); + } + + antennasArg.type = SoapySDR::ArgInfo::STRING; + antennasArg.units = ""; + antennasArg.name = "Antenna"; + antennasArg.key = "antenna"; + antennasArg.value = antennaToSelect; + + devSettings["antenna"] = addArgInfoProperty(m_propertyGrid, antennasArg); + deviceArgs["antenna"] = antennasArg; + + } //end if more than 1 antenna + + //A-6) Sample_rate: long currentSampleRate = wxGetApp().getSampleRate(); long deviceSampleRate = devConfig->getSampleRate(); @@ -150,11 +208,14 @@ void SDRDevicesDialog::refreshDeviceProperties() { devSettings["sample_rate"] = addArgInfoProperty(m_propertyGrid, sampleRateArg); deviceArgs["sample_rate"] = sampleRateArg; + + + //B) Runtime Settings: runtimeArgs.clear(); runtimeProps.clear(); streamProps.clear(); - + if (args.size()) { m_propertyGrid->Append(new wxPropertyCategory("Run-time Settings")); @@ -439,6 +500,7 @@ void SDRDevicesDialog::OnRefreshDevices( wxMouseEvent& /* event */) { } void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { + if (editId && event.GetProperty() == devSettings["name"]) { DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); @@ -457,7 +519,36 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { long offset = event.GetPropertyValue().GetInteger(); devConfig->setOffset(offset); + if (dev->isActive() || !wxGetApp().getDevice()) { + + wxGetApp().setOffset(offset); + } + + } else if (dev && event.GetProperty() == devSettings["ppm"]) { + DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); + + int ppm = event.GetPropertyValue().GetInteger(); + + devConfig->setPPM(ppm); + + if (dev->isActive() || !wxGetApp().getDevice()) { + + wxGetApp().setPPM(ppm); + } + } + else if (dev && event.GetProperty() == devSettings["agc_mode"]) { + + DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); + + bool agcMode = event.GetPropertyValue().GetBool(); + + devConfig->setAGCMode(agcMode); + if (dev->isActive() || !wxGetApp().getDevice()) { + wxGetApp().setAGCMode(agcMode); + } + } else if (dev && event.GetProperty() == devSettings["sample_rate"]) { + DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); std::string strRate = deviceArgs["sample_rate"].options[event.GetPropertyValue().GetInteger()]; @@ -465,15 +556,29 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { try { srate = std::stol(strRate); devConfig->setSampleRate(srate); - - if (dev->isActive() || !wxGetApp().getDevice()) { + if (dev->isActive() || !wxGetApp().getDevice()) { wxGetApp().setSampleRate(srate); - wxGetApp().notifyMainUIOfDeviceChange(); - } + } } catch (std::invalid_argument e) { // nop } - } else if (editId && dev) { + } else if (dev && event.GetProperty() == devSettings["antenna"]) { + DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); + + std::string strAntennaName = deviceArgs["antenna"].options[event.GetPropertyValue().GetInteger()]; + + try { + devConfig->setAntennaName(strAntennaName); + + if (dev->isActive() || !wxGetApp().getDevice()) { + wxGetApp().setAntennaName(strAntennaName); + } + } + catch (std::invalid_argument e) { + // nop + } + } + else if (editId && dev) { wxPGProperty *prop = event.GetProperty(); //change value of RuntimeProps for (std::map::iterator rtp = runtimeProps.begin(); rtp != runtimeProps.end(); rtp++) { @@ -499,6 +604,8 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { } } } + // general refresh. + wxGetApp().notifyMainUIOfDeviceChange(); } void SDRDevicesDialog::OnPropGridFocus( wxFocusEvent& /* event */) { diff --git a/src/sdr/SDRDeviceInfo.cpp b/src/sdr/SDRDeviceInfo.cpp index 3a00263..34c3c9b 100644 --- a/src/sdr/SDRDeviceInfo.cpp +++ b/src/sdr/SDRDeviceInfo.cpp @@ -190,6 +190,13 @@ std::vector SDRDeviceInfo::getSampleRates(int direction, size_t channel) { return result; } +std::vector SDRDeviceInfo::getAntennaNames(int direction, size_t channel) { + SoapySDR::Device *dev = getSoapyDevice(); + + return dev->listAntennas(direction, channel); + +} + long SDRDeviceInfo::getSampleRateNear(int direction, size_t channel, long sampleRate_in) { std::vector sampleRates = getSampleRates(direction, channel); long returnRate = sampleRates[0]; diff --git a/src/sdr/SDRDeviceInfo.h b/src/sdr/SDRDeviceInfo.h index cc903c1..d0bf831 100644 --- a/src/sdr/SDRDeviceInfo.h +++ b/src/sdr/SDRDeviceInfo.h @@ -83,6 +83,8 @@ public: bool hasCORR(int direction, size_t channel); std::vector getSampleRates(int direction, size_t channel); + + std::vector getAntennaNames(int direction, size_t channel); long getSampleRateNear(int direction, size_t channel, long sampleRate_in); diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index 9890caa..f361562 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -28,6 +28,7 @@ SDRThread::SDRThread() : IOThread(), buffers("SDRThreadBuffers") { rate_changed.store(false); freq_changed.store(false); offset_changed.store(false); + antenna_changed.store(false); ppm_changed .store(false); device_changed.store(false); @@ -437,6 +438,13 @@ void SDRThread::updateSettings() { if (!stream) { return; } + + if (antenna_changed.load()) { + + device->setAntenna(SOAPY_SDR_RX, 0, antennaName); + + antenna_changed.store(false); + } if (offset_changed.load()) { if (!freq_changed.load()) { @@ -524,7 +532,6 @@ void SDRThread::updateSettings() { gain_value_changed.store(false); } - if (setting_value_changed.load()) { std::lock_guard < std::mutex > lock(setting_busy); @@ -652,6 +659,12 @@ void SDRThread::unlockFrequency() { void SDRThread::setOffset(long long ofs) { offset.store(ofs); offset_changed.store(true); + + DeviceConfig *devConfig = deviceConfig.load(); + if (devConfig) { + devConfig->setOffset(ofs); + } + // std::cout << "Set offset: " << offset.load() << std::endl; } @@ -659,6 +672,20 @@ long long SDRThread::getOffset() { return offset.load(); } +void SDRThread::setAntenna(const std::string& name) { + antennaName = name; + antenna_changed.store(true); + + DeviceConfig *devConfig = deviceConfig.load(); + if (devConfig) { + devConfig->setAntennaName(antennaName); + } +} + +std::string SDRThread::getAntenna() { + return antennaName; +} + void SDRThread::setSampleRate(long rate) { sampleRate.store(rate); rate_changed = true; @@ -675,6 +702,12 @@ long SDRThread::getSampleRate() { void SDRThread::setPPM(int ppm) { this->ppm.store(ppm); ppm_changed.store(true); + + DeviceConfig *devConfig = deviceConfig.load(); + if (devConfig) { + devConfig->setPPM(ppm); + } + // std::cout << "Set PPM: " << this->ppm.load() << std::endl; } diff --git a/src/sdr/SoapySDRThread.h b/src/sdr/SoapySDRThread.h index 2bb2084..83472ff 100644 --- a/src/sdr/SoapySDRThread.h +++ b/src/sdr/SoapySDRThread.h @@ -76,6 +76,9 @@ public: void setOffset(long long ofs); long long getOffset(); + + void setAntenna(const std::string& name); + std::string getAntenna(); void setSampleRate(long rate); long getSampleRate(); @@ -119,7 +122,8 @@ protected: std::atomic_llong frequency, offset, lock_freq; std::atomic_int ppm, numElems, mtuElems, numChannels; std::atomic_bool hasPPM, hasHardwareDC; - std::atomic_bool agc_mode, rate_changed, freq_changed, offset_changed, + std::string antennaName; + std::atomic_bool agc_mode, rate_changed, freq_changed, offset_changed, antenna_changed, ppm_changed, device_changed, agc_mode_changed, gain_value_changed, setting_value_changed, frequency_locked, frequency_lock_init, iq_swap; std::mutex gain_busy; diff --git a/src/visual/TuningCanvas.cpp b/src/visual/TuningCanvas.cpp index 9ee6b3e..2604926 100644 --- a/src/visual/TuningCanvas.cpp +++ b/src/visual/TuningCanvas.cpp @@ -245,6 +245,7 @@ void TuningCanvas::StepTuner(ActiveState state, int exponent, bool up) { } wxGetApp().setPPM(currentPPM); + wxGetApp().notifyMainUIOfDeviceChange(); } }