diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 8a24b7aa4..4f2108177 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -93,33 +93,37 @@ static void lsEnter() screen->setOn(false); ledBlink.set(false); - if (!doPreflightSleep()) { - LOG_DEBUG("State change to LS aborted"); - sleepStart = -1; - powerFSM.trigger(EVENT_WAKE_TIMER); - return; - } - - sleepStart = millis(); + sleepStart = -1; sleepTime = 0; powerMon->setState(meshtastic_PowerMon_State_CPU_LightSleep); - -#ifdef ARCH_ESP32 - doLightSleep(SLEEP_TIME * 1000LL); -#endif } static void lsIdle() { if (!doPreflightSleep()) { +#ifdef DYNAMIC_LIGHT_SLEEP powerFSM.trigger(EVENT_WAKE_TIMER); +#endif return; } + if (sleepStart == -1) { + sleepStart = millis(); + } + sleepTime = millis() - sleepStart; #ifdef ARCH_ESP32 + uint32_t sleepLeft; + + sleepLeft = config.power.ls_secs * 1000LL - sleepTime; + if (sleepLeft > SLEEP_TIME * 1000LL) { + sleepLeft = SLEEP_TIME * 1000LL; + } + + doLightSleep(sleepLeft); + esp_sleep_source_t cause = esp_sleep_get_wakeup_cause(); switch (cause) { @@ -128,11 +132,6 @@ static void lsIdle() powerFSM.trigger(EVENT_INPUT); return; - case ESP_SLEEP_WAKEUP_EXT0: - LOG_DEBUG("Wake cause ESP_SLEEP_WAKEUP_EXT0"); - powerFSM.trigger(EVENT_RADIO_INTERRUPT); - return; - case ESP_SLEEP_WAKEUP_EXT1: LOG_DEBUG("Wake cause ESP_SLEEP_WAKEUP_EXT1"); powerFSM.trigger(EVENT_PRESS); @@ -143,11 +142,6 @@ static void lsIdle() powerFSM.trigger(EVENT_WAKE_TIMER); return; - case ESP_SLEEP_WAKEUP_UNDEFINED: - LOG_DEBUG("Wake cause ESP_SLEEP_WAKEUP_UNDEFINED"); - powerFSM.trigger(EVENT_WAKE_TIMER); - return; - default: if (sleepTime > config.power.ls_secs * 1000LL) { powerFSM.trigger(EVENT_WAKE_TIMER); @@ -155,15 +149,6 @@ static void lsIdle() } break; } - - uint32_t sleepLeft; - - sleepLeft = config.power.ls_secs * 1000LL - sleepTime; - if (sleepLeft > SLEEP_TIME * 1000LL) { - sleepLeft = SLEEP_TIME * 1000LL; - } - - doLightSleep(sleepLeft); #endif } @@ -183,21 +168,9 @@ static void lsExit() } } -static void nbEnter() -{ - LOG_DEBUG("State: NB"); - if (screen) - screen->setOn(false); -#ifdef ARCH_ESP32 - // Only ESP32 should turn off bluetooth - setBluetoothEnable(false); -#endif -} - static void darkEnter() { // LOG_DEBUG("State: DARK"); i - setBluetoothEnable(true); if (screen) screen->setOn(false); } @@ -205,18 +178,11 @@ static void darkEnter() static void serialEnter() { LOG_DEBUG("State: SERIAL"); - setBluetoothEnable(false); if (screen) { screen->setOn(true); } } -static void serialExit() -{ - // Turn bluetooth back on when we leave serial stream API - setBluetoothEnable(true); -} - static void powerEnter() { LOG_DEBUG("State: POWER"); @@ -228,7 +194,6 @@ static void powerEnter() } else { if (screen) screen->setOn(true); - setBluetoothEnable(true); // within enter() the function getState() returns the state we came from } } @@ -246,7 +211,6 @@ static void powerExit() { if (screen) screen->setOn(true); - setBluetoothEnable(true); } static void onEnter() @@ -254,7 +218,6 @@ static void onEnter() LOG_DEBUG("State: ON"); if (screen) screen->setOn(true); - setBluetoothEnable(true); } static void onIdle() @@ -274,9 +237,8 @@ State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN"); State stateSDS(sdsEnter, NULL, NULL, "SDS"); State stateLowBattSDS(lowBattSDSEnter, NULL, NULL, "SDS"); State stateLS(lsEnter, lsIdle, lsExit, "LS"); -State stateNB(nbEnter, NULL, NULL, "NB"); State stateDARK(darkEnter, NULL, NULL, "DARK"); -State stateSERIAL(serialEnter, NULL, serialExit, "SERIAL"); +State stateSERIAL(serialEnter, NULL, NULL, "SERIAL"); State stateBOOT(bootEnter, NULL, NULL, "BOOT"); State stateON(onEnter, onIdle, NULL, "ON"); State statePOWER(powerEnter, powerIdle, powerExit, "POWER"); @@ -286,20 +248,14 @@ void PowerFSM_setup() { bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0); bool hasPower = isPowered(); - State *stateIDLE; -#ifdef ARCH_ESP32 - stateIDLE = isRouter ? &stateNB : &stateDARK; -#else - stateIDLE = &stateDARK; -#endif - LOG_INFO("PowerFSM init, USB power=%d, is_power_saving=%d", hasPower ? 1 : 0, config.power.is_power_saving ? 1 : 0); + LOG_INFO("PowerFSM init, USB power=%d, is_power_saving=%d, wake_time_ms=%d", hasPower ? 1 : 0, + config.power.is_power_saving ? 1 : 0, WAKE_TIME_MS); powerFSM.add_timed_transition(&stateBOOT, hasPower ? &statePOWER : &stateON, 3 * 1000, NULL, "boot timeout"); // Handle press events - note: we ignore button presses when in API mode powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press"); - powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL, "Press"); powerFSM.add_transition(&stateDARK, isPowered() ? &statePOWER : &stateON, EVENT_PRESS, NULL, "Press"); powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_PRESS, NULL, "Press"); powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, NULL, "Press"); // reenter On to restart our timers @@ -309,7 +265,6 @@ void PowerFSM_setup() // Handle critically low power battery by forcing deep sleep powerFSM.add_transition(&stateBOOT, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); powerFSM.add_transition(&stateLS, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); - powerFSM.add_transition(&stateNB, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); powerFSM.add_transition(&stateDARK, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); powerFSM.add_transition(&stateON, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); powerFSM.add_transition(&stateSERIAL, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); @@ -317,14 +272,12 @@ void PowerFSM_setup() // Handle being told to power off powerFSM.add_transition(&stateBOOT, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown"); powerFSM.add_transition(&stateLS, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown"); - powerFSM.add_transition(&stateNB, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown"); powerFSM.add_transition(&stateDARK, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown"); powerFSM.add_transition(&stateON, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown"); powerFSM.add_transition(&stateSERIAL, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown"); // Inputbroker powerFSM.add_transition(&stateLS, &stateON, EVENT_INPUT, NULL, "Input Device"); - powerFSM.add_transition(&stateNB, &stateON, EVENT_INPUT, NULL, "Input Device"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_INPUT, NULL, "Input Device"); powerFSM.add_transition(&stateON, &stateON, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer @@ -339,56 +292,48 @@ void PowerFSM_setup() if (!isRouter) { powerFSM.add_transition(&stateLS, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone"); powerFSM.add_transition(&stateLS, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone"); - powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WEB_REQUEST, NULL, "Web request"); // Removed 2.7: we don't show the nodes individually for every node on the screen anymore // powerFSM.add_transition(&stateLS, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update"); - // powerFSM.add_transition(&stateNB, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update"); // powerFSM.add_transition(&stateDARK, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update"); // powerFSM.add_transition(&stateON, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update"); // Show the received text message powerFSM.add_transition(&stateLS, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text"); - powerFSM.add_transition(&stateNB, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text"); powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text"); // restarts the sleep timer - - } else { - // if we are a router we don't turn the screen on for these things - powerFSM.add_timed_transition( - &stateDARK, &stateNB, - Default::getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL, - "Bluetooth timeout"); } // If we are not in statePOWER but get a serial connection, suppress sleep (and keep the screen on) while connected powerFSM.add_transition(&stateLS, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "Serial API"); - powerFSM.add_transition(&stateNB, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "Serial API"); powerFSM.add_transition(&stateDARK, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "Serial API"); powerFSM.add_transition(&stateON, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "Serial API"); powerFSM.add_transition(&statePOWER, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "Serial API"); // If we get power connected, go to the power connect state powerFSM.add_transition(&stateLS, &statePOWER, EVENT_POWER_CONNECTED, NULL, "Power connect"); - powerFSM.add_transition(&stateNB, &statePOWER, EVENT_POWER_CONNECTED, NULL, "Power connect"); powerFSM.add_transition(&stateDARK, &statePOWER, EVENT_POWER_CONNECTED, NULL, "Power connect"); powerFSM.add_transition(&stateON, &statePOWER, EVENT_POWER_CONNECTED, NULL, "Power connect"); powerFSM.add_transition(&statePOWER, &stateON, EVENT_POWER_DISCONNECTED, NULL, "Power disconnected"); powerFSM.add_transition(&stateLS, &stateON, EVENT_POWER_DISCONNECTED, NULL, "Power disconnected"); - powerFSM.add_transition(&stateNB, &stateON, EVENT_POWER_DISCONNECTED, NULL, "Power disconnected"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_POWER_DISCONNECTED, NULL, "Power disconnected"); // the only way to leave state serial is for the client to disconnect (or we timeout and force disconnect them) // when we leave, go to ON (which might not be the correct state if we have power connected, we will fix that in onEnter) powerFSM.add_transition(&stateSERIAL, &stateON, EVENT_SERIAL_DISCONNECTED, NULL, "Serial disconnect"); - powerFSM.add_transition(&stateLS, stateIDLE, EVENT_WAKE_TIMER, NULL, "Wake timer"); - powerFSM.add_transition(&stateLS, stateIDLE, EVENT_RADIO_INTERRUPT, NULL, "Radio interrupt"); + powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer"); + powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer"); - powerFSM.add_transition(stateIDLE, stateIDLE, EVENT_WAKE_TIMER, NULL, "Wake timer"); - powerFSM.add_transition(stateIDLE, stateIDLE, EVENT_WEB_REQUEST, NULL, "Web request"); - powerFSM.add_transition(stateIDLE, stateIDLE, EVENT_RADIO_INTERRUPT, NULL, "Radio interrupt"); + powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WEB_REQUEST, NULL, "Web request"); + powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_WEB_REQUEST, NULL, "Web request"); + +#ifdef DYNAMIC_LIGHT_SLEEP + // it's better to exit dynamic light sleep when packet is received to ensure routing is properly handled + powerFSM.add_transition(&stateLS, &stateDARK, EVENT_RADIO_INTERRUPT, NULL, "Radio interrupt"); + powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_RADIO_INTERRUPT, NULL, "Radio interrupt"); +#endif #ifdef USE_EINK // Allow E-Ink devices to suppress the screensaver, if screen timeout set to 0 @@ -403,10 +348,10 @@ void PowerFSM_setup() NULL, "Screen-on timeout"); } -// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally) +// We never enter light-sleep on NRF52 (because the CPU uses so little power normally) #ifdef ARCH_ESP32 if (config.power.is_power_saving) { - powerFSM.add_timed_transition(stateIDLE, &stateLS, WAKE_TIME_MS, NULL, "Min wake timeout"); + powerFSM.add_timed_transition(&stateDARK, &stateLS, WAKE_TIME_MS, NULL, "Min wake timeout"); } #endif diff --git a/src/PowerFSM.h b/src/PowerFSM.h index 887c4dccb..6eea31a9d 100644 --- a/src/PowerFSM.h +++ b/src/PowerFSM.h @@ -24,11 +24,12 @@ #define EVENT_RADIO_INTERRUPT 18 #define EVENT_WEB_REQUEST 19 -#if defined(ARCH_ESP32) && !defined(WAKE_TIME_MS) +#ifdef ARCH_ESP32 #ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE +#define DYNAMIC_LIGHT_SLEEP #define WAKE_TIME_MS 500 #else -#define WAKE_TIME_MS Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs) +#define WAKE_TIME_MS (Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs)) #endif #endif diff --git a/src/main.cpp b/src/main.cpp index 76f08cefb..ccf8e788f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1369,12 +1369,16 @@ void setup() #endif #ifndef ARCH_PORTDUINO - - // Initialize Wifi #if HAS_WIFI + // Initialize Wifi initWifi(); #endif +#if HAS_BLUETOOTH + // Enable Bluetooth + setBluetoothEnable(true); +#endif + #if HAS_ETHERNET // Initialize Ethernet initEthernet(); diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 15cf2424b..c50aefe8e 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -159,7 +159,6 @@ void Router::abortSendAndNak(meshtastic_Routing_Error err, meshtastic_MeshPacket void Router::setReceivedMessage() { // LOG_DEBUG("set interval to ASAP"); - powerFSM.trigger(EVENT_WAKE_TIMER); setInterval(0); // Run ASAP, so we can figure out our correct sleep time runASAP = true; }