Das Interrupt-Control-Register (ICR)
----------------------------------------
So. Nun wissen wir also, wie man die
Timer der CIAs steuert. Interrupts haben
wir nun aber noch lange nicht! Die Timer
dienen ja lediglich als Interrupt-
Quellen. Wir benötigen noch ein weiteres
Register des CIA um ihm zu sagen, daß
beim Unterlauf eines Timers auch die
IRQ-Leitung (beim CIA1, bzw. NMI-Leitung
beim CIA2) des Prozessors zu aktivieren
ist, um einen Interrupt zu signalisie-
ren. Dieses Register ist Register 13
eines CIAs, das Interrupt Control Regi-
ster (ICR). Es ist wohl das wichtigste
Register im CIA überhaupt, denn ohne es
könnten wir mit ihm überhaupt nichts
anfangen!
Bevor wir also einen Timer zur Inter-
rupterzeugung starten, sollten wir also
immer im ICR auch angeben, daß dieser
Timer Interrupts erzeugen soll. Darüber-
hinaus gibt es auch noch eine ganze Men-
ge anderer Interruptquellen, die dieses
Register steuert. Ich gebe Ihnen hier
einmal eine tabellarische Öbersicht der
einzelnen Bits vom ICR. Die Bits müssen
gestezt sein, um einen Interrupt aus-
zulösen, wenn das entsprechende Ereignis
eintritt:
Bit0: Löse einen Interrupt aus, wenn
Timer A unterläuft.
Bit1: Löse einen Interrupt aus, wenn
Timer B unterläuft.
Bit2: Löse einen Interrupt aus, wenn die
Alarmzeit der Echtzeituhr mit der
aktuellen Zeit übereinstimmt.
Bit3: Löse einen Interrupt aus, wenn das
SDR (Serial Data Register) voll,
bzw. leer ist (abhängig von der
entsprechenden Betriebsart - he-
raus- oder hereinrollen).
Bit4: Löse einen Interrupt aus, wenn am
Pin FLAG (am Userport heraus-
geführt) ein Signal anliegt.
Bit5: Unbelegt.
Bit6: Unbelegt.
Bit7: Doppelfunktion (siehe unten).
Wie Sie sehen, ist es ganz einfach, be-
stimmte Interruptquellen zu wählen. So-
gar von externer Hardware können DIREKT
Interrupts ausgelöst werden.
Nun jedoch noch zu der Sonderfunktion
von Bit 7. Man muß bem ICR nämlich un-
terscheiden, ob man nun in das Register
schreibt, oder ob man es ausliest. Es
hat nämlich, wie die Timerregister auch,
eine Doppelfunktion. Man unterscheidet
zwischen einem Latch-Register, in dem
die Interrupt-Maske (INT-MASK) gespei-
chert wird und den Interrupt-Daten
(INT-DATA). Schreiben wir in das ICR, so
wird der geschriebene Wert zwar zwi-
schengespeichert, jedoch können wir ihn
nicht lesen. Denn wenn wir lesen, gibt
uns das ICR augenblickliche Informatio-
nen, ob und welches Interruptereignis
eingetreten ist, nicht aber, welchen
Wert wir vorher hineingeschrieben haben.
An diese Doppelfunktion von Registern
sollten Sie sich gewöhnen, denn wir wer-
den noch öfter damit zu tun haben.
Lesen wir nun aus dem ICR Daten aus, so
zeigt uns Bit 7 an, ob eines der zuge-
lassenen Interruptereignisse eingetreten
ist, das heißt, daß Bit 7 immer dann
gesetzt ist, wenn mindestens ein Bit von
INT-MASK mit einem Bit von INT-DATA
übereinstimmt. Dadurch haben wir eine
einfache Kontrolle, ob ein Interrupt
auch tatsächlich vom CIA ausgelöst wur-
de, oder nicht doch von was anderem (wie
zum Beispiel vom VIC, der ja die Raster-
Interrupts auslöst). Duch eine einfache
Abfrage mit dem Assembler-Befehl "BMI"
(Branch on MInus), der ja den Zustand
von Bit 7 überprüft, können wir schnell
feststellen, von wo der Interrupt nun
kommt.
Schreiben wir in das ICR, so ist Bit 7
nochmal doppeldeutig:
Ist es nämlich gelöscht, so wird jedes
weitere 1-Bit sein korrespondierendes
Maskenbit in INT-MASK löschen. Die ande-
ren Bits bleiben unberührt davon. Es
wird also quasi ein AND mit dem Wert den
wir schreiben und dem Wert der in INT-
MASK steht vollzogen.
Ist Bit 7 jedoch gesetzt, so wird jedes
weitere 1-Bit sein korrespondierendes
Masken-Bit setzen. Die anderen bleiben
ebenfalls davon unberührt. Diesmal wird
also ein OR mit den beiden Werten voll-
zogen. Damit können wir also problemlos
ganz gezielt Bits im ICR setzen und lö-
schen, ohne dabei aus Versehen andere
Bits zu verändern.
Auch hier will ich Ihnen eine grafische
Öbersicht liefern, damit Sie die Bitta-
belle vom ICR immer auf Papier parat
haben können.