LCOV - code coverage report
Current view: top level - src/MIDI_Outputs/Bankable/Abstract - MIDIAbsoluteEncoder.hpp (source / functions) Hit Total Coverage
Test: 169c36a3797bc662d84b5726f34a3f37d3c58247 Lines: 3 19 15.8 %
Date: 2024-11-09 15:32:27 Functions: 4 16 25.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <AH/STL/utility> // std::forward
       4             : #include <Banks/BankableAddresses.hpp>
       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             : namespace Bankable {
      19             : 
      20             : /**
      21             :  * @brief   An abstract class for rotary encoders that send absolute MIDI 
      22             :  *          events.
      23             :  */
      24             : template <class Enc, uint8_t NumBanks, class BankAddress, class Sender>
      25             : class GenericMIDIAbsoluteEncoder : public MIDIOutputElement {
      26             :   public:
      27           4 :     GenericMIDIAbsoluteEncoder(const BankAddress &address, Enc &&encoder,
      28             :                                int16_t speedMultiply, uint8_t pulsesPerStep,
      29             :                                const Sender &sender)
      30           4 :         : encoder(std::forward<Enc>(encoder)), address(address),
      31           8 :           encstate(speedMultiply, pulsesPerStep), sender(sender) {}
      32             : 
      33           0 :     void begin() override { begin_if_possible(encoder); }
      34             : 
      35           0 :     void update() override {
      36           0 :         auto encval = encoder.read();
      37           0 :         if (int16_t delta = encstate.update(encval)) {
      38           0 :             address.lock();
      39           0 :             int16_t oldValue = values[address.getSelection()];
      40           0 :             int16_t newValue = oldValue + delta;
      41           0 :             newValue = constrain(newValue, 0, maxValue);
      42           0 :             if (oldValue != newValue) {
      43           0 :                 values[address.getSelection()] = newValue;
      44           0 :                 forcedUpdate();
      45             :             }
      46           0 :             address.unlock();
      47             :         }
      48           0 :     }
      49             : 
      50             :     /// Send the current value over MIDI, even if the position of the encoder
      51             :     /// didn't change.
      52           0 :     void forcedUpdate() {
      53           0 :         sender.send(values[address.getSelection()], address.getActiveAddress());
      54           0 :     }
      55             :     void forcedUpdate(setting_t bank) {
      56             :         sender.send(values[bank], address.getActiveAddress(bank));
      57             :     }
      58             : 
      59             :     /**
      60             :      * @brief   Get the absolute value of the encoder in the given bank.
      61             :      */
      62             :     uint16_t getValue(setting_t bank) const { return values[bank]; }
      63             :     /**
      64             :      * @brief   Get the absolute value of the encoder in the active bank.
      65             :      */
      66             :     uint16_t getValue() const { return getValue(address.getSelection()); }
      67             : 
      68             :     /**
      69             :      * @brief   Set the absolute value of the encoder in the given bank.
      70             :      */
      71             :     void setValue(uint16_t value, setting_t bank) { values[bank] = value; }
      72             :     /**
      73             :      * @brief   Set the absolute value of the encoder in the active bank.
      74             :      */
      75             :     void setValue(uint16_t value) { setValue(value, address.getSelection()); }
      76             : 
      77             :     /// Get the maximum possible value that can be returned by @ref getValue.
      78             :     static int16_t getMaxValue() { return maxValue; }
      79             : 
      80             :     void setSpeedMultiply(int16_t speedMultiply) {
      81             :         encstate.setSpeedMultiply(speedMultiply);
      82             :     }
      83             :     int16_t getSpeedMultiply() const { return encstate.getSpeedMultiply(); }
      84             : 
      85             :     int16_t resetPositionOffset() {
      86             :         auto encval = encoder.read();
      87             :         return encstate.update(encval);
      88             :     }
      89             : 
      90             :   protected:
      91             :     Enc encoder;
      92             :     BankAddress address;
      93             :     Array<int16_t, NumBanks> values = {{}};
      94             :     EncoderState<decltype(encoder.read())> encstate;
      95             : 
      96             :     constexpr static int16_t maxValue = uint16_t(1u << Sender::precision()) - 1;
      97             : 
      98             :   public:
      99             :     Sender sender;
     100             : };
     101             : 
     102             : template <uint8_t NumBanks, class BankAddress, class Sender>
     103             : using MIDIAbsoluteEncoder =
     104             :     GenericMIDIAbsoluteEncoder<AHEncoder, NumBanks, BankAddress, Sender>;
     105             : 
     106             : template <uint8_t NumBanks, class BankAddress, class Sender>
     107             : using BorrowedMIDIAbsoluteEncoder =
     108             :     GenericMIDIAbsoluteEncoder<AHEncoder &, NumBanks, BankAddress, Sender>;
     109             : 
     110             : } // namespace Bankable
     111             : 
     112             : END_CS_NAMESPACE

Generated by: LCOV version 1.15