

	.Z80
	IF 	CRTDRV
;	**************************
;	CRT PROTOCOL DEVICE DRIVER
;	**************************
;
;	CRT STATUS ROUTINE
;
CRTST:	
	IF	USRCPM
	CALL	TSTFLSH
	ENDIF
;		
	LD	A,(CONBUF)	; GET BUFFER BEGINNING INDEX 
	LD	HL,CONBUF+1	; GET BUFFER END INDEX
	CP	(HL)		; CHAR IN BUFFER?
OSTATUS:
	LD	A,0		; SET NO CHAR FLAG
	RET	Z		; NO. CHECK USART
;
	DEC	A		; YES. RETURN CHAR READY
	RET		
;
;	CRT INPUT ROUTINE 
;
CRTIN:	CALL	CRTST		; CHECK IF CHAR READY
	JR	Z,CRTIN		; NOT READY YET
;
	LD	HL,CONBUF
	LD	A,(HL)		; GET BUFFER START INDEX
	LD	E,A		; SAVE FOR LATER
	INC	A		; BUMP INDEX
	CP	BUFSIZ		; PAST END OF INDEX?
	JR	C,NOPASS	; NO
;
	XOR	A
NOPASS:	LD	(HL),A		; SET NEW INDEX
	LD	D,0
	INC	HL		; GET BEG INDEX OF BUFFER AREA
	INC	HL
	ADD	HL,DE		; INDEX INTO BUFFER
	LD	A,(HL)		; GET CHAR FROM BUFFER
	AND	(IX+2)		; STRIP OFF PARITY BIT
;
	IF	USRCPM
	CP	10H		; CONTROL-P: PRINTER TOGGLE
	RET	NZ
	PUSH	AF
	CALL	BRKPT		; PRINTER BREAK POINT
	POP	AF
	ENDIF
;
	RET
;
;	CRT OUTPUT STATUS ROUTINE
;
CRTOST:	LD	A,0FFH		; ALWAYS READY
	RET
;
;	CRT OUTPUT ROUTINE 				****6/7/83***
;
CRTOUT:
	LD	A,C		; GEY DATA
	CP	7		; IS DATA CONTROL G?
	JP	Z,BELRING	; IF SO, GO TO BELL SOUND ROUTINE
	DI			; DISABLE SYSTEM INTERRUPT
	LD	(USER_STACK),SP	; SAVE USER STACK
	LD	SP,LOCSTK	; SET LOCAL STACK
	XOR	A
	LD	(C_BANK),A	; SAVE CURRENT SELECT BANK
	OUT	(BANKSW),A	; SWITCH TO MEMORY BANK 0
	CPL			; DISABLE KEYBOARD INPUT
	LD	(KB_DISABLE),A
	LD	A,(PRNTMO)	; GET PRINTER FUNCTION FLAG
	OR	A		; IS BUF. OR COPY PRINT MODE OFF
	JR	Z,OUTAL		; IF SO, DISPLAY CHAR. ON SCREEN
	JR	OUTPRNT		; OTHERWISE, CHECK PRINT FUNCTION
OUTAL:	EI			; ENABLE SYSTEM INTERRUPT
	CALL	ALOUT		; CALL ALPHA DRIVER
OUTDONE:
	DI			; DISABLE SYSTEM INTERRUPT
	LD	A,1
	LD	(C_BANK),A	; SET CURRENT SELECT BANK TO 1		
	OUT	(BANKSW),A	; SWITCH TO MEMORY BANK 1
	XOR	A
	LD	(KB_DISABLE),A	; ENABLE KEYBOARD INPUT
	LD	SP,(USER_STACK)	; RESTORE USER STACK
	EI			; ENABLE SYSTEM INTERRUPT
	RET
;
P_EMPTY:    DS	1		; FLAG TO INDICATE PRINTER BUFFER IS EMPTY
ESCFLAG:    DS	1		; FLAG TO INDICATE ESC CHAR. IS DETECTED
USER_STACK: DS	2		; USER STACK POINTER
KB_DISABLE: DB	0		; KEYBOARD INPUT DISABLE FLAG
XONXOFF:    DS	1		; FLAG TO INDICATE WHICH CHAR. IS SENT
STOBYTF:    DB	0		; STORAGE TO SAVE BYTFLAG 
;
;	ROUTINE TO RING BELL WHEN CONTROL G IS DETECTED
;
BELRING:	
	LD	B,20 		; SEND BELL SOUND 80 TIMES
NREDY:	IN	A,(PRNTCP)
	AND	4
	JR	Z,NREDY
	LD	A,5BH		; SET FREQUENCY OF BELL TO F0H
	OUT	(PRNTDP),A	; GO RING THE BELL
	DEC	B		
	JR	NZ,NREDY	; RING BELL 80 TIMES
	RET
;
;	ROUTINE TO HANDLE PRINT ESC SEQUENCE 
;
OUTPRNT:
	LD	A,C		; GET CHAR.
	CP	1BH		; IS CHAR. ESC?
	JR	Z,SETFLAG	; IF SO, GO SET FLAG
	LD	A,(ESCFLAG)	; IF NOT, CHECK ESCFALG SET
	OR	A		; IF SET, GO RESET ESCFLAG 
	CALL	NZ,RESETPMO	;
	PUSH	BC
	LD	A,C		; IF NOT, PUT CHAR. IN PRINTER BUFFER
	CALL	PUTBUFF		; AND DO NOT DISPLAY CHAR. ON THE SCREEN
	POP	BC
	LD	A,(PRNTMO)	;
	CP	1
	JR	Z,OUTDONE		
	JR	OUTAL		; AND ALSO DISPLAY CHAR. ON THE SCREEN.
SETFLAG:
	LD	A,1		; SET FLAG TO INDICATE ESC CHAR. HAS BEEN 
	LD	(ESCFLAG),A	; DETECTED
	JR	OUTDONE
;
RESETPMO:
	XOR	A		; RESET ESCFALG	
	LD	(ESCFLAG),A
	LD	A,C		; GET CHAR.
	CP	'a'		; IS CHAR. BUFFER PRINT TERMINATER(a)
	JR	Z,CLERFLG	; IF SO, GO SET PRINTER FLAG ACCORDINGLY
	CP	'A'		; IF NOT, CHECK COPY PRINT MODE TERMINATER
	JR	NZ,ESCBUF	; NO, PUT ESC CHAR. IN PRINTER BUFFER
CLERFLG:			; 
	XOR	A		; YES, SET PRINTER FLAG TO OFF STATE
	LD	(PRNTMO),A	;
	POP	HL		;
	JR	OUTDONE	
PUTBUFF:			
	DI
	CALL	SETBANK		; SWITCH BANK BEFORE PUTTING CHAR. IN THE BUF.
	CALL	PUT_CHR		; PUT CHAR.
	CALL	CHK_BSTAT	; CHECK BUFFER FULL
LSTBUF:	CALL	RESETBANK	; SWITCH BANK TO ORIGINAL BANK
	EI			;  ***ENALBE INTERRUPT***
	LD	A,(P_EMPTY)	; IS PRINTER BUFFER EMPTY?
	OR	A		; IF NOT, NO NEED TO WAKE UP PRINTER
	RET	Z		;
	XOR	A		; IF EMPTY, RESET EMPTY FLAG TO NOT EMPTY
	LD	(P_EMPTY),A	;
	IN	A,(IMRB)
	OR	8
	OUT	(IMRB),A
	LD	A,STIIVL+4
	OUT	(PVR),A
	IN	A,(IERB)
	OR	8
	LD	B,A
	LD	A,STIIVL+4
	OUT	(PVR),A
	LD	A,B
	OUT	(IERB),A
	CALL	INTPRNT		; WAKE UP PRINTER
	RET
;
ESCBUF:
	PUSH	BC		; SAVE CURRENT CHAR.
	LD	C,1BH		; PUT ESC CHAR. IN THE PRINTER BUFFER.
	CALL	PUTBUFF
	POP	BC		; GET CURRENT CHAR.
	RET
;
;	
SETBANK:
	XOR	A		; SWITCH BANK TO ZERO
	OUT	(BANKSW),A
	LD	A,(SCNMOD)
	OR	4		; 
	OUT	(0C4H),A	
	LD	A,C		; GET CHAR.
	LD	HL,BUF_PRNT	; SET PARAMETER
	LD	BC,PBUFSIZ	; HL = STARTING ADDRESS OF PRINTER BUFFER
				; BC = SIZE OF PRINTER BUFFER
	RET			;  A = CHARACTER TO BE STORE IN THE BUFFER
;
RESETBANK:
	LD	A,(SCNMOD)	; RESTORE SCREEN BACK TO PREVIOUS
	OUT	(0C4H),A	; STATE.
	LD	A,(C_BANK)	; SWITCH BANK TO PREVIOUS BANK THAT SYSTEM
	OUT	(BANKSW),A	; WAS WORKING WITH
	RET
;
;	IF PRINT BUFFER IS FULL, SEND XOFF TO KEY BOARD BUFFER
;	IF PRINT BUFFER BECOME EMPTY AND KEY BOARD BUFFER IS XOFF STATE,
;	SEND XON TO KEY BOARD BUFFER
;
CHK_BSTAT:
	LD	DE,(INPUTOFF)	; GET INPUT, OUTPUT POINTER OF PRINT BUFFER
	LD	BC,(OUTPUTOFF)	; COMPARE THEM TO SEE IF BUFFER IS FULL.
				; IF BUFFER IS NOT COMPLETELY FULL,
				; CHECK IF LESSER THEN 16 BYTES LEFT.
	CALL	CMP_DEBC	; 
	LD	L,C		; 
	LD	H,B		; 
	JR	C,CHK_FULL	; SET UP REGISTERS TO OBTAIN DIFFERENCE OF 
	EX	DE,HL		; INPUT AND OUTPUT POINTER
	SBC	HL,DE		; 
	LD	DE,PBUFSIZ
	EX	DE,HL
