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