.TITLE PLOTPRIMS - TEKTRONICS LOW LEVEL GRAPHICS PRIMITIVES .IDENT 'PLOP00' ; KEN DEMERS ; UTRC ; OCTOBER 1979 ; THESE ROUTINES ARE LOW LEVEL SYSTEM DEPENDENT ; GRAPHICS I/O ROUTINES. THEY ARE PART OF THE ; UTRC GRAPHICS LIBRARY THAT HAS THE SAME FUNCTIONALITY ; AS THE PDP-6 MEMO-SCOPE PACKAGE. ; PACKAGE REVISIONS ; MARCH 5,1980 - TO SUPPORT BLACK BOX(CAS) CONTROL A & B ; ALL OUTPUT IS PRECEEDED BY A CONTROL Y AND CONTROL A & TERMINATED BY ; A CONTROL Y AND CONTROL B TO ALLOW 2 TERMINALS TO BE CONNECTED TO 1 LINE. ; MARCH 28,1980 - TO ALLOW USER TO SPECIFY THE BAUD RATE OF HIS TERMINAL. ; THIS MINIMIZES WAITS FOR HARDCOPY ETC. IMPLIMENTED BY CALL BAUD(RATE) ; CALLS SUPPORTED: ; CHARACTER OUTPUT ROUTINES: ; CALL BACK(N) MOVES THE CURSOR BACK N SPACES ; CALL BAUD(RATE) INFORMS PACKAGE THE BAUD RATE OF TERMINAL ; CALL BELL(N) RINGS THE CONSOLE BELL N TIMES ADDING APPROPRIATE ; DELAYS FOR A SHORT CONTINUOUS SOUND ; CALL BLKBOX INFORM PLOTPRIMS THAT BLACK BOX IS IN USE ; CALL COPY MAKE A HARDCOPY OF THE SCREEN, DELAYS FUTHER ; OUTPUT ; CALL DOWN(N) MOVES THE CURSOR DOWN N LINES ; CALL ERASE ERASE THE SCREEN, DELAY APPROPRIATELY ; CALL HOME MOVES THE CURSOR TO THE TOP LEFT CORNER OF ; THE SCREEN ; CALL LFEED(N) MOVES THE CURSOR DOWN N LINES ; CALL CHAR(CHAR) OUTPUT THE GIVEN CHARACTER ; CALL UP(N) MOVES THE CURSOR UP N LINES ; MODE SET ROUTINES: ; CALL ALPHA GOES INTO ALPHA MODE AFTER FORCING OUTPUT OF ; REMAINING GRAPHICS ; PLOTTING ROUTINES: ; CALL M$OVCUR(X,Y) MOVE CURSOR ; WHERE: ; X = X COORDINATE TO MOVE CURSOR TO ; Y = Y COORDINATE TO MOVE CURSOR TO ; CALL LINE(X,Y) PLOT LINE FROM CURRENT CURSOR POSITION ; TO X,Y ; WHERE: ; X = NEW X COORDINATE ; Y = NEW Y COORDINATE ; CALL P$OINT(X,Y) PLOT P$OINT FROM CURRENT CURSOR POSITION ; TO X,Y ; WHERE: ; X = NEW X COORDINATE ; Y = NEW Y COORDINATE ; INPUT ROUTINES: ; CALL TINPUT(CHAR) GET A SINGLE CHARACTER, THE CHARACTER ; IS FOLLOWED BY A BLANK ; CALL FCURSE(CHAR,X,Y) GET GRAPHICS CROSS-HAIR POSITION ; CHAR IS AN INTEGER*2 ARGUMENT TO BE FILLED ; WITH THE CHARACTER TYPED TO SEND THE CURSOR. ; POSITION. IT IS FOLLOWED BY A BLANK. ; CALL S$TATUS(X,Y) GET CURRENT GRAPHICS POSITION ; INTENDED ENVIRONMENT ; FOR USE WITHIN FORTRAN ROUTINES, CALLED BY A STANDARD ; FORTRAN CALLING SEQUENCE. AT PRESENT THEY OUTPUT ; AND INPUT ON LOGICAL UNIT 5. I/O IS BUFFERED TO ; PROVIDE BETTER CPU EFFICIENCY (REDUCES FLOOD OF ; QIO REQUESTS). EVENT FLAGS EF.IN & EF.OUT CONTROL ; THIS ACTIVITY. THEY MUST BE DISTINCT AND SHOULD ; NOT CONFLICT WITH EITHER FORTRAN RUN TIME SYSTEM ; FLAGS OR FLAGS USED BY INVOKED ASSEMBLER ROUTINES. ; TERMINAL TYPE: ; THE TERMINAL SUPPORTED BY THIS VERSION IS A TEKTRONICS 4010-1 ; WITH THE FOLLOWING STRAPPING AND SPEED: ; 1. STRAPPING FOR L.CHR CHARS OF CROSS-HAIR DATA(ESC ^Z SEQUENCE) ; 2. STRAPPING FOR L.POS CHARS OF S$TATUS DATA(ESC ^E SEQUENCE) ; 3. SPEED <= 9600 BAUD ; 4. EXACT SPEED EXPRESSED IN MILLISECONDS PER CHARACTER IN "T$M.CHR" ; 5. COPY TIMES, ERASE TIMES, & BELL TIMES CAN BE CHANGED TO FIT ; A TERMINAL WITH DIFFERENT TIMING. (EQUATES TM.***) ; CONDITIONAL ASSEMBLY FOR TEKTRONICS 4025 TK4025=0 .PSECT PLOTPR,RW,I,LCL .MCALL QIO$,QIOSY$,QIOW$,DIR$,WTSE$ QIOSY$ ; INTERNAL GLOBALS .GLOBL .TILUN,.TOLUN,BACK,UP,HOME,ALPHA,C$HAR .GLOBL DOWN,L$FEED,BELL,COPY,ERASE,T$INPUT,F$CURSE .GLOBL X$ITPLT,SCURSR,O$UTLUN,BLKBOX .GLOBL S$TATUS,MVCURI,BAUD,L$INE,P$OINT .GLOBL GTCURI ; EXTERNAL GLOBALS .GLOBL S$AVARG,R$STARG,A$RGB1,A$RG21,USEREX ; ASSIGNMENTS .TILUN = 5 ;INPUT LOGICAL UNIT .TOLUN = 5 ;OUTPUT LOGICAL UNIT(DEFAULT) ;CAN BE CHANGED BY A CALL TO 'SETLUN' EF.IN = 10. ;TTY INPUT EVENT FLG EF.OUT = 11. ;TTY OUTPUT EVENT FLG ; CHARACTER CODES FOR THE 4010: CH.*** CH.NUL = 0 ;NULL CHAR, NO OUTPUT CH.SOH = 1 ;SOH (CONTROL A) CH.STX = 2 ;STX (CONTROL B) CH.EM = 31 ;EM (CONTROL Y) CH.BAK = 10 ;BACKSPACE CH.BEL = 7 ;BELL CH.DWN = 12 ;L$INE FEED CH.UP = 13 ;VERTICAL TAB CH.GRF = 35 ;GO INTO GRAPHIC MODE CH.ALF = 37 ;GO INTO ALPHA MODE CH.PAD = 26 ;PADDING CHAR, DOES NOT AFFECT IN ;PROCESS GRAPHICS CH.HOM = 14 ;GO TO TOP LEFT CORNER OF SCREEN CH.ESC = 33 ;ESCAPE - ENTER CONTROL SEQUENCE ; ESCAPE SEQUENCE CONTROL CHARACTERS: CE.*** CE.CPY = 27 ;MAKE HARD COPY CE.ERS = 14 ;ERASE SCREEN CE.CHR = 32 ;START CROSS-HAIR CURSOR CE.POS = 5 ;RETURN S$TATUS & POSITION L.CHR = 5 ;# OF CHARS OF CROSS-HAIR DATA L.POS = 5 ;# OF CHARS OF S$TATUS DATA ; TIMING CHARACTERISTICS - TIME IN MSECS FOR VARIOUS FUNCTIONS TMCHAR = 32. ;TIME FOR 1 CHAR(300 BAUD) ;T$M.CHR = 4 ;TIME FOR 1 CHAR(2400 BAUD) ;T$M.CHR = 1 ;TIME FOR 1 CHAR(9600 BAUD) TM.CPY = 10000. ;TIME TO MAKE A COPY TM.ERS = 1000. ;TIME TO ERASE SCREEN TM.BEL = 100. ;TIME TO RING BELL LDLYBF = 40. ;# OF PADDING CHARS IN THE DELAY ;OUTPUT BUFFER ; GRAPHICS CONTROL FORMAT USED WHEN SENDING X,Y ; COORDINATES TO THE 4010 CH.LOX = 100 ;FLG FOR LOW X BYTE CH.LOY = 140 ;FLG FOR LOW Y BYTE CH.HIX = 040 ;FLG FOR HI X BYTE CH.HIY = 040 ;FLG FOR HI Y BYTE ; MAXIMUM X & Y VALUES MAX.X = 1023. ;MAX X COORDINATE .IF NDF TK4025 MAX.Y = 780. ;MAX Y COORDINATE .ENDC .IF DF TK4025 MAX.Y = 755. .ENDC ; BACKSPACE N SPACES - CALL BACKSPACE(N) BACK: CALL S$AVARG ;SAVE REGS MOV @2(R5),R4 ;R4= # SPACES TO BACK UP BAC10: MOV #CH.BAK,R0 ;R0= BACKSPACE CHAR CALL DUMP ;DUMP THE BUFFER BAC20: SOB R4,BAC10 ;LOOP UNTIL DONE CALL R$STARG ;RESTORE REGS RETURN ; MOVE CURSER UP N L$INES - CALL UP(N) UP: MOV @2(R5),R4 ;R4= # OF L$INES TO MOVE UP UP10: MOV #CH.UP,R0 ;R0= VERTICAL TAB CALL DUMP ;DUMP THE BUFFER SOB R4,UP10 ;LOOP UNTIL DONE RETURN ; MOVE CURSER DOWN N L$INES - CALL DOWN(N) OR CALL L$FEED(N) L$FEED = . ;SET UP ENTRY P$OINT DOWN: CALL S$AVARG ;SAVE REGS MOV @2(R5),R4 ;R4= # OF L$INES TO MOVE DOWN DOW10: MOV #CH.DWN,R0 ;R0= L$INE FEED CHAR CALL DUMP ;DUMP THE BUFFER SOB R4,DOW10 ;LOOP UNTIL DONE CALL R$STARG ;RESTORE REGS RETURN ; MOVE TO TOP LEFT CORNER OF SCREEN - CALL HOME HOME: MOV #ARGBK1,R5 ;INIT PTR TO ARG BLK CALL MVCURI ;LET MOVE CURSOR ROUTINE PERFORM THE HOME CALL ALPHA ;PUT TERM BACK INTO ALPHA MODE RETURN ; GO TO ALPHAMERIC MODE - CALL ALPHA ALPHA: MOV #CH.ALF,R0 ;R0= ALPHA MODE CHAR(CONTROL SHIFT M) COMOUT: CALL DUMP ;DUMP EXISTING BUFFER RETURN ; WRITE ARBITRARY CHARACTER - CALL C$HAR(CHAR) C$HAR: CALL S$AVARG ;SAVE REGS MOVB @2(R5),R0 ;R0= CHAR PASSED AS AN ARG CALL DUMP ;DUMP EXISTING BUFFER,WRITE CHAR PASSED IN R0 CALL R$STARG ;RESTORE REGS RETURN ; RING THE BELL N TIMES - CALL BELL(N) ; REQUIRES DELAY AFTER TRANSMISSION SO THAT IT IS ; CONTINUOUS BELL: CALL S$AVARG ;SAVE REGS MOV @2(R5),-(SP) ;SAVE # OF TIMES TO RING BELL CLR R4 ;INIT HI ORDER FOR DIVIDE MOV #TM.BEL,R5 ;R5= TIME TO RING BELL IN MSECS DIV T$M.CHR,R4 ;GET # OF NULLS TO PRODUCE OUR DELAY BEL10: MOV #CH.BEL,R0 ;R0= BELL CHAR CALL DUMP ;DUMP THE BUFFER MOV R4,R0 ;R0= DELAY CNT CALL DELAY ;OUTPUT THE TIMING CHARS DEC (SP) ;DONE? BGT BEL10 ;NO TST (SP)+ ;GET RID OF BELL CNT CALL R$STARG ;RESTORE REGS RETURN ; INFORM PACKAGE THAT BLACK BOX IS IN USE BLKBOX: MOVB #1,B$BFLG ;FLG=1= BLACK BOX IS IN USE RETURN ; ROUTINE TO LET USER TELL US HIS BAUD RATE. ; IF THIS ROUTINE IS NOT CALLED 9600 BAUD IS ; ASSUMED. ; CALLING FORMAT: ; CALL BAUD(IRATE) ; WHERE: ; IRATE = BAUD RATE BAUD: CALL S$AVARG ;SAVE REGS MOV #TMCHAR,R0 ;GET TIME TO XFER 1 CHAR AT 300 BAUD IN MSECS CLR R2 ;INIT BAUD TABLE INDEX BAU10: CMP @2(R5),BAUDTB(R2) ;CK USER BAUD RATE WITH TABLE VALUE BLE BAU20 ;BR IF MATCH FOUND ASR R0 ;AS BAUD GO UP,TIME TO XFER CHAR GOES DOWN TST (R2)+ ;BUMP INDEX TST BAUDTB(R2) ;END OF TABLE? BNE BAU10 ;NO BR BAU30 ;LET DEFAULT BAUD RATE REMAIN BAU20: MOV R0,T$M.CHR ;SAVE TIME IN MSEC TO XFER 1 CHAR BAU30: CALL R$STARG ;RESTORE REGS RETURN ; MAKE A HARDCOPY - CALL COPY COPY: MOV #CH.ESC+,R0 ;R0= ESCAPE SEQUENCE FOR COPY CLR R4 ;INIT HI ORDER FOR DIVIDE MOV #TM.CPY,R5 ;R5= TIME TO COPY IN MSECS DIV T$M.CHR,R4 ;GET # OF NULLS TO PRODUCE OUR DELAY MOV R4,-(SP) ;COPY TIME IN CHAR TIME BR OUTDLY ;MAKE A COPY & WAIT ; ERASE THE SCREEN & WAIT - CALL ERASE ERASE: MOV #CH.ESC+,R0 ;ERASE ESCAPE SEQUENCE CLR R4 ;INIT HI ORDER FOR DIVIDE MOV #TM.ERS,R5 ;R5= TIME TO ERASE SCREEN IN MSECS DIV T$M.CHR,R4 ;GET # OF NULLS TO PRODUCE OUR DELAY MOV R4,-(SP) ;ERASE TIME IN CHAR TIME OUTDLY: CALL DUMP ;DUMP EXISTING BUFFER & WRITE CHAR IN R0 MOV (SP)+,R0 ;R0= DELAY CNT IN CHAR TIME CALL DELAY ;OUTPUT THE TIMING CHARS RETURN ; PLACE 1 INCOMING CHAR IN VARIABLE "CHAR" - CALL T$INPUT(CHAR) T$INPUT: MOV #1,R0 ;R0= # OF CHARS TO READ CNT CALL INPUT ;GET CHAR FROM TERMINAL TST (R5)+ ;BUMP R5 PAST # ARGS LOC IN ARG BLK MOV #40*400,@(R5)+ ;START WITH A NULL FOLLOWED BY A SPACE MOVB I$BFR,@-(R5) ;& FILL IN RESULTING CHAR RETURN ; GET CROSS-HAIR POSITION & CHAR TYPED - CALL F$CURSE(CHAR,IX,IY) SCURSR: F$CURSE: TST (R5)+ ;BUMP PTR PAST # ARGS LOC IN ARG BLK MOV #CH.ESC+,R0 ;R0= STRT CROSS-HAIR INPUT MODE ;CHAR CALL DUMP ;DUMP EXISTING BUFFER & WRITE CHAR IN R0 MOV #L.CHR,R0 ;R0= # OF CHARS TO READ CALL INPUT ;GET CHAR TYPED & CROSS HAIR POSITION MOV #I$BFR,R1 ;R1= STRTING ADDR OF INPUT BUFFER MOV #40*400,@(R5)+ ;STRT WITH A NULL FOLLOWED BY A SPACE MOVB (R1)+,@-(R5) ;& STORE THE CHAR TYPED BY THE USER TO ;SEND THE CROSS-HAIR CURSOR DATA, THEN BR STA10 ;USE S$TATUS TO FILL IN X,Y COORDINATES ; GET CURSER POSITION - CALL S$TATUS(X,Y) GTCURI: S$TATUS: MOV #CH.ESC+,R0 ;COMMAND TO REQUEST S$TATUS CALL DUMP ;DUMP EXISTING BUFFER,WRITE CHAR IN R0 MOV #L.POS,R0 ;R0= # CHAR OF POSITION DATA CALL INPUT ;GET THE POSITION DATA MOV #I$BFR+1,R1 ;R1= ADDR OF STRT OF POSITION DATA ; EXTRACT THE X,Y COORDINATES FROM RETURNED COORDINATE DATA ; ENTRY P$OINT USED BY F$CURSE ALSO STA10: CLR R0 ;FLG (=0 WHILE DOING X, -1 FOR Y) TST (R5)+ ;BUMP R5 TO X ARG ADDR STA20: MOVB (R1)+,R2 ;GET HI BYTE OF A COORDINATE BIC #^C37,R2 ;ONLY CONTAINS HI 5 BITS OF 10 BIT # ASH #5,R2 ;GET INTO STANDARD POSITION MOVB (R1)+,R3 ;GET 2ND BYTE OF A COORD S$TATUS (LOW ;5 BITS ARE DATA) BIC #^C37,R3 ;MASK OUT GARBAGE BIS R3,R2 ;CREATE FULL 10 BIT COORD MOV R2,@(R5)+ ;STORE THE X VALUE(1ST) OR Y(2ND TIME) COM R0 ;HAVE WE DONE Y YET? BNE STA20 ;NO RETURN ; SUBROUTINE TO GET A SPECIFIED # OF CHARACTERS INPUT ; FROM THE TERMINAL. ; INPUT: R0 = # OF CHARACTERS TO INPUT ; OUTPUT: I$BFR IS THE BUFFER CONTAINING THE RESULT ;(READ IN IMAGE MODE). ; NO ERRORS MAY OCCUR INPUT: MOV R0,REDQIO+Q.IOPL+2 ;STORE LENGTH OF READ DIR$ #REDQIO ;READ INPUT RETURN ; ON ENTRY: ; R0= # OF CHARACTERS TO BE OUTPUT AS PADDING ; NO ERRORS MAY OCCUR ; R0 IS NOT SAVED DELAY: MOV #LDLYBF,WRTQIO+Q.IOPL+2 ;SET LENGTH MOV #DLYBFR,WRTQIO+Q.IOPL ;SET ADDR OF PADDING CHARS DEL10: CMP R0,#LDLYBF ;LESS THAN 1 COMPLETE BUFFER TO GO? BLO DEL30 ;YES TSTB O$STAT ;OUTPUT IN PROGRESS? BNE DEL20 ;NO DIR$ #WATWRT ;WAIT FOR ANY OTHER OUTPUT TO COMPLETE DEL20: CALL WRITEQ ;WRITE A FULL PADDING BUFFER SUB #LDLYBF,R0 ;ADJUST CNT BR DEL10 DEL30: MOV R0,WRTQIO+Q.IOPL+2 ;WRITE 1 FINAL SHORT BUFFER BEQ DEL50 ;NOT NEEDED,WE'RE DONE TSTB O$STAT ;OUTPUT IN PROGRESS? BNE DEL40 ;NO DIR$ #WATWRT ;WAIT FOR ANY OTHER OUTPUT TO COMPLETE DEL40: CALL WRITEQ ;WRITE IT DEL50: RETURN ; BASIC GRAPHIC OUTPUT FOR 4010 ; MVCURI - ROUTINE TO MOVE CURSOR ; CALLING FORMAT: ; CALL MVCURI(IX,IY) ; WHERE: ; IX = NEW X COORDINATE ; IY = NEW Y COORDINATE MVCURI: CALL S$AVARG ;SAVE REGS CLR R4 ;MODE = 0 = MOVE CURSOR BR GEN10 ;GO TO GENERALIZED PLOT ROUTINE ; L$INE - ROUTINE TO PLOT A L$INE ; CALLING FORMAT: ; CALL L$INE(X,Y) ; WHERE: ; X = NEW X COORDINATE ; Y = NEW Y COORDINATE L$INE: CALL S$AVARG ;SAVE REGS MOV #1,R4 ;MODE > 0 = PLOT A L$INE BR GEN10 ;GO TO GENERALIZED PLOT ROUTINE ; P$OINT - ROUTINE TO PLOT A P$OINT ; CALLING FORMAT: ; CALL P$OINT(X,Y) ; WHERE: ; X = NEW X COORDINATE ; Y = NEW Y COORDINATE P$OINT: CALL S$AVARG ;SAVE REGS MOV #-1,R4 ;MODE < 0 = PLOT A P$OINT BR GEN10 ;GO TO GENERALIZED PLOT ROUTINE ; GENERALIZED PLOT SUPPORT FOT M$OVCUR,L$INE,P$OINT ; FUNCTION PERFORMED IS DEPENDENT ON THE SIGN OF MODE ; MODE = 0 INITIALIZES CURSER TO X,Y ; MODE > 0 DRAWS A VECTOR FROM THE CURRENT CURSER ; POSITION TO THE GIVEN COORDINATES ; MODE < 0 DRAWS A P$OINT AT X,Y ; GRAPHICS MODE IS EXITED BY A CALL TO SUBROUTINE 'ALPHA' ; THIS SUBROUTINE COLLECTS THE DATA FROM SUCCESSIVE CALLS ; WHICH HAVE STORED THE DATA IN F$DATA. THE ORDER OF ENTRIES ; IN THIS BUFFER IS THE SAME AS THE ORDER IN WHICH SUCCESSIVE ; CALLS PLACED THEM. WHEN THE BUFFER IS FULL OR ANOTHER OUTPUT ; SUBROUTINE IS CALLED, THE BUFFER IS FORMATTED FOR OUTPUT ; (BY DUMP) AND PRINTED. GEN10: TST (R5)+ ;BUMP PTR PAST # ARG LOC IN ARG BLK MOV F$POS,R0 ;R0= A(CURRENT BUFFER POSITION) MOV R4,(R0)+ ;STORE MODE IN BUFFER MOV @(R5)+,(R0)+ ;STORE X IN BUFFER MOV @(R5)+,(R0)+ ;STORE Y IN BUFFER MOV R0,F$POS ;UPDATE BUFFER P$OINTER CMP R0,#E$FDATA ;END OF BUFFER? BLO GEN20 ;NO CLR R0 ;R0=0= NO CHARS CALL DUMP ;DUMP BUFFER NOW GEN20: CALL R$STARG ;RESTORE REGS RETURN ; THIS SUBROUTINE DUMPS THE M$OVCUR,L$INE OR P$OINT DATA BUFFER. THE ; BUFFER IS DUMPED WHEN 1. M$OVCUR,L$INE OR P$OINT BUFFER IS FULL OR ; 2. AN OTHER CHARACTER IS OUTPUT WHICH FORCES THE ; OUTPUT OF THE M$OVCUR,L$INE OR P$OINT BUFFER. ; ON ENTRY: ; R0 = CHARACTER OR 2 CHARS TO FOLLOW THE PLOT MODE DATA ; (ZERO IF NONE) ; F$POS = ADDRESS WITHIN M$OVCUR,L$INE, OR P$OINT BUFFER TO DUMP ; F$DATA = ADDRESS OF START OF M$OVCUR,L$INE, OR P$OINT DATA ; ON EXIT: ; R0-R3 ALTERED ; OUTPUT IN PROGRESS BUT NOT COMPLETE ; NOTES: ; O$UTBF MUST BE LARGE ENOUGH TO HOLD ANY POSSIBLE ; CHARACTER SEQUENCE THAT COULD BE GENERATED BY THE ; VECTORS BECAUSE THERE IS NO BOUNDS CHECK. THERE CAN ; BE A MAXIMUM OF 6 CHARACTERS OF OUTPUT PER M$OVCUR,L$INE ; OR P$OINT CALL AND TWO CHARACTERS MAY FOLLOW IT. DUMP: MOV #O$UTBF,R1 ;P$OINT TO 1ST CHAR OF OUTPUT BUFFER MOV R0,-(SP) ;SAVE POTENTIAL CHAR TO APPEND MOV #F$DATA,R0 ;R0= STRT OF M$OVCUR,L$INE,OR P$OINT DATA TSTB O$STAT ;OUTPUT IN PROGRESS? BNE DUM10 ;NO DIR$ #WATWRT ;WAIT FOR PREVIOUS OUTPUT TO FINISH DUM10: CMP R0,F$POS ;IS BUFFER EMPTY? BEQ DUM60 ;YES,SKIP VECTOR FORMATTING MOV #-1,L$ASTY ;ASSUME THE CURSOR ISN'T POSITIONED ;AT THE LAST POSITION MOVB #-1,L$STHX ;SAME WITH X POSITION CLR @F$POS ;MARK END OF DATA WITH A MODE ZERO PLOT CODE ; THIS LOOP PROCESSES THE DIFFERENT PLOT MODES DUM30: TST (R0)+ ;MODE ZERO? BGT DUM50 ;VECTOR MODE BLT DUM40 ;P$OINT PLOT MODE ; MODE ZERO CMP R0,F$POS ;ANY DATA? BHIS DUM60 ;NO,EXIT LOOP ; MODE ZERO - SET NEW X,Y COORDINATE MOVB #CH.GRF,(R1)+ ;MOVE BEAM Z OFF CALL OUTXY ;OUTPUT THE X,Y COORDINATES BR DUM30 ;& TRY FOR MORE ; P$OINT PLOT MODE - (MODE < 0) ; SIMULATED BY DRAWING A L$INE FROM (X,Y) TO (X,Y) DUM40: MOVB #CH.GRF,(R1)+ ;SET NEW STARTING X,Y CALL OUTXY ;OUTPUT THE X,Y COORDINATES DEC R1 ;BACK OUTPUT PTR MOVB (R1)+,(R1)+ ;& REPEAT THE FINAL COORDINATE(LO X) BR DUM30 ;& TRY FOR MORE ; VECTOR PLOT MODE - SIMPLE VERSION DUM50: CALL OUTXY ;OUTPUT THE X,Y COORDINATES BR DUM30 ;& TRY FOR MORE ; END OF PLOT DATA REACHED - WRITE OUT THE BUFFER DUM60: MOV (SP)+,R0 ;RESTORE SAVED CHARACTERS TO OUTPUT ;FOLLOWING THE VECTORS BEQ DUM70 ;NONE MOVB R0,(R1)+ ;STORE THE 1ST CHAR SWAB R0 TSTB R0 ;IS THERE ANOTHER? BEQ DUM70 ;NO MOVB R0,(R1)+ ;STORE NEXT CHAR DUM70: TSTB B$BFLG ;IS BLACK BOX IN USE? BEQ DUM75 ;NO MOVB #CH.EM,(R1)+ ;APPEND CNTRL Y TO BUFFER MOVB #CH.STX,(R1)+ ;APPEND CNTRL B TO BUFFER MOV #O$UTBUF,R2 ;R2= START OF BUFF ADDR INCLUDING 2 CNTRL CHARS BR DUM77 DUM75: MOV #O$UTBF,R2 ;R2= START OF BUFFER ADDRESS(NO CNTRL A) DUM77: SUB R2,R1 ;CALCULATE LENGTH OF BUFFER MOV R2,WRTQIO+Q.IOPL ;STORE ADDR OF OUTPUT BUFFER FOR QIO MOV R1,WRTQIO+Q.IOPL+2 ;STORE LENGTH " " CALL WRITEQ ;OUTPUT BUFFER MOV #F$DATA,F$POS ;RE-INIT PLOT P$OINTER RETURN ; THIS ROUTINE IS USED TO OUTPUT X AND Y COORDINATES TO THE ; 4010. IT TAKES ADVANTAGE OF THE CAPABILITY OF THE 4010 TO ; RETAIN PREVIOUS X,Y COORDINATES WHICH HAVE BEEN OUTPUT. ; THE ALGORITHM FOR DETERMINING WHICH COORDINATES MUST BE ; OUTPUT IS AS FOLLOWS: ; HIGH Y IF CHANGED ; LOW Y IF CHANGED OR HIGH X IS CHANGED ; HIGH X IF CHANGED ; LOW X ALWAYS OUTPUT, CAUSES THE OPERATION TO TAKE PLACE ; THE COORDINATES ARE OUTPUT IN 5 BIT SEGMENTS. EACH COORDINATE ; IS 10 BITS AND THEY ARE OUTPUT IN THE ORDER HI Y, LOW Y, HI X, ; LOW X. ; ON ENTRY: ; R0= P$OINTER TO X THEN Y ; R1= P$OINTER TO OUTPUT POSITION ; ON EXIT: ; R0= ENTRY POSITION + 4 ; R1= NEW OUTPUT POSITION ; REGISTERS R2 THROUGH R4 ARE ALTERED ; ASSUMPTIONS: ; NO BOUNDS CHECK ARE MADE ON R1 ; X AND Y HAVE NOT BEEN CHECKED BEING WITHIN SCREEN DIMENSIONS ; THEY ARE FORCED TO THE EXTREME VALUE IF OUT OF RANGE ; REGISTER USAGE: ; R0 INPUT PTR ; R1 OUTPUT PTR ; R2 HIGH X ; R3 HIGH Y OR LOW X ; R4 LOW Y ; R5 CONSTANT "^C<37>" USED TO MASK 5 BITS FOR XMISSION TO 4010 OUTXY: MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 MOV #^C<37>,R5 ;INIT MASK MOV (R0)+,R2 ;GET 10 BIT X CMP R2,#MAX.X ;DOES X EXCEED SCREEN SIZE? BLOS OUT20 ;NO BGT OUT10 ;X>MAX.X FORCE X=MAX.X CLR R2 ;X<0 FORCE X=0 BR OUT20 OUT10: MOV #MAX.X,R2 ;X=MAX.X OUT20: MOV (R0)+,R3 ;R3= 10 BIT Y CMP R3,#MAX.Y ;DOES Y EXCEED SCREEN DIMENSIONS? BLOS OUT40 ;NO BGT OUT30 ;Y>MAX.Y CLR R3 ;Y<0 FORCE Y=0 BR OUT40 OUT30: MOV #MAX.Y,R3 ;FORCE Y=MAX.Y OUT40: MOV R3,R4 ;R4= Y BIC R5,R4 ;R4= LOW Y ASH #-5,R3 BIC R5,R3 ;R3= HIGH Y CMPB R3,L$STHY ;HAS HI Y CHANGED? BEQ OUT50 ;NO,THEN IT DOESN'T NEED TO BE RE-OUTPUT MOVB R3,L$STHY ;SAVE NEW LAST HIGH Y BIS #CH.HIY,R3 ;FLG IT SO 4010 CAN DETERMINE TYPE MOVB R3,(R1)+ ;ADD IT TO THE OUTPUT BUFFER OUT50: MOV R2,R3 ;R3= LOW X ASH #-5,R2 ;GET HIGH X BIC R5,R2 ;MASK OUT GARB BIC R5,R3 ;MASK OUT GARB OF LOW X ; WE MUST SEND LOW Y IF HIGH X HAS CHANGED CMPB R2,L$STHX ;HAS HI X CHANGED? BNE OUT60 ;YES CMPB R4,L$STLY ;HAS LOW Y CHANGED? BEQ OUT70 ;NO,SKIP LOW Y OUTPUT OUT60: MOVB R4,L$STLY ;SAVE NEW LOW Y BIS #CH.LOY,R4 ;FLG IT MOVB R4,(R1)+ ;ADD IT TO OUTPUT BUFFER OUT70: CMPB R2,L$STHX ;HAS HIGH X CHANGED? BEQ OUT80 ;NO MOVB R2,L$STHX ;SAVE NEW HIGH X BIS #CH.HIX,R2 ;FLG HI X MOVB R2,(R1)+ ;ADD IT TO OUTPUT BUFFER OUT80: BIS #CH.LOX,R3 ;FLG LO X,WHICH IS ALWAYS SENT MOVB R3,(R1)+ ;ADD IT TO OUTPUT BUFFER MOV (SP)+,R5 ;RESTORE R5 MOV (SP)+,R4 ;RESTORE R4 RETURN ; ROUTINE TO ISSUE A WRITE QIO USING THE WRTQIO DPB WRITEQ: TSTB O$STAT ;I/O IN PROGRESS? BNE WRI10 ;NO DIR$ #WATWRT ;WAIT FOR IT TO FINISH CLR O$STAT ;FLG=0= OUTPUT QIO IN PROGRESS WRI10: DIR$ #WRTQIO ;WRITE THE BUFFER TSTB X$ITFLG ;HAVE WE TOLD FORTRAN OF X$ITPLT YET? BNE WRI20 ;YES MOV R5,-(SP) ;SAVE R5 MOV #ARGBLK,R5 ;SET UP ARG BLK CALL USEREX ;TELL FORTRAN OF OUR EXIT ROUTINE MOV (SP)+,R5 ;RESTORE R5 INCB X$ITFLG ;FLG=1= USEREX HAS BEEN CALLED WRI20: RETURN ; THE FOLLOWING ROUTINE IS GIVEN CONTROL WHEN ; THE USER ISSUES A CALL EXIT FROM FORTRAN. X$ITPLT: CALL ALPHA ;PUT SCOPE BACK IN ALPHA MODE TSTB O$STAT ;DO WE HAVE A PENDING OUTPUT QIO? BNE XIT10 ;NO DIR$ #WATWRT ;WAIT FOR OUTPUT QIO TO FINISH XIT10: RETURN ; WRITE VIRTUAL BLK WITH WRITE PASS ALL QIO DPB WRTQIO: QIO$ IO.WVB!TF.WAL.,.TOLUN,EF.OUT,,O$STAT,,<0,0,0> O$UTLUN = WRTQIO + Q.IOLU ;ADDRESS OF LUN IN WRTQIO DPB. WATWRT: WTSE$ EF.OUT ;DPB TO WAIT FOR WRITE QIO TO COMPLETE ; USEREX FORTRAN ARG BLK ARGBLK: .BYTE 1,0 ;# ARGS,NOT USED .WORD X$ITPLT ;PTR TO OUR EXIT ROUTINE ; ARG BLK TO LET HOME EXECUTE A MOVE CURSOR CALL ARGBK1: .WORD 2 ;THIS ARG BLK ALLOWS MVCURI TO PERFORM A HOME OPERATION .WORD ARG1 .WORD ARG2 ARG1: .WORD 0 ;X HOME POSITION ARG2: .WORD 767. ;Y HOME POSITION ; IMAGE NON-ECHO READ TTY QIO DPB (TO GET CURSOR S$TATUS, CROSS HAIR...) REDQIO: QIOW$ IO.RNE!IO.RNC,.TILUN,EF.IN,,I$STAT,, ; BUFFER OF PADDING CHARACTERS USED TO PREVENT FUTHER ; OUTPUT AFTER A TIME CONSUMING SPECIAL FUNCTION FOR ; THE 4010. DLYBFR: .REPT LDLYBF .BYTE CH.PAD ;PADDING CHARACTER .ENDR ; TABLE OF ALLOWABLE BAUD RATES THAT ; THE USER'S SCOPE MAY RUN AT. ; THE BAUD RATE DETERMINES HOW MANY NULLS ; SFGL70 SENDS TO THE SCOPE TO PRODUCE A DELAY BAUDTB: .WORD 300.,600.,1200.,2400.,4800.,9600.,0 .END