diff --git a/include/dsp/agc.h b/include/dsp/agc.h index 2877d5ac0..e6e320800 100644 --- a/include/dsp/agc.h +++ b/include/dsp/agc.h @@ -38,6 +38,9 @@ public: MagSquaredAGC(int historySize, Real R); virtual ~MagSquaredAGC(); virtual void feed(Complex& ci); + Real getMagSq() const { return m_magsq; } +private: + Real m_magsq; }; class MagAGC : public AGC @@ -47,6 +50,9 @@ public: MagAGC(int historySize, Real R); virtual ~MagAGC(); virtual void feed(Complex& ci); + Real getMagSq() const { return m_magsq; } +private: + Real m_magsq; }; class AlphaAGC : public AGC @@ -58,8 +64,10 @@ public: virtual ~AlphaAGC(); void resize(int historySize, Real R, Real alpha); virtual void feed(Complex& ci); + Real getMagSq() const { return m_magsq; } private: Real m_alpha; + Real m_magsq; bool m_squelchOpen; }; diff --git a/plugins/channel/nfm/nfmdemod.cpp b/plugins/channel/nfm/nfmdemod.cpp index aaa6e42a2..070d46132 100644 --- a/plugins/channel/nfm/nfmdemod.cpp +++ b/plugins/channel/nfm/nfmdemod.cpp @@ -55,6 +55,7 @@ NFMDemod::NFMDemod() : m_agcLevel = 1.0; m_AGC.resize(240, m_agcLevel); + m_magsq = 0; m_ctcssDetector.setCoefficients(3000, 6000.0); // 0.5s / 2 Hz resolution m_afSquelch.setCoefficients(24, 600, 48000.0, 200, 0); // 4000 Hz span, 250us, 100ms attack @@ -134,6 +135,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto //ci *= (m_agcLevel / m_AGC.getValue()); m_AGC.feed(ci); + m_magsq = m_AGC.getMagSq(); // demod /* diff --git a/plugins/channel/nfm/nfmdemod.h b/plugins/channel/nfm/nfmdemod.h index bf3dae5fe..90818a678 100644 --- a/plugins/channel/nfm/nfmdemod.h +++ b/plugins/channel/nfm/nfmdemod.h @@ -64,6 +64,8 @@ public: m_ctcssIndexSelected = selectedCtcssIndex; } + Real getMagSq() const { return m_magsq; } + private: class MsgConfigureNFMDemod : public Message { MESSAGE_CLASS_DECLARATION @@ -163,6 +165,7 @@ private: AFSquelch m_afSquelch; Real m_agcLevel; // AGC will aim to this level Real m_agcFloor; // AGC will not go below this level + Real m_magsq; AudioVector m_audioBuffer; uint m_audioBufferFill; diff --git a/plugins/channel/nfm/nfmdemodgui.cpp b/plugins/channel/nfm/nfmdemodgui.cpp index 5ec0c1c2b..fc30276f1 100644 --- a/plugins/channel/nfm/nfmdemodgui.cpp +++ b/plugins/channel/nfm/nfmdemodgui.cpp @@ -10,8 +10,10 @@ #include "gui/glspectrum.h" #include "plugin/pluginapi.h" #include "util/simpleserializer.h" +#include "util/db.h" #include "gui/basicchannelsettingswidget.h" #include "dsp/dspengine.h" +#include "mainwindow.h" const int NFMDemodGUI::m_rfBW[] = { 5000, 6250, 8330, 10000, 12500, 15000, 20000, 25000, 40000 @@ -143,7 +145,7 @@ void NFMDemodGUI::viewChanged() applySettings(); } -void NFMDemodGUI::on_deltaMinus_clicked(bool minus) +void NFMDemodGUI::on_deltaMinus_toggled(bool minus) { int deltaFrequency = m_channelMarker.getCenterFrequency(); bool minusDelta = (deltaFrequency < 0); @@ -229,7 +231,8 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) : m_pluginAPI(pluginAPI), m_channelMarker(this), m_basicSettingsShown(false), - m_doApplySettings(true) + m_doApplySettings(true), + m_channelPowerDbAvg(20,0) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); @@ -239,6 +242,8 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) : m_nfmDemod = new NFMDemod(); m_nfmDemod->registerGUI(this); + connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); + int ctcss_nbTones; const Real *ctcss_tones = m_nfmDemod->getCtcssToneSet(ctcss_nbTones); @@ -334,3 +339,9 @@ void NFMDemodGUI::blockApplySettings(bool block) m_doApplySettings = !block; } +void NFMDemodGUI::tick() +{ + Real powDb = CalcDb::dbPower(m_nfmDemod->getMagSq()); + m_channelPowerDbAvg.feed(powDb); + ui->channelPower->setText(QString::number(m_channelPowerDbAvg.average(), 'f', 1)); +} diff --git a/plugins/channel/nfm/nfmdemodgui.h b/plugins/channel/nfm/nfmdemodgui.h index 0cc582926..50bba7b5a 100644 --- a/plugins/channel/nfm/nfmdemodgui.h +++ b/plugins/channel/nfm/nfmdemodgui.h @@ -5,6 +5,7 @@ #include "plugin/plugingui.h" #include "dsp/dsptypes.h" #include "dsp/channelmarker.h" +#include "dsp/movingaverage.h" class PluginAPI; @@ -38,7 +39,7 @@ public: private slots: void viewChanged(); void on_deltaFrequency_changed(quint64 value); - void on_deltaMinus_clicked(bool minus); + void on_deltaMinus_toggled(bool minus); void on_rfBW_valueChanged(int value); void on_afBW_valueChanged(int value); void on_volume_valueChanged(int value); @@ -47,6 +48,7 @@ private slots: void on_ctcssOn_toggled(bool checked); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDoubleClicked(); + void tick(); private: Ui::NFMDemodGUI* ui; @@ -59,6 +61,7 @@ private: Channelizer* m_channelizer; NFMDemod* m_nfmDemod; bool m_ctcssOn; + MovingAverage m_channelPowerDbAvg; static const int m_rfBW[]; diff --git a/plugins/channel/nfm/nfmdemodgui.ui b/plugins/channel/nfm/nfmdemodgui.ui index 85122430c..3ec498d85 100644 --- a/plugins/channel/nfm/nfmdemodgui.ui +++ b/plugins/channel/nfm/nfmdemodgui.ui @@ -6,8 +6,8 @@ 0 0 - 263 - 151 + 167 + 433 @@ -18,14 +18,17 @@ 6 35 - 251 - 111 + 122 + 395 Settings - + + + 3 + 2 @@ -38,268 +41,315 @@ 2 - - 3 - - - + + - - - Activate CTCSS - + - + ... + + + + :/plus.png + :/minus.png + + + + true - - + + + + 0 + 0 + + + - 16777215 - 16777215 + 32 + 16 + + + Monospace + 12 + + + + SizeVerCursor + + + Qt::StrongFocus + - Set CTCSS Frequency + Demod shift frequency from center in Hz + + + + + + + Hz + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Channel power + + + Qt::RightToLeft + + + 0.0 + + + + + + + dB - - - - 100 - - - 20 - - - Qt::Horizontal - - + + + + + + RF BW + + + + + + + 8 + + + 1 + + + 4 + + + Qt::Horizontal + + + + + + + + 50 + 0 + + + + 12.5 k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + - - - - 8 - - - 1 - - - 4 - - - Qt::Horizontal - - + + + + + + AF BW + + + + + + + 1 + + + 20 + + + 1 + + + 3 + + + Qt::Horizontal + + + + + + + + 50 + 0 + + + + 3 k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + - - - - Qt::RightToLeft - - - Minus - - + + + + + + Volume + + + + + + + 100 + + + 20 + + + Qt::Horizontal + + + + + + + + 50 + 0 + + + + 2.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + - - - - Squelch - - + + + + + + Squelch + + + + + + + Threshold min/max in dB + + + -200 + + + 0 + + + 1 + + + -150 + + + Qt::Horizontal + + + + + + + + 50 + 0 + + + + -15.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + - - - - AF BW - - - - - - - RF BW - - - - - - - Threshold min/max in dB - - - -200 - - - 0 - - - 1 - - - -150 - - - Qt::Horizontal - - - - - - - Volume - - - - - - - - 50 - 0 - - - - 12.5 k - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - 0 - - - - 3 k - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 1 - - - 20 - - - 1 - - - 3 - - - Qt::Horizontal - - - - - - - - 50 - 0 - - - - -15.0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - 0 - - - - 2.0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Hz - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - CTCSS - - - - - - - - 0 - 0 - - - - - 32 - 16 - - - - - Monospace - 12 - - - - SizeVerCursor - - - Qt::StrongFocus - - - Demod shift frequency from center in Hz - - - - - - - CTCSS detected - - - -- - - - Qt::AlignCenter - - + + + + + + CTCSS + + + + + + + + + Activate CTCSS + + + + + + + + + + + 16777215 + 16777215 + + + + Set CTCSS Frequency + + + + + + + + + CTCSS detected + + + -- + + + Qt::AlignCenter + + + + @@ -318,6 +368,8 @@ 1 - + + + diff --git a/sdrbase/dsp/agc.cpp b/sdrbase/dsp/agc.cpp index 6ecbc8729..fa1f5da02 100644 --- a/sdrbase/dsp/agc.cpp +++ b/sdrbase/dsp/agc.cpp @@ -46,11 +46,13 @@ Real AGC::getAverage() } MagSquaredAGC::MagSquaredAGC() : - AGC() + AGC(), + m_magsq(0.0) {} MagSquaredAGC::MagSquaredAGC(int historySize, Real R) : - AGC(historySize, R) + AGC(historySize, R), + m_magsq(0.0) {} MagSquaredAGC::~MagSquaredAGC() @@ -58,19 +60,21 @@ MagSquaredAGC::~MagSquaredAGC() void MagSquaredAGC::feed(Complex& ci) { - Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); - m_moving_average.feed(magsq); + m_magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); + m_moving_average.feed(m_magsq); m_u0 = m_R / m_moving_average.average(); ci *= m_u0; } MagAGC::MagAGC() : - AGC() + AGC(), + m_magsq(0.0) {} MagAGC::MagAGC(int historySize, Real R) : - AGC(historySize, R) + AGC(historySize, R), + m_magsq(0.0) {} MagAGC::~MagAGC() @@ -78,8 +82,8 @@ MagAGC::~MagAGC() void MagAGC::feed(Complex& ci) { - Real mag = sqrt(ci.real()*ci.real() + ci.imag()*ci.imag()); - m_moving_average.feed(mag); + m_magsq = sqrt(ci.real()*ci.real() + ci.imag()*ci.imag()); + m_moving_average.feed(m_magsq); m_u0 = m_R / m_moving_average.average(); ci *= m_u0; } @@ -88,12 +92,14 @@ void MagAGC::feed(Complex& ci) AlphaAGC::AlphaAGC() : AGC(), m_alpha(0.5), + m_magsq(0.0), m_squelchOpen(true) {} AlphaAGC::AlphaAGC(int historySize, Real R) : AGC(historySize, R), m_alpha(0.5), + m_magsq(0.0), m_squelchOpen(true) {} @@ -101,6 +107,7 @@ AlphaAGC::AlphaAGC(int historySize, Real R) : AlphaAGC::AlphaAGC(int historySize, Real R, Real alpha) : AGC(historySize, R), m_alpha(alpha), + m_magsq(0.0), m_squelchOpen(true) {} @@ -117,16 +124,16 @@ void AlphaAGC::resize(int historySize, Real R, Real alpha) void AlphaAGC::feed(Complex& ci) { - Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); + m_magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); - if (m_squelchOpen && (magsq)) + if (m_squelchOpen && (m_magsq)) { - m_moving_average.feed(m_moving_average.average() - m_alpha*(m_moving_average.average() - magsq)); + m_moving_average.feed(m_moving_average.average() - m_alpha*(m_moving_average.average() - m_magsq)); } else { //m_squelchOpen = true; - m_moving_average.feed(magsq); + m_moving_average.feed(m_magsq); } ci *= m_u0; }