@@ -27,11 +27,15 @@ static keypad_scanner_funcs_t keymatrix_funcs = {
27
27
};
28
28
29
29
static mp_uint_t row_column_to_key_number (keypad_demux_demuxkeymatrix_obj_t * self , mp_uint_t row , mp_uint_t column ) {
30
- 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 ;
31
32
}
32
33
33
- 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 ) {
34
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
35
39
mp_obj_t row_addr_dios [num_row_addr_pins ];
36
40
for (size_t row = 0 ; row < num_row_addr_pins ; row ++ ) {
37
41
digitalio_digitalinout_obj_t * dio =
@@ -42,17 +46,20 @@ void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatri
42
46
}
43
47
self -> row_addr_digitalinouts = mp_obj_new_tuple (num_row_addr_pins , row_addr_dios );
44
48
49
+ // the column pins are always inputs, with default state based on columns_to_anodes
45
50
mp_obj_t column_dios [num_column_pins ];
46
51
for (size_t column = 0 ; column < num_column_pins ; column ++ ) {
47
52
digitalio_digitalinout_obj_t * dio =
48
53
mp_obj_malloc (digitalio_digitalinout_obj_t , & digitalio_digitalinout_type );
49
54
dio -> base .type = & digitalio_digitalinout_type ;
50
55
common_hal_digitalio_digitalinout_construct (dio , column_pins [column ]);
51
- 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 );
52
57
column_dios [column ] = dio ;
53
58
}
54
59
self -> column_digitalinouts = mp_obj_new_tuple (num_column_pins , column_dios );
55
60
61
+ self -> columns_to_anodes = columns_to_anodes ;
62
+ self -> transpose = transpose ;
56
63
self -> funcs = & keymatrix_funcs ;
57
64
58
65
keypad_construct_common ((keypad_scanner_obj_t * )self , interval , max_events , debounce_threshold );
@@ -79,11 +86,15 @@ void common_hal_keypad_demux_demuxkeymatrix_deinit(keypad_demux_demuxkeymatrix_o
79
86
}
80
87
81
88
size_t common_hal_keypad_demux_demuxkeymatrix_get_row_count (keypad_demux_demuxkeymatrix_obj_t * self ) {
82
- 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 );
83
92
}
84
93
85
94
size_t common_hal_keypad_demux_demuxkeymatrix_get_column_count (keypad_demux_demuxkeymatrix_obj_t * self ) {
86
- return self -> column_digitalinouts -> len ;
95
+ return self -> transpose
96
+ ? (size_t )(1 << self -> row_addr_digitalinouts -> len )
97
+ : self -> column_digitalinouts -> len ;
87
98
}
88
99
89
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 ) {
@@ -105,11 +116,11 @@ static void demuxkeymatrix_scan_now(void *self_in, mp_obj_t timestamp) {
105
116
keypad_demux_demuxkeymatrix_obj_t * self = self_in ;
106
117
107
118
for (size_t row = 0 ; row < common_hal_keypad_demux_demuxkeymatrix_get_row_count (self ); row ++ ) {
108
- // Set the row address on the demultiplexer. This currently assumes an inverting
109
- // demux like the 74hc138 which outputs low on the selected line and high on non-selected ones.
110
- // This class should probably support a columns_to_anodes parameter where this case would
111
- // be True (the row gets pulled low), and a non-inverting demux like 74hc238 would
112
- // set columns_to_anodes=False.
119
+ // Set the row address on the demultiplexer.
120
+ // When columns_to_anodes is True (default) we've got an inverting demux
121
+ // so the selected line is pulled low, and we look for rows that get pulled low.
122
+ // When columns_to_anodes is False we do the reverse.
123
+ // We can safely ignore transposition since it's handled by row_column_to_key_number
113
124
size_t mask = 0b00000001 ;
114
125
for (size_t row_addr_pin = 0 ; row_addr_pin < self -> row_addr_digitalinouts -> len ; row_addr_pin ++ ) {
115
126
digitalio_digitalinout_obj_t * dio = self -> row_addr_digitalinouts -> items [row_addr_pin ];
@@ -128,9 +139,11 @@ static void demuxkeymatrix_scan_now(void *self_in, mp_obj_t timestamp) {
128
139
for (size_t column = 0 ; column < common_hal_keypad_demux_demuxkeymatrix_get_column_count (self ); column ++ ) {
129
140
mp_uint_t key_number = row_column_to_key_number (self , row , column );
130
141
131
- // Get the current state, by reading whether the column got pulled to the row value or not.
132
- // (with a columns_to_anodes parameter this could mimic the KeyMatrix code)
133
- const bool current = !common_hal_digitalio_digitalinout_get_value (self -> column_digitalinouts -> items [column ]);
142
+ // Get the current state, by reading whether the column got pulled to the row value or not,
143
+ // which is the opposite of columns_to_anodes.
144
+ const bool current =
145
+ common_hal_digitalio_digitalinout_get_value (self -> column_digitalinouts -> items [column ]) !=
146
+ self -> columns_to_anodes ;
134
147
135
148
// Record any transitions.
136
149
if (keypad_debounce ((keypad_scanner_obj_t * )self , key_number , current )) {
0 commit comments