-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from kiishor/feature/hsm_demo_toaster_oven
Feature/hsm demo toaster oven
- Loading branch information
Showing
11 changed files
with
863 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
cmake_minimum_required(VERSION 3.5 FATAL_ERROR) | ||
project("toaster_oven") | ||
|
||
# Setup path for source dir | ||
set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) | ||
set(TARGET_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../src) | ||
|
||
set(TARGET_FILES | ||
${TARGET_DIR}/hsm.c | ||
) | ||
|
||
set (DEMO_FILES | ||
${SRC_DIR}/main.c | ||
${SRC_DIR}/toaster_oven.c | ||
) | ||
|
||
set (HEADER_FILES | ||
${SRC_DIR}/toaster_oven.h | ||
${TARGET_DIR}/hsm.h | ||
) | ||
SOURCE_GROUP("Src" FILES ${DEMO_FILES} ${TARGET_FILES} ${HEADER_FILES}) | ||
|
||
include_directories( | ||
${SRC_DIR} | ||
${TARGET_DIR} | ||
) | ||
|
||
set(C_VERSION 99) | ||
if ("c_std_11" IN_LIST CMAKE_C_COMPILE_FEATURES) | ||
set(C_VERSION 11) | ||
endif() | ||
|
||
set(CMAKE_C_STANDARD ${C_VERSION}) | ||
set(CMAKE_C_STANDARD_REQUIRED ON) | ||
message("Your compiler supports : c${C_VERSION}") | ||
|
||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") | ||
|
||
add_executable(toaster_oven ${DEMO_FILES} ${TARGET_FILES} ${HEADER_FILES}) | ||
|
||
if ( CMAKE_C_COMPILER_ID MATCHES "Clang|AppleClang|GNU" ) | ||
target_compile_options( toaster_oven PRIVATE -Wall -Wextra -Wunreachable-code -Wpedantic) | ||
target_compile_options( toaster_oven PRIVATE -Werror ) | ||
endif() | ||
|
||
# Setup compiler include path | ||
target_include_directories(toaster_oven PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | ||
<CodeBlocks_project_file> | ||
<FileVersion major="1" minor="6" /> | ||
<Project> | ||
<Option title="toaster_oven" /> | ||
<Option pch_mode="2" /> | ||
<Option compiler="gcc" /> | ||
<Build> | ||
<Target title="Debug"> | ||
<Option output="bin/Debug/toaster_oven" prefix_auto="1" extension_auto="1" /> | ||
<Option object_output="obj/Debug/" /> | ||
<Option type="1" /> | ||
<Option compiler="gcc" /> | ||
<Compiler> | ||
<Add option="-g" /> | ||
</Compiler> | ||
</Target> | ||
<Target title="Release"> | ||
<Option output="bin/Release/toaster_oven" prefix_auto="1" extension_auto="1" /> | ||
<Option object_output="obj/Release/" /> | ||
<Option type="1" /> | ||
<Option compiler="gcc" /> | ||
<Compiler> | ||
<Add option="-O2" /> | ||
</Compiler> | ||
<Linker> | ||
<Add option="-s" /> | ||
</Linker> | ||
</Target> | ||
</Build> | ||
<Compiler> | ||
<Add option="-Wall" /> | ||
<Add option="-std=c17" /> | ||
<Add directory="../../../../src" /> | ||
<Add directory="../../build" /> | ||
</Compiler> | ||
<Unit filename="../../../../src/hsm.c"> | ||
<Option compilerVar="CC" /> | ||
</Unit> | ||
<Unit filename="../../../../src/hsm.h" /> | ||
<Unit filename="../../CMakeLists.txt" /> | ||
<Unit filename="../../readme.md" /> | ||
<Unit filename="../../src/main.c"> | ||
<Option compilerVar="CC" /> | ||
</Unit> | ||
<Unit filename="../../src/toaster_oven.c"> | ||
<Option compilerVar="CC" /> | ||
</Unit> | ||
<Unit filename="../../src/toaster_oven.h" /> | ||
<Extensions> | ||
<lib_finder disable_auto="1" /> | ||
</Extensions> | ||
</Project> | ||
</CodeBlocks_project_file> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# depslib dependency file v1.0 | ||
1576508940 source:c:\project\uml-state-machine-in-c\src\hsm.c | ||
<stdint.h> | ||
<stdbool.h> | ||
<stdio.h> | ||
"hsm.h" | ||
|
||
1577012586 c:\project\uml-state-machine-in-c\src\hsm.h | ||
"hsm_config.h" | ||
|
||
1581235125 c:\project\uml-state-machine-in-c\demo\toaster_oven\build\hsm_config.h | ||
|
||
1581258355 source:c:\project\uml-state-machine-in-c\demo\toaster_oven\src\main.c | ||
<stdint.h> | ||
<stdio.h> | ||
<pthread.h> | ||
<unistd.h> | ||
<semaphore.h> | ||
<stdbool.h> | ||
"hsm.h" | ||
"toaster_oven.h" | ||
|
||
1581236460 c:\project\uml-state-machine-in-c\demo\toaster_oven\src\toaster_oven.h | ||
|
||
1581260451 source:c:\project\uml-state-machine-in-c\demo\toaster_oven\src\toaster_oven.c | ||
<stdint.h> | ||
<stdio.h> | ||
<stdbool.h> | ||
"hsm.h" | ||
"toaster_oven.h" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | ||
<CodeBlocks_layout_file> | ||
<FileVersion major="1" minor="0" /> | ||
<ActiveTarget name="Debug" /> | ||
<File name="..\..\CMakeLists.txt" open="1" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | ||
<Cursor> | ||
<Cursor1 position="847" topLine="6" /> | ||
</Cursor> | ||
</File> | ||
<File name="..\..\..\..\src\hsm.c" open="1" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | ||
<Cursor> | ||
<Cursor1 position="8467" topLine="204" /> | ||
</Cursor> | ||
</File> | ||
<File name="..\..\readme.md" open="1" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | ||
<Cursor> | ||
<Cursor1 position="1767" topLine="15" /> | ||
</Cursor> | ||
</File> | ||
<File name="..\..\src\toaster_oven.h" open="1" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | ||
<Cursor> | ||
<Cursor1 position="1871" topLine="84" /> | ||
</Cursor> | ||
</File> | ||
<File name="..\..\..\..\src\hsm.h" open="1" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | ||
<Cursor> | ||
<Cursor1 position="2067" topLine="50" /> | ||
</Cursor> | ||
</File> | ||
<File name="..\..\src\toaster_oven.c" open="1" top="1" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | ||
<Cursor> | ||
<Cursor1 position="5759" topLine="220" /> | ||
</Cursor> | ||
</File> | ||
<File name="..\..\src\main.c" open="1" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | ||
<Cursor> | ||
<Cursor1 position="2017" topLine="63" /> | ||
</Cursor> | ||
</File> | ||
</CodeBlocks_layout_file> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* \file | ||
* \brief hierarchical state machine | ||
* \author Nandkishor Biradar | ||
* \date 17 December 2018 | ||
* Copyright (c) 2018-2019 Nandkishor Biradar | ||
* https://github.com/kiishor | ||
* Distributed under the MIT License, (See accompanying | ||
* file LICENSE or copy at https://mit-license.org/) | ||
*/ | ||
|
||
#ifndef HSM_CONFIG_H | ||
#define HSM_CONFIG_H | ||
|
||
// configuration file for hierarchical state machine. | ||
|
||
// Enable the state machine logging | ||
// 0: disable the state machine logger | ||
// 1: enable the state machine logger | ||
#define STATE_MACHINE_LOGGER 1 | ||
|
||
#endif // HSM_CONFIG_H |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
Toaster Oven state machine | ||
========================== | ||
|
||
## State diagram | ||
This example demonstrates a hierarchical state machine of a toaster oven as shown below. | ||
|
||
![Toaster oven: Hierarchical state machine](docs/Toaster_oven.svg) | ||
|
||
## States | ||
### 1. Door Close state | ||
This is a composite state and contains two substates. | ||
- **Entry action**: Turn off the oven lamp. | ||
|
||
#### a. Off state | ||
This state represents that oven is off. Supported events are events are, | ||
- **Start** : This event turn on the heater and heating timer. | ||
It also triggers the state transition to On state. | ||
- **Door_Open** : This event turns off the heater and pauses the heating timer. | ||
It also triggers the state transition to Door open state. | ||
|
||
#### b. On state | ||
This state represents oven is on (i.e. heater is on and timer is running). | ||
- **Entry action**: Turn on the heater. | ||
- **Exit action** : Turn off the heater. | ||
- **Stop** : This event turns off the heater and heating timer. | ||
It also triggers the state transition to off state. | ||
- **TimeOut** : This event turns off the heater and triggers the state transition to off state. | ||
- **Door_Open** : This event pauses the triggers the state transition to Door open state. | ||
|
||
### 2. Door Open state | ||
This state supports **Door_Close** event. | ||
- **Entry action**: Turn on the oven lamp. | ||
- **Door_Close** : This event triggers the state transition based on the resume timer. | ||
If resume time is greater than zero then it traverses to on state else it to off state. | ||
|
||
## Supported events | ||
1. Start | ||
2. Stop | ||
3. Door_Open | ||
4. Door_Close | ||
5. Timeout | ||
|
||
## How to use framework | ||
|
||
toaster_oven.c and toaster_oven.h files contain an implementation of oven state machine. | ||
|
||
### List of supported events | ||
|
||
Define the list of supported events as an enumeration in the header file of your state machine `toaster_oven.h`. | ||
event value must be non-zero. Hence initialize the first enum value to 1. | ||
```C | ||
//! List of oven events | ||
typedef enum | ||
{ | ||
EN_START = 1, | ||
EN_STOP, | ||
EN_DOOR_OPEN, | ||
EN_DOOR_CLOSE, | ||
EN_TIMEOUT, | ||
}oven_event_t; | ||
``` | ||
|
||
### State machine | ||
|
||
Create a structure derived from the `state_machine_t` that contains all the required variables for your state machine. | ||
|
||
```C | ||
//! Oven state machine | ||
typedef struct | ||
{ | ||
state_machine_t Machine; //!< Abstract state machine | ||
uint32_t Set_Time; //!< Set time of a oven | ||
uint32_t Resume_Time; //!< Remaining time when the oven is paused | ||
uint32_t Timer; //!< Oven timer | ||
bool Lamp; //!< Oven lamp | ||
bool Heater; //!< Oven heater | ||
}oven_t; | ||
``` | ||
Make sure that `state_machine_t` must be the first element in the derived structure. | ||
|
||
### state | ||
|
||
state_t in the hierarchical state machine contains an extra three members compared to finite state machine. | ||
```C | ||
const state_t* const Parent; //!< Parent state of the current state. | ||
const state_t* const Node; //!< Child states of the current state. | ||
uint32_t Level; //!< Hierarchy level from the top state. | ||
``` | ||
|
||
This demo uses macro to define the states. This macro make code more readable and maintainable | ||
and also reduces manual hardcoding of data. | ||
|
||
```C | ||
#define ADD_ROOT(NAME, HANDLER, ENTRY, EXIT, CHILD) | ||
``` | ||
Use this macro to add root state to the state machine. `DOOR_CLOSE_STATE` is defined using this macro. | ||
- This state doesn't contain parent state. | ||
- Level is zero | ||
- It is composite state and contains substates. | ||
--- | ||
|
||
```C | ||
#define ADD_ROOT_LEAF(NAME, HANDLER, ENTRY, EXIT) | ||
``` | ||
- This state doesn't contain parent state. `ADD_ROOT_LEAF` is defined using this macro. | ||
- Level is zero | ||
- It is a simple state and doesn't contains substates. | ||
--- | ||
|
||
```C | ||
#define ADD_LEAF(NAME, HANDLER, ENTRY, EXIT, PARENT, LEVEL) | ||
``` | ||
Use this macro to add leaf state to the composite state. `OFF_STATE` and `ON_STATE` are defined using this macro. | ||
- It is a simple state and doesn't contains substates. | ||
--- | ||
|
||
```C | ||
#define ALL_OVEN_STATES \ | ||
ADD_ROOT_LEAF(DOOR_OPEN_STATE, door_open_handler, door_open_entry_handler, NULL) \ | ||
ADD_ROOT(DOOR_CLOSE_STATE, NULL, door_close_entry_handler, NULL, Door_Close_State) \ | ||
|
||
#define ALL_DOOR_CLOSED_STATES(PARENT, LEVEL) \ | ||
ADD_LEAF(OFF_STATE, off_handler, off_entry_handler, NULL, PARENT, LEVEL) \ | ||
ADD_LEAF(ON_STATE, on_handler, on_entry_handler, on_exit_handler, PARENT, LEVEL) | ||
``` | ||
These macro's are used for creating the enumeration of `oven_state_t` and `door_close_state_t`. | ||
Also to initialize the state_t structures `Oven_State` and `Door_Close_State`. | ||
each state has function pointers to its event handler, entry and exit actions. | ||
The event handler must be initialized for each state. | ||
the entry and exit actions are optional, if not required then can be initialized as NULL. | ||
### event handler, entry and exit actions | ||
Define event handler, entry and exit action's based on following function signature | ||
```C | ||
typedef state_machine_result_t (*state_handler) (state_machine_t* const state); | ||
``` | ||
|
||
If handler supports the passed event, then it consumes the event and returns the status as `EVENT_HANDLED`. | ||
|
||
Use `switch_state` to switch state when the source state and target state have same parent state. | ||
e.g. switch from `OFF_STATE` to `ON_STATE` and vice versa. | ||
|
||
Use `traverse_state` for traversing from source state to target state when both have different parent state. | ||
e.g. switch from `DOOR_OPEN_STATE` to `OFF_STATE` / `ON_STATE` and vice versa. | ||
|
||
If handler doesn't support the passed event then return result as `EVENT_UN_HANDLED`. | ||
If the handler consumes the event and generates the new event then return the status as `TRIGGERED_TO_SELF`. | ||
|
Oops, something went wrong.