diff --git a/shared-bindings/keypad/Event.c b/shared-bindings/keypad/Event.c index d1c6e40b72..0e2b85ca64 100644 --- a/shared-bindings/keypad/Event.c +++ b/shared-bindings/keypad/Event.c @@ -29,24 +29,27 @@ #include "py/runtime.h" #include "shared-bindings/keypad/Event.h" +#include "shared-bindings/supervisor/__init__.h" //| class Event: //| """A key transition event.""" -//| def __init__(self, key_number: int=0, pressed: bool=True) -> None: +//| def __init__(self, key_number: int=0, pressed: bool=True, timestamp:int=-1) -> None: //| """Create a key transition event, which reports a key-pressed or key-released transition. //| //| :param int key_number: the key number //| :param bool pressed: ``True`` if the key was pressed; ``False`` if it was released. +//| :param int timestamp: The time in milliseconds that the keypress occurred in the `supervisor.ticks_ms` time system. If specified as None, the current value of `supervisor.ticks_ms` is used. //| """ //| ... //| STATIC mp_obj_t keypad_event_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { keypad_event_obj_t *self = m_new_obj(keypad_event_obj_t); self->base.type = &keypad_event_type; - enum { ARG_key_number, ARG_pressed }; + enum { ARG_key_number, ARG_pressed, ARG_timestamp }; static const mp_arg_t allowed_args[] = { { MP_QSTR_key_number, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_pressed, MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_timestamp, MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; 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); @@ -54,7 +57,13 @@ STATIC mp_obj_t keypad_event_make_new(const mp_obj_type_t *type, size_t n_args, const mp_uint_t key_number = (mp_uint_t)mp_arg_validate_int_min(args[ARG_key_number].u_int, 0, MP_QSTR_key_number); - common_hal_keypad_event_construct(self, key_number, args[ARG_pressed].u_bool); + mp_obj_t timestamp = args[ARG_timestamp].u_obj; + if (timestamp == mp_const_none) { + timestamp = supervisor_ticks_ms(); + } + + (void)mp_obj_get_int_truncated(timestamp); // ensure that timesamp is an integer + common_hal_keypad_event_construct(self, key_number, args[ARG_pressed].u_bool, timestamp); return MP_OBJ_FROM_PTR(self); } @@ -110,9 +119,27 @@ const mp_obj_property_t keypad_event_released_obj = { MP_ROM_NONE}, }; +//| timestamp: int +//| """The timestamp""" +//| +STATIC mp_obj_t keypad_event_get_timestamp(mp_obj_t self_in) { + keypad_event_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_keypad_event_get_timestamp(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(keypad_event_get_timestamp_obj, keypad_event_get_timestamp); + +const mp_obj_property_t keypad_event_timestamp_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&keypad_event_get_timestamp_obj, + MP_ROM_NONE, + MP_ROM_NONE}, +}; + + //| def __eq__(self, other: object) -> bool: //| """Two `Event` objects are equal if their `key_number` //| and `pressed`/`released` values are equal. +//| Note that this does not compare the event timestamps. //| """ //| ... //| @@ -138,7 +165,9 @@ STATIC mp_obj_t keypad_event_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_ob } //| def __hash__(self) -> int: -//| """Returns a hash for the `Event`, so it can be used in dictionaries, etc..""" +//| """Returns a hash for the `Event`, so it can be used in dictionaries, etc.. +//| +//| Note that as events with different timestamps compare equal, they also hash to the same value.""" //| ... //| STATIC mp_obj_t keypad_event_unary_op(mp_unary_op_t op, mp_obj_t self_in) { @@ -166,6 +195,7 @@ STATIC const mp_rom_map_elem_t keypad_event_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_key_number), MP_ROM_PTR(&keypad_event_key_number_obj) }, { MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_event_pressed_obj) }, { MP_ROM_QSTR(MP_QSTR_released), MP_ROM_PTR(&keypad_event_released_obj) }, + { MP_ROM_QSTR(MP_QSTR_timestamp), MP_ROM_PTR(&keypad_event_timestamp_obj) }, }; STATIC MP_DEFINE_CONST_DICT(keypad_event_locals_dict, keypad_event_locals_dict_table); diff --git a/shared-bindings/keypad/Event.h b/shared-bindings/keypad/Event.h index 35cfdcdc64..44e69299e4 100644 --- a/shared-bindings/keypad/Event.h +++ b/shared-bindings/keypad/Event.h @@ -32,9 +32,10 @@ extern const mp_obj_type_t keypad_event_type; -void common_hal_keypad_event_construct(keypad_event_obj_t *self, mp_uint_t key_number, bool pressed); +void common_hal_keypad_event_construct(keypad_event_obj_t *self, mp_uint_t key_number, bool pressed, mp_obj_t timestamp); mp_int_t common_hal_keypad_event_get_key_number(keypad_event_obj_t *self); bool common_hal_keypad_event_get_pressed(keypad_event_obj_t *self); bool common_hal_keypad_event_get_released(keypad_event_obj_t *self); +mp_obj_t common_hal_keypad_event_get_timestamp(keypad_event_obj_t *self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_EVENT__H diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index a9b99ed87d..28565fd2ea 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -251,7 +251,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_set_next_code_file_obj, 0, supervisor_set_ //| //| """ //| ... -STATIC mp_obj_t supervisor_ticks_ms(void) { +mp_obj_t supervisor_ticks_ms(void) { uint64_t ticks_ms = common_hal_time_monotonic_ms(); return mp_obj_new_int((ticks_ms + 0x1fff0000) % (1 << 29)); } diff --git a/shared-bindings/supervisor/__init__.h b/shared-bindings/supervisor/__init__.h index a2ad3dd6d4..40a1e73932 100644 --- a/shared-bindings/supervisor/__init__.h +++ b/shared-bindings/supervisor/__init__.h @@ -33,7 +33,7 @@ #include "common-hal/supervisor/Runtime.h" extern const super_runtime_obj_t common_hal_supervisor_runtime_obj; - +extern mp_obj_t supervisor_ticks_ms(void); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_SUPERVISOR___INIT___H diff --git a/shared-module/keypad/Event.c b/shared-module/keypad/Event.c index d938002cc5..70a30e3831 100644 --- a/shared-module/keypad/Event.c +++ b/shared-module/keypad/Event.c @@ -25,10 +25,12 @@ */ #include "shared-module/keypad/Event.h" +#include "shared-bindings/keypad/Event.h" -void common_hal_keypad_event_construct(keypad_event_obj_t *self, mp_int_t key_number, bool pressed) { +void common_hal_keypad_event_construct(keypad_event_obj_t *self, mp_uint_t key_number, bool pressed, mp_obj_t timestamp) { self->key_number = key_number; self->pressed = pressed; + self->timestamp = timestamp; } mp_int_t common_hal_keypad_event_get_key_number(keypad_event_obj_t *self) { @@ -42,3 +44,7 @@ bool common_hal_keypad_event_get_pressed(keypad_event_obj_t *self) { bool common_hal_keypad_event_get_released(keypad_event_obj_t *self) { return !self->pressed; } + +mp_obj_t common_hal_keypad_event_get_timestamp(keypad_event_obj_t *self) { + return self->timestamp; +} diff --git a/shared-module/keypad/Event.h b/shared-module/keypad/Event.h index 3c47b0e636..c30eb9aa38 100644 --- a/shared-module/keypad/Event.h +++ b/shared-module/keypad/Event.h @@ -33,6 +33,7 @@ typedef struct { mp_obj_base_t base; uint16_t key_number; bool pressed; + mp_obj_t timestamp; } keypad_event_obj_t; diff --git a/shared-module/keypad/EventQueue.c b/shared-module/keypad/EventQueue.c index 5986a29ce8..ddd1cd0e87 100644 --- a/shared-module/keypad/EventQueue.c +++ b/shared-module/keypad/EventQueue.c @@ -25,6 +25,7 @@ */ #include "shared-bindings/keypad/Event.h" +#include "shared-bindings/supervisor/__init__.h" #include "shared-module/keypad/EventQueue.h" // Key number is lower 15 bits of a 16-bit value. @@ -33,33 +34,34 @@ void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events) { // Event queue is 16-bit values. - ringbuf_alloc(&self->encoded_events, max_events * 2, false); + ringbuf_alloc(&self->encoded_events, max_events * (sizeof(uint16_t) + sizeof(mp_obj_t)), false); self->overflowed = false; } -mp_obj_t common_hal_keypad_eventqueue_get(keypad_eventqueue_obj_t *self) { - int encoded_event = ringbuf_get16(&self->encoded_events); - if (encoded_event == -1) { - return MP_ROM_NONE; - } - - keypad_event_obj_t *event = m_new_obj(keypad_event_obj_t); - event->base.type = &keypad_event_type; - common_hal_keypad_event_construct(event, encoded_event & EVENT_KEY_NUM_MASK, encoded_event & EVENT_PRESSED); - return MP_OBJ_FROM_PTR(event); -} - bool common_hal_keypad_eventqueue_get_into(keypad_eventqueue_obj_t *self, keypad_event_obj_t *event) { int encoded_event = ringbuf_get16(&self->encoded_events); if (encoded_event == -1) { return false; } + mp_obj_t ticks; + ringbuf_get_n(&self->encoded_events, (uint8_t *)&ticks, sizeof(ticks)); // "Construct" using the existing event. - common_hal_keypad_event_construct(event, encoded_event & EVENT_KEY_NUM_MASK, encoded_event & EVENT_PRESSED); + common_hal_keypad_event_construct(event, encoded_event & EVENT_KEY_NUM_MASK, encoded_event & EVENT_PRESSED, ticks); return true; } +mp_obj_t common_hal_keypad_eventqueue_get(keypad_eventqueue_obj_t *self) { + keypad_event_obj_t *event = m_new_obj(keypad_event_obj_t); + event->base.type = &keypad_event_type; + bool result = common_hal_keypad_eventqueue_get_into(self, event); + if (result) { + return event; + } + m_free(event); + return MP_ROM_NONE; +} + bool common_hal_keypad_eventqueue_get_overflowed(keypad_eventqueue_obj_t *self) { return self->overflowed; } @@ -77,7 +79,7 @@ size_t common_hal_keypad_eventqueue_get_length(keypad_eventqueue_obj_t *self) { return ringbuf_num_filled(&self->encoded_events); } -bool keypad_eventqueue_record(keypad_eventqueue_obj_t *self, mp_uint_t key_number, bool pressed) { +bool keypad_eventqueue_record(keypad_eventqueue_obj_t *self, mp_uint_t key_number, bool pressed, mp_obj_t timestamp) { if (ringbuf_num_empty(&self->encoded_events) == 0) { // Queue is full. Set the overflow flag. The caller will decide what else to do. common_hal_keypad_eventqueue_set_overflowed(self, true); @@ -89,6 +91,7 @@ bool keypad_eventqueue_record(keypad_eventqueue_obj_t *self, mp_uint_t key_numbe encoded_event |= EVENT_PRESSED; } ringbuf_put16(&self->encoded_events, encoded_event); + ringbuf_put_n(&self->encoded_events, (uint8_t *)×tamp, sizeof(mp_obj_t)); return true; } diff --git a/shared-module/keypad/EventQueue.h b/shared-module/keypad/EventQueue.h index ce5e55ef3b..f686d45960 100644 --- a/shared-module/keypad/EventQueue.h +++ b/shared-module/keypad/EventQueue.h @@ -36,6 +36,6 @@ typedef struct { bool overflowed; } keypad_eventqueue_obj_t; -bool keypad_eventqueue_record(keypad_eventqueue_obj_t *self, mp_uint_t key_number, bool pressed); +bool keypad_eventqueue_record(keypad_eventqueue_obj_t *self, mp_uint_t key_number, bool pressed, mp_obj_t timestamp); #endif // MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_EVENTQUEUE_H diff --git a/shared-module/keypad/KeyMatrix.c b/shared-module/keypad/KeyMatrix.c index 6db012d0f6..4e1e25aafa 100644 --- a/shared-module/keypad/KeyMatrix.c +++ b/shared-module/keypad/KeyMatrix.c @@ -32,6 +32,7 @@ #include "shared-bindings/keypad/EventQueue.h" #include "shared-bindings/keypad/KeyMatrix.h" #include "shared-bindings/keypad/__init__.h" +#include "shared-bindings/supervisor/__init__.h" #include "shared-bindings/util.h" #include "supervisor/port.h" #include "supervisor/shared/tick.h" @@ -146,6 +147,8 @@ void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self) { self->last_scan_ticks = now; + mp_obj_t timestamp = supervisor_ticks_ms(); + // On entry, all pins are set to inputs with a pull-up or pull-down, // depending on the diode orientation. for (size_t row = 0; row < common_hal_keypad_keymatrix_get_row_count(self); row++) { @@ -170,7 +173,7 @@ void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self) { // Record any transitions. if (previous != current) { - keypad_eventqueue_record(self->events, key_number, current); + keypad_eventqueue_record(self->events, key_number, current, timestamp); } } diff --git a/shared-module/keypad/Keys.c b/shared-module/keypad/Keys.c index 2880d18de5..ed913ec7a6 100644 --- a/shared-module/keypad/Keys.c +++ b/shared-module/keypad/Keys.c @@ -32,6 +32,7 @@ #include "shared-bindings/keypad/EventQueue.h" #include "shared-bindings/keypad/Keys.h" #include "shared-bindings/keypad/__init__.h" +#include "shared-bindings/supervisor/__init__.h" #include "supervisor/port.h" #include "supervisor/shared/tick.h" @@ -112,6 +113,8 @@ void keypad_keys_scan(keypad_keys_obj_t *self) { const size_t key_count = common_hal_keypad_keys_get_key_count(self); + mp_obj_t timestamp = supervisor_ticks_ms(); + for (mp_uint_t key_number = 0; key_number < key_count; key_number++) { // Remember the previous up/down state. const bool previous = self->currently_pressed[key_number]; @@ -125,7 +128,7 @@ void keypad_keys_scan(keypad_keys_obj_t *self) { // Record any transitions. if (previous != current) { - keypad_eventqueue_record(self->events, key_number, current); + keypad_eventqueue_record(self->events, key_number, current, timestamp); } } } diff --git a/shared-module/keypad/ShiftRegisterKeys.c b/shared-module/keypad/ShiftRegisterKeys.c index 5075437214..85803378b1 100644 --- a/shared-module/keypad/ShiftRegisterKeys.c +++ b/shared-module/keypad/ShiftRegisterKeys.c @@ -32,6 +32,7 @@ #include "shared-bindings/keypad/EventQueue.h" #include "shared-bindings/keypad/ShiftRegisterKeys.h" #include "shared-bindings/keypad/__init__.h" +#include "shared-bindings/supervisor/__init__.h" #include "supervisor/port.h" #include "supervisor/shared/tick.h" @@ -122,6 +123,8 @@ void keypad_shiftregisterkeys_scan(keypad_shiftregisterkeys_obj_t *self) { self->last_scan_ticks = now; + mp_obj_t timestamp = supervisor_ticks_ms(); + // Latch (freeze) the current state of the input pins. common_hal_digitalio_digitalinout_set_value(self->latch, self->value_to_latch); @@ -145,7 +148,7 @@ void keypad_shiftregisterkeys_scan(keypad_shiftregisterkeys_obj_t *self) { // Record any transitions. if (previous != current) { - keypad_eventqueue_record(self->events, key_number, current); + keypad_eventqueue_record(self->events, key_number, current, timestamp); } }