Imported Upstream version 3.2.2
[debian/gnuradio] / gnuradio-examples / python / ofdm / benchmark_ofdm_rx.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2006, 2007 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 3, 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, blks2
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 struct, sys
30
31 # from current dir
32 from receive_path import receive_path
33 import fusb_options
34
35 class my_top_block(gr.top_block):
36     def __init__(self, callback, options):
37         gr.top_block.__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(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         normal.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
122                           help="select USRP Rx side A or B")
123         normal.add_option("", "--rx-gain", type="eng_float", default=None, metavar="GAIN",
124                           help="set receiver gain in dB [default=midpoint].  See also --show-rx-gain-range")
125         normal.add_option("", "--show-rx-gain-range", action="store_true", default=False, 
126                           help="print min and max Rx gain available on selected daughterboard")
127         normal.add_option("-v", "--verbose", action="store_true", default=False)
128
129         expert.add_option("", "--rx-freq", type="eng_float", default=None,
130                           help="set Rx frequency to FREQ [default=%default]", metavar="FREQ")
131         expert.add_option("-d", "--decim", type="intx", default=128,
132                           help="set fpga decimation rate to DECIM [default=%default]")
133         expert.add_option("", "--snr", type="eng_float", default=30,
134                           help="set the SNR of the channel in dB [default=%default]")
135    
136
137     # Make a static method to call before instantiation
138     add_options = staticmethod(add_options)
139
140 def add_freq_option(parser):
141     """
142     Hackery that has the -f / --freq option set both tx_freq and rx_freq
143     """
144     def freq_callback(option, opt_str, value, parser):
145         parser.values.rx_freq = value
146         parser.values.tx_freq = value
147
148     if not parser.has_option('--freq'):
149         parser.add_option('-f', '--freq', type="eng_float",
150                           action="callback", callback=freq_callback,
151                           help="set Tx and/or Rx frequency to FREQ [default=%default]",
152                           metavar="FREQ")
153
154 # /////////////////////////////////////////////////////////////////////////////
155 #                                   main
156 # /////////////////////////////////////////////////////////////////////////////
157
158 def main():
159
160     global n_rcvd, n_right
161         
162     n_rcvd = 0
163     n_right = 0
164
165     def rx_callback(ok, payload):
166         global n_rcvd, n_right
167         n_rcvd += 1
168         (pktno,) = struct.unpack('!H', payload[0:2])
169         if ok:
170             n_right += 1
171         print "ok: %r \t pktno: %d \t n_rcvd: %d \t n_right: %d" % (ok, pktno, n_rcvd, n_right)
172
173         if 0:
174             printlst = list()
175             for x in payload[2:]:
176                 t = hex(ord(x)).replace('0x', '')
177                 if(len(t) == 1):
178                     t = '0' + t
179                 printlst.append(t)
180             printable = ''.join(printlst)
181
182             print printable
183             print "\n"
184
185     parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
186     expert_grp = parser.add_option_group("Expert")
187     parser.add_option("","--discontinuous", action="store_true", default=False,
188                       help="enable discontinuous")
189
190     my_top_block.add_options(parser, expert_grp)
191     receive_path.add_options(parser, expert_grp)
192     blks2.ofdm_mod.add_options(parser, expert_grp)
193     blks2.ofdm_demod.add_options(parser, expert_grp)
194     fusb_options.add_options(expert_grp)
195
196     (options, args) = parser.parse_args ()
197
198     # build the graph
199     tb = my_top_block(rx_callback, options)
200
201     r = gr.enable_realtime_scheduling()
202     if r != gr.RT_OK:
203         print "Warning: failed to enable realtime scheduling"
204
205     tb.start()                      # start flow graph
206     tb.wait()                       # wait for it to finish
207
208 if __name__ == '__main__':
209     try:
210         main()
211     except KeyboardInterrupt:
212         pass