feat(lighting): add backlight behavior
This commit is contained in:
parent
84365e6def
commit
85b2d30bd5
9 changed files with 371 additions and 2 deletions
|
@ -64,6 +64,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||||
target_sources(app PRIVATE src/keymap.c)
|
target_sources(app PRIVATE src/keymap.c)
|
||||||
endif()
|
endif()
|
||||||
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c)
|
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c)
|
||||||
|
target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/behaviors/behavior_backlight.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c)
|
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
|
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/battery.c)
|
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/battery.c)
|
||||||
|
@ -77,6 +78,7 @@ endif()
|
||||||
target_sources_ifdef(CONFIG_USB app PRIVATE src/usb.c)
|
target_sources_ifdef(CONFIG_USB app PRIVATE src/usb.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c)
|
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c)
|
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c)
|
||||||
|
target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c)
|
||||||
target_sources(app PRIVATE src/endpoints.c)
|
target_sources(app PRIVATE src/endpoints.c)
|
||||||
target_sources(app PRIVATE src/hid_listener.c)
|
target_sources(app PRIVATE src/hid_listener.c)
|
||||||
target_sources(app PRIVATE src/main.c)
|
target_sources(app PRIVATE src/main.c)
|
||||||
|
|
37
app/Kconfig
37
app/Kconfig
|
@ -257,7 +257,7 @@ menu "Display/LED Options"
|
||||||
|
|
||||||
rsource "src/display/Kconfig"
|
rsource "src/display/Kconfig"
|
||||||
|
|
||||||
config ZMK_RGB_UNDERGLOW
|
menuconfig ZMK_RGB_UNDERGLOW
|
||||||
bool "RGB Adressable LED Underglow"
|
bool "RGB Adressable LED Underglow"
|
||||||
select LED_STRIP
|
select LED_STRIP
|
||||||
|
|
||||||
|
@ -328,6 +328,39 @@ config ZMK_RGB_UNDERGLOW_ON_START
|
||||||
#ZMK_RGB_UNDERGLOW
|
#ZMK_RGB_UNDERGLOW
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
menuconfig ZMK_BACKLIGHT
|
||||||
|
bool "LED backlight"
|
||||||
|
select PWM
|
||||||
|
select LED
|
||||||
|
select ZMK_LED_PWM
|
||||||
|
|
||||||
|
if ZMK_BACKLIGHT
|
||||||
|
|
||||||
|
config ZMK_BACKLIGHT_BRT_STEP
|
||||||
|
int "Brightness step in percent"
|
||||||
|
range 1 100
|
||||||
|
default 20
|
||||||
|
|
||||||
|
config ZMK_BACKLIGHT_BRT_START
|
||||||
|
int "Default brightness in percent"
|
||||||
|
range 1 100
|
||||||
|
default 40
|
||||||
|
|
||||||
|
config ZMK_BACKLIGHT_ON_START
|
||||||
|
bool "Default backlight state"
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ZMK_BACKLIGHT_AUTO_OFF_IDLE
|
||||||
|
bool "Turn off backlight when keyboard goes into idle state"
|
||||||
|
default y
|
||||||
|
|
||||||
|
config ZMK_BACKLIGHT_AUTO_OFF_USB
|
||||||
|
bool "Turn off backlight when USB is disconnected"
|
||||||
|
default n
|
||||||
|
|
||||||
|
#ZMK_BACKLIGHT
|
||||||
|
endif
|
||||||
|
|
||||||
#Display/LED Options
|
#Display/LED Options
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
@ -378,7 +411,7 @@ config ZMK_COMBO_MAX_KEYS_PER_COMBO
|
||||||
int "Maximum number of keys per combo"
|
int "Maximum number of keys per combo"
|
||||||
default 4
|
default 4
|
||||||
|
|
||||||
#Display/LED Options
|
#Combo options
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "Advanced"
|
menu "Advanced"
|
||||||
|
|
|
@ -16,3 +16,4 @@
|
||||||
#include <behaviors/outputs.dtsi>
|
#include <behaviors/outputs.dtsi>
|
||||||
#include <behaviors/caps_word.dtsi>
|
#include <behaviors/caps_word.dtsi>
|
||||||
#include <behaviors/key_repeat.dtsi>
|
#include <behaviors/key_repeat.dtsi>
|
||||||
|
#include <behaviors/backlight.dtsi>
|
||||||
|
|
15
app/dts/behaviors/backlight.dtsi
Normal file
15
app/dts/behaviors/backlight.dtsi
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/ {
|
||||||
|
behaviors {
|
||||||
|
/omit-if-no-ref/ bl: behavior_backlight {
|
||||||
|
compatible = "zmk,behavior-backlight";
|
||||||
|
label = "BACKLIGHT";
|
||||||
|
#binding-cells = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
8
app/dts/bindings/behaviors/zmk,behavior-backlight.yaml
Normal file
8
app/dts/bindings/behaviors/zmk,behavior-backlight.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2021 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
description: Backlight behavior
|
||||||
|
|
||||||
|
compatible: "zmk,behavior-backlight"
|
||||||
|
|
||||||
|
include: one_param.yaml
|
11
app/include/dt-bindings/zmk/backlight.h
Normal file
11
app/include/dt-bindings/zmk/backlight.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BL_TOG 0
|
||||||
|
#define BL_ON 1
|
||||||
|
#define BL_OFF 2
|
||||||
|
#define BL_INC 3
|
||||||
|
#define BL_DEC 4
|
19
app/include/zmk/backlight.h
Normal file
19
app/include/zmk/backlight.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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();
|
||||||
|
int zmk_backlight_on();
|
||||||
|
int zmk_backlight_off();
|
||||||
|
int zmk_backlight_inc();
|
||||||
|
int zmk_backlight_dec();
|
224
app/src/backlight.c
Normal file
224
app/src/backlight.c
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <devicetree.h>
|
||||||
|
#include <init.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
#include <drivers/led.h>
|
||||||
|
#include <logging/log.h>
|
||||||
|
#include <settings/settings.h>
|
||||||
|
|
||||||
|
#include <zmk/activity.h>
|
||||||
|
#include <zmk/backlight.h>
|
||||||
|
#include <zmk/usb.h>
|
||||||
|
#include <zmk/event_manager.h>
|
||||||
|
#include <zmk/events/activity_state_changed.h>
|
||||||
|
#include <zmk/events/usb_conn_state_changed.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
BUILD_ASSERT(DT_HAS_CHOSEN(zmk_backlight),
|
||||||
|
"CONFIG_ZMK_BACKLIGHT is enabled but no zmk,backlight chosen node found");
|
||||||
|
|
||||||
|
static const struct device *const backlight_dev = DEVICE_DT_GET(DT_CHOSEN(zmk_backlight));
|
||||||
|
|
||||||
|
#define CHILD_COUNT(...) +1
|
||||||
|
#define DT_NUM_CHILD(node_id) (DT_FOREACH_CHILD(node_id, CHILD_COUNT))
|
||||||
|
|
||||||
|
#define BACKLIGHT_NUM_LEDS (DT_NUM_CHILD(DT_CHOSEN(zmk_backlight)))
|
||||||
|
|
||||||
|
struct backlight_state {
|
||||||
|
uint8_t brightness;
|
||||||
|
bool on;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct backlight_state state = {.brightness = CONFIG_ZMK_BACKLIGHT_BRT_START,
|
||||||
|
.on = IS_ENABLED(CONFIG_ZMK_BACKLIGHT_ON_START)};
|
||||||
|
|
||||||
|
static int zmk_backlight_update() {
|
||||||
|
uint8_t brt = state.on ? state.brightness : 0;
|
||||||
|
for (int i = 0; i < BACKLIGHT_NUM_LEDS; i++) {
|
||||||
|
int rc = led_set_brightness(backlight_dev, i, brt);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||||
|
static int backlight_settings_set(const char *name, size_t len, settings_read_cb read_cb,
|
||||||
|
void *cb_arg) {
|
||||||
|
const char *next;
|
||||||
|
|
||||||
|
if (settings_name_steq(name, "state", &next) && !next) {
|
||||||
|
if (len != sizeof(state)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = read_cb(cb_arg, &state, sizeof(state));
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return zmk_backlight_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct settings_handler backlight_conf = {.name = "backlight",
|
||||||
|
.h_set = backlight_settings_set};
|
||||||
|
|
||||||
|
static void zmk_backlight_save_state_work() {
|
||||||
|
settings_save_one("backlight/state", &state, sizeof(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
LOG_ERR("Backlight device \"%s\" is not ready", backlight_dev->name);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||||
|
settings_subsys_init();
|
||||||
|
|
||||||
|
int err = settings_register(&backlight_conf);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to register the backlight settings handler (err %d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_delayed_work_init(&backlight_save_work, zmk_backlight_save_state_work);
|
||||||
|
|
||||||
|
settings_load_subtree("backlight");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return zmk_backlight_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_backlight_set_on(bool on) {
|
||||||
|
if (!state.on && state.brightness == 0) {
|
||||||
|
state.brightness = CONFIG_ZMK_BACKLIGHT_BRT_STEP;
|
||||||
|
}
|
||||||
|
state.on = on;
|
||||||
|
|
||||||
|
int rc = zmk_backlight_update();
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return zmk_backlight_save_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool zmk_backlight_is_on() { return state.on; }
|
||||||
|
|
||||||
|
int zmk_backlight_set_brt(int brt) {
|
||||||
|
state.on = (brt > 0);
|
||||||
|
state.brightness = CLAMP(brt, 0, 100);
|
||||||
|
|
||||||
|
int rc = zmk_backlight_update();
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return zmk_backlight_save_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
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_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));
|
||||||
|
}
|
||||||
|
return zmk_backlight_set_brt(state.brightness + CONFIG_ZMK_BACKLIGHT_BRT_STEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_backlight_dec() {
|
||||||
|
return zmk_backlight_set_brt(state.brightness - CONFIG_ZMK_BACKLIGHT_BRT_STEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE)
|
||||||
|
static bool auto_off_idle_prev_state = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
|
||||||
|
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_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();
|
||||||
|
}
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZMK_LISTENER(backlight, backlight_event_listener);
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE) ||
|
||||||
|
// IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE)
|
||||||
|
ZMK_SUBSCRIPTION(backlight, zmk_activity_state_changed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
|
||||||
|
ZMK_SUBSCRIPTION(backlight, zmk_usb_conn_state_changed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SYS_INIT(zmk_backlight_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
56
app/src/behaviors/behavior_backlight.c
Normal file
56
app/src/behaviors/behavior_backlight.c
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT zmk_behavior_backlight
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <drivers/behavior.h>
|
||||||
|
#include <logging/log.h>
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/backlight.h>
|
||||||
|
#include <zmk/backlight.h>
|
||||||
|
#include <zmk/keymap.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
|
|
||||||
|
static int behavior_backlight_init(const struct device *dev) { 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:
|
||||||
|
return zmk_backlight_toggle();
|
||||||
|
case BL_ON:
|
||||||
|
return zmk_backlight_on();
|
||||||
|
case BL_OFF:
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
return ZMK_BEHAVIOR_OPAQUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct behavior_driver_api behavior_backlight_driver_api = {
|
||||||
|
.binding_pressed = on_keymap_binding_pressed,
|
||||||
|
.binding_released = on_keymap_binding_released,
|
||||||
|
};
|
||||||
|
|
||||||
|
DEVICE_DT_INST_DEFINE(0, behavior_backlight_init, device_pm_control_nop, NULL, NULL, APPLICATION,
|
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_backlight_driver_api);
|
||||||
|
|
||||||
|
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
|
Loading…
Add table
Reference in a new issue