home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
CPMUG
/
CPMUG042.ARK
/
BIDI.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
9KB
|
328 lines
;
; TITLE BI-DIRECTIONAL DIABLO PRINTER DRIVER
; FILENAME BIDI.LIB
; AUTHOR Robert A. Van Valzah 9/30/79
; LAST REVISOR R.A.V. 11/10/79
; REASON byte squeezing
;
;
; plan of attack:
; ===============
; characters come in one at a time and are stored into
; a buffer until a line feed comes in. at this point,
; the line in the buffer is analized and a decision is
; made to print it forward or backward so as to mininmize
; the head movement.
;
; the gory details:
; =================
; characters which are printable are just stored in the
; buffer. blanks, on the other hand, are accumulated
; and the number of blanks to move is stored with a bias
; of 80h. the first byte of the buffer is an exception:
; it is initialized to 0h and is used to accumulate the
; number of spaces between the left margin and the first
; printable character (this is the location leolpos).
; the position of the rightmost printable character is
; keep track of as characters come in the location reolpos.
;
; as the head is moved across the page, its position is
; recorded in hpos. this information is used in
; conjunction with leolpos and reolpos to determine if
; printing forward or backward will cause the shortest
; printhead movement. if the printhead is currently to
; the left of the centerpoint of the line, then it is
; shortest to move to the left end and start printing.
; otherwise, it is shortest to move to the right end
; and print backward. if the printhead is exactly at
; the midpoint, the line is printed backward so as to
; leave the printhead as close to the left margin
; as possible.
;
;
; port i/o number equates
;
base equ 0f4h
datal equ base
datah equ base+1
cmand equ base+2
stats equ base
;
; print formatting equates
;
ncols equ 120 ;max number of cols/line (must be <=126)
;
; command bits
;
restr equ 1 ;restore carriage
chstb equ 2 ;character strobe
xstb equ 4 ;carriage strobe
ystb equ 8 ;paper feed strobe
selpr equ 10h ;select printer
selry equ 20h ;select ready
rblft equ 40h ;ribbon lift
;
; status bits
;
chrdy equ 8 ;character ready
xrdy equ 10h ;carriage ready
yrdy equ 20h ;paper feed ready
;
;
; print character in reg c
;
print:
mov a,c ;get char to print to reg a
ani 7fh ;strip parity
mov c,a
lhld nbufad ;and pointer to next buffer address
cpi 13 ;test for special characters
rz ;ignore carriage return
cpi 10
jz plf ;line feed
cpi 12
jz pff ;form feed
inr m ;assume a space
cpi ' '
rz ;was a space, all done
dcr m ;un-do assumption
rc ;was some other control char, ignore
;must be a printable character
mov a,l ;see if buffer is about overflow
cpi low(buf+ncols-2)
rz
cpi low(buf) ;see if this is first character
mov a,m ;get amt to move before printing
jz gotamt ;jump if first character
cpi 81h
jz noblank ;no blanks between last & this char
sui 80h ;subtract flag value
gotamt: ;amount to move in reg a
inx h ;move over number of blanks
db 11h ;lxi trick to skip following mvi a
noblank:
mvi a,1 ;like one blank between character
mov m,c ;store the character comming in
inx h ;point to next buffer location
mvi m,81h ;init to one blank to next char
shld nbufad ;update buffer pointer
lxi h,reolpos ;update right end of line position
add m
mov m,a
ret
;
; print line feed
;
plf:
mov a,l ;see if nbufad = buf
cpi low(buf) ;if = then blank line
jz lfend ;=, so don't print anything
lda leolpos ;get left end of line position
mov b,a ;save it in reg b
lda reolpos ;get right end of line position
add b ;add leolpos to reolpos
rar ;divide by two to find midpoint
mov b,a ;save line center point in reg b
lda hpos ;get current head position
sub b ;hpos-(leolpos+reolpos)/2
jc forward ;middle > hpos
;
; print the buffer backward
;
backward:
mvi a,80h ;put end of buffer marker at left end
sta buf
lda reolpos ;get absolute position of right eol
lxi h,hpos ;compute amount to move to get there
sub m ;reolpos-hpos
lhld nbufad ;get right most character to print
dcx h
bkwd1:
;signed distance to move is now in reg a
call movprt ;move as needed and print a character
dcx h ;point to movement amount
mov a,m ;amount to move to reg a
sui 80h ;test for eob mark
jz lfend ;hit end of line
dcx h ;assume this is a movement
cma ;two's comp for leftward movement
inr a
jnc bkwd1 ;it was, reg a has amount to move
inx h ;it wasn't, fix buffer pointer
mvi a,0ffh ;move one space to the left
jmp bkwd1
;
; print buffer forwards
;
forward:
mvi m,80h ;put in eob mark (also ignores trailing blanks)
lxi h,buf ;pointer into buffer
mov a,m ;absolute pos of leftmost char to reg a
inx h ;point to first printable character
push h ;save buffer pointer
lxi h,hpos ;compute amount to move to get to leolpos
sub m ;leolpos-hpos
pop h ;restore buffer pointer
fwd1:
;signed distance to move is now in reg a
call movprt ;move and print a character
inx h ;point to next character
mov a,m ;get it
sui 80h ;test for end of line
jz lfend ;hit end of line
inx h ;point to character
jnc fwd1 ;was a movement, reg a has distance
dcx h ;was a character, backup pointer
mvi a,1 ;and set amount to move to 1
jmp fwd1 ;go print next character
;
; common finish up routine for print line feed
;
lfend:
lxi h,lfstodo ;add one to line feeds to do before
inr m ;printing next line
jmp init1 ;reset pointers
;
; print a form feed
;
pff:
lda lpp ;get lines per page
lxi h,lonp ;subtract lines printed on this page
sub m ;leaving lines left on this page
sta lfstodo ;which is the number of lfs to do
ret
;
; move the number of character positions in reg a (taken as a
; signed number, + to the right, - to the left) and
; print the character pointed to by reg hl.
;
movprt:
mov c,m ;get character to print
push h ;save while printing
mov e,a ;save amount to move in reg e
movr:
in stats ;wait for all movement to stop
ani chrdy+xrdy+yrdy
jnz movr
lxi h,hpos ;update the head position byte
mov a,e
add m ;add amount we are moving
mov m,a
mvi b,xstb ;ready x strobe for movstb
lda chwid ;load up character muliplicaton factor
call movstb ;send necessary x movement
lda lpp ;lines per page to reg b
mov b,a
lxi h,lfstodo ;number of pending line feeds
mov a,m ;skip movement if zero
ora a
jz noymov ;no y movement
mov e,a ;movement to reg e for movstb
mvi m,0 ;there will be none to do now
lxi h,lonp ;keep track of line on page
add m
mov m,a
sub b ;see if started new page
jc samepage ;nope
mov m,a ;yes - take lonp mod lpp
samepage:
lda linhgt ;load up line multiplicaton factor
mvi b,ystb ;ready y strobe for movstb
call movstb ;send necessary y movement
noymov:
mov e,c ;send character
mvi b,chstb ;send character strobe
mvi a,1 ;dummy multiplication factor
call movstb
pop h
ret
;
; move the signed amount in reg e using value in reg a as
; a mulitplication factor to get the number of increments
; then send strobe in reg b.
;
movstb:
push psw ;save multiplication factor
mov a,e ;form a 16 bit amount to move in reg de
ral ;sign of movement into carry
sbb a ;generate sign extention
mov d,a ;16-bit signed movement now in reg de
pop psw ;get multiplication factor
lxi h,0 ;initialize product
mulbyw: ;multiply
dad d
dcr a
jnz mulbyw ;keep multiplying
mov a,h ;is this leftward movement?
ora a
jp posmov ;no - distance is ok
xra a ;yes - negate distance
sub l ;reg a = 0 - low order
mov l,a ;which is low order compliment
sbb h ;now subtract out high order and
sub l ;subtract out excess low order
;complimented distance now in reg a and reg l
ori 4 ;and set negative motion bit
posmov:
cma ;high order data is active low
out datah ;send high order data
mov a,l ;get low order data
cma ;it too is active low
out datal ;send low order data
;fall thru to strobe
;
; pulse strobe in reg b
;
strobe:
xra a ;delay a while for data set-up time
dlay:
dcr a
jnz dlay
mvi a,0ffh-selpr-rblft-selry
push psw ;save bits which are allways high
sub b ;lower appropriate strobe bit
out cmand ;send strobe bit low
pop psw ;and send it high
out cmand
ret
;
; init for printing
;
init:
mvi b,restr ;pulse restore line to
call strobe ;reset printer
xra a ;set software head position to zero
sta hpos
sta lonp ;reset line counter to top of page
sta lfstodo ;zero out number of line feeds to do
init1: ;empty buffer entry point
xra a ;reset right end of line position
sta reolpos
lxi h,buf ;next buffer address pointer
shld nbufad
mov m,a ;inits left end of line position
ret
;
;
; ram parameter area
;
linhgt db 8 ;line height in increments
chwid db 6 ;character width in increments
lpp db 66 ;lines per page
;
; ram areas
;
lonp ds 1 ;current line on page, 0 = first line
lfstodo ds 1 ;line feeds to do before printing
hpos ds 1
reolpos ds 1
nbufad ds 2
buf:
leolpos: ;address of byte containing left eol
ds 1
lmostch: ;address of left most character
ds ncols
;
end