29#ifndef ETL_MESSAGE_TIMER_INCLUDED
30#define ETL_MESSAGE_TIMER_INCLUDED
34#include "message_types.h"
36#include "message_router.h"
37#include "message_bus.h"
38#include "static_assert.h"
45#if defined(ETL_IN_UNIT_TEST) && ETL_NOT_USING_STL
46 #define ETL_DISABLE_TIMER_UPDATES
47 #define ETL_ENABLE_TIMER_UPDATES
48 #define ETL_TIMER_UPDATES_ENABLED true
50 #undef ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK
51 #undef ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK
53 #if !defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && !defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
54 #error ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK not defined
57 #if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
58 #error Only define one of ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK
61 #if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
62 #define ETL_DISABLE_TIMER_UPDATES (++process_semaphore)
63 #define ETL_ENABLE_TIMER_UPDATES (--process_semaphore)
64 #define ETL_TIMER_UPDATES_ENABLED (process_semaphore.load() == 0)
67 #if defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
68 #if !defined(ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS) || !defined(ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS)
69 #error ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS and/or ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS not defined
72 #define ETL_DISABLE_TIMER_UPDATES ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS
73 #define ETL_ENABLE_TIMER_UPDATES ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS
74 #define ETL_TIMER_UPDATES_ENABLED true
86 : p_message(ETL_NULLPTR),
87 p_router(ETL_NULLPTR),
89 delta(etl::timer::state::INACTIVE),
90 destination_router_id(etl::imessage_bus::ALL_MESSAGE_ROUTERS),
91 id(etl::timer::id::NO_TIMER),
92 previous(etl::timer::id::NO_TIMER),
93 next(etl::timer::id::NO_TIMER),
104 etl::message_router_id_t destination_router_id_ = etl::imessage_bus::ALL_MESSAGE_ROUTERS)
105 : p_message(&message_),
108 delta(etl::timer::state::INACTIVE),
109 destination_router_id(destination_router_id_),
111 previous(etl::timer::id::NO_TIMER),
112 next(etl::timer::id::NO_TIMER),
113 repeating(repeating_)
122 return delta != etl::timer::state::INACTIVE;
130 delta = etl::timer::state::INACTIVE;
137 etl::message_router_id_t destination_router_id;
138 etl::timer::id::type id;
139 uint_least8_t previous;
150 namespace private_message_timer
161 : head(etl::timer::id::NO_TIMER),
162 tail(etl::timer::id::NO_TIMER),
163 current(etl::timer::id::NO_TIMER),
171 return head == etl::timer::id::NO_TIMER;
177 void insert(etl::timer::id::type id_)
181 if (head == etl::timer::id::NO_TIMER)
186 timer.previous = etl::timer::id::NO_TIMER;
187 timer.next = etl::timer::id::NO_TIMER;
192 etl::timer::id::type test_id = begin();
194 while (test_id != etl::timer::id::NO_TIMER)
199 if (
timer.delta <= test.delta)
207 timer.previous = test.previous;
209 timer.next = test.id;
212 test.delta -=
timer.delta;
214 if (
timer.previous != etl::timer::id::NO_TIMER)
222 timer.delta -= test.delta;
225 test_id = next(test_id);
229 if (test_id == etl::timer::id::NO_TIMER)
233 timer.previous = tail;
234 timer.next = etl::timer::id::NO_TIMER;
241 void remove(etl::timer::id::type id_,
bool has_expired)
256 tail =
timer.previous;
260 ptimers[
timer.next].previous =
timer.previous;
266 if (
timer.next != etl::timer::id::NO_TIMER)
272 timer.previous = etl::timer::id::NO_TIMER;
273 timer.next = etl::timer::id::NO_TIMER;
274 timer.delta = etl::timer::state::INACTIVE;
280 return ptimers[head];
284 etl::timer::id::type begin()
291 etl::timer::id::type previous(etl::timer::id::type last)
293 current = ptimers[last].previous;
298 etl::timer::id::type next(etl::timer::id::type last)
300 current = ptimers[last].next;
307 etl::timer::id::type
id = begin();
309 while (
id != etl::timer::id::NO_TIMER)
313 timer.next = etl::timer::id::NO_TIMER;
316 head = etl::timer::id::NO_TIMER;
317 tail = etl::timer::id::NO_TIMER;
318 current = etl::timer::id::NO_TIMER;
323 etl::timer::id::type head;
324 etl::timer::id::type tail;
325 etl::timer::id::type current;
345 etl::message_router_id_t destination_router_id_ = etl::imessage_router::ALL_MESSAGE_ROUTERS)
347 etl::timer::id::type
id = etl::timer::id::NO_TIMER;
349 bool is_space = (registered_timers < MAX_TIMERS);
354 if (!router_.is_null_router())
357 for (uint_least8_t i = 0U; i < MAX_TIMERS; ++i)
361 if (
timer.
id == etl::timer::id::NO_TIMER)
383 if (id_ != etl::timer::id::NO_TIMER)
387 if (
timer.
id != etl::timer::id::NO_TIMER)
389 if (
timer.is_active())
391 ETL_DISABLE_TIMER_UPDATES;
392 active_list.remove(
timer.
id,
true);
393 ETL_ENABLE_TIMER_UPDATES;
428 ETL_DISABLE_TIMER_UPDATES;
430 ETL_ENABLE_TIMER_UPDATES;
432 for (
int i = 0; i < MAX_TIMERS; ++i)
437 registered_timers = 0;
446 bool tick(uint32_t count)
450 if (ETL_TIMER_UPDATES_ENABLED)
453 bool has_active = !active_list.empty();
457 while (has_active && (count >= active_list.front().delta))
461 count -=
timer.delta;
463 active_list.remove(
timer.
id,
true);
471 if (timer.p_router != ETL_NULLPTR)
473 timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
476 has_active = !active_list.empty();
482 active_list.front().delta -= count;
496 bool start(etl::timer::id::type id_,
bool immediate_ =
false)
501 if (id_ != etl::timer::id::NO_TIMER)
506 if (
timer.
id != etl::timer::id::NO_TIMER)
509 if (
timer.period != etl::timer::state::INACTIVE)
511 ETL_DISABLE_TIMER_UPDATES;
512 if (
timer.is_active())
514 active_list.remove(
timer.
id,
false);
519 ETL_ENABLE_TIMER_UPDATES;
532 bool stop(etl::timer::id::type id_)
537 if (id_ != etl::timer::id::NO_TIMER)
542 if (
timer.
id != etl::timer::id::NO_TIMER)
544 if (
timer.is_active())
546 ETL_DISABLE_TIMER_UPDATES;
547 active_list.remove(
timer.
id,
false);
548 ETL_ENABLE_TIMER_UPDATES;
565 timer_array[id_].period = period_;
575 bool set_mode(etl::timer::id::type id_,
bool repeating_)
579 timer_array[id_].repeating = repeating_;
592 : timer_array(timer_array_),
593 active_list(timer_array_),
595#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
596 process_semaphore(0),
598 registered_timers(0),
599 MAX_TIMERS(MAX_TIMERS_)
620#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
622#if defined(ETL_TIMER_SEMAPHORE_TYPE)
623 typedef ETL_TIMER_SEMAPHORE_TYPE timer_semaphore_t;
626 typedef etl::atomic_uint16_t timer_semaphore_t;
628 #error No atomic type available
632 etl::timer_semaphore_t process_semaphore;
634 uint_least8_t registered_timers;
638 const uint_least8_t MAX_TIMERS;
644 template <u
int_least8_t MAX_TIMERS_>
649 ETL_STATIC_ASSERT(MAX_TIMERS_ <= 254,
"No more than 254 timers are allowed");
665#undef ETL_DISABLE_TIMER_UPDATES
666#undef ETL_ENABLE_TIMER_UPDATES
667#undef ETL_TIMER_UPDATES_ENABLED
This is the base of all message routers.
Definition: message_router_generator.h:121
Interface for message timer.
Definition: message_timer.h:335
void enable(bool state_)
Enable/disable the timer.
Definition: message_timer.h:410
bool start(etl::timer::id::type id_, bool immediate_=false)
Starts a timer.
Definition: message_timer.h:496
bool unregister_timer(etl::timer::id::type id_)
Unregister a timer.
Definition: message_timer.h:379
etl::timer::id::type register_timer(const etl::imessage &message_, etl::imessage_router &router_, uint32_t period_, bool repeating_, etl::message_router_id_t destination_router_id_=etl::imessage_router::ALL_MESSAGE_ROUTERS)
Register a timer.
Definition: message_timer.h:341
bool is_running() const
Get the enable/disable state.
Definition: message_timer.h:418
bool set_mode(etl::timer::id::type id_, bool repeating_)
Sets a timer's mode.
Definition: message_timer.h:575
imessage_timer(message_timer_data *const timer_array_, const uint_least8_t MAX_TIMERS_)
Constructor.
Definition: message_timer.h:591
void clear()
Clears the timer of data.
Definition: message_timer.h:426
bool stop(etl::timer::id::type id_)
Stops a timer.
Definition: message_timer.h:532
~imessage_timer()
Destructor.
Definition: message_timer.h:606
bool set_period(etl::timer::id::type id_, uint32_t period_)
Sets a timer's period.
Definition: message_timer.h:561
The message timer.
Definition: message_timer.h:646
message_timer()
Constructor.
Definition: message_timer.h:654
A specialised intrusive linked list for timer data.
Definition: message_timer.h:156
bitset_ext
Definition: absolute.h:38
The configuration of a timer.
Definition: message_timer.h:83
bool is_active() const
Returns true if the timer is active.
Definition: message_timer.h:120
void set_inactive()
Sets the timer to the inactive state.
Definition: message_timer.h:128
Common definitions for the timer framework.
Definition: timer.h:55