1 | #!/usr/bin/env python |
---|
2 | # |
---|
3 | # Copyright 2005,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, gru, blks2 |
---|
24 | from gnuradio import eng_notation |
---|
25 | import copy |
---|
26 | import sys |
---|
27 | |
---|
28 | # ///////////////////////////////////////////////////////////////////////////// |
---|
29 | # receive path |
---|
30 | # ///////////////////////////////////////////////////////////////////////////// |
---|
31 | |
---|
32 | class receive_path(gr.hier_block2): |
---|
33 | def __init__(self, demod_class, rx_callback, options): |
---|
34 | gr.hier_block2.__init__(self, "receive_path", |
---|
35 | gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature |
---|
36 | gr.io_signature(0, 0, 0)) # Output signature |
---|
37 | |
---|
38 | |
---|
39 | options = copy.copy(options) # make a copy so we can destructively modify |
---|
40 | |
---|
41 | self._verbose = options.verbose |
---|
42 | self._bitrate = options.bitrate # desired bit rate |
---|
43 | self._samples_per_symbol = options.samples_per_symbol # desired samples/symbol |
---|
44 | |
---|
45 | self._rx_callback = rx_callback # this callback is fired when there's a packet available |
---|
46 | self._demod_class = demod_class # the demodulator_class we're using |
---|
47 | |
---|
48 | # Get demod_kwargs |
---|
49 | demod_kwargs = self._demod_class.extract_kwargs_from_options(options) |
---|
50 | |
---|
51 | # Design filter to get actual channel we want |
---|
52 | sw_decim = 1 |
---|
53 | chan_coeffs = gr.firdes.low_pass (1.0, # gain |
---|
54 | sw_decim * self._samples_per_symbol, # sampling rate |
---|
55 | 1.0, # midpoint of trans. band |
---|
56 | 0.5, # width of trans. band |
---|
57 | gr.firdes.WIN_HANN) # filter type |
---|
58 | self.channel_filter = gr.fft_filter_ccc(sw_decim, chan_coeffs) |
---|
59 | |
---|
60 | # receiver |
---|
61 | self.packet_receiver = \ |
---|
62 | blks2.demod_pkts(self._demod_class(**demod_kwargs), |
---|
63 | access_code=None, |
---|
64 | callback=self._rx_callback, |
---|
65 | threshold=-1) |
---|
66 | |
---|
67 | # Carrier Sensing Blocks |
---|
68 | alpha = 0.001 |
---|
69 | thresh = 30 # in dB, will have to adjust |
---|
70 | self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha) |
---|
71 | |
---|
72 | # Display some information about the setup |
---|
73 | if self._verbose: |
---|
74 | self._print_verbage() |
---|
75 | |
---|
76 | # connect block input to channel filter |
---|
77 | self.connect(self, self.channel_filter) |
---|
78 | |
---|
79 | # connect the channel input filter to the carrier power detector |
---|
80 | self.connect(self.channel_filter, self.probe) |
---|
81 | |
---|
82 | # connect channel filter to the packet receiver |
---|
83 | self.connect(self.channel_filter, self.packet_receiver) |
---|
84 | |
---|
85 | def bitrate(self): |
---|
86 | return self._bitrate |
---|
87 | |
---|
88 | def samples_per_symbol(self): |
---|
89 | return self._samples_per_symbol |
---|
90 | |
---|
91 | def carrier_sensed(self): |
---|
92 | """ |
---|
93 | Return True if we think carrier is present. |
---|
94 | """ |
---|
95 | #return self.probe.level() > X |
---|
96 | return self.probe.unmuted() |
---|
97 | |
---|
98 | def carrier_threshold(self): |
---|
99 | """ |
---|
100 | Return current setting in dB. |
---|
101 | """ |
---|
102 | return self.probe.threshold() |
---|
103 | |
---|
104 | def set_carrier_threshold(self, threshold_in_db): |
---|
105 | """ |
---|
106 | Set carrier threshold. |
---|
107 | |
---|
108 | @param threshold_in_db: set detection threshold |
---|
109 | @type threshold_in_db: float (dB) |
---|
110 | """ |
---|
111 | self.probe.set_threshold(threshold_in_db) |
---|
112 | |
---|
113 | |
---|
114 | def add_options(normal, expert): |
---|
115 | """ |
---|
116 | Adds receiver-specific options to the Options Parser |
---|
117 | """ |
---|
118 | if not normal.has_option("--bitrate"): |
---|
119 | normal.add_option("-r", "--bitrate", type="eng_float", default=100e3, |
---|
120 | help="specify bitrate [default=%default].") |
---|
121 | normal.add_option("-v", "--verbose", action="store_true", default=False) |
---|
122 | expert.add_option("-S", "--samples-per-symbol", type="int", default=2, |
---|
123 | help="set samples/symbol [default=%default]") |
---|
124 | expert.add_option("", "--log", action="store_true", default=False, |
---|
125 | help="Log all parts of flow graph to files (CAUTION: lots of data)") |
---|
126 | |
---|
127 | # Make a static method to call before instantiation |
---|
128 | add_options = staticmethod(add_options) |
---|
129 | |
---|
130 | |
---|
131 | def _print_verbage(self): |
---|
132 | """ |
---|
133 | Prints information about the receive path |
---|
134 | """ |
---|
135 | print "\nReceive Path:" |
---|
136 | print "modulation: %s" % (self._demod_class.__name__) |
---|
137 | print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) |
---|
138 | print "samples/symbol: %3d" % (self._samples_per_symbol) |
---|