From f178f86a5401758304165e3f0b82dfff5a3e568a Mon Sep 17 00:00:00 2001 From: darknao Date: Sat, 4 Jan 2025 20:01:15 +0100 Subject: [PATCH] underglow-layer: use behaviors to control RGBs --- app/CMakeLists.txt | 3 + app/boards/arm/glove80/glove80_lh.dts | 8 ++ app/boards/arm/glove80/glove80_lh_defconfig | 26 ++++++ app/boards/arm/glove80/glove80_rh.dts | 8 ++ app/boards/arm/glove80/glove80_rh_defconfig | 4 + app/dts/behaviors.dtsi | 2 + app/dts/behaviors/ug_color.dtsi | 15 ++++ app/dts/behaviors/ug_indicators.dtsi | 33 ++++++++ .../zmk,behavior-underglow-color.yaml | 8 ++ .../zmk,behavior-underglow-indicators.yaml | 13 +++ app/dts/bindings/zmk,underglow-layer.yaml | 7 +- app/include/dt-bindings/zmk/hid_indicators.h | 9 +++ app/include/dt-bindings/zmk/rgb_colors.h | 3 +- .../zmk/events/underglow_color_changed.h | 15 ++++ app/include/zmk/rgb_underglow_layer.h | 13 ++- app/src/behaviors/behavior_underglow_color.c | 39 +++++++++ .../behaviors/behavior_underglow_indicators.c | 80 +++++++++++++++++++ app/src/events/underglow_color_changed.c | 10 +++ app/src/rgb_underglow.c | 63 ++++++++++----- app/src/rgb_underglow_layer.c | 19 ++++- 20 files changed, 352 insertions(+), 26 deletions(-) create mode 100644 app/dts/behaviors/ug_color.dtsi create mode 100644 app/dts/behaviors/ug_indicators.dtsi create mode 100644 app/dts/bindings/behaviors/zmk,behavior-underglow-color.yaml create mode 100644 app/dts/bindings/behaviors/zmk,behavior-underglow-indicators.yaml create mode 100644 app/include/dt-bindings/zmk/hid_indicators.h create mode 100644 app/include/zmk/events/underglow_color_changed.h create mode 100644 app/src/behaviors/behavior_underglow_color.c create mode 100644 app/src/behaviors/behavior_underglow_indicators.c create mode 100644 app/src/events/underglow_color_changed.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index da682567..61fa1bba 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -84,6 +84,9 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL) 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_underglow_color.c) +target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_underglow_indicators.c) +target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/events/underglow_color_changed.c) target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/behaviors/behavior_backlight.c) target_sources_ifdef(CONFIG_ZMK_BATTERY_REPORTING app PRIVATE src/events/battery_state_changed.c) diff --git a/app/boards/arm/glove80/glove80_lh.dts b/app/boards/arm/glove80/glove80_lh.dts index 2ed56688..7bd57742 100644 --- a/app/boards/arm/glove80/glove80_lh.dts +++ b/app/boards/arm/glove80/glove80_lh.dts @@ -19,6 +19,14 @@ zmk,battery = &vbatt; }; + underglow-layer { + compatible = "zmk,underglow-layer"; + pixel-lookup = <52>, <53>, <54>, <69>, <70>, <71>, <15>, <27>, <39>, <51>, <4>, <14>, <26>, <38>, + <50>, <68>, <3>, <13>, <25>, <37>, <49>, <67>, <2>, <12>, <24>, <36>, <48>, <66>, + <1>, <11>, <23>, <35>, <47>, <65>, <0>, <10>, <22>, <34>, <46>, <64>; + }; + + back_led_backlight: pwmleds { compatible = "pwm-leds"; pwm_led_0 { diff --git a/app/boards/arm/glove80/glove80_lh_defconfig b/app/boards/arm/glove80/glove80_lh_defconfig index a93f27cd..d36173bb 100644 --- a/app/boards/arm/glove80/glove80_lh_defconfig +++ b/app/boards/arm/glove80/glove80_lh_defconfig @@ -16,16 +16,32 @@ CONFIG_USB_DEVICE_VID=0x16c0 CONFIG_USB_DEVICE_MANUFACTURER="MoErgo" CONFIG_USB_DEVICE_SN="moergo.com:GLV80-0123456789ABCDEF" +CONFIG_BT_DEVICE_NAME="Glove80" + CONFIG_BT_DIS_PNP_PID=0x27db CONFIG_BT_DIS_PNP_VID=0x16c0 CONFIG_BT_DIS_MANUF="MoErgo" CONFIG_BT_DIS_MODEL="Glove80" +### Bluetooth configuration workarounds + +# Use higher radio transmit power CONFIG_BT_CTLR_TX_PWR_PLUS_8=y # Work-around for Windows bug with battery notifications CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n +# Allow unauthenticated re-pairing for already paired hosts. This would permit +# an attacker that can spoof the host's peer address to "steal" the keyboard +# pairing by overwriting it, but without access to the previous keys it can't +# establish a MITM, and the sudden loss of the keyboard would be very obvious to +# the previously-connected host. +CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE=y +CONFIG_ZMK_BLE_PASSKEY_ENTRY=n + +# Fetch peripheral battery level for status display reporting +CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING=y + # Enable MPU CONFIG_ARM_MPU=y @@ -51,6 +67,9 @@ CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y # Enable RGB underglow CONFIG_ZMK_RGB_UNDERGLOW=y +# disable EXT_POWER until underglow gets turned on +CONFIG_ZMK_EXT_POWER_START=n + CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER=y CONFIG_ZMK_RGB_UNDERGLOW_ON_START=n CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP=4 @@ -79,6 +98,13 @@ CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB=y # space. CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y +# Enable USB boot protocol support +CONFIG_ZMK_USB_BOOT=y +CONFIG_ZMK_HID_INDICATORS=y + +# Send HID indicator to peripherals +CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS=y + # Turn on debugging to disable optimization. Debug messages can result in larger # stacks, so enable stack protection and particularly a larger BLE peripheral stack. # CONFIG_DEBUG=y diff --git a/app/boards/arm/glove80/glove80_rh.dts b/app/boards/arm/glove80/glove80_rh.dts index 7b54f62c..0cb16518 100644 --- a/app/boards/arm/glove80/glove80_rh.dts +++ b/app/boards/arm/glove80/glove80_rh.dts @@ -20,6 +20,14 @@ zmk,battery = &vbatt; }; + underglow-layer { + compatible = "zmk,underglow-layer"; + pixel-lookup = <57>, <56>, <55>, <74>, <73>, <72>, <16>, <28>, <40>, <58>, <5>, <17>, <29>, <41>, + <59>, <75>, <6>, <18>, <30>, <42>, <60>, <76>, <7>, <19>, <31>, <43>, <61>, <77>, + <8>, <20>, <32>, <44>, <62>, <78>, <9>, <21>, <33>, <45>, <63>, <79>; + }; + + back_led_backlight: pwmleds { compatible = "pwm-leds"; pwm_led_0 { diff --git a/app/boards/arm/glove80/glove80_rh_defconfig b/app/boards/arm/glove80/glove80_rh_defconfig index ef29d682..b6795f5d 100644 --- a/app/boards/arm/glove80/glove80_rh_defconfig +++ b/app/boards/arm/glove80/glove80_rh_defconfig @@ -63,6 +63,10 @@ CONFIG_ZMK_RGB_UNDERGLOW_HUE_START=285 CONFIG_ZMK_RGB_UNDERGLOW_SAT_START=75 CONFIG_ZMK_RGB_UNDERGLOW_BRT_START=16 +# Enable HID indicators on peripheral +CONFIG_ZMK_HID_INDICATORS=y +CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS=y + # The power LED is implemented as a backlight # For now, the power LED is acting as a "USB connected" indicator CONFIG_ZMK_BACKLIGHT=y diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi index 653b085d..ff56705d 100644 --- a/app/dts/behaviors.dtsi +++ b/app/dts/behaviors.dtsi @@ -28,3 +28,5 @@ #include #include #include +#include +#include diff --git a/app/dts/behaviors/ug_color.dtsi b/app/dts/behaviors/ug_color.dtsi new file mode 100644 index 00000000..15d6c863 --- /dev/null +++ b/app/dts/behaviors/ug_color.dtsi @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +/ { + behaviors { + ug: ugcolor { + compatible = "zmk,behavior-underglow-color"; + #binding-cells = <1>; + display-name = "Underglow Color"; + }; + }; +}; diff --git a/app/dts/behaviors/ug_indicators.dtsi b/app/dts/behaviors/ug_indicators.dtsi new file mode 100644 index 00000000..b62c79b7 --- /dev/null +++ b/app/dts/behaviors/ug_indicators.dtsi @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + behaviors { + ug_nl: ugnumlk { + compatible = "zmk,behavior-underglow-indicators"; + indicator = ; + #binding-cells = <2>; + display-name = "Underglow NumLock indicator"; + }; + + ug_cl: ugcapslk { + compatible = "zmk,behavior-underglow-indicators"; + indicator = ; + #binding-cells = <2>; + display-name = "Underglow CapsLock indicator"; + }; + + ug_sl: ugscrllk { + compatible = "zmk,behavior-underglow-indicators"; + indicator = ; + #binding-cells = <2>; + display-name = "Underglow ScrollLock indicator"; + }; + + }; +}; diff --git a/app/dts/bindings/behaviors/zmk,behavior-underglow-color.yaml b/app/dts/bindings/behaviors/zmk,behavior-underglow-color.yaml new file mode 100644 index 00000000..b3e90278 --- /dev/null +++ b/app/dts/bindings/behaviors/zmk,behavior-underglow-color.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024, The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Set underglow to specified color + +compatible: "zmk,behavior-underglow-color" + +include: one_param.yaml diff --git a/app/dts/bindings/behaviors/zmk,behavior-underglow-indicators.yaml b/app/dts/bindings/behaviors/zmk,behavior-underglow-indicators.yaml new file mode 100644 index 00000000..553bb6c8 --- /dev/null +++ b/app/dts/bindings/behaviors/zmk,behavior-underglow-indicators.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2024, The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Set underglow for num lock indicator + +compatible: "zmk,behavior-underglow-indicators" + +include: two_param.yaml + +properties: + indicator: + type: int + default: 0 diff --git a/app/dts/bindings/zmk,underglow-layer.yaml b/app/dts/bindings/zmk,underglow-layer.yaml index 0f59c89a..62fec31b 100644 --- a/app/dts/bindings/zmk,underglow-layer.yaml +++ b/app/dts/bindings/zmk,underglow-layer.yaml @@ -3,12 +3,17 @@ description: | compatible: "zmk,underglow-layer" +properties: + pixel-lookup: + type: array + required: true + child-binding: description: "A layer to be used in a rgbmap" properties: bindings: - type: array + type: phandle-array required: true layer-id: type: int diff --git a/app/include/dt-bindings/zmk/hid_indicators.h b/app/include/dt-bindings/zmk/hid_indicators.h new file mode 100644 index 00000000..860c81db --- /dev/null +++ b/app/include/dt-bindings/zmk/hid_indicators.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define NUM_LOCK 0 +#define CAPS_LOCK 1 +#define SCROLL_LOCK 2 diff --git a/app/include/dt-bindings/zmk/rgb_colors.h b/app/include/dt-bindings/zmk/rgb_colors.h index 885c82d2..73e9cc1f 100644 --- a/app/include/dt-bindings/zmk/rgb_colors.h +++ b/app/include/dt-bindings/zmk/rgb_colors.h @@ -14,4 +14,5 @@ #define PURPLE 0x800080 #define PINK 0xffc0cb #define WHITE 0xffffff -#define ______ 0x000000 \ No newline at end of file +#define ___ 0x000000 +#define BLACK 0x000000 \ No newline at end of file diff --git a/app/include/zmk/events/underglow_color_changed.h b/app/include/zmk/events/underglow_color_changed.h new file mode 100644 index 00000000..24588ff2 --- /dev/null +++ b/app/include/zmk/events/underglow_color_changed.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include + +struct zmk_underglow_color_changed { + uint32_t layers; +}; + +ZMK_EVENT_DECLARE(zmk_underglow_color_changed); diff --git a/app/include/zmk/rgb_underglow_layer.h b/app/include/zmk/rgb_underglow_layer.h index 3681a97e..879aff1a 100644 --- a/app/include/zmk/rgb_underglow_layer.h +++ b/app/include/zmk/rgb_underglow_layer.h @@ -12,7 +12,18 @@ #define ZMK_RGBMAP_LAYERS_LEN \ (DT_FOREACH_CHILD(DT_INST(0, zmk_underglow_layer), ZMK_RGB_CHILD_LEN_PLUS_ONE) 0) +#define ZMK_RGBMAP_EXTRACT_BINDING(idx, drv_inst) \ + { \ + .behavior_dev = DEVICE_DT_NAME(DT_PHANDLE_BY_IDX(drv_inst, bindings, idx)), \ + .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(drv_inst, bindings, idx, param1), (0), \ + (DT_PHA_BY_IDX(drv_inst, bindings, idx, param1))), \ + .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(drv_inst, bindings, idx, param2), (0), \ + (DT_PHA_BY_IDX(drv_inst, bindings, idx, param2))), \ + } + +const int rgb_pixel_lookup(int idx); const int zmk_rgbmap_id(uint8_t layer); -uint32_t *rgb_underglow_get_bindings(uint8_t layer); +const struct zmk_behavior_binding *rgb_underglow_get_bindings(uint8_t layer); + uint8_t rgb_underglow_top_layer_with_state(uint32_t state_to_test); uint8_t rgb_underglow_top_layer(void); \ No newline at end of file diff --git a/app/src/behaviors/behavior_underglow_color.c b/app/src/behaviors/behavior_underglow_color.c new file mode 100644 index 00000000..29000aab --- /dev/null +++ b/app/src/behaviors/behavior_underglow_color.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_behavior_underglow_color + +// Dependencies +#include +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) + +// Initialization Function +static int underglow_color_init(const struct device *dev) { return 0; }; + +static int underglow_color_process(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + return binding->param1; +} + +// API Structure +static const struct behavior_driver_api underglow_color_driver_api = { + .binding_pressed = underglow_color_process, + .locality = BEHAVIOR_LOCALITY_GLOBAL, +#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) + .get_parameter_metadata = zmk_behavior_get_empty_param_metadata, +#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) + +}; + +BEHAVIOR_DT_INST_DEFINE(0, underglow_color_init, NULL, NULL, NULL, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &underglow_color_driver_api); + +#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ diff --git a/app/src/behaviors/behavior_underglow_indicators.c b/app/src/behaviors/behavior_underglow_indicators.c new file mode 100644 index 00000000..d29a60ae --- /dev/null +++ b/app/src/behaviors/behavior_underglow_indicators.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_behavior_underglow_indicators + +// Dependencies +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) + +struct underglow_indicators_data { + zmk_hid_indicators_t indicators; + uint32_t layers; +}; + +struct underglow_indicators_config { + int indicator; +}; + +static int underglow_indicators_init(const struct device *dev) { return 0; }; + +static int underglow_indicators_process(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + const struct device *dev = zmk_behavior_get_binding(binding->behavior_dev); + struct underglow_indicators_data *data = dev->data; + const struct underglow_indicators_config *config = dev->config; + data->layers |= BIT(event.layer); + + if (data->indicators & BIT(config->indicator)) + return binding->param2; + else + return binding->param1; +} + +static const struct behavior_driver_api underglow_indicators_driver_api = { + .binding_pressed = underglow_indicators_process, + .locality = BEHAVIOR_LOCALITY_GLOBAL, +#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) + .get_parameter_metadata = zmk_behavior_get_empty_param_metadata, +#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) +}; + +static int underglow_indicators_listener(const zmk_event_t *eh); + +ZMK_LISTENER(behavior_underglow_indicators, underglow_indicators_listener); +ZMK_SUBSCRIPTION(behavior_underglow_indicators, zmk_hid_indicators_changed); + +static struct underglow_indicators_data underglow_indicators_data = {.indicators = 0, .layers = 0}; + +static int underglow_indicators_listener(const zmk_event_t *eh) { + const struct zmk_hid_indicators_changed *ev = as_zmk_hid_indicators_changed(eh); + underglow_indicators_data.indicators = ev->indicators; + raise_zmk_underglow_color_changed( + (struct zmk_underglow_color_changed){.layers = underglow_indicators_data.layers}); + + return ZMK_EV_EVENT_BUBBLE; +} + +#define KP_INST(n) \ + static struct underglow_indicators_config underglow_indicators_config_##n = { \ + .indicator = DT_INST_PROP(n, indicator)}; \ + BEHAVIOR_DT_INST_DEFINE(n, underglow_indicators_init, NULL, &underglow_indicators_data, \ + &underglow_indicators_config_##n, POST_KERNEL, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ + &underglow_indicators_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(KP_INST) + +#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ diff --git a/app/src/events/underglow_color_changed.c b/app/src/events/underglow_color_changed.c new file mode 100644 index 00000000..c00bdc6b --- /dev/null +++ b/app/src/events/underglow_color_changed.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +ZMK_EVENT_IMPL(zmk_underglow_color_changed); \ No newline at end of file diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c index cf8e45a7..ae065bdd 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,7 @@ #include #include +#include #include #include @@ -33,6 +35,8 @@ #include #include #include +#include + #include #include @@ -52,13 +56,13 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #endif +#define STRIP_CHOSEN DT_CHOSEN(zmk_underglow) +#define STRIP_NUM_PIXELS DT_PROP(STRIP_CHOSEN, chain_length) + #if DT_HAS_COMPAT_STATUS_OKAY(zmk_underglow_layer) && IS_ENABLED(CONFIG_EXPERIMENTAL_RGB_LAYER) #define UNDERGLOW_LAYER_ENABLED 1 #endif -#define STRIP_CHOSEN DT_CHOSEN(zmk_underglow) -#define STRIP_NUM_PIXELS DT_PROP(STRIP_CHOSEN, chain_length) - #define HUE_MAX 360 #define SAT_MAX 100 #define BRT_MAX 100 @@ -455,27 +459,38 @@ static struct led_rgb hex_to_rgb(uint8_t r, uint8_t g, uint8_t b) { }; } -static int zmk_rgb_underglow_apply_rgbmap(uint32_t rgbmap[], size_t rgbmap_len) { -// TODO: Glove80 specifics, move that part to board's devicetree -#ifdef LEFT_HALF - const uint8_t LED_MATRIX[] = {52, 53, 54, 69, 70, 71, 15, 27, 39, 51, 4, 14, 26, 38, - 50, 68, 3, 13, 25, 37, 49, 67, 2, 12, 24, 36, 48, 66, - 1, 11, 23, 35, 47, 65, 0, 10, 22, 34, 46, 64}; -#else - const uint8_t LED_MATRIX[] = {57, 56, 55, 74, 73, 72, 16, 28, 40, 58, 5, 17, 29, 41, - 59, 75, 6, 18, 30, 42, 60, 76, 7, 19, 31, 43, 61, 77, - 8, 20, 32, 44, 62, 78, 9, 21, 33, 45, 63, 79}; -#endif +static int zmk_rgb_underglow_apply_rgbmap(struct zmk_behavior_binding *bindings, + size_t rgbmap_len) { int rc = 0; for (int i = 0; i < STRIP_NUM_PIXELS; i++) { - uint8_t midx = LED_MATRIX[i]; + uint8_t midx = rgb_pixel_lookup(i); if (midx >= ZMK_KEYMAP_LEN) { LOG_DBG("out of range"); } else { - pixels[i] = hex_to_rgb((rgbmap[midx] & 0xFF0000) >> 16, (rgbmap[midx] & 0xFF00) >> 8, - rgbmap[midx] & 0xFF); - if (rgbmap[midx] > 0) + const struct device *dev = zmk_behavior_get_binding(bindings[midx].behavior_dev); + + if (dev == NULL) { + continue; + } + + const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api; + + if (api->binding_pressed == NULL) { + continue; + } + struct zmk_behavior_binding_event event = {.position = midx, + .timestamp = k_uptime_get()}; + + int color = + api->binding_pressed((const struct zmk_behavior_binding *)&bindings[midx], event); + + if (color > 0) { + pixels[i] = + hex_to_rgb((color & 0xFF0000) >> 16, (color & 0xFF00) >> 8, color & 0xFF); rc = 1; + } else { + pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0}; + } } } return rc; @@ -485,7 +500,7 @@ static void zmk_rgb_underglow_set_layer(uint8_t layer) { if (!state.layer_enabled) return; - uint32_t *rgbmap = rgb_underglow_get_bindings(layer); + const struct zmk_behavior_binding *rgbmap = rgb_underglow_get_bindings(layer); if (rgbmap != NULL && zmk_rgb_underglow_apply_rgbmap(rgbmap, ZMK_KEYMAP_LEN)) { if (!state.on) zmk_rgb_underglow_transient_on(); @@ -914,6 +929,15 @@ static int rgb_underglow_event_listener(const zmk_event_t *eh) { zmk_rgb_underglow_set_layer(layer); return 0; } + if (as_zmk_underglow_color_changed(eh)) { + const struct zmk_underglow_color_changed *ev = as_zmk_underglow_color_changed(eh); + LOG_DBG("refresh layer %d", ev->layers); + uint8_t layer = rgb_underglow_top_layer(); + if ((ev->layers & (BIT(layer))) == BIT(layer)) { + zmk_rgb_underglow_set_layer(rgb_underglow_top_layer()); + } + return 0; + } #endif /* UNDERGLOW_LAYER_ENABLED */ #if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB) @@ -940,6 +964,7 @@ ZMK_SUBSCRIPTION(rgb_underglow, zmk_usb_conn_state_changed); #if IS_ENABLED(UNDERGLOW_LAYER_ENABLED) ZMK_SUBSCRIPTION(rgb_underglow, zmk_split_peripheral_layer_changed); +ZMK_SUBSCRIPTION(rgb_underglow, zmk_underglow_color_changed); #endif SYS_INIT(zmk_rgb_underglow_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/app/src/rgb_underglow_layer.c b/app/src/rgb_underglow_layer.c index fb9876cf..6cd0ceb9 100644 --- a/app/src/rgb_underglow_layer.c +++ b/app/src/rgb_underglow_layer.c @@ -24,13 +24,24 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #define UNDERGLOW_LAYER_ENABLED #define LAYER_ID(node) DT_PROP(node, layer_id) -#define RGB_BINDINGS(node) DT_PROP(node, bindings) -static uint32_t zmk_rgbmap[ZMK_RGBMAP_LAYERS_LEN][ZMK_KEYMAP_LEN] = { - DT_INST_FOREACH_CHILD_SEP(0, RGB_BINDINGS, (, ))}; +#define TRANSFORMED_RGB_LAYER(node) \ + {COND_CODE_1(DT_NODE_HAS_PROP(node, bindings), \ + (LISTIFY(DT_PROP_LEN(node, bindings), ZMK_RGBMAP_EXTRACT_BINDING, (, ), node)), \ + ())} + +#define RGBMAP_VAR(_name, _opts) \ + static _opts struct zmk_behavior_binding _name[ZMK_RGBMAP_LAYERS_LEN][ZMK_KEYMAP_LEN] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(0, TRANSFORMED_RGB_LAYER, (, ))}; + +RGBMAP_VAR(zmk_rgbmap, COND_CODE_1(IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE), (), (const))) + +const int pixel_lookup_table[] = DT_INST_PROP(0, pixel_lookup); static int zmk_rgbmap_ids[ZMK_RGBMAP_LAYERS_LEN] = {DT_INST_FOREACH_CHILD_SEP(0, LAYER_ID, (, ))}; +const int rgb_pixel_lookup(int idx) { return pixel_lookup_table[idx]; }; + const int zmk_rgbmap_id(uint8_t layer) { for (uint8_t i = 0; i < ZMK_RGBMAP_LAYERS_LEN; i++) { if (zmk_rgbmap_ids[i] == layer) { @@ -40,7 +51,7 @@ const int zmk_rgbmap_id(uint8_t layer) { return -1; } -uint32_t *rgb_underglow_get_bindings(uint8_t layer) { +const struct zmk_behavior_binding *rgb_underglow_get_bindings(uint8_t layer) { int rgblayer = zmk_rgbmap_id(layer); if (rgblayer == -1) { return NULL;