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
|