[Top][All Lists]
[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)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r3510 - in gnuradio/branches/developers/trondeau/wip2: gnuradio-core/src/python/gnuradio/blksimpl gnuradio-examples/python/gmsk2,
trondeau <=