DEFINITION TimerSupport; CONST timerName = "timer.device"; addRequest = Exec.nonstd + 0; getSysTime = Exec.nonstd + 1; setSysTime = Exec.nonstd + 2; (* modes for OpenTimer *) microHz = 0; vBlank = 1; TYPE TimeVal = STRUCT secs : LONGINT; micro : LONGINT END; TimeRequest = STRUCT END; TimeRequestPtr = POINTER TO TimeRequest; PROCEDURE AddTime(VAR dest, source: TimeVal); PROCEDURE CmpTime(VAR tv1, tv2: TimeVal): INTEGER; PROCEDURE SubTime(VAR dest, source: TimeVal); PROCEDURE OpenTimer(mode: LONGINT): TimeRequestPtr; PROCEDURE CloseTimer(timeReqPtr: TimeRequestPtr); PROCEDURE Delay(timeReqPtr: TimeRequestPtr; secs, micro: LONGINT); PROCEDURE SendIO(timeReqPtr: TimeRequestPtr; secs, micro: LONGINT); PROCEDURE WaitIO(timeReqPtr: TimeRequestPtr); PROCEDURE GetSysTime(VAR t: TimeVal); PROCEDURE SetSysTime(t: TimeVal); PROCEDURE StartClock; PROCEDURE ReadClock(VAR t: TimeVal); PROCEDURE WriteTime(t: TimeVal); PROCEDURE SysToNormalTime(SysTime: TimeVal; VAR Year, Month, Day: LONGINT; VAR Hour, Minute, Second: LONGINT); PROCEDURE NormalToSysTime(Year, Month, Day: LONGINT; Hour, Minute, Second: LONGINT; VAR SysTime: TimeVal); END TimerSupport. This modul supports the use of the Timer.device. For communication with the Timer.device sometimes the stucture TimeVal is used. In this structure the field secs specifies the passed time since 1-Jan-78 in seconds, and the field micro specifies the fractional part of the current second in microseconds. ( 1 microsecond = 1 µs = 1E-6 second ). The field micro should be normalized, this means micro<1E6. secs and micro should not be negative. The procedures StartClock, ReadClock and WriteTime simulates a stopwatch. StartClock resets the clock ( to zero) and starts it. ReadClock reads the time from this clock, without stopping it, and WriteTime writes this time using io.WriteInt. With this three procedures You can easily measure the time which a part of Your program needs for execution. The resolution of this clock is restricted to 1/50 second. The procedures SysToNormalTime and NormalToSysTime (© 1990 by Höhn & Benezan) are identical to the procedures on AMOK#25. They can be used to convert the seconds in the structure TimeVal to the normal date and time or vice versa. Remember that You should not use negative or unnormalized parameter like day=-17 or secs=12345. The procedures AddTime, CmpTime und SubTime can be used for some time-arithmetics: PROCEDURE AddTime(VAR dest, source: TimeVal); dest := dest + source PROCEDURE CmpTime(VAR tv1, tv2: TimeVal): INTEGER; if tv1 = tv1 : 0 if tv1 < tv2 : -1 if tv1 > tv2 : +1 PROCEDURE SubTime(VAR dest, source: TimeVal); dest := dest - source The procedure GetSysTime gives You the current systemtime. Use SysToNormalTime to convert the TimeVal-stucture in the normal form. The resolution of GetSysTime is only 1/50s. If You call GetSysTime several times, then the field micro may differ only by some microseconds. So You may think that You can measure very short timeintervalls of some microseconds. But this is not true. Each time You call GetSysTime the Timer.device will increase the systemtime by one or two microseconds. The Timer.device does this to make sure that every call of GetSysTime will give a changed value. So You can convert the microseconds to a string and than use the string as a name of a file or message-port. If Your program is running many times, so there will be no name-conflicts. You can use SetSysTime to change the systemtime. But be carefully if You turn the time back. It is possible that this confuses the system. Before using the following three procedures You have to open the Timer.device by using OpenTimer. The reason for this is that there are two units of the Timer.device: Unit_VBlank (vertical blank) and Unit_microHz. For the most functions of the Timer.device there is no difference between this two units, but if You use the Timer.device to wait for some time, than the two units behave in a different way. If You use the mode vBlank for opening the Timer.Device, than TimerSupport.Delay works in the same way as Dos.Delay. This means that You can only wait n/50s with n>0. If You try to wait 22000 µs for example, then Timer.device will round this value to 40000µs = 2/50s. But if You use the mode microHz when opening the Timer, You can wait some microseconds. PROCEDURE OpenTimer(mode: LONGINT): TimeRequestPtr; mode must be vBlank or microHz. The result is a pointer which You need for the following procedures Delay, SendIO and WaitIO. You can call OpenTimer more than one time, so You can open one Timer in mode vBlank and one in mode microHz. In the ROM-Kernal-Manual: Libraries and Devices, there I readed that the mode microHz have much system-overhead, which means that this modes takes a lot of power from the sytem. I have not noticed this effect, but You should use the mode microHz only if You have to wait only a few microseconds, and for example not for waiting 500000 µs. PROCEDURE Delay(timeReqPtr: TimeRequestPtr; secs, micro: LONGINT); This procedure can be used to wait for some time. In mode vBlank this procedure does the same as Dos.Delay, but in mode microHz You can wait for very short timeintervalls. PROCEDURE SendIO(timeReqPtr: TimeRequestPtr; secs, micro: LONGINT); PROCEDURE WaitIO(timeReqPtr: TimeRequestPtr); SendIO and WaitIO belong together and You must use these together, that means if You call SendIO You must call WaitIO with the same timeReqPtr. If You call SendIO and WaitIO this behaves like Delay, but there is one difference: Between SendIO and WaitIO You program can do something useful. SendIO starts a countdown. Than Your program can do something. And than You call WaitIO to test if or if not the countdown has terminated. For example suppose You wants to display a text or a picture for 10 seconds. During this time Your program should not sleep, but for example load the next picture. Your program could be like this: trPtr:=OpenTimer(vBlank); IF trPtr=NIL THEN HALT(0) END; LoadPicture(p1); DisplayPicture(p1); SendIO(trPtr,10,0); (* show this picture for at least 10 seconds *) LoadPicture(p2); (* load the next picture *) WaitIO(trPtr); (* has the countdown terminated? *) DisplayPicture(p2); Picture p1 will be shown for at least 10 seconds. If the loading of picture p2 takes more than 10 seconds, then picture p1 is diplayed longer. PROCEDURE CloseTimer(timeReqPtr: TimeRequestPtr); If You have called OpenTimer, You should use CloseTimer when You don't need this timer any more. To each call of OpenTimer there belongs a call of CloseTimer. (If Your program crashed, all open Timer-units will be closed automatically.) Stefan Salewski, 20.1.91 PS: I have developed and tested this modul on an Amiga 1000 with KickStart and Workbench 1.3 and the Amiga-Oberon-Compiler. The text refers to this systemconfiguration. There may be differences if You use Kickstart 2.0 or the new Amiga 3000!