def test_001_ofdm_ffe_all_in_one(self): symbol_length = 5 num_symbols = 2 fft_length = 3 alpha = 0.1 src_data0 = [77 * cmath.exp(2j * pi * x / 20) for x in range(0, 20)] src_data0[ 4] = 100 # should not matter, as this area of the symbol is not evaluated src_data0[12:19] = [ 100 ] * 7 # should not matter, as only the first two symbols are evaluated src_data1 = (0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) d = -2 * pi / 20 # phase diff between two consective samples expected_result = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, d, d, d, d, d, d, d, d) src0 = blocks.vector_source_c(src_data0) src1 = blocks.vector_source_b(src_data1) ffe = dab.ofdm_ffe_all_in_one(symbol_length, fft_length, num_symbols, alpha, 10) dst0 = blocks.vector_sink_f() self.tb.connect(src0, (ffe, 0)) self.tb.connect(src1, (ffe, 1)) self.tb.connect(ffe, dst0) self.tb.run() result_data0 = dst0.data() # print expected_result # print result_data0 self.assertFloatTuplesAlmostEqual(expected_result, result_data0, 3)
def test_001_ofdm_ffe_all_in_one(self): symbol_length = 5 num_symbols = 2 fft_length = 3 alpha = 0.1 src_data0 = [77*cmath.exp(2j*pi*x/20) for x in range(0,20)] src_data0[4] = 100 # should not matter, as this area of the symbol is not evaluated src_data0[12:19] = [100] * 7 # should not matter, as only the first two symbols are evaluated src_data1 = (0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) d = -2*pi/20 # phase diff between two consective samples expected_result = (0,0,0,0,0,0,0,0,0,0,0,0,d,d,d,d,d,d,d,d) src0 = blocks.vector_source_c(src_data0) src1 = blocks.vector_source_b(src_data1) ffe = dab.ofdm_ffe_all_in_one(symbol_length, fft_length, num_symbols, alpha, 10) dst0 = blocks.vector_sink_f() self.tb.connect(src0, (ffe,0)) self.tb.connect(src1, (ffe,1)) self.tb.connect(ffe, dst0) self.tb.run() result_data0 = dst0.data() # print expected_result # print result_data0 self.assertFloatTuplesAlmostEqual(expected_result, result_data0, 3)
def __init__(self, dab_params, rx_params, debug=False): """ OFDM time and coarse frequency synchronisation for DAB @param mode DAB mode (1-4) @param debug if True: write data streams out to files """ dp = dab_params rp = rx_params gr.hier_block2.__init__( self, "ofdm_sync_dab", gr.io_signature(1, 1, gr.sizeof_gr_complex), # input signature gr.io_signature2(2, 2, gr.sizeof_gr_complex, 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) # FIXME self.connect(self, self.input) # # null-symbol detection # # (outsourced to detect_zero.py) self.ns_detect = dab.detect_null(dp.ns_length, debug) self.connect(self.input, self.ns_detect) # # fine frequency synchronisation # # the code for fine frequency synchronisation is adapted from # ofdm_sync_ml.py; it abuses the cyclic prefix to find the fine # frequency error, as suggested in "ML Estimation of Timing and # Frequency Offset in OFDM Systems", by Jan-Jaap van de Beek, # Magnus Sandell, Per Ola Börjesson, see # http://www.sm.luth.se/csee/sp/research/report/bsb96r.html self.ffe = dab.ofdm_ffe_all_in_one(dp.symbol_length, dp.fft_length, rp.symbols_for_ffs_estimation, rp.ffs_alpha, int(dp.sample_rate)) if rp.correct_ffe: self.ffs_delay_input_for_correction = blocks.delay( gr.sizeof_gr_complex, dp.symbol_length * rp.symbols_for_ffs_estimation ) # by delaying the input, we can use the ff offset estimation from the first symbol to correct the first symbol itself self.ffs_delay_frame_start = blocks.delay( gr.sizeof_char, dp.symbol_length * rp.symbols_for_ffs_estimation ) # sample the value at the end of the symbol .. self.ffs_nco = analog.frequency_modulator_fc( 1 ) # ffs_sample_and_hold directly outputs phase error per sample self.ffs_mixer = blocks.multiply_cc() # calculate fine frequency error self.connect(self.input, (self.ffe, 0)) self.connect(self.ns_detect, (self.ffe, 1)) if rp.correct_ffe: # do the correction self.connect(self.ffe, self.ffs_nco, (self.ffs_mixer, 0)) self.connect(self.input, self.ffs_delay_input_for_correction, (self.ffs_mixer, 1)) # output - corrected signal and start of DAB frames self.connect(self.ffs_mixer, (self, 0)) self.connect(self.ns_detect, self.ffs_delay_frame_start, (self, 1)) else: # just patch the signal through self.connect(self.ffe, blocks.null_sink(gr.sizeof_float)) self.connect(self.input, (self, 0)) # frame start still needed .. self.connect(self.ns_detect, (self, 1)) if debug: self.connect( self.ffe, blocks.multiply_const_ff(1. / (dp.T * 2 * pi)), blocks.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_fine_freq_err_f.dat"))
def __init__(self, dab_params, rx_params, debug=False): """ OFDM time and coarse frequency synchronisation for DAB @param mode DAB mode (1-4) @param debug if True: write data streams out to files """ dp = dab_params rp = rx_params gr.hier_block2.__init__(self,"ofdm_sync_dab", gr.io_signature(1, 1, gr.sizeof_gr_complex), # input signature gr.io_signature2(2, 2, gr.sizeof_gr_complex, 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) # FIXME self.connect(self, self.input) # # null-symbol detection # # (outsourced to detect_zero.py) self.ns_detect = dab.detect_null(dp.ns_length, debug) self.connect(self.input, self.ns_detect) # # fine frequency synchronisation # # the code for fine frequency synchronisation is adapted from # ofdm_sync_ml.py; it abuses the cyclic prefix to find the fine # frequency error, as suggested in "ML Estimation of Timing and # Frequency Offset in OFDM Systems", by Jan-Jaap van de Beek, # Magnus Sandell, Per Ola Börjesson, see # http://www.sm.luth.se/csee/sp/research/report/bsb96r.html self.ffe = dab.ofdm_ffe_all_in_one(dp.symbol_length, dp.fft_length, rp.symbols_for_ffs_estimation, rp.ffs_alpha, int(dp.sample_rate)) if rp.correct_ffe: self.ffs_delay_input_for_correction = blocks.delay(gr.sizeof_gr_complex, dp.symbol_length*rp.symbols_for_ffs_estimation) # by delaying the input, we can use the ff offset estimation from the first symbol to correct the first symbol itself self.ffs_delay_frame_start = blocks.delay(gr.sizeof_char, dp.symbol_length*rp.symbols_for_ffs_estimation) # sample the value at the end of the symbol .. self.ffs_nco = analog.frequency_modulator_fc(1) # ffs_sample_and_hold directly outputs phase error per sample self.ffs_mixer = blocks.multiply_cc() # calculate fine frequency error self.connect(self.input, (self.ffe, 0)) self.connect(self.ns_detect, (self.ffe, 1)) if rp.correct_ffe: # do the correction self.connect(self.ffe, self.ffs_nco, (self.ffs_mixer, 0)) self.connect(self.input, self.ffs_delay_input_for_correction, (self.ffs_mixer, 1)) # output - corrected signal and start of DAB frames self.connect(self.ffs_mixer, (self, 0)) self.connect(self.ns_detect, self.ffs_delay_frame_start, (self, 1)) else: # just patch the signal through self.connect(self.ffe, blocks.null_sink(gr.sizeof_float)) self.connect(self.input, (self,0)) # frame start still needed .. self.connect(self.ns_detect, (self,1)) if debug: self.connect(self.ffe, blocks.multiply_const_ff(1./(dp.T*2*pi)), blocks.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_fine_freq_err_f.dat"))