Controlador MIDI por USB con PIC para Virtual Dj

Que desesperación, sigue sin funcionar. ¿Podeis enviarme el descriptor hid que utilizais? Sólo ahí me queda el fallo.

yo utilizo este
Código:
-------------------------------------------------------------------
The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.
********************************************************************/
 
/*********************************************************************
 * Descriptor specific type definitions are defined in:
 * usb_device.h
 *
 * Configuration options are defined in:
 * usb_config.h
 ********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C
/** INCLUDES *******************************************************/
#include "GenericTypeDefs.h"
#include "Compiler.h"
#include "usb_config.h"
#include "usb_device.h"
#include "usb_function_hid.h"
/** CONSTANTS ******************************************************/
#if defined(__18CXX)
#pragma romdata
#endif
/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
    0x12,    // Size of this descriptor in bytes
    USB_DESCRIPTOR_DEVICE,                // DEVICE descriptor type
    0x0200,                 // USB Spec Release Number in BCD format
    0x00,                   // Class Code
    0x00,                   // Subclass code
    0x00,                   // Protocol code
    USB_EP0_BUFF_SIZE,          // Max packet size for EP0, see usb_config.h
    MY_VID,                 // Vendor ID
    MY_PID,                 // Product ID: Mouse in a circle fw demo
    0x0107,//0x0003,                 // Device release number in BCD format
    0x01,                   // Manufacturer string index
    0x02,                   // Product string index
    0x00,                   // Device serial number string index
    0x01                    // Number of possible configurations
};
/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
    /* Configuration Descriptor */
    0x09,//sizeof(USB_CFG_DSC),    // Size of this descriptor in bytes
    USB_DESCRIPTOR_CONFIGURATION,                // CONFIGURATION descriptor type
    DESC_CONFIG_WORD(0x0026),   // Total length of data for this cfg
    1,                      // Number of interfaces in this cfg
    1,                      // Index value of this configuration
    0,                      // Configuration string index
    0x80,//_DEFAULT | _SELF,               // Attributes, see usb_device.h
    250,                     // Max power consumption (2X mA)
    /* Interface Descriptor */
    0x09,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
    USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
    0,                      // Interface Number
    0,                      // Alternate Setting Number
    1,                      // Number of endpoints in this intf
    HID_INTF,               // Class code
    BOOT_INTF_SUBCLASS,     // Subclass code
    HID_PROTOCOL_NONE,     // Protocol code
    0,                      // Interface string index
    /* HID Class-Specific Descriptor */
    0x09,//sizeof(USB_HID_DSC)+3,    // Size of this descriptor in bytes RRoj hack
    DSC_HID,                // HID descriptor type
    DESC_CONFIG_WORD(0x0110),                 // HID Spec Release Number in BCD format (1.11)
    0x21,                   // Country Code (0x00 for Not supported)
    HID_NUM_OF_DSC,         // Number of class descriptors, see usbcfg.h
    DSC_RPT,                // Report descriptor type
    DESC_CONFIG_WORD(67),   //sizeof(hid_rpt01),      // Size of the report descriptor
 
    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    HID_EP | _EP_IN,            //EndpointAddress
    _INTERRUPT,                       //Attributes
    DESC_CONFIG_WORD(8),                  //size
    0x0A                        //Interval
};
 
