From 07127fb074e8e8447e8b73f83d57966cdaea9d4a Mon Sep 17 00:00:00 2001 From: Eduard Iten Date: Tue, 17 Feb 2026 15:02:46 +0100 Subject: [PATCH] Sync while working on OT --- firmware/libs/game_mgmt/Kconfig | 1 + firmware/libs/game_mgmt/include/game_mgmt.h | 2 +- firmware/libs/game_mgmt/src/game_mgmt.c | 54 ++++++++++++++++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/firmware/libs/game_mgmt/Kconfig b/firmware/libs/game_mgmt/Kconfig index 45e5428..9f8ab9d 100644 --- a/firmware/libs/game_mgmt/Kconfig +++ b/firmware/libs/game_mgmt/Kconfig @@ -3,6 +3,7 @@ menuconfig GAME_MGMT # select BT select OPENTHREAD select OPENTHREAD_COAP + select LASERTAG_UTILS help Library for managing game states and logic in the lasertag device. diff --git a/firmware/libs/game_mgmt/include/game_mgmt.h b/firmware/libs/game_mgmt/include/game_mgmt.h index 4ab2bff..a6ef877 100644 --- a/firmware/libs/game_mgmt/include/game_mgmt.h +++ b/firmware/libs/game_mgmt/include/game_mgmt.h @@ -42,7 +42,7 @@ typedef struct __packed { struct { - uint32_t start_time; // lower 32 bits of the start time in the open thread timer + uint32_t start_time; // lower 32 bits of OpenThread network time in microseconds uint32_t duration; // in seconds, maximum 49 days (2^32 seconds), should be sufficient for any match ;) } start_game; struct diff --git a/firmware/libs/game_mgmt/src/game_mgmt.c b/firmware/libs/game_mgmt/src/game_mgmt.c index e3bbe40..d7f4a83 100644 --- a/firmware/libs/game_mgmt/src/game_mgmt.c +++ b/firmware/libs/game_mgmt/src/game_mgmt.c @@ -9,14 +9,18 @@ #include #include #include +#include LOG_MODULE_REGISTER(game_mgmt, CONFIG_GAME_MGMT_LOG_LEVEL); +// Global variables static sys_state_t current_state = SYS_STATE_IDLE; static uint64_t current_game_id = 0; +static struct k_work_delayable game_state_work; +// Forward declarations int game_mgmt_init_coap(void); -otInstance *openthread_get_default_instance(void); +void game_start_handler(struct k_work *work); static otInstance *game_mgmt_get_instance(void) { @@ -59,6 +63,18 @@ static int ot_error_to_errno(otError err) } } +static uint64_t game_mgmt_expand_t32_us(uint32_t t32_us, uint64_t now_us) +{ + uint64_t expanded_us = (now_us & 0xFFFFFFFF00000000ULL) | t32_us; + + if (expanded_us < now_us) + { + expanded_us += (1ULL << 32); + } + + return expanded_us; +} + static int game_mgmt_send_control_to(const otIp6Address *peer_addr, const game_control_payload_t *payload) { otInstance *instance = game_mgmt_get_instance(); @@ -129,6 +145,31 @@ static int game_mgmt_send_control_to(const otIp6Address *peer_addr, const game_c return 0; } +void schedule_game_start(uint64_t startTime_us) +{ + uint64_t now_us; + + now_us = thread_mgmt_get_network_time(); + if (now_us == 0) { + LOG_ERR("Cannot schedule game start: Network time not synchronized"); + return; + } + + int64_t delay_us = (int64_t)(startTime_us - now_us); + + if (delay_us > 0) { + k_work_init_delayable(&game_state_work, game_start_handler); + + k_work_reschedule(&game_state_work, K_USEC(delay_us)); + + printk("Game scheduled in %lld ms\n", delay_us / 1000); + } else { + // Start time is in the past -> execute immediately + k_work_init_delayable(&game_state_work, game_start_handler); + k_work_submit(&game_state_work.work); + } +} + int game_mgmt_send_control_multicast(const game_control_payload_t *payload) { otIp6Address multicast_addr; @@ -239,6 +280,10 @@ static void handle_game_control(void *aContext, otMessage *aMessage, const otMes LOG_DBG("Broadcast received: start time 0x%08X, duration %u s", payload.data.start_game.start_time, payload.data.start_game.duration); + + uint64_t now_us = thread_mgmt_get_network_time(); + uint64_t start_time_us = game_mgmt_expand_t32_us(payload.data.start_game.start_time, now_us); + schedule_game_start(start_time_us); } } } @@ -272,6 +317,12 @@ int game_mgmt_init_coap(void) return 0; } +void game_start_handler(struct k_work *work) +{ + ARG_UNUSED(work); + LOG_INF(FORMAT_BLUE_BOLD("Game start handler triggered")); +} + #if IS_ENABLED(CONFIG_GAME_MGMT_SHELL) #include @@ -298,6 +349,7 @@ static int cmd_game_start(const struct shell *sh, size_t argc, char **argv) } shell_print(sh, "Start broadcast sent for T+%u s.", delay_s); + schedule_game_start(game_mgmt_expand_t32_us(payload.data.start_game.start_time, now)); return 0; }