def add_mobile_station(self,station_id): """ Adds new receiver mobile station. Station ID must be unique. Initializes BER reference source. """ # Initialize id_src = self._control._id_source dmux = self._data_multiplexer port = self._data_multiplexer_nextport self._data_multiplexer_nextport += 1 # Setup ctrl_port = self._control.add_mobile_station(station_id) options = self._options if options.imgxfer: ref_src = ofdm.imgtransfer_src( options.img ) else: ref_src = ber_reference_source(self._options) if(options.coding): ## Encoder encoder = self._encoder = ofdm.encoder_bb(fo,0) unpack = self._unpack = blocks.unpack_k_bits_bb(2) ## Puncturing if not options.nopunct: puncturing = self._puncturing = puncture_bb(options.subcarriers) #sah = gr.sample_and_hold_bb() #sah_trigger = blocks.vector_source_b([1,0],True) #decim_sah=gr.keep_one_in_n(gr.sizeof_char,2) self.connect(self._bitmap_trigger_puncturing,(puncturing,2)) frametrigger_bitmap_filter = blocks.vector_source_b([1,0],True) bitmap_filter = self._puncturing_bitmap_src_filter = skip(gr.sizeof_char*options.subcarriers,2)# skip_known_symbols(frame_length,subcarriers) bitmap_filter.skip_call(0) #self.connect(self._bitmap_src_puncturing,bitmap_filter,(puncturing,1)) self.connect(self._map_src,bitmap_filter,(puncturing,1)) self.connect(frametrigger_bitmap_filter,(bitmap_filter,1)) #bmt = gr.char_to_float() #self.connect(bitmap_filter,blocks.vector_to_stream(gr.sizeof_char,options.subcarriers), bmt) #log_to_file(self, bmt, "data/bitmap_filter_tx.float") self.connect((self._control,ctrl_port),ref_src,encoder,unpack) if not options.nopunct: self.connect(unpack,puncturing,(dmux,port)) #self.connect(sah_trigger, (sah,1)) else: self.connect(unpack,(dmux,port)) else: self.connect((self._control,ctrl_port),ref_src,(dmux,port)) if options.log and options.coding: log_to_file(self, encoder, "data/encoder_out.char") log_to_file(self, ref_src, "data/reference_data_src.char") log_to_file(self, unpack, "data/encoder_unpacked_out.char") if not options.nopunct: log_to_file(self, puncturing, "data/puncturing_out.char")
def __init__( self, vlen, framelength, no_preambles = 1 ): gr.hier_block2.__init__( self, "ofdm_data_block_filter", gr.io_signature( 1, 1, gr.sizeof_gr_complex * vlen ), gr.io_signature( 1, 1, gr.sizeof_gr_complex * vlen ) ) datablock_filter = ofdm.skip( gr.sizeof_gr_complex * vlen, framelength ) for i in range( no_preambles ): datablock_filter.skip( i ) frame_trigger = ofdm_perfect_frame_trigger( framelength ) self.connect( self, datablock_filter, self ) self.connect( frame_trigger, ( datablock_filter, 1 ) ) self.frame_trigger = frame_trigger
def setup_snr_measurement(self): """ Perform SNR measurement. It uses the data reference from the BER measurement. I.e. if that is not setup, it will be setup. Only data subcarriers that are assigned to the station are considered in the measurement. Note that there is no sink prepared. You need to setup a sink, e.g. with one or more invocation of a "publish.."-function. SNR output is in dB. """ if not self.measuring_ber(): self.setup_ber_measurement() print "Warning: Setup BER Measurement forced" if self.measuring_snr(): return config = station_configuration() vlen = config.subcarriers frame_length = config.frame_length L = config.periodic_parts snr_est_filt = skip(gr.sizeof_gr_complex*vlen,frame_length/2) skipping_symbols = [0] + range(config.training_data.fbmc_no_preambles/2,frame_length/2) for x in skipping_symbols: snr_est_filt.skip_call(x) #snr_est_filt = skip(gr.sizeof_gr_complex*vlen,frame_length) #for x in range(1,frame_length): #snr_est_filt.skip_call(x) ## NOTE HACK!! first preamble is not equalized self.connect(self.symbol_output,snr_est_filt) self.connect(self.frame_trigger,(snr_est_filt,1)) # snrm = self._snr_measurement = milans_snr_estimator( vlen, vlen, L ) # # self.connect(snr_est_filt,snrm) # # if self._options.log: # log_to_file(self, self._snr_measurement, "data/milan_snr.float") #Addition for SINR estimation if self._options.sinr_est: snr_est_filt_2 = skip(gr.sizeof_gr_complex*vlen,frame_length) for x in range(frame_length): if x != config.training_data.channel_estimation_pilot[0]: snr_est_filt_2.skip_call(x) self.connect(self.symbol_output,snr_est_filt_2) self.connect(self.frame_trigger,(snr_est_filt_2,1)) sinrm = self._sinr_measurement = milans_sinr_sc_estimator2( vlen, vlen, L ) self.connect(snr_est_filt,sinrm) self.connect(snr_est_filt_2,(sinrm,1)) if self._options.log: log_to_file(self, (self._sinr_measurement,0), "data/milan_sinr_sc.float") log_to_file(self, (self._sinr_measurement,1), "data/milan_snr.float") else: #snrm = self._snr_measurement = milans_snr_estimator( vlen, vlen, L ) snr_estim = fbmc_snr_estimator( vlen, config.training_data.fbmc_no_preambles/2 -1 ) scsnrdb = filter.single_pole_iir_filter_ff(0.1) snrm = self._snr_measurement = blocks.nlog10_ff(10,1,0) #self.connect(self.snr_est_preamble,scsnrdb,snrm) #terminate_stream(self,self.snr_est_preamble) #self.connect(self.snr_est_preamble,snr_estim,scsnrdb,snrm) #self.connect((snr_estim,1),blocks.null_sink(gr.sizeof_float)) #log_to_file(self, snrm, "data/snrm.float") #log_to_file(self, snrm, "data/snrm.float") collect_preambles = blocks.stream_to_vector(gr.sizeof_gr_complex*vlen, config.training_data.fbmc_no_preambles/2 -1) self.connect(snr_est_filt, collect_preambles) self.connect(collect_preambles,snr_estim,scsnrdb,snrm) self.connect((snr_estim,1),blocks.null_sink(gr.sizeof_float))
def __init__(self, options): gr.hier_block2.__init__(self, "fbmc_receive_path", gr.io_signature(1,1,gr.sizeof_gr_complex), gr.io_signature(0,0,0)) print "This is FBMC receive path 1x1" common_options.defaults(options) config = self.config = station_configuration() config.data_subcarriers = dsubc = options.subcarriers config.cp_length = 0 config.frame_data_blocks = options.data_blocks config._verbose = options.verbose #TODO: update config.fft_length = options.fft_length config.dc_null = options.dc_null config.training_data = default_block_header(dsubc, config.fft_length,config.dc_null,options) config.coding = options.coding config.ber_window = options.ber_window config.periodic_parts = 8 config.frame_id_blocks = 1 # FIXME self._options = copy.copy(options) #FIXME: do we need this? config.fbmc = options.fbmc config.block_length = config.fft_length + config.cp_length config.frame_data_part = config.frame_data_blocks + config.frame_id_blocks config.frame_length = config.training_data.fbmc_no_preambles + 2*config.frame_data_part config.postpro_frame_length = config.frame_data_part + \ config.training_data.no_pilotsyms config.subcarriers = dsubc + \ config.training_data.pilot_subcarriers config.virtual_subcarriers = config.fft_length - config.subcarriers - config.dc_null total_subc = config.subcarriers # check some bounds if config.fft_length < config.subcarriers: raise SystemError, "Subcarrier number must be less than FFT length" if config.fft_length < config.cp_length: raise SystemError, "Cyclic prefix length must be less than FFT length" #self.input = gr.kludge_copy(gr.sizeof_gr_complex) #self.connect( self, self.input ) self.input = self self.ideal = options.ideal self.ideal2 = options.ideal2 ## Inner receiver ## Timing & Frequency Synchronization ## Channel estimation + Equalization ## Phase Tracking for sampling clock frequency offset correction inner_receiver = self.inner_receiver = fbmc_inner_receiver( options, options.log ) self.connect( self.input, inner_receiver ) ofdm_blocks = ( inner_receiver, 2 ) frame_start = ( inner_receiver, 1 ) disp_ctf = ( inner_receiver, 0 ) #self.snr_est_preamble = ( inner_receiver, 3 ) #terminate_stream(self,snr_est_preamble) disp_cfo = ( inner_receiver, 3 ) if self.ideal is False and self.ideal2 is False: self.zmq_probe_freqoff = zeromq.pub_sink(gr.sizeof_float, 1, "tcp://*:5557") self.connect(disp_cfo, self.zmq_probe_freqoff) else: self.connect(disp_cfo, blocks.null_sink(gr.sizeof_float)) # for ID decoder used_id_bits = config.used_id_bits = 8 #TODO: constant in source code! rep_id_bits = config.rep_id_bits = dsubc/used_id_bits #BPSK if options.log: print "rep_id_bits %d" % (rep_id_bits) if dsubc % used_id_bits <> 0: raise SystemError,"Data subcarriers need to be multiple of 10" ## Workaround to avoid periodic structure seed(1) whitener_pn = [randint(0,1) for i in range(used_id_bits*rep_id_bits)] ## NOTE!!! BIG HACK!!! ## first preamble ain't equalized .... ## for Milan's SNR estimator ## Outer Receiver ## Make new inner receiver compatible with old outer receiver ## FIXME: renew outer receiver self.ctf = disp_ctf #frame_sampler = ofdm_frame_sampler(options) frame_sampler = fbmc_frame_sampler(options) self.connect( ofdm_blocks, frame_sampler) self.connect( frame_start, (frame_sampler,1) ) # # ft = [0] * config.frame_length # ft[0] = 1 # # # The next block ensures that only complete frames find their way into # # the old outer receiver. The dynamic frame start trigger is hence # # replaced with a static one, fixed to the frame length. # # frame_sampler = ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, # config.frame_length ) # self.symbol_output = blocks.vector_to_stream( gr.sizeof_gr_complex * total_subc, # config.frame_length ) # delayed_frame_start = blocks.delay( gr.sizeof_char, config.frame_length - 1 ) # damn_static_frame_trigger = blocks.vector_source_b( ft, True ) # # if options.enable_erasure_decision: # frame_gate = vector_sampler( # gr.sizeof_gr_complex * total_subc * config.frame_length, 1 ) # self.connect( ofdm_blocks, frame_sampler, frame_gate, # self.symbol_output ) # else: # self.connect( ofdm_blocks, frame_sampler, self.symbol_output ) # # self.connect( frame_start, delayed_frame_start, ( frame_sampler, 1 ) ) if options.enable_erasure_decision: frame_gate = frame_sampler.frame_gate self.symbol_output = frame_sampler orig_frame_start = frame_start frame_start = (frame_sampler,1) self.frame_trigger = frame_start #terminate_stream(self, self.frame_trigger) ## Pilot block filter pb_filt = self._pilot_block_filter = fbmc_pilot_block_filter() self.connect(self.symbol_output,pb_filt) self.connect(self.frame_trigger,(pb_filt,1)) self.frame_data_trigger = (pb_filt,1) #self.symbol_output = pb_filt #if options.log: #log_to_file(self, pb_filt, "data/pb_filt_out.compl") if config.fbmc: pda_in = pb_filt else: ## Pilot subcarrier filter ps_filt = self._pilot_subcarrier_filter = pilot_subcarrier_filter() self.connect(self.symbol_output,ps_filt) if options.log: log_to_file(self, ps_filt, "data/ps_filt_out.compl") pda_in = ps_filt ## Workaround to avoid periodic structure # for ID decoder seed(1) whitener_pn = [randint(0,1) for i in range(used_id_bits*rep_id_bits)] if not options.enable_erasure_decision: ## ID Block Filter # Filter ID block, skip data blocks id_bfilt = self._id_block_filter = vector_sampler( gr.sizeof_gr_complex * dsubc, 1 ) if not config.frame_id_blocks == 1: raise SystemExit, "# ID Blocks > 1 not supported" self.connect( pda_in , id_bfilt ) self.connect( self.frame_data_trigger, ( id_bfilt, 1 ) ) # trigger #log_to_file( self, id_bfilt, "data/id_bfilt.compl" ) ## ID Demapper and Decoder, soft decision self.id_dec = self._id_decoder = ofdm.coded_bpsk_soft_decoder( dsubc, used_id_bits, whitener_pn ) self.connect( id_bfilt, self.id_dec ) print "Using coded BPSK soft decoder for ID detection" else: # options.enable_erasure_decision: id_bfilt = self._id_block_filter = vector_sampler( gr.sizeof_gr_complex * total_subc, config.frame_id_blocks ) id_bfilt_trig_delay = 0 for x in range( config.frame_length ): if x in config.training_data.pilotsym_pos: id_bfilt_trig_delay += 1 else: break print "Position of ID block within complete frame: %d" %(id_bfilt_trig_delay) assert( id_bfilt_trig_delay > 0 ) # else not supported id_bfilt_trig = blocks.delay( gr.sizeof_char, id_bfilt_trig_delay ) self.connect( ofdm_blocks, id_bfilt ) self.connect( orig_frame_start, id_bfilt_trig, ( id_bfilt, 1 ) ) self.id_dec = self._id_decoder = ofdm.coded_bpsk_soft_decoder( total_subc, used_id_bits, whitener_pn, config.training_data.shifted_pilot_tones ) self.connect( id_bfilt, self.id_dec ) print "Using coded BPSK soft decoder for ID detection" # The threshold block either returns 1.0 if the llr-value from the # id decoder is below the threshold, else 0.0. Hence we convert this # into chars, 0 and 1, and use it as trigger for the sampler. min_llr = ( self.id_dec, 1 ) erasure_threshold = gr.threshold_ff( 10.0, 10.0, 0 ) # FIXME is it the optimal threshold? erasure_dec = gr.float_to_char() id_gate = vector_sampler( gr.sizeof_short, 1 ) ctf_gate = vector_sampler( gr.sizeof_float * total_subc, 1 ) self.connect( self.id_dec , id_gate ) self.connect( self.ctf, ctf_gate ) self.connect( min_llr, erasure_threshold, erasure_dec ) self.connect( erasure_dec, ( frame_gate, 1 ) ) self.connect( erasure_dec, ( id_gate, 1 ) ) self.connect( erasure_dec, ( ctf_gate, 1 ) ) self.id_dec = self._id_decoder = id_gate self.ctf = ctf_gate print "Erasure decision for IDs is enabled" if options.log: id_dec_f = gr.short_to_float() self.connect(self.id_dec,id_dec_f) log_to_file(self, id_dec_f, "data/id_dec_out.float") if options.log: log_to_file(self, id_bfilt, "data/id_blockfilter_out.compl") # TODO: refactor names if options.log: map_src_f = gr.char_to_float(dsubc) self.connect(map_src,map_src_f) log_to_file(self, map_src_f, "data/map_src_out.float") ## Allocation Control if options.static_allocation: #DEBUG if options.coding: mode = 1 # Coding mode 1-9 bitspermode = [0.5,1,1.5,2,3,4,4.5,5,6] # Information bits per mode bitcount_vec = [(int)(config.data_subcarriers*config.frame_data_blocks*bitspermode[mode-1])] bitloading = mode else: bitloading = 1 bitcount_vec = [config.data_subcarriers*config.frame_data_blocks*bitloading] #bitcount_vec = [config.data_subcarriers*config.frame_data_blocks] self.bitcount_src = blocks.vector_source_i(bitcount_vec,True,1) # 0s for ID block, then data #bitloading_vec = [0]*dsubc+[0]*(dsubc/2)+[2]*(dsubc/2) bitloading_vec = [0]*dsubc+[bitloading]*dsubc bitloading_src = blocks.vector_source_b(bitloading_vec,True,dsubc) power_vec = [1]*config.data_subcarriers power_src = blocks.vector_source_f(power_vec,True,dsubc) else: self.allocation_buffer = ofdm.allocation_buffer(config.data_subcarriers, config.frame_data_blocks, "tcp://"+options.tx_hostname+":3333",config.coding) self.bitcount_src = (self.allocation_buffer,0) bitloading_src = (self.allocation_buffer,1) power_src = (self.allocation_buffer,2) self.connect(self.id_dec, self.allocation_buffer) if options.benchmarking: self.allocation_buffer.set_allocation([4]*config.data_subcarriers,[1]*config.data_subcarriers) if options.log: log_to_file(self, self.bitcount_src, "data/bitcount_src_rx.int") log_to_file(self, bitloading_src, "data/bitloading_src_rx.char") log_to_file(self, power_src, "data/power_src_rx.cmplx") log_to_file(self, self.id_dec, "data/id_dec_rx.short") ## Power Deallocator pda = self._power_deallocator = multiply_frame_fc(config.frame_data_part, dsubc) self.connect(pda_in,(pda,0)) self.connect(power_src,(pda,1)) ## Demodulator # if 0: # ac_vector = [0.0+0.0j]*208 # ac_vector[0] = (2*10**(-0.452)) # ac_vector[3] = (10**(-0.651)) # ac_vector[7] = (10**(-1.151)) # csi_vector_inv=abs(numpy.fft.fft(numpy.sqrt(ac_vector)))**2 # dm_csi = numpy.fft.fftshift(csi_vector_inv) # TODO dm_csi = [1]*dsubc # TODO dm_csi = blocks.vector_source_f(dm_csi,True) ## Depuncturer dp_trig = [0]*(config.frame_data_blocks/2) dp_trig[0] = 1 dp_trig = blocks.vector_source_b(dp_trig,True) # TODO if(options.coding): fo=ofdm.fsm(1,2,[91,121]) if options.interleave: int_object=trellis.interleaver(2000,666) deinterlv = trellis.permutation(int_object.K(),int_object.DEINTER(),1,gr.sizeof_float) demod = self._data_demodulator = generic_softdemapper_vcf(dsubc, config.frame_data_part, config.coding) #self.connect(dm_csi,blocks.stream_to_vector(gr.sizeof_float,dsubc),(demod,2)) if(options.ideal): self.connect(dm_csi,blocks.stream_to_vector(gr.sizeof_float,dsubc),(demod,2)) else: dm_csi_filter = self.dm_csi_filter = filter.single_pole_iir_filter_ff(0.01,dsubc) self.connect(self.ctf, self.dm_csi_filter,(demod,2)) #log_to_file(self, dm_csi_filter, "data/softs_csi.float") #self.connect(dm_trig,(demod,3)) else: demod = self._data_demodulator = generic_demapper_vcb(dsubc, config.frame_data_part) if options.benchmarking: # Do receiver benchmarking until the number of frames x symbols are collected self.connect(pda,blocks.head(gr.sizeof_gr_complex*dsubc, options.N*config.frame_data_blocks),demod) else: self.connect(pda,demod) self.connect(bitloading_src,(demod,1)) if(options.coding): ## Depuncturing if not options.nopunct: depuncturing = depuncture_ff(dsubc,0) frametrigger_bitmap_filter = blocks.vector_source_b([1,0],True) self.connect(bitloading_src,(depuncturing,1)) self.connect(dp_trig,(depuncturing,2)) ## Decoding chunkdivisor = int(numpy.ceil(config.frame_data_blocks/5.0)) print "Number of chunks at Viterbi decoder: ", chunkdivisor decoding = self._data_decoder = ofdm.viterbi_combined_fb(fo,dsubc,-1,-1,2,chunkdivisor,[-1,-1,-1,1,1,-1,1,1],ofdm.TRELLIS_EUCLIDEAN) if options.log and options.coding: log_to_file(self, decoding, "data/decoded.char") if not options.nopunct: log_to_file(self, depuncturing, "data/vit_in.float") if not options.nopunct: if options.interleave: self.connect(demod,deinterlv,depuncturing,decoding) else: self.connect(demod,depuncturing,decoding) else: self.connect(demod,decoding) self.connect(self.bitcount_src, multiply_const_ii(1./chunkdivisor), (decoding,1)) if options.scatterplot or options.scatter_plot_before_phase_tracking: if self.ideal2 is False: scatter_vec_elem = self._scatter_vec_elem = ofdm.vector_element(dsubc,40) scatter_s2v = self._scatter_s2v = blocks.stream_to_vector(gr.sizeof_gr_complex,config.frame_data_blocks) scatter_id_filt = skip(gr.sizeof_gr_complex*dsubc,config.frame_data_blocks) scatter_id_filt.skip_call(0) scatter_trig = [0]*config.frame_data_part scatter_trig[0] = 1 scatter_trig = blocks.vector_source_b(scatter_trig,True) self.connect(scatter_trig,(scatter_id_filt,1)) self.connect(scatter_vec_elem,scatter_s2v) if not options.scatter_plot_before_phase_tracking: print "Enabling Scatterplot for data subcarriers" self.connect(pda,scatter_id_filt,scatter_vec_elem) # Work on this #scatter_sink = ofdm.scatterplot_sink(dsubc) #self.connect(pda,scatter_sink) #self.connect(map_src,(scatter_sink,1)) #self.connect(dm_trig,(scatter_sink,2)) #print "Enabled scatterplot gui interface" self.zmq_probe_scatter = zeromq.pub_sink(gr.sizeof_gr_complex,config.frame_data_blocks, "tcp://*:5560") self.connect(scatter_s2v, blocks.keep_one_in_n(gr.sizeof_gr_complex*config.frame_data_blocks,20), self.zmq_probe_scatter) else: print "Enabling Scatterplot for data before phase tracking" inner_rx = inner_receiver.before_phase_tracking #scatter_sink2 = ofdm.scatterplot_sink(dsubc,"phase_tracking") op = copy.copy(options) op.enable_erasure_decision = False new_framesampler = ofdm_frame_sampler(op) self.connect( inner_rx, new_framesampler ) self.connect( orig_frame_start, (new_framesampler,1) ) new_ps_filter = pilot_subcarrier_filter() new_pb_filter = fbmc_pilot_block_filter() self.connect( (new_framesampler,1), (new_pb_filter,1) ) self.connect( new_framesampler, new_pb_filter, new_ps_filter, scatter_id_filt, scatter_vec_elem ) #self.connect( new_ps_filter, scatter_sink2 ) #self.connect( map_src, (scatter_sink2,1)) #self.connect( dm_trig, (scatter_sink2,2)) if options.log: if(options.coding): log_to_file(self, demod, "data/data_stream_out.float") else: data_f = gr.char_to_float() self.connect(demod,data_f) log_to_file(self, data_f, "data/data_stream_out.float") if options.sfo_feedback: used_id_bits = 8 rep_id_bits = config.data_subcarriers/used_id_bits seed(1) whitener_pn = [randint(0,1) for i in range(used_id_bits*rep_id_bits)] id_enc = ofdm.repetition_encoder_sb(used_id_bits,rep_id_bits,whitener_pn) self.connect( self.id_dec, id_enc ) id_mod = ofdm_bpsk_modulator(dsubc) self.connect( id_enc, id_mod ) id_mod_conj = gr.conjugate_cc(dsubc) self.connect( id_mod, id_mod_conj ) id_mult = blocks.multiply_vcc(dsubc) self.connect( id_bfilt, ( id_mult,0) ) self.connect( id_mod_conj, ( id_mult,1) ) # id_mult_avg = filter.single_pole_iir_filter_cc(0.01,dsubc) # self.connect( id_mult, id_mult_avg ) id_phase = gr.complex_to_arg(dsubc) self.connect( id_mult, id_phase ) log_to_file( self, id_phase, "data/id_phase.float" ) est=ofdm.LS_estimator_straight_slope(dsubc) self.connect(id_phase,est) slope=blocks.multiply_const_ff(1e6/2/3.14159265) self.connect( (est,0), slope ) log_to_file( self, slope, "data/slope.float" ) log_to_file( self, (est,1), "data/offset.float" ) # ------------------------------------------------------------------------ # # Display some information about the setup if config._verbose: self._print_verbage() ## debug logging ## if options.log: # log_to_file(self,self.ofdm_symbols,"data/unequalized_rx_ofdm_symbols.compl") # log_to_file(self,self.ofdm_symbols,"data/unequalized_rx_ofdm_symbols.float",mag=True) fftlen = 256 my_window = window.hamming(fftlen) #.blackmanharris(fftlen) rxs_sampler = vector_sampler(gr.sizeof_gr_complex,fftlen) rxs_sampler_vect = concatenate([[1],[0]*49]) rxs_trigger = blocks.vector_source_b(rxs_sampler_vect.tolist(),True) rxs_window = blocks.multiply_const_vcc(my_window) rxs_spectrum = gr.fft_vcc(fftlen,True,[],True) rxs_mag = gr.complex_to_mag(fftlen) rxs_avg = filter.single_pole_iir_filter_ff(0.01,fftlen) #rxs_logdb = blocks.nlog10_ff(20.0,fftlen,-20*log10(fftlen)) rxs_logdb = gr.kludge_copy( gr.sizeof_float * fftlen ) rxs_decimate_rate = gr.keep_one_in_n(gr.sizeof_float*fftlen,1) self.connect(rxs_trigger,(rxs_sampler,1)) self.connect(self.input,rxs_sampler,rxs_window, rxs_spectrum,rxs_mag,rxs_avg,rxs_logdb, rxs_decimate_rate) log_to_file( self, rxs_decimate_rate, "data/psd_input.float" ) #output branches self.publish_rx_performance_measure()
def add_mobile_station(self, station_id): """ Adds new receiver mobile station. Station ID must be unique. Initializes BER reference source. """ # Initialize id_src = self._control._id_source dmux = self._data_multiplexer port = self._data_multiplexer_nextport self._data_multiplexer_nextport += 1 # Setup ctrl_port = self._control.add_mobile_station(station_id) options = self._options if options.imgxfer: ref_src = ofdm.imgtransfer_src(options.img) else: ref_src = ber_reference_source(self._options) if (options.coding): ## Encoder encoder = self._encoder = ofdm.encoder_bb(fo, 0) unpack = self._unpack = blocks.unpack_k_bits_bb(2) ## Puncturing if not options.nopunct: puncturing = self._puncturing = puncture_bb( options.subcarriers) #sah = gr.sample_and_hold_bb() #sah_trigger = blocks.vector_source_b([1,0],True) #decim_sah=gr.keep_one_in_n(gr.sizeof_char,2) self.connect(self._bitmap_trigger_puncturing, (puncturing, 2)) frametrigger_bitmap_filter = blocks.vector_source_b([1, 0], True) bitmap_filter = self._puncturing_bitmap_src_filter = skip( gr.sizeof_char * options.subcarriers, 2) # skip_known_symbols(frame_length,subcarriers) bitmap_filter.skip_call(0) #self.connect(self._bitmap_src_puncturing,bitmap_filter,(puncturing,1)) self.connect(self._map_src, bitmap_filter, (puncturing, 1)) self.connect(frametrigger_bitmap_filter, (bitmap_filter, 1)) #bmt = gr.char_to_float() #self.connect(bitmap_filter,blocks.vector_to_stream(gr.sizeof_char,options.subcarriers), bmt) #log_to_file(self, bmt, "data/bitmap_filter_tx.float") self.connect((self._control, ctrl_port), ref_src, encoder, unpack) if not options.nopunct: self.connect(unpack, puncturing, (dmux, port)) #self.connect(sah_trigger, (sah,1)) else: self.connect(unpack, (dmux, port)) else: self.connect((self._control, ctrl_port), ref_src, (dmux, port)) if options.log and options.coding: log_to_file(self, encoder, "data/encoder_out.char") log_to_file(self, ref_src, "data/reference_data_src.char") log_to_file(self, unpack, "data/encoder_unpacked_out.char") if not options.nopunct: log_to_file(self, puncturing, "data/puncturing_out.char")
def __init__(self, subc, vlen, ss): gr.hier_block2.__init__( self, "new_snr_estimator", gr.io_signature(1, 1, gr.sizeof_gr_complex * vlen), gr.io_signature(1, 1, gr.sizeof_float)) print "Created Milan's SNR estimator" trigger = [0] * vlen trigger[0] = 1 u = range(vlen / ss * (ss - 1)) zeros_ind = map(lambda z: z + 1 + z / (ss - 1), u) skip1 = skip(gr.sizeof_gr_complex, vlen) for x in zeros_ind: skip1.skip(x) #print "skipped zeros",zeros_ind v = range(vlen / ss) ones_ind = map(lambda z: z * ss, v) skip2 = skip(gr.sizeof_gr_complex, vlen) for x in ones_ind: skip2.skip(x) #print "skipped ones",ones_ind v2s = gr.vector_to_stream(gr.sizeof_gr_complex, vlen) s2v1 = gr.stream_to_vector(gr.sizeof_gr_complex, vlen / ss) trigger_src_1 = gr.vector_source_b(trigger, True) s2v2 = gr.stream_to_vector(gr.sizeof_gr_complex, vlen / ss * (ss - 1)) trigger_src_2 = gr.vector_source_b(trigger, True) mag_sq_ones = gr.complex_to_mag_squared(vlen / ss) mag_sq_zeros = gr.complex_to_mag_squared(vlen / ss * (ss - 1)) filt_ones = gr.single_pole_iir_filter_ff(0.1, vlen / ss) filt_zeros = gr.single_pole_iir_filter_ff(0.1, vlen / ss * (ss - 1)) sum_ones = vector_sum_vff(vlen / ss) sum_zeros = vector_sum_vff(vlen / ss * (ss - 1)) D = gr.divide_ff() P = gr.multiply_ff() mult1 = gr.multiply_const_ff(ss - 1.0) add1 = gr.add_const_ff(-1.0) mult2 = gr.multiply_const_ff(1. / ss) scsnrdb = gr.nlog10_ff(10, 1, 0) filt_end = gr.single_pole_iir_filter_ff(0.1) self.connect(self, v2s, skip1, s2v1, mag_sq_ones, filt_ones, sum_ones) self.connect(trigger_src_1, (skip1, 1)) self.connect(v2s, skip2, s2v2, mag_sq_zeros, filt_zeros, sum_zeros) self.connect(trigger_src_2, (skip2, 1)) self.connect(sum_ones, D) self.connect(sum_zeros, (D, 1)) self.connect(D, mult1, add1, mult2) self.connect(mult2, scsnrdb, filt_end, self)
def __init__(self, subc, vlen, ss): gr.hier_block2.__init__( self, "new_snr_estimator", gr.io_signature(2, 2, gr.sizeof_gr_complex * vlen), #gr.io_signature2(2,2,gr.sizeof_float*vlen,gr.sizeof_float*vlen/ss*(ss-1))) gr.io_signature2(2, 2, gr.sizeof_float * vlen, gr.sizeof_float)) print "Created Milan's SINR estimator" trigger = [0] * vlen trigger[0] = 1 v = range(vlen / ss) ones_ind = map(lambda z: z * ss, v) skip2_pr0 = skip(gr.sizeof_gr_complex, vlen) skip2_pr1 = skip(gr.sizeof_gr_complex, vlen) for x in ones_ind: skip2_pr0.skip(x) skip2_pr1.skip(x) #print "skipped ones",ones_ind v2s_pr0 = gr.vector_to_stream(gr.sizeof_gr_complex, vlen) v2s_pr1 = gr.vector_to_stream(gr.sizeof_gr_complex, vlen) s2v2_pr0 = gr.stream_to_vector(gr.sizeof_gr_complex, vlen / ss * (ss - 1)) trigger_src_2_pr0 = gr.vector_source_b(trigger, True) s2v2_pr1 = gr.stream_to_vector(gr.sizeof_gr_complex, vlen / ss * (ss - 1)) trigger_src_2_pr1 = gr.vector_source_b(trigger, True) mag_sq_zeros_pr0 = gr.complex_to_mag_squared(vlen / ss * (ss - 1)) mag_sq_zeros_pr1 = gr.complex_to_mag_squared(vlen / ss * (ss - 1)) filt_zeros_pr0 = gr.single_pole_iir_filter_ff(0.01, vlen / ss * (ss - 1)) filt_zeros_pr1 = gr.single_pole_iir_filter_ff(0.01, vlen / ss * (ss - 1)) v1 = vlen / ss * (ss - 1) vevc1 = [-1] * v1 neg_nomin_z = gr.multiply_const_vff(vevc1) div_z = gr.divide_ff(vlen / ss * (ss - 1)) on_zeros = gr.add_const_vff(vevc1) sum_zeros = add_vff(vlen / ss * (ss - 1)) # For average sum_all = vector_sum_vff(vlen) mult = gr.multiply_const_ff(1. / vlen) scsnr_db_av = gr.nlog10_ff(10, 1, 0) filt_end_av = gr.single_pole_iir_filter_ff(0.1) self.connect((self, 0), v2s_pr0, skip2_pr0, s2v2_pr0, mag_sq_zeros_pr0, filt_zeros_pr0) self.connect(trigger_src_2_pr0, (skip2_pr0, 1)) self.connect((self, 1), v2s_pr1, skip2_pr1, s2v2_pr1, mag_sq_zeros_pr1, filt_zeros_pr1) self.connect(trigger_src_2_pr1, (skip2_pr1, 1)) # On zeros self.connect(filt_zeros_pr1, (sum_zeros, 0)) self.connect(filt_zeros_pr0, neg_nomin_z, (sum_zeros, 1)) self.connect(sum_zeros, div_z) self.connect(filt_zeros_pr0, (div_z, 1)) scsnr_db = gr.nlog10_ff(10, vlen, 0) filt_end = gr.single_pole_iir_filter_ff(0.1, vlen) dd = [] for i in range(vlen / ss): dd.extend([i * ss]) #print dd interpolator = sinr_interpolator(vlen, ss, dd) self.connect(div_z, interpolator, filt_end, scsnr_db, self) self.connect(interpolator, sum_all, mult, scsnr_db_av, filt_end_av, (self, 1))
def __init__(self, subc, vlen, ss): gr.hier_block2.__init__(self, "new_snr_estimator", gr.io_signature(1,1,gr.sizeof_gr_complex*vlen), gr.io_signature(1,1,gr.sizeof_float)) print "Created Milan's SNR estimator" trigger = [0]*vlen trigger[0] = 1 u = range (vlen/ss*(ss-1)) zeros_ind= map(lambda z: z+1+z/(ss-1),u) skip1 = skip(gr.sizeof_gr_complex,vlen) for x in zeros_ind: skip1.skip(x) #print "skipped zeros",zeros_ind v = range (vlen/ss) ones_ind= map(lambda z: z*ss,v) skip2 = skip(gr.sizeof_gr_complex,vlen) for x in ones_ind: skip2.skip(x) #print "skipped ones",ones_ind v2s = gr.vector_to_stream(gr.sizeof_gr_complex,vlen) s2v1 = gr.stream_to_vector(gr.sizeof_gr_complex,vlen/ss) trigger_src_1 = gr.vector_source_b(trigger,True) s2v2 = gr.stream_to_vector(gr.sizeof_gr_complex,vlen/ss*(ss-1)) trigger_src_2 = gr.vector_source_b(trigger,True) mag_sq_ones = gr.complex_to_mag_squared(vlen/ss) mag_sq_zeros = gr.complex_to_mag_squared(vlen/ss*(ss-1)) filt_ones = gr.single_pole_iir_filter_ff(0.1,vlen/ss) filt_zeros = gr.single_pole_iir_filter_ff(0.1,vlen/ss*(ss-1)) sum_ones = vector_sum_vff(vlen/ss) sum_zeros = vector_sum_vff(vlen/ss*(ss-1)) D = gr.divide_ff() P = gr.multiply_ff() mult1 = gr.multiply_const_ff(ss-1.0) add1 = gr.add_const_ff(-1.0) mult2 = gr.multiply_const_ff(1./ss) scsnrdb = gr.nlog10_ff(10,1,0) filt_end = gr.single_pole_iir_filter_ff(0.1) self.connect(self,v2s,skip1,s2v1,mag_sq_ones,filt_ones,sum_ones) self.connect(trigger_src_1,(skip1,1)) self.connect(v2s,skip2,s2v2,mag_sq_zeros,filt_zeros,sum_zeros) self.connect(trigger_src_2,(skip2,1)) self.connect(sum_ones,D) self.connect(sum_zeros,(D,1)) self.connect(D,mult1,add1,mult2) self.connect(mult2,scsnrdb,filt_end,self)
def __init__(self, subc, vlen, ss): gr.hier_block2.__init__(self, "new_snr_estimator", gr.io_signature(2,2,gr.sizeof_gr_complex*vlen), #gr.io_signature2(2,2,gr.sizeof_float*vlen,gr.sizeof_float*vlen/ss*(ss-1))) gr.io_signature2(2,2,gr.sizeof_float*vlen,gr.sizeof_float)) print "Created Milan's SINR estimator" trigger = [0]*vlen trigger[0] = 1 v = range (vlen/ss) ones_ind= map(lambda z: z*ss,v) skip2_pr0 = skip(gr.sizeof_gr_complex,vlen) skip2_pr1 = skip(gr.sizeof_gr_complex,vlen) for x in ones_ind: skip2_pr0.skip(x) skip2_pr1.skip(x) #print "skipped ones",ones_ind v2s_pr0 = gr.vector_to_stream(gr.sizeof_gr_complex,vlen) v2s_pr1 = gr.vector_to_stream(gr.sizeof_gr_complex,vlen) s2v2_pr0 = gr.stream_to_vector(gr.sizeof_gr_complex,vlen/ss*(ss-1)) trigger_src_2_pr0 = gr.vector_source_b(trigger,True) s2v2_pr1 = gr.stream_to_vector(gr.sizeof_gr_complex,vlen/ss*(ss-1)) trigger_src_2_pr1 = gr.vector_source_b(trigger,True) mag_sq_zeros_pr0 = gr.complex_to_mag_squared(vlen/ss*(ss-1)) mag_sq_zeros_pr1 = gr.complex_to_mag_squared(vlen/ss*(ss-1)) filt_zeros_pr0 = gr.single_pole_iir_filter_ff(0.01,vlen/ss*(ss-1)) filt_zeros_pr1 = gr.single_pole_iir_filter_ff(0.01,vlen/ss*(ss-1)) v1 = vlen/ss*(ss-1) vevc1 =[-1]*v1 neg_nomin_z = gr.multiply_const_vff(vevc1) div_z=gr.divide_ff(vlen/ss*(ss-1)) on_zeros = gr.add_const_vff(vevc1) sum_zeros = add_vff(vlen/ss*(ss-1)) # For average sum_all = vector_sum_vff(vlen) mult = gr.multiply_const_ff(1./vlen) scsnr_db_av = gr.nlog10_ff(10,1,0) filt_end_av = gr.single_pole_iir_filter_ff(0.1) self.connect((self,0),v2s_pr0,skip2_pr0,s2v2_pr0,mag_sq_zeros_pr0,filt_zeros_pr0) self.connect(trigger_src_2_pr0,(skip2_pr0,1)) self.connect((self,1),v2s_pr1,skip2_pr1,s2v2_pr1,mag_sq_zeros_pr1,filt_zeros_pr1) self.connect(trigger_src_2_pr1,(skip2_pr1,1)) # On zeros self.connect(filt_zeros_pr1,(sum_zeros,0)) self.connect(filt_zeros_pr0,neg_nomin_z,(sum_zeros,1)) self.connect(sum_zeros,div_z) self.connect(filt_zeros_pr0,(div_z,1)) scsnr_db = gr.nlog10_ff(10,vlen,0) filt_end = gr.single_pole_iir_filter_ff(0.1,vlen) dd = [] for i in range (vlen/ss): dd.extend([i*ss]) #print dd interpolator = sinr_interpolator(vlen, ss,dd) self.connect(div_z,interpolator,filt_end,scsnr_db,self) self.connect(interpolator,sum_all,mult,scsnr_db_av,filt_end_av,(self,1))