;==================================================================================================
; 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)
;					     62T bude trvat 17.48005μs, chyba +0.7% (57208bps)
;			60.76389T na ZX48k,  61T bude trvat 17.42857μs, chyba +0,4% (57377bps)
;					     62T bude trvat 17.71429μs, chyba +2.0% (56451bps)
;==================================================================================================

		cpu	z80undoc
		org	32768			; musí běžet v rychlé RAM

START		di				; nesmí být zpomalováno a přerušováno
		ld	bc,65533		; zvol registr 7 v AY
		ld	a,7
		out	(c),a
		ld	bc,49149		; vypni zvuk a nastav I/O port jako výstup (bit 6 v log. 1)
		ld	a,255
		out	(c),a
		ld	bc,65533		; zvol registr 14 v AY
		ld	a,14
		out	(c),a

SEND_STRING	ld	hl,DATA			; 10T	data, která budeme přenášet
		ld	bc,DATA_LENGTH		; 10T
SEND_STRING_L	push	bc			; 10T
		push	hl			; 10T

; celý cyklus 10+10+11+11+6+6+4+4+10=72T	projeví se na prodloužení stop bitu po dokončení přenosu

AYSER_SENDBYTE	ld	bc,49149		; 10T	registr 14 pro výstup zvolen, budu do něj zapisovat
		ld	e,128			; 7T	E bude počítadlo, 8x rotovat, nastane carry
		ld	a,247			; 7T	do A 0b11110111 = TxD do log.0, protože start bit
		out	(c),a			; 12T	zde začíná start bit a zde začíná záležet na taktech
		ld	a,(hl)			; 7T	vezmi byte, který má být vyslán
		ld	d,a			; 4T
		ld	l,247			; 7T	a teď můžu L změnit, před zavoláním AYSER_SENDBYTE
						;	bude muset být HL na zásobníku

; od outu sem 12+7+4+7 = 30T + k dalšímu outu bude 32T = 62T, trvání start bitu

AYSER_SENDB_L	rrc	d			; 8T	rotuj data skrz carry flag
		jp	c,AYSER_SENDB_1		; 10T
		ld	a,l			; 4T	do A 0 = TxD do log. 0
		jp	AYSER_SENDB_2		; 10T

AYSER_SENDB_1	ld	a,b			; 4T	do A B = TxD do log. 1 (B = 0b10111111)
		jp	AYSER_SENDB_2		; 10T

; od rrc d, bit = 1	8+10+4+10 = 32T
; od rrc d, bit = 0	8+10+4+10 = 32T

AYSER_SENDB_2	out	(c),a			; 12T
		rrc	e			; 8T
		jp	nc,AYSER_SENDB_L	; 10T

; celý cyklus trvá od AYSER_SENDB_L 8+10+4+10+12+8+10 = 62T, o takt víc, než by měl

		ld	a,255			; 7T	protože log. 1 do stop bitu i do RTS
		nop				; 4T	(použít raději rrc e 8T 3x?)
		nop				; 4T
		nop				; 4T
		nop				; 4T
		nop				; 4T
		nop				; 4T	zpoždění celkem 24T v 6x nop

; od minulého outu sem 12+8+10+7+6*4 = 61T, trvání posledního bitu (MSB)

		out	(c),a			; 12T	zde začíná stop bit
		nop				; 4T	zpoždění
		nop				; 4T	zpoždění
		nop				; 4T	zpoždění
		nop				; 4T	zpoždění	4x nop = 16T
		pop	hl			; 11T
		pop	bc			; 11T
		inc	hl			; 6T
		dec	bc			; 6T
		ld	a,b			; 4T
		or	c			; 4T
		jp	nz,SEND_STRING_L	; 10T

; od outu do jp včetně	12+4*4+11+11+6+6+4+4+10 = 80T
; začátek cyklu 44T prodlouží trvání stop bitu, celkem vychází 128T, nepatrně víc než 2 stop bity,
; naměřeno 36.6us

		ei				; 4T	před návratem do BASICu přerušení povol
		ret				; 10T


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

DATA_LENGTH	equ	$ - DATA