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 signalisieren. Dieses Register ist Register 13 eines CIAs, das Interrupt Control Register ( 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 Interrupterzeugung starten, sollten wir also
immer im ICR auch angeben, daß dieser
Timer Interrupts erzeugen soll. Darüberhinaus gibt es auch noch eine ganze Menge 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 auszulö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 - heraus- oder hereinrollen) .
Bit4 : Löse einen Interrupt aus, wenn am
Pin FLAG ( am Userport herausgeführt) ein Signal anliegt.
Bit5 : Unbelegt.
Bit6 : Unbelegt.
Bit7 : Doppelfunktion ( siehe unten) .
Wie Sie sehen, ist es ganz einfach, bestimmte Interruptquellen zu wählen. Sogar 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 unterscheiden, 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) gespeichert wird und den Interrupt-Daten
( INT-DATA) . Schreiben wir in das ICR, so
wird der geschriebene Wert zwar zwischengespeichert, jedoch können wir ihn
nicht lesen. Denn wenn wir lesen, gibt
uns das ICR augenblickliche Informationen, 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 werden noch öfter damit zu tun haben.
Lesen wir nun aus dem ICR Daten aus, so
zeigt uns Bit 7 an, ob eines der zugelassenen 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 wurde, 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 vollzogen. 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 Bittabelle vom ICR immer auf Papier parat
haben können.