Magic Disk 64

home to index to text: MD9401-KURSE-IRQ-KURS_3.2.txt
4) DIE PROBLEME BEI RASTER-IRQS         

Wenn Sie unser eben beschriebenes Beispielprogramm einmal gestartet und angeschaut haben, so wird Ihnen sicher aufgefallen sein, daß die Farbbalken nicht ganz sauber auf dem Bildschirm zu sehen waren. Bei jedem Farbübergang flackerte der Bildschirm am linken Rand.
Dies ist eines der größten Probleme bei der Raster-Interrupt- Programmierung.
Dadurch nämlich, daß der Rasterstrahl mit einer Wahnsinnsgeschwindigkeit über den Bildschirm huscht können minimale Verzögerungen im Programm, wie zum Beispiel ein weiterer Befehl, bevor die Farbänderung geschrieben wird, verheerende Folgen haben. In unserem Beispiel werden die beiden Farben nämlich genau dann geändert, wenn sich der Rasterstrahl gerade am Übergang vom Bildschirmrahmen zum Bildschirmhintergrund befindet. Dadurch entstehen die kleinen Farbsteifen am linken Rand, wo die Rahmenfarbe schon auf den neuen Wert, die Hintergrundfarbe jedoch noch auf dem alten Wert steht. Erst wenn letztere ebenfalls geändert wurde, ist das Bild so wie gewünscht. Zusätzlich benötigt unsere Routine immer Unterschiedlich viel Rechenzeit, da sie einige Branch-Befehle enthält, die je nach Zutreffen der abgefragten Bedingung 2 oder 3 Taktzyklen dauern, weswegen die Farbstreifen unruhig hinund herspringen. Zusätzlich kann es passieren, daß kurzfristig einer der drei Farbbereiche nicht richtig eingeschaltet wird, und dann der ganze Balken flackert. Dieser Fall tritt dann ein, wenn Rasterund CIA-Interrupt kurz hintereinander auftreten und ein gerade bearbeiteter Raster-IRQ durch den CIA-IRQ nochmals unterbrochen wird. Die Routine kann also noch erheblich verbessert werden! Stellen Sie doch einmal die Farbänderung jeweils an den Anfang der entsprechenden Unterroutine, und sperren Sie gleichzeitig mittels " SEI" das Auftreten weiterer IRQs. Die Flackereffekte sollten sich dadurch schon um einiges vermindern, aber dennoch werden Sie nicht ganz verschwinden. Das liegt hauptsächlich an unserer Verzweigungsroutine, die zwischen VICund CIA-IRQ unterscheidet.
Da sie für den Rasterstrahl nicht unerheblich Zeit verbraucht wird immer irgendwo eine Assynchronität festzustellen sein.
Sauberer soll das nun mit unserem nächsten Programmbeispiel gelöst werden.
Hier wollen wir ganz einfach den Betriebssystems-IRQ von CIA1 ganz unterbinden, und ihn quasi über den Raster-IRQ ' simulieren' . Zusätzlich soll die Abfrage nach der Rasterzeile, die den Interrupt auslöste wegfallen, so daß wenn unsere Routine angesprungen wird, immer gleich die gewünschte Farbe eingestellt werden kann. Da wir daraufhin auch keine Abfragen mittels Branch-Befehlen in unserem Interrupt-Programm haben, wird die Routine immer mit der gleichen Laufzeit ablaufen, weswegen unruhiges Zittern wegfallen wird. Hier nun zunächst das Beispielprogramm. Sie finden es auf dieser MD als ausführbaren Code unter dem Namen " RASTERDEMO2" . Es wird ebenso geladen und gestartet wie unser erstes Beispiel:

;*** Initialisierung                    
Init:                                   
  sei          ;IRQs sperren            
  lda #$7f     ;Alle Bits im CIA-ICR    
  sta $dc0d    ;löschen (CIA-IRQs)      
  lda $dc0d    ;CIA-ICR löschen         
  lda #$00     ;Rasterzeile 0 als Inter-
  sta $d012    ; ruptauslöser festlegen 
  lda $d011    ;Bit 7 in $D011          
  and #$7f     ; löschen.               
  sta $d011                             
  lda #$01     ;Rasterstrahl als Inter- 
  sta $d01a    ; rupt-quelle definieren 
  ldx #<(irq1) ;IRQ-Vektor bei $0314/   
  ldy #>(irq1) ; $0315 auf erste        
  stx $0314    ; Interrupt-             
  sty $0315    ; Routine verbiegen      
  cli          ;IRQs wieder freigeben   
  rts          ;ENDE!                   

;*** Erster Interrupt

