Updated license from GPL version 2 or later to GPL version 3 or later.
[debian/gnuradio] / gr-pager / src / usrp_flex.py
1 #!/usr/bin/env python
2
3 #
4 # Copyright 2006,2007 Free Software Foundation, Inc.
5
6 # This file is part of GNU Radio
7
8 # GNU Radio is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3, or (at your option)
11 # any later version.
12
13 # GNU Radio is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17
18 # You should have received a copy of the GNU General Public License
19 # along with GNU Radio; see the file COPYING.  If not, write to
20 # the Free Software Foundation, Inc., 51 Franklin Street,
21 # Boston, MA 02110-1301, USA.
22
23
24 from gnuradio import gr, gru, usrp, optfir, eng_notation, blks, pager
25 from gnuradio.eng_option import eng_option
26 from optparse import OptionParser
27 import time, os, sys
28 from string import split, join
29
30 """
31 This example application demonstrates receiving and demodulating the
32 FLEX pager protocol.
33
34 The following are required command line parameters:
35
36 -f FREQ     USRP receive frequency
37
38 The following are optional command line parameters:
39
40 -R SUBDEV   Daughter board specification, defaults to first found
41 -F FILE     Read samples from a file instead of USRP.
42 -c FREQ     Calibration offset.  Gets added to receive frequency.
43             Defaults to 0.0 Hz.
44 -g GAIN     Daughterboard gain setting. Defaults to mid-range.
45 -l          Log flow graph to files (LOTS of data)
46 -v          Verbose output
47
48 Once the program is running, ctrl-break (Ctrl-C) stops operation.
49 """
50
51 class app_top_block(gr.top_block):
52     def __init__(self, options, queue):
53         gr.top_block.__init__(self, "usrp_flex")
54         self.options = options
55         self.offset = 0.0
56         self.adj_time = time.time()
57         self.verbose = options.verbose
58                         
59         if options.from_file is None:
60             # Set up USRP source with specified RX daughterboard
61             self.src = usrp.source_c()
62             if options.rx_subdev_spec == None:
63                 options.rx_subdev_spec = usrp.pick_rx_subdevice(self.src)
64             self.subdev = usrp.selected_subdev(self.src, options.rx_subdev_spec)
65             self.src.set_mux(usrp.determine_rx_mux_value(self.src, options.rx_subdev_spec))
66
67             # Grab 250 KHz of spectrum (sample rate becomes 250 ksps complex)
68             self.src.set_decim_rate(256)
69                     
70             # If no gain specified, set to midrange
71             if options.gain is None:
72                 g = self.subdev.gain_range()
73                 options.gain = (g[0]+g[1])/2.0
74             self.subdev.set_gain(options.gain)
75
76             # Tune daughterboard
77             actual_frequency = options.frequency+options.calibration
78             tune_result = usrp.tune(self.src, 0, self.subdev, actual_frequency)
79             if not tune_result:
80                 sys.stderr.write("Failed to set center frequency to "+`actual_frequency`+"\n")
81                 sys.exit(1)
82
83             if options.verbose:
84                 print "Using RX daughterboard", self.subdev.side_and_name()
85                 print "USRP gain is", options.gain
86                 print "USRP tuned to", actual_frequency
87             
88         else:
89             # Use supplied file as source of samples
90             self.src = gr.file_source(gr.sizeof_gr_complex, options.from_file)
91             if options.verbose:
92                 print "Reading samples from", options.from_file
93             
94         if options.log and not options.from_file:
95             usrp_sink = gr.file_sink(gr.sizeof_gr_complex, 'usrp.dat')
96             self.connect(self.src, usrp_sink)
97
98         # Set up 22KHz-wide bandpass about center frequency. Decimate by 10
99         # to get channel rate of 25Ksps
100         taps = optfir.low_pass(1.0,   # Filter gain
101                                250e3, # Sample rate
102                                11000, # One-sided modulation bandwidth
103                                12500, # One-sided channel bandwidth
104                                0.1,   # Passband ripple
105                                60)    # Stopband attenuation
106         
107         if options.verbose:
108             print "Channel filter has", len(taps), "taps."
109
110         self.chan = gr.freq_xlating_fir_filter_ccf(10,    # Decimation rate
111                                               taps,  # Filter taps
112                                               0.0,   # Offset frequency
113                                               250e3) # Sample rate
114
115         if options.log:
116             chan_sink = gr.file_sink(gr.sizeof_gr_complex, 'chan.dat')
117             self.connect(self.chan, chan_sink)
118
119         # FLEX protocol demodulator
120         self.flex = pager.flex_demod(queue, options.frequency, options.verbose, options.log)
121
122         self.connect(self.src, self.chan, self.flex)
123
124     def freq_offset(self):
125         return self.flex.dc_offset()*1600
126
127     def adjust_freq(self):
128         if time.time() - self.adj_time > 1.6:   # Only do it once per FLEX frame
129             self.adj_time = time.time()
130             self.offset -= self.freq_offset()
131             self.chan.set_center_freq(self.offset)
132             if self.verbose:
133                 print "Channel frequency offset (Hz):", int(self.offset)
134                         
135 def main():
136     parser = OptionParser(option_class=eng_option)
137     parser.add_option("-f", "--frequency", type="eng_float", default=None,
138                       help="set receive frequency to Hz", metavar="Hz")
139     parser.add_option("-R", "--rx-subdev-spec", type="subdev",
140                       help="select USRP Rx side A or B", metavar="SUBDEV")
141     parser.add_option("-c",   "--calibration", type="eng_float", default=0.0,
142                       help="set frequency offset to Hz", metavar="Hz")
143     parser.add_option("-g", "--gain", type="int", default=None,
144                       help="set RF gain", metavar="dB")
145     parser.add_option("-l", "--log", action="store_true", default=False,
146                       help="log flowgraph to files (LOTS of data)")
147     parser.add_option("-v", "--verbose", action="store_true", default=False,
148                       help="display debug output")
149     parser.add_option("-F", "--from-file", default=None,
150                       help="read samples from file instead of USRP")
151     (options, args) = parser.parse_args()
152
153     if len(args) > 0 or (options.frequency == None and options.from_file == None):
154         print "Run 'usrp_flex.py -h' for options."
155         sys.exit(1)
156
157     if options.frequency == None:
158         options.frequency = 0.0
159
160     # Flow graph emits pages into message queue
161     queue = gr.msg_queue()
162     tb = app_top_block(options, queue)
163     r = gr.runtime(tb)
164     
165     try:
166         r.start()
167         while 1:
168             if not queue.empty_p():
169                 msg = queue.delete_head() # Blocking read
170                 page = join(split(msg.to_string(), chr(128)), '|')
171                 disp = []
172                 for n in range(len(page)):
173                     if ord(page[n]) < 32:
174                         disp.append('.')
175                     else:
176                         disp.append(page[n])
177                 print join(disp, '')
178                 tb.adjust_freq()
179                                                                                 
180             else:
181                 time.sleep(1)
182
183     except KeyboardInterrupt:
184         r.stop()
185
186 if __name__ == "__main__":
187     main()