	.TITLE 	LPA.15   EDIT 42 UOW
/
/  21 SEP 73 - TRY TO SIMULATE LINE PRINTER ACTION TO FIND OUT
/		DIFFICULTY WITH PDP-15 WATRAN LISTINGS
/
/COPYRIGHT 1971, DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
/9-23-71	EDIT 42
/J.M. WOLFBERG
/LPA.--IOPS LINE PRINTER HANDLER FOR LP15 LINE PRINTER
/	INTERFACE FOR DATA PRODUCTS 2310 AND 2410 LINE
/	PRINTERS AND THE MOHAWK 5000 PRINTER.
/CALLING SEQUENCE:
/	CAL + .DAT SLOT (9-17)
/	FUNCTION
/	N ARGS, WHERE N IS A FUNCTION OF "FUNCTION"
/	NORMAL RETURN
/BITS 12-13 OF .SCOM+4 INDICATE PRINTER.
/	00= UNDEFINED.
/	01= 80 COLUMNS.
/	10= 120 COLUMNS.
/	11= 132 COLUMNS.
/ASSEMBLY PARAMETERS:
/   ADSS=1 PRODUCES A VERSION WITHOUT EXTENDED ERROR MESSAGES.
/   NOFF=1 PRODUCES A VERSION WHICH NEVER INSERTS FF (EXCEPT ON .INIT).
/
/LOC 34=WORD COUNT (NEVER USED)
/LOC 35=CURRENT ADDRESS
/API CHANNEL 56
/
/*LPP1=706541			/PRINT 1 LINE.
/*LPPM=706521			/PRINT MULTI-LINES.
/*LPSF=706501			/SKIP IF DONE OR ERROR.
/*LPRS=706542+10			/CLEAR AC AND READ STATUS.
/*LPEI=706544			/ENABLE INTERRUPT.
/*LPDI=706561			/DISABLE INTERRUPT.
/*LPCD=706621			/CLEAR DONE FLAG.
/*LPCS=706641			/CLEAR STATUS & ERROR FLAG.
/
LPP1=700104
LPPM=700104
LPSF=700101
LPRS=IOT
LPEI=IOT
LPDI=IOT
LPCD=700102
LPCS=700112
API=50
ADSS=1
/
.SCOM=100
.MED=3
IDX=ISZ
SET=ISZ				/USED TO SET SWITCHES TO NON-ZERO.
EXERRS=.SCOM+37
	.IFUND ADSS
DOS=1
	.ENDC
	.GLOBL LPA.
	.TITLE CAL ENTRANCE
LPA.	DAC	LPCALP		/SAVE CAL POINTER.
	DAC	LPARGP		/AND ARGUMENT POINTER.
	IDX	LPARGP		/POINTS TO WORD 2 - FUNCTION CODE.
/LPA1 TO SKPSET-1 IS ONCE ONLY CODE AND IS USED FOR STORAGE AFTER THE INITAL SETUP.
/
/ LPOUT  - HOLDS EXIT ADDRESS FOR INTERRUPT.
/ LPAC   - HOLDS AC ON INTERRUPT.
/ MULTSW - NON-ZERO(400000)=MULTI-LINE MODE; 0=SINGLE LINE MODE.
/ LPHDRP - POINTER TO USER'S HEADER WORD.
/ LPDATP - POINTER TO USER'S FIRST DATA WORD.
/ LPHEAD - POINTER TO CURRENT OUTPUT BUFFER.
/ DATAWD - USER'S FIRST DATA WORD FOR POSSIBLE REPLACEMENT.
/ HEADER - USER'S HEADER WORD FOR POSSIBLE REPLACEMENT.
/ BUFSZE - 70 FOR 132 COLMS; 44 FOR 80 COLMS.
/ LPFFCT - # LINES TO PRINT PER PAGE.
/ LPCHAR - HOLDS 1ST CHAR OF DATA BUFFER FOR POSSIBLE REPLACEMENT.
/
LPA1	CAL	API		/API CHANNEL 56.
LPOUT	16			/.SETUP.
LPAC	LPSF
LPHDRP	LPINT
LPDATP	LAC (JMP SKPSET		/SET UP TO SKIP AROUND THIS CODE.
HEADER	DAC LPA1
LPMODE	LAC* (.SCOM+4
LPHEAD	AND SPACE
BUFSIZ	SNA
LPFFCT	JMP LPCHAR
DATAWD	LAC (70
MULTSW	SKP
LPCHAR	LAC (44
	DAC BUFSIZ
SKPSET	LAC*	LPARGP
	IDX	LPARGP		/POINTS TO WORD 3 - BUFFER ADDRESS.
	AND	(17777		/STRIP OFF UNIT NUMBER.
	TAD	(JMP LTABL-1	/DISPATCH TO PROCESS FUNCTION.
	DAC	.+1
	XX
LTABL	JMP	LPIN		/1 - .INIT
	SKP			/2 - .FSTAT,.RENAM,.DLETE - IGNORE
	JMP	LPER06		/3 - .SEEK - ERROR
	IDX	LPARGP		/4 - .ENTER - IGNORE
	JMP	LPNEXT		/5 - .CLEAR - IGNORE
	JMP	LPCLOS		/6 - .CLOSE
	JMP	LPNEXT		/7 - .MTAPE - IGNORE
	JMP	LPER06		/10 - .READ - ERROR.
	JMP	LPWRIT		/11 - .WRITE
	JMP	LPWAIT		/12 - .WAIT OR .WAITR
LPER06	LAW	6		/ILLEGAL HANDLER FUNCTION.
	.IFUND DOS
	JMP*	(4		/(.MED+1.
	.ENDC
	.TITLE INTERRUPT SERVICE
	.IFDEF DOS
	JMP SETERR
	.ENDC
/
/LPA. INTERRUPT SERVICE
/
LPINT	JMP	LPPIC		/JMP FOR PI ENTRY.
	DAC	LPAC		/STORE AC FOR API ENTRY.
	LAC (NOP
	DAC	LPFVSW		/LEAVE PIC ALONE ON EXIT.
	DAC TRNION		/SET TO NOP FOR API.
	LAC	LPINT		/FOR API, CONTAINS PC,L,EM,MP.
	JMP	LPCOM
LPPIC	DAC	LPAC		/SAVE AC ON PI ENTRY.
	LAC (ION
	DAC	LPFVSW
	DAC TRNION
	LAC*	(0		/GET PI,L,EM,MP.
LPCOM	DAC	LPOUT
/
/LPA. STATUS REGISTER
/	0 - ERROR*
/	1 - LP ALARM
/	2 - LINE OVER
/	3 - ILLEGAL HORIZONTAL TAB
/	4 - BUSY
/	5 - DONE*
/	* CAUSES PI OR API INTERRUPT
/
	LPRS			/READ AND
	LPCS			/CLEAR STATUS.
	LAC LPUND
	DZM LPUND
	SZA			/DON'T ALLOW FOR INTERRUPTS IF NONE WERE EXPECTED.
	JMP TRNION
	LAW 3
	.IFDEF DOS
	JMP SETERR
	.ENDC
	.IFUND DOS
	JMP* (4			/(.MED+1
	.ENDC
TRNION	XX			/ION IF PI; NOP IF API.
	SKP
	JMP LPERT		/ERROR CONDITION - SEE WHICH ONE.
CHKALL	LAC LPLFSW		/0 IF NO LF; + NON-0 IF LINE WAITING;
	DZM LPLFSW
	SZA
	JMP CHKMOD		/LINE WAITING.
	.IFUND NOFF
CHKFF	LAC LPFFCT		/0 IF LPA JUST OUTPUT A FF.
	SZA
	JMP CHKRST		/NO LINE WAITING.
	LAW -73			/RESET FF COUNTER.
	DAC LPFFCT
	.ENDC
	.IFDEF NOFF
	JMP CHKRST
	.ENDC
CHKMOD	SET INTERR
	LAC TWOLNE		/MULTILINE OPERATION?
	SZA!STL			/IOT ALREADY LPP1 BECAUSE JUST OUTPUT 1 LINE.
	JMP SETIOT		/RESET IOT FOR MULTILINE.
	JMP LPRINT		/OUTPUT WAITING LINE.
CHKRST	LAC HEADSW		/IF USER'S BUFFER WAS MODIFIED ON LAST
	SNA			/WRITE, MUST RESTORE IT TO ORIGINAL STATE.
	JMP LPEXIT		/NO - NOT MODIFIED.
	LAC HEADER		/REPLACE USER'S HEADER WORD.
	DAC* LPHDRP
	LAC DATAWD		/REPLACE USER'S FIRST DATA WORD.
	DAC* LPDATP
	DZM HEADSW
/
/INTERRUPT EXIT
/
LPEXIT	LAC	(JMP LPPIC	/RESTORE PIC INTERRUPT ENTRY.
	DAC	LPINT
	LAC	LPAC
LPFVSW	XX			/"ION" IF PI; "LAC LPAC" IF API.
	LPEI			/ENABLE INTERRUPTS FROM LINE PRINTER.
	DBR
	XCT	.+1
	XCT	.+1
	JMP*	LPOUT		/0 IF PI; DTIN IF API.
	.TITLE     ERROR ROUTINE
/
/ERROR ROUTINE
/
LPERT	SZL!RAL
	JMP	LPIPS4		/BIT 1 = LP ALARM.
	SZL!CLL
	JMP	LPER37		/BIT 2 = LINE OVER.
	SPA!RAL
	JMP LPER37-1		/BIT 3 = ILLEGAL HORIZONTAL TAB.
	SMA			/BIT 4= BUSY.
	JMP CHKALL		/NO SPECIFIC ERROR BIT UP - IGNORE.
	JMP LPRTY			/BIT 4 = BUSY: RETRY.
	STL
LPER37	LAC MULTSW		/PRINT ERRORS 37 AND 47 ONLY IF IN MULTI-LINE
	SMA			/MODE.
	JMP CHKALL		/IN SINGLE LINE MODE, IGNORE ERROR.
	LAW 47			/IOPS 47.  (ILLEGAL HORIZONTAL TAB)
	SNL
	LAW	37		/IOPS 37 (LINE OVER)
	.IFUND DOS
	JMP*	(4
	.ENDC
	.IFDEF DOS
SETERR	DAC ERRNUM
ERLOOP	NOP			/'JMP LPTRY' IF IOPS 4 ERROR.
	LAC ERRNUM
EROUT	JMS* (EXERRS
	JMP ERLOOP
	LAW -1
	.SIXBT 'LPA'
ERRNUM	0			/HOLDS ERROR NUMBER FOR REPEAT.
	.ENDC
LPIPS4	LAC	(LPRTY		/SET UP FOR IOPS4 RETURN.
	DAC*	(.MED
	.IFUND DOS
	LAC (4
	JMP* (4
	.ENDC
	.IFDEF DOS
	LAC (JMP LPRTY
	DAC ERLOOP
	LAW 4
	DAC ERRNUM
	JMP EROUT
LPRTY	LAC (NOP
	DAC ERLOOP
	LAC LPHEAD
	.ENDC
	.IFUND DOS
LPRTY	LAC LPHEAD		/RETRY AFTER IOPS 4.
	.ENDC
	JMP LPRNTA		/FIND CORRECT EXIT.
	.TITLE .INIT FUNCTION
/
/.INIT
/
LPIN	IDX	LPARGP
	LAC BUFSIZ		/36(10) FOR 80 COLS; 56(10) FOR 132 COLS.
	DAC* LPARGP		/RETURN TO USER.
	IDX LPARGP		/NOW POINTS TO RETURN.
	.IFUND NOFF
	LAW -73
	DAC	LPFFCT		/SET UP TO PRINT 57 (10) LINES PER PAGE.
	LAC* LPCALP		/BIT 6 OF FIRST WORD OF .INIT IS SET
	AND (4000		/TO INHIBIT FORM FEEDS EVERY 57 LINES.
	SZA
	JMP NOFF1
	LAC (ISZ LPFFCT
	JMP NOFF2
NOFF1	LAC (NOP		/INHIBIT FF.
	.ENDC
	DZM LPCLSW		/NO FF ON CLOSE EITHER.
	.IFUND NOFF
NOFF2	DAC LPFF3
	DAC	LPFF2
	.ENDC
	JMS LPIOCK		/INSURE LP NOT BUSY.
PRNTFF	LAC (LPP1
	DAC LPIOT
	LAC FF
	DAC CTLCHR
	LAC (1			/SET FFBUF FOR IMAGE MODE.
	DAC FFBUF
	LAC	FFBUFP		/OUTPUT FF.  
	JMS LPSET
LPNXT1	LPEI			/ENABLE INTERRUPTS FROM LINE PRINTER.
/
/NORMAL CAL EXIT
/
LPNEXT	DBR
	XCT	.+1
	XCT	.+1
	JMP*	LPARGP
	.TITLE .WRITE FUNCTION
/
/.WRITE
/
LPWRIT	JMS LPIOCK		/PRINTER BUSY?
	LAC* LPCALP		/GET THE DATA MODE FROM THE USER CAL.
	RAR; RTR; RTR; RTR; RTR	/PUT IN BITS 15-17.
	AND (3
	DAC LPMODE		/2=IOPS ASCII, 1=IMAGE ASCII.
	LAC*	LPARGP		/USER BUFFER ADDRESS.
	IDX LPARGP
	IDX LPARGP		/POINTS TO RETURN.
	DAC	LPHDRP
	LAC*	LPHDRP		/BIT 0=1 FOR MULTIPLE LINES;0 FOR SINGLE.
	DAC HEADER		/SAVE FOR POSSIBLE REPLACEMENT.
	DAC MULTSW		/BIT 0=1 IF MULTIPLE LINE MODE, 0 IF SINGLE.
	RAL
	LAC	(LPP1
	SZL
SETIOT	LAC	(LPPM
	DAC	LPIOT
	SNL
	JMP LPCTRL		/IN SINGLE LINE MODE.
LPRINT	DZM TWOLNE
	LAC LPLFSW
	SZA
	JMP LFOUT
	LAC LPHDRP
LPRNTA	JMS LPSET		/ISSUE IOTS.
	LAC INTERR		/BIT17=1 IF OUTPUTTING LINE AFTER LF OR FF.
	SNA
	JMP LPNXT1		/EXIT VIA CAL EXIT.
	DZM INTERR
	JMP LPEXIT		/EXIT VIA INTERRUPT EXIT.
/
/OUTPUT LF BEFORE THE CURRENT LINE.
/
LFOUT	LAC (LPP1
	DAC LPIOT		/SET FOR SINGLE LINE MODE.
	LAC LF
	DAC CTLCHR
	LAC FFBUFP
	JMP LPRNTA
/
/IN SINGLE LINE MODE MUST CHECK FIRST CHARACTER FOR THE VERTICAL CONTROL
/CHARACTERS 12 (LF), 14 (FF), 20 (OVERPRINT) AND 21 (DOUBLE SPACE).
/
LPCTRL	LAC HEADER
	AND (777774		/AND OUT BITS 16-17 FOR DATA MODE.
	XOR LPMODE
	DAC* LPHDRP		/SET UP DATA MODE IN BUFFER.
	SET HEADSW		/SET TO REPLACE USER'S BUFFER HEADER WORD.
	LAC LPHDRP		/IN SINGLE LINE MODE MUST CHECK
	TAD (2			/FIRST DATA CHAR FOR VERTICAL CONTROL CHAR.
	DAC LPDATP
	LAC LPMODE
	RAR			/LINK = 1 IF IN IMAGE MODE.
	LAC* LPDATP
	DAC DATAWD		/SAVE FOR POSSIBLE REPLACEMENT.
	SZL			/IF IN IMAGE MODE, CHARACTER ALREADY IN CORRECT BITS.
	JMP GOTCHR
	AND (774000		/ROTATE CHAR FROM BITS0-6 TO BITS11-17.
	RTL; RTL; RTL; RTL
GOTCHR	DAC LPCHAR		/SAVE FOR LATER CHECK.
	SAD DC1			/DC1? (DOUBLE SPACE) (CODE 21)
	.IFUND NOFF
	JMP CTLDC1		/YES - PRINT 2 LINES.
	.ENDC
	.IFDEF NOFF
	JMP CTLLF
	.ENDC
	SAD FF			/FF? (CODE 14)
	.IFUND NOFF
	JMP CTLFF		/YES: RESET FF CNT AND OUTPUT 2 LINES.
	.ENDC
	.IFDEF NOFF
	JMP CTLLF
	.ENDC
	SAD LF			/LINE FEED? (CODE 12)
	JMP CTLLF		/YES -  PRINT 2 LINES.
	SAD OVRPNT			/OVERPRINT? (AS OUTPUT BY F4 OTS) (CODE 20).
	JMP CTLOVR		/YES - REPLACE 1ST CHAR WITH 'CR' AND OUTPUT 2 LINES.
	SET LPLFSW		/SET LP SWTCH TO NON-0 SO WILL OUTPUT FF BEFORE LINE.
	.IFUND NOFF
	JMP LPFF
	.ENDC
	.IFDEF NOFF
	JMP LPRINT
	.ENDC
/
/HAVE FOUND A VERTICAL CONTROL CHARACTER.
/FF: RESET THE INTERNAL FF COUNT AND OUTPUT 2 LINES.
/LF: OUTPUT 2 LINES.
/DC1: SET SWITCH SO BUMP FF COUNT TWICE AND OUTPUT 2 LINES.
/OVERPRINT: REPLACE FIRST CHAR WITH A CR (WHICH EFFECTIVALLY DOES
/  NOTHING HERE) AND OUTPUT 2 LINES.
/
	.IFUND NOFF
CTLFF	LAW -73
	DAC LPFFCT		/RESET FF COUNT.
	SKP
CTLDC1	SET DBLESW		/SET TO COUNT 2 LINES.
	.ENDC
CTLLF	LAC (LPPM
	DAC LPIOT		/RESET IOT FOR MULTILINE MODE.
	LAC* LPHDRP
	AND (2
	XOR (2000		/SET UP TO PRINT 2 LINES.
	DAC* LPHDRP
	SET TWOLNE
	.IFUND NOFF
	LAC LPCHAR
	SAD OVRPNT		/NO FF CNT IF OVERPRINT.
	JMP LPRINT
LPFF	LAC DBLESW
	DZM DBLESW
	SZA
LPFF2	ISZ LPFFCT		/OR 'NOP'.
	SKP
	JMP FFOUT
LPFF3	ISZ LPFFCT
	JMP LPRINT
FFOUT	DZM LPLFSW		/NO NEED FOR BOTH FF AND LF.
	JMP PRNTFF
	.ENDC
	.IFDEF NOFF
	JMP LPRINT
	.ENDC
/
CTLOVR	LAC LPMODE		/MUST REPLACE 20 IN FIRST CHAR POSITION WITH
	SNA			/A CR.
	JMP LPOVR1
	LAC CR			/IMAGE MODE.
	JMP LPOVR2
LPOVR1	LAC DATAWD		/IOPS ASCII:
	AND (3777		/TAKE OUT FIRST 7 BIT CHAR AND
	XOR (064000		/PUT IN A CR.
LPOVR2	DAC* LPDATP
	JMP CTLLF
	.TITLE .CLOSE FUNCTION
/
/
/.CLOSE
/
LPCLOS	JMS	LPIOCK		/CHECK I/O UNDERWAY.
	ISZ	LPCLSW		/777777 IN AC IF HAVEN'T BEEN THRU CLOSE CODE.
	JMP	LPCLDN		/DONE.
	LAC (LPPM
	DAC LPIOT
	LAC FF
	DAC CTLCHR
	LAC (2001		/OUTPUT FF, CR TO ELIMINATE MANUAL PRINT
	DAC FFBUF		/BEING SET ON MOHAWK PRINTER.
	LAC	FFBUFP		/OUTPUT FF.
	JMS LPSET
	LPEI			/ENABLE INTERRUPTS FROM LINE PRINTER.
LPCALX	DBR
	XCT	.+1
	XCT	.+1
	JMP*	LPCALP		/HANG ON CAL.
LPCLSW	777777			/-1 = .CLOSE NOT DONE.
LPCLDN	LAW -1
	DAC	LPCLSW		/INITIALIZE .CLOSE INDICATOR
	JMP	LPNEXT		/EXIT.
	.TITLE .WAIT FUNCTION
/
/.WAIT OR .WAITR
/
LPWAIT	LAC*	LPCALP
	AND	(1000
	SNA			/BIT 8 = 1 FOR .WAITR
	JMP	LPWAT1		/.WAIT - GO HANG ON CAL.
	LAC	(700000		/LINK, ETC.
	AND	LPCALP
	DAC	LPCALP
	LAC*	LPARGP		/15-BIT BUSY ADDRESS.
	AND	(77777
	XOR	LPCALP
	DAC	LPCALP
	IDX	LPARGP
LPWAT1	JMS	LPIOCK		/CHECK I/O UNDERWAY.
	JMP* LPARGP		/OK - RETURN.
/
/CHECK FOR I/O UNDERWAY
/
LPIOCK	0
	LAC	LPUND		/0 = NO ACTIVITY.
	SNA
	JMP*	LPIOCK		/NO I/O UNDERWAY.
	JMP	LPCALX		/HANG ON CAL TIL NOT BUSY.
/
/ SETUP AND OUTPUT TO PRINTER.
/
LPSET	0
	LPDI			/TAKE LINE PRINTER OFF INTERRUPT.
	DAC LPHEAD		/SAVE IN CASE OF IOPS 4.
	TAD LPCLDN		/(-1.
	DAC* LPCA35
	DAC LPUND		/SET I/O BUSY FLAG.
LPIOT	LPP1			/LPP1 OR LPPM.
	JMP* LPSET
/
/CONSTANTS
/
LPCALP	0			/CAL ADDRESS.
LPARGP	0			/CAL ADDRESS - MODIFIED
HEADSW	0			/NON-ZERO = USER'S HEADER WORD HAS BEEN MODIFIED.
INTERR	0			/BIT17=1 IF OUTPUTTING LINE AFTER FF.
TWOLNE	0
LPLFSW	0			/LF SWITCH: NON-0 = LINE WAITING.
DC1	21			/SKIP 2 LINES (CODE OUTPUT BY OTS)
FF	14			/FORM FEED
LF	12			/LINE FEED
OVRPNT	20			/CODE FOR OVERPRINT OUTPUT BY OTS
SPACE	40
LPCA35	35			/CURRENT ADDRESS
DBLESW	0			/SET FOR 2 LINE SPACE SO BUMP FF TWICE
FFBUF	2001			/BIT 0=1 IF CLOSE.
LPUND	0
CTLCHR	0			/.SIXBT CHAR: FF(14), OR LF(12).
CR	15			/CR FOR CLOSE ONLY.
FFBUFP	FFBUF
	.END
