Example #1
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
    
    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 )
Example #2
0
    def __init__(self, options, noutputs=2):
        """
    @param options: parsed raw.ofdm_params
    """
        self.params = ofdm_params(options)
        params = self.params

        if noutputs == 2:
            output_signature = gr.io_signature2(
                2, 2, gr.sizeof_gr_complex * params.data_tones, gr.sizeof_char)
        elif noutputs == 3:
            output_signature = gr.io_signature3(
                3, 3, gr.sizeof_gr_complex * params.data_tones, gr.sizeof_char,
                gr.sizeof_float)
        elif noutputs == 4:
            output_signature = gr.io_signature4(
                4, 4, gr.sizeof_gr_complex * params.data_tones, gr.sizeof_char,
                gr.sizeof_float, gr.sizeof_float)
        else:
            # error
            raise Exception("unsupported number of outputs")

        gr.hier_block2.__init__(self, "ofdm_demod",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                output_signature)

        self.ofdm_recv = ofdm_receiver(params, options.log)

        # FIXME: magic parameters
        phgain = 0.4
        frgain = phgain * phgain / 4.0
        eqgain = 0.05
        self.ofdm_demod = raw.ofdm_demapper(params.carriers, phgain, frgain,
                                            eqgain)

        # the studios can't handle the whole ofdm in one thread
        #ofdm_recv = raw.wrap_sts(self.ofdm_recv)
        ofdm_recv = self.ofdm_recv

        self.connect(self, ofdm_recv)
        self.connect((ofdm_recv, 0), (self.ofdm_demod, 0))
        self.connect((ofdm_recv, 1), (self.ofdm_demod, 1))

        self.connect(self.ofdm_demod, (self, 0))
        self.connect((ofdm_recv, 1), (self, 1))

        if noutputs > 2:
            # average noise power per (pilot) subcarrier
            self.connect((self.ofdm_demod, 1), (self, 2))

        if noutputs > 3:
            # average signal power per subcarrier
            self.connect(
                (ofdm_recv, 0),
                gr.vector_to_stream(gr.sizeof_float, params.occupied_tones),
                gr.integrate_ff(params.occupied_tones),
                gr.multiply_ff(1.0 / params.occupied_tones), (self, 3))

        if options.log:
            self.connect(
                (self.ofdm_demod, 2),
                gr.file_sink(gr.sizeof_gr_complex * params.occupied_tones,
                             'rx-eq.dat'))
            self.connect((self.ofdm_demod, 1),
                         gr.file_sink(gr.sizeof_float, 'rx-noise.dat'))
            self.connect((self.ofdm_demod, 0),
                         gr.file_sink(gr.sizeof_gr_complex * params.data_tones,
                                      'rx-demap.dat'))
    def __init__(self, fft_length, cp_length, occupied_tones, snr, ks, carrier_map_bin, nc_filter, logging=False):
        gr.hier_block2.__init__(self, "ofdm_receiver",
                        gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                        gr.io_signature4(4, 4, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char, gr.sizeof_char, gr.sizeof_float)) # Output signature

        self._fft_length = fft_length
        self._occupied_tones = occupied_tones
        self._cp_length = cp_length
        self._nc_filter = nc_filter
        self._carrier_map_bin = carrier_map_bin

        win = [1 for i in range(self._fft_length)]

        self.initialize(ks, self._carrier_map_bin)

        SYNC = "pn"
        if SYNC == "ml":
            nco_sensitivity = -1.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_ml(fft_length, cp_length, snr, self._ks0time, logging)
        elif SYNC == "pn":
            nco_sensitivity = -2.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pn.ofdm_sync_pn(fft_length, cp_length, logging)
        elif SYNC == "pnac":
            nco_sensitivity = -2.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pnac(fft_length, cp_length, self._ks0time, logging)
        elif SYNC == "fixed":                                             # for testing only; do not user over the air
            self.chan_filt = gr.multiply_const_cc(1.0)                    # remove filter and filter delay for this
            nsymbols = 18                                                 # enter the number of symbols per packet
            freq_offset = 0.0                                             # if you use a frequency offset, enter it here
            nco_sensitivity = -2.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_fixed(fft_length, cp_length, nsymbols, freq_offset, logging)

        self.reset_filter()


        # TODO: why? Create a delay line, linklab
        self.delay = gr.delay(gr.sizeof_gr_complex, fft_length)

        self.nco = gr.frequency_modulator_fc(nco_sensitivity)         # generate a signal proportional to frequency error of sync block
        self.sigmix = gr.multiply_cc()
        self.sampler = flex.ofdm_sampler(fft_length, fft_length+cp_length)
        self.fft_demod = gr.fft_vcc(fft_length, True, win, True)
        self.ofdm_frame_acq = flex.ofdm_frame_acquisition(self._occupied_tones, self._fft_length,
                                                                                                        self._cp_length, self._ks[0], 1)

        if self._nc_filter:
            print '\nMulti-band Filter Turned ON!'
            self.ncofdm_filt = ncofdm_filt(self._fft_length, self._occupied_tones, self._carrier_map_bin)
            self.connect(self, self.chan_filt, self.ncofdm_filt)
            self.connect(self.ncofdm_filt, self.ofdm_sync)             # into the synchronization alg.
            self.connect((self.ofdm_sync,0), self.nco, (self.sigmix,1))   # use sync freq. offset output to derotate input signal
            self.connect(self.ncofdm_filt, self.delay, (self.sigmix,0))                 # signal to be derotated
        else :
            print '\nMulti-band Filter Turned OFF!'
            self.connect(self, self.chan_filt)
            self.connect(self.chan_filt, self.ofdm_sync)             # into the synchronization alg.
            self.connect((self.ofdm_sync,0), self.nco, (self.sigmix,1))   # use sync freq. offset output to derotate input signal
            self.connect(self.chan_filt, self.delay, (self.sigmix,0))                 # signal to be derotated

        self.connect(self.sigmix, (self.sampler,0))                   # sample off timing signal detected in sync alg
        self.connect((self.ofdm_sync,1), (self.sampler,1))            # timing signal to sample at

        self.connect((self.sampler,0), self.fft_demod)                # send derotated sampled signal to FFT
        self.connect(self.fft_demod, (self.ofdm_frame_acq,0))         # find frame start and equalize signal
        # TODO: do we need a char delay for the timing signal?
        self.connect((self.sampler,1), (self.ofdm_frame_acq,1))       # send timing signal to signal frame start

        # TODO: reconnect properly
        self.connect((self.ofdm_frame_acq,0), (self,0))               # finished with fine/coarse freq correction,
        self.connect((self.ofdm_sync,1), gr.delay(gr.sizeof_char,1), (self,1))

        self.connect((self.ofdm_frame_acq,1), (self,2))               # frame and symbol timing, and equalization
        self.connect((self.ofdm_frame_acq,2), (self,3))               # snr estimates

        if logging:
            self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "flex_ofdm_recv-chan_filt_c.dat"))
            self.connect(self.ncofdm_filt, gr.file_sink(gr.sizeof_gr_complex, "flex_ofdm_recv-ncofdm_filt_c.dat"))
            self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "flex_ofdm_recv-nco_c.dat"))
            self.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "flex_ofdm_recv-fft_out_c.dat"))
            self.connect(self.ofdm_frame_acq, gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "flex_ofdm_recv-frame_acq_data_c.dat"))
            self.connect((self.ofdm_frame_acq,3), gr.keep_one_in_n(gr.sizeof_float*occupied_tones, 32), gr.file_sink(gr.sizeof_float*occupied_tones, "flex_ofdm_recv-frame_acq_gain_f.dat"))
            self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, "flex_ofdm_recv-frame_acq_signal_b.dat"))
            self.connect((self.ofdm_frame_acq,2), gr.file_sink(gr.sizeof_float, "flex_ofdm_recv-frame_acq_snr_f.dat"))
            self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "flex_ofdm_recv-sampler_data_c.dat"))
            self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "flex_ofdm_recv-sampler_data_c.dat"))
            self.connect((self.sampler, 1), gr.file_sink(1*fft_length, "flex_ofdm_recv-sampler_signal_b.dat"))
            self.connect((self.ofdm_sync, 1), gr.file_sink(1, "flex_ofdm_recv-sync_b.dat"))
            self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "flex_ofdm_recv-sigmix_c.dat"))
        else:
            self.connect((self.ofdm_frame_acq,3), gr.null_sink(gr.sizeof_float*self._occupied_tones))
