Magic Disk 64

home to index to text: MD9109-KURSE-CIA_TEIL_3.txt

Kommen wir nun zu dem Programm selbst.
Hier ist der kommentierte Source-Code:

****************************************
start   sei           IRQs sperren      
        ldx #<(irq)   IRQ-Vektor        
        ldy #>(irq)    auf neue         
        stx $0314      IRQ-Routine      
        sty $0315      verbiegen.       
        ldx #<(nmi)   NMI-Vektor        
        ldy #>(nmi)    auf neue         
        stx $0318      NMI-Routine      
        sty $0319      verbiegen.       

ldx #$83 Timer A und B als stx cia1+13 Interruptquelle für stx cia2+13 beide CIAs setzen

        lda #00       Timer B von       
        sta cia1+6     CIA1             
        sta cia1+7     und              
        sta cia2+6     CIA2 mit dem Wert
        sta cia2+7     0 initialisieren.
        ldy #$90      Timer A von CIA2  
        sta cia2+4     initialisieren   
        sty cia2+5     ($9000=27 IRQs/s)
        lda #$21      Trigger=CNT und "T
                       mer Start"       
        sta cia1+15    in Control-Regist
        sta cia2+15    für Timer B von  
                       CIA1 und CIA2.   
        lda #$81      Timer A von CIA2  
        sta cia2+14    mit SysTakt als  
                       Trigger starten  
        lda #00       Bildschirm-       
        sta 53280      farben           
        lda #11        setzen           
        sta 53281      und              
        lda #<(text)   Begrüßungs-      
        ldy #>(text)   Text             
        jsr strout     ausgeben.        
        lda #01       Sprite 0          
        sta vic+39    als               
        sta vic+21    Maus-             
        lda #150      pfeil             
        sta vic       ini-              
        sta vic+1     tiali-            
        lda #41       sieren.           
        sta 2040                        
        cli          IRQs freigeben     
        rts          und ENDE.          
****************************************
nmi     pha          Alle               
        txa           Prozessorregister 
        pha           erstmal           
        tya           auf Stapel        
        pha           retten.           
        cli           IRQs freigeben.   
        lda $dd01    Datenport sporadis 
        eor #$ff     laden und invertie 
        sta mem      merken.            
        lda cia2+13  ICR von CIA2 holen 
        and #$02     Bit 1 isolieren    
        beq buttons  Wenn =0, dann war  
                      Timer A der NMI-  
                      Auslöser,   also  
                      Knopfabfrage.     
        lda mem      Sonst H-Bewegung.. 
        and #$08     Bit für HQ-Signal  
                       aus Datenport iso
                       lieren           
        beq moveleft  Wenn 0 war ->links
        bne moveright Wenn 1 war ->rechs
buttons lda mem      Aus Datenport die  
        and #$30     Bits 4 und 5 (Mau  
                     knöpfe) isolieren  
        beq bye      Wenn =0, dann war  
                     ner gedrückt.      
        and #$20    Sonst Bit5 isolier  
        beq leftone Wenn =0, war der    
                       linke gedrückt   
        lda #42     Spritepointer       
        ldx #01      und Timerwert lad  
l8      sta 2040     und setzen.        
        stx cia1+6   (Timerwert in BEI  
        stx cia2+6   CIAs!)             
        jmp bye      NMI beenden.       
leftone lda #41     Spritepointer und   
        ldx #00     Timerwert für link  
        jmp l8      Taste setzen        
****************************************
irq    lda cia1+13  ICR von CIA1 laden  
       and #$02     Bit 1 isolieren     
       bne ok       Wenn =1, dann wars  
                     ein Maus-IRQ       
       jmp sysirq   Sonst auf SysIRQ    
                     springen           
ok     cli          IRQs freigeben      
       lda $dd01    Datenport laden und 
       eor #$ff      invertieren.       
       and #$04     Bit für VQ-Signal   
                     isolieren          
       beq moveup   Wenn 0 war -> hoch  
       bne movedown Wenn 1 war -> runter
****************************************

