;; #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 }