! EDWIN device driver for Calcomp plotters connected via a 906 controller
! J. Gordon Hughes for Lattice Logic September 1982
from Edwin include Device
from Edwin include Icodes
from Imp include Lognames
external routine CALCOMP alias "EDWIN___L" (integer COM, X, Y)
const string (15) HOST TERM = "EDWIN_CALCOMP"
const integer stx = 2, etx = 3
const integer fela = true { True => dont use controller codes 11-14
! Configuration parameters
const integer double synch = false { A switch setting on controller }
const integer check summing = true { " }
const integer bias char = ' '
const integer threshold = 100 { When EDWIN flushes its buffer }
const integer radix = 126 - bias char
const integer synch = stx
const integer end mess = etx
const byte good mess str = '0'
const byte bad mess str = '1'
own byte array response request str (0:2) = 2, 13, 10
! Command codes
const integer No Op = 0
const integer pen down = 2
const integer pen up = 3
const integer select pen = 4
const integer do text = 5
const integer char type = 6
const integer radix def = 7
const integer escape = 8
const integer scale = 9
const integer pause = 10
const integer end of plot = 15
! Escape sub-codes
const integer double buffer = 1
const integer delay = 3
const integer good mess = 4
const integer bad mess = 5
const integer response request = 6
! Pens
const integer max colour = 15
own byte array slots (0:max colour) = 0, 3, 4, 2, 1, 4, 1, 2, 3, 1 (*)
own byte array slots to use (0:max colour) = 1, 3, 4, 2, 1, 4, 1, 2, 3, 1 (*)
own string (15) array COLOUR NAME (0:MAX COLOUR) = "black",
"black", "blue", "green", "red", "purple", "orange", "lime green", "brown",
"turquoise", "gold", "pen 11", "pen 12", "pen 13", "pen 14", "pen 15"
own byte current colour = 0
const integer max buffer size = 128
own integer max buffer { Max buffer size - size of stx/etx seq. }
own integer buffer count = 0
own integer check sum = 0
own integer pen state = pen up
own integer pending move = false
own integer pending colour = 1 { =0 => no pending colour, #0 => we want pen n }
own integer text mode = false
own string (63) text = ""
own integer sx = 0, sy = 0 { Logical position on plotter }
own integer ax = 0, ay = 0 { Actual position on plotter }
own integer wx, wy
own integer xl, xr, yb, yt
own byte new framed = false
routine SWAP (integer name A, B)
integer C
C = A; A = B; B = C
end
routine flush
integer i
checksum = 64+32-(checksum & 16_1F)
ttput (checksum) if check summing = true
ttput (end mess)
ttput (response request str (I)) for I = 1, 1, response request str(0)
flush output
Buffer Count = 0
return if VIEWING # 0
I = ttget until I = good mess str or I = bad mess str
signal 14, 4 if i = bad mess str
end
routine put (integer i)
if Buffer Count = 0 start
buffer count = 2
ttput (synch)
ttput (synch) and buffer count = buffer count + 1 if double synch = true
ttput (bias char)
checksum = 0
finish
buffer count = buffer count + 1
check sum <- check sum + i
ttput (i + bias char)
end
routine put str (string (7) wee str)
integer I
put (length(wee str))
put (charno(wee str,i)>>4&15) and put (charno(wee str,i)&15) for I = 1,1,length(wee str)
end
routine delta (integer x, y)
! Output a delta move.
const byte array dmap (1:49) = { As table 3-23 in the manual }
8_21, 8_51, 8_55, 8_34, 8_54, 8_50, 8_20,
8_61, 8_25, 8_71, 8_40, 8_70, 8_24, 8_60,
8_65, 8_75, 8_31, 8_44, 8_30, 8_74, 8_64,
8_35, 8_41, 8_45, 0, 8_46, 8_42, 8_36,
8_67, 8_77, 8_33, 8_47, 8_32, 8_76, 8_66,
8_63, 8_27, 8_73, 8_43, 8_72, 8_26, 8_62,
8_23, 8_53, 8_57, 8_37, 8_56, 8_52, 8_22
integer hx, mx, lx, hy, my, ly, xn, yn, xs, ys
return if x=0 and y=0
XS = 1 ; XS = -1 if X < 0 ; X = |X|
YS = 1 ; YS = -1 if Y < 0 ; Y = |Y|
HX = (X//radix) // radix
MX = X//radix - HX*radix
LX = X - MX * radix - HX*radix*radix
HY = (Y//radix) // radix
MY = Y//radix - HY*radix
LY = Y - MY * radix - HY*radix*radix
if HX=0 start
if MX = 0 start
if LX=0 then XN = 0 else XN = 1
finish else XN = 2
finish else XN = 3
if HY=0 start
if MY=0 start
if LY=0 then YN = 0 else YN = 1
finish else YN = 2
finish else YN = 3
put (dmap((3-YN*YS)*7 + (XN*XS+4)))
put (hx) if xn=3
put (mx) if xn>=2
put (lx) if xn>=1
put (hy) if yn=3
put (my) if yn>=2
put (ly) if yn>=1
flush if buffer count > threshold
end
routine Goto ( integer Sx, Sy )
integer Dx, Dy, Ex, Ey
Dx = Sx - Ax ; Dy = Sy - Ay
cycle
Ex = Dx ; Ey = Dy
while |Ex| > 16000 or |Ey| > 16000 cycle
Ex = Ex // 2
Ey = Ey // 2
repeat
Delta(Ex,Ey)
Dx = Dx-Ex
Dy = Dy-Ey
repeat until Dx = 0 = Dy
Ax = Sx ; Ay = Sy
end
routine do move
return if Pending Move = False
return if SX=AX and SY=AY
pending move = false
put (pen up)
pen state = pen up
goto (sx, sy)
end
routine do colour
if slots(pending colour)=0 and viewing=0 start
Do Move
put (pause)
flush
oper message ("Enter new ".colourname(pending colour)." pen in slot ". c
itos(slots to use (pending colour),0)." and press TEST on the plotter")
slots (current colour) = 0
slots (pending colour) = slots to use (pending colour)
current colour = pending colour
finish
put (select pen)
put (slots(pending colour))
pending colour = 0
flush if buffer count > threshold
end
routine do new frame
sx = 0; sy = 0; pending move = true
sx = xr if new framed = true
do move
ax = 0; ay = 0
new framed = true
end
routine flush text
integer i
do newframe if newframed # true
do move
put (do text)
put (length(text))
ttput (charno(text,i)) and buffer count=buffer count + 1 for I=1,1,length(text)
flush
text mode = false
end
routine change attribute (integer what, to)
own integer char size = 0, char rot = 0
integer dash, gap
switch as (0:att maximum)
-> as (what)
as(att colour):
pending colour = to if to#current colour
return
as(att line style):
return if Fela=true
put (13)
unless 0<to<5 and to#2 {no chain} then put (1) else start
if to=1 then DASH=3 and GAP=10
if to=3 then DASH=25 and GAP=10
if to=4 then DASH=45 and GAP=10
put (2)
delta (-dash, gap)
flush if buffer count > threshold
finish
return
as(att Char size):
return if Fela=true
char size = int ((to * 20)/12)
put (char type)
delta (char rot, char size)
return
as(att Char rot):
return if Fela=true
char rot = to
put (char type)
delta (char rot, char size)
return
as(att Char font):
return if Fela=true
to = 0 unless 0<=to<=4
put (14); put (to)
return
as(*): ! All other attributes ignored
end
switch sw (0:MAX COM)
flush text if text mode = true and com#6
-> sw (com)
sw(0): ! Initialise
DEV DATA_NAME = "a Calcomp plotter"
DEV DATA_DVX = 1500
DEV DATA_DVY = 1500
DEV DATA_MVX = 32000
DEV DATA_MVY = 32000
DEV DATA_UNITS PER CM = 200
if TRANSLATE (HOST TERM)#HOST TERM start
SET DEVICE (HOST TERM)
finish
put (radix def); put (radix)
put (escape); put (good mess); put str (tostring(good mess str))
put (escape); put (bad mess); put str (tostring(bad mess str))
put (escape); put (response request)
put str (string(addr(response request str(0))))
put (escape); put (double buffer) { Enable double buffering }
put (escape); put (delay); put (0) { Turn-around delay }
put (select pen); put (1)
put (pen up)
pen state = pen up
max buffer = max buffer size - response request str (0) - 2 { EXT + PEN UP }
max buffer = max buffer - 1 if checksumming = true
flush
pending move = true
SX = 0; SY = 0
return
sw(1): ! Terminate
SX = xr; SY = 0; pending move = true; Do Move
Put(End Of Plot)
flush
return
sw(2): ! Update
Do Move
flush
return
sw(3): ! Newframe
do newframe
return
sw(4): ! Move abs
sx = x; sy = y; pending move = true
return
sw(5): ! Line abs
do newframe if newframed#true
do move
do colour if pending colour # 0
put (pen down) and pen state = pen down if pen state # pen down
goto (x, y)
sx = x; sy = y
return
sw(6): ! Character
signal 14, 14 if Fela=True
if text mode # true start
text mode = true
text = ""
finish
text = text.to string(x)
flush text if length(text)=63 or buffer count + length(text) + 3 >= max buffer
return
sw(7): ! Attribute change
do move if pending move = true
change attribute (x, y)
return
sw(8): ! Lower viewport bounds
xl = x; yb = y
return
sw(9): ! Upper viewport bounds
xr = x; yt = y
return
SW(12): ! Lower box bounds
WX = X; WY = Y
return
SW(13): ! Upper box bounds
swap (wx, x) if wx > x
swap (wy, y) if wy > y
return if WX > XR or X < XL or WY > YT or Y < YB
WX = XL if WX < XL
WY = YB if WY < YB
X = XR if X > XR
Y = YT if Y > YT
! Box now clipped into the screen.
Calcomp (4, Wx, Wy)
Calcomp (5, Wx, y)
Calcomp (5, x,y)
Calcomp (5, x, Wy)
Calcomp (5, Wx, wy)
return
sw(*):
end
end of file