CHK_FULL:
	XOR	A		; SUBTRACT 17 FROM DIFFERENCE OF INPUT AND 
	SBC	HL,DE		; OUTPUT POINTER
	XOR	A		; IF RESULT IS SMALLER, SEND XOFF TO KEY
	LD	DE,135		; BOARD BUFFER.  AND SET XONXOFF FLAG TO
	SBC	HL,DE		; TO INDICATE XOFF IS SET.
	JR	NZ,CHK_DONE
	LD	A,(XONXOFF)
	OR	A
	JR	NZ,CHK_DONE
	LD	A,1
	LD	(XONXOFF),A
	LD	B,XOFF
	CALL	STORKB
	JR	CHK_DONE
CHK_XOFF:
	LD	A,(XONXOFF)	; IF BUFFER IS EMPTY OR NOT FULL, CHECK
	OR	A		; XONXOFF FLAG.
	JR	Z,CHK_DONE	; IF FLAG SET, RESET XONXOFF FLAG AND SEND
	XOR	A		; XON TO KEY BOARD BUFFER.
	LD	(XONXOFF),A
	LD	B,XON
	CALL	STORKB
CHK_DONE:
	RET
;
	ENDIF			; END OF CRT DRIVER
;
	IF 	TTYDRV
;
;	**************************
;	TTY PROTOCOL DEVICE DRIVER
;	**************************
;
; 	TTY Input Status Routine 
;
TTYST:	LD	A,(IX+1)	; GET TTY STATUS PORT
	CP	MODMCP		; CHECK IF MODEM PORT
	JR	Z,MODST		; YES, MODEM PORT

;	Printer port input status check

	LD	C,A		; NO, PRINTER PORT
	IN	A,(C)		; READ INPUT STATUS
	BIT	RCVRDY,A	; CHAR AVAILABLE?
	JP	OSTATUS		; NO. THEN SET A = 0
				; YES. THEN SET A = FFH

; 	Modem port input status check			***6/10/83***
;	RETURNS: Z = 0; A = 0FFH IF RCV. READY
;		 Z = 1; A = 0	 IF RCV. NOT READY
MODST:
	CALL	CHK_MRX		; CHECK RECEIVER BUFFER EMPTY
	JP	OSTATUS		; SET READY CONDITION
				; SET NOT READY CONDITION
;
;
;	TTY Input Routine
;
TTYIN:	CALL	TTYST		; CHECK INPUT STATUS
	JR	Z,TTYIN
	LD	A,(IX)		; GET DATA PORT
	CP	MODMDP
	JR	Z, TTYIN2	; INPUT CHARACTER FROM MODEM INPUT BUFFER
	LD	C,A
	IN	A,(C)		; GET CHARACTER
	JR	TTYIN3		
;
;	MODEM INPUT ROUTINE
;	GET CHARACTER FROM INPUT BUFFER
;	RETURNS: A = INPUT CHARACTER.
;
TTYIN2:
	CALL	TTYIN1
TTYIN3:	AND	(IX+2)
	EI
	RET

TTYIN1:
	LD	HL,MRX_BUFF
	LD	BC,MRX_BSIZE
	JP	GET_CHR		;GET CHARACTER OF MODEM RX. BUFFER
;
;	TTY Output Status Routine
;
TTYOST:	LD	A,(IX+1)	; GET STATUS PORT
	CP	MODMCP		; MODEM PORT?
	JR	Z,MODOST	; YES

; printer port output status check

	LD	A,(P_EMPTY)	; NO, PRINTER POR
	OR	A		; RESET EXTRN/STATUS COMMAND
	JR	Z,READY		; SEND OUT
	LD	HL,0
STATCHK:
	IN	A,(PARALCP)	; READ DART STATUS
	BIT	7,A		; CHECK TXMT READY AND CTS
	JR	Z,READY    	; READY TO SEND?
	DEC	HL
	LD	A,L
	OR	H
	JR	NZ,STATCHK	; IF Z = 0, THEN READY TO SEND
NREADY:	XOR	A		; A = 0, Z = 1(NOT READY TO SEND)
	RET
