* * * Word Wizard * SolPrinter 3 Driver * 1.1 (mod 1) * * * * * * Equates * * Conditions * TRUE equ 00001H FALSE equ 00000H * BUSY equ 0FFFFH DONE equ 00000H * * Characters * CHnull equ 000H CHdel equ 07FH CHcr equ 00DH CHlf equ 00AH CHff equ 00CH CHfle equ 001H CHnolf equ 0FFH CHesc equ 01BH CHsp equ 020H CHb equ CHsp CHws equ 07EH * * Control/Status Codes * CSds equ 7 device status request CSwpm equ 100 word processor mode CScps equ 101 cross perfs skip (not supported) CSsps equ 102 set page size CSshi equ 103 set horz. inc. CSsvi equ 104 set vert. inc. CScb equ 105 cancel buffer * * I/O Port Assignments * IOssp - serial status port * IOsdp - serial data port * IOssp equ 0F8H IOsdp equ 0F9H IOsdr equ 002H data set ready (when 0) IOscs equ 020H clear to send (when 0) IOsbe equ 080H transmitter buffer empty (when 1) * * Maximums and Initial Settings * MXvi equ 7 max. vert. inc. IIvi equ 8 number of vert. incs. to make one whole linefeed Ivi equ 8 init. vert. inc. Ipz equ 66 init. page size * * nlst copy NPTDEFS lst * * the program origin * org 07800H * * The Driver Table * DTrb dw 0 no reads DTrnb dw 0 DTrlb dw 0 DTwbr dw wblock write a block of 1 DTwb dw wblock write a block of 1 DTrew dw dummy rewind supported for BASIC DTeof dw eof end-file DTclo dw close the close operation DTsek dw 0 seek not supported DTctl dw ctrl control/status call DTblk dw 1 block size must be 1 !!! DTito db 1 must be 1 !!! DTini dw init dummy ret * * * wblock -- write a block of 1 character * HL = address of block * DE = block size * wblock call tmode word processing mode? jnz wbl2 yes * wbl1 call wait wait for printer task to go DONE jmp wbl3 DONE, send next character * * If in word processing mode, don't wait for input * to go DONE; instead, return to caller. * wbl2 call ti test input status jnz wblret return if status is BUSY (Z flag = 0) * * Get the character and start the printer task * by setting its status to BUSY. * wbl3 mov a,m get character call sib set input BUSY and send character to the next task call task give the printer driver task a chance to run * fall thru * * return to wblock caller * wblret xthl inx h inx h inx h xthl lxi h,0 nothing read ret * * * eof -- write an end-file on the printer * HL = block address * DE = block size * eof call cantst test for cancel rz * call wblock write any residew jmp dummy ignore eof return ret * * * close -- close the printer driver * close mvi a,FALSE sta cancel * call wait * mvi a,CHcr call sib send a cr call wait ret * * * wait - wait for the prinder driver to go DONE * wait call ti test input status rz . return when printer driver goes DONE (Z flag = 1) call task BUSY, give it a chance to go DONE jmp wait keep trying * * * ctrl -- process the Control/Status calls * * CSds -- return: DE=0 ==> printer driver BUSY * DE=1 ==> printer driver DONE * A =1 always * * CSwpm - entry : E =1 ==> word processor mode * E =0 ==> not word processor mode * return: A =1 ==> was in word processor mode * A =0 ==> was not in word processor mode * * CSshi - supported but not effective * * CSsvi - entry : E = new vertical increment in 1/48" * output: A = old increment * * CScb -- cancel the contents of any internal buffers * * CSsps - set page size to value in E * ctrl cpi CSds device status? jnz ctrl1 * call task give the printer task a chance to run call ti test input status jz ctrl0 DONE, indicate so lxi d,0 BUSY, indicate so mvi a,1 ret ctrl0 lxi d,1 DONE mvi a,1 ret ctrl1 equ $ * cpi CSwpm change word processing mode? jnz ctrl2 * lxi h,mode mov a,m get old value mov m,e set new value ret ctrl2 equ $ * cpi CSshi rz . ignored but supported * cpi CSsvi jnz ctrl3 * lxi h,vi mov a,m get old value mov m,e save new value ret . done ctrl3 equ $ * cpi CSsps set page size jnz ctrl4 * mov a,e lxi h,linz mov e,m mov m,a ret ctrl4 equ $ * cpi CScb jnz ctrle error, Control/Status op not supported * mvi a,TRUE sta cancel set cancel flag ret * * * Control/Status op not supported * ctrle call ERRL2 db ERNCT * * * task -- Saves the state of the machine for PTDOS and * restores the state of the machine for the * printer driver. * task push b save state for PTDOS push d push h push psw lxi h,0 dad sp shld ptstk * lhld tskstk restore the machine state for the printer driver sphl pop psw pop h pop d pop b ret . this will take us back to whomever called 'yield' * * * yield -- this saves the state of the machine for the printer * driver and restores the state for PTDOS. * yield push b save machine state for the printer driver push d push h push psw lxi h,0 dad sp shld tskstk * lhld ptstk restore state of the PTDOS execution sphl pop psw pop h pop d pop b ret . this will take us back to the caller of 'task' * * * server -- this is the main loop of the printer driver. It * waits for PTDOS code to set the 'status' semaphore * to the BUSY state indicating the there is a * character ready to be processed. It then processes * the character and sends the proper info to the * printing mechanism. * server mvi a,CHcr send out an initial cr to reset the printer call putc * mvi a,TRUE sta lffg set linefeed flag to TRUE * serv0 call getc get a character from PTDOS * call process process the character * jmp serv0 loop forever * * * process -- This processes the character. Some characters * are not sent to the printer mechanism; they * are handled specially. * A = the character to be processed * process cpi CHcr jnz pro0 * call pcr call to process carriage returns ret pro0 equ $ * cpi CHfle forced line end? jnz pro1 * call tmode check for word processor mode mvi a,CHfle jz pro1 not WPMODE, send character ret . ignore it pro1 equ $ * cpi CHlf rz . ignore linefeeds * cpi CHnolf jnz pro2 * mvi a,FALSE sta lffg set linefeed-after-cr flag to FALSE ret pro2 equ $ * cpi CHnull rz . ignore nulls * cpi CHdel rz . ignore delete characters * cpi CHws jnz pro3 * call tmode mvi a,CHws jz pro3 mvi a,CHb pro3 equ $ * cpi CHff jnz pro4 * call pff ret pro4 equ $ * cpi 32 jnc pro5 * mvi a,'?' translate all other control characters to '?' pro5 equ $ * call putc put the character out to the device * ret . and return * * * pcr -- process a carriage reutrn * pcr mvi a,CHcr call putc output a cr * lda lffg test linefeed-after-cr flag cpi TRUE first set hardware flags mvi a,TRUE the reset the flag to TRUE sta lffg * cz plf process a linefeed if TRUE * ret . all done with the cr * * * process a linefeed * plf lda vi the current vert. inc. per linefeed cpi IIvi = to the number of vert. incs. per real linefeed? jz plf2 yes, print a normal linefeed * * No, simulate a linefeed by commanding the printer to * move in descreet vertical increments * mov c,a get the number of increments into c * plf1 push b send one inc. mvi a,CHesc the escape sequence for descreet increments call putc mvi a,CHlf call putc mvi a,1 move one increment call putc pop b * dcr c one less inc. to go jnz plf1 * plf3 lda line account for the movement to the next line dcr a sta line rnz . page not empty, return lda linz page is empty, ... sta line ...fill it up again * ret * plf2 mvi a,CHlf move the paper one whole linefeed call putc jmp plf3 * * * process a form feed * pff lda line lines in this page mov b,a lda linz lines in a full page cmp b rz . if equal then this is a full page call plf roll off one more line jmp pff * * * getc -- get a character from the PTDOS task * on return: A = the character sent * getc call sid first set input DONE * getc0 call ti test input status jnz getc1 Z flag 1 means DONE, wait for BUSY call yield let the PTDOS task run for a while jmp getc0 * getc1 lda data get the data that was passed ret * * * putc -- put a character out to the printer mechanism * A = the character to be sent * putc push psw save character call cantst jnz putc0 pop psw ret * putc0 call tod test output status jz putc1 Z flag 0 means BUSY, wait until DONE call yield give the PTDOS task a chance to run jmp putc0 * putc1 pop psw get the character ani 07FH mask off parity call sob set output BUSY and send the character * ret * * * cantst - test the cancel flag * cantst lda cancel cpi TRUE ret * * * tmode - test Word Processor mode * set Z if false * tmode mov b,a lda mode ora a mov a,b ret * * * sid -- set input DONE. This sets the input (to the printer * driver) status semaphore to the DONE state. This * indicates to the PTDOS task that the printer driver * is ready to process another character. * sid mvi a,DONE sta status ret * * * sib -- set input BUSY. This sets the input (to the printer * driver) status semaphore to the BUSY state. This * tells the PTDOS task that it cannot send the printer * driver a character. PTDOS code must wait for the * semaphore to go DONE. * A = the character to be sent * sib sta data send the character to the printer driver mvi a,BUSY sta status make the printer driver BUSY ret * * * sob -- set output BUSY. This sets the hardware semaphore * to its BUSY state and starts the printer mechanism * going. There is no software complement (sod-set * output DONE) because the printer hardware does this. * A = the character to be sent * sob out IOsdp send out character ret * * * ti -- test input status. This tests the input (from the * PTDOS task) status for DONE and sets the Z flag * to 1 for DONE, 0 for BUSY. Carry flag is always 0. * ti lda status cpi DONE ret * * * tod -- test output for DONE. This tests the printer * mechanism status semaphore for a DONE condition. * The Z flag is set to 1 if DONE, 0 if not * tod in IOssp read in status port ani IOsbe+IOscs+IOsdr only these bits... cpi IOsbe+0+0 must be thus for a DONE state ret . return Z set if DONE, clear otherwise * * * init -- initialize the driver * init lxi h,server init the server's start addr shld iretadr lxi h,istkptr init the server's stack addr shld tskstk * mvi a,0 set to non-word processor mode sta mode * mvi a,Ipz initial page size sta line set current page size (top of form) sta linz set the size of the next page * mvi a,FALSE sta cancel cancel mode is FALSE * mvi a,DONE set input status to DONE sta status * mvi a,Ivi sta vi set initial vertical increment * call task lastly, initialize the control structure * ret . * * * Storage * status ds 1 printer driver BUSY/DONE semaphore ptstk ds 2 the stack ptr for the PTDOS task tskstk ds 2 the stack ptr for the printer driver task mode ds 1 the driver mode: word processor/non-word processor lffg ds 1 linefeed-after-cr flag data ds 1 the character passing buffer cancel ds 1 cancel state flag vi ds 1 vertical increments per LF * line ds 1 lines left on current page linz ds 1 lines per page * * Stacks * ds 45 stack istkptr ds 8 init tos iretadr ds 2 init addr of ret addr * *