add .num_keys and .store_states() to Keys and KeyMatrix

This commit is contained in:
Dan Halbert 2021-06-17 12:02:54 -04:00
parent cd31136c30
commit a152bd3b72
9 changed files with 172 additions and 45 deletions

View File

@ -83,6 +83,10 @@ msgstr ""
msgid "%q indices must be integers, not %s"
msgstr ""
#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c
msgid "%q length must be %q"
msgstr ""
#: shared-bindings/vectorio/Polygon.c
msgid "%q list must be a list"
msgstr ""
@ -120,6 +124,10 @@ msgstr ""
msgid "%q must be a tuple of length 2"
msgstr ""
#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c
msgid "%q must store bytes"
msgstr ""
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#: shared-bindings/canio/Match.c shared-bindings/keypad/KeyMatrix.c
#: shared-bindings/keypad/Keys.c

View File

@ -25,6 +25,7 @@
*/
#include "lib/utils/context_manager_helpers.h"
#include "py/binary.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "shared-bindings/keypad/Event.h"
@ -136,25 +137,22 @@ STATIC void check_for_deinit(keypad_keymatrix_obj_t *self) {
}
}
//| def pressed(self, key_num: int) -> None:
//| """Return ``True`` if the given key is pressed. This is a debounced read
//| of the key state which bypasses the `events` `EventQueue`.
//| """
//| ...
//| num_keys: int
//| """The number of keys that are being scanned. (read-only)
//| """
//|
STATIC mp_obj_t keypad_keymatrix_pressed(mp_obj_t self_in, mp_obj_t key_num_in) {
STATIC mp_obj_t keypad_keymatrix_get_num_keys(mp_obj_t self_in) {
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
mp_int_t key_num = mp_obj_get_int(key_num_in);
if (key_num < 0 || (size_t)key_num >= common_hal_keypad_keymatrix_num_keys(self)) {
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_key_num);
}
return mp_obj_new_bool(common_hal_keypad_keymatrix_pressed(self, (mp_uint_t)key_num));
return MP_OBJ_NEW_SMALL_INT(common_hal_keypad_keymatrix_get_num_keys(self));
}
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keymatrix_pressed_obj, keypad_keymatrix_pressed);
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keymatrix_get_num_keys_obj, keypad_keymatrix_get_num_keys);
const mp_obj_property_t keypad_keymatrix_num_keys_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&keypad_keymatrix_get_num_keys_obj,
MP_ROM_NONE,
MP_ROM_NONE},
};
//| def key_num(self, row: int, col: int) -> int:
//| """Return the key number for a given row and column.
@ -167,12 +165,12 @@ STATIC mp_obj_t keypad_keymatrix_key_num(mp_obj_t self_in, mp_obj_t row_in, mp_o
check_for_deinit(self);
const mp_int_t row = mp_obj_get_int(row_in);
if (row < 0 || (size_t)row >= common_hal_keypad_keymatrix_num_rows(self)) {
if (row < 0 || (size_t)row >= common_hal_keypad_keymatrix_get_num_rows(self)) {
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_row_num);
}
const mp_int_t col = mp_obj_get_int(col_in);
if (col < 0 || (size_t)col >= common_hal_keypad_keymatrix_num_cols(self)) {
if (col < 0 || (size_t)col >= common_hal_keypad_keymatrix_get_num_cols(self)) {
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_col_num);
}
@ -181,6 +179,52 @@ STATIC mp_obj_t keypad_keymatrix_key_num(mp_obj_t self_in, mp_obj_t row_in, mp_o
}
MP_DEFINE_CONST_FUN_OBJ_3(keypad_keymatrix_key_num_obj, keypad_keymatrix_key_num);
//| def pressed(self, key_num: int) -> None:
//| """Return ``True`` if the given key is pressed. This is a debounced read
//| of the key state which bypasses the `events` `EventQueue`.
//| """
//| ...
//|
STATIC mp_obj_t keypad_keymatrix_pressed(mp_obj_t self_in, mp_obj_t key_num_in) {
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
mp_int_t key_num = mp_obj_get_int(key_num_in);
if (key_num < 0 || (size_t)key_num >= common_hal_keypad_keymatrix_get_num_keys(self)) {
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_key_num);
}
return mp_obj_new_bool(common_hal_keypad_keymatrix_pressed(self, (mp_uint_t)key_num));
}
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keymatrix_pressed_obj, keypad_keymatrix_pressed);
//| def store_states(self, states: _typing.WriteableBuffer) -> None:
//| """Write the state of all the keys into ``states``.
//| Write a ``1`` if pressed, and ``0`` if released.
//| The ``length`` of ``states`` must be `num_keys`.
//| This is a debounced read of the state of all the keys, and bypasses the `events` `EventQueue`.
//| The read is done atomically.
//| """
//| ...
//|
STATIC mp_obj_t keypad_keymatrix_store_states(mp_obj_t self_in, mp_obj_t pressed) {
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(pressed, &bufinfo, MP_BUFFER_WRITE);
if (bufinfo.typecode != 'b' && bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE) {
mp_raise_ValueError_varg(translate("%q must store bytes"), MP_QSTR_states);
}
if (bufinfo.len != common_hal_keypad_keymatrix_get_num_keys(self)) {
mp_raise_ValueError_varg(translate("%q length must be %q"), MP_QSTR_states, MP_QSTR_num_keys);
}
common_hal_keypad_keymatrix_store_states(self, (uint8_t *)bufinfo.buf);
return MP_ROM_NONE;
}
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keymatrix_store_states_obj, keypad_keymatrix_store_states);
//| events: EventQueue
//| """The `EventQueue` associated with this `Keys` object. (read-only)
//| """
@ -199,13 +243,15 @@ const mp_obj_property_t keypad_keymatrix_events_obj = {
};
STATIC const mp_rom_map_elem_t keypad_keymatrix_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keymatrix_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keymatrix___exit___obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keymatrix_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keymatrix___exit___obj) },
{ MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_keymatrix_events_obj) },
{ MP_ROM_QSTR(MP_QSTR_key_num), MP_ROM_PTR(&keypad_keymatrix_key_num_obj) },
{ MP_ROM_QSTR(MP_QSTR_num_keys), MP_ROM_PTR(&keypad_keymatrix_num_keys_obj) },
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_keymatrix_pressed_obj) },
{ MP_ROM_QSTR(MP_QSTR_store_states), MP_ROM_PTR(&keypad_keymatrix_store_states_obj) },
};
STATIC MP_DEFINE_CONST_DICT(keypad_keymatrix_locals_dict, keypad_keymatrix_locals_dict_table);