;
READY:	DI	
	CALL	SETBANK
	CALL	CHK_OVFW	; DID PRINTER BUFFER OVERFLOW?
	CALL	RESETBANK
	EI
	JP	OSTATUS		» YES¬ RETURÎ WITÈ NOÔ READÙ CONDITION	
				; A = FF, Z = 0(READY TO SEND)

; modem port output status check

MODOST:	IN	A,(GPIP)	; READ I/O INTERRUPT REGISER
	BIT	1,A		; CHECK CTS
	JR	NZ,NREADY	; CTS LINE READY IF BIT 1 = 0

; xon/xoff protocol needed not to check cts line

MODTST:	
	IN	A,(MODTSR)	; GET TRANSMITTER STATUS
	BIT	7,A		; CHECK READY(BIT 7 = NOT ZERO)
	JP	OSTATUS		; SET READY CONDITION
				; SET NOT READY CONDITION
;
;	TTY Output Routine
;
TTYOUT:	LD	D,C		; SAVE CHAR IN D-REG
	PUSH	DE		; SAVE CHAR IN STACK
TTYLUP:	CALL	TTYOST		; CHECK TXMT STATUS
	JR	Z,TTYLUP
	LD	A,(IX)		; GET DATA PORT
	CP	MODMDP		; MODEM PORT?
	POP	DE		; GET CHAR. BACK
	LD	C,A		; DATA PORT TO C REG.
	LD	A,D		; 
	JR	NZ,PRNTPORT	; 
	AND	(IX+2)		; MASK OFF PARITY BIT
	OUT	(C),A		; SEND DATA OUT
	RET	
PRNTPORT:
	AND	(IX+2)		; MASK OFF PARITY BIT
	LD	C,A		; 
	DI
	CALL	SETBANK
	CALL	PUT_CHR		; PUT CHAR. IN THE PRINTER BUFF.
	CALL	LSTBUF
	RET
	ENDIF			; END OF TTY DRIVER
;
;
	IF 	ETXDRV
;	******************************
;	ETX/ACK PROTOCOL DEVICE DRIVER			****6/9/83****
;	******************************
;
;	ETX/ACK Device Output Status Routine
;	   <Dedicated to the modem port>
;	
;	EXIT: A=0     ->  PRINTER IS NOT READY
;	      A=0FFH  ->  PRINTER IS READY
;
MOUT_CHR: DEFB	0		; OUT CHARACTER		| DO NOT MOVE THE ORDER
UL1CNT:	DEFB	0		; BUFFER COUNTER	| OF THESE STORAGE
UL1SIZ:	DEFB	80H		; BUFFER SIZE		| PLEASE .....
;
ETXOST:	LD	HL,UL1CNT	; CURRENT BUFFER COUNT
	LD	A,(UL1SIZ)	; MAX COUNT
	CP	(HL)		; ROOM FOR MORE CHAR?
	LD	A,0FFH		; ANTICIPATE AFFIRMATIVE.
	RET	NZ		; LISTER IS READY.
	JP	MODST		; CHECK INPUT STATUS OF MODEM PORT
;	RET
;
;	ETX/ACK Device Output Routine
;
ETXOUT:
	LD	HL,UL1CNT	; CURRENT BUFFER COUNT
	INC	(HL)		; BUMP BUFFER COUNT
	DEC	HL		; SAVE OUTPUT CHARACTER TO MEMORY
	LD	(HL),C
;
UL1L10:	CALL	MODST		; CHECK RCV. INPUT STATUS OF MODEM PORT
	JR	Z,UL1L20	; NO. SEND CHARACTER.
	CALL	TTYIN1		; GET INPUT CHARACTER.
	AND	7FH		; STIP PARITY.
	CP	ASCACK		; IS IT ACK?
	JR	Z,UL1L60	; YES, PROCESS IT.
UL1L20:
	LD	HL,(UL1CNT)
	OR	A		; CLEAR CY = 0
	RR	H		; H = UL1SIZ/2 ; L = UL1CNT
	CP	L		; IS BUFFER HALF-FULL?
	JR	NZ,UL1L40	; NO, NO NEED FOR ETX.
; 
UL1L30:	CALL	MODOST		; CHECK OUTPUT STATUS OF MODEM PORT
	JR	Z,UL1L30	; NOT YET.
	LD	C,(IX)
	LD	A,ASCETX	; SEND OFF THE END-OF-
	OUT	(C),A		; BLOCK CHARACTER.
	JR	UL1L50		; NOW OUTPUT THE CHARACTER
; 
UL1L40:
	LD	HL,(UL1CNT)	; CURRENT BUFFER COUNT
	LD	A,H		; H = A = UL1SIZ; L = UL1CNT
	CP	L		; CHECK FOR FULL AND OVERFLOW.
				; (UL1SIZ = UL1CNT)?
	JR	Z,UL1L30	; FULL, SO SEND ANOTHER ETX
	JR	C,UL1L10	; OVERFLOW, WAIT FOR ACK
