, . . , Dendy ( , , , . .)
geektimes.ru/post/281520, Raspberry pi. , Nintendo Classic Mini, — . 4 , . , . , , , .
, .
Es gibt kein Geheimnis, dass dieses Gamepad sowohl mit Wii als auch mit Wii U verbunden werden kann, was bedeutet, dass es über die i2c-Schnittstelle abgefragt werden kann. Erfreulich ist, dass das Gamepad mit 3,3 V betrieben wird, sodass Sie sich nicht um die Anpassung der Spannungspegel kümmern müssen. Um das Gamepad mit dem Raspberry Pi zu verbinden, habe ich beschlossen, Anschlüsse für Wiimote auf Aliexpress zu kaufen, die von ihm auf die Platine gelötet werden. Obwohl das Paket zwei Anschlüsse enthielt und diese sich in einer gemeinsamen Blase befanden, war einer der Anschlüsse in einem schlechten Zustand. Keine Dose kann hier nicht. Nachdem alles gelötet war, musste überprüft werden, ob dies funktioniert. Dafür habe ich mich entschieden, die Dienstprogramme aus dem i2c-tools-Paket zu verwenden. Die Idee war, das Gerät unter der Adresse 52 zu bestimmen. Nachdem ich i2cdetect gestartet hatte, sah ich den Schatz:i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: 03 04 05 06 07 -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- 52 -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Mein Herz wurde sofort wärmer (als ob ein unbekanntes Mädchen dich im Frühjahr auf einer Straße anlächelte), also funktioniert es. Als nächstes mussten Sie googeln, um Peripheriegeräte mit der Wii zu verbinden. Ich habe ein Beispiel gefunden, wie sich ein Wii-Nunchak mit einem Himbeer-Pi verbindet. In diesem Beispiel habe ich herausgefunden, dass das Gamepad initialisiert werden muss, indem Null in das 0x40-Register geschrieben wird und dann jedes Mal kurz vor dem Lesen, wenn Sie nur eine Null schreiben und die ersten 6 Bytes lesen müssen.In diesem Fall stand ich auch vor der Wahl einer Bibliothek für i2c. Da ich mit der bcm2835-Bibliothek nicht erfolgreich war, habe ich mich für die im Beispiel verwendete Bibliothek entschieden - dies ist die WirinPi-Bibliothek. Alles hat mit ihr geklappt. Empirisch fand ich heraus, dass die Schaltflächeninformationen in 4 und 5 Bytes enthalten sind (wenn Sie Bytes von Null zählen). Informationen zu den Schaltflächen Auswählen, Starten, Abwärts, Rechts befinden sich im vierten Byte, und Informationen zu den Schaltflächen A, B, Aufwärts und Links befinden sich im fünften Byte. Darüber hinaus befinden sich die Informationen zu den Auswahltasten unten rechts in den oberen 4 Bits des Bytes und die Informationen zu den Starttasten unten. Gleiches gilt für das 5. Byte, die Informationen zu den Schaltflächen A, B befinden sich in den oberen 4 Bits des Bytes und die Informationen zu den Schaltflächen oben links in den unteren. Hier sind die Schaltflächencodes: A - 0xcf, B - 0xbf, up - 0xf0, left - 0xf1, select - 0xcf, start - 0xf3, down - 0xbf, right - 0x7f.Das Ergebnis des gemeinsamen Drückens von Tasten, deren Informationen sich in einem Byte und in denselben Bits befinden, ist ein logisches „UND“ ihrer Codes. Wenn Sie beispielsweise die Tasten A und B gleichzeitig drücken, erhalten Sie den Wert 0x8f.Hier ist ein Link zur Tabelle:
Als nächstes habe ich ein kleines Testprogramm zum Lesen von Schaltflächen geschrieben. Im Folgenden werde ich es vollständig auflisten und erklären, was damit passiert:#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <errno.h>
char i, a, b, c, d, state;
char bytes[6];
int main(void) {
wiringPiSetup();
int fd = wiringPiI2CSetup(0x52);
wiringPiI2CWriteReg8(fd, 0x40, 0x00);
delayMicroseconds(20);
while(1)
{
state = 0;
wiringPiI2CWrite(fd, 0x00);
delayMicroseconds(100);
for (i=0; i<6; i++)
{
bytes[i] = wiringPiI2CRead(fd);
}
a = bytes[5] >> 4;
b = bytes[5] << 4;
c = bytes[4] >> 4;
d = bytes[4] << 4;
if (a == 0xc)
state ^= (1 << 0);
if (a == 0xb)
state ^= (1 << 1);
if (c == 0xc)
state ^= (1 << 2);
if (d == 0x30)
state ^= (1 << 3);
if (b == 0x00)
state ^= (1 << 4);
if (c == 0xb)
state ^= (1 << 5);
if (b == 0x10)
state ^= (1 << 6);
if (c == 0x7)
state ^= (1 << 7);
printf("%x \n", state);
}
return 0;
}
Zu Beginn werden Variablen deklariert, mit deren Hilfe der Status einer bestimmten Schaltfläche ermittelt wird. Es ist wichtig, dass die Variablen vom Typ char sind. Andernfalls werden bei einer bitweisen Verschiebung nach links nur 4 Nullen hinzugefügt, und das war's. Die Interpretation wird falsch sein. Egal wie lustig es klingt, Sie müssen den Zauber verwenden .Als nächstes wird im Hauptteil des Programms die WiringPi-Bibliothek initialisiert - wiringPiSetup (); und dann wird die i2c-Adresse des Geräts auf 0x52 gesetzt. Als nächstes wird die Steuerung initialisiert:
wiringPiI2CWriteReg8(fd, 0x40, 0x00);
delayMicroseconds(20);
Nun, dann werden bereits im Hauptteil der Schleife 6 Bytes gelesen, und vor dem Lesen wird jedes Mal Null geschrieben. Danach wird der gedrückte Knopf bestimmt. Im Allgemeinen wurde der gesamte Code in die Emulatordateien migriert.Wie beim letzten Mal wird die Initialisierung der Bibliothek in der Datei fceu.c registriert:
int FCEUI_Initialize(void)
{
if(!FCEU_InitVirtualVideo())
return 0;
memset(&FSettings,0,sizeof(FSettings));
FSettings.UsrFirstSLine[0]=8;
FSettings.UsrFirstSLine[1]=0;
FSettings.UsrLastSLine[0]=231;
FSettings.UsrLastSLine[1]=239;
FSettings.SoundVolume=100;
FCEUPPU_Init();
X6502_Init();
wiringPiSetup();
return 1;
}
Nun und weiter betreffen alle Änderungen nur die Datei input.c. Zunächst werden in der Funktion FCEUI_Initialize (void) int die Betriebsmodi des GPIO-Ports für die Arbeit mit dem alten Gamepad (von Simba) festgelegt und das Gamepad initialisiert.
pinMode (0, OUTPUT);
pinMode (2, OUTPUT);
pinMode (3, INPUT);
digitalWrite (0, HIGH);
digitalWrite (2, LOW);
fd = wiringPiI2CSetup(0x52);
wiringPiI2CWriteReg8(fd, 0x40, 0x00);
usleep(20);
Zu Beginn müssen Sie auch Variablen deklarieren, die das Drücken der Taste bestimmen.In der statischen DECLFW (B4016) -Funktion wird ein Strobe für das alte Gamepad mitgeliefert, der neue Strobe wird nicht benötigt:
if (LastStrobe==0)
{
digitalWrite (0, LOW);
}
Beim Erstellen eines Testprogramms konnte ich das Problem der Identifizierung von zusammengedrückten Tasten, deren Informationen sich in einem Byte und in einem Bit befinden, nicht lösen. Am Ende habe ich das Switch-Case-Konstrukt anstelle von if else angewendet.Nun, die Funktion selbst ist die Funktion zum Lesen des Status der Tasten:
void FCEU_UpdateInput(void)
{
joy[0] = 0;
joy[1] = 0xff;
wiringPiI2CWrite(fd, 0x00);
usleep(100);
for (i = 0; i <= 7; i++)
{
bytes[i] = wiringPiI2CRead(fd);
joy[1] ^= digitalRead(3) << i;
digitalWrite (2, HIGH);
delayMicroseconds (20);
digitalWrite (2, LOW);
delayMicroseconds (20);
}
a = bytes[5] >> 4;
b = bytes[5] << 4;
c = bytes[4] >> 4;
d = bytes[4] << 4;
switch (a){
case 0xc:
joy[0] ^= (1 << 0);
break;
case 0xb:
joy[0] ^= (1 << 1);
break;
case 0x8:
joy[0] ^= (1 << 0);
joy[0] ^= (1 << 1);
break;
}
switch (b){
case 0x00:
joy[0] ^= (1 << 4);
break;
case 0x10:
joy[0] ^= (1 << 6);
break;
case 0x20:
joy[0] ^= (1 << 4);
joy[0] ^= (1 << 6);
break;
}
switch (c){
case 0xc:
joy[0] ^= (1 << 2);
break;
case 0xb:
joy[0] ^= (1 << 5);
break;
case 0x7:
joy[0] ^= (1 << 7);
break;
case 0x8:
joy[0] ^= (1 << 2);
joy[0] ^= (1 << 5);
break;
case 0x4:
joy[0] ^= (1 << 2);
joy[0] ^= (1 << 7);
break;
case 0x3:
joy[0] ^= (1 << 5);
joy[0] ^= (1 << 7);
break;
}
switch (d){
case 0x30:
joy[0] ^= (1 << 3);
break;
}
digitalWrite (0, HIGH);
}
In einem Zyklus habe ich das Lesen von Schaltflächen von beiden Gamepads kombiniert. Nun, denken Sie, dass 2 zusätzliche Bytes gelesen werden. Es spielt keine Rolle, aber alles geschieht gleichzeitig. Und es gibt keine Verzögerungen.Im Allgemeinen ist alles in Ordnung.PS: Soweit ich mich erinnere, morgen bei der Arbeit schon verzerrt.PPS Ich habe vergessen, dass Sie für eine erfolgreiche Kompilierung im Makefile (das nach Ausführung des Befehls Configure erstellt wurde) im Verzeichnis src -lwiringPi -lm -lrt an der Stelle hinzufügen müssen, an der die Bibliotheksabhängigkeiten geschrieben werden. Zeile:LIBS =