SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
Public Member Functions | Public Attributes | Protected Member Functions | Private Attributes | Static Private Attributes | List of all members
RDSDemod Class Reference

#include <rdsdemod.h>

Inherits QObject.

Public Member Functions

 RDSDemod ()
 
 ~RDSDemod ()
 
void setSampleRate (int srate)
 FIXME: fix rate for now. More...
 
bool process (Real rdsSample, bool &bit)
 

Public Attributes

struct {
   Real   acc
 
   Real   qua
 
   Real   fclk
 
m_report
 
double subcarr_phi
 
Real subcarr_bb [2]
 
double clock_offset
 
double clock_phi
 
double prev_clock_phi
 
Real lo_clock
 
Real prev_lo_clock
 
Real prev_bb
 
double d_cphi
 
int numsamples
 
Real prev_acc
 
int counter
 
int reading_frame
 
int tot_errs [2]
 
int dbit
 

Protected Member Functions

bool biphase (Real acc, bool &bit, Real d_cphi)
 
Real filter_lp_2400_iq (Real in, int iqIndex)
 
Real filter_lp_pll (Real input)
 
int sign (Real a)
 

Private Attributes

struct {
   double   subcarr_phi
 
   Real   subcarr_bb [2]
 
   double   clock_offset
 
   double   clock_phi
 
   double   prev_clock_phi
 
   Real   lo_clock
 
   Real   prev_lo_clock
 
   Real   prev_bb
 
   double   d_cphi
 
   Real   acc
 
   int   numsamples
 
   Real   prev_acc
 
   int   counter
 
   int   reading_frame
 
   int   tot_errs [2]
 
