def test_001_diff_phasor_vcc(self): a = [1 + 2j, 2 + 3.5j, 3.5 + 4j, 4 + 5j, 5 + 6j] b = [1j, 1j, 1j, 1j, 1j] c = [-1j + 3, 1j, -7 + 0j, 2.5j + 0.333, 3.2j] d = [(0.35979271051026462 + 0.89414454782483865j), (0.19421665709046287 + 0.024219594550527801j), (0.12445564785882557 + 0.40766238899138718j), (0.041869638845043688 + 0.97860437393366329j), (0.068927762235083234 + 0.16649764877365247j)] e = [(0.16207552830286298 + 0.435385030608331j), (0.47195779613669675 + 0.37824764113272558j), (0.13911998015446148 + 0.6585095669811617j), (0.093510743358783954 + 0.98446560079828938j), (0.86036393297704694 + 0.72043005342024602j)] multconj = lambda x, y: x.conjugate() * y src_data = a + b + c + d + e expected_result = [0j, 0j, 0j, 0j, 0j] + map(multconj, a, b) + map( multconj, b, c) + map(multconj, c, d) + map(multconj, d, e) src = blocks.vector_source_c(src_data) s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 5) diff_phasor_vcc = dab.diff_phasor_vcc(5) v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, 5) dst = blocks.vector_sink_c() self.tb.connect(src, s2v, diff_phasor_vcc, v2s, dst) self.tb.run() result_data = dst.data() # print expected_result # print result_data self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6)
def test_001_diff_phasor_vcc(self): a = [1+2j,2+3.5j,3.5+4j,4+5j,5+6j] b = [1j,1j,1j,1j,1j] c = [-1j+3,1j,-7+0j,2.5j+0.333,3.2j] d = [(0.35979271051026462+0.89414454782483865j), (0.19421665709046287+0.024219594550527801j), (0.12445564785882557+0.40766238899138718j), (0.041869638845043688+0.97860437393366329j), (0.068927762235083234+0.16649764877365247j)] e = [(0.16207552830286298+0.435385030608331j), (0.47195779613669675+0.37824764113272558j), (0.13911998015446148+0.6585095669811617j), (0.093510743358783954+0.98446560079828938j), (0.86036393297704694+0.72043005342024602j)] multconj = lambda x,y: x.conjugate()*y src_data = a+b+c+d+e expected_result = [0j,0j,0j,0j,0j]+map(multconj,a,b)+map(multconj,b,c)+map(multconj,c,d)+map(multconj,d,e) src = blocks.vector_source_c(src_data) s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 5) diff_phasor_vcc = dab.diff_phasor_vcc(5) v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, 5) dst = blocks.vector_sink_c() self.tb.connect(src, s2v, diff_phasor_vcc, v2s, dst) self.tb.run() result_data = dst.data() # print expected_result # print result_data self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6)
def __init__(self, dab_params, rx_params, verbose=False, debug=False): """ Hierarchical block for OFDM demodulation @param dab_params DAB parameter object (dab.parameters.dab_parameters) @param rx_params RX parameter object (dab.parameters.receiver_parameters) @param debug enables debug output to files @param verbose whether to produce verbose messages """ self.dp = dp = dab_params self.rp = rp = rx_params self.verbose = verbose if self.rp.softbits: gr.hier_block2.__init__(self,"ofdm_demod", gr.io_signature (1, 1, gr.sizeof_gr_complex), # input signature gr.io_signature2(2, 2, gr.sizeof_float*self.dp.num_carriers*2, gr.sizeof_char)) # output signature else: gr.hier_block2.__init__(self,"ofdm_demod", gr.io_signature (1, 1, gr.sizeof_gr_complex), # input signature gr.io_signature2(2, 2, gr.sizeof_char*self.dp.num_carriers/4, gr.sizeof_char)) # output signature # workaround for a problem that prevents connecting more than one block directly (see trac ticket #161) #self.input = gr.kludge_copy(gr.sizeof_gr_complex) self.input = blocks.multiply_const_cc(1.0) # FIXME self.connect(self, self.input) # input filtering if self.rp.input_fft_filter: if verbose: print "--> RX filter enabled" lowpass_taps = filter.firdes_low_pass(1.0, # gain dp.sample_rate, # sampling rate rp.filt_bw, # cutoff frequency rp.filt_tb, # width of transition band filter.firdes.WIN_HAMMING) # Hamming window self.fft_filter = filter.fft_filter_ccc(1, lowpass_taps) # correct sample rate offset, if enabled if self.rp.autocorrect_sample_rate: if verbose: print "--> dynamic sample rate correction enabled" self.rate_detect_ns = dab.detect_null(dp.ns_length, False) self.rate_estimator = dab.estimate_sample_rate_bf(dp.sample_rate, dp.frame_length) self.rate_prober = blocks.probe_signal_f() self.connect(self.input, self.rate_detect_ns, self.rate_estimator, self.rate_prober) # self.resample = gr.fractional_interpolator_cc(0, 1) self.resample = dab.fractional_interpolator_triggered_update_cc(0,1) self.connect(self.rate_detect_ns, (self.resample,1)) self.updater = Timer(0.1,self.update_correction) # self.updater = threading.Thread(target=self.update_correction) self.run_interpolater_update_thread = True self.updater.setDaemon(True) self.updater.start() else: self.run_interpolater_update_thread = False if self.rp.sample_rate_correction_factor != 1: if verbose: print "--> static sample rate correction enabled" self.resample = gr.fractional_interpolator_cc(0, self.rp.sample_rate_correction_factor) # timing and fine frequency synchronisation self.sync = dab.ofdm_sync_dab2(self.dp, self.rp, debug) # ofdm symbol sampler self.sampler = dab.ofdm_sampler(dp.fft_length, dp.cp_length, dp.symbols_per_frame, rp.cp_gap) # fft for symbol vectors self.fft = fft.fft_vcc(dp.fft_length, True, [], True) # coarse frequency synchronisation self.cfs = dab.ofdm_coarse_frequency_correct(dp.fft_length, dp.num_carriers, dp.cp_length) # diff phasor self.phase_diff = dab.diff_phasor_vcc(dp.num_carriers) # remove pilot symbol self.remove_pilot = dab.ofdm_remove_first_symbol_vcc(dp.num_carriers) # magnitude equalisation if self.rp.equalize_magnitude: if verbose: print "--> magnitude equalization enabled" self.equalizer = dab.magnitude_equalizer_vcc(dp.num_carriers, rp.symbols_for_magnitude_equalization) # frequency deinterleaving self.deinterleave = dab.frequency_interleaver_vcc(dp.frequency_deinterleaving_sequence_array) # symbol demapping self.demapper = dab.qpsk_demapper_vcb(dp.num_carriers) # # connect everything # if self.rp.autocorrect_sample_rate or self.rp.sample_rate_correction_factor != 1: self.connect(self.input, self.resample) self.input2 = self.resample else: self.input2 = self.input if self.rp.input_fft_filter: self.connect(self.input2, self.fft_filter, self.sync) else: self.connect(self.input2, self.sync) # data stream self.connect((self.sync, 0), (self.sampler, 0), self.fft, (self.cfs, 0), self.phase_diff, (self.remove_pilot,0)) if self.rp.equalize_magnitude: self.connect((self.remove_pilot,0), (self.equalizer,0), self.deinterleave) else: self.connect((self.remove_pilot,0), self.deinterleave) if self.rp.softbits: if verbose: print "--> using soft bits" self.softbit_interleaver = dab.complex_to_interleaved_float_vcf(self.dp.num_carriers) self.connect(self.deinterleave, self.softbit_interleaver, (self,0)) else: self.connect(self.deinterleave, self.demapper, (self,0)) # control stream self.connect((self.sync, 1), (self.sampler, 1), (self.cfs, 1), (self.remove_pilot,1)) if self.rp.equalize_magnitude: self.connect((self.remove_pilot,1), (self.equalizer,1), (self,1)) else: self.connect((self.remove_pilot,1), (self,1)) # calculate an estimate of the SNR self.phase_var_decim = blocks.keep_one_in_n(gr.sizeof_gr_complex*self.dp.num_carriers, self.rp.phase_var_estimate_downsample) self.phase_var_arg = blocks.complex_to_arg(dp.num_carriers) self.phase_var_v2s = blocks.vector_to_stream(gr.sizeof_float, dp.num_carriers) self.phase_var_mod = dab.modulo_ff(pi/2) self.phase_var_avg_mod = filter.iir_filter_ffd([rp.phase_var_estimate_alpha], [0,1-rp.phase_var_estimate_alpha]) self.phase_var_sub_avg = blocks.sub_ff() self.phase_var_sqr = blocks.multiply_ff() self.phase_var_avg = filter.iir_filter_ffd([rp.phase_var_estimate_alpha], [0,1-rp.phase_var_estimate_alpha]) self.probe_phase_var = blocks.probe_signal_f() self.connect((self.remove_pilot,0), self.phase_var_decim, self.phase_var_arg, self.phase_var_v2s, self.phase_var_mod, (self.phase_var_sub_avg,0), (self.phase_var_sqr,0)) self.connect(self.phase_var_mod, self.phase_var_avg_mod, (self.phase_var_sub_avg,1)) self.connect(self.phase_var_sub_avg, (self.phase_var_sqr,1)) self.connect(self.phase_var_sqr, self.phase_var_avg, self.probe_phase_var) # measure processing rate self.measure_rate = dab.measure_processing_rate(gr.sizeof_gr_complex, 2000000) self.connect(self.input, self.measure_rate) # debugging if debug: self.connect(self.fft, blocks.file_sink(gr.sizeof_gr_complex*dp.fft_length, "debug/ofdm_after_fft.dat")) self.connect((self.cfs,0), blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_after_cfs.dat")) self.connect(self.phase_diff, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_diff_phasor.dat")) self.connect((self.remove_pilot,0), blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_pilot_removed.dat")) self.connect((self.remove_pilot,1), blocks.file_sink(gr.sizeof_char, "debug/ofdm_after_cfs_trigger.dat")) self.connect(self.deinterleave, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_deinterleaved.dat")) if self.rp.equalize_magnitude: self.connect(self.equalizer, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_equalizer.dat")) if self.rp.softbits: self.connect(self.softbit_interleaver, blocks.file_sink(gr.sizeof_float*dp.num_carriers*2, "debug/softbits.dat"))