irq1:                                   
  lda #$70     ;Zeile $70 als Auslöser  
  sta $d012    ; für nächsten IRQ festl.
  dec $d019    ;VIC-IRR löschen         
  ldx #<(irq2) ;IRQ-Vektor auf          
  ldy #>(irq2) ; zweite Interrupt-      
  stx $0314    ; Routine                
  sty $0315    ; verbiegen              
  lda #$00     ;Rahmen u. Hintergrund   
  sta $d020    ; auf 'schwarz'          
  sta $d021    ; setzen                 
  jmp $febc    ;IRQ beenden             
;*** Zweiter Interrupt                  
irq2:                                   
  lda #$C0     ;Zeile $C0 als Auslöser  
  sta $d012    ; für nächsten IRQ festl.
  dec $d019    ;VIC-IRR löschen         
  ldx #<(irq3) ;IRQ-Vektor auf          
  ldy #>(irq3) ; dritte Interrupt-      
  stx $0314    ; Routine                
  sty $0315    ; verbiegen              
  lda #$00     ;Rahmen u. Hintergrund   
  sta $d020    ; auf 'rot'              
  sta $d021    ; setzen                 
  jmp $febc    ;IRQ beenden             
;*** Dritter Interrupt                  
irq2:                                   
  lda #$C0     ;Wieder Zeile 0 als Aus- 
  sta $d012    ; löser für IRQ festl.   
  dec $d019    ;VIC-IRR löschen         
  ldx #<(irq1) ;IRQ-Vektor wieder auf   
  ldy #>(irq) ; erste Interrupt-        
  stx $0314    ; Routine                
  sty $0315    ; verbiegen              
  lda #$00     ;Rahmen u. Hintergrund   
  sta $d020    ; auf 'gelb'             
  sta $d021    ; setzen                 
  jmp $ea31    ;Betr.sys.-IRQ anspringen

Die Initialisierungsroutine dieses Beispiels unterscheidet sich kaum von dem des ersten Programms. Wir setzen auch hier Zeile 0 als Auslöser für den ersten IRQ und verbiegen den IRQ-Vektor auf die erste IRQ-Routine mit dem Namen " IRQ1" .
Ganz am Anfang jedoch unterbinden wir alle CIA1- IRQs, indem wir durch Schreiben des Wertes $7 F alle Bits des CIA-ICRs löschen, womit wir alle von CIA1 auslösbaren IRQs sperren. Das anschließende Auslesen des ICRs dient dem ' freimachen' der CIA, falls dort noch eine Interruptanforderung vorliegen sollte, die nach Freigeben der IRQs ja sofort ausgeführt und so in unsere Raster-IRQ- Routine1 springen würde.
Die Interrupt-Routine selbst wird nun wirklich nur dann aufgerufen, wenn sich der Rasterstrahl in Zeile 0 befindet.
Deshalb können wir hier gleich, ohne große Abfragen durchführen zu müssen, Zeile $70 als nächsten Interruptauslöser festlegen und die Bildschirmfarben ändern. Damit hier nun ebenfalls die richtige Routine angesprungen wird, verbiegen wir den IRQ-Vektor noch auf die Routine " IRQ2", die speziell den Interrupt bei Zeile $70 behandeln soll.
Sie verfährt genauso mit dem dritten Interruptauslöser, Rasterzeile $ C0, für die die Routine " IRQ3" zuständig ist.
Sie biegt den IRQ-Vektor nun wieder zurück auf " IRQ1", womit das ganze von vorne beginnt. Eine Neuheit ist hier übrigens das Löschen des VIC-IRRs. Um selbiges zu tun, hatten wir in letztem Beispiel ja einen Schreibzuriff auf das Register durchführen müssen. Dies tun wir hier mit dem Befehl " DEC $ D019" . Er hat den Vorteil daß er kürzer und schneller ist als einzelnes ein Lesen und Schreiben des Registers und zudem kein Prozessorregister in Anspruch nimmt, in das wir lesen müssen.
Wie Sie nun sehen werden ist unsere Flagge nun nicht mehr von Flackererffekten gebeutelt. Die Farbbalken sind sauber durch horizontale Linien voneinander getrennt. Versuchen Sie jetzt doch einmal ein paar andere Farbkombinationen, oder vielleicht auch mehr Rasterbalken zu erzeugen. Oder kombinieren Sie doch einmal Hiresgrafik mit Text. Die Möglichkeiten solch recht einfacherer Raster-IRQs sind sehr vielseitig, und warten Sie erst einmal ab, wenn wir zu komplizierteren Routinen kommen. Dies wird im nächsten Monat dann schon der Fall sein, wenn wir per Rasterstrahl die Bildschirmränder abschalten werden. Bis dahin viel Spaß beim Rasterprogrammieren!
( ub)

Valid HTML 4.0 Transitional Valid CSS!