Merge pull request #4891 from dhalbert/keypad-scanning-events
keypad: support for vector and matrix key scanning
This commit is contained in:
commit
b81573d439
@ -83,10 +83,22 @@ msgstr ""
|
||||
msgid "%q indices must be integers, not %s"
|
||||
msgstr ""
|
||||
|
||||
#: py/argcheck.c
|
||||
msgid "%q length must be %q"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/vectorio/Polygon.c
|
||||
msgid "%q list must be a list"
|
||||
msgstr ""
|
||||
|
||||
#: py/argcheck.c
|
||||
msgid "%q must <= %d"
|
||||
msgstr ""
|
||||
|
||||
#: py/argcheck.c
|
||||
msgid "%q must be %d-%d"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/usb_hid/Device.c
|
||||
msgid "%q must be 0-255"
|
||||
msgstr ""
|
||||
@ -95,7 +107,11 @@ msgstr ""
|
||||
msgid "%q must be 1-255"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/memorymonitor/AllocationAlarm.c
|
||||
#: py/argcheck.c
|
||||
msgid "%q must be >= %d"
|
||||
msgstr ""
|
||||
|
||||
#: py/argcheck.c shared-bindings/memorymonitor/AllocationAlarm.c
|
||||
msgid "%q must be >= 0"
|
||||
msgstr ""
|
||||
|
||||
@ -111,6 +127,10 @@ msgstr ""
|
||||
msgid "%q must be None or between 1 and len(report_descriptor)-1"
|
||||
msgstr ""
|
||||
|
||||
#: py/argcheck.c
|
||||
msgid "%q must be a string"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/vectorio/Polygon.c
|
||||
msgid "%q must be a tuple of length 2"
|
||||
msgstr ""
|
||||
@ -119,6 +139,15 @@ msgstr ""
|
||||
msgid "%q must be between %d and %d"
|
||||
msgstr ""
|
||||
|
||||
#: py/argcheck.c
|
||||
msgid "%q must of type %q"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c
|
||||
#: shared-bindings/keypad/ShiftRegisterKeys.c
|
||||
msgid "%q must store bytes"
|
||||
msgstr ""
|
||||
|
||||
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
|
||||
#: shared-bindings/canio/Match.c
|
||||
msgid "%q out of range"
|
||||
|
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
|
||||
|
@ -14,6 +14,7 @@ LONGINT_IMPL = NONE
|
||||
|
||||
CIRCUITPY_BUSDEVICE = 1
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
|
||||
# Include these Python libraries in firmware.
|
||||
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_CircuitPlayground
|
||||
|
@ -11,6 +11,7 @@ EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
|
||||
|
||||
# Turn off features and optimizations for displayio build to make room for additional frozen libs.
|
||||
LONGINT_IMPL = NONE
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_PIXELBUF = 0
|
||||
CIRCUITPY_ROTARYIO = 0
|
||||
CIRCUITPY_RTC = 0
|
||||
|
@ -12,7 +12,6 @@ LONGINT_IMPL = NONE
|
||||
|
||||
# To keep the build small
|
||||
CIRCUITPY_AUDIOBUSIO = 0
|
||||
CIRCUITPY_GAMEPAD = 0
|
||||
|
||||
# Include these Python libraries in firmware.
|
||||
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
|
||||
|
@ -15,6 +15,7 @@ CIRCUITPY_AUDIOMP3 = 0
|
||||
CIRCUITPY_BLEIO_HCI = 0
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_MSGPACK = 0
|
||||
CIRCUITPY_PS2IO = 0
|
||||
CIRCUITPY_RGBMATRIX = 0
|
||||
|
@ -16,8 +16,8 @@ CIRCUITPY_DRIVE_LABEL = "PYCUBED"
|
||||
CIRCUITPY_AUDIOBUSIO = 0
|
||||
CIRCUITPY_BITMAPTOOLS = 0
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||
CIRCUITPY_GAMEPAD = 0
|
||||
CIRCUITPY_RGBMATRIX = 0
|
||||
CIRCUITPY_PS2IO = 0
|
||||
|
||||
|
@ -17,7 +17,7 @@ CIRCUITPY_AUDIOBUSIO = 0
|
||||
CIRCUITPY_BITMAPTOOLS = 0
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||
CIRCUITPY_GAMEPAD = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_RGBMATRIX = 0
|
||||
CIRCUITPY_PS2IO = 0
|
||||
|
||||
|
@ -11,4 +11,6 @@ SPI_FLASH_FILESYSTEM = 1
|
||||
EXTERNAL_FLASH_DEVICES = AT25SF161
|
||||
LONGINT_IMPL = MPZ
|
||||
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
|
||||
CIRCUITPY_BITBANG_APA102 = 1
|
||||
|
@ -22,7 +22,6 @@ CIRCUITPY_FREQUENCYIO = 0
|
||||
CIRCUITPY_AUDIOBUSIO = 0
|
||||
CIRCUITPY_BLEIO = 0
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_GAMEPAD = 0
|
||||
CIRCUITPY_I2CPERIPHERAL = 0
|
||||
CIRCUITPY_TOUCHIO = 0
|
||||
CIRCUITPY_RGBMATRIX = 0
|
||||
|
@ -21,7 +21,6 @@ CIRCUITPY_BITMAPTOOLS = 0
|
||||
CIRCUITPY_BLEIO_HCI = 0
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||
CIRCUITPY_GAMEPAD = 0
|
||||
CIRCUITPY_I2CPERIPHERAL = 0
|
||||
CIRCUITPY_TOUCHIO = 0
|
||||
CIRCUITPY_RGBMATRIX = 0
|
||||
|
@ -50,6 +50,7 @@ CIRCUITPY_FRAMEBUFFERIO ?= 0
|
||||
CIRCUITPY_FREQUENCYIO ?= 0
|
||||
CIRCUITPY_I2CPERIPHERAL ?= 0
|
||||
CIRCUITPY_JSON ?= 0
|
||||
CIRCUITPY_KEYPAD ?= 0
|
||||
CIRCUITPY_MSGPACK ?= 0
|
||||
CIRCUITPY_RE ?= 0
|
||||
CIRCUITPY_SDCARDIO ?= 0
|
||||
|
@ -18,6 +18,7 @@ CIRCUITPY_FRAMEBUFFERIO = 0
|
||||
CIRCUITPY_FREQUENCYIO = 0
|
||||
CIRCUITPY_I2CPERIPHERAL = 0
|
||||
CIRCUITPY_JSON = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_MSGPACK = 0
|
||||
CIRCUITPY_NEOPIXEL_WRITE = 0
|
||||
CIRCUITPY_NVM = 0
|
||||
|
@ -20,7 +20,7 @@ CIRCUITPY_COUNTIO = 0
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_ERRNO = 0
|
||||
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||
CIRCUITPY_GAMEPAD = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_MSGPACK = 0
|
||||
CIRCUITPY_NEOPIXEL_WRITE = 0
|
||||
CIRCUITPY_NVM = 0
|
||||
|
@ -22,6 +22,7 @@ CIRCUITPY_AUDIOPWMIO = 0
|
||||
CIRCUITPY_BUSDEVICE = 0
|
||||
CIRCUITPY_BITMAPTOOLS = 0
|
||||
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_MIDI = 0
|
||||
CIRCUITPY_MSGPACK = 0
|
||||
CIRCUITPY_ULAB = 0
|
||||
|
@ -20,4 +20,5 @@ LD_FILE = boards/STM32F401xe_boot.ld
|
||||
# For debugging - also comment BOOTLOADER_OFFSET and BOARD_VTOR_DEFER
|
||||
# LD_FILE = boards/STM32F401xe_fs.ld
|
||||
|
||||
CIRCUITPY_BLEIO_HCI = 0
|
||||
CIRCUITPY_ULAB = 0
|
||||
|
@ -16,5 +16,6 @@ LD_FILE = boards/STM32F411_fs.ld
|
||||
# Too big for the flash
|
||||
CIRCUITPY_AUDIOCORE = 0
|
||||
CIRCUITPY_AUDIOPWMIO = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_MIDI = 0
|
||||
CIRCUITPY_MSGPACK = 0
|
||||
|
@ -15,5 +15,6 @@ LD_FILE = boards/STM32F411_fs.ld
|
||||
# Too big for the flash
|
||||
CIRCUITPY_AUDIOCORE = 0
|
||||
CIRCUITPY_AUDIOPWMIO = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_MIDI = 0
|
||||
CIRCUITPY_MSGPACK = 0
|
||||
|
@ -162,3 +162,56 @@ NORETURN void mp_arg_error_unimpl_kw(void) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("keyword argument(s) not yet implemented - use normal args instead"));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
mp_int_t mp_arg_validate_int_min(mp_int_t i, mp_int_t min, qstr arg_name) {
|
||||
if (i < min) {
|
||||
mp_raise_ValueError_varg(translate("%q must be >= %d"), arg_name, min);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
mp_int_t mp_arg_validate_int_max(mp_int_t i, mp_int_t max, qstr arg_name) {
|
||||
if (i > max) {
|
||||
mp_raise_ValueError_varg(translate("%q must <= %d"), arg_name, max);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
mp_int_t mp_arg_validate_int_range(mp_int_t i, mp_int_t min, mp_int_t max, qstr arg_name) {
|
||||
if (i < min || i > max) {
|
||||
mp_raise_ValueError_varg(translate("%q must be %d-%d"), arg_name, min, max);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
mp_float_t mp_arg_validate_obj_float_non_negative(mp_obj_t float_in, mp_float_t default_for_null, qstr arg_name) {
|
||||
const mp_float_t f = (float_in == MP_OBJ_NULL)
|
||||
? default_for_null
|
||||
: mp_obj_get_float(float_in);
|
||||
if (f <= (mp_float_t)0.0) {
|
||||
mp_raise_ValueError_varg(translate("%q must be >= 0"), arg_name);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
size_t mp_arg_validate_length_with_name(mp_int_t i, size_t length, qstr arg_name, qstr length_name) {
|
||||
if (i != (mp_int_t)length) {
|
||||
mp_raise_ValueError_varg(translate("%q length must be %q"), MP_QSTR_pressed, MP_QSTR_num_keys);
|
||||
}
|
||||
return (size_t)i;
|
||||
}
|
||||
|
||||
mp_obj_t mp_arg_validate_type(mp_obj_t obj, const mp_obj_type_t *type, qstr arg_name) {
|
||||
if (!mp_obj_is_type(obj, type)) {
|
||||
mp_raise_TypeError_varg(translate("%q must of type %q"), arg_name, type->name);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
mp_obj_t mp_arg_validate_string(mp_obj_t obj, qstr arg_name) {
|
||||
if (!mp_obj_is_str(obj)) {
|
||||
mp_raise_TypeError_varg(translate("%q must be a string"), arg_name);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
@ -178,6 +178,9 @@ endif
|
||||
ifeq ($(CIRCUITPY_FRAMEBUFFERIO),1)
|
||||
SRC_PATTERNS += framebufferio/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY__EVE),1)
|
||||
SRC_PATTERNS += _eve/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_FREQUENCYIO),1)
|
||||
SRC_PATTERNS += frequencyio/%
|
||||
endif
|
||||
@ -196,12 +199,12 @@ endif
|
||||
ifeq ($(CIRCUITPY_IPADDRESS),1)
|
||||
SRC_PATTERNS += ipaddress/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_KEYPAD),1)
|
||||
SRC_PATTERNS += keypad/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_MATH),1)
|
||||
SRC_PATTERNS += math/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY__EVE),1)
|
||||
SRC_PATTERNS += _eve/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_MEMORYMONITOR),1)
|
||||
SRC_PATTERNS += memorymonitor/%
|
||||
endif
|
||||
@ -512,6 +515,12 @@ SRC_SHARED_MODULE_ALL = \
|
||||
framebufferio/__init__.c \
|
||||
ipaddress/IPv4Address.c \
|
||||
ipaddress/__init__.c \
|
||||
keypad/__init__.c \
|
||||
keypad/Event.c \
|
||||
keypad/EventQueue.c \
|
||||
keypad/KeyMatrix.c \
|
||||
keypad/ShiftRegisterKeys.c \
|
||||
keypad/Keys.c \
|
||||
sdcardio/SDCard.c \
|
||||
sdcardio/__init__.c \
|
||||
gamepad/GamePad.c \
|
||||
|
@ -440,6 +440,13 @@ extern const struct _mp_obj_module_t espidf_module;
|
||||
#define ESPIDF_MODULE
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY__EVE
|
||||
extern const struct _mp_obj_module_t _eve_module;
|
||||
#define _EVE_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__eve), (mp_obj_t)&_eve_module },
|
||||
#else
|
||||
#define _EVE_MODULE
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_FRAMEBUFFERIO
|
||||
extern const struct _mp_obj_module_t framebufferio_module;
|
||||
#define FRAMEBUFFERIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_framebufferio), (mp_obj_t)&framebufferio_module },
|
||||
@ -523,6 +530,23 @@ extern const struct _mp_obj_module_t ipaddress_module;
|
||||
#define JSON_MODULE
|
||||
#endif
|
||||
|
||||
#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_scanners_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
|
||||
extern const struct _mp_obj_module_t math_module;
|
||||
#define MATH_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module },
|
||||
@ -530,13 +554,6 @@ extern const struct _mp_obj_module_t math_module;
|
||||
#define MATH_MODULE
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY__EVE
|
||||
extern const struct _mp_obj_module_t _eve_module;
|
||||
#define _EVE_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__eve), (mp_obj_t)&_eve_module },
|
||||
#else
|
||||
#define _EVE_MODULE
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_MEMORYMONITOR
|
||||
extern const struct _mp_obj_module_t memorymonitor_module;
|
||||
#define MEMORYMONITOR_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_memorymonitor), (mp_obj_t)&memorymonitor_module },
|
||||
@ -877,6 +894,7 @@ extern const struct _mp_obj_module_t msgpack_module;
|
||||
VECTORIO_MODULE \
|
||||
ERRNO_MODULE \
|
||||
ESPIDF_MODULE \
|
||||
_EVE_MODULE \
|
||||
FRAMEBUFFERIO_MODULE \
|
||||
FREQUENCYIO_MODULE \
|
||||
GAMEPAD_MODULE \
|
||||
@ -886,8 +904,8 @@ extern const struct _mp_obj_module_t msgpack_module;
|
||||
IPADDRESS_MODULE \
|
||||
IMAGECAPTURE_MODULE \
|
||||
JSON_MODULE \
|
||||
KEYPAD_MODULE \
|
||||
MATH_MODULE \
|
||||
_EVE_MODULE \
|
||||
MEMORYMONITOR_MODULE \
|
||||
MICROCONTROLLER_MODULE \
|
||||
MSGPACK_MODULE \
|
||||
@ -954,6 +972,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 \
|
||||
|
@ -178,10 +178,13 @@ CFLAGS += -DCIRCUITPY_ERRNO=$(CIRCUITPY_ERRNO)
|
||||
CIRCUITPY_ESPIDF ?= 0
|
||||
CFLAGS += -DCIRCUITPY_ESPIDF=$(CIRCUITPY_ESPIDF)
|
||||
|
||||
CIRCUITPY__EVE ?= 0
|
||||
CFLAGS += -DCIRCUITPY__EVE=$(CIRCUITPY__EVE)
|
||||
|
||||
CIRCUITPY_FREQUENCYIO ?= $(CIRCUITPY_FULL_BUILD)
|
||||
CFLAGS += -DCIRCUITPY_FREQUENCYIO=$(CIRCUITPY_FREQUENCYIO)
|
||||
|
||||
CIRCUITPY_GAMEPAD ?= $(CIRCUITPY_FULL_BUILD)
|
||||
CIRCUITPY_GAMEPAD ?= 0
|
||||
CFLAGS += -DCIRCUITPY_GAMEPAD=$(CIRCUITPY_GAMEPAD)
|
||||
|
||||
CIRCUITPY_GAMEPADSHIFT ?= 0
|
||||
@ -199,12 +202,12 @@ CFLAGS += -DCIRCUITPY_IPADDRESS=$(CIRCUITPY_IPADDRESS)
|
||||
CIRCUITPY_JSON ?= $(CIRCUITPY_FULL_BUILD)
|
||||
CFLAGS += -DCIRCUITPY_JSON=$(CIRCUITPY_JSON)
|
||||
|
||||
CIRCUITPY_KEYPAD ?= $(CIRCUITPY_FULL_BUILD)
|
||||
CFLAGS += -DCIRCUITPY_KEYPAD=$(CIRCUITPY_KEYPAD)
|
||||
|
||||
CIRCUITPY_MATH ?= 1
|
||||
CFLAGS += -DCIRCUITPY_MATH=$(CIRCUITPY_MATH)
|
||||
|
||||
CIRCUITPY__EVE ?= 0
|
||||
CFLAGS += -DCIRCUITPY__EVE=$(CIRCUITPY__EVE)
|
||||
|
||||
CIRCUITPY_MEMORYMONITOR ?= 0
|
||||
CFLAGS += -DCIRCUITPY_MEMORYMONITOR=$(CIRCUITPY_MEMORYMONITOR)
|
||||
|
||||
|
@ -91,6 +91,14 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args,
|
||||
NORETURN void mp_arg_error_terse_mismatch(void);
|
||||
NORETURN void mp_arg_error_unimpl_kw(void);
|
||||
|
||||
mp_int_t mp_arg_validate_int_min(mp_int_t i, mp_int_t min, qstr arg_name);
|
||||
mp_int_t mp_arg_validate_int_max(mp_int_t i, mp_int_t j, qstr arg_name);
|
||||
mp_int_t mp_arg_validate_int_range(mp_int_t i, mp_int_t min, mp_int_t max, qstr arg_name);
|
||||
mp_float_t mp_arg_validate_obj_float_non_negative(mp_obj_t float_in, mp_float_t default_for_null, qstr arg_name);
|
||||
size_t mp_arg_validate_length_with_name(mp_int_t i, size_t length, qstr arg_name, qstr length_name);
|
||||
mp_obj_t mp_arg_validate_type(mp_obj_t obj, const mp_obj_type_t *type, qstr arg_name);
|
||||
mp_obj_t mp_arg_validate_string(mp_obj_t obj, qstr arg_name);
|
||||
|
||||
static inline mp_obj_dict_t *PLACE_IN_ITCM(mp_locals_get)(void) {
|
||||
return MP_STATE_THREAD(dict_locals);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@
|
||||
//| clock: microcontroller.Pin,
|
||||
//| vsync: Optional[microcontroller.Pin],
|
||||
//| href: Optional[microcontroller.Pin],
|
||||
//| ):
|
||||
//| ) -> None:
|
||||
//| """Create a parallel image capture object
|
||||
//|
|
||||
//| :param List[microcontroller.Pin] data_pins: The data pins.
|
||||
|
180
shared-bindings/keypad/Event.c
Normal file
180
shared-bindings/keypad/Event.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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 "py/obj.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-bindings/keypad/Event.h"
|
||||
|
||||
//| class Event:
|
||||
//| """A key transition event."""
|
||||
//| def __init__(self, key_number: int=0, pressed: bool=True) -> None:
|
||||
//| """Create a key transition event, which reports a key-pressed or key-released transition.
|
||||
//|
|
||||
//| :param int key_number: the key number
|
||||
//| :param bool pressed: ``True`` if the key was pressed; ``False`` if it was released.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_event_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
keypad_event_obj_t *self = m_new_obj(keypad_event_obj_t);
|
||||
self->base.type = &keypad_event_type;
|
||||
enum { ARG_key_number, ARG_pressed };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_key_number, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_pressed, MP_ARG_BOOL, {.u_bool = true} },
|
||||
};
|
||||
mp_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);
|
||||
|
||||
const mp_uint_t key_number =
|
||||
(mp_uint_t)mp_arg_validate_int_min(args[ARG_key_number].u_int, 0, MP_QSTR_key_number);
|
||||
|
||||
common_hal_keypad_event_construct(self, key_number, args[ARG_pressed].u_bool);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
//| key_number: int
|
||||
//| """The key number."""
|
||||
//|
|
||||
STATIC mp_obj_t keypad_event_get_key_number(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_number(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_event_get_key_number_obj, keypad_event_get_key_number);
|
||||
|
||||
const mp_obj_property_t keypad_event_key_number_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&keypad_event_get_key_number_obj,
|
||||
MP_ROM_NONE,
|
||||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
//| pressed: bool
|
||||
//| """``True`` if the event represents a key down (pressed) transition.
|
||||
//| The opposite of `released`.
|
||||
//| """
|
||||
//|
|
||||
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_get_pressed);
|
||||
|
||||
const mp_obj_property_t keypad_event_pressed_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&keypad_event_get_pressed_obj,
|
||||
MP_ROM_NONE,
|
||||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
//| released: bool
|
||||
//| """``True`` if the event represents a key up (released) transition.
|
||||
//| The opposite of `pressed`.
|
||||
//| """
|
||||
//|
|
||||
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_get_released);
|
||||
|
||||
const mp_obj_property_t keypad_event_released_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&keypad_event_get_released_obj,
|
||||
MP_ROM_NONE,
|
||||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
//| def __eq__(self, other: object) -> bool:
|
||||
//| """Two `Event` objects are equal if their `key_number`
|
||||
//| and `pressed`/`released` values are equal.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_event_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
switch (op) {
|
||||
case MP_BINARY_OP_EQUAL:
|
||||
if (mp_obj_is_type(rhs_in, &keypad_event_type)) {
|
||||
keypad_event_obj_t *lhs = MP_OBJ_TO_PTR(lhs_in);
|
||||
keypad_event_obj_t *rhs = MP_OBJ_TO_PTR(rhs_in);
|
||||
return mp_obj_new_bool(
|
||||
(common_hal_keypad_event_get_key_number(lhs) ==
|
||||
common_hal_keypad_event_get_key_number(rhs)) &&
|
||||
(common_hal_keypad_event_get_pressed(lhs) ==
|
||||
common_hal_keypad_event_get_pressed(rhs))
|
||||
);
|
||||
} else {
|
||||
return mp_const_false;
|
||||
}
|
||||
|
||||
default:
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
//| def __hash__(self) -> int:
|
||||
//| """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) {
|
||||
keypad_event_obj_t *self = MP_OBJ_TO_PTR(self);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_HASH: {
|
||||
const mp_int_t key_number = common_hal_keypad_event_get_key_number(self);
|
||||
const bool pressed = common_hal_keypad_event_get_pressed(self);
|
||||
return MP_OBJ_NEW_SMALL_INT((pressed << 15) + key_number);
|
||||
}
|
||||
default:
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void keypad_event_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
keypad_event_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<Event: key_number %d %s>",
|
||||
common_hal_keypad_event_get_key_number(self),
|
||||
common_hal_keypad_event_get_pressed(self) ? "pressed" : "released");
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t keypad_event_locals_dict_table[] = {
|
||||
// Properties
|
||||
{ MP_ROM_QSTR(MP_QSTR_key_number), MP_ROM_PTR(&keypad_event_key_number_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&keypad_event_pressed_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_released), MP_ROM_PTR(&keypad_event_released_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(keypad_event_locals_dict, keypad_event_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t keypad_event_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Event,
|
||||
.make_new = keypad_event_make_new,
|
||||
.print = keypad_event_print,
|
||||
.unary_op = keypad_event_unary_op,
|
||||
.binary_op = keypad_event_binary_op,
|
||||
.locals_dict = (mp_obj_dict_t *)&keypad_event_locals_dict,
|
||||
};
|
40
shared-bindings/keypad/Event.h
Normal file
40
shared-bindings/keypad/Event.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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_SHARED_BINDINGS_KEYPAD_EVENT__H
|
||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_EVENT__H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "shared-module/keypad/Event.h"
|
||||
|
||||
extern const mp_obj_type_t keypad_event_type;
|
||||
|
||||
void common_hal_keypad_event_construct(keypad_event_obj_t *self, mp_uint_t key_number, bool pressed);
|
||||
mp_int_t common_hal_keypad_event_get_key_number(keypad_event_obj_t *self);
|
||||
bool common_hal_keypad_event_get_pressed(keypad_event_obj_t *self);
|
||||
bool common_hal_keypad_event_get_released(keypad_event_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_EVENT__H
|
152
shared-bindings/keypad/EventQueue.c
Normal file
152
shared-bindings/keypad/EventQueue.c
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/keypad/Event.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 get(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 event is discarded, and
|
||||
//| `overflowed` is set to ``True``.
|
||||
//|
|
||||
//| :return: the next queued key transition `Event`
|
||||
//| :rtype: Optional[Event]
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_eventqueue_get(mp_obj_t self_in) {
|
||||
keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
return common_hal_keypad_eventqueue_get(self);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_eventqueue_get_obj, keypad_eventqueue_get);
|
||||
|
||||
//| def get_into(self, event: Event) -> bool:
|
||||
//| """Store the next key transition event in the supplied event, if available,
|
||||
//| and return ``True``.
|
||||
//| If there are no queued events, do not touch ``event`` and return ``False``.
|
||||
//|
|
||||
//| The advantage of this method over ``get()`` is that it does not allocate storage.
|
||||
//| Instead you can reuse an existing ``Event`` object.
|
||||
//|
|
||||
//| Note that the queue size is limited; see ``max_events`` in the constructor of
|
||||
//| a scanner such as `Keys` or `KeyMatrix`.
|
||||
//|
|
||||
//| :return ``True`` if an event was available and stored, ``False`` if not.
|
||||
//| :rtype: bool
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_eventqueue_get_into(mp_obj_t self_in, mp_obj_t event_in) {
|
||||
keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
keypad_event_obj_t *event = MP_OBJ_TO_PTR(mp_arg_validate_type(event_in, &keypad_event_type, MP_QSTR_event));
|
||||
|
||||
return mp_obj_new_bool(common_hal_keypad_eventqueue_get_into(self, event));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(keypad_eventqueue_get_into_obj, keypad_eventqueue_get_into);
|
||||
|
||||
//| def clear(self) -> None:
|
||||
//| """Clear any queued key transition events. Also sets `overflowed` to ``False``.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
//| overflowed: bool
|
||||
//| """``True`` if an event could not be added to the event queue because it was full. (read-only)
|
||||
//| Set to ``False`` by `clear()`.
|
||||
//| """
|
||||
//|
|
||||
STATIC mp_obj_t keypad_eventqueue_get_overflowed(mp_obj_t self_in) {
|
||||
keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_bool(common_hal_keypad_eventqueue_get_overflowed(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_eventqueue_get_overflowed_obj, keypad_eventqueue_get_overflowed);
|
||||
|
||||
const mp_obj_property_t keypad_eventqueue_overflowed_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&keypad_eventqueue_get_overflowed_obj,
|
||||
MP_ROM_NONE,
|
||||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
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_get), MP_ROM_PTR(&keypad_eventqueue_get_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_into), MP_ROM_PTR(&keypad_eventqueue_get_into_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,
|
||||
};
|
45
shared-bindings/keypad/EventQueue.h
Normal file
45
shared-bindings/keypad/EventQueue.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 "shared-module/keypad/Event.h"
|
||||
#include "shared-module/keypad/EventQueue.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_get(keypad_eventqueue_obj_t *self);
|
||||
bool common_hal_keypad_eventqueue_get_into(keypad_eventqueue_obj_t *self, keypad_event_obj_t *event);
|
||||
|
||||
bool common_hal_keypad_eventqueue_get_overflowed(keypad_eventqueue_obj_t *self);
|
||||
void common_hal_keypad_eventqueue_set_overflowed(keypad_eventqueue_obj_t *self, bool overflowed);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_EVENTQUEUE_H
|
269
shared-bindings/keypad/KeyMatrix.c
Normal file
269
shared-bindings/keypad/KeyMatrix.c
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* 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/binary.h"
|
||||
#include "py/objproperty.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], column_pins: Sequence[microcontroller.Pin], columns_to_anodes: bool = True, interval: float = 0.020, max_events: int = 64) -> None:
|
||||
//| """
|
||||
//| Create a `Keys` object that will scan the key matrix attached to the given row and column pins.
|
||||
//| There should not be any external pull-ups or pull-downs on the matrix:
|
||||
//| ``KeyMatrix`` enables internal pull-ups or pull-downs on the pins as necessary.
|
||||
//|
|
||||
//| The keys are numbered sequentially from zero. A key number can be computed
|
||||
//| by ``row * len(column_pins) + column``.
|
||||
//|
|
||||
//| An `EventQueue` is created when this object is created and is available in the `events` attribute.
|
||||
//|
|
||||
//| :param Sequence[microcontroller.Pin] row_pins: The pins attached to the rows.
|
||||
//| :param Sequence[microcontroller.Pin] column_pins: The pins attached to the colums.
|
||||
//| :param bool columns_to_anodes: Default ``True``.
|
||||
//| If the matrix uses diodes, the diode anodes are typically connected to the column pins,
|
||||
//| and the cathodes should be connected to the row pins. If your diodes are reversed,
|
||||
//| set ``columns_to_anodes`` to ``False``.
|
||||
//| :param float interval: Scan keys no more often than ``interval`` to allow for debouncing.
|
||||
//| ``interval`` is in float seconds. The default is 0.020 (20 msecs).
|
||||
//| :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.
|
||||
//| """
|
||||
//| ...
|
||||
|
||||
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_column_pins, ARG_columns_to_anodes, ARG_interval, ARG_max_events };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_row_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_column_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_columns_to_anodes, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
||||
{ MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_max_events, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
|
||||
};
|
||||
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 column_pins = args[ARG_column_pins].u_obj;
|
||||
const size_t num_column_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(column_pins));
|
||||
|
||||
const mp_float_t interval =
|
||||
mp_arg_validate_obj_float_non_negative(args[ARG_interval].u_obj, 0.020f, MP_QSTR_interval);
|
||||
const size_t max_events = (size_t)mp_arg_validate_int_min(args[ARG_max_events].u_int, 1, MP_QSTR_max_events);
|
||||
|
||||
mcu_pin_obj_t *row_pins_array[num_row_pins];
|
||||
mcu_pin_obj_t *column_pins_array[num_column_pins];
|
||||
|
||||
for (size_t row = 0; row < num_row_pins; row++) {
|
||||
mcu_pin_obj_t *pin =
|
||||
validate_obj_is_free_pin(mp_obj_subscr(row_pins, MP_OBJ_NEW_SMALL_INT(row), MP_OBJ_SENTINEL));
|
||||
row_pins_array[row] = pin;
|
||||
}
|
||||
|
||||
for (size_t column = 0; column < num_column_pins; column++) {
|
||||
mcu_pin_obj_t *pin =
|
||||
validate_obj_is_free_pin(mp_obj_subscr(column_pins, MP_OBJ_NEW_SMALL_INT(column), MP_OBJ_SENTINEL));
|
||||
column_pins_array[column] = pin;
|
||||
}
|
||||
|
||||
common_hal_keypad_keymatrix_construct(self, num_row_pins, row_pins_array, num_column_pins, column_pins_array, args[ARG_columns_to_anodes].u_bool, interval, 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 reset(self) -> None:
|
||||
//| """Reset the internal state of the scanner to assume that all keys are now released.
|
||||
//| Any key that is already pressed at the time of this call will therefore immediately cause
|
||||
//| a new key-pressed event to occur.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keymatrix_reset(mp_obj_t self_in) {
|
||||
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
common_hal_keypad_keymatrix_reset(self);
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keymatrix_reset_obj, keypad_keymatrix_reset);
|
||||
|
||||
//| key_count: int
|
||||
//| """The number of keys that are being scanned. (read-only)
|
||||
//| """
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keymatrix_get_key_count(mp_obj_t self_in) {
|
||||
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_keypad_keymatrix_get_key_count(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keymatrix_get_key_count_obj, keypad_keymatrix_get_key_count);
|
||||
|
||||
const mp_obj_property_t keypad_keymatrix_key_count_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&keypad_keymatrix_get_key_count_obj,
|
||||
MP_ROM_NONE,
|
||||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
//| def key_number_to_row_column(self, row: int, column: int) -> Tuple[int]:
|
||||
//| """Return the row and column for the given key number.
|
||||
//| The row is ``key_number // len(column_pins)``.
|
||||
//| The column is ``key_number % len(column_pins)``.
|
||||
//|
|
||||
//| :return: ``(row, column)``
|
||||
//| :rtype: Tuple[int]
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keymatrix_key_number_to_row_column(mp_obj_t self_in, mp_obj_t key_number_in) {
|
||||
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
const mp_uint_t key_number = (mp_uint_t)mp_arg_validate_int_range(
|
||||
mp_obj_get_int(key_number_in),
|
||||
0, (mp_int_t)common_hal_keypad_keymatrix_get_key_count(self),
|
||||
MP_QSTR_key_number);
|
||||
|
||||
mp_uint_t row;
|
||||
mp_uint_t column;
|
||||
common_hal_keypad_keymatrix_key_number_to_row_column(self, key_number, &row, &column);
|
||||
|
||||
mp_obj_t row_column[2];
|
||||
row_column[0] = MP_OBJ_NEW_SMALL_INT(row);
|
||||
row_column[1] = MP_OBJ_NEW_SMALL_INT(column);
|
||||
|
||||
return mp_obj_new_tuple(2, row_column);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(keypad_keymatrix_key_number_to_row_column_obj, keypad_keymatrix_key_number_to_row_column);
|
||||
|
||||
//| def row_column_to_key_number(self, row: int, column: int) -> int:
|
||||
//| """Return the key number for a given row and column.
|
||||
//| The key number is ``row * len(column_pins) + column``.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keymatrix_row_column_to_key_number(mp_obj_t self_in, mp_obj_t row_in, mp_obj_t column_in) {
|
||||
keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
const mp_uint_t row = (mp_uint_t)mp_arg_validate_int_range(
|
||||
mp_obj_get_int(row_in), 0, (mp_int_t)common_hal_keypad_keymatrix_get_row_count(self), MP_QSTR_row);
|
||||
|
||||
const mp_int_t column = (mp_uint_t)mp_arg_validate_int_range(
|
||||
mp_obj_get_int(column_in), 0, (mp_int_t)common_hal_keypad_keymatrix_get_column_count(self), MP_QSTR_column);
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT(
|
||||
(mp_int_t)common_hal_keypad_keymatrix_row_column_to_key_number(self, row, column));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(keypad_keymatrix_row_column_to_key_number_obj, keypad_keymatrix_row_column_to_key_number);
|
||||
|
||||
//| 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);
|
||||
check_for_deinit(self);
|
||||
|
||||
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_events), MP_ROM_PTR(&keypad_keymatrix_events_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_key_count), MP_ROM_PTR(&keypad_keymatrix_key_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&keypad_keymatrix_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_key_number_to_row_column), MP_ROM_PTR(&keypad_keymatrix_key_number_to_row_column_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_row_column_to_key_number), MP_ROM_PTR(&keypad_keymatrix_row_column_to_key_number_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_KeyMatrix,
|
||||
.make_new = keypad_keymatrix_make_new,
|
||||
.locals_dict = (mp_obj_t)&keypad_keymatrix_locals_dict,
|
||||
};
|
50
shared-bindings/keypad/KeyMatrix.h
Normal file
50
shared-bindings/keypad/KeyMatrix.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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_column_pins, mcu_pin_obj_t *column_pins[], bool columns_to_anodes, mp_float_t interval, 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);
|
||||
|
||||
void common_hal_keypad_keymatrix_key_number_to_row_column(keypad_keymatrix_obj_t *self, mp_uint_t key_number, mp_uint_t *row, mp_uint_t *column);
|
||||
mp_uint_t common_hal_keypad_keymatrix_row_column_to_key_number(keypad_keymatrix_obj_t *self, mp_uint_t row, mp_uint_t column);
|
||||
|
||||
size_t common_hal_keypad_keymatrix_get_key_count(keypad_keymatrix_obj_t *self);
|
||||
size_t common_hal_keypad_keymatrix_get_column_count(keypad_keymatrix_obj_t *self);
|
||||
size_t common_hal_keypad_keymatrix_get_row_count(keypad_keymatrix_obj_t *self);
|
||||
|
||||
mp_obj_t common_hal_keypad_keymatrix_get_events(keypad_keymatrix_obj_t *self);
|
||||
void common_hal_keypad_keymatrix_reset(keypad_keymatrix_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYMATRIX_H
|
209
shared-bindings/keypad/Keys.c
Normal file
209
shared-bindings/keypad/Keys.c
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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/binary.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/keypad/Event.h"
|
||||
#include "shared-bindings/keypad/Keys.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/util.h"
|
||||
|
||||
//| class Keys:
|
||||
//| """Manage a set of independent keys."""
|
||||
//|
|
||||
//| def __init__(self, pins: Sequence[microcontroller.Pin], *, value_when_pressed: bool, pull: bool = True, interval: float = 0.020, max_events: int = 64) -> None:
|
||||
//| """
|
||||
//| 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.
|
||||
//|
|
||||
//| :param Sequence[microcontroller.Pin] pins: The pins attached to the keys.
|
||||
//| The key numbers correspond to indices into this sequence.
|
||||
//| :param bool value_when_pressed: ``True`` if the pin reads high when the key is pressed.
|
||||
//| ``False`` if the pin reads low (is grounded) when the key is pressed.
|
||||
//| All the pins must be connected in the same way.
|
||||
//| :param bool pull: ``True`` if an internal pull-up or pull-down should be
|
||||
//| enabled on each pin. A pull-up will be used if ``value_when_pressed`` is ``False``;
|
||||
//| a pull-down will be used if it is ``True``.
|
||||
//| 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 float interval: Scan keys no more often than ``interval`` to allow for debouncing.
|
||||
//| ``interval`` is in float seconds. The default is 0.020 (20 msecs).
|
||||
//| :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.
|
||||
//| """
|
||||
//| ...
|
||||
|
||||
STATIC mp_obj_t keypad_keys_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
keypad_keys_obj_t *self = m_new_obj(keypad_keys_obj_t);
|
||||
self->base.type = &keypad_keys_type;
|
||||
enum { ARG_pins, ARG_value_when_pressed, ARG_pull, ARG_interval, ARG_max_events };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_value_when_pressed, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_BOOL },
|
||||
{ MP_QSTR_pull, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
||||
{ MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL } },
|
||||
{ MP_QSTR_max_events, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
|
||||
};
|
||||
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 pins = args[ARG_pins].u_obj;
|
||||
// mp_obj_len() will be >= 0.
|
||||
const size_t num_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(pins));
|
||||
|
||||
const bool value_when_pressed = args[ARG_value_when_pressed].u_bool;
|
||||
const mp_float_t interval =
|
||||
mp_arg_validate_obj_float_non_negative(args[ARG_interval].u_obj, 0.020f, MP_QSTR_interval);
|
||||
const size_t max_events = (size_t)mp_arg_validate_int_min(args[ARG_max_events].u_int, 1, MP_QSTR_max_events);
|
||||
|
||||
mcu_pin_obj_t *pins_array[num_pins];
|
||||
|
||||
for (mp_uint_t i = 0; i < num_pins; i++) {
|
||||
mcu_pin_obj_t *pin =
|
||||
validate_obj_is_free_pin(mp_obj_subscr(pins, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL));
|
||||
pins_array[i] = pin;
|
||||
}
|
||||
|
||||
common_hal_keypad_keys_construct(self, num_pins, pins_array, value_when_pressed, args[ARG_pull].u_bool, interval, 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 reset(self) -> None:
|
||||
//| """Reset the internal state of the scanner to assume that all keys are now released.
|
||||
//| Any key that is already pressed at the time of this call will therefore immediately cause
|
||||
//| a new key-pressed event to occur.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keys_reset(mp_obj_t self_in) {
|
||||
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
common_hal_keypad_keys_reset(self);
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_reset_obj, keypad_keys_reset);
|
||||
|
||||
//| key_count: int
|
||||
//| """The number of keys that are being scanned. (read-only)
|
||||
//| """
|
||||
//|
|
||||
STATIC mp_obj_t keypad_keys_get_key_count(mp_obj_t self_in) {
|
||||
keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_keypad_keys_get_key_count(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_get_key_count_obj, keypad_keys_get_key_count);
|
||||
|
||||
const mp_obj_property_t keypad_keys_key_count_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&keypad_keys_get_key_count_obj,
|
||||
MP_ROM_NONE,
|
||||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
//| 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);
|
||||
check_for_deinit(self);
|
||||
|
||||
return common_hal_keypad_keys_get_events(self);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_get_events_obj, keypad_keys_get_events);
|
||||
|
||||
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_key_count), MP_ROM_PTR(&keypad_keys_key_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&keypad_keys_reset_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(keypad_keys_locals_dict, keypad_keys_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t keypad_keys_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Keys,
|
||||
.make_new = keypad_keys_make_new,
|
||||
.locals_dict = (mp_obj_t)&keypad_keys_locals_dict,
|
||||
};
|
44
shared-bindings/keypad/Keys.h
Normal file
44
shared-bindings/keypad/Keys.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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_KEYS_H
|
||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYS_H
|
||||
|
||||
#include "py/objlist.h"
|
||||
#include "shared-module/keypad/Keys.h"
|
||||
|
||||
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, mp_float_t interval, 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);
|
||||
size_t common_hal_keypad_keys_get_key_count(keypad_keys_obj_t *self);
|
||||
void common_hal_keypad_keys_reset(keypad_keys_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_KEYS_H
|
213
shared-bindings/keypad/ShiftRegisterKeys.c
Normal file
213
shared-bindings/keypad/ShiftRegisterKeys.c
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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/binary.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/keypad/Event.h"
|
||||
#include "shared-bindings/keypad/ShiftRegisterKeys.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/util.h"
|
||||
|
||||
//| class ShiftRegisterKeys:
|
||||
//| """Manage a set of keys attached to an incoming shift register."""
|
||||
//|
|
||||
//| def __init__(self, *, clock: microcontroller.Pin, data: microcontroller.Pin, latch: microcontroller.Pin, value_to_latch: bool = True, key_count: int, value_when_pressed: bool, interval: float = 0.020, max_events: int = 64) -> None:
|
||||
//| """
|
||||
//| Create a `Keys` object that will scan keys attached to a parallel-in serial-out shift register
|
||||
//| like the 74HC165 or CD4021.
|
||||
//| Note that you may chain shift registers to load in as many values as you need.
|
||||
//|
|
||||
//| Key number 0 is the first (or more properly, the zero-th) bit read. In the
|
||||
//| 74HC165, this bit is labeled ``Q7``. Key number 1 will be the value of ``Q6``, etc.
|
||||
//|
|
||||
//| An `EventQueue` is created when this object is created and is available in the `events` attribute.
|
||||
//|
|
||||
//| :param microcontroller.Pin clock: The shift register clock pin.
|
||||
//| The shift register should clock on a low-to-high transition.
|
||||
//| :param microcontroller.Pin data: the incoming shift register data pin
|
||||
//| :param microcontroller.Pin latch:
|
||||
//| Pin used to latch parallel data going into the shift register.
|
||||
//| :param bool value_to_latch: Pin state to latch data being read.
|
||||
//| ``True`` if the data is latched when ``latch`` goes high
|
||||
//| ``False`` if the data is latched when ``latch goes low.
|
||||
//| The default is ``True``, which is how the 74HC165 operates. The CD4021 latch is the opposite.
|
||||
//| Once the data is latched, it will be shifted out by toggling the clock pin.
|
||||
//| :param int key_count: number of data lines to clock in
|
||||
//| :param bool value_when_pressed: ``True`` if the pin reads high when the key is pressed.
|
||||
//| ``False`` if the pin reads low (is grounded) when the key is pressed.
|
||||
//| :param float interval: Scan keys no more often than ``interval`` to allow for debouncing.
|
||||
//| ``interval`` is in float seconds. The default is 0.020 (20 msecs).
|
||||
//| :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.
|
||||
//| """
|
||||
//| ...
|
||||
|
||||
STATIC mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
keypad_shiftregisterkeys_obj_t *self = m_new_obj(keypad_shiftregisterkeys_obj_t);
|
||||
self->base.type = &keypad_shiftregisterkeys_type;
|
||||
enum { ARG_clock, ARG_data, ARG_latch, ARG_value_to_latch, ARG_key_count, ARG_value_when_pressed, ARG_interval, ARG_max_events };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_clock, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_latch, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_value_to_latch, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
||||
{ MP_QSTR_key_count, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_value_when_pressed, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_BOOL },
|
||||
{ MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_max_events, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
|
||||
};
|
||||
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);
|
||||
|
||||
mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj);
|
||||
mcu_pin_obj_t *data = validate_obj_is_free_pin(args[ARG_data].u_obj);
|
||||
mcu_pin_obj_t *latch = validate_obj_is_free_pin(args[ARG_latch].u_obj);
|
||||
const bool value_to_latch = args[ARG_value_to_latch].u_bool;
|
||||
|
||||
const size_t key_count = (size_t)mp_arg_validate_int_min(args[ARG_key_count].u_int, 1, MP_QSTR_key_count);
|
||||
const bool value_when_pressed = args[ARG_value_when_pressed].u_bool;
|
||||
const mp_float_t interval =
|
||||
mp_arg_validate_obj_float_non_negative(args[ARG_interval].u_obj, 0.020f, MP_QSTR_interval);
|
||||
const size_t max_events = (size_t)mp_arg_validate_int_min(args[ARG_max_events].u_int, 1, MP_QSTR_max_events);
|
||||
|
||||
common_hal_keypad_shiftregisterkeys_construct(
|
||||
self, clock, data, latch, value_to_latch, key_count, value_when_pressed, interval, max_events);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
//| def deinit(self) -> None:
|
||||
//| """Stop scanning and release the pins."""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_shiftregisterkeys_deinit(mp_obj_t self_in) {
|
||||
keypad_shiftregisterkeys_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
common_hal_keypad_shiftregisterkeys_deinit(self);
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_shiftregisterkeys_deinit_obj, keypad_shiftregisterkeys_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_shiftregisterkeys___exit__(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
common_hal_keypad_shiftregisterkeys_deinit(args[0]);
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_shiftregisterkeys___exit___obj, 4, 4, keypad_shiftregisterkeys___exit__);
|
||||
|
||||
STATIC void check_for_deinit(keypad_shiftregisterkeys_obj_t *self) {
|
||||
if (common_hal_keypad_shiftregisterkeys_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
}
|
||||
|
||||
//| def reset(self) -> None:
|
||||
//| """Reset the internal state of the scanner to assume that all keys are now released.
|
||||
//| Any key that is already pressed at the time of this call will therefore immediately cause
|
||||
//| a new key-pressed event to occur.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t keypad_shiftregisterkeys_reset(mp_obj_t self_in) {
|
||||
keypad_shiftregisterkeys_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
common_hal_keypad_shiftregisterkeys_reset(self);
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_shiftregisterkeys_reset_obj, keypad_shiftregisterkeys_reset);
|
||||
|
||||
//| key_count: int
|
||||
//| """The number of keys that are being scanned. (read-only)
|
||||
//| """
|
||||
//|
|
||||
STATIC mp_obj_t keypad_shiftregisterkeys_get_key_count(mp_obj_t self_in) {
|
||||
keypad_shiftregisterkeys_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_keypad_shiftregisterkeys_get_key_count(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_shiftregisterkeys_get_key_count_obj, keypad_shiftregisterkeys_get_key_count);
|
||||
|
||||
const mp_obj_property_t keypad_shiftregisterkeys_key_count_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&keypad_shiftregisterkeys_get_key_count_obj,
|
||||
MP_ROM_NONE,
|
||||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
//| events: EventQueue
|
||||
//| """The `EventQueue` associated with this `Keys` object. (read-only)
|
||||
//| """
|
||||
//|
|
||||
STATIC mp_obj_t keypad_shiftregisterkeys_get_events(mp_obj_t self_in) {
|
||||
keypad_shiftregisterkeys_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
|
||||
return common_hal_keypad_shiftregisterkeys_get_events(self);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(keypad_shiftregisterkeys_get_events_obj, keypad_shiftregisterkeys_get_events);
|
||||
|
||||
const mp_obj_property_t keypad_shiftregisterkeys_events_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&keypad_shiftregisterkeys_get_events_obj,
|
||||
MP_ROM_NONE,
|
||||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
STATIC const mp_rom_map_elem_t keypad_shiftregisterkeys_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_shiftregisterkeys_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_shiftregisterkeys___exit___obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_shiftregisterkeys_events_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_key_count), MP_ROM_PTR(&keypad_shiftregisterkeys_key_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&keypad_shiftregisterkeys_reset_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(keypad_shiftregisterkeys_locals_dict, keypad_shiftregisterkeys_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t keypad_shiftregisterkeys_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_ShiftRegisterKeys,
|
||||
.make_new = keypad_shiftregisterkeys_make_new,
|
||||
.locals_dict = (mp_obj_t)&keypad_shiftregisterkeys_locals_dict,
|
||||
};
|
44
shared-bindings/keypad/ShiftRegisterKeys.h
Normal file
44
shared-bindings/keypad/ShiftRegisterKeys.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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_SHIFTREGISTERKEYS_H
|
||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_SHIFTREGISTERKEYS_H
|
||||
|
||||
#include "py/objlist.h"
|
||||
#include "shared-module/keypad/ShiftRegisterKeys.h"
|
||||
|
||||
extern const mp_obj_type_t keypad_shiftregisterkeys_type;
|
||||
|
||||
void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_t *self, mcu_pin_obj_t *clock_pin, mcu_pin_obj_t *data_pin, mcu_pin_obj_t *latch_pin, bool value_to_latch, size_t key_count, bool value_when_pressed, mp_float_t interval, size_t max_events);
|
||||
|
||||
void common_hal_keypad_shiftregisterkeys_deinit(keypad_shiftregisterkeys_obj_t *self);
|
||||
bool common_hal_keypad_shiftregisterkeys_deinited(keypad_shiftregisterkeys_obj_t *self);
|
||||
|
||||
mp_obj_t common_hal_keypad_shiftregisterkeys_get_events(keypad_shiftregisterkeys_obj_t *self);
|
||||
size_t common_hal_keypad_shiftregisterkeys_get_key_count(keypad_shiftregisterkeys_obj_t *self);
|
||||
void common_hal_keypad_shiftregisterkeys_reset(keypad_shiftregisterkeys_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_SHIFTREGISTERKEYS_H
|
59
shared-bindings/keypad/__init__.c
Normal file
59
shared-bindings/keypad/__init__.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2011 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/obj.h"
|
||||
|
||||
#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"
|
||||
#include "shared-bindings/keypad/ShiftRegisterKeys.h"
|
||||
|
||||
//| """Support for scanning keys and key matrices
|
||||
//|
|
||||
//| The `keypad` module provides native support to scan sets of keys or buttons,
|
||||
//| connected independently to individual pins,
|
||||
//| connected to a shift register,
|
||||
//| or connected in a row-and-column matrix.
|
||||
//| """
|
||||
//|
|
||||
|
||||
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_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) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ShiftRegisterKeys), MP_OBJ_FROM_PTR(&keypad_shiftregisterkeys_type) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_MUTABLE_DICT(keypad_module_globals, keypad_module_globals_table);
|
||||
|
||||
const mp_obj_module_t keypad_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&keypad_module_globals,
|
||||
};
|
41
shared-bindings/keypad/__init__.h
Normal file
41
shared-bindings/keypad/__init__.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 SHARED_BINDINGS_KEYPAD_H
|
||||
#define SHARED_BINDINGS_KEYPAD_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objtuple.h"
|
||||
#include "shared-module/keypad/__init__.h"
|
||||
|
||||
extern mp_obj_tuple_t common_hal_keypad_devices;
|
||||
|
||||
void keypad_set_devices(mp_obj_t devices);
|
||||
|
||||
bool common_hal_keypad_disable(void);
|
||||
bool common_hal_keypad_enable(const mp_obj_t devices_seq);
|
||||
|
||||
#endif // SHARED_BINDINGS_KEYPAD_H
|
44
shared-module/keypad/Event.c
Normal file
44
shared-module/keypad/Event.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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-module/keypad/Event.h"
|
||||
|
||||
void common_hal_keypad_event_construct(keypad_event_obj_t *self, mp_int_t key_number, bool pressed) {
|
||||
self->key_number = key_number;
|
||||
self->pressed = pressed;
|
||||
}
|
||||
|
||||
mp_int_t common_hal_keypad_event_get_key_number(keypad_event_obj_t *self) {
|
||||
return self->key_number;
|
||||
}
|
||||
|
||||
bool common_hal_keypad_event_get_pressed(keypad_event_obj_t *self) {
|
||||
return self->pressed;
|
||||
}
|
||||
|
||||
bool common_hal_keypad_event_get_released(keypad_event_obj_t *self) {
|
||||
return !self->pressed;
|
||||
}
|
39
shared-module/keypad/Event.h
Normal file
39
shared-module/keypad/Event.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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_EVENT_H
|
||||
#define MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_EVENT_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
uint16_t key_number;
|
||||
bool pressed;
|
||||
} keypad_event_obj_t;
|
||||
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_EVENT_H
|
94
shared-module/keypad/EventQueue.c
Normal file
94
shared-module/keypad/EventQueue.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
// Key number is lower 15 bits of a 16-bit value.
|
||||
#define EVENT_PRESSED (1 << 15)
|
||||
#define EVENT_KEY_NUM_MASK ((1 << 15) - 1)
|
||||
|
||||
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);
|
||||
self->overflowed = false;
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_keypad_eventqueue_get(keypad_eventqueue_obj_t *self) {
|
||||
int encoded_event = ringbuf_get16(&self->encoded_events);
|
||||
if (encoded_event == -1) {
|
||||
return MP_ROM_NONE;
|
||||
}
|
||||
|
||||
keypad_event_obj_t *event = m_new_obj(keypad_event_obj_t);
|
||||
event->base.type = &keypad_event_type;
|
||||
common_hal_keypad_event_construct(event, encoded_event & EVENT_KEY_NUM_MASK, encoded_event & EVENT_PRESSED);
|
||||
return MP_OBJ_FROM_PTR(event);
|
||||
}
|
||||
|
||||
bool common_hal_keypad_eventqueue_get_into(keypad_eventqueue_obj_t *self, keypad_event_obj_t *event) {
|
||||
int encoded_event = ringbuf_get16(&self->encoded_events);
|
||||
if (encoded_event == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// "Construct" using the existing event.
|
||||
common_hal_keypad_event_construct(event, encoded_event & EVENT_KEY_NUM_MASK, encoded_event & EVENT_PRESSED);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool common_hal_keypad_eventqueue_get_overflowed(keypad_eventqueue_obj_t *self) {
|
||||
return self->overflowed;
|
||||
}
|
||||
|
||||
void common_hal_keypad_eventqueue_set_overflowed(keypad_eventqueue_obj_t *self, bool overflowed) {
|
||||
self->overflowed = overflowed;
|
||||
}
|
||||
|
||||
void common_hal_keypad_eventqueue_clear(keypad_eventqueue_obj_t *self) {
|
||||
ringbuf_clear(&self->encoded_events);
|
||||
common_hal_keypad_eventqueue_set_overflowed(self, false);
|
||||
}
|
||||
|
||||
size_t common_hal_keypad_eventqueue_get_length(keypad_eventqueue_obj_t *self) {
|
||||
return ringbuf_num_filled(&self->encoded_events);
|
||||
}
|
||||
|
||||
bool keypad_eventqueue_record(keypad_eventqueue_obj_t *self, mp_uint_t key_number, bool pressed) {
|
||||
if (ringbuf_num_empty(&self->encoded_events) == 0) {
|
||||
// Queue is full. Set the overflow flag. The caller will decide what else to do.
|
||||
common_hal_keypad_eventqueue_set_overflowed(self, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t encoded_event = key_number & EVENT_KEY_NUM_MASK;
|
||||
if (pressed) {
|
||||
encoded_event |= EVENT_PRESSED;
|
||||
}
|
||||
ringbuf_put16(&self->encoded_events, encoded_event);
|
||||
|
||||
return true;
|
||||
}
|
41
shared-module/keypad/EventQueue.h
Normal file
41
shared-module/keypad/EventQueue.h
Normal 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_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;
|
||||
bool overflowed;
|
||||
} keypad_eventqueue_obj_t;
|
||||
|
||||
bool keypad_eventqueue_record(keypad_eventqueue_obj_t *self, mp_uint_t key_number, bool pressed);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_EVENTQUEUE_H
|
182
shared-module/keypad/KeyMatrix.c
Normal file
182
shared-module/keypad/KeyMatrix.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.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"
|
||||
|
||||
static mp_uint_t row_column_to_key_number(keypad_keymatrix_obj_t *self, mp_uint_t row, mp_uint_t column) {
|
||||
return row * self->column_digitalinouts->len + column;
|
||||
}
|
||||
|
||||
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_column_pins, mcu_pin_obj_t *column_pins[], bool columns_to_anodes, mp_float_t interval, size_t max_events) {
|
||||
|
||||
mp_obj_t row_dios[num_row_pins];
|
||||
for (size_t row = 0; row < num_row_pins; row++) {
|
||||
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[row]);
|
||||
common_hal_digitalio_digitalinout_switch_to_input(dio, columns_to_anodes ? PULL_UP : PULL_DOWN);
|
||||
row_dios[row] = dio;
|
||||
}
|
||||
self->row_digitalinouts = mp_obj_new_tuple(num_row_pins, row_dios);
|
||||
|
||||
mp_obj_t column_dios[num_column_pins];
|
||||
for (size_t column = 0; column < num_column_pins; column++) {
|
||||
digitalio_digitalinout_obj_t *dio = m_new_obj(digitalio_digitalinout_obj_t);
|
||||
dio->base.type = &digitalio_digitalinout_type;
|
||||
common_hal_digitalio_digitalinout_construct(dio, column_pins[column]);
|
||||
common_hal_digitalio_digitalinout_switch_to_input(dio, columns_to_anodes ? PULL_UP : PULL_DOWN);
|
||||
column_dios[column] = dio;
|
||||
}
|
||||
self->column_digitalinouts = mp_obj_new_tuple(num_column_pins, column_dios);
|
||||
|
||||
self->currently_pressed = (bool *)gc_alloc(sizeof(bool) * num_row_pins * num_column_pins, false, false);
|
||||
self->previously_pressed = (bool *)gc_alloc(sizeof(bool) * num_row_pins * num_column_pins, false, false);
|
||||
|
||||
self->columns_to_anodes = columns_to_anodes;
|
||||
|
||||
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;
|
||||
|
||||
self->interval_ticks = (mp_uint_t)(interval * 1024); // interval * 1000 * (1024/1000)
|
||||
self->last_scan_ticks = port_get_raw_ticks(NULL);
|
||||
|
||||
// Add self to the list of active keypad scanners.
|
||||
keypad_register_scanner((keypad_scanner_obj_t *)self);
|
||||
|
||||
supervisor_enable_tick();
|
||||
}
|
||||
|
||||
void common_hal_keypad_keymatrix_deinit(keypad_keymatrix_obj_t *self) {
|
||||
if (common_hal_keypad_keymatrix_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove self from the list of active keypad scanners first.
|
||||
keypad_deregister_scanner((keypad_scanner_obj_t *)self);
|
||||
|
||||
for (size_t row = 0; row < common_hal_keypad_keymatrix_get_row_count(self); row++) {
|
||||
common_hal_digitalio_digitalinout_deinit(self->row_digitalinouts->items[row]);
|
||||
}
|
||||
self->row_digitalinouts = MP_ROM_NONE;
|
||||
|
||||
for (size_t column = 0; column < common_hal_keypad_keymatrix_get_column_count(self); column++) {
|
||||
common_hal_digitalio_digitalinout_deinit(self->column_digitalinouts->items[column]);
|
||||
}
|
||||
self->column_digitalinouts = MP_ROM_NONE;
|
||||
}
|
||||
|
||||
bool common_hal_keypad_keymatrix_deinited(keypad_keymatrix_obj_t *self) {
|
||||
return self->row_digitalinouts == MP_ROM_NONE;
|
||||
}
|
||||
|
||||
size_t common_hal_keypad_keymatrix_get_key_count(keypad_keymatrix_obj_t *self) {
|
||||
return common_hal_keypad_keymatrix_get_row_count(self) * common_hal_keypad_keymatrix_get_column_count(self);
|
||||
}
|
||||
|
||||
size_t common_hal_keypad_keymatrix_get_row_count(keypad_keymatrix_obj_t *self) {
|
||||
return self->row_digitalinouts->len;
|
||||
}
|
||||
|
||||
size_t common_hal_keypad_keymatrix_get_column_count(keypad_keymatrix_obj_t *self) {
|
||||
return self->column_digitalinouts->len;
|
||||
}
|
||||
|
||||
mp_uint_t common_hal_keypad_keymatrix_row_column_to_key_number(keypad_keymatrix_obj_t *self, mp_uint_t row, mp_uint_t column) {
|
||||
return row_column_to_key_number(self, row, column);
|
||||
}
|
||||
|
||||
void common_hal_keypad_keymatrix_key_number_to_row_column(keypad_keymatrix_obj_t *self, mp_uint_t key_number, mp_uint_t *row, mp_uint_t *column) {
|
||||
const size_t num_columns = common_hal_keypad_keymatrix_get_column_count(self);
|
||||
*row = key_number / num_columns;
|
||||
*column = key_number % num_columns;
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_keypad_keymatrix_get_events(keypad_keymatrix_obj_t *self) {
|
||||
return MP_OBJ_FROM_PTR(self->events);
|
||||
}
|
||||
|
||||
void common_hal_keypad_keymatrix_reset(keypad_keymatrix_obj_t *self) {
|
||||
const size_t key_count = common_hal_keypad_keymatrix_get_key_count(self);
|
||||
|
||||
supervisor_acquire_lock(&keypad_scanners_linked_list_lock);
|
||||
memset(self->previously_pressed, false, key_count);
|
||||
memset(self->currently_pressed, false, key_count);
|
||||
supervisor_release_lock(&keypad_scanners_linked_list_lock);
|
||||
}
|
||||
|
||||
void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self) {
|
||||
uint64_t now = port_get_raw_ticks(NULL);
|
||||
if (now - self->last_scan_ticks < self->interval_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 or pull-down,
|
||||
// depending on the diode orientation.
|
||||
for (size_t row = 0; row < common_hal_keypad_keymatrix_get_row_count(self); row++) {
|
||||
// Switch this row to an output and set level appropriately
|
||||
// Set low if columns_to_anodes is true, else set high.
|
||||
common_hal_digitalio_digitalinout_switch_to_output(
|
||||
self->row_digitalinouts->items[row], !self->columns_to_anodes, DRIVE_MODE_PUSH_PULL);
|
||||
|
||||
for (size_t column = 0; column < common_hal_keypad_keymatrix_get_column_count(self); column++) {
|
||||
mp_uint_t key_number = row_column_to_key_number(self, row, column);
|
||||
const bool previous = self->currently_pressed[key_number];
|
||||
self->previously_pressed[key_number] = previous;
|
||||
|
||||
// Get the current state, by reading whether the column got pulled to the row value or not.
|
||||
// If low and columns_to_anodes is true, the key is pressed.
|
||||
// If high and columns_to_anodes is false, the key is pressed.
|
||||
const bool current =
|
||||
common_hal_digitalio_digitalinout_get_value(self->column_digitalinouts->items[column]) !=
|
||||
self->columns_to_anodes;
|
||||
self->currently_pressed[key_number] = current;
|
||||
|
||||
// Record any transitions.
|
||||
if (previous != current) {
|
||||
keypad_eventqueue_record(self->events, key_number, current);
|
||||
}
|
||||
}
|
||||
|
||||
// Switch the row back to an input, pulled appropriately
|
||||
common_hal_digitalio_digitalinout_switch_to_input(
|
||||
self->row_digitalinouts->items[row], self->columns_to_anodes ? PULL_UP : PULL_DOWN);
|
||||
}
|
||||
}
|
53
shared-module/keypad/KeyMatrix.h
Normal file
53
shared-module/keypad/KeyMatrix.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 "py/obj.h"
|
||||
#include "py/objtuple.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;
|
||||
// All scanners have a next field here, to keep a linked list of active scanners.
|
||||
keypad_scanner_obj_t *next;
|
||||
mp_obj_tuple_t *row_digitalinouts;
|
||||
mp_obj_tuple_t *column_digitalinouts;
|
||||
mp_uint_t interval_ticks;
|
||||
uint64_t last_scan_ticks;
|
||||
bool *previously_pressed;
|
||||
bool *currently_pressed;
|
||||
keypad_eventqueue_obj_t *events;
|
||||
bool columns_to_anodes;
|
||||
} keypad_keymatrix_obj_t;
|
||||
|
||||
void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_KEYMATRIX_H
|
133
shared-module/keypad/Keys.c
Normal file
133
shared-module/keypad/Keys.c
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.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"
|
||||
|
||||
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, mp_float_t interval, size_t max_events) {
|
||||
mp_obj_t dios[num_pins];
|
||||
|
||||
for (size_t i = 0; i < num_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, pins[i]);
|
||||
if (pull) {
|
||||
common_hal_digitalio_digitalinout_set_pull(dio, value_when_pressed ? PULL_DOWN : PULL_UP);
|
||||
}
|
||||
dios[i] = dio;
|
||||
}
|
||||
|
||||
self->digitalinouts = mp_obj_new_tuple(num_pins, dios);
|
||||
self->currently_pressed = (bool *)gc_alloc(sizeof(bool) * num_pins, false, false);
|
||||
self->previously_pressed = (bool *)gc_alloc(sizeof(bool) * num_pins, false, false);
|
||||
self->value_when_pressed = value_when_pressed;
|
||||
|
||||
self->interval_ticks = (mp_uint_t)(interval * 1024); // interval * 1000 * (1024/1000)
|
||||
self->last_scan_ticks = port_get_raw_ticks(NULL);
|
||||
|
||||
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);
|
||||
|
||||
supervisor_enable_tick();
|
||||
}
|
||||
|
||||
void common_hal_keypad_keys_deinit(keypad_keys_obj_t *self) {
|
||||
if (common_hal_keypad_keys_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove self from the list of active keypad scanners first.
|
||||
keypad_deregister_scanner((keypad_scanner_obj_t *)self);
|
||||
|
||||
for (size_t key = 0; key < common_hal_keypad_keys_get_key_count(self); key++) {
|
||||
common_hal_digitalio_digitalinout_deinit(self->digitalinouts->items[key]);
|
||||
}
|
||||
self->digitalinouts = MP_ROM_NONE;
|
||||
|
||||
}
|
||||
|
||||
bool common_hal_keypad_keys_deinited(keypad_keys_obj_t *self) {
|
||||
return self->digitalinouts == MP_ROM_NONE;
|
||||
}
|
||||
|
||||
size_t common_hal_keypad_keys_get_key_count(keypad_keys_obj_t *self) {
|
||||
return self->digitalinouts->len;
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_keypad_keys_get_events(keypad_keys_obj_t *self) {
|
||||
return MP_OBJ_FROM_PTR(self->events);
|
||||
}
|
||||
|
||||
void common_hal_keypad_keys_reset(keypad_keys_obj_t *self) {
|
||||
const size_t key_count = common_hal_keypad_keys_get_key_count(self);
|
||||
|
||||
supervisor_acquire_lock(&keypad_scanners_linked_list_lock);
|
||||
memset(self->previously_pressed, false, key_count);
|
||||
memset(self->currently_pressed, false, key_count);
|
||||
supervisor_release_lock(&keypad_scanners_linked_list_lock);
|
||||
}
|
||||
|
||||
void keypad_keys_scan(keypad_keys_obj_t *self) {
|
||||
uint64_t now = port_get_raw_ticks(NULL);
|
||||
if (now - self->last_scan_ticks < self->interval_ticks) {
|
||||
// Too soon. Wait longer to debounce.
|
||||
return;
|
||||
}
|
||||
|
||||
self->last_scan_ticks = now;
|
||||
|
||||
const size_t key_count = common_hal_keypad_keys_get_key_count(self);
|
||||
|
||||
for (mp_uint_t key_number = 0; key_number < key_count; key_number++) {
|
||||
// Remember the previous up/down state.
|
||||
const bool previous = self->currently_pressed[key_number];
|
||||
self->previously_pressed[key_number] = previous;
|
||||
|
||||
// Get the current state.
|
||||
const bool current =
|
||||
common_hal_digitalio_digitalinout_get_value(self->digitalinouts->items[key_number]) ==
|
||||
self->value_when_pressed;
|
||||
self->currently_pressed[key_number] = current;
|
||||
|
||||
// Record any transitions.
|
||||
if (previous != current) {
|
||||
keypad_eventqueue_record(self->events, key_number, current);
|
||||
}
|
||||
}
|
||||
}
|
52
shared-module/keypad/Keys.h
Normal file
52
shared-module/keypad/Keys.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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_KEYS_H
|
||||
#define MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_KEYS_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objtuple.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;
|
||||
// All scanners have a next field here, to keep a linked list of active scanners.
|
||||
keypad_scanner_obj_t *next;
|
||||
mp_obj_tuple_t *digitalinouts;
|
||||
mp_uint_t interval_ticks;
|
||||
uint64_t last_scan_ticks;
|
||||
bool *previously_pressed;
|
||||
bool *currently_pressed;
|
||||
keypad_eventqueue_obj_t *events;
|
||||
bool value_when_pressed;
|
||||
} keypad_keys_obj_t;
|
||||
|
||||
void keypad_keys_scan(keypad_keys_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_KEYS_H
|
156
shared-module/keypad/ShiftRegisterKeys.c
Normal file
156
shared-module/keypad/ShiftRegisterKeys.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
#include "shared-bindings/keypad/EventQueue.h"
|
||||
#include "shared-bindings/keypad/ShiftRegisterKeys.h"
|
||||
#include "shared-bindings/keypad/__init__.h"
|
||||
#include "supervisor/port.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
|
||||
void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_t *self, mcu_pin_obj_t *clock_pin, mcu_pin_obj_t *data_pin, mcu_pin_obj_t *latch_pin, bool value_to_latch, size_t key_count, bool value_when_pressed, mp_float_t interval, size_t max_events) {
|
||||
|
||||
digitalio_digitalinout_obj_t *clock = m_new_obj(digitalio_digitalinout_obj_t);
|
||||
clock->base.type = &digitalio_digitalinout_type;
|
||||
common_hal_digitalio_digitalinout_construct(clock, clock_pin);
|
||||
common_hal_digitalio_digitalinout_switch_to_output(clock, false, DRIVE_MODE_PUSH_PULL);
|
||||
self->clock = clock;
|
||||
|
||||
digitalio_digitalinout_obj_t *data = m_new_obj(digitalio_digitalinout_obj_t);
|
||||
data->base.type = &digitalio_digitalinout_type;
|
||||
common_hal_digitalio_digitalinout_construct(data, data_pin);
|
||||
common_hal_digitalio_digitalinout_switch_to_input(data, PULL_NONE);
|
||||
self->data = data;
|
||||
|
||||
digitalio_digitalinout_obj_t *latch = m_new_obj(digitalio_digitalinout_obj_t);
|
||||
latch->base.type = &digitalio_digitalinout_type;
|
||||
common_hal_digitalio_digitalinout_construct(latch, latch_pin);
|
||||
common_hal_digitalio_digitalinout_switch_to_output(latch, true, DRIVE_MODE_PUSH_PULL);
|
||||
self->latch = latch;
|
||||
self->value_to_latch = value_to_latch;
|
||||
|
||||
self->currently_pressed = (bool *)gc_alloc(sizeof(bool) * key_count, false, false);
|
||||
self->previously_pressed = (bool *)gc_alloc(sizeof(bool) * key_count, false, false);
|
||||
self->value_when_pressed = value_when_pressed;
|
||||
self->key_count = key_count;
|
||||
|
||||
self->interval_ticks = (mp_uint_t)(interval * 1024); // interval * 1000 * (1024/1000)
|
||||
self->last_scan_ticks = port_get_raw_ticks(NULL);
|
||||
|
||||
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);
|
||||
|
||||
supervisor_enable_tick();
|
||||
}
|
||||
|
||||
void common_hal_keypad_shiftregisterkeys_deinit(keypad_shiftregisterkeys_obj_t *self) {
|
||||
if (common_hal_keypad_shiftregisterkeys_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove self from the list of active keypad scanners first.
|
||||
keypad_deregister_scanner((keypad_scanner_obj_t *)self);
|
||||
|
||||
|
||||
common_hal_digitalio_digitalinout_deinit(self->clock);
|
||||
self->clock = MP_ROM_NONE;
|
||||
|
||||
common_hal_digitalio_digitalinout_deinit(self->data);
|
||||
self->data = MP_ROM_NONE;
|
||||
|
||||
common_hal_digitalio_digitalinout_deinit(self->latch);
|
||||
self->latch = MP_ROM_NONE;
|
||||
}
|
||||
|
||||
bool common_hal_keypad_shiftregisterkeys_deinited(keypad_shiftregisterkeys_obj_t *self) {
|
||||
return self->clock == MP_ROM_NONE;
|
||||
}
|
||||
|
||||
size_t common_hal_keypad_shiftregisterkeys_get_key_count(keypad_shiftregisterkeys_obj_t *self) {
|
||||
return self->key_count;
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_keypad_shiftregisterkeys_get_events(keypad_shiftregisterkeys_obj_t *self) {
|
||||
return MP_OBJ_FROM_PTR(self->events);
|
||||
}
|
||||
|
||||
void common_hal_keypad_shiftregisterkeys_reset(keypad_shiftregisterkeys_obj_t *self) {
|
||||
const size_t key_count = common_hal_keypad_shiftregisterkeys_get_key_count(self);
|
||||
|
||||
supervisor_acquire_lock(&keypad_scanners_linked_list_lock);
|
||||
memset(self->previously_pressed, false, key_count);
|
||||
memset(self->currently_pressed, false, key_count);
|
||||
supervisor_release_lock(&keypad_scanners_linked_list_lock);
|
||||
}
|
||||
|
||||
void keypad_shiftregisterkeys_scan(keypad_shiftregisterkeys_obj_t *self) {
|
||||
uint64_t now = port_get_raw_ticks(NULL);
|
||||
if (now - self->last_scan_ticks < self->interval_ticks) {
|
||||
// Too soon. Wait longer to debounce.
|
||||
return;
|
||||
}
|
||||
|
||||
self->last_scan_ticks = now;
|
||||
|
||||
// Latch (freeze) the current state of the input pins.
|
||||
common_hal_digitalio_digitalinout_set_value(self->latch, self->value_to_latch);
|
||||
|
||||
const size_t key_count = common_hal_keypad_shiftregisterkeys_get_key_count(self);
|
||||
|
||||
for (mp_uint_t key_number = 0; key_number < key_count; key_number++) {
|
||||
// Zero-th data appears on on the data pin immediately, without shifting.
|
||||
common_hal_digitalio_digitalinout_set_value(self->clock, false);
|
||||
|
||||
// Remember the previous up/down state.
|
||||
const bool previous = self->currently_pressed[key_number];
|
||||
self->previously_pressed[key_number] = previous;
|
||||
|
||||
// Get the current state.
|
||||
const bool current =
|
||||
common_hal_digitalio_digitalinout_get_value(self->data) == self->value_when_pressed;
|
||||
self->currently_pressed[key_number] = current;
|
||||
|
||||
// Trigger a shift to get the next bit.
|
||||
common_hal_digitalio_digitalinout_set_value(self->clock, true);
|
||||
|
||||
// Record any transitions.
|
||||
if (previous != current) {
|
||||
keypad_eventqueue_record(self->events, key_number, current);
|
||||
}
|
||||
}
|
||||
|
||||
// Start reading the input pins again.
|
||||
common_hal_digitalio_digitalinout_set_value(self->latch, !self->value_to_latch);
|
||||
}
|
56
shared-module/keypad/ShiftRegisterKeys.h
Normal file
56
shared-module/keypad/ShiftRegisterKeys.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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_SHIFTREGISTERKEYS_H
|
||||
#define MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_SHIFTREGISTERKEYS_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objtuple.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;
|
||||
// All scanners have a next field here, to keep a linked list of active scanners.
|
||||
keypad_scanner_obj_t *next;
|
||||
digitalio_digitalinout_obj_t *clock;
|
||||
digitalio_digitalinout_obj_t *data;
|
||||
digitalio_digitalinout_obj_t *latch;
|
||||
size_t key_count;
|
||||
mp_uint_t interval_ticks;
|
||||
uint64_t last_scan_ticks;
|
||||
bool *previously_pressed;
|
||||
bool *currently_pressed;
|
||||
keypad_eventqueue_obj_t *events;
|
||||
bool value_when_pressed;
|
||||
bool value_to_latch;
|
||||
} keypad_shiftregisterkeys_obj_t;
|
||||
|
||||
void keypad_shiftregisterkeys_scan(keypad_shiftregisterkeys_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_KEYPAD_SHIFTREGISTERKEYS_H
|
96
shared-module/keypad/__init__.c
Normal file
96
shared-module/keypad/__init__.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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/keypad/Keys.h"
|
||||
#include "shared-bindings/keypad/KeyMatrix.h"
|
||||
#include "shared-bindings/keypad/ShiftRegisterKeys.h"
|
||||
#include "supervisor/shared/lock.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
|
||||
supervisor_lock_t keypad_scanners_linked_list_lock;
|
||||
|
||||
void keypad_tick(void) {
|
||||
// Fast path. Return immediately there are no scanners.
|
||||
if (!MP_STATE_VM(keypad_scanners_linked_list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip scanning if someone else has the lock. Don't wait for the lock.
|
||||
if (supervisor_try_lock(&keypad_scanners_linked_list_lock)) {
|
||||
mp_obj_t scanner = MP_STATE_VM(keypad_scanners_linked_list);
|
||||
while (scanner) {
|
||||
if (mp_obj_is_type(scanner, &keypad_keys_type)) {
|
||||
keypad_keys_scan((keypad_keys_obj_t *)scanner);
|
||||
} else if (mp_obj_is_type(scanner, &keypad_keymatrix_type)) {
|
||||
keypad_keymatrix_scan((keypad_keymatrix_obj_t *)scanner);
|
||||
} else if (mp_obj_is_type(scanner, &keypad_shiftregisterkeys_type)) {
|
||||
keypad_shiftregisterkeys_scan((keypad_shiftregisterkeys_obj_t *)scanner);
|
||||
}
|
||||
|
||||
scanner = ((keypad_scanner_obj_t *)scanner)->next;
|
||||
}
|
||||
supervisor_release_lock(&keypad_scanners_linked_list_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void keypad_reset(void) {
|
||||
if (MP_STATE_VM(keypad_scanners_linked_list)) {
|
||||
supervisor_disable_tick();
|
||||
}
|
||||
|
||||
MP_STATE_VM(keypad_scanners_linked_list) = NULL;
|
||||
keypad_scanners_linked_list_lock = false;
|
||||
}
|
||||
|
||||
// Register a Keys, KeyMatrix, etc. that will be scanned in the background
|
||||
void keypad_register_scanner(keypad_scanner_obj_t *scanner) {
|
||||
supervisor_acquire_lock(&keypad_scanners_linked_list_lock);
|
||||
scanner->next = MP_STATE_VM(keypad_scanners_linked_list);
|
||||
MP_STATE_VM(keypad_scanners_linked_list) = scanner;
|
||||
supervisor_release_lock(&keypad_scanners_linked_list_lock);
|
||||
}
|
||||
|
||||
// Remove scanner from the list of active scanners.
|
||||
void keypad_deregister_scanner(keypad_scanner_obj_t *scanner) {
|
||||
supervisor_acquire_lock(&keypad_scanners_linked_list_lock);
|
||||
if (MP_STATE_VM(keypad_scanners_linked_list) == scanner) {
|
||||
// Scanner is at the front; splice it out.
|
||||
MP_STATE_VM(keypad_scanners_linked_list) = scanner->next;
|
||||
scanner->next = NULL;
|
||||
} else {
|
||||
keypad_scanner_obj_t *current = MP_STATE_VM(keypad_scanners_linked_list);
|
||||
while (current) {
|
||||
if (current->next == scanner) {
|
||||
// Splice myself out.
|
||||
current->next = scanner->next;
|
||||
scanner->next = NULL;
|
||||
break;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
supervisor_release_lock(&keypad_scanners_linked_list_lock);
|
||||
}
|
50
shared-module/keypad/__init__.h
Normal file
50
shared-module/keypad/__init__.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 SHARED_MODULE_KEYPAD_H
|
||||
#define SHARED_MODULE_KEYPAD_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "supervisor/shared/lock.h"
|
||||
|
||||
// All scanners must have a next field immediately following base.
|
||||
// This is an ad hoc "superclass" struct for scanners, though they do
|
||||
// not actually have a superclass relationship.
|
||||
typedef struct _keypad_scanner_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct _keypad_scanner_obj_t *next;
|
||||
} keypad_scanner_obj_t;
|
||||
|
||||
extern supervisor_lock_t keypad_scanners_linked_list_lock;
|
||||
|
||||
void keypad_tick(void);
|
||||
void keypad_reset(void);
|
||||
|
||||
void keypad_register_scanner(keypad_scanner_obj_t *scanner);
|
||||
void keypad_deregister_scanner(keypad_scanner_obj_t *scanner);
|
||||
|
||||
|
||||
#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,7 +7,8 @@ SRC_SUPERVISOR = \
|
||||
supervisor/shared/cpu.c \
|
||||
supervisor/shared/filesystem.c \
|
||||
supervisor/shared/flash.c \
|
||||
supervisor/shared/memory.c \
|
||||
supervisor/shared/lock.c \
|
||||
supervisor/shared/memory.c \
|
||||
supervisor/shared/micropython.c \
|
||||
supervisor/shared/safe_mode.c \
|
||||
supervisor/shared/stack.c \
|
||||
|
Loading…
Reference in New Issue
Block a user