sforkowany z mirror/meshtastic-firmware
unify periodic timers
rodzic
132e54ecc5
commit
5f3e8b5309
1
TODO.md
1
TODO.md
|
@ -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
|
||||
|
|
35
src/GPS.cpp
35
src/GPS.cpp
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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(); }
|
|
@ -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;
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue