fix(kernel): allow command-phase byte reception while ATN is asserted #3

Merged
chris merged 1 commits from fix/command-phase-atn-abort into master 2026-06-20 03:36:35 +02:00
Owner

Summary

The IEC listener never decoded the LISTEN command and always fell through to "not addressed -> IDLE", so a real C64 transfer was never participated in. The captured logic-analyzer trace showed the same: the bus presence was acknowledged, but no per-byte handshake ever took place.

Root cause

wait_clk() aborted byte reception whenever ATN was asserted (low). However, ATN is held low for the entire command phase by design — that is precisely how the talker signals that the byte on the bus is a command.

As a result, the first wait_clk() poll inside receive_byte() saw ATN asserted and returned IEC_RX_ATN immediately, before a single bit was clocked. The state machine then busy-looped, re-entering receive_byte() (each call aborting instantly) until ATN was released — at which point addressed_listener was still false, dropping the bus to IDLE.

Fix

The ATN abort is now phase-relative, with IEC_RX_ATN meaning "ATN changed, abort":

  • Data phase (ATN released): abort if ATN asserts — the C64 is interrupting the data transfer with a new command.
  • Command phase (ATN asserted): abort if ATN releases — the command sequence has finished and control returns to the state machine.

The condition collapses neatly to iec_atn_asserted() == data_phase, and the phase flag is threaded through to all wait_clk() call sites in receive_byte().

Verification

Bit order and polarity were cross-checked against the real-printer captures and are unchanged: LSB-first, sample-on-CLK-release, released = 1. This reproduces the recorded bytes exactly ($24 -> LISTEN 4, $48 -> H). The command -> data turnaround now works: after the final command byte, the inter-byte wait_clk() observes the ATN release and the state machine proceeds into the addressed data phase.

The kernel module was not built or loaded as part of this change; on-hardware validation against a real C64 is expected to follow.

Closes #2

Generated by Clanker

## Summary The IEC listener never decoded the `LISTEN` command and always fell through to "not addressed -> IDLE", so a real C64 transfer was never participated in. The captured logic-analyzer trace showed the same: the bus presence was acknowledged, but no per-byte handshake ever took place. ## Root cause `wait_clk()` aborted byte reception whenever ATN was asserted (low). However, ATN is held low for the **entire command phase** by design — that is precisely how the talker signals that the byte on the bus is a command. As a result, the first `wait_clk()` poll inside `receive_byte()` saw ATN asserted and returned `IEC_RX_ATN` immediately, before a single bit was clocked. The state machine then busy-looped, re-entering `receive_byte()` (each call aborting instantly) until ATN was released — at which point `addressed_listener` was still `false`, dropping the bus to `IDLE`. ## Fix The ATN abort is now phase-relative, with `IEC_RX_ATN` meaning "ATN changed, abort": - **Data phase** (ATN released): abort if ATN *asserts* — the C64 is interrupting the data transfer with a new command. - **Command phase** (ATN asserted): abort if ATN *releases* — the command sequence has finished and control returns to the state machine. The condition collapses neatly to `iec_atn_asserted() == data_phase`, and the phase flag is threaded through to all `wait_clk()` call sites in `receive_byte()`. ## Verification Bit order and polarity were cross-checked against the real-printer captures and are unchanged: LSB-first, sample-on-CLK-release, released = 1. This reproduces the recorded bytes exactly (`$24` -> `LISTEN 4`, `$48` -> `H`). The command -> data turnaround now works: after the final command byte, the inter-byte `wait_clk()` observes the ATN release and the state machine proceeds into the addressed data phase. The kernel module was not built or loaded as part of this change; on-hardware validation against a real C64 is expected to follow. Closes #2 Generated by Clanker
chris added 1 commit 2026-06-20 03:12:26 +02:00
fix(kernel): allow command-phase byte reception while ATN is asserted
All checks were successful
Build kernel module / build (1:6.12.93-1+rpt1, bookworm) (pull_request) Successful in 1m18s
Build kernel module / build (1:6.18.34-1+rpt1, trixie) (pull_request) Successful in 1m13s
Build kernel module / release (pull_request) Has been skipped
c9cfebafda
wait_clk() aborted on any asserted ATN, but ATN is held low for the
entire command phase by design. Reception therefore aborted on the
first poll before clocking a single bit, so the listener never decoded
the LISTEN command and always fell through to "not addressed -> IDLE".

Make the ATN abort phase-relative via IEC_RX_ATN meaning "ATN changed":
in the data phase abort when ATN asserts (C64 interrupts with a new
command); in the command phase abort when ATN releases (command
sequence finished). The check collapses to
`iec_atn_asserted() == data_phase`.

Closes #2

Generated by Clanker

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
chris merged commit 160f6bb799 into master 2026-06-20 03:36:35 +02:00
chris deleted branch fix/command-phase-atn-abort 2026-06-20 03:41:20 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: chris/comodore-iec-emu#3
No description provided.