LCOV - code coverage report
Current view: top level - src/MIDI_Outputs/Abstract - MIDIAbsoluteEncoder.hpp (source / functions) Hit Total Coverage
Test: ffed98f648fe78e7aa7bdd228474317d40dadbec Lines: 16 17 94.1 %
Date: 2022-05-28 15:22:59 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             : AH_DIAGNOSTIC_WERROR()
      17             : 
      18             : BEGIN_CS_NAMESPACE
      19             : 
      20             : /**
      21             :  * @brief   An abstract class for rotary encoders that send absolute MIDI 
      22             :  *          events.
      23             :  */
      24             : template <class Enc, class Sender>
      25             : class GenericMIDIAbsoluteEncoder : public MIDIOutputElement {
      26             :   public:
      27           1 :     GenericMIDIAbsoluteEncoder(Enc &&encoder, MIDIAddress address,
      28             :                                int16_t speedMultiply, uint8_t pulsesPerStep,
      29             :                                const Sender &sender)
      30           1 :         : encoder(std::forward<Enc>(encoder)), address(address),
      31           2 :           encstate(speedMultiply, pulsesPerStep), sender(sender) {}
      32             : 
      33           0 :     void begin() override { begin_if_possible(encoder); }
      34             : 
      35           1 :     void update() override {
      36           1 :         auto encval = encoder.read();
      37           1 :         if (int16_t delta = encstate.update(encval)) {
      38           1 :             int16_t oldValue = value;
      39           1 :             int16_t newValue = oldValue + delta;
      40           1 :             newValue = constrain(newValue, 0, maxValue);
      41           1 :             if (oldValue != newValue) {
      42           1 :                 value = newValue;
      43           1 :                 forcedUpdate();
      44             :             }
      45             :         }
      46           1 :     }
      47             : 
      48             :     /// Send the current value over MIDI, even if the position of the encoder
      49             :     /// didn't change.
      50           1 :     void forcedUpdate() { sender.send(value, address); }
      51             : 
      52             :     /**
      53             :      * @brief   Get the absolute value of the encoder.
      54             :      */
      55           1 :     uint16_t getValue() const { return value; }
      56             : 
      57             :     /**
      58             :      * @brief   Set the absolute value of the encoder.
      59             :      */
      60           1 :     void setValue(uint16_t value) { this->value = value; }
      61             : 
      62             :     /// Get the maximum possible value that can be returned by @ref getValue.
      63             :     static int16_t getMaxValue() { return maxValue; }
      64             : 
      65             :     void setSpeedMultiply(int16_t speedMultiply) {
      66             :         encstate.setSpeedMultiply(speedMultiply);
      67             :     }
      68             :     int16_t getSpeedMultiply() const { return encstate.getSpeedMultiply(); }
      69             : 
      70             :     /// Get the MIDI address.
      71             :     MIDIAddress getAddress() const { return this->address; }
      72             :     /// Set the MIDI address.
      73             :     void setAddress(MIDIAddress address) { this->address = address; }
      74             : 
      75             :   private:
      76             :     Enc encoder;
      77             :     MIDIAddress address;
      78             :     int16_t value = 0;
      79             :     EncoderState<decltype(encoder.read())> encstate;
      80             : 
      81             :     constexpr static int16_t maxValue = uint16_t(1u << Sender::precision()) - 1;
      82             : 
      83             :   public:
      84             :     Sender sender;
      85             : };
      86             : 
      87             : template <class Sender>
      88             : using MIDIAbsoluteEncoder = GenericMIDIAbsoluteEncoder<AHEncoder, Sender>;
      89             : 
      90             : template <class Sender>
      91             : using BorrowedMIDIAbsoluteEncoder =
      92             :     GenericMIDIAbsoluteEncoder<AHEncoder &, Sender>;
      93             : 
      94             : END_CS_NAMESPACE
      95             : 
      96             : AH_DIAGNOSTIC_POP()

Generated by: LCOV version 1.15