refactor: Promote debounce to exposed mod lib.

* Promote previously local debounce code from kscan drivers to exposed
  module lib, for use with other drivers as needed.
* Refactor existing kscan driver to new "public" API.
This commit is contained in:
Peter Johanson 2023-09-11 21:56:37 -07:00 committed by Pete Johanson
parent c28ef1b61e
commit 0ca7f69b6d
12 changed files with 54 additions and 40 deletions

View File

@ -1,3 +1,4 @@
zephyr_include_directories(include)
add_subdirectory(drivers)
add_subdirectory(drivers)
add_subdirectory(lib)

View File

@ -1,2 +1,3 @@
rsource "drivers/Kconfig"
rsource "drivers/Kconfig"
rsource "lib/Kconfig"

View File

@ -3,7 +3,6 @@
zephyr_library_amend()
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER debounce.c)
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER kscan_gpio.c)
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_MATRIX kscan_gpio_matrix.c)
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DIRECT kscan_gpio_direct.c)

View File

@ -16,6 +16,7 @@ config ZMK_KSCAN_COMPOSITE_DRIVER
config ZMK_KSCAN_GPIO_DRIVER
bool
select GPIO
select ZMK_DEBOUNCE
config ZMK_KSCAN_GPIO_DEMUX
bool

View File

