Frequency tracker: added squelch gate control

This commit is contained in:
f4exb 2019-05-05 13:19:00 +02:00
parent f63b0fe96c
commit cdf8a63294
13 changed files with 152 additions and 22 deletions

View File

@ -59,6 +59,7 @@ FreqTracker::FreqTracker(DeviceSourceAPI *deviceAPI) :
m_channelSampleRate(48000),
m_running(false),
m_squelchOpen(false),
m_squelchGate(0),
m_magsqSum(0.0f),
m_magsqPeak(0.0f),
m_magsqCount(0),
@ -182,19 +183,35 @@ void FreqTracker::processOneSample(Complex &ci)
if (m_magsq < m_squelchLevel)
{
if (m_squelchCount > 0) {
m_squelchCount--;
if (m_squelchGate > 0)
{
if (m_squelchCount > 0) {
m_squelchCount--;
}
m_squelchOpen = m_squelchCount >= m_squelchGate;
}
else
{
m_squelchOpen = false;
}
}
else
{
if (m_squelchCount < m_channelSampleRate / 10) {
m_squelchCount++;
if (m_squelchGate > 0)
{
if (m_squelchCount < 2*m_squelchGate) {
m_squelchCount++;
}
m_squelchOpen = m_squelchCount >= m_squelchGate;
}
else
{
m_squelchOpen = true;
}
}
m_squelchOpen = (m_squelchCount >= m_channelSampleRate / 20);
if (m_squelchOpen)
{
if (m_settings.m_trackerType == FreqTrackerSettings::TrackerFLL)
@ -412,6 +429,11 @@ void FreqTracker::applySettings(const FreqTrackerSettings& settings, bool force)
reverseAPIKeys.append("rrcRolloff");
updateInterpolator = true;
}
if ((m_settings.m_squelchGate != settings.m_squelchGate) || force)
{
reverseAPIKeys.append("squelchGate");
updateInterpolator = true;
}
if (settings.m_useReverseAPI)
{
@ -439,6 +461,7 @@ void FreqTracker::setInterpolator()
m_interpolatorDistanceRemain = 0;
m_interpolatorDistance = (Real) m_inputSampleRate / (Real) m_channelSampleRate;
m_rrcFilter->create_rrc_filter(m_settings.m_rfBandwidth / m_channelSampleRate, m_settings.m_rrcRolloff / 100.0);
m_squelchGate = (m_channelSampleRate / 100) * m_settings.m_squelchGate; // gate is given in 10s of ms at channel sample rate
m_settingsMutex.unlock();
}

View File

@ -214,6 +214,7 @@ private:
Real m_squelchLevel;
uint32_t m_squelchCount;
bool m_squelchOpen;
uint32_t m_squelchGate; //!< Squelch gate in samples
double m_magsq;
double m_magsqSum;
double m_magsqPeak;

View File

@ -232,6 +232,13 @@ void FreqTrackerGUI::on_squelch_valueChanged(int value)
applySettings();
}
void FreqTrackerGUI::on_squelchGate_valueChanged(int value)
{
ui->squelchGateText->setText(QString("%1").arg(value * 10.0f, 0, 'f', 0));
m_settings.m_squelchGate = value;
applySettings();
}
void FreqTrackerGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
@ -369,6 +376,8 @@ void FreqTrackerGUI::displaySettings()
ui->rrcRolloff->setValue(m_settings.m_rrcRolloff);
QString rolloffStr = QString::number(m_settings.m_rrcRolloff/100.0, 'f', 2);
ui->rrcRolloffText->setText(rolloffStr);
ui->squelchGateText->setText(QString("%1").arg(m_settings.m_squelchGate * 10.0f, 0, 'f', 0));
ui->squelchGate->setValue(m_settings.m_squelchGate);
blockApplySettings(false);
}

View File

@ -94,6 +94,7 @@ private slots:
void on_rrc_toggled(bool checked);
void on_rrcRolloff_valueChanged(int value);
void on_squelch_valueChanged(int value);
void on_squelchGate_valueChanged(int value);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void handleInputMessages();

View File

@ -624,6 +624,53 @@
</property>
</widget>
</item>
<item>
<widget class="QDial" name="squelchGate">
<property name="minimumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<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>0</number>
</property>
<property name="maximum">
<number>99</number>
</property>
<property name="pageStep">
<number>1</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>
</item>
</layout>

View File

@ -42,6 +42,7 @@ void FreqTrackerSettings::resetToDefaults()
m_pllPskOrder = 2; // BPSK
m_rrc = false;
m_rrcRolloff = 35;
m_squelchGate = 5; // 50 ms
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
@ -74,6 +75,7 @@ QByteArray FreqTrackerSettings::serialize() const
s.writeU32(18, m_reverseAPIPort);
s.writeU32(19, m_reverseAPIDeviceIndex);
s.writeU32(20, m_reverseAPIChannelIndex);
s.writeS32(21, m_squelchGate);
return s.final();
}
@ -136,6 +138,8 @@ bool FreqTrackerSettings::deserialize(const QByteArray& data)
m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp;
d.readU32(20, &utmp, 0);
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
d.readS32(21, &tmp, 5);
m_squelchGate = tmp < 0 ? 0 : tmp > 99 ? 99 : tmp;
return true;
}

View File

@ -47,6 +47,7 @@ struct FreqTrackerSettings
uint32_t m_pllPskOrder;
bool m_rrc;
uint32_t m_rrcRolloff; //!< in 100ths
int m_squelchGate; //!< in 10s of ms
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;

View File

@ -2783,8 +2783,9 @@ margin-bottom: 20px;
"type" : "string"
},
"alphaEMA" : {
"type" : "integer",
"description" : "Alpha factor for delta frequency EMA in %"
"type" : "number",
"format" : "float",
"description" : "Alpha factor for delta frequency EMA"
},
"tracking" : {
"type" : "integer",
@ -2806,6 +2807,10 @@ margin-bottom: 20px;
"type" : "integer",
"description" : "RRC filter rolloff factor in %"
},
"squelchGate" : {
"type" : "integer",
"description" : "Squelch trigger gate in 10s of ms"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
@ -24919,7 +24924,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2019-05-05T01:27:03.875+02:00
Generated 2019-05-05T11:13:49.637+02:00
</div>
</div>
</div>

View File

@ -20,8 +20,9 @@ FreqTrackerSettings:
title:
type: string
alphaEMA:
description: Alpha factor for delta frequency EMA in %
type: integer
description: Alpha factor for delta frequency EMA
type: number
format: float
tracking:
description: Tracking 1 for enabled 0 for disabled
type: integer
@ -37,6 +38,9 @@ FreqTrackerSettings:
rrcRolloff:
description: RRC filter rolloff factor in %
type: integer
squelchGate:
description: Squelch trigger gate in 10s of ms
type: integer
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer

View File

@ -38,6 +38,9 @@ FreqTrackerSettings:
rrcRolloff:
description: RRC filter rolloff factor in %
type: integer
squelchGate:
description: Squelch trigger gate in 10s of ms
type: integer
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer

View File

@ -2783,8 +2783,9 @@ margin-bottom: 20px;
"type" : "string"
},
"alphaEMA" : {
"type" : "integer",
"description" : "Alpha factor for delta frequency EMA in %"
"type" : "number",
"format" : "float",
"description" : "Alpha factor for delta frequency EMA"
},
"tracking" : {
"type" : "integer",
@ -2806,6 +2807,10 @@ margin-bottom: 20px;
"type" : "integer",
"description" : "RRC filter rolloff factor in %"
},
"squelchGate" : {
"type" : "integer",
"description" : "Squelch trigger gate in 10s of ms"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
@ -24919,7 +24924,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2019-05-05T01:27:03.875+02:00
Generated 2019-05-05T11:13:49.637+02:00
</div>
</div>
</div>

View File

@ -40,7 +40,7 @@ SWGFreqTrackerSettings::SWGFreqTrackerSettings() {
m_rgb_color_isSet = false;
title = nullptr;
m_title_isSet = false;
alpha_ema = 0;
alpha_ema = 0.0f;
m_alpha_ema_isSet = false;
tracking = 0;
m_tracking_isSet = false;
@ -52,6 +52,8 @@ SWGFreqTrackerSettings::SWGFreqTrackerSettings() {
m_rrc_isSet = false;
rrc_rolloff = 0;
m_rrc_rolloff_isSet = false;
squelch_gate = 0;
m_squelch_gate_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = nullptr;
@ -82,7 +84,7 @@ SWGFreqTrackerSettings::init() {
m_rgb_color_isSet = false;
title = new QString("");
m_title_isSet = false;
alpha_ema = 0;
alpha_ema = 0.0f;
m_alpha_ema_isSet = false;
tracking = 0;
m_tracking_isSet = false;
@ -94,6 +96,8 @@ SWGFreqTrackerSettings::init() {
m_rrc_isSet = false;
rrc_rolloff = 0;
m_rrc_rolloff_isSet = false;
squelch_gate = 0;
m_squelch_gate_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = new QString("");
@ -123,6 +127,7 @@ SWGFreqTrackerSettings::cleanup() {
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
@ -154,7 +159,7 @@ SWGFreqTrackerSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
::SWGSDRangel::setValue(&alpha_ema, pJson["alphaEMA"], "qint32", "");
::SWGSDRangel::setValue(&alpha_ema, pJson["alphaEMA"], "float", "");
::SWGSDRangel::setValue(&tracking, pJson["tracking"], "qint32", "");
@ -166,6 +171,8 @@ SWGFreqTrackerSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&rrc_rolloff, pJson["rrcRolloff"], "qint32", "");
::SWGSDRangel::setValue(&squelch_gate, pJson["squelchGate"], "qint32", "");
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
@ -228,6 +235,9 @@ SWGFreqTrackerSettings::asJsonObject() {
if(m_rrc_rolloff_isSet){
obj->insert("rrcRolloff", QJsonValue(rrc_rolloff));
}
if(m_squelch_gate_isSet){
obj->insert("squelchGate", QJsonValue(squelch_gate));
}
if(m_use_reverse_api_isSet){
obj->insert("useReverseAPI", QJsonValue(use_reverse_api));
}
@ -307,12 +317,12 @@ SWGFreqTrackerSettings::setTitle(QString* title) {
this->m_title_isSet = true;
}
qint32
float
SWGFreqTrackerSettings::getAlphaEma() {
return alpha_ema;
}
void
SWGFreqTrackerSettings::setAlphaEma(qint32 alpha_ema) {
SWGFreqTrackerSettings::setAlphaEma(float alpha_ema) {
this->alpha_ema = alpha_ema;
this->m_alpha_ema_isSet = true;
}
@ -367,6 +377,16 @@ SWGFreqTrackerSettings::setRrcRolloff(qint32 rrc_rolloff) {
this->m_rrc_rolloff_isSet = true;
}
qint32
SWGFreqTrackerSettings::getSquelchGate() {
return squelch_gate;
}
void
SWGFreqTrackerSettings::setSquelchGate(qint32 squelch_gate) {
this->squelch_gate = squelch_gate;
this->m_squelch_gate_isSet = true;
}
qint32
SWGFreqTrackerSettings::getUseReverseApi() {
return use_reverse_api;
@ -434,6 +454,7 @@ SWGFreqTrackerSettings::isSet(){
if(m_pll_psk_order_isSet){ isObjectUpdated = true; break;}
if(m_rrc_isSet){ isObjectUpdated = true; break;}
if(m_rrc_rolloff_isSet){ isObjectUpdated = true; break;}
if(m_squelch_gate_isSet){ isObjectUpdated = true; break;}
if(m_use_reverse_api_isSet){ isObjectUpdated = true; break;}
if(reverse_api_address != nullptr && *reverse_api_address != QString("")){ isObjectUpdated = true; break;}
if(m_reverse_api_port_isSet){ isObjectUpdated = true; break;}

View File

@ -60,8 +60,8 @@ public:
QString* getTitle();
void setTitle(QString* title);
qint32 getAlphaEma();
void setAlphaEma(qint32 alpha_ema);
float getAlphaEma();
void setAlphaEma(float alpha_ema);
qint32 getTracking();
void setTracking(qint32 tracking);
@ -78,6 +78,9 @@ public:
qint32 getRrcRolloff();
void setRrcRolloff(qint32 rrc_rolloff);
qint32 getSquelchGate();
void setSquelchGate(qint32 squelch_gate);
qint32 getUseReverseApi();
void setUseReverseApi(qint32 use_reverse_api);
@ -115,7 +118,7 @@ private:
QString* title;
bool m_title_isSet;
qint32 alpha_ema;
float alpha_ema;
bool m_alpha_ema_isSet;
qint32 tracking;
@ -133,6 +136,9 @@ private:
qint32 rrc_rolloff;
bool m_rrc_rolloff_isSet;
qint32 squelch_gate;
bool m_squelch_gate_isSet;
qint32 use_reverse_api;
bool m_use_reverse_api_isSet;