USB HID y dispositivo de juegos

Hola a todos.

Quiero hacer un desarrollo en ccs para simular un dispositivo de juegos que windows reconozca sin problemas. La idea es utilizar mi propio hardware (cabrilla, pedales y botones) en varios juegos.

Tengo entendido que usando HID, se puede hacer esto. Desafortunadamente estoy empezando con el tema de usb y no tengo conocimiento en esta configuración. Estuve leyendo sobre el tema y encontré que tenía que hacer un HID descriptor donde configuro la cantidad de entradas análogas y digitales de mi "joystick", asi como la ubicación en bit y bytes de cada una de ellas. Como puedo hacer este HID descriptor? que mas necesito aparte de eso?

Espero me puedan ayudar. Gracias
 
Yo acabo de hacer algo parecido
Hay un documento: HID Usage Tables no recuerdo de donde lo descargué, en la página 147 viene un ejemplo de como configurar el HID para emular un gamepad de dos ejes Rocker y 6 botones, a partir de ese ejemplo y la lectura de una buena parte de ese documento logré hacer un gamepad de 2 ejes y 8 botones, la cantidad de botones es lo de menos.

Lo implementé en CCS, básicamente tienes que editar el HID Report, con lo siguiente

UsagePage(Generic Desktop),
Usage(Game Pad),
Collection(Application),
Usage (Pointer),
Collection (Physical),
Usage (X),
Usage (Y),
Logical Minimum (-1), Logical Maximum (1),
Report Count (2), Report Size (2),
Input (Data, Variable, Absolute, No Null),
End Collection(),

Report Count (4),
Report Size (1),
Input (Constant, Variable, Absolute), ; 4-bit pad

Usage Page (Buttons), ; Buttons on the stick
Usage Minimum (Button 1),
Usage Maximum (Button 6),
Logical Minimum (0), Logical Maximum (1),
Report Count (6),
Report Size (1),
Input (Data, Variable, Absolute),
Report Count (2),
Input (Constant, Variable, Absolute) ; 2-bit Pad
End Collection()

Tambien me basé en una nota de aplicación de ST titulada: USING THE ST7263 KIT TO IMPLEMENT A USB GAME PAD.

Mi idea es ponerle botones y palanca tipo arcade para jugar los títulos de antaño: Street Fighter EX, KI, KOF, etc. :)
 
En el programa principal estoy mandando los 2 bytes de datos correspondientes al GamePad donde los 4 LSB del byte0 coresponden a los ejes X y Y con valores de -1 a 1, el byte1 contiene el estado de los 8 botones. A esos 2 bytes le estoy mandando el valor de un contador, para que a manera de prueba cuando se conecte el GamePad se vea que se están presionando los botones y ejes.

Este es el código que utilizo en CCS y adjunto el archivo usb_gamepad_HID.h que contiene el reporte que es la parte donde se le dice a la PC como va a interpretar los datos que se la manden.


#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)

#DEFINE USB_HID_DEVICE TRUE

#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_TX_SIZE 8

#include <pic18_usb.h>
#include <usb_gamepad_HID.h> //USB Configuration and Device descriptors for this USB device
#include <usb.c> //handles usb setup tokens and get descriptor reports
#include <ctype.h>

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

/////////////////////////////////////////////////////////////////////////////
//
// Configure the demonstration I/O
//
/////////////////////////////////////////////////////////////////////////////
#define LED1 PIN_A5
#define LED2 PIN_B4
#define LED3 PIN_B5
#DEFINE BUTTON PIN_A4
#define LED_ON output_low
#define LED_OFF output_high

/////////////////////////////////////////////////////////////////////////////
//
// usb_debug_task()
//
// When called periodically, displays debugging informaciónrmation over serial
// to display enumeration and connection states. Also lights LED2 and LED3
// based upon enumeration and connection status.
//
/////////////////////////////////////////////////////////////////////////////
void usb_debug_task(void) {
static int8 last_connected;
static int8 last_enumerated;
int8 new_connected;
int8 new_enumerated;

new_connected=usb_attached();
new_enumerated=usb_enumerated();

if (new_connected)
LED_ON(LED2);
else
LED_OFF(LED2);

if (new_enumerated)
LED_ON(LED3);
else
LED_OFF(LED3);

if (new_connected && !last_connected)
printf("\r\n\nUSB connected, waiting for enumaration...");
if (!new_connected && last_connected)
printf("\r\n\nUSB disconnected, waiting for connection...");
if (new_enumerated && !last_enumerated)
printf("\r\n\nUSB enumerated by PC/HOST");
if (!new_enumerated && last_enumerated)
printf("\r\n\nUSB unenumerated by PC/HOST, waiting for enumeration...");

last_connected=new_connected;
last_enumerated=new_enumerated;
}