//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};
//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};
//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'V','i','r','t','u','a','l',' ','D','j','s',' ','C','o','n','t','r','o','l','l','e','r'
}};
//Class specific descriptor - HID mouse
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
//    {0x05, 0x01, /* Usage Page (Generic Desktop)             */
//    0x09, 0x02, /* Usage (Mouse)                            */
//    0xA1, 0x01, /* Collection (Application)                 */
//    0x09, 0x01, /*  Usage (Pointer)                         */
//    0xA1, 0x00, /*  Collection (Physical)                   */
//    0x05, 0x09, /*      Usage Page (Buttons)                */
//    0x19, 0x01, /*      Usage Minimum (01)                  */
//    0x29, 0x03, /*      Usage Maximum (03)                  */
//    0x15, 0x00, /*      Logical Minimum (0)                 */
//    0x25, 0x01, /*      Logical Maximum (0)                 */
//    0x95, 0x03, /*      Report Count (3)                    */
//    0x75, 0x01, /*      Report Size (1)                     */
//    0x81, 0x02, /*      Input (Data, Variable, Absolute)    */
//    0x95, 0x01, /*      Report Count (1)                    */
//    0x75, 0x05, /*      Report Size (5)                     */
//    0x81, 0x01, /*      Input (Constant)    ;5 bit padding  */
//    0x05, 0x01, /*      Usage Page (Generic Desktop)        */
//    0x09, 0x30, /*      Usage (X)                           */
//    0x09, 0x31, /*      Usage (Y)                           */
//    0x15, 0x81, /*      Logical Minimum (-127)              */
//    0x25, 0x7F, /*      Logical Maximum (127)               */
//    0x75, 0x08, /*      Report Size (8)                     */
//    0x95, 0x02, /*      Report Count (2)                    */
//    0x81, 0x06, /*      Input (Data, Variable, Relative)    */
//    0xC0, 0xC0}
{
   0x05, 0x01,         //Usage Page (Generic Desktop)
   0x09, 0x04,         //Usage (Joystick)
   0xA1, 0x01,         //Collection (Application) 
   0xA1, 0x02,            //Collection (Logical)
   0x75, 0x08,               //Report size (8)
   0x95, 0x04,               //Report count (4)
   0x15, 0x00,               //Logical Minimum (-127)
   0x26, 0xFF, 0x00,         //Logical Maximum (128)
   0x35, 0x00,               //Physical Minumum (0)
   0x46, 0xFF, 0x00,         //Physical Maximum (255)
   0x09, 0x30,               //Usage (X)
   0x09, 0x31,               //Usage (Y)
   0x09, 0x32,               //Usage (Z)
   0x09, 0x35,               //Usage (Rz)
   0x81, 0x02,               //Input (Data, Variable, Absolute)
   0x75, 0x08,               //Report size (8)
   0x95, 0x01,               //Report count (1)
   0x25, 0x07,               //Logical Maximum (7)
   0x46, 0x3B, 0x01,         //Physical Maximum (315)
   0x65, 0x14,               //Unit (Eng Rot: Degree)
   0x09, 0x39,               //Usage (Hat switch)
   0x81, 0x42,               //
   0x65, 0x00,               //Unit (None)
   0x75, 0x01,               //Report size (1)
   0x95, 0x08,               //Report count (8)
   0x25, 0x01,               //Logical Maximum (1)
   0x45, 0x01,               //Physical Maximum (1)
   0x05, 0x09,               //Usage Page (Button)
   0x19, 0x01,               //Usage Minumum (Button 1)
   0x29, 0x08,               //Usage Maximum (Button 8)
   0x81, 0x02,               //Input (Data, Variable, Relative) 
   0xC0,               //End collection
   0xC0            //End collection
 
////   size 53
//   0x05, 0x01,
//   0x09, 0x04,
//   0xa1, 0x01,
//    0x09, 0x01,
//   0xa1, 0x00,
//   0x75, 0x08,
//   0x95, 0x04,
//   0x15, 0x00,
//   0x25, 0xff,
//   0x35, 0x00,
//   0x46, 0xff, 0x00,
//   0x05, 0x01,
//   0x09, 0x30,
//   0x09, 0x31,
//   0x09, 0x32,
//   0x09, 0x35,
//   0x81, 0x02,
//   0x75, 0x01,
//   0x95, 0x08,
//   0x25, 0x01,
//   0x45, 0x01,
//   0x05, 0x09,
//   0x19, 0x01,
//   0x29, 0x08,
//   0x81, 0x02,
//   0xc0, 
//   0xc0
}
};/* End Collection,End Collection            */
//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
    (ROM BYTE *ROM)&configDescriptor1
};
//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
    (ROM BYTE *ROM)&sd000,
    (ROM BYTE *ROM)&sd001,
    (ROM BYTE *ROM)&sd002
};
/** EOF usb_descriptors.c ***************************************************/
#endif
Ver el archivo adjunto hid.rar
a lo mejor te sirve yo aun no puedo recibir nada pero si puedo enviar
 
Última edición:
Les comento que lo mejor no es usar un descriptor de gamepad, tiene muchas limitaciones, por ejemplo un maximo de 8 analogicos. Usen un hid generico, busquen ejemplos en google para sus lenguajes de programación, hay mucha info ;)
 
Les comento que lo mejor no es usar un descriptor de gamepad, tiene muchas limitaciones, por ejemplo un maximo de 8 analogicos. Usen un hid generico, busquen ejemplos en google para sus lenguajes de programación, hay mucha info ;)
si creo que ese es mi problema solo puedo hacer funcionar 7 potes el descriptor es de un gamepad ahora creo que empezare de nuevo con otro descriptor
 
Ah si es con CCS no te puedo ayudar porque yo también estoy aprendiendo ;) muy de a poco porque no tengo tiempo libre. El CCS se ve bueno pero en el proton ide escribo menos jeje!

Tenemos que ver el tema de las jogwheels, les paso un para de links:
http://www.instructables.com/id/HDDJ-Turning-an-old-hard-disk-drive-into-a-rotary/

El ultimo video es similar a lo que te comenté por privado rachelies... pero en vez de estar ubicados en esas barritas van en algo que se asemeje a una bateria :D
 
Lo de los jogwheels no parece tan dificil los datos que envia un denon los capture y son repetitivos esto es lo que envia

TIMESTAMP IN PORT STATUS DATA1 DATA2 CHAN NOTE EVENT

00057636 10 1 B3 25 00 4 --- Control Change
00059C53 10 1 B3 25 7F 4 --- Control Change
00059D92 10 1 B3 25 00 4 --- Control Change
0005A1FD 10 1 B3 25 7F 4 --- Control Change
0005A33C 10 1 B3 25 00 4 --- Control Change
0005AC98 10 1 B3 25 7F 4 --- Control Change
0005AD8E 10 1 B3 25 00 4 --- Control Change
0005B913 10 1 B3 25 7F 4 --- Control Change
0005B9D7 10 1 B3 25 00 4 --- Control Change

si giras a la izquierda solo cambia el b3 por b2 parecido a un encoder que una vez hice
para contar las espiras de una maquina de rebobinar
 
Eso si está claro, incluso en hid es cambiar un bit unicamente y ya lo hice... con dos pulsadores manejaba el scratch un paso adelante y un paso atrás.
A lo que voy es al tema hardware y a la lectura con el pic, eso todavia no lo estudié pero tengo entendido que es con interrupciones. Igual con el pic trabajando a 48Mhz no se si hace falta, es más, en una parte del midibox conectan multiples encoders a la placa Din y la misma no crea ninguna interrupcion.
 
A ver si esta tarde tengo tiempo a probar algo más en hid, si no, dejo mi controlador en midi que funciona bien. Lo de la latencia del midi es con el midi tradicional, pero por usb no tiene porque tener latencia. El usb va mucho más rápido que lo que el oido puede percibir, jajajaja.
Yo mi jogwhell lo hice con dos discos duros, y en el programa hice esto para enviar por midi:
Código:
////////////////////////////////////////////////////
//interrupción para pulsos encoder
////////////////////////////////////////////////////
#int_EXT2
void EXT2_isr()
{	
		//giro derecha
	if(!bit_test(INTCON2,4)) 		//entra por flanco bajada
		{	if(bit_test(PORTA,1)) p1=4;
			if(!bit_test(PORTA,1)) p1=1;
		}
		//giro izqierda
	if(bit_test(INTCON2,4))			//entra por flanco subida
		{ 	if(bit_test(PORTA,1)) p1=3;
			if(!bit_test(PORTA,1)) p1=2;
		}
	
	INTEDGE=!INTEDGE;
	
	if(p1==2||p1==4) encoderA=0x01;
	if(p1==1||p1==3) encoderA=0x7F;
	//if(encoderA>0x7F) encoderA=0x01;
	//if(encoderA<0x01) encoderA=0x7F;

	pulsos[3]=encoderA;
	usb_put_packet(1,pulsos,4,USB_DTS_TOGGLE);
}

Esto sería solo para uno de ellos. Utilizo dos entradas, y con una interrupcion entro en esta subrutina, detecto si el cambio para entrar en la subrutina fue un flanco de subida o de bajada, y después escaneo como está el otro pin, y así se si estoy girando a derecha o a izquierda. Envío 0x7F cuando giro a derecha o 0x01 cuando giro a izquierda, aunque estos valores no estoy seguro de que estén bien para VirtualDj, ya que también estuve haciendo pruebas con el Traktor y ahora no recuerdo de cual eran.

Otra desventaja que encuentro al HID es que no me vale con el Traktor, que solo admite Midi.
Un saludo y gracias por colaborar
 
Eso si está claro, incluso en hid es cambiar un bit unicamente y ya lo hice... con dos pulsadores manejaba el scratch un paso adelante y un paso atrás.
A lo que voy es al tema hardware ....
Lo del hardware tampoco se ve muy dificil mira esto
thump_75255746scap9ndpmcao52jlmca.jpg

para conectar un motor de paso como encoder

thump_7525583rotaryencodercloseup.jpg

este es óptico parecido a los que traen los controladores comerciales
claro que es mas facil decirlo que hacerlo pero en google encontraras mucha info
mira esta es con un raton viejo
Ver el archivo adjunto Como hacer un encoder óptico usando partes de un mouse mecánico.pdf
 
El circuito que tengo yo para utilizar el disco duro es este que adjunto.
No hace falta alimentar el motor ni nada, solo con 3 pines: uno para el canal A, otro para el B y otro que uno a la masa del circuito. Es muy muy sensible, con moverlo muy poco ya da pulsos, y a la salida del operacional tenemos +5V para meter al PIC.
 

