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 >
Assembly Source File  |  1984-04-29  |  9KB  |  328 lines

  1. ;
  2. ; TITLE        BI-DIRECTIONAL DIABLO PRINTER DRIVER
  3. ; FILENAME    BIDI.LIB
  4. ; AUTHOR    Robert A. Van Valzah   9/30/79
  5. ; LAST REVISOR    R.A.V.  11/10/79
  6. ; REASON    byte squeezing
  7. ;
  8. ; plan of attack:
  9. ; ===============
  10. ; characters come in one at a time and are stored into
  11. ; a buffer until a line feed comes in.  at this point,
  12. ; the line in the buffer is analized and a decision is
  13. ; made to print it forward or backward so as to mininmize
  14. ; the head movement.
  15. ;
  16. ; the gory details:
  17. ; =================
  18. ; characters which are printable are just stored in the
  19. ; buffer.  blanks, on the other hand, are accumulated
  20. ; and the number of blanks to move is stored with a bias
  21. ; of 80h.  the first byte of the buffer is an exception:
  22. ; it is initialized to 0h and is used to accumulate the
  23. ; number of spaces between the left margin and the first
  24. ; printable character (this is the location leolpos).
  25. ; the position of the rightmost printable character is
  26. ; keep track of as characters come in the location reolpos.
  27. ;
  28. ; as the head is moved across the page, its position is
  29. ; recorded in hpos.  this information is used in
  30. ; conjunction with leolpos and reolpos to determine if
  31. ; printing forward or backward will cause the shortest
  32. ; printhead movement.  if the printhead is currently to
  33. ; the left of the centerpoint of the line, then it is
  34. ; shortest to move to the left end and start printing.
  35. ; otherwise, it is shortest to move to the right end
  36. ; and print backward.  if the printhead is exactly at
  37. ; the midpoint, the line is printed backward so as to
  38. ; leave the printhead as close to the left margin
  39. ; as possible.
  40. ;
  41. ;
  42. ;    port i/o number equates
  43. ;
  44. base    equ    0f4h
  45. datal    equ    base
  46. datah    equ    base+1
  47. cmand    equ    base+2
  48. stats    equ    base
  49. ;
  50. ;    print formatting equates
  51. ;
  52. ncols    equ    120    ;max number of cols/line (must be <=126)
  53. ;
  54. ;    command bits
  55. ;
  56. restr    equ    1    ;restore carriage
  57. chstb    equ    2    ;character strobe
  58. xstb    equ    4    ;carriage strobe
  59. ystb    equ    8    ;paper feed strobe
  60. selpr    equ    10h    ;select printer
  61. selry    equ    20h    ;select ready
  62. rblft    equ    40h    ;ribbon lift
  63. ;
  64. ;    status bits
  65. ;
  66. chrdy    equ    8    ;character ready
  67. xrdy    equ    10h    ;carriage ready
  68. yrdy    equ    20h    ;paper feed ready
  69. ;
  70. ;
  71. ; print character in reg c
  72. ;
  73. print:
  74.     mov    a,c    ;get char to print to reg a
  75.     ani    7fh    ;strip parity
  76.     mov    c,a
  77.     lhld    nbufad    ;and pointer to next buffer address
  78.     cpi    13    ;test for special characters
  79.     rz        ;ignore carriage return
  80.     cpi    10
  81.     jz    plf    ;line feed
  82.     cpi    12
  83.     jz    pff    ;form feed
  84.     inr    m    ;assume a space
  85.     cpi    ' '
  86.     rz        ;was a space, all done
  87.     dcr    m    ;un-do assumption
  88.     rc        ;was some other control char, ignore
  89.     ;must be a printable character
  90.     mov    a,l    ;see if buffer is about overflow
  91.     cpi    low(buf+ncols-2)
  92.     rz
  93.     cpi    low(buf) ;see if this is first character
  94.     mov    a,m    ;get amt to move before printing
  95.     jz    gotamt    ;jump if first character
  96.     cpi    81h
  97.     jz    noblank    ;no blanks between last & this char
  98.     sui    80h    ;subtract flag value
  99. gotamt:    ;amount to move in reg a
  100.     inx    h    ;move over number of blanks
  101.     db    11h    ;lxi trick to skip following mvi a
  102. noblank:
  103.     mvi    a,1    ;like one blank between character
  104.     mov    m,c    ;store the character comming in
  105.     inx    h    ;point to next buffer location
  106.     mvi    m,81h    ;init to one blank to next char
  107.     shld    nbufad    ;update buffer pointer
  108.     lxi    h,reolpos ;update right end of line position
  109.     add    m
  110.     mov    m,a
  111.     ret
  112. ;
  113. ; print line feed
  114. ;
  115. plf:
  116.     mov    a,l    ;see if nbufad = buf
  117.     cpi    low(buf) ;if = then blank line
  118.     jz    lfend    ;=, so don't print anything
  119.     lda    leolpos    ;get left end of line position
  120.     mov    b,a    ;save it in reg b
  121.     lda    reolpos    ;get right end of line position
  122.     add    b    ;add leolpos to reolpos
  123.     rar        ;divide by two to find midpoint
  124.     mov    b,a    ;save line center point in reg b
  125.     lda    hpos    ;get current head position
  126.     sub    b    ;hpos-(leolpos+reolpos)/2
  127.     jc    forward    ;middle > hpos
  128. ;
  129. ; print the buffer backward
  130. ;
  131. backward:
  132.     mvi    a,80h    ;put end of buffer marker at left end
  133.     sta    buf
  134.     lda    reolpos    ;get absolute position of right eol
  135.     lxi    h,hpos    ;compute amount to move to get there
  136.     sub    m    ;reolpos-hpos
  137.     lhld    nbufad    ;get right most character to print
  138.     dcx    h
  139. bkwd1:
  140.     ;signed distance to move is now in reg a
  141.     call    movprt    ;move as needed and print a character
  142.     dcx    h    ;point to movement amount
  143.     mov    a,m    ;amount to move to reg a
  144.     sui    80h    ;test for eob mark
  145.     jz    lfend    ;hit end of line
  146.     dcx    h    ;assume this is a movement
  147.     cma        ;two's comp for leftward movement
  148.     inr    a
  149.     jnc    bkwd1    ;it was, reg a has amount to move
  150.     inx    h    ;it wasn't, fix buffer pointer
  151.     mvi    a,0ffh    ;move one space to the left
  152.     jmp    bkwd1
  153. ;
  154. ; print buffer forwards
  155. ;
  156. forward:
  157.     mvi    m,80h    ;put in eob mark (also ignores trailing blanks)
  158.     lxi    h,buf    ;pointer into buffer
  159.     mov    a,m    ;absolute pos of leftmost char to reg a
  160.     inx    h    ;point to first printable character
  161.     push    h    ;save buffer pointer
  162.     lxi    h,hpos    ;compute amount to move to get to leolpos
  163.     sub    m    ;leolpos-hpos
  164.     pop    h    ;restore buffer pointer
  165. fwd1:
  166.     ;signed distance to move is now in reg a
  167.     call    movprt    ;move and print a character
  168.     inx    h    ;point to next character
  169.     mov    a,m    ;get it
  170.     sui    80h    ;test for end of line
  171.     jz    lfend    ;hit end of line
  172.     inx    h    ;point to character
  173.     jnc    fwd1    ;was a movement, reg a has distance
  174.     dcx    h    ;was a character, backup pointer
  175.     mvi    a,1    ;and set amount to move to 1
  176.     jmp    fwd1    ;go print next character
  177. ;
  178. ; common finish up routine for print line feed
  179. ;
  180. lfend:
  181.     lxi    h,lfstodo ;add one to line feeds to do before
  182.     inr    m    ;printing next line
  183.     jmp    init1    ;reset pointers
  184. ;
  185. ; print a form feed
  186. ;
  187. pff:
  188.     lda    lpp    ;get lines per page
  189.     lxi    h,lonp    ;subtract lines printed on this page
  190.     sub    m    ;leaving lines left on this page
  191.     sta    lfstodo    ;which is the number of lfs to do
  192.     ret
  193. ;
  194. ; move the number of character positions in reg a (taken as a
  195. ; signed number, + to the right, - to the left) and
  196. ; print the character pointed to by reg hl.
  197. ;
  198. movprt:
  199.     mov    c,m    ;get character to print
  200.     push    h    ;save while printing
  201.     mov    e,a    ;save amount to move in reg e
  202. movr:
  203.     in    stats    ;wait for all movement to stop
  204.     ani    chrdy+xrdy+yrdy
  205.     jnz    movr
  206.     lxi    h,hpos    ;update the head position byte
  207.     mov    a,e
  208.     add    m    ;add amount we are moving
  209.     mov    m,a
  210.     mvi    b,xstb    ;ready x strobe for movstb
  211.     lda    chwid    ;load up character muliplicaton factor
  212.     call    movstb    ;send necessary x movement
  213.     lda    lpp    ;lines per page to reg b
  214.     mov    b,a
  215.     lxi    h,lfstodo ;number of pending line feeds
  216.     mov    a,m    ;skip movement if zero
  217.     ora    a
  218.     jz    noymov    ;no y movement
  219.     mov    e,a    ;movement to reg e for movstb
  220.     mvi    m,0    ;there will be none to do now
  221.     lxi    h,lonp    ;keep track of line on page
  222.     add    m
  223.     mov    m,a
  224.     sub    b    ;see if started new page
  225.     jc    samepage ;nope
  226.     mov    m,a    ;yes - take lonp mod lpp
  227. samepage:
  228.     lda    linhgt    ;load up line multiplicaton factor
  229.     mvi    b,ystb    ;ready y strobe for movstb
  230.     call    movstb    ;send necessary y movement
  231. noymov:
  232.     mov    e,c    ;send character
  233.     mvi    b,chstb    ;send character strobe
  234.     mvi    a,1    ;dummy multiplication factor
  235.     call    movstb
  236.     pop    h
  237.     ret
  238. ;
  239. ; move the signed amount in reg e using value in reg a as
  240. ; a mulitplication factor to get the number of increments
  241. ; then send strobe in reg b.
  242. ;
  243. movstb:
  244.     push    psw    ;save multiplication factor
  245.     mov    a,e    ;form a 16 bit amount to move in reg de
  246.     ral        ;sign of movement into carry
  247.     sbb    a    ;generate sign extention
  248.     mov    d,a    ;16-bit signed movement now in reg de
  249.     pop    psw    ;get multiplication factor
  250.     lxi    h,0    ;initialize product
  251. mulbyw:            ;multiply
  252.     dad    d
  253.     dcr    a
  254.     jnz    mulbyw    ;keep multiplying
  255.     mov    a,h    ;is this leftward movement?
  256.     ora    a
  257.     jp    posmov    ;no - distance is ok
  258.     xra    a    ;yes - negate distance
  259.     sub    l    ;reg a = 0 - low order
  260.     mov    l,a    ;which is low order compliment
  261.     sbb    h    ;now subtract out high order and
  262.     sub    l    ;subtract out excess low order
  263.     ;complimented distance now in reg a and reg l
  264.     ori    4    ;and set negative motion bit
  265. posmov:
  266.     cma        ;high order data is active low
  267.     out    datah    ;send high order data
  268.     mov    a,l    ;get low order data
  269.     cma        ;it too is active low
  270.     out    datal    ;send low  order data
  271.             ;fall thru to strobe
  272. ;
  273. ; pulse strobe in reg b
  274. ;
  275. strobe:
  276.     xra    a    ;delay a while for data set-up time
  277. dlay:
  278.     dcr    a
  279.     jnz    dlay
  280.     mvi    a,0ffh-selpr-rblft-selry
  281.     push    psw    ;save bits which are allways high
  282.     sub    b    ;lower appropriate strobe bit
  283.     out    cmand    ;send strobe bit low
  284.     pop    psw    ;and send it high
  285.     out    cmand
  286.     ret
  287. ;
  288. ; init for printing
  289. ;
  290. init:
  291.     mvi    b,restr    ;pulse restore line to
  292.     call    strobe    ;reset printer
  293.     xra    a    ;set software head position to zero
  294.     sta    hpos
  295.     sta    lonp    ;reset line counter to top of page
  296.     sta    lfstodo    ;zero out number of line feeds to do
  297. init1:    ;empty buffer entry point
  298.     xra    a    ;reset right end of line position
  299.     sta    reolpos
  300.     lxi    h,buf    ;next buffer address pointer
  301.     shld    nbufad
  302.     mov    m,a    ;inits left end of line position
  303.     ret
  304. ;
  305. ;
  306. ;    ram parameter area
  307. ;
  308. linhgt    db    8    ;line height in increments
  309. chwid    db    6    ;character width in increments
  310. lpp    db    66    ;lines per page
  311. ;
  312. ;    ram areas
  313. ;
  314. lonp    ds    1    ;current line on page, 0 = first line
  315. lfstodo    ds    1    ;line feeds to do before printing
  316. hpos    ds    1
  317. reolpos    ds    1
  318. nbufad    ds    2
  319. buf:
  320. leolpos:        ;address of byte containing left eol
  321.     ds    1
  322. lmostch:        ;address of left most character
  323.     ds    ncols
  324. ;
  325.     end
  326.  
  327.