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.