|
Last update: 250922 19:23:02 About State Machines.First litterature then in bottom more nerd c code Litteratur/links
Two videos (in danish)
State Machines based on function pointersThree based on function pointers State Machine based on C case switch constructionMaybe the most readable and therefore simple The one I useno more to say VideoA video and the written code for the case-swicth state machine idea Designing state machinesA whiteboard or blackboard is very usefull for discussing designs of your SM. Online tools (based on dot language e.g a->b; b->a; etc) might be what you need. http://viz-js.com/ is a dynamic that redraw during editing. The state machine can be downloaded as png or other formats. more to come fra https://stackoverflow.com/questions/68953216/hierarchical-state-machine-with-graphviz file [vendingsm here
digraph vendorMachine {
compound=true
graph [color=red]
node [color=red] // yuck style=filled fillcolor=yellow]
edge [color=red]
Entry[shape="point" label=""]
subgraph cluster_cancel {
label = "Cancel"
style = rounded
E2 [shape=rect label="" width=2 style=invis]
E2:sw->C0 [label=cancel]
C0 [label = <
<table cellborder="0" style="rounded">
<tr><td>C0</td></tr>
<hr/>
<tr><td></td></tr>
</table>
> margin=0 shape=none]
C25 [label = <
<table cellborder="0" style="rounded">
<tr><td>C25</td></tr>
<hr/>
<tr><td></td></tr>
</table>
> margin=0 shape=none]
C50 [label = <
<table cellborder="0" style="rounded">
<tr><td>C50</td></tr>
<hr/>
<tr><td></td></tr>
</table>
> margin=0 shape=none]
C75 [label = <
<table cellborder="0" style="rounded">
<tr><td>C75</td></tr>
<hr/>
<tr><td></td></tr>
</table>
> margin=0 shape=none]
subgraph cluster_DispenseC100Drink {
label = "DispenseC100Drink"
style = rounded
C100 [label = <
<table cellborder="0" style="rounded">
<tr><td>C100</td></tr>
<hr/>
<tr><td></td></tr>
</table>
> margin=0 shape=none]
subgraph cluster_DispenseC125Drink {
label = "DispenseC125Drink"
style = rounded
C125 [label = <
<table cellborder="0" style="rounded">
<tr><td>C125</td></tr>
<hr/>
<tr><td></td></tr>
</table>
> margin=0 shape=none]
C150 [label = <
<table cellborder="0" style="rounded">
<tr><td>C150</td></tr>
<hr/>
<tr><td></td></tr>
</table>
> margin=0 shape=none]
C175 [label = <
<table cellborder="0" style="rounded">
<tr><td>C175</td></tr>
<hr/>
<tr><td></td></tr>
</table>
> margin=0 shape=none]
C200 [label = <
<table cellborder="0" style="rounded">
<tr><td>C200</td></tr>
<hr/>
<tr><td></td></tr>
</table>
> margin=0 shape=none]
}
}
}
Entry -> C0
C0 -> C25[label=" Add\n$0.25 "]
C0 -> C50[label=" Add\n$0.50 "]
C25 -> C50[label=" Add\n$0.25 "]
C25 -> C75[label=" Add\n$0.50 "]
C50 -> C75[label=" Add\n$0.25 "]
C50 -> C100[label=" Add\n$0.50 "]
C100 -> C0[label=" Dispense\n $1.00 Drink " ltail="cluster_DispenseC100Drink"]
C75 -> C100[label=" Add\n$0.25 "]
C75 -> C125[label=" Add\n$0.50 "]
C100 -> C125[label=" Add\n$0.25 "]
C100 -> C150[label=" Add\n$0.50 "]
C125 -> C150[label=" Add\n$0.25 "]
C125 -> C175[label=" Add\n$0.50 "]
C125 -> C0[label=" Dispense\n $1.25 Drink " ltail="cluster_DispenseC125Drink"]
C150 -> C175[label=" Add\n$0.25 "]
C150 -> C200[label=" Add\n$0.50 "]
C175 -> C200[label=" Add\n$0.25 "]
C200 -> C0[label=" Dispense\n $2.00 Drink "]
}
ANOTHER FSM IN DOT
digraph finite_state_machine {
fontname="Helvetica,Arial,sans-serif"
node [fontname="Helvetica,Arial,sans-serif"]
edge [fontname="Helvetica,Arial,sans-serif"]
rankdir=LR;
node [shape = doublecircle]; 0 3 4 8;
node [shape = circle];
0 -> 2 [label = "SS(B)"];
0 -> 1 [label = "SS(S)"];
1 -> 3 [label = "S($end)"];
2 -> 6 [label = "SS(b)"];
2 -> 5 [label = "SS(a)"];
2 -> 4 [label = "S(A)"];
5 -> 7 [label = "S(b)"];
5 -> 5 [label = "S(a)"];
6 -> 6 [label = "S(b)"];
6 -> 5 [label = "S(a)"];
7 -> 8 [label = "S(b)"];
7 -> 5 [label = "S(a)"];
8 -> 6 [label = "S(b)"];
8 -> 5 [label = "S(a)"];
}
My own litle system
#include <stdio.h>
#include <unistd.h> // sleep
// States -- you need this forward dcl for the compiler and calling
// define NEXT(next,here,cond)
// |---- condition to be put on the arc in state machine
// |-------- state we are in just now (just for graph)
// |-------------- next state we will jump to
//
// all driven from main (or here setup fct)
typedef void *(*pFct)(void); // for typecast for calling function
#define NEXT(x,y,z) return ((pFct)x)
// my states
pFct led_on(); // as name indicates ...
pFct led_off();
pFct main_state();
pFct led_on() {
printf("on\n");
NEXT(main_state,led_on,back);
}
pFct led_off() {
printf("off\n");
NEXT(main_state,led_off,back);
}
pFct main_state()
{
static int t=0;
// pausefire
if (t==0) {
t = 1;
printf("main1\n");
NEXT(led_on, main_state, toOn);
}
else {
t = 0;
//delay
printf("main2\n");
NEXT(led_off, main_state, toOff);
}
// delay
}
void main() {
while(1) {
sleep(1);
statefunc = (*statefunc)();
}
}
Running the scripts in smdy.zip gives
|