Beispiel #1
0
  def enable_info_tx(self,unique_id,userid):
    """
    create servant for info_tx interface and give him our specifications.
    only fixed data should go here!
    """

    config = station_configuration()
    carrier_freq = 0.0
    bandwidth = self._bandwidth or 2e6
    if config.coding:
        bits = 6*config.data_subcarriers*config.frame_data_blocks # max. QAM256
    else:
        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
    infotx = info_tx_i(subcarriers= config.data_subcarriers,
                       fft_window=config.fft_length,
                       cp_length=config.cp_length,
                       carrier_freq=carrier_freq,
                       symbol_time=config.block_length/bandwidth,
                       bandwidth=bandwidth,
                       subbandwidth=bandwidth/config.fft_length,
                       max_datarate=(bits/tb),
                       burst_length=config.frame_length
                       )
    self.servants.append(general_corba_servant(str(unique_id),infotx))
    
    print "Enabled info_tx, id: %s" % (unique_id)
Beispiel #2
0
  def __init__(self, freq_off):
    gr.hier_block2.__init__(self, "freq_offset", 
        gr.io_signature(1,1,gr.sizeof_gr_complex),
        gr.io_signature(1,1,gr.sizeof_gr_complex))

    freqoff = freq_off
    config = self.config = station_configuration()
    
    print "Artificial Frequency Offset: ",freqoff
    freq_shift = blocks.multiply_cc()
    norm_freq = freqoff / config.fft_length
    freq_off_src = self.freq_off_src = analog.sig_source_c(1.0, analog.GR_SIN_WAVE, norm_freq, 1.0, 0.0 )
    self.connect( self,( freq_shift, 0 )  )
    self.connect( freq_off_src, ( freq_shift, 1 ) )
    self.connect( freq_shift, self )
Beispiel #3
0
    def __init__(self, freq_off):
        gr.hier_block2.__init__(self, "freq_offset",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                gr.io_signature(1, 1, gr.sizeof_gr_complex))

        freqoff = freq_off
        config = self.config = station_configuration()

        print "Artificial Frequency Offset: ", freqoff
        freq_shift = blocks.multiply_cc()
        norm_freq = freqoff / config.fft_length
        freq_off_src = self.freq_off_src = analog.sig_source_c(
            1.0, analog.GR_SIN_WAVE, norm_freq, 1.0, 0.0)
        self.connect(self, (freq_shift, 0))
        self.connect(freq_off_src, (freq_shift, 1))
        self.connect(freq_shift, self)
Beispiel #4
0
    def __init__(self, options):
        gr.top_block.__init__(self, "ofdm_tx")

        self._tx_freq = options.tx_freq  # tranmitter's center frequency
        self._tx_subdev_spec = options.tx_subdev_spec  # daughterboard to use
        self._fusb_block_size = options.fusb_block_size  # usb info for USRP
        self._fusb_nblocks = options.fusb_nblocks  # usb info for USRP
        self._which = options.which_usrp
        self._bandwidth = options.bandwidth
        self.servants = []

        self._interface = options.interface
        self._mac_addr = options.mac_addr

        self._options = copy.copy(options)

        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 = 0.5 / self._interpolation
        tb = bw / 5
        if self._interpolation > 1:
            self.filter = gr.hier_block2(
                "filter", gr.io_signature(1, 1, gr.sizeof_gr_complex),
                gr.io_signature(1, 1, gr.sizeof_gr_complex))
            self.filter.connect(self.filter, gr.interp_fir_filter_ccf(2, f1),
                                gr.interp_fir_filter_ccf(2, f1), self.filter)

            print "New"
#
#
#      self.filt_coeff = optfir.low_pass(1.0, 1.0, bw, bw+tb, 0.2, 60.0, 0)
#      self.filter = gr.interp_fir_filter_ccf(self._interpolation,self.filt_coeff)
#      print "Software interpolation filter length: %d" % (len(self.filt_coeff))
        else:
            self.filter = None

        if not options.from_file is None:
            # sent captured file to usrp
            self.src = gr.file_source(gr.sizeof_gr_complex, options.from_file)
            self._setup_usrp_sink()
            if hasattr(self, "filter"):
                self.connect(self.src, self.filter, self.u)  #,self.filter
            else:
                self.connect(self.src, self.u)

            return

        self._setup_tx_path(options)

        config = station_configuration()

        self.enable_info_tx("info_tx", "pa_user")
        #    if not options.no_cheat:
        #      self.txpath.enable_channel_cheating("channelcheat")
        self.txpath.enable_txpower_adjust("txpower")
        self.txpath.publish_txpower("txpower_info")
        #self.enable_txfreq_adjust("txfreq")

        if options.nullsink:
            self.dst = gr.null_sink(gr.sizeof_gr_complex)
            self.dst_2 = gr.null_sink(gr.sizeof_gr_complex)

        else:
            if not options.to_file is None:
                # capture transmitter's stream to disk
                self.dst = gr.file_sink(gr.sizeof_gr_complex, options.to_file)
                self.dst_2 = gr.file_sink(gr.sizeof_gr_complex,
                                          options.to_file)
                tmp = gr.throttle(gr.sizeof_gr_complex, 1e5)
                tmp_2 = gr.throttle(gr.sizeof_gr_complex, 1e5)
                self.connect(tmp, self.dst)
                self.connect(tmp_2, self.dst_2)
                self.dst = tmp
                self.dst_2 = tmp_2

                if options.force_filter:
                    print "Forcing filter usage"
                    self.connect(self.filter, self.dst)
                    self.dst = self.filter

            else:
                # connect transmitter to usrp
                self._setup_usrp_sink()
                if options.dyn_freq:
                    self.enable_txfreq_adjust("txfreq")

                if self.filter is not None:
                    self.connect(self.filter, self.dst)
                    self.dst = self.filter

                if options.record:
                    log_to_file(self, self.txpath, "data/txpath_out.compl")

                #self.publish_spectrum( 256 )

        if options.measure:
            self.m = throughput_measure(gr.sizeof_gr_complex)
            self.connect(self.m, self.dst)
            self.dst = self.m

        if options.samplingoffset is not None:
            soff = options.samplingoffset
            interp = gr.fractional_interpolator_cc(0.0, soff)
            self.connect(interp, self.dst)
            self.dst = interp

        if options.snr is not None:

            #      if options.berm is not None:
            #          noise_sigma = 380 #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 = gr.add_cc()
            awgn_noise_src = ofdm.complex_white_noise(0.0, noise_sigma)
            self.connect(awgn_noise_src, (awgn_chan, 1))
            self.connect(awgn_chan, self.dst)
            self.dst = awgn_chan

            if options.berm is False:
                fad_chan = itpp.tdl_channel()  #[0, -7, -20], [0, 2, 6]
                #fad_chan.set_norm_doppler( 1e-9 )
                #fad_chan.set_LOS( [500.,0,0] )
                fad_chan.set_channel_profile(itpp.ITU_Pedestrian_A, 5e-8)
                fad_chan.set_norm_doppler(1e-8)
                #        fad_chan = gr.fir_filter_ccc(1,[1.0,0.0,2e-1+0.1j,1e-4-0.04j])
                self.connect(fad_chan, self.dst)
                self.dst = fad_chan

        if options.freqoff is not None:
            freq_shift = gr.multiply_cc()
            norm_freq = options.freqoff / config.fft_length
            freq_off_src = gr.sig_source_c(1.0, gr.GR_SIN_WAVE, norm_freq, 1.0,
                                           0.0)
            self.connect(freq_off_src, (freq_shift, 1))
            dst = self.dst
            self.connect(freq_shift, dst)
            self.dst = freq_shift

        self.connect((self.txpath, 0), self.dst)
        self.connect((self.txpath, 1), self.dst_2)

        if options.cheat:
            self.txpath.enable_channel_cheating("channelcheat")

        print "Hit Strg^C to terminate"
Beispiel #5
0
  def __init__ (self, options):
    gr.top_block.__init__(self, "ofdm_benchmark")

    ##self._tx_freq            = options.tx_freq         # tranmitter's center frequency
    ##self._tx_subdev_spec     = options.tx_subdev_spec  # daughterboard to use
    ##self._fusb_block_size    = options.fusb_block_size # usb info for USRP
    ##self._fusb_nblocks       = options.fusb_nblocks    # usb info for USRP
    ##self._which              = options.which_usrp
    self._bandwidth          = options.bandwidth
    self.servants = []
    self._verbose            = options.verbose
    
    ##self._interface          = options.interface
    ##self._mac_addr           = options.mac_addr

    self._options = copy.copy( options )


    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_filter2 = 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 )
      self.tx_filter2.connect( self.tx_filter2, gr.interp_fir_filter_ccf(2,f1),
                           gr.interp_fir_filter_ccf(2,f1), self.tx_filter2 )
      print "New"

    else:
      self.tx_filter = None
      self.tx_filter2 = 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)
      self.rx_filter2 = gr.fir_filter_ccf(self.decimation,filt_coeff)
    else:
      self.rx_filter = None
      self.rx_filter2 = None
      
      
##    if not options.from_file is None:
##      # sent captured file to usrp
##      self.src = gr.file_source(gr.sizeof_gr_complex,options.from_file)
##      self._setup_usrp_sink()
##      if hasattr(self, "filter"):
##        self.connect(self.src,self.filter,self.u) #,self.filter
##      else:
##        self.connect(self.src,self.u)
##      
##      return 
    
    
    
    self._setup_tx_path(options)
    self._setup_rx_path(options)
    
    config = station_configuration()
    
    self.enable_info_tx("info_tx", "pa_user")
#    if not options.no_cheat:
#      self.txpath.enable_channel_cheating("channelcheat")
    self.txpath.enable_txpower_adjust("txpower")
    self.txpath.publish_txpower("txpower_info")
    
    if options.disable_equalization or options.ideal:
        #print "CHANGE set_k"
        self.rxpath.enable_estim_power_adjust("estim_power")
        #self.rxpath.publish_estim_power("txpower_info")
         
    #self.enable_txfreq_adjust("txfreq")
    
    

    if options.imgxfer:
      self.rxpath.setup_imgtransfer_sink()
    
    if not options.no_decoding:
      self.rxpath.publish_rx_performance_measure()
      
    


    self.dst	= (self.rxpath,0)
    self.dst2 	= (self.rxpath,1)
    
    if options.force_rx_filter:
      print "Forcing rx filter usage"
      self.connect( self.rx_filter, self.dst )
      self.connect( self.rx_filter2, self.dst2 )
      self.dst = self.rx_filter
      self.dst2 = self.rx_filter2
    
    
    if options.measure:
      self.m = throughput_measure(gr.sizeof_gr_complex)
      self.m2 = throughput_measure(gr.sizeof_gr_complex)
      self.connect( self.m, self.dst )
      self.connect( self.m2, self.dst2 )
      self.dst = self.m
      self.dst2 = self.m2


    if options.snr is not None:
      if options.berm is not False:
          noise_sigma = 380 #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_chan2 = blocks.add_cc()
      awgn_noise_src = ofdm.complex_white_noise( 0.0, noise_sigma )
      awgn_noise_src2 = ofdm.complex_white_noise( 0.0, noise_sigma )
      self.connect( awgn_chan, self.dst )
      self.connect( awgn_chan2, self.dst2 )
      self.connect( awgn_noise_src, (awgn_chan,1) )
      self.connect( awgn_noise_src2, (awgn_chan2,1) )  
      self.dst = awgn_chan
      self.dst2 = awgn_chan2



    if options.freqoff is not None:
      freq_shift = blocks.multiply_cc()
      freq_shift2 = blocks.multiply_cc()
      norm_freq = options.freqoff / config.fft_length
      freq_off_src = analog.sig_source_c(1.0, analog.GR_SIN_WAVE, norm_freq, 1.0, 0.0 )
      freq_off_src2 = analog.sig_source_c(1.0, analog.GR_SIN_WAVE, norm_freq, 1.0, 0.0 )
      self.connect( freq_off_src, ( freq_shift, 1 ) )
      self.connect( freq_off_src2, ( freq_shift2, 1 ) )
      dst = self.dst
      dst2 = self.dst2
      self.connect( freq_shift, dst )
      self.connect( freq_shift2, dst2 )
      self.dst = freq_shift
      self.dst2 = freq_shift2


    if options.multipath:
      if options.itu_channel:
        fad_chan = itpp.tdl_channel(  ) #[0, -7, -20], [0, 2, 6]
          #fad_chan.set_norm_doppler( 1e-9 )
          #fad_chan.set_LOS( [500.,0,0] )
        fad_chan2 = itpp.tdl_channel(  )
        fad_chan.set_channel_profile( itpp.ITU_Pedestrian_A, 5e-8 )
        fad_chan.set_norm_doppler( 1e-8 )
        fad_chan2.set_channel_profile( itpp.ITU_Pedestrian_A, 5e-8 )
        fad_chan2.set_norm_doppler( 1e-8 )
      else:
        fad_chan = gr.fir_filter_ccc(1,[1.0,0.0,2e-1+0.1j,1e-4-0.04j])
        fad_chan2 = gr.fir_filter_ccc(1,[1.0,0.0,2e-1+0.1j,1e-4-0.04j])
        
      self.connect( fad_chan, self.dst )
      self.connect( fad_chan2, self.dst2 )
      self.dst = fad_chan
      self.dst2 = fad_chan2

    if options.samplingoffset is not None:
      soff = options.samplingoffset
      interp = moms(1000000+soff,1000000)
      interp2 = moms(1000000+soff,1000000)
      self.connect( interp, self.dst )
      self.connect( interp2, self.dst2 )
      self.dst = interp
      self.dst2 = interp2
      
      if options.record:
       log_to_file( self, interp, "data/interp_out.compl" )
       log_to_file( self, interp2, "data/interp2_out.compl" )
    
    tmm =blocks.throttle(gr.sizeof_gr_complex,self._bandwidth)
    tmm2 =blocks.throttle(gr.sizeof_gr_complex,self._bandwidth)
    tmm_add = blocks.add_cc()
    tmm2_add = blocks.add_cc()
    self.connect( tmm, tmm_add )
    self.connect( tmm2, (tmm_add,1) )
    self.connect( tmm, tmm2_add )
    self.connect( tmm2, (tmm2_add,1) )
    self.connect( tmm_add, self.dst )
    self.connect( tmm2_add, self.dst2 )
    self.dst = tmm
    self.dst2 = tmm2
    
    inter = blocks.interleave(gr.sizeof_gr_complex)
    deinter = blocks.deinterleave(gr.sizeof_gr_complex)
    
    self.connect(inter, deinter)
    self.connect((deinter,0),self.dst)
    self.connect((deinter,1),self.dst2)
    self.dst = inter
    self.dst2 = (inter,1)
    
    
    if options.force_tx_filter:
      print "Forcing tx filter usage"
      self.connect( self.tx_filter, self.dst )
      self.connect( self.tx_filter2, self.dst2 )
      self.dst = self.tx_filter
      self.dst2 = self.tx_filter2
    if options.record:
      log_to_file( self, self.txpath, "data/txpath_out.compl" )
      log_to_file( self, self.txpath2, "data/txpath2_out.compl" )
      
    if options.nullsink:
        self.connect(gr.null_source(gr.sizeof_gr_complex), self.dst)
        self.connect(gr.null_source(gr.sizeof_gr_complex), self.dst2)
        self.dst = gr.null_sink(gr.sizeof_gr_complex)
        self.dst2 = gr.null_sink(gr.sizeof_gr_complex)
        
    
    self.connect( self.txpath,self.dst )
    self.connect( (self.txpath,1),self.dst2 )
    
    
    if options.cheat:
      self.txpath.enable_channel_cheating("channelcheat")

    
      
    print "Hit Strg^C to terminate"

    if options.event_rxbaseband:
      self.publish_rx_baseband_measure()
      
      
    if options.with_old_gui:
      self.publish_spectrum(256)
      self.rxpath.publish_ctf("ctf_display")
      self.rxpath.publish_ber_measurement(["ber"])
      self.rxpath.publish_average_snr(["totalsnr"])
      if options.sinr_est:
        self.rxpath.publish_sinrsc("sinrsc_display")
      

    
    print "Hit Strg^C to terminate"


    # Display some information about the setup
    if self._verbose:
        self._print_verbage()
Beispiel #6
0
  def __init__ (self, options):
    gr.top_block.__init__(self, "ofdm_mrrc_benchmark")

    ##self._tx_freq            = options.tx_freq         # tranmitter's center frequency
    ##self._tx_subdev_spec     = options.tx_subdev_spec  # daughterboard to use
    ##self._fusb_block_size    = options.fusb_block_size # usb info for USRP
    ##self._fusb_nblocks       = options.fusb_nblocks    # usb info for USRP
    ##self._which              = options.which_usrp
    self._bandwidth          = options.bandwidth
    self.servants = []
    self._verbose            = options.verbose
    
    ##self._interface          = options.interface
    ##self._mac_addr           = options.mac_addr

    self._options = copy.copy( options )


    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_filter2 = 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 )
      self.tx_filter2.connect( self.tx_filter2, gr.interp_fir_filter_ccf(2,f1),
                           gr.interp_fir_filter_ccf(2,f1), self.tx_filter2 )
      print "New"

    else:
      self.tx_filter = None
      self.tx_filter2 = 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)
      self.rx_filter2 = gr.fir_filter_ccf(self.decimation,filt_coeff)
    else:
      self.rx_filter = None
      self.rx_filter2 = None
      
      
##    if not options.from_file is None:
##      # sent captured file to usrp
##      self.src = gr.file_source(gr.sizeof_gr_complex,options.from_file)
##      self._setup_usrp_sink()
##      if hasattr(self, "filter"):
##        self.connect(self.src,self.filter,self.u) #,self.filter
##      else:
##        self.connect(self.src,self.u)
##      
##      return 
    
    
    
    self._setup_tx_path(options)
    self._setup_rx_path(options)
    self._setup_rpc_manager()
    
    config = self.config = station_configuration()
    
    #self.enable_txfreq_adjust("txfreq")
    
    

    if options.imgxfer:
      self.rxpath.setup_imgtransfer_sink()
    
    if not options.no_decoding:
      self.rxpath.publish_rx_performance_measure()
      
    


    self.dst	= (self.rxpath,0)
    self.dst2 	= (self.rxpath,1)
    
    if options.force_rx_filter:
      print "Forcing rx filter usage"
      self.connect( self.rx_filter, self.dst )
      self.connect( self.rx_filter2, self.dst2 )
      self.dst = self.rx_filter
      self.dst2 = self.rx_filter2
    
    
    if options.measure:
      self.m = throughput_measure(gr.sizeof_gr_complex)
      self.m2 = throughput_measure(gr.sizeof_gr_complex)
      self.connect( self.m, self.dst )
      self.connect( self.m2, self.dst2 )
      self.dst = self.m
      self.dst2 = self.m2


    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
          print " Noise St. Dev. %f" % (noise_sigma)#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_chan2 = blocks.add_cc()
      awgn_noise_src = analog.fastnoise_source_c(analog.GR_GAUSSIAN, noise_sigma, 0, 8192)
      awgn_noise_src2 = analog.fastnoise_source_c(analog.GR_GAUSSIAN, noise_sigma*2, 0, 2192)
      self.connect( awgn_chan, self.dst )
      self.connect( awgn_chan2, self.dst2 )
      self.connect( awgn_noise_src, (awgn_chan,1) )
      self.connect( awgn_noise_src2, (awgn_chan2,1) )  
      self.dst = awgn_chan
      self.dst2 = awgn_chan2



    if options.freqoff is not None:
      freq_off = self.freq_off = channel.freq_offset(options.freqoff )
      freq_off2 = self.freq_off2  = channel.freq_offset(options.freqoff )
      dst = self.dst
      dst2 = self.dst2
      self.connect( freq_off, dst )
      self.connect( freq_off2, dst2 )
      self.dst = freq_off
      self.dst2 = freq_off2
      self.rpc_mgr_tx.add_interface("set_freq_offset",self.freq_off.set_freqoff)
      self.rpc_mgr_tx.add_interface("set_freq_offset2",self.freq_off2.set_freqoff)


    if options.multipath:
      if options.itu_channel:
        self.fad_chan = channel.itpp_channel(options.bandwidth)
          #fad_chan.set_norm_doppler( 1e-9 )
          #fad_chan.set_LOS( [500.,0,0] )
        self.fad_chan2 = channel.itpp_channel(options.bandwidth)
        self.fad_chan.set_channel_profile( itpp.ITU_Pedestrian_A, 5e-8 )
        self.fad_chan.set_norm_doppler( 1e-8 )
        self.fad_chan2.set_channel_profile( itpp.ITU_Pedestrian_A, 5e-8 )
        self.fad_chan2.set_norm_doppler( 1e-8 )
        self.rpc_mgr_tx.add_interface("set_channel_profile",self.fad_chan.set_channel_profile)
        self.rpc_mgr_tx.add_interface("set_channel_profile",self.fad_chan2.set_channel_profile)
      else:
        fad_chan = filter.fir_filter_ccc(1,[1.0,0.0,2e-1+0.1j,1e-4-0.04j])
        fad_chan2 = filter.fir_filter_ccc(1,[1.0,0.0,2e-1+0.1j,1e-4-0.04j])
        
      self.connect( self.fad_chan, self.dst )
      self.connect( self.fad_chan2, self.dst2 )
      self.dst = self.fad_chan
      self.dst2 = self.fad_chan2

    if options.samplingoffset is not None:
      soff = options.samplingoffset
      interp = moms(1000000*(1.0+soff),1000000)
      interp2 = moms(1000000*(1.0+soff),1000000)
      self.connect( interp, self.dst )
      self.connect( interp2, self.dst2 )
      self.dst = interp
      self.dst2 = interp2
      
      if options.record:
       log_to_file( self, interp, "data/interp_out.compl" )
       log_to_file( self, interp2, "data/interp2_out.compl" )
    
    tmm =blocks.throttle(gr.sizeof_gr_complex, 1e6)
    #tmm2 =blocks.throttle(gr.sizeof_gr_complex, 1e6)
    
    #self.connect( tmm, self.dst )
    #self.connect( tmm2, self.dst2 )
    #self.dst = tmm
    #self.dst2 = tmm2
    
    #inter = blocks.interleave(gr.sizeof_gr_complex)
    #deinter = blocks.deinterleave(gr.sizeof_gr_complex)
    
    # Interleaving input/output streams
    ##self.connect(inter, deinter)
    #self.connect((deinter,0),self.dst)
    #self.connect((deinter,1),self.dst2)
    #self.dst = inter
    #self.dst2 = (inter,1)
    
    
    if options.force_tx_filter:
      print "Forcing tx filter usage"
      self.connect( self.tx_filter, self.dst )
      self.connect( self.tx_filter2, self.dst2 )
      self.dst = self.tx_filter
      self.dst2 = self.tx_filter2
    if options.record:
      log_to_file( self, self.txpath, "data/txpath_out.compl" )
      log_to_file( self, self.txpath2, "data/txpath2_out.compl" )
      
    if options.nullsink:
        self.connect(gr.null_source(gr.sizeof_gr_complex), self.dst)
        self.connect(gr.null_source(gr.sizeof_gr_complex), self.dst2)
        self.dst = gr.null_sink(gr.sizeof_gr_complex)
        self.dst2 = gr.null_sink(gr.sizeof_gr_complex)
        
    
    self.connect( self.txpath,tmm,self.dst )
    self.connect( tmm,self.dst2 )
    #self.connect( self.txpath,self.dst2 )
    
    print "Hit Strg^C to terminate"

    if self._verbose:
        self._print_verbage()
  def __init__( self, options, log = False ):
    
    ## Read configuration
    config = station_configuration()
    
    fft_length    = config.fft_length
    cp_length     = config.cp_length
    block_header  = config.training_data
    data_subc     = config.data_subcarriers
    virtual_subc  = config.virtual_subcarriers
    total_subc    = config.subcarriers
    block_length  = config.block_length
    frame_length  = config.frame_length
    
    L             = block_header.mm_periodic_parts
    
    frame_data_blocks    = options.data_blocks
    
    
    ## Set Input/Output signature
    gr.hier_block2.__init__( self, 
        "ofdm_inner_receiver",
        gr.io_signature(
            1, 1,
            gr.sizeof_gr_complex ),
        gr.io_signature4(
            4, 4,
            gr.sizeof_gr_complex * total_subc,    # OFDM blocks
            gr.sizeof_char,                       # Frame start
            gr.sizeof_float * total_subc,         # Normalized |CTF|^2
            gr.sizeof_float * total_subc ) )      # Normalized |CTF|^2
    
    
    ## Input and output ports
    self.input  = rx_input = (self,0)

    
    out_ofdm_blocks = ( self, 0 )
    out_frame_start = ( self, 1 )
    out_disp_ctf    = ( self, 2 )
    out_disp_ctf2    = ( self, 3 )
    
    ## pre-FFT processing
    
    
    ## Compute autocorrelations for S&C preamble
    ## and cyclic prefix
    sc_metric = autocorrelator( fft_length/2, fft_length/2 )
    gi_metric = autocorrelator( fft_length, cp_length )
    
    self.connect( rx_input, sc_metric )
    self.connect( rx_input, gi_metric )
    
    ## Sync. Output contains OFDM blocks
    sync = ofdm.time_sync( fft_length, cp_length )
    self.connect( rx_input, ( sync, 0 ) )
    self.connect( sc_metric, ( sync, 1 ) )
    self.connect( gi_metric, ( sync, 2 ) )
    ofdm_blocks = ( sync, 0 )
    frame_start = ( sync, 1 )
    
    if options.disable_time_sync or options.ideal:
      terminate_stream(self, ofdm_blocks)
      terminate_stream(self, frame_start)
      
      serial_to_parallel = blocks.stream_to_vector(gr.sizeof_gr_complex,block_length)
      discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
      ofdm_blocks = discard_cp
      self.connect( rx_input, serial_to_parallel, discard_cp )
      
      frame_start = [0]*frame_length
      frame_start[0] = 1
      frame_start = blocks.vector_source_b(frame_start,True)
      
      print "Disabled time synchronization stage"
    
    
    
    ## Extract preamble, feed to Morelli & Mengali frequency offset estimator
    assert( block_header.mm_preamble_pos == 0 )
    morelli_foe = ofdm.mm_frequency_estimator( fft_length, L )
    sampler_preamble = ofdm.vector_sampler( gr.sizeof_gr_complex * fft_length,
                                            1 )
    self.connect( ofdm_blocks, ( sampler_preamble, 0 ) )
    self.connect( frame_start, ( sampler_preamble, 1 ) )
    self.connect( sampler_preamble, morelli_foe )
    freq_offset = morelli_foe
    
    
    
    ## Adaptive LMS FIR filtering of frequency offset
    lms_fir = ofdm.lms_fir_ff( 20, 1e-3 ) # TODO: verify parameter choice
    self.connect( freq_offset, lms_fir )
    freq_offset = lms_fir
    log_to_file(self, lms_fir, "data/foe_21.float")
    
#    log_to_file(self, lms_fir, "data/lms_fir.float")
#    log_to_file(self, lms_fir2, "data/lms_fir2.float")
    
    if options.disable_freq_sync or options.ideal:
       terminate_stream(self, freq_offset)
       freq_offset = blocks.vector_source_f([0.0],True)
       print "Disabled frequency synchronization stage"
    
    ## Correct frequency shift, feed-forward structure
    frequency_shift = ofdm.frequency_shift_vcc( fft_length, -1.0/fft_length,
                                                cp_length )
    self.connect( ofdm_blocks, ( frequency_shift, 0 ) )
    self.connect( freq_offset, ( frequency_shift, 1 ) )
    self.connect( frame_start, ( frequency_shift, 2 ) )
    ofdm_blocks = frequency_shift
    
    
    ## FFT
    fft = fft_blocks.fft_vcc( fft_length, True, [], True )
    self.connect( ofdm_blocks, fft )
    ofdm_blocks = fft
    
    ## Remove virtual subcarriers
    if fft_length > data_subc:
      subcarrier_mask = ofdm.vector_mask( fft_length, virtual_subc/2,
                                           total_subc, [] )
      self.connect( ofdm_blocks, subcarrier_mask )
      ofdm_blocks = subcarrier_mask
      
       ## Least Squares estimator for channel transfer function (CTF)
    
    
      # if options.logcir:
          # log_to_file( self, ofdm_blocks, "data/OFDM_Blocks.compl" )
          
          # inv_preamble_fd = numpy.array( block_header.pilotsym_fd[ 
            # block_header.channel_estimation_pilot[0] ] )
          # print "Channel estimation pilot: ", inv_preamble_fd
          # inv_preamble_fd = 1. / inv_preamble_fd
          # LS_channel_estimator0 = ofdm.multiply_const_vcc( list( inv_preamble_fd ) )
          # self.connect( ofdm_blocks, LS_channel_estimator0, blocks.null_sink(gr.sizeof_gr_complex*total_subc))
          # log_to_file( self, LS_channel_estimator0, "data/OFDM_Blocks_eq.compl" )
          
    ## post-FFT processing
      
    
    
    ## extract channel estimation preamble from frame
    
    if options.est_preamble==1:
        chest_pre_trigger = blocks.delay( gr.sizeof_char, 
                                      1 )
        sampled_chest_preamble = \
          ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )
        self.connect( frame_start,       chest_pre_trigger )
        self.connect( chest_pre_trigger, ( sampled_chest_preamble, 1 ) )
        self.connect( ofdm_blocks,       ( sampled_chest_preamble, 0 ) )
        
        
        ## Least Squares estimator for channel transfer function (CTF)
        
        # Taking inverse for estimating h11 (h12)
        inv_preamble_fd_1 = numpy.array( block_header.pilotsym_fd_1[ 
            block_header.channel_estimation_pilot[0] ] )
        print "inv_preamble_fd_1: ",inv_preamble_fd_1
        inv_preamble_fd_1 = inv_preamble_fd_1[0::2]
        #print "inv_preamble_fd_1 ", inv_preamble_fd_1
        
        # Taking inverse for estimating h21 (h22)
        inv_preamble_fd_2 = numpy.array( block_header.pilotsym_fd_2[ 
            block_header.channel_estimation_pilot[0] ] )
        print "inv_preamble_fd_2: ",inv_preamble_fd_2
        inv_preamble_fd_2 = inv_preamble_fd_2[1::2]
        #print "inv_preamble_fd_2 ", inv_preamble_fd_2
        
        print "inv_preamble_fd_1: ",inv_preamble_fd_1
        print "inv_preamble_fd_2: ",inv_preamble_fd_2
        
        
        inv_preamble_fd_1 = 1. / inv_preamble_fd_1
        inv_preamble_fd_2 = 1. / inv_preamble_fd_2
        
        dd = []
        for i in range (total_subc/2):
            dd.extend([i*2])
            
        skip_block_1 = ofdm.int_skip(total_subc,2,0)
        skip_block_2 = ofdm.int_skip(total_subc,2,1)
    #    inta_estim_1 = ofdm.interpolator(total_subc,2,dd)
    #    inta_estim_2 = ofdm.interpolator(total_subc,2,dd)
        
        LS_channel_estimator_1 = ofdm.multiply_const_vcc( list( inv_preamble_fd_1 ) )
        LS_channel_estimator_2 = ofdm.multiply_const_vcc( list( inv_preamble_fd_2 ) )
        self.connect( sampled_chest_preamble,skip_block_1, LS_channel_estimator_1)#,inta_estim_1 )
        self.connect( sampled_chest_preamble,skip_block_2, LS_channel_estimator_2)#,inta_estim_2 )
        
        estimated_CTF_1 = LS_channel_estimator_1                  # h0
        estimated_CTF_2 = LS_channel_estimator_2                  # h1              # h3
            
        
        if not options.disable_ctf_enhancer:
          
          # if options.logcir:
            # ifft1 = fft_blocks.fft_vcc(total_subc,False,[],True)
            # self.connect( estimated_CTF, ifft1,blocks.null_sink(gr.sizeof_gr_complex*total_subc))
            # summ1 = ofdm.vector_sum_vcc(total_subc)
            # c2m =gr.complex_to_mag(total_subc)
            # self.connect( estimated_CTF,summ1 ,blocks.null_sink(gr.sizeof_gr_complex))
            # self.connect( estimated_CTF, c2m,blocks.null_sink(gr.sizeof_float*total_subc))
            # log_to_file( self, ifft1, "data/CIR1.compl" )
            # log_to_file( self, summ1, "data/CTFsumm1.compl" )
            # log_to_file( self, estimated_CTF, "data/CTF1.compl" )
            # log_to_file( self, c2m, "data/CTFmag1.float" )
            
          ## MSE enhancer
          ctf_mse_enhancer_1 = ofdm.CTF_MSE_enhancer( total_subc, cp_length + cp_length)
          ctf_mse_enhancer_2 = ofdm.CTF_MSE_enhancer( total_subc, cp_length + cp_length)
          self.connect( estimated_CTF_1, ctf_mse_enhancer_1 )
          self.connect( estimated_CTF_2, ctf_mse_enhancer_2 )
          
            
          estimated_CTF_1 = ctf_mse_enhancer_1
          estimated_CTF_2 = ctf_mse_enhancer_2
          
          print "Disabled CTF MSE enhancer"
        
        ctf_postprocess_1 = ofdm.postprocess_CTF_estimate( total_subc/2 )
        self.connect( estimated_CTF_1, ( ctf_postprocess_1, 0 ) )
        ctf_postprocess_2 = ofdm.postprocess_CTF_estimate( total_subc/2 )
        self.connect( estimated_CTF_2, ( ctf_postprocess_2, 0 ) )
               
        inv_CTF_1 = ( ctf_postprocess_1, 0 )
        disp_CTF_1 = ( ctf_postprocess_1, 1 )
        inv_CTF_2 = ( ctf_postprocess_2, 0 )
        disp_CTF_2 = ( ctf_postprocess_2, 1 )  
    
        disp_CTF_RX0 = blocks.add_ff(total_subc/2)
        
        self.connect ( disp_CTF_1, (disp_CTF_RX0, 0) )
        self.connect ( disp_CTF_2, (disp_CTF_RX0, 1) )
    
    
        terminate_stream(self,disp_CTF_RX0)
        terminate_stream(self,inv_CTF_2)
        
        disp_CTF_RX0 = blocks.null_source(gr.sizeof_float*total_subc)
        disp_CTF_RX1 = blocks.null_source(gr.sizeof_float*total_subc)
        ## Channel Equalizer
        
        #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
        #log_to_file(self, ofdm_blocks2, "data/vec_mask2.compl")
        
        nondata_blocks = []
        for i in range(config.frame_length):
          if i in config.training_data.pilotsym_pos:
            nondata_blocks.append(i)
            
        pilot_subc = block_header.pilot_tones
        pilot_subcarriers = block_header.pilot_subc_sym
        print "PILOT SUBCARRIERS: ", pilot_subcarriers
        
        phase_tracking = ofdm.lms_phase_tracking_03( total_subc, pilot_subc,
                                                   nondata_blocks,pilot_subcarriers,0 )
       
        
        ##phase_tracking = ofdm.lms_phase_tracking_02( total_subc, pilot_subc,
         ##                                          nondata_blocks )
        ##phase_tracking2 = ofdm.lms_phase_tracking_02( total_subc, pilot_subc,
         ##                                           nondata_blocks )
        
    #    self.connect( ofdm_blocks,          ( phase_tracking, 0 ) )
    #    self.connect( ofdm_blocks2,          ( phase_tracking, 1 ))
    #    self.connect( inv_CTF_1,            ( phase_tracking, 2 ) )
    #    self.connect( inv_CTF_3,            ( phase_tracking, 3 ) )
    #    self.connect( frame_start,            ( phase_tracking, 4 ) )
    #    self.connect( frame_start2,            ( phase_tracking, 5) )
    #    
    #    self.connect( ofdm_blocks2,          ( phase_tracking2, 0 ) )
    #    self.connect( ofdm_blocks,          ( phase_tracking2, 1 ))
    #    self.connect( inv_CTF_3,            ( phase_tracking2, 2 ) )
    #    self.connect( inv_CTF_1,            ( phase_tracking2, 3 ) )
    #    self.connect( frame_start2,            ( phase_tracking2, 4 ) )
    #    self.connect( frame_start,            ( phase_tracking2, 5 ) )
        
        self.connect( ofdm_blocks,          ( phase_tracking, 0 ) )
        self.connect( inv_CTF_1,            ( phase_tracking, 1 ) )
        self.connect( frame_start,            ( phase_tracking, 2 ) )
        
        #self.connect(phase_tracking,blocks.null_sink(gr.sizeof_gr_complex*total_subc))
        
        ofdm_blocks = phase_tracking
       
          
        '''equalizer = ofdm.channel_equalizer_mimo_2( total_subc )
        self.connect(  ofdm_blocks,         ( equalizer, 0 ) )
        self.connect(  ofdm_blocks2,        ( equalizer, 1 ) )
        self.connect( inv_CTF_1,            ( equalizer, 2 ) )
        self.connect( inv_CTF_2,            ( equalizer, 3 ) )
        self.connect( inv_CTF_3,            ( equalizer, 4 ) )
        self.connect( inv_CTF_4,            ( equalizer, 5 ) )
        self.connect( frame_start,          ( equalizer, 6 ) )
        self.connect( frame_start2,         ( equalizer, 7 ) )
        ofdm_blocks = equalizer'''
          
    
        equalizer = ofdm.channel_equalizer_mimo_2( total_subc )    
        self.connect(  ofdm_blocks,          ( equalizer, 0 ) )
        self.connect( estimated_CTF_1,            ( equalizer, 1 ) )
        self.connect( estimated_CTF_2,            ( equalizer, 2 ) )
        self.connect( frame_start,          ( equalizer, 3 ) )
        #ofdm_blocks = equalizer
    
        #ofdm_blocks2 = equalizer2
        
    
        ofdm_blocks = equalizer
        
        #log_to_file(self, equalizer,"data/equalizer.compl")
        log_to_file(self, ofdm_blocks,"data/equalizer.compl")
        log_to_file(self, estimated_CTF_1,"data/estimated_CTF_1.compl")
        log_to_file(self, estimated_CTF_2,"data/estimated_CTF_2.compl")
        
        
        
        
        
        
        ## LMS Phase tracking
        ## Track residual frequency offset and sampling clock frequency offset
        '''
        nondata_blocks = []
        for i in range(config.frame_length):
          if i in config.training_data.pilotsym_pos:
            nondata_blocks.append(i)
            
        pilot_subc = block_header.pilot_tones
            
        phase_tracking = ofdm.lms_phase_tracking_02( total_subc, pilot_subc,
                                                   nondata_blocks )
        self.connect( equalizer, ( phase_tracking, 0 ) )
        self.connect( frame_start, ( phase_tracking, 1 ) )
        
        phase_tracking2 = ofdm.lms_phase_tracking_02( total_subc, pilot_subc,
                                                    nondata_blocks )
        self.connect( equalizer2, ( phase_tracking2, 0 ) )
        self.connect( frame_start2, ( phase_tracking2, 1 ) )
        
        # if options.scatter_plot_before_phase_tracking:
          # self.before_phase_tracking = equalizer
          
        
        if options.disable_phase_tracking or options.ideal:
          terminate_stream(self, phase_tracking)
          terminate_stream(self, phase_tracking2)
          print "Disabled phase tracking stage"
        else:
          ofdm_blocks = phase_tracking
          ofdm_blocks2 = phase_tracking2
          
        log_to_file(self,phase_tracking, "data/phase_tracking.compl")
        '''
          
        '''combine = blocks.add_cc(config.subcarriers)
        self.connect(ofdm_blocks, (combine,0))
        self.connect(ofdm_blocks2, (combine,1))
        ofdm_blocks = combine'''
    ##    div = gr.multiply_cc(config.subcarriers)
    ##    const = blocks.vector_source_c([[0.5+0]*config.subcarriers],True)
    ##    self.connect(ofdm_blocks,div)
    ##    self.connect(const,(div,1))
    ##    ofdm_blocks=div
    #    log_to_file(self,combine,"data/combine.compl")
        ## Output connections
        
        self.connect( ofdm_blocks, out_ofdm_blocks )
        self.connect( frame_start, out_frame_start )
        self.connect( disp_CTF_RX0, out_disp_ctf )
        self.connect( disp_CTF_RX1, out_disp_ctf2 )
        
    else: # (2 preambles for channel estimation)
        chest_pre_trigger_1 = blocks.delay( gr.sizeof_char, 
                                      1 )
        
        chest_pre_trigger_2 = blocks.delay( gr.sizeof_char, 
                                      2 )
        sampled_chest_preamble_1 = \
          ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )
          
        sampled_chest_preamble_2 = \
          ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 ) 
           
        self.connect( frame_start,       chest_pre_trigger_1 )
        self.connect( chest_pre_trigger_1, ( sampled_chest_preamble_1, 1 ) )
        self.connect( ofdm_blocks,       ( sampled_chest_preamble_1, 0 ) )
        
        self.connect( frame_start,       chest_pre_trigger_2 )
        self.connect( chest_pre_trigger_2, ( sampled_chest_preamble_2, 1 ) )
        self.connect( ofdm_blocks,       ( sampled_chest_preamble_2, 0 ) )
        
        
        ## Least Squares estimator for channel transfer function (CTF)
        
        # Taking inverse for estimating h11 (h12)
        inv_preamble_fd_1 = numpy.array( block_header.pilotsym_fd_1[ 
            block_header.channel_estimation_pilot[0] ] )
        print "inv_preamble_fd_1: ",inv_preamble_fd_1
        #inv_preamble_fd_1 = inv_preamble_fd_1[0::2]
        #print "inv_preamble_fd_1 ", inv_preamble_fd_1
        
        # Taking inverse for estimating h21 (h22)
        inv_preamble_fd_2 = numpy.array( block_header.pilotsym_fd_2[ 
            block_header.channel_estimation_pilot[0]+1 ] )
        print "inv_preamble_fd_2: ",inv_preamble_fd_2
        #inv_preamble_fd_2 = inv_preamble_fd_2[1::2]
        #print "inv_preamble_fd_2 ", inv_preamble_fd_2
        
        print "inv_preamble_fd_1: ",inv_preamble_fd_1
        print "inv_preamble_fd_2: ",inv_preamble_fd_2
        
        
        inv_preamble_fd_1 = 1. / inv_preamble_fd_1
        inv_preamble_fd_2 = 1. / inv_preamble_fd_2
        
        #dd = []
        #for i in range (total_subc/2):
          #  dd.extend([i*2])
            
        skip_block_1 = ofdm.int_skip(total_subc,2,0)
        skip_block_11 = ofdm.int_skip(total_subc,2,0)
        skip_block_2 = ofdm.int_skip(total_subc,2,1)
    #    inta_estim_1 = ofdm.interpolator(total_subc,2,dd)
    #    inta_estim_2 = ofdm.interpolator(total_subc,2,dd)
        
        LS_channel_estimator_1 = ofdm.multiply_const_vcc( list( inv_preamble_fd_1 ) )
        LS_channel_estimator_2 = ofdm.multiply_const_vcc( list( inv_preamble_fd_2 ) )
        self.connect( sampled_chest_preamble_1, LS_channel_estimator_1)#,inta_estim_1 )
        self.connect( sampled_chest_preamble_2, LS_channel_estimator_2)#,inta_estim_2 )
        
        estimated_CTF_1 = LS_channel_estimator_1                  # h0
        estimated_CTF_2 = LS_channel_estimator_2                  # h1              # h3
            
        
        if not options.disable_ctf_enhancer:
          
          # if options.logcir:
            # ifft1 = fft_blocks.fft_vcc(total_subc,False,[],True)
            # self.connect( estimated_CTF, ifft1,blocks.null_sink(gr.sizeof_gr_complex*total_subc))
            # summ1 = ofdm.vector_sum_vcc(total_subc)
            # c2m =gr.complex_to_mag(total_subc)
            # self.connect( estimated_CTF,summ1 ,blocks.null_sink(gr.sizeof_gr_complex))
            # self.connect( estimated_CTF, c2m,blocks.null_sink(gr.sizeof_float*total_subc))
            # log_to_file( self, ifft1, "data/CIR1.compl" )
            # log_to_file( self, summ1, "data/CTFsumm1.compl" )
            # log_to_file( self, estimated_CTF, "data/CTF1.compl" )
            # log_to_file( self, c2m, "data/CTFmag1.float" )
            
          ## MSE enhancer
          ctf_mse_enhancer_1 = ofdm.CTF_MSE_enhancer( total_subc, cp_length + cp_length)
          ctf_mse_enhancer_2 = ofdm.CTF_MSE_enhancer( total_subc, cp_length + cp_length)
          self.connect( estimated_CTF_1, ctf_mse_enhancer_1 )
          self.connect( estimated_CTF_2, ctf_mse_enhancer_2 )
          
            
          estimated_CTF_1 = ctf_mse_enhancer_1
          estimated_CTF_2 = ctf_mse_enhancer_2
          
          print "Disabled CTF MSE enhancer"
        
        ctf_postprocess_1 = ofdm.postprocess_CTF_estimate( total_subc )
        self.connect( estimated_CTF_1, ( ctf_postprocess_1, 0 ) )
        ctf_postprocess_2 = ofdm.postprocess_CTF_estimate( total_subc )
        self.connect( estimated_CTF_2, ( ctf_postprocess_2, 0 ) )
               
        inv_CTF_1 = ( ctf_postprocess_1, 0 )
        disp_CTF_1 = ( ctf_postprocess_1, 1 )
        inv_CTF_2 = ( ctf_postprocess_2, 0 )
        disp_CTF_2 = ( ctf_postprocess_2, 1 )  
    
        #disp_CTF_RX0 = blocks.add_ff(total_subc)
        
        #self.connect ( disp_CTF_1, (disp_CTF_RX0, 0) )
        #self.connect ( disp_CTF_2, (disp_CTF_RX0, 1) )
    
    
        #terminate_stream(self,disp_CTF_RX0)
        terminate_stream(self,inv_CTF_2)
        
        disp_CTF_RX0 = disp_CTF_1
        disp_CTF_RX1 = disp_CTF_2
        ## Channel Equalizer
        
        #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
        #log_to_file(self, ofdm_blocks2, "data/vec_mask2.compl")
        
        nondata_blocks = []
        for i in range(config.frame_length):
          if i in config.training_data.pilotsym_pos:
            nondata_blocks.append(i)
            
        pilot_subc = block_header.pilot_tones
        pilot_subcarriers = block_header.pilot_subc_sym
        print "PILOT SUBCARRIERS: ", pilot_subcarriers
        
        phase_tracking = ofdm.lms_phase_tracking_03( total_subc, pilot_subc,
                                                   nondata_blocks,pilot_subcarriers,0 )
       
        
        ##phase_tracking = ofdm.lms_phase_tracking_02( total_subc, pilot_subc,
         ##                                          nondata_blocks )
        ##phase_tracking2 = ofdm.lms_phase_tracking_02( total_subc, pilot_subc,
         ##                                           nondata_blocks )
        
    #    self.connect( ofdm_blocks,          ( phase_tracking, 0 ) )
    #    self.connect( ofdm_blocks2,          ( phase_tracking, 1 ))
    #    self.connect( inv_CTF_1,            ( phase_tracking, 2 ) )
    #    self.connect( inv_CTF_3,            ( phase_tracking, 3 ) )
    #    self.connect( frame_start,            ( phase_tracking, 4 ) )
    #    self.connect( frame_start2,            ( phase_tracking, 5) )
    #    
    #    self.connect( ofdm_blocks2,          ( phase_tracking2, 0 ) )
    #    self.connect( ofdm_blocks,          ( phase_tracking2, 1 ))
    #    self.connect( inv_CTF_3,            ( phase_tracking2, 2 ) )
    #    self.connect( inv_CTF_1,            ( phase_tracking2, 3 ) )
    #    self.connect( frame_start2,            ( phase_tracking2, 4 ) )
    #    self.connect( frame_start,            ( phase_tracking2, 5 ) )
        
        self.connect( ofdm_blocks,          ( phase_tracking, 0 ) )
        self.connect( inv_CTF_1,    skip_block_11,   ( phase_tracking, 1 ) )
        self.connect( frame_start,            ( phase_tracking, 2 ) )
        
        #self.connect(phase_tracking,blocks.null_sink(gr.sizeof_gr_complex*total_subc))
        
        if options.disable_phase_tracking or options.ideal:
          terminate_stream(self, phase_tracking)
          print "Disabled phase tracking stage"
        else:
          ofdm_blocks = phase_tracking
          
       
          
        '''equalizer = ofdm.channel_equalizer_mimo_2( total_subc )
        self.connect(  ofdm_blocks,         ( equalizer, 0 ) )
        self.connect(  ofdm_blocks2,        ( equalizer, 1 ) )
        self.connect( inv_CTF_1,            ( equalizer, 2 ) )
        self.connect( inv_CTF_2,            ( equalizer, 3 ) )
        self.connect( inv_CTF_3,            ( equalizer, 4 ) )
        self.connect( inv_CTF_4,            ( equalizer, 5 ) )
        self.connect( frame_start,          ( equalizer, 6 ) )
        self.connect( frame_start2,         ( equalizer, 7 ) )
        ofdm_blocks = equalizer'''
          
    
        equalizer = ofdm.channel_equalizer_mimo_2( total_subc )    
        self.connect(  ofdm_blocks,          ( equalizer, 0 ) )
        self.connect( estimated_CTF_1,     skip_block_1,       ( equalizer, 1 ) )
        self.connect( estimated_CTF_2,    skip_block_2,        ( equalizer, 2 ) )
        self.connect( frame_start,          ( equalizer, 3 ) )
        #ofdm_blocks = equalizer
    
        #ofdm_blocks2 = equalizer2
        
    
        ofdm_blocks = equalizer
        
        #log_to_file(self, equalizer,"data/equalizer.compl")
        log_to_file(self, ofdm_blocks,"data/equalizer.compl")
        log_to_file(self, estimated_CTF_1,"data/estimated_CTF_1.compl")
        log_to_file(self, estimated_CTF_2,"data/estimated_CTF_2.compl")
        
        
        
        
        
        
        ## LMS Phase tracking
        ## Track residual frequency offset and sampling clock frequency offset
        '''
        nondata_blocks = []
        for i in range(config.frame_length):
          if i in config.training_data.pilotsym_pos:
            nondata_blocks.append(i)
            
        pilot_subc = block_header.pilot_tones
            
        phase_tracking = ofdm.lms_phase_tracking_02( total_subc, pilot_subc,
                                                   nondata_blocks )
        self.connect( equalizer, ( phase_tracking, 0 ) )
        self.connect( frame_start, ( phase_tracking, 1 ) )
        
        phase_tracking2 = ofdm.lms_phase_tracking_02( total_subc, pilot_subc,
                                                    nondata_blocks )
        self.connect( equalizer2, ( phase_tracking2, 0 ) )
        self.connect( frame_start2, ( phase_tracking2, 1 ) )
        
        # if options.scatter_plot_before_phase_tracking:
          # self.before_phase_tracking = equalizer
          
        
        if options.disable_phase_tracking or options.ideal:
          terminate_stream(self, phase_tracking)
          terminate_stream(self, phase_tracking2)
          print "Disabled phase tracking stage"
        else:
          ofdm_blocks = phase_tracking
          ofdm_blocks2 = phase_tracking2
          
        log_to_file(self,phase_tracking, "data/phase_tracking.compl")
        '''
          
        '''combine = blocks.add_cc(config.subcarriers)
        self.connect(ofdm_blocks, (combine,0))
        self.connect(ofdm_blocks2, (combine,1))
        ofdm_blocks = combine'''
    ##    div = gr.multiply_cc(config.subcarriers)
    ##    const = blocks.vector_source_c([[0.5+0]*config.subcarriers],True)
    ##    self.connect(ofdm_blocks,div)
    ##    self.connect(const,(div,1))
    ##    ofdm_blocks=div
    #    log_to_file(self,combine,"data/combine.compl")
        ## Output connections
        
        self.connect( ofdm_blocks, out_ofdm_blocks )
        self.connect( frame_start, out_frame_start )
        self.connect( disp_CTF_RX0, out_disp_ctf )
        self.connect( disp_CTF_RX1, out_disp_ctf2 )
