<> <> <> <> 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: BOOL _ FALSE; peekChar: CHAR _ Ascii.NUL; <> <<>> ZDown: PUBLIC PROC = { IF IsZUp[] THEN ToggleZ[]; }; ZUp: PUBLIC PROC = { IF ~IsZUp[] THEN ToggleZ[]; }; ToggleZ: PROC = { SendAndCheck["ZM*"]; <> }; 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]; <> }; 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*"]; }; <> <<>> 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; }]; }; <> 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] = { <> 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] = { <> 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.