Example #4
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

        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)
Example #5
0
  def __init__(self, options, noutputs = 2):
    """
    @param options: parsed raw.ofdm_params
    """
    self.params = ofdm_params(options)
    params = self.params

    if noutputs == 2:
      output_signature = gr.io_signature2(2, 2,
        gr.sizeof_gr_complex*params.data_tones,
        gr.sizeof_char
      )
    elif noutputs == 3:
      output_signature = gr.io_signature3(3, 3,
        gr.sizeof_gr_complex*params.data_tones,
        gr.sizeof_char,
        gr.sizeof_float
      )
    elif noutputs == 4:
      output_signature = gr.io_signature4(4, 4,
        gr.sizeof_gr_complex*params.data_tones,
        gr.sizeof_char,
        gr.sizeof_float,
        gr.sizeof_float
      )
    else:
      # error
      raise Exception("unsupported number of outputs")

    gr.hier_block2.__init__(self, "ofdm_demod",
      gr.io_signature(1, 1, gr.sizeof_gr_complex),
      output_signature
    )

    self.ofdm_recv = ofdm_receiver(params, options.log)

    # FIXME: magic parameters
    phgain = 0.4
    frgain = phgain*phgain / 4.0
    eqgain = 0.05
    self.ofdm_demod = raw.ofdm_demapper(params.carriers,
                                        phgain, frgain, eqgain)

    # the studios can't handle the whole ofdm in one thread
    #ofdm_recv = raw.wrap_sts(self.ofdm_recv)
    ofdm_recv = self.ofdm_recv

    self.connect(self, ofdm_recv)
    self.connect((ofdm_recv,0), (self.ofdm_demod,0))
    self.connect((ofdm_recv,1), (self.ofdm_demod,1))

    self.connect(self.ofdm_demod, (self,0))
    self.connect((ofdm_recv,1), (self,1))

    if noutputs > 2:
      # average noise power per (pilot) subcarrier
      self.connect((self.ofdm_demod,1), (self,2))

    if noutputs > 3:
      # average signal power per subcarrier
      self.connect((ofdm_recv,0),
        gr.vector_to_stream(gr.sizeof_float, params.occupied_tones),
        gr.integrate_ff(params.occupied_tones),
        gr.multiply_ff(1.0/params.occupied_tones), (self,3))

    if options.log:
      self.connect((self.ofdm_demod, 2),
                   gr.file_sink(gr.sizeof_gr_complex*params.occupied_tones,
                                'rx-eq.dat'))
      self.connect((self.ofdm_demod, 1),
                   gr.file_sink(gr.sizeof_float,
                                'rx-noise.dat'))
      self.connect((self.ofdm_demod, 0),
                   gr.file_sink(gr.sizeof_gr_complex*params.data_tones,
                                'rx-demap.dat'))