Ya logré comunicar el pic con la pc con esta configuración:
HID con polling in y out de 1ms (descriptor)
Endpoint 1
64bytes por paquete
El paquete lo envío hasta que acumulo 25 mediciones de la señal (2bytes x 25 = 50bytes). Lo curioso es que el pic no puede enviar paquetes cada 1ms, lo hace cada 1.73ms aproximadamente. Esto lo mido con osciloscopio y sabiendo que usb_put_packet confirma la entrega del paquete (regresa un bool = 1).
//debug
output_high(USBOK);
//Pone el buffer en el endpoint y espera hasta que se haya enviado
while(!(usb_put_packet(1, buffer_out, 64, USB_DTS_TOGGLE)));
//debug
output_low(USBOK);
El retraso se debe en parte a que usb_put_packet hace muchas cosas:
int1 usb_put_packet(int8 endpoint, int8 * ptr, int16 len, USB_DTS_BIT tgl) { //done
int16 j;
int8 i;
int8 * buff_add;
i=EP_BDxST_I(endpoint);
if (!bit_test(i,7)) {
buff_add=EP_BDxADR_I(endpoint);
for (j=0;j<len;j++) {
*buff_add=*ptr;
buff_add++;
ptr++;
}
return(usb_flush_in(endpoint, len, tgl));
}
else {
debug_usb(debug_putc,"\r\nPUT ERR");
}
return(0);
}
Así es como entiendo lo que hace putpacket:
- Primero verifica si la SIE no está manipulando el arreglo del endpoint de envío (bit 7 de i UOWN)
- Luego obtiene la dirección ram de dónde empieza el arreglo del endpoint
- Luego copia byte por byte el arreglo que se va a enviar al arreglo del endpoint
- Por último, ejecuta usb_flush_in que hace lo siguiente:
int1 usb_flush_in(int8 endpoint, int16 len, USB_DTS_BIT tgl) {
int8 i;
debug_usb(debug_putc,"\r\nPUT %X %U %LU",endpoint, tgl, len);
i=EP_BDxST_I(endpoint);
if (!bit_test(i,7)) {
EP_BDxCNT_I(endpoint)=len;
debug_display_ram(len, EP_BDxADR_I(endpoint));
#if USB_IGNORE_TX_DTS
i=0x80;
#else
if (tgl == USB_DTS_TOGGLE) {
i=EP_BDxST_I(endpoint);
if (bit_test(i,6))
tgl=USB_DTS_DATA0; //was DATA1, goto DATA0
else
tgl=USB_DTS_DATA1; //was DATA0, goto DATA1
}
else if (tgl == USB_DTS_USERX) {
i=EP_BDxST_O(endpoint);
if (bit_test(i,6))
tgl=USB_DTS_DATA1;
else
tgl=USB_DTS_DATA0;
}
if (tgl == USB_DTS_DATA1) {
i=0xC8; //DATA1, UOWN
}
else if (tgl == USB_DTS_DATA0) {
i=0x88; //DATA0, UOWN
}
#endif
//set BC8 and BC9
if (bit_test(len,8)) {bit_set(i,0);}
if (bit_test(len,9)) {bit_set(i,1);}
debug_usb(debug_putc," %X",i);
EP_BDxST_I(endpoint)=i;//save changes
return(1);
}
else {
debug_usb(debug_putc,"\r\nPUT ERR");
}
return(0);
}
+ Vuelve a verificar si la SIE está haciendo algo con el endpoint
+ Escribe en un registro USB (CNTI) los bytes que se enviarán del arreglo del endpoint
+ Por último copia los 2 bits más significativos de len y los anexa a BDSTAT
+ Todo lo anterior solo si la SIE no está manipulando el endpoint, y regresará un 1
+ Si la SIE estaba trabajando, entonces no se ejecuta lo anterior y se regresa un 0
Todo esto toma mucho tiempo y pues talvez se pueda mejorar. Voy a ver si mejoro esta función y si logro un polling menor a 1.73ms. Todo basándome en el tema de Modulay en el que gestiona una parte de la interrupción USB.