| 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 () |
|---|