def __init__(self, amplitude, subcarriers): #config = station_configuration() total_subc = subcarriers vlen = total_subc gr.hier_block2.__init__(self, "fbmc_rms_amplifier_grc", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex)) amp = self._amplifier = multiply_const_ccf(1.0) self._subcarriers = subcarriers self.connect(self, amp, self) self.set_rms_amplitude(amplitude)
def __init__(self,amplitude,subcarriers): #config = station_configuration() total_subc = subcarriers vlen = total_subc gr.hier_block2.__init__(self,"ofdm_rms_amplifier_grc", gr.io_signature(1,1,gr.sizeof_gr_complex), gr.io_signature(1,1,gr.sizeof_gr_complex)) amp = self._amplifier = multiply_const_ccf(1.0) self._subcarriers = subcarriers self.connect(self,amp,self) self.set_rms_amplitude(amplitude)
def __init__(self, options): gr.top_block.__init__(self, "ofdm_benchmark") self._bandwidth = options.bandwidth self.servants = [] self._verbose = options.verbose self._options = copy.copy(options) self.ideal = options.ideal self.ideal2 = options.ideal2 rms_amp = options.rms_amplitude self._interpolation = 1 f1 = numpy.array([ -107, 0, 445, 0, -1271, 0, 2959, 0, -6107, 0, 11953, 0, -24706, 0, 82359, 262144 / 2, 82359, 0, -24706, 0, 11953, 0, -6107, 0, 2959, 0, -1271, 0, 445, 0, -107 ], numpy.float64) / 262144. print "Software interpolation: %d" % (self._interpolation) bw = 1.0 / self._interpolation tb = bw / 5 if self._interpolation > 1: self.tx_filter = gr.hier_block2( "filter", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex)) self.tx_filter.connect(self.tx_filter, gr.interp_fir_filter_ccf(2, f1), gr.interp_fir_filter_ccf(2, f1), self.tx_filter) print "New" else: self.tx_filter = None self.decimation = 1 if self.decimation > 1: bw = 0.5 / self.decimation * 1 tb = bw / 5 # gain, sampling rate, passband cutoff, stopband cutoff # passband ripple in dB, stopband attenuation in dB # extra taps filt_coeff = optfir.low_pass(1.0, 1.0, bw, bw + tb, 0.1, 60.0, 1) print "Software decimation filter length: %d" % (len(filt_coeff)) self.rx_filter = gr.fir_filter_ccf(self.decimation, filt_coeff) else: self.rx_filter = None self._setup_tx_path(options) self._setup_rx_path(options) self._setup_rpc_manager() config = self.config = station_configuration() if options.imgxfer: self.rxpath.setup_imgtransfer_sink() if not options.no_decoding: self.rxpath.publish_rx_performance_measure() # capture transmitter's stream to disk #self.dst = gr.file_sink(gr.sizeof_gr_complex,options.to_file) self.dst = self.rxpath if options.force_rx_filter: print "Forcing rx filter usage" self.connect(self.rx_filter, self.dst) self.dst = self.rx_filter if options.ideal or self.ideal2: self._amplifier = ofdm.multiply_const_ccf(1.0) self.connect(self._amplifier, self.dst) self.dst = self._amplifier self.set_rms_amplitude(rms_amp) if options.measure: self.m = throughput_measure(gr.sizeof_gr_complex) self.connect(self.m, self.dst) self.dst = self.m if options.snr is not None: if options.berm is not None: noise_sigma = 380 / 32767.0 #empirically given, gives the received SNR range of (1:28) for tx amp. range of (500:10000) which is set in rm_ber_measurement.py #check for fading channel else: snr_db = options.snr snr = 10.0**(snr_db / 10.0) noise_sigma = sqrt(config.rms_amplitude**2 / snr) print " Noise St. Dev. %f" % (noise_sigma) awgn_chan = blocks.add_cc() #awgn_noise_src = ofdm.complex_white_noise( 0.0, noise_sigma ) awgn_noise_src = analog.fastnoise_source_c(analog.GR_GAUSSIAN, noise_sigma, 0, 8192) self.connect(awgn_noise_src, (awgn_chan, 1)) self.connect(awgn_chan, self.dst) self.dst = awgn_chan if options.freqoff is not None: freq_off = self.freq_off = channel.freq_offset(options.freqoff) dst = self.dst self.connect(freq_off, dst) self.dst = freq_off self.rpc_mgr_tx.add_interface("set_freq_offset", self.freq_off.set_freqoff) if options.multipath: if options.itu_channel: self.fad_chan = channel.itpp_channel(options.bandwidth) self.rpc_mgr_tx.add_interface( "set_channel_profile", self.fad_chan.set_channel_profile) self.rpc_mgr_tx.add_interface("set_norm_doppler", self.fad_chan.set_norm_doppler) else: #self.fad_chan = filter.fir_filter_ccc(1,[1.0,0.0,2e-1+0.1j,1e-4-0.04j]) # filter coefficients for the lab exercise self.fad_chan = filter.fir_filter_ccc(1, [0.3267, 0.8868, 0.3267]) #self.fad_chan = filter.fir_filter_ccc(1,[0,0,0.1,0.2,0.01,0.3])#0.3267,0.8868,0.3267]) #self.fad_chan = channels.selective_fading_model(5, 0.1, False, 1, -1, [0, 0, 0], [0.3267,0.8868,0.3267], 10 ) #self.fad_chan = channels.fading_model(6, 0.05, False); #self.fad_chan = channels.dynamic_channel_model(1000000, 0, 0, 0, 0, 3, 0.01, False, 0, [2e-6,4e-6,8e-6],[0.3267,0.8868,0.3267], 20, 0, 0) self.connect(self.fad_chan, self.dst) self.dst = self.fad_chan if options.samplingoffset is not None: soff = options.samplingoffset interp = moms(1000000 * (1.0 + soff), 1000000) #interp = filter.fractional_resampler_cc(0,1000000*(1.0+soff)/1000000.0) self.connect(interp, self.dst) self.dst = interp if options.record: log_to_file(self, interp, "data/interp_out.compl") tmm = blocks.throttle(gr.sizeof_gr_complex, options.bandwidth) self.connect(tmm, self.dst) self.dst = tmm if options.force_tx_filter: print "Forcing tx filter usage" self.connect(self.tx_filter, self.dst) self.dst = self.tx_filter if options.record: log_to_file(self, self.txpath, "data/txpath_out.compl") if options.scatterplot: print "Scatterplot enabled" self.connect(self.txpath, self.dst) print "Hit Strg^C to terminate" print "Hit Strg^C to terminate" # Display some information about the setup if self._verbose: self._print_verbage()
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(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, 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 __init__ (self, options): gr.top_block.__init__(self, "fbmc_benchmark") self._bandwidth = options.bandwidth self.servants = [] self._verbose = options.verbose self._options = copy.copy( options ) self.ideal = options.ideal self.ideal2 = options.ideal2 rms_amp = options.rms_amplitude #Disable OFDM channel estimation preamble -> Still experimental options.est_preamble = 0 self._interpolation = 1 f1 = numpy.array([-107,0,445,0,-1271,0,2959,0,-6107,0,11953, 0,-24706,0,82359,262144/2,82359,0,-24706,0, 11953,0,-6107,0,2959,0,-1271,0,445,0,-107], numpy.float64)/262144. print "Software interpolation: %d" % (self._interpolation) bw = 1.0/self._interpolation tb = bw/5 if self._interpolation > 1: self.tx_filter = gr.hier_block2("filter", gr.io_signature(1,1,gr.sizeof_gr_complex), gr.io_signature(1,1,gr.sizeof_gr_complex)) self.tx_filter.connect( self.tx_filter, gr.interp_fir_filter_ccf(2,f1), gr.interp_fir_filter_ccf(2,f1), self.tx_filter ) print "New" else: self.tx_filter = None self.decimation = 1 if self.decimation > 1: bw = 0.5/self.decimation * 1 tb = bw/5 # gain, sampling rate, passband cutoff, stopband cutoff # passband ripple in dB, stopband attenuation in dB # extra taps filt_coeff = optfir.low_pass(1.0, 1.0, bw, bw+tb, 0.1, 60.0, 1) print "Software decimation filter length: %d" % (len(filt_coeff)) self.rx_filter = gr.fir_filter_ccf(self.decimation,filt_coeff) else: self.rx_filter = None self._setup_tx_path(options) self._setup_rx_path(options) self._setup_rpc_manager() config = self.config = station_configuration() if options.imgxfer: self.rxpath.setup_imgtransfer_sink() if not options.no_decoding: self.rxpath.publish_rx_performance_measure() # capture transmitter's stream to disk #self.dst = gr.file_sink(gr.sizeof_gr_complex,options.to_file) self.dst= self.rxpath if options.force_rx_filter: print "Forcing rx filter usage" self.connect( self.rx_filter, self.dst ) self.dst = self.rx_filter if options.ideal or self.ideal2: self._amplifier = ofdm.multiply_const_ccf( 1.0 ) self.connect( self._amplifier, self.dst ) self.dst = self._amplifier self.set_rms_amplitude(rms_amp) if options.measure: self.m = throughput_measure(gr.sizeof_gr_complex) self.connect( self.m, self.dst ) self.dst = self.m if options.snr is not None: if options.berm is not None: #noise_sigma = 0.0001/32767.0 noise_sigma = 380/32767.0#250/32767.0 #380/32767.0 #empirically given, gives the received SNR range of (1:28) for tx amp. range of (500:10000) which is set in rm_ber_measurement.py #check for fading channel else: snr_db = options.snr snr = 10.0**(snr_db/10.0) noise_sigma = sqrt( config.rms_amplitude**2 / snr ) print " Noise St. Dev. %d" % (noise_sigma) awgn_chan = blocks.add_cc() #awgn_noise_src = ofdm.complex_white_noise( 0.0, noise_sigma ) #noise_sigma = 0.000000000001 awgn_noise_src = analog.fastnoise_source_c(analog.GR_GAUSSIAN, noise_sigma, 0, 8192) self.connect( awgn_noise_src, (awgn_chan,1) ) self.connect( awgn_chan,self.dst ) #self.connect( awgn_chan, blocks.skiphead( gr.sizeof_gr_complex, 3* config.fft_length ),self.dst ) self.dst = awgn_chan if options.freqoff is not None: freq_off = self.freq_off = channel.freq_offset(options.freqoff ) dst = self.dst self.connect(freq_off, dst) self.dst = freq_off self.rpc_mgr_tx.add_interface("set_freq_offset",self.freq_off.set_freqoff) #log_to_file( self, self.freq_off, "data/TRANSMITTER_OUT.compl" ) if options.multipath: if options.itu_channel: self.fad_chan = channel.itpp_channel(options.bandwidth) self.rpc_mgr_tx.add_interface("set_channel_profile",self.fad_chan.set_channel_profile) else: #self.fad_chan = filter.fir_filter_ccc(1,[1.0,0.0,2e-1+0.1j,1e-4-0.04j]) # filter coefficients for the lab exercise self.fad_chan = filter.fir_filter_ccc(1,[0,0,0.3267,0.8868,0.3267]) self.connect(self.fad_chan, self.dst) self.dst = self.fad_chan if options.samplingoffset is not None: soff = options.samplingoffset interp = moms(1000000*(1.0+soff),1000000) self.connect( interp, self.dst ) self.dst = interp if options.record: log_to_file( self, interp, "data/interp_out.compl" ) tmm =blocks.throttle(gr.sizeof_gr_complex,1e6) self.connect( tmm, self.dst ) self.dst = tmm if options.force_tx_filter: print "Forcing tx filter usage" self.connect( self.tx_filter, self.dst ) self.dst = self.tx_filter if options.record: log_to_file( self, self.txpath, "data/txpath_out.compl" ) if options.scatterplot: print "Scatterplot enabled" self.connect( self.txpath,self.dst ) #log_to_file( self, self.txpath, "data/fbmc_rx_input.compl" ) print "Hit Strg^C to terminate" print "Hit Strg^C to terminate" # Display some information about the setup if self._verbose: self._print_verbage()
def __init__ (self, options): gr.top_block.__init__(self, "ofdm_benchmark") self._bandwidth = options.bandwidth self.servants = [] self._verbose = options.verbose self._options = copy.copy( options ) self.ideal = options.ideal self.ideal2 = options.ideal2 rms_amp = options.rms_amplitude self._interpolation = 1 f1 = numpy.array([-107,0,445,0,-1271,0,2959,0,-6107,0,11953, 0,-24706,0,82359,262144/2,82359,0,-24706,0, 11953,0,-6107,0,2959,0,-1271,0,445,0,-107], numpy.float64)/262144. print "Software interpolation: %d" % (self._interpolation) bw = 1.0/self._interpolation tb = bw/5 if self._interpolation > 1: self.tx_filter = gr.hier_block2("filter", gr.io_signature(1,1,gr.sizeof_gr_complex), gr.io_signature(1,1,gr.sizeof_gr_complex)) self.tx_filter.connect( self.tx_filter, gr.interp_fir_filter_ccf(2,f1), gr.interp_fir_filter_ccf(2,f1), self.tx_filter ) print "New" else: self.tx_filter = None self.decimation = 1 if self.decimation > 1: bw = 0.5/self.decimation * 1 tb = bw/5 # gain, sampling rate, passband cutoff, stopband cutoff # passband ripple in dB, stopband attenuation in dB # extra taps filt_coeff = optfir.low_pass(1.0, 1.0, bw, bw+tb, 0.1, 60.0, 1) print "Software decimation filter length: %d" % (len(filt_coeff)) self.rx_filter = gr.fir_filter_ccf(self.decimation,filt_coeff) else: self.rx_filter = None self._setup_tx_path(options) self._setup_rx_path(options) self._setup_rpc_manager() config = self.config = station_configuration() if options.imgxfer: self.rxpath.setup_imgtransfer_sink() if not options.no_decoding: self.rxpath.publish_rx_performance_measure() # capture transmitter's stream to disk #self.dst = gr.file_sink(gr.sizeof_gr_complex,options.to_file) self.dst= self.rxpath if options.force_rx_filter: print "Forcing rx filter usage" self.connect( self.rx_filter, self.dst ) self.dst = self.rx_filter if options.ideal or self.ideal2: self._amplifier = ofdm.multiply_const_ccf( 1.0 ) self.connect( self._amplifier, self.dst ) self.dst = self._amplifier self.set_rms_amplitude(rms_amp) if options.measure: self.m = throughput_measure(gr.sizeof_gr_complex) self.connect( self.m, self.dst ) self.dst = self.m if options.snr is not None: if options.berm is not None: # empirically determined to reach 30db SNR max in simulation mode noise_sigma = 0.0035 else: snr_db = options.snr snr = 10.0**(snr_db/10.0) noise_sigma = sqrt( config.rms_amplitude**2 / snr ) print " Noise St. Dev. %f" % (noise_sigma) awgn_chan = blocks.add_cc() #awgn_noise_src = ofdm.complex_white_noise( 0.0, noise_sigma ) awgn_noise_src = analog.fastnoise_source_c(analog.GR_GAUSSIAN, noise_sigma, 0, 8192) self.connect( awgn_noise_src, (awgn_chan,1) ) self.connect( awgn_chan, self.dst ) self.dst = awgn_chan if options.freqoff is not None: freq_off = self.freq_off = channel.freq_offset(options.freqoff ) dst = self.dst self.connect(freq_off, dst) self.dst = freq_off self.rpc_mgr_tx.add_interface("set_freq_offset",self.freq_off.set_freqoff) if options.multipath: if options.itu_channel: self.fad_chan = channel.itpp_channel(options.bandwidth) self.rpc_mgr_tx.add_interface("set_channel_profile",self.fad_chan.set_channel_profile) self.rpc_mgr_tx.add_interface("set_norm_doppler",self.fad_chan.set_norm_doppler) else: #self.fad_chan = filter.fir_filter_ccc(1,[1.0,0.0,2e-1+0.1j,1e-4-0.04j]) # filter coefficients for the lab exercise self.fad_chan = filter.fir_filter_ccc(1,[0.3267,0.8868,0.3267]) #self.fad_chan = filter.fir_filter_ccc(1,[0,0,0.1,0.2,0.01,0.3])#0.3267,0.8868,0.3267]) #self.fad_chan = channels.selective_fading_model(5, 0.1, False, 1, -1, [0, 0, 0], [0.3267,0.8868,0.3267], 10 ) #self.fad_chan = channels.fading_model(6, 0.05, False); #self.fad_chan = channels.dynamic_channel_model(1000000, 0, 0, 0, 0, 3, 0.01, False, 0, [2e-6,4e-6,8e-6],[0.3267,0.8868,0.3267], 20, 0, 0) self.connect(self.fad_chan, self.dst) self.dst = self.fad_chan if options.samplingoffset is not None: soff = options.samplingoffset interp = moms(1000000*(1.0+soff),1000000) #interp = filter.fractional_resampler_cc(0,1000000*(1.0+soff)/1000000.0) self.connect( interp, self.dst ) self.dst = interp if options.record: log_to_file( self, interp, "data/interp_out.compl" ) tmm =blocks.throttle(gr.sizeof_gr_complex,options.bandwidth) self.connect( tmm, self.dst ) self.dst = tmm if options.force_tx_filter: print "Forcing tx filter usage" self.connect( self.tx_filter, self.dst ) self.dst = self.tx_filter if options.record: log_to_file( self, self.txpath, "data/txpath_out.compl" ) if options.scatterplot: print "Scatterplot enabled" self.connect( self.txpath,self.dst ) print "Hit Strg^C to terminate" print "Hit Strg^C to terminate" # Display some information about the setup if self._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()