1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-27 02:09:14 -05:00

NFM demod: added adjustable squelch gate time (AGC attack) to adjust the length of transient elimination from default 50ms

This commit is contained in:
f4exb 2016-03-31 19:38:39 +02:00
parent ce20f21b08
commit 68ed0013ea
6 changed files with 91 additions and 9 deletions

View File

@ -48,6 +48,7 @@ NFMDemod::NFMDemod() :
m_config.m_inputFrequencyOffset = 0; m_config.m_inputFrequencyOffset = 0;
m_config.m_rfBandwidth = 12500; m_config.m_rfBandwidth = 12500;
m_config.m_afBandwidth = 3000; m_config.m_afBandwidth = 3000;
m_config.m_squelchGate = 5; // 10s of ms at 48000 Hz sample rate. Corresponds to 2400 for AGC attack
m_config.m_squelch = -30.0; m_config.m_squelch = -30.0;
m_config.m_volume = 1.0; m_config.m_volume = 1.0;
m_config.m_ctcssOn = false; m_config.m_ctcssOn = false;
@ -78,6 +79,7 @@ void NFMDemod::configure(MessageQueue* messageQueue,
Real rfBandwidth, Real rfBandwidth,
Real afBandwidth, Real afBandwidth,
Real volume, Real volume,
int squelchGate,
Real squelch, Real squelch,
bool ctcssOn, bool ctcssOn,
bool audioMute) bool audioMute)
@ -85,6 +87,7 @@ void NFMDemod::configure(MessageQueue* messageQueue,
Message* cmd = MsgConfigureNFMDemod::create(rfBandwidth, Message* cmd = MsgConfigureNFMDemod::create(rfBandwidth,
afBandwidth, afBandwidth,
volume, volume,
squelchGate,
squelch, squelch,
ctcssOn, ctcssOn,
audioMute); audioMute);
@ -295,6 +298,7 @@ bool NFMDemod::handleMessage(const Message& cmd)
m_config.m_rfBandwidth = cfg.getRFBandwidth(); m_config.m_rfBandwidth = cfg.getRFBandwidth();
m_config.m_afBandwidth = cfg.getAFBandwidth(); m_config.m_afBandwidth = cfg.getAFBandwidth();
m_config.m_volume = cfg.getVolume(); m_config.m_volume = cfg.getVolume();
m_config.m_squelchGate = cfg.getSquelchGate();
m_config.m_squelch = cfg.getSquelch(); m_config.m_squelch = cfg.getSquelch();
m_config.m_ctcssOn = cfg.getCtcssOn(); m_config.m_ctcssOn = cfg.getCtcssOn();
m_config.m_audioMute = cfg.getAudioMute(); m_config.m_audioMute = cfg.getAudioMute();
@ -304,6 +308,7 @@ bool NFMDemod::handleMessage(const Message& cmd)
qDebug() << "NFMDemod::handleMessage: MsgConfigureNFMDemod: m_rfBandwidth: " << m_config.m_rfBandwidth qDebug() << "NFMDemod::handleMessage: MsgConfigureNFMDemod: m_rfBandwidth: " << m_config.m_rfBandwidth
<< " m_afBandwidth: " << m_config.m_afBandwidth << " m_afBandwidth: " << m_config.m_afBandwidth
<< " m_volume: " << m_config.m_volume << " m_volume: " << m_config.m_volume
<< " m_squelchGate" << m_config.m_squelchGate
<< " m_squelch: " << m_config.m_squelch << " m_squelch: " << m_config.m_squelch
<< " m_ctcssOn: " << m_config.m_ctcssOn << " m_ctcssOn: " << m_config.m_ctcssOn
<< " m_audioMute: " << m_config.m_audioMute; << " m_audioMute: " << m_config.m_audioMute;
@ -345,6 +350,12 @@ void NFMDemod::apply()
m_settingsMutex.unlock(); m_settingsMutex.unlock();
} }
if (m_config.m_squelchGate != m_running.m_squelchGate)
{
m_agcAttack = 480 * m_config.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate
m_AGC.resize(m_agcAttack, m_agcLevel);
}
if (m_config.m_squelch != m_running.m_squelch) if (m_config.m_squelch != m_running.m_squelch)
{ {
// input is a value in tenths of dB // input is a value in tenths of dB
@ -357,6 +368,7 @@ void NFMDemod::apply()
m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset; m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset;
m_running.m_rfBandwidth = m_config.m_rfBandwidth; m_running.m_rfBandwidth = m_config.m_rfBandwidth;
m_running.m_afBandwidth = m_config.m_afBandwidth; m_running.m_afBandwidth = m_config.m_afBandwidth;
m_running.m_squelchGate = m_config.m_squelchGate;
m_running.m_squelch = m_config.m_squelch; m_running.m_squelch = m_config.m_squelch;
m_running.m_volume = m_config.m_volume; m_running.m_volume = m_config.m_volume;
m_running.m_audioSampleRate = m_config.m_audioSampleRate; m_running.m_audioSampleRate = m_config.m_audioSampleRate;

View File

@ -44,6 +44,7 @@ public:
Real rfBandwidth, Real rfBandwidth,
Real afBandwidth, Real afBandwidth,
Real volume, Real volume,
int squelchGate,
Real squelch, Real squelch,
bool ctcssOn, bool ctcssOn,
bool audioMute); bool audioMute);
@ -76,7 +77,8 @@ private:
public: public:
Real getRFBandwidth() const { return m_rfBandwidth; } Real getRFBandwidth() const { return m_rfBandwidth; }
Real getAFBandwidth() const { return m_afBandwidth; } Real getAFBandwidth() const { return m_afBandwidth; }
Real getVolume() const { return m_volume; } Real getVolume() const { return m_volume; }\
int getSquelchGate() const { return m_squelchGate; }
Real getSquelch() const { return m_squelch; } Real getSquelch() const { return m_squelch; }
bool getCtcssOn() const { return m_ctcssOn; } bool getCtcssOn() const { return m_ctcssOn; }
bool getAudioMute() const { return m_audioMute; } bool getAudioMute() const { return m_audioMute; }
@ -84,17 +86,19 @@ private:
static MsgConfigureNFMDemod* create(Real rfBandwidth, static MsgConfigureNFMDemod* create(Real rfBandwidth,
Real afBandwidth, Real afBandwidth,
Real volume, Real volume,
int squelchGate,
Real squelch, Real squelch,
bool ctcssOn, bool ctcssOn,
bool audioMute) bool audioMute)
{ {
return new MsgConfigureNFMDemod(rfBandwidth, afBandwidth, volume, squelch, ctcssOn, audioMute); return new MsgConfigureNFMDemod(rfBandwidth, afBandwidth, volume, squelchGate, squelch, ctcssOn, audioMute);
} }
private: private:
Real m_rfBandwidth; Real m_rfBandwidth;
Real m_afBandwidth; Real m_afBandwidth;
Real m_volume; Real m_volume;
int m_squelchGate;
Real m_squelch; Real m_squelch;
bool m_ctcssOn; bool m_ctcssOn;
bool m_audioMute; bool m_audioMute;
@ -102,6 +106,7 @@ private:
MsgConfigureNFMDemod(Real rfBandwidth, MsgConfigureNFMDemod(Real rfBandwidth,
Real afBandwidth, Real afBandwidth,
Real volume, Real volume,
int squelchGate,
Real squelch, Real squelch,
bool ctcssOn, bool ctcssOn,
bool audioMute) : bool audioMute) :
@ -109,6 +114,7 @@ private:
m_rfBandwidth(rfBandwidth), m_rfBandwidth(rfBandwidth),
m_afBandwidth(afBandwidth), m_afBandwidth(afBandwidth),
m_volume(volume), m_volume(volume),
m_squelchGate(squelchGate),
m_squelch(squelch), m_squelch(squelch),
m_ctcssOn(ctcssOn), m_ctcssOn(ctcssOn),
m_audioMute(audioMute) m_audioMute(audioMute)
@ -131,6 +137,7 @@ private:
qint64 m_inputFrequencyOffset; qint64 m_inputFrequencyOffset;
Real m_rfBandwidth; Real m_rfBandwidth;
Real m_afBandwidth; Real m_afBandwidth;
int m_squelchGate;
Real m_squelch; Real m_squelch;
Real m_volume; Real m_volume;
bool m_ctcssOn; bool m_ctcssOn;
@ -143,6 +150,7 @@ private:
m_inputFrequencyOffset(0), m_inputFrequencyOffset(0),
m_rfBandwidth(-1), m_rfBandwidth(-1),
m_afBandwidth(-1), m_afBandwidth(-1),
m_squelchGate(50),
m_squelch(0), m_squelch(0),
m_volume(0), m_volume(0),
m_ctcssOn(false), m_ctcssOn(false),

