Initial public release.

This commit is contained in:
Joe Kearney 2025-02-01 19:22:12 -06:00
parent 7b169e8116
commit dac4af8d25
255 changed files with 68595 additions and 2 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,79 @@
/** \dir "BLE"
*
* \brief This directory contains source code for managing Bluetooth Low Energy communications.
*
*/
/** \file
* \brief This file defines the interface to the Bluetooth Low Energy communications used by this software.
*
*/
#ifndef COMM_BLE_H
#define COMM_BLE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Preprocessor and Type Definitions */
// Define this to print out BLE trace statements to the console.
//#define TRACE_BLE
//#define VERBOSE_BLE_TRACE
#define COMM_BLE_TASK_STACK_SIZE_in_bytes 4096
typedef enum
{
COMM_BLE_DEFAULT,
COMM_BLE_INITIALIZING,
COMM_BLE_IDLE,
COMM_BLE_SCANNING_FOR_KTAG_PACKETS,
COMM_BLE_ADVERTISING_AS_PERIPHERAL,
COMM_BLE_ADVERTISING_AS_BROADCASTER,
COMM_BLE_SCANNING_AND_ADVERTISING
} COMM_BLE_StateID_T;
typedef enum
{
COMM_BLE_COMMAND_NO_OP,
COMM_BLE_REQUEST_STATE_CHANGE,
COMM_BLE_PROCESS_BLE_EVENTS,
COMM_BLE_SCAN_FOR_KTAG_PACKETS,
COMM_BLE_ADVERTISE_AS_BROADCASTER,
COMM_BLE_ADVERTISE_AS_PERIPHERAL,
COMM_BLE_STOP_ADVERTISING,
COMM_BLE_SCAN_AND_ADVERTISE,
// COMM_BLE_COMMAND_IS_OUT_OF_RANGE is one more than the last valid command.
COMM_BLE_COMMAND_IS_OUT_OF_RANGE
} COMM_BLE_Command_ID_T;
typedef struct
{
COMM_BLE_Command_ID_T ID;
void * Data;
} COMM_BLE_Command_T;
/* Include Files */
/* Public Variables */
extern cy_stc_ble_conn_handle_t appConnHandle[CY_BLE_CONN_COUNT];
extern volatile uint8_t COMM_BLE_IASAlertLevel;
extern QueueHandle_t COMM_BLE_CommandQueue;
//! Handle of the COMM_BLE_Task() given when the task was created.
extern TaskHandle_t COMM_BLE_Task_Handle;
/* Public Functions */
void COMM_BLE_Init(void);
void COMM_BLE_Task(void * pvParameters);
void COMM_BLE_RequestState(COMM_BLE_StateID_T state);
#ifdef __cplusplus
}
#endif
#endif // COMM_BLE_H

View file

@ -0,0 +1,252 @@
/* Include Files */
#include "KTag.h"
/* Local Definitions and Constants */
/* Public Variables */
/* Private Variables */
static bool removeBondListFlag = false;
/* Private Function Prototypes */
/* Public Functions */
/*******************************************************************************
* Function Name: App_DisplayBondList()
********************************************************************************
*
* Summary:
* This function displays the bond list.
*
*******************************************************************************/
void App_DisplayBondList(void)
{
#ifdef TRACE_BLE
cy_en_ble_api_result_t apiResult;
cy_stc_ble_gap_peer_addr_info_t bondedDeviceInfo[CY_BLE_MAX_BONDED_DEVICES];
cy_stc_ble_gap_bonded_device_list_info_t bondedDeviceList =
{
.bdHandleAddrList = bondedDeviceInfo
};
uint8_t deviceCount;
/* Find out whether the device has bonded information stored already or not */
apiResult = Cy_BLE_GAP_GetBondList(&bondedDeviceList);
if (apiResult != CY_BLE_SUCCESS)
{
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_GetBondList API Error: 0x");
COMM_Console_Print_UInt32AsHex(apiResult);
COMM_Console_Print_String("\n");
}
else
{
deviceCount = bondedDeviceList.noOfDevices;
if(deviceCount != 0u)
{
uint8_t counter;
COMM_Console_Print_String("[BLE] Bond list:\n");
do
{
COMM_Console_Print_String(" ");
COMM_Console_Print_UInt8(deviceCount);
COMM_Console_Print_String(". ");
deviceCount--;
if(bondedDeviceList.bdHandleAddrList[deviceCount].bdAddr.type == CY_BLE_GAP_ADDR_TYPE_RANDOM)
{
COMM_Console_Print_String("Peer Random Address:");
}
else
{
COMM_Console_Print_String("Peer Public Address:");
}
for (counter = CY_BLE_GAP_BD_ADDR_SIZE; counter > 0u; counter--)
{
COMM_Console_Print_String(" ");
COMM_Console_Print_UInt8AsHex(bondedDeviceList.bdHandleAddrList[deviceCount].bdAddr.bdAddr[counter - 1u]);
}
COMM_Console_Print_String(", bdHandle: 0x");
COMM_Console_Print_UInt8AsHex(bondedDeviceList.bdHandleAddrList[deviceCount].bdHandle);
COMM_Console_Print_String("\n");
} while (deviceCount != 0u);
COMM_Console_Print_String("\n");
}
}
#endif // TRACE_BLE
}
/*******************************************************************************
* Function Name: App_RemoveDevidesFromBondList
********************************************************************************
*
* Summary:
* Remove devices from the bond list.
*
*******************************************************************************/
void App_RemoveDevicesFromBondList(void)
{
#if(CY_BLE_BONDING_REQUIREMENT == CY_BLE_BONDING_YES)
cy_en_ble_api_result_t apiResult;
cy_stc_ble_gap_bd_addr_t peerBdAddr = { .type = 0u };
#ifdef TRACE_BLE
COMM_Console_Print_String("[BLE] Cleaning Bond List...\n\n");
#endif // TRACE_BLE
/* Remove all bonded devices in the list */
apiResult = Cy_BLE_GAP_RemoveBondedDevice(&peerBdAddr);
if (apiResult != CY_BLE_SUCCESS)
{
#ifdef TRACE_BLE
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_RemoveBondedDevice API Error: 0x");
COMM_Console_Print_UInt32AsHex(apiResult);
COMM_Console_Print_String("\n");
#endif // TRACE_BLE
}
else
{
#ifdef TRACE_BLE
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_RemoveBondedDevice complete.\n\n");
#endif // TRACE_BLE
}
#else
#ifdef TRACE_BLE
COMM_Console_Print_String("[BLE] Bonding is disabled...no need to remove bonded devices.\n\n");
#endif // TRACE_BLE
#endif /* (CY_BLE_BONDING_REQUIREMENT == CY_BLE_BONDING_YES) */
/* Clean flag */
removeBondListFlag = false;
}
/*******************************************************************************
* Function Name: App_GetCountOfBondedDevices()
********************************************************************************
*
* Summary:
* This function returns the count of bonded devices
*
* Return:
* uint32_t The count of bonded devices
*
*******************************************************************************/
uint32_t App_GetCountOfBondedDevices(void)
{
cy_en_ble_api_result_t apiResult;
cy_stc_ble_gap_peer_addr_info_t bondedDeviceInfo[CY_BLE_MAX_BONDED_DEVICES];
cy_stc_ble_gap_bonded_device_list_info_t bondedDeviceList =
{
.bdHandleAddrList = bondedDeviceInfo
};
uint32_t deviceCount = 0u;
/* Find out whether the device has bonded information stored already or not */
apiResult = Cy_BLE_GAP_GetBondList(&bondedDeviceList);
if (apiResult != CY_BLE_SUCCESS)
{
#ifdef TRACE_BLE
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_GetBondList API Error: 0x");
COMM_Console_Print_UInt32AsHex(apiResult);
COMM_Console_Print_String("\n");
#endif // TRACE_BLE
}
else
{
deviceCount = bondedDeviceList.noOfDevices;
}
return (deviceCount);
}
/*******************************************************************************
* Function Name: App_IsDeviceInBondList()
********************************************************************************
*
* Summary:
* This function check if device with bdHandle is in the bond list
*
* Parameters:
* bdHandle - bond device handler
*
* Return:
* bool - true value when bdHandle exists in bond list
*
*******************************************************************************/
bool App_IsDeviceInBondList(uint32_t bdHandle)
{
cy_en_ble_api_result_t apiResult;
cy_stc_ble_gap_peer_addr_info_t bondedDeviceInfo[CY_BLE_MAX_BONDED_DEVICES];
cy_stc_ble_gap_bonded_device_list_info_t bondedDeviceList =
{
.bdHandleAddrList = bondedDeviceInfo
};
bool deviceIsDetected = false;
uint32_t deviceCount;
/* Find out whether the device has bonding information stored already or not */
apiResult = Cy_BLE_GAP_GetBondList(&bondedDeviceList);
if (apiResult != CY_BLE_SUCCESS)
{
#ifdef TRACE_BLE
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_GetBondList API Error: 0x");
COMM_Console_Print_UInt32AsHex(apiResult);
COMM_Console_Print_String("\n");
#endif // TRACE_BLE
}
else
{
deviceCount = bondedDeviceList.noOfDevices;
if(deviceCount != 0u)
{
do
{
deviceCount--;
if(bdHandle == bondedDeviceList.bdHandleAddrList[deviceCount].bdHandle)
{
deviceIsDetected = 1u;
}
} while(deviceCount != 0u);
}
}
return(deviceIsDetected);
}
/*******************************************************************************
* Function Name: App_SetRemoveBondListFlag()
********************************************************************************
* Summary:
* Set flag for removing bond list
*
*******************************************************************************/
void App_SetRemoveBondListFlag(void)
{
removeBondListFlag = true;
}
/*******************************************************************************
* Function Name: App_IsRemoveBondListFlag()
********************************************************************************
* Summary:
* Get value of remove bond list flag
*
* Return:
* true - remove bond list flag is set
* false - remove bond list flag is clear
*
*******************************************************************************/
bool App_IsRemoveBondListFlag(void)
{
return ((removeBondListFlag == true) ? true : false);
}
/* Private Functions */

View file

@ -0,0 +1,32 @@
/** \file
* \brief This file declares Bluetooth Low Energy bond list helper functions.
*
*/
#ifndef COMM_BLE_BOND_H
#define COMM_BLE_BOND_H
#ifdef __cplusplus
extern "C" {
#endif
/* Preprocessor and Type Definitions */
/* Include Files */
/* Public Variables */
/* Public Functions */
void App_DisplayBondList(void);
void App_RemoveDevicesFromBondListBySW2Press(uint32_t seconds);
void App_RemoveDevicesFromBondList(void);
void App_SetRemoveBondListFlag(void);
bool App_IsRemoveBondListFlag(void);
bool App_IsDeviceInBondList(uint32_t bdHandle);
uint32_t App_GetCountOfBondedDevices(void);
#ifdef __cplusplus
}
#endif
#endif // COMM_BLE_BOND_H

View file

@ -0,0 +1,177 @@
/* Include Files */
#include "KTag.h"
/* Local Definitions and Constants */
#define UART_CIRCULAR_BUFFER_SIZE 1024
#define BLE_UART_BUFFER_CHARACTERISTIC_SIZE 20
/* Public Variables */
/* Private Variables */
static uint_fast16_t UART_Tx_Notifications_Enabled = 0;
static uint8_t UART_Tx_Buffer_Storage[UART_CIRCULAR_BUFFER_SIZE];
static UTIL_CircularBuffer_T UART_Tx_Buffer;
static uint8_t BLE_UART_Tx_Buffer[BLE_UART_BUFFER_CHARACTERISTIC_SIZE];
static uint8_t Rx_Buffer[BLE_UART_BUFFER_CHARACTERISTIC_SIZE + 1];
/* Private Function Prototypes */
/* Public Functions */
void COMM_BLE_UART_Init(void)
{
UTIL_InitCircularBuffer(&UART_Tx_Buffer, UART_Tx_Buffer_Storage, UART_CIRCULAR_BUFFER_SIZE);
}
//! Sends a message over the BLE UART.
void COMM_BLE_UART_PutString(const char8 * string, uint16_t length)
{
for (uint8_t i = 0; i < length; i++)
{
(void) UTIL_PushToCircularBuffer(&UART_Tx_Buffer, *string++);
}
}
//! Sends a single character over the BLE UART.
void COMM_BLE_UART_PutChar(char8 character)
{
(void) UTIL_PushToCircularBuffer(&UART_Tx_Buffer, character);
}
void COMM_BLE_UART_MaybeSendData(void)
{
int8_t length = 0;
if (UTIL_IsCircularBufferEmpty(&UART_Tx_Buffer) == false)
{
while ((length < BLE_UART_BUFFER_CHARACTERISTIC_SIZE) && (UTIL_IsCircularBufferEmpty(&UART_Tx_Buffer) == false))
{
uint8_t value;
if (UTIL_PopFromCircularBuffer(&UART_Tx_Buffer, &value) == UTIL_CIRCULARBUFFERRESULT_SUCCESS)
{
BLE_UART_Tx_Buffer[length] = value;
length++;
}
}
}
if (length > 0)
{
for (uint_fast8_t i = 0; i < CY_BLE_CONN_COUNT; i++)
{
if (Cy_BLE_GetConnectionState(appConnHandle[i]) >= CY_BLE_CONN_STATE_CONNECTED)
{
cy_stc_ble_gatt_handle_value_pair_t tempHandle;
tempHandle.attrHandle = CY_BLE_NORDIC_UART_SERVICE_TX_CHAR_HANDLE;
tempHandle.value.val = (uint8 *) BLE_UART_Tx_Buffer;
tempHandle.value.actualLen = length;
tempHandle.value.len = length;
Cy_BLE_GATTS_WriteAttributeValueLocal(&tempHandle);
}
}
// Send notification to each client that has TX notifications enabled.
for (uint_fast8_t i = 0; i < CY_BLE_CONN_COUNT; i++)
{
if ((Cy_BLE_GetConnectionState(appConnHandle[i]) >= CY_BLE_CONN_STATE_CONNECTED) &&
Cy_BLE_GATTS_IsNotificationEnabled(&appConnHandle[i],
CY_BLE_NORDIC_UART_SERVICE_TX_TXCCCD_DESC_HANDLE))
{
cy_stc_ble_gatt_handle_value_pair_t tempHandle;
tempHandle.attrHandle = CY_BLE_NORDIC_UART_SERVICE_TX_CHAR_HANDLE;
tempHandle.value.val = (uint8 *) BLE_UART_Tx_Buffer;
tempHandle.value.actualLen = length;
tempHandle.value.len = length;
Cy_BLE_GATTS_SendNotification(&appConnHandle[i], &tempHandle);
}
}
}
}
//! BLE event handler for the BLE UART feature.
/*!
* This function should be called *before* events are handled in the event handler passed to
* Cy_BLE_Start(). If it returns `false`, then the rest of the event handler should proceed.
*
* \param event BLE stack event code received from the BLE middleware (one of cy_en_ble_event_t).
* \param eventParam pointer to an event-specific data structure containing the relevant event information.
* \return true if this handler has completely handled the event, and no further
* handling is necessary; false otherwise.
*/
bool COMM_BLE_UART_HandleEvent(uint32 event, void * eventParam)
{
static cy_stc_ble_gatts_write_cmd_req_param_t * writeReqParameter;
bool handled = false;
/* Take an action based on the current event */
switch ((cy_en_ble_event_t)event)
{
// Handle a write request.
case CY_BLE_EVT_GATTS_WRITE_REQ:
writeReqParameter = (cy_stc_ble_gatts_write_cmd_req_param_t*)eventParam;
// Request to write the UART.
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.2.0%2Fble_sdk_app_nus_eval.html&cp=5_5_0_4_1_2_24
if (writeReqParameter->handleValPair.attrHandle == CY_BLE_NORDIC_UART_SERVICE_RX_CHAR_HANDLE)
{
// Only update the value and write the response if the requested write is allowed.
if (CY_BLE_GATT_ERR_NONE == Cy_BLE_GATTS_WriteAttributeValuePeer(&writeReqParameter->connHandle, &writeReqParameter->handleValPair))
{
uint16_t i;
for (i = 0; (i < BLE_UART_BUFFER_CHARACTERISTIC_SIZE) && (i < writeReqParameter->handleValPair.value.len); i++)
{
Rx_Buffer[i] = writeReqParameter->handleValPair.value.val[i];
}
// NULL-terminate the buffer.
Rx_Buffer[i] = 0x00;
Cy_BLE_GATTS_WriteRsp(writeReqParameter->connHandle);
COMM_Console_Execute_Internal_Command(Rx_Buffer);
}
handled = true;
}
// Request for UART Tx notifications.
if (writeReqParameter->handleValPair.attrHandle == CY_BLE_NORDIC_UART_SERVICE_TX_TXCCCD_DESC_HANDLE)
{
if (CY_BLE_GATT_ERR_NONE == Cy_BLE_GATTS_WriteAttributeValuePeer(&writeReqParameter->connHandle, &writeReqParameter->handleValPair))
{
UART_Tx_Notifications_Enabled = writeReqParameter->handleValPair.value.val[0] & 0x01;
if (UART_Tx_Notifications_Enabled)
{
COMM_Console_Print_String("[BLE] UART Tx notifications enabled.\n");
}
else
{
COMM_Console_Print_String("[BLE] UART Tx notifications disabled.\n");
}
Cy_BLE_GATTS_WriteRsp(writeReqParameter->connHandle);
}
handled = true;
}
break;
default:
// (`handled` is already set to false.)
break;
}
return handled;
}
/* Private Functions */

View file

@ -0,0 +1,30 @@
/** \file
* \brief This file declares interface functions to a BLE UART implementation.
*
*/
#ifndef COMM_BLE_UART_H
#define COMM_BLE_UART_H
#ifdef __cplusplus
extern "C" {
#endif
/* Preprocessor and Type Definitions */
/* Include Files */
/* Public Variables */
/* Public Functions */
void COMM_BLE_UART_Init(void);
void COMM_BLE_UART_PutString(const char8 * string, uint16_t length);
void COMM_BLE_UART_PutChar(char8 character);
void COMM_BLE_UART_MaybeSendData(void);
bool COMM_BLE_UART_HandleEvent(uint32 event, void * eventParam);
#ifdef __cplusplus
}
#endif
#endif // COMM_BLE_UART_H

View file

@ -0,0 +1,50 @@
/** \dir "COMM"
*
* \brief This directory contains source code for the communication interfaces used by this software.
*
*/
/** \file
* \brief This file defines the interface to the communications used by this software.
*
* This file should be included by any file outside the COMM package wishing to make use
* of any of the configuration information provided by the COMM package.
*
*/
#ifndef COMM_H
#define COMM_H
#ifdef __cplusplus
extern "C" {
#endif
/* Include Files */
#include "COMM_IPC_Messages.h"
#include "BLE/COMM_BLE.h"
#include "BLE/COMM_BLE_Bond.h"
#include "BLE/COMM_BLE_UART.h"
#include "COMM_Console.h"
#include "COMM_Console_Util.h"
#include "COMM_I2C_Bus.h"
#include "COMM_Util.h"
#include "ConsoleCommands/COMM_ConsoleCommands.h"
#include "ConsoleCommands/COMM_BLE_ConsoleCommands.h"
#include "ConsoleCommands/COMM_NVM_ConsoleCommands.h"
#include "ConsoleCommands/COMM_RTOS_ConsoleCommands.h"
#include "ConsoleCommands/COMM_STATE_ConsoleCommands.h"
/* Preprocessor and Type Definitions */
#define DebugPrintf(...)
#define Task_DebugPrintf(...)
/* Public Variables */
/* Public Functions */
#ifdef __cplusplus
}
#endif
#endif // COMM_H

View file

@ -0,0 +1,639 @@
/** \file
* \brief This file implements a simple serial debug console and command interpreter.
*/
/** \defgroup CONSOLE Console
*
* \brief Serial debug console command interpreter.
*
* \todo Describe the command interpreter.
*
* @{
* @}
*/
/* Include Files */
#include "KTag.h"
/* Local Definitions and Constants */
//! Text representations of numeric digits, used by COMM_Console_Print_UInt32().
static const char8 DIGITS[] = "0123456789ABCDEF";
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
//! Maximum number of characters (save one) able to be printed by COMM_Console_Print_String().
#define MAX_CONSOLE_STRING_LENGTH 81
//! States in the COMM_Console_Task() state machine.
typedef enum
{
COMM_STATE_INITIALIZING = 0,
COMM_STATE_DISPLAY_POWERUP_INFO,
COMM_STATE_IDLE,
COMM_STATE_COMMAND_TOO_LONG,
COMM_STATE_IDENTIFY_COMMAND,
COMM_STATE_EXECUTE_COMMAND,
COMM_STATE_UNKNOWN_COMMAND
} COMM_Console_State_T;
/* Public Variables */
char8 Command_Buffer[COMM_CONSOLE_COMMAND_MAX_LENGTH];
uint_fast16_t Command_Buffer_Index = 0;
TaskHandle_t COMM_Console_Task_Handle;
/* Private Variables */
//! Current state of the COMM_Console_Task() state machine.
static COMM_Console_State_T Current_State = COMM_STATE_INITIALIZING;
//! Next state of the COMM_Console_Task() state machine.
static COMM_Console_State_T Next_State = COMM_STATE_INITIALIZING;
//! Index into the #COMM_Console_Command_Table for the command currently being handled.
/*!
* If #Current_Command is set to UINT_FAST16_MAX, the command being handled is unknown, or no command is being handled.
*/
static uint_fast16_t Current_Command = 0;
/* Private Function Prototypes */
static void ConsoleISR(void);
static bool ConsoleCommandMatches(const char8 * const command_name);
static void ReverseString(char8 * value, uint32_t length);
/* Inline Functions */
//! Swaps the characters in x and y.
static inline void Swap_Char8(char8 * x, char8 * y)
{
uint8_t temp = *x;
*x = *y;
*y = temp;
}
static inline void Reset_Command_Buffer()
{
taskENTER_CRITICAL();
for (uint_fast16_t i = 0; i < COMM_CONSOLE_COMMAND_MAX_LENGTH; i++)
{
Command_Buffer[i] = COMM_CONSOLE_STRING_TERMINATOR;
}
Command_Buffer_Index = 0;
taskEXIT_CRITICAL();
}
/* Public Functions */
//! Initializes the console.
/*!
* \ingroup CONSOLE
*/
void COMM_Console_Init(void)
{
// Enable the pullup on the Rx pin to keep the noise down.
Cy_GPIO_SetDrivemode(UART_Console_rx_PORT, UART_Console_rx_NUM, CY_GPIO_DM_PULLUP);
UART_Console_Start();
/// Unmask only the RX FIFO not empty interrupt bit.
UART_Console_HW->INTR_RX_MASK = SCB_INTR_RX_MASK_NOT_EMPTY_Msk;
Cy_SysInt_Init(&Int_UART_Console_cfg, ConsoleISR);
NVIC_ClearPendingIRQ(Int_UART_Console_cfg.intrSrc);
NVIC_EnableIRQ(Int_UART_Console_cfg.intrSrc);
}
//! Parses and handle console commands in the background.
/*!
* \ingroup CONSOLE
*
* The [UML State Machine Diagram](http://www.uml-diagrams.org/state-machine-diagrams.html) below
* shows how the console messages processed by this code. Note that all of the *Character Rx'd*
* transitions occur in the #UART_Console_SPI_UART_ISR_EntryCallback() itself on the PSoC4, in
* #ConsoleRxISR() on the PSoC5, and in #ConsoleISR() on the PSoC6, to improve overall performance.
*
* \startuml{COMM_Console_Task.png} "Console Task"
*
* skinparam headerFontSize 18
* skinparam state {
* BackgroundColor #eeeeee
* BackgroundColor<<Error>> #ffaaaa
* FontName Impact
* FontSize 18
* }
* skinparam note {
* FontName "Comic Sans MS"
* FontStyle italic
* }
*
* state "Initializing" as STATE_INITIALIZING
* [*] --> STATE_INITIALIZING
* note left of STATE_INITIALIZING : Wait for the rest of the system to come online.
* state "Display Powerup Info" as STATE_DISPLAY_POWERUP_INFO
* STATE_DISPLAY_POWERUP_INFO : do/ print OS version
* STATE_DISPLAY_POWERUP_INFO : do/ print configuration (debug or release)
* STATE_INITIALIZING --> STATE_DISPLAY_POWERUP_INFO : after(100ms)
* state "Idle" as STATE_IDLE
* STATE_IDLE : do/ RTOS_Sleep()
* STATE_DISPLAY_POWERUP_INFO --> STATE_IDLE
* state STATE_IS_EOM <<choice>>
* note top of STATE_IS_EOM : This happens in\nUART_Console_SPI_UART_ISR_ExitCallback() on PSoC4,\nConsoleRxISR() on PSoC5,\nand ConsoleISR() on PSoC6.
* STATE_IDLE --> STATE_IS_EOM : character rx'd
* state STATE_IS_COMMAND_BUFFER_FULL <<choice>>
* note top of STATE_IS_COMMAND_BUFFER_FULL : This happens in\nUART_Console_SPI_UART_ISR_ExitCallback() on PSoC4,\nConsoleRxISR() on PSoC5,\nand ConsoleISR() on PSoC6.
* STATE_IS_EOM --> STATE_IS_COMMAND_BUFFER_FULL : [else]
* state "Identify Command" as STATE_IDENTIFY_COMMAND
* STATE_IDENTIFY_COMMAND : do/ look for command in the COMM_Console_Command_Table[]
* STATE_IS_EOM --> STATE_IDENTIFY_COMMAND : [rx'd character is EOM]
* STATE_IDLE --> STATE_IDENTIFY_COMMAND : COMM_Console_Execute_Internal_Command()
* state "Command Too Long" as STATE_COMMAND_TOO_LONG
* STATE_COMMAND_TOO_LONG : do/ print error message
* STATE_COMMAND_TOO_LONG : do/ reset command buffer
* STATE_IS_COMMAND_BUFFER_FULL --> STATE_COMMAND_TOO_LONG : [command buffer is full]
* STATE_IS_COMMAND_BUFFER_FULL --> STATE_IDLE : [else]/\nAppend received character to command buffer
* STATE_COMMAND_TOO_LONG --> STATE_IDLE
* state "Execute Command" as STATE_EXECUTE_COMMAND
* STATE_EXECUTE_COMMAND : do/ execute console command
* STATE_EXECUTE_COMMAND : exit/ reset command buffer
* STATE_EXECUTE_COMMAND --> STATE_IDLE
* STATE_IDENTIFY_COMMAND --> STATE_EXECUTE_COMMAND : [command matched]
* state "Unknown Command" as STATE_UNKNOWN_COMMAND
* STATE_UNKNOWN_COMMAND : do/ print error message
* STATE_UNKNOWN_COMMAND : do/ reset command buffer
* STATE_IDENTIFY_COMMAND --> STATE_UNKNOWN_COMMAND : [else]
* STATE_UNKNOWN_COMMAND --> STATE_IDLE
*
* left footer Key: UML 2.5\nLast modified 2020-12-14
* \enduml
*
* \return None (infinite loop)
*/
void COMM_Console_Task(void * pvParameters)
{
static TickType_t xTicksToWait = pdMS_TO_TICKS(10);
static uint32_t * NotificationValue;
while(true)
{
(void) xTaskNotifyWait(0, 0, (uint32_t *)&NotificationValue, xTicksToWait);
// Change to the next state atomically.
taskENTER_CRITICAL();
Current_State = Next_State;
taskEXIT_CRITICAL();
switch (Current_State)
{
default:
case COMM_STATE_INITIALIZING:
Next_State = COMM_STATE_DISPLAY_POWERUP_INFO;
vTaskDelay(pdMS_TO_TICKS(10));
xTicksToWait = 1;
break;
case COMM_STATE_DISPLAY_POWERUP_INFO:
COMM_Console_Print_String("[COMM] ");
COMM_RTOS_HandleConsoleVersion(NULL, 0);
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String("[COMM] Console ready (awaiting commands).\n");
Next_State = COMM_STATE_IDLE;
xTicksToWait = 1;
break;
case COMM_STATE_IDLE:
xTicksToWait = pdMS_TO_TICKS(100);
break;
case COMM_STATE_COMMAND_TOO_LONG:
COMM_Console_Print_String("[COMM] ERROR: Command \"");
COMM_Console_Print_String(Command_Buffer);
COMM_Console_Print_String("\" too long!\n");
Reset_Command_Buffer();
Next_State = COMM_STATE_IDLE;
xTicksToWait = 1;
break;
case COMM_STATE_IDENTIFY_COMMAND:
Current_Command = UINT_FAST16_MAX;
for (uint_fast16_t i = 0; i < COMM_N_CONSOLE_COMMANDS; i++)
{
if (ConsoleCommandMatches(COMM_Console_Command_Table[i].Command_Name) == true)
{
Current_Command = i;
Next_State = COMM_STATE_EXECUTE_COMMAND;
xTicksToWait = 1;
break;
}
}
if (Current_Command == UINT_FAST16_MAX)
{
// No matching command was found.
Next_State = COMM_STATE_UNKNOWN_COMMAND;
xTicksToWait = 1;
}
break;
case COMM_STATE_EXECUTE_COMMAND:
if (COMM_Console_Command_Table[Current_Command].Execute_Command != NULL)
{
COMM_Console_Command_Result_T result = COMM_Console_Command_Table[Current_Command].Execute_Command(Command_Buffer, Command_Buffer_Index);
if (result == COMM_CONSOLE_CMD_RESULT_PARAMETER_ERROR)
{
COMM_Console_Print_String("ERROR: Parameter error!\n");
}
}
Reset_Command_Buffer();
Next_State = COMM_STATE_IDLE;
xTicksToWait = 1;
break;
case COMM_STATE_UNKNOWN_COMMAND:
COMM_Console_Print_String("ERROR: Command \"");
COMM_Console_Print_String(Command_Buffer);
COMM_Console_Print_String("\" not recognized! Try '?' for help.\n");
Reset_Command_Buffer();
Next_State = COMM_STATE_IDLE;
xTicksToWait = 1;
break;
}
}
}
SystemKResult_T HW_Execute_Console_Command(const uint8_t * const command)
{
COMM_Console_Execute_Internal_Command(command);
return SYSTEMK_RESULT_SUCCESS;
}
//! Executes a (potentially cross-task) console command.
/*!
* This function is used to initiate a console command from a software source internal to this
* CPU. This provides a way to use preexisting console commands on TX-only consoles.
*
* \note If two calls to this function are made back-to-back (before the COMM_Console_Task() has an
* opportunity to run), only the second command will be executed, as it will have overwritten the
* first. Allow time for the console commands to execute between calls to this function.
*
* \param command String containing the command to be executed.
*/
void COMM_Console_Execute_Internal_Command(const uint8_t * const command)
{
bool finished = false;
uint_fast16_t i = 0;
taskENTER_CRITICAL();
while ( (finished == false) &&
(i < COMM_CONSOLE_COMMAND_MAX_LENGTH) &&
(command[i] != COMM_CONSOLE_END_OF_MESSAGE ) &&
(command[i] != COMM_CONSOLE_STRING_TERMINATOR )
)
{
Command_Buffer[i] = command[i];
i++;
}
Command_Buffer_Index = i;
// If there is still room, terminate the command.
if (i < COMM_CONSOLE_COMMAND_MAX_LENGTH)
{
Command_Buffer[i] = COMM_CONSOLE_END_OF_MESSAGE;
}
taskEXIT_CRITICAL();
Next_State = COMM_STATE_IDENTIFY_COMMAND;
xTaskNotifyGive(COMM_Console_Task_Handle);
}
//! Prints a NULL-terminated string to the serial console.
void COMM_Console_Print_String(const char8 * const text)
{
for (size_t i = 0; i < MAX_CONSOLE_STRING_LENGTH; i++)
{
// Check for the end of the string. If there is no NULL terminator, up to
// MAX_CONSOLE_STRING_LENGTH characters of randomness will be printed.
if (text[i] == COMM_CONSOLE_STRING_TERMINATOR)
{
break;
}
// Send out the string, one character at a time.
COMM_Console_PutChar(text[i]);
}
}
//! Prints a 32-bit unsigned integer to the serial console.
void COMM_Console_Print_UInt32(uint32_t value)
{
// The largest string for a unit32_t is 10 characters (4294967296).
char8 buffer[10+1];
uint_fast8_t buffer_index = 0;
while (value > 9)
{
uint8_t digit_index = value % 10;
buffer[buffer_index] = DIGITS[digit_index];
value = value / 10;
buffer_index++;
}
buffer[buffer_index] = DIGITS[value];
buffer_index++;
ReverseString(buffer, buffer_index);
// NULL-terminate the string.
buffer[buffer_index] = 0;
COMM_Console_Print_String(buffer);
}
//! Prints a 32-bit signed integer to the serial console.
void COMM_Console_Print_SInt32(int32_t value)
{
if (value < 0)
{
value *= -1;
COMM_Console_PutChar('-');
}
COMM_Console_Print_UInt32(value);
}
//! Prints a 32-bit unsigned integer to the serial console using a hexadecimal representation.
void COMM_Console_Print_UInt32AsHex(uint32_t value)
{
// The largest hexadecimal string for a unit32_t is 8 characters (FFFFFFFF).
char8 buffer[8+1];
uint_fast8_t buffer_index = 0;
while (value > 15)
{
uint8_t digit_index = value % 16;
buffer[buffer_index] = DIGITS[digit_index];
value = value / 16;
buffer_index++;
}
buffer[buffer_index] = DIGITS[value];
buffer_index++;
ReverseString(buffer, buffer_index);
// NULL-terminate the string.
buffer[buffer_index] = 0;
COMM_Console_PutChar('0');
COMM_Console_PutChar('x');
COMM_Console_Print_String(buffer);
}
//! Prints a 64-bit unsigned integer to the serial console.
void COMM_Console_Print_UInt64(uint64_t value)
{
// The largest string for a unit64_t is 20 characters (18446744073709551615).
char8 buffer[20+1];
uint_fast8_t buffer_index = 0;
while (value > 9)
{
uint8_t digit_index = value % 10;
buffer[buffer_index] = DIGITS[digit_index];
value = value / 10;
buffer_index++;
}
buffer[buffer_index] = DIGITS[value];
buffer_index++;
ReverseString(buffer, buffer_index);
// NULL-terminate the string.
buffer[buffer_index] = 0;
COMM_Console_Print_String(buffer);
}
//! Prints a 64-bit unsigned integer to the serial console using a hexadecimal representation.
void COMM_Console_Print_UInt64AsHex(uint64_t value)
{
// The largest hexadecimal string for a unit64_t is 16 characters (FFFFFFFFFFFFFFFF).
char8 buffer[16+1];
uint_fast8_t buffer_index = 0;
while (value > 15)
{
uint8_t digit_index = value % 16;
buffer[buffer_index] = DIGITS[digit_index];
value = value / 16;
buffer_index++;
}
buffer[buffer_index] = DIGITS[value];
buffer_index++;
ReverseString(buffer, buffer_index);
// NULL-terminate the string.
buffer[buffer_index] = 0;
COMM_Console_PutChar('0');
COMM_Console_PutChar('x');
COMM_Console_Print_String(buffer);
}
//! Prints a floating-point number to the serial console.
/*!
* With thanks to Rick Regan and his [Quick and Dirty Floating-Point to Decimal Conversion](https://www.exploringbinary.com/quick-and-dirty-floating-point-to-decimal-conversion/).
*/
void COMM_Console_Print_Float(float value)
{
#define MAX_INTEGRAL_DIGITS 12
#define MAX_FRACTIONAL_DIGITS 6
#define BUFFER_SIZE (MAX_INTEGRAL_DIGITS + MAX_FRACTIONAL_DIGITS + 2)
char8 buffer[BUFFER_SIZE];
char8 integral_buffer_reversed[MAX_INTEGRAL_DIGITS];
uint16_t buffer_index = 0;
double integral_value;
double fractional_value;
bool overflow = false;
if (value < 0.0)
{
COMM_Console_Print_String("-");
value *= -1.0;
}
// Break the given value into fractional and integral parts.
fractional_value = modf(value, &integral_value);
if (integral_value > 0)
{
// Convert the integral part.
while ((integral_value > 0) && (buffer_index < MAX_INTEGRAL_DIGITS))
{
integral_buffer_reversed[buffer_index++] = '0' + (int)fmod(integral_value, 10);
integral_value = floor(integral_value / 10);
}
// If there is still an integral part remaining, and overflow has occurred.
if (integral_value > 0)
{
overflow = true;
}
// Reverse and append the integral part.
for (uint16_t i = 0; i < buffer_index; i++)
{
buffer[i] = integral_buffer_reversed[buffer_index-i-1];
}
}
else
{
// Append a leading zero.
buffer[buffer_index++] = '0';
}
// Append the decimal point.
buffer[buffer_index++] = '.';
// Convert the fractional part, even if it is zero, and leave room for the NULL terminator.
while (buffer_index < (BUFFER_SIZE - 1))
{
fractional_value *= 10;
buffer[buffer_index++] = '0' + (int)fractional_value;
fractional_value = modf(fractional_value, &integral_value);
}
// Append the NULL terminator.
buffer[buffer_index] = 0;
if (overflow == true)
{
COMM_Console_Print_String("OVERFLOW");
}
else
{
COMM_Console_Print_String(buffer);
}
}
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
//! Converts a byte to a two-character hexadecimal representation.
/*!
* \param buffer Buffer into which to place the resulting sting. It needs to be at least three
* characters wide.
* \param byte The byte to be converted.
*/
void COMM_Console_ByteToHex(char8 * buffer, uint8_t byte)
{
if (byte < 16)
{
buffer[0] = '0';
buffer[1] = DIGITS[byte];
buffer[2] = 0;
}
else
{
buffer[0] = DIGITS[byte / 16];
buffer[1] = DIGITS[byte % 16];
buffer[2] = 0;
}
}
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Private Functions */
static void ConsoleISR(void)
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
// Check for the "Rx FIFO not empty" interrput.
if ((UART_Console_HW->INTR_RX_MASKED & SCB_INTR_RX_MASKED_NOT_EMPTY_Msk ) != 0)
{
// Clear the "Rx FIFO not empty" interrput.
UART_Console_HW->INTR_RX = UART_Console_HW->INTR_RX & SCB_INTR_RX_NOT_EMPTY_Msk;
// Get the character.
uint32_t value = UART_Console_Get();
// Check if there is actually data. Sometimes the flag is set when there is no data (why?).
if (value != CY_SCB_UART_RX_NO_DATA)
{
char8 rx_data = (char8) value;
// Determine what to do with it.
if (Command_Buffer_Index < COMM_CONSOLE_COMMAND_MAX_LENGTH)
{
if (rx_data == COMM_CONSOLE_END_OF_MESSAGE)
{
Command_Buffer[Command_Buffer_Index] = COMM_CONSOLE_STRING_TERMINATOR;
Next_State = COMM_STATE_IDENTIFY_COMMAND;
vTaskNotifyGiveFromISR(COMM_Console_Task_Handle, &xHigherPriorityTaskWoken);
}
else
{
Command_Buffer[Command_Buffer_Index] = rx_data;
Command_Buffer_Index++;
}
}
else
{
Next_State = COMM_STATE_COMMAND_TOO_LONG;
vTaskNotifyGiveFromISR(COMM_Console_Task_Handle, &xHigherPriorityTaskWoken);
}
}
}
NVIC_ClearPendingIRQ(Int_UART_Console_cfg.intrSrc);
// If the state needs to change, a context switch might be required.
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
static bool ConsoleCommandMatches(const char8 * const command_name)
{
uint32_t i = 0;
bool is_match = false;
if (Command_Buffer[i] == command_name[i])
{
is_match = true;
i++;
}
while ( (is_match == true) &&
(i < COMM_CONSOLE_COMMAND_MAX_LENGTH) &&
(Command_Buffer[i] != COMM_CONSOLE_PARAMETER_DELIMITER) &&
(Command_Buffer[i] != COMM_CONSOLE_END_OF_MESSAGE ) &&
(Command_Buffer[i] != COMM_CONSOLE_STRING_TERMINATOR )
)
{
if ( Command_Buffer[i] != command_name[i] )
{
is_match = false;
}
i++;
}
return is_match;
}
//! Reverses a string in place.
/*!
* \param value Pointer to the string to be reversed.
* \param length Length of the string, including the NULL terminator.
*/
static void ReverseString(char8 * value, uint32_t length)
{
if (length > 1)
{
uint_fast32_t start = 0;
uint_fast32_t end = length - 1;
while (start < end)
{
Swap_Char8(value + start, value + end);
start++;
end--;
}
}
}
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)

