def test_001(self): frames = 5 config = station_configuration() config.subcarriers = 12 config.data_subcarriers = 8 config.training_data = dummy() config.training_data.shifted_pilot_tones = [1,4,8,11] data = [1.0] * config.subcarriers for x in config.training_data.shifted_pilot_tones: data[x] = 2.0 data = concatenate([data]*frames) ref = [1.0]*(config.data_subcarriers*frames) src = gr.vector_source_c(data) s2v = gr.stream_to_vector(gr.sizeof_gr_complex,config.subcarriers) dst = gr.vector_sink_c() v2s = gr.vector_to_stream(gr.sizeof_gr_complex,config.data_subcarriers) uut = preambles.pilot_subcarrier_filter() self.fg.connect(src,s2v,uut,v2s,dst) self.fg.run() self.assertEqual(ref,list(dst.data()))
def setup_imgtransfer_sink(self): demod = self._data_demodulator config = station_configuration() port = self._rx_control.add_mobile_station(config.rx_station_id) bc_src = (self._rx_control,port) UDP_PACKET_SIZE = 4096*8 imgtransfersink = ofdm.imgtransfer_sink( UDP_PACKET_SIZE, "localhost", 0, "localhost", 45454, self._options.img, False ) #imgtransfersink = ofdm.imgtransfer_sink(UDP_PACKET_SIZE,self._options.img, # False) #udpsink = gr.udp_sink( 1, "127.0.0.1", 0, "127.0.0.1", 45454, # UDP_PACKET_SIZE ) #udpsink = blocks.null_sink( gr.sizeof_char ) self.connect( bc_src, ( imgtransfersink, 0 ) ) self.connect( demod, ( imgtransfersink, 1 ) ) #self.connect( imgtransfersink, udpsink ) self._measuring_ber = True self._img_xfer_inprog = True self.imgxfer_sink = imgtransfersink self._ber_measuring_tool = None
def test_001(self): frames = 5 config = station_configuration() config.subcarriers = 12 config.data_subcarriers = 8 config.training_data = dummy() config.training_data.shifted_pilot_tones = [1, 4, 8, 11] data = [1.0] * config.subcarriers for x in config.training_data.shifted_pilot_tones: data[x] = 2.0 data = concatenate([data] * frames) ref = [1.0] * (config.data_subcarriers * frames) src = gr.vector_source_c(data) s2v = gr.stream_to_vector(gr.sizeof_gr_complex, config.subcarriers) dst = gr.vector_sink_c() v2s = gr.vector_to_stream(gr.sizeof_gr_complex, config.data_subcarriers) uut = preambles.pilot_subcarrier_filter() self.fg.connect(src, s2v, uut, v2s, dst) self.fg.run() self.assertEqual(ref, list(dst.data()))
def setup_ber_measurement(self): """ Setup bit error rate measurement blocks. Using the decoded ID, a reference source identical to that in the transmitter reproduces the sent data. A measurement block compares the demodulated stream and the reference. It counts the bit errors within the given window (specified at the command line). Access the BER value via get_ber(). """ if self.measuring_ber(): return if(self._options.coding): decoding = self._data_decoder else: demod = self._data_demodulator config = station_configuration() ## Data Reference Source dref_src = self._data_reference_source = ber_reference_source(self._options) self.connect(self.id_dec,(dref_src,0)) self.connect(self.bitcount_src,(dref_src,1)) ## BER Measuring Tool ber_mst = self._ber_measuring_tool = ber_measurement(int(config.ber_window)) if(self._options.coding): self.connect(decoding,ber_mst) else: self.connect(demod,ber_mst) self.connect(dref_src,(ber_mst,1)) self._measuring_ber = True if self._options.enable_ber2: ber2 = ofdm.bit_position_dependent_ber( "BER2_" + strftime("%Y%m%d%H%M%S",gmtime()) ) if(self._options.coding): self.connect( decoding, ( ber2, 1 ) ) else: self.connect( demod, ( ber2, 1 ) ) self.connect( dref_src, ( ber2, 0 ) ) self.connect( bc_src, ( ber2, 2 ) ) if self._options.log: log_to_file(self, ber_mst, "data/ber_out.float") data_f = gr.char_to_float() self.connect(dref_src,data_f) log_to_file(self, data_f, "data/dataref_out.float")
def publish_ber_measurement(self,unique_id): """ Install CORBA servant to allow remote access to the BER value. The servant is identified with the unique_id parameter. It is registered at the NameService as "ofdm_ti."+unique_id. If not setup previously, the measurement setup is invoked. """ self.setup_ber_measurement() config = station_configuration() uid = str(unique_id) max_buffered_windows = 3000 # FIXME: find better solution dist = config.ber_window
def add_mobile_station(self,uid): """ Register mobile station with unique id \param uid Provides a new bitcount stream for this id. The next free port of the control block is used. Returns assigned output port. """ config = station_configuration() port = self.cur_port self.cur_port += 1 bc_src = corba_bitcount_src_si(uid,self.evchan,self.ns_ip,self.ns_port,self.coding) self.connect(self._id_source,bc_src,(self,port)) return port
def add_mobile_station(self, uid): """ Register mobile station with unique id \param uid Provides a new bitcount stream for this id. The next free port of the control block is used. Returns assigned output port. """ config = station_configuration() port = self.cur_port self.cur_port += 1 bc_src = corba_bitcount_src_si(uid, self.evchan, self.ns_ip, self.ns_port, self.coding) self.connect(self._id_source, bc_src, (self, port)) return port
def __init__(self, options): config = station_configuration() dsubc = config.data_subcarriers gr.hier_block2.__init__( self, "static_tx_control", gr.io_signature(0, 0, 0), gr.io_signaturev( 4, -1, [ gr.sizeof_short, # ID gr.sizeof_short, # Multiplex control stream gr.sizeof_char * dsubc, # Bit Map gr.sizeof_float * dsubc, # Power Map gr.sizeof_int ])) # Bit count per frame self.control = ctrl = static_control(dsubc, config.frame_id_blocks, config.frame_data_blocks, options) id_out = (self, 0) mux_out = (self, 1) bitmap_out = (self, 2) powmap_out = (self, 3) self.cur_port = 4 ## ID Source (root) id_src = self._id_source = blocks.vector_source_s([ctrl.static_id], True) self.connect(id_src, id_out) ## Multiplex Source mux_src = self._multiplex_source = blocks.vector_source_s( ctrl.mux_stream, True) self.connect(mux_src, mux_out) ## Map Source map_src = blocks.vector_source_b(ctrl.rmod_stream, True, dsubc) self.connect(map_src, bitmap_out) ## Power Allocation Source pa_src = blocks.vector_source_f(ctrl.pow_stream, True, dsubc) self.connect(pa_src, powmap_out)
def __init__(self, options): config = station_configuration() dsubc = config.data_subcarriers gr.hier_block2.__init__( self, "corba_control", gr.io_signature(0, 0, 0), gr.io_signaturev( 4, -1, [ gr.sizeof_short, # ID gr.sizeof_short, # Multiplex control stream gr.sizeof_char * dsubc, # Bit Map gr.sizeof_int ])) # Bit count per frame id_out = (self, 0) mux_out = (self, 1) bitmap_out = (self, 2) self.cur_port = 3 self.ns_ip = ns_ip = options.nameservice_ip self.ns_port = ns_port = options.nameservice_port self.evchan = evchan = std_event_channel self.coding = coding = options.coding ## ID Source (root) id_src = self._id_source = corba_id_src(evchan, ns_ip, ns_port) self.connect(id_src, id_out) ## Multiplex Source mux_src = self._multiplex_source = corba_multiplex_src_ss( evchan, ns_ip, ns_port, coding) self.connect(id_src, mux_src, mux_out) ## Map Source map_src = self._bitmap_source = corba_bitmap_src( dsubc, 0, evchan, ns_ip, ns_port) self.connect(id_src, map_src, bitmap_out)
def add_mobile_station(self,uid): """ Register mobile station with unique id \param uid Provides a new bitcount stream for this id. The next free port of the control block is used. Returns assigned output port. """ config = station_configuration() port = self.cur_port self.cur_port += 1 smm = numpy.array(self.control.static_mod_map) sam = numpy.array(self.control.static_ass_map) bitcount = sum(smm[sam == uid])*config.frame_data_blocks bc_src = blocks.vector_source_i([bitcount],True) self.connect(bc_src,(self,port)) return port
def add_mobile_station(self, uid): """ Register mobile station with unique id \param uid Provides a new bitcount stream for this id. The next free port of the control block is used. Returns assigned output port. """ config = station_configuration() port = self.cur_port self.cur_port += 1 smm = numpy.array(self.control.static_mod_map) sam = numpy.array(self.control.static_ass_map) bitcount = sum(smm[sam == uid]) * config.frame_data_blocks bc_src = blocks.vector_source_i([bitcount], True) self.connect(bc_src, (self, port)) return port
def __init__(self, options): config = station_configuration() dsubc = config.data_subcarriers gr.hier_block2.__init__(self, "static_tx_control", gr.io_signature (0,0,0), gr.io_signaturev(4,-1,[gr.sizeof_short, # ID gr.sizeof_short, # Multiplex control stream gr.sizeof_char*dsubc, # Bit Map gr.sizeof_float*dsubc, # Power Map gr.sizeof_int ])) # Bit count per frame self.control = ctrl = static_control(dsubc,config.frame_id_blocks, config.frame_data_blocks,options) id_out = (self,0) mux_out = (self,1) bitmap_out = (self,2) powmap_out = (self,3) self.cur_port = 4 ## ID Source (root) id_src = self._id_source = blocks.vector_source_s([ctrl.static_id],True) self.connect(id_src,id_out) ## Multiplex Source mux_src = self._multiplex_source = blocks.vector_source_s(ctrl.mux_stream,True) self.connect(mux_src,mux_out) ## Map Source map_src = blocks.vector_source_b(ctrl.rmod_stream, True, dsubc) self.connect(map_src,bitmap_out) ## Power Allocation Source pa_src = blocks.vector_source_f(ctrl.pow_stream,True,dsubc) self.connect(pa_src,powmap_out)
def __init__(self,options): config = station_configuration() total_subc = config.subcarriers vlen = total_subc gr.hier_block2.__init__(self,"fbmc_frame_sampler", gr.io_signature2(2,2,gr.sizeof_gr_complex*vlen, gr.sizeof_char), gr.io_signature2(2,2,gr.sizeof_gr_complex*vlen, gr.sizeof_char)) frame_size = config.frame_data_part + config.training_data.fbmc_no_preambles/2 print "frame_size: ", frame_size ft = [0] * frame_size 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, frame_size ) symbol_output = blocks.vector_to_stream( gr.sizeof_gr_complex * total_subc, frame_size ) #delayed_frame_start = blocks.delay( gr.sizeof_char, config.frame_length-1 - config.training_data.fbmc_no_preambles/2 ) delayed_frame_start = blocks.delay( gr.sizeof_char, config.frame_length/2-1) damn_static_frame_trigger = blocks.vector_source_b( ft, True ) #oqam_postpro = ofdm.fbmc_oqam_postprocessing_vcvc(total_subc,0,0) self.connect( self, frame_sampler, symbol_output ,self) #self.connect( (self,1), blocks.keep_m_in_n(gr.sizeof_char,config.frame_data_part + config.training_data.fbmc_no_preambles/2,2*config.frame_data_part + config.training_data.fbmc_no_preambles,0),delayed_frame_start, ( frame_sampler, 1 ) ) self.connect( (self,1), delayed_frame_start, ( frame_sampler, 1 ) ) #self.connect( self, blocks.multiply_const_vcc(([1.0]*total_subc)) ,self) #terminate_stream(self,frame_sampler) self.connect( damn_static_frame_trigger, (self,1) )
def __init__(self,options): config = station_configuration() total_subc = config.subcarriers vlen = total_subc gr.hier_block2.__init__(self,"ofdm_frame_sampler", gr.io_signature2(2,2,gr.sizeof_gr_complex*vlen, gr.sizeof_char), gr.io_signature2(2,2,gr.sizeof_gr_complex*vlen, gr.sizeof_char)) 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 ) 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 ) #oqam_postpro = ofdm.fbmc_oqam_postprocessing_vcvc(total_subc,0,0) if options.enable_erasure_decision: self.frame_gate = vector_sampler( gr.sizeof_gr_complex * total_subc * config.frame_length, 1 ) self.connect( self, frame_sampler, self.frame_gate, symbol_output ) else: self.connect( self, frame_sampler, symbol_output, self ) self.connect( (self,1), delayed_frame_start, ( frame_sampler, 1 ) ) self.connect( damn_static_frame_trigger, (self,1) )
def __init__(self, options): config = station_configuration() dsubc = config.data_subcarriers gr.hier_block2.__init__(self, "corba_control", gr.io_signature (0,0,0), gr.io_signaturev(4,-1,[gr.sizeof_short, # ID gr.sizeof_short, # Multiplex control stream gr.sizeof_char*dsubc, # Bit Map gr.sizeof_int ])) # Bit count per frame id_out = (self,0) mux_out = (self,1) bitmap_out = (self,2) self.cur_port = 3 self.ns_ip = ns_ip = options.nameservice_ip self.ns_port = ns_port = options.nameservice_port self.evchan = evchan = std_event_channel self.coding = coding = options.coding ## ID Source (root) id_src = self._id_source = corba_id_src(evchan,ns_ip,ns_port) self.connect(id_src,id_out) ## Multiplex Source mux_src = self._multiplex_source = corba_multiplex_src_ss(evchan,ns_ip,ns_port,coding) self.connect(id_src,mux_src,mux_out) ## Map Source map_src = self._bitmap_source = corba_bitmap_src(dsubc, 0,evchan,ns_ip,ns_port) self.connect(id_src,map_src,bitmap_out)
def publish_rx_performance_measure(self): if self._rx_performance_measure_initialized(): return self.rx_performance_measure_initialized = True config = station_configuration() vlen = config.data_subcarriers vlen_sinr_sc = config.subcarriers # self.rx_per_sink = rpsink = rpsink_dummy() self.setup_ber_measurement() self.setup_snr_measurement() self.setup_snr_measurement_2() ber_mst = self._ber_measuring_tool if self._options.sinr_est: sinr_mst = self._sinr_measurement sinr_mst_2 = self._sinr_measurement_2 else: snr_mst = self._snr_measurement snr_mst_2 = self._snr_measurement_2 # 1. frame id # 2. channel transfer function ctf = self.filter_ctf() ctf_2 = self.filter_ctf_2() self.zmq_probe_ctf = zeromq.pub_sink(gr.sizeof_float,config.data_subcarriers, "tcp://*:5559") self.zmq_probe_ctf_2 = zeromq.pub_sink(gr.sizeof_float,config.data_subcarriers, "tcp://*:5558") self.connect(ctf, blocks.keep_one_in_n(gr.sizeof_float*config.data_subcarriers,20) ,self.zmq_probe_ctf) self.connect(ctf_2, blocks.keep_one_in_n(gr.sizeof_float*config.data_subcarriers,20) ,self.zmq_probe_ctf_2) # 3. BER ### FIXME HACK print "Normal BER measurement" trig_src = dynamic_trigger_ib(False) self.connect(self.bitcount_src,trig_src) ber_sampler = vector_sampler(gr.sizeof_float,1) self.connect(ber_mst,(ber_sampler,0)) self.connect(trig_src,(ber_sampler,1)) if self._options.log: trig_src_float = gr.char_to_float() self.connect(trig_src,trig_src_float) log_to_file(self, trig_src_float , 'data/dynamic_trigger_out.float') if self._options.sinr_est is False: self.zmq_probe_ber = zeromq.pub_sink(gr.sizeof_float, 1, "tcp://*:5556") self.connect(ber_sampler,blocks.keep_one_in_n(gr.sizeof_float,20) ,self.zmq_probe_ber) self.zmq_probe_snr = zeromq.pub_sink(gr.sizeof_float, 1, "tcp://*:5555") self.connect(snr_mst,blocks.keep_one_in_n(gr.sizeof_float,20) ,self.zmq_probe_snr) self.zmq_probe_snr_2 = zeromq.pub_sink(gr.sizeof_float, 1, "tcp://*:5554") self.connect(snr_mst_2,blocks.keep_one_in_n(gr.sizeof_float,20) ,self.zmq_probe_snr_2)
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 __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_signature(1,1,gr.sizeof_float*vlen)) print "Created Milan's SINR estimator 2" config = station_configuration() # 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 = blocks.multiply_const_ff(1./vlen) #scsnr_db_av = blocks.nlog10_ff(10,1,0) #filt_end_av = filter.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)) estimator = sinr_estimator(vlen, ss, config.dc_null) scsnr_db = blocks.nlog10_ff(10,vlen,0) #filt_end = filter.single_pole_iir_filter_ff(0.1,vlen) dd = [] #for i in range (vlen/ss): # dd.extend([i*ss]) for i in range (vlen/ss): if i < (vlen/ss)/2: dd.extend([i*ss + 4 + config.dc_null/2]) else: dd.extend([i*ss + 4 - config.dc_null/2]) #print dd interpolator = sinr_interpolator(vlen, ss,dd) self.connect((self,0),(estimator,0)) self.connect((self,1),(estimator,1)) #self.connect(estimator,interpolator,filt_end,scsnr_db,self) self.connect(estimator,interpolator,scsnr_db,self)
def publish_rx_performance_measure(self): if self._rx_performance_measure_initialized(): return self.rx_performance_measure_initialized = True config = station_configuration() vlen = config.data_subcarriers vlen_sinr_sc = config.subcarriers if self.ideal2 is False: self.setup_ber_measurement() self.setup_snr_measurement() ber_mst = self._ber_measuring_tool if self._options.sinr_est: sinr_mst = self._sinr_measurement else: if self.ideal2 is False: snr_mst = self._snr_measurement if self.ideal is False and self.ideal2 is False: self.ctf = self.filter_ctf() self.zmq_probe_ctf = zeromq.pub_sink(gr.sizeof_float,config.data_subcarriers, "tcp://*:5559") self.connect(self.ctf, blocks.keep_one_in_n(gr.sizeof_float*config.data_subcarriers,20) ,self.zmq_probe_ctf) else: #self.zmq_probe_ctf = zeromq.pub_sink(gr.sizeof_float,config.subcarriers, "tcp://*:5559") self.connect(self.ctf,blocks.null_sink(gr.sizeof_float*config.subcarriers)) #self.rx_per_sink = rpsink = corba_rxinfo_sink("himalaya",config.ns_ip, # config.ns_port,vlen,config.rx_station_id) # print "BER img xfer" # self.connect(ber_mst,(rpsink,3)) # ## no sampling needed # 3. SNR if self.ideal2 is False: print "Normal BER measurement" trig_src = dynamic_trigger_ib(False) self.connect(self.bitcount_src,trig_src) ber_sampler = vector_sampler(gr.sizeof_float,1) self.connect(ber_mst,(ber_sampler,0)) self.connect(trig_src,(ber_sampler,1)) else: if(self._options.coding): demod = self._data_decoder else: demod = self._data_demodulator self.connect(self.bitcount_src,blocks.null_sink(gr.sizeof_int) ) self.connect(demod,blocks.null_sink(gr.sizeof_char)) if self._options.log: trig_src_float = gr.char_to_float() self.connect(trig_src,trig_src_float) log_to_file(self, trig_src_float , 'data/dynamic_trigger_out.float') if self._options.sinr_est is False and self.ideal2 is False: self.zmq_probe_ber = zeromq.pub_sink(gr.sizeof_float, 1, "tcp://*:5556") self.connect(ber_sampler,blocks.keep_one_in_n(gr.sizeof_float,20) ,self.zmq_probe_ber) if self.ideal2 is False: self.zmq_probe_snr = zeromq.pub_sink(gr.sizeof_float, 1, "tcp://*:5555") self.connect(snr_mst,blocks.keep_one_in_n(gr.sizeof_float,20) ,self.zmq_probe_snr)
def __init__(self, options): gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex)) common_options.defaults(options) config = self.config = station_configuration() config.data_subcarriers = options.subcarriers config.cp_length = options.cp_length config.frame_data_blocks = options.data_blocks config._verbose = options.verbose config.fft_length = options.fft_length config.dc_null = options.dc_null config.training_data = default_block_header(config.data_subcarriers, config.fft_length, config.dc_null, options) config.coding = options.coding config.bandwidth = options.bandwidth config.gui_frame_rate = options.gui_frame_rate config.fbmc = options.fbmc config.frame_id_blocks = 1 # FIXME # digital rms amplitude sent to USRP rms_amp = options.rms_amplitude self._options = copy.copy(options) 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.frame_data_part + \ config.training_data.no_pilotsyms config.subcarriers = config.data_subcarriers + \ config.training_data.pilot_subcarriers config.virtual_subcarriers = config.fft_length - config.subcarriers - config.dc_null # default values if parameters not set if rms_amp is None: rms_amp = math.sqrt(config.subcarriers) config.rms_amplitude = rms_amp # 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" ## shortcuts blen = config.block_length flen = config.frame_length dsubc = config.data_subcarriers vsubc = config.virtual_subcarriers # Adaptive Transmitter Concept used_id_bits = config.used_id_bits = 8 #TODO: no constant in source code rep_id_bits = config.rep_id_bits = config.data_subcarriers / used_id_bits #BPSK if config.data_subcarriers % used_id_bits <> 0: raise SystemError, "Data subcarriers need to be multiple of %d" % ( used_id_bits) # adapt OFDM frame rate and GUI display frame rate self.keep_frame_n = int( 1.0 / (config.frame_length * (config.cp_length + config.fft_length) / config.bandwidth) / config.gui_frame_rate) ## Allocation Control self.allocation_src = allocation_src( config.data_subcarriers, config.frame_data_blocks, config.coding, "tcp://*:3333", "tcp://" + options.rx_hostname + ":3322") if options.static_allocation: #DEBUG # how many bits per subcarrier 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 modulbitspermode = [1, 2, 2, 4, 4, 6, 6, 6, 8] # Coding bits per mode bitcount_vec = [ (int)(config.data_subcarriers * config.frame_data_blocks * bitspermode[mode - 1]) ] modul_bitcount_vec = [ config.data_subcarriers * config.frame_data_blocks * modulbitspermode[mode - 1] ] bitcount_src = blocks.vector_source_i(bitcount_vec, True, 1) modul_bitcount_src = blocks.vector_source_i( modul_bitcount_vec, True, 1) bitloading = mode else: bitloading = 1 bitcount_vec = [ config.data_subcarriers * config.frame_data_blocks * bitloading ] bitcount_src = blocks.vector_source_i(bitcount_vec, True, 1) modul_bitcount_src = bitcount_src # id's for frames id_vec = range(0, 256) id_src = blocks.vector_source_s(id_vec, True, 1) # bitloading for ID symbol and then once for data symbols #bitloading_vec = [1]*dsubc+[0]*(dsubc/2)+[2]*(dsubc/2) #test_allocation = [bitloading]*(int)(config.data_subcarriers/8)+ [0]*(int)(config.data_subcarriers/4*3) + [bitloading]*(int)(config.data_subcarriers/8) #bitloading_vec = [1]*dsubc+[bitloading]*dsubc test_allocation = [bitloading] * dsubc bitloading_vec = [bitloading] * dsubc + test_allocation bitloading_src = blocks.vector_source_b(bitloading_vec, True, dsubc) # bitcount for frames #bitcount_vec = [config.data_subcarriers*config.frame_data_blocks*bitloading] bitcount_vec = [config.frame_data_blocks * sum(test_allocation)] bitcount_src = blocks.vector_source_i(bitcount_vec, True, 1) # power loading, here same for all symbols #power_vec = [1]*(int)(config.data_subcarriers/8)+ [0]*(int)(config.data_subcarriers/4*3) + [1]*(int)(config.data_subcarriers/8) power_vec = [1] * config.data_subcarriers power_src = blocks.vector_source_f(power_vec, True, dsubc) # mux control stream to mux id and data bits mux_vec = [0] * dsubc + [1] * bitcount_vec[0] mux_ctrl = blocks.vector_source_b(mux_vec, True, 1) else: id_src = (self.allocation_src, 0) bitcount_src = (self.allocation_src, 4) bitloading_src = (self.allocation_src, 2) power_src = (self.allocation_src, 1) if options.coding: modul_bitcount_src = (self.allocation_src, 5) else: modul_bitcount_src = bitcount_src mux_ctrl = ofdm.tx_mux_ctrl(dsubc) self.connect(modul_bitcount_src, mux_ctrl) #Initial allocation self.allocation_src.set_allocation([2] * config.data_subcarriers, [1] * config.data_subcarriers) self.allocation_src.set_allocation_scheme(0) if options.benchmarking: self.allocation_src.set_allocation( [4] * config.data_subcarriers, [1] * config.data_subcarriers) if options.lab_special_case: self.allocation_src.set_allocation( [0] * (config.data_subcarriers / 4) + [2] * (config.data_subcarriers / 2) + [0] * (config.data_subcarriers / 4), [1] * config.data_subcarriers) if options.log: log_to_file(self, id_src, "data/id_src.short") log_to_file(self, bitcount_src, "data/bitcount_src.int") log_to_file(self, bitloading_src, "data/bitloading_src.char") log_to_file(self, power_src, "data/power_src.cmplx") ## GUI probe output zmq_probe_bitloading = zeromq.pub_sink(gr.sizeof_char, dsubc, "tcp://*:4445") # also skip ID symbol bitloading with keep_one_in_n (side effect) # factor 2 for bitloading because we have two vectors per frame, one for id symbol and one for all payload/data symbols # factor config.frame_data_part for power because there is one vector per ofdm symbol per frame self.connect(bitloading_src, blocks.keep_one_in_n(gr.sizeof_char * dsubc, 2 * 40), zmq_probe_bitloading) zmq_probe_power = zeromq.pub_sink(gr.sizeof_float, dsubc, "tcp://*:4444") #self.connect(power_src, blocks.keep_one_in_n(gr.sizeof_gr_complex*dsubc,40), blocks.complex_to_real(dsubc), zmq_probe_power) self.connect(power_src, blocks.keep_one_in_n(gr.sizeof_float * dsubc, 40), zmq_probe_power) ## Workaround to avoid periodic structure seed(1) whitener_pn = [ randint(0, 1) for i in range(used_id_bits * rep_id_bits) ] ## ID Encoder id_enc = self._id_encoder = repetition_encoder_sb( used_id_bits, rep_id_bits, whitener_pn) self.connect(id_src, id_enc) if options.log: id_enc_f = gr.char_to_float() self.connect(id_enc, id_enc_f) log_to_file(self, id_enc_f, "data/id_enc_out.float") ## Reference Data Source ber_ref_src = ber_reference_source(self._options) self.connect(id_src, (ber_ref_src, 0)) self.connect(bitcount_src, (ber_ref_src, 1)) if options.log: log_to_file(self, ber_ref_src, "data/ber_rec_src_tx.char") if options.log: log_to_file(self, btrig, "data/bitmap_trig.char") ## Bitmap Update Trigger for puncturing if not options.nopunct: bmaptrig_stream_puncturing = [ 1 ] + [0] * (config.frame_data_blocks / 2 - 1) btrig_puncturing = self._bitmap_trigger_puncturing = blocks.vector_source_b( bmaptrig_stream_puncturing, True) bmapsrc_stream_puncturing = [1] * dsubc + [2] * dsubc bsrc_puncturing = self._bitmap_src_puncturing = blocks.vector_source_b( bmapsrc_stream_puncturing, True, dsubc) if options.log and options.coding and not options.nopunct: log_to_file(self, btrig_puncturing, "data/bitmap_trig_puncturing.char") ## Frame Trigger ftrig_stream = [1] + [0] * (config.frame_data_part - 1) ftrig = self._frame_trigger = blocks.vector_source_b( ftrig_stream, True) ## Data Multiplexer # Input 0: control stream # Input 1: encoded ID stream # Inputs 2..n: data streams dmux = self._data_multiplexer = stream_controlled_mux_b() self.connect(mux_ctrl, (dmux, 0)) self.connect(id_enc, (dmux, 1)) if options.coding: fo = trellis.fsm(1, 2, [91, 121]) encoder = self._encoder = trellis.encoder_bb(fo, 0) unpack = self._unpack = blocks.unpack_k_bits_bb(2) self.connect(ber_ref_src, encoder, unpack) if options.interleave: int_object = trellis.interleaver(2000, 666) interlv = trellis.permutation(int_object.K(), int_object.INTER(), 1, gr.sizeof_char) if not options.nopunct: bmaptrig_stream_puncturing = [ 1 ] + [0] * (config.frame_data_blocks / 2 - 1) btrig_puncturing = self._bitmap_trigger_puncturing = blocks.vector_source_b( bmaptrig_stream_puncturing, True) puncturing = self._puncturing = puncture_bb( config.data_subcarriers) self.connect(bitloading_src, (puncturing, 1)) self.connect(self._bitmap_trigger_puncturing, (puncturing, 2)) self.connect(unpack, puncturing) last_block = puncturing if options.interleave: self.connect(last_block, interlv) last_block = interlv if options.benchmarking: self.connect(last_block, blocks.head(gr.sizeof_char, options.N), (dmux, 2)) else: self.connect(last_block, (dmux, 2)) else: if options.benchmarking: self.connect(unpack, blocks.head(gr.sizeof_char, options.N), (dmux, 2)) else: self.connect(unpack, (dmux, 2)) else: if options.benchmarking: self.connect(ber_ref_src, blocks.head(gr.sizeof_char, options.N), (dmux, 2)) else: self.connect(ber_ref_src, (dmux, 2)) if options.log: dmux_f = gr.char_to_float() self.connect(dmux, dmux_f) log_to_file(self, dmux_f, "data/dmux_out.float") ## Modulator mod = self._modulator = generic_mapper_bcv(config.data_subcarriers, config.coding, config.frame_data_part) self.connect(dmux, (mod, 0)) self.connect(bitloading_src, (mod, 1)) #log_to_file(self, mod, "data/mod_out.compl") if options.log: log_to_file(self, mod, "data/mod_out.compl") modi = blocks.complex_to_imag(config.data_subcarriers) modr = blocks.complex_to_real(config.data_subcarriers) self.connect(mod, modi) self.connect(mod, modr) log_to_file(self, modi, "data/mod_imag_out.float") log_to_file(self, modr, "data/mod_real_out.float") ## Power allocator pa = self._power_allocator = multiply_frame_fc(config.frame_data_part, config.data_subcarriers) self.connect(mod, (pa, 0)) self.connect(power_src, (pa, 1)) if options.log: log_to_file(self, pa, "data/pa_out.compl") # Standard Transmitter Parts ## Pilot subcarriers psubc = self._pilot_subcarrier_inserter = pilot_subcarrier_inserter() self.connect(pa, psubc) if options.log: log_to_file(self, psubc, "data/psubc_out.compl") ## Add virtual subcarriers if config.fft_length > config.subcarriers: vsubc = self._virtual_subcarrier_extender = \ vector_padding_dc_null(config.subcarriers, config.fft_length,config.dc_null) self.connect(psubc, vsubc) else: vsubc = self._virtual_subcarrier_extender = psubc if options.log: log_to_file(self, vsubc, "data/vsubc_out.compl") ## IFFT, no window, block shift ifft = self._ifft = fft_blocks.fft_vcc(config.fft_length, False, [], True) self.connect(vsubc, ifft) if options.log: log_to_file(self, ifft, "data/ifft_out.compl") ## Pilot blocks (preambles) pblocks = self._pilot_block_inserter = pilot_block_inserter(5, False) self.connect(ifft, pblocks) if options.log: log_to_file(self, pblocks, "data/pilot_block_ins_out.compl") ## Cyclic Prefix cp = self._cyclic_prefixer = cyclic_prefixer(config.fft_length, config.block_length) self.connect(pblocks, cp) lastblock = cp if options.log: log_to_file(self, cp, "data/cp_out.compl") #Digital Amplifier for resource allocation #if not options.coding: rep = blocks.repeat(gr.sizeof_gr_complex, config.frame_length * config.block_length) amp = blocks.multiply_cc() self.connect(lastblock, (amp, 0)) self.connect((self.allocation_src, 3), rep, (amp, 1)) lastblock = amp ## Digital Amplifier #amp = self._amplifier = gr.multiply_const_cc(1) amp = self._amplifier = ofdm.multiply_const_ccf(1.0) self.connect(lastblock, amp) self.set_rms_amplitude(rms_amp) if options.log: log_to_file(self, amp, "data/amp_tx_out.compl") ## Tx parameters bandwidth = options.bandwidth or 2e6 bits = 8 * config.data_subcarriers * config.frame_data_blocks # max. QAM256 samples_per_frame = config.frame_length * config.block_length tb = samples_per_frame / bandwidth # set dummy carrier frequency if none available due to baseband mode if (options.tx_freq is None): options.tx_freq = 0.0 self.tx_parameters = {'carrier_frequency':options.tx_freq/1e9,'fft_size':config.fft_length, 'cp_size':config.cp_length \ , 'subcarrier_spacing':options.bandwidth/config.fft_length/1e3 \ , 'data_subcarriers':config.data_subcarriers, 'bandwidth':options.bandwidth/1e6 \ , 'frame_length':config.frame_length \ , 'symbol_time':(config.cp_length + config.fft_length)/options.bandwidth*1e6, 'max_data_rate':(bits/tb)/1e6} ## Setup Output self.connect(amp, self) # Display some information about the setup if config._verbose: self._print_verbage()
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_signature(1, 1, gr.sizeof_float * vlen)) print "Created Milan's SINR estimator 2" config = station_configuration() # 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 = blocks.multiply_const_ff(1./vlen) #scsnr_db_av = blocks.nlog10_ff(10,1,0) #filt_end_av = filter.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)) estimator = sinr_estimator(vlen, ss, config.dc_null) scsnr_db = blocks.nlog10_ff(10, vlen, 0) #filt_end = filter.single_pole_iir_filter_ff(0.1,vlen) dd = [] #for i in range (vlen/ss): # dd.extend([i*ss]) for i in range(vlen / ss): if i < (vlen / ss) / 2: dd.extend([i * ss + 4 + config.dc_null / 2]) else: dd.extend([i * ss + 4 - config.dc_null / 2]) #print dd interpolator = sinr_interpolator(vlen, ss, dd) self.connect((self, 0), (estimator, 0)) self.connect((self, 1), (estimator, 1)) #self.connect(estimator,interpolator,filt_end,scsnr_db,self) self.connect(estimator, interpolator, scsnr_db, self)
def __init__(self, options): gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0, 0, 0), gr.io_signature(2, 2, gr.sizeof_gr_complex)) common_options.defaults(options) config = self.config = station_configuration() config.data_subcarriers = options.subcarriers config.cp_length = options.cp_length config.frame_data_blocks = options.data_blocks config._verbose = options.verbose config.fft_length = options.fft_length config.training_data = default_block_header(config.data_subcarriers, config.fft_length, options) config.tx_station_id = options.station_id config.coding = options.coding if config.tx_station_id is None: raise SystemError, "Station ID not set" config.frame_id_blocks = 1 # FIXME # digital rms amplitude sent to USRP rms_amp = options.rms_amplitude self._options = copy.copy(options) self.servants = [] # FIXME 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.frame_data_part + \ config.training_data.no_pilotsyms config.subcarriers = config.data_subcarriers + \ config.training_data.pilot_subcarriers config.virtual_subcarriers = config.fft_length - config.subcarriers # default values if parameters not set if rms_amp is None: rms_amp = math.sqrt(config.subcarriers) config.rms_amplitude = rms_amp # 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" ## shortcuts blen = config.block_length flen = config.frame_length dsubc = config.data_subcarriers vsubc = config.virtual_subcarriers # ------------------------------------------------------------------------ # # Adaptive Transmitter Concept used_id_bits = config.used_id_bits = 8 #TODO: no constant in source code rep_id_bits = config.rep_id_bits = config.data_subcarriers / used_id_bits #BPSK if config.data_subcarriers % used_id_bits <> 0: raise SystemError, "Data subcarriers need to be multiple of %d" % ( used_id_bits) ## Control Part if options.debug: self._control = ctrl = static_tx_control(options) print "Statix TX Control used" else: self._control = ctrl = corba_tx_control(options) print "CORBA TX Control used" id_src = (ctrl, 0) mux_src = (ctrl, 1) map_src = self._map_src = (ctrl, 2) pa_src = (ctrl, 3) if options.log: id_src_f = gr.short_to_float() self.connect(id_src, id_src_f) log_to_file(self, id_src_f, "data/id_src_out.float") mux_src_f = gr.short_to_float() self.connect(mux_src, mux_src_f) log_to_file(self, mux_src_f, "data/mux_src_out.float") map_src_s = blocks.vector_to_stream(gr.sizeof_char, config.data_subcarriers) map_src_f = gr.char_to_float() self.connect(map_src, map_src_s, map_src_f) ##log_to_file(self, map_src_f, "data/map_src.float") ##log_to_file(self, pa_src, "data/pa_src_out.float") ## Workaround to avoid periodic structure seed(1) whitener_pn = [ randint(0, 1) for i in range(used_id_bits * rep_id_bits) ] ## ID Encoder id_enc = self._id_encoder = repetition_encoder_sb( used_id_bits, rep_id_bits, whitener_pn) self.connect(id_src, id_enc) if options.log: id_enc_f = gr.char_to_float() self.connect(id_enc, id_enc_f) log_to_file(self, id_enc_f, "data/id_enc_out.float") ## Bitmap Update Trigger # TODO #bmaptrig_stream = concatenate([[1, 2],[0]*(config.frame_data_part-7)]) bmaptrig_stream = concatenate([[1, 1], [0] * (config.frame_data_part - 2)]) print "bmaptrig_stream = ", bmaptrig_stream btrig = self._bitmap_trigger = blocks.vector_source_b( bmaptrig_stream.tolist(), True) if options.log: log_to_file(self, btrig, "data/bitmap_trig.char") ## Bitmap Update Trigger for puncturing # TODO if not options.nopunct: #bmaptrig_stream_puncturing = concatenate([[1],[0]*(config.frame_data_part-2)]) bmaptrig_stream_puncturing = concatenate( [[1], [0] * (config.frame_data_blocks / 2 - 1)]) btrig_puncturing = self._bitmap_trigger_puncturing = blocks.vector_source_b( bmaptrig_stream_puncturing.tolist(), True) bmapsrc_stream_puncturing = concatenate([[1] * dsubc, [2] * dsubc]) bsrc_puncturing = self._bitmap_src_puncturing = blocks.vector_source_b( bmapsrc_stream_puncturing.tolist(), True, dsubc) if options.log and options.coding and not options.nopunct: log_to_file(self, btrig_puncturing, "data/bitmap_trig_puncturing.char") ## Frame Trigger # TODO ftrig_stream = concatenate([[1], [0] * (config.frame_data_part - 1)]) ftrig = self._frame_trigger = blocks.vector_source_b( ftrig_stream.tolist(), True) ## Data Multiplexer # Input 0: control stream # Input 1: encoded ID stream # Inputs 2..n: data streams dmux = self._data_multiplexer = stream_controlled_mux_b() self.connect(mux_src, (dmux, 0)) self.connect(id_enc, (dmux, 1)) self._data_multiplexer_nextport = 2 if options.log: dmux_f = gr.char_to_float() self.connect(dmux, dmux_f) log_to_file(self, dmux_f, "data/dmux_out.float") ## Modulator mod = self._modulator = generic_mapper_bcv(config.data_subcarriers, options.coding) self.connect(dmux, (mod, 0)) self.connect(map_src, (mod, 1)) self.connect(btrig, (mod, 2)) if options.log: log_to_file(self, mod, "data/mod_out.compl") modi = gr.complex_to_imag(config.data_subcarriers) modr = gr.complex_to_real(config.data_subcarriers) self.connect(mod, modi) self.connect(mod, modr) log_to_file(self, modi, "data/mod_imag_out.float") log_to_file(self, modr, "data/mod_real_out.float") ## Power allocator if options.debug: ## static pa = self._power_allocator = power_allocator( config.data_subcarriers) self.connect(mod, (pa, 0)) self.connect(pa_src, (pa, 1)) else: ## with CORBA control event channel ns_ip = ctrl.ns_ip ns_port = ctrl.ns_port evchan = ctrl.evchan pa = self._power_allocator = corba_power_allocator(dsubc, \ evchan, ns_ip, ns_port, True) self.connect(mod, (pa, 0)) self.connect(id_src, (pa, 1)) self.connect(ftrig, (pa, 2)) if options.log: log_to_file(self, pa, "data/pa_out.compl") ## Pilot subcarriers psubc = self._pilot_subcarrier_inserter = pilot_subcarrier_inserter() self.connect(pa, psubc) pilot_subc = config.training_data.shifted_pilot_tones print "pilot_subc", pilot_subc stc = stc_encoder(config.subcarriers, config.frame_data_blocks, pilot_subc) self.connect(psubc, stc) if options.log: log_to_file(self, psubc, "data/psubc_out.compl") log_to_file(self, psubc_2, "data/psubc2_out.compl") log_to_file(self, pa, "data/pa.compl") log_to_file(self, (stc, 0), "data/stc_0.compl") log_to_file(self, (stc, 1), "data/stc_1.compl") ## Add virtual subcarriers if config.fft_length > config.subcarriers: vsubc = self._virtual_subcarrier_extender = \ vector_padding(config.subcarriers, config.fft_length) self.connect(stc, vsubc) vsubc_2 = self._virtual_subcarrier_extender_2 = \ vector_padding(config.subcarriers, config.fft_length) self.connect((stc, 1), vsubc_2) else: vsubc = self._virtual_subcarrier_extender = psubc vsubc_2 = self._virtual_subcarrier_extender_2 = psubc_2 log_to_file(self, psubc, "data/psubc.compl") log_to_file(self, stc, "data/stc1.compl") log_to_file(self, (stc, 1), "data/stc2.compl") if options.log: log_to_file(self, vsubc, "data/vsubc_out.compl") log_to_file(self, vsubc_2, "data/vsubc2_out.compl") ## IFFT, no window, block shift ifft = self._ifft = fft_blocks.fft_vcc(config.fft_length, False, [], True) self.connect(vsubc, ifft) ifft_2 = self._ifft_2 = fft_blocks.fft_vcc(config.fft_length, False, [], True) self.connect(vsubc_2, ifft_2) if options.log: log_to_file(self, ifft, "data/ifft_out.compl") log_to_file(self, ifft_2, "data/ifft2_out.compl") ## Pilot blocks (preambles) pblocks = self._pilot_block_inserter = pilot_block_inserter(1, False) self.connect(ifft, pblocks) pblocks_2 = self._pilot_block_inserter_2 = pilot_block_inserter( 2, False) self.connect(ifft_2, pblocks_2) if options.log: log_to_file(self, pblocks, "data/pilot_block_ins_out.compl") log_to_file(self, pblocks_2, "data/pilot_block_ins2_out.compl") ## Cyclic Prefix cp = self._cyclic_prefixer = cyclic_prefixer(config.fft_length, config.block_length) self.connect(pblocks, cp) cp_2 = self._cyclic_prefixer_2 = cyclic_prefixer( config.fft_length, config.block_length) self.connect(pblocks_2, cp_2) lastblock = cp lastblock_2 = cp_2 if options.log: log_to_file(self, cp, "data/cp_out.compl") log_to_file(self, cp_2, "data/cp2_out.compl") if options.cheat: ## Artificial Channel # kept to compare with previous system achan_ir = concatenate([[1.0], [0.0] * (config.cp_length - 1)]) achan = self._artificial_channel = gr.fir_filter_ccc(1, achan_ir) self.connect(lastblock, achan) lastblock = achan achan_2 = self._artificial_channel_2 = gr.fir_filter_ccc( 1, achan_ir) self.connect(lastblock_2, achan_2) lastblock_2 = achan_2 ## Digital Amplifier amp = self._amplifier = ofdm.multiply_const_ccf(1.0 / math.sqrt(2)) self.connect(lastblock, amp) amp_2 = self._amplifier_2 = ofdm.multiply_const_ccf(1.0 / math.sqrt(2)) self.connect(lastblock_2, amp_2) self.set_rms_amplitude(rms_amp) if options.log: log_to_file(self, amp, "data/amp_tx_out.compl") log_to_file(self, amp_2, "data/amp_tx2_out.compl") ## Setup Output self.connect(amp, (self, 0)) self.connect(amp_2, (self, 1)) # ------------------------------------------------------------------------ # # Display some information about the setup if config._verbose: self._print_verbage()
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_transmit_path", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex) ) common_options.defaults(options) config = self.config = station_configuration() config.data_subcarriers = options.subcarriers config.cp_length = 0 config.frame_data_blocks = options.data_blocks config._verbose = options.verbose config.fft_length = options.fft_length config.dc_null = options.dc_null config.training_data = default_block_header(config.data_subcarriers, config.fft_length, config.dc_null, options) config.coding = options.coding config.fbmc = options.fbmc config.adaptive_fbmc = options.adaptive_fbmc config.frame_id_blocks = 1 # FIXME # digital rms amplitude sent to USRP rms_amp = options.rms_amplitude self._options = copy.copy(options) 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.subcarriers = config.data_subcarriers + config.training_data.pilot_subcarriers config.virtual_subcarriers = config.fft_length - config.subcarriers - config.dc_null # default values if parameters not set if rms_amp is None: rms_amp = math.sqrt(config.subcarriers) config.rms_amplitude = rms_amp # 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" ## shortcuts blen = config.block_length flen = config.frame_length dsubc = config.data_subcarriers vsubc = config.virtual_subcarriers # Adaptive Transmitter Concept used_id_bits = config.used_id_bits = 8 # TODO: no constant in source code rep_id_bits = config.rep_id_bits = config.data_subcarriers / used_id_bits # BPSK if config.data_subcarriers % used_id_bits <> 0: raise SystemError, "Data subcarriers need to be multiple of %d" % (used_id_bits) ## Allocation Control self.allocation_src = allocation_src( config.data_subcarriers, config.frame_data_blocks, config.coding, "tcp://*:3333", "tcp://" + options.rx_hostname + ":3322", ) if options.static_allocation: # DEBUG # how many bits per subcarrier 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 modulbitspermode = [1, 2, 2, 4, 4, 6, 6, 6, 8] # Coding bits per mode bitcount_vec = [(int)(config.data_subcarriers * config.frame_data_blocks * bitspermode[mode - 1])] modul_bitcount_vec = [config.data_subcarriers * config.frame_data_blocks * modulbitspermode[mode - 1]] bitcount_src = blocks.vector_source_i(bitcount_vec, True, 1) modul_bitcount_src = blocks.vector_source_i(modul_bitcount_vec, True, 1) bitloading = mode else: bitloading = 1 bitcount_vec = [config.data_subcarriers * config.frame_data_blocks * bitloading] bitcount_src = blocks.vector_source_i(bitcount_vec, True, 1) modul_bitcount_src = bitcount_src # id's for frames id_vec = range(0, 256) id_src = blocks.vector_source_s(id_vec, True, 1) # bitloading for ID symbol and then once for data symbols # bitloading_vec = [1]*dsubc+[0]*(dsubc/2)+[2]*(dsubc/2) test_allocation = ( [bitloading] * (int)(config.data_subcarriers / 8) + [0] * (int)(config.data_subcarriers / 4 * 3) + [bitloading] * (int)(config.data_subcarriers / 8) ) # bitloading_vec = [1]*dsubc+[bitloading]*dsubc bitloading_vec = [1] * dsubc + test_allocation bitloading_src = blocks.vector_source_b(bitloading_vec, True, dsubc) # bitcount for frames # bitcount_vec = [config.data_subcarriers*config.frame_data_blocks*bitloading] bitcount_vec = [config.frame_data_blocks * sum(test_allocation)] bitcount_src = blocks.vector_source_i(bitcount_vec, True, 1) # power loading, here same for all symbols power_vec = ( [1] * (int)(config.data_subcarriers / 8) + [0] * (int)(config.data_subcarriers / 4 * 3) + [1] * (int)(config.data_subcarriers / 8) ) power_src = blocks.vector_source_f(power_vec, True, dsubc) # mux control stream to mux id and data bits mux_vec = [0] * dsubc + [1] * bitcount_vec[0] mux_ctrl = blocks.vector_source_b(mux_vec, True, 1) else: id_src = (self.allocation_src, 0) bitcount_src = (self.allocation_src, 4) bitloading_src = (self.allocation_src, 2) power_src = (self.allocation_src, 1) if options.coding: modul_bitcount_src = (self.allocation_src, 5) else: modul_bitcount_src = bitcount_src mux_ctrl = ofdm.tx_mux_ctrl(dsubc) self.connect(modul_bitcount_src, mux_ctrl) # Initial allocation self.allocation_src.set_allocation([4] * config.data_subcarriers, [1] * config.data_subcarriers) if options.benchmarking: self.allocation_src.set_allocation([4] * config.data_subcarriers, [1] * config.data_subcarriers) if options.lab_special_case: self.allocation_src.set_allocation( [0] * (config.data_subcarriers / 4) + [2] * (config.data_subcarriers / 2) + [0] * (config.data_subcarriers / 4), [1] * config.data_subcarriers, ) if options.log: log_to_file(self, id_src, "data/id_src.short") log_to_file(self, bitcount_src, "data/bitcount_src.int") log_to_file(self, bitloading_src, "data/bitloading_src.char") log_to_file(self, power_src, "data/power_src.cmplx") ## GUI probe output zmq_probe_bitloading = zeromq.pub_sink(gr.sizeof_char, dsubc, "tcp://*:4445") # also skip ID symbol bitloading with keep_one_in_n (side effect) # factor 2 for bitloading because we have two vectors per frame, one for id symbol and one for all payload/data symbols # factor config.frame_data_part for power because there is one vector per ofdm symbol per frame self.connect(bitloading_src, blocks.keep_one_in_n(gr.sizeof_char * dsubc, 2 * 40), zmq_probe_bitloading) zmq_probe_power = zeromq.pub_sink(gr.sizeof_float, dsubc, "tcp://*:4444") # self.connect(power_src, blocks.keep_one_in_n(gr.sizeof_gr_complex*dsubc,40), blocks.complex_to_real(dsubc), zmq_probe_power) self.connect(power_src, blocks.keep_one_in_n(gr.sizeof_float * dsubc, 40), zmq_probe_power) ## Workaround to avoid periodic structure seed(1) whitener_pn = [randint(0, 1) for i in range(used_id_bits * rep_id_bits)] ## ID Encoder id_enc = self._id_encoder = repetition_encoder_sb(used_id_bits, rep_id_bits, whitener_pn) self.connect(id_src, id_enc) if options.log: id_enc_f = gr.char_to_float() self.connect(id_enc, id_enc_f) log_to_file(self, id_enc_f, "data/id_enc_out.float") ## Reference Data Source ber_ref_src = ber_reference_source(self._options) self.connect(id_src, (ber_ref_src, 0)) self.connect(bitcount_src, (ber_ref_src, 1)) if options.log: log_to_file(self, ber_ref_src, "data/ber_rec_src_tx.char") if options.log: log_to_file(self, btrig, "data/bitmap_trig.char") ## Frame Trigger ftrig_stream = [1] + [0] * (config.frame_data_part - 1) ftrig = self._frame_trigger = blocks.vector_source_b(ftrig_stream, True) ## Data Multiplexer # Input 0: control stream # Input 1: encoded ID stream # Inputs 2..n: data streams dmux = self._data_multiplexer = stream_controlled_mux_b() self.connect(mux_ctrl, (dmux, 0)) self.connect(id_enc, (dmux, 1)) if options.coding: fo = trellis.fsm(1, 2, [91, 121]) encoder = self._encoder = trellis.encoder_bb(fo, 0) unpack = self._unpack = blocks.unpack_k_bits_bb(2) self.connect(ber_ref_src, encoder, unpack) if options.interleave: int_object = trellis.interleaver(2000, 666) interlv = trellis.permutation(int_object.K(), int_object.INTER(), 1, gr.sizeof_char) if not options.nopunct: bmaptrig_stream_puncturing = [1] + [0] * (config.frame_data_blocks / 2 - 1) btrig_puncturing = self._bitmap_trigger_puncturing = blocks.vector_source_b( bmaptrig_stream_puncturing, True ) puncturing = self._puncturing = puncture_bb(config.data_subcarriers) self.connect(bitloading_src, (puncturing, 1)) self.connect(self._bitmap_trigger_puncturing, (puncturing, 2)) self.connect(unpack, puncturing) last_block = puncturing if options.interleave: self.connect(last_block, interlv) last_block = interlv if options.benchmarking: self.connect(last_block, blocks.head(gr.sizeof_char, options.N), (dmux, 2)) else: self.connect(last_block, (dmux, 2)) else: if options.benchmarking: self.connect(unpack, blocks.head(gr.sizeof_char, options.N), (dmux, 2)) else: self.connect(unpack, (dmux, 2)) else: if options.benchmarking: self.connect(ber_ref_src, blocks.head(gr.sizeof_char, options.N), (dmux, 2)) else: self.connect(ber_ref_src, (dmux, 2)) if options.log: dmux_f = gr.char_to_float() self.connect(dmux, dmux_f) log_to_file(self, dmux_f, "data/dmux_out.float") ## Modulator mod = self._modulator = generic_mapper_bcv(config.data_subcarriers, config.coding, config.frame_data_part) self.connect(dmux, (mod, 0)) self.connect(bitloading_src, (mod, 1)) if options.log: log_to_file(self, mod, "data/mod_out.compl") modi = blocks.complex_to_imag(config.data_subcarriers) modr = blocks.complex_to_real(config.data_subcarriers) self.connect(mod, modi) self.connect(mod, modr) log_to_file(self, modi, "data/mod_imag_out.float") log_to_file(self, modr, "data/mod_real_out.float") ## Power allocator pa = self._power_allocator = multiply_frame_fc(config.frame_data_part, config.data_subcarriers) self.connect(mod, (pa, 0)) self.connect(power_src, (pa, 1)) if options.log: log_to_file(self, pa, "data/pa_out.compl") if options.fbmc: psubc = pa else: psubc = self._pilot_subcarrier_inserter = pilot_subcarrier_inserter() self.connect(pa, psubc) if options.log: log_to_file(self, psubc, "data/psubc_out.compl") subcarriers = config.subcarriers # fbmc_pblocks_timing = self._fbmc_timing_pilot_block_inserter = fbmc_timing_pilot_block_inserter(5,False) oqam_prep = self._oqam_prep = fbmc_oqam_preprocessing_vcvc(config.subcarriers, 0, 0) self.connect(psubc, oqam_prep) fbmc_pblocks = self._fbmc_pilot_block_inserter = fbmc_pilot_block_inserter(5, False) self.connect(oqam_prep, fbmc_pblocks) # log_to_file(self, fbmc_pblocks, "data/fbmc_pblocks_out.compl") # fbmc_insert_pream = self._fbmc_insert_pream = fbmc_insert_preamble_vcvc(M, syms_per_frame, preamble) # log_to_file(self, oqam_prep, "data/oqam_prep.compl") # log_to_file(self, psubc, "data/psubc_out.compl") # fbmc_pblocks = fbmc_pblocks_timing # log_to_file(self, fbmc_pblocks, "data/fbmc_pblocks_out.compl") beta_mult = self._beta_mult = fbmc_beta_multiplier_vcvc(config.subcarriers, 4, 4 * config.fft_length - 1, 0) self.connect(fbmc_pblocks, beta_mult) log_to_file(self, beta_mult, "data/beta_mult.compl") ## Add virtual subcarriers if config.fft_length > subcarriers: vsubc = self._virtual_subcarrier_extender = vector_padding_dc_null( config.subcarriers, config.fft_length, config.dc_null ) self.connect(beta_mult, vsubc) else: vsubc = self._virtual_subcarrier_extender = beta_mult if options.log: log_to_file(self, vsubc, "data/vsubc_out.compl") ## IFFT, no window, block shift ifft = self._ifft = fft_blocks.fft_vcc(config.fft_length, False, [], True) self.connect(vsubc, ifft) if options.log: log_to_file(self, ifft, "data/ifft_out.compl") # FBMC separate stream + filterbanks separate_oqam = self._separate_oqam = fbmc_separate_vcvc(config.fft_length, 2) poly_netw_1 = self._poly_netw_1 = fbmc_polyphase_network_vcvc( config.fft_length, 4, 4 * config.fft_length - 1, False ) poly_netw_2 = self._poly_netw_2 = fbmc_polyphase_network_vcvc( config.fft_length, 4, 4 * config.fft_length - 1, False ) overlap_p2s = self._overlap_p2s = fbmc_overlapping_parallel_to_serial_vcc(config.fft_length) self.connect(ifft, (separate_oqam, 0), poly_netw_1) self.connect((separate_oqam, 1), poly_netw_2) self.connect(poly_netw_1, (overlap_p2s, 0)) self.connect(poly_netw_2, (overlap_p2s, 1)) ## Pilot blocks (preambles) # pblocks = self._pilot_block_inserter = pilot_block_inserter2(5,False) # self.connect( overlap_p2s, blocks.stream_to_vector(gr.sizeof_gr_complex,config.fft_length/2), pblocks ) # log_to_file(self, pblocks, "data/fbmc_pilot_block_ins_out.compl") if options.log: log_to_file(self, pblocks, "data/pilot_block_ins_out.compl") ## Cyclic Prefix # cp = self._cyclic_prefixer = cyclic_prefixer(config.fft_length, # config.block_length) # cp= blocks.vector_to_stream(gr.sizeof_gr_complex, config.fft_length/2) # self.connect(pblocks, cp ) # self.connect( overlap_p2s,blocks.stream_to_vector(gr.sizeof_gr_complex,config.fft_length/2), cp ) lastblock = overlap_p2s if options.log: log_to_file(self, overlap_p2s, "data/overlap_p2s_out.compl") # Digital Amplifier for resource allocation if config.adaptive_fbmc: rep = blocks.repeat(gr.sizeof_gr_complex, config.frame_length * config.block_length) amp = blocks.multiply_cc() self.connect(lastblock, (amp, 0)) self.connect((self.allocation_src, 3), rep, (amp, 1)) lastblock = amp else: self.connect((self.allocation_src, 3), blocks.null_sink(gr.sizeof_gr_complex)) ## Digital Amplifier # amp = self._amplifier = gr.multiply_const_cc(1) amp = self._amplifier = ofdm.multiply_const_ccf(1.0) self.connect(lastblock, amp) self.set_rms_amplitude(rms_amp) # log_to_file(self, amp, "data/amp_tx_out.compl") if options.log: log_to_file(self, amp, "data/amp_tx_out.compl") ## Tx parameters bandwidth = options.bandwidth or 2e6 bits = 8 * config.data_subcarriers * config.frame_data_blocks # max. QAM256 samples_per_frame = config.frame_length * config.block_length tb = samples_per_frame / bandwidth # set dummy carrier frequency if none available due to baseband mode if options.tx_freq is None: options.tx_freq = 0.0 self.tx_parameters = { "carrier_frequency": options.tx_freq / 1e9, "fft_size": config.fft_length, "cp_size": config.cp_length, "subcarrier_spacing": options.bandwidth / config.fft_length / 1e3, "data_subcarriers": config.data_subcarriers, "bandwidth": options.bandwidth / 1e6, "frame_length": config.frame_length, "symbol_time": (config.cp_length + config.fft_length) / options.bandwidth * 1e6, "max_data_rate": (bits / tb) / 1e6, } ## Setup Output self.connect(amp, self) # Display some information about the setup if config._verbose: self._print_verbage()
def __init__(self, options): gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0,0,0), gr.io_signature(2,2,gr.sizeof_gr_complex)) common_options.defaults(options) config = self.config = station_configuration() config.data_subcarriers = options.subcarriers config.cp_length = options.cp_length config.frame_data_blocks = options.data_blocks config._verbose = options.verbose config.fft_length = options.fft_length config.training_data = default_block_header(config.data_subcarriers, config.fft_length,options) config.tx_station_id = options.station_id config.coding = options.coding if config.tx_station_id is None: raise SystemError, "Station ID not set" config.frame_id_blocks = 1 # FIXME # digital rms amplitude sent to USRP rms_amp = options.rms_amplitude self._options = copy.copy(options) self.servants = [] # FIXME 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.frame_data_part + \ config.training_data.no_pilotsyms config.subcarriers = config.data_subcarriers + \ config.training_data.pilot_subcarriers config.virtual_subcarriers = config.fft_length - config.subcarriers # default values if parameters not set if rms_amp is None: rms_amp = math.sqrt(config.subcarriers) config.rms_amplitude = rms_amp # 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" ## shortcuts blen = config.block_length flen = config.frame_length dsubc = config.data_subcarriers vsubc = config.virtual_subcarriers # ------------------------------------------------------------------------ # # Adaptive Transmitter Concept used_id_bits = config.used_id_bits = 8 #TODO: no constant in source code rep_id_bits = config.rep_id_bits = config.data_subcarriers/used_id_bits #BPSK if config.data_subcarriers % used_id_bits <> 0: raise SystemError,"Data subcarriers need to be multiple of %d" % (used_id_bits) ## Control Part if options.debug: self._control = ctrl = static_tx_control(options) print "Statix TX Control used" else: self._control = ctrl = corba_tx_control(options) print "CORBA TX Control used" id_src = (ctrl,0) mux_src = (ctrl,1) map_src = self._map_src = (ctrl,2) pa_src = (ctrl,3) if options.log: id_src_f = gr.short_to_float() self.connect(id_src,id_src_f) log_to_file(self, id_src_f, "data/id_src_out.float") mux_src_f = gr.short_to_float() self.connect(mux_src,mux_src_f) log_to_file(self, mux_src_f, "data/mux_src_out.float") map_src_s = blocks.vector_to_stream(gr.sizeof_char,config.data_subcarriers) map_src_f = gr.char_to_float() self.connect(map_src,map_src_s,map_src_f) ##log_to_file(self, map_src_f, "data/map_src.float") ##log_to_file(self, pa_src, "data/pa_src_out.float") ## Workaround to avoid periodic structure seed(1) whitener_pn = [randint(0,1) for i in range(used_id_bits*rep_id_bits)] ## ID Encoder id_enc = self._id_encoder = repetition_encoder_sb(used_id_bits,rep_id_bits,whitener_pn) self.connect(id_src,id_enc) if options.log: id_enc_f = gr.char_to_float() self.connect(id_enc,id_enc_f) log_to_file(self, id_enc_f, "data/id_enc_out.float") ## Bitmap Update Trigger # TODO #bmaptrig_stream = concatenate([[1, 2],[0]*(config.frame_data_part-7)]) bmaptrig_stream = concatenate([[1, 1],[0]*(config.frame_data_part-2)]) print"bmaptrig_stream = ",bmaptrig_stream btrig = self._bitmap_trigger = blocks.vector_source_b(bmaptrig_stream.tolist(), True) if options.log: log_to_file(self, btrig, "data/bitmap_trig.char") ## Bitmap Update Trigger for puncturing # TODO if not options.nopunct: #bmaptrig_stream_puncturing = concatenate([[1],[0]*(config.frame_data_part-2)]) bmaptrig_stream_puncturing = concatenate([[1],[0]*(config.frame_data_blocks/2-1)]) btrig_puncturing = self._bitmap_trigger_puncturing = blocks.vector_source_b(bmaptrig_stream_puncturing.tolist(), True) bmapsrc_stream_puncturing = concatenate([[1]*dsubc,[2]*dsubc]) bsrc_puncturing = self._bitmap_src_puncturing = blocks.vector_source_b(bmapsrc_stream_puncturing.tolist(), True, dsubc) if options.log and options.coding and not options.nopunct: log_to_file(self, btrig_puncturing, "data/bitmap_trig_puncturing.char") ## Frame Trigger # TODO ftrig_stream = concatenate([[1],[0]*(config.frame_data_part-1)]) ftrig = self._frame_trigger = blocks.vector_source_b(ftrig_stream.tolist(),True) ## Data Multiplexer # Input 0: control stream # Input 1: encoded ID stream # Inputs 2..n: data streams dmux = self._data_multiplexer = stream_controlled_mux_b() self.connect(mux_src,(dmux,0)) self.connect(id_enc,(dmux,1)) self._data_multiplexer_nextport = 2 if options.log: dmux_f = gr.char_to_float() self.connect(dmux,dmux_f) log_to_file(self, dmux_f, "data/dmux_out.float") ## Modulator mod = self._modulator = generic_mapper_bcv(config.data_subcarriers,options.coding) self.connect(dmux,(mod,0)) self.connect(map_src,(mod,1)) self.connect(btrig,(mod,2)) if options.log: log_to_file(self, mod, "data/mod_out.compl") modi = gr.complex_to_imag(config.data_subcarriers) modr = gr.complex_to_real(config.data_subcarriers) self.connect(mod,modi) self.connect(mod,modr) log_to_file(self, modi, "data/mod_imag_out.float") log_to_file(self, modr, "data/mod_real_out.float") ## Power allocator if options.debug: ## static pa = self._power_allocator = power_allocator(config.data_subcarriers) self.connect(mod,(pa,0)) self.connect(pa_src,(pa,1)) else: ## with CORBA control event channel ns_ip = ctrl.ns_ip ns_port = ctrl.ns_port evchan = ctrl.evchan pa = self._power_allocator = corba_power_allocator(dsubc, \ evchan, ns_ip, ns_port, True) self.connect(mod,(pa,0)) self.connect(id_src,(pa,1)) self.connect(ftrig,(pa,2)) if options.log: log_to_file(self, pa, "data/pa_out.compl") ## Pilot subcarriers psubc = self._pilot_subcarrier_inserter = pilot_subcarrier_inserter() self.connect( pa ,psubc ) pilot_subc = config.training_data.shifted_pilot_tones; print "pilot_subc", pilot_subc stc = stc_encoder( config.subcarriers, config.frame_data_blocks, pilot_subc ) self.connect(psubc, stc) if options.log: log_to_file(self, psubc, "data/psubc_out.compl") log_to_file(self, psubc_2, "data/psubc2_out.compl") log_to_file(self, pa, "data/pa.compl") log_to_file(self, ( stc, 0 ), "data/stc_0.compl") log_to_file(self, ( stc, 1 ), "data/stc_1.compl") ## Add virtual subcarriers if config.fft_length > config.subcarriers: vsubc = self._virtual_subcarrier_extender = \ vector_padding(config.subcarriers, config.fft_length) self.connect(stc,vsubc) vsubc_2 = self._virtual_subcarrier_extender_2 = \ vector_padding(config.subcarriers, config.fft_length) self.connect((stc,1),vsubc_2) else: vsubc = self._virtual_subcarrier_extender = psubc vsubc_2 = self._virtual_subcarrier_extender_2 = psubc_2 log_to_file(self, psubc, "data/psubc.compl") log_to_file(self, stc, "data/stc1.compl") log_to_file(self, (stc,1), "data/stc2.compl") if options.log: log_to_file(self, vsubc, "data/vsubc_out.compl") log_to_file(self, vsubc_2, "data/vsubc2_out.compl") ## IFFT, no window, block shift ifft = self._ifft = fft_blocks.fft_vcc(config.fft_length,False,[],True) self.connect(vsubc,ifft) ifft_2 = self._ifft_2 = fft_blocks.fft_vcc(config.fft_length,False,[],True) self.connect(vsubc_2,ifft_2) if options.log: log_to_file(self, ifft, "data/ifft_out.compl") log_to_file(self, ifft_2, "data/ifft2_out.compl") ## Pilot blocks (preambles) pblocks = self._pilot_block_inserter = pilot_block_inserter(1, False) self.connect( ifft, pblocks ) pblocks_2 = self._pilot_block_inserter_2 = pilot_block_inserter( 2, False) self.connect( ifft_2, pblocks_2 ) if options.log: log_to_file(self, pblocks, "data/pilot_block_ins_out.compl") log_to_file(self, pblocks_2, "data/pilot_block_ins2_out.compl") ## Cyclic Prefix cp = self._cyclic_prefixer = cyclic_prefixer(config.fft_length, config.block_length) self.connect( pblocks, cp ) cp_2 = self._cyclic_prefixer_2 = cyclic_prefixer(config.fft_length, config.block_length) self.connect( pblocks_2, cp_2 ) lastblock = cp lastblock_2 = cp_2 if options.log: log_to_file(self, cp, "data/cp_out.compl") log_to_file(self, cp_2, "data/cp2_out.compl") if options.cheat: ## Artificial Channel # kept to compare with previous system achan_ir = concatenate([[1.0],[0.0]*(config.cp_length-1)]) achan = self._artificial_channel = gr.fir_filter_ccc(1,achan_ir) self.connect( lastblock, achan ) lastblock = achan achan_2 = self._artificial_channel_2 = gr.fir_filter_ccc(1,achan_ir) self.connect( lastblock_2, achan_2 ) lastblock_2 = achan_2 ## Digital Amplifier amp = self._amplifier = ofdm.multiply_const_ccf( 1.0/math.sqrt(2) ) self.connect( lastblock, amp ) amp_2 = self._amplifier_2 = ofdm.multiply_const_ccf( 1.0/math.sqrt(2) ) self.connect( lastblock_2, amp_2 ) self.set_rms_amplitude(rms_amp) if options.log: log_to_file(self, amp, "data/amp_tx_out.compl") log_to_file(self, amp_2, "data/amp_tx2_out.compl") ## Setup Output self.connect(amp,(self,0)) self.connect(amp_2,(self,1)) # ------------------------------------------------------------------------ # # Display some information about the setup if config._verbose: self._print_verbage()