View File

@ -39,11 +39,12 @@ bool common_hal_keypad_keymatrix_deinited(keypad_keymatrix_obj_t *self);
mp_uint_t common_hal_keypad_keymatrix_key_num(keypad_keymatrix_obj_t *self, mp_uint_t row, mp_uint_t col);
mp_uint_t common_hal_keypad_keymatrix_num_keys(keypad_keymatrix_obj_t *self);
mp_uint_t common_hal_keypad_keymatrix_num_cols(keypad_keymatrix_obj_t *self);
mp_uint_t common_hal_keypad_keymatrix_num_rows(keypad_keymatrix_obj_t *self);
mp_uint_t common_hal_keypad_keymatrix_get_num_keys(keypad_keymatrix_obj_t *self);
mp_uint_t common_hal_keypad_keymatrix_get_num_cols(keypad_keymatrix_obj_t *self);
mp_uint_t common_hal_keypad_keymatrix_get_num_rows(keypad_keymatrix_obj_t *self);
mp_obj_t common_hal_keypad_keymatrix_get_events(keypad_keymatrix_obj_t *self);
bool common_hal_keypad_keymatrix_pressed(keypad_keymatrix_obj_t *self, mp_uint_t key_num);
void common_hal_keypad_keymatrix_store_states(keypad_keymatrix_obj_t *self, uint8_t *states);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYMATRIX_H

