unify periodic timers

1.2-legacy
geeksville 2020-02-21 08:41:36 -08:00
rodzic 132e54ecc5
commit 5f3e8b5309
7 zmienionych plików z 76 dodań i 58 usunięć

Wyświetl plik

@ -5,6 +5,7 @@ Items to complete before the first alpha release.
* implement CustomRF95::canSleep * implement CustomRF95::canSleep
* document rules for sleep wrt lora/bluetooth/screen/gps. also: if I have text messages (only) for the phone, then give a few seconds in the hopes BLE can get it across before we have to go back to sleep. * document rules for sleep wrt lora/bluetooth/screen/gps. also: if I have text messages (only) for the phone, then give a few seconds in the hopes BLE can get it across before we have to go back to sleep.
* wake from light sleep as needed for our next scheduled periodic task (needed for gps position broadcasts etc) * wake from light sleep as needed for our next scheduled periodic task (needed for gps position broadcasts etc)
* turn bluetooth off based on our sleep policy
* if the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs * if the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs
for it (because it will redownload the nodedb when it comes back) for it (because it will redownload the nodedb when it comes back)
* don't enter light sleep while the screen is on * don't enter light sleep while the screen is on

Wyświetl plik

@ -11,8 +11,9 @@ uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated onc
RTC_DATA_ATTR bool timeSetFromGPS; // We only reset our time once per _boot_ after that point just run from the internal clock (even across sleeps) RTC_DATA_ATTR bool timeSetFromGPS; // We only reset our time once per _boot_ after that point just run from the internal clock (even across sleeps)
GPS gps; GPS gps;
bool hasValidLocation; // default to false, until we complete our first read
GPS::GPS() : PeriodicTask(30 * 1000) GPS::GPS() : PeriodicTask()
{ {
} }
@ -57,8 +58,23 @@ void GPS::perhapsSetRTC(const struct timeval *tv)
void GPS::loop() void GPS::loop()
{ {
PeriodicTask::loop(); PeriodicTask::loop();
}
uint32_t GPS::getTime()
{
return ((millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
}
uint32_t GPS::getValidTime()
{
return timeSetFromGPS ? getTime() : 0;
}
uint32_t GPS::doTask()
{
#ifdef GPS_RX_PIN #ifdef GPS_RX_PIN
// Consume all characters that have arrived
while (_serial_gps.available()) while (_serial_gps.available())
{ {
encode(_serial_gps.read()); encode(_serial_gps.read());
@ -86,25 +102,16 @@ void GPS::loop()
perhapsSetRTC(&tv); perhapsSetRTC(&tv);
} }
#endif #endif
}
uint32_t GPS::getTime()
{
return ((millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
}
uint32_t GPS::getValidTime()
{
return timeSetFromGPS ? getTime() : 0;
}
void GPS::doTask()
{
if (location.isValid() && location.isUpdated()) if (location.isValid() && location.isUpdated())
{ // we only notify if position has changed { // we only notify if position has changed
// DEBUG_MSG("new gps pos\n"); // DEBUG_MSG("new gps pos\n");
hasValidLocation = true;
notifyObservers(); notifyObservers();
} }
// Once we have sent a location we only poll the GPS rarely, otherwise check back every 100ms until we have something over the serial
return hasValidLocation ? 30 * 1000 : 100;
} }
String GPS::getTimeStr() String GPS::getTimeStr()

Wyświetl plik

@ -27,7 +27,7 @@ public:
virtual void loop(); virtual void loop();
virtual void doTask(); virtual uint32_t doTask();
/// If we haven't yet set our RTC this boot, set it from a GPS derived time /// If we haven't yet set our RTC this boot, set it from a GPS derived time
void perhapsSetRTC(const struct timeval *tv); void perhapsSetRTC(const struct timeval *tv);

Wyświetl plik

@ -8,6 +8,7 @@
#include "NodeDB.h" #include "NodeDB.h"
#include "GPS.h" #include "GPS.h"
#include "screen.h" #include "screen.h"
#include "Periodic.h"
/* /*
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone. receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
@ -60,7 +61,9 @@ void MeshService::init()
DEBUG_MSG("radio init failed\n"); DEBUG_MSG("radio init failed\n");
gps.addObserver(this); gps.addObserver(this);
sendOurOwner();
// No need to call this here, our periodic task will fire quite soon
// sendOwnerPeriod();
} }
void MeshService::sendOurOwner(NodeNum dest) void MeshService::sendOurOwner(NodeNum dest)
@ -165,6 +168,16 @@ void MeshService::handleFromRadio()
bluetoothNotifyFromNum(fromNum); bluetoothNotifyFromNum(fromNum);
} }
uint32_t sendOwnerCb()
{
service.sendOurOwner();
return radioConfig.preferences.send_owner_secs * 1000;
}
Periodic sendOwnerPeriod(sendOwnerCb);
/// Do idle processing (mostly processing messages which have been queued from the radio) /// Do idle processing (mostly processing messages which have been queued from the radio)
void MeshService::loop() void MeshService::loop()
{ {
@ -173,13 +186,7 @@ void MeshService::loop()
handleFromRadio(); handleFromRadio();
// occasionally send our owner info // occasionally send our owner info
static uint32_t lastsend; sendOwnerPeriod.loop();
uint32_t now = millis();
if (now - lastsend > radioConfig.preferences.send_owner_secs * 1000)
{
lastsend = now;
sendOurOwner();
}
} }
/// The radioConfig object just changed, call this to force the hw to change to the new settings /// The radioConfig object just changed, call this to force the hw to change to the new settings

Wyświetl plik

@ -1,32 +1,22 @@
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#include "PeriodicTask.h"
/** /**
* Periodically invoke a callback. * Periodically invoke a callback.
* *
* FIXME: currently just syntatic sugar for polling in loop (you must call .loop), but eventually * This just provides C style callback conventions rather than a virtual function - FIXME, remove?
* generalize with the freertos scheduler so we can save lots of power by having everything either in
* something like this or triggered off of an irq.
*/ */
class Periodic class Periodic : public PeriodicTask
{ {
uint32_t lastMsec = 0;
uint32_t period = 1; // call soon after creation
uint32_t (*callback)(); uint32_t (*callback)();
public: public:
// callback returns the period for the next callback invocation (or 0 if we should no longer be called) // callback returns the period for the next callback invocation (or 0 if we should no longer be called)
Periodic(uint32_t (*_callback)()) : callback(_callback) {} Periodic(uint32_t (*_callback)()) : callback(_callback) {}
// for the time being this must be called from loop protected:
void loop()
{ uint32_t doTask();
uint32_t now = millis();
if (period && (now - lastMsec) >= period)
{
lastMsec = now;
period = (*callback)();
}
}
}; };

Wyświetl plik

@ -0,0 +1,19 @@
#include "PeriodicTask.h"
#include "Periodic.h"
PeriodicTask::PeriodicTask(uint32_t initialPeriod) : period(initialPeriod)
{
}
/// call this from loop
void PeriodicTask::loop()
{
uint32_t now = millis();
if (period && (now - lastMsec) >= period)
{
lastMsec = now;
period = doTask();
}
}
uint32_t Periodic::doTask() { return callback(); }

Wyświetl plik

@ -3,34 +3,28 @@
#include <Arduino.h> #include <Arduino.h>
#include "configuration.h" #include "configuration.h"
/**
* A base class for tasks that want their doTask() method invoked periodically
*
* FIXME: currently just syntatic sugar for polling in loop (you must call .loop), but eventually
* generalize with the freertos scheduler so we can save lots of power by having everything either in
* something like this or triggered off of an irq.
*/
class PeriodicTask class PeriodicTask
{ {
/// we use prevMsec rather than nextMsec because it is easier to handle the uint32 rollover in that case, also changes in periodMsec take effect immediately uint32_t lastMsec = 0;
uint32_t prevMsec; uint32_t period = 1; // call soon after creation
public: public:
uint32_t periodMsec; uint32_t periodMsec;
virtual ~PeriodicTask() {} virtual ~PeriodicTask() {}
PeriodicTask(uint32_t period) : periodMsec(period) PeriodicTask(uint32_t initialPeriod = 1);
{
prevMsec = millis();
}
/// call this from loop /// call this from loop
virtual void loop() virtual void loop();
{
uint32_t now = millis();
if (now > (prevMsec + periodMsec))
{
// FIXME, this lets period slightly drift based on scheduling - not sure if that is always good
prevMsec = now;
// DEBUG_MSG("Calling periodic task\n"); protected:
doTask(); virtual uint32_t doTask() = 0;
}
}
virtual void doTask() = 0;
}; };