Controlador MIDI por USB con PIC para Virtual Dj

Hola foro, decidí tomar el ejemplo de la matriz para los botones que subió rachelies "MIDI_12" pero tengo un problemilla del número de nota 0X00 a la 0X07 envía el valor de volumen de nota 0X7F pero después del número de nota 0X07 todos los valores de volumen de nota son 0X00 esto es lo que me muestra el Miditrace.

90 04 7F 00
90 04 00 00
90 05 7F 00
90 05 00 00
90 06 7F 00
90 06 00 00
90 07 7F 00
90 07 00 00
90 08 00 00
90 08 00 00
90 09 00 00
90 09 00 00
90 0A 00 00
90 0A 00 00

El subprograma de busca diferencias está bien no se a que se deba ustedes me podrían explicar he estado revisando pero no doy con la falla.

Código:
#include <18F4550.h>
#device ADC=8
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN      //~~~ 20MHZ OSCILLATOR CONFIGS ~~~//
#use delay(clock=48000000)


#DEFINE USB_HID_DEVICE     FALSE
#define USB_EP1_TX_ENABLE  USB_ENABLE_BULK  //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP2_RX_ENABLE  USB_ENABLE_BULK  //turn on EP1 for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE    64  //size to allocate for the tx endpoint 1 buffer
#define USB_EP2_RX_SIZE    64   //size to allocate for the rx endpoint 1 buffer

#include <pic18_usb.h>
#include <midi7.h>   //USB Configuration and Device descriptors 
#include <usb.c>           //handles usb setup tokens and get descriptor reports


#use fast_io(A)
#use fast_io(B)
#use fast_io(C)

#byte PORTA=0xF80
#byte PORTB=0xF81
#byte PORTC=0xF82
#byte LATB=0xF8A
#byte INTCON=0xFF2
#byte ADCON1=0XFC1

short bitT;
int tempoA1,tempoA2,tempoA11;
int matriz1,matriz2,matriz1bis,matriz2bis;
int matriz3,matriz4,matriz3bis,matriz4bis;
int diferencias,contador;
unsigned char envia[4];
unsigned char tempA[4];

void envianota()
{   
   envia[1]=0x90;
   envia[0]=envia[1]>>4;
   
   usb_put_packet(1,envia,4,USB_DTS_TOGGLE);
}


void busca_diferencias()
{   diferencias=matriz1^matriz1bis;
   if(diferencias!=0)
      {   contador=0x00;
         while(contador<=0x07)
         { if(bit_test(diferencias,0))
            {   envia[2]=contador;
               bitT=bit_test(matriz1,contador);
               envia[3]=0x7F*bitT;
               envianota();
            }
         contador++;
         rotate_right(&diferencias,1);

      }
      }
   diferencias=matriz2^matriz2bis;
   if(diferencias!=0)
      {   contador=0x08;
         while(contador<=0x0F)
         { if(bit_test(diferencias,0))
            {   envia[2]=contador;
               bitT=bit_test(matriz2,contador);
               envia[3]=0x7F*bitT;
               envianota();
            }
         contador++;
         rotate_right(&diferencias,1);

      }
      }
   diferencias=matriz3^matriz3bis;
   if(diferencias!=0)
      {   contador=0x10;
         while(contador<=0x17)
         { if(bit_test(diferencias,0))
            {   envia[2]=contador;
               bitT=bit_test(matriz3,contador);
               envia[3]=0x7F*bitT;
               envianota();
            }
         contador++;
         rotate_right(&diferencias,1);

      }
      }
   diferencias=matriz4^matriz4bis;
   if(diferencias!=0)
      {   contador=0x18;
         while(contador<=0x1F)
         { if(bit_test(diferencias,0))
            {   envia[2]=contador;
               bitT=bit_test(matriz4,contador);
               envia[3]=0x7F*bitT;
               envianota();
            }
         contador++;
         rotate_right(&diferencias,1);

      }
      }
}

