LCOV - code coverage report
Current view: top level - src/AH/Filters - Hysteresis.hpp (source / functions) Coverage Total Hit
Test: 73449d9b107c772cf65493691543348214e5d5eb Lines: 100.0 % 15 15
Test Date: 2026-06-06 17:44:35 Functions: 100.0 % 16 16
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta