	.IF	LIST3
	.LIST
	.PAGE
	.ELSE
	.NOLIST
	.ENDC
;****************************************************************************
;
;	Terminal I/O routines.
;
;	File:	SAGE.PROM3.TEXT
;	Date:	23-Mar-83
;	Issue:	3
;
;	COPYRIGHT (c) 1982, 1983 SAGE Computer Technology
;	All Rights Reserved
;
;****************************************************************************
;
;	Release History:
;
;	1     13-Jun-82 Initial release.
;	2     11-Dec-82 Added TERMDECM.
;	3     23-Mar-83 Initial SAGE IV release.
;
;****************************************************************************



	.PAGE
;****************************************************************************
;
;	The Terminal port is set up in asynchronous mode at one of eight
;	baud rates according to three of the DIP switches (3,2 & 1)
;	on the CPU board.  The 8251A is set up for eight data bits and
;	one stop bit.  DIP switch 4 in the Off position requires even
;	parity.	 In the On position the switch disables parity.
;
;	Switches:
;	3 2 1
;	D D D - 19.2K baud
;	D D U -	 9600 baud
;	D U D -	 4800 baud
;	D U U -	 2400 baud
;	U D D -	 1200 baud
;	U D U -	  600 baud
;	U U D -	  300 baud
;	U U U - reserved (same as 19.2K baud)
;
;	Set up Terminal USART baud rate generator (8253 interval timer).
;	Set up 8251A (USART) for Terminal.  Note that three zero bytes
;	  are initially output to the 8251A to insure that it is receiving
;	  commands.
;
;****************************************************************************

TERMINIT
	LEA	TERM_C,A0	;Terminal USART control port address
	CLR.B	D0
	MOVE.B	D0,(A0)		;First zero to the 8251A 
	MOVE.B	#76H,BAUD_C	;Set up for square wave output on 8253
	ROR.B	#8,D0		;Just for delay
	MOVE.B	D0,(A0)		;Second zero to the 8251A
	MOVE.B	DIPSWT,D1	;Get DIP switch settings
	ROR.B	#8,D0		;Just for delay
	MOVE.B	D0,(A0)		;Third zero to the 8251A
	MOVEQ	#6EH,D0		;Default to no parity
	BTST	#3,D1
	BEQ.S	$10		;Requested no parity
	MOVEQ	#7EH,D0		;Set up for parity
$10	MOVE.B	#40H,(A0)	;8251A reset command bit
	ANDI.W	#7,D1		;Isolate bits 0 - 2 of DIP switch
	MOVE.B	RATES(D1.W),BAUD1_D ;Apply low count from RATES table
	MOVE.B	D0,(A0)		;8251A mode selection (times 16 clock)
	MOVE.B	#0,BAUD1_D	;High count byte to 8253 is always zero
	ROR.B	#8,D0		;Just for delay
	MOVE.B	#25H,(A0)	;8251A transmit and receive enabled with
				;  Request-to-send.
	JMP	(A1)		;Return via A1


;	Baud Rate Table
;	These divide by counts will give 0.16% error from the desired value
;	when used on the 8253 input frequency of 615385 Hz (8 MHz / 13).
;	The USART should be set to a times 16 transmit/receive clock.

RATES	.BYTE	2.		;Reserved  (currently same as 19200 baud)
	.BYTE	128.		;for   300 baud (  4800 Hz is actually	 4808)
	.BYTE	 64.		;for   600 baud (  9600 Hz is actually	 9616)
	.BYTE	 32.		;for  1200 baud ( 19200 Hz is actually	19231)
	.BYTE	 16.		;for  2400 baud ( 38400 Hz is actually	38462)
	.BYTE	  8.		;for  4800 baud ( 76800 Hz is actually	76924)
	.BYTE	  4.		;for  9600 baud (153600 Hz is actually 153846)
	.BYTE	  2.		;for 19200 baud (307200 Hz is actually 307692)
	
	.PAGE
;****************************************************************************
;
;	Set up auxillary serial channel baud rate.
;
;	D1 = index to RATES table
;
;****************************************************************************