Adjuntos

  • Encoder.jpg
    Encoder.jpg
    101.2 KB · Visitas: 64
Otra desventaja que encuentro al HID es que no me vale con el Traktor, que solo admite Midi.
Y bueno, todo en la vida no se puede ;) pero en ese caso si la haces con HID podés usar el programa GLOVEPIE como puente entre el HID y el MIDI... yo hace unos dias tomé mi wiimote (que para la pc es un dispositivo hid) y usaba los acelerometros y demas para manejar el Ableton live.
Con la camara y un led infrarrojo sensando la posición en x y en y se podria hacer un theremin o manejar un efecto, la verdad es muy interesante todo lo que se puede hacer con el aparatito :D
Respecto al tema de las jogwheels, voy a probar esos esquemas, porque una vez armé uno que vi para eso y me quedaban los tres leds encendidos y como me dió bronca porque en vez de hacerlo en el protoboard lo hice en pcb y no anduvo no probé más...
Y se puede hacer sin interrupciones lo de los encoders creo, porque en la imagen adjunta se ve eso. Con el pic trabajando a 48Mhz se pueden detectar los cambios por mas rapidos que sean...
 

Adjuntos

  • MULTIPLES ENCODERS.jpg
    MULTIPLES ENCODERS.jpg
    50 KB · Visitas: 59
Claro que se puede hacer sin interrupciones, pero a mi me gusta más con interrupciones para no ocupar el micro constantemente escaneando las entradas. Para eso están las interrupciones, jejeje

Por cierto, muy bueno el video!!!
 
Me aclaraste la duda que tenia, gracias!
Alguien usó el encoder de la rueda de scroll de un mouse? porque por lo visto no larga dos señales en cuadratura... voy a probarlo de nuevo :)
 
Lo de la latencia del midi es con el midi tradicional, pero por usb no tiene porque tener latencia. El usb va mucho más rápido que lo que el oido puede percibir, jajajaja.
Sea tradicional o usb mis oidos hasta hace poco trabajaban a 1 Gb/s, asi que si noto la latencia, o bueno... por lo menos hasta unos 10 microsegundos.
Probe con el ultimo circuito ya que tenia los componentes a mano y me funcionó, es normal que quede un led encendido? digo, porque cuando el disco está quieto no hay ninguna tensión generada...
En cuanto pueda edito y subo el video
 
Lo prometido es deuda:
http://www.youtube.com/watch?v=Ts5YuJo7Wkk&feature=youtu.be
Tenia un problemita, el pic lo habia programado para que me mande tres pulsos en un sentido y uno en el inverso... y me colgaba el vdj, cual era el problema? que en el device habia especificado un reporte de leds hacia el pic y no lo estaba usando. Cuando le elimine esa parte funcionó bien, ahora me falta hacer el código para los encoders. Se dan cuenta que hicimos una consola que puede competir con las comerciales que son muchisimo mas costosas? he visto de 2500 pesos!
 
Última edición:
Rachelies como puedo leer el o los encoders sin usar interrupciones? tenés los "pasos" a seguir o algún ejemplo?

A ver si esta noche te lo puedo hacer, que es muy fácil, pero ahora estoy en el trabajo y no llegaré hasta la noche. No se si has entendido el ejemplo que puse con interrupciones, pero yo asigno a cada combinación un número:

p1=1 es Canal A bajo, canal B bajo
p1=2 canal A alto, canal B bajo
p1=3 canal A alto, canal B alto
p1=4 canal A bajo, canal B alto

Bueno, nada más que pueda te hago el código, que es simple.

Saludos
 
Lo logré, era cuestión de pensar un poquito lo que hacia el encoder y lo que yo queria :D
Con el esquema de los dos operacionales tengo un problema, que en vez de quedar las dos salidas en 0 hay una que permanece en 1... hasta que le quito el cristal al pic :) no se como solucionarlo, voy a ver si conecto la pata inversora de ese operacional a un divisor resistivo en vez de ponerla directo a masa.
Con la velocidad estoy satisfecho, pero de la resolución no hablemos mejor. Posiblemente termine utlizando un encoder óptico de un mouse, o, utilizando un motor diferente...
 
Bueno, me alegro que lo hayas logrado, no era muy dificil... ¿No te gusta la resolución? Hace tiempo que hice las pruebas, pero no recuerdo que me fuese mal con ello. ¿Serán todos los discos duros iguales?
Y tampoco recuerdo si quedaban a cero las dos salidas del operacional, pero creo que no, que según parabas así se quedaban, tendria que comprobarlo otra vez.
 
Atrás
Arriba