Beispiel #8
0
    def __init__(self, options, log=False):

        ## Read configuration
        config = station_configuration()

        fft_length = config.fft_length
        #cp_length     = config.cp_length
        block_header = config.training_data
        data_subc = config.data_subcarriers
        virtual_subc = config.virtual_subcarriers
        total_subc = config.subcarriers
        block_length = config.block_length
        frame_length = config.frame_length

        L = block_header.mm_periodic_parts

        cp_length = config.cp_length

        print "data_subc: ", config.data_subcarriers
        print "total_subc: ", config.subcarriers
        print "frame_lengthframe_length: ", frame_length

        ## Set Input/Output signature
        gr.hier_block2.__init__(
            self,
            "fbmc_inner_receiver",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),
            gr.io_signaturev(
                4,
                4,
                [
                    gr.sizeof_float * total_subc,  # Normalized |CTF|^2 
                    gr.sizeof_char,  # Frame start
                    gr.sizeof_gr_complex * total_subc,  # OFDM blocks, SNR est
                    gr.sizeof_float
                ]))  # CFO

        ## Input and output ports
        self.input = rx_input = self

        out_ofdm_blocks = (self, 2)
        out_frame_start = (self, 1)
        out_disp_ctf = (self, 0)
        out_disp_cfo = (self, 3)
        #out_snr_pream    = ( self, 3 )

        ## pre-FFT processing
        '''
    ## Compute autocorrelations for S&C preamble
    ## and cyclic prefix
    
    self._sc_metric = sc_metric = autocorrelator( fft_length/2, fft_length/2 )
    self._gi_metric = gi_metric = autocorrelator( fft_length, cp_length )
    
    self.connect( rx_input, sc_metric )
    self.connect( rx_input, gi_metric )
    terminate_stream(self, gi_metric)
    
    ## Sync. Output contains OFDM blocks
    sync = ofdm.time_sync( fft_length/2, 1)
    self.connect( rx_input, ( sync, 0 ) )
    self.connect( sc_metric, ( sync, 1 ) )
    self.connect( sc_metric, ( sync, 2 ) )
    
    ofdm_blocks = ( sync, 0 )
    frame_start = ( sync, 1 )
    log_to_file( self, ( sync, 1 ), "data/fbmc_peak_detector.char" )
    '''
        if options.ideal is False and options.ideal2 is False:
            #Testing old/new metric
            self.tm = schmidl.recursive_timing_metric(2 * fft_length)
            self.connect(self.input, self.tm)
            #log_to_file( self, self.tm, "data/fbmc_rec_sc_metric_ofdm.float" )

            timingmetric_shift = 0  #-2 #int(-cp_length * 0.8)
            tmfilter = filter.fft_filter_fff(
                1, [2. / fft_length] * (fft_length / 2)
            )  # ofdm.lms_fir_ff( fft_length, 1e-3 ) #; filter.fir_filter_fff(1, [1./fft_length]*fft_length)
            self.connect(self.tm, tmfilter)
            self.tm = tmfilter
            #log_to_file( self, self.tm, "data/fbmc_rec_sc_metric_ofdm2.float" )

            self._pd_thres = 0.6
            self._pd_lookahead = fft_length  # empirically chosen
            peak_detector = ofdm.peak_detector_02_fb(self._pd_lookahead,
                                                     self._pd_thres)
            self.connect(self.tm, peak_detector)
            #log_to_file( self, peak_detector, "data/fbmc_rec_peak_detector.char" )

            #frame_start = [0]*frame_length
            #frame_start[0] = 1
            #frame_start = blocks.vector_source_b(frame_start,True)

            #OLD
            #delayed_timesync = blocks.delay(gr.sizeof_char,
            #                           (frame_length-10)*fft_length/2 - fft_length/4 -1 + timingmetric_shift)
            delayed_timesync = blocks.delay(
                gr.sizeof_char,
                (frame_length - 10) * fft_length / 2 - fft_length / 4 +
                int(2.5 * fft_length) + timingmetric_shift - 1)
            #delayed_timesync = blocks.delay(gr.sizeof_char,
            #(frame_length-10)*fft_length/2 - fft_length/4 + int(3.5*fft_length)  + timingmetric_shift-1)
            self.connect(peak_detector, delayed_timesync)

            self.block_sampler = ofdm.vector_sampler(
                gr.sizeof_gr_complex, fft_length / 2 * frame_length)

            self.connect(self.input, self.block_sampler)
            self.connect(delayed_timesync, (self.block_sampler, 1))
            #log_to_file( self, self.block_sampler, "data/fbmc_block_sampler.compl" )

            vt2s = blocks.vector_to_stream(gr.sizeof_gr_complex * fft_length,
                                           frame_length / 2)
            self.connect(self.block_sampler, vt2s)
            #terminate_stream(self,ofdm_blocks)

            ofdm_blocks = vt2s
            '''
        # TODO: dynamic solution
        vt2s = blocks.vector_to_stream(gr.sizeof_gr_complex*block_length/2,
                                                frame_length)
        self.connect(self.block_sampler,vt2s)
        terminate_stream(self,( sync, 0 ))
        ofdm_blocks = vt2s
        '''

            ##stv_help = blocks.stream_to_vector(gr.sizeof_gr_complex*config.fft_length/2, 1)
            #stv_help = blocks.vector_to_stream(gr.sizeof_gr_complex*config.fft_length/2, 2)
            ##self.connect(ofdm_blocks, stv_help)
            ##ofdm_blocks = stv_help
            #ofdm_blocks = ( sync, 0 )
            #frame_start = ( sync, 1 )
            #log_to_file(self, frame_start, "data/frame_start.compl")

            #log_to_file( self, sc_metric, "data/sc_metric.float" )
            #log_to_file( self, gi_metric, "data/gi_metric.float" )
            #log_to_file( self, (sync,1), "data/sync.float" )

            #    log_to_file(self,ofdm_blocks,"data/ofdm_blocks_original.compl")
            frame_start = [0] * int(frame_length / 2)
            frame_start[0] = 1
            frame_start = blocks.vector_source_b(frame_start, True)

            #frame_start2 = [0]*int(frame_length/2)
            #frame_start2[0] = 1
            #frame_start2 = blocks.vector_source_b(frame_start2,True)

        if options.disable_time_sync or options.ideal or options.ideal2:
            if options.ideal is False and options.ideal2 is False:
                terminate_stream(self, ofdm_blocks)
                terminate_stream(self, frame_start)

            serial_to_parallel = blocks.stream_to_vector(
                gr.sizeof_gr_complex, fft_length)
            #discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
            #serial_to_parallel = blocks.stream_to_vector(gr.sizeof_gr_complex,block_length)
            #discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
            #self.connect( rx_input,serial_to_parallel)

            #self.connect( rx_input, blocks.delay(gr.sizeof_gr_complex,0),serial_to_parallel)
            initial_skip = blocks.skiphead(gr.sizeof_gr_complex,
                                           2 * fft_length)
            self.connect(rx_input, initial_skip)
            if options.ideal is False and options.ideal2 is False:
                self.connect(initial_skip, serial_to_parallel)
                ofdm_blocks = serial_to_parallel
            else:
                ofdm_blocks = initial_skip
            #self.connect( rx_input, serial_to_parallel, discard_cp )

            frame_start = [0] * int(frame_length / 2)
            frame_start[0] = 1
            frame_start = blocks.vector_source_b(frame_start, True)

            #frame_start2 = [0]*int(frame_length/2)
            #frame_start2[0] = 1
            #frame_start2 = blocks.vector_source_b(frame_start2,True)

            print "Disabled time synchronization stage"

        print "\t\t\t\t\tframe_length = ", frame_length

        if options.ideal is False and options.ideal2 is False:
            ## Extract preamble, feed to Morelli & Mengali frequency offset estimator
            assert (block_header.mm_preamble_pos == 0)
            morelli_foe = ofdm.mm_frequency_estimator(fft_length, 2, 1,
                                                      config.fbmc)
            sampler_preamble = ofdm.vector_sampler(
                gr.sizeof_gr_complex * fft_length, 1)
            self.connect(ofdm_blocks, (sampler_preamble, 0))
            self.connect(frame_start, blocks.delay(gr.sizeof_char, 1),
                         (sampler_preamble, 1))
            self.connect(sampler_preamble, morelli_foe)
            freq_offset = morelli_foe
            print "FRAME_LENGTH: ", frame_length
            #log_to_file( self, sampler_preamble, "data/sampler_preamble.compl" )
            #log_to_file( self, rx_input, "data/rx_input.compl" )
            #log_to_file( self, ofdm_blocks, "data/rx_input.compl" )

            #Extracting preamble for SNR estimation
            #fft_snr_est = fft_blocks.fft_vcc( fft_length, True, [], True )
            #self.connect( sampler_preamble, blocks.stream_to_vector(gr.sizeof_gr_complex*fft_length/2, 2),  fft_snr_est )

            ## Remove virtual subcarriers
            #if fft_length > data_subc:
            #subcarrier_mask_snr_est = ofdm.vector_mask( fft_length, virtual_subc/2,
            #                       total_subc, [] )
            #self.connect( fft_snr_est, subcarrier_mask_snr_est )
            #fft_snr_est = subcarrier_mask_snr_est
            #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
            ## Least Squares estimator for channel transfer function (CTF)

            #self.connect( fft_snr_est, out_snr_pream ) # Connecting to output

            ## Adaptive LMS FIR filtering of frequency offset
            lms_fir = ofdm.lms_fir_ff(20,
                                      1e-3)  # TODO: verify parameter choice
            self.connect(freq_offset, lms_fir)
            freq_offset = lms_fir

            self.connect(freq_offset,
                         blocks.keep_one_in_n(gr.sizeof_float,
                                              20), out_disp_cfo)
        else:
            self.connect(blocks.vector_source_f([1]), out_disp_cfo)

        #log_to_file(self, lms_fir, "data/lms_fir.float")

        if options.disable_freq_sync or options.ideal or options.ideal2:
            if options.ideal is False and options.ideal2 is False:
                terminate_stream(self, freq_offset)
                freq_offset = blocks.vector_source_f([0.0], True)
            print "Disabled frequency synchronization stage"

        if options.ideal is False and options.ideal2 is False:
            ## Correct frequency shift, feed-forward structure
            frequency_shift = ofdm.frequency_shift_vcc(fft_length,
                                                       -1.0 / fft_length, 0)

            #freq_shift = blocks.multiply_cc()
            #norm_freq = -0.1 / config.fft_length
            #freq_off = self.freq_off_src = analog.sig_source_c(1.0, analog.GR_SIN_WAVE, norm_freq, 1.0, 0.0 )

            self.connect(ofdm_blocks, (frequency_shift, 0))
            self.connect(freq_offset, (frequency_shift, 1))
            self.connect(frame_start, blocks.delay(gr.sizeof_char, 0),
                         (frequency_shift, 2))

            #self.connect(frequency_shift,s2help)
            #ofdm_blocks = s2help
            ofdm_blocks = frequency_shift
        #terminate_stream(self, frequency_shift)

        #inner_pb_filt = self._inner_pilot_block_filter = fbmc_inner_pilot_block_filter()
        #self.connect(ofdm_blocks,inner_pb_filt)
        #self.connect(frame_start,(inner_pb_filt,1))
        #self.connect((inner_pb_filt,1),blocks.null_sink(gr.sizeof_char))

        #ofdm_blocks = (inner_pb_filt,0)

        overlap_ser_to_par = ofdm.fbmc_overlapping_serial_to_parallel_cvc(
            fft_length)
        self.separate_vcvc = ofdm.fbmc_separate_vcvc(fft_length, 2)
        self.polyphase_network_vcvc_1 = ofdm.fbmc_polyphase_network_vcvc(
            fft_length, 4, 4 * fft_length - 1, True)
        self.polyphase_network_vcvc_2 = ofdm.fbmc_polyphase_network_vcvc(
            fft_length, 4, 4 * fft_length - 1, True)
        self.junction_vcvc = ofdm.fbmc_junction_vcvc(fft_length, 2)
        self.fft_fbmc = fft_blocks.fft_vcc(fft_length, True, [], True)

        print "config.training_data.fbmc_no_preambles: ", config.training_data.fbmc_no_preambles
        #center_preamble = [1, -1j, -1, 1j]

        #self.preamble = preamble = [0]*total_subc + center_preamble*((int)(total_subc/len(center_preamble)))+[0]*total_subc

        self.preamble = preamble = config.training_data.fbmc_pilotsym_fd_list
        #inv_preamble = 1. / numpy.array(self.preamble)
        #print "self.preamble: ", len(self.preamble
        #print "inv_preamble: ", list(inv_preamble)

        #print "self.preamble", self.preamble
        #print "self.preamble2", self.preamble2

        self.multiply_const = ofdm.multiply_const_vcc(
            ([1.0 / (math.sqrt(fft_length * 0.6863))] * total_subc))
        self.beta_multiplier_vcvc = ofdm.fbmc_beta_multiplier_vcvc(
            total_subc, 4, 4 * fft_length - 1, 0)
        #self.skiphead = blocks.skiphead(gr.sizeof_gr_complex*total_subc, 2*4-1-1)
        self.skiphead = blocks.skiphead(gr.sizeof_gr_complex * total_subc, 2)
        self.skiphead_1 = blocks.skiphead(gr.sizeof_gr_complex * total_subc, 0)
        #self.remove_preamble_vcvc = ofdm.fbmc_remove_preamble_vcvc(total_subc, config.frame_data_part/2, config.training_data.fbmc_no_preambles*total_subc/2)
        #self.subchannel_processing_vcvc = ofdm.fbmc_subchannel_processing_vcvc(total_subc, config.frame_data_part, 1, 2, 1, 0)
        self.oqam_postprocessing_vcvc = ofdm.fbmc_oqam_postprocessing_vcvc(
            total_subc, 0, 0)

        #log_to_file( self, ofdm_blocks, "data/PRE_FBMC.compl" )
        #log_to_file( self, self.fft_fbmc, "data/FFT_FBMC.compl" )

        if options.ideal is False and options.ideal2 is False:
            self.subchannel_processing_vcvc = ofdm.fbmc_subchannel_processing_vcvc(
                total_subc, config.frame_data_part, 3, 2, 1, 0)
            help2 = blocks.keep_one_in_n(gr.sizeof_gr_complex * total_subc,
                                         frame_length)
            self.connect((self.subchannel_processing_vcvc, 1), help2)
            #log_to_file( self, self.subchannel_processing_vcvc, "data/fbmc_subc.compl" )

        #terminate_stream(self, help2)

        if options.ideal is False and options.ideal2 is False:
            self.connect(
                ofdm_blocks,
                blocks.vector_to_stream(gr.sizeof_gr_complex, fft_length),
                overlap_ser_to_par)
        else:
            self.connect(ofdm_blocks, overlap_ser_to_par)

        self.connect(overlap_ser_to_par, self.separate_vcvc)
        self.connect((self.separate_vcvc, 1),
                     (self.polyphase_network_vcvc_2, 0))
        self.connect((self.separate_vcvc, 0),
                     (self.polyphase_network_vcvc_1, 0))
        self.connect((self.polyphase_network_vcvc_1, 0),
                     (self.junction_vcvc, 0))
        self.connect((self.polyphase_network_vcvc_2, 0),
                     (self.junction_vcvc, 1))
        self.connect(self.junction_vcvc, self.fft_fbmc)

        ofdm_blocks = self.fft_fbmc
        print "config.dc_null: ", config.dc_null
        if fft_length > data_subc:
            subcarrier_mask_fbmc = ofdm.vector_mask_dc_null(
                fft_length, virtual_subc / 2, total_subc, config.dc_null, [])
            self.connect(ofdm_blocks, subcarrier_mask_fbmc)
            ofdm_blocks = subcarrier_mask_fbmc
            #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
            ## Least Squares estimator for channel transfer function (CTF)
            #log_to_file( self, subcarrier_mask, "data/OFDM_Blocks.compl" )

        self.connect(ofdm_blocks, self.beta_multiplier_vcvc)

        ofdm_blocks = self.beta_multiplier_vcvc
        #self.connect(ofdm_blocks,self.multiply_const)
        #self.connect(self.multiply_const, (self.skiphead, 0))

        self.connect(ofdm_blocks, (self.skiphead, 0))
        #log_to_file( self, self.skiphead, "data/fbmc_skiphead_4.compl" )

        #self.connect(ofdm_blocks, self.multiply_const)
        #self.connect(self.multiply_const, self.beta_multiplier_vcvc)
        #self.connect((self.beta_multiplier_vcvc, 0), (self.skiphead, 0))
        if options.ideal or options.ideal2:
            self.connect((self.skiphead, 0), (self.skiphead_1, 0))
        else:
            self.connect((self.skiphead, 0),
                         (self.subchannel_processing_vcvc, 0))
            self.connect((self.subchannel_processing_vcvc, 0),
                         (self.skiphead_1, 0))

        #log_to_file( self, self.skiphead, "data/fbmc_subc.compl" )
        #self.connect((self.skiphead_1, 0),(self.remove_preamble_vcvc, 0))
        #self.connect((self.remove_preamble_vcvc, 0),  (self.oqam_postprocessing_vcvc, 0))

        #ofdm_blocks = self.oqam_postprocessing_vcvc
        #log_to_file( self, self.subchannel_processing_vcvc, "data/subc_0.compl" )
        #log_to_file( self, (self.subchannel_processing_vcvc,1), "data/subc_1.compl" )

        self.connect((self.skiphead_1, 0), (self.oqam_postprocessing_vcvc, 0))
        #self.connect((self.oqam_postprocessing_vcvc, 0), (self.remove_preamble_vcvc, 0) )

        ofdm_blocks = (self.oqam_postprocessing_vcvc, 0
                       )  #(self.remove_preamble_vcvc, 0)
        #log_to_file( self, (self.oqam_postprocessing_vcvc, 0), "data/fbmc_before_remove.compl" )

        #log_to_file( self, self.skiphead, "data/SKIP_HEAD_FBMC.compl" )
        #log_to_file( self, self.beta_multiplier_vcvc, "data/BETA_REC_FBMC.compl" )
        #log_to_file( self, self.oqam_postprocessing_vcvc, "data/REC_OUT_FBMC.compl" )
        """ DISABLED OFDM CHANNEL ESTIMATION PREMBLE -> CORRECT LATER to compare FBMC and OFDM channel estimation
    #TAKING THE CHANNEL ESTIMATION PREAMBLE
    chest_pre_trigger = blocks.delay( gr.sizeof_char, 3 )
    sampled_chest_preamble = ofdm.vector_sampler( gr.sizeof_gr_complex * fft_length/2, 2 )
      
    self.connect( frame_start,       chest_pre_trigger )
    self.connect( chest_pre_trigger, ( sampled_chest_preamble, 1 ) )
    self.connect( frequency_shift,       ( sampled_chest_preamble, 0 ) )
    #ofdm_blocks = sampled_chest_preamble
    
        
    ## FFT
    fft = fft_blocks.fft_vcc( fft_length, True, [], True )
    self.connect( sampled_chest_preamble, fft )
    ofdm_blocks_est = fft
    log_to_file( self, sampled_chest_preamble, "data/SAMPLED_EST_PREAMBLE.compl" )
    log_to_file( self, ofdm_blocks_est, "data/FFT.compl" )
    
    
    ## Remove virtual subcarriers
    if fft_length > data_subc:
      subcarrier_mask = ofdm.vector_mask( fft_length, virtual_subc/2,
                                           total_subc, [] )
      self.connect( ofdm_blocks_est, subcarrier_mask )
      ofdm_blocks_est = subcarrier_mask
      #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
       ## Least Squares estimator for channel transfer function (CTF)
      log_to_file( self, subcarrier_mask, "data/OFDM_Blocks.compl" )
    
          
    ## post-FFT processing
      
    
    
    ## extract channel estimation preamble from frame
    ##chest_pre_trigger = blocks.delay( gr.sizeof_char, 
                                  ##1 )
    ##sampled_chest_preamble = \
     ## ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )
    ##self.connect( frame_start,       chest_pre_trigger )
    ##self.connect( chest_pre_trigger, ( sampled_chest_preamble, 1 ) )
    ##self.connect( ofdm_blocks,       ( sampled_chest_preamble, 0 ) )
    

    
    ## Least Squares estimator for channel transfer function (CTF)
    inv_preamble_fd = numpy.array( block_header.pilotsym_fd[ 
        block_header.channel_estimation_pilot[0] ] )
    #print "Channel estimation pilot: ", inv_preamble_fd
    inv_preamble_fd = 1. / inv_preamble_fd
    
    LS_channel_estimator = ofdm.multiply_const_vcc( list( inv_preamble_fd ) )
    self.connect( ofdm_blocks_est, LS_channel_estimator )
    estimated_CTF = LS_channel_estimator
    terminate_stream(self,estimated_CTF)
    """
        if options.ideal is False and options.ideal2 is False:
            if options.logcir:
                log_to_file(self, sampled_chest_preamble, "data/PREAM.compl")

            if not options.disable_ctf_enhancer:

                if options.logcir:
                    ifft1 = fft_blocks.fft_vcc(total_subc, False, [], True)
                    self.connect(
                        estimated_CTF, ifft1,
                        gr.null_sink(gr.sizeof_gr_complex * total_subc))
                    summ1 = ofdm.vector_sum_vcc(total_subc)
                    c2m = gr.complex_to_mag(total_subc)
                    self.connect(estimated_CTF, summ1,
                                 gr.null_sink(gr.sizeof_gr_complex))
                    self.connect(estimated_CTF, c2m,
                                 gr.null_sink(gr.sizeof_float * total_subc))
                    log_to_file(self, ifft1, "data/CIR1.compl")
                    log_to_file(self, summ1, "data/CTFsumm1.compl")
                    log_to_file(self, estimated_CTF, "data/CTF1.compl")
                    log_to_file(self, c2m, "data/CTFmag1.float")

                ## MSE enhancer
                ctf_mse_enhancer = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                self.connect(estimated_CTF, ctf_mse_enhancer)
                #      log_to_file( self, ctf_mse_enhancer, "data/ctf_mse_enhancer_original.compl")
                #ifft3 = fft_blocks.fft_vcc(total_subc,False,[],True)
                #null_noise = ofdm.noise_nulling(total_subc, cp_length + cp_length)
                #ctf_mse_enhancer = fft_blocks.fft_vcc(total_subc,True,[],True)
                #ctf_mse_enhancer = ofdm.vector_mask( fft_length, virtual_subc/2,
                # total_subc, [] )
                #self.connect( estimated_CTF, ifft3,null_noise,ctf_mse_enhancer )

                estimated_CTF = ctf_mse_enhancer
                print "Disabled CTF MSE enhancer"

            if options.logcir:
                ifft2 = fft_blocks.fft_vcc(total_subc, False, [], True)
                self.connect(estimated_CTF, ifft2,
                             gr.null_sink(gr.sizeof_gr_complex * total_subc))
                summ2 = ofdm.vector_sum_vcc(total_subc)
                c2m2 = gr.complex_to_mag(total_subc)
                self.connect(estimated_CTF, summ2,
                             gr.null_sink(gr.sizeof_gr_complex))
                self.connect(estimated_CTF, c2m2,
                             gr.null_sink(gr.sizeof_float * total_subc))
                log_to_file(self, ifft2, "data/CIR2.compl")
                log_to_file(self, summ2, "data/CTFsumm2.compl")
                log_to_file(self, estimated_CTF, "data/CTF2.compl")
                log_to_file(self, c2m2, "data/CTFmag2.float")

            ## Postprocess the CTF estimate
            ## CTF -> inverse CTF (for equalizer)
            ## CTF -> norm |.|^2 (for CTF display)
            ctf_postprocess = ofdm.fbmc_postprocess_CTF_estimate(total_subc)

            self.connect(help2, ctf_postprocess)
            #estimated_SNR = ( ctf_postprocess, 0 )
            disp_CTF = (ctf_postprocess, 0)
            #self.connect(estimated_SNR,out_snr_pream)
            #log_to_file( self, estimated_SNR, "data/fbmc_SNR.float" )

            #Disable measured SNR output
            #terminate_stream(self, estimated_SNR)
            #self.connect(blocks.vector_source_f([10.0],True) ,out_snr_pream)


#     if options.disable_equalization or options.ideal:
#       terminate_stream(self, inv_estimated_CTF)
#       inv_estimated_CTF_vec = blocks.vector_source_c([1.0/fft_length*math.sqrt(total_subc)]*total_subc,True,total_subc)
#       inv_estimated_CTF_str = blocks.vector_to_stream(gr.sizeof_gr_complex, total_subc)
#       self.inv_estimated_CTF_mul = ofdm.multiply_const_ccf( 1.0/config.rms_amplitude )
#       #inv_estimated_CTF_mul.set_k(1.0/config.rms_amplitude)
#       inv_estimated_CTF = blocks.stream_to_vector(gr.sizeof_gr_complex, total_subc)
#       self.connect( inv_estimated_CTF_vec, inv_estimated_CTF_str, self.inv_estimated_CTF_mul, inv_estimated_CTF)
#       print "Disabled equalization stage"
        '''
    ## LMS Phase tracking
    ## Track residual frequency offset and sampling clock frequency offset

    nondata_blocks = []
    for i in range(config.frame_length):
      if i in config.training_data.pilotsym_pos:
        nondata_blocks.append(i)
        
    print"\t\t\t\t\tnondata_blocks=",nondata_blocks
    pilot_subc = block_header.pilot_tones
    pilot_subcarriers = block_header.pilot_subc_sym
    print "PILOT SUBCARRIERS: ", pilot_subcarriers
        
    phase_tracking = ofdm.lms_phase_tracking_03( total_subc, pilot_subc,
                                               nondata_blocks, pilot_subcarriers,0 )
    self.connect( ofdm_blocks, ( phase_tracking, 0 ) )
    self.connect( inv_estimated_CTF, ( phase_tracking, 1 ) )
    self.connect( frame_start, ( phase_tracking, 2 ) ) ##
    
    if options.scatter_plot_before_phase_tracking:
      self.before_phase_tracking = equalizer
      
    
    if options.disable_phase_tracking or options.ideal:
      terminate_stream(self, phase_tracking)
      print "Disabled phase tracking stage"
    else:
      ofdm_blocks = phase_tracking
    '''
        ## Channel Equalizer
        ##equalizer = ofdm.channel_equalizer( total_subc )
        ##self.connect( ofdm_blocks,       ( equalizer, 0 ) )
        ##self.connect( inv_estimated_CTF, ( equalizer, 1 ) )
        ##self.connect( frame_start,       ( equalizer, 2 ) )
        ##ofdm_blocks = equalizer
        #log_to_file(self, equalizer,"data/equalizer_siso.compl")

        #log_to_file(self, ofdm_blocks, "data/equalizer.compl")

        ## LMS Phase tracking
        ## Track residual frequency offset and sampling clock frequency offset

        nondata_blocks = []
        for i in range(config.frame_length):
            if i in config.training_data.pilotsym_pos:
                nondata_blocks.append(i)

        print "\t\t\t\t\tnondata_blocks=", nondata_blocks
        pilot_subc = block_header.pilot_tones
        pilot_subcarriers = block_header.pilot_subc_sym
        print "PILOT SUBCARRIERS: ", pilot_subcarriers

        if options.scatter_plot_before_phase_tracking:
            self.before_phase_tracking = equalizer

        ## Output connections

        self.connect(ofdm_blocks, out_ofdm_blocks)
        self.connect(frame_start, out_frame_start)
        if options.ideal is False and options.ideal2 is False:
            self.connect(disp_CTF, out_disp_ctf)
        else:
            self.connect(blocks.vector_source_f([1.0] * total_subc),
                         blocks.stream_to_vector(gr.sizeof_float, total_subc),
                         out_disp_ctf)

        if log:
            log_to_file(self, sc_metric, "data/sc_metric.float")
            log_to_file(self, gi_metric, "data/gi_metric.float")
            log_to_file(self, morelli_foe, "data/morelli_foe.float")
            log_to_file(self, lms_fir, "data/lms_fir.float")
            log_to_file(self, sampler_preamble, "data/preamble.compl")
            log_to_file(self, sync, "data/sync.compl")
            log_to_file(self, frequency_shift, "data/frequency_shift.compl")
            log_to_file(self, fft, "data/fft.compl")
            log_to_file(self, fft, "data/fft.float", mag=True)

            if vars().has_key('subcarrier_mask'):
                log_to_file(self, subcarrier_mask,
                            "data/subcarrier_mask.compl")

            log_to_file(self, ofdm_blocks, "data/ofdm_blocks_out.compl")
            log_to_file(self,
                        frame_start,
                        "data/frame_start.float",
                        char_to_float=True)

            log_to_file(self, sampled_chest_preamble,
                        "data/sampled_chest_preamble.compl")
            log_to_file(self, LS_channel_estimator,
                        "data/ls_channel_estimator.compl")
            log_to_file(self,
                        LS_channel_estimator,
                        "data/ls_channel_estimator.float",
                        mag=True)

            if "ctf_mse_enhancer" in locals():
                log_to_file(self, ctf_mse_enhancer,
                            "data/ctf_mse_enhancer.compl")
                log_to_file(self,
                            ctf_mse_enhancer,
                            "data/ctf_mse_enhancer.float",
                            mag=True)

            log_to_file(self, (ctf_postprocess, 0),
                        "data/inc_estimated_ctf.compl")
            log_to_file(self, (ctf_postprocess, 1), "data/disp_ctf.float")

            log_to_file(self, equalizer, "data/equalizer.compl")
            log_to_file(self, equalizer, "data/equalizer.float", mag=True)

            log_to_file(self, phase_tracking, "data/phase_tracking.compl")
Beispiel #9
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()
Beispiel #10
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()
Beispiel #11
0
  def __init__ (self, options):
    gr.top_block.__init__(self, "ofdm_tx")

    self._tx_freq            = options.tx_freq         # tranmitter's center frequency
    self._tx_subdev_spec     = options.tx_subdev_spec  # daughterboard to use
    self._fusb_block_size    = options.fusb_block_size # usb info for USRP
    self._fusb_nblocks       = options.fusb_nblocks    # usb info for USRP
    self._which              = options.which_usrp
    self._bandwidth          = options.bandwidth
    self.servants = []
    
    
    self._interface          = options.interface
    self._mac_addr           = options.mac_addr

    self._options = copy.copy( options )


    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 = 0.5/self._interpolation
    tb = bw/5
    if self._interpolation > 1:
      self.filter = gr.hier_block2("filter",
                                   gr.io_signature(1,1,gr.sizeof_gr_complex),
                                   gr.io_signature(1,1,gr.sizeof_gr_complex))
      self.filter.connect( self.filter, gr.interp_fir_filter_ccf(2,f1),
                           gr.interp_fir_filter_ccf(2,f1), self.filter )
      
      print "New"
#      
#      
#      self.filt_coeff = optfir.low_pass(1.0, 1.0, bw, bw+tb, 0.2, 60.0, 0)
#      self.filter = gr.interp_fir_filter_ccf(self._interpolation,self.filt_coeff)
#      print "Software interpolation filter length: %d" % (len(self.filt_coeff))
    else:
      self.filter = None
      
      
    if not options.from_file is None:
      # sent captured file to usrp
      self.src = gr.file_source(gr.sizeof_gr_complex,options.from_file)
      self._setup_usrp_sink()
      if hasattr(self, "filter"):
        self.connect(self.src,self.filter,self.u) #,self.filter
      else:
        self.connect(self.src,self.u)
      
      return 
    
    
    
    self._setup_tx_path(options)
    
    config = station_configuration()
    
    self.enable_info_tx("info_tx", "pa_user")
#    if not options.no_cheat:
#      self.txpath.enable_channel_cheating("channelcheat")
    self.txpath.enable_txpower_adjust("txpower")
    self.txpath.publish_txpower("txpower_info")
    #self.enable_txfreq_adjust("txfreq")
    
    
    
    if options.nullsink:
      self.dst = gr.null_sink( gr.sizeof_gr_complex )
    
    else:  
      if not options.to_file is None:
        # capture transmitter's stream to disk
        self.dst  = gr.file_sink(gr.sizeof_gr_complex,options.to_file)
        tmp = gr.throttle(gr.sizeof_gr_complex,1e5)
        self.connect( tmp, self.dst )
        self.dst = tmp
        
        if options.force_filter:
          print "Forcing filter usage"
          self.connect( self.filter, self.dst )
          self.dst = self.filter
        
      else:
        # connect transmitter to usrp
        self._setup_usrp_sink()
        if options.dyn_freq:
            self.enable_txfreq_adjust("txfreq")
            
        if self.filter is not None:
          self.connect( self.filter,self.dst )
          self.dst = self.filter
          
        if options.record:
          log_to_file( self, self.txpath, "data/txpath_out.compl" )
        
        #self.publish_spectrum( 256 )
        
      
        
        
        
    if options.measure:
      self.m = throughput_measure(gr.sizeof_gr_complex)
      self.connect( self.m, self.dst )
      self.dst = self.m
        
    if options.samplingoffset is not None:
      soff = options.samplingoffset
      interp = gr.fractional_interpolator_cc(0.0,soff)
      self.connect( interp, self.dst )
      self.dst = interp

    if options.snr is not None:
      
#      if options.berm is not None:
#          noise_sigma = 380 #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 = gr.add_cc()
      awgn_noise_src = ofdm.complex_white_noise( 0.0, noise_sigma )
      self.connect( awgn_noise_src, (awgn_chan,1) )
      self.connect( awgn_chan, self.dst )
      self.dst = awgn_chan
      
      if options.berm is False:
          fad_chan = itpp.tdl_channel(  ) #[0, -7, -20], [0, 2, 6]
          #fad_chan.set_norm_doppler( 1e-9 )
          #fad_chan.set_LOS( [500.,0,0] )
          fad_chan.set_channel_profile( itpp.ITU_Pedestrian_A, 5e-8 )
          fad_chan.set_norm_doppler( 1e-8 )
    #        fad_chan = gr.fir_filter_ccc(1,[1.0,0.0,2e-1+0.1j,1e-4-0.04j])
          self.connect( fad_chan, self.dst )
          self.dst = fad_chan


    if options.freqoff is not None:
      freq_shift = gr.multiply_cc()
      norm_freq = options.freqoff / config.fft_length
      freq_off_src = gr.sig_source_c(1.0, gr.GR_SIN_WAVE, norm_freq, 1.0, 0.0 )
      self.connect( freq_off_src, ( freq_shift, 1 ) )
      dst = self.dst
      self.connect( freq_shift, dst )
      self.dst = freq_shift
      



    
    self.connect( self.txpath, self.dst )
    
    

    if options.cheat:
      self.txpath.enable_channel_cheating("channelcheat")

    
      
    print "Hit Strg^C to terminate"
Beispiel #12
0
    def __init__(self, options):
        gr.top_block.__init__(self, "ofdm_mrrc_benchmark")

        ##self._tx_freq            = options.tx_freq         # tranmitter's center frequency
        ##self._tx_subdev_spec     = options.tx_subdev_spec  # daughterboard to use
        ##self._fusb_block_size    = options.fusb_block_size # usb info for USRP
        ##self._fusb_nblocks       = options.fusb_nblocks    # usb info for USRP
        ##self._which              = options.which_usrp
        self._bandwidth = options.bandwidth
        self.servants = []
        self._verbose = options.verbose

        ##self._interface          = options.interface
        ##self._mac_addr           = options.mac_addr

        self._options = copy.copy(options)

        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_filter2 = 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)
            self.tx_filter2.connect(self.tx_filter2,
                                    gr.interp_fir_filter_ccf(2, f1),
                                    gr.interp_fir_filter_ccf(2, f1),
                                    self.tx_filter2)
            print "New"

        else:
            self.tx_filter = None
            self.tx_filter2 = 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)
            self.rx_filter2 = gr.fir_filter_ccf(self.decimation, filt_coeff)
        else:
            self.rx_filter = None
            self.rx_filter2 = None

##    if not options.from_file is None:
##      # sent captured file to usrp
##      self.src = gr.file_source(gr.sizeof_gr_complex,options.from_file)
##      self._setup_usrp_sink()
##      if hasattr(self, "filter"):
##        self.connect(self.src,self.filter,self.u) #,self.filter
##      else:
##        self.connect(self.src,self.u)
##
##      return

        self._setup_tx_path(options)
        self._setup_rx_path(options)
        self._setup_rpc_manager()

        config = self.config = station_configuration()

        #self.enable_txfreq_adjust("txfreq")

        if options.imgxfer:
            self.rxpath.setup_imgtransfer_sink()

        if not options.no_decoding:
            self.rxpath.publish_rx_performance_measure()

        self.dst = (self.rxpath, 0)
        self.dst2 = (self.rxpath, 1)

        if options.force_rx_filter:
            print "Forcing rx filter usage"
            self.connect(self.rx_filter, self.dst)
            self.connect(self.rx_filter2, self.dst2)
            self.dst = self.rx_filter
            self.dst2 = self.rx_filter2

        if options.measure:
            self.m = throughput_measure(gr.sizeof_gr_complex)
            self.m2 = throughput_measure(gr.sizeof_gr_complex)
            self.connect(self.m, self.dst)
            self.connect(self.m2, self.dst2)
            self.dst = self.m
            self.dst2 = self.m2

        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
                print " Noise St. Dev. %f" % (noise_sigma
                                              )  #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_chan2 = blocks.add_cc()
            awgn_noise_src = analog.fastnoise_source_c(analog.GR_GAUSSIAN,
                                                       noise_sigma, 0, 8192)
            awgn_noise_src2 = analog.fastnoise_source_c(
                analog.GR_GAUSSIAN, noise_sigma * 2, 0, 2192)
            self.connect(awgn_chan, self.dst)
            self.connect(awgn_chan2, self.dst2)
            self.connect(awgn_noise_src, (awgn_chan, 1))
            self.connect(awgn_noise_src2, (awgn_chan2, 1))
            self.dst = awgn_chan
            self.dst2 = awgn_chan2

        if options.freqoff is not None:
            freq_off = self.freq_off = channel.freq_offset(options.freqoff)
            freq_off2 = self.freq_off2 = channel.freq_offset(options.freqoff)
            dst = self.dst
            dst2 = self.dst2
            self.connect(freq_off, dst)
            self.connect(freq_off2, dst2)
            self.dst = freq_off
            self.dst2 = freq_off2
            self.rpc_mgr_tx.add_interface("set_freq_offset",
                                          self.freq_off.set_freqoff)
            self.rpc_mgr_tx.add_interface("set_freq_offset2",
                                          self.freq_off2.set_freqoff)

        if options.multipath:
            if options.itu_channel:
                self.fad_chan = channel.itpp_channel(options.bandwidth)
                #fad_chan.set_norm_doppler( 1e-9 )
                #fad_chan.set_LOS( [500.,0,0] )
                self.fad_chan2 = channel.itpp_channel(options.bandwidth)
                self.fad_chan.set_channel_profile(itpp.ITU_Pedestrian_A, 5e-8)
                self.fad_chan.set_norm_doppler(1e-8)
                self.fad_chan2.set_channel_profile(itpp.ITU_Pedestrian_A, 5e-8)
                self.fad_chan2.set_norm_doppler(1e-8)
                self.rpc_mgr_tx.add_interface(
                    "set_channel_profile", self.fad_chan.set_channel_profile)
                self.rpc_mgr_tx.add_interface(
                    "set_channel_profile", self.fad_chan2.set_channel_profile)
            else:
                fad_chan = filter.fir_filter_ccc(
                    1, [1.0, 0.0, 2e-1 + 0.1j, 1e-4 - 0.04j])
                fad_chan2 = filter.fir_filter_ccc(
                    1, [1.0, 0.0, 2e-1 + 0.1j, 1e-4 - 0.04j])

            self.connect(self.fad_chan, self.dst)
            self.connect(self.fad_chan2, self.dst2)
            self.dst = self.fad_chan
            self.dst2 = self.fad_chan2

        if options.samplingoffset is not None:
            soff = options.samplingoffset
            interp = moms(1000000 * (1.0 + soff), 1000000)
            interp2 = moms(1000000 * (1.0 + soff), 1000000)
            self.connect(interp, self.dst)
            self.connect(interp2, self.dst2)
            self.dst = interp
            self.dst2 = interp2

            if options.record:
                log_to_file(self, interp, "data/interp_out.compl")
                log_to_file(self, interp2, "data/interp2_out.compl")

        tmm = blocks.throttle(gr.sizeof_gr_complex, 1e6)
        #tmm2 =blocks.throttle(gr.sizeof_gr_complex, 1e6)

        #self.connect( tmm, self.dst )
        #self.connect( tmm2, self.dst2 )
        #self.dst = tmm
        #self.dst2 = tmm2

        #inter = blocks.interleave(gr.sizeof_gr_complex)
        #deinter = blocks.deinterleave(gr.sizeof_gr_complex)

        # Interleaving input/output streams
        ##self.connect(inter, deinter)
        #self.connect((deinter,0),self.dst)
        #self.connect((deinter,1),self.dst2)
        #self.dst = inter
        #self.dst2 = (inter,1)

        if options.force_tx_filter:
            print "Forcing tx filter usage"
            self.connect(self.tx_filter, self.dst)
            self.connect(self.tx_filter2, self.dst2)
            self.dst = self.tx_filter
            self.dst2 = self.tx_filter2
        if options.record:
            log_to_file(self, self.txpath, "data/txpath_out.compl")
            log_to_file(self, self.txpath2, "data/txpath2_out.compl")

        if options.nullsink:
            self.connect(gr.null_source(gr.sizeof_gr_complex), self.dst)
            self.connect(gr.null_source(gr.sizeof_gr_complex), self.dst2)
            self.dst = gr.null_sink(gr.sizeof_gr_complex)
            self.dst2 = gr.null_sink(gr.sizeof_gr_complex)

        self.connect(self.txpath, tmm, self.dst)
        self.connect(tmm, self.dst2)
        #self.connect( self.txpath,self.dst2 )

        print "Hit Strg^C to terminate"

        if self._verbose:
            self._print_verbage()
Beispiel #13
0
    def __init__(self, options, log=False):

        ## Read configuration
        config = station_configuration()

        fft_length = config.fft_length
        cp_length = config.cp_length
        block_header = config.training_data
        data_subc = config.data_subcarriers
        virtual_subc = config.virtual_subcarriers
        total_subc = config.subcarriers
        block_length = config.block_length
        frame_length = config.frame_length
        dc_null = config.dc_null

        L = block_header.mm_periodic_parts

        ## Set Input/Output signature
        gr.hier_block2.__init__(
            self,
            "ofdm_inner_receiver",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),
            gr.io_signaturev(
                4,
                4,
                [
                    gr.sizeof_gr_complex * total_subc,  # OFDM blocks
                    gr.sizeof_char,  # Frame start
                    gr.sizeof_float * total_subc,
                    gr.sizeof_float
                ]))  # Normalized |CTF|^2

        ## Input and output ports
        self.input = rx_input = self

        out_ofdm_blocks = (self, 0)
        out_frame_start = (self, 1)
        out_disp_ctf = (self, 2)
        out_disp_cfo = (self, 3)

        ## pre-FFT processing
        if options.ideal is False and options.ideal2 is False:
            if options.old_receiver is False:
                ## Compute autocorrelations for S&C preamble
                ## and cyclic prefix

                self._sc_metric = sc_metric = autocorrelator(
                    fft_length / 2, fft_length / 2)
                self._gi_metric = gi_metric = autocorrelator(
                    fft_length, cp_length)

                self.connect(rx_input, sc_metric)
                self.connect(rx_input, gi_metric)

                ## Sync. Output contains OFDM blocks
                sync = ofdm.time_sync(fft_length, cp_length)
                self.connect(rx_input, (sync, 0))
                self.connect(sc_metric, (sync, 1))
                self.connect(gi_metric, (sync, 2))
                ofdm_blocks = (sync, 0)
                frame_start = (sync, 1)
                #log_to_file( self, ( sync, 1 ), "data/peak_detector.char" )
            else:

                #Testing old/new metric
                self.tm = schmidl.recursive_timing_metric(fft_length)
                self.connect(self.input, self.tm)
                #log_to_file( self, self.tm, "data/rec_sc_metric_ofdm.float" )

                timingmetric_shift = -2  #int(-cp_length/4)# 0#-2 #int(-cp_length * 0.8)
                tmfilter = filter.fft_filter_fff(1,
                                                 [1. / cp_length] * cp_length)
                self.connect(self.tm, tmfilter)
                self.tm = tmfilter

                self._pd_thres = 0.3
                self._pd_lookahead = fft_length / 2  # empirically chosen
                peak_detector = ofdm.peak_detector_02_fb(
                    self._pd_lookahead, self._pd_thres)
                self.connect(self.tm, peak_detector)
                #log_to_file( self, peak_detector, "data/rec_peak_detector.char" )

                frame_start = [0] * frame_length
                frame_start[0] = 1
                frame_start = self.frame_trigger_old = blocks.vector_source_b(
                    frame_start, True)

                delayed_timesync = blocks.delay(
                    gr.sizeof_char,
                    (frame_length - 1) * block_length + timingmetric_shift)
                self.connect(peak_detector, delayed_timesync)

                self.block_sampler = ofdm.vector_sampler(
                    gr.sizeof_gr_complex, block_length * frame_length)
                self.discard_cp = ofdm.vector_mask(block_length, cp_length,
                                                   fft_length, [])

                self.connect(self.input, self.block_sampler)
                self.connect(delayed_timesync, (self.block_sampler, 1))

                # TODO: dynamic solution
                vt2s = blocks.vector_to_stream(
                    gr.sizeof_gr_complex * block_length, frame_length)
                self.connect(self.block_sampler, vt2s, self.discard_cp)
                #terminate_stream(self,ofdm_blocks)
                ofdm_blocks = self.discard_cp
#     else:
#       serial_to_parallel = blocks.stream_to_vector(gr.sizeof_gr_complex,block_length)
#       discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
#       ofdm_blocks = discard_cp
#       self.connect( rx_input, serial_to_parallel, discard_cp )
#       frame_start = [0]*frame_length
#       frame_start[0] = 1
#       frame_start = blocks.vector_source_b(frame_start,True)
#
#       print "Disabled time synchronization stage"

## Compute autocorrelations for S&C preamble
## and cyclic prefix

#log_to_file( self, sc_metric, "data/sc_metric_ofdm.float" )
#log_to_file(self, frame_start, "data/frame_start.compl")

