mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 09:48:45 -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_intNumberOfLines=0;
|
||||
m_intNumberOfRowsToDisplay=0;
|
||||
m_intTVSampleRate = 0;
|
||||
|
||||
m_objMagSqAverage.resize(32, 1.0);
|
||||
|
||||
@ -190,7 +191,10 @@ void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
fltI = it->real();
|
||||
fltQ = it->imag();
|
||||
#endif
|
||||
|
||||
if (m_objRFRunning.m_intFrequencyOffset != 0)
|
||||
{
|
||||
m_nco.nextIQMul(fltI, fltQ);
|
||||
}
|
||||
|
||||
//********** demodulation **********
|
||||
|
||||
@ -494,9 +498,11 @@ bool ATVDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
DownChannelizer::MsgChannelizerNotification& objNotif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
||||
m_objConfig.m_intSampleRate = objNotif.getSampleRate();
|
||||
m_objRFConfig.m_intFrequencyOffset = objNotif.getFrequencyOffset();
|
||||
|
||||
qDebug() << "ATVDemod::handleMessage: MsgChannelizerNotification:"
|
||||
<< " m_intMsps: " << m_objConfig.m_intSampleRate;
|
||||
<< " m_intSampleRate: " << m_objConfig.m_intSampleRate
|
||||
<< " m_intFrequencyOffset: " << m_objRFConfig.m_intFrequencyOffset;
|
||||
|
||||
applySettings();
|
||||
|
||||
@ -553,6 +559,32 @@ void ATVDemod::applySettings()
|
||||
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)
|
||||
|| (m_objConfig.m_fltLineDurationUs != m_objRunning.m_fltLineDurationUs)
|
||||
|| (m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate)
|
||||
|
@ -78,6 +78,7 @@ public:
|
||||
|
||||
struct ATVRFConfig
|
||||
{
|
||||
int64_t m_intFrequencyOffset;
|
||||
ATVModulation m_enmModulation;
|
||||
float m_fltRFBandwidth;
|
||||
float m_fltRFOppBandwidth;
|
||||
@ -85,6 +86,7 @@ public:
|
||||
bool m_blndecimatorEnable;
|
||||
|
||||
ATVRFConfig() :
|
||||
m_intFrequencyOffset(0),
|
||||
m_enmModulation(ATV_FM1),
|
||||
m_fltRFBandwidth(0),
|
||||
m_fltRFOppBandwidth(0),
|
||||
@ -252,6 +254,9 @@ private:
|
||||
|
||||
MovingAverage<double> m_objMagSqAverage;
|
||||
|
||||
int m_intTVSampleRate;
|
||||
NCO m_nco;
|
||||
|
||||
// Interpolator group for decimation and/or double sideband RF filtering
|
||||
Interpolator m_interpolator;
|
||||
Real m_interpolatorDistance;
|
||||
|
@ -296,7 +296,7 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI,
|
||||
m_objChannelMarker.setCenterFrequency(0);
|
||||
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->addChannelMarker(&m_objChannelMarker);
|
||||
@ -333,7 +333,6 @@ void ATVDemodGUI::applySettings()
|
||||
ui->deltaFrequencyMinus->setChecked(m_objChannelMarker.getCenterFrequency() < 0);
|
||||
|
||||
m_objChannelizer->configure(m_objChannelizer->getInputMessageQueue(),
|
||||
//m_objATVDemod->GetSampleRate(),
|
||||
m_objChannelizer->getInputSampleRate(), // always use maximum available bandwidth
|
||||
m_objChannelMarker.getCenterFrequency());
|
||||
|
||||
@ -584,3 +583,23 @@ void ATVDemodGUI::on_decimator_toggled(bool checked)
|
||||
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_rfFiltering_toggled(bool checked);
|
||||
void on_decimator_toggled(bool checked);
|
||||
void on_deltaFrequency_changed(quint64 value);
|
||||
void on_deltaFrequencyMinus_toggled(bool minus);
|
||||
|
||||
private:
|
||||
Ui::ATVDemodGUI* ui;
|
||||
|
@ -65,6 +65,17 @@ Complex NCO::nextQI()
|
||||
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()
|
||||
{
|
||||
return m_table[m_phase];
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
Real next(); //!< Return next real sample
|
||||
Complex nextIQ(); //!< Return next complex sample
|
||||
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)
|
||||
Complex getIQ(); //!< Return 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