.TITLE TYPER V01.02 .IDENT /V01.02/ ; ; HANDLER FOR SPINWRITER. ; ; ACCEPTS ASCII TEXT, WITH TABS, BACKSPACES, LINE FEEDS, ; CARRIAGE RETURNS, AND FORM FEEDS. TRANSLATES INTO APPROPRIATE ; CHARACTER STREAM WITH EMBEDDED ESCAPE SEQUENCES SO AS TO RUN ; THE SPINWRITER IN BOUSTROPHEDON FASHION. ; HANDSHAKING IS DONE WITH PROTOCOL, DOUBLE BUFFERED. ; ; 'SET' OPTIONS ARE: ; WIDTH LIKE LP WIDTH ; FORM0 LIKE LP FORM0 ; INDENT SETS OFFSET FROM EDGE OF PRINTER TO FIRST PRINTED CHARACTER. ; .MCALL .DRBEG,.DRAST,.DRFIN,.DREND,.QELDF,.FORK ; .MACRO DEBUG .ENDM ; .IIF NDF MMG$T MMG$T = 0 .IIF NDF ERL$G ERL$G = 0 .IIF NDF TIM$IT TIM$IT = 0 ; .IIF NDF VEC VEC = 300 .IIF NDF ADDR ADDR = 175600 ;MPL DL-11 #1 ; TKVEC = VEC ; HARDWARE PARAMETERS TKCSR = ADDR TKBUF = TKCSR + 2 TYVEC = TKVEC + 4 TYCSR = TKCSR + 4 TYBUF = TKBUF + 4 LINLEN = 132. ; LENGTH OF PRINTED LINE TBUFSZ = 125. ; HALF LENGTH OF TYPER'S BUFFER ; ; ASCII CHARACTERS C.ETX= 003 C.BS= 010 C.TAB= 011 C.LF= 012 C.FF= 014 C.CR= 015 C.ESC= 033 C.SPAC= 040 ; ; TYSIZ = 0 ; NON-FILE-STRUCTURED DEVICE SIZE TYSTAT = 20201 ; WRITE-ONLY, DEVICE # 201 .ASECT . = 400 ; 'SET' CODE STARTS HERE ; .WORD 30. ; MINIMUM ACCEPTABLE WIDTH .RAD50 /WIDTH / .WORD /2+40000 ; NUMBER REQUIRED ; .WORD 100000 ; NO FORM0 => 0 FFOPT .RAD50 /FORM0 / .WORD /2+100000 ; ALLOW 'NO' FOR ANSWER ; .WORD 30. ; MINIMUM ACCEPTABLE WIDTH .RAD50 /INDENT/ .WORD /2+40000 ; NUMBER REQUIRED ; .WORD 0 ; END OF TABLE ; O.WIDTH: MOV R0,COLCNT ; SET COLUMN COUNT CMP #LINLEN,R0 BLO 1$ ; TOO BIG SETS CARRY ADD INDENT,R3 CMP R0,R3 ; TOO SMALL SETS CARRY 1$: RTS PC ; O.FORM0: MOVB #C.FF,R3 ; FOR BLOCK 0 MOVB R3,FFOPT RTS PC ; O.INDENT: MOV R0,INDENT ; SET INDENT VALUE ADD R0,R3 CMP COLCNT,R3 ; TOO BIG SETS CARRY RTS PC .QELDF .DRBEG TY,TYVEC,TYSIZ,TYSTAT,VECTBL ; TY: MOV PC,R4 ADD #BUFFER-1-.,R4 ; POINT TO START OF BUFFER MOV R4,BUFPTR ; ABSOLUTELY MOV TYCQE,R4 ASL Q.WCNT-Q.BLKN(R4) ; MAKE USER'S WORD COUNT INTO BYTE COUNT BCS 1$ ; MUST BE NEGATIVE FOR OUTPUT BIS #1,@-(R4) ; WAS POSITIVE, SET HARD ERROR BIT JMP EXIT ; AND LEAVE 1$: TST @R4 ; LOOK AT BLOCK NUMBER BNE 2$ ; NOT BLOCK 0 INC @R4 ; NOT BLOCK 0 AGAIN EITHER MOVB FFOPT,R5 ; SET UP FOR BLOCK 0 MOV INDENT,CHRPOS ; BEGIN AT BEGINNING OF LINE CLR FRSTNB ; WITH NO PRINTING CHAR'S FOUND YET MOV #-1,OUTACK ; WITH NO 'S OUTSTANDING 3$: TSTB @#TKCSR BPL 2$ ; MAKE SURE KEYBOARD IS CLEAR TSTB @#TKBUF ; BY READING IT BR 3$ 2$: FETCH: MOV PC,R4 ADD #SAVREG-.,R4 ; RESTORE REGISTERS MOV -(R4),R0 MOV -(R4),R1 MOV -(R4),R2 MOV -(R4),R3 MOV TYCQE,R4 .IF EQ MMG$T ADD #Q.WCNT-Q.BLKN,R4 ; POINT TO USER'S BYTE COUNT .IFTF CTLCHR: CMPB R5,#C.TAB ; IS IT A TAB? BNE 5$ MOVB #C.SPAC,R5 ; FILL TABS WITH SPACES 1$: CMP R0,COLCNT ; IF ROOM AVAILABLE BGE 2$ JSR PC,PUTBUF ; PUT SPACE IN BUFFER MOV R0,-(SP) SUB INDENT,@SP BIT #7,(SP)+ ; MODULO 8 BNE 1$ 2$: BR GETCHR ; 5$: CMPB R5,#C.CR BEQ MAKLIN CMPB R5,#C.LF BEQ MAKLIN CMPB R5,#C.BS BEQ MAKLIN CMPB R5,#C.FF BEQ MAKLIN ;,,, ; ; ARE TERMINATORS, OTHERS IGNORED .IFT GETCHR: TST @R4 ; ANYTHING LEFT IN USER'S BUFFER? .IFF GETCHR: TST Q.WCNT-Q.BLKN(R4) ; ANYTHING LEFT IN USER'S BUFFER? .IFTF BNE 1$ MOV PC,R4 ADD #SAVREG-.,R4 ; NO, SAVE REGISTERS MOV R0,-(R4) MOV R1,-(R4) MOV R2,-(R4) MOV R3,-(R4) JMP EXIT ; AND GO BACK FOR MORE .IFT 1$: INC @R4 ; COUNT A CHARACTER MOVB @-(R4),R5 ; GET IT INC (R4)+ ; AND POINT TO NEXT .IFF 1$: INC Q.WCNT-Q.BLKN(R4) ; COUNT A CHARACTER JSR PC,@$GTBYT ; GET IT & POINT TO NEXT MOV (SP)+,R5 .ENDC BIC #^C177,R5 ; LOOK AT 7-BIT ASCII CMPB R5,#C.SPAC ; IS IT A PRINTING CHARACTER BLT CTLCHR ; NO, MUST BE CONTROL CMP R0,COLCNT BGE 2$ ; IF THERE'S ROOM JSR PC,PUTBUF ; PUT CHAR IN 2$: BR GETCHR ; AND GO BACK FOR MORE ; PUTBUF: INC R0 ; PUT CHAR INTO NEXT LINE IMAGE LOCATION MOVB R5,0(R0) BUFPTR = .-2 CMPB R5,#C.SPAC BEQ 1$ MOV R0,R2 ; NOT A BLANK, THUS LAST NON-BLANK IS HERE TST R1 BNE 1$ MOV R0,R1 ; ALL BLANKS BEFORE HERE, THUS FIRST NON-BLANK 1$: RTS PC ; ; 'SET' PARAMETERS PUT HERE SO THEY ARE IN THE FIRST ; BLOCK OF THE HANDLER COLCNT: .WORD LINLEN ; WIDTH INDENT: .WORD FFOPT: .WORD C.FF ; IF FORM0, 0 IF NOFORM0 MAKLIN: MOV #1,R3 ; SET DIRECTION = RIGHT MOV R0,CHRPOS ; SAVE CURRENT CHARACTER POSITION MOV R1,R0 ; WHERE IS FIRST NON-BLANK BNE 10$ MOV BUFPTR,R1 ; THERE ARE NO NON-BLANK CHAR'S MOV R1,R2 ; FAKE A NULL LINE BR ENDLIN 10$: ADD R2,R0 ASR R0 ; FIND MIDDLE OF LINE CMP R0,OLDPOS BGE 2$ ; BRANCH IF DIRECTION = RIGHT NEG R3 ; SET DIRECTION LEFT MOV R1,R4 ; SWAP BEGINNING AND END OF LINE MOV R2,R1 MOV R4,R2 2$: ADD R3,R2 ; POSITION AFTER TYPING LAST CHAR. MOV R2,OLDPOS MOV R1,R4 ; PLACE WHERE TYPING BEGINS ADD BUFPTR,R2 ; MAKE ABSOLUTE POINTERS ADD BUFPTR,R1 SUB R3,R1 ; BACK UP BEGINNING POINTER MOV #'=,R0 ADD R3,R0 ; MAKE > FOR RIGHT OR < FOR LEFT MOVB R0,@R1 ; AND PUT IN BUFFER SUB R3,R1 ; BACK UP POINTER AGAIN MOVB #C.ESC,@R1 ; INSERT SUB R3,R1 ; AND BACK UP AGAIN DEC R4 ; GENERATE ABSOLUTE TAB TO BEGINNING MOV R4,R0 BIC #^C37,R0 ; LOW-ORDER 5 BITS BIS #'@,R0 ; MADE INTO ASCII CODE MOVB R0,@R1 ; AND PUT INTO BUFFER SUB R3,R1 ROLB R4 ROLB R4 ROLB R4 ROLB R4 ; ROTATE 5 RIGHT BIC #^C7,R4 ; HIGH-ORDER 3 BITS BIS #'P,R4 ; AGAIN MADE INTO ASCII MOVB R4,@R1 ; AND STUCK AWAY SUB R3,R1 ; ONE MORE CHAR. COMING HERE MOVB #C.ESC,@R1 ; TO START THE WHOLE SEQUENCE OFF ENDLIN: DEBUG MOVB R5,@R2 ; PUT TERMINATOR AT END OF LINE CMPB R5,#C.CR BNE 1$ CLRB @R2 ; DON'T SEND REAL MOV INDENT,CHRPOS ; BUT SYMBOLICALLY RETURN TO LEFT END BR 2$ 1$: CMPB R5,#C.BS BNE 2$ DEC CHRPOS ; SPACES BACKWARD BPL 2$ CLR CHRPOS ; BUT NOT PAST LEFT END OF LINE 2$: CLR FRSTNB ; SEARCH FOR NON-BLANK GOES ON AGAIN MOV R1,CHRPTR ; SET UP TO ACTUALLY PRINT THE LINE SUB R1,R2 ; CHARACTER COUNT -1 BPL 3$ NEG R2 3$: MOV R2,CHRCTR ; POSITIVE CHARACTER COUNT MOV R3,DIRFLG ; SAVE THESE THINGS, INTERRUPTS ARE COMING .ENABL LSB PLOOP: MOV PC,R4 ADD #CHRCTR-.,R4 ;POINT TO CHARACTER COUNTER TST @R4 BPL 1$ ; .FORK TYFBLK JMP FETCH ; GO MAKE ANOTHER LINE IMAGE ; 1$: DEC (R4)+ ; COUNT A CHARACTER DEBUG MOVB @(R4)+,@#TYBUF ; PUT IT OUT ADD @R4,-(R4) ; AND MOVE POINTER BR 2$ ; GO AWAY & WAIT ; .DRAST TY,4,ABORT ; INTERRUPT RETURNS TO HERE CLRB @#TYCSR ; DISABLE INTERRUPT DEC TBUFCT ; SENT ENOUGH CHAR'S TO PRINTER? BNE PLOOP ; NO MOV #TBUFSZ,TBUFCT ; YES, RESET COUNTER MOVB #C.ETX,@#TYBUF ; SEND FOR HANDSHAKE BISB #100,@#TKCSR ; PREPARE TO RECEIVE INC OUTACK ; COUNT ANOTHER OUTSTANDING BNE 3$ ; 2 OUTSTANDING BUFFERS FULL, JUST WAIT 2$: BISB #100,@#TYCSR ; OK TO PROCEED WITH OUTPUT 3$: RTS PC .DSABL LSB ; .DRAST TK,4,ABORT ; RETURNING COMES HERE TSTB @#TKBUF ; CLEAR TK READY, ASSUME IT WAS DEC OUTACK ; ANOTHER CAME BACK BEQ PLOOP ; RESUME SENDING CLRB @#TKCSR ; ALL S ARE BACK, RTS PC ; DO NOTHING ; ABORT: CLRB @#TKCSR ; CLEAR EVERYTHING CLRB @#TYCSR ; EXIT: .DRFIN TY VECTBL: .WORD TKVEC,TKINT-.,340,TYVEC,TYINT-.,340,0 ; .BLKB 5 ; ROOM FOR 3-CHAR & 2-CHAR ESCAPE SEQUENCE BUFFER: .BLKB LINLEN .BLKB 5 ; ESCAPE SEQUENCE, GOING THE OTHER WAY. .EVEN ; ; ;! THESE WORDS TO REMAIN CONTIGUOUS! CHRCTR: .WORD ;! OUTPUT CHARACTER COUNTER CHRPTR: .WORD ;! OUTPUT CHARACTER POINTER DIRFLG: .WORD ;! +1 PRINT TO RIGHT, -1 PRINT TO LEFT ; R3 LASTNB: .WORD ;! POSITION OF LAST "NON-BLANK ; R2 FRSTNB: .WORD ;! POSITION OF FIRST NON-BLANK ; R1 CHRPOS: .WORD ;! CURRENT CHARACTER POSITION ; R0 SAVREG: ;! REGISTERS ARE SAVED HERE, AS USED OLDPOS: .WORD ; LAST PRINTED CHARACTER OF PREVIOUS LINE TBUFCT: .WORD TBUFSZ ; HOW MANY CHAR'S TO SEND TO TYPER AT ONE TIME OUTACK: .WORD -1 ; (NUMBER-1) OF OUTSTANDING 'S ; TYFBLK: .WORD 0,0,0,0 .DREND TY .END