#    log_to_file(self,ofdm_blocks,"data/ofdm_blocks_original.compl")

        if options.disable_time_sync or options.ideal or options.ideal2:
            if options.ideal is False and options.ideal2 is False:
                terminate_stream(self, ofdm_blocks)
                terminate_stream(self, frame_start)

            serial_to_parallel = blocks.stream_to_vector(
                gr.sizeof_gr_complex, block_length)
            discard_cp = ofdm.vector_mask_dc_null(block_length, cp_length,
                                                  fft_length, dc_null, [])
            ofdm_blocks = discard_cp
            self.connect(rx_input, serial_to_parallel, discard_cp)

            frame_start = [0] * frame_length
            frame_start[0] = 1
            frame_start = blocks.vector_source_b(frame_start, True)

            print "Disabled time synchronization stage"

        print "\t\t\t\t\tframe_length = ", frame_length

        if options.ideal is False and options.ideal2 is False:
            ## Extract preamble, feed to Morelli & Mengali frequency offset estimator
            assert (block_header.mm_preamble_pos == 0)
            morelli_foe = ofdm.mm_frequency_estimator(fft_length, L, 1, 0)
            sampler_preamble = ofdm.vector_sampler(
                gr.sizeof_gr_complex * fft_length, 1)
            self.connect(ofdm_blocks, (sampler_preamble, 0))
            self.connect(frame_start, (sampler_preamble, 1))
            self.connect(sampler_preamble, morelli_foe)
            freq_offset = morelli_foe

            ## Adaptive LMS FIR filtering of frequency offset
            lms_fir = ofdm.lms_fir_ff(20,
                                      1e-3)  # TODO: verify parameter choice
            self.connect(freq_offset, lms_fir)
            freq_offset = lms_fir

            #self.zmq_probe_freqoff = zeromq.pub_sink(gr.sizeof_float, 1, "tcp://*:5557")
            self.connect(lms_fir, blocks.keep_one_in_n(gr.sizeof_float, 20),
                         out_disp_cfo)
        else:
            self.connect(blocks.vector_source_f([1]), out_disp_cfo)

            #log_to_file(self, lms_fir, "data/lms_fir.float")

        if options.disable_freq_sync or options.ideal or options.ideal2:
            if options.ideal is False and options.ideal2 is False:
                terminate_stream(self, freq_offset)
                freq_offset = blocks.vector_source_f([0.0], True)
            print "Disabled frequency synchronization stage"

        if options.ideal is False and options.ideal2 is False:
            ## Correct frequency shift, feed-forward structure
            frequency_shift = ofdm.frequency_shift_vcc(fft_length,
                                                       -1.0 / fft_length,
                                                       cp_length)
            self.connect(ofdm_blocks, (frequency_shift, 0))
            self.connect(freq_offset, (frequency_shift, 1))
            self.connect(frame_start, (frequency_shift, 2))
            ofdm_blocks = frequency_shift

        ## FFT
        fft = fft_blocks.fft_vcc(fft_length, True, [], True)
        self.connect(ofdm_blocks, fft)
        ofdm_blocks = fft
        #log_to_file( self, fft, "data/compen.float" )

        ## Remove virtual subcarriers
        if fft_length > data_subc:
            subcarrier_mask = ofdm.vector_mask_dc_null(fft_length,
                                                       virtual_subc / 2,
                                                       total_subc, dc_null, [])
            self.connect(ofdm_blocks, subcarrier_mask)
            ofdm_blocks = subcarrier_mask
            #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
            ## Least Squares estimator for channel transfer function (CTF)

            if options.logcir:
                log_to_file(self, ofdm_blocks, "data/OFDM_Blocks.compl")

                inv_preamble_fd = numpy.array(block_header.pilotsym_fd[
                    block_header.channel_estimation_pilot[0]])
                inv_preamble_fd = numpy.concatenate([
                    inv_preamble_fd[:total_subc / 2],
                    inv_preamble_fd[total_subc / 2 + dc_null:]
                ])
                #print "Channel estimation pilot: ", inv_preamble_fd
                inv_preamble_fd = 1. / inv_preamble_fd
                LS_channel_estimator0 = ofdm.multiply_const_vcc(
                    list(inv_preamble_fd))
                self.connect(ofdm_blocks, LS_channel_estimator0,
                             gr.null_sink(gr.sizeof_gr_complex * total_subc))
                log_to_file(self, LS_channel_estimator0,
                            "data/OFDM_Blocks_eq.compl")

        ## post-FFT processing

        ## extract channel estimation preamble from frame
        if options.ideal is False and options.ideal2 is False:
            chest_pre_trigger = blocks.delay(gr.sizeof_char, 1)
            sampled_chest_preamble = ofdm.vector_sampler(
                gr.sizeof_gr_complex * total_subc, 1)
            self.connect(frame_start, chest_pre_trigger)
            self.connect(chest_pre_trigger, (sampled_chest_preamble, 1))
            self.connect(ofdm_blocks, (sampled_chest_preamble, 0))

            ## Least Squares estimator for channel transfer function (CTF)
            inv_preamble_fd = numpy.array(block_header.pilotsym_fd[
                block_header.channel_estimation_pilot[0]])
            inv_preamble_fd = numpy.concatenate([
                inv_preamble_fd[:total_subc / 2],
                inv_preamble_fd[total_subc / 2 + dc_null:]
            ])
            #print "Channel estimation pilot: ", inv_preamble_fd
            inv_preamble_fd = 1. / inv_preamble_fd

            LS_channel_estimator = ofdm.multiply_const_vcc(
                list(inv_preamble_fd))
            self.connect(sampled_chest_preamble, LS_channel_estimator)
            estimated_CTF = LS_channel_estimator

            if options.logcir:
                log_to_file(self, sampled_chest_preamble, "data/PREAM.compl")

            if not options.disable_ctf_enhancer:

                if options.logcir:
                    ifft1 = fft_blocks.fft_vcc(total_subc, False, [], True)
                    self.connect(
                        estimated_CTF, ifft1,
                        gr.null_sink(gr.sizeof_gr_complex * total_subc))
                    summ1 = ofdm.vector_sum_vcc(total_subc)
                    c2m = gr.complex_to_mag(total_subc)
                    self.connect(estimated_CTF, summ1,
                                 gr.null_sink(gr.sizeof_gr_complex))
                    self.connect(estimated_CTF, c2m,
                                 gr.null_sink(gr.sizeof_float * total_subc))
                    log_to_file(self, ifft1, "data/CIR1.compl")
                    log_to_file(self, summ1, "data/CTFsumm1.compl")
                    log_to_file(self, estimated_CTF, "data/CTF1.compl")
                    log_to_file(self, c2m, "data/CTFmag1.float")

                ## MSE enhancer
                ctf_mse_enhancer = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                self.connect(estimated_CTF, ctf_mse_enhancer)
                #      log_to_file( self, ctf_mse_enhancer, "data/ctf_mse_enhancer_original.compl")
                #ifft3 = fft_blocks.fft_vcc(total_subc,False,[],True)
                #null_noise = ofdm.noise_nulling(total_subc, cp_length + cp_length)
                #ctf_mse_enhancer = fft_blocks.fft_vcc(total_subc,True,[],True)
                #ctf_mse_enhancer = ofdm.vector_mask( fft_length, virtual_subc/2,
                # total_subc, [] )
                #self.connect( estimated_CTF, ifft3,null_noise,ctf_mse_enhancer )

                estimated_CTF = ctf_mse_enhancer
                print "Disabled CTF MSE enhancer"

            if options.logcir:
                ifft2 = fft_blocks.fft_vcc(total_subc, False, [], True)
                self.connect(estimated_CTF, ifft2,
                             gr.null_sink(gr.sizeof_gr_complex * total_subc))
                summ2 = ofdm.vector_sum_vcc(total_subc)
                c2m2 = gr.complex_to_mag(total_subc)
                self.connect(estimated_CTF, summ2,
                             gr.null_sink(gr.sizeof_gr_complex))
                self.connect(estimated_CTF, c2m2,
                             gr.null_sink(gr.sizeof_float * total_subc))
                log_to_file(self, ifft2, "data/CIR2.compl")
                log_to_file(self, summ2, "data/CTFsumm2.compl")
                log_to_file(self, estimated_CTF, "data/CTF2.compl")
                log_to_file(self, c2m2, "data/CTFmag2.float")

        ## Postprocess the CTF estimate
        ## CTF -> inverse CTF (for equalizer)
        ## CTF -> norm |.|^2 (for CTF display)
            ctf_postprocess = ofdm.postprocess_CTF_estimate(total_subc)
            self.connect(estimated_CTF, ctf_postprocess)
            inv_estimated_CTF = (ctf_postprocess, 0)
            disp_CTF = (ctf_postprocess, 1)


#     if options.disable_equalization or options.ideal:
#       terminate_stream(self, inv_estimated_CTF)
#       inv_estimated_CTF_vec = blocks.vector_source_c([1.0/fft_length*math.sqrt(total_subc)]*total_subc,True,total_subc)
#       inv_estimated_CTF_str = blocks.vector_to_stream(gr.sizeof_gr_complex, total_subc)
#       self.inv_estimated_CTF_mul = ofdm.multiply_const_ccf( 1.0/config.rms_amplitude )
#       #inv_estimated_CTF_mul.set_k(1.0/config.rms_amplitude)
#       inv_estimated_CTF = blocks.stream_to_vector(gr.sizeof_gr_complex, total_subc)
#       self.connect( inv_estimated_CTF_vec, inv_estimated_CTF_str, self.inv_estimated_CTF_mul, inv_estimated_CTF)
#       print "Disabled equalization stage"
        '''
    ## LMS Phase tracking
    ## Track residual frequency offset and sampling clock frequency offset

    nondata_blocks = []
    for i in range(config.frame_length):
      if i in config.training_data.pilotsym_pos:
        nondata_blocks.append(i)
        
    print"\t\t\t\t\tnondata_blocks=",nondata_blocks
    pilot_subc = block_header.pilot_tones
    pilot_subcarriers = block_header.pilot_subc_sym
    print "PILOT SUBCARRIERS: ", pilot_subcarriers
        
    phase_tracking = ofdm.lms_phase_tracking_03( total_subc, pilot_subc,
                                               nondata_blocks, pilot_subcarriers,0 )
    self.connect( ofdm_blocks, ( phase_tracking, 0 ) )
    self.connect( inv_estimated_CTF, ( phase_tracking, 1 ) )
    self.connect( frame_start, ( phase_tracking, 2 ) ) ##
    
    if options.scatter_plot_before_phase_tracking:
      self.before_phase_tracking = equalizer
      
    
    if options.disable_phase_tracking or options.ideal:
      terminate_stream(self, phase_tracking)
      print "Disabled phase tracking stage"
    else:
      ofdm_blocks = phase_tracking
    '''
        ## Channel Equalizer
        if options.disable_equalization or options.ideal or options.ideal2:
            print "Disabled equalization stage"
            if options.ideal is False and options.ideal2 is False:
                terminate_stream(self, inv_estimated_CTF)
        else:
            equalizer = ofdm.channel_equalizer(total_subc)
            self.connect(ofdm_blocks, (equalizer, 0))
            self.connect(inv_estimated_CTF, (equalizer, 1))
            self.connect(frame_start, (equalizer, 2))
            ofdm_blocks = equalizer
        #log_to_file(self, equalizer,"data/equalizer_siso.compl")

        #log_to_file(self, ofdm_blocks, "data/equalizer.compl")

        ## LMS Phase tracking
        ## Track residual frequency offset and sampling clock frequency offset
        if options.ideal is False and options.ideal2 is False:
            nondata_blocks = []
            for i in range(config.frame_length):
                if i in config.training_data.pilotsym_pos:
                    nondata_blocks.append(i)

            print "\t\t\t\t\tnondata_blocks=", nondata_blocks
            pilot_subc = block_header.pilot_tones
            pilot_subcarriers = block_header.pilot_subc_sym
            print "PILOT SUBCARRIERS: ", pilot_subcarriers

            phase_tracking2 = ofdm.lms_phase_tracking_dc_null(
                total_subc, pilot_subc, nondata_blocks, pilot_subcarriers,
                dc_null)
            self.connect(ofdm_blocks, (phase_tracking2, 0))
            self.connect(frame_start, (phase_tracking2, 1))  ##

        if options.disable_phase_tracking or options.ideal or options.ideal2:
            if options.ideal is False and options.ideal2 is False:
                terminate_stream(self, phase_tracking2)
            print "Disabled phase tracking stage"
        else:
            ofdm_blocks = phase_tracking2

        if options.scatter_plot_before_phase_tracking:
            self.before_phase_tracking = equalizer

        ## Output connections

        self.connect(ofdm_blocks, out_ofdm_blocks)
        self.connect(frame_start, out_frame_start)
        if options.ideal is False and options.ideal2 is False:
            self.connect(disp_CTF, out_disp_ctf)
        else:
            self.connect(blocks.vector_source_f([1.0] * total_subc),
                         blocks.stream_to_vector(gr.sizeof_float, total_subc),
                         out_disp_ctf)

        if log:
            log_to_file(self, sc_metric, "data/sc_metric.float")
            log_to_file(self, gi_metric, "data/gi_metric.float")
            log_to_file(self, morelli_foe, "data/morelli_foe.float")
            log_to_file(self, lms_fir, "data/lms_fir.float")
            log_to_file(self, sampler_preamble, "data/preamble.compl")
            log_to_file(self, sync, "data/sync.compl")
            log_to_file(self, frequency_shift, "data/frequency_shift.compl")
            log_to_file(self, fft, "data/fft.compl")
            log_to_file(self, fft, "data/fft.float", mag=True)

            if vars().has_key('subcarrier_mask'):
                log_to_file(self, subcarrier_mask,
                            "data/subcarrier_mask.compl")

            log_to_file(self, ofdm_blocks, "data/ofdm_blocks_out.compl")
            log_to_file(self,
                        frame_start,
                        "data/frame_start.float",
                        char_to_float=True)

            log_to_file(self, sampled_chest_preamble,
                        "data/sampled_chest_preamble.compl")
            log_to_file(self, LS_channel_estimator,
                        "data/ls_channel_estimator.compl")
            log_to_file(self,
                        LS_channel_estimator,
                        "data/ls_channel_estimator.float",
                        mag=True)

            if "ctf_mse_enhancer" in locals():
                log_to_file(self, ctf_mse_enhancer,
                            "data/ctf_mse_enhancer.compl")
                log_to_file(self,
                            ctf_mse_enhancer,
                            "data/ctf_mse_enhancer.float",
                            mag=True)

            log_to_file(self, (ctf_postprocess, 0),
                        "data/inc_estimated_ctf.compl")
            log_to_file(self, (ctf_postprocess, 1), "data/disp_ctf.float")

            log_to_file(self, equalizer, "data/equalizer.compl")
            log_to_file(self, equalizer, "data/equalizer.float", mag=True)

            log_to_file(self, phase_tracking, "data/phase_tracking.compl")
