From e5909fbd714484889f62bdcf8a4c0a85448c2640 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Tue, 16 Jul 2024 15:36:18 -0700 Subject: [PATCH] Add debouncing for layer change Fixes #1 --- Kconfig | 8 ++++++++ leds.c | 30 ++++++++++++++++++------------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Kconfig b/Kconfig index 8cb73b5..ee98a15 100644 --- a/Kconfig +++ b/Kconfig @@ -33,8 +33,16 @@ config RGBLED_WIDGET_BATTERY_LEVEL_CRITICAL config RGBLED_WIDGET_SHOW_LAYER_CHANGE bool "Indicate highest active layer on each layer change with a sequence of blinks" +if RGBLED_WIDGET_SHOW_LAYER_CHANGE + config RGBLED_WIDGET_LAYER_BLINK_MS int "Blink and wait duration for layer indicator" default 100 +config RGBLED_WIDGET_LAYER_DEBOUNCE_MS + int "Wait duration after a layer change before showing the highest active layer" + default 100 + +endif # RGBLED_WIDGET_SHOW_LAYER_CHANGE + endif diff --git a/leds.c b/leds.c index aa4c2d3..f7c5358 100644 --- a/leds.c +++ b/leds.c @@ -20,6 +20,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #define LED_GPIO_NODE_ID DT_COMPAT_GET_ANY_STATUS_OKAY(gpio_leds) +#define SHOW_LAYER_CHANGE \ + (IS_ENABLED(CONFIG_RGBLED_WIDGET_SHOW_LAYER_CHANGE)) && \ + (!IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)) + BUILD_ASSERT(DT_NODE_EXISTS(DT_ALIAS(led_red)), "An alias for a red LED is not found for RGBLED_WIDGET"); BUILD_ASSERT(DT_NODE_EXISTS(DT_ALIAS(led_green)), @@ -130,18 +134,18 @@ ZMK_LISTENER(led_battery_listener, led_battery_listener_cb); ZMK_SUBSCRIPTION(led_battery_listener, zmk_battery_state_changed); #endif // IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING) -#if IS_ENABLED(CONFIG_RGBLED_WIDGET_SHOW_LAYER_CHANGE) -#if !IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) -static int led_layer_listener_cb(const zmk_event_t *eh) { - if (!initialized) { - return 0; - } +#if SHOW_LAYER_CHANGE +static struct k_work_delayable layer_indicate_work; - // ignore layer off events - if (!as_zmk_layer_state_changed(eh)->state) { - return 0; +static int led_layer_listener_cb(const zmk_event_t *eh) { + // ignore if not initialized yet or layer off events + if (initialized && as_zmk_layer_state_changed(eh)->state) { + k_work_reschedule(&layer_indicate_work, K_MSEC(CONFIG_RGBLED_WIDGET_LAYER_DEBOUNCE_MS)); } + return 0; +} +static void indicate_layer(struct k_work *work) { uint8_t index = zmk_keymap_highest_layer_active(); static const struct blink_item blink = {.duration_ms = CONFIG_RGBLED_WIDGET_LAYER_BLINK_MS, .color = LED_CYAN, @@ -155,19 +159,21 @@ static int led_layer_listener_cb(const zmk_event_t *eh) { k_msgq_put(&led_msgq, &last_blink, K_NO_WAIT); } } - return 0; } ZMK_LISTENER(led_layer_listener, led_layer_listener_cb); ZMK_SUBSCRIPTION(led_layer_listener, zmk_layer_state_changed); -#endif -#endif // IS_ENABLED(CONFIG_RGBLED_WIDGET_SHOW_LAYER_CHANGE) +#endif // SHOW_LAYER_CHANGE extern void led_process_thread(void *d0, void *d1, void *d2) { ARG_UNUSED(d0); ARG_UNUSED(d1); ARG_UNUSED(d2); +#if SHOW_LAYER_CHANGE + k_work_init_delayable(&layer_indicate_work, indicate_layer); +#endif + while (true) { // wait until a blink item is received and process it struct blink_item blink;