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 | Static Public Attributes | Private Attributes | List of all members
leansdr::cstln_receiver< T, SOFTSYMB > Struct Template Reference

#include <sdr.h>

+ Inheritance diagram for leansdr::cstln_receiver< T, SOFTSYMB >:
+ Collaboration diagram for leansdr::cstln_receiver< T, SOFTSYMB >:

Public Member Functions

 cstln_receiver (scheduler *sch, sampler_interface< T > *_sampler, pipebuf< complex< T >> &_in, pipebuf< SOFTSYMB > &_out, pipebuf< float > *_freq_out=NULL, pipebuf< float > *_ss_out=NULL, pipebuf< float > *_mer_out=NULL, pipebuf< cf32 > *_cstln_out=NULL)
 
void set_omega (float _omega, float tol=10e-6)
 
void set_freq (float freq)
 
void set_allow_drift (bool d)
 
void update_freq_limits ()
 
void run ()
 
void refresh_freq_tap ()
 
- Public Member Functions inherited from leansdr::runnable
 runnable (scheduler *_sch, const char *name)
 
- Public Member Functions inherited from leansdr::runnable_common
 runnable_common (const char *_name)
 
virtual ~runnable_common ()
 
virtual void shutdown ()
 

Public Attributes

sampler_interface< T > * sampler
 
cstln_lut< SOFTSYMB, 256 > * cstln
 
unsigned long meas_decimation
 
float omega
 
float min_omega
 
float max_omega
 
float freqw
 
float min_freqw
 
float max_freqw
 
float pll_adjustment
 
bool allow_drift
 
float kest
 
float freq_tap
 
complex< float > p
 
complex< float > c
 
- Public Attributes inherited from leansdr::runnable_common
const char * name
 

Static Public Attributes

static const unsigned int chunk_size = 128
 

Private Attributes

struct {
   complex< float >   p
 
