Skip to content

Commit 16a6203

Browse files
authored
Merge pull request #9035 from CDarius/cardputer_keyboard
Add Cardputer keyboard support
2 parents 84e937f + d8a4c50 commit 16a6203

File tree

10 files changed

+557
-0
lines changed

10 files changed

+557
-0
lines changed

docs/shared_bindings_matrix.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"keypad.KeyMatrix": "CIRCUITPY_KEYPAD_KEYMATRIX",
7979
"keypad.Keys": "CIRCUITPY_KEYPAD_KEYS",
8080
"keypad.ShiftRegisterKeys": "CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS",
81+
"keypad_demux.DemuxKeyMatrix": "CIRCUITPY_KEYPAD_DEMUX",
8182
"os.getenv": "CIRCUITPY_OS_GETENV",
8283
"select": "MICROPY_PY_SELECT_SELECT",
8384
"sys": "CIRCUITPY_SYS",

ports/atmel-samd/mpconfigport.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ CIRCUITPY_ROTARYIO_SOFTENCODER = 1
1111
CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 1
1212
CIRCUITPY_LTO = 1
1313

14+
CIRCUITPY_KEYPAD_DEMUX ?= 0
15+
1416
######################################################################
1517
# Put samd21-only choices here.
1618

py/circuitpy_defns.mk

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ endif
252252
ifeq ($(CIRCUITPY_KEYPAD),1)
253253
SRC_PATTERNS += keypad/%
254254
endif
255+
ifeq ($(CIRCUITPY_KEYPAD_DEMUX),1)
256+
SRC_PATTERNS += keypad_demux/%
257+
endif
255258
ifeq ($(CIRCUITPY_LOCALE),1)
256259
SRC_PATTERNS += locale/%
257260
endif
@@ -739,6 +742,12 @@ SRC_SHARED_MODULE_ALL += \
739742
ssl/SSLSocket.c
740743
endif
741744

745+
ifeq ($(CIRCUITPY_KEYPAD_DEMUX),1)
746+
SRC_SHARED_MODULE_ALL += \
747+
keypad_demux/__init__.c \
748+
keypad_demux/DemuxKeyMatrix.c
749+
endif
750+
742751
# If supporting _bleio via HCI, make devices/ble_hci/common-hal/_bleio be includable,
743752
# and use C source files in devices/ble_hci/common-hal.
744753
ifeq ($(CIRCUITPY_BLEIO_HCI),1)

py/circuitpy_mpconfig.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,9 @@ CFLAGS += -DCIRCUITPY_KEYPAD_KEYMATRIX=$(CIRCUITPY_KEYPAD_KEYMATRIX)
345345
CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS ?= $(CIRCUITPY_KEYPAD)
346346
CFLAGS += -DCIRCUITPY_KEYPAD_SHIFTREGISTERKEYS=$(CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS)
347347

