root/vtcross/branches/sriram/receive_path.py @ 368

Revision 368, 9.0 KB (checked in by sriram, 15 years ago)

Back to the good old receive path

Line 
1#!/usr/bin/env python
2#
3# Copyright 2005,2006,2007,2009 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
23from gnuradio import gr, gru, blks2
24from gnuradio import usrp
25from gnuradio import eng_notation
26import copy
27import sys
28
29# from current dir
30from pick_bitrate import pick_rx_bitrate
31import usrp_options
32
33# /////////////////////////////////////////////////////////////////////////////
34#                              receive path
35# /////////////////////////////////////////////////////////////////////////////
36
37class receive_path(gr.hier_block2):
38    def __init__(self, demod_class, rx_callback, options):
39
40        gr.hier_block2.__init__(self, "receive_path",
41                                gr.io_signature(0, 0, 0), # Input signature
42                                gr.io_signature(0, 0, 0)) # Output signature
43
44        options = copy.copy(options)    # make a copy so we can destructively modify
45
46        self._verbose            = options.verbose
47        self._rx_freq            = options.rx_freq         # receiver's center frequency
48        self._rx_gain            = options.rx_gain         # receiver's gain
49        self._bitrate            = options.bitrate         # desired bit rate
50        self._decim              = options.decim           # Decimating rate for the USRP (prelim)
51        self._samples_per_symbol = options.samples_per_symbol  # desired samples/symbol
52
53        self._rx_callback   = rx_callback      # this callback is fired when there's a packet available
54        self._demod_class   = demod_class      # the demodulator_class we're using
55
56        if self._rx_freq is None:
57            sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n")
58            raise SystemExit
59
60        # Set up USRP source; also adjusts decim, samples_per_symbol, and bitrate
61        self._setup_usrp_source(options)
62
63        if options.show_rx_gain_range:
64            print "Rx Gain Range: minimum = %g, maximum = %g, step size = %g"%tuple(self.u.gain_range())
65
66        self.set_gain(options.rx_gain)
67
68        # Set RF frequency
69        ok = self.set_freq(self._rx_freq)
70        if not ok:
71            print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(self._rx_freq))
72            raise ValueError, eng_notation.num_to_str(self._rx_freq)
73
74        # copy the final answers back into options for use by demodulator
75        options.samples_per_symbol = self._samples_per_symbol
76        options.bitrate = self._bitrate
77        options.decim = self._decim
78
79        # Get demod_kwargs
80        demod_kwargs = self._demod_class.extract_kwargs_from_options(options)
81
82        # Design filter to get actual channel we want
83        sw_decim = 1
84        chan_coeffs = gr.firdes.low_pass (1.0,                  # gain
85                                          sw_decim * self._samples_per_symbol, # sampling rate
86                                          1.0,                  # midpoint of trans. band
87                                          0.5,                  # width of trans. band
88                                          gr.firdes.WIN_HANN)   # filter type
89
90        # Decimating channel filter
91        # complex in and out, float taps
92        self.chan_filt = gr.fft_filter_ccc(sw_decim, chan_coeffs)
93        #self.chan_filt = gr.fir_filter_ccf(sw_decim, chan_coeffs)
94
95        # receiver
96        self.packet_receiver = \
97            blks2.demod_pkts(self._demod_class(**demod_kwargs),
98                             access_code=None,
99                             callback=self._rx_callback,
100                             threshold=-1)
101   
102        # Carrier Sensing Blocks
103        alpha = 0.001
104        thresh = 30   # in dB, will have to adjust
105
106        if options.log_rx_power == True:
107            self.probe = gr.probe_avg_mag_sqrd_cf(thresh,alpha)
108            self.power_sink = gr.file_sink(gr.sizeof_float, "rxpower.dat")
109            self.connect(self.chan_filt, self.probe, self.power_sink)
110        else:
111            self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha)
112            self.connect(self.chan_filt, self.probe)
113
114        # Display some information about the setup
115        if self._verbose:
116            self._print_verbage()
117           
118        self.connect(self.u, self.chan_filt, self.packet_receiver)
119
120    def _setup_usrp_source(self, options):
121
122        self.u = usrp_options.create_usrp_source(options)
123        adc_rate = self.u.adc_rate()
124
125        # derive values of bitrate, samples_per_symbol, and decim from desired info
126        (self._bitrate, self._samples_per_symbol, self._decim) = \
127            pick_rx_bitrate(self._bitrate, self._demod_class.bits_per_symbol(), \
128                            self._samples_per_symbol, self._decim, adc_rate)
129
130        self.u.set_decim(self._decim)
131
132    def set_freq(self, target_freq):
133        """
134        Set the center frequency we're interested in.
135
136        @param target_freq: frequency in Hz
137        @rypte: bool
138
139        Tuning is a two step process.  First we ask the front-end to
140        tune as close to the desired frequency as it can.  Then we use
141        the result of that operation and our target_frequency to
142        determine the value for the digital up converter.
143        """
144        return self.u.set_center_freq(target_freq)
145
146    def set_gain(self, gain):
147        """
148        Sets the analog gain in the USRP
149        """
150        return self.u.set_gain(gain)
151       
152    def bitrate(self):
153        return self._bitrate
154
155    def samples_per_symbol(self):
156        return self._samples_per_symbol
157
158    def decim(self):
159        return self._decim
160
161    def carrier_sensed(self):
162        """
163        Return True if we think carrier is present.
164        """
165        #return self.probe.level() > X
166        return self.probe.unmuted()
167
168    def carrier_threshold(self):
169        """
170        Return current setting in dB.
171        """
172        return self.probe.threshold()
173
174    def set_carrier_threshold(self, threshold_in_db):
175        """
176        Set carrier threshold.
177
178        @param threshold_in_db: set detection threshold
179        @type threshold_in_db:  float (dB)
180        """
181        self.probe.set_threshold(threshold_in_db)
182   
183    @staticmethod
184    def add_options(normal, expert):
185        """
186        Adds receiver-specific options to the Options Parser
187        """
188        add_freq_option(normal)
189        if not normal.has_option("--bitrate"):
190            normal.add_option("-r", "--bitrate", type="eng_float", default=None,
191                              help="specify bitrate.  samples-per-symbol and interp/decim will be derived.")
192        usrp_options.add_rx_options(normal, expert)
193        normal.add_option("-v", "--verbose", action="store_true", default=False)
194        expert.add_option("-S", "--samples-per-symbol", type="int", default=None,
195                          help="set samples/symbol [default=%default]")
196        expert.add_option("", "--rx-freq", type="eng_float", default=None,
197                          help="set Rx frequency to FREQ [default=%default]", metavar="FREQ")
198        expert.add_option("", "--log", action="store_true", default=False,
199                          help="Log all parts of flow graph to files (CAUTION: lots of data)")
200        expert.add_option("", "--log-rx-power", action="store_true", default=False,
201                          help="Log receive signal power to file (CAUTION: lots of data)")
202
203    def _print_verbage(self):
204        """
205        Prints information about the receive path
206        """
207        print "\nReceive Path:"
208        print "USRP %s"    % (self.u,)
209        print "Rx gain:         %g"    % (self.u.gain(),)
210        print "modulation:      %s"    % (self._demod_class.__name__)
211        print "bitrate:         %sb/s" % (eng_notation.num_to_str(self._bitrate))
212        print "samples/symbol:  %3d"   % (self._samples_per_symbol)
213        print "decim:           %3d"   % (self._decim)
214        print "Rx Frequency:    %s"    % (eng_notation.num_to_str(self._rx_freq))
215
216def add_freq_option(parser):
217    """
218    Hackery that has the -f / --freq option set both tx_freq and rx_freq
219    """
220    def freq_callback(option, opt_str, value, parser):
221        parser.values.rx_freq = value
222        parser.values.tx_freq = value
223
224    if not parser.has_option('--freq'):
225        parser.add_option('-f', '--freq', type="eng_float",
226                          action="callback", callback=freq_callback,
227                          help="set Tx and/or Rx frequency to FREQ [default=%default]",
228                          metavar="FREQ")
Note: See TracBrowser for help on using the browser.