; 
UL1L50:	CALL	MODOST
	JR	Z,UL1L50	; LOOP UNTIL TRANSMITTER READY
	LD	A,(MOUT_CHR)	; GET OUTPUT CHARACTER TO A-REG
	AND	(IX+2)		; ALL THIS TIME. STRIP PARITY
	LD	C,(IX)		; GET DATA PORT
	OUT	(C),A		; SHIP IT!
	RET			; ONLY EXIT POINT
;
UL1L60: LD	HL,(UL1CNT)
	OR	A		; CLEAR CY = 0
	RR	H		; DID WE EVER SEND AN ETX?( H = BUFFER/2)
	LD	A,L		; A = SEND COUNT
	SUB	H		; I.E., IS BUFFER > = HALF FULL?
	JR	C,UL1L50	; NO, SPURIOUS ACK
;
	LD	(UL1CNT),A	; ADJUST THE BUFFER COUNT
	JR	UL1L50		; AND SEND THE CHARACTER
	ENDIF			; END OF ETX/ACK DRIVER
;
	IF 	XONDRV
;              *******************
;	       X-ON/X-OFF PROTOCOL
;              ******************* 
;	<Dedicated to the modem port>
;
;	SEND A CHARACTER TO SERIAL PORT (RS-232C) THAT 
;	USE THE X-ON/X-OFF PROTOCOL FOR SYNCHRONIZATION.
;	RETURNS: SEND DATA COMPLETED
;
XONOFF:	DEFB	0FFH		;XON/OFF FLAG
XOFFTM:	DEFB	0		;XOFF TIMER COUNTER
;
XONOUT:	LD	A,C		;SAVE CHARACTER
	LD	(MOUT_CHR),A	;INTO MEMORY
;
XONWT1:	CALL	XONOST
	JR	Z,XONWT1	;WAIT IF TXMIT NOT READY
	LD	C,(IX)		;GET DATA PORT 
	LD	A,(MOUT_CHR)	;RESTORE DATA TO REG_A
	AND	(IX+2)		;MASK OFF BITS 
	OUT	(C),A		;SEND DATA OUT 
	RET
;
;	RETURN LIST DEVICE STATUS
;	RETURNS: ZFLAG = 0, A = 0 IF BUFFER FULL
;		 ZFLAG = 1, A = FF IF BUFFER EMPTY
;
XONOST:	CALL	MODST		;GET CURRENT MODEM PORT RECEIVE STATUS
	JR	Z,XON11		;SKIP IF NOT READY
	CALL	TTYIN1		;GET INPUT DATA FROM BUFFER
	AND	7FH		;STRIP OFF CARRY BIT
	CP	ASCDC3		;DATA = CNTL-S (X-OFF)
	JR	NZ,XONCHK	;SKIP IF NOT
	DI
	LD	A,0
	LD	(XONOFF),A	;YES, THEN PXONF =  X-OFF
	LD	A,0FFH-60	;DECREMENT TIMER
	LD	(XOFFTM),A
	EI
	JR	XON11
;
XONCHK:	CP	ASCDC1		;DATA = CNTL-Q (X-ON)?
	JR	NZ,XON11	;SKIP IF NOT
	LD	A,0FFH
	LD	(XONOFF),A      ;ELSE THEN PXONF = X-ON
;
XON11:	CALL	MODTST		;CHECK TXMT READY 
	JR	Z,XON12		;SKIP IF NOT
	LD	A,(XONOFF)	;TRANSMIT BUFFER EMPTY
	CP	0FFH
	JR	Z,XONOK		;READY TO SEND CHARACTER
;
XON12:	XOR	A		;NOT READY TO TXMT
	RET
;
XONOK:	XOR	A
	DEC	A		;READY TO TXMT
	RET
	ENDIF			;END OF XON/XOFF DRIVER
;
.8080
	IF 	LPTDRV
FORCL:	LXI	H,FORCEF	;				MMMOST2.0
      	LDA	LBCNT		;				MMMOST2.0
       	CPI	0		;				MMMOST2.0
      	RZ			;				MMMOST2.0
       	STA	LBLNG	        ;SET UP TRUE LENGTH IN REQBLK   MMMOST2.0
       	DCR	M		;				MMMOST2.0
      	MVI	C,1AH		;				MMMOST2.0
  	LXI	H,0		;				MMMOST2.0
      	SHLD	LBTIME 		;				MMMOST2.0
;
LPTOUT:	LXI	H,LBUFF		;FIND PLACE IN LIST BUFFER
	LDA	LBCNT		;CURRENT COUNT
	INR	A
	STA	LBCNT		;SAVE INCREMENTED COUNT
	DCR	A		;USE TO COMPUTE ADDR
	ADD	L
	MOV	L,A
	JNC	LNOCAR
	INR	H
