diff --git a/app/Kconfig b/app/Kconfig index 30d8e8cd082..3906a6b1481 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -288,6 +288,9 @@ menuconfig ZMK_RGB_UNDERGLOW if ZMK_RGB_UNDERGLOW +config ZMK_RGB_UNDERGLOW_TICK_PERIOD_MS + int "RGB animation tick period (ms)" + config ZMK_RGB_UNDERGLOW_EXT_POWER bool "RGB underglow toggling also controls external power" diff --git a/app/Kconfig.defaults b/app/Kconfig.defaults index 8800b454f40..d28cb13e6d4 100644 --- a/app/Kconfig.defaults +++ b/app/Kconfig.defaults @@ -53,6 +53,9 @@ if ZMK_RGB_UNDERGLOW config SPI default y +config ZMK_RGB_UNDERGLOW_TICK_PERIOD_MS + default 50 + config ZMK_RGB_UNDERGLOW_EXT_POWER default y diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c index 3453fb44e0d..fe1fbd48a29 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -207,34 +207,48 @@ static void zmk_rgb_underglow_tick_handler(struct k_timer *timer) { k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &underglow_tick_work); } -K_TIMER_DEFINE(underglow_tick, zmk_rgb_underglow_tick_handler, NULL); +static void zmk_rgb_underglow_off_handler(struct k_work *work) { + for (int i = 0; i < STRIP_NUM_PIXELS; i++) { + pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0}; + } + + led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS); +} + +K_WORK_DEFINE(underglow_off_work, zmk_rgb_underglow_off_handler); + +static void zmk_rgb_underglow_tick_stop_handler(struct k_timer *timer) { + + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &underglow_off_work); +} + +K_TIMER_DEFINE(underglow_tick, zmk_rgb_underglow_tick_handler, zmk_rgb_underglow_tick_stop_handler); #if IS_ENABLED(CONFIG_SETTINGS) static int rgb_settings_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) { const char *next; - int rc; if (settings_name_steq(name, "state", &next) && !next) { if (len != sizeof(state)) { return -EINVAL; } - rc = read_cb(cb_arg, &state, sizeof(state)); - if (rc >= 0) { - if (state.on) { - k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); - } + return read_cb(cb_arg, &state, sizeof(state)); + } - return 0; - } + return -ENOENT; +} - return rc; +static int rgb_settings_commit(void) { + if (state.on) { + k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(CONFIG_ZMK_RGB_UNDERGLOW_TICK_PERIOD_MS)); } - return -ENOENT; + return 0; } -SETTINGS_STATIC_HANDLER_DEFINE(rgb_underglow, "rgb/underglow", NULL, rgb_settings_set, NULL, NULL); +SETTINGS_STATIC_HANDLER_DEFINE(rgb_underglow, "rgb/underglow", NULL, rgb_settings_set, + rgb_settings_commit, NULL); static void zmk_rgb_underglow_save_state_work(struct k_work *_work) { settings_save_one("rgb/underglow/state", &state, sizeof(state)); @@ -273,9 +287,11 @@ static int zmk_rgb_underglow_init(void) { state.on = zmk_usb_is_powered(); #endif +#if !IS_ENABLED(CONFIG_SETTINGS) if (state.on) { - k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); + k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(CONFIG_ZMK_RGB_UNDERGLOW_TICK_PERIOD_MS)); } +#endif return 0; } @@ -312,21 +328,11 @@ int zmk_rgb_underglow_on(void) { state.on = true; state.animation_step = 0; - k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); + k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(CONFIG_ZMK_RGB_UNDERGLOW_TICK_PERIOD_MS)); return zmk_rgb_underglow_save_state(); } -static void zmk_rgb_underglow_off_handler(struct k_work *work) { - for (int i = 0; i < STRIP_NUM_PIXELS; i++) { - pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0}; - } - - led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS); -} - -K_WORK_DEFINE(underglow_off_work, zmk_rgb_underglow_off_handler); - int zmk_rgb_underglow_off(void) { if (!led_strip) return -ENODEV; @@ -340,10 +346,8 @@ int zmk_rgb_underglow_off(void) { } #endif - k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &underglow_off_work); - - k_timer_stop(&underglow_tick); state.on = false; + k_timer_stop(&underglow_tick); return zmk_rgb_underglow_save_state(); } diff --git a/docs/docs/config/lighting.md b/docs/docs/config/lighting.md index ceb49db89a0..e703038c604 100644 --- a/docs/docs/config/lighting.md +++ b/docs/docs/config/lighting.md @@ -17,23 +17,24 @@ RGB underglow depends on [Zephyr's LED strip driver](https://github.com/zephyrpr Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/Kconfig) -| Config | Type | Description | Default | -| ---------------------------------------- | ---- | --------------------------------------------------------- | ------- | -| `CONFIG_ZMK_RGB_UNDERGLOW` | bool | Enable RGB underglow | n | -| `CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER` | bool | Underglow toggling also controls external power | y | -| `CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE` | bool | Turn off RGB underglow when keyboard goes into idle state | n | -| `CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB` | bool | Turn off RGB underglow when USB is disconnected | n | -| `CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP` | int | Hue step in degrees (0-359) used by RGB actions | 10 | -| `CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP` | int | Saturation step in percent used by RGB actions | 10 | -| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP` | int | Brightness step in percent used by RGB actions | 10 | -| `CONFIG_ZMK_RGB_UNDERGLOW_HUE_START` | int | Default hue in degrees (0-359) | 0 | -| `CONFIG_ZMK_RGB_UNDERGLOW_SAT_START` | int | Default saturation percent (0-100) | 100 | -| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_START` | int | Default brightness in percent (0-100) | 100 | -| `CONFIG_ZMK_RGB_UNDERGLOW_SPD_START` | int | Default effect speed (1-5) | 3 | -| `CONFIG_ZMK_RGB_UNDERGLOW_EFF_START` | int | Default effect index from the effect list (see below) | 0 | -| `CONFIG_ZMK_RGB_UNDERGLOW_ON_START` | bool | Default on state | y | -| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN` | int | Minimum brightness in percent (0-100) | 0 | -| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX` | int | Maximum brightness in percent (0-100) | 100 | +| Config | Type | Description | Default | +| ----------------------------------------- | ---- | --------------------------------------------------------------------------- | ------- | +| `CONFIG_ZMK_RGB_UNDERGLOW` | bool | Enable RGB underglow | n | +| `CONFIG_ZMK_RGB_UNDERGLOW_TICK_PERIOD_MS` | int | Period in milliseconds, between ticks of the underglow animation processing | 50 | +| `CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER` | bool | Underglow toggling also controls external power | y | +| `CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE` | bool | Turn off RGB underglow when keyboard goes into idle state | n | +| `CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB` | bool | Turn off RGB underglow when USB is disconnected | n | +| `CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP` | int | Hue step in degrees (0-359) used by RGB actions | 10 | +| `CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP` | int | Saturation step in percent used by RGB actions | 10 | +| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP` | int | Brightness step in percent used by RGB actions | 10 | +| `CONFIG_ZMK_RGB_UNDERGLOW_HUE_START` | int | Default hue in degrees (0-359) | 0 | +| `CONFIG_ZMK_RGB_UNDERGLOW_SAT_START` | int | Default saturation percent (0-100) | 100 | +| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_START` | int | Default brightness in percent (0-100) | 100 | +| `CONFIG_ZMK_RGB_UNDERGLOW_SPD_START` | int | Default effect speed (1-5) | 3 | +| `CONFIG_ZMK_RGB_UNDERGLOW_EFF_START` | int | Default effect index from the effect list (see below) | 0 | +| `CONFIG_ZMK_RGB_UNDERGLOW_ON_START` | bool | Default on state | y | +| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN` | int | Minimum brightness in percent (0-100) | 0 | +| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX` | int | Maximum brightness in percent (0-100) | 100 | Values for `CONFIG_ZMK_RGB_UNDERGLOW_EFF_START`: