Compare commits

..

No commits in common. "160f6bb799ff1e11562da4da91a31bfdbed795e7" and "62dff1264ddb0ac911961e0981c78b5f9adccc4f" have entirely different histories.

View File

@ -108,26 +108,16 @@ static void emit_record(u8 kind, u8 value, u8 flags)
/* --- busy-poll helper ---------------------------------------------------- */ /* --- busy-poll helper ---------------------------------------------------- */
/* /*
* Spin until CLK reaches `want_asserted`, or timeout/ATN-change/RESET. Caller * Spin until CLK reaches `want_asserted`, or timeout/ATN/RESET. Caller holds
* holds local IRQs disabled. Uses a microsecond budget rather than a fixed * local IRQs disabled. Uses a microsecond budget rather than a fixed udelay so
* udelay so a slightly-fast C64 is handled correctly (research §1.3). * a slightly-fast C64 is handled correctly (research §1.3).
*
* The ATN abort is phase-relative, and IEC_RX_ATN means "ATN changed, abort":
* - data_phase: ATN is released; abort if it ASSERTS (C64 interrupts data
* transfer with a new command).
* - command phase: ATN is asserted for the whole command byte; abort if it
* RELEASES (the command sequence is over -> hand back to the state machine).
* Treating any asserted ATN as an abort (the previous behaviour) made command
* reception impossible: ATN is legitimately low the entire command phase, so
* the very first poll aborted before a single bit was clocked.
*/ */
static enum iec_rx wait_clk(bool want_asserted, unsigned int timeout_us, static enum iec_rx wait_clk(bool want_asserted, unsigned int timeout_us)
bool data_phase)
{ {
unsigned int waited = 0; unsigned int waited = 0;
while (iec_clk_asserted() != want_asserted) { while (iec_clk_asserted() != want_asserted) {
if (iec_atn_asserted() == data_phase) if (iec_atn_asserted())
return IEC_RX_ATN; return IEC_RX_ATN;
if (iec_reset_asserted()) if (iec_reset_asserted())
return IEC_RX_RESET; return IEC_RX_RESET;
@ -153,7 +143,7 @@ static enum iec_rx receive_byte(u8 *out, bool *eoi, bool data_phase)
*eoi = false; *eoi = false;
/* 1. READY-FOR-DATA: wait for talker to release CLK, then release DATA */ /* 1. READY-FOR-DATA: wait for talker to release CLK, then release DATA */
rc = wait_clk(false /* released */, IEC_CLK_TIMEOUT_US, data_phase); rc = wait_clk(false /* released */, IEC_CLK_TIMEOUT_US);
if (rc != IEC_RX_OK) if (rc != IEC_RX_OK)
return rc; return rc;
iec_data_release(); iec_data_release();
@ -181,12 +171,10 @@ static enum iec_rx receive_byte(u8 *out, bool *eoi, bool data_phase)
/* 3. RECEIVE 8 BITS, LSB first */ /* 3. RECEIVE 8 BITS, LSB first */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
rc = wait_clk(true /* asserted: data invalid/setup */, rc = wait_clk(true /* asserted: data invalid/setup */, IEC_CLK_TIMEOUT_US);
IEC_CLK_TIMEOUT_US, data_phase);
if (rc != IEC_RX_OK) if (rc != IEC_RX_OK)
goto out; goto out;
rc = wait_clk(false /* released: data valid -> sample */, rc = wait_clk(false /* released: data valid -> sample */, IEC_CLK_TIMEOUT_US);
IEC_CLK_TIMEOUT_US, data_phase);
if (rc != IEC_RX_OK) if (rc != IEC_RX_OK)
goto out; goto out;
/* released(high) = bit 1, asserted(low) = bit 0 */ /* released(high) = bit 1, asserted(low) = bit 0 */