summaryrefslogtreecommitdiff
path: root/gr-digital/python/digital/qa_meas_evm_cc.py
diff options
context:
space:
mode:
authormormj <34754695+mormj@users.noreply.github.com>2020-04-09 07:38:25 -0400
committerGitHub <noreply@github.com>2020-04-09 07:38:25 -0400
commit3c1750c481a578bd831fce933502fde88444eb54 (patch)
treeb2e3baf85a1e0605fdf4b0bfcf3e4d6280dfe439 /gr-digital/python/digital/qa_meas_evm_cc.py
parent7bc8622dda145164c97b73b1c8d4aaf3e0a8bf16 (diff)
digital: restructure equalizers and add dfe (#3306)
* digital: restructure equalizers and add dfe This commit restructures the linear equalizer to have a separate specifiable adaptive algorithm. Generally this works the same as the previous LMS and CMA decision directed equalizers, but also adds the ability to equalize using training sequences as well. Also, a Decision Feedback Equalizer structure is added * digital: more const in equalizers * digital: equalizers - more safety based on review * digital: dfe - use deque instead of vector for decision_history * digital - equalizers, further cleanup
Diffstat (limited to 'gr-digital/python/digital/qa_meas_evm_cc.py')
-rwxr-xr-xgr-digital/python/digital/qa_meas_evm_cc.py127
1 files changed, 127 insertions, 0 deletions
diff --git a/gr-digital/python/digital/qa_meas_evm_cc.py b/gr-digital/python/digital/qa_meas_evm_cc.py
new file mode 100755
index 0000000000..cf3b4577da
--- /dev/null
+++ b/gr-digital/python/digital/qa_meas_evm_cc.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+#
+# Copyright 2020 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+#
+
+from gnuradio import gr, gr_unittest
+from gnuradio import blocks
+
+import random, numpy
+from gnuradio import digital
+from gnuradio import channels
+
+class qa_meas_evm_cc(gr_unittest.TestCase):
+
+ def setUp(self):
+ random.seed(987654)
+ self.tb = gr.top_block()
+ self.num_data = num_data = 1000
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_qpsk(self):
+ # set up fg
+ expected_result = tuple(numpy.zeros((self.num_data,)))
+
+ self.cons = cons = digital.constellation_qpsk().base()
+ self.data = data = [random.randrange(len(cons.points())) for x in range(self.num_data)]
+ self.symbols = symbols = numpy.squeeze([cons.map_to_points_v(i) for i in data])
+
+ evm = digital.meas_evm_cc(cons, digital.evm_measurement_t_EVM_PERCENT)
+ vso = blocks.vector_source_c(symbols, False, 1, [])
+ # mc = blocks.multiply_const_cc(3.0+2.0j)
+ vsi = blocks.vector_sink_f()
+
+ self.tb.connect(vso, evm, vsi)
+ self.tb.run()
+ # check data
+
+ output_data = vsi.data()
+ self.assertEqual(expected_result, output_data)
+
+ def test_qpsk_nonzeroevm(self):
+ # set up fg
+ expected_result = tuple(numpy.zeros((self.num_data,)))
+
+ self.cons = cons = digital.constellation_qpsk().base()
+ self.data = data = [random.randrange(len(cons.points())) for x in range(self.num_data)]
+ self.symbols = symbols = numpy.squeeze([cons.map_to_points_v(i) for i in data])
+
+ evm = digital.meas_evm_cc(cons, digital.evm_measurement_t_EVM_PERCENT)
+ vso = blocks.vector_source_c(symbols, False, 1, [])
+ mc = blocks.multiply_const_cc(3.0+2.0j)
+ vsi = blocks.vector_sink_f()
+
+ self.tb.connect(vso, mc, evm, vsi)
+ self.tb.run()
+ # check data
+
+ output_data = vsi.data()
+ self.assertNotEqual(expected_result, output_data)
+
+ def test_qpsk_channel(self):
+ upper_bound = tuple(50.0*numpy.ones((self.num_data,)))
+ lower_bound = tuple(0.0*numpy.zeros((self.num_data,)))
+
+ self.cons = cons = digital.constellation_qpsk().base()
+ self.data = data = [random.randrange(len(cons.points())) for x in range(self.num_data)]
+ self.symbols = symbols = numpy.squeeze([cons.map_to_points_v(i) for i in data])
+
+ chan = channels.channel_model(
+ noise_voltage=0.1,
+ frequency_offset=0.0,
+ epsilon=1.0,
+ taps=[1.0 + 0.0j],
+ noise_seed=0,
+ block_tags=False)
+
+ evm = digital.meas_evm_cc(cons, digital.evm_measurement_t_EVM_PERCENT)
+ vso = blocks.vector_source_c(symbols, False, 1, [])
+ mc = blocks.multiply_const_cc(3.0+2.0j)
+ vsi = blocks.vector_sink_f()
+
+ self.tb.connect(vso, chan, evm, vsi)
+ self.tb.run()
+ # check data
+
+ output_data = vsi.data()
+ self.assertLess(output_data, upper_bound)
+ self.assertGreater(output_data, lower_bound)
+
+ def test_qam16_channel(self):
+ upper_bound = tuple(50.0*numpy.ones((self.num_data,)))
+ lower_bound = tuple(0.0*numpy.zeros((self.num_data,)))
+
+ self.cons = cons = digital.constellation_16qam().base()
+ self.data = data = [random.randrange(len(cons.points())) for x in range(self.num_data)]
+ self.symbols = symbols = numpy.squeeze([cons.map_to_points_v(i) for i in data])
+
+ chan = channels.channel_model(
+ noise_voltage=0.1,
+ frequency_offset=0.0,
+ epsilon=1.0,
+ taps=[1.0 + 0.0j],
+ noise_seed=0,
+ block_tags=False)
+
+ evm = digital.meas_evm_cc(cons, digital.evm_measurement_t_EVM_PERCENT)
+ vso = blocks.vector_source_c(symbols, False, 1, [])
+ mc = blocks.multiply_const_cc(3.0+2.0j)
+ vsi = blocks.vector_sink_f()
+
+ self.tb.connect(vso, chan, evm, vsi)
+ self.tb.run()
+ # check data
+
+ output_data = vsi.data()
+ self.assertLess(output_data, upper_bound)
+ self.assertGreater(output_data, lower_bound)
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_meas_evm_cc)