summaryrefslogtreecommitdiff
path: root/gr-digital/lib/meas_evm_cc_impl.cc
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/lib/meas_evm_cc_impl.cc
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/lib/meas_evm_cc_impl.cc')
-rw-r--r--gr-digital/lib/meas_evm_cc_impl.cc72
1 files changed, 72 insertions, 0 deletions
diff --git a/gr-digital/lib/meas_evm_cc_impl.cc b/gr-digital/lib/meas_evm_cc_impl.cc
new file mode 100644
index 0000000000..85d74cf358
--- /dev/null
+++ b/gr-digital/lib/meas_evm_cc_impl.cc
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2020 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "meas_evm_cc_impl.h"
+#include <gnuradio/io_signature.h>
+#include <numeric>
+
+namespace gr {
+namespace digital {
+
+meas_evm_cc::sptr meas_evm_cc::make(constellation_sptr cons, evm_measurement_t meas_type)
+{
+ return gnuradio::get_initial_sptr(new meas_evm_cc_impl(cons, meas_type));
+}
+
+meas_evm_cc_impl::meas_evm_cc_impl(constellation_sptr cons, evm_measurement_t meas_type)
+ : gr::sync_block("meas_evm_cc",
+ gr::io_signature::make(1, 1, sizeof(gr_complex)),
+ gr::io_signature::make(1, 1, sizeof(float))),
+ d_cons(cons),
+ d_cons_points(d_cons->points()),
+ d_meas_type(meas_type)
+{
+ // Calculate the average power of the constellation
+ float cons_mag_sq =
+ std::accumulate(d_cons_points.begin(),
+ d_cons_points.end(),
+ 0.0,
+ [](float s, gr_complex e) -> float { return s + std::norm(e); }) /
+ d_cons_points.size();
+ d_cons_mag = sqrt(cons_mag_sq);
+}
+
+meas_evm_cc_impl::~meas_evm_cc_impl() {}
+
+int meas_evm_cc_impl::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ auto in = static_cast<const gr_complex*>(input_items[0]);
+ auto out = static_cast<float*>(output_items[0]);
+
+ // Compare incoming symbols to the constellation decision points
+ for (int s = 0; s < noutput_items; s++) {
+ gr_complex u_n = in[s];
+ gr_complex decision;
+ d_cons->map_to_points(d_cons->decision_maker(&u_n), &decision);
+ float err_mag = std::abs(decision - u_n);
+
+ if (d_meas_type == evm_measurement_t::EVM_PERCENT) {
+ out[s] = (err_mag / d_cons_mag) * 100.0;
+ } else {
+ out[s] = 20 * log10(err_mag / d_cons_mag);
+ }
+ }
+
+ return noutput_items;
+}
+
+} // namespace digital
+} /* namespace gr */