P75 made Tetris playable, but input still had two bad properties: the chip consumed one event per NIF call, and the host viewer sent key-up and repeat noise into a tiny FIFO. P76 fixes the practical problem first. The host sends key-down commands only, and AtomVM drains queued input in one batched NIF call.
AtomVM on P76 (batched input bridge)
Found startup beam: game.beam
P76 AtomVM batched input bridge starting
rendered frames: 1
input events: 6
input batches: 1
input max batch: 6
input fifo status: 0
P76 AtomVM batched input bridge PASS
What changed
P76 keeps the P75 RTL FIFO, but changes the AtomVM side:
| layer | new piece |
|---|---|
| host | pygame writes event words into captured/input.fifo |
| harness | waits for host_input_ready before popping host events |
| RTL | 16-entry input FIFO, count field, saturated drop counter |
| viewer | sends key-down commands only, disables key repeat |
| AtomVM NIF | chip:input_events/0 drains queued events into one Erlang list |
| game | Tetris process applies the input batch and renders frames |
The scripted smoke queued six key events. The game drained all six as one batch, the RTL FIFO returned to zero, and the simulation exited cleanly after 14,284,133 post-load cycles.
A no-quit delayed-input run is closer to live play: it injected six
controls after the game started, rendered 301 frames, reported six input
events, changed the score to 40, and drained FIFO status to 0.
The first P76 attempt tried to make this a separate Erlang input-source
process. That is the shape we still want eventually, but it did not work
well enough here. receive after 1 missed live input, and a cooperative
after 0 process still did not produce useful on-screen control under
this AtomVM port. The working result is the conservative batched drain
inside the game tick.
Why not interrupts?
Interrupts need both sides wired. The hardware side can expose “input FIFO nonempty” as an IRQ condition, but the AtomVM bare-metal port still needs an M-mode trap handler, interrupt-enable setup, an IRQ acknowledge path, and a scheduler hook that wakes or runs the Erlang input source.
Just asserting external_irq would not safely deliver a process
message. P76 keeps the NIF boundary we need, but the actual separate
event source moves to the interrupt project.
Roadmap balance
AtomVM is one lane, not the whole project. The next few projects should keep three lanes visible:
| lane | near-term work |
|---|---|
| AtomVM | build the real interrupt/wakeup input source |
| Linux | return to userspace/init and platform-device proof points |
| MRuby | keep as a runtime side quest after the chip/host IO substrate is reusable |
What is not proven
F/D architectural compliance was NOT RUN. LibreLane hardening was NOT RUN. This is still RTL simulation, and P76 still polls from the game tick. It is not a hardware interrupt delivery result yet.
What just happened?
Host input now crosses into AtomVM in batches, and the viewer no longer spams the FIFO with key-up/repeat traffic. That made the game playable again and gave the interrupt project a sharper target.