LCOV - code coverage report
Current view: top level - src/MIDI_Outputs/Abstract - MIDIAbsoluteEncoder.hpp (source / functions) Hit Total Coverage
Test: 3a807a259ebe0769dd942f7f612dca5273937539 Lines: 16 17 94.1 %
Date: 2024-03-24 17:16:54 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <AH/STL/type_traits> // std::make_signed
       4             : #include <AH/STL/utility>     // std::forward
       5             : #include <Def/Def.hpp>
       6             : #include <Def/TypeTraits.hpp>
       7             : #include <MIDI_Outputs/Abstract/EncoderState.hpp>
       8             : #include <MIDI_Outputs/Abstract/MIDIOutputElement.hpp>
       9             : 
      10             : #ifdef ARDUINO
      11             : #include <Submodules/Encoder/AHEncoder.hpp>
      12             : #else
      13             : #include <Encoder.h> // Mock
      14             : #endif
      15             : 
      16             : BEGIN_CS_NAMESPACE
      17             : 
      18             : /**
      19             :  * @brief   An abstract class for rotary encoders that send absolute MIDI 
      20             :  *          events.
      21             :  */
      22             : template <class Enc, class Sender>
      23             : class GenericMIDIAbsoluteEncoder : public MIDIOutputElement {
      24             :   public:
      25           1 :     GenericMIDIAbsoluteEncoder(Enc &&encoder, MIDIAddress address,
      26             :                                int16_t speedMultiply, uint8_t pulsesPerStep,
      27             :                                const Sender &sender)
      28           1 :         : encoder(std::forward<Enc>(encoder)), address(address),
      29           2 :           encstate(speedMultiply, pulsesPerStep), sender(sender) {}
      30             : 
      31           0 :     void begin() override { begin_if_possible(encoder); }
      32             : 
      33           1 :     void update() override {
      34           1 :         auto encval = encoder.read();
      35           1 :         if (int16_t delta = encstate.update(encval)) {
      36           1 :             int16_t oldValue = value;
      37           1 :             int16_t newValue = oldValue + delta;
      38           1 :             newValue = constrain(newValue, 0, maxValue);
      39           1 :             if (oldValue != newValue) {
      40           1 :                 value = newValue;
      41           1 :                 forcedUpdate();
      42             :             }
      43             :         }
      44           1 :     }
      45             : 
      46             :     /// Send the current value over MIDI, even if the position of the encoder
      47             :     /// didn't change.
      48           1 :     void forcedUpdate() { sender.send(value, address); }
      49             : 
      50             :     /**
      51             :      * @brief   Get the absolute value of the encoder.
      52             :      */
      53           1 :     uint16_t getValue() const { return value; }
      54             : 
      55             :     /**
      56             :      * @brief   Set the absolute value of the encoder.
      57             :      */
      58           1 :     void setValue(uint16_t value) { this->value = value; }
      59             : 
      60             :     /// Get the maximum possible value that can be returned by @ref getValue.
      61             :     static int16_t getMaxValue() { return maxValue; }
      62             : 
      63             :     void setSpeedMultiply(int16_t speedMultiply) {
      64             :         encstate.setSpeedMultiply(speedMultiply);
      65             :     }
      66             :     int16_t getSpeedMultiply() const { return encstate.getSpeedMultiply(); }
      67             : 
      68             :     /// Get the MIDI address.
      69             :     MIDIAddress getAddress() const { return this->address; }
      70             :     /// Set the MIDI address.
      71             :     void setAddress(MIDIAddress address) { this->address = address; }
      72             : 
      73             :     int16_t resetPositionOffset() {
      74             :         auto encval = encoder.read();
      75             :         return encstate.update(encval);
      76             :     }
      77             : 
      78             :   private:
      79             :     Enc encoder;
      80             :     MIDIAddress address;
      81             :     int16_t value = 0;
      82             :     EncoderState<decltype(encoder.read())> encstate;
      83             : 
      84             :     constexpr static int16_t maxValue = uint16_t(1u << Sender::precision()) - 1;
      85             : 
      86             :   public:
      87             :     Sender sender;
      88             : };
      89             : 
      90             : template <class Sender>
      91             : using MIDIAbsoluteEncoder = GenericMIDIAbsoluteEncoder<AHEncoder, Sender>;
      92             : 
      93             : template <class Sender>
      94             : using BorrowedMIDIAbsoluteEncoder =
      95             :     GenericMIDIAbsoluteEncoder<AHEncoder &, Sender>;
      96             : 
      97             : END_CS_NAMESPACE

Generated by: LCOV version 1.15