DEFINITION MODULE TimerDevice;

(* Revision 1.1                                                         *)
(* Das Module TimerDevice enthält einige Routinen, die den Umgang mit	*)
(* dem Timer-Device und externen Timern erleichtern.                    *)
(* Auf den Files TimerDevice.sym und TimerDevice.obj liegt kein         *)
(* Copyright! Sie dürfen auch in kommerziellen Programmen eingebunden   *)
(* werden. Das Definitionsfile und der Sourcecode, sowie Teile daraus,  *)
(* sind Copyrightgeschützt. Sie müssen (komplett) zusammen mit dem Sym- *)
(* und Obj-File, sowie dem Demo weitergegeben werden. Es dürfen         *)
(* keinerlei Änderungen am Sourcecode ohne meine Erlaubnis vorgenommen  *)
(* werden.                                                              *)
(*                      © 1991 by Andre Wiethoff                        *)
(*                                                                      *)
(* Bei Verbesserungsvorschlägen, Fehlern oder bei Fragen:               *)
(* Andre Wiethoff                                                       *)
(* Höhenweg 2                                                           *)
(* D-57392 Schmallenberg / Germany                                      *)

FROM Timer	IMPORT TimeVal;
FROM ExecD      IMPORT DevicePtr;


CONST
  microHz = 0;                (* OpenTimer *)
  vBlank  = 1;


TYPE TimeList    = RECORD
       year      : LONGCARD;  (* Jahr			           *)
       month     : LONGCARD;  (* Monat			           *)
       day       : LONGCARD;  (* Tag			           *)
       hour      : LONGCARD;  (* Stunde			           *)
       minute    : LONGCARD;  (* Minute			           *)
       second    : LONGCARD;  (* Sekunde		           *)

       week      : LONGCARD;  (* Woche des Jahres	           *)
       dayOfWeek : LONGCARD;  (* Wochentag: 0=Sonntag, 1=Montag... *)
     END;


(* 'OpenTimer' öffnet das Timerdevice und initialisiert die IO-Variablen *)
(* Um die Routinen 'WaitSecs','GetSystemTime','SetSystemTime' oder       *)
(* 'CloseTimer' benutzen zu können muß das Device mit 'OpenTimer' zuerst *)
(* geöffnet worden sein.                                                 *)
(* Die Routinen 'MakeTimeList' und 'MakeTimeVal' können auch ohne das    *)
(* Device zu öffnen, benutzt werden.                                     *)
(* 'timer' gibt an ob der Vertikal-Blanking-Interrupt oder der Zähler, 	 *)
(* der die Netzfrequenz benutzt verwendet werden soll. Der 'microHz'	 *)
(* Zähler kann sehr kleine Zeitabstände verarbeiten, während er bei 	 *)
(* größeren ungenau wird. 'vBlank' arbeitet auf lange Zeit am genausten, *)
(* ist aber in den Microsekunden nicht schnell genug, da nur jede 1/50   *)
(* (PAL) bzw. 1/60 (NTSC) Sekunde die Uhr hochgezählt wird.		 *)
(* Wenn das Timerdevice schon geöffnet war, wird es erst geschlossen und *)
(* wieder neu geöffnet, um einen anderen Timer benutzen zu können.       *)
(* Wenn das TimerDevice geöffnet werden konnte, ist der DevicePtr        *)
(* ungleich NIL und verweist auf das TimerDevice. So können auch die     *)
(* Funktionen aus dem Modul Timer benutzt werden.                        *)

PROCEDURE OpenTimer(timer : CARDINAL) : DevicePtr;



(* 'WaitSecs' wartet mit Hilfe des Timerdevices eine in 'seconds' und    *)
(* 'micros' übergebene Zeit. Wenn die zu wartende Zeiteinheiten sich in  *)
(* in einem 'TimeVal' befinden, muß es nur aufgesplittet werden :        *)
(* WaitSecs(tv.secs,tv.micro);                                 		 *)

PROCEDURE WaitSecs(seconds,micros : LONGCARD);



(* 'GetSystemTime' ermittelt die Systemzeit des Computers und übergibt	 *)
(* diese in der TimeVal-Struktur, die per VAR-Parameter zurückgegeben	 *)
(* wird.								 *)

PROCEDURE GetSystemTime(VAR timeVal : TimeVal);



(* 'SetSystemTime' setzt die Systemzeit auf die in 'timeVal' angebenen	 *)
(* Daten.								 *)

PROCEDURE SetSystemTime(timeVal : TimeVal);



