Merge remote-tracking branch 'origin/development'

# Conflicts:
#	include/etl/version.h
This commit is contained in:
John Wellbelove 2018-06-17 22:15:05 +01:00
commit 2ce91a95ec
5 changed files with 143 additions and 60 deletions

View File

@ -238,21 +238,30 @@ namespace etl
/// Starts the FSM.
/// Can only be called once.
/// Subsequent calls will do nothing.
///\param call_on_enter_state If true will call on_enter_state() for the first state. Default = true.
///\param call_on_enter_state If will call on_enter_state() for the first state. Default = true.
//*******************************************
void start(bool call_on_enter_state = true)
{
// Can only be started once.
if (p_state == nullptr)
{
p_state = state_list[0];
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
// Can only be started once.
if (p_state == nullptr)
{
p_state = state_list[0];
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
if (call_on_enter_state)
{
p_state->on_enter_state();
}
}
if (call_on_enter_state)
{
etl::fsm_state_id_t next_state_id;
etl::ifsm_state* p_last_state;
do
{
p_last_state = p_state;
next_state_id = p_state->on_enter_state();
p_state = state_list[next_state_id];
} while (p_last_state != p_state);
}
}
}
//*******************************************
@ -260,7 +269,7 @@ namespace etl
//*******************************************
void receive(const etl::imessage& message)
{
etl::null_message_router nmr;
static etl::null_message_router nmr;
receive(nmr, message);
}
@ -269,26 +278,26 @@ namespace etl
//*******************************************
void receive(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
etl::ifsm_state* p_next_state = state_list[next_state_id];
etl::ifsm_state* p_next_state = state_list[next_state_id];
// Have we changed state?
if (p_next_state != p_state)
{
do
// Have we changed state?
if (p_next_state != p_state)
{
p_state->on_exit_state();
p_state = p_next_state;
do
{
p_state->on_exit_state();
p_state = p_next_state;
next_state_id = p_state->on_enter_state();
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
next_state_id = p_state->on_enter_state();
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
p_next_state = state_list[next_state_id];
p_next_state = state_list[next_state_id];
} while (p_next_state != p_state); // Have we changed state again?
}
} while (p_next_state != p_state); // Have we changed state again?
}
}
using imessage_router::accepts;

View File

@ -254,17 +254,26 @@ namespace etl
//*******************************************
void start(bool call_on_enter_state = true)
{
// Can only be started once.
if (p_state == nullptr)
{
p_state = state_list[0];
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
// Can only be started once.
if (p_state == nullptr)
{
p_state = state_list[0];
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
if (call_on_enter_state)
{
p_state->on_enter_state();
}
}
if (call_on_enter_state)
{
etl::fsm_state_id_t next_state_id;
etl::ifsm_state* p_last_state;
do
{
p_last_state = p_state;
next_state_id = p_state->on_enter_state();
p_state = state_list[next_state_id];
} while (p_last_state != p_state);
}
}
}
//*******************************************
@ -272,7 +281,7 @@ namespace etl
//*******************************************
void receive(const etl::imessage& message)
{
etl::null_message_router nmr;
static etl::null_message_router nmr;
receive(nmr, message);
}
@ -281,26 +290,26 @@ namespace etl
//*******************************************
void receive(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
etl::ifsm_state* p_next_state = state_list[next_state_id];
etl::ifsm_state* p_next_state = state_list[next_state_id];
// Have we changed state?
if (p_next_state != p_state)
{
do
// Have we changed state?
if (p_next_state != p_state)
{
p_state->on_exit_state();
p_state = p_next_state;
do
{
p_state->on_exit_state();
p_state = p_next_state;
next_state_id = p_state->on_enter_state();
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
next_state_id = p_state->on_enter_state();
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
p_next_state = state_list[next_state_id];
p_next_state = state_list[next_state_id];
} while (p_next_state != p_state); // Have we changed state again?
}
} while (p_next_state != p_state); // Have we changed state again?
}
}
using imessage_router::accepts;

View File

@ -76,12 +76,10 @@ namespace etl
const etl::message_id_t message_id;
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
public:
virtual ~imessage()
{
}
#else
protected:
~imessage()
{
}

View File

@ -37,10 +37,10 @@ SOFTWARE.
/// Definitions of the ETL version
///\ingroup utilities
#define ETL_VERSION "11.11.1"
#define ETL_VERSION "11.11.2"
#define ETL_VERSION_MAJOR 11
#define ETL_VERSION_MINOR 11
#define ETL_VERSION_PATCH 1
#define ETL_VERSION_PATCH 2
#endif

