From 8d953abdf7e414a0062abdf00ae8691f2a019a23 Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Thu, 23 Nov 2023 23:17:26 +0000 Subject: [PATCH] feat(rgb): Use data transfer framework --- app/src/behaviors/behavior_rgb_underglow.c | 2 +- app/src/rgb_underglow.c | 93 ++++++++++++++++++++-- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/app/src/behaviors/behavior_rgb_underglow.c b/app/src/behaviors/behavior_rgb_underglow.c index a16ee591..14b185ac 100644 --- a/app/src/behaviors/behavior_rgb_underglow.c +++ b/app/src/behaviors/behavior_rgb_underglow.c @@ -146,7 +146,7 @@ static const struct behavior_driver_api behavior_rgb_underglow_driver_api = { on_keymap_binding_convert_central_state_dependent_params, .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released, - .locality = BEHAVIOR_LOCALITY_GLOBAL, + .locality = BEHAVIOR_LOCALITY_CENTRAL, }; BEHAVIOR_DT_INST_DEFINE(0, behavior_rgb_underglow_init, NULL, NULL, NULL, POST_KERNEL, diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c index 5bf1ef25..32a331e9 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -21,11 +21,20 @@ #include #include +#include #include #include #include +#include #include +// Pull data sending framework if central, data receiving event if peripheral(s) +#if ZMK_BLE_IS_CENTRAL +#include +#elif IS_ENABLED(CONFIG_ZMK_SPLIT) +#include +#endif + LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #if !DT_HAS_CHOSEN(zmk_underglow) @@ -130,6 +139,21 @@ static struct led_rgb hsb_to_rgb(struct zmk_led_hsb hsb) { return rgb; } +#if ZMK_BLE_IS_CENTRAL + +static void zmk_rgb_send_state(struct k_work *work) { + LOG_HEXDUMP_DBG(&state, sizeof(struct rgb_underglow_state), "RGB state"); + int err = zmk_split_central_send_data(DATA_TAG_RGB_STATE, sizeof(struct rgb_underglow_state), + (uint8_t *)&state); + if (err) { + LOG_ERR("send failed (err %d)", err); + } +} + +K_WORK_DEFINE(rgb_send_state_work, zmk_rgb_send_state); + +#endif + static void zmk_rgb_underglow_effect_solid(void) { for (int i = 0; i < STRIP_NUM_PIXELS; i++) { pixels[i] = hsb_to_rgb(hsb_scale_min_max(state.color)); @@ -191,6 +215,14 @@ static void zmk_rgb_underglow_tick(struct k_work *work) { break; } +#if ZMK_BLE_IS_CENTRAL + // Every time the counter rolls to 1 synchronise the animations (If it was 0 then it constantly + // syncs when effect is a solid color) + if (state.animation_step == 1) { + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &rgb_send_state_work); + } +#endif + int err = led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS); if (err < 0) { LOG_ERR("Failed to update the RGB strip (%d)", err); @@ -278,7 +310,9 @@ static int zmk_rgb_underglow_init(void) { #if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB) state.on = zmk_usb_is_powered(); #endif - +#if ZMK_BLE_IS_CENTRAL + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &rgb_send_state_work); +#endif if (state.on) { k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); } @@ -287,6 +321,10 @@ static int zmk_rgb_underglow_init(void) { } int zmk_rgb_underglow_save_state(void) { + // Send new state to peripheral when anything changes +#if ZMK_BLE_IS_CENTRAL + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &rgb_send_state_work); +#endif #if IS_ENABLED(CONFIG_SETTINGS) int ret = k_work_reschedule(&underglow_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE)); return MIN(ret, 0); @@ -319,7 +357,6 @@ int zmk_rgb_underglow_on(void) { state.on = true; state.animation_step = 0; k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); - return zmk_rgb_underglow_save_state(); } @@ -496,8 +533,12 @@ static int rgb_underglow_auto_state(bool target_wake_state) { return zmk_rgb_underglow_off(); } } +#endif -static int rgb_underglow_event_listener(const zmk_event_t *eh) { +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE) || \ + IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB) || ZMK_BLE_IS_CENTRAL + +static int rgb_underglow_activity_event_listener(const zmk_event_t *eh) { #if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE) if (as_zmk_activity_state_changed(eh)) { @@ -511,19 +552,57 @@ static int rgb_underglow_event_listener(const zmk_event_t *eh) { } #endif +#if ZMK_BLE_IS_CENTRAL + if (as_zmk_split_peripheral_status_changed(eh)) { + // TODO: Have this only update when connected + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &rgb_send_state_work); + } +#endif + return -ENOTSUP; } -ZMK_LISTENER(rgb_underglow, rgb_underglow_event_listener); +ZMK_LISTENER(rgb_underglow_activity, rgb_underglow_activity_event_listener); #endif // IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE) || - // IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB) + // IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB) || ZMK_BLE_IS_CENTRAL #if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE) -ZMK_SUBSCRIPTION(rgb_underglow, zmk_activity_state_changed); +ZMK_SUBSCRIPTION(rgb_underglow_activity, zmk_activity_state_changed); #endif #if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB) -ZMK_SUBSCRIPTION(rgb_underglow, zmk_usb_conn_state_changed); +ZMK_SUBSCRIPTION(rgb_underglow_activity, zmk_usb_conn_state_changed); +#endif + +#if ZMK_BLE_IS_CENTRAL +ZMK_SUBSCRIPTION(rgb_underglow_activity, zmk_split_peripheral_status_changed); +#endif + +#if IS_ENABLED(CONFIG_ZMK_SPLIT) && !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) + +static int rgb_underglow_data_event_listener(const zmk_event_t *eh) { + const struct zmk_split_data_xfer_event *ev = as_zmk_split_data_xfer_event(eh); + if (ev->data_xfer.data_tag == DATA_TAG_RGB_STATE) { + LOG_DBG("RGB Data received of size: %d", ev->data_xfer.data_size); + // Should the RGB timer be stopped and started during this operation to keep state safe? + LOG_HEXDUMP_DBG(ev->data_xfer.data, sizeof(struct zmk_split_data_xfer_event), + "received event:"); + static bool prev_state = false; + memcpy(&state, ev->data_xfer.data, sizeof(struct rgb_underglow_state)); + LOG_HEXDUMP_DBG(&state, sizeof(struct rgb_underglow_state), "RGB state"); + LOG_DBG("new on_state %d", state.on); + if (prev_state && !state.on) { + zmk_rgb_underglow_off(); + } else if (!prev_state && state.on) { + zmk_rgb_underglow_on(); + } + prev_state = state.on; + } + return 0; +} + +ZMK_LISTENER(rgb_underglow_data, rgb_underglow_data_event_listener); +ZMK_SUBSCRIPTION(rgb_underglow_data, zmk_split_data_xfer_event); #endif SYS_INIT(zmk_rgb_underglow_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);