LNOCAR:	MOV	M,C		;PLACE CHAR IN BUFFER		MMMOST2.0
	LDA	FORCEF		;				MMMOST2.0
	CPI	0		;				MMMOST2.0
	JNZ	LSTYES		;				MMMOST2.0
	LDA	LBCNT		;				MMMOST2.0
	CPI	128		;IS BUFFER FULL?		MMMOST2.0
	RNZ			;IF NO WE'RE DONE		MMMOST2.0
	STA	LBLNG		;				MMMOST2.0
LSTYES:	XRA	A		;				MMMOST2.0
	STA	LBLNG+1		;EXTEND TO 16 BITS		MMMOST2.0
	STA	FORCEF		;				MMMOST2.0
	STA	LBCNT		;ZERO BUFFER COUNT		MMMOST2.0
	MVI	A,LSTCD		;REQUEST CODE TO 		MMMOST2.0
	STA	LRQCOD		;SPOOL PRINT BUFFER		MMMOST2.0
	LDA	IOBYTE		;ROTATE	LOGICAL 		MMMOST2.0
	RLC			;LIST DEVICE BITS 		MMMOST2.0
	RLC			;TO BITS #0-#1			MMMOST2.0
	STA	LSELCT		;				MMMOST2.0
				;				MMMOST2.0
	LXI	H,LRQBLK	;				MMMOST2.0
	MVI	B,10		;				MMMOST2.0
	CALL	PNXO		;MAKE REQUEST			MMMOST2.0
	CPI	0		;ANY ERROR			MMMOST2.0
	MVI	B,6		;				MMMOST2.0
	JNZ	PRNTERR		;				MMMOST2.0
	LXI	H,LBUFF		;				MMMOST2.0
	MVI	B,128		;				MMMOST2.0
	CALL	PNXO		;SEND PRINT BUFFER		MMMOST2.0
	CPI	0		;				MMMOST2.0
	MVI	B,6		;ERROR CODE			MMMOST2.0
	JNZ	PRNTERR		;IF ERROR ON SEND		MMMOST2.0
	RET			;NORMAL, GOOD SEND		MMMOST2.0
;
LPTOST:	MVI	A,0FFH		;ALWAYS READY
	RET
	ENDIF			;END OF SERVICE PROCESSOR PRINTER DEVICE
;
	IF	USRCPM
;
; 	INCREMENT AND TEST PRINTER FLUSH COUNT
; 	IF ZERO, ATTEMPT TO FLUSH PRINTER BUFFER
;
TSTFLSH:
	LHLD	LFLCNT
	INX	H
	SHLD	LFLCNT
	MOV	A,L
	ORA	H		;COUNT = 0?
	RNZ			;NO				MMMOST2.0
	CALL	FORCL		;YES, GO FLUSH BUFFER		MMMOST2.0
	LXI	H,0		;RESET FLUSH COUNTER		MMMOST2.0
	SHLD	LFLCNT		;				MMMOST2.0
	RET
	ENDIF
	.Z80
;
;	MODEM RECIEVER ROUTINE					****6/9/83***
;
MRX_INT:			; SYSTEM INTERRUPT DISABLE FROM HERE
	LD	(MRX_STACK),SP	; USER STACK
	LD	SP,MRX_STACK	; SET STACK POINTER TO LOCAL
	PUSH	AF		; SAVE ALL REGISTERS (A,BC,DE,HL AND FLAGS)
	PUSH	BC
	PUSH	DE
	PUSH	HL
	LD	A,1
	OUT	(BANKSW),A	; SWICTH BACK TO BANK #1 (TPA MEMORY)
;*************************************************************************
;	FOR THOSE USER WANT TO HANDLE THE RCV_BUFFER OR ERROR
;	BY THEIR SOFTWARE, THEN MODIFIED THE THREE BYTES CALL
;	INSTRUCTION AT LOCATION "MRX_IDR" TO THEIR SUBROUTINE
;	AT END USER MUST RETURN TO THIS ROUTINE HANDLER.
;	USER ROUTINES MUST USE THEIR OWN STACK IF USING MORE THAN
;	10 LEVELS OF STACK. MUST NOT ALTER ANY FOLLOWING REGS:
;	I, R, IX, IY, AF', BC', DE', HL', SP AND MUST KEEP 
;	SYSTEM INTERRUPT DISABLED.
;

MRX_IDR:
	CALL	MRX_CHR		; GET CHARACTER OUT OF RECEIVER REG.

;
;*************************************************************************
	LD	A,(C_BANK)	; GET PREVIOUS BANK #
	OUT	(BANKSW),A	; RESTORE PREVIOUS BANK SELECT
	POP	HL		; RESTORE ALL REGS (A, BC, DE, HL AND FLAGS)
	POP	DE
	POP	BC
	POP	AF
	LD	SP,(MRX_STACK)	; RESTORE SYSTEM STACK POINTER
	EI			; ENABLE SYSTEM INTERRUPT
	RETI

