diff --git a/app/dts/bindings/behaviors/three_param.yaml b/app/dts/bindings/behaviors/three_param.yaml new file mode 100644 index 00000000..c60f662d --- /dev/null +++ b/app/dts/bindings/behaviors/three_param.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +properties: + label: + type: string + required: false + deprecated: true + "#binding-cells": + type: int + required: true + const: 3 + +binding-cells: + - param1 + - param2 + - param3 diff --git a/app/include/zmk/behavior.h b/app/include/zmk/behavior.h index d45bbfff..a753e0ad 100644 --- a/app/include/zmk/behavior.h +++ b/app/include/zmk/behavior.h @@ -20,6 +20,7 @@ struct zmk_behavior_binding { const char *behavior_dev; uint32_t param1; uint32_t param2; + uint32_t param3; }; struct zmk_behavior_binding_event { diff --git a/app/include/zmk/split/bluetooth/service.h b/app/include/zmk/split/bluetooth/service.h index 112cd552..b18b1ca6 100644 --- a/app/include/zmk/split/bluetooth/service.h +++ b/app/include/zmk/split/bluetooth/service.h @@ -23,6 +23,7 @@ struct zmk_split_run_behavior_data { uint8_t state; uint32_t param1; uint32_t param2; + uint32_t param3; } __packed; struct zmk_split_run_behavior_payload { diff --git a/app/src/behavior_queue.c b/app/src/behavior_queue.c index 1511e755..e075be75 100644 --- a/app/src/behavior_queue.c +++ b/app/src/behavior_queue.c @@ -28,8 +28,8 @@ static void behavior_queue_process_next(struct k_work *work) { struct q_item item = {.wait = 0}; while (k_msgq_get(&zmk_behavior_queue_msgq, &item, K_NO_WAIT) == 0) { - LOG_DBG("Invoking %s: 0x%02x 0x%02x", item.binding.behavior_dev, item.binding.param1, - item.binding.param2); + LOG_DBG("Invoking %s: 0x%02x 0x%02x 0x%02x", item.binding.behavior_dev, item.binding.param1, + item.binding.param2, item.binding.param3); struct zmk_behavior_binding_event event = {.position = item.position, .timestamp = k_uptime_get()}; diff --git a/app/src/behaviors/behavior_rgb_underglow.c b/app/src/behaviors/behavior_rgb_underglow.c index c37e5217..e38e5bbc 100644 --- a/app/src/behaviors/behavior_rgb_underglow.c +++ b/app/src/behaviors/behavior_rgb_underglow.c @@ -198,19 +198,39 @@ on_keymap_binding_convert_central_state_dependent_params(struct zmk_behavior_bin case RGB_EFF_CMD: { binding->param1 = RGB_EFS_CMD; binding->param2 = zmk_rgb_underglow_calc_effect(1); + // Set the start date for the effect to begin to be 50ms in the future. + // This gives us time to get things ready on the both halves. + // TODO(PT): This is just to convey the idea, I'm unsure if the timescale here is actually milliseconds. + binding->param3 = k_uptime_get() + 50; break; } default: return 0; } - LOG_DBG("RGB relative convert to absolute (%d/%d)", binding->param1, binding->param2); + LOG_DBG("RGB relative convert to absolute (%d/%d, %d)", binding->param1, binding->param2, binding->param3); return 0; }; static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { + if (binding->param3 > 0) { + // TODO(PT): Here, both halves would wait until the start date specified by param3 has been + // reached. + // In my testing, however, it appears that this is invoked on the main half before the BLE + // command is sent to the peripheral half, so I think more rearranging would be needed + // (or perhaps this isn't the right place for this at all). + // Also, importantly, the clock here is currently just the uptime of this half, which isn't + // synchronized between the halves. If this were a real feature, each half would need to be + // synchronized with an external clock (or just each other's clocks). This perhaps could be + // pulled from the host? + LOG_WRN("Sleeping until timestamp is reached..."); + while (k_uptime_get() < binding->param3) { + // TODO(PT): Perhaps Zephyr has some kind of utility for a gentle spinloop? + } + LOG_WRN("Timestamp has elapsed! Timestamp: %d, Now: %d", binding->param3, k_uptime_get()); + } switch (binding->param1) { case RGB_TOG_CMD: return zmk_rgb_underglow_toggle(); diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 0f4cd78b..cee636bb 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -815,6 +815,7 @@ int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *bi struct zmk_split_run_behavior_payload payload = {.data = { .param1 = binding->param1, .param2 = binding->param2, + .param3 = binding->param3, .position = event.position, .state = state ? 1 : 0, }}; diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c index 505eb363..5484ad72 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -80,10 +80,11 @@ static ssize_t split_svc_run_behavior(struct bt_conn *conn, const struct bt_gatt struct zmk_behavior_binding binding = { .param1 = payload->data.param1, .param2 = payload->data.param2, + .param3 = payload->data.param3, .behavior_dev = payload->behavior_dev, }; - LOG_DBG("%s with params %d %d: pressed? %d", binding.behavior_dev, binding.param1, - binding.param2, payload->data.state); + LOG_WRN("%s with params %d %d %d: pressed? %d", binding.behavior_dev, binding.param1, + binding.param2, binding.param3, payload->data.state); struct zmk_behavior_binding_event event = {.position = payload->data.position, .timestamp = k_uptime_get()}; int err;