NFM Demod: added signal meter. Corrected squelch. Turned frequency dial green

This commit is contained in:
f4exb 2016-12-05 02:09:08 +01:00
parent c31846a334
commit 7c3cebf2e1
11 changed files with 132 additions and 48 deletions

View File

@ -234,7 +234,7 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget
connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGreenYellow));
ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenYellow);
//m_channelMarker = new ChannelMarker(this);

View File

@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>303</width>
<width>302</width>
<height>170</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>302</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<family>Sans Serif</family>
@ -25,15 +31,15 @@
<widget class="QWidget" name="settingsContainer" native="true">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>280</width>
<x>0</x>
<y>0</y>
<width>300</width>
<height>131</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>280</width>
<width>300</width>
<height>0</height>
</size>
</property>
@ -61,8 +67,8 @@
</property>
<property name="icon">
<iconset>
<selectedoff>:/plus.png</selectedoff>
<selectedon>:/minus.png</selectedon>
<selectedoff>:/plusrx.png</selectedoff>
<selectedon>:/minusrx.png</selectedon>
</iconset>
</property>
<property name="checkable">
@ -366,26 +372,6 @@
</customwidgets>
<resources>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -38,6 +38,9 @@ NFMDemod::NFMDemod() :
m_agcAttack(2400),
m_audioMute(false),
m_squelchOpen(false),
m_magsqSum(0.0f),
m_magsqPeak(0.0f),
m_magsqCount(0),
m_afSquelch(2, afSqTones),
m_audioFifo(4, 48000),
m_fmExcursion(2400),
@ -146,6 +149,16 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
qint16 sample;
m_AGC.feed(ci);
Real magsq = m_AGC.getMagSq();
magsq /= (1<<30);
m_magsqSum += magsq;
if (magsq > m_magsqPeak)
{
m_magsqPeak = magsq;
}
m_magsqCount++;
Real demod = m_phaseDiscri.phaseDiscriminator2(ci);
@ -155,7 +168,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
// AF processing
if (getMag() > m_squelchLevel)
if (m_AGC.getAverage()/(1<<30) > m_squelchLevel)
{
if (m_squelchCount < m_agcAttack)
{
@ -369,7 +382,7 @@ void NFMDemod::apply()
if (m_config.m_squelch != m_running.m_squelch)
{
// input is a value in tenths of dB
m_squelchLevel = std::pow(10.0, m_config.m_squelch / 200.0);
m_squelchLevel = std::pow(10.0, m_config.m_squelch / 10.0);
//m_squelchLevel *= m_squelchLevel;
m_afSquelch.setThreshold(m_squelchLevel);
}

View File

@ -71,6 +71,16 @@ public:
Real getMag() { return m_AGC.getAverage() / (1<<15); }
bool getSquelchOpen() const { return m_squelchOpen; }
void getMagSqLevels(Real& avg, Real& peak, int& nbSamples)
{
avg = m_magsqSum / m_magsqCount;
peak = m_magsqPeak;
nbSamples = m_magsqCount;
m_magsqSum = 0.0f;
m_magsqPeak = 0.0f;
m_magsqCount = 0;
}
private:
class MsgConfigureNFMDemod : public Message {
MESSAGE_CLASS_DECLARATION
@ -187,6 +197,9 @@ private:
double m_squelchLevel;
bool m_squelchOpen;
Real m_magsqSum;
Real m_magsqPeak;
int m_magsqCount;
Real m_lastArgument;
//Complex m_m1Sample;

View File

@ -291,7 +291,8 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
ui->ctcss->addItem(QString("%1").arg(ctcss_tones[i]));
}
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGreenYellow));
ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenYellow);
m_channelizer = new DownChannelizer(m_nfmDemod);
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
@ -337,15 +338,15 @@ void NFMDemodGUI::applySettings()
ui->deltaFrequency->setValue(abs(m_channelMarker.getCenterFrequency()));
ui->deltaMinus->setChecked(m_channelMarker.getCenterFrequency() < 0);
ui->squelchGateText->setText(QString("%1").arg(ui->squelchGate->value() * 10.0, 0, 'f', 0));
ui->squelchGateText->setText(QString("%1").arg(ui->squelchGate->value() * 10.0f, 0, 'f', 0));
m_nfmDemod->configure(m_nfmDemod->getInputMessageQueue(),
m_rfBW[ui->rfBW->currentIndex()],
ui->afBW->value() * 1000.0,
ui->afBW->value() * 1000.0f,
m_fmDev[ui->rfBW->currentIndex()],
ui->volume->value() / 10.0,
ui->volume->value() / 10.0f,
ui->squelchGate->value(), // in 10ths of ms
ui->squelch->value(),
ui->squelch->value() / 10.0f,
ui->ctcssOn->isChecked(),
ui->audioMute->isChecked());
}
@ -384,10 +385,33 @@ void NFMDemodGUI::blockApplySettings(bool block)
void NFMDemodGUI::tick()
{
Real powDb = CalcDb::dbPower(m_nfmDemod->getMag()) * 2;
m_channelPowerDbAvg.feed(powDb);
ui->channelPower->setText(QString::number(m_channelPowerDbAvg.average(), 'f', 1));
bool squelchOpen = m_nfmDemod->getSquelchOpen();
if (m_powerMeterTickCount < 4) // 200 ms
{
m_powerMeterTickCount++;
}
else
{
Real magsqAvg, magsqPeak;
int nbMagsqSamples;
m_nfmDemod->getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
Real powDbAvg = CalcDb::dbPower(magsqAvg);
Real powDbPeak = CalcDb::dbPower(magsqPeak);
ui->channelPowerMeter->levelChanged(
(100.0f + powDbAvg) / 100.0f,
(100.0f + powDbPeak) / 100.0f,
nbMagsqSamples);
ui->channelPower->setText(QString::number(powDbAvg, 'f', 1));
m_powerMeterTickCount = 0;
}
// Real powDb = CalcDb::dbPower(m_nfmDemod->getMag()) * 2;
// m_channelPowerDbAvg.feed(powDb);
// ui->channelPower->setText(QString::number(m_channelPowerDbAvg.average(), 'f', 1));
bool squelchOpen = m_nfmDemod->getSquelchOpen();
if (squelchOpen != m_squelchOpen)
{

View File

@ -69,6 +69,7 @@ private:
bool m_ctcssOn;
bool m_audioMute;
bool m_squelchOpen;
int m_powerMeterTickCount;
MovingAverage<Real> m_channelPowerDbAvg;
static const int m_rfBW[];

View File

@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>287</width>
<height>156</height>
<width>302</width>
<height>178</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>302</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<family>Sans Serif</family>
@ -24,10 +30,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>271</width>
<width>300</width>
<height>141</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
@ -52,8 +64,8 @@
</property>
<property name="icon">
<iconset>
<selectedoff>:/plus.png</selectedoff>
<selectedon>:/minus.png</selectedon>
<selectedoff>:/plusrx.png</selectedoff>
<selectedon>:/minusrx.png</selectedon>
</iconset>
</property>
<property name="checkable">
@ -143,6 +155,36 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="levelMeterLayout">
<item>
<widget class="QLabel" name="channelPowerMeterUnits">
<property name="text">
<string>dB</string>
</property>
</widget>
</item>
<item>
<widget class="LevelMeterSignalDB" name="channelPowerMeter" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>Level meter (dB) light: average, dark: peak, tip: peak hold</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="rfBWLayout">
<item>
@ -522,9 +564,6 @@
</item>
</layout>
</widget>
<zorder>settingsContainer</zorder>
<zorder>afBW</zorder>
<zorder>afBWText</zorder>
</widget>
<customwidgets>
<customwidget>
@ -539,6 +578,12 @@
<header>gui/valuedial.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LevelMeterSignalDB</class>
<extends>QWidget</extends>
<header>gui/levelmeter.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrbase/resources/res.qrc"/>

View File

@ -7,7 +7,7 @@
const PluginDescriptor NFMPlugin::m_pluginDescriptor = {
QString("NFM Demodulator"),
QString("2.0.0"),
QString("2.4.0"),
QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"),
true,

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

View File

@ -1,5 +1,7 @@
<RCC>
<qresource prefix="/">
<file>minusrx.png</file>
<file>plusrx.png</file>
<file>microphone.png</file>
<file>checkmark.png</file>
<file>questionmark.png</file>