/* -*- c++ -*- */ /* * Copyright 2015 Free Software Foundation, Inc. * * SPDX-License-Identifier: GPL-3.0-or-later * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "dvbt2_freqinterleaver_cc_impl.h" #include <gnuradio/io_signature.h> namespace gr { namespace dtv { dvbt2_freqinterleaver_cc::sptr dvbt2_freqinterleaver_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble) { return gnuradio::make_block_sptr<dvbt2_freqinterleaver_cc_impl>(carriermode, fftsize, pilotpattern, guardinterval, numdatasyms, paprmode, version, preamble); } /* * The private constructor */ dvbt2_freqinterleaver_cc_impl::dvbt2_freqinterleaver_cc_impl( dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble) : gr::sync_block("dvbt2_freqinterleaver_cc", gr::io_signature::make(1, 1, sizeof(gr_complex)), gr::io_signature::make(1, 1, sizeof(gr_complex))) { int max_states, xor_size, pn_mask, result; int q_even = 0; int q_odd = 0; int q_evenP2 = 0; int q_oddP2 = 0; int q_evenFC = 0; int q_oddFC = 0; int lfsr = 0; int logic1k[2] = { 0, 4 }; int logic2k[2] = { 0, 3 }; int logic4k[2] = { 0, 2 }; int logic8k[4] = { 0, 1, 4, 6 }; int logic16k[6] = { 0, 1, 4, 5, 9, 11 }; int logic32k[4] = { 0, 1, 2, 12 }; int* logic; const int *bitpermeven, *bitpermodd; int pn_degree, even, odd; if ((preamble == PREAMBLE_T2_SISO) || (preamble == PREAMBLE_T2_LITE_SISO)) { switch (fftsize) { case FFTSIZE_1K: N_P2 = 16; C_P2 = 558; break; case FFTSIZE_2K: N_P2 = 8; C_P2 = 1118; break; case FFTSIZE_4K: N_P2 = 4; C_P2 = 2236; break; case FFTSIZE_8K: case FFTSIZE_8K_T2GI: N_P2 = 2; C_P2 = 4472; break; case FFTSIZE_16K: case FFTSIZE_16K_T2GI: N_P2 = 1; C_P2 = 8944; break; case FFTSIZE_32K: case FFTSIZE_32K_T2GI: N_P2 = 1; C_P2 = 22432; break; } } else { switch (fftsize) { case FFTSIZE_1K: N_P2 = 16; C_P2 = 546; break; case FFTSIZE_2K: N_P2 = 8; C_P2 = 1098; break; case FFTSIZE_4K: N_P2 = 4; C_P2 = 2198; break; case FFTSIZE_8K: case FFTSIZE_8K_T2GI: N_P2 = 2; C_P2 = 4398; break; case FFTSIZE_16K: case FFTSIZE_16K_T2GI: N_P2 = 1; C_P2 = 8814; break; case FFTSIZE_32K: case FFTSIZE_32K_T2GI: N_P2 = 1; C_P2 = 17612; break; } } switch (fftsize) { case FFTSIZE_1K: pn_degree = 9; pn_mask = 0x1ff; max_states = 1024; logic = &logic1k[0]; xor_size = 2; bitpermeven = &bitperm1keven[0]; bitpermodd = &bitperm1kodd[0]; break; case FFTSIZE_2K: pn_degree = 10; pn_mask = 0x3ff; max_states = 2048; logic = &logic2k[0]; xor_size = 2; bitpermeven = &bitperm2keven[0]; bitpermodd = &bitperm2kodd[0]; break; case FFTSIZE_4K: pn_degree = 11; pn_mask = 0x7ff; max_states = 4096; logic = &logic4k[0]; xor_size = 2; bitpermeven = &bitperm4keven[0]; bitpermodd = &bitperm4kodd[0]; break; case FFTSIZE_8K: case FFTSIZE_8K_T2GI: pn_degree = 12; pn_mask = 0xfff; max_states = 8192; logic = &logic8k[0]; xor_size = 4; bitpermeven = &bitperm8keven[0]; bitpermodd = &bitperm8kodd[0]; break; case FFTSIZE_16K: case FFTSIZE_16K_T2GI: pn_degree = 13; pn_mask = 0x1fff; max_states = 16384; logic = &logic16k[0]; xor_size = 6; bitpermeven = &bitperm16keven[0]; bitpermodd = &bitperm16kodd[0]; break; case FFTSIZE_32K: case FFTSIZE_32K_T2GI: pn_degree = 14; pn_mask = 0x3fff; max_states = 32768; logic = &logic32k[0]; xor_size = 4; bitpermeven = &bitperm32k[0]; bitpermodd = &bitperm32k[0]; break; default: pn_degree = 0; pn_mask = 0; max_states = 0; logic = &logic1k[0]; xor_size = 0; bitpermeven = &bitperm1keven[0]; bitpermodd = &bitperm1kodd[0]; break; } switch (fftsize) { case FFTSIZE_1K: switch (pilotpattern) { case PILOT_PP1: C_DATA = 764; N_FC = 568; C_FC = 402; break; case PILOT_PP2: C_DATA = 768; N_FC = 710; C_FC = 654; break; case PILOT_PP3: C_DATA = 798; N_FC = 710; C_FC = 490; break; case PILOT_PP4: C_DATA = 804; N_FC = 780; C_FC = 707; break; case PILOT_PP5: C_DATA = 818; N_FC = 780; C_FC = 544; break; case PILOT_PP6: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP7: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP8: C_DATA = 0; N_FC = 0; C_FC = 0; break; } if (paprmode == PAPR_TR || paprmode == PAPR_BOTH) { if (C_DATA != 0) { C_DATA -= 10; } if (N_FC != 0) { N_FC -= 10; } if (C_FC != 0) { C_FC -= 10; } } break; case FFTSIZE_2K: switch (pilotpattern) { case PILOT_PP1: C_DATA = 1522; N_FC = 1136; C_FC = 804; break; case PILOT_PP2: C_DATA = 1532; N_FC = 1420; C_FC = 1309; break; case PILOT_PP3: C_DATA = 1596; N_FC = 1420; C_FC = 980; break; case PILOT_PP4: C_DATA = 1602; N_FC = 1562; C_FC = 1415; break; case PILOT_PP5: C_DATA = 1632; N_FC = 1562; C_FC = 1088; break; case PILOT_PP6: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP7: C_DATA = 1646; N_FC = 1632; C_FC = 1396; break; case PILOT_PP8: C_DATA = 0; N_FC = 0; C_FC = 0; break; } if (paprmode == PAPR_TR || paprmode == PAPR_BOTH) { if (C_DATA != 0) { C_DATA -= 18; } if (N_FC != 0) { N_FC -= 18; } if (C_FC != 0) { C_FC -= 18; } } break; case FFTSIZE_4K: switch (pilotpattern) { case PILOT_PP1: C_DATA = 3084; N_FC = 2272; C_FC = 1609; break; case PILOT_PP2: C_DATA = 3092; N_FC = 2840; C_FC = 2619; break; case PILOT_PP3: C_DATA = 3228; N_FC = 2840; C_FC = 1961; break; case PILOT_PP4: C_DATA = 3234; N_FC = 3124; C_FC = 2831; break; case PILOT_PP5: C_DATA = 3298; N_FC = 3124; C_FC = 2177; break; case PILOT_PP6: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP7: C_DATA = 3328; N_FC = 3266; C_FC = 2792; break; case PILOT_PP8: C_DATA = 0; N_FC = 0; C_FC = 0; break; } if (paprmode == PAPR_TR || paprmode == PAPR_BOTH) { if (C_DATA != 0) { C_DATA -= 36; } if (N_FC != 0) { N_FC -= 36; } if (C_FC != 0) { C_FC -= 36; } } break; case FFTSIZE_8K: case FFTSIZE_8K_T2GI: if (carriermode == CARRIERS_NORMAL) { switch (pilotpattern) { case PILOT_PP1: C_DATA = 6208; N_FC = 4544; C_FC = 3218; break; case PILOT_PP2: C_DATA = 6214; N_FC = 5680; C_FC = 5238; break; case PILOT_PP3: C_DATA = 6494; N_FC = 5680; C_FC = 3922; break; case PILOT_PP4: C_DATA = 6498; N_FC = 6248; C_FC = 5662; break; case PILOT_PP5: C_DATA = 6634; N_FC = 6248; C_FC = 4354; break; case PILOT_PP6: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP7: C_DATA = 6698; N_FC = 6532; C_FC = 5585; break; case PILOT_PP8: C_DATA = 6698; N_FC = 0; C_FC = 0; break; } } else { switch (pilotpattern) { case PILOT_PP1: C_DATA = 6296; N_FC = 4608; C_FC = 3264; break; case PILOT_PP2: C_DATA = 6298; N_FC = 5760; C_FC = 5312; break; case PILOT_PP3: C_DATA = 6584; N_FC = 5760; C_FC = 3978; break; case PILOT_PP4: C_DATA = 6588; N_FC = 6336; C_FC = 5742; break; case PILOT_PP5: C_DATA = 6728; N_FC = 6336; C_FC = 4416; break; case PILOT_PP6: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP7: C_DATA = 6788; N_FC = 6624; C_FC = 5664; break; case PILOT_PP8: C_DATA = 6788; N_FC = 0; C_FC = 0; break; } } if (paprmode == PAPR_TR || paprmode == PAPR_BOTH) { if (C_DATA != 0) { C_DATA -= 72; } if (N_FC != 0) { N_FC -= 72; } if (C_FC != 0) { C_FC -= 72; } } break; case FFTSIZE_16K: case FFTSIZE_16K_T2GI: if (carriermode == CARRIERS_NORMAL) { switch (pilotpattern) { case PILOT_PP1: C_DATA = 12418; N_FC = 9088; C_FC = 6437; break; case PILOT_PP2: C_DATA = 12436; N_FC = 11360; C_FC = 10476; break; case PILOT_PP3: C_DATA = 12988; N_FC = 11360; C_FC = 7845; break; case PILOT_PP4: C_DATA = 13002; N_FC = 12496; C_FC = 11324; break; case PILOT_PP5: C_DATA = 13272; N_FC = 12496; C_FC = 8709; break; case PILOT_PP6: C_DATA = 13288; N_FC = 13064; C_FC = 11801; break; case PILOT_PP7: C_DATA = 13416; N_FC = 13064; C_FC = 11170; break; case PILOT_PP8: C_DATA = 13406; N_FC = 0; C_FC = 0; break; } } else { switch (pilotpattern) { case PILOT_PP1: C_DATA = 12678; N_FC = 9280; C_FC = 6573; break; case PILOT_PP2: C_DATA = 12698; N_FC = 11600; C_FC = 10697; break; case PILOT_PP3: C_DATA = 13262; N_FC = 11600; C_FC = 8011; break; case PILOT_PP4: C_DATA = 13276; N_FC = 12760; C_FC = 11563; break; case PILOT_PP5: C_DATA = 13552; N_FC = 12760; C_FC = 8893; break; case PILOT_PP6: C_DATA = 13568; N_FC = 13340; C_FC = 12051; break; case PILOT_PP7: C_DATA = 13698; N_FC = 13340; C_FC = 11406; break; case PILOT_PP8: C_DATA = 13688; N_FC = 0; C_FC = 0; break; } } if (paprmode == PAPR_TR || paprmode == PAPR_BOTH) { if (C_DATA != 0) { C_DATA -= 144; } if (N_FC != 0) { N_FC -= 144; } if (C_FC != 0) { C_FC -= 144; } } break; case FFTSIZE_32K: case FFTSIZE_32K_T2GI: if (carriermode == CARRIERS_NORMAL) { switch (pilotpattern) { case PILOT_PP1: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP2: C_DATA = 24886; N_FC = 22720; C_FC = 20952; break; case PILOT_PP3: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP4: C_DATA = 26022; N_FC = 24992; C_FC = 22649; break; case PILOT_PP5: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP6: C_DATA = 26592; N_FC = 26128; C_FC = 23603; break; case PILOT_PP7: C_DATA = 26836; N_FC = 0; C_FC = 0; break; case PILOT_PP8: C_DATA = 26812; N_FC = 0; C_FC = 0; break; } } else { switch (pilotpattern) { case PILOT_PP1: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP2: C_DATA = 25412; N_FC = 23200; C_FC = 21395; break; case PILOT_PP3: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP4: C_DATA = 26572; N_FC = 25520; C_FC = 23127; break; case PILOT_PP5: C_DATA = 0; N_FC = 0; C_FC = 0; break; case PILOT_PP6: C_DATA = 27152; N_FC = 26680; C_FC = 24102; break; case PILOT_PP7: C_DATA = 27404; N_FC = 0; C_FC = 0; break; case PILOT_PP8: C_DATA = 27376; N_FC = 0; C_FC = 0; break; } } if (paprmode == PAPR_TR || paprmode == PAPR_BOTH) { if (C_DATA != 0) { C_DATA -= 288; } if (N_FC != 0) { N_FC -= 288; } if (C_FC != 0) { C_FC -= 288; } } break; } if ((preamble == PREAMBLE_T2_SISO) || (preamble == PREAMBLE_T2_LITE_SISO)) { if (guardinterval == GI_1_128 && pilotpattern == PILOT_PP7) { N_FC = 0; C_FC = 0; } if (guardinterval == GI_1_32 && pilotpattern == PILOT_PP4) { N_FC = 0; C_FC = 0; } if (guardinterval == GI_1_16 && pilotpattern == PILOT_PP2) { N_FC = 0; C_FC = 0; } if (guardinterval == GI_19_256 && pilotpattern == PILOT_PP2) { N_FC = 0; C_FC = 0; } } for (int i = 0; i < max_states; i++) { if (i == 0 || i == 1) { lfsr = 0; } else if (i == 2) { lfsr = 1; } else { result = 0; for (int k = 0; k < xor_size; k++) { result ^= (lfsr >> logic[k]) & 1; } lfsr &= pn_mask; lfsr >>= 1; lfsr |= result << (pn_degree - 1); } even = 0; odd = 0; for (int n = 0; n < pn_degree; n++) { even |= ((lfsr >> n) & 0x1) << bitpermeven[n]; } for (int n = 0; n < pn_degree; n++) { odd |= ((lfsr >> n) & 0x1) << bitpermodd[n]; } even = even + ((i % 2) * (max_states / 2)); odd = odd + ((i % 2) * (max_states / 2)); if (even < C_DATA) { Heven[q_even++] = even; } if (odd < C_DATA) { Hodd[q_odd++] = odd; } if (even < C_P2) { HevenP2[q_evenP2++] = even; } if (odd < C_P2) { HoddP2[q_oddP2++] = odd; } if (even < N_FC) { HevenFC[q_evenFC++] = even; } if (odd < N_FC) { HoddFC[q_oddFC++] = odd; } } if (fftsize == FFTSIZE_32K || fftsize == FFTSIZE_32K_T2GI) { for (int j = 0; j < q_odd; j++) { int a; a = Hodd[j]; Heven[a] = j; } for (int j = 0; j < q_oddP2; j++) { int a; a = HoddP2[j]; HevenP2[a] = j; } for (int j = 0; j < q_oddFC; j++) { int a; a = HoddFC[j]; HevenFC[a] = j; } } if (N_FC == 0) { set_output_multiple((N_P2 * C_P2) + (numdatasyms * C_DATA)); interleaved_items = (N_P2 * C_P2) + (numdatasyms * C_DATA); num_data_symbols = numdatasyms; } else { set_output_multiple((N_P2 * C_P2) + ((numdatasyms - 1) * C_DATA) + N_FC); interleaved_items = (N_P2 * C_P2) + ((numdatasyms - 1) * C_DATA) + N_FC; num_data_symbols = numdatasyms - 1; } } /* * Our virtual destructor. */ dvbt2_freqinterleaver_cc_impl::~dvbt2_freqinterleaver_cc_impl() {} int dvbt2_freqinterleaver_cc_impl::work(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) { const gr_complex* in = (const gr_complex*)input_items[0]; gr_complex* out = (gr_complex*)output_items[0]; int symbol = 0; int* H; for (int i = 0; i < noutput_items; i += interleaved_items) { for (int j = 0; j < N_P2; j++) { if ((symbol % 2) == 0) { H = HevenP2; } else { H = HoddP2; } for (int j = 0; j < C_P2; j++) { *out++ = in[H[j]]; } symbol++; in += C_P2; } for (int j = 0; j < num_data_symbols; j++) { if ((symbol % 2) == 0) { H = Heven; } else { H = Hodd; } for (int j = 0; j < C_DATA; j++) { *out++ = in[H[j]]; } symbol++; in += C_DATA; } if (N_FC != 0) { if ((symbol % 2) == 0) { H = HevenFC; } else { H = HoddFC; } for (int j = 0; j < N_FC; j++) { *out++ = in[H[j]]; } symbol++; in += N_FC; } } // Tell runtime system how many output items we produced. return noutput_items; } const int dvbt2_freqinterleaver_cc_impl::bitperm1keven[9] = { 8, 7, 6, 5, 0, 1, 2, 3, 4 }; const int dvbt2_freqinterleaver_cc_impl::bitperm1kodd[9] = { 6, 8, 7, 4, 1, 0, 5, 2, 3 }; const int dvbt2_freqinterleaver_cc_impl::bitperm2keven[10] = { 4, 3, 9, 6, 2, 8, 1, 5, 7, 0 }; const int dvbt2_freqinterleaver_cc_impl::bitperm2kodd[10] = { 6, 9, 4, 8, 5, 1, 0, 7, 2, 3 }; const int dvbt2_freqinterleaver_cc_impl::bitperm4keven[11] = { 6, 3, 0, 9, 4, 2, 1, 8, 5, 10, 7 }; const int dvbt2_freqinterleaver_cc_impl::bitperm4kodd[11] = { 5, 9, 1, 4, 3, 0, 8, 10, 7, 2, 6 }; const int dvbt2_freqinterleaver_cc_impl::bitperm8keven[12] = { 7, 1, 4, 2, 9, 6, 8, 10, 0, 3, 11, 5 }; const int dvbt2_freqinterleaver_cc_impl::bitperm8kodd[12] = { 11, 4, 9, 3, 1, 2, 5, 0, 6, 7, 10, 8 }; const int dvbt2_freqinterleaver_cc_impl::bitperm16keven[13] = { 9, 7, 6, 10, 12, 5, 1, 11, 0, 2, 3, 4, 8 }; const int dvbt2_freqinterleaver_cc_impl::bitperm16kodd[13] = { 6, 8, 10, 12, 2, 0, 4, 1, 11, 3, 5, 9, 7 }; const int dvbt2_freqinterleaver_cc_impl::bitperm32k[14] = { 7, 13, 3, 4, 9, 2, 12, 11, 1, 8, 10, 0, 5, 6 }; } /* namespace dtv */ } /* namespace gr */