29 #ifndef ETL_MESSAGE_TIMER_INCLUDED
30 #define ETL_MESSAGE_TIMER_INCLUDED
37 #include "message_types.h"
39 #include "message_router.h"
40 #include "message_bus.h"
41 #include "static_assert.h"
48 #if defined(ETL_IN_UNIT_TEST) && ETL_NOT_USING_STL
49 #define ETL_DISABLE_TIMER_UPDATES
50 #define ETL_ENABLE_TIMER_UPDATES
51 #define ETL_TIMER_UPDATES_ENABLED true
53 #undef ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK
54 #undef ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK
56 #if !defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && !defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
57 #error ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK not defined
60 #if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
61 #error Only define one of ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK
64 #if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
65 #define ETL_DISABLE_TIMER_UPDATES (++process_semaphore)
66 #define ETL_ENABLE_TIMER_UPDATES (--process_semaphore)
67 #define ETL_TIMER_UPDATES_ENABLED (process_semaphore.load() == 0)
70 #if defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
71 #if !defined(ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS) || !defined(ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS)
72 #error ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS and/or ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS not defined
75 #define ETL_DISABLE_TIMER_UPDATES (ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS)
76 #define ETL_ENABLE_TIMER_UPDATES (ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS)
77 #define ETL_TIMER_UPDATES_ENABLED true
89 : p_message(ETL_NULLPTR),
90 p_router(ETL_NULLPTR),
92 delta(etl::timer::state::INACTIVE),
93 destination_router_id(etl::imessage_bus::ALL_MESSAGE_ROUTERS),
94 id(etl::timer::id::NO_TIMER),
95 previous(etl::timer::id::NO_TIMER),
96 next(etl::timer::id::NO_TIMER),
107 etl::message_router_id_t destination_router_id_ = etl::imessage_bus::ALL_MESSAGE_ROUTERS)
108 : p_message(&message_),
111 delta(etl::timer::state::INACTIVE),
112 destination_router_id(destination_router_id_),
114 previous(etl::timer::id::NO_TIMER),
115 next(etl::timer::id::NO_TIMER),
116 repeating(repeating_)
125 return delta != etl::timer::state::INACTIVE;
133 delta = etl::timer::state::INACTIVE;
140 etl::message_router_id_t destination_router_id;
141 etl::timer::id::type id;
142 uint_least8_t previous;
153 namespace private_message_timer
164 : head(etl::timer::id::NO_TIMER),
165 tail(etl::timer::id::NO_TIMER),
166 current(etl::timer::id::NO_TIMER),
174 return head == etl::timer::id::NO_TIMER;
180 void insert(etl::timer::id::type id_)
184 if (head == etl::timer::id::NO_TIMER)
189 timer.previous = etl::timer::id::NO_TIMER;
190 timer.next = etl::timer::id::NO_TIMER;
195 etl::timer::id::type test_id = begin();
197 while (test_id != etl::timer::id::NO_TIMER)
202 if (
timer.delta <= test.delta)
210 timer.previous = test.previous;
212 timer.next = test.id;
215 test.delta -=
timer.delta;
217 if (
timer.previous != etl::timer::id::NO_TIMER)
225 timer.delta -= test.delta;
228 test_id = next(test_id);
232 if (test_id == etl::timer::id::NO_TIMER)
236 timer.previous = tail;
237 timer.next = etl::timer::id::NO_TIMER;
244 void remove(etl::timer::id::type id_,
bool has_expired)
259 tail =
timer.previous;
263 ptimers[
timer.next].previous =
timer.previous;
269 if (
timer.next != etl::timer::id::NO_TIMER)
275 timer.previous = etl::timer::id::NO_TIMER;
276 timer.next = etl::timer::id::NO_TIMER;
277 timer.delta = etl::timer::state::INACTIVE;
283 return ptimers[head];
287 etl::timer::id::type begin()
294 etl::timer::id::type previous(etl::timer::id::type last)
296 current = ptimers[last].previous;
301 etl::timer::id::type next(etl::timer::id::type last)
303 current = ptimers[last].next;
310 etl::timer::id::type
id = begin();
312 while (
id != etl::timer::id::NO_TIMER)
316 timer.next = etl::timer::id::NO_TIMER;
319 head = etl::timer::id::NO_TIMER;
320 tail = etl::timer::id::NO_TIMER;
321 current = etl::timer::id::NO_TIMER;
326 etl::timer::id::type head;
327 etl::timer::id::type tail;
328 etl::timer::id::type current;
348 etl::message_router_id_t destination_router_id_ = etl::imessage_router::ALL_MESSAGE_ROUTERS)
350 etl::timer::id::type
id = etl::timer::id::NO_TIMER;
352 bool is_space = (registered_timers < MAX_TIMERS);
357 if (!router_.is_null_router())
360 for (uint_least8_t i = 0; i < MAX_TIMERS; ++i)
364 if (
timer.
id == etl::timer::id::NO_TIMER)
386 if (id_ != etl::timer::id::NO_TIMER)
390 if (
timer.
id != etl::timer::id::NO_TIMER)
392 if (
timer.is_active())
394 ETL_DISABLE_TIMER_UPDATES;
395 active_list.remove(
timer.
id,
true);
396 ETL_ENABLE_TIMER_UPDATES;
431 ETL_DISABLE_TIMER_UPDATES;
433 ETL_ENABLE_TIMER_UPDATES;
435 for (
int i = 0; i < MAX_TIMERS; ++i)
440 registered_timers = 0;
449 bool tick(uint32_t count)
453 if (ETL_TIMER_UPDATES_ENABLED)
456 bool has_active = !active_list.empty();
460 while (has_active && (count >= active_list.front().delta))
464 count -=
timer.delta;
466 active_list.remove(
timer.
id,
true);
474 if (timer.p_router != ETL_NULLPTR)
477 timer.p_router->receive(nmr, timer.destination_router_id, *(timer.p_message));
480 has_active = !active_list.empty();
486 active_list.front().delta -= count;
500 bool start(etl::timer::id::type id_,
bool immediate_ =
false)
505 if (id_ != etl::timer::id::NO_TIMER)
510 if (
timer.
id != etl::timer::id::NO_TIMER)
513 if (
timer.period != etl::timer::state::INACTIVE)
515 ETL_DISABLE_TIMER_UPDATES;
516 if (
timer.is_active())
518 active_list.remove(
timer.
id,
false);
523 ETL_ENABLE_TIMER_UPDATES;
536 bool stop(etl::timer::id::type id_)
541 if (id_ != etl::timer::id::NO_TIMER)
546 if (
timer.
id != etl::timer::id::NO_TIMER)
548 if (
timer.is_active())
550 ETL_DISABLE_TIMER_UPDATES;
551 active_list.remove(
timer.
id,
false);
552 ETL_ENABLE_TIMER_UPDATES;
569 timer_array[id_].period = period_;
579 bool set_mode(etl::timer::id::type id_,
bool repeating_)
583 timer_array[id_].repeating = repeating_;
596 : timer_array(timer_array_),
597 active_list(timer_array_),
599 #if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
600 process_semaphore(0),
602 registered_timers(0),
603 MAX_TIMERS(MAX_TIMERS_)
622 volatile bool enabled;
624 #if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
627 volatile uint_least8_t registered_timers;
631 const uint_least8_t MAX_TIMERS;
637 template <u
int_least8_t MAX_TIMERS_>
642 ETL_STATIC_ASSERT(MAX_TIMERS_ <= 254,
"No more than 254 timers are allowed");
658 #undef ETL_DISABLE_TIMER_UPDATES
659 #undef ETL_ENABLE_TIMER_UPDATES
660 #undef ETL_TIMER_UPDATES_ENABLED
For all types except bool and pointers.
Definition: atomic_gcc_sync.h:69
This is the base of all message routers.
Definition: message_router_generator.h:114
Interface for message timer.
Definition: message_timer.h:338
void enable(bool state_)
Enable/disable the timer.
Definition: message_timer.h:413
bool start(etl::timer::id::type id_, bool immediate_=false)
Starts a timer.
Definition: message_timer.h:500
bool unregister_timer(etl::timer::id::type id_)
Unregister a timer.
Definition: message_timer.h:382
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:344
bool is_running() const
Get the enable/disable state.
Definition: message_timer.h:421
bool set_mode(etl::timer::id::type id_, bool repeating_)
Sets a timer's mode.
Definition: message_timer.h:579
imessage_timer(message_timer_data *const timer_array_, const uint_least8_t MAX_TIMERS_)
Constructor.
Definition: message_timer.h:595
void clear()
Clears the timer of data.
Definition: message_timer.h:429
bool stop(etl::timer::id::type id_)
Stops a timer.
Definition: message_timer.h:536
~imessage_timer()
Destructor.
Definition: message_timer.h:610
bool set_period(etl::timer::id::type id_, uint32_t period_)
Sets a timer's period.
Definition: message_timer.h:565
The message timer.
Definition: message_timer.h:639
message_timer()
Constructor.
Definition: message_timer.h:647
This router can be used as a sink for messages or a 'null source' router.
Definition: message_router_generator.h:194
A specialised intrusive linked list for timer data.
Definition: message_timer.h:159
Definition: absolute.h:37
The configuration of a timer.
Definition: message_timer.h:86
bool is_active() const
Returns true if the timer is active.
Definition: message_timer.h:123
void set_inactive()
Sets the timer to the inactive state.
Definition: message_timer.h:131
Common definitions for the timer framework.
Definition: timer.h:54