AUXBAUD LEA	AUX1_C,A0	;USART address
	CLR.W	D0
	MOVE.B	D0,(A0)		;First zero to 8251A
	MOVE.B	#0B6H,BAUD_C	;Set up for square wave from 8253
	ROR.B	#8,D0		;Just for delay
	MOVE.B	D0,(A0)		;Second zero to 8251A
	MOVE.B	RATES(D1.W),BAUD2_D ;Apply low count from rates
	ROR.B	#8,D0		;Just for delay
	MOVE.B	D0,(A0)		;Third zero to 8251A
	MOVE.B	D0,BAUD2_D	;High byte to 8253 is always 0
	ROR.B	#8,D0		;Just for delay
	MOVE.B	#40H,(A0)	;8251A reset
	ROR.B	#8,D0		;Just for delay
	MOVE.B	#4EH,(A0)	;8251A mode select (times 16 clock)
				;  No parity, 8 data bits
	ROR.B	#8,D0		;Just for delay
	MOVE.B	#27H,(A0)	;8251A transmit & receive enabled with
				;  request to send.
	RTS

	.PAGE
;****************************************************************************
;
;	Terminal I/O routines.
;
;	TERMCHAR - Outputs the character in D0 to the terminal.
;
;	TERMCRLF - Outputs a carriage return, a line feed, and five nulls
;		   to the terminal.
;
;	TERMTEXT - Outputs characters via (A0)+ until a zero character is
;		   detected.
;
;	TERMDIGT - Output a digit in hex from low four bits of D0.
;
;	TERMHEXB - Output byte from D0 in hex.
;
;	TERMHEXW - Output word from D0 in hex.
;
;	TERMHEXL - Output long word from D0 in hex.
;
;	TERMSPAC - Outputs a space.
;
;****************************************************************************

;	Output a carriage return & line feed to the terminal
TERMCRLF
	MOVE.L	D0,-(A7)	;Save working register
	MOVEQ	#CR,D0		;Output carriage return
	BSR.S	TERMCHAR
	MOVEQ	#LF,D0		;Output line feed
	BSR.S	TERMCHAR
	CLR.B	D0
	BSR.S	TERMCHAR	;Five nulls
	BSR.S	TERMCHAR
	BSR.S	TERMCHAR
	BSR.S	TERMCHAR
	BSR.S	TERMCHAR
	MOVE.L	(A7)+,D0	;Restore working register
	RTS


;	Output a space.
TERMSPAC
	MOVE.L	D0,-(A7)
	MOVEQ	#" ",D0
	BSR.S	TERMCHAR
	MOVE.L	(A7)+,D0
	RTS


;	Output a string of characters to the terminal
TERMTEXT
	MOVE.W	D0,-(A7)	;Save working register
$10	MOVE.B	(A0)+,D0	;Get next character
	BEQ.S	$20		;Done
	BSR.S	TERMCHAR	;Output the character
	BRA.S	$10		;Go back for more

$20	MOVE.W	(A7)+,D0	;Restore working register
	RTS

;	Output a byte in hex
TERMHEXB
	ROL.B	#4,D0
	BSR.S	TERMDIGT	;Output high digit
	ROL.B	#4,D0
	BSR.S	TERMDIGT	;Output low digit
	RTS

;	Output a word in hex
TERMHEXW
	MOVE.L	D1,-(A7)	;Save working register
	MOVEQ	#4-1,D1		;Set up loop count for digits
$10	ROL.W	#4,D0		;Right justify next digit
	BSR.S	TERMDIGT	;Output hex digit
	DBF	D1,$10
	MOVE.L	(A7)+,D1	;Restore working register
	RTS

;	Output a long word in hex
TERMHEXL
	MOVE.L	D1,-(A7)	;Save working register
	MOVEQ	#8-1,D1		;Set up loop count for digits
$10	ROL.L	#4,D0		;Right justify next digit
	BSR.S	TERMDIGT	;Output hex digit
	DBF	D1,$10
	MOVE.L	(A7)+,D1	;Restore working register
	RTS

