fixes for IEC
This commit is contained in:
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
@@ -1,118 +1,103 @@
|
|||||||
;; Receive a byte from the IEC bus.
|
;; Receive a byte from the IEC bus.
|
||||||
;; reference http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
|
;; Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc,
|
||||||
;; page 11.
|
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf (page 11)
|
||||||
|
|
||||||
|
|
||||||
;; XXX rework this, according to pagetable.com
|
|
||||||
|
|
||||||
iec_rx_byte:
|
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
|
rts
|
||||||
|
|
||||||
; ;; First, we wait for the talker to release the CLK line.
|
iec_rx_not_eoi:
|
||||||
; ;; XXX jsr iec_wait_for_clock_release
|
|
||||||
|
|
||||||
; ;; We then release the data line
|
;; Latch input bits in on rising edge of CLK, eight times for eight bits.
|
||||||
; ;; (We can use this routine, since we weren't holding CLK, anyway)
|
ldx #7
|
||||||
; jsr iec_release_clk_and_data
|
|
||||||
|
|
||||||
; ;; Wait for talker to assert CLK.
|
;; Get empty byte to load into.
|
||||||
; ;; If >200usec, then it is EOI and we have to assert the
|
lda #$00
|
||||||
; ;; DATA line for 60 usec to tell the TALKER that we have
|
pha
|
||||||
; ;; 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
|
|
||||||
|
|
||||||
iec_rx_bit_loop:
|
iec_rx_bit_loop:
|
||||||
|
|
||||||
; ;; Wait for CLK to release
|
;; Wait for CLK to release
|
||||||
; ;; jsr iec_wait_for_clock_release
|
jsr iec_wait_for_clk_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.
|
|
||||||
|
|
||||||
; ;; DATA now has the next bit, but inverted (well, except that it turns out not to be).
|
;; (we do this implicitly below, with a tighter routine,
|
||||||
; ;; DATA is in bit7, which is a bit annoying.
|
;; so that we don't have timing problems, as the requirements
|
||||||
; ;; But we can clock it out with a ROL instruction
|
;; are quite tight. Basically we need to read the clock and data
|
||||||
; ;; so that it is in C. We can then ROR it into the
|
;; bit from the same byte read.
|
||||||
; ;; 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.
|
|
||||||
|
|
||||||
; ;; Move data bit into C flag, and loop until bit 6 clears
|
;; DATA now has the next bit, but inverted (well, except that it turns out not to be).
|
||||||
; ;; i.e., the clock has been released.
|
;; DATA is in bit 7, which is a bit annoying.
|
||||||
;* LDA $DD00
|
;; But we can clock it out with a ROL instruction
|
||||||
; ROL
|
;; so that it is in C. We can then ROR it into the
|
||||||
; bpl -
|
;; 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
|
;; Move data bit into C flag, and loop until bit 6 clears
|
||||||
;; pla
|
;; i.e., the clock has been released.
|
||||||
; ROR
|
* lda CI2PRA
|
||||||
; pha
|
rol
|
||||||
|
bpl -
|
||||||
|
|
||||||
; ;; Wait for CLK to re-assert
|
;; Pull it into the data byte
|
||||||
; jsr iec_wait_for_clock_assert
|
pla
|
||||||
|
ror
|
||||||
|
pha
|
||||||
|
|
||||||
; ;; More bits?
|
;; Wait for CLK to be pulled again
|
||||||
; dex
|
jsr iec_wait_for_clk_pull
|
||||||
; bpl iec_rx_bit_loop
|
|
||||||
|
|
||||||
; ;; Then we must within 1000usec acknowledge the frame by
|
;; More bits?
|
||||||
; ;; asserting DATA. At this point, CLK is asserted by the
|
dex
|
||||||
; ;; talker and DATA by us, i.e., we are ready to receive
|
bpl iec_rx_bit_loop
|
||||||
; ;; the next byte. (p11).
|
|
||||||
; jsr iec_assert_data
|
|
||||||
|
|
||||||
; ;; Retreive the received byte
|
;; Then we must within 1000 usec acknowledge the frame by
|
||||||
; PLA
|
;; 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
|
;; Retreive the received byte
|
||||||
; CLC
|
pla
|
||||||
; RTS
|
|
||||||
|
;; Return no-error
|
||||||
|
clc
|
||||||
|
rts
|
||||||
|
|
||||||
@@ -1,39 +1,29 @@
|
|||||||
;; According to http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
|
;; According to http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
|
||||||
;; pages 7--8.
|
;; pages 7--8.
|
||||||
|
;; See also https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
|
||||||
|
|
||||||
iec_turnaround_to_listen:
|
iec_turnaround_to_listen:
|
||||||
|
|
||||||
;; Assert data and release clock
|
;; Pull DATA, release CLK and ATN (we are not sending commands)
|
||||||
lda $dd00
|
jsr iec_pull_data_release_atn_clock
|
||||||
and #$ef ; release clock (bit 4)
|
|
||||||
ora #$20 ; assert data (bit 5)
|
;; Wait for clock line to be pulled by the drive
|
||||||
sta $dd00
|
ldx #$FF ; XXX should we really use that high number?
|
||||||
|
*
|
||||||
;; Wait for clock line to be asserted by the drive
|
lda CI2PRA
|
||||||
* lda $dd00
|
rol ; to put BIT_CI2PRA_CLK_IN as the last (sign) bit
|
||||||
and #$40
|
bpl +
|
||||||
|
dex
|
||||||
bne -
|
bne -
|
||||||
|
|
||||||
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
|
;; Timeout
|
||||||
;; page 8 tells us we should not do anything here after waiting for
|
jsr printf
|
||||||
;; the clock line to assert.
|
.byte "DBG: TURNAROUND FAILED",$0d,$00
|
||||||
|
sec
|
||||||
ldx #$ff
|
rts
|
||||||
* lda $dd00
|
|
||||||
and #$40
|
|
||||||
bne +
|
|
||||||
dex
|
|
||||||
bne -
|
|
||||||
|
|
||||||
;; jsr printf
|
;; CLK is pulled by the device, OK
|
||||||
;; .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
|
|
||||||
clc
|
clc
|
||||||
rts
|
rts
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ iec_tx_command:
|
|||||||
|
|
||||||
;; Common part of iec_txbyte and iec_tx_common - waits for devices
|
;; Common part of iec_txbyte and iec_tx_common - waits for devices
|
||||||
;; and transmits a byte
|
;; and transmits a byte
|
||||||
|
|
||||||
pla
|
pla
|
||||||
jsr iec_tx_common
|
jsr iec_tx_common
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ iec_tx_common:
|
|||||||
|
|
||||||
;; Store the bye to send on a stack
|
;; Store the bye to send on a stack
|
||||||
pha
|
pha
|
||||||
|
|
||||||
;; Wait till all receivers are ready, they should all release DATA
|
;; Wait till all receivers are ready, they should all release DATA
|
||||||
jsr iec_wait_for_data_release
|
jsr iec_wait_for_data_release
|
||||||
|
|
||||||
;; Pull CLK back to indicate that DATA is not valid, keep it for 60us
|
;; 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
|
;; Don't wait too long, as 200us or more is considered EOI
|
||||||
|
|
||||||
jsr iec_pull_clk_release_data
|
jsr iec_pull_clk_release_data
|
||||||
@@ -42,11 +43,14 @@ iec_tx_common_bit_is_sent:
|
|||||||
pla
|
pla
|
||||||
dex
|
dex
|
||||||
bpl iec_tx_common_nextbit
|
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,
|
;; 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.
|
;; one can signal that it's busy much earlier (more than 100ms) than the other.
|
||||||
;; Can we do something about it?
|
;; Can we do something about it?
|
||||||
|
|
||||||
;; All done - give devices time to tell if they are busy by pulling DATA
|
;; All done - give devices time to tell if they are busy by pulling DATA
|
||||||
;; They should do it within 1ms
|
;; They should do it within 1ms
|
||||||
ldx #$FF
|
ldx #$FF
|
||||||
@@ -62,7 +66,9 @@ iec_tx_common_bit_is_sent:
|
|||||||
jsr iec_wait100us
|
jsr iec_wait100us
|
||||||
|
|
||||||
iec_tx_common_done:
|
iec_tx_common_done:
|
||||||
|
|
||||||
;; Byte sent, return
|
;; Byte sent, return
|
||||||
|
clc
|
||||||
rts
|
rts
|
||||||
|
|
||||||
iec_tx_common_nextbit:
|
iec_tx_common_nextbit:
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
iec_tx_eoi:
|
iec_tx_eoi:
|
||||||
|
|
||||||
;; Wait at least 200us
|
;; Wait at least 256 usec
|
||||||
jsr iec_wait100us
|
jsr iec_wait100us
|
||||||
jsr iec_wait100us
|
jsr iec_wait100us
|
||||||
|
jsr iec_wait60us
|
||||||
|
|
||||||
;; Restore the bus to idle state
|
;; Restore the bus to idle state
|
||||||
jsr iec_set_idle
|
jsr iec_set_idle
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ iec_wait100us:
|
|||||||
;; Wait 100usec
|
;; Wait 100usec
|
||||||
|
|
||||||
;; PAL:
|
;; 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:
|
;; 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
|
;; Waste cycles by reading some unimportant memory location
|
||||||
;; (in a loop) in order not to clutter VICE debug logs
|
;; (in a loop) in order not to clutter VICE debug logs
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ iec_wait20us:
|
|||||||
;; Wait 20usec
|
;; Wait 20usec
|
||||||
|
|
||||||
;; PAL:
|
;; 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:
|
;; 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
|
;; Waste cycles by reading some unimportant memory location
|
||||||
;; in order not to clutter VICE debug logs
|
;; in order not to clutter VICE debug logs
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ iec_wait60us:
|
|||||||
;; Wait 60usec
|
;; Wait 60usec
|
||||||
|
|
||||||
;; PAL:
|
;; 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:
|
;; 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
|
;; Waste cycles in a loop
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
@@ -15,9 +15,6 @@ open:
|
|||||||
bcs +
|
bcs +
|
||||||
bmi open_has_space
|
bmi open_has_space
|
||||||
*
|
*
|
||||||
jsr printf
|
|
||||||
.byte "FULL", $0D, 0
|
|
||||||
|
|
||||||
;; Table is full - according to https://codebase64.org/doku.php?id=base:kernalreference
|
;; Table is full - according to https://codebase64.org/doku.php?id=base:kernalreference
|
||||||
;; C flag set means error occured
|
;; C flag set means error occured
|
||||||
sec
|
sec
|
||||||
@@ -74,11 +71,9 @@ open_rs232:
|
|||||||
|
|
||||||
open_iec:
|
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:
|
;; XXX for now for channel 15 only!
|
||||||
;; 1. Call current device to attention as LISTENER = $20 + device
|
|
||||||
;; 2.
|
|
||||||
|
|
||||||
;; Disable IRQs, since timing matters!
|
;; Disable IRQs, since timing matters!
|
||||||
sei
|
sei
|
||||||
@@ -86,14 +81,25 @@ open_iec:
|
|||||||
;; Begin sending under attention
|
;; Begin sending under attention
|
||||||
;; XXX jsr iec_assert_atn
|
;; 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
|
lda current_device_number
|
||||||
jsr listen
|
jsr talk
|
||||||
bcs open_iec_error
|
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
|
;; Indicate success
|
||||||
lda #$00
|
lda #$00
|
||||||
clc
|
clc
|
||||||
|
|
||||||
open_iec_error:
|
open_iec_error:
|
||||||
;; Re-enable interrupts and return
|
;; Re-enable interrupts and return
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
; Function defined on pp272-273 of C64 Programmers Reference Guide
|
; Function defined on pp272-273 of C64 Programmers Reference Guide
|
||||||
tksa:
|
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
|
rts
|
||||||
Reference in new issue
Block a user