Merge branch 'digital'
authorTom Rondeau <trondeau@vt.edu>
Sun, 14 Mar 2010 22:39:03 +0000 (18:39 -0400)
committerTom Rondeau <trondeau@vt.edu>
Sun, 14 Mar 2010 22:39:03 +0000 (18:39 -0400)
23 files changed:
gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc
gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h
gnuradio-core/src/python/gnuradio/Makefile.am
gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py
gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py
gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py
gnuradio-core/src/python/gnuradio/modulation_utils2.py [new file with mode: 0644]
gnuradio-core/src/python/gnuradio/packet_utils.py
gnuradio-examples/grc/demod/digital_freq_lock.grc
gnuradio-examples/grc/demod/pam_sync.grc
gnuradio-examples/python/digital/benchmark_loopback.py
gnuradio-examples/python/digital/benchmark_qt_loopback2.py
gnuradio-examples/python/digital/benchmark_qt_rx2.py
gnuradio-examples/python/digital/benchmark_rx2.py [new file with mode: 0755]
gnuradio-examples/python/digital/benchmark_tx2.py [new file with mode: 0755]
gnuradio-examples/python/digital/pick_bitrate2.py [new file with mode: 0644]
gnuradio-examples/python/digital/receive_path.py
gnuradio-examples/python/digital/transmit_path.py
gnuradio-examples/python/digital/usrp_receive_path.py
gnuradio-examples/python/digital/usrp_receive_path2.py [new file with mode: 0644]
gnuradio-examples/python/digital/usrp_transmit_path.py
gnuradio-examples/python/digital/usrp_transmit_path2.py [new file with mode: 0644]

index 030e45ddfb803f1b724540774ab9247792a0a923..7f2c468b724529107e916c0f4b7f6c476f870488 100644 (file)
@@ -53,7 +53,7 @@ gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float samps_per_sym, float ro
 }
 
 
-static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)};
+static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(gr_complex)};
 static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int));
 gr_fll_band_edge_cc::gr_fll_band_edge_cc (float samps_per_sym, float rolloff,
                                          int filter_size, float alpha, float beta)
@@ -83,10 +83,11 @@ gr_fll_band_edge_cc::~gr_fll_band_edge_cc ()
 void
 gr_fll_band_edge_cc::set_alpha(float alpha) 
 { 
-  float eta = sqrt(2.0)/2.0;
-  float theta = alpha;
-  d_alpha = (4*eta*theta) / (1.0 + 2.0*eta*theta + theta*theta);
-  d_beta = (4*theta*theta) / (1.0 + 2.0*eta*theta + theta*theta);
+  //float eta = sqrt(2.0)/2.0;
+  //float theta = alpha;
+  //d_alpha = (4*eta*theta) / (1.0 + 2.0*eta*theta + theta*theta);
+  //d_beta = (4*theta*theta) / (1.0 + 2.0*eta*theta + theta*theta);
+  d_alpha = alpha;
 }
 
 void