View File

@ -57,6 +57,7 @@ void NFMDemodGUI::resetToDefaults()
ui->rfBW->setValue(4); ui->rfBW->setValue(4);
ui->afBW->setValue(3); ui->afBW->setValue(3);
ui->volume->setValue(20); ui->volume->setValue(20);
ui->squelchGate->setValue(5);
ui->squelch->setValue(-40); ui->squelch->setValue(-40);
ui->deltaFrequency->setValue(0); ui->deltaFrequency->setValue(0);
ui->ctcssOn->setChecked(false); ui->ctcssOn->setChecked(false);
@ -78,6 +79,7 @@ QByteArray NFMDemodGUI::serialize() const
s.writeS32(8, ui->ctcss->currentIndex()); s.writeS32(8, ui->ctcss->currentIndex());
s.writeBool(9, ui->ctcssOn->isChecked()); s.writeBool(9, ui->ctcssOn->isChecked());
s.writeBool(10, ui->audioMute->isChecked()); s.writeBool(10, ui->audioMute->isChecked());
s.writeS32(11, ui->squelchGate->value());
return s.final(); return s.final();
} }
@ -123,6 +125,8 @@ bool NFMDemodGUI::deserialize(const QByteArray& data)
ui->ctcssOn->setChecked(boolTmp); ui->ctcssOn->setChecked(boolTmp);
d.readBool(10, &boolTmp, false); d.readBool(10, &boolTmp, false);
ui->audioMute->setChecked(boolTmp); ui->audioMute->setChecked(boolTmp);
d.readS32(11, &tmp, 5);
ui->squelchGate->setValue(tmp);
blockApplySettings(false); blockApplySettings(false);
m_channelMarker.blockSignals(false); m_channelMarker.blockSignals(false);
@ -189,6 +193,12 @@ void NFMDemodGUI::on_volume_valueChanged(int value)
applySettings(); applySettings();
} }
void NFMDemodGUI::on_squelchGate_valueChanged(int value)
{
ui->squelchGateText->setText(QString("%1").arg(value * 10.0, 0, 'f', 0));
applySettings();
}
void NFMDemodGUI::on_squelch_valueChanged(int value) void NFMDemodGUI::on_squelch_valueChanged(int value)
{ {
ui->squelchText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1)); ui->squelchText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
@ -312,6 +322,7 @@ void NFMDemodGUI::applySettings()
m_rfBW[ui->rfBW->value()], m_rfBW[ui->rfBW->value()],
ui->afBW->value() * 1000.0, ui->afBW->value() * 1000.0,
ui->volume->value() / 10.0, ui->volume->value() / 10.0,
ui->squelchGate->value(), // in 10ths of ms
ui->squelch->value(), ui->squelch->value(),
ui->ctcssOn->isChecked(), ui->ctcssOn->isChecked(),
ui->audioMute->isChecked()); ui->audioMute->isChecked());