View file

@ -0,0 +1,144 @@
/** \file
* \brief This file defines the interface to a simple serial debug console and command interpreter.
*
* \note As always, <project.h> and <CONFIG.h> should be included <I>before</I> this file.
*/
#ifndef COMM_CONSOLE_H
#define COMM_CONSOLE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Include Files */
/* Preprocessor and Type Definitions */
#define COMM_CONSOLE_TASK_STACK_SIZE_in_bytes 512
#define COMM_Console_PutChar UART_and_BLE_PutChar
#define COMM_Console_PutString UART_and_BLE_PutString
#define COMM_CONSOLE_COMMAND_MAX_LENGTH 50
//! Character signifying the end of a console message.
#define COMM_CONSOLE_END_OF_MESSAGE ('\n')
//! Character used between parameters in a console message.
#define COMM_CONSOLE_PARAMETER_DELIMITER (' ')
//! Character signifying the end of a string.
#define COMM_CONSOLE_STRING_TERMINATOR ('\0')
//! Result of executing a console command callback.
typedef enum
{
COMM_CONSOLE_CMD_RESULT_UNKNOWN = 0,
COMM_CONSOLE_CMD_RESULT_SUCCESS = 1,
COMM_CONSOLE_CMD_RESULT_PARAMETER_ERROR = 2
} COMM_Console_Command_Result_T;
//! Result of parsing a console command parameter.
typedef enum
{
COMM_CONSOLE_PARAMETER_RESULT_UNKNOWN = 0,
COMM_CONSOLE_PARAMETER_RESULT_SUCCESS = 1,
COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR = 2,
COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END = 3
} COMM_Console_Parameter_Result_T;
//! Prototype of a console command callback.
/*!
* \ingroup CONSOLE
* All console commands must use this signature.
*
* \param[in] data Pointer to the string containg the console command (and any arguments).
* \param[in] size Size (in char8) of the data string.
* \return #COMM_CONSOLE_CMD_RESULT_SUCCESS on success
* \return #COMM_Console_Command_Result_T otherwise
*/
typedef COMM_Console_Command_Result_T (* const COMM_Console_Command_Handler_T)(char8 * data, uint32_t size);
typedef struct
{
const char8 * const Command_Name;
const char8 * const Help;
COMM_Console_Command_Handler_T Execute_Command;
} COMM_Console_Command_Table_Entry_T;
/* Public Variables */
//! Handle of the COMM_Console_Task() given when the task was created.
extern TaskHandle_t COMM_Console_Task_Handle;
/* Public Functions */
void COMM_Console_Init(void);
void COMM_Console_Task(void * pvParameters);
void COMM_Console_Execute_Internal_Command(const uint8_t * const command);
void COMM_Console_Print_String(const char8 * const text);
void COMM_Console_Print_UInt32(uint32_t value);
void COMM_Console_Print_SInt32(int32_t value);
void COMM_Console_Print_UInt32AsHex(uint32_t value);
void COMM_Console_Print_UInt64(uint64_t value);
void COMM_Console_Print_UInt64AsHex(uint64_t value);
void COMM_Console_Print_Float(float value);
void COMM_Console_ByteToHex(char8 * buffer, uint8_t byte);
/* Inline Functions */
//! Prints an 8-bit unsigned integer to the serial console.
inline void COMM_Console_Print_UInt8(uint8_t value)
{
COMM_Console_Print_UInt32((uint32_t) value);
}
//! Prints an 8-bit unsigned integer to the serial console using a hexadecimal representation.
inline void COMM_Console_Print_UInt8AsHex(uint8_t value)
{
COMM_Console_Print_UInt32AsHex((uint32_t) value);
}
//! Prints an 8-bit signed integer to the serial console.
inline void COMM_Console_Print_Int8(int8_t value)
{
COMM_Console_Print_SInt32((int32_t) value);
}
//! Prints a 16-bit unsigned integer to the serial console.
inline void COMM_Console_Print_UInt16(uint16_t value)
{
COMM_Console_Print_UInt32((uint32_t) value);
}
//! Prints a 16-bit unsigned integer to the serial console using a hexadecimal representation.
inline void COMM_Console_Print_UInt16AsHex(uint16_t value)
{
COMM_Console_Print_UInt32AsHex((uint32_t) value);
}
//! Prints a 16-bit signed integer to the serial console.
inline void COMM_Console_Print_Int16(int16_t value)
{
COMM_Console_Print_SInt32((int32_t) value);
}
static inline void UART_and_BLE_PutChar(uint8 txDataByte)
{
UART_Console_Put(txDataByte);
COMM_BLE_UART_PutChar(txDataByte);
}
static inline void UART_and_BLE_PutString(const char8 string[])
{
UART_Console_PutString(string);
COMM_BLE_UART_PutString(string, strlen(string));
}
#ifdef __cplusplus
}
#endif
#endif // COMM_CONSOLE_H

