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