1 | # |
---|
2 | # Copyright 2009 Free Software Foundation, Inc. |
---|
3 | # |
---|
4 | # This file is part of GNU Radio |
---|
5 | # |
---|
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) |
---|
9 | # any later version. |
---|
10 | # |
---|
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. |
---|
15 | # |
---|
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. |
---|
20 | # |
---|
21 | |
---|
22 | USRP1_TYPE = 'usrp1' |
---|
23 | USRP2_TYPE = 'usrp2' |
---|
24 | DUMMY_TYPE = 'dummy' |
---|
25 | #usrp2 rates common for decim and interp |
---|
26 | _USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) |
---|
27 | #dummy common rates |
---|
28 | _DUMMY_XRATES = range(4, 512, 2) |
---|
29 | _DUMMY_CONVERTER_RATE = 100e6 |
---|
30 | #dummy freq result |
---|
31 | class _dummy_freq_result(object): |
---|
32 | def __init__(self, target_freq): |
---|
33 | self.baseband_freq = target_freq |
---|
34 | self.dxc_freq = 0 |
---|
35 | self.residual_freq = 0 |
---|
36 | from gnuradio import gr, usrp, usrp2 |
---|
37 | |
---|
38 | ######################################################################## |
---|
39 | # generic usrp common stuff |
---|
40 | ######################################################################## |
---|
41 | class _generic_usrp_base(object): |
---|
42 | |
---|
43 | def __init__(self, which=0, subdev_spec=None, interface="", mac_addr="", |
---|
44 | fusb_block_size=0, fusb_nblocks=0, usrpx=None, lo_offset=None, gain=None): |
---|
45 | self._lo_offset = lo_offset |
---|
46 | #usrp options |
---|
47 | self._which = which |
---|
48 | self._subdev_spec = subdev_spec |
---|
49 | #usrp2 options |
---|
50 | self._interface = interface |
---|
51 | self._mac_addr = mac_addr |
---|
52 | #fusb options |
---|
53 | self._fusb_block_size = fusb_block_size |
---|
54 | self._fusb_nblocks = fusb_nblocks |
---|
55 | #pick which usrp model |
---|
56 | if usrpx == '0': self._setup_usrpx(DUMMY_TYPE) |
---|
57 | elif usrpx == '1' or self._subdev_spec: self._setup_usrpx(USRP1_TYPE) |
---|
58 | elif usrpx == '2' or self._mac_addr: self._setup_usrpx(USRP2_TYPE) |
---|
59 | else: #automatic |
---|
60 | try: self._setup_usrpx(USRP2_TYPE) |
---|
61 | except: |
---|
62 | try: self._setup_usrpx(USRP1_TYPE) |
---|
63 | except: raise Exception, 'Failed to automatically setup a usrp device.' |
---|
64 | #post usrp setup |
---|
65 | if self._lo_offset is not None: |
---|
66 | self.set_lo_offset(self._lo_offset) |
---|
67 | self.set_gain(gain) |
---|
68 | self.set_auto_tr(True) |
---|
69 | |
---|
70 | def _setup_usrpx(self, type): |
---|
71 | """ |
---|
72 | Call the appropriate setup method. |
---|
73 | @param type the usrp type constant |
---|
74 | """ |
---|
75 | self._type = type |
---|
76 | if self._type == USRP1_TYPE: self._setup_usrp1() |
---|
77 | elif self._type == USRP2_TYPE: self._setup_usrp2() |
---|
78 | elif self._type == DUMMY_TYPE: self._setup_dummy() |
---|
79 | |
---|
80 | def __str__(self): |
---|
81 | if self._type == USRP1_TYPE: return self._subdev.side_and_name() |
---|
82 | elif self._type == USRP2_TYPE: |
---|
83 | return 'Interface: %s MAC Address: %s D-Board ID: 0x%.2x'%( |
---|
84 | self._u.interface_name(), self._u.mac_addr(), self._u.daughterboard_id()) |
---|
85 | elif self._type == DUMMY_TYPE: return 'Dummy USRP Device' |
---|
86 | |
---|
87 | def gain(self): return self._gain |
---|
88 | |
---|
89 | def set_gain(self, gain=None): |
---|
90 | #automatic gain calculation |
---|
91 | r = self.gain_range() |
---|
92 | if gain is None: gain = (r[0] + r[1])/2 # set gain to midpoint |
---|
93 | #set gain for usrp |
---|
94 | self._gain = gain |
---|
95 | if self._type == USRP1_TYPE: return self._subdev.set_gain(gain) |
---|
96 | elif self._type == USRP2_TYPE: return self._u.set_gain(gain) |
---|
97 | elif self._type == DUMMY_TYPE: return True |
---|
98 | |
---|
99 | def gain_range(self): |
---|
100 | if self._type == USRP1_TYPE: return self._subdev.gain_range() |
---|
101 | elif self._type == USRP2_TYPE: return self._u.gain_range() |
---|
102 | elif self._type == DUMMY_TYPE: return (0, 0, 0) |
---|
103 | |
---|
104 | def set_center_freq(self, target_freq): |
---|
105 | if self._type == USRP1_TYPE: |
---|
106 | return self._u.tune(self._dxc, self._subdev, target_freq) |
---|
107 | elif self._type == USRP2_TYPE: |
---|
108 | return self._u.set_center_freq(target_freq) |
---|
109 | elif self._type == DUMMY_TYPE: return _dummy_freq_result(target_freq) |
---|
110 | |
---|
111 | def freq_range(self): |
---|
112 | if self._type == USRP1_TYPE: return self._subdev.freq_range() |
---|
113 | elif self._type == USRP2_TYPE: return self._u.freq_range() |
---|
114 | elif self._type == DUMMY_TYPE: return (-10e9, 10e9, 100e3) |
---|
115 | |
---|
116 | def set_lo_offset(self, lo_offset): |
---|
117 | if self._type == USRP1_TYPE: return self._subdev.set_lo_offset(lo_offset) |
---|
118 | elif self._type == USRP2_TYPE: return self._u.set_lo_offset(lo_offset) |
---|
119 | elif self._type == DUMMY_TYPE: return True |
---|
120 | |
---|
121 | def set_auto_tr(self, enable): |
---|
122 | if self._type == USRP1_TYPE: return self._subdev.set_auto_tr(enable) |
---|
123 | |
---|
124 | def __del__(self): |
---|
125 | try: # Avoid weak reference error |
---|
126 | del self._u |
---|
127 | del self._subdev |
---|
128 | except: pass |
---|
129 | |
---|
130 | ######################################################################## |
---|
131 | # generic usrp source |
---|
132 | ######################################################################## |
---|
133 | class generic_usrp_source_c(_generic_usrp_base, gr.hier_block2): |
---|
134 | """ |
---|
135 | Create a generic usrp source that represents usrp and usrp2. |
---|
136 | Take usrp and usrp2 constructor arguments and try to figure out usrp or usrp2. |
---|
137 | Provide generic access methods so the API looks the same for both. |
---|
138 | """ |
---|
139 | |
---|
140 | def __init__(self, **kwargs): |
---|
141 | gr.hier_block2.__init__(self, "generic_usrp_source", |
---|
142 | gr.io_signature(0, 0, 0), # Input signature |
---|
143 | gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature |
---|
144 | _generic_usrp_base.__init__(self, **kwargs) |
---|
145 | self.connect(self._u, self) |
---|
146 | |
---|
147 | #################################################################### |
---|
148 | # generic access methods |
---|
149 | #################################################################### |
---|
150 | def set_decim(self, decim): |
---|
151 | if decim not in self.get_decim_rates(): return False |
---|
152 | if self._type == USRP1_TYPE: return self._u.set_decim_rate(decim) |
---|
153 | elif self._type == USRP2_TYPE: return self._u.set_decim(decim) |
---|
154 | elif self._type == DUMMY_TYPE: return True |
---|
155 | |
---|
156 | def get_decim_rates(self): |
---|
157 | if self._type == USRP1_TYPE: return range(8, 256+1, 2) #default firmware w/ hb filters |
---|
158 | if self._type == USRP2_TYPE: return _USRP2_RATES |
---|
159 | elif self._type == DUMMY_TYPE: return _DUMMY_XRATES |
---|
160 | |
---|
161 | def adc_rate(self): |
---|
162 | if self._type == USRP1_TYPE: return self._u.adc_rate() |
---|
163 | if self._type == USRP2_TYPE: return self._u.adc_rate() |
---|
164 | elif self._type == DUMMY_TYPE: return _DUMMY_CONVERTER_RATE |
---|
165 | |
---|
166 | #################################################################### |
---|
167 | # setup usrp methods |
---|
168 | #################################################################### |
---|
169 | def _setup_usrp1(self): |
---|
170 | self._u = usrp.source_c (self._which, |
---|
171 | fusb_block_size=self._fusb_block_size, |
---|
172 | fusb_nblocks=self._fusb_nblocks) |
---|
173 | # determine the daughterboard subdevice we're using |
---|
174 | if self._subdev_spec is None: |
---|
175 | self._subdev_spec = usrp.pick_rx_subdevice(self._u) |
---|
176 | self._subdev = usrp.selected_subdev(self._u, self._subdev_spec) |
---|
177 | self._u.set_mux(usrp.determine_rx_mux_value(self._u, self._subdev_spec)) |
---|
178 | self._dxc = 0 |
---|
179 | |
---|
180 | def _setup_usrp2(self): |
---|
181 | self._u = usrp2.source_32fc(self._interface, self._mac_addr) |
---|
182 | |
---|
183 | def _setup_dummy(self): self._u = gr.null_source(gr.sizeof_gr_complex) |
---|
184 | |
---|
185 | ######################################################################## |
---|
186 | # generic usrp sink |
---|
187 | ######################################################################## |
---|
188 | class generic_usrp_sink_c(_generic_usrp_base, gr.hier_block2): |
---|
189 | """ |
---|
190 | Create a generic usrp sink that represents usrp and usrp2. |
---|
191 | Take usrp and usrp2 constructor arguments and try to figure out usrp or usrp2. |
---|
192 | Provide generic access methods so the API looks the same for both. |
---|
193 | """ |
---|
194 | |
---|
195 | def __init__(self, **kwargs): |
---|
196 | gr.hier_block2.__init__(self, "generic_usrp_sink", |
---|
197 | gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature |
---|
198 | gr.io_signature(0, 0, 0)) # Output signature |
---|
199 | _generic_usrp_base.__init__(self, **kwargs) |
---|
200 | if self._type == USRP1_TYPE: #scale 0.0 to 1.0 input for usrp1 |
---|
201 | self.connect(self, gr.multiply_const_cc((2**15)-1), self._u) |
---|
202 | else: self.connect(self, self._u) |
---|
203 | |
---|
204 | #################################################################### |
---|
205 | # generic access methods |
---|
206 | #################################################################### |
---|
207 | def set_interp(self, interp): |
---|
208 | if interp not in self.get_interp_rates(): return False |
---|
209 | if self._type == USRP1_TYPE: return self._u.set_interp_rate(interp) |
---|
210 | elif self._type == USRP2_TYPE: return self._u.set_interp(interp) |
---|
211 | elif self._type == DUMMY_TYPE: return True |
---|
212 | |
---|
213 | def get_interp_rates(self): |
---|
214 | if self._type == USRP1_TYPE: return range(16, 512+1, 4) |
---|
215 | if self._type == USRP2_TYPE: return _USRP2_RATES |
---|
216 | elif self._type == DUMMY_TYPE: return _DUMMY_XRATES |
---|
217 | |
---|
218 | def dac_rate(self): |
---|
219 | if self._type == USRP1_TYPE: return self._u.dac_rate() |
---|
220 | if self._type == USRP2_TYPE: return self._u.dac_rate() |
---|
221 | elif self._type == DUMMY_TYPE: return _DUMMY_CONVERTER_RATE |
---|
222 | |
---|
223 | #################################################################### |
---|
224 | # setup usrp methods |
---|
225 | #################################################################### |
---|
226 | def _setup_usrp1(self): |
---|
227 | self._u = usrp.sink_c (self._which, |
---|
228 | fusb_block_size=self._fusb_block_size, |
---|
229 | fusb_nblocks=self._fusb_nblocks) |
---|
230 | # determine the daughterboard subdevice we're using |
---|
231 | if self._subdev_spec is None: |
---|
232 | self._subdev_spec = usrp.pick_tx_subdevice(self._u) |
---|
233 | self._subdev = usrp.selected_subdev(self._u, self._subdev_spec) |
---|
234 | self._u.set_mux(usrp.determine_tx_mux_value(self._u, self._subdev_spec)) |
---|
235 | self._dxc = self._subdev.which() |
---|
236 | |
---|
237 | def _setup_usrp2(self): self._u = usrp2.sink_32fc(self._interface, self._mac_addr) |
---|
238 | |
---|
239 | def _setup_dummy(self): self._u = gr.null_sink(gr.sizeof_gr_complex) |
---|