2 # Copyright 2005 Free Software Foundation, Inc.
4 # This file is part of GNU Radio
6 # GNU Radio is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3, or (at your option)
11 # GNU Radio is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with GNU Radio; see the file COPYING. If not, write to
18 # the Free Software Foundation, Inc., 51 Franklin Street,
19 # Boston, MA 02110-1301, USA.
23 from gnuradio import gr, gru
24 from gnuradio.gr import hier_block_base
25 from gnuradio import usrp
26 from gnuradio import usrp1 # usrp Rev 1 and later
27 from gnuradio import blks
32 class multi_source_align(object):
33 def __init__(self, fg, master_serialno,decim,nchan=2,pga_gain=0.0,cordic_freq=0.0,mux=None,align_interval=-1):
35 Align multiple sources (usrps) using samplenumbers in the first channel.
37 Takes two ore more sources producing interleaved shorts.
38 produces nchan * nsources gr_complex output streams.
40 @param nchan: number of interleaved channels in source
41 @param align_interval: number of samples to minimally skip between alignments
42 default = -1 which means align only once per work call.
43 @param master_serial_no: serial number of the source which must be the master.
46 Exported sub-blocks (attributes):
52 mode=usrp.FPGA_MODE_NORMAL
53 mode = mode | usrp_prims.bmFR_MODE_RX_COUNTING_32BIT #(1 << 2) #usrp1.FPGA_MODE_COUNTING_32BIT
54 align=gr.align_on_samplenumbers_ss (nchan,align_interval)
55 self.usrp_master = None
56 self.usrp_slave = None
60 mux=self.get_default_mux() #Note that all channels have shifted left because of the added 32 bit counter channel
62 u1 = usrp.source_s (1, decim, nchan, gru.hexint(mux), mode,fpga_filename="multi_2rxhb_2tx.rbf" )
63 u0 = usrp.source_s (0, decim, nchan, gru.hexint(mux), mode,fpga_filename="multi_2rxhb_2tx.rbf" )
64 print 'usrp[0] serial',u0.serial_number()
65 print 'usrp[1] serial',u1.serial_number()
66 #default, choose the second found usrp as master (which is usually the usrp which was first plugged in)
71 if (not (master_serialno is None)): #((master_serialno>0) | (master_serialno <-2)):
72 if (u0.serial_number() == master_serialno):
77 elif (u1.serial_number() != master_serialno):
78 errorstring = 'Error. requested master_serialno ' + master_serialno +' not found\n'
79 errorstring = errorstring + 'Available are:\n'
80 errorstring = errorstring + 'usrp[1] serial_no = ' + u1.serial_number() +'\n'
81 errorstring = errorstring + 'usrp[0] serial_no = ' + u0.serial_number() +'\n'
83 raise ValueError, errorstring
84 else: #default, just choose the first found usrp as master
92 print 'usrp_master=usrp[%i] serial_no = %s' % (um_index,self.usrp_master.serial_number() ,)
93 print 'usrp_slave=usrp[%i] serial_no = %s' % (us_index,self.usrp_slave.serial_number() ,)
94 self.subdev_mAr = usrp.selected_subdev(self.usrp_master, (0,0))
95 self.subdev_mBr = usrp.selected_subdev(self.usrp_master, (1,0))
96 self.subdev_sAr = usrp.selected_subdev(self.usrp_slave, (0,0))
97 self.subdev_sBr = usrp.selected_subdev(self.usrp_slave, (1,0))
98 #throttle = gr.throttle(gr.sizeof_gr_complex, input_rate)
99 if not (pga_gain is None):
100 um.set_pga (0, pga_gain)
101 um.set_pga (1, pga_gain)
103 us.set_pga (0, pga_gain)
104 us.set_pga (1, pga_gain)
106 self.input_rate = um.adc_freq () / um.decim_rate ()
107 deintm=gr.deinterleave(gr.sizeof_gr_complex)
108 deints=gr.deinterleave(gr.sizeof_gr_complex)
109 nullsinkm=gr.null_sink(gr.sizeof_gr_complex)
110 nullsinks=gr.null_sink(gr.sizeof_gr_complex)
112 tocomplexm=gr.interleaved_short_to_complex()
113 tocomplexs=gr.interleaved_short_to_complex()
115 fg.connect(um,(align,0))
116 fg.connect(us,(align,1))
117 fg.connect((align,0),tocomplexm)
118 fg.connect((align,1),tocomplexs)
119 fg.connect(tocomplexm,deintm)
120 fg.connect(tocomplexs,deints)
121 fg.connect((deintm,0),nullsinkm) #The counters are not usefull for the user but must be connected to something
122 fg.connect((deints,0),nullsinks) #The counters are not usefull for the user but must be connected to something
124 nullsinkm3=gr.null_sink(gr.sizeof_gr_complex)
125 nullsinks3=gr.null_sink(gr.sizeof_gr_complex)
126 fg.connect((deintm,3), nullsinkm3) #channel 4 is not used but must be connected
127 fg.connect((deints,3), nullsinks3) #channel 4 is not used but must be connected
130 self.master_source=deintm
131 self.slave_source=deints
133 if not (cordic_freq is None):
134 um.set_rx_freq (1, cordic_freq)
135 um.set_rx_freq (0, cordic_freq)
136 us.set_rx_freq (1, cordic_freq)
137 us.set_rx_freq (0, cordic_freq)
139 self.enable_master_and_slave()
140 # add an idle handler
143 # wire the block together
144 #hier_block_multi_tail.__init__(self, fg, nchan,deintm,deints)
146 def get_default_mux(self):
147 return 0x10321032 # Note that all channels have shifted left because of the added 32 bit counter channel
149 def get_master_source_c(self):
150 return self.master_source
152 def get_slave_source_c(self):
153 return self.slave_source
155 def get_master_usrp(self):
156 return self.usrp_master
158 def get_slave_usrp(self):
159 return self.usrp_slave
161 def enable_master_and_slave(self):
162 # Warning, allways FIRST enable the slave before you enable the master
163 # This is to be sure you don't have two masters connecting to each other
164 # Otherwise you could ruin your hardware because the two sync outputs would be connected together
167 #disable master, enable slave and set sync pulse to zero
168 reg_mask = usrp_prims.bmFR_RX_SYNC_SLAVE | usrp_prims.bmFR_RX_SYNC_MASTER | usrp_prims.bmFR_RX_SYNC
169 self.usrp_slave._u._write_fpga_reg_masked(usrp_prims.FR_RX_MASTER_SLAVE, usrp_prims.bmFR_RX_SYNC_SLAVE,reg_mask)
170 #set SYNC slave iopin on daughterboards RXA as input
171 oe = 0 # set rx_a_io[bitnoFR_RX_SYNC_INPUT_IOPIN] as input
172 oe_mask = usrp_prims.bmFR_RX_SYNC_INPUT_IOPIN
173 self.usrp_slave._u._write_oe(0,oe,oe_mask)
174 #Now it is save to enable the master
177 #enable master, disable slave and set sync pulse to zero
178 reg_mask = usrp_prims.bmFR_RX_SYNC_SLAVE | usrp_prims.bmFR_RX_SYNC_MASTER | usrp_prims.bmFR_RX_SYNC
179 self.usrp_master._u._write_fpga_reg_masked(usrp_prims.FR_RX_MASTER_SLAVE,usrp_prims.bmFR_RX_SYNC_MASTER,reg_mask)
180 #set SYNC master iopin on daughterboards RXA as output
181 oe = usrp_prims.bmFR_RX_SYNC_OUTPUT_IOPIN # set rx_a_io[bitnoFR_RX_SYNC_OUTPUT_IOPIN] as output
182 oe_mask = usrp_prims.bmFR_RX_SYNC_OUTPUT_IOPIN
183 self.usrp_master._u._write_oe(0,oe,oe_mask)
185 def sync_usrps(self, evt):
190 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 )
191 #There should be a small delay here, but the time it takes to get the sync to the usrp is long enough
193 result = result & self.usrp_master._u._write_fpga_reg_masked (usrp_prims.FR_RX_MASTER_SLAVE,0 ,usrp_prims.bmFR_RX_SYNC);
196 def nullsink_counters(self):
197 nullsinkm=gr.null_sink(gr.sizeof_gr_complex)
198 nullsinks=gr.null_sink(gr.sizeof_gr_complex)
199 self.fg.connect((self.master_source,0),nullsinkm)
200 self.fg.connect((self.slave_source,0),nullsinks)
203 def print_db_info(self):
204 print "MASTER RX d'board %s" % (self.subdev_mAr.side_and_name(),)
205 print "MASTER RX d'board %s" % (self.subdev_mBr.side_and_name(),)
206 #print "TX d'board %s" % (self.subdev_At.side_and_name(),)
207 #print "TX d'board %s" % (self.subdev_Bt.side_and_name(),)
208 print "SLAVE RX d'board %s" % (self.subdev_sAr.side_and_name(),)
209 print "SLAVE RX d'board %s" % (self.subdev_sBr.side_and_name(),)
210 #print "TX d'board %s" % (self.subdev_At.side_and_name(),)
211 #print "TX d'board %s" % (self.subdev_Bt.side_and_name(),)
213 def tune_all_rx(self,target_freq):
215 r1 = usrp.tune(self.usrp_master, 0, self.subdev_mAr, target_freq)
218 r2 = usrp.tune(self.usrp_master, 1, self.subdev_mBr, target_freq)
221 r3 = usrp.tune(self.usrp_slave, 0, self.subdev_sAr, target_freq)
224 r4 = usrp.tune(self.usrp_slave, 1, self.subdev_sBr, target_freq)
227 return result,r1,r2,r3,r4
229 def set_gain_all_rx(self, gain):
230 self.subdev_mAr.set_gain(gain)
231 self.subdev_mBr.set_gain(gain)
232 self.subdev_sAr.set_gain(gain)
233 self.subdev_sBr.set_gain(gain)