Beispiel #14
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()
    def __init__(self, options, log=False):

        ## Read configuration
        config = station_configuration()

        fft_length = config.fft_length
        cp_length = config.cp_length
        block_header = config.training_data
        data_subc = config.data_subcarriers
        virtual_subc = config.virtual_subcarriers
        total_subc = config.subcarriers
        block_length = config.block_length
        frame_length = config.frame_length

        L = block_header.mm_periodic_parts

        frame_data_blocks = options.data_blocks

        ## Set Input/Output signature
        gr.hier_block2.__init__(
            self,
            "ofdm_inner_receiver",
            gr.io_signature(2, 2, gr.sizeof_gr_complex),
            gr.io_signature5(
                5,
                5,
                gr.sizeof_gr_complex * total_subc,  # OFDM blocks
                gr.sizeof_char,  # Frame start
                gr.sizeof_float * total_subc,  # Normalized |CTF|^2
                gr.sizeof_char,  # Frame start
                gr.sizeof_float * total_subc))  # Normalized |CTF|^2

        ## Input and output ports
        self.input = rx_input = (self, 0)
        self.input2 = rx2_input = (self, 1)

        out_ofdm_blocks = (self, 0)
        out_frame_start = (self, 1)
        out_disp_ctf = (self, 2)
        out_frame_start2 = (self, 3)
        out_disp_ctf2 = (self, 4)

        ## pre-FFT processing

        ## Compute autocorrelations for S&C preamble
        ## and cyclic prefix
        sc_metric = autocorrelator(fft_length / 2, fft_length / 2)
        gi_metric = autocorrelator(fft_length, cp_length)

        self.connect(rx_input, sc_metric)
        self.connect(rx_input, gi_metric)

        sc_metric2 = autocorrelator(fft_length / 2, fft_length / 2)
        gi_metric2 = autocorrelator(fft_length, cp_length)

        self.connect(rx2_input, sc_metric2)
        self.connect(rx2_input, gi_metric2)

        ## Sync. Output contains OFDM blocks
        sync = ofdm.time_sync(fft_length, cp_length)
        self.connect(rx_input, (sync, 0))
        self.connect(sc_metric, (sync, 1))
        self.connect(gi_metric, (sync, 2))
        ofdm_blocks = (sync, 0)
        frame_start = (sync, 1)

        sync2 = ofdm.time_sync(fft_length, cp_length)
        self.connect(rx2_input, (sync2, 0))
        self.connect(sc_metric2, (sync2, 1))
        self.connect(gi_metric2, (sync2, 2))
        ofdm_blocks2 = (sync2, 0)
        frame_start2 = (sync2, 1)

        if options.disable_time_sync or options.ideal:
            terminate_stream(self, ofdm_blocks)
            terminate_stream(self, ofdm_blocks2)
            terminate_stream(self, frame_start)
            terminate_stream(self, frame_start2)

            serial_to_parallel = blocks.stream_to_vector(
                gr.sizeof_gr_complex, block_length)
            serial_to_parallel2 = blocks.stream_to_vector(
                gr.sizeof_gr_complex, block_length)
            discard_cp = ofdm.vector_mask(block_length, cp_length, fft_length,
                                          [])
            discard_cp2 = ofdm.vector_mask(block_length, cp_length, fft_length,
                                           [])
            ofdm_blocks = discard_cp
            ofdm_blocks2 = discard_cp2
            self.connect(rx_input, serial_to_parallel, discard_cp)
            self.connect(rx2_input, serial_to_parallel2, discard_cp2)

            frame_start = [0] * frame_length
            frame_start[0] = 1
            frame_start = blocks.vector_source_b(frame_start, True)
            frame_start2 = [0] * frame_length
            frame_start2[0] = 1
            frame_start2 = blocks.vector_source_b(frame_start2, True)

            print "Disabled time synchronization stage"

        ## Extract preamble, feed to Morelli & Mengali frequency offset estimator
        assert (block_header.mm_preamble_pos == 0)
        morelli_foe = ofdm.mm_frequency_estimator(fft_length, L)
        sampler_preamble = ofdm.vector_sampler(
            gr.sizeof_gr_complex * fft_length, 1)
        self.connect(ofdm_blocks, (sampler_preamble, 0))
        self.connect(frame_start, (sampler_preamble, 1))
        self.connect(sampler_preamble, morelli_foe)
        freq_offset = morelli_foe

        morelli_foe2 = ofdm.mm_frequency_estimator(fft_length, L)
        sampler_preamble2 = ofdm.vector_sampler(
            gr.sizeof_gr_complex * fft_length, 1)
        self.connect(ofdm_blocks2, (sampler_preamble2, 0))
        self.connect(frame_start2, (sampler_preamble2, 1))
        self.connect(sampler_preamble2, morelli_foe2)
        freq_offset2 = morelli_foe2

        ## Adaptive LMS FIR filtering of frequency offset
        lms_fir = ofdm.lms_fir_ff(20, 1e-3)  # TODO: verify parameter choice
        self.connect(freq_offset, lms_fir)
        freq_offset = lms_fir

        lms_fir2 = ofdm.lms_fir_ff(20, 1e-3)  # TODO: verify parameter choice
        self.connect(freq_offset2, lms_fir2)
        freq_offset2 = lms_fir2

        #    log_to_file(self, lms_fir, "data/lms_fir.float")
        #    log_to_file(self, lms_fir2, "data/lms_fir2.float")

        if options.disable_freq_sync or options.ideal:
            terminate_stream(self, freq_offset)
            terminate_stream(self, freq_offset2)
            freq_offset = blocks.vector_source_f([0.0], True)
            freq_offset2 = blocks.vector_source_f([0.0], True)
            print "Disabled frequency synchronization stage"

        ## Correct frequency shift, feed-forward structure
        frequency_shift = ofdm.frequency_shift_vcc(fft_length,
                                                   -1.0 / fft_length,
                                                   cp_length)
        self.connect(ofdm_blocks, (frequency_shift, 0))
        self.connect(freq_offset, (frequency_shift, 1))
        self.connect(frame_start, (frequency_shift, 2))
        ofdm_blocks = frequency_shift

        frequency_shift2 = ofdm.frequency_shift_vcc(fft_length,
                                                    -1.0 / fft_length,
                                                    cp_length)
        self.connect(ofdm_blocks2, (frequency_shift2, 0))
        self.connect(freq_offset2, (frequency_shift2, 1))
        self.connect(frame_start2, (frequency_shift2, 2))
        ofdm_blocks2 = frequency_shift2

        ## FFT
        fft = fft_blocks.fft_vcc(fft_length, True, [], True)
        self.connect(ofdm_blocks, fft)
        ofdm_blocks = fft

        fft2 = fft_blocks.fft_vcc(fft_length, True, [], True)
        self.connect(ofdm_blocks2, fft2)
        ofdm_blocks2 = fft2

        ## Remove virtual subcarriers
        if fft_length > data_subc:
            subcarrier_mask = ofdm.vector_mask(fft_length, virtual_subc / 2,
                                               total_subc, [])
            self.connect(ofdm_blocks, subcarrier_mask)
            ofdm_blocks = subcarrier_mask

            subcarrier_mask2 = ofdm.vector_mask(fft_length, virtual_subc / 2,
                                                total_subc, [])
            self.connect(ofdm_blocks2, subcarrier_mask2)
            ofdm_blocks2 = subcarrier_mask2

            ## Least Squares estimator for channel transfer function (CTF)

            # if options.logcir:
            # log_to_file( self, ofdm_blocks, "data/OFDM_Blocks.compl" )

            # inv_preamble_fd = numpy.array( block_header.pilotsym_fd[
            # block_header.channel_estimation_pilot[0] ] )
            # print "Channel estimation pilot: ", inv_preamble_fd
            # inv_preamble_fd = 1. / inv_preamble_fd
            # LS_channel_estimator0 = ofdm.multiply_const_vcc( list( inv_preamble_fd ) )
            # self.connect( ofdm_blocks, LS_channel_estimator0, blocks.null_sink(gr.sizeof_gr_complex*total_subc))
            # log_to_file( self, LS_channel_estimator0, "data/OFDM_Blocks_eq.compl" )

        ## post-FFT processing

        if options.est_preamble == 1:
            ## extract channel estimation preamble from frame
            chest_pre_trigger = blocks.delay(gr.sizeof_char, 1)
            sampled_chest_preamble = \
              ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )
            self.connect(frame_start, chest_pre_trigger)
            self.connect(chest_pre_trigger, (sampled_chest_preamble, 1))
            self.connect(ofdm_blocks, (sampled_chest_preamble, 0))

            chest_pre_trigger2 = blocks.delay(gr.sizeof_char, 1)
            sampled_chest_preamble2 = \
              ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )
            self.connect(frame_start2, chest_pre_trigger2)
            self.connect(chest_pre_trigger2, (sampled_chest_preamble2, 1))
            self.connect(ofdm_blocks2, (sampled_chest_preamble2, 0))

            ## Least Squares estimator for channel transfer function (CTF)

            # Taking inverse for estimating h11 (h12)
            inv_preamble_fd_1 = numpy.array(block_header.pilotsym_fd_1[
                block_header.channel_estimation_pilot[0]])
            inv_preamble_fd_1 = inv_preamble_fd_1[0::2]

            # Taking inverse for estimating h21 (h22)
            inv_preamble_fd_2 = numpy.array(block_header.pilotsym_fd_2[
                block_header.channel_estimation_pilot[0]])
            inv_preamble_fd_2 = inv_preamble_fd_2[1::2]

            inv_preamble_fd_1 = 1. / inv_preamble_fd_1
            inv_preamble_fd_2 = 1. / inv_preamble_fd_2

            ## Least Squares estimator for channel transfer function (CTF)

            dd = []
            for i in range(total_subc / 2):
                dd.extend([i * 2])

            skip_block_1 = ofdm.int_skip(total_subc, 2, 0)
            skip_block_2 = ofdm.int_skip(total_subc, 2, 1)
            #    inta_estim_1 = ofdm.interpolator(total_subc,2,dd)
            #    inta_estim_2 = ofdm.interpolator(total_subc,2,dd)

            LS_channel_estimator_1 = ofdm.multiply_const_vcc(
                list(inv_preamble_fd_1))
            LS_channel_estimator_2 = ofdm.multiply_const_vcc(
                list(inv_preamble_fd_2))
            self.connect(sampled_chest_preamble, skip_block_1,
                         LS_channel_estimator_1)  #,inta_estim_1 )
            self.connect(sampled_chest_preamble, skip_block_2,
                         LS_channel_estimator_2)  #,inta_estim_2 )

            estimated_CTF_1 = LS_channel_estimator_1  # h0
            estimated_CTF_2 = LS_channel_estimator_2  # h1

            skip_block_3 = ofdm.int_skip(total_subc, 2, 0)
            skip_block_4 = ofdm.int_skip(total_subc, 2, 1)
            #    inta_estim_3 = ofdm.interpolator(total_subc,2,dd)
            #    inta_estim_4 = ofdm.interpolator(total_subc,2,dd)

            LS_channel_estimator_3 = ofdm.multiply_const_vcc(
                list(inv_preamble_fd_1))
            LS_channel_estimator_4 = ofdm.multiply_const_vcc(
                list(inv_preamble_fd_2))

            self.connect(sampled_chest_preamble2, skip_block_3,
                         LS_channel_estimator_3)  #,inta_estim_3 )
            self.connect(sampled_chest_preamble2, skip_block_4,
                         LS_channel_estimator_4)  #,inta_estim_4 )

            estimated_CTF_3 = LS_channel_estimator_3  # h2
            estimated_CTF_4 = LS_channel_estimator_4  # h3

            if not options.disable_ctf_enhancer:

                # if options.logcir:
                # ifft1 = fft_blocks.fft_vcc(total_subc,False,[],True)
                # self.connect( estimated_CTF, ifft1,blocks.null_sink(gr.sizeof_gr_complex*total_subc))
                # summ1 = ofdm.vector_sum_vcc(total_subc)
                # c2m =gr.complex_to_mag(total_subc)
                # self.connect( estimated_CTF,summ1 ,blocks.null_sink(gr.sizeof_gr_complex))
                # self.connect( estimated_CTF, c2m,blocks.null_sink(gr.sizeof_float*total_subc))
                # log_to_file( self, ifft1, "data/CIR1.compl" )
                # log_to_file( self, summ1, "data/CTFsumm1.compl" )
                # log_to_file( self, estimated_CTF, "data/CTF1.compl" )
                # log_to_file( self, c2m, "data/CTFmag1.float" )

                ## MSE enhancer
                ctf_mse_enhancer_1 = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                ctf_mse_enhancer_2 = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                self.connect(estimated_CTF_1, ctf_mse_enhancer_1)
                self.connect(estimated_CTF_2, ctf_mse_enhancer_2)

                ctf_mse_enhancer_3 = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                ctf_mse_enhancer_4 = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                self.connect(estimated_CTF_3, ctf_mse_enhancer_3)
                self.connect(estimated_CTF_4, ctf_mse_enhancer_4)

                estimated_CTF_1 = ctf_mse_enhancer_1
                estimated_CTF_2 = ctf_mse_enhancer_2

                estimated_CTF_3 = ctf_mse_enhancer_3
                estimated_CTF_4 = ctf_mse_enhancer_4
                print "Disabled CTF MSE enhancer"

            ctf_postprocess_1 = ofdm.postprocess_CTF_estimate(total_subc / 2)
            self.connect(estimated_CTF_1, (ctf_postprocess_1, 0))
            ctf_postprocess_2 = ofdm.postprocess_CTF_estimate(total_subc / 2)
            self.connect(estimated_CTF_2, (ctf_postprocess_2, 0))
            ctf_postprocess_3 = ofdm.postprocess_CTF_estimate(total_subc / 2)
            self.connect(estimated_CTF_3, (ctf_postprocess_3, 0))
            ctf_postprocess_4 = ofdm.postprocess_CTF_estimate(total_subc / 2)
            self.connect(estimated_CTF_4, (ctf_postprocess_4, 0))

            inv_CTF_1 = (ctf_postprocess_1, 0)
            disp_CTF_1 = (ctf_postprocess_1, 1)
            inv_CTF_2 = (ctf_postprocess_2, 0)
            disp_CTF_2 = (ctf_postprocess_2, 1)
            inv_CTF_3 = (ctf_postprocess_3, 0)
            disp_CTF_3 = (ctf_postprocess_3, 1)
            inv_CTF_4 = (ctf_postprocess_4, 0)
            disp_CTF_4 = (ctf_postprocess_4, 1)

            disp_CTF_RX0 = blocks.add_ff(total_subc / 2)
            disp_CTF_RX1 = blocks.add_ff(total_subc / 2)

            self.connect(disp_CTF_1, (disp_CTF_RX0, 0))
            self.connect(disp_CTF_2, (disp_CTF_RX0, 1))
            self.connect(disp_CTF_3, (disp_CTF_RX1, 0))
            self.connect(disp_CTF_4, (disp_CTF_RX1, 1))

            terminate_stream(self, disp_CTF_RX0)
            terminate_stream(self, disp_CTF_RX1)

            disp_CTF_RX0 = blocks.null_source(gr.sizeof_float * total_subc)
            disp_CTF_RX1 = blocks.null_source(gr.sizeof_float * total_subc)
            ## Channel Equalizer

            #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
            #log_to_file(self, ofdm_blocks2, "data/vec_mask2.compl")

            nondata_blocks = []
            for i in range(config.frame_length):
                if i in config.training_data.pilotsym_pos:
                    nondata_blocks.append(i)

            pilot_subc = block_header.pilot_tones
            pilot_subcarriers = block_header.pilot_subc_sym
            print "PILOT SUBCARRIERS: ", pilot_subcarriers

            phase_tracking = ofdm.lms_phase_tracking_03(
                total_subc, pilot_subc, nondata_blocks, pilot_subcarriers, 0)
            phase_tracking2 = ofdm.lms_phase_tracking_03(
                total_subc, pilot_subc, nondata_blocks, pilot_subcarriers, 0)

            ##phase_tracking = ofdm.LMS_phase_tracking2( total_subc, pilot_subc,
            ##                                          nondata_blocks )
            ##phase_tracking2 = ofdm.LMS_phase_tracking2( total_subc, pilot_subc,
            ##                                           nondata_blocks )

            #    self.connect( ofdm_blocks,          ( phase_tracking, 0 ) )
            #    self.connect( ofdm_blocks2,          ( phase_tracking, 1 ))
            #    self.connect( inv_CTF_1,            ( phase_tracking, 2 ) )
            #    self.connect( inv_CTF_3,            ( phase_tracking, 3 ) )
            #    self.connect( frame_start,            ( phase_tracking, 4 ) )
            #    self.connect( frame_start2,            ( phase_tracking, 5) )
            #
            #    self.connect( ofdm_blocks2,          ( phase_tracking2, 0 ) )
            #    self.connect( ofdm_blocks,          ( phase_tracking2, 1 ))
            #    self.connect( inv_CTF_3,            ( phase_tracking2, 2 ) )
            #    self.connect( inv_CTF_1,            ( phase_tracking2, 3 ) )
            #    self.connect( frame_start2,            ( phase_tracking2, 4 ) )
            #    self.connect( frame_start,            ( phase_tracking2, 5 ) )

            self.connect(ofdm_blocks, (phase_tracking, 0))
            self.connect(inv_CTF_1, (phase_tracking, 1))
            self.connect(frame_start, (phase_tracking, 2))

            self.connect(ofdm_blocks2, (phase_tracking2, 0))
            self.connect(inv_CTF_3, (phase_tracking2, 1))
            self.connect(frame_start2, (phase_tracking2, 2))

            #ofdm_blocks = phase_tracking
            #ofdm_blocks2 = phase_tracking2
            self.connect(phase_tracking,
                         blocks.null_sink(gr.sizeof_gr_complex * total_subc))
            self.connect(phase_tracking2,
                         blocks.null_sink(gr.sizeof_gr_complex * total_subc))

            terminate_stream(self, inv_CTF_2)
            terminate_stream(self, inv_CTF_4)
            #terminate_stream(self, inv_CTF_1)
            #terminate_stream(self, inv_CTF_3)
            terminate_stream(self, estimated_CTF_3)
            terminate_stream(self, estimated_CTF_4)
            ##terminate_stream(self, (phase_tracking,1))
            ##terminate_stream(self, (phase_tracking2,1))
            '''equalizer = ofdm.channel_equalizer_mimo_2( total_subc )
        self.connect(  ofdm_blocks,         ( equalizer, 0 ) )
        self.connect(  ofdm_blocks2,        ( equalizer, 1 ) )
        self.connect( inv_CTF_1,            ( equalizer, 2 ) )
        self.connect( inv_CTF_2,            ( equalizer, 3 ) )
        self.connect( inv_CTF_3,            ( equalizer, 4 ) )
        self.connect( inv_CTF_4,            ( equalizer, 5 ) )
        self.connect( frame_start,          ( equalizer, 6 ) )
        self.connect( frame_start2,         ( equalizer, 7 ) )
        ofdm_blocks = equalizer'''

            terminate_stream(self, inv_CTF_1)
            terminate_stream(self, inv_CTF_3)

            equalizer = ofdm.channel_equalizer_mimo_2(total_subc)
            self.connect(ofdm_blocks, (equalizer, 0))
            self.connect(estimated_CTF_1, (equalizer, 1))
            self.connect(estimated_CTF_2, (equalizer, 2))
            self.connect(frame_start, (equalizer, 3))
            ofdm_blocks = equalizer

            equalizer2 = ofdm.channel_equalizer_mimo_2(total_subc)
            self.connect(ofdm_blocks2, (equalizer2, 0))
            self.connect(estimated_CTF_3, (equalizer2, 1))
            self.connect(estimated_CTF_4, (equalizer2, 2))
            self.connect(frame_start2, (equalizer2, 3))
            ofdm_blocks2 = equalizer2

            #ofdm_blocks = equalizer
            #ofdm_blocks2 = equalizer2

            #log_to_file(self, equalizer,"data/equalizer.compl")
            #log_to_file(self, ofdm_blocks2,"data/equalizer.compl")
            #log_to_file(self, ofdm_blocks,"data/equalizer2.compl")

            ## LMS Phase tracking
            ## Track residual frequency offset and sampling clock frequency offset
            '''
        nondata_blocks = []
        for i in range(config.frame_length):
          if i in config.training_data.pilotsym_pos:
            nondata_blocks.append(i)
            
        pilot_subc = block_header.pilot_tones
            
        phase_tracking = ofdm.LMS_phase_tracking2( total_subc, pilot_subc,
                                                   nondata_blocks )
        self.connect( equalizer, ( phase_tracking, 0 ) )
        self.connect( frame_start, ( phase_tracking, 1 ) )
        
        phase_tracking2 = ofdm.LMS_phase_tracking2( total_subc, pilot_subc,
                                                    nondata_blocks )
        self.connect( equalizer2, ( phase_tracking2, 0 ) )
        self.connect( frame_start2, ( phase_tracking2, 1 ) )
        
        # if options.scatter_plot_before_phase_tracking:
          # self.before_phase_tracking = equalizer
          
        
        if options.disable_phase_tracking or options.ideal:
          terminate_stream(self, phase_tracking)
          terminate_stream(self, phase_tracking2)
          print "Disabled phase tracking stage"
        else:
          ofdm_blocks = phase_tracking
          ofdm_blocks2 = phase_tracking2
          
        log_to_file(self,phase_tracking, "data/phase_tracking.compl")
        '''

            combine = blocks.add_cc(config.subcarriers)
            self.connect(ofdm_blocks, (combine, 0))
            self.connect(ofdm_blocks2, (combine, 1))

            norm_val = [0.5] * 208
            norm = ofdm.multiply_const_vcc(norm_val)
            self.connect(combine, norm)

            ofdm_blocks = norm
            ##    div = gr.multiply_cc(config.subcarriers)
            ##    const = blocks.vector_source_c([[0.5+0]*config.subcarriers],True)
            ##    self.connect(ofdm_blocks,div)
            ##    self.connect(const,(div,1))
            ##    ofdm_blocks=div
            #    log_to_file(self,combine,"data/combine.compl")
            ## Output connections

            self.connect(ofdm_blocks, out_ofdm_blocks)
            self.connect(frame_start, out_frame_start)
            self.connect(disp_CTF_RX0, out_disp_ctf)
            self.connect(frame_start2, out_frame_start2)
            self.connect(disp_CTF_RX1, out_disp_ctf2)

        else:
            ## extract channel estimation preamble from frame

            chest_pre_trigger_11 = blocks.delay(gr.sizeof_char, 1)
            chest_pre_trigger_12 = blocks.delay(gr.sizeof_char, 2)
            sampled_chest_preamble_11 = \
              ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )
            sampled_chest_preamble_12 = \
              ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )

            self.connect(frame_start, chest_pre_trigger_11)
            self.connect(chest_pre_trigger_11, (sampled_chest_preamble_11, 1))
            self.connect(ofdm_blocks, (sampled_chest_preamble_11, 0))

            self.connect(frame_start, chest_pre_trigger_12)
            self.connect(chest_pre_trigger_12, (sampled_chest_preamble_12, 1))
            self.connect(ofdm_blocks, (sampled_chest_preamble_12, 0))

            chest_pre_trigger_21 = blocks.delay(gr.sizeof_char, 1)
            chest_pre_trigger_22 = blocks.delay(gr.sizeof_char, 2)
            sampled_chest_preamble_21 = \
              ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )
            sampled_chest_preamble_22 = \
              ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )

            self.connect(frame_start2, chest_pre_trigger_21)
            self.connect(chest_pre_trigger_21, (sampled_chest_preamble_21, 1))
            self.connect(ofdm_blocks2, (sampled_chest_preamble_21, 0))

            self.connect(frame_start2, chest_pre_trigger_22)
            self.connect(chest_pre_trigger_22, (sampled_chest_preamble_22, 1))
            self.connect(ofdm_blocks2, (sampled_chest_preamble_22, 0))

            # Taking inverse for estimating h11 (h12)
            inv_preamble_fd_1 = numpy.array(block_header.pilotsym_fd_1[
                block_header.channel_estimation_pilot[0]])
            #inv_preamble_fd_1 = inv_preamble_fd_1[0::2]

            # Taking inverse for estimating h21 (h22)
            inv_preamble_fd_2 = numpy.array(block_header.pilotsym_fd_2[
                block_header.channel_estimation_pilot[0] + 1])
            #inv_preamble_fd_2 = inv_preamble_fd_2[1::2]

            inv_preamble_fd_1 = 1. / inv_preamble_fd_1
            inv_preamble_fd_2 = 1. / inv_preamble_fd_2

            # dd = []
            #for i in range (total_subc/2):
            # dd.extend([i*2])

            skip_block_11 = ofdm.int_skip(total_subc, 2, 0)
            skip_block_111 = ofdm.int_skip(total_subc, 2, 0)
            skip_block_12 = ofdm.int_skip(total_subc, 2, 1)
            #    inta_estim_1 = ofdm.interpolator(total_subc,2,dd)
            #    inta_estim_2 = ofdm.interpolator(total_subc,2,dd)

            LS_channel_estimator_11 = ofdm.multiply_const_vcc(
                list(inv_preamble_fd_1))
            LS_channel_estimator_12 = ofdm.multiply_const_vcc(
                list(inv_preamble_fd_2))
            self.connect(sampled_chest_preamble_11,
                         LS_channel_estimator_11)  #,inta_estim_1 )
            self.connect(sampled_chest_preamble_12,
                         LS_channel_estimator_12)  #,inta_estim_2 )

            estimated_CTF_11 = LS_channel_estimator_11  # h0
            estimated_CTF_12 = LS_channel_estimator_12  # h1

            skip_block_21 = ofdm.int_skip(total_subc, 2, 0)
            skip_block_211 = ofdm.int_skip(total_subc, 2, 0)
            skip_block_22 = ofdm.int_skip(total_subc, 2, 1)
            #    inta_estim_3 = ofdm.interpolator(total_subc,2,dd)
            #    inta_estim_4 = ofdm.interpolator(total_subc,2,dd)

            LS_channel_estimator_21 = ofdm.multiply_const_vcc(
                list(inv_preamble_fd_1))
            LS_channel_estimator_22 = ofdm.multiply_const_vcc(
                list(inv_preamble_fd_2))

            self.connect(sampled_chest_preamble_21,
                         LS_channel_estimator_21)  #,inta_estim_3 )
            self.connect(sampled_chest_preamble_22,
                         LS_channel_estimator_22)  #,inta_estim_4 )

            estimated_CTF_21 = LS_channel_estimator_21  # h2
            estimated_CTF_22 = LS_channel_estimator_22  # h3

            if not options.disable_ctf_enhancer:

                # if options.logcir:
                # ifft1 = fft_blocks.fft_vcc(total_subc,False,[],True)
                # self.connect( estimated_CTF, ifft1,blocks.null_sink(gr.sizeof_gr_complex*total_subc))
                # summ1 = ofdm.vector_sum_vcc(total_subc)
                # c2m =gr.complex_to_mag(total_subc)
                # self.connect( estimated_CTF,summ1 ,blocks.null_sink(gr.sizeof_gr_complex))
                # self.connect( estimated_CTF, c2m,blocks.null_sink(gr.sizeof_float*total_subc))
                # log_to_file( self, ifft1, "data/CIR1.compl" )
                # log_to_file( self, summ1, "data/CTFsumm1.compl" )
                # log_to_file( self, estimated_CTF, "data/CTF1.compl" )
                # log_to_file( self, c2m, "data/CTFmag1.float" )

                ## MSE enhancer
                ctf_mse_enhancer_11 = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                ctf_mse_enhancer_12 = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                self.connect(estimated_CTF_11, ctf_mse_enhancer_11)
                self.connect(estimated_CTF_12, ctf_mse_enhancer_12)

                ctf_mse_enhancer_21 = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                ctf_mse_enhancer_22 = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                self.connect(estimated_CTF_21, ctf_mse_enhancer_21)
                self.connect(estimated_CTF_22, ctf_mse_enhancer_22)

                estimated_CTF_11 = ctf_mse_enhancer_11
                estimated_CTF_12 = ctf_mse_enhancer_12

                estimated_CTF_21 = ctf_mse_enhancer_21
                estimated_CTF_22 = ctf_mse_enhancer_22
                print "Disabled CTF MSE enhancer"

            ctf_postprocess_11 = ofdm.postprocess_CTF_estimate(total_subc)
            self.connect(estimated_CTF_11, (ctf_postprocess_11, 0))
            ctf_postprocess_12 = ofdm.postprocess_CTF_estimate(total_subc)
            self.connect(estimated_CTF_12, (ctf_postprocess_12, 0))

            ctf_postprocess_21 = ofdm.postprocess_CTF_estimate(total_subc)
            self.connect(estimated_CTF_21, (ctf_postprocess_21, 0))
            ctf_postprocess_22 = ofdm.postprocess_CTF_estimate(total_subc)
            self.connect(estimated_CTF_22, (ctf_postprocess_22, 0))

            inv_CTF_11 = (ctf_postprocess_11, 0)
            disp_CTF_11 = (ctf_postprocess_11, 1)
            inv_CTF_12 = (ctf_postprocess_12, 0)
            disp_CTF_12 = (ctf_postprocess_12, 1)
            inv_CTF_21 = (ctf_postprocess_21, 0)
            disp_CTF_21 = (ctf_postprocess_21, 1)
            inv_CTF_22 = (ctf_postprocess_22, 0)
            disp_CTF_22 = (ctf_postprocess_22, 1)

            #disp_CTF_RX0 = blocks.add_ff(total_subc)
            #disp_CTF_RX1 = blocks.add_ff(total_subc)

            #self.connect ( disp_CTF_11, (disp_CTF_RX0, 0) )
            #self.connect ( disp_CTF_12, (disp_CTF_RX0, 1) )
            #self.connect ( disp_CTF_21, (disp_CTF_RX1, 0) )
            #self.connect ( disp_CTF_22, (disp_CTF_RX1, 1) )

            terminate_stream(self, disp_CTF_21)
            terminate_stream(self, disp_CTF_22)

            disp_CTF_RX0 = disp_CTF_11
            disp_CTF_RX1 = disp_CTF_12
            ## Channel Equalizer

            #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
            #log_to_file(self, ofdm_blocks2, "data/vec_mask2.compl")

            nondata_blocks = []
            for i in range(config.frame_length):
                if i in config.training_data.pilotsym_pos:
                    nondata_blocks.append(i)

            pilot_subc = block_header.pilot_tones
            pilot_subcarriers = block_header.pilot_subc_sym
            print "PILOT SUBCARRIERS: ", pilot_subcarriers

            phase_tracking = ofdm.lms_phase_tracking_03(
                total_subc, pilot_subc, nondata_blocks, pilot_subcarriers, 0)
            phase_tracking2 = ofdm.lms_phase_tracking_03(
                total_subc, pilot_subc, nondata_blocks, pilot_subcarriers, 0)

            ##phase_tracking = ofdm.LMS_phase_tracking2( total_subc, pilot_subc,
            ##                                          nondata_blocks )
            ##phase_tracking2 = ofdm.LMS_phase_tracking2( total_subc, pilot_subc,
            ##                                           nondata_blocks )

            #    self.connect( ofdm_blocks,          ( phase_tracking, 0 ) )
            #    self.connect( ofdm_blocks2,          ( phase_tracking, 1 ))
            #    self.connect( inv_CTF_1,            ( phase_tracking, 2 ) )
            #    self.connect( inv_CTF_3,            ( phase_tracking, 3 ) )
            #    self.connect( frame_start,            ( phase_tracking, 4 ) )
            #    self.connect( frame_start2,            ( phase_tracking, 5) )
            #
            #    self.connect( ofdm_blocks2,          ( phase_tracking2, 0 ) )
            #    self.connect( ofdm_blocks,          ( phase_tracking2, 1 ))
            #    self.connect( inv_CTF_3,            ( phase_tracking2, 2 ) )
            #    self.connect( inv_CTF_1,            ( phase_tracking2, 3 ) )
            #    self.connect( frame_start2,            ( phase_tracking2, 4 ) )
            #    self.connect( frame_start,            ( phase_tracking2, 5 ) )

            self.connect(ofdm_blocks, (phase_tracking, 0))
            self.connect(inv_CTF_11, skip_block_111, (phase_tracking, 1))
            self.connect(frame_start, (phase_tracking, 2))

            self.connect(ofdm_blocks2, (phase_tracking2, 0))
            self.connect(inv_CTF_21, skip_block_211, (phase_tracking2, 1))
            self.connect(frame_start2, (phase_tracking2, 2))

            if options.disable_phase_tracking or options.ideal:
                terminate_stream(self, phase_tracking)
                terminate_stream(self, phase_tracking2)
                print "Disabled phase tracking stage"
            else:
                ofdm_blocks = phase_tracking
                ofdm_blocks2 = phase_tracking2

            self.connect(phase_tracking,
                         blocks.null_sink(gr.sizeof_gr_complex * total_subc))
            self.connect(phase_tracking2,
                         blocks.null_sink(gr.sizeof_gr_complex * total_subc))

            terminate_stream(self, inv_CTF_12)
            terminate_stream(self, inv_CTF_22)
            #terminate_stream(self, inv_CTF_1)
            #terminate_stream(self, inv_CTF_3)
            #terminate_stream(self, estimated_CTF_21)
            #terminate_stream(self, estimated_CTF_22)
            ##terminate_stream(self, (phase_tracking,1))
            ##terminate_stream(self, (phase_tracking2,1))

            equalizer = ofdm.channel_equalizer_mimo_3(total_subc)
            self.connect(ofdm_blocks, (equalizer, 0))
            self.connect(ofdm_blocks2, (equalizer, 1))
            self.connect(estimated_CTF_11, skip_block_11, (equalizer, 2))
            self.connect(estimated_CTF_12, skip_block_12, (equalizer, 3))
            self.connect(estimated_CTF_21, skip_block_21, (equalizer, 4))
            self.connect(estimated_CTF_22, skip_block_22, (equalizer, 5))
            self.connect(frame_start, (equalizer, 6))
            self.connect(frame_start, (equalizer, 7))
            ofdm_blocks = equalizer

            #terminate_stream(self, inv_CTF_11)
            #terminate_stream(self, inv_CTF_21)
            '''equalizer = ofdm.channel_equalizer_mimo_2( total_subc )    
        self.connect(  ofdm_blocks,          ( equalizer, 0 ) )
        self.connect( estimated_CTF_11,    skip_block_11,        ( equalizer, 1 ) )
        self.connect( estimated_CTF_12,   skip_block_12,         ( equalizer, 2 ) )
        self.connect( frame_start,          ( equalizer, 3 ) )
        ofdm_blocks = equalizer
        
        equalizer2 = ofdm.channel_equalizer_mimo_2( total_subc )    
        self.connect( ofdm_blocks2,         ( equalizer2, 0 ) )
        self.connect( estimated_CTF_21,  skip_block_21,            ( equalizer2, 1 ) )
        self.connect( estimated_CTF_22,    skip_block_22,        ( equalizer2, 2 ) )
        self.connect( frame_start2,         ( equalizer2, 3 ) )
        ofdm_blocks2 = equalizer2'''

            #ofdm_blocks = equalizer
            #ofdm_blocks2 = equalizer2

            #log_to_file(self, equalizer,"data/equalizer.compl")
            #log_to_file(self, ofdm_blocks2,"data/equalizer.compl")
            #log_to_file(self, ofdm_blocks,"data/equalizer2.compl")

            ## LMS Phase tracking
            ## Track residual frequency offset and sampling clock frequency offset
            '''
        nondata_blocks = []
        for i in range(config.frame_length):
          if i in config.training_data.pilotsym_pos:
            nondata_blocks.append(i)
            
        pilot_subc = block_header.pilot_tones
            
        phase_tracking = ofdm.LMS_phase_tracking2( total_subc, pilot_subc,
                                                   nondata_blocks )
        self.connect( equalizer, ( phase_tracking, 0 ) )
        self.connect( frame_start, ( phase_tracking, 1 ) )
        
        phase_tracking2 = ofdm.LMS_phase_tracking2( total_subc, pilot_subc,
                                                    nondata_blocks )
        self.connect( equalizer2, ( phase_tracking2, 0 ) )
        self.connect( frame_start2, ( phase_tracking2, 1 ) )
        
        # if options.scatter_plot_before_phase_tracking:
          # self.before_phase_tracking = equalizer
          
        
        if options.disable_phase_tracking or options.ideal:
          terminate_stream(self, phase_tracking)
          terminate_stream(self, phase_tracking2)
          print "Disabled phase tracking stage"
        else:
          ofdm_blocks = phase_tracking
          ofdm_blocks2 = phase_tracking2
          
        log_to_file(self,phase_tracking, "data/phase_tracking.compl")
        '''
            '''combine = blocks.add_cc(config.subcarriers)
        self.connect(ofdm_blocks, (combine,0))
        self.connect(ofdm_blocks2, (combine,1))
        
        norm_val = [0.5]*config.subcarriers
        norm = ofdm.multiply_const_vcc( norm_val)
        self.connect(combine,norm)
        
        ofdm_blocks = norm'''
            ##    div = gr.multiply_cc(config.subcarriers)
            ##    const = blocks.vector_source_c([[0.5+0]*config.subcarriers],True)
            ##    self.connect(ofdm_blocks,div)
            ##    self.connect(const,(div,1))
            ##    ofdm_blocks=div
            #    log_to_file(self,combine,"data/combine.compl")
            ## Output connections

            self.connect(ofdm_blocks, out_ofdm_blocks)
            self.connect(frame_start, out_frame_start)
            self.connect(disp_CTF_RX0, out_disp_ctf)
            self.connect(frame_start2, out_frame_start2)
            self.connect(disp_CTF_RX1, out_disp_ctf2)
