kscan: Limit maximum amount of key presses to 3

When using a keyboard without diodes in the key matrix, ghosting can
become a serious issue. Quite often three keys held at the same time are
needed to produce a ghosted fourth key press when using a row, col based
keyboard matrix. In these cases it makes sense to allow only three key
presses at the same time, ignoring all of them if a fourth is pressed.

The changes made here are a simple work-of-proof how this "limit the
amount of key presses" could be done.

Note: There's no configuration options or similar to change this
behavior right now.

Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
This commit is contained in:
Sophie Tyalie 2022-11-11 15:23:30 +01:00
parent 768fc4a5e5
commit 412376e8a4

View file

@ -225,6 +225,8 @@ static int kscan_matrix_read(const struct device *dev) {
struct kscan_matrix_data *data = dev->data; struct kscan_matrix_data *data = dev->data;
const struct kscan_matrix_config *config = dev->config; const struct kscan_matrix_config *config = dev->config;
int num_active = 0;
int stored_states[3] = {0};
// Scan the matrix. // Scan the matrix.
for (int o = 0; o < config->outputs.len; o++) { for (int o = 0; o < config->outputs.len; o++) {
const struct gpio_dt_spec *out_gpio = &config->outputs.gpios[o]; const struct gpio_dt_spec *out_gpio = &config->outputs.gpios[o];
@ -245,10 +247,21 @@ static int kscan_matrix_read(const struct device *dev) {
const int index = state_index_io(config, i, o); const int index = state_index_io(config, i, o);
const bool active = gpio_pin_get_dt(in_gpio); const bool active = gpio_pin_get_dt(in_gpio);
debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms,
if (active) {
if (num_active < sizeof(stored_states) / sizeof(stored_states[0])) {
stored_states[num_active] = index;
}
num_active++;
} else {
debounce_update(&data->matrix_state[index], active,
config->debounce_scan_period_ms,
&config->debounce_config); &config->debounce_config);
} }
}
err = gpio_pin_set_dt(out_gpio, 0); err = gpio_pin_set_dt(out_gpio, 0);
if (err) { if (err) {
LOG_ERR("Failed to set output %i inactive: %i", o, err); LOG_ERR("Failed to set output %i inactive: %i", o, err);
@ -260,6 +273,14 @@ static int kscan_matrix_read(const struct device *dev) {
#endif #endif
} }
if (0 < num_active && num_active <= 3) {
for (int i = 0; i < num_active; i++) {
int index = stored_states[i];
debounce_update(&data->matrix_state[index], true, config->debounce_scan_period_ms,
&config->debounce_config);
}
}
// Process the new state. // Process the new state.
bool continue_scan = false; bool continue_scan = false;