3 # Copyright 2005, 2006 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 2, 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, gru, modulation_utils
24 from gnuradio import usrp
25 from gnuradio import eng_notation
26 from gnuradio.eng_option import eng_option
27 from optparse import OptionParser
29 import random, time, struct, sys, math
32 from transmit_path import transmit_path
33 from pick_bitrate import pick_tx_bitrate
34 import ofdm, fusb_options
36 class usrp_graph(gr.flow_graph):
37 def __init__(self, options):
38 gr.flow_graph.__init__(self)
40 self._tx_freq = options.tx_freq # tranmitter's center frequency
41 self._tx_subdev_spec = options.tx_subdev_spec # daughterboard to use
42 self._bitrate = options.bitrate # desired bit rate
43 self._interp = options.interp # interpolating rate for the USRP (prelim)
44 self._fusb_block_size = options.fusb_block_size # usb info for USRP
45 self._fusb_nblocks = options.fusb_nblocks # usb info for USRP
47 if self._tx_freq is None:
48 sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n")
51 # Set up USRP sink; also adjusts interp, and bitrate
52 self._setup_usrp_sink()
54 # copy the final answers back into options for use by modulator
55 #options.bitrate = self._bitrate
57 self.txpath = transmit_path(self, options)
59 self.connect(self.txpath, self.u)
61 def _setup_usrp_sink(self):
63 Creates a USRP sink, determines the settings for best bitrate,
64 and attaches to the transmitter's subdevice.
66 self.u = usrp.sink_c(fusb_block_size=self._fusb_block_size,
67 fusb_nblocks=self._fusb_nblocks)
69 self.u.set_interp_rate(self._interp)
71 # determine the daughterboard subdevice we're using
72 if self._tx_subdev_spec is None:
73 self._tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
74 self.u.set_mux(usrp.determine_tx_mux_value(self.u, self._tx_subdev_spec))
75 self.subdev = usrp.selected_subdev(self.u, self._tx_subdev_spec)
77 # Set center frequency of USRP
78 ok = self.set_freq(self._tx_freq)
80 print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(self._tx_freq),)
83 # Set the USRP for maximum transmit gain
84 # (Note that on the RFX cards this is a nop.)
85 self.set_gain(self.subdev.gain_range()[0])
87 # enable Auto Transmit/Receive switching
88 self.set_auto_tr(True)
90 def set_freq(self, target_freq):
92 Set the center frequency we're interested in.
94 @param target_freq: frequency in Hz
97 Tuning is a two step process. First we ask the front-end to
98 tune as close to the desired frequency as it can. Then we use
99 the result of that operation and our target_frequency to
100 determine the value for the digital up converter.
102 r = self.u.tune(self.subdev._which, self.subdev, target_freq)
108 def set_gain(self, gain):
110 Sets the analog gain in the USRP
113 self.subdev.set_gain(gain)
115 def set_auto_tr(self, enable):
117 Turns on auto transmit/receive of USRP daughterboard (if exits; else ignored)
119 return self.subdev.set_auto_tr(enable)
124 def add_options(normal, expert):
126 Adds usrp-specific options to the Options Parser
128 add_freq_option(normal)
129 if not normal.has_option('--bitrate'):
130 normal.add_option("-r", "--bitrate", type="eng_float", default=None,
131 help="specify bitrate. samples-per-symbol and interp/decim will be derived.")
132 normal.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
133 help="select USRP Tx side A or B")
134 normal.add_option("-v", "--verbose", action="store_true", default=False)
136 expert.add_option("-S", "--samples-per-symbol", type="int", default=None,
137 help="set samples/symbol [default=%default]")
138 expert.add_option("", "--tx-freq", type="eng_float", default=None,
139 help="set transmit frequency to FREQ [default=%default]", metavar="FREQ")
140 expert.add_option("-i", "--interp", type="intx", default=64,
141 help="set fpga interpolation rate to INTERP [default=%default]")
142 # Make a static method to call before instantiation
143 add_options = staticmethod(add_options)
145 def _print_verbage(self):
147 Prints information about the transmit path
149 print "Using TX d'board %s" % (self.subdev.side_and_name(),)
150 print "modulation: %s" % (self._modulator_class.__name__)
151 print "interp: %3d" % (self._interp)
152 print "Tx Frequency: %s" % (eng_notation.num_to_str(self._tx_freq))
155 def add_freq_option(parser):
157 Hackery that has the -f / --freq option set both tx_freq and rx_freq
159 def freq_callback(option, opt_str, value, parser):
160 parser.values.rx_freq = value
161 parser.values.tx_freq = value
163 if not parser.has_option('--freq'):
164 parser.add_option('-f', '--freq', type="eng_float",
165 action="callback", callback=freq_callback,
166 help="set Tx and/or Rx frequency to FREQ [default=%default]",
169 # /////////////////////////////////////////////////////////////////////////////
171 # /////////////////////////////////////////////////////////////////////////////
175 def send_pkt(payload='', eof=False):
176 return fg.txpath.send_pkt(payload, eof)
178 parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
179 expert_grp = parser.add_option_group("Expert")
180 parser.add_option("-s", "--size", type="eng_float", default=1450,
181 help="set packet size [default=%default]")
182 parser.add_option("-M", "--megabytes", type="eng_float", default=1.0,
183 help="set megabytes to transmit [default=%default]")
184 parser.add_option("-r", "--sample-rate", type="eng_float", default=1e5,
185 help="set sample rate to RATE (%default)")
187 usrp_graph.add_options(parser, expert_grp)
188 transmit_path.add_options(parser, expert_grp)
189 ofdm.ofdm_mod.add_options(parser, expert_grp)
190 fusb_options.add_options(expert_grp)
192 (options, args) = parser.parse_args ()
194 if(options.mtu < options.size):
195 sys.stderr.write("MTU (%.0f) must be larger than the packet size (%.0f)\n"
196 % (options.mtu, options.size))
200 fg = usrp_graph(options)
202 r = gr.enable_realtime_scheduling()
204 print "Warning: failed to enable realtime scheduling"
206 fg.start() # start flow graph
208 # generate and send packets
209 nbytes = int(1e6 * options.megabytes)
212 pkt_size = int(options.size)
215 send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff))
217 sys.stderr.write('.')
218 #if options.discontinuous and pktno % 5 == 4:
223 fg.wait() # wait for it to finish
225 if __name__ == '__main__':
228 except KeyboardInterrupt: