You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
1.9 KiB
62 lines
1.9 KiB
/* |
|
* Copyright (c) 2021 The ZMK Contributors |
|
* |
|
* SPDX-License-Identifier: MIT |
|
*/ |
|
|
|
#include "debounce.h" |
|
|
|
static uint32_t get_threshold(const struct debounce_state *state, |
|
const struct 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) { |
|
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) { |
|
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) { |
|
// 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 |
|
// a counter, otherwise we decrement it. When the counter reaches a |
|
// threshold, the state flips and we reset the counter. |
|
state->changed = false; |
|
|
|
if (active == state->pressed) { |
|
decrement_counter(state, elapsed_ms); |
|
return; |
|
} |
|
|
|
const uint32_t flip_threshold = get_threshold(state, config); |
|
|
|
if (state->counter < flip_threshold) { |
|
increment_counter(state, elapsed_ms); |
|
return; |
|
} |
|
|
|
state->pressed = !state->pressed; |
|
state->counter = 0; |
|
state->changed = true; |
|
} |
|
|
|
bool debounce_is_active(const struct debounce_state *state) { |
|
return state->pressed || state->counter > 0; |
|
} |
|
|
|
bool debounce_is_pressed(const struct debounce_state *state) { return state->pressed; } |
|
|
|
bool debounce_get_changed(const struct debounce_state *state) { return state->changed; } |