summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-dtv/grc/dtv_atsc_deinterleaver.block.yml4
-rw-r--r--gr-dtv/grc/dtv_atsc_depad.block.yml2
-rw-r--r--gr-dtv/grc/dtv_atsc_derandomizer.block.yml4
-rw-r--r--gr-dtv/grc/dtv_atsc_equalizer.block.yml8
-rw-r--r--gr-dtv/grc/dtv_atsc_fs_checker.block.yml8
-rw-r--r--gr-dtv/grc/dtv_atsc_rs_decoder.block.yml4
-rw-r--r--gr-dtv/grc/dtv_atsc_sync.block.yml4
-rw-r--r--gr-dtv/grc/dtv_atsc_viterbi_decoder.block.yml6
-rw-r--r--gr-dtv/include/gnuradio/dtv/CMakeLists.txt1
-rw-r--r--gr-dtv/include/gnuradio/dtv/atsc_plinfo.h119
-rw-r--r--gr-dtv/lib/CMakeLists.txt1
-rw-r--r--gr-dtv/lib/atsc/atsc_deinterleaver_impl.cc41
-rw-r--r--gr-dtv/lib/atsc/atsc_depad_impl.cc17
-rw-r--r--gr-dtv/lib/atsc/atsc_derandomizer_impl.cc31
-rw-r--r--gr-dtv/lib/atsc/atsc_equalizer_impl.cc61
-rw-r--r--gr-dtv/lib/atsc/atsc_field_sync_mux_impl.cc3
-rw-r--r--gr-dtv/lib/atsc/atsc_fpll_impl.cc5
-rw-r--r--gr-dtv/lib/atsc/atsc_fs_checker_impl.cc31
-rw-r--r--gr-dtv/lib/atsc/atsc_fs_checker_impl.h3
-rw-r--r--gr-dtv/lib/atsc/atsc_interleaver_impl.cc1
-rw-r--r--gr-dtv/lib/atsc/atsc_plinfo.cc109
-rw-r--r--gr-dtv/lib/atsc/atsc_randomize.cc7
-rw-r--r--gr-dtv/lib/atsc/atsc_randomize.h3
-rw-r--r--gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc62
-rw-r--r--gr-dtv/lib/atsc/atsc_rs_decoder_impl.h4
-rw-r--r--gr-dtv/lib/atsc/atsc_sync_impl.cc15
-rw-r--r--gr-dtv/lib/atsc/atsc_trellis_encoder_impl.cc2
-rw-r--r--gr-dtv/lib/atsc/atsc_types.h155
-rw-r--r--gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc40
29 files changed, 464 insertions, 287 deletions
diff --git a/gr-dtv/grc/dtv_atsc_deinterleaver.block.yml b/gr-dtv/grc/dtv_atsc_deinterleaver.block.yml
index fd838138b4..7628bc8bc2 100644
--- a/gr-dtv/grc/dtv_atsc_deinterleaver.block.yml
+++ b/gr-dtv/grc/dtv_atsc_deinterleaver.block.yml
@@ -5,12 +5,12 @@ flags: [ python, cpp ]
inputs:
- domain: stream
dtype: byte
- vlen: 256
+ vlen: 207
outputs:
- domain: stream
dtype: byte
- vlen: 256
+ vlen: 207
templates:
imports: from gnuradio import dtv
diff --git a/gr-dtv/grc/dtv_atsc_depad.block.yml b/gr-dtv/grc/dtv_atsc_depad.block.yml
index b44773ea13..65ae1722f6 100644
--- a/gr-dtv/grc/dtv_atsc_depad.block.yml
+++ b/gr-dtv/grc/dtv_atsc_depad.block.yml
@@ -5,7 +5,7 @@ flags: [ python, cpp ]
inputs:
- domain: stream
dtype: byte
- vlen: 256
+ vlen: 188
outputs:
- domain: stream
diff --git a/gr-dtv/grc/dtv_atsc_derandomizer.block.yml b/gr-dtv/grc/dtv_atsc_derandomizer.block.yml
index cf6f747030..3329965030 100644
--- a/gr-dtv/grc/dtv_atsc_derandomizer.block.yml
+++ b/gr-dtv/grc/dtv_atsc_derandomizer.block.yml
@@ -5,12 +5,12 @@ flags: [ python, cpp ]
inputs:
- domain: stream
dtype: byte
- vlen: 256
+ vlen: 188
outputs:
- domain: stream
dtype: byte
- vlen: 256
+ vlen: 188
templates:
imports: from gnuradio import dtv
diff --git a/gr-dtv/grc/dtv_atsc_equalizer.block.yml b/gr-dtv/grc/dtv_atsc_equalizer.block.yml
index dfc0d9c5d5..3d55d85af7 100644
--- a/gr-dtv/grc/dtv_atsc_equalizer.block.yml
+++ b/gr-dtv/grc/dtv_atsc_equalizer.block.yml
@@ -4,13 +4,13 @@ flags: [ python, cpp ]
inputs:
- domain: stream
- dtype: byte
- vlen: 4096
+ dtype: float
+ vlen: 832
outputs:
- domain: stream
- dtype: byte
- vlen: 4096
+ dtype: float
+ vlen: 832
templates:
imports: from gnuradio import dtv
diff --git a/gr-dtv/grc/dtv_atsc_fs_checker.block.yml b/gr-dtv/grc/dtv_atsc_fs_checker.block.yml
index 31053440ac..098a440382 100644
--- a/gr-dtv/grc/dtv_atsc_fs_checker.block.yml
+++ b/gr-dtv/grc/dtv_atsc_fs_checker.block.yml
@@ -4,13 +4,13 @@ flags: [ python, cpp ]
inputs:
- domain: stream
- dtype: byte
- vlen: 4096
+ dtype: float
+ vlen: 832
outputs:
- domain: stream
- dtype: byte
- vlen: 4096
+ dtype: float
+ vlen: 832
templates:
imports: from gnuradio import dtv
diff --git a/gr-dtv/grc/dtv_atsc_rs_decoder.block.yml b/gr-dtv/grc/dtv_atsc_rs_decoder.block.yml
index e04c91ec3b..08bb639339 100644
--- a/gr-dtv/grc/dtv_atsc_rs_decoder.block.yml
+++ b/gr-dtv/grc/dtv_atsc_rs_decoder.block.yml
@@ -5,12 +5,12 @@ flags: [ python, cpp ]
inputs:
- domain: stream
dtype: byte
- vlen: 256
+ vlen: 207
outputs:
- domain: stream
dtype: byte
- vlen: 256
+ vlen: 188
templates:
imports: from gnuradio import dtv
diff --git a/gr-dtv/grc/dtv_atsc_sync.block.yml b/gr-dtv/grc/dtv_atsc_sync.block.yml
index d1dfdf43d5..02cfc83ab9 100644
--- a/gr-dtv/grc/dtv_atsc_sync.block.yml
+++ b/gr-dtv/grc/dtv_atsc_sync.block.yml
@@ -13,8 +13,8 @@ inputs:
outputs:
- domain: stream
- dtype: byte
- vlen: 4096
+ dtype: float
+ vlen: 832
templates:
imports: from gnuradio import dtv
diff --git a/gr-dtv/grc/dtv_atsc_viterbi_decoder.block.yml b/gr-dtv/grc/dtv_atsc_viterbi_decoder.block.yml
index 0649dcd2ad..199560c925 100644
--- a/gr-dtv/grc/dtv_atsc_viterbi_decoder.block.yml
+++ b/gr-dtv/grc/dtv_atsc_viterbi_decoder.block.yml
@@ -4,13 +4,13 @@ flags: [ python, cpp ]
inputs:
- domain: stream
- dtype: byte
- vlen: 4096
+ dtype: float
+ vlen: 832
outputs:
- domain: stream
dtype: byte
- vlen: 256
+ vlen: 207
templates:
imports: from gnuradio import dtv
diff --git a/gr-dtv/include/gnuradio/dtv/CMakeLists.txt b/gr-dtv/include/gnuradio/dtv/CMakeLists.txt
index cc7ebf4690..9d328f9733 100644
--- a/gr-dtv/include/gnuradio/dtv/CMakeLists.txt
+++ b/gr-dtv/include/gnuradio/dtv/CMakeLists.txt
@@ -11,6 +11,7 @@
install(FILES
api.h
atsc_consts.h
+ atsc_plinfo.h
atsc_deinterleaver.h
atsc_depad.h
atsc_derandomizer.h
diff --git a/gr-dtv/include/gnuradio/dtv/atsc_plinfo.h b/gr-dtv/include/gnuradio/dtv/atsc_plinfo.h
new file mode 100644
index 0000000000..4496ca8092
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/atsc_plinfo.h
@@ -0,0 +1,119 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2001,2006,2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef DTV_INCLUDED_ATSC_PLINFO_H
+#define DTV_INCLUDED_ATSC_PLINFO_H
+
+#include <gnuradio/dtv/atsc_consts.h>
+#include <boost/endian/conversion.hpp>
+#include <cassert>
+#include <cstring>
+
+#include <gnuradio/dtv/api.h>
+
+namespace gr {
+namespace dtv {
+
+/*!
+ * \brief pipeline info that flows with data
+ *
+ * Not all modules need all the info
+ */
+class DTV_API plinfo
+{
+public:
+ plinfo();
+ plinfo(uint16_t flags, int16_t segno);
+
+ /**
+ * @brief Resets the flags and segno fields
+ *
+ */
+ void reset();
+
+ /**
+ * @brief Load the flags and segno from an endian safe value that came over the tags
+ *
+ * @param tag_value
+ */
+ void from_tag_value(uint32_t tag_value);
+
+ /**
+ * @brief Return an endian safe value containing the flags and segno
+ *
+ * @return uint32_t
+ */
+ uint32_t get_tag_value() const;
+
+ // accessors
+ bool field_sync1_p() const;
+ bool field_sync2_p() const;
+ bool field_sync_p() const;
+
+ bool regular_seg_p() const;
+
+ bool in_field1_p() const;
+ bool in_field2_p() const;
+
+ bool first_regular_seg_p() const;
+
+ bool transport_error_p() const;
+
+ unsigned int segno() const;
+ unsigned int flags() const;
+
+ // setters
+
+ void set_field_sync1();
+
+ void set_field_sync2();
+
+ void set_regular_seg(bool field2, int segno);
+
+ void set_transport_error(bool error);
+
+ /*!
+ * Set \p OUT such that it reflects a \p NSEGS_OF_DELAY
+ * pipeline delay from \p IN.
+ */
+ static void delay(plinfo& out, const plinfo& in, int nsegs_of_delay);
+
+ // these three are mutually exclusive
+ // This is a regular data segment.
+ static constexpr int fl_regular_seg = 0x0001;
+ // This is a field sync segment, for 1st half of a field.
+ static constexpr int fl_field_sync1 = 0x0002;
+ // This is a field sync segment, for 2nd half of a field.
+ static constexpr int fl_field_sync2 = 0x0004;
+
+ // This bit is on ONLY when fl_regular_seg is set AND when this is
+ // the first regular data segment AFTER a field sync segment. This
+ // segment causes various processing modules to reset.
+ static constexpr int fl_first_regular_seg = 0x0008;
+
+ // which field are we in?
+ static constexpr int fl_field2 = 0x0010; // else field 1
+
+ // This bit is set when Reed-Solomon decoding detects an error that it
+ // can't correct. Note that other error detection (e.g. Viterbi) do not
+ // set it, since Reed-Solomon will correct many of those. This bit is
+ // then copied into the final Transport Stream packet so that MPEG
+ // software can see that the 188-byte data segment has been corrupted.
+ static constexpr int fl_transport_error = 0x0020;
+
+private:
+ uint16_t d_flags = 0; // bitmask
+ int16_t d_segno = 0; // segment number [-1,311] -1 is the field sync segment
+};
+
+} /* namespace dtv */
+} /* namespace gr */
+
+#endif /* _ATSC_PLINFO_H_ */
diff --git a/gr-dtv/lib/CMakeLists.txt b/gr-dtv/lib/CMakeLists.txt
index 7f26570e3a..18ca5539f4 100644
--- a/gr-dtv/lib/CMakeLists.txt
+++ b/gr-dtv/lib/CMakeLists.txt
@@ -9,6 +9,7 @@
# Setup library
########################################################################
add_library(gnuradio-dtv
+ atsc/atsc_plinfo.cc
atsc/atsc_deinterleaver_impl.cc
atsc/atsc_depad_impl.cc
atsc/atsc_derandomizer_impl.cc
diff --git a/gr-dtv/lib/atsc/atsc_deinterleaver_impl.cc b/gr-dtv/lib/atsc/atsc_deinterleaver_impl.cc
index 616a4c2688..d83d0a625f 100644
--- a/gr-dtv/lib/atsc/atsc_deinterleaver_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_deinterleaver_impl.cc
@@ -25,9 +25,10 @@ atsc_deinterleaver::sptr atsc_deinterleaver::make()
}
atsc_deinterleaver_impl::atsc_deinterleaver_impl()
- : gr::sync_block("atsc_deinterleaver",
- io_signature::make(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)),
- io_signature::make(1, 1, sizeof(atsc_mpeg_packet_rs_encoded))),
+ : gr::sync_block(
+ "atsc_deinterleaver",
+ io_signature::make(1, 1, ATSC_MPEG_RS_ENCODED_LENGTH * sizeof(uint8_t)),
+ io_signature::make(1, 1, ATSC_MPEG_RS_ENCODED_LENGTH * sizeof(uint8_t))),
alignment_fifo(156)
{
m_fifo.reserve(s_interleavers);
@@ -36,6 +37,8 @@ atsc_deinterleaver_impl::atsc_deinterleaver_impl()
m_fifo.emplace_back((s_interleavers - 1 - i) * 4);
sync();
+
+ set_tag_propagation_policy(TPP_CUSTOM);
}
atsc_deinterleaver_impl::~atsc_deinterleaver_impl() {}
@@ -52,24 +55,38 @@ int atsc_deinterleaver_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];
+ auto in = static_cast<const uint8_t*>(input_items[0]);
+ auto out = static_cast<uint8_t*>(output_items[0]);
+ std::vector<tag_t> tags;
+ auto tag_pmt = pmt::intern("plinfo");
for (int i = 0; i < noutput_items; i++) {
- assert(in[i].pli.regular_seg_p());
- plinfo::sanity_check(in[i].pli);
+ plinfo pli_in;
+ get_tags_in_window(tags, 0, i, i + 1, tag_pmt);
+ if (tags.size() > 0) {
+ pli_in.from_tag_value(pmt::to_uint64(tags[0].value));
+ } else {
+ throw std::runtime_error(
+ "Atsc Deinterleaver: Plinfo Tag not found on sample");
+ }
+
+ assert(pli_in.regular_seg_p());
// reset commutator if required using INPUT pipeline info
- if (in[i].pli.first_regular_seg_p())
+ if (pli_in.first_regular_seg_p())
sync();
// remap OUTPUT pipeline info to reflect all data segment end-to-end delay
- plinfo::delay(out[i].pli, in[i].pli, s_interleavers);
+ plinfo pli_out;
+ plinfo::delay(pli_out, pli_in, s_interleavers);
+
+ add_item_tag(
+ 0, nitems_written(0) + i, tag_pmt, pmt::from_uint64(pli_out.get_tag_value()));
// now do the actual deinterleaving
- for (unsigned int j = 0; j < sizeof(in[i].data); j++) {
- out[i].data[j] = alignment_fifo.stuff(transform(in[i].data[j]));
+ for (unsigned int j = 0; j < ATSC_MPEG_RS_ENCODED_LENGTH; j++) {
+ out[i * ATSC_MPEG_RS_ENCODED_LENGTH + j] =
+ alignment_fifo.stuff(transform(in[i * ATSC_MPEG_RS_ENCODED_LENGTH + j]));
}
}
diff --git a/gr-dtv/lib/atsc/atsc_depad_impl.cc b/gr-dtv/lib/atsc/atsc_depad_impl.cc
index a6d87a7362..246264fc6c 100644
--- a/gr-dtv/lib/atsc/atsc_depad_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_depad_impl.cc
@@ -25,10 +25,11 @@ atsc_depad::sptr atsc_depad::make()
}
atsc_depad_impl::atsc_depad_impl()
- : gr::sync_interpolator("atsc_depad",
- io_signature::make(1, 1, sizeof(atsc_mpeg_packet)),
- io_signature::make(1, 1, sizeof(unsigned char)),
- ATSC_MPEG_PKT_LENGTH)
+ : gr::sync_interpolator(
+ "atsc_depad",
+ io_signature::make(1, 1, ATSC_MPEG_PKT_LENGTH * sizeof(uint8_t)),
+ io_signature::make(1, 1, sizeof(uint8_t)),
+ ATSC_MPEG_PKT_LENGTH)
{
}
@@ -36,13 +37,15 @@ int atsc_depad_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];
- unsigned char* out = (unsigned char*)output_items[0];
+ auto in = static_cast<const uint8_t*>(input_items[0]);
+ auto out = static_cast<uint8_t*>(output_items[0]);
int i;
for (i = 0; i < noutput_items / ATSC_MPEG_PKT_LENGTH; i++)
- memcpy(&out[i * ATSC_MPEG_PKT_LENGTH], in[i].data, ATSC_MPEG_PKT_LENGTH);
+ memcpy(&out[i * ATSC_MPEG_PKT_LENGTH],
+ &in[i * ATSC_MPEG_PKT_LENGTH],
+ ATSC_MPEG_PKT_LENGTH);
return i * ATSC_MPEG_PKT_LENGTH;
}
diff --git a/gr-dtv/lib/atsc/atsc_derandomizer_impl.cc b/gr-dtv/lib/atsc/atsc_derandomizer_impl.cc
index 2b102838f0..33dcf47600 100644
--- a/gr-dtv/lib/atsc/atsc_derandomizer_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_derandomizer_impl.cc
@@ -26,35 +26,44 @@ atsc_derandomizer::sptr atsc_derandomizer::make()
atsc_derandomizer_impl::atsc_derandomizer_impl()
: gr::sync_block("dtv_atsc_derandomizer",
- io_signature::make(1, 1, sizeof(atsc_mpeg_packet_no_sync)),
- io_signature::make(1, 1, sizeof(atsc_mpeg_packet)))
+ io_signature::make(1, 1, ATSC_MPEG_PKT_LENGTH * sizeof(uint8_t)),
+ io_signature::make(1, 1, ATSC_MPEG_PKT_LENGTH * sizeof(uint8_t)))
{
d_rand.reset();
+ set_tag_propagation_policy(TPP_DONT);
}
int atsc_derandomizer_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* out = (atsc_mpeg_packet*)output_items[0];
+ auto in = static_cast<const uint8_t*>(input_items[0]);
+ auto out = static_cast<uint8_t*>(output_items[0]);
+ std::vector<tag_t> tags;
+ auto tag_pmt = pmt::intern("plinfo");
for (int i = 0; i < noutput_items; i++) {
+ plinfo pli_in;
+ get_tags_in_window(tags, 0, i, i + 1, tag_pmt);
+ if (tags.size() > 0) {
+ pli_in.from_tag_value(pmt::to_uint64(tags[0].value));
+ } else {
+ throw std::runtime_error("Atsc Derandomizer: Plinfo Tag not found on sample");
+ }
+ assert(pli_in.regular_seg_p());
- assert(in[i].pli.regular_seg_p());
-
- if (in[i].pli.first_regular_seg_p())
+ if (pli_in.first_regular_seg_p())
d_rand.reset();
- d_rand.derandomize(out[i], in[i]);
+ d_rand.derandomize(&out[i * ATSC_MPEG_PKT_LENGTH], &in[i * ATSC_MPEG_PKT_LENGTH]);
// Check the pipeline info for error status and and set the
// corresponding bit in transport packet header.
- if (in[i].pli.transport_error_p())
- out[i].data[1] |= MPEG_TRANSPORT_ERROR_BIT;
+ if (pli_in.transport_error_p())
+ out[i * ATSC_MPEG_PKT_LENGTH + 1] |= MPEG_TRANSPORT_ERROR_BIT;
else
- out[i].data[1] &= ~MPEG_TRANSPORT_ERROR_BIT;
+ out[i * ATSC_MPEG_PKT_LENGTH + 1] &= ~MPEG_TRANSPORT_ERROR_BIT;
}
return noutput_items;
diff --git a/gr-dtv/lib/atsc/atsc_equalizer_impl.cc b/gr-dtv/lib/atsc/atsc_equalizer_impl.cc
index 6c701d607b..5970fb5d63 100644
--- a/gr-dtv/lib/atsc/atsc_equalizer_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_equalizer_impl.cc
@@ -52,8 +52,8 @@ static void init_field_sync_common(float* p, int mask)
atsc_equalizer_impl::atsc_equalizer_impl()
: gr::block("dtv_atsc_equalizer",
- io_signature::make(1, 1, sizeof(atsc_soft_data_segment)),
- io_signature::make(1, 1, sizeof(atsc_soft_data_segment)))
+ io_signature::make(1, 1, ATSC_DATA_SEGMENT_LENGTH * sizeof(float)),
+ io_signature::make(1, 1, ATSC_DATA_SEGMENT_LENGTH * sizeof(float)))
{
init_field_sync_common(training_sequence1, 0);
init_field_sync_common(training_sequence2, 1);
@@ -64,6 +64,8 @@ atsc_equalizer_impl::atsc_equalizer_impl()
const int alignment_multiple = volk_get_alignment() / sizeof(float);
set_alignment(std::max(1, alignment_multiple));
+
+ set_tag_propagation_policy(TPP_CUSTOM); // use manual tag propagation
}
atsc_equalizer_impl::~atsc_equalizer_impl() {}
@@ -114,17 +116,30 @@ int atsc_equalizer_impl::general_work(int noutput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items)
{
- const atsc_soft_data_segment* in = (const atsc_soft_data_segment*)input_items[0];
- atsc_soft_data_segment* out = (atsc_soft_data_segment*)output_items[0];
+ auto in = static_cast<const float*>(input_items[0]);
+ auto out = static_cast<float*>(output_items[0]);
int output_produced = 0;
int i = 0;
+ std::vector<tag_t> tags;
+ auto tag_pmt = pmt::intern("plinfo");
+
+ plinfo pli_in;
if (d_buff_not_filled) {
memset(&data_mem[0], 0, NPRETAPS * sizeof(float));
- memcpy(&data_mem[NPRETAPS], in[i].data, ATSC_DATA_SEGMENT_LENGTH * sizeof(float));
- d_flags = in[i].pli._flags;
- d_segno = in[i].pli._segno;
+ memcpy(&data_mem[NPRETAPS],
+ in + i * ATSC_DATA_SEGMENT_LENGTH,
+ ATSC_DATA_SEGMENT_LENGTH * sizeof(float));
+ get_tags_in_window(tags, 0, 0, 1, tag_pmt);
+ if (tags.size() > 0) {
+ pli_in.from_tag_value(pmt::to_uint64(tags[0].value));
+ d_flags = pli_in.flags();
+ d_segno = pli_in.segno();
+ } else {
+ throw std::runtime_error("Atsc Equalizer: Plinfo Tag not found on sample");
+ }
+
d_buff_not_filled = false;
i++;
}
@@ -132,36 +147,44 @@ int atsc_equalizer_impl::general_work(int noutput_items,
for (; i < noutput_items; i++) {
memcpy(&data_mem[ATSC_DATA_SEGMENT_LENGTH + NPRETAPS],
- in[i].data,
+ in + i * ATSC_DATA_SEGMENT_LENGTH,
(NTAPS - NPRETAPS) * sizeof(float));
if (d_segno == -1) {
if (d_flags & 0x0010) {
adaptN(data_mem, training_sequence2, data_mem2, KNOWN_FIELD_SYNC_LENGTH);
- // filterN(&data_mem[KNOWN_FIELD_SYNC_LENGTH], data_mem2,
- // ATSC_DATA_SEGMENT_LENGTH - KNOWN_FIELD_SYNC_LENGTH);
} else if (!(d_flags & 0x0010)) {
adaptN(data_mem, training_sequence1, data_mem2, KNOWN_FIELD_SYNC_LENGTH);
- // filterN(&data_mem[KNOWN_FIELD_SYNC_LENGTH], data_mem2,
- // ATSC_DATA_SEGMENT_LENGTH - KNOWN_FIELD_SYNC_LENGTH);
}
} else {
filterN(data_mem, data_mem2, ATSC_DATA_SEGMENT_LENGTH);
- memcpy(out[output_produced].data,
+ memcpy(&out[output_produced * ATSC_DATA_SEGMENT_LENGTH],
data_mem2,
ATSC_DATA_SEGMENT_LENGTH * sizeof(float));
- out[output_produced].pli._flags = d_flags;
- out[output_produced].pli._segno = d_segno;
+ plinfo pli_out(d_flags, d_segno);
+ add_item_tag(0,
+ nitems_written(0) + output_produced,
+ tag_pmt,
+ pmt::from_uint64(pli_out.get_tag_value()));
+
output_produced++;
}
memcpy(data_mem, &data_mem[ATSC_DATA_SEGMENT_LENGTH], NPRETAPS * sizeof(float));
- memcpy(&data_mem[NPRETAPS], in[i].data, ATSC_DATA_SEGMENT_LENGTH * sizeof(float));
-
- d_flags = in[i].pli._flags;
- d_segno = in[i].pli._segno;
+ memcpy(&data_mem[NPRETAPS],
+ in + i * ATSC_DATA_SEGMENT_LENGTH,
+ ATSC_DATA_SEGMENT_LENGTH * sizeof(float));
+
+ get_tags_in_window(tags, 0, i, i + 1, tag_pmt);
+ if (tags.size() > 0) {
+ pli_in.from_tag_value(pmt::to_uint64(tags[0].value));
+ d_flags = pli_in.flags();
+ d_segno = pli_in.segno();
+ } else {
+ throw std::runtime_error("Atsc Equalizer: Plinfo Tag not found on sample");
+ }
}
consume_each(noutput_items);
diff --git a/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.cc b/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.cc
index 0e778a983d..3e505eac9a 100644
--- a/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_field_sync_mux_impl.cc
@@ -164,8 +164,7 @@ int atsc_field_sync_mux_impl::general_work(int noutput_items,
// write out field sync...
atsc_data_segment field_sync;
- field_sync.pli._flags = 0;
- field_sync.pli._segno = 0;
+ field_sync.pli.reset();
memset(field_sync._pad_, 0, atsc_data_segment::NPAD);
if (in[index].pli.in_field1_p()) {
diff --git a/gr-dtv/lib/atsc/atsc_fpll_impl.cc b/gr-dtv/lib/atsc/atsc_fpll_impl.cc
index 0904d1aad0..0a133eb429 100644
--- a/gr-dtv/lib/atsc/atsc_fpll_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_fpll_impl.cc
@@ -44,8 +44,9 @@ int atsc_fpll_impl::work(int noutput_items,
constexpr float alpha = 0.01;
constexpr float beta = alpha * alpha / 4.0;
- const gr_complex* in = (const gr_complex*)input_items[0];
- float* out = (float*)output_items[0];
+ auto in = static_cast<const gr_complex*>(input_items[0]);
+ auto out = static_cast<float*>(output_items[0]);
+
float a_cos, a_sin;
float x;
gr_complex result, filtered;
diff --git a/gr-dtv/lib/atsc/atsc_fs_checker_impl.cc b/gr-dtv/lib/atsc/atsc_fs_checker_impl.cc
index dd76277be9..cf00be36ee 100644
--- a/gr-dtv/lib/atsc/atsc_fs_checker_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_fs_checker_impl.cc
@@ -35,8 +35,8 @@ atsc_fs_checker::sptr atsc_fs_checker::make()
atsc_fs_checker_impl::atsc_fs_checker_impl()
: gr::block("dtv_atsc_fs_checker",
- io_signature::make(1, 1, sizeof(atsc_soft_data_segment)),
- io_signature::make(1, 1, sizeof(atsc_soft_data_segment)))
+ io_signature::make(1, 1, ATSC_DATA_SEGMENT_LENGTH * sizeof(float)),
+ io_signature::make(1, 1, ATSC_DATA_SEGMENT_LENGTH * sizeof(float)))
{
gr::configure_default_loggers(d_logger, d_debug_logger, "dtv_atsc_fs_checker");
reset();
@@ -59,17 +59,20 @@ int atsc_fs_checker_impl::general_work(int noutput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items)
{
- const atsc_soft_data_segment* in = (const atsc_soft_data_segment*)input_items[0];
- atsc_soft_data_segment* out = (atsc_soft_data_segment*)output_items[0];
+ const float* in = static_cast<const float*>(input_items[0]);
+ float* out = static_cast<float*>(output_items[0]);
int output_produced = 0;
+ auto tag_pmt = pmt::intern("plinfo");
+
for (int i = 0; i < noutput_items; i++) {
// check for a hit on the PN 511 pattern
int errors = 0;
for (int j = 0; j < LENGTH_511 && errors < PN511_ERROR_LIMIT; j++)
- errors += (in[i].data[j + OFFSET_511] >= 0) ^ atsc_pn511[j];
+ errors +=
+ (in[i * ATSC_DATA_SEGMENT_LENGTH + j + OFFSET_511] >= 0) ^ atsc_pn511[j];
GR_LOG_DEBUG(d_debug_logger,
std::string("second PN63 error count = ") + std::to_string(errors));
@@ -78,7 +81,8 @@ int atsc_fs_checker_impl::general_work(int noutput_items,
// determine if this is field 1 or field 2
errors = 0;
for (int j = 0; j < LENGTH_2ND_63; j++)
- errors += (in[i].data[j + OFFSET_2ND_63] >= 0) ^ atsc_pn63[j];
+ errors += (in[i * ATSC_DATA_SEGMENT_LENGTH + j + OFFSET_2ND_63] >= 0) ^
+ atsc_pn63[j];
// we should have either field 1 (== PN63) or field 2 (== ~PN63)
if (errors <= PN63_ERROR_LIMIT) {
@@ -98,14 +102,23 @@ int atsc_fs_checker_impl::general_work(int noutput_items,
if (d_field_num == 1 || d_field_num == 2) { // If we have sync
// So we copy out current packet data to an output packet and fill its plinfo
- for (int j = 0; j < ATSC_DATA_SEGMENT_LENGTH; j++)
- out[output_produced].data[j] = in[i].data[j];
- out[output_produced].pli.set_regular_seg((d_field_num == 2), d_segment_num);
+ memcpy(&out[output_produced * ATSC_DATA_SEGMENT_LENGTH],
+ &in[i * ATSC_DATA_SEGMENT_LENGTH],
+ ATSC_DATA_SEGMENT_LENGTH * sizeof(float));
+
+ plinfo pli_out;
+ pli_out.set_regular_seg((d_field_num == 2), d_segment_num);
+
d_segment_num++;
if (d_segment_num > (ATSC_SEGMENTS_PER_DATA_FIELD - 1)) {
d_field_num = 0;
d_segment_num = 0;
} else {
+ add_item_tag(0,
+ nitems_written(0) + output_produced,
+ tag_pmt,
+ pmt::from_uint64(pli_out.get_tag_value()));
+
output_produced++;
}
}
diff --git a/gr-dtv/lib/atsc/atsc_fs_checker_impl.h b/gr-dtv/lib/atsc/atsc_fs_checker_impl.h
index 603b3d02e4..e0727273a4 100644
--- a/gr-dtv/lib/atsc/atsc_fs_checker_impl.h
+++ b/gr-dtv/lib/atsc/atsc_fs_checker_impl.h
@@ -13,7 +13,6 @@
#include "atsc_syminfo_impl.h"
#include <gnuradio/dtv/atsc_fs_checker.h>
-#include <gnuradio/logger.h>
namespace gr {
namespace dtv {
@@ -28,8 +27,6 @@ private:
unsigned char d_bit_sr[SRSIZE]; // binary decision shift register
int d_field_num;
int d_segment_num;
- gr::logger_ptr d_logger;
- gr::logger_ptr d_debug_logger;
static constexpr int OFFSET_511 = 4; // offset to second PN 63 pattern
static constexpr int LENGTH_511 = 511; // length of PN 63 pattern
diff --git a/gr-dtv/lib/atsc/atsc_interleaver_impl.cc b/gr-dtv/lib/atsc/atsc_interleaver_impl.cc
index 07b748029a..51a9e7ab3e 100644
--- a/gr-dtv/lib/atsc/atsc_interleaver_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_interleaver_impl.cc
@@ -64,7 +64,6 @@ int atsc_interleaver_impl::work(int noutput_items,
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
diff --git a/gr-dtv/lib/atsc/atsc_plinfo.cc b/gr-dtv/lib/atsc/atsc_plinfo.cc
new file mode 100644
index 0000000000..3f14b0c782
--- /dev/null
+++ b/gr-dtv/lib/atsc/atsc_plinfo.cc
@@ -0,0 +1,109 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2001,2006,2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include <gnuradio/dtv/atsc_plinfo.h>
+
+namespace gr {
+namespace dtv {
+
+plinfo::plinfo() : d_flags(0), d_segno(0){};
+plinfo::plinfo(uint16_t flags, int16_t segno) : d_flags(flags), d_segno(segno){};
+
+void plinfo::reset()
+{
+ d_flags = 0;
+ d_segno = 0;
+}
+
+void plinfo::from_tag_value(uint32_t tag_value)
+{
+ auto native_val = boost::endian::big_to_native(tag_value);
+ d_flags = (native_val >> 16) & 0xFFFF;
+ d_segno = native_val & 0xFFFF;
+}
+
+uint32_t plinfo::get_tag_value() const
+{
+ return boost::endian::native_to_big(((d_flags & 0xFFFF) << 16) | (d_segno & 0xFFFF));
+}
+
+// accessors
+bool plinfo::field_sync1_p() const { return (d_flags & fl_field_sync1) != 0; }
+bool plinfo::field_sync2_p() const { return (d_flags & fl_field_sync2) != 0; }
+bool plinfo::field_sync_p() const { return field_sync1_p() || field_sync2_p(); }
+
+bool plinfo::regular_seg_p() const { return (d_flags & fl_regular_seg) != 0; }
+
+bool plinfo::in_field1_p() const { return (d_flags & fl_field2) == 0; }
+bool plinfo::in_field2_p() const { return (d_flags & fl_field2) != 0; }
+
+bool plinfo::first_regular_seg_p() const { return (d_flags & fl_first_regular_seg) != 0; }
+
+bool plinfo::transport_error_p() const { return (d_flags & fl_transport_error) != 0; }
+
+unsigned int plinfo::segno() const { return d_segno; }
+unsigned int plinfo::flags() const { return d_flags; }
+
+// setters
+
+void plinfo::set_field_sync1()
+{
+ d_segno = 0;
+ d_flags = fl_field_sync1;
+}
+
+void plinfo::set_field_sync2()
+{
+ d_segno = 0;
+ d_flags = fl_field_sync2 | fl_field2;
+}
+
+void plinfo::set_regular_seg(bool field2, int segno)
+{
+ d_segno = segno;
+ d_flags = fl_regular_seg;
+ if (segno == 0)
+ d_flags |= fl_first_regular_seg;
+ if (segno >= ATSC_DSEGS_PER_FIELD)
+ d_flags |= fl_transport_error;
+ if (field2)
+ d_flags |= fl_field2;
+}
+
+void plinfo::set_transport_error(bool error)
+{
+ if (error)
+ d_flags |= fl_transport_error;
+ else
+ d_flags &= ~fl_transport_error;
+}
+
+void plinfo::delay(plinfo& out, const plinfo& in, int nsegs_of_delay)
+{
+ assert(in.regular_seg_p());
+ assert(nsegs_of_delay >= 0);
+
+ int s = in.segno();
+ if (in.in_field2_p())
+ s += ATSC_DSEGS_PER_FIELD;
+
+ s -= nsegs_of_delay;
+ if (s < 0)
+ s += 2 * ATSC_DSEGS_PER_FIELD;
+
+ if (s < ATSC_DSEGS_PER_FIELD)
+ out.set_regular_seg(false, s); // field 1
+ else
+ out.set_regular_seg(true, s - ATSC_DSEGS_PER_FIELD); // field 2
+}
+
+
+} /* namespace dtv */
+} /* namespace gr */
diff --git a/gr-dtv/lib/atsc/atsc_randomize.cc b/gr-dtv/lib/atsc/atsc_randomize.cc
index d148dcd748..a4e0e611b5 100644
--- a/gr-dtv/lib/atsc/atsc_randomize.cc
+++ b/gr-dtv/lib/atsc/atsc_randomize.cc
@@ -53,13 +53,12 @@ void atsc_randomize::randomize(atsc_mpeg_packet_no_sync& out, const atsc_mpeg_pa
out.data[i] = in.data[i + 1] ^ output_and_clk();
}
-void atsc_randomize::derandomize(atsc_mpeg_packet& out,
- const atsc_mpeg_packet_no_sync& in)
+void atsc_randomize::derandomize(uint8_t* out, const uint8_t* in)
{
- out.data[0] = MPEG_SYNC_BYTE; // add sync byte to beginning of packet
+ out[0] = MPEG_SYNC_BYTE; // add sync byte to beginning of packet
for (int i = 0; i < ATSC_MPEG_DATA_LENGTH; i++)
- out.data[i + 1] = in.data[i] ^ output_and_clk();
+ out[i + 1] = in[i] ^ output_and_clk();
}
diff --git a/gr-dtv/lib/atsc/atsc_randomize.h b/gr-dtv/lib/atsc/atsc_randomize.h
index e005b8d40f..9d52fbcf10 100644
--- a/gr-dtv/lib/atsc/atsc_randomize.h
+++ b/gr-dtv/lib/atsc/atsc_randomize.h
@@ -12,6 +12,7 @@
#define INCLUDED_ATSC_RANDOMIZE_H
#include "atsc_types.h"
+#include <stdint.h>
namespace gr {
namespace dtv {
@@ -33,7 +34,7 @@ public:
void randomize(atsc_mpeg_packet_no_sync& out, const atsc_mpeg_packet& in);
//! derandomize (de-whiten) mpeg packet and add leading MPEG-2 sync byte
- void derandomize(atsc_mpeg_packet& out, const atsc_mpeg_packet_no_sync& in);
+ void derandomize(uint8_t* out, const uint8_t* in);
unsigned int state() const { return d_state; }
diff --git a/gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc b/gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc
index a22fffe537..4e6afe2753 100644
--- a/gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc
@@ -35,35 +35,38 @@ atsc_rs_decoder::sptr atsc_rs_decoder::make()
}
atsc_rs_decoder_impl::atsc_rs_decoder_impl()
- : gr::sync_block("dtv_atsc_rs_decoder",
- io_signature::make(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)),
- io_signature::make(1, 1, sizeof(atsc_mpeg_packet_no_sync)))
+ : gr::sync_block(
+ "dtv_atsc_rs_decoder",
+ io_signature::make(1, 1, sizeof(uint8_t) * ATSC_MPEG_RS_ENCODED_LENGTH),
+ io_signature::make(1, 1, sizeof(uint8_t) * ATSC_MPEG_PKT_LENGTH))
{
d_rs = init_rs_char(
rs_init_symsize, rs_init_gfpoly, rs_init_fcr, rs_init_prim, rs_init_nroots);
assert(d_rs != 0);
- d_nerrors_corrrected_count = 0;
+ d_nerrors_corrected_count = 0;
d_bad_packet_count = 0;
d_total_packets = 0;
+
+ set_tag_propagation_policy(TPP_CUSTOM);
}
-int atsc_rs_decoder_impl::decode(atsc_mpeg_packet_no_sync& out,
- const atsc_mpeg_packet_rs_encoded& in)
+int atsc_rs_decoder_impl::decode(uint8_t* out, const uint8_t* in)
{
unsigned char tmp[N];
int ncorrections;
- assert((int)(amount_of_pad + sizeof(in.data)) == N);
+ // assert((int)(amount_of_pad + sizeof(in.data)) == N);
+ assert((int)(amount_of_pad + ATSC_MPEG_RS_ENCODED_LENGTH) == N);
// add missing prefix zero padding to message
memset(tmp, 0, amount_of_pad);
- memcpy(&tmp[amount_of_pad], in.data, sizeof(in.data));
+ memcpy(&tmp[amount_of_pad], in, ATSC_MPEG_RS_ENCODED_LENGTH);
// correct message...
ncorrections = decode_rs_char(d_rs, tmp, 0, 0);
// copy corrected message to output, skipping prefix zero padding
- memcpy(out.data, &tmp[amount_of_pad], sizeof(out.data));
+ memcpy(out, &tmp[amount_of_pad], ATSC_MPEG_PKT_LENGTH);
return ncorrections;
}
@@ -77,7 +80,7 @@ atsc_rs_decoder_impl::~atsc_rs_decoder_impl()
int atsc_rs_decoder_impl::num_errors_corrected() const
{
- return d_nerrors_corrrected_count;
+ return d_nerrors_corrected_count;
}
int atsc_rs_decoder_impl::num_bad_packets() const { return d_bad_packet_count; }
@@ -88,29 +91,44 @@ int atsc_rs_decoder_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_no_sync* out = (atsc_mpeg_packet_no_sync*)output_items[0];
+ auto in = static_cast<const uint8_t*>(input_items[0]);
+ auto out = static_cast<uint8_t*>(output_items[0]);
+ std::vector<tag_t> tags;
+ auto tag_pmt = pmt::intern("plinfo");
for (int i = 0; i < noutput_items; i++) {
- assert(in[i].pli.regular_seg_p());
- out[i].pli = in[i].pli; // copy pipeline info...
+ plinfo pli_in;
+ get_tags_in_window(tags, 0, i, i + 1, tag_pmt);
+ if (tags.size() > 0) {
+ pli_in.from_tag_value(pmt::to_uint64(tags[0].value));
+ } else {
+ throw std::runtime_error(
+ "Atsc Viterbi Decoder: Plinfo Tag not found on sample");
+ }
+
+ assert(pli_in.regular_seg_p());
- int nerrors_corrrected = decode(out[i], in[i]);
- out[i].pli.set_transport_error(nerrors_corrrected == -1);
- if (nerrors_corrrected == -1) {
+ plinfo pli_out = pli_in; // copy pipeline info...
+
+
+ int nerrors_corrected =
+ decode(&out[i * ATSC_MPEG_PKT_LENGTH], &in[i * ATSC_MPEG_RS_ENCODED_LENGTH]);
+ pli_out.set_transport_error(nerrors_corrected == -1);
+ if (nerrors_corrected == -1) {
d_bad_packet_count++;
- d_nerrors_corrrected_count +=
- 10; // lower bound estimate; most this RS can fix
+ d_nerrors_corrected_count += 10; // lower bound estimate; most this RS can fix
} else {
- d_nerrors_corrrected_count += nerrors_corrrected;
+ d_nerrors_corrected_count += nerrors_corrected;
}
+ add_item_tag(
+ 0, nitems_written(0) + i, tag_pmt, pmt::from_uint64(pli_out.get_tag_value()));
+
d_total_packets++;
#if 0
if (d_total_packets > 1000) {
GR_LOG_INFO(d_logger, boost::format("Error rate: %1%\tPacket error rate: %2%") \
- % ((float)d_nerrors_corrrected_count/(ATSC_MPEG_DATA_LENGTH*d_total_packets))
+ % ((float)d_nerrors_corrected_count/(ATSC_MPEG_PKT_LENGTH*d_total_packets))
% ((float)d_bad_packet_count/d_total_packets));
}
#endif
diff --git a/gr-dtv/lib/atsc/atsc_rs_decoder_impl.h b/gr-dtv/lib/atsc/atsc_rs_decoder_impl.h
index 71a01ee436..c7b3c5d1c9 100644
--- a/gr-dtv/lib/atsc/atsc_rs_decoder_impl.h
+++ b/gr-dtv/lib/atsc/atsc_rs_decoder_impl.h
@@ -24,7 +24,7 @@ namespace dtv {
class atsc_rs_decoder_impl : public atsc_rs_decoder
{
private:
- int d_nerrors_corrrected_count;
+ int d_nerrors_corrected_count;
int d_bad_packet_count;
int d_total_packets;
void* d_rs;
@@ -43,7 +43,7 @@ public:
* Decode RS encoded packet.
* \returns a count of corrected symbols, or -1 if the block was uncorrectible.
*/
- int decode(atsc_mpeg_packet_no_sync& out, const atsc_mpeg_packet_rs_encoded& in);
+ int decode(uint8_t* out, const uint8_t* in);
int work(int noutput_items,
gr_vector_const_void_star& input_items,
diff --git a/gr-dtv/lib/atsc/atsc_sync_impl.cc b/gr-dtv/lib/atsc/atsc_sync_impl.cc
index 2cff86358c..d21ebe7c39 100644
--- a/gr-dtv/lib/atsc/atsc_sync_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_sync_impl.cc
@@ -34,7 +34,7 @@ atsc_sync::sptr atsc_sync::make(float rate)
atsc_sync_impl::atsc_sync_impl(float rate)
: gr::block("dtv_atsc_sync",
io_signature::make(1, 1, sizeof(float)),
- io_signature::make(1, 1, sizeof(atsc_soft_data_segment))),
+ io_signature::make(1, 1, ATSC_DATA_SEGMENT_LENGTH * sizeof(float))),
d_rx_clock_to_symbol_freq(rate / ATSC_SYMBOL_RATE),
d_si(0)
{
@@ -82,15 +82,15 @@ int atsc_sync_impl::general_work(int noutput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items)
{
- const float* in = (const float*)input_items[0];
- atsc_soft_data_segment* soft_data_segment_out =
- (atsc_soft_data_segment*)output_items[0];
+ const float* in = static_cast<const float*>(input_items[0]);
+ float* out = static_cast<float*>(output_items[0]);
float interp_sample;
// amount actually consumed
d_si = 0;
+
for (d_output_produced = 0; d_output_produced < noutput_items &&
(d_si + (int)d_interp.ntaps()) < ninput_items[0];) {
// First we interpolate a sample from input to work with
@@ -150,8 +150,6 @@ int atsc_sync_impl::general_work(int noutput_items,
// d_sample_mem[best_correlation_index - 1] -
// d_sample_mem[best_correlation_index];
- // printf( "d_timing_adjust = %f\n", d_timing_adjust );
-
int corr_count = best_correlation_index;
d_timing_adjust = -d_sample_mem[corr_count--];
@@ -180,8 +178,9 @@ int atsc_sync_impl::general_work(int noutput_items,
d_data_mem[d_symbol_index] = interp_sample;
if (d_symbol_index >= (ATSC_DATA_SEGMENT_LENGTH - 1)) {
- for (int i = 0; i < ATSC_DATA_SEGMENT_LENGTH; i++)
- soft_data_segment_out[d_output_produced].data[i] = d_data_mem[i];
+ memcpy(&out[d_output_produced * ATSC_DATA_SEGMENT_LENGTH],
+ d_data_mem,
+ ATSC_DATA_SEGMENT_LENGTH * sizeof(float));
d_output_produced++;
}
}
diff --git a/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.cc b/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.cc
index 3cddcba7ae..59c5a0d223 100644
--- a/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_trellis_encoder_impl.cc
@@ -71,7 +71,6 @@ void atsc_trellis_encoder_impl::encode(atsc_data_segment out[NCODERS],
// copy input into contiguous 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]));
@@ -91,7 +90,6 @@ void atsc_trellis_encoder_impl::encode(atsc_data_segment out[NCODERS],
// copy pipeline info
out[i].pli = in[i].pli;
- plinfo::sanity_check(out[i].pli);
assert(out[i].pli.regular_seg_p());
}
}
diff --git a/gr-dtv/lib/atsc/atsc_types.h b/gr-dtv/lib/atsc/atsc_types.h
index 6d48c91174..59ea3bbf59 100644
--- a/gr-dtv/lib/atsc/atsc_types.h
+++ b/gr-dtv/lib/atsc/atsc_types.h
@@ -15,151 +15,11 @@
#include <cassert>
#include <cstring>
+#include <gnuradio/dtv/atsc_plinfo.h>
+
namespace gr {
namespace dtv {
-/*!
- * \brief pipeline info that flows with data
- *
- * Not all modules need all the info
- */
-class plinfo
-{
-public:
- plinfo() : _flags(0), _segno(0) {}
-
- // accessors
-
- bool field_sync1_p() const { return (_flags & fl_field_sync1) != 0; }
- bool field_sync2_p() const { return (_flags & fl_field_sync2) != 0; }
- bool field_sync_p() const { return field_sync1_p() || field_sync2_p(); }
-
- bool regular_seg_p() const { return (_flags & fl_regular_seg) != 0; }
-
- bool in_field1_p() const { return (_flags & fl_field2) == 0; }
- bool in_field2_p() const { return (_flags & fl_field2) != 0; }
-
- bool first_regular_seg_p() const { return (_flags & fl_first_regular_seg) != 0; }
-
- bool transport_error_p() const { return (_flags & fl_transport_error) != 0; }
-
- unsigned int segno() const { return _segno; }
- unsigned int flags() const { return _flags; }
-
- // setters
-
- void set_field_sync1()
- {
- _segno = 0;
- _flags = fl_field_sync1;
- }
-
- void set_field_sync2()
- {
- _segno = 0;
- _flags = fl_field_sync2 | fl_field2;
- }
-
- void set_regular_seg(bool field2, int segno)
- {
- // assert (0 <= segno && segno < ATSC_DSEGS_PER_FIELD);
- _segno = segno;
- _flags = fl_regular_seg;
- if (segno == 0)
- _flags |= fl_first_regular_seg;
- if (segno >= ATSC_DSEGS_PER_FIELD)
- _flags |= fl_transport_error;
- if (field2)
- _flags |= fl_field2;
- }
-
- void set_transport_error(bool error)
- {
- if (error)
- _flags |= fl_transport_error;
- else
- _flags &= ~fl_transport_error;
- }
-
- // overload equality operator
- bool operator==(const plinfo& other) const
- {
- return (_flags == other._flags && _segno == other._segno);
- }
-
- bool operator!=(const plinfo& other) const
- {
- return !(_flags == other._flags && _segno == other._segno);
- }
-
- /*!
- * Set \p OUT such that it reflects a \p NSEGS_OF_DELAY
- * pipeline delay from \p IN.
- */
- static void delay(plinfo& out, const plinfo& in, int nsegs_of_delay)
- {
- assert(in.regular_seg_p());
- assert(nsegs_of_delay >= 0);
-
- int s = in.segno();
- if (in.in_field2_p())
- s += ATSC_DSEGS_PER_FIELD;
-
- s -= nsegs_of_delay;
- if (s < 0)
- s += 2 * ATSC_DSEGS_PER_FIELD;
-
- // assert (0 <= s && s < 2 * ATSC_DSEGS_PER_FIELD);
-
- if (s < ATSC_DSEGS_PER_FIELD)
- out.set_regular_seg(false, s); // field 1
- else
- out.set_regular_seg(true, s - ATSC_DSEGS_PER_FIELD); // field 2
- }
-
- /*!
- * confirm that \p X is plausible
- */
- static void sanity_check(const plinfo& in)
- {
- // basic sanity checks...
- // assert (x.segno () >= 0);
- // assert (x.segno () < (unsigned) ATSC_DSEGS_PER_FIELD);
- // assert ((x.flags () & ~0x3f) == 0);
-
- // assert (x.regular_seg_p () ^ x.field_sync_p ());
- // assert ((x.segno () != 0) ^ x.first_regular_seg_p ());
- }
-
- unsigned short _flags; // bitmask
- short _segno; // segment number [-1,311] -1 is the field sync segment
-
-protected:
- // these three are mutually exclusive
- // This is a regular data segment.
- static constexpr int fl_regular_seg = 0x0001;
- // This is a field sync segment, for 1st half of a field.
- static constexpr int fl_field_sync1 = 0x0002;
- // This is a field sync segment, for 2nd half of a field.
- static constexpr int fl_field_sync2 = 0x0004;
-
- // This bit is on ONLY when fl_regular_seg is set AND when this is
- // the first regular data segment AFTER a field sync segment. This
- // segment causes various processing modules to reset.
- static constexpr int fl_first_regular_seg = 0x0008;
-
- // which field are we in?
- static constexpr int fl_field2 = 0x0010; // else field 1
-
- // This bit is set when Reed-Solomon decoding detects an error that it
- // can't correct. Note that other error detection (e.g. Viterbi) do not
- // set it, since Reed-Solomon will correct many of those. This bit is
- // then copied into the final Transport Stream packet so that MPEG
- // software can see that the 188-byte data segment has been corrupted.
- static constexpr int fl_transport_error = 0x0020;
-};
-
-
class atsc_mpeg_packet
{
public:
@@ -255,17 +115,6 @@ public:
plinfo pli;
float data[ATSC_DATA_SEGMENT_LENGTH];
unsigned char _pad_[NPAD]; // pad to power of 2 (4096)
-
- // overload equality operator
- bool operator==(const atsc_data_segment& other) const
- {
- return std::memcmp(data, other.data, sizeof(data)) == 0;
- }
-
- bool operator!=(const atsc_data_segment& other) const
- {
- return !(std::memcmp(data, other.data, sizeof(data)) == 0);
- }
};
} /* namespace dtv */
diff --git a/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc b/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc
index e02649861e..1e53c78aba 100644
--- a/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc
@@ -26,9 +26,10 @@ atsc_viterbi_decoder::sptr atsc_viterbi_decoder::make()
}
atsc_viterbi_decoder_impl::atsc_viterbi_decoder_impl()
- : sync_block("dtv_atsc_viterbi_decoder",
- io_signature::make(1, 1, sizeof(atsc_soft_data_segment)),
- io_signature::make(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)))
+ : sync_block(
+ "dtv_atsc_viterbi_decoder",
+ io_signature::make(1, 1, sizeof(float) * ATSC_DATA_SEGMENT_LENGTH),
+ io_signature::make(1, 1, sizeof(unsigned char) * ATSC_MPEG_RS_ENCODED_LENGTH))
{
set_output_multiple(NCODERS);
@@ -49,6 +50,8 @@ atsc_viterbi_decoder_impl::atsc_viterbi_decoder_impl()
fifo.emplace_back(fifo_size);
reset();
+
+ set_tag_propagation_policy(TPP_CUSTOM);
}
atsc_viterbi_decoder_impl::~atsc_viterbi_decoder_impl() {}
@@ -71,8 +74,8 @@ int atsc_viterbi_decoder_impl::work(int noutput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items)
{
- const atsc_soft_data_segment* in = (const atsc_soft_data_segment*)input_items[0];
- atsc_mpeg_packet_rs_encoded* out = (atsc_mpeg_packet_rs_encoded*)output_items[0];
+ auto in = static_cast<const float*>(input_items[0]);
+ auto out = static_cast<unsigned char*>(output_items[0]);
// The way the fs_checker works ensures we start getting packets
// starting with a field sync, and out input multiple is set to
@@ -87,12 +90,17 @@ int atsc_viterbi_decoder_impl::work(int noutput_items,
unsigned char out_copy[OUTPUT_SIZE];
+ std::vector<tag_t> tags;
+ auto tag_pmt = pmt::intern("plinfo");
for (int i = 0; i < noutput_items; i += NCODERS) {
+
/* Build a continuous symbol buffer for each encoder */
for (unsigned int encoder = 0; encoder < NCODERS; encoder++)
for (unsigned int k = 0; k < enco_which_max; k++)
- symbols[encoder][k] = in[i + (enco_which_syms[encoder][k] / 832)]
- .data[enco_which_syms[encoder][k] % 832];
+ symbols[encoder][k] = in[(i + (enco_which_syms[encoder][k] / 832)) *
+ ATSC_DATA_SEGMENT_LENGTH +
+ enco_which_syms[encoder][k] % 832];
+
/* Now run each of the 12 Viterbi decoders over their subset of
the input symbols */
@@ -114,12 +122,26 @@ int atsc_viterbi_decoder_impl::work(int noutput_items,
// copy output from contiguous temp buffer into final output
for (int j = 0; j < NCODERS; j++) {
- memcpy(&out[i + j].data[0],
+ plinfo pli_in;
+ get_tags_in_window(tags, 0, i + j, i + j + 1, tag_pmt);
+ if (tags.size() > 0) {
+ pli_in.from_tag_value(pmt::to_uint64(tags[0].value));
+ } else {
+ throw std::runtime_error("No plinfo on tag");
+ }
+
+ memcpy(&out[(i * NCODERS + j) * ATSC_MPEG_RS_ENCODED_LENGTH],
&out_copy[j * OUTPUT_SIZE / NCODERS],
ATSC_MPEG_RS_ENCODED_LENGTH * sizeof(out_copy[0]));
+ plinfo pli_out;
// adjust pipeline info to reflect 12 segment delay
- plinfo::delay(out[i + j].pli, in[i + j].pli, NCODERS);
+ plinfo::delay(pli_out, pli_in, NCODERS);
+
+ add_item_tag(0,
+ nitems_written(0) + i + j,
+ tag_pmt,
+ pmt::from_uint64(pli_out.get_tag_value()));
}
}