summaryrefslogtreecommitdiff
path: root/experiments/length-RFast-grapheme.csv
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-26 01:13:28 -0300
committerGabriel Schneider <[email protected]>2026-08-26 01:13:28 -0300
commite1526395233aad15dc9e2fdb49d5842de3e7e77b (patch)
treea5ff0bdaf693ab2189ab7ea4a0219aa9262e26af /experiments/length-RFast-grapheme.csv
parent110eeeb80181b990901c22d28fa4fd41dd10cdd7 (diff)
downloadesp32p4-e1526395233aad15dc9e2fdb49d5842de3e7e77b.tar.gz
esp32p4-e1526395233aad15dc9e2fdb49d5842de3e7e77b.zip
Drain the receiver while the transmitter is full: keystrokes were being lost
Reported as "a key is stuck and is only sent when I send a new event". It was neither stuck nor late - it was gone, and a later frame repainting those cells is what made it look like it arrived eventually. The loop is read, apply, render, write, and `uart.write` blocks while the transmit FIFO is full. That wait is real backpressure and should stay: dropping half an escape sequence leaves the host terminal in the wrong colour for the rest of the session. But NOTHING drained the receive FIFO during it, and that FIFO is 128 bytes - 11 ms of wire at 115200. Measured on the die, typing a burst in one host write and counting what the firmware's loop actually took off the UART: burst before after after + chunked input 128 128 128 128 200 197 200 200 300 257 300 300 600 478 600 600 1200 - 1200 1200 2400 - 2316 2400 4096 - 3611 4096 Two windows had to close, and the second was only visible once the first was shut. `input_rescue.pump` drains the receiver on every iteration of the wait for transmitter room. That is the big one, and it is the whole reason this policy lives in its own file: `uart.zig` cannot be tested without the chip because every line of it is an MMIO access, while `pump` takes its port as `anytype` and runs against a fake with a two-byte transmit FIFO and an eight-byte receive FIFO in `zig build test`. The fake models the receive FIFO the way the hardware behaves - a byte arriving into a full FIFO is simply gone - so the test fails by 67 lost bytes with the rescue removed, which is the die's 88-of-200 in miniature. It also caught a flaw in its own first draft: a fake whose transmit FIFO drains as fast as it fills never blocks, so `pump` never waits and the test proves nothing. The second window was APPLYING the input. A keystroke costs 44 us on an empty line and 63 us at 640 characters, so handing the editor a full 128-byte batch is up to 8 ms in which nothing drains the receiver - against 11 ms of FIFO. The loop now feeds the editor eight bytes at a time and rescues between chunks. Splitting a burst at an arbitrary byte is already safe, because `pardes_p4_input` keeps whatever it could not parse; that is how it survives an escape sequence split across two UART reads. One render still happens per loop iteration, so this costs no extra wire. Eight rather than thirty-two by measurement: 32 left 2400 and 4096 lossy, 8 does not. Beyond 4096 bytes in one burst the editor genuinely cannot keep up, and the ring reports what it abandoned instead of losing it silently - `rxdrop` in the PROF line, alongside a running count of received bytes. That counter is the other lesson here: the first attempt at measuring this counted characters on the reconstructed screen, which cannot distinguish "never arrived" from "arrived but off the edge of the viewport", and it disagreed with the hardware in both directions. No cost to latency: round trip median 3687 us over 60 trials against 3687 before, maximum 3866, screen byte-identical to the vaxis reference, host tests green.
Diffstat (limited to 'experiments/length-RFast-grapheme.csv')
0 files changed, 0 insertions, 0 deletions