;PRINTHAN.68K	SEP-14-86	(ALSO SEE "INFOSTR")
;GENERIC PRINTER HANDLER
;WRITTEN BY LOREN BLANEY FOR DFM ENGINEERING
;THIS IS BASED ON 6502 CODE WRITTEN BY P.J.R. BOYLE.
;
;REVISION HISTORY:
;SEP-14-86, MODIFIED SO THAT ONE SOURCE PRODUCES FOUR HANDLERS
;
;NOTES:
;This program is used to produce the following handlers, depending on
; the conditional assembly flags:
;	PARHAN, EPSONHAN, ITOHAN, DUMHAN
;
;This printer handler paginates and handles tabs. The printer should be
; configured so that a <CR> moves to the start of the current line, and
; a <LF> moves down one line.
;This will print 60 lines per page, with a half-inch margin at the top
; and bottom. It is assumed that the page is 11 inches long and that
; there are 6 lines per inch.

	NOLIST
	INCLUDE	SYSPAG		;GET SYSTEM-PAGE DEFINATIONS
	LIST

;SELECT ONLY ONE OF THE FOLLOWING BY SETTING IT TRUE:
PARHAN	EQU	FALSE		;NON-SPECIFIC PRINTER HANDLER
EPSONHAN EQU	TRUE		;EPSON PRINTER HANDLER
ITOHAN	EQU	FALSE		;C.ITOH PRINTER HANDLER
DUMHAN	EQU	FALSE		;DIRECT CONTROL, NO PAGINATION, ETC.

DEVNUM	EQU	2		;PRINTER DEVICE NUMBER

	IF	EPSONHAN ! ITOHAN
LINESIZ	EQU	97		;NUMBER OF CHARACTERS +1 ON A LINE
	ELSE
LINESIZ	EQU	81		;NUMBER OF CHARACTERS +1 ON A LINE
	ENDIF

;I/O ADDRESSES:
CENDATA	EQU	$FFFFC1C1	;CENTRONICS DATA OUTPUT PORT
PPAR05	EQU	$FFFFC1C5	;CENTRONICS CONTROL PORT
CENSTAT	EQU	$FFFFC1C7	;CENTRONICS STATUS PORT
PPAR11	EQU	$FFFFC201	;GENERAL OUTPUT PORT, LED RED +

PPAR05X	EQU	$FFFF80F1	;COPY OF CENTRONICS CONTROL PORT

	ORG	MEMTOP- $1400
START	EQU	@		;ADDRESS WHERE THIS HANDLER STARTS

;=======================================================================
;PRINTER HANDLER
;
PRHAN	DC.L	DUMMY		;0 = OPENI
	DC.L	OPENO		;1 = OPENO
	DC.L	DUMMY		;2 = CHIN
	IF	DUMHAN
	DC.L	BYTOUT		;3 = BYTOUT, DIRECT OUTPUT
	ELSE
	DC.L	CHOUT		;3 = CHOUT, WITH PAGING, TABS, ETC.
	ENDIF
	DC.L	CLOSE		;4 = CLOSE
	DC.L	GETINFO		;5 = GETINFO
	DC.L	BYTOUT		;6 = BYTE OUT, LOW LEVEL OUTPUT
	DC.L	DUMMY		;7 = SPARE

HPOSN	DC.B	0		;HORIZONTAL POSITION COUNTER
				; (FIRST COLUMN = 0)
LINE	DC.B	0		;LINE COUNTER. TOP LINE = 0

;-----------------------------------------------------------------------
;OPEN (INITIALIZE) BUFFERED TERMINAL FOR OUTPUT
;
OPENO	MOVE.L	D0,-(SP)	;SAVE D0

	IF	EPSONHAN
	MOVEQ	#ESC,D0		;SET ELITE MODE (96 COLUMNS)
	BSR	BYTOUT
	MOVEQ	#'M',D0
	BSR	BYTOUT
	ENDIF

	IF	ITOHAN
	MOVEQ	#ESC,D0		;SET ELITE MODE (96 COLUMNS)
	BSR	BYTOUT
	MOVEQ	#'E',D0
	BSR	BYTOUT
	ENDIF

	CLR.B	LINE.L		;INIT LINE COUNTER TO FIRST LINE
	BSR	DOCR		;MAKE SURE WE'RE AT THE START OF
				; THE LINE
	MOVE.L	(SP)+,D0	;RESTORE D0
	RTS

