Files
open-roms/src/kernal/iec/iec_rx_byte.s
T

176 lines
4.0 KiB
ArmAsm

;; #LAYOUT# STD * #TAKE
;; #LAYOUT# * KERNAL_0 #TAKE
;; #LAYOUT# * * #IGNORE
; Receive a byte from the IEC bus.
; 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)
;
; Preserves .X and .Y registers
!ifdef CONFIG_IEC {
!ifdef CONFIG_IEC_JIFFYDOS {
iec_rx_dispatch:
!ifdef CONFIG_MB_M65 {
; If in native mode, switch to 1 MHz
jsr m65_iec_slow
}
lda IECPROTO
cmp #IEC_JIFFY
+beq jiffydos_rx_byte
; FALLTROUGH
} ; CONFIG_IEC_JIFFYDOS
iec_rx_byte:
!ifdef CONFIG_MB_M65 { !ifndef CONFIG_IEC_JIFFYDOS {
; If in native mode, switch to 1 MHz
jsr m65_iec_slow
} }
; Store .X and .Y on the stack - preserve them
+phx_trash_a
+phy_trash_a
; Timing is critical here - execute on disabled IRQs
; The best practice would be to do PHP first, but it seems this is not
; what the original ROM does; furthermore, pushing additional bytes to
; stack can wreck autostart softwaree loading at $0100
sei
; 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 were not pulling CLK anyway
jsr iec_release_clk_data
; Wait till data line is released (someone else might be holding it)
jsr iec_wait_for_data_release
; Check if EOI
jsr iec_rx_check_eoi
!ifdef CONFIG_IEC_DOLPHINDOS {
; Check if DolphinDOS was detected
lda IECPROTO
cmp #IEC_DOLPHIN
bne iec_rx_no_dolphindos
; For DolphinDOS just fetch the byte from parallel port
lda CIA2_PRB
pha
+bra iec_rx_acknowledge
iec_rx_no_dolphindos:
} ; CONFIG_IEC_DOLPHINDOS
; 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:
; Wait for CLK to release
jsr iec_wait_for_clk_release
; (we do this implicitly below, with a tighter routine,
; so that we do not 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).
; 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.
; Move data bit into C flag, and loop until bit 6 clears
; i.e., the clock has been released.
@1:
lda CIA2_PRA
rol
bpl @1
; Pull it into the data byte
pla
ror
pha
; Wait for CLK to be pulled again, over 300 usec (307 cycles on NTSC)
; consider this a timeout
ldy #$19 ; 2 cycles
iec_rx_clk_wait2:
lda CIA2_PRA ; 4 cycles
rol ; 2 cycles, to put CLK in as the last bit
bpl @2 ; 2 cycles if not jumped
dey ; 2 cycles
bne iec_rx_clk_wait2 ; 3 cycles if jumped
; Timeout
jsr kernalstatus_EOI
pla
+bra iec_rx_end
@2:
; More bits?
dex
bpl iec_rx_bit_loop
; FALLTROUGH
iec_rx_acknowledge:
; Then we must within 1000 usec acknowledge the byte 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
; Retrieve the received byte
pla
; Restore registers
sta TBTCNT ; $A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html
; FALLTROUGH
iec_rx_end:
!ifdef CONFIG_MB_M65 {
; If in native mode, switch back to fast mode
jsr m65_iec_fast
}
+ply_trash_a
+plx_trash_a
lda TBTCNT
clc
cli
rts
}