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();