AMIGA-Magazin · Ausgabe 5/05 OS4-Programmierung: das timer.device

Aktuelles Heft 05/05

Zur richtigen Zeit

Zeitmessungen oder Pausen sind Bestandteile vieler Anwendungen. Für diese und weitere Aufgaben benutzt man das timer.device. Wie Sie mit der internen Uhr von AmigaOS 4 arbeiten, zeigen wir Ihnen auf den folgenden Seiten.

von Michael Christoph

Bereits im letzten Teil wurden Devices kurz angesprochen. In der Regel findet man sie als Schnittstelle zu Hardware-Komponenten. Beispiele dafür sind etwa das serial.device oder das parallel.device. Das ide.device bzw. das scsi.device kümmern sich um die Festplatte. Zum anderen gibt es aber auch noch das console.device oder das clipboard.device, die eher als logische Einheiten anzusehen sind. Das timer.device fällt auch eher in diese Kategorie, verwendet aber auch ICs zur Zeitmessung. Nicht immer ist die Hardware sichtbar, wie ein Drucker oder Modem.

Generell kann man sagen, dass Devices immer dort eingesetzt werden, wo eine asynchrone Verarbeitung von Daten stattfindet. Liest man Daten von der Festplatte (IDOS->Read) stehen diese nach Rückkehr von der Funktion auch sofort zur Verfügung. Das gilt für fast alle Funktionen aus den Libraries. Anders sieht es aus, wenn Daten von der seriellen Schnittstelle gelesen werden. Solange dort keine Daten anliegen, würde das Programm auf die Rückkehr des Funktionsaufrufes warten. In der Zeit wäre dann auch das komplette GUI aus Anwendersicht »tot« und würde nicht mehr auf Eingaben reagieren. Darum ist hier eine asynchrone Verarbeitung notwendig.

Hier soll es nun um die Nutzung von Devices gehen. Im Speziellen mit dem timer.device, da man in den verschiedenen Programmen damit konfrontiert wird.

Die Kommunikation mit den Devices erfolgt über das Message-Prinzip, wobei so genannte IO-Requests zum Einsatz kommen. Diese Struktur wird gefüllt und mittels SendIO() die Abarbeitung gestartet. Aber alles der Reihe nach.

Das timer.device nutzen
Zuerst muss schließlich das Device geöffnet werden, bevor es benutzt werden kann. Auf Grund der schon beschriebenen Arbeitsweise müssen aber noch Vorbereitungen erfolgen. Zum einen wird ein Message-Port benötigt, der die Antworten empfängt, zum anderen muss der IORequest angelegt werden, mit dem die Kommandos transportiert werden. Dabei ist diese IO-Struktur abhängig vom verwendeten Device. Das timer.device verwendet z.B. einen timerequest, das serial.device ein IOExtSer und das audio.device ein IOAudio. Hier hilft also nur ein Blick in die jeweiligen Includes bzw. die Autodocs weiter. Ein Beispiel finden Sie in Listing 1.

Das timer.device stellt fünf logische Einheiten zur Verfügung, über die auch die Genauigkeit des Timers festgelegt wird. Von Bedeutung ist dabei, ob nur kurze Intervalle gewartet werden sollen (im Sekundenbereich) oder länger (z.B. über Stunden). Zu finden sind die Units in der Tabelle »Die Timer Units«.

Das timer.device stellt drei eigene Kommandos zur Verfügung. Über TR_ADDREQUEST kann eine definierbare Zeit gewartet werden, TR_GETSYSTIME und TR_SETSYSTIME erfragen bzw. ändern die Systemzeit (nicht zu verwechseln mit der Hardware-Zeit aus dem Uhrenchip). Um also eine Sekunde zu warten, genügen die folgenden vier Zeilen wie in Listing 2.

Da das Programm nach SendIO sofort zurückkehrt, wird normalerweise in einem Message-Loop gewartet, bis Ereignisse eintreffen. Das kann z.B. das Ablaufen des Timers sein, aber auch Benutzeraktionen, wie z.B. die Auswahl eines Menüpunktes oder das Betätigen eines Buttons (Listing 3). Auf keinen Fall darf die aus dem Port geholte Message mittels ReplyMsg() beantwortet werden, wie dies z.B. bei IDCMP-Nachrichten der Fall ist. Die Nachricht ist nämlich nichts anderes, als unser zuvor weggeschickter ioreq.

Der Vorteil der asynchronen Verarbeitung ist auch, dass diese jederzeit abgebrochen werden kann. Kommen z.B. keine Daten über den seriellen Port, kann der Benutzer entscheiden, dass nicht länger gewartet werden soll. Dazu dient das Kommando AbortIO(). Mit WaitIO() muss noch gewartet werden, bis auch die interne Verarbeitung abgebrochen wurde (Listing 4).

Die Funktion WaitIO macht dabei nichts anderes, als auf das Ende der Kommando-Abarbeitung zu warten. Es ist also eine Kombination aus Wait() und GetMsg(). Beachtet werden sollte, dass beide Kommandos nur dann verwendet werden dürfen, wenn zuvor ein SendIO() erfolgt ist. Bei WaitIO() besteht auch die Gefahr, dass das Programm hier ewig wartet, solange das Kommando nicht abgeschlossen ist.

