Ejemplo n.º 1
0
  def __init__(self,delay_num,delay_denom):
    gr.hier_block2.__init__(self,"moms_block",
      gr.io_signature(1,1,gr.sizeof_gr_complex),
      gr.io_signature(1,1,gr.sizeof_gr_complex))

    cmplx_to_real  = gr.complex_to_real()
    cmplx_to_img   = gr.complex_to_imag()

    iirf_real = gr.iir_filter_ffd([1.5],[1, -0.5])
    self.moms_real = moms_ff()
    self.moms_real.set_init_ip_fraction(delay_num,delay_denom)

    iirf_imag = gr.iir_filter_ffd([1.5],[1, -0.5])
    self.moms_imag = moms_ff()
    self.moms_imag.set_init_ip_fraction(delay_num,delay_denom)

    float_to_cmplx = gr.float_to_complex()

    self.connect((self,0),            (cmplx_to_real,0))
    self.connect((self,0),            (cmplx_to_img,0))
    self.connect((cmplx_to_real,0),   (iirf_real,0))
    self.connect((cmplx_to_img,0),    (iirf_imag,0))
    self.connect((iirf_real,0),       (self.moms_real,0))
    self.connect((iirf_imag,0),       (self.moms_imag,0))
    self.connect((self.moms_real,0),  (float_to_cmplx,0))
    self.connect((self.moms_imag,0),  (float_to_cmplx,1))
    self.connect((float_to_cmplx,0),  (self,0))
Ejemplo n.º 2
0
 def test_complex_to_imag(self):
     src_data = (0, 1, -1, 3 + 4j, -3 - 4j, -3 + 4j)
     expected_result = (0, 0, 0, 4, -4, 4)
     src = gr.vector_source_c(src_data)
     op = gr.complex_to_imag()
     dst = gr.vector_sink_f()
     self.tb.connect(src, op)
     self.tb.connect(op, dst)
     self.tb.run()
     actual_result = dst.data()
     self.assertFloatTuplesAlmostEqual(expected_result, actual_result, 5)
Ejemplo n.º 3
0
 def test_complex_to_imag (self):
     src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j)
     expected_result = (0, 0, 0, 4, -4, 4)
     src = gr.vector_source_c (src_data)
     op = gr.complex_to_imag ()
     dst = gr.vector_sink_f ()
     self.tb.connect (src, op)
     self.tb.connect (op, dst)
     self.tb.run ()
     actual_result = dst.data ()
     self.assertFloatTuplesAlmostEqual (expected_result, actual_result,5)
Ejemplo n.º 4
0
def complex_to_imag(N):
    op = gr.complex_to_imag()
    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
    return tb
