mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-25 17:28:50 -05:00
Full CTCSS support in NFM demod
This commit is contained in:
parent
471364f540
commit
56d51e9fef
@ -19,6 +19,7 @@
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
#include "nfmdemod.h"
|
||||
#include "nfmdemodgui.h"
|
||||
#include "audio/audiooutput.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "dsp/pidcontroller.h"
|
||||
@ -28,6 +29,7 @@
|
||||
MESSAGE_CLASS_DEFINITION(NFMDemod::MsgConfigureNFMDemod, Message)
|
||||
|
||||
NFMDemod::NFMDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
|
||||
m_ctcssIndex(0),
|
||||
m_sampleCount(0),
|
||||
m_sampleSink(sampleSink),
|
||||
m_audioFifo(audioFifo)
|
||||
@ -49,7 +51,7 @@ NFMDemod::NFMDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
|
||||
m_agcLevel = 0.003;
|
||||
m_AGC.resize(4096, m_agcLevel, 0, 0.1*m_agcLevel);
|
||||
|
||||
m_ctcssDetector.setCoefficients(1200, 6000.0); // 0.2s detection rate
|
||||
m_ctcssDetector.setCoefficients(3000, 6000.0); // 0.5s / 2 Hz resolution
|
||||
}
|
||||
|
||||
NFMDemod::~NFMDemod()
|
||||
@ -112,7 +114,8 @@ void NFMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iter
|
||||
m_squelchState = m_running.m_audioSampleRate/ 20;
|
||||
|
||||
qint16 sample;
|
||||
if(m_squelchState > 0) {
|
||||
if(m_squelchState > 0)
|
||||
{
|
||||
m_squelchState--;
|
||||
|
||||
m_AGC.feed(abs(ci));
|
||||
@ -166,16 +169,39 @@ void NFMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iter
|
||||
|
||||
if (m_ctcssDetector.getDetectedTone(maxToneIndex))
|
||||
{
|
||||
std::cerr << "CTCSS tone detected: " << m_ctcssDetector.getToneSet()[maxToneIndex] << std::endl;
|
||||
if (maxToneIndex+1 != m_ctcssIndex) {
|
||||
m_nfmDemodGUI->setCtcssFreq(m_ctcssDetector.getToneSet()[maxToneIndex]);
|
||||
m_ctcssIndex = maxToneIndex+1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_ctcssIndex != 0) {
|
||||
m_nfmDemodGUI->setCtcssFreq(0);
|
||||
m_ctcssIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
demod = m_bandpass.filter(demod);
|
||||
demod *= m_running.m_volume;
|
||||
sample = demod * ((1<<16)/301); // denominator = bandpass filter number of taps
|
||||
if (m_ctcssIndexSelected && (m_ctcssIndexSelected != m_ctcssIndex))
|
||||
{
|
||||
sample = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
demod = m_bandpass.filter(demod);
|
||||
demod *= m_running.m_volume;
|
||||
sample = demod * ((1<<15)/301); // denominator = bandpass filter number of taps
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_ctcssIndex != 0) {
|
||||
m_nfmDemodGUI->setCtcssFreq(0);
|
||||
m_ctcssIndex = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
m_AGC.close();
|
||||
sample = 0;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "util/message.h"
|
||||
|
||||
class AudioFifo;
|
||||
class NFMDemodGUI;
|
||||
|
||||
class NFMDemod : public SampleSink {
|
||||
public:
|
||||
@ -44,6 +45,19 @@ public:
|
||||
void stop();
|
||||
bool handleMessage(Message* cmd);
|
||||
|
||||
void registerGUI(NFMDemodGUI *nfmDemodGUI) {
|
||||
m_nfmDemodGUI = nfmDemodGUI;
|
||||
}
|
||||
|
||||
const Real *getCtcssToneSet(int& nbTones) const {
|
||||
nbTones = m_ctcssDetector.getNTones();
|
||||
return m_ctcssDetector.getToneSet();
|
||||
}
|
||||
|
||||
void setSelectedCtcssIndex(int selectedCtcssIndex) {
|
||||
m_ctcssIndexSelected = selectedCtcssIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
class MsgConfigureNFMDemod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
@ -92,6 +106,7 @@ private:
|
||||
Real m_afBandwidth;
|
||||
Real m_squelch;
|
||||
Real m_volume;
|
||||
int m_ctcssIndex;
|
||||
quint32 m_audioSampleRate;
|
||||
|
||||
Config() :
|
||||
@ -101,6 +116,7 @@ private:
|
||||
m_afBandwidth(-1),
|
||||
m_squelch(0),
|
||||
m_volume(0),
|
||||
m_ctcssIndex(0),
|
||||
m_audioSampleRate(0)
|
||||
{ }
|
||||
};
|
||||
@ -116,6 +132,8 @@ private:
|
||||
Lowpass<Real> m_lowpass;
|
||||
Bandpass<Real> m_bandpass;
|
||||
CTCSSDetector m_ctcssDetector;
|
||||
int m_ctcssIndex; // 0 for nothing detected
|
||||
int m_ctcssIndexSelected;
|
||||
int m_sampleCount;
|
||||
|
||||
Real m_squelchLevel;
|
||||
@ -136,6 +154,8 @@ private:
|
||||
AudioFifo* m_audioFifo;
|
||||
SampleVector m_sampleBuffer;
|
||||
|
||||
NFMDemodGUI *m_nfmDemodGUI;
|
||||
|
||||
void apply();
|
||||
};
|
||||
|
||||
|
@ -151,6 +151,12 @@ void NFMDemodGUI::on_squelch_valueChanged(int value)
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void NFMDemodGUI::on_ctcss_currentIndexChanged(int index)
|
||||
{
|
||||
if (m_nfmDemod != NULL) {
|
||||
m_nfmDemod->setSelectedCtcssIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void NFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
{
|
||||
@ -182,7 +188,19 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
||||
|
||||
m_audioFifo = new AudioFifo(4, 48000);
|
||||
m_nullSink = new NullSink();
|
||||
|
||||
m_nfmDemod = new NFMDemod(m_audioFifo, m_nullSink);
|
||||
m_nfmDemod->registerGUI(this);
|
||||
|
||||
int ctcss_nbTones;
|
||||
const Real *ctcss_tones = m_nfmDemod->getCtcssToneSet(ctcss_nbTones);
|
||||
|
||||
ui->ctcss->addItem("--");
|
||||
|
||||
for (int i=0; i<ctcss_nbTones; i++) {
|
||||
ui->ctcss->addItem(QString("%1").arg(ctcss_tones[i]));
|
||||
}
|
||||
|
||||
m_channelizer = new Channelizer(m_nfmDemod);
|
||||
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
|
||||
m_pluginAPI->addAudioSource(m_audioFifo);
|
||||
@ -238,3 +256,15 @@ void NFMDemodGUI::enterEvent(QEvent*)
|
||||
m_channelMarker->setHighlighted(true);
|
||||
}
|
||||
|
||||
void NFMDemodGUI::setCtcssFreq(Real ctcssFreq)
|
||||
{
|
||||
if (ctcssFreq == 0)
|
||||
{
|
||||
ui->ctcssText->setText("--");
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->ctcssText->setText(QString("%1").arg(ctcssFreq));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "plugin/plugingui.h"
|
||||
#include "dsp/dsptypes.h"
|
||||
|
||||
class PluginAPI;
|
||||
class ChannelMarker;
|
||||
@ -32,6 +33,7 @@ public:
|
||||
bool deserialize(const QByteArray& data);
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
void setCtcssFreq(Real ctcssFreq);
|
||||
|
||||
private slots:
|
||||
void viewChanged();
|
||||
@ -41,6 +43,7 @@ private slots:
|
||||
void on_afBW_valueChanged(int value);
|
||||
void on_volume_valueChanged(int value);
|
||||
void on_squelch_valueChanged(int value);
|
||||
void on_ctcss_currentIndexChanged(int index);
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onMenuDoubleClicked();
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>302</width>
|
||||
<height>138</height>
|
||||
<height>151</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -19,7 +19,7 @@
|
||||
<x>35</x>
|
||||
<y>35</y>
|
||||
<width>242</width>
|
||||
<height>96</height>
|
||||
<height>111</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -81,19 +81,26 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<widget class="QLabel" name="squelchLabel">
|
||||
<property name="text">
|
||||
<string>Squelch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="afLabel">
|
||||
<property name="text">
|
||||
<string>AF Bandwidth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="rfBWLabel">
|
||||
<property name="text">
|
||||
<string>RF Bandwidth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSlider" name="squelch">
|
||||
<property name="minimum">
|
||||
@ -126,13 +133,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>RF Bandwidth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="afBWText">
|
||||
<property name="minimumSize">
|
||||
@ -149,6 +149,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="volumeLabel">
|
||||
<property name="text">
|
||||
<string>Volume</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSlider" name="afBW">
|
||||
<property name="minimum">
|
||||
@ -184,13 +191,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Volume</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="volumeText">
|
||||
<property name="minimumSize">
|
||||
@ -207,6 +207,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="deltaUnits">
|
||||
<property name="text">
|
||||
<string>Hz</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="ValueDial" name="deltaFrequency" native="true">
|
||||
<property name="sizePolicy">
|
||||
@ -238,10 +245,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="deltaUnits">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="ctcssLabel">
|
||||
<property name="text">
|
||||
<string>Hz</string>
|
||||
<string>CTCSS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="ctcss"/>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="ctcssText">
|
||||
<property name="text">
|
||||
<string>--</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
Loading…
Reference in New Issue
Block a user