@@ -160,11 +161,12 @@ gr_fll_band_edge_cc::work (int noutput_items,
   const gr_complex *in  = (const gr_complex *) input_items[0];
   gr_complex *out = (gr_complex *) output_items[0];
 
-  float *frq, *phs, *err;
+  float *frq, *phs;
+  gr_complex *err;
   if(output_items.size() > 2) {
     frq = (float *) output_items[1];
     phs = (float *) output_items[2];
-    err = (float *) output_items[3];
+    err = (gr_complex *) output_items[3];
   }
 
   if (d_updated) {
@@ -174,16 +176,17 @@ gr_fll_band_edge_cc::work (int noutput_items,
 
   int i;
   gr_complex nco_out;
-  float out_upper, out_lower;
+  gr_complex out_upper, out_lower;
   float error;
+  float avg_k = 0.1;
   for(i = 0; i < noutput_items; i++) {
     nco_out = gr_expj(d_phase);
     out[i] = in[i] * nco_out;
 
-    out_upper = norm(d_filter_upper->filter(&out[i]));
-    out_lower = norm(d_filter_lower->filter(&out[i]));
-    error = out_lower - out_upper;
-    d_error = 0.01*error + 0.99*d_error;  // average error
+    out_upper = (d_filter_upper->filter(&out[i]));
+    out_lower = (d_filter_lower->filter(&out[i]));
+    error = -real((out_upper + out_lower) * conj(out_upper - out_lower));
+    d_error = avg_k*error + avg_k*d_error;  // average error
 
     d_freq = d_freq + d_beta * d_error;
     d_phase = d_phase + d_freq + d_alpha * d_error;
index 09baf7fde88b65dd0de45d6689988d1877a3983f..178e18f3e8469313b50996a9b39d662ac4c1406c 100644 (file)
@@ -45,8 +45,12 @@ class gri_fft_complex;
  * (e.g., rolloff factor) of the modulated signal. The placement in frequency of the band-edges
  * is determined by the oversampling ratio (number of samples per symbol) and the excess bandwidth.
  * The size of the filters should be fairly large so as to average over a number of symbols.
- * The FLL works by calculating the power in both the upper and lower bands and comparing them. The
- * difference in power between the filters is proportional to the frequency offset.
+ *
+ * The FLL works by filtering the upper and lower band edges into x_u(t) and x_l(t), respectively.
+ * These are combined to form cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining
+ * these to form the signal e(t) = Re{cc(t) \times ss(t)^*} (where ^* is the complex conjugate)
+ * provides an error signal at the DC term that is directly proportional to the carrier frequency.
+ * We then make a second-order loop using the error signal that is the running average of e(t).
  *
  * In theory, the band-edge filter is the derivative of the matched filter in frequency, 
  * (H_be(f) = \frac{H(f)}{df}. In practice, this comes down to a quarter sine wave at the point
index dcc0017b3c16660fd7b238a2a106e76720d2b4ee..f0516f2fd9e808387f6b687e50556b7ccca12c0a 100644 (file)
@@ -30,6 +30,7 @@ grpython_PYTHON =                     \
        eng_notation.py                 \
        eng_option.py                   \
        modulation_utils.py             \
+       modulation_utils2.py            \
        ofdm_packet_utils.py            \
        packet_utils.py                 \
        gr_unittest.py                  \
index 68d68362363fb10a1c9c466969bf6fb01b0e9fc3..7b24fb69d75bed59643c8af4296fc7385fd65d29 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2005,2007,2009 Free Software Foundation, Inc.
+# Copyright 2005,2007,2009,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
index 860015c3f02ab33621e576fd7b5aad9d2329741e..55e4890f309d274f3c5c5cb5f8194abb9e52cc20 100644 (file)
@@ -233,10 +233,10 @@ class dbpsk_demod(gr.hier_block2):
         arity = pow(2,self.bits_per_symbol())
 
         # Automatic gain control
-        scale = (1.0/16384.0)
-        self.pre_scaler = gr.multiply_const_cc(scale)   # scale the signal from full-range to +-1
-        #self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
-        self.agc = gr.feedforward_agc_cc(16, 2.0)
+        #scale = (1.0/16384.0)
+        #self.pre_scaler = gr.multiply_const_cc(scale)   # scale the signal from full-range to +-1
+        self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
+        #self.agc = gr.feedforward_agc_cc(16, 2.0)
 
         # RRC data filter
         ntaps = 11 * samples_per_symbol
@@ -288,7 +288,7 @@ class dbpsk_demod(gr.hier_block2):
             self._setup_logging()
 
         # Connect and Initialize base class
-        self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver,
+        self.connect(self, self.agc, self.rrc_filter, self.receiver,
                      self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self)
 
     def samples_per_symbol(self):
index e9fb3df89874266518b2a7025fbc020a20362a39..d7bcf53907c9e619a9aa3147bb801a85bdfb8e41 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2005,2006,2007 Free Software Foundation, Inc.
+# Copyright 2009,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -25,7 +25,7 @@
 differential BPSK modulation and demodulation.
 """
 
-from gnuradio import gr, gru, modulation_utils
+from gnuradio import gr, gru, modulation_utils2
 from math import pi, sqrt, ceil
 import psk
 import cmath
@@ -38,8 +38,8 @@ _def_gray_code = True
 _def_verbose = False
 _def_log = False
 
-_def_freq_alpha = 4e-3
-_def_costas_alpha = 0.1
+_def_freq_alpha = 0.010
+_def_phase_alpha = 0.1
 _def_timing_alpha = 0.100
 _def_timing_beta = 0.010
 _def_timing_max_dev = 1.5
@@ -83,7 +83,7 @@ class dbpsk2_mod(gr.hier_block2):
         self._excess_bw = excess_bw
         self._gray_code = gray_code
 
-        if not isinstance(self._samples_per_symbol, int) or self._samples_per_symbol < 2:
+        if self._samples_per_symbol < 2:
             raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol)
         
         arity = pow(2,self.bits_per_symbol())
@@ -103,7 +103,7 @@ class dbpsk2_mod(gr.hier_block2):
 
         # pulse shaping filter
         nfilts = 32
-        ntaps = nfilts * 11 * self._samples_per_symbol      # make nfilts filters of ntaps each
+        ntaps = nfilts * 11 * int(self._samples_per_symbol)    # make nfilts filters of ntaps each
         self.rrc_taps = gr.firdes.root_raised_cosine(
             nfilts,          # gain
             nfilts,          # sampling rate based on 32 filters in resampler
@@ -145,7 +145,7 @@ class dbpsk2_mod(gr.hier_block2):
         """
         Given command line options, create dictionary suitable for passing to __init__
         """
-        return modulation_utils.extract_kwargs_from_options(dbpsk2_mod.__init__,
+        return modulation_utils2.extract_kwargs_from_options(dbpsk2_mod.__init__,
                                                             ('self',), options)
     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
 
@@ -182,7 +182,7 @@ class dbpsk2_demod(gr.hier_block2):
                  samples_per_symbol=_def_samples_per_symbol,
                  excess_bw=_def_excess_bw,
                  freq_alpha=_def_freq_alpha,
-                 costas_alpha=_def_costas_alpha,
+                 phase_alpha=_def_phase_alpha,
                  timing_alpha=_def_timing_alpha,
                  timing_max_dev=_def_timing_max_dev,
                  gray_code=_def_gray_code,
@@ -201,8 +201,8 @@ class dbpsk2_demod(gr.hier_block2):
        @type excess_bw: float
         @param freq_alpha: loop filter gain for frequency recovery
         @type freq_alpha: float
-        @param costas_alpha: loop filter gain for phase/fine frequency recovery
-        @type costas_alpha: float
+        @param phase_alpha: loop filter gain for phase/fine frequency recovery
+        @type phase_alpha: float
         @param timing_alpha: loop alpha gain for timing recovery
         @type timing_alpha: float
         @param timing_max: timing loop maximum rate deviations
@@ -226,8 +226,8 @@ class dbpsk2_demod(gr.hier_block2):
         self._samples_per_symbol = samples_per_symbol
         self._excess_bw = excess_bw
         self._freq_alpha = freq_alpha
-        self._freq_beta = 0.25*self._freq_alpha**2
-        self._costas_alpha = costas_alpha
+        self._freq_beta = 0.10*self._freq_alpha
+        self._phase_alpha = phase_alpha
         self._timing_alpha = timing_alpha
         self._timing_beta = _def_timing_beta
         self._timing_max_dev=timing_max_dev
@@ -259,13 +259,13 @@ class dbpsk2_demod(gr.hier_block2):
         self.time_recov.set_beta(self._timing_beta)
 
         # Perform phase / fine frequency correction
-        self._costas_beta  = 0.25 * self._costas_alpha * self._costas_alpha
+        self._phase_beta  = 0.25 * self._phase_alpha * self._phase_alpha
         # Allow a frequency swing of +/- half of the sample rate
         fmin = -0.5
         fmax = 0.5
         
-        self.phase_recov = gr.costas_loop_cc(self._costas_alpha,
-                                             self._costas_beta,
+        self.phase_recov = gr.costas_loop_cc(self._phase_alpha,
+                                             self._phase_beta,
                                              fmax, fmin, arity)
 
         # Do differential decoding based on phase change of symbols
@@ -308,29 +308,27 @@ class dbpsk2_demod(gr.hier_block2):
         print "bits per symbol:     %d"   % self.bits_per_symbol()
         print "Gray code:           %s"   % self._gray_code
         print "RRC roll-off factor: %.2f" % self._excess_bw
-        print "FLL gain:            %.2f" % self._freq_alpha
-        print "Costas Loop alpha:   %.2f" % self._costas_alpha
-        print "Costas Loop beta:    %.2f" % self._costas_beta
-        print "Timing alpha gain:   %.2f" % self._timing_alpha
-        print "Timing beta gain:    %.2f" % self._timing_beta
+        print "FLL gain:            %.2e" % self._freq_alpha
+        print "Timing alpha gain:   %.2e" % self._timing_alpha
+        print "Timing beta gain:    %.2e" % self._timing_beta
         print "Timing max dev:      %.2f" % self._timing_max_dev
+        print "Phase track alpha:   %.2e" % self._phase_alpha
+        print "Phase track beta:    %.2e" % self._phase_beta
 
     def _setup_logging(self):
         print "Modulation logging turned on."
-        self.connect(self.pre_scaler,
-                         gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat"))
         self.connect(self.agc,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat"))
-        self.connect(self.rrc_filter,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat"))
-        self.connect(self.clock_recov,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_clock_recov.dat"))
+        self.connect(self.freq_recov,
+                     gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.dat"))
         self.connect(self.time_recov,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat"))
+        self.connect(self.phase_recov,
+                     gr.file_sink(gr.sizeof_gr_complex, "rx_phase_recov.dat"))
         self.connect(self.diffdec,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat"))        
         self.connect(self.slicer,
-                    gr.file_sink(gr.sizeof_char, "rx_slicer.dat"))
+                     gr.file_sink(gr.sizeof_char, "rx_slicer.dat"))
         self.connect(self.symbol_mapper,
                      gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat"))
         self.connect(self.unpack,
@@ -347,11 +345,11 @@ class dbpsk2_demod(gr.hier_block2):
                           help="disable gray coding on modulated bits (PSK)")
         parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha,
                           help="set frequency lock loop alpha gain value [default=%default] (PSK)")
-        parser.add_option("", "--costas-alpha", type="float", default=None,
-                          help="set Costas loop alpha value [default=%default] (PSK)")
-        parser.add_option("", "--gain-alpha", type="float", default=_def_timing_alpha,
+        parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha,
+                          help="set phase tracking loop alpha value [default=%default] (PSK)")
+        parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha,
                           help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)")
-        parser.add_option("", "--gain-beta", type="float", default=_def_timing_beta,
+        parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta,
                           help="set timing symbol sync loop gain beta value [default=%default] (GMSK/PSK)")
         parser.add_option("", "--timing-max-dev", type="float", default=_def_timing_max_dev,
                           help="set timing symbol sync loop maximum deviation [default=%default] (GMSK/PSK)")
@@ -361,11 +359,11 @@ class dbpsk2_demod(gr.hier_block2):
         """
         Given command line options, create dictionary suitable for passing to __init__
         """
-        return modulation_utils.extract_kwargs_from_options(
+        return modulation_utils2.extract_kwargs_from_options(
                  dbpsk2_demod.__init__, ('self',), options)
     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
 #
 # Add these to the mod/demod registry
 #
-modulation_utils.add_type_1_mod('dbpsk2', dbpsk2_mod)
-modulation_utils.add_type_1_demod('dbpsk2', dbpsk2_demod)
+modulation_utils2.add_type_1_mod('dbpsk2', dbpsk2_mod)
+modulation_utils2.add_type_1_demod('dbpsk2', dbpsk2_demod)
index 9fae6accac07c14cf5aff158d8b6f2dde0bbbd22..e1e627707becb0d7c6465b1a1b53acce7ebe13cb 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc.
+# Copyright 2009,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -25,7 +25,7 @@
 differential QPSK modulation and demodulation.
 """
 
-from gnuradio import gr, gru, modulation_utils
+from gnuradio import gr, gru, modulation_utils2
 from math import pi, sqrt
 import psk
 import cmath
@@ -38,8 +38,8 @@ _def_gray_code = True
 _def_verbose = False
 _def_log = False
 
-_def_freq_alpha = 4e-3
-_def_costas_alpha = 0.01
+_def_freq_alpha = 0.010
+_def_phase_alpha = 0.01
 _def_timing_alpha = 0.100
 _def_timing_beta = 0.010
 _def_timing_max_dev = 1.5
@@ -83,8 +83,8 @@ class dqpsk2_mod(gr.hier_block2):
         self._excess_bw = excess_bw
         self._gray_code = gray_code
 
-        if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
-            raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol)
+        if samples_per_symbol < 2:
+            raise TypeError, ("sbp must be >= 2, is %f" % samples_per_symbol)
 
        ntaps = 11 * samples_per_symbol
  
@@ -107,7 +107,7 @@ class dqpsk2_mod(gr.hier_block2):
 
         # pulse shaping filter
         nfilts = 32
-        ntaps = nfilts * 11 * self._samples_per_symbol      # make nfilts filters of ntaps each
+        ntaps = 11 * int(nfilts * self._samples_per_symbol)  # make nfilts filters of ntaps each
         self.rrc_taps = gr.firdes.root_raised_cosine(
             nfilts,          # gain
             nfilts,          # sampling rate based on 32 filters in resampler
@@ -168,7 +168,7 @@ class dqpsk2_mod(gr.hier_block2):
         """
         Given command line options, create dictionary suitable for passing to __init__
         """
-        return modulation_utils.extract_kwargs_from_options(dqpsk2_mod.__init__,
+        return modulation_utils2.extract_kwargs_from_options(dqpsk2_mod.__init__,
                                                             ('self',), options)
     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
 
@@ -185,7 +185,7 @@ class dqpsk2_demod(gr.hier_block2):
                  samples_per_symbol=_def_samples_per_symbol,
                  excess_bw=_def_excess_bw,
                  freq_alpha=_def_freq_alpha,
-                 costas_alpha=_def_costas_alpha,
+                 phase_alpha=_def_phase_alpha,
                  timing_alpha=_def_timing_alpha,
                  timing_max_dev=_def_timing_max_dev,
                  gray_code=_def_gray_code,
@@ -204,8 +204,8 @@ class dqpsk2_demod(gr.hier_block2):
        @type excess_bw: float
         @param freq_alpha: loop filter gain for frequency recovery
         @type freq_alpha: float
-        @param costas_alpha: loop filter gain
-        @type costas_alphas: float
+        @param phase_alpha: loop filter gain
+        @type phase_alphas: float
         @param timing_alpha: timing loop alpha gain
         @type timing_alpha: float
         @param timing_max: timing loop maximum rate deviations
@@ -230,7 +230,7 @@ class dqpsk2_demod(gr.hier_block2):
         self._excess_bw = excess_bw
         self._freq_alpha = freq_alpha
         self._freq_beta = 0.25*self._freq_alpha**2
-        self._costas_alpha = costas_alpha
+        self._phase_alpha = phase_alpha
         self._timing_alpha = timing_alpha
         self._timing_beta = _def_timing_beta
         self._timing_max_dev=timing_max_dev
@@ -264,13 +264,13 @@ class dqpsk2_demod(gr.hier_block2):
         
 
         # Perform phase / fine frequency correction
-        self._costas_beta  = 0.25 * self._costas_alpha * self._costas_alpha
+        self._phase_beta  = 0.25 * self._phase_alpha * self._phase_alpha
         # Allow a frequency swing of +/- half of the sample rate
         fmin = -0.5
         fmax = 0.5
 
-        self.phase_recov = gr.costas_loop_cc(self._costas_alpha,
-                                             self._costas_beta,
+        self.phase_recov = gr.costas_loop_cc(self._phase_alpha,
+                                             self._phase_beta,
                                              fmax, fmin, arity)
 
 
@@ -315,24 +315,22 @@ class dqpsk2_demod(gr.hier_block2):
         print "Gray code:           %s"   % self._gray_code
         print "RRC roll-off factor: %.2f" % self._excess_bw
         print "FLL gain:            %.2f" % self._freq_alpha
-        print "Costas Loop alpha:   %.2e" % self._costas_alpha
-        print "Costas Loop beta:    %.2e" % self._costas_beta
         print "Timing alpha gain:   %.2f" % self._timing_alpha
         print "Timing beta gain:    %.2f" % self._timing_beta
         print "Timing max dev:      %.2f" % self._timing_max_dev
+        print "Phase track alpha:   %.2e" % self._phase_alpha
+        print "Phase track beta:    %.2e" % self._phase_beta
 
     def _setup_logging(self):
         print "Modulation logging turned on."
-        self.connect(self.pre_scaler,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat"))
         self.connect(self.agc,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat"))
-        self.connect(self.rrc_filter,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat"))
-        self.connect(self.clock_recov,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_clock_recov.dat"))
+        self.connect(self.freq_recov,
+                     gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.dat"))
         self.connect(self.time_recov,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat"))
+        self.connect(self.phase_recov,
+                     gr.file_sink(gr.sizeof_gr_complex, "rx_phase_recov.dat"))
         self.connect(self.diffdec,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat"))        
         self.connect(self.slicer,
@@ -344,7 +342,7 @@ class dqpsk2_demod(gr.hier_block2):
 
     def add_options(parser):
         """
-        Adds modulation-specific options to the standard parser
+        Adds DQPSK demodulation-specific options to the standard parser
         """
         parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw,
                           help="set RRC excess bandwith factor [default=%default] (PSK)")
@@ -353,11 +351,11 @@ class dqpsk2_demod(gr.hier_block2):
                           help="disable gray coding on modulated bits (PSK)")
         parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha,
                           help="set frequency lock loop alpha gain value [default=%default] (PSK)")
-        parser.add_option("", "--costas-alpha", type="float", default=_def_costas_alpha,
-                          help="set Costas loop alpha value [default=%default] (PSK)")
-        parser.add_option("", "--gain-alpha", type="float", default=_def_timing_alpha,
+        parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha,
+                          help="set phase tracking loop alpha value [default=%default] (PSK)")
+        parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha,
                           help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)")
-        parser.add_option("", "--gain-beta", type="float", default=_def_timing_beta,
+        parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta,
                           help="set timing symbol sync loop gain beta value [default=%default] (GMSK/PSK)")
         parser.add_option("", "--timing-max-dev", type="float", default=_def_timing_max_dev,
                           help="set timing symbol sync loop maximum deviation [default=%default] (GMSK/PSK)")
@@ -367,7 +365,7 @@ class dqpsk2_demod(gr.hier_block2):
         """
         Given command line options, create dictionary suitable for passing to __init__
         """
-        return modulation_utils.extract_kwargs_from_options(
+        return modulation_utils2.extract_kwargs_from_options(
             dqpsk2_demod.__init__, ('self',), options)
     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
 
@@ -375,5 +373,5 @@ class dqpsk2_demod(gr.hier_block2):
 #
 # Add these to the mod/demod registry
 #
-modulation_utils.add_type_1_mod('dqpsk2', dqpsk2_mod)
-modulation_utils.add_type_1_demod('dqpsk2', dqpsk2_demod)
+modulation_utils2.add_type_1_mod('dqpsk2', dqpsk2_mod)
+modulation_utils2.add_type_1_demod('dqpsk2', dqpsk2_demod)
diff --git a/gnuradio-core/src/python/gnuradio/modulation_utils2.py b/gnuradio-core/src/python/gnuradio/modulation_utils2.py
new file mode 100644 (file)
index 0000000..c5dba3e
--- /dev/null
@@ -0,0 +1,81 @@
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+"""
+Miscellaneous utilities for managing mods and demods, as well as other items
+useful in dealing with generalized handling of different modulations and demods.
+"""
+
+import inspect
+
+
+# Type 1 modulators accept a stream of bytes on their input and produce complex baseband output
+_type_1_modulators = {}
+
+def type_1_mods():
+    return _type_1_modulators
+
+def add_type_1_mod(name, mod_class):
+    _type_1_modulators[name] = mod_class
+
+
+# Type 1 demodulators accept complex baseband input and produce a stream of bits, packed
+# 1 bit / byte as their output.  Their output is completely unambiguous.  There is no need
+# to resolve phase or polarity ambiguities.
+_type_1_demodulators = {}
+
+def type_1_demods():
+    return _type_1_demodulators
+
+def add_type_1_demod(name, demod_class):
+    _type_1_demodulators[name] = demod_class
+
+
+def extract_kwargs_from_options(function, excluded_args, options):
+    """
+    Given a function, a list of excluded arguments and the result of
+    parsing command line options, create a dictionary of key word
+    arguments suitable for passing to the function.  The dictionary
+    will be populated with key/value pairs where the keys are those
+    that are common to the function's argument list (minus the
+    excluded_args) and the attributes in options.  The values are the
+    corresponding values from options unless that value is None.
+    In that case, the corresponding dictionary entry is not populated.
+
+    (This allows different modulations that have the same parameter
+    names, but different default values to coexist.  The downside is
+    that --help in the option parser will list the default as None,
+    but in that case the default provided in the __init__ argument
+    list will be used since there is no kwargs entry.)
+
+    @param function: the function whose parameter list will be examined
+    @param excluded_args: function arguments that are NOT to be added to the dictionary
+    @type excluded_args: sequence of strings
+    @param options: result of command argument parsing
+    @type options: optparse.Values
+    """
+    # Try this in C++ ;)
+    args, varargs, varkw, defaults = inspect.getargspec(function)
+    d = {}
+    for kw in [a for a in args if a not in excluded_args]:
+        if hasattr(options, kw):
+            if getattr(options, kw) is not None:
+                d[kw] = getattr(options, kw)
+    return d
index 1417c17fa5b1d731a70bd07571040b66b710d5ed..e36b05413e1137b0a814eedd8dae635210d9336c 100644 (file)
@@ -143,7 +143,7 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol,
                        (payload_with_crc), '\x55'))
 
     if pad_for_usrp:
-        pkt = pkt + (_npadding_bytes(len(pkt), samples_per_symbol, bits_per_symbol) * '\x55')
+        pkt = pkt + (_npadding_bytes(len(pkt), int(samples_per_symbol), bits_per_symbol) * '\x55')
 
     #print "make_packet: len(pkt) =", len(pkt)
     return pkt
index 37ee8123eb084e212510c5768769e79584ba61a3..36037febb0b6c3156343a0869422ae85a7bed224 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version='1.0' encoding='ASCII'?>
 <flow_graph>
-  <timestamp>Fri Jan 29 18:10:00 2010</timestamp>
+  <timestamp>Sat Mar  6 17:17:12 2010</timestamp>
   <block>
     <key>options</key>
     <param>
     </param>
   </block>
   <block>
-    <key>variable_slider</key>
+    <key>root_raised_cosine_filter</key>
     <param>
       <key>id</key>
-      <value>alpha</value>
+      <value>root_raised_cosine_filter_0</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>label</key>
-      <value>Freq Alpha</value>
-    </param>
-    <param>
-      <key>value</key>
-      <value>0</value>
+      <key>type</key>
+      <value>interp_fir_filter_ccf</value>
     </param>
     <param>
-      <key>min</key>
-      <value>0</value>
+      <key>decim</key>
+      <value>1</value>
     </param>
     <param>
-      <key>max</key>
-      <value>0.001</value>
+      <key>interp</key>
+      <value>spb_gen</value>
     </param>
     <param>
-      <key>num_steps</key>
-      <value>1000</value>
+      <key>gain</key>
+      <value>2*spb_gen</value>
     </param>
     <param>
-      <key>style</key>
-      <value>wx.SL_HORIZONTAL</value>
+      <key>samp_rate</key>
+      <value>1.0</value>
     </param>
     <param>
-      <key>converver</key>
-      <value>float_converter</value>
+      <key>sym_rate</key>
+      <value>1./spb_gen</value>
     </param>
     <param>
-      <key>grid_pos</key>
-      <value></value>
+      <key>alpha</key>
+      <value>rolloff</value>
     </param>
     <param>
-      <key>notebook</key>
-      <value></value>
+      <key>ntaps</key>
+      <value>44</value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(552, 4)</value>
+      <value>(978, 157)</value>
     </param>
     <param>
       <key>_rotation</key>
     </param>
   </block>
   <block>
-    <key>variable_slider</key>
+    <key>gr_fll_band_edge_cc</key>
     <param>
       <key>id</key>
-      <value>beta</value>
+      <value>gr_fll_band_edge_cc_0</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>label</key>
-      <value>Freq Beta</value>
-    </param>
-    <param>
-      <key>value</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>min</key>
-      <value>0.0</value>
-    </param>
-    <param>
-      <key>max</key>
-      <value>0.0001</value>
+      <key>type</key>
+      <value>cc</value>
     </param>
     <param>
-      <key>num_steps</key>
-      <value>1000</value>
+      <key>samps_per_sym</key>
+      <value>spb_gen</value>
     </param>
     <param>
-      <key>style</key>
-      <value>wx.SL_HORIZONTAL</value>
+      <key>rolloff</key>
+      <value>rolloff</value>
     </param>
     <param>
-      <key>converver</key>
-      <value>float_converter</value>
+      <key>filter_size</key>
+      <value>44</value>
     </param>
     <param>
-      <key>grid_pos</key>
-      <value></value>
+      <key>alpha</key>
+      <value>alpha</value>
     </param>
     <param>
-      <key>notebook</key>
-      <value></value>
+      <key>beta</key>
+      <value>beta</value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(668, 5)</value>
+      <value>(874, 664)</value>
     </param>
     <param>
       <key>_rotation</key>
-      <value>180</value>
+      <value>0</value>
     </param>
   </block>
   <block>
-    <key>root_raised_cosine_filter</key>
+    <key>gr_channel_model</key>
     <param>
       <key>id</key>
-      <value>root_raised_cosine_filter_0</value>
+      <value>gr_channel_model_0</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>type</key>
-      <value>interp_fir_filter_ccf</value>
-    </param>
-    <param>
-      <key>decim</key>
-      <value>1</value>
-    </param>
-    <param>
-      <key>interp</key>
-      <value>spb_gen</value>
+      <key>noise_voltage</key>
+      <value>noise_amp</value>
     </param>
     <param>
-      <key>gain</key>
-      <value>2*spb_gen</value>
+      <key>freq_offset</key>
+      <value>freq_offset</value>
     </param>
     <param>
-      <key>samp_rate</key>
+      <key>epsilon</key>
       <value>1.0</value>
     </param>
     <param>
-      <key>sym_rate</key>
-      <value>1./spb_gen</value>
-    </param>
-    <param>
-      <key>alpha</key>
-      <value>rolloff</value>
+      <key>taps</key>
+      <value>1.0</value>
     </param>
     <param>
-      <key>ntaps</key>
-      <value>44</value>
+      <key>seed</key>
+      <value>42</value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(978, 157)</value>
+      <value>(618, 376)</value>
     </param>
     <param>
       <key>_rotation</key>
     </param>
   </block>
   <block>
-    <key>gr_fll_band_edge_cc</key>
+    <key>variable_slider</key>
     <param>
       <key>id</key>
-      <value>gr_fll_band_edge_cc_0</value>
+      <value>beta</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>type</key>
-      <value>cc</value>
+      <key>label</key>
+      <value>Freq Beta</value>
     </param>
     <param>
-      <key>samps_per_sym</key>
-      <value>spb_gen</value>
+      <key>value</key>
+      <value>0</value>
     </param>
     <param>
-      <key>rolloff</key>
-      <value>rolloff</value>
+      <key>min</key>
+      <value>0.0</value>
     </param>
     <param>
-      <key>filter_size</key>
-      <value>44</value>
+      <key>max</key>
+      <value>0.01</value>
     </param>
     <param>
-      <key>alpha</key>
-      <value>alpha</value>
+      <key>num_steps</key>
+      <value>1000</value>
     </param>
     <param>
-      <key>beta</key>
-      <value>beta</value>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value></value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(874, 664)</value>
+      <value>(668, 5)</value>
     </param>
     <param>
       <key>_rotation</key>
-      <value>0</value>
+      <value>180</value>
     </param>
   </block>
   <block>
-    <key>gr_channel_model</key>
+    <key>variable_slider</key>
     <param>
       <key>id</key>
-      <value>gr_channel_model_0</value>
+      <value>alpha</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>noise_voltage</key>
-      <value>noise_amp</value>
+      <key>label</key>
+      <value>Freq Alpha</value>
     </param>
     <param>
-      <key>freq_offset</key>
-      <value>freq_offset</value>
+      <key>value</key>
+      <value>0</value>
     </param>
     <param>
-      <key>epsilon</key>
-      <value>1.0</value>
+      <key>min</key>
+      <value>0</value>
     </param>
     <param>
-      <key>taps</key>
-      <value>1.0</value>
+      <key>max</key>
+      <value>0.1</value>
     </param>
     <param>
-      <key>seed</key>
-      <value>42</value>
+      <key>num_steps</key>
+      <value>1000</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value></value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(618, 376)</value>
+      <value>(552, 4)</value>
     </param>
     <param>
       <key>_rotation</key>
index 80a7aef0c668c1a67ea67cc7dd1d67c9b48c5222..8571995a582f95bfc71339bc971b76171b78b133 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version='1.0' encoding='ASCII'?>
 <flow_graph>
-  <timestamp>Mon Feb  1 18:58:32 2010</timestamp>
+  <timestamp>Sat Mar  6 17:17:22 2010</timestamp>
   <block>
     <key>options</key>
     <param>
       <value>0</value>
     </param>
   </block>
-  <block>
-    <key>variable_slider</key>
-    <param>
-      <key>id</key>
-      <value>freq_beta</value>
-    </param>
-    <param>
-      <key>_enabled</key>
-      <value>True</value>
-    </param>
-    <param>
-      <key>label</key>
-      <value>Freq Beta</value>
-    </param>
-    <param>
-      <key>value</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>min</key>
-      <value>0.0</value>
-    </param>
-    <param>
-      <key>max</key>
-      <value>0.0001</value>
-    </param>
-    <param>
-      <key>num_steps</key>
-      <value>1000</value>
-    </param>
-    <param>
-      <key>style</key>
-      <value>wx.SL_HORIZONTAL</value>
-    </param>
-    <param>
-      <key>converver</key>
-      <value>float_converter</value>
-    </param>
-    <param>
-      <key>grid_pos</key>
-      <value></value>
-    </param>
-    <param>
-      <key>notebook</key>
-      <value></value>
-    </param>
-    <param>
-      <key>_coordinate</key>
-      <value>(836, 9)</value>
-    </param>
-    <param>
-      <key>_rotation</key>
-      <value>180</value>
-    </param>
-  </block>
-  <block>
-    <key>variable_slider</key>
-    <param>
-      <key>id</key>
-      <value>freq_alpha</value>
-    </param>
-    <param>
-      <key>_enabled</key>
-      <value>True</value>
-    </param>
-    <param>
-      <key>label</key>
-      <value>Freq Alpha</value>
-    </param>
-    <param>
-      <key>value</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>min</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>max</key>
-      <value>0.001</value>
-    </param>
-    <param>
-      <key>num_steps</key>
-      <value>1000</value>
-    </param>
-    <param>
-      <key>style</key>
-      <value>wx.SL_HORIZONTAL</value>
-    </param>
-    <param>
-      <key>converver</key>
-      <value>float_converter</value>
-    </param>
-    <param>
-      <key>grid_pos</key>
-      <value></value>
-    </param>
-    <param>
-      <key>notebook</key>
-      <value></value>
-    </param>
-    <param>
-      <key>_coordinate</key>
-      <value>(734, 10)</value>
-    </param>
-    <param>
-      <key>_rotation</key>
-      <value>0</value>
-    </param>
-  </block>
   <block>
     <key>variable_slider</key>
     <param>
       <value>0</value>
     </param>
   </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>freq_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Freq Alpha</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>0.1</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>1000</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value></value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(734, 10)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>freq_beta</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Freq Beta</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0.0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>0.01</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>1000</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value></value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(836, 9)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>180</value>
+    </param>
+  </block>
   <connection>
     <source_block_id>random_source_x_0</source_block_id>
     <sink_block_id>gr_uchar_to_float_0</sink_block_id>
index 4cc4a7bee3698f1a14ae36706ce9c37307dd6ef7..47e4f20288a91e23ba5b57fbf7638b2dc217bc0f 100755 (executable)
@@ -44,6 +44,11 @@ class my_top_block(gr.top_block):
         noise_power = power_in_signal/SNR
         noise_voltage = math.sqrt(noise_power)
 
+        # With new interface, sps does not get set by default, but
+        # in the loopback, we don't recalculate it; so just force it here
+        if(options.samples_per_symbol == None):
+            options.samples_per_symbol = 2
+
         self.txpath = transmit_path(mod_class, options)
         self.throttle = gr.throttle(gr.sizeof_gr_complex, options.sample_rate)
         self.rxpath = receive_path(demod_class, rx_callback, options)
index 1cb95198e67d527c5cee6709dc2d35ab2b83e4c9..56c6c7f52e22f8dd2493c339938ff4641366cdbb 100755 (executable)
@@ -1,6 +1,26 @@
 #!/usr/bin/env python
-
-from gnuradio import gr, gru, modulation_utils
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr, gru, modulation_utils2
 from gnuradio import eng_notation
 from gnuradio.eng_option import eng_option
 from optparse import OptionParser
@@ -223,6 +243,11 @@ class my_top_block(gr.top_block):
 
         self._noise_voltage = self.get_noise_voltage(self._snr_dB)
 
+        # With new interface, sps does not get set by default, but
+        # in the loopback, we don't recalculate it; so just force it here
+        if(options.samples_per_symbol == None):
+            options.samples_per_symbol = 2
+
         self.txpath = transmit_path(mod_class, options)
         self.throttle = gr.throttle(gr.sizeof_gr_complex, self.sample_rate())
         self.rxpath = receive_path(demod_class, rx_callback, options)
@@ -269,6 +294,7 @@ class my_top_block(gr.top_block):
                 self.phase_recov = self.rxpath.packet_receiver._demodulator.phase_recov
                 self.time_recov = self.rxpath.packet_receiver._demodulator.time_recov
                 self.freq_recov.set_alpha(self._gain_freq)
+                self.freq_recov.set_beta(self._gain_freq/10.0)
                 self.phase_recov.set_alpha(self._gain_phase)
                 self.phase_recov.set_beta(0.25*self._gain_phase*self._gain_phase)
                 self.time_recov.set_alpha(self._gain_clock)
@@ -367,6 +393,7 @@ class my_top_block(gr.top_block):
         self._gain_freq = gain_freq
         #self._gain_freq_beta = .25 * self._gain_freq * self._gain_freq
         self.rxpath.packet_receiver._demodulator.freq_recov.set_alpha(self._gain_freq)
+        self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_freq/10.0)
         #self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_fre_beta)
 
 
@@ -431,15 +458,15 @@ def main():
     def send_pkt(payload='', eof=False):
         return tb.txpath.send_pkt(payload, eof)
 
-    mods = modulation_utils.type_1_mods()
-    demods = modulation_utils.type_1_demods()
+    mods = modulation_utils2.type_1_mods()
+    demods = modulation_utils2.type_1_demods()
 
     parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
     expert_grp = parser.add_option_group("Expert")
     channel_grp = parser.add_option_group("Channel")
 
     parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(),
-                      default='dbpsk',
+                      default='dbpsk2',
                       help="Select modulation from: %s [default=%%default]"
                             % (', '.join(mods.keys()),))
 
index cabbecb6ffa6d428b82eeededdf7d6ec8614fc55..0c37f4c6a8d00d4447614b200c94d2d5d2733607 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc.
+# Copyright 2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -20,7 +20,7 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import gr, gru, modulation_utils
+from gnuradio import gr, gru, modulation_utils2
 from gnuradio import usrp
 from gnuradio import eng_notation
 from gnuradio.eng_option import eng_option
@@ -33,7 +33,7 @@ import sys
 
 # from current dir
 from receive_path import receive_path
-from pick_bitrate import pick_rx_bitrate
+from pick_bitrate2 import pick_rx_bitrate
 
 try:
     from gnuradio.qtgui import qtgui
@@ -219,7 +219,7 @@ class my_top_block(gr.top_block):
 
         # FIXME: do better exposure to lower issues for control
         self._gain_clock = self.rxpath.packet_receiver._demodulator._timing_alpha
-        self._gain_phase = self.rxpath.packet_receiver._demodulator._costas_alpha
+        self._gain_phase = self.rxpath.packet_receiver._demodulator._phase_alpha
         self._gain_freq  = self.rxpath.packet_receiver._demodulator._freq_alpha
 
         self.connect(self.u, self.rxpath)
@@ -242,8 +242,8 @@ class my_top_block(gr.top_block):
             
             # Connect to the QT sinks
             # FIXME: make better exposure to receiver from rxpath
-            #self.receiver = self.rxpath.packet_receiver._demodulator.phase_recov
-            self.receiver = self.rxpath.packet_receiver._demodulator.freq_recov
+            self.receiver = self.rxpath.packet_receiver._demodulator.phase_recov
+            #self.receiver = self.rxpath.packet_receiver._demodulator.freq_recov
             self.connect(self.u, self.snk_rxin)
             self.connect(self.receiver, self.snk_rx)
             
@@ -267,9 +267,9 @@ class my_top_block(gr.top_block):
         self.u.set_decim(self._decim)
 
         (self._bitrate, self._samples_per_symbol, self._decim) = \
-                        pick_rx_bitrate(self._bitrate, self._demod_class.bits_per_symbol(), \
-                                        self._samples_per_symbol, self._decim, adc_rate,  \
-                                        self.u.get_decim_rates())
+                        pick_rx_bitrate(options.bitrate, self._demod_class.bits_per_symbol(), \
+                                        options.samples_per_symbol, options.decim, \
+                                        adc_rate, self.u.get_decim_rates())
 
         self.u.set_decim(self._decim)
         self.set_auto_tr(True)                 # enable Auto Transmit/Receive switching
@@ -353,6 +353,7 @@ class my_top_block(gr.top_block):
         self._gain_freq = gain_freq
         #self._gain_freq_beta = .25 * self._gain_freq * self._gain_freq
         self.rxpath.packet_receiver._demodulator.freq_recov.set_alpha(self._gain_freq)
+        self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_freq/10.0)
         #self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_fre_beta)
 
 
@@ -423,14 +424,14 @@ def main():
                 ok, pktno, n_rcvd, n_right)
 
 
-    demods = modulation_utils.type_1_demods()
+    demods = modulation_utils2.type_1_demods()
 
     # Create Options Parser:
     parser = OptionParser (option_class=eng_option, conflict_handler="resolve")
     expert_grp = parser.add_option_group("Expert")
 
     parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), 
-                      default='dbpsk',
+                      default='dbpsk2',
                       help="Select modulation from: %s [default=%%default]"
                             % (', '.join(demods.keys()),))
 
diff --git a/gnuradio-examples/python/digital/benchmark_rx2.py b/gnuradio-examples/python/digital/benchmark_rx2.py
new file mode 100755 (executable)
index 0000000..fe422be
--- /dev/null
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr, gru, modulation_utils2
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random
+import struct
+import sys
+
+# from current dir
+import usrp_receive_path2
+
+#import os
+#print os.getpid()
+#raw_input('Attach and press enter: ')
+
+class my_top_block(gr.top_block):
+    def __init__(self, demodulator, rx_callback, options):
+        gr.top_block.__init__(self)
+
+        # Set up receive path
+        self.rxpath = usrp_receive_path2.usrp_receive_path(demodulator, rx_callback, options) 
+
+        self.connect(self.rxpath)
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+global n_rcvd, n_right
+
+def main():
+    global n_rcvd, n_right
+
+    n_rcvd = 0
+    n_right = 0
+    
+    def rx_callback(ok, payload):
+        global n_rcvd, n_right
+        (pktno,) = struct.unpack('!H', payload[0:2])
+        n_rcvd += 1
+        if ok:
+            n_right += 1
+
+        print "ok = %5s  pktno = %4d  n_rcvd = %4d  n_right = %4d" % (
+            ok, pktno, n_rcvd, n_right)
+
+
+    demods = modulation_utils2.type_1_demods()
+
+    # Create Options Parser:
+    parser = OptionParser (option_class=eng_option, conflict_handler="resolve")
+    expert_grp = parser.add_option_group("Expert")
+
+    parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), 
+                      default='dbpsk2',
+                      help="Select modulation from: %s [default=%%default]"
+                            % (', '.join(demods.keys()),))
+
+    usrp_receive_path2.add_options(parser, expert_grp)
+
+    for mod in demods.values():
+        mod.add_options(expert_grp)
+
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help(sys.stderr)
+        sys.exit(1)
+
+    if options.rx_freq is None:
+        sys.stderr.write("You must specify -f FREQ or --freq FREQ\n")
+        parser.print_help(sys.stderr)
+        sys.exit(1)
+
+
+    # build the graph
+    tb = my_top_block(demods[options.modulation], rx_callback, options)
+
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: Failed to enable realtime scheduling."
+
+    tb.start()        # start flow graph
+    tb.wait()         # wait for it to finish
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/digital/benchmark_tx2.py b/gnuradio-examples/python/digital/benchmark_tx2.py
new file mode 100755 (executable)
index 0000000..6093dba
--- /dev/null
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr, gru, modulation_utils2
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random, time, struct, sys
+
+# from current dir
+import usrp_transmit_path2
+
+#import os 
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+class my_top_block(gr.top_block):
+    def __init__(self, modulator, options):
+        gr.top_block.__init__(self)
+
+        self.txpath = usrp_transmit_path2.usrp_transmit_path(modulator, options)
+
+        self.connect(self.txpath)
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+
+    def send_pkt(payload='', eof=False):
+        return tb.txpath.send_pkt(payload, eof)
+
+    def rx_callback(ok, payload):
+        print "ok = %r, payload = '%s'" % (ok, payload)
+
+    mods = modulation_utils2.type_1_mods()
+
+    parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
+    expert_grp = parser.add_option_group("Expert")
+
+    parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(),
+                      default='dbpsk2',
+                      help="Select modulation from: %s [default=%%default]"
+                            % (', '.join(mods.keys()),))
+
+    parser.add_option("-s", "--size", type="eng_float", default=1500,
+                      help="set packet size [default=%default]")
+    parser.add_option("-M", "--megabytes", type="eng_float", default=1.0,
+                      help="set megabytes to transmit [default=%default]")
+    parser.add_option("","--discontinuous", action="store_true", default=False,
+                      help="enable discontinous transmission (bursts of 5 packets)")
+    parser.add_option("","--from-file", default=None,
+                      help="use file for packet contents")
+
+    usrp_transmit_path2.add_options(parser, expert_grp)
+
+    for mod in mods.values():
+        mod.add_options(expert_grp)
+
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.tx_freq is None:
+        sys.stderr.write("You must specify -f FREQ or --freq FREQ\n")
+        parser.print_help(sys.stderr)
+        sys.exit(1)
+
+    if options.from_file is not None:
+        source_file = open(options.from_file, 'r')
+
+    # build the graph
+    tb = my_top_block(mods[options.modulation], options)
+
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: failed to enable realtime scheduling"
+
+    tb.start()                       # start flow graph
+        
+    # generate and send packets
+    nbytes = int(1e6 * options.megabytes)
+    n = 0
+    pktno = 0
+    pkt_size = int(options.size)
+
+    while n < nbytes:
+        if options.from_file is None:
+            data = (pkt_size - 2) * chr(pktno & 0xff) 
+        else:
+            data = source_file.read(pkt_size - 2)
+            if data == '':
+                break;
+
+        payload = struct.pack('!H', pktno & 0xffff) + data
+        send_pkt(payload)
+        n += len(payload)
+        sys.stderr.write('.')
+        if options.discontinuous and pktno % 5 == 4:
+            time.sleep(1)
+        pktno += 1
+        
+    send_pkt(eof=True)
+
+    tb.wait()                       # wait for it to finish
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/digital/pick_bitrate2.py b/gnuradio-examples/python/digital/pick_bitrate2.py
new file mode 100644 (file)
index 0000000..9253956
--- /dev/null
@@ -0,0 +1,154 @@
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import eng_notation
+
+_default_bitrate = 500e3
+_sps_min = 2
+_sps_max = 100
+
+def _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                  xrate, converter_rate, xrates):
+    """
+    @returns tuple (bitrate, samples_per_symbol, interp_rate_or_decim_rate)
+    """
+
+    if not isinstance(bits_per_symbol, int) or bits_per_symbol < 1:
+        raise ValueError, "bits_per_symbol must be an int >= 1"
+
+    converter_rate = float(converter_rate)
+    bits_per_symbol = float(bits_per_symbol)
+
+    # completely determined; if bitrate is specified, this overwrites it
+    if (samples_per_symbol is not None) and (xrate is not None):
+        bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+
+    # If only SPS is given
+    if (bitrate is None) and (samples_per_symbol is not None) and (xrate is None):
+        xrate = max(xrates)
+        bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+        
+    # If only xrate is given, just set SPS to 2 and calculate bitrate
+    if (bitrate is None) and (samples_per_symbol is None) and (xrate is not None):
+        samples_per_symbol = 2.0
+        bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+
+    # If no parameters are give, use the default bit rate
+    if (bitrate is None) and (samples_per_symbol is None) and (xrate is None):
+        bitrate = _default_bitrate
+
+    # If only bitrate is specified, return max xrate and appropriate
+    # samples per symbol (minimum of 2.0) to reach bit rate
+    if (samples_per_symbol is None) and (xrate is None):
+        xrates.sort()
+        for i in xrange(len(xrates)):
+            if((converter_rate / bits_per_symbol / xrates[i]) >= 2*bitrate):
+                rate = xrates[i]
+            else:
+                break
+
+        try:
+            xrate = rate
+        except UnboundLocalError:
+            raise ValueError("Requested bitrate out of bounds")
+            
+        samples_per_symbol = converter_rate / bits_per_symbol / rate / bitrate
+        bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+
+    # If bitrate and xrate are specified
+    if(samples_per_symbol is None):
+        samples_per_symbol = converter_rate / xrate / bits_per_symbol / bitrate
+
+    # If bitrate and SPS are specified
+    if(xrate is None):
+        xrate = converter_rate / samples_per_symbol / bits_per_symbol / bitrate
+        if((xrate in xrates) == False):
+            # Find the closest avaiable rate larger than the calculated one
+            xrates.sort()
+            for x in xrates:
+                if(x > xrate):
+                    xrate = x
+                    break
+            if(xrate > max(xrates)):
+                xrate = max(xrates)
+            
+            bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+            print "Could not find suitable rate for specified SPS and Bitrate"
+            print "Using rate = %d for bitrate of %sbps" % \
+                  (xrate, (eng_notation.num_to_str(bitrate)))
+
+    if((xrate in xrates) == False):
+        raise ValueError(("Invalid rate (rate = %d)" % xrate))
+    if((samples_per_symbol < _sps_min) or (samples_per_symbol > _sps_max)):
+        raise ValueError(("Invalid samples per symbol (sps = %.2f). Must be in [%.0f, %.0f]." \
+                          % (samples_per_symbol, _sps_min, _sps_max)))
+        
+    return (bitrate, samples_per_symbol, int(xrate))
+
+
+def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                    interp_rate, converter_rate, possible_interps):
+    """
+    Given the 4 input parameters, return at configuration that matches
+
+    @param bitrate: desired bitrate or None
+    @type bitrate: number or None
+    @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3
+    @type bits_per_symbol: integer >= 1
+    @param samples_per_symbol: samples/baud (aka samples/symbol)
+    @type samples_per_symbol: number or None
+    @param interp_rate: USRP interpolation factor
+    @type interp_rate: integer or None
+    @param converter_rate: converter sample rate in Hz
+    @type converter_rate: number
+    @param possible_interps: a list of possible rates
+    @type possible_interps: a list of integers
+
+    @returns tuple (bitrate, samples_per_symbol, interp_rate)
+    """
+
+    return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                         interp_rate, converter_rate, possible_interps)
+
+
+def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                    decim_rate, converter_rate, possible_decims):
+    """
+    Given the 4 input parameters, return at configuration that matches
+
+    @param bitrate: desired bitrate or None
+    @type bitrate: number or None
+    @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3
+    @type bits_per_symbol: integer >= 1
+    @param samples_per_symbol: samples/baud (aka samples/symbol)
+    @type samples_per_symbol: number or None
+    @param decim_rate: USRP decimation factor
+    @type decim_rate: integer or None
+    @param converter_rate: converter sample rate in Hz
+    @type converter_rate: number
+    @param possible_decims: a list of possible rates
+    @type possible_decims: a list of integers
+
+    @returns tuple (bitrate, samples_per_symbol, decim_rate)
+    """
+
+    return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                         decim_rate, converter_rate, possible_decims)
index c229aa9e4784c9f6d848d893b0d42c520d52d87c..0024d6941f714778d61c43b040a2aeb575c95816 100644 (file)
@@ -119,7 +119,7 @@ class receive_path(gr.hier_block2):
             normal.add_option("-r", "--bitrate", type="eng_float", default=100e3,
                               help="specify bitrate [default=%default].")
         normal.add_option("-v", "--verbose", action="store_true", default=False)
