# Joystick USB con PIC18F2550 1 analógico + 8 botones



## Moyano Jonathan (May 8, 2009)

Bueno acá les dejo un proyecto que hice en colaboración con otros usuarios del foro , se trata de un joistick USB basado en el PIC18F2550. El proyecto funciona correctamente en windows XP y vista (probado). El que tenga alguna duda pregunte.

PD: Hay otros post sobre joistick pero este es para poner el desarrollo definitivo de mi proyecto , el que tenga armado algo parecido que lo postee.

Un especial agradecimiento a LIAMNESSON ! que me ayudo con los descriptores USB y la teoría de funcionamiento.


----------



## jokelnice (May 8, 2009)

gracias moyano bueno el aporte


----------



## Moyano Jonathan (May 8, 2009)

De nada el GAMEPAD puede ser adaptado para 2 controles analogicos si se quiere es solo cuestion de modificar los descriptores.


----------



## LIAMNEESON (May 8, 2009)

Moyano Jonathan dijo:
			
		

> Bueno acá les dejo un proyecto que hice en colaboración con otros usuarios del foro , se trata de un joistick USB basado en el PIC18F2550. El proyecto funciona correctamente en windows XP y vista (probado). El que tenga alguna duda pregunte.
> 
> PD: Hay otros post sobre joistick pero este es para poner el desarrollo definitivo de mi proyecto , el que tenga armado algo parecido que lo postee.
> 
> Un especial agradecimiento a LIAMNESSON ! que me ayudo con los descriptores USB y la teoría de funcionamiento.



  jajaja , ya tenía rato que no entraba al foro  ops: , bueno lo bajo, por que no subes fotos digo si es que lo implementaste, o le vas a conectar un control de psx ?


----------



## Moyano Jonathan (May 9, 2009)

Lo arme en proto nomás y me olvide de sacarle fotos. El control es para hacerlo funcionar con juegos de PC solamente, por el momento no le voy a conectar el control de PSX


----------



## Vegetal Digital (May 16, 2009)

Podes poner una imagen del esquema? Mi proteus tiene problema con la versión y no me deja verlo
Gracias


----------



## Moyano Jonathan (May 16, 2009)

> Podes poner una imagen del esquema? Mi proteus tiene problema con la versión y no me deja verlo
> Gracias



Bueno acá está.


----------



## Vegetal Digital (May 18, 2009)

uy muchisimas gracias esta muy bueno e interesante el proyecto


----------



## Moyano Jonathan (May 18, 2009)

Cualquier duda que tengas comentame y vemos como la resolvemos !


----------



## neneriostb (May 19, 2009)

cordial saludo señor Moyano jhonatan a mi me gustaria conectar el microcontrolador 18f2550 por el puerto usb y por medio de una interfaz grafica manejada sobre cualquer programa del computador , yo pueda controlar el puerto b del micro como salida y el puerto a como entrada


----------



## JOJOJORGE (May 19, 2009)

Hola
Moyano Jonathan excelente trabajo, cuando pueda lo pruebo y sacare fotos.

lo del mando de psx no recuerdo donde pero en algún foro vi como se conectaba un mando de psx a un pic16f877a para control de un robot o algo lamentablemente no copie nada pero lo buscare otra ves.



			
				neneriostb dijo:
			
		

> cordial saludo señor Moyano jhonatan a mi me gustaria conectar el microcontrolador 18f2550 por el puerto usb y por medio de una interfaz grafica manejada sobre cualquer programa del computador , yo pueda controlar el puerto b del micro como salida y el puerto a como entrada


para lo que pides hay un hilo con muchos ejemplos fijate en https://www.forosdeelectronica.com/about29225.html

salu2


----------



## andrumic23 (May 26, 2009)

Excelente proyecto... realmente esa información me sirvió mucho, pero tengo unas duditas. 

1. cuantos axis es lo máximo que se pueden configurar con este pic.
2. Como se los agrego a este, que hay que modificarle al código...

Muchas gracias

Bye.


----------



## Moyano Jonathan (May 27, 2009)

le podes agregar 1 mas o 2 mas no me acuerdo. Te pongo toda la información para que te lo hagas.


----------



## electro_02006 (Jun 27, 2009)

hola moyano jonathan soy nuevo en el foro y mi pregunta es si se puede adaptar este proyecto para el pic18f4550?  y como lo aria?
por tu atensión muchas gracias y felicidades por este magnifico proyecto


----------



## Moyano Jonathan (Jun 27, 2009)

Si tenés que cambiar el archivo de cabezera del microcontrolador y compilar el proyecto nuevamente.


----------



## fvillar (Ene 26, 2010)

Un proyecto realmente interesante...
¿Cómo se puede cambiar el nombre que aparece cuando se conecta el usb?
Muchas gracias.


----------



## Moyano Jonathan (Ene 26, 2010)

Tenés que cambiar el archivo de descriptores


