Line data Source code
1 : #pragma once 2 : 3 : #include <AH/Settings/Warnings.hpp> 4 : AH_DIAGNOSTIC_WERROR() // Enable errors on warnings 5 : 6 : #include <stdint.h> 7 : 8 : /// @addtogroup AH_Filters 9 : /// @{ 10 : 11 : /** 12 : * @brief A class for applying hysteresis to a given input. 13 : * 14 : * This reduces the noise by decreasing the resolution, and it prevents flipping 15 : * back and forth between two values. 16 : * 17 : * <b>An example for `BITS` = 7 and an input from 0 to 1023</b> 18 : * ``` 19 : * 7 ┌───◄───┬─── 20 : * o 6 ┌───◄───┼───►───┘ 21 : * u 5 ┌───◄───┼───►───┘ 22 : * t 4 ┌───◄───┼───►───┘ 23 : * p 3 ┌───◄───┼───►───┘ 24 : * u 2 ┌───◄───┼───►───┘ 25 : * t 1 ┌───◄───┼───►───┘ 26 : * 0 ────┴───►───┘ 27 : * 0 128 256 384 512 640 768 896 1023 28 : * i n p u t 29 : * ``` 30 : * 31 : * @tparam BITS 32 : * The number of bits to decrease in resolution. 33 : * Increasing this number will result in a decrease in fluctuations. 34 : */ 35 : template <uint8_t BITS, class T_in = uint16_t, class T_out = uint8_t> 36 17 : class Hysteresis { 37 : public: 38 : /** 39 : * @brief Update the hysteresis output with a new input value. 40 : * 41 : * @param inputLevel 42 : * The input to calculate the output level from. 43 : * @retval true 44 : * The output level has changed. 45 : * @retval false 46 : * The output level is still the same. 47 : */ 48 94 : bool update(T_in inputLevel) { 49 94 : T_in prevLevelFull = (T_in(prevLevel) << BITS) | offset; 50 94 : T_in lowerbound = prevLevel > 0 ? prevLevelFull - margin : 0; 51 94 : T_in upperbound = prevLevel < max_out ? prevLevelFull + margin : max_in; 52 94 : if (inputLevel < lowerbound || inputLevel > upperbound) { 53 40 : prevLevel = inputLevel >> BITS; 54 40 : return true; 55 : } 56 54 : return false; 57 94 : } 58 : 59 : /** 60 : * @brief Get the current output level. 61 : * 62 : * @return The output level. 63 : */ 64 94 : T_out getValue() const { return prevLevel; } 65 : 66 : private: 67 17 : T_out prevLevel = 0; 68 : constexpr static T_in margin = (1UL << BITS) - 1; 69 : constexpr static T_in offset = 1UL << (BITS - 1); 70 : constexpr static T_in max_in = -1; 71 : constexpr static T_out max_out = static_cast<T_out>(max_in >> BITS); 72 : static_assert(max_in > 0, "Error: only unsigned types are supported"); 73 : }; 74 : 75 : /// @} 76 : 77 : AH_DIAGNOSTIC_POP()