compiles
This commit is contained in:
parent
627c426259
commit
32eec85230
36
lib/utils/linked_list.h
Normal file
36
lib/utils/linked_list.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of the MicroPython 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_LINKED_LIST_H
|
||||
#define MICROPY_INCLUDED_LINKED_LIST_H
|
||||
|
||||
#define LINKED_LIST_PREPEND(LIST_HEAD, OBJECT, NEXT_FIELD) \
|
||||
OBJECT->NEXT_FIELD = LIST_HEAD; \
|
||||
LIST_HEAD = OBJECT;
|
||||
|
||||
#define LINKED_LIST_DELETE(LIST_HEAD, OBJECT,
|
||||
|
||||
#endif // MICROPY_INCLUDED_LINKED_LIST_H
|
10
main.c
10
main.c
@ -86,6 +86,10 @@
|
||||
#include "shared-module/displayio/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_KEYPAD
|
||||
#include "shared-module/keypad/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_MEMORYMONITOR
|
||||
#include "shared-module/memorymonitor/__init__.h"
|
||||
#endif
|
||||
@ -230,9 +234,11 @@ STATIC void cleanup_after_vm(supervisor_allocation* heap) {
|
||||
#if CIRCUITPY_DISPLAYIO
|
||||
reset_displays();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_MEMORYMONITOR
|
||||
memorymonitor_reset();
|
||||
#endif
|
||||
|
||||
filesystem_flush();
|
||||
stop_mp();
|
||||
free_memory(heap);
|
||||
@ -242,6 +248,10 @@ STATIC void cleanup_after_vm(supervisor_allocation* heap) {
|
||||
common_hal_canio_reset();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_KEYPAD
|
||||
keypad_reset();
|
||||
#endif
|
||||
|
||||
// reset_board_busses() first because it may release pins from the never_reset state, so that
|
||||
// reset_port() can reset them.
|
||||
#if CIRCUITPY_BOARD
|
||||
|
@ -533,8 +533,20 @@ extern const struct _mp_obj_module_t ipaddress_module;
|
||||
#if CIRCUITPY_KEYPAD
|
||||
extern const struct _mp_obj_module_t keypad_module;
|
||||
#define KEYPAD_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_keypad), (mp_obj_t)&keypad_module },
|
||||
#define KEYPAD_ROOT_POINTERS \
|
||||
mp_obj_t keypad_keys_linked_list; \
|
||||
mp_obj_t keypad_keymatrix_linked_list;
|
||||
#else
|
||||
#define KEYPAD_MODULE
|
||||
#define KEYPAD_ROOT_POINTERS
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_GAMEPAD || CIRCUITPY_GAMEPADSHIFT
|
||||
// Scan gamepad every 32ms
|
||||
#define CIRCUITPY_GAMEPAD_TICKS 0x1f
|
||||
#define GAMEPAD_ROOT_POINTERS mp_obj_t gamepad_singleton;
|
||||
#else
|
||||
#define GAMEPAD_ROOT_POINTERS
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_MATH
|
||||
@ -962,6 +974,7 @@ struct _supervisor_allocation_node;
|
||||
vstr_t *repl_line; \
|
||||
mp_obj_t rtc_time_source; \
|
||||
GAMEPAD_ROOT_POINTERS \
|
||||
KEYPAD_ROOT_POINTERS \
|
||||
mp_obj_t pew_singleton; \
|
||||
BOARD_UART_ROOT_POINTER \
|
||||
FLASH_ROOT_POINTERS \
|
||||
|
228
shared-bindings/keypad/KeyMatrix.c
Normal file
228
shared-bindings/keypad/KeyMatrix.c
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* 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 "lib/utils/context_manager_helpers.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/keypad/Event.h"
|
||||
#include "shared-bindings/keypad/KeyMatrix.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/util.h"
|
||||
|
||||
//| class KeyMatrix:
|
||||
//| """Manage a 2D matrix of keys with row and column pins."""
|
||||
//|
|
||||
//| def __init__(self, row_pins: Sequence[microcontroller.Pin], col_pins: Sequence[microcontroller.Pin], max_events: int = 16) -> None:
|
||||
//| """
|
||||
//| Create a `Keys` object that will scan key matrix attached to the given row and column pins.
|
||||
//| If the matrix uses diodes, the diode anodes should be connected to the column pins,
|
||||
//| and the cathodes should be connected to the row pins.
|
||||
//|
|
||||
//| The keys are numbered sequentially from zero. A key number can be computed
|
||||
//| by ``col * len(row_pins) + row``.
|
||||
//|
|
||||
//| :param Sequence[microcontroller.Pin] row_pins: The pins attached to rows.
|
||||
//| :param Sequence[microcontroller.Pin] col_pins: The pins attached to rows.
|
||||
//| :param int max_events: Size of key event queue:
|
||||
//| 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.
|
||||
//| """
|
||||
//| ...
|
||||
|
||||
STATIC mp_obj_t keypad_keymatrix_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
keypad_keymatrix_obj_t *self = m_new_obj(keypad_keymatrix_obj_t);
|
||||
self->base.type = &keypad_keymatrix_type;
|
||||
enum { ARG_row_pins, ARG_col_pins, ARG_max_events };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_row_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_col_pins, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_BOOL },
|
||||
{ MP_QSTR_max_events, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} },
|
||||
};
|
||||
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);
|
||||
|
||||
mp_obj_t row_pins = args[ARG_row_pins].u_obj;
|
||||
// mp_obj_len() will be >= 0.
|
||||
const size_t num_row_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(row_pins));
|
||||
|
||||
mp_obj_t col_pins = args[ARG_col_pins].u_obj;
|
||||
const size_t num_col_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(col_pins));
|
||||
|
||||
if (args[ARG_max_events].u_int < 1) {
|
||||
mp_raise_ValueError_varg(translate("%q must be >= 1"), MP_QSTR_max_events);
|
||||
}
|
||||
const size_t max_events = (size_t)args[ARG_max_events].u_int;
|
||||
|
||||
mcu_pin_obj_t *row_pins_array[num_row_pins];
|
||||
mcu_pin_obj_t *col_pins_array[num_col_pins];
|
||||
|
||||
for (mp_uint_t i = 0; i < num_row_pins; i++) {
|
||||
mcu_pin_obj_t *pin =
|
||||
validate_obj_is_free_pin(mp_obj_subscr(row_pins, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL));
|
||||
row_pins_array[i] = pin;
|
||||
}
|
||||
|
||||
for (mp_uint_t i = 0; i < num_col_pins; i++) {
|
||||
mcu_pin_obj_t *pin =
|
||||
validate_obj_is_free_pin(mp_obj_subscr(col_pins, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL));
|
||||
col_pins_array[i] = pin;
|
||||
}
|
||||
|
||||
common_hal_keypad_keymatrix_construct(self, num_row_pins, row_pins_array, num_col_pins, col_pins_array, max_events);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
//| def deinit(self) -> None:
|
||||
//| """Stop scanning and release the pins."""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keymatrix_deinit(mp_obj_t self_in) {
|
||||
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
common_hal_keypad_keymatrix_deinit(self);
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keymatrix_deinit_obj, keypad_keymatrix_deinit);
|
||||
|
||||
//| def __enter__(self) -> KeyMatrix:
|
||||
//| """No-op used by Context Managers."""
|
||||
//| ...
|
||||
//|
|
||||
// Provided by context manager helper.
|
||||
|
||||
//| def __exit__(self) -> None:
|
||||
//| """Automatically deinitializes when exiting a context. See
|
||||
//| :ref:`lifetime-and-contextmanagers` for more info."""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keymatrix___exit__(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
common_hal_keypad_keymatrix_deinit(args[0]);
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_keymatrix___exit___obj, 4, 4, keypad_keymatrix___exit__);
|
||||
|
||||
STATIC void check_for_deinit(keypad_keymatrix_obj_t *self) {
|
||||
if (common_hal_keypad_keymatrix_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
}
|
||||
|
||||
//| 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, mp_obj_t event_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_2(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.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
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 || 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));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keymatrix_pressed_obj, keypad_keymatrix_pressed);
|
||||
|
||||
//| def key_num(self, row: int, col: int) -> int:
|
||||
//| """Return the key number for a given row and column.
|
||||
//| The key number is calculated by `row * number_of_columns + col`.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keymatrix_key_num(mp_obj_t self_in, mp_obj_t row_in, mp_obj_t col_in) {
|
||||
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
const mp_int_t row = mp_obj_get_int(row_in);
|
||||
if (row < 0 || row >= common_hal_keypad_keymatrix_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 || col >= common_hal_keypad_keymatrix_num_cols(self)) {
|
||||
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_col_num);
|
||||
}
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT(
|
||||
(mp_int_t)common_hal_keypad_keymatrix_key_num(self, (mp_uint_t)row, (mp_uint_t)col));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(keypad_keymatrix_key_num_obj, keypad_keymatrix_key_num);
|
||||
|
||||
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_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) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(keypad_keymatrix_locals_dict, keypad_keymatrix_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t keypad_keymatrix_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Keys,
|
||||
.make_new = keypad_keymatrix_make_new,
|
||||
.locals_dict = (mp_obj_t)&keypad_keymatrix_locals_dict,
|
||||
};
|
49
shared-bindings/keypad/KeyMatrix.h
Normal file
49
shared-bindings/keypad/KeyMatrix.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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_KEYMATRIX_H
|
||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYMATRIX_H
|
||||
|
||||
#include "py/objlist.h"
|
||||
#include "shared-module/keypad/KeyMatrix.h"
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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
|
@ -24,10 +24,12 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "lib/utils/context_manager_helpers.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/keypad/Event.h"
|
||||
#include "shared-bindings/keypad/Keys.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/util.h"
|
||||
|
||||
//| class Keys:
|
||||
//| """Manage a set of independent keys."""
|
||||
@ -88,9 +90,46 @@ STATIC mp_obj_t keypad_keys_make_new(const mp_obj_type_t *type, size_t n_args, c
|
||||
}
|
||||
|
||||
common_hal_keypad_keys_construct(self, num_pins, pins_array, value_when_pressed, args[ARG_pull].u_bool, max_events);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
//| def deinit(self) -> None:
|
||||
//| """Stop scanning and release the pins."""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keys_deinit(mp_obj_t self_in) {
|
||||
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
common_hal_keypad_keys_deinit(self);
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_deinit_obj, keypad_keys_deinit);
|
||||
|
||||
//| def __enter__(self) -> Keys:
|
||||
//| """No-op used by Context Managers."""
|
||||
//| ...
|
||||
//|
|
||||
// Provided by context manager helper.
|
||||
|
||||
//| def __exit__(self) -> None:
|
||||
//| """Automatically deinitializes when exiting a context. See
|
||||
//| :ref:`lifetime-and-contextmanagers` for more info."""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keys___exit__(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
common_hal_keypad_keys_deinit(args[0]);
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_keys___exit___obj, 4, 4, keypad_keys___exit__);
|
||||
|
||||
STATIC void check_for_deinit(keypad_keys_obj_t *self) {
|
||||
if (common_hal_keypad_keys_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
}
|
||||
|
||||
//| def next_event(self) -> Optional[Event]:
|
||||
//| """Return the next key transition event. Return ``None` if no events are pending.
|
||||
//|
|
||||
@ -104,6 +143,8 @@ STATIC mp_obj_t keypad_keys_make_new(const mp_obj_type_t *type, size_t n_args, c
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keys_next_event(mp_obj_t self_in, mp_obj_t event_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_2(keypad_keys_next_event_obj, keypad_keys_next_event);
|
||||
@ -115,6 +156,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(keypad_keys_next_event_obj, keypad_keys_next_event);
|
||||
//|
|
||||
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;
|
||||
@ -129,6 +171,8 @@ MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_clear_events_obj, keypad_keys_clear_events
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keys_pressed(mp_obj_t self_in, mp_obj_t key_num_in) {
|
||||
keypad_keys_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 || key_num >= common_hal_keypad_keys_num_keys(self)) {
|
||||
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_key_num);
|
||||
@ -139,6 +183,10 @@ 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) },
|
||||
|
||||
{ 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) },
|
||||
|
@ -33,6 +33,8 @@
|
||||
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_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);
|
||||
@ -40,6 +42,4 @@ 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);
|
||||
|
||||
void keypad_keys_scan(keypad_keys_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYS_H
|
||||
|
225
shared-module/keypad/KeyMatrix.c
Normal file
225
shared-module/keypad/KeyMatrix.c
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* 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/gc.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/keypad/Event.h"
|
||||
#include "shared-bindings/keypad/KeyMatrix.h"
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
#include "shared-bindings/util.h"
|
||||
#include "supervisor/port.h"
|
||||
#include "supervisor/shared/lock.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
|
||||
static supervisor_lock_t keypad_keymatrix_linked_list_lock;
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
mp_obj_t row_dios[num_row_pins];
|
||||
for (size_t i = 0; i < num_row_pins; i++) {
|
||||
digitalio_digitalinout_obj_t *dio = m_new_obj(digitalio_digitalinout_obj_t);
|
||||
dio->base.type = &digitalio_digitalinout_type;
|
||||
common_hal_digitalio_digitalinout_construct(dio, row_pins[i]);
|
||||
common_hal_digitalio_digitalinout_switch_to_input(dio, PULL_UP);
|
||||
row_dios[i] = dio;
|
||||
}
|
||||
self->row_digitalinouts = mp_obj_new_tuple(num_col_pins, row_dios);
|
||||
|
||||
mp_obj_t col_dios[num_col_pins];
|
||||
for (size_t i = 0; i < num_col_pins; i++) {
|
||||
digitalio_digitalinout_obj_t *dio = m_new_obj(digitalio_digitalinout_obj_t);
|
||||
dio->base.type = &digitalio_digitalinout_type;
|
||||
common_hal_digitalio_digitalinout_construct(dio, col_pins[i]);
|
||||
common_hal_digitalio_digitalinout_switch_to_input(dio, PULL_UP);
|
||||
col_dios[i] = dio;
|
||||
}
|
||||
self->col_digitalinouts = mp_obj_new_tuple(num_row_pins, col_dios);
|
||||
|
||||
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);
|
||||
|
||||
// Add self to the list of active Keys objects.
|
||||
|
||||
supervisor_acquire_lock(&keypad_keymatrix_linked_list_lock);
|
||||
self->next = MP_STATE_VM(keypad_keymatrix_linked_list);
|
||||
MP_STATE_VM(keypad_keymatrix_linked_list) = self;
|
||||
supervisor_release_lock(&keypad_keymatrix_linked_list_lock);
|
||||
}
|
||||
|
||||
void common_hal_keypad_keymatrix_deinit(keypad_keymatrix_obj_t *self) {
|
||||
if (common_hal_keypad_keymatrix_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t row = 0; row < common_hal_keypad_keymatrix_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++) {
|
||||
common_hal_digitalio_digitalinout_deinit(self->col_digitalinouts->items[col]);
|
||||
}
|
||||
self->col_digitalinouts = MP_ROM_NONE;
|
||||
|
||||
// Remove self from the list of active KeyMatrix objects.
|
||||
|
||||
supervisor_acquire_lock(&keypad_keymatrix_linked_list_lock);
|
||||
if (MP_STATE_VM(keypad_keymatrix_linked_list) == self) {
|
||||
// I'm at the front; splice myself out.
|
||||
MP_STATE_VM(keypad_keymatrix_linked_list) = self->next;
|
||||
} else {
|
||||
keypad_keymatrix_obj_t *current = MP_STATE_VM(keypad_keymatrix_linked_list);
|
||||
while (current) {
|
||||
if (current->next == self) {
|
||||
// Splice myself out.
|
||||
current->next = self->next;
|
||||
break;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
supervisor_release_lock(&keypad_keymatrix_linked_list_lock);
|
||||
}
|
||||
|
||||
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_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) {
|
||||
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];
|
||||
}
|
||||
|
||||
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);
|
||||
self->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);
|
||||
}
|
||||
|
||||
static 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) {
|
||||
// Too soon. Wait longer to debounce.
|
||||
return;
|
||||
}
|
||||
|
||||
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++) {
|
||||
// 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++) {
|
||||
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;
|
||||
|
||||
// Get the current state, by reading whether the col got pulled down or not.
|
||||
const bool current =
|
||||
common_hal_digitalio_digitalinout_get_value(self->col_digitalinouts->items[key_num]);
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Switch the row back to an input, pulled up.
|
||||
common_hal_digitalio_digitalinout_switch_to_input(self->row_digitalinouts->items[row], PULL_UP);
|
||||
}
|
||||
}
|
||||
|
||||
void keypad_keymatrix_tick(void) {
|
||||
// Fast path.
|
||||
if (!MP_STATE_VM(keypad_keymatrix_linked_list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (supervisor_try_lock(&keypad_keymatrix_linked_list_lock)) {
|
||||
keypad_keymatrix_obj_t *keypad_keymatrix = MP_STATE_VM(keypad_keymatrix_linked_list);
|
||||
while (keypad_keymatrix) {
|
||||
keypad_keymatrix_scan(keypad_keymatrix);
|
||||
keypad_keymatrix = keypad_keymatrix->next;
|
||||
}
|
||||
supervisor_release_lock(&keypad_keymatrix_linked_list_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void keypad_keymatrix_reset(void) {
|
||||
if (MP_STATE_VM(keypad_keymatrix_linked_list)) {
|
||||
supervisor_disable_tick();
|
||||
}
|
||||
|
||||
MP_STATE_VM(keypad_keys_linked_list) = NULL;
|
||||
keypad_keymatrix_linked_list_lock = false;
|
||||
}
|
51
shared-module/keypad/KeyMatrix.h
Normal file
51
shared-module/keypad/KeyMatrix.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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_KEYMATRIX_H
|
||||
#define MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_KEYMATRIX_H
|
||||
|
||||
#include "common-hal/digitalio/DigitalInOut.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objtuple.h"
|
||||
#include "py/ringbuf.h"
|
||||
|
||||
typedef struct _keypad_keymatrix_obj_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_tuple_t *row_digitalinouts;
|
||||
mp_obj_tuple_t *col_digitalinouts;
|
||||
uint64_t last_scan_ticks;
|
||||
bool *previously_pressed;
|
||||
bool *currently_pressed;
|
||||
ringbuf_t *encoded_events;
|
||||
// Keep a linked list of active KeyMatrix objects.
|
||||
struct _keypad_keymatrix_obj_t *next;
|
||||
} keypad_keymatrix_obj_t;
|
||||
|
||||
void keypad_keymatrix_tick();
|
||||
void keypad_keymatrix_reset();
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_KEYMATRIX_H
|
@ -25,11 +25,15 @@
|
||||
*/
|
||||
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/keypad/Event.h"
|
||||
#include "shared-bindings/keypad/Keys.h"
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
#include "py/runtime.h"
|
||||
#include "supervisor/port.h"
|
||||
#include "supervisor/shared/lock.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
|
||||
static supervisor_lock_t keypad_keys_linked_list_lock;
|
||||
|
||||
#define DEBOUNCE_TICKS (20)
|
||||
|
||||
@ -58,13 +62,73 @@ void common_hal_keypad_keys_construct(keypad_keys_obj_t *self, mp_uint_t num_pin
|
||||
|
||||
// Event queue is 16-bit values.
|
||||
ringbuf_alloc(self->encoded_events, max_events * 2, false);
|
||||
|
||||
// Add self to the list of active Keys objects.
|
||||
|
||||
supervisor_acquire_lock(&keypad_keys_linked_list_lock);
|
||||
self->next = MP_STATE_VM(keypad_keys_linked_list);
|
||||
MP_STATE_VM(keypad_keys_linked_list) = self;
|
||||
supervisor_release_lock(&keypad_keys_linked_list_lock);
|
||||
}
|
||||
|
||||
void common_hal_keypad_keys_deinit(keypad_keys_obj_t *self) {
|
||||
if (common_hal_keypad_keys_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t key = 0; key < common_hal_keypad_keys_num_keys(self); key++) {
|
||||
common_hal_digitalio_digitalinout_deinit(self->digitalinouts->items[key]);
|
||||
}
|
||||
self->digitalinouts = MP_ROM_NONE;
|
||||
|
||||
// Remove self from the list of active Keys objects.
|
||||
|
||||
supervisor_acquire_lock(&keypad_keys_linked_list_lock);
|
||||
if (MP_STATE_VM(keypad_keys_linked_list) == self) {
|
||||
// I'm at the front; splice myself out.
|
||||
MP_STATE_VM(keypad_keys_linked_list) = self->next;
|
||||
} else {
|
||||
keypad_keys_obj_t *current = MP_STATE_VM(keypad_keys_linked_list);
|
||||
while (current) {
|
||||
if (current->next == self) {
|
||||
// Splice myself out.
|
||||
current->next = self->next;
|
||||
break;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
supervisor_release_lock(&keypad_keys_linked_list_lock);
|
||||
}
|
||||
|
||||
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) {
|
||||
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];
|
||||
}
|
||||
|
||||
void keypad_keys_scan(keypad_keys_obj_t *self) {
|
||||
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);
|
||||
self->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);
|
||||
}
|
||||
|
||||
static void keypad_keys_scan(keypad_keys_obj_t *self) {
|
||||
uint64_t now = port_get_raw_ticks(NULL);
|
||||
if (now - self->last_scan_ticks < DEBOUNCE_TICKS) {
|
||||
// Too soon. Wait longer to debounce.
|
||||
@ -94,22 +158,27 @@ void keypad_keys_scan(keypad_keys_obj_t *self) {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
void keypad_keys_tick(void) {
|
||||
// Fast path.
|
||||
if (!MP_STATE_VM(keypad_keys_linked_list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
keypad_event_obj_t *event = m_new_obj(keypad_event_obj_t);
|
||||
self->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);
|
||||
if (supervisor_try_lock(&keypad_keys_linked_list_lock)) {
|
||||
keypad_keys_obj_t *keypad_keys = MP_STATE_VM(keypad_keys_linked_list);
|
||||
while (keypad_keys) {
|
||||
keypad_keys_scan(keypad_keys);
|
||||
keypad_keys = keypad_keys->next;
|
||||
}
|
||||
supervisor_release_lock(&keypad_keys_linked_list_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_keypad_keys_clear_events(keypad_keys_obj_t *self) {
|
||||
ringbuf_clear(self->encoded_events);
|
||||
void keypad_keys_reset(void) {
|
||||
if (MP_STATE_VM(keypad_keys_linked_list)) {
|
||||
supervisor_disable_tick();
|
||||
}
|
||||
|
||||
MP_STATE_VM(keypad_keys_linked_list) = NULL;
|
||||
keypad_keys_linked_list_lock = false;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "py/objtuple.h"
|
||||
#include "py/ringbuf.h"
|
||||
|
||||
typedef struct {
|
||||
typedef struct _keypad_keys_obj_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_tuple_t *digitalinouts;
|
||||
uint64_t last_scan_ticks;
|
||||
@ -41,7 +41,11 @@ typedef struct {
|
||||
bool *previously_pressed;
|
||||
bool *currently_pressed;
|
||||
ringbuf_t *encoded_events;
|
||||
// Keep a linked list of active Keys objects.
|
||||
struct _keypad_keys_obj_t *next;
|
||||
} keypad_keys_obj_t;
|
||||
|
||||
void keypad_keys_tick();
|
||||
void keypad_keys_reset();
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_KEYS_H
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of the MicroPython 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-module/keypad/Keys.h"
|
||||
#include "shared-module/keypad/KeyMatrix.h"
|
||||
|
||||
void keypad_tick(void) {
|
||||
keypad_keys_tick();
|
||||
keypad_keymatrix_tick();
|
||||
}
|
||||
|
||||
void keypad_reset(void) {
|
||||
keypad_keys_reset();
|
||||
keypad_keymatrix_reset();
|
||||
}
|
@ -27,4 +27,7 @@
|
||||
#ifndef SHARED_MODULE_KEYPAD_H
|
||||
#define SHARED_MODULE_KEYPAD_H
|
||||
|
||||
void keypad_tick(void);
|
||||
void keypad_reset(void);
|
||||
|
||||
#endif // SHARED_MODULE_KEYPAD_H
|
||||
|
51
supervisor/shared/lock.c
Normal file
51
supervisor/shared/lock.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of the MicroPython 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/microcontroller/__init__.h"
|
||||
#include "supervisor/shared/lock.h"
|
||||
|
||||
void supervisor_acquire_lock(supervisor_lock_t *lock) {
|
||||
while (!supervisor_try_lock(lock)) {
|
||||
RUN_BACKGROUND_TASKS;
|
||||
}
|
||||
}
|
||||
|
||||
bool supervisor_try_lock(supervisor_lock_t *lock) {
|
||||
bool grabbed_lock = false;
|
||||
common_hal_mcu_disable_interrupts();
|
||||
if (!*lock) {
|
||||
*lock = true;
|
||||
grabbed_lock = true;
|
||||
}
|
||||
common_hal_mcu_enable_interrupts();
|
||||
return grabbed_lock;
|
||||
}
|
||||
|
||||
void supervisor_release_lock(supervisor_lock_t *lock) {
|
||||
common_hal_mcu_disable_interrupts();
|
||||
*lock = false;
|
||||
common_hal_mcu_enable_interrupts();
|
||||
}
|
36
supervisor/shared/lock.h
Normal file
36
supervisor/shared/lock.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of the MicroPython 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_SUPERVISOR_LOCK_H
|
||||
#define MICROPY_INCLUDED_SUPERVISOR_LOCK_H
|
||||
|
||||
typedef volatile bool supervisor_lock_t;
|
||||
|
||||
void supervisor_acquire_lock(supervisor_lock_t *lock);
|
||||
bool supervisor_try_lock(supervisor_lock_t *lock);
|
||||
void supervisor_release_lock(supervisor_lock_t *lock);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SUPERVISOR_LOCK_H
|
@ -53,6 +53,10 @@
|
||||
#include "shared-module/gamepadshift/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_KEYPAD
|
||||
#include "shared-module/keypad/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_NETWORK
|
||||
#include "shared-module/network/__init__.h"
|
||||
#endif
|
||||
@ -108,9 +112,11 @@ void supervisor_tick(void) {
|
||||
#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
|
||||
filesystem_tick();
|
||||
#endif
|
||||
|
||||
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
|
||||
autoreload_tick();
|
||||
#endif
|
||||
|
||||
#ifdef CIRCUITPY_GAMEPAD_TICKS
|
||||
if (!(port_get_raw_ticks(NULL) & CIRCUITPY_GAMEPAD_TICKS)) {
|
||||
#if CIRCUITPY_GAMEPAD
|
||||
@ -121,6 +127,11 @@ void supervisor_tick(void) {
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_KEYPAD
|
||||
keypad_tick();
|
||||
#endif
|
||||
|
||||
background_callback_add(&tick_callback, supervisor_background_tasks, NULL);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ SRC_SUPERVISOR = \
|
||||
supervisor/shared/cpu.c \
|
||||
supervisor/shared/filesystem.c \
|
||||
supervisor/shared/flash.c \
|
||||
supervisor/shared/lock.c \
|
||||
supervisor/shared/memory.c \
|
||||
supervisor/shared/micropython.c \
|
||||
supervisor/shared/safe_mode.c \
|
||||
|
Loading…
Reference in New Issue
Block a user