Hier nun noch einige Erläuterungen:
1) Wie Sie sehen, müssen wir bei NMIs den Prozessorregister " von Hand" auf den Stapel retten. Bei NMIs geschieht dies nicht durch eine Routine im Betriebssystem, so wie es bei den IRQs der Fall war.
2) Nachdem eine der beiden Interruptroutinen aufgerufen wurde, wird so früh wie möglich das IRQ-Flag wieder gelöscht und die IRQs zugelassen. Das ist deshalb so wichtig, weil die IRQs beim Auftreten eines Interrupts ( sei das ein IRQ oder ein NMI) gesperrt werde. Befindet sich nun aber der Rechner gerade in einem NMI, während die Maus der Vertikalen bewegt wird, so wird kein IRQ ausgelöst, weil dieser ja noch gesperrt ist. Um das doch noch zu ermöglichen müssen wir den IRQ explizit freigeben.
Bei NMIs brauchen wir darauf nicht zu achten, weil NMIs ja nicht maskierbar sind. Das heißt, daß ein NMI immer einen NMI unterbrechen kann!
3) Denken Sie bitte nach wie vor daran daß die Daten der Datenports invertiert in den CIA-Registern stehen. Wir müssen sie beim Lesen deshalb gleich nochmal invertieren. Das ist gerade bei der Maustastenabfrage sehr wichtig, weshalb der Datenport in jedem Fall erst einmal invertiert wird, bevor eine Entscheidung getroffen wird, woher der NMI überhaupt kam.
Bei der Vertikalabfrage, hätte ich den Datenport nicht unbedingt invertieren müssen. Da hier lediglich nur ein eimziges Bit abgefragt wird, hätte ich die Branchbefehle zu den Bewegungsroutinen ebenso vertauschen k nnen. Der Vollständigkeit halber wird hier der Wert jedoch ebenfalls invertiert.
4) Sicher hat Sie die merkwürdige Mausbutton abfrage etwas verwirrt. Ich habe hier noch eine kleine Funktion eingebaut die durch die Art unserer Abfrage ganz einfach zu programmieren wurde.
Zunächst einmal wird durch den Druck auf einen der Mausknöpfe der Spritpointer zwischen den Spriteblöcken 00 und 42 hinund hergeschaltet. Dies nur, um Ihnen die Mausbuttonabfrage optisch zu signalisieren. Zusätzlich wird, je nach dem welchen Knopf sie noch drücken, ein anderer Wert in die Timer-Register geschrieben. Drücken Sie die linke Taste, so ist das der Wert 0, wie wir es für die Abfrage ja schon vereinbart hatten. Drücken Sie jedoch die rechte Maustaste, so wird der Wert 1 in die Timer geladen. Durch diesen kleinen, aber effektiven Trick können wir die Mausauflösung halbieren. Dadurch, daß nun 2 Impulse von der Maus kommen müssen, bis ein Interrupt auftritt müssen Sie die Maus doppelt wait über den Tisch bewegen, um den Mauspfeil eine bestimmte Strecke weg zu bewegen. Das kann oftmals kanz nützlich sein, z. B. wenn man genau zeichnen muß.
Wenn Sie brigens den Wert 2 die Timer schreiben, so verkleinet sich die Auflösung um ein Drittel und so fort. . .
5) Achten Sie bitte auch auf die Abfragen in den Interruptroutinen, von welchen Quelle der Interrupt kam. Im ICR sind dann n mlich die entsprechenden Bits die auch beim Einstellen der Interrupquellen benutzt werden gesetzt. So können wir also unterscheiden, von wo ein Interrupt kam.
6) Die Routinen MOVELEFT, MOVERIGHT, MOVE-UP und MOVEDOWN sind Routinen die den Mauspfeil bewegen und sollen hier nicht näher erläutert werden. Sie können Sie sich aber gerne im Source-Listing " AM GA-MAUS3 . SRC" auf dieser MD anschauen 7) Das Label ENDIRQ enthüllt die Adresse $ EA7 E. Ab dieser Adresse stehen im Betriebssystem die Befehle, mit denen jeder Interrupt ( auch NMIs) beendet werden. Es werden einfach die Prozesorregister wieder vom Stapel geholt.
Um unsere eigenen Interrupts zu beenden springe ich also der Einfachheit halber gleich diese Adresse an.
Natürlich brauchen Sie zum Betrieb der neuen Mausabfrage einen neuen Adapterstecker. Damit das nicht allzu umständlich wird, habe ich die Belegungen im Großen und Ganzen so gelassen wie sie beim erst Adapterstecker waren. Sie müssen lediglich zwei Leitungen umlöten:

* Das V-Signal ( Pin 1 an der Joyportbuchse) kommt jetzt an CNT1(= Pin 4 am Userport - vorher Pin C) .

