PRSEV_HANDLER_DEF(E_STATE_APP_SLEEP, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { if (eEvent == E_EVENT_NEW_STATE) { // Sleep は必ず E_EVENT_NEW_STATE 内など1回のみ呼び出される場所で呼び出す。 V_PRINTF(LB"! Sleeping..."); V_FLUSH(); pEv->bKeepStateOnSetAll = FALSE; // スリープ復帰の状態を維持 // Mininode の場合、特別な処理は無いのだが、ポーズ処理を行う ToCoNet_Nwk_bPause(sAppData.pContextNwk); // センサー用の電源制御回路を Hi に戻す vPortSetSns(FALSE); #ifdef LITE2525A vPortSetLo(LED); #else vPortSetHi(LED); #endif // 周期スリープに入る if(sAppData.sFlash.sData.i16param == NORMAL || sAppData.sFlash.sData.i16param == NEKOTTER ){ vSleep(sAppData.sFlash.sData.u32Slp, sAppData.u16frame_count == 1 ? FALSE : TRUE, FALSE); }else{ // 割り込みの設定 vAHI_DioSetDirection(PORT_INPUT_MASK_ADXL345, 0); // set as input (void)u32AHI_DioInterruptStatus(); // clear interrupt register vAHI_DioWakeEnable(PORT_INPUT_MASK_ADXL345, 0); // also use as DIO WAKE SOURCE vAHI_DioWakeEdge(PORT_INPUT_MASK_ADXL345, 0); // 割り込みエッジ(立上がりに設定) vSleep(0, FALSE, FALSE); } } }
/* スリープをする状態 */ PRSEV_HANDLER_DEF(E_STATE_APP_SLEEP, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { if (eEvent == E_EVENT_NEW_STATE) { // Sleep は必ず E_EVENT_NEW_STATE 内など1回のみ呼び出される場所で呼び出す。 V_PRINTF(LB"Sleeping..."); V_FLUSH(); // Mininode の場合、特別な処理は無いのだが、ポーズ処理を行う ToCoNet_Nwk_bPause(sAppData.pContextNwk); // print message. vAHI_UartDisable(UART_PORT); // UART を解除してから(このコードは入っていなくても動作は同じ) // set UART Rx port as interrupt source vAHI_DioSetDirection(PORT_INPUT_MASK, 0); // set as input (void)u32AHI_DioInterruptStatus(); // clear interrupt register vAHI_DioWakeEnable(PORT_INPUT_MASK, 0); // also use as DIO WAKE SOURCE // i16paramに関わらず状態の変化で起床 if(sAppData.bDI1_Now_Opened) { vAHI_DioWakeEdge(0, PORT_INPUT_MASK); // 割り込みエッジ(立下りに設定) } else { vAHI_DioWakeEdge(PORT_INPUT_MASK, 0); // 割り込みエッジ(立上がりに設定) } // wake up using wakeup timer as well. ToCoNet_vSleep(E_AHI_WAKE_TIMER_0, sAppData.sFlash.sData.u32Slp, FALSE, FALSE ); // PERIODIC RAM OFF SLEEP USING WK0 } }
PRSEV_HANDLER_DEF(E_STATE_APP_SLEEP, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { if (eEvent == E_EVENT_NEW_STATE) { // Sleep は必ず E_EVENT_NEW_STATE 内など1回のみ呼び出される場所で呼び出す。 V_PRINTF(LB"! Sleeping..."); V_FLUSH(); pEv->bKeepStateOnSetAll = FALSE; // スリープ復帰の状態を維持 // Mininode の場合、特別な処理は無いのだが、ポーズ処理を行う ToCoNet_Nwk_bPause(sAppData.pContextNwk); // センサー用の電源制御回路を Hi に戻す vPortSetSns(FALSE); // 周期スリープに入る // - 初回は5秒あけて、次回以降はスリープ復帰を基点に5秒 vSleep(sAppData.sFlash.sData.u32Slp, sAppData.u16frame_count == 1 ? FALSE : TRUE, FALSE); } }
PRSEV_HANDLER_DEF(E_STATE_APP_SLEEP, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { if (eEvent == E_EVENT_NEW_STATE) { // Sleep は必ず E_EVENT_NEW_STATE 内など1回のみ呼び出される場所で呼び出す。 V_PRINTF(LB"! Sleeping..."); V_FLUSH(); // Mininode の場合、特別な処理は無いのだが、ポーズ処理を行う ToCoNet_Nwk_bPause(sAppData.pContextNwk); // センサー用の電源制御回路を Hi に戻す vPortSetSns(FALSE); #ifdef LITE2525A vPortSetLo(LED); #else vPortSetHi(LED); #endif vAHI_DioWakeEnable(0, PORT_INPUT_MASK); // DISABLE DIO WAKE SOURCE ToCoNet_vSleep( E_AHI_WAKE_TIMER_0, sAppData.sFlash.sData.u32Slp, FALSE, FALSE); } }
/* * 送信後のチャタリング対策を行う状態 */ PRSEV_HANDLER_DEF(E_STATE_APP_CHAT_SLEEP, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { /* 遷移してきたとき一旦眠る */ if(eEvent == E_EVENT_NEW_STATE){ V_PRINTF(LB"Safe Chattering..."); V_FLUSH(); // Mininode の場合、特別な処理は無いのだが、ポーズ処理を行う ToCoNet_Nwk_bPause(sAppData.pContextNwk); // 割り込み禁止でスリープ pEv->bKeepStateOnSetAll = TRUE; // この状態から起床 vAHI_DioWakeEnable(0, PORT_INPUT_MASK); // DISABLE DIO WAKE SOURCE ToCoNet_vSleep(E_AHI_WAKE_TIMER_1, 200UL, FALSE, FALSE); /* 起床後すぐこの状態になったときずっと眠る状態へ */ }else if(eEvent == E_EVENT_START_UP){ pEv->bKeepStateOnSetAll = FALSE; ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP); // スリープ状態へ遷移 } }
/** * スリープへの遷移 * * @param E_STATE_APP_SLEEP * @param pEv * @param eEvent * @param u32evarg */ PRSEV_HANDLER_DEF(E_STATE_APP_SLEEP, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { if (eEvent == E_EVENT_NEW_STATE) { pEv->bKeepStateOnSetAll = FALSE; u8RetryCount = 0xff; // センサー用の電源制御回路を Hi に戻す vPortSetSns(FALSE); // RTS0 を通信禁止にする vPortSetHi(PORT_RTS0); // Sleep は必ず E_EVENT_NEW_STATE 内など1回のみ呼び出される場所で呼び出す。 V_PRINTF(LB"Sleeping..."); V_FLUSH(); // Mininode の場合、特別な処理は無いのだが、ポーズ処理を行う ToCoNet_Nwk_bPause(sAppData.pContextNwk); // スリープ状態に遷移 vSleep(0, FALSE, FALSE); } }
static void vProcessEvCore(tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { switch (pEv->eState) { /* * 起動時の状態 * ToCoNetの接続を行う。 * - スリープ復帰時は直前のアドレスに対して復帰をかける。失敗した場合は再探索を行う。 */ case E_STATE_IDLE: // start up message V_PRINTF(LB "*** ToCoSamp IO Monitor %d.%02d-%d %s ***", VERSION_MAIN, VERSION_SUB, VERSION_VAR, sAppData.bWakeupByButton ? "BTN" : "OTR"); V_PRINTF(LB "* App ID:%08x Long Addr:%08x Short Addr %04x", sToCoNet_AppContext.u32AppId, ToCoNet_u32GetSerial(), sToCoNet_AppContext.u16ShortAddress); SERIAL_vFlush(UART_PORT); if (eEvent == E_EVENT_START_UP) { if (IS_APPCONF_OPT_SECURE()) { bool_t bRes = bRegAesKey(sAppData.sFlash.sData.u32EncKey); V_PRINTF(LB "*** Register AES key (%d) ***", bRes); } #ifdef USE_LCD vLcdInit(); // register sLcd // 最下行を表示する V_PRINTF_LCD_BTM("*** ToCoSamp IO Monitor %d.%02d-%d ***", VERSION_MAIN, VERSION_SUB, VERSION_VAR); vLcdRefresh(); #endif } if (eEvent == E_EVENT_START_UP && (u32evarg & EVARG_START_UP_WAKEUP_RAMHOLD_MASK)) { V_PRINTF(LB "* Warm starting woke by %s.", sAppData.bWakeupByButton ? "DIO" : "WakeTimer"); /* * 接続復帰(スリープ後) */ sAppData.eLedState = E_LED_WAIT; ToCoNet_Nwk_bResume(sAppData.pContextNwk); // ネットワークの復元 ToCoNet_Event_SetState(pEv, E_STATE_APP_WAIT_NW_START); } else if (eEvent == E_EVENT_START_UP) { V_PRINTF(LB "* start end device[%d]", u32TickCount_ms & 0xFFFF); /* * ネットワークの接続 */ sAppData.sNwkLayerTreeConfig.u8Role = TOCONET_NWK_ROLE_ENDDEVICE; // EndDevice として構成する sAppData.sNwkLayerTreeConfig.u8ScanDur_10ms = 4; // 探索時間(中継機の数が数個程度なら 40ms 程度で十分) sAppData.pContextNwk = ToCoNet_NwkLyTr_psConfig(&sAppData.sNwkLayerTreeConfig); // 設定 if (sAppData.pContextNwk) { ToCoNet_Nwk_bInit(sAppData.pContextNwk); // ネットワーク初期化 ToCoNet_Nwk_bStart(sAppData.pContextNwk); // ネットワーク開始 } sAppData.eLedState = E_LED_WAIT; ToCoNet_Event_SetState(pEv, E_STATE_APP_WAIT_NW_START); break; } break; /* * ネットワークの開始待ち */ case E_STATE_APP_WAIT_NW_START: if (eEvent == E_EVENT_TOCONET_NWK_START) { ToCoNet_Event_SetState(pEv, E_STATE_RUNNING); } if (ToCoNet_Event_u32TickFrNewState(pEv) > 500) { ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP); } break; /* * 実行時の状態 * - ネットワーク開始後、メッセージプール要求を行う * - ネットワークがエラーになったり、タイムアウトが発生した場合はエラー状態とし、 * 再びスリープする */ case E_STATE_RUNNING: if (eEvent == E_EVENT_NEW_STATE) { // ネットワーク開始 V_PRINTF(LB"[NWK STARTED and REQUEST IO STATE:%d]", u32TickCount_ms & 0xFFFF); static uint8 u8Ct; #ifdef MSGPL_SLOT_TEST // メッセージプールの複数スロットのテストを行う // 起動ごとにスロット番号を変更して取得する u8Ct++; #else u8Ct = 0; #endif // メッセージプールの要求 if (ToCoNet_MsgPl_bRequest(u8Ct % TOCONET_MOD_MESSAGE_POOL_MAX_ENTITY)) { ToCoNet_Event_SetState(pEv, E_STATE_APP_IO_WAIT_RX); } else { ToCoNet_Event_SetState(pEv, E_STATE_APP_IO_RECV_ERROR); } } else if (eEvent == E_EVENT_TOCONET_NWK_DISCONNECT) { ToCoNet_Event_SetState(pEv, E_STATE_APP_IO_RECV_ERROR); } else { if (ToCoNet_Event_u32TickFrNewState(pEv) > ENDD_TIMEOUT_CONNECT_ms) { ToCoNet_Event_SetState(pEv, E_STATE_APP_IO_RECV_ERROR); } } break; /* * メッセージプールからの伝達待ち。 * - メッセージプールは cbToCoNet_vNwkEvent() に通知され、 * その関数中でE_EVENT_APP_GET_IC_INFOイベントを発行する。 */ case E_STATE_APP_IO_WAIT_RX: if (eEvent == E_EVENT_NEW_STATE) { V_PRINTF(LB"[E_STATE_APP_IO_WAIT_RX:%d]", u32TickCount_ms & 0xFFFF); } if (eEvent == E_EVENT_APP_GET_IC_INFO) { // メッセージが届いた if (u32evarg) { V_PRINTF(LB"[E_STATE_APP_IO_WAIT_RX:GOTDATA:%d]", u32TickCount_ms & 0xFFFF); ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP); } else { ToCoNet_Event_SetState(pEv, E_STATE_APP_IO_RECV_ERROR); } } else { // タイムアウト if (ToCoNet_Event_u32TickFrNewState(pEv) > ENDD_TIMEOUT_WAIT_MSG_ms) { V_PRINTF(LB"[E_STATE_APP_IO_WAIT_RX:TIMEOUT:%d]", u32TickCount_ms & 0xFFFF); ToCoNet_Event_SetState(pEv, E_STATE_APP_IO_RECV_ERROR); } } break; /* * 送信完了の処理 * - スリープ実行 */ case E_STATE_APP_IO_RECV_ERROR: case E_STATE_APP_SLEEP: if (eEvent == E_EVENT_NEW_STATE) { if (pEv->eState == E_STATE_APP_SLEEP) { V_PRINTF(LB"[E_STATE_APP_SLEEP_LED:%d]", u32TickCount_ms & 0xFFFF); sAppData.eLedState = E_LED_RESULT; } else { V_PRINTF(LB"[E_STATE_APP_IO_RECV_ERROR:%d]", u32TickCount_ms & 0xFFFF); sAppData.eLedState = E_LED_ERROR; } vPortSetHi(PORT_KIT_LED1); vPortSetHi(PORT_KIT_LED2); #ifdef NO_SLEEP ToCoNet_Event_SetState(pEv, E_STATE_APP_PREUDO_SLEEP); #else ToCoNet_Nwk_bPause(sAppData.pContextNwk); SERIAL_vFlush(UART_PORT); vSleep(0, FALSE, FALSE); #endif } break; case E_STATE_APP_PREUDO_SLEEP: // 指定時間スリープ相当の時間待ちを行う if (ToCoNet_Event_u32TickFrNewState(pEv) > ENDD_SLEEP_PERIOD_s * 1000UL) { ToCoNet_Event_SetState(pEv, E_STATE_RUNNING); } break; default: break; } }