View File

@ -31,9 +31,12 @@ SOFTWARE.
#include "fsm.h"
#include "enum_type.h"
#include "container.h"
#include "packet.h"
#include "queue.h"
#include <iostream>
namespace
{
const etl::message_router_id_t MOTOR_CONTROL = 0;
@ -49,6 +52,7 @@ namespace
STOP,
STOPPED,
SET_SPEED,
RECURSIVE,
UNSUPPORTED
};
@ -57,6 +61,7 @@ namespace
ETL_ENUM_TYPE(STOP, "Stop")
ETL_ENUM_TYPE(STOPPED, "Stopped")
ETL_ENUM_TYPE(SET_SPEED, "Set Speed")
ETL_ENUM_TYPE(RECURSIVE, "Recursive")
ETL_ENUM_TYPE(UNSUPPORTED, "Unsupported")
ETL_END_ENUM_TYPE
};
@ -92,6 +97,11 @@ namespace
{
};
//***********************************
class Recursive : public etl::message<EventId::RECURSIVE>
{
};
//***********************************
class Unsupported : public etl::message<EventId::UNSUPPORTED>
{
@ -145,7 +155,7 @@ namespace
}
//***********************************
void SetSpeed(int speed_)
void SetSpeedValue(int speed_)
{
speed = speed_;
}
@ -162,6 +172,19 @@ namespace
isLampOn = false;
}
//***********************************
template <typename T>
void queue_recursive_message(const T& message)
{
messageQueue.emplace(message);
}
typedef etl::largest<Start, Stop, SetSpeed, Stopped, Recursive> Largest_t;
typedef etl::packet<etl::imessage, Largest_t::size, Largest_t::alignment> Packet_t;
etl::queue<Packet_t, 2> messageQueue;
int startCount;
int stopCount;
int setSpeedCount;
@ -174,7 +197,7 @@ namespace
//***********************************
// The idle state.
//***********************************
class Idle : public etl::fsm_state<MotorControl, Idle, StateId::IDLE, Start>
class Idle : public etl::fsm_state<MotorControl, Idle, StateId::IDLE, Start, Recursive>
{
public:
@ -185,6 +208,13 @@ namespace
return StateId::RUNNING;
}
//***********************************
etl::fsm_state_id_t on_event(etl::imessage_router&, const Recursive&)
{
get_fsm_context().queue_recursive_message(Start());
return StateId::IDLE;
}
//***********************************
etl::fsm_state_id_t on_event_unknown(etl::imessage_router&, const etl::imessage&)
{
@ -226,7 +256,7 @@ namespace
etl::fsm_state_id_t on_event(etl::imessage_router&, const SetSpeed& event)
{
++get_fsm_context().setSpeedCount;
get_fsm_context().SetSpeed(event.speed);
get_fsm_context().SetSpeedValue(event.speed);
return STATE_ID;
}
@ -309,7 +339,7 @@ namespace
CHECK(!motorControl.is_started());
// Start the FSM.
motorControl.start();
motorControl.start(false);
CHECK(motorControl.is_started());
// Now in Idle state.
@ -447,7 +477,7 @@ namespace
CHECK(!motorControl.is_started());
// Start the FSM.
motorControl.start();
motorControl.start(false);
CHECK(motorControl.is_started());
// Now in Idle state.
@ -484,6 +514,43 @@ namespace
CHECK_EQUAL(0, motorControl.unknownCount);
}
//*************************************************************************
TEST(test_fsm_recursive_event)
{
etl::null_message_router nmr;
motorControl.reset();
motorControl.ClearStatistics();
motorControl.messageQueue.clear();
// Start the FSM.
motorControl.start(false);
// Now in Idle state.
// Send Start event.
motorControl.receive(nmr, Recursive());
CHECK_EQUAL(1, motorControl.messageQueue.size());
// Send the queued message.
motorControl.receive(nmr, motorControl.messageQueue.front().get());
motorControl.messageQueue.pop();
// Now in Running state.
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(true, motorControl.isLampOn);
CHECK_EQUAL(0, motorControl.setSpeedCount);
CHECK_EQUAL(0, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(0, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(0, motorControl.unknownCount);
}
//*************************************************************************
TEST(test_fsm_supported)
{