29 #ifndef ETL_CALLBACK_TIMER_INCLUDED
30 #define ETL_CALLBACK_TIMER_INCLUDED
38 #include "static_assert.h"
44 #if ETL_CPP11_SUPPORTED
51 #if defined(ETL_IN_UNIT_TEST) && ETL_NOT_USING_STL
52 #define ETL_DISABLE_TIMER_UPDATES
53 #define ETL_ENABLE_TIMER_UPDATES
54 #define ETL_TIMER_UPDATES_ENABLED true
56 #undef ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK
57 #undef ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK
59 #if !defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK) && !defined(ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK)
60 #error ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK or ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK not defined
63 #if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK) && defined(ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK)
64 #error Only define one of ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK or ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK
67 #if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK)
68 #define ETL_DISABLE_TIMER_UPDATES (++process_semaphore)
69 #define ETL_ENABLE_TIMER_UPDATES (--process_semaphore)
70 #define ETL_TIMER_UPDATES_ENABLED (process_semaphore.load() == 0)
74 #if defined(ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK)
75 #if !defined(ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS) || !defined(ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS)
76 #error ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS and/or ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS not defined
79 #define ETL_DISABLE_TIMER_UPDATES (ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS)
80 #define ETL_ENABLE_TIMER_UPDATES (ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS)
81 #define ETL_TIMER_UPDATES_ENABLED true
99 : p_callback(ETL_NULLPTR),
101 delta(etl::timer::state::INACTIVE),
102 id(etl::timer::id::NO_TIMER),
103 previous(etl::timer::id::NO_TIMER),
104 next(etl::timer::id::NO_TIMER),
114 void (*p_callback_)(),
117 : p_callback(reinterpret_cast<void*>(p_callback_)),
123 repeating(repeating_),
135 : p_callback(reinterpret_cast<void*>(&callback_)),
141 repeating(repeating_),
146 #if ETL_CPP11_SUPPORTED
154 : p_callback(reinterpret_cast<void*>(&callback_)),
160 repeating(repeating_),
171 return delta != etl::timer::state::INACTIVE;
179 delta = etl::timer::state::INACTIVE;
185 etl::timer::id::type id;
186 uint_least8_t previous;
189 callback_type cbk_type;
198 namespace private_callback_timer
209 : head(etl::timer::id::NO_TIMER),
210 tail(etl::timer::id::NO_TIMER),
211 current(etl::timer::id::NO_TIMER),
219 return head == etl::timer::id::NO_TIMER;
225 void insert(etl::timer::id::type id_)
229 if (head == etl::timer::id::NO_TIMER)
234 timer.previous = etl::timer::id::NO_TIMER;
235 timer.next = etl::timer::id::NO_TIMER;
240 etl::timer::id::type test_id = begin();
242 while (test_id != etl::timer::id::NO_TIMER)
247 if (
timer.delta <= test.delta)
255 timer.previous = test.previous;
257 timer.next = test.id;
260 test.delta -=
timer.delta;
262 if (
timer.previous != etl::timer::id::NO_TIMER)
270 timer.delta -= test.delta;
273 test_id = next(test_id);
277 if (test_id == etl::timer::id::NO_TIMER)
281 timer.previous = tail;
282 timer.next = etl::timer::id::NO_TIMER;
289 void remove(etl::timer::id::type id_,
bool has_expired)
304 tail =
timer.previous;
308 ptimers[
timer.next].previous =
timer.previous;
314 if (
timer.next != etl::timer::id::NO_TIMER)
320 timer.previous = etl::timer::id::NO_TIMER;
321 timer.next = etl::timer::id::NO_TIMER;
322 timer.delta = etl::timer::state::INACTIVE;
328 return ptimers[head];
332 etl::timer::id::type begin()
339 etl::timer::id::type previous(etl::timer::id::type last)
341 current = ptimers[last].previous;
346 etl::timer::id::type next(etl::timer::id::type last)
348 current = ptimers[last].next;
355 etl::timer::id::type
id = begin();
357 while (
id != etl::timer::id::NO_TIMER)
361 timer.next = etl::timer::id::NO_TIMER;
364 head = etl::timer::id::NO_TIMER;
365 tail = etl::timer::id::NO_TIMER;
366 current = etl::timer::id::NO_TIMER;
371 etl::timer::id::type head;
372 etl::timer::id::type tail;
373 etl::timer::id::type current;
393 etl::timer::id::type
id = etl::timer::id::NO_TIMER;
395 bool is_space = (registered_timers < MAX_TIMERS);
400 for (uint_least8_t i = 0; i < MAX_TIMERS; ++i)
404 if (
timer.
id == etl::timer::id::NO_TIMER)
425 etl::timer::id::type
id = etl::timer::id::NO_TIMER;
427 bool is_space = (registered_timers < MAX_TIMERS);
432 for (uint_least8_t i = 0; i < MAX_TIMERS; ++i)
436 if (
timer.
id == etl::timer::id::NO_TIMER)
453 #if ETL_CPP11_SUPPORTED
458 etl::timer::id::type
id = etl::timer::id::NO_TIMER;
460 bool is_space = (registered_timers < MAX_TIMERS);
465 for (uint_least8_t i = 0; i < MAX_TIMERS; ++i)
469 if (
timer.
id == etl::timer::id::NO_TIMER)
491 if (id_ != etl::timer::id::NO_TIMER)
495 if (
timer.
id != etl::timer::id::NO_TIMER)
497 if (
timer.is_active())
499 ETL_DISABLE_TIMER_UPDATES;
500 active_list.remove(
timer.
id,
false);
501 ETL_ENABLE_TIMER_UPDATES;
536 ETL_DISABLE_TIMER_UPDATES;
538 ETL_ENABLE_TIMER_UPDATES;
540 for (
int i = 0; i < MAX_TIMERS; ++i)
545 registered_timers = 0;
554 bool tick(uint32_t count)
558 if (ETL_TIMER_UPDATES_ENABLED)
561 bool has_active = !active_list.empty();
565 while (has_active && (count >= active_list.front().delta))
569 count -=
timer.delta;
571 active_list.remove(
timer.
id,
true);
580 if (timer.p_callback != ETL_NULLPTR)
582 if (timer.cbk_type == callback_timer_data::C_CALLBACK)
585 reinterpret_cast<void(*)()
>(timer.p_callback)();
587 else if(timer.cbk_type == callback_timer_data::IFUNCTION)
592 #if ETL_CPP11_SUPPORTED
593 else if(timer.cbk_type == callback_timer_data::DELEGATE)
596 (*
reinterpret_cast<etl::delegate<
void()
>*>(timer.p_callback))();
601 has_active = !active_list.empty();
607 active_list.front().delta -= count;
621 bool start(etl::timer::id::type id_,
bool immediate_ =
false)
626 if (id_ != etl::timer::id::NO_TIMER)
631 if (
timer.
id != etl::timer::id::NO_TIMER)
634 if (
timer.period != etl::timer::state::INACTIVE)
636 ETL_DISABLE_TIMER_UPDATES;
637 if (
timer.is_active())
639 active_list.remove(
timer.
id,
false);
644 ETL_ENABLE_TIMER_UPDATES;
657 bool stop(etl::timer::id::type id_)
662 if (id_ != etl::timer::id::NO_TIMER)
667 if (
timer.
id != etl::timer::id::NO_TIMER)
669 if (
timer.is_active())
671 ETL_DISABLE_TIMER_UPDATES;
672 active_list.remove(
timer.
id,
false);
673 ETL_ENABLE_TIMER_UPDATES;
690 timer_array[id_].period = period_;
700 bool set_mode(etl::timer::id::type id_,
bool repeating_)
704 timer_array[id_].repeating = repeating_;
717 : timer_array(timer_array_),
718 active_list(timer_array_),
720 #if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK)
721 process_semaphore(0),
723 registered_timers(0),
724 MAX_TIMERS(MAX_TIMERS_)
736 volatile bool enabled;
737 #if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK)
740 volatile uint_least8_t registered_timers;
744 const uint_least8_t MAX_TIMERS;
750 template <const u
int_least8_t MAX_TIMERS_>
755 ETL_STATIC_ASSERT(MAX_TIMERS_ <= 254,
"No more than 254 timers are allowed");
771 #undef ETL_DISABLE_TIMER_UPDATES
772 #undef ETL_ENABLE_TIMER_UPDATES
773 #undef ETL_TIMER_UPDATES_ENABLED
For all types except bool and pointers.
Definition: atomic_gcc_sync.h:69
The callback timer.
Definition: callback_timer.h:752
callback_timer()
Constructor.
Definition: callback_timer.h:760
Definition: delegate.h:91
Interface for callback timer.
Definition: callback_timer.h:383
bool unregister_timer(etl::timer::id::type id_)
Register a timer.
Definition: callback_timer.h:487
bool is_running() const
Get the enable/disable state.
Definition: callback_timer.h:526
bool set_period(etl::timer::id::type id_, uint32_t period_)
Sets a timer's period.
Definition: callback_timer.h:686
etl::timer::id::type register_timer(void(*p_callback_)(), uint32_t period_, bool repeating_)
Register a timer.
Definition: callback_timer.h:389
bool start(etl::timer::id::type id_, bool immediate_=false)
Starts a timer.
Definition: callback_timer.h:621
icallback_timer(callback_timer_data *const timer_array_, const uint_least8_t MAX_TIMERS_)
Constructor.
Definition: callback_timer.h:716
bool set_mode(etl::timer::id::type id_, bool repeating_)
Sets a timer's mode.
Definition: callback_timer.h:700
bool stop(etl::timer::id::type id_)
Stops a timer.
Definition: callback_timer.h:657
void enable(bool state_)
Enable/disable the timer.
Definition: callback_timer.h:518
etl::timer::id::type register_timer(etl::ifunction< void > &callback_, uint32_t period_, bool repeating_)
Register a timer.
Definition: callback_timer.h:421
void clear()
Clears the timer of data.
Definition: callback_timer.h:534
A specialised intrusive linked list for timer data.
Definition: callback_timer.h:204
Definition: function.h:73
Definition: absolute.h:37
The configuration of a timer.
Definition: callback_timer.h:89
callback_timer_data(etl::timer::id::type id_, void(*p_callback_)(), uint32_t period_, bool repeating_)
C function callback.
Definition: callback_timer.h:113
callback_timer_data(etl::timer::id::type id_, etl::ifunction< void > &callback_, uint32_t period_, bool repeating_)
ETL function callback.
Definition: callback_timer.h:131
bool is_active() const
Returns true if the timer is active.
Definition: callback_timer.h:169
void set_inactive()
Sets the timer to the inactive state.
Definition: callback_timer.h:177
Common definitions for the timer framework.
Definition: timer.h:54