View File

@ -25,6 +25,7 @@
*/
#include "lib/utils/context_manager_helpers.h"
#include "py/binary.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "shared-bindings/keypad/Event.h"
@ -135,9 +136,26 @@ STATIC void check_for_deinit(keypad_keys_obj_t *self) {
}
}
//| num_keys: int
//| """The number of keys that are being scanned. (read-only)
//| """
//|
STATIC mp_obj_t keypad_keys_get_num_keys(mp_obj_t self_in) {
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(common_hal_keypad_keys_get_num_keys(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_get_num_keys_obj, keypad_keys_get_num_keys);
const mp_obj_property_t keypad_keys_num_keys_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&keypad_keys_get_num_keys_obj,
MP_ROM_NONE,
MP_ROM_NONE},
};
//| def pressed(self, key_num: int) -> None:
//| """Return ``True`` if the given key is pressed. This is a debounced read
//| of the key state which bypasses the `events` `EventQueue`.
//| """Return ``True`` if the given key is pressed.
// This is a debounced read of the key state which bypasses the `events` `EventQueue`.
//| """
//| ...
//|
@ -146,7 +164,7 @@ STATIC mp_obj_t keypad_keys_pressed(mp_obj_t self_in, mp_obj_t key_num_in) {
check_for_deinit(self);
mp_int_t key_num = mp_obj_get_int(key_num_in);
if (key_num < 0 || (size_t)key_num >= common_hal_keypad_keys_num_keys(self)) {
if (key_num < 0 || (size_t)key_num >= common_hal_keypad_keys_get_num_keys(self)) {
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_key_num);
}
@ -154,6 +172,33 @@ STATIC mp_obj_t keypad_keys_pressed(mp_obj_t self_in, mp_obj_t key_num_in) {
}
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keys_pressed_obj, keypad_keys_pressed);
//| def store_states(self, states: _typing.WriteableBuffer) -> None:
//| """Write the states of all the keys into ``states``.
//| Write a ``1`` if pressed, and ``0`` if released.
//| The ``length`` of ``states`` must be `num_keys`.
//| This is a debounced read of the state of all the keys, and bypasses the `events` `EventQueue`.
//| The read is done atomically.
//| """
//| ...
//|
STATIC mp_obj_t keypad_keys_store_states(mp_obj_t self_in, mp_obj_t pressed) {
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(pressed, &bufinfo, MP_BUFFER_WRITE);
if (bufinfo.typecode != 'b' && bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE) {
mp_raise_ValueError_varg(translate("%q must store bytes"), MP_QSTR_pressed);
}
if (bufinfo.len != common_hal_keypad_keys_get_num_keys(self)) {
mp_raise_ValueError_varg(translate("%q length must be %q"), MP_QSTR_pressed, MP_QSTR_num_keys);
}
common_hal_keypad_keys_store_states(self, (uint8_t *)bufinfo.buf);
return MP_ROM_NONE;
}
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keys_store_states_obj, keypad_keys_store_states);
//| events: EventQueue
//| """The `EventQueue` associated with this `Keys` object. (read-only)
//| """
@ -172,12 +217,14 @@ const mp_obj_property_t keypad_keys_events_obj = {
};
STATIC const mp_rom_map_elem_t keypad_keys_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keys_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keys___exit___obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keys_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keys___exit___obj) },
{ MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_keys_events_obj) },
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_keys_pressed_obj) },
{ MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_keys_events_obj) },
{ MP_ROM_QSTR(MP_QSTR_num_keys), MP_ROM_PTR(&keypad_keys_num_keys_obj) },
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_keys_pressed_obj) },
{ MP_ROM_QSTR(MP_QSTR_store_states), MP_ROM_PTR(&keypad_keys_store_states_obj) },
};
STATIC MP_DEFINE_CONST_DICT(keypad_keys_locals_dict, keypad_keys_locals_dict_table);

View File

@ -38,7 +38,8 @@ void common_hal_keypad_keys_deinit(keypad_keys_obj_t *self);
bool common_hal_keypad_keys_deinited(keypad_keys_obj_t *self);
mp_obj_t common_hal_keypad_keys_get_events(keypad_keys_obj_t *self);
mp_uint_t common_hal_keypad_keys_num_keys(keypad_keys_obj_t *self);
mp_uint_t common_hal_keypad_keys_get_num_keys(keypad_keys_obj_t *self);
bool common_hal_keypad_keys_pressed(keypad_keys_obj_t *self, mp_uint_t key_num);
void common_hal_keypad_keys_store_states(keypad_keys_obj_t *self, uint8_t *states);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYS_H

View File

@ -24,6 +24,8 @@
* THE SOFTWARE.
*/
#include <string.h>
#include "py/gc.h"
#include "py/runtime.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
@ -84,12 +86,12 @@ void common_hal_keypad_keymatrix_deinit(keypad_keymatrix_obj_t *self) {
// Remove self from the list of active keypad scanners first.
keypad_deregister_scanner((keypad_scanner_obj_t *)self);
for (size_t row = 0; row < common_hal_keypad_keymatrix_num_rows(self); row++) {
for (size_t row = 0; row < common_hal_keypad_keymatrix_get_num_rows(self); row++) {
common_hal_digitalio_digitalinout_deinit(self->row_digitalinouts->items[row]);
}
self->row_digitalinouts = MP_ROM_NONE;
for (size_t col = 0; col < common_hal_keypad_keymatrix_num_cols(self); col++) {
for (size_t col = 0; col < common_hal_keypad_keymatrix_get_num_cols(self); col++) {
common_hal_digitalio_digitalinout_deinit(self->col_digitalinouts->items[col]);
}
self->col_digitalinouts = MP_ROM_NONE;
@ -99,21 +101,30 @@ bool common_hal_keypad_keymatrix_deinited(keypad_keymatrix_obj_t *self) {
return self->row_digitalinouts == MP_ROM_NONE;
}
size_t common_hal_keypad_keymatrix_num_keys(keypad_keymatrix_obj_t *self) {
return common_hal_keypad_keymatrix_num_rows(self) * common_hal_keypad_keymatrix_num_cols(self);
size_t common_hal_keypad_keymatrix_get_num_keys(keypad_keymatrix_obj_t *self) {
return common_hal_keypad_keymatrix_get_num_rows(self) * common_hal_keypad_keymatrix_get_num_cols(self);
}
size_t common_hal_keypad_keymatrix_num_rows(keypad_keymatrix_obj_t *self) {
size_t common_hal_keypad_keymatrix_get_num_rows(keypad_keymatrix_obj_t *self) {
return self->row_digitalinouts->len;
}
size_t common_hal_keypad_keymatrix_num_cols(keypad_keymatrix_obj_t *self) {
size_t common_hal_keypad_keymatrix_get_num_cols(keypad_keymatrix_obj_t *self) {
return self->col_digitalinouts->len;
}
bool common_hal_keypad_keymatrix_pressed(keypad_keymatrix_obj_t *self, mp_uint_t key_num) {
return self->currently_pressed[key_num];
}
// The length of states has already been validated.
void common_hal_keypad_keymatrix_store_states(keypad_keymatrix_obj_t *self, uint8_t *states) {
// Read the state atomically.
supervisor_acquire_lock(&keypad_scanners_linked_list_lock);
memcpy(states, self->currently_pressed, common_hal_keypad_keymatrix_get_num_keys(self));
supervisor_release_lock(&keypad_scanners_linked_list_lock);
}
mp_uint_t common_hal_keypad_keymatrix_key_num(keypad_keymatrix_obj_t *self, mp_uint_t row, mp_uint_t col) {
return row_col_to_key_num(self, row, col);
}
@ -132,12 +143,12 @@ void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self) {
self->last_scan_ticks = now;
// On entry, all pins are set to inputs with a pull-up.
for (size_t row = 0; row < common_hal_keypad_keymatrix_num_rows(self); row++) {
for (size_t row = 0; row < common_hal_keypad_keymatrix_get_num_rows(self); row++) {
// Switch this row to an output and set to low.
common_hal_digitalio_digitalinout_switch_to_output(
self->row_digitalinouts->items[row], false, DRIVE_MODE_PUSH_PULL);
for (size_t col = 0; col < common_hal_keypad_keymatrix_num_cols(self); col++) {
for (size_t col = 0; col < common_hal_keypad_keymatrix_get_num_cols(self); col++) {
mp_uint_t key_num = row_col_to_key_num(self, row, col);
const bool previous = self->currently_pressed[key_num];
self->previously_pressed[key_num] = previous;

View File

@ -24,6 +24,8 @@
* THE SOFTWARE.
*/
#include <string.h>
#include "py/gc.h"
#include "py/runtime.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
@ -73,7 +75,7 @@ void common_hal_keypad_keys_deinit(keypad_keys_obj_t *self) {
// Remove self from the list of active keypad scanners first.
keypad_deregister_scanner((keypad_scanner_obj_t *)self);
for (size_t key = 0; key < common_hal_keypad_keys_num_keys(self); key++) {
for (size_t key = 0; key < common_hal_keypad_keys_get_num_keys(self); key++) {
common_hal_digitalio_digitalinout_deinit(self->digitalinouts->items[key]);
}
self->digitalinouts = MP_ROM_NONE;
@ -84,13 +86,21 @@ bool common_hal_keypad_keys_deinited(keypad_keys_obj_t *self) {
return self->digitalinouts == MP_ROM_NONE;
}
size_t common_hal_keypad_keys_num_keys(keypad_keys_obj_t *self) {
size_t common_hal_keypad_keys_get_num_keys(keypad_keys_obj_t *self) {
return self->digitalinouts->len;
}
bool common_hal_keypad_keys_pressed(keypad_keys_obj_t *self, mp_uint_t key_num) {
return self->currently_pressed[key_num];
}
// The length of states has already been validated.
void common_hal_keypad_keys_store_states(keypad_keys_obj_t *self, uint8_t *states) {
// Read the state atomically.
supervisor_acquire_lock(&keypad_scanners_linked_list_lock);
memcpy(states, self->currently_pressed, common_hal_keypad_keys_get_num_keys(self));
supervisor_release_lock(&keypad_scanners_linked_list_lock);
}
mp_obj_t common_hal_keypad_keys_get_events(keypad_keys_obj_t *self) {
return MP_OBJ_FROM_PTR(self->events);
}
@ -104,7 +114,7 @@ void keypad_keys_scan(keypad_keys_obj_t *self) {
self->last_scan_ticks = now;
for (mp_uint_t key_num = 0; key_num < common_hal_keypad_keys_num_keys(self); key_num++) {
for (mp_uint_t key_num = 0; key_num < common_hal_keypad_keys_get_num_keys(self); key_num++) {
// Remember the previous up/down state.
const bool previous = self->currently_pressed[key_num];
self->previously_pressed[key_num] = previous;

View File

@ -29,7 +29,7 @@
#include "supervisor/shared/lock.h"
#include "supervisor/shared/tick.h"
static supervisor_lock_t keypad_scanners_linked_list_lock;
supervisor_lock_t keypad_scanners_linked_list_lock;
void keypad_tick(void) {
// Fast path. Return immediately if there are no scanners.

View File

@ -28,6 +28,7 @@
#define SHARED_MODULE_KEYPAD_H
#include "py/obj.h"
#include "supervisor/shared/lock.h"
// All scanners must have a next field immediately following base.
// This is an ad hoc "superclass" struct for scanners, though they do
@ -37,6 +38,8 @@ typedef struct _keypad_scanner_obj_t {
struct _keypad_scanner_obj_t *next;
} keypad_scanner_obj_t;
extern supervisor_lock_t keypad_scanners_linked_list_lock;
void keypad_tick(void);
void keypad_reset(void);