1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#include "RotaryEncoder.h"
#if SUPPORT_12864_LCD
#include "Pins.h"
#include "IoPorts.h"
RotaryEncoder::RotaryEncoder(Pin p0, Pin p1, Pin pb)
: pin0(p0), pin1(p1), pinButton(pb), ppc(1), encoderChange(0), encoderState(0), newPress(false), reverseDirection(false) {}
inline unsigned int RotaryEncoder::ReadEncoderState() const
{
return (digitalRead(pin0) ? 1u : 0u) | (digitalRead(pin1) ? 2u : 0u);
}
void RotaryEncoder::Init(int pulsesPerClick)
{
ppc = max<unsigned int>(abs(pulsesPerClick), 1);
reverseDirection = (pulsesPerClick < 0);
// Set up pins
IoPort::SetPinMode(pin0, INPUT_PULLUP);
IoPort::SetPinMode(pin1, INPUT_PULLUP);
IoPort::SetPinMode(pinButton, INPUT_PULLUP);
delay(2); // ensure we read the initial state correctly
// Initialise encoder variables
encoderChange = 0;
encoderState = ReadEncoderState();
// Initialise button variables
buttonState = !digitalRead(pinButton);
whenSame = millis();
newPress = false;
}
void RotaryEncoder::Poll()
{
// State transition table. Each entry has the following meaning:
// 0 - the encoder hasn't moved
// 1 or 2 - the encoder has moved 1 or 2 units clockwise
// -1 or -2 = the encoder has moved 1 or 2 units anticlockwise
static const int tbl[16] =
{
0, +1, -1, 0, // position 3 = 00 to 11, can't really do anything, so 0
-1, 0, -2, +1, // position 2 = 01 to 10, assume it was a bounce and should be 01 -> 00 -> 10
+1, +2, 0, -1, // position 1 = 10 to 01, assume it was a bounce and should be 10 -> 00 -> 01
0, -1, +1, 0 // position 0 = 11 to 10, can't really do anything
};
// Poll the encoder
const unsigned int t = ReadEncoderState();
const int movement = tbl[(encoderState << 2) | t];
if (movement != 0)
{
encoderChange += movement;
encoderState = t;
}
// Poll the button
const uint32_t now = millis();
const bool b = !digitalRead(pinButton);
if (b == buttonState)
{
whenSame = now;
}
else if (now - whenSame > DebounceMillis)
{
buttonState = b;
whenSame = now;
if (buttonState)
{
newPress = true;
}
}
}
int RotaryEncoder::GetChange()
{
int r;
if (encoderChange >= ppc - 1)
{
r = (encoderChange + 1)/ppc;
}
else if (encoderChange <= 1 - ppc)
{
r = -((1 - encoderChange)/ppc);
}
else
{
r = 0;
}
encoderChange -= (r * ppc);
return (reverseDirection) ? -r : r;
}
bool RotaryEncoder::GetButtonPress()
{
const bool ret = newPress;
newPress = false;
return ret;
}
#endif
// End
|