EGlasImpl.mesa
Copyright © 1985 by Xerox Corporation.  All rights reserved.
Barth, September 18, 1985 3:15:56 pm PDT
Last Edited by: Gasbarro February 21, 1986 2:47:56 pm PST
 
DIRECTORY Ascii, Basics, Convert, EGlas, IO, Process, Rope, XBus;
EGlasImpl: 
CEDAR 
PROGRAM
IMPORTS Basics, Convert, IO, Process, Rope, XBus
EXPORTS EGlas
= BEGIN
 
[Indigo]<Dicentra>11.1>Heads>Private>TTYPortHeadDicentra.mesa
[Indigo]<Dicentra>11.1>Heads>Friends>MultibusAddresses.mesa
Krock: Use second connector because it doesn't fit.
scc0: LONG CARDINAL = 29000H;  -- MultibusAddresses.scc2
chanB: LONG POINTER TO Words = LOOPHOLE[scc0 + 00H];
chanA: LONG POINTER TO Words = LOOPHOLE[scc0 + 10H];
chan: LONG POINTER TO Words ← chanA;  -- Line 0
Words: TYPE = RECORD [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15: WORD];
initialized: BOOL ← FALSE;
Load: 
PUBLIC 
PROCEDURE = {
SendAndCheck["LD*", FALSE];
};
 
ZUp: 
PUBLIC 
PROCEDURE = {
IF ~IsZUp[] THEN ToggleZ[];
};
 
ZDown: 
PUBLIC 
PROCEDURE = {
IF IsZUp[] THEN ToggleZ[];
};
 
