1 | #!/usr/bin/env python
|
---|
2 |
|
---|
3 | from gnuradio import gr, gru
|
---|
4 | from gnuradio import usrp
|
---|
5 | from gnuradio.eng_option import eng_option
|
---|
6 | from gnuradio import eng_notation
|
---|
7 | from optparse import OptionParser
|
---|
8 | import sys
|
---|
9 |
|
---|
10 |
|
---|
11 | class my_graph(gr.flow_graph):
|
---|
12 | def __init__ (self,options):
|
---|
13 | gr.flow_graph.__init__(self)
|
---|
14 |
|
---|
15 | # controllable values
|
---|
16 | self.interp = options.interp #64
|
---|
17 | self.waveform_type = options.type #gr.GR_SIN_WAVE
|
---|
18 | self.waveform_ampl = options.amplitude #16000
|
---|
19 | self.waveform_freq = options.waveform_freq #1e3
|
---|
20 | self.waveform_offset = 0
|
---|
21 | self.siggap = options.siggap
|
---|
22 | self._instantiate_blocks ()
|
---|
23 | self.set_waveform_type (self.waveform_type,options.multiple,options.tofile)
|
---|
24 |
|
---|
25 | def usb_freq (self):
|
---|
26 | return self.u.dac_freq() / self.interp
|
---|
27 |
|
---|
28 | def usb_throughput (self):
|
---|
29 | return self.usb_freq () * 4
|
---|
30 |
|
---|
31 | def set_waveform_type (self, type,multiple,tofile):
|
---|
32 | '''
|
---|
33 | valid waveform types are: gr.GR_SIN_WAVE, gr.GR_CONST_WAVE,
|
---|
34 | gr.GR_UNIFORM and gr.GR_GAUSSIAN and gr.GR_IMPULSE
|
---|
35 | '''
|
---|
36 | self._configure_graph (type,multiple,tofile)
|
---|
37 | self.waveform_type = type
|
---|
38 |
|
---|
39 | def set_waveform_ampl (self, ampl):
|
---|
40 | self.waveform_ampl = ampl
|
---|
41 | self.siggen.set_amplitude (ampl)
|
---|
42 | self.siggen1.set_amplitude (ampl)
|
---|
43 | self.siggen2.set_amplitude (ampl)
|
---|
44 | self.siggen3.set_amplitude (ampl)
|
---|
45 | self.noisegen.set_amplitude (ampl)
|
---|
46 |
|
---|
47 | def set_waveform_freq (self, freq):
|
---|
48 | self.waveform_freq = freq
|
---|
49 | self.siggen.set_frequency (freq)
|
---|
50 | self.siggen1.set_frequency (freq+self.siggap*1)
|
---|
51 | self.siggen2.set_frequency (freq+self.siggap*2)
|
---|
52 | self.siggen3.set_frequency (freq+self.siggap*3)
|
---|
53 |
|
---|
54 | def set_waveform_offset (self, offset):
|
---|
55 | self.waveform_offset = offset
|
---|
56 | self.siggen.set_offset (offset)
|
---|
57 | self.siggen1.set_offset (offset)
|
---|
58 | self.siggen2.set_offset (offset)
|
---|
59 | self.siggen3.set_offset (offset)
|
---|
60 |
|
---|
61 | def set_interpolator (self, interp):
|
---|
62 | self.interp = interp
|
---|
63 | self.siggen.set_sampling_freq (self.usb_freq ())
|
---|
64 | self.siggen1.set_sampling_freq (self.usb_freq ())
|
---|
65 | self.siggen2.set_sampling_freq (self.usb_freq ())
|
---|
66 | self.siggen3.set_sampling_freq (self.usb_freq ())
|
---|
67 | self.u.set_interp_rate (interp)
|
---|
68 | print "sampling freq:",self.usb_freq()/1e6,"M"
|
---|
69 | print "dac_freq:",eng_notation.num_to_str(self.u.dac_freq())
|
---|
70 | print "interp rate:", self.interp
|
---|
71 |
|
---|
72 | def _instantiate_blocks (self):
|
---|
73 | self.src = None
|
---|
74 | self.u = usrp.sink_c (which=0, interp_rate=self.interp)
|
---|
75 |
|
---|
76 | #self.siggap = 100e3
|
---|
77 |
|
---|
78 | self.siggen = gr.sig_source_c (self.usb_freq (),
|
---|
79 | gr.GR_SIN_WAVE,
|
---|
80 | self.waveform_freq,
|
---|
81 | self.waveform_ampl,
|
---|
82 | self.waveform_offset)
|
---|
83 |
|
---|
84 | self.siggen1 = gr.sig_source_c(self.usb_freq(),
|
---|
85 | gr.GR_SIN_WAVE,
|
---|
86 | self.waveform_freq+self.siggap,
|
---|
87 | self.waveform_ampl,
|
---|
88 | self.waveform_offset)
|
---|
89 |
|
---|
90 | self.siggen2 = gr.sig_source_c(self.usb_freq(),
|
---|
91 | gr.GR_SIN_WAVE,
|
---|
92 | self.waveform_freq+self.siggap*2,
|
---|
93 | self.waveform_ampl,
|
---|
94 | self.waveform_offset)
|
---|
95 |
|
---|
96 | self.siggen3 = gr.sig_source_c(self.usb_freq(),
|
---|
97 | gr.GR_SIN_WAVE,
|
---|
98 | self.waveform_freq+self.siggap*3,
|
---|
99 | self.waveform_ampl,
|
---|
100 | self.waveform_offset)
|
---|
101 |
|
---|
102 | self.noisegen = gr.noise_source_c (gr.GR_UNIFORM,
|
---|
103 | self.waveform_ampl)
|
---|
104 | re = 8000
|
---|
105 | im = 8000j
|
---|
106 | tt = 8000+8000j
|
---|
107 | self.src_data = (re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,re,-re,-re,-re,-re,-re,-re,-re,-re,-re,-re,-re,-re,-re,-re,-re,-re) #(32*re, 16*)
|
---|
108 | self.vectgen = gr.vector_source_c(self.src_data, 1)
|
---|
109 | # self.file_sink = gr.file_sink (gr.sizeof_gr_complex, "siggen.dat")
|
---|
110 |
|
---|
111 | def _configure_graph (self, type,multiple,tofile):
|
---|
112 | was_running = self.is_running ()
|
---|
113 | if was_running:
|
---|
114 | self.stop ()
|
---|
115 | self.disconnect_all ()
|
---|
116 | if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
|
---|
117 | adder= gr.add_cc ()
|
---|
118 | if multiple == 2:
|
---|
119 | self.connect (self.siggen, (adder,0))
|
---|
120 | self.connect (self.siggen1,(adder,1))
|
---|
121 | elif multiple == 3:
|
---|
122 | self.connect (self.siggen, (adder,0))
|
---|
123 | self.connect (self.siggen1,(adder,1))
|
---|
124 | self.connect (self.siggen2,(adder,2))
|
---|
125 | elif multiple == 4:
|
---|
126 | self.connect (self.siggen, (adder,0))
|
---|
127 | self.connect (self.siggen1,(adder,1))
|
---|
128 | self.connect (self.siggen2,(adder,2))
|
---|
129 | self.connect (self.siggen3,(adder,3))
|
---|
130 | else:
|
---|
131 | self.connect (self.siggen, (adder,0))
|
---|
132 |
|
---|
133 | #self.connect (adder, self.u)
|
---|
134 | # self.connect (self.siggen, self.file_sink)
|
---|
135 | self.siggen.set_waveform (type)
|
---|
136 | self.siggen1.set_waveform(type)
|
---|
137 | self.siggen2.set_waveform(type)
|
---|
138 | self.siggen3.set_waveform(type)
|
---|
139 | self.src = adder
|
---|
140 | if tofile==0:
|
---|
141 | self.connect (adder, self.u)
|
---|
142 | print "sending out ",multiple, "sine waves to usrp "
|
---|
143 | else:
|
---|
144 | self.file_sink = gr.file_sink (gr.sizeof_gr_complex, "siggen.dat")
|
---|
145 | self.head = gr.head(gr.sizeof_gr_complex, 20000)
|
---|
146 | self.connect(self.src, self.head, self.file_sink)
|
---|
147 | print "sending out ",multiple, "sine waves to file "
|
---|
148 |
|
---|
149 | elif type == gr.GR_UNIFORM or type == gr.GR_GAUSSIAN:
|
---|
150 | self.connect (self.noisegen, self.u)
|
---|
151 | self.noisegen.set_type (type)
|
---|
152 | self.src = self.noisegen
|
---|
153 | elif type == gr.GR_IMPULSE:
|
---|
154 | self.connect (self.vectgen,self.u)
|
---|
155 | self.src = self.vectgen
|
---|
156 | else:
|
---|
157 | raise ValueError, type
|
---|
158 | if was_running:
|
---|
159 | self.start ()
|
---|
160 |
|
---|
161 | def set_freq(self, target_freq):
|
---|
162 | """
|
---|
163 | Set the center frequency we're interested in.
|
---|
164 |
|
---|
165 | @param target_freq: frequency in Hz
|
---|
166 | @rypte: bool
|
---|
167 |
|
---|
168 | Tuning is a two step process. First we ask the front-end to
|
---|
169 | tune as close to the desired frequency as it can. Then we use
|
---|
170 | the result of that operation and our target_frequency to
|
---|
171 | determine the value for the digital up converter.
|
---|
172 | """
|
---|
173 | r = self.u.tune(self.subdev._which, self.subdev, target_freq)
|
---|
174 | if r:
|
---|
175 | print "r.baseband_freq =", eng_notation.num_to_str(r.baseband_freq)
|
---|
176 | print "r.dxc_freq =", eng_notation.num_to_str(r.dxc_freq)
|
---|
177 | print "r.residual_freq =", eng_notation.num_to_str(r.residual_freq)
|
---|
178 | print "r.inverted =", r.inverted
|
---|
179 | return True
|
---|
180 |
|
---|
181 | return False
|
---|
182 |
|
---|
183 |
|
---|
184 |
|
---|
185 | def main ():
|
---|
186 | parser = OptionParser (option_class=eng_option)
|
---|
187 | parser.add_option ("-T", "--tx-subdev-spec", type="subdev", default=(0, 0),
|
---|
188 | help="select USRP Tx side A or B")
|
---|
189 | parser.add_option ("-f", "--rf-freq", type="eng_float", default=None,
|
---|
190 | help="set RF center frequency to FREQ")
|
---|
191 | parser.add_option ("-i", "--interp", type="int", default=64,
|
---|
192 | help="set fgpa interpolation rate to INTERP")
|
---|
193 |
|
---|
194 | parser.add_option ("-m", "--multiple", type="int", default=1,
|
---|
195 | help="set the number of sine wave to add on")
|
---|
196 | parser.add_option ("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE,
|
---|
197 | help="generate a complex sinusoid [default]", default=gr.GR_SIN_WAVE)
|
---|
198 | parser.add_option ("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE,
|
---|
199 | help="generate a constant output")
|
---|
200 | parser.add_option ("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN,
|
---|
201 | help="generate Gaussian random output")
|
---|
202 | parser.add_option ("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
|
---|
203 | help="generate Uniform random output")
|
---|
204 |
|
---|
205 | parser.add_option ("--impulse", dest="type", action="store_const", const=gr.GR_IMPULSE,
|
---|
206 | help="generate a impulse signal", default=gr.GR_IMPULSE)
|
---|
207 | parser.add_option ("-w", "--waveform-freq", type="eng_float", default=100e3,
|
---|
208 | help="set waveform frequency to FREQ")
|
---|
209 | parser.add_option ("-l", "--tofile", type="int", default=0,
|
---|
210 | help="set whether dump the data to a file 1 true 0 false")
|
---|
211 | parser.add_option ("-a", "--amplitude", type="eng_float", default=16e3,
|
---|
212 | help="set waveform amplitude to AMPLITUDE", metavar="AMPL")
|
---|
213 | parser.add_option ("-o", "--offset", type="eng_float", default=0,
|
---|
214 | help="set waveform offset to OFFSET")
|
---|
215 | parser.add_option ("-g", "--siggap", type="eng_float", default=100e3,
|
---|
216 | help="set the gap between two waveforms")
|
---|
217 | (options, args) = parser.parse_args ()
|
---|
218 |
|
---|
219 | if len(args) != 0:
|
---|
220 | parser.print_help()
|
---|
221 | raise SystemExit
|
---|
222 |
|
---|
223 | if options.rf_freq is None:
|
---|
224 | sys.stderr.write("usrp_siggen: must specify RF center frequency with -f RF_FREQ\n")
|
---|
225 | parser.print_help()
|
---|
226 | raise SystemExit
|
---|
227 |
|
---|
228 | fg = my_graph(options)
|
---|
229 | fg.set_interpolator (options.interp)
|
---|
230 | #fg.set_waveform_type (options.type,options.multiple)
|
---|
231 | #fg.set_waveform_freq (options.waveform_freq)
|
---|
232 | #fg.set_waveform_ampl (options.amplitude)
|
---|
233 | #fg.set_waveform_offset (options.offset)
|
---|
234 |
|
---|
235 | # determine the daughterboard subdevice we're using
|
---|
236 | if options.tx_subdev_spec is None:
|
---|
237 | options.tx_subdev_spec = usrp.pick_tx_subdevice(fg.u)
|
---|
238 |
|
---|
239 | m = usrp.determine_tx_mux_value(fg.u, options.tx_subdev_spec)
|
---|
240 | print "mux = %#04x" % (m,)
|
---|
241 | fg.u.set_mux(m)
|
---|
242 | #fg.u.set_mux(0x98)
|
---|
243 | fg.subdev = usrp.selected_subdev(fg.u, options.tx_subdev_spec)
|
---|
244 | print "Using TX d'board %s" % (fg.subdev.side_and_name(),)
|
---|
245 |
|
---|
246 | fg.subdev.set_gain(fg.subdev.gain_range()[1]) # set max Tx gain
|
---|
247 |
|
---|
248 | if not fg.set_freq(options.rf_freq):
|
---|
249 | sys.stderr.write('Failed to set RF frequency\n')
|
---|
250 | raise SystemExit
|
---|
251 |
|
---|
252 | fg.subdev.set_enable(True) # enable transmitter
|
---|
253 |
|
---|
254 | try:
|
---|
255 | #fg.run()
|
---|
256 | fg.start()
|
---|
257 | raw_input ('Press Enter to quit: ')
|
---|
258 | fg.stop ()
|
---|
259 | except KeyboardInterrupt:
|
---|
260 | pass
|
---|
261 |
|
---|
262 | if __name__ == '__main__':
|
---|
263 | main ()
|
---|