
ASSEMBLERKURS - LEKTION 27: CIA-Chips-Register (Version 1: Stand: 06/2025)

Autor: Göran Strack

Bereits in Lektion 11 wurde über die beiden 8520-Chips CIA-A und CIA-B die im
Amiga eingebaut sind gesprochen und einige Beispiele zur Tastatur und den 
Timern vorgestellt. In dieser Lektion soll das Wissen mit weiteren Beispielen
und Erklärungen vertieft werden.

********************************************************************************
*  Lektion 11 Wiederholung - CIA-Basiswissen - zur Erinnerung				   *
********************************************************************************

Bei den 8520-Chips handelt es sich nicht um kundenspezifische Chips wie Agnus,
Paula oder Denise, sondern um allgemeine E/A-Chips die mit praktisch jeder CPU,
arbeiten. Sie befassen sich weniger mit der Hardwareplattform selbst, sind aber
als Schnittstelle zur externen Hardware wie Tastatur, Maus, Joysticks sowie
parallelen und seriellen Schnittstellen erforderlich um Peripheriegeräte zu
unterstützen.

Vorneweg, an dieser Stelle lohnt sich einen Blick in den Amiga Schaltplan um
die Gemeinsamkeiten und Unterschiede in der Verdrahtung der beiden Chips zu 
sehen.

Jeder Chip hat folgende Anschlüsse:
- 4 Adressleitungen (RS0-RS3) und eine Chip-Select-Leitung (/CS)
- 8 Datenleitungen  (D0:7 für CIAA, D8:15 für CIAB) Datenaustausch mit der CPU
- 16 Portausgänge   (PA0:7 und PB0:7)
- 1 Resetleitung    (/Reset)
- 1 Interruptleitung (/INT) (CIAA - INT2, CIAB - INT6)
- 1 Tick			(CIAA - Vsync oder Extick, CIAB - Hsync)
- 1 E-Clock			(Eingangstakt) gleichbedeutend mit: 02 pulses
- 1 RW				steuert die Datenrichtung von und zur CPU
- 1 SP				(CIAA - KBDATA, CIAB  - Parallel Port - BUSY)
- 1 CNT				(CIAA - KBCLOCK, CIAB - Parallel Port - POUT)
- 1 PC				(CIAA - Parallel Port - STROBE, CIAB - unbenutzt)
- 1 F				(CIAA - Parallel Port - ACK, CIAB - Index )

Jede CIA hat zwei Ports PRA/PRB und zwei Datenrichtungsregister DDRA/DDRB:
-CIA-A: PRA - Maus-, Joysticktaste, Power-LED, Diskettenlaufwerk
-CIA-A: PRB - Parallel Port - Drucker
-CIA-B: PRA - Parallel Port/ RS232
-CIA-B: PRB - Diskettenlaufwerk

Weiterhin hat jeder Chip intern drei Timer:
- Timer A	- 16 Bit, Abwärtszähler
- Timer B	- 16 Bit, Abwärtszähler
- Timer ToD	- 24 Bit, Aufwärtszähler

-CIA-A: TA	- benutzt als Tastaturschnittstelle
-CIA-A: TB  - wird von EXEC für den Taskaustausch verwendet etc.
-CIA-A: ToD - 50/60 Hz Timer benutzt von Timer.device 
-CIA-B: TA	- nicht verwendet, für Programme verfügbar
-CIA-B: TB	- nicht verwendet, für Programme verfügbar
-CIA-B: ToD - wird von der graphics.library verwendet, um der
			  Positionen des Elektronenstrahls zu folgen

Und darüber hinaus gibt es noch zwei serielle Datenregister:
-CIA-A: SDR	- mit der Tastatur verbunden
-CIA-B: SDR - nicht verwendet


CIAA Übersicht der Adressen
---------------------------------------------------------------------------
 Byte    Register                  Data bits
Addresse   Name     7     6     5     4     3     2     1    0
---------------------------------------------------------------------------
$BFE001    pra     /FIR1 /FIR0  /RDY /TK0  /WPRO /CHNG /LED  OVL
$BFE101    prb     Parallel port
$BFE201    ddra    Datenrichtung für Port A (BFE001);1=output (normalerweise $03)
$BFE301    ddrb    Datenrichtung für Port B (BFE101);1=output (kann in/out sein)
$BFE401    talo    CIAA Timer A Byte niedrig (7.15909 MHz NTSC; 7.09379 MHz PAL)
$BFE501    tahi    CIAA Timer A Byte hoch
$BFE601    tblo    CIAA Timer B Byte niedrig (7.15909 MHz NTSC; 7.09379 MHz PAL)
$BFE701    tbhi    CIAA Timer B Byte hoch
$BFE801    todlo   Timer zu 50/60 Hz - Bits 7-0 (VSync or line tick)
$BFE901    todmid  Timer zu 50/60 Hz - Bits 15-8
$BFEA01    todhi   Timer zu 50/60 Hz - Bits 23-16
$BFEB01            Nicht verwendet
$BFEC01    sdr     CIAA serial data register (mit der Tastatur verbunden)
$BFED01    icr     CIAA interrupt control register
$BFEE01    cra     CIAA control register A
$BFEF01    crb     CIAA control register B

Hinweis: Die CIAA kann einen INT2-Interrupt generieren, d.h. Lev.2, $68.


CIAB Übersicht der Adressen
---------------------------------------------------------------------------
 Byte     Register                   Data bits
Addresse    Name     7     6     5     4     3     2     1     0
---------------------------------------------------------------------------
$BFD000    pra     /DTR  /RTS  /CD   /CTS  /DSR   SEL   POUT  BUSY
$BFD100    prb     /MTR  /SEL3 /SEL2 /SEL1 /SEL0 /SIDE  DIR  /STEP
$BFD200    ddra    Datenrichtung für Port A (BFD000);1 = output (normalerweise $FF)
$BFD300    ddrb    Datenrichtung für Port B (BFD100);1 = output (normalerweise $FF)
$BFD400    talo    CIAB Timer A Byte niedrig (7.15909 MHz NTSC; 7.09379 MHz PAL)
$BFD500    tahi    CIAB Timer A Byte hoch
$BFD600    tblo    CIAB Timer B Byte niedrig (7.15909 Mhz NTSC; 7.09379 Mhz PAL)
$BFD700    tbhi    CIAB Timer B Byte hoch
$BFD800    todlo   Timer für horizontale Synchronisation -  Bits 7-0
$BFD900    todmid  Timer für horizontale Synchronisation -  Bits 15-8
$BFDA00    todhi   Timer für horizontale Synchronisation -  Bits 23-16
$BFDB00            Nicht verwendet
$BFDC00    sdr     CIAB serial data register (nicht verwendet)
$BFDD00    icr     CIAB interrupt control register
$BFDE00    cra     CIAB Control register A
$BFDF00    crb     CIAB Control register B