View file

@ -0,0 +1,254 @@
/** \file
* \brief This file implements utility functions used by the command interpreter.
*/
/**
* \ingroup CONSOLE
*/
/* Include Files */
#include "KTag.h"
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Local Definitions and Constants */
/* Public Variables */
/* Private Variables */
/* Private Function Prototypes */
/* Public Functions */
//! Find the start location of the nth parameter in the buffer.
/*!
* \note The command itself is parameter 0.
*/
COMM_Console_Parameter_Result_T COMM_Console_FindNthParameter(const char * const buffer, const uint8_t parameterNumber, const char ** parameterLocation)
{
uint32_t buffer_index = 0;
uint32_t parameter_index = 0;
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
while (parameterNumber != parameter_index)
{
if (buffer[buffer_index] == COMM_CONSOLE_PARAMETER_DELIMITER)
{
parameter_index++;
}
else if (buffer[buffer_index] == COMM_CONSOLE_END_OF_MESSAGE)
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
break;
}
else if (buffer[buffer_index] == COMM_CONSOLE_STRING_TERMINATOR)
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
break;
}
buffer_index++;
}
if (result == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
*parameterLocation = &buffer[buffer_index];
}
return result;
}
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt8(const char * const buffer, uint8_t * const parameterUInt8)
{
uint8_t value = 0;
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
// Strings containing uint8s range from "0" to "255". The large number has three characters.
uint_fast16_t MAX_CHARACTERS = 3;
uint_fast16_t index = 0;
while (index < (MAX_CHARACTERS + 1))
{
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
{
value *= 10;
value += buffer[index] - '0';
index++;
}
else if ( (buffer[index] == COMM_CONSOLE_PARAMETER_DELIMITER) ||
(buffer[index] == COMM_CONSOLE_STRING_TERMINATOR) ||
(buffer[index] == COMM_CONSOLE_END_OF_MESSAGE) )
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END;
break;
}
else
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
break;
}
}
if (result == COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END)
{
result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
*parameterUInt8 = value;
}
return result;
}
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt16(const char * const buffer, uint16_t * const parameterUInt16)
{
uint16_t value = 0;
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
// Strings containing uint16s range from "0" to "65535". The large number has five characters.
uint_fast16_t MAX_CHARACTERS = 5;
uint_fast16_t index = 0;
while (index < (MAX_CHARACTERS + 1))
{
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
{
value *= 10;
value += buffer[index] - '0';
index++;
}
else if ( (buffer[index] == COMM_CONSOLE_PARAMETER_DELIMITER) ||
(buffer[index] == COMM_CONSOLE_STRING_TERMINATOR) ||
(buffer[index] == COMM_CONSOLE_END_OF_MESSAGE) )
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END;
break;
}
else
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
break;
}
}
if (result == COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END)
{
result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
*parameterUInt16 = value;
}
return result;
}
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterInt32(const char * const buffer, int32_t * const parameterInt32)
{
int32_t value = 0;
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
bool is_negative = false;
// Strings containing int32s range from "-2147483648" to "2147483647". The negative number has eleven characters.
uint_fast16_t MAX_CHARACTERS = 11;
uint_fast16_t index = 0;
if (buffer[index] == '-')
{
is_negative = true;
index++;
}
while (index < (MAX_CHARACTERS + 1))
{
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
{
value *= 10;
value += buffer[index] - '0';
index++;
}
else if ( (buffer[index] == COMM_CONSOLE_PARAMETER_DELIMITER) ||
(buffer[index] == COMM_CONSOLE_STRING_TERMINATOR) ||
(buffer[index] == COMM_CONSOLE_END_OF_MESSAGE) )
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END;
break;
}
else
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
break;
}
}
if (is_negative == true)
{
value *= -1;
}
if (result == COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END)
{
result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
*parameterInt32 = value;
}
return result;
}
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt32(const char * const buffer, uint32_t * const parameterUInt32)
{
uint32_t value = 0;
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
// Strings containing uint32s range from "0" to "4294967296". The large number has ten characters.
uint_fast16_t MAX_CHARACTERS = 10;
uint_fast16_t index = 0;
while (index < (MAX_CHARACTERS + 1))
{
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
{
value *= 10;
value += buffer[index] - '0';
index++;
}
else if ( (buffer[index] == COMM_CONSOLE_PARAMETER_DELIMITER) ||
(buffer[index] == COMM_CONSOLE_STRING_TERMINATOR) ||
(buffer[index] == COMM_CONSOLE_END_OF_MESSAGE) )
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END;
break;
}
else
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
break;
}
}
if (result == COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END)
{
result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
*parameterUInt32 = value;
}
return result;
}
COMM_Console_Parameter_Result_T COMM_Console_DecodeHexParameterUInt64(const char * const buffer, uint64_t * const parameterUInt64)
{
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
struct _reent context;
context._errno = 0;
*parameterUInt64 = _strtoull_r(&context, buffer, NULL, 16);
if (context._errno != 0)
{
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
}
return result;
}
/* Private Functions */
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)

View file

@ -0,0 +1,50 @@
/** \file
* \brief Utility functions used by the command interpreter.
*
* \note As always, <project.h> and <RTOS.h> should be included <I>before</I> this file.
*/
#ifndef COMM_CONSOLE_UTIL_H
#define COMM_CONSOLE_UTIL_H
#ifdef __cplusplus
extern "C" {
#endif
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Include Files */
/* Preprocessor and Type Definitions */
/* Public Variables */
/* Public Functions */
COMM_Console_Parameter_Result_T COMM_Console_FindNthParameter(const char * const buffer, const uint8_t parameterNumber, const char ** parameterLocation);
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt8(const char * const buffer, uint8_t * const parameterUInt8);
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt16(const char * const buffer, uint16_t * const parameterUInt16);
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterInt32(const char * const buffer, int32_t * const parameterInt32);
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt32(const char * const buffer, uint32_t * const parameterUInt32);
COMM_Console_Parameter_Result_T COMM_Console_DecodeHexParameterUInt64(const char * const buffer, uint64_t * const parameterUInt64);
//! Returns `true` if this character marks the end of a console message; `false` otherwise.
inline bool COMM_Console_IsEndOfMessage(char8 character)
{
bool result = false;
if ( (character == COMM_CONSOLE_END_OF_MESSAGE) ||
(character == COMM_CONSOLE_STRING_TERMINATOR) )
{
result = true;
}
return result;
}
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
#ifdef __cplusplus
}
#endif
#endif // COMM_CONSOLE_UTIL_H

View file

@ -0,0 +1,33 @@
/** \file
* \brief This file implements the I²C bus.
*
* See COMM_I2C_Bus.h for a detailed description of the functionality implemented by this code.
*/
/* Include Files */
#include "KTag.h"
/* Local Definitions and Constants */
/* Public Variables */
SemaphoreHandle_t COMM_I2C_Bus_Mutex = NULL;
/* Private Variables */
/* Private Function Prototypes */
/* Public Functions */
//! Initializes the I²C bus.
/*!
*
*/
void COMM_I2C_Init(void)
{
COMM_I2C_Bus_Mutex = xSemaphoreCreateMutex();
I2C_Start();
}
/* Private Functions */

View file

@ -0,0 +1,29 @@
/** \file
* \brief This file defines the interface to the I²C bus.
*
*/
#ifndef COMM_I2C_BUS_H
#define COMM_I2C_BUS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Preprocessor and Type Definitions */
/* Include Files */
/* Public Variables */
extern SemaphoreHandle_t COMM_I2C_Bus_Mutex;
/* Public Functions */
void COMM_I2C_Init(void);
#ifdef __cplusplus
}
#endif
#endif // COMM_I2C_BUS_H

View file

