Пример #1
0
    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)
Пример #3
0
    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()
Пример #4
0
    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()
Пример #5
0
    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()
Пример #6
0
    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()
Пример #7
0
  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()
Пример #8
0
  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()
Пример #9
0
  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()