From c7894f3bc5db7b0157d0a86efb0c9cb954204a15 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 22 Feb 2020 13:14:10 -0800 Subject: [PATCH] fsm WIP might work --- docs/sw-design.md | 2 +- src/GPS.cpp | 6 ++++++ src/GPS.h | 3 +++ src/PowerFSM.cpp | 48 ++++++++++++++++++++++++++--------------------- src/PowerFSM.h | 4 +++- src/main.ino | 8 ++++---- src/sleep.cpp | 4 ---- src/sleep.h | 1 + 8 files changed, 45 insertions(+), 31 deletions(-) diff --git a/docs/sw-design.md b/docs/sw-design.md index e204f394e..84a7a1117 100644 --- a/docs/sw-design.md +++ b/docs/sw-design.md @@ -15,7 +15,7 @@ From lower to higher power consumption. * light-sleep (LS) - CPU is suspended (RAM stays alive), radio is on, bluetooth is off, GPS is off. Note: currently GPS is not turned off during light sleep, but there is a TODO item to fix this. - onEntry: setBluetoothOn(false), setGPSPower(false) - happens inside doLightSleep() + onEntry: setBluetoothOn(false), setGPSPower(false), doLightSleep() onIdle: (if we wake because our led blink timer has expired) blink the led then go back to sleep until we sleep for ls_secs onExit: setGPSPower(true), start trying to get gps lock: gps.startLock(), once lock arrives service.sendPosition(BROADCAST) diff --git a/src/GPS.cpp b/src/GPS.cpp index 9465c5714..a60e16ca9 100644 --- a/src/GPS.cpp +++ b/src/GPS.cpp @@ -137,6 +137,12 @@ void GPS::doTask() setPeriod(hasValidLocation && !wantNewLocation ? 30 * 1000 : 100); } +void GPS::startLock() +{ + wantNewLocation = true; + setPeriod(1); +} + String GPS::getTimeStr() { static char t[12]; // used to sprintf for Serial output diff --git a/src/GPS.h b/src/GPS.h index fe30b9d2b..7b45e103f 100644 --- a/src/GPS.h +++ b/src/GPS.h @@ -38,6 +38,9 @@ public: /// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs void prepareSleep(); + /// Restart our lock attempt - try to get and broadcast a GPS reading ASAP + void startLock(); + private: void readFromRTC(); }; diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 014900ef9..8e7780bd5 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -5,6 +5,7 @@ #include "configuration.h" #include "screen.h" #include "PowerFSM.h" +#include "GPS.h" static void sdsEnter() { @@ -23,7 +24,7 @@ static void sdsEnter() static void lsEnter() { -/* + /* // while we have bluetooth on, we can't do light sleep, but once off stay in light_sleep all the time // we will wake from light sleep on button press or interrupt from the RF95 radio if (!bluetoothOn && !is_screen_on() && service.radio.rf95.canSleep() && gps.canSleep()) @@ -33,6 +34,8 @@ static void lsEnter() delay(msecstosleep); } */ + gps.prepareSleep(); // abandon in-process parsing + setGPSPower(false); // kill GPS power doLightSleep(radioConfig.preferences.ls_secs * 1000LL); } @@ -43,7 +46,8 @@ static void lsIdle() static void lsExit() { - // nothing + setGPSPower(true); // restore GPS power + gps.startLock(); } static void nbEnter() @@ -54,7 +58,7 @@ static void nbEnter() static void darkEnter() { DEBUG_MSG("screen timeout, turn it off for now...\n"); - screen.setOn(true); + screen.setOn(false); } static void onEnter() @@ -76,31 +80,33 @@ static void screenPress() screen.onPress(); } -State stateSDS(sdsEnter, NULL, NULL); -State stateLS(lsEnter, lsIdle, lsExit); -State stateNB(nbEnter, NULL, NULL); -State stateDARK(darkEnter, NULL, NULL); -State stateON(onEnter, NULL, onExit); +State stateSDS(sdsEnter, NULL, NULL, "SDS"); +State stateLS(lsEnter, lsIdle, lsExit, "LS"); +State stateNB(nbEnter, NULL, NULL, "NB"); +State stateDARK(darkEnter, NULL, NULL, "DARK"); +State stateON(onEnter, NULL, onExit, "ON"); Fsm powerFSM(&stateDARK); void PowerFSM_setup() { - powerFSM.add_transition(&stateDARK, &stateON, EVENT_BOOT, NULL); - powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WAKE_TIMER, wakeForPing); - powerFSM.add_transition(&stateLS, &stateNB, EVENT_RECEIVED_PACKET, NULL); + powerFSM.add_transition(&stateDARK, &stateON, EVENT_BOOT, NULL, "Boot"); + powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WAKE_TIMER, wakeForPing, "Wake timer"); + powerFSM.add_transition(&stateLS, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet"); - powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL); - powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL); - powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL); - powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress); // reenter On to restart our timers + powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press"); + 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 - powerFSM.add_transition(&stateLS, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL); - powerFSM.add_transition(&stateNB, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL); - powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL); + 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"); - powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL); + powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone"); - powerFSM.add_timed_transition(&stateON, &stateDARK, radioConfig.preferences.screen_on_secs, NULL); + powerFSM.add_timed_transition(&stateON, &stateDARK, radioConfig.preferences.screen_on_secs, NULL, "Screen-on timeout"); - powerFSM.add_timed_transition(&stateDARK, &stateNB, radioConfig.preferences.phone_timeout_secs, NULL); + powerFSM.add_timed_transition(&stateDARK, &stateNB, radioConfig.preferences.phone_timeout_secs, NULL, "Phone timeout"); + + powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state } \ No newline at end of file diff --git a/src/PowerFSM.h b/src/PowerFSM.h index 7a72d4d7a..2492d14a6 100644 --- a/src/PowerFSM.h +++ b/src/PowerFSM.h @@ -11,4 +11,6 @@ #define EVENT_RECEIVED_TEXT_MSG 5 #define EVENT_BOOT 6 -extern Fsm powerFSM; \ No newline at end of file +extern Fsm powerFSM; + +void PowerFSM_setup(); \ No newline at end of file diff --git a/src/main.ino b/src/main.ino index 69315a554..13db77b66 100644 --- a/src/main.ino +++ b/src/main.ino @@ -50,7 +50,6 @@ bool isUSBPowered = false; bool ssd1306_found = false; bool axp192_found = false; - #define xstr(s) str(s) #define str(s) #s @@ -58,7 +57,6 @@ bool axp192_found = false; // Application // ----------------------------------------------------------------------------- - void scanI2Cdevice(void) { byte err, addr; @@ -188,7 +186,6 @@ void axp192Init() #endif } - const char *getDeviceName() { uint8_t dmac[6]; @@ -208,7 +205,6 @@ void setup() #endif initDeepSleep(); - // delay(1000); FIXME - remove #ifdef VEXT_ENABLE pinMode(VEXT_ENABLE, OUTPUT); @@ -267,6 +263,9 @@ void setup() setBluetoothEnable(false); setCPUFast(false); // 80MHz is fine for our slow peripherals + + PowerFSM_setup(); + powerFSM.trigger(EVENT_BOOT); // transition to ON, FIXME, only do this for cold boots, not waking from SDS } uint32_t ledBlinker() @@ -303,6 +302,7 @@ void loop() { uint32_t msecstosleep = 1000 * 30; // How long can we sleep before we again need to service the main loop? + powerFSM.run_machine(); gps.loop(); screen.loop(); service.loop(); diff --git a/src/sleep.cpp b/src/sleep.cpp index 02641a509..c4e90c449 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -213,8 +213,6 @@ void doLightSleep(uint64_t sleepMsec) // FIXME, use a more reasonable default uint64_t sleepUsec = sleepMsec * 1000LL; setBluetoothEnable(false); // has to be off before calling light sleep - gps.prepareSleep(); // abandon in-process parsing - setGPSPower(false); // kill GPS power setLed(false); // Never leave led on while in light sleep // NOTE! ESP docs say we must disable bluetooth and wifi before light sleep @@ -231,8 +229,6 @@ void doLightSleep(uint64_t sleepMsec) // FIXME, use a more reasonable default esp_sleep_enable_timer_wakeup(sleepUsec); esp_light_sleep_start(); DEBUG_MSG("Exit light sleep\n"); - - setGPSPower(true); // restore GPS power } #if 0 diff --git a/src/sleep.h b/src/sleep.h index 9e3aadd3d..dd72878bb 100644 --- a/src/sleep.h +++ b/src/sleep.h @@ -5,6 +5,7 @@ void doDeepSleep(uint64_t msecToWake); void doLightSleep(uint64_t msecToWake); void setBluetoothEnable(bool on); +void setGPSPower(bool on); // Perform power on init that we do on each wake from deep sleep void initDeepSleep();