Making old and new digital modulations completely seperable by adding modulation_util...
authorTom Rondeau <trondeau@vt.edu>
Sun, 14 Mar 2010 21:32:23 +0000 (17:32 -0400)
committerTom Rondeau <trondeau@vt.edu>
Sun, 14 Mar 2010 21:32:23 +0000 (17:32 -0400)
gnuradio-core/src/python/gnuradio/Makefile.am
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-examples/python/digital/benchmark_qt_loopback2.py
gnuradio-examples/python/digital/benchmark_qt_rx2.py
gnuradio-examples/python/digital/benchmark_rx2.py
gnuradio-examples/python/digital/benchmark_tx2.py

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 135b38e1f5ae26d222383cc7ccb5f0f7ac3ef21a..2d073afec5a27c10063fa40da1eb16ca4bada96b 100644 (file)
@@ -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
@@ -39,7 +39,7 @@ _def_verbose = False
 _def_log = False
 
 _def_freq_alpha = 0.010
-_def_costas_alpha = 0.1
+_def_phase_alpha = 0.1
 _def_timing_alpha = 0.100
 _def_timing_beta = 0.010
 _def_timing_max_dev = 1.5
@@ -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
@@ -227,7 +227,7 @@ class dbpsk2_demod(gr.hier_block2):
         self._excess_bw = excess_bw
         self._freq_alpha = freq_alpha
         self._freq_beta = 0.10*self._freq_alpha
-        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
@@ -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
@@ -309,11 +309,11 @@ class dbpsk2_demod(gr.hier_block2):
         print "Gray code:           %s"   % self._gray_code
         print "RRC roll-off factor: %.2f" % self._excess_bw
         print "FLL gain:            %.2e" % self._freq_alpha
-        print "Costas Loop alpha:   %.2e" % self._costas_alpha
-        print "Costas Loop beta:    %.2e" % self._costas_beta
         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."
@@ -328,7 +328,7 @@ class dbpsk2_demod(gr.hier_block2):
         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,
@@ -345,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)")
@@ -359,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 f852a324c61b5d4d50c1a0312d74b3bcb67be1e3..856b4cb693ebe79dd553c02468234714295c80b4 100644 (file)
@@ -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
@@ -39,7 +39,7 @@ _def_verbose = False
 _def_log = False
 
 _def_freq_alpha = 0.010
-_def_costas_alpha = 0.01
+_def_phase_alpha = 0.01
 _def_timing_alpha = 0.100
 _def_timing_beta = 0.010
 _def_timing_max_dev = 1.5
@@ -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,11 +315,11 @@ 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."
@@ -342,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)")
@@ -351,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)")
@@ -365,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)
 
@@ -373,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..71ba773
--- /dev/null
@@ -0,0 +1,81 @@
+#
+# Copyright 2006 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 1f236fd7fe5975b724258a59c1de31ffd07784fa..acf370cfd63466378d271aad26f2cac0754d5924 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-from gnuradio import gr, gru, modulation_utils
+from gnuradio import gr, gru, modulation_utils2
 from gnuradio import eng_notation
 from gnuradio.eng_option import eng_option
 from optparse import OptionParser
@@ -438,15 +438,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 d9d58e537b50c55e1ae92f72c644969caf412edf..6fad31a9441b2affce6968c18aab9e6541536f8b 100755 (executable)
@@ -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
@@ -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)
@@ -424,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()),))
 
index cc3dd67277d08b7932f5c47b5826de4166f5221d..ed6d4f0f52180774fa8fe96a804a4e9c9399aa7b 100755 (executable)
@@ -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
@@ -69,14 +69,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='gmsk',
+                      default='dbpsk2',
                       help="Select modulation from: %s [default=%%default]"
                             % (', '.join(demods.keys()),))
 
index a79ac7cc353051da9f52f27951ff074a47912222..670c4052c3da0ae741209003db08babc5c7aa77b 100755 (executable)
@@ -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
@@ -55,13 +55,13 @@ def main():
     def rx_callback(ok, payload):
         print "ok = %r, payload = '%s'" % (ok, payload)
 
-    mods = modulation_utils.type_1_mods()
+    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='gmsk',
+                      default='dbpsk2',
                       help="Select modulation from: %s [default=%%default]"
                             % (', '.join(mods.keys()),))