Las vacaciones están llegando a su fin, lo que significa que es hora de arrepentirse del hígado y girar la cabeza. Entonces otra idea vino a mi mente. Después de conectar el gamepad de Dendy (es un joystick, es un controlador, es un joystick, es una consola de juegos, etc.) geektimes.ru/post/281520 , pensé en conectar un segundo a Raspberry pi. No quería comprar la segunda basura con botones atascados, y por cierto, la tiraron en los estantes de la Nintendo Classic Mini, bueno, cuando la tiraste, comprarás rábano picante. El objetivo no era comprar un emulador para 4K, pero decidí comprar un gamepad. Afortunadamente, logré comprarlo, fue el último en la tienda. Aquellos que estén interesados en lo que surgió, pueden hacer clic en el botón a continuación.Aquí hay un enlace directo a la prueba , si el normal no está activado.
No hay ningún secreto de que este gamepad se puede conectar a Wii y Wii U, lo que significa que se puede interrogar a través de la interfaz i2c. Lo que es alentador es que el gamepad funciona con 3.3 V, lo que significa que no tiene que preocuparse por los niveles de voltaje correspondientes. Para conectar el gamepad a la Raspberry pi, decidí comprar conectores para wiimote en aliexpress, que están soldados en la placa de él. Aunque había 2 conectores en el paquete, y estaban en una burbuja común, uno de los conectores estaba en mal estado. No estaño no puede hacer aquí. Después de que todo fue soldado, fue necesario verificar si esto funciona. Para esto, decidí usar las utilidades del paquete i2c-tools. La idea era determinar el dispositivo en la dirección: 52. Después de lanzar i2cdetect, vi lo atesorado: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: -- -- -- -- -- -- -- --
Inmediatamente mi corazón se calentó (como si una niña desconocida te sonriera en una calle en primavera), así que funciona. Luego, tenía que buscar en Google para conectar periféricos a la Wii. Encontré un ejemplo de cómo un nunchak de Wii se conecta a una Raspberry pi. A partir de este ejemplo, descubrí que el gamepad debe inicializarse escribiendo cero en el registro 0x40, y luego, justo antes de leer cada vez, solo necesita escribir un cero y leer los primeros 6 bytes.En este caso, también enfrenté la elección de una biblioteca para i2c. Como no tuve éxito con la biblioteca bcm2835, decidí usar la biblioteca que se usó en el ejemplo: esta es la biblioteca WirinPi. Todo salió bien con ella. Empíricamente, descubrí que la información del botón está contenida en 4 y 5 bytes (si cuenta bytes desde cero). La información sobre los botones de selección, inicio, abajo, derecha está en el cuarto byte, y la información sobre los botones A, B, arriba, izquierda está en el quinto byte. Además, la información sobre los botones de selección, abajo, derecha está en los 4 bits superiores del byte, y la información sobre el botón de inicio está en la parte inferior. Lo mismo es cierto para el 5to byte, la información sobre los botones A, B está en los 4 bits altos del byte, y la información sobre los botones hacia arriba, izquierda está en los más bajos. Aquí están los códigos de los botones: A - 0xcf, B - 0xbf, arriba - 0xf0, izquierda - 0xf1, seleccione - 0xcf, inicio - 0xf3, abajo - 0xbf, derecha - 0x7f.El resultado de la presión conjunta de botones, cuya información se encuentra en un byte y en los mismos bits, es un "Y" lógico de sus códigos. Entonces, por ejemplo, presionar los botones A y B juntos da el valor 0x8f.Aquí hay un enlace a la tabla: a
continuación, escribí un pequeño programa de prueba para leer los botones, a continuación lo enumeraré por completo y explicaré lo que está sucediendo con él:#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;
}
Al principio, las variables se declaran, con la ayuda de las cuales se determinará el estado de un botón en particular. Es importante que las variables sean del tipo char, de lo contrario con un desplazamiento a la izquierda, solo se agregan 4 ceros, y eso es todo. La interpretación será incorrecta. No importa cuán divertido suene, debes usar el hechizo .A continuación, en el cuerpo principal del programa, la biblioteca WiringPi se inicializa - cableadoPiSetup () ;, y luego la dirección i2c del dispositivo se establece en 0x52. A continuación, se inicializa el controlador:
wiringPiI2CWriteReg8(fd, 0x40, 0x00);
delayMicroseconds(20);
Bueno, entonces, ya en el cuerpo del bucle, se leen 6 bytes, y antes de leer, se escribe cero cada vez. Y después de eso, se determina el botón presionado. En general, todo este código migró a los archivos del emulador.Como la última vez, la inicialización de la biblioteca se registra en el archivo 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;
}
Bueno y más, todos los cambios se refieren solo al archivo input.c. Inicialmente, en la función FCEUI_Initialize (void) int, se configuran los modos de funcionamiento del puerto gpio para trabajar con el viejo gamepad (de Simba) y se inicializa el gamepad.
pinMode (0, OUTPUT);
pinMode (2, OUTPUT);
pinMode (3, INPUT);
digitalWrite (0, HIGH);
digitalWrite (2, LOW);
fd = wiringPiI2CSetup(0x52);
wiringPiI2CWriteReg8(fd, 0x40, 0x00);
usleep(20);
Al principio, también debe declarar variables que determinarán las pulsaciones de los botones.En la función estática DECLFW (B4016), se proporciona una luz estroboscópica para el viejo gamepad, no se necesita la nueva luz estroboscópica:
if (LastStrobe==0)
{
digitalWrite (0, LOW);
}
Al crear un programa de prueba, no pude resolver el problema de identificar los botones presionados juntos, la información acerca de cuál está en un byte y en un bit. Al final, apliqué la construcción de mayúsculas y minúsculas en lugar de if if else.Bueno, la función en sí es la función de leer el estado de los botones:
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 ciclo, combiné la lectura de los botones de ambos gamepads, bueno, creo que se leen 2 bytes adicionales, no importa, pero todo sucede al mismo tiempo. Y no hay retrasos.En general, todo está bien.PD: Como recuerdo, mañana en el trabajo, ya distorsionado.PPS Olvidé agregar que para una compilación exitosa, en el Makefile (formado después de ejecutar el comando Configurar), que se encuentra en el directorio src, debe agregar -lwiringPi -lm -lrt al lugar donde se escriben las dependencias de la biblioteca. Línea:LIBS =