Initial public release of SystemK.

This commit is contained in:
Joe Kearney 2025-01-25 13:45:14 -06:00
parent 387f57cdda
commit 6f51f5b006
129 changed files with 11654 additions and 2 deletions

301
BLE/BLE_Packets.c Normal file
View file

@ -0,0 +1,301 @@
/*
* This program source code file is part of SystemK, a library in the KTag project.
*
* 🛡 <https://ktag.clubk.club> 🃞
*
* Copyright © 2016-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 <string.h>
#include "SystemK.h"
#define N_PACKET_BUFFERS 10
static BLE_Packet_T Packet_Buffers[N_PACKET_BUFFERS];
static BLE_AdvertisingData_T Advertising_Data;
static uint8_t my_BD_ADDR[6];
static bool is_my_BD_ADDR_initialized = false;
static const char *KLOG_TAG = "BLE";
void BLE_InitPacketBuffers(void)
{
for (uint_fast8_t i = 0; i < N_PACKET_BUFFERS; i++)
{
Packet_Buffers[i].Generic.type = BLE_PACKET_TYPE_BUFFER_FREE;
}
}
//! This function always returns a buffer, but it will clobber data if there are no free buffers.
static inline BLE_Packet_T * BLE_GetPacketBuffer(void)
{
for (uint_fast8_t i = 0; i < N_PACKET_BUFFERS; i++)
{
if (Packet_Buffers[i].Generic.type == BLE_PACKET_TYPE_BUFFER_FREE)
{
return &Packet_Buffers[i];
}
}
KLOG_ERROR(KLOG_TAG, "Overwrote a BLE packet buffer: consider increasing N_PACKET_BUFFERS.");
// Just use the last one.
return &Packet_Buffers[N_PACKET_BUFFERS - 1];
}
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 * result = NULL;
// All KTag packets are 31 bytes long.
if (received_data_length == BLE_KTAG_PACKET_TOTAL_SIZE)
{
// Is this a KTag packet?
if ( (received_data[0] == 0x1E) &&
(received_data[1] == 0xFF) &&
(received_data[2] == 0xFF) &&
(received_data[3] == 0xFF) &&
(received_data[4] == 'K') &&
(received_data[5] == 'T') &&
(received_data[6] == 'a') &&
(received_data[7] == 'g') )
{
result = BLE_GetPacketBuffer();
memcpy(result->Generic.BD_ADDR, peer_BD_ADDR, BD_ADDR_SIZE);
result->Generic.RSSI = rssi_in_dBm;
uint8_t packet_type = received_data[8];
// Validate the packet type.
if ( (packet_type < BLE_FIRST_VALID_PACKET_TYPE) ||
(packet_type > BLE_LAST_VALID_PACKET_TYPE) )
{
packet_type = BLE_PACKET_TYPE_UNKNOWN;
}
result->Generic.type = packet_type;
uint8_t event_number = received_data[9];
result->Generic.event_number = event_number;
// Copy the remaining MAX_BLE_PACKET_DATA_SIZE bytes of data over.
memcpy(result->Generic.data, &received_data[10], BLE_KTAG_PACKET_DATA_SIZE);
}
}
return result;
}
void BLE_UpdateInstigationPacket(uint32_t Game_Length_in_ms, uint32_t Time_Remaining_Until_Countdown_in_ms)
{
static uint8_t EventNumber = 0;
Advertising_Data.length = BLE_KTAG_PACKET_TOTAL_SIZE;
// Manufacturer Specific Data
Advertising_Data.data[0] = 0x1E;
Advertising_Data.data[1] = 0xFF;
Advertising_Data.data[2] = 0xFF;
Advertising_Data.data[3] = 0xFF;
Advertising_Data.data[4] = 'K';
Advertising_Data.data[5] = 'T';
Advertising_Data.data[6] = 'a';
Advertising_Data.data[7] = 'g';
Advertising_Data.data[8] = BLE_PACKET_TYPE_INSTIGATE_GAME;
Advertising_Data.data[9] = EventNumber++;
Advertising_Data.data[10] = (Game_Length_in_ms >> 0) & 0xFF;
Advertising_Data.data[11] = (Game_Length_in_ms >> 8) & 0xFF;
Advertising_Data.data[12] = (Game_Length_in_ms >> 16) & 0xFF;
Advertising_Data.data[13] = (Game_Length_in_ms >> 24) & 0xFF;
Advertising_Data.data[14] = (Time_Remaining_Until_Countdown_in_ms >> 0) & 0xFF;
Advertising_Data.data[15] = (Time_Remaining_Until_Countdown_in_ms >> 8) & 0xFF;
Advertising_Data.data[16] = (Time_Remaining_Until_Countdown_in_ms >> 16) & 0xFF;
Advertising_Data.data[17] = (Time_Remaining_Until_Countdown_in_ms >> 24) & 0xFF;
Advertising_Data.data[18] = 0x00;
Advertising_Data.data[19] = 0xFF;
Advertising_Data.data[20] = 0xFF;
Advertising_Data.data[21] = 0xFF;
Advertising_Data.data[22] = 0xFF;
Advertising_Data.data[23] = 0xFF;
Advertising_Data.data[24] = 0xFF;
Advertising_Data.data[25] = 0xFF;
Advertising_Data.data[26] = 0xFF;
Advertising_Data.data[27] = 0xFF;
Advertising_Data.data[28] = 0xFF;
Advertising_Data.data[29] = 0xFF;
Advertising_Data.data[30] = 0xFF;
SystemKResult_T result = BLE_SetAdvertisingData(&Advertising_Data);
if (result != SYSTEMK_RESULT_SUCCESS)
{
KLOG_ERROR(KLOG_TAG, "Error updating instigation packet!");
}
}
void BLE_UpdateStatusPacket()
{
static uint8_t EventNumber = 0;
uint8_t team_ID;
uint8_t player_ID;
uint8_t weapon_ID;
Protocol_T protocol;
(void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_TEAMID, &team_ID);
(void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_PLAYERID, &player_ID);
(void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_WEAPONID, &weapon_ID);
protocol = GetWeaponFromID(weapon_ID).Protocol;
uint32_t Team_Color = (uint32_t)PROTOCOLS_GetColor(protocol, team_ID, player_ID);
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_STATUS;
Advertising_Data.data[9] = EventNumber++;
Advertising_Data.data[10] = 4; // Tx Power in dBm
Advertising_Data.data[11] = DUBUQUE_PROTOCOL;
Advertising_Data.data[12] = team_ID;
Advertising_Data.data[13] = player_ID;
Advertising_Data.data[14] = Get_Health();
Advertising_Data.data[15] = 0x00;
Advertising_Data.data[16] = MAX_HEALTH;
Advertising_Data.data[17] = 0x00;
Advertising_Data.data[18] = (Team_Color >> 0) & 0xFF;
Advertising_Data.data[19] = (Team_Color >> 8) & 0xFF;
Advertising_Data.data[20] = (Team_Color >> 16) & 0xFF;
Advertising_Data.data[21] = (Team_Color >> 24) & 0xFF;
Advertising_Data.data[22] = (Team_Color >> 0) & 0xFF; // Secondary Color
Advertising_Data.data[23] = (Team_Color >> 8) & 0xFF; // Secondary Color
Advertising_Data.data[24] = (Team_Color >> 16) & 0xFF; // Secondary Color
Advertising_Data.data[25] = (Team_Color >> 24) & 0xFF; // Secondary Color
Advertising_Data.data[26] = 0xFF;
Advertising_Data.data[27] = 0xFF;
Advertising_Data.data[28] = 0xFF;
Advertising_Data.data[29] = 0xFF;
Advertising_Data.data[30] = 0xFF;
SystemKResult_T result = BLE_SetAdvertisingData(&Advertising_Data);
if (result != SYSTEMK_RESULT_SUCCESS)
{
KLOG_ERROR(KLOG_TAG, "Error updating status packet!");
}
}
void BLE_UpdateTagPacket(int16_t damage, color_t color, uint8_t target_BD_ADDR[BD_ADDR_SIZE])
{
static uint8_t EventNumber = 0;
uint8_t team_ID;
uint8_t player_ID;
(void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_TEAMID, &team_ID);
(void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_PLAYERID, &player_ID);
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_TAG;
Advertising_Data.data[9] = EventNumber++;
Advertising_Data.data[10] = 4; // Tx Power in dBm
Advertising_Data.data[11] = DUBUQUE_PROTOCOL;
Advertising_Data.data[12] = team_ID;
Advertising_Data.data[13] = player_ID;
Advertising_Data.data[14] = (uint8_t)((damage >> 0) & 0xFF);
Advertising_Data.data[15] = (uint8_t)((damage >> 8) & 0xFF);
Advertising_Data.data[16] = (color >> 0) & 0xFF;
Advertising_Data.data[17] = (color >> 8) & 0xFF;
Advertising_Data.data[18] = (color >> 16) & 0xFF;
Advertising_Data.data[19] = (color >> 24) & 0xFF;
Advertising_Data.data[20] = target_BD_ADDR[0],
Advertising_Data.data[21] = target_BD_ADDR[1],
Advertising_Data.data[22] = target_BD_ADDR[2],
Advertising_Data.data[23] = target_BD_ADDR[3],
Advertising_Data.data[24] = target_BD_ADDR[4],
Advertising_Data.data[25] = target_BD_ADDR[5],
Advertising_Data.data[26] = 0xFF;
Advertising_Data.data[27] = 0xFF;
Advertising_Data.data[28] = 0xFF;
Advertising_Data.data[29] = 0xFF;
Advertising_Data.data[30] = 0xFF;
SystemKResult_T result = BLE_SetAdvertisingData(&Advertising_Data);
if (result != SYSTEMK_RESULT_SUCCESS)
{
KLOG_ERROR(KLOG_TAG, "Error updating status packet!");
}
}
bool BLE_IsBLEPacketForMe(const uint8_t BD_ADDR[6])
{
bool for_me = false;
if (is_my_BD_ADDR_initialized == false)
{
if (BLE_GetMyAddress(my_BD_ADDR) == SYSTEMK_RESULT_SUCCESS)
{
is_my_BD_ADDR_initialized = true;
}
else
{
KLOG_ERROR(KLOG_TAG, "Couldn't get my BD_ADDR!");
}
}
// Is this my address?
if ((is_my_BD_ADDR_initialized == true) &&
(BD_ADDR[0] == my_BD_ADDR[0]) &&
(BD_ADDR[1] == my_BD_ADDR[1]) &&
(BD_ADDR[2] == my_BD_ADDR[2]) &&
(BD_ADDR[3] == my_BD_ADDR[3]) &&
(BD_ADDR[4] == my_BD_ADDR[4]) &&
(BD_ADDR[5] == my_BD_ADDR[5]))
{
for_me = true;
}
// Is this the broadcast address?
if ((BD_ADDR[0] == 0xFF) &&
(BD_ADDR[1] == 0xFF) &&
(BD_ADDR[2] == 0xFF) &&
(BD_ADDR[3] == 0xFF) &&
(BD_ADDR[4] == 0xFF) &&
(BD_ADDR[5] == 0xFF))
{
for_me = true;
}
return for_me;
}