input: kbd_matrix: implement stable poll period support

Implement a new stable-poll-period-ms property to specify a new (slower)
polling rate for when the matrix is stable.

The keyboard thread can eat up a surprisingly high amount of cpu cycles in
busy waiting if the specific hardware implementation happen to have a
particularly slow settle time, but high frequency polling is really only
needed when debouncing.

The new property allow slowing down the polling rate when the matrix is
stable (either key pressed but none to be debounced or idle in the case
of the gpio implementation with no interrupts), this allows reducing the
overall cpu time taken by the keyboard scanning thread when keys are
persistently pressed.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
This commit is contained in:
Fabio Baltieri 2024-10-23 18:06:00 +01:00 committed by Anas Nashif
parent 410c8a57e0
commit 13a2f42d50
4 changed files with 33 additions and 5 deletions

View file

@ -121,7 +121,7 @@ static __maybe_unused void gpio_kbd_matrix_idle_poll_handler(const struct device
if (gpio_kbd_matrix_read_row(dev) == 0) {
k_work_reschedule(cfg->idle_poll_dwork,
K_USEC(common->poll_period_us));
K_USEC(common->stable_poll_period_us));
return;
}
@ -137,7 +137,7 @@ static void gpio_kbd_matrix_set_detect_mode(const struct device *dev, bool enabl
if (cfg->idle_poll_dwork != NULL) {
if (enabled) {
k_work_reschedule(cfg->idle_poll_dwork,
K_USEC(common->poll_period_us));
K_USEC(common->stable_poll_period_us));
}
return;
}

View file

@ -264,6 +264,19 @@ static k_timepoint_t input_kbd_matrix_poll_timeout(const struct device *dev)
return sys_timepoint_calc(K_MSEC(cfg->poll_timeout_ms));
}
static bool input_kbd_matrix_is_unstable(const struct device *dev)
{
const struct input_kbd_matrix_common_config *cfg = dev->config;
for (uint8_t c = 0; c < cfg->col_size; c++) {
if (cfg->matrix_unstable_state[c] != 0) {
return true;
}
}
return false;
}
static void input_kbd_matrix_poll(const struct device *dev)
{
const struct input_kbd_matrix_common_config *cfg = dev->config;
@ -271,6 +284,7 @@ static void input_kbd_matrix_poll(const struct device *dev)
uint32_t current_cycles;
uint32_t cycles_diff;
uint32_t wait_period_us;
uint32_t poll_period_us;
poll_time_end = input_kbd_matrix_poll_timeout(dev);
@ -289,10 +303,14 @@ static void input_kbd_matrix_poll(const struct device *dev)
*/
current_cycles = k_cycle_get_32();
cycles_diff = current_cycles - start_period_cycles;
wait_period_us = cfg->poll_period_us - k_cyc_to_us_floor32(cycles_diff);
wait_period_us = CLAMP(wait_period_us,
USEC_PER_MSEC, cfg->poll_period_us);
if (input_kbd_matrix_is_unstable(dev)) {
poll_period_us = cfg->poll_period_us;
} else {
poll_period_us = cfg->stable_poll_period_us;
}
wait_period_us = CLAMP(poll_period_us - k_cyc_to_us_floor32(cycles_diff),
USEC_PER_MSEC, poll_period_us);
LOG_DBG("wait_period_us: %d", wait_period_us);

View file

@ -23,6 +23,12 @@ properties:
Defines the poll period in msecs between between matrix scans, set to 0
to never exit poll mode. Defaults to 5ms if unspecified.
stable-poll-period-ms:
type: int
description: |
Defines the poll period in msecs between matrix scans when the matrix is
stable, defaults to poll-period-ms value if unspecified.
poll-timeout-ms:
type: int
default: 100

View file

@ -113,6 +113,7 @@ struct input_kbd_matrix_common_config {
uint8_t row_size;
uint8_t col_size;
uint32_t poll_period_us;
uint32_t stable_poll_period_us;
uint32_t poll_timeout_ms;
uint32_t debounce_down_us;
uint32_t debounce_up_us;
@ -192,6 +193,9 @@ struct input_kbd_matrix_common_config {
.row_size = _row_size, \
.col_size = _col_size, \
.poll_period_us = DT_PROP(node_id, poll_period_ms) * USEC_PER_MSEC, \
.stable_poll_period_us = DT_PROP_OR(node_id, stable_poll_period_ms, \
DT_PROP(node_id, poll_period_ms)) * \
USEC_PER_MSEC, \
.poll_timeout_ms = DT_PROP(node_id, poll_timeout_ms), \
.debounce_down_us = DT_PROP(node_id, debounce_down_ms) * USEC_PER_MSEC, \
.debounce_up_us = DT_PROP(node_id, debounce_up_ms) * USEC_PER_MSEC, \