mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-10-02 17:56:45 -04:00
BFM decoder: implement RDS decoder
This commit is contained in:
parent
dae67170a7
commit
6782c753ad
@ -137,11 +137,17 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
|||||||
if (m_running.m_rdsActive)
|
if (m_running.m_rdsActive)
|
||||||
{
|
{
|
||||||
//Complex r(demod * 2.0 * std::cos(3.0 * m_pilotPLLSamples[2]), 0.0);
|
//Complex r(demod * 2.0 * std::cos(3.0 * m_pilotPLLSamples[2]), 0.0);
|
||||||
Complex r(demod * 2.0 * std::cos(3.0 * m_pilotPLLSamples[2]), m_pilotPLLSamples[2]);
|
Complex r(demod * 2.0 * std::cos(3.0 * m_pilotPLLSamples[2]), 0.0);
|
||||||
|
|
||||||
if (m_interpolatorRDS.interpolate(&m_interpolatorRDSDistanceRemain, r, &cr))
|
if (m_interpolatorRDS.interpolate(&m_interpolatorRDSDistanceRemain, r, &cr))
|
||||||
{
|
{
|
||||||
m_rdsDemod.process(cr.real(), cr.imag());
|
bool bit;
|
||||||
|
|
||||||
|
if (m_rdsDemod.process(cr.real(), bit))
|
||||||
|
{
|
||||||
|
m_rdsDecoder.frameSync(bit);
|
||||||
|
}
|
||||||
|
|
||||||
m_interpolatorRDSDistanceRemain += m_interpolatorRDSDistance;
|
m_interpolatorRDSDistanceRemain += m_interpolatorRDSDistance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "audio/audiofifo.h"
|
#include "audio/audiofifo.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
#include "rdsdemod.h"
|
#include "rdsdemod.h"
|
||||||
|
#include "rdsdecoder.h"
|
||||||
|
|
||||||
#define rfFilterFftLength 1024
|
#define rfFilterFftLength 1024
|
||||||
|
|
||||||
@ -192,6 +193,7 @@ private:
|
|||||||
Real m_pilotPLLSamples[3];
|
Real m_pilotPLLSamples[3];
|
||||||
|
|
||||||
RDSDemod m_rdsDemod;
|
RDSDemod m_rdsDemod;
|
||||||
|
RDSDecoder m_rdsDecoder;
|
||||||
|
|
||||||
LowPassFilterRC m_deemphasisFilterX;
|
LowPassFilterRC m_deemphasisFilterX;
|
||||||
LowPassFilterRC m_deemphasisFilterY;
|
LowPassFilterRC m_deemphasisFilterY;
|
||||||
|
@ -44,6 +44,7 @@ RDSDemod::RDSDemod() :
|
|||||||
m_parms.prev_acc = 0;
|
m_parms.prev_acc = 0;
|
||||||
m_parms.counter = 0;
|
m_parms.counter = 0;
|
||||||
m_parms.reading_frame = 0;
|
m_parms.reading_frame = 0;
|
||||||
|
m_parms.dbit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RDSDemod::~RDSDemod()
|
RDSDemod::~RDSDemod()
|
||||||
@ -55,8 +56,10 @@ void RDSDemod::setSampleRate(int srate) /// FIXME: fix rate for now
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void RDSDemod::process(Real demod, Real pilot)
|
bool RDSDemod::process(Real demod, bool& bit)
|
||||||
{
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
m_udpDebug.write(m_parms.lo_clock * m_parms.subcarr_bb[0]);
|
m_udpDebug.write(m_parms.lo_clock * m_parms.subcarr_bb[0]);
|
||||||
|
|
||||||
// Subcarrier downmix & phase recovery
|
// Subcarrier downmix & phase recovery
|
||||||
@ -101,7 +104,7 @@ void RDSDemod::process(Real demod, Real pilot)
|
|||||||
|
|
||||||
if (sign(m_parms.lo_clock) != sign(m_parms.prev_lo_clock))
|
if (sign(m_parms.lo_clock) != sign(m_parms.prev_lo_clock))
|
||||||
{
|
{
|
||||||
biphase(m_parms.acc, m_parms.clock_phi - m_parms.prev_clock_phi);
|
ret = biphase(m_parms.acc, bit, m_parms.clock_phi - m_parms.prev_clock_phi);
|
||||||
m_parms.acc = 0;
|
m_parms.acc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,10 +115,13 @@ void RDSDemod::process(Real demod, Real pilot)
|
|||||||
m_parms.prev_bb = m_parms.subcarr_bb[0];
|
m_parms.prev_bb = m_parms.subcarr_bb[0];
|
||||||
m_parms.prev_clock_phi = m_parms.clock_phi;
|
m_parms.prev_clock_phi = m_parms.clock_phi;
|
||||||
m_prev = demod;
|
m_prev = demod;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RDSDemod::biphase(Real acc, Real d_cphi)
|
bool RDSDemod::biphase(Real acc, bool& bit, Real d_cphi)
|
||||||
{
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
if (sign(acc) != sign(m_parms.prev_acc)) // two successive of different sign: error detected
|
if (sign(acc) != sign(m_parms.prev_acc)) // two successive of different sign: error detected
|
||||||
{
|
{
|
||||||
@ -124,7 +130,11 @@ void RDSDemod::biphase(Real acc, Real d_cphi)
|
|||||||
|
|
||||||
if (m_parms.counter % 2 == m_parms.reading_frame) // two successive of the same sing: OK
|
if (m_parms.counter % 2 == m_parms.reading_frame) // two successive of the same sing: OK
|
||||||
{
|
{
|
||||||
// TODO: take action print_delta(sign(acc + prev_acc));
|
// new bit found
|
||||||
|
int b = sign(m_parms.acc + m_parms.prev_acc);
|
||||||
|
bit = b ^ m_parms.dbit;
|
||||||
|
m_parms.dbit = b;
|
||||||
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_parms.counter == 0)
|
if (m_parms.counter == 0)
|
||||||
@ -149,6 +159,8 @@ void RDSDemod::biphase(Real acc, Real d_cphi)
|
|||||||
|
|
||||||
m_parms.prev_acc = acc; // memorize (z^-1)
|
m_parms.prev_acc = acc; // memorize (z^-1)
|
||||||
m_parms.counter = (m_parms.counter + 1) % 800;
|
m_parms.counter = (m_parms.counter + 1) % 800;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Real RDSDemod::filter_lp_2400_iq(Real input, int iqIndex)
|
Real RDSDemod::filter_lp_2400_iq(Real input, int iqIndex)
|
||||||
|
@ -32,10 +32,10 @@ public:
|
|||||||
~RDSDemod();
|
~RDSDemod();
|
||||||
|
|
||||||
void setSampleRate(int srate);
|
void setSampleRate(int srate);
|
||||||
void process(Real rdsSample, Real pilotSample);
|
bool process(Real rdsSample, bool &bit);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void biphase(Real acc, Real d_cphi);
|
bool biphase(Real acc, bool &bit, Real d_cphi);
|
||||||
Real filter_lp_2400_iq(Real in, int iqIndex);
|
Real filter_lp_2400_iq(Real in, int iqIndex);
|
||||||
Real filter_lp_pll(Real input);
|
Real filter_lp_pll(Real input);
|
||||||
int sign(Real a);
|
int sign(Real a);
|
||||||
@ -58,6 +58,7 @@ private:
|
|||||||
int counter;
|
int counter;
|
||||||
int reading_frame;
|
int reading_frame;
|
||||||
int tot_errs[2];
|
int tot_errs[2];
|
||||||
|
int dbit;
|
||||||
} m_parms;
|
} m_parms;
|
||||||
|
|
||||||
Real m_xv[2][2+1];
|
Real m_xv[2][2+1];
|
||||||
|
Loading…
Reference in New Issue
Block a user