;	Output a digit from least four bits of D0
TERMDIGT
	MOVE.W	D0,-(A7)	;Save working register
	ANDI.B	#0FH,D0		;Mask for low nibble
	CMP.B	#9,D0
	BLS.S	$10		;Was in decimal range
	ADDI.B	#"A"-"0"-10.,D0 ;Offset to 'A' to 'F' range for hex
$10	ADDI.B	#"0",D0		;Add in ASCII character offset
	BSR.S	TERMCHAR	;Output the ASCII digit character
	MOVE.W	(A7)+,D0	;Restore working register
	RTS

;	Output a character to the terminal
TERMCHAR
	TST.B	BUGBIOS		;Check if using BIOS I/O
	BNE.S	$100		;Use BIOS I/O
	MOVE.W	D1,-(A7)	;Save working register
$10	MOVE.W	#0FFFFH,D1	;Set up counter for character timeout
				;  in > 250 milliseconds
$20	BTST	#2,TERM_S	;Check if transmitter empyt
	DBNE	D1,$20
	BEQ.S	$30		;Had timeout
	MOVE.B	D0,TERM_O	;Output character to Usart
	MOVE.W	(A7)+,D1	;Restore working register
	RTS

$30	MOVEM.L D0-D1/A0-A1,-(A7) ;Save working registers for init
	LEA	$40,A1		;Set up return address for TERMINIT
	BRA	TERMINIT	;Re-initialized the USART & Baud rate clock
	
$40	MOVEM.L (A7)+,D0-D1/A0-A1 ;Restore working registers
	BRA.S	$10

;	BIOS Output
$100	TRAP	#10.		;Output character
	RTS


;	Output an Unsigned Decimal Word from D0
TERMDECM
	MOVEM.L D0-D3,-(A7)
	MOVEQ	#0,D1
	MOVE.W	D0,D1
	MOVEQ	#0,D2
	MOVE.W	#10000.,D2
	CLR.B	D3
$10	DIVU	D2,D1
	BNE.S	$20		;Result is not zero
	TST.B	D3
	BEQ.S	$30		;Don't print digit
$20	MOVE.B	D1,D0
	BSR	TERMDIGT
	ST	D3		;Set digit printed flag
$30	CLR.W	D1
	SWAP	D1
	DIVU	#10.,D2		;Scale down
	BNE.S	$10
	MOVEM.L (A7)+,D0-D3
	RTS

	.PAGE
;****************************************************************************
;
;	Keyboard input routines.
;
;	Returns character from terminal in D0.
;
;****************************************************************************

KEYBCHAR
	TST.B	BUGBIOS		;Check if using BIOS I/O
	BNE.S	$100		;Use BIOS I/O
	MOVE.L	D1,-(A7)	;Save a register
$10	MOVE.B	TERM_S,D1	;Get status
	BTST	#1,D1		;Check for character
	BEQ.S	$10		;No character yet
	MOVE.B	TERM_I,D0	;Get the character
	ANDI.B	#38H,D1		;Check for errors
	BNE.S	$20		;Found USART detected errors
	MOVE.L	(A7)+,D1	;Restore register
	RTS

;	Process USART detected error
$20	MOVE.B	#35H,TERM_C	;Clear error
	MOVEQ	#BELL,D0	;Output warning bell
	BSR	TERMCHAR
	BRA.S	$10

;	BIOS Input
$100	TRAP	#9.		;Read a character
	RTS


;****************************************************************************
;
;	Keyboard character check.
;
;	Returns condition of NE if character is ready to read.
;
;****************************************************************************

KEYCHK
	BTST	#1,TERM_S
	RTS


;****************************************************************************
;
;	KEYBCH	 - Gets character from keyboard, strips off bit 7, converts
;		   lower to upper case, and echoes character.  Returns the
;		   character in D0.
;
;****************************************************************************

KEYBCH
	BSR.S	KEYBCHAR	;Get raw character
	BCLR	#7,D0		;Strip off bit 7
	CMPI.B	#"a",D0		;Check for lower case
	BLT.S	$10		;Not lower case
	CMPI.B	#"z",D0
	BGT.S	$10		;Not lower case
	BCLR	#5,D0		;Make lower case into upper case
$10	RTS


                                                                                                                                                                                                                                                          