Magic Disk 64

home to index to html: MD9401-KURSE-IRQ-KURS_3.2.html
4) DIE PROBLEME BEI RASTER-IRQS         
Wenn Sie unser eben  beschriebenes  Bei-
spielprogramm einmal gestartet und ange-
schaut  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  Bildschirmhinter-
grund 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  hin-   und   her-
springen. Zusätzlich kann es  passieren,
daß kurzfristig  einer  der  drei  Farb-
bereiche  nicht  richtig   eingeschaltet
wird,  und   dann   der   ganze   Balken
flackert. Dieser Fall  tritt  dann  ein,
wenn  Raster-  und  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 VIC- und 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  Bei-
spiels 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 $7F 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!