
; Listing27d.s - Timer A von CIA B einstellen um einen INT6 interrupt alle 10ms zu generieren

	SECTION	CIA,CODE

;	include	"DaWorkBench.s"	; entferne das; vor dem Speichern mit "wo"

*****************************************************************************
	include	"/Sources/startup2.s"	; Speichern Sie Interrupt, DMA und so weiter.
*****************************************************************************

; Mit DMASET entscheiden wir, welche DMA-Kanäle geöffnet und welche geschlossen werden sollen

			;5432109876543210
DMASET	equ	%1000000000000000	; kein DMA aktivieren

WAITDISK	equ	30				; 50-150 zur Rettung (je nach Fall)
;MICS:		equ	7093			; 10ms => (*100/second)
MICS:		equ 4*14209			; alle 4 frames (1 bis 4 frames) durch probieren

Start:
	lea		$dff000,a6			; Custom-Chip-Base
	lea     $bfd000,a5			; CIAB - Base
	move.w  #$7fff,$9a(a6)		; $00dff09a - INTENA - all off

	move.l	BaseVBR(pc),a0	    ; in a0 ist der Wert des VBR	
	move.l	#MyInt78,$78(a0)	; ich lege meinen Interrupt-Level 6 fest
		
	move.w	#DMASET,$96(a6)		; DMACON - aktivieren kein DMA								
	
; um den Timer-Interrupt in den nicht sichtaberen Bereich zu verlegen, warten wir hier
WarteY:							
	move.l	4(a6),d0			; $dff004 - VPOSR/VHPOSR
	andi.l	#$1ff00,d0			; wirkt sich nur auf die Bits der vertikalen Zeile aus
	cmpi.l	#$01000,d0			; warte auf Zeile  $10
	bne.s	WarteY

	bsr CiaInit					; Level6 Interrupt vorbereiten

	move.w	#$e000,$9a(a6)		; INTENA - "Exter"-Interrupt aktivieren per Level 6 ($78)		

Mouse:
	btst	#6,$bfe001			; Maus gedrückt? (Der Prozessor 
	bne.s	Mouse				; unterbricht die Schleife alle 10ms um die Farbe zu ändern

	move.w  #$6000,$9a(a6)		; $00dff09a - INTENA CLEAR/INTEN/EXTER
	move.b  #$01,$d00(a5)		; $00bfdd00 - ICR - CIAB interrupt control register 
								; (lösche TA-Flag)

	rts							; Exit

*******************************************************************************
* In dieser Routine wird der CIA-B Timer A voreingestellt			          *
*******************************************************************************

	; Reihenfolge:
	; CRA, CIA-B		- Steuerregister festlegen
	; TALO/Hi, CIA-B	- Timerwert vorladen
	; INTENA, INTREQ	- Interrupts festlegen und Anforderungen löschen
	; ICR, CIA-B		- Interrupt TA freigeben
	; CRA, CIA-B		- Timer TA starten

CiaInit:	
	move.b  $e00(a5),d0				; $bfde00 - CRA, CIA-B
	andi.b   #%11000000,d0			; setzt Bit 0-5 zurück, Bit 3=0 - runmode continuous
	move.b  d0,$e00(a5)				; CRA - Steuerregister festlegen
	  
	move.b  #(MICS&$ff),$400(a5)	; TALO - Setzen Sie das Low-Byte der Zeit
	move.b  #(MICS>>8),$500(a5)		; TAHI - Setzen Sie das High-Byte der Zeit
	
	move.w  #$7fff,$9a(a6)			; INTENA - disable all interrupts
	move.w  #$7fff,$9c(a6)			; INTREQ - clear all pending interrupts
	
	move.b  #$7f,$d00(a5)			; ICR, CIA-B - alle aus	
	move.b  #$81,$d00(a5)			; ICR, CIA-B - nur TA ein	
	move.w  #$e000,$9a(a6)			; INTENA - Bit 15, 14, 13

	bset.b  #0,$e00(a5)				; CRA, CIA-B - Start timer!!
	rts
	
*******************************************************************************
*	INTERRUPT-Routine  $78 (Level 6) - Timer A CIA-B						  *
*******************************************************************************

; 13 EXTER 6 ($78)	Input/Output Port und Timer, verbunden mit INT6-Leitung

myInt78:
	movem.l	d0-d7/a0-a6,-(sp)	; speichern der Register auf dem Stack
	move.w	$1c(a6),d1			; INTENAR in d1
	btst.l	#14,d1				; Bit Master Toggle zurückgesetzt?
	beq.s	NoInt6				; wenn ja, Interrupt ist nicht aktiv!
	and.w	$1e(a6),d1			; INREQR - in d1 bleiben nur die Bits gesetzt
								; die in INTENA und INTREQ gesetzt sind
								; um sicher zu sein, dass wenn der Interrupt
								; auftritt, auch aktiviert war.

	btst.l	#13,d1				; INTREQR - EXTER?
	beq.w	NoInt6

	; es handelt sich um einen 'gültigen' Level 6 - Interrupt - Exter