----------



## fvillar (Ene 27, 2010)

Muchas gracias. Eso ya lo he intentado, pero pese a que cambio el nombre y lo recompilo no se produce ninguna transformación a la hora de ver el nombre cuando conecto el USB. Sin embargo, sí que tiene efecto el añadir más botones. No sé si me estoy dejando algún paso o tengo que configurar de algún modo el compilador.
Gracias.


----------



## pic-man (Feb 5, 2010)

Moyano Jonathan muchas felicidades por este proyecto! Estoy aprendiendo C porque quiero dar el salto a los micros 18F y todo el código que pueda leer lo voy a aprovechar así que me voy a poner a estudiar el firmware de este gamepad a ver si logro entenderlo.

Muchas felicidades y también muchas gracias!


----------



## flakiyo (Feb 5, 2010)

Felicidades....muy bueno !


----------



## Golgo13 (Feb 14, 2010)

Hola excelente proyecto, lo has probado con un Microsoft Sidewinder force feedback


----------



## pauloss (Mar 31, 2010)

moyano en la parte del esquema lo que es la la direccion aparece logicamente como 2 potenciometros..esos potencimetros se pueden sustituir por una palanca???? y la palanca ya trae esa configuracion o como se implementaria con los potenciometros seria muy tardado para jugar ??


----------



## Moyano Jonathan (Abr 1, 2010)

Si la palanca es "tipo potenciómetro" ...entonces lo podés cambiar ahora si son del tipo encoder rotativo tendrías que decodificar los datos del encoder y luego enviarlos por USB.


----------



## Josel99 (Ago 26, 2010)

Excelente Proyecto!!! quisiera saber varias cosas: como le añado otro eje al gamepad?, Lo estoy probando en windows vista pero no me lo reconoce por completo, existe algún driver externo que se le pueda instalar?


----------



## Moyano Jonathan (Ago 26, 2010)

Es raro que no te lo reconozca en vista por q el driver es guenerico .....ahora de como se le puede añadir otro gamepad...lo tenes que modificar en los descriptores.


----------



## Randy (Ago 26, 2010)

Gracias Moyano Jonathan. Exelente aporte!!


----------



## fisicomolon (Nov 6, 2010)

Primero, genial aporte, excelente de verdad, un gran trabajo.

Me gustaría preguntar un par de cosas, aunque no se si quizás es demasiado tarde, pues hace unos meses que nadie comenta en este hilo, en fin...

Estoy haciendo lo siguiente:
Simulo el circuito en proteus con sus drivers para usb virtuales funciona perfecto.
He modificado los descriptores para dejar el mando con un único control, un "throttle" analógico.
Estoy usando pic c compiler para compilar el hex una vez modificados los descriptores.

Pero hay un par de cosas que necesito saber:


1.- No he conseguido cambiar el nombre MoyaPIC_GAMEPAD que aparece como nombre del dispositivo, he buscado en los descriptores pero solo he encontrado "Moya" como parte de un comentario. ¿Podrías especificar exactamente donde se encuentra?

2.- Puedo conectar un led que se encienda cuando pulse algún boton del mando, ¿Necesito modificar los descriptores o alguna otra parte del proyecto para esto? ¿O tengo que hacerlo mediante el software?

Muchas gracias por vuestro genial trabajo aquí.


----------



## Moyano Jonathan (Nov 6, 2010)

Para ponerle tu propio mensaje tenés que modificar los descriptores del USB


----------



## fisicomolon (Nov 6, 2010)

Gracias por tu respuesta, ya he encontrado como modificarlo, pero he de aclarar que no se modifica el mensaje aun modificando el  descriptor, ya que en el registro de windows se guarda el pid y el vid asociado al dispositivo y a su mensaje, tienes que cambiar el mensaje además del pid y el vid para que windows le asigne un nombre de dispositivo distinto, no he coseguido ni borrando el registro, solo cambiando el pid y el vid.

Y lo del led? alguna idea?


----------



## ByAxel (Nov 6, 2010)

Sugerencia: Con el PIC conectado a la PC, ve al administrador de dispositivos, busca el controlador Joistick USB para el PIC y clic en la opción desinstalar (marca todo si te aparecen opciones).


----------



## snakewather (Nov 7, 2010)

Gracias Exelente precisamente ahora estoy utilizando este PIC lo voy a checar saludos!.


----------



## ingACME (Dic 24, 2010)

muy bueno el tema muchas gracias por compartir esta informacion con el foro .........


----------



## jacobsot (Ene 18, 2011)

Hola a todos. Tengo tu excelente programa pero no me funciona. Uso el Quemador winpic800 no se que configuracion al rato de quemar hay que usar. Agradeceria la ayuda, adiocional se puede hacer este sin reloj externo y usar el interno del pic18f2550. Gracias.


----------



## chapin (Ene 22, 2011)

una pregunta alguien sabe de algun proyecto que utilize pbasic en algun gamepad ?


----------



## anotherhero (Ene 24, 2011)

Ayuda, los potenciometros no me calibran correctamente el gamepad, que puede ser, variaciones en voltaje? Como testean ustedes el gamepad?


----------



## spek87 (Ene 24, 2011)

hola amigo me interesa mucho tu tema y es muy bueno, 
a mi me interesa hacer una pedalera para conrtolar un programa para efectos de guitarra c llama guitar rig4
ojala me pudieras ayudar tengo entendido que c puede hacer con este pic pero la verdad c muy poco de electroniaca, tu gamepad me sirve mucho pero quiero saber como progamarlo para ese programa.........saludos


----------



## chassito (Feb 2, 2011)

hola amigo muy buen proyecto desearia q me ayudes a anular los controles analogicos y habilitar la mayor cantidad de botones digitales o las flechas de direccion no soy bueno en pregramacion y quisiera q me indiques como hacerlo ojala me puedas ayudar.
 te agradesco de antemano


----------



## Moyano Jonathan (Feb 2, 2011)

Hay que modificar los descriptores para añadir más botones o controles...luego modificar la toma de de datos para que acepte los nuevos controles..

Usen el buscador , por que eso ya se ha hecho.

Cualquier cosa que encuentre el link donde lo explica...se los pongo.


----------



## albermillan69 (Jun 6, 2011)

Moyano!! como estas??' MUY BIEN TU APORTE; TU SIEMPRE CON EL USB

Estoy simulando este Gamepad y funciona Perfect..
Pero le agregue mas botones ya que yo uso el 18f4550

Asi quedaron los descritores:

//Botones 1-8
      0x05, 0x09, // usage page (buttons) Choose the “button” usage page
      0x19, 0x01, // usage minimum (1) There are three buttons
      0x29, 0x08, // usage maximum (8)
      0x15, 0x00, // logical minimum (0) Each button is represented by one bit
      0x25, 0x01, // logical maximum (1)
      0x95, 0x08, // report count (8) Three reports, one bit each
      0x75, 0x01, // report size (1)
      0x81, 0x02, // input (data, variable, absolute)
//Botones 9-16
      0x05, 0x09, // USAGE_PAGE (Button)
      0x19, 0x09, // USAGE_MINIMUM (Button 9) 'MAS botones'
      0x29, 0x10, // USAGE_MAXIMUM (Button 16)
      0x15, 0x00, // LOGICAL_MINIMUM (0)
      0x25, 0x01, // LOGICAL_MAXIMUM (1)
      0x95, 0x08, // REPORT_COUNT (8)
      0x75, 0x01, // REPORT_SIZE (1)
      0x81, 0x02, // INPUT (Data,Var,Abs)
//Botones 17-24      
      0x05, 0x09, // USAGE_PAGE (Button)
      0x19, 0x11, // USAGE_MINIMUM (Button 17) 'MAS botones'
      0x29, 0x18, // USAGE_MAXIMUM (Button 24)
      0x15, 0x00, // LOGICAL_MINIMUM (0)
      0x25, 0x01, // LOGICAL_MAXIMUM (1)
      0x95, 0x08, // REPORT_COUNT (8)
      0x75, 0x01, // REPORT_SIZE (1)
      0x81, 0x02, // INPUT (Data,Var,Abs)
//Botones 15-32      
      0x05, 0x09, // USAGE_PAGE (Button)
      0x19, 0x19, // USAGE_MINIMUM (Button 17) 'MAS botones'
      0x29, 0x20, // USAGE_MAXIMUM (Button 24)
      0x15, 0x00, // LOGICAL_MINIMUM (0)
      0x25, 0x01, // LOGICAL_MAXIMUM (1)
      0x95, 0x08, // REPORT_COUNT (8)
      0x75, 0x01, // REPORT_SIZE (1)
      0x81, 0x02, // INPUT (Data,Var,Abs)

Espero les sirva a los que vienen atras!!

Ahora tengo es una prengunta!! esta configuracion con 1 analogico, funciona para simuladores de autos?? osea solo giros de derecha e izquierda??

Gracias...


----------



## chassito (Jun 11, 2011)

ya cree mi joypad usb con pic18f2550 de ejes x y mas 10 botones
pero tengo una consulta quisiera saber si hay alguna forma de presionar internamente los botones del joypad mediante codigo:
actualmente lo hago con otro pic externamente.
Lo que necesito es que una vez alimentamos el pic presione internamente algunos botones del joypad una sola vez
EJ
high boton 1
delay_ms(200)
low boton 1
delay_ms(2000)
high up
delay_ms(200)
low up
delay_ms(3000)
Esto es solo un ejemplo de lo que quiero hacer, q mediante codigo de programacion le indique al pic q presione un boton o un eje internamente.
esperando su ayuda y respuestas me despido de ustedes:


----------



