3 # Copyright 2008,2009 Free Software Foundation, Inc.
5 # This file is part of GNU Radio
7 # GNU Radio is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3, or (at your option)
12 # GNU Radio is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with GNU Radio; see the file COPYING. If not, write to
19 # the Free Software Foundation, Inc., 51 Franklin Street,
20 # Boston, MA 02110-1301, USA.
23 from gnuradio import gr, eng_notation, usrp2
24 from gnuradio.eng_option import eng_option
25 from optparse import OptionParser
29 n2s = eng_notation.num_to_str
31 waveforms = { gr.GR_SIN_WAVE : "Complex Sinusoid",
32 gr.GR_CONST_WAVE : "Constant",
33 gr.GR_GAUSSIAN : "Gaussian Noise",
34 gr.GR_UNIFORM : "Uniform Noise",
39 # GUI-unaware GNU Radio flowgraph. This may be used either with command
40 # line applications or GUI applications.
42 class top_block(gr.top_block):
43 def __init__(self, options, args):
44 gr.top_block.__init__(self)
45 self._verbose = options.verbose
49 self._freq = None # Indicates frequency hasn't been successfully set yet
53 self._type = None # Indicates waveform flowgraph not created yet
54 self._offset = options.offset
56 self.set_usrp2(options.interface, options.mac_addr)
57 self.set_interp(options.interp)
58 self.set_gain(options.gain)
59 self.set_freq(options.tx_freq, options.lo_offset)
60 self.set_amplitude(options.amplitude)
62 self.set_waveform_freq(options.waveform_freq)
63 #self.set_waveform2_freq(options.waveform2_freq)
64 self._waveform2_freq = options.waveform2_freq
65 self.set_waveform(options.type)
67 def set_usrp2(self, interface, mac_addr):
68 self._u = usrp2.sink_32fc(interface, mac_addr)
69 self._dac_rate = self._u.dac_rate()
71 print "Network interface:", interface
72 print "Network address:", self._u.mac_addr()
73 print "Daughterboard ID:", hex(self._u.daughterboard_id())
75 def set_interp(self, interp):
76 if interp < 4 or interp > 512: # FIXME get from flowgraph
77 if self._verbose: print "Interpolation rate out of range:", interp
80 if not self._u.set_interp(interp):
81 raise RuntimeError("Failed to set interpolation rate %i" % (interp,))
84 self._eth_rate = self._dac_rate/self._interp
86 print "USRP2 interpolation rate:", self._interp
87 print "USRP2 IF bandwidth: %sHz" % (n2s(self._eth_rate),)
89 if (self._type == gr.GR_SIN_WAVE or
90 self._type == gr.GR_CONST_WAVE):
91 self._src.set_sampling_freq(self._eth_rate)
92 elif self._type == "2tone":
93 self._src1.set_sampling_freq(self._eth_rate)
94 self._src1.set_sampling_freq(self._eth_rate)
95 elif self._type == "sweep":
96 self._src1.set_sampling_freq(self._eth_rate)
97 self._src1.set_sampling_freq(self._waveform_freq*2*math.pi/self._eth_rate)
99 return True # Waveform not yet set
101 if self._verbose: print "Set interpolation rate to:", interp
104 def set_gain(self, gain):
106 g = self._u.gain_range()
107 gain = float(g[0]+g[1])/2
109 print "Using auto-calculated mid-point TX gain"
110 self._u.set_gain(gain)
113 print "Set TX gain to:", self._gain
115 def set_freq(self, target_freq, lo_offset=None):
116 if lo_offset is not None:
117 self._lo_offset = lo_offset
118 self._u.set_lo_offset(self._lo_offset)
120 print "Set LO offset frequency to: %sHz" % (n2s(lo_offset),)
122 if target_freq is None:
123 f = self._u.freq_range()
124 target_freq = float(f[0]+f[1])/2.0
126 print "Using auto-calculated mid-point frequency"
128 tr = self._u.set_center_freq(target_freq)
129 fs = "%sHz" % (n2s(target_freq),)
131 self._freq = target_freq
134 return True # Waveform not yet set
136 if self._verbose: print "Set amplitude to:", amplitude
139 def set_gain(self, gain):
141 g = self._u.gain_range()
142 gain = float(g[0]+g[1])/2
144 print "Using auto-calculated mid-point TX gain"
145 self._u.set_gain(gain)
148 print "Set TX gain to:", self._gain
150 def set_freq(self, target_freq, lo_offset=None):
151 if lo_offset is not None:
152 self._lo_offset = lo_offset
153 self._u.set_lo_offset(self._lo_offset)
155 print "Set LO offset frequency to: %sHz" % (n2s(lo_offset),)
157 if target_freq is None:
158 f = self._u.freq_range()
159 target_freq = float(f[0]+f[1])/2.0
161 print "Using auto-calculated mid-point frequency"
163 tr = self._u.set_center_freq(target_freq)
164 fs = "%sHz" % (n2s(target_freq),)
166 self._freq = target_freq
167 self._ddc_freq = tr.dxc_freq
168 self._bb_freq = tr.baseband_freq
170 print "Set center frequency to", fs
171 print "Tx baseband frequency: %sHz" % (n2s(tr.baseband_freq),)
172 print "Tx DDC frequency: %sHz" % (n2s(tr.dxc_freq),)
173 print "Tx residual frequency: %sHz" % (n2s(tr.residual_freq),)
177 def set_waveform_freq(self, freq):
178 self._waveform_freq = freq
179 if self._type == gr.GR_SIN_WAVE:
180 self._src.set_frequency(freq)
181 elif self._type == "2tone" or self._type == "sweep":
182 self._src1.set_frequency(freq)
185 def set_waveform2_freq(self, freq):
186 self._waveform2_freq = freq
187 if self._type == "2tone":
188 self._src2.set_frequency(freq)
189 elif self._type == "sweep":
190 self._src1.set_frequency(freq)
193 def set_waveform(self, type):
195 self.disconnect_all()
197 if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
198 self._src = gr.sig_source_c(self._eth_rate, # Sample rate
199 type, # Waveform type
200 self._waveform_freq, # Waveform frequency
201 self._amplitude, # Waveform amplitude
202 self._offset) # Waveform offset
203 elif type == gr.GR_GAUSSIAN or type == gr.GR_UNIFORM:
204 self._src = gr.noise_source_c(type, self._amplitude)
205 elif type == "2tone":
206 self._src1 = gr.sig_source_c(self._eth_rate,
211 if(self._waveform2_freq is None):
212 self._waveform2_freq = -self._waveform_freq
214 self._src2 = gr.sig_source_c(self._eth_rate,
216 self._waveform2_freq,
219 self._src = gr.add_cc()
220 self.connect(self._src1,(self._src,0))
221 self.connect(self._src2,(self._src,1))
222 elif type == "sweep":
223 # rf freq is center frequency
224 # waveform_freq is total swept width
225 # waveform2_freq is sweep rate
226 # will sweep from (rf_freq-waveform_freq/2) to (rf_freq+waveform_freq/2)
227 if self._waveform2_freq is None:
228 self._waveform2_freq = 0.1
230 self._src1 = gr.sig_source_f(self._eth_rate,
232 self._waveform2_freq,
235 self._src2 = gr.frequency_modulator_fc(self._waveform_freq*2*math.pi/self._eth_rate)
236 self._src = gr.multiply_const_cc(self._amplitude)
237 self.connect(self._src1,self._src2,self._src)
239 raise RuntimeError("Unknown waveform type")
241 self.connect(self._src, self._u)
246 print "Set baseband modulation to:", waveforms[self._type]
247 if type == gr.GR_SIN_WAVE:
248 print "Modulation frequency: %sHz" % (n2s(self._waveform_freq),)
249 print "Initial phase:", self._offset
250 elif type == "2tone":
251 print "Tone 1: %sHz" % (n2s(self._waveform_freq),)
252 print "Tone 2: %sHz" % (n2s(self._waveform2_freq),)
253 elif type == "sweep":
254 print "Sweeping across %sHz to %sHz" % (n2s(-self._waveform_freq/2.0),n2s(self._waveform_freq/2.0))
255 print "Sweep rate: %sHz" % (n2s(self._waveform2_freq),)
256 print "TX amplitude:", self._amplitude
259 def set_amplitude(self, amplitude):
260 if amplitude < 0.0 or amplitude > 1.0:
261 if self._verbose: print "Amplitude out of range:", amplitude
264 self._amplitude = amplitude
266 if (self._type == gr.GR_SIN_WAVE or
267 self._type == gr.GR_CONST_WAVE or
268 self._type == gr.GR_GAUSSIAN or
269 self._type == gr.GR_UNIFORM):
270 self._src.set_amplitude(amplitude)
271 elif self._type == "2tone":
272 self._src1.set_amplitude(amplitude/2.0)
273 self._src2.set_amplitude(amplitude/2.0)
274 elif self._type == "sweep":
275 self._src.set_k(amplitude)
277 return True # Waveform not yet set
279 if self._verbose: print "Set amplitude to:", amplitude
285 #def interface(self):
286 # return self._u.ifc_name()
289 return self._u.mac_addr()
292 return self._u.ifc_name()
294 def daughterboard_id(self):
295 return self._u.daughterboard_id()
297 def interp_rate(self):
301 return self._eth_rate
306 def freq_range(self):
307 fr = self._u.freq_range()
308 if self._u.daughterboard_id() == 0x0000:
309 fr = (-50e6, 50e6) # DEBUG
313 return self._ddc_freq
315 def baseband_freq(self):
319 return self._amplitude
321 def waveform_type(self):
324 def waveform_freq(self):
325 return self._waveform_freq
327 def waveform2_freq(self):
328 if self._waveform2_freq is None:
329 return -self._waveform_freq
331 return self._waveform2_freq
334 usage="%prog: [options]"
336 parser = OptionParser(option_class=eng_option, usage=usage)
338 parser.add_option("-e", "--interface", type="string", default="eth0",
339 help="Use specified Ethernet interface [default=%default]")
340 parser.add_option("-m", "--mac-addr", type="string", default="",
341 help="Use USRP2 at specified MAC address [default=None]")
342 parser.add_option("-i", "--interp", type="int", default=16, metavar="INTERP",
343 help="Set FPGA interpolation rate of INTERP [default=%default]")
344 parser.add_option("-f", "--tx-freq", type="eng_float", default=None,
345 help="Set carrier frequency to FREQ [default=mid-point]", metavar="FREQ")
346 parser.add_option("--lo-offset", type="eng_float", default=None,
347 help="set daughterboard LO offset to OFFSET [default=hw default]")
348 parser.add_option("-g", "--gain", type="eng_float", default=None,
349 help="Set TX gain to GAIN [default=mid-point]")
350 parser.add_option("-w", "--waveform-freq", type="eng_float", default=0,
351 help="Set baseband waveform frequency to FREQ [default=%default]")
352 parser.add_option("-x", "--waveform2-freq", type="eng_float", default=None,
353 help="Set 2nd waveform frequency to FREQ [default=%default]")
354 parser.add_option("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE,
355 help="Generate a carrier modulated by a complex sine wave", default=gr.GR_SIN_WAVE)
356 parser.add_option("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE,
357 help="Generate a constant carrier")
358 parser.add_option("--offset", type="eng_float", default=0,
359 help="Set waveform phase offset to OFFSET [default=%default]")
360 parser.add_option("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN,
361 help="Generate Gaussian random output")
362 parser.add_option("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
363 help="Generate Uniform random output")
364 parser.add_option("--2tone", dest="type", action="store_const", const="2tone",
365 help="Generate Two Tone signal for IMD testing")
366 parser.add_option("--sweep", dest="type", action="store_const", const="sweep",
367 help="Generate a swept sine wave")
368 parser.add_option("-a", "--amplitude", type="eng_float", default=0.1,
369 help="Set output amplitude to AMPL (0.0-1.0) [default=%default]", metavar="AMPL")
370 parser.add_option("-v", "--verbose", action="store_true", default=False,
371 help="Use verbose console output [default=%default]")
373 (options, args) = parser.parse_args()
375 return (options, args)
377 # If this script is executed, the following runs. If it is imported, the below does not run.
378 if __name__ == "__main__":
379 if gr.enable_realtime_scheduling() != gr.RT_OK:
380 print "Note: failed to enable realtime scheduling, continuing"
382 # Grab command line options and create top block
384 (options, args) = get_options()
385 tb = top_block(options, args)
387 except RuntimeError, e:
395 except KeyboardInterrupt: