commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r3510 - in gnuradio/branches/developers/trondeau/wip2:


From: trondeau
Subject: [Commit-gnuradio] r3510 - in gnuradio/branches/developers/trondeau/wip2: gnuradio-core/src/python/gnuradio/blksimpl gnuradio-examples/python/gmsk2
Date: Sat, 9 Sep 2006 16:14:18 -0600 (MDT)

Author: trondeau
Date: 2006-09-09 16:14:17 -0600 (Sat, 09 Sep 2006)
New Revision: 3510

Added:
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/bpsk.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/dbpsk.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/dqpsk.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/gmsk.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/modulators.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/psk.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/qpsk.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_tx.py
Removed:
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2_pkt.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/bpsk.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/dbpsk.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/dqpsk.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/qpsk.py
Modified:
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py
   
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/transmit_path.py
Log:
work in progress: reformatting digital modulation

Modified: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am
   2006-09-09 16:15:29 UTC (rev 3509)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am
   2006-09-09 22:14:17 UTC (rev 3510)
@@ -29,14 +29,18 @@
 grblkspython_PYTHON =          \
        __init__.py             \
        am_demod.py             \
+       bpsk.py                 \
+       dbpsk.py                \
+       dqpsk.py                \
        filterbank.py           \
        fm_demod.py             \
        fm_emph.py              \
-       gmsk2.py                \
-       gmsk2_pkt.py            \
+       gmsk.py                 \
+       modulators.py           \
        nbfm_rx.py              \
        nbfm_tx.py              \
        pkt.py                  \
+       psk.py                  \
        rational_resampler.py   \
        standard_squelch.py     \
        wfm_rcv.py              \

Copied: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/bpsk.py
 (from rev 3499, 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/bpsk.py)
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/bpsk.py
                               (rev 0)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/bpsk.py
       2006-09-09 22:14:17 UTC (rev 3510)
@@ -0,0 +1,222 @@
+#
+# Copyright 2005,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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# See gnuradio-examples/python/gmsk2 for examples
+
+"""
+BPSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru
+from math import pi, sqrt
+import psk
+import cmath
+import Numeric
+from pprint import pprint
+
+# /////////////////////////////////////////////////////////////////////////////
+#            BPSK mod/demod with steams of bytes as data i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+class bpsk_mod(gr.hier_block):
+
+    def __init__(self, fg, spb, excess_bw, gray_code=True, verbose=True, 
debug=False):
+        """
+       Hierarchical block for RRC-filtered BPSK modulation.
+
+       The input is a byte stream (unsigned char) and the
+       output is the complex modulated signal at baseband.
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: integer
+       @param excess_bw: Root-raised cosine filter excess bandwidth
+       @type excess_bw: float
+        @param gray_code: Tell modulator to Gray code the bits
+        @type gray_code: bool
+        @param verbose: Print information about modulator?
+        @type verbose: bool
+        @param debug: Print modualtion data to files?
+        @type debug: bool
+       """
+        if not isinstance(spb, int) or spb < 2:
+            raise TypeError, ("sbp must be an integer >= 2, is %d" % spb)
+        self.spb = spb
+
+       ntaps = 11 * spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+
+        # turn bytes into k-bit vectors
+        self.bytes2chunks = \
+          gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)
+
+        self.chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity])
+
+        # pulse shaping filter
+       self.rrc_taps = gr.firdes.root_raised_cosine(
+               spb,            # gain  (spb since we're interpolating by spb)
+               spb,            # sampling rate
+               1.0,            # symbol rate
+               excess_bw,      # excess bandwidth (roll-off factor)
+                ntaps)
+
+       self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps)
+
+       # Connect
+        fg.connect(self.bytes2chunks, self.chunks2symbols, self.rrc_filter)
+
+        if verbose:
+            print "bits_per_symbol =", bits_per_symbol
+           
+        if debug:
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            
+       # Initialize base class
+       gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an 
instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM
+
+    def arguments(self=None):
+        args = {'spb':2, 'excess_bw':0.3, 'gray_code':True, 'verbose':True, 
'debug':False}
+        return args
+    arguments = staticmethod(arguments)
+
+    def add_options(parser):
+        """
+        Adds modulation-specific options to the standard parser
+        """
+        parser.add_option("", "--excess-bw", type="float", default=0.3,
+                          help="set RRC excess bandwith factor 
[default=%default]")
+        parser.add_option("", "--no-gray-code", action="store_false", 
default=True,
+                          help="Don't use gray coding on modulated bits 
[default=%default]")
+    add_options=staticmethod(add_options)
+
+
+class bpsk_demod__coherent_detection_of_psk(gr.hier_block):
+    def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05):
+        """
+       Hierarchical block for RRC-filtered BPSK demodulation
+
+       The input is the complex modulated signal at baseband.
+       The output is a stream of bits packed 1 bit per byte (LSB)
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: float
+       @param excess_bw: Root-raised cosine filter excess bandwidth
+       @type excess_bw: float
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+       """
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.preamp = gr.multiply_const_cc(10e-5)
+        self.agc = gr.agc_cc(1e-3, 1, 1)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull 
it from higher layer?
+        costas_order = 2
+        costas_alpha *= 15   # 2nd order loop needs more gain
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 
costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, 
omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, 
self.clock_recovery,
+                   self.slicer, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, 
"clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.preamp, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an 
instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM
+
+
+bpsk_demod = bpsk_demod__coherent_detection_of_psk
+

Copied: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/dbpsk.py
 (from rev 3499, 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/dbpsk.py)
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/dbpsk.py
                              (rev 0)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/dbpsk.py
      2006-09-09 22:14:17 UTC (rev 3510)
@@ -0,0 +1,243 @@
+#
+# Copyright 2005,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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# See gnuradio-examples/python/gmsk2 for examples
+
+"""
+differential BPSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru
+from math import pi, sqrt
+import psk
+import cmath
+import Numeric
+from pprint import pprint
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#            BPSK mod/demod with steams of bytes as data i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+class dbpsk_mod(gr.hier_block):
+    def __init__(self, fg, spb=2, excess_bw=0.35, gray_code=True, 
verbose=True, debug=False):
+        """
+       Hierarchical block for RRC-filtered QPSK modulation.
+
+       The input is a byte stream (unsigned char) and the
+       output is the complex modulated signal at baseband.
+        
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: integer
+       @param excess_bw: Root-raised cosine filter excess bandwidth
+       @type excess_bw: float
+        @param gray_code: Tell modulator to Gray code the bits
+        @type gray_code: bool
+        @param verbose: Print information about modulator?
+        @type verbose: bool
+        @param debug: Print modualtion data to files?
+        @type debug: bool
+       """
+
+        if not isinstance(spb, int) or spb < 2:
+            raise TypeError, ("sbp must be an integer >= 2, is %d" % spb)
+        self.spb = spb
+        
+       ntaps = 11 * spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        self.bits_per_symbol = bits_per_symbol
+       
+        # turn bytes into k-bit vectors
+        self.bytes2chunks = \
+          gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)
+
+        if gray_code:
+            self.gray_coder = gr.map_bb(psk.binary_to_gray[arity])
+        else:
+            self.gray_coder = gr.map_bb(psk.binary_to_ungray[arity])
+
+        self.diffenc = gr.diff_encoder_bb(arity)
+        
+        self.chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity])
+
+        # pulse shaping filter
+       self.rrc_taps = gr.firdes.root_raised_cosine(
+               spb,            # gain  (spb since we're interpolating by spb)
+               spb,            # sampling rate
+               1.0,            # symbol rate
+               excess_bw,      # excess bandwidth (roll-off factor)
+                ntaps)
+
+       self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps)
+
+       # Connect
+        fg.connect(self.bytes2chunks, self.gray_coder, self.diffenc,
+                   self.chunks2symbols, self.rrc_filter)
+
+        if verbose:
+            print "bits_per_symbol =", bits_per_symbol
+         
+        if debug:
+            fg.connect(self.gray_coder,
+                       gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+            fg.connect(self.diffenc,
+                       gr.file_sink(gr.sizeof_char, "diffenc.dat"))
+            
+       # Initialize base class
+       gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # static method that's also callable on an 
instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM
+
+    def arguments(self=None):
+        args = {'spb':2, 'excess_bw':0.3, 'gray_code':True, 'verbose':True, 
'debug':False}
+        return args
+    arguments = staticmethod(arguments)
+
+    def add_options(parser):
+        """
+        Adds modulation-specific options to the standard parser
+        """
+        parser.add_option("", "--excess-bw", type="float", default=0.3,
+                          help="set RRC excess bandwith factor 
[default=%default]")
+        parser.add_option("", "--no-gray-code", action="store_false", 
default=True,
+                          help="Don't use gray coding on modulated bits 
[default=%default]")
+    add_options=staticmethod(add_options)
+
+
+class 
dbpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block):
+    def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05):
+        """
+       Hierarchical block for RRC-filtered BPSK demodulation
+
+       The input is the complex modulated signal at baseband.
+       The output is a stream of bits packed 1 bit per byte (LSB)
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: float
+       @param excess_bw: Root-raised cosine filter excess bandwidth
+       @type excess_bw: float
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+       """
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.preamp = gr.multiply_const_cc(10e-5)
+        self.agc = gr.agc_cc(1e-3, 1, 1, 1000)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull 
it from higher layer?
+        costas_order = 2
+        costas_alpha *= 15   # 2nd order loop needs more gain
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 
costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, 
omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        self.diffdec = gr.diff_phasor_cc()
+        #self.diffdec = gr.diff_decoder_bb(arity)
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, 
self.clock_recovery,
+                   self.diffdec, self.slicer, self.gray_decoder, self.unpack)
+        #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, 
self.clock_recovery,
+        #           self.slicer, self.diffdec, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, 
"clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            fg.connect(self.diffdec,
+                       gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat"))
+            #fg.connect(self.diffdec,
+            #          gr.file_sink(gr.sizeof_char, "diffdec.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.preamp, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an 
instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM
+
+
+dbpsk_demod = dbpsk_demod__coherent_detection_of_differentially_encoded_psk
+