Natürlich lässt sich so auch ein ausstehender Timer abbrechen. Auf diese Weise ist es möglich, dass eine Minute auf eine Benutzerreaktion gewartet wird und danach automatisch mit dem Programm fortgefahren wird.

Der Messageloop muss nur überprüfen, ob zuerst eine Benutzeraktion erfolgt ist (IDCMP-Nachricht) oder der Timer abgelaufen ist (IORequest-Nachricht). Vor allem bei Batch-Programmen ­ die z.B. über Nacht laufen ­ wäre es ärgerlich, wenn das Programm die ganze Nacht auf eine Benutzereingabe wartet. Natürlich lassen sich nicht alle Rückfragen mit dieser Methode behandeln, aber einfache Rückmeldungen oder Fehlerausgaben, könnten auch einfach in der Shell erfolgen.

Wie schon aus den anderen Teilen bekannt, müssen beim Programmende auch wieder alle angelegten Resourcen freigegeben werden. Das wäre zuerst das Schließen des Devices, dann das Freigeben des IORequest und schließlich die Freigabe des MessagePorts (Listing 5).

Ein komplettes Beispiel finden Sie im Beispielprogramm »StopUhr.c« auf der nächsten Heft-CD bzw. auf unserer Internetseite.

Library-Funktionen im timer.device
Das timer.device ist aber nicht nur ein reinrassiges Device, sondern stellt auch Library-Funktionen zur Verfügung. Hierzu wird wieder, wie schon bekannt, zuerst das Device geöffnet. Im nächsten Schritt wird der Library-Zeiger gesetzt und das Interface dazu angefordert. Ein Beispiel finden Sie in
Listing 6. Später können dann die Funktionen wie in Listing 7 benutzt werden.

Die Kombination aus timer.device, Library-Funktion und einem Reaction-GUI kommt im Beispielprogramm »WinClock.c« zum Einsatz. Auf Grund des asynchronen Timers wird jede Sekunde die aktuelle Uhrzeit abgefragt und per IUtility->Amiga2Date() zur Ausgabe umgewandelt und in einem normalen Readonly-String-Gadget angezeigt. Zusätzlich reagiert das Programm auch auf Aktionen des Anwenders, die sich jedoch in diesem Beispiel auf das Fenster-Schließsymbol beschränken.

In der nächsten Ausgabe gehen wir weiter auf den Einsatz des timer.device ein. Dann geht es um die Programmierung von Dockies. Mit diesen Elementen lassen sich Programme in die AmiDock-Leiste einbinden und für vielfältige Aufgaben verwenden.

lb

Die Timer-Units

Bei UNIT_MICROHZ und UNIT_ECLOCK handelt es sich um einen sehr genauen Timer (im 2 Mikrosekundenbereich), der aber bei längeren Wartezeiten zu Ungenauigkeiten führt. UNIT_MICROHZ verwendet eine timeval-Struktur, UNIT_ECLOCK eine eclockval-Struktur im IORequest.

UNIT_WAITECLOCK hat die gleiche Genauigkeit wie die beiden vorgestellten Units. Sie wartet aber bis die angegebene Zeit (in der eclockval-Struktur) erreicht wird und kehrt erst dann zurück.
Die Unit eignet sich also besonders gut für Alarmfunktionen, die zu einer bestimmten Zeit (z.B. jede Stunde) ausgelöst werden sollen.

UNIT_VBLANK ist auch über eine längere Zeitspanne sehr genau, wird aber nur bei jedem VBlank-Interrupt ausgewertet. Da er für Messungen im Minutenbereich und länger vorgesehen ist, spielen einige Mikrosekunden Ungenauigkeit hier keine Rolle. Bei Zeiten, die mehr als eine Sekunde lang sind, ist er dem MicroHz-Timer vorzuziehen.

UNIT_WAITUNTIL wartet hingegen, bis die angegebene Zeit erreicht (bzw. überschritten) wurde.

 

Bestens informiert:
WinClock zeigt Datum und Uhrzeit sekundengenau an.

 

 

 

 

Gestoppt
Ein Beispiel des Source-Codes gibt es auf der nächsten Heft-CD.

Listingübersicht

Listing 1: Struktur für das times.deivce

Listing 2: Eine Sekunde warten
Listing 3: Warten auf ein Signal
Listing 4: Abbruch eines Aufrufs
Listing 5: Freigabe der Resourcen
Listing 6: Interface anfordern
Listing 7: Aufruf einer timer.device-Funktion

 


Download:enthält:
Download StopUhr : Shellprogramm einer Stopuhr
WinClock : GUI-Programm mit Uhrzeitabfrage und anzeige
os4prog-11-timerdev-src.lha,
63.460 bytes


Hauptseite © 2005 All Rights Reserved. Alle Rechte vorbehalten Franzis' Verlag GmbH
Veröffentlichung und Vervielfältigung nur mit schriftlicher Genehmigung des Verlags

Kommentare, Fragen, Korrekturen und Kritik bitte an Webmaster AMIGA schicken.
Zuletzt aktualisiert am 23. Juli 2005, Michael Christoph.