Skip to content

Commit 9f9dcd0

Browse files
committed
Add Cardputer keyboard support
1 parent 60bd748 commit 9f9dcd0

File tree

7 files changed

+517
-0
lines changed

7 files changed

+517
-0
lines changed

ports/espressif/boards/m5stack_cardputer/mpconfigboard.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ CIRCUITPY_ESP_FLASH_SIZE = 8MB
1111
CIRCUITPY_ESPCAMERA = 0
1212

1313
CIRCUITPY_GIFIO = 1
14+
15+
# Enable board-specific modules
16+
USER_C_MODULES = boards/m5stack_cardputer/usermods
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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 <string.h>
28+
29+
#include "py/gc.h"
30+
#include "py/runtime.h"
31+
#include "shared-bindings/digitalio/DigitalInOut.h"
32+
#include "shared-bindings/keypad/EventQueue.h"
33+
#include "shared-bindings/keypad/__init__.h"
34+
#include "shared-bindings/supervisor/__init__.h"
35+
#include "shared-bindings/util.h"
36+
#include "supervisor/port.h"
37+
#include "supervisor/shared/tick.h"
38+
#include "DemuxKeyMatrix.h"
39+
40+
static void demuxkeymatrix_scan_now(void *self_in, mp_obj_t timestamp);
41+
static size_t demuxkeymatrix_get_key_count(void *self_in);
42+
43+
static keypad_scanner_funcs_t keymatrix_funcs = {
44+
.scan_now = demuxkeymatrix_scan_now,
45+
.get_key_count = demuxkeymatrix_get_key_count,
46+
};
47+
48+
static mp_uint_t row_column_to_key_number(cardputer_demuxkeymatrix_obj_t *self, mp_uint_t row, mp_uint_t column) {
49+
return row * self->column_digitalinouts->len + column;
50+
}
51+
52+
void common_hal_cardputer_demuxkeymatrix_construct(cardputer_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) {
53+
54+
mp_obj_t row_addr_dios[num_row_addr_pins];
55+
for (size_t row = 0; row < num_row_addr_pins; row++) {
56+
digitalio_digitalinout_obj_t *dio =
57+
mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type);
58+
common_hal_digitalio_digitalinout_construct(dio, row_addr_pins[row]);
59+
common_hal_digitalio_digitalinout_switch_to_output(dio, false, DRIVE_MODE_PUSH_PULL);
60+
row_addr_dios[row] = dio;
61+
}
62+
self->row_addr_digitalinouts = mp_obj_new_tuple(num_row_addr_pins, row_addr_dios);
63+
64+
mp_obj_t column_dios[num_column_pins];
65+
for (size_t column = 0; column < num_column_pins; column++) {
66+
digitalio_digitalinout_obj_t *dio =
67+
mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type);
68+
dio->base.type = &digitalio_digitalinout_type;
69+
common_hal_digitalio_digitalinout_construct(dio, column_pins[column]);
70+
common_hal_digitalio_digitalinout_switch_to_input(dio, PULL_UP);
71+
column_dios[column] = dio;
72+
}
73+
self->column_digitalinouts = mp_obj_new_tuple(num_column_pins, column_dios);
74+
75+
size_t num_rows = 1 << num_row_addr_pins;
76+
self->currently_pressed = (bool *)m_malloc(sizeof(bool) * num_rows * num_column_pins);
77+
self->previously_pressed = (bool *)m_malloc(sizeof(bool) * num_rows * num_column_pins);
78+
79+
self->funcs = &keymatrix_funcs;
80+
81+
keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events);
82+
}
83+
84+
void common_hal_cardputer_demuxkeymatrix_deinit(cardputer_demuxkeymatrix_obj_t *self) {
85+
if (common_hal_keypad_deinited(self)) {
86+
return;
87+
}
88+
89+
// Remove self from the list of active keypad scanners first.
90+
keypad_deregister_scanner((keypad_scanner_obj_t *)self);
91+
92+
for (size_t row_addr = 0; row_addr < self->row_addr_digitalinouts->len; row_addr++) {
93+
common_hal_digitalio_digitalinout_deinit(self->row_addr_digitalinouts->items[row_addr]);
94+
}
95+
self->row_addr_digitalinouts = MP_ROM_NONE;
96+
97+
for (size_t column = 0; column < self->column_digitalinouts->len; column++) {
98+
common_hal_digitalio_digitalinout_deinit(self->column_digitalinouts->items[column]);
99+
}
100+
self->column_digitalinouts = MP_ROM_NONE;
101+
common_hal_keypad_deinit_core(self);
102+
}
103+
104+
size_t common_hal_cardputer_demuxkeymatrix_get_row_count(cardputer_demuxkeymatrix_obj_t *self) {
105+
return 1 << self->row_addr_digitalinouts->len;
106+
}
107+
108+
size_t common_hal_cardputer_demuxkeymatrix_get_column_count(cardputer_demuxkeymatrix_obj_t *self) {
109+
return self->column_digitalinouts->len;
110+
}
111+
112+
mp_uint_t common_hal_cardputer_demuxkeymatrix_row_column_to_key_number(cardputer_demuxkeymatrix_obj_t *self, mp_uint_t row, mp_uint_t column) {
113+
return row_column_to_key_number(self, row, column);
114+
}
115+
116+
void common_hal_cardputer_demuxkeymatrix_key_number_to_row_column(cardputer_demuxkeymatrix_obj_t *self, mp_uint_t key_number, mp_uint_t *row, mp_uint_t *column) {
117+
const size_t num_columns = common_hal_cardputer_demuxkeymatrix_get_column_count(self);
118+
*row = key_number / num_columns;
119+
*column = key_number % num_columns;
120+
}
121+
122+
static size_t demuxkeymatrix_get_key_count(void *self_in) {
123+
cardputer_demuxkeymatrix_obj_t *self = self_in;
124+
return common_hal_cardputer_demuxkeymatrix_get_column_count(self) * common_hal_cardputer_demuxkeymatrix_get_row_count(self);
125+
}
126+
127+
static void demuxkeymatrix_scan_now(void *self_in, mp_obj_t timestamp) {
128+
cardputer_demuxkeymatrix_obj_t *self = self_in;
129+
130+
for (size_t row = 0; row < common_hal_cardputer_demuxkeymatrix_get_row_count(self); row++) {
131+
// Set the row address on demultiplexer
132+
size_t mask = 0b00000001;
133+
for (size_t row_addr_pin = 0; row_addr_pin < self->row_addr_digitalinouts->len; row_addr_pin++) {
134+
digitalio_digitalinout_obj_t *dio = self->row_addr_digitalinouts->items[row_addr_pin];
135+
common_hal_digitalio_digitalinout_set_value(dio, (mask & row) != 0);
136+
mask = mask << 1;
137+
}
138+
139+
for (size_t column = 0; column < common_hal_cardputer_demuxkeymatrix_get_column_count(self); column++) {
140+
mp_uint_t key_number = row_column_to_key_number(self, row, column);
141+
const bool previous = self->currently_pressed[key_number];
142+
self->previously_pressed[key_number] = previous;
143+
144+
// Get the current state, by reading whether the column got pulled to the row value or not.
145+
// If low, the key is pressed.
146+
const bool current = !common_hal_digitalio_digitalinout_get_value(self->column_digitalinouts->items[column]);
147+
self->currently_pressed[key_number] = current;
148+
149+
// Record any transitions.
150+
if (previous != current) {
151+
keypad_eventqueue_record(self->events, key_number, current, timestamp);
152+
}
153+
}
154+
}
155+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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_MODULE_CARDPUTER_DEMUXKEYMATRIX_H
28+
#define MICROPY_INCLUDED_SHARED_MODULE_CARDPUTER_DEMUXKEYMATRIX_H
29+
30+
#include "py/obj.h"
31+
#include "py/objtuple.h"
32+
33+
#include "common-hal/digitalio/DigitalInOut.h"
34+
#include "shared-module/keypad/__init__.h"
35+
#include "shared-module/keypad/EventQueue.h"
36+
37+
typedef struct {
38+
KEYPAD_SCANNER_COMMON_FIELDS;
39+
mp_obj_tuple_t *row_addr_digitalinouts;
40+
mp_obj_tuple_t *column_digitalinouts;
41+
} cardputer_demuxkeymatrix_obj_t;
42+
43+
void cardputer_demuxkeymatrix_scan(cardputer_demuxkeymatrix_obj_t *self);
44+
45+
void common_hal_cardputer_demuxkeymatrix_construct(cardputer_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);
46+
47+
void common_hal_cardputer_demuxkeymatrix_deinit(cardputer_demuxkeymatrix_obj_t *self);
48+
49+
void common_hal_cardputer_demuxkeymatrix_key_number_to_row_column(cardputer_demuxkeymatrix_obj_t *self, mp_uint_t key_number, mp_uint_t *row, mp_uint_t *column);
50+
mp_uint_t common_hal_cardputer_demuxkeymatrix_row_column_to_key_number(cardputer_demuxkeymatrix_obj_t *self, mp_uint_t row, mp_uint_t column);
51+
52+
size_t common_hal_cardputer_demuxkeymatrix_get_column_count(cardputer_demuxkeymatrix_obj_t *self);
53+
size_t common_hal_cardputer_demuxkeymatrix_get_row_count(cardputer_demuxkeymatrix_obj_t *self);
54+
55+
#endif // MICROPY_INCLUDED_SHARED_MODULE_CARDPUTER_DEMUXKEYMATRIX_H

0 commit comments

Comments
 (0)