IsZUp: 
PROCEDURE 
RETURNS [
BOOLEAN]= {
status: INT;
Send["?SA*"];
CheckResponse[2, "SA"];
IF (status ← GetInt[2,16]) > 15 THEN SynchError[];  -- high nibble should be zero
CheckResponse[1, "*"];
RETURN[Basics.BITAND[status, 2]#0];
};
 
ToggleZ: 
PROCEDURE = {
SendAndCheck["ZM*"];
Process.Pause[Process.SecondsToTicks[1]]; --Tak said this is a good idea
};
 
TestStart: 
PUBLIC 
PROCEDURE = {
SendAndCheck["TS*"];
};
 
Seek: 
PUBLIC 
PROCEDURE [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
};
 
GetDeviceCoordinates: 
PUBLIC 
PROCEDURE [] 
RETURNS [x, y: 
REAL] = {
Send["?DC*"];
CheckResponse[2, "DC"];
x ← GetReal[5];
CheckResponse[1, "-"];
y ← GetReal[5];
CheckResponse[1, "*"];
};
 
SetDeviceCoordinates: 
PUBLIC 
PROCEDURE [x, y: 
REAL] = {
s: ROPE ← IO.PutFR["DC%g-%g*", IO.real[x], IO.real[y]];
SendAndCheck[s];
};
 
SetDieSize: 
PUBLIC 
PROCEDURE [x, y: 
REAL] = {
s: ROPE ← IO.PutFR["DS%g-%g*", IO.real[x], IO.real[y]];
SendAndCheck[s];
};
 
LampOn: 
PUBLIC 
PROCEDURE [] = {
SendAndCheck["LO*"];
};
 
LampOff: 
PUBLIC 
PROCEDURE [] = {
SendAndCheck["LF*"];
};
 
ManualMode: 
PUBLIC 
PROCEDURE [] = {
SendAndCheck["EM*"];
};
 
GetInt: 
PROCEDURE [digits: 
CARDINAL, base: Convert.Base] 
RETURNS[i: 
INT] = {
c: CHAR;
s: IO.STREAM ← IO.ROS[];
FOR j: 
CARDINAL 
IN [0..digits) 
DO
s.PutChar[c←GetChar[]];
ENDLOOP;
 
RETURN[Convert.IntFromRope[IO.RopeFromROS[s], base]];
};
 
GetReal: 
PROCEDURE [digits: 
CARDINAL] 
RETURNS[r: 
REAL] = {
digits is the total of integer+deciamlPoint+fractional characters
c: CHAR;
s: IO.STREAM ← IO.ROS[];
FOR j: 
CARDINAL 
IN [0..digits) 
DO
s.PutChar[(c←GetChar[])];
ENDLOOP;
 
RETURN[Convert.RealFromRope[IO.RopeFromROS[s]]];
};
 
CheckResponse: 
PROCEDURE [chars: 
CARDINAL, expected: 
ROPE] = {
c: CHAR;
s: IO.STREAM ← IO.ROS[];
FOR j: 
CARDINAL 
IN [0..chars) 
DO
s.PutChar[(c←GetChar[])];
ENDLOOP;
 
IF Rope.Compare[IO.RopeFromROS[s], expected, FALSE] # equal THEN SynchError[];
};
 
SendAndCheck: 
PROCEDURE [s: 
ROPE, retry: 
BOOL ← 
TRUE] = {
c: CHAR;
If the command succeeds a "^s*" is returned, if instead a "^q*" or "^r*" (\021 or \022) is returned then the prober went on/off-line during execution of the command.  If the command can be retried it should be sent again.  The probable cause of the prober being off-line during a load command is an auto-align failure.  In this event the user finishes the load command manually.
DO
Send[s];
SELECT (c ← GetChar[]) 
FROM
Ascii.ControlS => IF GetChar[] # '* THEN SynchError[] ELSE EXIT;
'\021, '\022 => IF GetChar[] # '* THEN SynchError[] ELSE IF NOT retry THEN EXIT;
ENDCASE => SynchError[];
 
ENDLOOP;
 
};
 
Send: 
PROCEDURE [s:
 ROPE] = {
FOR i:
INT 
IN [0..s.Length[]) 
DO
PutChar[s.Fetch[i]];
ENDLOOP;
 
};
 
SynchError: 
PROCEDURE = {
ERROR;
};
 
PutChar: 
PROCEDURE [char: 
CHARACTER] = 
TRUSTED {
IF ~initialized THEN Init[];
UNTIL ReadyToPut[] DO Process.CheckForAbort[]; ENDLOOP;
IOWrite[@chan.r8, LOOPHOLE[char]];
};
 
ReadyToPut: 
PROCEDURE 
RETURNS [
BOOLEAN] = 
TRUSTED {
bits: WORD = IORead[@chan.r0];
RETURN[Basics.BITAND[bits, 4] # 0];  -- Tx Buffer Empty
};
 
GetChar: 
PROCEDURE 
RETURNS [char: 
CHARACTER] = 
TRUSTED {
IF ~initialized THEN Init[];
UNTIL ReadyToGet[] DO Process.CheckForAbort[]; ENDLOOP;
char ← LOOPHOLE[Basics.BITAND[IORead[@chan.r8], 177B]];
};
 
ReadyToGet: 
PROCEDURE 
RETURNS [
BOOLEAN] = 
TRUSTED {
bits: WORD = IORead[@chan.r0];
RETURN[Basics.BITAND[bits, 1] # 0];  -- Rx Character Available
};
 
Init: 
PUBLIC PROCEDURE = 
TRUSTED {
IOWrite[@chanB.r0, 002H];  -- Shift Left (ADR0 is ignored)
IOWrite[@chan.r9, 0C0H];  -- Hardware Reset
IOWrite[@chan.r1, 000H];  -- No interrupts
IOWrite[@chan.r3, 0C1H];  -- 8bits/char, RxE
IOWrite[@chan.r4, 04AH];  -- 16xClock, 1.5 Stop Bits
IOWrite[@chan.r5, 0EAH];  -- DTR, 8bits/char, TxE, RTS
IOWrite[@chan.r11, 050H];  -- Clocks from BR Gen
IOWrite[@chan.r12, 31];  -- Low byte of time constant
IOWrite[@chan.r13, 000H];  -- High byte of time constant
IOWrite[@chan.r14, 003H];  -- Enable Baud Rate Gen from PClk
initialized ← TRUE;
};
 
IORead: 
PROCEDURE [adr: 
LONG 
POINTER] 
RETURNS [data: 
CARDINAL] = 
TRUSTED {
data ← XBus.IORead[LOOPHOLE[2*LOOPHOLE[adr, LONG CARDINAL], LONG POINTER]];
};
 
IOWrite: 
PROCEDURE [adr: 
LONG 
POINTER, data: 
CARDINAL] = 
TRUSTED {
XBus.IOWrite[LOOPHOLE[2*LOOPHOLE[adr, LONG CARDINAL], LONG POINTER], data];
};
 
END.