;==================================================================================================
; 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
;
; Modified by Cygnus to simple example able transieve small data block.
;
;	AY I/O	ZX name	dir.	better name
;
;	A2	CTS	out	RTS
;	A3	RxD	out	TxD	->
;	A6	DTR	in	CTS	<-
;	A7	TxD	in	RxD

		cpu	z80undoc
		org	32768			; must run in fast RAM
		
START		di				; 4T	disable interrupt
		exx
		push	hl			; 10T
		exx
		ld	hl,DATA			; 10T	data address
		ld	de,DATA_LENGTH		; 10T	number of bytes to transfer

SET_AY_PORTS	ld	bc,65533		; 10T	BC = 65533, register port
		ld	a,7			; 7T	select AY register 7
		out	(c),a			; 12T	65533,7

		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	49149,255

		ld	b,a			; 4T	BC = 65535 / AY register port
		ld	a,14			; 7T	select AY register 14 (I/O port)
		out	(c),a			; 12T	65533,14

		ld	a,b			; 4T	A = 255
		ld	b,191			; 7T	BC = 49149 / data port
		out	(c),a			; 12T	49149,255, all bits high, only pullup resistors on outputs

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

RS232_57600BPS	ld	a,(hl)			; 7T	read data
		exx				; 4T	secondary set BC, DE, HL
		ld	hl,16630		; 10T	H = 0100 0000, L = 1111 0110 mask/bits for RS232/MIDI serial port
		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 in E
; total 7+4+10+7+10+4+4 = 46T
; wait for CTS or BREAK
WAIT_FOR_CTS	call	8020			; 17T+?	test BREAK (33 or 53T?)
		jr	nc,END			; 12/7	nc = BREAK was pressed
		in	a,(c)			; 12T	read AY I/O port
		and	h			; 4T	mask all bits except bit 6 = signal CTS
		jr	nz,WAIT_FOR_CTS		; 12/7T	repeat until zero, it means CTS is low, data can be transmitted
		ld	b,191			; 7T	BC = 49149 / data port AY-3-8912 
		scf				; 4T	set carry flag
TRANSMIT_LOOP	jr	c,TRANSMIT_0		; 12/7T
TRANSMIT_1	ld	a,254			; 7T	TxD = 1 (A3/A1)
		jr	SSAVE_AY_OUT		; 12T

TRANSMIT_0	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	12+8+4+12+12+4+10 = 62T
; bit 0..7 - 0	12+8+4+12+12+4+10 = 62T
; bit 0..7 - 1	12+8+4+12+7+7+12 = 62T
; stop bit	12+8+4+12+7+7+7+4 = 61T + another delays

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,TRANSMIT_LOOP	; 12/7T	jump if any bit left
		scf				; 4T	set carry flag
		
		exx				; 4T	primary set BC, DE, HL	
		inc	hl			; 6T	next address
		dec	de			; 6T	decrement byte counter
		ld	a,d			; 4T	and test if byte counter is zero
		or	e			; 4T
		jp	nz,RS232_57600BPS	; 10T	repeat until all bytes are sent
; total 12+8+4+7+4+4+6+6+4+4+10 = 69T
		ei				; 4T
		exx
		pop	hl			; 11T
		exx
		ret				; 10T

END		pop	hl			; 11T
		exx				; 4T	primary set BC, DE, HL	
		ei				; 4T
		ret				; 10T

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

DATA		db	"Hello RS232 world! ZX Spectrum 128 is sending data."
		db	13,10			; CR, LF

DATA_LENGTH	equ	$ - DATA