Home Stecker und Schnittstellen am Falcon F030 VME-Bus Interface Falcon - Umbau
 

12.15 Jaguar Pad am Falcon


Das Jaguar Pad am Falcon



An erster Stelle finden Sie Beispiele dafür wie man das JaguarPad am Atari Falcon per Software abfragt. Die Beispiele sind für PureC

JAGUAR.PRJ
1: jaguar.tos
2:
3       .C [ -Y ]
4:      .L [ -Y -L ]
5:
6: =
7:
8:      pcstart.o
9:
10: main.c
11:     jagstick.c
12:
13:     PCSTDLIB.LIB
14:     PCTOSLIB.LIB 1: /*



MAIN.C
1: */
2: */Testprogramm für Jaguar Controller-Abfrage
3: */
4:
5:      #include <stdlib.h>
6:      #include <screen.h>
7:      #include <stdio.h>
8:      #include "jagstick.h"
9:
10: #define PORT 1 /* Port l(B) wird abgefragt
11:
12:     void main(void)
13:     {
14:     for(;;)
15: {
16:     req_jagpads();
17: Cur_home();
18:     if (jpstatus[PORT].up) printf("U");
19:     if (jpstatus[PORT].down) printf("D");
20:     if (jpstatus[PORT].left) printf("L");
21:     if (jpstatus[PORT].right) printf("R");
22:     if (jpstatus[PORT].fire-a) printf("A");
23:     if (jpstatus[PORT].fire-b) printf("B");
24:     if (jpstatus[PORT).fire-c) printf("C");
25:   if (jpstatus[PORT).k0) printf("0");
26:     if (jpstatus[PORT).kl) printf("1");
27:     if (jpstatus[PORT].k2) printf("2");
28:     if (jpstatus[PORT].k3) printf("3");
29:     if (jpstatus[PORT].k4) printf ("4");
30:     if (jpstatus[PORT].k5) printf("5");
31:     if (jpstatus[PORT].k6) printf ("6");
32:     if (jpstatus[PORT].k7) printf("7") ;
33:     if (jpstatus[PORT].k8) printf("8");
34:     if (jpstatus[PORT].k9) printf("9");
35:     if (jpstatus[PORT].ks) printf("*");
36:     if (jpstatus[PORT].kr) printf ("#");
37:     if (jpstatus[PORT].pause) printf("P");
38:         printf("                                  ");
39:     if (jpstatus[PORT].option) break;
40:  }
41:
42:      exit(0);





JAGSTICK.H
1: /*
2:      /* Headerfile fürs Abfragen der Jaguarjoypads
3:      /*
4:
5:      typedef struct
6:      {
7:      int up,down,left,right : 1; /* Zustände der Richtungen */
8:      int fire_a,fire_b,fire_c : 1; /* Zustände der Feuerknöpfe */
9:      int pause,option : 1; /* Zustände von Option/Feuer */
10:   int k1,k2,k3,k4,k5,k6,k7,k8,k9,k0,kr,ks: 1;
11:     /* Zustände der Tastatur am JoyPad */
12:     /* kr = # und ks = * */
13:     } JAGPAD;
14:
15:  extern JAGPAD jpstatus[2];
16:




