mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 17:58:43 -05:00
NFM Demod: added signal meter. Corrected squelch. Turned frequency dial green
This commit is contained in:
parent
c31846a334
commit
7c3cebf2e1
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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[];
|
||||
|
@ -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"/>
|
||||
|
@ -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,
|
||||
|
BIN
sdrbase/resources/minusrx.png
Normal file
BIN
sdrbase/resources/minusrx.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 231 B |
BIN
sdrbase/resources/plusrx.png
Normal file
BIN
sdrbase/resources/plusrx.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 373 B |
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user