Line data Source code
1 : #pragma once 2 : 3 : #if !defined(Encoder_h_) && !defined(IDE) 4 : #error \ 5 : "The PJRC Encoder library should be included before the Control-Surface \ 6 : library. (#include <Encoder.h>)" 7 : #endif 8 : 9 : #include "Selector.hpp" 10 : #include <AH/Hardware/ExtendedInputOutput/ExtendedInputOutput.hpp> 11 : #include <Def/Def.hpp> 12 : 13 : BEGIN_CS_NAMESPACE 14 : 15 : template <setting_t N, class Callback = EmptySelectorCallback> 16 2 : class GenericEncoderSelector : public GenericSelector<N, Callback> { 17 : using Parent = GenericSelector<N, Callback>; 18 : 19 : public: 20 2 : GenericEncoderSelector(Selectable<N> &selectable, const Callback &callback, 21 : const EncoderSwitchPinList &pins, 22 : int8_t pulsesPerStep = 4, Wrap wrap = Wrap::Wrap) 23 6 : : GenericSelector<N, Callback>{selectable, callback}, encoder{pins.A, 24 2 : pins.B}, 25 4 : switchPin{pins.switchPin}, pulsesPerStep{pulsesPerStep}, wrap{wrap} {} 26 : 27 0 : void begin() override { 28 0 : Parent::begin(); 29 0 : if (switchPin != NO_PIN) 30 0 : AH::ExtIO::pinMode(switchPin, INPUT_PULLUP); 31 0 : } 32 : 33 0 : void update() override { 34 0 : Parent::update(); 35 0 : long currentPosition = encoder.read(); 36 0 : long difference = (currentPosition - previousPosition) / pulsesPerStep; 37 0 : if (difference) { 38 0 : previousPosition += difference * pulsesPerStep; 39 0 : if (difference > 0) 40 0 : while (difference-- > 0) 41 0 : this->increment(wrap); 42 : else 43 0 : while (difference++ < 0) 44 0 : this->decrement(wrap); 45 0 : } 46 : 47 0 : if (switchPin != NO_PIN) { 48 0 : bool currentState = AH::ExtIO::digitalRead(switchPin); 49 0 : if (previousSwitchState == HIGH && currentState == LOW) { 50 : // TODO: invert? 51 0 : this->reset(); 52 0 : } 53 0 : previousSwitchState = currentState; 54 0 : } 55 0 : } 56 : 57 : private: 58 : Encoder encoder; 59 : pin_t switchPin; 60 : int8_t pulsesPerStep; 61 : Wrap wrap; 62 : 63 2 : long previousPosition = 0; 64 2 : bool previousSwitchState = HIGH; 65 : }; 66 : 67 : // -------------------------------------------------------------------------- // 68 : 69 : /** 70 : * @brief Selector that reads from a rotary encoder. 71 : * 72 : * @ingroup Selectors 73 : * 74 : * @tparam N 75 : * The number of settings. 76 : */ 77 : template <setting_t N> 78 1 : class EncoderSelector : public GenericEncoderSelector<N> { 79 : public: 80 1 : EncoderSelector(Selectable<N> &selectable, const EncoderSwitchPinList &pins, 81 : int8_t pulsesPerStep = 4, Wrap wrap = Wrap::Wrap) 82 1 : : GenericEncoderSelector<N>{ 83 1 : selectable, {}, pins, pulsesPerStep, wrap, 84 2 : } {} 85 : }; 86 : 87 : END_CS_NAMESPACE