f8ebb820d6f490b55cccff4cae8c8e35b47d6adf
[debian/gnuradio] / gnuradio-examples / python / ofdm / benchmark_ofdm_rx.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2005, 2006 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 2, 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, 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
28
29 import random, time, struct, sys, math
30
31 # from current dir
32 from receive_path import receive_path
33 import ofdm, fusb_options
34
35 class usrp_graph(gr.flow_graph):
36     def __init__(self, callback, options):
37         gr.flow_graph.__init__(self)
38
39         self._rx_freq            = options.rx_freq         # receiver's center frequency
40         self._rx_gain            = options.rx_gain         # receiver's gain
41         self._rx_subdev_spec     = options.rx_subdev_spec  # daughterboard to use
42         self._decim              = options.decim           # Decimating rate for the USRP (prelim)
43         self._fusb_block_size    = options.fusb_block_size # usb info for USRP
44         self._fusb_nblocks       = options.fusb_nblocks    # usb info for USRP
45
46         if self._rx_freq is None:
47             sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n")
48             raise SystemExit
49
50         # Set up USRP source
51         self._setup_usrp_source()
52         ok = self.set_freq(self._rx_freq)
53         if not ok:
54             print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(self._rx_freq))
55             raise ValueError, eng_notation.num_to_str(self._rx_freq)
56         g = self.subdev.gain_range()
57         if options.show_rx_gain_range:
58             print "Rx Gain Range: minimum = %g, maximum = %g, step size = %g" \
59                   % (g[0], g[1], g[2])
60         self.set_gain(options.rx_gain)
61         self.set_auto_tr(True)                 # enable Auto Transmit/Receive switching
62
63         # Set up receive path
64         self.rxpath = receive_path(self, callback, options)
65
66         self.connect(self.u, self.rxpath)
67
68     def _setup_usrp_source(self):
69         self.u = usrp.source_c (fusb_block_size=self._fusb_block_size,
70                                 fusb_nblocks=self._fusb_nblocks)
71         adc_rate = self.u.adc_rate()
72
73         self.u.set_decim_rate(self._decim)
74
75         # determine the daughterboard subdevice we're using
76         if self._rx_subdev_spec is None:
77             self._rx_subdev_spec = usrp.pick_rx_subdevice(self.u)
78         self.subdev = usrp.selected_subdev(self.u, self._rx_subdev_spec)
79
80         self.u.set_mux(usrp.determine_rx_mux_value(self.u, self._rx_subdev_spec))
81
82     def set_freq(self, target_freq):
83         """
84         Set the center frequency we're interested in.
85
86         @param target_freq: frequency in Hz
87         @rypte: bool
88
89         Tuning is a two step process.  First we ask the front-end to
90         tune as close to the desired frequency as it can.  Then we use
91         the result of that operation and our target_frequency to
92         determine the value for the digital up converter.
93         """
94         r = self.u.tune(0, self.subdev, target_freq)
95         if r:
96             return True
97
98         return False
99
100     def set_gain(self, gain):
101         """
102         Sets the analog gain in the USRP
103         """
104         if gain is None:
105             r = self.subdev.gain_range()
106             gain = (r[0] + r[1])/2               # set gain to midpoint
107         self.gain = gain
108         return self.subdev.set_gain(gain)
109
110     def set_auto_tr(self, enable):
111         return self.subdev.set_auto_tr(enable)
112
113     def decim(self):
114         return self._decim
115
116     def add_options(normal, expert):
117         """
118         Adds usrp-specific options to the Options Parser
119         """
120         add_freq_option(normal)
121         if not normal.has_option("--bitrate"):
122             normal.add_option("-r", "--bitrate", type="eng_float", default=None,
123                               help="specify bitrate.  samples-per-symbol and interp/decim will be derived.")
124         normal.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
125                           help="select USRP Rx side A or B")
126         normal.add_option("", "--rx-gain", type="eng_float", default=None, metavar="GAIN",
127                           help="set receiver gain in dB [default=midpoint].  See also --show-rx-gain-range")
128         normal.add_option("", "--show-rx-gain-range", action="store_true", default=False, 
129                           help="print min and max Rx gain available on selected daughterboard")
130         normal.add_option("-v", "--verbose", action="store_true", default=False)
131
132         expert.add_option("-S", "--samples-per-symbol", type="int", default=None,
133                           help="set samples/symbol [default=%default]")
134         expert.add_option("", "--rx-freq", type="eng_float", default=None,
135                           help="set Rx frequency to FREQ [default=%default]", metavar="FREQ")
136         expert.add_option("-d", "--decim", type="intx", default=32,
137                           help="set fpga decimation rate to DECIM [default=%default]")
138         expert.add_option("", "--snr", type="eng_float", default=30,
139                           help="set the SNR of the channel in dB [default=%default]")
140    
141
142     # Make a static method to call before instantiation
143     add_options = staticmethod(add_options)
144
145 def add_freq_option(parser):
146     """
147     Hackery that has the -f / --freq option set both tx_freq and rx_freq
148     """
149     def freq_callback(option, opt_str, value, parser):
150         parser.values.rx_freq = value
151         parser.values.tx_freq = value
152
153     if not parser.has_option('--freq'):
154         parser.add_option('-f', '--freq', type="eng_float",
155                           action="callback", callback=freq_callback,
156                           help="set Tx and/or Rx frequency to FREQ [default=%default]",
157                           metavar="FREQ")
158
159 # /////////////////////////////////////////////////////////////////////////////
160 #                                   main
161 # /////////////////////////////////////////////////////////////////////////////
162
163 def main():
164
165     global n_rcvd, n_right
166         
167     n_rcvd = 0
168     n_right = 0
169
170     def rx_callback(ok, payload):
171         global n_rcvd, n_right
172         n_rcvd += 1
173         (pktno,) = struct.unpack('!H', payload[0:2])
174         if ok:
175             n_right += 1
176         print "ok: %r \t pktno: %d \t n_rcvd: %d \t n_right: %d" % (ok, pktno, n_rcvd, n_right)
177
178     parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
179     expert_grp = parser.add_option_group("Expert")
180     parser.add_option("-r", "--sample-rate", type="eng_float", default=1e5,
181                       help="set sample rate to RATE (%default)") 
182
183     usrp_graph.add_options(parser, expert_grp)
184     receive_path.add_options(parser, expert_grp)
185     ofdm.ofdm_mod.add_options(parser, expert_grp)
186     fusb_options.add_options(expert_grp)
187
188     (options, args) = parser.parse_args ()
189
190     # build the graph
191     fg = usrp_graph(rx_callback, options)
192
193     r = gr.enable_realtime_scheduling()
194     if r != gr.RT_OK:
195         print "Warning: failed to enable realtime scheduling"
196
197     fg.start()                      # start flow graph
198     fg.wait()                       # wait for it to finish
199
200 if __name__ == '__main__':
201     try:
202         main()
203     except KeyboardInterrupt:
204         pass