29#ifndef ETL_MESSAGE_TIMER_INCLUDED
30#define ETL_MESSAGE_TIMER_INCLUDED
37#include "message_bus.h"
38#include "message_router.h"
39#include "message_types.h"
41#include "static_assert.h"
46#if defined(ETL_IN_UNIT_TEST) && ETL_NOT_USING_STL
47 #define ETL_DISABLE_TIMER_UPDATES
48 #define ETL_ENABLE_TIMER_UPDATES
49 #define ETL_TIMER_UPDATES_ENABLED true
51 #undef ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK
52 #undef ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK
54 #if !defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && !defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
55 #error ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK not defined
58 #if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
59 #error Only define one of ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK
62 #if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
63 #define ETL_DISABLE_TIMER_UPDATES (++process_semaphore)
64 #define ETL_ENABLE_TIMER_UPDATES (--process_semaphore)
65 #define ETL_TIMER_UPDATES_ENABLED (process_semaphore.load() == 0)
68 #if defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK)
69 #if !defined(ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS) || !defined(ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS)
70 #error ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS and/or ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS not defined
73 #define ETL_DISABLE_TIMER_UPDATES ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS
74 #define ETL_ENABLE_TIMER_UPDATES ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS
75 #define ETL_TIMER_UPDATES_ENABLED true
83 struct message_timer_data
87 : p_message(ETL_NULLPTR)
88 , p_router(ETL_NULLPTR)
90 , delta(etl::timer::state::Inactive)
91 , destination_router_id(etl::imessage_bus::ALL_MESSAGE_ROUTERS)
92 , id(etl::timer::id::NO_TIMER)
93 , previous(etl::timer::id::NO_TIMER)
94 , next(etl::timer::id::NO_TIMER)
101 etl::message_router_id_t destination_router_id_ = etl::imessage_bus::ALL_MESSAGE_ROUTERS)
102 : p_message(&message_)
103 , p_router(&irouter_)
105 , delta(etl::timer::state::Inactive)
106 , destination_router_id(destination_router_id_)
108 , previous(etl::timer::id::NO_TIMER)
109 , next(etl::timer::id::NO_TIMER)
110 , repeating(repeating_)
119 return delta != etl::timer::state::Inactive;
127 delta = etl::timer::state::Inactive;
134 etl::message_router_id_t destination_router_id;
135 etl::timer::id::type id;
136 uint_least8_t previous;
147 namespace private_message_timer
158 : head(etl::timer::id::NO_TIMER)
159 , tail(etl::timer::id::NO_TIMER)
160 , current(etl::timer::id::NO_TIMER)
168 return head == etl::timer::id::NO_TIMER;
174 void insert(etl::timer::id::type id_)
178 if (head == etl::timer::id::NO_TIMER)
183 timer.previous = etl::timer::id::NO_TIMER;
184 timer.next = etl::timer::id::NO_TIMER;
189 etl::timer::id::type test_id = begin();
191 while (test_id != etl::timer::id::NO_TIMER)
196 if (
timer.delta <= test.delta)
204 timer.previous = test.previous;
206 timer.next = test.id;
209 test.delta -=
timer.delta;
211 if (
timer.previous != etl::timer::id::NO_TIMER)
219 timer.delta -= test.delta;
222 test_id = next(test_id);
226 if (test_id == etl::timer::id::NO_TIMER)
230 timer.previous = tail;
231 timer.next = etl::timer::id::NO_TIMER;
238 void remove(etl::timer::id::type id_,
bool has_expired)
253 tail =
timer.previous;
257 ptimers[
timer.next].previous =
timer.previous;
263 if (
timer.next != etl::timer::id::NO_TIMER)
269 timer.previous = etl::timer::id::NO_TIMER;
270 timer.next = etl::timer::id::NO_TIMER;
271 timer.delta = etl::timer::state::Inactive;
277 return ptimers[head];
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;
341 typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
347 etl::message_router_id_t destination_router_id_ = etl::imessage_router::ALL_MESSAGE_ROUTERS)
349 etl::timer::id::type
id = etl::timer::id::NO_TIMER;
351 bool is_space = (registered_timers < Max_Timers);
356 if (!router_.is_null_router())
359 for (uint_least8_t i = 0U; i < Max_Timers; ++i)
363 if (
timer.
id == etl::timer::id::NO_TIMER)
385 if (id_ != etl::timer::id::NO_TIMER)
389 if (
timer.
id != etl::timer::id::NO_TIMER)
391 if (
timer.is_active())
393 ETL_DISABLE_TIMER_UPDATES;
394 active_list.remove(
timer.
id,
true);
395 remove_callback.call_if(
timer.
id);
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);
467 remove_callback.call_if(
timer.
id);
473 insert_callback.call_if(
timer.
id);
476 if (timer.p_router != ETL_NULLPTR)
478 timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
481 has_active = !active_list.empty();
487 active_list.front().delta -= count;
501 bool start(etl::timer::id::type id_,
bool immediate_ =
false)
506 if (id_ != etl::timer::id::NO_TIMER)
511 if (
timer.
id != etl::timer::id::NO_TIMER)
514 if (
timer.period != etl::timer::state::Inactive)
516 ETL_DISABLE_TIMER_UPDATES;
517 if (
timer.is_active())
519 active_list.remove(
timer.
id,
false);
520 remove_callback.call_if(
timer.
id);
525 insert_callback.call_if(
timer.
id);
526 ETL_ENABLE_TIMER_UPDATES;
539 bool stop(etl::timer::id::type id_)
544 if (id_ != etl::timer::id::NO_TIMER)
549 if (
timer.
id != etl::timer::id::NO_TIMER)
551 if (
timer.is_active())
553 ETL_DISABLE_TIMER_UPDATES;
554 active_list.remove(
timer.
id,
false);
555 remove_callback.call_if(
timer.
id);
556 ETL_ENABLE_TIMER_UPDATES;
573 timer_array[id_].period = period_;
583 bool set_mode(etl::timer::id::type id_,
bool repeating_)
587 timer_array[id_].repeating = repeating_;
599 ETL_DISABLE_TIMER_UPDATES;
600 bool result = !active_list.empty();
601 ETL_ENABLE_TIMER_UPDATES;
613 uint32_t delta =
static_cast<uint32_t
>(etl::timer::interval::No_Active_Interval);
615 ETL_DISABLE_TIMER_UPDATES;
616 if (!active_list.empty())
618 delta = active_list.front().delta;
620 ETL_ENABLE_TIMER_UPDATES;
630 insert_callback = insert_;
638 remove_callback = remove_;
642 void clear_insert_callback()
644 insert_callback.clear();
648 void clear_remove_callback()
650 remove_callback.clear();
659 : timer_array(timer_array_)
660 , active_list(timer_array_)
663#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
668 , Max_Timers(Max_Timers_)
687#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK)
689 #if defined(ETL_TIMER_SEMAPHORE_TYPE)
690 typedef ETL_TIMER_SEMAPHORE_TYPE timer_semaphore_t;
693 typedef etl::atomic_uint16_t timer_semaphore_t;
695 #error No atomic type available
699 mutable etl::timer_semaphore_t process_semaphore;
701 uint_least8_t registered_timers;
703 event_callback_type insert_callback;
704 event_callback_type remove_callback;
708 const uint_least8_t Max_Timers;
714 template <u
int_least8_t Max_Timers_>
719 ETL_STATIC_ASSERT(Max_Timers_ <= 254,
"No more than 254 timers are allowed");
735#undef ETL_DISABLE_TIMER_UPDATES
736#undef ETL_ENABLE_TIMER_UPDATES
737#undef ETL_TIMER_UPDATES_ENABLED
Declaration.
Definition delegate_cpp03.h:191
This is the base of all message routers.
Definition message_router.h:138
Interface for message timer.
Definition message_timer.h:338
uint32_t time_to_next() const
Definition message_timer.h:611
bool has_active_timer() const
Check if there is an active timer.
Definition message_timer.h:597
void set_remove_callback(event_callback_type remove_)
Set a callback when a timer is removed from list.
Definition message_timer.h:636
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:501
bool unregister_timer(etl::timer::id::type id_)
Unregister a timer.
Definition message_timer.h:381
imessage_timer(message_timer_data *const timer_array_, const uint_least8_t Max_Timers_)
Constructor.
Definition message_timer.h:658
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:346
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:583
void set_insert_callback(event_callback_type insert_)
Set a callback when a timer is inserted on list.
Definition message_timer.h:628
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:539
~imessage_timer()
Destructor.
Definition message_timer.h:675
bool set_period(etl::timer::id::type id_, uint32_t period_)
Sets a timer's period.
Definition message_timer.h:569
message_timer()
Constructor.
Definition message_timer.h:724
A specialised intrusive linked list for timer data.
Definition message_timer.h:153
bitset_ext
Definition absolute.h:40
The configuration of a timer.
Definition message_timer.h:84
bool is_active() const
Returns true if the timer is active.
Definition message_timer.h:117
void set_inactive()
Sets the timer to the inactive state.
Definition message_timer.h:125
Common definitions for the timer framework.
Definition timer.h:55