added frequency sweep capability
[debian/gnuradio] / gr-utils / src / python / usrp2_siggen.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2008 Free Software Foundation, Inc.
4
5 # This file is part of GNU Radio
6
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)
10 # any later version.
11
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.
16
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.
21
22
23 from gnuradio import gr, eng_notation
24 from gnuradio import usrp2
25 from gnuradio.eng_option import eng_option
26 from optparse import OptionParser
27 import sys
28 import math
29
30 n2s = eng_notation.num_to_str
31
32 class siggen_top_block(gr.top_block):
33     def __init__(self, options):
34         gr.top_block.__init__(self)
35
36         # Create a USRP2 sink with the requested interpolation rate
37         self._u = usrp2.sink_32fc(options.interface, options.mac_addr)
38         self._u.set_interp(options.interp)
39
40         # Set the Tx daughterboard gain as requested
41         if options.gain is None:
42             g = self._u.gain_range()
43             options.gain = float(g[0]+g[1])/2
44         self._u.set_gain(options.gain)
45
46         # Tune the USRP2 FPGA and daughterboard to the requested center frequency
47         tr = self._u.set_center_freq(options.tx_freq)
48         if tr == None:
49             sys.stderr.write('Failed to set center frequency\n')
50             raise SystemExit, 1
51
52         eth_rate = self._u.dac_rate()/self._u.interp()
53         
54         # Create a source for the requested waveform type
55         if options.type == gr.GR_SIN_WAVE or options.type == gr.GR_CONST_WAVE:
56             self._src = gr.sig_source_c(eth_rate,              # Sample rate
57                                         options.type,          # Waveform type
58                                         options.waveform_freq, # Waveform frequency
59                                         options.amplitude,     # Waveform amplitude
60                                         options.offset)        # Waveform offset
61             
62         elif options.type == gr.GR_GAUSSIAN or options.type == gr.GR_UNIFORM:
63             self._src = gr.noise_source_c(options.type, options.amplitude)
64         elif options.type == "2tone":
65             self._src1 = gr.sig_source_c(eth_rate,
66                                          gr.GR_SIN_WAVE,
67                                          options.waveform_freq,
68                                          options.amplitude,
69                                          0)
70             if(options.waveform2_freq is None):
71                 w2freq = -options.waveform_freq
72             else:
73                 w2freq = options.waveform2_freq
74             self._src2 = gr.sig_source_c(eth_rate,
75                                          gr.GR_SIN_WAVE,
76                                          w2freq,
77                                          options.amplitude,
78                                          0)
79             self._src = gr.add_cc()
80             self.connect(self._src1,(self._src,0))
81             self.connect(self._src2,(self._src,1))
82         elif options.type == "sweep":
83             # rf freq is center frequency
84             # waveform_freq is total swept width
85             # waveform2_freq is sweep rate
86             #  will sweep from (rf_freq-waveform_freq/2) to (rf_freq+waveform_freq/2)
87             self._src1 = gr.sig_source_f(eth_rate,
88                                          gr.GR_TRI_WAVE,
89                                          options.waveform2_freq,
90                                          1.0,  # options.waveform_freq,
91                                          -0.5)
92             self._src2 = gr.frequency_modulator_fc(options.waveform_freq*2*math.pi/eth_rate)
93             self._src = gr.multiply_const_cc(options.amplitude)
94             self.connect(self._src1,self._src2,self._src)
95         else:
96             sys.stderr.write('Unknown waveform type\n')
97             raise SystemExit, 1
98
99         if options.verbose:
100             print "Network interface:", options.interface
101             print "USRP2 address:", self._u.mac_addr()
102             #print "Using TX d'board %s" % (self._u.tx_name(),)
103             print "Tx gain:", options.gain
104             print "Tx baseband frequency:", n2s(tr.baseband_freq), "Hz"
105             print "Tx DDC frequency:", n2s(tr.dxc_freq), "Hz"
106             print "Tx residual frequency:", n2s(tr.residual_freq), "Hz"
107             print "Tx interpolation rate:", options.interp
108             print "Tx GbE sample rate:", n2s(eth_rate), "samples/sec"
109             if options.type == gr.GR_SIN_WAVE:
110                 print "Baseband waveform type: Sine wave"
111                 print "Baseband waveform frequency:", n2s(options.waveform_freq), "Hz"
112             elif options.type == gr.GR_CONST_WAVE:
113                 print "Baseband waveform type: Constant"
114             elif options.type == gr.GR_GAUSSIAN:
115                 print "Baseband waveform type: Gaussian noise"
116             elif options.type == gr.GR_UNIFORM:
117                 print "Baseband waveform type: Uniform noise"           
118                             
119         # Wire the flowgraph
120         self.connect(self._src, self._u)
121             
122 def get_options():
123     usage="%prog: [options]"
124
125     parser = OptionParser(option_class=eng_option, usage=usage)
126     parser.add_option("-e", "--interface", type="string", default="eth0",
127                       help="use specified Ethernet interface [default=%default]")
128     parser.add_option("-m", "--mac-addr", type="string", default="",
129                       help="use USRP2 at specified MAC address [default=None]")  
130     parser.add_option("-i", "--interp", type="int", default=16,
131                       help="set fgpa decimation rate to DECIM [default=%default]")
132     parser.add_option("-g", "--gain", type="eng_float", default=None,
133                       help="set output gain to GAIN [default=%default]")
134     parser.add_option("-f", "--tx-freq", type="eng_float", default=None,
135                       help="set frequency to FREQ", metavar="FREQ")
136     parser.add_option("-v", "--verbose", action="store_true", default=False,
137                       help="verbose output")
138     parser.add_option("-w", "--waveform-freq", type="eng_float", default=0,
139                       help="set waveform frequency to FREQ [default=%default]")
140     parser.add_option("-x", "--waveform2-freq", type="eng_float", default=None,
141                       help="set waveform frequency to FREQ [default=%default]")
142     parser.add_option("-a", "--amplitude", type="eng_float", default=0.5,
143                       help="set waveform amplitude to AMPLITUDE (0-1.0) [default=%default]", metavar="AMPL")
144     parser.add_option("--offset", type="eng_float", default=0,
145                       help="set waveform offset to OFFSET [default=%default]")
146     parser.add_option("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE,
147                       help="generate a complex sinusoid [default]", default=gr.GR_SIN_WAVE)
148     parser.add_option("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE, 
149                       help="generate a constant output")
150     parser.add_option("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN,
151                       help="generate Gaussian random output")
152     parser.add_option("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
153                       help="generate Uniform random output")
154     parser.add_option("--2tone", dest="type", action="store_const", const="2tone",
155                       help="generate Two Tone signal for IMD testing")
156     parser.add_option("--sweep", dest="type", action="store_const", const="sweep",
157                       help="generate a swept sine wave")
158                       
159     (options, args) = parser.parse_args ()
160     if len(args) != 0:
161         parser.print_help()
162         raise SystemExit, 1
163     
164     if options.tx_freq is None:
165         parser.print_help()
166         sys.stderr.write('You must specify the frequency with -f FREQ\n');
167         raise SystemExit, 1
168     
169     return options
170
171
172 if __name__ == '__main__':
173     options = get_options()
174     tb = siggen_top_block(options)
175     
176     try:
177         tb.run()
178     except KeyboardInterrupt:
179         pass