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
|
@ -25,5 +25,6 @@
|
||||||
SystemKResult_T BLE_GetMyAddress(uint8_t * BD_ADDR);
|
SystemKResult_T BLE_GetMyAddress(uint8_t * BD_ADDR);
|
||||||
SystemKResult_T BLE_ScanAndAdvertise(void);
|
SystemKResult_T BLE_ScanAndAdvertise(void);
|
||||||
SystemKResult_T BLE_SetAdvertisingData(BLE_AdvertisingData_T * data);
|
SystemKResult_T BLE_SetAdvertisingData(BLE_AdvertisingData_T * data);
|
||||||
|
SystemKResult_T BLE_StopAdvertising(void);
|
||||||
|
|
||||||
#endif // BLE_HW_INTERFACE_H
|
#endif // BLE_HW_INTERFACE_H
|
||||||
|
|
|
@ -49,11 +49,14 @@ static PacketTracker_T Tracker =
|
||||||
.head = 0,
|
.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,
|
bool BLE_IsPacketNew(const uint8_t *sender_BD_ADDR,
|
||||||
BLE_PacketType_T packet_type,
|
BLE_PacketType_T packet_type,
|
||||||
uint8_t event_number)
|
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.
|
// Check if the packet already exists in the tracker.
|
||||||
for (int i = 0; i < Tracker.count; i++)
|
for (int i = 0; i < Tracker.count; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -147,17 +147,19 @@ 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;
|
static uint8_t EventNumber = 0;
|
||||||
|
|
||||||
uint8_t team_ID;
|
uint8_t team_ID;
|
||||||
uint8_t player_ID;
|
uint8_t player_ID;
|
||||||
uint8_t weapon_ID;
|
uint8_t weapon_ID;
|
||||||
|
uint32_t secondary_color;
|
||||||
Protocol_T protocol;
|
Protocol_T protocol;
|
||||||
(void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_TEAMID, &team_ID);
|
(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_PLAYERID, &player_ID);
|
||||||
(void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_WEAPONID, &weapon_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;
|
protocol = GetWeaponFromID(weapon_ID).Protocol;
|
||||||
uint32_t Team_Color = (uint32_t)PROTOCOLS_GetColor(protocol, team_ID, player_ID);
|
uint32_t Team_Color = (uint32_t)PROTOCOLS_GetColor(protocol, team_ID, player_ID);
|
||||||
|
|
||||||
|
@ -180,17 +182,17 @@ void BLE_UpdateStatusPacket()
|
||||||
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;
|
||||||
Advertising_Data.data[20] = (Team_Color >> 16) & 0xFF;
|
Advertising_Data.data[20] = (Team_Color >> 16) & 0xFF;
|
||||||
Advertising_Data.data[21] = (Team_Color >> 24) & 0xFF;
|
Advertising_Data.data[21] = (Team_Color >> 24) & 0xFF;
|
||||||
Advertising_Data.data[22] = (Team_Color >> 0) & 0xFF; // Secondary Color
|
Advertising_Data.data[22] = (secondary_color >> 0) & 0xFF;
|
||||||
Advertising_Data.data[23] = (Team_Color >> 8) & 0xFF; // Secondary Color
|
Advertising_Data.data[23] = (secondary_color >> 8) & 0xFF;
|
||||||
Advertising_Data.data[24] = (Team_Color >> 16) & 0xFF; // Secondary Color
|
Advertising_Data.data[24] = (secondary_color >> 16) & 0xFF;
|
||||||
Advertising_Data.data[25] = (Team_Color >> 24) & 0xFF; // Secondary Color
|
Advertising_Data.data[25] = (secondary_color >> 24) & 0xFF;
|
||||||
Advertising_Data.data[26] = 0xFF;
|
Advertising_Data.data[26] = current_state;
|
||||||
Advertising_Data.data[27] = 0xFF;
|
Advertising_Data.data[27] = 0xFF;
|
||||||
Advertising_Data.data[28] = 0xFF;
|
Advertising_Data.data[28] = 0xFF;
|
||||||
Advertising_Data.data[29] = 0xFF;
|
Advertising_Data.data[29] = 0xFF;
|
||||||
|
@ -237,12 +239,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[17] = (color >> 8) & 0xFF;
|
||||||
Advertising_Data.data[18] = (color >> 16) & 0xFF;
|
Advertising_Data.data[18] = (color >> 16) & 0xFF;
|
||||||
Advertising_Data.data[19] = (color >> 24) & 0xFF;
|
Advertising_Data.data[19] = (color >> 24) & 0xFF;
|
||||||
Advertising_Data.data[20] = target_BD_ADDR[0],
|
Advertising_Data.data[20] = target_BD_ADDR[0];
|
||||||
Advertising_Data.data[21] = target_BD_ADDR[1],
|
Advertising_Data.data[21] = target_BD_ADDR[1];
|
||||||
Advertising_Data.data[22] = target_BD_ADDR[2],
|
Advertising_Data.data[22] = target_BD_ADDR[2];
|
||||||
Advertising_Data.data[23] = target_BD_ADDR[3],
|
Advertising_Data.data[23] = target_BD_ADDR[3];
|
||||||
Advertising_Data.data[24] = target_BD_ADDR[4],
|
Advertising_Data.data[24] = target_BD_ADDR[4];
|
||||||
Advertising_Data.data[25] = target_BD_ADDR[5],
|
Advertising_Data.data[25] = target_BD_ADDR[5];
|
||||||
Advertising_Data.data[26] = 0xFF;
|
Advertising_Data.data[26] = 0xFF;
|
||||||
Advertising_Data.data[27] = 0xFF;
|
Advertising_Data.data[27] = 0xFF;
|
||||||
Advertising_Data.data[28] = 0xFF;
|
Advertising_Data.data[28] = 0xFF;
|
||||||
|
@ -257,6 +259,168 @@ 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)
|
||||||
|
{
|
||||||
|
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] = 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!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS)
|
||||||
|
{
|
||||||
|
KLOG_ERROR(KLOG_TAG, "Couldn't scan and advertise!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
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 BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[6])
|
||||||
{
|
{
|
||||||
bool for_me = false;
|
bool for_me = false;
|
||||||
|
@ -286,12 +450,12 @@ bool BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[6])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this the broadcast address?
|
// Is this the broadcast address?
|
||||||
if ((BD_ADDR[0] == 0xFF) &&
|
if ((BD_ADDR[0] == BLE_BROADCAST_ADDRESS[0]) &&
|
||||||
(BD_ADDR[1] == 0xFF) &&
|
(BD_ADDR[1] == BLE_BROADCAST_ADDRESS[1]) &&
|
||||||
(BD_ADDR[2] == 0xFF) &&
|
(BD_ADDR[2] == BLE_BROADCAST_ADDRESS[2]) &&
|
||||||
(BD_ADDR[3] == 0xFF) &&
|
(BD_ADDR[3] == BLE_BROADCAST_ADDRESS[3]) &&
|
||||||
(BD_ADDR[4] == 0xFF) &&
|
(BD_ADDR[4] == BLE_BROADCAST_ADDRESS[4]) &&
|
||||||
(BD_ADDR[5] == 0xFF))
|
(BD_ADDR[5] == BLE_BROADCAST_ADDRESS[5]))
|
||||||
{
|
{
|
||||||
for_me = true;
|
for_me = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,8 @@
|
||||||
#define BLE_PACKETS_H
|
#define BLE_PACKETS_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C"
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Preprocessor and Type Definitions */
|
/* Preprocessor and Type Definitions */
|
||||||
|
@ -59,11 +60,13 @@ typedef enum
|
||||||
BLE_PACKET_TYPE_BUFFER_FREE = 0,
|
BLE_PACKET_TYPE_BUFFER_FREE = 0,
|
||||||
BLE_PACKET_TYPE_INSTIGATE_GAME = 1,
|
BLE_PACKET_TYPE_INSTIGATE_GAME = 1,
|
||||||
BLE_FIRST_VALID_PACKET_TYPE = BLE_PACKET_TYPE_INSTIGATE_GAME,
|
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_TAG = 3,
|
||||||
BLE_PACKET_TYPE_CONSOLE = 4,
|
BLE_PACKET_TYPE_CONSOLE = 4,
|
||||||
BLE_PACKET_TYPE_STATUS = 5,
|
BLE_PACKET_TYPE_STATUS = 5,
|
||||||
BLE_LAST_VALID_PACKET_TYPE = BLE_PACKET_TYPE_STATUS,
|
BLE_PACKET_TYPE_PARAMETERS = 6,
|
||||||
|
BLE_PACKET_TYPE_HELLO = 7,
|
||||||
|
BLE_LAST_VALID_PACKET_TYPE = BLE_PACKET_TYPE_HELLO,
|
||||||
BLE_PACKET_TYPE_UNKNOWN
|
BLE_PACKET_TYPE_UNKNOWN
|
||||||
} BLE_PacketType_T;
|
} BLE_PacketType_T;
|
||||||
|
|
||||||
|
@ -87,11 +90,20 @@ typedef struct
|
||||||
|
|
||||||
uint32_t game_length_in_ms;
|
uint32_t game_length_in_ms;
|
||||||
uint32_t time_remaining_until_countdown_in_ms;
|
uint32_t time_remaining_until_countdown_in_ms;
|
||||||
uint8_t random_time_after_countdown_in_ms_x100;
|
uint8_t unused[13];
|
||||||
uint8_t unused[12];
|
|
||||||
} __attribute__((packed, aligned(1))) BLE_InstigationPacket_T;
|
} __attribute__((packed, aligned(1))) BLE_InstigationPacket_T;
|
||||||
|
|
||||||
//! Contents of the BLE packet #BLE_PACKET_TYPE_JOIN_NOW.
|
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
|
typedef struct
|
||||||
{
|
{
|
||||||
BLE_PacketType_T type;
|
BLE_PacketType_T type;
|
||||||
|
@ -99,10 +111,11 @@ typedef struct
|
||||||
int8_t RSSI;
|
int8_t RSSI;
|
||||||
uint8_t event_number;
|
uint8_t event_number;
|
||||||
|
|
||||||
uint32_t game_length_in_ms;
|
uint8_t target_BD_ADDR[BD_ADDR_SIZE];
|
||||||
uint32_t time_remaining_in_game_in_ms;
|
uint32_t event_ID;
|
||||||
uint8_t unused[13];
|
uint32_t event_data;
|
||||||
} __attribute__((packed, aligned(1))) BLE_JoinNowPacket_T;
|
uint8_t unused[7];
|
||||||
|
} __attribute__((packed, aligned(1))) BLE_EventPacket_T;
|
||||||
|
|
||||||
//! Contents of the BLE packet #BLE_PACKET_TYPE_TAG.
|
//! Contents of the BLE packet #BLE_PACKET_TYPE_TAG.
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -149,17 +162,116 @@ typedef struct
|
||||||
uint16_t maximum_health;
|
uint16_t maximum_health;
|
||||||
color_t primary_color;
|
color_t primary_color;
|
||||||
color_t secondary_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;
|
} __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_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_ParameterKey_T BLE_GetValidConfigKey(uint16_t key)
|
||||||
|
{
|
||||||
|
BLE_ParameterKey_T result = BLE_PARAMETER_KEY_NONE;
|
||||||
|
|
||||||
|
if ((key >= BLE_FIRST_VALID_CONFIGURATION_KEY) &&
|
||||||
|
(key <= BLE_LAST_VALID_CONFIGURATION_KEY))
|
||||||
|
{
|
||||||
|
result = (BLE_ParameterKey_T)key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
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_ParametersPacket_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
|
typedef union
|
||||||
{
|
{
|
||||||
BLE_GenericPacketType_T Generic;
|
BLE_GenericPacketType_T Generic;
|
||||||
BLE_InstigationPacket_T Instigation;
|
BLE_InstigationPacket_T Instigation;
|
||||||
BLE_JoinNowPacket_T JoinNow;
|
BLE_EventPacket_T Event;
|
||||||
BLE_TagPacket_T Tag;
|
BLE_TagPacket_T Tag;
|
||||||
BLE_ConsolePacket_T Console;
|
BLE_ConsolePacket_T Console;
|
||||||
BLE_StatusPacket_T Status;
|
BLE_StatusPacket_T Status;
|
||||||
|
BLE_ParametersPacket_T Configuration;
|
||||||
|
BLE_HelloPacket_T Hello;
|
||||||
} BLE_Packet_T;
|
} BLE_Packet_T;
|
||||||
|
|
||||||
/* Include Files */
|
/* Include Files */
|
||||||
|
@ -168,11 +280,11 @@ typedef union
|
||||||
|
|
||||||
/* Public Functions */
|
/* Public Functions */
|
||||||
|
|
||||||
inline void BLE_FreePacketBuffer(void * buffer)
|
inline void BLE_FreePacketBuffer(BLE_GenericPacketType_T *buffer)
|
||||||
{
|
{
|
||||||
if (buffer != NULL)
|
if (buffer != NULL)
|
||||||
{
|
{
|
||||||
((BLE_GenericPacketType_T *)buffer)->type = BLE_PACKET_TYPE_BUFFER_FREE;
|
buffer->type = BLE_PACKET_TYPE_BUFFER_FREE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,8 +292,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);
|
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_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_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]);
|
bool BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[BD_ADDR_SIZE]);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
54
BLE/BLE_Utils.c
Normal file
54
BLE/BLE_Utils.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of SystemK, a library in the KTag project.
|
||||||
|
*
|
||||||
|
* 🛡️ <https://ktag.clubk.club> 🃞
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
* \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[5-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;
|
||||||
|
}
|
24
BLE/BLE_Utils.h
Normal file
24
BLE/BLE_Utils.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of SystemK, a library in the KTag project.
|
||||||
|
*
|
||||||
|
* 🛡️ <https://ktag.clubk.club> 🃞
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern const uint8_t BLE_BROADCAST_ADDRESS[6];
|
||||||
|
|
||||||
|
const char* BLE_ADDR_To_Str(const uint8_t bd_addr[6]);
|
|
@ -2,6 +2,7 @@ idf_component_register(
|
||||||
SRCS
|
SRCS
|
||||||
"BLE/BLE_Packets.c"
|
"BLE/BLE_Packets.c"
|
||||||
"BLE/BLE_Packet_Tracker.c"
|
"BLE/BLE_Packet_Tracker.c"
|
||||||
|
"BLE/BLE_Utils.c"
|
||||||
"Events/KEvents.c"
|
"Events/KEvents.c"
|
||||||
"Game/Game.c"
|
"Game/Game.c"
|
||||||
"Game/Weapons.c"
|
"Game/Weapons.c"
|
||||||
|
|
|
@ -79,6 +79,8 @@ typedef enum
|
||||||
KEVENT_AUDIO_COMPLETED = 36,
|
KEVENT_AUDIO_COMPLETED = 36,
|
||||||
KEVENT_GAME_OVER = 37,
|
KEVENT_GAME_OVER = 37,
|
||||||
KEVENT_PLAY_PRESSED_ON_REMOTE = 38,
|
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 is one more than the last valid event.
|
||||||
KEVENT_IS_OUT_OF_RANGE
|
KEVENT_IS_OUT_OF_RANGE
|
||||||
} KEvent_ID_T;
|
} KEvent_ID_T;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
66
Game/Game.h
66
Game/Game.h
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -44,6 +42,18 @@ typedef enum
|
||||||
MAXIMUM_TEAM_ID = 7
|
MAXIMUM_TEAM_ID = 7
|
||||||
} TeamID_t;
|
} 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)
|
__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*.
|
static uint8_t Team_ID = 0; // This is static because AUDIO_PRONOUNCE_NUMBER_0_TO_100 needs a *pointer*.
|
||||||
|
@ -77,6 +87,27 @@ __attribute__((always_inline)) inline TeamID_t Resolve_Common_Team_ID(uint8_t te
|
||||||
return (team_ID & COMMON_TEAM_ID_MASK);
|
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)
|
__attribute__((always_inline)) inline bool Team_Can_Tag_Me(uint8_t tagging_team_ID)
|
||||||
{
|
{
|
||||||
bool can_tag = false;
|
bool can_tag = false;
|
||||||
|
@ -104,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;
|
||||||
|
@ -130,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)
|
||||||
|
|
|
@ -158,7 +158,7 @@ Weapon_t WeaponsByID[NUMBER_OF_WEAPONS] =
|
||||||
|
|
||||||
// The Dubuque Protocol
|
// The Dubuque Protocol
|
||||||
{
|
{
|
||||||
.ID = LASER_X_ID,
|
.ID = DUBUQUE_PROTOCOL_ID,
|
||||||
.Type = ENERGY,
|
.Type = ENERGY,
|
||||||
.Protocol = DUBUQUE_PROTOCOL,
|
.Protocol = DUBUQUE_PROTOCOL,
|
||||||
.Damage_Per_Shot = 1,
|
.Damage_Per_Shot = 1,
|
||||||
|
|
|
@ -109,9 +109,9 @@ static inline void PackPulseTrain(TimedPulseTrain_T *pulsetrain, uint32_t data)
|
||||||
|
|
||||||
TimedPulseTrain_T *NEC_EncodePacket(CommandPacket_T *packet)
|
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;
|
return &Command_Send_Buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,20 +22,29 @@
|
||||||
#ifndef SETTINGS_INTERFACE_H
|
#ifndef SETTINGS_INTERFACE_H
|
||||||
#define SETTINGS_INTERFACE_H
|
#define SETTINGS_INTERFACE_H
|
||||||
|
|
||||||
|
#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_T_START_GAME_in_ms
|
SYSTEMK_SETTING_MAX_HEALTH,
|
||||||
|
SYSTEMK_SETTING_N_SPECIAL_WEAPONS_ON_REENTRY,
|
||||||
|
SYSTEMK_SETTING_T_START_GAME_in_ms,
|
||||||
|
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);
|
||||||
SystemKResult_T SETTINGS_set_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_get_uint32_t(SystemKSettingID_T id, uint32_t * value);
|
||||||
SystemKResult_T SETTINGS_set_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);
|
SystemKResult_T SETTINGS_Save(void);
|
||||||
|
|
||||||
#endif // SETTINGS_INTERFACE_H
|
#endif // SETTINGS_INTERFACE_H
|
||||||
|
|
|
@ -37,7 +37,8 @@ static const int_fast8_t TAG_RSSI_THRESHOLD = -75;
|
||||||
|
|
||||||
static void BLEStatusTimerCallback(TimerHandle_t xTimer)
|
static void BLEStatusTimerCallback(TimerHandle_t xTimer)
|
||||||
{
|
{
|
||||||
BLE_UpdateStatusPacket();
|
StateMachineContext_T* context = GetContext();
|
||||||
|
BLE_UpdateStatusPacket(context->States.Current_State);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GameDurationTimerCallback(TimerHandle_t xTimer)
|
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_RXd_data.neighbors[slot].TimeToLive_in_ms = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLE_UpdateStatusPacket();
|
BLE_UpdateStatusPacket(context->States.Current_State);
|
||||||
if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS)
|
if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS)
|
||||||
{
|
{
|
||||||
KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!");
|
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.
|
// 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)
|
if (GameDurationTimer == NULL)
|
||||||
{
|
{
|
||||||
|
@ -129,7 +131,7 @@ void Playing_Exit(StateMachineContext_T *context)
|
||||||
{
|
{
|
||||||
LOG("Exiting the Playing state.");
|
LOG("Exiting the Playing state.");
|
||||||
xTimerStop(BLEStatusTimer, portMAX_DELAY);
|
xTimerStop(BLEStatusTimer, portMAX_DELAY);
|
||||||
BLE_UpdateStatusPacket();
|
BLE_UpdateStatusPacket(context->States.Next_State);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleBLEStatusPacket(const BLE_StatusPacket_T *const packet)
|
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};
|
// NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_BLE_NEARBY, .Data = (void *)&BLE_RXd_data, .Prominence = NEOPIXELS_BACKGROUND};
|
||||||
// xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
// xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
||||||
|
|
||||||
|
BLE_FreePacketBuffer((BLE_GenericPacketType_T *)packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleBLETagPacket(const BLE_TagPacket_T *const packet)
|
void HandleBLETagPacket(const BLE_TagPacket_T *const packet)
|
||||||
|
@ -202,7 +206,11 @@ void HandleBLETagPacket(const BLE_TagPacket_T *const packet)
|
||||||
{
|
{
|
||||||
if (BLE_IsPacketNew(packet->BD_ADDR, BLE_PACKET_TYPE_TAG, packet->event_number))
|
if (BLE_IsPacketNew(packet->BD_ADDR, BLE_PACKET_TYPE_TAG, packet->event_number))
|
||||||
{
|
{
|
||||||
|
Health_In_Percent = (int16_t)Get_Health();
|
||||||
|
|
||||||
if (packet->damage > 0)
|
if (packet->damage > 0)
|
||||||
|
{
|
||||||
|
if (Health_In_Percent > 0)
|
||||||
{
|
{
|
||||||
Reduce_Health(packet->damage);
|
Reduce_Health(packet->damage);
|
||||||
|
|
||||||
|
@ -214,17 +222,15 @@ void HandleBLETagPacket(const BLE_TagPacket_T *const packet)
|
||||||
NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_TAG_RECEIVED, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)&ReceivedTagColor};
|
NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_TAG_RECEIVED, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)&ReceivedTagColor};
|
||||||
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (packet->damage < 0)
|
else if (packet->damage < 0)
|
||||||
{
|
{
|
||||||
Health_In_Percent = (uint8_t)Get_Health();
|
|
||||||
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);
|
||||||
|
@ -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);
|
Playing_Entry(context);
|
||||||
srand(xTaskGetTickCount());
|
srand(xTaskGetTickCount());
|
||||||
}
|
}
|
||||||
|
BLE_UpdateStatusPacket(STATE_PLAYING__INTERACTING);
|
||||||
LOG("Entering the Interacting substate of the Playing state.");
|
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);
|
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
||||||
|
|
||||||
Increment_Tags_Received();
|
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)
|
else if (player_ID != my_player_ID)
|
||||||
|
@ -344,14 +349,7 @@ static void Playing__Interacting_Do(StateMachineContext_T * context)
|
||||||
|
|
||||||
case KEVENT_BLE_PACKET_RECEIVED:
|
case KEVENT_BLE_PACKET_RECEIVED:
|
||||||
#ifdef LOG_INTERACTING_SUBSTATE
|
#ifdef LOG_INTERACTING_SUBSTATE
|
||||||
//KLOG_INFO(KLOG_TAG, "KEVENT_BLE_PACKET_RECEIVED from %02X:%02X:%02X:%02X:%02X:%02X",
|
//KLOG_INFO(KLOG_TAG, "KEVENT_BLE_PACKET_RECEIVED from %s", BLE_ADDR_To_Str(((BLE_Packet_T *)Event.Data)->Generic.BD_ADDR));
|
||||||
// ((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]
|
|
||||||
//);
|
|
||||||
#endif // LOG_INTERACTING_SUBSTATE
|
#endif // LOG_INTERACTING_SUBSTATE
|
||||||
if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_STATUS)
|
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);
|
HandleBLETagPacket((BLE_TagPacket_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);
|
BLE_FreePacketBuffer(Event.Data);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEVENT_ACCESSORY_SWITCH_PRESSED:
|
case KEVENT_ACCESSORY_SWITCH_PRESSED:
|
||||||
|
@ -398,7 +402,7 @@ static void Playing__Interacting_Do(StateMachineContext_T * context)
|
||||||
|
|
||||||
case KEVENT_GAME_OVER:
|
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);
|
Perform_Audio_Action(&audio_action);
|
||||||
Transition_For_Event(context, STATE_WRAPPING_UP, &Event);
|
Transition_For_Event(context, STATE_WRAPPING_UP, &Event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -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};
|
NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_TAGGED_OUT, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00};
|
||||||
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
||||||
|
|
||||||
BLE_UpdateStatusPacket();
|
BLE_UpdateStatusPacket(STATE_PLAYING__TAGGED_OUT);
|
||||||
|
|
||||||
Increment_Times_Tagged_Out();
|
Increment_Times_Tagged_Out();
|
||||||
}
|
}
|
||||||
|
@ -78,11 +94,14 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT)
|
||||||
|
{
|
||||||
|
HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data, context);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BLE_FreePacketBuffer(Event.Data);
|
BLE_FreePacketBuffer(Event.Data);
|
||||||
|
@ -97,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,16 +125,15 @@ static void Playing__Tagged_Out_Do(StateMachineContext_T * context)
|
||||||
|
|
||||||
case KEVENT_GAME_OVER:
|
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);
|
Perform_Audio_Action(&audio_action);
|
||||||
Transition_For_Event(context, STATE_WRAPPING_UP, &Event);
|
Transition_For_Event(context, STATE_WRAPPING_UP, &Event);
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -26,6 +26,18 @@ static void Configuring_Entry(StateMachineContext_T *context);
|
||||||
static void Configuring_Do(StateMachineContext_T *context);
|
static void Configuring_Do(StateMachineContext_T *context);
|
||||||
static void Configuring_Exit(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
|
#define MAX_MENU_DEPTH 10
|
||||||
static MenuItem_T const *CurrentMenuItem;
|
static MenuItem_T const *CurrentMenuItem;
|
||||||
static uint8_t MenuItemHistoryIndex = 0;
|
static uint8_t MenuItemHistoryIndex = 0;
|
||||||
|
@ -40,7 +52,8 @@ const StateActivity_T STATE_CONFIGURING_Activities =
|
||||||
{
|
{
|
||||||
.Entry = Configuring_Entry,
|
.Entry = Configuring_Entry,
|
||||||
.Do = Configuring_Do,
|
.Do = Configuring_Do,
|
||||||
.Exit = Configuring_Exit};
|
.Exit = Configuring_Exit
|
||||||
|
};
|
||||||
|
|
||||||
//! Sets up the Configuring state.
|
//! 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};
|
NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_MENU, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00};
|
||||||
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
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)
|
if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS)
|
||||||
{
|
{
|
||||||
KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!");
|
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.
|
// Reset the menu.
|
||||||
CurrentMenuItem = RootMenu;
|
CurrentMenuItem = RootMenu;
|
||||||
MenuItemHistory[MenuItemHistoryIndex] = CurrentMenuItem;
|
MenuItemHistory[MenuItemHistoryIndex] = CurrentMenuItem;
|
||||||
|
@ -72,6 +108,13 @@ static void Configuring_Do(StateMachineContext_T *context)
|
||||||
portBASE_TYPE xStatus;
|
portBASE_TYPE xStatus;
|
||||||
static KEvent_T Event;
|
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);
|
xStatus = Receive_KEvent(&Event);
|
||||||
|
|
||||||
if (xStatus == pdPASS)
|
if (xStatus == pdPASS)
|
||||||
|
@ -150,6 +193,7 @@ static void Configuring_Do(StateMachineContext_T *context)
|
||||||
CurrentMenuItem->OnFocus(true);
|
CurrentMenuItem->OnFocus(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BLE_UpdateHelloPacket();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEVENT_TRIGGER_SWITCH_RELEASED:
|
case KEVENT_TRIGGER_SWITCH_RELEASED:
|
||||||
|
@ -180,6 +224,8 @@ static void Configuring_Do(StateMachineContext_T *context)
|
||||||
{
|
{
|
||||||
KLOG_WARN(KLOG_TAG, "Failed to increment team!");
|
KLOG_WARN(KLOG_TAG, "Failed to increment team!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BLE_UpdateHelloPacket();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -191,6 +237,21 @@ static void Configuring_Do(StateMachineContext_T *context)
|
||||||
Transition_For_Event(context, STATE_REPROGRAMMING, &Event);
|
Transition_For_Event(context, STATE_REPROGRAMMING, &Event);
|
||||||
break;
|
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:
|
default:
|
||||||
// All other events are ignored in this state.
|
// All other events are ignored in this state.
|
||||||
ProcessUnhandledEvent(&Event);
|
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};
|
NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_ALL_OFF, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00};
|
||||||
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
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)
|
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};
|
NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_TEST_PATTERN, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00};
|
||||||
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
||||||
AudioAction_T audio_action = {.ID = AUDIO_PLAY_STARTUP_SOUND, .Play_To_Completion = true, .Data = (void *)0x00};
|
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;
|
uint8_t weapon_ID = NERF_LASER_STRIKE_BLASTER_ID;
|
||||||
(void) SETTINGS_set_uint8_t(SYSTEMK_SETTING_WEAPONID, weapon_ID);
|
(void) SETTINGS_set_uint8_t(SYSTEMK_SETTING_WEAPONID, weapon_ID);
|
||||||
(void) SETTINGS_Save();
|
(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 Files */
|
||||||
#include "SystemK.h"
|
#include "SystemK.h"
|
||||||
|
|
||||||
const StateActivity_T STATE_DEFAULT_Activities =
|
|
||||||
{
|
|
||||||
.Entry = NULL,
|
|
||||||
.Do = NULL,
|
|
||||||
.Exit = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Activities for the top-level state machine.
|
//! Activities for the top-level state machine.
|
||||||
/*!
|
/*!
|
||||||
* This array is indexed by #StateID_T (except there is no entry for
|
* 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[] =
|
static const StateActivity_T * Activities[] =
|
||||||
{
|
{
|
||||||
&STATE_DEFAULT_Activities,
|
|
||||||
&STATE_INITIALIZING_Activities,
|
&STATE_INITIALIZING_Activities,
|
||||||
&STATE_REPROGRAMMING_Activities,
|
&STATE_REPROGRAMMING_Activities,
|
||||||
&STATE_CONFIGURING_Activities,
|
&STATE_CONFIGURING_Activities,
|
||||||
|
@ -62,6 +54,11 @@ static StateMachineContext_T Context =
|
||||||
.Time_At_State_Entry_In_Ticks = 0,
|
.Time_At_State_Entry_In_Ticks = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StateMachineContext_T* GetContext()
|
||||||
|
{
|
||||||
|
return &Context;
|
||||||
|
}
|
||||||
|
|
||||||
TaskHandle_t State_Machine_Task_Handle;
|
TaskHandle_t State_Machine_Task_Handle;
|
||||||
|
|
||||||
void State_Machine_Task(void * pvParameters)
|
void State_Machine_Task(void * pvParameters)
|
||||||
|
@ -131,3 +128,70 @@ void ProcessUnhandledEvent(KEvent_T * Event)
|
||||||
break;
|
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
|
typedef enum
|
||||||
{
|
{
|
||||||
STATE_DEFAULT = 0,
|
STATE_INITIALIZING = 0,
|
||||||
STATE_INITIALIZING = 1,
|
STATE_REPROGRAMMING = 1,
|
||||||
STATE_REPROGRAMMING = 2,
|
STATE_CONFIGURING = 2,
|
||||||
STATE_CONFIGURING = 3,
|
STATE_READY = 3,
|
||||||
STATE_READY = 4,
|
|
||||||
|
|
||||||
// Substates of STATE_STARTING_GAME
|
// Substates of STATE_STARTING_GAME
|
||||||
STATE_STARTING_GAME__INSTIGATING = 5,
|
STATE_STARTING_GAME__INSTIGATING = 4,
|
||||||
STATE_STARTING_GAME__RESPONDING = 6,
|
STATE_STARTING_GAME__RESPONDING = 5,
|
||||||
STATE_STARTING_GAME__COUNTING_DOWN = 7,
|
STATE_STARTING_GAME__COUNTING_DOWN = 6,
|
||||||
|
|
||||||
// Substates of STATE_PLAYING
|
// Substates of STATE_PLAYING
|
||||||
STATE_PLAYING__INTERACTING = 8,
|
STATE_PLAYING__INTERACTING = 7,
|
||||||
STATE_PLAYING__TAGGED_OUT = 9,
|
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 is one more than the last valid state.
|
||||||
STATE_IS_OUT_OF_RANGE,
|
STATE_IS_OUT_OF_RANGE,
|
||||||
|
@ -107,6 +106,7 @@ extern TaskHandle_t State_Machine_Task_Handle;
|
||||||
|
|
||||||
void State_Machine_Task(void * pvParameters);
|
void State_Machine_Task(void * pvParameters);
|
||||||
void ProcessUnhandledEvent(KEvent_T * Event);
|
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)
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StateMachineContext_T* GetContext();
|
||||||
|
|
||||||
#include "State_Configuring.h"
|
#include "State_Configuring.h"
|
||||||
#include "State_Ready.h"
|
#include "State_Ready.h"
|
||||||
#include "State_Initializing.h"
|
#include "State_Initializing.h"
|
||||||
|
|
|
@ -47,13 +47,15 @@ static void Ready_Entry(StateMachineContext_T * context)
|
||||||
LOG("Entering the Ready state.");
|
LOG("Entering the Ready state.");
|
||||||
NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_IDLE, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00};
|
NeoPixelsAction_T neopixels_action = {.ID = NEOPIXELS_IDLE, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00};
|
||||||
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
||||||
BLE_UpdateStatusPacket();
|
BLE_UpdateStatusPacket(STATE_READY);
|
||||||
if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS)
|
if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS)
|
||||||
{
|
{
|
||||||
KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!");
|
KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!");
|
||||||
}
|
}
|
||||||
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(Get_Max_Health());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Executes the Ready state.
|
//! Executes the Ready state.
|
||||||
|
@ -90,6 +92,10 @@ static void Ready_Do(StateMachineContext_T * context)
|
||||||
{
|
{
|
||||||
Transition_For_Event(context, STATE_STARTING_GAME__RESPONDING, &Event);
|
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
|
else
|
||||||
{
|
{
|
||||||
BLE_FreePacketBuffer(Event.Data);
|
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_Do(StateMachineContext_T * context);
|
||||||
static void Wrapping_Up_Exit(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.
|
//! Activities for the **Wrapping Up** state.
|
||||||
const StateActivity_T STATE_WRAPPING_UP_Activities =
|
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.");
|
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_IDLE, .Prominence = NEOPIXELS_FOREGROUND, .Data = (void *)0x00};
|
||||||
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
xQueueSend(xQueueNeoPixels, &neopixels_action, 0);
|
||||||
BLE_UpdateStatusPacket();
|
BLE_UpdateStatusPacket(STATE_WRAPPING_UP);
|
||||||
if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS)
|
if (BLE_ScanAndAdvertise() != SYSTEMK_RESULT_SUCCESS)
|
||||||
{
|
{
|
||||||
KLOG_ERROR(KLOG_TAG, "Couldn't start BLE!");
|
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.
|
//! Executes the Wrapping Up state.
|
||||||
|
@ -84,8 +109,14 @@ static void Wrapping_Up_Do(StateMachineContext_T * context)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEVENT_BLE_PACKET_RECEIVED:
|
case KEVENT_BLE_PACKET_RECEIVED:
|
||||||
// TODO
|
if (((BLE_Packet_T *)Event.Data)->Generic.type == BLE_PACKET_TYPE_EVENT)
|
||||||
|
{
|
||||||
|
HandleBLEEventPacket((BLE_EventPacket_T *)Event.Data, context);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
BLE_FreePacketBuffer(Event.Data);
|
BLE_FreePacketBuffer(Event.Data);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -70,6 +70,10 @@
|
||||||
#ifndef SYSTEMK_H
|
#ifndef SYSTEMK_H
|
||||||
#define SYSTEMK_H
|
#define SYSTEMK_H
|
||||||
|
|
||||||
|
#define SYSTEMK_MAJOR_VERSION 0
|
||||||
|
#define SYSTEMK_MINOR_VERSION 99
|
||||||
|
#define SYSTEMK_VERSION_STRING "00.99"
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
@ -99,6 +103,7 @@
|
||||||
#include "BLE/BLE_Packets.h"
|
#include "BLE/BLE_Packets.h"
|
||||||
#include "BLE/BLE_Packet_Tracker.h"
|
#include "BLE/BLE_Packet_Tracker.h"
|
||||||
#include "BLE/BLE_HW_Interface.h"
|
#include "BLE/BLE_HW_Interface.h"
|
||||||
|
#include "BLE/BLE_Utils.h"
|
||||||
#include "IR/IR_HW_Interface.h"
|
#include "IR/IR_HW_Interface.h"
|
||||||
#include "States/State_Machine.h"
|
#include "States/State_Machine.h"
|
||||||
#include "Menu/Menu.h"
|
#include "Menu/Menu.h"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue