-
Notifications
You must be signed in to change notification settings - Fork 197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add light versions. #32
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
StaticThreadControllerLite.h - Controlls a list of ThreadsLite with different timings | ||
|
||
Basicaly, what it does is to keep track of current ThreadsLite and run when | ||
necessary. | ||
|
||
StaticThreadControllerLite is based on the class StaticThreadController, | ||
but takes less memory and maximum period is only 32,767 seconds. | ||
WARNING! It is not recommended to use if you do not have a memory deficit. | ||
|
||
Copyright © 2016 Alex Eremin. | ||
Copyright © 2018 Stanislav Hnatiuk. | ||
Released into the public domain. | ||
*/ | ||
|
||
#ifndef STATICTHREADCONTROLLERLITE_H | ||
#define STATICTHREADCONTROLLERLITE_H | ||
|
||
#include "ThreadLite.h" | ||
|
||
template <uint8_t N> | ||
class StaticThreadControllerLite { | ||
protected: | ||
ThreadLite thread[N]; | ||
public: | ||
template <typename... T> | ||
StaticThreadControllerLite(T... params) : thread{params...} { }; | ||
|
||
// Runs all ThreadLite | ||
void run() { | ||
for (uint8_t i = 0; i < N; i++) { | ||
// Is enabled? Timeout exceeded? | ||
if (thread[i].shouldRun()) { | ||
thread[i].run(); | ||
} | ||
} | ||
} | ||
|
||
// Return the quantity of ThreadsLite | ||
static constexpr int size() { | ||
return N; | ||
}; | ||
|
||
// Return the I ThreadLite on the array | ||
// Doesn't perform any bounds checks and behaviour is | ||
// unpredictable in case of index > N | ||
ThreadLite& operator[](uint8_t index) { | ||
return thread[index]; | ||
} | ||
}; | ||
|
||
#endif // STATICTHREADCONTROLLERLITE_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright © 2013 Ivan Seidel Gomes. | ||
// Copyright © 2018 Stanislav Hnatiuk. | ||
|
||
#include "ThreadLite.h" | ||
|
||
ThreadLite::ThreadLite(void (*callback)(void), TIME_INT _interval) { | ||
_onRun = callback; | ||
_cached_next_run = 0; | ||
last_run = 0; | ||
setInterval(_interval); | ||
}; | ||
|
||
void ThreadLite::runned() { | ||
// Saves last_run | ||
last_run = millis(); | ||
|
||
// Cache next run | ||
_cached_next_run = last_run + interval; | ||
} | ||
|
||
void ThreadLite::setInterval(TIME_INT _interval) { | ||
// Save interval | ||
interval = _interval; | ||
|
||
// Cache the next run based on the last_run | ||
_cached_next_run = last_run + interval; | ||
} | ||
|
||
bool ThreadLite::shouldRun() { | ||
TIME_INT time = millis(); | ||
// If the "sign" bit is set the signed difference would be negative | ||
bool time_remaining = (time - _cached_next_run) & TIME_OVERFLOW; | ||
|
||
// Exceeded the time limit, AND is enabled? Then should run... | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
ThreadLite is always enabled :) |
||
return !time_remaining; | ||
} | ||
|
||
void ThreadLite::run() { | ||
_onRun(); | ||
// Update last_run and _cached_next_run | ||
runned(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
ThreadLite.h - An runnable object | ||
|
||
Thread is responsable for holding the "action" for something, | ||
also, it responds if it "should" or "should not" run, based on | ||
the current time; | ||
|
||
ThreadLite is based on the class Thread, but takes less memory | ||
and maximum period is only 32,767 seconds. | ||
WARNING! It is not recommended to use if you do not have a memory deficit. | ||
|
||
Copyright © 2013 Ivan Seidel Gomes. | ||
Copyright © 2018 Stanislav Hnatiuk. | ||
Released into the public domain. | ||
*/ | ||
|
||
#ifndef THREADLITE_H | ||
#define THREADLITE_H | ||
|
||
#if defined(ARDUINO) && ARDUINO >= 100 | ||
#include <Arduino.h> | ||
#endif | ||
|
||
#define TIME_INT uint16_t | ||
#define TIME_OVERFLOW 0x8000 // uint16_t = 0x8000 or uint32_t = 0x80000000 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm just curious why do you define a new type in that way? Do you need extra flexibility to easily change underlying type? Don't you consider to make a template class in this case? using TIME_INT=uint16_t;
constexpr TIME_INT TIME_OVERFLOW = (1 << (sizeof (TIME_INT) * 8 - 1)); Seems it should be done in the mainline too (instead of using 0x80000000)... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for giving this correction. I used bad practice before. |
||
|
||
class ThreadLite { | ||
protected: | ||
// Desired interval between runs | ||
TIME_INT interval; | ||
|
||
// Last runned time in Ms | ||
TIME_INT last_run; | ||
|
||
// Scheduled run in Ms (MUST BE CACHED) | ||
TIME_INT _cached_next_run; | ||
|
||
/* | ||
IMPORTANT! Run after all calls to run() | ||
Updates last_run and cache next run. | ||
NOTE: This MUST be called if extending | ||
this class and implementing run() method | ||
*/ | ||
|
||
// Default is to mark it runned "now" | ||
void runned(); | ||
|
||
// Callback for run() if not implemented | ||
void (*_onRun)(void); | ||
|
||
public: | ||
ThreadLite(void (*callback)(void), TIME_INT _interval); | ||
|
||
// Set the desired interval for calls, and update _cached_next_run | ||
void setInterval(TIME_INT _interval); | ||
|
||
// Default is to check whether it should run "now" | ||
bool shouldRun(); | ||
|
||
// Runs ThreadLite | ||
void run(); | ||
}; | ||
|
||
#endif // THREADLITE_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoiding to initialize last_run may lead to missed first interval.
For example, if we set very small interval, for example 10ms and current millis() is greater than 32780 (we still use unsigned type, so it can be) then _cached_next_run will be 10 (lasr_run + interval) and sign bit will be set for all the operations until we overflow and thus should_run() will return false.
So for the first run we have to wait around 32 seconds instead of 10ms.
It's kind of rare situation, but I think last_run should be initialized to millis() here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I had a special case in my project and could not use initialization to save memory.