(* 'MakeTimeList' rechnet die Daten einer TimeVal-Struktur in eine 	 *)
(* TimeList-Struktur um, die einfacher ausgelesen werden kann.		 *)
(* Diese Procedure benötigt nicht das Timer-Device.                      *)

PROCEDURE MakeTimeList(    timeVal  : TimeVal;
		       VAR timeList : TimeList);



(* 'MakeTimeVal' wandelt die Daten einer TimeList-Struktur zurück in die *)
(* Moduleigene TimeVal-Struktur. Die Einträge 'week' und 'dayOfWeek'     *)
(* werden hierbei nicht benutzt. Bei Verwendung eines Tages              *)
(* (einer Stunde,..) die nicht existiert, gibt die Funktion FALSE zurück.*)
(* timeVal enthält dann nur die (gekürzte) Zeit. Bei Erfolg wird TRUE    *)
(* zurückgegeben. Auch diese Routine benötigt nicht das Timer-Device.    *)

PROCEDURE MakeTimeVal(    timeList : TimeList;
		      VAR timeVal  : TimeVal) : BOOLEAN;



(* 'GetDaysOfMonth' gibt die Anzahl Tage zurück, die der Monat 'month'   *)
(* im Jahr 'year' besitzt. Bei Übertretung der internen Grenzen wird     *)
(* als Monateslänge 0 zurückgegeben. (Timer-Device wird nicht benötigt)  *)

PROCEDURE GetDaysOfMonth(year,month : LONGCARD) : LONGCARD;



(* 'CloseTimer' gibt alle mit 'OpenTimer' geöffneten Resourcen frei.     *)
(* Diese werden allerdings auch, wenn das Device nicht zuvor geschlossen *)
(* wurde, nach Programmende automatisch wieder freigegeben.		 *)

PROCEDURE CloseTimer;



(* Die folgenden Routinen benötigen ebenfalls nicht das Timerdevice und  *)
(* sprechen die Echzeituhr des Amigas, wenn vorhanden, an.               *)

(* 'BackupClockExistent' prüft ob der Computer eine Echtzeituhr          *)
(* besitzt. Nur bei einem wahren Ergebnis, das das Vorhandensein einer   *)
(* Echtzeituhr bestätigt, haben die folgenden Befehle Sinn.              *)
(* Es ist ratsam vor dem Benutzen der folgenden Routinen diese Funktion  *)
(* aufzurufen, da sie auch dazu benutzt wird, die Echtzeituhr im         *)
(* Speicher zu lokalisieren, da sie bei verschiedenen Amigas an          *)
(* verschiedenen Addressen liegen kann. Voreingestellt sind die          *)
(* Addressen auf die Echtzeituhr im A500 und im A2000B.                  *)

PROCEDURE BackupClockExistent() : BOOLEAN;



(* 'ResetBackupClock' setzt den Zähler der 1/50 Sekunden der             *)
(* Echzeituhr auf 0 herab, um sie mit anderen Uhren zu synchronisieren.  *)
(* Nach dem Aufruf beginnt die Echtzeituhr die begonnene Sekunde von     *)
(* 0 an zu zählen.                                                       *)

PROCEDURE ResetBackupClock;



(* Mit 'StopBackupClock' kann man die Echzeituhr anhalten. Die Zeit      *)
(* die das Anhalten dauert, fehlt der Echtzeituhr. Nach dem Anhalten     *)
(* geht sie höchstwahrscheinlich nach!                                   *)

PROCEDURE StopBackupClock;



(* 'StartBackupClock' startet die Echtzeituhr nach 'StopBackupClock'     *)
(* wieder.                                                               *)

PROCEDURE StartBackupClock;



(* 'GetBackupClock' liest die Daten der Echtzeituhr in die TimeList-     *)
(* Struktur ein, die hier auch in den Timerdevice-Routinen benutzt wird. *)
(* So kann sie sofort dort oder per Hand ausgewertet werden.             *)
(* Es werden alle TimeList-Einträge ausgefüllt. 'week' und 'dayOfWeek'   *)
(* werden berechnet.                                                     *)

PROCEDURE GetBackupClock(VAR timeList : TimeList);



(* 'SetBackupClock' schreibt die Daten einer TimeList-Struktur in die    *)
(* Echtzeituhr. Somit kann man die Zeit sichern und später wieder mit    *)
(* 'GetBackupClock' oder dem CLI-Befehl SetClock setzen. Die Einträge    *)
(* 'week' und 'dayOfWeek' werden nicht berücksichtigt.                   *)

PROCEDURE SetBackupClock(timeList : TimeList);



END TimerDevice.
