diff --git a/app/dts/behaviors/backlight.dtsi b/app/dts/behaviors/backlight.dtsi index b05d97ae..6127f605 100644 --- a/app/dts/behaviors/backlight.dtsi +++ b/app/dts/behaviors/backlight.dtsi @@ -9,7 +9,7 @@ /omit-if-no-ref/ bl: behavior_backlight { compatible = "zmk,behavior-backlight"; label = "BACKLIGHT"; - #binding-cells = <1>; + #binding-cells = <2>; }; }; }; diff --git a/app/dts/bindings/behaviors/zmk,behavior-backlight.yaml b/app/dts/bindings/behaviors/zmk,behavior-backlight.yaml index e035e15e..159a7c70 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-backlight.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-backlight.yaml @@ -5,4 +5,4 @@ description: Backlight behavior compatible: "zmk,behavior-backlight" -include: one_param.yaml +include: two_param.yaml diff --git a/app/include/dt-bindings/zmk/backlight.h b/app/include/dt-bindings/zmk/backlight.h index c33e4344..70572437 100644 --- a/app/include/dt-bindings/zmk/backlight.h +++ b/app/include/dt-bindings/zmk/backlight.h @@ -4,8 +4,16 @@ * SPDX-License-Identifier: MIT */ -#define BL_TOG 0 -#define BL_ON 1 -#define BL_OFF 2 -#define BL_INC 3 -#define BL_DEC 4 +#define BL_TOG_CMD 0 +#define BL_ON_CMD 1 +#define BL_OFF_CMD 2 +#define BL_INC_CMD 3 +#define BL_DEC_CMD 4 +#define BL_SET_CMD 5 + +#define BL_TOG BL_TOG_CMD 0 +#define BL_ON BL_ON_CMD 0 +#define BL_OFF BL_OFF_CMD 0 +#define BL_INC BL_INC_CMD 0 +#define BL_DEC BL_DEC_CMD 0 +#define BL_SET BL_SET_CMD diff --git a/app/include/zmk/backlight.h b/app/include/zmk/backlight.h index 817efe7a..8711d884 100644 --- a/app/include/zmk/backlight.h +++ b/app/include/zmk/backlight.h @@ -6,14 +6,11 @@ #pragma once -int zmk_backlight_set_on(bool on); -bool zmk_backlight_is_on(); - -int zmk_backlight_set_brt(int brt); -int zmk_backlight_get_brt(); - int zmk_backlight_toggle(); +bool zmk_backlight_get_on(); int zmk_backlight_on(); int zmk_backlight_off(); -int zmk_backlight_inc(); -int zmk_backlight_dec(); +uint8_t zmk_backlight_calc_brt(int direction); +int zmk_backlight_set_brt(uint8_t brightness); +int zmk_backlight_adjust_brt(int direction); +int zmk_backlight_get_brt(); diff --git a/app/src/backlight.c b/app/src/backlight.c index 517e6133..fc8831c7 100644 --- a/app/src/backlight.c +++ b/app/src/backlight.c @@ -32,6 +32,8 @@ static const struct device *const backlight_dev = DEVICE_DT_GET(DT_CHOSEN(zmk_ba #define BACKLIGHT_NUM_LEDS (DT_NUM_CHILD(DT_CHOSEN(zmk_backlight))) +#define BRT_MAX 100 + struct backlight_state { uint8_t brightness; bool on; @@ -80,16 +82,7 @@ static void zmk_backlight_save_state_work() { } static struct k_delayed_work backlight_save_work; -#endif // IS_ENABLED(CONFIG_SETTINGS) - -static int zmk_backlight_save_state() { -#if IS_ENABLED(CONFIG_SETTINGS) - k_delayed_work_cancel(&backlight_save_work); - return k_delayed_work_submit(&backlight_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE)); -#else - return 0; #endif -} static int zmk_backlight_init(const struct device *_arg) { if (!device_is_ready(backlight_dev)) { @@ -114,11 +107,22 @@ static int zmk_backlight_init(const struct device *_arg) { return zmk_backlight_update(); } -int zmk_backlight_set_on(bool on) { +static int zmk_backlight_save_state() { +#if IS_ENABLED(CONFIG_SETTINGS) + k_delayed_work_cancel(&backlight_save_work); + return k_delayed_work_submit(&backlight_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE)); +#else + return 0; +#endif +} + +bool zmk_backlight_get_on() { return state.on; } + +int zmk_backlight_on() { if (!state.on && state.brightness == 0) { state.brightness = CONFIG_ZMK_BACKLIGHT_BRT_STEP; } - state.on = on; + state.on = true; int rc = zmk_backlight_update(); if (rc != 0) { @@ -128,11 +132,9 @@ int zmk_backlight_set_on(bool on) { return zmk_backlight_save_state(); } -bool zmk_backlight_is_on() { return state.on; } +int zmk_backlight_off() { -int zmk_backlight_set_brt(int brt) { - state.on = (brt > 0); - state.brightness = CLAMP(brt, 0, 100); + state.on = false; int rc = zmk_backlight_update(); if (rc != 0) { @@ -144,21 +146,42 @@ int zmk_backlight_set_brt(int brt) { int zmk_backlight_get_brt() { return state.on ? state.brightness : 0; } -int zmk_backlight_toggle() { return zmk_backlight_set_on(!state.on); } +int zmk_backlight_toggle() { return state.on ? zmk_backlight_off() : zmk_backlight_on(); } -int zmk_backlight_on() { return zmk_backlight_set_on(true); } - -int zmk_backlight_off() { return zmk_backlight_set_on(false); } - -int zmk_backlight_inc() { - if (!state.on) { - return zmk_backlight_set_brt(MAX(state.brightness, CONFIG_ZMK_BACKLIGHT_BRT_STEP)); +int zmk_backlight_set_brt(uint8_t brightness) { + if (brightness > BRT_MAX) { + brightness = BRT_MAX; } - return zmk_backlight_set_brt(state.brightness + CONFIG_ZMK_BACKLIGHT_BRT_STEP); + + state.brightness = brightness; + state.on = (brightness > 0); + + int rc = zmk_backlight_update(); + if (rc != 0) { + return rc; + } + + return zmk_backlight_save_state(); } -int zmk_backlight_dec() { - return zmk_backlight_set_brt(state.brightness - CONFIG_ZMK_BACKLIGHT_BRT_STEP); +uint8_t zmk_backlight_calc_brt(int direction) { + uint8_t brightness = state.brightness; + + int b = state.brightness + (direction * CONFIG_ZMK_BACKLIGHT_BRT_STEP); + return CLAMP(b, 0, BRT_MAX); +} + +int zmk_backlight_adjust_brt(int direction) { + + state.brightness = zmk_backlight_calc_brt(direction); + state.on = (state.brightness > 0); + + int rc = zmk_backlight_update(); + if (rc != 0) { + return rc; + } + + return zmk_backlight_save_state(); } #if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE) @@ -170,39 +193,34 @@ static bool auto_off_usb_prev_state = false; #endif #if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE) || IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB) +static int backlight_auto_state(bool *prev_state, bool *new_state) { + if (state.on == *new_state) { + return 0; + } + if (*new_state) { + state.on = *prev_state; + *prev_state = false; + return zmk_backlight_on(); + } else { + state.on = false; + *prev_state = true; + return zmk_backlight_off(); + } +} + static int backlight_event_listener(const zmk_event_t *eh) { #if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE) if (as_zmk_activity_state_changed(eh)) { bool new_state = (zmk_activity_get_state() == ZMK_ACTIVITY_ACTIVE); - if (state.on == new_state) { - return 0; - } - if (new_state) { - state.on = auto_off_idle_prev_state; - auto_off_idle_prev_state = false; - } else { - state.on = false; - auto_off_idle_prev_state = true; - } - return zmk_backlight_update(); + return backlight_auto_state(&auto_off_idle_prev_state, &new_state); } #endif #if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB) if (as_zmk_usb_conn_state_changed(eh)) { bool new_state = zmk_usb_is_powered(); - if (state.on == new_state) { - return 0; - } - if (new_state) { - state.on = auto_off_usb_prev_state; - auto_off_usb_prev_state = false; - } else { - state.on = false; - auto_off_usb_prev_state = true; - } - return zmk_backlight_update(); + return backlight_auto_state(&auto_off_usb_prev_state, &new_state); } #endif diff --git a/app/src/behaviors/behavior_backlight.c b/app/src/behaviors/behavior_backlight.c index 8d921f45..3dcbd3c4 100644 --- a/app/src/behaviors/behavior_backlight.c +++ b/app/src/behaviors/behavior_backlight.c @@ -20,21 +20,52 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); static int behavior_backlight_init(const struct device *dev) { return 0; } +static int +on_keymap_binding_convert_central_state_dependent_params(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + switch (binding->param1) { + case BL_TOG_CMD: { + binding->param1 = zmk_backlight_get_on() ? BL_OFF_CMD : BL_ON_CMD; + break; + } + case BL_INC_CMD: { + uint8_t brightness = zmk_backlight_calc_brt(1); + + binding->param1 = BL_SET_CMD; + binding->param2 = brightness; + break; + } + case BL_DEC_CMD: { + uint8_t brightness = zmk_backlight_calc_brt(-1); + + binding->param1 = BL_SET_CMD; + binding->param2 = brightness; + break; + } + default: + return 0; + } + + LOG_DBG("Backlight relative to absolute (%d/%d)", binding->param1, binding->param2); + + return 0; +} + static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { switch (binding->param1) { - case BL_TOG: + case BL_TOG_CMD: return zmk_backlight_toggle(); - case BL_ON: + case BL_ON_CMD: return zmk_backlight_on(); - case BL_OFF: + case BL_OFF_CMD: return zmk_backlight_off(); - case BL_INC: - return zmk_backlight_inc(); - case BL_DEC: - return zmk_backlight_dec(); - default: - LOG_ERR("Unknown backlight command: %d", binding->param1); + case BL_INC_CMD: + return zmk_backlight_adjust_brt(1); + case BL_DEC_CMD: + return zmk_backlight_adjust_brt(-1); + case BL_SET_CMD: + return zmk_backlight_set_brt(binding->param2); } return -ENOTSUP; @@ -46,6 +77,8 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding, } static const struct behavior_driver_api behavior_backlight_driver_api = { + .binding_convert_central_state_dependent_params = + on_keymap_binding_convert_central_state_dependent_params, .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released, };