Controlador USB per a joystick i botons MAME

De wikijoan
Salta a la navegació Salta a la cerca

Referències

En el marc del projecte PiMAME, per a construir un moble MAME Arcade basat en Raspberry Pi, necessito connectar el joystick i botons al port usb. Està explicat en el següent enllaç:

Per seguir els passos de l'enllaç necessito un programador per als xips AVR, i saber compilar i programar els xips AVR. Està explicat en els següents enllaços*

Important!:

Desenvolupament

Atmel8 i cristall 12MHz

He començat utilitzant al Atmel168 i un cristall de 16MHz. He mirat d'adaptar el codi a 16MHz i el Atmel168, però no m'ha acabat de sortir. Per tant vull seguir la mateixa configuració que l'enllaç original de raphnet.net. Després d'algun que altre problema, ja funciona. Funciona amb dues configuracions diferents: utiltizant dos diodes zener de 3,6V, i també dos diodes.

El circuit que he muntat és el que es publica en l'article original que segueixo, el projecte usb_game12 de raphnet.net.

Connecto el dispositiu i automàticament el reconeix:

$ cat /var/log/syslog
...
Feb 11 00:04:41 musica kernel: [   77.902095] usb 2-1.1: new low-speed USB device number 4 using ehci_hcd
Feb 11 00:04:42 musica mtp-probe: checking bus 2, device 4: "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1"
Feb 11 00:04:42 musica mtp-probe: bus: 2, device: 4 was not an MTP device
Feb 11 00:04:42 musica kernel: [   78.014903] input: raphnet.net USB_Game12 as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1:1.0/input/input11
Feb 11 00:04:42 musica kernel: [   78.015183] generic-usb 0003:1781:0A96.0002: input,hidraw1: USB HID v1.01 Gamepad [raphnet.net USB_Game12] on usb-0000:00:1d.0-1.1/input0
$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 003: ID 0c45:6406 Microdia 
Bus 002 Device 003: ID 046d:c046 Logitech, Inc. RX1000 Laser Mouse
Bus 002 Device 004: ID 1781:0a96 Multiple Vendors
$ cat /proc/bus/input/devices
I: Bus=0003 Vendor=1781 Product=0a96 Version=0101
N: Name="joanillo-mame USB_Game12"
P: Phys=usb-0000:00:1d.0-1.1/input0
S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1:1.0/input/input11
U: Uniq=1000
H: Handlers=event11 js0 
B: PROP=0
B: EV=1b
B: KEY=ff0000 0 0 0 0 0 0 0 0 0
B: ABS=3
B: MSC=10

El dispositiu ja està connectat, ara bé, com es demostra que és una gamepad? Com veig que funciona? Tinc un dubte, doncs pensava que ficant un editor de text veuria certs caràcters en apretar el botó... Envio un mail al fòrum de V-USB i descobreixo la resposta.

Com es comenta en l'enllaç, nececcito el paquest joystick per tenir la utilitat jscal:

$ sudo apt-get install joystick

$ ls /dev/input/js0 
/dev/input/js0

$ jscal /dev/input/js0
Joystick has 2 axes and 8 buttons.
Correction for axis 0 is broken line, precision is 0.
Coeficients are: 112, 142, 5534751, 5534751
Correction for axis 1 is broken line, precision is 0.
Coeficients are: 112, 142, 5534751, 5534751

$ jscal -c /dev/input/js0
Joystick has 2 axes and 8 buttons.
Correction for axis 0 is broken line, precision is 0.
Coeficients are: 112, 142, 5534751, 5534751
Correction for axis 1 is broken line, precision is 0.
Coeficients are: 112, 142, 5534751, 5534751

Calibrating precision: wait and don't touch the joystick.
Done. Precision is:                                             
Axis: 0:     0
Axis: 1:     0

Move axis 0 to minimum position and push any button.
Hold ... OK.
$ jstest /dev/input/js0
Driver version is 2.1.0.
Joystick (raphnet.net USB_Game12) has 2 axes (X, Y)
and 8 buttons (BtnX, BtnY, BtnZ, BtnTL, BtnTR, BtnTL2, BtnTR2, BtnSelect).
Testing ... (interrupt to exit)
Axes:  0:     0  1:     0 Buttons:  0:off  1:off  2:off  3:off  4:off  5:off  6:off  7:off

