-- Copyright (C) 1983, 1985 by Xerox Corporation. All rights reserved. -- TestPopCorn.mesa, HGM, 25-Jun-85 3:39:05 DIRECTORY FormSW USING [ AllocateItemDescriptor, ClientItemsProcType, CommandItem, Display, LongNumberItem, newLine, ProcType, StringItem], Heap USING [systemZone], MsgSW USING [Post], Process USING [Detach, Pause, SecondsToTicks, Yield], ProcessorFace USING [microsecondsPerHundredPulses], Put USING [Char, CR, Line, LongDecimal, LongNumber, Text], Runtime USING [GetBcdTime], String USING [AppendString], System USING [ GetClockPulses, GetGreenwichMeanTime, GreenwichMeanTime, Pulses, PulsesToMicroseconds], Time USING [Append, Unpack], Tool USING [ Create, UnusedLogName, MakeFormSW, MakeFileSW, MakeMsgSW, MakeSWsProc], ToolWindow USING [TransitionProcType], UserInput USING [UserAbort], UserTerminal USING [BlinkDisplay], Window USING [Handle], PopCorn USING [Error, GetClockOffset], PupDefs USING [ AppendPupAddress, GetPupAddress, PupAddress, PupNameTrouble, PupPackageDestroy, PupPackageMake]; TestPopCorn: PROGRAM IMPORTS FormSW, Heap, MsgSW, Process, ProcessorFace, Put, Runtime, String, System, Time, Tool, UserInput, UserTerminal, PopCorn, PupDefs = BEGIN z: UNCOUNTED ZONE = Heap.systemZone; msg, log, form: Window.Handle ← NIL; target: LONG STRING ← NIL; lo: LONG INTEGER ← -9999999; hi: LONG INTEGER ← 9999999; min, max: LONG CARDINAL ← 1000000; error: LONG CARDINAL ← 0; running: BOOLEAN ← FALSE; Init: PROCEDURE = BEGIN herald: STRING = [100]; String.AppendString[herald, "TestPopCorn of "L]; Time.Append[herald, Time.Unpack[Runtime.GetBcdTime[]]]; [] ← Tool.Create[ name: herald, makeSWsProc: MakeSWs, clientTransition: Transition]; END; MakeSWs: Tool.MakeSWsProc = BEGIN logFileName: STRING = [40]; msg ← Tool.MakeMsgSW[window: window, lines: 1]; form ← Tool.MakeFormSW[window: window, formProc: MakeItemArray]; Tool.UnusedLogName[logFileName, "TestPopCorn.log$"L]; log ← Tool.MakeFileSW[window: window, name: logFileName]; END; MakeItemArray: FormSW.ClientItemsProcType = BEGIN nItems: CARDINAL = 9; i: INTEGER ← -1; items ← FormSW.AllocateItemDescriptor[nItems]; items[i ← i + 1] ← FormSW.CommandItem[ tag: "PokeIt"L, place: FormSW.newLine, proc: PokeIt]; items[i ← i + 1] ← FormSW.CommandItem[tag: "Tick"L, proc: Tick]; items[i ← i + 1] ← FormSW.CommandItem[tag: "Tock"L, proc: Tock]; items[i ← i + 1] ← FormSW.StringItem[tag: "Target"L, string: @target, inHeap: TRUE]; items[i ← i + 1] ← FormSW.LongNumberItem[tag: " Lo"L, value: @lo, place: FormSW.newLine]; items[i ← i + 1] ← FormSW.LongNumberItem[tag: " Hi"L, value: @hi]; items[i ← i + 1] ← FormSW.LongNumberItem[tag: "Min"L, value: @min, place: FormSW.newLine]; items[i ← i + 1] ← FormSW.LongNumberItem[tag: "Max"L, value: @max]; items[i ← i + 1] ← FormSW.LongNumberItem[tag: "Error"L, value: @error]; IF (i + 1) # nItems THEN ERROR; RETURN[items, TRUE]; END; Transition: ToolWindow.TransitionProcType = BEGIN SELECT TRUE FROM old = inactive => -- tool is becomming active BEGIN [] ← PupDefs.PupPackageMake[]; target ← z.NEW[StringBody[40]]; String.AppendString[target, "PopCorn"L]; END; new = inactive => BEGIN z.FREE[@target]; PupDefs.PupPackageDestroy[]; END; ENDCASE; END; PokeIt: FormSW.ProcType = BEGIN where: PupDefs.PupAddress; IF running THEN BEGIN MsgSW.Post[msg, "Already running."L]; RETURN; END; Header["Poking...."L]; Put.Text[log, target]; Put.Char[log, '=]; PupDefs.GetPupAddress[@where, target ! PupDefs.PupNameTrouble => BEGIN MsgSW.Post[msg, e]; Put.Line[log, e]; GOTO Trouble; END]; PrintPupAddress[where]; Put.Line[log, "."L]; running ← TRUE; Process.Detach[FORK Poker[where]]; EXITS Trouble => NULL; END; Poker: PROCEDURE [where: PupDefs.PupAddress] = BEGIN UNTIL UserInput.UserAbort[log] DO diff: LONG INTEGER; flight, error: LONG CARDINAL; [diff, flight] ← PopCorn.GetClockOffset[where, 2 ! PopCorn.Error => BEGIN Put.Text[log, " Error from PupCorn: "L]; Put.Text[log, text]; Put.Line[log, "."L]; GOTO Trouble; END;]; Put.Text[log, target]; Put.Text[log, " says it's clock is "L]; Put.LongDecimal[log, diff]; Put.Text[log, " ms faster than ours. The flight time was "L]; Put.LongDecimal[log, flight]; Put.Line[log, " ms."L]; error ← flight + 80; -- DLion clock jitters **************** CheckLoHigh[diff - error, diff + error]; Process.Pause[Process.SecondsToTicks[5]]; ENDLOOP; Trailer["Finished."L]; running ← FALSE; EXITS Trouble => running ← FALSE; END; CheckLoHigh: PROCEDURE [newLow, newHigh: LONG INTEGER] = BEGIN hit: BOOLEAN ← FALSE; IF newLow > lo THEN BEGIN hit ← TRUE; lo ← newLow; Put.Text[log, "Better Lo is "L]; Put.LongDecimal[log, lo]; Put.Line[log, "."L]; END; IF newHigh < hi THEN BEGIN hit ← TRUE; hi ← newHigh; Put.Text[log, "Better Hi is "L]; Put.LongDecimal[log, hi]; Put.Line[log, "."L]; END; IF hit THEN BEGIN FormSW.Display[form]; Put.Text[log, "Time is now known within "L]; Put.LongDecimal[log, (hi - lo + 1) / 2]; Put.Line[log, " ms."L]; END; IF lo > hi THEN BEGIN UserTerminal.BlinkDisplay[]; Put.Line[log, " ******** Clocks are mixed up."L]; lo ← -999999; hi ← 999999; FormSW.Display[form]; END; END; Tick: FormSW.ProcType = BEGIN IF running THEN BEGIN MsgSW.Post[msg, "Already running."L]; RETURN; END; Header["Ticking... (using processor clock)."L]; running ← TRUE; Process.Detach[FORK Ticker[]]; END; Ticker: PROCEDURE = BEGIN FOR i: CARDINAL IN [0..100) UNTIL UserInput.UserAbort[log] DO start, stop, oldStart, oldStop: System.Pulses; first, second: System.GreenwichMeanTime; start ← System.GetClockPulses[]; first ← System.GetGreenwichMeanTime[]; DO temp: System.Pulses ← System.GetClockPulses[]; second ← System.GetGreenwichMeanTime[]; stop ← System.GetClockPulses[]; IF first # second THEN EXIT; start ← temp; ENDLOOP; IF i # 0 THEN BEGIN slop: LONG CARDINAL; slop ← System.PulsesToMicroseconds[[stop-start]]; Put.LongNumber[log, stop-start, [10, FALSE, FALSE, 4]]; Put.LongNumber[log, slop, [10, FALSE, FALSE, 6]]; Put.LongNumber[log, System.PulsesToMicroseconds[[start-oldStart]], [10, FALSE, FALSE, 8]]; Put.Line[log, "."L]; CheckMinMax[[stop - oldStart], [start - oldStop]]; END; THROUGH [0..10) DO Process.Yield[]; ENDLOOP; oldStart ← start; oldStop ← stop; ENDLOOP; Trailer["Finished."L]; running ← FALSE; END; Tock: FormSW.ProcType = BEGIN IF running THEN BEGIN MsgSW.Post[msg, "Already running."L]; RETURN; END; Header["Tocking... (using our clock)."L]; running ← TRUE; Process.Detach[FORK Tocker[]]; END; Tocker: PROCEDURE = BEGIN FOR i: CARDINAL IN [0..100) UNTIL UserInput.UserAbort[log] DO start, stop, oldStart, oldStop: System.Pulses; first, second: System.GreenwichMeanTime; start ← System.GetClockPulses[]; first ← MyGetGreenwichMeanTime[]; DO temp: System.Pulses ← System.GetClockPulses[]; second ← MyGetGreenwichMeanTime[]; stop ← System.GetClockPulses[]; IF first # second THEN EXIT; start ← temp; ENDLOOP; IF i # 0 THEN BEGIN slop: LONG CARDINAL; slop ← System.PulsesToMicroseconds[[stop-start]]; Put.LongNumber[log, stop-start, [10, FALSE, FALSE, 4]]; Put.LongNumber[log, slop, [10, FALSE, FALSE, 6]]; Put.LongNumber[log, System.PulsesToMicroseconds[[start-oldStart]], [10, FALSE, FALSE, 8]]; Put.Line[log, "."L]; CheckMinMax[[stop - oldStart], [start - oldStop]]; END; THROUGH [0..10) DO Process.Yield[]; ENDLOOP; oldStart ← start; oldStop ← stop; ENDLOOP; Trailer["Finished."L]; running ← FALSE; END; CheckMinMax: PROCEDURE [minPulses, maxPulses: System.Pulses] = BEGIN hit: BOOLEAN ← FALSE; newMin: LONG CARDINAL ← System.PulsesToMicroseconds[minPulses]; newMax: LONG CARDINAL ← System.PulsesToMicroseconds[maxPulses]; UNTIL newMax < 1500000 DO newMax ← newMax - 1000000; ENDLOOP; IF newMin < min THEN BEGIN hit ← TRUE; min ← newMin; Put.Text[log, "New Min is "L]; Put.LongDecimal[log, min]; Put.Line[log, "."L]; END; IF newMax > max THEN BEGIN hit ← TRUE; max ← newMax; Put.Text[log, "New Max is "L]; Put.LongDecimal[log, max]; Put.Line[log, "."L]; END; IF hit THEN BEGIN oldError: LONG CARDINAL ← error; error ← MAX[(1000000 - min), (max - 1000000)]; FormSW.Display[form]; IF error # oldError THEN BEGIN Put.Text[log, "Clock error is now up to "L]; Put.LongDecimal[log, error]; Put.Line[log, " microsec."L]; END; END; END; -- Simulate greenwich mean time features of ProcessorFace using -- interval timer because DLion TOD clock has much jitter MyGetGreenwichMeanTime: PROCEDURE RETURNS [System.GreenwichMeanTime] = BEGIN seconds: System.GreenwichMeanTime = [((System.GetClockPulses[] - pulsesGmtSimulated)*100)/pulsesPer100Seconds]; pulsesGmtSimulated ← pulsesGmtSimulated + seconds*pulsesPer100Seconds/100; -- long multiply! The truncation keeps pulsesGmtSimulated at the right value gmtSimulated ← [gmtSimulated + seconds]; RETURN[gmtSimulated] END; MySetGreenwichMeanTime: PROCEDURE [gmt: System.GreenwichMeanTime] = BEGIN pulsesGmtSimulated ← System.GetClockPulses[]; gmtSimulated ← gmt; END; gmtSimulated: System.GreenwichMeanTime; pulsesGmtSimulated: LONG CARDINAL; pulsesPer100Seconds: LONG CARDINAL ← 10*(1D9/ProcessorFace.microsecondsPerHundredPulses); Header: PROCEDURE [s: STRING] = BEGIN Put.CR[log]; Put.Line[log, s]; MsgSW.Post[msg, s]; END; Trailer: PROCEDURE [s: STRING] = BEGIN Put.Line[log, s]; MsgSW.Post[msg, s]; END; PrintPupAddress: PROCEDURE [a: PupDefs.PupAddress] = BEGIN temp: STRING = [40]; PupDefs.AppendPupAddress[temp, a]; Put.Text[log, temp]; END; MySetGreenwichMeanTime[System.GetGreenwichMeanTime[]]; Init[]; END...