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
SyncError: SIGNAL [ROPE] = CODE;
endOfText: BOOL ← FALSE;
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: ROPE ← IO.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: ROPE ← IO.PutFR["DC%g-%g*", IO.real[x], IO.real[y]];
SendAndCheck[s];
};
SetDieSize:
PUBLIC
PROC [x, y:
REAL] = {
s: ROPE ← IO.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.STREAM ← IO.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.STREAM ← IO.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.STREAM ← IO.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:
BOOL ←
TRUE] = {
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.