WIP state machine builds

This commit is contained in:
geeksville
2020-02-22 12:01:59 -08:00
parent 045529d91f
commit 509f9b6e2b
10 changed files with 173 additions and 54 deletions
+106
View File
@@ -0,0 +1,106 @@
#include "sleep.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "configuration.h"
#include "screen.h"
#include "PowerFSM.h"
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);
}
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())
doLightSleep(radioConfig.preferences.ls_secs);
else
{
delay(msecstosleep);
} */
doLightSleep(radioConfig.preferences.ls_secs * 1000LL);
}
static void lsIdle()
{
// FIXME - blink led when we occasionally wake from timer, then go back to light sleep
}
static void lsExit()
{
// nothing
}
static void nbEnter()
{
setBluetoothEnable(false);
}
static void darkEnter()
{
DEBUG_MSG("screen timeout, turn it off for now...\n");
screen.setOn(true);
}
static void onEnter()
{
screen.setOn(true);
setBluetoothEnable(true);
}
static void onExit()
{
screen.setOn(false);
}
static void wakeForPing()
{
}
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);
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(&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_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(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL);
powerFSM.add_timed_transition(&stateON, &stateDARK, radioConfig.preferences.screen_on_secs, NULL);
powerFSM.add_timed_transition(&stateDARK, &stateNB, radioConfig.preferences.phone_timeout_secs, NULL);
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include "Fsm.h"
// See sw-design.md for documentation
#define EVENT_PRESS 1
#define EVENT_WAKE_TIMER 2
#define EVENT_RECEIVED_PACKET 3
#define EVENT_PACKET_FOR_PHONE 4
#define EVENT_RECEIVED_TEXT_MSG 5
#define EVENT_BOOT 6
extern Fsm powerFSM;
-4
View File
@@ -60,10 +60,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define REQUIRE_RADIO true // If true, we will fail to start if the radio is not found
// If not defined, we will wait for lock forever
#define MINWAKE_MSECS (60 * 60 * 1000) // stay awake a long time (30 mins) for debugging - FIXME, change per the TBD sleep rules doc
// #define MINWAKE_MSECS (30 * 1000) // Wait after every boot for GPS lock (may need longer than 5s because we turned the gps off during deep sleep)
// -----------------------------------------------------------------------------
// DEBUG
+4 -20
View File
@@ -37,6 +37,7 @@
#include "esp_pm.h"
#include "MeshRadio.h"
#include "sleep.h"
#include "PowerFSM.h"
#ifdef T_BEAM_V10
#include "axp20x.h"
@@ -337,7 +338,7 @@ void loop()
// if user presses button for more than 3 secs, discard our network prefs and reboot (FIXME, use a debounce lib instead of this boilerplate)
static bool wasPressed = false;
static uint32_t minPressMs; // what tick should we call this press long enough
static uint32_t lastPingMs, lastPressMs;
static uint32_t lastPingMs;
if (!digitalRead(BUTTON_PIN))
{
if (!wasPressed)
@@ -349,7 +350,6 @@ void loop()
wasPressed = true;
uint32_t now = millis();
lastPressMs = now;
minPressMs = now + 3000;
if (now - lastPingMs > 60 * 1000)
@@ -358,7 +358,7 @@ void loop()
lastPingMs = now;
}
screen_press();
powerFSM.trigger(EVENT_PRESS);
}
}
else if (wasPressed)
@@ -375,15 +375,6 @@ void loop()
}
#endif
#ifdef MINWAKE_MSECS
// 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 > MINWAKE_MSECS)
{
doDeepSleep(radioConfig.preferences.sds_secs);
}
#endif
// No GPS lock yet, let the OS put the main CPU in low power mode for 100ms (or until another interrupt comes in)
// i.e. don't just keep spinning in loop as fast as we can.
//DEBUG_MSG("msecs %d\n", msecstosleep);
@@ -391,12 +382,5 @@ void loop()
// FIXME - until button press handling is done by interrupt (see polling above) we can't sleep very long at all or buttons feel slow
msecstosleep = 10;
// 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())
doLightSleep(60 * 1000); // FIXME, wake up to briefly flash led, then go back to sleep (without repowering bluetooth)
else
{
delay(msecstosleep);
}
delay(msecstosleep);
}
+14 -16
View File
@@ -60,7 +60,7 @@ static bool showingBootScreen = true; // start by showing the bootscreen
uint32_t lastPressMs;
bool is_screen_on() { return screenOn; }
bool Screen::isOn() { return screenOn; }
void msOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
{
@@ -491,22 +491,19 @@ void _screen_header()
}
#endif
void screen_off()
{
if (!disp)
return;
dispdev.displayOff();
screenOn = false;
}
void screen_on()
void Screen::setOn(bool on)
{
if (!disp)
return;
if(on != screenOn) {
if(on)
dispdev.displayOn();
screenOn = true;
else
dispdev.displayOff();
screenOn = on;
}
}
static void screen_print(const char *text, uint8_t x, uint8_t y, uint8_t alignment)
@@ -579,7 +576,7 @@ void Screen::setup()
// Scroll buffer
dispdev.setLogBuffer(3, 32);
screen_on(); // update our screenOn bool
setOn(true); // update our screenOn bool
#ifdef BICOLOR_DISPLAY
dispdev.flipScreenVertically(); // looks better without this on lora32
@@ -612,7 +609,7 @@ void Screen::doTask()
if (wakeScreen) // If a new text message arrived, turn the screen on immedately
{
lastPressMs = millis(); // if we were told to wake the screen, reset the press timeout
screen_on(); // make sure the screen is not asleep
screen.setOn(true); // make sure the screen is not asleep
wakeScreen = false;
}
@@ -655,11 +652,12 @@ void Screen::doTask()
nodeDB.updateTextMessage = false;
}
/*
if (millis() - lastPressMs > SCREEN_SLEEP_MS)
{
DEBUG_MSG("screen timeout, turn it off for now...\n");
screen_off();
}
screen.setOn(false);
} */
}
}
@@ -716,7 +714,7 @@ void screen_set_frames()
}
/// handle press of the button
void screen_press()
void Screen::onPress()
{
// screen_start_bluetooth(123456);
+9 -2
View File
@@ -4,7 +4,6 @@
void screen_print(const char * text);
void screen_on(), screen_off(), screen_press();
// Show the bluetooth PIN screen
void screen_start_bluetooth(uint32_t pin);
@@ -12,7 +11,6 @@ void screen_start_bluetooth(uint32_t pin);
// restore our regular frame list
void screen_set_frames();
bool is_screen_on();
/**
* Slowly I'm moving screen crap into this class
@@ -27,6 +25,15 @@ public:
/// Turn on the screen asap
void doWakeScreen();
/// Is the screen currently on
bool isOn();
/// Turn the screen on/off
void setOn(bool on);
/// Handle a button press
void onPress();
};
extern Screen screen;
+6 -1
View File
@@ -65,6 +65,8 @@ void setLed(bool ledOn)
void setGPSPower(bool on)
{
DEBUG_MSG("Setting GPS power=%d\n", on);
#ifdef T_BEAM_V10
if (axp192_found)
axp.setPowerOutPut(AXP192_LDO3, on ? AXP202_ON : AXP202_OFF); // GPS main power
@@ -97,7 +99,7 @@ void doDeepSleep(uint64_t msecToWake)
BLEDevice::deinit(false); // We are required to shutdown bluetooth before deep or light sleep
screen_off(); // datasheet says this will draw only 10ua
screen.setOn(false); // datasheet says this will draw only 10ua
// Put radio in sleep mode (will still draw power but only 0.2uA)
service.radio.rf95.sleep();
@@ -212,6 +214,7 @@ void doLightSleep(uint64_t sleepMsec) // FIXME, use a more reasonable default
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
@@ -228,6 +231,8 @@ 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
+2
View File
@@ -1,5 +1,7 @@
#pragma once
#include "Arduino.h"
void doDeepSleep(uint64_t msecToWake);
void doLightSleep(uint64_t msecToWake);
void setBluetoothEnable(bool on);