Reworked BLE according to v0.11 of the KTag Beacon Specification #2

Merged
Joe merged 13 commits from New_BLE into main 2025-06-08 21:52:30 +00:00
11 changed files with 84 additions and 21 deletions
Showing only changes of commit 47822bbdec - Show all commits

View file

@ -180,7 +180,7 @@ void BLE_UpdateStatusPacket(uint8_t current_state)
Advertising_Data.data[13] = player_ID; Advertising_Data.data[13] = player_ID;
Advertising_Data.data[14] = Get_Health(); Advertising_Data.data[14] = Get_Health();
Advertising_Data.data[15] = 0x00; 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[17] = 0x00;
Advertising_Data.data[18] = (Team_Color >> 0) & 0xFF; Advertising_Data.data[18] = (Team_Color >> 0) & 0xFF;
Advertising_Data.data[19] = (Team_Color >> 8) & 0xFF; Advertising_Data.data[19] = (Team_Color >> 8) & 0xFF;

View file

@ -23,7 +23,8 @@
KTag_Game_Data_T KTAG_Game_Data = KTag_Game_Data_T KTAG_Game_Data =
{ {
.My_Health = MAX_HEALTH, .My_Health = 0,
.Max_Health = 0,
.My_Weapon = TEST_PATTERN_ID, .My_Weapon = TEST_PATTERN_ID,
.My_Shield_Strength = 100, .My_Shield_Strength = 100,
.Time_Remaining_in_Game_in_ms = UINT32_MAX, .Time_Remaining_in_Game_in_ms = UINT32_MAX,

View file

@ -24,8 +24,6 @@
#include "Weapons.h" #include "Weapons.h"
#define MAX_HEALTH 10
//! Implemented according to the 2024-07-20 "KTag Teams Compatibility Matrix". //! Implemented according to the 2024-07-20 "KTag Teams Compatibility Matrix".
typedef enum typedef enum
{ {
@ -137,6 +135,7 @@ typedef struct
uint8_t My_Health; uint8_t My_Health;
WeaponID_t My_Weapon; WeaponID_t My_Weapon;
uint8_t My_Shield_Strength; uint8_t My_Shield_Strength;
uint8_t Max_Health;
uint32_t Time_Remaining_in_Game_in_ms; uint32_t Time_Remaining_in_Game_in_ms;
uint32_t Time_Remaining_Until_Countdown_in_ms; uint32_t Time_Remaining_Until_Countdown_in_ms;
uint16_t Shots_Fired; 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) __attribute__((always_inline)) inline void Reduce_Health(uint8_t reduction)
{ {
if (reduction < KTAG_Game_Data.My_Health) if (reduction < KTAG_Game_Data.My_Health)

View file

@ -22,17 +22,21 @@
#ifndef SETTINGS_INTERFACE_H #ifndef SETTINGS_INTERFACE_H
#define 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 typedef enum
{ {
SYSTEMK_SETTING_DEVICE_TYPE,
SYSTEMK_SETTING_IS_RIGHT_HANDED, SYSTEMK_SETTING_IS_RIGHT_HANDED,
SYSTEMK_SETTING_AUDIO_VOLUME, SYSTEMK_SETTING_AUDIO_VOLUME,
SYSTEMK_SETTING_TEAMID, SYSTEMK_SETTING_TEAMID,
SYSTEMK_SETTING_PLAYERID, SYSTEMK_SETTING_PLAYERID,
SYSTEMK_SETTING_WEAPONID, SYSTEMK_SETTING_WEAPONID,
SYSTEMK_SETTING_MAX_HEALTH,
SYSTEMK_SETTING_N_SPECIAL_WEAPONS_ON_REENTRY,
SYSTEMK_SETTING_T_START_GAME_in_ms, SYSTEMK_SETTING_T_START_GAME_in_ms,
SYSTEMK_SETTING_DEVICE_TYPE, SYSTEMK_SETTING_T_GAME_LENGTH_in_ms,
SYSTEMK_SETTING_SECONDARY_COLOR
} SystemKSettingID_T; } SystemKSettingID_T;
SystemKResult_T SETTINGS_get_uint8_t(SystemKSettingID_T id, uint8_t * value); SystemKResult_T SETTINGS_get_uint8_t(SystemKSettingID_T id, uint8_t * value);

View file

@ -226,13 +226,11 @@ void HandleBLETagPacket(const BLE_TagPacket_T *const packet)
else if (packet->damage < 0) else if (packet->damage < 0)
{ {
Health_In_Percent -= packet->damage; 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); 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}; 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); Perform_Audio_Action(&audio_action);

View file

@ -22,6 +22,22 @@
/* Include Files */ /* Include Files */
#include "SystemK.h" #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_Entry(StateMachineContext_T * context);
static void Playing__Tagged_Out_Do(StateMachineContext_T * context); static void Playing__Tagged_Out_Do(StateMachineContext_T * context);
static void Playing__Tagged_Out_Exit(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) if (Back_In() == true)
{ {
// TODO: Get this from settings. Reset_Bombs();
Set_Available_Bombs(1);
Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event); 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? // Was it a "long" press?
if (duration_of_press_in_ms > 5000) if (duration_of_press_in_ms > 5000)
{ {
Set_Health(MAX_HEALTH); Set_Health(Get_Max_Health());
// TODO: Get this from settings. Reset_Bombs();
Set_Available_Bombs(1);
Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event); Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event);
} }
} }
@ -118,9 +132,8 @@ static void Playing__Tagged_Out_Do(StateMachineContext_T * context)
break; break;
case KEVENT_PLAY_PRESSED_ON_REMOTE: case KEVENT_PLAY_PRESSED_ON_REMOTE:
Set_Health(MAX_HEALTH); Set_Health(Get_Max_Health());
// TODO: Get this from settings. Reset_Bombs();
Set_Available_Bombs(1);
Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event); Transition_For_Event(context, STATE_PLAYING__INTERACTING, &Event);
break; break;

