diff --git a/plugins/channelrx/demodatv/atvdemod.cpp b/plugins/channelrx/demodatv/atvdemod.cpp
index 7df670175..5380a005b 100644
--- a/plugins/channelrx/demodatv/atvdemod.cpp
+++ b/plugins/channelrx/demodatv/atvdemod.cpp
@@ -76,6 +76,8 @@ ATVDemod::ATVDemod(BasebandSampleSink* objScopeSink) :
memset((void*)m_fltBufferI,0,6*sizeof(float));
memset((void*)m_fltBufferQ,0,6*sizeof(float));
+
+ m_objPhaseDiscri.setFMScaling(1.0f);
}
ATVDemod::~ATVDemod()
@@ -119,7 +121,8 @@ void ATVDemod::configureRF(
float fltRFOppBandwidth,
bool blnFFTFiltering,
bool blnDecimatorEnable,
- float fltBFOFrequency)
+ float fltBFOFrequency,
+ float fmDeviation)
{
Message* msgCmd = MsgConfigureRFATVDemod::create(
enmModulation,
@@ -127,7 +130,8 @@ void ATVDemod::configureRF(
fltRFOppBandwidth,
blnFFTFiltering,
blnDecimatorEnable,
- fltBFOFrequency);
+ fltBFOFrequency,
+ fmDeviation);
objMessageQueue->push(msgCmd);
}
@@ -272,15 +276,14 @@ void ATVDemod::demod(Complex& c)
float& fltI = m_objRFRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].real() : c.real();
float& fltQ = m_objRFRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].imag() : c.imag();
#endif
- double magSq = fltI*fltI + fltQ*fltQ;
- m_objMagSqAverage.feed(magSq);
-
- fltNorm = sqrt(magSq);
+ double magSq;
if ((m_objRFRunning.m_enmModulation == ATV_FM1) || (m_objRFRunning.m_enmModulation == ATV_FM2))
{
//Amplitude FM
-
+ magSq = fltI*fltI + fltQ*fltQ;
+ m_objMagSqAverage.feed(magSq);
+ fltNorm = sqrt(magSq);
fltNormI= fltI/fltNorm;
fltNormQ= fltQ/fltNorm;
@@ -324,11 +327,13 @@ void ATVDemod::demod(Complex& c)
m_fltBufferI[0]=fltNormI;
m_fltBufferQ[0]=fltNormQ;
-
}
else if (m_objRFRunning.m_enmModulation == ATV_AM)
{
//Amplitude AM
+ magSq = fltI*fltI + fltQ*fltQ;
+ m_objMagSqAverage.feed(magSq);
+ fltNorm = sqrt(magSq);
fltVal = fltNorm;
//********** Mini and Maxi Amplitude tracking **********
@@ -349,6 +354,10 @@ void ATVDemod::demod(Complex& c)
}
else if ((m_objRFRunning.m_enmModulation == ATV_USB) || (m_objRFRunning.m_enmModulation == ATV_LSB))
{
+ magSq = fltI*fltI + fltQ*fltQ;
+ m_objMagSqAverage.feed(magSq);
+ fltNorm = sqrt(magSq);
+
Real bfoValues[2];
float fltFiltered = m_bfoFilter.run(fltI);
m_bfoPLL.process(fltFiltered, bfoValues);
@@ -380,12 +389,23 @@ void ATVDemod::demod(Complex& c)
fltVal -= m_fltAmpMin;
fltVal /=m_fltAmpDelta;
}
+ else if (m_objRFRunning.m_enmModulation == ATV_FM3)
+ {
+ float rawDeviation;
+ fltVal = (m_objPhaseDiscri.phaseDiscriminatorDelta(c, magSq, rawDeviation)/ m_objRFRunning.m_fmDeviation) + 0.5f;
+ fltVal = fltVal < 0.0f ? 0.0f : fltVal > 1.0f ? 1.0f : fltVal;
+ m_objMagSqAverage.feed(magSq);
+ fltNorm = sqrt(magSq);
+ }
else
{
+ magSq = fltI*fltI + fltQ*fltQ;
+ m_objMagSqAverage.feed(magSq);
+ fltNorm = sqrt(magSq);
fltVal = 0.0f;
}
- m_objScopeSampleBuffer.push_back(Sample(fltVal*32768.0f, 0.0f));
+ m_objScopeSampleBuffer.push_back(Sample(fltVal*32767.0f, 0.0f));
fltVal = m_objRunning.m_blnInvertVideo ? 1.0f - fltVal : fltVal;
@@ -640,7 +660,8 @@ bool ATVDemod::handleMessage(const Message& cmd)
<< " m_fltRFOppBandwidth:" << m_objRFConfig.m_fltRFOppBandwidth
<< " m_blnFFTFiltering:" << m_objRFConfig.m_blnFFTFiltering
<< " m_blnDecimatorEnable:" << m_objRFConfig.m_blndecimatorEnable
- << " m_fltBFOFrequency:" << m_objRFConfig.m_fltBFOFrequency;
+ << " m_fltBFOFrequency:" << m_objRFConfig.m_fltBFOFrequency
+ << " m_fmDeviation:" << m_objRFConfig.m_fmDeviation;
applySettings();
@@ -761,6 +782,11 @@ void ATVDemod::applySettings()
m_bfoFilter.setFrequencies(m_objRFConfig.m_fltBFOFrequency, m_objConfigPrivate.m_intTVSampleRate);
}
+// if (m_objRFConfig.m_fmDeviation != m_objRFRunning.m_fmDeviation)
+// {
+// m_objPhaseDiscri.setFMScaling(m_objRFConfig.m_fmDeviation);
+// }
+
m_objRunning = m_objConfig;
m_objRFRunning = m_objRFConfig;
m_objRunningPrivate = m_objConfigPrivate;
diff --git a/plugins/channelrx/demodatv/atvdemod.h b/plugins/channelrx/demodatv/atvdemod.h
index aec6ca80a..d25d68681 100644
--- a/plugins/channelrx/demodatv/atvdemod.h
+++ b/plugins/channelrx/demodatv/atvdemod.h
@@ -33,6 +33,7 @@
#include "dsp/agc.h"
#include "dsp/phaselock.h"
#include "dsp/recursivefilters.h"
+#include "dsp/phasediscri.h"
#include "audio/audiofifo.h"
#include "util/message.h"
#include "atvscreen.h"
@@ -47,6 +48,7 @@ public:
enum ATVModulation {
ATV_FM1, //!< Classical frequency modulation with discriminator #1
ATV_FM2, //!< Classical frequency modulation with discriminator #2
+ ATV_FM3, //!< Classical frequency modulation with phase derivative discriminator
ATV_AM, //!< Classical amplitude modulation
ATV_USB, //!< AM with vestigial lower side band (main signal is in the upper side)
ATV_LSB //!< AM with vestigial upper side band (main signal is in the lower side)
@@ -89,6 +91,7 @@ public:
bool m_blnFFTFiltering;
bool m_blndecimatorEnable;
float m_fltBFOFrequency;
+ float m_fmDeviation;
ATVRFConfig() :
m_intFrequencyOffset(0),
@@ -97,7 +100,8 @@ public:
m_fltRFOppBandwidth(0),
m_blnFFTFiltering(false),
m_blndecimatorEnable(false),
- m_fltBFOFrequency(0.0f)
+ m_fltBFOFrequency(0.0f),
+ m_fmDeviation(1.0f)
{
}
};
@@ -143,7 +147,8 @@ public:
float fltRFOppBandwidth,
bool blnFFTFiltering,
bool blndecimatorEnable,
- float fltBFOFrequency);
+ float fltBFOFrequency,
+ float fmDeviation);
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
virtual void start();
@@ -232,7 +237,8 @@ private:
float fltRFOppBandwidth,
bool blnFFTFiltering,
bool blndecimatorEnable,
- int intBFOFrequency)
+ int intBFOFrequency,
+ float fmDeviation)
{
return new MsgConfigureRFATVDemod(
enmModulation,
@@ -240,7 +246,8 @@ private:
fltRFOppBandwidth,
blnFFTFiltering,
blndecimatorEnable,
- intBFOFrequency);
+ intBFOFrequency,
+ fmDeviation);
}
ATVRFConfig m_objMsgConfig;
@@ -252,7 +259,8 @@ private:
float fltRFOppBandwidth,
bool blnFFTFiltering,
bool blndecimatorEnable,
- float fltBFOFrequency) :
+ float fltBFOFrequency,
+ float fmDeviation) :
Message()
{
m_objMsgConfig.m_enmModulation = enmModulation;
@@ -261,6 +269,7 @@ private:
m_objMsgConfig.m_blnFFTFiltering = blnFFTFiltering;
m_objMsgConfig.m_blndecimatorEnable = blndecimatorEnable;
m_objMsgConfig.m_fltBFOFrequency = fltBFOFrequency;
+ m_objMsgConfig.m_fmDeviation = fmDeviation;
}
};
@@ -322,6 +331,9 @@ private:
int m_DSBFilterBufferIndex;
static const int m_ssbFftLen;
+ // Used for FM
+ PhaseDiscriminators m_objPhaseDiscri;
+
//QElapsedTimer m_objTimer;
ATVConfig m_objRunning;
diff --git a/plugins/channelrx/demodatv/atvdemodgui.cpp b/plugins/channelrx/demodatv/atvdemodgui.cpp
index b600ab934..f36a7a95a 100644
--- a/plugins/channelrx/demodatv/atvdemodgui.cpp
+++ b/plugins/channelrx/demodatv/atvdemodgui.cpp
@@ -92,6 +92,7 @@ void ATVDemodGUI::resetToDefaults()
ui->rfBW->setValue(10);
ui->rfOppBW->setValue(10);
ui->bfo->setValue(0);
+ ui->fmDeviation->setValue(100);
blockApplySettings(false);
lineTimeUpdate();
@@ -118,6 +119,7 @@ QByteArray ATVDemodGUI::serialize() const
s.writeS32(14, ui->bfo->value());
s.writeBool(15, ui->invertVideo->isChecked());
s.writeS32(16, ui->nbLines->currentIndex());
+ s.writeS32(17, ui->fmDeviation->value());
return s.final();
}
@@ -179,6 +181,8 @@ bool ATVDemodGUI::deserialize(const QByteArray& arrData)
ui->invertVideo->setChecked(booltmp);
d.readS32(16, &tmp, 0);
ui->nbLines->setCurrentIndex(tmp);
+ d.readS32(17, &tmp, 100);
+ ui->fmDeviation->setValue(tmp);
blockApplySettings(false);
m_objChannelMarker.blockSignals(false);
@@ -322,6 +326,9 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI,
ui->scopeGUI->focusOnTrigger(0); // re-focus to take changes into account in the GUI
connect(m_objATVDemod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
+
+ QChar delta = QChar(0x94, 0x03);
+ ui->fmDeviationLabel->setText(delta);
}
ATVDemodGUI::~ATVDemodGUI()
@@ -378,7 +385,8 @@ void ATVDemodGUI::applyRFSettings()
ui->rfOppBW->value() * m_rfSliderDivisor * 1.0f,
ui->rfFiltering->isChecked(),
ui->decimatorEnable->isChecked(),
- ui->bfo->value() * 10.0f);
+ ui->bfo->value() * 10.0f,
+ ui->fmDeviation->value() / 100.0f);
}
}
@@ -600,6 +608,12 @@ void ATVDemodGUI::on_bfo_valueChanged(int value)
applyRFSettings();
}
+void ATVDemodGUI::on_fmDeviation_valueChanged(int value)
+{
+ ui->fmDeviationText->setText(QString("%1").arg(value));
+ applyRFSettings();
+}
+
void ATVDemodGUI::lineTimeUpdate()
{
float nominalLineTime = getNominalLineTime(ui->nbLines->currentIndex(), ui->fps->currentIndex());
diff --git a/plugins/channelrx/demodatv/atvdemodgui.h b/plugins/channelrx/demodatv/atvdemodgui.h
index 9b63950fd..c1ab351d6 100644
--- a/plugins/channelrx/demodatv/atvdemodgui.h
+++ b/plugins/channelrx/demodatv/atvdemodgui.h
@@ -83,6 +83,7 @@ private slots:
void on_deltaFrequency_changed(quint64 value);
void on_deltaFrequencyMinus_toggled(bool minus);
void on_bfo_valueChanged(int value);
+ void on_fmDeviation_valueChanged(int value);
private:
Ui::ATVDemodGUI* ui;
diff --git a/plugins/channelrx/demodatv/atvdemodgui.ui b/plugins/channelrx/demodatv/atvdemodgui.ui
index cdac1bb5c..c215d7793 100644
--- a/plugins/channelrx/demodatv/atvdemodgui.ui
+++ b/plugins/channelrx/demodatv/atvdemodgui.ui
@@ -40,7 +40,7 @@
10
10
681
- 81
+ 83
@@ -275,6 +275,11 @@
FM 2
+ -
+
+ FM 3
+
+
-
AM
@@ -292,6 +297,58 @@
+ -
+
+
+ D
+
+
+
+ -
+
+
+
+ 24
+ 24
+
+
+
+ 1
+
+
+ 125
+
+
+ 1
+
+
+ 100
+
+
+
+ -
+
+
+
+ 20
+ 0
+
+
+
+ 100
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
-
diff --git a/plugins/channelrx/demodnfm/nfmdemod.cpp b/plugins/channelrx/demodnfm/nfmdemod.cpp
index 8c3d24a36..868a092df 100644
--- a/plugins/channelrx/demodnfm/nfmdemod.cpp
+++ b/plugins/channelrx/demodnfm/nfmdemod.cpp
@@ -156,7 +156,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
//m_AGC.feed(ci);
//double magsqRaw = m_AGC.getMagSq();
- long double magsqRaw; // = ci.real()*ci.real() + c.imag()*c.imag();
+ double magsqRaw; // = ci.real()*ci.real() + c.imag()*c.imag();
Real deviation;
Real demod = m_phaseDiscri.phaseDiscriminatorDelta(ci, magsqRaw, deviation);
diff --git a/sdrbase/dsp/phasediscri.h b/sdrbase/dsp/phasediscri.h
index dcad85f54..362133801 100644
--- a/sdrbase/dsp/phasediscri.h
+++ b/sdrbase/dsp/phasediscri.h
@@ -55,7 +55,7 @@ public:
* Discriminator with phase detection using atan2 and frequency by derivation.
* This yields a precise deviation to sample rate ratio: Sample rate => +/-1.0
*/
- Real phaseDiscriminatorDelta(const Complex& sample, long double& magsq, Real& fmDev)
+ Real phaseDiscriminatorDelta(const Complex& sample, double& magsq, Real& fmDev)
{
Real fltI = sample.real();
Real fltQ = sample.imag();