diff --git a/plugins/channelrx/udpsrc/udpsrc.cpp b/plugins/channelrx/udpsrc/udpsrc.cpp
index 9d4e44aa1..cbbf94937 100644
--- a/plugins/channelrx/udpsrc/udpsrc.cpp
+++ b/plugins/channelrx/udpsrc/udpsrc.cpp
@@ -15,14 +15,15 @@
// along with this program. If not, see . //
///////////////////////////////////////////////////////////////////////////////////
-#include "udpsrc.h"
-
-#include
#include
#include
+
+#include "dsp/downchannelizer.h"
#include "dsp/dspengine.h"
+#include "util/db.h"
#include "udpsrcgui.h"
+#include "udpsrc.h"
MESSAGE_CLASS_DEFINITION(UDPSrc::MsgUDPSrcConfigure, Message)
MESSAGE_CLASS_DEFINITION(UDPSrc::MsgUDPSrcConfigureImmediate, Message)
@@ -38,6 +39,12 @@ UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, BasebandSampl
m_outMovingAverage(480, 1e-10),
m_inMovingAverage(480, 1e-10),
m_audioFifo(4, 24000),
+ m_squelch(1e-6),
+ m_squelchEnabled(true),
+ m_squelchOpen(false),
+ m_squelchOpenCount(0),
+ m_squelchCloseCount(0),
+ m_squelchThreshold(4800),
m_settingsMutex(QMutex::Recursive)
{
setObjectName("UDPSrc");
@@ -144,7 +151,7 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
{
Complex ci;
fftfilt::cmplx* sideband;
- Real l, r;
+ double l, r;
m_sampleBuffer.clear();
m_settingsMutex.lock();
@@ -157,17 +164,18 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
if(m_interpolator.decimate(&m_sampleDistanceRemain, c, &ci))
{
double inMagSq = ci.real()*ci.real() + ci.imag()*ci.imag();
- //m_magsq = (inMagSq*m_gain*m_gain) / (1<<30);
- m_outMovingAverage.feed((inMagSq*m_gain*m_gain) / (1<<30));
+
m_inMovingAverage.feed(inMagSq / (1<<30));
- m_magsq = m_outMovingAverage.average();
m_inMagsq = m_inMovingAverage.average();
- Sample s(ci.real() * m_gain, ci.imag() * m_gain);
- m_sampleBuffer.push_back(s);
+ Sample ss(ci.real(), ci.imag());
+ m_sampleBuffer.push_back(ss);
+
m_sampleDistanceRemain += m_inputSampleRate / m_outputSampleRate;
- if (m_sampleFormat == FormatLSB)
+ calculateSquelch(m_inMagsq);
+
+ if (m_sampleFormat == FormatLSB) // binaural LSB
{
int n_out = UDPFilter->runSSB(ci, &sideband, false);
@@ -175,13 +183,14 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
{
for (int i = 0; i < n_out; i++)
{
- l = sideband[i].real();
- r = sideband[i].imag();
- m_udpBuffer->write(Sample(l, r));
+ l = m_squelchOpen ? sideband[i].real() * m_gain : 0;
+ r = m_squelchOpen ? sideband[i].imag() * m_gain : 0;
+ m_udpBuffer->write(Sample(l, r));
+ m_outMovingAverage.feed((l*l + r*r) / (1<<30));
}
}
}
- if (m_sampleFormat == FormatUSB)
+ if (m_sampleFormat == FormatUSB) // binaural USB
{
int n_out = UDPFilter->runSSB(ci, &sideband, true);
@@ -189,23 +198,26 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
{
for (int i = 0; i < n_out; i++)
{
- l = sideband[i].real();
- r = sideband[i].imag();
+ l = m_squelchOpen ? sideband[i].real() * m_gain : 0;
+ r = m_squelchOpen ? sideband[i].imag() * m_gain : 0;
m_udpBuffer->write(Sample(l, r));
+ m_outMovingAverage.feed((l*l + r*r) / (1<<30));
}
}
}
else if (m_sampleFormat == FormatNFM)
{
- Real demod = 32768.0f * m_phaseDiscri.phaseDiscriminator(ci);
+ double demod = m_squelchOpen ? 32768.0 * m_phaseDiscri.phaseDiscriminator(ci) * m_gain : 0;
m_udpBuffer->write(Sample(demod, demod));
+ m_outMovingAverage.feed((demod * demod) / (1<<30));
}
else if (m_sampleFormat == FormatNFMMono)
{
- FixReal demod = (FixReal) (32768.0f * m_phaseDiscri.phaseDiscriminator(ci));
+ FixReal demod = m_squelchOpen ? (FixReal) (32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * m_gain) : 0;
m_udpBufferMono->write(demod);
+ m_outMovingAverage.feed((demod * demod) / 1073741824.0);
}
- else if (m_sampleFormat == FormatLSBMono)
+ else if (m_sampleFormat == FormatLSBMono) // Monaural LSB
{
int n_out = UDPFilter->runSSB(ci, &sideband, false);
@@ -213,12 +225,13 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
{
for (int i = 0; i < n_out; i++)
{
- l = (sideband[i].real() + sideband[i].imag()) * 0.7;
+ l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_gain : 0;
m_udpBufferMono->write(l);
+ m_outMovingAverage.feed((l * l) / (1<<30));
}
}
}
- else if (m_sampleFormat == FormatUSBMono)
+ else if (m_sampleFormat == FormatUSBMono) // Monaural USB
{
int n_out = UDPFilter->runSSB(ci, &sideband, true);
@@ -226,20 +239,35 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
{
for (int i = 0; i < n_out; i++)
{
- l = (sideband[i].real() + sideband[i].imag()) * 0.7;
+ l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_gain : 0;
m_udpBufferMono->write(l);
+ m_outMovingAverage.feed((l * l) / (1<<30));
}
}
}
else if (m_sampleFormat == FormatAMMono)
{
- FixReal demod = (FixReal) (32768.0f * sqrt(inMagSq) * m_gain);
+ FixReal demod = m_squelchOpen ? (FixReal) (32768.0f * sqrt(inMagSq) * m_gain) : 0;
m_udpBufferMono->write(demod);
+ m_outMovingAverage.feed((demod * demod) / (1<<30));
}
else // Raw I/Q samples
{
- m_udpBuffer->write(s);
+ if (m_squelchOpen)
+ {
+ Sample s(ci.real() * m_gain, ci.imag() * m_gain);
+ m_udpBuffer->write(s);
+ m_outMovingAverage.feed((inMagSq*m_gain*m_gain) / (1<<30));
+ }
+ else
+ {
+ Sample s(0, 0);
+ m_udpBuffer->write(s);
+ m_outMovingAverage.feed(0);
+ }
}
+
+ m_magsq = m_outMovingAverage.average();
}
}
@@ -320,13 +348,18 @@ bool UDPSrc::handleMessage(const Message& cmd)
m_volume = cfg.getVolume();
}
+ m_squelch = CalcDb::powerFromdB(cfg.getSquelchDB());
+ m_squelchEnabled = cfg.getSquelchEnabled();
+
m_settingsMutex.unlock();
qDebug() << "UDPSrc::handleMessage: MsgUDPSrcConfigureImmediate: "
<< " m_audioActive: " << m_audioActive
<< " m_audioStereo: " << m_audioStereo
<< " m_gain: " << m_gain
- << " m_volume: " << m_volume;
+ << " m_squelchEnabled: " << m_squelchEnabled
+ << " m_squelch: " << m_squelch
+ << " getSquelchDB: " << cfg.getSquelchDB();
return true;
@@ -384,8 +417,9 @@ bool UDPSrc::handleMessage(const Message& cmd)
m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
UDPFilter->create_filter(0.0, (m_rfBandwidth / 2.0) / m_outputSampleRate);
- m_inMovingAverage.resize(m_inputSampleRate * 0.01, 1e-10); // 10 ms
+ m_inMovingAverage.resize(m_outputSampleRate * 0.01, 1e-10); // 10 ms
m_outMovingAverage.resize(m_outputSampleRate * 0.01, 1e-10); // 10 ms
+ m_squelchThreshold = m_outputSampleRate * 0.05; // 50 ms
m_settingsMutex.unlock();
diff --git a/plugins/channelrx/udpsrc/udpsrc.h b/plugins/channelrx/udpsrc/udpsrc.h
index 0eb363841..b445f30ff 100644
--- a/plugins/channelrx/udpsrc/udpsrc.h
+++ b/plugins/channelrx/udpsrc/udpsrc.h
@@ -78,6 +78,7 @@ public:
void setSpectrum(MessageQueue* messageQueue, bool enabled);
double getMagSq() const { return m_magsq; }
double getInMagSq() const { return m_inMagsq; }
+ bool getSquelchOpen() const { return m_squelchOpen; }
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
virtual void start();
@@ -161,7 +162,7 @@ protected:
static MsgUDPSrcConfigureImmediate* create(
bool audioActive,
bool audioStereo,
- int boost,
+ int gain,
int volume,
Real squelchDB,
bool squelchEnabled)
@@ -169,7 +170,7 @@ protected:
return new MsgUDPSrcConfigureImmediate(
audioActive,
audioStereo,
- boost,
+ gain,
volume,
squelchDB,
squelchEnabled);
@@ -269,7 +270,53 @@ protected:
PhaseDiscriminators m_phaseDiscri;
+ Real m_squelch; //!< squared magnitude
+ bool m_squelchEnabled;
+ bool m_squelchOpen;
+ int m_squelchOpenCount;
+ int m_squelchCloseCount;
+ int m_squelchThreshold;
+
QMutex m_settingsMutex;
+
+ inline void calculateSquelch(double value)
+ {
+ if ((!m_squelchEnabled) || (value > m_squelch))
+ {
+ if (m_squelchOpenCount < m_squelchThreshold) {
+ m_squelchOpenCount++;
+ } else {
+ m_squelchCloseCount = m_squelchThreshold;
+ m_squelchOpen = true;
+ }
+ }
+ else
+ {
+ if (m_squelchCloseCount > 0) {
+ m_squelchCloseCount--;
+ } else {
+ m_squelchOpenCount = 0;
+ m_squelchOpen = false;
+ }
+ }
+ }
+
+ inline void initSquelch(bool open)
+ {
+ if (open)
+ {
+ m_squelchOpen = true;
+ m_squelchOpenCount = m_squelchThreshold;
+ m_squelchCloseCount = m_squelchThreshold;
+ }
+ else
+ {
+ m_squelchOpen = false;
+ m_squelchOpenCount = 0;
+ m_squelchCloseCount = 0;
+ }
+ }
+
};
#endif // INCLUDE_UDPSRC_H
diff --git a/plugins/channelrx/udpsrc/udpsrcgui.cpp b/plugins/channelrx/udpsrc/udpsrcgui.cpp
index d6c895433..4636ba028 100644
--- a/plugins/channelrx/udpsrc/udpsrcgui.cpp
+++ b/plugins/channelrx/udpsrc/udpsrcgui.cpp
@@ -172,7 +172,7 @@ bool UDPSrcGUI::deserialize(const QByteArray& data)
ui->udpPort->setText(QString("%1").arg(s32tmp));
d.readBlob(7, &bytetmp);
ui->spectrumGUI->deserialize(bytetmp);
- d.readS32(16, &s32tmp, 10);
+ d.readS32(8, &s32tmp, 10);
ui->gain->setValue(s32tmp);
ui->gainText->setText(tr("%1").arg(s32tmp/10.0, 0, 'f', 1));
d.readS32(9, &s32tmp, 0);
@@ -231,6 +231,12 @@ void UDPSrcGUI::tick()
ui->inputPower->setText(QString::number(inPowDb, 'f', 1));
}
+ if (m_udpSrc->getSquelchOpen()) {
+ ui->squelchLabel->setStyleSheet("QLabel { background-color : green; }");
+ } else {
+ ui->squelchLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
+ }
+
m_tickCount++;
}
@@ -265,6 +271,7 @@ UDPSrcGUI::UDPSrcGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget*
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
+ ui->squelchLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
ui->glSpectrum->setCenterFrequency(0);
ui->glSpectrum->setSampleRate(ui->sampleRate->text().toInt());