View file

@ -22,6 +22,8 @@
/* Include Files */ /* Include Files */
#include "SystemK.h" #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_Entry(StateMachineContext_T * context);
static void Starting_Game__Counting_Down_Do(StateMachineContext_T * context); static void Starting_Game__Counting_Down_Do(StateMachineContext_T * context);
static void Starting_Game__Counting_Down_Exit(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_Shots_Fired();
Reset_Tags_Received(); Reset_Tags_Received();
Reset_Times_Tagged_Out(); 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; N_Lights_Lit = 0;
AudioAction_T audio_action = {.ID = AUDIO_SILENCE, .Data = (void *)0x00}; AudioAction_T audio_action = {.ID = AUDIO_SILENCE, .Data = (void *)0x00};

View file

@ -50,6 +50,10 @@ static void Starting_Game__Instigating_Entry(StateMachineContext_T * context)
LOG("Entering the Instigating substate of the Starting Game state."); 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); Set_Time_Remaining_in_Game(UINT32_MAX);
uint32_t start_game_time_in_ms; uint32_t start_game_time_in_ms;
(void) SETTINGS_get_uint32_t(SYSTEMK_SETTING_T_START_GAME_in_ms, &start_game_time_in_ms); (void) SETTINGS_get_uint32_t(SYSTEMK_SETTING_T_START_GAME_in_ms, &start_game_time_in_ms);

View file

@ -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; 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); 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; 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); Set_Time_Remaining_Until_Countdown(time_remaining_until_countdown_in_ms);

View file

@ -330,4 +330,6 @@ void HandleBLEConfigurationPacket(const BLE_ParametersPacket_T *const packet)
} }
} }
} }
BLE_FreePacketBuffer((BLE_GenericPacketType_T *)packet);
} }

View file

@ -55,7 +55,7 @@ static void Ready_Entry(StateMachineContext_T * context)
AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_ON, .Data = (void *)0x00}; AudioAction_T audio_action = {.ID = AUDIO_PLAY_GAME_ON, .Data = (void *)0x00};
Perform_Audio_Action(&audio_action); Perform_Audio_Action(&audio_action);
Set_Health(MAX_HEALTH); Set_Health(Get_Max_Health());
} }
//! Executes the Ready state. //! Executes the Ready state.