-
Notifications
You must be signed in to change notification settings - Fork 0
/
keypadBlocking.h
249 lines (222 loc) · 10.3 KB
/
keypadBlocking.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/**
* @file KeypadBlocking.h
* @author Aditya Agarwal ([email protected])
*
* @brief Simple Library to use a 4x4 Keypad sensor with MBed OS
*
* @copyright Copyright (c) 2023
*
*/
#ifndef __KEYPADBLOCKING_H__
#define __KEYPADBLOCKING_H__
#include "keypad.h"
/**
* @brief Class that provides a simple interface to use a 4x4 keypad
*
* @remark At a time, only a single button on the keypad can be pressed, pressing multiple buttons
* at the same time will only cause the earliest to be accepted, while all others are rejected
*/
class KeypadBlocking {
/**
* @brief Structure to encapsulate the coordinates of a button
*
*/
struct button_coord {
/** Row */
uint32_t r;
/** Column */
uint32_t c;
};
/** Keypad instance that is internally used */
Keypad keypad;
/** Ordered list of coordinates of buttons that were pressed */
CircularBuffer<button_coord, KEYPAD_BUFFER_LEN> pressBuf;
/** Ordered list of coordinates of buttons that were released */
CircularBuffer<button_coord, KEYPAD_BUFFER_LEN> releaseBuf;
/** Ordered list of coordinates of buttons that were long-pressed */
CircularBuffer<button_coord, KEYPAD_BUFFER_LEN> longpressBuf;
Mutex pressMutex;
Mutex releaseMutex;
Mutex longpressMutex;
public:
/**
* @brief Construct a new KeypadBlocking object
*
* @param r0 Microcontroller Pin to which Row Pin 0 of the keypad is connected
* @param r1 Microcontroller Pin to which Row Pin 1 of the keypad is connected
* @param r2 Microcontroller Pin to which Row Pin 2 of the keypad is connected
* @param r3 Microcontroller Pin to which Row Pin 3 of the keypad is connected
* @param c0 Microcontroller Pin to which Column Pin 0 of the keypad is connected
* @param c1 Microcontroller Pin to which Column Pin 1 of the keypad is connected
* @param c2 Microcontroller Pin to which Column Pin 2 of the keypad is connected
* @param c3 Microcontroller Pin to which Column Pin 3 of the keypad is connected
*
*/
KeypadBlocking(PinName r0, PinName r1, PinName r2, PinName r3, PinName c0, PinName c1, PinName c2, PinName c3);
/**
* @brief Initializes the internal keypad object (See Keypad::initialize())
*
* @remark This method must be called before the object can start recording keypad events
* @remark If the thread was already initialized, then the KeypadBlocking::finalize() method must be called
* before trying to initialize it again
*
* @attention Can not call this method from ISR context
* @attention It is unsafe to call this method from multiple threads concurrently
*
* @return true if the object could be initialized, false otherwise
*
*/
bool initialize();
/**
* @brief Finalizes the internal HCSR04 object (see HCSR04::finalize())
*
* @remark After calling this method, the object can not measure keypad events
* @remark If the thread was not initialized or previously finalized, then the KeypadBlocking::initialize() method must be called
* before trying to finalize it again
* @remark Any unconsumed events (presses, releases, long-presses) are preserved after calling this method
*
* @attention Can not call this method from ISR context
* @attention It is unsafe to call this method from multiple threads concurrently
*
* @return true if the object could be finalized, false otherwise
*
*/
bool finalize();
/**
* @brief Checks if the object was initialized and callbacks can be dispatched correctly
*
* @attention This function can be called from ISR context
*
* @return true if the thread is running, false otherwise
*
*/
bool is_initialized() const;
/**
* @brief Checks the number of unconsumed button presses
*
* @attention This function can be called from ISR context
*
* @return Number of button presses have not been popped yet
*
*/
uint32_t press_available() const;
/**
* @brief Checks the number of unconsumed button releases
*
* @attention This function can be called from ISR context
*
* @return Number of button releases have not been popped yet
*
*/
uint32_t release_available() const;
/**
* @brief Checks the number of unconsumed button long-presses
*
* @attention This function can be called from ISR context
*
* @return Number of button long-presses have not been popped yet
*
*/
uint32_t longpress_available() const;
/**
* @brief Returns the earliest unconsumed press without removing it from the internal buffer
*
* @attention This function can be called from ISR context
*
* @param rptr Location of variable where the row should be stored (only used if a button press was available)
* @param cptr Location of variable where the column should be stored (only used if a button press was available)
*
* @return true if a button press was available to peek, false otherwise
*
*/
bool peek_press(uint32_t *rptr, uint32_t *cptr) const;
/**
* @brief Returns the earliest unconsumed press and removes it from the internal buffer
*
* @attention This function can be called from ISR context
* @attention It is not safe to call this method from multiple threads concurrently
*
* @param rptr Location of variable where the row should be stored (only used if a button press was available)
* @param cptr Location of variable where the column should be stored (only used if a button press was available)
*
* @return true if a button press was available to pop, false otherwise
*
*/
bool pop_press();
/**
* @brief Returns the earliest unconsumed release without removing it from the internal buffer
*
* @attention This function can be called from ISR context
*
* @param rptr Location of variable where the row should be stored (only used if a button press was available)
* @param cptr Location of variable where the column should be stored (only used if a button press was available)
*
* @return true if a button release was available to peek, false otherwise
*
*/
bool peek_release(uint32_t *rptr, uint32_t *cptr) const;
/**
* @brief Returns the earliest unconsumed release and removes it from the internal buffer
*
* @attention This function can be called from ISR context
* @attention It is not safe to call this method from multiple threads concurrently
*
* @param rptr Location of variable where the row should be stored (only used if a button press was available)
* @param cptr Location of variable where the column should be stored (only used if a button press was available)
*
* @return true if a button release was available to pop, false otherwise
*
*/
bool pop_release();
/**
* @brief Returns the earliest unconsumed long-press without removing it from the internal buffer
*
* @attention This function can be called from ISR context
*
* @param rptr Location of variable where the row should be stored (only used if a button press was available)
* @param cptr Location of variable where the column should be stored (only used if a button press was available)
*
* @return true if a long-press was available to peek, false otherwise
*
*/
bool peek_longpress(uint32_t *rptr, uint32_t *cptr) const;
/**
* @brief Returns the earliest unconsumed long-press and removes it from the internal buffer
*
* @attention This function can be called from ISR context
* @attention It is not safe to call this method from multiple threads concurrently
*
* @param rptr Location of variable where the row should be stored (only used if a button press was available)
* @param cptr Location of variable where the column should be stored (only used if a button press was available)
*
* @return true if a button long-press was available to pop, false otherwise
*
*/
bool pop_longpress();
private:
/**
* @brief Adds presses to the internal buffer (used as a callback by the internal keypad object)
*
* @param r Row of the button that was pressed
* @param c Column of the button that was released
*
*/
void push_press(uint32_t r, uint32_t c);
/**
* @brief Adds releases to the internal buffer (used as a callback by the internal keypad object)
*
* @param r Row of the button that was released
* @param c Column of the button that was released
*
*/
void push_release(uint32_t r, uint32_t c);
/**
* @brief Adds long-presses to the internal buffer (used as a callback by the internal keypad object)
*
* @param r Row of the button that was long-pressed
* @param c Column of the button that was long-pressed
*
*/
void push_longpress(uint32_t r, uint32_t c);
};
#endif //__KEYPADBLOCKING_H__