This commit is contained in:
Dan Halbert 2021-06-14 20:54:43 -04:00
parent 627c426259
commit 32eec85230
17 changed files with 893 additions and 20 deletions

36
lib/utils/linked_list.h Normal file
View 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
View File

@ -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

View File

@ -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 \

View 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,
};

View 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

View File

@ -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) },

View File

@ -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

View 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;
}

View 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

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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
View 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
View 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

View File

@ -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);
}

View File

@ -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 \