LCOV - code coverage report
Current view: top level - src/MIDI_Outputs/Bankable/Abstract - MIDIAbsoluteEncoder.hpp (source / functions) Coverage Total Hit
Test: 73449d9b107c772cf65493691543348214e5d5eb Lines: 15.8 % 19 3
Test Date: 2026-06-06 17:44:35 Functions: 25.0 % 16 4
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 2.4-beta