## alexv (Ago 10, 2011)

Moyano Jonathan dijo:


> Bueno acá les dejo un proyecto que hice en colaboración con otros usuarios del foro , se trata de un joistick USB basado en el PIC18F2550. El proyecto funciona correctamente en windows XP y vista (probado). El que tenga alguna duda pregunte.
> 
> PD: Hay otros post sobre joistick pero este es para poner el desarrollo definitivo de mi proyecto , el que tenga armado algo parecido que lo postee.
> 
> Un especial agradecimiento a LIAMNESSON ! que me ayudo con los descriptores USB y la teoría de funcionamiento.



Moyano! no puedo escribir mensajes privados por ser nuevo en el foro! si me envias un privado con tu mail te respondo, sino vamos a desvirtuar este thread


----------



## Ericktronik (Sep 28, 2011)

Hola quiero modificar el programa para poder utilizar 2 ejes más.
sucede que voy a hacer mi propio volante estido Logitech G25 y quiero poder implementar 4 ejes:
eje 1: timon
eje 2: acelerador
eje 3: freno
eje 4: clutch
los botones lo usaria para la palanca de cambios y otras fonciones.
tambien quisiera hacer que cuando el voltaje de el eje 1 (timon) sea 0.01V me active un pin para bloquear el giro del timon y que cuando sea 4.99 tambien lo haga.(es para no dañar el potenciometro, ya que pienso utilizar uno de presicion de 10 vueltas y no quiero romperlo ya que son muy caros y el que tengo lo consegui casi en $1 us algo que no volvere a conseguir nunca).
agradesco su ayuda y consejos. tengo poca experiencia con pic's, manejo muy por encima el 16f877, pero en la comunicacion con pc si se me hace muy dificil.


----------



## Larva93 (Mar 12, 2012)

Como hago para agregar mas ejes en el codigo? .. necesito al menos 3 ejes mas.

Desde ya muchas gracias.

PD: Probé este y funciona de maravilla en w7 64bits.


----------



## Ecsar (Abr 5, 2012)

Hola Moyano,

muy bueno tu joystick, podrías indicarme como hacer para tener 4 direcciones digitales, en vez
de los analógicos?

muchas gracias desde ya.


----------



## Ecsar (Abr 16, 2012)

Moyano Jonathan dijo:


> Cualquier duda que tengas comentame y vemos como la resolvemos !



Hola Jonathan,

ya entendí los descriptores, pero al compilarlo con la version de css que comentaste me da este error:


>>> Warning 203 "C:\PICC\drivers\pic18_usb.h" Line 436(1,1): Condition always TRUE
>>> Warning 216 "GAMEPAD.c" Line 96(0,1): Interrupts disabled during call to prevent re-entrancy:  (usb_token_reset)
>>> Warning 216 "GAMEPAD.c" Line 96(0,1): Interrupts disabled during call to prevent re-entrancy:  (usb_flush_in)
      Memory usage:   ROM=12%      RAM=21% - 23%
      0 Errors,  3 Warnings.


puede ser porque me falte alguna librería?
por ahí vi un manual creo que era tuyo para configurar mplab ide con css para compilar,
pero tuve que formatear y no lo encuentro, lo tienes por ahí porfa?


Gracias por tu tiempo.


----------



## lubeck (Abr 16, 2012)

seguro que es un Error???, que querrá decir Warning???


----------



## Ecsar (Abr 16, 2012)

lubeck dijo:


> seguro que es un Error???, que querrá decir Warning???



Hola Lubeck,

ya se que es una advertencia, me lo compila, pero cuando meto el .hex en proteus me reinicia la pc.

Gracias por responder.

saludos.


----------



## AReyes (Jun 18, 2012)

Hola que tal, he probado el circuito y tengo un problema, resulta que a veces el PC si reconoce el joystick, a veces dice que tiene problemas y otras tantas (la mayoría) ni aparece en el PC, es como si estuviera muerto por completo, ya revise la tensión que debería caer en cada parte y esta bien, también he programado varias veces el PIC y nada.

El joystick lo tengo que en protoboard, ya probe varias protoboards y solde algunos cables para garantizar el contacto, y aún así, no consigo que funcione....

Que podrá ser ??


----------



## alaroa (Jun 22, 2012)

Hola a todos, 

No he visto si tienen esto en el foro pero espero que sea mi aportación.

La conexión en MAC es mas facil realizarla con HID porque si no se hace así la programación se complica, y si que se complica, existe en la pagina http://www.signal11.us/oss/hidapi/hidapi/doxygen/html/index.html una librería que facilita la conexión.

Este es el programa que yo hice de ejemplo, es solo un contador y una entrada analógica y para la salida son digitales por el puerto B, el programa esta echo en xcode. Espero que les sirva de algo.


----------



## sonystark (Dic 25, 2014)

Como puedo aumentar hut o direccionales digitales


----------



