mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-20 02:11:28 +10:00
WIP state machine builds
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
void doDeepSleep(uint64_t msecToWake);
|
||||
void doLightSleep(uint64_t msecToWake);
|
||||
void setBluetoothEnable(bool on);
|
||||
|
||||
Reference in New Issue
Block a user