Merge pull request #571 from cjcliffe/vso_SoapySDR_antenna_support

Add  Antenna support (RX only), plus improved Settings menu.
This commit is contained in:
Vincent Sonnier 2017-08-25 06:23:22 +02:00 committed by GitHub
commit 8993121fc6
12 changed files with 311 additions and 38 deletions

View File

@ -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<iMax; i++) {

View File

@ -31,6 +31,9 @@ public:
void setSampleRate(long srate);
long getSampleRate();
void setAntennaName(const std::string& name);
const std::string& getAntennaName();
void setAGCMode(bool agcMode);
bool getAGCMode();
@ -64,12 +67,14 @@ public:
private:
std::string deviceId;
std::string deviceName;
std::mutex busy_lock;
std::atomic_int ppm;
std::atomic_llong offset;
std::atomic_bool agcMode;
std::atomic_long sampleRate;
std::string antennaName;
ConfigSettings streamOpts;
ConfigGains gains;
std::map<std::string, std::string> settings;

View File

@ -26,6 +26,8 @@
#include "ImagePanel.h"
#include <thread>
#include <iostream>
#include <iomanip>
#include <wx/panel.h>
#include <wx/numformatter.h>
@ -101,7 +103,7 @@ AppFrame::AppFrame() :
#endif
gainCanvas = new GainCanvas(demodPanel, attribList);
gainCanvas->setHelpTip("Tuner gains in dB. Click / use Mousewheel to change.");
gainCanvas->setHelpTip("Tuner gains, usually in dB. Click / use Mousewheel to change.");
gainSizerItem = demodTray->Add(gainCanvas, 0, wxEXPAND | wxALL, 0);
gainSizerItem->Show(false);
gainSpacerItem = demodTray->AddSpacer(1);
@ -752,11 +754,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, getSettingsLabel("Power Level Offset", std::to_string(wxGetApp().getConfig()->getDBOffset()), "dB"));
settingsMenuItems[wxID_SET_FREQ_OFFSET] = newSettingsMenu->Append(wxID_SET_FREQ_OFFSET, getSettingsLabel("Frequency Offset", std::to_string(wxGetApp().getOffset()) , "Hz"));
if (devInfo->hasCORR(SOAPY_SDR_RX, 0)) {
newSettingsMenu->Append(wxID_SET_PPM, "Device PPM");
settingsMenuItems[wxID_SET_PPM] = newSettingsMenu->Append(wxID_SET_PPM, getSettingsLabel("Device PPM", std::to_string(wxGetApp().getPPM()) , "ppm"));
}
if (devInfo->getDriver() != "rtlsdr") {
@ -771,7 +775,44 @@ 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<std::string> 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(getSettingsLabel("Antenna", antennaChecked));
}
}
//Runtime settings part
SoapySDR::ArgInfoList::const_iterator args_i;
settingArgs = soapyDev->getSettingInfo();
@ -790,15 +831,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, getSettingsLabel(arg.name, currentVal, arg.units), 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, getSettingsLabel(arg.name, currentVal, arg.units), arg.description);
i++;
} else if (arg.type == SoapySDR::ArgInfo::STRING) {
if (arg.options.size()) {
wxMenu *subMenu = new wxMenu;
int j = 0;
std::vector<int> 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 +851,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, getSettingsLabel(arg.name, currentVal, arg.units), 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, getSettingsLabel(arg.name, currentVal, arg.units), arg.description);
i++;
}
}
@ -1104,7 +1153,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(getSettingsLabel("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 +1171,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(getSettingsLabel(arg.name, arg.options[optIdx], arg.units));
break;
}
else if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size()) {
@ -1127,6 +1186,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(getSettingsLabel(arg.name, stringVal.ToStdString(), arg.units));
if (stringVal.ToStdString() != "") {
wxGetApp().getSDRThread()->writeSetting(arg.key, stringVal.ToStdString());
}
@ -1141,6 +1203,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(getSettingsLabel(arg.name, std::to_string(intVal), arg.units));
if (intVal != -1) {
wxGetApp().getSDRThread()->writeSetting(arg.key, std::to_string(intVal));
}
@ -1154,6 +1219,7 @@ bool AppFrame::actionOnMenuSettings(wxCommandEvent& event) {
catch (std::invalid_argument e) {
// ...
}
settingsMenuItems[menuIdx + wxID_SETTINGS_BASE]->SetItemLabel(getSettingsLabel(arg.name, floatVal.ToStdString(), arg.units));
break;
}
else {
@ -1508,6 +1574,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(getSettingsLabel("Frequency Offset", std::to_string(wxGetApp().getOffset()), "Hz"));
}
}
else if (event.GetId() == wxID_SET_DB_OFFSET) {
@ -1515,6 +1583,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(getSettingsLabel("Power Level Offset", std::to_string(wxGetApp().getConfig()->getDBOffset()), "dB"));
}
}
else if (actionOnMenuAGC(event)) {
@ -1527,6 +1596,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(getSettingsLabel("Device PPM", std::to_string(wxGetApp().getPPM()), "ppm"));
}
else if (actionOnMenuLoadSave(event)) {
return;
@ -2019,13 +2090,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 +2133,7 @@ void AppFrame::saveSession(std::string fileName) {
}
bool AppFrame::loadSession(std::string fileName) {
DataTree l;
if (!l.LoadFromFileXML(fileName)) {
return false;
@ -2664,3 +2737,19 @@ void AppFrame::setStatusText(std::string statusText, int value) {
GetStatusBar()->SetStatusText(
wxString::Format(statusText.c_str(), wxNumberFormatter::ToString((long)value, wxNumberFormatter::Style_WithThousandsSep)));
}
wxString AppFrame::getSettingsLabel(const std::string& settingsName,
const std::string& settingsValue,
const std::string& settingsSuffix) {
size_t itemStringSize = 30;
int justifValueSize = itemStringSize - settingsName.length() - 1;
std::stringstream full_label;
full_label << settingsName + " : ";
full_label << std::right << std::setw(justifValueSize);
full_label << settingsValue + " " + settingsSuffix;
return wxString(full_label.str());
}

View File

@ -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
@ -163,6 +166,10 @@ private:
bool actionOnMenuLoadSave(wxCommandEvent& event);
bool actionOnMenuRig(wxCommandEvent& event);
wxString getSettingsLabel(const std::string& settingsName,
const std::string& settingsValue,
const std::string& settingsSuffix = "");
ScopeCanvas *scopeCanvas;
SpectrumCanvas *spectrumCanvas;
WaterfallCanvas *waterfallCanvas;
@ -192,6 +199,12 @@ private:
std::map<int,RtAudio::DeviceInfo> outputDevices;
std::map<int, wxMenuItem *> outputDeviceMenuItems;
std::map<int, wxMenuItem *> sampleRateMenuItems;
std::map<int, wxMenuItem *> antennaMenuItems;
//depending on context, maps the item id to wxMenuItem*,
//OR the submenu item id to its parent wxMenuItem*.
std::map<int, wxMenuItem *> settingsMenuItems;
std::map<int, wxMenuItem *> audioSampleRateMenuItems;
std::map<int, wxMenuItem *> directSamplingMenuItems;
wxMenuBar *menuBar;
@ -207,6 +220,8 @@ private:
int settingsIdMax;
std::vector<long> sampleRates;
long manualSampleRate = -1;
std::vector<std::string> antennaNames;
std::string currentSessionFile;

View File

@ -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() {

View File

@ -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<SDRDeviceInfo *> *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;

View File

@ -8,6 +8,8 @@
#include "CubicSDR.h"
#include <algorithm>
#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,61 @@ 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) Antennas, is there are more than 1 RX antenna, else do not expose the setting.
//get the saved setting
const std::string& currentSetAntenna = devConfig->getAntennaName();
//compare to the list of existing antennas
SoapySDR::ArgInfo antennasArg;
std::vector<std::string> 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;
}
else {
//erroneous antenna name, re-write device config with the first choice of teh list.
devConfig->setAntennaName(antennaToSelect);
}
//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
else {
devConfig->setAntennaName("");
}
//A-4) Sample_rate:
long currentSampleRate = wxGetApp().getSampleRate();
long deviceSampleRate = devConfig->getSampleRate();
@ -150,11 +201,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 +493,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 +512,14 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) {
long offset = event.GetPropertyValue().GetInteger();
devConfig->setOffset(offset);
} else if (dev && event.GetProperty() == devSettings["sample_rate"]) {
if (dev->isActive() || !wxGetApp().getDevice()) {
wxGetApp().setOffset(offset);
}
}
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 +527,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<std::string, wxPGProperty *>::iterator rtp = runtimeProps.begin(); rtp != runtimeProps.end(); rtp++) {
@ -499,6 +575,8 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) {
}
}
}
// general refresh.
wxGetApp().notifyMainUIOfDeviceChange();
}
void SDRDevicesDialog::OnPropGridFocus( wxFocusEvent& /* event */) {

View File

@ -190,6 +190,13 @@ std::vector<long> SDRDeviceInfo::getSampleRates(int direction, size_t channel) {
return result;
}
std::vector<std::string> 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<long> sampleRates = getSampleRates(direction, channel);
long returnRate = sampleRates[0];

View File

@ -83,6 +83,8 @@ public:
bool hasCORR(int direction, size_t channel);
std::vector<long> getSampleRates(int direction, size_t channel);
std::vector<std::string> getAntennaNames(int direction, size_t channel);
long getSampleRateNear(int direction, size_t channel, long sampleRate_in);

View File

@ -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;
}

View File

@ -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;

View File

@ -245,6 +245,7 @@ void TuningCanvas::StepTuner(ActiveState state, int exponent, bool up) {
}
wxGetApp().setPPM(currentPPM);
wxGetApp().notifyMainUIOfDeviceChange();
}
}