CIA-Kurs: "Die Geheimnisse des Secret Service..." (Teil 6)
Willkommen zum 6 . Teil unseres CIA-Kurses. Diesmal wollen wir, wie letzten
Monat schon versprochen, die Echtzeituhren der CIAs programmieren. Hierbei handelt es sich pro CIA um je eine 24- Stunden-Uhr, die weitaus genauer als die
von BASIC bekannte TI$- Uhr gehen. Sie
werden nämlich über die Frequenz des
Wechselstroms der aus der Steckdose
kommt getriggert. Da diese Frequenz in
der Regel immer 50 Hertz beträgt ( dafür
sorgt das Elektrizitätswerk, das ihn in
das Stromnetz einspeist), gehen die Uhren der CIA so gut wie nie falsch!
Zudem haben wir die Möglichkeit, eine
Alarmzeit zu programmieren. Stimmt irgendwann die aktuelle Uhrzeit mit der
angegebenen Alarmzeit überein, so löst
die jeweilige CIA einen Interrupt aus.
Dieser wird uns im ICR dann auch ge- trennt als Alarm-Interrupt angezeigt.
Auch dieses Mal habe ich Ihnen bezüglich
unseres Schwerpunktes ein Programm geschrieben, daß sich auf dieser MD befindet. Es heißt " CLOCK" und wird mit RUN
gestartet. Desweiteren finden Sie wie
immer auch den Source-Code von CLOCK
unter dem Namen " CLOCK. SRC" im Hypra-Ass- Format auf dieser Diskette. Mit einem Laden an den BASIC-Anfang (",8") können Sie ihn sich mit LIST anschauen.
Kommen wir nun jedoch erst einmal zur
Theorie. Wie programmiert man denn einen
CIA-Timer?
Das gestaltet sich eigentlich als relativ einfach. In den Registern 8-11 einer
jeden CIA werden Zehntelsekunden, Sekunden, Minuten und Stunden abgelegt. Aus
diesen Registern kann ebenso die aktuelle Uhrzeit ausgelesen werden. Dennoch
gibt es einige Besonderheiten, die wir
beachten müssen. Hier zunächst einmal eine Auflistung der besagten Register
mit ihrer Funktion:
Register Funktion
8 Zehntelsekunden 9 Sekunden 10 Minuten 11 Stunden
Erfreulicherweise sind die Uhren der
CIAs so ausgelegt, daß sie im BCD-Format
arbeiten. Dies ist ein spezielles Darstellungsformat für Zahlen, das uns die
Umwandlung der Ziffern für eine Bildschirmausgabe erheblich vereinfacht. BCD
steht für " Binary Coded Decimal", was
übersetzt " Binär kodierte Dezimalzahl" bedeutet. Dieser Code ist unter anderem
auch deshalb so vorteilhaft, weil der
Prozessor des C64, der 6510, es uns erlaubt, mit diesen Zahlen zu rechnen.
Vielleicht kennen Sie ja die Assemblerbefehle SED und CLD. Mit ihnen kann man das Dezimal-Flag des Prozessorstatusregisters setzen oder löschen, um dem 6510 mitzuteilen, daß man nun mit BCD-Zahlen
rechnen möchte.
Ich will Ihnen das einmal anhand einiger
Beispiele erläutern. Kommen wir zunächst
zu dem Zahlenformat selbst. Im BCD-Format wird ein Byte nicht wie sonst
anhand seiner gesetzten, oder gelöschten
Bits codiert, sondern ein Byte wird in
zwei 4- Bit Bereiche aufgepalten. Einen
solchen 4- Bit Abschnitt bezeichnet man
im Fachjargon als Nibble. Hier einmal
eine keine Verdeutlichung:
Nibble1 Nibble2
10010011
Nibble1 ist hierbei das höherwertige, Nibble2 das niederwertige Nibble eines
Bytes. Im BCD-Format stellt nun jedes
Nibble eine Zahl zwischen 0 und 9 dar, die dem normalen Binärformat entspricht( deshlb auch " binär kodiert") . Hier einmal eine Tabelle mit den Werten für die
Ziffern:
Wert Binär
0 0000 1 0001 2 0010 3 0011 4 0100 5 0101 6 0110 7 0111 8 1000 9 1001
Sie sehen, die Werte entsprechen also
denselben Werten die sie im Binärformat
haben. Die Besonderheit des BCD-Formates
ist nun, daß, wie oben schon erwähnt, jedes Nibble eines Bytes eine Dezimalziffer kodiert. Die Binärzahl aus dem
obigen Beipiel kann also folgendermaßen interpretiert werden:
Binär : 1001 0011 BCD-Format : 9 3 = 93 Dezimal umgewandelt: 147
Das höherwertige Nibble der Zahl hat den
Binärwert 9, das niederwertige 3, weshalb die BCD-Zahl 93 lautet! So kann nun
jede Zahl zwischen 0 und 99 kodiert werden. Die sonst 256 verschienden Binärzahlen werden auf 100 Kombinationen reduziert. Zahlen wie 11001010 gibt es im
BCD-Format nicht. Hier wäre die Wertigkeit der Nibbles 12 und 10 . Im BCD-Format gibt dies jedoch keinen Sinn, weshalb Bytewerte wie diese wegfallen.
In der Informatik spricht man dann von
einem " redundanten Code"- man kann mit
ihm weniger Elemente kodieren, als es
Möglichkeiten gibt.
Welchen Vorteil gibt uns nun das BCD-Format in Bezug auf die Timerprogrammierung? Nun aufgrund der einzelnen Nibble- codierung können wir sehr leicht die
Ziffern der Minuten, Stunden, etc. herausfinden. Eine komplizierte Binär-Dezimal- Umwandlung fällt weg.
Desweiteren können wir mit dem Prozessor
im BCD-Format rechnen. Hierzu setzt man
zunächst das Dezimal-Flag mit dem Assembler- Befehl SED. Hiernach verhalten sich
die Befehle ADC und SBC so, daß sie immer BCD-Werte liefern, vorausgesetzt, man addiert auch BCD-Werte miteinander.
Hierzu drei kleine Beispiele:
1) $11 + $12 = $23 2) $11 + $0C = $1D 3) $12 + $19 = $31
Ich habe in den Beispielen Hexadezimalzahlen verwendet, weil mit Ihnen BCD-Zahlen einfacher anzuzeigen sind. Hexzahlen stellen ja ebenfalls die zwei
Nibbles eines Bytes dar, nur daß man
alle Möglichkeiten eines Nibbles berücksichtigt ( von 0 bis F) . Beachten wir nun, daß Zahlen wie $1 C gar keine BCD-Zahlen sind, und verwenden wir sie auch
nicht, so können durch das Hexadezimalsystem sehr einfach BCD-Zahlen dargestellt werden. Hierbei entspricht die
Zahl $12 nicht wie sonst dem Dezimalwert
18, sondern tatsächlich dem Wert 12 ! ! !
Das erste und dritte Beispiel soll Ihnen
nun verdeutlichen, wie im BCD-Format
gerechnet wird.11+12 ergibt tatsächlich
23 . Das wäre nun jedoch nichts neues, da
$11+$12 auch $23 ergäbe. Deshalb zeigt
Beispiel 3 das Aufreten eines Öberlaufs.
Ist der BCD-Modus eingeschaltet, so erhalten wir aus der Addition 12+19 das
Ergebnis 31, was auch richtig ist. Bei
abgeschaltetem BCD-Modus wäre $12+$19- gleich $2 B! Beispiel 2 dient als Gegenbeispiel für eine BCD-Rechung. Weil wir
hier mit $0 C addierten, was ja keine
BCD-Zahl ist, kommt auch keine BCD-Zahl
als Ergebnis heraus.
Soviel zum BCD-Format. Kommen wir nun
zurück zu den Uhren der CIAs. Um die Uhr einer CIA zu Setzen müssen wir also nur
BCD-Zahlen in die jeweiligen Register
schreiben um die aktuelle Zeit einzustellen. Hierbei müssen wir jedoch noch
einige Dinge beachten:
1) Beim Setzen der Uhrzeit sollte IMMER
zunächst das Register für die Stunden
( Reg.11) beschrieben werden. Wird
nämlich auf dieses Register zugegriffen, so hält die entsprechende CIA
die komplette Uhr an. Dies ist deshalb so wichtig, da die Uhr ja gerade
in dem Moment, in dem wir schreiben
auf die nächste Stunde umspringen
könnte. Würden wir eine 10 in das
Stundenregister schreiben und die
restlichen Register stünden auf der
Zeit " :59 :59 .9", so würde noch während wir die Minuten schreiben die
Uhr die volle Stunde erreichen und
unsere 10 wäre eine 11, und das
ist nicht die aktuelle Uhrzeit!
Umgekehrt verhält es sich mit dem Register für die Zehntelsekunden
( Reg.8) . Erst, wenn es beschrieben
wurde, wird die Uhr wieder in Gang
gesetzt. Deshalb müssen wir also immer gleich die komplette Uhrzeit setzen, damit die Uhr auch wirklich
läuft!
Ahnlich verhält es sich auch beim
Lesen. Hier sollten wir ebenfalls
IMMER zuerst die Stundenzahl lesen.
Dies veranlaßt die CIA zum Zwischenspeichern der Uhrzeit in den 4 Uhrregistern zum Zeitpunkt des Zugriffs.
Intern läuft die Uhr allerdings weiter, sie wird also NICHT angehalten.
So können wir immer die richtige
Zeit, nämlich die, die zum Zeitpunkt
des Zugriffs in der Uhr stand, auslesen. Auch hier muß das Zehntelsekundenregister als letztes ausgelesen
werden, damit die tatsächliche Uhrzeit wieder in die 4 Uhrregister
übertragen wird.
( Weiter geht' s im zweiten Teil. . .)