diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index f9aa9aab52..04c6ead9b7 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -84,6 +84,7 @@ msgid "%q indices must be integers, not %s" msgstr "" #: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c +#: shared-bindings/keypad/ShiftRegisterKeys.c msgid "%q length must be %q" msgstr "" @@ -110,7 +111,7 @@ msgstr "" #: shared-bindings/_bleio/CharacteristicBuffer.c #: shared-bindings/_bleio/PacketBuffer.c shared-bindings/displayio/Group.c #: shared-bindings/displayio/Shape.c shared-bindings/keypad/KeyMatrix.c -#: shared-bindings/keypad/Keys.c +#: shared-bindings/keypad/Keys.c shared-bindings/keypad/ShiftRegisterKeys.c #: shared-bindings/memorymonitor/AllocationAlarm.c #: shared-bindings/vectorio/Circle.c shared-bindings/vectorio/Rectangle.c msgid "%q must be >= 1" @@ -125,12 +126,13 @@ msgid "%q must be a tuple of length 2" msgstr "" #: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c +#: shared-bindings/keypad/ShiftRegisterKeys.c msgid "%q must store bytes" msgstr "" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c shared-bindings/keypad/KeyMatrix.c -#: shared-bindings/keypad/Keys.c +#: shared-bindings/keypad/Keys.c shared-bindings/keypad/ShiftRegisterKeys.c msgid "%q out of range" msgstr "" diff --git a/shared-bindings/keypad/KeyMatrix.c b/shared-bindings/keypad/KeyMatrix.c index d63bfdc0b3..98cefa0198 100644 --- a/shared-bindings/keypad/KeyMatrix.c +++ b/shared-bindings/keypad/KeyMatrix.c @@ -36,12 +36,10 @@ //| class KeyMatrix: //| """Manage a 2D matrix of keys with row and column pins.""" //| -//| def __init__(self, row_pins: Sequence[microcontroller.Pin], col_pins: Sequence[microcontroller.Pin], max_events: int = 64) -> None: +//| def __init__(self, row_pins: Sequence[microcontroller.Pin], col_pins: Sequence[microcontroller.Pin], columns_to_anodes: bool = True, max_events: int = 64) -> None: //| """ //| Create a `Keys` object that will scan the key matrix attached to the given row and column pins. -//| If the matrix uses diodes, the diode anodes should be connected to the column pins, -//| and the cathodes should be connected to the row pins. If your diodes are reversed, -//| simply exchange the row and column pin sequences. +//| There should not be any pull-ups or pull-downs on the matrix. //| //| The keys are numbered sequentially from zero. A key number can be computed //| by ``row * len(col_pins) + col``. @@ -52,6 +50,11 @@ //| //| :param Sequence[microcontroller.Pin] row_pins: The pins attached to the rows. //| :param Sequence[microcontroller.Pin] col_pins: The pins attached to the colums. +//| :param bool columns_to_anodes: Default ``True``. +//| If the matrix uses diodes, the diode anodes are typically connected to the column pins, +//| and the cathodes should be connected to the row pins. If your diodes are reversed, +//| set ``columns_to_anodes`` to ``False``. +//| //| :param int max_events: maximum size of `events` `EventQueue`: //| maximum number of key transition events that are saved. //| Must be >= 1. @@ -62,10 +65,11 @@ STATIC mp_obj_t keypad_keymatrix_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { keypad_keymatrix_obj_t *self = m_new_obj(keypad_keymatrix_obj_t); self->base.type = &keypad_keymatrix_type; - enum { ARG_row_pins, ARG_col_pins, ARG_max_events }; + enum { ARG_row_pins, ARG_col_pins, ARG_columns_to_anodes, ARG_max_events }; static const mp_arg_t allowed_args[] = { { MP_QSTR_row_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_col_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_columns_to_anodes, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, { MP_QSTR_max_events, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -98,7 +102,7 @@ STATIC mp_obj_t keypad_keymatrix_make_new(const mp_obj_type_t *type, size_t n_ar col_pins_array[col] = pin; } - common_hal_keypad_keymatrix_construct(self, num_row_pins, row_pins_array, num_col_pins, col_pins_array, max_events); + common_hal_keypad_keymatrix_construct(self, num_row_pins, row_pins_array, num_col_pins, col_pins_array, args[ARG_columns_to_anodes].u_bool, max_events); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/keypad/KeyMatrix.h b/shared-bindings/keypad/KeyMatrix.h index 24ac405a82..59df6830e9 100644 --- a/shared-bindings/keypad/KeyMatrix.h +++ b/shared-bindings/keypad/KeyMatrix.h @@ -32,7 +32,7 @@ extern const mp_obj_type_t keypad_keymatrix_type; -void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint_t num_row_pins, mcu_pin_obj_t *row_pins[], mp_uint_t num_col_pins, mcu_pin_obj_t *col_pins[], size_t max_events); +void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint_t num_row_pins, mcu_pin_obj_t *row_pins[], mp_uint_t num_col_pins, mcu_pin_obj_t *col_pins[], bool columns_to_anodes, size_t max_events); void common_hal_keypad_keymatrix_deinit(keypad_keymatrix_obj_t *self); bool common_hal_keypad_keymatrix_deinited(keypad_keymatrix_obj_t *self); diff --git a/shared-module/keypad/KeyMatrix.c b/shared-module/keypad/KeyMatrix.c index bd72b4a940..5aa7f95e5f 100644 --- a/shared-module/keypad/KeyMatrix.c +++ b/shared-module/keypad/KeyMatrix.c @@ -42,14 +42,14 @@ static mp_uint_t row_col_to_key_num(keypad_keymatrix_obj_t *self, mp_uint_t row, return row * self->col_digitalinouts->len + col; } -void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint_t num_row_pins, mcu_pin_obj_t *row_pins[], mp_uint_t num_col_pins, mcu_pin_obj_t *col_pins[], size_t max_events) { +void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint_t num_row_pins, mcu_pin_obj_t *row_pins[], mp_uint_t num_col_pins, mcu_pin_obj_t *col_pins[], bool columns_to_anodes, size_t max_events) { mp_obj_t row_dios[num_row_pins]; for (size_t row = 0; row < num_row_pins; row++) { digitalio_digitalinout_obj_t *dio = m_new_obj(digitalio_digitalinout_obj_t); dio->base.type = &digitalio_digitalinout_type; common_hal_digitalio_digitalinout_construct(dio, row_pins[row]); - common_hal_digitalio_digitalinout_switch_to_input(dio, PULL_UP); + common_hal_digitalio_digitalinout_switch_to_input(dio, columns_to_anodes ? PULL_UP : PULL_DOWN); row_dios[row] = dio; } self->row_digitalinouts = mp_obj_new_tuple(num_row_pins, row_dios); @@ -59,7 +59,7 @@ void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint digitalio_digitalinout_obj_t *dio = m_new_obj(digitalio_digitalinout_obj_t); dio->base.type = &digitalio_digitalinout_type; common_hal_digitalio_digitalinout_construct(dio, col_pins[col]); - common_hal_digitalio_digitalinout_switch_to_input(dio, PULL_UP); + common_hal_digitalio_digitalinout_switch_to_input(dio, columns_to_anodes ? PULL_UP : PULL_DOWN); col_dios[col] = dio; } self->col_digitalinouts = mp_obj_new_tuple(num_col_pins, col_dios); @@ -67,6 +67,8 @@ void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint self->currently_pressed = (bool *)gc_alloc(sizeof(bool) * num_row_pins * num_col_pins, false, false); self->previously_pressed = (bool *)gc_alloc(sizeof(bool) * num_row_pins * num_col_pins, false, false); + self->columns_to_anodes = columns_to_anodes; + keypad_eventqueue_obj_t *events = m_new_obj(keypad_eventqueue_obj_t); events->base.type = &keypad_eventqueue_type; common_hal_keypad_eventqueue_construct(events, max_events); @@ -142,21 +144,25 @@ void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self) { self->last_scan_ticks = now; - // On entry, all pins are set to inputs with a pull-up. + // On entry, all pins are set to inputs with a pull-up or pull-down, + // depending on the diode orientation. for (size_t row = 0; row < common_hal_keypad_keymatrix_get_num_rows(self); row++) { - // Switch this row to an output and set to low. + // Switch this row to an output and set level appropriately + // Set low if columns_to_anodes is true, else set high. common_hal_digitalio_digitalinout_switch_to_output( - self->row_digitalinouts->items[row], false, DRIVE_MODE_PUSH_PULL); + self->row_digitalinouts->items[row], !self->columns_to_anodes, DRIVE_MODE_PUSH_PULL); for (size_t col = 0; col < common_hal_keypad_keymatrix_get_num_cols(self); col++) { mp_uint_t key_num = row_col_to_key_num(self, row, col); const bool previous = self->currently_pressed[key_num]; self->previously_pressed[key_num] = previous; - // Get the current state, by reading whether the col got pulled down or not. - // If low, the key is pressed. + // Get the current state, by reading whether the col got pulled to the row value or not. + // If low and columns_to_anodes is true, the key is pressed. + // If high and columns_to_anodes is false, the key is pressed. const bool current = - !common_hal_digitalio_digitalinout_get_value(self->col_digitalinouts->items[col]); + common_hal_digitalio_digitalinout_get_value(self->col_digitalinouts->items[col]) != + self->columns_to_anodes; self->currently_pressed[key_num] = current; // Record any transitions. @@ -165,7 +171,8 @@ void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self) { } } - // Switch the row back to an input, pulled up. - common_hal_digitalio_digitalinout_switch_to_input(self->row_digitalinouts->items[row], PULL_UP); + // Switch the row back to an input, pulled appropriately + common_hal_digitalio_digitalinout_switch_to_input( + self->row_digitalinouts->items[row], self->columns_to_anodes ? PULL_UP : PULL_DOWN); } } diff --git a/shared-module/keypad/KeyMatrix.h b/shared-module/keypad/KeyMatrix.h index 253067890a..14c6f8069c 100644 --- a/shared-module/keypad/KeyMatrix.h +++ b/shared-module/keypad/KeyMatrix.h @@ -44,6 +44,7 @@ typedef struct { bool *previously_pressed; bool *currently_pressed; keypad_eventqueue_obj_t *events; + bool columns_to_anodes; } keypad_keymatrix_obj_t; void keypad_keymatrix_scan(keypad_keymatrix_obj_t *self);