<> <> <> <> DIRECTORY Ascii, Basics, Convert, EGlas, IO, Process, Rope, XBus; EGlasImpl: CEDAR PROGRAM IMPORTS Basics, Convert, IO, Process, Rope, XBus EXPORTS EGlas = BEGIN ROPE: TYPE = Rope.ROPE; <<[Indigo]11.1>Heads>Private>TTYPortHeadDicentra.mesa>> <<[Indigo]11.1>Heads>Friends>MultibusAddresses.mesa>> <> 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] = { <> 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; <> 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.