JAGSTICK.C
1: /*
2:      /* Routinen zum Abfragen der Jaguarjoypads
3:      /*
4:
5:      #include <tos.h>
6:      #include "jagstick.h"
7:
8:      #define NULL (void*)0|
9:
10:     #define adr(a) *((int *)(a))
11:
12:
13:     #define bitwert(a) (l<<a)       /* liefert 2^a */
14:     #define EXREGO Oxffff9200|
15:     #define EXREG1 Oxffff9202|
16:     #define test(var 17: bit)((var&bitwert(bit))==0?-1:0)
18:     /* liefert -1
19:     wenn das Bit bit
20:     in der Variable var
21:     gelöscht ist */
22:
23:     JAGPAD jpstatus[2];
24:     /* Hier wird das Ergebnis gespeichert */
25:     void req_jagpads(void)
26:     {
27:     int r0,rl;
28:
29:     long oss;
30:
31:     oss=Super(0|); /* SuperVisorMode an */
33:     adr(EXREG1)=~(bitwert(0)+bitwert(4)); /* $ffff9202=NOT(2^0+2^4) */
34:     r0=adr(EXREG0);/* r0 = Inhalt von $ffff9200 */
35:     r1=adr(EXREG1);/* rl = Inhalt von $ffff9202 */
36:
37:     jpstatus[0].up=test(r1,8);
38:
39:     jpstatus[0].down=test(r1,9);
40:
41:     jpstatus[0].ieft=test(r1,10);
42:
43:     jpstatus[0].right=test(r1,11);
44:
45:     jpstatus[0].pause=test(r0,0);
46:
47:     jpstatus[0].fire_a=test(r0,1);
48:
49:     jpstatus[l].up=test(r1,12)
50:
51:     jpstatus[l].down=test(r1,13);
52:
53:     jpstatus[l].left=test(r1,14);
54:
55:     jpstatus[l].right=test(r1,15);
56:
57:     jpstatus[l].pause=test(r0,2);
58:
59:     jpstatus[l].fire_a=test(r0,3);
60:
61:
62:     adr(EXREG1)=~(bitwert(l)+bitwert(5)); /* $ffff9202=NOT(2^1+2^5) */
63:     r0=adr(EXREG0);/* r0 = Inhalt von $ffff9200 */
64:     r1=adr(EXREG1);/* rl = Inhalt von $ffff9202 */
65:
66:     jpstatus[0].ks=test(r1,8);
67:
68:   jpstatus[0].k7=test(r1,9);
69:
70:     jpstatus[0].k4=test(r1,10);
71:
72:     jpstatus[0].kl=test(r1,11);
74:     jpstatus[0].fire_b=test(r0,1);
75:
76:     jpstatus[l].ks=test(r1,12);
77:
78:     jpstatus[l].k7=test(r1,13);
79:
80:     jpstatus[l]. k4 = test(rl, 1 4);
81:
82:     jpstatus[1]. kl =test(r1,15);
83:
84:     jpstatus[l]. fire_b = test(r0,3);
85:
86:
87:     adr(EXREG1) =~(bitwert(2) + bitwert(6)); /* $ffff9202=NOT(2^2+2^6) */
88:     r0=adr(EXREG0);/* r0 = Inhalt von $ffff9200 */
89:     r1=adr(EXREG1);/* r1 = Inhalt von $ffff9202 */
90:
91:     jpstatus[0].k0=test(r1,8);
92:
93:     jpstatus[0].k8=test(r1,9);
94:
95:   jpstatus[0].k5=test(r1,10);
96:
97:   jpstatus[0].k2=test(r1,11);
98:
99:     jpstatus[0].fire-c=test(r0,1);
100:
101:    jpstatus[l].k0=test(r1,12);
102:
103:    jpstatus[l].k8=test(r1,13);
104:
105:    jpstatus[l].k5=test(r1,14);
106:
107:    jpstatuslll.k2=test(r1,15);
108:
109:    jpstatus[l].fire_c=test(r0,3);
110:
111:
112:    adr(EXREG1)=~(bitwert(3)+bitwert(7));/* $ffff9202=NOT(22+26) */
113:    r0=adr(EXREG0);/* r0 = Inhalt von $ffff9200 */
114:    r1=adr(EXREG1);
115:    /* rl = Inhalt von $ffff9202 */
116:    jpstatus[0].kr=test(r1,8);
117:
118:    jpstatus[0].k9=test(r1,9);
119:
120:    jpstatus[0].k6=test(r1,10);
121:
122:    jpstatus[0].k3=test(r1,11);
123:
124:    jpstatus[0].option=test(r0,1);
125:
126:    jpstatus[l].kr=test(r1,12);
127:
128:    jpstatus[l].k9=test(r1,13);
129:
130:    jpstatus[l].k6=test(r1,14);
131:
132:    jpstatus[l].k3=test(r1,15);
133:    jpstatus[l].option=test(r0,3);
134:    Super((void*)oss);
135:    /* SuperVisorMode aus */



Wie frage ich den Jaguar-Controller am Falcon030 / STE ab?

Daß man den Jaguar-Controler in irgend einer Form auch an den Falcon oder STE anschließen kann ist naheliegend. Wie die Abfrage aber konkret geschehen muß, wird hier kurz erläutert.

Jeder, der einen Jaguar und einen Falcon030 bzw. STE besitzt wird festgestellt haben, daß die analogen Joyports vollkommen identisch sind. Wie man den Computern beibringt, den Controller auch auszuwerten, soll dieser Artikel zeigen. Nun, zunächst einmal ist man ja versucht, einfach diverse Spiele, die den erweiterten Joyport nutzten, auszuprobieren. Doch leider muß man schnell feststellen, daß zwar irgendwelche Signale vom Computer empfangen werden, so daß der Protagonist des entsprechenden Spielchens entweder an Orientierungslosigkeit leidet und rennt oder ziellos umherrennt und nicht dort hin, wohin man drückt, oder er springt nicht, weil der gedrückte Feuerknopf nicht als solcher erkannt wird. Also Fehlanzeige?

Überlegt und nachgezählt...

Der Joyport hat ja nur 15 Pins, obwohl der Controller 21 Schaltelemente hat. Nun, es muß also einen Trick geben. Da war doch noch etwas wie - klar, man kann die ext. Joyports als Ein- und Ausgänge benutzen. Damit kann man dann so etwas wie eine Matrix implementieren, bei der man einfach dem Controller sendet, welchen Status der Tasten man gerne hätte - und zurück bekommt man einen entsprechenden Code. Genauso hat sich Atari das auch gedacht. Das Ganze ist wirklich ähnlich wie die Sound-/DMA-Matrix geschaltet. Matrizen ziehen sich also durch das gesamte Innenleben des Falcon. Kommen wir zum Wesentlichen.

$FFFF9200 [R/W] word ext. Joystick Fire Buttons (Bits 0-3)

$FFFF9202 [R/W] word ext. Joystick Directions (Bits 0-15)

Diese wurden somit umdefiniert. $FFFF9200 wird zwar weiterhin für die Firebuttons verwendet, jedoch kommen die Buttons "Option" und "Pause" hinzu. Also muß müssen hier fünf Buttons mit 2 Bits codiert sein. Auch die restlichen 16 Schalter im Jaguar Controller sind mit jeweils nur 4 Bit im Register $FFFF9202 geschaltet. Der grobe Ablauf des Abfragens der JoyPorts bzw. des Controllers ist jetzt also in etwa wie folgt:


1. Abzufragende Leitungen in Register $FFFF9202 schreiben
2. Richtungs- und Tastatur-Status in $FFFF9202 (wie bei 1.) auslesen
3. Button-Status $FFFF9200 auslesen


Dabei ist allerdings zu beachten, daß die entsprechend angeführten Register low-aktiv sind, d.h. ein gelöschtes Bit bedeutet "gedrückt" bzw. "ist abzufragen". Kommen wir also zu der mächtigen Matrix, um die sich alles dreht.

Um z.B. den Status von Feuerknopf B aus JoyPort B zu ermitteln, sendet man auf $FFFF9202 den Wert NOT(2^7)=$FF7F (d.h. man schreibt den Wert in das entsprechende Register), liest dann den Wert von $FFFF9200 aus, und überprüft, ob das Bit 5 mit der Wertigkeit 2^5 gelöscht ist. Wenn dies der Fall ist, ist der Feuerknopf gedrückt.

Analog gilt für ein anderes Beispiel folgendes (diejenigen, die es begriffen haben, können diesen Absatz überspringen): Angenommen, wir wollen wissen, ob an Port A das Pad noch oben gedrückt ist. Senden wir also auf $FFFF9200 den Wert NOT(2^0)=$FFFE, dann fragen wir das Register $FFFF9200 auf Gelöschtheit des Bits 8 ab. Ist es gelöscht, so wurde nach oben gedrückt.

Daß die gesamten Zugriffe auf die Hardware-Register im "Supervisormodus" zu erfolgen haben, sollte wohl klar sein. Man sieht, es sind 4 Abfragen für das gesamte JoyPad notwendig, aber das ist es doch wert, oder?

Noch eine Bitte an alte, die diese großartigen Pads jetzt supporten wollen: Bitte macht Eure Sache konfigurierbar, so daß Video-Erweiterungsbesitzer (wie ich) auswählen können, in welchen Port sie den Joystick stecken wollen, zumal es auch andere Erweiterungen gibt, die bestimmte Paddleports brauchen, z.B mit Screenblaster oder einer SpeedResoloution Karte.

Der abgedruckte Sourcecode soll die ganze Vorgehensweise noch etwas durchleuchten. Er wurde mit Pure C erstellt, und es wurde darauf geachtet, daß keine speziellen Befehle, die eine Portierung in andere Sprachen erschweren würden, verwendet wurden.

Carsten Tolkmit




Abbildung 1 - Innenschaltung des Jaguar Pads








Copyright © Robert Schaffner (support@doitarchive.de)
Letzte Aktualisierung am 23. Dezember 2003
Home Stecker und Schnittstellen am Falcon F030 VME-Bus Interface Falcon - Umbau