mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-18 01:46:08 +08:00
Merge remote-tracking branch 'origin/feature/light_weight_fsm' into development
This commit is contained in:
commit
d1a63fd507
@ -69,7 +69,11 @@ SOFTWARE.
|
||||
#endif
|
||||
|
||||
#if defined(ETL_COMPILER_GCC)
|
||||
#define GCC_VERSION ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__)
|
||||
#define ETL_COMPILER_VERSION __GNUC__
|
||||
#define ETL_COMPILER_FULL_VERSION ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__)
|
||||
#elif defined ETL_COMPILER_MICROSOFT
|
||||
#define ETL_COMPILER_VERSION _MSC_VER
|
||||
#define ETL_COMPILER_FULL_VERSION _MSC_FULL_VER
|
||||
#endif
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
@ -84,4 +88,10 @@ SOFTWARE.
|
||||
#define ETL_IF_CONSTEXPR
|
||||
#endif
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
#define ETL_DELETE = delete
|
||||
#else
|
||||
#define ETL_DELETE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
289
include/etl/state_chart.h
Normal file
289
include/etl/state_chart.h
Normal file
@ -0,0 +1,289 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2018 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_STATE_CHART_INCLUDED
|
||||
#define ETL_STATE_CHART_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "etl/platform.h"
|
||||
#include "etl/nullptr.h"
|
||||
#include "etl/array.h"
|
||||
#include "etl/array_view.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// Simple Finite State Machine Interface
|
||||
//***************************************************************************
|
||||
class istate_chart
|
||||
{
|
||||
public:
|
||||
|
||||
typedef uint32_t state_id_t;
|
||||
typedef uint32_t event_id_t;
|
||||
|
||||
virtual state_id_t get_state_id() const = 0;
|
||||
virtual void process_event(const event_id_t event_id) = 0;
|
||||
|
||||
virtual ~istate_chart()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Simple Finite State Machine
|
||||
//***************************************************************************
|
||||
template <typename TObject>
|
||||
class state_chart : public istate_chart
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Transition definition
|
||||
//*************************************************************************
|
||||
struct transition
|
||||
{
|
||||
transition(const event_id_t event_id_,
|
||||
const state_id_t current_state_id_,
|
||||
const state_id_t next_state_id_,
|
||||
void (TObject::* const action_)() = nullptr,
|
||||
bool (TObject::* const guard_)() = nullptr)
|
||||
: event_id(event_id_),
|
||||
current_state_id(current_state_id_),
|
||||
next_state_id(next_state_id_),
|
||||
action(action_),
|
||||
guard(guard_)
|
||||
{
|
||||
}
|
||||
|
||||
const event_id_t event_id;
|
||||
const state_id_t current_state_id;
|
||||
const state_id_t next_state_id;
|
||||
void (TObject::* const action)();
|
||||
bool (TObject::* const guard)();
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// State definition
|
||||
//*************************************************************************
|
||||
struct state
|
||||
{
|
||||
state(const state_id_t state_id_,
|
||||
void (TObject::* const on_entry_)() = nullptr,
|
||||
void (TObject::* const on_exit_)() = nullptr)
|
||||
: state_id(state_id_),
|
||||
on_entry(on_entry_),
|
||||
on_exit(on_exit_)
|
||||
{
|
||||
}
|
||||
|
||||
state_id_t state_id;
|
||||
void (TObject::* const on_entry)();
|
||||
void (TObject::* const on_exit)();
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
/// \tparam TRANSITION_TABLE_SIZE The transition table size.
|
||||
/// \param object_ A reference to the implementation object.
|
||||
/// \param transition_table_ The table of transitions.
|
||||
/// \param state_id_ The initial state id.
|
||||
//*************************************************************************
|
||||
template <const uint32_t TRANSITION_TABLE_SIZE>
|
||||
state_chart(TObject& object_,
|
||||
const etl::array<transition, TRANSITION_TABLE_SIZE>& transition_table_,
|
||||
const state_id_t state_id_)
|
||||
: object(object_),
|
||||
current_state_id(state_id_),
|
||||
transition_table(transition_table_.begin(), transition_table_.end())
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Sets the state table.
|
||||
/// \tparam STATE_TABLE_SIZE The state table size.
|
||||
/// \param state_table_ A reference to the state table.
|
||||
//*************************************************************************
|
||||
template <const uint32_t STATE_TABLE_SIZE>
|
||||
void set_state_table(const etl::array<state, STATE_TABLE_SIZE>& state_table_)
|
||||
{
|
||||
state_table.assign(state_table_.begin(), state_table_.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets a reference to the implementation object.
|
||||
/// \return Reference to the implementation object.
|
||||
//*************************************************************************
|
||||
TObject& get_object()
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets a const reference to the implementation object.
|
||||
/// \return Const reference to the implementation object.
|
||||
//*************************************************************************
|
||||
const TObject& get_object() const
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the current state id.
|
||||
/// \return The current state id.
|
||||
//*************************************************************************
|
||||
state_id_t get_state_id() const
|
||||
{
|
||||
return current_state_id;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the current state id.
|
||||
/// \return The current state id.
|
||||
//*************************************************************************
|
||||
const state* find_state(state_id_t state_id)
|
||||
{
|
||||
if (state_table.empty())
|
||||
{
|
||||
return state_table.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::find_if(state_table.begin(),
|
||||
state_table.end(),
|
||||
is_state(state_id));
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Processes the specified event.
|
||||
/// The state machine will action the <b>first</b> item in the transition table
|
||||
/// that satisfies the conditions for executing the action.
|
||||
/// \param event_id The id of the event to process.
|
||||
//*************************************************************************
|
||||
void process_event(const event_id_t event_id)
|
||||
{
|
||||
// Scan the transition table.
|
||||
const transition* t = std::find_if(transition_table.begin(),
|
||||
transition_table.end(),
|
||||
is_transition(event_id, current_state_id));
|
||||
|
||||
// Found an entry?
|
||||
if (t != transition_table.end())
|
||||
{
|
||||
// Shall we execute the transition?
|
||||
if ((t->guard == nullptr) || ((object.*t->guard)()))
|
||||
{
|
||||
const bool to_new_state = (current_state_id != t->next_state_id);
|
||||
|
||||
// Execute the state exit if necessary.
|
||||
if (to_new_state)
|
||||
{
|
||||
// See if we have a state item for the current state.
|
||||
const state* s = find_state(current_state_id);
|
||||
|
||||
// If the current state has an 'on_exit' then call it.
|
||||
if ((s != state_table.end()) && (s->on_exit != nullptr))
|
||||
{
|
||||
(object.*(s->on_exit))();
|
||||
}
|
||||
}
|
||||
|
||||
// Shall we execute the action?
|
||||
if (t->action != nullptr)
|
||||
{
|
||||
(object.*t->action)();
|
||||
}
|
||||
|
||||
// Execute the state entry if necessary.
|
||||
if (to_new_state)
|
||||
{
|
||||
// See if we have a state item for the next state.
|
||||
const state* s = find_state(t->next_state_id);
|
||||
|
||||
// If the new state has an 'on_entry' then call it.
|
||||
if ((s != state_table.end()) && (s->on_entry != nullptr))
|
||||
{
|
||||
(object.*(s->on_entry))();
|
||||
}
|
||||
}
|
||||
|
||||
current_state_id = t->next_state_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*************************************************************************
|
||||
struct is_transition
|
||||
{
|
||||
is_transition(event_id_t event_id_, state_id_t state_id_)
|
||||
: event_id(event_id_),
|
||||
state_id(state_id_)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const transition& t) const
|
||||
{
|
||||
return (t.event_id == event_id) && (t.current_state_id == state_id);
|
||||
}
|
||||
|
||||
const event_id_t event_id;
|
||||
const state_id_t state_id;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct is_state
|
||||
{
|
||||
is_state(state_id_t state_id_)
|
||||
: state_id(state_id_)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const state& s) const
|
||||
{
|
||||
return (s.state_id == state_id);
|
||||
}
|
||||
|
||||
const state_id_t state_id;
|
||||
};
|
||||
|
||||
// Disabled
|
||||
state_chart(const state_chart&) ETL_DELETE;
|
||||
state_chart& operator =(const state_chart&) ETL_DELETE;
|
||||
|
||||
TObject& object; ///< The object that supplies guard and action member functions.
|
||||
state_id_t current_state_id; ///< The current state id.
|
||||
const etl::array_view<const transition> transition_table; ///< The table of transitions.
|
||||
etl::array_view<const state> state_table; ///< The table of states.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -37,13 +37,13 @@ SOFTWARE.
|
||||
/// Definitions of the ETL version
|
||||
///\ingroup utilities
|
||||
|
||||
#define ETL_VERSION "11.16.5"
|
||||
#define ETL_VERSION_W L"11.16.5"
|
||||
#define ETL_VERSION_U16 u"11.16.5"
|
||||
#define ETL_VERSION_U32 U"11.16.5"
|
||||
#define ETL_VERSION "11.17.0"
|
||||
#define ETL_VERSION_W L"11.17.0"
|
||||
#define ETL_VERSION_U16 u"11.17.0"
|
||||
#define ETL_VERSION_U32 U"11.17.0"
|
||||
#define ETL_VERSION_MAJOR 11
|
||||
#define ETL_VERSION_MINOR 16
|
||||
#define ETL_VERSION_PATCH 5
|
||||
#define ETL_VERSION_MINOR 17
|
||||
#define ETL_VERSION_PATCH 0
|
||||
#define ETL_VERSION_VALUE ((ETL_VERSION_MAJOR * 10000) + (ETL_VERSION_MINOR * 100) + ETL_VERSION_PATCH)
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,3 +1,11 @@
|
||||
===============================================================================
|
||||
11.17.0
|
||||
Added etl::state_chart
|
||||
|
||||
===============================================================================
|
||||
11.16.6
|
||||
Fixed implementations of key_comp and value_comp for maps and sets
|
||||
|
||||
===============================================================================
|
||||
11.16.5
|
||||
Added 'ull' suffix to 64bit literals
|
||||
|
||||
@ -279,6 +279,7 @@
|
||||
<Unit filename="../../include/etl/spsc_queue_mutex.h" />
|
||||
<Unit filename="../../include/etl/sqrt.h" />
|
||||
<Unit filename="../../include/etl/stack.h" />
|
||||
<Unit filename="../../include/etl/state_chart.h" />
|
||||
<Unit filename="../../include/etl/static_assert.h" />
|
||||
<Unit filename="../../include/etl/stl/algorithm.h" />
|
||||
<Unit filename="../../include/etl/stl/alternate/algorithm.h" />
|
||||
@ -423,6 +424,7 @@
|
||||
<Unit filename="../test_set.cpp" />
|
||||
<Unit filename="../test_smallest.cpp" />
|
||||
<Unit filename="../test_stack.cpp" />
|
||||
<Unit filename="../test_state_chart.cpp" />
|
||||
<Unit filename="../test_string_char.cpp" />
|
||||
<Unit filename="../test_string_u16.cpp" />
|
||||
<Unit filename="../test_string_u32.cpp" />
|
||||
|
||||
387
test/test_state_chart.cpp
Normal file
387
test/test_state_chart.cpp
Normal file
@ -0,0 +1,387 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2018 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "UnitTest++.h"
|
||||
|
||||
#include "etl/state_chart.h"
|
||||
#include "etl/enum_type.h"
|
||||
#include "etl/queue.h"
|
||||
#include "etl/array.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
//***************************************************************************
|
||||
// Events
|
||||
struct EventId
|
||||
{
|
||||
enum enum_type
|
||||
{
|
||||
START,
|
||||
STOP,
|
||||
EMERGENCY_STOP,
|
||||
STOPPED,
|
||||
SET_SPEED
|
||||
};
|
||||
|
||||
ETL_DECLARE_ENUM_TYPE(EventId, etl::istate_chart::event_id_t)
|
||||
ETL_ENUM_TYPE(START, "Start")
|
||||
ETL_ENUM_TYPE(STOP, "Stop")
|
||||
ETL_ENUM_TYPE(EMERGENCY_STOP, "Emergency Stop")
|
||||
ETL_ENUM_TYPE(STOPPED, "Stopped")
|
||||
ETL_ENUM_TYPE(SET_SPEED, "Set Speed")
|
||||
ETL_END_ENUM_TYPE
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// States
|
||||
struct StateId
|
||||
{
|
||||
enum enum_type
|
||||
{
|
||||
IDLE,
|
||||
RUNNING,
|
||||
WINDING_DOWN,
|
||||
NUMBER_OF_STATES
|
||||
};
|
||||
|
||||
ETL_DECLARE_ENUM_TYPE(StateId, etl::istate_chart::state_id_t)
|
||||
ETL_ENUM_TYPE(IDLE, "Idle")
|
||||
ETL_ENUM_TYPE(RUNNING, "Running")
|
||||
ETL_ENUM_TYPE(WINDING_DOWN, "Winding Down")
|
||||
ETL_END_ENUM_TYPE
|
||||
};
|
||||
|
||||
//***********************************
|
||||
// The motor control FSM.
|
||||
//***********************************
|
||||
class MotorControl : public etl::state_chart<MotorControl>
|
||||
{
|
||||
public:
|
||||
|
||||
MotorControl()
|
||||
: state_chart<MotorControl>(*this, transitionTable, StateId::IDLE)
|
||||
{
|
||||
this->set_state_table(stateTable);
|
||||
ClearStatistics();
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void ClearStatistics()
|
||||
{
|
||||
startCount = 0;
|
||||
stopCount = 0;
|
||||
setSpeedCount = 0;
|
||||
stoppedCount = 0;
|
||||
isLampOn = false;
|
||||
speed = 0;
|
||||
windingDown = 0;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void OnStart()
|
||||
{
|
||||
++startCount;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void OnStop()
|
||||
{
|
||||
++stopCount;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void OnStopped()
|
||||
{
|
||||
++stoppedCount;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void OnSetSpeed()
|
||||
{
|
||||
++setSpeedCount;
|
||||
SetSpeedValue(100);
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void OnEnterIdle()
|
||||
{
|
||||
TurnRunningLampOff();
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void OnEnterRunning()
|
||||
{
|
||||
TurnRunningLampOn();
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void OnEnterWindingDown()
|
||||
{
|
||||
++windingDown;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void OnExitWindingDown()
|
||||
{
|
||||
--windingDown;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void SetSpeedValue(int speed_)
|
||||
{
|
||||
speed = speed_;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
bool Guard()
|
||||
{
|
||||
return guard;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void TurnRunningLampOn()
|
||||
{
|
||||
isLampOn = true;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void TurnRunningLampOff()
|
||||
{
|
||||
isLampOn = false;
|
||||
}
|
||||
|
||||
int startCount;
|
||||
int stopCount;
|
||||
int setSpeedCount;
|
||||
int stoppedCount;
|
||||
bool isLampOn;
|
||||
int speed;
|
||||
int windingDown;
|
||||
|
||||
bool guard;
|
||||
|
||||
static const etl::array<MotorControl::transition, 5> transitionTable;
|
||||
static const etl::array<MotorControl::state, 3> stateTable;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
const etl::array<MotorControl::transition, 5> MotorControl::transitionTable =
|
||||
{
|
||||
MotorControl::transition(EventId::START, StateId::IDLE, StateId::RUNNING, &MotorControl::OnStart, &MotorControl::Guard),
|
||||
MotorControl::transition(EventId::STOP, StateId::RUNNING, StateId::WINDING_DOWN, &MotorControl::OnStop),
|
||||
MotorControl::transition(EventId::STOPPED, StateId::WINDING_DOWN, StateId::IDLE, &MotorControl::OnStopped),
|
||||
MotorControl::transition(EventId::EMERGENCY_STOP, StateId::RUNNING, StateId::IDLE, &MotorControl::OnStop),
|
||||
MotorControl::transition(EventId::SET_SPEED, StateId::RUNNING, StateId::RUNNING, &MotorControl::OnSetSpeed)
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
const etl::array<MotorControl::state, 3> MotorControl::stateTable =
|
||||
{
|
||||
MotorControl::state(StateId::IDLE, &MotorControl::OnEnterIdle, nullptr),
|
||||
MotorControl::state(StateId::RUNNING, &MotorControl::OnEnterRunning, nullptr),
|
||||
MotorControl::state(StateId::WINDING_DOWN, &MotorControl::OnEnterWindingDown, &MotorControl::OnExitWindingDown)
|
||||
};
|
||||
|
||||
MotorControl motorControl;
|
||||
|
||||
SUITE(test_state_chart_class)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_state_chart)
|
||||
{
|
||||
motorControl.ClearStatistics();
|
||||
|
||||
// Now in Idle state.
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id()));
|
||||
|
||||
CHECK_EQUAL(false, motorControl.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.speed);
|
||||
CHECK_EQUAL(0, motorControl.startCount);
|
||||
CHECK_EQUAL(0, motorControl.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.stoppedCount);
|
||||
CHECK_EQUAL(0, motorControl.windingDown);
|
||||
|
||||
// Send unhandled events.
|
||||
motorControl.process_event(EventId::STOP);
|
||||
motorControl.process_event(EventId::STOPPED);
|
||||
|
||||
CHECK_EQUAL(StateId::IDLE, motorControl.get_state_id());
|
||||
|
||||
CHECK_EQUAL(false, motorControl.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.speed);
|
||||
CHECK_EQUAL(0, motorControl.startCount);
|
||||
CHECK_EQUAL(0, motorControl.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.stoppedCount);
|
||||
|
||||
// Send Start event.
|
||||
motorControl.guard = false;
|
||||
motorControl.process_event(EventId::START);
|
||||
|
||||
// Still in Idle state.
|
||||
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id()));
|
||||
|
||||
CHECK_EQUAL(false, motorControl.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.speed);
|
||||
CHECK_EQUAL(0, motorControl.startCount);
|
||||
CHECK_EQUAL(0, motorControl.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.stoppedCount);
|
||||
CHECK_EQUAL(0, motorControl.windingDown);
|
||||
|
||||
// Send Start event.
|
||||
motorControl.guard = true;
|
||||
motorControl.process_event(EventId::START);
|
||||
|
||||
// Now in Running state.
|
||||
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.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.windingDown);
|
||||
|
||||
// Send unhandled events.
|
||||
motorControl.process_event(EventId::START);
|
||||
motorControl.process_event(EventId::STOPPED);
|
||||
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.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.windingDown);
|
||||
|
||||
// Send SetSpeed event.
|
||||
motorControl.process_event(EventId::SET_SPEED);
|
||||
|
||||
// Still in Running state.
|
||||
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
|
||||
|
||||
CHECK_EQUAL(true, motorControl.isLampOn);
|
||||
CHECK_EQUAL(1, motorControl.setSpeedCount);
|
||||
CHECK_EQUAL(100, motorControl.speed);
|
||||
CHECK_EQUAL(1, motorControl.startCount);
|
||||
CHECK_EQUAL(0, motorControl.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.stoppedCount);
|
||||
CHECK_EQUAL(0, motorControl.windingDown);
|
||||
|
||||
// Send Stop event.
|
||||
motorControl.process_event(EventId::STOP);
|
||||
|
||||
// Now in WindingDown state.
|
||||
|
||||
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state_id()));
|
||||
|
||||
CHECK_EQUAL(true, motorControl.isLampOn);
|
||||
CHECK_EQUAL(1, motorControl.setSpeedCount);
|
||||
CHECK_EQUAL(100, motorControl.speed);
|
||||
CHECK_EQUAL(1, motorControl.startCount);
|
||||
CHECK_EQUAL(1, motorControl.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.stoppedCount);
|
||||
CHECK_EQUAL(1, motorControl.windingDown);
|
||||
|
||||
// Send unhandled events.
|
||||
motorControl.process_event(EventId::START);
|
||||
motorControl.process_event(EventId::STOP);
|
||||
|
||||
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state_id()));
|
||||
|
||||
CHECK_EQUAL(true, motorControl.isLampOn);
|
||||
CHECK_EQUAL(1, motorControl.setSpeedCount);
|
||||
CHECK_EQUAL(100, motorControl.speed);
|
||||
CHECK_EQUAL(1, motorControl.startCount);
|
||||
CHECK_EQUAL(1, motorControl.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.stoppedCount);
|
||||
CHECK_EQUAL(1, motorControl.windingDown);
|
||||
|
||||
// Send Stopped event.
|
||||
motorControl.process_event(EventId::STOPPED);
|
||||
|
||||
// Now in Idle state.
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id()));
|
||||
|
||||
CHECK_EQUAL(false, motorControl.isLampOn);
|
||||
CHECK_EQUAL(1, motorControl.setSpeedCount);
|
||||
CHECK_EQUAL(100, motorControl.speed);
|
||||
CHECK_EQUAL(1, motorControl.startCount);
|
||||
CHECK_EQUAL(1, motorControl.stopCount);
|
||||
CHECK_EQUAL(1, motorControl.stoppedCount);
|
||||
CHECK_EQUAL(0, motorControl.windingDown);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_fsm_emergency_stop)
|
||||
{
|
||||
motorControl.ClearStatistics();
|
||||
|
||||
// Now in Idle state.
|
||||
|
||||
// Send Start event.
|
||||
motorControl.process_event(EventId::START);
|
||||
|
||||
// Now in Running state.
|
||||
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.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.windingDown);
|
||||
|
||||
// Send emergency Stop event.
|
||||
motorControl.process_event(EventId::EMERGENCY_STOP);
|
||||
|
||||
// Now in Idle state.
|
||||
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id()));
|
||||
|
||||
CHECK_EQUAL(false, motorControl.isLampOn);
|
||||
CHECK_EQUAL(0, motorControl.setSpeedCount);
|
||||
CHECK_EQUAL(0, motorControl.speed);
|
||||
CHECK_EQUAL(1, motorControl.startCount);
|
||||
CHECK_EQUAL(1, motorControl.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.stoppedCount);
|
||||
CHECK_EQUAL(0, motorControl.windingDown);
|
||||
}
|
||||
};
|
||||
}
|
||||
8
test/vs2017/cpp.hint
Normal file
8
test/vs2017/cpp.hint
Normal file
@ -0,0 +1,8 @@
|
||||
// Hint files help the Visual Studio IDE interpret Visual C++ identifiers
|
||||
// such as names of functions and macros.
|
||||
// For more information see https://go.microsoft.com/fwlink/?linkid=865984
|
||||
#define ETL_CONSTEXPR
|
||||
#define ETL_CONSTEXPR_IF
|
||||
#define ETL_DELETE
|
||||
|
||||
|
||||
@ -371,6 +371,7 @@
|
||||
<ClInclude Include="..\..\include\etl\fsm.h" />
|
||||
<ClInclude Include="..\..\include\etl\fsm_generator.h" />
|
||||
<ClInclude Include="..\..\include\etl\largest_generator.h" />
|
||||
<ClInclude Include="..\..\include\etl\state_chart.h" />
|
||||
<ClInclude Include="..\..\include\etl\math_constants.h" />
|
||||
<ClInclude Include="..\..\include\etl\memory_model.h" />
|
||||
<ClInclude Include="..\..\include\etl\message.h" />
|
||||
@ -728,6 +729,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_state_chart.cpp" />
|
||||
<ClCompile Include="..\test_smallest.cpp" />
|
||||
<ClCompile Include="..\test_stack.cpp" />
|
||||
<ClCompile Include="..\test_string_char.cpp" />
|
||||
@ -768,6 +770,7 @@
|
||||
<None Include="..\..\include\etl\generate_type_lookup.bat" />
|
||||
<None Include="..\..\include\etl\generate_type_traits.bat" />
|
||||
<None Include="..\..\include\etl\generate_variant_pool.bat" />
|
||||
<None Include="cpp.hint" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\CMakeLists.txt" />
|
||||
|
||||
@ -693,6 +693,9 @@
|
||||
<ClInclude Include="..\..\include\etl\atomic\atomic_llvm_sync.h">
|
||||
<Filter>ETL\Utilities\Atomic</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\state_chart.h">
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\main.cpp">
|
||||
@ -1136,6 +1139,9 @@
|
||||
<ClCompile Include="..\test_no_stl_iterator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_state_chart.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\library.properties">
|
||||
@ -1174,6 +1180,7 @@
|
||||
<None Include="..\..\include\etl\generate_type_select.bat">
|
||||
<Filter>Resource Files\Generators</Filter>
|
||||
</None>
|
||||
<None Include="cpp.hint" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\include\etl\file_error_numbers.txt">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user