Changeset 327

Show
Ignore:
Timestamp:
07/16/09 15:29:35 (15 years ago)
Author:
sriram
Message:

Have added the spectrum sense part to code

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • vtcross/branches/sriram/benchmark_txrxnode1.py

    r325 r327  
    44from gnuradio import gr, gru, modulation_utils 
    55from gnuradio import eng_notation 
     6##########spectrum sense specific imports 
     7from gnuradio import optfir, window 
     8from gnuradio import usrp 
     9from gnuradio.eng_option import eng_option 
     10from usrpm import usrp_dbid 
     11########## 
    612from gnuradio.eng_option import eng_option 
    713from optparse import OptionParser 
     
    3137        self.connect(self.txpath); 
    3238        self.connect(self.rxpath); 
     39 
     40 
     41##################### Spectrum sense specific classes########################################################### 
     42class tune(gr.feval_dd): 
     43    """ 
     44    This class allows C++ code to callback into python. 
     45    """ 
     46    def __init__(self, tb): 
     47        gr.feval_dd.__init__(self) 
     48        self.tb = tb 
     49 
     50    def eval(self, ignore): 
     51        """ 
     52        This method is called from gr.bin_statistics_f when it wants to change 
     53        the center frequency.  This method tunes the front end to the new center 
     54        frequency, and returns the new frequency as its result. 
     55        """ 
     56        try: 
     57            # We use this try block so that if something goes wrong from here  
     58            # down, at least we'll have a prayer of knowing what went wrong. 
     59            # Without this, you get a very mysterious: 
     60            # 
     61            #   terminate called after throwing an instance of 'Swig::DirectorMethodException' 
     62            #   Aborted 
     63            # 
     64            # message on stderr.  Not exactly helpful ;) 
     65 
     66            new_freq = self.tb.set_next_freq() 
     67            return new_freq 
     68 
     69        except Exception, e: 
     70            print "tune: Exception: ", e 
     71 
     72 
     73class parse_msg(object): 
     74    def __init__(self, msg): 
     75        self.center_freq = msg.arg1() 
     76        self.vlen = int(msg.arg2()) 
     77        assert(msg.length() == self.vlen * gr.sizeof_float) 
     78 
     79        # FIXME consider using Numarray or NumPy vector 
     80        t = msg.to_string() 
     81        self.raw_data = t 
     82        self.data = struct.unpack('%df' % (self.vlen,), t) 
     83 
     84 
     85class spec_sense_top_block(gr.top_block): 
     86 
     87    def __init__(self,min_f,max_f): 
     88        gr.top_block.__init__(self) 
     89 
     90        usage = "usage: %prog [options] min_freq max_freq" 
     91        parser = OptionParser(option_class=eng_option, usage=usage) 
     92        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0,0), 
     93                          help="select USRP Rx side A or B (default=A)") 
     94        parser.add_option("-g", "--gain", type="eng_float", default=None, 
     95                          help="set gain in dB (default is midpoint)") 
     96        parser.add_option("", "--tune-delay", type="eng_float", default=1e-3, metavar="SECS", 
     97                          help="time to delay (in seconds) after changing frequency [default=%default]") 
     98        parser.add_option("", "--dwell-delay", type="eng_float", default=10e-3, metavar="SECS", 
     99                          help="time to dwell (in seconds) at a given frequncy [default=%default]") 
     100        parser.add_option("-F", "--fft-size", type="int", default=256, 
     101                          help="specify number of FFT bins [default=%default]") 
     102        parser.add_option("-d", "--decim", type="intx", default=16, 
     103                          help="set decimation to DECIM [default=%default]") 
     104        parser.add_option("", "--real-time", action="store_true", default=False, 
     105                          help="Attempt to enable real-time scheduling") 
     106        parser.add_option("-B", "--fusb-block-size", type="int", default=0, 
     107                          help="specify fast usb block size [default=%default]") 
     108        parser.add_option("-N", "--fusb-nblocks", type="int", default=0, 
     109                          help="specify number of fast usb blocks [default=%default]") 
     110 
     111        (options, args) = parser.parse_args() 
     112        #if len(args) != 2: 
     113         #   parser.print_help() 
     114         #   sys.exit(1) 
     115 
     116        #self.min_freq = eng_notation.str_to_num(args[0]) 
     117        self.min_freq = float(min_f) # setting min and max frequency inside the init rather than taking it from the command line 
     118        #self.max_freq = eng_notation.str_to_num(args[1]) 
     119        self.max_freq = float(max_f) 
     120 
     121        if self.min_freq > self.max_freq: 
     122            self.min_freq, self.max_freq = self.max_freq, self.min_freq   # swap them 
     123 
     124        self.fft_size = options.fft_size 
     125 
     126 
     127        if not options.real_time: 
     128            realtime = False 
     129        else: 
     130            # Attempt to enable realtime scheduling 
     131            r = gr.enable_realtime_scheduling() 
     132            if r == gr.RT_OK: 
     133                realtime = True 
     134            else: 
     135                realtime = False 
     136                print "Note: failed to enable realtime scheduling" 
     137 
     138        # If the user hasn't set the fusb_* parameters on the command line, 
     139        # pick some values that will reduce latency. 
     140 
     141        if 1: 
     142            if options.fusb_block_size == 0 and options.fusb_nblocks == 0: 
     143                if realtime:                        # be more aggressive 
     144                    options.fusb_block_size = gr.prefs().get_long('fusb', 'rt_block_size', 1024) 
     145                    options.fusb_nblocks    = gr.prefs().get_long('fusb', 'rt_nblocks', 16) 
     146                else: 
     147                    options.fusb_block_size = gr.prefs().get_long('fusb', 'block_size', 4096) 
     148                    options.fusb_nblocks    = gr.prefs().get_long('fusb', 'nblocks', 16) 
     149     
     150        #print "fusb_block_size =", options.fusb_block_size 
     151        #print "fusb_nblocks    =", options.fusb_nblocks 
     152 
     153        # build graph 
     154         
     155        self.u = usrp.source_c(fusb_block_size=options.fusb_block_size, 
     156                               fusb_nblocks=options.fusb_nblocks) 
     157 
     158 
     159        adc_rate = self.u.adc_rate()                # 64 MS/s 
     160        usrp_decim = options.decim 
     161        self.u.set_decim_rate(usrp_decim) 
     162        usrp_rate = adc_rate / usrp_decim 
     163 
     164        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) 
     165        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) 
     166        print "Using RX d'board %s" % (self.subdev.side_and_name(),) 
     167 
     168 
     169        s2v = gr.stream_to_vector(gr.sizeof_gr_complex, self.fft_size) 
     170 
     171        mywindow = window.blackmanharris(self.fft_size) 
     172        fft = gr.fft_vcc(self.fft_size, True, mywindow) 
     173        power = 0 
     174        for tap in mywindow: 
     175            power += tap*tap 
     176             
     177        c2mag = gr.complex_to_mag_squared(self.fft_size) 
     178        print "print c2mag ",c2mag,"\n" 
     179        # FIXME the log10 primitive is dog slow 
     180        log = gr.nlog10_ff(10, self.fft_size, 
     181                           -20*math.log10(self.fft_size)-10*math.log10(power/self.fft_size)) 
     182                 
     183        # Set the freq_step to 75% of the actual data throughput. 
     184        # This allows us to discard the bins on both ends of the spectrum. 
     185 
     186        self.freq_step = 0.75 * usrp_rate 
     187        self.min_center_freq = self.min_freq + self.freq_step/2 
     188        nsteps = math.ceil((self.max_freq - self.min_freq) / self.freq_step) 
     189        self.max_center_freq = self.min_center_freq + (nsteps * self.freq_step) 
     190 
     191        self.next_freq = self.min_center_freq 
     192         
     193        tune_delay  = max(0, int(round(options.tune_delay * usrp_rate / self.fft_size)))  # in fft_frames 
     194        dwell_delay = max(1, int(round(options.dwell_delay * usrp_rate / self.fft_size))) # in fft_frames 
     195 
     196        self.msgq = gr.msg_queue(16) 
     197        self._tune_callback = tune(self)        # hang on to this to keep it from being GC'd 
     198        stats = gr.bin_statistics_f(self.fft_size, self.msgq, 
     199                                    self._tune_callback, tune_delay, dwell_delay) 
     200 
     201        # FIXME leave out the log10 until we speed it up 
     202        #self.connect(self.u, s2v, fft, c2mag, log, stats) 
     203        self.connect(self.u, s2v, fft, c2mag, stats) 
     204 
     205        if options.gain is None: 
     206            # if no gain was specified, use the mid-point in dB 
     207            g = self.subdev.gain_range() 
     208            options.gain = float(g[0]+g[1])/2 
     209 
     210        self.set_gain(options.gain) 
     211        print "gain =", options.gain 
     212 
     213 
     214    def set_next_freq(self): 
     215        target_freq = self.next_freq 
     216        self.next_freq = self.next_freq + self.freq_step 
     217        if self.next_freq >= self.max_center_freq: 
     218            self.next_freq = self.min_center_freq 
     219 
     220        if not self.set_freq(target_freq): 
     221            print "Failed to set frequency to", target_freq 
     222 
     223        return target_freq 
     224                           
     225 
     226    def set_freq(self, target_freq): 
     227        """ 
     228        Set the center frequency we're interested in. 
     229 
     230        @param target_freq: frequency in Hz 
     231        @rypte: bool 
     232 
     233        Tuning is a two step process.  First we ask the front-end to 
     234        tune as close to the desired frequency as it can.  Then we use 
     235        the result of that operation and our target_frequency to 
     236        determine the value for the digital down converter. 
     237        """ 
     238        return self.u.tune(0, self.subdev, target_freq) 
     239 
     240 
     241    def set_gain(self, gain): 
     242        self.subdev.set_gain(gain) 
     243 
     244    def set_min_max_freq(self,minimum,maximum):# setting min and max frequency  
     245        self.min_freq = float(minimum)  
     246        self.max_freq = float(maximum) 
     247 
     248    def get_avg_power(self,trials): 
     249        power_sum = 0 #sum of powers(each power value is determined by adding the 'fft square' points..these fft square points are essentially points from  the PSD curve...and adding them gives us the power contained in the spectrum) 
     250        counter = 0 
     251        _trials = int(trials) 
     252        while counter < _trials : 
     253 
     254                # Get the next message sent from the C++ code (blocking call). 
     255                # It contains the center frequency and the mag squared of the fft 
     256                m = parse_msg(self.msgq.delete_head()) 
     257                print "printing mag sq of fft ",sum(m.data),"\n" 
     258                #if sum(m.data) > 1e12: 
     259                power_sum = power_sum + sum(m.data) 
     260                # Print center freq so we know that something is happening... 
     261                #print m.center_freq 
     262                counter +=1 
     263                # FIXME do something useful with the data... 
     264         
     265                # m.data are the mag_squared of the fft output (they are in the 
     266                # standard order.  I.e., bin 0 == DC.) 
     267                # You'll probably want to do the equivalent of "fftshift" on them 
     268                # m.raw_data is a string that contains the binary floats. 
     269                # You could write this as binary to a file. 
     270 
     271        avg_power = power_sum/_trials 
     272        print "printing average power ",avg_power,"\n" 
     273        return avg_power 
     274 
     275######################## end of spectrum sense specific classes ############################################################# 
     276 
    33277         
    34278#//////main//////   
     
    117361        parser_tx.print_help() 
    118362        sys.exit(1) 
    119  
     363    ############# Setting some default values for tx side of the block 
     364    options_tx.tx_freq = 462.5625e6 #setting default tx_freq value 
     365    options_tx.samples_per_symbol =  2 
     366    options_tx.modulation = 'dbpsk' 
     367    ############# 
    120368    if options_tx.tx_freq is None: 
    121369        sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") 
     
    157405        parser_rx.print_help(sys.stderr) 
    158406        sys.exit(1) 
    159  
     407    ############# Setting some default values for rx side of the block 
     408    options_rx.rx_freq = 462.5625e6 #setting default rx_freq value 
     409    options_rx.samples_per_symbol =  2 
     410    options_rx.modulation = 'dbpsk' 
     411    ############# 
    160412    if options_rx.rx_freq is None: 
    161413        sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") 
     
    164416    print "printing rx options",options_rx,"&&&&\n" 
    165417 
    166 # build the graph 
     418 
     419 
     420    ######################## adding another top block for usrp spectrum sense ######################## 
     421    trials = 10 
     422    default_min_freq = 462.4825e6 #80 Khz to the left of channel 1 (462.5625e6) in frs band  
     423    default_max_freq = 462.6425e6 #80 Khz to the right of channel 1 (462.5625e6) in frs band  
     424    tb_spec_sense = spec_sense_top_block(default_min_freq,default_min_freq) 
     425    tb_spec_sense.subdev.select_rx_antenna('RX2') 
     426    tb_spec_sense.start()              # start executing flow graph in another thread... 
     427    avg = tb_spec_sense.get_avg_power(trials) 
     428    print "printing the average power ",avg, "\n" 
     429    tb_spec_sense.stop()    
     430     
     431 
     432    ################################################################################################## 
     433 
     434    # build the graph 
    167435 
    168436    tb = my_top_block(mods[options_tx.modulation], 
    169                       demods[options_rx.modulation], 
    170                       rx_callback,options_tx, 
    171                       options_rx) 
     437                     demods[options_rx.modulation], 
     438                     rx_callback,options_tx, 
     439                     options_rx) 
    172440    r = gr.enable_realtime_scheduling() 
    173441    if r != gr.RT_OK: 
    174         print "Warning: failed to enable realtime scheduling" 
    175  
    176     tb.start() 
     442       print "Warning: failed to enable realtime scheduling" 
     443 
     444    #tb.start() 
    177445    # generate and send packets 
    178446    #print "printing megamytes",options_tx.megabytes,"  $$$$\n" 
     
    197465    #while running 
    198466     
    199     if mode  == "sync": 
    200         #nbytes = int(1e6 * .0003) 
    201         #nbytes = int(1e6 * .0003) 
    202         nbytes = 6 
    203         pkt_size = 6 
    204         print "printing packet size",pkt_size,"pkt size\n" 
    205         while sync_status != True: 
    206                 ch = random.randint(1, 7) 
    207                 #ch = int(random.choice('17')) 
    208                 #ch = random.randint(6,12) 
    209                 ch = 1 
    210                 hop_freq = float(1e6 * (462.5625+(ch-1)*0.025))#setting the centre freq frequency for sending packets 
    211                 print "hop freq is ",hop_freq 
    212                 #hop_freq = float(1e6 * (462.5625+(5-1)*0.05))#setting the centre freq frequency for sending packets 
    213                 tb.txpath.set_freq(hop_freq) 
    214                 tb.rxpath.set_freq(hop_freq) 
    215                 #print "inside while pppp printing sync channel",sync_status,"  done" 
    216                 #if sync_status == "True": 
    217                 #print "synchronization done..data channel is found" 
    218                 #break 
    219                 #else: 
    220                 #print "inside else1" 
    221                 n = 0 
    222                 pktno = 0 
    223                 print >> myfile, "out" 
    224                 while n < nbytes: 
    225                         print >> myfile, "inside while" 
    226                         if options_tx.from_file is None: 
    227                                 #data = (pkt_size - 2) * chr(pktno & 0xff) #0xff is 255 
    228                                 data = 's'+'s'+str(ch)+str(ch) #adding redundant bits for sync and channel 
    229                                 #print >> myfile, data 
    230                                 #print "printing data",data,"****\n" 
    231                         else: 
    232                                 data = source_file.read(pkt_size - 2) 
    233                                 if data == '': 
    234                                         break; 
    235  
    236                         payload = struct.pack('!H', pktno & 0xffff) + data 
    237                         #print "printing payload",payload,"**\n" 
    238          
    239                         send_pkt(tb,payload) 
    240                         #print "printing payload",payload,"**\n" 
    241                         n += len(payload) 
    242                         sys.stderr.write('.') 
    243                         if options_tx.discontinuous and pktno % 5 == 4: 
    244                                 time.sleep(1) 
    245                         pktno += 1 
    246                         #print "before sleeping for 10 seconds and value of resend count is",resend_count 
    247                 time.sleep(0.05) 
    248                 #time.sleep(2) 
    249                 #resend_count += 1  
    250     print "sync channel found! and it is channel ",ch,"\n" 
    251     send_pkt(tb,eof=True) 
    252     #myfile.close() 
    253     tb.wait() 
     467     
    254468 
    255469 
     
    286500 
    287501 
    288      
    289  
    290  
    291  
     502 
     503 
     504 
     505 
     506 
     507 
     508 
     509 
     510 
     511 
     512 
     513 
     514 
     515 
     516 
     517     
     518 
     519 
     520