! EDWIN driver for the PRINTRONIX 300 Matrix printer ! JGH November 1980 %external %integer %spec VIEWING %external %integer %spec DEVICE %external %routine %spec TTPUT (%integer I) %external %string(255) %spec BUFF %external %routine %spec FLUSH OUTPUT %external %routine %spec CHARACTER (%integer CH) %external %routine %spec SET CHAR QUALITY (%integer Q) %external %integer %fn %spec OUT STREAM %external %routine %spec OPEN OUTPUT (%integer I, %string (127) ST) %const %integer PRINTER = 6; ! EDWIN Device number. %const %integer TRUE = 0, FALSE = 1 %const %integer PLOT = 5; ! To indicate that the line is a plot line. ! Nb - for Moray House 664 x 780, for VAX and EMAS 774 x 780 %const %integer DOTS WIDE = 774 , DOTS HIGH = 779 %const %integer LINE MAX = DOTS WIDE//8 - 1 %record %format LINEF (%byte %integer %array X (0:LINE MAX)) !%record %format PAGEF (%record(LINEF) %array A (0:DOTS HIGH-1)); ! NOT EMAS !%own %record (PAGEF) PAGE ; ! VAX !%own %record (PAGEF) %name PAGE ; ! MOUSES !%record %format PARM FM (%short DSNO, DACT, SSNO, SACT, %integer P1, P2, P3, P4, P5, P6) %own %record (LINEF) %array PAGE (0:DOTS HIGH-1) ; ! EMAS %own %byte %integer DRAWN = TRUE %own %integer SX = 0, SY = 0 ! MOUSES-specific claim and release segment operations !%record(*)%map ANY SEGMENT(%integer bytes) ! %record(parmfm) p ! p_p2 = bytes; p_p3 = -1; ! <0 => any seg will do ! svc(8,p) ! %signal 14,300,p_p1 %if p_p1 < 0 ! %result == record(p_p1<<16); ! seg. no => addr !%end ! !%routine RELEASE SEGMENT(%record(*)%name r) ! %record(parmfm) p ! p_p1 = addr(r)>>16; svc(9,p) !%end %routine DRAW PAGE %const %integer LINE BUFF LEN = (DOTS WIDE+5)//6 + 4 + 2 %const %integer LIM = LINE MAX // 3 * 3 %string (LINE BUFF LEN) LINE BUFF %integer P, J, LB, I %byte %integer %array %name L ! 3-bit inversion table %constbyteintegerarray inverse(0:7) = 2_000, 2_100, 2_010, 2_110, 2_001, 2_101, 2_011, 2_111 ! 0 1 2 3 4 5 6 7 %for I = DOTS HIGH-1, -1, 0 %cycle L == PAGE(I)_X; ! EMAS ! L == PAGE_A(I)_X; ! NOT EMAS LB = ADDR (LINE BUFF) %for J = ADDR(L(0)), 3, ADDR(L(LIM)) %cycle P = (((BYTE INTEGER(J)<< 8) ! BYTE INTEGER(J+1)) << 8) ! BYTE INTEGER (J+2) BYTE INTEGER (LB + 4) = P&63; P = P >> 6 BYTE INTEGER (LB + 3) = P&63; P = P >> 6 BYTE INTEGER (LB + 2) = P&63; P = P >> 6 BYTE INTEGER (LB + 1) = P&63 LB = LB + 4 %repeat LENGTH(LINE BUFF) = LB - ADDR(LINE BUFF) %if LIM#LINE MAX %start P = 0 %for J = LIM+1, 1, LINE MAX %cycle P = (P<<8)!L(J) %repeat P = P << (8*(3-(LINE MAX - LIM))) %for J = 18, -6, 0 %cycle LINE BUFF = LINE BUFF.TO STRING((P>>J)&63) %repeat %finish ! Strip trailing spaces (represented by binary zero) J = LENGTH(LINE BUFF) J = J-1 %while J>0 %and CHARNO(LINE BUFF, J)=0 LENGTH(LINE BUFF) = J ! Add various bits and characters required by Printronix printer %for j = addr(line buff)+1,1,lb %cycle p = byte integer(j) byte integer(j) = inverse(p&7)<<3 ! inverse(p>>3) ! 64 %repeat BUFF = LINE BUFF.TO STRING(PLOT).TO STRING(NL) FLUSH OUTPUT %repeat DRAWN = TRUE %end %routine DRAW LINE (%integer TX,TY) ! This is algorithm 162 in the Collected Algorithms from CACM. ! ! XYMOVE computes the code string required to move the pen of a ! digital incremental X-Y plotter from an initial point (XZ,YZ) to ! a terminal point (XN,YN) by the "best" approximation to the ! straight line between the points. The permitted elemental pen ! movement is to an adjacent point in a plane Cartesian point latice, ! diagonal moves permitted. %integer A,B,D,E,F,T,I,XMOVE,YMOVE,X,Y %const %byte %integer %array XCODE(1:16) = 4,0,0,0,0,0,4,0,4,5,5,5,5,5,4,5 %const %byte %integer %array YCODE(1:16) = 1,1,0,1,0,2,2,2,2,2,0,2,0,1,1,1 ! PY,PX+PY,PX,PX+PY,PX,PX+NY,NY,PX+NY,NY,NY+NX,NX,NX+NY,NX,NX+PY,PY,NX+PY %routine MOVE (%integer X, Y) ! Move incrementaly over the screen. SX = SX + 1 %if X=0 SX = SX - 1 %if X=5 SY = SY + 1 %if Y=1 SY = SY - 1 %if Y=2 %end %routine MARK ! make mark in line buffer - represented as a linear bit string %byte %integer %name B ! b == page_a(sy)_x(sx>>3); ! NOT EMAS B == PAGE(SY)_X(SX>>3); ! EMAS A label to avert a compiler bug: b = b ! (16_80 >> (sx&7) ) %end MARK %and %return %if SX=TX %and SY=TY A = TX - SX B = TY - SY D = A + B T = B - A I = 0 %if B>=0 %then I=2 %if D>=0 %then I=I+2 %if T>=0 %then I=I+2 %if A>=0 %then I=8-I %else I=I+10 A = -A %if A<0 B = -B %if B<0 F = A + B D = B - A %if D>=0 %then T=A %and D=-D %else T= B E = 0 XMOVE = XCODE (I-1) YMOVE = YCODE (I-1) X = XCODE (I) Y = YCODE (I) %cycle A = D + E B = T + E + A MARK %if B>=0 %start E = A F = F - 2 MOVE (X, Y) %finish %else %start E = E + T F = F - 1 MOVE (XMOVE,YMOVE) %finish %exit %if F<=0 %repeat MARK %end %external %routine P300 (%integer COM, X, Y) %switch SW(0:7) %return %if DEVICE#PRINTER %or COM > 7 -> SW (COM) SW(0): ! Initialise %if VIEWING = 0 %start ! VIEWING = 1; ! VAX, MOUSES ! OPEN OUTPUT (VIEWING, "LP.LIS") VIEWING = 80; ! EMAS OPEN OUTPUT (VIEWING, "LP#LIS") %finish ! PAGE == ANY SEGMENT(64*1024) ; ! MOUSES only ! Next bit for machines with Banners - X = OUT STREAM SELECT OUTPUT (VIEWING) NEWPAGE SELECT OUTPUT (X) ! PAGE = 0; ! NOT EMAS PAGE (X) = 0 %for X = 0, 1, DOTS HIGH-1; ! EMAS ONLY SX = 0 SY = 0 %return SW(1): ! Terminate draw page %if drawn # TRUE ! RELEASE SEGMENT (PAGE) ; ! MOUSES only %return SW(2): ! Update %return SW(3): ! Newframe DRAW PAGE %if drawn # TRUE ! PAGE = 0; ! NOT EMAS PAGE (X) = 0 %for X = 0,1,DOTS HIGH-1; ! EMAS ONLY SX = 0 SY = 0 DRAWN = FALSE %return SW(4): ! Move SX = X SY = Y %return SW(5): ! Line DRAW LINE (X,Y) DRAWN = FALSE %return SW(6): ! Character ! Send it back to EDWIN to get it done as a software one. SET CHAR QUALITY (1) CHARACTER (X) %return SW(7): ! Attributes - none supported. %end %end %of %file