Ejemplo n.º 5
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()
Ejemplo n.º 6
0
    def __init__(self, options, payload='', msgq_limit=2, pad_for_usrp=False):
        """
	Hierarchical block for sending packets

        Packets to be sent are enqueued by calling send_pkt.
        The output is the complex modulated signal at baseband.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param msgq_limit: maximum number of messages in message queue
        @type msgq_limit: int
        @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
        """

	gr.hier_block2.__init__(self, "ofdm_mod",
				gr.io_signature(0, 0, 0),       # Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
	
    
        self._fft_length          = 64
        self._total_sub_carriers  = 53
	self._data_subcarriers    = 48
	self._cp_length           = 16
 	self._regime              = options.regime
	self._symbol_length       = self._fft_length + self._cp_length
        self._role                = options.role
	
	# assuming we have 100Ms/s going to the USRP2 and 80 samples per symbol
	# we can calculate the OFDM symboltime (in microseconds) 
	# depending on the interpolation factor 
	self._symbol_time	  = options.interp*(self._fft_length+self._cp_length)/100
	
        win = []

	if(self._regime == "1" or self._regime == "2"):
	    rotated_const = ofdm_packet_utils.bpsk(self)
        
        elif (self._regime == "3" or self._regime == "4"):	
	    rotated_const = ofdm_packet_utils.qpsk(self)

        elif(self._regime == "5" or self._regime == "6"):
            rotated_const = ofdm_packet_utils.qam16(self) 

        elif(self._regime == "7" or self._regime == "8"):
            rotated_const = ofdm_packet_utils.qam64(self)
	
        # map groups of bits to complex symbols
        self._pkt_input = ftw.ofdm_mapper(rotated_const, msgq_limit, self._data_subcarriers, self._fft_length)
        
        # insert pilot symbols (use pnc block * by lzyou)
        if self._role == 'A':
            print " >>> [FPNC]: *A* Insert Pilot"
            self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 1)
        elif self._role == 'B':
            print " >>> [FPNC]: *B* Insert Pilot"
            self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 2)
        else:
            print " >>> [FTW ]: Insert Pilot"
            self.pilot = ftw.ofdm_pilot_cc(self._data_subcarriers)
        # just for test
        #self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 1)
        #self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 2)
	
        # move subcarriers to their designated place and insert DC  
        self.cmap  = ftw.ofdm_cmap_cc(self._fft_length, self._total_sub_carriers)        

	# inverse fast fourier transform
        self.ifft = gr.fft_vcc(self._fft_length, False, win, False)

        # add cyclic prefix
	from gnuradio import digital
        self.cp_adder = digital.ofdm_cyclic_prefixer(self._fft_length, self._symbol_length)
        self.connect(gr.null_source(gr.sizeof_char), (self.cp_adder, 1))  # Note: dirty modification to accomdate the API change
        
        # scale accordingly
        self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length))
        
	# we need to know the number of OFDM data symbols for preamble and zerogap
	info = ofdm_packet_utils.get_info(payload, options.regime, self._symbol_time)	
	N_sym             = info["N_sym"]
	
	# add training sequence (modify by lzyou)
        if self._role == 'A':
            print " >>> [FPNC]: *A* Insert Preamble"
            self.preamble= ofdm_packet_utils.insert_preamble(self._symbol_length, N_sym, 'A')
        elif self._role == 'B':
            print " >>> [FPNC]: *B* Insert Preamble"
            self.preamble= ofdm_packet_utils.insert_preamble(self._symbol_length, N_sym, 'B')
        else:
            print " >>> [FTW ]: Insert Preamble"
            self.preamble= ofdm_packet_utils.insert_preamble(self._symbol_length, N_sym)        

        # append zero samples at the end (receiver needs that to decode)
        if self._role == None:
            print " >>> [FTW ]: Insert Zerogap"
	    self.zerogap    = ofdm_packet_utils.insert_zerogap(self._symbol_length, N_sym)
        else:
            print " >>> [FPNC]: Insert Zerogap"
            self.zerogap    = ofdm_packet_utils.insert_zerogap(self._symbol_length, N_sym, 'FPNC')

	self.s2v = gr.stream_to_vector(gr.sizeof_gr_complex , self._symbol_length)
	self.v2s = gr.vector_to_stream(gr.sizeof_gr_complex , self._symbol_length)
	
	# swap real and immaginary component before sending (GNURadio/USRP2 bug!)
	if options.swapIQ == True:
		self.gr_complex_to_imag_0 = gr.complex_to_imag(1)
		self.gr_complex_to_real_0 = gr.complex_to_real(1)
		self.gr_float_to_complex_0 = gr.float_to_complex(1)
		self.connect((self.v2s, 0), (self.gr_complex_to_imag_0, 0))
		self.connect((self.v2s, 0), (self.gr_complex_to_real_0, 0))
		self.connect((self.gr_complex_to_real_0, 0), (self.gr_float_to_complex_0, 1))
		self.connect((self.gr_complex_to_imag_0, 0), (self.gr_float_to_complex_0, 0))
		self.connect((self.gr_float_to_complex_0, 0), (self))
	elif options.swapIQ == False:
		self.gr_complex_to_imag_0 = gr.complex_to_imag(1)
		self.gr_complex_to_real_0 = gr.complex_to_real(1)
		self.gr_float_to_complex_0 = gr.float_to_complex(1)
		self.connect((self.v2s, 0), (self.gr_complex_to_imag_0, 0))
		self.connect((self.v2s, 0), (self.gr_complex_to_real_0, 0))
		self.connect((self.gr_complex_to_imag_0, 0), (self.gr_float_to_complex_0, 1))
		self.connect((self.gr_complex_to_real_0, 0), (self.gr_float_to_complex_0, 0))
		self.connect((self.gr_float_to_complex_0, 0), (self))
		
        # connect the blocks
	self.connect((self._pkt_input, 0), (self.pilot, 0))
	self.connect((self._pkt_input,1), (self.preamble, 1))
	self.connect((self.preamble,1), (self.zerogap, 1))
	
	self.connect(self.pilot, self.cmap, self.ifft, self.cp_adder, self.scale, self.s2v, self.preamble, self.zerogap, self.v2s)

        if options.log:
            self.connect((self._pkt_input), gr.file_sink(gr.sizeof_gr_complex * self._data_subcarriers, "ofdm_mapper.dat"))
	    self.connect(self.pilot, gr.file_sink(gr.sizeof_gr_complex * (5 + self._data_subcarriers), "ofdm_pilot.dat"))
	    self.connect(self.cmap, gr.file_sink(gr.sizeof_gr_complex * self._fft_length, "ofdm_cmap.dat"))	
            self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex * self._fft_length, "ofdm_ifft.dat"))
            self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder.dat"))	   
	    self.connect(self.scale, gr.file_sink(gr.sizeof_gr_complex, "ofdm_scale.dat"))
            self.connect(self.preamble, gr.file_sink(gr.sizeof_gr_complex * self._symbol_length, "ofdm_preamble.dat"))
            self.connect(self.zerogap, gr.file_sink(gr.sizeof_gr_complex * self._symbol_length, "ofdm_zerogap.dat"))
