diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 41a097c483b7..bd49785ca5f7 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -80,6 +80,7 @@ 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_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c) target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c) +target_sources_ifdef(CONFIG_ZMK_LED_INDICATORS app PRIVATE src/led_indicators.c) target_sources(app PRIVATE src/endpoints.c) target_sources(app PRIVATE src/hid_listener.c) target_sources(app PRIVATE src/led_indicators_generic.c) diff --git a/app/Kconfig b/app/Kconfig index 08a35696de94..87d2d4aec234 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -358,6 +358,20 @@ config ZMK_BACKLIGHT_AUTO_OFF_USB #ZMK_BACKLIGHT endif +menuconfig ZMK_LED_INDICATORS + bool "LED indicators" + select LED + +if ZMK_LED_INDICATORS + +config ZMK_LED_INDICATORS_BRT + int "Brightness in percent" + range 1 100 + default 80 + +#ZMK_LED_INDICATORS +endif + #Display/LED Options endmenu diff --git a/app/dts/bindings/zmk,led-indicators.yaml b/app/dts/bindings/zmk,led-indicators.yaml new file mode 100644 index 000000000000..bc22890ca2dc --- /dev/null +++ b/app/dts/bindings/zmk,led-indicators.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2021 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: LED indicators + +compatible: "zmk,led-indicators" + +child-binding: + description: LED indicator + + properties: + ctrl: + type: phandle + required: true + index: + type: int + required: true + binding: + type: int + required: true diff --git a/app/src/led_indicators.c b/app/src/led_indicators.c new file mode 100644 index 000000000000..9109a65c05ba --- /dev/null +++ b/app/src/led_indicators.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +BUILD_ASSERT(DT_HAS_CHOSEN(zmk_led_indicators), + "CONFIG_ZMK_LED_INDICATORS is enabled but no zmk,led-indicators chosen node found"); + +struct zmk_led_cfg { + const struct device *ctrl; + int index; + int binding; +}; + +#define LED_CFG(node_id) \ + (struct zmk_led_cfg){ \ + .ctrl = DEVICE_DT_GET(DT_PHANDLE(node_id, ctrl)), \ + .index = DT_PROP(node_id, index), \ + .binding = DT_PROP(node_id, binding), \ + }, + +static const struct zmk_led_cfg led_indicators[] = { + DT_FOREACH_CHILD(DT_CHOSEN(zmk_led_indicators), LED_CFG)}; + +static int leds_init(const struct device *_arg) { + for (int i = 0; i < ARRAY_SIZE(led_indicators); i++) { + if (!device_is_ready(led_indicators[i].ctrl)) { + LOG_ERR("LED device \"%s\" is not ready", led_indicators[i].ctrl->name); + return -ENODEV; + } + } + + return 0; +} + +static int leds_listener(const zmk_event_t *eh) { + zmk_leds_flags_t flags = zmk_leds_get_current_flags(); + + for (int i = 0; i < ARRAY_SIZE(led_indicators); i++) { + uint8_t value = + (flags & BIT(led_indicators[i].binding)) ? CONFIG_ZMK_LED_INDICATORS_BRT : 0; + int rc = led_set_brightness(led_indicators[i].ctrl, led_indicators[i].index, value); + if (rc != 0) { + return rc; + } + } + + return 0; +} + +ZMK_LISTENER(leds_listener, leds_listener); +ZMK_SUBSCRIPTION(leds_listener, zmk_led_changed); + +SYS_INIT(leds_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);