mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-22 03:36:24 -05:00
Save sample rate, gain levels and AGC state per-device, add sample rate to device dialog
This commit is contained in:
parent
6df9bfd167
commit
68b095ef8d
@ -4,6 +4,8 @@
|
||||
DeviceConfig::DeviceConfig() : deviceId("") {
|
||||
ppm.store(0);
|
||||
offset.store(0);
|
||||
agcMode.store(true);
|
||||
sampleRate.store(0);
|
||||
}
|
||||
|
||||
DeviceConfig::DeviceConfig(std::string deviceId) : DeviceConfig() {
|
||||
@ -26,6 +28,24 @@ long long DeviceConfig::getOffset() {
|
||||
return offset.load();
|
||||
}
|
||||
|
||||
|
||||
void DeviceConfig::setSampleRate(long srate) {
|
||||
sampleRate.store(srate);
|
||||
}
|
||||
|
||||
long DeviceConfig::getSampleRate() {
|
||||
return sampleRate.load();
|
||||
}
|
||||
|
||||
void DeviceConfig::setAGCMode(bool agcMode) {
|
||||
this->agcMode.store(agcMode);
|
||||
}
|
||||
|
||||
bool DeviceConfig::getAGCMode() {
|
||||
return agcMode.load();
|
||||
}
|
||||
|
||||
|
||||
void DeviceConfig::setDeviceId(std::string deviceId) {
|
||||
busy_lock.lock();
|
||||
this->deviceId = deviceId;
|
||||
@ -62,21 +82,38 @@ void DeviceConfig::save(DataNode *node) {
|
||||
busy_lock.lock();
|
||||
*node->newChild("id") = deviceId;
|
||||
*node->newChild("name") = deviceName;
|
||||
*node->newChild("ppm") = (int)ppm;
|
||||
*node->newChild("offset") = offset;
|
||||
DataNode *streamOptsNode = node->newChild("streamOpts");
|
||||
for (ConfigSettings::const_iterator opt_i = streamOpts.begin(); opt_i != streamOpts.end(); opt_i++) {
|
||||
*streamOptsNode->newChild(opt_i->first.c_str()) = opt_i->second;
|
||||
*node->newChild("ppm") = (int)ppm.load();
|
||||
*node->newChild("offset") = offset.load();
|
||||
*node->newChild("sample_rate") = sampleRate.load();
|
||||
*node->newChild("agc_mode") = agcMode.load()?1:0;
|
||||
|
||||
if (streamOpts.size()) {
|
||||
DataNode *streamOptsNode = node->newChild("streamOpts");
|
||||
for (ConfigSettings::const_iterator opt_i = streamOpts.begin(); opt_i != streamOpts.end(); opt_i++) {
|
||||
*streamOptsNode->newChild(opt_i->first.c_str()) = opt_i->second;
|
||||
}
|
||||
}
|
||||
DataNode *settingsNode = node->newChild("settings");
|
||||
for (ConfigSettings::const_iterator set_i = settings.begin(); set_i != settings.end(); set_i++) {
|
||||
*settingsNode->newChild(set_i->first.c_str()) = set_i->second;
|
||||
if (settings.size()) {
|
||||
DataNode *settingsNode = node->newChild("settings");
|
||||
for (ConfigSettings::const_iterator set_i = settings.begin(); set_i != settings.end(); set_i++) {
|
||||
*settingsNode->newChild(set_i->first.c_str()) = set_i->second;
|
||||
}
|
||||
}
|
||||
DataNode *rigIFs = node->newChild("rig_ifs");
|
||||
for (std::map<int, long long>::const_iterator rigIF_i = rigIF.begin(); rigIF_i != rigIF.end(); rigIF_i++) {
|
||||
DataNode *ifNode = rigIFs->newChild("rig_if");
|
||||
*ifNode->newChild("model") = rigIF_i->first;
|
||||
*ifNode->newChild("sdr_if") = rigIF_i->second;
|
||||
if (rigIF.size()) {
|
||||
DataNode *rigIFs = node->newChild("rig_ifs");
|
||||
for (std::map<int, long long>::const_iterator rigIF_i = rigIF.begin(); rigIF_i != rigIF.end(); rigIF_i++) {
|
||||
DataNode *ifNode = rigIFs->newChild("rig_if");
|
||||
*ifNode->newChild("model") = rigIF_i->first;
|
||||
*ifNode->newChild("sdr_if") = rigIF_i->second;
|
||||
}
|
||||
}
|
||||
if (gains.size()) {
|
||||
DataNode *gainsNode = node->newChild("gains");
|
||||
for (ConfigGains::const_iterator gain_i = gains.begin(); gain_i != gains.end(); gain_i++) {
|
||||
DataNode *gainNode = gainsNode->newChild("gain");
|
||||
*gainNode->newChild("id") = gain_i->first;
|
||||
*gainNode->newChild("value") = gain_i->second;
|
||||
}
|
||||
}
|
||||
busy_lock.unlock();
|
||||
}
|
||||
@ -91,14 +128,24 @@ void DeviceConfig::load(DataNode *node) {
|
||||
int ppmValue = 0;
|
||||
ppm_node->element()->get(ppmValue);
|
||||
setPPM(ppmValue);
|
||||
std::cout << "Loaded PPM for device '" << deviceId << "' at " << ppmValue << "ppm" << std::endl;
|
||||
}
|
||||
if (node->hasAnother("offset")) {
|
||||
DataNode *offset_node = node->getNext("offset");
|
||||
long long offsetValue = 0;
|
||||
offset_node->element()->get(offsetValue);
|
||||
setOffset(offsetValue);
|
||||
std::cout << "Loaded offset for device '" << deviceId << "' at " << offsetValue << "Hz" << std::endl;
|
||||
}
|
||||
if (node->hasAnother("agc_mode")) {
|
||||
DataNode *agc_node = node->getNext("agc_mode");
|
||||
int agcModeValue = 0;
|
||||
agc_node->element()->get(agcModeValue);
|
||||
setAGCMode(agcModeValue?true:false);
|
||||
}
|
||||
if (node->hasAnother("sample_rate")) {
|
||||
DataNode *sample_rate_node = node->getNext("sample_rate");
|
||||
long sampleRateValue = 0;
|
||||
sample_rate_node->element()->get(sampleRateValue);
|
||||
setSampleRate(sampleRateValue);
|
||||
}
|
||||
if (node->hasAnother("streamOpts")) {
|
||||
DataNode *streamOptsNode = node->getNext("streamOpts");
|
||||
@ -139,6 +186,21 @@ void DeviceConfig::load(DataNode *node) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node->hasAnother("gains")) {
|
||||
DataNode *gainsNode = node->getNext("gains");
|
||||
while (gainsNode->hasAnother("gain")) {
|
||||
DataNode *gainNode = gainsNode->getNext("gain");
|
||||
std::string keyName;
|
||||
float fltSettingValue;
|
||||
|
||||
gainNode->getNext("id")->element()->get(keyName);
|
||||
gainNode->getNext("value")->element()->get(fltSettingValue);
|
||||
|
||||
if (keyName != "" && !(fltSettingValue!=fltSettingValue)) {
|
||||
setGain(keyName, fltSettingValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
busy_lock.unlock();
|
||||
}
|
||||
|
||||
@ -181,6 +243,27 @@ ConfigSettings DeviceConfig::getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
void DeviceConfig::setGains(ConfigGains gains) {
|
||||
this->gains = gains;
|
||||
}
|
||||
|
||||
ConfigGains DeviceConfig::getGains() {
|
||||
return gains;
|
||||
}
|
||||
|
||||
void DeviceConfig::setGain(std::string key, float value) {
|
||||
gains[key] = value;
|
||||
}
|
||||
|
||||
float DeviceConfig::getGain(std::string key, float defaultValue) {
|
||||
if (gains.find(key) != gains.end()) {
|
||||
return gains[key];
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
void DeviceConfig::setRigIF(int rigType, long long freq) {
|
||||
rigIF[rigType] = freq;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "SDRDeviceInfo.h"
|
||||
|
||||
typedef std::map<std::string, std::string> ConfigSettings;
|
||||
typedef std::map<std::string, float> ConfigGains;
|
||||
|
||||
class DeviceConfig {
|
||||
public:
|
||||
@ -24,6 +25,12 @@ public:
|
||||
void setOffset(long long offset);
|
||||
long long getOffset();
|
||||
|
||||
void setSampleRate(long srate);
|
||||
long getSampleRate();
|
||||
|
||||
void setAGCMode(bool agcMode);
|
||||
bool getAGCMode();
|
||||
|
||||
void setDeviceId(std::string deviceId);
|
||||
std::string getDeviceId();
|
||||
|
||||
@ -39,7 +46,12 @@ public:
|
||||
ConfigSettings getSettings();
|
||||
void setSetting(std::string key, std::string value);
|
||||
std::string getSetting(std::string key, std::string defaultValue);
|
||||
|
||||
|
||||
void setGains(ConfigGains gains);
|
||||
ConfigGains getGains();
|
||||
void setGain(std::string key, float value);
|
||||
float getGain(std::string key, float defaultValue);
|
||||
|
||||
void setRigIF(int rigType, long long freq);
|
||||
long long getRigIF(int rigType);
|
||||
|
||||
@ -53,7 +65,10 @@ private:
|
||||
|
||||
std::atomic_int ppm;
|
||||
std::atomic_llong offset;
|
||||
std::atomic_bool agcMode;
|
||||
std::atomic_long sampleRate;
|
||||
ConfigSettings streamOpts;
|
||||
ConfigGains gains;
|
||||
std::map<std::string, std::string> settings;
|
||||
std::map<int, long long> rigIF;
|
||||
};
|
||||
|
@ -1597,7 +1597,9 @@ bool AppFrame::loadSession(std::string fileName) {
|
||||
|
||||
long long center_freq = *header->getNext("center_freq");
|
||||
std::cout << "\tCenter Frequency: " << center_freq << std::endl;
|
||||
|
||||
|
||||
wxGetApp().setFrequency(center_freq);
|
||||
|
||||
if (header->hasAnother("sample_rate")) {
|
||||
int sample_rate = *header->getNext("sample_rate");
|
||||
|
||||
@ -1613,8 +1615,6 @@ bool AppFrame::loadSession(std::string fileName) {
|
||||
|
||||
}
|
||||
|
||||
wxGetApp().setFrequency(center_freq);
|
||||
|
||||
DataNode *demodulators = l.rootNode()->getNext("demodulators");
|
||||
|
||||
int numDemodulators = 0;
|
||||
|
@ -544,14 +544,11 @@ void CubicSDR::setDevice(SDRDeviceInfo *dev) {
|
||||
SoapySDR::Device *soapyDev = dev->getSoapyDevice();
|
||||
|
||||
if (soapyDev) {
|
||||
//long long freqHigh, freqLow;
|
||||
if (long devSampleRate = devConfig->getSampleRate()) {
|
||||
sampleRate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, devSampleRate);
|
||||
sampleRateInitialized.store(true);
|
||||
}
|
||||
|
||||
//SoapySDR::RangeList freqRange = soapyDev->getFrequencyRange(SOAPY_SDR_RX, 0);
|
||||
|
||||
//freqLow = freqRange[0].minimum();
|
||||
//freqHigh = freqRange[freqRange.size()-1].maximum();
|
||||
|
||||
// Try for a reasonable default sample rate.
|
||||
if (!sampleRateInitialized.load()) {
|
||||
sampleRate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, DEFAULT_SAMPLE_RATE);
|
||||
sampleRateInitialized.store(true);
|
||||
@ -568,9 +565,16 @@ void CubicSDR::setDevice(SDRDeviceInfo *dev) {
|
||||
|
||||
setPPM(devConfig->getPPM());
|
||||
setOffset(devConfig->getOffset());
|
||||
|
||||
|
||||
if (devConfig->getAGCMode()) {
|
||||
setAGCMode(true);
|
||||
} else {
|
||||
setAGCMode(false);
|
||||
}
|
||||
|
||||
t_SDR = new std::thread(&SDRThread::threadMain, sdrThread);
|
||||
}
|
||||
}
|
||||
|
||||
stoppedDev = nullptr;
|
||||
}
|
||||
|
@ -113,6 +113,30 @@ void SDRDevicesDialog::refreshDeviceProperties() {
|
||||
devSettings["name"] = m_propertyGrid->Append( new wxStringProperty("Name", wxPG_LABEL, devConfig->getDeviceName()) );
|
||||
devSettings["offset"] = m_propertyGrid->Append( new wxIntProperty("Offset (Hz)", wxPG_LABEL, devConfig->getOffset()) );
|
||||
|
||||
int currentSampleRate = wxGetApp().getSampleRate();
|
||||
int deviceSampleRate = devConfig->getSampleRate();
|
||||
|
||||
if (!deviceSampleRate) {
|
||||
deviceSampleRate = selDev->getSampleRateNear(SOAPY_SDR_RX, 0, currentSampleRate);
|
||||
}
|
||||
|
||||
SoapySDR::ArgInfo sampleRateArg;
|
||||
std::vector<long> rateOpts = selDev->getSampleRates(SOAPY_SDR_RX, 0);
|
||||
|
||||
for (std::vector<long>::iterator rate_i = rateOpts.begin(); rate_i != rateOpts.end(); rate_i++) {
|
||||
sampleRateArg.options.push_back(std::to_string(*rate_i));
|
||||
sampleRateArg.optionNames.push_back(frequencyToStr(*rate_i));
|
||||
}
|
||||
|
||||
sampleRateArg.type = SoapySDR::ArgInfo::STRING;
|
||||
sampleRateArg.units = "Hz";
|
||||
sampleRateArg.name = "Sample Rate";
|
||||
sampleRateArg.key = "sample_rate";
|
||||
sampleRateArg.value = std::to_string(deviceSampleRate);
|
||||
|
||||
devSettings["sample_rate"] = addArgInfoProperty(m_propertyGrid, sampleRateArg);
|
||||
deviceArgs["sample_rate"] = sampleRateArg;
|
||||
|
||||
runtimeArgs.erase(runtimeArgs.begin(), runtimeArgs.end());
|
||||
runtimeProps.erase(runtimeProps.begin(), runtimeProps.end());
|
||||
streamProps.erase(streamProps.begin(), streamProps.end());
|
||||
@ -291,6 +315,7 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event) {
|
||||
wxGetApp().setDeviceArgs(settingArgs);
|
||||
wxGetApp().setStreamArgs(streamArgs);
|
||||
wxGetApp().setDevice(dev);
|
||||
|
||||
Close();
|
||||
}
|
||||
event.Skip();
|
||||
@ -406,6 +431,21 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) {
|
||||
long offset = event.GetPropertyValue().GetInteger();
|
||||
|
||||
devConfig->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()];
|
||||
int srate = 0;
|
||||
try {
|
||||
srate = std::stoi(strRate);
|
||||
devConfig->setSampleRate(srate);
|
||||
|
||||
if (dev->isActive() || !wxGetApp().getDevice()) {
|
||||
wxGetApp().setSampleRate(srate);
|
||||
}
|
||||
} catch (std::invalid_argument e) {
|
||||
// nop
|
||||
}
|
||||
} else if (editId && dev) {
|
||||
wxPGProperty *prop = event.GetProperty();
|
||||
|
||||
|
@ -36,6 +36,7 @@ private:
|
||||
std::map<wxTreeItemId, SDRDeviceInfo *> devItems;
|
||||
std::map<wxTreeItemId, SDRDeviceInfo *>::iterator devItems_i;
|
||||
SDRDeviceInfo *dev;
|
||||
std::map<std::string, SoapySDR::ArgInfo> deviceArgs;
|
||||
std::map<std::string, wxPGProperty *> runtimeProps;
|
||||
std::map<std::string, SoapySDR::ArgInfo> runtimeArgs;
|
||||
std::map<std::string, wxPGProperty *> streamProps;
|
||||
|
@ -302,6 +302,15 @@ void SDRThread::updateSettings() {
|
||||
agc_mode_changed.store(false);
|
||||
if (!agc_mode.load()) {
|
||||
updateGains();
|
||||
|
||||
DeviceConfig *devConfig = deviceConfig.load();
|
||||
ConfigGains gains = devConfig->getGains();
|
||||
|
||||
if (gains.size()) {
|
||||
for (ConfigGains::iterator gain_i = gains.begin(); gain_i != gains.end(); gain_i++) {
|
||||
setGain(gain_i->first, gain_i->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
doUpdate = true;
|
||||
}
|
||||
@ -394,7 +403,7 @@ int SDRThread::getOptimalElementCount(long long sampleRate, int fps) {
|
||||
int elemCount = (int)floor((double)sampleRate/(double)fps);
|
||||
int nch = numChannels.load();
|
||||
elemCount = int(ceil((double)elemCount/(double)nch))*nch;
|
||||
std::cout << "Calculated optimal " << numChannels.load() << " channel element count of " << elemCount << std::endl;
|
||||
// std::cout << "Calculated optimal " << numChannels.load() << " channel element count of " << elemCount << std::endl;
|
||||
return elemCount;
|
||||
}
|
||||
|
||||
@ -450,7 +459,7 @@ void SDRThread::unlockFrequency() {
|
||||
void SDRThread::setOffset(long long ofs) {
|
||||
offset.store(ofs);
|
||||
offset_changed.store(true);
|
||||
std::cout << "Set offset: " << offset.load() << std::endl;
|
||||
// std::cout << "Set offset: " << offset.load() << std::endl;
|
||||
}
|
||||
|
||||
long long SDRThread::getOffset() {
|
||||
@ -460,7 +469,11 @@ long long SDRThread::getOffset() {
|
||||
void SDRThread::setSampleRate(int rate) {
|
||||
sampleRate.store(rate);
|
||||
rate_changed = true;
|
||||
std::cout << "Set sample rate: " << sampleRate.load() << std::endl;
|
||||
DeviceConfig *devConfig = deviceConfig.load();
|
||||
if (devConfig) {
|
||||
devConfig->setSampleRate(rate);
|
||||
}
|
||||
// std::cout << "Set sample rate: " << sampleRate.load() << std::endl;
|
||||
}
|
||||
int SDRThread::getSampleRate() {
|
||||
return sampleRate.load();
|
||||
@ -469,7 +482,7 @@ int SDRThread::getSampleRate() {
|
||||
void SDRThread::setPPM(int ppm) {
|
||||
this->ppm.store(ppm);
|
||||
ppm_changed.store(true);
|
||||
std::cout << "Set PPM: " << this->ppm.load() << std::endl;
|
||||
// std::cout << "Set PPM: " << this->ppm.load() << std::endl;
|
||||
}
|
||||
|
||||
int SDRThread::getPPM() {
|
||||
@ -479,6 +492,10 @@ int SDRThread::getPPM() {
|
||||
void SDRThread::setAGCMode(bool mode) {
|
||||
agc_mode.store(mode);
|
||||
agc_mode_changed.store(true);
|
||||
DeviceConfig *devConfig = deviceConfig.load();
|
||||
if (devConfig) {
|
||||
devConfig->setAGCMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
bool SDRThread::getAGCMode() {
|
||||
@ -499,6 +516,11 @@ void SDRThread::setGain(std::string name, float value) {
|
||||
gainChanged[name] = true;
|
||||
gain_value_changed.store(true);
|
||||
gain_busy.unlock();
|
||||
|
||||
DeviceConfig *devConfig = deviceConfig.load();
|
||||
if (devConfig) {
|
||||
devConfig->setGain(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
float SDRThread::getGain(std::string name) {
|
||||
|
@ -371,6 +371,8 @@ std::string DataElement::toString() {
|
||||
double floatSettingValue;
|
||||
get(floatSettingValue);
|
||||
strValue = std::to_string(floatSettingValue);
|
||||
} else if (dataType == DATA_NULL) {
|
||||
strValue = "";
|
||||
} else {
|
||||
std::cout << "Unhandled DataElement toString for type: " << dataType << std::endl;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ GainCanvas::GainCanvas(wxWindow *parent, int *dispAttrs) :
|
||||
barWidth = (1.0/numGains)*0.8;
|
||||
startPos = spacing/2.0;
|
||||
barHeight = 0.8;
|
||||
refreshCounter = 0;
|
||||
}
|
||||
|
||||
GainCanvas::~GainCanvas() {
|
||||
@ -186,8 +187,9 @@ void GainCanvas::updateGainUI() {
|
||||
const wxSize ClientSize = GetClientSize();
|
||||
|
||||
SDRDeviceInfo *devInfo = wxGetApp().getDevice();
|
||||
DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(devInfo->getDeviceId());
|
||||
|
||||
SDRRangeMap gains = devInfo->getGains(SOAPY_SDR_RX, 0);
|
||||
gains = devInfo->getGains(SOAPY_SDR_RX, 0);
|
||||
SDRRangeMap::iterator gi;
|
||||
|
||||
numGains = gains.size();
|
||||
@ -223,7 +225,8 @@ void GainCanvas::updateGainUI() {
|
||||
gInfo->name = gi->first;
|
||||
gInfo->low = gi->second.minimum();
|
||||
gInfo->high = gi->second.maximum();
|
||||
gInfo->current = wxGetApp().getGain(gInfo->name);
|
||||
gInfo->current = devConfig->getGain(gInfo->name,wxGetApp().getGain(gInfo->name));
|
||||
gInfo->changed = false;
|
||||
|
||||
gInfo->panel.setBorderPx(1);
|
||||
gInfo->panel.setFill(GLPanel::GLPANEL_FILL_GRAD_BAR_X);
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "MouseTracker.h"
|
||||
#include "GLPanel.h"
|
||||
#include "PrimaryGLContext.h"
|
||||
|
||||
#include "SDRDeviceInfo.h"
|
||||
#include "Timer.h"
|
||||
|
||||
class GainInfo {
|
||||
@ -53,8 +53,10 @@ private:
|
||||
std::string helpTip;
|
||||
std::vector<GainInfo *> gainInfo;
|
||||
GLPanel bgPanel;
|
||||
SDRRangeMap gains;
|
||||
|
||||
float spacing, barWidth, startPos, barHeight, numGains;
|
||||
int refreshCounter;
|
||||
wxSize clientSize;
|
||||
//
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
|
Loading…
Reference in New Issue
Block a user