#pragma once #include #include #include #include #include #include #include BEGIN_CS_NAMESPACE template class GenericMIDIAbsoluteEncoder : public MIDIOutputElement { public: GenericMIDIAbsoluteEncoder(Enc &&encoder, MIDIAddress address, int16_t speedMultiply, uint8_t pulsesPerStep, const Sender &sender) : encoder(std::forward(encoder)), address(address), encstate(speedMultiply, pulsesPerStep), sender(sender) {} void begin() override { begin_if_possible(encoder); } void update() override { auto encval = encoder.read(); if (int16_t delta = encstate.update(encval)) { int16_t oldValue = value; int16_t newValue = oldValue + delta; newValue = constrain(newValue, 0, maxValue); if (oldValue != newValue) { value = newValue; forcedUpdate(); } } } void forcedUpdate() { sender.send(value, address); } uint16_t getValue() const { return value; } void setValue(uint16_t value) { this->value = value; } static int16_t getMaxValue() { return maxValue; } void setSpeedMultiply(int16_t speedMultiply) { encstate.setSpeedMultiply(speedMultiply); } int16_t getSpeedMultiply() const { return encstate.getSpeedMultiply(); } MIDIAddress getAddress() const { return this->address; } void setAddress(MIDIAddress address) { this->address = address; } int16_t resetPositionOffset() { auto encval = encoder.read(); return encstate.update(encval); } private: Enc encoder; MIDIAddress address; int16_t value = 0; EncoderState encstate; constexpr static int16_t maxValue = uint16_t(1u << Sender::precision()) - 1; public: Sender sender; }; template using MIDIAbsoluteEncoder = GenericMIDIAbsoluteEncoder; template using BorrowedMIDIAbsoluteEncoder = GenericMIDIAbsoluteEncoder; END_CS_NAMESPACE