Merged r5463:5504 from jcorgan/snd into trunk. Work in progress, adds digital loopbac...
[debian/gnuradio] / gr-sounder / src / python / usrp_sounder.py
1 #!/usr/bin/env python
2 #
3 # Copyright 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 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, usrp
24 from gnuradio import eng_notation
25 from gnuradio.eng_option import eng_option
26 from optparse import OptionParser
27 import sys, time
28
29 n2s = eng_notation.num_to_str
30
31 FR_MODE = usrp.FR_USER_0
32 bmFR_MODE_RESET = 1 << 0        # bit 0: active high reset
33 bmFR_MODE_TX    = 1 << 1        # bit 1: enable transmitter
34 bmFR_MODE_RX    = 1 << 2        # bit 2: enable receiver
35 bmFR_MODE_LP    = 1 << 3        # bit 3: enable digital loopback
36
37 FR_DEGREE = usrp.FR_USER_1
38
39 class sounder:
40     def __init__(self, options):
41         self._options = options
42         self._mode = 0
43         
44         self._u = None
45         self._trans = None
46         self._rcvr = None
47         self._transmitting = False
48         self._receiving = False
49                 
50         if options.transmit:
51             print "Creating sounder transmitter."
52             self._trans = usrp.sink_s(fpga_filename='usrp_sounder.rbf')
53             self._trans_subdev_spec = usrp.pick_tx_subdevice(self._trans)
54             self._trans_subdev = usrp.selected_subdev(self._trans, self._trans_subdev_spec)
55             self._trans.start()
56             self._u = self._trans
57                 
58         if options.receive:
59             print "Creating sounder receiver."
60             self._fg = gr.flow_graph()
61             self._rcvr = usrp.source_s(fpga_filename='usrp_sounder.rbf', decim_rate=128)
62             self._rcvr_subdev_spec = usrp.pick_rx_subdevice(self._rcvr)
63             self._rcvr_subdev = usrp.selected_subdev(self._rcvr, self._rcvr_subdev_spec)
64             self._sink = gr.file_sink(gr.sizeof_short, "output.dat")
65
66             if options.samples >= 0:
67                 self._head = gr.head(gr.sizeof_short, options.samples*gr.sizeof_short)
68                 self._fg.connect(self._rcvr, self._head, self._sink)
69             else:
70                 self._fg.connect(self._rcvr, self._sink)
71             self._u = self._rcvr # either receiver or transmitter object will do
72         
73         self.set_reset(True)
74         self.set_freq(options.frequency)
75         self.set_degree(options.degree)
76         self.set_loopback(options.loopback)     
77         self.set_reset(False)
78                 
79     def set_freq(self, frequency):
80         print "Setting center frequency to", n2s(frequency)
81         if self._rcvr:
82             self._rcvr.tune(0, self._rcvr_subdev, frequency)
83         
84         if self._trans:
85             self._trans.tune(0, self._trans_subdev, frequency)
86
87     def set_degree(self, degree):
88         print "Setting PN code degree to", degree
89         self._u._write_fpga_reg(FR_DEGREE, degree);
90             
91     def _write_mode(self):
92         print "Writing mode register with:", hex(self._mode)
93         self._u._write_fpga_reg(FR_MODE, self._mode)
94
95     def enable_tx(self, value):
96         if value:
97             print "Enabling transmitter."
98             self._mode |= bmFR_MODE_TX
99             self._transmitting = True
100         else:
101             print "Disabling transmitter."
102             self._mode &= ~bmFR_MODE_TX
103         self._write_mode()
104                     
105     def enable_rx(self, value):
106         if value:
107             print "Starting receiver flow graph."
108             self._mode |= bmFR_MODE_RX
109             self._write_mode()
110             self._fg.start()
111             self._receiving = True
112             if self._options.samples >= 0:
113                 self._fg.wait()
114         else:
115             print "Stopping receiver flow graph."
116             if self._options.samples < 0:
117                 self._fg.stop()
118                 print "Waiting for threads..."
119                 self._fg.wait()
120                 print "Receiver flow graph stopped."
121             self._mode &= ~bmFR_MODE_RX
122             self._write_mode()
123             self._receiving = False
124                 
125     def set_loopback(self, value):
126         if value:
127             print "Enabling digital loopback."
128             self._mode |= bmFR_MODE_LP
129         else:
130             print "Disabling digital loopback."
131             self._mode &= ~bmFR_MODE_LP
132         self._write_mode()
133
134     def set_reset(self, value):
135         if value:
136             print "Asserting reset."
137             self._mode |= bmFR_MODE_RESET
138         else:
139             print "De-asserting reset."
140             self._mode &= ~bmFR_MODE_RESET
141         self._write_mode()
142
143     def __del__(self):
144         if self._transmitting:
145             self.enable_tx(False)
146             
147         if self._receiving:
148             self.enable_rx(False)
149             
150 # ------------------------------------------------------------------------------
151     
152 def main():
153     parser = OptionParser(option_class=eng_option)
154     parser.add_option("-f", "--frequency", type="eng_float", default=0.0,
155                       help="set frequency to FREQ in Hz, default is %default", metavar="FREQ")
156
157     parser.add_option("-d", "--degree", type="int", default=16,
158                       help="set souding sequence degree (len=2^degree-1), default is %default")
159
160     parser.add_option("-t", "--transmit", action="store_true", default=False,
161                       help="enable sounding transmitter")
162
163     parser.add_option("-r", "--receive", action="store_true", default=False,
164                       help="enable sounding receiver")
165
166     parser.add_option("-n", "--samples", type="int", default=-1,
167                       help="number of samples to capture on receive, default is infinite")
168
169     parser.add_option("-l", "--loopback", action="store_true", default=False,
170                       help="enable digital loopback, default is disabled")
171
172     (options, args) = parser.parse_args()
173
174     if len(args) != 0 or not (options.transmit | options.receive):
175         parser.print_help()
176         sys.exit(1)
177
178     print "Using PN code degree of", options.degree, "length", 2**options.degree-1
179     print "Sounding frequency range is", n2s(options.frequency-16e6), "to", n2s(options.frequency+16e6)
180     
181     s = sounder(options)
182
183     if options.transmit:
184         s.enable_tx(True)
185
186     if options.receive:
187         s.enable_rx(True)
188
189     if options.samples < 0:
190         raw_input("Press enter to exit.")
191         
192 if __name__ == "__main__":
193     main()