diff options
author | Tom Rondeau <trondeau@vt.edu> | 2013-03-15 20:49:05 -0400 |
---|---|---|
committer | Tom Rondeau <trondeau@vt.edu> | 2013-03-15 20:49:05 -0400 |
commit | 3d38e82e7d87dfc01132b199e33b53add8a706fa (patch) | |
tree | af4545bcf3cea24dc30571601116a3a89381ad5d /gr-atsc/python | |
parent | 39ff6d4814c858f2dbaf3c8007940872c46d6c95 (diff) |
atsc: adjustments to atsc to start to conform to v3.7 structure.
Not going to comply completely with the new structure; just wanted to get it so that it looked more consistent once installed.
Diffstat (limited to 'gr-atsc/python')
-rw-r--r-- | gr-atsc/python/CMakeLists.txt | 60 | ||||
-rw-r--r-- | gr-atsc/python/README | 34 | ||||
-rw-r--r-- | gr-atsc/python/all_atsc.py | 142 | ||||
-rw-r--r-- | gr-atsc/python/atsc_utils.py | 75 | ||||
-rwxr-xr-x | gr-atsc/python/btl-fsd.py | 48 | ||||
-rwxr-xr-x | gr-atsc/python/fpll.py | 88 | ||||
-rwxr-xr-x | gr-atsc/python/interp.py | 66 | ||||
-rwxr-xr-x | gr-atsc/python/interp_short.py | 78 | ||||
-rwxr-xr-x | gr-atsc/python/qa_atsc.py | 222 | ||||
-rwxr-xr-x | gr-atsc/python/viterbi-out.py | 58 | ||||
-rwxr-xr-x | gr-atsc/python/xlate.py | 58 |
11 files changed, 929 insertions, 0 deletions
diff --git a/gr-atsc/python/CMakeLists.txt b/gr-atsc/python/CMakeLists.txt new file mode 100644 index 0000000000..aaa5bd93c4 --- /dev/null +++ b/gr-atsc/python/CMakeLists.txt @@ -0,0 +1,60 @@ +# Copyright 2011-2012 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 3, 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., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Install python examples +######################################################################## +include(GrPython) + +GR_PYTHON_INSTALL( + PROGRAMS + btl-fsd.py + fpll.py + interp.py + xlate.py + viterbi-out.py + DESTINATION ${GR_PKG_DATA_DIR}/examples/atsc + COMPONENT "atsc_examples" +) + +install( + FILES README + DESTINATION ${GR_PKG_DATA_DIR}/examples/atsc + COMPONENT "atsc_examples" +) + +######################################################################## +# Handle the unit tests +######################################################################## +if(ENABLE_TESTING) + +list(APPEND GR_TEST_PYTHON_DIRS + ${CMAKE_BINARY_DIR}/gr-atsc/src/lib + ${CMAKE_BINARY_DIR}/gr-blocks/python + ${CMAKE_BINARY_DIR}/gr-blocks/swig +) +list(APPEND GR_TEST_TARGET_DEPS gnuradio-atsc gnuradio-fec gnuradio-filter gnuradio-analog gnuradio-fft) + +include(GrTest) +file(GLOB py_qa_test_files "qa_*.py") +foreach(py_qa_test_file ${py_qa_test_files}) + get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) + GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) +endforeach(py_qa_test_file) +endif(ENABLE_TESTING) diff --git a/gr-atsc/python/README b/gr-atsc/python/README new file mode 100644 index 0000000000..74d6ba134c --- /dev/null +++ b/gr-atsc/python/README @@ -0,0 +1,34 @@ +Decoding ATSC using 19.2MSps rate over 5 processes +-------------------------------------------------- + +1) Verify signal, adjust antenna and find best gain setting using uhd_fft.py, +station frequency from the fcc video database, and sample rate to 6.4e6. + +2) Capture data - adjust gain (-g) frequency (-f) and which side +the tvrx is on to fit your local setup: + +uhd_rx_cfile.py -s --samp-rate=6.4e6 -g 65 -f 503e6 atsc_data_6-4m_complex + +You probably still need fast disks to take the data, like a raid-0 set of +striped sata drives. Make sure there are no or very few Ou overruns. Saving +the raw usrp data in 'short' form halves the disk space/bus bandwidth that +the usual complex form uses. + +3) 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 + +4) In seperate windows run processes: + +./interp_short.py <input rf data at 6.4Msps> +./xlate.py +./fpll.py +./btl-fsd.py +./viterbi-out.py <output mpeg transport stream> + + + diff --git a/gr-atsc/python/all_atsc.py b/gr-atsc/python/all_atsc.py new file mode 100644 index 0000000000..7cac785149 --- /dev/null +++ b/gr-atsc/python/all_atsc.py @@ -0,0 +1,142 @@ +#!/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: +# +# uhd_rx_cfile.py --samp-rate=6.4e6 +# -f <center of tv signal channel freq> +# -g <appropriate gain for best signal / noise> +# -s output shorts +# +# 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, atsc +from gnuradio import filter +from gnuradio import blocks +import sys, os, math + +def graph (args): + + nargs = len(args) + if nargs == 2: + infile = args[0] + outfile = args[1] + else: + raise ValueError('usage: interp.py input_file output_file\n') + + tb = gr.top_block () + + # Convert to a from shorts to a stream of complex numbers. + srcf = blocks.file_source (gr.sizeof_short,infile) + s2ss = blocks.stream_to_streams(gr.sizeof_short,2) + s2f1 = blocks.short_to_float() + s2f2 = blocks.short_to_float() + src0 = blocks.float_to_complex() + tb.connect(srcf, s2ss) + tb.connect((s2ss, 0), s2f1, (src0, 0)) + tb.connect((s2ss, 1), s2f2, (src0, 1)) + + # Low pass filter it and increase sample rate by a factor of 3. + lp_coeffs = filter.firdes.low_pass ( 3, 19.2e6, 3.2e6, .5e6, filter.firdes.WIN_HAMMING ) + lp = filter.interp_fir_filter_ccf ( 3, lp_coeffs ) + tb.connect(src0, lp) + + # Upconvert it. + duc_coeffs = filter.firdes.low_pass ( 1, 19.2e6, 9e6, 1e6, filter.firdes.WIN_HAMMING ) + duc = filter.freq_xlating_fir_filter_ccf ( 1, duc_coeffs, 5.75e6, 19.2e6 ) + # Discard the imaginary component. + c2f = blocks.complex_to_float() + tb.connect(lp, duc, c2f) + + # Frequency Phase Lock Loop + 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 = filter.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 = filter.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 = filter.firdes.low_pass(1.0, + input_rate, + (lower_edge + upper_edge) * 0.5, + transition_width, + filter.firdes.WIN_HAMMING); + + lp_filter = filter.fir_filter_fff(1,lp_coeffs) + + alpha = 1e-5 + iir = filter.single_pole_iir_filter_ff(alpha) + remove_dc = blocks.sub_ff() + + tb.connect(c2f, fpll, lp_filter) + tb.connect(lp_filter, iir) + tb.connect(lp_filter, (remove_dc,0)) + tb.connect(iir, (remove_dc,1)) + + # Bit Timing Loop, Field Sync Checker and Equalizer + + btl = atsc.bit_timing_loop() + fsc = atsc.fs_checker() + eq = atsc.equalizer() + fsd = atsc.field_sync_demux() + + tb.connect(remove_dc, btl) + tb.connect((btl, 0),(fsc, 0),(eq, 0),(fsd, 0)) + tb.connect((btl, 1),(fsc, 1),(eq, 1),(fsd, 1)) + + # Viterbi + + viterbi = atsc.viterbi_decoder() + deinter = atsc.deinterleaver() + rs_dec = atsc.rs_decoder() + derand = atsc.derandomizer() + depad = atsc.depad() + dst = blocks.file_sink(gr.sizeof_char, outfile) + tb.connect(fsd, viterbi, deinter, rs_dec, derand, depad, dst) + + dst2 = blocks.file_sink(gr.sizeof_gr_complex, "atsc_complex.data") + tb.connect(src0, dst2) + + tb.run () + +if __name__ == '__main__': + graph (sys.argv[1:]) + + diff --git a/gr-atsc/python/atsc_utils.py b/gr-atsc/python/atsc_utils.py new file mode 100644 index 0000000000..fc2465bed2 --- /dev/null +++ b/gr-atsc/python/atsc_utils.py @@ -0,0 +1,75 @@ +# +# Copyright 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 3, 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., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import random +import sys + +MPEG_SYNC_BYTE = 0x47 + +def make_fake_transport_stream_packet(npkts): + """ + Return a sequence of 8-bit ints that represents an MPEG Transport Stream packet. + + Args: + npkts: how many 188-byte packets to return + + FYI, each ATSC Data Frame contains two Data Fields, each of which contains + 312 data segments. Each transport stream packet maps to a data segment. + """ + r = [0] * (npkts * 188) + i = 0 + for j in range(npkts): + r[i+0] = MPEG_SYNC_BYTE + r[i+1] = random.randint(0, 127) # top bit (transport error bit) clear + i = i + 2 + for n in range(186): + r[i + n] = random.randint(0, 255) + i = i + 186 + + return r + + +def pad_stream(src, sizeof_total, sizeof_pad): + sizeof_valid = sizeof_total - sizeof_pad + assert sizeof_valid > 0 + assert (len(src) % sizeof_valid) == 0 + npkts = len(src) // sizeof_valid + dst = [0] * (npkts * sizeof_total) + for i in range(npkts): + src_s = i * sizeof_valid + dst_s = i * sizeof_total + dst[dst_s:dst_s + sizeof_valid] = src[src_s:src_s + sizeof_valid] + return dst + + +def depad_stream(src, sizeof_total, sizeof_pad): + sizeof_valid = sizeof_total - sizeof_pad + assert sizeof_valid > 0 + assert (len(src) % sizeof_total) == 0 + npkts = len(src) // sizeof_total + dst = [0] * (npkts * sizeof_valid) + for i in range(npkts): + src_s = i * sizeof_total + dst_s = i * sizeof_valid + dst[dst_s:dst_s + sizeof_valid] = src[src_s:src_s + sizeof_valid] + return dst + + diff --git a/gr-atsc/python/btl-fsd.py b/gr-atsc/python/btl-fsd.py new file mode 100755 index 0000000000..6bcab3dce3 --- /dev/null +++ b/gr-atsc/python/btl-fsd.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005,2007 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 3, 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 +from gnuradio import atsc +from gnuradio import blocks +import os + +print os.getpid() + +tb = gr.top_block() + +btl = atsc.bit_timing_loop() +fsc = atsc.fs_checker() +eq = atsc.equalizer() +fsd = atsc.field_sync_demux() + +out_data = blocks.file_sink(atsc.sizeof_atsc_soft_data_segment,"/tmp/atsc_pipe_5") + +inp = blocks.file_source(gr.sizeof_float,"/tmp/atsc_pipe_3") + +tb.connect(inp,btl) +tb.connect((btl,0),(fsc,0),(eq,0),(fsd,0)) +tb.connect((btl,1),(fsc,1),(eq,1),(fsd,1)) +tb.connect(fsd,out_data) + +tb.run() + + diff --git a/gr-atsc/python/fpll.py b/gr-atsc/python/fpll.py new file mode 100755 index 0000000000..dee81da13d --- /dev/null +++ b/gr-atsc/python/fpll.py @@ -0,0 +1,88 @@ +#!/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 3, 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 +from gnuradio import blocks +from gnuradio import filter +import math, os + +def main(): + + print os.getpid() + + tb = gr.top_block() + + u = blocks.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 = filter.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 = filter.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 = filter.firdes.low_pass (1.0, + input_rate, + (lower_edge + upper_edge) * 0.5, + transition_width, + filter.firdes.WIN_HAMMING); + + lp_filter = filter.fir_filter_fff (1,lp_coeffs) + + alpha = 1e-5 + iir = filter.single_pole_iir_filter_ff(alpha) + remove_dc = blocks.sub_ff() + + out = blocks.file_sink(gr.sizeof_float,"/tmp/atsc_pipe_3") + # out = blocks.file_sink(gr.sizeof_float,"/mnt/sata/atsc_data_float") + + tb.connect(u, fpll, lp_filter) + tb.connect(lp_filter, iir) + tb.connect(lp_filter, (remove_dc,0)) + tb.connect(iir, (remove_dc,1)) + tb.connect(remove_dc, out) + + tb.run() + + +if __name__ == '__main__': + main () + + + diff --git a/gr-atsc/python/interp.py b/gr-atsc/python/interp.py new file mode 100755 index 0000000000..ee2d234892 --- /dev/null +++ b/gr-atsc/python/interp.py @@ -0,0 +1,66 @@ +#!/usr/bin/env /usr/bin/python +# +# Copyright 2004,2007 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 3, 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: +# +# uhd_rx_cfile.py --samp-rate=6.4e6 +# -f <center of tv signal channel freq> +# -g <appropriate gain for best signal / noise> +# +# 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 +from gnuradio import blocks +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) + + tb = gr.top_block() + + src0 = blocks.file_source(gr.sizeof_gr_complex, infile) + + lp_coeffs = filter.firdes.low_pass(3, 19.2e6, 3.2e6, .5e6, + filter.firdes.WIN_HAMMING ) + lp = filter.interp_fir_filter_ccf(1, lp_coeffs) + + file = blocks.file_sink(gr.sizeof_gr_complex, "/tmp/atsc_pipe_1") + + tb.connect(src0, lp, file) + + tb.start() + raw_input('Head End: Press Enter to stop') + tb.stop() + +if __name__ == '__main__': + graph(sys.argv[1:]) + + diff --git a/gr-atsc/python/interp_short.py b/gr-atsc/python/interp_short.py new file mode 100755 index 0000000000..d07b941c12 --- /dev/null +++ b/gr-atsc/python/interp_short.py @@ -0,0 +1,78 @@ +#!/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: +# +# uhd_rx_cfile.py --samp-rate=6.4e6 +# -f <center of tv signal channel freq> +# -g <appropriate gain for best signal / noise> +# -s output shorts +# +# 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 +from gnuradio import blocks +from gnuradio import filter +import sys, os + +def graph (args): + + print os.getpid() + + nargs = len (args) + if nargs == 1: + infile = args[0] + else: + sys.stderr.write('usage: interp.py input_file\n') + sys.exit (1) + + tb = gr.top_block() + + srcf = blocks.file_source(gr.sizeof_short,infile) + s2ss = blocks.stream_to_streams(gr.sizeof_short,2) + s2f1 = blocks.short_to_float() + s2f2 = blocks.short_to_float() + src0 = blocks.float_to_complex() + + + lp_coeffs = filter.firdes.low_pass(3, 19.2e6, 3.2e6, .5e6, + filter.firdes.WIN_HAMMING) + lp = filter.interp_fir_filter_ccf(3, lp_coeffs) + + file = blocks.file_sink(gr.sizeof_gr_complex,"/tmp/atsc_pipe_1") + + tb.connect( srcf, s2ss ) + tb.connect( (s2ss, 0), s2f1, (src0,0) ) + tb.connect( (s2ss, 1), s2f2, (src0,1) ) + tb.connect( src0, lp, file) + + tb.start() + raw_input ('Head End: Press Enter to stop') + tb.stop() + +if __name__ == '__main__': + graph (sys.argv[1:]) + + diff --git a/gr-atsc/python/qa_atsc.py b/gr-atsc/python/qa_atsc.py new file mode 100755 index 0000000000..507bc8aa47 --- /dev/null +++ b/gr-atsc/python/qa_atsc.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006,2007 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 3, 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., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import atsc # qa code needs to run without being installed +#from gnuradio import atsc +from atsc_utils import * +import sys +import blocks_swig as blocks + +class memoize(object): + def __init__(self, thunk): + self.thunk = thunk + self.cached = False + self.value = None + + def __call__(self): + if self.cached: + return self.value + self.value = self.thunk() + self.cached = True + return self.value + + +""" +Make a fake transport stream that's big enough for our purposes. +We generate 8 full fields. This is relatively expensive. It +takes about 2 seconds to execute. +""" +make_transport_stream = \ + memoize(lambda : tuple(make_fake_transport_stream_packet(8 * atsc.ATSC_DSEGS_PER_FIELD))) + + +def pad_transport_stream(src): + """ + An MPEG transport stream packet is 188 bytes long. Internally we use a packet + that is 256 bytes long to help with buffer alignment. This function adds the + appropriate trailing padding to convert each packet from 188 to 256 bytes. + """ + return pad_stream(src, atsc.sizeof_atsc_mpeg_packet, atsc.sizeof_atsc_mpeg_packet_pad) + + +def depad_transport_stream(src): + """ + An MPEG transport stream packet is 188 bytes long. Internally we use a packet + that is 256 bytes long to help with buffer alignment. This function removes the + trailing padding to convert each packet from 256 back to 188 bytes. + """ + return depad_stream(src, atsc.sizeof_atsc_mpeg_packet, atsc.sizeof_atsc_mpeg_packet_pad) + + +class vector_source_ts(gr.hier_block2): + """ + MPEG Transport stream source for testing. + """ + def __init__(self, ts): + """ + Pad tranport stream packets to 256 bytes and reformat appropriately. + + Args: + ts: MPEG transport stream. (sequence of ints in [0,255]; len(ts) % 188 == 0) + """ + + src = gr.vector_source_b(pad_transport_stream(ts)) + s2v = blocks.stream_to_vector(gr.sizeof_char, atsc.sizeof_atsc_mpeg_packet) + + gr.hier_block2.__init__(self, "vector_source_ts", + gr.io_signature(0, 0, 0), + s2v.output_signature()) + self.connect(src, s2v, self) + + +class vector_sink_ts(gr.hier_block2): + """ + MPEG Transport stream sink for testing. + """ + def __init__(self): + """ + """ + + v2s = blocks.vector_to_stream(gr.sizeof_char, atsc.sizeof_atsc_mpeg_packet) + self.sink = gr.vector_sink_b() + gr.hier_block2.__init__(self, "vector_sink_ts", + v2s.input_signature(), + gr.io_signature(0, 0, 0)) + self.connect(self, v2s, self.sink) + + def data(self): + """ + Extracts tranport stream from sink and returns it to python. + + Depads tranport stream packets from 256 back to 188 bytes. + @rtype: tuple of ints in [0,255]; len(result) % 188 == 0 + """ + return tuple(depad_transport_stream(self.sink.data())) + + + +class qa_atsc(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + + # The tests are run in alphabetical order + + def test_loopback_000(self): + """ + Loopback randomizer to derandomizer + """ + src_data = make_transport_stream() + expected_result = src_data + + src = vector_source_ts(src_data) + rand = atsc.randomizer() + derand = atsc.derandomizer() + dst = vector_sink_ts() + self.tb.connect(src, rand, derand, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + def test_loopback_001(self): + """ + Loopback randomizer/rs_encoder to rs_decoder/derandomizer + """ + src_data = make_transport_stream() + expected_result = src_data + + src = vector_source_ts(src_data) + rand = atsc.randomizer() + rs_enc = atsc.rs_encoder() + rs_dec = atsc.rs_decoder() + derand = atsc.derandomizer() + dst = vector_sink_ts() + self.tb.connect(src, rand, rs_enc, rs_dec, derand, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + def test_loopback_002(self): + """ + Loopback randomizer/rs_encoder/interleaver to + deinterleaver/rs_decoder/derandomizer + """ + src_data = make_transport_stream() + interleaver_delay = 52 + expected_result = src_data[0:len(src_data)-(interleaver_delay*atsc.ATSC_MPEG_PKT_LENGTH)] + + src = vector_source_ts(src_data) + rand = atsc.randomizer() + rs_enc = atsc.rs_encoder() + inter = atsc.interleaver() + deinter = atsc.deinterleaver() + rs_dec = atsc.rs_decoder() + derand = atsc.derandomizer() + dst = vector_sink_ts() + self.tb.connect(src, rand, rs_enc, inter, deinter, rs_dec, derand, dst) + self.tb.run () + result_data = dst.data () + result_data = result_data[(interleaver_delay*atsc.ATSC_MPEG_PKT_LENGTH):len(result_data)] + self.assertEqual (expected_result, result_data) + + + def test_loopback_003(self): + """ + Loopback randomizer/rs_encoder/interleaver/trellis_encoder + via ds_to_softds to + viterbi_decoder/deinterleaver/rs_decoder/derandomizer + """ + src_data = make_transport_stream() + interleaver_delay = 52 + viterbi_delay = 12 + expected_result = src_data[0:len(src_data)-((interleaver_delay+viterbi_delay)*atsc.ATSC_MPEG_PKT_LENGTH)] + + src = vector_source_ts(src_data) + rand = atsc.randomizer() + rs_enc = atsc.rs_encoder() + inter = atsc.interleaver() + trellis = atsc.trellis_encoder() + softds = atsc.ds_to_softds() + viterbi = atsc.viterbi_decoder() + deinter = atsc.deinterleaver() + rs_dec = atsc.rs_decoder() + derand = atsc.derandomizer() + dst = vector_sink_ts() + self.tb.connect(src, rand, rs_enc, inter, trellis, softds, viterbi, deinter, rs_dec, derand, dst) + self.tb.run () + result_data = dst.data ()[((interleaver_delay+viterbi_delay)*atsc.ATSC_MPEG_PKT_LENGTH):len(dst.data())] + self.assertEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main() + + + + + + diff --git a/gr-atsc/python/viterbi-out.py b/gr-atsc/python/viterbi-out.py new file mode 100755 index 0000000000..cc60ffda42 --- /dev/null +++ b/gr-atsc/python/viterbi-out.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006,2007 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 3, 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 +from gnuradio import blocks +import sys, os + +def main(args): + + print os.getpid() + + nargs = len (args) + if nargs == 1: + outfile = args[0] + else: + sys.stderr.write ('usage: viterbi_out.py output_file\n') + sys.exit (1) + + tb = gr.top_block() + + src = blocks.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 = blocks.file_sink(gr.sizeof_char,outfile) + tb.connect(src, viterbi, deinter, rs_dec, derand, depad, dst) + tb.run () + + +if __name__ == '__main__': + main(sys.argv[1:]) + + + + + + diff --git a/gr-atsc/python/xlate.py b/gr-atsc/python/xlate.py new file mode 100755 index 0000000000..3d049ac524 --- /dev/null +++ b/gr-atsc/python/xlate.py @@ -0,0 +1,58 @@ +#!/usr/bin/env /usr/bin/python +# +# Copyright 2004,2007 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 3, 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 +from gnuradio import filter +from gnuradio import blocks +import os + +def graph (): + print os.getpid() + sampling_freq = 19200000 + + tb = gr.top_block () + + src0 = blocks.file_source(gr.sizeof_gr_complex,"/tmp/atsc_pipe_1") + + duc_coeffs = filter.firdes.low_pass( 1, 19.2e6, 9e6, 1e6, filter.firdes.WIN_HAMMING ) + duc = filter.freq_xlating_fir_filter_ccf( 1 duc_coeffs, 5.75e6, 19.2e6 ) + + c2f = blocks.complex_to_float() + file = blocks.file_sink(gr.sizeof_float,"/tmp/atsc_pipe_2") + + tb.connect( src0, duc, c2f, file ) + + tb.run() + +if __name__ == '__main__': + graph () |