* Das H-Signal ( Pin 2 an der Joyportbuchse) kommt jetzt an CNT2(= Pin 6 am Userport - vorher Pin D) .
Schließen Sie den neuen Stecker nun bei abgeschaltetem 64 er am Userport an, und stecken Sie eine AMIGA-Maus am anderen Ende ein. Jetzt können Sie das Programm " AMIGA-MAUS3" von dieser MD laden und mit RUN starten. Wie Sie sehen, können Sie nun auch weiterhin Eingaben machen, da der Cursor weiterhin blinkt. Denken Sie nun daran, daß es bei Diskettenzugriffen Probleme geben wird, da die NMIs den Datenverkehr stören( sollten Sie noch aus dem ersten Teilen dieses Kurses wissen) .
In solchen Fällen ist es ratsam die Abfrage doch abzuschalten ( z. B. indem man die Timer einfach anhält, oder sie als Interruptquellen sperrt) .
Zum Schluß möchte ich Ihnen noch eine weitere Funktion der CIAs erklären. Nur mit dem Userport erhält sie überhaupt einen Sinn, weshalb ich sie bis jetzt auslassen mußte.
Vielleicht erinnern Sie sich noch daran, daß das Register 12 einer CIA das sogenannte " Serial-Data- Register" ist. Mit diesem Register kann über die SP-Leitung ( die ja von beiden CIAs am Userport anliegt) ein einfacher serieller Datenaustausch mit einem anderen Rechner( im einfachsten Fall ebenfalls ein 64' er stattfinden. Das kann sehr nützlich sein wenn man z. B. ein Spiel programmieren möchte, bei dem zwei Spieler an jeweils einem eigenen Rechner gegeneinander spielen Wenn das Spielprogramm also Daten über die Tätigkeiten und Bewegungen des anderen Spielers benötigt.
Über das SD-Register wird dieser Datenaustausch stark vereinfacht und ist fast noch unkomplzierter, als wenn man sich der normal Seriellen Schnittstelle ( RS232) des Betriebssystems bedient.
Bei der Datenübertragung müssen wir unterscheiden, ob die SP-Leitung nun auf Ein oder Ausgang geschaltet ist. Dies wird mit Bit 6 des Control-Registers- Timer A ( Reg.14) angegeben. Ist es auf 1, so ist SP auf Ausgang, ist es auf 0, so ist SP auf Eingang geschaltet. Je nach Betriebsart verhält sich die Benutzung von SDR wie folgt:

* Wenn SP Ausgang ist, so wird ein Wert, der in das SDR geschrieben wird mit der halben Unterlauffrequenz von Timer A in den entsprechenden CIA an SP " herausgesch ben" . Das heißt, daß der Wert Bit für Bit, bei jedem Timerunter lauf an SP e scheint. Nach 8 Unterläufen ist SDR wi der leer und es wird ein Interrupt ausgelöst. Bit3 im ICR zeigt an, daß der Interrupt von dem leeren SDR-Regist kommt.

* Wenn SP Eingang ist, so wird mit jeder steigenden Flanke an CNT der entsprechende CIA der Wert, der gerade anliegt (0 oder 1) in ein internes Schieberegister übernommen. Ist dies Mal ge- schehen, so wird der Wert in das SDR übertragen und ebenfalls ein Interrupt ausgelöst. Hier erkennt man ebefalls an Bit 3 im ICR, daß das SDR voll ist und ausgelesen werden kann.
Kombiniert man das Ganze jetzt noch mit der Möglichkeit, daß die CIA bei einem Timerunterlauf ein Signal an PB6 anlegen kann, so kann man sehr einfach Daten austauschen. Möchten Sie z. B. Daten an einen anderen C64 senden, so müssen Sie sich ein Kabel bauen, daß die Userporte der beiden Rechner miteinander verbindet.
Dabei sollte der SP-Ausgang von Rechnern mit dem SP-Eingang von Rechner 2 verbunden sein und die Leitung PB6 von Recher1 mit der Leitung CNT von Rechner2( ob SP1 oder SP2, bzw. CNT1 oder CNT2 hängt davon ab mit welcher CIA sie die Daten übertragen wollen) .
Jetzt müssen Sie im Control-Register von Timer A ( des sendenden Rechners) noch festlegen, daß das Signal an PB6 bei jedem Timerunterlauf in die jeweils andere Lage gekippt werden soll. Das geschieht, indem Sie die Bits 1 und 2 dieses Registers auf 1 setzen. Dadurch erscheint nämlich ebenfalls mit der halben Unterlauffrequenz von Timer A( des sendenden Rechners) ein Signal an PB6 und läst somit die Datenübernahme am empfangenden Rechner aus!
Das war es dann endgültig mit dem CIA-Kurs. Ich hoffe, daß Sie nun einen besseren Einblick in die Funktionen dieser beiden kleinen, aber extrem mächtigen Bausteine innerhalb unseres Rechners haben. Wie Sie sehen lassen sich sehr viele Probleme mit Interrupts leichter lösen ( wie die Mausabfrage beweist) . Zusätzlich können Sie mit dem Userport vielf ltige Har wareerweiterungen leicht und einfach bedienen.
Ich freue mich also, wenn es Ihnen ein wenig Spaß gemacht hat und bi n für Kritik und Anregungen zu neuen Kursen immer zu haben ( auch ein kleiner Kursautor kriegt gerne Leserpost) .

   Bis auf Weiteres also ein letztes Mal
"Servus"                                
                   Ihr Uli Basters (ub) 

Valid HTML 4.0 Transitional Valid CSS!