X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=gr-usrp%2Fsrc%2Fusrp_multi.py;fp=gr-usrp%2Fsrc%2Fusrp_multi.py;h=c04d7312455bd6f664bb75bb749d37e2bc3139de;hb=8a9ddbb0675f9bfcc6e03b457fba6c79474a3693;hp=0000000000000000000000000000000000000000;hpb=82d471b9b4a8b389b5da44b19c69c36420828382;p=debian%2Fgnuradio diff --git a/gr-usrp/src/usrp_multi.py b/gr-usrp/src/usrp_multi.py new file mode 100644 index 00000000..c04d7312 --- /dev/null +++ b/gr-usrp/src/usrp_multi.py @@ -0,0 +1,233 @@ +# +# Copyright 2005,2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import math +from gnuradio import gr, gru +from gnuradio.gr import hier_block2 +from gnuradio import usrp +from usrpm import usrp_prims +import sys + + +class multi_source_align(object): + def __init__(self, fg, master_serialno, decim, nchan=2, pga_gain=0.0, + cordic_freq=0.0, mux=None, align_interval=-1, + fpga_filename="multi_2rxhb_2tx.rbf"): + """ + Align multiple sources (usrps) using samplenumbers in the first channel. + + Takes two ore more sources producing interleaved shorts. + produces nchan * nsources gr_complex output streams. + + @param nchan: number of interleaved channels in source + @param align_interval: number of samples to minimally skip between alignments + default = -1 which means align only once per work call. + @param master_serial_no: serial number of the source which must be the master. + + + Exported sub-blocks (attributes): + master_source + slave_source + usrp_master + usrp_slave + """ + mode=usrp.FPGA_MODE_NORMAL + mode = mode | usrp_prims.bmFR_MODE_RX_COUNTING_32BIT #(1 << 2) #usrp1.FPGA_MODE_COUNTING_32BIT + align=gr.align_on_samplenumbers_ss (nchan,align_interval) + self.usrp_master = None + self.usrp_slave = None + # um is master usrp + # us is slave usrp + if mux is None: + mux=self.get_default_mux() #Note that all channels have shifted left because of the added 32 bit counter channel + + u1 = usrp.source_s (1, decim, nchan, gru.hexint(mux), mode,fpga_filename=fpga_filename ) + u0 = usrp.source_s (0, decim, nchan, gru.hexint(mux), mode,fpga_filename=fpga_filename ) + print 'usrp[0] serial',u0.serial_number() + print 'usrp[1] serial',u1.serial_number() + #default, choose the second found usrp as master (which is usually the usrp which was first plugged in) + um_index=1 + um=u1 + us_index=0 + us=u0 + if (not (master_serialno is None)): #((master_serialno>0) | (master_serialno <-2)): + if (u0.serial_number() == master_serialno): + um_index=0 + um=u0 + us_index=1 + us=u1 + elif (u1.serial_number() != master_serialno): + errorstring = 'Error. requested master_serialno ' + master_serialno +' not found\n' + errorstring = errorstring + 'Available are:\n' + errorstring = errorstring + 'usrp[1] serial_no = ' + u1.serial_number() +'\n' + errorstring = errorstring + 'usrp[0] serial_no = ' + u0.serial_number() +'\n' + print errorstring + raise ValueError, errorstring + else: #default, just choose the first found usrp as master + um_index=1 + um=u1 + us_index=0 + us=u0 + + self.usrp_master=um + self.usrp_slave=us + print 'usrp_master=usrp[%i] serial_no = %s' % (um_index,self.usrp_master.serial_number() ,) + print 'usrp_slave=usrp[%i] serial_no = %s' % (us_index,self.usrp_slave.serial_number() ,) + self.subdev_mAr = usrp.selected_subdev(self.usrp_master, (0,0)) + self.subdev_mBr = usrp.selected_subdev(self.usrp_master, (1,0)) + self.subdev_sAr = usrp.selected_subdev(self.usrp_slave, (0,0)) + self.subdev_sBr = usrp.selected_subdev(self.usrp_slave, (1,0)) + #throttle = gr.throttle(gr.sizeof_gr_complex, input_rate) + if not (pga_gain is None): + um.set_pga (0, pga_gain) + um.set_pga (1, pga_gain) + + us.set_pga (0, pga_gain) + us.set_pga (1, pga_gain) + + self.input_rate = um.adc_freq () / um.decim_rate () + deintm=gr.deinterleave(gr.sizeof_gr_complex) + deints=gr.deinterleave(gr.sizeof_gr_complex) + nullsinkm=gr.null_sink(gr.sizeof_gr_complex) + nullsinks=gr.null_sink(gr.sizeof_gr_complex) + + tocomplexm=gr.interleaved_short_to_complex() + tocomplexs=gr.interleaved_short_to_complex() + + fg.connect(um,(align,0)) + fg.connect(us,(align,1)) + fg.connect((align,0),tocomplexm) + fg.connect((align,1),tocomplexs) + fg.connect(tocomplexm,deintm) + fg.connect(tocomplexs,deints) + fg.connect((deintm,0),nullsinkm) #The counters are not usefull for the user but must be connected to something + fg.connect((deints,0),nullsinks) #The counters are not usefull for the user but must be connected to something + if 4==nchan: + nullsinkm3=gr.null_sink(gr.sizeof_gr_complex) + nullsinks3=gr.null_sink(gr.sizeof_gr_complex) + fg.connect((deintm,3), nullsinkm3) #channel 4 is not used but must be connected + fg.connect((deints,3), nullsinks3) #channel 4 is not used but must be connected + + self.fg=fg + self.master_source=deintm + self.slave_source=deints + + if not (cordic_freq is None): + um.set_rx_freq (1, cordic_freq) + um.set_rx_freq (0, cordic_freq) + us.set_rx_freq (1, cordic_freq) + us.set_rx_freq (0, cordic_freq) + + self.enable_master_and_slave() + # add an idle handler + self.unsynced=True + + # wire the block together + #hier_block_multi_tail.__init__(self, fg, nchan,deintm,deints) + + def get_default_mux(self): + return 0x10321032 # Note that all channels have shifted left because of the added 32 bit counter channel + + def get_master_source_c(self): + return self.master_source + + def get_slave_source_c(self): + return self.slave_source + + def get_master_usrp(self): + return self.usrp_master + + def get_slave_usrp(self): + return self.usrp_slave + + def enable_master_and_slave(self): + # Warning, allways FIRST enable the slave before you enable the master + # This is to be sure you don't have two masters connecting to each other + # Otherwise you could ruin your hardware because the two sync outputs would be connected together + + #SLAVE + #disable master, enable slave and set sync pulse to zero + reg_mask = usrp_prims.bmFR_RX_SYNC_SLAVE | usrp_prims.bmFR_RX_SYNC_MASTER | usrp_prims.bmFR_RX_SYNC + self.usrp_slave._u._write_fpga_reg_masked(usrp_prims.FR_RX_MASTER_SLAVE, usrp_prims.bmFR_RX_SYNC_SLAVE,reg_mask) + #set SYNC slave iopin on daughterboards RXA as input + oe = 0 # set rx_a_io[bitnoFR_RX_SYNC_INPUT_IOPIN] as input + oe_mask = usrp_prims.bmFR_RX_SYNC_INPUT_IOPIN + self.usrp_slave._u._write_oe(0,oe,oe_mask) + #Now it is save to enable the master + + #MASTER + #enable master, disable slave and set sync pulse to zero + reg_mask = usrp_prims.bmFR_RX_SYNC_SLAVE | usrp_prims.bmFR_RX_SYNC_MASTER | usrp_prims.bmFR_RX_SYNC + self.usrp_master._u._write_fpga_reg_masked(usrp_prims.FR_RX_MASTER_SLAVE,usrp_prims.bmFR_RX_SYNC_MASTER,reg_mask) + #set SYNC master iopin on daughterboards RXA as output + oe = usrp_prims.bmFR_RX_SYNC_OUTPUT_IOPIN # set rx_a_io[bitnoFR_RX_SYNC_OUTPUT_IOPIN] as output + oe_mask = usrp_prims.bmFR_RX_SYNC_OUTPUT_IOPIN + self.usrp_master._u._write_oe(0,oe,oe_mask) + + def sync_usrps(self, evt): + self.sync() + + def sync(self): + result=False + result = self.usrp_master._u._write_fpga_reg_masked (usrp_prims.FR_RX_MASTER_SLAVE, usrp_prims.bmFR_RX_SYNC, usrp_prims.bmFR_RX_SYNC ) + #There should be a small delay here, but the time it takes to get the sync to the usrp is long enough + #turn sync pulse off + result = result & self.usrp_master._u._write_fpga_reg_masked (usrp_prims.FR_RX_MASTER_SLAVE,0 ,usrp_prims.bmFR_RX_SYNC); + return result; + + def nullsink_counters(self): + nullsinkm=gr.null_sink(gr.sizeof_gr_complex) + nullsinks=gr.null_sink(gr.sizeof_gr_complex) + self.fg.connect((self.master_source,0),nullsinkm) + self.fg.connect((self.slave_source,0),nullsinks) + + + def print_db_info(self): + print "MASTER RX d'board %s" % (self.subdev_mAr.side_and_name(),) + print "MASTER RX d'board %s" % (self.subdev_mBr.side_and_name(),) + #print "TX d'board %s" % (self.subdev_At.side_and_name(),) + #print "TX d'board %s" % (self.subdev_Bt.side_and_name(),) + print "SLAVE RX d'board %s" % (self.subdev_sAr.side_and_name(),) + print "SLAVE RX d'board %s" % (self.subdev_sBr.side_and_name(),) + #print "TX d'board %s" % (self.subdev_At.side_and_name(),) + #print "TX d'board %s" % (self.subdev_Bt.side_and_name(),) + + def tune_all_rx(self,target_freq): + result = True + r1 = usrp.tune(self.usrp_master, 0, self.subdev_mAr, target_freq) + if r1 is None: + result=False + r2 = usrp.tune(self.usrp_master, 1, self.subdev_mBr, target_freq) + if r2 is None: + result=False + r3 = usrp.tune(self.usrp_slave, 0, self.subdev_sAr, target_freq) + if r3 is None: + result=False + r4 = usrp.tune(self.usrp_slave, 1, self.subdev_sBr, target_freq) + if r4 is None: + result=False + return result,r1,r2,r3,r4 + + def set_gain_all_rx(self, gain): + self.subdev_mAr.set_gain(gain) + self.subdev_mBr.set_gain(gain) + self.subdev_sAr.set_gain(gain) + self.subdev_sBr.set_gain(gain)