2020-02-22 20:01:59 +00:00
|
|
|
|
2020-03-18 20:51:32 +00:00
|
|
|
#include "PowerFSM.h"
|
|
|
|
#include "GPS.h"
|
2020-02-22 20:01:59 +00:00
|
|
|
#include "MeshService.h"
|
|
|
|
#include "NodeDB.h"
|
|
|
|
#include "configuration.h"
|
2020-02-24 19:21:08 +00:00
|
|
|
#include "main.h"
|
2020-03-18 20:51:32 +00:00
|
|
|
#include "screen.h"
|
|
|
|
#include "sleep.h"
|
2020-04-10 19:18:48 +00:00
|
|
|
#include "target_specific.h"
|
2020-02-22 20:01:59 +00:00
|
|
|
|
|
|
|
static void sdsEnter()
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
|
|
|
|
// Don't deepsleep if we have USB power or if the user as pressed a button recently
|
|
|
|
// !isUSBPowered <- doesn't work yet because the axp192 isn't letting the battery fully charge when we are awake - FIXME
|
|
|
|
if (millis() - lastPressMs > radioConfig.preferences.mesh_sds_timeout_secs)
|
|
|
|
{
|
|
|
|
doDeepSleep(radioConfig.preferences.sds_secs);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
doDeepSleep(radioConfig.preferences.sds_secs * 1000LL);
|
|
|
|
}
|
|
|
|
|
2020-03-25 19:25:46 +00:00
|
|
|
#include "error.h"
|
|
|
|
|
2020-06-10 21:11:43 +00:00
|
|
|
static uint32_t secsSlept;
|
|
|
|
|
2020-02-22 20:01:59 +00:00
|
|
|
static void lsEnter()
|
|
|
|
{
|
2020-03-18 22:00:17 +00:00
|
|
|
DEBUG_MSG("lsEnter begin, ls_secs=%u\n", radioConfig.preferences.ls_secs);
|
2020-03-05 00:46:57 +00:00
|
|
|
screen.setOn(false);
|
2020-06-10 21:11:43 +00:00
|
|
|
secsSlept = 0; // How long have we been sleeping this time
|
2020-03-05 02:59:10 +00:00
|
|
|
|
2020-03-14 05:38:58 +00:00
|
|
|
DEBUG_MSG("lsEnter end\n");
|
2020-02-22 20:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void lsIdle()
|
|
|
|
{
|
2020-06-10 21:11:43 +00:00
|
|
|
// DEBUG_MSG("lsIdle begin ls_secs=%u\n", radioConfig.preferences.ls_secs);
|
2020-03-14 05:38:58 +00:00
|
|
|
|
2020-04-15 03:22:27 +00:00
|
|
|
#ifndef NO_ESP32
|
2020-02-23 01:40:31 +00:00
|
|
|
esp_sleep_source_t wakeCause = ESP_SLEEP_WAKEUP_UNDEFINED;
|
|
|
|
|
2020-06-10 21:11:43 +00:00
|
|
|
// Do we have more sleeping to do?
|
|
|
|
if (secsSlept < radioConfig.preferences.ls_secs) {
|
2020-02-23 01:40:31 +00:00
|
|
|
// Briefly come out of sleep long enough to blink the led once every few seconds
|
2020-06-10 21:11:43 +00:00
|
|
|
uint32_t sleepTime = 30;
|
2020-02-23 01:40:31 +00:00
|
|
|
|
2020-06-10 21:11:43 +00:00
|
|
|
// If some other service would stall sleep, don't let sleep happen yet
|
|
|
|
if (doPreflightSleep()) {
|
|
|
|
setLed(false); // Never leave led on while in light sleep
|
|
|
|
wakeCause = doLightSleep(sleepTime * 1000LL);
|
2020-02-23 01:40:31 +00:00
|
|
|
|
2020-06-10 21:11:43 +00:00
|
|
|
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER) {
|
|
|
|
// Normal case: timer expired, we should just go back to sleep ASAP
|
2020-02-23 02:02:44 +00:00
|
|
|
|
2020-06-10 21:11:43 +00:00
|
|
|
setLed(true); // briefly turn on led
|
|
|
|
wakeCause = doLightSleep(1); // leave led on for 1ms
|
2020-02-23 01:40:31 +00:00
|
|
|
|
2020-06-10 21:11:43 +00:00
|
|
|
secsSlept += sleepTime;
|
|
|
|
// DEBUG_MSG("sleeping, flash led!\n");
|
2020-06-10 21:36:11 +00:00
|
|
|
}
|
|
|
|
if (wakeCause == ESP_SLEEP_WAKEUP_UART) {
|
|
|
|
// Not currently used (because uart triggers in hw have problems)
|
|
|
|
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
|
2020-06-10 21:11:43 +00:00
|
|
|
} else {
|
|
|
|
// We woke for some other reason (button press, uart, device interrupt)
|
2020-06-10 21:36:11 +00:00
|
|
|
//uint64_t status = esp_sleep_get_ext1_wakeup_status();
|
2020-06-10 21:11:43 +00:00
|
|
|
DEBUG_MSG("wakeCause %d\n", wakeCause);
|
2020-03-14 05:38:58 +00:00
|
|
|
|
2020-04-01 04:56:35 +00:00
|
|
|
#ifdef BUTTON_PIN
|
2020-06-10 21:11:43 +00:00
|
|
|
bool pressed = !digitalRead(BUTTON_PIN);
|
2020-04-01 04:56:35 +00:00
|
|
|
#else
|
2020-06-10 21:11:43 +00:00
|
|
|
bool pressed = false;
|
2020-04-01 04:56:35 +00:00
|
|
|
#endif
|
2020-06-10 21:11:43 +00:00
|
|
|
if (pressed) // If we woke because of press, instead generate a PRESS event.
|
|
|
|
{
|
|
|
|
powerFSM.trigger(EVENT_PRESS);
|
|
|
|
} else {
|
|
|
|
// Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
|
|
|
|
powerFSM.trigger(EVENT_WAKE_TIMER);
|
|
|
|
}
|
|
|
|
}
|
2020-03-18 20:51:32 +00:00
|
|
|
}
|
2020-06-10 21:11:43 +00:00
|
|
|
} else {
|
|
|
|
// Time to stop sleeping!
|
|
|
|
setLed(false);
|
|
|
|
DEBUG_MSG("reached ls_secs, servicing loop()\n");
|
|
|
|
powerFSM.trigger(EVENT_WAKE_TIMER);
|
2020-03-03 21:31:44 +00:00
|
|
|
}
|
2020-04-15 03:22:27 +00:00
|
|
|
#endif
|
2020-02-22 20:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void lsExit()
|
|
|
|
{
|
2020-03-14 03:30:48 +00:00
|
|
|
// setGPSPower(true); // restore GPS power
|
2020-05-04 18:15:05 +00:00
|
|
|
gps->startLock();
|
2020-02-22 20:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void nbEnter()
|
|
|
|
{
|
2020-03-05 00:46:57 +00:00
|
|
|
screen.setOn(false);
|
2020-02-22 20:01:59 +00:00
|
|
|
setBluetoothEnable(false);
|
2020-02-22 22:45:58 +00:00
|
|
|
|
|
|
|
// FIXME - check if we already have packets for phone and immediately trigger EVENT_PACKETS_FOR_PHONE
|
2020-02-22 20:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void darkEnter()
|
|
|
|
{
|
2020-04-05 20:09:46 +00:00
|
|
|
setBluetoothEnable(true);
|
2020-02-22 21:14:10 +00:00
|
|
|
screen.setOn(false);
|
2020-02-22 20:01:59 +00:00
|
|
|
}
|
|
|
|
|
2020-06-08 23:35:26 +00:00
|
|
|
static void serialEnter()
|
|
|
|
{
|
|
|
|
setBluetoothEnable(false);
|
|
|
|
screen.setOn(true);
|
|
|
|
}
|
|
|
|
|
2020-02-22 20:01:59 +00:00
|
|
|
static void onEnter()
|
|
|
|
{
|
|
|
|
screen.setOn(true);
|
|
|
|
setBluetoothEnable(true);
|
|
|
|
|
2020-03-18 20:51:32 +00:00
|
|
|
static uint32_t lastPingMs;
|
2020-03-05 00:46:57 +00:00
|
|
|
|
2020-03-18 20:51:32 +00:00
|
|
|
uint32_t now = millis();
|
|
|
|
|
2020-05-22 00:21:44 +00:00
|
|
|
if (now - lastPingMs > 30 * 1000) { // if more than a minute since our last press, ask other nodes to update their state
|
|
|
|
if (displayedNodeNum)
|
|
|
|
service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node
|
2020-03-18 20:51:32 +00:00
|
|
|
lastPingMs = now;
|
|
|
|
}
|
2020-02-22 20:01:59 +00:00
|
|
|
}
|
|
|
|
|
2020-03-18 20:51:32 +00:00
|
|
|
static void wakeForPing() {}
|
|
|
|
|
2020-02-22 20:01:59 +00:00
|
|
|
static void screenPress()
|
|
|
|
{
|
|
|
|
screen.onPress();
|
|
|
|
}
|
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
static void bootEnter() {}
|
2020-03-18 22:00:17 +00:00
|
|
|
|
2020-02-22 21:14:10 +00:00
|
|
|
State stateSDS(sdsEnter, NULL, NULL, "SDS");
|
|
|
|
State stateLS(lsEnter, lsIdle, lsExit, "LS");
|
|
|
|
State stateNB(nbEnter, NULL, NULL, "NB");
|
|
|
|
State stateDARK(darkEnter, NULL, NULL, "DARK");
|
2020-06-08 23:35:26 +00:00
|
|
|
State stateSERIAL(serialEnter, NULL, NULL, "SERIAL");
|
2020-03-19 02:15:51 +00:00
|
|
|
State stateBOOT(bootEnter, NULL, NULL, "BOOT");
|
2020-03-05 00:46:57 +00:00
|
|
|
State stateON(onEnter, NULL, NULL, "ON");
|
2020-03-18 22:00:17 +00:00
|
|
|
Fsm powerFSM(&stateBOOT);
|
2020-02-22 20:01:59 +00:00
|
|
|
|
|
|
|
void PowerFSM_setup()
|
|
|
|
{
|
2020-03-19 02:15:51 +00:00
|
|
|
powerFSM.add_timed_transition(&stateBOOT, &stateON, 3 * 1000, NULL, "boot timeout");
|
2020-03-18 22:00:17 +00:00
|
|
|
|
2020-02-22 21:14:10 +00:00
|
|
|
powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WAKE_TIMER, wakeForPing, "Wake timer");
|
2020-02-22 22:45:58 +00:00
|
|
|
|
2020-03-18 20:51:32 +00:00
|
|
|
// Note we don't really use this transition, because when we wake from light sleep we _always_ transition to NB and then it
|
|
|
|
// handles things powerFSM.add_transition(&stateLS, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet");
|
2020-02-22 22:45:58 +00:00
|
|
|
|
2020-02-22 21:50:08 +00:00
|
|
|
powerFSM.add_transition(&stateNB, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet, resetting win wake");
|
2020-02-22 21:14:10 +00:00
|
|
|
|
2020-06-08 23:35:26 +00:00
|
|
|
// Handle press events - note: we ignore button presses when in API mode
|
2020-03-18 20:51:32 +00:00
|
|
|
powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press");
|
2020-02-22 21:14:10 +00:00
|
|
|
powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL, "Press");
|
|
|
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press");
|
|
|
|
powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers
|
2020-02-22 20:01:59 +00:00
|
|
|
|
2020-05-17 11:51:36 +00:00
|
|
|
// Handle critically low power battery by forcing deep sleep
|
|
|
|
powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
|
|
|
powerFSM.add_transition(&stateLS, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
|
|
|
powerFSM.add_transition(&stateNB, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
|
|
|
powerFSM.add_transition(&stateDARK, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
|
|
|
powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
2020-06-08 23:35:26 +00:00
|
|
|
powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
2020-05-17 11:51:36 +00:00
|
|
|
|
2020-02-24 18:23:07 +00:00
|
|
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
|
|
|
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
2020-02-23 02:02:44 +00:00
|
|
|
|
|
|
|
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");
|
|
|
|
|
2020-02-22 21:14:10 +00:00
|
|
|
powerFSM.add_transition(&stateLS, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
|
|
|
|
powerFSM.add_transition(&stateNB, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
|
|
|
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
|
2020-02-25 18:29:37 +00:00
|
|
|
powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text"); // restarts the sleep timer
|
2020-02-22 20:01:59 +00:00
|
|
|
|
2020-06-08 23:35:26 +00:00
|
|
|
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(&stateSERIAL, &stateNB, EVENT_SERIAL_DISCONNECTED, NULL, "serial disconnect");
|
|
|
|
|
2020-02-23 16:53:52 +00:00
|
|
|
powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
|
|
|
|
|
2020-02-22 21:14:10 +00:00
|
|
|
powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone");
|
2020-02-22 20:01:59 +00:00
|
|
|
|
2020-02-22 21:50:08 +00:00
|
|
|
powerFSM.add_timed_transition(&stateON, &stateDARK, radioConfig.preferences.screen_on_secs * 1000, NULL, "Screen-on timeout");
|
2020-02-22 20:01:59 +00:00
|
|
|
|
2020-02-22 21:50:08 +00:00
|
|
|
powerFSM.add_timed_transition(&stateDARK, &stateNB, radioConfig.preferences.phone_timeout_secs * 1000, NULL, "Phone timeout");
|
|
|
|
|
2020-04-24 18:21:10 +00:00
|
|
|
#ifndef NRF52_SERIES
|
|
|
|
// We never enter light-sleep state on NRF52 (because the CPU uses so little power normally)
|
2020-02-22 21:50:08 +00:00
|
|
|
powerFSM.add_timed_transition(&stateNB, &stateLS, radioConfig.preferences.min_wake_secs * 1000, NULL, "Min wake timeout");
|
|
|
|
|
2020-03-18 20:51:32 +00:00
|
|
|
powerFSM.add_timed_transition(&stateDARK, &stateLS, radioConfig.preferences.wait_bluetooth_secs * 1000, NULL,
|
|
|
|
"Bluetooth timeout");
|
2020-04-24 18:21:10 +00:00
|
|
|
#endif
|
2020-02-22 20:01:59 +00:00
|
|
|
|
2020-03-18 20:51:32 +00:00
|
|
|
powerFSM.add_timed_transition(&stateLS, &stateSDS, radioConfig.preferences.mesh_sds_timeout_secs * 1000, NULL,
|
|
|
|
"mesh timeout");
|
2020-03-05 02:59:10 +00:00
|
|
|
// removing for now, because some users don't even have phones
|
2020-03-18 20:51:32 +00:00
|
|
|
// powerFSM.add_timed_transition(&stateLS, &stateSDS, radioConfig.preferences.phone_sds_timeout_sec * 1000, NULL, "phone
|
|
|
|
// timeout");
|
2020-03-03 21:31:44 +00:00
|
|
|
|
2020-02-22 21:14:10 +00:00
|
|
|
powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state
|
2020-03-15 23:47:38 +00:00
|
|
|
}
|