;
;	MODEM RECEIVER ROUTINE					****6/9/83***
;
MRX_CHR:
	IN	A,(MODRSR)	; CHECK RCV. STATUS
	AND	11111000B	; READ STATUS TO CLEAR ERROR FLAGS.
	CP	80H		; BUFFER READY AND ERROR ?
	RET	C		; RETURN IF BUFFER NOT READY
	IN	A,(MODMDP)	; READ RX. DATA TO A-REG
;********************************************************
;	IF Z = 0 THEN NO ERROR				*
;	IF Z = 1 THEN ERROR (OV, PE, FE, BREAK)???	*
;	PUT THE RCV_CHR INTO BUFFER ANYWAY.		*
;********************************************************
	LD	HL,MRX_BUFF	; ADDRESS MODEM RECEIVER BUFFER
	LD	BC,MRX_BSIZE	; BUFFER SIZE
;
;	PUT CHARACTER INTO RING BUFFER
;	IF BUFFER OVERFLOW THEN IGNORE INPUT CHARACTER.
;	ACCEPTS: A = INPUT CHAR.
;		 HL = BUFFER POINTER
;		 BC = BUFFER SIZE
;	RETURNS: CY = 0 IF CHAR --> BUFFER
;		 CY = 1 IF BUFFER FULL
PUT_CHR:
	PUSH	HL		; SAVE BUFFER POINTER
	PUSH	AF		; SAVE INPUT CHARACTER
	CALL	CHK_OVFW	; IS BUFFER OVERFLOW?
	JR	Z,PUT_C2	; YES, OVERFLOW CNANOT STORE CHARACTER
	INC	HL	
	ADD	HL,BC		; INDEX TO CHARACTER SPACE
	POP	AF		; RESTORE CHARACTER
	LD	(HL),A
	POP	HL
	LD	(HL),E		; RESTORE START BUFFER POINTER
	INC	HL
	LD	(HL),D		; UPDATE INPUT BUFFER POINTER
	OR	A
	RET
;
PUT_C2:
	POP	AF
	POP	HL
	SCF
	RET
;
CHK_OVFW:
	LD	E,(HL)		; DE = INPUT POINTER
	INC	HL
	LD	D,(HL)
	PUSH	DE		; SEVE OLD INPUT INDEX POINTER
	INC	DE		; BC = BUFFER SIZE
	CALL	CMP_DEBC	; DE > BC ?
	JR	C,PUT_C1	; SKIP IF DE < BC
	LD	DE,0		; ELSE DE = 0
PUT_C1:
	INC	HL
	LD	C,(HL)		; BC = OUTPUT POINTER
	INC	HL
	LD	B,(HL)
	CALL	CMP_DEBC	; INPUT POINTER = OUTPUT POINTER ?
	POP	BC		; RESTORE OLD INPUT INDEX POINTER TO BC-REG
	RET
;
;	CHECK RECEIVER BUFFER EMPTY
;	RETURNS: Z = 1 IF BUFFER EMPTY
;		 Z = 0 IF BUFFER NOT EMPTY
CHK_MRX:
	LD	DE,(MRX_BUFF)
	LD	BC,(MRX_BUFF+2)
;
;	COMPARE 16 BITS UNS.INTEGER
;	ACCEPTS: DE = 16 UNS. INT
;		 BC = 16 UNS. INT
;	RETURNS: Z = 0 ; CY = 1 IF DE < BC
;		 Z = 1 ; CY = 0 IF DE = BC
;		 Z = 0 ; CY = 0 IF DE > BC
;
CMP_DEBC:
	LD	A,D
	CP	B
	RET	NZ
	LD	A,E
	CP	C
	RET
;
;	GET CHARACTER FROM RING BUFFER
;	ACCEPTS: HL = BUFFER POINTER
;		 BC = BUFFER SIZE
;	RETURNS:  Z = 1 IF BUFFER EMPTY
;		ELSE A = RETURNS CHARACTER
;
GET_CHR:
	PUSH	BC		;SAVE BUFFER SIZE
	LD	E,(HL)		;GET INPUT BUFFER INDEX TO DE
	INC	HL
	LD	D,(HL)
	INC	HL
	LD	C,(HL)		; GET OUTPUT BUFFER INDEX TO BC
	INC	HL
	LD	B,(HL)
	CALL	CMP_DEBC	; INPUT INDEX = OUTPUT INDEX ?
	POP	DE		; RESTORE BUFFER SIZE TO DE (NOT BC)
	RET	Z		; EXIT IF BUFFER EMPTY
	DI			; **** DISABLE SYSTEM INTERRUPT ****
	PUSH	HL		; ELSE SAVE OUTPUT INDEX BUFFER POINTER
	INC	HL
	ADD	HL,BC		; INDEX TO RX. CHARACTER IN BUFFER
	LD	L,(HL)		; GET CHARACTER TO L-REG
	INC	BC		; ADJUST OUTPUT INDEX POINTER TO NEXT
	CALL	CMP_DEBC	; OUTPUT INDEX = BUFFER SIZE ?
	JR	NZ,GET_C1	; SKIP IF NOT EQUAL
	LD	BC,0		; ELSE RESET OUPUT INDEX POINTER