Hinweis: CIAB kann ein INT6, d.h. Level 6, generieren: $78.

*******************************************************************************
* Adressierung																  *
*******************************************************************************

Die internen 16 Register der CIA-Chips werden über die Adressleitungen RS0-RS3 
adressiert (RS-Register Select). Durch 4 Adressleitungen sind 2^4 
Bitkombinationen möglich, dh. von $0 bis $F. Es gibt dann noch ein Chip-Select
Eingang welches als 'fünftes Adressbit' angesehen werden könnte. Bei Auswahl
aktiviert es den 8520 CIA-Chip. Die CS-Leitung ist für gewöhnlich '0', weil es
low-aktiv ist und gleichbleibend bei Auswahl des Chips durch die Basisadresse.

Die Adressen zur Auswahl der CIA-Chips sind aber nicht $0 bis $F bzw. $10 
bis $1F, sondern etwas seltsam. Und zwar sind die Basisadressen:
CIA-A: $BFE001	
CIA-B: $BFD000	

Wobei auffällt, das es sich um eine 24-Bit-Adresse handelt, bei der der 
Adressteil oberhalb des 64K Adressraumes $bfxxxx fest ist und die Auswahl eines
der 16 Register des Chips durch die 16^2-Stelle x00 erfolgt. Weiterhin ist
Bit 0 bei beiden Chip immer entweder '0' oder '1' und die 16^3-Stelle ist
wiederum fest und ist bei CIA-B auf 'D' und bei CIA-A auf 'E' festgesetzt.

Die Verwendung der Datenleitungen (D0:7 für CIAA, D8:15 für CIAB) erklärt die
Verwendung von geraden und ungeraden Adressen.

Im Schaltplan sieht man das die CIA-Chips durch die Adressleitungen 8 bis 11 
und durch das CS-Signal A12 (CIA-A) und A13 (CIA-B) erfolgt. Das bedeutet, dass
die Registerauswahl durch die Bits 8-11 -> von $0 bis $F und die Aktivierung
durch die Bits A12 und A13 erfolgt.

Schauen wir uns den festen und variablen Adressaufbau kurz an:

>?$BFD000
$00BFD000 = %00000000`10111111`11010000`00000000
>?$BFE001
$00BFE001 = %00000000`10111111`11100000`00000001

