From 48aff5baf1159b1fecf051eb801a0f833568e0b4 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 31 Jan 2016 15:11:54 -0500 Subject: [PATCH 01/10] Remove SoapySDR::Device proxy classes and functions, use SoapySDR directly --- src/AppFrame.cpp | 25 ++- src/CubicSDR.cpp | 33 ++-- src/forms/SDRDevices/SDRDevices.cpp | 12 +- src/sdr/SDRDeviceInfo.cpp | 245 +++++++--------------------- src/sdr/SDRDeviceInfo.h | 96 ++--------- src/sdr/SDREnumerator.cpp | 115 +++++++------ src/sdr/SoapySDRThread.cpp | 32 ++-- src/visual/GainCanvas.cpp | 12 +- 8 files changed, 178 insertions(+), 392 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 947d4ba..0044ebc 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -556,7 +556,7 @@ void AppFrame::updateDeviceParams() { // Build settings menu wxMenu *newSettingsMenu = new wxMenu; newSettingsMenu->Append(wxID_SET_FREQ_OFFSET, "Frequency Offset"); - if (devInfo->getRxChannel()->hasCORR()) { + if (devInfo->hasCORR(SOAPY_SDR_RX, 0)) { newSettingsMenu->Append(wxID_SET_PPM, "Device PPM"); } @@ -566,7 +566,7 @@ void AppFrame::updateDeviceParams() { SoapySDR::ArgInfoList::const_iterator args_i; int i = 0; - settingArgs = devInfo->getSettingsArgInfo(); + settingArgs = devInfo->getSoapyDevice()->getSettingInfo(); for (args_i = settingArgs.begin(); args_i != settingArgs.end(); args_i++) { SoapySDR::ArgInfo arg = (*args_i); std::string currentVal = wxGetApp().getSDRThread()->readSetting(arg.key); @@ -610,7 +610,7 @@ void AppFrame::updateDeviceParams() { settingsMenu = newSettingsMenu; // Build sample rate menu - sampleRates = devInfo->getRxChannel()->getSampleRates(); + sampleRates = devInfo->getSampleRates(SOAPY_SDR_RX, 0); sampleRateMenuItems.erase(sampleRateMenuItems.begin(),sampleRateMenuItems.end()); wxMenu *newSampleRateMenu = new wxMenu; @@ -637,7 +637,7 @@ void AppFrame::updateDeviceParams() { if (!wxGetApp().getAGCMode()) { gainSpacerItem->Show(true); gainSizerItem->Show(true); - gainSizerItem->SetMinSize(devInfo->getRxChannel()->getGains().size()*50,0); + gainSizerItem->SetMinSize(devInfo->getSoapyDevice()->listGains(SOAPY_SDR_RX,0).size()*50,0); demodTray->Layout(); gainCanvas->updateGainUI(); gainCanvas->Refresh(); @@ -695,7 +695,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) { wxGetApp().setAGCMode(false); gainSpacerItem->Show(true); gainSizerItem->Show(true); - gainSizerItem->SetMinSize(wxGetApp().getDevice()->getRxChannel()->getGains().size()*40,0); + gainSizerItem->SetMinSize(wxGetApp().getDevice()->getSoapyDevice()->listGains(SOAPY_SDR_RX, 0).size()*40,0); demodTray->Layout(); gainCanvas->updateGainUI(); gainCanvas->Refresh(); @@ -837,14 +837,14 @@ void AppFrame::OnMenu(wxCommandEvent& event) { break; } - SDRDeviceChannel *chan = dev->getRxChannel(); + std::vector sampleRates = dev->getSampleRates(SOAPY_SDR_RX, 0); rateLow = 2000000; rateHigh = 30000000; - if (chan->getSampleRates().size()) { - rateLow = chan->getSampleRates()[0]; - rateHigh = chan->getSampleRates()[chan->getSampleRates().size()-1]; + if (sampleRates.size()) { + rateLow = sampleRates[0]; + rateHigh = sampleRates[sampleRates.size()-1]; } long bw = wxGetNumberFromUser("\n" + dev->getName() + "\n\n " @@ -1377,11 +1377,8 @@ bool AppFrame::loadSession(std::string fileName) { SDRDeviceInfo *dev = wxGetApp().getSDRThread()->getDevice(); if (dev) { - SDRDeviceChannel *chan = dev->getRxChannel(); - if (chan) { - // Try for a reasonable default sample rate. - sample_rate = chan->getSampleRateNear(sample_rate); - } + // Try for a reasonable default sample rate. + sample_rate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, sample_rate); wxGetApp().setSampleRate(sample_rate); deviceChanged.store(true); } else { diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index b265957..e804af3 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -526,45 +526,34 @@ void CubicSDR::setDevice(SDRDeviceInfo *dev) { DeviceConfig *devConfig = config.getDevice(dev->getDeviceId()); - SDRDeviceChannel *chan = dev->getRxChannel(); + SoapySDR::Device *soapyDev = dev->getSoapyDevice(); - if (chan) { + if (soapyDev) { long long freqHigh, freqLow; - freqHigh = chan->getRFRange().getHigh(); - freqLow = chan->getRFRange().getLow(); + 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 = chan->getSampleRateNear(DEFAULT_SAMPLE_RATE); + sampleRate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, DEFAULT_SAMPLE_RATE); sampleRateInitialized.store(true); + } else { + sampleRate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, sampleRate); } - int rateHigh, rateLow; - - rateHigh = rateLow = sampleRate; - - if (chan->getSampleRates().size()) { - rateLow = chan->getSampleRates()[0]; - rateHigh = chan->getSampleRates()[chan->getSampleRates().size()-1]; - } - - if (sampleRate > rateHigh) { - sampleRate = rateHigh; - } else if (sampleRate < rateLow) { - sampleRate = rateLow; - } - if (frequency < sampleRate/2) { frequency = sampleRate/2; } - + setFrequency(frequency); setSampleRate(sampleRate); setPPM(devConfig->getPPM()); setOffset(devConfig->getOffset()); - + t_SDR = new std::thread(&SDRThread::threadMain, sdrThread); } } diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index 96aa84b..c3088f9 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -104,7 +104,7 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getName()); m_propertyGrid->Clear(); - SoapySDR::ArgInfoList args = dev->getSettingsArgInfo(); + SoapySDR::ArgInfoList args = dev->getSoapyDevice()->getSettingInfo(); SoapySDR::ArgInfoList::const_iterator args_i; m_propertyGrid->Append(new wxPropertyCategory("General Settings")); @@ -125,8 +125,8 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { } } - if (dev->getRxChannel()) { - args = dev->getRxChannel()->getStreamArgsInfo(); + if (dev) { + args = dev->getSoapyDevice()->getStreamArgsInfo(SOAPY_SDR_RX, 0); DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); ConfigSettings devStreamOpts = devConfig->getStreamOpts(); @@ -237,7 +237,7 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) { if (dev != NULL) { int i = 0; SoapySDR::ArgInfoList::const_iterator args_i; - SoapySDR::ArgInfoList args = dev->getSettingsArgInfo(); + SoapySDR::ArgInfoList args = dev->getSoapyDevice()->getSettingInfo(); SoapySDR::Kwargs settingArgs; SoapySDR::Kwargs streamArgs; @@ -257,8 +257,8 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) { i++; } - if (dev->getRxChannel()) { - args = dev->getRxChannel()->getStreamArgsInfo(); + if (dev) { + args = dev->getSoapyDevice()->getStreamArgsInfo(SOAPY_SDR_RX, 0); if (args.size()) { for (args_i = args.begin(); args_i != args.end(); args_i++) { diff --git a/src/sdr/SDRDeviceInfo.cpp b/src/sdr/SDRDeviceInfo.cpp index 596c3f9..345f236 100644 --- a/src/sdr/SDRDeviceInfo.cpp +++ b/src/sdr/SDRDeviceInfo.cpp @@ -1,167 +1,14 @@ #include "SDRDeviceInfo.h" #include -SDRDeviceRange::SDRDeviceRange() { - low = 0; - high = 0; +SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false), remote(false), manual(false), soapyDevice(nullptr) { + } -SDRDeviceRange::SDRDeviceRange(double low, double high) { - this->low = low; - this->high = high; -} - -SDRDeviceRange::SDRDeviceRange(std::string name, double low, double high) : SDRDeviceRange(low, high) { - this->name = name; -} - -double SDRDeviceRange::getLow() { - return low; -} -void SDRDeviceRange::setLow(double low) { - this->low = low; -} -double SDRDeviceRange::getHigh() { - return high; -} -void SDRDeviceRange::setHigh(double high) { - this->high = high; -} - -std::string SDRDeviceRange::getName() { - return this->name; -} - -void SDRDeviceRange::setName(std::string name) { - this->name = name; -} - -SDRDeviceChannel::SDRDeviceChannel() { - hardwareDC = false; - hasCorr = false; -} - -SDRDeviceChannel::~SDRDeviceChannel() { - -} - -int SDRDeviceChannel::getChannel() { - return channel; -} - -void SDRDeviceChannel::setChannel(int channel) { - this->channel = channel; -} - -bool SDRDeviceChannel::isFullDuplex() { - return fullDuplex; -} - -void SDRDeviceChannel::setFullDuplex(bool fullDuplex) { - this->fullDuplex = fullDuplex; -} - -bool SDRDeviceChannel::isTx() { - return tx; -} - -void SDRDeviceChannel::setTx(bool tx) { - this->tx = tx; -} - -bool SDRDeviceChannel::isRx() { - return rx; -} - -void SDRDeviceChannel::setRx(bool rx) { - this->rx = rx; -} - -SDRDeviceRange &SDRDeviceChannel::getGain() { - return rangeGain; -} - -SDRDeviceRange &SDRDeviceChannel::getLNAGain() { - return rangeLNA; -} - -SDRDeviceRange &SDRDeviceChannel::getFreqRange() { - return rangeFull; -} - -SDRDeviceRange &SDRDeviceChannel::getRFRange() { - return rangeRF; -} - -void SDRDeviceChannel::addGain(SDRDeviceRange range) { - gainInfo.push_back(range); -} - -std::vector &SDRDeviceChannel::getGains() { - return gainInfo; -} - -void SDRDeviceChannel::addGain(std::string name, SoapySDR::Range range) { - gainInfo.push_back(SDRDeviceRange(name,range.minimum(),range.maximum())); -} - -std::vector &SDRDeviceChannel::getSampleRates() { - return sampleRates; -} - -long SDRDeviceChannel::getSampleRateNear(long sampleRate_in) { - long returnRate = sampleRates[0]; - long sDelta = (long)sampleRate_in-sampleRates[0]; - long minDelta = std::abs(sDelta); - for (std::vector::iterator i = sampleRates.begin(); i != sampleRates.end(); i++) { - long thisDelta = std::abs(sampleRate_in - (*i)); - if (thisDelta < minDelta) { - minDelta = thisDelta; - returnRate = (*i); - } +SDRDeviceInfo::~SDRDeviceInfo() { + if (soapyDevice != nullptr) { + SoapySDR::Device::unmake(soapyDevice); } - return returnRate; -} - -std::vector &SDRDeviceChannel::getFilterBandwidths() { - return filterBandwidths; -} - -const bool& SDRDeviceChannel::hasHardwareDC() const { - return hardwareDC; -} - -void SDRDeviceChannel::setHardwareDC(const bool& hardware) { - hardwareDC = hardware; -} - -const bool& SDRDeviceChannel::hasCORR() const { - return hasCorr; -} - -void SDRDeviceChannel::setCORR(const bool& hasCorr) { - this->hasCorr = hasCorr; -} - -void SDRDeviceChannel::setStreamArgsInfo(SoapySDR::ArgInfoList streamArgs) { - streamArgInfo = streamArgs; -} - -SoapySDR::ArgInfoList SDRDeviceChannel::getStreamArgsInfo() { - return streamArgInfo; -} - -std::vector SDRDeviceChannel::getStreamArgNames() { - std::vector names; - for (SoapySDR::ArgInfoList::const_iterator i = streamArgInfo.begin(); i != streamArgInfo.end(); i++) { - names.push_back((*i).key); - } - return names; -} - - -SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false), remote(false), manual(false) { - } std::string SDRDeviceInfo::getDeviceId() { @@ -294,48 +141,66 @@ SoapySDR::Kwargs SDRDeviceInfo::getStreamArgs() { return streamArgs; } -void SDRDeviceInfo::setSettingsInfo(SoapySDR::ArgInfoList settingsArgs) { - settingInfo = settingsArgs; -} - -SoapySDR::ArgInfoList SDRDeviceInfo::getSettingsArgInfo() { - return settingInfo; -} - -std::vector SDRDeviceInfo::getSettingNames() { - std::vector names; - for (SoapySDR::ArgInfoList::const_iterator i = settingInfo.begin(); i != settingInfo.end(); i++) { - names.push_back((*i).key); +void SDRDeviceInfo::setSoapyDevice(SoapySDR::Device *dev) { + if (soapyDevice) { + SoapySDR::Device::unmake(soapyDevice); } - return names; + soapyDevice = dev; } - -void SDRDeviceInfo::addChannel(SDRDeviceChannel *chan) { - channels.push_back(chan); +SoapySDR::Device *SDRDeviceInfo::getSoapyDevice() { + if (soapyDevice == nullptr) { + soapyDevice = SoapySDR::Device::make(deviceArgs); + } + return soapyDevice; } -std::vector &SDRDeviceInfo::getChannels() { - return channels; +bool SDRDeviceInfo::hasCORR(int direction, size_t channel) { + SoapySDR::Device *dev = getSoapyDevice(); + + std::vector freqs = dev->listFrequencies(direction, channel); + if (std::find(freqs.begin(), freqs.end(), "CORR") != freqs.end()) { + return true; + } else { + return false; + } } -SDRDeviceChannel * SDRDeviceInfo::getRxChannel() { - std::vector::iterator channel_i; - for (channel_i = channels.begin(); channel_i != channels.end(); channel_i++) { - if ((*channel_i)->isRx()) { - return (*channel_i); +std::vector SDRDeviceInfo::getSampleRates(int direction, size_t channel) { + SoapySDR::Device *dev = getSoapyDevice(); + + std::vector result; + std::vector sampleRates = dev->listSampleRates(direction, channel); + for (std::vector::iterator si = sampleRates.begin(); si != sampleRates.end(); si++) { + result.push_back((long)(*si)); + } + + return result; +} + +long SDRDeviceInfo::getSampleRateNear(int direction, size_t channel, long sampleRate_in) { + std::vector sampleRates = getSampleRates(direction, channel); + long returnRate = sampleRates[0]; + long sDelta = (long)sampleRate_in-sampleRates[0]; + long minDelta = std::abs(sDelta); + for (std::vector::iterator i = sampleRates.begin(); i != sampleRates.end(); i++) { + long thisDelta = std::abs(sampleRate_in - (*i)); + if (thisDelta < minDelta) { + minDelta = thisDelta; + returnRate = (*i); } } - return NULL; + return returnRate; } -SDRDeviceChannel * SDRDeviceInfo::getTxChannel() { - std::vector::iterator channel_i; - for (channel_i = channels.begin(); channel_i != channels.end(); channel_i++) { - if ((*channel_i)->isTx()) { - return (*channel_i); - } +SDRRangeMap SDRDeviceInfo::getGains(int direction, size_t channel) { + SoapySDR::Device *dev = getSoapyDevice(); + std::vector gainNames = dev->listGains(direction, channel); + std::map gainMap; + + for (std::vector::iterator gname = gainNames.begin(); gname!= gainNames.end(); gname++) { + gainMap[(*gname)] = dev->getGainRange(direction, channel, (*gname)); } - return NULL; + + return gainMap; } - diff --git a/src/sdr/SDRDeviceInfo.h b/src/sdr/SDRDeviceInfo.h index 157c24a..6b3998c 100644 --- a/src/sdr/SDRDeviceInfo.h +++ b/src/sdr/SDRDeviceInfo.h @@ -4,84 +4,19 @@ #include #include +#include typedef struct _SDRManualDef { std::string factory; std::string params; } SDRManualDef; -class SDRDeviceRange { -public: - SDRDeviceRange(); - SDRDeviceRange(double low, double high); - SDRDeviceRange(std::string name, double low, double high); - - double getLow(); - void setLow(double low); - double getHigh(); - void setHigh(double high); - std::string getName(); - void setName(std::string name); - -private: - std::string name; - double low, high; -}; - -class SDRDeviceChannel { -public: - SDRDeviceChannel(); - ~SDRDeviceChannel(); - - int getChannel(); - void setChannel(int channel); - - bool isFullDuplex(); - void setFullDuplex(bool fullDuplex); - - bool isTx(); - void setTx(bool tx); - - bool isRx(); - void setRx(bool rx); - - void addGain(SDRDeviceRange range); - void addGain(std::string name, SoapySDR::Range range); - std::vector &getGains(); - - SDRDeviceRange &getGain(); - SDRDeviceRange &getLNAGain(); - SDRDeviceRange &getFreqRange(); - SDRDeviceRange &getRFRange(); - - std::vector &getSampleRates(); - long getSampleRateNear(long sampleRate_in); - std::vector &getFilterBandwidths(); - - const bool& hasHardwareDC() const; - void setHardwareDC(const bool& hardware); - - const bool& hasCORR() const; - void setCORR(const bool& corr); - - void setStreamArgsInfo(SoapySDR::ArgInfoList streamArgs); - SoapySDR::ArgInfoList getStreamArgsInfo(); - std::vector getStreamArgNames(); - -private: - int channel; - bool fullDuplex, tx, rx, hardwareDC, hasCorr; - SDRDeviceRange rangeGain, rangeLNA, rangeFull, rangeRF; - std::vector sampleRates; - std::vector filterBandwidths; - SoapySDR::ArgInfoList streamArgInfo; - std::vector gainInfo; -}; - +typedef std::map SDRRangeMap; class SDRDeviceInfo { public: SDRDeviceInfo(); + ~SDRDeviceInfo(); std::string getDeviceId(); @@ -123,11 +58,6 @@ public: void setManualParams(std::string manualParams); std::string getManualParams(); - - void addChannel(SDRDeviceChannel *chan); - std::vector &getChannels(); - SDRDeviceChannel * getRxChannel(); - SDRDeviceChannel * getTxChannel(); void setDeviceArgs(SoapySDR::Kwargs deviceArgs); SoapySDR::Kwargs getDeviceArgs(); @@ -135,11 +65,22 @@ public: void setStreamArgs(SoapySDR::Kwargs deviceArgs); SoapySDR::Kwargs getStreamArgs(); - void setSettingsInfo(SoapySDR::ArgInfoList settingsArgs); - SoapySDR::ArgInfoList getSettingsArgInfo(); +// void setSettingsInfo(SoapySDR::ArgInfoList settingsArgs); +// SoapySDR::ArgInfoList getSettingsArgInfo(); - std::vector getSettingNames(); +// std::vector getSettingNames(); + void setSoapyDevice(SoapySDR::Device *dev); + SoapySDR::Device *getSoapyDevice(); + + bool hasCORR(int direction, size_t channel); + + std::vector getSampleRates(int direction, size_t channel); + + long getSampleRateNear(int direction, size_t channel, long sampleRate_in); + + SDRRangeMap getGains(int direction, size_t channel); + private: int index; std::string name, serial, product, manufacturer, tuner; @@ -147,6 +88,5 @@ private: bool timestamps, available, remote, manual; SoapySDR::Kwargs deviceArgs, streamArgs; - SoapySDR::ArgInfoList settingInfo; - std::vector channels; + SoapySDR::Device *soapyDevice; }; diff --git a/src/sdr/SDREnumerator.cpp b/src/sdr/SDREnumerator.cpp index 873bf80..e178c88 100644 --- a/src/sdr/SDREnumerator.cpp +++ b/src/sdr/SDREnumerator.cpp @@ -273,67 +273,66 @@ std::vector *SDREnumerator::enumerate_devices(std::string remot } dev->setDeviceArgs(deviceArgs); - dev->setSettingsInfo(settingsInfo); +// dev->setSettingsInfo(settingsInfo); - int numChan = device->getNumChannels(SOAPY_SDR_RX); - for (int i = 0; i < numChan; i++) { - SDRDeviceChannel *chan = new SDRDeviceChannel(); - - SoapySDR::RangeList rfRange = device->getFrequencyRange(SOAPY_SDR_RX, i); - double rfMin = rfRange[0].minimum(); - double rfMax = rfRange[rfRange.size()-1].maximum(); - chan->setChannel(i); - chan->setFullDuplex(device->getFullDuplex(SOAPY_SDR_RX, i)); - chan->setRx(true); - chan->setTx(false); - chan->getRFRange().setLow(rfMin); - chan->getRFRange().setHigh(rfMax); - - std::vector freqs = device->listFrequencies(SOAPY_SDR_RX,i); - if (std::find(freqs.begin(), freqs.end(), "CORR") != freqs.end()) { - chan->setCORR(true); - } else { - chan->setCORR(false); - } - - if (device->hasDCOffsetMode(SOAPY_SDR_RX, i)) { - chan->setHardwareDC(true); - } else { - chan->setHardwareDC(false); - } - - std::vector rates = device->listSampleRates(SOAPY_SDR_RX, i); - for (std::vector::iterator i = rates.begin(); i != rates.end(); i++) { - chan->getSampleRates().push_back((long)(*i)); - } - - ConfigSettings devStreamOpts = cfg->getStreamOpts(); - if (devStreamOpts.size()) { - dev->setStreamArgs(devStreamOpts); - } - - SoapySDR::ArgInfoList optArgs = device->getStreamArgsInfo(SOAPY_SDR_RX, i); - - if (devStreamOpts.size()) { - for (int j = 0, jMax = optArgs.size(); j < jMax; j++) { - if (devStreamOpts.find(optArgs[j].key) != devStreamOpts.end()) { - optArgs[j].value = devStreamOpts[optArgs[j].key]; - } - } - } - chan->setStreamArgsInfo(optArgs); - - std::vector gainNames = device->listGains(SOAPY_SDR_RX, i); - - for (std::vector::iterator gname = gainNames.begin(); gname!= gainNames.end(); gname++) { - chan->addGain((*gname),device->getGainRange(SOAPY_SDR_RX, i, (*gname))); - } - - dev->addChannel(chan); - } +// int numChan = device->getNumChannels(SOAPY_SDR_RX); +// for (int i = 0; i < numChan; i++) { +// SDRDeviceChannel *chan = new SDRDeviceChannel(); +// +// SoapySDR::RangeList rfRange = device->getFrequencyRange(SOAPY_SDR_RX, i); +// double rfMin = rfRange[0].minimum(); +// double rfMax = rfRange[rfRange.size()-1].maximum(); +// chan->setChannel(i); +// chan->setFullDuplex(device->getFullDuplex(SOAPY_SDR_RX, i)); +// chan->setRx(true); +// chan->setTx(false); +// chan->getRFRange().setLow(rfMin); +// chan->getRFRange().setHigh(rfMax); +// +// std::vector freqs = device->listFrequencies(SOAPY_SDR_RX,i); +// if (std::find(freqs.begin(), freqs.end(), "CORR") != freqs.end()) { +// chan->setCORR(true); +// } else { +// chan->setCORR(false); +// } +// +// if (device->hasDCOffsetMode(SOAPY_SDR_RX, i)) { +// chan->setHardwareDC(true); +// } else { +// chan->setHardwareDC(false); +// } +// +// std::vector rates = device->listSampleRates(SOAPY_SDR_RX, i); +// for (std::vector::iterator i = rates.begin(); i != rates.end(); i++) { +// chan->getSampleRates().push_back((long)(*i)); +// } +// +// ConfigSettings devStreamOpts = cfg->getStreamOpts(); +// if (devStreamOpts.size()) { +// dev->setStreamArgs(devStreamOpts); +// } +// +// SoapySDR::ArgInfoList optArgs = device->getStreamArgsInfo(SOAPY_SDR_RX, i); +// +// if (devStreamOpts.size()) { +// for (int j = 0, jMax = optArgs.size(); j < jMax; j++) { +// if (devStreamOpts.find(optArgs[j].key) != devStreamOpts.end()) { +// optArgs[j].value = devStreamOpts[optArgs[j].key]; +// } +// } +// } +// chan->setStreamArgsInfo(optArgs); +// +// std::vector gainNames = device->listGains(SOAPY_SDR_RX, i); +// +// for (std::vector::iterator gname = gainNames.begin(); gname!= gainNames.end(); gname++) { +// chan->addGain((*gname),device->getGainRange(SOAPY_SDR_RX, i, (*gname))); +// } +// +// dev->addChannel(chan); +// } SoapySDR::Device::unmake(device); - dev->setAvailable(true); } catch (const std::exception &ex) { std::cerr << "Error making device: " << ex.what() << std::endl; diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index 7a13480..ecbec96 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -73,7 +73,7 @@ void SDRThread::init() { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Initializing device.")); - device = SoapySDR::Device::make(args); + device = devInfo->getSoapyDevice(); SoapySDR::Kwargs currentStreamArgs = combineArgs(devInfo->getStreamArgs(),streamArgs); stream = device->setupStream(SOAPY_SDR_RX,"CF32", std::vector(), currentStreamArgs); @@ -90,17 +90,16 @@ void SDRThread::init() { device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load()); device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency - offset.load()); device->activateStream(stream); - SDRDeviceChannel *chan = devInfo->getRxChannel(); - if (chan->hasCORR()) { + if (devInfo->hasCORR(SOAPY_SDR_RX, 0)) { hasPPM.store(true); device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm.load()); } else { hasPPM.store(false); } - if (chan->hasHardwareDC()) { + if (device->hasDCOffsetMode(SOAPY_SDR_RX, 0)) { hasHardwareDC.store(true); // wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Found hardware DC offset correction support, internal disabled.")); - device->setDCOffsetMode(SOAPY_SDR_RX, chan->getChannel(), true); + device->setDCOffsetMode(SOAPY_SDR_RX, 0, true); } else { hasHardwareDC.store(false); } @@ -139,7 +138,7 @@ void SDRThread::init() { } setting_value_changed.store(false); - SoapySDR::ArgInfoList devSettings = deviceInfo.load()->getSettingsArgInfo(); + SoapySDR::ArgInfoList devSettings = deviceInfo.load()->getSoapyDevice()->getSettingInfo(); if (devSettings.size()) { for (size_t j = 0; j < settingsInfo.size(); j++) { if (settings.find(settingsInfo[j].key) != settings.end()) { @@ -147,7 +146,7 @@ void SDRThread::init() { } } } - deviceInfo.load()->setSettingsInfo(devSettings); +// deviceInfo.load()->setSettingsInfo(devSettings); setting_busy.unlock(); @@ -155,9 +154,10 @@ void SDRThread::init() { } void SDRThread::deinit() { + SDRDeviceInfo *devInfo = deviceInfo.load(); device->deactivateStream(stream); device->closeStream(stream); - SoapySDR::Device::unmake(device); + devInfo->setSoapyDevice(nullptr); free(buffs[0]); } @@ -247,10 +247,10 @@ void SDRThread::updateGains() { gainValues.erase(gainValues.begin(),gainValues.end()); gainChanged.erase(gainChanged.begin(),gainChanged.end()); - std::vector gains = devInfo->getRxChannel()->getGains(); - for (std::vector::iterator gi = gains.begin(); gi != gains.end(); gi++) { - gainValues[(*gi).getName()] = device->getGain(SOAPY_SDR_RX, devInfo->getRxChannel()->getChannel(), (*gi).getName()); - gainChanged[(*gi).getName()] = false; + SDRRangeMap gains = devInfo->getGains(SOAPY_SDR_RX, 0); + for (SDRRangeMap::iterator gi = gains.begin(); gi != gains.end(); gi++) { + gainValues[gi->first] = device->getGain(SOAPY_SDR_RX, 0, gi->first); + gainChanged[gi->first] = false; } gain_value_changed.store(false); @@ -304,9 +304,7 @@ void SDRThread::updateSettings() { // } if (agc_mode_changed.load()) { - SDRDeviceInfo *devInfo = deviceInfo.load(); - - device->setGainMode(SOAPY_SDR_RX,devInfo->getRxChannel()->getChannel(),agc_mode.load()); + device->setGainMode(SOAPY_SDR_RX, 0, agc_mode.load()); agc_mode_changed.store(false); if (!agc_mode.load()) { updateGains(); @@ -314,12 +312,10 @@ void SDRThread::updateSettings() { } if (gain_value_changed.load() && !agc_mode.load()) { - SDRDeviceInfo *devInfo = deviceInfo.load(); - gain_busy.lock(); for (std::map::iterator gci = gainChanged.begin(); gci != gainChanged.end(); gci++) { if (gci->second) { - device->setGain(SOAPY_SDR_RX, devInfo->getRxChannel()->getChannel(), gci->first, gainValues[gci->first]); + device->setGain(SOAPY_SDR_RX, 0, gci->first, gainValues[gci->first]); gainChanged[gci->first] = false; } } diff --git a/src/visual/GainCanvas.cpp b/src/visual/GainCanvas.cpp index 4235674..3b82e82 100644 --- a/src/visual/GainCanvas.cpp +++ b/src/visual/GainCanvas.cpp @@ -184,8 +184,8 @@ void GainCanvas::updateGainUI() { SDRDeviceInfo *devInfo = wxGetApp().getDevice(); - std::vector &gains = devInfo->getRxChannel()->getGains(); - std::vector::iterator gi; + SDRRangeMap gains = devInfo->getGains(SOAPY_SDR_RX, 0); + SDRRangeMap::iterator gi; numGains = gains.size(); float i = 0; @@ -217,9 +217,9 @@ void GainCanvas::updateGainUI() { GainInfo *gInfo = new GainInfo; float midPos = -1.0+startPos+spacing*i; - gInfo->name = (*gi).getName(); - gInfo->low = (*gi).getLow(); - gInfo->high = (*gi).getHigh(); + gInfo->name = gi->first; + gInfo->low = gi->second.minimum(); + gInfo->high = gi->second.maximum(); gInfo->current = wxGetApp().getGain(gInfo->name); gInfo->panel.setBorderPx(1); @@ -251,7 +251,7 @@ void GainCanvas::updateGainUI() { gInfo->labelPanel.setSize(spacing/2.0,(15.0/float(ClientSize.y))); gInfo->labelPanel.setPosition(midPos, -barHeight-(20.0/float(ClientSize.y))); - gInfo->labelPanel.setText((*gi).getName()); + gInfo->labelPanel.setText(gi->first); gInfo->labelPanel.setFill(GLPanel::GLPANEL_FILL_NONE); bgPanel.addChild(&(gInfo->labelPanel)); From 609a2216ad94cde52bf6c2b6ba5d1ee5b347118d Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 1 Feb 2016 20:30:48 -0500 Subject: [PATCH 02/10] SDR Device settings live refresh --- src/forms/SDRDevices/SDRDevices.cpp | 70 ++++++++++++++++------------- src/forms/SDRDevices/SDRDevices.h | 4 +- src/sdr/SDREnumerator.cpp | 58 ------------------------ src/sdr/SoapySDRThread.cpp | 12 +---- 4 files changed, 45 insertions(+), 99 deletions(-) diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index c3088f9..986e31f 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -95,33 +95,34 @@ wxPGProperty *SDRDevicesDialog::addArgInfoProperty(wxPropertyGrid *pg, SoapySDR: return prop; } -void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { - +void SDRDevicesDialog::refreshDeviceProperties() { SDRDeviceInfo *selDev = getSelectedDevice(devTree->GetSelection()); if (selDev && selDev->isAvailable()) { dev = selDev; selId = devTree->GetSelection(); DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getName()); m_propertyGrid->Clear(); - - SoapySDR::ArgInfoList args = dev->getSoapyDevice()->getSettingInfo(); + + SoapySDR::Device *soapyDev = dev->getSoapyDevice(); + SoapySDR::ArgInfoList args = soapyDev->getSettingInfo(); SoapySDR::ArgInfoList::const_iterator args_i; - + m_propertyGrid->Append(new wxPropertyCategory("General Settings")); devSettings.erase(devSettings.begin(),devSettings.end()); 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()) ); - - props.erase(props.begin(), props.end()); - + + runtimeProps.erase(runtimeProps.begin(), runtimeProps.end()); + streamProps.erase(streamProps.begin(), streamProps.end()); + if (args.size()) { m_propertyGrid->Append(new wxPropertyCategory("Run-time Settings")); - for (args_i = args.begin(); args_i != args.end(); args_i++) { SoapySDR::ArgInfo arg = (*args_i); - props.push_back(addArgInfoProperty(m_propertyGrid, arg)); + arg.value = soapyDev->readSetting(arg.key); + runtimeProps[arg.key] = addArgInfoProperty(m_propertyGrid, arg); } } @@ -137,13 +138,13 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { } } } - + if (args.size()) { m_propertyGrid->Append(new wxPropertyCategory("Stream Settings")); - + for (args_i = args.begin(); args_i != args.end(); args_i++) { SoapySDR::ArgInfo arg = (*args_i); - props.push_back(addArgInfoProperty(m_propertyGrid, arg)); + streamProps[arg.key] = addArgInfoProperty(m_propertyGrid, arg); } } } @@ -159,7 +160,8 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { } else if (selDev && !selDev->isAvailable() && selDev->isManual()) { m_propertyGrid->Clear(); devSettings.erase(devSettings.begin(),devSettings.end()); - props.erase(props.begin(), props.end()); + runtimeProps.erase(runtimeProps.begin(), runtimeProps.end()); + streamProps.erase(streamProps.begin(), streamProps.end()); removeId = devTree->GetSelection(); dev = nullptr; selId = nullptr; @@ -170,6 +172,10 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { m_addRemoteButton->SetLabel("Add"); removeId = nullptr; } +} + +void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { + refreshDeviceProperties(); event.Skip(); } @@ -181,7 +187,8 @@ void SDRDevicesDialog::OnAddRemote( wxMouseEvent& /* event */) { SDREnumerator::removeManual(selDev->getDriver(),selDev->getManualParams()); m_propertyGrid->Clear(); devSettings.erase(devSettings.begin(),devSettings.end()); - props.erase(props.begin(), props.end()); + runtimeProps.erase(runtimeProps.begin(), runtimeProps.end()); + streamProps.erase(streamProps.begin(), streamProps.end()); dev = nullptr; selId = nullptr; editId = nullptr; @@ -233,9 +240,8 @@ SDRDeviceInfo *SDRDevicesDialog::getSelectedDevice(wxTreeItemId selId) { return NULL; } -void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) { +void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event) { if (dev != NULL) { - int i = 0; SoapySDR::ArgInfoList::const_iterator args_i; SoapySDR::ArgInfoList args = dev->getSoapyDevice()->getSettingInfo(); @@ -244,7 +250,7 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) { for (args_i = args.begin(); args_i != args.end(); args_i++) { SoapySDR::ArgInfo arg = (*args_i); - wxPGProperty *prop = props[i]; + wxPGProperty *prop = runtimeProps[arg.key]; if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size()) { settingArgs[arg.key] = arg.options[prop->GetChoiceSelection()]; @@ -253,8 +259,6 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) { } else { settingArgs[arg.key] = prop->GetValueAsString(); } - - i++; } if (dev) { @@ -263,7 +267,7 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) { if (args.size()) { for (args_i = args.begin(); args_i != args.end(); args_i++) { SoapySDR::ArgInfo arg = (*args_i); - wxPGProperty *prop = props[i]; + wxPGProperty *prop = streamProps[arg.key]; if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size()) { streamArgs[arg.key] = arg.options[prop->GetChoiceSelection()]; @@ -272,8 +276,6 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) { } else { streamArgs[arg.key] = prop->GetValueAsString(); } - - i++; } } } @@ -287,6 +289,7 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) { wxGetApp().setDevice(dev); Close(); } + event.Skip(); } void SDRDevicesDialog::OnTreeDoubleClick( wxMouseEvent& event ) { @@ -381,10 +384,6 @@ void SDRDevicesDialog::OnRefreshDevices( wxMouseEvent& /* event */) { } void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { - if (!editId) { - return; - } - SDRDeviceInfo *dev = getSelectedDevice(editId); if (editId && event.GetProperty() == devSettings["name"]) { DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); @@ -397,13 +396,23 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { if (devName == "") { event.GetProperty()->SetValueFromString(devConfig->getDeviceName()); } - } - if (dev && event.GetProperty() == devSettings["offset"]) { + } else if (dev && event.GetProperty() == devSettings["offset"]) { DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); long offset = event.GetPropertyValue().GetInteger(); devConfig->setOffset(offset); + } else if (editId && dev) { + wxPGProperty *prop = event.GetProperty(); + + for (std::map::iterator rtp = runtimeProps.begin(); rtp != runtimeProps.end(); rtp++) { + if (rtp->second == prop) { + SoapySDR::Device *soapyDev = dev->getSoapyDevice(); + soapyDev->writeSetting(rtp->first, prop->GetValueAsString().ToStdString()); + refreshDeviceProperties(); + return; + } + } } } @@ -417,7 +426,8 @@ void SDRDevicesDialog::doRefreshDevices() { devTree->DeleteAllItems(); devTree->Disable(); m_propertyGrid->Clear(); - props.erase(props.begin(),props.end()); + runtimeProps.erase(runtimeProps.begin(), runtimeProps.end()); + streamProps.erase(streamProps.begin(), streamProps.end()); devSettings.erase(devSettings.begin(), devSettings.end()); m_refreshButton->Disable(); m_addRemoteButton->Disable(); diff --git a/src/forms/SDRDevices/SDRDevices.h b/src/forms/SDRDevices/SDRDevices.h index 333c56a..d98fa62 100644 --- a/src/forms/SDRDevices/SDRDevices.h +++ b/src/forms/SDRDevices/SDRDevices.h @@ -24,6 +24,7 @@ public: void OnPropGridFocus( wxFocusEvent& event ); private: + void refreshDeviceProperties(); void doRefreshDevices(); SDRDeviceInfo *getSelectedDevice(wxTreeItemId selId); @@ -35,7 +36,8 @@ private: std::map devItems; std::map::iterator devItems_i; SDRDeviceInfo *dev; - std::vector props; + std::map runtimeProps; + std::map streamProps; std::map devSettings; wxTreeItemId selId; wxTreeItemId editId; diff --git a/src/sdr/SDREnumerator.cpp b/src/sdr/SDREnumerator.cpp index e178c88..0001211 100644 --- a/src/sdr/SDREnumerator.cpp +++ b/src/sdr/SDREnumerator.cpp @@ -273,64 +273,6 @@ std::vector *SDREnumerator::enumerate_devices(std::string remot } dev->setDeviceArgs(deviceArgs); -// dev->setSettingsInfo(settingsInfo); - -// int numChan = device->getNumChannels(SOAPY_SDR_RX); -// for (int i = 0; i < numChan; i++) { -// SDRDeviceChannel *chan = new SDRDeviceChannel(); -// -// SoapySDR::RangeList rfRange = device->getFrequencyRange(SOAPY_SDR_RX, i); -// double rfMin = rfRange[0].minimum(); -// double rfMax = rfRange[rfRange.size()-1].maximum(); -// chan->setChannel(i); -// chan->setFullDuplex(device->getFullDuplex(SOAPY_SDR_RX, i)); -// chan->setRx(true); -// chan->setTx(false); -// chan->getRFRange().setLow(rfMin); -// chan->getRFRange().setHigh(rfMax); -// -// std::vector freqs = device->listFrequencies(SOAPY_SDR_RX,i); -// if (std::find(freqs.begin(), freqs.end(), "CORR") != freqs.end()) { -// chan->setCORR(true); -// } else { -// chan->setCORR(false); -// } -// -// if (device->hasDCOffsetMode(SOAPY_SDR_RX, i)) { -// chan->setHardwareDC(true); -// } else { -// chan->setHardwareDC(false); -// } -// -// std::vector rates = device->listSampleRates(SOAPY_SDR_RX, i); -// for (std::vector::iterator i = rates.begin(); i != rates.end(); i++) { -// chan->getSampleRates().push_back((long)(*i)); -// } -// -// ConfigSettings devStreamOpts = cfg->getStreamOpts(); -// if (devStreamOpts.size()) { -// dev->setStreamArgs(devStreamOpts); -// } -// -// SoapySDR::ArgInfoList optArgs = device->getStreamArgsInfo(SOAPY_SDR_RX, i); -// -// if (devStreamOpts.size()) { -// for (int j = 0, jMax = optArgs.size(); j < jMax; j++) { -// if (devStreamOpts.find(optArgs[j].key) != devStreamOpts.end()) { -// optArgs[j].value = devStreamOpts[optArgs[j].key]; -// } -// } -// } -// chan->setStreamArgsInfo(optArgs); -// -// std::vector gainNames = device->listGains(SOAPY_SDR_RX, i); -// -// for (std::vector::iterator gname = gainNames.begin(); gname!= gainNames.end(); gname++) { -// chan->addGain((*gname),device->getGainRange(SOAPY_SDR_RX, i, (*gname))); -// } -// -// dev->addChannel(chan); -// } SoapySDR::Device::unmake(device); dev->setAvailable(true); diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index ecbec96..2689a19 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -137,19 +137,11 @@ void SDRThread::init() { } } setting_value_changed.store(false); - - SoapySDR::ArgInfoList devSettings = deviceInfo.load()->getSoapyDevice()->getSettingInfo(); - if (devSettings.size()) { - for (size_t j = 0; j < settingsInfo.size(); j++) { - if (settings.find(settingsInfo[j].key) != settings.end()) { - devSettings[j].value = settings[devSettings[j].key]; - } - } - } -// deviceInfo.load()->setSettingsInfo(devSettings); setting_busy.unlock(); + updateSettings(); + wxGetApp().sdrThreadNotify(SDRThread::SDR_THREAD_INITIALIZED, std::string("Device Initialized.")); } From 2518e22682857f62870250dd2e1f3faa67f7f2b5 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 2 Feb 2016 19:27:08 -0500 Subject: [PATCH 03/10] Update device on setting and bandwidth change --- src/AppFrame.cpp | 5 +++-- src/sdr/SoapySDRThread.cpp | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 0044ebc..e662125 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -566,10 +566,11 @@ void AppFrame::updateDeviceParams() { SoapySDR::ArgInfoList::const_iterator args_i; int i = 0; - settingArgs = devInfo->getSoapyDevice()->getSettingInfo(); + SoapySDR::Device *soapyDev = devInfo->getSoapyDevice(); + settingArgs = soapyDev->getSettingInfo(); for (args_i = settingArgs.begin(); args_i != settingArgs.end(); args_i++) { SoapySDR::ArgInfo arg = (*args_i); - std::string currentVal = wxGetApp().getSDRThread()->readSetting(arg.key); + std::string currentVal = soapyDev->readSetting(arg.key); if (arg.type == SoapySDR::ArgInfo::BOOL) { wxMenuItem *item = newSettingsMenu->AppendCheckItem(wxID_SETTINGS_BASE+i, arg.name, arg.description); item->Check(currentVal=="true"); diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index 2689a19..7ed1cd4 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -249,6 +249,8 @@ void SDRThread::updateGains() { } void SDRThread::updateSettings() { + bool doUpdate = false; + if (offset_changed.load()) { if (!freq_changed.load()) { frequency.store(frequency.load()); @@ -273,6 +275,7 @@ void SDRThread::updateSettings() { buffs[0] = malloc(mtuElems.load() * 4 * sizeof(float)); numOverflow = 0; rate_changed.store(false); + doUpdate = true; } if (ppm_changed.load() && hasPPM.load()) { @@ -301,6 +304,7 @@ void SDRThread::updateSettings() { if (!agc_mode.load()) { updateGains(); } + doUpdate = true; } if (gain_value_changed.load() && !agc_mode.load()) { @@ -329,6 +333,12 @@ void SDRThread::updateSettings() { setting_value_changed.store(false); setting_busy.unlock(); + + doUpdate = true; + } + + if (doUpdate) { + wxGetApp().sdrThreadNotify(SDRThread::SDR_THREAD_INITIALIZED, std::string("Settings updated.")); } } From cc189cc274ef3e411e878d0349c23cddb74b34d3 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 2 Feb 2016 20:05:32 -0500 Subject: [PATCH 04/10] Fix refresh, allow device dialog to update active device --- src/forms/SDRDevices/SDRDevices.cpp | 14 +++++++++----- src/sdr/SDRDeviceInfo.cpp | 10 +++++++++- src/sdr/SDRDeviceInfo.h | 6 +++++- src/sdr/SoapySDRThread.cpp | 8 +++++--- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index 986e31f..2309e71 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -408,7 +408,11 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { for (std::map::iterator rtp = runtimeProps.begin(); rtp != runtimeProps.end(); rtp++) { if (rtp->second == prop) { SoapySDR::Device *soapyDev = dev->getSoapyDevice(); - soapyDev->writeSetting(rtp->first, prop->GetValueAsString().ToStdString()); + std::string settingValue = prop->GetValueAsString().ToStdString(); + soapyDev->writeSetting(rtp->first, settingValue); + if (dev->isActive()) { + wxGetApp().getSDRThread()->writeSetting(rtp->first, settingValue); + } refreshDeviceProperties(); return; } @@ -422,6 +426,10 @@ void SDRDevicesDialog::OnPropGridFocus( wxFocusEvent& /* event */) { void SDRDevicesDialog::doRefreshDevices() { + selId = nullptr; + editId = nullptr; + removeId = nullptr; + dev = nullptr; wxGetApp().stopDevice(); devTree->DeleteAllItems(); devTree->Disable(); @@ -433,10 +441,6 @@ void SDRDevicesDialog::doRefreshDevices() { m_addRemoteButton->Disable(); m_useSelectedButton->Disable(); wxGetApp().reEnumerateDevices(); - selId = nullptr; - editId = nullptr; - removeId = nullptr; - dev = nullptr; refresh = true; m_addRemoteButton->SetLabel("Add"); } diff --git a/src/sdr/SDRDeviceInfo.cpp b/src/sdr/SDRDeviceInfo.cpp index 345f236..a60202a 100644 --- a/src/sdr/SDRDeviceInfo.cpp +++ b/src/sdr/SDRDeviceInfo.cpp @@ -1,7 +1,7 @@ #include "SDRDeviceInfo.h" #include -SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false), remote(false), manual(false), soapyDevice(nullptr) { +SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false), remote(false), manual(false), active(false), soapyDevice(nullptr) { } @@ -37,6 +37,14 @@ void SDRDeviceInfo::setAvailable(bool available) { this->available = available; } +bool SDRDeviceInfo::isActive() const { + return active.load(); +} + +void SDRDeviceInfo::setActive(bool active) { + this->active.store(active); +} + const std::string& SDRDeviceInfo::getName() const { return name; } diff --git a/src/sdr/SDRDeviceInfo.h b/src/sdr/SDRDeviceInfo.h index 6b3998c..086efea 100644 --- a/src/sdr/SDRDeviceInfo.h +++ b/src/sdr/SDRDeviceInfo.h @@ -25,7 +25,10 @@ public: bool isAvailable() const; void setAvailable(bool available); - + + bool isActive() const; + void setActive(bool active); + const std::string& getName() const; void setName(const std::string& name); @@ -86,6 +89,7 @@ private: std::string name, serial, product, manufacturer, tuner; std::string driver, hardware, manual_params; bool timestamps, available, remote, manual; + std::atomic_bool active; SoapySDR::Kwargs deviceArgs, streamArgs; SoapySDR::Device *soapyDevice; diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index 7ed1cd4..fac214c 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -146,10 +146,8 @@ void SDRThread::init() { } void SDRThread::deinit() { - SDRDeviceInfo *devInfo = deviceInfo.load(); device->deactivateStream(stream); device->closeStream(stream); - devInfo->setSoapyDevice(nullptr); free(buffs[0]); } @@ -353,11 +351,15 @@ void SDRThread::run() { std::cout << "SDR thread starting." << std::endl; terminated.store(false); - if (deviceInfo.load() != NULL) { + SDRDeviceInfo *activeDev = deviceInfo.load(); + + if (activeDev != NULL) { std::cout << "device init()" << std::endl; init(); std::cout << "starting readLoop()" << std::endl; + activeDev->setActive(true); readLoop(); + activeDev->setActive(false); std::cout << "readLoop() ended." << std::endl; deinit(); std::cout << "device deinit()" << std::endl; From 090d7514824c68a8da5858c494b2caa94c7759c1 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 2 Feb 2016 20:41:12 -0500 Subject: [PATCH 05/10] Bonus SSB optimize/tweak --- src/modules/modem/analog/ModemLSB.cpp | 9 ++++----- src/modules/modem/analog/ModemUSB.cpp | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp index f23af1d..beaf9cd 100644 --- a/src/modules/modem/analog/ModemLSB.cpp +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -2,12 +2,12 @@ ModemLSB::ModemLSB() : ModemAnalog() { // half band filter used for side-band elimination - demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1); + demodAM_LSB = ampmodem_create(0.25, 0.25, LIQUID_AMPMODEM_LSB, 1); // options float fc = 0.25f; // filter cutoff frequency float ft = 0.05f; // filter transition float As = 90.0f; // stop-band attenuation [dB] - float mu = 0.0f; // fractional timing offset + float mu = 0.5f; // fractional timing offset // estimate required filter length and generate filter unsigned int h_len = estimate_req_filter_len(ft,As); @@ -57,14 +57,13 @@ void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a return; } - liquid_float_complex x, y; + liquid_float_complex x; for (int i = 0; i < bufSize; i++) { // Reject upper band nco_crcf_step(ssbShift); nco_crcf_mix_up(ssbShift, input->data[i], &x); firfilt_crcf_push(ssbFilt, x); firfilt_crcf_execute(ssbFilt, &x); - nco_crcf_mix_down(ssbShift, x, &y); - ampmodem_demodulate(demodAM_LSB, y, &demodOutputData[i]); + ampmodem_demodulate(demodAM_LSB, x, &demodOutputData[i]); } buildAudioOutput(akit, audioOut, true); diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp index 51c88c5..3ae5685 100644 --- a/src/modules/modem/analog/ModemUSB.cpp +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -2,12 +2,12 @@ ModemUSB::ModemUSB() : ModemAnalog() { // half band filter used for side-band elimination - demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1); + demodAM_USB = ampmodem_create(0.25, -0.25, LIQUID_AMPMODEM_USB, 1); // options float fc = 0.25f; // filter cutoff frequency float ft = 0.05f; // filter transition float As = 90.0f; // stop-band attenuation [dB] - float mu = 0.0f; // fractional timing offset + float mu = 0.5f; // fractional timing offset // estimate required filter length and generate filter unsigned int h_len = estimate_req_filter_len(ft,As); @@ -57,14 +57,13 @@ void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a return; } - liquid_float_complex x, y; + liquid_float_complex x; for (int i = 0; i < bufSize; i++) { // Reject lower band nco_crcf_step(ssbShift); nco_crcf_mix_down(ssbShift, input->data[i], &x); firfilt_crcf_push(ssbFilt, x); firfilt_crcf_execute(ssbFilt, &x); - nco_crcf_mix_up(ssbShift, x, &y); - ampmodem_demodulate(demodAM_USB, y, &demodOutputData[i]); + ampmodem_demodulate(demodAM_USB, x, &demodOutputData[i]); } buildAudioOutput(akit, audioOut, true); From 1523d55b6cc6d0bcc1e7ee2f645fb0dd6b89bf5f Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 2 Feb 2016 21:26:24 -0500 Subject: [PATCH 06/10] SSB FIR kaiser -> Simple IIR Lowpass --- src/modules/modem/analog/ModemLSB.cpp | 22 +++++----------------- src/modules/modem/analog/ModemLSB.h | 3 ++- src/modules/modem/analog/ModemUSB.cpp | 13 +------------ src/modules/modem/analog/ModemUSB.h | 2 +- 4 files changed, 9 insertions(+), 31 deletions(-) diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp index beaf9cd..5d89a15 100644 --- a/src/modules/modem/analog/ModemLSB.cpp +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -3,20 +3,9 @@ ModemLSB::ModemLSB() : ModemAnalog() { // half band filter used for side-band elimination demodAM_LSB = ampmodem_create(0.25, 0.25, LIQUID_AMPMODEM_LSB, 1); - // options - float fc = 0.25f; // filter cutoff frequency - float ft = 0.05f; // filter transition - float As = 90.0f; // stop-band attenuation [dB] - float mu = 0.5f; // fractional timing offset - - // estimate required filter length and generate filter - unsigned int h_len = estimate_req_filter_len(ft,As); - float *h = (float *) malloc(h_len * sizeof(float)); - liquid_firdes_kaiser(h_len,fc,As,mu,h); - ssbFilt = firfilt_crcf_create(h,h_len); + ssbFilt = iirfilt_crcf_create_lowpass(6, 0.25); ssbShift = nco_crcf_create(LIQUID_NCO); nco_crcf_set_frequency(ssbShift, (2.0 * M_PI) * 0.25); - free(h); } Modem *ModemLSB::factory() { @@ -28,7 +17,7 @@ std::string ModemLSB::getName() { } ModemLSB::~ModemLSB() { - firfilt_crcf_destroy(ssbFilt); + iirfilt_crcf_destroy(ssbFilt); nco_crcf_destroy(ssbShift); ampmodem_destroy(demodAM_LSB); } @@ -57,13 +46,12 @@ void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a return; } - liquid_float_complex x; + liquid_float_complex x, y; for (int i = 0; i < bufSize; i++) { // Reject upper band nco_crcf_step(ssbShift); nco_crcf_mix_up(ssbShift, input->data[i], &x); - firfilt_crcf_push(ssbFilt, x); - firfilt_crcf_execute(ssbFilt, &x); - ampmodem_demodulate(demodAM_LSB, x, &demodOutputData[i]); + iirfilt_crcf_execute(ssbFilt, x, &y); + ampmodem_demodulate(demodAM_LSB, y, &demodOutputData[i]); } buildAudioOutput(akit, audioOut, true); diff --git a/src/modules/modem/analog/ModemLSB.h b/src/modules/modem/analog/ModemLSB.h index 875921d..96470d4 100644 --- a/src/modules/modem/analog/ModemLSB.h +++ b/src/modules/modem/analog/ModemLSB.h @@ -16,7 +16,8 @@ public: void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: - firfilt_crcf ssbFilt; + iirfilt_crcf ssbFilt; +// firfilt_crcf ssbFilt; nco_crcf ssbShift; ampmodem demodAM_LSB; }; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp index 3ae5685..d77a068 100644 --- a/src/modules/modem/analog/ModemUSB.cpp +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -3,20 +3,9 @@ ModemUSB::ModemUSB() : ModemAnalog() { // half band filter used for side-band elimination demodAM_USB = ampmodem_create(0.25, -0.25, LIQUID_AMPMODEM_USB, 1); - // options - float fc = 0.25f; // filter cutoff frequency - float ft = 0.05f; // filter transition - float As = 90.0f; // stop-band attenuation [dB] - float mu = 0.5f; // fractional timing offset - - // estimate required filter length and generate filter - unsigned int h_len = estimate_req_filter_len(ft,As); - float *h = (float *) malloc(h_len * sizeof(float)); - liquid_firdes_kaiser(h_len,fc,As,mu,h); - ssbFilt = firfilt_crcf_create(h,h_len); + ssbFilt = iirfilt_crcf_create_lowpass(6, 0.25); ssbShift = nco_crcf_create(LIQUID_NCO); nco_crcf_set_frequency(ssbShift, (2.0 * M_PI) * 0.25); - free(h); } Modem *ModemUSB::factory() { diff --git a/src/modules/modem/analog/ModemUSB.h b/src/modules/modem/analog/ModemUSB.h index 259af62..72e6c27 100644 --- a/src/modules/modem/analog/ModemUSB.h +++ b/src/modules/modem/analog/ModemUSB.h @@ -16,7 +16,7 @@ public: void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut); private: - firfilt_crcf ssbFilt; + iirfilt_crcf ssbFilt; nco_crcf ssbShift; ampmodem demodAM_USB; }; \ No newline at end of file From c6c62d73341a35d7af4a5df2b9915a580727e97b Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 2 Feb 2016 21:29:01 -0500 Subject: [PATCH 07/10] Note: hit save before committing :) --- src/modules/modem/analog/ModemUSB.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp index d77a068..a59f0d8 100644 --- a/src/modules/modem/analog/ModemUSB.cpp +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -17,7 +17,7 @@ std::string ModemUSB::getName() { } ModemUSB::~ModemUSB() { - firfilt_crcf_destroy(ssbFilt); + iirfilt_crcf_destroy(ssbFilt); nco_crcf_destroy(ssbShift); ampmodem_destroy(demodAM_USB); } @@ -46,13 +46,12 @@ void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a return; } - liquid_float_complex x; + liquid_float_complex x,y; for (int i = 0; i < bufSize; i++) { // Reject lower band nco_crcf_step(ssbShift); nco_crcf_mix_down(ssbShift, input->data[i], &x); - firfilt_crcf_push(ssbFilt, x); - firfilt_crcf_execute(ssbFilt, &x); - ampmodem_demodulate(demodAM_USB, x, &demodOutputData[i]); + iirfilt_crcf_execute(ssbFilt, x, &y); + ampmodem_demodulate(demodAM_USB, y, &demodOutputData[i]); } buildAudioOutput(akit, audioOut, true); From a0ae752b18909341a8bf420b22ae6c0a83c9f89e Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 2 Feb 2016 23:12:01 -0500 Subject: [PATCH 08/10] Make sure soapy devices are un-made before re-enumeration --- src/sdr/SDREnumerator.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sdr/SDREnumerator.cpp b/src/sdr/SDREnumerator.cpp index 0001211..6f1b2b0 100644 --- a/src/sdr/SDREnumerator.cpp +++ b/src/sdr/SDREnumerator.cpp @@ -390,6 +390,12 @@ void SDREnumerator::reset() { soapy_initialized = false; factories.erase(factories.begin(), factories.end()); modules.erase(modules.begin(), modules.end()); + for (std::map< std::string, std::vector >::iterator di = devs.begin(); di != devs.end(); di++) { + for (std::vector::iterator i = di->second.begin(); i != di->second.end(); i++) { + (*i)->setSoapyDevice(nullptr); + } + + } devs.erase(devs.begin(), devs.end()); } From 7f1c0a700d0620861a457632b701a9aa9a3f2698 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 3 Feb 2016 00:05:26 -0500 Subject: [PATCH 09/10] Fix device dialog runtime bool/option arg updates --- src/forms/SDRDevices/SDRDevices.cpp | 14 ++++++++++++++ src/forms/SDRDevices/SDRDevices.h | 1 + 2 files changed, 15 insertions(+) diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index 2309e71..c683337 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -113,6 +113,7 @@ 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()) ); + runtimeArgs.erase(runtimeArgs.begin(), runtimeArgs.end()); runtimeProps.erase(runtimeProps.begin(), runtimeProps.end()); streamProps.erase(streamProps.begin(), streamProps.end()); @@ -123,6 +124,7 @@ void SDRDevicesDialog::refreshDeviceProperties() { SoapySDR::ArgInfo arg = (*args_i); arg.value = soapyDev->readSetting(arg.key); runtimeProps[arg.key] = addArgInfoProperty(m_propertyGrid, arg); + runtimeArgs[arg.key] = arg; } } @@ -160,6 +162,7 @@ void SDRDevicesDialog::refreshDeviceProperties() { } else if (selDev && !selDev->isAvailable() && selDev->isManual()) { m_propertyGrid->Clear(); devSettings.erase(devSettings.begin(),devSettings.end()); + runtimeArgs.erase(runtimeArgs.begin(), runtimeArgs.end()); runtimeProps.erase(runtimeProps.begin(), runtimeProps.end()); streamProps.erase(streamProps.begin(), streamProps.end()); removeId = devTree->GetSelection(); @@ -187,6 +190,7 @@ void SDRDevicesDialog::OnAddRemote( wxMouseEvent& /* event */) { SDREnumerator::removeManual(selDev->getDriver(),selDev->getManualParams()); m_propertyGrid->Clear(); devSettings.erase(devSettings.begin(),devSettings.end()); + runtimeArgs.erase(runtimeArgs.begin(), runtimeArgs.end()); runtimeProps.erase(runtimeProps.begin(), runtimeProps.end()); streamProps.erase(streamProps.begin(), streamProps.end()); dev = nullptr; @@ -409,6 +413,15 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { if (rtp->second == prop) { SoapySDR::Device *soapyDev = dev->getSoapyDevice(); std::string settingValue = prop->GetValueAsString().ToStdString(); + SoapySDR::ArgInfo arg = runtimeArgs[rtp->first]; + if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size()) { + settingValue = arg.options[prop->GetChoiceSelection()]; + } else if (arg.type == SoapySDR::ArgInfo::BOOL) { + settingValue = (prop->GetValueAsString()=="True")?"true":"false"; + } else { + settingValue = prop->GetValueAsString(); + } + soapyDev->writeSetting(rtp->first, settingValue); if (dev->isActive()) { wxGetApp().getSDRThread()->writeSetting(rtp->first, settingValue); @@ -434,6 +447,7 @@ void SDRDevicesDialog::doRefreshDevices() { devTree->DeleteAllItems(); devTree->Disable(); m_propertyGrid->Clear(); + runtimeArgs.erase(runtimeArgs.begin(), runtimeArgs.end()); runtimeProps.erase(runtimeProps.begin(), runtimeProps.end()); streamProps.erase(streamProps.begin(), streamProps.end()); devSettings.erase(devSettings.begin(), devSettings.end()); diff --git a/src/forms/SDRDevices/SDRDevices.h b/src/forms/SDRDevices/SDRDevices.h index d98fa62..ad8f71d 100644 --- a/src/forms/SDRDevices/SDRDevices.h +++ b/src/forms/SDRDevices/SDRDevices.h @@ -37,6 +37,7 @@ private: std::map::iterator devItems_i; SDRDeviceInfo *dev; std::map runtimeProps; + std::map runtimeArgs; std::map streamProps; std::map devSettings; wxTreeItemId selId; From 52fefab9807e2eaf16381c4272951cce4d18a679 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 3 Feb 2016 21:24:37 -0500 Subject: [PATCH 10/10] Fix SSB drift with re-write of SSB demod w/o ampmodem --- src/modules/modem/analog/ModemLSB.cpp | 11 ++++++++--- src/modules/modem/analog/ModemLSB.h | 5 +++-- src/modules/modem/analog/ModemUSB.cpp | 13 +++++++++---- src/modules/modem/analog/ModemUSB.h | 1 + 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp index 5d89a15..0b98ccc 100644 --- a/src/modules/modem/analog/ModemLSB.cpp +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -2,10 +2,11 @@ ModemLSB::ModemLSB() : ModemAnalog() { // half band filter used for side-band elimination - demodAM_LSB = ampmodem_create(0.25, 0.25, LIQUID_AMPMODEM_LSB, 1); + // demodAM_LSB = ampmodem_create(0.25, 0.25, LIQUID_AMPMODEM_LSB, 1); ssbFilt = iirfilt_crcf_create_lowpass(6, 0.25); ssbShift = nco_crcf_create(LIQUID_NCO); nco_crcf_set_frequency(ssbShift, (2.0 * M_PI) * 0.25); + c2rFilt = firhilbf_create(5, 90.0); } Modem *ModemLSB::factory() { @@ -19,7 +20,8 @@ std::string ModemLSB::getName() { ModemLSB::~ModemLSB() { iirfilt_crcf_destroy(ssbFilt); nco_crcf_destroy(ssbShift); - ampmodem_destroy(demodAM_LSB); + firhilbf_destroy(c2rFilt); + // ampmodem_destroy(demodAM_LSB); } int ModemLSB::checkSampleRate(long long sampleRate, int /* audioSampleRate */) { @@ -51,7 +53,10 @@ void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a nco_crcf_step(ssbShift); nco_crcf_mix_up(ssbShift, input->data[i], &x); iirfilt_crcf_execute(ssbFilt, x, &y); - ampmodem_demodulate(demodAM_LSB, y, &demodOutputData[i]); + nco_crcf_mix_down(ssbShift, y, &x); + // Liquid-DSP AMPModem SSB drifts with strong signals near baseband (like a carrier?) + // ampmodem_demodulate(demodAM_LSB, y, &demodOutputData[i]); + firhilbf_c2r_execute(c2rFilt, x, &demodOutputData[i]); } buildAudioOutput(akit, audioOut, true); diff --git a/src/modules/modem/analog/ModemLSB.h b/src/modules/modem/analog/ModemLSB.h index 96470d4..016c574 100644 --- a/src/modules/modem/analog/ModemLSB.h +++ b/src/modules/modem/analog/ModemLSB.h @@ -17,7 +17,8 @@ public: private: iirfilt_crcf ssbFilt; -// firfilt_crcf ssbFilt; + firhilbf c2rFilt; nco_crcf ssbShift; - ampmodem demodAM_LSB; + // firfilt_crcf ssbFilt; + // ampmodem demodAM_LSB; }; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp index a59f0d8..e2b3d3c 100644 --- a/src/modules/modem/analog/ModemUSB.cpp +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -2,10 +2,11 @@ ModemUSB::ModemUSB() : ModemAnalog() { // half band filter used for side-band elimination - demodAM_USB = ampmodem_create(0.25, -0.25, LIQUID_AMPMODEM_USB, 1); + // demodAM_USB = ampmodem_create(0.25, -0.25, LIQUID_AMPMODEM_USB, 1); ssbFilt = iirfilt_crcf_create_lowpass(6, 0.25); ssbShift = nco_crcf_create(LIQUID_NCO); nco_crcf_set_frequency(ssbShift, (2.0 * M_PI) * 0.25); + c2rFilt = firhilbf_create(5, 90.0); } Modem *ModemUSB::factory() { @@ -19,7 +20,8 @@ std::string ModemUSB::getName() { ModemUSB::~ModemUSB() { iirfilt_crcf_destroy(ssbFilt); nco_crcf_destroy(ssbShift); - ampmodem_destroy(demodAM_USB); + firhilbf_destroy(c2rFilt); + // ampmodem_destroy(demodAM_USB); } int ModemUSB::checkSampleRate(long long sampleRate, int /* audioSampleRate */) { @@ -46,12 +48,15 @@ void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a return; } - liquid_float_complex x,y; + liquid_float_complex x, y; for (int i = 0; i < bufSize; i++) { // Reject lower band nco_crcf_step(ssbShift); nco_crcf_mix_down(ssbShift, input->data[i], &x); iirfilt_crcf_execute(ssbFilt, x, &y); - ampmodem_demodulate(demodAM_USB, y, &demodOutputData[i]); + nco_crcf_mix_up(ssbShift, y, &x); + // Liquid-DSP AMPModem SSB drifts with strong signals near baseband (like a carrier?) + // ampmodem_demodulate(demodAM_USB, y, &demodOutputData[i]); + firhilbf_c2r_execute(c2rFilt, x, &demodOutputData[i]); } buildAudioOutput(akit, audioOut, true); diff --git a/src/modules/modem/analog/ModemUSB.h b/src/modules/modem/analog/ModemUSB.h index 72e6c27..e6b6fdc 100644 --- a/src/modules/modem/analog/ModemUSB.h +++ b/src/modules/modem/analog/ModemUSB.h @@ -17,6 +17,7 @@ public: private: iirfilt_crcf ssbFilt; + firhilbf c2rFilt; nco_crcf ssbShift; ampmodem demodAM_USB; }; \ No newline at end of file