mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 09:48:45 -05:00
ATV Demod: FM mode using phaseDiscriminatorDelta with deviation scaling
This commit is contained in:
parent
b1c2f59a87
commit
016f7c1e37
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -40,7 +40,7 @@
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>681</width>
|
||||
<height>81</height>
|
||||
<height>83</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -275,6 +275,11 @@
|
||||
<string>FM 2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>FM 3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>AM</string>
|
||||
@ -292,6 +297,58 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="fmDeviationLabel">
|
||||
<property name="text">
|
||||
<string>D</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="fmDeviation">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>125</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="fmDeviationText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>100</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="rfFiltering">
|
||||
<property name="toolTip">
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user