1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-02-03 09:44:01 -05:00

UDPSink plugin: implemented squelch gate control

This commit is contained in:
f4exb 2017-08-19 00:52:10 +02:00
parent 587d38665d
commit b3bd9967a4
8 changed files with 274 additions and 161 deletions

View File

@ -411,6 +411,7 @@ void UDPSrc::apply(bool force)
if ((m_config.m_squelchGate != m_running.m_squelchGate) || force) if ((m_config.m_squelchGate != m_running.m_squelchGate) || force)
{ {
m_squelchThreshold = m_config.m_outputSampleRate * m_config.m_squelchGate; m_squelchThreshold = m_config.m_outputSampleRate * m_config.m_squelchGate;
initSquelch(m_squelchOpen);
} }
if ((m_config.m_udpAddressStr != m_running.m_udpAddressStr) || force) if ((m_config.m_udpAddressStr != m_running.m_udpAddressStr) || force)

View File

@ -106,6 +106,7 @@ QByteArray UDPSrcGUI::serialize() const
s.writeBool(14, m_audioStereo); s.writeBool(14, m_audioStereo);
s.writeS32(15, m_fmDeviation); s.writeS32(15, m_fmDeviation);
s.writeS32(16, ui->squelch->value()); s.writeS32(16, ui->squelch->value());
s.writeS32(17, ui->squelchGate->value());
return s.final(); return s.final();
} }
@ -193,8 +194,11 @@ bool UDPSrcGUI::deserialize(const QByteArray& data)
d.readS32(16, &s32tmp, -60); d.readS32(16, &s32tmp, -60);
ui->squelch->setValue(s32tmp); ui->squelch->setValue(s32tmp);
ui->squelchText->setText(tr("%1").arg(s32tmp*1.0, 0, 'f', 0)); ui->squelchText->setText(tr("%1").arg(s32tmp*1.0, 0, 'f', 0));
d.readS32(17, &s32tmp, 5);
ui->squelchGate->setValue(s32tmp);
ui->squelchGateText->setText(tr("%1").arg(s32tmp*10.0, 0, 'f', 0));
blockApplySettings(false); blockApplySettings(false);
m_channelMarker.blockSignals(false); m_channelMarker.blockSignals(false);
applySettingsImmediate(true); applySettingsImmediate(true);

View File

@ -550,68 +550,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="GainLayout">
<item>
<widget class="QLabel" name="gainLabel">
<property name="text">
<string>Gain</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="gain">
<property name="toolTip">
<string>Output linear gain</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gainText">
<property name="minimumSize">
<size>
<width>28</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Output linear gain</string>
</property>
<property name="text">
<string>00.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="7" column="1">
<widget class="QPushButton" name="applyBtn">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Apply text input and/or samples format</string>
</property>
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
<item row="8" column="1"> <item row="8" column="1">
<layout class="QHBoxLayout" name="SquelchLayout"> <layout class="QHBoxLayout" name="SquelchLayout">
<item> <item>
@ -711,6 +649,68 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="7" column="1">
<layout class="QHBoxLayout" name="GainLayout">
<item>
<widget class="QLabel" name="gainLabel">
<property name="text">
<string>Gain</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="gain">
<property name="toolTip">
<string>Output linear gain</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gainText">
<property name="minimumSize">
<size>
<width>28</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Output linear gain</string>
</property>
<property name="text">
<string>00.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="applyBtn">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Apply text input and/or samples format</string>
</property>
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="spectrumBox" native="true"> <widget class="QWidget" name="spectrumBox" native="true">

View File

@ -266,6 +266,7 @@ bool UDPSink::handleMessage(const Message& cmd)
m_config.m_channelMute = cfg.getChannelMute(); m_config.m_channelMute = cfg.getChannelMute();
m_config.m_gain = cfg.getGain(); m_config.m_gain = cfg.getGain();
m_config.m_squelch = CalcDb::powerFromdB(cfg.getSquelchDB()); m_config.m_squelch = CalcDb::powerFromdB(cfg.getSquelchDB());
m_config.m_squelchGate = cfg.getSquelchGate();
m_config.m_squelchEnabled = cfg.getSquelchEnabled(); m_config.m_squelchEnabled = cfg.getSquelchEnabled();
apply(cfg.getForce()); apply(cfg.getForce());
@ -280,6 +281,7 @@ bool UDPSink::handleMessage(const Message& cmd)
<< " m_channelMute: " << m_config.m_channelMute << " m_channelMute: " << m_config.m_channelMute
<< " m_gain: " << m_config.m_gain << " m_gain: " << m_config.m_gain
<< " squelchDB: " << cfg.getSquelchDB() << " squelchDB: " << cfg.getSquelchDB()
<< " m_squelchGate: " << m_config.m_squelchGate
<< " m_squelch: " << m_config.m_squelch << " m_squelch: " << m_config.m_squelch
<< " m_squelchEnabled: " << m_config.m_squelchEnabled; << " m_squelchEnabled: " << m_config.m_squelchEnabled;
@ -378,6 +380,7 @@ void UDPSink::configure(MessageQueue* messageQueue,
bool channelMute, bool channelMute,
Real gain, Real gain,
Real squelchDB, Real squelchDB,
Real squelchGate,
bool squelchEnabled, bool squelchEnabled,
bool force) bool force)
{ {
@ -390,6 +393,7 @@ void UDPSink::configure(MessageQueue* messageQueue,
channelMute, channelMute,
gain, gain,
squelchDB, squelchDB,
squelchGate,
squelchEnabled, squelchEnabled,
force); force);
messageQueue->push(cmd); messageQueue->push(cmd);
@ -439,10 +443,17 @@ void UDPSink::apply(bool force)
m_levelSum = 0.0f; m_levelSum = 0.0f;
m_udpHandler.resizeBuffer(m_config.m_inputSampleRate); m_udpHandler.resizeBuffer(m_config.m_inputSampleRate);
m_inMovingAverage.resize(m_config.m_inputSampleRate * 0.01, 1e-10); // 10 ms m_inMovingAverage.resize(m_config.m_inputSampleRate * 0.01, 1e-10); // 10 ms
m_squelchThreshold = m_config.m_inputSampleRate * 0.1; // 100 ms m_squelchThreshold = m_config.m_inputSampleRate * m_config.m_squelchGate;
initSquelch(m_squelchOpen);
m_settingsMutex.unlock(); m_settingsMutex.unlock();
} }
if ((m_config.m_squelchGate != m_running.m_squelchGate) || force)
{
m_squelchThreshold = m_config.m_outputSampleRate * m_config.m_squelchGate;
initSquelch(m_squelchOpen);
}
if ((m_config.m_udpAddressStr != m_running.m_udpAddressStr) || if ((m_config.m_udpAddressStr != m_running.m_udpAddressStr) ||
(m_config.m_udpPort != m_running.m_udpPort) || force) (m_config.m_udpPort != m_running.m_udpPort) || force)
{ {

View File

@ -69,6 +69,7 @@ public:
bool channelMute, bool channelMute,
Real gain, Real gain,
Real squelchDB, Real squelchDB,
Real squelchGate,
bool squelchEnabled, bool squelchEnabled,
bool force = false); bool force = false);
void setSpectrum(MessageQueue* messageQueue, bool enabled); void setSpectrum(MessageQueue* messageQueue, bool enabled);
@ -97,6 +98,7 @@ private:
bool getChannelMute() const { return m_channelMute; } bool getChannelMute() const { return m_channelMute; }
Real getGain() const { return m_gain; } Real getGain() const { return m_gain; }
Real getSquelchDB() const { return m_squelchDB; } Real getSquelchDB() const { return m_squelchDB; }
Real getSquelchGate() const { return m_squelchGate; }
bool getSquelchEnabled() const { return m_squelchEnabled; } bool getSquelchEnabled() const { return m_squelchEnabled; }
bool getForce() const { return m_force; } bool getForce() const { return m_force; }
@ -110,6 +112,7 @@ private:
bool channelMute, bool channelMute,
Real gain, Real gain,
Real squelchDB, Real squelchDB,
Real squelchGate,
bool squelchEnabled, bool squelchEnabled,
bool force) bool force)
{ {
@ -122,6 +125,7 @@ private:
channelMute, channelMute,
gain, gain,
squelchDB, squelchDB,
squelchGate,
squelchEnabled, squelchEnabled,
force); force);
} }
@ -136,6 +140,7 @@ private:
bool m_channelMute; bool m_channelMute;
Real m_gain; Real m_gain;
Real m_squelchDB; Real m_squelchDB;
Real m_squelchGate;
bool m_squelchEnabled; bool m_squelchEnabled;
bool m_force; bool m_force;
@ -148,6 +153,7 @@ private:
bool channelMute, bool channelMute,
Real gain, Real gain,
Real squelchDB, Real squelchDB,
Real squelchGate,
bool squelchEnabled, bool squelchEnabled,
bool force) : bool force) :
Message(), Message(),
@ -160,6 +166,7 @@ private:
m_channelMute(channelMute), m_channelMute(channelMute),
m_gain(gain), m_gain(gain),
m_squelchDB(squelchDB), m_squelchDB(squelchDB),
m_squelchGate(squelchGate),
m_squelchEnabled(squelchEnabled), m_squelchEnabled(squelchEnabled),
m_force(force) m_force(force)
{ } { }
@ -213,6 +220,7 @@ private:
bool m_channelMute; bool m_channelMute;
Real m_gain; Real m_gain;
Real m_squelch; //!< squared magnitude Real m_squelch; //!< squared magnitude
Real m_squelchGate; //!< seconds
bool m_squelchEnabled; bool m_squelchEnabled;
QString m_udpAddressStr; QString m_udpAddressStr;
@ -229,6 +237,7 @@ private:
m_channelMute(false), m_channelMute(false),
m_gain(1.0), m_gain(1.0),
m_squelch(-50.0), m_squelch(-50.0),
m_squelchGate(0.05),
m_squelchEnabled(true), m_squelchEnabled(true),
m_udpAddressStr("127.0.0.1"), m_udpAddressStr("127.0.0.1"),
m_udpPort(9999) m_udpPort(9999)
@ -289,21 +298,41 @@ private:
{ {
if ((!m_running.m_squelchEnabled) || (value > m_running.m_squelch)) if ((!m_running.m_squelchEnabled) || (value > m_running.m_squelch))
{ {
if (m_squelchOpenCount < m_squelchThreshold) { if (m_squelchThreshold == 0)
m_squelchOpenCount++; {
} else {
m_squelchCloseCount = m_squelchThreshold;
m_squelchOpen = true; m_squelchOpen = true;
} }
else
{
if (m_squelchOpenCount < m_squelchThreshold)
{
m_squelchOpenCount++;
}
else
{
m_squelchCloseCount = m_squelchThreshold;
m_squelchOpen = true;
}
}
} }
else else
{ {
if (m_squelchCloseCount > 0) { if (m_squelchThreshold == 0)
m_squelchCloseCount--; {
} else {
m_squelchOpenCount = 0;
m_squelchOpen = false; m_squelchOpen = false;
} }
else
{
if (m_squelchCloseCount > 0)
{
m_squelchCloseCount--;
}
else
{
m_squelchOpenCount = 0;
m_squelchOpen = false;
}
}
} }
} }