Per tant, ara ja tinc la certesa de què funciona, tot i que no sé exactament què he de fer en la Raspberry Pi per tal de què reconegui el Gamepad.

Aquí lo important és estudiar i entendre el projecte V-USB: Virtual USB port for AVR microcontrollers:

És la solució per fer dispositius USB amb uC Atmel, ja siguin HID o d'altres protocols. Ja he fet el primer dispositiu, s'obre un gran camp per explorar. El lloc per estudiar més els dispositius USB fets amb V-USB seria:

Atmel168 i cristall 16MHz (funciona amb la configuració diodes)

En aquest apartat s'estudiaran els canvis que s'han de fer en el codi original per adaptar el projecte a Atmel168 i 16MHz de freqüència de rellotge. Així mateix, canviaré la informació sobre el propietari del dispositiu USB.

Copio i renombro la carpeta usb_game12-1.0/ a usb_game12-1.0-atmega168. La carpeta usbdrv ve del projecte V-USB.

El primer que faig és mirar-me el Makefile i canvio les següents línies:

UISP -> res, perquè aquesta no és la meva comanda per gravar el xip.
COMPILE = avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega168 -DF_CPU=16000000L #-DDEBUG_LEVEL=1
flash_usb:
	sudo avrdude -p m168 -P usb -c usbasp -Uflash:w:$(HEXFILE) -B 1.0
fuse_usb:
	sudo avrdude -p m168 -P usb -c usbasp -Uhfuse:w:0xc9:m -Ulfuse:w:0x9f:m -B 10.0

