EGlasImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Barth, September 18, 1985 3:15:56 pm PDT
Last Edited by: Gasbarro February 18, 1986 2:20:11 pm PST
DIRECTORY Ascii, Basics, Convert, XBusRS232, EGlas, IO, MessageWindow, Rope, RPCBinding;
EGlasImpl: CEDAR PROGRAM
IMPORTS Basics, Convert, XBusRS232, IO, MessageWindow, Rope, RPCBinding
EXPORTS EGlas
= BEGIN
ROPE: TYPE = Rope.ROPE;
SyncError: SIGNAL [ROPE] = CODE;
endOfText: BOOLFALSE;
peekChar: CHAR ← Ascii.NUL;
These use "SendAndCheck" and are retried by that common procedure
ZDown: PUBLIC PROC = {
IF IsZUp[] THEN ToggleZ[];
};
ZUp: PUBLIC PROC = {
IF ~IsZUp[] THEN ToggleZ[];
};
ToggleZ: PROC = {
SendAndCheck["ZM*"];
Process.Pause[Process.SecondsToTicks[1]]; --Tak said this is a good idea (I guess he was wrong)
};
Load: PUBLIC PROC = {
SendAndCheck["LD*", FALSE];
};
TestStart: PUBLIC PROC = {
SendAndCheck["TS*"];
};
Seek: PUBLIC PROC [x, y: REAL] = {
s: ROPEIO.PutFR["SK%g-%g*", IO.real[x], IO.real[y]];
SendAndCheck[s];
Process.Pause[Process.SecondsToTicks[1]]; --Tak said this is a good idea (I guess he was wrong)
};
SetDeviceCoordinates: PUBLIC PROC [x, y: REAL] = {
s: ROPEIO.PutFR["DC%g-%g*", IO.real[x], IO.real[y]];
SendAndCheck[s];
};
SetDieSize: PUBLIC PROC [x, y: REAL] = {
s: ROPEIO.PutFR["DS%g-%g*", IO.real[x], IO.real[y]];
SendAndCheck[s];
};
LampOn: PUBLIC PROC [] = {
SendAndCheck["LO*"];
};
LampOff: PUBLIC PROC [] = {
SendAndCheck["LF*"];
};
ManualMode: PUBLIC PROC [] = {
SendAndCheck["EM*"];
};
These must be explicitly retried
IsZUp: PROC RETURNS [BOOLEAN]= {
ReallyIsZUp: PROC RETURNS [BOOLEAN] ~ {
status: INT;
Send["?SA*"];
CompareResponse["SA"];
IF (status ← GetInt[16]) > 15 THEN Error["Invalid status"]; -- high nibble should be zero
CompareResponse["*"];
RETURN[Basics.BITAND[status, 2]#0];
};
retryCount: NAT ← 0;
RETURN[ReallyIsZUp[! SyncError, IO.Error, Convert.Error => {
Init[];
retryCount ← retryCount+1;
IF retryCount < 6 THEN RETRY;
}]];
};
GetDeviceCoordinates: PUBLIC PROC RETURNS [x, y: REAL] = {
ReallyGetDeviceCoordinates: PROC ~ {
Send["?DC*"];
CompareResponse["DC"];
x ← GetReal[];
CompareResponse["-"];
y ← GetReal[];
CompareResponse["*"];
};
retryCount: NAT ← 0;
ReallyGetDeviceCoordinates[! SyncError, IO.Error, Convert.Error => {
Init[];
retryCount ← retryCount+1;
IF retryCount < 6 THEN RETRY;
}];
};
Private Parts
GetInt: PROC [base: Convert.Base] RETURNS[i: INT] = {
c: CHAR;
s: IO.STREAMIO.ROS[];
WHILE (c ← PeekChar[])#'* DO
c ← GetChar[];
IF NOT c IN ['0..'9] THEN Error[Rope.Cat["\"", IO.RopeFromROS[s], "\" is not a legal INTEGER string"]] ELSE s.PutChar[c];
ENDLOOP;
RETURN[Convert.IntFromRope[IO.RopeFromROS[s], base]];
};
GetReal: PROC [] RETURNS[r: REAL] = {
digits is the total of integer+deciamlPoint+fractional characters
c: CHAR;
s: IO.STREAMIO.ROS[];
WHILE (c ← PeekChar[])#'* DO
s.PutChar[(c ← GetChar[])];
IF (NOT c IN ['0..'9]) AND (c#'.) THEN Error[Rope.Cat["\"", IO.RopeFromROS[s], "\" is not a legal REAL string"]];
ENDLOOP;
RETURN[Convert.RealFromRope[IO.RopeFromROS[s]]];
};
CompareResponse: PROC [expected: ROPE] = {
c: CHAR;
s: IO.STREAMIO.ROS[];
FOR j: INT IN [0..Rope.Length[expected]) DO
s.PutChar[(c←GetChar[])];
ENDLOOP;
IF Rope.Compare[IO.RopeFromROS[s], expected, FALSE] # equal THEN Error[IO.PutFR["Response expected: %g, got: %g", IO.rope[expected], IO.rope[IO.RopeFromROS[s]]]];
};
SendAndCheck: PROC [s: ROPE, retry: BOOLTRUE] = {
If the command succeeds a "^s*" is returned. If instead a "^q*" or "^r*" (\021 or \022) is returned, then the prober went off/on-line during execution of the command. If the command can be retried it is sent again. The most probable cause of the prober going off-line during a load command is an auto-align failure. In this event the user should finish the load operation manually.
ReallySendAndCheck: PROC = {
Send[s];
SELECT (c ← GetChar[]) FROM
Ascii.ControlS => IF GetChar[] # '* THEN Error["Bad command terminator"];
'\021, '\022 => IF GetChar[] # '* THEN Error["Bad command terminator"] ELSE Error["Prober went off/on line during command"];
ENDCASE => Error["Unexpected response"];
};
c: CHAR;
retryCount: NAT ← 0;
ReallySendAndCheck[! SyncError => {
Init[];
retryCount ← retryCount+1;
IF retry AND (retryCount < 6) THEN RETRY;
}];
};
Send: PROC [s: ROPE] = {
FOR i:INT IN [0..s.Length[]) DO
PutC[s.Fetch[i]];
endOfText ← FALSE;
ENDLOOP;
};
GetChar: PROC RETURNS [c: CHAR] = {
c ← peekChar;
SELECT TRUE FROM
peekChar=Ascii.NUL AND endOfText => Error["Attempted to read past end of message"];
peekChar=Ascii.NUL AND ~endOfText => {
c ← GetC[];
IF c='* THEN endOfText ← TRUE ELSE peekChar ← GetC[];
};
peekChar='* => {
endOfText ← TRUE;
peekChar ← Ascii.NUL;
};
ENDCASE => peekChar ← GetC[];
};
PeekChar: PROC RETURNS [CHAR] = {
IF peekChar=Ascii.NUL THEN [] ← GetChar[];
RETURN[peekChar];
};
PutC: PROC [c: CHAR] = {
retryCount: NAT ← 0;
XBusRS232.PutChar[c ! RPCBinding.CallFailed => {
retryCount ← retryCount+1;
IF retryCount < 6 THEN RESUME;
}];
};
GetC: PROC RETURNS [CHAR] = {
retryCount: NAT ← 0;
RETURN[XBusRS232.GetChar[! RPCBinding.CallFailed => {
retryCount ← retryCount+1;
IF retryCount < 6 THEN RESUME;
}]];
};
Init: PUBLIC PROC = {
retryCount: NAT ← 0;
XBusRS232.Init[! RPCBinding.CallFailed => {
retryCount ← retryCount+1;
IF retryCount < 6 THEN RESUME;
}];
endOfText ← FALSE;
peekChar ← Ascii.NUL;
};
Error: PROC [msg: ROPE] = {
MessageWindow.Append[msg, TRUE];
MessageWindow.Blink[];
MessageWindow.Append[msg, TRUE];
SyncError[msg];
};
END.