Skip to content

Commit

Permalink
refactor: Promote debounce to exposed mod lib.
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
petejohanson committed Sep 15, 2023
1 parent af5f5a6 commit 396a43b
Show file tree
Hide file tree
Showing 12 changed files with 54 additions and 40 deletions.
3 changes: 2 additions & 1 deletion app/module/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
zephyr_include_directories(include)

add_subdirectory(drivers)
add_subdirectory(drivers)
add_subdirectory(lib)
3 changes: 2 additions & 1 deletion app/module/Kconfig
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@

rsource "drivers/Kconfig"
rsource "drivers/Kconfig"
rsource "lib/Kconfig"
1 change: 0 additions & 1 deletion app/module/drivers/kscan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions app/module/drivers/kscan/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 11 additions & 10 deletions app/module/drivers/kscan/kscan_gpio_direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* SPDX-License-Identifier: MIT
*/

#include "debounce.h"
#include "kscan_gpio.h"

#include <zephyr/device.h>
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -182,19 +183,19 @@ 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.
bool continue_scan = false;

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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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)];)) \
Expand Down
21 changes: 11 additions & 10 deletions app/module/drivers/kscan/kscan_gpio_matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* SPDX-License-Identifier: MIT
*/

#include "debounce.h"
#include "kscan_gpio.h"

#include <zephyr/device.h>
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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)];)) \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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);
2 changes: 2 additions & 0 deletions app/module/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

add_subdirectory_ifdef(CONFIG_ZMK_DEBOUNCE zmk_debounce)
2 changes: 2 additions & 0 deletions app/module/lib/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

rsource "zmk_debounce/Kconfig"
3 changes: 3 additions & 0 deletions app/module/lib/zmk_debounce/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

zephyr_library()
zephyr_library_sources(debounce.c)
3 changes: 3 additions & 0 deletions app/module/lib/zmk_debounce/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

config ZMK_DEBOUNCE
bool "Debounce Support"
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,31 @@
* 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 {
state->counter += 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 {
state->counter -= 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
Expand All @@ -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; }

0 comments on commit 396a43b

Please sign in to comment.