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
* 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)
* 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
for it (because it will redownload the nodedb when it comes back)
* 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)
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()
{
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
// Consume all characters that have arrived
while (_serial_gps.available())
{
encode(_serial_gps.read());
@ -86,25 +102,16 @@ void GPS::loop()
perhapsSetRTC(&tv);
}
#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())
{ // we only notify if position has changed
// DEBUG_MSG("new gps pos\n");
hasValidLocation = true;
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()

Wyświetl plik

@ -27,7 +27,7 @@ public:
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
void perhapsSetRTC(const struct timeval *tv);

Wyświetl plik

@ -8,6 +8,7 @@
#include "NodeDB.h"
#include "GPS.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.
@ -60,7 +61,9 @@ void MeshService::init()
DEBUG_MSG("radio init failed\n");
gps.addObserver(this);
sendOurOwner();
// No need to call this here, our periodic task will fire quite soon
// sendOwnerPeriod();
}
void MeshService::sendOurOwner(NodeNum dest)
@ -165,6 +168,16 @@ void MeshService::handleFromRadio()
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)
void MeshService::loop()
{
@ -173,13 +186,7 @@ void MeshService::loop()
handleFromRadio();
// occasionally send our owner info
static uint32_t lastsend;
uint32_t now = millis();
if (now - lastsend > radioConfig.preferences.send_owner_secs * 1000)
{
lastsend = now;
sendOurOwner();
}
sendOwnerPeriod.loop();
}
/// 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
#include <Arduino.h>
#include "PeriodicTask.h"
/**
* Periodically invoke a callback.
*
* 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.
* This just provides C style callback conventions rather than a virtual function - FIXME, remove?
*/
class Periodic
class Periodic : public PeriodicTask
{
uint32_t lastMsec = 0;
uint32_t period = 1; // call soon after creation
uint32_t (*callback)();
public:
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
Periodic(uint32_t (*_callback)()) : callback(_callback) {}
// for the time being this must be called from loop
void loop()
{
uint32_t now = millis();
if (period && (now - lastMsec) >= period)
{
lastMsec = now;
period = (*callback)();
}
}
protected:
uint32_t doTask();
};

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 "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
{
/// 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 prevMsec;
uint32_t lastMsec = 0;
uint32_t period = 1; // call soon after creation
public:
uint32_t periodMsec;
virtual ~PeriodicTask() {}
PeriodicTask(uint32_t period) : periodMsec(period)
{
prevMsec = millis();
}
PeriodicTask(uint32_t initialPeriod = 1);
/// call this from 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;
virtual void loop();
// DEBUG_MSG("Calling periodic task\n");
doTask();
}
}
virtual void doTask() = 0;
protected:
virtual uint32_t doTask() = 0;
};