Magic Disk 64

home to index to html: MD9102-KURSE-CIA-KURS_TEIL_4.2.html
            IRQ-Kurs Teil 4.2           
Wollen wir uns nun einmal anschauen, wie
unser  NMI-Programm  aufgebaut  ist. Die
NMIs werden übrigens über  Timer  A  der
CIA2  ausgelöst,  der denselben Wert wie
der Timer des System-IRQs als  Startwert
bekommt (das wäre der Wert 16420=$4024).
Hier also das Programm:                 
----------  NMI vorbereiten             
LDA $7F     "NMI-Quellen sperren" laden,
STA DD0D    und in ICR von CIA2.        
LDX #$2B    Zeiger auf eigene...        
LDY #$90    ...Routinen laden,          
STX 0318    und NMI-Vektor...           
STY 0319    ...setzen.                  
LDX #$24    Timerwert LO-Byte.          
LDY #$40    Timerwert HI-Byte.          
STX DD04    In TALO und...              
STY DD05    ...in TAHI schreiben.       
LDA #$81    Wert laden...               
STA DD0D    Timer A als Interruptquelle 
            festlegen.                  
STA DD0E    Timer A starten.            
----------  SID einstellen.             
LDA #$0F    Wert 15 für volle Lautstärke
STA D418    ...ins Lautstärkeregister.  
LDA #$00    Zählregister für Tonfrequenz
STA 02      initialisieren.             
RTS         Und zurück.                 
----------  NMI-Routine                 
CLI         IRQs wieder freigeben.      
PHA         Akku,                       
TXA         X-,                         
PHA                                     
TYA         und Y-Register auf Stapel   
PHA         retten.                     
LDA #16     Wert für "Dreieckswelle aus"
STA D404    ...in SID schreiben         
LDA 02      Zähler für Frequenz lesen...
STA D401    und in Frequenz-HI schreiben
INC 02      Zähler um 1 erhöhen.        
LDA #17     Wert für "Dreieckswelle an" 
STA D404    ...in SID schreiben.        
LDA DD0D    NMIs wieder freigeben       
PLA         Akku,                       
TAY         X-,                         
PLA                                     
TAX         und Y-Register wieder vom   
PLA         Stapel zurückholen.         
RTI         Und Interrupt verlassen     
----------                              
Im ersten Teil dieses Listings haben wir
die Initialisierungsroutine für  unseren
NMI.  Hier werden zunächst auf die schon
beschriebene Art und Weise  alle  Inter-
ruptquellen die von der CIA2 kommen, ge-
sperrt. Anschließend wird der NMI-Vektor
bei $0318/$0319 auf unsere eigene Routi-
ne  verbogen  (die  Routine  beginnt bei
$9000 im Speicher, weshalb die eigentli-
che Interruptroutine bei $902B beginnt).
Ist  dies getan, müssen wir als nächstes
den Timerwert in die  Timerregister  für
Timer  A  laden  (wie bei CIA1 sind dies
die Register 4 und 5 - TALO  und  TAHI).
Dies ist der wie oben schon beschriebene
Wert  $4024.  Jetzt  müssen wir nur noch
den Timer A als NMI-Interruptquelle set-
zen  und  ihn anschließend starten. Dies
geschieht in den folgenden 3 Zeilen. Was
der Wert $81 für Register 13  (ICR)  und
14  (CRA)  bedeutet  wissen Sie ja schon
aus Teil 1 dieses Kurses, als ich  Ihnen
die Funktionen dieser  Register  genauer
erläutert habe.                         
Zum Abschluß der Initialisierungsroutine
müssen wir auch noch den SID darauf vor-
bereiten,  Sound  auszugeben. Dazu haben
wir auch noch genug Zeit, da  der  schon
laufende  Timer  zum  nächsten Interrupt
noch lange genug zählen wird (ich  hätte
die  SID-Initialisierung auch vorher an-
bringen können). Also wird  erst  einmal
die  Lautstärke  des  Soundchips  einge-
schaltet, sowie den  Anfangsfrequenzwert
für unseren Soundeffekt in  Adresse  $02
in der Zeropage geschrieben.            
Diese Adresse wird als Zählregister  be-
nutzt,  da  man auf die Register des SID
leider nicht zum Lesen  zugreifen  kann.
Somit  sind  sie also auch nicht mittels
INC hochzählbar. Nun sind alle  Voreins-
tellungen  getätigt, und wir können wie-
der zum aufrufenden Programm  zurückver-
zweigen.                                
Im zweiten Teil des Listings  sehen  Sie
nun  die  NMi-Routine selbst. Als erstes
erlauben wir hier wieder  das  Auftreten
von  IRQs  (sie  erinnern  sich, das Be-
triebssystem hatte sie ja gesperrt). Nun
werden nach der mittlerweile schon  alt-
bekannten  Methode die Prozessorregister
auf den Stapel  gerettet,  was  wir  bei
NMIs ja IMMER von Hand machen müssen, da
das   Betriebssystem  uns  diese  Arbeit
leider nicht abnimmt.                   
Nun  kommt  der Teil, in dem der nächste
Ton gespielt wird. Hierzu wird erst ein-
mal  die  Stimme 1 des SID abgeschaltet.
Dies ist notwendig, weil wir keine Hüll-
kurve  vorher festgelegt hatten, die ei-
nen Ton möglicherweise dauerhaft spielen
würde.  Deshalb  befinden  sich  in  den
Hüllkurvenregistern  die  Werte  0,  was
bedeutet, daß ein Ton nur ganz kurz  an-
geschlagen  wird  und gleich wieder ver-
stummt. Damit man aber die nächste  Fre-
quenz  nun  hört  müssen  wir die Stimme
also erst noch ausschalten. Anschließend
wird der Inhalt des Zählregisters $02 in
das HI-Byte-Frequenzregister von  Stimme
1  geschrieben  ($D401),  und der Zähler
für den nächsten Interrupt um 1  erhöht.
Nun schalten wir Stimme 1 wieder an, und
zwar  mit einer Dreieckswellenform - der
Ton wird nun gespielt.                  
Die  Arbeit  des  NMIs ist getan, machen
wir uns also  daran,  den  Interrupt  zu
beenden.  Ebenso  altbekannt werden also
das ICR wieder freigegeben, die  Prozes-
sorregister zurückgeholt und mittels RTI
der NMI beendet.                        
So. Nun wissen Sie also alles wissenwer-
te über NMIs. Bis auf einige kleine Aus-
nahmen, können  Sie  diese  Interruptart
genauso behandeln, wie einen IRQ. Da die
CIAs  ja  baugleich sind, fällt die CIA-
gesteuterte Programmierung von  NMIs  ja
ebenso aus, wie beim IRQ.               
Ein ebenfalls ganz interessantes  Anwen-
dungsgebiet  von  NMIs ist die Steuerung
von gewiseen Funktionen über einen Druck
auf die  RESTORE-Taste.  Ich  habe  dies
einmal  bei  einem Apfelmännchenprogramm
benutzt. Diese  Programme  berechnen  ja
bekanntermaßen  Grafiken aus der Mandel-
brotmenge, die zwar ganz ansehlich sind,
deren  Berechnung  jedoch  oft  Stunden,
wenn  nicht  sogar Tage dauern kann. Ich
wollte nun eben jenes Programm beschleu-
nigen, indem ich den Bildschirm abschal-
te.  Wie  Sie  vielleicht  wissen,  kann
durch  diese  Maßnahme eine Geschwingig-
keitssteigerung von 5%  erzielt  werden,
da der VIC bei abgeschaltetem Bildschirm
micht  mehr  auf den Speicher des Compu-
ters zugreifen muß,  um  die  Daten  für
Grafiken, Zeichen, Sprites und ähnliches
zu holen. Dadurch stört er den Prozessor
nicht  mehr beim Zugriff, wodurch dieser
schneller arbeiten kann. Das Problem war
nun  jedoch,  daß  ich  weiterhin  sehen
wollte, wie weit der Rechner nun mit der
Grafikberechnung  fortgefahren  ist. Mit
einer  einfachen  NMI-Routine  war  dies
möglich.  Ohne  noch zeitraubend die Ta-
statur abzufragen, habe ich einfach  ei-
nen neuen NMI "eingekoppelt", der nichts
anderes  tut,  als  den Bildschirm aus-,
bzw. einzuschalten, wenn man die  RESTO-
RE-Taste  drückt. Dieser Trick läßt sich
vielfältig anwenden und ist  einfach  zu
programmieren, hier das kleine Programm:
-----------------  Initialisierung      
MAIN LDA #$7F      CIA2-NMIs...         
     STA CIA2+13   sperren.             
     LDX #<(NMI)   NMI-RAM-Vektor       
     LDY #>(NMI)   ...auf eigene        
     STX $0318     ...NMI-Routine       
     STY $0319     ...verbiegen.        
     RTS           Tschüß!              