Exter:
	move.b	$bfdd00,d0			; CIA-B ICR - ist es ein Interrupt von Timer A?
								; (durch Lesen von ICR, verursachen wir
								; auch seine Nullsetzung, so ist der Interrupt
								; "gelöscht" wie in INTREQ).

	btst	#0,d0				; Bit TA, (Interrupt CIA), zurückgesetzt?
	beq.w NoInt6
IntTA:	
	; wenn wir hier sind war es ein Timer A Interrupt
	lea     Colors(pc),a0		; Colors-Base nach a0
    move.w  (a0),d0				; aktueller Zählerwert auslesen (ist Offsetwert und Farbwert)   
    addq.w  #2,d0				; Zählerwert wird immer um zwei erhöht, steht somit bei Beginn auf 0, dann 2 usw.
    cmpi.w  #8*14*2-2,d0		; mit "Ende" vergleichen ob 112 Farbwerte = $de
    bne.b   NoBounce			; solange ungleich überspringen
	moveq   #0,d0				; Zählerwert auf Null zurück
NoBounce: 
	move.w  d0,(a0)+			; aktuellen Zählerwert zurückschreiben und aufs nächste Wort zeigen 
    adda.w  d0,a0				; Adresse auf aktuellen Farbwert erhöhen
	move.w  (a0),$180(a6)		; $00dff180 - Farbe setzen
			
NoInt6:
	move.w  #$2000,$dff09c		; INTREQ Anfrage entfernen, int ausgeführt!
	movem.l	(sp)+,d0-d7/a0-a6	; wiederherstellen der Register vom Stack

	rte

Colors:
    dc.w          -2,$0110,$0220,$0330,$0440,$0550,$0660,$0770
    dc.w        $0880,$0990,$0aa0,$0bb0,$0cc0,$0dd0,$0ee0,$0ff0
    dc.w        $0ff0,$0fe0,$0fd0,$0fc0,$0fb0,$0fa0,$0f90,$0f80
    dc.w        $0f70,$0f60,$0f50,$0f40,$0f30,$0f20,$0f10,$0f00
    dc.w        $0f00,$0f01,$0f02,$0f03,$0f04,$0f05,$0f06,$0f07
    dc.w        $0f08,$0f09,$0f0a,$0f0b,$0f0c,$0f0d,$0f0e,$0f0f
    dc.w        $0f0f,$0e0f,$0d0f,$0c0f,$0b0f,$0a0f,$090f,$080f
    dc.w        $070f,$060f,$050f,$040f,$030f,$020f,$010f,$000f
    dc.w        $000f,$001f,$002f,$003f,$004f,$005f,$006f,$007f
    dc.w        $008f,$009f,$00af,$00bf,$00cf,$00df,$00ef,$00ff
    dc.w        $00ff,$00fe,$00fd,$00fc,$00fb,$00fa,$00f9,$00f8
    dc.w        $00f7,$00f6,$00f5,$00f4,$00f3,$00f2,$00f1,$00f0
    dc.w        $00f0,$00e0,$00d0,$00c0,$00b0,$00a0,$0090,$0080
    dc.w        $0070,$0060,$0050,$0040,$0030,$0020,$0010,0


*****************************************************************************

	SECTION	GRAPHIC,DATA_C

Copperlist:						; hier nicht benötigt
	dc.w	$100,$200			; BPLCON0 - keine Bitplanes
	dc.w	$180,$00e			; COLOR00 blau
	dc.w	$ffff,$fffe			; Ende Copperlist

	end


; $bfde00
; CIA:	ICR  (Interrupt Control Register)				[d]
;
; 0	TA			underflow
; 1	TB			underflow
; 2	ALARM		TOD alarm
; 3	SP			serial port full/empty
; 4	FLAG		flag
; 5-6			unused
; 7  R			IR
; 7  W			set/clear
;
; $bfdd00 
; CIA:  CRA, CRB  (Control Register)					[e-f]
;
; 0		Start		0 = stop / 1 = start TA; {0}=0 when TA underflow
; 1		PBON		1 = TA output on PB / 0 = normal mode
; 2		OUTMODE		1 = toggle / 0 = pulse
; 3		RUNMODE		1 = one-shot / 0 = continous mode
; 4	  S	LOAD		1 = force load (strobe, always 0)
; 5   A	INMODE		1 = TA counts positive CNT transition
;					0 = TA counts 02 pulses
; 6   A	SPMODE		serial port....
; 7   A	unused
; 6-5 B	INMODE		00 = TB counts 02 pulses
;					01 = TB counts positive CNT transition
;					10 = TB counts TA underflow pulses
;					11 = TB counts TA underflow pulses while CNT is high
; 7   B	ALARM		1 = writing TOD sets alarm
;					0 = writing TOD sets clock
;					Reading TOD always reads TOD clock

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

Die abgelaufene Zeit kann man auch selbst berechnen. 
>g
Breakpoint 0 triggered.
Cycles: 35465 Chip, 70930 CPU. (V=6 H=137 -> V=162 H=190)

35465*281,94ns=10ms

Um ein stabiles Raster zu erhalten:
1 Frame: 141476 cycles -> Cycles: 70738 Chip, 141476 CPU
70738*281,94 ns=19,94ms --> 20ms
141476/10=14148 ticks                   ; Bitplane auf 0 Lowres