Ejemplo n.º 7
0
    def __init__(self, options, msgq_limit=2, pad_for_usrp=False):
        """
	Hierarchical block for sending packets

        Packets to be sent are enqueued by calling send_pkt.
        The output is the complex modulated signal at baseband.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param msgq_limit: maximum number of messages in message queue
        @type msgq_limit: int
        @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
        """

	gr.hier_block2.__init__(self, "ofdm_mod",
				gr.io_signature(0, 0, 0),       # Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
	
    
        self._fft_length          = 64
        self._total_sub_carriers  = 53
	self._data_subcarriers    = 48
	self._cp_length           = 16
 	self._regime              = options.regime
	self._symbol_length       = self._fft_length + self._cp_length
	
	# assuming we have 100Ms/s going to the USRP2 and 80 samples per symbol
	# we can calculate the OFDM symboltime (in microseconds) 
	# depending on the interpolation factor 
	self._symbol_time      = 100000000*(self._symbol_length )/(100*options.bandwidth)
        self._n_sym = options.nsym
	
        win = []
        self._modulation = options.modulation
        if self._modulation == "bpsk":
            rotated_const = ofdm_packet_utils.bpsk(self)
        elif self._modulation == "qpsk":
            rotated_const = ofdm_packet_utils.qpsk(self)
        elif self._modulation == "qam16":
            rotated_const = ofdm_packet_utils.qam16(self)
        elif self._modulation == "qam64":
            rotated_const = ofdm_packet_utils.qam64(self)

#	if(self._regime == "1" or self._regime == "2"):
#	    rotated_const = ofdm_packet_utils.bpsk(self)
 #       
  #      elif (self._regime == "3" or self._regime == "4"):	
	#    rotated_const = ofdm_packet_utils.qpsk(self)
#
 #       elif(self._regime == "5" or self._regime == "6"):
  #          rotated_const = ofdm_packet_utils.qam16(self) 
#
 #       elif(self._regime == "7" or self._regime == "8"):
 #           rotated_const = ofdm_packet_utils.qam64(self)
	
        # map groups of bits to complex symbols
        self._pkt_input = gr_ieee802_11.ofdm_symbol_mapper(rotated_const, msgq_limit, self._data_subcarriers, self._fft_length)
        
        # insert pilot symbols
        self.pilot = gr_ieee802_11.ofdm_pilot_insert(self._data_subcarriers)
	
        # move subcarriers to their designated place and insert DC  
        self.cmap  = gr_ieee802_11.ofdm_carrier_mapper(self._fft_length, self._total_sub_carriers)        

	# inverse fast fourier transform
        self.ifft = gr.fft_vcc(self._fft_length, False, win, False)

        # add cyclic prefix
        self.cp_adder = digital_swig.ofdm_cyclic_prefixer(self._fft_length, self._symbol_length)
        
        # scale accordingly
        self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length))
      
	# we need to know the number of OFDM data symbols for preamble and zerogap
    
    # MODIFIED FROM ORIGINAL
    # Instead of having the OFDM data symbols recorded in a python dictionary, the value of N_sym is updated when the class ofdm_mod invoked. 
	N_sym             = self._n_sym
    
	
	# add training sequence
        self.preamble= ofdm_packet_utils.insert_preamble(self._symbol_length, N_sym)

        # append zero samples at the end (receiver needs that to decode)
	self.zerogap    = ofdm_packet_utils.insert_zerogap(self._symbol_length, N_sym)
        
        # repeat the frame a number of times 
        self.repeat = gr_ieee802_11.ofdm_symbol_repeater(self._symbol_length, options.repetition, N_sym)

	self.s2v = gr.stream_to_vector(gr.sizeof_gr_complex , self._symbol_length)
	self.v2s = gr.vector_to_stream(gr.sizeof_gr_complex , self._symbol_length)
	
	# swap real and immaginary component before sending (GNURadio/USRP2 bug!)
	self.gr_complex_to_imag_0 = gr.complex_to_imag(1)
	self.gr_complex_to_real_0 = gr.complex_to_real(1)
	self.gr_float_to_complex_0 = gr.float_to_complex(1)
	self.connect((self.v2s, 0), (self.gr_complex_to_imag_0, 0))
	self.connect((self.v2s, 0), (self.gr_complex_to_real_0, 0))
	self.connect((self.gr_complex_to_imag_0, 0), (self.gr_float_to_complex_0, 1))
	self.connect((self.gr_complex_to_real_0, 0), (self.gr_float_to_complex_0, 0))
	self.connect((self.gr_float_to_complex_0, 0), (self))
		
        # connect the blocks
	self.connect((self._pkt_input, 0), (self.pilot, 0))
	self.connect((self._pkt_input,1), (self.preamble, 1))
	self.connect((self.preamble,1), (self.zerogap, 1))
	
	#if options.repetition == 1:
	self.connect(self.pilot, self.cmap, self.ifft, self.cp_adder, self.scale, self.s2v, \
        self.preamble, self.zerogap, self.v2s)
                
	#elif options.repetition > 1:
	#self.connect(self.pilot, self.cmap, self.ifft, self.cp_adder, self.scale, self.s2v, self.preamble, self.zerogap, self.repeat, self.v2s)
    
	#else:
	#	print"Error: repetiton must be a integer number >= 1 \n"
	#	sys.exit(1)

        if options.log:
            self.connect((self._pkt_input), gr.file_sink(gr.sizeof_gr_complex * self._data_subcarriers, "ofdm_mapper.dat"))
	    self.connect(self.pilot, gr.file_sink(gr.sizeof_gr_complex * (5 + self._data_subcarriers), "ofdm_pilot.dat"))
	    self.connect(self.cmap, gr.file_sink(gr.sizeof_gr_complex * self._fft_length, "ofdm_cmap.dat"))	
            self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex * self._fft_length, "ofdm_ifft.dat"))
            self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder.dat"))	   
	    self.connect(self.scale, gr.file_sink(gr.sizeof_gr_complex, "ofdm_scale.dat"))
            self.connect(self.preamble, gr.file_sink(gr.sizeof_gr_complex * self._symbol_length, "ofdm_preamble.dat"))
            self.connect(self.zerogap, gr.file_sink(gr.sizeof_gr_complex * self._symbol_length, "ofdm_zerogap.dat"))
