17 #ifndef LEANSDR_DVBS2_H 18 #define LEANSDR_DVBS2_H 43 static const int S2_MAX_ERR_SOF_INITIAL = 1;
44 static const int S2_MAX_ERR_SOF = 13;
45 static const int S2_MAX_ERR_PLSCODE = 8;
46 static const int S2_MAX_ERR_PILOT = 10;
48 static const int pilot_length = 36;
62 for (
int s = 0; s <
LENGTH; ++s)
64 int angle = ((VALUE >> (LENGTH - 1 - s)) & 1) * 2 + (s & 1);
79 static const int COUNT = 128;
91 for (
int index = 0; index < COUNT; ++index)
94 for (
int row = 0; row < 6; ++row)
95 if ((index >> (6 - row)) & 1)
98 for (
int bit = 31; bit >= 0; --bit)
100 int yi = (y >> bit) & 1;
102 code = (code << 2) | (yi << 1) | (yi ^ 1);
104 code = (code << 2) | (yi << 1) | yi;
109 codewords[index] = code;
113 int yi = (code >> (LENGTH - 1 -
i)) & 1;
114 int nyi = yi ^ (
i & 1);
115 symbols[index][
i].
re =
cstln_amp * (1 - 2 * nyi) / sqrtf(2);
116 symbols[index][
i].
im =
cstln_amp * (1 - 2 * yi) / sqrtf(2);
120 static const uint64_t SCRAMBLING = 0x719d83c953422dfa;
132 uint32_t stx = 0x00001, sty = 0x3ffff;
134 for (
int i = 0;
i < codenum; ++
i)
137 for (
int i = 0;
i < 131072; ++
i)
139 int zn = (stx ^ sty) & 1;
145 for (
int i = 0;
i < 131072; ++
i)
147 int zn = (stx ^ sty) & 1;
155 int bit = ((X >> 7) ^ X) & 1;
156 return ((bit << 18) | X) >> 1;
160 int bit = ((Y >> 10) ^ (Y >> 7) ^ (Y >> 5) ^ Y) & 1;
161 return ((bit << 18) | Y) >> 1;
174 for (
int i = 0;
i <
sizeof(pattern); ++
i)
177 for (
int n = 8; n--;)
179 int bit = ((st >> 13) ^ (st >> 14)) & 1;
180 out = (out << 1) | bit;
181 st = (st << 1) | bit;
188 for (
int i = 0;
i < bbsize; ++
i)
189 out[
i] = in[
i] ^ pattern[
i];
206 template <
typename SOFTSYMB>
222 static const int MAX_SLOTS_PER_FRAME = 360;
223 static const int MAX_SYMBOLS_PER_FRAME =
225 ((MAX_SLOTS_PER_FRAME - 1) / 16) * pilot_length;
288 fail(
"Invalid MODCOD number");
291 fail(
"Unsupported MODCOD");
297 template <
typename T>
303 :
runnable(sch,
"S2 frame transmitter"),
304 in(_in), out(_out,
modcod_info::MAX_SYMBOLS_PER_FRAME)
307 qsymbols[0].re = +amp;
308 qsymbols[0].im = +amp;
309 qsymbols[1].re = +amp;
310 qsymbols[1].im = -amp;
311 qsymbols[2].re = -amp;
312 qsymbols[2].im = +amp;
313 qsymbols[3].re = -amp;
314 qsymbols[3].im = -amp;
318 while (in.readable() >= 1)
322 fail(
"Expected PLS pseudo-slot");
326 if (in.readable() < 1 + nslots)
330 (pls->
pilots ? ((nslots - 1) / 16) * pilot_length : 0));
331 if (out.writable() < nsymbols)
333 update_cstln(mcinfo);
334 int nw = run_frame(pls, mcinfo, pin + 1, nslots, out.wr());
336 fail(
"Bug: s2_frame_transmitter overflow");
338 out.written(nsymbols);
348 memcpy(pout, sof.symbols, sof.LENGTH *
sizeof(*pout));
350 int pls_index = (pls->
modcod << 2) | (pls->
sf << 1) | pls->
pilots;
351 memcpy(pout, plscodes.symbols[pls_index], plscodes.LENGTH *
sizeof(*pout));
352 pout += plscodes.LENGTH;
354 int till_next_pilot = pls->
pilots ? 16 : nslots;
355 uint8_t *scr = &scrambling.Rn[0];
356 for (
int S = 0; S < nslots; ++S, ++pin, --till_next_pilot)
358 if (till_next_pilot == 0)
361 for (
int s = 0; s < pilot_length; ++s, ++scr, ++pout)
362 scramble(&qsymbols[0], *scr, pout);
363 till_next_pilot = 16;
367 fail(
"s2_frame_transmitter: bad input sequence");
368 const hard_ss *ps = pin->symbols;
369 for (
int s = 0; s < pin->LENGTH; ++s, ++ps, ++scr, ++pout)
370 scramble(&csymbols[*ps], *scr, pout);
406 fprintf(stderr,
"Warning: Variable MODCOD is inefficient\n");
411 fprintf(stderr,
"Building constellation %d\n", mcinfo->
nsymbols);
414 mcinfo->
g1, mcinfo->
g2, mcinfo->
g3);
416 for (
int s = 0; s < cstln->
nsymbols; ++s)
431 static int pl_errors = 0, pl_symbols = 0;
433 #define TEST_DIVERSITY 0 435 template <
typename T,
typename SOFTSYMB>
443 static const int MAX_SYMBOLS_PER_FRAME =
457 :
runnable(sch,
"S2 frame receiver"),
459 meas_decimation(1048576),
462 in_power(0), ev_power(0), agc_gain(1), agc_bw(1e-3),
465 in(_in), out(_out, 1 +
modcod_info::MAX_SLOTS_PER_FRAME),
471 cstln_pls_out(
opt_writer(_cstln_pls_out, 1024)),
472 symbols_out(
opt_writer(_symbols_out, MAX_SYMBOLS_PER_FRAME)),
486 fprintf(stderr,
"** DEBUG: Diversity test mode (slower)\n");
514 int min_samples = (1 + MAX_SYMBOLS_PER_FRAME +
517 while (in.readable() >= min_samples + sampler->
readahead() &&
529 report_state =
false;
551 memset(hist, 0,
sizeof(hist));
564 freqw16 = 65536 * Ftune;
565 min_freqw16 = freqw16 - 65536.0 / 9;
566 max_freqw16 = freqw16 + 65536.0 / 9;
570 int nsamples = MAX_SYMBOLS_PER_FRAME * omega;
571 for (
int s = nsamples; s--; ++pin)
580 if (coarse_count == 50)
582 float freqw = atan2f(diffcorr.
im, diffcorr.
re) * omega;
583 fprintf(stderr,
"COARSE(%d): %f rad/symb (%.0f Hz at %.0f baud)\n",
584 coarse_count, freqw, freqw * Fm / (2 *
M_PI), Fm);
586 freqw16 = freqw * 65536 / (2*
M_PI);
588 fprintf(stderr,
"Ignoring coarse det, using %f\n", freqw16 * Fm / 65536);
590 enter_frame_search();
601 fprintf(stderr,
"ACQ\n");
602 state = FRAME_SEARCH;
608 if (cstln_out && cstln_out->writable() >= 1024)
609 psampled = cstln_out->wr();
614 phase16 -= 65536 *
floor(phase16 / 65536);
616 int nsymbols = MAX_SYMBOLS_PER_FRAME;
625 for (
int s = 0; s < nsymbols; ++s)
632 if (psampled && s < 1024)
637 uint8_t symb = track_symbol(&ss, p, qpsk, 1);
640 for (
sync *ps = syncs; ps < syncs + nsyncs; ++ps)
642 ps->hist = (ps->hist << 1) | ((ps->tobpsk >> symb) & 1);
644 if (errors <= S2_MAX_ERR_SOF_INITIAL)
647 fprintf(stderr,
"Found SOF+%d at %d offset %f\n",
648 errors, s, ps->offset16);
649 ss.
ph16 += ps->offset16;
650 in.read(ss.
p - in.rd());
655 cstln_out->written(psampled - cstln_out->wr());
656 enter_frame_locked();
664 in.read(ss.
p - in.rd());
669 cstln_out->written(psampled - cstln_out->wr());
677 fprintf(stderr,
"LOCKED\n");
678 state = FRAME_LOCKED;
698 ph16 = fmodf(ph16, 65536.0f);
702 #define xfprintf(...) \ 710 if (cstln_out && cstln_out->writable() >= 1024)
711 psampled = cstln_out->wr();
715 if (cstln_pls_out && cstln_pls_out->writable() >= 1024)
716 psampled_pls = cstln_pls_out->wr();
721 complex<float> *psymbols = symbols_out ? symbols_out->wr() : NULL;
725 xfprintf(stderr,
"lock0step fw= %f (%.0f Hz) mu=%f\n",
726 freqw16, freqw16 * Fm / 65536, mu);
728 sampler_state ss = {in.rd(), mu, phase16, freqw16, scrambling.Rn};
737 for (
int s = 0; s < plscodes.LENGTH; ++s)
742 *psymbols++ = p * scale_symbols;
747 int bit = (p.
im < 1);
748 plscode = (plscode << 1) | bit;
751 int pls_errors = S2_MAX_ERR_PLSCODE + 1;
753 for (
int i = 0;
i < plscodes.COUNT; ++
i)
765 fprintf(stderr,
"Too many errors in plheader (%d)\n", pls_errors);
766 in.read(ss.
p - in.rd());
767 enter_frame_search();
773 pls_symbols, plscodes.LENGTH);
775 align_phase(&ss, pls_corr);
778 pls.
modcod = pls_index >> 2;
779 pls.
sf = pls_index & 2;
780 pls.
pilots = pls_index & 1;
781 xfprintf(stderr,
"PLS: modcod %d, short=%d, pilots=%d (%d errors)\n",
786 fprintf(stderr,
"Unsupported or corrupted MODCOD\n");
787 in.read(ss.
p - in.rd());
788 enter_frame_search();
791 #if 1 // TBD use fec_infos 794 fprintf(stderr,
"Unsupported or corrupted FEC\n");
795 in.read(ss.
p - in.rd());
796 enter_frame_search();
801 if (mcinfo->
c != m_modcodType) {
802 m_modcodType = mcinfo->
c;
804 if (mcinfo->
rate != m_modcodRate) {
805 m_modcodRate = mcinfo->
rate;
809 if (!cstln || cstln->nsymbols != mcinfo->
nsymbols)
813 fprintf(stderr,
"Warning: Variable MODCOD is inefficient\n");
816 fprintf(stderr,
"Creating LUT for %s ratecode %d\n",
819 mcinfo->
g1, mcinfo->
g2, mcinfo->
g3);
821 cstln->m_typeCode = (
int) mcinfo->
c;
822 cstln->m_setByModcod =
true;
824 fprintf(stderr,
"Dumping constellation LUT to stdout.\n");
840 int pilot_errors = 0;
843 int till_next_pls = pls.
pilots ? 16 : S;
845 for (
int leansdr_slots = S; leansdr_slots--; ++pout, --till_next_pls)
847 if (till_next_pls == 0)
852 for (
int s = 0; s < pilot_length; ++s)
859 *psymbols++ = p * scale_symbols;
861 (void)track_symbol(&ss, p, qpsk, 1);
865 if (d.
im < 0 || d.
re < 0)
870 if (errors > S2_MAX_ERR_PILOT)
873 fprintf(stderr,
"Too many errors in pilot (%d/36)\n", errors);
874 in.read(ss.
p - in.rd());
875 enter_frame_search();
878 pilot_errors += errors;
880 align_phase(&ss, corr);
886 for (
int s = 0; s < pout->
LENGTH; ++s)
888 p = interp_next(&ss) * agc_gain;
891 *psymbols++ = p * scale_symbols;
893 #if 1 || TEST_DIVERSITY 894 (void)track_symbol(&ss, p, cstln, 0);
898 SOFTSYMB *symb = &cstln->lookup(d.
re, d.
im)->ss;
899 #else // Avoid scaling floats. May wrap at very low SNR. 900 SOFTSYMB *symb = &cstln->lookup((
int)d.
re, (
int)d.
im)->ss;
910 memset(hist, 0,
sizeof(hist));
913 for (
int s = 0; s < sof.LENGTH; ++s)
920 *psymbols++ = p * scale_symbols;
922 uint8_t symb = track_symbol(&ss, p, qpsk, 1);
925 int bit = (p.
im < 0);
926 sofbits = (sofbits << 1) | bit;
927 sof_corr +=
conjprod(sof.symbols[s], p);
930 if (sof_errors >= S2_MAX_ERR_SOF)
933 fprintf(stderr,
"Too many errors in SOF (%d/26)\n", sof_errors);
934 in.read(ss.
p - in.rd());
939 align_phase(&ss, sof_corr);
942 out.written(pout - pout0);
945 meas_count += ss.
p - in.rd();
946 in.read(ss.
p - in.rd());
953 cstln_out->written(psampled - cstln_out->wr());
955 cstln_pls_out->written(psampled_pls - cstln_pls_out->wr());
958 symbols_out->written(psymbols - symbols_out->wr());
960 if (meas_count >= meas_decimation)
962 opt_write(freq_out, freqw16 / 65536 / omega);
966 opt_write(mer_out, 10 * logf(mer) / logf(10));
967 meas_count -= meas_decimation;
970 int all_errors = pls_errors + pilot_errors + sof_errors;
971 int max_errors = plscodes.LENGTH + sof.LENGTH;
973 max_errors += ((S - 1) / 16) * pilot_length;
975 xfprintf(stderr,
"success fw= %f (%.0f Hz) mu= %f " 976 "errors=%d/64+%d+%d/26 = %2d/%d\n",
977 freqw16, freqw16 * Fm / 65536, mu,
978 pls_errors, pilot_errors, sof_errors, all_errors, max_errors);
979 pl_errors += all_errors;
980 pl_symbols += max_errors;
985 fprintf(stderr,
"PL SER: %f ppm\n", pl_errors / (pl_symbols + 1e-6) * 1e6);
991 for (
int i = 0;
i < n; ++
i)
997 float in_p = p.
re * p.
re + p.
im * p.
im;
998 in_power = in_p * agc_bw + in_power * (1.0f - agc_bw);
1006 if (!strongpls || !cstln)
1014 agc_gain =
cstln_amp / cstln->amp_max / in_amp;
1056 float cmu = 1.0f - ss->
mu;
1058 ss->
p[0].im*cmu + ss->
p[1].im*ss->
mu);
1077 float err = atan2f(c.
im,c.
re) * (65536/(2*
M_PI));
1082 float err = c.
im / c.
re * (65536 / (2 *
M_PI));
1092 float kph, kfw, kmu;
1099 ss->
ph16 += cr->phase_error * gains[mode].kph;
1100 ss->
fw16 += cr->phase_error * gains[mode].kfw;
1101 if (ss->
fw16 < min_freqw16)
1102 ss->
fw16 = min_freqw16;
1103 if (ss->
fw16 > max_freqw16)
1104 ss->
fw16 = max_freqw16;
1110 hist[0].c.
re = cp->
re;
1111 hist[0].c.im = cp->
im;
1113 ((hist[0].p.re - hist[2].p.re) * hist[1].c.re +
1114 (hist[0].p.im - hist[2].p.im) * hist[1].c.im) -
1115 ((hist[0].c.re - hist[2].c.re) * hist[1].p.re +
1116 (hist[0].c.im - hist[2].c.im) * hist[1].p.
im);
1117 float mucorr = muerr * gains[mode].kmu;
1118 const float max_mucorr = 0.1;
1120 if (mucorr < -max_mucorr)
1121 mucorr = -max_mucorr;
1122 if (mucorr > max_mucorr)
1123 mucorr = max_mucorr;
1127 float ev_p = ev.
re * ev.
re + ev.
im * ev.
im;
1128 ev_power = ev_p * agc_bw + ev_power * (1.0f - agc_bw);
1143 static const int MAXSYNCS = 8;
1150 } syncs[MAXSYNCS], *current_sync;
1157 int random_decision = 0;
1161 fprintf(stderr,
"Special case for 8PSK locking as QPSK pi/8\n");
1165 for (
int r = 0; r < nrot; ++r)
1167 if (nsyncs == MAXSYNCS)
1168 fail(
"Bug: too many syncs");
1169 sync *s = &syncs[nsyncs++];
1171 float angle = -2 *
M_PI * r / nrot;
1176 float re = p.
re * cosf(angle) - p.
im * sinf(angle);
1177 float im = p.
re * sinf(angle) + p.
im * cosf(angle);
1185 bit = random_decision;
1186 random_decision ^= 1;
1212 static const int MAX_SLOTS = 240;
1213 static const int MAX_SYMBOLS =
1217 template <
typename SOFTBYTE>
1221 SOFTBYTE bytes[64800 / 8];
1233 in(_in), out(_out, 1 + 360)
1254 serialize_qpsk(pbytes, nslots, pout);
1260 interleave(bps, rows, pbytes, nslots,
false, pout);
1262 interleave(bps, rows, pbytes, nslots,
true, pout);
1274 #if 0 // For reference 1277 for ( ; nslots; --nslots,++pout ) {
1280 for (
int ns=pout->
LENGTH; ns--; ++ps ) {
1281 if ( nacc < 2 ) { acc=*pin++; nacc=8; }
1287 if ( nacc )
fail(
"Bug: s2_interleaver");
1290 fatal(
"Bug: Truncated byte");
1291 for (; nslots; nslots -= 2)
1298 for (
int i = 0;
i < 22; ++
i)
1302 *ps++ = (b >> 4) & 3;
1303 *ps++ = (b >> 2) & 3;
1308 *ps++ = (b >> 4) & 3;
1313 *ps++ = (b >> 2) & 3;
1315 for (
int i = 0;
i < 22; ++
i)
1319 *ps++ = (b >> 4) & 3;
1320 *ps++ = (b >> 2) & 3;
1330 #if 0 // For reference 1331 static void interleave(
int bps,
int rows,
1332 const hard_sb *pin,
int nslots,
1334 if ( bps==4 && rows==4050 && msb_first )
1335 return interleave4050(pin, nslots, pout);
1336 if ( rows % 8 )
fatal(
"modcod/framesize combination not supported\n");
1337 int stride = rows/8;
1340 for ( ; nslots; --nslots,++pout ) {
1343 for (
int ns=pout->
LENGTH; ns--; ++ps ) {
1346 for (
int b=0; b<bps; ++b,pi+=stride ) accs[b] = *pi;
1352 for (
int b=0; b<bps; ++b ) {
1353 symb = (symb<<1) | (accs[b]>>7);
1357 for (
int b=bps; b--; ) {
1358 symb = (symb<<1) | (accs[b]>>7);
1365 if ( nacc )
fail(
"Bug: s2_interleaver");
1369 const hard_sb *pin,
int nslots,
1372 void (*func)(
int rows,
const hard_sb *pin,
int nslots,
1378 func = interleave<1, 2>;
1381 func = interleave<1, 3>;
1384 func = interleave<1, 4>;
1387 func = interleave<1, 5>;
1396 func = interleave<0, 2>;
1399 func = interleave<0, 3>;
1402 func = interleave<0, 4>;
1405 func = interleave<0, 5>;
1410 (*func)(rows, pin, nslots, pout);
1412 template <
int MSB_FIRST,
int BPS>
1416 if (BPS == 4 && rows == 4050 && MSB_FIRST)
1417 return interleave4050(pin, nslots, pout);
1419 fatal(
"modcod/framesize combination not supported\n");
1420 int stride = rows / 8;
1422 fatal(
"Bug: Truncated byte");
1425 for (; nslots; nslots -= 4)
1433 for (
int i = 0;
i < 11; ++
i)
1435 split_byte<BPS>(pin++, stride, accs);
1436 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 8);
1438 split_byte<BPS>(pin++, stride, accs);
1439 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 2);
1444 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 6);
1445 for (
int i = 0;
i < 10; ++
i)
1447 split_byte<BPS>(pin++, stride, accs);
1448 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 8);
1450 split_byte<BPS>(pin++, stride, accs);
1451 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 4);
1454 pout->is_pls =
false;
1456 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 4);
1457 for (
int i = 0;
i < 10; ++
i)
1459 split_byte<BPS>(pin++, stride, accs);
1460 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 8);
1462 split_byte<BPS>(pin++, stride, accs);
1463 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 6);
1466 pout->is_pls =
false;
1468 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 2);
1469 for (
int i = 0;
i < 11; ++
i)
1471 split_byte<BPS>(pin++, stride, accs);
1472 pop_symbols<MSB_FIRST, BPS>(accs, &ps, 8);
1482 for (
int b = 0; b < BPS; ++b, pi += stride)
1485 template <
int MSB_FIRST,
int BPS>
1488 for (
int i = 0;
i < ns; ++
i)
1492 for (
int b = 0; b < BPS; ++b)
1494 symb = (symb << 1) | (accs[b] >> 7);
1496 symb = (symb << 1) | (accs[BPS - 1 - b] >> 7);
1497 for (
int b = 0; b < BPS; ++b)
1513 for (; nslots; --nslots, ++pout)
1517 for (
int ns = pout->
LENGTH; ns--; ++ps)
1521 if (nslots == 1 && ns == 1)
1525 accs[1] = (pin[506] << 2) | (pin[507] >> 6);
1526 accs[2] = (pin[1012] << 4) | (pin[1013] >> 4);
1527 accs[3] = (pin[1518] << 6);
1532 accs[1] = (pin[506] << 2) | (pin[507] >> 6);
1533 accs[2] = (pin[1012] << 4) | (pin[1013] >> 4);
1534 accs[3] = (pin[1518] << 6) | (pin[1519] >> 2);
1540 for (
int b = 0; b < 4; ++b)
1542 symb = (symb << 1) | (accs[b] >> 7);
1558 template <
typename SOFTSYMB,
typename SOFTBYTE>
1564 :
runnable(sch,
"S2 deinterleaver"),
1574 fail(
"s2_deinterleaver: bad input sequence");
1582 SOFTBYTE *pbytes = pout->
bytes;
1584 deserialize_qpsk(pin + 1, nslots, pbytes);
1590 deinterleave(bps, rows, pin + 1, nslots,
false, pbytes);
1592 deinterleave(bps, rows, pin + 1, nslots,
true, pbytes);
1594 in.
read(1 + nslots);
1607 for (; nslots; --nslots, ++pin)
1610 for (
int ns = pin->
LENGTH; ns--; ++ps)
1612 pack_qpsk_symbol(*ps, &acc, nacc);
1625 #if 0 // For reference 1626 static void deinterleave(
int bps,
int rows,
1628 bool msb_first, SOFTBYTE *pout) {
1629 if ( bps==4 && rows==4050 && msb_first )
1630 return deinterleave4050(pin, nslots, pout);
1631 if ( rows % 8 )
fatal(
"modcod/framesize combination not supported\n");
1632 int stride = rows/8;
1636 for ( ; nslots; --nslots,++pin ) {
1637 const SOFTSYMB *ps = pin->
symbols;
1638 for (
int ns=pin->
LENGTH; ns--; ++ps ) {
1639 split_symbol(*ps, bps, accs, nacc, msb_first);
1642 SOFTBYTE *po = pout;
1643 for (
int b=0; b<bps; ++b,po+=stride ) *po = accs[b];
1649 if ( nacc )
fail(
"Bug: s2_deinterleaver");
1654 bool msb_first, SOFTBYTE *pout)
1657 SOFTBYTE *pout) = 0;
1662 func = deinterleave<1, 2>;
1665 func = deinterleave<1, 3>;
1668 func = deinterleave<1, 4>;
1671 func = deinterleave<1, 5>;
1680 func = deinterleave<0, 2>;
1683 func = deinterleave<0, 3>;
1686 func = deinterleave<0, 4>;
1689 func = deinterleave<0, 5>;
1694 (*func)(rows, pin, nslots, pout);
1697 template <
int MSB_FIRST,
int BPS>
1701 if (BPS == 4 && rows == 4050 && MSB_FIRST)
1702 return deinterleave4050(pin, nslots, pout);
1704 fatal(
"modcod/framesize combination not supported\n");
1705 int stride = rows / 8;
1707 for (
int b = 0; b < BPS; ++b)
1710 for (; nslots; --nslots, ++pin)
1712 const SOFTSYMB *ps = pin->
symbols;
1713 for (
int ns = pin->
LENGTH; ns--; ++ps)
1715 split_symbol(*ps, BPS, accs, nacc, MSB_FIRST);
1719 SOFTBYTE *po = pout;
1721 for (
int b = 0; b < BPS; ++b, po += stride)
1729 fail(
"Bug: s2_deinterleaver");
1739 const int rows = 4050;
1741 for (
int b = 0; b < 4; ++b)
1744 for (; nslots; --nslots, ++pin)
1746 const SOFTSYMB *ps = pin->
symbols;
1747 for (
int ns = pin->
LENGTH; ns--; ++ps)
1749 split_symbol(*ps, 4, accs, nacc,
true);
1753 for (
int b = 0; b < 8; ++b)
1766 fatal(
"Bug: Expected 2 leftover rows\n");
1768 for (
int b = nacc; b < 8; ++b)
1769 split_symbol(pin->
symbols[0], 4, accs, b,
true);
1770 for (
int b = 0; b < nacc; ++b)
1787 for (
int b = 0; b < bps; ++b)
1792 for (
int b = 0; b < bps; ++b)
1797 template <
int MSB_FIRST,
int BPS>
1803 for (
int b = 0; b < BPS; ++b)
1808 for (
int b = 0; b < BPS; ++b)
1820 for (
int b = 0; b < bps; ++b)
1821 accs[b].bits[nacc] = ps.
bits[bps - 1 - b];
1825 for (
int b = 0; b < bps; ++b)
1826 accs[b].bits[nacc] = ps.
bits[b];
1830 template <
int MSB_FIRST,
int BPS>
1836 for (
int b = 0; b < BPS; ++b)
1837 accs[b].bits[nacc] = ps.
bits[BPS - 1 - b];
1841 for (
int b = 0; b < BPS; ++b)
1842 accs[b].bits[nacc] = ps.
bits[b];
1852 *acc = (*acc << 2) | s;
1872 static const struct fec_info
1874 static const int KBCH_MAX = 58192;
1878 const s2_ldpc_table *ldpc;
1882 {32208, 32400, 12, &ldpc_nf_fec12},
1883 {43040, 43200, 10, &ldpc_nf_fec23},
1885 {48408, 48600, 12, &ldpc_nf_fec34},
1886 {53840, 54000, 10, &ldpc_nf_fec56},
1888 {51648, 51840, 12, &ldpc_nf_fec45},
1889 {57472, 57600, 8, &ldpc_nf_fec89},
1890 {58192, 58320, 8, &ldpc_nf_fec910},
1891 {16008, 16200, 12, &ldpc_nf_fec14},
1892 {21408, 21600, 12, &ldpc_nf_fec13},
1893 {25728, 25920, 12, &ldpc_nf_fec25},
1894 {38688, 38880, 12, &ldpc_nf_fec35},
1898 {7032, 7200, 12, &ldpc_sf_fec12},
1899 {10632, 10800, 12, &ldpc_sf_fec23},
1901 {11712, 11880, 12, &ldpc_sf_fec34},
1902 {13152, 13320, 12, &ldpc_sf_fec56},
1904 {12432, 12600, 12, &ldpc_sf_fec45},
1905 {14232, 14400, 12, &ldpc_sf_fec89},
1907 {3072, 3240, 12, &ldpc_sf_fec14},
1908 {5232, 5400, 12, &ldpc_sf_fec13},
1909 {6312, 6480, 12, &ldpc_sf_fec25},
1910 {9552, 9720, 12, &ldpc_sf_fec35},
1923 template <
typename SOFTBIT,
typename SOFTBYTE>
1930 memset(ldpcs, 0,
sizeof(ldpcs));
1931 for (
int sf = 0; sf <= 1; ++sf)
1933 for (
int fec = 0; fec <
FEC_COUNT; ++fec)
1935 const fec_info *fi = &fec_infos[sf][fec];
1938 ldpcs[sf][fec] = NULL;
1942 int n = (sf ? 64800 / 4 : 64800);
1951 for (
int sf = 0; sf <= 1; ++sf)
1952 for (
int fec = 0; fec <
FEC_COUNT; ++fec)
1954 s2_ldpc_engine *ldpc = ldpcs[sf][fec];
2005 memset(bchs, 0,
sizeof(bchs));
2006 bchs[0][
FEC12] =
new s2_bch_engine_nf12(bch_polys[0], 12);
2007 bchs[0][
FEC23] =
new s2_bch_engine_nf10(bch_polys[0], 10);
2008 bchs[0][
FEC34] =
new s2_bch_engine_nf12(bch_polys[0], 12);
2009 bchs[0][
FEC56] =
new s2_bch_engine_nf10(bch_polys[0], 10);
2010 bchs[0][
FEC45] =
new s2_bch_engine_nf12(bch_polys[0], 12);
2011 bchs[0][
FEC89] =
new s2_bch_engine_nf8(bch_polys[0], 8);
2012 bchs[0][
FEC910] =
new s2_bch_engine_nf8(bch_polys[0], 8);
2013 bchs[0][
FEC14] =
new s2_bch_engine_nf12(bch_polys[0], 12);
2014 bchs[0][
FEC13] =
new s2_bch_engine_nf12(bch_polys[0], 12);
2015 bchs[0][
FEC25] =
new s2_bch_engine_nf12(bch_polys[0], 12);
2016 bchs[0][
FEC35] =
new s2_bch_engine_nf12(bch_polys[0], 12);
2017 bchs[1][
FEC12] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2018 bchs[1][
FEC23] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2019 bchs[1][
FEC34] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2020 bchs[1][
FEC56] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2021 bchs[1][
FEC45] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2022 bchs[1][
FEC89] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2023 bchs[1][
FEC14] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2024 bchs[1][
FEC13] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2025 bchs[1][
FEC25] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2026 bchs[1][
FEC35] =
new s2_bch_engine_sf12(bch_polys[1], 12);
2043 s2ldpc.print_node_stats();
2051 run_frame(in.
rd(), out.
wr());
2061 const fec_info *fi = &fec_infos[pin->
pls.
sf][mcinfo->
rate];
2064 bbscrambling.transform(pin->
bytes, fi->Kbch / 8, pbytes);
2066 size_t msgbytes = fi->Kbch / 8;
2067 size_t cwbytes = fi->kldpc / 8;
2069 bch->
encode(pbytes, msgbytes, pbytes + msgbytes);
2072 size_t msgbits = fi->kldpc;
2074 s2_ldpc_engine *ldpc = s2ldpc.ldpcs[pin->
pls.
sf][mcinfo->
rate];
2075 ldpc->
encode(fi->ldpc, pbytes, msgbits, cwbits, pbytes + msgbits / 8);
2089 template <
typename SOFTBIT,
typename SOFTBYTE>
2104 s2ldpc.print_node_stats();
2113 const fec_info *fi = &fec_infos[pin->
pls.sf][mcinfo->
rate];
2114 bool corrupted =
false;
2115 bool residual_errors;
2119 size_t cwbits = pin->
pls.framebits();
2120 size_t msgbits = fi->kldpc;
2121 size_t chkbits = cwbits - msgbits;
2122 s2_ldpc_engine *ldpc = s2ldpc.ldpcs[pin->
pls.sf][mcinfo->
rate];
2125 fprintf(stderr,
"LDPCCORR = %d\n", ncorr);
2131 size_t cwbytes = fi->kldpc / 8;
2132 size_t msgbytes = fi->Kbch / 8;
2133 size_t chkbytes = cwbytes - msgbytes;
2136 int ncorr = bch->
decode(hardbytes, cwbytes);
2138 fprintf(stderr,
"BCHCORR = %d\n", ncorr);
2139 corrupted = (ncorr < 0);
2140 residual_errors = (ncorr != 0);
2143 opt_write(errcount, (ncorr >= 0) ? ncorr : fi->Kbch);
2145 int bbsize = fi->Kbch / 8;
2149 fprintf(stderr,
"Passing bad frame\n");
2158 bbscrambling.transform(hardbytes, bbsize, pout->
bytes);
2162 fprintf(stderr,
"%c", corrupted ?
':' : residual_errors ?
'.' :
'_');
2180 template <
typename T,
int _SIZE>
2183 static const int SIZE = _SIZE;
2185 bool full() {
return count == SIZE; }
2189 wr = (wr + 1) % SIZE;
2197 const T *res = &q[rd];
2198 rd = (rd + 1) % SIZE;
2207 template <
typename SOFTBIT,
typename SOFTBYTE>
2216 const char *_command,
2228 for (
int mc = 0; mc < 32; ++mc)
2229 for (
int sf = 0; sf < 2; ++sf)
2230 pools[mc][sf].procs = NULL;
2234 bool work_done =
false;
2236 bool all_blocked =
false;
2237 while (in.
readable() >= 1 && !jobs.full())
2239 if (!send_frame(in.
rd()))
2249 while ((all_blocked || !work_done || jobs.full()) &&
2251 jobs.peek()->h->b_out &&
2255 receive_frame(jobs.get());
2282 pool *p = get_pool(&pin->
pls);
2286 size_t iosize = (pin->
pls.framebits() / 8) *
sizeof(SOFTBYTE);
2288 int nw = write(h->
fd_tx, pin->
bytes, iosize);
2289 if (nw < 0 && errno == EWOULDBLOCK)
2292 fatal(
"write(LDPC helper");
2294 fatal(
"partial write(LDPC helper)");
2315 for (
int i = 0;
i < nhelpers; ++
i)
2316 spawn_helper(&p->
procs[
i], pls);
2325 fprintf(stderr,
"Spawning LDPC helper: modcod=%d sf=%d\n",
2328 if (pipe(tx) || pipe(rx))
2331 int pipesize = 64800 * batch_size;
2332 if (fcntl(tx[0], F_SETPIPE_SZ, pipesize) < 0 ||
2333 fcntl(rx[0], F_SETPIPE_SZ, pipesize) < 0 ||
2334 fcntl(tx[1], F_SETPIPE_SZ, pipesize) < 0 ||
2335 fcntl(rx[1], F_SETPIPE_SZ, pipesize) < 0)
2338 "*** Failed to increase pipe size.\n" 2339 "*** Try echo %d > /proc/sys/fs/pipe-max-size\n",
2342 fatal(
"F_SETPIPE_SZ");
2344 fprintf(stderr,
"*** Throughput will be suboptimal.\n");
2346 int child = vfork();
2355 sprintf(mc_arg,
"%d", pls->
modcod);
2356 const char *sf_arg = pls->
sf ?
"--shortframes" : NULL;
2357 const char *argv[] = {command,
"--modcod", mc_arg, sf_arg, NULL};
2358 execve(command, (
char *
const *)argv, NULL);
2367 int flags = fcntl(h->
fd_tx, F_GETFL);
2368 if (fcntl(h->
fd_tx, F_SETFL, flags | O_NONBLOCK))
2369 fatal(
"fcntl(helper)");
2377 size_t iosize = (pls->
framebits() / 8) *
sizeof(ldpc_buf[0]);
2378 int nr = read(job->
h->
fd_rx, ldpc_buf, iosize);
2380 fatal(
"read(LDPC helper)");
2382 fatal(
"partial read(LDPC helper)");
2386 const fec_info *fi = &fec_infos[job->
pls.
sf][mcinfo->
rate];
2388 size_t cwbytes = fi->kldpc / 8;
2389 size_t msgbytes = fi->Kbch / 8;
2390 size_t chkbytes = cwbytes - msgbytes;
2392 int ncorr = bch->
decode(hardbytes, cwbytes);
2394 fprintf(stderr,
"BCHCORR = %d\n", ncorr);
2395 bool corrupted = (ncorr < 0);
2398 opt_write(errcount, (ncorr >= 0) ? ncorr : fi->Kbch);
2402 fprintf(stderr,
"Passing bad frame\n");
2411 bbscrambling.transform(hardbytes, fi->Kbch / 8, pout->
bytes);
2415 fprintf(stderr,
"%c", corrupted ?
'!' : ncorr ?
'.' :
'_');
2420 SOFTBYTE ldpc_buf[64800 / 8];
2449 const fec_info *fi = &fec_infos[pls.
sf][mcinfo->
rate];
2450 int framebytes = fi->Kbch / 8;
2452 fail(
"MODCOD/framesize combination not allowed");
2453 if (10 + nremain + 188 * in.
readable() < framebytes)
2458 uint8_t *end = buf + framebytes;
2461 *buf++ = 0x30 | rolloff_code;
2466 uint16_t dfl = (framebytes - 10) * 8;
2471 *buf++ = syncd >> 8;
2473 *buf++ = crc8.compute(bbheader, 9);
2475 memcpy(buf, rembuf, nremain);
2480 if (tsp->
data[0] != MPEG_SYNC)
2484 int nused = end - buf;
2487 memcpy(buf, tsp->
data + 1, nused);
2492 memcpy(rembuf, tsp->
data + 1 + nused, nremain);
2497 fail(
"Bug: s2_framer");
2521 in(_in), out(_out, MAX_TS_PER_BBFRAME),
2522 current_state(false),
2526 locktime_out(
opt_writer(_locktime_out, MAX_TS_PER_BBFRAME))
2539 report_state =
false;
2541 run_bbframe(in.
rd());
2550 uint16_t upl = (bbh[2] << 8) | bbh[3];
2551 uint16_t dfl = (bbh[4] << 8) | bbh[5];
2553 uint16_t syncd = (bbh[7] << 8) | bbh[8];
2554 uint8_t crcexp = crc8.compute(bbh, 9);
2557 int ro_code = bbh[0] & 3;
2560 static float ro_values[] = {0.35, 0.25, 0.20, 0};
2561 fprintf(stderr,
"BBH: crc %02x/%02x %s ma=%02x%02x ro=%.2f" 2562 " upl=%d dfl=%d sync=%02x syncd=%d\n",
2563 crc, crcexp, (crc == crcexp) ?
"OK" :
"KO",
2564 bbh[0], bbh[1], ro_values[ro_code], upl, dfl, sync, syncd);
2566 if (crc != crcexp || upl != 188 * 8 || sync != 0x47 || dfl > fec_info::KBCH_MAX ||
2567 syncd > dfl || (dfl & 7) || (syncd & 7))
2570 fprintf(stderr,
"Bad bbframe\n");
2581 fprintf(stderr,
"Start TS at %d\n", pos);
2587 if (syncd / 8 != missing)
2589 fprintf(stderr,
"Lost a bbframe ?\n");
2600 memcpy(pout->
data, leftover, 188 - missing);
2601 memcpy(pout->
data + (188 - missing), data + pos, missing);
2609 while (pos + 188 <= dfl / 8)
2612 memcpy(pout->
data, data + pos, 188);
2613 pout->
data[0] = sync;
2618 int remain = dfl / 8 - pos;
2621 memcpy(leftover, data + pos, remain);
2623 missing = 188 - remain;
2629 info_is_locked(
false);
2634 info_is_locked(
true);
2640 if (newstate != current_state)
2643 current_state = newstate;
2652 static const int MAX_TS_PER_BBFRAME = fec_info::KBCH_MAX / 8 / 188 + 1;
2665 #endif // LEANSDR_DVBS2_H void spawn_helper(helper_instance *h, const s2_pls *pls)
bch_engine< uint32_t, 192, 17, 16, uint16_t, 0x002d > s2_bch_engine_nf12
static void split_byte(const hard_sb *pi, int stride, hard_sb accs[BPS])
virtual int decode(uint8_t *cw, size_t cwbytes)=0
s2_framer(scheduler *sch, pipebuf< tspacket > &_in, pipebuf< bbframe > &_out)
s2_fecenc(scheduler *sch, pipebuf< bbframe > &_in, pipebuf< fecframe< hard_sb >> &_out)
uint8_t * softbytes_harden(hard_sb p[], int nbytes, uint8_t storage[])
s2_bbscrambling bbscrambling
static const char * names[]
bool send_frame(fecframe< SOFTBYTE > *pin)
s2_plscodes< T > plscodes
s2_scrambling(int codenum=0)
static void interleave(int bps, int rows, const hard_sb *pin, int nslots, bool msb_first, plslot< hard_ss > *pout)
uint32_t lfsr_x(uint32_t X)
bch_engine< uint32_t, 128, 17, 16, uint16_t, 0x002d > s2_bch_engine_nf8
pipereader< plslot< hard_ss > > in
static void interleave4050(const hard_sb *pin, int nslots, plslot< hard_ss > *pout)
pipewriter< complex< float > > * symbols_out
ldpc_engine< SOFTBIT, SOFTBYTE, 8, uint16_t > s2_ldpc_engine
s2_deframer(scheduler *sch, pipebuf< bbframe > &_in, pipebuf< tspacket > &_out, pipebuf< int > *_state_out=NULL, pipebuf< unsigned long > *_locktime_out=NULL)
void run_bbframe(bbframe *pin)
static const int MAX_SLOTS_PER_FRAME
void scramble(const complex< T > *src, uint8_t r, complex< T > *dst)
s2_frame_receiver(scheduler *sch, sampler_interface< T > *_sampler, pipebuf< complex< T >> &_in, pipebuf< plslot< SOFTSYMB >> &_out, pipebuf< float > *_freq_out=NULL, pipebuf< float > *_ss_out=NULL, pipebuf< float > *_mer_out=NULL, pipebuf< complex< float >> *_cstln_out=NULL, pipebuf< complex< float >> *_cstln_pls_out=NULL, pipebuf< complex< float >> *_symbols_out=NULL, pipebuf< int > *_state_out=NULL)
s2_bbscrambling bbscrambling
void add_syncs(cstln_lut< SOFTSYMB, 256 > *c)
complex< float > interp_next(sampler_state *ss)
pipewriter< bbframe > out
void run_frame(const bbframe *pin, fecframe< hard_sb > *pout)
static void pop_symbols(hard_sb accs[BPS], hard_ss **ps, int ns)
int hamming_weight(uint8_t x)
pipewriter< tspacket > out
cstln_lut< hard_ss, 256 > * cstln
bch_engine< uint32_t, 160, 17, 16, uint16_t, 0x002d > s2_bch_engine_nf10
s2_ldpc_engines< SOFTBIT, SOFTBYTE > s2ldpc
s2_plscodes< T > plscodes
Fixed< IntType, IntBits > floor(Fixed< IntType, IntBits > const &x)
pipereader< fecframe< hard_sb > > in
static void deinterleave(int bps, int rows, const plslot< SOFTSYMB > *pin, int nslots, bool msb_first, SOFTBYTE *pout)
uint8_t track_symbol(sampler_state *ss, const complex< float > &p, cstln_lut< SOFTSYMB, 256 > *c, int mode)
s2_fecdec_helper(scheduler *sch, pipebuf< fecframe< SOFTBYTE >> &_in, pipebuf< bbframe > &_out, const char *_command, pipebuf< int > *_bitcount=NULL, pipebuf< int > *_errcount=NULL)
cstln_lut< SOFTSYMB, 256 > * qpsk
static void deinterleave4050(const plslot< SOFTSYMB > *pin, int nslots, SOFTBYTE *pout)
virtual complex< T > interp(const complex< T > *pin, float mu, float phase)=0
pipewriter< fecframe< SOFTBYTE > > out
static void split_symbol(const llr_ss &ps, hard_sb accs[], int nacc)
virtual void encode(const uint8_t *msg, size_t msgbytes, uint8_t *out)=0
complex< float > descramble(sampler_state *ss, const complex< float > &p)
pipewriter< bbframe > out
complex< T > symbols[LENGTH]
void info_is_locked(bool newstate)
static void split_symbol(const llr_ss &ps, int bps, hard_sb accs[], int nacc, bool msb_first)
static const uint32_t MASK
void opt_write(pipewriter< T > *p, T val)
cstln_lut< SOFTSYMB, 256 > * cstln
pipewriter< fecframe< hard_sb > > out
void encode(const ldpc_table< Taddr > *table, const SOFTWORD *msg, int k, int n, SOFTWORD *parity, int integrate=true)
static void pack_qpsk_symbol(const llr_ss &ps, hard_sb *acc, int nacc)
result * lookup(float I, float Q)
pipewriter< int > * state_out
pipewriter< complex< float > > * cstln_pls_out
static void split_symbol(const llr_ss &ps, int bps, llr_sb accs[], int nacc, bool msb_first)
pipewriter< plslot< SOFTSYMB > > out
bool opt_writable(pipewriter< T > *p, int n=1)
pipewriter< int > * state_out
virtual void update_freq(float freqw, int period=1)
void written(unsigned long n)
void track_agc(const complex< float > &p)
pipewriter< int > * errcount
static void interleave(int rows, const hard_sb *pin, int nslots, plslot< hard_ss > *pout)
pipewriter< T > * opt_writer(pipebuf< T > *buf, unsigned long min_write=1)
pipewriter< int > * errcount
void align_phase(sampler_state *ss, const complex< float > &c)
ldpc_table< uint16_t > s2_ldpc_table
void transform(const uint8_t *in, int bbsize, uint8_t *out)
s2_frame_transmitter(scheduler *sch, pipebuf< plslot< hard_ss >> &_in, pipebuf< complex< T >> &_out)
pipereader< plslot< SOFTSYMB > > in
s2_fecdec(scheduler *sch, pipebuf< fecframe< SOFTBYTE >> &_in, pipebuf< bbframe > &_out, pipebuf< int > *_bitcount=NULL, pipebuf< int > *_errcount=NULL)
s2_bbscrambling bbscrambling
pipewriter< bbframe > out
void fatal(const char *s)
void enter_frame_locked()
const struct leansdr::modcod_info modcod_infos[32]
s2_interleaver(scheduler *sch, pipebuf< fecframe< hard_sb >> &_in, pipebuf< plslot< hard_ss >> &_out)
s2_ldpc_engines< bool, hard_sb > s2ldpc
int decode_bitflip(const ldpc_table< Taddr > *table, SOFTWORD *cw, int k, int n, int max_bitflips)
static void deinterleave(int rows, const plslot< SOFTSYMB > *pin, int nslots, SOFTBYTE *pout)
ldpc_engine< bool, hard_sb, 8, uint16_t > s2_ldpc_engine
void receive_frame(const helper_job *job)
simplequeue< helper_job, 1024 > jobs
void enter_frame_search()
pipereader< complex< T > > in
pipereader< tspacket > in
s2_deinterleaver(scheduler *sch, pipebuf< plslot< SOFTSYMB >> &_in, pipebuf< fecframe< SOFTBYTE >> &_out)
pipewriter< complex< T > > out
static const uint32_t VALUE
pipewriter< plslot< hard_ss > > out
static void serialize_qpsk(const hard_sb *pin, int nslots, plslot< hard_ss > *pout)
complex< int8_t > * symbols
void init_agc(const complex< T > *buf, int n)
void softwords_set(hard_sb p[], int b)
static void deserialize_qpsk(plslot< SOFTSYMB > *pin, int nslots, SOFTBYTE *pout)
const modcod_info * check_modcod(int m)
int run_frame(s2_pls *pls, const modcod_info *mcinfo, const plslot< hard_ss > *pin, int nslots, complex< T > *pout)
virtual int readahead()=0
bool softword_get(const hard_sb &p, int b)
pipewriter< float > * ss_out
static void pack_qpsk_symbol(const llr_ss &ps, llr_sb *acc, int nacc)
sampler_interface< T > * sampler
pipewriter< complex< float > > * cstln_out
pipereader< fecframe< SOFTBYTE > > in
static void split_symbol(const llr_ss &ps, llr_sb accs[], int nacc)
void skip_symbols(int ns, float omega)
complex< float > diffcorr
void softword_clear(hard_sb *p)
uint32_t lfsr_y(uint32_t Y)
pipewriter< unsigned long > * locktime_out
void read(unsigned long n)
pipereader< fecframe< SOFTBYTE > > in
complex< T > conjprod(const complex< T > &u, const complex< T > &v)
bch_engine< uint32_t, 168, 17, 14, uint16_t, 0x002b > s2_bch_engine_sf12
pool * get_pool(const s2_pls *pls)
T cnorm2(const complex< T > &u)
unsigned __int64 uint64_t
ldpc_engine< bool, hard_sb, 8, uint16_t > s2_ldpc_engine
void update_cstln(const modcod_info *mcinfo)