/**************************************************************************** * * NAME: AppColdStart * * DESCRIPTION: * * RETURNS: * ****************************************************************************/ void cbAppColdStart(bool_t bAfterAhiInit) { if (!bAfterAhiInit) { // before AHI initialization (very first of code) // Module Registration ToCoNet_REG_MOD_ALL(); } else { // clear application context memset(&sAppData, 0x00, sizeof(sAppData)); // SPRINTF SPRINTF_vInit128(); // Configuration // フラッシュメモリからの読み出し // フラッシュからの読み込みが失敗した場合、ID=15 で設定する sAppData.bFlashLoaded = Config_bLoad(&sAppData.sFlash); // ToCoNet configuration sToCoNet_AppContext.u32AppId = sAppData.sFlash.sData.u32appid; sToCoNet_AppContext.u8Channel = sAppData.sFlash.sData.u8ch; sToCoNet_AppContext.u32ChMask = sAppData.sFlash.sData.u32chmask; sToCoNet_AppContext.u8TxMacRetry = 1; sToCoNet_AppContext.bRxOnIdle = TRUE; // event machine ToCoNet_Event_Register_State_Machine(vProcessEvCore); // main state machine // Other Hardware vSerialInit(); ToCoNet_vDebugInit(&sSerStream); ToCoNet_vDebugLevel(TOCONET_DEBUG_LEVEL); vInitHardware(FALSE); Interactive_vInit(); // START UP MESSAGE vfPrintf(&sSerStream, "\r\n*** ToCoTemp Parent %d.%02d-%d ***", VERSION_MAIN, VERSION_SUB, VERSION_VAR); vfPrintf(&sSerStream, LB "* App ID:%08x Long Addr:%08x Short Addr %04x", sToCoNet_AppContext.u32AppId, ToCoNet_u32GetSerial(), sToCoNet_AppContext.u16ShortAddress); } }
/**************************************************************************** * * NAME: AppColdStart * * DESCRIPTION: * * RETURNS: * ****************************************************************************/ PUBLIC void cbAppColdStart(bool_t bAfterAhiInit) { if (!bAfterAhiInit) { // before AHI initialization (very first of code) // Module Registration ToCoNet_REG_MOD_ALL(); } else { // clear application context memset(&sAppData, 0x00, sizeof(sAppData)); memset(&sSerCmd, 0x00, sizeof(sSerCmd)); // SPRINTF SPRINTF_vInit128(); // configure network] sToCoNet_AppContext.u32AppId = APP_ID; sToCoNet_AppContext.u8Channel = CHANNEL; sToCoNet_AppContext.u32ChMask = CHMASK; sToCoNet_AppContext.u8TxMacRetry = 1; sToCoNet_AppContext.bRxOnIdle = TRUE; // version info sAppData.u32ToCoNetVersion = ToCoNet_u32GetVersion(); // event machine ToCoNet_Event_Register_State_Machine(vProcessEvCore); // main state machine // Other Hardware vSerialInit(); ToCoNet_vDebugInit(&sSerStream); ToCoNet_vDebugLevel(TOCONET_DEBUG_LEVEL); vInitHardware(FALSE); // START UP MESSAGE vfPrintf(&sSerStream, "\r\n\r\n*** " APP_NAME " %d.%02d-%d ***", VERSION_MAIN, VERSION_SUB, VERSION_VAR); vfPrintf(&sSerStream, LB "* App ID:%08x Long Addr:%08x Short Addr %04x", sToCoNet_AppContext.u32AppId, ToCoNet_u32GetSerial(), sToCoNet_AppContext.u16ShortAddress); } }
/**************************************************************************** * * NAME: cbvMcRxHandler * * DESCRIPTION: * * RETURNS: * ****************************************************************************/ PUBLIC void cbToCoNet_vRxEvent(tsRxDataApp *pRx) { int i; // print coming payload V_PRINTF( "\n\r[PKT Ad:%04x,Ln:%03d,Seq:%03d,Lq:%03d,Tms:%05d \"", pRx->u32SrcAddr, pRx->u8Len, // Actual payload byte: the network layer uses additional 4 bytes. pRx->u8Seq, pRx->u8Lqi, pRx->u32Tick & 0xFFFF); for (i = 0; i < pRx->u8Len; i++) { if (i < 32) { V_PUTCHAR((pRx->auData[i] >= 0x20 && pRx->auData[i] <= 0x7f) ? pRx->auData[i] : '.'); } else { V_PRINTF( ".."); break; } } V_PRINTF( "\"]"); // 直接受信したパケットを上位へ転送する if (pRx->auData[0] == 'T') { tsTxDataApp sTx; memset(&sTx, 0, sizeof(sTx)); sTx.u32DstAddr = TOCONET_NWK_ADDR_PARENT; sTx.u32SrcAddr = ToCoNet_u32GetSerial(); // Transmit using Long address sTx.u8Cmd = 0; // data packet. sTx.u8Seq = pRx->u8Seq; sTx.u8CbId = pRx->u8Seq; sTx.u16DelayMax = 300; // 送信開始の遅延を大きめに設定する memcpy(sTx.auData, pRx->auData, pRx->u8Len); sTx.auData[0] = 'R'; sTx.u8Len = pRx->u8Len; #ifdef USE_AES sTx.bSecurePacket = TRUE; #endif SPRINTF_vRewind(); vfPrintf(SPRINTF_Stream, ":%03d", pRx->u8Lqi); memcpy(sTx.auData + sTx.u8Len, SPRINTF_pu8GetBuff(), SPRINTF_u16Length()); sTx.u8Len += SPRINTF_u16Length(); ToCoNet_Nwk_bTx(sAppData.pContextNwk, &sTx); } }
/** * 設定処理用の状態マシン(未使用) */ static void vProcessEvCoreConfig(tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { switch (pEv->eState) { case E_STATE_IDLE: if (eEvent == E_EVENT_START_UP) { Interactive_vSetMode(TRUE, 0); vSerInitMessage(); vfPrintf(&sSerStream, LB LB "*** Entering Config Mode ***"); ToCoNet_Event_SetState(pEv, E_STATE_RUNNING); } break; case E_STATE_RUNNING: break; default: break; } }
PRIVATE void vProcessEvCore(tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { switch (pEv->eState) { case E_STATE_IDLE: if (eEvent == E_EVENT_START_UP) { // フラッシュからの読み込みが成功すれば、その Layer を採用する sAppData.sNwkLayerTreeConfig.u8Layer = 0; if (bFlash_Read(&sAppData.sFlash, FLASH_SECTOR_NUMBER-1, 0)) { sAppData.sNwkLayerTreeConfig.u8Layer = sAppData.sFlash.sData.u8Layer; } if (sAppData.sNwkLayerTreeConfig.u8Layer == 0) { sAppData.sNwkLayerTreeConfig.u8Layer = 1; } sAppData.sNwkLayerTreeConfig.u16TxMinDelayUp_ms = 100; sAppData.sNwkLayerTreeConfig.u16TxMaxDelayUp_ms = 200; #ifdef USE_AES // 暗号化鍵の登録 ToCoNet_bRegisterAesKey((void*)au8EncKey, NULL); #endif // Router として始動 sAppData.sNwkLayerTreeConfig.u8Role = TOCONET_NWK_ROLE_ROUTER; sAppData.pContextNwk = ToCoNet_NwkLyTr_psConfig(&sAppData.sNwkLayerTreeConfig); if (sAppData.pContextNwk) { vfPrintf(&sSerStream, LB "* start router (layer %d)", sAppData.sFlash.sData.u8Layer); ToCoNet_Nwk_bInit(sAppData.pContextNwk); ToCoNet_Nwk_bStart(sAppData.pContextNwk); ToCoNet_Event_SetState(pEv, E_STATE_RUNNING); } else { // fatal error } // start with verbose mode bSerCmd_VerboseMode = TRUE; } break; case E_STATE_RUNNING: break; default: break; } }
/**************************************************************************** * * NAME: vProcessEvent * * DESCRIPTION: * The Application Main State Machine. * * RETURNS: * ****************************************************************************/ static void vProcessEvCore(tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { switch (pEv->eState) { case E_STATE_IDLE: if (eEvent == E_EVENT_START_UP) { // フラッシュからの読み込みが成功すれば、その Layer を採用する sAppData.sNwkLayerTreeConfig.u8Layer = sAppData.sFlash.sData.u8layer; if (IS_APPCONF_OPT_SECURE()) { bool_t bRes = bRegAesKey(sAppData.sFlash.sData.u32EncKey); V_PRINTF(LB "*** Register AES key (%d) ***", bRes); } // Router として始動 sAppData.sNwkLayerTreeConfig.u8Role = TOCONET_NWK_ROLE_ROUTER; sAppData.sNwkLayerTreeConfig.u16TxMaxDelayUp_ms = 100; sAppData.pContextNwk = ToCoNet_NwkLyTr_psConfig(&sAppData.sNwkLayerTreeConfig); if (sAppData.pContextNwk) { vfPrintf(&sSerStream, LB "* start router (layer %d)", sAppData.sFlash.sData.u8layer); ToCoNet_Nwk_bInit(sAppData.pContextNwk); ToCoNet_Nwk_bStart(sAppData.pContextNwk); ToCoNet_Event_SetState(pEv, E_STATE_RUNNING); } else { // fatal error } // start with verbose mode Interactive_vSetMode(TRUE, 0); } break; case E_STATE_RUNNING: break; default: break; } }
/**************************************************************************** * * NAME: u16TSL2561readResult * * DESCRIPTION: * Wrapper to read a measurement, followed by a conversion function to work * out the value in degrees Celcius. * * RETURNS: * int16: 0~10000 [1 := 5Lux], 100 means 500 Lux. * 0x8000, error * * NOTES: * the data conversion fomula is : * ReadValue / 1.2 [LUX] * ****************************************************************************/ PUBLIC uint32 u32TSL2561readResult( void ) { bool_t bOk = TRUE; uint32 u32result = 0x00; uint16 data[2]; uint8 au8data[2]; uint8 command; uint32 Lux; command = CMD | WORD | TSL2561_DATA0; bOk &= bSMBusWrite(TSL2561_ADDRESS, command, 0, NULL ); bOk &= bSMBusSequentialRead(TSL2561_ADDRESS, 2, au8data); if (bOk == FALSE) { u32result = (uint16)SENSOR_TAG_DATA_ERROR; } else { data[0] = ((au8data[1] << 8) | au8data[0]); // 読み込んだ数値を代入 command = CMD | WORD | TSL2561_DATA1; bOk &= bSMBusWrite(TSL2561_ADDRESS, command, 0, NULL ); bOk &= bSMBusSequentialRead(TSL2561_ADDRESS, 2, au8data); if (bOk == FALSE) { u32result = SENSOR_TAG_DATA_ERROR; } data[1] = ((au8data[1] << 8) | au8data[0]); // 読み込んだ数値を代入 // TSL2561FN 照度の計算 Lux = u32CalcLux(data); u32result = Lux; } #ifdef SERIAL_DEBUG vfPrintf(&sDebugStream, "\n\rTSL2561 DATA %x", *((uint16*)au8data) ); #endif return u32result; }
// the Main loop PRIVATE void vProcessSnsObj_TSL2561(void *pvObj, teEvent eEvent) { tsSnsObj *pSnsObj = (tsSnsObj *)pvObj; tsObjData_TSL2561 *pObj = (tsObjData_TSL2561 *)pSnsObj->pvData; // general process (independent from each state) switch (eEvent) { case E_EVENT_TICK_TIMER: if (pObj->u8TickCount < 100) { pObj->u8TickCount += pSnsObj->u8TickDelta; #ifdef SERIAL_DEBUG vfPrintf(&sDebugStream, "+"); #endif } break; case E_EVENT_START_UP: pObj->u8TickCount = 100; // expire immediately #ifdef SERIAL_DEBUG vfPrintf(&sDebugStream, "\n\rTSL2561 WAKEUP"); #endif break; default: break; } // state machine switch(pSnsObj->u8State) { case E_SNSOBJ_STATE_INACTIVE: // do nothing until E_ORDER_INITIALIZE event break; case E_SNSOBJ_STATE_IDLE: switch (eEvent) { case E_EVENT_NEW_STATE: break; case E_ORDER_KICK: vSnsObj_NewState(pSnsObj, E_SNSOBJ_STATE_MEASURING); #ifdef SERIAL_DEBUG vfPrintf(&sDebugStream, "\n\rTSL2561 KICKED"); #endif break; default: break; } break; case E_SNSOBJ_STATE_MEASURING: switch (eEvent) { case E_EVENT_NEW_STATE: pObj->u32Result = SENSOR_TAG_DATA_ERROR; pObj->u8TickWait = TSL2561_CONVTIME; pObj->bBusy = TRUE; #ifdef TSL2561_ALWAYS_RESET u8reset_flag = TRUE; if (!bTSL2561reset(TURE)) { vSnsObj_NewState(pSnsObj, E_SNSOBJ_STATE_COMPLETE); } #else if (!bTSL2561startRead()) { // kick I2C communication vSnsObj_NewState(pSnsObj, E_SNSOBJ_STATE_COMPLETE); } #endif pObj->u8TickCount = 0; break; default: break; } // wait until completion if (pObj->u8TickCount > pObj->u8TickWait) { #ifdef TSL2561_ALWAYS_RESET if (u8reset_flag) { u8reset_flag = 0; if (!bTSL2561startRead()) { vTSL2561_new_state(pObj, E_SNSOBJ_STATE_COMPLETE); } pObj->u8TickCount = 0; pObj->u8TickWait = TSL2561_CONVTIME; break; } #endif pObj->u32Result = u32TSL2561readResult(); // data arrival pObj->bBusy = FALSE; vSnsObj_NewState(pSnsObj, E_SNSOBJ_STATE_COMPLETE); } break; case E_SNSOBJ_STATE_COMPLETE: switch (eEvent) { case E_EVENT_NEW_STATE: #ifdef SERIAL_DEBUG vfPrintf(&sDebugStream, "\n\rTSL2561_CP: %d", pObj->i16Result); #endif break; case E_ORDER_KICK: // back to IDLE state vSnsObj_NewState(pSnsObj, E_SNSOBJ_STATE_IDLE); break; default: break; } break; default: break; } }
PUBLIC bool_t bShakereadResult( int16* ai16accel ) { static int16 ai16TmpAccel[3]={0, 0, 0}; bool_t bOk = TRUE; uint8 au8data[2]; int16 max = 0x8000; uint8 num; // FIFOのデータ数 uint8 i; int16 sum[32]; uint8 count = 0; int16 x[33]; int16 y[33]; int16 z[33]; // FIFOでたまった個数を読み込む bOk &= bSMBusWrite(ADXL345_ADDRESS, ADXL345_FIFO_STATUS, 0, NULL ); bOk &= bSMBusSequentialRead( ADXL345_ADDRESS, 1, &num ); // FIFOの中身を全部読む num = (num&0x7f); if( num == READ_FIFO ){ // 各軸の読み込み for( i=0; i<num; i++ ){ // X軸 bOk &= bGetAxis( ADXL345_IDX_X, au8data ); x[i] = (((au8data[1] << 8) | au8data[0])); } for( i=0; i<num; i++ ){ // Y軸 bOk &= bGetAxis( ADXL345_IDX_Y, au8data ); y[i] = (((au8data[1] << 8) | au8data[0])); } for( i=0; i<num; i++ ){ // Z軸 bOk &= bGetAxis( ADXL345_IDX_Z, au8data ); z[i] = (((au8data[1] << 8) | au8data[0])); } // FIFOの設定をもう一度 bOk &= bSetFIFO(); for( i=0; i<num; i++ ){ x[i] = (x[i]<<2)/10; y[i] = (y[i]<<2)/10; z[i] = (z[i]<<2)/10; if( i == 0 ){ sum[i] = ( x[i]-ai16TmpAccel[0] + y[i]-ai16TmpAccel[1] + z[i]-ai16TmpAccel[2] ); }else{ sum[i] = ( x[i]-x[i-1] + y[i]-y[i-1] + z[i]-z[i-1] ); } if( sum[i] < 0 ){ sum[i] *= -1; } max = sum[i]>max ? sum[i] : max; if( sum[i] > u16ThAccel ){ count++; } #if 0 vfPrintf(& sSerStream, "\n\r%2d:%d,%d,%d %d", i, x[i], y[i], z[i], sum[i] ); SERIAL_vFlush(E_AHI_UART_0); } vfPrintf( &sSerStream, "\n\r" ); #else } #endif ai16accel[0] = max; ai16accel[1] = z[0]; ai16accel[2] = count; ai16TmpAccel[0] = x[num-1]; ai16TmpAccel[1] = y[num-1]; ai16TmpAccel[2] = z[num-1]; }else{
/**************************************************************************** * * NAME: vHandleSerialInput * * DESCRIPTION: * * PARAMETERS: Name RW Usage * * RETURNS: * * NOTES: ****************************************************************************/ PRIVATE void vHandleSerialInput() { // handle UART command while (!SERIAL_bRxQueueEmpty(sSerPort.u8SerialPort)) { int16 i16Char; i16Char = SERIAL_i16RxChar(sSerPort.u8SerialPort); // process if (i16Char >=0 && i16Char <= 0xFF) { uint8 u8res = u8ParseSerCmd(&sSerCmd, (uint8)i16Char); if (u8res == E_SERCMD_VERBOSE) { vfPrintf(&sSerStream, "\n\rVERBOSE MODE = %s", bSerCmd_VerboseMode ? "ON" : "OFF"); continue; } if (!bSerCmd_VerboseMode) continue; switch (i16Char) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': sAppData.sFlash.sData.u8Layer = i16Char - '0'; if (bFlash_Write(&sAppData.sFlash, FLASH_SECTOR_NUMBER - 1, 0)) { V_PRINTF( LB "Flash Saved (Router Layer #%d)... RESETTING", sAppData.sFlash.sData.u8Layer); vWait(100000); vAHI_SwReset(); } else { V_PRINTF( LB "Failed to save flash..."); } break; case 'i': // info _C { tsToCoNet_NwkLyTr_Context *pc = (tsToCoNet_NwkLyTr_Context *)(sAppData.pContextNwk); V_PRINTF( LB "Info: la=%d ty=%d ro=%02x st=%02x", pc->sInfo.u8Layer, pc->sInfo.u8NwkTypeId, pc->sInfo.u8Role, pc->sInfo.u8State); V_PRINTF( LB "Parent: %08x", pc->u32AddrHigherLayer); V_PRINTF( LB "LostParent: %d", pc->u8Ct_LostParent); V_PRINTF( LB "SecRescan: %d, SecRelocate: %d", pc->u8Ct_Second_To_Rescan, pc->u8Ct_Second_To_Relocate); } break; case '>': sToCoNet_AppContext.u8Channel++; if (sToCoNet_AppContext.u8Channel > 25) sToCoNet_AppContext.u8Channel = 0; ToCoNet_vRfConfig(); V_PRINTF( LB"channel set to %d.", sToCoNet_AppContext.u8Channel); break; case '<': sToCoNet_AppContext.u8Channel--; if (sToCoNet_AppContext.u8Channel < 11) sToCoNet_AppContext.u8Channel = 25; ToCoNet_vRfConfig(); V_PRINTF( LB"channel set to %d.", sToCoNet_AppContext.u8Channel); break; case 't': SPRINTF_vRewind(); vfPrintf(SPRINTF_Stream, "TEST FROM ROUTER(#%08X)", ToCoNet_u32GetSerial()); bTransmitToParent(sAppData.pContextNwk, SPRINTF_pu8GetBuff(), SPRINTF_u16Length()); break; case 'd': case 'D': _C { static uint8 u8DgbLvl; u8DgbLvl++; if(u8DgbLvl > 10) u8DgbLvl = 0; ToCoNet_vDebugLevel(u8DgbLvl); V_PRINTF( LB"set NwkCode debug level to %d.", u8DgbLvl); } break; default: break; } } }
/**************************************************************************** * * NAME: cbToCoNet_vNwkEvent * * DESCRIPTION: * * PARAMETERS: Name RW Usage * * RETURNS: * * NOTES: ****************************************************************************/ void cbToCoNet_vNwkEvent(teEvent eEvent, uint32 u32arg) { switch(eEvent) { /* * ネットワークが開始された */ case E_EVENT_TOCONET_NWK_START: V_PRINTF(LB"[E_EVENT_TOCONET_NWK_START:%d,Ch:%d]", u32TickCount_ms & 0xFFFF, sToCoNet_AppContext.u8Channel); vDispInfo(&sSerStream, (void*)sAppData.pContextNwk); // pass this event to the event machine ToCoNet_Event_Process(E_EVENT_TOCONET_NWK_START, u32arg, vProcessEvCore); break; /* * ネットワークが切断された */ case E_EVENT_TOCONET_NWK_DISCONNECT: V_PRINTF(LB"[E_EVENT_TOCONET_NWK_DISCONNECT]"); // pass this event to the event machine ToCoNet_Event_Process(E_EVENT_TOCONET_NWK_DISCONNECT, u32arg, vProcessEvCore); break; /* * メッセージプールを受信 */ case E_EVENT_TOCONET_NWK_MESSAGE_POOL: if (u32arg) { tsToCoNet_MsgPl_Entity *pInfo = (void*)u32arg; int i; //static uint8 u8seq = 0; uint8 u8buff[TOCONET_MOD_MESSAGE_POOL_MAX_MESSAGE+1]; memcpy(u8buff, pInfo->au8Message, pInfo->u8MessageLen); // u8Message にデータ u8MessageLen にデータ長 u8buff[pInfo->u8MessageLen] = 0; // UART にメッセージ出力 if (pInfo->bGotData) { // empty なら FALSE になる V_PRINTF(LB"---MSGPOOL sl=%d ln=%d msg=", pInfo->u8Slot, pInfo->u8MessageLen ); SPRINTF_vRewind(); for (i = 0; i < pInfo->u8MessageLen; i++) { vfPrintf(SPRINTF_Stream, "%02X", u8buff[i]); } V_PRINTF("%s", SPRINTF_pu8GetBuff()); #ifdef USE_LCD V_PRINTF_LCD("%02x:%s\r\n", u8seq++, SPRINTF_pu8GetBuff()); vLcdRefresh(); #endif V_PRINTF("---"); } else { V_PRINTF(LB"---MSGPOOL sl=%d EMPTY ---", pInfo->u8Slot ); #ifdef USE_LCD V_PRINTF_LCD("%02x: EMPTY\r\n", u8seq++); vLcdRefresh(); #endif } ToCoNet_Event_Process(E_EVENT_APP_GET_IC_INFO, pInfo->bGotData, vProcessEvCore); // vProcessEvCore にイベント送信 } break; default: break; } }