-        expert.add_option("-S", "--samples-per-symbol", type="int", default=2,
+        expert.add_option("-S", "--samples-per-symbol", type="float", default=None,
                           help="set samples/symbol [default=%default]")
         expert.add_option("", "--log", action="store_true", default=False,
                           help="Log all parts of flow graph to files (CAUTION: lots of data)")
@@ -135,4 +135,4 @@ class receive_path(gr.hier_block2):
         print "\nReceive Path:"
         print "modulation:      %s"    % (self._demod_class.__name__)
         print "bitrate:         %sb/s" % (eng_notation.num_to_str(self._bitrate))
-        print "samples/symbol:  %3d"   % (self._samples_per_symbol)
+        print "samples/symbol:  %.4f"   % (self._samples_per_symbol)
index 9badcdc0840499d081bc0355c99e401cb2c45da2..86ebf75c3e87b70482f5a110b7dc664450ee16f3 100644 (file)
@@ -99,7 +99,7 @@ class transmit_path(gr.hier_block2):
                           help="set transmitter digital amplitude: 0 <= AMPL < 1 [default=%default]")
         normal.add_option("-v", "--verbose", action="store_true", default=False)
 
-        expert.add_option("-S", "--samples-per-symbol", type="int", default=2,
+        expert.add_option("-S", "--samples-per-symbol", type="float", default=None,
                           help="set samples/symbol [default=%default]")
         expert.add_option("", "--log", action="store_true", default=False,
                           help="Log all parts of flow graph to file (CAUTION: lots of data)")
@@ -114,5 +114,5 @@ class transmit_path(gr.hier_block2):
         print "Tx amplitude     %s"    % (self._tx_amplitude)
         print "modulation:      %s"    % (self._modulator_class.__name__)
         print "bitrate:         %sb/s" % (eng_notation.num_to_str(self._bitrate))
-        print "samples/symbol:  %3d"   % (self._samples_per_symbol)
+        print "samples/symbol:  %.4f"    % (self._samples_per_symbol)
         
index 517825cc1b53881bed8a1b78f700185f05fcb161..a8f16e28a9f5b884369f5c1731778c5a0abb2d42 100644 (file)
@@ -59,37 +59,35 @@ class usrp_receive_path(gr.hier_block2):
         if options.rx_freq is None:
             sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n")
             raise SystemExit
-        rx_path = receive_path.receive_path(demod_class, rx_callback, options)
-        for attr in dir(rx_path): #forward the methods
-            if not attr.startswith('_') and not hasattr(self, attr):
-                setattr(self, attr, getattr(rx_path, attr))
 
         #setup usrp
         self._demod_class = demod_class
         self._setup_usrp_source(options)
 
-        # Set up resampler based on rate determined by _setup_usrp_source
-        rs_taps = gr.firdes.low_pass_2(32, 32, 0.45, 0.1, 60)
-        self.resampler = gr.pfb_arb_resampler_ccf(self.rs_rate, rs_taps)
+        rx_path = receive_path.receive_path(demod_class, rx_callback, options)
+        for attr in dir(rx_path): #forward the methods
+            if not attr.startswith('_') and not hasattr(self, attr):
+                setattr(self, attr, getattr(rx_path, attr))
 
         #connect
-        self.connect(self.u, self.resampler, rx_path)
+        self.connect(self.u, rx_path)
 
     def _setup_usrp_source(self, options):
         self.u = usrp_options.create_usrp_source(options)
         adc_rate = self.u.adc_rate()
         self.rs_rate = options.bitrate
-        if options.verbose:
-            print 'USRP Source:', self.u
+
         (self._bitrate, self._samples_per_symbol, self._decim) = \
                         pick_rx_bitrate(options.bitrate, self._demod_class.bits_per_symbol(), \
-                                        options.samples_per_symbol, options.decim, adc_rate,  \
-                                        self.u.get_decim_rates())
+                                        options.samples_per_symbol, options.decim,
+                                        adc_rate, self.u.get_decim_rates())
 
