Skip to content

Commit a152bd3

Browse files
committed
add .num_keys and .store_states() to Keys and KeyMatrix
1 parent cd31136 commit a152bd3

File tree

9 files changed

+170
-43
lines changed

9 files changed

+170
-43
lines changed

locale/circuitpython.pot

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ msgstr ""
8383
msgid "%q indices must be integers, not %s"
8484
msgstr ""
8585

86+
#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c
87+
msgid "%q length must be %q"
88+
msgstr ""
89+
8690
#: shared-bindings/vectorio/Polygon.c
8791
msgid "%q list must be a list"
8892
msgstr ""
@@ -120,6 +124,10 @@ msgstr ""
120124
msgid "%q must be a tuple of length 2"
121125
msgstr ""
122126

127+
#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c
128+
msgid "%q must store bytes"
129+
msgstr ""
130+
123131
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
124132
#: shared-bindings/canio/Match.c shared-bindings/keypad/KeyMatrix.c
125133
#: shared-bindings/keypad/Keys.c

shared-bindings/keypad/KeyMatrix.c

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626

2727
#include "lib/utils/context_manager_helpers.h"
28+
#include "py/binary.h"
2829
#include "py/objproperty.h"
2930
#include "py/runtime.h"
3031
#include "shared-bindings/keypad/Event.h"
@@ -136,6 +137,47 @@ STATIC void check_for_deinit(keypad_keymatrix_obj_t *self) {
136137
}
137138
}
138139

140+
//| num_keys: int
141+
//| """The number of keys that are being scanned. (read-only)
142+
//| """
143+
//|
144+
STATIC mp_obj_t keypad_keymatrix_get_num_keys(mp_obj_t self_in) {
145+
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
146+
return MP_OBJ_NEW_SMALL_INT(common_hal_keypad_keymatrix_get_num_keys(self));
147+
}
148+
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keymatrix_get_num_keys_obj, keypad_keymatrix_get_num_keys);
149+
150+
const mp_obj_property_t keypad_keymatrix_num_keys_obj = {
151+
.base.type = &mp_type_property,
152+
.proxy = {(mp_obj_t)&keypad_keymatrix_get_num_keys_obj,
153+
MP_ROM_NONE,
154+
MP_ROM_NONE},
155+
};
156+
157+
//| def key_num(self, row: int, col: int) -> int:
158+
//| """Return the key number for a given row and column.
159+
//| The key number is calculated by ``row * len(col_pins) + col``.
160+
//| """
161+
//| ...
162+
//|
163+
STATIC mp_obj_t keypad_keymatrix_key_num(mp_obj_t self_in, mp_obj_t row_in, mp_obj_t col_in) {
164+
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
165+
check_for_deinit(self);
166+
167+
const mp_int_t row = mp_obj_get_int(row_in);
168+
if (row < 0 || (size_t)row >= common_hal_keypad_keymatrix_get_num_rows(self)) {
169+
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_row_num);
170+
}
171+
172+
const mp_int_t col = mp_obj_get_int(col_in);
173+
if (col < 0 || (size_t)col >= common_hal_keypad_keymatrix_get_num_cols(self)) {
174+
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_col_num);
175+
}
176+
177+
return MP_OBJ_NEW_SMALL_INT(
178+
(mp_int_t)common_hal_keypad_keymatrix_key_num(self, (mp_uint_t)row, (mp_uint_t)col));
179+
}
180+
MP_DEFINE_CONST_FUN_OBJ_3(keypad_keymatrix_key_num_obj, keypad_keymatrix_key_num);
139181

140182
//| def pressed(self, key_num: int) -> None:
141183
//| """Return ``True`` if the given key is pressed. This is a debounced read
@@ -148,38 +190,40 @@ STATIC mp_obj_t keypad_keymatrix_pressed(mp_obj_t self_in, mp_obj_t key_num_in)
148190
check_for_deinit(self);
149191

