add boost::sml example
This commit is contained in:
@@ -89,6 +89,7 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/hal/adc/inc
|
||||
${CMAKE_SOURCE_DIR}/cstdlib_support
|
||||
${CMAKE_SOURCE_DIR}/util/inc
|
||||
${CMAKE_SOURCE_DIR}/libs/boost
|
||||
)
|
||||
|
||||
set(EXECUTABLE ${PROJECT_NAME}.elf)
|
||||
@@ -130,8 +131,6 @@ target_link_options(
|
||||
-mthumb
|
||||
${LIB_SPECS}
|
||||
-lnosys
|
||||
-u
|
||||
_printf_float
|
||||
-lc
|
||||
-lm
|
||||
-Wl,--no-warn-rwx-segments
|
||||
|
||||
92
Chapter17/fsm/app/src/main_fsm_boost_sml.cpp
Normal file
92
Chapter17/fsm/app/src/main_fsm_boost_sml.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <stm32f072xb.h>
|
||||
|
||||
#include <hal.hpp>
|
||||
#include <stm32f0xx_hal_uart.hpp>
|
||||
#include <uart_stm32.hpp>
|
||||
|
||||
#include <retarget.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "sml.hpp"
|
||||
|
||||
namespace sml = boost::sml;
|
||||
|
||||
struct ble_button_pressed{};
|
||||
struct connection_request{};
|
||||
struct timer_expired{};
|
||||
|
||||
constexpr auto start_advertising = [](){
|
||||
printf("Action: start_advertising()\n");
|
||||
};
|
||||
|
||||
constexpr auto stop_advertising = [](){
|
||||
printf("Action: stop_advertising()\n");
|
||||
};
|
||||
|
||||
constexpr auto disconnect = [](){
|
||||
printf("Action: disconnect()\n");
|
||||
};
|
||||
|
||||
struct ble_fsm {
|
||||
auto operator()() const {
|
||||
using namespace sml;
|
||||
/**
|
||||
* Initial state: *initial_state
|
||||
* Transition DSL: src_state + event [ guard ] / action = dst_state
|
||||
*/
|
||||
return make_transition_table(
|
||||
*"idle"_s + event<ble_button_pressed> / start_advertising = "advertising"_s,
|
||||
"advertising"_s + event<connection_request> = "connected"_s,
|
||||
"advertising"_s + event<timer_expired> / stop_advertising = "idle"_s,
|
||||
"connected"_s + event<ble_button_pressed> / disconnect = "idle"_s
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
hal::init();
|
||||
|
||||
hal::uart_stm32<hal::stm32::uart> uart(USART2);
|
||||
uart.init();
|
||||
|
||||
retarget::set_stdio_uart(&uart);
|
||||
|
||||
using namespace sml;
|
||||
|
||||
sm<ble_fsm> my_ble_fsm{};
|
||||
|
||||
const auto print_current_state = [&]() {
|
||||
printf("Current State: ");
|
||||
if(my_ble_fsm.is("idle"_s)) {
|
||||
printf("idle\n");
|
||||
}
|
||||
if(my_ble_fsm.is("advertising"_s)) {
|
||||
printf("advertising\n");
|
||||
}
|
||||
if(my_ble_fsm.is("connected"_s)) {
|
||||
printf("connected\n");
|
||||
}
|
||||
};
|
||||
|
||||
print_current_state();
|
||||
|
||||
my_ble_fsm.process_event(ble_button_pressed{});
|
||||
print_current_state();
|
||||
|
||||
my_ble_fsm.process_event(connection_request{});
|
||||
print_current_state();
|
||||
|
||||
my_ble_fsm.process_event(ble_button_pressed{});
|
||||
print_current_state();
|
||||
|
||||
while(true)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
static const char* state_to_string(ble_state state) {
|
||||
namespace {
|
||||
const char* state_to_string(ble_state state) {
|
||||
switch (state) {
|
||||
case ble_state::idle: return "idle";
|
||||
case ble_state::advertising: return "advertising";
|
||||
@@ -82,6 +83,7 @@ static const char* state_to_string(ble_state state) {
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
174
Chapter17/fsm/app/src/main_fsm_state_pattern.cpp
Normal file
174
Chapter17/fsm/app/src/main_fsm_state_pattern.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <stm32f072xb.h>
|
||||
|
||||
#include <hal.hpp>
|
||||
#include <stm32f0xx_hal_uart.hpp>
|
||||
#include <uart_stm32.hpp>
|
||||
|
||||
#include <retarget.hpp>
|
||||
|
||||
#include "etl/vector.h"
|
||||
|
||||
enum class ble_state {
|
||||
idle,
|
||||
advertising,
|
||||
connected
|
||||
};
|
||||
|
||||
enum class ble_event {
|
||||
ble_button_pressed,
|
||||
connection_request,
|
||||
timer_expired
|
||||
};
|
||||
|
||||
class state {
|
||||
public:
|
||||
virtual ble_state handle_event(ble_event event) = 0;
|
||||
virtual ble_state get_state_enum() = 0;
|
||||
};
|
||||
|
||||
class idle : public state{
|
||||
public:
|
||||
ble_state handle_event(ble_event event) {
|
||||
if (event == ble_event::ble_button_pressed) {
|
||||
start_advertising();
|
||||
return ble_state::advertising;
|
||||
}
|
||||
return get_state_enum();
|
||||
}
|
||||
ble_state get_state_enum() {
|
||||
return ble_state::idle;
|
||||
}
|
||||
private:
|
||||
void start_advertising() {
|
||||
printf("Action: start_advertising()\n");
|
||||
}
|
||||
};
|
||||
|
||||
class advertising : public state{
|
||||
public:
|
||||
ble_state handle_event(ble_event event) {
|
||||
if (event == ble_event::connection_request) {
|
||||
return ble_state::connected;
|
||||
}
|
||||
if (event == ble_event::timer_expired) {
|
||||
stop_advertising();
|
||||
return ble_state::idle;
|
||||
}
|
||||
return get_state_enum();
|
||||
}
|
||||
ble_state get_state_enum() {
|
||||
return ble_state::advertising;
|
||||
}
|
||||
private:
|
||||
void stop_advertising() {
|
||||
printf("Action: stop_advertising()\n");
|
||||
}
|
||||
};
|
||||
|
||||
class connected : public state{
|
||||
public:
|
||||
ble_state handle_event(ble_event event) {
|
||||
if (event == ble_event::ble_button_pressed) {
|
||||
disconnect();
|
||||
return ble_state::idle;
|
||||
}
|
||||
return get_state_enum();
|
||||
}
|
||||
ble_state get_state_enum() {
|
||||
return ble_state::connected;
|
||||
}
|
||||
private:
|
||||
void disconnect() {
|
||||
printf("Action: disconnect()\n");
|
||||
}
|
||||
};
|
||||
|
||||
class ble_fsm {
|
||||
public:
|
||||
void handle_event(ble_event event) {
|
||||
if(auto the_state = get_the_state(current_state_)) {
|
||||
current_state_ = the_state->handle_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
ble_state get_state() const {
|
||||
return current_state_;
|
||||
}
|
||||
|
||||
void add_state(state *the_state) {
|
||||
states_.push_back(the_state);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<state*> states_;
|
||||
ble_state current_state_ = ble_state::idle;
|
||||
|
||||
state* get_the_state(ble_state state_enum) {
|
||||
const auto is_state_enum = [&] (state *the_state) {
|
||||
return the_state->get_state_enum() == state_enum;
|
||||
};
|
||||
auto it = std::find_if(states_.begin(), states_.end(), is_state_enum);
|
||||
|
||||
if(it != states_.end()) {
|
||||
return *it;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
const char* state_to_string(ble_state state) {
|
||||
switch (state) {
|
||||
case ble_state::idle: return "idle";
|
||||
case ble_state::advertising: return "advertising";
|
||||
case ble_state::connected: return "connected";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
hal::init();
|
||||
|
||||
hal::uart_stm32<hal::stm32::uart> uart(USART2);
|
||||
uart.init();
|
||||
|
||||
retarget::set_stdio_uart(&uart);
|
||||
|
||||
ble_fsm my_ble_fsm;
|
||||
|
||||
idle idle_s;
|
||||
advertising advertising_s;
|
||||
connected connected_s;
|
||||
|
||||
my_ble_fsm.add_state(&idle_s);
|
||||
my_ble_fsm.add_state(&advertising_s);
|
||||
my_ble_fsm.add_state(&connected_s);
|
||||
|
||||
const auto print_current_state = [&]() {
|
||||
printf("Current State: %s\n", state_to_string(my_ble_fsm.get_state()));
|
||||
};
|
||||
|
||||
print_current_state();
|
||||
|
||||
my_ble_fsm.handle_event(ble_event::ble_button_pressed);
|
||||
print_current_state();
|
||||
|
||||
my_ble_fsm.handle_event(ble_event::connection_request);
|
||||
print_current_state();
|
||||
|
||||
my_ble_fsm.handle_event(ble_event::ble_button_pressed);
|
||||
print_current_state();
|
||||
|
||||
|
||||
while(true)
|
||||
{
|
||||
}
|
||||
}
|
||||
2900
Chapter17/fsm/libs/boost/sml.hpp
Normal file
2900
Chapter17/fsm/libs/boost/sml.hpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user