P77 proved that host input can raise machine external IRQ and return
cleanly through the bare-metal trap handler. P78 moves the delivery
point into AtomVM: the platform’s sys_poll_events notices the input
IRQ counter, drains the FIFO, and sends each event to the subscribed
Erlang process as {input, Event}.
P78 AtomVM input IRQ mailbox bridge starting
rendered frames: 1
input events: 6
input mailbox events: 6
input mailbox delivered: 6
input irq count: 2
input irq seen: true
input fifo status: 0
P78 AtomVM input IRQ mailbox bridge PASS
What changed
The game server calls chip:input_subscribe/0 from its own process.
That records the process id in platform data. When sys_poll_events
runs and sees the P77 trap counter change, it drains the MMIO FIFO and
uses globalcontext_send_message to enqueue one {input, Event} tuple
per host control.
| layer | new behavior |
|---|---|
| platform NIF | chip:input_subscribe/0 picks the mailbox target |
| scheduler wait hook | sys_poll_events treats the input IRQ count as a wake condition |
| platform delivery | FIFO words become Erlang {input, Event} messages |
| game loop | Tetris handles input in its receive loop instead of polling the FIFO |
| observability | chip:input_mailbox_count/0 reports delivered messages |
The scripted smoke queued six controls. The harness delivered all six,
the trap handler saw input IRQ, sys_poll_events delivered six mailbox
messages, the FIFO returned to 0, and the run halted PASS after
15,456,265 post-load cycles.
Limit
This is still a project-specific platform bridge. It is not the generic
AtomVM listener/port-driver model, and it still busy-polls mtime for
ordinary timeouts. The important proof is narrower but useful: host
controls can become normal Erlang messages on the chip.
Verification
cd projects/78_atomvm_irq_mailbox/test
make all
make verilator-run-input-smoke
SDL_VIDEODRIVER=dummy uv run --with pygame --with pillow ../viewer.py \
captured/frames/frame_0000.bin 128 96 --scale 4 \
--png captured/p78-irq-mailbox-smoke-frame.png
Honest Status
| check | status |
|---|---|
| AtomVM input IRQ mailbox bridge starts | PASS |
| Host FIFO input reaches harness | PASS |
| FIFO-not-empty input IRQ reaches M-mode trap handler | PASS |
sys_poll_events drains FIFO after input IRQ | PASS |
Erlang game server receives {input, Event} messages | PASS |
chip:input_mailbox_count/0 reports delivered messages | PASS |
| Tetris framebuffer renders | PASS |
| Scripted quit via mailbox input | PASS |
| Generic AtomVM listener/port-driver integration | NOT RUN |
| F/D architectural compliance | NOT RUN |
| LibreLane hardening | NOT RUN |
What just happened?
The viewer-to-chip control path now ends in the shape we wanted for the game: a running Erlang process receives input messages. That makes the interactive demo much less fake, while keeping the remaining AtomVM driver work clearly scoped.