; prserver transfer routines (receive and send)

debounce    = 1

; The machines with a VIA that use a VIA control line for handshaking
; must reset the interrupt flag before it can be used again.

clearviaifr = target & (vic20 | pet3001 | pet4001)

; On machines with a CIA, Olaf experiences a bouncing FLAG line.
; The following tries to avoid the consequences.

ciadebounce = debounce && (target & (c64 | c128))

#if cable & (prlink | prlink88)

  ; .A := data, .Y := 00, .X preserved
receive_switch:
		;;; wait for first part of handshake
  lda #strval
1$:
  bit strobe	; wait for handshaking
  beq 1$
#if clearviaifr
  sta strobe
#endif		; clearviaifr

		;;; and only then switch data direction.
  lda #0	; switch back to inputs
  sta ddr

  beq receive1	; branch always

receive:
#if clearviaifr
rereceive:	; rereceive (without handshake) is only different for the CIA
#endif
  lda #strval
0$:
  bit strobe	; wait for handshaking
  beq 0$
#if clearviaifr
  sta strobe
#else
rereceive:	; rereceive (receive without handshaking) for the CIA
#endif		; clearviaifr
receive1:
  lda #ackval
  eor ack
  ldy data	; read the byte
#if ciadebounce
  bit strobe	; clear possible bounces
#endif
  sta ack	; acknowledge
  tya
  ldy #0
  rts

  ; .A trashed, .Y := 00, .X preserved
send_switch:
		;;; wait for first part of handshake
  tay
  lda #strval
1$:
  bit strobe	; wait for handshaking
  beq 1$
#if clearviaifr
  sta strobe
#endif
		;;; and only then switch data direction.
#if cable & prlink88
  lda #$ff
#else
  lda #$0f
#endif
  sta ddr	; set the data lines to output
  bne send1	; branch always

send:
  tay
  lda #strval
0$:
  bit strobe	; wait for handshaking
  beq 0$
#if clearviaifr
  sta strobe
#endif
send1:
#if cable & prlink88
#else
  tya
  sta data	; send the low nybble
  lsr
  lsr
  lsr
  lsr
  tay		; move the high nybble to y
  lda #ackval
  eor ack
#if ciadebounce
  bit strobe	; clear possible bounces
#endif
  sta ack	; ack: the low nybble is on the bus
  lda #strval
1$:
  bit strobe	; handshake
  beq 1$
#if clearviaifr
  sta strobe
#endif		; via
#endif		; prlink88
  sty data	; send the high nybble (or the whole byte, for prlink88)
  ldy #0
  lda ack
  eor #ackval
#if ciadebounce
  bit strobe	; clear possible bounces
#endif
  sta ack	; ack: the high nybble is on the bus
  rts

#endif		; prlink | prlink88

#if cable & pc64

  ; .A := data, .Y := 00, .X preserved
receive_switch:
receive:
#if clearviaifr
rereceive:
#endif
  lda #strval
0$:
  bit strobe	; wait for handshaking
  beq 0$
#if clearviaifr
  sta strobe
#else
rereceive:
#endif
  lda ack
  and #255 - ackval
  ldy data
  sta ack
  tya
  lsr
  lsr
  lsr
  lsr
  sta stemp
  lda #strval
1$:
  bit strobe
  beq 1$
#if clearviaifr
  sta strobe
#endif
  lda ack
  ora #ackval
  tay
  lda data
  sty ack
  and #$F0
  ora stemp
  ldy #0
  rts

  ; .A trashed, .Y := 00, .X preserved
send_switch:
send:
  tay
  lda #strval
0$:
  bit strobe	; wait for handshaking
  beq 0$
#if clearviaifr
  sta strobe
#endif
  sty data
  lda ack
  and #255 - ackval
  sta ack
  tya
  lsr
  lsr
  lsr
  lsr
  tay
  lda #strval
1$:
  bit strobe	; wait for handshaking
  beq 1$
#if clearviaifr
  sta strobe
#endif
  sty data
  lda ack
  ora #ackval
  sta ack
  ldy #0
  rts

#endif		; pc64

#if cable & c64net

  ; .A := data, .Y := 00, .X preserved
receive_switch:
receive:
rereceive:
  lda #8
0$:
  bit data	; initial handshaking
  beq 0$
  lda data	; get the high nybble
  and #$f0
  sta stemp
  lda #8
  sta data	; acknowledge (place 0 on PB2)
1$:
  bit data	; wait for acknowledgement
  bne 1$
  ldy #4
  lda data	; get the low nybble
  sty data	; acknowledge
  ldy #0
  lsr
  lsr
  lsr
  lsr
  ora stemp
  rts

  ; .A trashed, .Y := 00, .X preserved
send_switch:	; switch to sending and send
send:
  tay
0$:
  lda data	; initial handshaking
  and #$f8
  eor #$f0
  bne 0$
  lda #0
  sta data
1$:
  lda data
  bne 1$
  tya
  ora #4
  sta data	; send the lowest bit pair
  lda #8
2$:
  bit data	; wait for acknowledgement
  beq 2$
  tya
  lsr
  lsr
  tay
  and #3
  sta data	; send the lowest bit pair but one
  lda #8
3$:
  bit data	; wait for acknowledgement
  bne 3$
  tya
  lsr
  lsr
  tay
  ora #4
  sta data	; send the highest bit pair but one
  lda #8
4$:
  bit data	; wait for acknowledgement
  beq 4$
  tya
  lsr
  lsr
  sta data	; send the highest bit pair
  lda #8
5$:
  bit data	; wait for acknowledgement
  bne 5$
  lda #4
  sta data
  ldy #0
  rts

#endif		; pc64

#if cable & transnib

  ; .A := data, .Y := 00, .X preserved
receive_switch:
  lda #$40	; $40 is DRCV (output), $80 is DRDY (input)
  sta ddr
receive:
rereceive:
  jsr recvnyb	; high nybble first
  asl
  asl
  asl
  asl
  sta stemp
  jsr recvnyb
  ldy #0	; (y is preserved in this function)
  ora stemp
  rts

recvnyb:
rdrdyhi:
  bit data	; - Receiver starts waiting for DRDY to go low.
  bmi rdrdyhi
		; - Sender puts nybble on data lines, pulls DRDY low and waits
		; for DRCV to go low.
  lda data	; - Receiver gets nybble,
  and #$ff-$40	;   pulls DRCV low
  sta data
rdrdylo:
  bit data	;   and waits for DRDY to go high.
  bpl rdrdylo
		; - Sender pulls DRDY high and waits for DRCV to go high.
  ora #$40
  sta data	; - Receiver pulls DRCV high
  and #$0f
  rts

  ; .A trashed, .Y := 00, .X preserved
send_switch:
  ldy #$4f	; $80 is DRCV (input), $40 is DRDY (output)
  sty ddr	; note that the names are swapped from receiving but the
		; data direction isn't!
send:
  tay		; high nybble first
  lsr
  lsr
  lsr
  lsr
  jsr sendnyb
  tya
  and #$0f	; fall through to send low nybble
  ldy #0	; clear y

sendnyb:	; - Receiver starts waiting for DRDY to go low.
  sta data	; - Sender puts nybble on data lines, pulls DRDY low and
rdrcvhi:
  bit data	;   waits or DRCV to go low.
  bmi rdrcvhi
		; - Receiver gets nybble, pulls DRCV low
		;   and waits for DRDY to go high.
  ora #$40	; - Sender pulls DRDY high and
  sta data
rdrcvlo:
  bit data	;   waits for DRCV to go high.
  bpl rdrcvlo

  rts

#endif
