Timer Events
Timer behavior is split between TimerHandler and TimerTask.
TimerHandler reacts to button events and state changes. TimerTask publishes display countdown messages and TIMER_COUNTDOWN events while a timer is running.
Event Summary
| Event | Payload | Meaning |
|---|---|---|
TIMER_STARTED |
none | A full timer is considered started |
TIMER_CLEARED |
none | Timer was stopped/reset or returned idle |
TIMER_EXPIRED |
none | Timer or pause interval expired |
TIMER_COUNTDOWN |
timer_event.seconds_remaining |
Current remaining seconds |
Starting Timers
The timer handler listens for BUTTON_ACTION pressed events:
| Button | Behavior |
|---|---|
TIMER_120 |
starts timer120Seconds |
TIMER_60 |
starts timer60Seconds |
TIMER_530 with no active quizzer |
starts timer530SingleSeconds and enters the special five-timer state |
TIMER_530 with an active quizzer |
starts timer530DoubleSeconds |
CONTEST |
starts contestSeconds with a pause at contestPauseSeconds |
TIMER_RESET |
stops the timer, clears display when appropriate, publishes TIMER_CLEARED |
Defaults:
| Config field | Default |
|---|---|
timer_60_seconds |
60 |
timer_120_seconds |
120 |
timer_530_single_seconds |
5 |
timer_530_double_seconds |
30 |
contest_seconds |
150 |
contest_pause_seconds |
30 |
contest_gap_ms |
4000 |
Countdown Events
When a timer starts, TimerTask immediately publishes:
EventMessage {
type: TIMER_COUNTDOWN
timer_event {
seconds_remaining: <duration>
}
}
Then it publishes a new countdown event approximately once per second. When stopped, it publishes seconds_remaining=0.
Expiration
When a timer reaches the end, TimerTask calls back into TimerHandler, which publishes TIMER_EXPIRED.
The root timer handler responds to TIMER_EXPIRED by:
- publishing
TIMER_STARTED - writing
Expiredto the display if no quizzer is displayed - starting the configured holdoff timer
- playing the timer sound
The timerRunning state also has a TIMER_EXPIRED handler that plays the timer sound, resets the holdoff timer, and transitions idle. Because state handlers fall back through the parent state in the current state machine, clients should treat TIMER_EXPIRED, TIMER_STARTED, and TIMER_CLEARED as state notifications rather than a strict one-to-one request/response sequence.
Contest Timer
Contest mode starts a timer with a pause point. When the pause point is reached, the timer handler:
- writes
Contest?to the display - plays the contest timer sound
- waits
contest_gap_ms - resumes the timer automatically
Pressing CONTEST during the contest gap manually advances the gap handling by sending a local TIMER_EXPIRED event.
Display Interaction With Quizzers
Timer code tracks whether a quizzer has been displayed.
If a quizzer is displayed, timer reset and timer expiration paths avoid clearing or overwriting that display text in some cases. This is why QUIZZER_ACTIVE and QUIZZER_DISPLAYED are separate events.