View File

@ -43,6 +43,7 @@ private slots:
void on_rfBW_valueChanged(int value); void on_rfBW_valueChanged(int value);
void on_afBW_valueChanged(int value); void on_afBW_valueChanged(int value);
void on_volume_valueChanged(int value); void on_volume_valueChanged(int value);
void on_squelchGate_valueChanged(int value);
void on_squelch_valueChanged(int value); void on_squelch_valueChanged(int value);
void on_ctcss_currentIndexChanged(int index); void on_ctcss_currentIndexChanged(int index);
void on_ctcssOn_toggled(bool checked); void on_ctcssOn_toggled(bool checked);

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>281</width> <width>279</width>
<height>162</height> <height>172</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
@ -25,7 +25,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>271</width> <width>271</width>
<height>131</height> <height>161</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -243,7 +243,7 @@
<item> <item>
<widget class="QLabel" name="volumeLabel"> <widget class="QLabel" name="volumeLabel">
<property name="text"> <property name="text">
<string>Volume</string> <string>Vol</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -289,14 +289,14 @@
<item> <item>
<widget class="QLabel" name="squelchLabel"> <widget class="QLabel" name="squelchLabel">
<property name="text"> <property name="text">
<string>Squelch</string> <string>Sq</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QSlider" name="squelch"> <widget class="QSlider" name="squelch">
<property name="toolTip"> <property name="toolTip">
<string>Squelch</string> <string>Squelch threshold (dB)</string>
</property> </property>
<property name="minimum"> <property name="minimum">
<number>-1000</number> <number>-1000</number>
@ -323,6 +323,9 @@
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>Squelch threshold (dB)</string>
</property>
<property name="text"> <property name="text">
<string>-15.0</string> <string>-15.0</string>
</property> </property>
@ -331,6 +334,53 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QDial" name="squelchGate">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Squelch gate (ms)</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>5</number>
</property>
<property name="sliderPosition">
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="squelchGateText">
<property name="minimumSize">
<size>
<width>25</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Squelch gate (ms)</string>
</property>
<property name="text">
<string>000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View File