## Fuegomp3 (Sep 16, 2020)

Que tal gente, ando buscando un poco de ayuda, resulta que quiero armar una interface para dos joysticks. Usando un solo pic18f2550, quiero que windows lo reconozca como dos joysticks independientes, como no soy programador, busque algo ya hecho y no consegui nada que funcione, asi que me puse a leer y modificar algunos codigos fuentes que hay en este mismo foro, por ejemplo los de Jonathan Moyano y los de Leamneesom, pero no logro que funcione, apenas windows reconoce el dispositivo pero no lo puede iniciar. Les dejo el codigo a ver i alguno encuentra el error de por que no puede iniciar siquiera uno de los dos joysticks,

Codigo del descriptor:

```
// Descriptores para GAMEPAD USB.

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>


   const char USB_CLASS_SPECIFIC_DESC[] = {

      0x05, 0x01, // usage page (generic desktop Choose the usage page "mouse" is on
      0x09, 0x05, // usage Device is a gamepad
      0xA1, 0x01, // collection (application) This collection encompasses the report format
      0x09, 0x01, // usage (pointer) Choose the key code usage page
      0xA1, 0x00, // collection (physical) Physical collection
      0x85, 0x01, // REPORT ID 1
      0x09, 0x30, // usage (X) X direction of pointer
      0x09, 0x31, // usage (Y) Y direction of pointer
      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)
      0x95, 0x02, // report count (2) Two reports, eight bit each
      0x81, 0x02, // input (data, variable, absolute)
      0xC0,       // end collection

      0x05, 0x09, // usage page (buttons) Choose the “button” usage page
      0x19, 0x01, // usage minimum (1) There are three buttons
      0x29, 0x08, // usage maximum (8)
      0x15, 0x00, // logical minimum (0) Each button is represented by one bit
      0x25, 0x01, // logical maximum (1)
      0x95, 0x08, // report count (8) Three reports, one bit each
      0x75, 0x01, // report size (1)
      0x81, 0x02, // input (data, variable, absolute)
      0xC0,       // end collection

      0x05, 0x01, // usage page (generic desktop Choose the usage page "mouse" is on
      0x09, 0x05, // usage Device is a gamepad
      0xA1, 0x01, // collection (application) This collection encompasses the report format
      0x85, 0x02, // REPORT ID 2
      0x09, 0x01, // usage (pointer) Choose the key code usage page
      0xA1, 0x00, // collection (physical) Physical collection
      0x09, 0x30, // usage (X) X direction of pointer
      0x09, 0x31, // usage (Y) Y direction of pointer
      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)
      0x95, 0x02, // report count (2) Two reports, eight bit each
      0x81, 0x02, // input (data, variable, absolute)
      0xC0,       // end collection

      0x05, 0x09, // usage page (buttons) Choose the "button" usage page
      0x19, 0x01, // usage minimum (1) There are three buttons
      0x29, 0x08, // usage maximum (8)
      0x15, 0x00, // logical minimum (0) Each button is represented by one bit
      0x25, 0x01, // logical maximum (1)
      0x95, 0x08, // report count (8) Three reports, one bit each
      0x75, 0x01, // report size (1)
      0x81, 0x02, // input (data, variable, absolute)
      0xC0,       // end collection

   };

   //if a class has an extra descriptor not part of the config descriptor,
   // this lookup table defines where to look for it in the const
   // USB_CLASS_SPECIFIC_DESC[] array.
   //first element is the config number (if your device has more than one config)
   //second element is which interface number
   //set element to 0xFFFF if this config/interface combo doesn't exist
   const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP[USB_NUM_CONFIGURATIONS][2] =
   {
   //config 1
      //interface 0
         0,     
      //interface 1
         50
   };

   //if a class has an extra descriptor not part of the config descriptor,
   // this lookup table defines the size of that descriptor.
   //first element is the config number (if your device has more than one config)
   //second element is which interface number
   //set element to 0xFFFF if this config/interface combo doesn't exist
   const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[USB_NUM_CONFIGURATIONS][2] =
   {
   //config 1
      //interface 0
       49,  //sizeof(USB_CLASS_SPECIFIC_DESC)
      //interface 1
       49
};



//////////////////////////////////////////////////////////////////
///
///   start config descriptor
///   right now we only support one configuration descriptor.
///   the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

   #DEFINE USB_TOTAL_CONFIG_LEN      59 //config+interface+class+endpoint

   const char USB_CONFIG_DESC[] = {
   //IN ORDER TO COMPLY WITH WINDOWS HOSTS, THE ORDER OF THIS ARRAY MUST BE:
      //    config(s)
      //    interface(s)
      //    class(es)
      //    endpoint(s)

   //config_descriptor for config index 1
         USB_DESC_CONFIG_LEN, //length of descriptor size          ==1
         USB_DESC_CONFIG_TYPE, //constant CONFIGURATION (CONFIGURATION 0x02)     ==2
         USB_TOTAL_CONFIG_LEN,0, //size of all data returned for this config      ==3,4
         2, //number of interfaces this device supports       ==5
         0x01, //identifier for this configuration.  (IF we had more than one configurations)      ==6
         0x00, //index of string descriptor for this configuration      ==7
         0xC0, //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 unused and bit7=1         ==8
         0x32, //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA)

   //interface descriptor 1
         USB_DESC_INTERFACE_LEN, //length of descriptor      =10
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =11
         0x00, //number defining this interface (IF we had more than one interface)    ==12
         0x00, //alternate setting     ==13
         1, //number of endpoins, except 0 (pic167xx has 3, but we dont have to use all).       ==14
         0x03, //class code, 03 = HID     ==15
         0x00, //subclass code //boot     ==16
         0x00, //protocol code      ==17
         0x02, //index of string descriptor for interface      ==18

   //class descriptor 1  (HID)
         USB_DESC_CLASS_LEN, //length of descriptor    ==19
         USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID)      ==20
         0x01,0x01, //hid class release number (1.0) (try 1.10)      ==21,22
         0x00, //localized country code (0 = none)       ==23
         0x00, //number of hid class descrptors that follow (1)      ==24
         0x22, //report descriptor type (0x22 == HID)                ==25
         USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][0], 0x00, //length of report descriptor            ==26,27

   //endpoint descriptor 1
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==28
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==29
         0x81, //endpoint number and direction (0x81 = EP1 IN)       ==30
         0x03, //USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt)         ==31
         USB_EP1_TX_SIZE,0x00, //maximum packet size supported                  ==32,33
         10  //polling interval, in ms.  (cant be smaller than 10 for slow speed devices)     ==34
 
   //interface descriptor 2
         USB_DESC_INTERFACE_LEN, //length of descriptor      =35
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =36
         0x01, //number defining this interface (IF we had more than one interface)    ==37
         0x00, //alternate setting     ==38
         1, //number of endpoins, except 0 (pic167xx has 3, but we dont have to use all).       ==39
         0x03, //class code, 03 = HID     ==40
         0x00, //subclass code //boot     ==41
         0x00, //protocol code      ==42
         0x03, //index of string descriptor for interface      ==43

   //class descriptor 2  (HID)
         USB_DESC_CLASS_LEN, //length of descriptor    ==44
         USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID)      ==45
         0x01,0x01, //hid class release number (1.0) (try 1.10)      ==46,47
         0x00, //localized country code (0 = none)       ==48
         0x00, //number of hid class descrptors that follow (0)      ==49
         0x22, //report descriptor type (0x22 == HID)                ==50
         USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][1], 0x00, //length of report descriptor            ==51,52

   //endpoint descriptor 2
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==53
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==54
         0x82, //endpoint number and direction (0x82 = EP2 IN)       ==55
         0x03, //USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt)         ==56
         USB_EP2_TX_SIZE,0x00, //maximum packet size supported                  ==57,58
         10  //polling interval, in ms.  (cant be smaller than 10 for slow speed devices)     ==59
      
   };


   //****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
   //since we can't make pointers to constants in certain pic16s, this is an offset table to find
   //  a specific descriptor in the above table.

   //NOTE: DO TO A LIMITATION OF THE CCS CODE, ALL HID INTERFACES MUST START AT 0 AND BE SEQUENTIAL
   //      FOR EXAMPLE, IF YOU HAVE 2 HID INTERFACES THEY MUST BE INTERFACE 0 AND INTERFACE 1
   #define USB_NUM_HID_INTERFACES   2

   //the maximum number of interfaces seen on any config
   //for example, if config 1 has 1 interface and config 2 has 2 interfaces you must define this as 2
   #define USB_MAX_NUM_INTERFACES   2

   //define how many interfaces there are per config.  [0] is the first config, etc.
   const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={2};

   //define where to find class descriptors
   //first dimension is the config number
   //second dimension specifies which interface
   //last dimension specifies which class in this interface to get, but most will only have 1 class per interface
   //if a class descriptor is not valid, set the value to 0xFFFF
   const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS][2][1]=
   {
   //config 1
      //interface 0
         //class 1
         18,
   //config 1
      //interface 1
         //class 1
         43
   };


   #if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
      #error USB_TOTAL_CONFIG_LEN not defined correctly
   #endif


//////////////////////////////////////////////////////////////////
///
///   Descriptores del dispositivo
///
//////////////////////////////////////////////////////////////////

   const char USB_DEVICE_DESC[USB_DESC_DEVICE_LEN] ={
         USB_DESC_DEVICE_LEN, // Longitud del reporte.
         0x01, // Constante del dispositivo = 1
         0x00,0x02, // Versión del USB 1.10.
         0x00, // Código de clase.
         0x00, // Código de subclase.
         0x00, // Código de protocolo.
         USB_MAX_EP0_PACKET_LENGTH, // Tamaño máximo del paquete de datos del endpoint 0 = 8 para HID.
         0x81,0x17, // Vendor  id =  decimal(6017), hexadecimal(1781) // Identificadores de easyHID.
         0xD0,0x07, // Product id =  decimal(2000), hexadecimal(7D0)
         0x00,0x01, // Número del dispositivo.
         0x01,
         0x02,
         0x00,
         USB_NUM_CONFIGURATIONS  // Número de posibles configuraciones.
   };

   #if (sizeof(USB_DEVICE_DESC) != USB_DESC_DEVICE_LEN)
      #error USB_DESC_DEVICE_LEN not defined correctly
   #endif

//////////////////////////////////////////////////////////////////
/// Descriptores del fabricante
//////////////////////////////////////////////////////////////////


char USB_STRING_DESC_OFFSET[]={0,4,14,46};

char const USB_STRING_DESC[]={
   // Primer descriptor.
         4, // Longitud del descriptor. 1
         USB_DESC_STRING_TYPE, // 2
         0x09,0x04,   // Lenguaje id = Inglés (Definido por microsoft). 3,4
   // Segundo descriptor.
         10, // Longitud del descriptor. 5
         USB_DESC_STRING_TYPE, // Descriptor del compilador utilizado. (STRING) (Puede ser el nombre de la compañía) 6
         'C',0, //7,8
         'C',0, //9,10
         's',0, //11,12
         'P',0, //13,14
        
   // Tercer descriptor.
         32, //length of string index //15
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING) //16
         'A',0, //17,18
         'R',0, //19,20
         'C',0, //23,24
         'A',0, //25,26
         'D',0, //27,28
         'E',0, //29,30
         ' ',0, //31,32
         'J',0, //33,34
         'O',0, //35,36
         'Y',0, //37,38
         'S',0, //39,40
         'T',0, //41,42
         'I',0, //43,44
         'C',0, //45,46
         'K',0, //47,46
    
   // Cuarto desciptor
         22, //length of string index //47
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING) //50
         'J',0, //51,52
         'O',0, //53,54
         'Y',0, //55,56
         'S',0, //57,58
         'T',0, //59,60
         'I',0, //61,62
         'C',0, //63,64
         'K',0, //65,66
         ' ',0, //67,68
         '2',0, //69,70

};

#ENDIF
```

