def est_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 est_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)
def est_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)
def est_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 est_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 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 ()
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 ()
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 = 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) tb.connect(src, viterbi, deinter, rs_dec, derand, depad, dst) tb.run ()
def est_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 __init__(self, if_rate, # Incoming sample rate symbol_rate, # Original symbol rate excess_bw, # RRC excess bandwidth, typically 0.35-0.5 costas_alpha, # Costas loop 1st order gain, typically 0.01-0.2 costas_beta, # Costas loop 2nd order gain, typically alpha^2/4.0 costas_max, # Costas loop max frequency offset in radians/sample mm_gain_mu, # M&M loop 1st order gain, typically 0.001-0.2 mm_gain_omega, # M&M loop 2nd order gain, typically alpha^2/4.0 mm_omega_limit, # M&M loop max timing error ): gr.hier_block2.__init__(self, "receive_path", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(0, 0, 0)) # Output signature self._if_rate = if_rate self._sps = int(self._if_rate/symbol_rate) print "IF sample rate:", n2s(self._if_rate) print "Symbol rate:", n2s(symbol_rate) print "Samples/symbol:", self._sps print "RRC bandwidth:", excess_bw # Create AGC to scale input to unity self._agc = gr.agc_cc(1e-5, 1.0, 1.0, 1.0) # Create RRC with specified excess bandwidth taps = gr.firdes.root_raised_cosine(1.0, # Gain self._sps, # Sampling rate 1.0, # Symbol rate excess_bw, # Roll-off factor 11*self._sps) # Number of taps self._rrc = gr.fir_filter_ccf(1, taps) # Create a Costas loop frequency/phase recovery block print "Costas alpha:", costas_alpha print "Costas beta:", costas_beta print "Costas max:", costas_max self._costas = gr.costas_loop_cc(costas_alpha, # PLL first order gain costas_beta, # PLL second order gain costas_max, # Max frequency offset rad/sample -costas_max, # Min frequency offset rad/sample 2) # BPSK # Create a M&M bit synchronization retiming block mm_mu = 0.5 mm_omega = self._sps print "MM gain mu:", mm_gain_mu print "MM gain omega:", mm_gain_omega print "MM omega limit:", mm_omega_limit self._mm = gr.clock_recovery_mm_cc(mm_omega, # Initial samples/symbol mm_gain_omega, # Second order gain mm_mu, # Initial symbol phase mm_gain_mu, # First order gain mm_omega_limit) # Maximum timing offset # Add an SNR probe on the demodulated constellation self._snr_probe = gr.probe_mpsk_snr_c(10.0/symbol_rate) self.connect(self._mm, self._snr_probe) # Slice the resulting constellation into bits. # Get inphase channel and make decision about 0 self._c2r = gr.complex_to_real() self._slicer = gr.binary_slicer_fb() # Descramble BERT sequence. A channel error will create 3 incorrect bits self._descrambler = gr.descrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit descrambler self._decoder = atsc.rs_decoder() #reed-solomon decoder # Measure BER by the density of 0s in the stream self._ber = gr.probe_density_b(1.0/symbol_rate) self.connect(self, self._agc, self._rrc, self._costas, self._mm, self._c2r, self._slicer, self._descrambler, self._ber)
def graph (args): print os.getpid() nargs = len(args) if nargs == 2: infile = args[0] outfile = args[1] else: raise ValueError('usage: interp.py input_file output_file.ts\n') input_rate = 19.2e6 IF_freq = 5.75e6 tb = gr.top_block() # Read from input file srcf = blocks.file_source(gr.sizeof_short, infile) # Convert interleaved shorts (I,Q,I,Q) to complex is2c = blocks.interleaved_short_to_complex() # 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 / 3, symbol_rate, .1152, NTAPS) rrc = filter.fir_filter_ccf(1, tt) # Interpolate Filter our 6MHz wide signal centered at 0 ilp_coeffs = filter.firdes.low_pass(1, input_rate, 3.2e6, .5e6, filter.firdes.WIN_HAMMING) ilp = filter.interp_fir_filter_ccf(3, ilp_coeffs) # Move the center frequency to 5.75MHz ( this wont be needed soon ) 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 ) # fpll input is float c2f = blocks.complex_to_float() # Phase locked loop fpll = atsc.fpll() # Clean fpll output lp_coeffs2 = filter.firdes.low_pass (1.0, input_rate, 5.75e6, 120e3, filter.firdes.WIN_HAMMING); lp_filter = filter.fir_filter_fff (1, lp_coeffs2) # Remove pilot ( at DC now ) iir = filter.single_pole_iir_filter_ff(1e-5) remove_dc = blocks.sub_ff() # 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() # Viterbi viterbi = atsc.viterbi_decoder() deinter = atsc.deinterleaver() rs_dec = atsc.rs_decoder() derand = atsc.derandomizer() depad = atsc.depad() # Write to output file outf = blocks.file_sink(gr.sizeof_char,outfile) # Connect it all together tb.connect( srcf, is2c, rrc, ilp, duc, c2f, 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, btl ) tb.connect( (btl, 0), (fsc, 0), (eq, 0), (fsd,0) ) tb.connect( (btl, 1), (fsc, 1), (eq, 1), (fsd,1) ) tb.connect( fsd, viterbi, deinter, rs_dec, derand, depad, outf ) tb.run()
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()
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 = gr.file_source (gr.sizeof_short,infile) s2ss = gr.stream_to_streams(gr.sizeof_short,2) s2f1 = gr.short_to_float() s2f2 = gr.short_to_float() src0 = gr.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 = gr.firdes.low_pass ( 3, 19.2e6, 3.2e6, .5e6, gr.firdes.WIN_HAMMING ) lp = gr.interp_fir_filter_ccf ( 3, lp_coeffs ) tb.connect(src0, lp) # Upconvert it. 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 ) # Discard the imaginary component. c2f = gr.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 = 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() 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 = gr.file_sink(gr.sizeof_char, outfile) tb.connect(fsd, viterbi, deinter, rs_dec, derand, depad, dst) dst2 = gr.file_sink(gr.sizeof_gr_complex, "atsc_complex.data") tb.connect(src0, dst2) tb.run ()
def graph(args): print os.getpid() nargs = len(args) if nargs == 2: infile = args[0] outfile = args[1] else: raise ValueError('usage: interp.py input_file output_file.ts\n') input_rate = 19.2e6 IF_freq = 5.75e6 tb = gr.top_block() # Read from input file srcf = blocks.file_source(gr.sizeof_short, infile) # Convert interleaved shorts (I,Q,I,Q) to complex is2c = blocks.interleaved_short_to_complex() # 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 / 3, symbol_rate, .1152, NTAPS) rrc = filter.fir_filter_ccf(1, tt) # Interpolate Filter our 6MHz wide signal centered at 0 ilp_coeffs = filter.firdes.low_pass(1, input_rate, 3.2e6, .5e6, filter.firdes.WIN_HAMMING) ilp = filter.interp_fir_filter_ccf(3, ilp_coeffs) # Move the center frequency to 5.75MHz ( this won't be needed soon ) 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) # fpll input is float c2f = blocks.complex_to_float() # Phase locked loop fpll = atsc.fpll() # Clean fpll output lp_coeffs2 = filter.firdes.low_pass(1.0, input_rate, 5.75e6, 120e3, filter.firdes.WIN_HAMMING) lp_filter = filter.fir_filter_fff(1, lp_coeffs2) # Remove pilot ( at DC now ) iir = filter.single_pole_iir_filter_ff(1e-5) remove_dc = blocks.sub_ff() # 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() # Viterbi viterbi = atsc.viterbi_decoder() deinter = atsc.deinterleaver() rs_dec = atsc.rs_decoder() derand = atsc.derandomizer() depad = atsc.depad() # Write to output file outf = blocks.file_sink(gr.sizeof_char, outfile) # Connect it all together tb.connect(srcf, is2c, rrc, ilp, duc, c2f, 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, btl) tb.connect((btl, 0), (fsc, 0), (eq, 0), (fsd, 0)) tb.connect((btl, 1), (fsc, 1), (eq, 1), (fsd, 1)) tb.connect(fsd, viterbi, deinter, rs_dec, derand, depad, outf) tb.run()