-        # Calculate resampler rate based on requested and actual rates
-        self.rs_rate = 1.0 /(self._bitrate / self.rs_rate)
-        
-        print "Resampling by %f to get bitrate of %ssps" % ( self.rs_rate, eng_notation.num_to_str(self._bitrate/self.rs_rate))
+        if options.verbose:
+            print 'USRP Source:', self.u
+            print 'Decimation: ', self._decim
+
+        options.samples_per_symbol = self._samples_per_symbol
+        options.decim = self._decim
         
         self.u.set_decim(self._decim)
 
diff --git a/gnuradio-examples/python/digital/usrp_receive_path2.py b/gnuradio-examples/python/digital/usrp_receive_path2.py
new file mode 100644 (file)
index 0000000..d200172
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import usrp_options
+import receive_path
+from pick_bitrate2 import pick_rx_bitrate
+from gnuradio import eng_notation
+
+def add_freq_option(parser):
+    """
+    Hackery that has the -f / --freq option set both tx_freq and rx_freq
+    """
+    def freq_callback(option, opt_str, value, parser):
+        parser.values.rx_freq = value
+        parser.values.tx_freq = value
+
+    if not parser.has_option('--freq'):
+        parser.add_option('-f', '--freq', type="eng_float",
+                          action="callback", callback=freq_callback,
+                          help="set Tx and/or Rx frequency to FREQ [default=%default]",
+                          metavar="FREQ")
+
+def add_options(parser, expert):
+    add_freq_option(parser)
+    usrp_options.add_rx_options(parser)
+    receive_path.receive_path.add_options(parser, expert)
+    expert.add_option("", "--rx-freq", type="eng_float", default=None,
+                          help="set Rx frequency to FREQ [default=%default]", metavar="FREQ")
+    parser.add_option("-v", "--verbose", action="store_true", default=False)
+
+class usrp_receive_path(gr.hier_block2):
+
+    def __init__(self, demod_class, rx_callback, options):
+        '''
+        See below for what options should hold
+        '''
+        gr.hier_block2.__init__(self, "usrp_receive_path",
+                gr.io_signature(0, 0, 0),                    # Input signature
+                gr.io_signature(0, 0, 0)) # Output signature
+        if options.rx_freq is None:
+            sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n")
+            raise SystemExit
+
+        #setup usrp
+        self._demod_class = demod_class
+        self._setup_usrp_source(options)
+
+        rx_path = receive_path.receive_path(demod_class, rx_callback, options)
+        for attr in dir(rx_path): #forward the methods
+            if not attr.startswith('_') and not hasattr(self, attr):
+                setattr(self, attr, getattr(rx_path, attr))
+
+        #connect
+        self.connect(self.u, rx_path)
+
+    def _setup_usrp_source(self, options):
+        self.u = usrp_options.create_usrp_source(options)
+        adc_rate = self.u.adc_rate()
+        self.rs_rate = options.bitrate
+
+        (self._bitrate, self._samples_per_symbol, self._decim) = \
+                        pick_rx_bitrate(options.bitrate, self._demod_class.bits_per_symbol(), \
+                                        options.samples_per_symbol, options.decim,
+                                        adc_rate, self.u.get_decim_rates())
+
+        if options.verbose:
+            print 'USRP Source:', self.u
+            print 'Decimation: ', self._decim
+
+        options.samples_per_symbol = self._samples_per_symbol
+        options.decim = self._decim
+        
+        self.u.set_decim(self._decim)
+
+        if not self.u.set_center_freq(options.rx_freq):
+            print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.rx_freq))
+            raise ValueError, eng_notation.num_to_str(options.rx_freq)
index ee63dcd2b7e2d35a07194ef94fe81840c8269179..f0f467599a6f6e78b0d4dfce46cce6d1facda01d 100644 (file)
@@ -58,21 +58,18 @@ class usrp_transmit_path(gr.hier_block2):
         if options.tx_freq is None:
             sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n")
             raise SystemExit