#int_RB
void RB_isr()
{
   matriz1bis=matriz1;
   matriz2bis=matriz2;
   matriz3bis=matriz3;
   matriz4bis=matriz4;
   LATB=PORTB;
   delay_ms(20);
   if(bit_test(PORTB,7)&&bit_test(PORTB,6)&&bit_test(PORTB,5)&&bit_test(PORTB,4))
   {
      matriz1=matriz2=matriz3=matriz4=0;
      busca_diferencias();
      return;
   }
   output_high(PIN_A2);
   output_high(PIN_A3);
   output_high(PIN_A4);
   output_high(PIN_A5);
   output_high(PIN_C0);
   output_high(PIN_C1);
   output_high(PIN_C2);
   delay_cycles(10);
   output_low(PIN_C6);
   delay_cycles(10);
   if(!(bit_test(PORTB,7)&&bit_test(PORTB,6)&&bit_test(PORTB,5)&&bit_test(PORTB,4)))
   {
      if(!bit_test(PORTB,7)) bit_set(matriz4,4);
      else bit_clear(matriz4,4);
      if(!bit_test(PORTB,6)) bit_set(matriz4,5);
      else bit_clear(matriz4,5);
      if(!bit_test(PORTB,5)) bit_set(matriz4,6);
      else bit_clear(matriz4,6);
      if(!bit_test(PORTB,4)) bit_set(matriz4,7);
      else bit_clear(matriz4,7);
      delay_cycles(10);

   }
   output_low(PIN_C2);
   delay_cycles(10);
   output_high(PIN_C6);
   delay_cycles(10);
   if(!(bit_test(PORTB,7)&&bit_test(PORTB,6)&&bit_test(PORTB,5)&&bit_test(PORTB,4)))
   {
      if(!bit_test(PORTB,7)) bit_set(matriz4,0);
      else bit_clear(matriz4,0);
      if(!bit_test(PORTB,6)) bit_set(matriz4,1);
      else bit_clear(matriz4,1);
      if(!bit_test(PORTB,5)) bit_set(matriz4,2);
      else bit_clear(matriz4,2);
      if(!bit_test(PORTB,4)) bit_set(matriz4,3);
      else bit_clear(matriz4,3);
      delay_cycles(10);

   }
   output_low(PIN_C1);
   delay_cycles(10);
   output_high(PIN_C2);
   delay_cycles(10);
   if(!(bit_test(PORTB,7)&&bit_test(PORTB,6)&&bit_test(PORTB,5)&&bit_test(PORTB,4)))
   {
      if(!bit_test(PORTB,7)) bit_set(matriz3,4);
      else bit_clear(matriz3,4);
      if(!bit_test(PORTB,6)) bit_set(matriz3,5);
      else bit_clear(matriz3,5);
      if(!bit_test(PORTB,5)) bit_set(matriz3,6);
      else bit_clear(matriz3,6);
      if(!bit_test(PORTB,4)) bit_set(matriz3,7);
      else bit_clear(matriz3,7);
      delay_cycles(10);
   
   }
   output_low(PIN_C0);
   delay_cycles(10);
   output_high(PIN_C1);
   delay_cycles(10);
   if(!(bit_test(PORTB,7)&&bit_test(PORTB,6)&&bit_test(PORTB,5)&&bit_test(PORTB,4)))
   {
      if(!bit_test(PORTB,7)) bit_set(matriz3,0);
      else bit_clear(matriz3,0);
      if(!bit_test(PORTB,6)) bit_set(matriz3,1);
      else bit_clear(matriz3,1);
      if(!bit_test(PORTB,5)) bit_set(matriz3,2);
      else bit_clear(matriz3,2);
      if(!bit_test(PORTB,4)) bit_set(matriz3,3);
      else bit_clear(matriz3,3);
      delay_cycles(10);
   
   }
   output_low(PIN_A5);
   delay_cycles(10);
   output_high(PIN_C0);
   delay_cycles(10);
   if(!(bit_test(PORTB,7)&&bit_test(PORTB,6)&&bit_test(PORTB,5)&&bit_test(PORTB,4)))
   {
      if(!bit_test(PORTB,7)) bit_set(matriz2,4);
      else bit_clear(matriz2,4);
      if(!bit_test(PORTB,6)) bit_set(matriz2,5);
      else bit_clear(matriz2,5);
      if(!bit_test(PORTB,5)) bit_set(matriz2,6);
      else bit_clear(matriz2,6);
      if(!bit_test(PORTB,4)) bit_set(matriz2,7);
      else bit_clear(matriz2,7);
      delay_cycles(10);
   
   }
   output_low(PIN_A4);
   delay_cycles(10);
   output_high(PIN_A5);
   delay_cycles(10);
   if(!(bit_test(PORTB,7)&&bit_test(PORTB,6)&&bit_test(PORTB,5)&&bit_test(PORTB,4)))
   {
      if(!bit_test(PORTB,7)) bit_set(matriz2,0);
      else bit_clear(matriz2,0);
      if(!bit_test(PORTB,6)) bit_set(matriz2,1);
      else bit_clear(matriz2,1);
      if(!bit_test(PORTB,5)) bit_set(matriz2,2);
      else bit_clear(matriz2,2);
      if(!bit_test(PORTB,4)) bit_set(matriz2,3);
      else bit_clear(matriz2,3);
      delay_cycles(10);
   
   }
   output_low(PIN_A3);
   delay_cycles(10);
   output_high(PIN_A4);
   delay_cycles(10);
   if(!(bit_test(PORTB,7)&&bit_test(PORTB,6)&&bit_test(PORTB,5)&&bit_test(PORTB,4)))
   {
      if(!bit_test(PORTB,7)) bit_set(matriz1,4);
      else bit_clear(matriz1,4);
      if(!bit_test(PORTB,6)) bit_set(matriz1,5);
      else bit_clear(matriz1,5);
      if(!bit_test(PORTB,5)) bit_set(matriz1,6);
      else bit_clear(matriz1,6);
      if(!bit_test(PORTB,4)) bit_set(matriz1,7);
      else bit_clear(matriz1,7);
      delay_cycles(10);
   
   }
   output_low(PIN_A2);
   delay_cycles(10);
   output_high(PIN_A3);
   delay_cycles(10);
   if(!(bit_test(PORTB,7)&&bit_test(PORTB,6)&&bit_test(PORTB,5)&&bit_test(PORTB,4)))
   {
      if(!bit_test(PORTB,7)) bit_set(matriz1,0);
      else bit_clear(matriz1,0);
      if(!bit_test(PORTB,6)) bit_set(matriz1,1);
      else bit_clear(matriz1,1);
      if(!bit_test(PORTB,5)) bit_set(matriz1,2);
      else bit_clear(matriz1,2);
      if(!bit_test(PORTB,4)) bit_set(matriz1,3);
      else bit_clear(matriz1,3);
      delay_cycles(10);
   
   }
      output_low(PIN_A2);
      output_low(PIN_A3);
      output_low(PIN_A4);
      output_low(PIN_A5);
      output_low(PIN_C0);
      output_low(PIN_C1);
      output_low(PIN_C2);
      output_low(PIN_C6);
      LATB=PORTB;
      busca_diferencias();
      return;
}

