summaryrefslogtreecommitdiff
path: root/gr-dtv/lib/atsc
diff options
context:
space:
mode:
authorRon Economos <w6rz@comcast.net>2015-01-20 18:56:31 -0800
committerRon Economos <w6rz@comcast.net>2015-01-20 18:56:31 -0800
commita8fbd0c6f0fef8da457fcf26f23991ef1237a5bb (patch)
treea34e9afbffa73a80f40d7b99e5769cd461b9d773 /gr-dtv/lib/atsc
parent0bea2cce5337048c984889875c6434be401e1a23 (diff)
Add ATSC transmitter blocks and flow graph to gr-dtv.
Diffstat (limited to 'gr-dtv/lib/atsc')
-rw-r--r--gr-dtv/lib/atsc/atsc_basic_trellis_encoder.cc65
-rw-r--r--gr-dtv/lib/atsc/atsc_basic_trellis_encoder.h63
-rw-r--r--gr-dtv/lib/atsc/atsc_field_sync_mux_impl.cc243
-rw-r--r--gr-dtv/lib/atsc/atsc_field_sync_mux_impl.h60
-rw-r--r--gr-dtv/lib/atsc/atsc_interleaver_impl.cc122
-rw-r--r--gr-dtv/lib/atsc/atsc_interleaver_impl.h51
-rw-r--r--gr-dtv/lib/atsc/atsc_pad_impl.cc74
-rw-r--r--gr-dtv/lib/atsc/atsc_pad_impl.h45
-rw-r--r--gr-dtv/lib/atsc/atsc_randomizer_impl.cc106
-rw-r--r--gr-dtv/lib/atsc/atsc_randomizer_impl.h53
-rw-r--r--gr-dtv/lib/atsc/atsc_rs_encoder_impl.cc112
-rw-r--r--gr-dtv/lib/atsc/atsc_rs_encoder_impl.h54
-rw-r--r--gr-dtv/lib/atsc/atsc_trellis_encoder_impl.cc264
-rw-r--r--gr-dtv/lib/atsc/atsc_trellis_encoder_impl.h60
14 files changed, 1372 insertions, 0 deletions
diff --git a/gr-dtv/lib/atsc/atsc_basic_trellis_encoder.cc b/gr-dtv/lib/atsc/atsc_basic_trellis_encoder.cc
new file mode 100644
index 0000000000..f7327c75fb
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_basic_trellis_encoder.cc
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "atsc_basic_trellis_encoder.h"
+#include <assert.h>
+
+namespace gr {
+ namespace dtv {
+
+ const unsigned char atsc_basic_trellis_encoder::next_state[32] = {
+ 0,1,4,5,
+ 2,3,6,7,
+ 1,0,5,4,
+ 3,2,7,6,
+ 4,5,0,1,
+ 6,7,2,3,
+ 5,4,1,0,
+ 7,6,3,2
+ };
+
+ const unsigned char atsc_basic_trellis_encoder::out_symbol[32] = {
+ 0,2,4,6,
+ 1,3,5,7,
+ 0,2,4,6,
+ 1,3,5,7,
+ 4,6,0,2,
+ 5,7,1,3,
+ 4,6,0,2,
+ 5,7,1,3
+ };
+
+ /*!
+ * Encode two bit INPUT into 3 bit return value. Domain is [0,3],
+ * Range is [0,7]. The mapping to bipolar levels is not done.
+ */
+
+ int
+ atsc_basic_trellis_encoder::encode(unsigned int input)
+ {
+ assert (input < 4);
+ int index = (state << 2) + input;
+ state = next_state[index];
+ return out_symbol[index];
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/atsc/atsc_basic_trellis_encoder.h b/gr-dtv/lib/atsc/atsc_basic_trellis_encoder.h
new file mode 100644
index 0000000000..a4e64fb225
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_basic_trellis_encoder.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_ATSC_TRELLIS_ENCODER_H
+#define INCLUDED_ATSC_TRELLIS_ENCODER_H
+
+/*!
+ * \brief ATSC trellis encoder building block.
+ *
+ * Note this is NOT the 12x interleaved interface.
+ *
+ * This implements a single instance of the ATSC trellis encoder.
+ * This is a rate 2/3 encoder (really a constraint length 3, rate 1/2
+ * encoder with the top bit passed through unencoded. This does not
+ * implement the "precoding" of the top bit, because the NTSC rejection
+ * filter is not supported.
+ */
+
+namespace gr {
+ namespace dtv {
+
+ class atsc_basic_trellis_encoder
+ {
+ private:
+ int state; // two bit state;
+
+ public:
+ atsc_basic_trellis_encoder() : state(0) {}
+
+ /*!
+ * Encode two bit INPUT into 3 bit return value. Domain is [0,3],
+ * Range is [0,7]. The mapping to bipolar levels is not done.
+ */
+ int encode(unsigned int input);
+
+ //! reset encoder state
+ void reset() {state = 0;}
+
+ static const unsigned char next_state[32];
+ static const unsigned char out_symbol[32];
+ };
+
+ } /* namespace dtv */
+} /* namespace gr */
+
+#endif /* INCLUDED_ATSC_TRELLIS_ENCODER_H */
diff --git a/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.cc b/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.cc
new file mode 100644
index 0000000000..01400e697e
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.cc
@@ -0,0 +1,243 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "atsc_field_sync_mux_impl.h"
+#include "gnuradio/dtv/atsc_consts.h"
+
+namespace gr {
+ namespace dtv {
+
+ static const int N_SAVED_SYMBOLS = 12;
+
+ atsc_field_sync_mux::sptr
+ atsc_field_sync_mux::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new atsc_field_sync_mux_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ atsc_field_sync_mux_impl::atsc_field_sync_mux_impl()
+ : gr::block("atsc_field_sync_mux",
+ gr::io_signature::make(1, 1, sizeof(atsc_data_segment)),
+ gr::io_signature::make(1, 1, sizeof(atsc_data_segment)))
+ {
+ d_already_output_field_sync = false;
+ for (int i = 0; i < N_SAVED_SYMBOLS; i++)
+ {
+ d_saved_symbols[i] = 0;
+ }
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ atsc_field_sync_mux_impl::~atsc_field_sync_mux_impl()
+ {
+ }
+
+ void
+ atsc_field_sync_mux_impl::init_field_sync_common(unsigned char *p, int mask,
+ const unsigned char saved_symbols[N_SAVED_SYMBOLS])
+ {
+ static const unsigned char bin_map[2] = {1, 6}; // map binary values to 1 of 8 levels
+
+ int i = 0;
+
+ p[i++] = bin_map[1]; // data segment sync pulse
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[1];
+
+ for (int j = 0; j < 511; j++) // PN511
+ {
+ p[i++] = bin_map[atsc_pn511[j]];
+ }
+
+ for (int j = 0; j < 63; j++) // PN63
+ {
+ p[i++] = bin_map[atsc_pn63[j]];
+ }
+
+ for (int j = 0; j < 63; j++) // PN63, toggled on field 2
+ {
+ p[i++] = bin_map[atsc_pn63[j] ^ mask];
+ }
+
+ for (int j = 0; j < 63; j++) // PN63
+ {
+ p[i++] = bin_map[atsc_pn63[j]];
+ }
+
+ p[i++] = bin_map[0]; // 24 bits of 8VSB mode identifier
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[0];
+
+ p[i++] = bin_map[1];
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[1];
+ p[i++] = bin_map[0];
+
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[1];
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[1];
+
+ p[i++] = bin_map[1];
+ p[i++] = bin_map[1];
+ p[i++] = bin_map[1];
+ p[i++] = bin_map[1];
+
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[1];
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[1];
+
+ p[i++] = bin_map[1];
+ p[i++] = bin_map[0];
+ p[i++] = bin_map[1];
+ p[i++] = bin_map[0];
+
+ for (int j = 0; j < 92; j++) // 92 more bits
+ {
+ p[i++] = bin_map[atsc_pn63[j % 63]];
+ }
+
+ // now copy the last 12 symbols of the previous segment
+
+ for (int j = 0; j < N_SAVED_SYMBOLS; j++)
+ {
+ p[i++] = saved_symbols[j];
+ }
+
+ assert (i == ATSC_DATA_SEGMENT_LENGTH);
+ }
+
+ inline void
+ atsc_field_sync_mux_impl::init_field_sync_1(atsc_data_segment *s,
+ const unsigned char saved_symbols[N_SAVED_SYMBOLS])
+ {
+ init_field_sync_common(&s->data[0], 0, saved_symbols);
+ }
+
+ inline void
+ atsc_field_sync_mux_impl::init_field_sync_2(atsc_data_segment *s,
+ const unsigned char saved_symbols[N_SAVED_SYMBOLS])
+ {
+ init_field_sync_common(&s->data[0], 1, saved_symbols);
+ }
+
+ void
+ atsc_field_sync_mux_impl::save_last_symbols(unsigned char saved_symbols[N_SAVED_SYMBOLS],
+ const atsc_data_segment &seg)
+ {
+ for (int i = 0; i < N_SAVED_SYMBOLS; i++)
+ {
+ saved_symbols[i] = seg.data[i + ATSC_DATA_SEGMENT_LENGTH - N_SAVED_SYMBOLS];
+ }
+ }
+
+ inline bool
+ atsc_field_sync_mux_impl::last_regular_seg_p(const plinfo &pli)
+ {
+ return pli.regular_seg_p() && (pli.segno() == ATSC_DSEGS_PER_FIELD - 1);
+ }
+
+ void
+ atsc_field_sync_mux_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items;
+ }
+
+ int
+ atsc_field_sync_mux_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 atsc_data_segment *in = (const atsc_data_segment *) input_items[0];
+ atsc_data_segment *out = (atsc_data_segment *) output_items[0];
+ int in_length = ninput_items[0];
+ int index = 0;
+ int outdex = 0;
+
+ for (outdex = 0; outdex < noutput_items && index < in_length; outdex++)
+ {
+ assert(in[index].pli.regular_seg_p());
+
+ if (!in[index].pli.first_regular_seg_p())
+ {
+ out[outdex] = in[index]; // just copy in to out
+
+ if (last_regular_seg_p(in[index].pli))
+ {
+ save_last_symbols(d_saved_symbols, in[index]);
+ }
+ index++;
+ }
+ else
+ { // first_regular_seg_p
+ if (!d_already_output_field_sync)
+ {
+ // write out field sync...
+ atsc_data_segment field_sync;
+
+ if (in[index].pli.in_field1_p())
+ {
+ init_field_sync_1(&field_sync, d_saved_symbols);
+ }
+ else
+ {
+ init_field_sync_2(&field_sync, d_saved_symbols);
+ }
+
+ // note that index doesn't advance in this branch
+ out[outdex] = field_sync;
+ d_already_output_field_sync = true;
+ }
+ else
+ {
+ // already output field sync, now output first regular segment
+ out[outdex] = in[index];
+ index++;
+ d_already_output_field_sync = false;
+ }
+ }
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each (index);
+
+ // Tell runtime system how many output items we produced.
+ return outdex;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.h b/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.h
new file mode 100644
index 0000000000..ba73faaac6
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_ATSC_FIELD_SYNC_MUX_IMPL_H
+#define INCLUDED_DTV_ATSC_FIELD_SYNC_MUX_IMPL_H
+
+#include <gnuradio/dtv/atsc_field_sync_mux.h>
+#include "atsc_pnXXX_impl.h"
+#include "atsc_types.h"
+
+namespace gr {
+ namespace dtv {
+
+ class atsc_field_sync_mux_impl : public atsc_field_sync_mux
+ {
+ private:
+ static const int N_SAVED_SYMBOLS = 12;
+ bool d_already_output_field_sync;
+ unsigned char d_saved_symbols[N_SAVED_SYMBOLS];
+
+ void init_field_sync_common(unsigned char *p, int mask, const unsigned char saved_symbols[N_SAVED_SYMBOLS]);
+ inline void init_field_sync_1(atsc_data_segment *s, const unsigned char saved_symbols[N_SAVED_SYMBOLS]);
+ inline void init_field_sync_2(atsc_data_segment *s, const unsigned char saved_symbols[N_SAVED_SYMBOLS]);
+ void save_last_symbols(unsigned char saved_symbols[N_SAVED_SYMBOLS], const atsc_data_segment &seg);
+ inline bool last_regular_seg_p(const plinfo &pli);
+
+ public:
+ atsc_field_sync_mux_impl();
+ ~atsc_field_sync_mux_impl();
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_ATSC_FIELD_SYNC_MUX_IMPL_H */
+
diff --git a/gr-dtv/lib/atsc/atsc_interleaver_impl.cc b/gr-dtv/lib/atsc/atsc_interleaver_impl.cc
new file mode 100644
index 0000000000..6d147f5682
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_interleaver_impl.cc
@@ -0,0 +1,122 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "atsc_interleaver_impl.h"
+#include "gnuradio/dtv/atsc_consts.h"
+
+namespace gr {
+ namespace dtv {
+
+ atsc_interleaver::sptr
+ atsc_interleaver::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new atsc_interleaver_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ atsc_interleaver_impl::atsc_interleaver_impl()
+ : gr::sync_block("atsc_interleaver",
+ gr::io_signature::make(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)),
+ gr::io_signature::make(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)))
+ {
+ I = 52; /* ATSC interleaver */
+ J = 4;
+ registers = (unsigned char *) malloc(sizeof(unsigned char) * I * ((I - 1) * J));
+ if (registers == NULL) {
+ fprintf(stderr, "Out of memory.\n");
+ exit(1);
+ }
+
+ pointers = (int *) malloc(sizeof(int) * I);
+ if (pointers == NULL) {
+ fprintf(stderr, "Out of memory.\n");
+ exit(1);
+ }
+
+ memset(registers, 0, sizeof(unsigned char) * I * ((I - 1) * J));
+ memset(pointers, 0, sizeof(int) * I);
+
+ this->I = I;
+ this->J = J;
+ commutator = 0;
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ atsc_interleaver_impl::~atsc_interleaver_impl()
+ {
+ free(pointers);
+ free(registers);
+ }
+
+ int
+ atsc_interleaver_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const atsc_mpeg_packet_rs_encoded *in = (const atsc_mpeg_packet_rs_encoded *) input_items[0];
+ atsc_mpeg_packet_rs_encoded *out = (atsc_mpeg_packet_rs_encoded *) output_items[0];
+ int p, n = ATSC_MPEG_RS_ENCODED_LENGTH;
+
+ for (int i = 0; i < noutput_items; i++)
+ {
+ assert(in[i].pli.regular_seg_p());
+ plinfo::sanity_check(in[i].pli);
+
+ out[i].pli = in[i].pli; // copy pipeline info
+ if (in[i].pli.first_regular_seg_p()) // reset commutator if required
+ {
+ commutator = 0;
+ }
+ for (int j = 0; j < n; j++)
+ {
+ if (commutator == 0)
+ {
+ out[i].data[j] = in[i].data[j];
+ }
+ else
+ {
+ p = pointers[commutator];
+
+ out[i].data[j] = registers[commutator * (I - 1) * J + p];
+ registers[commutator * (I - 1) * J + p] = in[i].data[j];
+
+ pointers[commutator] = (p + 1) % (commutator * J);
+ }
+ commutator = (commutator + 1) % I;
+ }
+ }
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/atsc/atsc_interleaver_impl.h b/gr-dtv/lib/atsc/atsc_interleaver_impl.h
new file mode 100644
index 0000000000..337edcf0ec
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_interleaver_impl.h
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_ATSC_INTERLEAVER_IMPL_H
+#define INCLUDED_DTV_ATSC_INTERLEAVER_IMPL_H
+
+#include <gnuradio/dtv/atsc_interleaver.h>
+#include "atsc_types.h"
+
+namespace gr {
+ namespace dtv {
+
+ class atsc_interleaver_impl : public atsc_interleaver
+ {
+ private:
+ int I, J;
+ int commutator;
+ unsigned char *registers;
+ int *pointers;
+
+ public:
+ atsc_interleaver_impl();
+ ~atsc_interleaver_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_ATSC_INTERLEAVER_IMPL_H */
+
diff --git a/gr-dtv/lib/atsc/atsc_pad_impl.cc b/gr-dtv/lib/atsc/atsc_pad_impl.cc
new file mode 100644
index 0000000000..1b5e733f19
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_pad_impl.cc
@@ -0,0 +1,74 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "atsc_pad_impl.h"
+#include "gnuradio/dtv/atsc_consts.h"
+
+namespace gr {
+ namespace dtv {
+
+ atsc_pad::sptr
+ atsc_pad::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new atsc_pad_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ atsc_pad_impl::atsc_pad_impl()
+ : gr::sync_decimator("atsc_pad",
+ gr::io_signature::make(1, 1, sizeof(unsigned char)),
+ gr::io_signature::make(1, 1, sizeof(atsc_mpeg_packet)), ATSC_MPEG_PKT_LENGTH)
+ {}
+
+ /*
+ * Our virtual destructor.
+ */
+ atsc_pad_impl::~atsc_pad_impl()
+ {
+ }
+
+ int
+ atsc_pad_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ atsc_mpeg_packet *out = (atsc_mpeg_packet *) output_items[0];
+
+ for (int i = 0; i < noutput_items; i++)
+ {
+ memcpy(out[i].data, &in[i * ATSC_MPEG_PKT_LENGTH], ATSC_MPEG_PKT_LENGTH);
+ }
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/atsc/atsc_pad_impl.h b/gr-dtv/lib/atsc/atsc_pad_impl.h
new file mode 100644
index 0000000000..4a661bd394
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_pad_impl.h
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_ATSC_PAD_IMPL_H
+#define INCLUDED_DTV_ATSC_PAD_IMPL_H
+
+#include <gnuradio/dtv/atsc_pad.h>
+#include "atsc_types.h"
+
+namespace gr {
+ namespace dtv {
+
+ class atsc_pad_impl : public atsc_pad
+ {
+ public:
+ atsc_pad_impl();
+ ~atsc_pad_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_ATSC_PAD_IMPL_H */
+
diff --git a/gr-dtv/lib/atsc/atsc_randomizer_impl.cc b/gr-dtv/lib/atsc/atsc_randomizer_impl.cc
new file mode 100644
index 0000000000..55d47851d2
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_randomizer_impl.cc
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "atsc_randomizer_impl.h"
+#include "gnuradio/dtv/atsc_consts.h"
+
+namespace gr {
+ namespace dtv {
+
+ atsc_randomizer::sptr
+ atsc_randomizer::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new atsc_randomizer_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ atsc_randomizer_impl::atsc_randomizer_impl()
+ : gr::sync_block("atsc_randomizer",
+ gr::io_signature::make(1, 1, sizeof(atsc_mpeg_packet)),
+ gr::io_signature::make(1, 1, sizeof(atsc_mpeg_packet_no_sync)))
+ {
+ reset();
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ atsc_randomizer_impl::~atsc_randomizer_impl()
+ {
+ }
+
+ void
+ atsc_randomizer_impl::reset()
+ {
+ d_rand.reset();
+ d_field2 = false;
+ d_segno = 0;
+ }
+
+ int
+ atsc_randomizer_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const atsc_mpeg_packet *in = (const atsc_mpeg_packet *) input_items[0];
+ atsc_mpeg_packet_no_sync *out = (atsc_mpeg_packet_no_sync *) output_items[0];
+
+ for (int i = 0; i < noutput_items; i++)
+ {
+ // sanity check incoming data.
+ assert((in[i].data[0] == MPEG_SYNC_BYTE));
+ assert((in[i].data[1] & MPEG_TRANSPORT_ERROR_BIT) == 0);
+
+ // initialize plinfo for downstream
+ //
+ // We do this here because the randomizer is effectively
+ // the head of the tx processing chain
+ //
+ out[i].pli.set_regular_seg(d_field2, d_segno);
+ d_segno++;
+ if (d_segno == 312)
+ {
+ d_segno = 0;
+ d_field2 = !d_field2;
+ }
+
+ if (out[i].pli.first_regular_seg_p())
+ {
+ d_rand.reset();
+ }
+
+ d_rand.randomize(out[i], in[i]);
+ }
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/atsc/atsc_randomizer_impl.h b/gr-dtv/lib/atsc/atsc_randomizer_impl.h
new file mode 100644
index 0000000000..48ee213dfb
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_randomizer_impl.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_ATSC_RANDOMIZER_IMPL_H
+#define INCLUDED_DTV_ATSC_RANDOMIZER_IMPL_H
+
+#include <gnuradio/dtv/atsc_randomizer.h>
+#include "atsc_randomize.h"
+#include "atsc_types.h"
+
+namespace gr {
+ namespace dtv {
+
+ class atsc_randomizer_impl : public atsc_randomizer
+ {
+ private:
+ atsc_randomize d_rand;
+ int d_segno;
+ bool d_field2;
+
+ void reset(void);
+
+ public:
+ atsc_randomizer_impl();
+ ~atsc_randomizer_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_ATSC_RANDOMIZER_IMPL_H */
+
diff --git a/gr-dtv/lib/atsc/atsc_rs_encoder_impl.cc b/gr-dtv/lib/atsc/atsc_rs_encoder_impl.cc
new file mode 100644
index 0000000000..002dc17d93
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_rs_encoder_impl.cc
@@ -0,0 +1,112 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "atsc_rs_encoder_impl.h"
+
+namespace gr {
+ namespace dtv {
+
+ static const int rs_init_symsize = 8;
+ static const int rs_init_gfpoly = 0x11d;
+ static const int rs_init_fcr = 0; // first consecutive root
+ static const int rs_init_prim = 1; // primitive is 1 (alpha)
+ static const int rs_init_nroots = 20;
+
+ static const int N = (1 << rs_init_symsize) - 1; // 255
+ static const int K = N - rs_init_nroots; // 235
+
+ static const int amount_of_pad = N - ATSC_MPEG_RS_ENCODED_LENGTH; // 48
+
+ atsc_rs_encoder::sptr
+ atsc_rs_encoder::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new atsc_rs_encoder_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ atsc_rs_encoder_impl::atsc_rs_encoder_impl()
+ : gr::sync_block("atsc_rs_encoder",
+ gr::io_signature::make(1, 1, sizeof(atsc_mpeg_packet_no_sync)),
+ gr::io_signature::make(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)))
+ {
+ d_rs = init_rs_char(rs_init_symsize, rs_init_gfpoly, rs_init_fcr, rs_init_prim, rs_init_nroots);
+ assert (d_rs != 0);
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ atsc_rs_encoder_impl::~atsc_rs_encoder_impl()
+ {
+ if (d_rs)
+ {
+ free_rs_char(d_rs);
+ }
+ d_rs = 0;
+ }
+
+ void
+ atsc_rs_encoder_impl::encode(atsc_mpeg_packet_rs_encoded &out, const atsc_mpeg_packet_no_sync &in)
+ {
+ unsigned char tmp[K];
+
+ assert((int)(amount_of_pad + sizeof (in.data)) == K);
+
+ // add missing prefix zero padding to message
+ memset(tmp, 0, amount_of_pad);
+ memcpy(&tmp[amount_of_pad], in.data, sizeof (in.data));
+
+ // copy message portion to output packet
+ memcpy(out.data, in.data, sizeof (in.data));
+
+ // now compute parity bytes and add them to tail end of output packet
+ encode_rs_char(d_rs, tmp, &out.data[sizeof (in.data)]);
+ }
+
+ int
+ atsc_rs_encoder_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const atsc_mpeg_packet_no_sync *in = (const atsc_mpeg_packet_no_sync *) input_items[0];
+ atsc_mpeg_packet_rs_encoded *out = (atsc_mpeg_packet_rs_encoded *) output_items[0];
+
+ for (int i = 0; i < noutput_items; i++)
+ {
+ assert(in[i].pli.regular_seg_p());
+ out[i].pli = in[i].pli; // copy pipeline info...
+ encode(out[i], in[i]);
+ }
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/atsc/atsc_rs_encoder_impl.h b/gr-dtv/lib/atsc/atsc_rs_encoder_impl.h
new file mode 100644
index 0000000000..3f82a29f03
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_rs_encoder_impl.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_ATSC_RS_ENCODER_IMPL_H
+#define INCLUDED_DTV_ATSC_RS_ENCODER_IMPL_H
+
+#include <gnuradio/dtv/atsc_rs_encoder.h>
+#include "atsc_types.h"
+
+extern "C"
+{
+#include <gnuradio/fec/rs.h>
+}
+
+namespace gr {
+ namespace dtv {
+
+ class atsc_rs_encoder_impl : public atsc_rs_encoder
+ {
+ private:
+ void *d_rs;
+ void encode(atsc_mpeg_packet_rs_encoded &out, const atsc_mpeg_packet_no_sync &in);
+
+ public:
+ atsc_rs_encoder_impl();
+ ~atsc_rs_encoder_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_ATSC_RS_ENCODER_IMPL_H */
+
diff --git a/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.cc b/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.cc
new file mode 100644
index 0000000000..3baf045d25
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.cc
@@ -0,0 +1,264 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "atsc_trellis_encoder_impl.h"
+#include "gnuradio/dtv/atsc_consts.h"
+#include <stdio.h>
+
+namespace gr {
+ namespace dtv {
+
+static const int DIBITS_PER_BYTE = 4;
+
+#define SEGOF(x) ( (x) / ((SEGMENT_SIZE + 1) * DIBITS_PER_BYTE))
+#define SYMOF(x) (((x) % ((SEGMENT_SIZE + 1) * DIBITS_PER_BYTE)) - 4)
+
+/* How many separate Trellis encoders / Viterbi decoders run in parallel */
+static const int NCODERS = 12;
+
+#define ENCODER_SEG_BUMP 4
+
+/* A Segment sync symbol is an 8VSB +5,-5,-5,+5 sequence that occurs at
+ the start of each 207-byte segment (including field sync segments). */
+#define DSEG_SYNC_SYM1 0x06 /* +5 */
+#define DSEG_SYNC_SYM2 0x01 /* -5 */
+#define DSEG_SYNC_SYM3 0x01 /* -5 */
+#define DSEG_SYNC_SYM4 0x06 /* +5 */
+
+/* Shift counts to bit numbers (high order, low order); 9x entries unused */
+static const int bit1[8] = {1, 99, 3, 98, 5, 97, 7, 96};
+static const int bit2[8] = {0, 99, 2, 98, 4, 97, 6, 96};
+
+ atsc_trellis_encoder::sptr
+ atsc_trellis_encoder::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new atsc_trellis_encoder_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ atsc_trellis_encoder_impl::atsc_trellis_encoder_impl()
+ : gr::sync_block("atsc_trellis_encoder",
+ gr::io_signature::make(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)),
+ gr::io_signature::make(1, 1, sizeof(atsc_data_segment)))
+ {
+ reset();
+ debug = false;
+ set_output_multiple(NCODERS);
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ atsc_trellis_encoder_impl::~atsc_trellis_encoder_impl()
+ {
+ }
+
+ void
+ atsc_trellis_encoder_impl::reset()
+ {
+ for (int i = 0; i < NCODERS; i++)
+ {
+ enc[i].reset();
+ }
+ }
+
+ void
+ atsc_trellis_encoder_impl::encode(atsc_data_segment out[NCODERS],
+ const atsc_mpeg_packet_rs_encoded in[NCODERS])
+ {
+ unsigned char out_copy[OUTPUT_SIZE];
+ unsigned char in_copy[INPUT_SIZE];
+
+ assert (sizeof (in_copy) == sizeof (in[0].data) * NCODERS);
+ assert (sizeof (out_copy) == sizeof (out[0].data) * NCODERS);
+
+ // copy input into continguous temporary buffer
+ for (int i = 0; i < NCODERS; i++)
+ {
+ assert(in[i].pli.regular_seg_p());
+ plinfo::sanity_check (in[i].pli);
+ memcpy(&in_copy[i * INPUT_SIZE / NCODERS], &in[i].data[0], ATSC_MPEG_RS_ENCODED_LENGTH * sizeof (in_copy[0]));
+ }
+
+ memset(out_copy, 0, sizeof (out_copy)); // FIXME, sanity check
+
+ // do the deed...
+ encode_helper(out_copy, in_copy);
+
+ // copy output from contiguous temp buffer into final output
+ for (int i = 0; i < NCODERS; i++)
+ {
+ memcpy(&out[i].data[0], &out_copy[i * OUTPUT_SIZE / NCODERS], ATSC_DATA_SEGMENT_LENGTH * sizeof (out_copy[0]));
+
+ // copy pipeline info
+ out[i].pli = in[i].pli;
+
+ plinfo::sanity_check(out[i].pli);
+ assert(out[i].pli.regular_seg_p());
+ }
+ }
+
+ /*
+ * This code expects contiguous arrrays. Use it as is, it computes
+ * the correct answer. Maybe someday, when we've run out of better
+ * things to do, rework to avoid the copying in encode.
+ */
+ void
+ atsc_trellis_encoder_impl::encode_helper(unsigned char output[OUTPUT_SIZE],
+ const unsigned char input[INPUT_SIZE])
+ {
+ int i;
+ int encoder;
+ unsigned char trellis_buffer[NCODERS];
+ int trellis_wherefrom[NCODERS];
+ unsigned char *out, *next_out_seg;
+ int chunk;
+ int shift;
+ unsigned char dibit;
+ unsigned char symbol;
+ int skip_encoder_bump;
+
+ /* FIXME, we may want special processing here for a flag
+ * byte to keep track of which part of the field we're in?
+ */
+
+ encoder = NCODERS - ENCODER_SEG_BUMP;
+ skip_encoder_bump = 0;
+ out = output;
+ next_out_seg = out;
+
+ for (chunk = 0; chunk < INPUT_SIZE; chunk += NCODERS)
+ {
+ /* Load a new chunk of bytes into the Trellis encoder buffers.
+ * They get loaded in an order that depends on where we are in
+ * the segment sync progress (sigh).
+ * GRR! When the chunk reload happens at the same time as the
+ * segment boundary, we should bump the encoder NOW for the reload,
+ * rather than LATER during the bitshift transition!!!
+ */
+ if (out >= next_out_seg)
+ {
+ encoder = (encoder + ENCODER_SEG_BUMP) % NCODERS;
+ skip_encoder_bump = 1;
+ }
+
+ for (i = 0; i < NCODERS; i++)
+ {
+ /* for debug */
+ trellis_wherefrom[encoder] = chunk + i;
+ trellis_buffer[encoder] = input [chunk + i];
+ encoder++;
+ if (encoder >= NCODERS)
+ {
+ encoder = 0;
+ }
+ }
+
+ for (shift = 6; shift >= 0; shift -= 2)
+ {
+ /* Segment boundaries happen to occur on some bitshift transitions. */
+ if (out >= next_out_seg)
+ {
+ /* Segment transition. Output a data segment sync symbol,
+ * and mess with the trellis encoder mux.
+ */
+ *out++ = DSEG_SYNC_SYM1;
+ *out++ = DSEG_SYNC_SYM2;
+ *out++ = DSEG_SYNC_SYM3;
+ *out++ = DSEG_SYNC_SYM4;
+ if (debug)
+ {
+ printf("SYNC SYNC SYNC SYNC\n");
+ }
+ next_out_seg = out + (SEGMENT_SIZE * DIBITS_PER_BYTE);
+
+ if (!skip_encoder_bump)
+ {
+ encoder = (encoder + ENCODER_SEG_BUMP) % NCODERS;
+ }
+ skip_encoder_bump = 0;
+ }
+
+ /* Now run each of the 12 Trellis encoders to spit out 12 symbols.
+ * Each encoder takes input from the same byte of the chunk, but
+ * the outputs of the encoders come out in various orders.
+ * NOPE -- this is false. The encoders take input from various
+ * bytes of the chunk (which changes at segment sync time), AND
+ * they also come out in various orders. You really do have to
+ * keep separate track of: the input bytes, the encoders, and
+ * the output bytes -- because they're all moving with respect
+ * to each other!!!
+ */
+ for (i = 0; i < NCODERS; i++)
+ {
+ dibit = 0x03 & (trellis_buffer[encoder] >> shift);
+ if (debug)
+ {
+ printf("Seg %ld Symb %3ld Trell %2d Byte %6d Bits %d-%d = dibit %d ", (long) SEGOF(out-output), (long) SYMOF(out-output), encoder, trellis_wherefrom[encoder], bit1[shift], bit2[shift], dibit);
+ }
+ symbol = enc[encoder].encode(dibit);
+ *out++ = symbol;
+ encoder++;
+ if (encoder >= NCODERS)
+ {
+ encoder = 0;
+ }
+ if (debug)
+ {
+ printf("sym %d\n", symbol);
+ }
+ } /* Encoders */
+ } /* Bit shifts */
+ } /* Chunks */
+
+ /* Check up on ourselves */
+ assert (0 == (INPUT_SIZE * DIBITS_PER_BYTE) % NCODERS);
+ assert (OUTPUT_SIZE == out - output);
+ assert (NCODERS - ENCODER_SEG_BUMP == encoder);
+ }
+
+ int
+ atsc_trellis_encoder_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const atsc_mpeg_packet_rs_encoded *in = (const atsc_mpeg_packet_rs_encoded *) input_items[0];
+ atsc_data_segment *out = (atsc_data_segment *) output_items[0];
+
+ for (int i = 0; i < noutput_items; i += NCODERS)
+ {
+ encode(&out[i], &in[i]);
+ }
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.h b/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.h
new file mode 100644
index 0000000000..f81b4d0015
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_ATSC_TRELLIS_ENCODER_IMPL_H
+#define INCLUDED_DTV_ATSC_TRELLIS_ENCODER_IMPL_H
+
+#include <gnuradio/dtv/atsc_trellis_encoder.h>
+#include "atsc_basic_trellis_encoder.h"
+#include "atsc_types.h"
+
+namespace gr {
+ namespace dtv {
+
+ class atsc_trellis_encoder_impl : public atsc_trellis_encoder
+ {
+ private:
+ bool debug;
+
+ static const int NCODERS = 12;
+ static const int SEGMENT_SIZE = ATSC_MPEG_RS_ENCODED_LENGTH;
+ static const int INPUT_SIZE = (SEGMENT_SIZE * 12);
+ static const int OUTPUT_SIZE = (ATSC_DATA_SEGMENT_LENGTH * 12);
+
+ void reset();
+ void encode(atsc_data_segment out[NCODERS], const atsc_mpeg_packet_rs_encoded in[NCODERS]);
+ void encode_helper(unsigned char output[OUTPUT_SIZE], const unsigned char input[INPUT_SIZE]);
+
+ atsc_basic_trellis_encoder enc[NCODERS];
+
+ public:
+ atsc_trellis_encoder_impl();
+ ~atsc_trellis_encoder_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_ATSC_TRELLIS_ENCODER_IMPL_H */
+