/StateSmith

A state machine code generation tool suitable for bare metal, embedded and more.

Primary LanguageC#Apache License 2.0Apache-2.0

StateSmith

StateSmith is a cross platform, free/open source tool for generating state machines. The generated code is human readable, has zero dependencies and is suitable for use with tiny bare metal microcontrollers, kernels, or servers. It avoids dynamic memory allocations for the safety or performance inclined.

StateSmith will one day generate code for multiple different languages, but for now, the focus is on good old C (or C++) with zero dependencies.

picture 5

PlantUML input coming!

A fair number of people would like to avoid using a GUI for designing their state machines so I'm adding support for PlantUML input StateSmith#21 .

StateSmith will continue to support GUI diagram files which are super helpful for larger designs.

Demo

Here's a demo youtube video showing a Laser Tag menu implemented with StateSmith and running in an Arduino simulation.

picture 1

Quick Start ๐Ÿš€

Want to jump right in and just try it!? See quick-start.md

You'll be controlling a console light bulb's brightness in no time!

See also the examples.

Need help? Suggestion? Brainstorm?

Feel free to open a github issue.

Or you can use the project's discussion space.

Why StateSmith?

I couldn't find a state machine code generator that was suitable for low level embedded application use, had an attractive license, and was enjoyable to use.

Many options were painfully slow to use. You couldn't just start designing/writing code. You had to spend a bunch of time creating object oriented mappings of every little thing in an awkward GUI.

One of the reasons why I like StateSmith so much is that you can just get started using it and write code how you want. You can even start with pseudo code and gradually shape it into real code. Even though StateSmith uses a GUI for drawing state machines, all of a state's functionality is written in text - no annoying awkward GUIs that slow you down.

Human Readable Code

To make the generated code as enjoyable to look at as possible, there are a fair number of customizations possible. You can easily create a custom name mangling for pretty much everything.

The default naming strategy looks like this:

// State machine constructor...
void LaserTagMenu1Sm_ctor(LaserTagMenu1Sm* self);

But, you can easily customize to output another common naming convention like this:

// State machine constructor...
void blinky1_printf_sm_ctor(blinky1_printf_sm* self);

Show me the code!

In the future, StateSmith will support numerous state machine code generators. You'll be able to choose from super fast, balanced, and tiny size. You'll also be able to implement your own. The current code generation strategy implements a balanced approach that will work well for various targets.

For the below diagram, here's the generated .h file and .c file.

picture 6

The above state machine isn't very interesting. It just transitions between one state and another state when the do event is dispatched to it.

A more interesting example: Laser Tag Menu! Pew pew! ๐Ÿ”ซ

There are a bunch of examples. Below is one of them.

picture 7

You can interact with the generated laser tag menu code using the wokwi simulation.

Here's the menu layout:

APP
โ”œโ”€โ”€ HOME
โ”‚   โ”œโ”€โ”€ HOME1
โ”‚   โ”œโ”€โ”€ HOME2
โ”‚   โ””โ”€โ”€ HOME3
โ””โ”€โ”€ MAIN MENU
        โ”œโ”€โ”€ SELECT CLASS
        โ”‚   โ”œโ”€โ”€ ENGINEER
        โ”‚   โ”œโ”€โ”€ HEAVY
        โ”‚   โ”œโ”€โ”€ ARCHER
        โ”‚   โ”œโ”€โ”€ WIZARD
        โ”‚   โ””โ”€โ”€ SPY
        โ”‚โ”€โ”€ SHOW INFO
        โ”‚   โ”œโ”€โ”€ INFO 1
        โ”‚   โ”œโ”€โ”€ INFO 2
        โ”‚   โ””โ”€โ”€ INFO 3
        โ””โ”€โ”€ EAT BACK PRESSES
            โ””โ”€โ”€ <stuff to show event handling>

Here's the design diagram. To view inside collapsed states like MM_SELECT_CLASS, you'll need to open the diagram using the UI (see below).

User Interface

StateSmith doesn't actually provide a UI - it currently relies on the free to use, but closed source yEd editor.

picture 9

yEd is great because it is free to use (even for commercial use), cross platform, and meets our needs pretty well once you get used to it.

StateSmith parses the yEd xml file, builds some intermediate graph representations (which will allow user modification soon), then passes the graph to the code generator.

One major future goal is to create a draw.io vscode extension that we can use for the front end. StateSmith was written with this goal in mind so adding a different compiler front end will be relatively easy. The hard part is customizing draw.io to behave the way we need (entering collapsed groups). I did a quick proof of concept and it looks very doable, just needs time and hopefully an excited contributor that is good with web UIs :)

Why use yEd? I like that we just type in text. Some of the other strict UML State Machine tools I tried drove me crazy. It was just so slow to do anything.

How to use yEd for StateSmith

See ./docs/yed-training.md

Is StateSmith ready for use? ๐Ÿงช

StateSmith is generating working code, and has some decent test coverage, but I'm sure we are going to uncover some bugs.

Release 0.5.4-alpha added a lot of helpful error messages for when the input design is incorrect in some way:

Failed parsing diagram edge
from: Statemachine{LaserTagMenu1Sm}.State{MENUS_GROUP}.State{MM_SELECT_CLASS}
to:   Statemachine{LaserTagMenu1Sm}.State{MENUS_GROUP}.State{CLASS_SAVED}
Edge label: `via exitt saved`
Reason(s): mismatched input 'exitt' expecting {'entry', 'exit'} at line 1 column 4. Offending symbol: `exitt`.
           extraneous input 'saved' expecting <EOF> at line 1 column 10. Offending symbol: `saved`.
Edge diagram id: n0::n3::e3

The main thing I'd like to caution at this point is that there will be some refactoring in the near future which may affect user code generation scripts. Breaking changes and migration steps will be documented in ./CHANGELOG.md however and should be pretty minimal.

Features

See ./docs/diagram-features.md

How To Run StateSmith

StateSmith is still in alpha development phase so please be patient :)

There will eventually be a standalone CLI tool that has no installation dependencies and works cross platform. See issue 10.

For now, we actually just run StateSmith as a regular C# project from the command line, vscode, or visual studio.

Tutorial

See quick-start.md