;-----------------------------------------------------------------------
;OUTPUT THE CHARACTER IN D0 TO THE PRINTER
; HANDLE SOME SPECIAL CHARACTERS: NUL, TAB, CR, & FF.
; THIS DOES NOT HANDLE DELETES (DEL)
;
CHOUT	CMPI.B	#$20,D0		;IS IT A CONTROL CHARACTER?
	BHS.S	CHO190		;(BHS) BRANCH IF NOT

	CMPI.B	#NUL,D0		;IS IT A NULL CHARACTER?
	BNE.S	CHO110		;BRANCH IF NOT
DUMMY	RTS			;IGNORE NULLS

CHO110	CMPI.B	#TAB,D0		;IS IT A TAB CHARACTER?
	BNE.S	CHO120		;BRANCH IF NOT
	BRA	DOTAB		;(PBRA) DO TAB AND RETURN

CHO120	CMPI.B	#CR,D0		;IS IT A CARRIAGE RETURN?
	BNE.S	CHO130		;BRANCH IF NOT
	BRA	NEWLIN		;(PBRA) START A NEW LINE AND RETURN

CHO130	CMPI.B	#FF,D0		;IS IT A FORM FEED?
	BNE.S	CHO150		;BRANCH IF NOT
	BRA	NEWPAG		;(PBRA) DO PAGE EJECT AND RETURN

CHO150	CMPI.B	#LF,D0		;IS IT A LINE FEED?
	BNE.S	CHO160		;BRANCH IF NOT
	RTS			;IGNORE IT (THESE ARE STILL A PROBLEM)

CHO160	CMPI.B	#BS,D0		;IS IT A BACKSPACE?
	BNE.S	CHO190		;BRANCH IF NOT
	SUBQ.B	#1,HPOSN.L	;DECREMENT X POSITION
	BRA	BYTOUT		;(PBRA) OUTPUT THE CHARACTER AND RETURN

CHO190	ADDQ.B	#1,HPOSN.L	;BUMP X POSITION
	CMPI.B	#LINESIZ,HPOSN.L ;ARE WE AT THE END OF THE LINE +1?
	BLO.S	CHO195		;BRANCH IF NOT
	BSR	DOCRLF		;START A NEW LINE
CHO195	BRA	BYTOUT		;(PBRA) OUTPUT THE CHARACTER AND RETURN

;-----------------------------------------------------------------------
;CLOSE THE PRINTER
;
CLOSE	BRA.S	NEWPAG		;(PBRA) EJECT PAGE AND RETURN

;-----------------------------------------------------------------------
;RETURN THE ADDRESS OF THE INFORMATION ARRAY IN D0
;
GETINFO	MOVE.L	#INFO,D0
	RTS

INFO	DC.L	START		;STARTING AND ENDING ADDRESSES OF THIS
	DC.L	END		; HANDLER
	DC.L	INFOSTR		;DESCRIPTION

	IF	EPSONHAN
INFOSTR	ASCII	'EPSONHAN  SEP-14-86  96-column Epson printe'
	DC.B	'r' + $80
	ENDIF

	IF	ITOHAN
INFOSTR	ASCII	'ITOHAN    SEP-14-86  96-column C.Itoh printe'
	DC.B	'r' + $80
	ENDIF

	IF	PARHAN
INFOSTR	ASCII	'PARHAN    SEP-14-86  80-column Generic printe'
	DC.B	'r' + $80
	ENDIF

	IF	DUMHAN
INFOSTR	ASCII	'DUMHAN    SEP-14-86  Direct control of printe'
	DC.B	'r' + $80
	ENDIF

