7
7
#include <string.h>
8
8
9
9
#include "py/gc.h"
10
+ #include "py/mphal.h"
10
11
#include "py/runtime.h"
11
12
#include "shared-bindings/digitalio/DigitalInOut.h"
12
13
#include "shared-bindings/keypad/EventQueue.h"
@@ -26,11 +27,15 @@ static keypad_scanner_funcs_t keymatrix_funcs = {
26
27
};
27
28
28
29
static mp_uint_t row_column_to_key_number (keypad_demux_demuxkeymatrix_obj_t * self , mp_uint_t row , mp_uint_t column ) {
29
- return row * self -> column_digitalinouts -> len + column ;
30
+ // return the key index in the user's coordinate system
31
+ return row * common_hal_keypad_demux_demuxkeymatrix_get_column_count (self ) + column ;
30
32
}
31
33
32
- 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 , uint8_t debounce_threshold ) {
34
+ 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 [], bool columns_to_anodes , bool transpose , mp_float_t interval , size_t max_events , uint8_t debounce_threshold ) {
33
35
36
+ // the multiplexed pins are outputs so we can set the address for the target row
37
+ // the sense of the address pins themselves doesn't change with columns_to_anodes
38
+ // but the value output on the selected row line will be !columns_to_anodes
34
39
mp_obj_t row_addr_dios [num_row_addr_pins ];
35
40
for (size_t row = 0 ; row < num_row_addr_pins ; row ++ ) {
36
41
digitalio_digitalinout_obj_t * dio =
@@ -41,17 +46,20 @@ void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatri
41
46
}
42
47
self -> row_addr_digitalinouts = mp_obj_new_tuple (num_row_addr_pins , row_addr_dios );
43
48
49
+ // the column pins are always inputs, with default state based on columns_to_anodes
44
50
mp_obj_t column_dios [num_column_pins ];
45
51
for (size_t column = 0 ; column < num_column_pins ; column ++ ) {
46
52
digitalio_digitalinout_obj_t * dio =
47
53
mp_obj_malloc (digitalio_digitalinout_obj_t , & digitalio_digitalinout_type );
48
54
dio -> base .type = & digitalio_digitalinout_type ;
49
55
common_hal_digitalio_digitalinout_construct (dio , column_pins [column ]);
50
- common_hal_digitalio_digitalinout_switch_to_input (dio , PULL_UP );
56
+ common_hal_digitalio_digitalinout_switch_to_input (dio , columns_to_anodes ? PULL_UP : PULL_DOWN );
51
57
column_dios [column ] = dio ;
52
58
}
53
59
self -> column_digitalinouts = mp_obj_new_tuple (num_column_pins , column_dios );
54
60
61
+ self -> columns_to_anodes = columns_to_anodes ;
62
+ self -> transpose = transpose ;
55
63
self -> funcs = & keymatrix_funcs ;
56
64
57
65
keypad_construct_common ((keypad_scanner_obj_t * )self , interval , max_events , debounce_threshold );
@@ -78,11 +86,15 @@ void common_hal_keypad_demux_demuxkeymatrix_deinit(keypad_demux_demuxkeymatrix_o
78
86
}
79
87
80
88
size_t common_hal_keypad_demux_demuxkeymatrix_get_row_count (keypad_demux_demuxkeymatrix_obj_t * self ) {
81
- return 1 << self -> row_addr_digitalinouts -> len ;
89
+ return self -> transpose
90
+ ? self -> column_digitalinouts -> len
91
+ : (size_t )(1 << self -> row_addr_digitalinouts -> len );
82
92
}
83
93
84
94
size_t common_hal_keypad_demux_demuxkeymatrix_get_column_count (keypad_demux_demuxkeymatrix_obj_t * self ) {
85
- return self -> column_digitalinouts -> len ;
95
+ return self -> transpose
96
+ ? (size_t )(1 << self -> row_addr_digitalinouts -> len )
97
+ : self -> column_digitalinouts -> len ;
86
98
}
87
99
88
100
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 ) {
@@ -102,22 +114,38 @@ static size_t demuxkeymatrix_get_key_count(void *self_in) {
102
114
103
115
static void demuxkeymatrix_scan_now (void * self_in , mp_obj_t timestamp ) {
104
116
keypad_demux_demuxkeymatrix_obj_t * self = self_in ;
105
-
106
- for (size_t row = 0 ; row < common_hal_keypad_demux_demuxkeymatrix_get_row_count (self ); row ++ ) {
107
- // Set the row address on demultiplexer
117
+ // We always scan through the multiplexed lines using the array sizes directly
118
+ // and apply transposition only when translating to key number.
119
+ for (int row = 0 ; row < (1 << self -> row_addr_digitalinouts -> len ); row ++ ) {
120
+ // Set the row address on the demultiplexer.
121
+ // When columns_to_anodes is True (default) we've got an inverting demux
122
+ // so the selected line is pulled low, and we look for rows that get pulled low.
123
+ // When columns_to_anodes is False we do the reverse.
108
124
size_t mask = 0b00000001 ;
109
125
for (size_t row_addr_pin = 0 ; row_addr_pin < self -> row_addr_digitalinouts -> len ; row_addr_pin ++ ) {
110
126
digitalio_digitalinout_obj_t * dio = self -> row_addr_digitalinouts -> items [row_addr_pin ];
111
127
common_hal_digitalio_digitalinout_set_value (dio , (mask & row ) != 0 );
112
128
mask = mask << 1 ;
113
129
}
114
130
115
- for (size_t column = 0 ; column < common_hal_keypad_demux_demuxkeymatrix_get_column_count (self ); column ++ ) {
116
- mp_uint_t key_number = row_column_to_key_number (self , row , column );
117
-
118
- // Get the current state, by reading whether the column got pulled to the row value or not.
119
- // If low, the key is pressed.
120
- const bool current = !common_hal_digitalio_digitalinout_get_value (self -> column_digitalinouts -> items [column ]);
131
+ // Wait a moment to let the columns settle.
132
+ // The normal KeyMatrix uses a 1us delay but that still gave echoes on my
133
+ // nullbitsco nibble 65% (16 x 5 matrix). For example when key (row, col) is pressed
134
+ // both (row, col) and (row+1, col) (and sometimes row+2) are registered,
135
+ // especially when row+1 is a power of 2 (all mux bits change) and col is 0.
136
+ // The QMK implementation for this keyboard uses a 5us delay which works here too
137
+ mp_hal_delay_us (5 );
138
+
139
+ for (size_t column = 0 ; column < self -> column_digitalinouts -> len ; column ++ ) {
140
+ mp_uint_t key_number = self -> transpose
141
+ ? row_column_to_key_number (self , column , row )
142
+ : row_column_to_key_number (self , row , column );
143
+
144
+ // Get the current state, by reading whether the column got pulled to the row value or not,
145
+ // which is the opposite of columns_to_anodes.
146
+ const bool current =
147
+ common_hal_digitalio_digitalinout_get_value (self -> column_digitalinouts -> items [column ]) !=
148
+ self -> columns_to_anodes ;
121
149
122
150
// Record any transitions.
123
151
if (keypad_debounce ((keypad_scanner_obj_t * )self , key_number , current )) {
0 commit comments