factor out keypad.EventQueue

This commit is contained in:
Dan Halbert 2021-06-16 15:27:59 -04:00
parent 3d18c5c327
commit cd31136c30
15 changed files with 352 additions and 164 deletions

View File

@ -517,6 +517,7 @@ SRC_SHARED_MODULE_ALL = \
ipaddress/__init__.c \
keypad/__init__.c \
keypad/Event.c \
keypad/EventQueue.c \
keypad/KeyMatrix.c \
keypad/Keys.c \
sdcardio/SDCard.c \

View File

@ -64,11 +64,11 @@ STATIC mp_obj_t keypad_event_make_new(const mp_obj_type_t *type, size_t n_args,
//| key_num: int
//| """The key number."""
//|
STATIC mp_obj_t keypad_event_obj_get_key_num(mp_obj_t self_in) {
STATIC mp_obj_t keypad_event_get_key_num(mp_obj_t self_in) {
keypad_event_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(common_hal_keypad_event_get_key_num(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_event_get_key_num_obj, keypad_event_obj_get_key_num);
MP_DEFINE_CONST_FUN_OBJ_1(keypad_event_get_key_num_obj, keypad_event_get_key_num);
const mp_obj_property_t keypad_event_key_num_obj = {
.base.type = &mp_type_property,
@ -78,15 +78,15 @@ const mp_obj_property_t keypad_event_key_num_obj = {
};
//| pressed: bool
//| """True if event represents a key down (pressed) transition.
//| """``True`` if the event represents a key down (pressed) transition.
//| The opposite of `released`.
//| """
//|
STATIC mp_obj_t keypad_event_obj_get_pressed(mp_obj_t self_in) {
STATIC mp_obj_t keypad_event_get_pressed(mp_obj_t self_in) {
keypad_event_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(common_hal_keypad_event_get_pressed(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_event_get_pressed_obj, keypad_event_obj_get_pressed);
MP_DEFINE_CONST_FUN_OBJ_1(keypad_event_get_pressed_obj, keypad_event_get_pressed);
const mp_obj_property_t keypad_event_pressed_obj = {
.base.type = &mp_type_property,
@ -96,15 +96,15 @@ const mp_obj_property_t keypad_event_pressed_obj = {
};
//| released: bool
//| """True if event represents a key up (released) transition.
//| """``True`` if the event represents a key up (released) transition.
//| The opposite of `pressed`.
//| """
//|
STATIC mp_obj_t keypad_event_obj_get_released(mp_obj_t self_in) {
STATIC mp_obj_t keypad_event_get_released(mp_obj_t self_in) {
keypad_event_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(common_hal_keypad_event_get_released(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_event_get_released_obj, keypad_event_obj_get_released);
MP_DEFINE_CONST_FUN_OBJ_1(keypad_event_get_released_obj, keypad_event_get_released);
const mp_obj_property_t keypad_event_released_obj = {
.base.type = &mp_type_property,
@ -114,7 +114,7 @@ const mp_obj_property_t keypad_event_released_obj = {
};
//| def __eq__(self, other: object) -> bool:
//| """Two Event objects are equal if their `key_num`
//| """Two `Event` objects are equal if their `key_num`
//| and `pressed`/`released` values are equal.
//| """
//| ...
@ -140,7 +140,7 @@ 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.."""
//| ...
//|
STATIC mp_obj_t keypad_event_unary_op(mp_unary_op_t op, mp_obj_t self_in) {

View File

@ -0,0 +1,105 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "shared-bindings/keypad/EventQueue.h"
//| class EventQueue:
//| """A queue of `Event` objects, filled by a `keypad` scanner such as `Keys` or `KeyMatrix`.
//|
//| You cannot create an instance of `EventQueue` directly. Each scanner creates an
//| instance when it is created.
//| """
//| ...
//| def next(self) -> Optional[Event]:
//| """Return the next key transition event. Return ``None`` if no events are pending.
//|
//| 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: the next queued key transition `Event`
//| :rtype: Optional[Event]
//| """
//| ...
//|
STATIC mp_obj_t keypad_eventqueue_next(mp_obj_t self_in) {
keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in);
return common_hal_keypad_eventqueue_next(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_eventqueue_next_obj, keypad_eventqueue_next);
//| def clear(self) -> None:
//| """Clear any queued key transition events.
//| """
//| ...
//|
STATIC mp_obj_t keypad_eventqueue_clear(mp_obj_t self_in) {
keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_keypad_eventqueue_clear(self);
return MP_ROM_NONE;
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_eventqueue_clear_obj, keypad_eventqueue_clear);
//| def __bool__(self) -> bool:
//| """``True`` if `len()` is greater than zero.
//| This is an easy way to check if the queue is empty.
//| """
//| ...
//|
//| def __len__(self) -> int:
//| """Return the number of events currently in the queue. Used to implement ``len()``."""
//| ...
//|
STATIC mp_obj_t keypad_eventqueue_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint16_t len = common_hal_keypad_eventqueue_get_length(self);
switch (op) {
case MP_UNARY_OP_BOOL:
return mp_obj_new_bool(len != 0);
case MP_UNARY_OP_LEN:
return MP_OBJ_NEW_SMALL_INT(len);
default:
return MP_OBJ_NULL; // op not supported
}
}
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) },
};
STATIC MP_DEFINE_CONST_DICT(keypad_eventqueue_locals_dict, keypad_eventqueue_locals_dict_table);
const mp_obj_type_t keypad_eventqueue_type = {
{ &mp_type_type },
.name = MP_QSTR_Keys,
.unary_op = keypad_eventqueue_unary_op,
.locals_dict = (mp_obj_t)&keypad_eventqueue_locals_dict,
};

View File

@ -0,0 +1,41 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#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"
extern const mp_obj_type_t keypad_eventqueue_type;
void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events);
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);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_EVENTQUEUE_H

View File

@ -25,6 +25,7 @@
*/
#include "lib/utils/context_manager_helpers.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "shared-bindings/keypad/Event.h"
#include "shared-bindings/keypad/KeyMatrix.h"
@ -44,11 +45,13 @@
//| The keys are numbered sequentially from zero. A key number can be computed
//| by ``row * len(col_pins) + col``.
//|
//| An `EventQueue` is created when this object is created and is available in the `events` attribute.
//|
//| The keys are debounced by waiting about 20 msecs before reporting a transition.
//|
//| :param Sequence[microcontroller.Pin] row_pins: The pins attached to the rows.
//| :param Sequence[microcontroller.Pin] col_pins: The pins attached to the colums.
//| :param int max_events: Size of key event queue:
//| :param int max_events: maximum size of `events` `EventQueue`:
//| maximum number of key transition events that are saved.
//| Must be >= 1.
//| If a new event arrives when the queue is full, the oldest event is discarded.
@ -133,42 +136,10 @@ STATIC void check_for_deinit(keypad_keymatrix_obj_t *self) {
}
}
//| def next_event(self) -> Optional[Event]:
//| """Return the next key transition event. Return ``None`` if no events are pending.
//|
//| Note that the queue size is limited; see ``max_events`` in the constructor.
//| If a new event arrives when the queue is full, the oldest event is discarded.
//|
//| :return: the next queued key transition `Event`
//| :rtype: Optional[Event]
//| """
//| ...
//|
STATIC mp_obj_t keypad_keymatrix_next_event(mp_obj_t self_in) {
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return common_hal_keypad_keymatrix_next_event(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keymatrix_next_event_obj, keypad_keymatrix_next_event);
//| def clear_events(self) -> None:
//| """Clear any queued key transition events.
//| """
//| ...
//|
STATIC mp_obj_t keypad_keymatrix_clear_events(mp_obj_t self_in) {
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
common_hal_keypad_keymatrix_clear_events(self);
return MP_ROM_NONE;
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keymatrix_clear_events_obj, keypad_keymatrix_clear_events);
//| 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 event queue.
//| of the key state which bypasses the `events` `EventQueue`.
//| """
//| ...
//|
@ -210,14 +181,30 @@ 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);
//| events: EventQueue
//| """The `EventQueue` associated with this `Keys` object. (read-only)
//| """
//|
STATIC mp_obj_t keypad_keymatrix_get_events(mp_obj_t self_in) {
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
return common_hal_keypad_keymatrix_get_events(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keymatrix_get_events_obj, keypad_keymatrix_get_events);
const mp_obj_property_t keypad_keymatrix_events_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&keypad_keymatrix_get_events_obj,
MP_ROM_NONE,
MP_ROM_NONE},
};
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_clear_events), MP_ROM_PTR(&keypad_keymatrix_clear_events_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_next_event), MP_ROM_PTR(&keypad_keymatrix_next_event_obj) },
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_keymatrix_pressed_obj) },
};
@ -225,7 +212,7 @@ STATIC MP_DEFINE_CONST_DICT(keypad_keymatrix_locals_dict, keypad_keymatrix_local
const mp_obj_type_t keypad_keymatrix_type = {
{ &mp_type_type },
.name = MP_QSTR_Keys,
.name = MP_QSTR_KeyMatrix,
.make_new = keypad_keymatrix_make_new,
.locals_dict = (mp_obj_t)&keypad_keymatrix_locals_dict,
};

View File

@ -33,6 +33,7 @@
extern const mp_obj_type_t keypad_keymatrix_type;
void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint_t num_row_pins, mcu_pin_obj_t *row_pins[], mp_uint_t num_col_pins, mcu_pin_obj_t *col_pins[], size_t max_events);
void common_hal_keypad_keymatrix_deinit(keypad_keymatrix_obj_t *self);
bool common_hal_keypad_keymatrix_deinited(keypad_keymatrix_obj_t *self);
@ -42,8 +43,7 @@ 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_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);
mp_obj_t common_hal_keypad_keymatrix_next_event(keypad_keymatrix_obj_t *self);
void common_hal_keypad_keymatrix_clear_events(keypad_keymatrix_obj_t *self);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYMATRIX_H

