ShiftRegisterKeys: allow specifying sense of latch

This commit is contained in:
Dan Halbert 2021-06-21 19:03:48 -04:00
parent 8c74b4a5f2
commit f052dc4d8b
4 changed files with 18 additions and 11 deletions

View File

@ -36,10 +36,10 @@
//| class ShiftRegisterKeys:
//| """Manage a set of keys attached to an incoming shift register."""
//|
//| def __init__(self, clock: microcontroller.Pin, data: microcontroller.Pin, latch: microcontroller.Pin, value_when_pressed: bool, interval: float = 0.020, max_events: int = 64) -> None:
//| def __init__(self, *, clock: microcontroller.Pin, data: microcontroller.Pin, latch: microcontroller.Pin, value_to_latch: bool = True, num_keys: int, value_when_pressed: bool, interval: float = 0.020, max_events: int = 64) -> None:
//| """
//| Create a `Keys` object that will scan keys attached to a parallel-in serial-out shift register
//| like the 74HC165 or equivalent.
//| like the 74HC165 or CD4021.
//| Note that you may chain shift registers to load in as many values as you need.
//|
//| Key number 0 is the first (or more properly, the zero-th) bit read. In the
@ -53,8 +53,12 @@
//| The shift register should clock on a low-to-high transition.
//| :param microcontroller.Pin data: the incoming shift register data pin
//| :param microcontroller.Pin latch:
//| Pin used to trigger loading parallel data pins into the shift register.
//| Active low: pull low to load the data.
//| Pin used to latch parallel data going into the shift register.
//| :param bool value_to_latch: Pin state to latch data being read.
//| ``True`` if the data is latched when ``latch`` goes high
//| ``False`` if the data is latched when ``latch goes low.
//| The default is ``True``, which is how the 74HC165 operates. The CD4021 latch is the opposite.
//| Once the data is latched, it will be shifted out by toggling the clock pin.
//| :param int num_keys: number of data lines to clock in
//| :param bool value_when_pressed: ``True`` if the pin reads high when the key is pressed.
//| ``False`` if the pin reads low (is grounded) when the key is pressed.
@ -70,11 +74,12 @@
STATIC mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
keypad_shiftregisterkeys_obj_t *self = m_new_obj(keypad_shiftregisterkeys_obj_t);
self->base.type = &keypad_shiftregisterkeys_type;
enum { ARG_clock, ARG_data, ARG_latch, ARG_num_keys, ARG_value_when_pressed, ARG_interval, ARG_max_events };
enum { ARG_clock, ARG_data, ARG_latch, ARG_value_to_latch, ARG_num_keys, ARG_value_when_pressed, ARG_interval, ARG_max_events };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_clock, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_latch, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_value_to_latch, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
{ MP_QSTR_num_keys, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_value_when_pressed, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_BOOL },
{ MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
@ -86,6 +91,7 @@ STATIC mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, siz
mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj);
mcu_pin_obj_t *data = validate_obj_is_free_pin(args[ARG_data].u_obj);
mcu_pin_obj_t *latch = validate_obj_is_free_pin(args[ARG_latch].u_obj);
const bool value_to_latch = args[ARG_value_to_latch].u_bool;
const size_t num_keys = (size_t)mp_arg_validate_int_min(args[ARG_num_keys].u_int, 1, MP_QSTR_num_keys);
const bool value_when_pressed = args[ARG_value_when_pressed].u_bool;
@ -94,7 +100,7 @@ STATIC mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, siz
const size_t max_events = (size_t)mp_arg_validate_int_min(args[ARG_max_events].u_int, 1, MP_QSTR_max_events);
common_hal_keypad_shiftregisterkeys_construct(
self, clock, data, latch, num_keys, value_when_pressed, interval, max_events);
self, clock, data, latch, value_to_latch, num_keys, value_when_pressed, interval, max_events);
return MP_OBJ_FROM_PTR(self);
}

View File

@ -32,7 +32,7 @@
extern const mp_obj_type_t keypad_shiftregisterkeys_type;
void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_t *self, mcu_pin_obj_t *clock_pin, mcu_pin_obj_t *data_pin, mcu_pin_obj_t *latch_pin, size_t num_keys, bool value_when_pressed, mp_float_t interval, size_t max_events);
void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_t *self, mcu_pin_obj_t *clock_pin, mcu_pin_obj_t *data_pin, mcu_pin_obj_t *latch_pin, bool value_to_latch, size_t num_keys, bool value_when_pressed, mp_float_t interval, size_t max_events);
void common_hal_keypad_shiftregisterkeys_deinit(keypad_shiftregisterkeys_obj_t *self);
bool common_hal_keypad_shiftregisterkeys_deinited(keypad_shiftregisterkeys_obj_t *self);

View File

@ -35,7 +35,7 @@
#include "supervisor/port.h"
#include "supervisor/shared/tick.h"
void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_t *self, mcu_pin_obj_t *clock_pin, mcu_pin_obj_t *data_pin, mcu_pin_obj_t *latch_pin, size_t num_keys, bool value_when_pressed, mp_float_t interval, size_t max_events) {
void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_t *self, mcu_pin_obj_t *clock_pin, mcu_pin_obj_t *data_pin, mcu_pin_obj_t *latch_pin, bool value_to_latch, size_t num_keys, bool value_when_pressed, mp_float_t interval, size_t max_events) {
digitalio_digitalinout_obj_t *clock = m_new_obj(digitalio_digitalinout_obj_t);
clock->base.type = &digitalio_digitalinout_type;
@ -54,6 +54,7 @@ void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_
common_hal_digitalio_digitalinout_construct(latch, latch_pin);
common_hal_digitalio_digitalinout_switch_to_output(latch, true, DRIVE_MODE_PUSH_PULL);
self->latch = latch;
self->value_to_latch = value_to_latch;
self->currently_pressed = (bool *)gc_alloc(sizeof(bool) * num_keys, false, false);
self->previously_pressed = (bool *)gc_alloc(sizeof(bool) * num_keys, false, false);
@ -126,7 +127,7 @@ void keypad_shiftregisterkeys_scan(keypad_shiftregisterkeys_obj_t *self) {
self->last_scan_ticks = now;
// Latch (freeze) the current state of the input pins.
common_hal_digitalio_digitalinout_set_value(self->latch, true);
common_hal_digitalio_digitalinout_set_value(self->latch, self->value_to_latch);
for (mp_uint_t key_num = 0; key_num < common_hal_keypad_shiftregisterkeys_get_num_keys(self); key_num++) {
// Zero-th data appears on on the data pin immediately, without shifting.
@ -151,6 +152,5 @@ void keypad_shiftregisterkeys_scan(keypad_shiftregisterkeys_obj_t *self) {
}
// Start reading the input pins again.
common_hal_digitalio_digitalinout_set_value(self->latch, false);
common_hal_digitalio_digitalinout_set_value(self->latch, !self->value_to_latch);
}

View File

@ -48,6 +48,7 @@ typedef struct {
bool *currently_pressed;
keypad_eventqueue_obj_t *events;
bool value_when_pressed;
bool value_to_latch;
} keypad_shiftregisterkeys_obj_t;
void keypad_shiftregisterkeys_scan(keypad_shiftregisterkeys_obj_t *self);