Modeling the Casio F-91W with Statecharts: A Hardcore Embedded State Machine Practice

The Casio F-91W's multi-mode interaction is inherently a state machine, and modeling it with statecharts is clearer and more testable than if-else.
Using the Casio F-91W digital watch as an example, the article explains why multi-mode, multi-level devices with editing flows are well suited to modeling with Statecharts. It distinguishes flat FSMs from Harel's Statecharts, noting that hierarchical states, orthogonal regions, history states, and guards prevent state explosion, then covers the project's key design of translating button presses into semantic events via an input layer and implementing timeout-commit with a composite editing state and delayed events, and finally summarizes the benefits of structured testing and behavior traceability.
Why a Watch Is Worth Modeling with Statecharts
The Casio F-91W is a legend in the digital watch world. It's cheap, durable, and so simple to use that it barely needs a manual—but when you actually break it down into a software system, you'll find its interaction logic is far more complex than it appears on the surface: timing, alarms, stopwatch, hourly time signal, 12/24-hour format, date and day-of-week switching. These modes are switched and edited via the Mode button at the bottom-left and the Adjust button at the top-left.
A recent project that sparked discussion on Hacker News attempts to model the behavior of the F-91W using Statecharts. The project's core argument is that a device like the F-91W—multi-mode, multi-level, with editing states—is inherently a natural state machine, and describing it with statecharts gets closer to real interaction than a pile of if-else statements ever could.

Statecharts Are Not Just Ordinary State Machines
To understand this project, you first need to distinguish between a "finite state machine (FSM)" and a "statechart."
A regular FSM is flat: a set of states, a set of events, and events triggering state transitions. But the F-91W's interaction is nested—when you're in "alarm mode," you might be in an "hour editing" substate; pressing Adjust switches you to "minute editing," and pressing Light takes you back to the browsing state. Expressing this kind of hierarchy with a flat FSM quickly balloons into state explosion.
Statecharts were proposed by David Harel in 1987, with core extensions including:
- Hierarchical States: States can nest substates, and transitions on parent states can be inherited by all substates
- Orthogonal Regions: A system can be in multiple parallel states simultaneously, such as "display refresh" and "key handling" running in parallel
- History States: When returning to a composite state, it can remember the last substate you exited from
- Guards & Actions: Transitions can carry conditions and side effects
The F-91W's mode switching is perfectly suited to abstraction with hierarchical states: the top level is "time mode / alarm mode / stopwatch mode / hourly time signal setting," and each mode defines its own substates and editing flow internally. The Mode button handles top-level transitions, the Adjust button handles entering and navigating editing substates, and the Light button is a global, instantaneous action that doesn't change the mode state—this is a textbook use case for orthogonal regions or global events.
State Explosion refers to the phenomenon where, when modeling a complex system with a flat FSM, the number of states grows exponentially with independent dimensions. Suppose the F-91W had only four mutually independent dimensions—"current mode," "whether editing," "which field is being edited," and "12/24-hour format"—each with several possible values. A flat representation would have to enumerate the entire Cartesian product of these into mutually unrelated states, and the count would quickly exceed what any human could maintain. Worse, the same logical action (say, pressing Light to turn on the backlight) would need to be copied as a separate transition across dozens of states, so any requirement change would require sweeping modifications that are extremely easy to miss. Hierarchical states and orthogonal regions were designed precisely to eliminate this redundancy: shared behavior is lifted to a parent state or parallel region and defined only once, dropping the total state count from product-scale to sum-scale. This is the most fundamental engineering value of statecharts over FSMs.
Translating Button Semantics into Events
The F-91W has only three buttons: Mode, Adjust, and Light. A key design decision in the project is to distinguish each button's "short press" and "long press" into separate events, rather than judging press duration everywhere inside state transitions.
The benefit of this approach is that all transitions in the statechart are driven by semantic events, such as MODE_PRESS, ADJUST_PRESS, ADJUST_LONG_PRESS, and LIGHT_PRESS. Logic tightly coupled to hardware—button debouncing, long-press detection—is isolated in an input layer outside the state machine.
The transition logic for editing states thus becomes much clearer: in alarm mode, pressing Adjust enters hour editing, pressing Adjust again switches to minute editing, and pressing Adjust once more or waiting for a timeout commits the change and returns to the browsing state. Carrying this flow with an "editing session" composite state is far more reliable than maintaining a global editingField variable—a requirement like timeout-commit is nearly free to express in a statechart using delayed events.
Delayed Events are a standard mechanism in statechart implementations such as SCXML and XState: when entering a state, you can schedule an event that fires automatically after N milliseconds. If another transition leaves that state within that time, the timer is automatically cancelled. This maps naturally onto requirements like "timeout commit"—when entering the "editing session" composite state, attach a TIMEOUT delayed event; each user keypress resets or advances the editing flow, and once the input goes silent past the timeout, the commit fires automatically and the machine returns to the browsing state. Compared with hand-writing setTimeout and then checking in the callback whether you're still in an editing state, the cancellation semantics of delayed events are guaranteed by the state machine, so you won't get timer leaks or state mismatches. Button Debouncing is another layer: mechanical buttons produce multiple level bounces within a few milliseconds of being pressed and released, and without handling, these get recognized as multiple consecutive presses. By putting debouncing and long-press detection in the input layer, every event the statechart receives is already a clean, semantically discrete signal, and the transition logic no longer needs to care about timing details.
The Real Value of Statecharts: Testability and Traceability
This project was discussed on Hacker News largely not because of the F-91W itself, but because it demonstrates the practical value of statecharts in embedded and front-end interactions.
Once all device behavior is consolidated into a single statechart, you get two direct benefits:
First, testing becomes structured. You don't need to brute-force various button combinations and hope for the best—instead, you can write unit tests for each transition: given the current state and an event, assert the next state and output. State coverage becomes directly measurable.
Second, behavior becomes traceable. When a user reports "the watch face froze after I pressed Adjust," you can trace along the statechart to find which transition is missing a guard condition, or which substate has no exit. Compared with mentally simulating a pile of boolean flags while reading code, a statechart turns "what happens under what circumstances" into a diagram you can inspect with your own eyes.
State Coverage is a common metric for measuring test completeness, referring to how many states and transitions in a statechart the test cases have executed. It's closer to the real risk of interactive systems than line coverage: a piece of covered code may correspond to transition paths that have never been triggered, and user-reported bugs often hide on exactly those paths. In practice, you can require every transition to be reached by at least one test, asserting separately for branches where guards are true and false, so the test suite size scales linearly with the statechart size instead of combinatorially exploding like brute-forcing button combinations. Statecharts can also be exported directly by tools as test scripts or visual diagrams, letting "test cases" and "design documentation" share the same source of truth and avoiding the two drifting apart over time.
Takeaways for Developers at Home
If you're building a smartwatch, an in-car infotainment head unit, or any interactive system with multi-level menus and editing flows, the F-91W case study is worth referencing. Its complexity sits right between a "toy demo" and a "real product"—simple enough to explain clearly in a single article, yet realistic enough to expose the practical benefits of statecharts.
Common statechart implementations include XState (JavaScript/TypeScript), the SCXML specification, and various embedded state machine frameworks. When choosing, there's no need to pursue an "all-at-once" approach—start by drawing the substates within a single mode, then progressively fill in the top-level transitions for the Mode button. That's far more pragmatic than trying to draw the whole diagram from the start.
The F-91W proves something simple: the more a device appears simple, the more its interaction states deserve to be modeled carefully.
One-line Summary
The Casio F-91W's multi-mode interaction is inherently a state machine, and modeling it with statecharts is clearer and more testable than if-else.
Paragraph Summary
Using the Casio F-91W digital watch as an example, the article explains why multi-mode, multi-level devices with editing flows are well suited to modeling with Statecharts. The author first distinguishes flat FSMs from Harel's Statecharts, noting that hierarchical states, orthogonal regions, history states, and guards can prevent state explosion. It then covers the project's key design: translating the Mode/Adjust/Light buttons' short and long presses into semantic events, isolating debouncing and long-press detection in the input layer, and elegantly implementing timeout-commit via an "editing session" composite state with delayed events. Finally, it summarizes statecharts' two main benefits—structured testing and behavior traceability—and offers advice on incremental modeling and tool selection for developers building interactive systems like smartwatches and in-car head units.
Related articles

Chain of Thought Isn't Just for AI: How Humans Can Use CoT to Improve Thinking Quality
Chain of Thought isn't just a prompt trick for large models. Starting from a Hacker News discussion, this article analyzes why CoT works for human thinking too, breaks down actionable ways to transfer it, and highlights the key differences between human CoT and machine CoT.
Cloudflare Teams Up with OpenAI: Closi…
Cloudflare Teams Up with OpenAI: Closing the Loop from Vulnerability Discovery to Defense with AI
Cloudflare uses OpenAI Daybreak to investigate security vulnerabilities and generate reviewable remediation plans, while developers use Codex to boost coding efficiency and quality.

Orca Multi-Agent Orchestration in Practice: A Guide to Parallel Collaboration with Claude and Codex
Orca is Stable AI's free open-source agent workbench supporting 34 agents like Claude Code and Codex in parallel. Learn its Git worktree isolation, multi-model orchestration, and mobile management.