oder anders:	     23-16.   15-8  . 7-0
$00BFD000 = %--------`fest`1101.0000`00000000
$00BFE001 = %--------`fest`1110.0000`00000001
		  = %--------`fest`11xx.xxxx`0000000x			    

Aber, wenn beide Auswahlbits A12,A13 auf '0' gesetzt werden (weil low-aktiv)
dann werden auch beide CIA-Chips gleichzeitig ausgewählt. 

A13 A12 
0	0	-> c -> $bfc000 -> es werden beide Chips ausgewählt	
0	1	-> d -> $bfd000		; CIA-B
1	0	-> e -> $bfe000		; CIA-A
1	1	-> f -> $bff000 -> wählt keinen Chip aus

In Listing27a.s schreiben wir mit einem Wort beide Timer 'todlo'-Register. 
					
*******************************************************************************

Toni Wilen:
Ja. A1000- und Gary-basierte Amigas können gleichzeitig auf beide CIAs
zugreifen (wenn beide Auswahlbits aktiv sind). Ich weiß nicht, ob das so 
vorgesehen war oder ob es nur ein Nebeneffekt war. Gayle und Fat Gary 
erlauben nur eine einzelne CIA-Auswahl, nur bfexxx oder bfdxxx Adressraum
aktiviert die CIA-Auswahlzeile.

Einige nicht dokumentierte Funktionen von CD32 nach einigen Tagen des 
Herumprobierens mit mon und asmone. Wurde bereits im cd32load-Thread gepostet.

- Es scheint, dass nicht zugeordnete Adressen nicht „schweben“, alle ungültigen
  Lesevorgänge scheinen immer Nullen zurückzugeben.
- CIA-Chipauswahl, Adressbits 12 und 13 sind CIA-Auswahlen.
  Gary: 0=keine,1=A,2=B,3=A+B, Gayle: 0=keine,1=A,2=B,3=keine, 
  Akiko: 0=A,1=A,2=B,3=B
- CIA-Adressraum: Gary: $A00000-$BFFFFF, Gayle: $BFDxxx und $BFExxx, 
  Akiko: $BFE000-$BFFFFF.
- Benutzerdefinierter Registerspiegel bei $B90000-$B9FFFF! 
  (Das ist wirklich seltsam...)
– Akiko-Adressen werden von $B80000 bis $B87FFF abgebildet und haben eine 
  64-Byte-Spiegelung.
– Vollständige Akiko-ID bei $B80000.l ist $C0CACAFE (KS prüft nur auf $CAFE).
– Alle schreibgeschützten Register scheinen dieselben Daten zu lesen wie das
  benachbarte schreibgeschützte Register. (kein zufälliges Daten-/Busrauschen
  wie bei anderen schreibgeschützten Registern).
– Interruptregister haben nur die Bits 24 bis 31 beschreibbar, andere Bits
  werden immer als Nullen gelesen.
– Konfigurationsregister ($B80024) hat die Bits 23 bis 31 beschreibbar, andere
  Bits werden immer als Nullen gelesen.
– Interrupt-Bit für angekommenen Subkanal wird beim Booten aus unbekanntem 
  Grund gesetzt, Subchannel-Indexregister ($B80018) funktioniert merkwürdig und
  hat beim Booten einen unerwarteten Wert ($C2).
– Interne CIAs von Akiko haben keine externen TOD-Eingabepins. CIA-A TOD, das
  normalerweise Vsyncs oder die Zählrate von Netzteil-Ticks zählt, wird mit
  $B80020 Bit 23 (0=50Hz, 1=60Hz) ausgewählt. Die CIA-B (hsync)-Timing-Logik ist
  noch nicht bekannt, wird aber auch intern generiert.

*******************************************************************************
* Ports																		  *	
*******************************************************************************

Wie der Name des Datenrichtungsregisters DDRA und DDRB es schon sagt, bestimmen
sie mit diesen Registern die Richtung einzelner zugehöriger Portpins, um sie zu
Ein- oder Ausgängen zu machen. Es wäre also sinngemäß ein Steuerregister.
Die Portpins selbst können also als Ein- oder Ausgänge verwendet werden.
Dadurch dass sie vorbelegt sind, sind auch ihre Datenrichtungen vorbestimmt. Es
gibt keinen freien Portpin für eigene Anwendungen. Es sei denn man nutzt
zweckentfremdet z.B. den Feuerknopf-Eingang des Joysticks für andere Aufgaben.

CIAA Übersicht der Adressen
---------------------------------------------------------------------------
 Byte    Register                  Data bits
Addresse   Name     7     6     5     4     3     2     1    0
---------------------------------------------------------------------------
$BFE001    pra     /FIR1 /FIR0  /RDY /TK0  /WPRO /CHNG /LED  OVL
$BFE101    prb     Parallel port
$BFE201    ddra    Datenrichtung für Port A (BFE001);1=output (normalerweise $03)
$BFE301    ddrb    Datenrichtung für Port B (BFE101);1=output (kann in/out sein)

CIAB Übersicht der Adressen
$BFD000    pra     /DTR  /RTS  /CD   /CTS  /DSR   SEL   POUT  BUSY
$BFD100    prb     /MTR  /SEL3 /SEL2 /SEL1 /SEL0 /SIDE  DIR  /STEP
$BFD200    ddra    Datenrichtung für Port A (BFD000);1 = output (normalerweise $FF)
$BFD300    ddrb    Datenrichtung für Port B (BFD100);1 = output (normalerweise $FF)


CIA-A  Address BFEr01  data bits 7-0  (A12*) (INT2)

PA7..	game port 1, pin 6 (fire button*)
PA6..	game port 0, pin 6 (fire button*)
PA5..	RDY*      disk ready*
PA4..	TK0*      disk track 00*
PA3..	WPRO*     write protect*
PA2..	CHNG*     disk change*
PA1..	LED*      led light (0=bright)
PA0..	OVL       memory overlay bit
SP...	KDAT      keyboard data
CNT..	KCLK      keyboard clock

PB7..	P7         data 7
PB6..	P6         data 6
PB5..	P5         data 5     Centronics parallel interface
PB4..	P4         data 4          data
PB3..	P3         data 3
PB2..	P2         data 2
PB1..	P1         data 1
PB0..	P0         data 0
PC...	drdy*                Centronics control
F....	ack* 


In Listing27b.s	werden Portausgänge gelesen oder geschrieben.
In Listing27b2.s wird demonstriert wozu das Memory OVL-Bit gut ist.

Noch ein Hinweis: In den Listings14 (Audio) ist eine der ersten Anweisungen:

bset    #1,$bfe001            ; Schaltet den Tiefpassfilter aus
	
Normalerweise dämpft der Tiefpassfilter das Signal linear zwischen 4 und 7 kHz,
so daß ab 7 kHz nichts mehr zu hören ist. Mit diesem Bit, das übrigens auch die
Helligkeit der Power-LED kontrolliert, schaltet man ihn auf allen 
Amiga-Modellen, außer dem Amiga 1000, aus. Im übrigen ist es meist das erste 
was in Protracker Mods passiert. Selten wird der bei Musik angelassen.

-------------------------------------------------------------------------------
 Parallel port		- fehlt															
 
-------------------------------------------------------------------------------
 Diskettenlaufwerk															 	
 
Der Port B des CIA-B wird zur Steuerung der Diskettenlaufwerke verwendet: 
 
Wichtig in CIABRPB ($bfd100) sind:
Bit 7: /MOTOR (active low)
Bit 6: /DSKSEL3 (active low)
Bit 5: /DSKSEL2 (active low)
Bit 4: /DSKSEL1 (active low)
Bit 3: /DSKSEL0 (active low)

Bei jeder Auswahl eines Antriebs (Wechsel des Auswahlbits von high nach low)
wird der Zustand des Motorbits gespeichert.

Um den Antriebsmotor von Laufwerk 0 einzuschalten:
	lea    $bfd100,a0
	or.b   #$08,(a0)	; %0000.1000 - Laufwerk 0 auswählen - Motor-on Bit 					
	and.b  #$00,(a0)	; %0000.0000 - Laufwerk 0 hi-low

Um alle Antriebsmotoren auszuschalten, verwende ich diesen Code:

	lea    $bfd100,a0
	or.b   #$f8,(a0)	; %1111.1000 - alle Antriebe anwählen
	;nop				; mit high-low-Wechsel wird Motorbit gespeichert
	and.b  #$87,(a0)	; %1000.0111 - MOTOR-off-Bit setzen und Antriebe 
						; abwählen
	or.b   #$78,(a0)	; %0111.1000 - alle Antriebe wieder abwählen.

1. MOTOR-off-Bit setzen und alle Antriebe abwählen.
2. Alle Antriebe anwählen, damit diese den MOTOR-off-Zustand erkennen.
3. Alle Antriebe wieder abwählen.

In Listing27b3.s werden die Laufwerksmotore an- und ausgeschaltet. Mit WinUAE
ist es möglich das Laufwerksgeräusch akustisch zu hören.

Im Übrigen sind NOPs nicht notwendig. Zugriffe auf CIA-Chips werden 
automatisch auf den E-Clock Takt heruntergebremst, was langsam genug ist.

*******************************************************************************
* Timer A und B																  *	
*******************************************************************************

Die Timer A und B sind Abwärtszähler. Der Wertebereich ist 16Bit. Sie zählen 
somit von maximal $ffff (65535) nach 0. Bei einem Unterlauf -1 wird dieses
Ereignis im TA-Flag bzw. TB-Flag signalisiert. Der Eingangstakt von Timer A und
Timer B ist 1/10 vom CPU-Takt und wird E-Clock genannt. 
Nur die Timer A und B von CIA-B sind frei und können für Programme genutzt 
werden.
Durch das Schreiben in TAHi oder TBHi im One-Shot-Mode wird der Timer 
unabhängig von seinem Startbit gestartet. Es sollte deswegen zuerst der
Low-Anteil und anschließend der Hi-Anteil in das Latch-Register geschrieben
werden. Soll der Timer später an einer beliebigen Stelle im Programm mit einem
bestimmten Startwert gestartet werden, muss dafür das Timer Startbit und das
Force Load Bit gleichzeitig gesetzt werden.

Das Auslesen der Timerregister muss so schnell wie möglich erfolgen, da ihr 
Inhalt nicht zwischengespeichert wird. Nur der ToD kann beim Lesen gestoppt
werden. Aus disem Grund bietet es sich an, den ausgelesenen Wert zu überprüfen.

z.B. Während des Auslesens erfolgt der Wechsel im Register: 
tihi/lo = $0100-1=>$00ff	Ausgelesen würde dann: $01ff

Um dies abzufangen:

	move.b (timerhi,a0),d0	; $01
	move.b (timerlo,a0),d1	; $00
	cmp.b (timerhi,a0),d0	; $01=$00
	beq.b no_change
	move.b (timerhi,a0),d0	; $00
no_change					; $00ff

Zwar bieten die IO-Chips hinsichtlich der Konfiguration der Timer A und B über
OUTMODE oder INMODE weitere Einstellmöglichkeiten, aber nicht alle 
Einstelloptionen sind für den Emulator relevant.
So können die Timer im Emulator nicht mit einem 'virtuellen' externen Signal/
Takt heruntergezählt werden. bzw. das Ausgangssignal vom Timer A und B kann 
nicht an einen virtuellen Pin ausgegeben werden.

CIAA Übersicht der Adressen
---------------------------------------------------------------------------
 Byte    Register                  Data bits
Addresse   Name     7     6     5     4     3     2     1    0
---------------------------------------------------------------------------
$BFE401    talo    CIAA Timer A Byte niedrig (7.15909 MHz NTSC; 7.09379 MHz PAL)
$BFE501    tahi    CIAA Timer A Byte hoch
$BFE601    tblo    CIAA Timer B Byte niedrig (7.15909 MHz NTSC; 7.09379 MHz PAL)
$BFE701    tbhi    CIAA Timer B Byte hoch
...
$BFEE01    cra     CIAA control register A
$BFEF01    crb     CIAA control register B

CIAB Übersicht der Adressen
$BFD400    talo    CIAB Timer A Byte niedrig (7.15909 MHz NTSC; 7.09379 MHz PAL)
$BFD500    tahi    CIAB Timer A Byte hoch
$BFD600    tblo    CIAB Timer B Byte niedrig (7.15909 Mhz NTSC; 7.09379 Mhz PAL)
$BFD700    tbhi    CIAB Timer B Byte hoch
...
$BFDE00    cra     CIAB Control register A
$BFDF00    crb     CIAB Control register B

;-------------------------------------------------------------------------------

CONTROL REGISTER A:

  BIT  NAME     FUNCTION
  ---  ----     --------
   0   START    1 = start Timer A, 0 = stop Timer A.
                    This bit is automatically reset (= 0) when
                    underflow occurs during one-shot mode.
   1   PBON     1 = Timer A output on PB6, 0 = PB6 is normal operation.
   2   OUTMODE  1 = toggle, 0 = pulse.
   3   RUNMODE  1 = one-shot mode, 0 = continuous mode.
   4   LOAD     1 = force load (this is a strobe input, there is no
                    data storage;  bit 4 will always read back a zero
                    and writing a 0 has no effect.)
   5   INMODE   1 = Timer A counts positive CNT transitions,
                0 = Timer A counts 02 pulses.
   6   SPMODE   1 = Serial port=output (CNT is the source of the shift
                    clock)
                0 = Serial port=input  (external shift clock is
                    required)
   7   UNUSED


REG# NAME UNUSED  SPMODE  INMODE  LOAD   RUNMODE  OUTMODE   PBON    START
---- ---- ------  ------  ------  ----   -------  -------   ----    -----
 E   CRA  unused  0=input  0=02  1=force  0=cont. 0=pulse  0=PB6OFF 0=stop
          unused  1=output 1=CNT   load   1=one-  1=toggle 1=PB6ON  1=start
                                 (strobe)   shot

                           |<--------  Timer  A Variables --------------->|

All unused register bits are unaffected by a write and forced to 0 on a
read.


CONTROL REGISTER B:

  BIT  NAME     FUNCTION
  ---  ----     --------
   0   START    1 = start Timer B, 0 = stop Timer B.
                    This bit is automatically reset (= 0) when
                    underflow occurs during one-shot mode.
   1   PBON     1 = Timer B output on PB7, 0 = PB7 is normal
                    operation.
   2   OUTMODE  1 = toggle, 0 = pulse.
   3   RUNMODE  1 = one-shot mode, 0 = continuous mode.
   4   LOAD     1 = force load (this is a strobe input, there is no
                    data storage;  bit 4 will always read back a
                    zero and writing a 0 has no effect.)
  6,5  INMODE   Bits CRB6 and CRB5 select one of four possible
                input modes for Timer B, as follows:

                CRB6  CRB5   Mode Selected
                ----  ----   ---------------------------------------
                 0     0     Timer B counts 02 pulses
                 0     1     Timer B counts positive CNT transitions
                 1     0     Timer B counts Timer A underflow pulses
                 1     1     Timer B counts Timer A underflow pulses
                               while CNT pin is held high.

   7   ALARM     1 = writing to TOD registers sets Alarm
                 0 = writing to TOD registers sets TOD clock.
                     Reading TOD registers always reads TOD clock,
                     regardless of the state of the Alarm bit.


REG# NAME ALARM    INMODE     LOAD      RUNMODE  OUTMODE  PBON    START
---- ---- -----    ------     ----      -------  -------  ----    -----
 F   CRB  0=TOD    00=02      1=force   0=cont.  0=pulse  0=PB7OFF 0=stop
          1=Alarm  01=CNT       load    1=one-   1=toggle 1=PB7ON  1=start
                   10=Timer A  (strobe)   shot
                   11=CNT+
                     Timer A

                   |<---------------  Timer B  Variables ------------>|


All unused register bits are unaffected by a write and forced to 0 on a
read.
					 
;-------------------------------------------------------------------------------
Eingangstakt und Zeiten berechnen

HRM: The 02 clock is a TIL compatible input used for internal device operation
and as a timing reference for communicating with the system data bus. On the
Amiga, this is connected to the 68000 "E" clock. The "E" clock runs at 1/10 of
the CPU clock. This works out to .715909 Mhz for NTSC or .709379 Mhz for PAL.

							|		NTSC			|		PAL
-----------------------------------------------------------------------------
Frequenz:					|	60Hz				| 50Hz
Hauptkristallfrequenz		|	~28,63636363 MHz	| 28,37516 MHz
Paula Taktrate (CCK's)		|	~3579545,45 Hz 		| 3546895 Hz (genau)
Farbtakt (CCK) (1/f)		|	279,36 ns			| 281,94 ns

CPU-Takt:					|	7.159090 MHz		| 7.093790 MHz
E-Clock:					|	0.715909 MHz	    | 0.709379 MHz
TA-clock (t=1/f):			|	1,396825 µs		    | 1,409683 µs

Videozeilen:				|	262/263 = 525		| 312/313 = 625	 
Buszyklen pro Zeile			|	227.5 CCK			| 227 CCK
H-Frequenz					|	15734,26Hz			| 15625,0881 Hz
1 Rasterzeile				|	~63,56µs			| 64µs

1 Rasterzeile in E-Clock	|   45,46 ~ 45 ticks	| 45,40 ~ 45 ticks	
Timerwert für 10ms			| 7159,09 ~ 7159 = 10ms | 7093,79 ~ 7094 = 10ms
Timerwert 1 frame			| 11932 ticks (16,667Hz)| 14148 ticks (20ms)


Zu den Frequenzen und Timerwerten:

Nehmen Sie einfach die Hauptkristallfrequenz für PAL/NTSC-Amigas (28,37516 MHz
für PAL und ~28,63636363 MHz (wiederholend) für NTSC) und teilen Sie diese
durch 8, um die Paula-Taktrate zu erhalten. Jeder Takt (außer der Tastatur) 
wird von diesem Kristall abgeleitet, sogar die Videotakte. Die Paula-Taktrate
entspricht der Anzahl der Farbtake (Color Clocks/CCKs) pro Sekunde. 

Die nominalen Paula-Raten sind also:
PAL: genau 3546895 Hz
NTSC: ~3579545,45 Hz (wiederholend)
	
Dies sind Nominalwerte, die Frequenzen im realen Fall werden aufgrund von 
Kristalltoleranzen und möglicherweise anderen externen Faktoren um einen
kleinen Bruchteil abweichen.

Auch der CPU-Takt ist vom Hauptkristall abgeleitet: Hauptkristallfrequenz/4.
bzw. 2*Paula-Takt.

Die EClockFrequency (der Basistakt für CIA-Chips) ist CCK/5 bzw. 
Paula-Taktrate/5 oder CPU-Takt/10.

PAL:	
Das PAL-Bild besteht aus 312/313 Halbbilder, d.h. 312,5*50Hz=15625. Um genau
zu sein beträgt die PAL-H Frequenz 15625,0881Hz. Der Kehrwert 1/f=64µs.

Daraus ergibt sich Anzahl der "Farbtakte", CCK's (Color Clocks) oder Buszyklen
pro Video- bzw. Scanzeile. (Paula-Taktrate/PAL-H-Frequenz)
3546895 Hz/15625 Hz=227,00128 bzw (ungenau)
3546895 Hz/15625,0881 Hz = 227 CCK's pro Videozeile (genau)

NTSC:
Das NTSC-Bild besteht aus 262/263 Halbbilder, d.h. 262,5*60Hz=15750. Um genau
zu sein beträgt die NTSC-H Frequenz 15734,26Hz. Der Kehrwert 1/f=63,56µs.
3579545,45 Hz/ 15750 Hz= 227,2727(ungenau)	
3579545,45 Hz/ 15734,26Hz = 227,5 CCK's pro Videozeile (genau)
		
EAB/ross:
NTSC-only AGNUS generates 262/263 lines with duration 227.5CCK and frame with
propereq/serration/blank (internally it uses alternating 227/228 cycles).
PAL-only AGNUS generates 312/313 lines with duration 227CCK (both internally
and externally) and proper frame.

HRM: Die gesamte Zeitmessung erfolgt auf der Grundlage eines "Farbtakts", der
auf NTSC-Rechnern 279,36 ns und auf PAL-Rechnern 281,94 ns lang ist.

;------------------------------------------------------------------------------
Nebenrechnung PAL:

312+313=625 | 50Hz=20ms (bzw. 2x312,5)

313 Zeilen:		20ms/313=63,89776µs -> 1 Rasterzeile in PAL
				63,89776µs/227CCK = 281,4879ns clock cycle

312 Zeilen:		20ms/312=64,106µs -> 1 Rasterzeile in PAL
				64,106µs/227CCK = 282,390ns clock cycle

				(281,4879ns+282,390ns)/2=281,93ns
				(63,89776µs+64,106µs)/2=64,00µs
				20ms/625=64µs
;------------------------------------------------------------------------------
Nebenrechnung NTSC:

263+262=525	| 60Hz=16,66666ms

263 Zeilen:		16,66666ms/263=63,376µs -> 1Rasterzeile in NTSC
				63,376µs/227,5CCK = 278,555ns clock cycle

262 Zeilen:		16,66666ms/262=63,613µs -> 1Rasterzeile in NTSC
				63,613µs/227,5CCK = 279,6186ns clock cycle

				(278,555ns+279,6186ns)/2=279,087ns
				(63,376µs+63,613µs)/2=63,49µs
				16,6666ms/525=63,49µs

Eine Rasterzeile benötigt in PAL 64µs und in NTSC 63,5µs.

;------------------------------------------------------------------------------

1 Rasterzeile dauert in PAL:  64,0µs/ 1,409683 µs = 45,40 ~ 45 ticks
1 Rasterzeile dauert in NTSC: 63,5µs/ 1,396825 µs = 45,46 ~ 45 ticks

Angenommen man wollte eine bestimmte Anzahl an Rasterzeilen warten:

LINES: equ 40				; 40 Rasterzeilen mit Timer A oder B warten
MISC:  equ LINES*45			; 1800 ticks (oder TA-clock)

Listing27c.s	; (modifizierte Variante von Listing11n1.s) 	
-> Timer A des CIA-B im One-Shot mode für eine gewisse Zeit laufen lassen
Listing27c2.s	; (modifizierte Variante von Listing11n1b.s)	
->  Timer B des CIAB im One-Shot mode für eine gewisse Zeit laufen lassen

Der Timer signalisiert die abgelaufene Zeit durch das Bit 0 (TA) oder Bit 1
(TB) bei einem Unterlauf. 

PAL:	((1800+1)*1,409683µs)/64,0µs=39,66 Rasterzeilen	
NTSC:	((1800+1)*1,396825µs)/63,5µs=39,61 Rasterzeilen

Oder man möchte die Zeit in ms bzw. Anzahl der Rasterzeilen wissen, die eine
Routine benötigt, so kann man den Timer A CIA-B zur Zeitmessung verwenden.

Dabei wäre eine maximale Zeit von $ffff=65535+1 'ticks' messbar. Was einer Zeit
entspricht von:
NTSC: 1,396825 µs * 65536= 91,54ms => 91540µs  (1000µs = 1ms)
PAL:  1,409683 µs * 65536= 92,38ms => 92380µs

Aber besser vorstellbar ist wahrscheinlich eine Angabe in Rasterzeilen.
Rasterzeilen = ticks/45 
Rasterzeilen = 65536/45=1456 --> entspricht ca. 4,65 frames (bei 313 Zeilen)

In den Listings27c3.s messen wir die Ausführungszeit einer Routine mit dem 
Timer A von CIA-B in Ticks und in Anzahl Rasterzeilen.

In Listing27c4.s bringen wir etwas Dynamik ins Programm und zeigen auch die 
Ausführungszeit in Rasterzeilen auf dem Bildschirm an.

Das Listing27c5.s dient dazu zwischen 50Hz/60Hz zu unterscheiden. Dazu habe ich
den Quellcode von timer.device analysiert und etwas optimiert.
Die Funktionsweise ist: es werden von Vsync zum nächsten Vsync die Timertakte
(E-Clock) mit dem Timer B gemessen und dann ausgewertet. Vielleicht habe ich 
die Grenzen (CMP-Werte) etwas zu eng gelegt, aber auf dem A500 funktioniert es
in PAL und NTSC. Da der A500 der langsamste ist, A1200 wäre schneller, sollte 
es auf allen Systemen funktionieren? Habe dies aber nicht getestet.
Ich meine: der Vergleich und das Stoppen kosten selbst etwas Zeit, sodaß nie
wirklich z.B. 14188 gezählt werden, sondern z.B. 14208. Warum 20 Takte mehr
verstehe ich auch nicht, denn 10 CPU-Takte wären 1 E-Clock-Takt.

*******************************************************************************
* Timer A und B	- Interrupt													  *	
*******************************************************************************

CIA können Interrupts der Stufe 2 (CIA A) und Stufe 6 (CIA B) für die CPU 
auslösen - in Verbindung mit den entsprechenden Custom Chip Registern (INTENA,
INTENAR, INTREQ, INTREQR).

Das Register ICR enthält dabei an der selben Adresse zwei Register. Beim 
Schreiben wird dabei wie bei den Custom Chip Registern durch ein Set/Clear-Bit
(Bit7 nicht Bit15) die Interrupt-Maske, also der entsprechende Interrupt 
freigegeben.

Beim Lesen des Registers ICR erfahren sie, welche Quelle einen Interrupt 
ausgelöst hat. Da, aber beim Lesen des Registers der Inhalt zurückgesetzt wird,
müssen sie, falls sie an mehreren Interruptquellen interessiert sind den Wert
zunächst zwischenspeichern und dann der Reihe nach abfragen. Nur so erfahren
sie z.B. ob es ein Timer A oder Timer B Interrupt war.

BIT	NAME	BESCHREIBUNG

07	IR		Bit das, falls gesetzt ist, anzeigt, dass ein Interrupt ausgeführt
			wird
06	0
05	0
04	FLG		ein negativer Übergang an FLAG setzt das FLAG-Interrupt-Bit
03	SP		Wenn gesetzt, befinden wir uns in einem von der Tastatur
			generierten Interrupt
02	ALRM	ToD		(Clock und Alarmzeit stimmen überein)
01	TB		Timer B (bei Unterlauf)
00	TA		Timer A (bei Unterlauf)

Durch Bit 4 (FLG) kann immer dann ein Interrupt ausgelöst werden wenn der /F 
Pin vom CIA auf Low gezogen wird.

Bei CIA-A wäre das der /STROBE Pin des Parallel Ports und bei CIA-B die /INDEX
Leitung vom Diskettenlaufwerk. Letztere wird allerdings in keiner mir bekannten
Disketten-Routine genutzt. Meistens nutzt man die Sync-Words um den Anfang 
eines Tracks zu finden.

CIAA Übersicht der Adressen
---------------------------------------------------------------------------
 Byte    Register                  Data bits
Addresse   Name     7     6     5     4     3     2     1    0
---------------------------------------------------------------------------

$BFED01    icr     CIAA interrupt control register
...
$BFDD00    icr     CIAB interrupt control register

ICR:	
					REG  NAME       D7   D6   D5   D4   D3   D2   D1  D0
					---  ----       ---- ---- ---- ---- ---- ---- --- ---	

(nur schreibend)	 D    ICR        S/C   x    x   FLG  SP   ALRM TB  TA
(nur lesend)		 D    ICR        IR    0    0   FLG  SP   ALRM TB  TA


In Listing27d.s wird der freie Timer A vom CIA-B so eingerichtet, dass er
alle 10ms bzw. in einem festen Frameraster einen INT6 Interrupt generiert.

Hinweise wie man die abgelaufene Zeit überprüfen kann bzw. wie man ein 
stabiles Raster erhält ist im Kommentar des Listings enthalten.

Und in Listing27d2.s wird eine kurze Interrupt-Routine erstellt die den 
10ms Interrupt als Basiszähltakt z.B. für eine Uhr in einer Variable zählt.
Die Timer selbst laufen im dabei continous-mode.

In Listings27d3.s arbeiten zwei Timer gleichzeitig im Interruptbetrieb. 
Timer A varriert zeitgesteuert die Anzahl der Rasterzeilen und Timer B die
Farbe in diesem Bereich. Auch ein spezieller Timer B INMODE kann durch das
Programm gezeigt werden. (Timer B counts Timer A underflow pulses)


*******************************************************************************
* Timer ToD																	  *	
*******************************************************************************

Der Timer ToD (Time of Day) hat nur aus historischen Gründen diesen Namen. 
Während im 6526 hier die Zeit BCD-codiert in den Registern steht und das 
Eingangssignal vom 50Hz/60Hz Stromnetz abgeleitet ist, werden beim 8520 Hsync 
oder Vsync-Signale gezählt.
CIA-A : 50/60 Hz event counter (VSync or line tick)
CIA-B : Horizontal sync event

Das Hsync-Signal tritt während der horizontalen Austastlücke und das Vsync-
Signal während der vertikalen Austastlücke auf. Der CIA 8520 TOD zählt binar
und der Wertebereich ist 24 Bit, d.h. von 0 bis $FFFFFF (16.777.215)

Da ein Frame 313 Zeilen hat treten also pro Frame 313 Hsync Ereignisse auf und
diese werden im TOD gezählt. Hsync bzw. Vsync ist somit die Zeitbasis, also der
Eingangstakt (oder ToD-Clock) des ToD. Strenggenommen sind es bei PAL pro 
Sekunde 50*312,5=15625 Hsync-Ereignisse.

Der TOD selber ist aber einerseits ein Zählregister und zwar ein Vorwärtszähler
im Unterschied zu Timer A oder Timer B und ein Alarmregister. Nun kann ein 
"Alarm" zu einem bestimmten Zeitpunkt in der Zukunft programmiert werden, der 
dann bei Erreichen des Zählerwertes (Zeitpunkt) einen Alarm auslöst und einen
Interrupt erzeugt.

Die Alarm Register befinden sich an denselben Adressen wie die entsprechenden
TOD-Register. Der Zugriff auf den Alarm wird durch ein Steuerregister-Bit 
geregelt und zwar über das Steuerregister CRB Bit 7.

CRB Bit7 Alarm - 1 writing to TOD registers sets Alarm
			   - 0 writing to TOD registers sets Clock 

*** Schreiben: ****
Für das ordnungsgemäße Setzen und Lesen von TOD, also bei der Einstellung der 
Zeit muss eine bestimmte Reihenfolge eingehalten werden. Durch einen 
Schreibvorgang in das MSB-Register todhi wird TOD gestoppt. Die Uhr wird erst 
wieder gestartet nach einem Schreibvorgang in das LSB-Ereignisregister todlo.
Dadurch wird sichergestellt, dass TOO immer zum gewünschten Zeitpunkt startet.

Reihenfolge beim Schreibvorgang:	
- High Byte (stoppt Timer), Middle, Low Byte (startet Timer)

*** Lesen: ****
Das Lesen von TOD gibt immer die "Live"-TOD clock, also die Zeit zurück. Der
Alarm ist dabei schreibgeschützt, d.h. bei jedem Lesen von TOD wird die Zeit 
unabhängig vom Zustand des ALARM-Zugriffsbits (CRB-Bit 7) gelesen.

Reihenfolge beim Lesevorgang:	
- High Byte (Latch aktiviert), Middle, Low Byte (Latch deaktiviert).
 Latch aktiviert meint, der Wert wird konstant gehalten.

Lesevorgang:
Da ein Übertrag von einer Stufe zur nächsten jederzeit in Bezug auf eine 
Leseoperation auftreten kann, ist eine Latching-Funktion enthalten, um alle
ToD-Informationen während einer Lesesequenz konstant zu halten. 

Wenn nur ein Register gelesen werden soll, gibt es kein Übertragsproblem, und
das Register kann "on the fly" gelesen werden, vorausgesetzt, dass auf jedes 
Lesen des MSB-Ereignisses ein Lesen des LSB-Ereignisses folgt, um die 
Verriegelung zu deaktivieren.

ToD-Einstellung:
Es bietet sich daher an die Register in folgender Reihenfolge zu beschreiben:
Erst die Alarmzeit und dann die "Uhrzeit".

						; hier wird der Alarm gesetzt
move.b  #$80,($f00,a5)	; $bfdf00 - CRB7 - 1-writing to TOD registers sets Alarm
move.b  d0,($a00,a5)	; $bfda00 - todhi - Hsync event counter bits 23-16
move.b  d0,($900,a5)	; $bfd900 - todmid - Hsync event counter bits 15-8
move.b  #255,($800,a5)	; $bfd800 - todlo - Hsync event counter bits 7-0
    
						; hier wird die Clockzeit gesetzt
move.b  d0,($f00,a5)	; $bfdf00 - CRB - 0 - writing to TOD reg. sets TOD clock
move.b  d0,($a00,a5)	; $bfda00 - todhi - Hsync event counter bits 23-16 
						; schreiben nach todhi stoppt die Uhr
move.b  d0,($900,a5)	; $bfd900 - todmid - Hsync event counter bits 15-8
move.b  #229,($800,a5)	; $bfd800 - todlo - Hsync event counter bits 7-0 
						; Die Uhr wird erst wieder gestartet nach einem 
						; Schreibvorgang in das LSB-Ereignisregister.


CIAA Übersicht der Adressen
---------------------------------------------------------------------------
 Byte    Register                  Data bits
Addresse   Name     7     6     5     4     3     2     1    0
---------------------------------------------------------------------------
$BFE801    todlo   Timer zu 50/60 Hz - Bits 7-0 (VSync or line tick)
$BFE901    todmid  Timer zu 50/60 Hz - Bits 15-8
$BFEA01    todhi   Timer zu 50/60 Hz - Bits 23-16
$BFED01    icr     CIAA interrupt control register
...
$BFD800    todlo   Timer für horizontale Synchronisation -  Bits 7-0
$BFD900    todmid  Timer für horizontale Synchronisation -  Bits 15-8
$BFDA00    todhi   Timer für horizontale Synchronisation -  Bits 23-16
$BFDD00    icr     CIAB interrupt control register

In Listing27e.s wird der Timer ToD des CIA-A als Vsync oder 50/60Hz 
Ereigniszähler verwendet um z.B. eine Zeit von 2s zu warten. (modifizierte 
Variante von Listing11n2.s)

1s mit Vsync sind 50 ticks
1s mit Hsync sind 312,5*50=15625 ticks => $00003D09
PAL: 50 Halbbilder pro Sekunde a 312,5 Zeilen=15625 Zeilen/s => bei 1s=1000ms

In Listing27e2.s wird gezeigt was durch den Timer ToD des CIA-B als Hsync
Ereignistrigger möglich ist. "ToD Rainbow"

Listing27e3.s ist nochmal Listing26b.s nur um zu zeigen, dass der Timer ToD
des CIA-B eingesetzt werden kann um die abgelaufene Zeit einer Routine in ms zu
ermitteln.

*******************************************************************************
* Keyboard																	  *	
*******************************************************************************

$BFEC01    sdr     CIAA serial data register (mit der Tastatur verbunden)

Ich verweise auf die Lektion 11 an dieser Stelle.

Listing27f.s		; Kopie - Listing11m1.s
Listing27f2.s		; Kopie - Listing11m2.s

 
*******************************************************************************
* Serial																  	  *	
*******************************************************************************

$BFDC00    sdr     CIAB serial data register (nicht verwendet)


*******************************************************************************
* Zusammenfassung CIA-A/-B Register - Besonderheiten						  *	
*******************************************************************************

Die CIA-Register sind im Gegensatz zu den Custom Chip Registern nicht über den
Copper, sondern nur über die CPU zugänglich und sie unterscheiden sich von den 
Custom Chip Registern auch dadurch, dass es keine Lese- und Schreibversionen 
von ausgewählten Registern wie z.B. DMACON, INTENA, INTEREQ gibt und der 
Zugriff erfolgt immer Byteweise.
Die meisten CIA-Register sind normale Lese-/Schreibregister. Nur die Interrupt-
und ToD-Register sind etwas Besonderes. Bei den Timerregistern wäre ansonsten
noch zu erwähnen, dass der geladene Zählerwert in einem Latch-Register
gepuffert steht.

CIA-A/CIA-B Übersicht der Adressen und Register
---------------------------------------------------------------------------
  Byte		  Byte		Register                  
Adresse		Adresse		Name		Debugger
 CIA-A		 CIA-B
---------------------------------------------------------------------------
$BFE001		$BFD000		pra			PRA
$BFE101		$BFD100		prb			PRB
$BFE201		$BFD200		ddra		DDRA
$BFE301		$BFD300		ddrb		DDRB
$BFE401		$BFD400		talo		TA	(+ Latch)
$BFE501		$BFD500		tahi    
$BFE601		$BFD600		tblo		TB	(+ Latch)
$BFE701		$BFD700		tbhi    
$BFE801		$BFD800		todlo		TOD	(Clock)		ALARM	(=> 2 Register)
$BFE901		$BFD900		todmid  
$BFEA01		$BFDA00		todhi   
$BFEB01		$BFDB00		Nicht verwendet
$BFEC01		$BFDC00		sdr			(SDR neu ab WinUAE 6.0)
$BFED01		$BFDD00		icr			ICR				IM		(=> 2 Register)
$BFEE01		$BFDE00		cra			CRA 
$BFEF01		$BFDF00		crb			CRB

Hinweis: 
Die CIAA kann einen INT2-Interrupt generieren, d.h. Lev.2, $68 und die CIAB
einen INT6-Interrupt, d.h. Level 6, $78.

WinUAE Debugger:
>c
A: CRA 00 CRB 08 ICR 00 IM 0a TA ffff (ffff) TB 0863 (0863)
   PRA c0 PRB 00 DDRA 03 DDRB 00 (SDR neu ab WinUAE 6.0)
   TOD 0009ca (0009ca) ALARM 000000 -- CYC=000000185C0B2A00
B: CRA 00 CRB 80 ICR 04 IM 00 TA ffff (ffff) TB ffff (ffff)
   PRA ff PRB ff DDRA c0 DDRB ff (SDR neu ab WinUAE 6.0)
   TOD 000069 (00ffff) ALARM 0000ac --
   
Bei der Debugger Ausgabe wären die Werte in den Klammern bei den Timern A und B
die gepufferten Latch-Werte, also die zuletzt in TA(B)HI,LO und ToD geladenen 
Werte. Ansonsten ist es der aktuelle Zählerstand. Bei den ToD-Register stehen
somit drei Werte: aktueller Zählerstand, (Latch) und die eingestellte Alarmzeit.

ICR enthält zwei Register an derselben Adresse, eines nur lesbar und eines nur 
schreibbar. Sie sind vollständig getrennt und zwar haben wir beim ICR die 
eingestellte Interrupt-Maske 'IM' die bestimmt welche Interrupts einen 
Interrupt anfordern können und ICR selbst zeigt die gemeldeten Interrupts an.

					 REG  NAME	 	    D7   D6   D5   D4   D3   D2   D1  D0
					 ---  ----		    ---- ---- ---- ---- ---- ---- --- ---
(nur schreibend)	 D    ICR => IM     S/C   x    x   FLG  SP   ALRM TB  TA
(nur lesend)		 D    ICR => ICR    IR    0    0   FLG  SP   ALRM TB  TA

WinUAE Debugger: IM	set interrupt mask, ICR	read and clear interrupt status

Beim Schreiben in ICR (Interrupt Enable) bestimmt S/C (Set/Clear) welches
Ereignis einen Interrupt auslösen kann, ähnlich z.B: INTENA. Beim Auslesen 
bestimmt Bit 7 'IR' ob ein Interrupt Request, also eine Interrupt-Anforderung
ausgelöst wurde. Das spezielle Bit zeigt dann auf die genaue Quelle.

Hinweis:
CIA's gehen bei der Bestätigung von IRQs anders vor, es ist nur das ICR-Lesen, 
das sie bereinigt, im Gegensatz zu PAULA, das explizit geschrieben werden muss.
Deshalb müssen Sie, wenn Sie an mehr als einer CIA-IRQ-Quelle interessiert 
sind, alle (gepufferten) Bits der Reihe nach überprüfen um herauszufinden, was
einen Interrupt generiert hat und nicht auf den nächsten Trigger warten, sonst 
verlieren Sie es!

Oder durch einfaches Lesen des ICR wird das	entsprechende Datenbit automatisch
gelöscht. Dadurch entfällt zwar das manuelle Löschen, aber Sie müssen die
Daten beim Lesen speichern, wenn Sie die Interrupts in einer Umgebung mit
mehreren CIA-Interrupts korrekt verarbeiten	möchten.

Lesen Sie zuerst ICR, um den CIA-Interrupt zu löschen, und schreiben Sie dann
in INTREQ, um den Paula-Interrupt zu löschen. Das erste Schreiben in INTREQ 
führt zu nichts, wenn der CIA-Interrupt noch aktiv ist. (Es wird sofort durch
den noch ungereinigten externen Zustand des CIA erneut ausgelöst).

Die richtige Reihenfolge ist:	(siehe Listing27d2.s)

	btst.b #0,$bfdd00		; zuerst ICR lesen --> löscht CIA-Interrupt
	beq.b .exit
	addi.l    #1,t10ms		; Interruptereignis bearbeiten oder zählen
.exit	
	move.w #$2000,$dff09c	; dann in INTREQ schreiben -> quittiert Interrupt
	rte		; die Maske der IRQs zurückgeben, die in der vorherigen Bedingung 
			; verwendet werden sollen - die internen SR-IP-Maskenbits

(Ein BTST ist ein vollständig gelesenes Byte, also eine ICR-Bestätigung.)

Nochmal:
Selbst wenn Sie also eine bestimmte Maske schreiben, enthält das Register beim
Lesen die "historische Situation" der Interrupt-Anfragen, auch derjenigen, die
sofort maskiert wurden. Das bedeutet, dass ausstehende Interrupts nach dem
Schreiben ausstehend bleiben.

ToD:
Der TOD selber ist einerseits ein Zählregister und ein Alarmregister.
Die Alarm Register befinden sich an denselben Adressen wie die entsprechenden
Clock-Register. Der Zugriff auf den Alarm wird durch ein Steuerregister-Bit 
geregelt und zwar über das Steuerregister CRB Bit 7.

CRB Bit7 Alarm - 1 writing to TOD registers sets Alarm
			   - 0 writing to TOD registers sets Clock 

*******************************************************************************
* Unterschiede 8520 zu CIA 6526 											  *	
*******************************************************************************

							8520		6526
ToD		zählweise			binär		BCD
ToD		Anzahl Register		3			4

8520 zählt einfach externe Ereignisse (24 Bit): 
Auf Amiga zählt CIA-A 50/60 Hz, CIA-B H-Sync.

Die Echtzeituhr (ToD) benutzt die 50- bzw. 60-Hz-Netzfrequenz als Referenz, die
Zeit kann beim 6526 und 8521 über vier Register (Zehntelsekunden, Sekunden, 
Minuten, Stunden) im BCD-Format ausgelesen werden. Beim 8520 kann der Timerwert
über drei Register ausgelesen werden. Zusätzlich kann eine Alarmzeit gesetzt
werden, bei deren Erreichen ein Interrupt ausgelöst wird.

Wenn cra/crb[3] gesetzt ist (Oneshot-Modus), startet das Schreiben in die
Timer-Hi-Register den Timer auf 8520, auf anderen startet er nicht.
Das gilt nur für den 8520.

6526 hat auch ein TODIN-Bit in CRA, das in 8520 nicht vorhanden ist, für eine
genaue Zeit von 50/60Hz.

*******************************************************************************
* Ende																		  *	
*******************************************************************************
