/* -*- c++ -*- */ /* * Copyright 2015,2016 Free Software Foundation, Inc. * * SPDX-License-Identifier: GPL-3.0-or-later * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "dvbs2_interleaver_bb_impl.h" #include <gnuradio/io_signature.h> namespace gr { namespace dtv { dvbs2_interleaver_bb::sptr dvbs2_interleaver_bb::make(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation) { return gnuradio::make_block_sptr<dvbs2_interleaver_bb_impl>( framesize, rate, constellation); } /* * The private constructor */ dvbs2_interleaver_bb_impl::dvbs2_interleaver_bb_impl(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation) : gr::block("dvbs2_interleaver_bb", gr::io_signature::make(1, 1, sizeof(unsigned char)), gr::io_signature::make(1, 1, sizeof(unsigned char))) { int rows; signal_constellation = constellation; code_rate = rate; if (framesize == FECFRAME_NORMAL) { frame_size = FRAME_SIZE_NORMAL; if (rate == C2_9_VLSNR) { frame_size = FRAME_SIZE_NORMAL - NORMAL_PUNCTURING; } } else if (framesize == FECFRAME_SHORT) { frame_size = FRAME_SIZE_SHORT; if (rate == C1_5_VLSNR_SF2 || rate == C11_45_VLSNR_SF2) { frame_size = FRAME_SIZE_SHORT - SHORT_PUNCTURING_SET1; } if (rate == C1_5_VLSNR || rate == C4_15_VLSNR || rate == C1_3_VLSNR) { frame_size = FRAME_SIZE_SHORT - SHORT_PUNCTURING_SET2; } } else { frame_size = FRAME_SIZE_MEDIUM - MEDIUM_PUNCTURING; } switch (constellation) { case MOD_BPSK: mod = 1; rows = frame_size / mod; set_output_multiple(rows); packed_items = rows; break; case MOD_BPSK_SF2: mod = 1; rows = frame_size / mod; set_output_multiple(rows * 2); packed_items = rows * 2; break; case MOD_QPSK: mod = 2; rows = frame_size / mod; set_output_multiple(rows); packed_items = rows; break; case MOD_8PSK: mod = 3; rows = frame_size / mod; /* 210 */ if (rate == C3_5) { rowaddr0 = rows * 2; rowaddr1 = rows; rowaddr2 = 0; } /* 102 */ else if (rate == C25_36 || rate == C13_18 || rate == C7_15 || rate == C8_15 || rate == C26_45) { rowaddr0 = rows; rowaddr1 = 0; rowaddr2 = rows * 2; } /* 012 */ else { rowaddr0 = 0; rowaddr1 = rows; rowaddr2 = rows * 2; } set_output_multiple(rows); packed_items = rows; break; case MOD_8APSK: mod = 3; rows = frame_size / mod; /* 012 */ rowaddr0 = 0; rowaddr1 = rows; rowaddr2 = rows * 2; set_output_multiple(rows); packed_items = rows; break; case MOD_16APSK: mod = 4; rows = frame_size / mod; if (rate == C26_45) { /* 3201 */ if (frame_size == FRAME_SIZE_NORMAL) { rowaddr0 = rows * 3; rowaddr1 = rows * 2; rowaddr2 = 0; rowaddr3 = rows; } /* 2130 */ else { rowaddr0 = rows * 2; rowaddr1 = rows; rowaddr2 = rows * 3; rowaddr3 = 0; } } else if (rate == C3_5) { /* 3210 */ if (frame_size == FRAME_SIZE_NORMAL) { rowaddr0 = rows * 3; rowaddr1 = rows * 2; rowaddr2 = rows; rowaddr3 = 0; } /* 3201 */ else { rowaddr0 = rows * 3; rowaddr1 = rows * 2; rowaddr2 = 0; rowaddr3 = rows; } } /* 3012 */ else if (rate == C28_45) { rowaddr0 = rows * 3; rowaddr1 = 0; rowaddr2 = rows; rowaddr3 = rows * 2; } /* 3021 */ else if (rate == C23_36 || rate == C13_18) { rowaddr0 = rows * 3; rowaddr1 = 0; rowaddr2 = rows * 2; rowaddr3 = rows; } /* 2310 */ else if (rate == C25_36) { rowaddr0 = rows * 2; rowaddr1 = rows * 3; rowaddr2 = rows; rowaddr3 = 0; } /* 2103 */ else if (rate == C7_15 || rate == C8_15) { rowaddr0 = rows * 2; rowaddr1 = rows; rowaddr2 = 0; rowaddr3 = rows * 3; } /* 3210 */ else if (rate == C140_180) { rowaddr0 = rows * 3; rowaddr1 = rows * 2; rowaddr2 = rows; rowaddr3 = 0; } /* 0321 */ else if (rate == C154_180) { rowaddr0 = 0; rowaddr1 = rows * 3; rowaddr2 = rows * 2; rowaddr3 = rows; } /* 0123 */ else { rowaddr0 = 0; rowaddr1 = rows; rowaddr2 = rows * 2; rowaddr3 = rows * 3; } set_output_multiple(rows); packed_items = rows; break; case MOD_8_8APSK: mod = 4; rows = frame_size / mod; /* 3210 */ if (rate == C90_180) { rowaddr0 = rows * 3; rowaddr1 = rows * 2; rowaddr2 = rows; rowaddr3 = 0; } /* 2310 */ else if (rate == C96_180) { rowaddr0 = rows * 2; rowaddr1 = rows * 3; rowaddr2 = rows; rowaddr3 = 0; } /* 2301 */ else if (rate == C100_180) { rowaddr0 = rows * 2; rowaddr1 = rows * 3; rowaddr2 = 0; rowaddr3 = rows; } /* 0123 */ else { rowaddr0 = 0; rowaddr1 = rows; rowaddr2 = rows * 2; rowaddr3 = rows * 3; } set_output_multiple(rows); packed_items = rows; break; case MOD_32APSK: mod = 5; rows = frame_size / mod; /* 01234 */ rowaddr0 = 0; rowaddr1 = rows; rowaddr2 = rows * 2; rowaddr3 = rows * 3; rowaddr4 = rows * 4; set_output_multiple(rows); packed_items = rows; break; case MOD_4_12_16APSK: mod = 5; rows = frame_size / mod; /* 21430 */ if (frame_size == FRAME_SIZE_NORMAL) { rowaddr0 = rows * 2; rowaddr1 = rows; rowaddr2 = rows * 4; rowaddr3 = rows * 3; rowaddr4 = 0; } else { /* 41230 */ if (rate == C2_3) { rowaddr0 = rows * 4; rowaddr1 = rows; rowaddr2 = rows * 2; rowaddr3 = rows * 3; rowaddr4 = 0; } /* 10423 */ else if (rate == C32_45) { rowaddr0 = rows; rowaddr1 = 0; rowaddr2 = rows * 4; rowaddr3 = rows * 2; rowaddr4 = rows * 3; } } set_output_multiple(rows); packed_items = rows; break; case MOD_4_8_4_16APSK: mod = 5; rows = frame_size / mod; /* 40213 */ if (rate == C140_180) { rowaddr0 = rows * 4; rowaddr1 = 0; rowaddr2 = rows * 2; rowaddr3 = rows; rowaddr4 = rows * 3; } /* 40312 */ else { rowaddr0 = rows * 4; rowaddr1 = 0; rowaddr2 = rows * 3; rowaddr3 = rows; rowaddr4 = rows * 2; } set_output_multiple(rows); packed_items = rows; break; case MOD_64APSK: mod = 6; rows = frame_size / mod; /* 305214 */ rowaddr0 = rows * 3; rowaddr1 = 0; rowaddr2 = rows * 5; rowaddr3 = rows * 2; rowaddr4 = rows; rowaddr5 = rows * 4; set_output_multiple(rows); packed_items = rows; break; case MOD_8_16_20_20APSK: mod = 6; rows = frame_size / mod; /* 201543 */ if (rate == C7_9) { rowaddr0 = rows * 2; rowaddr1 = 0; rowaddr2 = rows; rowaddr3 = rows * 5; rowaddr4 = rows * 4; rowaddr5 = rows * 3; } /* 124053 */ else if (rate == C4_5) { rowaddr0 = rows; rowaddr1 = rows * 2; rowaddr2 = rows * 4; rowaddr3 = 0; rowaddr4 = rows * 5; rowaddr5 = rows * 3; } /* 421053 */ else if (rate == C5_6) { rowaddr0 = rows * 4; rowaddr1 = rows * 2; rowaddr2 = rows; rowaddr3 = 0; rowaddr4 = rows * 5; rowaddr5 = rows * 3; } set_output_multiple(rows); packed_items = rows; break; case MOD_4_12_20_28APSK: mod = 6; rows = frame_size / mod; /* 520143 */ rowaddr0 = rows * 5; rowaddr1 = rows * 2; rowaddr2 = 0; rowaddr3 = rows; rowaddr4 = rows * 4; rowaddr5 = rows * 3; set_output_multiple(rows); packed_items = rows; break; case MOD_128APSK: mod = 7; rows = (frame_size + 6) / mod; /* 4250316 */ if (rate == C135_180) { rowaddr0 = rows * 4; rowaddr1 = rows * 2; rowaddr2 = rows * 5; rowaddr3 = 0; rowaddr4 = rows * 3; rowaddr5 = rows; rowaddr6 = rows * 6; } /* 4130256 */ else if (rate == C140_180) { rowaddr0 = rows * 4; rowaddr1 = rows; rowaddr2 = rows * 3; rowaddr3 = 0; rowaddr4 = rows * 2; rowaddr5 = rows * 5; rowaddr6 = rows * 6; } set_output_multiple(rows + 12); packed_items = rows + 12; break; case MOD_256APSK: mod = 8; rows = frame_size / mod; /* 40372156 */ if (rate == C116_180) { rowaddr0 = rows * 4; rowaddr1 = 0; rowaddr2 = rows * 3; rowaddr3 = rows * 7; rowaddr4 = rows * 2; rowaddr5 = rows; rowaddr6 = rows * 5; rowaddr7 = rows * 6; } /* 46320571 */ else if (rate == C124_180) { rowaddr0 = rows * 4; rowaddr1 = rows * 6; rowaddr2 = rows * 3; rowaddr3 = rows * 2; rowaddr4 = 0; rowaddr5 = rows * 5; rowaddr6 = rows * 7; rowaddr7 = rows; } /* 75642301 */ else if (rate == C128_180) { rowaddr0 = rows * 7; rowaddr1 = rows * 5; rowaddr2 = rows * 6; rowaddr3 = rows * 4; rowaddr4 = rows * 2; rowaddr5 = rows * 3; rowaddr6 = 0; rowaddr7 = rows; } /* 50743612 */ else if (rate == C135_180) { rowaddr0 = rows * 5; rowaddr1 = 0; rowaddr2 = rows * 7; rowaddr3 = rows * 4; rowaddr4 = rows * 3; rowaddr5 = rows * 6; rowaddr6 = rows; rowaddr7 = rows * 2; } /* 01234567 */ else { rowaddr0 = 0; rowaddr1 = rows; rowaddr2 = rows * 2; rowaddr3 = rows * 3; rowaddr4 = rows * 4; rowaddr5 = rows * 5; rowaddr6 = rows * 6; rowaddr7 = rows * 7; } set_output_multiple(rows); packed_items = rows; break; default: mod = 2; rows = frame_size / mod; set_output_multiple(rows); packed_items = rows; break; } } /* * Our virtual destructor. */ dvbs2_interleaver_bb_impl::~dvbs2_interleaver_bb_impl() {} void dvbs2_interleaver_bb_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required) { if (signal_constellation == MOD_128APSK) { ninput_items_required[0] = ((noutput_items / 9270) * 9258) * mod; } else if (signal_constellation == MOD_BPSK_SF2) { ninput_items_required[0] = (noutput_items * mod) / 2; } else { ninput_items_required[0] = noutput_items * mod; } } int dvbs2_interleaver_bb_impl::general_work(int noutput_items, gr_vector_int& ninput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) { const unsigned char* in = (const unsigned char*)input_items[0]; unsigned char* out = (unsigned char*)output_items[0]; int consumed = 0; int produced = 0; int rows; switch (signal_constellation) { case MOD_BPSK: for (int i = 0; i < noutput_items; i += packed_items) { rows = frame_size; for (int j = 0; j < rows; j++) { out[produced++] = in[consumed++]; } } break; case MOD_BPSK_SF2: for (int i = 0; i < noutput_items; i += packed_items) { rows = frame_size; for (int j = 0; j < rows; j++) { out[produced++] = in[consumed]; out[produced++] = in[consumed++]; } } break; case MOD_QPSK: for (int i = 0; i < noutput_items; i += packed_items) { rows = frame_size / 2; for (int j = 0; j < rows; j++) { out[produced] = in[consumed++] << 1; out[produced++] |= in[consumed++]; } } break; case MOD_8PSK: case MOD_8APSK: for (int i = 0; i < noutput_items; i += packed_items) { rows = frame_size / 3; const unsigned char *c1, *c2, *c3; c1 = &in[consumed + rowaddr0]; c2 = &in[consumed + rowaddr1]; c3 = &in[consumed + rowaddr2]; for (int j = 0; j < rows; j++) { out[produced++] = (c1[j] << 2) | (c2[j] << 1) | (c3[j]); consumed += 3; } } break; case MOD_16APSK: case MOD_8_8APSK: for (int i = 0; i < noutput_items; i += packed_items) { rows = frame_size / 4; const unsigned char *c1, *c2, *c3, *c4; c1 = &in[consumed + rowaddr0]; c2 = &in[consumed + rowaddr1]; c3 = &in[consumed + rowaddr2]; c4 = &in[consumed + rowaddr3]; for (int j = 0; j < rows; j++) { out[produced++] = (c1[j] << 3) | (c2[j] << 2) | (c3[j] << 1) | (c4[j]); consumed += 4; } } break; case MOD_32APSK: case MOD_4_12_16APSK: case MOD_4_8_4_16APSK: for (int i = 0; i < noutput_items; i += packed_items) { rows = frame_size / 5; const unsigned char *c1, *c2, *c3, *c4, *c5; c1 = &in[consumed + rowaddr0]; c2 = &in[consumed + rowaddr1]; c3 = &in[consumed + rowaddr2]; c4 = &in[consumed + rowaddr3]; c5 = &in[consumed + rowaddr4]; for (int j = 0; j < rows; j++) { out[produced++] = (c1[j] << 4) | (c2[j] << 3) | (c3[j] << 2) | (c4[j] << 1) | c5[j]; consumed += 5; } } break; case MOD_64APSK: case MOD_8_16_20_20APSK: case MOD_4_12_20_28APSK: for (int i = 0; i < noutput_items; i += packed_items) { rows = frame_size / 6; const unsigned char *c1, *c2, *c3, *c4, *c5, *c6; c1 = &in[consumed + rowaddr0]; c2 = &in[consumed + rowaddr1]; c3 = &in[consumed + rowaddr2]; c4 = &in[consumed + rowaddr3]; c5 = &in[consumed + rowaddr4]; c6 = &in[consumed + rowaddr5]; for (int j = 0; j < rows; j++) { out[produced++] = (c1[j] << 5) | (c2[j] << 4) | (c3[j] << 3) | (c4[j] << 2) | (c5[j] << 1) | c6[j]; consumed += 6; } } break; case MOD_128APSK: for (int i = 0; i < noutput_items; i += packed_items) { rows = (frame_size + 6) / 7; const unsigned char *c1, *c2, *c3, *c4, *c5, *c6, *c7; c1 = &in[consumed + rowaddr0]; c2 = &in[consumed + rowaddr1]; c3 = &in[consumed + rowaddr2]; c4 = &in[consumed + rowaddr3]; c5 = &in[consumed + rowaddr4]; c6 = &in[consumed + rowaddr5]; c7 = &in[consumed + rowaddr6]; for (int j = 0; j < rows; j++) { out[produced++] = (c1[j] << 6) | (c2[j] << 5) | (c3[j] << 4) | (c4[j] << 3) | (c5[j] << 2) | (c6[j] << 1) | c7[j]; consumed += 7; } for (int j = 0; j < 12; j++) { out[produced++] = 0x7f; } } break; case MOD_256APSK: for (int i = 0; i < noutput_items; i += packed_items) { rows = frame_size / 8; const unsigned char *c1, *c2, *c3, *c4, *c5, *c6, *c7, *c8; c1 = &in[consumed + rowaddr0]; c2 = &in[consumed + rowaddr1]; c3 = &in[consumed + rowaddr2]; c4 = &in[consumed + rowaddr3]; c5 = &in[consumed + rowaddr4]; c6 = &in[consumed + rowaddr5]; c7 = &in[consumed + rowaddr6]; c8 = &in[consumed + rowaddr7]; for (int j = 0; j < rows; j++) { out[produced++] = (c1[j] << 7) | (c2[j] << 6) | (c3[j] << 5) | (c4[j] << 4) | (c5[j] << 3) | (c6[j] << 2) | (c7[j] << 1) | c8[j]; consumed += 8; } } break; default: for (int i = 0; i < noutput_items; i += packed_items) { rows = frame_size / 2; for (int j = 0; j < rows; j++) { out[produced] = in[consumed++] << 1; out[produced++] |= in[consumed++]; } } break; } // Tell runtime system how many input items we consumed on // each input stream. consume_each(consumed); // Tell runtime system how many output items we produced. return noutput_items; } } /* namespace dtv */ } /* namespace gr */