2020TPC-SW/2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE_UART.c
2025-02-01 19:52:04 -06:00

177 lines
6.6 KiB
C

/* 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 */