LCOV - code coverage report
Current view: top level - src/MIDI_Outputs/Abstract - EncoderState.hpp (source / functions) Hit Total Coverage
Test: 169c36a3797bc662d84b5726f34a3f37d3c58247 Lines: 12 12 100.0 %
Date: 2024-11-09 15:32:27 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <AH/STL/type_traits>
       4             : #include <Settings/NamespaceSettings.hpp>
       5             : #include <stdint.h>
       6             : 
       7             : BEGIN_CS_NAMESPACE
       8             : 
       9             : /// Class to keep track of relative position changes of rotary encoders.
      10             : template <class Enc_t>
      11             : class EncoderState {
      12             :   private:
      13             :     using SignedEnc_t = typename std::make_signed<Enc_t>::type;
      14             :     int16_t speedMultiply;
      15             :     uint8_t pulsesPerStep;
      16             :     int16_t remainder = 0;
      17             :     Enc_t deltaOffset = 0;
      18             : 
      19             :   public:
      20          21 :     EncoderState(int16_t speedMultiply, uint8_t pulsesPerStep)
      21          21 :         : speedMultiply(speedMultiply), pulsesPerStep(pulsesPerStep) {}
      22             : 
      23          35 :     int16_t update(Enc_t encval) {
      24             :         // If Enc_t is an unsigned type, integer overflow is well-defined, which
      25             :         // is what we want when Enc_t is small and expected to overflow.
      26             :         // However, we need it to be signed because we're interested in the
      27             :         // delta.
      28          35 :         Enc_t uDelta = encval - deltaOffset;
      29          35 :         if (uDelta == 0)
      30           2 :             return 0;
      31          33 :         int16_t delta = static_cast<SignedEnc_t>(uDelta);
      32             :         // Assumption: delta and speedMultiply are relatively small, so
      33             :         // multiplication probably won't overflow.
      34          33 :         int16_t multipliedDelta = delta * speedMultiply + remainder;
      35          33 :         int16_t scaledDelta = multipliedDelta / pulsesPerStep;
      36          33 :         remainder = multipliedDelta % pulsesPerStep;
      37          33 :         deltaOffset += uDelta;
      38          33 :         return scaledDelta;
      39             :     }
      40             :     void setSpeedMultiply(int16_t speedMultiply) {
      41             :         // TODO: Is this correct? Is it necessary? What with negative speedMult?
      42             :         remainder = remainder * speedMultiply / this->speedMultiply;
      43             :         this->speedMultiply = speedMultiply;
      44             :     }
      45             :     int16_t getSpeedMultiply() const { return this->speedMultiply; }
      46             : };
      47             : 
      48             : END_CS_NAMESPACE

Generated by: LCOV version 1.15