View File

@ -25,6 +25,7 @@
*/
#include "lib/utils/context_manager_helpers.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "shared-bindings/keypad/Event.h"
#include "shared-bindings/keypad/Keys.h"
@ -39,6 +40,8 @@
//| Create a `Keys` object that will scan keys attached to the given sequence of pins.
//| Each key is independent and attached to its own pin.
//|
//| An `EventQueue` is created when this object is created and is available in the `events` attribute.
//|
//| The keys are debounced by waiting about 20 msecs before reporting a transition.
//|
//| :param Sequence[microcontroller.Pin] pins: The pins attached to the keys.
@ -52,7 +55,7 @@
//| If an external pull is already provided for all the pins, you can set ``pull`` to ``False``.
//| However, enabling an internal pull when an external one is already present is not a problem;
//| it simply uses slightly more current.
//| :param int max_events: Size of key event queue:
//| :param int max_events: maximum size of `events` `EventQueue`:
//| maximum number of key transition events that are saved.
//| Must be >= 1.
//| If a new event arrives when the queue is full, the oldest event is discarded.
@ -132,42 +135,9 @@ STATIC void check_for_deinit(keypad_keys_obj_t *self) {
}
}
//| def next_event(self) -> Optional[Event]:
//| """Return the next key transition event. Return ``None`` if no events are pending.
//|
//| Note that the queue size is limited; see ``max_events`` in the constructor.
//| If a new event arrives when the queue is full, the oldest event is discarded.
//|
//| :return: the next queued key transition `Event`
//| :rtype: Optional[Event]
//| """
//| ...
//|
STATIC mp_obj_t keypad_keys_next_event(mp_obj_t self_in) {
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return common_hal_keypad_keys_next_event(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_next_event_obj, keypad_keys_next_event);
//| def clear_events(self) -> None:
//| """Clear any queued key transition events.
//| """
//| ...
//|
STATIC mp_obj_t keypad_keys_clear_events(mp_obj_t self_in) {
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
common_hal_keypad_keys_clear_events(self);
return MP_ROM_NONE;
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_clear_events_obj, keypad_keys_clear_events);
//| 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 event queue.
//| of the key state which bypasses the `events` `EventQueue`.
//| """
//| ...
//|
@ -184,14 +154,30 @@ 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);
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) },
//| events: EventQueue
//| """The `EventQueue` associated with this `Keys` object. (read-only)
//| """
//|
STATIC mp_obj_t keypad_keys_get_events(mp_obj_t self_in) {
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
return common_hal_keypad_keys_get_events(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_get_events_obj, keypad_keys_get_events);
{ MP_ROM_QSTR(MP_QSTR_clear_events), MP_ROM_PTR(&keypad_keys_clear_events_obj) },
{ MP_ROM_QSTR(MP_QSTR_next_event), MP_ROM_PTR(&keypad_keys_next_event_obj) },
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_keys_pressed_obj) },
const mp_obj_property_t keypad_keys_events_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&keypad_keys_get_events_obj,
MP_ROM_NONE,
MP_ROM_NONE},
};
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_events), MP_ROM_PTR(&keypad_keys_events_obj) },
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_keys_pressed_obj) },
};
STATIC MP_DEFINE_CONST_DICT(keypad_keys_locals_dict, keypad_keys_locals_dict_table);

