diff options
Diffstat (limited to 'gr-digital/python/digital/cpm.py')
-rw-r--r-- | gr-digital/python/digital/cpm.py | 121 |
1 files changed, 64 insertions, 57 deletions
diff --git a/gr-digital/python/digital/cpm.py b/gr-digital/python/digital/cpm.py index 322c3f0bfc..0752f01d66 100644 --- a/gr-digital/python/digital/cpm.py +++ b/gr-digital/python/digital/cpm.py @@ -1,37 +1,44 @@ # -# CPM modulation and demodulation. +# CPM modulation and demodulation. # # # Copyright 2005-2007,2011 Free Software Foundation, Inc. -# +# # This file is part of GNU Radio -# +# # GNU Radio is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. -# +# # GNU Radio is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with GNU Radio; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. -# +# + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals # See gnuradio-examples/python/digital for examples + +from math import pi +import numpy + from gnuradio import gr, filter from gnuradio import analog from gnuradio import blocks -from math import pi -import numpy +from . import digital_swig +from . import modulation_utils -import digital_swig -import modulation_utils # default values (used in __init__ and add_options) _def_samples_per_symbol = 2 @@ -53,16 +60,16 @@ _def_log = False class cpm_mod(gr.hier_block2): """ Hierarchical block for Continuous Phase modulation. - + The input is a byte stream (unsigned char) representing packed bits and the output is the complex modulated signal at baseband. - + See Proakis for definition of generic CPM signals: s(t)=exp(j phi(t)) phi(t)= 2 pi h int_0^t f(t') dt' f(t)=sum_k a_k g(t-kT) (normalizing assumption: int_0^infty g(t) dt = 1/2) - + Args: samples_per_symbol: samples per baud >= 2 (integer) bits_per_symbol: bits per symbol (integer) @@ -76,21 +83,21 @@ class cpm_mod(gr.hier_block2): debug: Print modulation data to files? (boolean) """ - def __init__(self, + def __init__(self, samples_per_symbol=_def_samples_per_symbol, bits_per_symbol=_def_bits_per_symbol, h_numerator=_def_h_numerator, h_denominator=_def_h_denominator, cpm_type=_def_cpm_type, - bt=_def_bt, - symbols_per_pulse=_def_symbols_per_pulse, + bt=_def_bt, + symbols_per_pulse=_def_symbols_per_pulse, generic_taps=_def_generic_taps, verbose=_def_verbose, log=_def_log): - gr.hier_block2.__init__(self, "cpm_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.hier_block2.__init__(self, "cpm_mod", + gr.io_signature(1, 1, gr.sizeof_char), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._samples_per_symbol = samples_per_symbol self._bits_per_symbol = bits_per_symbol @@ -99,29 +106,29 @@ class cpm_mod(gr.hier_block2): self._cpm_type = cpm_type self._bt=bt if cpm_type == 0 or cpm_type == 2 or cpm_type == 3: # CPFSK, RC, Generic - self._symbols_per_pulse = symbols_per_pulse + self._symbols_per_pulse = symbols_per_pulse elif cpm_type == 1: # GMSK - self._symbols_per_pulse = 4 + self._symbols_per_pulse = 4 else: - raise TypeError, ("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,)) + raise TypeError("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,)) self._generic_taps=numpy.array(generic_taps) if samples_per_symbol < 2: - raise TypeError, ("samples_per_symbol must be >= 2, is %r" % (samples_per_symbol,)) + raise TypeError("samples_per_symbol must be >= 2, is %r" % (samples_per_symbol,)) self.nsymbols = 2**bits_per_symbol self.sym_alphabet = numpy.arange(-(self.nsymbols-1),self.nsymbols,2).tolist() - self.ntaps = int(self._symbols_per_pulse * samples_per_symbol) - sensitivity = 2 * pi * h_numerator / h_denominator / samples_per_symbol + self.ntaps = int(self._symbols_per_pulse * samples_per_symbol) + sensitivity = 2 * pi * h_numerator / h_denominator / samples_per_symbol # Unpack Bytes into bits_per_symbol groups self.B2s = blocks.packed_to_unpacked_bb(bits_per_symbol,gr.GR_MSB_FIRST) - - - # Turn it into symmetric PAM data. + + + # Turn it into symmetric PAM data. self.pam = digital_swig.chunks_to_symbols_bf(self.sym_alphabet,1) # Generate pulse (sum of taps = samples_per_symbol/2) @@ -129,72 +136,72 @@ class cpm_mod(gr.hier_block2): self.taps= (1.0/self._symbols_per_pulse/2,) * self.ntaps elif cpm_type == 1: # GMSK gaussian_taps = filter.firdes.gaussian( - 1.0/2, # gain + 1.0 / 2, # gain samples_per_symbol, # symbol_rate bt, # bandwidth * symbol time self.ntaps # number of taps ) - sqwave = (1,) * samples_per_symbol # rectangular window - self.taps = numpy.convolve(numpy.array(gaussian_taps),numpy.array(sqwave)) + sqwave = (1,) * samples_per_symbol # rectangular window + self.taps = numpy.convolve(numpy.array(gaussian_taps),numpy.array(sqwave)) elif cpm_type == 2: # Raised Cosine # generalize it for arbitrary roll-off factor - self.taps = (1-numpy.cos(2*pi*numpy.arange(0,self.ntaps)/samples_per_symbol/self._symbols_per_pulse))/(2*self._symbols_per_pulse) + self.taps = (1-numpy.cos(2*pi*numpy.arange(0 / self.ntaps/samples_per_symbol/self._symbols_per_pulse)),(2*self._symbols_per_pulse)) elif cpm_type == 3: # Generic CPM self.taps = generic_taps else: - raise TypeError, ("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,)) + raise TypeError("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,)) self.filter = filter.pfb.arb_resampler_fff(samples_per_symbol, self.taps) - # FM modulation - self.fmmod = analog.frequency_modulator_fc(sensitivity) - + # FM modulation + self.fmmod = analog.frequency_modulator_fc(sensitivity) + if verbose: self._print_verbage() - + if log: self._setup_logging() - # Connect - self.connect(self, self.B2s, self.pam, self.filter, self.fmmod, self) + # Connect + self.connect(self, self.B2s, self.pam, self.filter, self.fmmod, self) def samples_per_symbol(self): return self._samples_per_symbol - - def bits_per_symbol(self): + + def bits_per_symbol(self): return self._bits_per_symbol - - def h_numerator(self): + + def h_numerator(self): return self._h_numerator - def h_denominator(self): + def h_denominator(self): return self._h_denominator - def cpm_type(self): + def cpm_type(self): return self._cpm_type - def bt(self): + def bt(self): return self._bt - def symbols_per_pulse(self): + def symbols_per_pulse(self): return self._symbols_per_pulse def _print_verbage(self): - print "Samples per symbol = %d" % self._samples_per_symbol - print "Bits per symbol = %d" % self._bits_per_symbol - print "h = " , self._h_numerator , " / " , self._h_denominator - print "Symbol alphabet = " , self.sym_alphabet - print "Symbols per pulse = %d" % self._symbols_per_pulse - print "taps = " , self.taps - - print "CPM type = %d" % self._cpm_type + print("Samples per symbol = %d" % self._samples_per_symbol) + print("Bits per symbol = %d" % self._bits_per_symbol) + print("h = " , self._h_numerator , " / " , self._h_denominator) + print("Symbol alphabet = " , self.sym_alphabet) + print("Symbols per pulse = %d" % self._symbols_per_pulse) + print("taps = " , self.taps) + + print("CPM type = %d" % self._cpm_type) if self._cpm_type == 1: - print "Gaussian filter BT = %.2f" % self._bt + print("Gaussian filter BT = %.2f" % self._bt) def _setup_logging(self): - print "Modulation logging turned on." + print("Modulation logging turned on.") self.connect(self.B2s, blocks.file_sink(gr.sizeof_float, "symbols.dat")) self.connect(self.pam, |