From 4be177aae0e2f877ed9ee180f1befca46375a29b Mon Sep 17 00:00:00 2001 From: angweekiat Date: Thu, 5 Sep 2024 18:54:21 +0800 Subject: [PATCH 1/4] feat(split): sync central & peripherals last activity timing Sync central last activity timings to all devices, by having the central emit how long it's inactive for, and the peripheral(s) using it to adjust the local last activity time. Prior to this commit, key presses on a peripheral keeps the central awake, but not vice versa. With this commit, key presses on the central (or hypothetical peripheral B) can keep peripheral A awake. This is done by: 1. Adding a new `SYNC_ACTIVITY` GATT characteristic for central to sync it's inactive timer to the other peripheral(s). 2. Central's `activity.c` broadcasting the inactive time at a regular `ZMK_SPLIT_SYNC_SLEEP_TIMERS_INTERVAL_MS` interval 3. Peripheral's `service.c` receiving the data and sending it to its `activity.c` 4. Peripheral's `activity.c` determining the new `activity_last_uptime` value using the inactive duration as a relative difference. Additionally: - `central.c` is updated to sync the timers upon a new BLE connection, so that new devices don't need to wait the full interval to get sync-ed. - If a peripheral is in IDLE mode when the central comes online, it'll get sync-ed to ACTIVE as well. Cons: - This solution doesn't handle cases where the peripheral(s) is already in deep sleep, since BLE is turned off. However, the sync-ing can prevent peripheral(s) from going into deep sleep if the central is used. - This is a time based sync, so it won't be as accurate as event based where each key press is sync-ed to the peripheral(s), but that would take up more of the channel bandwidth. - If `ZMK_SPLIT_SYNC_SLEEP_TIMERS_INTERVAL_MS` > `ZMK_IDLE_TIMEOUT`, there can be situations where the peripheral(s) goes into IDLE before receiving the next sync from central. The original default interval was 5 minutes, primarily to prevent unnecessary deep sleeps, but it would run into the above case. --- app/CMakeLists.txt | 1 + app/include/zmk/events/sync_activity_event.h | 16 +++++ app/include/zmk/split/bluetooth/central.h | 8 ++- app/include/zmk/split/bluetooth/uuid.h | 1 + app/src/activity.c | 49 ++++++++++++++- app/src/events/sync_activity_event.c | 10 +++ app/src/split/Kconfig | 15 +++++ app/src/split/bluetooth/central.c | 66 ++++++++++++++++++++ app/src/split/bluetooth/service.c | 33 ++++++++++ 9 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 app/include/zmk/events/sync_activity_event.h create mode 100644 app/src/events/sync_activity_event.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index fd4b7ab5519..5ab6a3e3887 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -94,6 +94,7 @@ target_sources_ifdef(CONFIG_ZMK_BATTERY_REPORTING app PRIVATE src/battery.c) target_sources_ifdef(CONFIG_ZMK_HID_INDICATORS app PRIVATE src/events/hid_indicators_changed.c) target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_peripheral_status_changed.c) +target_sources_ifdef(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING app PRIVATE src/events/sync_activity_event.c) add_subdirectory(src/split) target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c) diff --git a/app/include/zmk/events/sync_activity_event.h b/app/include/zmk/events/sync_activity_event.h new file mode 100644 index 00000000000..18d48095828 --- /dev/null +++ b/app/include/zmk/events/sync_activity_event.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include + +struct zmk_sync_activity_event { + int32_t central_inactive_duration; +}; + +ZMK_EVENT_DECLARE(zmk_sync_activity_event); diff --git a/app/include/zmk/split/bluetooth/central.h b/app/include/zmk/split/bluetooth/central.h index 5e9e09ff6a1..491fe5d4989 100644 --- a/app/include/zmk/split/bluetooth/central.h +++ b/app/include/zmk/split/bluetooth/central.h @@ -21,4 +21,10 @@ int zmk_split_bt_update_hid_indicator(zmk_hid_indicators_t indicators); int zmk_split_get_peripheral_battery_level(uint8_t source, uint8_t *level); -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) \ No newline at end of file +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + +int zmk_split_bt_sync_activity(int32_t inactive_duration); + +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) \ No newline at end of file diff --git a/app/include/zmk/split/bluetooth/uuid.h b/app/include/zmk/split/bluetooth/uuid.h index dccdfc804c5..07da04df4a6 100644 --- a/app/include/zmk/split/bluetooth/uuid.h +++ b/app/include/zmk/split/bluetooth/uuid.h @@ -18,3 +18,4 @@ #define ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID ZMK_BT_SPLIT_UUID(0x00000002) #define ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000003) #define ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID ZMK_BT_SPLIT_UUID(0x00000004) +#define ZMK_SPLIT_BT_CHAR_SYNC_ACTIVITY_UUID ZMK_BT_SPLIT_UUID(0x00000005) diff --git a/app/src/activity.c b/app/src/activity.c index 454e91e5da0..ab069bd03de 100644 --- a/app/src/activity.c +++ b/app/src/activity.c @@ -17,6 +17,11 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#include +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) #include @@ -37,6 +42,12 @@ bool is_usb_power_present(void) { static enum zmk_activity_state activity_state; static uint32_t activity_last_uptime; +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ + IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) +static uint32_t last_sync_time; +#define SLEEP_TIMERS_SYNC_MS CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_INTERVAL_MS +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && + // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) #define MAX_IDLE_MS CONFIG_ZMK_IDLE_TIMEOUT @@ -68,6 +79,7 @@ int activity_event_listener(const zmk_event_t *eh) { void activity_work_handler(struct k_work *work) { int32_t current = k_uptime_get(); int32_t inactive_time = current - activity_last_uptime; + #if IS_ENABLED(CONFIG_ZMK_SLEEP) if (inactive_time > MAX_SLEEP_MS && !is_usb_power_present()) { // Put devices in suspend power mode before sleeping @@ -83,8 +95,17 @@ void activity_work_handler(struct k_work *work) { } else #endif /* IS_ENABLED(CONFIG_ZMK_SLEEP) */ if (inactive_time > MAX_IDLE_MS) { - set_state(ZMK_ACTIVITY_IDLE); - } + set_state(ZMK_ACTIVITY_IDLE); + } + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ + IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) + if (current - last_sync_time > SLEEP_TIMERS_SYNC_MS) { + last_sync_time = current; + zmk_split_bt_sync_activity(inactive_time); + } +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && + // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) } K_WORK_DEFINE(activity_work, activity_work_handler); @@ -104,4 +125,28 @@ ZMK_LISTENER(activity, activity_event_listener); ZMK_SUBSCRIPTION(activity, zmk_position_state_changed); ZMK_SUBSCRIPTION(activity, zmk_sensor_event); +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ + !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) +int sync_activity_event_listener(const zmk_event_t *eh) { + struct zmk_sync_activity_event *ev = as_zmk_sync_activity_event(eh); + if (ev == NULL) { + LOG_ERR("Invalid event type"); + return -ENOTSUP; + } + int32_t central_activity_last_uptime = k_uptime_get() - ev->central_inactive_duration; + activity_last_uptime = central_activity_last_uptime; + int32_t new_inactive_time = k_uptime_get() - activity_last_uptime; + + if (activity_state == ZMK_ACTIVITY_IDLE && new_inactive_time < MAX_IDLE_MS) { + LOG_DBG("Syncing state to active to match central device."); + return set_state(ZMK_ACTIVITY_ACTIVE); + } + return 0; +} + +ZMK_LISTENER(sync_activity, sync_activity_event_listener); +ZMK_SUBSCRIPTION(sync_activity, zmk_sync_activity_event); +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && + // !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) + SYS_INIT(activity_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/app/src/events/sync_activity_event.c b/app/src/events/sync_activity_event.c new file mode 100644 index 00000000000..2acc80f5ea3 --- /dev/null +++ b/app/src/events/sync_activity_event.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +ZMK_EVENT_IMPL(zmk_sync_activity_event); \ No newline at end of file diff --git a/app/src/split/Kconfig b/app/src/split/Kconfig index ce90037b1ea..ab1ee1df0d4 100644 --- a/app/src/split/Kconfig +++ b/app/src/split/Kconfig @@ -26,6 +26,21 @@ config ZMK_SPLIT_PERIPHERAL_HID_INDICATORS help Enable propagating the HID (LED) Indicator state to the split peripheral(s). +config ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING + bool "Sync last activity timing across all devices" + default n + help + Sync central device last activity timing to the split peripheral(s). + Does not help to wake up peripheral devices that have gone to deep sleep. + +if ZMK_SPLIT_ROLE_CENTRAL && ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING +config ZMK_SPLIT_SYNC_LAST_ACTIVITY_INTERVAL_MS + int "Last activity time sync interval in milliseconds" + default 30000 + +#ZMK_SPLIT_ROLE_CENTRAL && ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING +endif + #ZMK_SPLIT endif diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 0f4cd78b531..25aac767f64 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -49,6 +49,9 @@ struct peripheral_slot { struct bt_gatt_subscribe_params sensor_subscribe_params; struct bt_gatt_discover_params sub_discover_params; uint16_t run_behavior_handle; +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + uint16_t sync_activity_handle; +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) struct bt_gatt_subscribe_params batt_lvl_subscribe_params; struct bt_gatt_read_params batt_lvl_read_params; @@ -66,6 +69,11 @@ static bool is_scanning = false; static const struct bt_uuid_128 split_service_uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID); +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +static int32_t activity_inactive_duration; +static void split_central_sync_activity_with_delay(); +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_position_state_changed), CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4); @@ -144,6 +152,9 @@ int release_peripheral_slot(int index) { #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) slot->update_hid_indicators = 0; #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + slot->sync_activity_handle = 0; +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) return 0; } @@ -465,6 +476,13 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, slot->batt_lvl_read_params.single.offset = 0; bt_gatt_read(conn, &slot->batt_lvl_read_params); #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */ +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + } else if (!bt_uuid_cmp(chrc_uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_SYNC_ACTIVITY_UUID))) { + LOG_DBG("Found sync activity handle"); + slot->discover_params.uuid = NULL; + slot->discover_params.start_handle = attr->handle + 2; + slot->sync_activity_handle = bt_gatt_attr_value_handle(attr); +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) } bool subscribed = slot->run_behavior_handle && slot->subscribe_params.value_handle; @@ -476,6 +494,9 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) subscribed = subscribed && slot->update_hid_indicators; #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + subscribed = subscribed && slot->sync_activity_handle; +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) subscribed = subscribed && slot->batt_lvl_subscribe_params.value_handle; #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */ @@ -713,6 +734,10 @@ static void split_central_connected(struct bt_conn *conn, uint8_t conn_err) { confirm_peripheral_slot_conn(conn); split_central_process_connection(conn); + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + split_central_sync_activity_with_delay(); +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) } static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) { @@ -866,6 +891,47 @@ int zmk_split_bt_update_hid_indicator(zmk_hid_indicators_t indicators) { #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + +static void split_central_sync_activity_callback(struct k_work *work) { + for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { + if (peripherals[i].state != PERIPHERAL_SLOT_STATE_CONNECTED || + peripherals[i].sync_activity_handle == 0) { + continue; + } + + int err = bt_gatt_write_without_response( + peripherals[i].conn, peripherals[i].sync_activity_handle, &activity_inactive_duration, + sizeof(activity_inactive_duration), true); + + if (err) { + LOG_ERR("Failed to sync activity state (err %d)", err); + } + } +} + +static K_WORK_DEFINE(split_central_sync_activity, split_central_sync_activity_callback); + +void split_central_sync_activity_delay_timer_callback(struct k_timer *_timer) { + k_timer_stop(_timer); + k_work_submit_to_queue(&split_central_split_run_q, &split_central_sync_activity); +} +K_TIMER_DEFINE(split_central_sync_activity_delay_timer, + split_central_sync_activity_delay_timer_callback, NULL); + +static void split_central_sync_activity_with_delay() { + // Bluetooth discovery is done only after connection, so a delay is added here to compensate + // for that, before syncing the sleep timers + k_timer_start(&split_central_sync_activity_delay_timer, K_SECONDS(1), K_SECONDS(1)); +} + +int zmk_split_bt_sync_activity(int32_t inactive_duration) { + activity_inactive_duration = inactive_duration; + return k_work_submit_to_queue(&split_central_split_run_q, &split_central_sync_activity); +} + +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + static int finish_init() { 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 505eb363cd8..4f1769b0e4b 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -25,6 +25,9 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) #include #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#include +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) #include #include @@ -138,6 +141,30 @@ static ssize_t split_svc_update_indicators(struct bt_conn *conn, const struct bt #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +static int32_t central_inactive_duration; + +static void split_svc_sync_activity_callback(struct k_work *work) { + raise_zmk_sync_activity_event( + (struct zmk_sync_activity_event){.central_inactive_duration = central_inactive_duration}); +} + +static K_WORK_DEFINE(split_svc_sync_activity_work, split_svc_sync_activity_callback); + +static ssize_t split_svc_sync_activity(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, uint16_t offset, + uint8_t flags) { + if (offset + len > sizeof(int32_t)) { + return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); + } + + memcpy((uint8_t *)¢ral_inactive_duration + offset, buf, len); + k_work_submit(&split_svc_sync_activity_work); + + return len; +} +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + BT_GATT_SERVICE_DEFINE( split_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)), BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), @@ -160,6 +187,12 @@ BT_GATT_SERVICE_DEFINE( BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, split_svc_update_indicators, NULL), #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_SYNC_ACTIVITY_UUID), + BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, + split_svc_sync_activity, NULL), +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) ); K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE); From 63b989c0c3e01ff09c0779f9911a8111d9c587d4 Mon Sep 17 00:00:00 2001 From: angweekiat Date: Fri, 6 Sep 2024 20:44:59 +0800 Subject: [PATCH 2/4] add 2nd sync timer --- app/include/zmk/split/bluetooth/central.h | 2 +- app/src/activity.c | 25 ++++++++++++++++------- app/src/split/Kconfig | 8 ++++++-- app/src/split/bluetooth/central.c | 2 +- app/src/split/bluetooth/service.c | 1 + 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/app/include/zmk/split/bluetooth/central.h b/app/include/zmk/split/bluetooth/central.h index 491fe5d4989..69d024c2947 100644 --- a/app/include/zmk/split/bluetooth/central.h +++ b/app/include/zmk/split/bluetooth/central.h @@ -25,6 +25,6 @@ int zmk_split_get_peripheral_battery_level(uint8_t source, uint8_t *level); #if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) -int zmk_split_bt_sync_activity(int32_t inactive_duration); +int zmk_split_bt_queue_sync_activity(int32_t inactive_duration); #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) \ No newline at end of file diff --git a/app/src/activity.c b/app/src/activity.c index ab069bd03de..040ee8c0826 100644 --- a/app/src/activity.c +++ b/app/src/activity.c @@ -44,8 +44,10 @@ static enum zmk_activity_state activity_state; static uint32_t activity_last_uptime; #if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) -static uint32_t last_sync_time; -#define SLEEP_TIMERS_SYNC_MS CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_INTERVAL_MS +static uint32_t last_periodic_sync_time; +#if ZMK_SPLIT_SYNC_KEY_PRESS_INTERVAL_MS > 0 +static uint32_t last_event_sync_time; +#endif // ZMK_SPLIT_SYNC_KEY_PRESS_INTERVAL_MS > 0 #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) @@ -73,6 +75,15 @@ enum zmk_activity_state zmk_activity_get_state(void) { return activity_state; } int activity_event_listener(const zmk_event_t *eh) { activity_last_uptime = k_uptime_get(); +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ + IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && ZMK_SPLIT_SYNC_KEY_PRESS_INTERVAL_MS > 0 + if (current - last_event_sync_time > ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS) { + last_event_sync_time = current; + zmk_split_bt_queue_sync_activity(0); + } +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && + // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && ZMK_SPLIT_SYNC_KEY_PRESS_INTERVAL_MS > 0 + return set_state(ZMK_ACTIVITY_ACTIVE); } @@ -95,14 +106,14 @@ void activity_work_handler(struct k_work *work) { } else #endif /* IS_ENABLED(CONFIG_ZMK_SLEEP) */ if (inactive_time > MAX_IDLE_MS) { - set_state(ZMK_ACTIVITY_IDLE); - } + set_state(ZMK_ACTIVITY_IDLE); + } #if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) - if (current - last_sync_time > SLEEP_TIMERS_SYNC_MS) { - last_sync_time = current; - zmk_split_bt_sync_activity(inactive_time); + if (current - last_periodic_sync_time > CONFIG_ZMK_SPLIT_SYNC_PERIODIC_INTERVAL_MS) { + last_periodic_sync_time = current; + zmk_split_bt_queue_sync_activity(inactive_time); } #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) diff --git a/app/src/split/Kconfig b/app/src/split/Kconfig index ab1ee1df0d4..ff7d1431164 100644 --- a/app/src/split/Kconfig +++ b/app/src/split/Kconfig @@ -34,10 +34,14 @@ config ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING Does not help to wake up peripheral devices that have gone to deep sleep. if ZMK_SPLIT_ROLE_CENTRAL && ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING -config ZMK_SPLIT_SYNC_LAST_ACTIVITY_INTERVAL_MS - int "Last activity time sync interval in milliseconds" +config ZMK_SPLIT_SYNC_PERIODIC_INTERVAL_MS + int "Last activity time periodic sync interval in milliseconds" default 30000 +config ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS + int "Last activity time sync interval in milliseconds" + default 0 + #ZMK_SPLIT_ROLE_CENTRAL && ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING endif diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 25aac767f64..81dae40940b 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -925,7 +925,7 @@ static void split_central_sync_activity_with_delay() { k_timer_start(&split_central_sync_activity_delay_timer, K_SECONDS(1), K_SECONDS(1)); } -int zmk_split_bt_sync_activity(int32_t inactive_duration) { +int zmk_split_bt_queue_sync_activity(int32_t inactive_duration) { activity_inactive_duration = inactive_duration; return k_work_submit_to_queue(&split_central_split_run_q, &split_central_sync_activity); } diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c index 4f1769b0e4b..1030efe9a16 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -193,6 +193,7 @@ BT_GATT_SERVICE_DEFINE( BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, split_svc_sync_activity, NULL), #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + ); K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE); From 273ad05c45893ef6b336e2346105ab1cfe5cf1b2 Mon Sep 17 00:00:00 2001 From: angweekiat Date: Fri, 6 Sep 2024 21:26:46 +0800 Subject: [PATCH 3/4] cleanup variables --- app/src/activity.c | 14 +++++++------- app/src/split/Kconfig | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/activity.c b/app/src/activity.c index 040ee8c0826..3dac94e35fd 100644 --- a/app/src/activity.c +++ b/app/src/activity.c @@ -45,9 +45,9 @@ static uint32_t activity_last_uptime; #if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) static uint32_t last_periodic_sync_time; -#if ZMK_SPLIT_SYNC_KEY_PRESS_INTERVAL_MS > 0 +#if CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS > 0 static uint32_t last_event_sync_time; -#endif // ZMK_SPLIT_SYNC_KEY_PRESS_INTERVAL_MS > 0 +#endif // CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS > 0 #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) @@ -76,13 +76,14 @@ int activity_event_listener(const zmk_event_t *eh) { activity_last_uptime = k_uptime_get(); #if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ - IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && ZMK_SPLIT_SYNC_KEY_PRESS_INTERVAL_MS > 0 - if (current - last_event_sync_time > ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS) { - last_event_sync_time = current; + IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS > 0 + if (activity_last_uptime - last_event_sync_time > CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS) { + last_event_sync_time = activity_last_uptime; zmk_split_bt_queue_sync_activity(0); } #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && - // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && ZMK_SPLIT_SYNC_KEY_PRESS_INTERVAL_MS > 0 + // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS > + // 0 return set_state(ZMK_ACTIVITY_ACTIVE); } @@ -90,7 +91,6 @@ int activity_event_listener(const zmk_event_t *eh) { void activity_work_handler(struct k_work *work) { int32_t current = k_uptime_get(); int32_t inactive_time = current - activity_last_uptime; - #if IS_ENABLED(CONFIG_ZMK_SLEEP) if (inactive_time > MAX_SLEEP_MS && !is_usb_power_present()) { // Put devices in suspend power mode before sleeping diff --git a/app/src/split/Kconfig b/app/src/split/Kconfig index ff7d1431164..556ace875c0 100644 --- a/app/src/split/Kconfig +++ b/app/src/split/Kconfig @@ -39,7 +39,7 @@ config ZMK_SPLIT_SYNC_PERIODIC_INTERVAL_MS default 30000 config ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS - int "Last activity time sync interval in milliseconds" + int "Sync timings on events (key/sensors presses) as well, 0 to disable. Represents minimum interval in milliseconds" default 0 #ZMK_SPLIT_ROLE_CENTRAL && ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING From aa2d3aa894206c0ec5a77bd65734cb166f8f303f Mon Sep 17 00:00:00 2001 From: angweekiat Date: Sat, 7 Sep 2024 15:27:00 +0800 Subject: [PATCH 4/4] split into 2 sync options --- app/CMakeLists.txt | 3 +- app/include/zmk/split/bluetooth/central.h | 6 ++- app/src/activity.c | 66 +++++++++++++---------- app/src/split/Kconfig | 23 ++++---- app/src/split/bluetooth/central.c | 38 +++++++------ app/src/split/bluetooth/service.c | 16 +++--- 6 files changed, 90 insertions(+), 62 deletions(-) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 5ab6a3e3887..162f2b59a4e 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -94,7 +94,8 @@ target_sources_ifdef(CONFIG_ZMK_BATTERY_REPORTING app PRIVATE src/battery.c) target_sources_ifdef(CONFIG_ZMK_HID_INDICATORS app PRIVATE src/events/hid_indicators_changed.c) target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_peripheral_status_changed.c) -target_sources_ifdef(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING app PRIVATE src/events/sync_activity_event.c) +target_sources_ifdef(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC app PRIVATE src/events/sync_activity_event.c) +target_sources_ifdef(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT app PRIVATE src/events/sync_activity_event.c) add_subdirectory(src/split) target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c) diff --git a/app/include/zmk/split/bluetooth/central.h b/app/include/zmk/split/bluetooth/central.h index 69d024c2947..addaa87677c 100644 --- a/app/include/zmk/split/bluetooth/central.h +++ b/app/include/zmk/split/bluetooth/central.h @@ -23,8 +23,10 @@ int zmk_split_get_peripheral_battery_level(uint8_t source, uint8_t *level); #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || \ + IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) int zmk_split_bt_queue_sync_activity(int32_t inactive_duration); -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) \ No newline at end of file +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || + // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) \ No newline at end of file diff --git a/app/src/activity.c b/app/src/activity.c index 3dac94e35fd..2087c0fb3fc 100644 --- a/app/src/activity.c +++ b/app/src/activity.c @@ -19,9 +19,11 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || \ + IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) #include -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || + // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) #include @@ -42,14 +44,20 @@ bool is_usb_power_present(void) { static enum zmk_activity_state activity_state; static uint32_t activity_last_uptime; -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ - IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) static uint32_t last_periodic_sync_time; -#if CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS > 0 +#define PERIODIC_SYNC_INTERVAL_MS CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC_INTERVAL_MS +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) static uint32_t last_event_sync_time; -#endif // CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS > 0 -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && - // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) +#define EVENT_SYNC_MIN_INTERVAL_MS CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_EVENT_MIN_INTERVAL +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) + +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) #define MAX_IDLE_MS CONFIG_ZMK_IDLE_TIMEOUT @@ -75,15 +83,15 @@ enum zmk_activity_state zmk_activity_get_state(void) { return activity_state; } int activity_event_listener(const zmk_event_t *eh) { activity_last_uptime = k_uptime_get(); -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ - IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS > 0 - if (activity_last_uptime - last_event_sync_time > CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS) { +#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && \ + IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) + if (activity_last_uptime - last_event_sync_time > EVENT_SYNC_MIN_INTERVAL_MS) { + LOG_DBG("Refresh %d", activity_last_uptime - last_event_sync_time); last_event_sync_time = activity_last_uptime; zmk_split_bt_queue_sync_activity(0); } -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && - // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && CONFIG_ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS > - // 0 +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && + // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) return set_state(ZMK_ACTIVITY_ACTIVE); } @@ -109,14 +117,14 @@ void activity_work_handler(struct k_work *work) { set_state(ZMK_ACTIVITY_IDLE); } -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ - IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) - if (current - last_periodic_sync_time > CONFIG_ZMK_SPLIT_SYNC_PERIODIC_INTERVAL_MS) { +#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && \ + IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) + if (current - last_periodic_sync_time > PERIODIC_SYNC_INTERVAL_MS) { last_periodic_sync_time = current; zmk_split_bt_queue_sync_activity(inactive_time); } -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && - // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && + // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) } K_WORK_DEFINE(activity_work, activity_work_handler); @@ -136,19 +144,22 @@ ZMK_LISTENER(activity, activity_event_listener); ZMK_SUBSCRIPTION(activity, zmk_position_state_changed); ZMK_SUBSCRIPTION(activity, zmk_sensor_event); -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && \ - !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) +#if !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && \ + (IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || \ + IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT)) + int sync_activity_event_listener(const zmk_event_t *eh) { + int32_t current = k_uptime_get(); + struct zmk_sync_activity_event *ev = as_zmk_sync_activity_event(eh); if (ev == NULL) { LOG_ERR("Invalid event type"); return -ENOTSUP; } - int32_t central_activity_last_uptime = k_uptime_get() - ev->central_inactive_duration; - activity_last_uptime = central_activity_last_uptime; - int32_t new_inactive_time = k_uptime_get() - activity_last_uptime; - if (activity_state == ZMK_ACTIVITY_IDLE && new_inactive_time < MAX_IDLE_MS) { + activity_last_uptime = current - ev->central_inactive_duration; + + if (activity_state == ZMK_ACTIVITY_IDLE && ev->central_inactive_duration < MAX_IDLE_MS) { LOG_DBG("Syncing state to active to match central device."); return set_state(ZMK_ACTIVITY_ACTIVE); } @@ -157,7 +168,8 @@ int sync_activity_event_listener(const zmk_event_t *eh) { ZMK_LISTENER(sync_activity, sync_activity_event_listener); ZMK_SUBSCRIPTION(sync_activity, zmk_sync_activity_event); -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) && - // !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) +#endif // !IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) && + // (IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || + // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT)) SYS_INIT(activity_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/app/src/split/Kconfig b/app/src/split/Kconfig index 556ace875c0..e10aff306ef 100644 --- a/app/src/split/Kconfig +++ b/app/src/split/Kconfig @@ -26,24 +26,27 @@ config ZMK_SPLIT_PERIPHERAL_HID_INDICATORS help Enable propagating the HID (LED) Indicator state to the split peripheral(s). -config ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING - bool "Sync last activity timing across all devices" +config ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC + bool "Sync last activity timing across all devices periodically" default n help - Sync central device last activity timing to the split peripheral(s). + Sync central device last activity timing to the split peripheral(s) with a periodic interval. Does not help to wake up peripheral devices that have gone to deep sleep. -if ZMK_SPLIT_ROLE_CENTRAL && ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING -config ZMK_SPLIT_SYNC_PERIODIC_INTERVAL_MS +config ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC_INTERVAL_MS int "Last activity time periodic sync interval in milliseconds" default 30000 -config ZMK_SPLIT_SYNC_EVENT_MIN_INTERVAL_MS - int "Sync timings on events (key/sensors presses) as well, 0 to disable. Represents minimum interval in milliseconds" - default 0 +config ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT + bool "Sync last activity timing across all devices upon central activity event" + default n + help + Sync central device last activity timing to the split peripheral(s) when an event (key press/sensor) + is detected. Does not help to wake up peripheral devices that have gone to deep sleep. -#ZMK_SPLIT_ROLE_CENTRAL && ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING -endif +config ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_EVENT_MIN_INTERVAL + int "Sync timings on events (key/sensors presses) as well, 0 to disable. Represents minimum interval in milliseconds" + default 1000 #ZMK_SPLIT endif diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 81dae40940b..398fc7620a9 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -35,6 +35,12 @@ static int start_scanning(void); #define POSITION_STATE_DATA_LEN 16 +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || \ + IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) +#define SYNC_LAST_ACTIVITY_TIMING 1 +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || + // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) + enum peripheral_slot_state { PERIPHERAL_SLOT_STATE_OPEN, PERIPHERAL_SLOT_STATE_CONNECTING, @@ -49,9 +55,9 @@ struct peripheral_slot { struct bt_gatt_subscribe_params sensor_subscribe_params; struct bt_gatt_discover_params sub_discover_params; uint16_t run_behavior_handle; -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) uint16_t sync_activity_handle; -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) struct bt_gatt_subscribe_params batt_lvl_subscribe_params; struct bt_gatt_read_params batt_lvl_read_params; @@ -69,10 +75,10 @@ static bool is_scanning = false; static const struct bt_uuid_128 split_service_uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID); -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) static int32_t activity_inactive_duration; static void split_central_sync_activity_with_delay(); -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_position_state_changed), CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4); @@ -152,9 +158,9 @@ int release_peripheral_slot(int index) { #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) slot->update_hid_indicators = 0; #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) slot->sync_activity_handle = 0; -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) return 0; } @@ -476,13 +482,13 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, slot->batt_lvl_read_params.single.offset = 0; bt_gatt_read(conn, &slot->batt_lvl_read_params); #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */ -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) } else if (!bt_uuid_cmp(chrc_uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_SYNC_ACTIVITY_UUID))) { LOG_DBG("Found sync activity handle"); slot->discover_params.uuid = NULL; slot->discover_params.start_handle = attr->handle + 2; slot->sync_activity_handle = bt_gatt_attr_value_handle(attr); -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) } bool subscribed = slot->run_behavior_handle && slot->subscribe_params.value_handle; @@ -494,9 +500,9 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) subscribed = subscribed && slot->update_hid_indicators; #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) subscribed = subscribed && slot->sync_activity_handle; -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) subscribed = subscribed && slot->batt_lvl_subscribe_params.value_handle; #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */ @@ -735,9 +741,11 @@ static void split_central_connected(struct bt_conn *conn, uint8_t conn_err) { confirm_peripheral_slot_conn(conn); split_central_process_connection(conn); -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) + // Bluetooth discovery is done only after connection, so a delay is + /// added here to compensate for that before syncing the activity time split_central_sync_activity_with_delay(); -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) } static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) { @@ -891,7 +899,7 @@ int zmk_split_bt_update_hid_indicator(zmk_hid_indicators_t indicators) { #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) static void split_central_sync_activity_callback(struct k_work *work) { for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { @@ -920,8 +928,6 @@ K_TIMER_DEFINE(split_central_sync_activity_delay_timer, split_central_sync_activity_delay_timer_callback, NULL); static void split_central_sync_activity_with_delay() { - // Bluetooth discovery is done only after connection, so a delay is added here to compensate - // for that, before syncing the sleep timers k_timer_start(&split_central_sync_activity_delay_timer, K_SECONDS(1), K_SECONDS(1)); } @@ -930,7 +936,7 @@ int zmk_split_bt_queue_sync_activity(int32_t inactive_duration) { return k_work_submit_to_queue(&split_central_split_run_q, &split_central_sync_activity); } -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) static int finish_init() { 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 1030efe9a16..4015dd791e3 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -25,9 +25,13 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) #include #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) + +#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || \ + IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) #include -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#define SYNC_LAST_ACTIVITY_TIMING 1 +#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_PERIODIC) || + // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING_ON_EVENT) #include #include @@ -141,7 +145,7 @@ static ssize_t split_svc_update_indicators(struct bt_conn *conn, const struct bt #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) static int32_t central_inactive_duration; static void split_svc_sync_activity_callback(struct k_work *work) { @@ -163,7 +167,7 @@ static ssize_t split_svc_sync_activity(struct bt_conn *conn, const struct bt_gat return len; } -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) BT_GATT_SERVICE_DEFINE( split_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)), @@ -188,11 +192,11 @@ BT_GATT_SERVICE_DEFINE( split_svc_update_indicators, NULL), #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) -#if IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#if IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_SYNC_ACTIVITY_UUID), BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, split_svc_sync_activity, NULL), -#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_SYNC_LAST_ACTIVITY_TIMING) +#endif // IS_ENABLED(SYNC_LAST_ACTIVITY_TIMING) );