From 4c0802e83d72ca43536c2cc2842bb0aadb9c71ec Mon Sep 17 00:00:00 2001
From: Ben Reynwar <ben@reynwar.net>
Date: Wed, 6 Mar 2013 12:37:40 -0700
Subject: digital: Adding option to QAM to help with frequency locking.

---
 gr-digital/python/qa_constellation.py | 5 +++++
 1 file changed, 5 insertions(+)

(limited to 'gr-digital/python/qa_constellation.py')

diff --git a/gr-digital/python/qa_constellation.py b/gr-digital/python/qa_constellation.py
index 6962ec6338..1560021f56 100755
--- a/gr-digital/python/qa_constellation.py
+++ b/gr-digital/python/qa_constellation.py
@@ -73,6 +73,11 @@ tested_constellation_info = (
      {'constellation_points': (4, 16, 64),
       'mod_code': tested_mod_codes, },
      True, None),
+    (qam.qam_constellation,
+     {'constellation_points': (16, 64),
+      'mod_code': [mod_codes.GRAY_CODE],
+      'large_ampls_to_corners': [True]},
+     True, None),
     (digital_swig.constellation_bpsk, {}, True, None),
     (digital_swig.constellation_qpsk, {}, False, None),
     (digital_swig.constellation_dqpsk, {}, True, None),
-- 
cgit v1.2.3


From bed49a09f0c395f29d0a367a4bafce12b9765fa9 Mon Sep 17 00:00:00 2001
From: Ben Reynwar <ben@reynwar.net>
Date: Wed, 6 Mar 2013 13:41:33 -0700
Subject: digital: Making qa_constellation_receiver more reliable.

---
 gr-digital/python/qa_constellation.py          | 52 ++++++++++++++++++++------
 gr-digital/python/qa_constellation_receiver.py | 50 +++++++++++++++----------
 2 files changed, 71 insertions(+), 31 deletions(-)

(limited to 'gr-digital/python/qa_constellation.py')

diff --git a/gr-digital/python/qa_constellation.py b/gr-digital/python/qa_constellation.py
index 1560021f56..0e3ab72ee4 100755
--- a/gr-digital/python/qa_constellation.py
+++ b/gr-digital/python/qa_constellation.py
@@ -64,19 +64,19 @@ def threed_constell():
     dim = 3
     return digital_swig.constellation_calcdist(points, [], rot_sym, dim)
 