Beispiel #16
0
  def __init__( self, options, log = False ):
    
    ## Read configuration
    config = station_configuration()
    
    fft_length    = config.fft_length
    cp_length     = config.cp_length
    block_header  = config.training_data
    data_subc     = config.data_subcarriers
    virtual_subc  = config.virtual_subcarriers
    total_subc    = config.subcarriers
    block_length  = config.block_length
    frame_length  = config.frame_length
    dc_null       = config.dc_null
    
    L             = block_header.mm_periodic_parts
    
    
    ## Set Input/Output signature
    gr.hier_block2.__init__( self, 
        "ofdm_inner_receiver",
        gr.io_signature(
            1, 1,
            gr.sizeof_gr_complex ),
        gr.io_signaturev(
            4, 4,
            [gr.sizeof_gr_complex * total_subc,    # OFDM blocks
            gr.sizeof_char,                       # Frame start
            gr.sizeof_float * total_subc,
            gr.sizeof_float] ) )      # Normalized |CTF|^2 
    
    
    ## Input and output ports
    self.input = rx_input = self
    
    out_ofdm_blocks = ( self, 0 )
    out_frame_start = ( self, 1 )
    out_disp_ctf    = ( self, 2 )
    out_disp_cfo    = ( self, 3 )
    
    
    ## pre-FFT processing
    if options.ideal is False and options.ideal2 is False:
        if options.old_receiver is False:
            ## Compute autocorrelations for S&C preamble
            ## and cyclic prefix
            
            self._sc_metric = sc_metric = autocorrelator( fft_length/2, fft_length/2 )
            self._gi_metric = gi_metric = autocorrelator( fft_length, cp_length )
            
            self.connect( rx_input, sc_metric )
            self.connect( rx_input, gi_metric )    
            
            ## Sync. Output contains OFDM blocks
            sync = ofdm.time_sync( fft_length, cp_length )
            self.connect( rx_input, ( sync, 0 ) )
            self.connect( sc_metric, ( sync, 1 ) )
            self.connect( gi_metric, ( sync, 2 ) )
            ofdm_blocks = ( sync, 0 )
            frame_start = ( sync, 1 )
            #log_to_file( self, ( sync, 1 ), "data/peak_detector.char" )
        else:
    
            #Testing old/new metric
            self.tm = schmidl.recursive_timing_metric(fft_length)
            self.connect( self.input, self.tm)
            #log_to_file( self, self.tm, "data/rec_sc_metric_ofdm.float" )
            
            timingmetric_shift = -2#int(-cp_length/4)# 0#-2 #int(-cp_length * 0.8)
            tmfilter = filter.fft_filter_fff(1, [1./cp_length]*cp_length)
            self.connect( self.tm, tmfilter )
            self.tm = tmfilter
        
            
            
            self._pd_thres = 0.3
            self._pd_lookahead = fft_length / 2 # empirically chosen
            peak_detector = ofdm.peak_detector_02_fb(self._pd_lookahead, self._pd_thres)
            self.connect(self.tm, peak_detector)
            #log_to_file( self, peak_detector, "data/rec_peak_detector.char" )
            
            
            frame_start = [0]*frame_length
            frame_start[0] = 1
            frame_start = self.frame_trigger_old = blocks.vector_source_b(frame_start,True)
            
            
            delayed_timesync = blocks.delay(gr.sizeof_char,
                                        (frame_length-1)*block_length + timingmetric_shift)
            self.connect( peak_detector, delayed_timesync )
            
            self.block_sampler = ofdm.vector_sampler(gr.sizeof_gr_complex,block_length*frame_length)
            self.discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
            
            self.connect(self.input,self.block_sampler)
            self.connect(delayed_timesync,(self.block_sampler,1))
        
            # TODO: dynamic solution
            vt2s = blocks.vector_to_stream(gr.sizeof_gr_complex*block_length,
                                                    frame_length)
            self.connect(self.block_sampler,vt2s,self.discard_cp)
            #terminate_stream(self,ofdm_blocks)
            ofdm_blocks = self.discard_cp
#     else:
#       serial_to_parallel = blocks.stream_to_vector(gr.sizeof_gr_complex,block_length)
#       discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
#       ofdm_blocks = discard_cp
#       self.connect( rx_input, serial_to_parallel, discard_cp )
#       frame_start = [0]*frame_length
#       frame_start[0] = 1
#       frame_start = blocks.vector_source_b(frame_start,True)
#       
#       print "Disabled time synchronization stage"
    
    ## Compute autocorrelations for S&C preamble
    ## and cyclic prefix
    
    #log_to_file( self, sc_metric, "data/sc_metric_ofdm.float" )
    #log_to_file(self, frame_start, "data/frame_start.compl")
    
#    log_to_file(self,ofdm_blocks,"data/ofdm_blocks_original.compl")
    
    if options.disable_time_sync or options.ideal or options.ideal2:
      if options.ideal is False and options.ideal2 is False:
          terminate_stream(self, ofdm_blocks)
          terminate_stream(self, frame_start)
      
      serial_to_parallel = blocks.stream_to_vector(gr.sizeof_gr_complex,block_length)
      discard_cp = ofdm.vector_mask_dc_null(block_length,cp_length,fft_length,dc_null, [])
      ofdm_blocks = discard_cp
      self.connect( rx_input, serial_to_parallel, discard_cp )
      
      frame_start = [0]*frame_length
      frame_start[0] = 1
      frame_start = blocks.vector_source_b(frame_start,True)
      
      print "Disabled time synchronization stage"
    
    print"\t\t\t\t\tframe_length = ",frame_length
    
    
    
    
    if options.ideal is False and options.ideal2 is False:
        ## Extract preamble, feed to Morelli & Mengali frequency offset estimator
        assert( block_header.mm_preamble_pos == 0 )
        morelli_foe = ofdm.mm_frequency_estimator( fft_length, L,1,0 )
        sampler_preamble = ofdm.vector_sampler( gr.sizeof_gr_complex * fft_length,
                                            1 )
        self.connect( ofdm_blocks, ( sampler_preamble, 0 ) )
        self.connect( frame_start, ( sampler_preamble, 1 ) )
        self.connect( sampler_preamble, morelli_foe )
        freq_offset = morelli_foe
    
    
        ## Adaptive LMS FIR filtering of frequency offset
        lms_fir = ofdm.lms_fir_ff( 20, 1e-3 ) # TODO: verify parameter choice
        self.connect( freq_offset, lms_fir )
        freq_offset = lms_fir
    
        #self.zmq_probe_freqoff = zeromq.pub_sink(gr.sizeof_float, 1, "tcp://*:5557")
        self.connect(lms_fir, blocks.keep_one_in_n(gr.sizeof_float,20) ,out_disp_cfo)
    else:
        self.connect(blocks.vector_source_f ([1]) ,out_disp_cfo)
    
        #log_to_file(self, lms_fir, "data/lms_fir.float")
    
    if options.disable_freq_sync or options.ideal or options.ideal2:
      if options.ideal is False and options.ideal2 is False:
          terminate_stream(self, freq_offset)
          freq_offset = blocks.vector_source_f([0.0],True)
      print "Disabled frequency synchronization stage"
    
    if options.ideal is False and options.ideal2 is False:
        ## Correct frequency shift, feed-forward structure
        frequency_shift = ofdm.frequency_shift_vcc( fft_length, -1.0/fft_length,
                                                    cp_length )
        self.connect( ofdm_blocks, ( frequency_shift, 0 ) )
        self.connect( freq_offset, ( frequency_shift, 1 ) )
        self.connect( frame_start, ( frequency_shift, 2 ) )
        ofdm_blocks = frequency_shift
    
    
    
    
    ## FFT
    fft = fft_blocks.fft_vcc( fft_length, True, [], True )
    self.connect( ofdm_blocks, fft )
    ofdm_blocks = fft
    #log_to_file( self, fft, "data/compen.float" )
    
    
    
    ## Remove virtual subcarriers
    if fft_length > data_subc:
      subcarrier_mask = ofdm.vector_mask_dc_null( fft_length, virtual_subc/2,
                                           total_subc, dc_null, [] )
      self.connect( ofdm_blocks, subcarrier_mask )
      ofdm_blocks = subcarrier_mask
      #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
       ## Least Squares estimator for channel transfer function (CTF)
    
    
      if options.logcir:
          log_to_file( self, ofdm_blocks, "data/OFDM_Blocks.compl" )
          
          inv_preamble_fd = numpy.array( block_header.pilotsym_fd[ 
            block_header.channel_estimation_pilot[0] ] )
          inv_preamble_fd = numpy.concatenate([inv_preamble_fd[:total_subc/2],inv_preamble_fd[total_subc/2+dc_null:]])
          #print "Channel estimation pilot: ", inv_preamble_fd
          inv_preamble_fd = 1. / inv_preamble_fd
          LS_channel_estimator0 = ofdm.multiply_const_vcc( list( inv_preamble_fd ) )
          self.connect( ofdm_blocks, LS_channel_estimator0, gr.null_sink(gr.sizeof_gr_complex*total_subc))
          log_to_file( self, LS_channel_estimator0, "data/OFDM_Blocks_eq.compl" )
          
    ## post-FFT processing
      
    
    
    ## extract channel estimation preamble from frame
    if options.ideal is False and options.ideal2 is False:
        chest_pre_trigger = blocks.delay( gr.sizeof_char, 1)
        sampled_chest_preamble = ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1)
        self.connect( frame_start,       chest_pre_trigger )
        self.connect( chest_pre_trigger, ( sampled_chest_preamble, 1 ) )
        self.connect( ofdm_blocks,       ( sampled_chest_preamble, 0 ) )
    

    
        ## Least Squares estimator for channel transfer function (CTF)
        inv_preamble_fd = numpy.array( block_header.pilotsym_fd[ 
                                                            block_header.channel_estimation_pilot[0] ] )
        inv_preamble_fd = numpy.concatenate([inv_preamble_fd[:total_subc/2],inv_preamble_fd[total_subc/2+dc_null:]])    
        #print "Channel estimation pilot: ", inv_preamble_fd
        inv_preamble_fd = 1. / inv_preamble_fd
    
        LS_channel_estimator = ofdm.multiply_const_vcc( list( inv_preamble_fd ) )
        self.connect( sampled_chest_preamble, LS_channel_estimator )
        estimated_CTF = LS_channel_estimator
    
        if options.logcir:
             log_to_file( self, sampled_chest_preamble, "data/PREAM.compl" )
     
    
        if not options.disable_ctf_enhancer:
      
      
            if options.logcir:
                ifft1 = fft_blocks.fft_vcc(total_subc,False,[],True)
                self.connect( estimated_CTF, ifft1,gr.null_sink(gr.sizeof_gr_complex*total_subc))
                summ1 = ofdm.vector_sum_vcc(total_subc)
                c2m =gr.complex_to_mag(total_subc)
                self.connect( estimated_CTF,summ1 ,gr.null_sink(gr.sizeof_gr_complex))
                self.connect( estimated_CTF, c2m,gr.null_sink(gr.sizeof_float*total_subc))
                log_to_file( self, ifft1, "data/CIR1.compl" )
                log_to_file( self, summ1, "data/CTFsumm1.compl" )
                log_to_file( self, estimated_CTF, "data/CTF1.compl" )
                log_to_file( self, c2m, "data/CTFmag1.float" )
        
            ## MSE enhancer
            ctf_mse_enhancer = ofdm.CTF_MSE_enhancer( total_subc, cp_length + cp_length)
            self.connect( estimated_CTF, ctf_mse_enhancer )
#      log_to_file( self, ctf_mse_enhancer, "data/ctf_mse_enhancer_original.compl")
      #ifft3 = fft_blocks.fft_vcc(total_subc,False,[],True)
      #null_noise = ofdm.noise_nulling(total_subc, cp_length + cp_length)
      #ctf_mse_enhancer = fft_blocks.fft_vcc(total_subc,True,[],True)
      #ctf_mse_enhancer = ofdm.vector_mask( fft_length, virtual_subc/2,
                                          # total_subc, [] )
      #self.connect( estimated_CTF, ifft3,null_noise,ctf_mse_enhancer )
        
            estimated_CTF = ctf_mse_enhancer 
            print "Disabled CTF MSE enhancer"

        if options.logcir:
             ifft2 = fft_blocks.fft_vcc(total_subc,False,[],True)
             self.connect( estimated_CTF, ifft2,gr.null_sink(gr.sizeof_gr_complex*total_subc))
             summ2 = ofdm.vector_sum_vcc(total_subc)
             c2m2 =gr.complex_to_mag(total_subc)
             self.connect( estimated_CTF,summ2 ,gr.null_sink(gr.sizeof_gr_complex))
             self.connect( estimated_CTF, c2m2,gr.null_sink(gr.sizeof_float*total_subc))
             log_to_file( self, ifft2, "data/CIR2.compl" )
             log_to_file( self, summ2, "data/CTFsumm2.compl" )
             log_to_file( self, estimated_CTF, "data/CTF2.compl" )
             log_to_file( self, c2m2, "data/CTFmag2.float" )
         
    ## Postprocess the CTF estimate
    ## CTF -> inverse CTF (for equalizer)
    ## CTF -> norm |.|^2 (for CTF display)
        ctf_postprocess = ofdm.postprocess_CTF_estimate( total_subc )
        self.connect( estimated_CTF, ctf_postprocess )
        inv_estimated_CTF = ( ctf_postprocess, 0 )
        disp_CTF = ( ctf_postprocess, 1 )
    
#     if options.disable_equalization or options.ideal:
#       terminate_stream(self, inv_estimated_CTF)
#       inv_estimated_CTF_vec = blocks.vector_source_c([1.0/fft_length*math.sqrt(total_subc)]*total_subc,True,total_subc)
#       inv_estimated_CTF_str = blocks.vector_to_stream(gr.sizeof_gr_complex, total_subc)
#       self.inv_estimated_CTF_mul = ofdm.multiply_const_ccf( 1.0/config.rms_amplitude )
#       #inv_estimated_CTF_mul.set_k(1.0/config.rms_amplitude)
#       inv_estimated_CTF = blocks.stream_to_vector(gr.sizeof_gr_complex, total_subc)
#       self.connect( inv_estimated_CTF_vec, inv_estimated_CTF_str, self.inv_estimated_CTF_mul, inv_estimated_CTF)
#       print "Disabled equalization stage"
    '''
    ## LMS Phase tracking
    ## Track residual frequency offset and sampling clock frequency offset

    nondata_blocks = []
    for i in range(config.frame_length):
      if i in config.training_data.pilotsym_pos:
        nondata_blocks.append(i)
        
    print"\t\t\t\t\tnondata_blocks=",nondata_blocks
    pilot_subc = block_header.pilot_tones
    pilot_subcarriers = block_header.pilot_subc_sym
    print "PILOT SUBCARRIERS: ", pilot_subcarriers
        
    phase_tracking = ofdm.lms_phase_tracking_03( total_subc, pilot_subc,
                                               nondata_blocks, pilot_subcarriers,0 )
    self.connect( ofdm_blocks, ( phase_tracking, 0 ) )
    self.connect( inv_estimated_CTF, ( phase_tracking, 1 ) )
    self.connect( frame_start, ( phase_tracking, 2 ) ) ##
    
    if options.scatter_plot_before_phase_tracking:
      self.before_phase_tracking = equalizer
      
    
    if options.disable_phase_tracking or options.ideal:
      terminate_stream(self, phase_tracking)
      print "Disabled phase tracking stage"
    else:
      ofdm_blocks = phase_tracking
    '''
    ## Channel Equalizer
    if options.disable_equalization or options.ideal or options.ideal2:
        print "Disabled equalization stage"
        if options.ideal is False and options.ideal2 is False:
            terminate_stream(self, inv_estimated_CTF)
    else:
        equalizer = ofdm.channel_equalizer( total_subc )
        self.connect( ofdm_blocks,       ( equalizer, 0 ) )
        self.connect( inv_estimated_CTF, ( equalizer, 1 ) )
        self.connect( frame_start,       ( equalizer, 2 ) )
        ofdm_blocks = equalizer
    #log_to_file(self, equalizer,"data/equalizer_siso.compl")
    
    
    #log_to_file(self, ofdm_blocks, "data/equalizer.compl")

    ## LMS Phase tracking
    ## Track residual frequency offset and sampling clock frequency offset
    if options.ideal is False and options.ideal2 is False:
        nondata_blocks = []
        for i in range(config.frame_length):
          if i in config.training_data.pilotsym_pos:
            nondata_blocks.append(i)
            
        print"\t\t\t\t\tnondata_blocks=",nondata_blocks
        pilot_subc = block_header.pilot_tones
        pilot_subcarriers = block_header.pilot_subc_sym
        print "PILOT SUBCARRIERS: ", pilot_subcarriers
         
        phase_tracking2 = ofdm.lms_phase_tracking_dc_null( total_subc, pilot_subc,
                                                   nondata_blocks, pilot_subcarriers, dc_null  )
        self.connect( ofdm_blocks, ( phase_tracking2, 0 ) )
        self.connect( frame_start, ( phase_tracking2, 1 ) ) ##
        
    if options.disable_phase_tracking or options.ideal or options.ideal2:
        if options.ideal is False and options.ideal2 is False:
            terminate_stream(self, phase_tracking2)
        print "Disabled phase tracking stage"
    else:
        ofdm_blocks = phase_tracking2
    
    if options.scatter_plot_before_phase_tracking:
      self.before_phase_tracking = equalizer


    ## Output connections

    self.connect( ofdm_blocks, out_ofdm_blocks )
    self.connect( frame_start, out_frame_start )
    if options.ideal is False and options.ideal2 is False:
        self.connect( disp_CTF, out_disp_ctf )
    else:
        self.connect( blocks.vector_source_f([1.0]*total_subc),blocks.stream_to_vector(gr.sizeof_float,total_subc), out_disp_ctf )

    if log:
      log_to_file( self, sc_metric, "data/sc_metric.float" )
      log_to_file( self, gi_metric, "data/gi_metric.float" )
      log_to_file( self, morelli_foe, "data/morelli_foe.float" )
      log_to_file( self, lms_fir, "data/lms_fir.float" )
      log_to_file( self, sampler_preamble, "data/preamble.compl" )
      log_to_file( self, sync, "data/sync.compl" )
      log_to_file( self, frequency_shift, "data/frequency_shift.compl" )
      log_to_file( self, fft, "data/fft.compl")
      log_to_file( self, fft, "data/fft.float", mag=True )
      
      if vars().has_key( 'subcarrier_mask' ):
        log_to_file( self, subcarrier_mask, "data/subcarrier_mask.compl" )
      
      log_to_file( self, ofdm_blocks, "data/ofdm_blocks_out.compl" )
      log_to_file( self, frame_start, "data/frame_start.float", 
                   char_to_float=True )
      
      log_to_file( self, sampled_chest_preamble, 
                   "data/sampled_chest_preamble.compl" )
      log_to_file( self, LS_channel_estimator, 
                   "data/ls_channel_estimator.compl" )
      log_to_file( self, LS_channel_estimator, 
                   "data/ls_channel_estimator.float", mag=True )
      
      if "ctf_mse_enhancer" in locals(): 
        log_to_file( self, ctf_mse_enhancer, "data/ctf_mse_enhancer.compl" )
        log_to_file( self, ctf_mse_enhancer, "data/ctf_mse_enhancer.float", 
                     mag=True )
      
      log_to_file( self, (ctf_postprocess,0), "data/inc_estimated_ctf.compl" )
      log_to_file( self, (ctf_postprocess,1), "data/disp_ctf.float" )
      
      log_to_file( self, equalizer, "data/equalizer.compl" )
      log_to_file( self, equalizer, "data/equalizer.float", mag=True )
      
      log_to_file( self, phase_tracking, "data/phase_tracking.compl" )
