-
Notifications
You must be signed in to change notification settings - Fork 1
/
ZordButton.h
154 lines (121 loc) · 3.78 KB
/
ZordButton.h
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* ZordButton by sonik-br
*
* Button class:
* MUST call begin() one time.
* Debounces a button state.
*
* ArcadePad class:
* MUST call begin() one time.
* Can instantiate and handle multiple Button instances.
*
* Arduino's digitalRead() seems to be fast enough for button reading.
* It's also possible to modify the code and use direct port access.
* Tested with DigitalIO and FastGPIO libs.
*
* Credits:
* Debounce and held/timertick from
* https://github.com/sakabug/Bugtton
*
*/
#ifndef ZORDBUTTON_H
#define ZORDBUTTON_H
class Button {
private:
const uint8_t pin_n;
bool finalState;
uint32_t updateMillis;
//debounce
uint8_t debounceTime;
bool currentState;
bool debouncedState;
bool stateChanged;
uint32_t buttonMillis;
//stateDuration()
uint32_t debouncedAt;
void configurePin() const { pinMode(pin_n, INPUT_PULLUP); }
bool getPinState() const { return digitalRead(pin_n); }
bool debounce() {
if((debouncedState != currentState) && (updateMillis - buttonMillis) > debounceTime) {
debouncedState = currentState;
debouncedAt = updateMillis;
buttonMillis = updateMillis;
return true;
}
return false;
}
public:
Button(const uint8_t pin) : pin_n(pin) { };
void begin(const uint8_t time) {
configurePin(); //configure pin as INPUT_PULLUP
updateMillis = millis();
finalState = HIGH;
//debounce
stateChanged = false;
currentState = HIGH;
debouncedState = HIGH;
debounceTime = time;
buttonMillis = updateMillis;
//stateDuration()
debouncedAt = updateMillis;
}
bool update() {
stateChanged = false;
updateMillis = millis();
currentState = getPinState();
if(debounce() && finalState != currentState) {
stateChanged = true;
finalState = currentState;
debouncedAt = updateMillis;
}
return stateChanged;
}
bool state() const { return finalState; }
bool fell() const { return stateChanged && !finalState; }
bool rose() const { return stateChanged && finalState; }
uint32_t stateDuration() const { return millis() - debouncedAt; }
}; //end class Buton
class ArcadePad {
private:
Button** _pins;
const uint8_t _count;
const uint8_t _interval;
public:
ArcadePad(const uint8_t count, const uint8_t* buttons, const uint8_t interval) :
_pins(new Button*[count]),
_count(count),
_interval(interval)
{
for(uint8_t i = 0; i < _count; ++i)
_pins[i] = new Button(buttons[i]);
}
void begin() const {
for(uint8_t i = 0; i < _count; ++i)
_pins[i]->begin(_interval);
}
bool update() {
bool stateChanged = false;
//const bool turboTick = isTurboTick();
for(uint8_t i = 0; i < _count; ++i) {
if(_pins[i]->update())
stateChanged = true;
}
return stateChanged;
}
bool state(const uint8_t i) const { return _pins[i]->state(); }
bool fell(const uint8_t i) const { return _pins[i]->fell(); }
bool rose(const uint8_t i) const { return _pins[i]->rose(); }
}; //end class ArcadePad
#endif
//direct pin access using DigitalIO
//#include <DigitalIO.h>
//DigitalPin<tpin> pin;
//virtual void configurePin() override { pin.config (INPUT, HIGH); }
//virtual bool getPinState() override { return pin == HIGH; }
//direct pin access using https://github.com/pololu/fastgpio-arduino
//#include <FastGPIO.h>
//FastGPIO::Pin<tpin> pin;
//virtual void configurePin() override { pin.setInputPulledUp(); }
//virtual bool getPinState() override { return pin.isInputHigh(); }
//protected:
// virtual void configurePin() = 0;
// virtual bool getPinState() = 0;