-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsystem.cpp
141 lines (120 loc) · 4.44 KB
/
system.cpp
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
// ========================================
// INCLUDES
// ========================================
#include "system.h"
// ========================================
// MACROS
// ========================================
#define BUTTON_COUNT 3
#define CLICK_TIMEOUT_MS 200
#define ENTER_HOLD_MS 300
#define REPEAT_HOLD_MS 100
// ========================================
// TYPES
// ========================================
enum ButtonDetectionState {
BUTTON_STATE_IDLE,
BUTTON_STATE_PRESSED,
BUTTON_STATE_HOLD,
BUTTON_STATE_SINGLE_CLICK,
BUTTON_STATE_SINGLE_CLICK_THEN_PRESSED,
};
struct ButtonDetectionHandler {
ButtonDetectionState state;
long lastEventTime;
uint8_t input;
bool doubleClickEnabled;
};
// ========================================
// PROTOTYPES
// ========================================
// ========================================
// GLOBALS
// ========================================
Pocuter* pocuter;
double dt;
uint8_t lastButtonState;
ButtonDetectionHandler buttonHandler[BUTTON_COUNT];
// ========================================
// FUNCTIONS
// ========================================
void enableDoubleClick(int bt) {
if (0 <= bt && bt < BUTTON_COUNT)
buttonHandler[bt].doubleClickEnabled = true;
}
void disableDoubleClick(int bt) {
if (0 <= bt && bt < BUTTON_COUNT)
buttonHandler[bt].doubleClickEnabled = false;
}
void updateInput() {
long ms = millis();
uint8_t currentButtonState = pocuter->Buttons->getButtonState();
for (int i = 0; i < BUTTON_COUNT; i++) {
ButtonDetectionHandler *handler = &buttonHandler[i];
bool currentState = currentButtonState & (1 << i);
bool lastState = lastButtonState & (1 << i);
bool pressed = !lastState && currentState;
bool released = lastState && !currentState;
handler->input = 0;
ButtonDetectionState newState = handler->state;
switch (handler->state) {
default:
case BUTTON_STATE_IDLE:
if (pressed)
newState = BUTTON_STATE_PRESSED;
break;
case BUTTON_STATE_PRESSED:
if (released) {
if (!handler->doubleClickEnabled) {
handler->input = SINGLE_CLICK;
newState = BUTTON_STATE_IDLE;
} else
newState = BUTTON_STATE_SINGLE_CLICK;
} else {
if (ms - handler->lastEventTime > ENTER_HOLD_MS) {
handler->input = HOLD;
newState = BUTTON_STATE_HOLD;
}
}
break;
case BUTTON_STATE_HOLD:
if (released) {
if (!handler->doubleClickEnabled) {
handler->input = SINGLE_CLICK;
newState = BUTTON_STATE_IDLE;
} else
newState = BUTTON_STATE_SINGLE_CLICK;
} else {
if (ms - handler->lastEventTime > REPEAT_HOLD_MS) {
handler->input = HOLD;
}
}
break;
case BUTTON_STATE_SINGLE_CLICK:
if (pressed)
newState = BUTTON_STATE_SINGLE_CLICK_THEN_PRESSED;
if (ms - handler->lastEventTime > CLICK_TIMEOUT_MS) {
handler->input = SINGLE_CLICK;
newState = BUTTON_STATE_IDLE;
}
break;
case BUTTON_STATE_SINGLE_CLICK_THEN_PRESSED:
if (released) {
handler->input = DOUBLE_CLICK;
newState = BUTTON_STATE_IDLE;
}
break;
}
if (handler->state != newState || handler->input != 0)
handler->lastEventTime = millis();
handler->state = newState;
if (handler->state == BUTTON_STATE_PRESSED || handler->state == BUTTON_STATE_HOLD || handler->state == BUTTON_STATE_SINGLE_CLICK_THEN_PRESSED)
handler->input |= PRESSED_CONT;
}
lastButtonState = currentButtonState;
}
uint8_t getInput(int bt) {
if (0 <= bt && bt < BUTTON_COUNT)
return buttonHandler[bt].input;
return 0;
}