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