Desde ya agradezco alguna orientacion de que me esta faltando o le estoy errando


Codigo del Joystick:

```
// Programa de control para probar un GAMEPAD compuesto por 1 control analógico y 8 botones digitales.
// Utilizaremos un PIC18F2550 con conexión USB.
// Programador: Moyano Jonathan
// Librerías de descriptores: Programada por LIAMNESSON y modificada para uso personal.
// 30/03/09
//*****************************************************************************************************

#include <18F2550.h> // Definición de registros internos del PIC18F2550.
#device ADC=8 // CAD a 8 bits, justificación a a la derecha.
#fuses NOMCLR,HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN
// NOMCLR: No vamos ha usar el PIN MCLR, el reset se hará por soft.
// XTPLL: Vamos a usar un cristal de 4.00Mhz.
// NOWDT: No vamos a usar el perro guardian.
// NOPROTECT: Memoria no protejida contra lecturas.
// NODEBUG: No utilizamos código para debugear.
// NOLVP: No utilizamos el modo de programación con bajo voltaje.
// USBDIV: signfica que el clock del usb se tomará del PLL/2 = 96Mhz/2 = 48Mhz.
// PLL1: significa que el PLL prescaler no dividirá la frecuencia del cristal. para XT = 4Mhz.
// CPUDIV1: El PLL postscaler decide la división en 2 de la frecuencia de salida del PLL de 96MHZ, si queremos 48MHZ, lo dejamos como está.
// VREGEN: habilita el regulador de 3.3 volts que usa el módulo USB.
// NOPBADEN: Deshabilitamos el módulo conversor ADC del puerto B.

#use delay(clock=48000000)


#DEFINE USB_HID_DEVICE TRUE // Vamos a utilizar el protocolo HID.

// Solamente definimos el buffer de salida ya que solamente enviaremos datos a la PC.

#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT
#define USB_EP1_TX_SIZE 4 // Definición del tamaño del buffer de salida.
#define USB_EP2_TX_ENABLE USB_ENABLE_INTERRUPT
#define USB_EP2_TX_SIZE 4 // Definición del tamaño del buffer de salida.

/*********************************************************************************************************/

// Definición de las librerías utilizadas.
#include <pic18_usb.h>    // Drivers's USB del PIC18F2550.
#include <joystick-2.h> // Descriptores USB para el GAMEPAD.
#include <usb.c> // Funciones del USB.

/*********************************************************************************************************/

// Comienza programa principal.

void main(void) {

int envia[3]; // Definimos los 3 bytes a enviar al EP1.
#define     eje_x       envia[0]     // Byte del eje X del mando analógico.                         
#define     eje_y       envia[1]     // Byte del eje Y del mando analógico.
#define     botones     envia[2]     // Byte de los 8 botones del PAD.

int envia2[3]; // Definimos los 3 bytes a enviar al EP2.
#define     eje_x2       envia2[0]     // Byte del eje X del mando analógico.                         
#define     eje_y2       envia2[1]     // Byte del eje Y del mando analógico.
#define     botones2     envia2[2]     // Byte de los 8 botones del PAD.

int botonera; // Variable que toma el valor de los botones presionados.
int botonera2; // Variable que toma el valor de los botones presionados.
                                                              
output_b(0x00); // Limpiamos el puerto B.
output_c(0x00); // Limpiamos el puerto C.
// Configuraciones varias:
   disable_interrupts(global);
   disable_interrupts(int_timer1);
   disable_interrupts(int_rda);
   disable_interrupts(int_ext);
   disable_interrupts(int_ext1);
   disable_interrupts(int_ext2);
   setup_spi(FALSE);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   port_b_pullups(FALSE);
   //port_c_pullups(FALSE);

   setup_adc_ports(AN0_TO_AN3 || VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_64);


// Iniciamos el USB.
      usb_init();                           // Inicializamos el USB.
      usb_wait_for_enumeration();           // Esperamos hasta que el dispositivo sea configurado por la PC.
      while(true) {
      usb_task();                                                         // Habilita el periferico usb y las interrupciones.

        if (usb_enumerated()) // Si el puerto es enumerado y configurado por el host..
                  {

                          set_adc_channel(0); // Selecciono el canal de conversión para el eje X.
                          delay_us(10); // Espero 10uS, a que termine la conversión.
                          eje_x = read_adc(); // Guardamos el valor de la variable.

                          set_adc_channel(1); // Selecciono el canal de conversión para el eje Y.
                          delay_us(10); // Espero 10uS, a que termine la conversión.
                          eje_y = read_adc(); // Guardamos el valor de la variable.

                          botonera = input_b(); // Tomamos el valor de los botones.
                          botones = botonera;   // Guardamos el valor de la variable.
                          usb_put_packet(1,envia,3,USB_DTS_TOGGLE);   // Enviamos los datos por USB.

                          set_adc_channel(2); // Selecciono el canal de conversión para el eje X.
                          delay_us(10); // Espero 10uS, a que termine la conversión.
                          eje_x2 = read_adc(); // Guardamos el valor de la variable.

                          set_adc_channel(3); // Selecciono el canal de conversión para el eje Y.
                          delay_us(10); // Espero 10uS, a que termine la conversión.
                          eje_y2 = read_adc(); // Guardamos el valor de la variable.

                          botonera2 = input_c(); // Tomamos el valor de los botones.
                          botones2 = botonera2;   // Guardamos el valor de la variable.
                          usb_put_packet(1,envia2,3,USB_DTS_TOGGLE);   // Enviamos los datos por USB

                      }

                      }
}
```