150192
mp_int_t key_num = mp_obj_get_int(key_num_in);
151-
if (key_num < 0 || (size_t)key_num >= common_hal_keypad_keymatrix_num_keys(self)) {
193+
if (key_num < 0 || (size_t)key_num >= common_hal_keypad_keymatrix_get_num_keys(self)) {
152194
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_key_num);
153195
}
154196

155197
return mp_obj_new_bool(common_hal_keypad_keymatrix_pressed(self, (mp_uint_t)key_num));
156198
}
157199
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keymatrix_pressed_obj, keypad_keymatrix_pressed);
158200

159-
//| def key_num(self, row: int, col: int) -> int:
160-
//| """Return the key number for a given row and column.
161-
//| The key number is calculated by ``row * len(col_pins) + col``.
201+
//| def store_states(self, states: _typing.WriteableBuffer) -> None:
202+
//| """Write the state of all the keys into ``states``.
203+
//| Write a ``1`` if pressed, and ``0`` if released.
204+
//| The ``length`` of ``states`` must be `num_keys`.
205+
//| This is a debounced read of the state of all the keys, and bypasses the `events` `EventQueue`.
206+
//| The read is done atomically.
162207
//| """
163208
//| ...
164209
//|
165-
STATIC mp_obj_t keypad_keymatrix_key_num(mp_obj_t self_in, mp_obj_t row_in, mp_obj_t col_in) {
210+
STATIC mp_obj_t keypad_keymatrix_store_states(mp_obj_t self_in, mp_obj_t pressed) {
166211
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
167212
check_for_deinit(self);
168213

169-
const mp_int_t row = mp_obj_get_int(row_in);
170-
if (row < 0 || (size_t)row >= common_hal_keypad_keymatrix_num_rows(self)) {
171-
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_row_num);
214+
mp_buffer_info_t bufinfo;
215+
mp_get_buffer_raise(pressed, &bufinfo, MP_BUFFER_WRITE);
216+
if (bufinfo.typecode != 'b' && bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE) {
217+
mp_raise_ValueError_varg(translate("%q must store bytes"), MP_QSTR_states);
172218
}
173-
174-
const mp_int_t col = mp_obj_get_int(col_in);
175-
if (col < 0 || (size_t)col >= common_hal_keypad_keymatrix_num_cols(self)) {
176-
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_col_num);
219+
if (bufinfo.len != common_hal_keypad_keymatrix_get_num_keys(self)) {
220+
mp_raise_ValueError_varg(translate("%q length must be %q"), MP_QSTR_states, MP_QSTR_num_keys);
177221
}
178222

179-
return MP_OBJ_NEW_SMALL_INT(
180-
(mp_int_t)common_hal_keypad_keymatrix_key_num(self, (mp_uint_t)row, (mp_uint_t)col));
223+
common_hal_keypad_keymatrix_store_states(self, (uint8_t *)bufinfo.buf);
224+
return MP_ROM_NONE;
181225
}
182-
MP_DEFINE_CONST_FUN_OBJ_3(keypad_keymatrix_key_num_obj, keypad_keymatrix_key_num);
226+
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keymatrix_store_states_obj, keypad_keymatrix_store_states);
183227

184228
//| events: EventQueue
185229
//| """The `EventQueue` associated with this `Keys` object. (read-only)
@@ -199,13 +243,15 @@ const mp_obj_property_t keypad_keymatrix_events_obj = {
199243
};
200244

201245
STATIC const mp_rom_map_elem_t keypad_keymatrix_locals_dict_table[] = {
202-
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keymatrix_deinit_obj) },
203-
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
204-
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keymatrix___exit___obj) },
246+
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keymatrix_deinit_obj) },
247+
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
248+
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keymatrix___exit___obj) },
205249

206250
{ MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_keymatrix_events_obj) },
207251
{ MP_ROM_QSTR(MP_QSTR_key_num), MP_ROM_PTR(&keypad_keymatrix_key_num_obj) },
252+
{ MP_ROM_QSTR(MP_QSTR_num_keys), MP_ROM_PTR(&keypad_keymatrix_num_keys_obj) },
208253
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_keymatrix_pressed_obj) },
254+
{ MP_ROM_QSTR(MP_QSTR_store_states), MP_ROM_PTR(&keypad_keymatrix_store_states_obj) },
209255
};
210256

