mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-23 04:08:36 -05:00
Initial commit: Antenna support, Enhanced Settings menu, Enhanced SDR device dialog
This commit is contained in:
parent
e32e687fe8
commit
1042c62c3b
@ -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++) {
|
||||
|
@ -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;
|
||||
|
@ -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<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(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<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 +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;
|
||||
|
@ -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<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 +216,8 @@ private:
|
||||
int settingsIdMax;
|
||||
std::vector<long> sampleRates;
|
||||
long manualSampleRate = -1;
|
||||
|
||||
std::vector<std::string> antennaNames;
|
||||
|
||||
std::string currentSessionFile;
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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,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<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;
|
||||
}
|
||||
|
||||
//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<std::string, wxPGProperty *>::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 */) {
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -245,6 +245,7 @@ void TuningCanvas::StepTuner(ActiveState state, int exponent, bool up) {
|
||||
}
|
||||
|
||||
wxGetApp().setPPM(currentPPM);
|
||||
wxGetApp().notifyMainUIOfDeviceChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user