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/lib/meas_evm_cc_impl.cc | |
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/lib/meas_evm_cc_impl.cc')
-rw-r--r-- | gr-digital/lib/meas_evm_cc_impl.cc | 72 |
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 */ |