211257
STATIC MP_DEFINE_CONST_DICT(keypad_keymatrix_locals_dict, keypad_keymatrix_locals_dict_table);

shared-bindings/keypad/KeyMatrix.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ bool common_hal_keypad_keymatrix_deinited(keypad_keymatrix_obj_t *self);
3939

4040
mp_uint_t common_hal_keypad_keymatrix_key_num(keypad_keymatrix_obj_t *self, mp_uint_t row, mp_uint_t col);
4141

42-
mp_uint_t common_hal_keypad_keymatrix_num_keys(keypad_keymatrix_obj_t *self);
43-
mp_uint_t common_hal_keypad_keymatrix_num_cols(keypad_keymatrix_obj_t *self);
44-
mp_uint_t common_hal_keypad_keymatrix_num_rows(keypad_keymatrix_obj_t *self);
42+
mp_uint_t common_hal_keypad_keymatrix_get_num_keys(keypad_keymatrix_obj_t *self);
43+
mp_uint_t common_hal_keypad_keymatrix_get_num_cols(keypad_keymatrix_obj_t *self);
44+
mp_uint_t common_hal_keypad_keymatrix_get_num_rows(keypad_keymatrix_obj_t *self);
4545

4646
mp_obj_t common_hal_keypad_keymatrix_get_events(keypad_keymatrix_obj_t *self);
4747
bool common_hal_keypad_keymatrix_pressed(keypad_keymatrix_obj_t *self, mp_uint_t key_num);
48+
void common_hal_keypad_keymatrix_store_states(keypad_keymatrix_obj_t *self, uint8_t *states);
4849

4950
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYMATRIX_H

shared-bindings/keypad/Keys.c

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626

2727
#include "lib/utils/context_manager_helpers.h"
28+
#include "py/binary.h"
2829
#include "py/objproperty.h"
2930
#include "py/runtime.h"
3031
#include "shared-bindings/keypad/Event.h"
@@ -135,9 +136,26 @@ STATIC void check_for_deinit(keypad_keys_obj_t *self) {
135136
}
136137
}
137138

139+
//| num_keys: int
140+
//| """The number of keys that are being scanned. (read-only)
141+
//| """
142+
//|
143+
STATIC mp_obj_t keypad_keys_get_num_keys(mp_obj_t self_in) {
144+
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
145+
return MP_OBJ_NEW_SMALL_INT(common_hal_keypad_keys_get_num_keys(self));
146+
}
147+
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_get_num_keys_obj, keypad_keys_get_num_keys);
148+
149+
const mp_obj_property_t keypad_keys_num_keys_obj = {
150+
.base.type = &mp_type_property,
151+
.proxy = {(mp_obj_t)&keypad_keys_get_num_keys_obj,
152+
MP_ROM_NONE,
153+
MP_ROM_NONE},
154+
};
155+
138156
//| def pressed(self, key_num: int) -> None:
139-
//| """Return ``True`` if the given key is pressed. This is a debounced read
140-
//| of the key state which bypasses the `events` `EventQueue`.
157+
//| """Return ``True`` if the given key is pressed.
158+
// This is a debounced read of the key state which bypasses the `events` `EventQueue`.
141159
//| """
142160
//| ...
143161
//|
@@ -146,14 +164,41 @@ STATIC mp_obj_t keypad_keys_pressed(mp_obj_t self_in, mp_obj_t key_num_in) {
146164
check_for_deinit(self);
147165

148166
mp_int_t key_num = mp_obj_get_int(key_num_in);
149-
if (key_num < 0 || (size_t)key_num >= common_hal_keypad_keys_num_keys(self)) {
167+
if (key_num < 0 || (size_t)key_num >= common_hal_keypad_keys_get_num_keys(self)) {
150168
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_key_num);
151169
}
152170

153171
return mp_obj_new_bool(common_hal_keypad_keys_pressed(self, (mp_uint_t)key_num));
154172
}
155173
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keys_pressed_obj, keypad_keys_pressed);
156174

175+
//| def store_states(self, states: _typing.WriteableBuffer) -> None:
176+
//| """Write the states of all the keys into ``states``.
177+
//| Write a ``1`` if pressed, and ``0`` if released.
178+
//| The ``length`` of ``states`` must be `num_keys`.
179+
//| This is a debounced read of the state of all the keys, and bypasses the `events` `EventQueue`.
180+
//| The read is done atomically.
181+
//| """
182+
//| ...
183+
//|
184+
STATIC mp_obj_t keypad_keys_store_states(mp_obj_t self_in, mp_obj_t pressed) {
185+
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
186+
check_for_deinit(self);
187+
188+
mp_buffer_info_t bufinfo;
189+
mp_get_buffer_raise(pressed, &bufinfo, MP_BUFFER_WRITE);
190+
if (bufinfo.typecode != 'b' && bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE) {
191+
mp_raise_ValueError_varg(translate("%q must store bytes"), MP_QSTR_pressed);
192+
}
193+
if (bufinfo.len != common_hal_keypad_keys_get_num_keys(self)) {
194+
mp_raise_ValueError_varg(translate("%q length must be %q"), MP_QSTR_pressed, MP_QSTR_num_keys);
195+
}
196+
197+
common_hal_keypad_keys_store_states(self, (uint8_t *)bufinfo.buf);
198+
return MP_ROM_NONE;
199+
}
200+
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keys_store_states_obj, keypad_keys_store_states);
201+
157202
//| events: EventQueue
158203
//| """The `EventQueue` associated with this `Keys` object. (read-only)
159204
//| """
@@ -172,12 +217,14 @@ const mp_obj_property_t keypad_keys_events_obj = {
172217
};
173218

174219
STATIC const mp_rom_map_elem_t keypad_keys_locals_dict_table[] = {
175-
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keys_deinit_obj) },
176-
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
177-
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keys___exit___obj) },
178-
179-
{ MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_keys_events_obj) },
180-
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_keys_pressed_obj) },
220+
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keys_deinit_obj) },
221+
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
222+
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keys___exit___obj) },
223+
224+
{ MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_keys_events_obj) },
225+
{ MP_ROM_QSTR(MP_QSTR_num_keys), MP_ROM_PTR(&keypad_keys_num_keys_obj) },
226+
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_keys_pressed_obj) },
227+
{ MP_ROM_QSTR(MP_QSTR_store_states), MP_ROM_PTR(&keypad_keys_store_states_obj) },
181228
};
182229

183230
STATIC MP_DEFINE_CONST_DICT(keypad_keys_locals_dict, keypad_keys_locals_dict_table);

shared-bindings/keypad/Keys.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ void common_hal_keypad_keys_deinit(keypad_keys_obj_t *self);
3838
bool common_hal_keypad_keys_deinited(keypad_keys_obj_t *self);
3939

4040
mp_obj_t common_hal_keypad_keys_get_events(keypad_keys_obj_t *self);
41-
mp_uint_t common_hal_keypad_keys_num_keys(keypad_keys_obj_t *self);
41+
mp_uint_t common_hal_keypad_keys_get_num_keys(keypad_keys_obj_t *self);
4242
bool common_hal_keypad_keys_pressed(keypad_keys_obj_t *self, mp_uint_t key_num);
43+
void common_hal_keypad_keys_store_states(keypad_keys_obj_t *self, uint8_t *states);
4344

4445
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYS_H

shared-module/keypad/KeyMatrix.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
#include <string.h>
28+
2729
#include "py/gc.h"
2830
#include "py/runtime.h"
2931
#include "shared-bindings/digitalio/DigitalInOut.h"
@@ -84,12 +86,12 @@ void common_hal_keypad_keymatrix_deinit(keypad_keymatrix_obj_t *self) {
8486
// Remove self from the list of active keypad scanners first.
8587
keypad_deregister_scanner((keypad_scanner_obj_t *)self);
8688

87-
for (size_t row = 0; row < common_hal_keypad_keymatrix_num_rows(self); row++) {
89+
for (size_t row = 0; row < common_hal_keypad_keymatrix_get_num_rows(self); row++) {
8890
common_hal_digitalio_digitalinout_deinit(self->row_digitalinouts->items[row]);
8991
}
9092
self->row_digitalinouts = MP_ROM_NONE;
9193

92-
for (size_t col = 0; col < common_hal_keypad_keymatrix_num_cols(self); col++) {
94+
for (size_t col = 0; col < common_hal_keypad_keymatrix_get_num_cols(self); col++) {
9395
common_hal_digitalio_digitalinout_deinit(self->col_digitalinouts->items[col]);
9496
}
9597
self->col_digitalinouts = MP_ROM_NONE;
@@ -99,21 +101,30 @@ bool common_hal_keypad_keymatrix_deinited(keypad_keymatrix_obj_t *self) {
99101
return self->row_digitalinouts == MP_ROM_NONE;
100102
}
101103

102-
size_t common_hal_keypad_keymatrix_num_keys(keypad_keymatrix_obj_t *self) {
103-
return common_hal_keypad_keymatrix_num_rows(self) * common_hal_keypad_keymatrix_num_cols(self);
104+
size_t common_hal_keypad_keymatrix_get_num_keys(keypad_keymatrix_obj_t *self) {
105+
return common_hal_keypad_keymatrix_get_num_rows(self) * common_hal_keypad_keymatrix_get_num_cols(self);
104106
}
105107

106-
size_t common_hal_keypad_keymatrix_num_rows(keypad_keymatrix_obj_t *self) {
108+
size_t common_hal_keypad_keymatrix_get_num_rows(keypad_keymatrix_obj_t *self) {
107109
return self->row_digitalinouts->len;
108110
}
109111

110-
size_t common_hal_keypad_keymatrix_num_cols(keypad_keymatrix_obj_t *self) {
112+
size_t common_hal_keypad_keymatrix_get_num_cols(keypad_keymatrix_obj_t *self) {
111113
return self->col_digitalinouts->len;
112114
}
113115

114116
bool common_hal_keypad_keymatrix_pressed(keypad_keymatrix_obj_t *self, mp_uint_t key_num) {
115117
return self->currently_pressed[key_num];
116118
}
119+
120+
// The length of states has already been validated.
121+
void common_hal_keypad_keymatrix_store_states(keypad_keymatrix_obj_t *self, uint8_t *states) {
122+
// Read the state atomically.
123+
supervisor_acquire_lock(&keypad_scanners_linked_list_lock);
124+
memcpy(states, self->currently_pressed, common_hal_keypad_keymatrix_get_num_keys(self));
125+
supervisor_release_lock(&keypad_scanners_linked_list_lock);
126+
}
127+
117128
mp_uint_t common_hal_keypad_keymatrix_key_num(keypad_keymatrix_obj_t *self, mp_uint_t row, mp_uint_t col) {
118129
return row_col_to_key_num(self, row, col);
119130
}
@@ -132,12 +143,12 @@ void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self) {
132143
self->last_scan_ticks = now;
133144

134145
// On entry, all pins are set to inputs with a pull-up.
135-
for (size_t row = 0; row < common_hal_keypad_keymatrix_num_rows(self); row++) {
146+
for (size_t row = 0; row < common_hal_keypad_keymatrix_get_num_rows(self); row++) {
136147
// Switch this row to an output and set to low.
137148
common_hal_digitalio_digitalinout_switch_to_output(
138149
self->row_digitalinouts->items[row], false, DRIVE_MODE_PUSH_PULL);
139150

140-
for (size_t col = 0; col < common_hal_keypad_keymatrix_num_cols(self); col++) {
151+
for (size_t col = 0; col < common_hal_keypad_keymatrix_get_num_cols(self); col++) {
141152
mp_uint_t key_num = row_col_to_key_num(self, row, col);
142153
const bool previous = self->currently_pressed[key_num];
143154
self->previously_pressed[key_num] = previous;

0 commit comments

Comments
 (0)