Copied: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/dqpsk.py
 (from rev 3499, 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/dqpsk.py)
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/dqpsk.py
                              (rev 0)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/dqpsk.py
      2006-09-09 22:14:17 UTC (rev 3510)
@@ -0,0 +1,241 @@
+#
+# Copyright 2005,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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# See gnuradio-examples/python/gmsk2 for examples
+
+"""
+differential QPSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru
+from math import pi, sqrt
+import psk
+import cmath
+import Numeric
+from pprint import pprint
+
+# /////////////////////////////////////////////////////////////////////////////
+#            QPSK mod/demod with steams of bytes as data i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+class dqpsk_mod(gr.hier_block):
+
+    def __init__(self, fg, spb=2, excess_bw=0.35, gray_code=True, 
verbose=True, debug=False):
+        """
+       Hierarchical block for RRC-filtered QPSK modulation.
+
+       The input is a byte stream (unsigned char) and the
+       output is the complex modulated signal at baseband.
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: integer
+       @param excess_bw: Root-raised cosine filter excess bandwidth
+       @type excess_bw: float
+        @param gray_code: Tell modulator to Gray code the bits
+        @type gray_code: bool
+        @param verbose: Print information about modulator?
+        @type verbose: bool
+        @param debug: Print modualtion data to files?
+        @type debug: bool
+       """
+        
+        if not isinstance(spb, int) or spb < 2:
+            raise TypeError, ("sbp must be an integer >= 2, is %d" % spb)
+        self.spb = spb
+
+       ntaps = 11 * spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+
+        # turn bytes into k-bit vectors
+        self.bytes2chunks = \
+          gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)
+
+        if gray_code:
+            self.gray_coder = gr.map_bb(psk.binary_to_gray[arity])
+        else:
+            self.gray_coder = gr.map_bb(psk.binary_to_ungray[arity])
+            
+        self.diffenc = gr.diff_encoder_bb(arity)
+
+        self.chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity])
+
+        # pulse shaping filter
+       self.rrc_taps = gr.firdes.root_raised_cosine(
+               spb,            # gain  (spb since we're interpolating by spb)
+               spb,            # sampling rate
+               1.0,            # symbol rate
+               excess_bw,      # excess bandwidth (roll-off factor)
+                ntaps)
+
+       self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps)
+
+       # Connect
+        fg.connect(self.bytes2chunks, self.gray_coder, self.diffenc,
+                   self.chunks2symbols, self.rrc_filter)
+
+        if verbose:
+            print "bits_per_symbol =", bits_per_symbol
+        
+        if debug:
+            fg.connect(self.gray_coder,
+                       gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+            fg.connect(self.diffenc,
+                       gr.file_sink(gr.sizeof_char, "diffenc.dat"))
+            
+       # Initialize base class
+       gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an 
instance
+        return 2
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM
+
+    def arguments(self=None):
+        args = {'spb':2, 'excess_bw':0.3, 'gray_code':True, 'verbose':True, 
'debug':False}
+        return args
+    arguments = staticmethod(arguments)
+
+    def add_options(parser):
+        """
+        Adds modulation-specific options to the standard parser
+        """
+        parser.add_option("", "--excess-bw", type="float", default=0.3,
+                          help="set RRC excess bandwith factor 
[default=%default]")
+        parser.add_option("", "--no-gray-code", action="store_false", 
default=True,
+                          help="Don't use gray coding on modulated bits 
[default=%default]")
+    add_options=staticmethod(add_options)
+
+
+class 
dqpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block):
+    def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05):
+        """
+       Hierarchical block for RRC-filtered QPSK demodulation
+
+       The input is the complex modulated signal at baseband.
+       The output is a stream of bits packed 1 bit per byte (LSB)
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: float
+       @param excess_bw: Root-raised cosine filter excess bandwidth
+       @type excess_bw: float
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+       """
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.preamp = gr.multiply_const_cc(10e-5)
+        self.agc = gr.agc_cc(1e-3, 1, 1)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull 
it from higher layer?
+        costas_order = 4
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 
costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, 
omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        self.diffdec = gr.diff_phasor_cc()
+        #self.diffdec = gr.diff_decoder_bb(arity)
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, 
self.clock_recovery,
+                   self.diffdec, self.slicer, self.gray_decoder, self.unpack)
+        #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, 
self.clock_recovery,
+        #           self.slicer, self.diffdec, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, 
"clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            fg.connect(self.diffdec,
+                       gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat"))
+            #fg.connect(self.diffdec,
+            #          gr.file_sink(gr.sizeof_char, "diffdec.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.preamp, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an 
instance
+        return 2
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM
+
+
+dqpsk_demod = dqpsk_demod__coherent_detection_of_differentially_encoded_psk
+

Copied: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/gmsk.py
 (from rev 3499, 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py)
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/gmsk.py
                               (rev 0)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/gmsk.py
       2006-09-09 22:14:17 UTC (rev 3510)
@@ -0,0 +1,187 @@
+#
+# GMSK modulation and demodulation.  
+#
+#
+# Copyright 2005,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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# See gnuradio-examples/python/gmsk2 for examples
+
+from gnuradio import gr
+from math import pi
+import Numeric
+
+# /////////////////////////////////////////////////////////////////////////////
+#            GMSK mod/demod with steams of bytes as data i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+class gmsk_mod(gr.hier_block):
+
+    def __init__(self, fg, spb=2, bt=0.3, verbose=True, debug=False):
+        """
+       Hierarchical block for Gaussian Minimum Shift Key (GMSK)
+       modulation.
+
+       The input is a byte stream (unsigned char) and the
+       output is the complex modulated signal at baseband.
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: integer
+       @param bt: Gaussian filter bandwidth * symbol time
+       @type bt: float
+        @param verbose: Print information about modulator?
+        @type verbose: bool
+        @param debug: Print modualtion data to files?
+        @type debug: bool       
+       """
+
+        print spb
+        if not isinstance(spb, int) or spb < 2:
+            raise TypeError, ("sbp must be an integer >= 2, is %d" % spb)
+        self.spb = spb
+
+       ntaps = 4 * spb                 # up to 3 bits in filter at once
+       sensitivity = (pi / 2) / spb    # phase change per bit = pi / 2
+
+       # Turn it into NRZ data.
+       self.nrz = gr.bytes_to_syms()
+
+       # Form Gaussian filter
+
+        # Generate Gaussian response (Needs to be convolved with window below).
+       self.gaussian_taps = gr.firdes.gaussian(
+               1,              # gain
+               spb,            # symbol_rate
+               bt,             # bandwidth * symbol time
+               ntaps           # number of taps
+               )
+
+       self.sqwave = (1,) * spb       # rectangular window
+       self.taps = 
Numeric.convolve(Numeric.array(self.gaussian_taps),Numeric.array(self.sqwave))
+       self.gaussian_filter = gr.interp_fir_filter_fff(spb, self.taps)
+
+       # FM modulation
+       self.fmmod = gr.frequency_modulator_fc(sensitivity)
+               
+       # Connect
+       fg.connect(self.nrz, self.gaussian_filter, self.fmmod)
+
+        if verbose:
+            pass # I have nothing to say...
+         
+        if debug:
+            fg.connect(self.gaussian_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, 
"gaussianfilter.dat"))
+            fg.connect(self.diffenc,
+                       gr.file_sink(gr.sizeof_gr_complex, "gmsk_mod.dat"))
+
+       # Initialize base class
+       gr.hier_block.__init__(self, fg, self.nrz, self.fmmod)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an 
instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM
+
+    def arguments(self=None):
+        args = {'spb':2, 'bt':0.3, 'verbose':True, 'debug':False}
+        return args
+    arguments = staticmethod(arguments)
+
+    def add_options(parser):
+        """
+        Adds modulation-specific options to the standard parser
+        """
+        parser.add_option("", "--bt", type="float", default=0.3,
+                          help="set bandwidth-time product [default=%default]")
+    add_options=staticmethod(add_options)
+
+
+class gmsk_demod(gr.hier_block):
+
+    def __init__(self, fg, spb=2, omega=None, gain_mu=0.03, mu=0.5,
+                 omega_relative_limit=0.000200, freq_error=0.0):
+        """
+       Hierarchical block for Gaussian Minimum Shift Key (GMSK)
+       demodulation.
+
+       The input is the complex modulated signal at baseband.
+       The output is a stream of symbols ready to be sliced at zero.
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud
+       @type spb: integer
+
+        Clock recovery parameters.  These all have reasonble defaults.
+        
+        @param omega: nominal relative freq (defaults to spb)
+        @type omega: float
+        @param gain_mu: controls rate of mu adjustment
+        @type gain_mu: float
+        @param mu: fractional delay [0.0, 1.0]
+        @type mu: float
+        @param omega_relative_limit: sets max variation in omega
+        @type omega_relative_limit: float, typically 0.000200 (200 ppm)
+        @param freq_error: bit rate error as a fraction
+        @param float
+       """
+        if spb < 2:
+            raise TypeError, "sbp >= 2"
+        self.spb = spb
+        
+        if omega is None:
+            omega = spb*(1+freq_error)
+
+       gain_omega = .25*gain_mu*gain_mu        # critically damped
+
+        # Automatic gain control
+        self.preamp = gr.multiply_const_cc(10e-5)
+        self.agc = gr.agc_cc(1e-3, 1, 1, 1000)
+
+       # Demodulate FM
+       sensitivity = (pi / 2) / spb
+       self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity)
+
+        alpha = 0.0008
+
+       # the clock recovery block tracks the symbol clock and resamples as 
needed.
+       # the output of the block is a stream of soft symbols (float)
+       self.clock_recovery = gr.clock_recovery_mm_ff(omega, gain_omega, mu, 
gain_mu,
+                                                      omega_relative_limit)
+
+        # slice the floats at 0, outputting 1 bit (the LSB of the output byte) 
per sample
+        self.slicer = gr.binary_slicer_fb()
+
+       fg.connect(self.preamp, self.agc, self.fmdemod, self.clock_recovery, 
self.slicer)
+        
+       # Initialize base class
+       gr.hier_block.__init__(self, fg, self.preamp, self.slicer)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an 
instance
+        return 1
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM

Deleted: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py

Deleted: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2_pkt.py

Added: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/modulators.py
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/modulators.py
                         (rev 0)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/modulators.py
 2006-09-09 22:14:17 UTC (rev 3510)
@@ -0,0 +1,25 @@
+import bpsk,  \
+       dbpsk, \
+       dqpsk, \
+       gmsk
+
+modulators = {
+    'bpsk':  getattr(bpsk,  "bpsk_mod"),
+    'dbpsk': getattr(dbpsk, "dbpsk_mod"),
+    'dqpsk': getattr(dqpsk, "dqpsk_mod"),
+    'gmsk':  getattr(gmsk,  "gmsk_mod"),
+}
+
+demodulators = [
+    getattr(bpsk,  "bpsk_demod"),
+    getattr(dbpsk, "dbpsk_demod"),
+    getattr(dqpsk, "dqpsk_demod"),
+    getattr(gmsk,  "gmsk_demod"),
+]
+
+def kwargs(modulator, attrs):
+    args = modulator.arguments()
+    for key in args:
+        if(hasattr(attrs, key)):
+            args[key] = getattr(attrs,key)
+    return args

Added: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/psk.py
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/psk.py
                                (rev 0)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/psk.py
        2006-09-09 22:14:17 UTC (rev 3510)
@@ -0,0 +1,67 @@
+#
+# Copyright 2005,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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from math import pi, sqrt
+import cmath
+
+def make_constellation(m):
+    return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)]
+        
+# Common definition of constellations for Tx and Rx
+constellation = {
+    2 : make_constellation(2),           # BPSK
+    4 : make_constellation(4),           # QPSK
+    8 : make_constellation(8)            # 8PSK
+    }
+
+# -----------------------
+# Do Gray code
+# -----------------------
+# binary to gray coding
+binary_to_gray = {
+    2 : (0, 1),
+    4 : (0, 1, 3, 2),
+    8 : (0, 1, 3, 2, 7, 6, 4, 5)
+    }
+   
+# gray to binary
+gray_to_binary = {
+    2 : (0, 1),
+    4 : (0, 1, 3, 2),
+    8 : (0, 1, 3, 2, 6, 7, 5, 4)
+    }
+
+# -----------------------
+# Don't Gray code
+# -----------------------
+# identity mapping
+binary_to_gray = {
+    2 : (0, 1),
+    4 : (0, 1, 2, 3),
+    8 : (0, 1, 2, 3, 4, 5, 6, 7)
+    }
+    
+# identity mapping
+ungray_to_binary = {
+    2 : (0, 1),
+    4 : (0, 1, 2, 3),
+    8 : (0, 1, 2, 3, 4, 5, 6, 7)
+    }

Copied: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/qpsk.py
 (from rev 3499, 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/qpsk.py)
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/qpsk.py
                               (rev 0)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-core/src/python/gnuradio/blksimpl/qpsk.py
       2006-09-09 22:14:17 UTC (rev 3510)
@@ -0,0 +1,355 @@
+#
+# Copyright 2005,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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+# See gnuradio-examples/python/gmsk2 for examples
+
+from gnuradio import gr, gru
+from math import pi, sqrt
+import psk
+import cmath
+import Numeric
+from pprint import pprint
+
+# /////////////////////////////////////////////////////////////////////////////
+#            QPSK mod/demod with steams of bytes as data i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+class qpsk_mod(gr.hier_block):
+
+    def __init__(self, fg, spb=2, excess_bw=0.35, gray_code=True, 
verbose=True, debug=False):
+        """
+       Hierarchical block for RRC-filtered QPSK modulation.
+
+       The input is a byte stream (unsigned char) and the
+       output is the complex modulated signal at baseband.
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: integer
+       @param excess_bw: Root-raised cosine filter excess bandwidth
+       @type excess_bw: float
+        @param gray_code: Tell modulator to Gray code the bits
+        @type gray_code: bool
+        @param verbose: Print information about modulator?
+        @type verbose: bool
+        @param debug: Print modualtion data to files?
+        @type debug: bool
+       """
+        
+        if not isinstance(spb, int) or spb < 2:
+            raise TypeError, ("sbp must be an integer >= 2, is %d" % spb)
+        self.spb = spb
+
+       ntaps = 11 * spb
+
+        bits_per_symbol = self.bits_per_baud()
+        arity = pow(2,bits_per_symbol)
+
+        # turn bytes into k-bit vectors
+        self.bytes2chunks = \
+          gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)
+
+        if gray_code:
+            self.gray_coder = gr.map_bb(psk.binary_to_gray[arity])
+        else:
+            self.gray_coder = gr.map_bb(psk.binary_to_ungray[arity])
+
+        self.chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity])
+
+        # pulse shaping filter
+       self.rrc_taps = gr.firdes.root_raised_cosine(
+               spb,            # gain  (spb since we're interpolating by spb)
+               spb,            # sampling rate
+               1.0,            # symbol rate
+               excess_bw,      # excess bandwidth (roll-off factor)
+                ntaps)
+
+       self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps)
+
+       # Connect
+        fg.connect(self.bytes2chunks, self.gray_coder,
+                   self.chunks2symbols, self.rrc_filter)
+
+        if verbose:
+            print "bits_per_symbol =", bits_per_symbol
+        
+        if debug:
+            fg.connect(self.gray_coder,
+                       gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+           
+       # Initialize base class
+       gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # static method that's also callable on an 
instance
+        return 2
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM
+
+    def arguments(self=None):
+        args = {'spb':2, 'excess_bw':0.3, 'gray_code':True, 'verbose':True, 
'debug':False}
+        return args
+    arguments = staticmethod(arguments)
+
+
+class 
mpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block):
+    def __init__(self, fg, spb, arity, excess_bw, diff=False, 
costas_alpha=0.005, gain_mu=0.05):
+        """
+       Hierarchical block for RRC-filtered PSK demodulation
+
+       The input is the complex modulated signal at baseband.
+       The output is a stream of bits packed 1 bit per byte (LSB)
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: float
+       @param excess_bw: Root-raised cosine filter excess bandwidth
+       @type excess_bw: float
+        @param arity: whick PSK: 2, 4, 8
+        @type arity: int in {2, 4, 8}
+        @param diff: differential PSK if true
+        @type diff: bool
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+       """
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        if not arity in (2, 4):
+            raise ValueError, "n must be 2 or 4"
+
+        if not diff and arity==4:
+            raise NotImplementedError, "non-differential QPSK not supported 
yet"
+
+        bits_per_symbol = int(gru.log2(arity))
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.agc = gr.agc_cc(1e-3, 1, 1)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull 
it from higher layer?
+        if arity == 2:
+            costas_order = 2
+            costas_alpha *= 15   # 2nd order loop needs more gain
+        else:
+            costas_order = 4
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 
costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, 
omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        if(diff):
+            self.diffdec = gr.diff_phasor_cc()
+            #self.diffdec = gr.diff_decoder_bb(arity)
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        if(diff):
+            fg.connect(self.agc, self.costas_loop, self.rrc_filter, 
self.clock_recovery,
+                       self.diffdec, self.slicer, self.gray_decoder, 
self.unpack)
+        else:
+            fg.connect(self.agc, self.costas_loop, self.rrc_filter, 
self.clock_recovery,
+                       self.slicer, self.gray_decoder, self.unpack)
+
+        #fg.connect(self.agc, self.costas_loop, self.rrc_filter, 
self.clock_recovery,
+        #           self.slicer, self.diffdec, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, 
"clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            if(diff):
+                fg.connect(self.diffdec,
+                           gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat"))
+                #fg.connect(self.diffdec,
+                #          gr.file_sink(gr.sizeof_char, "diffdec.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.agc, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self=None):   # staticmethod that's also callable on an 
instance
+        return 2
+    bits_per_baud = staticmethod(bits_per_baud)      # make it a static 
method.  RTFM
+
+    def arguments(self=None):
+        args = {'spb':2, 'excess_bw':0.3, 'gray_code':True, 'verbose':True, 
'debug':False}
+        return args
+    arguments = staticmethod(arguments)
+
+
+#########################################################################
+
+class 
mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk(gr.hier_block):
+    def __init__(self, fg, spb, arity, excess_bw, diff=False, 
costas_alpha=0.005, gain_mu=0.05):
+        """
+       Hierarchical block for RRC-filtered PSK demodulation
+
+       The input is the complex modulated signal at baseband.
+       The output is a stream of bits packed 1 bit per byte (LSB)
+
+       @param fg: flow graph
+       @type fg: flow graph
+       @param spb: samples per baud >= 2
+       @type spb: float
+       @param excess_bw: Root-raised cosine filter excess bandwidth
+       @type excess_bw: float
+        @param arity: whick PSK: 2, 4, 8
+        @type arity: int in {2, 4, 8}
+        @param diff: differential PSK if true
+        @type diff: bool
+        @param costas_alpha: loop filter gain
+        @type costas_alphas: float
+        @param gain_mu:
+        @type gain_mu: float
+       """
+        if spb < 2:
+            raise TypeError, "sbp must be >= 2"
+        self.spb = spb
+
+        if not arity in (2, 4):
+            raise ValueError, "n must be 2 or 4"
+
+        bits_per_symbol = int(gru.log2(arity))
+        print "bits_per_symbol =", bits_per_symbol
+
+        # Automatic gain control
+        self.agc = gr.agc_cc(1e-3, 1, 1)
+        
+        # Costas loop (carrier tracking)
+        # FIXME: need to decide how to handle this more generally; do we pull 
it from higher layer?
+        if arity == 2:
+            costas_order = 2
+            costas_alpha *= 15   # 2nd order loop needs more gain
+        else:
+            costas_order = 4
+        beta = .25 * costas_alpha * costas_alpha
+        self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 
costas_order)
+
+        # RRC data filter
+        ntaps = 11 * spb
+        self.rrc_taps = gr.firdes.root_raised_cosine(
+            1.0,                # gain 
+            spb,                # sampling rate
+            1.0,                # symbol rate
+            excess_bw,          # excess bandwidth (roll-off factor)
+            ntaps)
+
+        self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps)
+
+        # symbol clock recovery
+        omega = spb
+        gain_omega = .25 * gain_mu * gain_mu
+        omega_rel_limit = 0.5
+        mu = 0.05
+        gain_mu = 0.1
+        self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega,
+                                                    mu, gain_mu, 
omega_rel_limit)
+
+        # find closest constellation point
+        #rot = .707 + .707j
+        rot = 1
+        rotated_const = map(lambda pt: pt * rot, constellation[arity])
+        print "rotated_const =", rotated_const
+
+        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+        self.gray_decoder = gr.map_bb(gray_to_binary[arity])
+        
+        # unpack the k bit vector into a stream of bits
+        self.unpack = gr.unpack_k_bits_bb(bits_per_symbol)
+
+        fg.connect(self.agc, self.costas_loop, self.rrc_filter, 
self.clock_recovery,
+                   self.slicer, self.gray_decoder, self.unpack)
+        
+        # Debug sinks
+        if 1:
+            fg.connect(self.agc,
+                       gr.file_sink(gr.sizeof_gr_complex, "agc.dat"))
+            fg.connect(self.costas_loop,
+                       gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat"))
+            fg.connect(self.rrc_filter,
+                       gr.file_sink(gr.sizeof_gr_complex, "rrc.dat"))
+            fg.connect(self.clock_recovery,
+                       gr.file_sink(gr.sizeof_gr_complex, 
"clock_recovery.dat"))
+            fg.connect(self.slicer,
+                       gr.file_sink(gr.sizeof_char, "slicer.dat"))
+            fg.connect(self.unpack,
+                       gr.file_sink(gr.sizeof_char, "unpack.dat"))
+
+        # Initialize base class
+        gr.hier_block.__init__(self, fg, self.agc, self.unpack)
+
+    def samples_per_baud(self):
+        return self.spb
+
+    def bits_per_baud(self):
+        return self.bits_per_symbol
+
+
+mpsk_demod = mpsk_demod__coherent_detection_of_differentially_encoded_psk
+#mpsk_demod = mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk

Modified: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py
      2006-09-09 16:15:29 UTC (rev 3509)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py
      2006-09-09 22:14:17 UTC (rev 3510)
@@ -97,7 +97,7 @@
     demod_kwargs = { } # placeholder    
     
     # build the graph
-    fg = my_graph(blks.gmsk2_demod,
+    fg = my_graph(blks.gmsk_demod,
                   options.rx_subdev_spec, options.bitrate,
                   options.decim, options.spb, rx_callback,
                   options, demod_kwargs)

Modified: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py
      2006-09-09 16:15:29 UTC (rev 3509)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py
      2006-09-09 22:14:17 UTC (rev 3510)
@@ -39,16 +39,11 @@
 #print os.getpid()
 #raw_input('Attach and press enter')
 
-
 class my_graph(gr.flow_graph):
 
-    def __init__(self, mod_class, tx_subdev_spec,
-                 bitrate, interp_rate, spb, gain,
-                 options, mod_kwargs):
+    def __init__(self, options, mod_kwargs):
         gr.flow_graph.__init__(self)
-        self.txpath = transmit_path(self, mod_class, tx_subdev_spec,
-                                    bitrate, interp_rate, spb, gain,
-                                    options, mod_kwargs)
+        self.txpath = transmit_path(self, options, mod_kwargs)
 
 
 # /////////////////////////////////////////////////////////////////////////////
@@ -71,7 +66,7 @@
                       metavar="FREQ")
     parser.add_option("-r", "--bitrate", type="eng_float", default=None,
                       help="specify bitrate.  spb and interp will be derived.")
-    parser.add_option("-S", "--spb", type="int", default=None,
+    parser.add_option("-S", "--spb", type="int", default=2,
                       help="set samples/baud [default=%default]")
     parser.add_option("-i", "--interp", type="intx", default=None,
                       help="set fpga interpolation rate to INTERP 
[default=%default]")
@@ -97,16 +92,21 @@
 
     pkt_size = int(options.size)
 
+    # Add gmsk_mod modulator class to options list
+    options.modulation = getattr(blks, "gmsk_mod")
+
+    # Add GMSK modulator's properties
     mod_kwargs = {
+        'spb': options.spb,
         'bt' : options.bt,
+        'verbose' : False,
+        'debug'   : False,
         }
-
+        
     # build the graph
-    fg = my_graph(blks.gmsk2_mod, options.tx_subdev_spec,
-                  options.bitrate, options.interp, options.spb, options.gain,
-                  options, mod_kwargs)
+    fg = my_graph(options, mod_kwargs)
 
-    print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),)
+    print "bitrate: %sbps" % (eng_notation.num_to_str(fg.txpath.bitrate()),)
     print "spb:     %3d" % (fg.txpath.spb(),)
     print "interp:  %3d" % (fg.txpath.interp(),)
 
@@ -114,10 +114,14 @@
     if not ok:
         print "Failed to set Tx frequency to %s" % 
(eng_notation.num_to_str(options.freq),)
         raise SystemExit
+    else:
+        print "Transmitting on frequency %s" % 
(eng_notation.num_to_str(options.freq))
 
     r = gr.enable_realtime_scheduling()
     if r != gr.RT_OK:
         print "Warning: failed to enable realtime scheduling"
+    else:
+        print "Started realtime scheduling"
 
     fg.start()                       # start flow graph
 

Modified: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py
      2006-09-09 16:15:29 UTC (rev 3509)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py
      2006-09-09 22:14:17 UTC (rev 3510)
@@ -29,9 +29,6 @@
 import random, time, struct, sys
 
 # from current dir
-from bpsk  import bpsk_mod
-from dbpsk import dbpsk_mod
-from dqpsk import dqpsk_mod
 from transmit_path import transmit_path
 import fusb_options
 
@@ -42,13 +39,9 @@
 
 class my_graph(gr.flow_graph):
 
-    def __init__(self, mod_class, tx_subdev_spec,
-                 bitrate, interp_rate, spb, gain,
-                 options, mod_kwargs):
+    def __init__(self, options, mod_kwargs):
         gr.flow_graph.__init__(self)
-        self.txpath = transmit_path(self, mod_class, tx_subdev_spec,
-                                    bitrate, interp_rate, spb, gain,
-                                    options, mod_kwargs)
+        self.txpath = transmit_path(self, options, mod_kwargs)
 
 
 # /////////////////////////////////////////////////////////////////////////////
@@ -71,22 +64,26 @@
                       metavar="FREQ")
     parser.add_option("-r", "--bitrate", type="eng_float", default=None,
                       help="specify bitrate.  spb and interp will be derived.")
-    parser.add_option("-S", "--spb", type="int", default=None,
+    parser.add_option("-S", "--spb", type="int", default=2,
                       help="set samples/baud [default=%default]")
     parser.add_option("-i", "--interp", type="intx", default=None,
                       help="set fpga interpolation rate to INTERP 
[default=%default]")
     parser.add_option("-s", "--size", type="eng_float", default=1500,
                       help="set packet size [default=%default]")
-    parser.add_option("-m", "--modulation", type="string", default='dbpsk',
-                      help="modulation type (bpsk, dbpsk, dqpsk) 
[default=%default]")
-    parser.add_option("", "--excess-bw", type="float", default=0.3,
-                      help="set RRC excess bandwith factor [default=%default]")
     parser.add_option("-g", "--gain", type="eng_float", default=100.0,
                       help="transmitter gain [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("-m", "--modulation", type="string", default='dbpsk',
+                      help="modulation type (bpsk, dbpsk, dqpsk) 
[default=%default]")
+    parser.add_option("", "--excess-bw", type="float", default=0.3,
+                      help="set RRC excess bandwith factor [default=%default]")
+    parser.add_option("", "--no-gray-code", action="store_false", default=True,
+                      help="Don't use gray coding on modulated bits 
[default=%default]")
+
     fusb_options.add_options(parser)
     (options, args) = parser.parse_args ()
 
@@ -99,23 +96,20 @@
 
     pkt_size = int(options.size)
 
+    # Add PSK modulator class to options list
+    options.modulation = getattr(blks, options.modulation + "_mod")
+ 
+    # Add PSK modulator's properties
     mod_kwargs = {
+        'spb'       : options.spb,
         'excess_bw' : options.excess_bw,
+        'gray_code' : options.no_gray_code,
+        'verbose'   : False,
+        'debug'     : False,
         }
-
-    #FIXME: rework when static class defintions are ready for the modulation 
types
-    if(options.modulation=='bpsk'):
-        modulation=bpsk_mod
-    elif( options.modulation=='dbpsk'):
-        modulation=dbpsk_mod
-    else:
-        modulation=dqpsk_mod
-
+ 
     # build the graph
-    fg = my_graph(modulation,
-                  options.tx_subdev_spec, options.bitrate, options.interp,
-                  options.spb, options.gain,
-                  options, mod_kwargs)
+    fg = my_graph(options, mod_kwargs)
 
     print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),)
     print "spb:     %3d" % (fg.txpath.spb(),)

Added: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_tx.py
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_tx.py
                           (rev 0)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_tx.py
   2006-09-09 22:14:17 UTC (rev 3510)
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+#
+# Copyright 2005, 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 2, 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# 
+
+from gnuradio import gr, gru, blks
+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, optparse
+
+# from current dir
+from transmit_path import transmit_path
+import fusb_options
+
+#import os 
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+
+class my_graph(gr.flow_graph):
+    def __init__(self, modulator, options):
+        gr.flow_graph.__init__(self)
+        self.txpath = transmit_path(self, modulator, options)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+
+    def send_pkt(payload='', eof=False):
+        return fg.txpath.send_pkt(payload, eof)
+
+    def rx_callback(ok, payload):
+        print "ok = %r, payload = '%s'" % (ok, payload)
+
+    parser = OptionParser (option_class=eng_option)
+    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)")
+
+    transmit_path.add_options(parser)
+
+    parser.add_option("-m", "--modulation", type="choice", 
choices=blks.modulators.keys(),
+                      default='dbpsk',
+                      help="Set modulation type %s" % blks.modulators.keys())
+
+    # Print out all (unique) options from the modulators
+    # FIXME: work on trying to get a heirarchy of a per-modulation list
+    for mod in blks.modulators.values():
+        try:
+            mod.add_options(parser)
+        except optparse.OptionConflictError:
+            pass
+
+    fusb_options.add_options(parser)
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.freq < 1e6:
+        options.freq *= 1e6
+
+    pkt_size = int(options.size)
+
+    # build the graph
+    fg = my_graph(blks.modulators[options.modulation], options)
+
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: failed to enable realtime scheduling"
+
+    fg.start()                       # start flow graph
+
+    # generate and send packets
+    nbytes = int(1e6 * options.megabytes)
+    n = 0
+    pktno = 0
+
+    while n < nbytes:
+        send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff))
+        n += pkt_size
+        sys.stderr.write('.')
+        if options.discontinuous and pktno % 5 == 4:
+            time.sleep(1)
+        pktno += 1
+        
+    send_pkt(eof=True)
+    fg.wait()                       # wait for it to finish
+    fg.txpath.set_auto_tr(False)
+
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass


Property changes on: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/benchmark_tx.py
___________________________________________________________________
Name: svn:executable
   + *

Deleted: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/bpsk.py

Deleted: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/dbpsk.py

Deleted: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/dqpsk.py

Deleted: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/qpsk.py

Modified: 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/transmit_path.py
===================================================================
--- 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/transmit_path.py
  2006-09-09 16:15:29 UTC (rev 3509)
+++ 
gnuradio/branches/developers/trondeau/wip2/gnuradio-examples/python/gmsk2/transmit_path.py
  2006-09-09 22:14:17 UTC (rev 3510)
@@ -21,6 +21,7 @@
 
 from gnuradio import gr, gru, blks
 from gnuradio import usrp
+from gnuradio import eng_notation
 
 # from current dir
 from pick_bitrate import pick_tx_bitrate
@@ -30,46 +31,89 @@
 # /////////////////////////////////////////////////////////////////////////////
 
 class transmit_path(gr.hier_block): 
-    def __init__(self, fg, mod_class, tx_subdev_spec,
-                 bitrate, interp, spb, gain,
-                 options, mod_kwargs):
+    def __init__(self, fg, modulator, options, verbose=True):
+        '''
+        See below for what options should hold
+        '''
 
-        self.normal_gain = gain
+        self._center_freq     = options.freq            # tranmitter's carrier 
frequency
+        self._gain            = options.gain            # transmitter's 
digital gain
+        self._tx_subdev_spec  = options.tx_subdev_spec  # daughterboard to use
+        self._bitrate         = options.bitrate         # desired bit rate
+        self._interp          = options.interp          # interpolating rate 
for the USRP (prelim)
+        self._spb             = options.spb             # desired samples/baud
+        self._fusb_block_size = options.fusb_block_size # usb info for USRP
+        self._fusb_nblocks    = options.fusb_nblocks    # usb info for USRP
 
-        self.u = usrp.sink_c (fusb_block_size=options.fusb_block_size,
-                              fusb_nblocks=options.fusb_nblocks)
-        dac_rate = self.u.dac_rate();
+        self._modulator       = modulator               # the modulator we are 
using
+    
+        # Set up USRP sink; also adjusts interp, spb, and bitrate
+        self.set_usrp_sink()
 
-        print mod_class
-        print mod_class.bits_per_baud()
-        (self._bitrate, self._spb, self._interp) = \
-            pick_tx_bitrate(bitrate, mod_class.bits_per_baud(), spb, interp, 
dac_rate)
+        # Get mod_kwargs
+        mod_kwargs = blks.kwargs(self._modulator, [self._spb, self._interp, 
self._bitrate])
 
-        self.u.set_interp_rate(self._interp)
-
-        # determine the daughterboard subdevice we're using
-        if tx_subdev_spec is None:
-            tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
-        self.u.set_mux(usrp.determine_tx_mux_value(self.u, tx_subdev_spec))
-        self.subdev = usrp.selected_subdev(self.u, tx_subdev_spec)
-        print "Using TX d'board %s" % (self.subdev.side_and_name(),)
-
+        # Set carrier frequency of USRP
+        ok = self.set_freq(self._center_freq)
+        if not ok:
+            print "Failed to set Tx frequency to %s" % 
(eng_notation.num_to_str(options.freq),)
+            raise SystemExit
+    
         # transmitter
         self.packet_transmitter = \
             blks.mod_pkts(fg,
-                          mod_class(fg, spb=self._spb, **mod_kwargs),
+                          self._modulator(fg, **mod_kwargs),
                           access_code=None,
                           msgq_limit=4,
                           pad_for_usrp=True)
 
-        self.amp = gr.multiply_const_cc (self.normal_gain)
+        # Set gains: digital and USRP
+        self.amp = gr.multiply_const_cc(self._gain)
+        self.set_gain(self.subdev.gain_range()[1])    # set max Tx gain
 
+        # enable Auto Transmit/Receive switching
+        self.set_auto_tr(True)
+
+        # Display some information about the setup
+        if verbose:
+            print "modulation: %s" % (self._modulator.__name__)
+            print "bitrate:    %sb/sec" % 
(eng_notation.num_to_str(self._bitrate))
+            print "spb:        %3d" % (self._spb)
+            print "interp:     %3d" % (self._interp)
+            print "Center Frequency: %s" % 
(eng_notation.num_to_str(self._center_freq))
+            print "Using TX d'board %s" % (self.subdev.side_and_name(),)
+
+        # Create and setup transmit path flow graph
         fg.connect(self.packet_transmitter, self.amp, self.u)
         gr.hier_block.__init__(self, fg, None, None)
 
-        self.set_gain(self.subdev.gain_range()[1])  # set max Tx gain
-        self.set_auto_tr(True)                      # enable Auto 
Transmit/Receive switching
+    def set_usrp_sink(self):
+        """
+        Creates a USRP sink, determines the settings for best bitrate,
+        and attaches to the transmitter's subdevice.
+        """
+        self.u = usrp.sink_c (fusb_block_size=self._fusb_block_size,
+                              fusb_nblocks=self._fusb_nblocks)
+        dac_rate = self.u.dac_rate();
 
+        self.set_bitrate(dac_rate)
+        
+        self.u.set_interp_rate(self._interp)
+
+        # determine the daughterboard subdevice we're using
+        if self._tx_subdev_spec is None:
+            self._tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
+        self.u.set_mux(usrp.determine_tx_mux_value(self.u, 
self._tx_subdev_spec))
+        self.subdev = usrp.selected_subdev(self.u, self._tx_subdev_spec)
+
+    def set_bitrate(self, dac_rate):
+        # determine best set of bitrate, spb, and interp from desired info
+        (self._bitrate, self._spb, self._interp) = \
+            pick_tx_bitrate(self._bitrate, self._modulator.bits_per_baud(), \
+                            self._spb, self._interp, dac_rate)
+
+        print self._spb
+
     def set_freq(self, target_freq):
         """
         Set the center frequency we're interested in.
@@ -106,3 +150,23 @@
 
     def interp(self):
         return self._interp
+
+    def add_options(parser):
+        """
+        Adds transmitter-specific options to the Options Parser
+        """
+        parser.add_option("-T", "--tx-subdev-spec", type="subdev", 
default=None,
+                          help="select USRP Tx side A or B")
+        parser.add_option("-f", "--freq", type="eng_float", default=423.1e6,
+                          help="set Tx and Rx frequency to FREQ 
[default=%default]",
+                          metavar="FREQ")
+        parser.add_option("-r", "--bitrate", type="eng_float", default=None,
+                          help="specify bitrate.  spb and interp will be 
derived.")
+        parser.add_option("-S", "--spb", type="int", default=None,
+                          help="set samples/baud [default=%default]")
+        parser.add_option("-i", "--interp", type="intx", default=None,
+                          help="set fpga interpolation rate to INTERP 
[default=%default]")
+        parser.add_option("-g", "--gain", type="eng_float", default=100.0,
+                          help="transmitter gain [default=%default]")
+    # Make a static method to call before instantiation
+    add_options = staticmethod(add_options)





reply via email to

[Prev in Thread] Current Thread [Next in Thread]