diff --git a/BLE/BLE_HW_Interface.h b/BLE/BLE_HW_Interface.h index 7a9759e..89cc232 100644 --- a/BLE/BLE_HW_Interface.h +++ b/BLE/BLE_HW_Interface.h @@ -26,5 +26,8 @@ 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); +SystemKResult_T BLE_StopScanning(void); +SystemKResult_T BLE_Quiet(uint32_t duration_ms); +SystemKResult_T BLE_Unquiet(void); #endif // BLE_HW_INTERFACE_H diff --git a/BLE/BLE_Packets.c b/BLE/BLE_Packets.c index b150e6f..c44fc62 100644 --- a/BLE/BLE_Packets.c +++ b/BLE/BLE_Packets.c @@ -24,7 +24,7 @@ #include "SystemK.h" -#define N_PACKET_BUFFERS 10 +#define N_PACKET_BUFFERS 20 static BLE_Packet_T Packet_Buffers[N_PACKET_BUFFERS]; static BLE_AdvertisingData_T Advertising_Data; static uint8_t my_BD_ADDR[6]; @@ -147,6 +147,54 @@ void BLE_UpdateInstigationPacket(uint32_t Game_Length_in_ms, uint32_t Time_Remai } } +void BLE_UpdateEventPacket(uint8_t target_BD_ADDR[BD_ADDR_SIZE], BLE_EventID_T event_ID, uint32_t event_data) +{ + 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_EVENT; + Advertising_Data.data[9] = EventNumber++; + Advertising_Data.data[10] = target_BD_ADDR[0]; + Advertising_Data.data[11] = target_BD_ADDR[1]; + Advertising_Data.data[12] = target_BD_ADDR[2]; + Advertising_Data.data[13] = target_BD_ADDR[3]; + Advertising_Data.data[14] = target_BD_ADDR[4]; + Advertising_Data.data[15] = target_BD_ADDR[5]; + Advertising_Data.data[16] = (event_ID >> 0) & 0xFF; + Advertising_Data.data[17] = (event_ID >> 8) & 0xFF; + Advertising_Data.data[18] = (event_ID >> 16) & 0xFF; + Advertising_Data.data[19] = (event_ID >> 24) & 0xFF; + Advertising_Data.data[20] = (event_data >> 0) & 0xFF; + Advertising_Data.data[21] = (event_data >> 8) & 0xFF; + Advertising_Data.data[22] = (event_data >> 16) & 0xFF; + Advertising_Data.data[23] = (event_data >> 24) & 0xFF; + Advertising_Data.data[24] = 0xFF; + Advertising_Data.data[25] = 0xFF; + Advertising_Data.data[26] = 0xFF; + Advertising_Data.data[27] = 0xFF; + Advertising_Data.data[28] = 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 updating event packet!"); + } +} + void BLE_UpdateStatusPacket(uint8_t current_state) { static uint8_t EventNumber = 0; @@ -262,7 +310,7 @@ 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) +void BLE_RespondToConfigurationPacket(const BLE_ParametersPacket_T *const packet, BLE_ParametersSubtype_T response) { Advertising_Data.length = BLE_KTAG_PACKET_TOTAL_SIZE; @@ -312,7 +360,7 @@ 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) +void BLE_UpdateParametersPacket(BLE_ParametersSubtype_T subtype, const uint8_t target_BD_ADDR[BD_ADDR_SIZE], 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; @@ -327,13 +375,13 @@ void BLE_BroadcastCurrentParameterInfoPacket(const BLE_ParameterKey_T key_one, c 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[10] = target_BD_ADDR[0]; + Advertising_Data.data[11] = target_BD_ADDR[1]; + Advertising_Data.data[12] = target_BD_ADDR[2]; + Advertising_Data.data[13] = target_BD_ADDR[3]; + Advertising_Data.data[14] = target_BD_ADDR[4]; + Advertising_Data.data[15] = target_BD_ADDR[5]; + Advertising_Data.data[16] = (uint8_t)subtype; 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); @@ -348,15 +396,16 @@ void BLE_BroadcastCurrentParameterInfoPacket(const BLE_ParameterKey_T key_one, c 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!"); - } + KLOG_ERROR(KLOG_TAG, "Error updating parameters packet!"); + } } + void BLE_UpdateHelloPacket() { static uint8_t EventNumber = 0; diff --git a/BLE/BLE_Packets.h b/BLE/BLE_Packets.h index 48a68ae..d1f3e36 100644 --- a/BLE/BLE_Packets.h +++ b/BLE/BLE_Packets.h @@ -100,6 +100,9 @@ typedef enum BLE_EVENT_CONFIGURED = 2, BLE_EVENT_WRAPUP_COMPLETE = 3, BLE_EVENT_GAME_OVER = 4, + BLE_EVENT_QUIET = 5, + BLE_EVENT_UNQUIET = 6, + BLE_EVENT_FORCE_STATE = 7, BLE_EVENT_UNUSED = 0xFFFFFFFF } BLE_EventID_T; @@ -174,7 +177,7 @@ typedef enum BLE_ACKNOWLEDGE_PARAMETER_CHANGE = 0x03, BLE_ERROR_CHANGING_PARAMETERS = 0x04, BLE_ERROR_RESPONDING_TO_REQUEST = 0xFF -} BLE_ConfigurationSubtype_T; +} BLE_ParametersSubtype_T; typedef enum { @@ -292,10 +295,11 @@ 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_UpdateEventPacket(uint8_t target_BD_ADDR[BD_ADDR_SIZE], BLE_EventID_T event, uint32_t data); 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_RespondToConfigurationPacket(const BLE_ParametersPacket_T *const packet, BLE_ParametersSubtype_T response); +void BLE_UpdateParametersPacket(BLE_ParametersSubtype_T subtype, const uint8_t target_BD_ADDR[BD_ADDR_SIZE], 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/BLE/BLE_Utils.c b/BLE/BLE_Utils.c index a0030f4..234ba62 100644 --- a/BLE/BLE_Utils.c +++ b/BLE/BLE_Utils.c @@ -22,6 +22,7 @@ #include #include #include +#include "SystemK.h" const uint8_t BLE_BROADCAST_ADDRESS[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -51,4 +52,76 @@ const char *BLE_ADDR_To_Str(const uint8_t bd_addr[6]) str_addr[17] = '\0'; // Ensure null termination. return str_addr; +} + +SystemKResult_T BLE_HandleCommonEvents(KEvent_T *event) +{ + SystemKResult_T result = SYSTEMK_RESULT_EVENT_NOT_HANDLED; + + if (event->ID == KEVENT_BLE_PACKET_RECEIVED) + { + BLE_Packet_T * packet = (BLE_Packet_T *)event->Data; + + if (packet->Generic.type == BLE_PACKET_TYPE_EVENT) + { + BLE_EventPacket_T * event_packet = (BLE_EventPacket_T *)packet; + + if (BLE_IsBLEPacketForMe(event_packet->target_BD_ADDR)) + { + if (BLE_IsPacketNew(event_packet->BD_ADDR, BLE_PACKET_TYPE_EVENT, event_packet->event_number)) + { + if (event_packet->event_ID == BLE_EVENT_QUIET) + { + uint32_t duration_ms = event_packet->event_data; + if (BLE_Quiet(duration_ms) == SYSTEMK_RESULT_SUCCESS) + { + if (duration_ms > 0) + { + KLOG_INFO("BLE", "Quiet mode activated for %lu ms.", duration_ms); + } + else + { + KLOG_INFO("BLE", "Quiet mode activated until further notice."); + } + } + else + { + KLOG_ERROR("BLE", "Failed to activate quiet mode."); + } + result = SYSTEMK_RESULT_SUCCESS; + } + else if (event_packet->event_ID == BLE_EVENT_UNQUIET) + { + if (BLE_Unquiet() == SYSTEMK_RESULT_SUCCESS) + { + KLOG_INFO("BLE", "Quiet mode deactivated."); + } + else + { + KLOG_ERROR("BLE", "Failed to deactivate quiet mode."); + } + result = SYSTEMK_RESULT_SUCCESS; + } + else if (event_packet->event_ID == BLE_EVENT_FORCE_STATE) + { + uint32_t requested_state = event_packet->event_data; + + if (requested_state < STATE_IS_OUT_OF_RANGE) + { + Transition_For_Event(GetContext(), (StateID_T)requested_state, event); + KLOG_INFO("BLE", "State %lu forced.", requested_state); + result = SYSTEMK_RESULT_SUCCESS; + } + else + { + KLOG_ERROR("BLE", "Attempted to force unknown state %lu.", requested_state); + result = SYSTEMK_RESULT_OVERFLOW; + } + } + } + } + } + } + + return result; } \ No newline at end of file diff --git a/BLE/BLE_Utils.h b/BLE/BLE_Utils.h index 84837df..c52efc0 100644 --- a/BLE/BLE_Utils.h +++ b/BLE/BLE_Utils.h @@ -19,6 +19,7 @@ * file in the root of this repository. If not, see . */ - extern const uint8_t BLE_BROADCAST_ADDRESS[6]; +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 +const char* BLE_ADDR_To_Str(const uint8_t bd_addr[6]); +SystemKResult_T BLE_HandleCommonEvents(KEvent_T *event); \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c9e2bb9..592d9f6 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ idf_component_register( "NeoPixels/Animations/Tag_Received.c" "NeoPixels/Animations/Team_Colors.c" "NeoPixels/Animations/Test_Pattern.c" + "NeoPixels/Animations/Wrapping_Up_Animation.c" "Protocols/Dubuque.c" "Protocols/Dynasty.c" "Protocols/Laser_X.c" diff --git a/Events/KEvents.c b/Events/KEvents.c index d191ae5..8b1f052 100755 --- a/Events/KEvents.c +++ b/Events/KEvents.c @@ -30,7 +30,7 @@ #define ITEM_SIZE sizeof(KEvent_T) static StaticQueue_t StaticQueue; static uint8_t QueueStorageArea[QUEUE_LENGTH * ITEM_SIZE]; -QueueHandle_t xQueueEvents; +static QueueHandle_t xQueueEvents; static void Remap_Event(KEvent_T *event) { @@ -61,7 +61,11 @@ void Init_KEvents(void) void Post_KEvent(KEvent_T *event) { Remap_Event(event); - xQueueSend(xQueueEvents, event, 0); + if (BLE_HandleCommonEvents(event) == SYSTEMK_RESULT_EVENT_NOT_HANDLED) + { + // If the event was not handled by the BLE subsystem, post it to the global event queue. + xQueueSend(xQueueEvents, event, 0); + } } void Post_KEvent_From_ISR(KEvent_T *event, portBASE_TYPE *xHigherPriorityTaskWoken) diff --git a/KIsForQuality.png b/KIsForQuality.png new file mode 100644 index 0000000..7205c47 Binary files /dev/null and b/KIsForQuality.png differ diff --git a/NeoPixels/Animations/Wrapping_Up_Animation.c b/NeoPixels/Animations/Wrapping_Up_Animation.c new file mode 100644 index 0000000..078ecaf --- /dev/null +++ b/NeoPixels/Animations/Wrapping_Up_Animation.c @@ -0,0 +1,119 @@ + +/* + * 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 "SystemK.h" + +static uint8_t Scene = 0; +static uint8_t N_SCENES = 8; +static uint16_t Time_in_Current_Scene_in_ms = 0; +static color_t My_Color = COLOR_BLACK; + +static void Reset(void * Data) +{ + Time_in_Current_Scene_in_ms = 0; + Scene = N_SCENES - 1; +} + +static AnimationStepResult_T NextStep(void) +{ + My_Color = HW_NeoPixels_Get_My_Color(); + +#if (CONFIG_KTAG_N_NEOPIXEL_CHANNELS == 1) + switch (Scene) + { + default: + case 0: + Set_Barrel_Flash(Color(0x70, 0xFF, 0xFF, 0xFF)); + Set_Heart(Color(0x00, 0x00, 0x00, 0x00)); + Set_Square(Color(0x00, 0x00, 0x00, 0x00)); + Set_Circle(Color(0x00, 0x00, 0x00, 0x00)); + Set_Arrow(ApplyMask(My_Color, 0x70)); + break; + + case 1: + Set_Barrel_Flash(Color(0x00, 0x00, 0x00, 0x00)); + Set_Heart(Color(0x00, 0x00, 0x00, 0x00)); + Set_Square(Color(0x00, 0x00, 0x00, 0x00)); + Set_Circle(ApplyMask(My_Color, 0x70)); + Set_Arrow(Color(0x00, 0x00, 0x00, 0x00)); + break; + + case 2: + Set_Barrel_Flash(Color(0x70, 0xFF, 0xFF, 0xFF)); + Set_Heart(Color(0x00, 0x00, 0x00, 0x00)); + Set_Square(ApplyMask(My_Color, 0x70)); + Set_Circle(Color(0x00, 0x00, 0x00, 0x00)); + Set_Arrow(Color(0x00, 0x00, 0x00, 0x00)); + break; + + case 3: + Set_Barrel_Flash(Color(0x00, 0x00, 0x00, 0x00)); + Set_Heart(ApplyMask(My_Color, 0x70)); + Set_Square(Color(0x00, 0x00, 0x00, 0x00)); + Set_Circle(Color(0x00, 0x00, 0x00, 0x00)); + Set_Arrow(Color(0x00, 0x00, 0x00, 0x00)); + break; + } +#elif (CONFIG_KTAG_N_NEOPIXEL_CHANNELS == 4) + NeoPixels_Set_Color(NEOPIXEL_CHANNEL_BARREL, BARREL_FLASH_PIXEL, ApplyMask(COLOR_WHITE, 0x70)); + for (uint_fast8_t pixel = 0; pixel < CONFIG_KTAG_MAX_NEOPIXELS_PER_CHANNEL; pixel++) + { + if ((pixel % N_SCENES) == Scene) + { + NeoPixels_Set_Color(NEOPIXEL_CHANNEL_RECEIVER, pixel, ApplyMask(My_Color, 0x70)); + NeoPixels_Set_Color(NEOPIXEL_CHANNEL_DISPLAY, pixel, ApplyMask(My_Color, 0x70)); + NeoPixels_Set_Color(NEOPIXEL_CHANNEL_EFFECTS, pixel, ApplyMask(My_Color, 0x70)); + } + else + { + NeoPixels_Set_Color(NEOPIXEL_CHANNEL_RECEIVER, pixel, COLOR_BLACK); + NeoPixels_Set_Color(NEOPIXEL_CHANNEL_DISPLAY, pixel, COLOR_BLACK); + NeoPixels_Set_Color(NEOPIXEL_CHANNEL_EFFECTS, pixel, COLOR_BLACK); + } + } + NeoPixels_Set_Color(NEOPIXEL_CHANNEL_RECEIVER, RECEIVER_INDICATOR_PIXEL, ApplyMask(COLOR_WHITE, 0x70)); +#endif // CONFIG_KTAG_N_NEOPIXEL_CHANNELS + + Time_in_Current_Scene_in_ms += CONFIG_KTAG_ANIMATION_STEP_TIME_IN_ms; + + if (Time_in_Current_Scene_in_ms > 25) + { + Time_in_Current_Scene_in_ms = 0; + + if (Scene > 0) + { + Scene--; + } + else + { + Scene = N_SCENES - 1; + } + } + + return ANIMATION_ONGOING; +} + +Animation_T Wrapping_Up_Animation = +{ + .Reset = Reset, + .NextStep = NextStep +}; diff --git a/NeoPixels/Animations/Wrapping_Up_Animation.h b/NeoPixels/Animations/Wrapping_Up_Animation.h new file mode 100644 index 0000000..722726f --- /dev/null +++ b/NeoPixels/Animations/Wrapping_Up_Animation.h @@ -0,0 +1,28 @@ + +/* + * 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 . + */ + +#ifndef WRAPPING_UP_ANIMATION_H +#define WRAPPING_UP_ANIMATION_H + +extern Animation_T Wrapping_Up_Animation; + +#endif // WRAPPING_UP_ANIMATION_H diff --git a/NeoPixels/NeoPixels.c b/NeoPixels/NeoPixels.c index 789ccb7..a13e64f 100644 --- a/NeoPixels/NeoPixels.c +++ b/NeoPixels/NeoPixels.c @@ -120,6 +120,10 @@ void NeoPixels_Task(void * pvParameters) case NEOPIXELS_BLE_NEARBY: New_Animation = &BLE_Nearby_Animation; break; + + case NEOPIXELS_WRAPPING_UP: + New_Animation = &Wrapping_Up_Animation; + break; } if (New_Animation != NULL) diff --git a/NeoPixels/NeoPixels.h b/NeoPixels/NeoPixels.h index af75da8..8cd2414 100644 --- a/NeoPixels/NeoPixels.h +++ b/NeoPixels/NeoPixels.h @@ -85,6 +85,7 @@ #include "Animations/Tagged_Out.h" #include "Animations/Team_Colors.h" #include "Animations/Test_Pattern.h" +#include "Animations/Wrapping_Up_Animation.h" extern QueueHandle_t xQueueNeoPixels; extern TaskHandle_t NeoPixels_Task_Handle; @@ -138,8 +139,9 @@ typedef enum NEOPIXELS_COUNTDOWN, //! For #NEOPIXELS_TEAM_COLORS, #NeoPixelsAction_T::Data is a #DisplayStyle_T. NEOPIXELS_TEAM_COLORS, - //! For #NEOPIXELS_TEAM_COLORS, #NeoPixelsAction_T::Data is a #BLENearby_T. - NEOPIXELS_BLE_NEARBY + //! For #NEOPIXELS_BLE_NEARBY, #NeoPixelsAction_T::Data is a #BLENearby_T. + NEOPIXELS_BLE_NEARBY, + NEOPIXELS_WRAPPING_UP } NeoPixelsActionID_T; typedef enum diff --git a/README.md b/README.md index 09bb4df..40e8148 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ # SystemK -...where the 'K' stands for quality. \ No newline at end of file +...where the 'K' stands for Quality. + +![K is for Quality](KIsForQuality.png) + +*SystemK* is the name for the common software that is at the core of KTag devices. + +This is that software. \ No newline at end of file diff --git a/Results.h b/Results.h index 45959aa..3f651ee 100644 --- a/Results.h +++ b/Results.h @@ -39,12 +39,15 @@ typedef enum SYSTEMK_RESULT_QUEUE_IS_FULL, SYSTEMK_RESULT_NOT_READY, SYSTEMK_RESULT_FAILED_TO_CREATE_RTOS_TASK, + SYSTEMK_RESULT_FAILED_TO_CREATE_RTOS_TIMER, + SYSTEMK_RESULT_FAILED_TO_START_RTOS_TIMER, SYSTEMK_RESULT_FILE_NOT_FOUND, SYSTEMK_RESULT_KEY_NOT_FOUND, SYSTEMK_RESULT_READ_FAILED, SYSTEMK_RESULT_WRITE_FAILED, SYSTEMK_RESULT_OVERFLOW, - SYSTEMK_RESULT_UNDERFLOW + SYSTEMK_RESULT_UNDERFLOW, + SYSTEMK_RESULT_EVENT_NOT_HANDLED } SystemKResult_T; #endif // RESULTS_H diff --git a/States/Playing/State_Playing.c b/States/Playing/State_Playing.c index b65b99f..841b105 100644 --- a/States/Playing/State_Playing.c +++ b/States/Playing/State_Playing.c @@ -24,7 +24,7 @@ static TimerHandle_t BLEStatusTimer = NULL; static StaticTimer_t xBLEStatusTimerBuffer; -static TickType_t xBLEStatusTimerPeriod = 3000 / portTICK_PERIOD_MS; +static TickType_t xBLEStatusTimerPeriod = 500 / portTICK_PERIOD_MS; static TimerHandle_t GameDurationTimer = NULL; static StaticTimer_t xGameDurationTimerBuffer; diff --git a/States/Playing/State_Playing__Interacting.c b/States/Playing/State_Playing__Interacting.c index 69254aa..767d644 100644 --- a/States/Playing/State_Playing__Interacting.c +++ b/States/Playing/State_Playing__Interacting.c @@ -406,6 +406,7 @@ static void Playing__Interacting_Do(StateMachineContext_T * context) } break; + case KEVENT_PLAY_PRESSED_ON_REMOTE: case KEVENT_GAME_OVER: { AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_OVER, .Play_To_Completion = true}; @@ -413,6 +414,21 @@ static void Playing__Interacting_Do(StateMachineContext_T * context) Transition_For_Event(context, STATE_WRAPPING_UP, &Event); } break; + + case KEVENT_MENU_UP: + { +#ifdef LOG_INTERACTING_SUBSTATE + KLOG_INFO(KLOG_TAG, "Simulating a tag leading to being tagged out."); +#endif // LOG_INTERACTING_SUBSTATE + Reduce_Health(Get_Max_Health()); + + 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); + } + break; default: // All other events are ignored in this state. diff --git a/States/Playing/State_Playing__Tagged_Out.c b/States/Playing/State_Playing__Tagged_Out.c index 58e50ed..9a4bf3f 100644 --- a/States/Playing/State_Playing__Tagged_Out.c +++ b/States/Playing/State_Playing__Tagged_Out.c @@ -185,6 +185,7 @@ static void Playing__Tagged_Out_Do(StateMachineContext_T * context) } break; + case KEVENT_PLAY_PRESSED_ON_REMOTE: case KEVENT_GAME_OVER: { AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_OVER, .Play_To_Completion = true}; @@ -193,7 +194,7 @@ static void Playing__Tagged_Out_Do(StateMachineContext_T * context) } break; - case KEVENT_PLAY_PRESSED_ON_REMOTE: + case KEVENT_MENU_DOWN: Set_Health(Get_Max_Health()); Reset_Bombs(); Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event); diff --git a/States/Starting_Game/State_Starting_Game__Counting_Down.c b/States/Starting_Game/State_Starting_Game__Counting_Down.c index e5b4164..c352794 100644 --- a/States/Starting_Game/State_Starting_Game__Counting_Down.c +++ b/States/Starting_Game/State_Starting_Game__Counting_Down.c @@ -50,6 +50,7 @@ static void Starting_Game__Counting_Down_Entry(StateMachineContext_T * context) Reset_Shots_Fired(); Reset_Tags_Received(); Reset_Times_Tagged_Out(); + Set_Health(Get_Max_Health()); uint8_t n_bombs; if (SETTINGS_get_uint8_t(SYSTEMK_SETTING_N_SPECIAL_WEAPONS_ON_REENTRY, &n_bombs) == SYSTEMK_RESULT_SUCCESS) diff --git a/States/State_Configuring.c b/States/State_Configuring.c index f11203e..d9416d1 100644 --- a/States/State_Configuring.c +++ b/States/State_Configuring.c @@ -34,8 +34,7 @@ static TickType_t xBLEConfigurationResponseTimerPeriod = 3000 / portTICK_PERIOD_ static void BLEConfigurationResponseTimerCallback(TimerHandle_t xTimer) { - // Don't send HELLO packets once configuration has started. - BLE_StopAdvertising(); + BLE_UpdateHelloPacket(); } #define MAX_MENU_DEPTH 10 @@ -107,13 +106,6 @@ static void Configuring_Do(StateMachineContext_T *context) { portBASE_TYPE xStatus; static KEvent_T Event; - - // 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)) - { - BLE_UpdateHelloPacket(); - } xStatus = Receive_KEvent(&Event); @@ -238,7 +230,12 @@ static void Configuring_Do(StateMachineContext_T *context) break; case KEVENT_BLE_PACKET_RECEIVED: - if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_PARAMETERS) + if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_INSTIGATE_GAME) + { + Transition_For_Event(context, STATE_STARTING_GAME__RESPONDING, &Event); + // Don't free the packet buffer here; it will be freed in Starting_Game__Responding_Entry(). + } + else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_PARAMETERS) { HandleBLEConfigurationPacket((BLE_ParametersPacket_T *)Event.Data); } @@ -408,6 +405,12 @@ void HandleBLEConfigurationPacket(const BLE_ParametersPacket_T *const packet) BLE_RespondToConfigurationPacket(packet, BLE_ERROR_CHANGING_PARAMETERS); } + // A parameters request addressed to this device or broadcast will end a BLE Quiet. + if (BLE_Unquiet() != SYSTEMK_RESULT_SUCCESS) + { + KLOG_ERROR(KLOG_TAG, "Couldn't Unquiet to respond to a Parameters request!"); + } + if (xTimerStart(BLEConfigurationResponseTimer, 0) != pdPASS) { KLOG_ERROR(KLOG_TAG, "Couldn't start the BLEConfigurationResponseTimer!"); @@ -415,11 +418,6 @@ 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); } diff --git a/States/State_Initializing.c b/States/State_Initializing.c index 1570297..55e2b9f 100644 --- a/States/State_Initializing.c +++ b/States/State_Initializing.c @@ -68,7 +68,7 @@ static void Initializing_Do(StateMachineContext_T * context) { switch (Event.ID) { - case KEVENT_TRIGGER_SWITCH_PRESSED: + case KEVENT_ACCESSORY_SWITCH_PRESSED: Transition_For_Event(context, STATE_REPROGRAMMING, &Event); break; diff --git a/States/State_Ready.c b/States/State_Ready.c index 777e37c..ea86d60 100644 --- a/States/State_Ready.c +++ b/States/State_Ready.c @@ -54,8 +54,6 @@ 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(Get_Max_Health()); } //! Executes the Ready state. @@ -91,6 +89,7 @@ static void Ready_Do(StateMachineContext_T * context) if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_INSTIGATE_GAME) { Transition_For_Event(context, STATE_STARTING_GAME__RESPONDING, &Event); + // Don't free the packet buffer here; it will be freed in Starting_Game__Responding_Entry(). } else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) { diff --git a/States/State_Wrapping_Up.c b/States/State_Wrapping_Up.c index fc915b3..133e27d 100644 --- a/States/State_Wrapping_Up.c +++ b/States/State_Wrapping_Up.c @@ -54,7 +54,7 @@ const StateActivity_T STATE_WRAPPING_UP_Activities = 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}; + NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_WRAPPING_UP, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00}; xQueueSend(xQueueNeoPixels, &neopixels_action, 0); BLE_UpdateStatusPacket(STATE_WRAPPING_UP); if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS) @@ -109,7 +109,12 @@ static void Wrapping_Up_Do(StateMachineContext_T * context) break; case KEVENT_BLE_PACKET_RECEIVED: - if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) + if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_INSTIGATE_GAME) + { + Transition_For_Event(context, STATE_STARTING_GAME__RESPONDING, &Event); + // Don't free the packet buffer here; it will be freed in Starting_Game__Responding_Entry(). + } + else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT) { HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data, context); } @@ -118,6 +123,10 @@ static void Wrapping_Up_Do(StateMachineContext_T * context) BLE_FreePacketBuffer(Event.Data); } break; + + case KEVENT_PLAY_PRESSED_ON_REMOTE: + Transition_For_Event(context, STATE_CONFIGURING, &Event); + break; default: // All other events are ignored in this state.