;--------------------------------------------------------
;
; Lifeboat USER.ASM file for a Cromemco TU-ART with
; port A at 00h and port B at 10h.
;
;    Ver     Date      Notes
;    ---  ----------   ---------------------
;    1.0  07/06/2022   Mike Douglas
;
; To add this USER file to CP/M after a MOVCPM xx and
; SAVE 40 CPMxx.COM operation:
;
;    A>DDT CPMxx.COM
;    -IUSERTU.HEX
;    -Rxxxx	(where xxxx = value of OFFSET symbol)
;    -G0	(zero, not "oh", or type CTRL-C)
;    A>		(save 40 CPMxx.COM or SYSGEN here)
;
;--------------------------------------------------------

; Change MSIZE to the desired CP/M memory size in K

MSIZE	EQU	48		;Distribution size

BIOS	EQU	(MSIZE*1024)-0C00H	;Memory location of BIOS
USER	EQU	BIOS+600H	;and of this USER AREA
OFFSET	EQU	2600H-USER	;To overlay SYSGEN image
IOBYTE	EQU	3		;Location of IOBYTE in CP/M

; TU-ART board equates

ASTAT	EQU	00H		;STATUS PORT A
ADATA	EQU	01H		;DATA PORT A
ACOM	EQU	02H		;COMMAND PORT A
AINTR	EQU	03H		;INTERRUPT MASK PORT A

BSTAT	EQU	10H		;STATUS PORT B
BDATA	EQU	11H		;DATA PORT B
BCOM	EQU	12H		;COMMAND PORT B
BINTR	EQU	13H		;INTERRUPT MASK PORT B

TURESET	EQU	01H		;DEVICE RESET COMMAND
SINRDY	EQU	40H		;INPUT BYTE RECEIVED
SOUTRDY	EQU	80H		;READY TO XMIT


	ORG	USER		;Start of USER AREA

; JUMP TABLE - Jumps MUST remain here in same order

CINIT	JMP	UCINIT		;Cold boot init
WINIT	JMP	UWINIT		;Warm boot init
CONST	JMP	INSTATA		;Console status port A
CONIN	JMP	INA		;Console input port A
CONOUT	JMP	OUTA		;Console output port A
LIST	JMP	OUTB		;Printer output to port B
PUNCH	JMP	OUTB		;Punch output to port B
READER	JMP	INB		;Reader input from port B
LISTST	JMP	OSTATB		;Output status port B

; This 8 byte data area used externally MUST remain.

LENUA	DW	USRLEN		;Length of USER AREA
USRIOB	DB	0		;Initial IOBYTE
	DB	0,0,0,0,0

; TUART BAUD RATE SETTING CAN BE PATCHED HERE

BAUDA	DB	0C0H		;9600 baud, 1 stop bit
BAUDB	DB	0C0H		;9600 baud, 1 stop bit

; CHECK CONSOLE INPUT STATUS (PORT A)

INSTATA	IN	ASTAT		;GET CONSOLE STATUS
	ANI	SINRDY		;LOOK AT INPUT READY FLAG
	RZ			;RETURN 0 IF NO DATA
	MVI	A,0FFH		;ELSE 0FFh FOR DATA AVAILABLE
	RET

; READ A CHARACTER FROM CONSOLE (PORT A)

INA	IN	ASTAT		;GET CONSOLE STATUS
	ANI	SINRDY		;IF NOT READY,
	JZ	INA		;LOOP UNTIL INPUT AVAILABLE
	IN	ADATA		;READ A CHARACTER
;	ANI	7FH		;MASK MSBIT
	RET

; WRITE A CHARACTER TO THE CONSOLE (PORT A)

OUTA	PUSH	PSW		;SAVE OUTPUT CHAR
OUTALP	IN	ASTAT		;GET CONSOLE STATUS
	ANI	SOUTRDY		;IF NOT READY,
	JZ	OUTALP		;LOOP UNTIL INPUT AVAILABLE
	POP	PSW		;RESTORE OUTPUT CHARACTER
	OUT	ADATA		;WRITE CHARACTER
        RET

; CHECK OUTPUT STATUS OF PORT B

OSTATB	IN	BSTAT		;GET PORT BSTATUS
	ANI	SOUTRDY		;LOOK AT OUTPUT READY FLAG
	RZ			;RETURN 0 IF READY
	MVI	A,0FFH		;ELSE 0FFh FOR NOT READY
	RET

; READ A CHARACTER FROM PORT B

INB	IN	BSTAT		;GET CONSOLE STATUS
	ANI	SINRDY		;IF NOT READY,
	JZ	INB		;LOOP UNTIL INPUT AVAILABLE
	IN	BDATA		;READ THE CHARACTER
	RET

; WRITE A CHARACTER TO PORT B

OUTB	PUSH	PSW		;SAVE OUTPUT CHAR
OUTBLP	IN	BSTAT		;GET CONSOLE STATUS
	ANI	SOUTRDY		;IF NOT READY,
	JZ	OUTBLP		;LOOP UNTIL INPUT AVAILABLE
	POP	PSW		;RESTORE OUTPUT CHARACTER
	OUT	BDATA		;WRITE CHARACTER
	RET

; WARM START INITIALIZATION

UWINIT	RET			;DO NOTHING

; COLD START INITIALIZATION

UCINIT	LDA	USRIOB		;Load initial IOBYTE
	STA	IOBYTE		;and store
	MVI	A,TURESET	;RESET COMMAND
	OUT	ACOM		;DEVICE A
	OUT	BCOM		;DEVICE B
	XRA	A		;EMPTY INTERRUPT MASK
	OUT	AINTR		;DEVICE A
	OUT	BINTR		;DEVICE B
	LDA	BAUDA		;SERIAL PORT CONFIG
	OUT	ASTAT		;DEVICE A
	LDA	BAUDB
	OUT	BSTAT		;DEVICE B
	RET

USRLEN	EQU	$-CINIT		;Length of USER AREA
	END