   complex< float >   c
 
hist [3]
 
pipereader< complex< T > > in
 
pipewriter< SOFTSYMB > out
 
float est_insp
 
float agc_gain
 
float mu
 
float phase
 
float est_sp
 
float est_ep
 
unsigned long meas_count
 
pipewriter< float > * freq_out
 
pipewriter< float > * ss_out
 
pipewriter< float > * mer_out
 
pipewriter< cf32 > * cstln_out
 

Additional Inherited Members

- Protected Attributes inherited from leansdr::runnable
schedulersch
 

Detailed Description

template<typename T, typename SOFTSYMB>
struct leansdr::cstln_receiver< T, SOFTSYMB >

Definition at line 1037 of file sdr.h.

Constructor & Destructor Documentation

◆ cstln_receiver()

template<typename T, typename SOFTSYMB>
leansdr::cstln_receiver< T, SOFTSYMB >::cstln_receiver ( scheduler sch,
sampler_interface< T > *  _sampler,
pipebuf< complex< T >> &  _in,
pipebuf< SOFTSYMB > &  _out,
pipebuf< float > *  _freq_out = NULL,
pipebuf< float > *  _ss_out = NULL,
pipebuf< float > *  _mer_out = NULL,
pipebuf< cf32 > *  _cstln_out = NULL 
)
inline

Definition at line 1049 of file sdr.h.

1056  : runnable(sch, "Constellation receiver"),
1057  sampler(_sampler),
1058  cstln(NULL),
1059  meas_decimation(1048576),
1060  pll_adjustment(1.0),
1061  allow_drift(false),
1062  kest(0.01),
1063  in(_in),
1064  out(_out, chunk_size),
1066  agc_gain(1),
1067  mu(0),
1068  phase(0),
1069  est_sp(0),
1070  est_ep(0),
1071  meas_count(0)
1072  {
1073  set_omega(1);
1074  set_freq(0);
1075  freq_out = _freq_out ? new pipewriter<float>(*_freq_out) : NULL;
1076  ss_out = _ss_out ? new pipewriter<float>(*_ss_out) : NULL;
1077  mer_out = _mer_out ? new pipewriter<float>(*_mer_out) : NULL;
1078  cstln_out = _cstln_out ? new pipewriter<cf32>(*_cstln_out) : NULL;
1079  memset(hist, 0, sizeof(hist));
1080  }
static const unsigned int chunk_size
Definition: sdr.h:1046
cstln_lut< SOFTSYMB, 256 > * cstln
Definition: sdr.h:1040
pipewriter< cf32 > * cstln_out
Definition: sdr.h:1312
unsigned long meas_decimation
Definition: sdr.h:1041
runnable(scheduler *_sch, const char *name)
Definition: framework.h:193
pipewriter< SOFTSYMB > out
Definition: sdr.h:1303
pipewriter< float > * ss_out
Definition: sdr.h:1311
struct leansdr::cstln_receiver::@8 hist[3]
pipewriter< float > * mer_out
Definition: sdr.h:1311
void set_omega(float _omega, float tol=10e-6)
Definition: sdr.h:1082
pipereader< complex< T > > in
Definition: sdr.h:1302
sampler_interface< T > * sampler
Definition: sdr.h:1039
pipewriter< float > * freq_out
Definition: sdr.h:1311
scheduler * sch
Definition: framework.h:199
unsigned long meas_count
Definition: sdr.h:1310
const float cstln_amp
Definition: sdr.h:404
void set_freq(float freq)
Definition: sdr.h:1090

Member Function Documentation

◆ refresh_freq_tap()

template<typename T, typename SOFTSYMB>
void leansdr::cstln_receiver< T, SOFTSYMB >::refresh_freq_tap ( )
inline

Definition at line 1290 of file sdr.h.

1291  {
1292  freq_tap = freqw / 65536;
1293  }

◆ run()

template<typename T, typename SOFTSYMB>
void leansdr::cstln_receiver< T, SOFTSYMB >::run ( )
inlinevirtual

Reimplemented from leansdr::runnable_common.

Definition at line 1136 of file sdr.h.

1137  {
1138  if (!cstln)
1139  fail("constellation not set");
1140 
1141  // Magic constants that work with the qa recordings.
1142  float freq_alpha = 0.04;
1143  float freq_beta = 0.0012 / omega * pll_adjustment;
1144  float gain_mu = 0.02 / (cstln_amp * cstln_amp) * 2;
1145 
1146  int max_meas = chunk_size / meas_decimation + 1;
1147  // Large margin on output_size because mu adjustments
1148  // can lead to more than chunk_size/min_omega symbols.
1149  while (in.readable() >= chunk_size + sampler->readahead() && out.writable() >= chunk_size && (!freq_out || freq_out->writable() >= max_meas) && (!ss_out || ss_out->writable() >= max_meas) && (!mer_out || mer_out->writable() >= max_meas) && (!cstln_out || cstln_out->writable() >= max_meas))
1150  {
1151  sampler->update_freq(freqw, chunk_size);
1152 
1153  complex<T> *pin = in.rd(), *pin0 = pin, *pend = pin + chunk_size;
1154  SOFTSYMB *pout = out.wr(), *pout0 = pout;
1155 
1156  // These are scoped outside the loop for SS and MER estimation.
1157  complex<float> sg{0.0f, 0.0f}; // Symbol before AGC;
1158  complex<float> s; // For MER estimation and constellation viewer
1159  complex<signed char> *cstln_point = NULL;
1160 
1161  while (pin < pend)
1162  {
1163  // Here mu is the time of the next symbol counted from 0 at pin.
1164  if (mu < 1)
1165  {
1166  // Here 0<=mu<1 is the fractional time of the next symbol
1167  // between pin and pin+1.
1168  sg = sampler->interp(pin, mu, phase + mu * freqw);
1169  s = sg * agc_gain;
1170 
1171  // Constellation look-up
1172  typename cstln_lut<SOFTSYMB, 256>::result *cr =
1173  cstln->lookup(s.re, s.im);
1174  *pout = cr->ss;
1175  ++pout;
1176 
1177  // PLL
1178  phase += cr->phase_error * freq_alpha;
1179  freqw += cr->phase_error * freq_beta;
1180 
1181  // Modified Mueller and Müller
1182  // mu[k]=real((c[k]-c[k-2])*conj(p[k-1])-(p[k]-p[k-2])*conj(c[k-1]))
1183  // =dot(c[k]-c[k-2],p[k-1]) - dot(p[k]-p[k-2],c[k-1])
1184  // p = received signals
1185  // c = decisions (constellation points)
1186  hist[2] = hist[1];
1187  hist[1] = hist[0];
1188  hist[0].p.re = s.re;
1189  hist[0].p.im = s.im;
1190  cstln_point = &cstln->symbols[cr->symbol];
1191  hist[0].c.re = cstln_point->re;
1192  hist[0].c.im = cstln_point->im;
1193  float muerr = ((hist[0].p.re - hist[2].p.re) * hist[1].c.re + (hist[0].p.im - hist[2].p.im) * hist[1].c.im) - ((hist[0].c.re - hist[2].c.re) * hist[1].p.re + (hist[0].c.im - hist[2].c.im) * hist[1].p.im);
1194  float mucorr = muerr * gain_mu;
1195  const float max_mucorr = 0.1;
1196  // TBD Optimize out statically
1197  if (mucorr < -max_mucorr)
1198  mucorr = -max_mucorr;
1199  if (mucorr > max_mucorr)
1200  mucorr = max_mucorr;
1201  mu += mucorr;
1202  mu += omega; // Next symbol time;
1203  } // mu<1
1204 
1205  // Next sample
1206  ++pin;
1207  --mu;
1208  phase += freqw;
1209  } // chunk_size
1210 
1211  in.read(pin - pin0);
1212  out.written(pout - pout0);
1213 
1214  // Normalize phase so that it never exceeds 32 bits.
1215  // Max freqw is 2^31/65536/chunk_size = 256 Hz
1216  // (this may happen with leandvb --drift --decim).
1217  phase = fmodf(phase, 65536); // Rounding direction irrelevant
1218 
1219  if (cstln_point)
1220  {
1221  // Output the last interpolated PSK symbol, max once per chunk_size
1222  if (cstln_out)
1223  cstln_out->write(s);
1224 
1225  // AGC
1226  // For APSK we must do AGC on the symbols, not the whole signal.
1227  // TODO Use a better estimator at low SNR.
1228  float insp = sg.re * sg.re + sg.im * sg.im;
1229  est_insp = insp * kest + est_insp * (1 - kest);
1230 
1231  if (est_insp)
1232  agc_gain = cstln_amp / gen_sqrt(est_insp);
1233 
1234  // SS and MER
1235  complex<float> ev(s.re - cstln_point->re,
1236  s.im - cstln_point->im);
1237  float sig_power, ev_power;
1238 
1239  if (cstln->nsymbols == 2)
1240  {
1241  // Special case for BPSK: Ignore quadrature component of noise.
1242  // TBD Projection on I axis assumes BPSK at 45°
1243  float sig_real = (cstln_point->re + cstln_point->im) * 0.707;
1244  float ev_real = (ev.re + ev.im) * 0.707;
1245  sig_power = sig_real * sig_real;
1246  ev_power = ev_real * ev_real;
1247  }
1248  else
1249  {
1250  sig_power = (int)cstln_point->re * cstln_point->re + (int)cstln_point->im * cstln_point->im;
1251  ev_power = ev.re * ev.re + ev.im * ev.im;
1252  }
1253 
1254  est_sp = sig_power * kest + est_sp * (1 - kest);
1255  est_ep = ev_power * kest + est_ep * (1 - kest);
1256  }
1257 
1258  // This is best done periodically ouside the inner loop,
1259  // but will cause non-deterministic output.
1260 
1261  if (!allow_drift)
1262  {
1263  if (freqw < min_freqw || freqw > max_freqw)
1264  freqw = (max_freqw + min_freqw) / 2;
1265  }
1266 
1267  // Output measurements
1268 
1269  refresh_freq_tap();
1270 
1271  meas_count += pin - pin0;
1272 
1273  while (meas_count >= meas_decimation)
1274  {
1276  if (freq_out)
1278  if (ss_out)
1279  ss_out->write(sqrtf(est_insp));
1280  if (mer_out)
1281  mer_out->write(
1282  est_ep ? 10 * logf(est_sp / est_ep) / logf(10) : 0);
1283  }
1284 
1285  } // Work to do
1286  }
static const unsigned int chunk_size
Definition: sdr.h:1046
cstln_lut< SOFTSYMB, 256 > * cstln
Definition: sdr.h:1040
pipewriter< cf32 > * cstln_out
Definition: sdr.h:1312
unsigned long meas_decimation
Definition: sdr.h:1041
complex< float > p
Definition: sdr.h:1298
pipewriter< SOFTSYMB > out
Definition: sdr.h:1303
pipewriter< float > * ss_out
Definition: sdr.h:1311
struct leansdr::cstln_receiver::@8 hist[3]
void fail(const char *s)
Definition: framework.cpp:11
result * lookup(float I, float Q)
Definition: sdr.h:689
pipewriter< float > * mer_out
Definition: sdr.h:1311
complex< float > c
Definition: sdr.h:1299
void written(unsigned long n)
Definition: framework.h:308
pipereader< complex< T > > in
Definition: sdr.h:1302
sampler_interface< T > * sampler
Definition: sdr.h:1039
T gen_sqrt(T x)
pipewriter< float > * freq_out
Definition: sdr.h:1311
void write(const T &e)
Definition: framework.h:319
complex< int8_t > * symbols
Definition: sdr.h:478
void refresh_freq_tap()
Definition: sdr.h:1290
unsigned long meas_count
Definition: sdr.h:1310
const float cstln_amp
Definition: sdr.h:404

◆ set_allow_drift()

template<typename T, typename SOFTSYMB>
void leansdr::cstln_receiver< T, SOFTSYMB >::set_allow_drift ( bool  d)
inline

Definition at line 1097 of file sdr.h.

1098  {
1099  allow_drift = d;
1100  }

◆ set_freq()

template<typename T, typename SOFTSYMB>
void leansdr::cstln_receiver< T, SOFTSYMB >::set_freq ( float  freq)
inline

Definition at line 1090 of file sdr.h.

1091  {
1092  freqw = freq * 65536;
1094  refresh_freq_tap();
1095  }
void update_freq_limits()
Definition: sdr.h:1102
void refresh_freq_tap()
Definition: sdr.h:1290

◆ set_omega()

template<typename T, typename SOFTSYMB>
void leansdr::cstln_receiver< T, SOFTSYMB >::set_omega ( float  _omega,
float  tol = 10e-6 
)
inline

Definition at line 1082 of file sdr.h.

1083  {
1084  omega = _omega;
1085  min_omega = omega * (1 - tol);
1086  max_omega = omega * (1 + tol);
1088  }
void update_freq_limits()
Definition: sdr.h:1102

◆ update_freq_limits()

template<typename T, typename SOFTSYMB>
void leansdr::cstln_receiver< T, SOFTSYMB >::update_freq_limits ( )
inline

Definition at line 1102 of file sdr.h.

1103  {
1104  // Prevent PLL from crossing +-SR/n/2 and locking at +-SR/n.
1105  int n = 4;
1106 
1107  if (cstln)
1108  {
1109  switch (cstln->nsymbols)
1110  {
1111  case 2:
1112  n = 2;
1113  break; // BPSK
1114  case 4:
1115  n = 4;
1116  break; // QPSK
1117  case 8:
1118  n = 8;
1119  break; // 8PSK
1120  case 16:
1121  n = 12;
1122  break; // 16APSK
1123  case 32:
1124  n = 16;
1125  break; // 32APSK
1126  default:
1127  n = 4;
1128  break;
1129  }
1130  }
1131 
1132  min_freqw = freqw - 65536 / max_omega / n / 2;
1133  max_freqw = freqw + 65536 / max_omega / n / 2;
1134  }
cstln_lut< SOFTSYMB, 256 > * cstln
Definition: sdr.h:1040

Member Data Documentation

◆ agc_gain

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::agc_gain
private

Definition at line 1304 of file sdr.h.

◆ allow_drift

template<typename T, typename SOFTSYMB>
bool leansdr::cstln_receiver< T, SOFTSYMB >::allow_drift

Definition at line 1045 of file sdr.h.

◆ c

template<typename T, typename SOFTSYMB>
complex<float> leansdr::cstln_receiver< T, SOFTSYMB >::c

Definition at line 1299 of file sdr.h.

◆ chunk_size

template<typename T, typename SOFTSYMB>
const unsigned int leansdr::cstln_receiver< T, SOFTSYMB >::chunk_size = 128
static

Definition at line 1046 of file sdr.h.

◆ cstln

template<typename T, typename SOFTSYMB>
cstln_lut<SOFTSYMB, 256>* leansdr::cstln_receiver< T, SOFTSYMB >::cstln

Definition at line 1040 of file sdr.h.

Referenced by DATVDemod::InitDATVFramework().

◆ cstln_out

template<typename T, typename SOFTSYMB>
pipewriter<cf32>* leansdr::cstln_receiver< T, SOFTSYMB >::cstln_out
private

Definition at line 1312 of file sdr.h.

◆ est_ep

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::est_ep
private

Definition at line 1309 of file sdr.h.

◆ est_insp

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::est_insp
private

Definition at line 1304 of file sdr.h.

◆ est_sp

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::est_sp
private

Definition at line 1308 of file sdr.h.

◆ freq_out

template<typename T, typename SOFTSYMB>
pipewriter<float>* leansdr::cstln_receiver< T, SOFTSYMB >::freq_out
private

Definition at line 1311 of file sdr.h.

◆ freq_tap

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::freq_tap

Definition at line 1288 of file sdr.h.

◆ freqw

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::freqw

Definition at line 1043 of file sdr.h.

◆ hist

struct { ... } leansdr::cstln_receiver< T, SOFTSYMB >::hist[3]

◆ in

template<typename T, typename SOFTSYMB>
pipereader<complex<T> > leansdr::cstln_receiver< T, SOFTSYMB >::in
private

Definition at line 1302 of file sdr.h.

◆ kest

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::kest

Definition at line 1047 of file sdr.h.

◆ max_freqw

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::max_freqw

Definition at line 1043 of file sdr.h.

◆ max_omega

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::max_omega

Definition at line 1042 of file sdr.h.

◆ meas_count

template<typename T, typename SOFTSYMB>
unsigned long leansdr::cstln_receiver< T, SOFTSYMB >::meas_count
private

Definition at line 1310 of file sdr.h.

◆ meas_decimation

template<typename T, typename SOFTSYMB>
unsigned long leansdr::cstln_receiver< T, SOFTSYMB >::meas_decimation

Definition at line 1041 of file sdr.h.

◆ mer_out

template<typename T, typename SOFTSYMB>
pipewriter<float> * leansdr::cstln_receiver< T, SOFTSYMB >::mer_out
private

Definition at line 1311 of file sdr.h.

◆ min_freqw

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::min_freqw

Definition at line 1043 of file sdr.h.

◆ min_omega

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::min_omega

Definition at line 1042 of file sdr.h.

◆ mu

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::mu
private

Definition at line 1305 of file sdr.h.

◆ omega

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::omega

Definition at line 1042 of file sdr.h.

◆ out

template<typename T, typename SOFTSYMB>
pipewriter<SOFTSYMB> leansdr::cstln_receiver< T, SOFTSYMB >::out
private

Definition at line 1303 of file sdr.h.

◆ p

template<typename T, typename SOFTSYMB>
complex<float> leansdr::cstln_receiver< T, SOFTSYMB >::p

Definition at line 1298 of file sdr.h.

◆ phase

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::phase
private

Definition at line 1306 of file sdr.h.

◆ pll_adjustment

template<typename T, typename SOFTSYMB>
float leansdr::cstln_receiver< T, SOFTSYMB >::pll_adjustment

Definition at line 1044 of file sdr.h.

◆ sampler

template<typename T, typename SOFTSYMB>
sampler_interface<T>* leansdr::cstln_receiver< T, SOFTSYMB >::sampler

Definition at line 1039 of file sdr.h.

◆ ss_out

template<typename T, typename SOFTSYMB>
pipewriter<float> * leansdr::cstln_receiver< T, SOFTSYMB >::ss_out
private

Definition at line 1311 of file sdr.h.


The documentation for this struct was generated from the following file: