Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * TaskScheduler.hpp
- *
- * Created: 16.11.2015 3:44:02
- * Author: dx
- * Very simple tiny task scheduler designed with minimal overhead in mind
- * You pay for what you are using only!
- * General use case with default settings:
- * TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerService > TaskScheduler;
- * Defaults:
- * timer resolution 8Bit Timer8Bit
- * task disable feature is turned off TaskDisable_OFF
- * task timers are NOT reloaded in constructor! use TS_RELOAD_ON_CONSTRUCT or ReloadAllTaskTimers()
- Usually not a problem, see description below!
- * MakeTasklist<Task1, Task2, TaskN> supports up to 16 tasks
- * Task must be a class with _STATIC_ uint32_t Period and _STATIC_ Run() func
- * static is required!
- * You may optionally add other functions and variables - this will have no effect on scheduler's work
- struct task1
- {
- static const uint32_t Period = 22;
- static void Run()
- { //this is non member function call
- Task1_func();
- //also you may call some instance func
- //SomeClass.Foo();
- //you may implement task code right here if you want
- //PORTB |= (1<< PINB3);
- }
- };
- * TimerService provides time(timer ticks to the scheduler)
- * Implement as class with static method uint32_t GetTickCount()
- struct TimeService
- {
- static uint32_t GetTickCount()
- {
- return G_TimerTicks; //returning a global tick counter, but you can return hardware counter - no problem.
- };
- };
- * Timer resolution: Timer8Bit, Timer16Bit or Timer32Bit
- * TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerService, Timer32Bit > TaskScheduler;
- * Task disable feature TaskDisable_ON TaskDisable_OFF
- * TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerService, Timer8Bit, TaskDisable_ON > TaskScheduler;
- * TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerServicem Timer8Bit, TaskDisable_OFF > TaskScheduler; //also valid code
- * NOTE:
- * By default timers[] are NOT explicitly initialized in constructor.
- * Usually TaskScheduler instant is a global variable(i.e. has static duration) and all timers will be initialized by 0
- * which means, if your TimerService is also global and starts count from 0 - everything is fine!!!
- *
- * You may pass TS_RELOAD_ON_CONSTRUCT to constructor to make timers reload on instantiation:
- * TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerService > TaskScheduler( TS_RELOAD_ON_CONSTRUCT );
- * or call somewhere:
- * TaskScheduler.ReloadAllTaskTimers(); //preferred way of doing timer initialization. Costs less Flash bytes.
- * TS_RELOAD_ON_CONSTRUCT will cost you more Flash bytes! Don't know why constructor is so heavy.
- */
- #include <stdint.h>
- #include "loki/Typelist.h"
- #include "loki/TypeManip.h"
- #ifndef TASKSCHEDULER_H_
- #define TASKSCHEDULER_H_
- //encapsulates Loki library for end user
- //Use as follows:
- //TinyScheduler< MakeTasklist<Task1, Task2, TaskN> > TaskScheduler;
- template< typename T1 = Loki::NullType, typename T2 = Loki::NullType, typename T3 = Loki::NullType,
- typename T4 = Loki::NullType, typename T5 = Loki::NullType, typename T6 = Loki::NullType,
- typename T7 = Loki::NullType, typename T8 = Loki::NullType, typename T9 = Loki::NullType,
- typename T10 = Loki::NullType, typename T11 = Loki::NullType, typename T12 = Loki::NullType,
- typename T13 = Loki::NullType, typename T14 = Loki::NullType, typename T15 = Loki::NullType,
- typename T16 = Loki::NullType >
- struct MakeTasklist {
- typedef typename Loki::TL::MakeTypelist<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::Result Result;
- };
- template<> struct MakeTasklist<>{ typedef typename Loki::TL::MakeTypelist<>::Result Result; };
- //use this flag to tell constructor do ReloadAllTimers() on scheduler instantiation
- enum{TS_RELOAD_ON_CONSTRUCT};
- //TimerResolution template param
- struct Timer8Bit{ typedef uint8_t TimerType; };
- struct Timer16Bit{ typedef uint16_t TimerType; };
- struct Timer32Bit{ typedef uint32_t TimerType; };
- //TaskDisableFeature template param
- struct TaskDisable_ON{};
- struct TaskDisable_OFF{};
- //To enable empty base optimization TaskDisable feature is moved to dedicated class
- //empty base optimization gives us 1 byte RAM when TaskDisableFeature is turned off
- //Dummy methods are also static to allow completely optimize them away.
- template<typename TList, typename TaskDisableFeature> class TaskDisableImplementation;
- template<typename TList>
- class TaskDisableImplementation<TList, TaskDisable_OFF>
- {
- protected:
- static bool IsTaskEnabled_impl(const int& i){return true;}
- static void TaskDisable_impl(const int& i){}
- static void TaskEnable_impl(const int& i){}
- };
- template<typename TList>
- class TaskDisableImplementation<TList, TaskDisable_ON>
- {
- protected:
- bool IsTaskEnabled_impl(const int& i){ return !( TaskDisableMask & (1 << i) ); }
- void TaskDisable_impl(const int& i){ TaskDisableMask |= 1 << i; }
- void TaskEnable_impl(const int& i){ TaskDisableMask &= ~(1 << i); }
- private:
- static const int TaskListLen = Loki::TL::Length< typename TList::Result >::value;
- //select type depending on task list length. To support task list of up to 16 tasks
- typename Loki::Select< (TaskListLen > 8), uint16_t, uint8_t >::Result TaskDisableMask;
- };
- template< typename TList, typename TimeService, typename TimerResolution=Timer8Bit,
- typename TaskDisableFeature=TaskDisable_OFF>
- class TinyScheduler : TaskDisableImplementation<TList, TaskDisableFeature>
- {
- typedef TaskDisableImplementation<TList, TaskDisableFeature> BaseClass;
- public:
- TinyScheduler() {};
- //this will fire up on TS_RELOAD_ON_CONSTRUCT
- TinyScheduler(const int&){ ReloadAllTaskTimers(); };
- void RunScheduled(){ RunScheduled_imp( Loki::Int2Type<TaskListLen-1>(), TimeService::GetTickCount() ); }
- template<typename T>
- void TaskDisable(const T&){ BaseClass::TaskDisable_impl( Loki::TL::IndexOf<TaskList, T>::value ); }
- template<typename T>
- void TaskEnable(const T&){ BaseClass::TaskEnable_impl( Loki::TL::IndexOf<TaskList, T>::value ); }
- template<typename T>
- void ReloadTaskTimer(const T&){ timers[ Loki::TL::IndexOf<TaskList, T>::value ] = TimeService::GetTickCount(); }
- void ReloadAllTaskTimers(){ ReloadAll_impl( Loki::Int2Type<TaskListLen-1>(), TimeService::GetTickCount() ); }
- private:
- typedef typename TList::Result TaskList;
- static const int TaskListLen = Loki::TL::Length< TaskList >::value;
- typedef typename TimerResolution::TimerType TimerT;
- TimerT timers[TaskListLen];
- TinyScheduler(const TinyScheduler&);
- TinyScheduler& operator=(const TinyScheduler&);
- //recursive iteration over TaskList and reload task timers
- template<int I>
- void ReloadAll_impl(Loki::Int2Type<I>, const TimerT& nowTicks)
- {
- ReloadAll_impl( Loki::Int2Type<I-1>(), nowTicks );
- timers[I] = nowTicks;
- }
- void ReloadAll_impl(Loki::Int2Type<0>, const TimerT& nowTicks)
- {
- timers[0] = nowTicks;
- }
- template<int I>
- void RunScheduled_imp(Loki::Int2Type<I>, const TimerT& nowTicks)
- {
- RunScheduled_imp( Loki::Int2Type<I-1>(), nowTicks );
- if( BaseClass::IsTaskEnabled_impl(I) )
- {
- typedef typename Loki::TL::TypeAt<TaskList, I>::Result Task;
- if( static_cast<TimerT>((nowTicks - timers[I])) >= Task::Period )
- {
- Task::Run();
- timers[I] = TimeService::GetTickCount();
- }
- }
- }
- void RunScheduled_imp(Loki::Int2Type<0>, const TimerT& nowTicks)
- {
- if( BaseClass::IsTaskEnabled_impl(0) )
- {
- typedef typename Loki::TL::TypeAt<TaskList, 0>::Result Task;
- if( static_cast<TimerT>((nowTicks - timers[0])) >= Task::Period )
- {
- Task::Run();
- timers[0] = TimeService::GetTickCount();
- }
- }
- }
- };
- #endif /* TASKSCHEDULER_H_ */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement