From 16dcfbe22b6a925eade7d1bad3db01234bac4a5f Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Wed, 1 May 2019 21:40:32 +0930 Subject: [PATCH] begin implementing IEC serial protocol. --- c64/kernal/errors.s | 6 +++ c64/kernal/iec_assert_atn.s | 5 +++ c64/kernal/iec_assert_clk_and_data.s | 6 +++ c64/kernal/iec_assert_clk_release_data.s | 6 +++ c64/kernal/iec_release_clk.s | 5 +++ c64/kernal/iec_release_clk_and_data.s | 6 +++ c64/kernal/iec_tx_byte.s | 50 ++++++++++++++++++++++++ c64/kernal/iec_wait20us.s | 7 ++++ c64/kernal/iec_wait60us.s | 9 +++++ c64/kernal/iec_wait_for_data_release.s | 5 +++ c64/kernal/open.s | 47 +++++++++++++++++++++- c64/kernal/wait1ms.s | 14 +++++++ 12 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 c64/kernal/errors.s create mode 100644 c64/kernal/iec_assert_atn.s create mode 100644 c64/kernal/iec_assert_clk_and_data.s create mode 100644 c64/kernal/iec_assert_clk_release_data.s create mode 100644 c64/kernal/iec_release_clk.s create mode 100644 c64/kernal/iec_release_clk_and_data.s create mode 100644 c64/kernal/iec_tx_byte.s create mode 100644 c64/kernal/iec_wait20us.s create mode 100644 c64/kernal/iec_wait60us.s create mode 100644 c64/kernal/iec_wait_for_data_release.s create mode 100644 c64/kernal/wait1ms.s diff --git a/c64/kernal/errors.s b/c64/kernal/errors.s new file mode 100644 index 00000000..751a2194 --- /dev/null +++ b/c64/kernal/errors.s @@ -0,0 +1,6 @@ + + +kernalerror_DEVICE_NOT_FOUND: + lda #$05 + sec + rts diff --git a/c64/kernal/iec_assert_atn.s b/c64/kernal/iec_assert_atn.s new file mode 100644 index 00000000..407ee358 --- /dev/null +++ b/c64/kernal/iec_assert_atn.s @@ -0,0 +1,5 @@ +iec_assert_atn: + lda $dd0d + ora #$08 + sta $dd0d + rts diff --git a/c64/kernal/iec_assert_clk_and_data.s b/c64/kernal/iec_assert_clk_and_data.s new file mode 100644 index 00000000..8596466a --- /dev/null +++ b/c64/kernal/iec_assert_clk_and_data.s @@ -0,0 +1,6 @@ +iec_assert_clk_and_data: + lda $dd00 + and #$08 + ora #$30 + sta $dd00 + rts diff --git a/c64/kernal/iec_assert_clk_release_data.s b/c64/kernal/iec_assert_clk_release_data.s new file mode 100644 index 00000000..91fbe920 --- /dev/null +++ b/c64/kernal/iec_assert_clk_release_data.s @@ -0,0 +1,6 @@ +iec_assert_clk_release_data: + lda $dd00 + and #$08 + ora #$10 + sta $dd00 + rts diff --git a/c64/kernal/iec_release_clk.s b/c64/kernal/iec_release_clk.s new file mode 100644 index 00000000..ee227eb2 --- /dev/null +++ b/c64/kernal/iec_release_clk.s @@ -0,0 +1,5 @@ +iec_release_clk: + lda $dd00 + and #$18 + sta $dd00 + rts diff --git a/c64/kernal/iec_release_clk_and_data.s b/c64/kernal/iec_release_clk_and_data.s new file mode 100644 index 00000000..c8bc6d9e --- /dev/null +++ b/c64/kernal/iec_release_clk_and_data.s @@ -0,0 +1,6 @@ +iec_release_clk_and_data: + + lda $DD00 + and #$08 + sta $DD00 + rts diff --git a/c64/kernal/iec_tx_byte.s b/c64/kernal/iec_tx_byte.s new file mode 100644 index 00000000..6d609ff8 --- /dev/null +++ b/c64/kernal/iec_tx_byte.s @@ -0,0 +1,50 @@ +iec_tx_byte: + + ;; Do the actual transmission of 8 bits of data + ldx #8 + +iec_tx_byte_nextbit: + ;; Is next bit 0 or 1? + lsr + pha + bcs + + + ;; Setup 0 + jsr iec_assert_clk_release_data + jmp iec_tx_byte_l1 +* + ;; Setup 1 + jsr iec_assert_clk_and_data +iec_tx_byte_l1: + ;; Clock bit out + jsr iec_wait20us + jsr iec_release_clk + jsr iec_wait20us + + ;; More bits to send? + pla + dex + bpl iec_tx_byte_nextbit + + ;; Done sending bits. Wait for acknowledgement + jsr iec_assert_clk_release_data + + ;; Acknowledgement must happen within 1ms, else it + ;; is DEVICE NOT PRESENT + ;; We can't easily count rasters here, so we just + ;; try a set number of times + ldx #$ff +* lda $DD00 + bmi + + dex + bne - + + ;; Timeout - DEVICE NOT PRESENT + cli + jmp kernalerror_DEVICE_NOT_FOUND +* + ;; All done. + ;; End state is TALKER is asserting CLK, and listener is asserting DATA + ;; until they are ready for the next byte. + clc + rts diff --git a/c64/kernal/iec_wait20us.s b/c64/kernal/iec_wait20us.s new file mode 100644 index 00000000..e406780f --- /dev/null +++ b/c64/kernal/iec_wait20us.s @@ -0,0 +1,7 @@ + +iec_wait20us: + ;; Wait 20usec + ;; JSR + RTS already costs 12, so need only 8 more + ldx $dd00 + ldx $dd00 + rts diff --git a/c64/kernal/iec_wait60us.s b/c64/kernal/iec_wait60us.s new file mode 100644 index 00000000..e1abfdb5 --- /dev/null +++ b/c64/kernal/iec_wait60us.s @@ -0,0 +1,9 @@ +iec_wait60us: + + ;; Waste ~60 clock cycles (including JSR + RTS) + ldx #$06 +* lda $dd00 + dex + bpl - + + rts diff --git a/c64/kernal/iec_wait_for_data_release.s b/c64/kernal/iec_wait_for_data_release.s new file mode 100644 index 00000000..36232975 --- /dev/null +++ b/c64/kernal/iec_wait_for_data_release.s @@ -0,0 +1,5 @@ +iec_wait_for_data_release: + LDA $DD00 + and #$40 + beq iec_wait_for_data_release + rts diff --git a/c64/kernal/open.s b/c64/kernal/open.s index 33619b4b..a912220c 100644 --- a/c64/kernal/open.s +++ b/c64/kernal/open.s @@ -1,3 +1,48 @@ -; Function defined on pp272-273 of C64 Programmers Reference Guide + ; Function defined on pp272-273 of C64 Programmers Reference Guide + ;; See also http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf + + ;; Sequence is: + ;; 1. Call current device to attention as LISTENER = $20 + device + ;; 2. open: + + ;; Disable IRQs, since timing matters! + SEI + + ;; Begin sending under attention + jsr iec_assert_atn + jsr iec_assert_clk_release_data + + ;; Give devices time to respond + jsr wait1ms + + ;; Did a device respond? (DATA will be pulled if so) + lda $DD00 + bmi + + + ;; No devices present, so we can immediately return with device not found + cli + jmp kernalerror_DEVICE_NOT_FOUND +* + + ;; Release CLK and wait for DATA to release. + jsr iec_release_clk_and_data + + ;; Wait for DATA to be released + ;; Listener is allowed to hold DATA for as long as they want. + ;; i.e., this is the part of the protocol where the listener indicates + ;; that they are busy doing something, like processing the previous + ;; character. + jsr iec_wait_for_data_release + + ;; We then wait for 60 usec (less than 200usec so we don't + ;; signal EOI), before asserting CLK again. + jsr iec_wait60us + + ;; Re-assert CLK line + jsr iec_assert_clk_release_data + + ;; CLK is now asserted, and we are ready to transmit a byte + jsr iec_tx_byte + rts diff --git a/c64/kernal/wait1ms.s b/c64/kernal/wait1ms.s new file mode 100644 index 00000000..c2a24d44 --- /dev/null +++ b/c64/kernal/wait1ms.s @@ -0,0 +1,14 @@ + ;; 16 rasters = 16 x 63 cycles = ~1ms + ;; (Probably 2 will be bad lines, so we will over-estimate the delay a bit) + +wait1ms: + ldx #16 + lda $d012 +* + cmp $d012 + beq - + lda $d012 + dex + bne - + rts +