View File

@ -33,13 +33,12 @@
extern const mp_obj_type_t keypad_keys_type;
void common_hal_keypad_keys_construct(keypad_keys_obj_t *self, mp_uint_t num_pins, mcu_pin_obj_t *pins[], bool value_when_pressed, bool pull, size_t max_events);
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);
bool common_hal_keypad_keys_pressed(keypad_keys_obj_t *self, mp_uint_t key_num);
mp_obj_t common_hal_keypad_keys_next_event(keypad_keys_obj_t *self);
void common_hal_keypad_keys_clear_events(keypad_keys_obj_t *self);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYS_H

View File

@ -28,6 +28,7 @@
#include "shared-bindings/keypad/__init__.h"
#include "shared-bindings/keypad/Event.h"
#include "shared-bindings/keypad/EventQueue.h"
#include "shared-bindings/keypad/KeyMatrix.h"
#include "shared-bindings/keypad/Keys.h"
@ -39,10 +40,11 @@
//|
STATIC mp_map_elem_t keypad_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_keypad) },
{ MP_ROM_QSTR(MP_QSTR_Event), MP_OBJ_FROM_PTR(&keypad_event_type) },
{ MP_ROM_QSTR(MP_QSTR_KeyMatrix), MP_OBJ_FROM_PTR(&keypad_keymatrix_type) },
{ MP_ROM_QSTR(MP_QSTR_Keys), MP_OBJ_FROM_PTR(&keypad_keys_type) },
{ MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_keypad) },
{ MP_ROM_QSTR(MP_QSTR_Event), MP_OBJ_FROM_PTR(&keypad_event_type) },
{ MP_ROM_QSTR(MP_QSTR_EventQueue), MP_OBJ_FROM_PTR(&keypad_eventqueue_type) },
{ MP_ROM_QSTR(MP_QSTR_KeyMatrix), MP_OBJ_FROM_PTR(&keypad_keymatrix_type) },
{ MP_ROM_QSTR(MP_QSTR_Keys), MP_OBJ_FROM_PTR(&keypad_keys_type) },
};
STATIC MP_DEFINE_MUTABLE_DICT(keypad_module_globals, keypad_module_globals_table);

View File

@ -0,0 +1,66 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/keypad/Event.h"
#include "shared-module/keypad/EventQueue.h"
// Top bit of 16-bit event indicates pressed or released. Rest is key_num.
#define EVENT_PRESSED (1 << 15)
#define EVENT_RELEASED (0)
#define EVENT_KEY_NUM_MASK (~EVENT_PRESSED)
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);
}
mp_obj_t common_hal_keypad_eventqueue_next(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);
}
void common_hal_keypad_eventqueue_clear(keypad_eventqueue_obj_t *self) {
ringbuf_clear(&self->encoded_events);
}
size_t common_hal_keypad_eventqueue_get_length(keypad_eventqueue_obj_t *self) {
return ringbuf_num_filled(&self->encoded_events);
}
void keypad_eventqueue_record(keypad_eventqueue_obj_t *self, mp_uint_t key_num, bool pressed) {
if (ringbuf_num_empty(&self->encoded_events) == 0) {
// Discard oldest if full.
ringbuf_get16(&self->encoded_events);
}
ringbuf_put16(&self->encoded_events, key_num | (pressed ? EVENT_PRESSED : EVENT_RELEASED));
}

View File

@ -0,0 +1,40 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_EVENTQUEUE_H
#define MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_EVENTQUEUE_H
#include "py/obj.h"
#include "py/ringbuf.h"
typedef struct {
mp_obj_base_t base;
ringbuf_t encoded_events;
} keypad_eventqueue_obj_t;
void keypad_eventqueue_record(keypad_eventqueue_obj_t *self, mp_uint_t key_num, bool pressed);
#endif // MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_EVENTQUEUE_H

