diff --git a/arduino/libs/ArduinoThread/StaticThreadController.h b/arduino/libs/ArduinoThread/StaticThreadController.h new file mode 100644 index 0000000..6e316ea --- /dev/null +++ b/arduino/libs/ArduinoThread/StaticThreadController.h @@ -0,0 +1,75 @@ +/* + StaticThreadController.h - Controlls a list of Threads with different timings + + Basicaly, what it does is to keep track of current Threads and run when + necessary. + + StaticThreadController is an extended class of Thread, because of that, + it allows you to add a StaticThreadController inside another kind of ThreadController... + + It works exact as ThreadController except you can't add or remove treads dynamically. + + Created by Alex Eremin, September, 2016. + Released into the public domain. +*/ + +#ifndef StaticThreadController_h +#define StaticThreadController_h + +#include "Thread.h" + +template +class StaticThreadController: public Thread{ +protected: + //since this is a static controller, the pointers themselves can be const + //it should be distinguished from 'const Thread* thread[N]' + Thread * const thread[N]; +public: + template + StaticThreadController(T... params) : + Thread(), + thread{params...} + { + #ifdef USE_THREAD_NAMES + // Overrides name + ThreadName = "StaticThreadController "; + ThreadName = ThreadName + ThreadID; + #endif + }; + + // run() Method is overrided + void run() override + { + // Run this thread before + if(_onRun != nullptr && shouldRun()) + _onRun(); + + for(int i = 0; i < N; i++){ + // Is enabled? Timeout exceeded? + if(thread[i]->shouldRun()){ + thread[i]->run(); + } + } + + // StaticThreadController extends Thread, so we should flag as runned thread + runned(); + } + + // Return the quantity of Threads + static constexpr int size() { return N; }; + + // Return the I Thread on the array + // Returns nullptr if index is out of bounds + Thread* get(int index) { + return (index >= 0 && index < N) ? thread[index] : nullptr; + }; + + // Return the I Thread on the array + // Doesn't perform any bounds checks and behaviour is + // unpredictable in case of index > N + Thread& operator[](int index) { + return *thread[index]; + }; +}; + +#endif diff --git a/arduino/libs/ArduinoThread/Thread.cpp b/arduino/libs/ArduinoThread/Thread.cpp new file mode 100644 index 0000000..cd29d98 --- /dev/null +++ b/arduino/libs/ArduinoThread/Thread.cpp @@ -0,0 +1,52 @@ +#include "Thread.h" + +Thread::Thread(void (*callback)(void), unsigned long _interval){ + enabled = true; + onRun(callback); + _cached_next_run = 0; + last_run = millis(); + + ThreadID = (int)this; + #ifdef USE_THREAD_NAMES + ThreadName = "Thread "; + ThreadName = ThreadName + ThreadID; + #endif + + setInterval(_interval); +}; + +void Thread::runned(unsigned long time){ + // Saves last_run + last_run = time; + + // Cache next run + _cached_next_run = last_run + interval; +} + +void Thread::setInterval(unsigned long _interval){ + // Save interval + interval = _interval; + + // Cache the next run based on the last_run + _cached_next_run = last_run + interval; +} + +bool Thread::shouldRun(unsigned long time){ + // If the "sign" bit is set the signed difference would be negative + bool time_remaining = (time - _cached_next_run) & 0x80000000; + + // Exceeded the time limit, AND is enabled? Then should run... + return !time_remaining && enabled; +} + +void Thread::onRun(void (*callback)(void)){ + _onRun = callback; +} + +void Thread::run(){ + if(_onRun != NULL) + _onRun(); + + // Update last_run and _cached_next_run + runned(); +} diff --git a/arduino/libs/ArduinoThread/Thread.h b/arduino/libs/ArduinoThread/Thread.h new file mode 100644 index 0000000..0e580a9 --- /dev/null +++ b/arduino/libs/ArduinoThread/Thread.h @@ -0,0 +1,89 @@ +/* + Thread.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; + + For instructions, go to https://github.com/ivanseidel/ArduinoThread + + Created by Ivan Seidel Gomes, March, 2013. + Released into the public domain. +*/ + +#ifndef Thread_h +#define Thread_h + +#if defined(ARDUINO) && ARDUINO >= 100 + #include +#else + #include +#endif + +#include + +/* + Uncomment this line to enable ThreadName Strings. + + It might be usefull if you are loging thread with Serial, + or displaying a list of threads... +*/ +// #define USE_THREAD_NAMES 1 + +class Thread{ +protected: + // Desired interval between runs + unsigned long interval; + + // Last runned time in Ms + unsigned long last_run; + + // Scheduled run in Ms (MUST BE CACHED) + unsigned long _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 + */ + void runned(unsigned long time); + + // Default is to mark it runned "now" + void runned() { runned(millis()); } + + // Callback for run() if not implemented + void (*_onRun)(void); + +public: + + // If the current Thread is enabled or not + bool enabled; + + // ID of the Thread (initialized from memory adr.) + int ThreadID; + + #ifdef USE_THREAD_NAMES + // Thread Name (used for better UI). + String ThreadName; + #endif + + Thread(void (*callback)(void) = NULL, unsigned long _interval = 0); + + // Set the desired interval for calls, and update _cached_next_run + virtual void setInterval(unsigned long _interval); + + // Return if the Thread should be runned or not + virtual bool shouldRun(unsigned long time); + + // Default is to check whether it should run "now" + bool shouldRun() { return shouldRun(millis()); } + + // Callback set + void onRun(void (*callback)(void)); + + // Runs Thread + virtual void run(); +}; + +#endif diff --git a/arduino/libs/ArduinoThread/ThreadController.cpp b/arduino/libs/ArduinoThread/ThreadController.cpp new file mode 100644 index 0000000..7d8e41c --- /dev/null +++ b/arduino/libs/ArduinoThread/ThreadController.cpp @@ -0,0 +1,114 @@ +#include "Thread.h" +#include "ThreadController.h" + +ThreadController::ThreadController(unsigned long _interval): Thread(){ + cached_size = 0; + + clear(); + setInterval(_interval); + + #ifdef USE_THREAD_NAMES + // Overrides name + ThreadName = "ThreadController "; + ThreadName = ThreadName + ThreadID; + #endif +} + +/* + ThreadController run() (cool stuf) +*/ +void ThreadController::run(){ + // Run this thread before + if(_onRun != NULL) + _onRun(); + + unsigned long time = millis(); + int checks = 0; + for(int i = 0; i < MAX_THREADS && checks < cached_size; i++){ + // Object exists? Is enabled? Timeout exceeded? + if(thread[i]){ + checks++; + if(thread[i]->shouldRun(time)){ + thread[i]->run(); + } + } + } + + // ThreadController extends Thread, so we should flag as runned thread + runned(); +} + + +/* + List controller (boring part) +*/ +bool ThreadController::add(Thread* _thread){ + // Check if the Thread already exists on the array + for(int i = 0; i < MAX_THREADS; i++){ + if(thread[i] != NULL && thread[i]->ThreadID == _thread->ThreadID) + return true; + } + + // Find an empty slot + for(int i = 0; i < MAX_THREADS; i++){ + if(!thread[i]){ + // Found a empty slot, now add Thread + thread[i] = _thread; + cached_size++; + return true; + } + } + + // Array is full + return false; +} + +void ThreadController::remove(int id){ + // Find Threads with the id, and removes + for(int i = 0; i < MAX_THREADS; i++){ + if(thread[i]->ThreadID == id){ + thread[i] = NULL; + cached_size--; + return; + } + } +} + +void ThreadController::remove(Thread* _thread){ + remove(_thread->ThreadID); +} + +void ThreadController::clear(){ + for(int i = 0; i < MAX_THREADS; i++){ + thread[i] = NULL; + } + cached_size = 0; +} + +int ThreadController::size(bool cached){ + if(cached) + return cached_size; + + int size = 0; + for(int i = 0; i < MAX_THREADS; i++){ + if(thread[i]) + size++; + } + cached_size = size; + + return cached_size; +} + +Thread* ThreadController::get(int index){ + int pos = -1; + for(int i = 0; i < MAX_THREADS; i++){ + if(thread[i] != NULL){ + pos++; + + if(pos == index) + return thread[i]; + } + } + + return NULL; +} diff --git a/arduino/libs/ArduinoThread/ThreadController.h b/arduino/libs/ArduinoThread/ThreadController.h new file mode 100644 index 0000000..8e2888c --- /dev/null +++ b/arduino/libs/ArduinoThread/ThreadController.h @@ -0,0 +1,53 @@ +/* + ThreadController.h - Controlls a list of Threads with different timings + + Basicaly, what it does is to keep track of current Threads and run when + necessary. + + ThreadController is an extended class of Thread, because of that, + it allows you to add a ThreadController inside another ThreadController... + + For instructions, go to https://github.com/ivanseidel/ArduinoThread + + Created by Ivan Seidel Gomes, March, 2013. + Released into the public domain. +*/ + +#ifndef ThreadController_h +#define ThreadController_h + +#include "Thread.h" +#include "inttypes.h" + +#define MAX_THREADS 15 + +class ThreadController: public Thread{ +protected: + Thread* thread[MAX_THREADS]; + int cached_size; +public: + ThreadController(unsigned long _interval = 0); + + // run() Method is overrided + void run(); + + // Adds a thread in the first available slot (remove first) + // Returns if the Thread could be added or not + bool add(Thread* _thread); + + // remove the thread (given the Thread* or ThreadID) + void remove(int _id); + void remove(Thread* _thread); + + // Removes all threads + void clear(); + + // Return the quantity of Threads + int size(bool cached = true); + + // Return the I Thread on the array + // Returns NULL if none found + Thread* get(int index); +}; + +#endif