|
|
WIP
|
|
|
# WIP
|
|
|
|
|
|
Finite state machine, handles events using the current state's handler |
|
|
\ No newline at end of file |
|
|
Finite state machine, handles events using the current state's handler.
|
|
|
|
|
|
## Example
|
|
|
This example implements the following very simple finite state machine behavior:
|
|
|
|
|
|

|
|
|
|
|
|
No action is specified for the involved events (`EV_ENTRY`, `EV_EXIT`, `EV_1`, `EV_2`). They simply trigger the transitions.
|
|
|
|
|
|
[Here](https://git.skywarder.eu/scs/skyward-boardcore/-/tree/master/src/tests/catch/examples) and [here](https://git.skywarder.eu/r2a/skyward-boardcore/tree/master/src/entrypoints/examples) you can find a more advanced example which also use the [catch testing framework](Testing) to test the implemented FSM.
|
|
|
|
|
|
#### MyFSM.h
|
|
|
As always when dealing with events and topics, after we include the required dependencies, we have to define the set of possible events and topics.
|
|
|
```cpp
|
|
|
#pragma once
|
|
|
|
|
|
#include "events/FSM.h"
|
|
|
#include "events/EventBroker.h"
|
|
|
|
|
|
enum ExampleEvents : uint8_t
|
|
|
{
|
|
|
EV_1 = EV_FIRST_SIGNAL,
|
|
|
EV_2
|
|
|
};
|
|
|
|
|
|
enum ExampleTopics : uint8_t
|
|
|
{
|
|
|
TOPIC_1
|
|
|
};
|
|
|
```
|
|
|
|
|
|
Then we can define the MyFSM class and its states, which are identified by the two methods `state_S1` and `state_S2`.
|
|
|
|
|
|
```cpp
|
|
|
class MyFSM : public FSM<MyFSM>
|
|
|
{
|
|
|
public:
|
|
|
MyFSM()
|
|
|
: FSM(&MyFSM::state_S1), // set FSM initial state to state_S1
|
|
|
last_event(0)
|
|
|
{
|
|
|
// make this object to subscribe to TOPIC_1
|
|
|
sEventBroker->subscribe(this, TOPIC_1);
|
|
|
}
|
|
|
|
|
|
~MyFSM()
|
|
|
{
|
|
|
// unsubscribe from all the topics this object was subscribed to
|
|
|
sEventBroker->unsubscribe(this);
|
|
|
}
|
|
|
|
|
|
void state_S1(const Event& ev)
|
|
|
{
|
|
|
switch (ev.sig)
|
|
|
{
|
|
|
case EV_ENTRY:
|
|
|
case EV_EXIT:
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
case EV_1:
|
|
|
{
|
|
|
TRACE("S1: EV_1 \n");
|
|
|
// self-loop on state_S1
|
|
|
transition(&MyFSM::state_S1);
|
|
|
break;
|
|
|
}
|
|
|
case EV_2:
|
|
|
{
|
|
|
TRACE("S1: EV_2 ---> S2 \n");
|
|
|
transition(&MyFSM::state_S2);
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
last_event = ev.sig;
|
|
|
}
|
|
|
|
|
|
void state_S2(const Event& ev)
|
|
|
{
|
|
|
switch (ev.sig)
|
|
|
{
|
|
|
case EV_ENTRY:
|
|
|
case EV_EXIT:
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
case EV_1:
|
|
|
{
|
|
|
TRACE("S2: EV_1 ---> S1 \n");
|
|
|
transition(&MyFSM::state_S1);
|
|
|
break;
|
|
|
}
|
|
|
case EV_2:
|
|
|
{
|
|
|
TRACE("S2: EV_2 \n");
|
|
|
// self-loop on state S2
|
|
|
transition(&MyFSM::state_S2);
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
last_event = ev.sig;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
uint8_t last_event;
|
|
|
};
|
|
|
```
|
|
|
|
|
|
|
|
|
#### test-fsm.cpp
|
|
|
```cpp
|
|
|
#include <Common.h>
|
|
|
#include "MyFSM.h"
|
|
|
|
|
|
using namespace miosix;
|
|
|
|
|
|
int main()
|
|
|
{
|
|
|
EventBroker* broker = EventBroker::getInstance(); // singleton object
|
|
|
broker->start();
|
|
|
|
|
|
MyFSM fsm;
|
|
|
|
|
|
if (fsm.start())
|
|
|
{
|
|
|
// trigger self-loop on state S1
|
|
|
broker->post(Event{EV_1}, TOPIC_1);
|
|
|
Thread::sleep(100);
|
|
|
|
|
|
// trigger transition to state S2
|
|
|
broker->post(Event{EV_2}, TOPIC_1);
|
|
|
Thread::sleep(100);
|
|
|
|
|
|
// trigger self-loop on state S2
|
|
|
broker->post(Event{EV_2}, TOPIC_1);
|
|
|
Thread::sleep(100);
|
|
|
|
|
|
// trigger transition to state S1 with a delayed event
|
|
|
const unsigned int DELAY_MS = 1000;
|
|
|
broker->postDelayed<DELAY_MS>(Event{EV_1}, TOPIC_1);
|
|
|
|
|
|
// wait for the delayed event to be posted
|
|
|
// before stopping the active objects
|
|
|
Thread::sleep(2000);
|
|
|
|
|
|
fsm.stop();
|
|
|
broker->stop();
|
|
|
}
|
|
|
else {
|
|
|
TRACE("Failed to start MyFSM\n");
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### Output
|
|
|
|
|
|
```sh
|
|
|
0.12> S1: EV_1
|
|
|
0.22> S1: EV_2 ---> S2
|
|
|
0.32> S2: EV_2
|
|
|
1.42> S2: EV_1 ---> S1
|
|
|
``` |
|
|
\ No newline at end of file |