diff --git a/app/include/zmk/split/bluetooth/central.h b/app/include/zmk/split/bluetooth/central.h index eab4ac0ca59..228c531e690 100644 --- a/app/include/zmk/split/bluetooth/central.h +++ b/app/include/zmk/split/bluetooth/central.h @@ -7,4 +7,12 @@ #include int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding, - struct zmk_behavior_binding_event event, bool state); \ No newline at end of file + struct zmk_behavior_binding_event event, bool state); + +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW) +int zmk_split_bt_update_led(struct zmk_periph_led *periph); +#endif + +#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT) +int zmk_split_bt_update_bl(struct backlight_state *periph); +#endif diff --git a/app/include/zmk/split/bluetooth/service.h b/app/include/zmk/split/bluetooth/service.h index 112cd552942..f935d6b3452 100644 --- a/app/include/zmk/split/bluetooth/service.h +++ b/app/include/zmk/split/bluetooth/service.h @@ -30,6 +30,20 @@ struct zmk_split_run_behavior_payload { char behavior_dev[ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN]; } __packed; +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW) +struct zmk_split_update_led_data { + uint8_t layer; + uint8_t indicators; +} __packed; +#endif + +#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT) +struct zmk_split_update_bl_data { + uint8_t brightness; + bool on; +} __packed; +#endif + int zmk_split_bt_position_pressed(uint8_t position); int zmk_split_bt_position_released(uint8_t position); int zmk_split_bt_sensor_triggered(uint8_t sensor_index, diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c index 5eec212233d..f3d1c50f117 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -81,6 +81,18 @@ static struct led_rgb pixels[STRIP_NUM_PIXELS]; static struct rgb_underglow_state state; +static struct zmk_periph_led led_data; + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE) +static bool last_ble_state[2]; +#endif + +static bool triggered; + +#if ZMK_BLE_IS_CENTRAL +static struct zmk_periph_led old_led_data; +#endif + #if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER) static const struct device *ext_power; #endif @@ -196,6 +208,311 @@ static void zmk_rgb_underglow_effect_swirl() { state.animation_step = state.animation_step % HUE_MAX; } +#if ZMK_BLE_IS_CENTRAL +static struct k_work_delayable led_update_work; + +static void zmk_rgb_underglow_central_send() { + int err = zmk_split_bt_update_led(&led_data); + if (err) { + LOG_ERR("send failed (err %d)", err); + } +} +#endif + +static void zmk_rgb_underglow_effect_kinesis() { +#if ZMK_BLE_IS_CENTRAL + // leds for central(left) side + + old_led_data.layer = led_data.layer; + old_led_data.indicators = led_data.indicators; + led_data.indicators = zmk_hid_indicators_get_current_profile(); + led_data.layer = zmk_keymap_highest_layer_active(); + + pixels[0].r = (led_data.indicators & ZMK_LED_CAPSLOCK_BIT) * CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].g = (led_data.indicators & ZMK_LED_CAPSLOCK_BIT) * CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].b = (led_data.indicators & ZMK_LED_CAPSLOCK_BIT) * CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + // set second led as bluetooth state + switch (zmk_ble_active_profile_index()) { + case 0: + pixels[1].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[1].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[1].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 1: + pixels[1].r = 0; + pixels[1].g = 0; + pixels[1].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 2: + pixels[1].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[1].g = 0; + pixels[1].b = 0; + break; + case 3: + pixels[1].r = 0; + pixels[1].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[1].b = 0; + break; + case 4: + pixels[1].r = 0; + pixels[1].g = 0; + pixels[1].b = 0; + break; + } + // blink second led slowly if bluetooth not paired, quickly if not connected + if (zmk_ble_active_profile_is_open()) { + pixels[1].r = pixels[1].r * last_ble_state[0]; + pixels[1].g = pixels[1].g * last_ble_state[0]; + pixels[1].b = pixels[1].b * last_ble_state[0]; + if (state.animation_step > 3) { + last_ble_state[0] = !last_ble_state[0]; + state.animation_step = 0; + } + state.animation_step++; + } else if (!zmk_ble_active_profile_is_connected()) { + pixels[1].r = pixels[1].r * last_ble_state[1]; + pixels[1].g = pixels[1].g * last_ble_state[1]; + pixels[1].b = pixels[1].b * last_ble_state[1]; + if (state.animation_step > 14) { + last_ble_state[1] = !last_ble_state[1]; + state.animation_step = 0; + } + state.animation_step++; + } + // set third led as layer state + switch (led_data.layer) { + case 0: + pixels[2].r = 0; + pixels[2].g = 0; + pixels[2].b = 0; + break; + case 1: + pixels[2].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 2: + pixels[2].r = 0; + pixels[2].g = 0; + pixels[2].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 3: + pixels[2].r = 0; + pixels[2].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].b = 0; + break; + case 4: + pixels[2].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].g = 0; + pixels[2].b = 0; + break; + case 5: + pixels[2].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].g = 0; + pixels[2].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 6: + pixels[2].r = 0; + pixels[2].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 7: + pixels[2].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].b = 0; + break; + default: + pixels[2].r = 0; + pixels[2].g = 0; + pixels[2].b = 0; + break; + } + if (old_led_data.layer != led_data.layer || old_led_data.indicators != led_data.indicators) { + zmk_rgb_underglow_central_send(); + } +#else +#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE) + // leds for peripheral(right) side + /* if (zmk_ble_active_profile_is_open()) { + pixels[0].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE * last_ble_state[0]; + pixels[0].g = 0; + pixels[0].b = 0; + pixels[1].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE * last_ble_state[0]; + pixels[1].g = 0; + pixels[1].b = 0; + pixels[2].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE * last_ble_state[0]; + pixels[2].g = 0; + pixels[2].b = 0; + if (state.animation_step > 3) { + last_ble_state[0] = !last_ble_state[0]; + state.animation_step = 0; + } + state.animation_step++; + } else */ + if (!zmk_split_bt_peripheral_is_connected()) { + pixels[0].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE * last_ble_state[1]; + pixels[0].g = 0; + pixels[0].b = 0; + pixels[1].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE * last_ble_state[1]; + pixels[1].g = 0; + pixels[1].b = 0; + pixels[2].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE * last_ble_state[1]; + pixels[2].g = 0; + pixels[2].b = 0; + if (state.animation_step > 14) { + last_ble_state[1] = !last_ble_state[1]; + state.animation_step = 0; + } + state.animation_step++; + } else { +#endif + // set first led as LED_NUMLOCK + pixels[2].r = + (led_data.indicators & ZMK_LED_NUMLOCK_BIT) * CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].g = + (led_data.indicators & ZMK_LED_NUMLOCK_BIT) * CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[2].b = + (led_data.indicators & ZMK_LED_NUMLOCK_BIT) * CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + // set second led as scroll Lock + pixels[1].r = + (led_data.indicators & ZMK_LED_SCROLLLOCK_BIT) * CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[1].g = + (led_data.indicators & ZMK_LED_SCROLLLOCK_BIT) * CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[1].b = + (led_data.indicators & ZMK_LED_SCROLLLOCK_BIT) * CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + // set third led as layer + switch (led_data.layer) { + case 0: + pixels[0].r = 0; + pixels[0].g = 0; + pixels[0].b = 0; + break; + case 1: + pixels[0].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 2: + pixels[0].r = 0; + pixels[0].g = 0; + pixels[0].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 3: + pixels[0].r = 0; + pixels[0].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].b = 0; + break; + case 4: + pixels[0].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].g = 0; + pixels[0].b = 0; + break; + case 5: + pixels[0].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].g = 0; + pixels[0].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 6: + pixels[0].r = 0; + pixels[0].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + break; + case 7: + pixels[0].r = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].g = CONFIG_ZMK_RGB_UNDERGLOW_BRT_SCALE; + pixels[0].b = 0; + break; + default: + pixels[0].r = 0; + pixels[0].g = 0; + pixels[0].b = 0; + break; + } +#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE) + } +#endif +#endif +} + +static void zmk_rgb_underglow_effect_test() { + triggered = true; + struct led_rgb rgb; + rgb.r = 0; + rgb.g = 0; + rgb.b = 0; + + for (int i = 0; i < STRIP_NUM_PIXELS; i++) { + struct zmk_led_hsb hsb = state.color; + hsb.h = state.animation_step; + + pixels[i] = hsb_to_rgb(hsb_scale_min_max(hsb)); + } + if (state.animation_step < (HUE_MAX * 3)) { + struct zmk_led_hsb hsb = state.color; + hsb.h = state.animation_step; + rgb.r = 0; + + pixels[0] = rgb; + pixels[1] = rgb; + pixels[2] = hsb_to_rgb(hsb_scale_min_max(hsb)); + } + if (state.animation_step < (HUE_MAX * 2)) { + struct zmk_led_hsb hsb = state.color; + hsb.h = state.animation_step - HUE_MAX; + rgb.r = 0; + rgb.g = 0; + rgb.b = 0; + pixels[0] = rgb; + pixels[1] = hsb_to_rgb(hsb_scale_min_max(hsb)); + pixels[2] = rgb; + } + if (state.animation_step < HUE_MAX) { + struct zmk_led_hsb hsb = state.color; + hsb.h = state.animation_step; + rgb.r = 0; + rgb.g = 0; + rgb.b = 0; + pixels[0] = hsb_to_rgb(hsb_scale_min_max(hsb)); + pixels[1] = rgb; + pixels[2] = rgb; + } + + state.animation_step += 20; + if (state.animation_step > (HUE_MAX * 3)) { + + rgb.r = 255; + rgb.g = 255; + rgb.b = 255; + for (int i = 0; i < STRIP_NUM_PIXELS; i++) + pixels[i] = rgb; + } +} + +static void zmk_rgb_underglow_effect_battery() { + uint8_t soc = zmk_battery_state_of_charge(); + struct led_rgb rgb; + if (soc > 80) { + rgb.r = 0; + rgb.g = 255; + rgb.b = 0; + } else if (soc > 50 && soc < 80) { + rgb.r = 255; + rgb.g = 255; + rgb.b = 0; + } else if (soc > 20 && soc < 51) { + rgb.r = 255; + rgb.g = 140; + rgb.b = 0; + } else { + rgb.r = 255; + rgb.g = 0; + rgb.b = 0; + } + for (int i = 0; i < STRIP_NUM_PIXELS; i++) { + pixels[i] = rgb; + } +} + static void zmk_rgb_underglow_tick(struct k_work *work) { switch (state.current_effect) { case UNDERGLOW_EFFECT_SOLID: diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 5d1cf36b871..b2c19a5ee1d 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -704,10 +704,144 @@ int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *bi return split_bt_invoke_behavior_payload(wrapper); } +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW) +K_THREAD_STACK_DEFINE(split_central_split_led_q_stack, + CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_LED_STACK_SIZE); + +struct k_work_q split_central_split_led_q; + +K_MSGQ_DEFINE(zmk_split_central_split_led_msgq, sizeof(struct zmk_split_update_led_data), + CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_LED_QUEUE_SIZE, 2); + +void split_central_split_led_callback(struct k_work *work) { + struct zmk_split_update_led_data payload; + + while (k_msgq_get(&zmk_split_central_split_led_msgq, &payload, K_NO_WAIT) == 0) { + if (peripherals[0].state != PERIPHERAL_SLOT_STATE_CONNECTED) { + LOG_ERR("Source not connected"); + continue; + } + + int err = bt_gatt_write_without_response(peripherals[0].conn, + peripherals[0].update_led_handle, &payload, + sizeof(struct zmk_split_update_led_data), true); + + if (err) { + LOG_ERR("Failed to write the update led characteristic (err %d)", err); + } + } +} + +K_WORK_DEFINE(split_central_split_led_work, split_central_split_led_callback); + +static int split_bt_update_led_payload(struct zmk_split_update_led_data payload) { + LOG_DBG(""); + + int err = k_msgq_put(&zmk_split_central_split_led_msgq, &payload, K_MSEC(100)); + if (err) { + switch (err) { + case -EAGAIN: { + LOG_WRN("Consumer message queue full, popping first message and queueing again"); + struct zmk_split_update_led_data discarded_report; + k_msgq_get(&zmk_split_central_split_led_msgq, &discarded_report, K_NO_WAIT); + return split_bt_update_led_payload(payload); + } + default: + LOG_WRN("Failed to queue behavior to send (%d)", err); + return err; + } + } + + k_work_submit_to_queue(&split_central_split_led_q, &split_central_split_led_work); + + return 0; +}; + +int zmk_split_bt_update_led(struct zmk_periph_led *periph) { + struct zmk_split_update_led_data payload = {.layer = periph->layer, + .indicators = periph->indicators}; + + return split_bt_update_led_payload(payload); +} +#endif + +#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT) +K_THREAD_STACK_DEFINE(split_central_split_bl_q_stack, + CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_BL_STACK_SIZE); + +struct k_work_q split_central_split_bl_q; + +K_MSGQ_DEFINE(zmk_split_central_split_bl_msgq, sizeof(struct zmk_split_update_bl_data), + CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_BL_QUEUE_SIZE, 2); + +void split_central_split_bl_callback(struct k_work *work) { + struct zmk_split_update_bl_data payload; + + while (k_msgq_get(&zmk_split_central_split_bl_msgq, &payload, K_NO_WAIT) == 0) { + if (peripherals[0].state != PERIPHERAL_SLOT_STATE_CONNECTED) { + LOG_ERR("Source not connected"); + continue; + } + + int err = + bt_gatt_write_without_response(peripherals[0].conn, peripherals[0].update_bl_handle, + &payload, sizeof(struct zmk_split_update_bl_data), true); + + if (err) { + LOG_ERR("Failed to write the update bl characteristic (err %d)", err); + } + } +} + +K_WORK_DEFINE(split_central_split_bl_work, split_central_split_bl_callback); + +static int split_bt_update_bl_payload(struct zmk_split_update_bl_data payload) { + LOG_DBG(""); + + int err = k_msgq_put(&zmk_split_central_split_bl_msgq, &payload, K_MSEC(100)); + if (err) { + switch (err) { + case -EAGAIN: { + LOG_WRN("Consumer message queue full, popping first message and queueing again"); + struct zmk_split_update_bl_data discarded_report; + k_msgq_get(&zmk_split_central_split_bl_msgq, &discarded_report, K_NO_WAIT); + return split_bt_update_bl_payload(payload); + } + default: + LOG_WRN("Failed to queue behavior to send (%d)", err); + return err; + } + } + + k_work_submit_to_queue(&split_central_split_bl_q, &split_central_split_bl_work); + + return 0; +}; + +int zmk_split_bt_update_bl(struct backlight_state *periph) { + struct zmk_split_update_bl_data payload = {.brightness = periph->brightness, .on = periph->on}; + + return split_bt_update_bl_payload(payload); +} +#endif + int zmk_split_bt_central_init(const struct device *_arg) { k_work_queue_start(&split_central_split_run_q, split_central_split_run_q_stack, K_THREAD_STACK_SIZEOF(split_central_split_run_q_stack), CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL); + +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW) + k_work_queue_start(&split_central_split_led_q, split_central_split_led_q_stack, + K_THREAD_STACK_SIZEOF(split_central_split_led_q_stack), + CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL); +#endif + +#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT) + k_work_queue_start(&split_central_split_bl_q, split_central_split_bl_q_stack, + K_THREAD_STACK_SIZEOF(split_central_split_bl_q_stack), + CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL); +#endif + bt_conn_cb_register(&conn_callbacks); return IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) ? 0 : start_scanning(); diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c index 4059e746be1..8f85848c94a 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -49,6 +49,14 @@ static struct zmk_split_run_behavior_payload behavior_run_payload; static struct zmk_split_update_led_data update_led_data; static struct zmk_split_update_bl_data update_bl_data; +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW) +static struct zmk_split_update_led_data update_led_data; +#endif + +#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT) +static struct zmk_split_update_bl_data update_bl_data; +#endif + static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs, void *buf, uint16_t len, uint16_t offset) { return bt_gatt_attr_read(conn, attrs, buf, len, offset, &position_state, @@ -100,6 +108,52 @@ static ssize_t split_svc_run_behavior(struct bt_conn *conn, const struct bt_gatt return len; } +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW) +static ssize_t split_svc_update_led(struct bt_conn *conn, const struct bt_gatt_attr *attrs, + const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { + struct zmk_split_update_led_data *payload = attrs->user_data; + uint16_t end_addr = offset + len; + + LOG_DBG("offset %d len %d", offset, len); + + memcpy(payload + offset, buf, len); + + // We run if: + // 1: We've gotten all the position/state/param data. + // 2: We have a null terminated string for the behavior device label. + if ((end_addr == sizeof(struct zmk_split_update_led_data))) { + struct zmk_periph_led periph = {.layer = payload->layer, .indicators = payload->indicators}; + zmk_rgb_underglow_set_periph(periph); + LOG_DBG("Update leds with params %d and %d", periph.layer, periph.indicators); + } + + return len; +} +#endif + +#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT) +static ssize_t split_svc_update_bl(struct bt_conn *conn, const struct bt_gatt_attr *attrs, + const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { + struct zmk_split_update_bl_data *payload = attrs->user_data; + uint16_t end_addr = offset + len; + + LOG_DBG("offset %d len %d", offset, len); + + memcpy(payload + offset, buf, len); + + // We run if: + // 1: We've gotten all the position/state/param data. + // 2: We have a null terminated string for the behavior device label. + if ((end_addr == sizeof(struct zmk_split_update_bl_data))) { + struct backlight_state periph = {.brightness = payload->brightness, .on = payload->on}; + zmk_backlight_update_vals(periph); + LOG_DBG("Update leds with params %d and %d", periph.on, periph.brightness); + } + + return len; +} +#endif + static ssize_t split_svc_num_of_positions(struct bt_conn *conn, const struct bt_gatt_attr *attrs, void *buf, uint16_t len, uint16_t offset) { return bt_gatt_attr_read(conn, attrs, buf, len, offset, attrs->user_data, sizeof(uint8_t)); @@ -118,6 +172,19 @@ BT_GATT_SERVICE_DEFINE( BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID), BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, split_svc_run_behavior, &behavior_run_payload), + +#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW) + BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_UPDATE_LED_UUID), + BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, + split_svc_update_led, &update_led_data), +#endif + +#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT) + BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_UPDATE_BL_UUID), + BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, + split_svc_update_bl, &update_bl_data), +#endif + BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL, &num_of_positions), #if ZMK_KEYMAP_HAS_SENSORS diff --git a/app/tests/backlight/basic/native_posix_64.conf b/app/tests/backlight/basic/native_posix_64.conf index bd29a072c9c..e06889e62c1 100644 --- a/app/tests/backlight/basic/native_posix_64.conf +++ b/app/tests/backlight/basic/native_posix_64.conf @@ -9,3 +9,5 @@ CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 CONFIG_LED_GPIO=y CONFIG_ZMK_BACKLIGHT=y +CONFIG_ZMK_BACKLIGHT_BRT_START=40 +CONFIG_ZMK_BACKLIGHT_BRT_SCALE=100 diff --git a/app/tests/backlight/config-brt/native_posix_64.conf b/app/tests/backlight/config-brt/native_posix_64.conf index 65cdd3263d9..71a0122430b 100644 --- a/app/tests/backlight/config-brt/native_posix_64.conf +++ b/app/tests/backlight/config-brt/native_posix_64.conf @@ -10,3 +10,4 @@ CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 CONFIG_LED_GPIO=y CONFIG_ZMK_BACKLIGHT=y CONFIG_ZMK_BACKLIGHT_BRT_START=60 +CONFIG_ZMK_BACKLIGHT_BRT_SCALE=100 diff --git a/app/tests/backlight/config-on/native_posix_64.conf b/app/tests/backlight/config-on/native_posix_64.conf index eb9e7c8a1b2..af1222f321b 100644 --- a/app/tests/backlight/config-on/native_posix_64.conf +++ b/app/tests/backlight/config-on/native_posix_64.conf @@ -10,3 +10,5 @@ CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 CONFIG_LED_GPIO=y CONFIG_ZMK_BACKLIGHT=y CONFIG_ZMK_BACKLIGHT_ON_START=n +CONFIG_ZMK_BACKLIGHT_BRT_START=40 +CONFIG_ZMK_BACKLIGHT_BRT_SCALE=100 diff --git a/app/tests/backlight/config-step/native_posix_64.conf b/app/tests/backlight/config-step/native_posix_64.conf index c03eb7b01a6..3d14669f38e 100644 --- a/app/tests/backlight/config-step/native_posix_64.conf +++ b/app/tests/backlight/config-step/native_posix_64.conf @@ -11,3 +11,4 @@ CONFIG_LED_GPIO=y CONFIG_ZMK_BACKLIGHT=y CONFIG_ZMK_BACKLIGHT_BRT_START=60 CONFIG_ZMK_BACKLIGHT_BRT_STEP=30 +CONFIG_ZMK_BACKLIGHT_BRT_SCALE=100 diff --git a/app/tests/backlight/cycle/native_posix_64.conf b/app/tests/backlight/cycle/native_posix_64.conf index bd29a072c9c..e06889e62c1 100644 --- a/app/tests/backlight/cycle/native_posix_64.conf +++ b/app/tests/backlight/cycle/native_posix_64.conf @@ -9,3 +9,5 @@ CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 CONFIG_LED_GPIO=y CONFIG_ZMK_BACKLIGHT=y +CONFIG_ZMK_BACKLIGHT_BRT_START=40 +CONFIG_ZMK_BACKLIGHT_BRT_SCALE=100 diff --git a/app/tests/backlight/low-brightness/native_posix_64.conf b/app/tests/backlight/low-brightness/native_posix_64.conf index bd29a072c9c..e06889e62c1 100644 --- a/app/tests/backlight/low-brightness/native_posix_64.conf +++ b/app/tests/backlight/low-brightness/native_posix_64.conf @@ -9,3 +9,5 @@ CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 CONFIG_LED_GPIO=y CONFIG_ZMK_BACKLIGHT=y +CONFIG_ZMK_BACKLIGHT_BRT_START=40 +CONFIG_ZMK_BACKLIGHT_BRT_SCALE=100