esp32

Example of the component fishwaldo/fsm v0.2.0
# ESP32 example — button/LED machine with timers

A minimal but complete ESP-IDF application showing the library's intended
embedded usage: **the application is C**, the state machine is C++ behind an
`extern "C"` facade, and all timing flows through the machine's own deadlines.

## What it does

- BOOT button (GPIO0, active low), LED on GPIO2.
- Short press toggles the LED.
- Hold ≥ 1.5 s: the LED blinks at 4 Hz until released.
- Presses are debounced with a 30 ms qualification window.

All three timings — debounce, long-press, blink — are `fsm::after(...)`
columns in the state table ([main/button_fsm.cpp](main/button_fsm.cpp)); no
`esp_timer` callbacks, no timer tasks, no cancellation races.

## The event-loop pattern

[main/main.c](main/main.c) is the part worth copying:

1. The GPIO ISR posts edge events into a FreeRTOS queue — it never touches
   the machine.
2. The task asks `btn_next_deadline()` and blocks on `xQueueReceive` for
   exactly that long (the machine owns the nearest-deadline computation, so
   the loop cannot forget a timeout source).
3. Wake-ups deliver queued events via `btn_dispatch()`; `btn_service()`
   fires whatever came due. Arm, fire and transit all happen on this one
   task, which removes timer/cancel races *by construction*.

## Build

```sh
. $IDF_PATH/export.sh
idf.py set-target esp32        # or esp32s3/c3/...
idf.py build flash monitor
```

The `fsm` dependency is declared in [main/idf_component.yml](main/idf_component.yml):
building inside this repository resolves it from the source tree via
`override_path`, while a standalone copy of this example fetches
`fishwaldo/fsm` from the component registry. In your own project, depend on
it the same way:

```yaml
dependencies:
  fishwaldo/fsm: "^0.2.0"
```

Kconfig options live under *Component config → FSM library*
(`CONFIG_FSM_OBSERVER`, `CONFIG_FSM_INTROSPECTION`).

To create a project from this example, run:

idf.py create-project-from-example "fishwaldo/fsm=0.2.0:esp32"

or download archive (~7.61 KB)