View File

@ -94,6 +94,7 @@ QByteArray UDPSinkGUI::serialize() const
s.writeU32(12, m_channelMarker.getColor().rgb()); s.writeU32(12, m_channelMarker.getColor().rgb());
s.writeString(13, m_channelMarker.getTitle()); s.writeString(13, m_channelMarker.getTitle());
s.writeS32(14, ui->squelch->value()); s.writeS32(14, ui->squelch->value());
s.writeS32(15, ui->squelchGate->value());
return s.final(); return s.final();
} }
@ -180,6 +181,9 @@ bool UDPSinkGUI::deserialize(const QByteArray& data)
d.readS32(14, &s32tmp, -60); d.readS32(14, &s32tmp, -60);
ui->squelch->setValue(s32tmp); ui->squelch->setValue(s32tmp);
ui->squelchText->setText(tr("%1").arg(s32tmp*1.0, 0, 'f', 0)); ui->squelchText->setText(tr("%1").arg(s32tmp*1.0, 0, 'f', 0));
d.readS32(15, &s32tmp, 5);
ui->squelchGate->setValue(s32tmp);
ui->squelchGateText->setText(tr("%1").arg(s32tmp*10.0, 0, 'f', 0));
blockApplySettings(false); blockApplySettings(false);
m_channelMarker.blockSignals(false); m_channelMarker.blockSignals(false);
@ -398,6 +402,7 @@ void UDPSinkGUI::applySettings(bool force)
ui->channelMute->isChecked(), ui->channelMute->isChecked(),
ui->gain->value() / 10.0f, ui->gain->value() / 10.0f,
ui->squelch->value() * 1.0f, ui->squelch->value() * 1.0f,
ui->squelchGate->value() * 0.01f,
ui->squelch->value() != -100, ui->squelch->value() != -100,
force); force);
@ -409,6 +414,7 @@ void UDPSinkGUI::displaySettings()
{ {
ui->gainText->setText(tr("%1").arg(ui->gain->value()/10.0, 0, 'f', 1)); ui->gainText->setText(tr("%1").arg(ui->gain->value()/10.0, 0, 'f', 1));
ui->squelchText->setText(tr("%1").arg(ui->squelch->value()*1.0, 0, 'f', 0)); ui->squelchText->setText(tr("%1").arg(ui->squelch->value()*1.0, 0, 'f', 0));
ui->squelchGateText->setText(tr("%1").arg(ui->squelchGate->value()*10.0, 0, 'f', 0));
} }
void UDPSinkGUI::channelMarkerChanged() void UDPSinkGUI::channelMarkerChanged()
@ -478,6 +484,12 @@ void UDPSinkGUI::on_squelch_valueChanged(int value)
applySettings(); applySettings();
} }
void UDPSinkGUI::on_squelchGate_valueChanged(int value)
{
ui->squelchGateText->setText(tr("%1").arg(value*10.0, 0, 'f', 0));
applySettings();
}
void UDPSinkGUI::on_channelMute_toggled(bool checked __attribute__((unused))) void UDPSinkGUI::on_channelMute_toggled(bool checked __attribute__((unused)))
{ {
applySettings(); applySettings();

View File

@ -69,6 +69,7 @@ private slots:
void onMenuDoubleClicked(); void onMenuDoubleClicked();
void on_gain_valueChanged(int value); void on_gain_valueChanged(int value);
void on_squelch_valueChanged(int value); void on_squelch_valueChanged(int value);
void on_squelchGate_valueChanged(int value);
void on_channelMute_toggled(bool checked); void on_channelMute_toggled(bool checked);
void on_resetUDPReadIndex_clicked(); void on_resetUDPReadIndex_clicked();
void tick(); void tick();

View File

@ -6,13 +6,13 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>348</width> <width>342</width>
<height>400</height> <height>400</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>316</width> <width>342</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
@ -48,7 +48,7 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>330</width> <width>340</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
@ -111,72 +111,15 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="squelchLabel"> <widget class="QPushButton" name="applyBtn">
<property name="text"> <property name="enabled">
<string>Sq</string> <bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QDial" name="squelch">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Power squelch threshold (dB)</string> <string>Apply text input and/or samples format</string>
</property>
<property name="minimum">
<number>-100</number>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>-50</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="squelchText">
<property name="minimumSize">
<size>
<width>22</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Power squelch threshold (dB)</string>
</property> </property>
<property name="text"> <property name="text">
<string>-00</string> <string>Apply</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="inputPower">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Input power (dB) to which squelch applies</string>
</property>
<property name="text">
<string>-100.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
</widget> </widget>
</item> </item>
@ -228,6 +171,19 @@
</item> </item>
<item row="0" column="2"> <item row="0" column="2">
<layout class="QHBoxLayout" name="ChannelPowerLayout"> <layout class="QHBoxLayout" name="ChannelPowerLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QLabel" name="channelPower"> <widget class="QLabel" name="channelPower">
<property name="minimumSize"> <property name="minimumSize">
@ -250,19 +206,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QToolButton" name="channelMute"> <widget class="QToolButton" name="channelMute">
<property name="toolTip"> <property name="toolTip">
@ -408,6 +351,38 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="inputPower">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Input power (dB) to which squelch applies</string>
</property>
<property name="text">
<string>-100.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="1" column="0" rowspan="2"> <item row="1" column="0" rowspan="2">
@ -715,17 +690,97 @@
</layout> </layout>
</item> </item>
<item row="4" column="2"> <item row="4" column="2">
<widget class="QPushButton" name="applyBtn"> <layout class="QHBoxLayout" name="SquelchLayout">
<property name="enabled"> <item>
<bool>false</bool> <widget class="QLabel" name="squelchLabel">
</property> <property name="text">
<property name="toolTip"> <string>Sq</string>
<string>Apply text input and/or samples format</string> </property>
</property> </widget>
<property name="text"> </item>
<string>Apply</string> <item>
</property> <widget class="QSlider" name="squelch">
</widget> <property name="toolTip">
<string>Power squelch threshold (dB)</string>
</property>
<property name="minimum">
<number>-100</number>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>-50</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="squelchText">
<property name="minimumSize">
<size>
<width>22</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Power squelch threshold (dB)</string>
</property>
<property name="text">
<string>-00</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDial" name="squelchGate">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Squelch gate (ms)</string>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="squelchGateText">
<property name="minimumSize">
<size>
<width>24</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>
</item> </item>
</layout> </layout>
</widget> </widget>