mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-29 19:28:47 -05:00
ATV Demod: implement NCO and interpolator change
This commit is contained in:
parent
529e2c2c27
commit
c3c6b79de4
@ -63,6 +63,7 @@ ATVDemod::ATVDemod() :
|
|||||||
m_intSynchroPoints=0;
|
m_intSynchroPoints=0;
|
||||||
m_intNumberOfLines=0;
|
m_intNumberOfLines=0;
|
||||||
m_intNumberOfRowsToDisplay=0;
|
m_intNumberOfRowsToDisplay=0;
|
||||||
|
m_intTVSampleRate = 0;
|
||||||
|
|
||||||
m_objMagSqAverage.resize(32, 1.0);
|
m_objMagSqAverage.resize(32, 1.0);
|
||||||
|
|
||||||
@ -190,7 +191,10 @@ void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
|||||||
fltI = it->real();
|
fltI = it->real();
|
||||||
fltQ = it->imag();
|
fltQ = it->imag();
|
||||||
#endif
|
#endif
|
||||||
|
if (m_objRFRunning.m_intFrequencyOffset != 0)
|
||||||
|
{
|
||||||
|
m_nco.nextIQMul(fltI, fltQ);
|
||||||
|
}
|
||||||
|
|
||||||
//********** demodulation **********
|
//********** demodulation **********
|
||||||
|
|
||||||
@ -494,9 +498,11 @@ bool ATVDemod::handleMessage(const Message& cmd)
|
|||||||
{
|
{
|
||||||
DownChannelizer::MsgChannelizerNotification& objNotif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
DownChannelizer::MsgChannelizerNotification& objNotif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
||||||
m_objConfig.m_intSampleRate = objNotif.getSampleRate();
|
m_objConfig.m_intSampleRate = objNotif.getSampleRate();
|
||||||
|
m_objRFConfig.m_intFrequencyOffset = objNotif.getFrequencyOffset();
|
||||||
|
|
||||||
qDebug() << "ATVDemod::handleMessage: MsgChannelizerNotification:"
|
qDebug() << "ATVDemod::handleMessage: MsgChannelizerNotification:"
|
||||||
<< " m_intMsps: " << m_objConfig.m_intSampleRate;
|
<< " m_intSampleRate: " << m_objConfig.m_intSampleRate
|
||||||
|
<< " m_intFrequencyOffset: " << m_objRFConfig.m_intFrequencyOffset;
|
||||||
|
|
||||||
applySettings();
|
applySettings();
|
||||||
|
|
||||||
@ -553,6 +559,32 @@ void ATVDemod::applySettings()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if((m_objRFConfig.m_intFrequencyOffset != m_objRFRunning.m_intFrequencyOffset) ||
|
||||||
|
(m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate))
|
||||||
|
{
|
||||||
|
m_nco.setFreq(-m_objRFConfig.m_intFrequencyOffset, m_objConfig.m_intSampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate)
|
||||||
|
|| (m_objRFConfig.m_fltRFBandwidth != m_objRFRunning.m_fltRFBandwidth))
|
||||||
|
{
|
||||||
|
m_intTVSampleRate = (m_objConfig.m_intSampleRate / 1000000) * 1000000; // make sure working sample rate is a multiple of rate units
|
||||||
|
|
||||||
|
if (m_intTVSampleRate > 0)
|
||||||
|
{
|
||||||
|
m_interpolatorDistance = (Real) m_intTVSampleRate / (Real) m_objConfig.m_intSampleRate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_intTVSampleRate = m_objConfig.m_intSampleRate;
|
||||||
|
m_interpolatorDistanceRemain = 0;
|
||||||
|
m_interpolatorDistance = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_interpolatorDistanceRemain = 0;
|
||||||
|
m_interpolator.create(48, m_intTVSampleRate, m_objRFConfig.m_fltRFBandwidth / 2.2, 3.0);
|
||||||
|
}
|
||||||
|
|
||||||
if((m_objConfig.m_fltFramePerS != m_objRunning.m_fltFramePerS)
|
if((m_objConfig.m_fltFramePerS != m_objRunning.m_fltFramePerS)
|
||||||
|| (m_objConfig.m_fltLineDurationUs != m_objRunning.m_fltLineDurationUs)
|
|| (m_objConfig.m_fltLineDurationUs != m_objRunning.m_fltLineDurationUs)
|
||||||
|| (m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate)
|
|| (m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate)
|
||||||
|
@ -78,6 +78,7 @@ public:
|
|||||||
|
|
||||||
struct ATVRFConfig
|
struct ATVRFConfig
|
||||||
{
|
{
|
||||||
|
int64_t m_intFrequencyOffset;
|
||||||
ATVModulation m_enmModulation;
|
ATVModulation m_enmModulation;
|
||||||
float m_fltRFBandwidth;
|
float m_fltRFBandwidth;
|
||||||
float m_fltRFOppBandwidth;
|
float m_fltRFOppBandwidth;
|
||||||
@ -85,6 +86,7 @@ public:
|
|||||||
bool m_blndecimatorEnable;
|
bool m_blndecimatorEnable;
|
||||||
|
|
||||||
ATVRFConfig() :
|
ATVRFConfig() :
|
||||||
|
m_intFrequencyOffset(0),
|
||||||
m_enmModulation(ATV_FM1),
|
m_enmModulation(ATV_FM1),
|
||||||
m_fltRFBandwidth(0),
|
m_fltRFBandwidth(0),
|
||||||
m_fltRFOppBandwidth(0),
|
m_fltRFOppBandwidth(0),
|
||||||
@ -252,6 +254,9 @@ private:
|
|||||||
|
|
||||||
MovingAverage<double> m_objMagSqAverage;
|
MovingAverage<double> m_objMagSqAverage;
|
||||||
|
|
||||||
|
int m_intTVSampleRate;
|
||||||
|
NCO m_nco;
|
||||||
|
|
||||||
// Interpolator group for decimation and/or double sideband RF filtering
|
// Interpolator group for decimation and/or double sideband RF filtering
|
||||||
Interpolator m_interpolator;
|
Interpolator m_interpolator;
|
||||||
Real m_interpolatorDistance;
|
Real m_interpolatorDistance;
|
||||||
|
@ -296,7 +296,7 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI,
|
|||||||
m_objChannelMarker.setCenterFrequency(0);
|
m_objChannelMarker.setCenterFrequency(0);
|
||||||
m_objChannelMarker.setVisible(true);
|
m_objChannelMarker.setVisible(true);
|
||||||
|
|
||||||
//connect(&m_objChannelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
connect(&m_objChannelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
||||||
|
|
||||||
m_objDeviceAPI->registerChannelInstance(m_strChannelID, this);
|
m_objDeviceAPI->registerChannelInstance(m_strChannelID, this);
|
||||||
m_objDeviceAPI->addChannelMarker(&m_objChannelMarker);
|
m_objDeviceAPI->addChannelMarker(&m_objChannelMarker);
|
||||||
@ -333,7 +333,6 @@ void ATVDemodGUI::applySettings()
|
|||||||
ui->deltaFrequencyMinus->setChecked(m_objChannelMarker.getCenterFrequency() < 0);
|
ui->deltaFrequencyMinus->setChecked(m_objChannelMarker.getCenterFrequency() < 0);
|
||||||
|
|
||||||
m_objChannelizer->configure(m_objChannelizer->getInputMessageQueue(),
|
m_objChannelizer->configure(m_objChannelizer->getInputMessageQueue(),
|
||||||
//m_objATVDemod->GetSampleRate(),
|
|
||||||
m_objChannelizer->getInputSampleRate(), // always use maximum available bandwidth
|
m_objChannelizer->getInputSampleRate(), // always use maximum available bandwidth
|
||||||
m_objChannelMarker.getCenterFrequency());
|
m_objChannelMarker.getCenterFrequency());
|
||||||
|
|
||||||
@ -584,3 +583,23 @@ void ATVDemodGUI::on_decimator_toggled(bool checked)
|
|||||||
applyRFSettings();
|
applyRFSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ATVDemodGUI::on_deltaFrequency_changed(quint64 value)
|
||||||
|
{
|
||||||
|
if (ui->deltaFrequencyMinus->isChecked()) {
|
||||||
|
m_objChannelMarker.setCenterFrequency(-value);
|
||||||
|
} else {
|
||||||
|
m_objChannelMarker.setCenterFrequency(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ATVDemodGUI::on_deltaFrequencyMinus_toggled(bool minus)
|
||||||
|
{
|
||||||
|
int deltaFrequency = m_objChannelMarker.getCenterFrequency();
|
||||||
|
bool minusDelta = (deltaFrequency < 0);
|
||||||
|
|
||||||
|
if (minus ^ minusDelta) // sign change
|
||||||
|
{
|
||||||
|
m_objChannelMarker.setCenterFrequency(-deltaFrequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,8 @@ private slots:
|
|||||||
void on_rfOppBW_valueChanged(int value);
|
void on_rfOppBW_valueChanged(int value);
|
||||||
void on_rfFiltering_toggled(bool checked);
|
void on_rfFiltering_toggled(bool checked);
|
||||||
void on_decimator_toggled(bool checked);
|
void on_decimator_toggled(bool checked);
|
||||||
|
void on_deltaFrequency_changed(quint64 value);
|
||||||
|
void on_deltaFrequencyMinus_toggled(bool minus);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::ATVDemodGUI* ui;
|
Ui::ATVDemodGUI* ui;
|
||||||
|
@ -65,6 +65,17 @@ Complex NCO::nextQI()
|
|||||||
return Complex(-m_table[(m_phase + TableSize / 4) % TableSize], m_table[m_phase]);
|
return Complex(-m_table[(m_phase + TableSize / 4) % TableSize], m_table[m_phase]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NCO::nextIQMul(Real& i, Real& q)
|
||||||
|
{
|
||||||
|
nextPhase();
|
||||||
|
Real x = i;
|
||||||
|
Real y = q;
|
||||||
|
const Real& u = m_table[m_phase];
|
||||||
|
const Real& v = -m_table[(m_phase + TableSize / 4) % TableSize];
|
||||||
|
i = x*u - y*v;
|
||||||
|
q = x*v + y*u;
|
||||||
|
}
|
||||||
|
|
||||||
float NCO::get()
|
float NCO::get()
|
||||||
{
|
{
|
||||||
return m_table[m_phase];
|
return m_table[m_phase];
|
||||||
|
@ -52,6 +52,7 @@ public:
|
|||||||
Real next(); //!< Return next real sample
|
Real next(); //!< Return next real sample
|
||||||
Complex nextIQ(); //!< Return next complex sample
|
Complex nextIQ(); //!< Return next complex sample
|
||||||
Complex nextQI(); //!< Return next complex sample (reversed)
|
Complex nextQI(); //!< Return next complex sample (reversed)
|
||||||
|
void nextIQMul(Real& i, Real& q); //!< multiply I,Q separately with next sample
|
||||||
Real get(); //!< Return current real sample (no phase increment)
|
Real get(); //!< Return current real sample (no phase increment)
|
||||||
Complex getIQ(); //!< Return current complex sample (no phase increment)
|
Complex getIQ(); //!< Return current complex sample (no phase increment)
|
||||||
void getIQ(Complex& c); //!< Sets to the current complex sample (no phase increment)
|
void getIQ(Complex& c); //!< Sets to the current complex sample (no phase increment)
|
||||||
|
Loading…
Reference in New Issue
Block a user