-----------------  NMI-Routine          
NMI  PHA           Akku retten.         
     LDA $D011     Register laden,      
     EOR #16       Bildschirmbit inver- 
                   tieren.              
     STA $D011     Und wieder speichern.
     PLA           Akku zurückholen.    
     RTI           NMI-Ende.            
-----------------                       
Das ist tatsächlich alles! Das  Programm
ist  im "Hypra-Ass"-Quellcode angegeben,
dessen Sonderfunktionen ich Ihnen letzen
Monat ja schon erklärte. Hier eine Doku-
mentation:                              
Im  ersten Teil wird zunächst einmal die
CIA2 als Interruptquelle gesperrt.  Dies
ist  nicht  unbedingt  notwendig, da sie
sowieso ausgeschaltet sein  sollte,  je-
doch  habe  ich  es  hier zur Sicherheit
einmal  gemacht.  Desweiteren  wird  der
NMI-Vektor  auf unseren eigenen NMI ver-
bogen, und die Initialisierung ist been-
det.                                    
Nun zum zweiten  Teil:  Zunächst  einmal
rette  ich  hier nur den Akku. X- und Y-
Register werden in der  NMI-Routine  so-
wieso  nicht  benutzt,  weshalb  wir sie
nicht unbedingt auch noch retten müssen.
Als nächstes laden wir  den  Inhalt  von
Register 17 des VIC ($D011=dez.53265) in
den Akku, da mit dem 4. Bit dieses Regi-
sters der  Bildschirm  ein-  und  ausge-
schaltet  wird.  Der Inhalt dieses Regi-
sters wird nun einfach mit dem Wert  des
4.  Bits geEORt. Dabei wird der Wert des
Bits immer invertiert. Ist es 1  (=Bild-
schirm  an),  so  wird  es nach dem EOR-
Befehl 0 (=Bildschirm aus) sein und  um-
gekehrt.  Der neue Wert muß nun nur noch
wieder in $D011 zurückwandern,  und  wir
können den NMI beenden.                 
Das  Programm  finden  Sie übrigens auch
auf dieser  MD  unter  dem  Namen  "NMI-
SCREENOFF".  Es muß absolut (",8,1") ge-
laden werden und wird mit SYS 49152  ge-
startet.  Ab dann können Sie per Tasten-
druck auf RESTORE  den  Bildschirm  nach
Belieben ein- und ausschalten.          
Das  war  es  dann man wieder für diesen
Monat. Ich wünsche Ihnen noch viel  Spaß
beim  herumexperimentieren  mit den NMIs
und seien Sie  nicht  enttäuscht,  wenns
mal  nicht  auf  Anhieb  klappen sollte,
denn: Wer noch nie einen  Rechnerabsturz
erlebt  hat, ist kein wahrer Programmie-
rer!                                    
In diesem Sinne bis nächsten Monat,     
                   Ihr Uli Basters (ub).



Valid HTML 4.0 Transitional Valid CSS!