View File

@ -26,21 +26,16 @@
#include "py/gc.h"
#include "py/runtime.h"
#include "shared-bindings/keypad/__init__.h"
#include "shared-bindings/keypad/Event.h"
#include "shared-bindings/keypad/KeyMatrix.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/keypad/EventQueue.h"
#include "shared-bindings/keypad/KeyMatrix.h"
#include "shared-bindings/keypad/__init__.h"
#include "shared-bindings/util.h"
#include "supervisor/port.h"
#include "supervisor/shared/tick.h"
#define DEBOUNCE_TICKS (20)
// Top bit of 16-bit event indicates pressed or released. Rest is key_num.
#define EVENT_PRESSED (1 << 15)
#define EVENT_RELEASED (0)
#define EVENT_KEY_NUM_MASK (~EVENT_PRESSED)
static mp_uint_t row_col_to_key_num(keypad_keymatrix_obj_t *self, mp_uint_t row, mp_uint_t col) {
return row * self->col_digitalinouts->len + col;
}
@ -70,8 +65,10 @@ void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint
self->currently_pressed = (bool *)gc_alloc(sizeof(bool) * num_row_pins * num_col_pins, false, false);
self->previously_pressed = (bool *)gc_alloc(sizeof(bool) * num_row_pins * num_col_pins, false, false);
// Event queue is 16-bit values.
ringbuf_alloc(&self->encoded_events, max_events * 2, false);
keypad_eventqueue_obj_t *events = m_new_obj(keypad_eventqueue_obj_t);
events->base.type = &keypad_eventqueue_type;
common_hal_keypad_eventqueue_construct(events, max_events);
self->events = events;
// Add self to the list of active keypad scanners.
keypad_register_scanner((keypad_scanner_obj_t *)self);
@ -117,27 +114,14 @@ size_t common_hal_keypad_keymatrix_num_cols(keypad_keymatrix_obj_t *self) {
bool common_hal_keypad_keymatrix_pressed(keypad_keymatrix_obj_t *self, mp_uint_t key_num) {
return self->currently_pressed[key_num];
}
mp_obj_t common_hal_keypad_keymatrix_next_event(keypad_keymatrix_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);
}
void common_hal_keypad_keymatrix_clear_events(keypad_keymatrix_obj_t *self) {
ringbuf_clear(&self->encoded_events);
}
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);
}
mp_obj_t common_hal_keypad_keymatrix_get_events(keypad_keymatrix_obj_t *self) {
return MP_OBJ_FROM_PTR(self->events);
}
void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self) {
uint64_t now = port_get_raw_ticks(NULL);
if (now - self->last_scan_ticks < DEBOUNCE_TICKS) {
@ -166,13 +150,8 @@ void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self) {
// Record any transitions.
if (previous != current) {
if (ringbuf_num_empty(&self->encoded_events) == 0) {
// Discard oldest if full.
ringbuf_get16(&self->encoded_events);
}
ringbuf_put16(&self->encoded_events, key_num | (current ? EVENT_PRESSED : EVENT_RELEASED));
keypad_eventqueue_record(self->events, key_num, current);
}
}
// Switch the row back to an input, pulled up.

View File

@ -29,10 +29,10 @@
#include "py/obj.h"
#include "py/objtuple.h"
#include "py/ringbuf.h"
#include "common-hal/digitalio/DigitalInOut.h"
#include "shared-module/keypad/__init__.h"
#include "shared-module/keypad/EventQueue.h"
typedef struct {
mp_obj_base_t base;
@ -43,7 +43,7 @@ typedef struct {
uint64_t last_scan_ticks;
bool *previously_pressed;
bool *currently_pressed;
ringbuf_t encoded_events;
keypad_eventqueue_obj_t *events;
} keypad_keymatrix_obj_t;
void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self);

View File

@ -26,20 +26,15 @@
#include "py/gc.h"
#include "py/runtime.h"
#include "shared-bindings/keypad/__init__.h"
#include "shared-bindings/keypad/Event.h"
#include "shared-bindings/keypad/Keys.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/keypad/EventQueue.h"
#include "shared-bindings/keypad/Keys.h"
#include "shared-bindings/keypad/__init__.h"
#include "supervisor/port.h"
#include "supervisor/shared/tick.h"
#define DEBOUNCE_TICKS (20)
// Top bit of 16-bit event indicates pressed or released. Rest is key_num.
#define EVENT_PRESSED (1 << 15)
#define EVENT_RELEASED (0)
#define EVENT_KEY_NUM_MASK (~EVENT_PRESSED)
void common_hal_keypad_keys_construct(keypad_keys_obj_t *self, mp_uint_t num_pins, mcu_pin_obj_t *pins[], bool value_when_pressed, bool pull, size_t max_events) {
mp_obj_t dios[num_pins];
@ -59,8 +54,10 @@ void common_hal_keypad_keys_construct(keypad_keys_obj_t *self, mp_uint_t num_pin
self->value_when_pressed = value_when_pressed;
self->last_scan_ticks = port_get_raw_ticks(NULL);
// Event queue is 16-bit values.
ringbuf_alloc(&self->encoded_events, max_events * 2, false);
keypad_eventqueue_obj_t *events = m_new_obj(keypad_eventqueue_obj_t);
events->base.type = &keypad_eventqueue_type;
common_hal_keypad_eventqueue_construct(events, max_events);
self->events = events;
// Add self to the list of active keypad scanners.
keypad_register_scanner((keypad_scanner_obj_t *)self);
@ -94,20 +91,8 @@ bool common_hal_keypad_keys_pressed(keypad_keys_obj_t *self, mp_uint_t key_num)
return self->currently_pressed[key_num];
}
mp_obj_t common_hal_keypad_keys_next_event(keypad_keys_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);
}
void common_hal_keypad_keys_clear_events(keypad_keys_obj_t *self) {
ringbuf_clear(&self->encoded_events);
mp_obj_t common_hal_keypad_keys_get_events(keypad_keys_obj_t *self) {
return MP_OBJ_FROM_PTR(self->events);
}
void keypad_keys_scan(keypad_keys_obj_t *self) {
@ -129,13 +114,10 @@ void keypad_keys_scan(keypad_keys_obj_t *self) {
common_hal_digitalio_digitalinout_get_value(self->digitalinouts->items[key_num]) ==
self->value_when_pressed;
self->currently_pressed[key_num] = current;
// Record any transitions.
if (previous != current) {
if (ringbuf_num_empty(&self->encoded_events) == 0) {
// Discard oldest if full.
ringbuf_get16(&self->encoded_events);
}
ringbuf_put16(&self->encoded_events, key_num | (current ? EVENT_PRESSED : EVENT_RELEASED));
keypad_eventqueue_record(self->events, key_num, current);
}
}
}

View File

@ -29,10 +29,10 @@
#include "py/obj.h"
#include "py/objtuple.h"
#include "py/ringbuf.h"
#include "common-hal/digitalio/DigitalInOut.h"
#include "shared-module/keypad/__init__.h"
#include "shared-module/keypad/EventQueue.h"
typedef struct {
mp_obj_base_t base;
@ -42,7 +42,7 @@ typedef struct {
uint64_t last_scan_ticks;
bool *previously_pressed;
bool *currently_pressed;
ringbuf_t encoded_events;
keypad_eventqueue_obj_t *events;
bool value_when_pressed;
} keypad_keys_obj_t;