;********************************************************
;* *
;* BI-DIRECTIONAL PRINTING DRIVER *
;* FOR DIABLO 1620 OR SIMILAR *
;* DAISYWHEEL PRINTER *
;* *
;********************************************************
;
; VERSION: 1.00
;
; DATE: 03/Mar/1980
;
; HISTORY: Modified for CP/M use
; from PTDOS program
; originally published by PROTEUS
;
; Modifications by:
; Bill Bolton
; Software Tools
; P.O. Box 80,
; Newport Beach,
; NSW, 2106,
; Australia
;
NULL EQU 000H ;ASCII NULL
DEL EQU 07FH ;ASCII DELETE
CR EQU 00DH ;ASCII CARRIAGE RETURN
LF EQU 00AH ;ASCII LINE FEED
FF EQU 00CH ;ASCII FORM FEED
ESC EQU 01BH ;ASCII ESCAPE
HTAB EQU 009H ;ASCII HORIZONTAL TAB
SPACE EQU 020H ;ASCII ' '
BACKSP EQU 008H ;ASCII BACKSPACE
ACK EQU 006H ;ASCII ACKNOWLEDGE
ETX EQU 003H ;ASCII END OF TEXT
STPORT EQU 003H ;HORIZON 1ST SERIAL STATUS
DPORT EQU STPORT-1 ;HORIZON 1ST SERIAL DATA
OUTMASK EQU 001H ;OUTPUT STATUS MASK
INMASK EQU 002H ;INPUT STATUS MASK
COUNT EQU 150 ;DIABLO BUFFER LENGTH
;
ORG 0F200H ;Or wherever suits
;
PROCESS:
MOV A,C
CPI CR ;CARRIAGE RETURN ?
JZ PRINT ;YES, PRINT OUT THE BUFFER
CPI LF ;LINE FEED ?
JZ PUTC ;YES, SEND IT
CPI FF ;FORM FEED ?
JZ PUTC ;YES, SEND IT
CPI DEL ;DELETE ?
RZ ;YES, IGNORE IT
CPI NULL ;NULL ?
RZ ;IGNORE IT
;
PRO2:
LDA EOLINE ;INCREMENT END OF LINE
INR A
STA EOLINE
LHLD TXTPT ;GET TEXT POINTER
MOV M,C ;CHARACTER WAS IN C
INX H ;BUMP POINTER
MVI M,0 ;BUFFER END MARK IS 0
SHLD TXTPT ;STORE POINTER
RET
;
;* This routine strips leading and lagging blanks from
;* the buffer before sending the buffer out to the printer.
;
;* Strip the leading blanks
;
PRINT:
LXI H,BUFFER+1 ;POINT TO 1ST CHARACTER POSITION
MVI D,0 ;BLANKS COUNTER
MVI A,SPACE ;BLANK FOR COMPARISION
P1:
CMP M ;BLANK ?
JNZ P2 ;NO, STOP COUNTING
INR D
INX H
JMP P1
;
P2:
DCX H ;POINT TO CHAR-1
MVI M,0 ;PUT IN A MARKER
MOV A,D ;GET BLANK COUNT
STA BOLINE ;AND SAVE IT
;
;* Strip the lagging blanks
;
LHLD TXTPT ;POINT TO BUFFER END MARK
LDA EOLINE ;GET CHARACTER COUNT
MOV D,A
MVI A,SPACE ;GET A SPACE
;
P3:
DCX H
DCR D ;BLANK COUNTER
CMP M ;IS IT A SPACE ?
JZ P3 ;YES, KEEP COUNTING
;
P4:
INX H ;NO, BACK UP THE POINTER
MVI M,0 ;STORE END MARKER
MOV A,D
STA EOLINE ;STORE NEW COUNT
SHLD TXTPT ;STORE NEW BUFER END
;
;* Calculate the most efficient direction to print
;* (logic seeking).
;
DRCTN:
LDA HDPOS ;GET PRINT HEAD POSITION
PUSH PSW ;SAVE IT
LXI H,BOLINE ;POINT TO BEGINNING OF LINE
SUB M ;FIND THE DIFFERENCE
CM ABSVAL ;TAKE THE ABSOLUTE VALUE
MOV B,A ;SAVE IT IN B
INX H ;GET THE END OF LINE
POP PSW ;GET HEAD POSITION
SUB M ;FIND THE DIFFERENCE
CM ABSVAL ;TAKE THE ABSOLUTE VALUE
SUB B ;COMPARE DISTANCE TO BOL AND EOL
JP MFWRD ;IF PLUS FORWARD IS FASTER
;
;* Print backwards
;
MBWRD:
MVI D,'6' ;DIABLO BACKWARD PRINT CODE
LDA EOLINE ;GET END OF LINE
CALL ALIGN ;PROCESS THE DATA
LDA BOLINE ;POSITION OF 1ST BUFFER CHARACTER
ORA A ;IS IT THE ZERO POSITION
JZ MB2 ;YES, CANT TAB LEFT OF MARGIN
DCR A
;
MB2:
STA HDPOS ;UPDATE HEAD POSITION
LXI D,-1
LHLD TXTPT ;POINT TO END OF BUFFER
JMP PRLINE ;PRINT THE BUFFER
;
;* Print forwards
;
MFWRD:
MVI D,'5' ;DIABLO FORWARD PRINT CODE
LDA BOLINE ;GET BEGINNING OF LINE
CALL ALIGN
LDA EOLINE ;GET LAST CHARACTER POSITION
INR A
STA HDPOS ;SAVE NEW HEAD POSITION
LXI H,BUFFER ;POINT TO BUFFER START
LDA BOLINE ;COMPUTE POSITION OF 1ST NON BLANK
MVI D,0
MOV E,A
DAD D
LXI D,1 ;SET UP TO READ BUFFER FORWARD
;
;* Print the buffer
;
PRLINE:
DAD D ;BUMP HL
MOV A,M ;MOVE CHARACTER IN BUFFER TO A
ORA A ;END OF BUFFER ?
JZ CLRBUF ;YES, GO CLEAN UP
CALL PUTC ;PRINT THE CHARACTER
JMP PRLINE
;
;* Align the Print Head to the correct position
;* to start printing
;
;* NOTE: The diablo 1610/1620 can only do an
;* "absolute tab" to the first 126 character
;* positions.
;
;* D = Direction of printing
;* A = BOLINE or EOLINE
;
ALIGN:
MOV E,A ;SAVE BOLINE/EOLINE
MVI A,ESC ;GET "COMMAND" CODE
CALL PUTC ;SEND IT
MOV A,D ;GET THE DIRECTION CODE
CALL PUTC ;SEND IT
;
MVI A,ESC ;GET "COMMAND" CODE
CALL PUTC ;SEND IT
MVI A,HTAB ;GET ABSOLUTE TAB CODE
CALL PUTC ;SEND IT
MOV A,E ;GET LOCATION TO TAB TO
ADI 1 ;ADD TO SATISFY DIABLO
JMP PUTC ;SEND IT AND RETURN
;
CLRBUF:
LXI H,BUFFER+1 ;CLEAR BUFFER
SHLD TXTPT
XRA A
STA EOLINE ;RESET COUNTERS
STA BOLINE
STA BUFFER+1
RET
;
ABSVAL:
CMA ;TAKE THE ABSOLUTE VALUE
INR A
RET
;
PUTC:
MOV C,A
CALL OUTPUT ;SEND THE CHARACTER
CPI ESC ;WAS IT AN ESCAPE?
JZ ESCSEQ ;YES, NEEDS SPECIAL TREATMENT
LDA OUTCNT ;CHARS SENT SINCE O/P COUNT RESET
DCR A
STORE:
STA OUTCNT ;SAVE UPDATED COUNT
RNZ ;NO, RETURN
MVI A,COUNT ;SET COUNT
STA OUTCNT
MVI C,ETX ;YES, GET ETX
CALL OUTPUT ;SEND IT
ACKLOOP:
CALL INPUT ;GET CHARACTER FROM PRINTER
CPI ACK ;DIABLO SENDS ACK WHEN IT GETS ETX
;FROM ITS CHARACTER BUFFER
JNZ ACKLOOP ;NOT FOUND, KEEP LOOKING
RET
;
ESCSEQ:
LDA OUTCNT ;GET OUTPUT COUNT
ADI 2 ;MAKE SURE NEXT TWO CHARS,
JMP STORE ;GET SENT BEFORE ETX
;
OUTPUT:
IN STPORT ;1ST SERIAL PORT
ANI OUTMASK
JZ OUTPUT
MOV A,C
OUT DPORT
RET
;
INPUT:
IN STPORT
ANI INMASK
JZ INPUT
IN DPORT
ANI 07FH
RET
;
;
HDPOS DB 0 ;CURRENT HEAD POSITION
BOLINE DB 0 ;BEGINNING OF LINE POINTER
EOLINE DB 0 ;END OF LINE POINTER
TXTPT DW BUFFER+1 ;BUFFER POINTER
OUTCNT DB COUNT ;CHARACTERS SENT TO PRINTER
;
BUFFER DW 0000H
DS 160 ;CHARACTER BUFFER
;
END PROCESS