-tested_constellation_info = (
+# A list of tuples for constellation testing.  The contents of the
+# tuples are (constructor, poss_args, differential, diff_argname).
+
+# These constellations should lock on well.
+easy_constellation_info = (
     (psk.psk_constellation,
-     {'m': (2, 4, 8, 16, 32, 64),
-      'mod_code': tested_mod_codes, },
-     True, None),
-    (qam.qam_constellation,
-     {'constellation_points': (4, 16, 64),
+     {'m': (2, 4, 8, 16, ),
       'mod_code': tested_mod_codes, },
      True, None),
     (qam.qam_constellation,
-     {'constellation_points': (16, 64),
-      'mod_code': [mod_codes.GRAY_CODE],
-      'large_ampls_to_corners': [True]},
+     {'constellation_points': (4,),
+      'mod_code': tested_mod_codes, 
+      'large_ampls_to_corners': [False],},
      True, None),
     (digital_swig.constellation_bpsk, {}, True, None),
     (digital_swig.constellation_qpsk, {}, False, None),
@@ -86,11 +86,41 @@ tested_constellation_info = (
     (threed_constell, {}, True, None),
     )
 
-def tested_constellations():
+# These constellations don't work nicely.
+# We have a lower required error rate.
+medium_constellation_info = (
+    (psk.psk_constellation,
+     {'m': (32, 64),
+      'mod_code': tested_mod_codes, },
+     True, None),
+    (qam.qam_constellation,
+     {'constellation_points': (16 ,),
+      'mod_code': tested_mod_codes, 
+      'large_ampls_to_corners': [False, True],},
+     True, None),
+)
+
+# These constellation are basically broken in our test
+difficult_constellation_info = (
+    (qam.qam_constellation,
+     {'constellation_points': (64,),
+      'mod_code': tested_mod_codes, 
+      'large_ampls_to_corners': [False, True],},
+     True, None),    
+)
+
+def tested_constellations(easy=True, medium=True, difficult=True):
     """
     Generator to produce (constellation, differential) tuples for testing purposes.
     """
-    for constructor, poss_args, differential, diff_argname in tested_constellation_info:
+    constellation_info = []
+    if easy:
+        constellation_info += easy_constellation_info
+    if medium:
+        constellation_info += medium_constellation_info
+    if difficult:
+        constellation_info += difficult_constellation_info
+    for constructor, poss_args, differential, diff_argname in constellation_info:
         if differential:
             diff_poss = (True, False)
         else:
diff --git a/gr-digital/python/qa_constellation_receiver.py b/gr-digital/python/qa_constellation_receiver.py
index 2d25433b92..37e56b4cf7 100755
--- a/gr-digital/python/qa_constellation_receiver.py
+++ b/gr-digital/python/qa_constellation_receiver.py
@@ -39,7 +39,9 @@ SEED = 1239
 # We need this many to let the frequency recovery block converge.
 DATA_LENGTH = 2000
 # Test fails if fraction of output that is correct is less than this.
-REQ_CORRECT = 0.7
+EASY_REQ_CORRECT = 0.9
+# For constellations that aren't expected to work so well.
+MEDIUM_REQ_CORRECT = 0.8
 
 # CHANNEL PARAMETERS
 NOISE_VOLTAGE = 0.01
@@ -78,25 +80,33 @@ class test_constellation_receiver (gr_unittest.TestCase):
         self.indices = alignment.random_sample(
             self.max_data_length, self.max_num_samples, SEED)
 
-        for constellation, differential in tested_constellations():
-            # The constellation_receiver doesn't work for constellations
-            # of multple dimensions (i.e. multiple complex numbers to a
-            # single symbol).
-            # That is not implemented since the receiver has no way of
-            # knowing where the beginning of a symbol is.
-            # It also doesn't work for non-differential modulation.
-            if constellation.dimensionality() != 1 or not differential:
-                continue
-            data_length = DATA_LENGTH * constellation.bits_per_symbol()
-            tb = rec_test_tb(constellation, differential,
-                             src_data=self.src_data[:data_length])
-            tb.run()
-            data = tb.dst.data()
-            d1 = tb.src_data[:int(len(tb.src_data)*self.ignore_fraction)]
-            d2 = data[:int(len(data)*self.ignore_fraction)]
-            correct, overlap, offset, indices = alignment.align_sequences(
-                d1, d2, indices=self.indices)
-            self.assertTrue(correct > REQ_CORRECT)
+        requirements = (
+            (EASY_REQ_CORRECT, tested_constellations(easy=True, medium=False, difficult=False)),
+            (MEDIUM_REQ_CORRECT, tested_constellations(easy=False, medium=True, difficult=False)),
+            )
+        for req_correct, tcs in requirements:
+            for constellation, differential in tcs:
+                # The constellation_receiver doesn't work for constellations
+                # of multple dimensions (i.e. multiple complex numbers to a
+                # single symbol).
+                # That is not implemented since the receiver has no way of
+                # knowing where the beginning of a symbol is.
+                # It also doesn't work for non-differential modulation.
+                if constellation.dimensionality() != 1 or not differential:
+                    continue
+                data_length = DATA_LENGTH * constellation.bits_per_symbol()
+                tb = rec_test_tb(constellation, differential,
+                                 src_data=self.src_data[:data_length])
+                tb.run()
+                data = tb.dst.data()
+                d1 = tb.src_data[:int(len(tb.src_data)*self.ignore_fraction)]
+                d2 = data[:int(len(data)*self.ignore_fraction)]
+                correct, overlap, offset, indices = alignment.align_sequences(
+                    d1, d2, indices=self.indices)
+                if correct <= req_correct:
+                    print("Constellation is {0}. Differential is {1}.  Required correct is {2}. Correct is {3}. FAIL.".
+                          format(constellation, differential, req_correct, correct))
+                self.assertTrue(correct > req_correct)
             
 
 class rec_test_tb (gr.top_block):
-- 
cgit v1.2.3


From 9ff75b4133400de216afe236d4cdbb368ec8afd8 Mon Sep 17 00:00:00 2001
From: Ben Reynwar <ben@reynwar.net>
Date: Wed, 6 Mar 2013 13:42:31 -0700
Subject: digital: Adding a QAM-like constellation with 32 points.

---
 gr-digital/python/CMakeLists.txt      |  1 +
 gr-digital/python/qa_constellation.py |  4 ++
 gr-digital/python/qamlike.py          | 75 +++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)
 create mode 100644 gr-digital/python/qamlike.py

(limited to 'gr-digital/python/qa_constellation.py')

diff --git a/gr-digital/python/CMakeLists.txt b/gr-digital/python/CMakeLists.txt
index 8f2af0664d..9be5e1ae75 100644
--- a/gr-digital/python/CMakeLists.txt
+++ b/gr-digital/python/CMakeLists.txt
@@ -43,6 +43,7 @@ GR_PYTHON_INSTALL(
     pkt.py
     psk.py
     qam.py
+    qamlike.py
     qpsk.py
     DESTINATION ${GR_PYTHON_DIR}/gnuradio/digital
     COMPONENT "digital_python"
diff --git a/gr-digital/python/qa_constellation.py b/gr-digital/python/qa_constellation.py
index 0e3ab72ee4..ddd8c71e64 100755
--- a/gr-digital/python/qa_constellation.py
+++ b/gr-digital/python/qa_constellation.py
@@ -30,6 +30,7 @@ import digital_swig
 # import from local folder
 import psk
 import qam
+import qamlike
 
 tested_mod_codes = (mod_codes.NO_CODE, mod_codes.GRAY_CODE)
 
@@ -98,6 +99,9 @@ medium_constellation_info = (
       'mod_code': tested_mod_codes, 
       'large_ampls_to_corners': [False, True],},
      True, None),
+    (qamlike.qam32_holeinside_constellation,
+     {'large_ampls_to_corners': [True]},
+     True, None),
 )
 
 # These constellation are basically broken in our test
diff --git a/gr-digital/python/qamlike.py b/gr-digital/python/qamlike.py
new file mode 100644
index 0000000000..2f8c855339
--- /dev/null
+++ b/gr-digital/python/qamlike.py
@@ -0,0 +1,75 @@
+# Copyright 2013 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.
+# 
+
+"""
+This file contains constellations that are similar to QAM, but are not perfect squares.
+"""
+
+import digital_swig
+from qam import large_ampls_to_corners_mapping
+
+def qam32_holeinside_constellation(large_ampls_to_corners=False):
+    # First make constellation for one quadrant.
+    #      0   1   2 
+    # 2 - 010 111 110
+    # 1 - 011 101 100
+    # 0 - 000 001
+
+    # Have put hole in the side rather than corner.
+    # Corner point is helpful for frequency locking.
+
+    # It has an attempt at some gray-coding, but not
+    # a very good one.
+
+    # Indices are (horizontal, vertical).
+    indices_and_numbers = (
+        ((0, 0), 0b000),
+        ((0, 1), 0b011),
+        ((0, 2), 0b010),
+        ((1, 0), 0b001),
+        ((1, 1), 0b101),
+        ((1, 2), 0b111),
+        ((2, 1), 0b100),
+        ((2, 2), 0b110),
+        )
+    points = [None]*32
+    for indices, number in indices_and_numbers:
+        p_in_quadrant = 0.5+indices[0] + 1j*(0.5+indices[1])
+        for quadrant in range(4):
+            index = number + 8 * quadrant
+            rotation = pow(1j, quadrant)
+            p = p_in_quadrant * rotation
+            points[index] = p
+    side = 6
+    width = 1
+    # Double number of boxes on side
+    # This is so that points in the 'hole' get assigned correctly.
+    side = 12
+    width = 0.5
+    pre_diff_code = []
+    if not large_ampls_to_corners:
+        constellation = digital_swig.constellation_rect(points, pre_diff_code, 4,
+                                                        side, side, width, width)
+    else:
+        sector_values = large_ampls_to_corners_mapping(side, points, width)
+        constellation = digital_swig.constellation_expl_rect(
+            points, pre_diff_code, 4, side, side, width, width, sector_values)
+    return constellation
+
-- 
cgit v1.2.3