diff options
Diffstat (limited to 'gr-digital/python/digital/qam.py')
-rw-r--r-- | gr-digital/python/digital/qam.py | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/gr-digital/python/digital/qam.py b/gr-digital/python/digital/qam.py index 29e88ee236..d74866b946 100644 --- a/gr-digital/python/digital/qam.py +++ b/gr-digital/python/digital/qam.py @@ -29,13 +29,16 @@ _def_differential = True # coding is used within but not between each quadrant. _def_mod_code = mod_codes.NO_CODE + def is_power_of_four(x): v = log(x) / log(4) return int(v) == v + def get_bit(x, n): """ Get the n'th bit of integer x (from little end).""" - return (x&(0x01 << n)) >> n + return (x & (0x01 << n)) >> n + def get_bits(x, n, k): """ Get the k bits of integer x starting at bit n(from little end).""" @@ -44,6 +47,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): """ Create a constellation with m possible symbols where m must be @@ -71,9 +75,9 @@ def make_differential_constellation(m, gray_coded): else: i_gcs = dict([(i, i) for i in range(0, side)]) # The distance between points is found. - step = 1 / (side-0.5) + step = 1 / (side - 0.5) - gc_to_x = [(i_gcs[gc]+0.5)*step for gc in range(0, side)] + gc_to_x = [(i_gcs[gc] + 0.5) * step for gc in range(0, side)] # Takes the (x, y) location of the point with the quadrant along # with the quadrant number. (x, y) are integers referring to which @@ -93,16 +97,18 @@ def make_differential_constellation(m, gray_coded): # First two bits determine quadrant. # Next (k-2)/2 bits determine x position. # Following (k-2)/2 bits determine y position. - # How x and y relate to real and imag depends on quadrant (see get_c function). + # How x and y relate to real and imag depends on quadrant (see get_c + # function). const_map = [] for i in range(m): - y = get_bits(i, 0, (k-2) // 2) - x = get_bits(i, (k-2) // 2, (k-2) // 2) - quad = get_bits(i, k-2, 2) + y = get_bits(i, 0, (k - 2) // 2) + x = get_bits(i, (k - 2) // 2, (k - 2) // 2) + quad = get_bits(i, k - 2, 2) const_map.append(get_c(x, y, quad)) return const_map + def make_non_differential_constellation(m, gray_coded): side = int(pow(m, 0.5)) if (not isinstance(m, int) or m < 4 or not is_power_of_four(m)): @@ -117,22 +123,23 @@ def make_non_differential_constellation(m, gray_coded): else: i_gcs = list(range(0, side)) # The distance between points is found. - step = 2.0 / (side-1) + step = 2.0 / (side - 1) - gc_to_x = [-1 + i_gcs[gc]*step for gc in range(0, side)] + gc_to_x = [-1 + i_gcs[gc] * step for gc in range(0, side)] # First k/2 bits determine x position. # Following k/2 bits determine y position. const_map = [] for i in range(m): y = gc_to_x[get_bits(i, 0, k // 2)] x = gc_to_x[get_bits(i, k // 2, k // 2)] - const_map.append(complex(x,y)) + const_map.append(complex(x, y)) return const_map # ///////////////////////////////////////////////////////////////////////////// # QAM constellation # ///////////////////////////////////////////////////////////////////////////// + def qam_constellation(constellation_points=_def_constellation_points, differential=_def_differential, mod_code=_def_mod_code, @@ -154,18 +161,20 @@ def qam_constellation(constellation_points=_def_constellation_points, else: raise ValueError("Mod code is not implemented for QAM") if differential: - points = make_differential_constellation(constellation_points, gray_coded=False) + points = make_differential_constellation( + constellation_points, gray_coded=False) else: - points = make_non_differential_constellation(constellation_points, gray_coded) + points = make_non_differential_constellation( + constellation_points, gray_coded) side = int(sqrt(constellation_points)) - width = 2.0 / (side-1) + width = 2.0 / (side - 1) # No pre-diff code # Should add one so that we can gray-code the quadrant bits too. pre_diff_code = [] if not large_ampls_to_corners: constellation = digital.constellation_rect(points, pre_diff_code, 4, - side, side, width, width) + side, side, width, width) else: sector_values = large_ampls_to_corners_mapping(side, points, width) constellation = digital.constellation_expl_rect( @@ -173,6 +182,7 @@ def qam_constellation(constellation_points=_def_constellation_points, return constellation + def find_closest_point(p, qs): """ Return in index of the closest point in 'qs' to 'p'. @@ -180,12 +190,13 @@ def find_closest_point(p, qs): min_dist = None min_i = None for i, q in enumerate(qs): - dist = abs(q-p) + dist = abs(q - p) if min_dist is None or dist < min_dist: min_dist = dist min_i = i return min_i + def large_ampls_to_corners_mapping(side, points, width): """ We have a grid that we use for decision making. One additional row/column @@ -222,7 +233,7 @@ def large_ampls_to_corners_mapping(side, points, width): # Value in this extra layer will be mapped to the closest corner rather # than the closest constellation point. extra_layers = 1 - side = side + extra_layers*2 + side = side + extra_layers * 2 # Calculate sector values sector_values = [] for real_x in range(side): @@ -230,10 +241,10 @@ def large_ampls_to_corners_mapping(side, points, width): sector = real_x * side + imag_x # If this sector is a normal constellation sector then # use the center point. - c = ((real_x-side / 2.0+0.5)*width + - (imag_x-side / 2.0+0.5)*width*1j) - if (real_x >= extra_layers and real_x < side-extra_layers - and imag_x >= extra_layers and imag_x < side-extra_layers): + c = ((real_x - side / 2.0 + 0.5) * width + + (imag_x - side / 2.0 + 0.5) * width * 1j) + if (real_x >= extra_layers and real_x < side - extra_layers + and imag_x >= extra_layers and imag_x < side - extra_layers): # This is not an edge row/column. Find closest point. index = find_closest_point(c, points) else: @@ -242,4 +253,5 @@ def large_ampls_to_corners_mapping(side, points, width): sector_values.append(index) return sector_values + modulation_utils.add_type_1_constellation('qam', qam_constellation) |