void main(void) {
   delay_ms(1000);
   set_tris_A(0b00000011);      //PORTA todo salidas, menos AN0 y AN1
   set_tris_B(0b11111111);      //PORTB entradas
   set_tris_C(0b10000000);
   port_B_pullups(TRUE);
   LATB=PORTB;
   output_C(0);
   PORTA=0;
   tempoA11=tempoA2=0;
   setup_adc_ports(AN0_TO_AN1);  //AN0 y AN1 como entradas analogicas
   setup_adc(ADC_CLOCK_INTERNAL);
   
   usb_init_cs();
   
   INTCON=0;
   enable_interrupts(INT_RB);   //Interrupciones por cambio en RB7 a RB4
   enable_interrupts(global);

   while (TRUE) {
      usb_task();

      if(usb_enumerated()) 
    {

         set_adc_channel(0);
         delay_us(30);
         tempoA1=read_adc();
         tempoA11=tempoA1/2;      //convierte del rango
                           //0xFF a 0x7F para Midi
        
         if(tempoA11!=tempoA2) //comprueba si ha cambiado el tempo para enviarlo  
            {   tempA[1]=0xB0;
               tempA[0]=tempA[1]>>4;
               tempA[2]=0x00;
               tempA[3]=tempoA11;
               usb_put_packet(1,tempA,4,USB_DTS_TOGGLE);
               tempoA2=tempoA11;
            }
        }
     }
  }
 
He encontrado el fallo. Ese archivo que he subido me acabo de dar cuenta que está mal. En la subrutina de "busca_diferencias()", en la primera parte se analiza la matriz1; eso está bien. En las 3 restantes, en las líneas como:
Código:
bitT=bit_test(matriz2,contador);
debería poner:
Código:
bitT=bit_test(matriz2,(contador-8));
En matriz3 y matriz4 también hay que corregirlo, pero restando 16 y 24 respectivamente.
Pongo ese trozo de código completo:
Código:
void busca_diferencias()
{	diferencias=matriz1^matriz1bis;
	if(diferencias!=0)
		{	contador=0x00;
			while(contador<=0x07)
			{ if(bit_test(diferencias,0))
				{	envia[2]=contador;
					bitT=bit_test(matriz1,contador);
					envia[3]=0x7F*bitT;
					envianota();
				}
			contador++;
			rotate_right(&diferencias,1);

		}
		}
	diferencias=matriz2^matriz2bis;
	if(diferencias!=0)
		{	contador=0x08;
			while(contador<=0x0F)
			{ if(bit_test(diferencias,0))
				{	envia[2]=contador;
					bitT=bit_test(matriz2,(contador-8));
					envia[3]=0x7F*bitT;
					envianota();
				}
			contador++;
			rotate_right(&diferencias,1);

		}
		}
	diferencias=matriz3^matriz3bis;
	if(diferencias!=0)
		{	contador=0x10;
			while(contador<=0x17)
			{ if(bit_test(diferencias,0))
				{	envia[2]=contador;
					bitT=bit_test(matriz3,(contador-16));
					envia[3]=0x7F*bitT;
					envianota();
				}
			contador++;
			rotate_right(&diferencias,1);

		}
		}
	diferencias=matriz4^matriz4bis;
	if(diferencias!=0)
		{	contador=0x18;
			while(contador<=0x1F)
			{ if(bit_test(diferencias,0))
				{	envia[2]=contador;
					bitT=bit_test(matriz4,(contador-24));
					envia[3]=0x7F*bitT;
					envianota();
				}
			contador++;
			rotate_right(&diferencias,1);

		}
		}
}

Perdón por el error.
Un saludo
 
Gracias por la corrección del código rachelies todo funcionando bien, también hice pruebas del encoder. Que tal son los CD4051? O que multiplexor recomiendan? La idea es agregar unos cuantos potes y ya comienzan a escasear los puertos del pic jejeje.
 
Nunca he probado los multiplexores. En mi controlador lo que tengo son expansores de salidas PCF8574N (que utilizo para los leds) que se conectan por i2c, y así no gastas pines para manejar los multiplexores. También hay circuitos de estos para conversiones a/d.
Creo que el i2c es la mejor opción para ampliar el circuito sin seguir gastando pines del microcontrolador.
Un saludo



Sin buscar mucho, lo primero que me ha salido ha sido esto, ADS1015. 4 conversores A/D con interface i2c
 
Última edición:
Hay varios proyectos así, utilizando un joystick o creando una interface HID con un PIC, y luego hay varios software que convierten estos comandos en MIDI. Yo empecé por ahí, pero me parece un rollo tener que poner un software intermedio.
 
sisi, es verdad, lo puse como ejemplo, por ejemplo en mi caso me vendria bien solo tener un boton de play y pause por deck, el plato que ahora no me acuerdo como se llama apenas lo uso, el resto de las funciones las realizo con consola externa(volumen, fader, etc)
 
Buenos dias a todos les cuento ya tengo trabajando botones, fader, y encoder me gustaria agregarle los led, alguien podria explicarme mejor esta parte en el foro dice que con esta instruccion el pic detecta los datos de entrada.

Código:
if (usb_kbhit(1)) 
{
  usb_get_packet(1,recibe,8);
}

pero como direcciono el dato a un puerto del pic o en dado caso un expansorpara tener mas salidas, como sabe al pic que nota midi se esta enviando para cada led. yo uso traktor y estoy trabajando en MIDI.

Gracias.
 
Hola Niht. Has llegado al punto más engorroso, jejeje. A ver si te lo puedo explicar fácilmente, porque hace tiempo que no uso el traktor, aunque es más fácil que con VirtualDj. Por ejemplo para el botón del play, vas a configuración de "Midi Mapping". Agregas un nuevo comando, "Transport"--"Play/Pause", y luego lo configuras como "Output---LED" y la asignas a la nota que te interese.
Luego, cuando el Traktor lo vea oportuno, te envia esa nota por el Midi, que es lo que detecta el PIC con
Código:
if (usb_kbhit(1)) 
{
  usb_get_packet(1,recibe,8);
}

A mi me llega una trama más o menos así:

Encender led: 09 90 20 7F
Apagar led: 09 90 20 00

Cuando ese "if" detecta que ha llegado algo, voy a una subrutina donde descifro que es lo que ha llegado, leyendo el tercer byte que es la nota, en este caso 0x20 y el cuarto byte, que si es 0x7F es encender led, y si es 0x00 apagar.

Que led tienes que encender o apagar lo tienes que tener en cuenta tú. En mi controlador, de la 0x20 a la 0x27 van a un expansor de salidas, de la 0x28 a 0x2F a otro, y de la 0x30 a 0x37 a otro más, total 24 leds.
Este es mi programa completo para gestionar los leds:

Código:
int32 leds;
#locate leds=0x50
#byte leds1=0x50
#byte leds2=0x51
#byte leds3=0x52

/////////////////////////////////////////
//subprograma para lectura leds
////////////////////////////////////////

void detecta_led()
{	leds1copia=leds1;
	leds2copia=leds2;
	leds3copia=leds3;	
	recibe[2]=recibe[2]-32;
	if(recibe[3]==127) bit_clear(leds,recibe[2]);		//encender leds
	if(recibe[3]==0) bit_set(leds,recibe[2]);		//apagar leds
	
	if(leds1!=leds1copia){
		i2c_start();
		i2c_write(0x40);
		i2c_write(leds1);
		i2c_stop();
		}	
	if(leds2!=leds2copia){
		i2c_start();
		i2c_write(0x42);
		i2c_write(leds2);
		i2c_stop();
		}	
	if(leds3!=leds3copia){
		i2c_start();
		i2c_write(0x44);
		i2c_write(leds3);
		i2c_stop();
		}	
}

Un saludo y ya comentarás que tal. Espero que la explicación esté mas o menos, jejeje
 
hola!!! estube probando los codigos para el pic que han subido y ya hice funcionar algunos con lo que no he podido es con los Jogswheel para hacer el scratch, use unos codigos que hay en el tema el que tiene interrupciones y el que no pero no me funcionan consegui un motor de disco duro y monte el circuito de los operacionales para generar los pulsos pero no me funcionan los codigo que probe. si hay algun alma caritativa que se apiade de mi y me ayude con el codigo para poner a funcionar los jogwheel se lo agradesco yo se que me diran que en el tema esta todo para hacerlo y creanme ya lo he leido de arriba a abajo y he buscado en internet pero quedo en las mismas... gracias por la colaboracion que me den.
 
fernandoae el codigo sin interrupciones al que te refieres es este?
Código:
x=0;
for(;;){	
	pos2=pos;

if(bit_test(PORTB,0)){
	if(bit_test(PORTB,1)) pos=3;
	else pos=2;
}
if(!(bit_test(PORTB,0))){
	if(bit_test(PORTB,1)) pos=4;
	else pos=1;
}
if (pos2!=pos){
	switch(pos){
		case 1: if(pos2==4) x++;
				else x--;
				break;
		case 2: if(pos2==1) x++;
				else x--;
				break;
		case 3: if(pos2==2) x++;
				else x--;
				break;
		case 4: if(pos2==3) x++;
				else x--;
				break;
}
}
}

podrias explicarme con este codigo como enviar el buffer con los datos midi.
 
Claro, igual yo mucho no manejo ccs... yo uso mas el basic ;) pero es esta parte la del codigo:
if (pos2!=pos){ switch(pos){ case 1: if(pos2==4) x++; else x--; break; case 2: if(pos2==1) x++; else x--; break; case 3: if(pos2==2) x++; else x--; break; case 4: if(pos2==3) x++; else x--; break;
 
Buenas a todos! Excelentes los aportes de todos; muy interesante el proyecto. Quería preguntarles cómo hago para que el Traktor reconozca el dispositivo? No me quedó muy claro lo de los Mappers y Devices. Estoy programando en CCS y simulando con Proteus (ni bien consiga el PIC lo armo real). Hasta ahora logro que windows me reconozca como dispositivo de audio USB (estoy usando el descriptor midi7.h) pero no sé cómo verlo desde traktor. Muchas gracias, saludos!
 
El Traktor no lleva Mappers y Devices, eso es en el VirtualDj. Ahora mismo no tengo el Traktor aquí no recuerdo de memoria, pero en el botón de configuración, hay un sitio donde salía algo así como Dispositivos Midi o algo así. Échale un vistazo que te tiene que salir por algún sitio, dale vueltas.
Un saludo.
 
Atrás
Arriba