288 lines
10 KiB
C
288 lines
10 KiB
C
/* Include Files */
|
|
#include "KTag.h"
|
|
|
|
QueueHandle_t xQueueAudio;
|
|
TaskHandle_t Audio_Task_Handle;
|
|
|
|
static const uint8_t START_BYTE = 0x7E;
|
|
static const uint8_t VERSION_BYTE = 0xFF;
|
|
static const uint8_t END_BYTE = 0xEF;
|
|
|
|
// Valid volumes are 0 - 30.
|
|
static const uint8_t COMMAND_SPECIFY_VOLUME = 0x06;
|
|
static const uint8_t COMMAND_PAUSE = 0x0E;
|
|
static const uint8_t COMMAND_PLAY_TRACK_IN_FOLDER = 0x0F;
|
|
|
|
__attribute__((always_inline)) inline uint16_t CalculateChecksum(uint8_t * buffer, uint8_t length)
|
|
{
|
|
uint16_t checksum = 0;
|
|
|
|
for (uint_fast8_t i = 0; i < length; i++)
|
|
{
|
|
checksum += buffer[i];
|
|
}
|
|
|
|
return (0 - checksum);
|
|
}
|
|
|
|
static void Send_Command(uint8_t command, bool requireFeedback, uint16_t parameter)
|
|
{
|
|
uint8_t buffer[10];
|
|
uint16_t checksum;
|
|
|
|
buffer[0] = START_BYTE;
|
|
buffer[1] = VERSION_BYTE;
|
|
buffer[2] = 6; // count
|
|
buffer[3] = command;
|
|
buffer[4] = requireFeedback;
|
|
buffer[5] = (uint8_t)(parameter >> 8);
|
|
buffer[6] = (uint8_t)(parameter);
|
|
|
|
checksum = CalculateChecksum(&buffer[1], 6);
|
|
|
|
buffer[7] = (uint8_t)(checksum >> 8);
|
|
buffer[8] = (uint8_t)(checksum);
|
|
buffer[9] = END_BYTE;
|
|
|
|
for (uint_fast8_t i = 0; i < 10; i++)
|
|
{
|
|
UART_Audio_Put(buffer[i]);
|
|
}
|
|
}
|
|
|
|
SystemKResult_T Perform_Audio_Action(AudioAction_T * action)
|
|
{
|
|
if (xQueueSend(xQueueAudio, action, 0) == pdTRUE)
|
|
{
|
|
return SYSTEMK_RESULT_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return SYSTEMK_RESULT_QUEUE_IS_FULL;
|
|
}
|
|
}
|
|
|
|
void Init_Audio(void)
|
|
{
|
|
UART_Audio_Start();
|
|
|
|
xQueueAudio = xQueueCreate(5, sizeof(AudioAction_T));
|
|
}
|
|
|
|
void Audio_Task(void * pvParameters)
|
|
{
|
|
portBASE_TYPE xStatus;
|
|
|
|
while (IsNVMInitialized() == false)
|
|
{
|
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
|
}
|
|
Send_Command(COMMAND_SPECIFY_VOLUME, false, NVM_VOLUME);
|
|
|
|
while (true)
|
|
{
|
|
AudioAction_T action;
|
|
|
|
xStatus = xQueueReceive(xQueueAudio, &action, 0);
|
|
|
|
if (xStatus == pdPASS)
|
|
{
|
|
switch (action.ID)
|
|
{
|
|
case AUDIO_SET_VOLUME:
|
|
{
|
|
uint8_t volume = *((uint8_t *)action.Data);
|
|
if (volume <= 30)
|
|
{
|
|
Send_Command(COMMAND_SPECIFY_VOLUME, false, volume);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case AUDIO_SILENCE:
|
|
Send_Command(COMMAND_PAUSE, false, 0x0000);
|
|
break;
|
|
|
|
case AUDIO_PLAY_STARTUP_SOUND:
|
|
// Play track "001" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0101);
|
|
break;
|
|
|
|
case AUDIO_PLAY_SHOT_FIRED:
|
|
// Play track "002" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0102);
|
|
break;
|
|
|
|
case AUDIO_PLAY_TAG_RECEIVED:
|
|
// Play track "003" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0103);
|
|
break;
|
|
|
|
case AUDIO_PLAY_TAGGED_OUT:
|
|
// Play track "004" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0104);
|
|
break;
|
|
|
|
case AUDIO_PLAY_MISFIRE:
|
|
// Play track "005" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0105);
|
|
break;
|
|
|
|
case AUDIO_PRONOUNCE_NUMBER_0_TO_100:
|
|
{
|
|
uint8_t file_index = *((uint8_t *)action.Data);
|
|
if (file_index > 100)
|
|
{
|
|
file_index = 100;
|
|
}
|
|
else if (file_index == 0)
|
|
{
|
|
file_index = 101;
|
|
}
|
|
// The numbers are stored in folder "10".
|
|
// 001.mp3 is "one", 100.mp3 is "one hundred", and 101.mp3 is "zero".
|
|
uint16_t filenumber = 0x0A00 + file_index;
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, filenumber);
|
|
}
|
|
break;
|
|
|
|
case AUDIO_PLAY_MENU_PROMPT:
|
|
// Play track "006" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0106);
|
|
break;
|
|
|
|
case AUDIO_PLAY_SELECTION_INDICATOR:
|
|
// Play track "007" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0107);
|
|
break;
|
|
|
|
case AUDIO_PLAY_HEALTH_REMAINING:
|
|
// Play track "008" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0108);
|
|
break;
|
|
|
|
case AUDIO_PLAY_ELECTRONIC_DANCE_MUSIC:
|
|
// Play track "009" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0109);
|
|
break;
|
|
|
|
default:
|
|
case AUDIO_PLAY_GENERIC_ERROR:
|
|
// Play track "010" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x010A);
|
|
break;
|
|
|
|
case AUDIO_PLAY_VOLUME_PROMPT:
|
|
// Play track "011" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x010B);
|
|
break;
|
|
|
|
case AUDIO_PLAY_RIGHT_HANDED:
|
|
// Play track "012" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x010C);
|
|
break;
|
|
|
|
case AUDIO_PLAY_LEFT_HANDED:
|
|
// Play track "013" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x010D);
|
|
break;
|
|
|
|
case AUDIO_PLAY_GAME_ON:
|
|
// Play track "014" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x010E);
|
|
break;
|
|
|
|
case AUDIO_PLAY_HARDWARE_SETTINGS_PROMPT:
|
|
// Play track "015" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x010F);
|
|
break;
|
|
|
|
case AUDIO_PLAY_GAME_SETTINGS_PROMPT:
|
|
// Play track "016" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0110);
|
|
break;
|
|
|
|
case AUDIO_PLAY_BONK:
|
|
// Play track "017" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0111);
|
|
break;
|
|
|
|
case AUDIO_PLAY_NEAR_MISS:
|
|
// Play track "018" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0112);
|
|
break;
|
|
|
|
case AUDIO_PLAY_PLAYER_ID_PROMPT:
|
|
// Play track "019" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0113);
|
|
break;
|
|
|
|
case AUDIO_PLAY_TEAM_ID_PROMPT:
|
|
// Play track "020" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0114);
|
|
break;
|
|
|
|
case AUDIO_PLAY_FRIENDLY_FIRE:
|
|
// Play track "021" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0115);
|
|
break;
|
|
|
|
case AUDIO_PLAY_STARTING_THEME:
|
|
// Play track "022" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0116);
|
|
break;
|
|
|
|
case AUDIO_PLAY_BOOP:
|
|
// Play track "023" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0117);
|
|
break;
|
|
|
|
case AUDIO_PLAY_BEEP:
|
|
// Play track "024" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0118);
|
|
break;
|
|
|
|
case AUDIO_PLAY_REPROGRAMMING:
|
|
// Play track "025" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x0119);
|
|
break;
|
|
|
|
case AUDIO_PLAY_BOMB:
|
|
// Play track "026" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x011A);
|
|
break;
|
|
|
|
case AUDIO_PLAY_GAME_OVER:
|
|
// Play track "027" in folder "01".
|
|
Send_Command(COMMAND_PLAY_TRACK_IN_FOLDER, false, 0x011B);
|
|
break;
|
|
}
|
|
|
|
if (action.Play_To_Completion == true)
|
|
{
|
|
do
|
|
{
|
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
|
} while (Is_Audio_Playing() == true);
|
|
|
|
KEvent_T command_received_event = {.ID = KEVENT_AUDIO_COMPLETED, .Data = (void *)action.ID};
|
|
Post_KEvent(&command_received_event);
|
|
}
|
|
}
|
|
|
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
|
}
|
|
}
|
|
|
|
bool Is_Audio_Playing()
|
|
{
|
|
bool result = false;
|
|
|
|
// The signal is active low.
|
|
if (Cy_GPIO_Read(Pin_Audio_Busy_PORT, Pin_Audio_Busy_NUM) == 0)
|
|
{
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|