----------



## bidomo (Oct 6, 2020)

Buenas gente!

Alguna manera de escribir este código en 2020?


----------



## cosmefulanito04 (Oct 6, 2020)

Fuegomp3 dijo:


> Que tal gente, ando buscando un poco de ayuda, resulta que quiero armar una interface para dos joysticks. Usando un solo pic18f2550, quiero que windows lo reconozca como dos joysticks independientes, como no soy programador, busque algo ya hecho y no consegui nada que funcione, asi que me puse a leer y modificar algunos codigos fuentes que hay en este mismo foro, por ejemplo los de Jonathan Moyano y los de Leamneesom, pero no logro que funcione, apenas windows reconoce el dispositivo pero no lo puede iniciar. Les dejo el codigo a ver i alguno encuentra el error de por que no puede iniciar siquiera uno de los dos joysticks



Yo hace poco estuve jugando con esto para armarme un conversor gamport a usb (no usé el uC que estás usando). ¿Te aparece en windows el dispositivo?

El descriptor pareciera estar bien, salvo que lo inicias como gampad en vez de joystick:


```
0x09, 0x05, // usage Device is a gamepad
```

En vez de:


```
0x09, 0x04, // usage Device is a joystick
```

No creo que eso sea un problema en si, pero si queremos un joystick, avisémosle al SO lo que realmente es.

Te puedo pasar los descriptores con los que estuve jugando, pero antes te recomendaría que trates de hacer funcionar un joystick a la vez y después implementes el 2do.


----------



## Fuegomp3 (Oct 8, 2020)

Gracias Cosme por responder. El codigo que puse arriba tenia muchas fallas, al final termine optando por usar dos interfaces separadas y listo, con un .HEX ya bastante conocido como es el de Willynovi, 4 ejes y 32 botones.

Saludos, y nuevamente gracias.


----------

