147 lines
3.9 KiB
ArmAsm
147 lines
3.9 KiB
ArmAsm
// 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
|
|
|
|
|
|
#if CONFIG_IEC
|
|
|
|
|
|
iec_rx_byte:
|
|
|
|
// 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 weren't 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
|
|
|
|
// 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_wait1:
|
|
lda CIA2_PRA // 4 cycles
|
|
rol // 2 cycles, to put CLK in as the last bit
|
|
bpl iec_rx_not_eoi // 2 cycles if not jumped
|
|
dex // 2 cycles
|
|
bne iec_rx_clk_wait1 // 3 cycles if jumped
|
|
|
|
// Timeout - either this is the last byte of stream, or the stream is empty at all.
|
|
// Mark end of stream in IOSTATUS
|
|
jsr kernalstatus_EOI
|
|
|
|
iec_rx_not_empty:
|
|
|
|
// Pull data for 60 usec to confirm it
|
|
jsr iec_release_clk_pull_data
|
|
jsr iec_wait60us
|
|
jsr iec_release_clk_data
|
|
|
|
iec_rx_not_eoi:
|
|
|
|
// 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 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).
|
|
// 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.
|
|
|
|
!: lda CIA2_PRA
|
|
rol
|
|
bpl !-
|
|
|
|
// 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 cycles if not jumped
|
|
dey // 2 cycles
|
|
bne iec_rx_clk_wait2 // 3 cycles if jumped
|
|
|
|
// Timeout
|
|
jsr kernalstatus_EOI
|
|
pla
|
|
|
|
jmp iec_rx_end
|
|
!:
|
|
// More bits?
|
|
dex
|
|
bpl iec_rx_bit_loop
|
|
|
|
// 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
|
|
|
|
// 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:
|
|
|
|
ply_trash_a
|
|
plx_trash_a
|
|
lda TBTCNT
|
|
|
|
clc
|
|
cli
|
|
rts
|
|
|
|
|
|
#endif // CONFIG_IEC
|