enum, typedef and state machines
An enum gives integer constants names, and typedef gives the type a short name. Together they describe a state machine: a variable holds the current state, and a step function maps state plus event to the next state. Handling every case without a default lets the compiler flag a missed state.
enum and typedef
enum { ST_IDLE, ST_CONNECTING, ST_ONLINE } defines named integer constants, numbered 0, 1, 2 unless you give values. typedef names the type, so state_t s; reads better than enum state s;. A final ST_COUNT entry gives the number of states, handy for sizing tables such as names below.
A state machine in a switch
Firmware often waits for things: a button to settle, a reply to arrive, a timeout. A state machine makes that explicit. One variable holds the current state, and a step function takes the state and an event and returns the next state. Each call is short and never blocks, so it fits in a super-loop or an interrupt-driven design. Because every transition is in one place, the behaviour can be tested event by event on a PC.
#include <stdio.h>typedef enum { ST_IDLE, ST_CONNECTING, ST_ONLINE, ST_COUNT } state_t;typedef enum { EV_START, EV_ACK, EV_TIMEOUT } event_t;static const char *const names[ST_COUNT] = { "IDLE", "CONNECTING", "ONLINE" };static state_t step(state_t s, event_t e) { switch (s) { /* no default: -Wswitch flags a missing state */ case ST_IDLE: return (e == EV_START) ? ST_CONNECTING : ST_IDLE; case ST_CONNECTING: if (e == EV_ACK) { return ST_ONLINE; } return (e == EV_TIMEOUT) ? ST_IDLE : ST_CONNECTING; case ST_ONLINE: return (e == EV_TIMEOUT) ? ST_IDLE : ST_ONLINE; case ST_COUNT: break; } return ST_IDLE;}int main(void) { const event_t events[] = { EV_START, EV_TIMEOUT, EV_START, EV_ACK }; state_t s = ST_IDLE; for (unsigned i = 0; i < sizeof events / sizeof events[0]; i++) { state_t next = step(s, events[i]); printf("%-10s -> %s\n", names[s], names[next]); s = next; } return 0;}
IDLE -> CONNECTING CONNECTING -> IDLE IDLE -> CONNECTING CONNECTING -> ONLINE
Table-driven machines
When there are many states and events, a two-dimensional table, next_state[state][event], can replace the switch, often paired with a table of action functions. The whole machine is then data that can be read, reviewed and placed in Flash as const.