From b5fc9b252d5293b210e1fa5daeaf693c701c497b Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Sat, 13 Aug 2022 09:38:36 +0200 Subject: [PATCH] Moved code of compensating filter for MDx PWM-based DAC to a dedicated class. --- openrtx/include/core/dsp.h | 11 --- .../include/protocols/M17/M17Modulator.hpp | 4 +- .../include/protocols/M17/PwmCompensator.hpp | 99 +++++++++++++++++++ openrtx/src/core/dsp.cpp | 37 ------- openrtx/src/protocols/M17/M17Modulator.cpp | 13 ++- 5 files changed, 107 insertions(+), 57 deletions(-) create mode 100644 openrtx/include/protocols/M17/PwmCompensator.hpp diff --git a/openrtx/include/core/dsp.h b/openrtx/include/core/dsp.h index 63eb31c5..b5e21fea 100644 --- a/openrtx/include/core/dsp.h +++ b/openrtx/include/core/dsp.h @@ -55,17 +55,6 @@ filter_state_t; */ void dsp_resetFilterState(filter_state_t *state); -/** - * Compensate for the filtering applied by the PWM output over the modulated - * signal. The buffer is be processed in place to save memory. - * - * @param state: pointer to the data structure containing the filter state. - * @param buffer: the buffer to be used as both source and destination. - * @param length: the length of the input buffer. - */ -void dsp_pwmCompensate(filter_state_t *state, audio_sample_t *buffer, - size_t length); - /** * Remove the DC offset from a collection of audio samples, processing data * in-place. diff --git a/openrtx/include/protocols/M17/M17Modulator.hpp b/openrtx/include/protocols/M17/M17Modulator.hpp index 006b571d..79671b19 100644 --- a/openrtx/include/protocols/M17/M17Modulator.hpp +++ b/openrtx/include/protocols/M17/M17Modulator.hpp @@ -27,10 +27,10 @@ #include #include +#include #include #include #include -#include namespace M17 { @@ -115,7 +115,7 @@ private: bool txRunning; ///< Transmission running. #if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0) - filter_state_t pwmFilterState; + PwmCompensator pwmComp; #endif }; diff --git a/openrtx/include/protocols/M17/PwmCompensator.hpp b/openrtx/include/protocols/M17/PwmCompensator.hpp new file mode 100644 index 00000000..3afd0442 --- /dev/null +++ b/openrtx/include/protocols/M17/PwmCompensator.hpp @@ -0,0 +1,99 @@ +/*************************************************************************** + * Copyright (C) 2022 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN, * + * Silvano Seva IU2KWO, * + * Frederik Saraci IU2NRO * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#ifndef PWMCOMPENSATOR_H +#define PWMCOMPENSATOR_H + +#ifndef __cplusplus +#error This header is C++ only! +#endif + +#include +#include +#include + +/** + * Compensation filter for MDx PWM-based baseband output. + */ +class PwmCompensator +{ +public: + + /** + * Constructor. + */ + PwmCompensator() + { + reset(); + } + + /** + * Destructor. + */ + ~PwmCompensator() { } + + /** + * Perform one step of the filter, computing a new output value given + * the input value and the history of previous input values. + * + * @param input: input value for the current time step. + * @return output as a function of the current and past input values. + */ + float operator()(const float& input) + { + u[0] = input; + y[0] = (a/d)*(u[0]) + + (b/d)*(u[1]) + + (c/d)*(u[2]) + - (e/d)*(y[1]) + - (f/d)*(y[2]); + + for(size_t i = 2; i > 0; i--) + { + u[i] = u[i - 1]; + y[i] = y[i - 1]; + } + + return y[0] * 0.5f; + } + + /** + * Reset history, clearing the memory of past values. + */ + void reset() + { + u.fill(0.0f); + y.fill(0.0f); + } + +private: + + static constexpr float a = 4982680082321166792352.0f; + static constexpr float b = -6330013275146484168000.0f; + static constexpr float c = 1871109008789062500000.0f; + static constexpr float d = 548027992248535162477.0f; + static constexpr float e = -24496793746948241250.0f; + static constexpr float f = 244617462158203125.0f; + + std::array< float, 3 > u; ///< History of past inputs. + std::array< float, 3 > y; ///< History of past outputs. +}; + +#endif /* PWMCOMPENSATOR_H */ diff --git a/openrtx/src/core/dsp.cpp b/openrtx/src/core/dsp.cpp index 2de2889a..efea1c0f 100644 --- a/openrtx/src/core/dsp.cpp +++ b/openrtx/src/core/dsp.cpp @@ -33,43 +33,6 @@ void dsp_resetFilterState(filter_state_t *state) state->initialised = false; } -void dsp_pwmCompensate(filter_state_t *state, audio_sample_t *buffer, - size_t length) -{ - static constexpr float a = 4982680082321166792352.0f; - static constexpr float b = -6330013275146484168000.0f; - static constexpr float c = 1871109008789062500000.0f; - static constexpr float d = 548027992248535162477.0f; - static constexpr float e = -24496793746948241250.0f; - static constexpr float f = 244617462158203125.0f; - - // Initialise filter with first two values, for smooth transient. - if(length <= 2) return; - - if(state->initialised == false) - { - state->u[2] = static_cast< float >(buffer[0]); - state->u[1] = static_cast< float >(buffer[1]); - state->initialised = true; - } - - for(size_t i = 2; i < length; i++) - { - state->u[0] = static_cast< float >(buffer[i]); - state->y[0] = (a/d)*(state->u[0]) - + (b/d)*(state->u[1]) - + (c/d)*(state->u[2]) - - (e/d)*(state->y[1]) - - (f/d)*(state->y[2]); - - state->u[2] = state->u[1]; - state->u[1] = state->u[0]; - state->y[2] = state->y[1]; - state->y[1] = state->y[0]; - buffer[i] = static_cast< audio_sample_t >((state->y[0] * 0.5f) + 0.5f); - } -} - void dsp_dcRemoval(filter_state_t *state, audio_sample_t *buffer, size_t length) { /* diff --git a/openrtx/src/protocols/M17/M17Modulator.cpp b/openrtx/src/protocols/M17/M17Modulator.cpp index 7fa6fb96..4c93b7a3 100644 --- a/openrtx/src/protocols/M17/M17Modulator.cpp +++ b/openrtx/src/protocols/M17/M17Modulator.cpp @@ -54,7 +54,7 @@ void M17Modulator::init() idleBuffer = baseband_buffer.get(); txRunning = false; #if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0) - dsp_resetFilterState(&pwmFilterState); + pwmComp.reset(); #endif } @@ -147,7 +147,7 @@ void M17Modulator::stop() idleBuffer = baseband_buffer.get(); #if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0) - dsp_resetFilterState(&pwmFilterState); + pwmComp.reset(); #endif } @@ -164,13 +164,12 @@ void M17Modulator::symbolsToBaseband() { float elem = static_cast< float >(idleBuffer[i]); elem = M17::rrc_48k(elem * M17_RRC_GAIN) - M17_RRC_OFFSET; + #if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0) + elem = pwmComp(elem); + elem *= -1.0f; // Invert signal phase + #endif idleBuffer[i] = static_cast< int16_t >(elem); } - - #if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0) - dsp_pwmCompensate(&pwmFilterState, idleBuffer, M17_FRAME_SAMPLES); - dsp_invertPhase(idleBuffer, M17_FRAME_SAMPLES); - #endif } #ifndef PLATFORM_LINUX