-        tx_path = transmit_path.transmit_path(modulator_class, options)
-        for attr in dir(tx_path): #forward the methods
-            if not attr.startswith('_') and not hasattr(self, attr):
-                setattr(self, attr, getattr(tx_path, attr))
 
         #setup usrp
         self._modulator_class = modulator_class
         self._setup_usrp_sink(options)
 
-        # Set up resampler based on rate determined by _setup_usrp_sink
-        rs_taps = gr.firdes.low_pass_2(32, 32, 0.45, 0.1, 60)
-        self.resampler = gr.pfb_arb_resampler_ccf(self.rs_rate, rs_taps)
+        tx_path = transmit_path.transmit_path(modulator_class, options)
+        for attr in dir(tx_path): #forward the methods
+            if not attr.startswith('_') and not hasattr(self, attr):
+                setattr(self, attr, getattr(tx_path, attr))
 
         #connect
-        self.connect(tx_path, self.resampler, self.u)
+        self.connect(tx_path, self.u)
         
     def _setup_usrp_sink(self, options):
         """
@@ -82,17 +79,20 @@ class usrp_transmit_path(gr.hier_block2):
         self.u = usrp_options.create_usrp_sink(options)
         dac_rate = self.u.dac_rate()
         self.rs_rate = options.bitrate    # Store requested bit rate
-        if options.verbose:
-            print 'USRP Sink:', self.u
+            
         (self._bitrate, self._samples_per_symbol, self._interp) = \
-                        pick_tx_bitrate(options.bitrate, self._modulator_class.bits_per_symbol(), \
-                                        options.samples_per_symbol, options.interp, dac_rate, \
-                                        self.u.get_interp_rates())
+                        pick_tx_bitrate(options.bitrate, self._modulator_class.bits_per_symbol(),
+                                        options.samples_per_symbol, options.interp,
+                                        dac_rate, self.u.get_interp_rates())
 
-        # Calculate resampler rate based on requested and actual rates
-        self.rs_rate = self._bitrate / self.rs_rate
-        print "Resampling by %f to get bitrate of %ssps" % (self.rs_rate, eng_notation.num_to_str(self._bitrate/self.rs_rate))
+        options.interp = self._interp
+        options.samples_per_symbol = self._samples_per_symbol
+        options.bitrate = self._bitrate
 
+        if options.verbose:
+            print 'USRP Sink:', self.u
+            print "Interpolation Rate: ", self._interp
+        
         self.u.set_interp(self._interp)
         self.u.set_auto_tr(True)
 
diff --git a/gnuradio-examples/python/digital/usrp_transmit_path2.py b/gnuradio-examples/python/digital/usrp_transmit_path2.py
new file mode 100644 (file)
index 0000000..54930e5
--- /dev/null
@@ -0,0 +1,101 @@
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import usrp_options
+import transmit_path
+from pick_bitrate2 import pick_tx_bitrate
+from gnuradio import eng_notation
+
+def add_freq_option(parser):
+    """
+    Hackery that has the -f / --freq option set both tx_freq and rx_freq
+    """
+    def freq_callback(option, opt_str, value, parser):
+        parser.values.rx_freq = value
+        parser.values.tx_freq = value
+
+    if not parser.has_option('--freq'):
+        parser.add_option('-f', '--freq', type="eng_float",
+                          action="callback", callback=freq_callback,
+                          help="set Tx and/or Rx frequency to FREQ [default=%default]",
+                          metavar="FREQ")
+
+def add_options(parser, expert):
+    add_freq_option(parser)
+    usrp_options.add_tx_options(parser)
+    transmit_path.transmit_path.add_options(parser, expert)
+    expert.add_option("", "--tx-freq", type="eng_float", default=None,
+                          help="set transmit frequency to FREQ [default=%default]", metavar="FREQ")
+    parser.add_option("-v", "--verbose", action="store_true", default=False)
+
+class usrp_transmit_path(gr.hier_block2):
+    def __init__(self, modulator_class, options):
+        '''
+        See below for what options should hold
+        '''
+        gr.hier_block2.__init__(self, "usrp_transmit_path",
+                gr.io_signature(0, 0, 0),                    # Input signature
+                gr.io_signature(0, 0, 0)) # Output signature
+        if options.tx_freq is None:
+            sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n")
+            raise SystemExit
+
+        #setup usrp
+        self._modulator_class = modulator_class
+        self._setup_usrp_sink(options)
+
+        tx_path = transmit_path.transmit_path(modulator_class, options)
+        for attr in dir(tx_path): #forward the methods
+            if not attr.startswith('_') and not hasattr(self, attr):
+                setattr(self, attr, getattr(tx_path, attr))
+
+        #connect
+        self.connect(tx_path, self.u)
+        
+    def _setup_usrp_sink(self, options):
+        """
+        Creates a USRP sink, determines the settings for best bitrate,
+        and attaches to the transmitter's subdevice.
+        """
+        self.u = usrp_options.create_usrp_sink(options)
+        dac_rate = self.u.dac_rate()
+        self.rs_rate = options.bitrate    # Store requested bit rate
+            
+        (self._bitrate, self._samples_per_symbol, self._interp) = \
+                        pick_tx_bitrate(options.bitrate, self._modulator_class.bits_per_symbol(),
+                                        options.samples_per_symbol, options.interp,
+                                        dac_rate, self.u.get_interp_rates())
+
+        options.interp = self._interp
+        options.samples_per_symbol = self._samples_per_symbol
+        options.bitrate = self._bitrate
+
+        if options.verbose:
+            print 'USRP Sink:', self.u
+            print "Interpolation Rate: ", self._interp
+        
+        self.u.set_interp(self._interp)
+        self.u.set_auto_tr(True)
+
+        if not self.u.set_center_freq(options.tx_freq):
+            print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.tx_freq))
+            raise ValueError, eng_notation.num_to_str(options.tx_freq)