GET_C1:
	LD	A,L		; RESTORE CHARACTER INTO A-REG
	POP	HL		; RESTORE OUTPUT INDEX BUFFER POINTER
	LD	(HL),B		; UPDATE OUTPUT INDEX POINTER
	DEC	HL
	LD	(HL),C
	LD	C,0
	DEC	C
	RET
;
INTPRNT:
	IF	TS803 
	DI			;  *****DISABLE INTERRUPT*****
	LD	(MRX_STACK),SP	; CHANGE TO LOCAL STACK
	LD	SP,PBUF_STACK
	PUSH	AF		; SAVE REGS.
	PUSH	BC
	PUSH	DE
	PUSH	HL
	CALL	SETBANK		; SWITCH BANK TO ZERO
	CALL	GET_CHR		; GET CHAR. FROM PRINTER BUFFER
	JR	Z,SETEMPTY
	OUT	(PRNTDP),A
;
RESTOR:	CALL	RESETBANK	; SWTCH BANK TO PREVIOUS BANK
	POP	HL		;
	POP	DE		; GET REGS. BACK
	POP	BC
	POP	AF
	LD	SP,(MRX_STACK)
	EI	
	RETI
	ENDIF
;
INTPARAL:
	IF	TPCI
	DI			;  *****DISABLE INTERRUPT*****
	LD	(MRX_STACK),SP	; SET UP LOCAL STACK
	LD	SP,PBUF_STACK
	PUSH	AF		; SAVE REGISTERS
	PUSH	BC
	PUSH	DE
	PUSH	HL
	CALL	SETBANK		; SWITCH BANK TO ZERO
	CALL	GET_CHR		; GET CHAR. FROM PRINT BUFFER
	JR	Z,SETEMPTY	; IF EMPTY, SKIP
	LD	B,A		; SAVE CHAR. IN REG. B
	LD	HL,8000H
PBUSY:	IN	A,(PARALCP)	; CHECK IF PARALLEL CONTROL PORT IS BUSY.
	BIT	7,A		
	JR	Z,PNBUSY	; IF BUSY, WAIT UTILL TIME OUT.
	DEC	HL
	LD	A,H
	OR	L
	JR	NZ,PBUSY	; 
PNBUSY:	LD	A,B		; IF NOT, RESTORE CHAR, IN REG B
	OUT	(PARALDP),A	; AND SEND IT OUT TO PARALLEL DATA PORT
	LD	A,PSTOBE	; SEND STOBE TO CONTROL PORT
	OUT	(PARALCP),A	; TO INDICATE DATA IS READY TO PICK UP
	LD	A,RSTOBE	; RESET STOBE 
	OUT	(PARALCP),A
RESTOR:
	CALL	RESETBANK	; SWITCH BANK TO PREVIOUS BANK
	POP	HL		; RESTORE REGISTERS
	POP	DE
	POP	BC
	POP	AF
	LD	SP,(MRX_STACK)	; CHANGE BACK TO PREVIOUS STACK
	EI
	RETI
	ENDIF

SETEMPTY:
	CALL	CHK_XOFF
	LD	A,1		; SET FALG TO INDICATE BUFFER EMPTY
	LD	(P_EMPTY),A
	IN	A,(IMRB)
	AND	0F7H
	OUT	(IMRB),A
	LD	A,STIIVL+4
	OUT	(PVR),A
	IN	A,(IERB)
	AND	0F7H
	LD	B,A
	LD	A,STIIVL+4
	OUT	(PVR),A
	LD	A,B
	OUT	(IERB),A
	
	IF	TS800 OR TS803 OR TS803H
	LD	A,28H		; GO TO SLEEP
	OUT	(PRNTCP),A
	ENDIF

	JR	RESTOR

MRX_RSET:
	LD	HL,0
	LD	(MRX_BUF),HL
	LD	(MRX_BUF+2),HL
	LD	HL,MRX_CHR
	LD	(MRX_IDR+1),HL
	RET
;
C_BANK:	DB	1		; CURRENT SELECT MEMORY BANK#
MRX_BSIZE EQU	128		; INPUT BUFFER SIZE
;
; END OF TPCICONS.MAC


