From fadffc1afc92d7f3735ee686ff1cd12e9e85f388 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 2 Jul 2024 06:14:22 +0200 Subject: [PATCH] WDSP receiver: implemmted noise blanker and CW peaking filter --- plugins/channelrx/wdsprx/CMakeLists.txt | 6 + plugins/channelrx/wdsprx/wdsprxamdialog.cpp | 45 +++++ plugins/channelrx/wdsprx/wdsprxamdialog.h | 54 ++++++ plugins/channelrx/wdsprx/wdsprxamdialog.ui | 71 ++++++++ .../channelrx/wdsprx/wdsprxcwpeakdialog.cpp | 73 ++++++++ plugins/channelrx/wdsprx/wdsprxcwpeakdialog.h | 63 +++++++ .../channelrx/wdsprx/wdsprxcwpeakdialog.ui | 164 +++++++++++++++++ plugins/channelrx/wdsprx/wdsprxdnbdialog.cpp | 58 +----- plugins/channelrx/wdsprx/wdsprxdnbdialog.h | 25 +-- plugins/channelrx/wdsprx/wdsprxdnbdialog.ui | 131 +++----------- plugins/channelrx/wdsprx/wdsprxgui.cpp | 166 +++++++++++++++--- plugins/channelrx/wdsprx/wdsprxgui.h | 12 +- plugins/channelrx/wdsprx/wdsprxgui.ui | 60 ++++++- plugins/channelrx/wdsprx/wdsprxsettings.cpp | 58 ++++-- plugins/channelrx/wdsprx/wdsprxsettings.h | 60 ++++--- plugins/channelrx/wdsprx/wdsprxsink.cpp | 116 +++++++++--- wdsp/RXA.cpp | 3 +- wdsp/comm.hpp | 1 + wdsp/nbp.cpp | 4 +- wdsp/snb.cpp | 4 +- 20 files changed, 910 insertions(+), 264 deletions(-) create mode 100644 plugins/channelrx/wdsprx/wdsprxamdialog.cpp create mode 100644 plugins/channelrx/wdsprx/wdsprxamdialog.h create mode 100644 plugins/channelrx/wdsprx/wdsprxamdialog.ui create mode 100644 plugins/channelrx/wdsprx/wdsprxcwpeakdialog.cpp create mode 100644 plugins/channelrx/wdsprx/wdsprxcwpeakdialog.h create mode 100644 plugins/channelrx/wdsprx/wdsprxcwpeakdialog.ui diff --git a/plugins/channelrx/wdsprx/CMakeLists.txt b/plugins/channelrx/wdsprx/CMakeLists.txt index fba4e9d31..a411d3ddd 100644 --- a/plugins/channelrx/wdsprx/CMakeLists.txt +++ b/plugins/channelrx/wdsprx/CMakeLists.txt @@ -28,6 +28,10 @@ if(NOT SERVER_MODE) ${wdsprx_SOURCES} wdsprxagcdialog.cpp wdsprxagcdialog.ui + wdsprxamdialog.cpp + wdsprxamdialog.ui + wdsprxcwpeakdialog.cpp + wdsprxcwpeakdialog.ui wdsprxdnbdialog.cpp wdsprxdnbdialog.ui wdsprxdnrdialog.cpp @@ -39,6 +43,8 @@ if(NOT SERVER_MODE) ${wdsprx_HEADERS} wdsprxgui.h wdsprxagcdialog.h + wdsprxamdialog.h + wdsprxcwpeakdialog.h wdsprxdnbdialog.h wdsprxdnrdialog.h ) diff --git a/plugins/channelrx/wdsprx/wdsprxamdialog.cpp b/plugins/channelrx/wdsprx/wdsprxamdialog.cpp new file mode 100644 index 000000000..f03a86281 --- /dev/null +++ b/plugins/channelrx/wdsprx/wdsprxamdialog.cpp @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////////// + +#include "wdsprxamdialog.h" +#include "ui_wdsprxamdialog.h" + +WDSPRxAMDialog::WDSPRxAMDialog(QWidget* parent) : + QDialog(parent), + ui(new Ui::WDSPRxAMDialog) +{ + ui->setupUi(this); +} + +WDSPRxAMDialog::~WDSPRxAMDialog() +{ + delete ui; +} + +void WDSPRxAMDialog::setFadeLevel(bool fadeLevel) +{ + ui->fadeLevel->blockSignals(true); + ui->fadeLevel->setChecked(fadeLevel); + ui->fadeLevel->blockSignals(false); + m_fadeLevel = fadeLevel; +} + +void WDSPRxAMDialog::on_fadeLevel_clicked(bool checked) +{ + m_fadeLevel = checked; + emit valueChanged(ChangedFadeLevel); +} diff --git a/plugins/channelrx/wdsprx/wdsprxamdialog.h b/plugins/channelrx/wdsprx/wdsprxamdialog.h new file mode 100644 index 000000000..a74a4275a --- /dev/null +++ b/plugins/channelrx/wdsprx/wdsprxamdialog.h @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////////// +#ifndef INCLUDE_WDSPRXAMDIALOG_H +#define INCLUDE_WDSPRXAMDIALOG_H + +#include + +#include "export.h" +#include "wdsprxsettings.h" + + +namespace Ui { + class WDSPRxAMDialog; +} + +class SDRGUI_API WDSPRxAMDialog : public QDialog { + Q_OBJECT +public: + enum ValueChanged { + ChangedFadeLevel, + }; + + explicit WDSPRxAMDialog(QWidget* parent = nullptr); + ~WDSPRxAMDialog(); + + void setFadeLevel(bool fadeLevel); + bool getFadeLevel() const { return m_fadeLevel; } + +signals: + void valueChanged(int valueChanged); + +private: + Ui::WDSPRxAMDialog *ui; + bool m_fadeLevel; + +private slots: + void on_fadeLevel_clicked(bool checked); +}; + +#endif diff --git a/plugins/channelrx/wdsprx/wdsprxamdialog.ui b/plugins/channelrx/wdsprx/wdsprxamdialog.ui new file mode 100644 index 000000000..3d55809ac --- /dev/null +++ b/plugins/channelrx/wdsprx/wdsprxamdialog.ui @@ -0,0 +1,71 @@ + + + WDSPRxAMDialog + + + + 0 + 0 + 224 + 80 + + + + AM/SAM Options + + + + + + Fade Level + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + WDSPRxAMDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WDSPRxAMDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.cpp b/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.cpp new file mode 100644 index 000000000..4c6f1d361 --- /dev/null +++ b/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.cpp @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////////// + +#include "wdsprxcwpeakdialog.h" +#include "ui_wdsprxcwpeakdialog.h" + +WDSPRxCWPeakDialog::WDSPRxCWPeakDialog(QWidget* parent) : + QDialog(parent), + ui(new Ui::WDSPRxCWPeakDialog) +{ + ui->setupUi(this); +} + +WDSPRxCWPeakDialog::~WDSPRxCWPeakDialog() +{ + delete ui; +} + +void WDSPRxCWPeakDialog::setCWPeakFrequency(double cwPeakFrequency) +{ + ui->cwPeakFrequency->blockSignals(true); + ui->cwPeakFrequency->setValue(cwPeakFrequency); + ui->cwPeakFrequency->blockSignals(false); + m_cwPeakFrequency = cwPeakFrequency; +} + +void WDSPRxCWPeakDialog::setCWBandwidth(double cwBandwidth) +{ + ui->cwBandwidth->blockSignals(true); + ui->cwBandwidth->setValue(cwBandwidth); + ui->cwBandwidth->blockSignals(false); + m_cwBandwidth = cwBandwidth; +} + +void WDSPRxCWPeakDialog::setCWGain(double cwGain) +{ + ui->cwGain->blockSignals(true); + ui->cwGain->setValue(cwGain); + ui->cwGain->blockSignals(false); + m_cwGain = cwGain; +} + +void WDSPRxCWPeakDialog::on_cwPeakFrequency_valueChanged(double value) +{ + m_cwPeakFrequency = value; + emit valueChanged(ChangedCWPeakFrequency); +} + +void WDSPRxCWPeakDialog::on_cwBandwidth_valueChanged(double value) +{ + m_cwBandwidth = value; + emit valueChanged(ChangedCWBandwidth); +} + +void WDSPRxCWPeakDialog::on_cwGain_valueChanged(double value) +{ + m_cwGain = value; + emit valueChanged(ChangedCWGain); +} diff --git a/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.h b/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.h new file mode 100644 index 000000000..0c7aaefda --- /dev/null +++ b/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.h @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////////// +#ifndef INCLUDE_WDSPRXCWPEAKDIALOG_H +#define INCLUDE_WDSPRXCWPEAKDIALOG_H + +#include + +#include "export.h" +#include "wdsprxsettings.h" + +namespace Ui { + class WDSPRxCWPeakDialog; +} + +class SDRGUI_API WDSPRxCWPeakDialog : public QDialog { + Q_OBJECT +public: + enum ValueChanged { + ChangedCWPeakFrequency, + ChangedCWBandwidth, + ChangedCWGain + }; + + explicit WDSPRxCWPeakDialog(QWidget* parent = nullptr); + ~WDSPRxCWPeakDialog(); + + void setCWPeakFrequency(double cwPeakFrequency); + void setCWBandwidth(double cwBandwidth); + void setCWGain(double cwGain); + double getCWPeakFrequency() const { return m_cwPeakFrequency; } + double getCWBandwidth() const { return m_cwBandwidth; } + double getCWGain() const { return m_cwGain; } + +signals: + void valueChanged(int valueChanged); + +private: + Ui::WDSPRxCWPeakDialog *ui; + double m_cwPeakFrequency; + double m_cwBandwidth; + double m_cwGain; + +private slots: + void on_cwPeakFrequency_valueChanged(double value); + void on_cwBandwidth_valueChanged(double value); + void on_cwGain_valueChanged(double value); +}; + +#endif diff --git a/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.ui b/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.ui new file mode 100644 index 000000000..5c7777b74 --- /dev/null +++ b/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.ui @@ -0,0 +1,164 @@ + + + WDSPRxCWPeakDialog + + + + 0 + 0 + 268 + 158 + + + + CW Peak Filter + + + + + + + + Noise blanking slew time (ms) + + + 1 + + + 20.000000000000000 + + + 200.000000000000000 + + + 10.000000000000000 + + + QAbstractSpinBox::DefaultStepType + + + 100.000000000000000 + + + + + + + Noise blanking slew time (ms) + + + 1 + + + 300.000000000000000 + + + 1000.000000000000000 + + + 10.000000000000000 + + + QAbstractSpinBox::DefaultStepType + + + 600.000000000000000 + + + + + + + CW Peak Frequency (Hz) + + + + + + + Bandwidth (Hz) + + + + + + + Gain + + + + + + + Noise blanking slew time (ms) + + + 1 + + + 1.000000000000000 + + + 10.000000000000000 + + + 0.100000000000000 + + + QAbstractSpinBox::DefaultStepType + + + 2.000000000000000 + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + WDSPRxCWPeakDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WDSPRxCWPeakDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/channelrx/wdsprx/wdsprxdnbdialog.cpp b/plugins/channelrx/wdsprx/wdsprxdnbdialog.cpp index 13e347203..4b9946476 100644 --- a/plugins/channelrx/wdsprx/wdsprxdnbdialog.cpp +++ b/plugins/channelrx/wdsprx/wdsprxdnbdialog.cpp @@ -77,36 +77,12 @@ void WDSPRxDNBDialog::setNBThreshold(int threshold) m_nbThreshold = threshold; } -void WDSPRxDNBDialog::setNB2SlewTime(double time) +void WDSPRxDNBDialog::setNBAvgTime(double time) { - ui->nb2SlewTime->blockSignals(true); - ui->nb2SlewTime->setValue(time); - ui->nb2SlewTime->blockSignals(false); - m_nb2SlewTime = time; -} - -void WDSPRxDNBDialog::setNB2LeadTime(double time) -{ - ui->nb2LeadTime->blockSignals(true); - ui->nb2LeadTime->setValue(time); - ui->nb2LeadTime->blockSignals(false); - m_nb2LeadTime = time; -} - -void WDSPRxDNBDialog::setNB2LagTime(double time) -{ - ui->nb2LagTime->blockSignals(true); - ui->nb2LagTime->setValue(time); - ui->nb2LagTime->blockSignals(false); - m_nb2LagTime = time; -} - -void WDSPRxDNBDialog::setNB2Threshold(int threshold) -{ - ui->nb2Threshold->blockSignals(true); - ui->nb2Threshold->setValue(threshold); - ui->nb2Threshold->blockSignals(false); - m_nb2Threshold = threshold; + ui->nbAvgTime->blockSignals(true); + ui->nbAvgTime->setValue(time); + ui->nbAvgTime->blockSignals(false); + m_nbAvgTime = time; } void WDSPRxDNBDialog::on_nb_currentIndexChanged(int index) @@ -145,26 +121,8 @@ void WDSPRxDNBDialog::on_nbThreshold_valueChanged(int value) emit valueChanged(ChangedNBThreshold); } -void WDSPRxDNBDialog::on_nb2SlewTime_valueChanged(double value) +void WDSPRxDNBDialog::on_nbAvgTime_valueChanged(double value) { - m_nb2SlewTime = value; - emit valueChanged(ChangedNB2SlewTime); -} - -void WDSPRxDNBDialog::on_nb2LeadTime_valueChanged(double value) -{ - m_nb2LeadTime = value; - emit valueChanged(ChangedNB2LeadTime); -} - -void WDSPRxDNBDialog::on_nb2LagTime_valueChanged(double value) -{ - m_nb2LagTime = value; - emit valueChanged(ChangedNB2LagTime); -} - -void WDSPRxDNBDialog::on_nb2Threshold_valueChanged(int value) -{ - m_nb2Threshold = value; - emit valueChanged(ChangedNB2Threshold); + m_nbAvgTime = value; + emit valueChanged(ChangedNBAvgTime); } diff --git a/plugins/channelrx/wdsprx/wdsprxdnbdialog.h b/plugins/channelrx/wdsprx/wdsprxdnbdialog.h index db17851cf..9fbab0e95 100644 --- a/plugins/channelrx/wdsprx/wdsprxdnbdialog.h +++ b/plugins/channelrx/wdsprx/wdsprxdnbdialog.h @@ -36,10 +36,7 @@ public: ChangedNBLeadTime, ChangedNBLagTime, ChangedNBThreshold, - ChangedNB2SlewTime, - ChangedNB2LeadTime, - ChangedNB2LagTime, - ChangedNB2Threshold, + ChangedNBAvgTime, }; explicit WDSPRxDNBDialog(QWidget* parent = nullptr); @@ -51,10 +48,7 @@ public: void setNBLeadTime(double time); void setNBLagTime(double time); void setNBThreshold(int threshold); - void setNB2SlewTime(double time); - void setNB2LeadTime(double time); - void setNB2LagTime(double time); - void setNB2Threshold(int threshold); + void setNBAvgTime(double time); WDSPRxProfile::WDSPRxNBScheme getNBScheme() const { return m_nbScheme; } WDSPRxProfile::WDSPRxNB2Mode getNB2Mode() const { return m_nb2Mode; } @@ -62,10 +56,7 @@ public: double getNBLeadTime() const { return m_nbLeadTime; } double getNBLagTime() const { return m_nbLagTime; } int getNBThreshold() const { return m_nbThreshold; } - double getNB2SlewTime() const { return m_nb2SlewTime; } - double getNB2LeadTime() const { return m_nb2LeadTime; } - double getNB2LagTime() const { return m_nb2LagTime; } - int getNB2Threshold() const { return m_nb2Threshold; } + double getNBAvgTime() const { return m_nbAvgTime; } signals: void valueChanged(int valueChanged); @@ -78,10 +69,7 @@ private: double m_nbLeadTime; double m_nbLagTime; int m_nbThreshold; - double m_nb2SlewTime; - double m_nb2LeadTime; - double m_nb2LagTime; - int m_nb2Threshold; + double m_nbAvgTime; private slots: void on_nb_currentIndexChanged(int index); @@ -90,10 +78,7 @@ private slots: void on_nbLeadTime_valueChanged(double value); void on_nbLagTime_valueChanged(double value); void on_nbThreshold_valueChanged(int value); - void on_nb2SlewTime_valueChanged(double value); - void on_nb2LeadTime_valueChanged(double value); - void on_nb2LagTime_valueChanged(double value); - void on_nb2Threshold_valueChanged(int value); + void on_nbAvgTime_valueChanged(double value); }; #endif // INCLUDE_WDSPRXDNBDIALOG_H diff --git a/plugins/channelrx/wdsprx/wdsprxdnbdialog.ui b/plugins/channelrx/wdsprx/wdsprxdnbdialog.ui index 921f77cad..0634b9a74 100644 --- a/plugins/channelrx/wdsprx/wdsprxdnbdialog.ui +++ b/plugins/channelrx/wdsprx/wdsprxdnbdialog.ui @@ -6,8 +6,8 @@ 0 0 - 510 - 271 + 445 + 234 @@ -54,28 +54,6 @@ - - - - Noise blanking slew time (ms) - - - 4 - - - 1.000000000000000 - - - 0.000100000000000 - - - QAbstractSpinBox::DefaultStepType - - - 0.010000000000000 - - - @@ -118,14 +96,14 @@ - NB Lead time (ms) + Lead time (ms) - NB Slew time (ms) + Slew time (ms) @@ -138,7 +116,7 @@ 4 - 1.000000000000000 + 2.000000000000000 0.000100000000000 @@ -147,21 +125,21 @@ QAbstractSpinBox::DefaultStepType - 0.010000000000000 + 0.100000000000000 - - + + - NB2 Slew time (ms) + Lag time (ms) - NB Threshold + Threshold @@ -174,39 +152,20 @@ 4 - 1.000000000000000 + 2.000000000000000 0.000100000000000 - 0.010000000000000 - - - - - - - Noise blanking lead time (ms) - - - 4 - - - 1.000000000000000 - - - 0.000100000000000 - - - 0.010000000000000 + 0.100000000000000 - Noise blanking threshold + Noise blanking threshold multiplier 15 @@ -219,13 +178,6 @@ - - - - NB2 Lead time (ms) - - - @@ -235,69 +187,42 @@ 4 - 1.000000000000000 + 2.000000000000000 0.000100000000000 - 0.010000000000000 + 0.100000000000000 - - + + - NB Lag time (ms) + Avg time (ms) - - - - NB2 Lag time (ms) - - - - - + + - Noise blanking lag time (ms) + Noise blanking averaging time (ms) - 4 - - - 1.000000000000000 - - - 0.000100000000000 - - - 0.010000000000000 - - - - - - - NB2 Threshold - - - - - - - Noise blanking threshold + 1 - 15 + 10.000000000000000 - 500 + 100.000000000000000 + + + 1.000000000000000 - 30 + 50.000000000000000 diff --git a/plugins/channelrx/wdsprx/wdsprxgui.cpp b/plugins/channelrx/wdsprx/wdsprxgui.cpp index b8709d4b0..270753c9c 100644 --- a/plugins/channelrx/wdsprx/wdsprxgui.cpp +++ b/plugins/channelrx/wdsprx/wdsprxgui.cpp @@ -40,6 +40,8 @@ #include "wdsprxagcdialog.h" #include "wdsprxdnbdialog.h" #include "wdsprxdnrdialog.h" +#include "wdsprxamdialog.h" +#include "wdsprxcwpeakdialog.h" WDSPRxGUI* WDSPRxGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) { @@ -215,6 +217,20 @@ void WDSPRxGUI::on_dnr_toggled(bool checked) applySettings(); } +void WDSPRxGUI::on_dnb_toggled(bool checked) +{ + m_settings.m_dnb = checked; + m_settings.m_profiles[m_settings.m_profileIndex].m_dnb = m_settings.m_dnb; + applySettings(); +} + +void WDSPRxGUI::on_cwPeaking_toggled(bool checked) +{ + m_settings.m_cwPeaking = checked; + m_settings.m_profiles[m_settings.m_profileIndex].m_cwPeaking = m_settings.m_cwPeaking; + applySettings(); +} + void WDSPRxGUI::on_agcGain_valueChanged(int value) { QString s = QString::number(value, 'f', 0); @@ -270,6 +286,7 @@ void WDSPRxGUI::on_profileIndex_valueChanged(int value) ui->BW->setMinimum(-480); ui->lowCut->setMaximum(480); ui->lowCut->setMinimum(-480); + m_settings.m_demod = m_settings.m_profiles[m_settings.m_profileIndex].m_demod; // AGC setup m_settings.m_agc = m_settings.m_profiles[m_settings.m_profileIndex].m_agc; m_settings.m_agcGain = m_settings.m_profiles[m_settings.m_profileIndex].m_agcGain; @@ -281,6 +298,7 @@ void WDSPRxGUI::on_profileIndex_valueChanged(int value) m_settings.m_nbLeadTime = m_settings.m_profiles[m_settings.m_profileIndex].m_nbLeadTime; m_settings.m_nbLagTime = m_settings.m_profiles[m_settings.m_profileIndex].m_nbLagTime; m_settings.m_nbThreshold = m_settings.m_profiles[m_settings.m_profileIndex].m_nbThreshold; + m_settings.m_nbAvgTime = m_settings.m_profiles[m_settings.m_profileIndex].m_nbAvgTime; // Noise reduction m_settings.m_dnr = m_settings.m_profiles[m_settings.m_profileIndex].m_dnr; m_settings.m_snb = m_settings.m_profiles[m_settings.m_profileIndex].m_snb; @@ -290,10 +308,37 @@ void WDSPRxGUI::on_profileIndex_valueChanged(int value) m_settings.m_nr2NPE = m_settings.m_profiles[m_settings.m_profileIndex].m_nr2NPE; m_settings.m_nrPosition = m_settings.m_profiles[m_settings.m_profileIndex].m_nrPosition; m_settings.m_nr2ArtifactReduction = m_settings.m_profiles[m_settings.m_profileIndex].m_nr2ArtifactReduction; + // demod + m_settings.m_demod = m_settings.m_profiles[m_settings.m_profileIndex].m_demod; + m_settings.m_cwPeaking = m_settings.m_profiles[m_settings.m_profileIndex].m_cwPeaking; + m_settings.m_cwPeakFrequency = m_settings.m_profiles[m_settings.m_profileIndex].m_cwPeakFrequency; + m_settings.m_cwBandwidth = m_settings.m_profiles[m_settings.m_profileIndex].m_cwBandwidth; + m_settings.m_cwGain = m_settings.m_profiles[m_settings.m_profileIndex].m_cwGain; displaySettings(); applyBandwidths(m_settings.m_profiles[m_settings.m_profileIndex].m_spanLog2, true); // does applySettings(true) } +void WDSPRxGUI::on_demod_currentIndexChanged(int index) +{ + m_settings.m_demod = (WDSPRxProfile::WDSPRxDemod) index; + m_settings.m_profiles[m_settings.m_profileIndex].m_demod = m_settings.m_demod; + + switch(m_settings.m_demod) + { + case WDSPRxProfile::DemodSSB: + break; + case WDSPRxProfile::DemodAM: + case WDSPRxProfile::DemodSAM: + case WDSPRxProfile::DemodFMN: + m_settings.m_dsb = true; + break; + default: + break; + } + displaySettings(); + applySettings(); +} + void WDSPRxGUI::onMenuDialogCalled(const QPoint &p) { if (m_contextMenuType == ContextMenuChannelSettings) @@ -368,7 +413,9 @@ WDSPRxGUI::WDSPRxGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam m_audioSampleRate(-1), m_agcDialog(nullptr), m_dnbDialog(nullptr), - m_dnrDialog(nullptr) + m_dnrDialog(nullptr), + m_amDialog(nullptr), + m_cwPeakDialog(nullptr) { setAttribute(Qt::WA_DeleteOnClose, true); m_helpURL = "plugins/channelrx/demodssb/readme.md"; @@ -396,6 +443,12 @@ WDSPRxGUI::WDSPRxGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam CRightClickEnabler *dnrRightClickEnabler = new CRightClickEnabler(ui->dnr); connect(dnrRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(dnrSetupDialog(const QPoint &))); + CRightClickEnabler *cwPeakRightClickEnabler = new CRightClickEnabler(ui->cwPeaking); + connect(cwPeakRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(cwPeakSetupDialog(const QPoint &))); + + CRightClickEnabler *demodRightClickEnabler = new CRightClickEnabler(ui->demod); + connect(demodRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(demodSetupDialog(const QPoint &))); + ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03))); ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999); @@ -657,11 +710,14 @@ void WDSPRxGUI::displaySettings() ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); + ui->demod->setCurrentIndex(m_settings.m_demod); ui->agc->setChecked(m_settings.m_agc); ui->agcGain->setValue(m_settings.m_agcGain); QString s = QString::number((ui->agcGain->value()), 'f', 0); ui->agcGainText->setText(s); ui->dnr->setChecked(m_settings.m_dnr); + ui->dnb->setChecked(m_settings.m_dnb); + ui->cwPeaking->setChecked(m_settings.m_cwPeaking); ui->audioBinaural->setChecked(m_settings.m_audioBinaural); ui->audioFlipChannels->setChecked(m_settings.m_audioFlipChannels); ui->audioMute->setChecked(m_settings.m_audioMute); @@ -790,10 +846,7 @@ void WDSPRxGUI::dnbSetupDialog(const QPoint& p) m_dnbDialog->setNBLeadTime(m_settings.m_nbLeadTime); m_dnbDialog->setNBLagTime(m_settings.m_nbLagTime); m_dnbDialog->setNBThreshold(m_settings.m_nbThreshold); - m_dnbDialog->setNB2SlewTime(m_settings.m_nb2SlewTime); - m_dnbDialog->setNB2LeadTime(m_settings.m_nb2LeadTime); - m_dnbDialog->setNB2LagTime(m_settings.m_nb2LagTime); - m_dnbDialog->setNB2Threshold(m_settings.m_nb2Threshold); + m_dnbDialog->setNBAvgTime(m_settings.m_nbAvgTime); QObject::connect(m_dnbDialog, &WDSPRxDNBDialog::valueChanged, this, &WDSPRxGUI::dnbSetup); m_dnbDialog->exec(); QObject::disconnect(m_dnbDialog, &WDSPRxDNBDialog::valueChanged, this, &WDSPRxGUI::dnbSetup); @@ -841,24 +894,9 @@ void WDSPRxGUI::dnbSetup(int32_t iValueChanged) m_settings.m_profiles[m_settings.m_profileIndex].m_nbThreshold = m_settings.m_nbThreshold; applySettings(); break; - case WDSPRxDNBDialog::ValueChanged::ChangedNB2SlewTime: - m_settings.m_nb2SlewTime = m_dnbDialog->getNB2SlewTime(); - m_settings.m_profiles[m_settings.m_profileIndex].m_nb2SlewTime = m_settings.m_nb2SlewTime; - applySettings(); - break; - case WDSPRxDNBDialog::ValueChanged::ChangedNB2LeadTime: - m_settings.m_nb2LeadTime = m_dnbDialog->getNB2LeadTime(); - m_settings.m_profiles[m_settings.m_profileIndex].m_nb2LeadTime = m_settings.m_nb2LeadTime; - applySettings(); - break; - case WDSPRxDNBDialog::ValueChanged::ChangedNB2LagTime: - m_settings.m_nb2LagTime = m_dnbDialog->getNB2LagTime(); - m_settings.m_profiles[m_settings.m_profileIndex].m_nb2LagTime = m_settings.m_nb2LagTime; - applySettings(); - break; - case WDSPRxDNBDialog::ValueChanged::ChangedNB2Threshold: - m_settings.m_nb2Threshold = m_dnbDialog->getNB2Threshold(); - m_settings.m_profiles[m_settings.m_profileIndex].m_nb2Threshold = m_settings.m_nb2Threshold; + case WDSPRxDNBDialog::ValueChanged::ChangedNBAvgTime: + m_settings.m_nbAvgTime = m_dnbDialog->getNBAvgTime(); + m_settings.m_profiles[m_settings.m_profileIndex].m_nbAvgTime = m_settings.m_nbAvgTime; applySettings(); break; default: @@ -934,6 +972,86 @@ void WDSPRxGUI::dnrSetup(int32_t iValueChanged) } } +void WDSPRxGUI::cwPeakSetupDialog(const QPoint& p) +{ + m_cwPeakDialog = new WDSPRxCWPeakDialog(); + m_cwPeakDialog->move(p); + m_cwPeakDialog->setCWPeakFrequency(m_settings.m_cwPeakFrequency); + m_cwPeakDialog->setCWBandwidth(m_settings.m_cwBandwidth); + m_cwPeakDialog->setCWGain(m_settings.m_cwGain); + QObject::connect(m_cwPeakDialog, &WDSPRxCWPeakDialog::valueChanged, this, &WDSPRxGUI::cwPeakSetup); + m_cwPeakDialog->exec(); + QObject::disconnect(m_cwPeakDialog, &WDSPRxCWPeakDialog::valueChanged, this, &WDSPRxGUI::cwPeakSetup); + m_cwPeakDialog->deleteLater(); + m_cwPeakDialog = nullptr; +} + +void WDSPRxGUI::cwPeakSetup(int iValueChanged) +{ + if (!m_cwPeakDialog) { + return; + } + + WDSPRxCWPeakDialog::ValueChanged valueChanged = (WDSPRxCWPeakDialog::ValueChanged) iValueChanged; + + switch (valueChanged) + { + case WDSPRxCWPeakDialog::ChangedCWPeakFrequency: + m_settings.m_cwPeakFrequency = m_cwPeakDialog->getCWPeakFrequency(); + m_settings.m_profiles[m_settings.m_profileIndex].m_cwPeakFrequency = m_settings.m_cwPeakFrequency; + applySettings(); + break; + case WDSPRxCWPeakDialog::ChangedCWBandwidth: + m_settings.m_cwBandwidth = m_cwPeakDialog->getCWBandwidth(); + m_settings.m_profiles[m_settings.m_profileIndex].m_cwBandwidth = m_settings.m_cwBandwidth; + applySettings(); + break; + case WDSPRxCWPeakDialog::ChangedCWGain: + m_settings.m_cwGain = m_cwPeakDialog->getCWGain(); + m_settings.m_profiles[m_settings.m_profileIndex].m_cwGain = m_settings.m_cwGain; + applySettings(); + break; + default: + break; + } +} + + +void WDSPRxGUI::demodSetupDialog(const QPoint& p) +{ + if ((m_settings.m_demod == WDSPRxProfile::DemodAM) || (m_settings.m_demod == WDSPRxProfile::DemodSAM)) + { + m_amDialog = new WDSPRxAMDialog(); + m_amDialog->move(p); + m_amDialog->setFadeLevel(m_settings.m_amFadeLevel); + QObject::connect(m_amDialog, &WDSPRxAMDialog::valueChanged, this, &WDSPRxGUI::amSetup); + m_amDialog->exec(); + QObject::disconnect(m_amDialog, &WDSPRxAMDialog::valueChanged, this, &WDSPRxGUI::amSetup); + m_amDialog->deleteLater(); + m_amDialog = nullptr; + } +} + +void WDSPRxGUI::amSetup(int iValueChanged) +{ + if (!m_amDialog) { + return; + } + + WDSPRxAMDialog::ValueChanged valueChanged = (WDSPRxAMDialog::ValueChanged) iValueChanged; + + switch (valueChanged) + { + case WDSPRxAMDialog::ChangedFadeLevel: + m_settings.m_amFadeLevel = m_amDialog->getFadeLevel(); + m_settings.m_profiles[m_settings.m_profileIndex].m_amFadeLevel = m_settings.m_amFadeLevel; + applySettings(); + break; + default: + break; + } +} + void WDSPRxGUI::tick() { double powDbAvg, powDbPeak; @@ -986,6 +1104,8 @@ void WDSPRxGUI::makeUIConnections() QObject::connect(ui->flipSidebands, &QPushButton::clicked, this, &WDSPRxGUI::on_flipSidebands_clicked); QObject::connect(ui->fftWindow, QOverload::of(&QComboBox::currentIndexChanged), this, &WDSPRxGUI::on_fftWindow_currentIndexChanged); QObject::connect(ui->filterIndex, &QDial::valueChanged, this, &WDSPRxGUI::on_profileIndex_valueChanged); + QObject::connect(ui->demod, QOverload::of(&QComboBox::currentIndexChanged), this, &WDSPRxGUI::on_demod_currentIndexChanged); + QObject::connect(ui->cwPeaking, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_cwPeaking_toggled); } void WDSPRxGUI::updateAbsoluteCenterFrequency() diff --git a/plugins/channelrx/wdsprx/wdsprxgui.h b/plugins/channelrx/wdsprx/wdsprxgui.h index 18dafe211..8971b9214 100644 --- a/plugins/channelrx/wdsprx/wdsprxgui.h +++ b/plugins/channelrx/wdsprx/wdsprxgui.h @@ -37,6 +37,8 @@ class WDSPRx; class WDSPRxAGCDialog; class WDSPRxDNBDialog; class WDSPRxDNRDialog; +class WDSPRxAMDialog; +class WDSPRxCWPeakDialog; class SpectrumVis; class BasebandSampleSink; @@ -95,6 +97,8 @@ private: WDSPRxAGCDialog* m_agcDialog; WDSPRxDNBDialog* m_dnbDialog; WDSPRxDNRDialog* m_dnrDialog; + WDSPRxAMDialog* m_amDialog; + WDSPRxCWPeakDialog* m_cwPeakDialog; QIcon m_iconDSBUSB; QIcon m_iconDSBLSB; @@ -125,13 +129,15 @@ private slots: void on_volume_valueChanged(int value); void on_agc_toggled(bool checked); void on_dnr_toggled(bool checked); - // void on_dnb_toggled(bool checked); + void on_dnb_toggled(bool checked); void on_agcGain_valueChanged(int value); void on_audioMute_toggled(bool checked); void on_spanLog2_valueChanged(int value); void on_flipSidebands_clicked(bool checked); void on_fftWindow_currentIndexChanged(int index); void on_profileIndex_valueChanged(int value); + void on_demod_currentIndexChanged(int index); + void on_cwPeaking_toggled(bool checked); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); void handleInputMessages(); @@ -142,6 +148,10 @@ private slots: void dnbSetup(int valueChanged); void dnrSetupDialog(const QPoint& p); void dnrSetup(int valueChanged); + void cwPeakSetupDialog(const QPoint& p); + void cwPeakSetup(int valueChanged); + void demodSetupDialog(const QPoint& p); + void amSetup(int valueChanged); void tick(); }; diff --git a/plugins/channelrx/wdsprx/wdsprxgui.ui b/plugins/channelrx/wdsprx/wdsprxgui.ui index 2c835ba62..d070e015b 100644 --- a/plugins/channelrx/wdsprx/wdsprxgui.ui +++ b/plugins/channelrx/wdsprx/wdsprxgui.ui @@ -6,7 +6,7 @@ 0 0 - 414 + 452 179 @@ -18,7 +18,7 @@ - 414 + 452 0 @@ -36,13 +36,13 @@ 0 0 - 412 + 450 181 - 412 + 450 0 @@ -752,6 +752,39 @@ + + + + + 60 + 16777215 + + + + Modulation (right click for options) + + + + SSB + + + + + AM + + + + + SAM + + + + + FM + + + + @@ -810,7 +843,7 @@ - Toggle AGC + Toggle AGC (right click for options) AGC @@ -867,7 +900,7 @@ - Toggle Digital Noise Reduction + Toggle Digital Noise Reduction (right click for options) NR @@ -880,7 +913,7 @@ - Toggle Digital Noise Blanker + Toggle Digital Noise Blanker (right click for options) NB @@ -890,6 +923,19 @@ + + + + Toggle CW peaking filter (right click for options) + + + CW + + + true + + + diff --git a/plugins/channelrx/wdsprx/wdsprxsettings.cpp b/plugins/channelrx/wdsprx/wdsprxsettings.cpp index c532d28b8..7450db2f1 100644 --- a/plugins/channelrx/wdsprx/wdsprxsettings.cpp +++ b/plugins/channelrx/wdsprx/wdsprxsettings.cpp @@ -41,6 +41,7 @@ WDSPRxSettings::WDSPRxSettings() : void WDSPRxSettings::resetToDefaults() { + m_demod = WDSPRxProfile::DemodSSB; m_audioBinaural = false; m_audioFlipChannels = false; m_dsb = false; @@ -55,10 +56,11 @@ void WDSPRxSettings::resetToDefaults() m_dnb = false; m_nbScheme = WDSPRxProfile::WDSPRxNBScheme::NBSchemeNB; m_nb2Mode = WDSPRxProfile::WDSPRxNB2Mode::NB2ModeZero; - m_nbSlewTime = 0.01; - m_nbLeadTime = 0.01; - m_nbLagTime = 0.01; + m_nbSlewTime = 0.1; + m_nbLeadTime = 0.1; + m_nbLagTime = 0.1; m_nbThreshold = 30; + m_nbAvgTime = 50.0; // Noise reduction m_dnr = false; m_snb = false; @@ -68,6 +70,12 @@ void WDSPRxSettings::resetToDefaults() m_nr2NPE = WDSPRxProfile::NR2NPEOSMS; m_nrPosition = WDSPRxProfile::NRPositionPreAGC; m_nr2ArtifactReduction = true; + // Demods + m_amFadeLevel = false; + m_cwPeaking = false; + m_cwPeakFrequency = 600.0; + m_cwBandwidth = 100.0; + m_cwGain = 2.0; // m_volume = 1.0; m_inputFrequencyOffset = 0; @@ -89,6 +97,7 @@ QByteArray WDSPRxSettings::serialize() const { SimpleSerializer s(1); s.writeS32( 1, m_inputFrequencyOffset); + s.writeS32( 2, (int) m_demod); s.writeS32( 3, m_volume * 10.0); if (m_spectrumGUI) { @@ -113,6 +122,7 @@ QByteArray WDSPRxSettings::serialize() const s.writeDouble(24, m_nbLeadTime); s.writeDouble(25, m_nbLagTime); s.writeS32( 26, m_nbThreshold); + s.writeDouble(27, m_nbAvgTime); // Noise reduction s.writeBool( 30, m_dnr); s.writeBool( 31, m_snb); @@ -122,6 +132,12 @@ QByteArray WDSPRxSettings::serialize() const s.writeS32( 35, (int) m_nr2NPE); s.writeS32( 36, (int) m_nrPosition); s.writeBool( 37, m_nr2ArtifactReduction); + // Demods + s.writeBool( 40, m_amFadeLevel); + s.writeBool( 41, m_cwPeaking); + s.writeDouble(42, m_cwPeakFrequency); + s.writeDouble(43, m_cwBandwidth); + s.writeDouble(44, m_cwGain); // s.writeString(70, m_title); s.writeString(71, m_audioDeviceName); @@ -143,6 +159,7 @@ QByteArray WDSPRxSettings::serialize() const for (unsigned int i = 0; i < 10; i++) { + s.writeS32 (104 + 50*i, (int) m_profiles[i].m_demod); // Filter s.writeS32 (100 + 50*i, m_profiles[i].m_spanLog2); s.writeS32 (101 + 50*i, m_profiles[i].m_highCutoff / 100.0); @@ -162,6 +179,7 @@ QByteArray WDSPRxSettings::serialize() const s.writeDouble(124 + 50*i, m_profiles[i].m_nbLeadTime); s.writeDouble(125 + 50*i, m_profiles[i].m_nbLagTime); s.writeS32 (126 + 50*i, m_profiles[i].m_nbThreshold); + s.writeDouble(127 + 50*i, m_profiles[i].m_nbAvgTime); // Noise reduction s.writeBool (130 + 50*i, m_profiles[i].m_dnr); s.writeBool (131 + 50*i, m_profiles[i].m_snb); @@ -171,6 +189,12 @@ QByteArray WDSPRxSettings::serialize() const s.writeS32 (135 + 50*i, (int) m_profiles[i].m_nr2NPE); s.writeS32 (136 + 50*i, (int) m_profiles[i].m_nrPosition); s.writeBool (137 + 50*i, m_profiles[i].m_nr2ArtifactReduction); + // Demods + s.writeBool (140 + 50*i, m_profiles[i].m_amFadeLevel); + s.writeBool (141 + 50*i, m_profiles[i].m_cwPeaking); + s.writeDouble(142 + 50*i, m_profiles[i].m_cwPeakFrequency); + s.writeDouble(143 + 50*i, m_profiles[i].m_cwBandwidth); + s.writeDouble(144 + 50*i, m_profiles[i].m_cwGain); } return s.final(); @@ -194,6 +218,8 @@ bool WDSPRxSettings::deserialize(const QByteArray& data) QString strtmp; d.readS32( 1, &m_inputFrequencyOffset, 0); + d.readS32( 2, &tmp, 0); + m_demod = (WDSPRxProfile::WDSPRxDemod) tmp; d.readS32( 3, &tmp, 30); m_volume = tmp / 10.0; @@ -220,10 +246,11 @@ bool WDSPRxSettings::deserialize(const QByteArray& data) m_nbScheme = (WDSPRxProfile::WDSPRxNBScheme) tmp; d.readS32( 22, &tmp, 2); m_nb2Mode = (WDSPRxProfile::WDSPRxNB2Mode) tmp; - d.readDouble(23, &m_nbSlewTime, 0.01); - d.readDouble(24, &m_nbLeadTime, 0.01); - d.readDouble(25, &m_nbLagTime, 0.01); + d.readDouble(23, &m_nbSlewTime, 0.1); + d.readDouble(24, &m_nbLeadTime, 0.1); + d.readDouble(25, &m_nbLagTime, 0.1); d.readS32( 26, &m_nbThreshold, 30); + d.readDouble(27, &m_nbAvgTime, 50.0); // Nosie reduction d.readBool( 30, &m_dnr, false); d.readBool( 31, &m_snb, false); @@ -237,6 +264,10 @@ bool WDSPRxSettings::deserialize(const QByteArray& data) d.readS32( 36, &tmp, 2); m_nrPosition = (WDSPRxProfile::WDSPRxNRPosition) tmp; d.readBool( 37, &m_nr2ArtifactReduction, true); + // Demods + d.readBool( 40, &m_amFadeLevel, false); + d.readBool( 41, &m_cwPeaking, false); + d.readDouble(42, &m_cwPeakFrequency, 600.0); // d.readString(70, &m_title, "WDSP Receiver"); d.readString(71, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName); @@ -270,6 +301,8 @@ bool WDSPRxSettings::deserialize(const QByteArray& data) for (unsigned int i = 0; (i < 10); i++) { + d.readS32 (104 + 50*i, &tmp, 9); + m_profiles[i].m_demod = (WDSPRxProfile::WDSPRxDemod) tmp; // Filter d.readS32 (100 + 50*i, &m_profiles[i].m_spanLog2, 3); d.readS32 (101 + 50*i, &tmp, 30); @@ -290,10 +323,11 @@ bool WDSPRxSettings::deserialize(const QByteArray& data) m_profiles[i].m_nbScheme = (WDSPRxProfile::WDSPRxNBScheme) tmp; d.readS32 (122 + 50*i, &tmp); m_profiles[i].m_nb2Mode = (WDSPRxProfile::WDSPRxNB2Mode) tmp; - d.readDouble(123 + 50*i, &m_profiles[i].m_nbSlewTime, 0.01); - d.readDouble(124 + 50*i, &m_profiles[i].m_nbLeadTime, 0.01); - d.readDouble(125 + 50*i, &m_profiles[i].m_nbLagTime, 0.01); - d.readS32 (126 + 50*i, &m_profiles[i].m_nbThreshold, 40); + d.readDouble(123 + 50*i, &m_profiles[i].m_nbSlewTime, 0.1); + d.readDouble(124 + 50*i, &m_profiles[i].m_nbLeadTime, 0.1); + d.readDouble(125 + 50*i, &m_profiles[i].m_nbLagTime, 0.1); + d.readS32 (126 + 50*i, &m_profiles[i].m_nbThreshold, 30); + d.readDouble(127 + 50*i, &m_profiles[i].m_nbAvgTime, 50.0); // Noise reduction d.readBool (130 + 50*i, &m_profiles[i].m_dnr, false); d.readBool (131 + 50*i, &m_profiles[i].m_snb, false); @@ -307,6 +341,10 @@ bool WDSPRxSettings::deserialize(const QByteArray& data) d.readS32 (136 + 50*i, &tmp); m_profiles[i].m_nrPosition = (WDSPRxProfile::WDSPRxNRPosition) tmp; d.readBool (137 + 50*i, &m_profiles[i].m_nr2ArtifactReduction); + // Demods + d.readBool (140 + 50*i, &m_amFadeLevel, false); + d.readBool (141 + 50*i, &m_cwPeaking, false); + d.readDouble(142 + 50*i, &m_profiles[i].m_cwPeakFrequency, 600.0); } return true; diff --git a/plugins/channelrx/wdsprx/wdsprxsettings.h b/plugins/channelrx/wdsprx/wdsprxsettings.h index c48043a6d..abd38c961 100644 --- a/plugins/channelrx/wdsprx/wdsprxsettings.h +++ b/plugins/channelrx/wdsprx/wdsprxsettings.h @@ -28,6 +28,13 @@ class Serializable; struct WDSPRxProfile { + enum WDSPRxDemod + { + DemodSSB, + DemodAM, + DemodSAM, + DemodFMN, + }; enum WDSPRxAGCMode { AGCLong, @@ -42,8 +49,8 @@ struct WDSPRxProfile }; enum WDSPRxNBScheme { - NBSchemeNB, - NBSchemeNB2, + NBSchemeNB, //!< Preemptive Wideband Blanker (ANB) + NBSchemeNB2, //!< Interpolating Wideband Blanker (NOB) }; enum WDSPRxNR2Gain { @@ -70,6 +77,7 @@ struct WDSPRxProfile NB2ModeInterpolate, }; + WDSPRxDemod m_demod; // Filter int m_spanLog2; Real m_highCutoff; @@ -85,14 +93,11 @@ struct WDSPRxProfile bool m_dnb; WDSPRxNBScheme m_nbScheme; WDSPRxNB2Mode m_nb2Mode; - double m_nbSlewTime; // a.k.a tau - double m_nbLeadTime; - double m_nbLagTime; + double m_nbSlewTime; // a.k.a tau + double m_nbLeadTime; // a.k.a adv time + double m_nbLagTime; // a.k.a hang time int m_nbThreshold; - double m_nb2SlewTime; // a.k.a tau - double m_nb2LeadTime; - double m_nb2LagTime; - int m_nb2Threshold; + double m_nbAvgTime; // a.k.a back tau // Noise rediction bool m_dnr; bool m_snb; @@ -102,8 +107,15 @@ struct WDSPRxProfile WDSPRxNR2NPE m_nr2NPE; WDSPRxNRPosition m_nrPosition; bool m_nr2ArtifactReduction; + // Demods + bool m_amFadeLevel; + bool m_cwPeaking; + double m_cwPeakFrequency; + double m_cwBandwidth; + double m_cwGain; WDSPRxProfile() : + m_demod(DemodSSB), m_spanLog2(3), m_highCutoff(3000), m_lowCutoff(300), @@ -116,14 +128,11 @@ struct WDSPRxProfile m_dnb(false), m_nbScheme(NBSchemeNB), m_nb2Mode(NB2ModeZero), - m_nbSlewTime(0.01), - m_nbLeadTime(0.01), - m_nbLagTime(0.01), + m_nbSlewTime(0.1), + m_nbLeadTime(0.1), + m_nbLagTime(0.1), m_nbThreshold(30), - m_nb2SlewTime(0.01), - m_nb2LeadTime(0.01), - m_nb2LagTime(0.01), - m_nb2Threshold(30), + m_nbAvgTime(50.0), m_dnr(false), m_snb(false), m_anf(false), @@ -131,12 +140,18 @@ struct WDSPRxProfile m_nr2Gain(NR2GainGamma), m_nr2NPE(NR2NPEOSMS), m_nrPosition(NRPositionPreAGC), - m_nr2ArtifactReduction(true) + m_nr2ArtifactReduction(true), + m_amFadeLevel(false), + m_cwPeaking(false), + m_cwPeakFrequency(600.0), + m_cwBandwidth(100.0), + m_cwGain(2.0) {} }; struct WDSPRxSettings { + WDSPRxProfile::WDSPRxDemod m_demod; qint32 m_inputFrequencyOffset; // Real m_highCutoff; // Real m_lowCutoff; @@ -160,10 +175,7 @@ struct WDSPRxSettings double m_nbLeadTime; double m_nbLagTime; int m_nbThreshold; - double m_nb2SlewTime; - double m_nb2LeadTime; - double m_nb2LagTime; - int m_nb2Threshold; + double m_nbAvgTime; // Noise reduction bool m_dnr; bool m_snb; @@ -173,6 +185,12 @@ struct WDSPRxSettings WDSPRxProfile::WDSPRxNR2NPE m_nr2NPE; WDSPRxProfile::WDSPRxNRPosition m_nrPosition; bool m_nr2ArtifactReduction; + // Demods + bool m_amFadeLevel; + bool m_cwPeaking; + double m_cwPeakFrequency; + double m_cwBandwidth; + double m_cwGain; quint32 m_rgbColor; QString m_title; diff --git a/plugins/channelrx/wdsprx/wdsprxsink.cpp b/plugins/channelrx/wdsprx/wdsprxsink.cpp index 397986e2c..2f9c3f217 100644 --- a/plugins/channelrx/wdsprx/wdsprxsink.cpp +++ b/plugins/channelrx/wdsprx/wdsprxsink.cpp @@ -36,6 +36,8 @@ #include "anf.hpp" #include "anb.hpp" #include "nob.hpp" +#include "amd.hpp" +#include "iir.cpp" #include "wdsprxsink.h" @@ -326,6 +328,7 @@ void WDSPRxSink::applyAudioSampleRate(int sampleRate) void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) { qDebug() << "WDSPRxSink::applySettings:" + << " m_demod: " << settings.m_demod << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset << " m_profileIndex: " << settings.m_profileIndex << " m_spanLog2: " << settings.m_profiles[settings.m_profileIndex].m_spanLog2 @@ -337,12 +340,18 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) << " m_audioFlipChannels: " << settings.m_audioFlipChannels << " m_dsb: " << settings.m_dsb << " m_audioMute: " << settings.m_audioMute - << " m_agcActive: " << settings.m_agc + << " m_agc: " << settings.m_agc << " m_agcMode: " << settings.m_agcMode << " m_agcGain: " << settings.m_agcGain << " m_agcSlope: " << settings.m_agcSlope << " m_agcHangThreshold: " << settings.m_agcHangThreshold << " m_audioDeviceName: " << settings.m_audioDeviceName + << " m_dnr: " << settings.m_dnr + << " m_nrScheme: " << settings.m_nrScheme + << " m_nrPosition: "<< settings.m_nrPosition + << " m_nr2Gain: " << settings.m_nr2Gain + << " m_nr2NPE: " << settings.m_nr2NPE + << " m_nr2ArtifactReduction: " << settings.m_nr2ArtifactReduction << " m_streamIndex: " << settings.m_streamIndex << " m_useReverseAPI: " << settings.m_useReverseAPI << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress @@ -351,14 +360,16 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) << " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex << " force: " << force; - // Filter + // Filter and mode if((m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff != settings.m_profiles[settings.m_profileIndex].m_highCutoff) || (m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff != settings.m_profiles[settings.m_profileIndex].m_lowCutoff) || (m_settings.m_profiles[m_settings.m_profileIndex].m_fftWindow != settings.m_profiles[settings.m_profileIndex].m_fftWindow) || + (m_settings.m_demod != settings.m_demod) || (m_settings.m_dsb != settings.m_dsb) || force) { float band, low, high, fLow, fHigh; + bool usb, dsb; band = settings.m_profiles[settings.m_profileIndex].m_highCutoff; high = band; @@ -368,10 +379,12 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) { band = -band; m_spectrumProbe.setUSB(false); + usb = false; } else { m_spectrumProbe.setUSB(true); + usb = true; } m_Bandwidth = band; @@ -383,12 +396,14 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) fLow = high; fHigh = -high; m_spectrumProbe.setDSB(true); + dsb = true; } else { fLow = high; fHigh = low; m_spectrumProbe.setDSB(false); + dsb = false; } } else @@ -398,12 +413,14 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) fLow = -high; fHigh = high; m_spectrumProbe.setDSB(true); + dsb = true; } else { fLow = low; fHigh = high; m_spectrumProbe.setDSB(false); + dsb = false; } } @@ -414,6 +431,34 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) WDSP::RXA::SetPassband(*m_rxa, fLow, fHigh); WDSP::NBP::NBPSetWindow(*m_rxa, m_settings.m_profiles[m_settings.m_profileIndex].m_fftWindow); + + if (settings.m_demod == WDSPRxProfile::DemodSSB) + { + if (dsb) + { + WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_DSB); + } + else + { + if (usb) { + WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_USB); + } else { + WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_LSB); + } + } + } + else if (settings.m_demod == WDSPRxProfile::DemodAM) + { + WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_AM); + } + else if (settings.m_demod == WDSPRxProfile::DemodSAM) + { + WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_SAM); + } + else if (settings.m_demod == WDSPRxProfile::DemodFMN) + { + WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_FM); + } } if ((m_settings.m_profiles[settings.m_profileIndex].m_spanLog2 != settings.m_profiles[settings.m_profileIndex].m_spanLog2) || force) { @@ -498,14 +543,33 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) WDSP::EMNR::SetEMNRaeRun(*m_rxa, settings.m_nr2ArtifactReduction ? 1 : 0); } - if ((m_settings.m_snb != settings.m_snb) || force) { - WDSP::SNBA::SetSNBARun(*m_rxa, settings.m_snb ? 1 : 0); - } - if ((m_settings.m_anf != settings.m_anf) || force) { WDSP::ANF::SetANFRun(*m_rxa, settings.m_anf ? 1 : 0); } + // Causes corruption + // if ((m_settings.m_snb != settings.m_snb) || force) { + // WDSP::SNBA::SetSNBARun(*m_rxa, settings.m_snb ? 1 : 0); + // } + + // CW Peaking + + if ((m_settings.m_cwPeaking != settings.m_cwPeaking) || force) { + WDSP::SPEAK::SetSPCWRun(*m_rxa, settings.m_cwPeaking ? 1 : 0); + } + + if ((m_settings.m_cwPeakFrequency != settings.m_cwPeakFrequency) || force) { + WDSP::SPEAK::SetSPCWFreq(*m_rxa, settings.m_cwPeakFrequency); + } + + if ((m_settings.m_cwBandwidth != settings.m_cwBandwidth) || force) { + WDSP::SPEAK::SetSPCWBandwidth(*m_rxa, settings.m_cwBandwidth); + } + + if ((m_settings.m_cwGain != settings.m_cwGain) || force) { + WDSP::SPEAK::SetSPCWGain(*m_rxa, settings.m_cwGain); + } + // Noise Blanker if ((m_settings.m_dnb != settings.m_dnb) @@ -530,36 +594,40 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) } } - if ((m_settings.m_nbSlewTime != settings.m_nbSlewTime) || force) { - WDSP::ANB::SetANBTau(*m_rxa, settings.m_nbSlewTime); + if ((m_settings.m_nbSlewTime != settings.m_nbSlewTime) || force) + { + WDSP::ANB::SetANBTau(*m_rxa, settings.m_nbSlewTime * 0.001); + WDSP::NOB::SetNOBTau(*m_rxa, settings.m_nbSlewTime * 0.001); } - if ((m_settings.m_nbLeadTime != settings.m_nbLeadTime) || force) { - WDSP::ANB::SetANBAdvtime(*m_rxa, settings.m_nbLeadTime); + if ((m_settings.m_nbLeadTime != settings.m_nbLeadTime) || force) + { + WDSP::ANB::SetANBAdvtime(*m_rxa, settings.m_nbLeadTime * 0.001); + WDSP::NOB::SetNOBAdvtime(*m_rxa, settings.m_nbLeadTime * 0.001); } - if ((m_settings.m_nbLagTime != settings.m_nbLagTime) || force) { - WDSP::ANB::SetANBHangtime(*m_rxa, settings.m_nbLagTime); + if ((m_settings.m_nbLagTime != settings.m_nbLagTime) || force) + { + WDSP::ANB::SetANBHangtime(*m_rxa, settings.m_nbLagTime * 0.001); + WDSP::NOB::SetNOBHangtime(*m_rxa, settings.m_nbLagTime * 0.001); } - if ((m_settings.m_nbThreshold != settings.m_nbThreshold) || force) { + if ((m_settings.m_nbThreshold != settings.m_nbThreshold) || force) + { WDSP::ANB::SetANBThreshold(*m_rxa, settings.m_nbThreshold); + WDSP::NOB::SetNOBThreshold(*m_rxa, settings.m_nbThreshold); } - if ((m_settings.m_nb2SlewTime != settings.m_nb2SlewTime) || force) { - WDSP::NOB::SetNOBTau(*m_rxa, settings.m_nb2SlewTime); + if ((m_settings.m_nbAvgTime != settings.m_nbAvgTime) || force) + { + WDSP::ANB::SetANBBacktau(*m_rxa, settings.m_nbAvgTime * 0.001); + WDSP::NOB::SetNOBBacktau(*m_rxa, settings.m_nbAvgTime * 0.001); } - if ((m_settings.m_nb2LeadTime != settings.m_nb2LeadTime) || force) { - WDSP::NOB::SetNOBAdvtime(*m_rxa, settings.m_nb2LeadTime); - } + // AM option - if ((m_settings.m_nb2LagTime != settings.m_nb2LagTime) || force) { - WDSP::NOB::SetNOBHangtime(*m_rxa, settings.m_nb2LagTime); - } - - if ((m_settings.m_nb2Threshold != settings.m_nb2Threshold) || force) { - WDSP::NOB::SetNOBThreshold(*m_rxa, settings.m_nb2Threshold); + if ((m_settings.m_amFadeLevel != settings.m_amFadeLevel) || force) { + WDSP::AMD::SetAMDFadeLevel(*m_rxa, settings.m_amFadeLevel); } // Audio panel diff --git a/wdsp/RXA.cpp b/wdsp/RXA.cpp index ea584fe3b..32dc81ae1 100644 --- a/wdsp/RXA.cpp +++ b/wdsp/RXA.cpp @@ -916,7 +916,7 @@ void RXA::SetMode (RXA& rxa, int mode) rxa.mode = mode; rxa.amd.p->run = 0; rxa.fmd.p->run = 0; - rxa.agc.p->run = 1; + switch (mode) { case RXA_AM: @@ -937,6 +937,7 @@ void RXA::SetMode (RXA& rxa, int mode) break; } + bp1Set (rxa); bpsnbaSet (rxa); // update variables rxa.csDSP.unlock(); diff --git a/wdsp/comm.hpp b/wdsp/comm.hpp index 555bdce83..61a7908f0 100644 --- a/wdsp/comm.hpp +++ b/wdsp/comm.hpp @@ -77,6 +77,7 @@ warren@wpratt.com namespace WDSP { // miscellaneous typedef float wcomplex[2]; +typedef double dcomplex[2]; } #include diff --git a/wdsp/nbp.cpp b/wdsp/nbp.cpp index a496159e5..ceb080fe8 100644 --- a/wdsp/nbp.cpp +++ b/wdsp/nbp.cpp @@ -571,12 +571,12 @@ void NBP::NBPSetNotchesRun (RXA& rxa, int run) { a->master_run = run; // update variables b->fnfrun = a->master_run; - BPSNBA::bpsnbaCheck (rxa, rxa.mode, run); + RXA::bpsnbaCheck (rxa, rxa.mode, run); calc_nbp_impulse (b); // recalc nbp impulse response FIRCORE::setImpulse_fircore (b->p, b->impulse, 0); // calculate new filter masks delete[] (b->impulse); rxa.csDSP.lock(); // block DSP channel processing - BPSNBA::bpsnbaSet (rxa); + RXA::bpsnbaSet (rxa); FIRCORE::setUpdate_fircore (b->p); // apply new filter masks rxa.csDSP.unlock(); // unblock channel processing } diff --git a/wdsp/snb.cpp b/wdsp/snb.cpp index f0ac274ee..02a79c3f4 100644 --- a/wdsp/snb.cpp +++ b/wdsp/snb.cpp @@ -640,13 +640,13 @@ void SNBA::SetSNBARun (RXA& rxa, int run) SNBA *a = rxa.snba.p; if (a->run != run) { - BPSNBA::bpsnbaCheck (rxa, rxa.mode, rxa.ndb.p->master_run); + RXA::bpsnbaCheck (rxa, rxa.mode, rxa.ndb.p->master_run); RXA::bp1Check (rxa, rxa.amd.p->run, run, rxa.emnr.p->run, rxa.anf.p->run, rxa.anr.p->run); rxa.csDSP.lock(); a->run = run; RXA::bp1Set (rxa); - BPSNBA::bpsnbaSet (rxa); + RXA::bpsnbaSet (rxa); rxa.csDSP.unlock(); } }