diff --git a/plugins/channelrx/demodssb/ssbdemod.cpp b/plugins/channelrx/demodssb/ssbdemod.cpp index b1a86fa17..1d2f5f815 100644 --- a/plugins/channelrx/demodssb/ssbdemod.cpp +++ b/plugins/channelrx/demodssb/ssbdemod.cpp @@ -318,6 +318,7 @@ bool SSBDemod::handleMessage(const Message& cmd) m_agcActive = cfg.getAGC(); int agcNbSamples = 48 * (1<volume->setValue(40); ui->deltaFrequency->setValue(0); ui->spanLog2->setValue(3); + ui->agc->setChecked(false); + ui->agcTimeLog2->setValue(7); + ui->agcPowerThreshold->setValue(-40); + ui->agcThresholdGate->setValue(4); blockApplySettings(false); applySettings(); @@ -133,11 +137,10 @@ bool SSBDemodGUI::deserialize(const QByteArray& data) ui->agcTimeLog2->setValue(tmp); QString s = QString::number((1<agcTimeText->setText(s); - d.readS32(13, &tmp, -20); + d.readS32(13, &tmp, -40); ui->agcPowerThreshold->setValue(tmp); - s = QString::number(tmp, 'f', 0); - ui->agcPowerThresholdText->setText(s); - d.readS32(14, &tmp, 5); + displayAGCPowerThreshold(tmp); + d.readS32(14, &tmp, 4); ui->agcThresholdGate->setValue(tmp); s = QString::number(tmp, 'f', 0); ui->agcThresholdGateText->setText(s); @@ -298,8 +301,7 @@ void SSBDemodGUI::on_agcTimeLog2_valueChanged(int value) void SSBDemodGUI::on_agcPowerThreshold_valueChanged(int value) { - QString s = QString::number(value, 'f', 0); - ui->agcPowerThresholdText->setText(s); + displayAGCPowerThreshold(value); applySettings(); } @@ -522,6 +524,19 @@ void SSBDemodGUI::applySettings() } } +void SSBDemodGUI::displayAGCPowerThreshold(int value) +{ + if (value == -99) + { + ui->agcPowerThresholdText->setText("---"); + } + else + { + QString s = QString::number(value, 'f', 0); + ui->agcPowerThresholdText->setText(s); + } +} + void SSBDemodGUI::leaveEvent(QEvent*) { blockApplySettings(true); diff --git a/plugins/channelrx/demodssb/ssbdemodgui.h b/plugins/channelrx/demodssb/ssbdemodgui.h index db374405e..22c406216 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.h +++ b/plugins/channelrx/demodssb/ssbdemodgui.h @@ -88,6 +88,8 @@ private: void blockApplySettings(bool block); void applySettings(); + void displayAGCPowerThreshold(int value); + void leaveEvent(QEvent*); void enterEvent(QEvent*); }; diff --git a/plugins/channelrx/demodssb/ssbdemodgui.ui b/plugins/channelrx/demodssb/ssbdemodgui.ui index d2688f13e..c810f96a5 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.ui +++ b/plugins/channelrx/demodssb/ssbdemodgui.ui @@ -533,7 +533,7 @@ 1 - -50 + -40 diff --git a/sdrbase/dsp/agc.cpp b/sdrbase/dsp/agc.cpp index af8e7c2a5..d1645041e 100644 --- a/sdrbase/dsp/agc.cpp +++ b/sdrbase/dsp/agc.cpp @@ -49,6 +49,7 @@ MagSquaredAGC::MagSquaredAGC(int historySize, double R, double threshold) : AGC(historySize, R), m_magsq(0.0), m_threshold(threshold), + m_thresholdEnable(true), m_gate(0), m_stepLength(std::min(StepLengthMax, historySize/2)), m_stepDelta(1.0/m_stepLength), @@ -137,8 +138,10 @@ double MagSquaredAGC::feedAndGetValue(const Complex& ci) MagAGC::MagAGC(int historySize, double R, double threshold) : AGC(historySize, R), + m_squared(false), m_magsq(0.0), m_threshold(threshold), + m_thresholdEnable(true), m_gate(0), m_stepLength(std::min(StepLengthMax, historySize/2)), m_stepDelta(1.0/m_stepLength), @@ -159,6 +162,17 @@ void MagAGC::resize(int historySize, Real R) AGC::resize(historySize, R); } +void MagAGC::setThresholdEnable(bool enable) +{ + if (m_thresholdEnable != enable) + { + m_stepUpCounter = 0; + m_stepDownCounter = m_stepLength; + } + + m_thresholdEnable = enable; +} + void MagAGC::feed(Complex& ci) { ci *= feedAndGetValue(ci); @@ -168,55 +182,62 @@ double MagAGC::feedAndGetValue(const Complex& ci) { m_magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); m_moving_average.feed(m_magsq); - m_u0 = m_R / sqrt(m_moving_average.average()); + m_u0 = m_R / (m_squared ? m_moving_average.average() : sqrt(m_moving_average.average())); - if (m_magsq > m_threshold) + if (m_thresholdEnable) { - if (m_gateCounter < m_gate) + if (m_magsq > m_threshold) { - m_gateCounter++; + if (m_gateCounter < m_gate) + { + m_gateCounter++; + } + else + { + m_count = 0; + } } else { - m_count = 0; + if (m_count < m_moving_average.historySize()) { + m_count++; + } + + m_gateCounter = 0; + } + + if (m_count < m_moving_average.historySize()) + { + m_stepDownCounter = m_stepUpCounter; + + if (m_stepUpCounter < m_stepLength) + { + m_stepUpCounter++; + return m_u0 * StepFunctions::smootherstep(m_stepUpCounter * m_stepDelta); + } + else + { + return m_u0; + } + } + else + { + m_stepUpCounter = m_stepDownCounter; + + if (m_stepDownCounter > 0) + { + m_stepDownCounter--; + return m_u0 * StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta); + } + else + { + return 0.0; + } } } else { - if (m_count < m_moving_average.historySize()) { - m_count++; - } - - m_gateCounter = 0; - } - - if (m_count < m_moving_average.historySize()) - { - m_stepDownCounter = m_stepUpCounter; - - if (m_stepUpCounter < m_stepLength) - { - m_stepUpCounter++; - return m_u0 * StepFunctions::smootherstep(m_stepUpCounter * m_stepDelta); - } - else - { - return m_u0; - } - } - else - { - m_stepUpCounter = m_stepDownCounter; - - if (m_stepDownCounter > 0) - { - m_stepDownCounter--; - return m_u0 * StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta); - } - else - { - return 0.0; - } + return m_u0; } } diff --git a/sdrbase/dsp/agc.h b/sdrbase/dsp/agc.h index 77312727e..f948a8004 100644 --- a/sdrbase/dsp/agc.h +++ b/sdrbase/dsp/agc.h @@ -39,16 +39,18 @@ public: double feedAndGetValue(const Complex& ci); double getMagSq() const { return m_magsq; } void setThreshold(double threshold) { m_threshold = threshold; } + void setThresholdEnable(bool enable) { m_thresholdEnable = enable; } void setGate(int gate) { m_gate = gate; } private: double m_magsq; - double m_threshold; //!< squelch on magsq average - int m_gate; //!< power threshold gate in number of samples - int m_stepLength; //!< transition step length in number of samples - double m_stepDelta; //!< transition step unit by sample - int m_stepUpCounter; //!< step up transition samples counter - int m_stepDownCounter; //!< step down transition samples counter - int m_gateCounter; //!< threshold gate samples counter + double m_threshold; //!< squelch on magsq average + bool m_thresholdEnable; //!< enable squelch on power threshold + int m_gate; //!< power threshold gate in number of samples + int m_stepLength; //!< transition step length in number of samples + double m_stepDelta; //!< transition step unit by sample + int m_stepUpCounter; //!< step up transition samples counter + int m_stepDownCounter; //!< step down transition samples counter + int m_gateCounter; //!< threshold gate samples counter }; class MagAGC : public AGC @@ -56,15 +58,19 @@ class MagAGC : public AGC public: MagAGC(int historySize, double R, double threshold); virtual ~MagAGC(); + void setSquared(bool squared) { m_squared = squared; } void resize(int historySize, Real R); virtual void feed(Complex& ci); double feedAndGetValue(const Complex& ci); Real getMagSq() const { return m_magsq; } void setThreshold(double threshold) { m_threshold = threshold; } + void setThresholdEnable(bool enable); void setGate(int gate) { m_gate = gate; } private: - double m_magsq; + bool m_squared; //!< use squared magnitude (power) to compute AGC value + double m_magsq; //!< current squared magnitude (power) double m_threshold; //!< squelch on magsq average + bool m_thresholdEnable; //!< enable squelch on power threshold int m_gate; //!< power threshold gate in number of samples int m_stepLength; //!< transition step length in number of samples double m_stepDelta; //!< transition step unit by sample