Last update: 240319 12:35:14 About State Machines.First litterature then in bottom more nerd c code Litterater/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 DOTdigraph 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 |