Beispiel #17
0
  def __init__( self, options, log = False ):
    
    ## Read configuration
    config = station_configuration()
    
    fft_length    = config.fft_length
    #cp_length     = config.cp_length
    block_header  = config.training_data
    data_subc     = config.data_subcarriers
    virtual_subc  = config.virtual_subcarriers
    total_subc    = config.subcarriers
    block_length  = config.block_length
    frame_length  = config.frame_length
    
    L             = block_header.mm_periodic_parts
    
        
    cp_length     = config.cp_length


    
    print "data_subc: ", config.data_subcarriers
    print "total_subc: ", config.subcarriers
    print "frame_lengthframe_length: ", frame_length
    
    
    ## Set Input/Output signature
    gr.hier_block2.__init__( self, 
        "fbmc_inner_receiver",
        gr.io_signature(
            1, 1,
            gr.sizeof_gr_complex ),
        gr.io_signaturev(
            4, 4,
            [gr.sizeof_float * total_subc,    # Normalized |CTF|^2 
            gr.sizeof_char,                       # Frame start
            gr.sizeof_gr_complex * total_subc, # OFDM blocks, SNR est
            gr.sizeof_float] ) )      # CFO
    
    
    ## Input and output ports
    self.input = rx_input = self
    
    out_ofdm_blocks = ( self, 2 )
    out_frame_start = ( self, 1 )
    out_disp_ctf    = ( self, 0 )
    out_disp_cfo    = ( self, 3 )
    #out_snr_pream    = ( self, 3 )
    
    
    
    
    ## pre-FFT processing
    
    '''
    ## Compute autocorrelations for S&C preamble
    ## and cyclic prefix
    
    self._sc_metric = sc_metric = autocorrelator( fft_length/2, fft_length/2 )
    self._gi_metric = gi_metric = autocorrelator( fft_length, cp_length )
    
    self.connect( rx_input, sc_metric )
    self.connect( rx_input, gi_metric )
    terminate_stream(self, gi_metric)
    
    ## Sync. Output contains OFDM blocks
    sync = ofdm.time_sync( fft_length/2, 1)
    self.connect( rx_input, ( sync, 0 ) )
    self.connect( sc_metric, ( sync, 1 ) )
    self.connect( sc_metric, ( sync, 2 ) )
    
    ofdm_blocks = ( sync, 0 )
    frame_start = ( sync, 1 )
    log_to_file( self, ( sync, 1 ), "data/fbmc_peak_detector.char" )
    '''
    if options.ideal is False and options.ideal2 is False:
        #Testing old/new metric
        self.tm = schmidl.recursive_timing_metric(2*fft_length)
        self.connect( self.input, self.tm)
        #log_to_file( self, self.tm, "data/fbmc_rec_sc_metric_ofdm.float" )
        
        timingmetric_shift = 0 #-2 #int(-cp_length * 0.8)
        tmfilter = filter.fft_filter_fff(1, [2./fft_length]*(fft_length/2))# ofdm.lms_fir_ff( fft_length, 1e-3 ) #; filter.fir_filter_fff(1, [1./fft_length]*fft_length)
        self.connect( self.tm, tmfilter )
        self.tm = tmfilter
        #log_to_file( self, self.tm, "data/fbmc_rec_sc_metric_ofdm2.float" )
        
        self._pd_thres = 0.6
        self._pd_lookahead = fft_length # empirically chosen
        peak_detector = ofdm.peak_detector_02_fb(self._pd_lookahead, self._pd_thres)
        self.connect(self.tm, peak_detector)
        #log_to_file( self, peak_detector, "data/fbmc_rec_peak_detector.char" )
        
        
        #frame_start = [0]*frame_length
        #frame_start[0] = 1
        #frame_start = blocks.vector_source_b(frame_start,True)
        
        #OLD
        #delayed_timesync = blocks.delay(gr.sizeof_char,
         #                           (frame_length-10)*fft_length/2 - fft_length/4 -1 + timingmetric_shift)
        delayed_timesync = blocks.delay(gr.sizeof_char,
                                    (frame_length-10)*fft_length/2 - fft_length/4  + int(2.5*fft_length)  + timingmetric_shift-1)
        #delayed_timesync = blocks.delay(gr.sizeof_char,
                                    #(frame_length-10)*fft_length/2 - fft_length/4 + int(3.5*fft_length)  + timingmetric_shift-1)
        self.connect( peak_detector, delayed_timesync )
        
        self.block_sampler = ofdm.vector_sampler(gr.sizeof_gr_complex,fft_length/2*frame_length)
        
        self.connect(self.input,self.block_sampler)
        self.connect(delayed_timesync,(self.block_sampler,1))
        #log_to_file( self, self.block_sampler, "data/fbmc_block_sampler.compl" )
        
        vt2s = blocks.vector_to_stream(gr.sizeof_gr_complex*fft_length,
                                                frame_length/2)
        self.connect(self.block_sampler,vt2s)
        #terminate_stream(self,ofdm_blocks)
        
        ofdm_blocks = vt2s
        
        '''
        # TODO: dynamic solution
        vt2s = blocks.vector_to_stream(gr.sizeof_gr_complex*block_length/2,
                                                frame_length)
        self.connect(self.block_sampler,vt2s)
        terminate_stream(self,( sync, 0 ))
        ofdm_blocks = vt2s
        '''
        
        
        
        
        
        ##stv_help = blocks.stream_to_vector(gr.sizeof_gr_complex*config.fft_length/2, 1)
        #stv_help = blocks.vector_to_stream(gr.sizeof_gr_complex*config.fft_length/2, 2)
       ##self.connect(ofdm_blocks, stv_help)
        ##ofdm_blocks = stv_help
        #ofdm_blocks = ( sync, 0 )
        #frame_start = ( sync, 1 )
        #log_to_file(self, frame_start, "data/frame_start.compl")
        
        #log_to_file( self, sc_metric, "data/sc_metric.float" )
        #log_to_file( self, gi_metric, "data/gi_metric.float" )
        #log_to_file( self, (sync,1), "data/sync.float" )
        
    #    log_to_file(self,ofdm_blocks,"data/ofdm_blocks_original.compl")
        frame_start = [0]*int(frame_length/2)
        frame_start[0] = 1
        frame_start = blocks.vector_source_b(frame_start,True)          
        
        #frame_start2 = [0]*int(frame_length/2)
        #frame_start2[0] = 1
        #frame_start2 = blocks.vector_source_b(frame_start2,True)
    
    if options.disable_time_sync or options.ideal or options.ideal2:
      if options.ideal is False and options.ideal2 is False:
        terminate_stream(self, ofdm_blocks)
        terminate_stream(self, frame_start)
      
      serial_to_parallel = blocks.stream_to_vector(gr.sizeof_gr_complex,fft_length)
      #discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
      #serial_to_parallel = blocks.stream_to_vector(gr.sizeof_gr_complex,block_length)
      #discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
      #self.connect( rx_input,serial_to_parallel)
      
      #self.connect( rx_input, blocks.delay(gr.sizeof_gr_complex,0),serial_to_parallel)
      initial_skip = blocks.skiphead(gr.sizeof_gr_complex,2*fft_length)
      self.connect( rx_input, initial_skip)
      if options.ideal is False and options.ideal2 is False:          
          self.connect(  initial_skip, serial_to_parallel)
          ofdm_blocks = serial_to_parallel
      else:
          ofdm_blocks = initial_skip
      #self.connect( rx_input, serial_to_parallel, discard_cp )
      
      frame_start = [0]*int(frame_length/2)
      frame_start[0] = 1
      frame_start = blocks.vector_source_b(frame_start,True)
      
      #frame_start2 = [0]*int(frame_length/2)
      #frame_start2[0] = 1
      #frame_start2 = blocks.vector_source_b(frame_start2,True)
      
      print "Disabled time synchronization stage"
    
    print"\t\t\t\t\tframe_length = ",frame_length
    
    if options.ideal is False and options.ideal2 is False:
        ## Extract preamble, feed to Morelli & Mengali frequency offset estimator
        assert( block_header.mm_preamble_pos == 0 )
        morelli_foe = ofdm.mm_frequency_estimator( fft_length, 2, 1, config.fbmc )
        sampler_preamble = ofdm.vector_sampler( gr.sizeof_gr_complex * fft_length,
                                                1 )
        self.connect( ofdm_blocks, ( sampler_preamble, 0 ) )
        self.connect( frame_start, blocks.delay( gr.sizeof_char, 1 ), ( sampler_preamble, 1 ) )
        self.connect( sampler_preamble, morelli_foe )
        freq_offset = morelli_foe
        print "FRAME_LENGTH: ", frame_length
        #log_to_file( self, sampler_preamble, "data/sampler_preamble.compl" )
        #log_to_file( self, rx_input, "data/rx_input.compl" )
        #log_to_file( self, ofdm_blocks, "data/rx_input.compl" )

        
        #Extracting preamble for SNR estimation
        #fft_snr_est = fft_blocks.fft_vcc( fft_length, True, [], True )
        #self.connect( sampler_preamble, blocks.stream_to_vector(gr.sizeof_gr_complex*fft_length/2, 2),  fft_snr_est )
        
        
        ## Remove virtual subcarriers
        #if fft_length > data_subc:
          #subcarrier_mask_snr_est = ofdm.vector_mask( fft_length, virtual_subc/2,
                        #                       total_subc, [] )
          #self.connect( fft_snr_est, subcarrier_mask_snr_est )
          #fft_snr_est = subcarrier_mask_snr_est
          #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
           ## Least Squares estimator for channel transfer function (CTF)
        
        #self.connect( fft_snr_est, out_snr_pream ) # Connecting to output
        
        ## Adaptive LMS FIR filtering of frequency offset
        lms_fir = ofdm.lms_fir_ff( 20, 1e-3 ) # TODO: verify parameter choice
        self.connect( freq_offset, lms_fir )
        freq_offset = lms_fir
        
        self.connect(freq_offset, blocks.keep_one_in_n(gr.sizeof_float,20) ,out_disp_cfo)
    else:
        self.connect(blocks.vector_source_f ([1]) ,out_disp_cfo)

    
    #log_to_file(self, lms_fir, "data/lms_fir.float")
    
    if options.disable_freq_sync or options.ideal or options.ideal2:
      if options.ideal is False and options.ideal2 is False:  
          terminate_stream(self, freq_offset)
          freq_offset = blocks.vector_source_f([0.0],True)
      print "Disabled frequency synchronization stage"
    
    if options.ideal is False and options.ideal2 is False:
        ## Correct frequency shift, feed-forward structure
        frequency_shift = ofdm.frequency_shift_vcc( fft_length, -1.0/fft_length,
                                                    0)
        
        #freq_shift = blocks.multiply_cc()
        #norm_freq = -0.1 / config.fft_length
        #freq_off = self.freq_off_src = analog.sig_source_c(1.0, analog.GR_SIN_WAVE, norm_freq, 1.0, 0.0 )
        
        self.connect( ofdm_blocks, ( frequency_shift, 0 ) )
        self.connect( freq_offset, ( frequency_shift, 1 ) )
        self.connect( frame_start,blocks.delay( gr.sizeof_char, 0), ( frequency_shift, 2 ) )
        
        

        
        #self.connect(frequency_shift,s2help)
        #ofdm_blocks = s2help
        ofdm_blocks = frequency_shift
    #terminate_stream(self, frequency_shift)
    
    
    
    #inner_pb_filt = self._inner_pilot_block_filter = fbmc_inner_pilot_block_filter()
    #self.connect(ofdm_blocks,inner_pb_filt)
    #self.connect(frame_start,(inner_pb_filt,1))
    #self.connect((inner_pb_filt,1),blocks.null_sink(gr.sizeof_char))
    
    #ofdm_blocks = (inner_pb_filt,0)
    
    
    overlap_ser_to_par = ofdm.fbmc_overlapping_serial_to_parallel_cvc(fft_length)
    self.separate_vcvc = ofdm.fbmc_separate_vcvc(fft_length, 2)
    self.polyphase_network_vcvc_1 = ofdm.fbmc_polyphase_network_vcvc(fft_length, 4, 4*fft_length-1, True)
    self.polyphase_network_vcvc_2 = ofdm.fbmc_polyphase_network_vcvc(fft_length, 4, 4*fft_length-1, True)
    self.junction_vcvc = ofdm.fbmc_junction_vcvc(fft_length, 2)
    self.fft_fbmc = fft_blocks.fft_vcc(fft_length, True, [], True)
    
    print "config.training_data.fbmc_no_preambles: ", config.training_data.fbmc_no_preambles
    #center_preamble = [1, -1j, -1, 1j]
    
    #self.preamble = preamble = [0]*total_subc + center_preamble*((int)(total_subc/len(center_preamble)))+[0]*total_subc
    
    self.preamble = preamble = config.training_data.fbmc_pilotsym_fd_list
    #inv_preamble = 1. / numpy.array(self.preamble)
    #print "self.preamble: ", len(self.preamble
    #print "inv_preamble: ", list(inv_preamble)
    
    #print "self.preamble", self.preamble
    #print "self.preamble2", self.preamble2
    
    
    self.multiply_const= ofdm.multiply_const_vcc(([1.0/(math.sqrt(fft_length*0.6863))]*total_subc))    
    self.beta_multiplier_vcvc = ofdm.fbmc_beta_multiplier_vcvc(total_subc, 4, 4*fft_length-1, 0)
    #self.skiphead = blocks.skiphead(gr.sizeof_gr_complex*total_subc, 2*4-1-1)
    self.skiphead = blocks.skiphead(gr.sizeof_gr_complex*total_subc,2)
    self.skiphead_1 = blocks.skiphead(gr.sizeof_gr_complex*total_subc, 0)
    #self.remove_preamble_vcvc = ofdm.fbmc_remove_preamble_vcvc(total_subc, config.frame_data_part/2, config.training_data.fbmc_no_preambles*total_subc/2)
    #self.subchannel_processing_vcvc = ofdm.fbmc_subchannel_processing_vcvc(total_subc, config.frame_data_part, 1, 2, 1, 0)
    self.oqam_postprocessing_vcvc = ofdm.fbmc_oqam_postprocessing_vcvc(total_subc, 0, 0)
    
    #log_to_file( self, ofdm_blocks, "data/PRE_FBMC.compl" )
    #log_to_file( self, self.fft_fbmc, "data/FFT_FBMC.compl" )

    if options.ideal is False and options.ideal2 is False:
        self.subchannel_processing_vcvc = ofdm.fbmc_subchannel_processing_vcvc(total_subc, config.frame_data_part, 3, 2, 1, 0)
        help2 = blocks.keep_one_in_n(gr.sizeof_gr_complex*total_subc,frame_length)
        self.connect ((self.subchannel_processing_vcvc,1),help2)
        #log_to_file( self, self.subchannel_processing_vcvc, "data/fbmc_subc.compl" )

    
    #terminate_stream(self, help2)
    
    if options.ideal is False and options.ideal2 is False:
        self.connect(ofdm_blocks, blocks.vector_to_stream(gr.sizeof_gr_complex, fft_length),overlap_ser_to_par)
    else:
        self.connect(ofdm_blocks,overlap_ser_to_par)
        
    self.connect(overlap_ser_to_par, self.separate_vcvc)
    self.connect((self.separate_vcvc, 1), (self.polyphase_network_vcvc_2, 0))
    self.connect((self.separate_vcvc, 0), (self.polyphase_network_vcvc_1, 0))
    self.connect((self.polyphase_network_vcvc_1, 0), (self.junction_vcvc, 0))
    self.connect((self.polyphase_network_vcvc_2, 0), (self.junction_vcvc, 1))
    self.connect(self.junction_vcvc, self.fft_fbmc)
    
    ofdm_blocks = self.fft_fbmc
    print "config.dc_null: ", config.dc_null
    if fft_length > data_subc:
      subcarrier_mask_fbmc = ofdm.vector_mask_dc_null( fft_length, virtual_subc/2,
                                           total_subc, config.dc_null, [] )
      self.connect( ofdm_blocks, subcarrier_mask_fbmc )
      ofdm_blocks = subcarrier_mask_fbmc
      #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
       ## Least Squares estimator for channel transfer function (CTF)
      #log_to_file( self, subcarrier_mask, "data/OFDM_Blocks.compl" )
      
    
    self.connect(ofdm_blocks, self.beta_multiplier_vcvc)
    
    ofdm_blocks = self.beta_multiplier_vcvc
    #self.connect(ofdm_blocks,self.multiply_const)
    #self.connect(self.multiply_const, (self.skiphead, 0))
    
    self.connect(ofdm_blocks, (self.skiphead, 0))
    #log_to_file( self, self.skiphead, "data/fbmc_skiphead_4.compl" )
    
    
    #self.connect(ofdm_blocks, self.multiply_const)
    #self.connect(self.multiply_const, self.beta_multiplier_vcvc)
    #self.connect((self.beta_multiplier_vcvc, 0), (self.skiphead, 0))
    if options.ideal or options.ideal2:
        self.connect((self.skiphead, 0),(self.skiphead_1, 0))
    else:
        self.connect((self.skiphead, 0), (self.subchannel_processing_vcvc, 0))
        self.connect((self.subchannel_processing_vcvc, 0), (self.skiphead_1, 0))
        
    #log_to_file( self, self.skiphead, "data/fbmc_subc.compl" )    
    #self.connect((self.skiphead_1, 0),(self.remove_preamble_vcvc, 0))
    #self.connect((self.remove_preamble_vcvc, 0),  (self.oqam_postprocessing_vcvc, 0))
    
    #ofdm_blocks = self.oqam_postprocessing_vcvc
    #log_to_file( self, self.subchannel_processing_vcvc, "data/subc_0.compl" )
    #log_to_file( self, (self.subchannel_processing_vcvc,1), "data/subc_1.compl" )
    
    
    
    self.connect((self.skiphead_1, 0),(self.oqam_postprocessing_vcvc, 0))
    #self.connect((self.oqam_postprocessing_vcvc, 0), (self.remove_preamble_vcvc, 0) )
    
    ofdm_blocks = (self.oqam_postprocessing_vcvc, 0)#(self.remove_preamble_vcvc, 0)
    #log_to_file( self, (self.oqam_postprocessing_vcvc, 0), "data/fbmc_before_remove.compl" )
    
    #log_to_file( self, self.skiphead, "data/SKIP_HEAD_FBMC.compl" )
    #log_to_file( self, self.beta_multiplier_vcvc, "data/BETA_REC_FBMC.compl" )
    #log_to_file( self, self.oqam_postprocessing_vcvc, "data/REC_OUT_FBMC.compl" )
        
    

    
    
    
    
    
    """ DISABLED OFDM CHANNEL ESTIMATION PREMBLE -> CORRECT LATER to compare FBMC and OFDM channel estimation
    #TAKING THE CHANNEL ESTIMATION PREAMBLE
    chest_pre_trigger = blocks.delay( gr.sizeof_char, 3 )
    sampled_chest_preamble = ofdm.vector_sampler( gr.sizeof_gr_complex * fft_length/2, 2 )
      
    self.connect( frame_start,       chest_pre_trigger )
    self.connect( chest_pre_trigger, ( sampled_chest_preamble, 1 ) )
    self.connect( frequency_shift,       ( sampled_chest_preamble, 0 ) )
    #ofdm_blocks = sampled_chest_preamble
    
        
    ## FFT
    fft = fft_blocks.fft_vcc( fft_length, True, [], True )
    self.connect( sampled_chest_preamble, fft )
    ofdm_blocks_est = fft
    log_to_file( self, sampled_chest_preamble, "data/SAMPLED_EST_PREAMBLE.compl" )
    log_to_file( self, ofdm_blocks_est, "data/FFT.compl" )
    
    
    ## Remove virtual subcarriers
    if fft_length > data_subc:
      subcarrier_mask = ofdm.vector_mask( fft_length, virtual_subc/2,
                                           total_subc, [] )
      self.connect( ofdm_blocks_est, subcarrier_mask )
      ofdm_blocks_est = subcarrier_mask
      #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
       ## Least Squares estimator for channel transfer function (CTF)
      log_to_file( self, subcarrier_mask, "data/OFDM_Blocks.compl" )
    
          
    ## post-FFT processing
      
    
    
    ## extract channel estimation preamble from frame
    ##chest_pre_trigger = blocks.delay( gr.sizeof_char, 
                                  ##1 )
    ##sampled_chest_preamble = \
     ## ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )
    ##self.connect( frame_start,       chest_pre_trigger )
    ##self.connect( chest_pre_trigger, ( sampled_chest_preamble, 1 ) )
    ##self.connect( ofdm_blocks,       ( sampled_chest_preamble, 0 ) )
    

    
    ## Least Squares estimator for channel transfer function (CTF)
    inv_preamble_fd = numpy.array( block_header.pilotsym_fd[ 
        block_header.channel_estimation_pilot[0] ] )
    #print "Channel estimation pilot: ", inv_preamble_fd
    inv_preamble_fd = 1. / inv_preamble_fd
    
    LS_channel_estimator = ofdm.multiply_const_vcc( list( inv_preamble_fd ) )
    self.connect( ofdm_blocks_est, LS_channel_estimator )
    estimated_CTF = LS_channel_estimator
    terminate_stream(self,estimated_CTF)
    """
    if options.ideal is False and options.ideal2 is False:
        if options.logcir:
         log_to_file( self, sampled_chest_preamble, "data/PREAM.compl" )
     
    
        if not options.disable_ctf_enhancer:
      
      
            if options.logcir:
                ifft1 = fft_blocks.fft_vcc(total_subc,False,[],True)
                self.connect( estimated_CTF, ifft1,gr.null_sink(gr.sizeof_gr_complex*total_subc))
                summ1 = ofdm.vector_sum_vcc(total_subc)
                c2m =gr.complex_to_mag(total_subc)
                self.connect( estimated_CTF,summ1 ,gr.null_sink(gr.sizeof_gr_complex))
                self.connect( estimated_CTF, c2m,gr.null_sink(gr.sizeof_float*total_subc))
                log_to_file( self, ifft1, "data/CIR1.compl" )
                log_to_file( self, summ1, "data/CTFsumm1.compl" )
                log_to_file( self, estimated_CTF, "data/CTF1.compl" )
                log_to_file( self, c2m, "data/CTFmag1.float" )
        
            ## MSE enhancer
            ctf_mse_enhancer = ofdm.CTF_MSE_enhancer( total_subc, cp_length + cp_length)
            self.connect( estimated_CTF, ctf_mse_enhancer )
#      log_to_file( self, ctf_mse_enhancer, "data/ctf_mse_enhancer_original.compl")
      #ifft3 = fft_blocks.fft_vcc(total_subc,False,[],True)
      #null_noise = ofdm.noise_nulling(total_subc, cp_length + cp_length)
      #ctf_mse_enhancer = fft_blocks.fft_vcc(total_subc,True,[],True)
      #ctf_mse_enhancer = ofdm.vector_mask( fft_length, virtual_subc/2,
                                          # total_subc, [] )
      #self.connect( estimated_CTF, ifft3,null_noise,ctf_mse_enhancer )
        
            estimated_CTF = ctf_mse_enhancer 
            print "Disabled CTF MSE enhancer"

        if options.logcir:
         ifft2 = fft_blocks.fft_vcc(total_subc,False,[],True)
         self.connect( estimated_CTF, ifft2,gr.null_sink(gr.sizeof_gr_complex*total_subc))
         summ2 = ofdm.vector_sum_vcc(total_subc)
         c2m2 =gr.complex_to_mag(total_subc)
         self.connect( estimated_CTF,summ2 ,gr.null_sink(gr.sizeof_gr_complex))
         self.connect( estimated_CTF, c2m2,gr.null_sink(gr.sizeof_float*total_subc))
         log_to_file( self, ifft2, "data/CIR2.compl" )
         log_to_file( self, summ2, "data/CTFsumm2.compl" )
         log_to_file( self, estimated_CTF, "data/CTF2.compl" )
         log_to_file( self, c2m2, "data/CTFmag2.float" )
         
        ## Postprocess the CTF estimate
        ## CTF -> inverse CTF (for equalizer)
        ## CTF -> norm |.|^2 (for CTF display)
        ctf_postprocess = ofdm.fbmc_postprocess_CTF_estimate( total_subc )
        
        self.connect( help2, ctf_postprocess )
        #estimated_SNR = ( ctf_postprocess, 0 )
        disp_CTF = ( ctf_postprocess, 0 )
        #self.connect(estimated_SNR,out_snr_pream)
        #log_to_file( self, estimated_SNR, "data/fbmc_SNR.float" )
        
        #Disable measured SNR output
        #terminate_stream(self, estimated_SNR)
        #self.connect(blocks.vector_source_f([10.0],True) ,out_snr_pream)
    
#     if options.disable_equalization or options.ideal:
#       terminate_stream(self, inv_estimated_CTF)
#       inv_estimated_CTF_vec = blocks.vector_source_c([1.0/fft_length*math.sqrt(total_subc)]*total_subc,True,total_subc)
#       inv_estimated_CTF_str = blocks.vector_to_stream(gr.sizeof_gr_complex, total_subc)
#       self.inv_estimated_CTF_mul = ofdm.multiply_const_ccf( 1.0/config.rms_amplitude )
#       #inv_estimated_CTF_mul.set_k(1.0/config.rms_amplitude)
#       inv_estimated_CTF = blocks.stream_to_vector(gr.sizeof_gr_complex, total_subc)
#       self.connect( inv_estimated_CTF_vec, inv_estimated_CTF_str, self.inv_estimated_CTF_mul, inv_estimated_CTF)
#       print "Disabled equalization stage"
    '''
    ## LMS Phase tracking
    ## Track residual frequency offset and sampling clock frequency offset

    nondata_blocks = []
    for i in range(config.frame_length):
      if i in config.training_data.pilotsym_pos:
        nondata_blocks.append(i)
        
    print"\t\t\t\t\tnondata_blocks=",nondata_blocks
    pilot_subc = block_header.pilot_tones
    pilot_subcarriers = block_header.pilot_subc_sym
    print "PILOT SUBCARRIERS: ", pilot_subcarriers
        
    phase_tracking = ofdm.lms_phase_tracking_03( total_subc, pilot_subc,
                                               nondata_blocks, pilot_subcarriers,0 )
    self.connect( ofdm_blocks, ( phase_tracking, 0 ) )
    self.connect( inv_estimated_CTF, ( phase_tracking, 1 ) )
    self.connect( frame_start, ( phase_tracking, 2 ) ) ##
    
    if options.scatter_plot_before_phase_tracking:
      self.before_phase_tracking = equalizer
      
    
    if options.disable_phase_tracking or options.ideal:
      terminate_stream(self, phase_tracking)
      print "Disabled phase tracking stage"
    else:
      ofdm_blocks = phase_tracking
    '''
    ## Channel Equalizer
    ##equalizer = ofdm.channel_equalizer( total_subc )
    ##self.connect( ofdm_blocks,       ( equalizer, 0 ) )
    ##self.connect( inv_estimated_CTF, ( equalizer, 1 ) )
    ##self.connect( frame_start,       ( equalizer, 2 ) )
    ##ofdm_blocks = equalizer
    #log_to_file(self, equalizer,"data/equalizer_siso.compl")
    
    
    #log_to_file(self, ofdm_blocks, "data/equalizer.compl")

    ## LMS Phase tracking
    ## Track residual frequency offset and sampling clock frequency offset

    nondata_blocks = []
    for i in range(config.frame_length):
      if i in config.training_data.pilotsym_pos:
        nondata_blocks.append(i)
        
    print"\t\t\t\t\tnondata_blocks=",nondata_blocks
    pilot_subc = block_header.pilot_tones
    pilot_subcarriers = block_header.pilot_subc_sym
    print "PILOT SUBCARRIERS: ", pilot_subcarriers
    
    if options.scatter_plot_before_phase_tracking:
      self.before_phase_tracking = equalizer
        

    ## Output connections

    self.connect( ofdm_blocks, out_ofdm_blocks )
    self.connect( frame_start, out_frame_start )
    if options.ideal is False and options.ideal2 is False:
        self.connect( disp_CTF, out_disp_ctf )
    else:
        self.connect( blocks.vector_source_f([1.0]*total_subc),blocks.stream_to_vector(gr.sizeof_float,total_subc), out_disp_ctf )
    
    

    if log:
      log_to_file( self, sc_metric, "data/sc_metric.float" )
      log_to_file( self, gi_metric, "data/gi_metric.float" )
      log_to_file( self, morelli_foe, "data/morelli_foe.float" )
      log_to_file( self, lms_fir, "data/lms_fir.float" )
      log_to_file( self, sampler_preamble, "data/preamble.compl" )
      log_to_file( self, sync, "data/sync.compl" )
      log_to_file( self, frequency_shift, "data/frequency_shift.compl" )
      log_to_file( self, fft, "data/fft.compl")
      log_to_file( self, fft, "data/fft.float", mag=True )
      
      if vars().has_key( 'subcarrier_mask' ):
        log_to_file( self, subcarrier_mask, "data/subcarrier_mask.compl" )
      
      log_to_file( self, ofdm_blocks, "data/ofdm_blocks_out.compl" )
      log_to_file( self, frame_start, "data/frame_start.float", 
                   char_to_float=True )
      
      log_to_file( self, sampled_chest_preamble, 
                   "data/sampled_chest_preamble.compl" )
      log_to_file( self, LS_channel_estimator, 
                   "data/ls_channel_estimator.compl" )
      log_to_file( self, LS_channel_estimator, 
                   "data/ls_channel_estimator.float", mag=True )
      
      if "ctf_mse_enhancer" in locals(): 
        log_to_file( self, ctf_mse_enhancer, "data/ctf_mse_enhancer.compl" )
        log_to_file( self, ctf_mse_enhancer, "data/ctf_mse_enhancer.float", 
                     mag=True )
      
      log_to_file( self, (ctf_postprocess,0), "data/inc_estimated_ctf.compl" )
      log_to_file( self, (ctf_postprocess,1), "data/disp_ctf.float" )
      
      log_to_file( self, equalizer, "data/equalizer.compl" )
      log_to_file( self, equalizer, "data/equalizer.float", mag=True )
      
      log_to_file( self, phase_tracking, "data/phase_tracking.compl" )