1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#!/usr/bin/env python
from gnuradio import gr, gru, usrp, optfir, eng_notation, blks, pager
from gnuradio.eng_option import eng_option
from optparse import OptionParser
import time, os, sys
from string import split, join
"""
This example application demonstrates receiving and demodulating the
FLEX pager protocol.
A receive chain is built up of the following signal processing
blocks:
USRP - Daughter board source generating complex baseband signal.
CHAN - Low pass filter to select channel bandwidth
AGC - Automatic gain control leveling signal at [-1.0, +1.0]
FLEX - FLEX pager protocol decoder
The following are required command line parameters:
-f FREQ USRP receive frequency
The following are optional command line parameters:
-R SUBDEV Daughter board specification, defaults to first found
-c FREQ Calibration offset. Gets added to receive frequency.
Defaults to 0.0 Hz.
-g GAIN Daughterboard gain setting. Defaults to mid-range.
-r RFSQL RF squelch in db. Defaults to -50.0.
Once the program is running, ctrl-break (Ctrl-C) stops operation.
"""
class usrp_source_c(gr.hier_block):
"""
Create a USRP source object supplying complex floats.
Selects user supplied subdevice or chooses first available one.
Calibration value is the offset from the tuned frequency to
the actual frequency.
"""
def __init__(self, fg, subdev_spec, decim, gain=None, calibration=0.0):
self._decim = decim
self._src = usrp.source_c()
if subdev_spec is None:
subdev_spec = usrp.pick_rx_subdevice(self._src)
self._subdev = usrp.selected_subdev(self._src, subdev_spec)
self._src.set_mux(usrp.determine_rx_mux_value(self._src, subdev_spec))
self._src.set_decim_rate(self._decim)
# If no gain specified, set to midrange
if gain is None:
g = self._subdev.gain_range()
gain = (g[0]+g[1])/2.0
self._subdev.set_gain(gain)
self._cal = calibration
gr.hier_block.__init__(self, fg, self._src, self._src)
def tune(self, freq):
result = usrp.tune(self._src, 0, self._subdev, freq+self._cal)
# TODO: deal with residual
def rate(self):
return self._src.adc_rate()/self._decim
class app_flow_graph(gr.flow_graph):
def __init__(self, options, args, queue):
gr.flow_graph.__init__(self)
self.options = options
self.args = args
USRP = usrp_source_c(self, # Flow graph
options.rx_subdev_spec, # Daugherboard spec
256, # IF decimation ratio gets 250K if_rate
options.gain, # Receiver gain
options.calibration) # Frequency offset
USRP.tune(options.frequency)
if_rate = USRP.rate()
channel_rate = 25000
channel_decim = int(if_rate / channel_rate)
CHAN_taps = optfir.low_pass(1.0, # Filter gain
if_rate, # Sample rate
8000, # One sided modulation bandwidth
10000, # One sided channel bandwidth
0.1, # Passband ripple
60) # Stopband attenuation
CHAN = gr.freq_xlating_fir_filter_ccf(channel_decim, # Decimation rate
CHAN_taps, # Filter taps
0.0, # Offset frequency
if_rate) # Sample rate
AGC = gr.agc_cc(1.0/channel_rate, # Time constant
1.0, # Reference power
1.0, # Initial gain
1.0) # Maximum gain
FLEX = pager.flex_demod(self, 25000, queue)
self.connect(USRP, CHAN, AGC, FLEX.INPUT)
def main():
parser = OptionParser(option_class=eng_option)
parser.add_option("-f", "--frequency", type="eng_float",
help="set receive frequency to Hz", metavar="Hz")
parser.add_option("-R", "--rx-subdev-spec", type="subdev",
help="select USRP Rx side A or B", metavar="SUBDEV")
parser.add_option("-c", "--calibration", type="eng_float", default=0.0,
help="set frequency offset to Hz", metavar="Hz")
parser.add_option("-g", "--gain", type="int", default=None,
help="set RF gain", metavar="dB")
(options, args) = parser.parse_args()
if options.frequency < 1e6:
options.frequency *= 1e6
queue = gr.msg_queue()
fg = app_flow_graph(options, args, queue)
try:
fg.start()
while 1:
msg = queue.delete_head() # Blocking read
fields = split(msg.to_string(), chr(128))
print join(fields, '|')
except KeyboardInterrupt:
fg.stop()
if __name__ == "__main__":
main()
|