@ -4,7 +4,6 @@
* SPDX-License-Identifier: MIT
*/
#include "debounce.h"
#include "kscan_gpio.h"
#include <zephyr/device.h>
@ -15,6 +14,8 @@
#include <zephyr/logging/log.h>
#include <zephyr/sys/util.h>
#include <zmk/debounce.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define DT_DRV_COMPAT zmk_kscan_gpio_direct
@ -61,11 +62,11 @@ struct kscan_direct_data {
/** Timestamp of the current or scheduled scan. */
int64_t scan_time;
/** Current state of the inputs as an array of length config->inputs.len */
struct debounce_state *pin_state;
struct zmk_debounce_state *pin_state;
};
struct kscan_direct_config {
struct debounce_config debounce_config;
struct zmk_debounce_config debounce_config;
int32_t debounce_scan_period_ms;
int32_t poll_period_ms;
bool toggle_mode;
@ -182,8 +183,8 @@ static int kscan_direct_read(const struct device *dev) {
return active;
}
debounce_update(&data->pin_state[gpio->index], active, config->debounce_scan_period_ms,
&config->debounce_config);
zmk_debounce_update(&data->pin_state[gpio->index], active, config->debounce_scan_period_ms,
&config->debounce_config);
}
// Process the new state.
@ -191,10 +192,10 @@ static int kscan_direct_read(const struct device *dev) {
for (int i = 0; i < data->inputs.len; i++) {
const struct kscan_gpio *gpio = &data->inputs.gpios[i];
struct debounce_state *state = &data->pin_state[gpio->index];
struct zmk_debounce_state *state = &data->pin_state[gpio->index];
if (debounce_get_changed(state)) {
const bool pressed = debounce_is_pressed(state);
if (zmk_debounce_get_changed(state)) {
const bool pressed = zmk_debounce_is_pressed(state);
LOG_DBG("Sending event at 0,%i state %s", gpio->index, pressed ? "on" : "off");
data->callback(dev, 0, gpio->index, pressed);
@ -203,7 +204,7 @@ static int kscan_direct_read(const struct device *dev) {
}
}
continue_scan = continue_scan || debounce_is_active(state);
continue_scan = continue_scan || zmk_debounce_is_active(state);
}
if (continue_scan) {
@ -332,7 +333,7 @@ static const struct kscan_driver_api kscan_direct_api = {
static struct kscan_gpio kscan_direct_inputs_##n[] = { \
LISTIFY(INST_INPUTS_LEN(n), KSCAN_DIRECT_INPUT_CFG_INIT, (, ), n)}; \
\
static struct debounce_state kscan_direct_state_##n[INST_INPUTS_LEN(n)]; \
static struct zmk_debounce_state kscan_direct_state_##n[INST_INPUTS_LEN(n)]; \
\
COND_INTERRUPTS( \
(static struct kscan_direct_irq_callback kscan_direct_irqs_##n[INST_INPUTS_LEN(n)];)) \

View File

@ -4,7 +4,6 @@
* SPDX-License-Identifier: MIT
*/
#include "debounce.h"
#include "kscan_gpio.h"
#include <zephyr/device.h>
@ -16,6 +15,8 @@
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/util.h>
#include <zmk/debounce.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define DT_DRV_COMPAT zmk_kscan_gpio_matrix
@ -80,12 +81,12 @@ struct kscan_matrix_data {
* Current state of the matrix as a flattened 2D array of length
* (config->rows * config->cols)
*/
struct debounce_state *matrix_state;
struct zmk_debounce_state *matrix_state;
};
struct kscan_matrix_config {
struct kscan_gpio_list outputs;
struct debounce_config debounce_config;
struct zmk_debounce_config debounce_config;
size_t rows;
size_t cols;
int32_t debounce_scan_period_ms;
@ -242,8 +243,8 @@ static int kscan_matrix_read(const struct device *dev) {
return active;
}
debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms,
&config->debounce_config);
zmk_debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms,
&config->debounce_config);
}
err = gpio_pin_set_dt(&out_gpio->spec, 0);
@ -263,16 +264,16 @@ static int kscan_matrix_read(const struct device *dev) {
for (int r = 0; r < config->rows; r++) {
for (int c = 0; c < config->cols; c++) {
const int index = state_index_rc(config, r, c);
struct debounce_state *state = &data->matrix_state[index];
struct zmk_debounce_state *state = &data->matrix_state[index];
if (debounce_get_changed(state)) {
const bool pressed = debounce_is_pressed(state);
if (zmk_debounce_get_changed(state)) {
const bool pressed = zmk_debounce_is_pressed(state);
LOG_DBG("Sending event at %i,%i state %s", r, c, pressed ? "on" : "off");
data->callback(dev, r, c, pressed);
}
continue_scan = continue_scan || debounce_is_active(state);
continue_scan = continue_scan || zmk_debounce_is_active(state);
}
}
@ -438,7 +439,7 @@ static const struct kscan_driver_api kscan_matrix_api = {
static struct kscan_gpio kscan_matrix_cols_##n[] = { \
LISTIFY(INST_COLS_LEN(n), KSCAN_GPIO_COL_CFG_INIT, (, ), n)}; \
\
static struct debounce_state kscan_matrix_state_##n[INST_MATRIX_LEN(n)]; \
static struct zmk_debounce_state kscan_matrix_state_##n[INST_MATRIX_LEN(n)]; \
\
COND_INTERRUPTS( \
(static struct kscan_matrix_irq_callback kscan_matrix_irqs_##n[INST_INPUTS_LEN(n)];)) \

View File

@ -13,13 +13,13 @@
#define DEBOUNCE_COUNTER_BITS 14
#define DEBOUNCE_COUNTER_MAX BIT_MASK(DEBOUNCE_COUNTER_BITS)
struct debounce_state {
struct zmk_debounce_state {
bool pressed : 1;
bool changed : 1;
uint16_t counter : DEBOUNCE_COUNTER_BITS;
};
struct debounce_config {
struct zmk_debounce_config {
/** Duration a switch must be pressed to latch as pressed. */
uint32_t debounce_press_ms;
/** Duration a switch must be released to latch as released. */
@ -34,23 +34,23 @@ struct debounce_config {
* @param elapsed_ms Time elapsed since the previous update in milliseconds.
* @param config Debounce settings.
*/
void debounce_update(struct debounce_state *state, const bool active, const int elapsed_ms,
const struct debounce_config *config);
void zmk_debounce_update(struct zmk_debounce_state *state, const bool active, const int elapsed_ms,
const struct zmk_debounce_config *config);
/**
* @returns whether the switch is either latched as pressed or it is potentially
* pressed but the debouncer has not yet made a decision. If this returns true,
* the kscan driver should continue to poll quickly.
*/
bool debounce_is_active(const struct debounce_state *state);
bool zmk_debounce_is_active(const struct zmk_debounce_state *state);
/**
* @returns whether the switch is latched as pressed.
*/
bool debounce_is_pressed(const struct debounce_state *state);
bool zmk_debounce_is_pressed(const struct zmk_debounce_state *state);
/**
* @returns whether the pressed state of the switch changed in the last call to
* debounce_update.
*/
bool debounce_get_changed(const struct debounce_state *state);
bool zmk_debounce_get_changed(const struct zmk_debounce_state *state);

View File

@ -0,0 +1,2 @@
add_subdirectory_ifdef(CONFIG_ZMK_DEBOUNCE zmk_debounce)

2
app/module/lib/Kconfig Normal file
View File

@ -0,0 +1,2 @@
rsource "zmk_debounce/Kconfig"

View File

@ -0,0 +1,3 @@
zephyr_library()
zephyr_library_sources(debounce.c)

View File

@ -0,0 +1,3 @@
config ZMK_DEBOUNCE
bool "Debounce Support"

View File

@ -4,14 +4,14 @@
* SPDX-License-Identifier: MIT
*/
#include "debounce.h"
#include <zmk/debounce.h>
static uint32_t get_threshold(const struct debounce_state *state,
const struct debounce_config *config) {
static uint32_t get_threshold(const struct zmk_debounce_state *state,
const struct zmk_debounce_config *config) {
return state->pressed ? config->debounce_release_ms : config->debounce_press_ms;
}
static void increment_counter(struct debounce_state *state, const int elapsed_ms) {
static void increment_counter(struct zmk_debounce_state *state, const int elapsed_ms) {
if (state->counter + elapsed_ms > DEBOUNCE_COUNTER_MAX) {
state->counter = DEBOUNCE_COUNTER_MAX;
} else {
@ -19,7 +19,7 @@ static void increment_counter(struct debounce_state *state, const int elapsed_ms
}
}
static void decrement_counter(struct debounce_state *state, const int elapsed_ms) {
static void decrement_counter(struct zmk_debounce_state *state, const int elapsed_ms) {
if (state->counter < elapsed_ms) {
state->counter = 0;
} else {
@ -27,8 +27,8 @@ static void decrement_counter(struct debounce_state *state, const int elapsed_ms
}
}
void debounce_update(struct debounce_state *state, const bool active, const int elapsed_ms,
const struct debounce_config *config) {
void zmk_debounce_update(struct zmk_debounce_state *state, const bool active, const int elapsed_ms,
const struct zmk_debounce_config *config) {
// This uses a variation of the integrator debouncing described at
// https://www.kennethkuhn.com/electronics/debounce.c
// Every update where "active" does not match the current state, we increment
@ -53,10 +53,10 @@ void debounce_update(struct debounce_state *state, const bool active, const int
state->changed = true;
}
bool debounce_is_active(const struct debounce_state *state) {
bool zmk_debounce_is_active(const struct zmk_debounce_state *state) {
return state->pressed || state->counter > 0;
}
bool debounce_is_pressed(const struct debounce_state *state) { return state->pressed; }
bool zmk_debounce_is_pressed(const struct zmk_debounce_state *state) { return state->pressed; }
bool debounce_get_changed(const struct debounce_state *state) { return state->changed; }
bool zmk_debounce_get_changed(const struct zmk_debounce_state *state) { return state->changed; }