void main(void) {
#define MOUSE_SEQUENCE_STEPS 16
const char mouse_seq[MOUSE_SEQUENCE_STEPS]=
{0, 1, 3, 4, 4, 4, 3, 1, 0, -1, -3, -4, -4, -4, -3, -1};

int8 out_data[2];
int8 x_seq=0; int8 y_seq=MOUSE_SEQUENCE_STEPS/4;
int8 count=0;

int8 x=0;

LED_ON(LED1);
LED_OFF(LED2);
LED_OFF(LED3);

usb_init_cs();

printf("\r\n");

while (TRUE) {
usb_task();
usb_debug_task();
if (usb_enumerated()) {

out_data[0]=x; // Los 4 LSB son los 2 ejes
out_data[1]=x; // Son los 8 botones

if (usb_put_packet(1,out_data,2,USB_DTS_TOGGLE))
x++;
delay_ms(250);
}
}
}
 

Adjuntos

  • usb_gamepad_hid_157.h
    12.3 KB · Visitas: 285
Moyano Jonathan dijo:
Muchas gracias LIAMNEESON, voy a ver que sale de toda la información que me diste.

De nada, lo más complicado es configurar el Report del HID, creo que por eso existen programas como el EasyHID.

Lo puedes simular en Proteus con los Drivers de USB que trae, que me parecen algo innovador.
 
Ahora como puedo probar los datos proveniente del PIC osea he visto programas para probar los jostick usb esos me servirian? Con respecto a usb en proteus, no le tengo mucha confianza, mejor lo pruebo en protoboard
 
Trabajando en XP te vas a panel de control - dispositivos de juego y ahi te debe aparecer el gamepad cuando lo conectes, le das configurar y vas a ver los botones que se presionan y los ejes igualmente.

Yo lo simulé en Proteus con una Aspire One corre bien sin problemas, aunque me imagino que esos drivers del Proteus todavía están en pruebas.

Lo puedes probar en un emulador o algún juego de PC.
 
Gracias por toda la información. Voy a hacer pruebas hoy y les comento los resultados. Me gustaria saber como configuras el HID Report para adaptarlo a tus necesidades de entradas análogas y digitales. Yo bajé el easy HID, pero no pude configurar nada de eso, solo me da la opcion de configurar tiempos de lectura y el tamaño de los buffers y los archivos de salida no supe como usarlos en CCS.
 
Si te refieres a las entradas anlógicas para el gamepad tendrías que modificar los valores de los ejes X y Y del ejemplo anterior

Usage (X),
Usage (Y),
Logical Minimum (-1), Logical Maximum (1),
Report Count (2), Report Size (2),

Estos valores estan configurados para ejes con 3 estados -1, 0 y 1
Y se mandan en 2 bits, los 2 ejes.
Por eso el Report Count y el Report Size de 2

Si quieres una resolución de 8 bits para los ejes X y Y te quedaría algo así:

0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8) bits
0x95, 0x02, // REPORT_COUNT (2)

Lee los documentos que menciono ahí viene eso.
 
Lo tengo simulado en proteus, mi idea es ponerle botones y palanca tipo arcade, pero los botones me salen como en $2.5 dlls c/u :eek: , utilizo el puerto B para los 8 botones y el puerto D para la palanca, no tiene complejidad alguna. Tengo varios pendientes por ahora así que me conformé con tener la programación 100% funcional :)
 
Ahora la palanca no tendría que ir a uno de los puertos analógicos del PIC ya que son dos ejes X e Y entonces tenés que leer 2 salidas en más o menos el mismo tiempo y luego enviar la información por USB.
 
Si puedes enviar el archivo de simulacion de proteus sería buenisimo. Estoy leyendo los documentos de tablas para desarrollo HID que estan en la pagina de usb.org y hasta el momento no entiendo como adicionar botones y señales análogas.

En lo que Liamneeson envió quedé confundido porque no veo por ningún lado como hace la lectura de los botones y como hace la transferencia de esa información a usb.
 
Atrás
Arriba