   int   dbit
 
m_parms
 
Real m_xv [2][2+1]
 
Real m_yv [2][2+1]
 
Real m_xw [1+1]
 
Real m_yw [1+1]
 
Real m_prev
 
int m_srate
 

Static Private Attributes

static const Real m_pllBeta = 50
 
static const Real m_fsc = 1187.5
 

Detailed Description

Definition at line 28 of file rdsdemod.h.

Constructor & Destructor Documentation

◆ RDSDemod()

RDSDemod::RDSDemod ( )

Definition at line 34 of file rdsdemod.cpp.

References m_parms, m_prev, m_report, m_srate, m_xv, m_xw, m_yv, and m_yw.

36 {
37  m_srate = 250000;
38 
39  m_parms.subcarr_phi = 0;
40  memset(m_parms.subcarr_bb, 0, sizeof(m_parms.subcarr_bb));
41  m_parms.clock_offset = 0;
42  m_parms.clock_phi = 0;
43  m_parms.prev_clock_phi = 0;
44  m_parms.lo_clock = 0;
45  m_parms.prev_lo_clock = 0;
46  m_parms.prev_bb = 0;
47  m_parms.d_cphi = 0;
48  m_parms.acc = 0;
49  m_parms.numsamples = 0;
50  m_parms.prev_acc = 0;
51  m_parms.counter = 0;
52  m_parms.reading_frame = 0;
53  memset(m_parms.tot_errs, 0, sizeof(m_parms.tot_errs));
54  m_parms.dbit = 0;
55  m_prev = 0.0f;
56  memset(m_xv, 0, 6*sizeof(Real));
57  memset(m_yv, 0, 6*sizeof(Real));
58  memset(m_xw, 0, 2*sizeof(Real));
59  memset(m_yw, 0, 2*sizeof(Real));
60  m_report.acc = 0.0f;
61  m_report.fclk = 0.0f;
62  m_report.qua = 0.0f;
63 }
struct RDSDemod::@1 m_report
Real m_yw[1+1]
Definition: rdsdemod.h:74
Real m_prev
Definition: rdsdemod.h:75
Real m_xv[2][2+1]
Definition: rdsdemod.h:71
int m_srate
Definition: rdsdemod.h:77
Real m_yv[2][2+1]
Definition: rdsdemod.h:72
struct RDSDemod::@2 m_parms
Real m_xw[1+1]
Definition: rdsdemod.h:73
float Real
Definition: dsptypes.h:42

◆ ~RDSDemod()

RDSDemod::~RDSDemod ( )

Definition at line 65 of file rdsdemod.cpp.

66 {
67  //delete m_socket;
68 }

Member Function Documentation

◆ biphase()

bool RDSDemod::biphase ( Real  acc,
bool &  bit,
Real  d_cphi 
)
protected

Definition at line 138 of file rdsdemod.cpp.

References abs(), acc, m_parms, M_PI, m_report, m_srate, and sign().

Referenced by process().

139 {
140  bool ret = false;
141 
142  if (sign(acc) != sign(m_parms.prev_acc)) // two successive of different sign: error detected
143  {
144  m_parms.tot_errs[m_parms.counter % 2]++;
145  }
146 
147  if (m_parms.counter % 2 == m_parms.reading_frame) // two successive of the same sing: OK
148  {
149  // new bit found
150  int b = sign(m_parms.acc + m_parms.prev_acc);
151  bit = b ^ m_parms.dbit;
152  m_parms.dbit = b;
153  ret = true;
154  }
155 
156  if (m_parms.counter == 0)
157  {
158  if (m_parms.tot_errs[1 - m_parms.reading_frame] < m_parms.tot_errs[m_parms.reading_frame])
159  {
160  m_parms.reading_frame = 1 - m_parms.reading_frame;
161  }
162 
163  m_report.qua = (1.0 * abs(m_parms.tot_errs[0] - m_parms.tot_errs[1]) / (m_parms.tot_errs[0] + m_parms.tot_errs[1])) * 100;
164  m_report.acc = acc;
165  m_report.fclk = (d_cphi / (2 * M_PI)) * m_srate;
166 
167  /*
168  qDebug("RDSDemod::biphase: frame: %d acc: %+6.3f errs: %3d %3d qual: %3.0f%% clk: %7.2f",
169  m_parms.reading_frame,
170  acc,
171  m_parms.tot_errs[0],
172  m_parms.tot_errs[1],
173  m_report.qua,
174  m_report.fclk);*/
175 
176  m_parms.tot_errs[0] = 0;
177  m_parms.tot_errs[1] = 0;
178  }
179 
180  m_parms.prev_acc = acc; // memorize (z^-1)
181  m_parms.counter = (m_parms.counter + 1) % 800;
182 
183  return ret;
184 }
struct RDSDemod::@1 m_report
Fixed< IntType, IntBits > abs(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2313
#define M_PI
Definition: rdsdemod.cpp:27
int sign(Real a)
Definition: rdsdemod.cpp:211
Real acc
Definition: rdsdemod.h:39
int m_srate
Definition: rdsdemod.h:77
struct RDSDemod::@2 m_parms
double d_cphi
Definition: rdsdemod.h:61
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ filter_lp_2400_iq()

Real RDSDemod::filter_lp_2400_iq ( Real  in,
int  iqIndex 
)
protected

Definition at line 186 of file rdsdemod.cpp.

References m_xv, and m_yv.

Referenced by process().

187 {
188  /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher
189  Command line: /www/usr/fisher/helpers/mkfilter -Bu -Lp -o 10
190  -a 4.8000000000e-03 0.0000000000e+00 -l */
191 
192  m_xv[iqIndex][0] = m_xv[iqIndex][1]; m_xv[iqIndex][1] = m_xv[iqIndex][2];
193  m_xv[iqIndex][2] = input / 4.491730007e+03;
194  m_yv[iqIndex][0] = m_yv[iqIndex][1]; m_yv[iqIndex][1] = m_yv[iqIndex][2];
195  m_yv[iqIndex][2] = (m_xv[iqIndex][0] + m_xv[iqIndex][2]) + 2 * m_xv[iqIndex][1]
196  + ( -0.9582451124 * m_yv[iqIndex][0]) + ( 1.9573545869 * m_yv[iqIndex][1]);
197 
198  return m_yv[iqIndex][2];
199 }
Real m_xv[2][2+1]
Definition: rdsdemod.h:71
Real m_yv[2][2+1]
Definition: rdsdemod.h:72
+ Here is the caller graph for this function:

◆ filter_lp_pll()

Real RDSDemod::filter_lp_pll ( Real  input)
protected

Definition at line 201 of file rdsdemod.cpp.

References m_xw, and m_yw.

202 {
203  m_xw[0] = m_xw[1];
204  m_xw[1] = input / 3.716236217e+01;
205  m_yw[0] = m_yw[1];
206  m_yw[1] = (m_xw[0] + m_xw[1])
207  + ( 0.9461821078 * m_yw[0]);
208  return m_yw[1];
209 }
Real m_yw[1+1]
Definition: rdsdemod.h:74
Real m_xw[1+1]
Definition: rdsdemod.h:73

◆ process()

bool RDSDemod::process ( Real  rdsSample,
bool &  bit 
)

Definition at line 75 of file rdsdemod.cpp.

References biphase(), filter_lp_2400_iq(), m_fsc, m_parms, M_PI, M_PI_2, m_prev, m_srate, and sign().

Referenced by BFMDemod::feed().

76 {
77  bool ret = false;
78 
79  //m_udpDebug.write(m_parms.lo_clock * m_parms.subcarr_bb[0]); // UDP debug
80 
81  // Subcarrier downmix & phase recovery
82 
83  m_parms.subcarr_bb[0] = filter_lp_2400_iq(demod, 0);
84 
85  // 1187.5 Hz clock
86 
87  /*
88  if (m_parms.subcarr_phi > 1e9) // ~ every 37 hours => not really useful
89  {
90  qDebug("RDSDemod::process: reset 1187.5 Hz clock");
91  m_parms.subcarr_phi = 0;
92  m_parms.clock_offset = 0;
93  }*/
94 
95  m_parms.subcarr_phi += (2 * M_PI * m_fsc) / (Real) m_srate;
96  m_parms.clock_phi = m_parms.subcarr_phi + m_parms.clock_offset;
97 
98  // Clock phase recovery
99 
100  if (sign(m_parms.prev_bb) != sign(m_parms.subcarr_bb[0]))
101  {
102  m_parms.d_cphi = std::fmod(m_parms.clock_phi, M_PI);
103 
104  if (m_parms.d_cphi >= M_PI_2)
105  {
106  m_parms.d_cphi -= M_PI;
107  }
108 
109  m_parms.clock_offset -= 0.005 * m_parms.d_cphi;
110  }
111 
112  m_parms.clock_phi = std::fmod(m_parms.clock_phi, 2 * M_PI);
113  m_parms.lo_clock = (m_parms.clock_phi < M_PI ? 1 : -1);
114 
115  /* Decimate band-limited signal */
116  if (m_parms.numsamples % 8 == 0)
117  {
118  /* biphase symbol integrate & dump */
119  m_parms.acc += m_parms.subcarr_bb[0] * m_parms.lo_clock;
120 
121  if (sign(m_parms.lo_clock) != sign(m_parms.prev_lo_clock))
122  {
123  ret = biphase(m_parms.acc, bit, m_parms.clock_phi - m_parms.prev_clock_phi);
124  m_parms.acc = 0;
125  }
126 
127  m_parms.prev_lo_clock = m_parms.lo_clock;
128  }
129 
130  m_parms.numsamples++;
131  m_parms.prev_bb = m_parms.subcarr_bb[0];
132  m_parms.prev_clock_phi = m_parms.clock_phi;
133  m_prev = demod;
134 
135  return ret;
136 }
bool biphase(Real acc, bool &bit, Real d_cphi)
Definition: rdsdemod.cpp:138
static const Real m_fsc
Definition: rdsdemod.h:80
#define M_PI_2
Definition: rdsdemod.cpp:29
#define M_PI
Definition: rdsdemod.cpp:27
Real filter_lp_2400_iq(Real in, int iqIndex)
Definition: rdsdemod.cpp:186
int sign(Real a)
Definition: rdsdemod.cpp:211
Real m_prev
Definition: rdsdemod.h:75
int m_srate
Definition: rdsdemod.h:77
struct RDSDemod::@2 m_parms
float Real
Definition: dsptypes.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setSampleRate()

void RDSDemod::setSampleRate ( int  srate)

FIXME: fix rate for now.

Definition at line 70 of file rdsdemod.cpp.

71 {
72  (void) srate;
73 }

◆ sign()

int RDSDemod::sign ( Real  a)
protected

Definition at line 211 of file rdsdemod.cpp.

Referenced by biphase(), and process().

212 {
213  return (a >= 0 ? 1 : 0);
214 }
+ Here is the caller graph for this function:

Member Data Documentation

◆ acc

Real RDSDemod::acc

Definition at line 39 of file rdsdemod.h.

Referenced by biphase().

◆ clock_offset

double RDSDemod::clock_offset

Definition at line 55 of file rdsdemod.h.

◆ clock_phi

double RDSDemod::clock_phi

Definition at line 56 of file rdsdemod.h.

◆ counter

int RDSDemod::counter

Definition at line 65 of file rdsdemod.h.

◆ d_cphi

double RDSDemod::d_cphi

Definition at line 61 of file rdsdemod.h.

◆ dbit

int RDSDemod::dbit

Definition at line 68 of file rdsdemod.h.

◆ fclk

Real RDSDemod::fclk

Definition at line 41 of file rdsdemod.h.

◆ lo_clock

Real RDSDemod::lo_clock

Definition at line 58 of file rdsdemod.h.

◆ m_fsc

const Real RDSDemod::m_fsc = 1187.5
staticprivate

Definition at line 80 of file rdsdemod.h.

Referenced by process().

◆ m_parms

struct { ... } RDSDemod::m_parms

Referenced by biphase(), process(), and RDSDemod().

◆ m_pllBeta

const Real RDSDemod::m_pllBeta = 50
staticprivate

Definition at line 79 of file rdsdemod.h.

◆ m_prev

Real RDSDemod::m_prev
private

Definition at line 75 of file rdsdemod.h.

Referenced by process(), and RDSDemod().

◆ m_report

struct { ... } RDSDemod::m_report

Referenced by biphase(), and RDSDemod().

◆ m_srate

int RDSDemod::m_srate
private

Definition at line 77 of file rdsdemod.h.

Referenced by biphase(), process(), and RDSDemod().

◆ m_xv

Real RDSDemod::m_xv[2][2+1]
private

Definition at line 71 of file rdsdemod.h.

Referenced by filter_lp_2400_iq(), and RDSDemod().

◆ m_xw

Real RDSDemod::m_xw[1+1]
private

Definition at line 73 of file rdsdemod.h.

Referenced by filter_lp_pll(), and RDSDemod().

◆ m_yv

Real RDSDemod::m_yv[2][2+1]
private

Definition at line 72 of file rdsdemod.h.

Referenced by filter_lp_2400_iq(), and RDSDemod().

◆ m_yw

Real RDSDemod::m_yw[1+1]
private

Definition at line 74 of file rdsdemod.h.

Referenced by filter_lp_pll(), and RDSDemod().

◆ numsamples

int RDSDemod::numsamples

Definition at line 63 of file rdsdemod.h.

◆ prev_acc

Real RDSDemod::prev_acc

Definition at line 64 of file rdsdemod.h.

◆ prev_bb

Real RDSDemod::prev_bb

Definition at line 60 of file rdsdemod.h.

◆ prev_clock_phi

double RDSDemod::prev_clock_phi

Definition at line 57 of file rdsdemod.h.

◆ prev_lo_clock

Real RDSDemod::prev_lo_clock

Definition at line 59 of file rdsdemod.h.

◆ qua

Real RDSDemod::qua

Definition at line 40 of file rdsdemod.h.

◆ reading_frame

int RDSDemod::reading_frame

Definition at line 66 of file rdsdemod.h.

◆ subcarr_bb

Real RDSDemod::subcarr_bb[2]

Definition at line 54 of file rdsdemod.h.

◆ subcarr_phi

double RDSDemod::subcarr_phi

Definition at line 53 of file rdsdemod.h.

◆ tot_errs

int RDSDemod::tot_errs[2]

Definition at line 67 of file rdsdemod.h.


The documentation for this class was generated from the following files: