/********************************************************************* * @fn timeAppGapStateCB * * @brief Notification from the profile of a state change. * * @param newState - new state * * @return none */ static void timeAppGapStateCB( gaprole_States_t newState ) { // if connected if ( newState == GAPROLE_CONNECTED ) { linkDBItem_t *pItem; // Get connection handle GAPRole_GetParameter( GAPROLE_CONNHANDLE, &timeAppConnHandle ); // Get peer bd address if ( (pItem = linkDB_Find( timeAppConnHandle )) != NULL) { // If connected to device without bond do service discovery if ( !osal_memcmp( pItem->addr, timeAppBondedAddr, B_ADDR_LEN ) ) { timeAppDiscoveryCmpl = FALSE; } // Initiate service discovery if necessary if ( timeAppDiscoveryCmpl == FALSE ) { osal_start_timerEx( timeAppTaskId, START_DISCOVERY_EVT, DEFAULT_DISCOVERY_DELAY ); } } LCD_WRITE_STRING( "Connected", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_2 ); } // if disconnected else if ( timeAppGapState == GAPROLE_CONNECTED && newState != GAPROLE_CONNECTED ) { uint8 advState = TRUE; timeAppDisconnected(); if ( newState == GAPROLE_WAITING_AFTER_TIMEOUT ) { // link loss timeout-- use fast advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_FAST_ADV_DURATION ); } else { // Else use slow advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION ); } // Enable advertising GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); LCD_WRITE_STRING( "Disconnected", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_2 ); } // if advertising stopped else if ( timeAppGapState == GAPROLE_ADVERTISING && newState == GAPROLE_WAITING ) { // if advertising stopped by user if ( timeAppAdvCancelled ) { timeAppAdvCancelled = FALSE; } // if fast advertising switch to slow else if ( GAP_GetParamValue( TGAP_GEN_DISC_ADV_INT_MIN ) == DEFAULT_FAST_ADV_INTERVAL ) { uint8 advState = TRUE; GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION ); GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } } // if started else if ( newState == GAPROLE_STARTED ) { #ifndef CC2540_MINIDK uint8 bdAddr[B_ADDR_LEN]; GAPRole_GetParameter( GAPROLE_BD_ADDR, &bdAddr ); LCD_WRITE_STRING( "Time App", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( bdAddr2Str( bdAddr ), HAL_LCD_LINE_2 ); #endif // Initialize time clock after writing first two lines of LCD timeAppClockInit(); } timeAppGapState = newState; }
/*************************************************************************************************** * @fn MT_AfDataRequest * * @brief Process AF Register command * * @param pBuf - pointer to the received buffer * * @return none ***************************************************************************************************/ void MT_AfDataRequest(uint8 *pBuf) { #define MT_AF_REQ_MSG_LEN 10 #define MT_AF_REQ_MSG_EXT 10 endPointDesc_t *epDesc; afAddrType_t dstAddr; cId_t cId; uint8 transId, txOpts, radius; uint8 cmd0, cmd1; uint8 retValue = ZFailure; uint16 dataLen, tempLen; /* Parse header */ cmd0 = pBuf[MT_RPC_POS_CMD0]; cmd1 = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; if (cmd1 == MT_AF_DATA_REQUEST_EXT) { dstAddr.addrMode = (afAddrMode_t)*pBuf++; if (dstAddr.addrMode == afAddr64Bit) { (void)osal_memcpy(dstAddr.addr.extAddr, pBuf, Z_EXTADDR_LEN); } else { dstAddr.addr.shortAddr = BUILD_UINT16(pBuf[0], pBuf[1]); } pBuf += Z_EXTADDR_LEN; dstAddr.endPoint = *pBuf++; dstAddr.panId = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf += 2; } else { /* Destination address */ dstAddr.addrMode = afAddr16Bit; dstAddr.addr.shortAddr = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf += 2; /* Destination endpoint */ dstAddr.endPoint = *pBuf++; dstAddr.panId = 0; } /* Source endpoint */ epDesc = afFindEndPointDesc(*pBuf++); /* ClusterId */ cId = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf +=2; /* TransId */ transId = *pBuf++; /* TxOption */ txOpts = *pBuf++; /* Radius */ radius = *pBuf++; /* Length */ if (cmd1 == MT_AF_DATA_REQUEST_EXT) { dataLen = BUILD_UINT16(pBuf[0], pBuf[1]); tempLen = dataLen + MT_AF_REQ_MSG_LEN + MT_AF_REQ_MSG_EXT; pBuf += 2; } else { dataLen = *pBuf++; tempLen = dataLen + MT_AF_REQ_MSG_LEN; } if ( epDesc == NULL ) { retValue = afStatus_INVALID_PARAMETER; } else if (tempLen > (uint16)MT_RPC_DATA_MAX) { if (pMtAfDataReq != NULL) { retValue = afStatus_INVALID_PARAMETER; } else if ((pMtAfDataReq = osal_mem_alloc(sizeof(mtAfDataReq_t) + dataLen)) == NULL) { retValue = afStatus_MEM_FAIL; } else { retValue = afStatus_SUCCESS; pMtAfDataReq->data = (uint8 *)(pMtAfDataReq+1); (void)osal_memcpy(&(pMtAfDataReq->dstAddr), &dstAddr, sizeof(afAddrType_t)); pMtAfDataReq->epDesc = epDesc; pMtAfDataReq->cId = cId; pMtAfDataReq->dataLen = dataLen; pMtAfDataReq->transId = transId; pMtAfDataReq->txOpts = txOpts; pMtAfDataReq->radius = radius; // Setup to time-out the huge outgoing item if host does not MT_AF_DATA_STORE it. pMtAfDataReq->tick = MT_AF_EXEC_CNT; if (ZSuccess != osal_start_timerEx(MT_TaskID, MT_AF_EXEC_EVT, MT_AF_EXEC_DLY)) { (void)osal_set_event(MT_TaskID, MT_AF_EXEC_EVT); } } } else { retValue = AF_DataRequest(&dstAddr, epDesc, cId, dataLen, pBuf, &transId, txOpts, radius); } if (MT_RPC_CMD_SREQ == (cmd0 & MT_RPC_CMD_TYPE_MASK)) { MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP|(uint8)MT_RPC_SYS_AF), cmd1, 1, &retValue); } }
/********************************************************************************************* * @fn simpleBLECentralEventCB * * @brief Central event callback function. * * @param pEvent - pointer to event structure * * @return none **********************************************************************************************/ static void simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent ){ switch ( pEvent->gap.opcode ){ case GAP_DEVICE_INIT_DONE_EVENT:{ //LCDPrintText("Central Initialized",0,PRINT_STRING); osal_memcpy(mac_buffer[0],pEvent->initDone.devAddr, MAC_LEN); HalLcdWriteString(bdAddr2Str( mac_buffer[0]), HAL_LCD_LINE_1); uint32 random_scan_duration =500;//to avoid normal scan be discarded by the timer,so its lasting-time should be short GAP_SetParamValue( TGAP_GEN_DISC_SCAN, random_scan_duration ); //random scan duration //LCDPrintText("discovering",0,PRINT_STRING); uint32 timeout_value = 200; // timeout_value - in milliseconds. osal_start_timerEx(MasterSlaveSwitchTaskID, PERIOD_DETECH_EVT, timeout_value); uint8 return_status; if(return_status = GAPCentralRole_StartDiscovery(DISCOVERY_MODE, ACTIVE_SCAN, DISCOVERY_WHITE_LIST )) LCDPrintText("discovery error:",return_status,PRINT_VALUE); break; } case GAP_DEVICE_INFO_EVENT:{ //find a new device // filtering device discovery results based on service UUID //LCDPrintText("find new device",0,PRINT_STRING); if(simpleBLEScanRes >= MAX_SCAN_RES){ GAPCentralRole_CancelDiscovery(); break; } if ( simpleBLEFindSvcUuid(WANTED_SERVICE_UUID, pEvent->deviceInfo.pEvtData, pEvent->deviceInfo.dataLen) ){ simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType ); //GAPCentralRole_CancelDiscovery(); //stop discoverying } break; } case GAP_DEVICE_DISCOVERY_EVENT:{ //discaovery has completed osal_stop_timerEx(MasterSlaveSwitchTaskID,PERIOD_DETECH_EVT); //LCDPrintText("disca completed ",0,PRINT_STRING); if ( simpleBLEScanRes > 0 ){ // connect to current device in scan result uint8 random_select = random_num%simpleBLEScanRes; //LCDPrintText("random_select ",random_select,PRINT_STRING); CurrentConnectionInfo.MacType= simpleBLEDevList[random_select].addrType; CurrentConnectionInfo.MacAddr= simpleBLEDevList[random_select].addr; uint8 return_status; if(return_status = GAPCentralRole_EstablishLink( LINK_HIGH_DUTY_CYCLE, LINK_WHITE_LIST, CurrentConnectionInfo.MacType, CurrentConnectionInfo.MacAddr)){ LCDPrintText("Link Error",return_status,PRINT_VALUE); osal_set_event(MasterSlaveSwitchTaskID, MSS_CHANGE_ROLE_EVT); } } else{ //LCDPrintText("no device found",0,PRINT_STRING); osal_set_event(MasterSlaveSwitchTaskID, MSS_CHANGE_ROLE_EVT); //switch to periperal } break; } case GAP_LINK_ESTABLISHED_EVENT:{ if ( pEvent->gap.hdr.status == SUCCESS ){ //LCDPrintText("Connected",0,PRINT_STRING); CurrentConnectionInfo.Handle= pEvent->linkCmpl.connectionHandle; if(CharHandleSearchFlag == 1) simpleBLECentralStartDiscovery(); else{ ClientWriteValue(); CharSendingFlag =1; //LCDPrintText("NO NEED TO",0,PRINT_STRING); } } else{ LCDPrintText("Connect Failed ",pEvent->gap.hdr.status,PRINT_VALUE); osal_set_event(MasterSlaveSwitchTaskID, MSS_CHANGE_ROLE_EVT); } break; } case GAP_LINK_TERMINATED_EVENT:{ osal_set_event(MasterSlaveSwitchTaskID, MSS_CHANGE_ROLE_EVT); break; } case GAP_LINK_PARAM_UPDATE_EVENT: break; default: break; } }
/************************************************************************************************** * @fn Hal_ProcessEvent * * @brief Hal Process Event * * @param task_id - Hal TaskId * events - events * * @return None **************************************************************************************************/ uint16 Hal_ProcessEvent( uint8 task_id, uint16 events ) { uint8 *msgPtr; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { msgPtr = osal_msg_receive(Hal_TaskID); while (msgPtr) { /* Do something here - for now, just deallocate the msg and move on */ /* De-allocate */ osal_msg_deallocate( msgPtr ); /* Next */ msgPtr = osal_msg_receive( Hal_TaskID ); } return events ^ SYS_EVENT_MSG; } #if (defined HAL_BUZZER) && (HAL_BUZZER == TRUE) if (events & HAL_BUZZER_EVENT) { HalBuzzerStop(); return events ^ HAL_BUZZER_EVENT; } #endif #ifdef CC2591_COMPRESSION_WORKAROUND if ( events & PERIOD_RSSI_RESET_EVT ) { macRxResetRssi(); return (events ^ PERIOD_RSSI_RESET_EVT); } #endif if ( events & HAL_LED_BLINK_EVENT ) { #if (defined (BLINK_LEDS)) && (HAL_LED == TRUE) HalLedUpdate(); #endif /* BLINK_LEDS && HAL_LED */ return events ^ HAL_LED_BLINK_EVENT; } if (events & HAL_KEY_EVENT) { #if (defined HAL_KEY) && (HAL_KEY == TRUE) /* Check for keys */ HalKeyPoll(); /* if interrupt disabled, do next polling */ if (!Hal_KeyIntEnable) { osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100); } #endif return events ^ HAL_KEY_EVENT; } #if defined POWER_SAVING if ( events & HAL_SLEEP_TIMER_EVENT ) { halRestoreSleepLevel(); return events ^ HAL_SLEEP_TIMER_EVENT; } if ( events & HAL_PWRMGR_HOLD_EVENT ) { (void)osal_pwrmgr_task_state(Hal_TaskID, PWRMGR_HOLD); (void)osal_stop_timerEx(Hal_TaskID, HAL_PWRMGR_CONSERVE_EVENT); (void)osal_clear_event(Hal_TaskID, HAL_PWRMGR_CONSERVE_EVENT); return (events & ~(HAL_PWRMGR_HOLD_EVENT | HAL_PWRMGR_CONSERVE_EVENT)); } if ( events & HAL_PWRMGR_CONSERVE_EVENT ) { (void)osal_pwrmgr_task_state(Hal_TaskID, PWRMGR_CONSERVE); return events ^ HAL_PWRMGR_CONSERVE_EVENT; } #endif return 0; }
/********************************************************************* * @fn SimpleBLEPeripheral_ProcessEvent * * @brief Simple BLE Peripheral Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return events not processed */ uint16 SimpleBLEPeripheral_ProcessEvent( uint8 task_id, uint16 events ) { VOID task_id; // OSAL required parameter that isn't used in this function if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( simpleBLEPeripheral_TaskID )) != NULL ) { simpleBLEPeripheral_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & SBP_START_DEVICE_EVT ) { // Start the Device VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs ); // Start Bond Manager VOID GAPBondMgr_Register( &simpleBLEPeripheral_BondMgrCBs ); // Set timer for first periodic event osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD ); return ( events ^ SBP_START_DEVICE_EVT ); } if ( events & SBP_PERIODIC_EVT ) { // Restart timer if ( SBP_PERIODIC_EVT_PERIOD ) { osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD ); } // Perform periodic application task performPeriodicTask(); return (events ^ SBP_PERIODIC_EVT); } if ( events & SBP_LED_TOGGLE_EVT ) { // Assuming that the LED is on P0_4 in the circuit. if(led_toggle_flag == 0) { P0_4 = 1; led_toggle_flag = 1; } else { P0_4 = 0; led_toggle_flag = 0; } VOID osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_LED_TOGGLE_EVT, 1000 ); return ( events ^ SBP_LED_TOGGLE_EVT ); } // Discard unknown events return 0; }
/************************************************************************************************** * @fn zapSBL_RxExt * * @brief This function is the registered callback for the UART to the external application * that is driving the serial boot load to the ZNP. * * input parameters * * @param port - Don't care. * @param event - Don't care. * * output parameters * * None. * * @return None. ************************************************************************************************** */ static void zapSBL_RxExt(uint8 port, uint8 event) { uint8 ch; (void)port; (void)event; // Use external UART Rx as the trigger to start an SBL session. if (!zapSBL_Active) { if ((zapSBL_Buf = osal_mem_alloc(SB_BUF_SIZE)) == NULL) { return; } zapSBL_Active = TRUE; zapSBL_ResetZNP(); // Stop other tasks access (e.g. zapMonitor()) to SPI when in SBL mode. (void)osal_memset(tasksEvents+1, 0, ((tasksCnt-1) * sizeof(uint16))); for (ch = 1; ch < tasksCnt; ch++) { uint16 evt; for (evt = 0x0001; evt < 0x8000; evt <<= 1) { (void)osal_stop_timerEx(ch, evt); } } if (ZSuccess != osal_start_timerEx(zapSBL_TaskId, ZAP_SBL_EVT_EXIT, ZAP_SBL_DLY_EXIT)) { (void)osal_set_event(zapSBL_TaskId, ZAP_SBL_EVT_EXIT); } #if HAL_LCD HalLcdWriteString( "TexasInstruments", 1 ); HalLcdWriteString( "ZAP Proxy to ZNP", 2 ); HalLcdWriteString( " BootLoader ", 3 ); #endif } while (HalUARTRead(ZAP_SBL_EXT_PORT, &ch, 1)) { sbBuf[sbSte + sbIdx] = ch; switch (sbSte) { case SB_SOF_STATE: if (SB_SOF == ch) { sbSte = SB_LEN_STATE; } break; case SB_LEN_STATE: sbFcs = 0; sbSte = ((sbLen = ch) >= SB_BUF_SIZE) ? SB_SOF_STATE : SB_CMD1_STATE; break; case SB_CMD1_STATE: sbSte = SB_CMD2_STATE; break; case SB_CMD2_STATE: sbSte = (sbLen) ? SB_DATA_STATE : SB_FCS_STATE; break; case SB_DATA_STATE: if (++sbIdx == sbLen) { sbSte = SB_FCS_STATE; } break; case SB_FCS_STATE: if (sbFcs == ch) { sbBuf[SB_DATA_STATE + sbIdx] = ch; zapSBL_Tx(); } else { // TODO - RemoTI did not have here or on bad length - adding could cause > 1 SB_INVALID_FCS // for a single data packet which could put out of sync with PC for awhile or // infinte, depending on PC-side? // sbResp(SB_INVALID_FCS, 1); } sbSte = sbIdx = 0; break; default: break; } sbFcs ^= ch; if (ZSuccess != osal_start_timerEx(zapSBL_TaskId, ZAP_SBL_EVT_EXIT, ZAP_SBL_DLY_EXIT)) { (void)osal_set_event(zapSBL_TaskId, ZAP_SBL_EVT_EXIT); } } }
/************************************************************************************************** * @fn pulseDataCalc * * @brief This function is called by MHMSAppEvt() to calculate the data for a MHMS report. * The function will called on a 2ms interval and detect whether a pulse is being measured. * If a pulse is determined it will invoke the MHMSdataReq interrupt timer (20ms intervals) * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ static void pulseDataCalc(void) { MHMSEvtDat_sync = TRUE; //Pulse Data collection has been synced, no need to respond to annc commands to set EVT static int Pulse_sketch_count = 0; if (INVALID_NODE_ADDR == MHMSAddr) { return; } if (ZSuccess != osal_start_timerEx(MHMSTaskId, MHMS_EVT_DAT, MHMS_DLY_DAT)) //If the timer can't be started set event flag again for it to be service again { (void)osal_set_event(MHMSTaskId, MHMS_EVT_DAT); } pulseBPM(MHMSDat); //Function to collect/calculate Pulse #if TVSA_DATA_CNF MHMSDat[MHMS_RTG_IDX] = MHMSCnfErrCnt; #else MHMSDat[MHMS_RTG_IDX] = 0; #endif if(QS == TRUE && MHMSEvtReq_sync == FALSE) { //If pulse is being measured synchronize MHMSdatareq event osal_set_event(MHMSTaskId, MHMS_EVT_REQ); MHMSEvtReq_sync = TRUE; } else if(QS == FALSE && MHMSEvtCheckin_sync == FALSE) { osal_set_event(MHMSTaskId, MHMS_EVT_CHECKIN); //Since no pulse data is being collected, just send check in data to gateway MHMSEvtCheckin_sync = TRUE; } Pulse_sketch_count++; //MHMS USB communication with Pulse sensor Processor application if(EnableUSBPulseSketchTxFlag == TRUE && Pulse_sketch_count >= 10) { uint8 BPMBuf[7] = {'B',0,0,0,10,13}; uint8 IBIBuf[7] = {'Q',0,0,0,10,13}; uint8 SignalBuf[7] = {'S',0,0,0,10,13}; Pulse_sketch_count = 0; //reset count //conversion Signal Dec to ASCII uint16 temp = (BUILD_UINT16(MHMSDat[15], MHMSDat[16])) - 400; if(temp > 999) { SignalBuf[1] = '9'; SignalBuf[2] = '9'; SignalBuf[3] = '9'; } else { SignalBuf[1] = (uint8)((temp/100)+ 48); SignalBuf[2] = (uint8)((((temp%100) - (temp % 100)%10)/10) + 48); SignalBuf[3] = (uint8)(((temp % 100)%10)+ 48); } //conversion BPM Dec to ASCII temp = (uint16)MHMSDat[13]; BPMBuf[1] = (uint8)((temp/100)+ 48); BPMBuf[2] = (uint8)((((temp%100) - (temp % 100)%10)/10) + 48); BPMBuf[3] = (uint8)(((temp % 100)%10)+ 48); //conversion IBI Dec to ASCII temp = (uint16)MHMSDat[18]; IBIBuf[1] = (uint8)((temp/100)+ 48); IBIBuf[2] = (uint8)((((temp%100) - (temp % 100)%10)/10) + 48); IBIBuf[3] = (uint8)(((temp % 100)%10)+ 48); HalUARTWrite(0, SignalBuf, 6); HalUARTWrite(0, BPMBuf, 6); HalUARTWrite(0, IBIBuf, 6); } }
/********************************************************************* * @fn CyclingSensor_ProcessEvent * * @brief Cycling Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return events not processed */ uint16 CyclingSensor_ProcessEvent( uint8 task_id, uint16 events ) { VOID task_id; // OSAL required parameter that isn't used in this function if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( sensor_TaskID )) != NULL ) { sensor_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & START_DEVICE_EVT ) { // Start the Device VOID GAPRole_StartDevice( &cyclingPeripheralCB ); // Register with bond manager after starting device GAPBondMgr_Register( (gapBondCBs_t *) &cyclingBondCB ); return ( events ^ START_DEVICE_EVT ); } if ( events & CSC_PERIODIC_EVT ) { // Perform sensor's periodic task sensorPeriodicTask(); return (events ^ CSC_PERIODIC_EVT); } if ( events & CSC_CONN_PARAM_UPDATE_EVT ) { // Send param update. If it fails, retry until successful. GAPRole_SendUpdateParam( DEFAULT_DESIRED_MIN_CONN_INTERVAL, DEFAULT_DESIRED_MAX_CONN_INTERVAL, DEFAULT_DESIRED_SLAVE_LATENCY, DEFAULT_DESIRED_CONN_TIMEOUT, GAPROLE_RESEND_PARAM_UPDATE ); // Assuming service discovery complete, start neglect timer if ( USING_NEGLECT_TIMEOUT ) { osal_start_timerEx( sensor_TaskID, CSC_NEGLECT_TIMEOUT_EVT, NEGLECT_TIMEOUT_DELAY ); } return (events ^ CSC_CONN_PARAM_UPDATE_EVT); } if ( events & CSC_NEGLECT_TIMEOUT_EVT ) { // No user input, terminate connection. GAPRole_TerminateConnection(); return ( events ^ CSC_NEGLECT_TIMEOUT_EVT ); } if ( events & CSC_RESET_EVT ) { // Soft reset in action if ( gapProfileState == GAPROLE_CONNECTED ) { // Exit the connection GAPRole_TerminateConnection(); // There is no callback for manual termination of the link. change state variable here. gapProfileState = GAPROLE_WAITING; // Set timer to give the end advertising event time to finish osal_start_timerEx( sensor_TaskID, CSC_RESET_EVT, 500 ); } else if ( gapProfileState == GAPROLE_ADVERTISING ) { uint8 value = FALSE; // Turn off advertising GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &value ); // Set timer to give the end advertising event time to finish osal_start_timerEx( sensor_TaskID, CSC_RESET_EVT, 500 ); } else if ( USING_WHITE_LIST == TRUE ) { //temporary variable uint8 value = GAP_FILTER_POLICY_ALL; // Turn off white list filter policy GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof( uint8 ), &value); sensorUsingWhiteList = FALSE; // Clear the white list HCI_LE_ClearWhiteListCmd(); // Set timer to give the end advertising event time to finish osal_start_timerEx( sensor_TaskID, CSC_RESET_EVT, 500 ); } else if ( (gapProfileState == GAPROLE_STARTED) || (gapProfileState == GAPROLE_WAITING) || (gapProfileState == GAPROLE_WAITING_AFTER_TIMEOUT) ) { uint8 eraseBonds = TRUE; // Erase all bonds GAPBondMgr_SetParameter( GAPBOND_ERASE_ALLBONDS, 0, &eraseBonds ); // Turn on GREEN LED for set time HalLedSet( HAL_LED_1, HAL_LED_MODE_BLINK ); } return (events ^ CSC_RESET_EVT); } // Discard unknown events return 0; }
/********************************************************************* * @fn sensor_HandleKeys * * @brief Handles all key events for this device. * * @param shift - true if in shift/alt. * @param keys - bit field for key events. Valid entries: * HAL_KEY_SW_2 * HAL_KEY_SW_1 * * @return none */ static void sensor_HandleKeys( uint8 shift, uint8 keys ) { if ( keys == ( HAL_KEY_SW_1 | HAL_KEY_SW_2 ) ) { // Reset in progress has started resetInProgress = TRUE; // Set OSAL timer for reset osal_start_timerEx( sensor_TaskID, CSC_RESET_EVT, CSC_RESET_DELAY ); } else if ( keys & HAL_KEY_SW_1 ) { if ( resetInProgress == TRUE ) { // Cancel the reset resetInProgress = FALSE; osal_stop_timerEx ( sensor_TaskID, CSC_RESET_EVT ); } // set simulated measurement flag index if (++sensorFlagsIdx == FLAGS_IDX_MAX) { sensorFlagsIdx = 0; } } else if ( keys & HAL_KEY_SW_2 ) { if ( resetInProgress == TRUE ) { // Cancel the reset resetInProgress = FALSE; osal_stop_timerEx ( sensor_TaskID, CSC_RESET_EVT ); } // if not in a connection, toggle advertising on and off if ( gapProfileState != GAPROLE_CONNECTED ) { uint8 status; // Set fast advertising interval for user-initiated connections GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_WHITE_LIST_ADV_DURATION ); // toggle GAP advertisement status GAPRole_GetParameter( GAPROLE_ADVERT_ENABLED, &status ); status = !status; // If not already using white list, begin to do so. // Only do so if about to begin advertising if ( USING_WHITE_LIST && status == TRUE ) { uint8 bondCount = 0; GAPBondMgr_GetParameter( GAPBOND_BOND_COUNT, &bondCount ); if ((sensorUsingWhiteList == FALSE) && (bondCount > 0) ) { uint8 value = GAP_FILTER_POLICY_WHITE; GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof( uint8 ), &value); sensorUsingWhiteList = TRUE; } } GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &status ); // Set state variable if (status == FALSE) { sensorAdvCancelled = TRUE; } } } // End of key press else if ( keys == 0x00 ) { if ( resetInProgress == TRUE ) { resetInProgress = FALSE; osal_stop_timerEx( sensor_TaskID, CSC_RESET_EVT ); } } }
/************************************************************************************************** * @fn HalKeyConfig * * @brief Configure the Key serivce * * @param interruptEnable - TRUE/FALSE, enable/disable interrupt * cback - pointer to the CallBack function * * @return None **************************************************************************************************/ void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback) { /* Enable/Disable Interrupt or */ Hal_KeyIntEnable = interruptEnable; /* Register the callback fucntion */ pHalKeyProcessFunction = cback; /* Determine if interrupt is enable or not */ if (Hal_KeyIntEnable) { /* Rising/Falling edge configuratinn */ PICTL &= ~(HAL_KEY_SW_6_EDGEBIT); /* Clear the edge bit */ /* For falling edge, the bit must be set. */ #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE) PICTL |= HAL_KEY_SW_6_EDGEBIT; #endif /* Interrupt configuration: * - Enable interrupt generation at the port * - Enable CPU interrupt * - Clear any pending interrupt */ HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT; HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT; HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Rising/Falling edge configuratinn */ HAL_KEY_JOY_MOVE_ICTL &= ~(HAL_KEY_JOY_MOVE_EDGEBIT); /* Clear the edge bit */ /* For falling edge, the bit must be set. */ #if (HAL_KEY_JOY_MOVE_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_EDGEBIT; #endif /* Interrupt configuration: * - Enable interrupt generation at the port * - Enable CPU interrupt * - Clear any pending interrupt */ HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_ICTLBIT; HAL_KEY_JOY_MOVE_IEN |= HAL_KEY_JOY_MOVE_IENBIT; HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT); /* Do this only after the hal_key is configured - to work with sleep stuff */ if (HalKeyConfigured == TRUE) { osal_stop_timerEx( Hal_TaskID, HAL_KEY_EVENT); /* Cancel polling if active */ } } else /* Interrupts NOT enabled */ { HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */ HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT); /* Clear interrupt enable bit */ osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_POLLING_VALUE); /* Kick off polling */ } /* Key now is configured */ HalKeyConfigured = TRUE; }
/********************************************************************* * @fn SampleApp_ProcessEvent * * @brief Generic Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return none */ uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { // Received when a key is pressed case KEY_CHANGE: SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys ); break; // Received when a messages is received (OTA) for this endpoint case AF_INCOMING_MSG_CMD: SampleApp_MessageMSGCB( MSGpkt ); break; // Received whenever the device changes state in the network case ZDO_STATE_CHANGE: SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); if ( (SampleApp_NwkState == DEV_ZB_COORD) || (SampleApp_NwkState == DEV_ROUTER) || (SampleApp_NwkState == DEV_END_DEVICE) ) { // Start sending the periodic message in a regular interval. osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT ); } else { // Device is no longer in the network } break; default: break; } // Release the memory osal_msg_deallocate( (uint8 *)MSGpkt ); // Next - if one is available MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } // Send a message out - This event is generated by a timer // (setup in SampleApp_Init()). if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ) { // Send the periodic message SampleApp_SendPeriodicMessage(); // Setup to send message again in normal period (+ a little jitter) osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, (/*SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT*/ 1000 + (osal_rand() & 0x00FF)) ); // return unprocessed events return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT); } // Discard unknown events return 0; }
/********************************************************************* * @fn SimpleBLEPeripheral_ProcessEvent * * @brief Simple BLE Peripheral Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return events not processed */ uint16 SimpleBLEPeripheral_ProcessEvent(uint8 task_id, uint16 events) { VOID task_id; // OSAL required parameter that isn't used in this function if (events & SYS_EVENT_MSG) { uint8 *pMsg; if ((pMsg = osal_msg_receive(simpleBLEPeripheral_TaskID)) != NULL) { simpleBLEPeripheral_ProcessOSALMsg((osal_event_hdr_t *) pMsg); // Release the OSAL message VOID osal_msg_deallocate(pMsg); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if (events & SBP_START_DEVICE_EVT) { // Start the Device GAPRole_StartDevice(&simpleBLEPeripheral_PeripheralCBs); // Start Bond Manager GAPBondMgr_Register(&simpleBLEPeripheral_BondMgrCBs); // Set timer for first periodic event osal_start_timerEx(simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD); return (events ^ SBP_START_DEVICE_EVT); } if (events & SBP_PERIODIC_EVT) { // Restart timer if (SBP_PERIODIC_EVT_PERIOD) { osal_start_timerEx(simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD); } // Perform periodic application task performPeriodicTask(); return (events ^ SBP_PERIODIC_EVT); } if (events & SBP_ZEKEZANG_EVT) { uint8 initial_advertising_enable = FALSE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &initial_advertising_enable); return (events ^ SBP_ZEKEZANG_EVT); } if (events & SBP_SEND_IRDATA_EVT) { HalLcdWriteString("send plan complete...", HAL_LCD_LINE_4); return (events ^ SBP_SEND_IRDATA_EVT); } if (events & SBP_ADV_IN_CONNECTION_EVT) { uint8 turnOnAdv = TRUE; // Turn on advertising while in a connection GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &turnOnAdv); return (events ^ SBP_ADV_IN_CONNECTION_EVT); } return 0; }
/********************************************************************* * @fn sensorTag_HandleKeys * * @brief Handles all key events for this device. * * @param shift - true if in shift/alt. * @param keys - bit field for key events. Valid entries: * HAL_KEY_SW_2 * HAL_KEY_SW_1 * * @return none */ static void sensorTag_HandleKeys( uint8 shift, uint8 keys ) { uint8 SK_Keys = 0; VOID shift; // Intentionally unreferenced parameter if (keys & HAL_KEY_SW_1) { // Reset the system if side key is pressed for more than 3 seconds sysResetRequest = TRUE; osal_start_timerEx( sensorTag_TaskID, ST_SYS_RESET_EVT, ST_SYS_RESET_DELAY ); if (!testMode ) // Side key { // If device is not in a connection, pressing the side key should toggle // advertising on and off if ( gapProfileState != GAPROLE_CONNECTED ) { uint8 current_adv_enabled_status; uint8 new_adv_enabled_status; // Find the current GAP advertising status GAPRole_GetParameter( GAPROLE_ADVERT_ENABLED, ¤t_adv_enabled_status ); if( current_adv_enabled_status == FALSE ) { new_adv_enabled_status = TRUE; } else { new_adv_enabled_status = FALSE; } // Change the GAP advertisement status to opposite of current status GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &new_adv_enabled_status ); } if ( gapProfileState == GAPROLE_CONNECTED ) { uint8 adv_enabled = TRUE; // Disconnect GAPRole_TerminateConnection(); // Start advertising GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &adv_enabled ); } } else { // Test mode if ( keys & HAL_KEY_SW_1 ) // Side key { SK_Keys |= SK_KEY_SIDE; } } } if ( keys & HAL_KEY_SW_2 ) // Carbon S2 { SK_Keys |= SK_KEY_LEFT; } if ( keys & HAL_KEY_SW_3 ) // Carbon S3 { SK_Keys |= SK_KEY_RIGHT; } if (!(keys & HAL_KEY_SW_1)) { // Cancel system reset request sysResetRequest = FALSE; } // Set the value of the keys state to the Simple Keys Profile; // This will send out a notification of the keys state if enabled SK_SetParameter( SK_KEY_ATTR, sizeof ( uint8 ), &SK_Keys ); }
/********************************************************************* * @fn SensorTag_ProcessEvent * * @brief Simple BLE Peripheral Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return events not processed */ uint16 SensorTag_ProcessEvent( uint8 task_id, uint16 events ) { VOID task_id; // OSAL required parameter that isn't used in this function if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( sensorTag_TaskID )) != NULL ) { sensorTag_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } // Handle system reset (long press on side key) if ( events & ST_SYS_RESET_EVT ) { if (sysResetRequest) { HAL_SYSTEM_RESET(); } return ( events ^ ST_SYS_RESET_EVT ); } if ( events & ST_START_DEVICE_EVT ) { // Start the Device VOID GAPRole_StartDevice( &sensorTag_PeripheralCBs ); // Start Bond Manager VOID GAPBondMgr_Register( &sensorTag_BondMgrCBs ); return ( events ^ ST_START_DEVICE_EVT ); } ////////////////////////// // IR TEMPERATURE // ////////////////////////// if ( events & ST_IRTEMPERATURE_READ_EVT ) { if ( irTempEnabled ) { if (HalIRTempStatus() == TMP006_DATA_READY) { readIrTempData(); osal_start_timerEx( sensorTag_TaskID, ST_IRTEMPERATURE_READ_EVT, TEMP_DEFAULT_PERIOD-TEMP_MEAS_DELAY ); } else if (HalIRTempStatus() == TMP006_OFF) { HalIRTempTurnOn(); osal_start_timerEx( sensorTag_TaskID, ST_IRTEMPERATURE_READ_EVT, TEMP_MEAS_DELAY ); } } else { //Turn off Temperatur sensor VOID HalIRTempTurnOff(); VOID resetCharacteristicValue(IRTEMPERATURE_SERV_UUID,IRTEMPERATURE_DATA,0,IRTEMPERATURE_DATA_LEN); VOID resetCharacteristicValue(IRTEMPERATURE_SERV_UUID,IRTEMPERATURE_CONF,ST_CFG_SENSOR_DISABLE,sizeof ( uint8 )); } return (events ^ ST_IRTEMPERATURE_READ_EVT); } ////////////////////////// // Accelerometer // ////////////////////////// if ( events & ST_ACCELEROMETER_SENSOR_EVT ) { if(accEnabled) { readAccData(); osal_start_timerEx( sensorTag_TaskID, ST_ACCELEROMETER_SENSOR_EVT, sensorAccPeriod ); } else { VOID resetCharacteristicValue( ACCELEROMETER_SERV_UUID, ACCELEROMETER_DATA, 0, ACCELEROMETER_DATA_LEN ); VOID resetCharacteristicValue( ACCELEROMETER_SERV_UUID, ACCELEROMETER_CONF, ST_CFG_SENSOR_DISABLE, sizeof ( uint8 )); VOID resetCharacteristicValue( ACCELEROMETER_SERV_UUID, ACCELEROMETER_PERI, ACC_DEFAULT_PERIOD/ACCELEROMETER_TIME_UNIT, sizeof ( uint8 )); } return (events ^ ST_ACCELEROMETER_SENSOR_EVT); } ////////////////////////// // Humidity // ////////////////////////// if ( events & ST_HUMIDITY_SENSOR_EVT ) { if (humiEnabled) { HalHumiExecMeasurementStep(humiState); if (humiState == 2) { readHumData(); humiState = 0; osal_start_timerEx( sensorTag_TaskID, ST_HUMIDITY_SENSOR_EVT, HUM_DEFAULT_PERIOD ); } else { humiState++; osal_start_timerEx( sensorTag_TaskID, ST_HUMIDITY_SENSOR_EVT, HUM_FSM_PERIOD ); } } else { resetCharacteristicValue( HUMIDITY_SERV_UUID, HUMIDITY_DATA, 0, HUMIDITY_DATA_LEN); resetCharacteristicValue( HUMIDITY_SERV_UUID, HUMIDITY_CONF, ST_CFG_SENSOR_DISABLE, sizeof ( uint8 )); } return (events ^ ST_HUMIDITY_SENSOR_EVT); } ////////////////////////// // Magnetometer // ////////////////////////// if ( events & ST_MAGNETOMETER_SENSOR_EVT ) { if(magEnabled) { if (HalMagStatus() == MAG3110_DATA_READY) { readMagData(); } else if (HalMagStatus() == MAG3110_OFF) { HalMagTurnOn(); } osal_start_timerEx( sensorTag_TaskID, ST_MAGNETOMETER_SENSOR_EVT, sensorMagPeriod ); } else { HalMagTurnOff(); resetCharacteristicValue( MAGNETOMETER_SERV_UUID, MAGNETOMETER_DATA, 0, MAGNETOMETER_DATA_LEN); resetCharacteristicValue( MAGNETOMETER_SERV_UUID, MAGNETOMETER_CONF, ST_CFG_SENSOR_DISABLE, sizeof ( uint8 )); resetCharacteristicValue( MAGNETOMETER_SERV_UUID, MAGNETOMETER_PERI, MAG_DEFAULT_PERIOD/MAGNETOMETER_TIME_UNIT, sizeof ( uint8 )); } return (events ^ ST_MAGNETOMETER_SENSOR_EVT); } ////////////////////////// // Barometer // ////////////////////////// if ( events & ST_BAROMETER_SENSOR_EVT ) { if (barEnabled) { if (barBusy) { barBusy = FALSE; readBarData(); osal_start_timerEx( sensorTag_TaskID, ST_BAROMETER_SENSOR_EVT, BAR_DEFAULT_PERIOD ); } else { barBusy = TRUE; HalBarStartMeasurement(); osal_start_timerEx( sensorTag_TaskID, ST_BAROMETER_SENSOR_EVT, BAR_FSM_PERIOD ); } } else { resetCharacteristicValue( BAROMETER_SERV_UUID, BAROMETER_DATA, 0, BAROMETER_DATA_LEN); resetCharacteristicValue( BAROMETER_SERV_UUID, BAROMETER_CONF, ST_CFG_SENSOR_DISABLE, sizeof ( uint8 )); resetCharacteristicValue( BAROMETER_SERV_UUID, BAROMETER_CALI, 0, BAROMETER_CALI_LEN); } return (events ^ ST_BAROMETER_SENSOR_EVT); } ////////////////////////// // Gyroscope // ////////////////////////// if ( events & ST_GYROSCOPE_SENSOR_EVT ) { uint8 status; status = HalGyroStatus(); if(gyroEnabled) { if (status == HAL_GYRO_STOPPED) { HalGyroSelectAxes(sensorGyroAxes); HalGyroTurnOn(); osal_start_timerEx( sensorTag_TaskID, ST_GYROSCOPE_SENSOR_EVT, GYRO_STARTUP_TIME); } else { if(sensorGyroUpdateAxes) { HalGyroSelectAxes(sensorGyroAxes); sensorGyroUpdateAxes = FALSE; } if (status == HAL_GYRO_DATA_READY) { readGyroData(); osal_start_timerEx( sensorTag_TaskID, ST_GYROSCOPE_SENSOR_EVT, GYRO_DEFAULT_PERIOD - GYRO_STARTUP_TIME); } else { // Gyro needs to be activated; HalGyroWakeUp(); osal_start_timerEx( sensorTag_TaskID, ST_GYROSCOPE_SENSOR_EVT, GYRO_STARTUP_TIME); } } } else { HalGyroTurnOff(); if ( status == HAL_GYRO_STOPPED) { resetCharacteristicValue( GYROSCOPE_SERV_UUID, GYROSCOPE_DATA, 0, GYROSCOPE_DATA_LEN); resetCharacteristicValue( GYROSCOPE_SERV_UUID, GYROSCOPE_CONF, ST_CFG_SENSOR_DISABLE, sizeof( uint8 )); } else { // Indicate error resetCharacteristicValue( GYROSCOPE_SERV_UUID, GYROSCOPE_DATA, ST_CFG_ERROR, GYROSCOPE_DATA_LEN); resetCharacteristicValue( GYROSCOPE_SERV_UUID, GYROSCOPE_CONF, ST_CFG_ERROR, sizeof( uint8 )); } } return (events ^ ST_GYROSCOPE_SENSOR_EVT); } #if defined ( PLUS_BROADCASTER ) if ( events & ST_ADV_IN_CONNECTION_EVT ) { uint8 turnOnAdv = TRUE; // Turn on advertising while in a connection GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &turnOnAdv ); return (events ^ ST_ADV_IN_CONNECTION_EVT); } #endif // PLUS_BROADCASTER // Discard unknown events return 0; }
/********************************************************************* * @fn gapRole_ProcessOSALMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void gapRole_ProcessOSALMsg( osal_event_hdr_t *pMsg ) { switch ( pMsg->event ) { case HCI_GAP_EVENT_EVENT: if ( pMsg->status == HCI_COMMAND_COMPLETE_EVENT_CODE ) { hciEvt_CmdComplete_t *pPkt = (hciEvt_CmdComplete_t *)pMsg; if ( pPkt->cmdOpcode == HCI_READ_RSSI ) { int8 rssi = (int8)pPkt->pReturnParam[3]; if ( (gapRole_state == GAPROLE_CONNECTED) && (rssi != RSSI_NOT_AVAILABLE) ) { // Report RSSI to app if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnRssiRead ) { pGapRoles_AppCGs->pfnRssiRead( rssi ); } } } } break; case GAP_MSG_EVENT: gapRole_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); break; case L2CAP_SIGNAL_EVENT: { l2capSignalEvent_t *pPkt = (l2capSignalEvent_t *)pMsg; // Process the Parameter Update Response if ( pPkt->opcode == L2CAP_PARAM_UPDATE_RSP ) { l2capParamUpdateRsp_t *pRsp = (l2capParamUpdateRsp_t *)&(pPkt->cmd.updateRsp); if ( ( pRsp->result == L2CAP_CONN_PARAMS_REJECTED ) && ( paramUpdateNoSuccessOption == GAPROLE_TERMINATE_LINK ) ) { // Cancel connection param update timeout timer VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ); // Terminate connection immediately GAPRole_TerminateConnection(); } else { uint16 timeout = GAP_GetParamValue( TGAP_CONN_PARAM_TIMEOUT ); // Let's wait for Controller to update connection parameters if they're // accepted. Otherwise, decide what to do based on no success option. VOID osal_start_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT, timeout ); } } } break; default: break; } }
/********************************************************************* * @fn SensorGapStateCB * * @brief Notification from the profile of a state change. * * @param newState - new state * * @return none */ static void SensorGapStateCB( gaprole_States_t newState ) { // If connected if (newState == GAPROLE_CONNECTED) { // Get connection handle GAPRole_GetParameter(GAPROLE_CONNHANDLE, &gapConnHandle); // Set timer to update connection parameters // 5 seconds should allow enough time for Service Discovery by the collector to finish osal_start_timerEx( sensor_TaskID, CSC_CONN_PARAM_UPDATE_EVT, SVC_DISC_DELAY); } // If disconnected else if (gapProfileState == GAPROLE_CONNECTED && newState != GAPROLE_CONNECTED) { uint8 advState = TRUE; uint8 bondCount = 0; // Stop periodic measurement osal_stop_timerEx( sensor_TaskID, CSC_PERIODIC_EVT ); // Reset client characteristic configuration descriptors Cycling_HandleConnStatusCB( gapConnHandle, LINKDB_STATUS_UPDATE_REMOVED ); // If not already using white list, begin to do so. GAPBondMgr_GetParameter( GAPBOND_BOND_COUNT, &bondCount ); if( USING_WHITE_LIST && sensorUsingWhiteList == FALSE && bondCount > 0 ) { uint8 value = GAP_FILTER_POLICY_WHITE; GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof( uint8 ), &value); sensorUsingWhiteList = TRUE; } if ( newState == GAPROLE_WAITING_AFTER_TIMEOUT ) { // link loss timeout-- use fast advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_WHITE_LIST_ADV_DURATION ); } else { // Else use slow advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_WHITE_LIST_ADV_DURATION ); } // Enable advertising GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } // if advertising stopped else if ( gapProfileState == GAPROLE_ADVERTISING && newState == GAPROLE_WAITING ) { uint8 whiteListUsed = FALSE; // if white list is in use, disable to allow general access if( sensorUsingWhiteList == TRUE ) { uint8 value = GAP_FILTER_POLICY_ALL; GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof( uint8), &value); whiteListUsed = TRUE; sensorUsingWhiteList = FALSE; } // if advertising stopped by user if ( sensorAdvCancelled ) { sensorAdvCancelled = FALSE; } // if fast advertising interrupted to cancel white list else if ( ( (!USING_WHITE_LIST) || whiteListUsed) && (GAP_GetParamValue( TGAP_GEN_DISC_ADV_INT_MIN ) == DEFAULT_FAST_ADV_INTERVAL ) ) { uint8 advState = TRUE; GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_FAST_ADV_DURATION ); GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } // if fast advertising switch to slow or if was already slow but using white list. else if ( ((!USING_WHITE_LIST) || whiteListUsed) || (GAP_GetParamValue( TGAP_GEN_DISC_ADV_INT_MIN ) == DEFAULT_FAST_ADV_INTERVAL) ) { uint8 advState = TRUE; GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION ); GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } } // if started else if (newState == GAPROLE_STARTED) { // Set the system ID from the bd addr uint8 systemId[DEVINFO_SYSTEM_ID_LEN]; GAPRole_GetParameter(GAPROLE_BD_ADDR, systemId); // shift three bytes up systemId[7] = systemId[5]; systemId[6] = systemId[4]; systemId[5] = systemId[3]; // set middle bytes to zero systemId[4] = 0; systemId[3] = 0; DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); } gapProfileState = newState; }
/********************************************************************* * @fn gapRole_ProcessGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) { uint8 notify = FALSE; // State changed notify the app? (default no) switch ( pMsg->opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg; bStatus_t stat = pPkt->hdr.status; if ( stat == SUCCESS ) { // Save off the generated keys VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapRole_IRK ); VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapRole_SRK ); // Save off the information VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_state = GAPROLE_STARTED; // Update the advertising data stat = GAP_UpdateAdvertisingData( gapRole_TaskID, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData ); } if ( stat != SUCCESS ) { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_ADV_DATA_UPDATE_DONE_EVENT: { gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { if ( pPkt->adType ) { // Setup the Response Data pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData ); } else if ( ( gapRole_state != GAPROLE_ADVERTISING ) && ( osal_get_timeoutEx( gapRole_TaskID, START_ADVERTISING_EVT ) == 0 ) ) { // Start advertising VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); } } if ( pPkt->hdr.status != SUCCESS ) { // Set into Error state gapRole_state = GAPROLE_ERROR; notify = TRUE; } } break; case GAP_MAKE_DISCOVERABLE_DONE_EVENT: case GAP_END_DISCOVERABLE_DONE_EVENT: { gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT ) { if (gapRole_state == GAPROLE_CONNECTED) { gapRole_state = GAPROLE_CONNECTED_ADV; } else { gapRole_state = GAPROLE_ADVERTISING; } } else // GAP_END_DISCOVERABLE_DONE_EVENT { if ( gapRole_AdvertOffTime != 0 ) { if ( ( gapRole_AdvEnabled ) ) { VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime ); } } else { // Since gapRole_AdvertOffTime is set to 0, the device should not // automatically become discoverable again after a period of time. // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; } if (gapRole_state == GAPROLE_CONNECTED_ADV) { // In the Advertising Off period gapRole_state = GAPROLE_CONNECTED; } else if (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT) { // Advertising was just turned off after the link disconnected so begin // advertising again. gapRole_AdvEnabled = TRUE; // Turn advertising back on. VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); } else { // In the Advertising Off period gapRole_state = GAPROLE_WAITING; } } } else { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { VOID osal_memcpy( gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_ConnectionHandle = pPkt->connectionHandle; gapRole_state = GAPROLE_CONNECTED; if ( gapRole_RSSIReadRate ) { // Start the RSSI Reads VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } // Store connection information gapRole_ConnInterval = pPkt->connInterval; gapRole_ConnSlaveLatency = pPkt->connLatency; gapRole_ConnTimeout = pPkt->connTimeout; // Check whether update parameter request is enabled if ( gapRole_ParamUpdateEnable == TRUE ) { // Get the minimum time upon connection establishment before the // peripheral can start a connection update procedure. uint16 timeout = GAP_GetParamValue( TGAP_CONN_PAUSE_PERIPHERAL ); osal_start_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT, timeout*1000 ); } // Notify the Bond Manager to the connection VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_PERIPHERAL ); // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; } else if ( pPkt->hdr.status == bleGAPConnNotAcceptable ) { // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; // Go to WAITING state, and then start advertising gapRole_state = GAPROLE_WAITING; } else { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_LINK_TERMINATED_EVENT: { gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg; VOID GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); osal_memset( gapRole_ConnectedDevAddr, 0, B_ADDR_LEN ); // Erase connection information gapRole_ConnInterval = 0; gapRole_ConnSlaveLatency = 0; gapRole_ConnTimeout = 0; // Cancel all connection parameter update timers (if any active) VOID osal_stop_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT ); VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ); // Go to WAITING state, and then start advertising if( pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM ) { gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT; } else { gapRole_state = GAPROLE_WAITING; } notify = TRUE; // Check if still advertising from within last connection. if ( gapRole_AdvEnabled) { // End advertising so we can restart advertising in order // to change to connectable advertising from nonconnectable. VOID GAP_EndDiscoverable( gapRole_TaskID ); } else // Turn advertising back on. { gapRole_AdvEnabled = TRUE; VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT); } gapRole_ConnectionHandle = INVALID_CONNHANDLE; } break; case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg; // Cancel connection param update timeout timer (if active) VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ); if ( pPkt->hdr.status == SUCCESS ) { // Store new connection parameters gapRole_ConnInterval = pPkt->connInterval; gapRole_ConnSlaveLatency = pPkt->connLatency; gapRole_ConnTimeout = pPkt->connTimeout; // Make sure there's no pending connection update procedure if ( osal_get_timeoutEx( gapRole_TaskID, START_CONN_UPDATE_EVT ) == 0 ) { // Notify the application with the new connection parameters if ( pGapRoles_ParamUpdateCB != NULL ) { (*pGapRoles_ParamUpdateCB)( gapRole_ConnInterval, gapRole_ConnSlaveLatency, gapRole_ConnTimeout ); } } } } break; default: break; } if ( notify == TRUE ) { // Notify the application with the new state change if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) { pGapRoles_AppCGs->pfnStateChange( gapRole_state ); } } }
/********************************************************************* * @fn SensorCB * * @brief Callback function for CSC service. * * @param event - service event * @param pNewCummVal - pointer to new wheel revolution data * if specified by event. NULL otherwise. * @return none */ static void SensorCB( uint8 event, uint32 *pNewCummVal ) { switch ( event ) { case CSC_CMD_SET_CUMM_VAL: // Cancel neglect timer if ( USING_NEGLECT_TIMEOUT ) { osal_stop_timerEx( sensor_TaskID, CSC_NEGLECT_TIMEOUT_EVT ); } cummWheelRevs = *pNewCummVal; // Start neglect timer if ( USING_NEGLECT_TIMEOUT ) { osal_start_timerEx( sensor_TaskID, CSC_NEGLECT_TIMEOUT_EVT, NEGLECT_TIMEOUT_DELAY ); } break; case CSC_CMD_UPDATE_SENS_LOC: // Cancel neglect timer if ( USING_NEGLECT_TIMEOUT ) { osal_stop_timerEx( sensor_TaskID, CSC_NEGLECT_TIMEOUT_EVT ); } // Get updated sensor location Cycling_GetParameter( CSC_SENS_LOC, &sensorLocation ); // Start neglect timer if ( USING_NEGLECT_TIMEOUT ) { osal_start_timerEx( sensor_TaskID, CSC_NEGLECT_TIMEOUT_EVT, NEGLECT_TIMEOUT_DELAY ); } break; case CSC_MEAS_NOTI_ENABLED: // Cancel neglect timer if ( USING_NEGLECT_TIMEOUT ) { osal_stop_timerEx( sensor_TaskID, CSC_NEGLECT_TIMEOUT_EVT ); } // If connected start periodic measurement if (gapProfileState == GAPROLE_CONNECTED) { osal_start_timerEx( sensor_TaskID, CSC_PERIODIC_EVT, DEFAULT_CSC_PERIOD ); } break; case CSC_MEAS_NOTI_DISABLED: // Stop periodic measurement osal_stop_timerEx( sensor_TaskID, CSC_PERIODIC_EVT ); // Start neglect timer if ( USING_NEGLECT_TIMEOUT ) { osal_start_timerEx( sensor_TaskID, CSC_NEGLECT_TIMEOUT_EVT, NEGLECT_TIMEOUT_DELAY ); } break; case CSC_READ_ATTR: case CSC_WRITE_ATTR: if ( USING_NEGLECT_TIMEOUT ) { // Cancel neglect timer osal_stop_timerEx( sensor_TaskID, CSC_NEGLECT_TIMEOUT_EVT ); // Start neglect timer osal_start_timerEx( sensor_TaskID, CSC_NEGLECT_TIMEOUT_EVT, NEGLECT_TIMEOUT_DELAY ); } break; default: break; } }
/************************************************************************************************** * @fn MHMSZdoStateChange * * @brief This function is called by MHMSSysEvtMsg() for a ZDO_STATE_CHANGE message. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ static void MHMSZdoStateChange(void) { if(DEV_ZB_COORD == devState) { (void)osal_stop_timerEx(MHMSTaskId, MHMS_EVT_ANN); if ((DEV_ZB_COORD == devState) || (DEV_ROUTER == devState) || (DEV_END_DEVICE == devState)) { if (INVALID_NODE_ADDR == MHMSAddr) { MHMSAddr = NWK_PAN_COORD_ADDR; } if (INVALID_NODE_ADDR != MHMSAddr) { if (ZSuccess != osal_start_timerEx(MHMSTaskId, MHMS_EVT_ANN, MHMS_DLY_ANN)) { (void)osal_set_event(MHMSTaskId, MHMS_EVT_ANN); } } } } else if ((DEV_ROUTER == devState) || (DEV_END_DEVICE == devState)) { (void)osal_stop_timerEx(MHMSTaskId, MHMS_EVT_DAT); MHMSEvtDat_sync = FALSE; //allow node to respond to Anounce commands to begin pulse collection if ((DEV_ROUTER == devState) || (DEV_END_DEVICE == devState)) // { uint16 tmp = NLME_GetCoordShortAddr(); uint8 dly = MHMS_STG_DAT; MHMSDat[MHMS_PAR_LSB] = LO_UINT16(tmp); MHMSDat[MHMS_PAR_MSB] = HI_UINT16(tmp); TestDatTx[MHMS_PAR_LSB] = LO_UINT16(tmp); TestDatTx[MHMS_PAR_MSB] = HI_UINT16(tmp); if ((DEV_ROUTER == devState) || (DEV_ZB_COORD == devState)) { MHMSDat[MHMS_TYP_IDX] |= 0x80; TestDatTx[MHMS_TEST_PAYLOAD_LEN-3] |= 0x80; } else { MHMSDat[MHMS_TYP_IDX] &= (0xFF ^ 0x80); TestDatTx[MHMS_TEST_PAYLOAD_LEN-3] &= (0xFF ^ 0x80); } #if TVSA_DONGLE_IS_ZC if (INVALID_NODE_ADDR == MHMSAddr) { MHMSAddr = NWK_PAN_COORD_ADDR; } #endif if (INVALID_NODE_ADDR != MHMSAddr && dev_gateway == FALSE) { if (ZSuccess != osal_start_timerEx(MHMSTaskId, MHMS_EVT_DAT, (dly + MHMS_DLY_MIN))) { (void)osal_set_event(MHMSTaskId, MHMS_EVT_DAT); } } if (0 == 0) { (void)osal_cpyExtAddr(MHMSDat+MHMS_IEE_IDX, &aExtendedAddress); (void)osal_cpyExtAddr(TestDatTx+MHMS_IEE_IDX, &aExtendedAddress); } } } #if defined LCD_SUPPORTED HalLcdWriteValue(devState, 10, HAL_LCD_LINE_4); #endif }
void CurrentDetectionT1_Init(uint8 task_id) { IO_Init(); CurrentDetectionT1_TaskID = task_id; CurrentDetectionT1_NwkState = DEV_INIT; CurrentDetectionT1_TransID = 0; MT_UartInit(); MT_UartRegisterTaskID(task_id); // Device hardware initialization can be added here or in main() (Zmain.c). // If the hardware is application specific - add it here. // If the hardware is other parts of the device add it in main(). #if defined ( BUILD_ALL_DEVICES ) // The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START // We are looking at a jumper (defined in CurrentDetectionT1Hw.c) to be jumpered // together - if they are - we will start up a coordinator. Otherwise, // the device will start as a router. if (readCoordinatorJumper()) zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR; else zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER; #endif // BUILD_ALL_DEVICES // Setup for the periodic message's destination address // Broadcast to everyone CurrentDetectionT1_Periodic_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; CurrentDetectionT1_Periodic_DstAddr.endPoint = HEARTBEAT_ENDPOINT; CurrentDetectionT1_Periodic_DstAddr.addr.shortAddr = 0; // Fill out the endpoint description. CurrentDetectionT1_epDesc.endPoint = HEARTBEAT_ENDPOINT; CurrentDetectionT1_epDesc.task_id = &CurrentDetectionT1_TaskID; CurrentDetectionT1_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&CurrentDetectionT1_SimpleDesc; CurrentDetectionT1_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister(&CurrentDetectionT1_epDesc); // Register for all key events - This app will handle all key events RegisterForKeys(CurrentDetectionT1_TaskID); nv_read_config(); HalAdcInit(); HalAdcSetReference(HAL_ADC_REF_AVDD); #ifdef DEBUG_TRACE //memset(serialNumber, 0, SN_LEN); //serialNumber[SN_LEN - 1] = 20; #endif memcpy(serialNumber, aExtendedAddress, SN_LEN); //Feed WatchDog WDCTL = 0xa0; WDCTL = 0x50; osal_start_timerEx(CurrentDetectionT1_TaskID, DTCT_HEARTBEAT_MSG_EVT, 10); osal_start_timerEx(CurrentDetectionT1_TaskID, DTCT_LED_WTD_EVT, 10); }
/********************************************************************* * @fn zclSample_event_loop * * @brief Event Loop Processor for zclGeneral. * * @param none * * @return none */ uint16 zclRouterVersion1_event_loop( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclRouterVersion1_TaskID )) ) { switch ( MSGpkt->hdr.event ) { case ZCL_INCOMING_MSG: // Incoming ZCL Foundation command/response messages zclRouterVersion1_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt ); break; case KEY_CHANGE: //zclRouterVersion1_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys ); break; case ZDO_STATE_CHANGE: zclRouterVersion1_NwkState = (devStates_t)(MSGpkt->hdr.status); // now on the network if ( (zclRouterVersion1_NwkState == DEV_ZB_COORD) || (zclRouterVersion1_NwkState == DEV_ROUTER) || (zclRouterVersion1_NwkState == DEV_END_DEVICE) ) { HalLedSet(HAL_LED_1,HAL_LED_MODE_ON); } break; default: { } break; } // Release the memory osal_msg_deallocate( (uint8 *)MSGpkt ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & SET_PARAMETER ) { button1 = P0_2; button2 = P0_3; button3 = P0_4; return ( events = CHECK_INPUT_BUTTON); } if ( events & CHECK_INPUT_BUTTON ) { if (button1 ^ P0_2 ) { HalLedSet(HAL_LED_2,HAL_LED_MODE_TOGGLE); button1 = P0_2 ; } if (button2 ^ P0_3 ) { if(P1_2 == 0) { P1_2 = 1; //P0_1 = 1; } else { P1_2 = 0; //P0_1 = 0; } button2 = P0_3 ; } if (button3 ^ P0_4 ) { if(P1_3 == 0) { P1_3 = 1; //P0_1 = 1; } else { P1_3 = 0; //P0_1 = 0; } button3 = P0_4 ; } if (P0_1) { ZDOInitDevice(0); } if ( P0_0) { zclRouterVersion1_BasicResetCB(); } osal_start_timerEx(zclRouterVersion1_TaskID, CHECK_INPUT_BUTTON, 400); return ( events ^ CHECK_INPUT_BUTTON ); } return 0; }
uint16 CurrentDetectionT1_ProcessEvent(uint8 task_id, uint16 events) { static uint16 timerCount = 0; static uint32 heartBitFailNum = 0; //uint8 deltaInfo[] = "delta = 1\n"; afIncomingMSGPacket_t* MSGpkt; (void)task_id; // Intentionally unreferenced parameter if (events & SYS_EVENT_MSG) { MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(CurrentDetectionT1_TaskID); while (MSGpkt) { switch (MSGpkt->hdr.event) { case CMD_SERIAL_MSG: CurrentDetectionT1_SerialCMD((mtOSALSerialData_t *)MSGpkt); break; case AF_INCOMING_MSG_CMD: CurrentDetectionT1_RfCMD(MSGpkt->cmd.DataLength, MSGpkt->cmd.Data); HalLedBlink(HAL_LED_2, 2, 20, 50); break; // Received whenever the device changes state in the network case ZDO_STATE_CHANGE: CurrentDetectionT1_NwkState = (devStates_t)(MSGpkt->hdr.status); if (CurrentDetectionT1_NwkState == DEV_END_DEVICE) { HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); HalUARTWrite(0, EndDeviceStatus, strlen((char *)EndDeviceStatus)); inNetwork = true; } break; default: break; } // Release the memory osal_msg_deallocate((uint8 *)MSGpkt); // Next - if one is available MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(CurrentDetectionT1_TaskID); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } // Send a message out - This event is generated by a timer // (setup in CurrentDetectionT1_Init()). if (events & DTCT_HEARTBEAT_MSG_EVT) { uint8 sendToG1Data[HEART_BIT_MSG_LEN]; sendToG1Data[HEART_BIT_MSG_LEN - 1] = 0; memcpy(sendToG1Data, serialNumber, SN_LEN); reset_osal_SystemClock(); if (lastNvTime_l + get_osal_SystemClock() < lastNvTime_l) { nv_write_config(); HAL_SYSTEM_RESET(); } if (CurrentDetectionT1_HandleSendRepairMessage(sendToG1Data)) { CurrentDetectionT1_SampleCurrentAdcValue(true); osal_start_timerEx( CurrentDetectionT1_TaskID, DTCT_HEARTBEAT_MSG_EVT, DTCT_TIMER_MSG_TIMEOUT); // The repairing status, no need to send ADC value any more. return (events ^ DTCT_HEARTBEAT_MSG_EVT); } CurrentDetectionT1_SampleCurrentAdcValue(false); ++timerCount; if ((timerCount == (480 * heartbitRate)) || (timerCount == (960 * heartbitRate)) || (timerCount == (1440 * heartbitRate))) { CurrentDetectionT1_RecoverHeartBeatMessage(sendToG1Data); } // send heart beat every 1.92s. else if (timerCount == (HEARTBIT_TIME_UINT * heartbitRate)) { CurrentDetectionT1_SetAverageCurrentAdcValue(sendToG1Data, CYCLE_NUM_IN_UINT * heartbitRate); SET_HEART_BIT_STATUS(sendToG1Data , HEART_BIT_STATUS_POWER_SUPPLY_MASK, 0); SET_HEART_BIT_STATUS(sendToG1Data , HEART_BIT_STATUS_BATTERY_CHARGING_MASK, 1); if (inNetwork) { // Send the Heartbeat Message if (!CurrentDetectionT1_SendHeartBeatMessage(sendToG1Data)) { ++heartBitFailNum; CurrentDetectionT1_StoreHeartBeatMessage(sendToG1Data); } else { heartBitFailNum = 0; } } else { ++heartBitFailNum; if (CurrentDetectionT1_CheckDelta(sendToG1Data)) { CurrentDetectionT1_StoreHeartBeatMessage(sendToG1Data); } } if (heartBitFailNum == FAIL_TIMES_TO_RESTART) { if (nv_mem_number()) { nv_write_msg(); } HAL_SYSTEM_RESET(); } timerCount = 0; } osal_start_timerEx( CurrentDetectionT1_TaskID, DTCT_HEARTBEAT_MSG_EVT, DTCT_TIMER_MSG_TIMEOUT); // return unprocessed events return (events ^ DTCT_HEARTBEAT_MSG_EVT); } if (events & DTCT_LED_WTD_EVT) { //Feed WatchDog WDCTL = 0xa0; WDCTL = 0x50; if (P2_0) { HalLedSet(HAL_LED_1, HAL_LED_MODE_ON); HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); } else { checkLedStatus(); } osal_start_timerEx( CurrentDetectionT1_TaskID, DTCT_LED_WTD_EVT, DTCT_LED_WTD_EVT_TIMEOUT); return (events ^ DTCT_LED_WTD_EVT); } // Discard unknown events return 0; }
/********************************************************************* * @fn GenericApp_ProcessEvent * * @brief Generic Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return none */ uint16 GenericApp_ProcessEvent( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; afDataConfirm_t *afDataConfirm; // Data Confirmation message fields byte sentEP; ZStatus_t sentStatus; byte sentTransID; // This should match the value sent (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID ); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { case ZDO_CB_MSG: GenericApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt ); break; case KEY_CHANGE: GenericApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys ); break; case AF_DATA_CONFIRM_CMD: // This message is received as a confirmation of a data packet sent. // The status is of ZStatus_t type [defined in ZComDef.h] // The message fields are defined in AF.h afDataConfirm = (afDataConfirm_t *)MSGpkt; sentEP = afDataConfirm->endpoint; sentStatus = afDataConfirm->hdr.status; sentTransID = afDataConfirm->transID; (void)sentEP; (void)sentTransID; // Action taken when confirmation is received. if ( sentStatus != ZSuccess ) { // The data wasn't delivered -- Do something } break; case AF_INCOMING_MSG_CMD: GenericApp_MessageMSGCB( MSGpkt ); break; case ZDO_STATE_CHANGE: GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status); if ( (GenericApp_NwkState == DEV_ZB_COORD) || (GenericApp_NwkState == DEV_ROUTER) || (GenericApp_NwkState == DEV_END_DEVICE) ) { //Send short addr to coordinator osal_set_event(GenericApp_TaskID,SEND_ADDR_EVT); // Start sending "the" message in a regular interval. osal_start_timerEx( GenericApp_TaskID, GENERICAPP_SEND_MSG_EVT, GENERICAPP_SEND_MSG_TIMEOUT ); } break; default: break; } // Release the memory osal_msg_deallocate( (uint8 *)MSGpkt ); // Next MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } // Send a message out - This event is generated by a timer // (setup in GenericApp_Init()). if ( events & GENERICAPP_SEND_MSG_EVT ) { // Send "the" message GenericApp_SendTheMessage(); // Setup to send message again osal_start_timerEx( GenericApp_TaskID, GENERICAPP_SEND_MSG_EVT, GENERICAPP_SEND_MSG_TIMEOUT ); // return unprocessed events return (events ^ GENERICAPP_SEND_MSG_EVT); } if ( events & SEND_ADDR_EVT ) { // Send "the" message My_SendTheShortAddr(); // return unprocessed events return (events ^ SEND_ADDR_EVT); } #if defined( IAR_ARMCM3_LM ) // Receive a message from the RTOS queue if ( events & GENERICAPP_RTOS_MSG_EVT ) { // Process message from RTOS queue GenericApp_ProcessRtosMessage(); // return unprocessed events return (events ^ GENERICAPP_RTOS_MSG_EVT); } #endif // Discard unknown events return 0; }
/********************************************************************* * @fn simpleBLECentralEventCB * * @brief Central event callback function. * * @param pEvent - pointer to event structure * * @return none */ static void simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent ) { switch ( pEvent->gap.opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { LCD_WRITE_STRING( "BLE Central", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( bdAddr2Str( pEvent->initDone.devAddr ), HAL_LCD_LINE_2 ); } break; case GAP_DEVICE_INFO_EVENT: { var1= pEvent->deviceInfo.pEvtData; dataToPrint = var1[5]; //LCD_WRITE_STRING( bdAddr2Str(var1), HAL_LCD_LINE_3 ); if(dataToPrint == 0xA1) { LCD_WRITE_STRING_VALUE( "Value",var1[6], 16, HAL_LCD_LINE_3); } // if filtering device discovery results based on service UUID if ( DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE ) { if ( simpleBLEFindSvcUuid( SIMPLEPROFILE_SERV_UUID, pEvent->deviceInfo.pEvtData, pEvent->deviceInfo.dataLen ) ) { simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType ); } } } break; case GAP_DEVICE_DISCOVERY_EVENT: { // discovery complete simpleBLEScanning = FALSE; // if not filtering device discovery results based on service UUID if ( DEFAULT_DEV_DISC_BY_SVC_UUID == FALSE ) { // Copy results simpleBLEScanRes = pEvent->discCmpl.numDevs; osal_memcpy( simpleBLEDevList, pEvent->discCmpl.pDevList, (sizeof( gapDevRec_t ) * pEvent->discCmpl.numDevs) ); } LCD_WRITE_STRING_VALUE( "Devices Found", simpleBLEScanRes, 10, HAL_LCD_LINE_1 ); if ( simpleBLEScanRes > 0 ) { LCD_WRITE_STRING( "<- To Select", HAL_LCD_LINE_2 ); simpleBLEState = BLE_STATE_IDLE; simpleBLEConnHandle = GAP_CONNHANDLE_INIT; simpleBLERssi = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; } if ( simpleBLEState != BLE_STATE_CONNECTED ) { if ( !simpleBLEScanning ) { uint8 adc7 = HalAdcRead (HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_8); LCD_WRITE_STRING_VALUE( "Value",adc7, 16, HAL_LCD_LINE_2); advertData[6]= var1[6]; advertData[8]= 0xA9; if(adc7>0x7E) advertData[9]= 0x01; else advertData[9]= 0x02; advertData[10]= 0xB9; GAP_UpdateAdvertisingData( GAPROLE_ADVERT_ENABLED,TRUE, sizeof(advertData),advertData); simpleBLEScanning = TRUE; simpleBLEScanRes = 0; LCD_WRITE_STRING( "Discovering...", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_2 ); GAPCentralRole_StartDiscovery( DEFAULT_DISCOVERY_MODE, DEFAULT_DISCOVERY_ACTIVE_SCAN, DEFAULT_DISCOVERY_WHITE_LIST ); } else { GAPCentralRole_CancelDiscovery(); } } // initialize scan index to last device simpleBLEScanIdx = simpleBLEScanRes; } break; case GAP_LINK_ESTABLISHED_EVENT: { if ( pEvent->gap.hdr.status == SUCCESS ) { simpleBLEState = BLE_STATE_CONNECTED; simpleBLEConnHandle = pEvent->linkCmpl.connectionHandle; simpleBLEProcedureInProgress = TRUE; // If service discovery not performed initiate service discovery if ( simpleBLECharHdl == 0 ) { osal_start_timerEx( simpleBLETaskId, START_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY ); } LCD_WRITE_STRING( bdAddr2Str(var1), HAL_LCD_LINE_3 ); LCD_WRITE_STRING( "Connected", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( bdAddr2Str( pEvent->linkCmpl.devAddr ), HAL_LCD_LINE_2 ); } else { simpleBLEState = BLE_STATE_IDLE; simpleBLEConnHandle = GAP_CONNHANDLE_INIT; simpleBLERssi = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; LCD_WRITE_STRING( "Connect Failed", HAL_LCD_LINE_1 ); LCD_WRITE_STRING_VALUE( "Reason:", pEvent->gap.hdr.status, 10, HAL_LCD_LINE_2 ); } } break; case GAP_LINK_TERMINATED_EVENT: { simpleBLEState = BLE_STATE_IDLE; simpleBLEConnHandle = GAP_CONNHANDLE_INIT; simpleBLERssi = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; simpleBLECharHdl = 0; simpleBLEProcedureInProgress = FALSE; LCD_WRITE_STRING( "Disconnected", HAL_LCD_LINE_1 ); LCD_WRITE_STRING_VALUE( "Reason:", pEvent->linkTerminate.reason, 10, HAL_LCD_LINE_2 ); } break; case GAP_LINK_PARAM_UPDATE_EVENT: { LCD_WRITE_STRING( "Connected Update", HAL_LCD_LINE_1 ); } break; default: break; } }
/********************************************************************* * @fn OTA_Dongle_event_loop * * @brief Event Loop Processor for zclGeneral. * * @param none * * @return none */ uint16 OTA_Dongle_event_loop( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( OTA_Dongle_TaskID )) ) { switch ( MSGpkt->hdr.event ) { case ZDO_CB_MSG: OTA_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt ); break; case MT_SYS_APP_MSG: case MT_SYS_APP_RSP_MSG: OTA_ProcSysAppMsg((mtSysAppMsg_t *)MSGpkt); break; case ZCL_INCOMING_MSG: // Incoming ZCL Foundation command/response messages OTA_Dongle_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt ); break; case KEY_CHANGE: OTA_Dongle_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys ); break; case ZDO_STATE_CHANGE: OTA_Dongle_devState = (devStates_t)(MSGpkt->hdr.status); if ((OTA_Dongle_devState == DEV_END_DEVICE) || (OTA_Dongle_devState == DEV_ROUTER) || (OTA_Dongle_devState == DEV_ZB_COORD)) OTA_Send_JoinInd(); break; default: break; } // Release the memory osal_msg_deallocate( (uint8 *)MSGpkt ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & OTA_DONGLE_DONGLE_NOTIFY_EVT ) { OTA_Send_DongleInd(); osal_start_timerEx( OTA_Dongle_TaskID, OTA_DONGLE_DONGLE_NOTIFY_EVT, 4000 ); return ( events ^ OTA_DONGLE_DONGLE_NOTIFY_EVT ); } if ( events & OTA_DONGLE_IDENTIFY_TIMEOUT_EVT ) { if ( OTA_Dongle_IdentifyTime > 0 ) { OTA_Dongle_IdentifyTime--; } OTA_Dongle_ProcessIdentifyTimeChange(); return ( events ^ OTA_DONGLE_IDENTIFY_TIMEOUT_EVT ); } // Discard unknown events return 0; }
/********************************************************************* * @brief Set a GAP Role parameter. * * Public function defined in peripheral.h. */ bStatus_t GAPRole_SetParameter( uint16 param, uint8 len, void *pValue ) { bStatus_t ret = SUCCESS; switch ( param ) { case GAPROLE_IRK: if ( len == KEYLEN ) { VOID osal_memcpy( gapRole_IRK, pValue, KEYLEN ) ; } else { ret = bleInvalidRange; } break; case GAPROLE_SRK: if ( len == KEYLEN ) { VOID osal_memcpy( gapRole_SRK, pValue, KEYLEN ) ; } else { ret = bleInvalidRange; } break; case GAPROLE_SIGNCOUNTER: if ( len == sizeof ( uint32 ) ) { gapRole_signCounter = *((uint32*)pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADVERT_ENABLED: if ( len == sizeof( uint8 ) ) { uint8 oldAdvEnabled = gapRole_AdvEnabled; gapRole_AdvEnabled = *((uint8*)pValue); if ( (oldAdvEnabled) && (gapRole_AdvEnabled == FALSE) ) { // Turn off Advertising if ( ( gapRole_state == GAPROLE_ADVERTISING ) || ( gapRole_state == GAPROLE_CONNECTED_ADV ) || ( gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT ) ) { VOID GAP_EndDiscoverable( gapRole_TaskID ); } } else if ( (oldAdvEnabled == FALSE) && (gapRole_AdvEnabled) ) { // Turn on Advertising if ( (gapRole_state == GAPROLE_STARTED) || (gapRole_state == GAPROLE_WAITING) || (gapRole_state == GAPROLE_CONNECTED) || (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT) ) { VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); } } } else { ret = bleInvalidRange; } break; case GAPROLE_ADVERT_OFF_TIME: if ( len == sizeof ( uint16 ) ) { gapRole_AdvertOffTime = *((uint16*)pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADVERT_DATA: if ( len <= B_MAX_ADV_LEN ) { VOID osal_memset( gapRole_AdvertData, 0, B_MAX_ADV_LEN ); VOID osal_memcpy( gapRole_AdvertData, pValue, len ); gapRole_AdvertDataLen = len; // Update the advertising data ret = GAP_UpdateAdvertisingData( gapRole_TaskID, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData ); } else { ret = bleInvalidRange; } break; case GAPROLE_SCAN_RSP_DATA: if ( len <= B_MAX_ADV_LEN ) { VOID osal_memset( gapRole_ScanRspData, 0, B_MAX_ADV_LEN ); VOID osal_memcpy( gapRole_ScanRspData, pValue, len ); gapRole_ScanRspDataLen = len; // Update the Response Data ret = GAP_UpdateAdvertisingData( gapRole_TaskID, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData ); } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_EVENT_TYPE: if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= GAP_ADTYPE_ADV_LDC_DIRECT_IND) ) { gapRole_AdvEventType = *((uint8*)pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_DIRECT_TYPE: if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= ADDRTYPE_PRIVATE_RESOLVE) ) { gapRole_AdvDirectType = *((uint8*)pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_DIRECT_ADDR: if ( len == B_ADDR_LEN ) { VOID osal_memcpy( gapRole_AdvDirectAddr, pValue, B_ADDR_LEN ) ; } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_CHANNEL_MAP: if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= 0x07) ) { gapRole_AdvChanMap = *((uint8*)pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_FILTER_POLICY: if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= GAP_FILTER_POLICY_WHITE) ) { gapRole_AdvFilterPolicy = *((uint8*)pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_RSSI_READ_RATE: if ( len == sizeof ( uint16 ) ) { gapRole_RSSIReadRate = *((uint16*)pValue); if ( (gapRole_RSSIReadRate) && (gapRole_state == GAPROLE_CONNECTED) ) { // Start the RSSI Reads VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } } else { ret = bleInvalidRange; } break; case GAPROLE_PARAM_UPDATE_ENABLE: if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= TRUE) ) { gapRole_ParamUpdateEnable = *((uint8*)pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_MIN_CONN_INTERVAL: { uint16 newInterval = *((uint16*)pValue); if ( len == sizeof ( uint16 ) && ( newInterval >= MIN_CONN_INTERVAL ) && ( newInterval <= MAX_CONN_INTERVAL ) ) { gapRole_MinConnInterval = newInterval; } else { ret = bleInvalidRange; } } break; case GAPROLE_MAX_CONN_INTERVAL: { uint16 newInterval = *((uint16*)pValue); if ( len == sizeof ( uint16 ) && ( newInterval >= MIN_CONN_INTERVAL) && ( newInterval <= MAX_CONN_INTERVAL) ) { gapRole_MaxConnInterval = newInterval; } else { ret = bleInvalidRange; } } break; case GAPROLE_SLAVE_LATENCY: { uint16 latency = *((uint16*)pValue); if ( len == sizeof ( uint16 ) && (latency < MAX_SLAVE_LATENCY) ) { gapRole_SlaveLatency = latency; } else { ret = bleInvalidRange; } } break; case GAPROLE_TIMEOUT_MULTIPLIER: { uint16 newTimeout = *((uint16*)pValue); if ( len == sizeof ( uint16 ) && (newTimeout >= MIN_TIMEOUT_MULTIPLIER) && (newTimeout <= MAX_TIMEOUT_MULTIPLIER) ) { gapRole_TimeoutMultiplier = newTimeout; } else { ret = bleInvalidRange; } } break; case GAPROLE_PARAM_UPDATE_REQ: { uint8 req = *((uint8*)pValue); if ( len == sizeof ( uint8 ) && (req == TRUE) ) { // Make sure we don't send an L2CAP Connection Parameter Update Request // command within TGAP(conn_param_timeout) of an L2CAP Connection Parameter // Update Response being received. if ( osal_get_timeoutEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ) == 0 ) { // Start connection update procedure gapRole_startConnUpdate( GAPROLE_NO_ACTION ); // Connection update requested by app, cancel such pending procedure (if active) VOID osal_stop_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT ); } else { ret = blePending; } } else { ret = bleInvalidRange; } } break; default: // The param value isn't part of this profile, try the GAP. if ( (param < TGAP_PARAMID_MAX) && (len == sizeof ( uint16 )) ) { ret = GAP_SetParamValue( param, *((uint16*)pValue) ); } else { ret = INVALIDPARAMETER; } break; } return ( ret ); }
/*************************************************************************************************** * @fn MT_AfIncomingMsg * * @brief Process the callback subscription for AF Incoming data. * * @param pkt - Incoming AF data. * * @return none ***************************************************************************************************/ void MT_AfIncomingMsg(afIncomingMSGPacket_t *pMsg) { #define MT_AF_INC_MSG_LEN 17 #define MT_AF_INC_MSG_EXT 10 uint16 dataLen = pMsg->cmd.DataLength; // Length of the data section in the response packet. uint16 respLen = MT_AF_INC_MSG_LEN + dataLen; uint8 cmd = MT_AF_INCOMING_MSG; uint8 *pRsp, *pTmp; mtAfInMsgList_t *pItem = NULL; #if defined INTER_PAN if (StubAPS_InterPan(pMsg->srcAddr.panId, pMsg->srcAddr.endPoint)) { cmd = MT_AF_INCOMING_MSG_EXT; } else #endif if ((pMsg->srcAddr.addrMode == afAddr64Bit) || (respLen > (uint16)(MT_RPC_DATA_MAX - MT_AF_INC_MSG_EXT))) { cmd = MT_AF_INCOMING_MSG_EXT; } if (cmd == MT_AF_INCOMING_MSG_EXT) { respLen += MT_AF_INC_MSG_EXT; } if (respLen > (uint16)MT_RPC_DATA_MAX) { if ((pItem = (mtAfInMsgList_t *)osal_mem_alloc(sizeof(mtAfInMsgList_t) + dataLen)) == NULL) { return; // If cannot hold a huge message, cannot give indication at all. } pItem->data = (uint8 *)(pItem+1); respLen -= dataLen; // Zero data bytes are sent with an over-sized incoming indication. } // Attempt to allocate memory for the response packet. if ((pRsp = osal_mem_alloc(respLen)) == NULL) { if (pItem != NULL) { (void)osal_mem_free(pItem); } return; } pTmp = pRsp; /* Group ID */ *pTmp++ = LO_UINT16(pMsg->groupId); *pTmp++ = HI_UINT16(pMsg->groupId); /* Cluster ID */ *pTmp++ = LO_UINT16(pMsg->clusterId); *pTmp++ = HI_UINT16(pMsg->clusterId); if (cmd == MT_AF_INCOMING_MSG_EXT) { *pTmp++ = pMsg->srcAddr.addrMode; if (pMsg->srcAddr.addrMode == afAddr64Bit) { (void)osal_memcpy(pTmp, pMsg->srcAddr.addr.extAddr, Z_EXTADDR_LEN); } else { pTmp[0] = LO_UINT16(pMsg->srcAddr.addr.shortAddr); pTmp[1] = HI_UINT16(pMsg->srcAddr.addr.shortAddr); } pTmp += Z_EXTADDR_LEN; *pTmp++ = pMsg->srcAddr.endPoint; #if defined INTER_PAN *pTmp++ = LO_UINT16(pMsg->srcAddr.panId); *pTmp++ = HI_UINT16(pMsg->srcAddr.panId); #else *pTmp++ = 0; *pTmp++ = 0; #endif } else { /* Source Address */ *pTmp++ = LO_UINT16(pMsg->srcAddr.addr.shortAddr); *pTmp++ = HI_UINT16(pMsg->srcAddr.addr.shortAddr); /* Source EP */ *pTmp++ = pMsg->srcAddr.endPoint; } /* Destination EP */ *pTmp++ = pMsg->endPoint; /* WasBroadCast */ *pTmp++ = pMsg->wasBroadcast; /* LinkQuality */ *pTmp++ = pMsg->LinkQuality; /* SecurityUse */ *pTmp++ = pMsg->SecurityUse; /* Timestamp */ *pTmp++ = BREAK_UINT32(pMsg->timestamp, 0); *pTmp++ = BREAK_UINT32(pMsg->timestamp, 1); *pTmp++ = BREAK_UINT32(pMsg->timestamp, 2); *pTmp++ = BREAK_UINT32(pMsg->timestamp, 3); /* Data Length */ if (cmd == MT_AF_INCOMING_MSG_EXT) { /* Z-Tool apparently takes the last Byte before the data buffer as the dynamic length and * ignores the bigger UInt16 length of an EXT incoming message. But no data bytes will be sent * with a huge message, so it's necessary to work-around and fake-out Z-Tool with a zero here. */ *pTmp++ = 0; // TODO - workaround Z-Tool shortcoming; should be: = pMsg->cmd.TransSeqNumber; *pTmp++ = LO_UINT16(dataLen); *pTmp++ = HI_UINT16(dataLen); } else { *pTmp++ = pMsg->cmd.TransSeqNumber; *pTmp++ = dataLen; } /* Data */ if (pItem != NULL) { // Enqueue the new huge incoming item. pItem->next = pMtAfInMsgList; pMtAfInMsgList = pItem; // Setup to time-out the huge incoming item if host does not MT_AF_DATA_RETRIEVE it. pItem->tick = MT_AF_EXEC_CNT; if (ZSuccess != osal_start_timerEx(MT_TaskID, MT_AF_EXEC_EVT, MT_AF_EXEC_DLY)) { (void)osal_set_event(MT_TaskID, MT_AF_EXEC_EVT); } pItem->timestamp = pMsg->timestamp; (void)osal_memcpy(pItem->data, pMsg->cmd.Data, dataLen); } else { (void)osal_memcpy(pTmp, pMsg->cmd.Data, dataLen); } /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_AREQ|(uint8)MT_RPC_SYS_AF), cmd, respLen, pRsp); (void)osal_mem_free(pRsp); }
/********************************************************************* * @brief Task Event Processor function. * * Internal function defined in peripheral.h. */ uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events ) { VOID task_id; // OSAL required parameter that isn't used in this function if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( gapRole_TaskID )) != NULL ) { gapRole_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED ) { // Sign counter changed, save it to NV VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter ); return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED ); } if ( events & START_ADVERTISING_EVT ) { if ( gapRole_AdvEnabled ) { gapAdvertisingParams_t params; // Setup advertisement parameters if ( gapRole_state == GAPROLE_CONNECTED ) { // While in a connection, we can only advertise non-connectable undirected. params.eventType = GAP_ADTYPE_ADV_NONCONN_IND; } else { params.eventType = gapRole_AdvEventType; params.initiatorAddrType = gapRole_AdvDirectType; /**wkxboot****/ //change_bdaddr(); /**wkxboot****/ VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN ); } params.channelMap = gapRole_AdvChanMap; params.filterPolicy = gapRole_AdvFilterPolicy; if ( GAP_MakeDiscoverable( gapRole_TaskID, ¶ms ) != SUCCESS ) { gapRole_state = GAPROLE_ERROR; // Notify the application with the new state change if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) { pGapRoles_AppCGs->pfnStateChange( gapRole_state ); } } } return ( events ^ START_ADVERTISING_EVT ); } if ( events & RSSI_READ_EVT ) { // Only get RSSI when in a connection if ( gapRole_state == GAPROLE_CONNECTED ) { // Ask for RSSI VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle ); // Setup next event if ( gapRole_RSSIReadRate ) { VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } } return ( events ^ RSSI_READ_EVT ); } if ( events & START_CONN_UPDATE_EVT ) { // Start connection update procedure gapRole_startConnUpdate( GAPROLE_NO_ACTION ); return ( events ^ START_CONN_UPDATE_EVT ); } if ( events & CONN_PARAM_TIMEOUT_EVT ) { // Unsuccessful in updating connection parameters gapRole_HandleParamUpdateNoSuccess(); return ( events ^ CONN_PARAM_TIMEOUT_EVT ); } // Discard unknown events return 0; }
/********************************************************************* * @fn TimeApp_Init * * @brief Initialization function for the Time App App Task. * This is called during initialization and should contain * any application specific initialization (ie. hardware * initialization/setup, table initialization, power up * notificaiton ... ). * * @param task_id - the ID assigned by OSAL. This ID should be * used to send messages and set timers. * * @return none */ void TimeApp_Init( uint8 task_id ) { timeAppTaskId = task_id; // Setup the GAP Peripheral Role Profile { uint8 advEnable = FALSE; uint16 advertOffTime = 0; uint8 updateRequest = DEFAULT_ENABLE_UPDATE_REQUEST; uint16 minInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; uint16 maxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL; uint16 slaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY; uint16 connTimeout = DEFAULT_DESIRED_CONN_TIMEOUT; GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advEnable ); GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &advertOffTime ); GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_ENABLE, sizeof( uint8 ), &updateRequest ); GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &minInterval ); GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &maxInterval ); GAPRole_SetParameter( GAPROLE_SLAVE_LATENCY, sizeof( uint16 ), &slaveLatency ); GAPRole_SetParameter( GAPROLE_TIMEOUT_MULTIPLIER, sizeof( uint16 ), &connTimeout ); GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( timeAppScanData ), timeAppScanData ); GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( timeAppAdvData ), timeAppAdvData ); } // Setup GAP GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, timeAppDeviceName ); // Setup the GAP Bond Manager { uint32 passkey = DEFAULT_PASSCODE; uint8 pairMode = DEFAULT_PAIRING_MODE; uint8 mitm = DEFAULT_MITM_MODE; uint8 ioCap = DEFAULT_IO_CAPABILITIES; uint8 bonding = DEFAULT_BONDING_MODE; GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof( uint32 ), &passkey ); GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof( uint8 ), &pairMode ); GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof( uint8 ), &mitm ); GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof( uint8 ), &ioCap ); GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof( uint8 ), &bonding ); } // Initialize GATT Client VOID GATT_InitClient(); // Register to receive incoming ATT Indications/Notifications GATT_RegisterForInd( timeAppTaskId ); // Initialize GATT attributes GGS_AddService( GATT_ALL_SERVICES ); // GAP GATTServApp_AddService( GATT_ALL_SERVICES ); // GATT attributes // Register for all key events - This app will handle all key events RegisterForKeys( timeAppTaskId ); // makes sure LEDs are off HalLedSet( (HAL_LED_1 | HAL_LED_2), HAL_LED_MODE_OFF ); // If key pressed on startup clear all stored bonds if ( HalKeyRead() & HAL_KEY_CENTER ) { GAPBondMgr_SetParameter( GAPBOND_ERASE_ALLBONDS, 0, 0 ); } // Start clock update timer osal_start_timerEx( timeAppTaskId, CLOCK_UPDATE_EVT, DEFAULT_CLOCK_UPDATE_PERIOD ); // Setup a delayed profile startup osal_set_event( timeAppTaskId, START_DEVICE_EVT ); }
/********************************************************************* * @fn peripheralStateNotificationCB * * @brief Notification from the profile of a state change. * * @param newState - new state * * @return none */ static void peripheralStateNotificationCB( gaprole_States_t newState ) { uint16 connHandle = INVALID_CONNHANDLE; uint8 valFalse = FALSE; if ( gapProfileState != newState ) { switch( newState ) { case GAPROLE_STARTED: { // Set the system ID from the bd addr uint8 systemId[DEVINFO_SYSTEM_ID_LEN]; GAPRole_GetParameter(GAPROLE_BD_ADDR, systemId); // shift three bytes up systemId[7] = systemId[5]; systemId[6] = systemId[4]; systemId[5] = systemId[3]; // set middle bytes to zero systemId[4] = 0; systemId[3] = 0; DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); } break; //if the state changed to connected, initially assume that keyfob is in range case GAPROLE_ADVERTISING: { // Visual feedback that we are advertising. HalLedSet( HAL_LED_2, HAL_LED_MODE_ON ); } break; //if the state changed to connected, initially assume that keyfob is in range case GAPROLE_CONNECTED: { // set the proximity state to either path loss alert or in range depending // on the value of keyfobProxIMAlertLevel (which was set by proximity monitor) if( keyfobProxIMAlertLevel != PP_ALERT_LEVEL_NO ) { keyfobProximityState = KEYFOB_PROXSTATE_PATH_LOSS; // perform alert keyfobapp_PerformAlert(); buzzer_beep_count = 0; } else // if keyfobProxIMAlertLevel == PP_ALERT_LEVEL_NO { keyfobProximityState = KEYFOB_PROXSTATE_CONNECTED_IN_RANGE; keyfobapp_StopAlert(); } GAPRole_GetParameter( GAPROLE_CONNHANDLE, &connHandle ); #if defined ( PLUS_BROADCASTER ) osal_start_timerEx( keyfobapp_TaskID, KFD_ADV_IN_CONNECTION_EVT, ADV_IN_CONN_WAIT ); #endif // Turn off LED that shows we're advertising HalLedSet( HAL_LED_2, HAL_LED_MODE_OFF ); } break; case GAPROLE_WAITING: { // then the link was terminated intentionally by the slave or master, // or advertising timed out keyfobProximityState = KEYFOB_PROXSTATE_INITIALIZED; // Turn off immediate alert ProxReporter_SetParameter(PP_IM_ALERT_LEVEL, sizeof(valFalse), &valFalse); keyfobProxIMAlertLevel = PP_ALERT_LEVEL_NO; // Change attribute value of Accelerometer Enable to FALSE Accel_SetParameter(ACCEL_ENABLER, sizeof(valFalse), &valFalse); // Stop the acceleromter accelEnablerChangeCB(); // SetParameter does not trigger the callback // Turn off LED that shows we're advertising HalLedSet( HAL_LED_2, HAL_LED_MODE_OFF ); // Stop alert if it was active if( keyfobAlertState != ALERT_STATE_OFF ) { keyfobapp_StopAlert(); } } break; case GAPROLE_WAITING_AFTER_TIMEOUT: { // the link was dropped due to supervision timeout keyfobProximityState = KEYFOB_PROXSTATE_LINK_LOSS; // Turn off immediate alert ProxReporter_SetParameter(PP_IM_ALERT_LEVEL, sizeof(valFalse), &valFalse); keyfobProxIMAlertLevel = PP_ALERT_LEVEL_NO; // Change attribute value of Accelerometer Enable to FALSE Accel_SetParameter(ACCEL_ENABLER, sizeof(valFalse), &valFalse); // Stop the acceleromter accelEnablerChangeCB(); // SetParameter does not trigger the callback // Perform link loss alert if enabled if( keyfobProxLLAlertLevel != PP_ALERT_LEVEL_NO ) { keyfobapp_PerformAlert(); buzzer_beep_count = 0; } } break; default: // do nothing break; } } gapProfileState = newState; }