<> <> <> DIRECTORY DicentraRS232CAsync, ColorTrixBasics, ColorTrixMap, Dunn, Imager, ImagerColorMap, ImagerSmooth, IO, InterminalBackdoor, MessageWindow, Process, Rope, Terminal, ThisMachine; DunnImpl: CEDAR PROGRAM IMPORTS DicentraRS232CAsync, ColorTrixBasics, ColorTrixMap, Imager, ImagerSmooth, IO, InterminalBackdoor, MessageWindow, Process, Rope, ThisMachine EXPORTS Dunn ~ BEGIN OPEN Dunn; <<>> null: CHAR ~ '\000; defaultHost: ROPE ~ "York"; defaultDisplay: ROPE ~ "Reprisal"; time: RECORD [short, med, long: INT] _ [10, 60, 120]; -- timeouts in seconds TOKEN: TYPE = RECORD [ok: BOOL, ch: CHAR]; NYBBLE: TYPE = MACHINE DEPENDENT RECORD [hibits:[0..17b], bit3,bit2,bit1,bit0:BOOL]; OpenFailed: PUBLIC ERROR = CODE; InUse: PUBLIC ERROR [user: ROPE] = CODE; SnapperError: PUBLIC ERROR [msg: ROPE] ~ CODE; Simulate: PUBLIC PROC RETURNS [Handle] ~ { RETURN[NEW[HandleRec _ [simulate: FALSE]]]; }; Open: PUBLIC PROC [host, display: ROPE _ NIL] RETURNS [handle: Handle] ~ { IF host = NIL THEN host _ defaultHost; IF display = NIL THEN display _ defaultDisplay; handle _ NEW [HandleRec]; IF Rope.Equal[ThisMachine.Name[], display, FALSE] THEN { MessageWindow.Append[" Opening connection.."]; handle.simulate _ FALSE; handle.stream _ DicentraRS232CAsync.CreateStream[host: host ! IO.Error, IO.EndOfStream => ERROR OpenFailed; DicentraRS232CAsync.CommError => ERROR OpenFailed; DicentraRS232CAsync.CommBusy => ERROR InUse[currentUser]; ]; MessageWindow.Append[" Open"]; } ELSE { handle.simulate _ TRUE; MessageWindow.Append[" Simulation"]; }; }; Close: PUBLIC PROC [handle: Handle] ~ { IF NOT handle.simulate THEN { MessageWindow.Append[" Closing"]; IO.Flush[handle.stream]; IO.Close[handle.stream]; }; MessageWindow.Append[" Done"]; }; Cmd: PUBLIC PROC [handle: Handle, cmd: cmdCode] RETURNS [BOOL] ~ { IF NOT handle.simulate THEN { IO.PutChar[handle.stream, LOOPHOLE[cmd, CHAR]]; IO.Flush[handle.stream]; RETURN[CheckReady[handle.stream]]; }; RETURN[TRUE]; }; CheckReady: PROC [s: STREAM] RETURNS [ok: BOOL _ TRUE] ~ { IO.PutChar[s, LOOPHOLE[cmdCode[readyTest], CHAR]]; IO.Flush[s]; IF IO.GetChar[s] # 'R THEN { MessageWindow.Append[" Not Ready"]; RETURN [FALSE]; }; IF IO.GetChar[s] # '\n THEN { MessageWindow.Append[" Not OK"]; RETURN [FALSE]; }; }; Expose: PUBLIC PROC [handle: Handle] RETURNS [BOOL] ~ { RETURN Cmd[handle, exposeSeq] }; Composite: PUBLIC PROC [handle: Handle] RETURNS [BOOL] ~ { RETURN [Cmd[handle, selectNrmSeqMode]] }; Separate: PUBLIC PROC [handle: Handle] RETURNS [BOOL] ~ { RETURN [Cmd[handle, selectSepSeqMode]] }; Color: PUBLIC PROC [handle: Handle] RETURNS [BOOL] ~ { RETURN [Cmd[handle, selectColor]] }; BW: PUBLIC PROC [handle: Handle] RETURNS [BOOL] ~ { RETURN [Cmd[handle, selectBW]] }; Reset: PUBLIC PROC [handle: Handle] RETURNS [BOOL] ~ { RETURN[ Cmd[handle, restoreFilterWheel] AND Cmd[handle, closeAuxShutter] AND Composite[handle] AND Color[handle]]; }; colorAtom: ARRAY ImagerColorMap.Gun OF ATOM ~ [$Red, $Green, $Blue]; Snapper: PUBLIC PROC [action: PROC[Context], pixelUnits: BOOL _ FALSE, color: BOOL _ TRUE, smooth: BOOL _ TRUE] ~ { handle: Handle; vt: Terminal.Virtual _ InterminalBackdoor.terminal; cd: Context ~ IF smooth OR color THEN ColorTrixBasics.InitCd[smooth, pixelUnits, FALSE] ELSE ColorTrixBasics.InitCd[gray, pixelUnits, FALSE]; DrawAndExpose: PROC ~ { saveAction: PROC ~ {action[cd]}; IF color THEN { IF NOT Separate[handle] THEN ERROR SnapperError["Dunn mode failure."]; FOR gun: ImagerColorMap.Gun IN ImagerColorMap.Gun DO ImagerSmooth.SetComponent[cd, colorAtom[gun]]; ColorTrixBasics.ClearVt[vt, 255]; Process.CheckForAbort[]; ColorTrixMap.PrimaryOnly[gun]; Imager.DoSaveAll[cd, saveAction]; IF NOT Expose[handle] THEN ERROR SnapperError["Dunn expose failure."]; ENDLOOP; } ELSE { ColorTrixBasics.ClearVt[vt, 255]; Process.CheckForAbort[]; Imager.DoSaveAll[cd, saveAction]; IF NOT Expose[handle] THEN ERROR SnapperError["Dunn expose failure."]; }; }; handle _ Open[]; DrawAndExpose[ ! UNWIND => {Close[handle]}]; Close[handle]; }; END. .. ReadToken: PROC [h: Handle, timer: INT _ time.med] RETURNS [t: TOKEN _ [TRUE, null]] ~ { waited: BOOL _ FALSE; FOR i: INT _ 1, i+1 DO IF i > timer THEN { t.ok _ FALSE; IF waited THEN h.debug.PutF["\n"]; RETURN }; IF IO.CharsAvail[h.stream] # 0 THEN EXIT; IF h.debug # NIL THEN {waited _ TRUE; h.debug.PutF["wait... "]}; Process.Pause[Process.SecondsToTicks[1]]; ENDLOOP; IF waited THEN h.debug.PutF["\n"]; t.ch _ IO.GetChar[h.stream ! IO.EndOfStream => t.ok _ FALSE]; }; Status: PUBLIC PROC [handle: Handle] RETURNS [open, sync, film, io: BOOL _ TRUE] ~ { Check: PROC RETURNS[BOOL] ~ { IO.PutChar[handle.stream, LOOPHOLE[cmdCode[statusRequest], CHAR]]; IO.Flush[handle.stream]; t _ ReadToken[handle, time.short]; IF NOT t.ok THEN RETURN[FALSE]; n _ LOOPHOLE[t.ch, NYBBLE]; t _ ReadToken[handle, time.short]; IF NOT t.ok THEN RETURN[FALSE]; t _ ReadToken[handle, time.short]; IF NOT t.ok THEN RETURN[FALSE]; t _ ReadToken[handle, time.short]; IF NOT t.ok OR t.ch # '\n THEN RETURN[FALSE]; RETURN[TRUE]; }; t: TOKEN; n: NYBBLE; IF HandleDisabled[handle] THEN RETURN; IF NOT HandleOK[handle] THEN RETURN[open: FALSE]; THROUGH [0..10] DO IF Check[] THEN RETURN[sync: NOT n.bit0, film: NOT n.bit3]; IO.Flush[handle.stream]; IO.Reset[handle.stream]; ENDLOOP; RETURN[io: FALSE]; }; Cmd: PUBLIC PROC [handle: Handle, cmd: cmdCode] RETURNS [BOOL _ TRUE] ~ { Check: PROC RETURNS[BOOL] ~ { IO.PutChar[handle.stream, LOOPHOLE[cmdCode[readyTest], CHAR]]; IO.Flush[handle.stream]; t _ ReadToken[handle]; IF NOT t.ok OR t.ch # 'R THEN RETURN[FALSE]; t _ ReadToken[handle]; IF NOT t.ok OR t.ch # '\n THEN RETURN[FALSE]; RETURN[TRUE]; }; t: TOKEN; IF HandleDisabled[handle] THEN RETURN; IF NOT Ready[handle] THEN RETURN[FALSE]; IO.PutChar[handle.stream, LOOPHOLE[cmd, CHAR]]; -- send command THROUGH [0..10] DO IF Check[] THEN RETURN[TRUE]; IO.Flush[handle.stream]; IO.Reset[handle.stream]; ENDLOOP; RETURN[FALSE]; }; <<>> HandleOK: PUBLIC PROC [handle: Handle] RETURNS [BOOL] ~ { RETURN[handle # NIL AND handle.stream # NIL]; }; HandleDisabled: PUBLIC PROC [handle: Handle] RETURNS [BOOL] ~ { RETURN[handle # NIL AND NOT handle.enable]; }; Status: PUBLIC PROC [handle: Handle] RETURNS [open, sync, film, io: BOOL _ TRUE] ~ { n: NYBBLE; IF HandleDisabled[handle] THEN RETURN; IF NOT HandleOK[handle] THEN RETURN[open: FALSE]; IO.PutChar[handle.stream, LOOPHOLE[cmdCode[statusRequest], CHAR]]; IO.Flush[handle.stream]; n _ LOOPHOLE[IO.GetChar[handle.stream], NYBBLE]; [] _ IO.GetChar[handle.stream]; [] _ IO.GetChar[handle.stream]; IF IO.GetChar[handle.stream] # '\n THEN RETURN[io: FALSE]; RETURN[sync: NOT n.bit0, film: NOT n.bit3]; }; Ready: PUBLIC PROC [handle: Handle] RETURNS [BOOL] ~ { IF HandleDisabled[handle] THEN RETURN[FALSE]; IO.PutChar[handle.stream, LOOPHOLE[cmdCode[readyTest], CHAR]]; IO.Flush[handle.stream]; IF IO.GetChar[handle.stream] # 'R THEN RETURN[FALSE]; RETURN[IO.GetChar[handle.stream] = '\n]; }; Reserve: PUBLIC PROC RETURNS [handle: Handle _ NIL, errorMsg: ROPE _ NIL] ~ { open, sync, film, io : BOOL _ FALSE; handle _ Open[! OpenFailed => {errorMsg _ "Can't open Dunn. "; CONTINUE}; InUse => { errorMsg _ Rope.Cat["Dunn in use by ", user.Substr[0, user.SkipTo[0, "+"]], ". "]; CONTINUE } ]; IF errorMsg = NIL THEN { [open, sync, film, io] _ Status[handle]; IF NOT open THEN errorMsg _ Rope.Concat[errorMsg, "Not opened. "]; IF NOT sync THEN errorMsg _ Rope.Concat[errorMsg, "No sync. "]; IF NOT film THEN errorMsg _ Rope.Concat[errorMsg, "No film. "]; IF NOT io THEN errorMsg _ Rope.Concat[errorMsg, "IO error. "]; }; IF errorMsg # NIL THEN { IF open THEN Close[handle]; -- refuse Dunn operations handle _ NIL; }; }; DebugOff: PUBLIC PROC [handle: Handle] ~ { IF handle # NIL THEN handle.debug _ NIL; }; DebugOn: PUBLIC PROC [handle: Handle, stream: STREAM] ~ { IF handle # NIL THEN handle.debug _ stream; }; Enable: PUBLIC PROC [handle: Handle] ~ { IF handle # NIL THEN handle.enable _ TRUE; }; Disable: PUBLIC PROC [handle: Handle] ~ { IF handle # NIL THEN handle.enable _ FALSE; };