diff options
author | Ben Reynwar <ben@reynwar.net> | 2011-02-09 14:19:40 -0700 |
---|---|---|
committer | Ben Reynwar <ben@reynwar.net> | 2011-02-09 14:19:40 -0700 |
commit | e4df34e785651787930b2b2fcd4c9fbdeac5d8fc (patch) | |
tree | 1a363fd74dbb184e2d78d6d278d7c4a27195b808 /gnuradio-core/src/python | |
parent | 765c9f6e947d6dd765d1f33f3d4668f0c69486ee (diff) |
Changed constellation objects so that codings besides gray code can be used.
Diffstat (limited to 'gnuradio-core/src/python')
6 files changed, 74 insertions, 42 deletions
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/generic_mod_demod.py b/gnuradio-core/src/python/gnuradio/blks2impl/generic_mod_demod.py index 933de91131..b88ff72a0d 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/generic_mod_demod.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/generic_mod_demod.py @@ -27,7 +27,7 @@ Generic modulation and demodulation. from gnuradio import gr from gnuradio.modulation_utils2 import extract_kwargs_from_options_for_class -from gnuradio.utils.gray_code import gray_code, inverse_gray_code +from gnuradio.utils import mod_codes # default values (used in __init__ and add_options) _def_samples_per_symbol = 2 @@ -47,7 +47,6 @@ _def_phase_alpha = 0.1 _def_constellation_points = 16 # Whether differential coding is used. _def_differential = True -_def_gray_coded = True def add_common_options(parser): """ @@ -59,10 +58,10 @@ def add_common_options(parser): help="use differential encoding [default=%default]") parser.add_option("", "--not-differential", action="store_false", dest="differential", help="do not use differential encoding [default=%default]") - parser.add_option("", "--gray-coded", action="store_true", dest="gray_coded", default=True, - help="use gray code [default=%default]") - parser.add_option("", "--not-gray-coded", action="store_false", dest="gray_coded", - help="do not use gray code [default=%default]") + parser.add_option("", "--mod-code", type="choice", choices=mod_codes.codes, + default=mod_codes.NO_CODE, + help="Select modulation code from: %s [default=%%default]" + % (', '.join(mod_codes.codes),)) parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw, help="set RRC excess bandwith factor [default=%default]") @@ -75,7 +74,6 @@ class generic_mod(gr.hier_block2): def __init__(self, constellation, differential=_def_differential, - gray_coded=_def_gray_coded, samples_per_symbol=_def_samples_per_symbol, excess_bw=_def_excess_bw, verbose=_def_verbose, @@ -106,7 +104,6 @@ class generic_mod(gr.hier_block2): self._samples_per_symbol = samples_per_symbol self._excess_bw = excess_bw self._differential = differential - self._gray_coded = gray_coded if not isinstance(self._samples_per_symbol, int) or self._samples_per_symbol < 2: raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol) @@ -119,8 +116,8 @@ class generic_mod(gr.hier_block2): self.bytes2chunks = \ gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - if gray_coded: - self.symbol_mapper = gr.map_bb(gray_code(arity)) + if self._constellation.apply_pre_diff_code(): + self.symbol_mapper = gr.map_bb(self._constellation.pre_diff_code()) if differential: self.diffenc = gr.diff_encoder_bb(arity) @@ -140,7 +137,7 @@ class generic_mod(gr.hier_block2): # Connect blocks = [self, self.bytes2chunks] - if gray_coded: + if self._constellation.apply_pre_diff_code(): blocks.append(self.symbol_mapper) if differential: blocks.append(self.diffenc) @@ -184,7 +181,7 @@ class generic_mod(gr.hier_block2): print "Modulation logging turned on." self.connect(self.bytes2chunks, gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) - if self._gray_coded: + if self._constellation.apply_pre_diff_code(): self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.dat")) if self._differential: @@ -208,7 +205,6 @@ class generic_demod(gr.hier_block2): def __init__(self, constellation, samples_per_symbol=_def_samples_per_symbol, differential=_def_differential, - gray_coded=_def_gray_coded, excess_bw=_def_excess_bw, freq_alpha=_def_freq_alpha, timing_alpha=_def_timing_alpha, @@ -256,7 +252,6 @@ class generic_demod(gr.hier_block2): self._timing_beta = _def_timing_beta self._timing_max_dev=timing_max_dev self._differential = differential - self._gray_coded = gray_coded if not isinstance(self._samples_per_symbol, int) or self._samples_per_symbol < 2: raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol) @@ -296,8 +291,9 @@ class generic_demod(gr.hier_block2): if differential: self.diffdec = gr.diff_decoder_bb(arity) - if gray_coded: - self.symbol_mapper = gr.map_bb(inverse_gray_code(arity)) + if self._constellation.apply_pre_diff_code(): + self.symbol_mapper = gr.map_bb( + mod_codes.invert_code(self._constellation.pre_diff_code())) # unpack the k bit vector into a stream of bits self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) @@ -312,7 +308,7 @@ class generic_demod(gr.hier_block2): blocks = [self, self.agc, self.freq_recov, self.time_recov, self.receiver] if differential: blocks.append(self.diffdec) - if gray_coded: + if self._constellation.apply_pre_diff_code(): blocks.append(self.symbol_mapper) blocks += [self.unpack, self] self.connect(*blocks) @@ -365,7 +361,7 @@ class generic_demod(gr.hier_block2): if self._differential: self.connect(self.diffdec, gr.file_sink(gr.sizeof_char, "rx_diffdec.dat")) - if self._gray_coded: + if self._constellation.apply_pre_diff_code(): self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) self.connect(self.unpack, diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/psk2.py b/gnuradio-core/src/python/gnuradio/blks2impl/psk2.py index 4fd2c77fec..95f25e75a9 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/psk2.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/psk2.py @@ -28,17 +28,32 @@ from cmath import exp from gnuradio import gr, modulation_utils2 from gnuradio.blks2impl.generic_mod_demod import generic_mod, generic_demod +from gnuradio.utils import mod_codes, gray_code # Default number of points in constellation. _def_constellation_points = 4 -# Whether differential coding is used. -_def_differential = True - +# The default encoding (e.g. gray-code, set-partition) +_def_mod_code = mod_codes.GRAY_CODE + +def create_encodings(mod_code, arity): + post_diff_code = None + if mod_code not in mod_codes.codes: + raise ValueError('That modulation code does not exist.') + if mod_code == mod_codes.GRAY_CODE: + pre_diff_code = gray_code.gray_code(arity) + elif mod_code == mod_codes.SET_PARTITION_CODE: + pre_diff_code = set_partition_code.set_partition_code(arity) + elif mod_code == mod_codes.NO_CODE: + pre_diff_code = [] + else: + raise ValueError('That modulation code is not implemented for this constellation.') + return (pre_diff_code, post_diff_code) + # ///////////////////////////////////////////////////////////////////////////// # PSK constellation # ///////////////////////////////////////////////////////////////////////////// -def psk_constellation(m=_def_constellation_points): +def psk_constellation(m=_def_constellation_points, mod_code=_def_mod_code): """ Creates a PSK constellation object. """ @@ -46,7 +61,11 @@ def psk_constellation(m=_def_constellation_points): if (k != int(k)): raise StandardError('Number of constellation points must be a power of two.') points = [exp(2*pi*(0+1j)*i/m) for i in range(0,m)] - constellation = gr.constellation_psk(points, m) + pre_diff_code, post_diff_code = create_encodings(mod_code, m) + if post_diff_code is not None: + inverse_post_diff_code = mod_codes.invert_code(post_diff_code) + points = [points[x] for x in inverse_post_diff_code] + constellation = gr.constellation_psk(points, pre_diff_code, m) return constellation # ///////////////////////////////////////////////////////////////////////////// @@ -56,6 +75,7 @@ def psk_constellation(m=_def_constellation_points): class psk_mod(generic_mod): def __init__(self, constellation_points=_def_constellation_points, + mod_code=_def_mod_code, *args, **kwargs): """ @@ -67,7 +87,7 @@ class psk_mod(generic_mod): See generic_mod block for list of parameters. """ - constellation = psk_constellation(constellation_points) + constellation = psk_constellation(constellation_points, mod_code) super(psk_mod, self).__init__(constellation, *args, **kwargs) # ///////////////////////////////////////////////////////////////////////////// @@ -78,6 +98,7 @@ class psk_mod(generic_mod): class psk_demod(generic_demod): def __init__(self, constellation_points=_def_constellation_points, + mod_code=_def_mod_code, *args, **kwargs): """ @@ -89,7 +110,7 @@ class psk_demod(generic_demod): See generic_demod block for list of parameters. """ - constellation = psk_constellation(constellation_points) + constellation = psk_constellation(constellation_points, mod_code) super(psk_demod, self).__init__(constellation, *args, **kwargs) # diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/qam.py b/gnuradio-core/src/python/gnuradio/blks2impl/qam.py index 20ca6ee89b..143f6e1083 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/qam.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/qam.py @@ -28,6 +28,7 @@ from math import pi, sqrt, log from gnuradio import gr, modulation_utils2 from gnuradio.blks2impl.generic_mod_demod import generic_mod, generic_demod from gnuradio.utils.gray_code import gray_code +from gnuradio.utils import mod_codes # Default number of points in constellation. _def_constellation_points = 16 @@ -35,7 +36,7 @@ _def_constellation_points = 16 _def_differential = True # Whether gray coding is used. If differential is True then gray # coding is used within but not between each quadrant. -_def_gray_coded = True +_def_mod_code = mod_codes.NO_CODE def is_power_of_four(x): v = log(x)/log(4) @@ -52,7 +53,7 @@ def get_bits(x, n, k): # Remove all bits bigger than n+k-1 return v % pow(2, k) -def make_differential_constellation(m, gray_coded=_def_gray_coded): +def make_differential_constellation(m, gray_coded): """ Create a constellation with m possible symbols where m must be a power of 4. @@ -111,7 +112,7 @@ def make_differential_constellation(m, gray_coded=_def_gray_coded): return const_map -def make_not_differential_constellation(m, gray_coded=_def_gray_coded): +def make_not_differential_constellation(m, gray_coded): side = pow(m, 0.5) if (not isinstance(m, int) or m < 4 or not is_power_of_four(m)): raise ValueError("m must be a power of 4 integer.") @@ -145,17 +146,26 @@ def make_not_differential_constellation(m, gray_coded=_def_gray_coded): def qam_constellation(constellation_points=_def_constellation_points, differential=_def_differential, - gray_coded=_def_gray_coded,): + mod_code=_def_mod_code): """ Creates a QAM constellation object. """ + if mod_code == mod_codes.GRAY_CODE: + gray_coded = True + elif mod_code == mod_codes.NO_CODE: + gray_coded = False + else: + raise ValueError("Mod code is not implemented for QAM") if differential: points = make_differential_constellation(constellation_points, gray_coded) else: points = make_not_differential_constellation(constellation_points, gray_coded) side = int(sqrt(constellation_points)) width = 2.0/(side-1) - constellation = gr.constellation_rect(points, side, side, width, width) + # No pre-diff code + # Should add one so that we can gray-code the quadrant bits too. + pre_diff_code = [] + constellation = gr.constellation_rect(points, pre_diff_code, side, side, width, width) return constellation # ///////////////////////////////////////////////////////////////////////////// @@ -166,7 +176,7 @@ class qam_mod(generic_mod): def __init__(self, constellation_points=_def_constellation_points, differential=_def_differential, - gray_coded=_def_gray_coded, + mod_code=_def_mod_code, *args, **kwargs): """ @@ -178,11 +188,11 @@ class qam_mod(generic_mod): See generic_mod block for list of parameters. """ - constellation = qam_constellation(constellation_points, differential, gray_coded) + constellation = qam_constellation(constellation_points, differential, mod_code) # We take care of the gray coding in the constellation generation so it doesn't # need to be done in the block. super(qam_mod, self).__init__(constellation, differential=differential, - gray_coded=False, *args, **kwargs) + *args, **kwargs) # ///////////////////////////////////////////////////////////////////////////// # QAM demodulator @@ -193,7 +203,7 @@ class qam_demod(generic_demod): def __init__(self, constellation_points=_def_constellation_points, differential=_def_differential, - gray_coded=_def_gray_coded, + mod_code=_def_mod_code, *args, **kwargs): """ @@ -204,11 +214,10 @@ class qam_demod(generic_demod): See generic_demod block for list of parameters. """ - constellation = qam_constellation(constellation_points, differential, gray_coded) + constellation = qam_constellation(constellation_points, differential, mod_code) # We take care of the gray coding in the constellation generation so it doesn't # need to be done in the block. super(qam_demod, self).__init__(constellation, differential=differential, - gray_coded=False, *args, **kwargs) # diff --git a/gnuradio-core/src/python/gnuradio/utils/Makefile.am b/gnuradio-core/src/python/gnuradio/utils/Makefile.am index 4c8e46891b..c0ac613b9a 100644 --- a/gnuradio-core/src/python/gnuradio/utils/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/utils/Makefile.am @@ -30,6 +30,7 @@ TESTS = \ nobase_utilspython_PYTHON = \ __init__.py \ gray_code.py \ + mod_codes.py \ doxyxml/__init__.py \ doxyxml/base.py \ doxyxml/doxyindex.py \ diff --git a/gnuradio-core/src/python/gnuradio/utils/gray_code.py b/gnuradio-core/src/python/gnuradio/utils/gray_code.py index 7d3e0fcb8d..70cb9d7e22 100644 --- a/gnuradio-core/src/python/gnuradio/utils/gray_code.py +++ b/gnuradio-core/src/python/gnuradio/utils/gray_code.py @@ -43,9 +43,3 @@ _gray_code_generator = GrayCodeGenerator() gray_code = _gray_code_generator.get_gray_code -def inverse_gray_code(length): - gc = enumerate(gray_code(length)) - igc = [(b, a) for (a, b) in gc] - igc.sort() - return [a for (b, a) in igc] - diff --git a/gnuradio-core/src/python/gnuradio/utils/mod_codes.py b/gnuradio-core/src/python/gnuradio/utils/mod_codes.py new file mode 100644 index 0000000000..db3dc252d7 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/utils/mod_codes.py @@ -0,0 +1,11 @@ +GRAY_CODE = 'gray' +SET_PARTITION_CODE = 'set-partition' +NO_CODE = 'none' + +codes = (GRAY_CODE, SET_PARTITION_CODE, NO_CODE) + +def invert_code(code): + c = enumerate(code) + ic = [(b, a) for (a, b) in c] + ic.sort() + return [a for (b, a) in ic] |