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