mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-26 13:48:38 -05:00
Merge pull request #273 from cjcliffe/soapy_refresh
SoapySDR settings refresh support + SSB Optimize/Drift Fix
This commit is contained in:
commit
c489142c12
@ -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,10 +566,11 @@ void AppFrame::updateDeviceParams() {
|
||||
SoapySDR::ArgInfoList::const_iterator args_i;
|
||||
|
||||
int i = 0;
|
||||
settingArgs = devInfo->getSettingsArgInfo();
|
||||
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");
|
||||
@ -610,7 +611,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 +638,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 +696,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 +838,14 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
||||
break;
|
||||
}
|
||||
|
||||
SDRDeviceChannel *chan = dev->getRxChannel();
|
||||
std::vector<long> 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 +1378,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);
|
||||
}
|
||||
sample_rate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, sample_rate);
|
||||
wxGetApp().setSampleRate(sample_rate);
|
||||
deviceChanged.store(true);
|
||||
} else {
|
||||
|
@ -526,33 +526,22 @@ 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);
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
sampleRate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, sampleRate);
|
||||
}
|
||||
|
||||
if (frequency < sampleRate/2) {
|
||||
|
@ -95,8 +95,7 @@ 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;
|
||||
@ -104,7 +103,8 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) {
|
||||
DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getName());
|
||||
m_propertyGrid->Clear();
|
||||
|
||||
SoapySDR::ArgInfoList args = dev->getSettingsArgInfo();
|
||||
SoapySDR::Device *soapyDev = dev->getSoapyDevice();
|
||||
SoapySDR::ArgInfoList args = soapyDev->getSettingInfo();
|
||||
SoapySDR::ArgInfoList::const_iterator args_i;
|
||||
|
||||
m_propertyGrid->Append(new wxPropertyCategory("General Settings"));
|
||||
@ -113,20 +113,23 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) {
|
||||
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());
|
||||
runtimeArgs.erase(runtimeArgs.begin(), runtimeArgs.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);
|
||||
runtimeArgs[arg.key] = arg;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
@ -143,7 +146,7 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) {
|
||||
|
||||
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 +162,9 @@ 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());
|
||||
runtimeArgs.erase(runtimeArgs.begin(), runtimeArgs.end());
|
||||
runtimeProps.erase(runtimeProps.begin(), runtimeProps.end());
|
||||
streamProps.erase(streamProps.begin(), streamProps.end());
|
||||
removeId = devTree->GetSelection();
|
||||
dev = nullptr;
|
||||
selId = nullptr;
|
||||
@ -170,6 +175,10 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) {
|
||||
m_addRemoteButton->SetLabel("Add");
|
||||
removeId = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) {
|
||||
refreshDeviceProperties();
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@ -181,7 +190,9 @@ 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());
|
||||
runtimeArgs.erase(runtimeArgs.begin(), runtimeArgs.end());
|
||||
runtimeProps.erase(runtimeProps.begin(), runtimeProps.end());
|
||||
streamProps.erase(streamProps.begin(), streamProps.end());
|
||||
dev = nullptr;
|
||||
selId = nullptr;
|
||||
editId = nullptr;
|
||||
@ -233,18 +244,17 @@ 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->getSettingsArgInfo();
|
||||
SoapySDR::ArgInfoList args = dev->getSoapyDevice()->getSettingInfo();
|
||||
|
||||
SoapySDR::Kwargs settingArgs;
|
||||
SoapySDR::Kwargs streamArgs;
|
||||
|
||||
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,17 +263,15 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) {
|
||||
} else {
|
||||
settingArgs[arg.key] = prop->GetValueAsString();
|
||||
}
|
||||
|
||||
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++) {
|
||||
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 +280,6 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) {
|
||||
} else {
|
||||
streamArgs[arg.key] = prop->GetValueAsString();
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -287,6 +293,7 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& /* event */) {
|
||||
wxGetApp().setDevice(dev);
|
||||
Close();
|
||||
}
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void SDRDevicesDialog::OnTreeDoubleClick( wxMouseEvent& event ) {
|
||||
@ -381,10 +388,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 +400,36 @@ 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<std::string, wxPGProperty *>::iterator rtp = runtimeProps.begin(); rtp != runtimeProps.end(); rtp++) {
|
||||
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);
|
||||
}
|
||||
refreshDeviceProperties();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,20 +439,22 @@ void SDRDevicesDialog::OnPropGridFocus( wxFocusEvent& /* event */) {
|
||||
|
||||
|
||||
void SDRDevicesDialog::doRefreshDevices() {
|
||||
selId = nullptr;
|
||||
editId = nullptr;
|
||||
removeId = nullptr;
|
||||
dev = nullptr;
|
||||
wxGetApp().stopDevice();
|
||||
devTree->DeleteAllItems();
|
||||
devTree->Disable();
|
||||
m_propertyGrid->Clear();
|
||||
props.erase(props.begin(),props.end());
|
||||
runtimeArgs.erase(runtimeArgs.begin(), runtimeArgs.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();
|
||||
m_useSelectedButton->Disable();
|
||||
wxGetApp().reEnumerateDevices();
|
||||
selId = nullptr;
|
||||
editId = nullptr;
|
||||
removeId = nullptr;
|
||||
dev = nullptr;
|
||||
refresh = true;
|
||||
m_addRemoteButton->SetLabel("Add");
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ public:
|
||||
void OnPropGridFocus( wxFocusEvent& event );
|
||||
|
||||
private:
|
||||
void refreshDeviceProperties();
|
||||
void doRefreshDevices();
|
||||
|
||||
SDRDeviceInfo *getSelectedDevice(wxTreeItemId selId);
|
||||
@ -35,7 +36,9 @@ private:
|
||||
std::map<wxTreeItemId, SDRDeviceInfo *> devItems;
|
||||
std::map<wxTreeItemId, SDRDeviceInfo *>::iterator devItems_i;
|
||||
SDRDeviceInfo *dev;
|
||||
std::vector<wxPGProperty *> props;
|
||||
std::map<std::string, wxPGProperty *> runtimeProps;
|
||||
std::map<std::string, SoapySDR::ArgInfo> runtimeArgs;
|
||||
std::map<std::string, wxPGProperty *> streamProps;
|
||||
std::map<std::string, wxPGProperty *> devSettings;
|
||||
wxTreeItemId selId;
|
||||
wxTreeItemId editId;
|
||||
|
@ -2,21 +2,11 @@
|
||||
|
||||
ModemLSB::ModemLSB() : ModemAnalog() {
|
||||
// half band filter used for side-band elimination
|
||||
demodAM_LSB = ampmodem_create(0.5, 0.0, 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
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
free(h);
|
||||
c2rFilt = firhilbf_create(5, 90.0);
|
||||
}
|
||||
|
||||
Modem *ModemLSB::factory() {
|
||||
@ -28,9 +18,10 @@ std::string ModemLSB::getName() {
|
||||
}
|
||||
|
||||
ModemLSB::~ModemLSB() {
|
||||
firfilt_crcf_destroy(ssbFilt);
|
||||
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 */) {
|
||||
@ -61,10 +52,11 @@ void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a
|
||||
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]);
|
||||
iirfilt_crcf_execute(ssbFilt, x, &y);
|
||||
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);
|
||||
|
@ -16,7 +16,9 @@ public:
|
||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||
|
||||
private:
|
||||
firfilt_crcf ssbFilt;
|
||||
iirfilt_crcf ssbFilt;
|
||||
firhilbf c2rFilt;
|
||||
nco_crcf ssbShift;
|
||||
ampmodem demodAM_LSB;
|
||||
// firfilt_crcf ssbFilt;
|
||||
// ampmodem demodAM_LSB;
|
||||
};
|
@ -2,21 +2,11 @@
|
||||
|
||||
ModemUSB::ModemUSB() : ModemAnalog() {
|
||||
// half band filter used for side-band elimination
|
||||
demodAM_USB = ampmodem_create(0.5, 0.0, 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
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
free(h);
|
||||
c2rFilt = firhilbf_create(5, 90.0);
|
||||
}
|
||||
|
||||
Modem *ModemUSB::factory() {
|
||||
@ -28,9 +18,10 @@ std::string ModemUSB::getName() {
|
||||
}
|
||||
|
||||
ModemUSB::~ModemUSB() {
|
||||
firfilt_crcf_destroy(ssbFilt);
|
||||
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 */) {
|
||||
@ -61,10 +52,11 @@ void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *a
|
||||
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]);
|
||||
iirfilt_crcf_execute(ssbFilt, x, &y);
|
||||
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);
|
||||
|
@ -16,7 +16,8 @@ public:
|
||||
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||
|
||||
private:
|
||||
firfilt_crcf ssbFilt;
|
||||
iirfilt_crcf ssbFilt;
|
||||
firhilbf c2rFilt;
|
||||
nco_crcf ssbShift;
|
||||
ampmodem demodAM_USB;
|
||||
};
|
@ -1,167 +1,14 @@
|
||||
#include "SDRDeviceInfo.h"
|
||||
#include <cstdlib>
|
||||
|
||||
SDRDeviceRange::SDRDeviceRange() {
|
||||
low = 0;
|
||||
high = 0;
|
||||
}
|
||||
|
||||
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() {
|
||||
SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false), remote(false), manual(false), active(false), soapyDevice(nullptr) {
|
||||
|
||||
}
|
||||
|
||||
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<SDRDeviceRange> &SDRDeviceChannel::getGains() {
|
||||
return gainInfo;
|
||||
}
|
||||
|
||||
void SDRDeviceChannel::addGain(std::string name, SoapySDR::Range range) {
|
||||
gainInfo.push_back(SDRDeviceRange(name,range.minimum(),range.maximum()));
|
||||
}
|
||||
|
||||
std::vector<long> &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<long>::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<long long> &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<std::string> SDRDeviceChannel::getStreamArgNames() {
|
||||
std::vector<std::string> 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() {
|
||||
@ -190,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;
|
||||
}
|
||||
@ -294,48 +149,66 @@ SoapySDR::Kwargs SDRDeviceInfo::getStreamArgs() {
|
||||
return streamArgs;
|
||||
}
|
||||
|
||||
void SDRDeviceInfo::setSettingsInfo(SoapySDR::ArgInfoList settingsArgs) {
|
||||
settingInfo = settingsArgs;
|
||||
}
|
||||
|
||||
SoapySDR::ArgInfoList SDRDeviceInfo::getSettingsArgInfo() {
|
||||
return settingInfo;
|
||||
}
|
||||
|
||||
std::vector<std::string> SDRDeviceInfo::getSettingNames() {
|
||||
std::vector<std::string> 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<SDRDeviceChannel *> &SDRDeviceInfo::getChannels() {
|
||||
return channels;
|
||||
bool SDRDeviceInfo::hasCORR(int direction, size_t channel) {
|
||||
SoapySDR::Device *dev = getSoapyDevice();
|
||||
|
||||
std::vector<std::string> 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<SDRDeviceChannel *>::iterator channel_i;
|
||||
for (channel_i = channels.begin(); channel_i != channels.end(); channel_i++) {
|
||||
if ((*channel_i)->isRx()) {
|
||||
return (*channel_i);
|
||||
std::vector<long> SDRDeviceInfo::getSampleRates(int direction, size_t channel) {
|
||||
SoapySDR::Device *dev = getSoapyDevice();
|
||||
|
||||
std::vector<long> result;
|
||||
std::vector<double> sampleRates = dev->listSampleRates(direction, channel);
|
||||
for (std::vector<double>::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<long> sampleRates = getSampleRates(direction, channel);
|
||||
long returnRate = sampleRates[0];
|
||||
long sDelta = (long)sampleRate_in-sampleRates[0];
|
||||
long minDelta = std::abs(sDelta);
|
||||
for (std::vector<long>::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<SDRDeviceChannel *>::iterator channel_i;
|
||||
for (channel_i = channels.begin(); channel_i != channels.end(); channel_i++) {
|
||||
if ((*channel_i)->isTx()) {
|
||||
return (*channel_i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
SDRRangeMap SDRDeviceInfo::getGains(int direction, size_t channel) {
|
||||
SoapySDR::Device *dev = getSoapyDevice();
|
||||
std::vector<std::string> gainNames = dev->listGains(direction, channel);
|
||||
std::map<std::string, SoapySDR::Range> gainMap;
|
||||
|
||||
for (std::vector<std::string>::iterator gname = gainNames.begin(); gname!= gainNames.end(); gname++) {
|
||||
gainMap[(*gname)] = dev->getGainRange(direction, channel, (*gname));
|
||||
}
|
||||
|
||||
return gainMap;
|
||||
}
|
||||
|
@ -4,84 +4,19 @@
|
||||
#include <vector>
|
||||
|
||||
#include <SoapySDR/Types.hpp>
|
||||
#include <SoapySDR/Device.hpp>
|
||||
|
||||
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<SDRDeviceRange> &getGains();
|
||||
|
||||
SDRDeviceRange &getGain();
|
||||
SDRDeviceRange &getLNAGain();
|
||||
SDRDeviceRange &getFreqRange();
|
||||
SDRDeviceRange &getRFRange();
|
||||
|
||||
std::vector<long> &getSampleRates();
|
||||
long getSampleRateNear(long sampleRate_in);
|
||||
std::vector<long long> &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<std::string> getStreamArgNames();
|
||||
|
||||
private:
|
||||
int channel;
|
||||
bool fullDuplex, tx, rx, hardwareDC, hasCorr;
|
||||
SDRDeviceRange rangeGain, rangeLNA, rangeFull, rangeRF;
|
||||
std::vector<long> sampleRates;
|
||||
std::vector<long long> filterBandwidths;
|
||||
SoapySDR::ArgInfoList streamArgInfo;
|
||||
std::vector<SDRDeviceRange> gainInfo;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, SoapySDR::Range> SDRRangeMap;
|
||||
|
||||
class SDRDeviceInfo {
|
||||
public:
|
||||
SDRDeviceInfo();
|
||||
~SDRDeviceInfo();
|
||||
|
||||
std::string getDeviceId();
|
||||
|
||||
@ -91,6 +26,9 @@ 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);
|
||||
|
||||
@ -124,29 +62,35 @@ public:
|
||||
void setManualParams(std::string manualParams);
|
||||
std::string getManualParams();
|
||||
|
||||
void addChannel(SDRDeviceChannel *chan);
|
||||
std::vector<SDRDeviceChannel *> &getChannels();
|
||||
SDRDeviceChannel * getRxChannel();
|
||||
SDRDeviceChannel * getTxChannel();
|
||||
|
||||
void setDeviceArgs(SoapySDR::Kwargs deviceArgs);
|
||||
SoapySDR::Kwargs getDeviceArgs();
|
||||
|
||||
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<std::string> getSettingNames();
|
||||
// std::vector<std::string> getSettingNames();
|
||||
|
||||
void setSoapyDevice(SoapySDR::Device *dev);
|
||||
SoapySDR::Device *getSoapyDevice();
|
||||
|
||||
bool hasCORR(int direction, size_t channel);
|
||||
|
||||
std::vector<long> 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;
|
||||
std::string driver, hardware, manual_params;
|
||||
bool timestamps, available, remote, manual;
|
||||
std::atomic_bool active;
|
||||
|
||||
SoapySDR::Kwargs deviceArgs, streamArgs;
|
||||
SoapySDR::ArgInfoList settingInfo;
|
||||
std::vector<SDRDeviceChannel *> channels;
|
||||
SoapySDR::Device *soapyDevice;
|
||||
};
|
||||
|
@ -273,67 +273,8 @@ std::vector<SDRDeviceInfo *> *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<std::string> 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<double> rates = device->listSampleRates(SOAPY_SDR_RX, i);
|
||||
for (std::vector<double>::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<std::string> gainNames = device->listGains(SOAPY_SDR_RX, i);
|
||||
|
||||
for (std::vector<std::string>::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;
|
||||
@ -449,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<SDRDeviceInfo *> >::iterator di = devs.begin(); di != devs.end(); di++) {
|
||||
for (std::vector<SDRDeviceInfo *>::iterator i = di->second.begin(); i != di->second.end(); i++) {
|
||||
(*i)->setSoapyDevice(nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
devs.erase(devs.begin(), devs.end());
|
||||
}
|
||||
|
||||
|
@ -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<size_t>(), 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,25 +138,16 @@ void SDRThread::init() {
|
||||
}
|
||||
setting_value_changed.store(false);
|
||||
|
||||
SoapySDR::ArgInfoList devSettings = deviceInfo.load()->getSettingsArgInfo();
|
||||
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."));
|
||||
}
|
||||
|
||||
void SDRThread::deinit() {
|
||||
device->deactivateStream(stream);
|
||||
device->closeStream(stream);
|
||||
SoapySDR::Device::unmake(device);
|
||||
free(buffs[0]);
|
||||
}
|
||||
|
||||
@ -247,16 +237,18 @@ void SDRThread::updateGains() {
|
||||
gainValues.erase(gainValues.begin(),gainValues.end());
|
||||
gainChanged.erase(gainChanged.begin(),gainChanged.end());
|
||||
|
||||
std::vector<SDRDeviceRange> gains = devInfo->getRxChannel()->getGains();
|
||||
for (std::vector<SDRDeviceRange>::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);
|
||||
}
|
||||
|
||||
void SDRThread::updateSettings() {
|
||||
bool doUpdate = false;
|
||||
|
||||
if (offset_changed.load()) {
|
||||
if (!freq_changed.load()) {
|
||||
frequency.store(frequency.load());
|
||||
@ -281,6 +273,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()) {
|
||||
@ -304,22 +297,19 @@ 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();
|
||||
}
|
||||
doUpdate = true;
|
||||
}
|
||||
|
||||
if (gain_value_changed.load() && !agc_mode.load()) {
|
||||
SDRDeviceInfo *devInfo = deviceInfo.load();
|
||||
|
||||
gain_busy.lock();
|
||||
for (std::map<std::string,bool>::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;
|
||||
}
|
||||
}
|
||||
@ -341,6 +331,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."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,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;
|
||||
|
@ -184,8 +184,8 @@ void GainCanvas::updateGainUI() {
|
||||
|
||||
SDRDeviceInfo *devInfo = wxGetApp().getDevice();
|
||||
|
||||
std::vector<SDRDeviceRange> &gains = devInfo->getRxChannel()->getGains();
|
||||
std::vector<SDRDeviceRange>::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));
|
||||
|
Loading…
Reference in New Issue
Block a user