348+
CIRCUITPY_KEYPAD_DEMUX ?= $(CIRCUITPY_KEYPAD)
349+
CFLAGS += -DCIRCUITPY_KEYPAD_DEMUX=$(CIRCUITPY_KEYPAD_DEMUX)
350+
348351
CIRCUITPY_LOCALE ?= $(CIRCUITPY_FULL_BUILD)
349352
CFLAGS += -DCIRCUITPY_LOCALE=$(CIRCUITPY_LOCALE)
350353

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024 CDarius
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "shared/runtime/context_manager_helpers.h"
28+
#include "py/binary.h"
29+
#include "py/objproperty.h"
30+
#include "py/runtime.h"
31+
#include "shared-bindings/keypad/__init__.h"
32+
#include "shared-bindings/keypad/Event.h"
33+
#include "shared-bindings/keypad_demux/DemuxKeyMatrix.h"
34+
#include "shared-bindings/microcontroller/Pin.h"
35+
#include "shared-bindings/util.h"
36+
37+
//| class DemuxKeyMatrix:
38+
//| """Manage Cardputer 2D matrix of keys with a demultiplexer to drive rows and pins on columns.
39+
//|
40+
//| .. raw:: html
41+
//|
42+
//| <p>
43+
//| <details>
44+
//| <summary>Available on these boards</summary>
45+
//| <ul>
46+
//| {% for board in support_matrix_reverse["keypad_demux.DemuxKeyMatrix"] %}
47+
//| <li> {{ board }}
48+
//| {% endfor %}
49+
//| </ul>
50+
//| </details>
51+
//| </p>
52+
//|
53+
//| """
54+
//|
55+
//| def __init__(
56+
//| self,
57+
//| row_addr_pins: Sequence[microcontroller.Pin],
58+
//| column_pins: Sequence[microcontroller.Pin],
59+
//| interval: float = 0.020,
60+
//| max_events: int = 64,
61+
//| ) -> None:
62+
//| """
63+
//| Create a `keypad.Keys` object that will scan the key matrix attached to the given row and column pins.
64+
//| There should not be any external pull-ups or pull-downs on the matrix:
65+
//| ``DemuxKeyMatrix`` enables internal pull-ups or pull-downs on the pins as necessary.
66+
//|
67+
//| The keys are numbered sequentially from zero. A key number can be computed
68+
//| by ``row * len(column_pins) + column``.
69+
//|
70+
//| An `keypad.EventQueue` is created when this object is created and is available in the `events` attribute.
71+
//|
72+
//| :param Sequence[microcontroller.Pin] row_addr_pins: The pins attached to the rows demultiplexer.
73+
//| :param Sequence[microcontroller.Pin] column_pins: The pins attached to the columns.
74+
//| :param float interval: Scan keys no more often than ``interval`` to allow for debouncing.
75+
//| ``interval`` is in float seconds. The default is 0.020 (20 msecs).
76+
//| :param int max_events: maximum size of `events` `keypad.EventQueue`:
77+
//| maximum number of key transition events that are saved.
78+
//| Must be >= 1.
79+
//| If a new event arrives when the queue is full, the oldest event is discarded.
80+
//| """
81+
//| ...
82+
83+
STATIC mp_obj_t keypad_demux_demuxkeymatrix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
84+
keypad_demux_demuxkeymatrix_obj_t *self = mp_obj_malloc(keypad_demux_demuxkeymatrix_obj_t, &keypad_demux_demuxkeymatrix_type);
85+
enum { ARG_row_addr_pins, ARG_column_pins, ARG_interval, ARG_max_events };
86+
static const mp_arg_t allowed_args[] = {
87+
{ MP_QSTR_row_addr_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
88+
{ MP_QSTR_column_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
89+
{ MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
90+
{ MP_QSTR_max_events, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
91+
};
92+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
93+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
94+
95+
mp_obj_t row_addr_pins = args[ARG_row_addr_pins].u_obj;
96+
// mp_obj_len() will be >= 0.
97+
const size_t num_row_addr_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(row_addr_pins));
98+
99+
mp_obj_t column_pins = args[ARG_column_pins].u_obj;
100+
const size_t num_column_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(column_pins));
101+
102+
const mp_float_t interval =
103+
mp_arg_validate_obj_float_non_negative(args[ARG_interval].u_obj, 0.020f, MP_QSTR_interval);
104+
const size_t max_events = (size_t)mp_arg_validate_int_min(args[ARG_max_events].u_int, 1, MP_QSTR_max_events);
105+
106+
const mcu_pin_obj_t *row_addr_pins_array[num_row_addr_pins];
107+
const mcu_pin_obj_t *column_pins_array[num_column_pins];
108+
109+
validate_no_duplicate_pins_2(row_addr_pins, column_pins, MP_QSTR_row_addr_pins, MP_QSTR_column_pins);
110+
111+
for (size_t row_addr = 0; row_addr < num_row_addr_pins; row_addr++) {
112+
const mcu_pin_obj_t *pin =
113+
validate_obj_is_free_pin(mp_obj_subscr(row_addr_pins, MP_OBJ_NEW_SMALL_INT(row_addr), MP_OBJ_SENTINEL), MP_QSTR_pin);
114+
row_addr_pins_array[row_addr] = pin;
115+
}
116+
117+
for (size_t column = 0; column < num_column_pins; column++) {
118+
const mcu_pin_obj_t *pin =
119+
validate_obj_is_free_pin(mp_obj_subscr(column_pins, MP_OBJ_NEW_SMALL_INT(column), MP_OBJ_SENTINEL), MP_QSTR_pin);
120+
column_pins_array[column] = pin;
121+
}
122+
123+
common_hal_keypad_demux_demuxkeymatrix_construct(self, num_row_addr_pins, row_addr_pins_array, num_column_pins, column_pins_array, interval, max_events);
124+
return MP_OBJ_FROM_PTR(self);
125+
}
126+
127+
//| def deinit(self) -> None:
128+
//| """Stop scanning and release the pins."""
129+
//| ...
130+
STATIC mp_obj_t keypad_demux_demuxkeymatrix_deinit(mp_obj_t self_in) {
131+
keypad_demux_demuxkeymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
132+
common_hal_keypad_demux_demuxkeymatrix_deinit(self);
133+
return MP_ROM_NONE;
134+
}
135+
MP_DEFINE_CONST_FUN_OBJ_1(keypad_demux_demuxkeymatrix_deinit_obj, keypad_demux_demuxkeymatrix_deinit);
136+
137+
//| def __enter__(self) -> DemuxKeyMatrix:
138+
//| """No-op used by Context Managers."""
139+
//| ...
140+
// Provided by context manager helper.
141+
142+
//| def __exit__(self) -> None:
143+
//| """Automatically deinitializes when exiting a context. See
144+
//| :ref:`lifetime-and-contextmanagers` for more info."""
145+
//| ...
146+
STATIC mp_obj_t keypad_demux_demuxkeymatrix___exit__(size_t n_args, const mp_obj_t *args) {
147+
(void)n_args;
148+
common_hal_keypad_demux_demuxkeymatrix_deinit(args[0]);
149+
return MP_ROM_NONE;
150+
}
151+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_demux_demuxkeymatrix___exit___obj, 4, 4, keypad_demux_demuxkeymatrix___exit__);
152+
153+
STATIC void check_for_deinit(keypad_demux_demuxkeymatrix_obj_t *self) {
154+
if (common_hal_keypad_deinited(self)) {
155+
raise_deinited_error();
156+
}
157+
}
158+
159+
//| def reset(self) -> None:
160+
//| """Reset the internal state of the scanner to assume that all keys are now released.
161+
//| Any key that is already pressed at the time of this call will therefore immediately cause
162+
//| a new key-pressed event to occur.
163+
//| """
164+
//| ...
165+
166+
//| key_count: int
167+
//| """The number of keys that are being scanned. (read-only)
168+
//| """
169+
170+
//| def key_number_to_row_column(self, key_number: int) -> Tuple[int]:
171+
//| """Return the row and column for the given key number.
172+
//| The row is ``key_number // len(column_pins)``.
173+
//| The column is ``key_number % len(column_pins)``.
174+
//|
175+
//| :return: ``(row, column)``
176+
//| :rtype: Tuple[int]
177+
//| """
178+
//| ...
179+
STATIC mp_obj_t keypad_demux_demuxkeymatrix_key_number_to_row_column(mp_obj_t self_in, mp_obj_t key_number_in) {
180+
keypad_demux_demuxkeymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
181+
check_for_deinit(self);
182+
183+
const mp_uint_t key_number = (mp_uint_t)mp_arg_validate_int_range(
184+
mp_obj_get_int(key_number_in),
185+
0, (mp_int_t)common_hal_keypad_generic_get_key_count(self),
186+
MP_QSTR_key_number);
187+
188+
mp_uint_t row;
189+
mp_uint_t column;
190+
common_hal_keypad_demux_demuxkeymatrix_key_number_to_row_column(self, key_number, &row, &column);
191+
192+
mp_obj_t row_column[2];
193+
row_column[0] = MP_OBJ_NEW_SMALL_INT(row);
194+
row_column[1] = MP_OBJ_NEW_SMALL_INT(column);
195+
196+
return mp_obj_new_tuple(2, row_column);
197+
}
198+
MP_DEFINE_CONST_FUN_OBJ_2(keypad_demux_demuxkeymatrix_key_number_to_row_column_obj, keypad_demux_demuxkeymatrix_key_number_to_row_column);
199+
200+
//| def row_column_to_key_number(self, row: int, column: int) -> int:
201+
//| """Return the key number for a given row and column.
202+
//| The key number is ``row * len(column_pins) + column``.
203+
//| """
204+
//| ...
205+
STATIC mp_obj_t keypad_demux_demuxkeymatrix_row_column_to_key_number(mp_obj_t self_in, mp_obj_t row_in, mp_obj_t column_in) {
206+
keypad_demux_demuxkeymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in);
207+
check_for_deinit(self);
208+
209+
const mp_uint_t row = (mp_uint_t)mp_arg_validate_int_range(
210+
mp_obj_get_int(row_in), 0, (mp_int_t)common_hal_keypad_demux_demuxkeymatrix_get_row_count(self), MP_QSTR_row);
211+
212+
const mp_int_t column = (mp_uint_t)mp_arg_validate_int_range(
213+
mp_obj_get_int(column_in), 0, (mp_int_t)common_hal_keypad_demux_demuxkeymatrix_get_column_count(self), MP_QSTR_column);
214+
215+
return MP_OBJ_NEW_SMALL_INT(
216+
(mp_int_t)common_hal_keypad_demux_demuxkeymatrix_row_column_to_key_number(self, row, column));
217+
}
218+
MP_DEFINE_CONST_FUN_OBJ_3(keypad_demux_demuxkeymatrix_row_column_to_key_number_obj, keypad_demux_demuxkeymatrix_row_column_to_key_number);
219+
220+
//| events: keypad.EventQueue
221+
//| """The `keypad.EventQueue` associated with this `keypad.Keys` object. (read-only)
222+
//| """
223+
//|
224+
225+
STATIC const mp_rom_map_elem_t keypad_demux_demuxkeymatrix_locals_dict_table[] = {
226+
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_demux_demuxkeymatrix_deinit_obj) },
227+
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
228+
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_demux_demuxkeymatrix___exit___obj) },
229+
230+
{ MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_generic_events_obj) },
231+
{ MP_ROM_QSTR(MP_QSTR_key_count), MP_ROM_PTR(&keypad_generic_key_count_obj) },
232+
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&keypad_generic_reset_obj) },
233+
{ MP_ROM_QSTR(MP_QSTR_key_number_to_row_column), MP_ROM_PTR(&keypad_demux_demuxkeymatrix_key_number_to_row_column_obj) },
234+
{ MP_ROM_QSTR(MP_QSTR_row_column_to_key_number), MP_ROM_PTR(&keypad_demux_demuxkeymatrix_row_column_to_key_number_obj) },
235+
};
236+
237+
STATIC MP_DEFINE_CONST_DICT(keypad_demux_demuxkeymatrix_locals_dict, keypad_demux_demuxkeymatrix_locals_dict_table);
238+
239+
MP_DEFINE_CONST_OBJ_TYPE(
240+
keypad_demux_demuxkeymatrix_type,
241+
MP_QSTR_DemuxKeyMatrix,
242+
MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS,
243+
make_new, keypad_demux_demuxkeymatrix_make_new,
244+
locals_dict, &keypad_demux_demuxkeymatrix_locals_dict
245+
);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024 CDarius
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_DEMUX_DEMUXKEYMATRIX_H
28+
#define MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_DEMUX_DEMUXKEYMATRIX_H
29+
30+
#include "py/objlist.h"
31+
#include "shared-module/keypad_demux/DemuxKeyMatrix.h"
32+
33+
extern const mp_obj_type_t keypad_demux_demuxkeymatrix_type;
34+
35+
void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t num_row_addr_pins, const mcu_pin_obj_t *row_addr_pins[], mp_uint_t num_column_pins, const mcu_pin_obj_t *column_pins[], mp_float_t interval, size_t max_events);
36+
37+
void common_hal_keypad_demux_demuxkeymatrix_deinit(keypad_demux_demuxkeymatrix_obj_t *self);
38+
39+
void common_hal_keypad_demux_demuxkeymatrix_key_number_to_row_column(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t key_number, mp_uint_t *row, mp_uint_t *column);
40+
mp_uint_t common_hal_keypad_demux_demuxkeymatrix_row_column_to_key_number(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t row, mp_uint_t column);
41+
42+
size_t common_hal_keypad_demux_demuxkeymatrix_get_column_count(keypad_demux_demuxkeymatrix_obj_t *self);
43+
size_t common_hal_keypad_demux_demuxkeymatrix_get_row_count(keypad_demux_demuxkeymatrix_obj_t *self);
44+
45+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_KEYPAD_DEMUX_DEMUXKEYMATRIX_H
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024 CDarius
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/obj.h"
28+
29+
#include "shared-bindings/keypad_demux/DemuxKeyMatrix.h"
30+
#include "shared-bindings/util.h"
31+
32+
//| """Support for scanning key matrices that use a demultiplexer
33+
//|
34+
//| The `keypad_demux` module provides native support to scan sets of keys or buttons,
35+
//| connected in a row-and-column matrix.
36+
//|
37+
//| .. jinja
38+
//| """
39+
40+
STATIC mp_rom_map_elem_t keypad_demux_module_globals_table[] = {
41+
{ MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_keypad_demux) },
42+
{ MP_ROM_QSTR(MP_QSTR_DemuxKeyMatrix), MP_OBJ_FROM_PTR(&keypad_demux_demuxkeymatrix_type) },
43+
};
44+
45+
STATIC MP_DEFINE_CONST_DICT(keypad_demux_module_globals, keypad_demux_module_globals_table);
46+
47+
const mp_obj_module_t keypad_demux_module = {
48+
.base = { &mp_type_module },
49+
.globals = (mp_obj_dict_t *)&keypad_demux_module_globals,
50+
};
51+
52+
MP_REGISTER_MODULE(MP_QSTR_keypad_demux, keypad_demux_module);

0 commit comments

Comments
 (0)