Skip to content

Commit fdb38cc

Browse files
committed
wip: include transpose and columns_to_anodes options
1 parent 111040f commit fdb38cc

File tree

5 files changed

+54
-18
lines changed

5 files changed

+54
-18
lines changed

shared-bindings/keypad_demux/DemuxKeyMatrix.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
//| self,
3737
//| row_addr_pins: Sequence[microcontroller.Pin],
3838
//| column_pins: Sequence[microcontroller.Pin],
39+
//| columns_to_anodes: bool = True,
40+
//| transpose: bool = False,
3941
//| interval: float = 0.020,
4042
//| max_events: int = 64,
4143
//| debounce_threshold: int = 1,
@@ -51,7 +53,18 @@
5153
//| An `keypad.EventQueue` is created when this object is created and is available in the `events` attribute.
5254
//|
5355
//| :param Sequence[microcontroller.Pin] row_addr_pins: The pins attached to the rows demultiplexer.
56+
//| If your columns are multiplexed, set ``transpose`` to ``True``.
5457
//| :param Sequence[microcontroller.Pin] column_pins: The pins attached to the columns.
58+
//| :param bool columns_to_anodes: Default ``True``.
59+
//| If the matrix uses diodes, the diode anodes are typically connected to the column pins
60+
//| with the cathodes connected to the row pins. This implies an inverting multiplexer that drives
61+
//| the selected row pin low. If your diodes are reversed, with a non-inverting multiplexer
62+
//| that drives the selected row high, set ``columns_to_anodes`` to ``False``.
63+
//| If ``transpose`` is ``True`` the sense of columns and rows are reversed here.
64+
//| :param bool transpose: Default ``False``.
65+
//| If your matrix is multiplexed on columns rather than rows, set ``transpose`` to ``True``.
66+
//| This swaps the meaning of ``row_addr_pins`` to ``column_addr_pins``;
67+
//| ``column_pins`` to ``row_pins``; and ``columns_to_anodes`` to ``rows_to_anodes``.
5568
//| :param float interval: Scan keys no more often than ``interval`` to allow for debouncing.
5669
//| ``interval`` is in float seconds. The default is 0.020 (20 msecs).
5770
//| :param int max_events: maximum size of `events` `keypad.EventQueue`:
@@ -67,10 +80,12 @@
6780

6881
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) {
6982
keypad_demux_demuxkeymatrix_obj_t *self = mp_obj_malloc(keypad_demux_demuxkeymatrix_obj_t, &keypad_demux_demuxkeymatrix_type);
70-
enum { ARG_row_addr_pins, ARG_column_pins, ARG_interval, ARG_max_events, ARG_debounce_threshold };
83+
enum { ARG_row_addr_pins, ARG_column_pins, ARG_columns_to_anodes, ARG_transpose, ARG_interval, ARG_max_events, ARG_debounce_threshold };
7184
static const mp_arg_t allowed_args[] = {
7285
{ MP_QSTR_row_addr_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
7386
{ MP_QSTR_column_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
87+
{ MP_QSTR_columns_to_anodes, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
88+
{ MP_QSTR_transpose, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
7489
{ MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
7590
{ MP_QSTR_max_events, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
7691
{ MP_QSTR_debounce_threshold, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
@@ -107,7 +122,7 @@ static mp_obj_t keypad_demux_demuxkeymatrix_make_new(const mp_obj_type_t *type,
107122
column_pins_array[column] = pin;
108123
}
109124

110-
common_hal_keypad_demux_demuxkeymatrix_construct(self, num_row_addr_pins, row_addr_pins_array, num_column_pins, column_pins_array, interval, max_events, debounce_threshold);
125+
common_hal_keypad_demux_demuxkeymatrix_construct(self, num_row_addr_pins, row_addr_pins_array, num_column_pins, column_pins_array, args[ARG_columns_to_anodes].u_bool, args[ARG_transpose].u_bool, interval, max_events, debounce_threshold);
111126
return MP_OBJ_FROM_PTR(self);
112127
}
113128

shared-bindings/keypad_demux/DemuxKeyMatrix.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
extern const mp_obj_type_t keypad_demux_demuxkeymatrix_type;
1313

14-
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);
14+
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);
1515

1616
void common_hal_keypad_demux_demuxkeymatrix_deinit(keypad_demux_demuxkeymatrix_obj_t *self);
1717

shared-bindings/keypad_demux/__init__.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,14 @@
1111

1212
//| """Support for scanning key matrices that use a demultiplexer
1313
//|
14-
//| The `keypad_demux` module provides native support to scan sets of keys or buttons,
15-
//| connected in a row-and-column matrix.
14+
//| The `keypad_demux` module provides native support to scan a matrix of keys or buttons
15+
//| where either the row or column axis is controlled by a demultiplexer or decoder IC
16+
//| such as the 74LS138 or 74LS238. In this arrangement a binary input value
17+
//| determines which column (or row) to select, thereby reducing the number of input pins.
18+
//| For example the input 101 would select line 5 in the matrix.
19+
//| Set ``columns_to_anodes`` to ``False`` with a non-inverting demultiplexer
20+
//| which drives the selected line high.
21+
//| Set ``transpose`` to ``True`` if columns are multiplexed rather than rows.
1622
//|
1723
//| .. jinja
1824
//| """

shared-module/keypad_demux/DemuxKeyMatrix.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,15 @@ static keypad_scanner_funcs_t keymatrix_funcs = {
2727
};
2828

2929
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;
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

8188
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);
8392
}
8493

8594
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;
8798
}
8899

89100
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) {
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)) {

shared-module/keypad_demux/DemuxKeyMatrix.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ typedef struct {
1717
KEYPAD_SCANNER_COMMON_FIELDS;
1818
mp_obj_tuple_t *row_addr_digitalinouts;
1919
mp_obj_tuple_t *column_digitalinouts;
20+
bool columns_to_anodes;
21+
bool transpose;
2022
} keypad_demux_demuxkeymatrix_obj_t;
2123

2224
void keypad_demux_demuxkeymatrix_scan(keypad_demux_demuxkeymatrix_obj_t *self);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy