From 1458b71d90310444e556f515ee86dde7c287ed79 Mon Sep 17 00:00:00 2001
From: japm48 <japm48@users.noreply.github.com>
Date: Tue, 20 Oct 2020 07:54:59 +0200
Subject: digital: ofdm_equalizer_simpledfe: add enable_soft_output option

Enable outputting equalized symbols that are not exactly constellation
symbols. This is useful for OFDM soft decoding/demodulation (e.g.
optimal turbo or LDPC decoding).

For compatibility, this new behaviour has to be enabled by setting the
new option "enable_soft_output" to true (false by default).
---
 .../bindings/ofdm_equalizer_simpledfe_python.cc    |  3 +-
 .../python/digital/qa_ofdm_frame_equalizer_vcvc.py | 37 ++++++++++++++++++++--
 2 files changed, 36 insertions(+), 4 deletions(-)
 mode change 100644 => 100755 gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py

(limited to 'gr-digital/python/digital')

diff --git a/gr-digital/python/digital/bindings/ofdm_equalizer_simpledfe_python.cc b/gr-digital/python/digital/bindings/ofdm_equalizer_simpledfe_python.cc
index 44bb7e5b42..fcd939057f 100644
--- a/gr-digital/python/digital/bindings/ofdm_equalizer_simpledfe_python.cc
+++ b/gr-digital/python/digital/bindings/ofdm_equalizer_simpledfe_python.cc
@@ -14,7 +14,7 @@
 /* BINDTOOL_GEN_AUTOMATIC(0)                                                       */
 /* BINDTOOL_USE_PYGCCXML(0)                                                        */
 /* BINDTOOL_HEADER_FILE(ofdm_equalizer_simpledfe.h) */
-/* BINDTOOL_HEADER_FILE_HASH(8091e37dbba4afc0b7a2fd9441996144)                     */
+/* BINDTOOL_HEADER_FILE_HASH(e484906ff9740a46f83b999ec69f511e)                     */
 /***********************************************************************************/
 
 #include <pybind11/complex.h>
@@ -47,6 +47,7 @@ void bind_ofdm_equalizer_simpledfe(py::module& m)
              py::arg("symbols_skipped") = 0,
              py::arg("alpha") = 0.10000000000000001,
              py::arg("input_is_shifted") = true,
+             py::arg("enable_soft_output") = false,
              D(ofdm_equalizer_simpledfe, make))
 
 
diff --git a/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py
old mode 100644
new mode 100755
index 6af2817685..a1b2a2e070
--- a/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py
+++ b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py
@@ -167,6 +167,7 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase):
         # Check data
         self.assertComplexTuplesAlmostEqual(rx_expected, sink.data()[0], places=4)
 
+
     def test_002_static (self):
         """
         - Add a simple channel
@@ -229,6 +230,9 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase):
         expected_dict = {
                 'ofdm_sync_chan_taps': channel[-fft_len:]
         }
+        # Won't be exactly the same when compiled with -fcx-limited-range
+        self.assertTrue(numpy.allclose(tag_dict['ofdm_sync_chan_taps'], expected_dict['ofdm_sync_chan_taps']))
+        expected_dict['ofdm_sync_chan_taps'] = tag_dict['ofdm_sync_chan_taps']
         self.assertEqual(tag_dict, expected_dict)
 
     def test_002_static_wo_tags (self):
@@ -330,6 +334,9 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase):
         equalizer = digital.ofdm_equalizer_simpledfe(
             fft_len, cnst.base(), occupied_carriers, pilot_carriers, pilot_symbols, 0, 0.01
         )
+        equalizer_soft = digital.ofdm_equalizer_simpledfe(
+            fft_len, cnst.base(), occupied_carriers, pilot_carriers, pilot_symbols, 0, 0.01, enable_soft_output=True
+        )
         channel = [
             0, 0,  1,  1, 0,  1,  1, 0,
             0, 0,  1,  1, 0,  1,  1, 0, # These coefficients will be rotated slightly...
@@ -346,16 +353,40 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase):
         chan_tag.value = pmt.init_c32vector(fft_len, channel[:fft_len])
         src = blocks.vector_source_c(numpy.multiply(tx_signal, channel), False, fft_len, (chan_tag,))
         eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, self.tsb_key, True)
+        eq_soft = digital.ofdm_frame_equalizer_vcvc(equalizer_soft.base(), 0, self.tsb_key, True)
         sink = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key)
+        sink_soft = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key)
+        stream_to_tagged = blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data) // fft_len, self.tsb_key)
         self.tb.connect(
                 src,
-                blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data) // fft_len, self.tsb_key),
+                stream_to_tagged,
                 eq,
                 sink
         )
+        self.tb.connect(
+          stream_to_tagged,
+          eq_soft,
+          sink_soft
+        )
         self.tb.run ()
-        rx_data = [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in sink.data()[0]]
+
+        out_syms = numpy.array(sink.data()[0])
+        out_syms_soft = numpy.array(sink_soft.data()[0])
+        demod = lambda syms: [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in syms]
+        rx_data = demod(out_syms)
+        rx_data_soft = demod(out_syms_soft)
+
+        ## Uncomment to plot symbols
+        #import matplotlib.pyplot as plt
+        #def plot_syms(d): plt.figure(); plt.plot(d.real, d.imag, 'b.')
+        #
+        #plot_syms(out_syms)
+        #plot_syms(out_syms_soft)
+        #plt.show()
+
         self.assertEqual(tx_data, rx_data)
+        self.assertEqual(rx_data, rx_data_soft)
+        self.assertFalse(numpy.allclose(out_syms, out_syms_soft))
         self.assertEqual(len(sink.tags()), 1)
         tag = sink.tags()[0]
         self.assertEqual(pmt.symbol_to_string(tag.key), "ofdm_sync_chan_taps")
@@ -363,5 +394,5 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase):
 
 
 if __name__ == '__main__':
-    gr_unittest.run(qa_ofdm_frame_equalizer_vcvc, "qa_ofdm_frame_equalizer_vcvc.xml")
+    gr_unittest.run(qa_ofdm_frame_equalizer_vcvc)
 
-- 
cgit v1.2.3