Les vacances se terminent, ce qui signifie qu'il est temps de regretter le foie et de tourner la tête. Une autre idée m'est donc venue à l'esprit. Après avoir connecté la manette de jeu de Dendy (c'est un joystick, c'est un contrôleur, c'est un joystick, c'est une console de jeu, etc.) geektimes.ru/post/281520 , j'ai pensé à connecter une seconde à Raspberry pi. Je ne voulais pas acheter la deuxième camelote avec des boutons de blocage, et ici, au fait, j'ai été jetée sur les étagères de la Nintendo Classic Mini, eh bien, comme ils l'ont jetée - vous achèterez du raifort. Le but n'était pas d'acheter un émulateur pour 4K, mais j'ai décidé d'acheter une manette de jeu. Heureusement, j'ai réussi à l'acheter, c'était la dernière du magasin. Ceux qui sont intéressés par ce qui en est arrivé peuvent cliquer sur le bouton ci-dessous.Voici un lien direct vers la preuve , si la régulière n'est pas activée.
Il n'y a pas de secret pour personne que cette manette de jeu peut être connectée à la fois à la Wii et à la Wii U, ce qui signifie qu'elle peut être interrogée via l'interface i2c. Ce qui est encourageant, c'est que la manette de jeu est alimentée par 3,3 V, ce qui signifie que vous n'avez pas à vous soucier des niveaux de tension correspondants. Pour connecter la manette de jeu au Raspberry pi, j'ai décidé d'acheter des connecteurs pour wiimote sur aliexpress, qui sont soudés sur la carte de lui. Bien qu'il y ait 2 connecteurs dans l'emballage et qu'ils se trouvaient dans une bulle commune, l'un des connecteurs est tombé en ruine. Aucun bidon ne peut faire ici. Après que tout a été soudé, il a fallu vérifier si cela fonctionne. Pour cela, j'ai décidé d'utiliser les utilitaires du package i2c-tools. L'idée était de déterminer l'appareil à l'adresse - 52. Après avoir lancé i2cdetect, j'ai vu le précieux: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: -- -- -- -- -- -- -- --
Mon cœur s'est immédiatement réchauffé (comme si une fille inconnue vous souriait dans une rue au printemps), alors ça marche. Ensuite, vous deviez google pour connecter des périphériques à la Wii. J'ai trouvé un exemple de la façon dont un nunchak Wii se connecte à un Raspberry pi. À partir de cet exemple, j'ai découvert que la manette de jeu doit être initialisée en écrivant zéro dans le registre 0x40, puis juste avant de lire chaque fois que vous avez juste besoin d'écrire un zéro et de lire les 6 premiers octets.Dans ce cas, j'ai également été confronté au choix d'une bibliothèque pour i2c. Comme je n'ai pas réussi avec la bibliothèque bcm2835, j'ai décidé d'utiliser la bibliothèque utilisée dans l'exemple - il s'agit de la bibliothèque WirinPi. Tout a fonctionné avec elle. Empiriquement, j'ai découvert que les informations du bouton sont contenues dans 4 et 5 octets (si vous comptez des octets à partir de zéro). Les informations sur les boutons de sélection, de démarrage, de descente et de droite se trouvent dans le quatrième octet, et les informations sur les boutons A, B, haut et gauche se trouvent dans le cinquième octet. De plus, les informations sur les boutons de sélection, bas et droit sont dans les 4 bits supérieurs de l'octet, et les informations sur le bouton de démarrage sont dans le bas. Il en va de même pour le 5ème octet, les informations sur les boutons A, B sont dans les 4 bits supérieurs de l'octet, et les informations sur les boutons haut, gauche sont dans les bas. Voici les codes des boutons: A - 0xcf, B - 0xbf, haut - 0xf0, gauche - 0xf1, sélectionnez - 0xcf, démarrez - 0xf3, bas - 0xbf, droite - 0x7f.Le résultat de la pression conjointe sur des boutons, dont les informations sont dans un octet et dans les mêmes bits, est un «ET» logique de leurs codes. Ainsi, par exemple, appuyer simultanément sur les boutons A et B donne la valeur 0x8f.Voici un lien vers le tableau:
Ensuite, j'ai écrit un petit programme de test pour la lecture des boutons, ci-dessous je vais le lister en entier et expliquer ce qui se passe avec:#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;
}
Au tout début, des variables sont déclarées, à l'aide desquelles l'état d'un bouton particulier sera déterminé. Il est important que les variables soient de type char, sinon avec un décalage au niveau du bit vers la gauche, seulement 4 zéros sont ajoutés, et c'est tout. L'interprétation sera fausse. Peu importe à quel point cela semble drôle, vous devez utiliser le sort .Ensuite, dans le corps principal du programme, la bibliothèque WiringPi est initialisée - câblagePiSetup ();, puis l'adresse i2c du périphérique est définie sur 0x52. Ensuite, le contrôleur est initialisé:
wiringPiI2CWriteReg8(fd, 0x40, 0x00);
delayMicroseconds(20);
Eh bien, déjà, dans le corps de la boucle, 6 octets sont lus, et avant la lecture, zéro est écrit à chaque fois. Et après cela, le bouton enfoncé est déterminé. En général, tout ce code a migré vers les fichiers de l'émulateur.Comme la dernière fois, l'initialisation de la bibliothèque est enregistrée dans le fichier fceu.c:
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;
}
Et bien toutes les modifications ne concernent que le fichier input.c. Initialement, dans la fonction FCEUI_Initialize (void) int, les modes de fonctionnement du port gpio pour travailler avec l'ancienne manette de jeu (de Simba) sont définis et la manette de jeu est initialisée.
pinMode (0, OUTPUT);
pinMode (2, OUTPUT);
pinMode (3, INPUT);
digitalWrite (0, HIGH);
digitalWrite (2, LOW);
fd = wiringPiI2CSetup(0x52);
wiringPiI2CWriteReg8(fd, 0x40, 0x00);
usleep(20);
Au début, vous devez également déclarer des variables qui détermineront les pressions sur les boutons.Dans la fonction statique DECLFW (B4016), un stroboscope est fourni pour l'ancien gamepad, le nouveau stroboscope n'est pas nécessaire:
if (LastStrobe==0)
{
digitalWrite (0, LOW);
}
Lors de la création d'un programme de test, je n'ai pas pu résoudre le problème d'identification des boutons enfoncés ensemble, dont les informations sont sur un octet et sur un bit. À la fin, j'ai appliqué la construction de cas de commutation au lieu de if else.Eh bien, la fonction elle-même est une fonction de lecture de l'état des boutons:
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);
}
En un cycle, j'ai combiné la lecture des boutons des deux manettes, eh bien, pensez que 2 octets supplémentaires sont lus, cela n'a pas d'importance, mais tout se passe en même temps. Et il n'y a aucun retard.En général, tout va bien.PS: Si je me souviens bien, demain au travail, déjà déformé.PPS J'ai oublié d'ajouter que pour une compilation réussie, dans le Makefile (formé après l'exécution de la commande Configure), qui se trouve dans le répertoire src, vous devez ajouter -lwiringPi -lm -lrt à l'endroit où les dépendances de la bibliothèque sont écrites. Ligne:LIBS =