diff options
author | mormj <34754695+mormj@users.noreply.github.com> | 2020-04-09 07:38:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-09 07:38:25 -0400 |
commit | 3c1750c481a578bd831fce933502fde88444eb54 (patch) | |
tree | b2e3baf85a1e0605fdf4b0bfcf3e4d6280dfe439 /gr-digital/python/digital/qa_meas_evm_cc.py | |
parent | 7bc8622dda145164c97b73b1c8d4aaf3e0a8bf16 (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-x | gr-digital/python/digital/qa_meas_evm_cc.py | 127 |
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) |