Add callback_timer support for etl::delegate (#164)

This commit is contained in:
mchodzikiewicz 2019-11-17 10:20:15 +01:00 committed by John Wellbelove
parent 1b0e9c5f9f
commit bab8cf9ba3
2 changed files with 92 additions and 7 deletions

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include "static_assert.h"
#include "timer.h"
#include "atomic.h"
#include "delegate.h"
#undef ETL_FILE
#define ETL_FILE "43"
@ -73,6 +74,9 @@ namespace etl
/// The configuration of a timer.
struct callback_timer_data
{
enum callback_type {
C_CALLBACK,IFUNCTION,DELEGATE
};
//*******************************************
callback_timer_data()
: p_callback(nullptr),
@ -82,7 +86,7 @@ namespace etl
previous(etl::timer::id::NO_TIMER),
next(etl::timer::id::NO_TIMER),
repeating(true),
has_c_callback(true)
cbk_type(IFUNCTION)
{
}
@ -100,7 +104,7 @@ namespace etl
previous(etl::timer::id::NO_TIMER),
next(etl::timer::id::NO_TIMER),
repeating(repeating_),
has_c_callback(true)
cbk_type(C_CALLBACK)
{
}
@ -118,10 +122,28 @@ namespace etl
previous(etl::timer::id::NO_TIMER),
next(etl::timer::id::NO_TIMER),
repeating(repeating_),
has_c_callback(false)
cbk_type(IFUNCTION)
{
}
//*******************************************
/// ETL delegate callback
//*******************************************
callback_timer_data(etl::timer::id::type id_,
etl::delegate<void()>& callback_,
uint32_t period_,
bool repeating_)
: p_callback(reinterpret_cast<void*>(&callback_)),
period(period_),
delta(etl::timer::state::INACTIVE),
id(id_),
previous(etl::timer::id::NO_TIMER),
next(etl::timer::id::NO_TIMER),
repeating(repeating_),
cbk_type(DELEGATE)
{
}
//*******************************************
/// Returns true if the timer is active.
//*******************************************
@ -145,7 +167,7 @@ namespace etl
uint_least8_t previous;
uint_least8_t next;
bool repeating;
bool has_c_callback;
callback_type cbk_type;
private:
@ -406,6 +428,38 @@ namespace etl
return id;
}
//*******************************************
/// Register a timer.
//*******************************************
etl::timer::id::type register_timer(etl::delegate<void()>& callback_,
uint32_t period_,
bool repeating_)
{
etl::timer::id::type id = etl::timer::id::NO_TIMER;
bool is_space = (registered_timers < MAX_TIMERS);
if (is_space)
{
// Search for the free space.
for (uint_least8_t i = 0; i < MAX_TIMERS; ++i)
{
etl::callback_timer_data& timer = timer_array[i];
if (timer.id == etl::timer::id::NO_TIMER)
{
// Create in-place.
new (&timer) callback_timer_data(i, callback_, period_, repeating_);
++registered_timers;
id = i;
break;
}
}
}
return id;
}
//*******************************************
/// Unregister a timer.
//*******************************************
@ -504,16 +558,24 @@ namespace etl
if (timer.p_callback != nullptr)
{
if (timer.has_c_callback)
if (timer.cbk_type == callback_timer_data::C_CALLBACK)
{
// Call the C callback.
reinterpret_cast<void(*)()>(timer.p_callback)();
}
else
else if(timer.cbk_type == callback_timer_data::IFUNCTION)
{
// Call the function wrapper callback.
(*reinterpret_cast<etl::ifunction<void>*>(timer.p_callback))();
}
else if(timer.cbk_type == callback_timer_data::DELEGATE)
{
// Call the function wrapper callback.
(*reinterpret_cast<etl::delegate<void()>*>(timer.p_callback))();
}
else {
ETL_ALWAYS_ASSERT("Callback timer have incorrect callback type stored")
}
}
has_active = !active_list.empty();

View File

@ -130,7 +130,7 @@ namespace
//=========================================================================
TEST(callback_timer_one_shot)
{
etl::callback_timer<3> timer_controller;
etl::callback_timer<4> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::SINGLE_SHOT);
etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::SINGLE_SHOT);
@ -646,6 +646,29 @@ namespace
CHECK_ARRAY_EQUAL(compare1.data(), free_tick_list1.data(), compare1.size());
}
class test_object{
public:
void call() {
called++;
}
size_t called = 0;
};
TEST(callback_timer_call_etl_delegate)
{
test_object test_obj;
etl::delegate<void()> delegate_callback = etl::delegate<void()>::create<test_object,&test_object::call>(test_obj);
etl::callback_timer<1> timer_controller;
timer_controller.enable(true);
etl::timer::id::type id = timer_controller.register_timer(delegate_callback, 5, etl::timer::mode::SINGLE_SHOT);
timer_controller.start(id);
timer_controller.tick(4);
CHECK(test_obj.called == 0);
timer_controller.tick(2);
CHECK(test_obj.called == 1);
}
//=========================================================================
#if REALTIME_TEST