// Copyright 2020 Mobilinkd LLC. #pragma once #include "IirFilter.h" #include #include #include #include namespace modemm17 { template struct SymbolEvm { using filter_type = BaseIirFilter; using symbol_t = int; using result_type = std::tuple; filter_type filter_; float erasure_limit_; float evm_ = 0.0; SymbolEvm(filter_type&& filter, float erasure_limit = 0.0) : filter_(std::forward(filter)), erasure_limit_(erasure_limit) {} float evm() const { return evm_; } /** * Decode a normalized sample into a symbol. Symbols * are decoded into +3, +1, -1, -3. If an erasure limit * is set, symbols outside this limit are 'erased' and * returned as 0. */ result_type operator()(float sample) { symbol_t symbol; float evm; sample = std::min(3.0f, std::max(-3.0f, sample)); if (sample > 2) { symbol = 3; evm = (sample - 3) * 0.333333; } else if (sample > 0) { symbol = 1; evm = sample - 1; } else if (sample >= -2) { symbol = -1; evm = sample + 1; } else { symbol = -3; evm = (sample + 3) * 0.333333; } if (erasure_limit_ and (std::abs(evm) > erasure_limit_)) symbol = 0; evm_ = filter_(evm); return std::make_tuple(symbol, evm); } }; template SymbolEvm makeSymbolEvm( BaseIirFilter&& filter, float erasure_limit = 0.0f ) { return std::move(SymbolEvm(std::move(filter), erasure_limit)); } } // modemm17