;==================================================================================================
; RS232 - transmitting through AY-3-8912 without data flow control
;
; 57600bps (17,3611μs)	61.57813T na ZX128k, 61T bude trvat 17.19811μs, chyba -0.9% (58146bps)
;			60.76389T na ZX48k,  61T bude trvat 17.42857μs, chyba +0,4% (57377bps)
;==================================================================================================
; original author Paul Farrow - this is code disassembled from his RS232 ROM, but only RS232 part

		cpu	z80undoc
		org	32768

SET_AY_PORTS	ld	bc,65533		; 10T	BC = 65533, register port
		ld	a,7			; 7T	select AY register 7
		out	(c),a			; 12T
		ld	a,b			; 4T	A = 255 / set IO port as output (1 on bit 6) and disable all sound channels
		ld	b,191			; 7T	BC = 49149, data port
		out	(c),a			; 12T
		ld	b,a			; 4T	BC = 65535 / AY register port
		ld	a,14			; 7T	select AY register 14 (I/O port)
		out	(c),a			; 12T
		ld	a,b			; 4T	A = 255
		ld	b,191			; 7T	BC = 49149 / data port
		out	(c),a			; 12T	write data byte 255, all bits high (like pullups?)
		ret				; 10T

; total 10+7+12+4+7+12+4+7+12+7+4+12+10 = 108T

SLOAD_AY_R	ld	de,33019		; 10T	D = 1000 0000, E = 1111 1011	(ZX 128k RS232 - *A2, A3, A6, *A7)
		jr	SLOAD_AY		; 12T	jump to common part
		
SLOAD_AY_K	ld	de,8446			; 10T	D = 0010 0000, E = 1111 1110	(ZX 128k Keypad - *A0, A1, A4, *A5)
SLOAD_AY	ld	a,e			; 4T
		ld	e,0			; 7T
		ld	hl,49151		; 10T	H = 1011 1111 (191 * 256 + 253 = 49149), L = 1111 1111 (255 * 256 + 253 = 65535)
		ld	bc,49149		; 10T	AY data port
		out	(c),a			; 12T	set CTS (ZX Spectrum is ready recieve data)
		ld	b,l			; 4T	B = 255
SLOAD_AY_WAIT	in	a,(c)			; 12T	read control port = IO port - repeat 3 times
		and	d			; 4T	check TxD (data from PC)
		jr	z,SLOAD_AY_RD_1		; 7/12T	Z = start bit
		in	a,(c)			; 12T
		and	d			; 4T
		jr	z,SLOAD_AY_RD_1		; 7/12T
		in	a,(c)			; 12T
		and	d			; 4T
		jr	z,SLOAD_AY_RD_1		; 7/12T
		dec	e			; 4T	decrement counter
		jr	nz,SLOAD_AY_WAIT	; 7/12T	wait for start bit again if NZ
		in	a,(c)			; 12T
		and	d			; 4T
		jr	z,SLOAD_AY_RD_1		; 7/12T
		ld	a,l			; 4T	A = 255
		ld	b,h			; 4T	B = 191 -> BC = 49149 (what port is it selcting now?)
		out	(c),a			; 12T
		ld	b,l			; 4T	B = 255 -> BC = 65533
SLOAD_AY_WAI2	in	a,(c)			; 12T	what port was read here?
		and	d			; 4T
		jr	z,SLOAD_AY_RD_2		; 7/12T
		in	a,(c)			; 12T
		and	d			; 4T
		jr	z,SLOAD_AY_RD_2		; 7/12T
		in	a,(c)			; 12T
		and	d			; 4T
		jr	z,SLOAD_AY_RD_2		; 7/12T
		dec	e			; 4T
		jp	nz,SLOAD_AY_WAI2	; 10T
		xor	a			; 4T
		ret				; 10T

; start bit detected, read other bits (this is critical for precize timing)

SLOAD_AY_RD_1	nop				; 4T	only delay?
SLOAD_AY_RD_2	ld	a,l			; 4T	A = 255
		ld	b,h			; 4T	B = 191 -> BC = 49149
		out	(c),a			; 12T	write 255 to what register? 14?
		ld	e,10000000b		; 7T	this will be counter to 8
		ld	b,l			; 4T	B = 255 -> BC = 65533
SLOAD_AY_BITL	in	a,(c)			; 12T	read AY I/O port
		cp	(ix+0)			; 19T	delay?
		and	d			; 4T	zero irrelevant bits, leave only one (bit 7 for RS232/MIDI connector)
		add	a,255			; 7T	activate carry flag if bit from serial port was H
		rr	e			; 8T	8x rotate E to right and carry flag copy in bit 7
		jr	nc,SLOAD_AY_BITL	; 12/7T	carry = last bit was read
		xor	a			; 4T	set Z flag, A = 0, only delay?
		ld	a,e			; 4T	A = E
		scf				; 4T	set carry flag
		ret				; 10T

; ZX Spectrum 128k Keypad is using bits
;	A0	?	output
;	A1	?	output
;	A4	?	input
;	A5	?	input
;
; ZX Spectrum 128k RS232 is using bits
;	A2	CTS	output		RTS
;	A3	RxD	output		TxD
;	A6	DTR	input		CTS
;	A7	TxD	input		RxD

SSAVE_AY_R	ld	hl,16630		; 10T		H = 0100 0000, L = 1111 0110	mask/bits for RS232/MIDI
		jr	SSAVE_AY		; 12T

SSAVE_AY_K	ld	hl,4348			; 10T		H = 0001 0000, L = 1111 1100	mask/bits for KEYPAD
SSAVE_AY	ld	d,10			; 7T		bit counter (start bit + 8 bits + stop bit)
		ld	bc,65533		; 10T		BC = 65535 / register port AY-3-8912 
		cpl				; 4T		invert A
		ld	e,a			; 4T		copy inverted data into E
; wait for CTS or BREAK
SSAVE_AY_WFSB	call	8020			; 17T+(33|53T)	test BREAK / nc = BREAK was pressed
		ret	nc			; 11/5T
		in	a,(c)			; 12T		read AY I/O port
		and	h			; 4T
		jr	nz,SSAVE_AY_WFSB	; 12/7T		Z = CTS in low detected
		ld	b,191			; 7T		BC = 49149 / data port AY-3-8912 
		scf				; 4T		set carry
SSAVE_AY_LOOP	jr	c,SSAVE_AY_OVER		; 12/7T
		ld	a,254			; 7T		TxD = 1 (A3/A1)
		jr	SSAVE_AY_OUT		; 12T
		
SSAVE_AY_OVER	ld	a,l			; 4T		TxD = 0 (A3/A1)
		jp	SSAVE_AY_OUT		; 10T

; CTS detected from in	12+4+7+7+4+12+4+10 = 60T (still not transmitting anything)
; start bit from out	12+8+4+12+12+4+10 = 62T
; bit 1			12+8+4+12+7+7+12 = 62T
; stop bit (nc)		12+8+4+12+7+7+12 = 62T

SSAVE_AY_OUT	out	(c),a			; 12T		write to AY I/O port
		srl	e			; 8T		shift right logical - shift data byte, 0 to bit 7, bit 0 to carry
		dec	d			; 4T		decrement bit counter
		jr	nz,SSAVE_AY_LOOP	; 12/7T		jump if any bit left
		scf				; 4T
		ret				; 10T

; after stop bit 12+8+4+7+4+10 = 45T (and more)