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.
dvb.h
Go to the documentation of this file.
1 // This file is part of LeanSDR Copyright (C) 2016-2019 <pabr@pabr.org>.
2 // See the toplevel README for more information.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef LEANSDR_DVB_H
18 #define LEANSDR_DVB_H
19 
20 #include <stdint.h>
21 
22 #include "leansdr/convolutional.h"
23 #include "leansdr/rs.h"
24 #include "leansdr/sdr.h"
25 #include "leansdr/viterbi.h"
26 
27 #ifndef M_PI
28 # define M_PI 3.14159265358979323846
29 #endif
30 
31 namespace leansdr
32 {
33 
34 static const int SIZE_RSPACKET = 204;
35 static const int MPEG_SYNC = 0x47;
36 static const int MPEG_SYNC_INV = (MPEG_SYNC ^ 0xff);
37 static const int MPEG_SYNC_CORRUPTED = 0x55;
38 
39 // Generic deconvolution
40 
42 {
48  FEC78, // DVB-S
51  FEC910, // DVB-S2
55  FEC35, // DVB-S2
57 };
58 
59 // static const char *fec_names[] = {
60 // [FEC12] = "1/2",
61 // [FEC23] = "2/3",
62 // [FEC46] = "4/6",
63 // [FEC34] = "3/4",
64 // [FEC56] = "5/6",
65 // [FEC78] = "7/8",
66 // [FEC45] = "4/5",
67 // [FEC89] = "8/9",
68 // [FEC910] = "9/10",
69 // [FEC14] = "1/4",
70 // [FEC13] = "1/3",
71 // [FEC25] = "2/5",
72 // [FEC35] = "3/5",
73 // };
74 
75 // EN 300 421, section 4.4.3, table 2 Punctured code, G1=0171, G2=0133
76 static const int DVBS_G1 = 0171;
77 static const int DVBS_G2 = 0133;
78 
79 // G1 = 0b1111001
80 // G2 = 0b1011011
81 //
82 // G1 = [ 1 1 1 1 0 0 1 ]
83 // G2 = [ 1 0 1 1 0 1 1 ]
84 //
85 // C = [ G2 ;
86 // G1 ;
87 // 0 G2 ;
88 // 0 G1 ;
89 // 0 0 G2 ;
90 // 0 0 G1 ]
91 //
92 // C = [ 1 0 1 1 0 1 1 0 0 0 0 0 0 ;
93 // 1 1 1 1 0 0 1 0 0 0 0 0 0 ;
94 // 0 1 0 1 1 0 1 1 0 0 0 0 0 ;
95 // 0 1 1 1 1 0 0 1 0 0 0 0 0 ;
96 // 0 0 1 0 1 1 0 1 1 0 0 0 0 ;
97 // 0 0 1 1 1 1 0 0 1 0 0 0 0 ;
98 // 0 0 0 1 0 1 1 0 1 1 0 0 0 ;
99 // 0 0 0 1 1 1 1 0 0 1 0 0 0 ;
100 // 0 0 0 0 1 0 1 1 0 1 1 0 0 ;
101 // 0 0 0 0 1 1 1 1 0 0 1 0 0 ;
102 // 0 0 0 0 0 1 0 1 1 0 1 1 0 ;
103 // 0 0 0 0 0 1 1 1 1 0 0 1 0 ;
104 // 0 0 0 0 0 0 1 0 1 1 0 1 1 ;
105 // 0 0 0 0 0 0 1 1 1 1 0 0 1 ]
106 //
107 // IQ = [ Q1; I1; ... Q10; I10 ] = C * S
108 //
109 // D * C == [ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
110 //
111 // D = [ 0 1 0 1 1 1 0 1 1 1 0 0 0 0]
112 // D = 0x3ba
113 
114 template <typename Tbyte, Tbyte BYTE_ERASED>
116 {
118  pipebuf<eucl_ss> &_in,
119  pipebuf<Tbyte> &_out,
120  uint32_t gX,
121  uint32_t gY,
122  uint32_t pX,
123  uint32_t pY) : runnable(sch, "deconvol_sync"),
124  fastlock(false),
125  in(_in),
126  out(_out, SIZE_RSPACKET),
127  skip(0)
128  {
129  conv = new uint32_t[2];
130  conv[0] = gX;
131  conv[1] = gY;
132  nG = 2;
133  punct = new uint32_t[2];
134  punct[0] = pX;
135  punct[1] = pY;
136  punctperiod = 0;
137  punctweight = 0;
138 
139  for (int i = 0; i < 2; ++i)
140  {
141  int nbits = log2(punct[i]) + 1;
142  if (nbits > punctperiod)
143  punctperiod = nbits;
145  }
146 
147  if (sch->verbose)
148  fprintf(stderr, "puncturing %d/%d\n", punctperiod, punctweight);
149 
150  deconv = new iq_t[punctperiod];
151  deconv2 = new iq_t[punctperiod];
153  init_syncs();
154  locked = &syncs[0];
155  }
156 
158  typedef uint64_t iq_t;
159 
160  static int log2(uint64_t x)
161  {
162  int n = -1;
163  for (; x; ++n, x >>= 1)
164  ;
165  return n;
166  }
167 
168  iq_t convolve(signal_t s)
169  {
170  int sbits = log2(s) + 1;
171  iq_t iq = 0;
172  unsigned char state = 0;
173 
174  for (int b = sbits - 1; b >= 0; --b)
175  { // Feed into convolver, MSB first
176  unsigned char bit = (s >> b) & 1;
177  state = (state >> 1) | (bit << 6); // Shift register
178 
179  for (int j = 0; j < nG; ++j)
180  {
181  unsigned char xy = parity(state & conv[j]); // Taps
182  if (punct[j] & (1 << (b % punctperiod)))
183  iq = (iq << 1) | xy;
184  }
185  }
186 
187  return iq;
188  }
189 
190  void run()
191  {
192  run_decoding();
193  }
194 
195  void next_sync()
196  {
197  if (fastlock)
198  fail("Bug: next_sync() called with fastlock");
199 
200  ++locked;
201 
202  if (locked == &syncs[NSYNCS])
203  {
204  locked = &syncs[0];
205  // Try next symbol alignment (for FEC other than 1/2)
206  skip = 1;
207  }
208  }
209 
210  bool fastlock;
211 
212  private:
213  static const int maxsbits = 64;
215 
216  //static const int traceback = 48; // For code rate 7/8
217  static const int traceback = 64; // For code rate 7/8 with fastlock
218 
219  void solve_rec(iq_t prefix, unsigned int nprefix, signal_t exp, iq_t *best)
220  {
221  if (prefix > *best)
222  return;
223  if (nprefix > sizeof(prefix) * 8)
224  return;
225 
226  int solved = 1;
227 
228  for (int b = 0; b < maxsbits; ++b)
229  {
230  if (parity(prefix & response[b]) != ((exp >> b) & 1))
231  {
232  // Current candidate does not solve this column.
233  if ((response[b] >> nprefix) == 0)
234  // No more bits to trace back.
235  return;
236  solved = 0;
237  }
238  }
239 
240  if (solved)
241  {
242  *best = prefix;
243  return;
244  }
245 
246  solve_rec(prefix, nprefix + 1, exp, best);
247  solve_rec(prefix | ((iq_t)1 << nprefix), nprefix + 1, exp, best);
248  }
249 
250  static const int LATENCY = 0;
251 
253  {
254  for (int sbit = 0; sbit < maxsbits; ++sbit)
255  {
256  response[sbit] = convolve((iq_t)1 << sbit);
257  //fprintf(stderr, "response %d = %x\n", sbit, response[sbit]);
258  }
259  for (int b = 0; b < punctperiod; ++b)
260  {
261  deconv[b] = -(iq_t)1;
262  solve_rec(0, 0, 1 << (LATENCY + b), &deconv[b]);
263  }
264 
265  // Alternate polynomials for fastlock
266  for (int b = 0; b < punctperiod; ++b)
267  {
268  uint64_t d = deconv[b], d2 = d;
269  // 1/2
270  if (d == 0x00000000000003baLL)
271  d2 = 0x0000000000038ccaLL;
272  // 2/3
273  if (d == 0x0000000000000f29LL)
274  d2 = 0x000000003c569329LL;
275  if (d == 0x000000000003c552LL)
276  d2 = 0x00000000001dee1cLL;
277  if (d == 0x0000000000007948LL)
278  d2 = 0x00000001e2b49948LL;
279  if (d == 0x00000000000001deLL)
280  d2 = 0x00000000001e2a90LL;
281  // 3/4
282  if (d == 0x000000000000f247LL)
283  d2 = 0x000000000fd6383bLL;
284  if (d == 0x00000000000fd9eeLL)
285  d2 = 0x000000000fd91392LL;
286  if (d == 0x0000000000f248d8LL)
287  d2 = 0x00000000fd9eef18LL;
288  // 5/6
289  if (d == 0x0000000000f5727fLL)
290  d2 = 0x000003d5c909758fLL;
291  if (d == 0x000000003d5c90aaLL)
292  d2 = 0x0f5727f0229c90aaLL;
293  if (d == 0x000000003daa371cLL)
294  d2 = 0x000003d5f45630ecLL;
295  if (d == 0x0000000f5727ff48LL)
296  d2 = 0x0000f57d28260348LL;
297  if (d == 0x0000000f57d28260LL)
298  d2 = 0xf5727ff48128260LL;
299  // 7/8
300  if (d == 0x0000fbeac76c454fLL)
301  d2 = 0x00fb11d6ba045a8fLL;
302  if (d == 0x00000000fb11d6baLL)
303  d2 = 0xfbea3c7d930e16baLL;
304  if (d == 0x0000fb112d5038dcLL)
305  d2 = 0x00fb112d5038271cLL;
306  if (d == 0x000000fbea3c7d68LL)
307  d2 = 0x00fbeac7975462a8LL;
308  if (d == 0x00000000fb112d50LL)
309  d2 = 0x00fbea3c86793290LL;
310  if (d == 0x0000fb112dabd2e0LL)
311  d2 = 0x00fb112d50c3cd20LL;
312  if (d == 0x00000000fb11d640LL)
313  d2 = 0x00fbea3c8679c980LL;
314  if (d2 == d)
315  fail("Alt polynomial not provided");
316  deconv2[b] = d2;
317  }
318 
319  if (sch->debug)
320  {
321  for (int b = 0; b < punctperiod; ++b)
322  {
323  fprintf(stderr, "deconv[%d]=0x%016llx %d taps / %d bits\n",
324  b, (unsigned long long)deconv[b], hamming_weight(deconv[b]), log2(deconv[b]) + 1);
325  }
326  }
327 
328  // Sanity check
329  for (int b = 0; b < punctperiod; ++b)
330  {
331  for (int i = 0; i < maxsbits; ++i)
332  {
333  iq_t iq = convolve((iq_t)1 << (LATENCY + i));
334  int expect = (b == i) ? 1 : 0;
335  int d = parity(iq & deconv[b]);
336  if (d != expect)
337  fail("Failed to inverse convolutional coding");
338  int d2 = parity(iq & deconv2[b]);
339  if (d2 != expect)
340  fail("Failed to inverse convolutional coding (alt)");
341  }
342 
343  if (traceback > sizeof(iq_t) * 8)
344  fail("Bug: traceback exceeds register size");
345  if (log2(deconv[b]) + 1 > traceback)
346  fail("traceback insufficient for deconvolution");
347  if (log2(deconv2[b]) + 1 > traceback)
348  fail("traceback insufficient for deconvolution (alt)");
349  }
350  }
351 
352  static const int NSYNCS = 4;
353 
354  struct sync_t
355  {
356  u8 lut[2][2]; // lut[(re>0)?1:0][(im>0)?1:0] = 0b000000IQ
357  iq_t in;
358  int n_in;
359  signal_t out;
360  int n_out;
361  // Auxiliary shift register for fastlock
362  iq_t in2;
363  int n_in2, n_out2;
364  } syncs[NSYNCS];
365 
366  void init_syncs()
367  {
368  // EN 300 421, section 4.5, Figure 5 QPSK constellation
369  // Four rotations * two conjugations.
370  // 180° rotation is detected as polarity inversion in mpeg_sync.
371  for (int sync_id = 0; sync_id < NSYNCS; ++sync_id)
372  {
373  for (int re_pos = 0; re_pos <= 1; ++re_pos)
374  {
375  for (int im_pos = 0; im_pos <= 1; ++im_pos)
376  {
377  int re_neg = !re_pos; //int im_neg = !im_pos;
378  int I, Q;
379  switch (sync_id)
380  {
381  case 0: // Direct 0°
382  I = re_pos ? 0 : 1;
383  Q = im_pos ? 0 : 1;
384  break;
385  case 1: // Direct 90°
386  I = im_pos ? 0 : 1;
387  Q = re_neg ? 0 : 1;
388  break;
389  case 2: // Conj 0°
390  I = re_pos ? 0 : 1;
391  Q = im_pos ? 1 : 0;
392  break;
393  case 3: // Conj 90°
394  I = im_pos ? 1 : 0;
395  Q = re_neg ? 0 : 1;
396  break;
397 #if 0
398  case 4: // Direct 180°
399  I = re_neg ? 0 : 1;
400  Q = im_neg ? 0 : 1;
401  break;
402  case 5:// Direct 270°
403  I = im_neg ? 0 : 1;
404  Q = re_pos ? 0 : 1;
405  break;
406  case 6:// Conj 180°
407  I = re_neg ? 0 : 1;
408  Q = im_neg ? 1 : 0;
409  break;
410  case 7:// Conj 270°
411  I = im_neg ? 1 : 0;
412  Q = re_pos ? 0 : 1;
413  break;
414 #endif
415  }
416 
417  syncs[sync_id].lut[re_pos][im_pos] = (I << 1) | Q;
418  }
419  }
420 
421  syncs[sync_id].n_in = 0;
422  syncs[sync_id].n_out = 0;
423  syncs[sync_id].n_in2 = 0;
424  syncs[sync_id].n_out2 = 0;
425  }
426  }
427 
428  // TODO: Unroll for each code rate setting.
429  // 1/2: 8 symbols -> 1 byte
430  // 2/3 12 symbols -> 2 bytes
431  // 3/4 16 symbols -> 3 bytes
432  // 5/6 24 symbols -> 5 bytes
433  // 7/8 32 symbols -> 7 bytes
434 
435  inline Tbyte readbyte(sync_t *s, eucl_ss *&p)
436  {
437  while (s->n_out < 8)
438  {
439  iq_t iq = s->in;
440 
441  while (s->n_in < traceback)
442  {
443  u8 iqbits = s->lut[(p->nearest & 2) ? 1 : 0][p->nearest & 1];
444  ++p;
445  iq = (iq << 2) | iqbits;
446  s->n_in += 2;
447  }
448 
449  s->in = iq;
450 
451  for (int b = punctperiod - 1; b >= 0; --b)
452  {
453  u8 bit = parity(iq & deconv[b]);
454  s->out = (s->out << 1) | bit;
455  }
456 
457  s->n_out += punctperiod;
458  s->n_in -= punctweight;
459  }
460 
461  Tbyte res = (s->out >> (s->n_out - 8)) & 255;
462  s->n_out -= 8;
463  return res;
464  }
465 
466  inline unsigned long readerrors(sync_t *s, eucl_ss *&p)
467  {
468  unsigned long res = 0;
469 
470  while (s->n_out2 < 8)
471  {
472  iq_t iq = s->in2;
473 
474  while (s->n_in2 < traceback)
475  {
476  u8 iqbits = s->lut[(p->nearest & 2) ? 1 : 0][p->nearest & 1];
477  ++p;
478  iq = (iq << 2) | iqbits;
479  s->n_in2 += 2;
480  }
481 
482  s->in2 = iq;
483 
484  for (int b = punctperiod - 1; b >= 0; --b)
485  {
486  u8 bit = parity(iq & deconv[b]);
487  u8 bit2 = parity(iq & deconv2[b]);
488  if (bit2 != bit)
489  ++res;
490  }
491 
492  s->n_out2 += punctperiod;
493  s->n_in2 -= punctweight;
494  }
495 
496  s->n_out2 -= 8;
497  return res;
498  }
499 
501  {
502  in.read(skip);
503  skip = 0;
504 
505  // 8 byte margin to fill the deconvolver
506  if (in.readable() < 64)
507  return;
508 
509  int maxrd = (in.readable() - 64) / (punctweight / 2) * punctperiod / 8;
510  int maxwr = out.writable();
511  int n = (maxrd < maxwr) ? maxrd : maxwr;
512 
513  if (!n)
514  return;
515  // Require enough symbols to discriminate in fastlock mode
516  // (threshold must be less than size of rspacket)
517 
518  if (n < 32)
519  return;
520 
521  if (fastlock)
522  {
523  // Try all sync alignments
524  long errors_best = 1 << 30;
525  sync_t *best = &syncs[0];
526 
527  for (sync_t *s = syncs; s < syncs + NSYNCS; ++s)
528  {
529  eucl_ss *pin = in.rd();
530  long errors = 0;
531 
532  for (int c = n; c--;)
533  errors += readerrors(s, pin);
534 
535  if (errors < errors_best)
536  {
537  errors_best = errors;
538  best = s;
539  }
540  }
541 
542  if (best != locked)
543  {
544  // Another alignment produces fewer bit errors
545  if (sch->debug)
546  {
547  fprintf(stderr, "{%d->%d}\n", (int)(locked - syncs), (int)(best - syncs));
548  }
549 
550  locked = best;
551  }
552 
553  // If deconvolution bit error rate > 33%, try next sample alignment
554  if (errors_best > n * 8 / 3)
555  {
556  // fprintf(stderr, ">");
557  skip = 1;
558  }
559  }
560 
561  eucl_ss *pin = in.rd(), *pin0 = pin;
562  Tbyte *pout = out.wr(), *pout0 = pout;
563 
564  while (n--)
565  {
566  *pout++ = readbyte(locked, pin);
567  }
568 
569  in.read(pin - pin0);
570  out.written(pout - pout0);
571  }
572 
575  // DECONVOL
576  int nG;
577  uint32_t *conv; // [nG] Convolution polynomials; MSB is newest
578  uint32_t *punct; // [nG] Puncturing pattern
580  iq_t *deconv; // [punctperiod] Deconvolution polynomials
581  iq_t *deconv2; // [punctperiod] Alternate polynomials (for fastlock)
582  sync_t *locked;
583  int skip;
584 };
585 
587 
588 deconvol_sync_simple *make_deconvol_sync_simple(scheduler *sch,
589  pipebuf<eucl_ss> &_in,
590  pipebuf<u8> &_out,
591  enum code_rate rate);
592 
593 // CONVOLUTIONAL ENCODER
594 
595 static const uint16_t polys_fec12[] = {
596  DVBS_G1,
597  DVBS_G2 // X1Y1
598 };
599 
600 static const uint16_t polys_fec23[] = {
601  DVBS_G1, DVBS_G2,
602  DVBS_G2 << 1 // X1Y1Y2
603 };
604 
605 // Same code rate as 2/3, usable with QPSK
606 static const uint16_t polys_fec46[] = {
607  DVBS_G1, DVBS_G2,
608  DVBS_G2 << 1, // X1Y1Y2
609  DVBS_G1 << 2, DVBS_G2 << 2,
610  DVBS_G2 << 3 // X3Y3Y4
611 };
612 
613 static const uint16_t polys_fec34[] = {
614  DVBS_G1,
615  DVBS_G2, // X1Y1
616  DVBS_G2 << 1,
617  DVBS_G1 << 2 // Y2X3
618 };
619 
620 static const uint16_t polys_fec45[] = {
621  // Non standard
622  DVBS_G1,
623  DVBS_G2, // X1Y1
624  DVBS_G2 << 1,
625  DVBS_G1 << 2, // Y2X3
626  DVBS_G1 << 3 // X4
627 };
628 
629 static const uint16_t polys_fec56[] = {
630  DVBS_G1,
631  DVBS_G2, // X1Y1
632  DVBS_G2 << 1,
633  DVBS_G1 << 2, // Y2X3
634  DVBS_G2 << 3,
635  DVBS_G1 << 4 // Y4X5
636 };
637 
638 static const uint16_t polys_fec78[] = {
639  DVBS_G1,
640  DVBS_G2, // X1Y1
641  DVBS_G2 << 1,
642  DVBS_G2 << 2, // Y2Y3
643  DVBS_G2 << 3,
644  DVBS_G1 << 4, // Y4X5
645  DVBS_G2 << 5,
646  DVBS_G1 << 6 // Y6X7
647 };
648 
649 // FEC parameters, for convolutional coding only (not S2).
650 static struct fec_spec
651 {
652  int bits_in; // Entering the convolutional coder
653  int bits_out; // Exiting the convolutional coder
654  const uint16_t *polys; // [bits_out]
655 } fec_specs[FEC_COUNT] =
656  {
657  {1, 2, polys_fec12},
658  {2, 3, polys_fec23},
659  {4, 6, polys_fec46},
660  {3, 4, polys_fec34},
661  {5, 6, polys_fec56},
662  {7, 8, polys_fec78},
663  {4, 5, polys_fec45}, // Non-standard
664 };
665 
667 {
668  typedef u8 uncoded_byte;
669  typedef u8 hardsymbol;
670 
673  pipebuf<hardsymbol> &_out,
674  code_rate fec,
675  int bits_per_symbol) : runnable(sch, "dvb_convol"),
676  in(_in),
677  out(_out, 64) // BPSK 7/8: 7 bytes in, 64 symbols out
678  {
679  fec_spec *fs = &fec_specs[fec];
680 
681  if (!fs->bits_in)
682  fail("Unexpected FEC");
683 
684  convol.bits_in = fs->bits_in;
685  convol.bits_out = fs->bits_out;
686  convol.polys = fs->polys;
687  convol.bps = bits_per_symbol;
688 
689  // FEC must output a whole number of IQ symbols
690  if (convol.bits_out % convol.bps)
691  fail("Code rate not suitable for this constellation");
692  }
693 
694  void run()
695  {
696  int count = min(in.readable(), out.writable() * convol.bps / convol.bits_out * convol.bits_in / 8);
697  // Process in multiples of the puncturing period and of 8 bits.
698  int chunk = convol.bits_in;
699  count = (count / chunk) * chunk;
700  convol.encode(in.rd(), out.wr(), count);
701  in.read(count);
702  int nout = count * 8 / convol.bits_in * convol.bits_out / convol.bps;
703  out.written(nout);
704  }
705 
706  private:
710 };
711 // dvb_convol
712 
713 // NEW ALGEBRAIC DECONVOLUTION
714 
715 // QPSK 1/2 only;
716 // With DVB-S polynomials hardcoded.
717 
718 template <typename Tin>
720 {
721  typedef u8 decoded_byte;
723  static const int chunk_size = 64; // At least 2*sizeof(Thist)/8
724 
726  pipebuf<Tin> &_in,
727  pipebuf<decoded_byte> &_out) : runnable(sch, "deconvol_sync_multipoly"),
728  resync_period(32),
729  in(_in),
730  out(_out, chunk_size),
731  resync_phase(0)
732  {
733  init_syncs();
734  locked = &syncs[0];
735  }
736 
737  void run()
738  {
739  while (in.readable() >= chunk_size * 8 && out.writable() >= chunk_size)
740  {
741  int errors_best = 1 << 30;
742  sync_t *best = NULL;
743 
744  for (sync_t *s = syncs; s < syncs + NSYNCS; ++s)
745  {
746  if (resync_phase != 0 && s != locked)
747  // Decode only the currently-locked alignment
748  continue;
749 
750  Tin *pin = in.rd();
751  static decoded_byte dummy[chunk_size];
752  decoded_byte *pout = (s == locked) ? out.wr() : dummy;
753  int nerrors = s->deconv.run(pin, s->lut, pout, chunk_size);
754 
755  if (nerrors < errors_best)
756  {
757  errors_best = nerrors;
758  best = s;
759  }
760  }
761 
762  in.read(chunk_size * 8);
763  out.written(chunk_size);
764 
765  if (best != locked)
766  {
767  if (sch->debug)
768  fprintf(stderr, "%%%d", (int)(best - syncs));
769  locked = best;
770  }
771 
772  if (++resync_phase >= resync_period)
773  resync_phase = 0;
774  } // Work to do
775  } // run()
776 
777  private:
781 
782  static const int NSYNCS = 4;
783 
784  struct sync_t
785  {
787  u8 lut[4]; // TBD Swap and flip bits in the polynomials instead.
788  } syncs[NSYNCS];
789 
791 
792  void init_syncs()
793  {
794  for (int s = 0; s < NSYNCS; ++s)
795  // EN 300 421, section 4.5, Figure 5 QPSK constellation
796  // Four rotations * two conjugations.
797  // 180° rotation is detected as polarity inversion in mpeg_sync.
798  // 2 | 0
799  // --+--
800  // 3 | 1
801  // 0°
802  syncs[0].lut[0] = 0;
803 
804  syncs[0].lut[1] = 1;
805  syncs[0].lut[2] = 2;
806  syncs[0].lut[3] = 3;
807  // 90°
808  syncs[1].lut[0] = 2;
809  syncs[1].lut[1] = 0;
810  syncs[1].lut[2] = 3;
811  syncs[1].lut[3] = 1;
812  // 0° conjugated
813  syncs[2].lut[0] = 1;
814  syncs[2].lut[1] = 0;
815  syncs[2].lut[2] = 3;
816  syncs[2].lut[3] = 2;
817  // 90° conjugated
818  syncs[3].lut[0] = 0;
819  syncs[3].lut[1] = 2;
820  syncs[3].lut[2] = 1;
821  syncs[3].lut[3] = 3;
822  }
823 };
824 // dvb_deconvol_sync
825 
828 
829 // BIT ALIGNMENT AND MPEG SYNC DETECTION
830 
831 template <typename Tbyte, Tbyte BYTE_ERASED>
833 {
834  int scan_syncs, want_syncs;
835  unsigned long lock_timeout;
836  bool fastlock;
838 
840  pipebuf<Tbyte> &_in,
841  pipebuf<Tbyte> &_out,
842  deconvol_sync<Tbyte, 0> *_deconv,
843  pipebuf<int> *_state_out = NULL,
844  pipebuf<unsigned long> *_locktime_out = NULL) : runnable(sch, "sync_detect"),
845  scan_syncs(8),
846  want_syncs(4),
847  lock_timeout(4),
848  fastlock(false),
849  resync_period(1),
850  in(_in),
851  out(_out, SIZE_RSPACKET * (scan_syncs + 1)),
852  deconv(_deconv),
853  polarity(0),
854  resync_phase(0),
855  bitphase(0),
856  synchronized(false),
857  next_sync_count(0),
858  report_state(true)
859  {
860  state_out = _state_out ? new pipewriter<int>(*_state_out) : NULL;
861  locktime_out = _locktime_out ? new pipewriter<unsigned long>(*_locktime_out) : NULL;
862  }
863 
864  void run()
865  {
866  if (report_state && state_out && state_out->writable() >= 1)
867  {
868  // Report unlocked state on first invocation.
869  state_out->write(0);
870  report_state = false;
871  }
872 
873  if (synchronized)
874  {
875  run_decoding();
876  }
877  else
878  {
879  if (fastlock)
880  run_searching_fast();
881  else
882  run_searching();
883  }
884  }
885 
887  {
888  bool next_sync = false;
889  int chunk = SIZE_RSPACKET * scan_syncs;
890 
891  while (in.readable() >= chunk + 1 // Need 1 ahead for bit shifting
892  && out.writable() >= chunk // Use as temp buffer
893  && (!state_out || state_out->writable() >= 1))
894  {
895  if (search_sync())
896  return;
897 
898  in.read(chunk);
899  // Switch to next bit alignment
900  ++bitphase;
901 
902  if (bitphase == 8)
903  {
904  bitphase = 0;
905  next_sync = true;
906  }
907  }
908 
909  if (next_sync)
910  {
911  // No lock this time
912  ++next_sync_count;
913 
914  if (next_sync_count >= 3)
915  {
916  // After a few cycles without a lock, resync the deconvolver.
917  next_sync_count = 0;
918  if (deconv)
919  deconv->next_sync();
920  }
921  }
922  }
923 
925  {
926  int chunk = SIZE_RSPACKET * scan_syncs;
927 
928  while (in.readable() >= chunk + 1 // Need 1 ahead for bit shifting
929  && out.writable() >= chunk // Use as temp buffer
930  && (!state_out || state_out->writable() >= 1))
931  {
932  if (resync_phase == 0)
933  {
934  // Try all bit alighments
935  for (bitphase = 0; bitphase <= 7; ++bitphase)
936  {
937  if (search_sync())
938  return;
939  }
940  }
941 
942  in.read(SIZE_RSPACKET);
943 
944  if (++resync_phase >= resync_period)
945  resync_phase = 0;
946  }
947  }
948 
949  bool search_sync()
950  {
951  int chunk = SIZE_RSPACKET * scan_syncs;
952  // Bit-shift [scan_sync] packets according to current [bitphase]
953  Tbyte *pin = in.rd(), *pend = pin + chunk;
954  Tbyte *pout = out.wr();
955  unsigned short w = *pin++;
956 
957  for (; pin <= pend; ++pin, ++pout)
958  {
959  w = (w << 8) | *pin;
960  *pout = w >> bitphase;
961  }
962 
963  // Search for [want_sync] start codes at all 204 offsets
964  for (int i = 0; i < SIZE_RSPACKET; ++i)
965  {
966  int nsyncs_p = 0, nsyncs_n = 0; // # start codes assuming pos/neg polarity
967  int phase8_p = -1, phase8_n = -1; // Position in sequence of 8 packets
968  Tbyte *p = &out.wr()[i];
969 
970  for (int j = 0; j < scan_syncs; ++j, p += SIZE_RSPACKET)
971  {
972  Tbyte b = *p;
973 
974  if (b == MPEG_SYNC)
975  {
976  ++nsyncs_p;
977  phase8_n = (8 - j) & 7;
978  }
979 
980  if (b == MPEG_SYNC_INV)
981  {
982  ++nsyncs_n;
983  phase8_p = (8 - j) & 7;
984  }
985  }
986 
987  // Detect most likely polarity
988  int nsyncs;
989 
990  if (nsyncs_p > nsyncs_n)
991  {
992  polarity = 0;
993  nsyncs = nsyncs_p;
994  phase8 = phase8_p;
995  }
996  else
997  {
998  polarity = -1;
999  nsyncs = nsyncs_n;
1000  phase8 = phase8_n;
1001  }
1002 
1003  if (nsyncs >= want_syncs && phase8 >= 0)
1004  {
1005  if (sch->debug)
1006  fprintf(stderr, "Locked\n");
1007 
1008  if (!i)
1009  { // Avoid fixpoint detection in scheduler
1010  i = SIZE_RSPACKET;
1011  phase8 = (phase8 + 1) & 7;
1012  }
1013 
1014  in.read(i); // Skip to first start code
1015  synchronized = true;
1016  lock_timeleft = lock_timeout;
1017  locktime = 0;
1018 
1019  if (state_out)
1020  state_out->write(1);
1021 
1022  return true;
1023  }
1024  }
1025  return false;
1026  }
1027 
1029  {
1030  while (in.readable() >= SIZE_RSPACKET + 1 && out.writable() >= SIZE_RSPACKET && (!state_out || state_out->writable() >= 1) && (!locktime_out || locktime_out->writable() >= 1))
1031  {
1032  Tbyte *pin = in.rd(), *pend = pin + SIZE_RSPACKET;
1033  Tbyte *pout = out.wr();
1034  unsigned short w = *pin++;
1035 
1036  for (; pin <= pend; ++pin, ++pout)
1037  {
1038  w = (w << 8) | *pin;
1039  *pout = (w >> bitphase) ^ polarity;
1040  }
1041 
1042  in.read(SIZE_RSPACKET);
1043  Tbyte syncbyte = *out.wr();
1044  out.written(SIZE_RSPACKET);
1045  ++locktime;
1046 
1047  if (locktime_out)
1048  locktime_out->write(locktime);
1049 
1050  // Reset timer if sync byte is correct
1051  Tbyte expected = phase8 ? MPEG_SYNC : MPEG_SYNC_INV;
1052 
1053  if (syncbyte == expected)
1054  lock_timeleft = lock_timeout;
1055 
1056  phase8 = (phase8 + 1) & 7;
1057  --lock_timeleft;
1058 
1059  if (!lock_timeleft)
1060  {
1061  if (sch->debug)
1062  fprintf(stderr, "Unlocked\n");
1063 
1064  synchronized = false;
1065  next_sync_count = 0;
1066 
1067  if (state_out)
1068  state_out->write(0);
1069 
1070  return;
1071  }
1072  }
1073  }
1074 
1075  private:
1079  unsigned char polarity; // XOR mask, 0 or 0xff
1082  bool synchronized;
1084  int phase8; // Position in 8-packet cycle, -1 if not synchronized
1085  unsigned long lock_timeleft;
1086  unsigned long locktime;
1090 };
1091 
1092 template <typename Tbyte>
1093 struct rspacket
1094 {
1095  Tbyte data[SIZE_RSPACKET];
1096 };
1097 
1098 // INTERLEAVER
1099 
1101 {
1103  pipebuf<rspacket<u8>> &_in,
1104  pipebuf<u8> &_out) : runnable(sch, "interleaver"),
1105  in(_in),
1106  out(_out, SIZE_RSPACKET)
1107  {
1108  }
1109 
1110  void run()
1111  {
1112  while (in.readable() >= 12 && out.writable() >= SIZE_RSPACKET)
1113  {
1114  rspacket<u8> *pin = in.rd();
1115  u8 *pout = out.wr();
1116  int delay = 0;
1117 
1118  for (int i = 0; i < SIZE_RSPACKET; ++i, ++pout, delay = (delay + 1) % 12)
1119  {
1120  *pout = pin[11 - delay].data[i];
1121  }
1122 
1123  in.read(1);
1124  out.written(SIZE_RSPACKET);
1125  }
1126  }
1127 
1128  private:
1131 };
1132 // interleaver
1133 
1134 // DEINTERLEAVER
1135 
1136 template <typename Tbyte>
1138 {
1140  pipebuf<Tbyte> &_in,
1141  pipebuf<rspacket<Tbyte>> &_out) : runnable(sch, "deinterleaver"),
1142  in(_in),
1143  out(_out)
1144  {
1145  }
1146 
1147  void run()
1148  {
1149  while (in.readable() >= 17 * 11 * 12 + SIZE_RSPACKET && out.writable() >= 1)
1150  {
1151  Tbyte *pin = in.rd() + 17 * 11 * 12, *pend = pin + SIZE_RSPACKET;
1152  Tbyte *pout = out.wr()->data;
1153 
1154  for (int delay = 17 * 11; pin < pend; ++pin, ++pout, delay = (delay - 17 + 17 * 12) % (17 * 12))
1155  {
1156  *pout = pin[-delay * 12];
1157  }
1158 
1159  in.read(SIZE_RSPACKET);
1160  out.written(1);
1161  }
1162  }
1163 
1164  private:
1167 };
1168 // deinterleaver
1169 
1170 static const int SIZE_TSPACKET = 188; // TBD remove
1171 struct tspacket
1172 {
1173  static const int SIZE = 188;
1174  u8 data[SIZE_TSPACKET];
1175 };
1176 
1177 // RS ENCODER
1178 
1180 {
1182  pipebuf<tspacket> &_in,
1183  pipebuf<rspacket<u8>> &_out) : runnable(sch, "RS encoder"),
1184  in(_in),
1185  out(_out)
1186  {
1187  }
1188 
1189  void run()
1190  {
1191  while (in.readable() >= 1 && out.writable() >= 1)
1192  {
1193  u8 *pin = in.rd()->data;
1194  u8 *pout = out.wr()->data;
1195  // The first 188 bytes are the uncoded message P(X)
1196  memcpy(pout, pin, SIZE_TSPACKET);
1197  // Append 16 RS parity bytes R(X) = - (P(X)*X^16 mod G(X))
1198  // so that G(X) divides the coded message S(X) = P(X)*X^16 - R(X).
1199  rs.encode(pout);
1200  in.read(1);
1201  out.written(1);
1202  }
1203  }
1204 
1205  private:
1209 };
1210 // rs_encoder
1211 
1212 // RS DECODER
1213 
1214 template <typename Tbyte, int BYTE_ERASED>
1216 {
1218 
1220  pipebuf<rspacket<Tbyte>> &_in,
1221  pipebuf<tspacket> &_out,
1222  pipebuf<int> *_bitcount = NULL,
1223  pipebuf<int> *_errcount = NULL) : runnable(sch, "RS decoder"),
1224  in(_in),
1225  out(_out)
1226  {
1227  bitcount = _bitcount ? new pipewriter<int>(*_bitcount) : NULL;
1228  errcount = _errcount ? new pipewriter<int>(*_errcount) : NULL;
1229  }
1230 
1231  void run()
1232  {
1233  if (bitcount && bitcount->writable() < 1)
1234  return;
1235  if (errcount && errcount->writable() < 1)
1236  return;
1237 
1238  int nbits = 0, nerrs = 0;
1239 
1240  while (in.readable() >= 1 && out.writable() >= 1)
1241  {
1242  Tbyte *pin = in.rd()->data;
1243  u8 *pout = out.wr()->data;
1244 
1245  nbits += SIZE_RSPACKET * 8;
1246 
1247  // The message is the first 188 bytes.
1248  if (sizeof(Tbyte) == 1)
1249  memcpy(pout, pin, SIZE_TSPACKET);
1250  else
1251  fail("Erasures not implemented");
1252 
1253  u8 synd[16];
1254  bool corrupted = rs.syndromes(pin, synd);
1255 
1256 #if 0
1257  if ( ! corrupted ) {
1258  // Test BM
1259  fprintf(stderr, "Simulating errors\n");
1260  pin[203] ^= 42;
1261  pin[202] ^= 99;
1262  corrupted = rs.syndromes(pin, synd);
1263  }
1264 #endif
1265  if (!corrupted)
1266  {
1267  if (sch->debug)
1268  fprintf(stderr, "_"); // Packet received without errors.
1269  }
1270  else
1271  {
1272  corrupted = rs.correct(synd, pout, pin, &nerrs);
1273 
1274  if (sch->debug)
1275  {
1276  if (!corrupted)
1277  fprintf(stderr, "."); // Errors were corrected.
1278  else
1279  fprintf(stderr, "!"); // Packet still corrupted.
1280  }
1281  }
1282 
1283  in.read(1);
1284 
1285  // Output corrupted packets (with a special mark)
1286  // otherwise the derandomizer will lose synchronization.
1287  if (corrupted)
1288  pout[0] ^= MPEG_SYNC_CORRUPTED;
1289 
1290  out.written(1);
1291  }
1292 
1293  if (nbits)
1294  {
1295  if (bitcount)
1296  bitcount->write(nbits);
1297  if (errcount)
1298  errcount->write(nerrs);
1299  }
1300  }
1301 
1302  private:
1306 };
1307 // rs_decoder
1308 
1309 // RANDOMIZER
1310 
1312 {
1314  pipebuf<tspacket> &_in,
1315  pipebuf<tspacket> &_out) : runnable(sch, "derandomizer"),
1316  in(_in),
1317  out(_out)
1318  {
1319  precompute_pattern();
1320  pos = pattern;
1321  pattern_end = pattern + sizeof(pattern) / sizeof(pattern[0]);
1322  }
1323 
1325  {
1326  // EN 300 421, section 4.4.1 Transport multiplex adaptation
1327  pattern[0] = 0xff; // Invert one in eight sync bytes
1328  unsigned short st = 000251; // 0b 000 000 010 101 001 (Fig 2 reversed)
1329 
1330  for (int i = 1; i < 188 * 8; ++i)
1331  {
1332  u8 out = 0;
1333 
1334  for (int n = 8; n--;)
1335  {
1336  int bit = ((st >> 13) ^ (st >> 14)) & 1; // Taps
1337  out = (out << 1) | bit; // MSB first
1338  st = (st << 1) | bit; // Feedback
1339  }
1340 
1341  pattern[i] = (i % 188) ? out : 0; // Inhibit on sync bytes
1342  }
1343  }
1344 
1345  void run()
1346  {
1347  while (in.readable() >= 1 && out.writable() >= 1)
1348  {
1349  u8 *pin = in.rd()->data, *pend = pin + SIZE_TSPACKET;
1350  u8 *pout = out.wr()->data;
1351  if (pin[0] != MPEG_SYNC)
1352  fprintf(stderr, "randomizer: bad MPEG sync %02x\n", pin[0]);
1353  for (; pin < pend; ++pin, ++pout, ++pos)
1354  *pout = *pin ^ *pos;
1355  if (pos == pattern_end)
1356  pos = pattern;
1357  in.read(1);
1358  out.written(1);
1359  }
1360  }
1361 
1362  private:
1363  u8 pattern[188 * 8], *pattern_end, *pos;
1366 };
1367 // randomizer
1368 
1369 // DERANDOMIZER
1370 
1372 {
1374  pipebuf<tspacket> &_in,
1375  pipebuf<tspacket> &_out) : runnable(sch, "derandomizer"),
1376  in(_in),
1377  out(_out)
1378  {
1379  precompute_pattern();
1380  pos = pattern;
1381  pattern_end = pattern + sizeof(pattern) / sizeof(pattern[0]);
1382  }
1383 
1385  {
1386  // EN 300 421, section 4.4.1 Transport multiplex adaptation
1387  pattern[0] = 0xff; // Restore the inverted sync byte
1388  unsigned short st = 000251; // 0b 000 000 010 101 001 (Fig 2 reversed)
1389 
1390  for (int i = 1; i < 188 * 8; ++i)
1391  {
1392  u8 out = 0;
1393 
1394  for (int n = 8; n--;)
1395  {
1396  int bit = ((st >> 13) ^ (st >> 14)) & 1; // Taps
1397  out = (out << 1) | bit; // MSB first
1398  st = (st << 1) | bit; // Feedback
1399  }
1400 
1401  pattern[i] = (i % 188) ? out : 0; // Inhibit on sync bytes
1402  }
1403  }
1404 
1405  void run()
1406  {
1407  while (in.readable() >= 1 && out.writable() >= 1)
1408  {
1409  u8 *pin = in.rd()->data, *pend = pin + SIZE_TSPACKET;
1410  u8 *pout = out.wr()->data;
1411 
1412  if (pin[0] == MPEG_SYNC_INV || pin[0] == (MPEG_SYNC_INV ^ MPEG_SYNC_CORRUPTED))
1413  {
1414  if (pos != pattern)
1415  {
1416  if (sch->debug)
1417  fprintf(stderr, "derandomizer: resynchronizing\n");
1418  pos = pattern;
1419  }
1420  }
1421 
1422  for (; pin < pend; ++pin, ++pout, ++pos)
1423  {
1424  *pout = *pin ^ *pos;
1425  }
1426 
1427  if (pos == pattern_end)
1428  pos = pattern;
1429 
1430  in.read(1);
1431 
1432  u8 sync = out.wr()->data[0];
1433 
1434  if (sync == MPEG_SYNC)
1435  {
1436  out.written(1);
1437  }
1438  else
1439  {
1440  if (sync != (MPEG_SYNC ^ MPEG_SYNC_CORRUPTED))
1441  if (sch->debug)
1442  fprintf(stderr, "(%02x)", sync);
1443 
1444  out.wr()->data[1] |= 0x80; // Set the Transport Error Indicator bit
1445  // We could output corrupted packets here, in case the
1446  // MPEG decoder can use them somehow.
1447  //out.written(1);
1448  }
1449  }
1450  }
1451 
1452  private:
1453  u8 pattern[188 * 8], *pattern_end, *pos;
1456 };
1457 // derandomizer
1458 
1459 // VITERBI DECODING
1460 // Supports all code rates and constellations
1461 // Simplified metric to support large constellations.
1462 
1463 // This version implements puncturing by expanding the trellis.
1464 // TBD Compare performance vs skipping updates in a 1/2 trellis.
1465 
1467 {
1468  typedef uint8_t TS, TCS, TUS;
1469  typedef int32_t TBM; // Only 16 bits per IQ, but several IQ per Viterbi CS
1470  typedef int32_t TPM;
1472 
1473  // 1/2: 6 bits of state, 1 bit in, 2 bits out
1477 
1478  // 2/3: 6 bits of state, 2 bits in, 3 bits out
1482 
1483  // 4/6: 6 bits of state, 4 bits in, 6 bits out
1487 
1488  // 3/4: 6 bits of state, 3 bits in, 4 bits out
1492 
1493  // 4/5: 6 bits of state, 4 bits in, 5 bits out (non-standard)
1497 
1498  // 5/6: 6 bits of state, 5 bits in, 6 bits out
1502 
1503  // 7/8: 6 bits of state, 7 bits in, 8 bits out
1507 
1508  private:
1512  fec_spec *fec;
1513  int bits_per_symbol; // Bits per IQ symbol (not per coded symbol)
1514  int nsyncs;
1515  int nshifts;
1516 
1517  struct sync
1518  {
1519  int shift;
1520  dvb_dec_interface *dec;
1521  TCS *map; // [nsymbols]
1522  } * syncs; // [nsyncs]
1523 
1525  static const int chunk_size = 128;
1527 
1528  public:
1530 
1532  pipebuf<eucl_ss> &_in,
1533  pipebuf<unsigned char> &_out,
1534  cstln_lut<eucl_ss, 256> *_cstln,
1535  code_rate cr) : runnable(sch, "viterbi_sync"),
1536  in(_in),
1537  out(_out, chunk_size),
1538  cstln(_cstln),
1539  current_sync(0),
1540  resync_phase(0),
1541  resync_period(32) // 1/32 = 9% synchronization overhead TBD
1542  {
1543  bits_per_symbol = log2i(cstln->nsymbols);
1544  fec = &fec_specs[cr];
1545 
1546  { // Sanity check: FEC block size must be a multiple of label size.
1547  int symbols_per_block = fec->bits_out / bits_per_symbol;
1548  if (bits_per_symbol * symbols_per_block != fec->bits_out)
1549  fail("Code rate not suitable for this constellation");
1550  }
1551 
1552  int nconj;
1553 
1554  switch (cstln->nsymbols)
1555  {
1556  case 2:
1557  nconj = 1;
1558  break; // Conjugation is not relevant for BPSK
1559  default:
1560  nconj = 2;
1561  break;
1562  }
1563 
1564  int nrotations;
1565 
1566  switch (cstln->nsymbols)
1567  {
1568  case 2:
1569  case 4:
1570  // For BPSK and QPSK, 180° rotation is handled as
1571  // polarity inversion in mpeg_sync.
1572  nrotations = cstln->nrotations / 2;
1573  break;
1574  default:
1575  nrotations = cstln->nrotations;
1576  break;
1577  }
1578 
1579  nshifts = fec->bits_out / bits_per_symbol;
1580  nsyncs = nconj * nrotations * nshifts;
1581 
1582  // TBD Many HOM constellations are labelled in such a way
1583  // that certain rot/conj combinations are equivalent to
1584  // polarity inversion. We could reduce nsyncs.
1585 
1586  syncs = new sync[nsyncs];
1587 
1588  for (int s = 0; s < nsyncs; ++s)
1589  {
1590  // Bit pattern [shift|conj|rot]
1591  int rot = s % nrotations;
1592  int conj = (s / nrotations) % nconj;
1593  int shift = s / nrotations / nconj;
1594  syncs[s].shift = shift;
1595 
1596  if (shift) // Reuse identical map
1597  syncs[s].map = syncs[conj * nrotations + rot].map;
1598  else
1599  syncs[s].map = init_map(conj,
1600  2 * M_PI * rot / cstln->nrotations);
1601 #if 0
1602  fprintf(stderr, "sync %3d: conj%d offs%d rot%d/%d map:",
1603  s, conj, syncs[s].shift, rot, cstln->nrotations);
1604  for ( int i=0; i<cstln->nsymbols; ++i )
1605  fprintf(stderr, " %2d", syncs[s].map[i]);
1606  fprintf(stderr, "\n");
1607 #endif
1608  }
1609 
1610  if (cr == FEC12)
1611  {
1612  trellis_12 *trell = new trellis_12();
1613  trell->init_convolutional(fec->polys);
1614  for (int s = 0; s < nsyncs; ++s)
1615  syncs[s].dec = new dvb_dec_12(trell);
1616  }
1617  else if (cr == FEC23)
1618  {
1619  trellis_23 *trell = new trellis_23();
1620  trell->init_convolutional(fec->polys);
1621  for (int s = 0; s < nsyncs; ++s)
1622  syncs[s].dec = new dvb_dec_23(trell);
1623  }
1624  else if (cr == FEC46)
1625  {
1626  trellis_46 *trell = new trellis_46();
1627  trell->init_convolutional(fec->polys);
1628  for (int s = 0; s < nsyncs; ++s)
1629  syncs[s].dec = new dvb_dec_46(trell);
1630  }
1631  else if (cr == FEC34)
1632  {
1633  trellis_34 *trell = new trellis_34();
1634  trell->init_convolutional(fec->polys);
1635  for (int s = 0; s < nsyncs; ++s)
1636  syncs[s].dec = new dvb_dec_34(trell);
1637  }
1638  else if (cr == FEC45)
1639  {
1640  trellis_45 *trell = new trellis_45();
1641  trell->init_convolutional(fec->polys);
1642  for (int s = 0; s < nsyncs; ++s)
1643  syncs[s].dec = new dvb_dec_45(trell);
1644  }
1645  else if (cr == FEC56)
1646  {
1647  trellis_56 *trell = new trellis_56();
1648  trell->init_convolutional(fec->polys);
1649  for (int s = 0; s < nsyncs; ++s)
1650  syncs[s].dec = new dvb_dec_56(trell);
1651  }
1652  else if (cr == FEC78)
1653  {
1654  trellis_78 *trell = new trellis_78();
1655  trell->init_convolutional(fec->polys);
1656  for (int s = 0; s < nsyncs; ++s)
1657  syncs[s].dec = new dvb_dec_78(trell);
1658  }
1659  else
1660  {
1661  fail("CR not supported");
1662  }
1663  }
1664 
1665  TCS *init_map(bool conj, float angle)
1666  {
1667  // Each constellation has its own pattern for labels.
1668  // Here we simply tabulate systematically.
1669  TCS *map = new TCS[cstln->nsymbols];
1670  float ca = cosf(angle), sa = sinf(angle);
1671 
1672  for (int i = 0; i < cstln->nsymbols; ++i)
1673  {
1674  int8_t I = cstln->symbols[i].re;
1675  int8_t Q = cstln->symbols[i].im;
1676 
1677  if (conj)
1678  Q = -Q;
1679 
1680  int8_t RI = I * ca - Q * sa;
1681  int8_t RQ = I * sa + Q * ca;
1682  cstln_lut<eucl_ss, 256>::result *pr = cstln->lookup(RI, RQ);
1683  map[i] = pr->ss.nearest;
1684  }
1685 
1686  return map;
1687  }
1688 
1689  inline TUS update_sync(int s, eucl_ss *pin, TPM *discr)
1690  {
1691  // Read one FEC ouput block
1692  pin += syncs[s].shift;
1693  TCS cs = 0;
1694  TBM cost = 0;
1695 
1696  for (int i = 0; i < nshifts; ++i, ++pin)
1697  {
1698  cs = (cs << bits_per_symbol) | syncs[s].map[pin->nearest];
1699  cost -= pin->discr2;
1700  }
1701 
1702  return syncs[s].dec->update(cs, cost, discr);
1703  }
1704 
1705  void run()
1706  {
1707  // Number of FEC blocks to fill the bitpath depth.
1708  // Before that we cannot discriminate between synchronizers
1709  int discr_delay = 64 / fec->bits_in;
1710 
1711  // Process [chunk_size] FEC blocks at a time
1712 
1713  TPM *totaldiscr = new TPM[nsyncs];
1714 
1715  while ((long)in.readable() >= nshifts * chunk_size + (nshifts - 1) && (long)out.writable() * 8 >= fec->bits_in * chunk_size)
1716  {
1717  for (int s = 0; s < nsyncs; ++s)
1718  totaldiscr[s] = 0;
1719 
1720  uint64_t outstream = 0;
1721  int nout = 0;
1722  eucl_ss *pin = in.rd();
1723 
1724  for (int blocknum = 0; blocknum < chunk_size; ++blocknum, pin += nshifts)
1725  {
1726  TPM discr;
1727  TUS result = update_sync(current_sync, pin, &discr);
1728  outstream = (outstream << fec->bits_in) | result;
1729  nout += fec->bits_in;
1730 
1731  if (blocknum >= discr_delay)
1732  totaldiscr[current_sync] += discr;
1733 
1734  if (!resync_phase)
1735  {
1736  // Every [resync_period] chunks, also run the other decoders.
1737  for (int s = 0; s < nsyncs; ++s)
1738  {
1739  if (s == current_sync)
1740  continue;
1741 
1742  TPM discr;
1743  (void)update_sync(s, pin, &discr);
1744 
1745  if (blocknum >= discr_delay)
1746  totaldiscr[s] += discr;
1747  }
1748  }
1749 
1750  while (nout >= 8)
1751  {
1752  out.write(outstream >> (nout - 8));
1753  nout -= 8;
1754  }
1755  } // chunk_size
1756 
1757  in.read(chunk_size * nshifts);
1758 
1759  if (nout)
1760  fail("overlapping out");
1761 
1762  if (!resync_phase)
1763  {
1764  // Switch to another decoder ?
1765  int best = current_sync;
1766 
1767  for (int s = 0; s < nsyncs; ++s)
1768  if (totaldiscr[s] > totaldiscr[best])
1769  best = s;
1770 
1771  if (best != current_sync)
1772  {
1773  if (sch->debug)
1774  fprintf(stderr, "{%d->%d}", current_sync, best);
1775  current_sync = best;
1776  }
1777  }
1778 
1779  if (++resync_phase >= resync_period)
1780  resync_phase = 0;
1781  }
1782 
1783  delete[] totaldiscr;
1784  }
1785 };
1786 // viterbi_sync
1787 
1788 } // namespace leansdr
1789 
1790 #endif // LEANSDR_DVB_H
uint32_t * punct
Definition: dvb.h:578
int resync_period
Definition: dvb.h:837
viterbi_dec< TS, 64, TUS, 8, TCS, 16, TBM, TPM, path_34 > dvb_dec_34
Definition: dvb.h:1491
trellis< TS, 64, TUS, 128, 256 > trellis_78
Definition: dvb.h:1505
bool search_sync()
Definition: dvb.h:949
iq_t response[maxsbits]
Definition: dvb.h:214
pipereader< Tbyte > in
Definition: dvb.h:1165
int want_syncs
Definition: dvb.h:834
trellis< TS, 64, TUS, 16, 32 > trellis_45
Definition: dvb.h:1495
trellis< TS, 64, TUS, 32, 64 > trellis_56
Definition: dvb.h:1500
pipewriter< unsigned long > * locktime_out
Definition: dvb.h:1088
trellis< TS, 64, TUS, 2, 4 > trellis_12
Definition: dvb.h:1475
pipewriter< u8 > out
Definition: dvb.h:1130
int log2i(uint64_t x)
Definition: math.cpp:48
deconvol_sync_simple * make_deconvol_sync_simple(scheduler *sch, pipebuf< eucl_ss > &_in, pipebuf< u8 > &_out, enum code_rate rate)
Definition: dvb.cpp:6
convol_multipoly< uint16_t, 16 > convol
Definition: dvb.h:709
rs_engine rs
Definition: dvb.h:1217
deconvol_sync(scheduler *sch, pipebuf< eucl_ss > &_in, pipebuf< Tbyte > &_out, uint32_t gX, uint32_t gY, uint32_t pX, uint32_t pY)
Definition: dvb.h:117
static const int NSYNCS
Definition: dvb.h:352
randomizer(scheduler *sch, pipebuf< tspacket > &_in, pipebuf< tspacket > &_out)
Definition: dvb.h:1313
pipereader< Tin > in
Definition: dvb.h:778
uint32_t * conv
Definition: dvb.h:577
void inverse_convolution()
Definition: dvb.h:252
bitpath< uint32_t, TUS, 1, 32 > path_12
Definition: dvb.h:1474
rs_encoder(scheduler *sch, pipebuf< tspacket > &_in, pipebuf< rspacket< u8 >> &_out)
Definition: dvb.h:1181
void run()
Definition: dvb.h:694
Tbyte data[SIZE_RSPACKET]
Definition: dvb.h:1095
rs_decoder(scheduler *sch, pipebuf< rspacket< Tbyte >> &_in, pipebuf< tspacket > &_out, pipebuf< int > *_bitcount=NULL, pipebuf< int > *_errcount=NULL)
Definition: dvb.h:1219
deconvol_poly2< Tin, uint32_t, uint64_t, 0x3ba, 0x38f70 > deconv
Definition: dvb.h:786
unsigned long readerrors(sync_t *s, eucl_ss *&p)
Definition: dvb.h:466
static const int traceback
Definition: dvb.h:217
unsigned long locktime
Definition: dvb.h:1086
pipewriter< Tbyte > out
Definition: dvb.h:574
unsigned char u8
Definition: framework.h:453
static const int maxsbits
Definition: dvb.h:213
void run_decoding()
Definition: dvb.h:1028
bitpath< uint64_t, TUS, 4, 16 > path_46
Definition: dvb.h:1484
unsigned char polarity
Definition: dvb.h:1079
pipereader< uncoded_byte > in
Definition: dvb.h:707
viterbi_dec< TS, 64, TUS, 16, TCS, 32, TBM, TPM, path_45 > dvb_dec_45
Definition: dvb.h:1496
pipereader< eucl_ss > in
Definition: dvb.h:573
uint64_t signal_t
Definition: dvb.h:157
pipereader< tspacket > in
Definition: dvb.h:1454
derandomizer(scheduler *sch, pipebuf< tspacket > &_in, pipebuf< tspacket > &_out)
Definition: dvb.h:1373
void run_searching_fast()
Definition: dvb.h:924
uint16_t discr2
Definition: sdr.h:435
bitpath< uint64_t, TUS, 5, 12 > path_56
Definition: dvb.h:1499
int hamming_weight(uint8_t x)
Definition: math.cpp:6
pipewriter< int > * errcount
Definition: dvb.h:1305
bool correct(u8 synd[16], u8 pout[188], u8 pin[204]=NULL, int *bits_corrected=NULL)
Definition: rs.h:201
void solve_rec(iq_t prefix, unsigned int nprefix, signal_t exp, iq_t *best)
Definition: dvb.h:219
Fixed< IntType, IntBits > exp(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2289
viterbi_dec< TS, 64, TUS, 4, TCS, 8, TBM, TPM, path_23 > dvb_dec_23
Definition: dvb.h:1481
TCS * init_map(bool conj, float angle)
Definition: dvb.h:1665
viterbi_sync(scheduler *sch, pipebuf< eucl_ss > &_in, pipebuf< unsigned char > &_out, cstln_lut< eucl_ss, 256 > *_cstln, code_rate cr)
Definition: dvb.h:1531
unsigned int uint32_t
Definition: rtptypes_win.h:46
pipereader< rspacket< u8 > > in
Definition: dvb.h:1129
void run_decoding()
Definition: dvb.h:500
code_rate
Definition: dvb.h:41
bitpath< uint64_t, TUS, 4, 16 > path_45
Definition: dvb.h:1494
pipereader< tspacket > in
Definition: dvb.h:1364
deconvol_sync< u8, 0 > deconvol_sync_simple
Definition: dvb.h:586
unsigned long lock_timeout
Definition: dvb.h:835
struct leansdr::deconvol_sync::sync_t syncs[NSYNCS]
void precompute_pattern()
Definition: dvb.h:1324
trellis< TS, 64, TUS, 16, 64 > trellis_46
Definition: dvb.h:1485
dvb_deconvol_sync< u8 > dvb_deconvol_sync_hard
Definition: dvb.h:827
unsigned char uint8_t
Definition: rtptypes_win.h:42
pipereader< Tbyte > in
Definition: dvb.h:1076
pipewriter< hardsymbol > out
Definition: dvb.h:708
pipewriter< Tbyte > out
Definition: dvb.h:1077
trellis< TS, 64, TUS, 8, 16 > trellis_34
Definition: dvb.h:1490
unsigned short uint16_t
Definition: rtptypes_win.h:44
pipereader< rspacket< Tbyte > > in
Definition: dvb.h:1303
dvb_deconvol_sync(scheduler *sch, pipebuf< Tin > &_in, pipebuf< decoded_byte > &_out)
Definition: dvb.h:725
void fail(const char *s)
Definition: framework.cpp:11
result * lookup(float I, float Q)
Definition: sdr.h:689
viterbi_dec< TS, 64, TUS, 2, TCS, 4, TBM, TPM, path_12 > dvb_dec_12
Definition: dvb.h:1476
static int log2(uint64_t x)
Definition: dvb.h:160
int32_t i
Definition: decimators.h:244
pipewriter< tspacket > out
Definition: dvb.h:1455
sync_t * locked
Definition: dvb.h:582
pipewriter< rspacket< Tbyte > > out
Definition: dvb.h:1166
char int8_t
Definition: rtptypes_win.h:41
trellis< TS, 64, TUS, 4, 8 > trellis_23
Definition: dvb.h:1480
static const int LATENCY
Definition: dvb.h:250
pipereader< eucl_ss > in
Definition: dvb.h:1509
int int32_t
Definition: rtptypes_win.h:45
void init_syncs()
Definition: dvb.h:366
bitpath< uint64_t, TUS, 7, 9 > path_78
Definition: dvb.h:1504
void run_searching()
Definition: dvb.h:886
#define M_PI
Definition: dvb.h:28
cstln_lut< eucl_ss, 256 > * cstln
Definition: dvb.h:1511
pipereader< tspacket > in
Definition: dvb.h:1207
dvb_convol(scheduler *sch, pipebuf< uncoded_byte > &_in, pipebuf< hardsymbol > &_out, code_rate fec, int bits_per_symbol)
Definition: dvb.h:671
viterbi_dec< TS, 64, TUS, 32, TCS, 64, TBM, TPM, path_56 > dvb_dec_56
Definition: dvb.h:1501
fec_spec * fec
Definition: dvb.h:1512
Tbyte readbyte(sync_t *s, eucl_ss *&p)
Definition: dvb.h:435
uint8_t nearest
Definition: sdr.h:436
viterbi_dec< TS, 64, TUS, 16, TCS, 64, TBM, TPM, path_46 > dvb_dec_46
Definition: dvb.h:1486
dvb_deconvol_sync< eucl_ss > dvb_deconvol_sync_soft
Definition: dvb.h:826
viterbi_dec< TS, 64, TUS, 128, TCS, 256, TBM, TPM, path_78 > dvb_dec_78
Definition: dvb.h:1506
viterbi_dec_interface< TUS, TCS, TBM, TPM > dvb_dec_interface
Definition: dvb.h:1471
dvb_dec_interface * dec
Definition: dvb.h:1520
rs_engine rs
Definition: dvb.h:1206
bool syndromes(const u8 *poly, u8 *synd)
Definition: rs.h:132
void precompute_pattern()
Definition: dvb.h:1384
void init_convolutional(const uint16_t G[])
Definition: viterbi.h:65
bitpath< uint64_t, TUS, 3, 21 > path_23
Definition: dvb.h:1479
int resync_phase
Definition: dvb.h:1080
pipewriter< rspacket< u8 > > out
Definition: dvb.h:1208
unsigned char parity(uint8_t x)
Definition: math.cpp:27
scheduler * sch
Definition: framework.h:199
void next_sync()
Definition: dvb.h:195
uint64_t iq_t
Definition: dvb.h:158
void write(const T &e)
Definition: framework.h:319
complex< int8_t > * symbols
Definition: sdr.h:478
unsigned long lock_timeleft
Definition: dvb.h:1085
pipewriter< tspacket > out
Definition: dvb.h:1365
bool report_state
Definition: dvb.h:1089
int next_sync_count
Definition: dvb.h:1083
void run()
Definition: dvb.h:864
pipewriter< unsigned char > out
Definition: dvb.h:1510
pipewriter< int > * state_out
Definition: dvb.h:1087
deinterleaver(scheduler *sch, pipebuf< Tbyte > &_in, pipebuf< rspacket< Tbyte >> &_out)
Definition: dvb.h:1139
interleaver(scheduler *sch, pipebuf< rspacket< u8 >> &_in, pipebuf< u8 > &_out)
Definition: dvb.h:1102
bool fastlock
Definition: dvb.h:836
pipewriter< tspacket > out
Definition: dvb.h:1304
void read(unsigned long n)
Definition: framework.h:367
deconvol_sync< Tbyte, 0 > * deconv
Definition: dvb.h:1078
pipewriter< decoded_byte > out
Definition: dvb.h:779
mpeg_sync(scheduler *sch, pipebuf< Tbyte > &_in, pipebuf< Tbyte > &_out, deconvol_sync< Tbyte, 0 > *_deconv, pipebuf< int > *_state_out=NULL, pipebuf< unsigned long > *_locktime_out=NULL)
Definition: dvb.h:839
TUS update_sync(int s, eucl_ss *pin, TPM *discr)
Definition: dvb.h:1689
T min(const T &x, const T &y)
Definition: framework.h:440
unsigned __int64 uint64_t
Definition: rtptypes_win.h:48
bitpath< uint64_t, TUS, 3, 21 > path_34
Definition: dvb.h:1489
iq_t convolve(signal_t s)
Definition: dvb.h:168