fixes for IEC

This commit is contained in:
FeralChild64 committed 2019-06-20 16:49:35 +02:00
1 parent 28ce7e69bf
commit 5f57f58163
13 files changed
+167 -151

No files matched your search

@@ -0,0 +1,7 @@
iec_pull_data_release_atn_clock:
lda CI2PRA
ora #BIT_CI2PRA_DAT_OUT ; pull
and #$FF - BIT_CI2PRA_ATN_OUT - BIT_CI2PRA_CLK_OUT ; release
sta CI2PRA
rts
+83 -98
View File
@@ -1,118 +1,103 @@
;; Receive a byte from the IEC bus.
;; reference http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; page 11.
;; XXX rework this, according to pagetable.com
;; Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc,
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf (page 11)
iec_rx_byte:
;; First, we wait for the talker to release the CLK line
jsr iec_wait_for_clk_release
;; We then release the DATA to signal we are ready
;; We can use this routine, since we weren't pulling CLK anyway
jsr iec_release_clk_data
;; Wait for talker to pull CLK.
;; If over 200 usec (205 cycles on NTSC machine) , then it is EOI.
;; Loop iteraction takes 13 cycles, 17 full iterations are enough
ldx #$11 ; 2 cycles
iec_rx_clk_wait:
lda CI2PRA ; 4 cycles
rol ; 2 cycles, to put BIT_CI2PRA_CLK_IN as the last bit
bpl iec_rx_not_eoi ; 2 cycles if not jumped
dex ; 2 cycles
bne iec_rx_clk_wait ; 3 cycles if jumped
;; Timeout - wait for pulled CLK and pull data for 60 usec to confirm
jsr iec_wait_for_clk_pull
jsr iec_release_clk_pull_data
jsr iec_wait60us
jsr iec_release_clk_data
;; Store EOI information in IOSTATUS - XXX this should be done by the caller!
lda IOSTATUS
ora #$40
sta IOSTATUS
sec
rts
; ;; First, we wait for the talker to release the CLK line.
; ;; XXX jsr iec_wait_for_clock_release
iec_rx_not_eoi:
; ;; We then release the data line
; ;; (We can use this routine, since we weren't holding CLK, anyway)
; jsr iec_release_clk_and_data
;; Latch input bits in on rising edge of CLK, eight times for eight bits.
ldx #7
; ;; Wait for talker to assert CLK.
; ;; If >200usec, then it is EOI and we have to assert the
; ;; DATA line for 60 usec to tell the TALKER that we have
; ;; acknowledged the EOI.
; ldx #20
iec_rx_clk_wait:
; ;; Loop takes 11 usec, so ~20 iterations for 200usec timeout
; lda $dd00
; rol
; bpl not_eoi
; dex
; cpx #$21
; bne not_rx_timeout
; ;; Time out waiting for CLK to assert again.
; ;; = error
; sec
; rts
not_rx_timeout:
; cpx #$00
; bpl iec_rx_clk_wait
; ;; Remember EOI condition
; lda IOSTATUS
; ora #$40
; sta IOSTATUS
; ;; EOI timeout: So pulse DATA line for 60 usec
; jsr iec_assert_data
; jsr iec_wait60us
; jsr iec_release_clk_and_data
; ;; And still wait for CLK to be asserted
; ;; XXX - This will cause periodic EOI pulses if the sender takes too long.
; ;; That is probably ok.
; ldx #$7f
; jmp iec_rx_clk_wait
not_eoi:
; ;; CLK is now low. Latch input bits in on rising edge
; ;; of CLK, eight times for eight bits.
; ldx #7
; ;; Get empty byte to load into.
; lda #$00
; pha
;; Get empty byte to load into.
lda #$00
pha
iec_rx_bit_loop:
; ;; Wait for CLK to release
; ;; jsr iec_wait_for_clock_release
; ;; (we do this implicitly below, with a tighter routine,
; ;; so that we don't have timing problems, as the requirements
; ;; are quite tight. Basically we need to read the clock and data
; ;; bit from the same byte read.
;; Wait for CLK to release
jsr iec_wait_for_clk_release
; ;; DATA now has the next bit, but inverted (well, except that it turns out not to be).
; ;; DATA is in bit7, which is a bit annoying.
; ;; But we can clock it out with a ROL instruction
; ;; so that it is in C. We can then ROR it into the
; ;; partial data byte.
; ;; We use ROR so that we shift in from the top, so that
; ;; the first bit we shift in ends up in bit 0 after all
; ;; 8 bits have been read.
; ;; ODD: For some reason we don't need to invert the
; ;; received bits. This is weird, because we invert them
; ;; on the way out, and everything in the protocol seems
; ;; to indicate that we sould do so. But experimentation
; ;; has confirmed the bits don't need inversion on reception.
;; (we do this implicitly below, with a tighter routine,
;; so that we don't have timing problems, as the requirements
;; are quite tight. Basically we need to read the clock and data
;; bit from the same byte read.
; ;; Move data bit into C flag, and loop until bit 6 clears
; ;; i.e., the clock has been released.
;* LDA $DD00
; ROL
; bpl -
;; DATA now has the next bit, but inverted (well, except that it turns out not to be).
;; DATA is in bit 7, which is a bit annoying.
;; But we can clock it out with a ROL instruction
;; so that it is in C. We can then ROR it into the
;; partial data byte.
;; We use ROR so that we shift in from the top, so that
;; the first bit we shift in ends up in bit 0 after all
;; 8 bits have been read.
;; ODD: For some reason we don't need to invert the
;; received bits. This is weird, because we invert them
;; on the way out, and everything in the protocol seems
;; to indicate that we sould do so. But experimentation
;; has confirmed the bits don't need inversion on reception.
; ;; Pull it into the data byte
;; pla
; ROR
; pha
;; Move data bit into C flag, and loop until bit 6 clears
;; i.e., the clock has been released.
* lda CI2PRA
rol
bpl -
; ;; Wait for CLK to re-assert
; jsr iec_wait_for_clock_assert
;; Pull it into the data byte
pla
ror
pha
; ;; More bits?
; dex
; bpl iec_rx_bit_loop
;; Wait for CLK to be pulled again
jsr iec_wait_for_clk_pull
; ;; Then we must within 1000usec acknowledge the frame by
; ;; asserting DATA. At this point, CLK is asserted by the
; ;; talker and DATA by us, i.e., we are ready to receive
; ;; the next byte. (p11).
; jsr iec_assert_data
;; More bits?
dex
bpl iec_rx_bit_loop
; ;; Retreive the received byte
; PLA
;; Then we must within 1000 usec acknowledge the frame by
;; pulling DATA. At this point, CLK is pulled by the
;; talker and DATA by us, i.e., we are ready to receive
;; the next byte. (p11).
jsr iec_release_clk_pull_data
; ;; Return no-error
; CLC
; RTS
;; Retreive the received byte
pla
;; Return no-error
clc
rts
+20 -30
View File
@@ -1,39 +1,29 @@
;; According to http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; pages 7--8.
;; See also https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
iec_turnaround_to_listen:
;; Assert data and release clock
lda $dd00
and #$ef ; release clock (bit 4)
ora #$20 ; assert data (bit 5)
sta $dd00
;; Wait for clock line to be asserted by the drive
* lda $dd00
and #$40
;; Pull DATA, release CLK and ATN (we are not sending commands)
jsr iec_pull_data_release_atn_clock
;; Wait for clock line to be pulled by the drive
ldx #$FF ; XXX should we really use that high number?
*
lda CI2PRA
rol ; to put BIT_CI2PRA_CLK_IN as the last (sign) bit
bpl +
dex
bne -
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; page 8 tells us we should not do anything here after waiting for
;; the clock line to assert.
ldx #$ff
* lda $dd00
and #$40
bne +
dex
bne -
;; Timeout
jsr printf
.byte "DBG: TURNAROUND FAILED",$0d,$00
sec
rts
;; jsr printf
;; .byte "TURNAROUND FAILED - FILE NOT FOUND?",$0d,$00
;; ;; Timeout = file not found error
;; ;; (https://www.pagetable.com/?p=1023)
lda #4
sec
rts
*
;; ATN turn around successful
;; CLK is pulled by the device, OK
*
clc
rts
+1 -1
View File
@@ -35,7 +35,7 @@ iec_tx_command:
;; Common part of iec_txbyte and iec_tx_common - waits for devices
;; and transmits a byte
pla
jsr iec_tx_common
+10 -4
View File
@@ -6,11 +6,12 @@ iec_tx_common:
;; Store the bye to send on a stack
pha
;; Wait till all receivers are ready, they should all release DATA
jsr iec_wait_for_data_release
;; Pull CLK back to indicate that DATA is not valid, keep it for 60us
;; We can use this routine as we don't hold DATA anyway (and its state doesn't even matter)
;; Don't wait too long, as 200us or more is considered EOI
jsr iec_pull_clk_release_data
@@ -42,11 +43,14 @@ iec_tx_common_bit_is_sent:
pla
dex
bpl iec_tx_common_nextbit
;; Whole byte send, make sure ATN is released
jsr iec_release_atn_clk_data
;; XXX the flow below is REALLY dangerous, as if there are multiple devices,
;; one can signal that it's busy much earlier (more than 100ms) than the other.
;; Can we do something about it?
;; All done - give devices time to tell if they are busy by pulling DATA
;; They should do it within 1ms
ldx #$FF
@@ -62,7 +66,9 @@ iec_tx_common_bit_is_sent:
jsr iec_wait100us
iec_tx_common_done:
;; Byte sent, return
clc
rts
iec_tx_common_nextbit:
+2 -1
View File
@@ -1,9 +1,10 @@
iec_tx_eoi:
;; Wait at least 200us
;; Wait at least 256 usec
jsr iec_wait100us
jsr iec_wait100us
jsr iec_wait60us
;; Restore the bus to idle state
jsr iec_set_idle
+2 -2
View File
@@ -4,9 +4,9 @@ iec_wait100us:
;; Wait 100usec
;; PAL:
;; - CPU frequency 0.985248 MHz, we need to waste at least 102 cycles
;; - CPU frequency 0.985248 MHz, we need to waste at least 99 cycles
;; NTSC:
;; - CPU frequency 1.022727 MHZ, we need to waste at least 98 cycles
;; - CPU frequency 1.022727 MHZ, we need to waste at least 103 cycles
;; Waste cycles by reading some unimportant memory location
;; (in a loop) in order not to clutter VICE debug logs
+2 -2
View File
@@ -4,9 +4,9 @@ iec_wait20us:
;; Wait 20usec
;; PAL:
;; - CPU frequency 0.985248 MHz, we need to waste at least 21 cycles
;; - CPU frequency 0.985248 MHz, we need to waste at least 20 cycles
;; NTSC:
;; - CPU frequency 1.022727 MHZ, we need to waste at least 20 cycles
;; - CPU frequency 1.022727 MHZ, we need to waste at least 21 cycles
;; Waste cycles by reading some unimportant memory location
;; in order not to clutter VICE debug logs
+2 -2
View File
@@ -4,9 +4,9 @@ iec_wait60us:
;; Wait 60usec
;; PAL:
;; - CPU frequency 0.985248 MHz, we need to waste at least 61 cycles
;; - CPU frequency 0.985248 MHz, we need to waste at least 60 cycles
;; NTSC:
;; - CPU frequency 1.022727 MHZ, we need to waste at least 59 cycles
;; - CPU frequency 1.022727 MHZ, we need to waste at least 62 cycles
;; Waste cycles in a loop
+6
View File
@@ -0,0 +1,6 @@
iec_wait_for_clk_pull:
lda CI2PRA
rol ; to put BIT_CI2PRA_CLK_IN as the last (sign) bit
bmi iec_wait_for_clk_pull
rts
+6
View File
@@ -0,0 +1,6 @@
iec_wait_for_clk_release:
lda CI2PRA
and #BIT_CI2PRA_CLK_IN
beq iec_wait_for_clk_release
rts
+17 -11
View File
@@ -15,9 +15,6 @@ open:
bcs +
bmi open_has_space
*
jsr printf
.byte "FULL", $0D, 0
;; Table is full - according to https://codebase64.org/doku.php?id=base:kernalreference
;; C flag set means error occured
sec
@@ -74,11 +71,9 @@ open_rs232:
open_iec:
;; XXX add FILENAM support, test it
;; Part implemented according to https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
;; Sequence is:
;; 1. Call current device to attention as LISTENER = $20 + device
;; 2.
;; XXX for now for channel 15 only!
;; Disable IRQs, since timing matters!
sei
@@ -86,14 +81,25 @@ open_iec:
;; Begin sending under attention
;; XXX jsr iec_assert_atn
;; CLK is now asserted, and we are ready to transmit a byte
;; Request device to talk
lda current_device_number
jsr listen
bcs open_iec_error
jsr talk
bcs open_iec_error ; XXX what about the accumulator?
jsr printf
.byte "DBG: OPEN 1", $0D, 0
;; Send secondary address
lda current_secondary_address
jsr tksa
bcs open_iec_error ; XXX what about the accumulator?
jsr printf
.byte "DBG: OPEN 2", $0D, 0
;; Indicate success
lda #$00
clc
clc
open_iec_error:
;; Re-enable interrupts and return
+9
View File
@@ -1,3 +1,12 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
tksa:
;; This routine is documented in 'C64 Programmer's Reference Guide', page 302 and
;; https://www.pagetable.com/?p=1031, , https://github.com/mist64/cbmbus_doc
ora #$F0
jsr iec_tx_command
bcs tksa_error
jmp iec_turnaround_to_listen
tksa_error:
rts