Erschienen in 64'er Magazin, Ausgabe 06/1994 · Originaldatei: UHR.TXT
Hinweis: Dies ist das an die Redaktion eingereichte Manuskript, nicht der gedruckte Endtext. Layout, Bildunterschriften, Korrekturen und Kürzungen der Redaktion können in der veröffentlichten Fassung abweichen.
| Objekt | 64'er Magazin |
|---|---|
| Ausgabe | 6/94 |
| Rubrik | Basic-Corner |
| Redakteur | Harry Beiler BL |
| Autor | Nicki Heusler, XXX/XXXXXX |
| Datum | 17.03.1994 |
| Thema | Die Echtzeituhr der CIAs |
Basic-Corner
Beim nächsten Ton...
Die echte Zeit im C 64
Wer einmal mit der Softwareuhr gearbeitet hat, weiß, was Ungenauigkeit bedeutet. Nutzen Sie die genaue Echtzeituhr der CIAs! Damit wird alles anders.
von Nikolaus M. Heusler
Eigentlich ist die Softwareuhr des C 64 noch ein Relikt aus den Zeiten des legendären PET: Dieses "Schätzeisen", das vom Betriebssystem unterstützt wird, und nach PRINT TI$ die ungefähre Zeit ausgibt, beruht auf einem Zähler, der etwa 60 mal je Sekunde erhöht wird. Bei Diskettenzugriffen und wird die schon vorhandene Ungenauigkeit von etwa 30 Minuten pro Tag noch weiter erhöht. Vielleicht verschweigt auch aus diesem Grund das Handbuch schamhaft die Existenz dieser Uhr.
Commodore hat dem C 64 gleich zwei sehr genaue Hardware-Uhren eingebaut, die ebenso wie Ihr Radio-Wecker von der 50 Hz Netzfrequenz gespeist werden. Was liegt also näher, als eine davon für unsere Zwecke zu nutzen? Zunächst aber einige grundsätzliche Erklärungen. Im C 64 gibt es zwei Bausteine namens CIA ("Complex Interface Adapter"), zuständig für alles, was mit Ein-/Ausgabe zu tun hat: Tastatur, Floppy, Joysticks, Interrupts und so weiter. In jeder CIA gibt es einen Funktionsblock namens TOD, womit hier allerdings nichts jenseits von Zeit und Raum gemeint ist, sondern "Time of Day", also "Tageszeit". Diese Uhr wird wie erwähnt vom Stromnetz gesteuert und zählt die Zeit mit einer Genauigkeit von einer Zehntelsekunde. Die Abweichung ist vergleichbar mit der bei netzgespeisten Tischuhren: einige Sekunden pro Tag. Die Uhr läßt sich auch zwischen dem amerikanischen (60 Hz Wechselstrom) und dem deutschen Stromnetz (50 Hz) umschalten, so daß die Zeit immer stimmt. Jede TOD enthält außerdem einen Wecker, der zu einer einstellbaren Zeit einen Interrupt auslösen kann. Leider ist es in Basic nicht ganz einfach, diesen Wecker anzuwenden. Wir beschränken uns daher auf die Uhr.
Die Zeit wird in den Registern 8 bis 11 der CIA verwaltet (siehe Tabelle). Leider können wir diese nicht einfach mit PEEK und POKE behandeln, da die Zeit in dem speziellen BCD-Format gespeichert wird (Textkasten), das Umrechnungen erfordert. Außerdem erfolgt die Zeitrechnung wie in USA üblich nicht im 24 Stunden-Format, sondern die Uhren zählen nur bis zwölf und kennzeichnen in einem besonderen Bit Vormittag oder Nachmittag. Wenige Basiczeilen genügen jedoch für die Umrechnung in unser für Mitteleuropäer gewohntes Format.
Dazu dient das Listing dieser Basic-Corner, das Sie mit dem Checksummer eingeben sollten. Die Unterprogramme ab 10000 und 20000 könnten Sie in Ihren eigenen Programmen einsetzen, sie dienen zum Stellen und Auslesen der TOD.
Uhr stellen
Und das geht so: Ab Zeile 10000 verwenden wir ausnahmeweise den INPUT-Befehl zur Eingabe der Uhrzeit, es kommt hier nicht so sehr auf Benutzerfreundlichkeit an. Geben Sie die Uhr um 24-Stunden-Format ein: Beispielsweise
18 RETURN 32 RETURN 3 RETURN
um die Uhr auf 18:32:03 Uhr zu stellen. Die gewählte Zeit wird nach dem dritten Druck auf RETURN übernommen. In Zeile 10060 rechnen wir die Uhr in das 12-Stunden-Format um: Ist die eingegebene Stundenzahl größer 12, so handelt es sich um eine Uhrzeit am Nachmittag, wir ziehen 12 ab und setzen das Bit 7 (Wert 128, es markiert "PM", also "post meridiem", "nachmittag"). Die Zeile 10070 rechnet die verbleibenden Ziffern der Stundenzahl in das BCD-Format um und addiert ggf. das PM-Flag. Sodann kann mit POKE die Stundenzahl in das Register Nr. 11 der CIA geschrieben werden. Die Uhr bleibt dabei stehen, damit wir genügend Zeit haben, auch Minuten und Sekunden zu setzen. In Zeile 10090 bis 10100 wandeln wir Minuten und die Sekunden in das BCD-Format und schreiben beides in Register 9 bzw. 10. In 10110 schreiben wir eine Null in das Zehntelsekunden-Register 8. Dies bewirkt, daß die Uhr startet. Vergessen Sie diesen Befehl bei eigenen Versuchen nicht! Auch wenn es Ihnen nicht auf die Zehntel ankommen, beschreiben Sie dieses Register bei einem Stellvorgang stets abschließend, da die Uhr sonst steht. Der zweite POKE dieser Zeile schaltet die Uhr - wie es sich für Europa gehört - auf das 50 Hz-Stromnetz um. Vergessen Sie dies, würden Sie sich über einen sehr langen Tag (Fehler ca. 20 Prozent) wundern. Dieser POKE ist übrigens auch nach RUN/STOP-RESTORE erforderlich, da der C 64 seine CIAs dabei wieder auf 60 Hz-Betrieb schaltet. Er ist halt amerikanischen Ursprungs.
Wie spät ist es bitte?
Recht ähnlich geht man beim Lesen der Zeit vor: In Zeile 20010 lesen wir das Stundenregister nach HR. Je nachdem, ob das Bit 7 gesetzt ist (PM) oder nicht (AM), geben wir in H einen Offset von 0 oder 12 vor, der später in Zeile 20020 zu dem nach der 12-Stunden-Uhr errechneten Zeitwert addiert wird. Zeile 20030 dient zum Umrechnen der Minuten vom BCD- in das Dezimalformat, in 20040 bearbeiten wir die Sekunden. Die Uhr läuft nach dem Lesen des Stundenregisters intern zwar weiter, wird jedoch so lange eingefroren, bis wir auch das Zehntelsekundenregister lesen (Zeile 20050). Auch wenn es Ihnen nicht auf die Zehntelsekunden ankommt, müssen Sie daher nach dem Lesen der Uhr immer auch dieses Register in irgend eine Variable auslesen. Zeile 20070 zeigt die Zeit dann mehr oder weniger sauber am Bildschirm an. Lassen Sie bitte nicht die Klammern in den Zeilen 20020 bis 20040 weg - der C 64 würde sonst falsch rechnen: Die Operation AND hat eine niedrigere Priorität als die Addition.
Möchten Sie die beiden Unterroutinen in eigenen Programmen verwenden, erfolgt der Aufruf mit GOSUB 10000 zum Stellen der Uhr oder GOSUB 20000 zur Ermittlung der Uhrzeit.
Sie sehen also, daß bereits wenige Zeilen genügen, um dem C 64 eine viel genauere Uhrzeit zu spendieren. Es gibt übrigens - für die ganz Bequemen - bereits Hilfsprogramme, die intern im System die Variable TI$ so verändern, daß auf eine der beiden Echtzeituhren zugegriffen wird.
(Nikolaus M. Heusler/bl)
Listing. Das Test-/Demoprogramm für die CIA-Echtzeituhr, bitte mit dem Checksummer eingeben
TEXTKÄSTEN
Checkliste für den Fall, daß es nicht klappt
1. Haben Sie die Uhr auf 50 Hz Betrieb geschaltet (zum Beispiel nach RUN/STOP-RESTORE)?
2. Haben Sie beim Stellen zuerst das Stunden- und als letztes das Zehntelsekunden-Register beschrieben?
3. Haben Sie nach einem Lesevorgang auch das Zehntelsekunden-Register gelesen?
4. Haben Sie die Umwandlung von/in BCD und 12/24-Stunden richtig durchgeführt?
5. Stimmt die Startadresse der gewählten CIA? Vielleicht ist der Baustein defekt - probieren Sie es einmal mit der zweiten CIA.
TOD im C 64
Jeder Baustein CIA 6526 besitzt eine Uhr (TOD), die aus der Netzfrequenz eine sehr genaue Tageszeit berechnet. Diese stellt sie in den Registern 11 (Stunden) bis 8 (Zehntelsekunden) zur Verfügung. Außerdem gehören noch weitere Register zu der Uhr (vgl. Tabelle).
Eine Besonderheit betrifft das Lesen und Schreiben der Uhrzeit: Durch Schreiben ins Stunden-, Minuten- oder Sekundenregister stoppt die Uhr. Erst wenn man auch die Zehntelsekunden setzt, startet der Zeitmesser. Dies kann man zum zehntelsekundengenauen Stellen verwenden. Ähnlich ist es beim Lesen: Sobald eines der höheren Register gelesen wird, steht die Uhr scheinbar. Allerdings werden in Wirklichkeit nur die Register eingefroren, sie verändern sich nicht mehr, damit genügend Zeit zum Lesen bleibt. Intern läuft die TOD ganz normal weiter. Erst wenn das Zehntelsekunden-Register gelesen wird, aktualisiert die CIA auch die Register wieder (versorgt sie wieder mit der genauen Zeit).
Als letztes bleibt noch die Alarm-Funktion: Mit dem Bit 7 (Wert 128) des Registers 15 können Sie Uhr- und Alarmzeit wechseln (beim Schreiben, gelesen wird immer nur die Uhrzeit). Ist dieses Bit gelöscht, bewirkt ein Schreibzugriff auf die Register 8 mit 11 wie oben beschrieben ein Stellen der Uhr. Setzen Sie das Bit dagegen, haben Sie via Register 8 mit 11 Schreibzugriff auf die gewünschte Alarmzeit. Ist sie erreicht und der Wecker aktiviert, wird im Register 13 Bit 2 gesetzt. Damit lassen sich dann nach Belieben weitere Aktionen auslösen (zum Beispiel Ausgabe eines Tonsignals).
Bitte verwechseln Sie die hier vorgestellten Echtzeituhren nicht mit den RTCs, die gelegentlich vorgestellt werden und die die Uhrzeit auch nach dem Abschalten des Computers speichern (vgl. z.B. 64'er 10/89 Seite 73 oder Sonderheft 67 Seite 48). Diese arbeiten mit separaten Uhren-Bausteinen. Die hier vorgestellte TOD des C 64 behält die Zeit nur bis zum Abschalten des Computers.
Die Register der TOD
Addieren Sie zu den Registernummern noch die Startadresse der jeweiligen CIA (56320=$DC00 oder 56576=$DD00), um die Speicherzelle zu erhalten. Register 10 (Minuten) erhält so beispielsweise die Adresse 56320+10 = 56330 für CIA Nr. 1 oder Adresse 56576+10 = 56586 für CIA Nr. 2. Welche der beiden CIAs Sie verwenden, ist nur dann von Bedeutung, wenn Sie entweder zwei Uhren parallel verwenden möchten oder aber wenn - wie beim C 64 des Autors dieses Artikels - eine der beiden TODs defekt ist.
Register Bitgruppe Bedeutung 8 Bit 0 bis 3: Zehntelsekunden Einer Bit 4 bis 7: Zehntelsekunden Zehner 9 Bit 0 bis 3: Sekunden Einer Bit 4 bis 7: Sekunden Zehner 10 Bit 0 bis 3: Minuten Einer Bit 4 bis 7: Minuten Zehner 11 Bit 0 bis 3: Stunden Einer Bit 4: Stunden Zehner Bit 7: 0 = Vormittag (AM) 1 = Nachmittag (PM) 13 Bit 2: 1 = Alarmzeit erreicht 14 Bit 7: 0 = 60 Hz (USA) 1 = 50 Hz (Europa) 15 Bit 7: 0 = Uhrzeit schreiben 1 = Alarmzeit schreiben
BCD-Code, was ist das?
BCD ist die englische Abkürzung für "binary coded decimals", also "binär codierte Dezimalzahlen". Dahinter verbirgt sich ein recht einfaches Verfahren, um Dezimalzahlen im Computer unterzubringen. Für jede Stelle der Zahl (Einer und Zehner) werden vier Bit reserviert, die den Wert aufnehmen. Im Gegensatz zum sonst gebräuchlichen Binärsystem werden also nicht den acht Bit von 0 bis 7 Wertigkeiten von 1 bis 128 zugeordnet. Hier ein Beispiel:
Die zu wandelnde Zahl lautet dezimal 49.
1. Stelle binär: 4 = 0100
2. Stelle binär: 9 = 1001
BCD-Zahl: 0100 1001
Die acht Bit dieser BCD-Zahl werden in die Speicherzelle geschrieben. Der binäre Wert von 49 würde dagegen 0011 0001 lauten - auch acht Bit, aber anders codiert.
Beachten Sie, daß bei BCD-codierten Speicherzellen nicht alle Bit-Kombinationen erfaßt sind. Der Wertebereich für eine Speicherzelle geht also nicht wie bei Binärzahlen gewohnt von 0 bis 255, sondern nur von 00 bis 99 (oder für die Uhr sogar nur von 00 bis 59 bzw. bis 12). Da nur die Zahlen 0 bis 9 codiert werden, mit vier Bit je Stelle jedoch 16 Kombinationen möglich sind, bleiben sechs Kombinationen pro Stelle übrig, die in BCD keinen Sinn ergeben und daher meist zu unvorhersagbaren Ergebnissen führen. Die Register der Uhr sind ebenfalls BCD-codiert. Eine Ausnahme macht das Stundenregister. Hier ist die Einerstelle der Stude in den unteren vier Bit gespeichert, in den oberen vier bedient das unterste (Bit 4) die Zehnerstelle, die ja bei einer 12-Stunden-Uhr nur 0 oder 1 annehmen kann. Für Zeiten über 12 Uhr bedient man sich eines Tricks: Bit 7 (Wert 128) wird gesetzt und kennzeichnet damit Zeiten nach Mittag, 12:00:00. Zur Stundenzahl soll also 12 addiert werden.