From a9212c5a3ad76fbea9c401354ae092ef970b900e Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Mon, 3 Feb 2025 20:49:54 -0600 Subject: [PATCH 01/12] WIP: New BLE --- BLE/BLE_Packets.c | 84 +++++++++++++++++++--- BLE/BLE_Packets.h | 71 ++++++++++++++---- Settings/Settings_Interface.h | 7 +- States/Playing/State_Playing.c | 30 +++++--- States/Playing/State_Playing__Tagged_Out.c | 2 +- States/State_Configuring.c | 6 +- States/State_Initializing.c | 3 +- States/State_Machine.c | 13 ++-- States/State_Machine.h | 23 +++--- States/State_Ready.c | 2 +- States/State_Wrapping_Up.c | 2 +- SystemK.h | 4 ++ 12 files changed, 191 insertions(+), 56 deletions(-) diff --git a/BLE/BLE_Packets.c b/BLE/BLE_Packets.c index c2cc0a9..14a548c 100644 --- a/BLE/BLE_Packets.c +++ b/BLE/BLE_Packets.c @@ -147,7 +147,7 @@ void BLE_UpdateInstigationPacket(uint32_t Game_Length_in_ms, uint32_t Time_Remai } } -void BLE_UpdateStatusPacket() +void BLE_UpdateStatusPacket(uint8_t current_state) { static uint8_t EventNumber = 0; @@ -190,7 +190,7 @@ void BLE_UpdateStatusPacket() Advertising_Data.data[23] = (Team_Color >> 8) & 0xFF; // Secondary Color Advertising_Data.data[24] = (Team_Color >> 16) & 0xFF; // Secondary Color Advertising_Data.data[25] = (Team_Color >> 24) & 0xFF; // Secondary Color - Advertising_Data.data[26] = 0xFF; + Advertising_Data.data[26] = current_state; Advertising_Data.data[27] = 0xFF; Advertising_Data.data[28] = 0xFF; Advertising_Data.data[29] = 0xFF; @@ -237,12 +237,12 @@ void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[B Advertising_Data.data[17] = (color >> 8) & 0xFF; Advertising_Data.data[18] = (color >> 16) & 0xFF; Advertising_Data.data[19] = (color >> 24) & 0xFF; - Advertising_Data.data[20] = target_BD_ADDR[0], - Advertising_Data.data[21] = target_BD_ADDR[1], - Advertising_Data.data[22] = target_BD_ADDR[2], - Advertising_Data.data[23] = target_BD_ADDR[3], - Advertising_Data.data[24] = target_BD_ADDR[4], - Advertising_Data.data[25] = target_BD_ADDR[5], + Advertising_Data.data[20] = target_BD_ADDR[0]; + Advertising_Data.data[21] = target_BD_ADDR[1]; + Advertising_Data.data[22] = target_BD_ADDR[2]; + Advertising_Data.data[23] = target_BD_ADDR[3]; + Advertising_Data.data[24] = target_BD_ADDR[4]; + Advertising_Data.data[25] = target_BD_ADDR[5]; Advertising_Data.data[26] = 0xFF; Advertising_Data.data[27] = 0xFF; Advertising_Data.data[28] = 0xFF; @@ -257,6 +257,74 @@ void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[B } } +void BLE_UpdateHelloPacket() +{ + static uint8_t EventNumber = 0; + + uint32_t device_type32; + uint16_t device_type = BLE_DEVICE_TYPE_UNKNOWN; + if (SETTINGS_get_uint32_t(SYSTEMK_SETTING_DEVICE_TYPE, &device_type32) == SYSTEMK_RESULT_SUCCESS) + { + device_type = (uint16_t)device_type32; + } + + uint8_t team_ID; + (void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_TEAMID, &team_ID); + + char device_name[SYSTEMK_MAX_CHARS_IN_DEVICE_NAME + 1]; + SystemKResult_T result = SETTINGS_get_device_name(&device_name[0]); + if (result != SYSTEMK_RESULT_SUCCESS) + { + strcpy(device_name, "Anonymous"); + } + size_t len = strlen(device_name); + if (len < sizeof(device_name)) { + memset(device_name + len, 0x00, sizeof(device_name) - len); + } + + Advertising_Data.length = BLE_KTAG_PACKET_TOTAL_SIZE; + + // Manufacturer Specific Data + Advertising_Data.data[0] = 0x1E; + Advertising_Data.data[1] = 0xFF; + Advertising_Data.data[2] = 0xFF; + Advertising_Data.data[3] = 0xFF; + Advertising_Data.data[4] = 'K'; + Advertising_Data.data[5] = 'T'; + Advertising_Data.data[6] = 'a'; + Advertising_Data.data[7] = 'g'; + Advertising_Data.data[8] = BLE_PACKET_TYPE_HELLO; + Advertising_Data.data[9] = EventNumber++; + Advertising_Data.data[10] = SYSTEMK_MAJOR_VERSION; + Advertising_Data.data[11] = SYSTEMK_MINOR_VERSION; + Advertising_Data.data[12] = (device_type >> 0) & 0xFF; + Advertising_Data.data[13] = (device_type >> 8) & 0xFF; + Advertising_Data.data[14] = team_ID; + Advertising_Data.data[15] = device_name[0]; + Advertising_Data.data[16] = device_name[1]; + Advertising_Data.data[17] = device_name[2]; + Advertising_Data.data[18] = device_name[3]; + Advertising_Data.data[19] = device_name[4]; + Advertising_Data.data[20] = device_name[5]; + Advertising_Data.data[21] = device_name[6]; + Advertising_Data.data[22] = device_name[7]; + Advertising_Data.data[23] = device_name[8]; + Advertising_Data.data[24] = device_name[9]; + Advertising_Data.data[25] = device_name[10]; + Advertising_Data.data[26] = device_name[11]; + Advertising_Data.data[27] = device_name[12]; + Advertising_Data.data[28] = device_name[13]; + Advertising_Data.data[29] = device_name[14]; + Advertising_Data.data[30] = device_name[15]; + + result = BLE_SetAdvertisingData(&Advertising_Data); + + if (result != SYSTEMK_RESULT_SUCCESS) + { + KLOG_ERROR(KLOG_TAG, "Error updating hello packet!"); + } +} + bool BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[6]) { bool for_me = false; diff --git a/BLE/BLE_Packets.h b/BLE/BLE_Packets.h index d1f0a03..d535b46 100644 --- a/BLE/BLE_Packets.h +++ b/BLE/BLE_Packets.h @@ -59,11 +59,13 @@ typedef enum BLE_PACKET_TYPE_BUFFER_FREE = 0, BLE_PACKET_TYPE_INSTIGATE_GAME = 1, BLE_FIRST_VALID_PACKET_TYPE = BLE_PACKET_TYPE_INSTIGATE_GAME, - BLE_PACKET_TYPE_JOIN_NOW = 2, + BLE_PACKET_TYPE_EVENT = 2, BLE_PACKET_TYPE_TAG = 3, BLE_PACKET_TYPE_CONSOLE = 4, BLE_PACKET_TYPE_STATUS = 5, - BLE_LAST_VALID_PACKET_TYPE = BLE_PACKET_TYPE_STATUS, + BLE_PACKET_TYPE_CONFIGURATION = 6, + BLE_PACKET_TYPE_HELLO = 7, + BLE_LAST_VALID_PACKET_TYPE = BLE_PACKET_TYPE_HELLO, BLE_PACKET_TYPE_UNKNOWN } BLE_PacketType_T; @@ -87,11 +89,10 @@ typedef struct uint32_t game_length_in_ms; uint32_t time_remaining_until_countdown_in_ms; - uint8_t random_time_after_countdown_in_ms_x100; - uint8_t unused[12]; + uint8_t unused[13]; } __attribute__((packed, aligned(1))) BLE_InstigationPacket_T; -//! Contents of the BLE packet #BLE_PACKET_TYPE_JOIN_NOW. +//! Contents of the BLE packet #BLE_PACKET_TYPE_EVENT. typedef struct { BLE_PacketType_T type; @@ -99,10 +100,11 @@ typedef struct int8_t RSSI; uint8_t event_number; - uint32_t game_length_in_ms; - uint32_t time_remaining_in_game_in_ms; - uint8_t unused[13]; -} __attribute__((packed, aligned(1))) BLE_JoinNowPacket_T; + uint8_t target_BD_ADDR[BD_ADDR_SIZE]; + uint32_t event_ID; + uint32_t event_data; + uint8_t unused[7]; +} __attribute__((packed, aligned(1))) BLE_EventPacket_T; //! Contents of the BLE packet #BLE_PACKET_TYPE_TAG. typedef struct @@ -149,17 +151,61 @@ typedef struct uint16_t maximum_health; color_t primary_color; color_t secondary_color; - uint8_t unused[5]; + uint8_t SystemK_top_level_state; // StateID_T + uint8_t unused[4]; } __attribute__((packed, aligned(1)))BLE_StatusPacket_T; +//! Contents of the BLE packet #BLE_PACKET_TYPE_CONFIGURATION. +typedef struct +{ + BLE_PacketType_T type; + uint8_t BD_ADDR[BD_ADDR_SIZE]; + int8_t RSSI; + uint8_t event_number; + + uint8_t target_BD_ADDR[BD_ADDR_SIZE]; + uint8_t subtype; + uint16_t key_one; + uint32_t value_one; + uint16_t key_two; + uint32_t value_two; + uint8_t unused[2]; +} __attribute__((packed, aligned(1)))BLE_ConfigurationPacket_T; + +typedef enum +{ + BLE_DEVICE_TYPE_LITTLE_BOY_BLUE = 0x0000, + BLE_DEVICE_TYPE_2020TPC = 0x0001, + BLE_DEVICE_TYPE_MOBILE_APP = 0x0002, + BLE_DEVICE_TYPE_32ESPECIAL = 0x0003, + BLE_DEVICE_TYPE_UNKNOWN = 0xFFFF +} BLE_DeviceType_T; + +//! Contents of the BLE packet #BLE_PACKET_TYPE_HELLO. +typedef struct +{ + BLE_PacketType_T type; + uint8_t BD_ADDR[BD_ADDR_SIZE]; + int8_t RSSI; + uint8_t event_number; + + uint8_t SystemK_major_version; + uint8_t SystemK_minor_version; + uint16_t device_type; + uint8_t team_ID; + uint8_t device_name[SYSTEMK_MAX_CHARS_IN_DEVICE_NAME]; +} __attribute__((packed, aligned(1)))BLE_HelloPacket_T; + typedef union { BLE_GenericPacketType_T Generic; BLE_InstigationPacket_T Instigation; - BLE_JoinNowPacket_T JoinNow; + BLE_EventPacket_T Event; BLE_TagPacket_T Tag; BLE_ConsolePacket_T Console; BLE_StatusPacket_T Status; + BLE_ConfigurationPacket_T Configuration; + BLE_HelloPacket_T Hello; } BLE_Packet_T; /* Include Files */ @@ -180,8 +226,9 @@ void BLE_InitPacketBuffers(void); BLE_Packet_T * BLE_DecodeKTagPacket(const uint8_t * received_data, uint8_t received_data_length, uint8_t peer_BD_ADDR[BD_ADDR_SIZE], int8_t rssi_in_dBm); void BLE_UpdateInstigationPacket(uint32_t Game_Length_in_ms, uint32_t Time_Remaining_Until_Countdown_in_ms); -void BLE_UpdateStatusPacket(); +void BLE_UpdateStatusPacket(uint8_t current_state); void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[BD_ADDR_SIZE]); +void BLE_UpdateHelloPacket(); bool BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[BD_ADDR_SIZE]); #ifdef __cplusplus diff --git a/Settings/Settings_Interface.h b/Settings/Settings_Interface.h index 4f80805..5074030 100644 --- a/Settings/Settings_Interface.h +++ b/Settings/Settings_Interface.h @@ -21,6 +21,8 @@ #ifndef SETTINGS_INTERFACE_H #define SETTINGS_INTERFACE_H + +#define SYSTEMK_MAX_CHARS_IN_DEVICE_NAME 15 typedef enum { @@ -29,13 +31,16 @@ typedef enum SYSTEMK_SETTING_TEAMID, SYSTEMK_SETTING_PLAYERID, SYSTEMK_SETTING_WEAPONID, - SYSTEMK_SETTING_T_START_GAME_in_ms + SYSTEMK_SETTING_T_START_GAME_in_ms, + SYSTEMK_SETTING_DEVICE_TYPE, } SystemKSettingID_T; SystemKResult_T SETTINGS_get_uint8_t(SystemKSettingID_T id, uint8_t * value); SystemKResult_T SETTINGS_set_uint8_t(SystemKSettingID_T id, uint8_t value); SystemKResult_T SETTINGS_get_uint32_t(SystemKSettingID_T id, uint32_t * value); SystemKResult_T SETTINGS_set_uint32_t(SystemKSettingID_T id, uint32_t value); +SystemKResult_T SETTINGS_get_device_name(char* name); +SystemKResult_T SETTINGS_set_device_name(char* name); SystemKResult_T SETTINGS_Save(void); #endif // SETTINGS_INTERFACE_H diff --git a/States/Playing/State_Playing.c b/States/Playing/State_Playing.c index 832d2c1..9efedcd 100644 --- a/States/Playing/State_Playing.c +++ b/States/Playing/State_Playing.c @@ -37,7 +37,8 @@ static const int_fast8_t TAG_RSSI_THRESHOLD = -75; static void BLEStatusTimerCallback(TimerHandle_t xTimer) { - BLE_UpdateStatusPacket(); + StateMachineContext_T* context = GetContext(); + BLE_UpdateStatusPacket(context->States.Current_State); } static void GameDurationTimerCallback(TimerHandle_t xTimer) @@ -60,7 +61,7 @@ void Playing_Entry(StateMachineContext_T *context) BLE_RXd_data.neighbors[slot].TimeToLive_in_ms = 0; } - BLE_UpdateStatusPacket(); + BLE_UpdateStatusPacket(context->States.Current_State); if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS) { KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!"); @@ -92,7 +93,8 @@ void Playing_Entry(StateMachineContext_T *context) } // The timer is only needed for timed games. - if (Get_Time_Remaining_in_Game_in_ms() != UINT32_MAX) + if ((Get_Time_Remaining_in_Game_in_ms() != UINT32_MAX) && + (Get_Time_Remaining_in_Game_in_ms() != 0)) { if (GameDurationTimer == NULL) { @@ -129,7 +131,7 @@ void Playing_Exit(StateMachineContext_T *context) { LOG("Exiting the Playing state."); xTimerStop(BLEStatusTimer, portMAX_DELAY); - BLE_UpdateStatusPacket(); + BLE_UpdateStatusPacket(context->States.Next_State); } void HandleBLEStatusPacket(const BLE_StatusPacket_T *const packet) @@ -202,21 +204,25 @@ void HandleBLETagPacket(const BLE_TagPacket_T *const packet) { if (BLE_IsPacketNew(packet->BD_ADDR, BLE_PACKET_TYPE_TAG, packet->event_number)) { + Health_In_Percent = (int16_t)Get_Health(); + if (packet->damage > 0) { - Reduce_Health(packet->damage); + if (Health_In_Percent > 0) + { + Reduce_Health(packet->damage); - ReceivedTagColor = packet->color; + ReceivedTagColor = packet->color; - AudioAction_T audio_action = {.ID = AUDIO_PLAY_TAG_RECEIVED, .Data = (void *)0x00}; - Perform_Audio_Action(&audio_action); + AudioAction_T audio_action = {.ID = AUDIO_PLAY_TAG_RECEIVED, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); - NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_TAG_RECEIVED, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)&ReceivedTagColor}; - xQueueSend(xQueueNeoPixels, &neopixels_action, 0); + NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_TAG_RECEIVED, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)&ReceivedTagColor}; + xQueueSend(xQueueNeoPixels, &neopixels_action, 0); + } } else if (packet->damage < 0) { - Health_In_Percent = (uint8_t)Get_Health(); Health_In_Percent -= packet->damage; if (Health_In_Percent > MAX_HEALTH) { @@ -236,4 +242,6 @@ void HandleBLETagPacket(const BLE_TagPacket_T *const packet) } } } + + BLE_FreePacketBuffer(packet); } diff --git a/States/Playing/State_Playing__Tagged_Out.c b/States/Playing/State_Playing__Tagged_Out.c index 87e445a..007d60c 100644 --- a/States/Playing/State_Playing__Tagged_Out.c +++ b/States/Playing/State_Playing__Tagged_Out.c @@ -51,7 +51,7 @@ static void Playing__Tagged_Out_Entry(StateMachineContext_T * context) NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_TAGGED_OUT, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00}; xQueueSend(xQueueNeoPixels, &neopixels_action, 0); - BLE_UpdateStatusPacket(); + BLE_UpdateStatusPacket(STATE_PLAYING__TAGGED_OUT); Increment_Times_Tagged_Out(); } diff --git a/States/State_Configuring.c b/States/State_Configuring.c index 6c79699..24cf594 100644 --- a/States/State_Configuring.c +++ b/States/State_Configuring.c @@ -52,7 +52,8 @@ static void Configuring_Entry(StateMachineContext_T *context) NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_MENU, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00}; xQueueSend(xQueueNeoPixels, &neopixels_action, 0); - BLE_UpdateStatusPacket(); + BLE_UpdateHelloPacket(); + if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS) { KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!"); @@ -150,6 +151,7 @@ static void Configuring_Do(StateMachineContext_T *context) CurrentMenuItem->OnFocus(true); } } + BLE_UpdateHelloPacket(); break; case KEVENT_TRIGGER_SWITCH_RELEASED: @@ -180,6 +182,8 @@ static void Configuring_Do(StateMachineContext_T *context) { KLOG_WARN(KLOG_TAG, "Failed to increment team!"); } + + BLE_UpdateHelloPacket(); } break; diff --git a/States/State_Initializing.c b/States/State_Initializing.c index 2f52060..14a0d09 100644 --- a/States/State_Initializing.c +++ b/States/State_Initializing.c @@ -44,7 +44,8 @@ const StateActivity_T STATE_INITIALIZING_Activities = */ static void Initializing_Entry(StateMachineContext_T * context) { - LOG("Entering the Initializing state."); + KLOG_INFO("SystemK", "Using SystemK version %s.", SYSTEMK_VERSION_STRING); + NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_TEST_PATTERN, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00}; xQueueSend(xQueueNeoPixels, &neopixels_action, 0); AudioAction_T audio_action = {.ID = AUDIO_PLAY_STARTUP_SOUND, .Play_To_Completion = true, .Data = (void *)0x00}; diff --git a/States/State_Machine.c b/States/State_Machine.c index f3e702b..5f056f9 100644 --- a/States/State_Machine.c +++ b/States/State_Machine.c @@ -22,13 +22,6 @@ /* Include Files */ #include "SystemK.h" -const StateActivity_T STATE_DEFAULT_Activities = -{ - .Entry = NULL, - .Do = NULL, - .Exit = NULL -}; - //! Activities for the top-level state machine. /*! * This array is indexed by #StateID_T (except there is no entry for @@ -37,7 +30,6 @@ const StateActivity_T STATE_DEFAULT_Activities = */ static const StateActivity_T * Activities[] = { - &STATE_DEFAULT_Activities, &STATE_INITIALIZING_Activities, &STATE_REPROGRAMMING_Activities, &STATE_CONFIGURING_Activities, @@ -62,6 +54,11 @@ static StateMachineContext_T Context = .Time_At_State_Entry_In_Ticks = 0, }; +StateMachineContext_T* GetContext() +{ + return &Context; +} + TaskHandle_t State_Machine_Task_Handle; void State_Machine_Task(void * pvParameters) diff --git a/States/State_Machine.h b/States/State_Machine.h index 31d375a..5656daa 100644 --- a/States/State_Machine.h +++ b/States/State_Machine.h @@ -36,22 +36,21 @@ */ typedef enum { - STATE_DEFAULT = 0, - STATE_INITIALIZING = 1, - STATE_REPROGRAMMING = 2, - STATE_CONFIGURING = 3, - STATE_READY = 4, + STATE_INITIALIZING = 0, + STATE_REPROGRAMMING = 1, + STATE_CONFIGURING = 2, + STATE_READY = 3, // Substates of STATE_STARTING_GAME - STATE_STARTING_GAME__INSTIGATING = 5, - STATE_STARTING_GAME__RESPONDING = 6, - STATE_STARTING_GAME__COUNTING_DOWN = 7, + STATE_STARTING_GAME__INSTIGATING = 4, + STATE_STARTING_GAME__RESPONDING = 5, + STATE_STARTING_GAME__COUNTING_DOWN = 6, // Substates of STATE_PLAYING - STATE_PLAYING__INTERACTING = 8, - STATE_PLAYING__TAGGED_OUT = 9, + STATE_PLAYING__INTERACTING = 7, + STATE_PLAYING__TAGGED_OUT = 8, - STATE_WRAPPING_UP = 10, + STATE_WRAPPING_UP = 9, // STATE_IS_OUT_OF_RANGE is one more than the last valid state. STATE_IS_OUT_OF_RANGE, @@ -120,6 +119,8 @@ inline uint32_t GetTimeInState_in_ms(StateMachineContext_T * context) return result; } +StateMachineContext_T* GetContext(); + #include "State_Configuring.h" #include "State_Ready.h" #include "State_Initializing.h" diff --git a/States/State_Ready.c b/States/State_Ready.c index 21b4af4..c58c4bb 100644 --- a/States/State_Ready.c +++ b/States/State_Ready.c @@ -47,7 +47,7 @@ static void Ready_Entry(StateMachineContext_T * context) LOG("Entering the Ready state."); NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_IDLE, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00}; xQueueSend(xQueueNeoPixels, &neopixels_action, 0); - BLE_UpdateStatusPacket(); + BLE_UpdateStatusPacket(STATE_READY); if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS) { KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!"); diff --git a/States/State_Wrapping_Up.c b/States/State_Wrapping_Up.c index 1361f93..af0d07c 100644 --- a/States/State_Wrapping_Up.c +++ b/States/State_Wrapping_Up.c @@ -47,7 +47,7 @@ static void Wrapping_Up_Entry(StateMachineContext_T * context) LOG("Entering the Wrapping Up state."); NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_IDLE, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00}; xQueueSend(xQueueNeoPixels, &neopixels_action, 0); - BLE_UpdateStatusPacket(); + BLE_UpdateStatusPacket(STATE_WRAPPING_UP); if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS) { KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!"); diff --git a/SystemK.h b/SystemK.h index 289cfb1..aeadecb 100755 --- a/SystemK.h +++ b/SystemK.h @@ -70,6 +70,10 @@ #ifndef SYSTEMK_H #define SYSTEMK_H +#define SYSTEMK_MAJOR_VERSION 0 +#define SYSTEMK_MINOR_VERSION 99 +#define SYSTEMK_VERSION_STRING "00.99" + #ifdef ESP_PLATFORM #include "freertos/FreeRTOS.h" #include "freertos/task.h" -- 2.47.2 From 58f379dc1871b06a7cde07e5e2b77e93f5aebaeb Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Sat, 15 Feb 2025 16:13:58 -0600 Subject: [PATCH 02/12] WIP: More new BLE --- BLE/BLE_Packet_Tracker.c | 5 +- BLE/BLE_Packets.c | 47 +++++++++++++++ BLE/BLE_Packets.h | 74 ++++++++++++++++------- BLE/BLE_Utils.c | 52 ++++++++++++++++ BLE/BLE_Utils.h | 22 +++++++ CMakeLists.txt | 1 + Game/Game.h | 12 ++++ States/Playing/State_Playing.c | 4 +- States/State_Configuring.c | 105 +++++++++++++++++++++++++++++++++ SystemK.h | 1 + 10 files changed, 301 insertions(+), 22 deletions(-) create mode 100644 BLE/BLE_Utils.c create mode 100644 BLE/BLE_Utils.h diff --git a/BLE/BLE_Packet_Tracker.c b/BLE/BLE_Packet_Tracker.c index 7f1ff2d..11f698a 100644 --- a/BLE/BLE_Packet_Tracker.c +++ b/BLE/BLE_Packet_Tracker.c @@ -49,11 +49,14 @@ static PacketTracker_T Tracker = .head = 0, }; -// A packet is _new_ if the combination of BLE adress, type, and event number have not been seen recently. +// A packet is _new_ if the combination of BLE address, type, and event number have not been seen recently. bool BLE_IsPacketNew(const uint8_t *sender_BD_ADDR, BLE_PacketType_T packet_type, uint8_t event_number) { + //esp_log_level_set("BLE", ESP_LOG_DEBUG); + //KLOG_DEBUG("BLE", "Packet from %s", BLE_ADDR_To_Str(sender_BD_ADDR)); + // Check if the packet already exists in the tracker. for (int i = 0; i < Tracker.count; i++) { diff --git a/BLE/BLE_Packets.c b/BLE/BLE_Packets.c index 14a548c..dcc2c3f 100644 --- a/BLE/BLE_Packets.c +++ b/BLE/BLE_Packets.c @@ -257,6 +257,53 @@ void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[B } } +void BLE_RespondToConfigurationPacket(const BLE_ConfigurationPacket_T *const packet, BLE_ConfigurationSubtype_T response) +{ + static uint8_t EventNumber = 0; + + Advertising_Data.length = BLE_KTAG_PACKET_TOTAL_SIZE; + + // Manufacturer Specific Data + Advertising_Data.data[0] = 0x1E; + Advertising_Data.data[1] = 0xFF; + Advertising_Data.data[2] = 0xFF; + Advertising_Data.data[3] = 0xFF; + Advertising_Data.data[4] = 'K'; + Advertising_Data.data[5] = 'T'; + Advertising_Data.data[6] = 'a'; + Advertising_Data.data[7] = 'g'; + Advertising_Data.data[8] = BLE_PACKET_TYPE_CONFIGURATION; + Advertising_Data.data[9] = EventNumber++; + Advertising_Data.data[10] = packet->BD_ADDR[0]; + Advertising_Data.data[11] = packet->BD_ADDR[1]; + Advertising_Data.data[12] = packet->BD_ADDR[2]; + Advertising_Data.data[13] = packet->BD_ADDR[3]; + Advertising_Data.data[14] = packet->BD_ADDR[4]; + Advertising_Data.data[15] = packet->BD_ADDR[5]; + Advertising_Data.data[16] = (uint8_t)response; + Advertising_Data.data[17] = (uint8_t)((packet->key_one >> 0) & 0xFF); + Advertising_Data.data[18] = (uint8_t)((packet->key_one >> 8) & 0xFF); + Advertising_Data.data[19] = (uint8_t)((packet->value_one >> 0) & 0xFF); + Advertising_Data.data[20] = (uint8_t)((packet->value_one >> 8) & 0xFF); + Advertising_Data.data[21] = (uint8_t)((packet->value_one >> 16) & 0xFF); + Advertising_Data.data[22] = (uint8_t)((packet->value_one >> 24) & 0xFF); + Advertising_Data.data[23] = (uint8_t)((packet->key_two >> 0) & 0xFF); + Advertising_Data.data[24] = (uint8_t)((packet->key_two >> 8) & 0xFF); + Advertising_Data.data[25] = (uint8_t)((packet->value_two >> 0) & 0xFF); + Advertising_Data.data[26] = (uint8_t)((packet->value_two >> 8) & 0xFF); + Advertising_Data.data[27] = (uint8_t)((packet->value_two >> 16) & 0xFF); + Advertising_Data.data[28] = (uint8_t)((packet->value_two >> 24) & 0xFF); + Advertising_Data.data[29] = 0xFF; + Advertising_Data.data[30] = 0xFF; + + SystemKResult_T result = BLE_SetAdvertisingData(&Advertising_Data); + + if (result != SYSTEMK_RESULT_SUCCESS) + { + KLOG_ERROR(KLOG_TAG, "Error responding to configuration packet!"); + } +} + void BLE_UpdateHelloPacket() { static uint8_t EventNumber = 0; diff --git a/BLE/BLE_Packets.h b/BLE/BLE_Packets.h index d535b46..a849a07 100644 --- a/BLE/BLE_Packets.h +++ b/BLE/BLE_Packets.h @@ -29,7 +29,8 @@ #define BLE_PACKETS_H #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif /* Preprocessor and Type Definitions */ @@ -75,7 +76,7 @@ typedef struct uint8_t BD_ADDR[BD_ADDR_SIZE]; int8_t RSSI; uint8_t event_number; - + uint8_t data[BLE_KTAG_PACKET_DATA_SIZE]; } __attribute__((packed, aligned(1))) BLE_GenericPacketType_T; @@ -86,7 +87,7 @@ typedef struct uint8_t BD_ADDR[BD_ADDR_SIZE]; int8_t RSSI; uint8_t event_number; - + uint32_t game_length_in_ms; uint32_t time_remaining_until_countdown_in_ms; uint8_t unused[13]; @@ -99,7 +100,7 @@ typedef struct uint8_t BD_ADDR[BD_ADDR_SIZE]; int8_t RSSI; uint8_t event_number; - + uint8_t target_BD_ADDR[BD_ADDR_SIZE]; uint32_t event_ID; uint32_t event_data; @@ -122,7 +123,7 @@ typedef struct color_t color; uint8_t target_BD_ADDR[BD_ADDR_SIZE]; uint8_t unused[5]; -} __attribute__((packed, aligned(1)))BLE_TagPacket_T; +} __attribute__((packed, aligned(1))) BLE_TagPacket_T; //! Contents of the BLE packet #BLE_PACKET_TYPE_CONSOLE. typedef struct @@ -131,9 +132,9 @@ typedef struct uint8_t BD_ADDR[BD_ADDR_SIZE]; int8_t RSSI; uint8_t event_number; - + uint8_t console_data[BLE_KTAG_PACKET_DATA_SIZE]; -} __attribute__((packed, aligned(1)))BLE_ConsolePacket_T; +} __attribute__((packed, aligned(1))) BLE_ConsolePacket_T; //! Contents of the BLE packet #BLE_PACKET_TYPE_STATUS. typedef struct @@ -142,7 +143,7 @@ typedef struct uint8_t BD_ADDR[BD_ADDR_SIZE]; int8_t RSSI; uint8_t event_number; - + int8_t tx_power_level; uint8_t protocol; uint8_t team_ID; @@ -153,7 +154,39 @@ typedef struct color_t secondary_color; uint8_t SystemK_top_level_state; // StateID_T uint8_t unused[4]; -} __attribute__((packed, aligned(1)))BLE_StatusPacket_T; +} __attribute__((packed, aligned(1))) BLE_StatusPacket_T; + +typedef enum +{ + BLE_REQUEST_CURRENT_PARAMETER_INFORMATION = 0x00, + BLE_CURRENT_PARAMETER_INFORMATION = 0x01, + BLE_REQUEST_PARAMETER_CHANGE = 0x02, + BLE_ACKNOWLEDGE_PARAMETER_CHANGE = 0x03, + BLE_ERROR_CHANGING_PARAMETERS = 0x04, + BLE_ERROR_RESPONDING_TO_REQUEST = 0xFF +} BLE_ConfigurationSubtype_T; + +typedef enum +{ + BLE_CONFIGURATION_KEY_NONE = 0x0000, + BLE_CONFIGURATION_KEY_TEAM_ID = 0x0001, + BLE_FIRST_VALID_CONFIGURATION_KEY = BLE_CONFIGURATION_KEY_TEAM_ID, + BLE_LAST_VALID_CONFIGURATION_KEY = BLE_CONFIGURATION_KEY_TEAM_ID, + BLE_DEVICE_TYPE_UNUSED = 0xFFFF +} BLE_ConfigurationKey_T; + +inline BLE_ConfigurationKey_T BLE_GetValidConfigKey(uint16_t key) +{ + BLE_ConfigurationKey_T result = BLE_CONFIGURATION_KEY_NONE; + + if ((key >= BLE_FIRST_VALID_CONFIGURATION_KEY) && + (key <= BLE_LAST_VALID_CONFIGURATION_KEY)) + { + result = (BLE_ConfigurationKey_T)key; + } + + return result; +} //! Contents of the BLE packet #BLE_PACKET_TYPE_CONFIGURATION. typedef struct @@ -162,7 +195,7 @@ typedef struct uint8_t BD_ADDR[BD_ADDR_SIZE]; int8_t RSSI; uint8_t event_number; - + uint8_t target_BD_ADDR[BD_ADDR_SIZE]; uint8_t subtype; uint16_t key_one; @@ -170,15 +203,15 @@ typedef struct uint16_t key_two; uint32_t value_two; uint8_t unused[2]; -} __attribute__((packed, aligned(1)))BLE_ConfigurationPacket_T; +} __attribute__((packed, aligned(1))) BLE_ConfigurationPacket_T; typedef enum { BLE_DEVICE_TYPE_LITTLE_BOY_BLUE = 0x0000, - BLE_DEVICE_TYPE_2020TPC = 0x0001, - BLE_DEVICE_TYPE_MOBILE_APP = 0x0002, - BLE_DEVICE_TYPE_32ESPECIAL = 0x0003, - BLE_DEVICE_TYPE_UNKNOWN = 0xFFFF + BLE_DEVICE_TYPE_2020TPC = 0x0001, + BLE_DEVICE_TYPE_MOBILE_APP = 0x0002, + BLE_DEVICE_TYPE_32ESPECIAL = 0x0003, + BLE_DEVICE_TYPE_UNKNOWN = 0xFFFF } BLE_DeviceType_T; //! Contents of the BLE packet #BLE_PACKET_TYPE_HELLO. @@ -188,13 +221,13 @@ typedef struct uint8_t BD_ADDR[BD_ADDR_SIZE]; int8_t RSSI; uint8_t event_number; - + uint8_t SystemK_major_version; uint8_t SystemK_minor_version; uint16_t device_type; uint8_t team_ID; uint8_t device_name[SYSTEMK_MAX_CHARS_IN_DEVICE_NAME]; -} __attribute__((packed, aligned(1)))BLE_HelloPacket_T; +} __attribute__((packed, aligned(1))) BLE_HelloPacket_T; typedef union { @@ -214,20 +247,21 @@ typedef union /* Public Functions */ -inline void BLE_FreePacketBuffer(void * buffer) +inline void BLE_FreePacketBuffer(BLE_GenericPacketType_T *buffer) { if (buffer != NULL) { - ((BLE_GenericPacketType_T *)buffer)->type = BLE_PACKET_TYPE_BUFFER_FREE; + buffer->type = BLE_PACKET_TYPE_BUFFER_FREE; } } void BLE_InitPacketBuffers(void); -BLE_Packet_T * BLE_DecodeKTagPacket(const uint8_t * received_data, uint8_t received_data_length, uint8_t peer_BD_ADDR[BD_ADDR_SIZE], int8_t rssi_in_dBm); +BLE_Packet_T *BLE_DecodeKTagPacket(const uint8_t *received_data, uint8_t received_data_length, uint8_t peer_BD_ADDR[BD_ADDR_SIZE], int8_t rssi_in_dBm); void BLE_UpdateInstigationPacket(uint32_t Game_Length_in_ms, uint32_t Time_Remaining_Until_Countdown_in_ms); void BLE_UpdateStatusPacket(uint8_t current_state); void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[BD_ADDR_SIZE]); +void BLE_RespondToConfigurationPacket(const BLE_ConfigurationPacket_T *const packet, BLE_ConfigurationSubtype_T response); void BLE_UpdateHelloPacket(); bool BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[BD_ADDR_SIZE]); diff --git a/BLE/BLE_Utils.c b/BLE/BLE_Utils.c new file mode 100644 index 0000000..15ec5cd --- /dev/null +++ b/BLE/BLE_Utils.c @@ -0,0 +1,52 @@ +/* + * This program source code file is part of SystemK, a library in the KTag project. + * + * 🛡️ 🃞 + * + * Copyright © 2025 Joseph P. Kearney and the KTag developers. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * There should be a copy of the GNU Affero General Public License in the LICENSE + * file in the root of this repository. If not, see . + */ + +#include +#include +#include + + //! Converts a 6-byte Bluetooth Low Energy address to a human-readable string (for logging). + /*! + * \param bd_addr The Bluetooth address as a 6-byte array + * \return Pointer to a static string containing the formatted address + * + * Output format: "XX:XX:XX:XX:XX:XX" where XX are uppercase hexadecimal values + * \note This function is not reentrant as it uses a static buffer! + */ +const char *BLE_ADDR_To_Str(const uint8_t bd_addr[6]) +{ + static char str_addr[18]; // 17 characters + null terminator + + // Convert each byte and add separating colons. + for (int i = 0; i < 6; i++) + { + snprintf(&str_addr[i * 3], sizeof(str_addr) - (i * 3), "%02X", bd_addr[i]); + + // Add colon separator except after the last byte. + if (i < 5) + { + str_addr[(i * 3) + 2] = ':'; + } + } + + str_addr[17] = '\0'; // Ensure null termination. + return str_addr; +} \ No newline at end of file diff --git a/BLE/BLE_Utils.h b/BLE/BLE_Utils.h new file mode 100644 index 0000000..42cd2b2 --- /dev/null +++ b/BLE/BLE_Utils.h @@ -0,0 +1,22 @@ +/* + * This program source code file is part of SystemK, a library in the KTag project. + * + * 🛡️ 🃞 + * + * Copyright © 2025 Joseph P. Kearney and the KTag developers. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * There should be a copy of the GNU Affero General Public License in the LICENSE + * file in the root of this repository. If not, see . + */ + + const char* BLE_ADDR_To_Str(const uint8_t bd_addr[6]); \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c04f98e..c9e2bb9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ idf_component_register( SRCS "BLE/BLE_Packets.c" "BLE/BLE_Packet_Tracker.c" + "BLE/BLE_Utils.c" "Events/KEvents.c" "Game/Game.c" "Game/Weapons.c" diff --git a/Game/Game.h b/Game/Game.h index a9ca257..0d9fc02 100644 --- a/Game/Game.h +++ b/Game/Game.h @@ -44,6 +44,18 @@ typedef enum MAXIMUM_TEAM_ID = 7 } TeamID_t; +inline bool Is_Valid_Team_ID(uint8_t team_ID) +{ + bool result = false; + + if (team_ID <= MAXIMUM_TEAM_ID) + { + result = true; + } + + return result; +} + __attribute__((always_inline)) static inline SystemKResult_T Set_Team_With_Audio_Feedback(uint8_t team_ID) { static uint8_t Team_ID = 0; // This is static because AUDIO_PRONOUNCE_NUMBER_0_TO_100 needs a *pointer*. diff --git a/States/Playing/State_Playing.c b/States/Playing/State_Playing.c index 9efedcd..a347799 100644 --- a/States/Playing/State_Playing.c +++ b/States/Playing/State_Playing.c @@ -181,6 +181,8 @@ void HandleBLEStatusPacket(const BLE_StatusPacket_T *const packet) // NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_BLE_NEARBY, .Data = (void *)&BLE_RXd_data, .Prominence = NEOPIXELS_BACKGROUND}; // xQueueSend(xQueueNeoPixels, &neopixels_action, 0); + + BLE_FreePacketBuffer((BLE_GenericPacketType_T *)packet); } void HandleBLETagPacket(const BLE_TagPacket_T *const packet) @@ -243,5 +245,5 @@ void HandleBLETagPacket(const BLE_TagPacket_T *const packet) } } - BLE_FreePacketBuffer(packet); + BLE_FreePacketBuffer((BLE_GenericPacketType_T *)packet); } diff --git a/States/State_Configuring.c b/States/State_Configuring.c index 24cf594..a399ec4 100644 --- a/States/State_Configuring.c +++ b/States/State_Configuring.c @@ -26,6 +26,18 @@ static void Configuring_Entry(StateMachineContext_T *context); static void Configuring_Do(StateMachineContext_T *context); static void Configuring_Exit(StateMachineContext_T *context); +static void HandleBLEConfigurationPacket(const BLE_ConfigurationPacket_T *const packet); +static void HandleBLEEventPacket(const BLE_EventPacket_T *const packet); + +static TimerHandle_t BLEConfigurationResponseTimer = NULL; +static StaticTimer_t xBLEConfigurationResponseTimerBuffer; +static TickType_t xBLEConfigurationResponseTimerPeriod = 3000 / portTICK_PERIOD_MS; + +static void BLEConfigurationResponseTimerCallback(TimerHandle_t xTimer) +{ + BLE_UpdateHelloPacket(); +} + #define MAX_MENU_DEPTH 10 static MenuItem_T const *CurrentMenuItem; static uint8_t MenuItemHistoryIndex = 0; @@ -59,6 +71,22 @@ static void Configuring_Entry(StateMachineContext_T *context) KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!"); } + if (BLEConfigurationResponseTimer == NULL) + { + BLEConfigurationResponseTimer = xTimerCreateStatic( + "BLEConfigResponse", + xBLEConfigurationResponseTimerPeriod, + pdTRUE, + (void *)0, + BLEConfigurationResponseTimerCallback, + &xBLEConfigurationResponseTimerBuffer); + } + + if (BLEConfigurationResponseTimer == NULL) + { + KLOG_ERROR(KLOG_TAG, "Couldn't create the BLEConfigurationResponseTimer!"); + } + // Reset the menu. CurrentMenuItem = RootMenu; MenuItemHistory[MenuItemHistoryIndex] = CurrentMenuItem; @@ -195,6 +223,19 @@ static void Configuring_Do(StateMachineContext_T *context) Transition_For_Event(context, STATE_REPROGRAMMING, &Event); break; + case KEVENT_BLE_PACKET_RECEIVED: + if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_CONFIGURATION) + { + HandleBLEConfigurationPacket((BLE_ConfigurationPacket_T *)Event.Data); + } + else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) + { + HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data); + } + + BLE_FreePacketBuffer(Event.Data); + break; + default: // All other events are ignored in this state. ProcessUnhandledEvent(&Event); @@ -218,3 +259,67 @@ static void Configuring_Exit(StateMachineContext_T *context) NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_ALL_OFF, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00}; xQueueSend(xQueueNeoPixels, &neopixels_action, 0); } + +static SystemKResult_T HandleParameterChangeRequest(BLE_ConfigurationKey_T key, uint32_t value) +{ + SystemKResult_T result = SYSTEMK_RESULT_UNSPECIFIED_FAILURE; + + if (key == BLE_CONFIGURATION_KEY_TEAM_ID) + { + uint8_t team_ID = (uint8_t)value; + if (Is_Valid_Team_ID(team_ID)) + { + result = Set_Team_With_Audio_Feedback(team_ID); + } + } + + return result; +} + +void HandleBLEConfigurationPacket(const BLE_ConfigurationPacket_T *const packet) +{ + if (BLE_IsBLEPacketForMe(packet->target_BD_ADDR)) + { + if (BLE_IsPacketNew(packet->BD_ADDR, BLE_PACKET_TYPE_CONFIGURATION, packet->event_number)) + { + if (packet->subtype == BLE_REQUEST_PARAMETER_CHANGE) + { + SystemKResult_T result = SYSTEMK_RESULT_SUCCESS; + + BLE_ConfigurationKey_T key_one = BLE_GetValidConfigKey(packet->key_one); + if (key_one != BLE_CONFIGURATION_KEY_NONE) + { + result = HandleParameterChangeRequest(key_one, packet->value_one); + } + + if (result == SYSTEMK_RESULT_SUCCESS) + { + BLE_ConfigurationKey_T key_two = BLE_GetValidConfigKey(packet->key_two); + if (key_two != BLE_CONFIGURATION_KEY_NONE) + { + result = HandleParameterChangeRequest(key_two, packet->value_two); + } + } + + if (result == SYSTEMK_RESULT_SUCCESS) + { + BLE_RespondToConfigurationPacket(packet, BLE_ACKNOWLEDGE_PARAMETER_CHANGE); + } + else + { + KLOG_ERROR(KLOG_TAG, "Error changing parameter(s)!"); + BLE_RespondToConfigurationPacket(packet, BLE_ERROR_CHANGING_PARAMETERS); + } + + if (xTimerStart(BLEConfigurationResponseTimer, 0) != pdPASS) + { + KLOG_ERROR(KLOG_TAG, "Couldn't start the BLEConfigurationResponseTimer!"); + } + } + } + } +} + +static void HandleBLEEventPacket(const BLE_EventPacket_T *const packet) +{ +} diff --git a/SystemK.h b/SystemK.h index aeadecb..2ff8590 100755 --- a/SystemK.h +++ b/SystemK.h @@ -103,6 +103,7 @@ #include "BLE/BLE_Packets.h" #include "BLE/BLE_Packet_Tracker.h" #include "BLE/BLE_HW_Interface.h" +#include "BLE/BLE_Utils.h" #include "IR/IR_HW_Interface.h" #include "States/State_Machine.h" #include "Menu/Menu.h" -- 2.47.2 From 82ec410264cd43e5dbd1778a1dc51ebf36f2f0b5 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Sat, 15 Feb 2025 19:58:52 -0600 Subject: [PATCH 03/12] Added BLE events --- BLE/BLE_Packets.h | 10 +++ BLE/BLE_Utils.c | 2 +- Events/KEvents.h | 2 + States/Playing/State_Playing__Interacting.c | 21 +++---- States/Playing/State_Playing__Tagged_Out.c | 6 +- States/State_Configuring.c | 19 +++--- States/State_Machine.c | 67 +++++++++++++++++++++ States/State_Machine.h | 1 + States/State_Ready.c | 6 ++ States/State_Wrapping_Up.c | 10 ++- 10 files changed, 121 insertions(+), 23 deletions(-) diff --git a/BLE/BLE_Packets.h b/BLE/BLE_Packets.h index a849a07..4d140b3 100644 --- a/BLE/BLE_Packets.h +++ b/BLE/BLE_Packets.h @@ -93,6 +93,16 @@ typedef struct uint8_t unused[13]; } __attribute__((packed, aligned(1))) BLE_InstigationPacket_T; +typedef enum +{ + BLE_EVENT_NO_EVENT = 0, + BLE_EVENT_CONFIGURE = 1, + BLE_EVENT_CONFIGURED = 2, + BLE_EVENT_WRAPUP_COMPLETE = 3, + BLE_EVENT_GAME_OVER = 4, + BLE_EVENT_UNUSED = 0xFFFFFFFF +} BLE_EventID_T; + //! Contents of the BLE packet #BLE_PACKET_TYPE_EVENT. typedef struct { diff --git a/BLE/BLE_Utils.c b/BLE/BLE_Utils.c index 15ec5cd..1a05031 100644 --- a/BLE/BLE_Utils.c +++ b/BLE/BLE_Utils.c @@ -38,7 +38,7 @@ const char *BLE_ADDR_To_Str(const uint8_t bd_addr[6]) // Convert each byte and add separating colons. for (int i = 0; i < 6; i++) { - snprintf(&str_addr[i * 3], sizeof(str_addr) - (i * 3), "%02X", bd_addr[i]); + snprintf(&str_addr[i * 3], sizeof(str_addr) - (i * 3), "%02X", bd_addr[5-i]); // Add colon separator except after the last byte. if (i < 5) diff --git a/Events/KEvents.h b/Events/KEvents.h index a992606..027a733 100755 --- a/Events/KEvents.h +++ b/Events/KEvents.h @@ -79,6 +79,8 @@ typedef enum KEVENT_AUDIO_COMPLETED = 36, KEVENT_GAME_OVER = 37, KEVENT_PLAY_PRESSED_ON_REMOTE = 38, + //! For #KEVENT_BLE_EVENT_RECEIVED, #KEvent_T::Data contains the BLE_EventID_T of the received event. + KEVENT_BLE_EVENT_RECEIVED = 39, // KEVENT_IS_OUT_OF_RANGE is one more than the last valid event. KEVENT_IS_OUT_OF_RANGE } KEvent_ID_T; diff --git a/States/Playing/State_Playing__Interacting.c b/States/Playing/State_Playing__Interacting.c index f8d968f..8adc07e 100644 --- a/States/Playing/State_Playing__Interacting.c +++ b/States/Playing/State_Playing__Interacting.c @@ -344,14 +344,7 @@ static void Playing__Interacting_Do(StateMachineContext_T * context) case KEVENT_BLE_PACKET_RECEIVED: #ifdef LOG_INTERACTING_SUBSTATE - //KLOG_INFO(KLOG_TAG, "KEVENT_BLE_PACKET_RECEIVED from %02X:%02X:%02X:%02X:%02X:%02X", - // ((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR[5], - // ((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR[4], - // ((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR[3], - // ((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR[2], - // ((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR[1], - // ((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR[0] - //); + KLOG_INFO(KLOG_TAG, "KEVENT_BLE_PACKET_RECEIVED from %s", BLE_ADDR_To_Str(((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR)); #endif // LOG_INTERACTING_SUBSTATE if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_STATUS) { @@ -361,8 +354,14 @@ static void Playing__Interacting_Do(StateMachineContext_T * context) { HandleBLETagPacket((BLE_TagPacket_T *)Event.Data); } - - BLE_FreePacketBuffer(Event.Data); + else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) + { + HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data, context); + } + else + { + BLE_FreePacketBuffer(Event.Data); + } break; case KEVENT_ACCESSORY_SWITCH_PRESSED: @@ -398,7 +397,7 @@ static void Playing__Interacting_Do(StateMachineContext_T * context) case KEVENT_GAME_OVER: { - AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_OVER, .Data = (void *)0x00}; + AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_OVER, .Play_To_Completion = true}; Perform_Audio_Action(&audio_action); Transition_For_Event(context, STATE_WRAPPING_UP, &Event); } diff --git a/States/Playing/State_Playing__Tagged_Out.c b/States/Playing/State_Playing__Tagged_Out.c index 007d60c..3bbd22a 100644 --- a/States/Playing/State_Playing__Tagged_Out.c +++ b/States/Playing/State_Playing__Tagged_Out.c @@ -83,6 +83,10 @@ static void Playing__Tagged_Out_Do(StateMachineContext_T * context) Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event); } } + else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) + { + HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data, context); + } else { BLE_FreePacketBuffer(Event.Data); @@ -107,7 +111,7 @@ static void Playing__Tagged_Out_Do(StateMachineContext_T * context) case KEVENT_GAME_OVER: { - AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_OVER, .Data = (void *)0x00}; + AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_OVER, .Play_To_Completion = true}; Perform_Audio_Action(&audio_action); Transition_For_Event(context, STATE_WRAPPING_UP, &Event); } diff --git a/States/State_Configuring.c b/States/State_Configuring.c index a399ec4..02074da 100644 --- a/States/State_Configuring.c +++ b/States/State_Configuring.c @@ -27,7 +27,6 @@ static void Configuring_Do(StateMachineContext_T *context); static void Configuring_Exit(StateMachineContext_T *context); static void HandleBLEConfigurationPacket(const BLE_ConfigurationPacket_T *const packet); -static void HandleBLEEventPacket(const BLE_EventPacket_T *const packet); static TimerHandle_t BLEConfigurationResponseTimer = NULL; static StaticTimer_t xBLEConfigurationResponseTimerBuffer; @@ -64,6 +63,12 @@ static void Configuring_Entry(StateMachineContext_T *context) NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_MENU, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00}; xQueueSend(xQueueNeoPixels, &neopixels_action, 0); + if (context->Cause_Of_Transition->ID == KEVENT_BLE_EVENT_RECEIVED) + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_BEEP, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + } + BLE_UpdateHelloPacket(); if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS) @@ -230,10 +235,12 @@ static void Configuring_Do(StateMachineContext_T *context) } else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) { - HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data); + HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data, context); + } + else + { + BLE_FreePacketBuffer(Event.Data); } - - BLE_FreePacketBuffer(Event.Data); break; default: @@ -319,7 +326,3 @@ void HandleBLEConfigurationPacket(const BLE_ConfigurationPacket_T *const packet) } } } - -static void HandleBLEEventPacket(const BLE_EventPacket_T *const packet) -{ -} diff --git a/States/State_Machine.c b/States/State_Machine.c index 5f056f9..7bb4151 100644 --- a/States/State_Machine.c +++ b/States/State_Machine.c @@ -128,3 +128,70 @@ void ProcessUnhandledEvent(KEvent_T * Event) break; } } + +void HandleBLEEventPacket(const BLE_EventPacket_T *const packet, StateMachineContext_T *context) +{ + if (BLE_IsBLEPacketForMe(packet->target_BD_ADDR)) + { + if (BLE_IsPacketNew(packet->BD_ADDR, BLE_PACKET_TYPE_EVENT, packet->event_number)) + { + if (packet->event_ID == BLE_EVENT_CONFIGURED) + { + if (context->States.Current_State == STATE_CONFIGURING) + { + static KEvent_T Event = + { + .ID = KEVENT_BLE_EVENT_RECEIVED, + .Data = (void *)BLE_EVENT_CONFIGURED + }; + Transition_For_Event(context, STATE_READY, &Event); + } + } + else if (packet->event_ID == BLE_EVENT_CONFIGURE) + { + if (context->States.Current_State == STATE_READY) + { + static KEvent_T Event = + { + .ID = KEVENT_BLE_EVENT_RECEIVED, + .Data = (void *)BLE_EVENT_CONFIGURE + }; + Transition_For_Event(context, STATE_CONFIGURING, &Event); + } + } + else if (packet->event_ID == BLE_EVENT_WRAPUP_COMPLETE) + { + if (context->States.Current_State == STATE_WRAPPING_UP) + { + StateID_T next_state = (StateID_T)packet->event_data; + + if (next_state < STATE_IS_OUT_OF_RANGE) + { + static KEvent_T Event = + { + .ID = KEVENT_BLE_EVENT_RECEIVED, + .Data = (void *)BLE_EVENT_WRAPUP_COMPLETE + }; + Transition_For_Event(context, next_state, &Event); + } + else + { + KLOG_WARN("STATE", "Received a BLE Wrapup Complete event with an invalid Next State!"); + } + } + } + else if (packet->event_ID == BLE_EVENT_GAME_OVER) + { + if ((context->States.Current_State == STATE_PLAYING__INTERACTING) || + (context->States.Current_State == STATE_PLAYING__TAGGED_OUT)) + { + KEvent_T game_over_event = { .ID = KEVENT_GAME_OVER, .Data = (void *)0x00 }; + Post_KEvent(&game_over_event); + } + } + } + } + + BLE_FreePacketBuffer((BLE_GenericPacketType_T *)packet); +} + diff --git a/States/State_Machine.h b/States/State_Machine.h index 5656daa..981986e 100644 --- a/States/State_Machine.h +++ b/States/State_Machine.h @@ -106,6 +106,7 @@ extern TaskHandle_t State_Machine_Task_Handle; void State_Machine_Task(void * pvParameters); void ProcessUnhandledEvent(KEvent_T * Event); +void HandleBLEEventPacket(const BLE_EventPacket_T *const packet, StateMachineContext_T *context); inline void Transition_For_Event(StateMachineContext_T* context, StateID_T next_state, KEvent_T* event) { diff --git a/States/State_Ready.c b/States/State_Ready.c index c58c4bb..e5be80d 100644 --- a/States/State_Ready.c +++ b/States/State_Ready.c @@ -54,6 +54,8 @@ static void Ready_Entry(StateMachineContext_T * context) } AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_ON, .Data = (void *)0x00}; Perform_Audio_Action(&audio_action); + + Set_Health(MAX_HEALTH); } //! Executes the Ready state. @@ -90,6 +92,10 @@ static void Ready_Do(StateMachineContext_T * context) { Transition_For_Event(context, STATE_STARTING_GAME__RESPONDING, &Event); } + else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) + { + HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data, context); + } else { BLE_FreePacketBuffer(Event.Data); diff --git a/States/State_Wrapping_Up.c b/States/State_Wrapping_Up.c index af0d07c..81273bf 100644 --- a/States/State_Wrapping_Up.c +++ b/States/State_Wrapping_Up.c @@ -84,8 +84,14 @@ static void Wrapping_Up_Do(StateMachineContext_T * context) break; case KEVENT_BLE_PACKET_RECEIVED: - // TODO - BLE_FreePacketBuffer(Event.Data); + if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) + { + HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data, context); + } + else + { + BLE_FreePacketBuffer(Event.Data); + } break; default: -- 2.47.2 From 908bdbba3589bd5efdb37c2519c3ec5855e0a9d8 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Mon, 24 Feb 2025 19:54:37 -0600 Subject: [PATCH 04/12] Updated BLE to spec. version 0.11 --- BLE/BLE_Packets.c | 4 +-- BLE/BLE_Packets.h | 51 +++++++++++++++++++++++++++----------- Game/Game.h | 21 ++++++++++++++++ States/State_Configuring.c | 27 ++++++++++++-------- 4 files changed, 76 insertions(+), 27 deletions(-) diff --git a/BLE/BLE_Packets.c b/BLE/BLE_Packets.c index dcc2c3f..3e97084 100644 --- a/BLE/BLE_Packets.c +++ b/BLE/BLE_Packets.c @@ -257,7 +257,7 @@ void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[B } } -void BLE_RespondToConfigurationPacket(const BLE_ConfigurationPacket_T *const packet, BLE_ConfigurationSubtype_T response) +void BLE_RespondToConfigurationPacket(const BLE_ParametersPacket_T *const packet, BLE_ConfigurationSubtype_T response) { static uint8_t EventNumber = 0; @@ -272,7 +272,7 @@ void BLE_RespondToConfigurationPacket(const BLE_ConfigurationPacket_T *const pac Advertising_Data.data[5] = 'T'; Advertising_Data.data[6] = 'a'; Advertising_Data.data[7] = 'g'; - Advertising_Data.data[8] = BLE_PACKET_TYPE_CONFIGURATION; + Advertising_Data.data[8] = BLE_PACKET_TYPE_PARAMETERS; Advertising_Data.data[9] = EventNumber++; Advertising_Data.data[10] = packet->BD_ADDR[0]; Advertising_Data.data[11] = packet->BD_ADDR[1]; diff --git a/BLE/BLE_Packets.h b/BLE/BLE_Packets.h index 4d140b3..65744c6 100644 --- a/BLE/BLE_Packets.h +++ b/BLE/BLE_Packets.h @@ -64,7 +64,7 @@ typedef enum BLE_PACKET_TYPE_TAG = 3, BLE_PACKET_TYPE_CONSOLE = 4, BLE_PACKET_TYPE_STATUS = 5, - BLE_PACKET_TYPE_CONFIGURATION = 6, + BLE_PACKET_TYPE_PARAMETERS = 6, BLE_PACKET_TYPE_HELLO = 7, BLE_LAST_VALID_PACKET_TYPE = BLE_PACKET_TYPE_HELLO, BLE_PACKET_TYPE_UNKNOWN @@ -178,27 +178,50 @@ typedef enum typedef enum { - BLE_CONFIGURATION_KEY_NONE = 0x0000, - BLE_CONFIGURATION_KEY_TEAM_ID = 0x0001, - BLE_FIRST_VALID_CONFIGURATION_KEY = BLE_CONFIGURATION_KEY_TEAM_ID, - BLE_LAST_VALID_CONFIGURATION_KEY = BLE_CONFIGURATION_KEY_TEAM_ID, - BLE_DEVICE_TYPE_UNUSED = 0xFFFF -} BLE_ConfigurationKey_T; + BLE_PARAMETER_KEY_NONE = 0, + BLE_PARAMETER_KEY_TEAM_ID = 1, + BLE_PARAMETER_KEY_PLAYER_ID = 2, + BLE_PARAMETER_KEY_GAME_LENGTH = 3, + BLE_PARAMETER_KEY_MAX_HEALTH = 4, + BLE_PARAMETER_KEY_SECONDARY_COLOR = 5, + BLE_PARAMETER_KEY_SPECIAL_WEAPONS_ON_REENTRY = 6, + BLE_FIRST_VALID_CONFIGURATION_KEY = BLE_PARAMETER_KEY_TEAM_ID, + BLE_LAST_VALID_CONFIGURATION_KEY = BLE_PARAMETER_KEY_SPECIAL_WEAPONS_ON_REENTRY, + BLE_PARAMETER_KEY_SHOTS_FIRED_THIS_GAME = 10001, + BLE_PARAMETER_KEY_TAGS_RECEIVED_THIS_GAME = 10002, + BLE_PARAMETER_KEY_TIMES_TAGGED_OUT_THIS_GAME = 10003, + BLE_FIRST_VALID_GAME_RESULT_KEY = BLE_PARAMETER_KEY_SHOTS_FIRED_THIS_GAME, + BLE_LAST_VALID_GAME_RESULT_KEY = BLE_PARAMETER_KEY_TIMES_TAGGED_OUT_THIS_GAME, + BLE_PARAMETER_KEY_UNUSED = 65535 +} BLE_ParameterKey_T; -inline BLE_ConfigurationKey_T BLE_GetValidConfigKey(uint16_t key) +inline BLE_ParameterKey_T BLE_GetValidConfigKey(uint16_t key) { - BLE_ConfigurationKey_T result = BLE_CONFIGURATION_KEY_NONE; + BLE_ParameterKey_T result = BLE_PARAMETER_KEY_NONE; if ((key >= BLE_FIRST_VALID_CONFIGURATION_KEY) && (key <= BLE_LAST_VALID_CONFIGURATION_KEY)) { - result = (BLE_ConfigurationKey_T)key; + result = (BLE_ParameterKey_T)key; } return result; } -//! Contents of the BLE packet #BLE_PACKET_TYPE_CONFIGURATION. +inline BLE_ParameterKey_T BLE_GetValidGameResultKey(uint16_t key) +{ + BLE_ParameterKey_T result = BLE_PARAMETER_KEY_NONE; + + if ((key >= BLE_FIRST_VALID_GAME_RESULT_KEY) && + (key <= BLE_LAST_VALID_GAME_RESULT_KEY)) + { + result = (BLE_ParameterKey_T)key; + } + + return result; +} + +//! Contents of the BLE packet #BLE_PACKET_TYPE_PARAMETERS. typedef struct { BLE_PacketType_T type; @@ -213,7 +236,7 @@ typedef struct uint16_t key_two; uint32_t value_two; uint8_t unused[2]; -} __attribute__((packed, aligned(1))) BLE_ConfigurationPacket_T; +} __attribute__((packed, aligned(1))) BLE_ParametersPacket_T; typedef enum { @@ -247,7 +270,7 @@ typedef union BLE_TagPacket_T Tag; BLE_ConsolePacket_T Console; BLE_StatusPacket_T Status; - BLE_ConfigurationPacket_T Configuration; + BLE_ParametersPacket_T Configuration; BLE_HelloPacket_T Hello; } BLE_Packet_T; @@ -271,7 +294,7 @@ BLE_Packet_T *BLE_DecodeKTagPacket(const uint8_t *received_data, uint8_t receive void BLE_UpdateInstigationPacket(uint32_t Game_Length_in_ms, uint32_t Time_Remaining_Until_Countdown_in_ms); void BLE_UpdateStatusPacket(uint8_t current_state); void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[BD_ADDR_SIZE]); -void BLE_RespondToConfigurationPacket(const BLE_ConfigurationPacket_T *const packet, BLE_ConfigurationSubtype_T response); +void BLE_RespondToConfigurationPacket(const BLE_ParametersPacket_T *const packet, BLE_ConfigurationSubtype_T response); void BLE_UpdateHelloPacket(); bool BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[BD_ADDR_SIZE]); diff --git a/Game/Game.h b/Game/Game.h index 0d9fc02..fbbeadc 100644 --- a/Game/Game.h +++ b/Game/Game.h @@ -89,6 +89,27 @@ __attribute__((always_inline)) inline TeamID_t Resolve_Common_Team_ID(uint8_t te return (team_ID & COMMON_TEAM_ID_MASK); } +__attribute__((always_inline)) static inline SystemKResult_T Set_Player_With_Audio_Feedback(uint8_t player_ID) +{ + static uint8_t Player_ID = 0; // This is static because AUDIO_PRONOUNCE_NUMBER_0_TO_100 needs a *pointer*. + SystemKResult_T result = SYSTEMK_RESULT_SUCCESS; + + Player_ID = player_ID; + + result = SETTINGS_set_uint8_t(SYSTEMK_SETTING_PLAYERID, Player_ID); + + if (result == SYSTEMK_RESULT_SUCCESS) + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_PLAYER_ID_PROMPT, .Play_To_Completion = true, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + + AudioAction_T volume_action = {.ID = AUDIO_PRONOUNCE_NUMBER_0_TO_100, .Play_To_Completion = true, .Data = (void *)&Player_ID}; + Perform_Audio_Action(&volume_action); + } + + return result; +} + __attribute__((always_inline)) inline bool Team_Can_Tag_Me(uint8_t tagging_team_ID) { bool can_tag = false; diff --git a/States/State_Configuring.c b/States/State_Configuring.c index 02074da..4008858 100644 --- a/States/State_Configuring.c +++ b/States/State_Configuring.c @@ -26,7 +26,7 @@ static void Configuring_Entry(StateMachineContext_T *context); static void Configuring_Do(StateMachineContext_T *context); static void Configuring_Exit(StateMachineContext_T *context); -static void HandleBLEConfigurationPacket(const BLE_ConfigurationPacket_T *const packet); +static void HandleBLEConfigurationPacket(const BLE_ParametersPacket_T *const packet); static TimerHandle_t BLEConfigurationResponseTimer = NULL; static StaticTimer_t xBLEConfigurationResponseTimerBuffer; @@ -229,9 +229,9 @@ static void Configuring_Do(StateMachineContext_T *context) break; case KEVENT_BLE_PACKET_RECEIVED: - if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_CONFIGURATION) + if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_PARAMETERS) { - HandleBLEConfigurationPacket((BLE_ConfigurationPacket_T *)Event.Data); + HandleBLEConfigurationPacket((BLE_ParametersPacket_T *)Event.Data); } else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) { @@ -267,11 +267,11 @@ static void Configuring_Exit(StateMachineContext_T *context) xQueueSend(xQueueNeoPixels, &neopixels_action, 0); } -static SystemKResult_T HandleParameterChangeRequest(BLE_ConfigurationKey_T key, uint32_t value) +static SystemKResult_T HandleParameterChangeRequest(BLE_ParameterKey_T key, uint32_t value) { SystemKResult_T result = SYSTEMK_RESULT_UNSPECIFIED_FAILURE; - if (key == BLE_CONFIGURATION_KEY_TEAM_ID) + if (key == BLE_PARAMETER_KEY_TEAM_ID) { uint8_t team_ID = (uint8_t)value; if (Is_Valid_Team_ID(team_ID)) @@ -279,30 +279,35 @@ static SystemKResult_T HandleParameterChangeRequest(BLE_ConfigurationKey_T key, result = Set_Team_With_Audio_Feedback(team_ID); } } + else if (key == BLE_PARAMETER_KEY_PLAYER_ID) + { + uint8_t player_ID = (uint8_t)value; + result = Set_Player_With_Audio_Feedback(player_ID); + } return result; } -void HandleBLEConfigurationPacket(const BLE_ConfigurationPacket_T *const packet) +void HandleBLEConfigurationPacket(const BLE_ParametersPacket_T *const packet) { if (BLE_IsBLEPacketForMe(packet->target_BD_ADDR)) { - if (BLE_IsPacketNew(packet->BD_ADDR, BLE_PACKET_TYPE_CONFIGURATION, packet->event_number)) + if (BLE_IsPacketNew(packet->BD_ADDR, BLE_PACKET_TYPE_PARAMETERS, packet->event_number)) { if (packet->subtype == BLE_REQUEST_PARAMETER_CHANGE) { SystemKResult_T result = SYSTEMK_RESULT_SUCCESS; - BLE_ConfigurationKey_T key_one = BLE_GetValidConfigKey(packet->key_one); - if (key_one != BLE_CONFIGURATION_KEY_NONE) + BLE_ParameterKey_T key_one = BLE_GetValidConfigKey(packet->key_one); + if (key_one != BLE_PARAMETER_KEY_NONE) { result = HandleParameterChangeRequest(key_one, packet->value_one); } if (result == SYSTEMK_RESULT_SUCCESS) { - BLE_ConfigurationKey_T key_two = BLE_GetValidConfigKey(packet->key_two); - if (key_two != BLE_CONFIGURATION_KEY_NONE) + BLE_ParameterKey_T key_two = BLE_GetValidConfigKey(packet->key_two); + if (key_two != BLE_PARAMETER_KEY_NONE) { result = HandleParameterChangeRequest(key_two, packet->value_two); } -- 2.47.2 From 47822bbdec20eda1a4c21871c7b4fe17c36bb731 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Sat, 1 Mar 2025 06:09:51 -0600 Subject: [PATCH 05/12] Many new settings to support the new state machine functionality. --- BLE/BLE_Packets.c | 2 +- Game/Game.c | 3 +- Game/Game.h | 33 +++++++++++++++++-- Settings/Settings_Interface.h | 8 +++-- States/Playing/State_Playing.c | 6 ++-- States/Playing/State_Playing__Tagged_Out.c | 29 +++++++++++----- .../State_Starting_Game__Counting_Down.c | 15 +++++++-- .../State_Starting_Game__Instigating.c | 4 +++ .../State_Starting_Game__Responding.c | 1 + States/State_Configuring.c | 2 ++ States/State_Ready.c | 2 +- 11 files changed, 84 insertions(+), 21 deletions(-) diff --git a/BLE/BLE_Packets.c b/BLE/BLE_Packets.c index 3e97084..578bfce 100644 --- a/BLE/BLE_Packets.c +++ b/BLE/BLE_Packets.c @@ -180,7 +180,7 @@ void BLE_UpdateStatusPacket(uint8_t current_state) Advertising_Data.data[13] = player_ID; Advertising_Data.data[14] = Get_Health(); Advertising_Data.data[15] = 0x00; - Advertising_Data.data[16] = MAX_HEALTH; + Advertising_Data.data[16] = Get_Max_Health(); Advertising_Data.data[17] = 0x00; Advertising_Data.data[18] = (Team_Color >> 0) & 0xFF; Advertising_Data.data[19] = (Team_Color >> 8) & 0xFF; diff --git a/Game/Game.c b/Game/Game.c index 8fa8744..3ba634f 100644 --- a/Game/Game.c +++ b/Game/Game.c @@ -23,7 +23,8 @@ KTag_Game_Data_T KTAG_Game_Data = { - .My_Health = MAX_HEALTH, + .My_Health = 0, + .Max_Health = 0, .My_Weapon = TEST_PATTERN_ID, .My_Shield_Strength = 100, .Time_Remaining_in_Game_in_ms = UINT32_MAX, diff --git a/Game/Game.h b/Game/Game.h index fbbeadc..fabef8d 100644 --- a/Game/Game.h +++ b/Game/Game.h @@ -24,8 +24,6 @@ #include "Weapons.h" -#define MAX_HEALTH 10 - //! Implemented according to the 2024-07-20 "KTag Teams Compatibility Matrix". typedef enum { @@ -137,6 +135,7 @@ typedef struct uint8_t My_Health; WeaponID_t My_Weapon; uint8_t My_Shield_Strength; + uint8_t Max_Health; uint32_t Time_Remaining_in_Game_in_ms; uint32_t Time_Remaining_Until_Countdown_in_ms; uint16_t Shots_Fired; @@ -163,6 +162,36 @@ __attribute__((always_inline)) inline void Set_Health(uint8_t health) } } +__attribute__((always_inline)) inline uint8_t Get_Max_Health() +{ + if (KTAG_Game_Data.Max_Health == 0) + { + // Initialize from settings. + uint8_t max_health; + if (SETTINGS_get_uint8_t(SYSTEMK_SETTING_MAX_HEALTH, &max_health) == SYSTEMK_RESULT_SUCCESS) + { + KTAG_Game_Data.Max_Health = max_health; + } + else + { + KTAG_Game_Data.Max_Health = 100; + } + } + + return KTAG_Game_Data.Max_Health; +} + +__attribute__((always_inline)) inline void Set_Max_Health(uint8_t health) +{ + KTAG_Game_Data.Max_Health = health; + + // Limit current health to max health. + if (KTAG_Game_Data.My_Health > health) + { + KTAG_Game_Data.My_Health = health; + } +} + __attribute__((always_inline)) inline void Reduce_Health(uint8_t reduction) { if (reduction < KTAG_Game_Data.My_Health) diff --git a/Settings/Settings_Interface.h b/Settings/Settings_Interface.h index 5074030..e5fa376 100644 --- a/Settings/Settings_Interface.h +++ b/Settings/Settings_Interface.h @@ -22,17 +22,21 @@ #ifndef SETTINGS_INTERFACE_H #define SETTINGS_INTERFACE_H -#define SYSTEMK_MAX_CHARS_IN_DEVICE_NAME 15 +#define SYSTEMK_MAX_CHARS_IN_DEVICE_NAME 16 typedef enum { + SYSTEMK_SETTING_DEVICE_TYPE, SYSTEMK_SETTING_IS_RIGHT_HANDED, SYSTEMK_SETTING_AUDIO_VOLUME, SYSTEMK_SETTING_TEAMID, SYSTEMK_SETTING_PLAYERID, SYSTEMK_SETTING_WEAPONID, + SYSTEMK_SETTING_MAX_HEALTH, + SYSTEMK_SETTING_N_SPECIAL_WEAPONS_ON_REENTRY, SYSTEMK_SETTING_T_START_GAME_in_ms, - SYSTEMK_SETTING_DEVICE_TYPE, + SYSTEMK_SETTING_T_GAME_LENGTH_in_ms, + SYSTEMK_SETTING_SECONDARY_COLOR } SystemKSettingID_T; SystemKResult_T SETTINGS_get_uint8_t(SystemKSettingID_T id, uint8_t * value); diff --git a/States/Playing/State_Playing.c b/States/Playing/State_Playing.c index a347799..b65b99f 100644 --- a/States/Playing/State_Playing.c +++ b/States/Playing/State_Playing.c @@ -226,13 +226,11 @@ void HandleBLETagPacket(const BLE_TagPacket_T *const packet) else if (packet->damage < 0) { Health_In_Percent -= packet->damage; - if (Health_In_Percent > MAX_HEALTH) + if (Health_In_Percent > Get_Max_Health()) { - Health_In_Percent = MAX_HEALTH; + Health_In_Percent = Get_Max_Health(); } - Health_In_Percent = MAX_HEALTH; - Set_Health(Health_In_Percent); AudioAction_T audio_action = {.ID = AUDIO_PRONOUNCE_NUMBER_0_TO_100, .Play_To_Completion = true, .Data = (void *)&Health_In_Percent}; Perform_Audio_Action(&audio_action); diff --git a/States/Playing/State_Playing__Tagged_Out.c b/States/Playing/State_Playing__Tagged_Out.c index 3bbd22a..7ab9cd6 100644 --- a/States/Playing/State_Playing__Tagged_Out.c +++ b/States/Playing/State_Playing__Tagged_Out.c @@ -22,6 +22,22 @@ /* Include Files */ #include "SystemK.h" +static const char *KLOG_TAG = "STATE_PLAYING__TAGGED_OUT"; + +static void Reset_Bombs() +{ + uint8_t n_bombs; + if (SETTINGS_get_uint8_t(SYSTEMK_SETTING_N_SPECIAL_WEAPONS_ON_REENTRY, &n_bombs) == SYSTEMK_RESULT_SUCCESS) + { + Set_Available_Bombs(n_bombs); + } + else + { + Set_Available_Bombs(0); + KLOG_ERROR(KLOG_TAG, "Error getting available bombs!"); + } +} + static void Playing__Tagged_Out_Entry(StateMachineContext_T * context); static void Playing__Tagged_Out_Do(StateMachineContext_T * context); static void Playing__Tagged_Out_Exit(StateMachineContext_T * context); @@ -78,8 +94,7 @@ static void Playing__Tagged_Out_Do(StateMachineContext_T * context) if (Back_In() == true) { - // TODO: Get this from settings. - Set_Available_Bombs(1); + Reset_Bombs(); Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event); } } @@ -101,9 +116,8 @@ static void Playing__Tagged_Out_Do(StateMachineContext_T * context) // Was it a "long" press? if (duration_of_press_in_ms > 5000) { - Set_Health(MAX_HEALTH); - // TODO: Get this from settings. - Set_Available_Bombs(1); + Set_Health(Get_Max_Health()); + Reset_Bombs(); Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event); } } @@ -118,9 +132,8 @@ static void Playing__Tagged_Out_Do(StateMachineContext_T * context) break; case KEVENT_PLAY_PRESSED_ON_REMOTE: - Set_Health(MAX_HEALTH); - // TODO: Get this from settings. - Set_Available_Bombs(1); + Set_Health(Get_Max_Health()); + Reset_Bombs(); Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event); break; diff --git a/States/Starting_Game/State_Starting_Game__Counting_Down.c b/States/Starting_Game/State_Starting_Game__Counting_Down.c index da80484..e5b4164 100644 --- a/States/Starting_Game/State_Starting_Game__Counting_Down.c +++ b/States/Starting_Game/State_Starting_Game__Counting_Down.c @@ -22,6 +22,8 @@ /* Include Files */ #include "SystemK.h" +static const char *KLOG_TAG = "STARTING_GAME__COUNTING_DOWN"; + static void Starting_Game__Counting_Down_Entry(StateMachineContext_T * context); static void Starting_Game__Counting_Down_Do(StateMachineContext_T * context); static void Starting_Game__Counting_Down_Exit(StateMachineContext_T * context); @@ -48,8 +50,17 @@ static void Starting_Game__Counting_Down_Entry(StateMachineContext_T * context) Reset_Shots_Fired(); Reset_Tags_Received(); Reset_Times_Tagged_Out(); - // TODO: Get this from settings. - Set_Available_Bombs(1); + + uint8_t n_bombs; + if (SETTINGS_get_uint8_t(SYSTEMK_SETTING_N_SPECIAL_WEAPONS_ON_REENTRY, &n_bombs) == SYSTEMK_RESULT_SUCCESS) + { + Set_Available_Bombs(n_bombs); + } + else + { + Set_Available_Bombs(0); + KLOG_ERROR(KLOG_TAG, "Error getting available bombs!"); + } N_Lights_Lit = 0; AudioAction_T audio_action = {.ID = AUDIO_SILENCE, .Data = (void *)0x00}; diff --git a/States/Starting_Game/State_Starting_Game__Instigating.c b/States/Starting_Game/State_Starting_Game__Instigating.c index e4664b3..d835f61 100644 --- a/States/Starting_Game/State_Starting_Game__Instigating.c +++ b/States/Starting_Game/State_Starting_Game__Instigating.c @@ -49,6 +49,10 @@ static void Starting_Game__Instigating_Entry(StateMachineContext_T * context) Starting_Game_Entry(context); LOG("Entering the Instigating substate of the Starting Game state."); + + uint32_t game_length_in_ms; + (void) SETTINGS_get_uint32_t(SYSTEMK_SETTING_T_GAME_LENGTH_in_ms, &game_length_in_ms); + Set_Time_Remaining_Until_Countdown(game_length_in_ms); Set_Time_Remaining_in_Game(UINT32_MAX); uint32_t start_game_time_in_ms; diff --git a/States/Starting_Game/State_Starting_Game__Responding.c b/States/Starting_Game/State_Starting_Game__Responding.c index 7651254..9f17784 100644 --- a/States/Starting_Game/State_Starting_Game__Responding.c +++ b/States/Starting_Game/State_Starting_Game__Responding.c @@ -56,6 +56,7 @@ static void Starting_Game__Responding_Entry(StateMachineContext_T * context) { uint32_t game_length_in_ms = ((BLE_Packet_T *)context->Cause_Of_Transition->Data)->Instigation.game_length_in_ms; Set_Time_Remaining_in_Game(game_length_in_ms); + (void) SETTINGS_set_uint32_t(SYSTEMK_SETTING_T_GAME_LENGTH_in_ms, game_length_in_ms); uint32_t time_remaining_until_countdown_in_ms = ((BLE_Packet_T *)context->Cause_Of_Transition->Data)->Instigation.time_remaining_until_countdown_in_ms; Set_Time_Remaining_Until_Countdown(time_remaining_until_countdown_in_ms); diff --git a/States/State_Configuring.c b/States/State_Configuring.c index 4008858..e27b0f8 100644 --- a/States/State_Configuring.c +++ b/States/State_Configuring.c @@ -330,4 +330,6 @@ void HandleBLEConfigurationPacket(const BLE_ParametersPacket_T *const packet) } } } + + BLE_FreePacketBuffer((BLE_GenericPacketType_T *)packet); } diff --git a/States/State_Ready.c b/States/State_Ready.c index e5be80d..777e37c 100644 --- a/States/State_Ready.c +++ b/States/State_Ready.c @@ -55,7 +55,7 @@ static void Ready_Entry(StateMachineContext_T * context) AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_ON, .Data = (void *)0x00}; Perform_Audio_Action(&audio_action); - Set_Health(MAX_HEALTH); + Set_Health(Get_Max_Health()); } //! Executes the Ready state. -- 2.47.2 From cd33c3597481af67082b7db56bdab45ebd403ef6 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Sat, 1 Mar 2025 16:57:45 -0600 Subject: [PATCH 06/12] Fixes after testing. --- BLE/BLE_Packets.c | 10 ++- States/Playing/State_Playing__Interacting.c | 1 + States/State_Configuring.c | 87 ++++++++++++++++++++- States/State_Initializing.c | 10 --- 4 files changed, 92 insertions(+), 16 deletions(-) diff --git a/BLE/BLE_Packets.c b/BLE/BLE_Packets.c index 578bfce..a1da397 100644 --- a/BLE/BLE_Packets.c +++ b/BLE/BLE_Packets.c @@ -154,10 +154,12 @@ void BLE_UpdateStatusPacket(uint8_t current_state) uint8_t team_ID; uint8_t player_ID; uint8_t weapon_ID; + uint32_t secondary_color; Protocol_T protocol; (void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_TEAMID, &team_ID); (void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_PLAYERID, &player_ID); (void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_WEAPONID, &weapon_ID); + (void) SETTINGS_get_uint32_t(SYSTEMK_SETTING_SECONDARY_COLOR, &secondary_color); protocol = GetWeaponFromID(weapon_ID).Protocol; uint32_t Team_Color = (uint32_t)PROTOCOLS_GetColor(protocol, team_ID, player_ID); @@ -186,10 +188,10 @@ void BLE_UpdateStatusPacket(uint8_t current_state) Advertising_Data.data[19] = (Team_Color >> 8) & 0xFF; Advertising_Data.data[20] = (Team_Color >> 16) & 0xFF; Advertising_Data.data[21] = (Team_Color >> 24) & 0xFF; - Advertising_Data.data[22] = (Team_Color >> 0) & 0xFF; // Secondary Color - Advertising_Data.data[23] = (Team_Color >> 8) & 0xFF; // Secondary Color - Advertising_Data.data[24] = (Team_Color >> 16) & 0xFF; // Secondary Color - Advertising_Data.data[25] = (Team_Color >> 24) & 0xFF; // Secondary Color + Advertising_Data.data[22] = (secondary_color >> 0) & 0xFF; + Advertising_Data.data[23] = (secondary_color >> 8) & 0xFF; + Advertising_Data.data[24] = (secondary_color >> 16) & 0xFF; + Advertising_Data.data[25] = (secondary_color >> 24) & 0xFF; Advertising_Data.data[26] = current_state; Advertising_Data.data[27] = 0xFF; Advertising_Data.data[28] = 0xFF; diff --git a/States/Playing/State_Playing__Interacting.c b/States/Playing/State_Playing__Interacting.c index 8adc07e..0b1fd32 100644 --- a/States/Playing/State_Playing__Interacting.c +++ b/States/Playing/State_Playing__Interacting.c @@ -60,6 +60,7 @@ static void Playing__Interacting_Entry(StateMachineContext_T * context) Playing_Entry(context); srand(xTaskGetTickCount()); } + BLE_UpdateStatusPacket(STATE_PLAYING__INTERACTING); LOG("Entering the Interacting substate of the Playing state."); } diff --git a/States/State_Configuring.c b/States/State_Configuring.c index e27b0f8..f196438 100644 --- a/States/State_Configuring.c +++ b/States/State_Configuring.c @@ -68,7 +68,7 @@ static void Configuring_Entry(StateMachineContext_T *context) AudioAction_T audio_action = {.ID = AUDIO_PLAY_BEEP, .Data = (void *)0x00}; Perform_Audio_Action(&audio_action); } - + BLE_UpdateHelloPacket(); if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS) @@ -81,7 +81,7 @@ static void Configuring_Entry(StateMachineContext_T *context) BLEConfigurationResponseTimer = xTimerCreateStatic( "BLEConfigResponse", xBLEConfigurationResponseTimerPeriod, - pdTRUE, + pdFALSE, (void *)0, BLEConfigurationResponseTimerCallback, &xBLEConfigurationResponseTimerBuffer); @@ -105,6 +105,13 @@ static void Configuring_Do(StateMachineContext_T *context) { portBASE_TYPE xStatus; static KEvent_T Event; + + // For the first hunderd milliseconds, keep updating the Hello packet, since on some platforms (PSoC6), one call is not enough. + // TODO: Fix the Hello packet hack on PSoC6. + if ((xTaskGetTickCount() - context->Time_At_State_Entry_In_Ticks) < (100 / portTICK_PERIOD_MS)) + { + BLE_UpdateHelloPacket(); + } xStatus = Receive_KEvent(&Event); @@ -278,11 +285,87 @@ static SystemKResult_T HandleParameterChangeRequest(BLE_ParameterKey_T key, uint { result = Set_Team_With_Audio_Feedback(team_ID); } + if (result == SYSTEMK_RESULT_SUCCESS) + { + KLOG_INFO(KLOG_TAG, "Team set to %u over BLE.", team_ID); + } } else if (key == BLE_PARAMETER_KEY_PLAYER_ID) { uint8_t player_ID = (uint8_t)value; result = Set_Player_With_Audio_Feedback(player_ID); + if (result == SYSTEMK_RESULT_SUCCESS) + { + KLOG_INFO(KLOG_TAG, "Player set to %u over BLE.", player_ID); + } + } + else if (key == BLE_PARAMETER_KEY_GAME_LENGTH) + { + result = SETTINGS_set_uint32_t(SYSTEMK_SETTING_T_GAME_LENGTH_in_ms, value); + + if (result == SYSTEMK_RESULT_SUCCESS) + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_BEEP, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + KLOG_INFO(KLOG_TAG, "Game length set to %lu ms over BLE.", value); + } + else + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_BONK, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + } + } + else if (key == BLE_PARAMETER_KEY_MAX_HEALTH) + { + uint8_t max_health = (uint8_t)value; + Set_Max_Health(max_health); + result = SETTINGS_set_uint8_t(SYSTEMK_SETTING_MAX_HEALTH, max_health); + + if (result == SYSTEMK_RESULT_SUCCESS) + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_BEEP, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + KLOG_INFO(KLOG_TAG, "Max health set to %u over BLE.", max_health); + } + else + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_BONK, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + } + } + else if (key == BLE_PARAMETER_KEY_SECONDARY_COLOR) + { + result = SETTINGS_set_uint32_t(SYSTEMK_SETTING_SECONDARY_COLOR, value); + + if (result == SYSTEMK_RESULT_SUCCESS) + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_BEEP, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + KLOG_INFO(KLOG_TAG, "Secondary color set to %lu over BLE.", value); + } + else + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_BONK, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + } + } + else if (key == BLE_PARAMETER_KEY_SPECIAL_WEAPONS_ON_REENTRY) + { + uint8_t n_weapons_on_reentry = (uint8_t)value; + Set_Available_Bombs(n_weapons_on_reentry); + result = SETTINGS_set_uint8_t(SYSTEMK_SETTING_N_SPECIAL_WEAPONS_ON_REENTRY, n_weapons_on_reentry); + + if (result == SYSTEMK_RESULT_SUCCESS) + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_BEEP, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + KLOG_INFO(KLOG_TAG, "Number of special weapons granted on reentry set to %u over BLE.", n_weapons_on_reentry); + } + else + { + AudioAction_T audio_action = {.ID = AUDIO_PLAY_BONK, .Data = (void *)0x00}; + Perform_Audio_Action(&audio_action); + } } return result; diff --git a/States/State_Initializing.c b/States/State_Initializing.c index 14a0d09..0b490d8 100644 --- a/States/State_Initializing.c +++ b/States/State_Initializing.c @@ -114,14 +114,4 @@ static void Initializing_Exit(StateMachineContext_T * context) uint8_t weapon_ID = NERF_LASER_STRIKE_BLASTER_ID; (void) SETTINGS_set_uint8_t(SYSTEMK_SETTING_WEAPONID, weapon_ID); (void) SETTINGS_Save(); - - //! \todo TEAM_PURPLE is always one-hit kill. - uint8_t team_ID; - (void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_TEAMID, &team_ID); - TeamID_t my_common_team_ID = Resolve_Common_Team_ID(team_ID); - - if (my_common_team_ID == TEAM_PURPLE) - { - Set_Health(10); - } } -- 2.47.2 From c11206e6255fef994c826fb446a234132571af4f Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Sat, 1 Mar 2025 18:59:46 -0600 Subject: [PATCH 07/12] Fixes after testing on ESP32. --- BLE/BLE_Packets.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/BLE/BLE_Packets.c b/BLE/BLE_Packets.c index a1da397..443b52e 100644 --- a/BLE/BLE_Packets.c +++ b/BLE/BLE_Packets.c @@ -326,10 +326,6 @@ void BLE_UpdateHelloPacket() { strcpy(device_name, "Anonymous"); } - size_t len = strlen(device_name); - if (len < sizeof(device_name)) { - memset(device_name + len, 0x00, sizeof(device_name) - len); - } Advertising_Data.length = BLE_KTAG_PACKET_TOTAL_SIZE; -- 2.47.2 From cb7204269140ba9c6dbe44ca5a5dbaf8c031f685 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Sat, 22 Mar 2025 14:28:51 -0500 Subject: [PATCH 08/12] Improved logging in the Playing_Interacting state. --- States/Playing/State_Playing__Interacting.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/States/Playing/State_Playing__Interacting.c b/States/Playing/State_Playing__Interacting.c index 0b1fd32..ddb9f44 100644 --- a/States/Playing/State_Playing__Interacting.c +++ b/States/Playing/State_Playing__Interacting.c @@ -306,6 +306,10 @@ static void Playing__Interacting_Do(StateMachineContext_T * context) xQueueSend(xQueueNeoPixels, &neopixels_action, 0); Increment_Tags_Received(); + +#ifdef LOG_INTERACTING_SUBSTATE + KLOG_INFO(KLOG_TAG, "%u of %u health remaining", KTAG_Game_Data.My_Health, KTAG_Game_Data.Max_Health); +#endif // LOG_INTERACTING_SUBSTATE } } else if (player_ID != my_player_ID) @@ -345,7 +349,7 @@ static void Playing__Interacting_Do(StateMachineContext_T * context) case KEVENT_BLE_PACKET_RECEIVED: #ifdef LOG_INTERACTING_SUBSTATE - KLOG_INFO(KLOG_TAG, "KEVENT_BLE_PACKET_RECEIVED from %s", BLE_ADDR_To_Str(((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR)); + //KLOG_INFO(KLOG_TAG, "KEVENT_BLE_PACKET_RECEIVED from %s", BLE_ADDR_To_Str(((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR)); #endif // LOG_INTERACTING_SUBSTATE if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_STATUS) { -- 2.47.2 From eaef8247e5e34377389cea571f353f56013de110 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Mon, 31 Mar 2025 20:30:01 -0500 Subject: [PATCH 09/12] Added BLE_BROADCAST_ADDRESS --- BLE/BLE_Utils.c | 2 ++ BLE/BLE_Utils.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/BLE/BLE_Utils.c b/BLE/BLE_Utils.c index 1a05031..a0030f4 100644 --- a/BLE/BLE_Utils.c +++ b/BLE/BLE_Utils.c @@ -23,6 +23,8 @@ #include #include +const uint8_t BLE_BROADCAST_ADDRESS[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + //! Converts a 6-byte Bluetooth Low Energy address to a human-readable string (for logging). /*! * \param bd_addr The Bluetooth address as a 6-byte array diff --git a/BLE/BLE_Utils.h b/BLE/BLE_Utils.h index 42cd2b2..84837df 100644 --- a/BLE/BLE_Utils.h +++ b/BLE/BLE_Utils.h @@ -19,4 +19,6 @@ * file in the root of this repository. If not, see . */ + extern const uint8_t BLE_BROADCAST_ADDRESS[6]; + const char* BLE_ADDR_To_Str(const uint8_t bd_addr[6]); \ No newline at end of file -- 2.47.2 From ba23026d13618bdcbf28717c64059f8229105aab Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Mon, 31 Mar 2025 20:30:39 -0500 Subject: [PATCH 10/12] We need a code formatter. --- States/State_Configuring.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/States/State_Configuring.c b/States/State_Configuring.c index f196438..d0b3362 100644 --- a/States/State_Configuring.c +++ b/States/State_Configuring.c @@ -48,10 +48,11 @@ static const char *KLOG_TAG = "STATE_CONFIGURING"; //! Activities for the **Configuring** state. const StateActivity_T STATE_CONFIGURING_Activities = - { - .Entry = Configuring_Entry, - .Do = Configuring_Do, - .Exit = Configuring_Exit}; +{ + .Entry = Configuring_Entry, + .Do = Configuring_Do, + .Exit = Configuring_Exit +}; //! Sets up the Configuring state. /*! -- 2.47.2 From 63825263911578804866ec4b34310248b8074f17 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Sat, 24 May 2025 16:53:40 -0500 Subject: [PATCH 11/12] Added BLE_StopAdvertising(). --- BLE/BLE_HW_Interface.h | 1 + BLE/BLE_Packets.c | 5 +++++ Game/Weapons.c | 2 +- States/State_Configuring.c | 10 ++++++++-- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/BLE/BLE_HW_Interface.h b/BLE/BLE_HW_Interface.h index 6b3f31c..7a9759e 100644 --- a/BLE/BLE_HW_Interface.h +++ b/BLE/BLE_HW_Interface.h @@ -25,5 +25,6 @@ SystemKResult_T BLE_GetMyAddress(uint8_t * BD_ADDR); SystemKResult_T BLE_ScanAndAdvertise(void); SystemKResult_T BLE_SetAdvertisingData(BLE_AdvertisingData_T * data); +SystemKResult_T BLE_StopAdvertising(void); #endif // BLE_HW_INTERFACE_H diff --git a/BLE/BLE_Packets.c b/BLE/BLE_Packets.c index 443b52e..8b165fb 100644 --- a/BLE/BLE_Packets.c +++ b/BLE/BLE_Packets.c @@ -304,6 +304,11 @@ void BLE_RespondToConfigurationPacket(const BLE_ParametersPacket_T *const packet { KLOG_ERROR(KLOG_TAG, "Error responding to configuration packet!"); } + + if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS) + { + KLOG_ERROR(KLOG_TAG, "Couldn't scan and advertise!"); + } } void BLE_UpdateHelloPacket() diff --git a/Game/Weapons.c b/Game/Weapons.c index f90f523..52da364 100644 --- a/Game/Weapons.c +++ b/Game/Weapons.c @@ -158,7 +158,7 @@ Weapon_t WeaponsByID[NUMBER_OF_WEAPONS] = // The Dubuque Protocol { - .ID = LASER_X_ID, + .ID = DUBUQUE_PROTOCOL_ID, .Type = ENERGY, .Protocol = DUBUQUE_PROTOCOL, .Damage_Per_Shot = 1, diff --git a/States/State_Configuring.c b/States/State_Configuring.c index f196438..bf2c664 100644 --- a/States/State_Configuring.c +++ b/States/State_Configuring.c @@ -34,7 +34,8 @@ static TickType_t xBLEConfigurationResponseTimerPeriod = 3000 / portTICK_PERIOD_ static void BLEConfigurationResponseTimerCallback(TimerHandle_t xTimer) { - BLE_UpdateHelloPacket(); + // Don't send HELLO packets once configuration has started. + BLE_StopAdvertising(); } #define MAX_MENU_DEPTH 10 @@ -106,7 +107,7 @@ static void Configuring_Do(StateMachineContext_T *context) portBASE_TYPE xStatus; static KEvent_T Event; - // For the first hunderd milliseconds, keep updating the Hello packet, since on some platforms (PSoC6), one call is not enough. + // For the first hundred milliseconds, keep updating the Hello packet, since on some platforms (PSoC6), one call is not enough. // TODO: Fix the Hello packet hack on PSoC6. if ((xTaskGetTickCount() - context->Time_At_State_Entry_In_Ticks) < (100 / portTICK_PERIOD_MS)) { @@ -413,6 +414,11 @@ void HandleBLEConfigurationPacket(const BLE_ParametersPacket_T *const packet) } } } + else + { + // Once configuration has begun, stop advertising the HELLO packet to free up bandwidth. + BLE_StopAdvertising(); + } BLE_FreePacketBuffer((BLE_GenericPacketType_T *)packet); } -- 2.47.2 From 747e336cc15e52aaf8a40d5f25a00bdd56ec7904 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Thu, 5 Jun 2025 20:11:10 -0500 Subject: [PATCH 12/12] BLE fixes. --- BLE/BLE_Packets.c | 64 ++++++++++++++++++++++++++++++++------ BLE/BLE_Packets.h | 1 + Protocols/NEC.c | 4 +-- States/State_Wrapping_Up.c | 25 +++++++++++++++ 4 files changed, 83 insertions(+), 11 deletions(-) diff --git a/BLE/BLE_Packets.c b/BLE/BLE_Packets.c index 443b52e..75c3ecb 100644 --- a/BLE/BLE_Packets.c +++ b/BLE/BLE_Packets.c @@ -259,10 +259,11 @@ void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[B } } +//! Event number used for all BLE_PACKET_TYPE_PARAMETERS packets. +static uint8_t ParametersEventNumber = 0; + void BLE_RespondToConfigurationPacket(const BLE_ParametersPacket_T *const packet, BLE_ConfigurationSubtype_T response) { - static uint8_t EventNumber = 0; - Advertising_Data.length = BLE_KTAG_PACKET_TOTAL_SIZE; // Manufacturer Specific Data @@ -275,7 +276,7 @@ void BLE_RespondToConfigurationPacket(const BLE_ParametersPacket_T *const packet Advertising_Data.data[6] = 'a'; Advertising_Data.data[7] = 'g'; Advertising_Data.data[8] = BLE_PACKET_TYPE_PARAMETERS; - Advertising_Data.data[9] = EventNumber++; + Advertising_Data.data[9] = ParametersEventNumber++; Advertising_Data.data[10] = packet->BD_ADDR[0]; Advertising_Data.data[11] = packet->BD_ADDR[1]; Advertising_Data.data[12] = packet->BD_ADDR[2]; @@ -306,6 +307,51 @@ void BLE_RespondToConfigurationPacket(const BLE_ParametersPacket_T *const packet } } +void BLE_BroadcastCurrentParameterInfoPacket(const BLE_ParameterKey_T key_one, const uint32_t value_one, const BLE_ParameterKey_T key_two, const uint32_t value_two) +{ + Advertising_Data.length = BLE_KTAG_PACKET_TOTAL_SIZE; + + // Manufacturer Specific Data + Advertising_Data.data[0] = 0x1E; + Advertising_Data.data[1] = 0xFF; + Advertising_Data.data[2] = 0xFF; + Advertising_Data.data[3] = 0xFF; + Advertising_Data.data[4] = 'K'; + Advertising_Data.data[5] = 'T'; + Advertising_Data.data[6] = 'a'; + Advertising_Data.data[7] = 'g'; + Advertising_Data.data[8] = BLE_PACKET_TYPE_PARAMETERS; + Advertising_Data.data[9] = ParametersEventNumber++; + Advertising_Data.data[10] = BLE_BROADCAST_ADDRESS[0]; + Advertising_Data.data[11] = BLE_BROADCAST_ADDRESS[1]; + Advertising_Data.data[12] = BLE_BROADCAST_ADDRESS[2]; + Advertising_Data.data[13] = BLE_BROADCAST_ADDRESS[3]; + Advertising_Data.data[14] = BLE_BROADCAST_ADDRESS[4]; + Advertising_Data.data[15] = BLE_BROADCAST_ADDRESS[5]; + Advertising_Data.data[16] = BLE_CURRENT_PARAMETER_INFORMATION; + Advertising_Data.data[17] = (uint8_t)((key_one >> 0) & 0xFF); + Advertising_Data.data[18] = (uint8_t)((key_one >> 8) & 0xFF); + Advertising_Data.data[19] = (uint8_t)((value_one >> 0) & 0xFF); + Advertising_Data.data[20] = (uint8_t)((value_one >> 8) & 0xFF); + Advertising_Data.data[21] = (uint8_t)((value_one >> 16) & 0xFF); + Advertising_Data.data[22] = (uint8_t)((value_one >> 24) & 0xFF); + Advertising_Data.data[23] = (uint8_t)((key_two >> 0) & 0xFF); + Advertising_Data.data[24] = (uint8_t)((key_two >> 8) & 0xFF); + Advertising_Data.data[25] = (uint8_t)((value_two >> 0) & 0xFF); + Advertising_Data.data[26] = (uint8_t)((value_two >> 8) & 0xFF); + Advertising_Data.data[27] = (uint8_t)((value_two >> 16) & 0xFF); + Advertising_Data.data[28] = (uint8_t)((value_two >> 24) & 0xFF); + Advertising_Data.data[29] = 0xFF; + Advertising_Data.data[30] = 0xFF; + + SystemKResult_T result = BLE_SetAdvertisingData(&Advertising_Data); + + if (result != SYSTEMK_RESULT_SUCCESS) + { + KLOG_ERROR(KLOG_TAG, "Error responding to configuration packet!"); + } +} + void BLE_UpdateHelloPacket() { static uint8_t EventNumber = 0; @@ -399,12 +445,12 @@ bool BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[6]) } // Is this the broadcast address? - if ((BD_ADDR[0] == 0xFF) && - (BD_ADDR[1] == 0xFF) && - (BD_ADDR[2] == 0xFF) && - (BD_ADDR[3] == 0xFF) && - (BD_ADDR[4] == 0xFF) && - (BD_ADDR[5] == 0xFF)) + if ((BD_ADDR[0] == BLE_BROADCAST_ADDRESS[0]) && + (BD_ADDR[1] == BLE_BROADCAST_ADDRESS[1]) && + (BD_ADDR[2] == BLE_BROADCAST_ADDRESS[2]) && + (BD_ADDR[3] == BLE_BROADCAST_ADDRESS[3]) && + (BD_ADDR[4] == BLE_BROADCAST_ADDRESS[4]) && + (BD_ADDR[5] == BLE_BROADCAST_ADDRESS[5])) { for_me = true; } diff --git a/BLE/BLE_Packets.h b/BLE/BLE_Packets.h index 65744c6..48a68ae 100644 --- a/BLE/BLE_Packets.h +++ b/BLE/BLE_Packets.h @@ -295,6 +295,7 @@ void BLE_UpdateInstigationPacket(uint32_t Game_Length_in_ms, uint32_t Time_Remai void BLE_UpdateStatusPacket(uint8_t current_state); void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[BD_ADDR_SIZE]); void BLE_RespondToConfigurationPacket(const BLE_ParametersPacket_T *const packet, BLE_ConfigurationSubtype_T response); +void BLE_BroadcastCurrentParameterInfoPacket(const BLE_ParameterKey_T key_one, const uint32_t value_one, const BLE_ParameterKey_T key_two, const uint32_t value_two); void BLE_UpdateHelloPacket(); bool BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[BD_ADDR_SIZE]); diff --git a/Protocols/NEC.c b/Protocols/NEC.c index 263fa7e..4e10e30 100755 --- a/Protocols/NEC.c +++ b/Protocols/NEC.c @@ -109,9 +109,9 @@ static inline void PackPulseTrain(TimedPulseTrain_T *pulsetrain, uint32_t data) TimedPulseTrain_T *NEC_EncodePacket(CommandPacket_T *packet) { - uint32_t packed_data = 0x00000000; + uint32_t data = packet->data; - PackPulseTrain(&Command_Send_Buffer, packed_data); + PackPulseTrain(&Command_Send_Buffer, data); return &Command_Send_Buffer; } diff --git a/States/State_Wrapping_Up.c b/States/State_Wrapping_Up.c index 81273bf..fc915b3 100644 --- a/States/State_Wrapping_Up.c +++ b/States/State_Wrapping_Up.c @@ -30,6 +30,15 @@ static void Wrapping_Up_Entry(StateMachineContext_T * context); static void Wrapping_Up_Do(StateMachineContext_T * context); static void Wrapping_Up_Exit(StateMachineContext_T * context); +static TimerHandle_t BLEInfoRequestResponseTimer = NULL; +static StaticTimer_t xBLEInfoRequestResponseTimerBuffer; +static TickType_t xBLEInfoRequestResponseTimerPeriod = 3000 / portTICK_PERIOD_MS; + +static void BLEInfoRequestResponseTimerCallback(TimerHandle_t xTimer) +{ + BLE_UpdateStatusPacket(STATE_WRAPPING_UP); +} + //! Activities for the **Wrapping Up** state. const StateActivity_T STATE_WRAPPING_UP_Activities = { @@ -52,6 +61,22 @@ static void Wrapping_Up_Entry(StateMachineContext_T * context) { KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!"); } + + if (BLEInfoRequestResponseTimer == NULL) + { + BLEInfoRequestResponseTimer = xTimerCreateStatic( + "BLEInfoRequestResponse", + xBLEInfoRequestResponseTimerPeriod, + pdFALSE, + (void *)0, + BLEInfoRequestResponseTimerCallback, + &xBLEInfoRequestResponseTimerBuffer); + } + + if (BLEInfoRequestResponseTimer == NULL) + { + KLOG_ERROR(KLOG_TAG, "Couldn't create the BLEInfoRequestResponseTimer!"); + } } //! Executes the Wrapping Up state. -- 2.47.2