(els fuses no s'han de canviar encara que siguin xips diferents i el rellotge també, que tots dos són > 8MHz. Mirar-ho en un fuse calculator)

Ara ja puc compilar:

$ make
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=16000000L  -c usbdrv/usbdrv.c -o usbdrv/usbdrv.o
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=16000000L  -x assembler-with-cpp -c usbdrv/usbdrvasm.S -o usbdrv/usbdrvasm.o
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=16000000L  -c usbdrv/oddebug.c -o usbdrv/oddebug.o
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=16000000L  -c main.c -o main.o
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=16000000L  -c twelve.c -o twelve.o
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=16000000L  -c devdesc.c -o devdesc.o
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=16000000L  -o main.bin usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o twelve.o devdesc.o -Wl,-Map=main.map
rm -f main.hex main.eep.hex
avr-objcopy -j .text -j .data -O ihex main.bin main.hex
./checksize main.bin
ROM: 2560 bytes (data=58)
RAM: 134 bytes

i si tinc connectat el programador amb el xip, ja puc gravar:

$ make flash_usb
sudo avrdude -p m168 -P usb -c usbasp -Uflash:w:main.hex -B 1.0
...

$ make fuse_usb
sudo avrdude -p m8 -P usb -c usbasp -Uhfuse:w:0xc9:m -Ulfuse:w:0x9f:m -B 10.0
...

Ara bé, fins ara no he tocat per res el codi font. Què falta?.

En referència a utiltizar un rellotge de 16MHz, llegeixo en el Readme.txt de la carpeta usbdrv/:

CPU CORE CLOCK FREQUENCY
========================
We supply assembler modules for clock frequencies of 12 MHz, 16 MHz and
16.5 MHz. Other clock rates are not supported. The actual clock rate must be
configured in usbdrv.h unless you use the default 12 MHz.

12 MHz Clock
This is the traditional clock rate of AVR-USB because it's the lowest clock
rate where the timing constraints of the USB spec can be met.

16 MHz Clock
This clock rate has been added for users of the Arduino board and other
ready-made boards which come with a fixed 16 MHz crystal. It's also an option
if you need the slightly higher clock rate for performance reasons. Since
16 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code
is somewhat tricky and has to insert a leap cycle every third byte.

Tanmateix, això no m'ha suposat cap canvi en el codi, funciona correctament.

En el fitxer usbconfig.h trobo la línia:

#define USB_CFG_CLOCK_KHZ       (F_CPU/1000)

Però precisament el paràmetre F_CPU el defineixo en el Makefile.

A partir de la línia 130 del fixer usbconfig.h hi ha la descripció del dispositiu:

#define USB_CFG_VENDOR_NAME     'j', 'o', 'a', 'n', 'i', 'l', 'l', 'o', '-', 'm', 'a', 'm', 'e'
#define USB_CFG_VENDOR_NAME_LEN 13

Fixem-nos com dic que el meu dispositiu USB és una HID:

#define USB_CFG_INTERFACE_CLASS     3   /* HID */

En el fitxer twelve.c tinc la pista per mapejar els botons als pins correctes del xip:

	/* 
	 * --- 10 button on multiuse2 pinout ---
	 * PC5: Up
	 * PC4: Down
	 * PC3: Left
	 * PC2: Right
	 *
	 * PC1: Button 0
	 * PC0: Button 1
	 * PB5: Button 2
	 * PB4: Button 3
	 * PB3: Button 4
	 * PB2: Button 5 (JP2)
	 * PB1: Button 6 (JP1)
	 * PB0: Button 7
	 */

Més coses. Com es comenta a Programació_dels_microcontroladors_AVR:_avr-gcc, en el codi (fitxer main.c) he de renombrar alguns ports per tal de què compili correctament:

TCCR0 to TCCR0B
TCCR2 to TCCR2B
TIFR to TIFR0 
OCR2 to OCR0A
OCF2 to OCF0A

Funciona!. Però amb una salvetat: funciona amb la configuració diodes (http://www.obdev.at/Images/vusb/circuit-zoomed.gif). Amb la configuració diodes Zener es reconeix el dispositiu però no funciona el mapejat (rejoystick), En canvi, amb Atmel8/12MHz funcionava perfectament amb les dues configuracions.(És possible que amb Atmel168 i 12MHz també funcioni). Una altra possibilitat és cercar uns altres diodes Zener doncs sembla ser que han de ser uns concretes de baixa potència...

Fer funcionar la pimame amb el Gamepad

No confondre un Gamepad amb un keyboard, són dispositius diferents. El primer que esperava era que en apretar els botons veigués alguna cosa per pantalla, i no...

Com que pimame espera uns botons: 1, 2, ESC,..., el que s'ha de fer és mapejar els botons del gamepad amb les tecles correctes del teclat.

que no calgui sudo

once that is in place, it is time to tell udevd about the new device. For that, I created a udev rule:

/etc/udev/rules.d/10-local.rules:
KERNEL=="js*", SUBSYSTEM=="input", MODE="660", OWNER="joan", GROUP="joan", ATTRS{name}=="joanillo-mame USB_Game12", NAME="input/js0"
KERNEL=="uinput", MODE="660", OWNER="joan", GROUP="joan"

De fet són dues regles, doncs són dos dispositus: el joystick, i també el dispositiu /dev/uinput que és el mòdul del kernel que sap enviar tecles a qualsevol lloc.

rejoystick

Una solució és rejoystick:

Descarrego: rejoystick_0.8.1-1_i386.deb

$ sudo dpkg -i rejoystick_0.8.1-1_i386.deb

This program "translates" keypresses on joystick/gamepads/joypads into keypresses on a keyboard. It's great to use as a substitute for a remote control and perfect to use when you play games that don't have gamepad support.

Per tal de configurar el mapejat: (també pot servir per testejar que funciona correctament)

$ rejoystick

Per tal de què funcioni el mapejat he d'escriure en el terminal:

$ rejoystick -d

i per aturar el mapejat:

$ killall -9 rejoystick

El problema de rejoystick és que no he aconseguit fer-lo funcionar a la RP per un problema d'arquitectura.

joy2key

rejoystick funciona bé amb l'ordinador, però el problema és que no he aconseguit intal.lar-lo a la RP. El que sí que s'insta.la és el joy2key.

Ara falta configurar-ho,

$ sudo ./joy2key -config Alias

fitxer .joy2keyrc:

START Alias
-terminal
-buttons 1 2 3 4 5 6 7 8
-axis Left Right Up Down
-dev /dev/input/js0
-thresh -16383 16383 -16383 16383 -16383 16383 -16383 16383 -16383 16383 -16383 16383
-autorepeat 5

I com que és molt difícil configurar-lo, finalment he modificat el projecte: joy2key_joanillo. Ara utilitza uinput per a simular el pitjar una tecla, que és una solució de baix nivell, independent de la finestra, etc.


creat per Joan Quintana Compte, febrer 2014