From b622d2b13bd9f09828dda1246638f1466b1185ab Mon Sep 17 00:00:00 2001 From: Rob Riggs Date: Sun, 20 Jun 2021 20:43:34 -0500 Subject: [PATCH] Remove now-unused M17 components. --- TNC/CarrierDetect.h | 40 -------------- TNC/DeviationError.h | 96 ---------------------------------- TNC/FrequencyError.h | 63 ---------------------- TNC/Fsk4Demod.h | 122 ------------------------------------------- TNC/PhaseEstimator.h | 50 ------------------ TNC/SymbolEvm.h | 70 ------------------------- 6 files changed, 441 deletions(-) delete mode 100644 TNC/CarrierDetect.h delete mode 100644 TNC/DeviationError.h delete mode 100644 TNC/FrequencyError.h delete mode 100644 TNC/Fsk4Demod.h delete mode 100644 TNC/PhaseEstimator.h delete mode 100644 TNC/SymbolEvm.h diff --git a/TNC/CarrierDetect.h b/TNC/CarrierDetect.h deleted file mode 100644 index b408f23..0000000 --- a/TNC/CarrierDetect.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 Mobilinkd LLC. - -#pragma once - -#include "IirFilter.hpp" - -#include -#include -#include -#include - -namespace mobilinkd -{ - -template -struct CarrierDetect -{ - using result_t = std::tuple; - - tnc::IirFilter<3> filter_; - FloatType lock_; - FloatType unlock_; - bool locked_ = false; - - CarrierDetect(std::array const& b, std::array const& a, FloatType lock_level, FloatType unlock_level) - : filter_(b, a), lock_(lock_level), unlock_(unlock_level) - { - } - - result_t operator()(FloatType value) - { - auto filtered = filter_(std::abs(value)); - if (locked_ && (filtered > unlock_)) locked_ = false; - else if (!locked_ && (filtered < lock_)) locked_ = true; - - return std::make_tuple(locked_, filtered); - } -}; - -} // mobilinkd diff --git a/TNC/DeviationError.h b/TNC/DeviationError.h deleted file mode 100644 index 51c475b..0000000 --- a/TNC/DeviationError.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2020 Mobilinkd LLC. - -#pragma once - -#include -#include -#include - -namespace mobilinkd -{ - -template -struct DeviationError -{ - using float_type = T; - using array_t = std::array; - - array_t minima_{0}; - array_t maxima_{0}; - size_t min_index_ = 0; - size_t max_index_ = 0; - bool min_rolled_ = false; - bool max_rolled_ = false; - size_t min_count_ = 0; - size_t max_count_ = 0; - float_type min_estimate_ = 0.0; - float_type max_estimate_ = 0.0; - - const float_type ZERO = 0.0; - - DeviationError() - { - minima_.fill(0.0); - maxima_.fill(0.0); - } - - float_type operator()(float_type sample) - { - if (sample > ZERO) - { - if (sample > max_estimate_ * 0.67 or max_count_ == 5) - { - max_count_ = 0; - maxima_[max_index_++] = sample; - if (max_index_ == N) - { - max_rolled_ = true; - max_index_ = 0; - } - if (max_rolled_) - { - max_estimate_ = std::accumulate(std::begin(maxima_), std::end(maxima_), ZERO) / N; - } - else - { - max_estimate_ = std::accumulate(std::begin(maxima_), std::begin(maxima_) + max_index_, ZERO) / max_index_; - } - } - else - { - ++max_count_; - } - } - else if (sample < 0) - { - if (sample < min_estimate_ * 0.67 or min_count_ == 5) - { - min_count_ = 0; - minima_[min_index_++] = sample; - if (min_index_ == N) - { - min_rolled_ = true; - min_index_ = 0; - } - if (min_rolled_) - { - min_estimate_ = std::accumulate(std::begin(minima_), std::end(minima_), ZERO) / N; - } - else - { - min_estimate_ = std::accumulate(std::begin(minima_), std::begin(minima_) + min_index_, ZERO) / min_index_; - } - } - else - { - ++min_count_; - } - } - - auto deviation = max_estimate_ - min_estimate_; - auto deviation_error = std::min(6.0 / deviation, 100.0); - return deviation_error; - } -}; - -} // mobilinkd diff --git a/TNC/FrequencyError.h b/TNC/FrequencyError.h deleted file mode 100644 index a89a405..0000000 --- a/TNC/FrequencyError.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2020 Mobilinkd LLC. - -#pragma once - -#include "IirFilter.hpp" - -#include -#include -#include - -namespace mobilinkd -{ - -template -struct FrequencyError -{ - using float_type = FloatType; - using array_t = std::array; - using filter_type = tnc::IirFilter<3>; - - array_t samples_{0}; - size_t index_ = 0; - float_type accum_ = 0.0; - filter_type filter_; - - const float_type ZERO = 0.0; - - FrequencyError(const std::array& b, const std::array& a) - : filter_(b, a) - { - samples_.fill(0.0); - } - - auto operator()(float_type sample) - { - FloatType evm = 0; - bool use = true; - - if (sample > 2) - { - evm = sample - 3; - } - else if (sample >= -2) - { - use = false; - } - else - { - evm = sample + 3; - } - - if (use) - { - accum_ = accum_ - samples_[index_] + evm; - samples_[index_++] = evm; - if (index_ == N) index_ = 0; - } - - return filter_(accum_ / N); - } -}; - -} // mobilinkd diff --git a/TNC/Fsk4Demod.h b/TNC/Fsk4Demod.h deleted file mode 100644 index 5616d78..0000000 --- a/TNC/Fsk4Demod.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2020 Mobilinkd LLC. - -#pragma once - -#include "FirFilter.h" -#include "PhaseEstimator.h" -#include "DeviationError.h" -#include "FrequencyError.h" -#include "SymbolEvm.h" - -#include -#include -#include -#include - -namespace mobilinkd -{ - -namespace detail -{ -inline const auto rrc_taps = std::experimental::make_array( - -151, -100, -18, 80, 175, 246, 275, 249, 170, 49, -90, -219, - -304, -318, -245, -88, 131, 373, 581, 695, 659, 437, 22, -556, - -1229, -1890, -2409, -2641, -2452, -1738, -441, 1434, 3816, 6563, - 9480, 12334, 14880, 16891, 18179, 18622, 18179, 16891, 14880, 12334, - 9480, 6563, 3816, 1434, -441, -1738, -2452, -2641, -2409, -1890, - -1229, -556, 22, 437, 659, 695, 581, 373, 131, -88, -245, -318, -304, - -219, -90, 49, 170, 249, 275, 246, 175, 80, -18, -100, -151); - -inline const auto evm_b = std::experimental::make_array(0.02008337, 0.04016673, 0.02008337); -inline const auto evm_a = std::experimental::make_array(1.0, -1.56101808, 0.64135154); -} // detail - -struct Fsk4Demod -{ - using demod_result_t = std::tuple; - using result_t = std::optional>; - - tnc::Q15FirFilter<320, std::tuple_size::value> rrc; - PhaseEstimator phase = PhaseEstimator(48000, 4800); - DeviationError deviation; - FrequencyError frequency; - SymbolEvm::value> symbol_evm = makeSymbolEvm(makeIirFilter(detail::evm_b, detail::evm_a)); - - double sample_rate = 48000; - double symbol_rate = 4800; - double gain = 0.04; - std::array samples{0}; - double t = 0; - double dt = symbol_rate / sample_rate; - double ideal_dt = dt; - bool sample_now = false; - double estimated_deviation = 1.0; - double estimated_frequency_offset = 0.0; - double evm_average = 0.0; - - Fsk4Demod(double sample_rate, double symbol_rate, double gain = 0.04) - : sample_rate(sample_rate) - , symbol_rate(symbol_rate) - , gain(gain * symbol_rate / sample_rate) - , dt(symbol_rate / sample_rate) - , ideal_dt(dt) - { - samples.fill(0.0); - } - - demod_result_t demod() - { - estimated_deviation = deviation(samples[1]); - for (auto& sample : samples) sample *= estimated_deviation; - - estimated_frequency_offset = frequency(samples[1]); - for (auto& sample : samples) sample -= estimated_frequency_offset; - - auto phase_estimate = phase(samples); - if (samples[1] < 0) phase_estimate *= -1; - - dt = ideal_dt - (phase_estimate * gain); - t += dt; - - auto [symbol, evm] = symbol_evm(samples[1]); - evm_average = symbol_evm.evm(); - samples[0] = samples[2]; - - return std::make_tuple(samples[1], phase_estimate, symbol, evm); - } - - /** - * Process the sample. If a symbol is ready, return a tuple - * containing the sample used, the estimated phase, the decoded - * symbol, the EVM, the deviation error and the frequency error - * (sample, phase, symbol, evm, ed, ef), otherwise None. - */ - result_t operator()(double sample) - { - auto filtered_sample = rrc(sample); - - if (sample_now) - { - samples[2] = filtered_sample; - sample_now = false; - auto [prev_sample, phase_estimate, symbol, evm] = demod(); - return std::make_tuple(prev_sample, phase_estimate, symbol, evm, estimated_deviation, estimated_frequency_offset, evm_average); - } - - t += dt; - if (t < 1.0) - { - samples[0] = filtered_sample; - } - else - { - t -= 1.0; - samples[1] = filtered_sample; - sample_now = true; - } - - return std::nullopt; - } -}; - -} // mobilinkd diff --git a/TNC/PhaseEstimator.h b/TNC/PhaseEstimator.h deleted file mode 100644 index c328dc5..0000000 --- a/TNC/PhaseEstimator.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2020 Mobilinkd LLC. - -#pragma once - -#include -#include -#include - -namespace mobilinkd -{ - -/** - * Estimate the phase of a sample by estimating the - * tangent of the sample point. This is done by computing - * the magnitude difference of the previous and following - * samples. We do not correct for 0-crossing errors because - * these errors have not affected the performance of clock - * recovery. - */ -template -struct PhaseEstimator -{ - using samples_t = std::array; // 3 samples in length - - FloatType dx_; - - PhaseEstimator(FloatType sample_rate, FloatType symbol_rate) - : dx_(2.0 * symbol_rate / sample_rate) - { - assert(dx_ > 0.0); - } - - /** - * This performs a rolling estimate of the phase. - * - * @param samples are three samples centered around the current sample point - * (t-1, t, t+1). - */ - FloatType operator()(const samples_t& samples) - { - auto ratio = ((samples.at(2) - samples.at(0)) / 3.0f) / dx_; - // Clamp +/-5. - ratio = std::min(FloatType(5.0), ratio); - ratio = std::max(FloatType(-5.0), ratio); - - return ratio; - } -}; - -} // mobilinkd diff --git a/TNC/SymbolEvm.h b/TNC/SymbolEvm.h deleted file mode 100644 index 5522414..0000000 --- a/TNC/SymbolEvm.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2020 Mobilinkd LLC. - -#pragma once - -#include "IirFilter.hpp" - -#include -#include -#include - -namespace mobilinkd -{ - -template -struct SymbolEvm -{ - using filter_type = tnc::IirFilter; - using symbol_t = int; - using result_type = std::tuple; - - filter_type filter_; - FloatType evm_ = 0.0; - - SymbolEvm(const std::array& b, const std::array& a) - : filter_(b, a) - {} - - FloatType 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()(FloatType sample) - { - symbol_t symbol; - FloatType evm; - - sample = std::min(3.0f, std::max(-3.0f, sample)); - - if (sample > 2) - { - symbol = 3; - evm = (sample - 3) * 0.333333f; - } - 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.333333f; - } - - evm_ = filter_(evm); - - return std::make_tuple(symbol, evm); - } -}; - -} // mobilinkd