@ -84,7 +84,7 @@
<item> <item>
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Version 1.1.5 - Copyright (C) 2015-2016 Edouard Griffiths, F4EXB. &lt;/p&gt;&lt;p&gt;Code at &lt;a href=&quot;https://github.com/f4exb/sdrangel&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/f4exb/sdrangel&lt;/span&gt;&lt;/a&gt; This is a complete redesign from RTL-SDRangelove at &lt;a href=&quot;https://github.com/hexameron/rtl-sdrangelove&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/hexameron/rtl-sdrangelove&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Many thanks to the original developers:&lt;/p&gt;&lt;p&gt;The osmocom developer team - especially horizon, Hoernchen &amp;amp; tnt.&lt;/p&gt;&lt;p&gt;Christian Daniel from maintech GmbH.&lt;/p&gt;&lt;p&gt;John Greb (hexameron) for the contributions in RTL-SDRangelove&lt;/p&gt;&lt;p&gt;The following rules apply to the SDRangel main application and libsdrbase:&lt;br/&gt;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; either version 2 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. You should have received a copy of the GNU General Public License along with this program. If not, see &lt;a href=&quot;http://www.gnu.org/licenses/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.gnu.org/licenses/&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;For the license of installed plugins, look into the plugin list.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Version 1.1.6 - Copyright (C) 2015-2016 Edouard Griffiths, F4EXB. &lt;/p&gt;&lt;p&gt;Code at &lt;a href=&quot;https://github.com/f4exb/sdrangel&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/f4exb/sdrangel&lt;/span&gt;&lt;/a&gt; This is a complete redesign from RTL-SDRangelove at &lt;a href=&quot;https://github.com/hexameron/rtl-sdrangelove&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/hexameron/rtl-sdrangelove&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Many thanks to the original developers:&lt;/p&gt;&lt;p&gt;The osmocom developer team - especially horizon, Hoernchen &amp;amp; tnt.&lt;/p&gt;&lt;p&gt;Christian Daniel from maintech GmbH.&lt;/p&gt;&lt;p&gt;John Greb (hexameron) for the contributions in RTL-SDRangelove&lt;/p&gt;&lt;p&gt;The following rules apply to the SDRangel main application and libsdrbase:&lt;br/&gt;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; either version 2 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. You should have received a copy of the GNU General Public License along with this program. If not, see &lt;a href=&quot;http://www.gnu.org/licenses/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.gnu.org/licenses/&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;For the license of installed plugins, look into the plugin list.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>