@ -0,0 +1,285 @@
/** \file
* \brief This file implements messaging using inter-processor communication (IPC).
*
* \see https://community.cypress.com/thread/36182.
*/
/**
* \ingroup CONSOLE
*/
/* Include Files */
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <project.h>
#include "COMM_IPC_Messages.h"
/* Private Function Prototypes */
#if (__CORTEX_M == 0)
static void Message_Received_for_CM0(uint32_t * msg);
static void Message_Received_by_CM4(void);
#endif // (__CORTEX_M == 0)
#if (__CORTEX_M == 4)
static void Message_Received_for_CM4(uint32_t * msg);
static void Message_Received_by_CM0(void);
#endif // (__CORTEX_M == 4)
static void IPC_UserPipeInit(void);
static void IPC_UserPipeISR(void);
/* Local Definitions and Constants */
//! Number of clients supported on the user pipe.
#define CY_IPC_USRPIPE_CLIENT_CNT (uint32_t)(8u)
#define CY_IPC_CHAN_USRPIPE_CM0 (uint32_t)(8u)
#define CY_IPC_CHAN_USRPIPE_CM4 (uint32_t)(9u)
#define CY_IPC_INTR_USRPIPE_CM0 (uint32_t)(8u)
#define CY_IPC_INTR_USRPIPE_CM4 (uint32_t)(9u)
#define CY_IPC_EP_USRPIPE_ADDR_CM0_EP (uint32_t)(2u)
#define CY_IPC_EP_USRPIPE_ADDR_CM4_EP (uint32_t)(3u)
#if (CY_CPU_CORTEX_M0P)
#define IPC_EP_USRPIPE_ADDR CY_IPC_EP_USRPIPE_ADDR_CM0_EP
#else
#define IPC_EP_USRPIPE_ADDR CY_IPC_EP_USRPIPE_ADDR_CM4_EP
#endif /* (CY_CPU_CORTEX_M0P) */
/* User Pipe Configuration */
#define IPC_USRPIPE_CHAN_MASK_CM0 (uint32_t)(0x0001ul << CY_IPC_CHAN_USRPIPE_CM0)
#define IPC_USRPIPE_CHAN_MASK_CM4 (uint32_t)(0x0001ul << CY_IPC_CHAN_USRPIPE_CM4)
#define IPC_USRPIPE_INTR_MASK (uint32_t)( IPC_USRPIPE_CHAN_MASK_CM0 | IPC_USRPIPE_CHAN_MASK_CM4 )
#define IPC_INTR_USRPIPE_PRIOR_CM0 (uint32_t)(1u) /* Notifier Priority */
#define IPC_INTR_USRPIPE_PRIOR_CM4 (uint32_t)(1u) /* Notifier Priority */
#define IPC_INTR_USRPIPE_MUX_CM0 (uint32_t)(7u) /* IPC CYPRESS PIPE */
#define IPC_USRPIPE_CONFIG_CM0 (uint32_t)(IPC_USRPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos)\
|(CY_IPC_INTR_USRPIPE_CM0 << CY_IPC_PIPE_CFG_INTR_Pos )\
|(CY_IPC_CHAN_USRPIPE_CM0)
#define IPC_USRPIPE_CONFIG_CM4 (uint32_t)(IPC_USRPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos)\
|(CY_IPC_INTR_USRPIPE_CM4 << CY_IPC_PIPE_CFG_INTR_Pos )\
|(CY_IPC_CHAN_USRPIPE_CM4)
#define USRPIPE_CONFIG \
{\
/* .ep0ConfigData */ {\
/* .ipcNotifierNumber */ CY_IPC_INTR_USRPIPE_CM0,\
/* .ipcNotifierPriority */ IPC_INTR_USRPIPE_PRIOR_CM0,\
/* .ipcNotifierMuxNumber */ IPC_INTR_USRPIPE_MUX_CM0,\
/* .epAddress */ CY_IPC_EP_USRPIPE_ADDR_CM0_EP,\
/* .epConfig */ IPC_USRPIPE_CONFIG_CM0\
},\
/* .ep1ConfigData */ {\
/* .ipcNotifierNumber */ CY_IPC_INTR_USRPIPE_CM4,\
/* .ipcNotifierPriority */ IPC_INTR_USRPIPE_PRIOR_CM4,\
/* .ipcNotifierMuxNumber */ 0u,\
/* .epAddress */ CY_IPC_EP_USRPIPE_ADDR_CM4_EP,\
/* .epConfig */ IPC_USRPIPE_CONFIG_CM4\
},\
/* .endpointClientsCount */ CY_IPC_USRPIPE_CLIENT_CNT,\
/* .endpointsCallbacksArray */ ipc_pipe_CbArray,\
/* .userPipeIsrHandler */ &IPC_UserPipeISR\
}
//! Client ID for messages from the CM0 to the CM4
#define COMM_IPC_CM0_TO_CM4_CLIENT_ID 0
//! Client ID for messages from the CM4 to the CM0
#define COMM_IPC_CM4_TO_CM0_CLIENT_ID 1
/* Public Variables */
/* Private Variables */
#if (__CORTEX_M == 0)
static COMM_IPCMessage_T MessageBuffer =
{
.ClientID = _VAL2FLD(CY_IPC_PIPE_MSG_CLIENT, COMM_IPC_CM0_TO_CM4_CLIENT_ID) | _VAL2FLD(CY_IPC_PIPE_MSG_USR, 0) | _VAL2FLD(CY_IPC_PIPE_MSG_RELEASE, IPC_USRPIPE_INTR_MASK),
.MessageID = COMM_SMM_DefaultNoMessage,
.Data = NULL
};
static volatile bool OK_to_send_from_CM0_to_CM4 = true;
#endif // (__CORTEX_M == 0)
#if (__CORTEX_M == 4)
static COMM_IPCMessage_T MessageBuffer =
{
.ClientID = _VAL2FLD(CY_IPC_PIPE_MSG_CLIENT, COMM_IPC_CM4_TO_CM0_CLIENT_ID) | _VAL2FLD(CY_IPC_PIPE_MSG_USR, 0) | _VAL2FLD(CY_IPC_PIPE_MSG_RELEASE, IPC_USRPIPE_INTR_MASK),
.MessageID = COMM_SMM_DefaultNoMessage,
.Data = NULL
};
static volatile bool OK_to_send_from_CM4_to_CM0 = true;
#endif // (__CORTEX_M == 4)
/* Public Functions */
#if (__CORTEX_M == 0)
//! Initializes the inter-processor communications on the Cortex-M0 core.
/*!
* This should be called *before* calling Cy_SysEnableCM4().
*/
void COMM_InitIPCMessages(void)
{
IPC_UserPipeInit();
// Register a callback to handle messages from CM4.
Cy_IPC_Pipe_RegisterCallback(IPC_EP_USRPIPE_ADDR,
Message_Received_for_CM0,
CY_IPC_EP_CYPIPE_CM4_ADDR);
}
#endif // (__CORTEX_M == 0)
#if (__CORTEX_M == 4)
//! Initializes the inter-processor communications on the Cortex-M4 core.
void COMM_InitIPCMessages(void)
{
IPC_UserPipeInit();
// Register a callback to handle messages from CM0.
Cy_IPC_Pipe_RegisterCallback(IPC_EP_USRPIPE_ADDR,
Message_Received_for_CM4,
CY_IPC_EP_CYPIPE_CM0_ADDR);
}
#endif // (__CORTEX_M == 4)
//! Sends an inter-processor communication message to the other core.
bool COMM_SendMessageToOtherCore(COMM_IPCMessageID_T message_ID, void * message_data)
{
bool message_sent = false;
MessageBuffer.MessageID = message_ID;
MessageBuffer.Data = message_data;
#if (__CORTEX_M == 0)
if (OK_to_send_from_CM0_to_CM4 == true)
{
OK_to_send_from_CM0_to_CM4 = false;
uint32_t timeout_in_us = 2000;
cy_en_ipc_pipe_status_t ipcStatus;
do
{
ipcStatus = Cy_IPC_Pipe_SendMessage(CY_IPC_EP_USRPIPE_ADDR_CM4_EP,
CY_IPC_EP_USRPIPE_ADDR_CM0_EP,
(uint32_t *) &MessageBuffer,
Message_Received_by_CM4);
Cy_SysLib_DelayUs(1u);
timeout_in_us--;
} while((ipcStatus != CY_IPC_PIPE_SUCCESS) && (timeout_in_us != 0));
message_sent = true;
}
#endif // (__CORTEX_M == 0)
#if (__CORTEX_M == 4)
if (OK_to_send_from_CM4_to_CM0 == true)
{
OK_to_send_from_CM4_to_CM0 = false;
uint32_t timeout_in_us = 2000;
cy_en_ipc_pipe_status_t ipcStatus;
do
{
ipcStatus = Cy_IPC_Pipe_SendMessage(CY_IPC_EP_USRPIPE_ADDR_CM0_EP,
CY_IPC_EP_USRPIPE_ADDR_CM4_EP,
(uint32_t *) &MessageBuffer,
Message_Received_by_CM0);
Cy_SysLib_DelayUs(1u);
timeout_in_us--;
} while((ipcStatus != CY_IPC_PIPE_SUCCESS) && (timeout_in_us != 0));
message_sent = true;
}
#endif // (__CORTEX_M == 4)
return message_sent;
}
/* Private Functions */
#if (__CORTEX_M == 0)
//! Callback for messages received by the CM0 core from the CM4 core.
/*!
* \note This code is executed inside an interrupt handler.
*/
static void Message_Received_for_CM0(uint32_t * msg)
{
switch (((COMM_IPCMessage_T *)msg)->MessageID)
{
default:
case COMM_SMM_DefaultNoMessage:
case COMM_SMM_NoMessage:
break;
case COMM_SMM_RebootImmediately:
// Perform a software reset of both cores.
NVIC_SystemReset();
break;
}
}
static void Message_Received_by_CM4(void)
{
OK_to_send_from_CM0_to_CM4 = true;
}
#endif // (__CORTEX_M == 0)
#if (__CORTEX_M == 4)
//! Callback for messages received by the CM4 core from the CM0 core.
/*!
* \note This code is executed inside an interrupt handler.
*/
static void Message_Received_for_CM4(uint32_t * msg)
{
switch (((COMM_IPCMessage_T *)msg)->MessageID)
{
default:
case COMM_SMM_DefaultNoMessage:
case COMM_SMM_NoMessage:
break;
case COMM_SMM_RebootImmediately:
// This message does nothing on CM4
break;
}
}
static void Message_Received_by_CM0(void)
{
OK_to_send_from_CM4_to_CM0 = true;
}
#endif // (__CORTEX_M == 4)
//! Initializes the IPC user pipe.
static void IPC_UserPipeInit(void)
{
static cy_ipc_pipe_callback_ptr_t ipc_pipe_CbArray[CY_IPC_USRPIPE_CLIENT_CNT];
static const cy_stc_ipc_pipe_config_t userPipeConfig = USRPIPE_CONFIG;
uint32_t savedIntrStatus = Cy_SysLib_EnterCriticalSection();
Cy_IPC_Pipe_Init(&userPipeConfig);
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
}
//! Interrupt service routine for the user pipe.
void IPC_UserPipeISR(void)
{
Cy_IPC_Pipe_ExecuteCallback(IPC_EP_USRPIPE_ADDR);
}

View file

@ -0,0 +1,49 @@
/** \file
* \brief This file contains definitions and prototypes for messaging using inter-processor
* communication (IPC).
*/
#ifndef COMM_IPC_MESSAGES_H
#define COMM_IPC_MESSAGES_H
#ifdef __cplusplus
extern "C" {
#endif
/* Include Files */
/* Preprocessor and Type Definitions */
typedef enum
{
//! This is not an actual message. Upon receipt, do nothing.
COMM_SMM_DefaultNoMessage = 0,
//! Reboot the system immediately upon receipt of this message (Data is "don't care").
COMM_SMM_RebootImmediately,
//! This is not an actual message. Upon receipt, do nothing.
COMM_SMM_NoMessage = 0xFFFFFFFF,
} COMM_IPCMessageID_T;
typedef struct
{
//! The client ID number is the index into the callback array.
uint32_t ClientID;
//! The message ID represents the meaning of the message being sent.
COMM_IPCMessageID_T MessageID;
//! The contents of Data are different for each message ID. See #COMM_IPCMessageID_T for more details.
void * Data;
} COMM_IPCMessage_T;
/* Public Variables */
/* Public Functions */
void COMM_InitIPCMessages(void);
bool COMM_SendMessageToOtherCore(COMM_IPCMessageID_T message_ID, void * message_data);
#ifdef __cplusplus
}
#endif
#endif // COMM_IPC_MESSAGES_H

View file

@ -0,0 +1,48 @@
/** \file
* \brief This file implements utility functions used by the communications package.
*/
/**
* \ingroup CONSOLE
*/
/* Include Files */
#include "KTag.h"
/* Local Definitions and Constants */
/* Public Variables */
/* Private Variables */
static char8 uint64_buffer[20+1];
/* Private Function Prototypes */
/* Public Functions */
//! Converts a UInt64 to a NULL-terminated string.
/*!
* This function is necessary because newlib-nano does not support "%llu" / #PRIu64.
* \see https://answers.launchpad.net/gcc-arm-embedded/+question/257014
*
* \note This function is not reentrant!
*
* \param value pointer to the digital input object.
* \return pointer to a NULL-terminated string containing the base-10 textual representation of #value.
*/
char8 * COMM_UInt64ToDecimal(uint64_t value)
{
char8 * p = uint64_buffer + sizeof(uint64_buffer);
*(--p) = 0x00;
for (bool first_time = true; value || first_time; first_time = false)
{
const uint32_t digit = value % 10;
const char c = '0' + digit;
*(--p) = c;
value = value / 10;
}
return p;
}
/* Private Functions */

View file

@ -0,0 +1,27 @@
/** \file
* \brief Utility functions used by the communications package.
*
* \note As always, <project.h> and <RTOS.h> should be included <I>before</I> this file.
*/
#ifndef COMM_UTIL_H
#define COMM_UTIL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Include Files */
/* Preprocessor and Type Definitions */
/* Public Variables */
/* Public Functions */
char8 * COMM_UInt64ToDecimal(uint64_t value);
#ifdef __cplusplus
}
#endif
#endif // COMM_UTIL_H

View file

@ -0,0 +1,78 @@
/** \file
* \brief This file defines the serial console commands for the Bluetooth Low Energy subsystem.
*/
/* Include Files */
#include "KTag.h"
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED) && (CONFIG__FEATURE_BLE == CONFIG__FEATURE_ENABLED)
/* Local Definitions and Constants */
/* Private Function Prototypes */
/* Public Variables */
/* Private Variables */
/* Public Functions */
/* Private Functions */
//! Console command handler for subcommands of the 'ble' command.
COMM_Console_Command_Result_T COMM_HandleBLECommand(char8 * data, uint32_t size)
{
// data[0] through data[3] is 'ble '.
if (data[4] == '?')
{
COMM_Console_Print_String("ble ? Display this help.\n");
COMM_Console_Print_String("ble cmd <id> Inject the BLE command with ID <id>.\n");
}
else if ( (data[4] == 'c') &&
(data[5] == 'm') &&
(data[6] == 'd') )
{
if (COMM_Console_IsEndOfMessage(data[7]))
{
COMM_Console_Print_String("ERROR: missing BLE command ID!\n");
}
else if (data[7] == ' ')
{
uint16_t id = 0;
if (COMM_Console_DecodeParameterUInt16(&(data[8]), &id) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
if ((id > COMM_BLE_COMMAND_NO_OP) && (id < COMM_BLE_COMMAND_IS_OUT_OF_RANGE))
{
COMM_BLE_Command_T command = {.ID = id, .Data = (void *)0x00};
xQueueSend(COMM_BLE_CommandQueue, &command, 0);
}
else
{
COMM_Console_Print_String("ERROR: specified BLE command ID (");
COMM_Console_Print_UInt16(id);
COMM_Console_Print_String(") is invalid!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: could not comprehend BLE command ID!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: unrecognized or mangled command!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: Unknown BLE command!\n");
}
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED) && (CONFIG__FEATURE_BLE == CONFIG__FEATURE_ENABLED)

View file

@ -0,0 +1,29 @@
/** \file
* \brief This file declares the serial console commands for the Bluetooth Low Energy subsystem.
*/
#ifndef COMM_BLE_CONSOLECOMMANDS_H
#define COMM_BLE_CONSOLECOMMANDS_H
#ifdef __cplusplus
extern "C" {
#endif
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Include Files */
/* Preprocessor and Type Definitions */
/* Public Variables */
/* Public Functions */
COMM_Console_Command_Result_T COMM_HandleBLECommand(char8 * data, uint32_t size);
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
#ifdef __cplusplus
}
#endif
#endif // COMM_BLE_CONSOLECOMMANDS_H

View file

@ -0,0 +1,73 @@
/** \file
* \brief This file defines the serial console commands for this CPU.
*/
/* Include Files */
#include "KTag.h"
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Local Definitions and Constants */
/* Private Function Prototypes */
static COMM_Console_Command_Result_T HandleConsoleHelp(char8 * data, uint32_t size);
static COMM_Console_Command_Result_T HandleConsoleComment(char8 * data, uint32_t size);
static COMM_Console_Command_Result_T HandleConsoleUptime(char8 * data, uint32_t size);
/* Public Variables */
const COMM_Console_Command_Table_Entry_T COMM_Console_Command_Table[] =
{
{"?", " Show this help.", HandleConsoleHelp},
{"#", " Comment (Do not omit the space after the #.)", HandleConsoleComment},
{"event", " Generate an event in the high-level state machine (\'event ?\' for help).", COMM_HandleEventCommand},
{"ble", " Interact with the Bluetooth Low Energy subsystem (try \'ble ?\').", COMM_HandleBLECommand},
{"up", " Display uptime.", HandleConsoleUptime},
{"cpu (r)", " Display CPU usage ('r' to reset maximum).", COMM_RTOS_HandleConsoleCPU},
{"stack", " Display stack usage.", COMM_RTOS_HandleConsoleStack},
{"version", " Display RTOS version.", COMM_RTOS_HandleConsoleVersion},
{"reboot", " Performs a software reset on both cores.", COMM_RTOS_HandleConsoleReboot},
{"nvm", " Interact with the Nonvolatile Memory (try \'nvm ?\').", COMM_NVM_HandleConsoleNVMCommand},
{"reprogram", " Loads the KTag bootloader for OTA reprogramming.", COMM_RTOS_HandleConsoleReprogram},
};
//! Size of the #COMM_Console_Command_Table array (i.e. the number of console commands).
const uint_fast16_t COMM_N_CONSOLE_COMMANDS = (uint_fast16_t) (sizeof(COMM_Console_Command_Table) / sizeof(COMM_Console_Command_Table_Entry_T));
/* Private Variables */
/* Public Functions */
/* Private Functions */
static COMM_Console_Command_Result_T HandleConsoleHelp(char8 * data, uint32_t size)
{
for (uint_fast16_t i = 0; i < COMM_N_CONSOLE_COMMANDS; i++)
{
COMM_Console_Print_String(COMM_Console_Command_Table[i].Command_Name);
COMM_Console_Print_String(" ");
COMM_Console_Print_String(COMM_Console_Command_Table[i].Help);
COMM_Console_Print_String("\n");
vTaskDelay(pdMS_TO_TICKS(10));
}
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
static COMM_Console_Command_Result_T HandleConsoleComment(char8 * data, uint32_t size)
{
COMM_Console_Print_String("Comment.\n");
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
static COMM_Console_Command_Result_T HandleConsoleUptime(char8 * data, uint32_t size)
{
#if (configTICK_RATE_HZ != 1000)
#error This code assumes configTICK_RATE_HZ is set to 1000 (== 1ms ticks)!
#endif // (configTICK_RATE_HZ != 1000)
COMM_Console_Print_String("Up ");
COMM_Console_Print_UInt32(xTaskGetTickCount());
COMM_Console_Print_String(" milliseconds.\n");
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)

View file

@ -0,0 +1,30 @@
/** \file
* \brief This file configures the serial console commands on this CPU.
*/
#ifndef COMM_CONSOLECOMMANDS_H
#define COMM_CONSOLECOMMANDS_H
#ifdef __cplusplus
extern "C" {
#endif
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Include Files */
/* Preprocessor and Type Definitions */
/* Public Variables */
extern const COMM_Console_Command_Table_Entry_T COMM_Console_Command_Table[];
extern const uint_fast16_t COMM_N_CONSOLE_COMMANDS;
/* Public Functions */
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
#ifdef __cplusplus
}
#endif
#endif // COMM_CONSOLECOMMANDS_H

View file

@ -0,0 +1,207 @@
/** \file
* \brief This file defines the serial console commands for the Nonvolatile Memory.
*/
/* Include Files */
#include "KTag.h"
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Local Definitions and Constants */
/* Private Function Prototypes */
/* Public Variables */
/* Private Variables */
/* Public Functions */
/* Private Functions */
//! Console command handler for subcommands of the 'nvm' command.
COMM_Console_Command_Result_T COMM_NVM_HandleConsoleNVMCommand(char8 * data, uint32_t size)
{
// data[0] through data[3] is 'nvm '.
if (data[4] == '?')
{
COMM_Console_Print_String("nvm ? Display this help.\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String("nvm dump Display the entire Nonvolatile Memory.\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String("nvm names Display the NVM parameter names.\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String("nvm get <parameter> Display an individual parameter from NVM.\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String("nvm set <parameter> <value> Assign a value to an individual parameter in NVM (be careful!).\n");
vTaskDelay(pdMS_TO_TICKS(10));
}
else if ((data[4] == 'd') && (data[5] == 'u') && (data[6] == 'm') && (data[7] == 'p'))
{
for (uint8_t i = 0; i < NVM_N_ONCHIP_EEPROM_ENTRIES; i++)
{
COMM_Console_Print_String("NVM[");
COMM_Console_Print_UInt16(i);
COMM_Console_Print_String("]: ");
for (uint8_t j = 0; j < NVM_OnChipEEPROMEntries[i]->Size; j++)
{
char8 buffer[3];
COMM_Console_ByteToHex(buffer, *(NVM_OnChipEEPROMEntries[i]->Value + j));
COMM_Console_Print_String("0x");
COMM_Console_Print_String(buffer);
COMM_Console_Print_String(" ");
}
COMM_Console_Print_String("\n");
}
}
else if ((data[4] == 'n') && (data[5] == 'a') && (data[6] == 'm') && (data[7] == 'e') && (data[8] == 's'))
{
COMM_Console_Print_String("Valid NVM parameters:\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String(" test_1\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String(" test_2\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String(" volume\n");
vTaskDelay(pdMS_TO_TICKS(10));
}
else if ((data[4] == 'g') && (data[5] == 'e') && (data[6] == 't') && (data[7] == ' '))
{
if (strncmp(&data[8], "volume", 6) == 0)
{
COMM_Console_Print_String("Volume: ");
COMM_Console_Print_UInt8(NVM_VOLUME);
COMM_Console_Print_String("\n");
}
else if (strncmp(&data[8], "test_1", 6) == 0)
{
COMM_Console_Print_String("Test 1: ");
COMM_Console_Print_UInt16(NVM_ONCHIP_TEST_1);
COMM_Console_Print_String("\n");
}
else if (strncmp(&data[8], "test_2", 6) == 0)
{
COMM_Console_Print_String("Test 2: ");
COMM_Console_Print_UInt32(NVM_ONCHIP_TEST_2);
COMM_Console_Print_String("\n");
}
else if (strncmp(&data[8], "test_3", 6) == 0)
{
COMM_Console_Print_String("Test 3: ");
COMM_Console_Print_UInt16(NVM_EXTERNAL_TEST_3);
COMM_Console_Print_String("\n");
}
else if (strncmp(&data[8], "test_4", 6) == 0)
{
COMM_Console_Print_String("Test 4: ");
COMM_Console_Print_UInt32(NVM_EXTERNAL_TEST_4);
COMM_Console_Print_String("\n");
}
else
{
COMM_Console_Print_String("ERROR: Unknown NVM parameter!\n");
}
}
else if ((data[4] == 's') && (data[5] == 'e') && (data[6] == 't') && (data[7] == ' '))
{
if (strncmp(&data[8], "volume", 6) == 0)
{
uint8_t volume = 0;
if (COMM_Console_DecodeParameterUInt8(&(data[15]), &volume) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
NVM_VOLUME = volume;
NVM_SaveExternalEEPROMEntry(NVM_VOLUME_ENTRY_PTR);
COMM_Console_Print_String("Volume changed to ");
COMM_Console_Print_UInt8(NVM_VOLUME);
COMM_Console_Print_String("\n");
}
else
{
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
}
}
else if (strncmp(&data[8], "test_1", 6) == 0)
{
uint16_t test_value = 0;
if (COMM_Console_DecodeParameterUInt16(&(data[15]), &test_value) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
NVM_ONCHIP_TEST_1 = test_value;
NVM_SaveOnChipEEPROMEntry(NVM_ONCHIP_TEST_1_ENTRY_PTR);
COMM_Console_Print_String("Test 1 value changed to ");
COMM_Console_Print_UInt16(NVM_ONCHIP_TEST_1);
COMM_Console_Print_String("\n");
}
else
{
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
}
}
else if (strncmp(&data[8], "test_2", 6) == 0)
{
uint32_t test_value = 0;
if (COMM_Console_DecodeParameterUInt32(&(data[15]), &test_value) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
NVM_ONCHIP_TEST_2 = test_value;
NVM_SaveOnChipEEPROMEntry(NVM_ONCHIP_TEST_2_ENTRY_PTR);
COMM_Console_Print_String("Test 2 value changed to ");
COMM_Console_Print_UInt32(NVM_ONCHIP_TEST_2);
COMM_Console_Print_String("\n");
}
else
{
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
}
}
else if (strncmp(&data[8], "test_3", 6) == 0)
{
uint16_t test_value = 0;
if (COMM_Console_DecodeParameterUInt16(&(data[15]), &test_value) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
NVM_EXTERNAL_TEST_3 = test_value;
NVM_SaveExternalEEPROMEntry(NVM_EXTERNAL_TEST_3_ENTRY_PTR);
COMM_Console_Print_String("Test 3 value changed to ");
COMM_Console_Print_UInt16(NVM_EXTERNAL_TEST_3);
COMM_Console_Print_String("\n");
}
else
{
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
}
}
else if (strncmp(&data[8], "test_4", 6) == 0)
{
uint32_t test_value = 0;
if (COMM_Console_DecodeParameterUInt32(&(data[15]), &test_value) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
NVM_EXTERNAL_TEST_4 = test_value;
NVM_SaveExternalEEPROMEntry(NVM_EXTERNAL_TEST_4_ENTRY_PTR);
COMM_Console_Print_String("Test 4 value changed to ");
COMM_Console_Print_UInt32(NVM_EXTERNAL_TEST_4);
COMM_Console_Print_String("\n");
}
else
{
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: Unknown NVM parameter!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: Unknown NVM command!\n");
}
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)

View file

@ -0,0 +1,29 @@
/** \file
* \brief This file declares the serial console commands for the Nonvolatile Memory.
*/
#ifndef COMM_NVM_CONSOLECOMMANDS_H
#define COMM_NVM_CONSOLECOMMANDS_H
#ifdef __cplusplus
extern "C" {
#endif
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Include Files */
/* Preprocessor and Type Definitions */
/* Public Variables */
/* Public Functions */
COMM_Console_Command_Result_T COMM_NVM_HandleConsoleNVMCommand(char8 * data, uint32_t size);
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
#ifdef __cplusplus
}
#endif
#endif // COMM_NVM_CONSOLECOMMANDS_H

View file

@ -0,0 +1,120 @@
/** \file
* \brief This file defines the serial console commands for the RTOS package.
*/
/* Include Files */
#include "KTag.h"
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Local Definitions and Constants */
/* Private Function Prototypes */
/* Public Variables */
/* Private Variables */
/* Public Functions */
/* Private Functions */
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleVersion(char8 * data, uint32_t size)
{
COMM_Console_Print_String("PSoC 6 running FreeRTOS ");
COMM_Console_Print_String(tskKERNEL_VERSION_NUMBER);
#ifdef NDEBUG
COMM_Console_Print_String(" (Release, compiled ");
#else
COMM_Console_Print_String(" (Debug, compiled ");
#endif // NDEBUG
COMM_Console_Print_String(__DATE__);
COMM_Console_Print_String(" ");
COMM_Console_Print_String(__TIME__);
COMM_Console_Print_String(").\n");
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleStack(char8 * data, uint32_t size)
{
for (uint_fast8_t i = 0; i < CONFIG_N_TASK_HANDLES; i++)
{
TaskStatus_t status;
vTaskGetInfo(*CONFIG_TaskHandles[i], &status, pdTRUE, eInvalid);
COMM_Console_Print_String(status.pcTaskName);
COMM_Console_Print_String(": ");
COMM_Console_Print_UInt16(status.usStackHighWaterMark);
COMM_Console_Print_String("\n");
}
// Repeat for the Idle Task.
{
TaskStatus_t status;
vTaskGetInfo(xTaskGetIdleTaskHandle(), &status, pdTRUE, eInvalid);
COMM_Console_Print_String(status.pcTaskName);
COMM_Console_Print_String(": ");
COMM_Console_Print_UInt16(status.usStackHighWaterMark);
COMM_Console_Print_String("\n");
}
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleCPU(char8 * data, uint32_t size)
{
// data[0] through data[3] is 'cpu '.
if (data[4] == 'r')
{
//COMM_Console_Print_String("Max CPU reset.\n");
COMM_Console_Print_String("(Not yet implemented.)\n");
}
else
{
for (uint_fast8_t i = 0; i < CONFIG_N_TASK_HANDLES; i++)
{
TaskStatus_t status;
vTaskGetInfo(*CONFIG_TaskHandles[i], &status, pdTRUE, eInvalid);
COMM_Console_Print_String(status.pcTaskName);
COMM_Console_Print_String(": ");
COMM_Console_Print_UInt32(status.ulRunTimeCounter);
COMM_Console_Print_String("\n");
}
// Repeat for the Idle Task.
{
TaskStatus_t status;
vTaskGetInfo(xTaskGetIdleTaskHandle(), &status, pdTRUE, eInvalid);
COMM_Console_Print_String(status.pcTaskName);
COMM_Console_Print_String(": ");
COMM_Console_Print_UInt16(status.ulRunTimeCounter);
COMM_Console_Print_String("\n");
}
}
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleReboot(char8 * data, uint32_t size)
{
(void) COMM_SendMessageToOtherCore(COMM_SMM_RebootImmediately, NULL);
// Not that it matters...
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleReprogram(char8 * data, uint32_t size)
{
COMM_Console_Print_String("Entering bootloader for BLE reprogramming.\n");
vTaskDelay(pdMS_TO_TICKS(100));
Cy_DFU_ExecuteApp(0u);
// Not that it matters...
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)

View file

@ -0,0 +1,33 @@
/** \file
* \brief This file declares the serial console commands for the RTOS package.
*/
#ifndef COMM_RTOS_CONSOLECOMMANDS_H
#define COMM_RTOS_CONSOLECOMMANDS_H
#ifdef __cplusplus
extern "C" {
#endif
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Include Files */
/* Preprocessor and Type Definitions */
/* Public Variables */
/* Public Functions */
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleVersion(char8 * data, uint32_t size);
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleStack(char8 * data, uint32_t size);
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleCPU(char8 * data, uint32_t size);
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleReboot(char8 * data, uint32_t size);
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleReprogram(char8 * data, uint32_t size);
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
#ifdef __cplusplus
}
#endif
#endif // COMM_RTOS_CONSOLECOMMANDS_H

View file

@ -0,0 +1,189 @@
/** \file
* \brief This file defines the serial console commands for the high-level state machine.
*/
/* Include Files */
#include "KTag.h"
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Local Definitions and Constants */
/* Private Function Prototypes */
static void Simulate_Hit(uint8_t team_ID, uint16_t damage);
/* Public Variables */
/* Private Variables */
/* Public Functions */
//! Console command handler for the 'event' command.
COMM_Console_Command_Result_T COMM_HandleEventCommand(char8 * data, uint32_t size)
{
// data[0] through data[5] is 'event '.
if (data[6] == '?')
{
COMM_Console_Print_String("event ? Display this help.\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String("event raw <id> Inject the event with ID <id>.\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String("event tag <n> Send <n> tag(s).\n");
vTaskDelay(pdMS_TO_TICKS(10));
COMM_Console_Print_String("event hit <t> <d> Simulate a hit from team <t> for <d> damage.\n");
vTaskDelay(pdMS_TO_TICKS(10));
}
else if ( (data[6] == 'r') &&
(data[7] == 'a') &&
(data[8] == 'w') )
{
if (COMM_Console_IsEndOfMessage(data[9]))
{
COMM_Console_Print_String("ERROR: missing event ID!\n");
}
else if (data[9] == ' ')
{
uint16_t id = 0;
if (COMM_Console_DecodeParameterUInt16(&(data[10]), &id) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
if ((id > KEVENT_NO_EVENT) && (id < KEVENT_IS_OUT_OF_RANGE))
{
KEvent_T raw_event = { .ID = id, .Data = (void *)0x00 };
Post_KEvent(&raw_event);
}
else
{
COMM_Console_Print_String("ERROR: specified event ID (");
COMM_Console_Print_UInt16(id);
COMM_Console_Print_String(") is invalid!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: could not comprehend event ID!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: unrecognized or mangled command!\n");
}
}
else if ( (data[6] == 't') &&
(data[7] == 'a') &&
(data[8] == 'g') )
{
if (COMM_Console_IsEndOfMessage(data[9]))
{
if (Send_Tag() == SYSTEMK_RESULT_SUCCESS)
{
COMM_Console_Print_String("Tag sent.\n");
}
else
{
COMM_Console_Print_String("Error: Couldn't send tag!\n");
}
}
else if (data[9] == ' ')
{
uint16_t times = 0;
if (COMM_Console_DecodeParameterUInt16(&(data[10]), &times) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
while (times > 0)
{
if (Send_Tag() == SYSTEMK_RESULT_SUCCESS)
{
COMM_Console_Print_String("Tag sent.\n");
}
else
{
COMM_Console_Print_String("Error: Couldn't send tag!\n");
}
//! \todo Why can't the console command 'event tag <n>' send tags faster than once per second?
vTaskDelay(1000 / portTICK_PERIOD_MS);
times--;
}
}
else
{
COMM_Console_Print_String("ERROR: could not comprehend tag repetitions!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: unrecognized or mangled command!\n");
}
}
else if ( (data[6] == 'h') &&
(data[7] == 'i') &&
(data[8] == 't') )
{
if (COMM_Console_IsEndOfMessage(data[9]))
{
Simulate_Hit(1, 10);
COMM_Console_Print_String("Hit!\n");
}
else if (data[9] == ' ')
{
uint8_t team_ID = 0;
uint16_t damage = 10;
if (COMM_Console_DecodeParameterUInt8(&(data[10]), &team_ID) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
const char * damage_location;
// Damage is the first parameter after team ID.
if (COMM_Console_FindNthParameter(&(data[10]), 1, &damage_location) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
if (COMM_Console_DecodeParameterUInt16(damage_location, &damage) != COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
{
COMM_Console_Print_String("ERROR: could not comprehend damage--using default.\n");
damage = 10;
}
}
Simulate_Hit(team_ID, damage);
COMM_Console_Print_String("Hit!\n");
}
else
{
COMM_Console_Print_String("ERROR: could not comprehend team ID!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: unrecognized or mangled command!\n");
}
}
else
{
COMM_Console_Print_String("ERROR: Unknown event command!\n");
}
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
}
/* Private Functions */
static void Simulate_Hit(uint8_t team_ID, uint16_t damage)
{
static DecodedPacket_T Simulated_Tag_Rx_Buffer;
static KEvent_T tag_received_event;
Simulated_Tag_Rx_Buffer.Tag.type = DECODED_PACKET_TYPE_TAG_RECEIVED;
Simulated_Tag_Rx_Buffer.Tag.protocol = LASER_X_PROTOCOL;
Simulated_Tag_Rx_Buffer.Tag.player_ID = 0x00;
Simulated_Tag_Rx_Buffer.Tag.team_ID = team_ID;
Simulated_Tag_Rx_Buffer.Tag.damage = damage;
Simulated_Tag_Rx_Buffer.Tag.color = GetColorFromTeamID(team_ID);
tag_received_event.ID = KEVENT_TAG_RECEIVED;
tag_received_event.Data = &Simulated_Tag_Rx_Buffer;
Post_KEvent(&tag_received_event);
}
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)

View file

@ -0,0 +1,29 @@
/** \file
* \brief This file declares the serial console commands for the high-level state machine.
*/
#ifndef COMM_STATE_CONSOLECOMMANDS_H
#define COMM_STATE_CONSOLECOMMANDS_H
#ifdef __cplusplus
extern "C" {
#endif
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
/* Include Files */
/* Preprocessor and Type Definitions */
/* Public Variables */
/* Public Functions */
COMM_Console_Command_Result_T COMM_HandleEventCommand(char8 * data, uint32_t size);
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
#ifdef __cplusplus
}
#endif
#endif // COMM_STATE_CONSOLECOMMANDS_H