From 154e91ab855115979bd0a73766cf7392dccfc3b4 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 21 Jun 2021 08:18:06 -0400 Subject: [PATCH] add EventQueue.store_next() to allow reusing event objects --- locale/circuitpython.pot | 4 ++++ shared-bindings/keypad/Event.c | 6 ++--- shared-bindings/keypad/EventQueue.c | 34 +++++++++++++++++++++++++++-- shared-bindings/keypad/EventQueue.h | 5 +++-- shared-module/keypad/EventQueue.c | 14 ++++++++++++ 5 files changed, 56 insertions(+), 7 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 04c6ead9b7..b399aba91f 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -949,6 +949,10 @@ msgstr "" msgid "Expected a UUID" msgstr "" +#: shared-bindings/keypad/EventQueue.c +msgid "Expected an %q" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" diff --git a/shared-bindings/keypad/Event.c b/shared-bindings/keypad/Event.c index 7abd75e54d..22f3b6b37d 100644 --- a/shared-bindings/keypad/Event.c +++ b/shared-bindings/keypad/Event.c @@ -32,7 +32,7 @@ //| class Event: //| """A key transition event.""" -//| def __init__(self, key_num: int, pressed: bool) -> None: +//| def __init__(self, key_num: int=0, pressed: bool=True) -> None: //| """Create a key transition event, which reports a key-pressed or key-released transition. //| //| :param int key_num: the key number @@ -46,8 +46,8 @@ STATIC mp_obj_t keypad_event_make_new(const mp_obj_type_t *type, size_t n_args, self->base.type = &keypad_event_type; enum { ARG_key_num, ARG_pressed }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_key_num, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_pressed, MP_ARG_REQUIRED | MP_ARG_BOOL }, + { MP_QSTR_key_num, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_pressed, MP_ARG_BOOL, {.u_bool = true} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); diff --git a/shared-bindings/keypad/EventQueue.c b/shared-bindings/keypad/EventQueue.c index 9ffebf3662..8cd3e74986 100644 --- a/shared-bindings/keypad/EventQueue.c +++ b/shared-bindings/keypad/EventQueue.c @@ -25,6 +25,7 @@ */ #include "py/runtime.h" +#include "shared-bindings/keypad/Event.h" #include "shared-bindings/keypad/EventQueue.h" //| class EventQueue: @@ -54,6 +55,34 @@ STATIC mp_obj_t keypad_eventqueue_next(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(keypad_eventqueue_next_obj, keypad_eventqueue_next); +//| def store_next(self, Event: event) -> bool: +//| """Store the next key transition event in the supplied event, if available, +//| and return ``True``. +//| If there are no queued events, do not touch ``event`` and return ``False``. +//| +//| The advantage of this method over ``next()`` is that it does not allocate storage. +//| Instead you can reuse an existing ``Event`` object. +//| +//| Note that the queue size is limited; see ``max_events`` in the constructor of +//| a scanner such as `Keys` or `KeyMatrix`. +//| If a new event arrives when the queue is full, the oldest event is discarded. +//| +//| :return ``True`` if an event was available and stored, ``False`` if not. +//| :rtype: bool +//| """ +//| ... +//| +STATIC mp_obj_t keypad_eventqueue_store_next(mp_obj_t self_in, mp_obj_t event_in) { + keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (!mp_obj_is_type(event_in, &keypad_event_type)) { + mp_raise_ValueError_varg(translate("Expected an %q"), MP_QSTR_Event); + } + keypad_event_obj_t *event = MP_OBJ_TO_PTR(event_in); + return mp_obj_new_bool(common_hal_keypad_eventqueue_store_next(self, event)); +} +MP_DEFINE_CONST_FUN_OBJ_2(keypad_eventqueue_store_next_obj, keypad_eventqueue_store_next); + //| def clear(self) -> None: //| """Clear any queued key transition events. //| """ @@ -91,8 +120,9 @@ STATIC mp_obj_t keypad_eventqueue_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } STATIC const mp_rom_map_elem_t keypad_eventqueue_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&keypad_eventqueue_clear_obj) }, - { MP_ROM_QSTR(MP_QSTR_next), MP_ROM_PTR(&keypad_eventqueue_next_obj) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&keypad_eventqueue_clear_obj) }, + { MP_ROM_QSTR(MP_QSTR_next), MP_ROM_PTR(&keypad_eventqueue_next_obj) }, + { MP_ROM_QSTR(MP_QSTR_store_next), MP_ROM_PTR(&keypad_eventqueue_store_next_obj) }, }; STATIC MP_DEFINE_CONST_DICT(keypad_eventqueue_locals_dict, keypad_eventqueue_locals_dict_table); diff --git a/shared-bindings/keypad/EventQueue.h b/shared-bindings/keypad/EventQueue.h index d6b2ac32c6..6faa2971fd 100644 --- a/shared-bindings/keypad/EventQueue.h +++ b/shared-bindings/keypad/EventQueue.h @@ -27,8 +27,8 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_EVENTQUEUE_H #define MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_EVENTQUEUE_H -#include "py/objlist.h" -#include "shared-module/keypad/Keys.h" +#include "shared-module/keypad/Event.h" +#include "shared-module/keypad/EventQueue.h" extern const mp_obj_type_t keypad_eventqueue_type; @@ -37,5 +37,6 @@ void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_ void common_hal_keypad_eventqueue_clear(keypad_eventqueue_obj_t *self); size_t common_hal_keypad_eventqueue_get_length(keypad_eventqueue_obj_t *self); mp_obj_t common_hal_keypad_eventqueue_next(keypad_eventqueue_obj_t *self); +bool common_hal_keypad_eventqueue_store_next(keypad_eventqueue_obj_t *self, keypad_event_obj_t *event); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_EVENTQUEUE_H diff --git a/shared-module/keypad/EventQueue.c b/shared-module/keypad/EventQueue.c index e75d93106a..556e425e4b 100644 --- a/shared-module/keypad/EventQueue.c +++ b/shared-module/keypad/EventQueue.c @@ -49,6 +49,20 @@ mp_obj_t common_hal_keypad_eventqueue_next(keypad_eventqueue_obj_t *self) { return MP_OBJ_FROM_PTR(event); } +bool common_hal_keypad_eventqueue_store_next(keypad_eventqueue_obj_t *self, keypad_event_obj_t *event) { + int encoded_event = ringbuf_get16(&self->encoded_events); + if (encoded_event == -1) { + return false; + } + + // "Construct" using the existing event. + common_hal_keypad_event_construct(event, encoded_event & EVENT_KEY_NUM_MASK, encoded_event & EVENT_PRESSED); + return true; +} + + + + void common_hal_keypad_eventqueue_clear(keypad_eventqueue_obj_t *self) { ringbuf_clear(&self->encoded_events); }