@@ -27,11 +27,15 @@ static keypad_scanner_funcs_t keymatrix_funcs = {
2727};
2828
2929static 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 ;
3132}
3233
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 ) {
3435
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
3539 mp_obj_t row_addr_dios [num_row_addr_pins ];
3640 for (size_t row = 0 ; row < num_row_addr_pins ; row ++ ) {
3741 digitalio_digitalinout_obj_t * dio =
@@ -42,17 +46,20 @@ void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatri
4246 }
4347 self -> row_addr_digitalinouts = mp_obj_new_tuple (num_row_addr_pins , row_addr_dios );
4448
49+ // the column pins are always inputs, with default state based on columns_to_anodes
4550 mp_obj_t column_dios [num_column_pins ];
4651 for (size_t column = 0 ; column < num_column_pins ; column ++ ) {
4752 digitalio_digitalinout_obj_t * dio =
4853 mp_obj_malloc (digitalio_digitalinout_obj_t , & digitalio_digitalinout_type );
4954 dio -> base .type = & digitalio_digitalinout_type ;
5055 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 );
5257 column_dios [column ] = dio ;
5358 }
5459 self -> column_digitalinouts = mp_obj_new_tuple (num_column_pins , column_dios );
5560
61+ self -> columns_to_anodes = columns_to_anodes ;
62+ self -> transpose = transpose ;
5663 self -> funcs = & keymatrix_funcs ;
5764
5865 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
7986}
8087
8188size_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 );
8392}
8493
8594size_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 ;
8798}
8899
89100mp_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) {
105116 keypad_demux_demuxkeymatrix_obj_t * self = self_in ;
106117
107118 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
113124 size_t mask = 0b00000001 ;
114125 for (size_t row_addr_pin = 0 ; row_addr_pin < self -> row_addr_digitalinouts -> len ; row_addr_pin ++ ) {
115126 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) {
128139 for (size_t column = 0 ; column < common_hal_keypad_demux_demuxkeymatrix_get_column_count (self ); column ++ ) {
129140 mp_uint_t key_number = row_column_to_key_number (self , row , column );
130141
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 ;
134147
135148 // Record any transitions.
136149 if (keypad_debounce ((keypad_scanner_obj_t * )self , key_number , current )) {
0 commit comments