;-----------------------------------------------------------------------
;SPACE OVER TO THE NEXT TAB STOP
;
DOTAB	MOVE.L	D0,-(SP)	;SAVE D0
DOTAB10	MOVEQ	#SPACE,D0	;OUTPUT A SPACE CHARACTER
	BSR.S	BYTOUT

	ADDQ.B	#1,HPOSN.L	;BUMP X POSITION
	CMPI.B	#LINESIZ,HPOSN.L ;ARE WE AT THE END OF THE LINE +1?
	BLO.S	DOTAB20		;BRANCH IF NOT
	BSR	DOCRLF		;START A NEW LINE

DOTAB20	MOVE.B	HPOSN.L,D0	;ARE WE AT THE NEXT TAB STOP?
	ANDI.B	#$07,D0
	BNE.S	DOTAB10		;BRANCH IF NOT
	MOVE.L	(SP)+,D0	;RESTORE D0
	RTS

;-----------------------------------------------------------------------
;MOVE TO THE NEXT LINE
; CHECK FOR END-OF-PAGE
;
NEWLIN	BSR.S	DOCRLF		;MOVE DOWN A LINE
	CMPI.B	#60,LINE.L
	BLO.S	NL90		;(BLO) BRANCH IF WE ARE (WE SCROLL)
	BSR.S	NEWPAG
NL90	RTS

;-----------------------------------------------------------------------
;ADVANCE TO THE BEGINNING OF THE NEXT PAGE (FORM FEED)
;
NEWPAG	BSR.S	DOCR		;MAKE SURE WE'RE IN THE LEFT COLUMN
NP10	BSR.S	DOLF		;MOVE DOWN A LINE UNTIL WE'RE AT THE
	CMPI.B	#66,LINE.L	; TOP OF THE NEXT PAGE
	BLO.S	NP10		;(BLO) 6 LINES PER INCH * 11 INCHES
	CLR.B	LINE.L		; = 66 LINES.  RESET LINE COUNTER
	RTS

;-----------------------------------------------------------------------
;ADVANCE TO THE BEGINNING OF THE NEXT LINE
;
DOCRLF	BSR.S	DOCR		;OUTPUT A CARRIAGE RETURN & A LINE FEED
	BRA.S	DOLF		;(PBRA)

;-----------------------------------------------------------------------
;OUTPUT A CARRIAGE RETURN
;
DOCR	MOVE.L	D0,-(SP)	;SAVE D0
	MOVEQ	#CR,D0		;OUTPUT A CARRIAGE RETURN
	BSR.S	BYTOUT
	CLR.B	HPOSN.L		;RESET HORIZONTAL POSITION TO 0
	MOVE.L	(SP)+,D0	;RESTORE D0
	RTS

;-----------------------------------------------------------------------
;OUTPUT A LINE FEED
;
DOLF	MOVE.L	D0,-(SP)	;SAVE D0
	MOVEQ	#LF,D0		;OUTPUT A LINE FEED
	BSR.S	BYTOUT
	ADDQ.B	#1,LINE.L	;COUNT THIS LINE
	MOVE.L	(SP)+,D0	;RESTORE D0
	RTS

;======================================================================
;LOW-LEVEL ROUTINE TO OUTPUT THE BYTE IN D0 TO THE PRINTER
;
BYTOUT	BTST	#4,CENSTAT	;WAIT UNTIL NOT BUSY
	BNE.S	BYTOUT		; I.E: UNTIL BIT #4 IS LOW

	MOVE.B	D0,CENDATA	;OUTPUT THE DATA BYTE

	BCLR	#4,PPAR05X	;DELAY AT LEAST 1 US THEN
	MOVE.B	PPAR05X,PPAR05	; SET STROBE BIT LOW (TRUE)
	BSET	#4,PPAR05X	;DELAY AT LEAST 1 US THEN
	MOVE.B	PPAR05X,PPAR05	; SET STROBE BIT HIGH (FALSE)
	RTS

END	EQU	@		;ADDRESS WHERE THIS HANDLER ENDS +1

;-----------------------------------------------------------------------
;HOOK THIS HANDLER INTO THE DEVICE-HANDLER TABLE
;
	ORG	4 *DEVNUM +DEVTBL
	DC.L	PRHAN

	END
-