Reworked BLE according to v0.11 of the KTag Beacon Specification (#2)
This was done to support the new KTag Konfigurator app, which Jack created for his Senior Design project. Co-authored-by: Joe Kearney <joe@clubk.club> Reviewed-on: #2
This commit is contained in:
parent
4fe072f2d3
commit
bfcdf4c354
26 changed files with 917 additions and 128 deletions
|
@ -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)
|
||||
|
@ -179,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)
|
||||
|
@ -202,29 +206,31 @@ 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)
|
||||
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);
|
||||
|
@ -236,4 +242,6 @@ void HandleBLETagPacket(const BLE_TagPacket_T *const packet)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLE_FreePacketBuffer((BLE_GenericPacketType_T *)packet);
|
||||
}
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
||||
|
@ -305,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)
|
||||
|
@ -344,14 +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 %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 +359,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 +402,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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
@ -51,7 +67,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();
|
||||
}
|
||||
|
@ -78,11 +94,14 @@ 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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
@ -97,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);
|
||||
}
|
||||
}
|
||||
|
@ -107,16 +125,15 @@ 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);
|
||||
}
|
||||
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;
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_ParametersPacket_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)
|
||||
{
|
||||
// Don't send HELLO packets once configuration has started.
|
||||
BLE_StopAdvertising();
|
||||
}
|
||||
|
||||
#define MAX_MENU_DEPTH 10
|
||||
static MenuItem_T const *CurrentMenuItem;
|
||||
static uint8_t MenuItemHistoryIndex = 0;
|
||||
|
@ -37,10 +49,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.
|
||||
/*!
|
||||
|
@ -52,12 +65,35 @@ 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();
|
||||
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)
|
||||
{
|
||||
KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!");
|
||||
}
|
||||
|
||||
if (BLEConfigurationResponseTimer == NULL)
|
||||
{
|
||||
BLEConfigurationResponseTimer = xTimerCreateStatic(
|
||||
"BLEConfigResponse",
|
||||
xBLEConfigurationResponseTimerPeriod,
|
||||
pdFALSE,
|
||||
(void *)0,
|
||||
BLEConfigurationResponseTimerCallback,
|
||||
&xBLEConfigurationResponseTimerBuffer);
|
||||
}
|
||||
|
||||
if (BLEConfigurationResponseTimer == NULL)
|
||||
{
|
||||
KLOG_ERROR(KLOG_TAG, "Couldn't create the BLEConfigurationResponseTimer!");
|
||||
}
|
||||
|
||||
// Reset the menu.
|
||||
CurrentMenuItem = RootMenu;
|
||||
MenuItemHistory[MenuItemHistoryIndex] = CurrentMenuItem;
|
||||
|
@ -71,6 +107,13 @@ 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);
|
||||
|
||||
|
@ -150,6 +193,7 @@ static void Configuring_Do(StateMachineContext_T *context)
|
|||
CurrentMenuItem->OnFocus(true);
|
||||
}
|
||||
}
|
||||
BLE_UpdateHelloPacket();
|
||||
break;
|
||||
|
||||
case KEVENT_TRIGGER_SWITCH_RELEASED:
|
||||
|
@ -180,6 +224,8 @@ static void Configuring_Do(StateMachineContext_T *context)
|
|||
{
|
||||
KLOG_WARN(KLOG_TAG, "Failed to increment team!");
|
||||
}
|
||||
|
||||
BLE_UpdateHelloPacket();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -191,6 +237,21 @@ 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_PARAMETERS)
|
||||
{
|
||||
HandleBLEConfigurationPacket((BLE_ParametersPacket_T *)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;
|
||||
|
||||
default:
|
||||
// All other events are ignored in this state.
|
||||
ProcessUnhandledEvent(&Event);
|
||||
|
@ -214,3 +275,151 @@ 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_ParameterKey_T key, uint32_t value)
|
||||
{
|
||||
SystemKResult_T result = SYSTEMK_RESULT_UNSPECIFIED_FAILURE;
|
||||
|
||||
if (key == BLE_PARAMETER_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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
void HandleBLEConfigurationPacket(const BLE_ParametersPacket_T *const packet)
|
||||
{
|
||||
if (BLE_IsBLEPacketForMe(packet->target_BD_ADDR))
|
||||
{
|
||||
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_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_ParameterKey_T key_two = BLE_GetValidConfigKey(packet->key_two);
|
||||
if (key_two != BLE_PARAMETER_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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Once configuration has begun, stop advertising the HELLO packet to free up bandwidth.
|
||||
BLE_StopAdvertising();
|
||||
}
|
||||
|
||||
BLE_FreePacketBuffer((BLE_GenericPacketType_T *)packet);
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
@ -113,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -131,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
@ -107,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)
|
||||
{
|
||||
|
@ -120,6 +120,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"
|
||||
|
|
|
@ -47,13 +47,15 @@ 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!");
|
||||
}
|
||||
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.
|
||||
|
@ -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);
|
||||
|
|
|
@ -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 =
|
||||
{
|
||||
|
@ -47,11 +56,27 @@ 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!");
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -84,8 +109,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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue