4 Transmit N simultaneous narrow band FM signals.
6 They will be centered at the frequency specified on the command line,
7 and will spaced at 25kHz steps from there.
9 The program opens N files with names audio-N.dat where N is in [0,7].
10 These files should contain floating point audio samples in the range [-1,1]
11 sampled at 32kS/sec. You can create files like this using
15 from gnuradio import gr, eng_notation
16 from gnuradio import usrp
17 from gnuradio import audio
18 from gnuradio import blks
19 from gnuradio.eng_option import eng_option
20 from optparse import OptionParser
21 from usrpm import usrp_dbid
25 from gnuradio.wxgui import stdgui, fftsink
26 from gnuradio import tx_debug_gui
30 ########################################################
31 # instantiate one transmit chain for each call
33 class pipeline(gr.hier_block):
34 def __init__(self, fg, filename, lo_freq, audio_rate, if_rate):
36 src = gr.file_source (gr.sizeof_float, filename, True)
37 fmtx = blks.nbfm_tx (fg, audio_rate, if_rate,
38 max_dev=5e3, tau=75e-6)
41 lo = gr.sig_source_c (if_rate, # sample rate
42 gr.GR_SIN_WAVE, # waveform type
46 mixer = gr.multiply_cc ()
48 fg.connect (src, fmtx, (mixer, 0))
49 fg.connect (lo, (mixer, 1))
51 gr.hier_block.__init__(self, fg, src, mixer)
55 class fm_tx_graph (stdgui.gui_flow_graph):
56 def __init__(self, frame, panel, vbox, argv):
58 stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
60 parser = OptionParser (option_class=eng_option)
61 parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
62 help="select USRP Tx side A or B")
63 parser.add_option("-f", "--freq", type="eng_float", default=None,
64 help="set Tx frequency to FREQ [required]", metavar="FREQ")
65 parser.add_option("-n", "--nchannels", type="int", default=4,
66 help="number of Tx channels [1,4]")
67 parser.add_option("","--debug", action="store_true", default=False,
68 help="Launch Tx debugger")
69 (options, args) = parser.parse_args ()
75 if options.nchannels < 1 or options.nchannels > MAX_CHANNELS:
76 sys.stderr.write ("fm_tx4: nchannels out of range. Must be in [1,%d]\n" % MAX_CHANNELS)
79 if options.freq is None:
80 sys.stderr.write("fm_tx4: must specify frequency with -f FREQ\n")
84 # ----------------------------------------------------------------
85 # Set up constants and parameters
87 self.u = usrp.sink_c () # the USRP sink (consumes samples)
89 self.dac_rate = self.u.dac_rate() # 128 MS/s
90 self.usrp_interp = 400
91 self.u.set_interp_rate(self.usrp_interp)
92 self.usrp_rate = self.dac_rate / self.usrp_interp # 320 kS/s
94 self.audio_rate = self.usrp_rate / self.sw_interp # 32 kS/s
96 # determine the daughterboard subdevice we're using
97 if options.tx_subdev_spec is None:
98 options.tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
100 m = usrp.determine_tx_mux_value(self.u, options.tx_subdev_spec)
101 #print "mux = %#04x" % (m,)
103 self.subdev = usrp.selected_subdev(self.u, options.tx_subdev_spec)
104 print "Using TX d'board %s" % (self.subdev.side_and_name(),)
106 self.subdev.set_gain(self.subdev.gain_range()[1]) # set max Tx gain
107 if not self.set_freq(options.freq):
108 freq_range = self.subdev.freq_range()
109 print "Failed to set frequency to %s. Daughterboard supports %s to %s" % (
110 eng_notation.num_to_str(options.freq),
111 eng_notation.num_to_str(freq_range[0]),
112 eng_notation.num_to_str(freq_range[1]))
114 self.subdev.set_enable(True) # enable transmitter
118 # Instantiate N NBFM channels
120 offset = (0 * step, 1 * step, -1 * step, 2 * step, -2 * step, 3 * step, -3 * step)
121 for i in range (options.nchannels):
122 t = pipeline (self, "audio-%d.dat" % (i % 4), offset[i],
123 self.audio_rate, self.usrp_rate)
124 self.connect (t, (sum, i))
126 gain = gr.multiply_const_cc (4000.0 / options.nchannels)
129 self.connect (sum, gain)
130 self.connect (gain, self.u)
132 # plot an FFT to verify we are sending what we want
134 post_mod = fftsink.fft_sink_c(self, panel, title="Post Modulation",
135 fft_size=512, sample_rate=self.usrp_rate,
136 y_per_div=20, ref_level=40)
137 self.connect (sum, post_mod)
138 vbox.Add (post_mod.win, 1, wx.EXPAND)
142 self.debugger = tx_debug_gui.tx_debug_gui(self.subdev)
143 self.debugger.Show(True)
146 def set_freq(self, target_freq):
148 Set the center frequency we're interested in.
150 @param target_freq: frequency in Hz
153 Tuning is a two step process. First we ask the front-end to
154 tune as close to the desired frequency as it can. Then we use
155 the result of that operation and our target_frequency to
156 determine the value for the digital up converter. Finally, we feed
157 any residual_freq to the s/w freq translater.
160 r = self.u.tune(self.subdev._which, self.subdev, target_freq)
162 print "r.baseband_freq =", eng_notation.num_to_str(r.baseband_freq)
163 print "r.dxc_freq =", eng_notation.num_to_str(r.dxc_freq)
164 print "r.residual_freq =", eng_notation.num_to_str(r.residual_freq)
165 print "r.inverted =", r.inverted
167 # Could use residual_freq in s/w freq translator
173 app = stdgui.stdapp (fm_tx_graph, "Multichannel FM Tx")
176 if __name__ == '__main__':