void HandleLeds(void) { static uint32 ledTimer = LED_TIMEOUT; static uint8 greenLed = LED_OFF; /* Blink green LED to indicate that device is scanning */ if(CyBle_GetState() == CYBLE_STATE_SCANNING) { if(--ledTimer == 0u) { ledTimer = LED_TIMEOUT; greenLed ^= LED_OFF; Scanning_LED_Write(greenLed); } } /* Blink blue LED to indicate that device has received a notification */ else if(CyBle_GetState() == CYBLE_STATE_CONNECTED) { if((LED_ON == Notification_LED_Read()) && (--ledTimer == 0u)) { ledTimer = LED_TIMEOUT; Notification_LED_Write(LED_OFF); } } else { /* nothing else */ } }
/******************************************************************************* * Function Name: ConnectToPeripheralDevice ******************************************************************************** * Summary: * Connects to Peripheral device with given BD Address. * * Parameters: * void * * Return: * void * *******************************************************************************/ void ConnectToPeripheralDevice(void) { CYBLE_API_RESULT_T apiResult; /* If flag has been set to connect to a device... */ if(clientConnectToDevice) { /* Process pending BLE events */ CyBle_ProcessEvents(); #if 0 if(CYBLE_STATE_SCANNING == CyBle_GetState()) { CyBle_GapcStopScan(); #ifdef DEBUG_ENABLED UART_UartPutString("Stop Scan called from clientConnectToDevice "); SendBLEStatetoUART(CyBle_GetState()); UART_UartPutCRLF(' '); #endif CyBle_ProcessEvents(); } #endif if(CYBLE_STATE_DISCONNECTED == CyBle_GetState()) { /* Reset the flag to connect to a device*/ clientConnectToDevice = FALSE; /* Connect to the device whose address has been saved as part of * potential node search */ apiResult = CyBle_GapcConnectDevice(&peripAddr); if(apiResult != CYBLE_ERROR_OK) { #ifdef DEBUG_ENABLED UART_UartPutString("Connect Request failed "); SendBLEStatetoUART(CyBle_GetState()); UART_UartPutCRLF(' '); #endif } else { #ifdef DEBUG_ENABLED UART_UartPutString("Connect Request Sent "); SendBLEStatetoUART(CyBle_GetState()); UART_UartPutCRLF(' '); #endif } /* Process pending BLE events */ CyBle_ProcessEvents(); } } }
/******************************************************************************* * Function Name: LowPowerImplementation() ******************************************************************************** * Summary: * Implements low power in the project. * * Parameters: * None * * Return: * None * * Theory: * The function tries to enter deep sleep as much as possible - whenever the * BLE is idle and the UART transmission/reception is not happening. At all other * times, the function tries to enter CPU sleep. * *******************************************************************************/ static void LowPowerImplementation(void) { CYBLE_LP_MODE_T bleMode; uint8 interruptStatus; /* For advertising and connected states, implement deep sleep * functionality to achieve low power in the system. For more details * on the low power implementation, refer to the Low Power Application * Note. */ if((CyBle_GetState() == CYBLE_STATE_ADVERTISING) || (CyBle_GetState() == CYBLE_STATE_CONNECTED)) { /* Request BLE subsystem to enter into Deep-Sleep mode between connection and advertising intervals */ bleMode = CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP); /* Disable global interrupts */ interruptStatus = CyEnterCriticalSection(); /* When BLE subsystem has been put into Deep-Sleep mode */ if(bleMode == CYBLE_BLESS_DEEPSLEEP) { /* And it is still there or ECO is on */ if((CyBle_GetBleSsState() == CYBLE_BLESS_STATE_ECO_ON) || (CyBle_GetBleSsState() == CYBLE_BLESS_STATE_DEEPSLEEP)) { #if (DEBUG_UART_ENABLED == ENABLED) /* Put the CPU into the Deep-Sleep mode when all debug information has been sent */ if((UART_DEB_SpiUartGetTxBufferSize() + UART_DEB_GET_TX_FIFO_SR_VALID) == 0u) { CySysPmDeepSleep(); } else /* Put the CPU into Sleep mode and let SCB to continue sending debug data */ { CySysPmSleep(); } #else CySysPmDeepSleep(); #endif /* (DEBUG_UART_ENABLED == ENABLED) */ } } else /* When BLE subsystem has been put into Sleep mode or is active */ { /* And hardware doesn't finish Tx/Rx opeation - put the CPU into Sleep mode */ if(CyBle_GetBleSsState() != CYBLE_BLESS_STATE_EVENT_CLOSE) { CySysPmSleep(); } } /* Enable global interrupt */ CyExitCriticalSection(interruptStatus); } }
/******************************************************************************* * Function Name: InitializeSystem ******************************************************************************** * * Summary: * Systm initialization function. * * Parameters: * None * * Return: * None * *******************************************************************************/ void InitializeSystem(void) { CyGlobalIntEnable; /* Enable Global Interrupts*/ /* Internal low power oscillator is no longer required after Watch Crystal oscillator is started */ CySysClkIloStop(); /* Set the divider for ECO, ECO will be used as source when IMO is switched off to save power */ CySysClkWriteEcoDiv(CY_SYS_CLK_ECO_DIV8); BLE_Engine_Start(); /* Kick start the BLE GATT server and client interface */ /* Wait for BLE Component to Initialize */ while (CyBle_GetState() == CYBLE_STATE_INITIALIZING) { CyBle_ProcessEvents(); } #if BLE_COEXISTENCE_ENABLE *(uint32*)(CYREG_RADIO_TX_RX_MUX_REGISTER)&= ~RADIO_TX_RX_MUX_MASK; /* Clear Previous mux selection */ *(uint32*)(CYREG_RADIO_TX_RX_MUX_REGISTER) |= BLESS_MUX_INPUT_MASK; /* Set BLESS as the source of the mux */ *(uint32*)(CYREG_BLE_BLESS_RF_CONFIG) |= RADIO_TX_RX_SEL; /* Select Tx enable & Rx enable signals from BLESS as input to mux */ Radio_Control_Interrupt_StartEx(&Radio_Control_ISR); #endif /* End of #if BLE_COEXISTENCE_ENABLE */ }
void Initialization(void) { /* Set the divider for ECO, ECO will be used as source when IMO is switched off to save power, to drive the HFCLK */ CySysClkWriteEcoDiv(CY_SYS_CLK_ECO_DIV8); /* Do the following for achieving lowest possible WCO & ECO startup current: * 1. Shut down the ECO (to reduce power consumption while WCO is starting) * 2. Enable WDT counter 0 to wakeup the system after 500ms (500ms = WCO startup time) * 3. Configure PSoC 4 BLE device in DeepSleep mode for the 500ms WCO startup time * 4. After WCO is enabled, restart the ECO so that BLESS interface can function * 5. Enable WDT counter 1 to wakeup the system after 1ms (1ms = ECO startup time) * 5. Configure PSoC 4 BLE device in DeepSleep mode for the 1ms ECO startup time */ CySysClkEcoStop(); /* Shutdown the ECO and later re-start in low power mode after WCO is turned on */ WDT_Interrupt_StartEx(WDT_Handler); /* Initialize WDT interrupt */ WCO_ECO_LowPowerStart(); /* Enable WCO & ECO in low power mode using WDT counter 0/1 as system wakeup sources respectively */ CyBle_Start(BLE_AppEventHandler); while (CyBle_GetState() == CYBLE_STATE_INITIALIZING) { CyBle_ProcessEvents(); } }
/****************************************************************************** ##Function Name: CyBle_GattcStartDiscovery ******************************************************************************* Summary: Starts the automatic server discovery process. Two events may be generated after calling this function - CYBLE_EVT_GATTC_DISCOVERY_COMPLETE or CYBLE_EVT_GATTC_ERROR_RSP. The CYBLE_EVT_GATTC_DISCOVERY_COMPLETE event is generated when the remote device was successfully discovered. The CYBLE_EVT_GATTC_ERROR_RSP is generated if the device discovery is failed. Parameters: connHandle: The handle which consists of the device ID and ATT connection ID. Return: CYBLE_API_RESULT_T : Return value indicates if the function succeeded or failed. Following are the possible error codes. CYBLE_ERROR_OK - On successful operation CYBLE_ERROR_INVALID_PARAMETER - 'connHandle' value does not represent any existing entry. in the Stack CYBLE_ERROR_INVALID_OPERATION - The operation is not permitted. CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed. ******************************************************************************/ CYBLE_API_RESULT_T CyBle_GattcStartDiscovery(CYBLE_CONN_HANDLE_T connHandle) { uint8 j; CYBLE_API_RESULT_T apiResult; if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else { CyBle_ServiceInit(); cyBle_connHandle = connHandle; /* Clean old discovery information */ for(j = 0u; j < (uint8) CYBLE_SRVI_COUNT; j++) { (void)memset(&cyBle_serverInfo[j].range, 0, sizeof(cyBle_serverInfo[0].range)); } apiResult = CyBle_GattcDiscoverAllPrimaryServices(connHandle); if(CYBLE_ERROR_OK == apiResult) { CyBle_SetClientState(CYBLE_CLIENT_STATE_SRVC_DISCOVERING); cyBle_eventHandlerFlag |= CYBLE_AUTO_DISCOVERY; } } return (apiResult); }
void HandleI2CWrite(void) { CYBLE_GATTC_WRITE_CMD_REQ_T I2CDataWriteCmd; /* Check if the peripheral is connected before trying to write*/ if(CyBle_GetState() == CYBLE_STATE_CONNECTED) { /* update the attribute handle to be written */ I2CDataWriteCmd.attrHandle = I2CWriteDataCharHandle; I2CDataWriteCmd.value.len = byteCnt; I2CDataWriteCmd.value.val = wrBuf; do { apiResult = CyBle_GattcWriteWithoutResponse(cyBle_connHandle, &I2CDataWriteCmd); CyBle_ProcessEvents(); } while((CYBLE_ERROR_OK != apiResult) && (CYBLE_STATE_CONNECTED == cyBle_state)); } }
/****************************************************************************** ##Function Name: CyBle_HrssSendNotification ******************************************************************************* Summary: Sends notification of a specified Heart Rate Service characteristic value to the Client device. No response is expected. The CYBLE_EVT_HRSC_NOTIFICATION event is received by the peer device, on invoking this function. Parameters: connHandle: The connection handle which consist of the device ID and ATT connection ID. charIndex: The index of a service characteristic. attrSize: The size of the characteristic value attribute. The Heart Rate Measurement characteristic has a 20 byte length (by default). The Body Sensor Location and Control Point characteristic both have 1 byte length. *attrValue: The pointer to the characteristic value data that should be sent to the client device. Return: Return value is of type CYBLE_API_RESULT_T. * CYBLE_ERROR_OK - The request handled successfully * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameter failed * CYBLE_ERROR_INVALID_OPERATION - This operation is not permitted * CYBLE_ERROR_INVALID_STATE - Connection with the client is not established * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed. * CYBLE_ERROR_NTF_DISABLED - Notification is not enabled by the client. ******************************************************************************/ CYBLE_API_RESULT_T CyBle_HrssSendNotification(CYBLE_CONN_HANDLE_T connHandle, CYBLE_HRS_CHAR_INDEX_T charIndex, uint8 attrSize, uint8 *attrValue) { CYBLE_API_RESULT_T apiResult; CYBLE_GATTS_HANDLE_VALUE_NTF_T ntfReqParam; /* Send Notification if it is enabled and connected */ if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else if(charIndex >= CYBLE_HRS_CHAR_COUNT) { apiResult = CYBLE_ERROR_INVALID_PARAMETER; } else if((cyBle_hrss.hrmCccdHandle == CYBLE_GATT_INVALID_ATTR_HANDLE_VALUE) || (!CYBLE_IS_NOTIFICATION_ENABLED(cyBle_hrss.hrmCccdHandle))) { apiResult = CYBLE_ERROR_NTF_DISABLED; } else { /* Fill all fields of write request structure ... */ ntfReqParam.attrHandle = cyBle_hrss.charHandle[charIndex]; ntfReqParam.value.val = attrValue; ntfReqParam.value.len = attrSize; /* Send notification to client using previously filled structure */ apiResult = CyBle_GattsNotification(connHandle, &ntfReqParam); } return (apiResult); }
/******************************************************************************* * Function Name: InitializeSystem ******************************************************************************** * * Summary: * Systm initialization function. * * Parameters: * None * * Return: * None * *******************************************************************************/ void InitializeSystem(void) { CyGlobalIntEnable; /* Enable Global Interrupts*/ /* Internal low power oscillator is no longer required after Watch Crystal oscillator is started */ CySysClkIloStop(); /* Set the divider for ECO, ECO will be used as source when IMO is switched off to save power */ CySysClkWriteEcoDiv(CY_SYS_CLK_ECO_DIV8); BLE_Engine_Start(); /* start the BLE interface */ /* Wait for BLE Component to Initialize */ while (CyBle_GetState() == CYBLE_STATE_INITIALIZING) { CyBle_ProcessEvents(); } #if (CONSOLE_LOG_ENABLE) Console_Start(); /* Console log interface */ Console_UartPutString("System initialization complete\r\n"); #endif /* End of #if (CONSOLE_LOG_ENABLE) */ /* ADD YOUR CODE TO INITIALIZE OTHER COMPONENTS IN YOUR DESIGN */ }
/******************************************************************************* * Function Name: StackEventHandler ******************************************************************************** * * Summary: * This is an event callback function to receive events from the BLE Component. * * Parameters: * uint8 event: Event from the CYBLE component * void* eventParams: A structure instance for corresponding event type. The * list of event structure is described in the component * datasheet. * * Return: * None * *******************************************************************************/ void StackEventHandler(uint32 event, void *eventParam) { switch(event) { /* Mandatory events to be handled by Find Me Target design */ case CYBLE_EVT_STACK_ON: case CYBLE_EVT_GAP_DEVICE_DISCONNECTED: /* Start BLE advertisement for 30 seconds and update link * status on LEDs */ CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST); Advertising_LED_Write(LED_ON); break; case CYBLE_EVT_GAPP_ADVERTISEMENT_START_STOP: if(CyBle_GetState() == CYBLE_STATE_DISCONNECTED) { /* Advertisement event timed out, go to low power * mode (Hibernate mode) and wait for an external * user event to wake up the device again */ Advertising_LED_Write(LED_OFF); Hibernate_LED_Write(LED_ON); Wakeup_SW_ClearInterrupt(); Wakeup_Interrupt_ClearPending(); Wakeup_Interrupt_Start(); CySysPmHibernate(); } break; default: break; } }
/****************************************************************************** ##Function Name: CyBle_HtssSendIndication ******************************************************************************* Summary: Sends indication with a characteristic value of the Health Thermometer Service, which is a value specified by charIndex, to the Client device. Parameters: connHandle: The connection handle. charIndex: The index of the service characteristic. attrSize: The size of the characteristic value attribute. *attrValue: The pointer to the characteristic value data that should be sent to the Client device. Return: Return value is of type CYBLE_API_RESULT_T. * CYBLE_ERROR_OK - The request handled successfully * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameter failed * CYBLE_ERROR_INVALID_OPERATION - This operation is not permitted * CYBLE_ERROR_INVALID_STATE - Connection with the client is not established * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed * CYBLE_ERROR_IND_DISABLED - Indication is not enabled by the client ******************************************************************************/ CYBLE_API_RESULT_T CyBle_HtssSendIndication(CYBLE_CONN_HANDLE_T connHandle, CYBLE_HTS_CHAR_INDEX_T charIndex, uint8 attrSize, uint8 *attrValue) { CYBLE_API_RESULT_T apiResult; /* Send Notification if it is enabled and connected */ if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else if(!CYBLE_IS_INDICATION_ENABLED(cyBle_htss.charInfo[charIndex].descrHandle[CYBLE_HTS_CCCD])) { apiResult = CYBLE_ERROR_IND_DISABLED; } else { CYBLE_GATTS_HANDLE_VALUE_NTF_T ntfReqParam; /* Fill all fields of write request structure ... */ ntfReqParam.attrHandle = cyBle_htss.charInfo[charIndex].charHandle; ntfReqParam.value.val = attrValue; ntfReqParam.value.len = attrSize; /* Send indication to client using previously filled structure */ apiResult = CyBle_GattsIndication(connHandle, &ntfReqParam); /* Save handle to support service specific value confirmation response from client */ if(apiResult == CYBLE_ERROR_OK) { cyBle_htssReqHandle = ntfReqParam.attrHandle; } } return (apiResult); }
/****************************************************************************** * Function Name: CyBle_AnssSendNotification ***************************************************************************//** * * Sends a notification with the characteristic value, as specified by its charIndex, * to the Client device. * On enabling notification successfully for a service characteristic, if the GATT * server has an updated value to be notified to the GATT Client, it sends out a * 'Handle Value Notification' which results in CYBLE_EVT_ANSC_NOTIFICATION event * at the GATT Client's end. * * \param connHandle: The connection handle. * \param charIndex: The index of the service characteristic of type CYBLE_ANS_CHAR_INDEX_T. * The valid values are, * * CYBLE_ANS_UNREAD_ALERT_STATUS * * CYBLE_ANS_NEW_ALERT * \param attrSize: The size of the characteristic value attribute. * \param attrValue: The pointer to the characteristic value data that should be sent * to the Client device. * * \return * Return value is of type CYBLE_API_RESULT_T. * * CYBLE_ERROR_OK - The function completed successfully. * * CYBLE_ERROR_INVALID_PARAMETER - Validation of input parameter is failed. * * CYBLE_ERROR_INVALID_OPERATION - Operation is invalid for this. * characteristic. * * CYBLE_ERROR_INVALID_STATE - Connection with the client is not established. * * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed. * * CYBLE_ERROR_NTF_DISABLED - Notification is not enabled by the client. * ******************************************************************************/ CYBLE_API_RESULT_T CyBle_AnssSendNotification(CYBLE_CONN_HANDLE_T connHandle, CYBLE_ANS_CHAR_INDEX_T charIndex, uint8 attrSize, uint8 *attrValue) { CYBLE_API_RESULT_T apiResult = CYBLE_ERROR_INVALID_PARAMETER; if((charIndex == CYBLE_ANS_NEW_ALERT) || (charIndex == CYBLE_ANS_UNREAD_ALERT_STATUS)) { /* Send Notification if it is enabled and connected */ if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else if(!CYBLE_IS_NOTIFICATION_ENABLED(cyBle_anss.charInfo[charIndex].descrHandle[CYBLE_ANS_CCCD])) { apiResult = CYBLE_ERROR_NTF_DISABLED; } else { CYBLE_GATTS_HANDLE_VALUE_NTF_T ntfReqParam; /* Fill all fields of write request structure ... */ ntfReqParam.attrHandle = cyBle_anss.charInfo[charIndex].charHandle; ntfReqParam.value.val = attrValue; ntfReqParam.value.len = attrSize; /* Send notification to client using previously filled structure */ apiResult = CyBle_GattsNotification(connHandle, &ntfReqParam); } } return (apiResult); }
/******************************************************************************* * Function Name: LowPowerImplementation() ******************************************************************************** * Summary: * Implements low power in the project. * * Parameters: * None * * Return: * None * * Theory: * The function tries to enter deep sleep as much as possible - whenever the * BLE is idle and the UART transmission/reception is not happening. At all other * times, the function tries to enter CPU sleep. * *******************************************************************************/ static void LowPowerImplementation(void) { CYBLE_LP_MODE_T bleMode; uint8 interruptStatus; /* For advertising and connected states, implement deep sleep * functionality to achieve low power in the system. For more details * on the low power implementation, refer to the Low Power Application * Note. */ if((CyBle_GetState() == CYBLE_STATE_ADVERTISING) || (CyBle_GetState() == CYBLE_STATE_CONNECTED)) { bleMode = CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP); interruptStatus = CyEnterCriticalSection(); if(bleMode == CYBLE_BLESS_DEEPSLEEP) { if((CyBle_GetBleSsState() == CYBLE_BLESS_STATE_ECO_ON) || (CyBle_GetBleSsState() == CYBLE_BLESS_STATE_DEEPSLEEP)) { /* Deep sleep only if UART completes transfer and we * are not waiting for the user to enter anything. */ if(((UART_SpiUartGetTxBufferSize() + UART_GET_TX_FIFO_SR_VALID) == 0u) && (ancsUsageState != ANCS_USAGE_INCOMING_CALL_WAITING_FOR_INPUT)) { CySysPmDeepSleep(); } else { CySysPmSleep(); } } } else { if(CyBle_GetBleSsState() != CYBLE_BLESS_STATE_EVENT_CLOSE) { CySysPmSleep(); } } CyExitCriticalSection(interruptStatus); } }
/******************************************************************************* * Function Name: RestartCentralScanning ******************************************************************************** * Summary: * Restarts Central scanning. Also, if the time that the device has remained * in Central role exceeds pre-determined value, then the switch role flag is set. * * Parameters: * void * * Return: * void * *******************************************************************************/ void RestartCentralScanning(void) { /* If the current role is Central and the Central time has exceeded the preset time, * then set the flag to switch role to Peripheral */ if((BLE_CENTRAL == ble_gap_state) && (WatchDog_CurrentCount() - centralStartedTime > CENTRAL_STATE_SPAN) && ((CYBLE_STATE_DISCONNECTED == CyBle_GetState()) || (CYBLE_STATE_SCANNING == CyBle_GetState()))) { /* Switch role flag set */ switch_Role = TRUE; #ifdef DEBUG_ENABLED UART_UartPutString("switchRole from restartScanning loop "); UART_UartPutCRLF(' '); #endif return; } /* If restart scanning flag is set, the restart the Central scanning */ if(restartScanning) { /* Process pending BLE events */ CyBle_ProcessEvents(); if(CYBLE_STATE_DISCONNECTED == CyBle_GetState()) { /* Reset the restart scanning flag */ restartScanning = FALSE; #ifdef DEBUG_ENABLED UART_UartPutString("restartScanning loop "); UART_UartPutCRLF(' '); #endif /* Start Central scan and process the event */ CyBle_GapcStartScan(CYBLE_SCANNING_FAST); CyBle_ProcessEvents(); #ifdef DEBUG_ENABLED UART_UartPutString("Start Scan from restartScanning loop "); UART_UartPutCRLF(' '); #endif } } }
/* BLE stack event handler */ void BLE_AppEventHandler(uint32 event, void* eventParam) { CYBLE_API_RESULT_T apiResult; switch (event) { /********************************************************** * General Events ***********************************************************/ /* This event is received when component is Started */ case CYBLE_EVT_STACK_ON: /* Start with a regular UID/URL packet */ isRegularAdvScheduled = true; ConfigureAdvPacket(isRegularAdvScheduled); initCounter = 0; WDT_EnableWcoCounter(); /* Enable WDT's WCO counter (counter 0) */ break; case CYBLE_EVT_GAPP_ADVERTISEMENT_START_STOP: if(CyBle_GetState() != CYBLE_STATE_ADVERTISING) { /* On advertisement timeout, restart advertisement */ #if (IS_EDDYSTONE_TLM_PRESENT) if(true == isRegularAdvScheduled) { /* Configure for TLM packet */ isRegularAdvScheduled = false; } else { /* Configure for regular UID/URL packet */ isRegularAdvScheduled = true; } ConfigureAdvPacket(isRegularAdvScheduled); #endif CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_CUSTOM); } break; default: break; } }
/******************************************************************************* * Function Name: Handleleds ******************************************************************************** * * Summary: * This is used to TURN ON and TURN OFF the LEDs based on the "state". * * Parameters: * None * Return: * None * *******************************************************************************/ void HandleLeds() { /*if Disconnected TURN ON RED LED*/ if(CyBle_GetState()==CYBLE_STATE_DISCONNECTED) { Advertising_Led_Write(LED_OFF); Disconnect_Led_Write(LED_ON); Connect_Led_Write(LED_OFF); } /*if Advertising TURN ON BLUE LED*/ else if(CyBle_GetState()==CYBLE_STATE_ADVERTISING) { Advertising_Led_Write(LED_ON); Disconnect_Led_Write(LED_OFF); Connect_Led_Write(LED_OFF); } /*If Connected TURN ON GREEN LED*/ else if(CyBle_GetState()==CYBLE_STATE_CONNECTED) { Advertising_Led_Write(LED_OFF); Disconnect_Led_Write(LED_OFF); Connect_Led_Write(LED_ON); } }
/****************************************************************************** ##Function Name: CyBle_GattsReInitGattDb ******************************************************************************* Summary: Reinitializes the GATT database. Parameters: None Return: CYBLE_API_RESULT_T: An API result states if the API succeeded or failed with error codes: * CYBLE_ERROR_OK: GATT database was reinitialized successfully * CYBLE_ERROR_INVALID_STATE: If the function is called in any state except CYBLE_STATE_DISCONNECTED. * Any of the CyBle_GattsDbRegister() stack API function return values. ******************************************************************************/ CYBLE_API_RESULT_T CyBle_GattsReInitGattDb(void) { CYBLE_API_RESULT_T apiResult; if(CYBLE_STATE_DISCONNECTED == CyBle_GetState()) { apiResult = CyBle_GattsDbRegister(cyBle_gattDB, CYBLE_GATT_DB_INDEX_COUNT, CYBLE_GATT_DB_MAX_VALUE_LEN); } else { apiResult = CYBLE_ERROR_INVALID_STATE; } return(apiResult); }
/******************************************************************************* * Function Name: AppCallBack() ******************************************************************************** * * Summary: * This is an event callback function to receive events from the BLE Component. * * Parameters: * event - the event code * *eventParam - the event parameters * *******************************************************************************/ void AppCallBack(uint32 event, void* eventParam) { #ifdef DEBUG_OUT DebugOut(event, eventParam); #endif switch(event) { case CYBLE_EVT_GAP_DEVICE_DISCONNECTED: Disconnect_LED_Write(LED_ON); mainTimer = 0; case CYBLE_EVT_STACK_ON: heartRateSimulation = DISABLED; /* Put the device into discoverable mode so that remote can search it. */ StartAdvertisement(ADV_STATE_GENERAL); Advertising_LED_Write(LED_ON); advState = ADV_STATE_GENERAL; break; case CYBLE_EVT_GAPP_ADVERTISEMENT_START_STOP: if(CyBle_GetState() == CYBLE_STATE_DISCONNECTED) /* ADV timed out */ { if(advState == ADV_STATE_GENERAL) { Advertising_LED_Write(LED_OFF); CyDelay(100); StartAdvertisement(ADV_STATE_WHITELIST); Advertising_LED_Write(LED_ON); advState = ADV_STATE_WHITELIST; } else { /* No connectionestablished, shut down ADV */ Advertising_LED_Write(LED_OFF); } } break; case CYBLE_EVT_GAP_DEVICE_CONNECTED: Disconnect_LED_Write(LED_OFF); Advertising_LED_Write(LED_OFF); break; default: break; } }
/******************************************************************************* * Function Name: StackEventHandler ******************************************************************************** * * Summary: * This is an event callback function to receive events from the BLE Component. * * Parameters: * uint8 event: Event from the CYBLE component * void* eventParams: A structure instance for corresponding event type. The * list of event structure is described in the component * datasheet. * * Return: * None * *******************************************************************************/ void StackEventHandler(uint32 event, void *eventParam) { switch(event) { /* Mandatory events to be handled by Find Me Target design */ case CYBLE_EVT_GAP_DEVICE_DISCONNECTED: case CYBLE_EVT_STACK_ON: StartAdvertisement(ADV_STATE_GENERAL); linkAlertLevel = NO_ALERT; Advertising_LED_Write(LED_ON); Disconnection_LED_Write(LED_OFF); advState = ADV_STATE_GENERAL; break; case CYBLE_EVT_GAP_DEVICE_CONNECTED: /* Indicate successful BLE link establishment * by turning off Advertising_LED and Disconnection_LED */ linkAlertLevel = NO_ALERT; Advertising_LED_Write(LED_OFF); break; case CYBLE_EVT_GAPP_ADVERTISEMENT_START_STOP: if(CyBle_GetState() == CYBLE_STATE_DISCONNECTED) /* ADV timed out */ { if(advState == ADV_STATE_GENERAL) { Advertising_LED_Write(LED_OFF); CyDelay(100); Advertising_LED_Write(LED_ON); StartAdvertisement(ADV_STATE_WHITELIST); advState = ADV_STATE_WHITELIST; } else { /* No connection established, shut down ADV */ Advertising_LED_Write(LED_OFF); Disconnection_LED_Write(LED_ON); } } break; default: break; } }
/****************************************************************************** ##Function Name: CyBle_GlssSendIndication ******************************************************************************* Summary: Sends a indication of the specified characteristic to the client device, as defined by the charIndex value. Parameters: connHandle: The connection handle which consist of the device ID and ATT connection ID. charIndex: The index of the service characteristic. attrSize: The size of the characteristic value attribute. *attrValue: Pointer to the Characteristic value data that should be sent to Client device. Return: Return value is of type CYBLE_API_RESULT_T. * CYBLE_ERROR_OK - The request handled successfully * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameter failed * CYBLE_ERROR_INVALID_OPERATION - Operation is invalid for this characteristic * CYBLE_ERROR_GATT_DB_INVALID_ATTR_HANDLE - Optional characteristic is absent * CYBLE_ERROR_INVALID_STATE - Connection with the client is not established * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed * CYBLE_ERROR_IND_DISABLED - Indication is not enabled by the client ******************************************************************************/ CYBLE_API_RESULT_T CyBle_GlssSendIndication(CYBLE_CONN_HANDLE_T connHandle, CYBLE_GLS_CHAR_INDEX_T charIndex, uint8 attrSize, uint8 *attrValue) { CYBLE_API_RESULT_T apiResult; /* Send Indication if it is enabled and connected */ if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else if(charIndex >= CYBLE_GLS_CHAR_COUNT) { apiResult = CYBLE_ERROR_INVALID_PARAMETER; } else if(CYBLE_GATT_INVALID_ATTR_HANDLE_VALUE == cyBle_glss.charInfo[charIndex].cccdHandle) { apiResult = CYBLE_ERROR_GATT_DB_INVALID_ATTR_HANDLE; } else if(!CYBLE_IS_INDICATION_ENABLED(cyBle_glss.charInfo[charIndex].cccdHandle)) { apiResult = CYBLE_ERROR_IND_DISABLED; } else { CYBLE_GATTS_HANDLE_VALUE_IND_T indParam; /* Fill all fields of write request structure ... */ indParam.attrHandle = cyBle_glss.charInfo[charIndex].charHandle; indParam.value.val = attrValue; indParam.value.len = attrSize; /* Send notification to client using previously filled structure */ apiResult = CyBle_GattsIndication(connHandle, &indParam); if(CYBLE_ERROR_OK == apiResult) { /* Save handle to support service specific value confirmation response from client */ cyBle_glssReqHandle = indParam.attrHandle; } } return (apiResult); }
/******************************************************************************* * Function Name: main ******************************************************************************** * * Summary: * Main function. * * Parameters: * None * * Return: * None * *******************************************************************************/ int main() { CYBLE_API_RESULT_T apiResult; CYBLE_STATE_T bleState; CyGlobalIntEnable; PWM_Start(); UART_Start(); UART_UartPutString("Welcome to BLE OOB Pairing Demo\r\n"); apiResult = CyBle_Start(StackEventHandler); if(apiResult != CYBLE_ERROR_OK) { /* BLE stack initialization failed, check your configuration */ CYASSERT(0); } CyBle_IasRegisterAttrCallback(IasEventHandler); for(;;) { /* Single API call to service all the BLE stack events. Must be * called at least once in a BLE connection interval */ CyBle_ProcessEvents(); bleState = CyBle_GetState(); if(bleState != CYBLE_STATE_STOPPED && bleState != CYBLE_STATE_INITIALIZING) { /* Configure BLESS in DeepSleep mode */ CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP); /* Configure PSoC 4 BLE system in sleep mode */ CySysPmSleep(); /* BLE link layer timing interrupt will wake up the system */ } } }
/******************************************************************************* * Function Name: Timer_Interrupt ******************************************************************************** * * Summary: * Handles the Interrupt Service Routine for the WDT timer. * It is called from common WDT ISR located in BLE component. * *******************************************************************************/ void Timer_Interrupt(void) { if(CySysWdtGetInterruptSource() & WDT_INTERRUPT_SOURCE) { static uint8 led = LED_OFF; /* Blink LED to indicate that device advertises */ if(CYBLE_STATE_ADVERTISING == CyBle_GetState()) { led ^= LED_OFF; Advertising_LED_Write(led); } /* Indicate that timer is raised to the main loop */ mainTimer++; /* Clears interrupt request */ CySysWdtClearInterrupt(WDT_INTERRUPT_SOURCE); } }
/****************************************************************************** * Function Name: CyBle_GattcStartPartialDiscovery ***************************************************************************//** * * Starts the automatic server discovery process as per the range provided * on a GATT Server to which it is connected. This API could be used for * partial server discovery after indication received to the Service Changed * Characteristic Value. Two events may be generated * after calling this function - CYBLE_EVT_GATTC_DISCOVERY_COMPLETE or * CYBLE_EVT_GATTC_ERROR_RSP. The CYBLE_EVT_GATTC_DISCOVERY_COMPLETE event is * generated when the remote device was successfully discovered. The * CYBLE_EVT_GATTC_ERROR_RSP is generated if the device discovery is failed. * * \param connHandle: The handle which consists of the device ID and ATT connection ID. * \param startHandle: Start of affected attribute handle range. * \param endHandle: End of affected attribute handle range. * * \return * CYBLE_API_RESULT_T : Return value indicates if the function succeeded or * failed. Following are the possible error codes. * * <table> * <tr> * <th>Errors codes</th> * <th>Description</th> * </tr> * <tr> * <td>CYBLE_ERROR_OK</td> * <td>On successful operation</td> * </tr> * <tr> * <td>CYBLE_ERROR_INVALID_PARAMETER</td> * <td>'connHandle' value does not represent any existing entry.</td> * </tr> * <tr> * <td>CYBLE_ERROR_INVALID_OPERATION</td> * <td>The operation is not permitted</td> * </tr> * <tr> * <td>CYBLE_ERROR_MEMORY_ALLOCATION_FAILED</td> * <td>Memory allocation failed</td> * </tr> * <tr> * <td>CYBLE_ERROR_INVALID_STATE</td> * <td>If the function is called in any state except connected or discovered</td> * </tr> * </table> * ******************************************************************************/ CYBLE_API_RESULT_T CyBle_GattcStartPartialDiscovery(CYBLE_CONN_HANDLE_T connHandle, CYBLE_GATT_DB_ATTR_HANDLE_T startHandle, CYBLE_GATT_DB_ATTR_HANDLE_T endHandle) { uint8 j; CYBLE_API_RESULT_T apiResult; if((CyBle_GetState() != CYBLE_STATE_CONNECTED) || ((CyBle_GetClientState() != CYBLE_CLIENT_STATE_CONNECTED) && (CyBle_GetClientState() != CYBLE_CLIENT_STATE_DISCOVERED))) { apiResult = CYBLE_ERROR_INVALID_STATE; } else { /* Clean old discovery information of affected attribute range */ for(j = 0u; j < (uint8) CYBLE_SRVI_COUNT; j++) { if((cyBle_serverInfo[j].range.startHandle >= startHandle) && (cyBle_serverInfo[j].range.startHandle <= endHandle)) { (void)memset(&cyBle_serverInfo[j].range, 0, sizeof(cyBle_serverInfo[0].range)); } } cyBle_connHandle = connHandle; cyBle_gattcDiscoveryRange.startHandle = startHandle; cyBle_gattcDiscoveryRange.endHandle = endHandle; CyBle_ServiceInit(); apiResult = CyBle_GattcDiscoverPrimaryServices(connHandle, &cyBle_gattcDiscoveryRange); if(CYBLE_ERROR_OK == apiResult) { CyBle_SetClientState(CYBLE_CLIENT_STATE_SRVC_DISCOVERING); cyBle_eventHandlerFlag |= CYBLE_AUTO_DISCOVERY; } } return (apiResult); }
/****************************************************************************** ##Function Name: CyBle_BcssSendIndication ******************************************************************************* Summary: Sends an indication with a characteristic value of the Body Composition Service, which is a value specified by charIndex, to the client's device. Parameters: connHandle: The connection handle. charIndex: The index of the service characteristic. attrSize: The size of the characteristic value attribute. *attrValue: The pointer to the characteristic value data that should be sent to the client's device. Return: A return value is of type CYBLE_API_RESULT_T. * CYBLE_ERROR_OK - The request handled successfully * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameter failed * CYBLE_ERROR_INVALID_OPERATION - This operation is not permitted * CYBLE_ERROR_INVALID_STATE - Connection with the client is not established * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed. * CYBLE_ERROR_IND_DISABLED - Indication is not enabled by the client. ******************************************************************************/ CYBLE_API_RESULT_T CyBle_BcssSendIndication(CYBLE_CONN_HANDLE_T connHandle, CYBLE_BCS_CHAR_INDEX_T charIndex, uint8 attrSize, uint8 *attrValue) { /* Store new data in database */ CYBLE_API_RESULT_T apiResult = CYBLE_ERROR_INVALID_PARAMETER; if(charIndex == CYBLE_BCS_BODY_COMPOSITION_MEASUREMENT) { /* Send indication if it is enabled and connected */ if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else if(!CYBLE_IS_INDICATION_ENABLED( cyBle_bcss.charInfo[CYBLE_BCS_BODY_COMPOSITION_MEASUREMENT].descrHandle[CYBLE_BCS_CCCD])) { apiResult = CYBLE_ERROR_IND_DISABLED; } else { CYBLE_GATTS_HANDLE_VALUE_IND_T indReqParam; /* Fill all fields of write request structure ... */ indReqParam.attrHandle = cyBle_bcss.charInfo[CYBLE_BCS_BODY_COMPOSITION_MEASUREMENT].descrHandle[CYBLE_BCS_CCCD]; indReqParam.value.val = attrValue; indReqParam.value.len = attrSize; /* Send indication to client using previously filled structure */ apiResult = CyBle_GattsIndication(connHandle, &indReqParam); /* Save handle to support service specific value confirmation response from client */ if(apiResult == CYBLE_ERROR_OK) { cyBle_bcssReqHandle = indReqParam.attrHandle; } } } return (apiResult); }
/******************************************************************************* * Function Name: InitializeSystem ******************************************************************************** * * Summary: * Systm initialization function. * * Parameters: * None * * Return: * None * *******************************************************************************/ void InitializeSystem(void) { CyGlobalIntEnable; /* Enable Global Interrupts*/ /* Set the divider for ECO, ECO will be used as source when IMO is switched off to save power */ CySysClkWriteEcoDiv(CY_SYS_CLK_ECO_DIV8); #if LOW_POWER_STARTUP_ENABLE /* If LOW_POWER_STARTUP_ENABLE is set, then do the following for achieving lowest possible WCO & ECO startup current: * 1. Shut down the ECO (to reduce power consumption while WCO is starting) * 2. Enable WDT counter 0 to wakeup the system after 500ms (500ms = WCO startup time) * 3. Configure PSoC 4 BLE device in DeepSleep mode for the 500ms WCO startup time * 4. After WCO is enabled, restart the ECO so that BLESS interface can function * 5. Enable WDT counter 1 to wakeup the system after 1ms (1ms = ECO startup time) * 5. Configure PSoC 4 BLE device in DeepSleep mode for the 1ms ECO startup time */ CySysClkEcoStop(); /* Shutdown the ECO and later re-start in low power mode after WCO is turned on */ WDT_Interrupt_StartEx(WDT_Handler); /* Initialize WDT interrupt */ WCO_ECO_LowPowerStart(); /* Enable WCO & ECO in low power mode using WDT counter 0/1 as system wakeup sources respectively */ #endif /* End of #if LOW_POWER_STARTUP_ENABLE */ #if (CONSOLE_LOG_ENABLE) Console_Start(); /* Console log interface */ Console_UartPutString("Low power system startup complete\r\n"); #endif /* End of #if (CONSOLE_LOG_ENABLE) */ BLE_Engine_Start(); /* start the BLE interface */ /* Wait for BLE Component to Initialize */ while (CyBle_GetState() == CYBLE_STATE_INITIALIZING) { CyBle_ProcessEvents(); } }
/******************************************************************************* * Function Name: BLE_AppEventHandler ******************************************************************************** * * Summary: * BLE stack generic event handler routine for handling connection, discovery, * security etc. events. * * Parameters: * event - event that triggered this callback * eventParam - parameters for the event. * * Return: * None *******************************************************************************/ void BLE_AppEventHandler(uint32 event, void* eventParam) { CYBLE_API_RESULT_T apiResult; (void)eventParam; switch (event) { /********************************************************** * General Events ***********************************************************/ case CYBLE_EVT_STACK_ON: /* This event is received when component is Started */ /* Enter in to discoverable mode so that remote can search it. */ apiResult = CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST); if(apiResult != CYBLE_ERROR_OK) { CYASSERT(0); } break; case CYBLE_EVT_GAPP_ADVERTISEMENT_START_STOP: if(CyBle_GetState() == CYBLE_STATE_DISCONNECTED) { /* On advertisement timeout, restart advertisement */ apiResult = CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST); if(apiResult != CYBLE_ERROR_OK) { CYASSERT(0); } } break; default: break; } }
/****************************************************************************** ##Function Name: CyBle_BassSendNotification ******************************************************************************* Summary: This function updates the value of the Battery Level characteristic in the GATT database. If the client has configured a notification on the Battery Level characteristic, the function additionally sends this value using a GATT Notification message. The CYBLE_EVT_BASC_NOTIFICATION event is received by the peer device, on invoking this function. Parameters: connHandle: The BLE peer device connection handle serviceIndex: The index of the service instance. e.g. If two Battery Services are supported in your design, then first service will be identified by serviceIndex of 0 and the second by serviceIndex of 1. charIndex: The index of a service characteristic of type CYBLE_BAS_CHAR_INDEX_T. attrSize: The size of the characteristic value attribute. A battery level characteristic has 1 byte length. *attrValue: The pointer to the characteristic value data that should be sent to the Client device. Return: Return value is of type CYBLE_API_RESULT_T. * CYBLE_ERROR_OK - The request handled successfully * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameter failed * CYBLE_ERROR_INVALID_OPERATION - This operation is not permitted * CYBLE_ERROR_INVALID_STATE - Connection with the client is not established * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed. * CYBLE_ERROR_NTF_DISABLED - Notification is not enabled by the client. ******************************************************************************/ CYBLE_API_RESULT_T CyBle_BassSendNotification(CYBLE_CONN_HANDLE_T connHandle, uint8 serviceIndex, CYBLE_BAS_CHAR_INDEX_T charIndex, uint8 attrSize, uint8 *attrValue) { CYBLE_API_RESULT_T apiResult; /* Store new data in database */ apiResult = CyBle_BassSetCharacteristicValue(serviceIndex, charIndex, attrSize, attrValue); if(CYBLE_ERROR_OK == apiResult) { /* Send Notification if it is enabled and connected */ if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else if((cyBle_bass[serviceIndex].cccdHandle == CYBLE_GATT_INVALID_ATTR_HANDLE_VALUE) || (!CYBLE_IS_NOTIFICATION_ENABLED(cyBle_bass[serviceIndex].cccdHandle))) { apiResult = CYBLE_ERROR_NTF_DISABLED; } else { CYBLE_GATTS_HANDLE_VALUE_NTF_T ntfReqParam; /* Fill all fields of write request structure ... */ ntfReqParam.attrHandle = cyBle_bass[serviceIndex].batteryLevelHandle; ntfReqParam.value.val = attrValue; ntfReqParam.value.len = attrSize; /* Send notification to client using previously filled structure */ apiResult = CyBle_GattsNotification(connHandle, &ntfReqParam); } } return (apiResult); }
int main() { CYBLE_LP_MODE_T lpMode; CYBLE_BLESS_STATE_T blessState; CYBLE_STACK_LIB_VERSION_T stackVersion; CyGlobalIntEnable; UART_DEB_Start(); /* Start communication component */ printf("BLE Heart Rate Collector Example Project \r\n"); Disconnect_LED_Write(LED_OFF); Scanning_LED_Write(LED_OFF); Notification_LED_Write(LED_OFF); apiResult = CyBle_Start(AppCallBack); if(apiResult != CYBLE_ERROR_OK) { printf("CyBle_Start API Error: 0x%x \r\n", apiResult); } apiResult = CyBle_GetStackLibraryVersion(&stackVersion); if(apiResult != CYBLE_ERROR_OK) { printf("CyBle_GetStackLibraryVersion API Error: 0x%x \r\n", apiResult); } else { printf("Stack Version: %d.%d.%d.%d \r\n", stackVersion.majorVersion, stackVersion.minorVersion, stackVersion.patch, stackVersion.buildNumber); } CyBle_BasRegisterAttrCallback(BasCallBack); HrsInit(); while(1) { if(CyBle_GetState() != CYBLE_STATE_INITIALIZING) { /* Enter DeepSleep mode between connection intervals */ lpMode = CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP); CyGlobalIntDisable; blessState = CyBle_GetBleSsState(); if(lpMode == CYBLE_BLESS_DEEPSLEEP) { if(blessState == CYBLE_BLESS_STATE_ECO_ON || blessState == CYBLE_BLESS_STATE_DEEPSLEEP) { /* Put the device into the DeepSleep mode only when all debug information has been sent */ if((UART_DEB_SpiUartGetTxBufferSize() + UART_DEB_GET_TX_FIFO_SR_VALID) == 0u) { CySysPmDeepSleep(); } else { CySysPmSleep(); } } } else { if(blessState != CYBLE_BLESS_STATE_EVENT_CLOSE) { CySysPmSleep(); } } CyGlobalIntEnable; /* Handle advertising led blinking */ HandleLeds(); } /* Store bonding data to flash only when all debug information has been sent */ if((cyBle_pendingFlashWrite != 0u) && ((UART_DEB_SpiUartGetTxBufferSize() + UART_DEB_GET_TX_FIFO_SR_VALID) == 0u)) { apiResult = CyBle_StoreBondingData(0u); printf("Store bonding data, status: %x \r\n", apiResult); } /******************************************************************* * Processes all pending BLE events in the stack *******************************************************************/ CyBle_ProcessEvents(); } }
/******************************************************************************* * Function Name: AppCallBack() ******************************************************************************** * * Summary: * This is an event callback function to receive events from the BLE Component. * *******************************************************************************/ void AppCallBack(uint32 event, void* eventParam) { CYBLE_API_RESULT_T apiResult; CYBLE_GAP_BD_ADDR_T localAddr; CYBLE_GAP_AUTH_INFO_T *authInfo; uint8 i; switch (event) { /********************************************************** * General Events ***********************************************************/ case CYBLE_EVT_STACK_ON: /* This event is received when the component is Started */ /* Enter into discoverable mode so that remote can search it. */ apiResult = CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST); if(apiResult != CYBLE_ERROR_OK) { DBG_PRINTF("StartAdvertisement API Error: %d \r\n", apiResult); } DBG_PRINTF("Bluetooth On, StartAdvertisement with addr: "); localAddr.type = 0u; CyBle_GetDeviceAddress(&localAddr); for(i = CYBLE_GAP_BD_ADDR_SIZE; i > 0u; i--) { DBG_PRINTF("%2.2x", localAddr.bdAddr[i-1]); } DBG_PRINTF("\r\n"); break; case CYBLE_EVT_TIMEOUT: break; case CYBLE_EVT_HARDWARE_ERROR: /* This event indicates that some internal HW error has occurred. */ DBG_PRINTF("CYBLE_EVT_HARDWARE_ERROR \r\n"); break; /* This event will be triggered by host stack if BLE stack is busy or not busy. * Parameter corresponding to this event will be the state of BLE stack. * BLE stack busy = CYBLE_STACK_STATE_BUSY, * BLE stack not busy = CYBLE_STACK_STATE_FREE */ case CYBLE_EVT_STACK_BUSY_STATUS: DBG_PRINTF("CYBLE_EVT_STACK_BUSY_STATUS: %x\r\n", *(uint8 *)eventParam); break; case CYBLE_EVT_HCI_STATUS: DBG_PRINTF("CYBLE_EVT_HCI_STATUS: %x \r\n", *(uint8 *)eventParam); break; /********************************************************** * GAP Events ***********************************************************/ case CYBLE_EVT_GAP_AUTH_REQ: DBG_PRINTF("CYBLE_EVT_AUTH_REQ: security=%x, bonding=%x, ekeySize=%x, err=%x \r\n", (*(CYBLE_GAP_AUTH_INFO_T *)eventParam).security, (*(CYBLE_GAP_AUTH_INFO_T *)eventParam).bonding, (*(CYBLE_GAP_AUTH_INFO_T *)eventParam).ekeySize, (*(CYBLE_GAP_AUTH_INFO_T *)eventParam).authErr); break; case CYBLE_EVT_GAP_PASSKEY_ENTRY_REQUEST: DBG_PRINTF("CYBLE_EVT_PASSKEY_ENTRY_REQUEST press 'p' to enter passkey \r\n"); break; case CYBLE_EVT_GAP_PASSKEY_DISPLAY_REQUEST: DBG_PRINTF("CYBLE_EVT_PASSKEY_DISPLAY_REQUEST %6.6ld \r\n", *(uint32 *)eventParam); break; case CYBLE_EVT_GAP_KEYINFO_EXCHNGE_CMPLT: DBG_PRINTF("CYBLE_EVT_GAP_KEYINFO_EXCHNGE_CMPLT \r\n"); break; case CYBLE_EVT_GAP_AUTH_COMPLETE: authInfo = (CYBLE_GAP_AUTH_INFO_T *)eventParam; (void)authInfo; DBG_PRINTF("AUTH_COMPLETE: security:%x, bonding:%x, ekeySize:%x, authErr %x \r\n", authInfo->security, authInfo->bonding, authInfo->ekeySize, authInfo->authErr); break; case CYBLE_EVT_GAP_AUTH_FAILED: DBG_PRINTF("CYBLE_EVT_AUTH_FAILED: %x \r\n", *(uint8 *)eventParam); break; case CYBLE_EVT_GAPP_ADVERTISEMENT_START_STOP: DBG_PRINTF("CYBLE_EVT_ADVERTISING, state: %x \r\n", CyBle_GetState()); if(CYBLE_STATE_DISCONNECTED == CyBle_GetState()) { /* Fast and slow advertising period complete, go to low power * mode (Hibernate mode) and wait for an external * user event to wake up the device again */ DBG_PRINTF("Hibernate \r\n"); LED_BLU_Write(LED_OFF); LED_RED_Write(LED_ON); LED_GRN_Write(LED_OFF); SW2_ClearInterrupt(); Wakeup_Interrupt_ClearPending(); Wakeup_Interrupt_Start(); #if (DEBUG_UART_ENABLED == ENABLED) /* Wait until debug info is sent */ while((UART_DEB_SpiUartGetTxBufferSize() + UART_DEB_GET_TX_FIFO_SR_VALID) != 0); #endif /* (DEBUG_UART_ENABLED == ENABLED) */ CySysPmHibernate(); } break; case CYBLE_EVT_GAP_DEVICE_CONNECTED: DBG_PRINTF("CYBLE_EVT_GAP_DEVICE_CONNECTED \r\n"); LED_BLU_Write(LED_OFF); break; case CYBLE_EVT_GAP_DEVICE_DISCONNECTED: DBG_PRINTF("CYBLE_EVT_GAP_DEVICE_DISCONNECTED\r\n"); apiResult = CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST); if(apiResult != CYBLE_ERROR_OK) { DBG_PRINTF("StartAdvertisement API Error: %d \r\n", apiResult); } break; case CYBLE_EVT_GATTS_XCNHG_MTU_REQ: { uint16 mtu; CyBle_GattGetMtuSize(&mtu); DBG_PRINTF("CYBLE_EVT_GATTS_XCNHG_MTU_REQ, final mtu= %d \r\n", mtu); } break; case CYBLE_EVT_GATTS_WRITE_REQ: DBG_PRINTF("CYBLE_EVT_GATT_WRITE_REQ: %x = ",((CYBLE_GATTS_WRITE_REQ_PARAM_T *)eventParam)->handleValPair.attrHandle); ShowValue(&((CYBLE_GATTS_WRITE_REQ_PARAM_T *)eventParam)->handleValPair.value); (void)CyBle_GattsWriteRsp(((CYBLE_GATTS_WRITE_REQ_PARAM_T *)eventParam)->connHandle); break; case CYBLE_EVT_GAP_ENCRYPT_CHANGE: DBG_PRINTF("CYBLE_EVT_GAP_ENCRYPT_CHANGE: %x \r\n", *(uint8 *)eventParam); break; case CYBLE_EVT_GAPC_CONNECTION_UPDATE_COMPLETE: DBG_PRINTF("CYBLE_EVT_CONNECTION_UPDATE_COMPLETE: %x \r\n", *(uint8 *)eventParam); break; /********************************************************** * GATT Events ***********************************************************/ case CYBLE_EVT_GATT_CONNECT_IND: DBG_PRINTF("CYBLE_EVT_GATT_CONNECT_IND: %x, %x \r\n", cyBle_connHandle.attId, cyBle_connHandle.bdHandle); /* Register service specific callback functions */ HidsInit(); BasInit(); ScpsInit(); break; case CYBLE_EVT_GATT_DISCONNECT_IND: DBG_PRINTF("CYBLE_EVT_GATT_DISCONNECT_IND \r\n"); break; case CYBLE_EVT_GATTS_READ_CHAR_VAL_ACCESS_REQ: /* Triggered on server side when client sends read request and when * characteristic has CYBLE_GATT_DB_ATTR_CHAR_VAL_RD_EVENT property set. * This event could be ignored by application unless it need to response * by error response which needs to be set in gattErrorCode field of * event parameter. */ DBG_PRINTF("CYBLE_EVT_GATTS_READ_CHAR_VAL_ACCESS_REQ: handle: %x \r\n", ((CYBLE_GATTS_CHAR_VAL_READ_REQ_T *)eventParam)->attrHandle); break; /********************************************************** * Other Events ***********************************************************/ case CYBLE_EVT_PENDING_FLASH_WRITE: /* Inform application that flash write is pending. Stack internal data * structures are modified and require to be stored in Flash using * CyBle_StoreBondingData() */ DBG_PRINTF("CYBLE_EVT_PENDING_FLASH_WRITE\r\n"); break; default: DBG_PRINTF("OTHER event: %lx \r\n", event); break; } }
*******************************************************************************/int main() { CyGlobalIntEnable; #if (DEBUG_UART_ENABLED == ENABLED) UART_DEB_Start(); #endif /* (DEBUG_UART_ENABLED == ENABLED) */ DBG_PRINTF("BLE HID Keyboard Example Project \r\n"); LED_RED_Write(LED_OFF); LED_BLU_Write(LED_OFF); LED_GRN_Write(LED_OFF); /* Start CYBLE component and register generic event handler */ CyBle_Start(AppCallBack); #if (BAS_MEASURE_ENABLE != 0) ADC_Start(); #endif /* BAS_MEASURE_ENABLE != 0 */ while(1) { /* CyBle_ProcessEvents() allows BLE stack to process pending events */ CyBle_ProcessEvents(); /* To achieve low power in the device */ LowPowerImplementation(); if((CyBle_GetState() == CYBLE_STATE_CONNECTED) && (suspend != CYBLE_HIDS_CP_SUSPEND)) { if(mainTimer != 0u) { mainTimer = 0u; #if (BAS_SIMULATE_ENABLE != 0) SimulateBattery(); CyBle_ProcessEvents(); #endif /* BAS_SIMULATE_ENABLE != 0 */ #if (BAS_MEASURE_ENABLE != 0) MeasureBattery(); CyBle_ProcessEvents(); #endif /* BAS_MEASURE_ENABLE != 0 */ if(keyboardSimulation == ENABLED) { SimulateKeyboard(); } } /* Store bonding data to flash only when all debug information has been sent */ #if(CYBLE_BONDING_REQUIREMENT == CYBLE_BONDING_YES) #if (DEBUG_UART_ENABLED == ENABLED) if((cyBle_pendingFlashWrite != 0u) && ((UART_DEB_SpiUartGetTxBufferSize() + UART_DEB_GET_TX_FIFO_SR_VALID) == 0u)) #else if(cyBle_pendingFlashWrite != 0u) #endif /* (DEBUG_UART_ENABLED == ENABLED) */ { CYBLE_API_RESULT_T apiResult; apiResult = CyBle_StoreBondingData(0u); (void)apiResult; DBG_PRINTF("Store bonding data, status: %x \r\n", apiResult); } #endif /* CYBLE_BONDING_REQUIREMENT == CYBLE_BONDING_YES */ } } }