def __init__(self): gr.top_block.__init__(self) usage = "%prog: [options] samples_file" parser = OptionParser(option_class=eng_option, usage=usage) (options, args) = parser.parse_args () if len(args)<1: # print "using gaussian noise as source" # self.sigsrc = gr.noise_source_c(gr.GR_GAUSSIAN,10e6) print "using repeating random vector as source" self.sigsrc = blocks.vector_source_c([10e6*(random.random() + 1j*random.random()) for i in range(0,100000)],True) self.src = blocks.throttle( gr.sizeof_gr_complex,2048000) self.connect(self.sigsrc, self.src) else: filename = args[0] print "using samples from file " + filename self.src = blocks.file_source(gr.sizeof_gr_complex, filename, False) dp = parameters.dab_parameters(1) rp = parameters.receiver_parameters(1) self.sync_dab = ofdm_sync_dab(dp, rp, False) self.nop0 = blocks.nop(gr.sizeof_gr_complex) self.nop1 = blocks.nop(gr.sizeof_char) self.connect(self.src, self.sync_dab, self.nop0) self.connect((self.sync_dab,1), self.nop1)
def __init__(self): gr.top_block.__init__(self) usage = "%prog: [options] samples_file" parser = OptionParser(option_class=eng_option, usage=usage) (options, args) = parser.parse_args() if len(args) < 1: # print "using gaussian noise as source" # self.sigsrc = gr.noise_source_c(gr.GR_GAUSSIAN,10e6) print "using repeating random vector as source" self.sigsrc = blocks.vector_source_c([ 10e6 * (random.random() + 1j * random.random()) for i in range(0, 100000) ], True) self.src = blocks.throttle(gr.sizeof_gr_complex, 2048000) self.connect(self.sigsrc, self.src) else: filename = args[0] print "using samples from file " + filename self.src = blocks.file_source(gr.sizeof_gr_complex, filename, False) dp = parameters.dab_parameters(1) rp = parameters.receiver_parameters(1) self.sync_dab = ofdm_sync_dab(dp, rp, False) self.nop0 = blocks.nop(gr.sizeof_gr_complex) self.nop1 = blocks.nop(gr.sizeof_char) self.connect(self.src, self.sync_dab, self.nop0) self.connect((self.sync_dab, 1), self.nop1)
def __init__(self): gr.top_block.__init__(self) usage = "%prog: [options] samples_file" parser = OptionParser(option_class=eng_option, usage=usage) parser.add_option("-m", "--dab-mode", type="int", default=1, help="DAB mode [default=%default]") parser.add_option("-F", "--filter-input", action="store_true", default=False, help="Enable FFT filter at input") parser.add_option("-s", "--resample-fixed", type="float", default=1, help="resample by a fixed factor (fractional interpolation)") parser.add_option("-S", "--autocorrect-sample-rate", action="store_true", default=False, help="Estimate sample rate offset and resample (dynamic fractional interpolation)") parser.add_option('-r', '--sample-rate', type="int", default=2048000, help="Use non-standard sample rate (default=%default)") parser.add_option('-e', '--equalize-magnitude', action="store_true", default=False, help="Enable individual carrier magnitude equalizer") parser.add_option('-d', '--debug', action="store_true", default=False, help="Write output to files") parser.add_option('-v', '--verbose', action="store_true", default=False, help="Print status messages") (options, args) = parser.parse_args () dp = parameters.dab_parameters(options.dab_mode, verbose=options.verbose, sample_rate=options.sample_rate) rp = parameters.receiver_parameters(options.dab_mode, input_fft_filter=options.filter_input, autocorrect_sample_rate=options.autocorrect_sample_rate, sample_rate_correction_factor=options.resample_fixed, equalize_magnitude=options.equalize_magnitude, verbose=options.verbose) if len(args)<1: if options.verbose: print "-> using repeating random vector as source" self.sigsrc = gr.vector_source_c([10e6*(random.random() + 1j*random.random()) for i in range(0,100000)],True) self.ns_simulate = gr.vector_source_c([0.01]*dp.ns_length+[1]*dp.symbols_per_frame*dp.symbol_length,1) self.mult = gr.multiply_cc() # simulate null symbols ... self.src = gr.throttle( gr.sizeof_gr_complex,2048000) self.connect(self.sigsrc, (self.mult, 0)) self.connect(self.ns_simulate, (self.mult, 1)) self.connect(self.mult, self.src) else: filename = args[0] if options.verbose: print "-> using samples from file " + filename self.src = gr.file_source(gr.sizeof_gr_complex, filename, False) self.dab_demod = ofdm.ofdm_demod(dp, rp, debug=options.debug, verbose=options.verbose) self.connect(self.src, self.dab_demod) # sink output to nowhere self.nop0 = gr.nop(gr.sizeof_char*dp.num_carriers/4) self.nop1 = gr.nop(gr.sizeof_char) self.connect((self.dab_demod,0),self.nop0) self.connect((self.dab_demod,1),self.nop1)
def __init__(self): gr.top_block.__init__(self) usage = "%prog: [options] samples_file" parser = OptionParser(option_class=eng_option, usage=usage) parser.add_option("-m", "--dab-mode", type="int", default=1, help="DAB mode [default=%default]") parser.add_option("-F", "--filter-input", action="store_true", default=False, help="Enable FFT filter at input") parser.add_option( "-s", "--resample-fixed", type="float", default=1, help="resample by a fixed factor (fractional interpolation)") parser.add_option( "-S", "--autocorrect-sample-rate", action="store_true", default=False, help= "Estimate sample rate offset and resample (dynamic fractional interpolation)" ) parser.add_option( '-r', '--sample-rate', type="int", default=2048000, help="Use non-standard sample rate (default=%default)") parser.add_option('-e', '--equalize-magnitude', action="store_true", default=False, help="Enable individual carrier magnitude equalizer") parser.add_option('-d', '--debug', action="store_true", default=False, help="Write output to files") parser.add_option('-v', '--verbose', action="store_true", default=False, help="Print status messages") (options, args) = parser.parse_args() dp = parameters.dab_parameters(options.dab_mode, verbose=options.verbose, sample_rate=options.sample_rate) rp = parameters.receiver_parameters( options.dab_mode, input_fft_filter=options.filter_input, autocorrect_sample_rate=options.autocorrect_sample_rate, sample_rate_correction_factor=options.resample_fixed, equalize_magnitude=options.equalize_magnitude, verbose=options.verbose) if len(args) < 1: if options.verbose: print "-> using repeating random vector as source" self.sigsrc = blocks.vector_source_c([ 10e6 * (random.random() + 1j * random.random()) for i in range(0, 100000) ], True) self.ns_simulate = blocks.vector_source_c( [0.01] * dp.ns_length + [1] * dp.symbols_per_frame * dp.symbol_length, 1) self.mult = blocks.multiply_cc() # simulate null symbols ... self.src = blocks.throttle(gr.sizeof_gr_complex, 2048000) self.connect(self.sigsrc, (self.mult, 0)) self.connect(self.ns_simulate, (self.mult, 1)) self.connect(self.mult, self.src) else: filename = args[0] if options.verbose: print "-> using samples from file " + filename self.src = blocks.file_source(gr.sizeof_gr_complex, filename, False) self.dab_demod = ofdm.ofdm_demod(dp, rp, debug=options.debug, verbose=options.verbose) self.connect(self.src, self.dab_demod) # sink output to nowhere self.nop0 = blocks.nop(gr.sizeof_char * dp.num_carriers / 4) self.nop1 = blocks.nop(gr.sizeof_char) self.connect((self.dab_demod, 0), self.nop0) self.connect((self.dab_demod, 1), self.nop1)
def __init__(self, mode, 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 """ if mode < 1 or mode > 4: raise ValueError, "Invalid DAB mode: " + str( mode) + " (modes 1-4 exist)" # get the correct DAB parameters dp = parameters.dab_parameters(mode) rp = parameters.receiver_parameters(mode) 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.connect(self, self.input) # # null-symbol detection # # (outsourced to detect_zero.py) self.ns_detect = detect_null.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.ffs_delay = gr.delay(gr.sizeof_gr_complex, dp.fft_length) self.ffs_conj = gr.conjugate_cc() self.ffs_mult = gr.multiply_cc() # self.ffs_moving_sum = gr.fir_filter_ccf(1, [1]*dp.cp_length) self.ffs_moving_sum = dab_swig.moving_sum_cc(dp.cp_length) self.ffs_angle = gr.complex_to_arg() self.ffs_angle_scale = gr.multiply_const_ff(1. / dp.fft_length) self.ffs_delay_sample_and_hold = gr.delay( gr.sizeof_char, dp.symbol_length) # sample the value at the end of the symbol .. self.ffs_sample_and_hold = gr.sample_and_hold_ff() self.ffs_delay_input_for_correction = gr.delay( gr.sizeof_gr_complex, dp.symbol_length ) # by delaying the input, we can use the ff offset estimation from the first symbol to correct the first symbol itself self.ffs_nco = gr.frequency_modulator_fc( 1) # ffs_sample_and_hold directly outputs phase error per sample self.ffs_mixer = gr.multiply_cc() # calculate fine frequency error self.connect(self.input, self.ffs_conj, self.ffs_mult) self.connect(self.input, self.ffs_delay, (self.ffs_mult, 1)) self.connect(self.ffs_mult, self.ffs_moving_sum, self.ffs_angle) # only use the value from the first half of the first symbol self.connect(self.ffs_angle, self.ffs_angle_scale, (self.ffs_sample_and_hold, 0)) self.connect(self.ns_detect, self.ffs_delay_sample_and_hold, (self.ffs_sample_and_hold, 1)) # do the correction self.connect(self.ffs_sample_and_hold, 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.ffs_delay_sample_and_hold, (self, 1)) if debug: self.connect( self.ffs_angle, gr.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_ffs_angle.dat")) self.connect( self.ffs_sample_and_hold, gr.multiply_const_ff(1. / (dp.T * 2 * pi)), gr.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_fine_freq_err_f.dat")) self.connect( self.ffs_mixer, gr.file_sink(gr.sizeof_gr_complex, "debug/ofdm_sync_dab_fine_freq_corrected_c.dat"))
def __init__(self, mode, 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 """ if mode<1 or mode>4: raise ValueError, "Invalid DAB mode: "+str(mode)+" (modes 1-4 exist)" # get the correct DAB parameters dp = parameters.dab_parameters(mode) rp = parameters.receiver_parameters(mode) 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.connect(self, self.input) # # null-symbol detection # # (outsourced to detect_zero.py) self.ns_detect = detect_null.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.ffs_delay = gr.delay(gr.sizeof_gr_complex, dp.fft_length) self.ffs_conj = gr.conjugate_cc() self.ffs_mult = gr.multiply_cc() # self.ffs_moving_sum = gr.fir_filter_ccf(1, [1]*dp.cp_length) self.ffs_moving_sum = dab_swig.moving_sum_cc(dp.cp_length) self.ffs_angle = gr.complex_to_arg() self.ffs_angle_scale = gr.multiply_const_ff(1./dp.fft_length) self.ffs_delay_sample_and_hold = gr.delay(gr.sizeof_char, dp.symbol_length) # sample the value at the end of the symbol .. self.ffs_sample_and_hold = gr.sample_and_hold_ff() self.ffs_delay_input_for_correction = gr.delay(gr.sizeof_gr_complex, dp.symbol_length) # by delaying the input, we can use the ff offset estimation from the first symbol to correct the first symbol itself self.ffs_nco = gr.frequency_modulator_fc(1) # ffs_sample_and_hold directly outputs phase error per sample self.ffs_mixer = gr.multiply_cc() # calculate fine frequency error self.connect(self.input, self.ffs_conj, self.ffs_mult) self.connect(self.input, self.ffs_delay, (self.ffs_mult, 1)) self.connect(self.ffs_mult, self.ffs_moving_sum, self.ffs_angle) # only use the value from the first half of the first symbol self.connect(self.ffs_angle, self.ffs_angle_scale, (self.ffs_sample_and_hold, 0)) self.connect(self.ns_detect, self.ffs_delay_sample_and_hold, (self.ffs_sample_and_hold, 1)) # do the correction self.connect(self.ffs_sample_and_hold, 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.ffs_delay_sample_and_hold, (self, 1)) if debug: self.connect(self.ffs_angle, gr.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_ffs_angle.dat")) self.connect(self.ffs_sample_and_hold, gr.multiply_const_ff(1./(dp.T*2*pi)), gr.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_fine_freq_err_f.dat")) self.connect(self.ffs_mixer, gr.file_sink(gr.sizeof_gr_complex, "debug/ofdm_sync_dab_fine_freq_corrected_c.dat"))