You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

152 lines
5.2 KiB

//-----------------------------------------------------------------------------
// 2022 Ahoy, https://ahoydtu.de
// Lukas Pusch, lukas@lpusch.de
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//-----------------------------------------------------------------------------
#ifndef __SCHEDULER_H__
#define __SCHEDULER_H__
#include <functional>
#include "dbg.h"
namespace ah {
typedef std::function<void()> scdCb;
enum {SCD_SEC = 1, SCD_MIN = 60, SCD_HOUR = 3600, SCD_12H = 43200, SCD_DAY = 86400};
struct sP {
scdCb c;
uint32_t timeout;
uint32_t reload;
bool isTimestamp;
sP() : c(NULL), timeout(0), reload(0), isTimestamp(false) {}
sP(scdCb a, uint32_t tmt, uint32_t rl, bool its) : c(a), timeout(tmt), reload(rl), isTimestamp(its) {}
};
#define MAX_NUM_TICKER 30
class Scheduler {
public:
Scheduler() {}
void setup() {
mUptime = 0;
mTimestamp = 0;
mMax = 0;
mPrevMillis = millis();
for (uint8_t i = 0; i < MAX_NUM_TICKER; i++)
mTickerInUse[i] = false;
}
void loop(void) {
mMillis = millis();
mDiff = mMillis - mPrevMillis;
if (mDiff < 1000)
return;
mDiffSeconds = 1;
if (mDiff < 2000)
mPrevMillis += 1000;
else {
if (mMillis < mPrevMillis) { // overflow
mDiff = mMillis;
if (mDiff < 1000)
return;
}
mDiffSeconds = mDiff / 1000;
mPrevMillis += (mDiffSeconds * 1000);
}
mUptime += mDiffSeconds;
if(0 != mTimestamp)
mTimestamp += mDiffSeconds;
checkTicker();
}
void once(scdCb c, uint32_t timeout) { addTicker(c, timeout, 0, false); }
void onceAt(scdCb c, uint32_t timestamp) { addTicker(c, timestamp, 0, true); }
uint8_t every(scdCb c, uint32_t interval){ return addTicker(c, interval, interval, false); }
void everySec(scdCb c) { every(c, SCD_SEC); }
void everyMin(scdCb c) { every(c, SCD_MIN); }
void everyHour(scdCb c) { every(c, SCD_HOUR); }
void every12h(scdCb c) { every(c, SCD_12H); }
void everyDay(scdCb c) { every(c, SCD_DAY); }
virtual void setTimestamp(uint32_t ts) {
mTimestamp = ts;
}
bool resetEveryById(uint8_t id) {
if (mTickerInUse[id] == false)
return false;
mTicker[id].timeout = mTicker[id].reload;
return true;
}
uint32_t getUptime(void) {
return mUptime;
}
uint32_t getTimestamp(void) {
return mTimestamp;
}
void getStat(uint8_t *max) {
*max = mMax;
}
protected:
uint32_t mTimestamp;
private:
inline uint8_t addTicker(scdCb c, uint32_t timeout, uint32_t reload, bool isTimestamp) {
for (uint8_t i = 0; i < MAX_NUM_TICKER; i++) {
if (!mTickerInUse[i]) {
mTickerInUse[i] = true;
mTicker[i].c = c;
mTicker[i].timeout = timeout;
mTicker[i].reload = reload;
mTicker[i].isTimestamp = isTimestamp;
if(mMax == i)
mMax = i + 1;
return i;
}
}
return 0xff;
}
inline void checkTicker(void) {
bool inUse[MAX_NUM_TICKER];
for (uint8_t i = 0; i < MAX_NUM_TICKER; i++)
inUse[i] = mTickerInUse[i];
for (uint8_t i = 0; i < MAX_NUM_TICKER; i++) {
if (inUse[i]) {
if (mTicker[i].timeout <= ((mTicker[i].isTimestamp) ? mTimestamp : mDiffSeconds)) { // expired
if(0 == mTicker[i].reload)
mTickerInUse[i] = false;
else
mTicker[i].timeout = mTicker[i].reload;
//DPRINTLN(DBG_INFO, "checkTick " + String(i) + " reload: " + String(mTicker[i].reload) + ", timeout: " + String(mTicker[i].timeout));
(mTicker[i].c)();
yield();
}
else // not expired
if (!mTicker[i].isTimestamp)
mTicker[i].timeout -= mDiffSeconds;
}
}
}
sP mTicker[MAX_NUM_TICKER];
bool mTickerInUse[MAX_NUM_TICKER];
uint32_t mMillis, mPrevMillis, mDiff;
uint32_t mUptime;
uint8_t mDiffSeconds;
uint8_t mMax;
};
}
#endif /*__SCHEDULER_H__*/