Ejemplo n.º 8
0
def complex_to_imag(N):
    op = gr.complex_to_imag()
    tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
    return tb
Ejemplo n.º 9
0
    def __init__(self, options, payload='', msgq_limit=2, pad_for_usrp=False):
        """
	Hierarchical block for sending packets

        Packets to be sent are enqueued by calling send_pkt.
        The output is the complex modulated signal at baseband.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param msgq_limit: maximum number of messages in message queue
        @type msgq_limit: int
        @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
        """

        gr.hier_block2.__init__(
            self,
            "ofdm_mod",
            gr.io_signature(0, 0, 0),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_gr_complex))  # Output signature

        self._fft_length = 64
        self._total_sub_carriers = 53
        self._data_subcarriers = 48
        self._cp_length = 16
        self._regime = options.regime
        self._symbol_length = self._fft_length + self._cp_length
        self._role = options.role

        # assuming we have 100Ms/s going to the USRP2 and 80 samples per symbol
        # we can calculate the OFDM symboltime (in microseconds)
        # depending on the interpolation factor
        self._symbol_time = options.interp * (self._fft_length +
                                              self._cp_length) / 100

        win = []

        if (self._regime == "1" or self._regime == "2"):
            rotated_const = ofdm_packet_utils.bpsk(self)

        elif (self._regime == "3" or self._regime == "4"):
            rotated_const = ofdm_packet_utils.qpsk(self)

        elif (self._regime == "5" or self._regime == "6"):
            rotated_const = ofdm_packet_utils.qam16(self)

        elif (self._regime == "7" or self._regime == "8"):
            rotated_const = ofdm_packet_utils.qam64(self)

        # map groups of bits to complex symbols
        self._pkt_input = ftw.ofdm_mapper(rotated_const, msgq_limit,
                                          self._data_subcarriers,
                                          self._fft_length)

        # insert pilot symbols (use pnc block * by lzyou)
        if self._role == 'A':
            print " >>> [FPNC]: *A* Insert Pilot"
            self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 1)
        elif self._role == 'B':
            print " >>> [FPNC]: *B* Insert Pilot"
            self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 2)
        else:
            print " >>> [FTW ]: Insert Pilot"
            self.pilot = ftw.ofdm_pilot_cc(self._data_subcarriers)
        # just for test
        #self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 1)
        #self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 2)

        # move subcarriers to their designated place and insert DC
        self.cmap = ftw.ofdm_cmap_cc(self._fft_length,
                                     self._total_sub_carriers)

        # inverse fast fourier transform
        self.ifft = gr.fft_vcc(self._fft_length, False, win, False)

        # add cyclic prefix
        from gnuradio import digital
        self.cp_adder = digital.ofdm_cyclic_prefixer(self._fft_length,
                                                     self._symbol_length)
        self.connect(
            gr.null_source(gr.sizeof_char),
            (self.cp_adder,
             1))  # Note: dirty modification to accomdate the API change

        # scale accordingly
        self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length))

        # we need to know the number of OFDM data symbols for preamble and zerogap
        info = ofdm_packet_utils.get_info(payload, options.regime,
                                          self._symbol_time)
        N_sym = info["N_sym"]

        # add training sequence (modify by lzyou)
        if self._role == 'A':
            print " >>> [FPNC]: *A* Insert Preamble"
            self.preamble = ofdm_packet_utils.insert_preamble(
                self._symbol_length, N_sym, 'A')
        elif self._role == 'B':
            print " >>> [FPNC]: *B* Insert Preamble"
            self.preamble = ofdm_packet_utils.insert_preamble(
                self._symbol_length, N_sym, 'B')
        else:
            print " >>> [FTW ]: Insert Preamble"
            self.preamble = ofdm_packet_utils.insert_preamble(
                self._symbol_length, N_sym)

        # append zero samples at the end (receiver needs that to decode)
        if self._role == None:
            print " >>> [FTW ]: Insert Zerogap"
            self.zerogap = ofdm_packet_utils.insert_zerogap(
                self._symbol_length, N_sym)
        else:
            print " >>> [FPNC]: Insert Zerogap"
            self.zerogap = ofdm_packet_utils.insert_zerogap(
                self._symbol_length, N_sym, 'FPNC')

        self.s2v = gr.stream_to_vector(gr.sizeof_gr_complex,
                                       self._symbol_length)
        self.v2s = gr.vector_to_stream(gr.sizeof_gr_complex,
                                       self._symbol_length)

        # swap real and immaginary component before sending (GNURadio/USRP2 bug!)
        if options.swapIQ == True:
            self.gr_complex_to_imag_0 = gr.complex_to_imag(1)
            self.gr_complex_to_real_0 = gr.complex_to_real(1)
            self.gr_float_to_complex_0 = gr.float_to_complex(1)
            self.connect((self.v2s, 0), (self.gr_complex_to_imag_0, 0))
            self.connect((self.v2s, 0), (self.gr_complex_to_real_0, 0))
            self.connect((self.gr_complex_to_real_0, 0),
                         (self.gr_float_to_complex_0, 1))
            self.connect((self.gr_complex_to_imag_0, 0),
                         (self.gr_float_to_complex_0, 0))
            self.connect((self.gr_float_to_complex_0, 0), (self))
        elif options.swapIQ == False:
            self.gr_complex_to_imag_0 = gr.complex_to_imag(1)
            self.gr_complex_to_real_0 = gr.complex_to_real(1)
            self.gr_float_to_complex_0 = gr.float_to_complex(1)
            self.connect((self.v2s, 0), (self.gr_complex_to_imag_0, 0))
            self.connect((self.v2s, 0), (self.gr_complex_to_real_0, 0))
            self.connect((self.gr_complex_to_imag_0, 0),
                         (self.gr_float_to_complex_0, 1))
            self.connect((self.gr_complex_to_real_0, 0),
                         (self.gr_float_to_complex_0, 0))
            self.connect((self.gr_float_to_complex_0, 0), (self))

        # connect the blocks
        self.connect((self._pkt_input, 0), (self.pilot, 0))
        self.connect((self._pkt_input, 1), (self.preamble, 1))
        self.connect((self.preamble, 1), (self.zerogap, 1))

        self.connect(self.pilot, self.cmap, self.ifft, self.cp_adder,
                     self.scale, self.s2v, self.preamble, self.zerogap,
                     self.v2s)

        if options.log:
            self.connect(
                (self._pkt_input),
                gr.file_sink(gr.sizeof_gr_complex * self._data_subcarriers,
                             "ofdm_mapper.dat"))
            self.connect(
                self.pilot,
                gr.file_sink(
                    gr.sizeof_gr_complex * (5 + self._data_subcarriers),
                    "ofdm_pilot.dat"))
            self.connect(
                self.cmap,
                gr.file_sink(gr.sizeof_gr_complex * self._fft_length,
                             "ofdm_cmap.dat"))
            self.connect(
                self.ifft,
                gr.file_sink(gr.sizeof_gr_complex * self._fft_length,
                             "ofdm_ifft.dat"))
            self.connect(
                self.cp_adder,
                gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder.dat"))
            self.connect(self.scale,
                         gr.file_sink(gr.sizeof_gr_complex, "ofdm_scale.dat"))
            self.connect(
                self.preamble,
                gr.file_sink(gr.sizeof_gr_complex * self._symbol_length,
                             "ofdm_preamble.dat"))
            self.connect(
                self.zerogap,
                gr.file_sink(gr.sizeof_gr_complex * self._symbol_length,
                             "ofdm_zerogap.dat"))
Ejemplo n.º 10
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()