mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-25 09:42:35 +00:00
unify periodic timers
This commit is contained in:
parent
132e54ecc5
commit
5f3e8b5309
1
TODO.md
1
TODO.md
@ -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
|
||||||
|
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)
|
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()
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
19
src/PeriodicTask.cpp
Normal file
19
src/PeriodicTask.cpp
Normal file
@ -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 <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;
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user