From d049678e49aefaa823ce45bd9310e2e43c93e1cf Mon Sep 17 00:00:00 2001 From: cswiger Date: Mon, 23 Apr 2007 10:45:42 +0000 Subject: [PATCH] Fixed atsc_field_sync_demux to consume input even when not creating output. Added python files to make a complete 2.x atsc receiver, but it is not fully working. It will happily produce the exact same amount of transport stream output as a working system but has errors in the data. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5081 221aa14e-8319-0410-a670-987f0aec2ac5 --- gr-atsc/src/lib/atsc.i | 2 +- gr-atsc/src/lib/atsc_bit_timing_loop.cc | 3 +- gr-atsc/src/lib/atsc_field_sync_demux.cc | 45 +++++++++---- gr-atsc/src/lib/atsc_field_sync_demux.h | 17 +++-- gr-atsc/src/lib/atsci_sssr.cc | 3 +- gr-atsc/src/python/README | 32 +++++++++ gr-atsc/src/python/btl-fsd.py | 28 ++++++++ gr-atsc/src/python/fpll.py | 84 ++++++++++++++++++++++++ gr-atsc/src/python/interp.py | 74 +++++++++++++++++++++ gr-atsc/src/python/viterbi-out.py | 55 ++++++++++++++++ gr-atsc/src/python/xlate.py | 54 +++++++++++++++ 11 files changed, 376 insertions(+), 21 deletions(-) create mode 100644 gr-atsc/src/python/README create mode 100755 gr-atsc/src/python/btl-fsd.py create mode 100755 gr-atsc/src/python/fpll.py create mode 100755 gr-atsc/src/python/interp.py create mode 100755 gr-atsc/src/python/viterbi-out.py create mode 100755 gr-atsc/src/python/xlate.py diff --git a/gr-atsc/src/lib/atsc.i b/gr-atsc/src/lib/atsc.i index 9c2fdecb..77f5b75f 100644 --- a/gr-atsc/src/lib/atsc.i +++ b/gr-atsc/src/lib/atsc.i @@ -187,7 +187,7 @@ GR_SWIG_BLOCK_MAGIC(atsc,field_sync_demux); atsc_field_sync_demux_sptr atsc_make_field_sync_demux(); -class atsc_field_sync_demux : public gr_sync_decimator +class atsc_field_sync_demux : public gr_block { atsc_field_sync_demux(); diff --git a/gr-atsc/src/lib/atsc_bit_timing_loop.cc b/gr-atsc/src/lib/atsc_bit_timing_loop.cc index 49623a4f..7c12fc11 100644 --- a/gr-atsc/src/lib/atsc_bit_timing_loop.cc +++ b/gr-atsc/src/lib/atsc_bit_timing_loop.cc @@ -28,7 +28,8 @@ #include #include -float input_rate = 20e6; +// Input rate changed from 20MHz to 19.2 to support usrp at 3 * 6.4MHz +float input_rate = 19.2e6; double ratio_of_rx_clock_to_symbol_freq = input_rate / ATSC_SYMBOL_RATE; diff --git a/gr-atsc/src/lib/atsc_field_sync_demux.cc b/gr-atsc/src/lib/atsc_field_sync_demux.cc index 1534da8a..070c901a 100644 --- a/gr-atsc/src/lib/atsc_field_sync_demux.cc +++ b/gr-atsc/src/lib/atsc_field_sync_demux.cc @@ -46,11 +46,12 @@ atsc_make_field_sync_demux() } atsc_field_sync_demux::atsc_field_sync_demux() - : gr_sync_decimator("atsc_field_sync_demux", + : gr_block("atsc_field_sync_demux", gr_make_io_signature(2, 2, sizeof(float)), - gr_make_io_signature(1, 1, sizeof(atsc_soft_data_segment)),DEC), + gr_make_io_signature(1, 1, sizeof(atsc_soft_data_segment))), d_locked(false), d_in_field2(true), d_segment_number(0), - d_next_input(0), d_lost_index(0) + d_next_input(0), d_lost_index(0), d_inputs0_size(0), + d_inputs0_index(0), d_consume(0) { reset(); } @@ -66,13 +67,27 @@ atsc_field_sync_demux::forecast (int noutput_items, gr_vector_int &ninput_items_ { unsigned ninputs = ninput_items_required.size(); for (unsigned i = 0; i < ninputs; i++) { - ninput_items_required[i] = noutput_items * DEC + 2 * DEC - 1; + ninput_items_required[i] = noutput_items * DEC + 2 * DEC ; - inputs0_index = d_next_input; - inputs0_size = noutput_items * DEC + 2 * DEC - 1; + d_inputs0_index = d_next_input; + d_inputs0_size = noutput_items * DEC + 2 * DEC ; } } +int +atsc_field_sync_demux::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int r = work (noutput_items, input_items, output_items); + consume_each (d_consume); + // printf("Consumed: %d, produced: %d\n",d_consume,r); + // we consume input even if no output is produced + // while looking for sync + return r; +} + int atsc_field_sync_demux::work (int noutput_items, @@ -92,7 +107,7 @@ atsc_field_sync_demux::work (int noutput_items, if (d_locked){ d_locked = false; - d_lost_index = inputs0_index + ii; + d_lost_index = d_inputs0_index + ii; cerr << "atsc_field_sync_demux: lost sync at " << d_lost_index << endl; } @@ -100,9 +115,9 @@ atsc_field_sync_demux::work (int noutput_items, // ... search for beginning of a field sync // cerr << "atsc_field_sync_demux: searching for sync at " - // << inputs0_index + ii << endl; + // << d_inputs0_index + ii << endl; - for (ii = 1; ii < inputs0_size; ii++){ + for (ii = 1; ii < d_inputs0_size; ii++){ if (atsc::tag_is_start_field_sync (input_tags[ii])){ // found one d_locked = true; @@ -116,16 +131,19 @@ atsc_field_sync_demux::work (int noutput_items, str = "SEGMENT"; cerr << "atsc_field_sync_demux: synced (" << str << ") at " - << inputs0_index + ii - << " [delta = " << inputs0_index + ii - d_lost_index + << d_inputs0_index + ii + << " [delta = " << d_inputs0_index + ii - d_lost_index << "]\n"; d_next_input += ii; // update for forecast + d_consume = ii; return 0; // no work completed so far } } // no non-NORMAL tag found d_next_input += ii; // update for forecast + d_consume = ii; + // printf("ii: %d, d_next_input: %d\n",ii,d_next_input); return 0; // no work completed so far } @@ -135,7 +153,7 @@ atsc_field_sync_demux::work (int noutput_items, while (k < noutput_items){ - if (inputs0_size - ii < ATSC_DATA_SEGMENT_LENGTH){ + if (d_inputs0_size - ii < ATSC_DATA_SEGMENT_LENGTH){ // We're out of input data. cerr << "atsc_field_sync_demux: ran out of input data\n"; d_next_input += ii; // update for forecast @@ -145,7 +163,7 @@ atsc_field_sync_demux::work (int noutput_items, if (!tag_is_seg_sync_or_field_sync (input_tags[ii])){ // lost sync... cerr << "atsc_field_sync_demux: lost sync at " - << inputs0_index + ii << endl; + << d_inputs0_index + ii << endl; d_next_input += ii; // update for forecast return k; // return amount of work completed so far @@ -179,6 +197,7 @@ atsc_field_sync_demux::work (int noutput_items, } d_next_input += ii; // update for forecast + d_consume = ii; return k; // return amount of work completed } diff --git a/gr-atsc/src/lib/atsc_field_sync_demux.h b/gr-atsc/src/lib/atsc_field_sync_demux.h index 05ef068c..48bc1b86 100644 --- a/gr-atsc/src/lib/atsc_field_sync_demux.h +++ b/gr-atsc/src/lib/atsc_field_sync_demux.h @@ -22,7 +22,7 @@ #ifndef INCLUDED_ATSC_FIELD_SYNC_DEMUX_H #define INCLUDED_ATSC_FIELD_SYNC_DEMUX_H -#include +#include #include class atsc_field_sync_demux; @@ -36,9 +36,8 @@ atsc_field_sync_demux_sptr atsc_make_field_sync_demux(); * This class accepts 1 stream of floats (data), and 1 stream of tags (syminfo). * It outputs one stream of atsc_soft_data_segment packets * \ingroup atsc * - * input: atsc_data_segment; output: atsc_data_segment */ -class atsc_field_sync_demux : public gr_sync_decimator +class atsc_field_sync_demux : public gr_block { friend atsc_field_sync_demux_sptr atsc_make_field_sync_demux(); @@ -46,6 +45,13 @@ class atsc_field_sync_demux : public gr_sync_decimator public: 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); + + int work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); @@ -59,8 +65,9 @@ protected: gr_uint64 d_next_input; gr_uint64 d_lost_index; // diagnostic fluff - unsigned long long inputs0_index; // for inputs[0].index - unsigned long inputs0_size; // for inputs[0].size + unsigned long long d_inputs0_index; // for inputs[0].index + unsigned long d_inputs0_size; // for inputs[0].size + int d_consume; }; diff --git a/gr-atsc/src/lib/atsci_sssr.cc b/gr-atsc/src/lib/atsci_sssr.cc index b52f7a66..f44b9243 100644 --- a/gr-atsc/src/lib/atsci_sssr.cc +++ b/gr-atsc/src/lib/atsci_sssr.cc @@ -189,7 +189,8 @@ static const double ADJUSTMENT_GAIN = 1.0e-5 / (10 * ATSC_DATA_SEGMENT_LENGTH); atsci_interpolator::atsci_interpolator (double nominal_ratio_of_rx_clock_to_symbol_freq) { - assert (nominal_ratio_of_rx_clock_to_symbol_freq >= 1.8); +// Tweaked ratio from 1.8 to 1.78 to support input rate of 19.2MHz + assert (nominal_ratio_of_rx_clock_to_symbol_freq >= 1.78); d_nominal_ratio_of_rx_clock_to_symbol_freq = nominal_ratio_of_rx_clock_to_symbol_freq; diff --git a/gr-atsc/src/python/README b/gr-atsc/src/python/README new file mode 100644 index 00000000..c5dd4af9 --- /dev/null +++ b/gr-atsc/src/python/README @@ -0,0 +1,32 @@ +Currently the best, fastest software decode is by using +19.2MSps over 5 processes. + +1) Capture data - adjust gain (-g) frequency (-f) and which side +the tvrx is on to fit your local setup: + +usrp_rx_cfile -R B -d 10 -g 65 -f 503e6 atsc_data_6-4m_complex + + +2) Make pipes: + +mkfifo /tmp/atsc_pipe_1 +mkfifo /tmp/atsc_pipe_2 +mkfifo /tmp/atsc_pipe_3 +mkfifo /tmp/atsc_pipe_4 +mkfifo /tmp/atsc_pipe_5 + +3) In seperate windows run processes: + +./interp.py +./xlate.py +./fpll.py +./btl-fsd.py +./viterbi-out.py + + +Status: Not fully working. + +Currently gr-atsc 2.x will produce the exact amount of data as a working system, +but there are a some differences in the output. If you substitute the btl-fsd.py +block with the corresponding code from gnuradio-0.9 it works. + diff --git a/gr-atsc/src/python/btl-fsd.py b/gr-atsc/src/python/btl-fsd.py new file mode 100755 index 00000000..ed26f4bb --- /dev/null +++ b/gr-atsc/src/python/btl-fsd.py @@ -0,0 +1,28 @@ +#!/usr/bin/python + +from gnuradio import gr +from gnuradio import atsc + +fg = gr.flow_graph() + +btl = atsc.bit_timing_loop() +fsc = atsc.fs_checker() +eq = atsc.equalizer() +fsd = atsc.field_sync_demux() + +out_data = gr.file_sink(atsc.sizeof_atsc_soft_data_segment,"/tmp/atsc_pipe_5") + +inp = gr.file_source(gr.sizeof_float,"/tmp/atsc_pipe_3") + +fg.connect(inp,btl) +fg.connect((btl,0),(fsc,0)) +fg.connect((btl,1),(fsc,1)) +fg.connect((fsc,0),(eq,0)) +fg.connect((fsc,1),(eq,1)) +fg.connect((eq,0),(fsd,0)) +fg.connect((eq,1),(fsd,1)) +fg.connect(fsd,out_data) + +fg.run() + + diff --git a/gr-atsc/src/python/fpll.py b/gr-atsc/src/python/fpll.py new file mode 100755 index 00000000..0788d0fb --- /dev/null +++ b/gr-atsc/src/python/fpll.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 2, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, atsc +import math + +def main(): + + fg = gr.flow_graph() + + u = gr.file_source(gr.sizeof_float,"/tmp/atsc_pipe_2") + + input_rate = 19.2e6 + IF_freq = 5.75e6 + + + # 1/2 as wide because we're designing lp filter + symbol_rate = atsc.ATSC_SYMBOL_RATE/2. + NTAPS = 279 + tt = gr.firdes.root_raised_cosine (1.0, input_rate, symbol_rate, .115, NTAPS) + # heterodyne the low pass coefficients up to the specified bandpass + # center frequency. Note that when we do this, the filter bandwidth + # is effectively twice the low pass (2.69 * 2 = 5.38) and hence + # matches the diagram in the ATSC spec. + arg = 2. * math.pi * IF_freq / input_rate + t=[] + for i in range(len(tt)): + t += [tt[i] * 2. * math.cos(arg * i)] + rrc = gr.fir_filter_fff(1, t) + + fpll = atsc.fpll() + + pilot_freq = IF_freq - 3e6 + 0.31e6 + lower_edge = 6e6 - 0.31e6 + upper_edge = IF_freq - 3e6 + pilot_freq + transition_width = upper_edge - lower_edge + lp_coeffs = gr.firdes.low_pass (1.0, + input_rate, + (lower_edge + upper_edge) * 0.5, + transition_width, + gr.firdes.WIN_HAMMING); + + lp_filter = gr.fir_filter_fff (1,lp_coeffs) + + alpha = 1e-5 + iir = gr.single_pole_iir_filter_ff(alpha) + remove_dc = gr.sub_ff() + + out = gr.file_sink(gr.sizeof_float,"/tmp/atsc_pipe_3") + # out = gr.file_sink(gr.sizeof_float,"/mnt/sata/atsc_data_float") + + fg.connect(u, fpll, lp_filter) + fg.connect(lp_filter, iir) + fg.connect(lp_filter, (remove_dc,0)) + fg.connect(iir, (remove_dc,1)) + fg.connect(remove_dc, out) + + fg.run() + + +if __name__ == '__main__': + main () + + + diff --git a/gr-atsc/src/python/interp.py b/gr-atsc/src/python/interp.py new file mode 100755 index 00000000..36cc7244 --- /dev/null +++ b/gr-atsc/src/python/interp.py @@ -0,0 +1,74 @@ +#!/usr/bin/env /usr/bin/python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 2, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# +# This module starts the atsc processing chain taking the captured +# off-air signal created with: +# +# usrp_rx_cfile.py -R +# -d 10 set decimation to get signal at 6.4e6 rate +# -f
+# -g +# +# All this module does is multiply the sample rate by 3, from 6.4e6 to +# 19.2e6 complex samples / sec, then lowpass filter with a cutoff of 3.2MHz +# and a transition band width of .5MHz. Center of the tv channels is +# then at 0 with edges at -3.2MHz and 3.2MHz. + +from gnuradio import gr +import sys + +def graph (args): + + nargs = len (args) + if nargs == 1: + infile = args[0] + else: + sys.stderr.write('usage: interp.py input_file\n') + sys.exit (1) + + sampling_freq = 6400000 + + fg = gr.flow_graph () + + src0 = gr.file_source (gr.sizeof_gr_complex,infile) + src1 = gr.sig_source_c (sampling_freq, gr.GR_CONST_WAVE, 1, 0) + src2 = gr.sig_source_c (sampling_freq, gr.GR_CONST_WAVE, 1, 0) + + interlv = gr.interleave(gr.sizeof_gr_complex) + + lp_coeffs = gr.firdes.low_pass ( 3, 19.2e6, 3.2e6, .5e6, gr.firdes.WIN_HAMMING ) + lp = gr.fir_filter_ccf ( 1, lp_coeffs ) + + file = gr.file_sink(gr.sizeof_gr_complex,"/tmp/atsc_pipe_1") + + fg.connect( src0, (interlv, 0) ) + fg.connect( src1, (interlv, 1) ) + fg.connect( src2, (interlv, 2) ) + fg.connect( interlv, lp, file ) + + fg.start() + raw_input ('Head End: Press Enter to stop') + fg.stop() + +if __name__ == '__main__': + graph (sys.argv[1:]) + + diff --git a/gr-atsc/src/python/viterbi-out.py b/gr-atsc/src/python/viterbi-out.py new file mode 100755 index 00000000..f74900b3 --- /dev/null +++ b/gr-atsc/src/python/viterbi-out.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 2, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, atsc +import sys + +def main(args): + + nargs = len (args) + if nargs == 1: + outfile = args[0] + else: + sys.stderr.write ('usage: viterbi_out.py output_file\n') + sys.exit (1) + + fg = gr.flow_graph() + + src = gr.file_source(atsc.sizeof_atsc_soft_data_segment, "/tmp/atsc_pipe_5") + viterbi = atsc.viterbi_decoder() + deinter = atsc.deinterleaver() + rs_dec = atsc.rs_decoder() + derand = atsc.derandomizer() + depad = atsc.depad() + dst = gr.file_sink(gr.sizeof_char,outfile) + fg.connect(src, viterbi, deinter, rs_dec, derand, depad, dst) + fg.run () + + +if __name__ == '__main__': + main(sys.argv[1:]) + + + + + + diff --git a/gr-atsc/src/python/xlate.py b/gr-atsc/src/python/xlate.py new file mode 100755 index 00000000..4a7171d4 --- /dev/null +++ b/gr-atsc/src/python/xlate.py @@ -0,0 +1,54 @@ +#!/usr/bin/env /usr/bin/python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 2, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# +# This module upconverts the 19.2e6 sample rate signal from a center +# of 0 to 5.75e6 and converts to float, to prepare the signal for +# the old gnuradio 0.9 block (bit timing loop, field sync checker, +# equalizer and field sync demux), effectively simulating an +# mc4020 card, except the sample rate is 19.2e6 instead of 20e6. +# +# The signal is then centered on 5.75e6 with edges at 5.75 + 3.2 = 8.95MHz +# and 5.75 - 3.2 = 2.55Mhz, low pass filtered with cutoff at 9Mhz and a +# transition band width of 1Mhz. +# +# Input complex -3.2 to 3.2Mhz, output float 2.55 to 8.95Mhz. + +from gnuradio import gr + +def graph (): + sampling_freq = 19200000 + + fg = gr.flow_graph () + + src0 = gr.file_source (gr.sizeof_gr_complex,"/tmp/atsc_pipe_1") + + duc_coeffs = gr.firdes.low_pass ( 1, 19.2e6, 9e6, 1e6, gr.firdes.WIN_HAMMING ) + duc = gr.freq_xlating_fir_filter_ccf ( 1, duc_coeffs, 5.75e6, 19.2e6 ) + + c2f = gr.complex_to_float() + file = gr.file_sink(gr.sizeof_float,"/tmp/atsc_pipe_2") + + fg.connect( src0, duc, c2f, file ) + + fg.run() + +if __name__ == '__main__': + graph () -- 2.30.2