Browse Source

USB audio on Teensy 4.0 (mostly kinda working now)

teensy4-core
PaulStoffregen 4 years ago
parent
commit
f3ba9ebd86
2 changed files with 49 additions and 29 deletions
  1. +22
    -7
      teensy4/usb.c
  2. +27
    -22
      teensy4/usb_audio.cpp

+ 22
- 7
teensy4/usb.c View File

case 0x0221: case 0x0221:
case 0x0321: case 0x0321:
case 0x0421: case 0x0421:
endpoint0_receive(NULL, 0, 1); // handle these after ACK
return;
// TODO: remove this terrible kludge, but why oh why does servicing this
// request stop the isochronous endpoints? Maybe a bug in endpoint0_receive?
if (usb_audio_transmit_setting || usb_audio_receive_setting) break; // kludge!!!

printf("set_feature, word1=%x, len=%d\n", setup.word1, setup.wLength);
if (setup.wLength <= sizeof(endpoint0_buffer)) {
endpoint0_setupdata.bothwords = setupdata;
endpoint0_receive(endpoint0_buffer, setup.wLength, 1);
return; // handle these after ACK
}
break;
case 0x81A1: // GET FEATURE case 0x81A1: // GET FEATURE
case 0x82A1: case 0x82A1:
case 0x83A1: case 0x83A1:
case 0x84A1: case 0x84A1:
if (setup.wLength <= sizeof(endpoint0_buffer)) { if (setup.wLength <= sizeof(endpoint0_buffer)) {
/*if (usb_audio_get_feature(&setup, endpoint0_buffer, setup.wLength)) {
endpoint0_transmit(endpoint0_buffer, setup.wLength, 0);
uint32_t len;
static uint8_t buf[2];
if (usb_audio_get_feature(&setup, buf, &len)) {
printf("GET feature, len=%d\n", len);
endpoint0_transmit(buf, len, 0);
return; return;
}*/
}
} }
break; break;
case 0x81A2: // GET_CUR (wValue=0, wIndex=interface, wLength=len) case 0x81A2: // GET_CUR (wValue=0, wIndex=interface, wLength=len)
setup_t setup; setup_t setup;


setup.bothwords = endpoint0_setupdata.bothwords; setup.bothwords = endpoint0_setupdata.bothwords;
//printf("complete %x %x %x\n", setup.word1, setup.word2, endpoint0_buffer[0]);
printf("complete %x %x %x\n", setup.word1, setup.word2, endpoint0_buffer[0]);
#ifdef CDC_STATUS_INTERFACE #ifdef CDC_STATUS_INTERFACE
if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) { if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
memcpy(usb_cdc_line_coding, endpoint0_buffer, 7); memcpy(usb_cdc_line_coding, endpoint0_buffer, 7);
} }
#endif #endif
#ifdef AUDIO_INTERFACE #ifdef AUDIO_INTERFACE
// TODO: usb_audio_set_feature()
if (setup.word1 == 0x02010121 /* TODO: check setup.word2 */) {
usb_audio_set_feature(&endpoint0_setupdata, endpoint0_buffer);
// TODO: usb_audio_set_feature()
}
#endif #endif
} }



+ 27
- 22
teensy4/usb_audio.cpp View File



extern volatile uint8_t usb_high_speed; extern volatile uint8_t usb_high_speed;
static void rx_event(transfer_t *t); static void rx_event(transfer_t *t);
static void rx_queue_transfer(void);
static void tx_event(transfer_t *t);


/*static*/ transfer_t rx_transfer __attribute__ ((used, aligned(32))); /*static*/ transfer_t rx_transfer __attribute__ ((used, aligned(32)));
/*static*/ transfer_t sync_transfer __attribute__ ((used, aligned(32))); /*static*/ transfer_t sync_transfer __attribute__ ((used, aligned(32)));
/*static*/ transfer_t tx_transfer __attribute__ ((used, aligned(32)));
DMAMEM static uint8_t rx_buffer[AUDIO_RX_SIZE] __attribute__ ((aligned(32))); DMAMEM static uint8_t rx_buffer[AUDIO_RX_SIZE] __attribute__ ((aligned(32)));
DMAMEM uint32_t usb_audio_sync_feedback;
DMAMEM static uint8_t tx_buffer[AUDIO_RX_SIZE] __attribute__ ((aligned(32)));
DMAMEM uint32_t usb_audio_sync_feedback __attribute__ ((aligned(32)));


uint8_t usb_audio_receive_setting=0; uint8_t usb_audio_receive_setting=0;
uint8_t usb_audio_transmit_setting=0; uint8_t usb_audio_transmit_setting=0;
{ {
if (t) { if (t) {
int len = AUDIO_RX_SIZE - ((rx_transfer.status >> 16) & 0x7FFF); int len = AUDIO_RX_SIZE - ((rx_transfer.status >> 16) & 0x7FFF);
//printf("rx %u\n", len);
printf("rx %u\n", len);
usb_audio_receive_callback(len); usb_audio_receive_callback(len);
} }
usb_prepare_transfer(&rx_transfer, rx_buffer, AUDIO_RX_SIZE, 0); usb_prepare_transfer(&rx_transfer, rx_buffer, AUDIO_RX_SIZE, 0);
//printf("sync %x\n", sync_transfer.status); // too slow, can't print this much //printf("sync %x\n", sync_transfer.status); // too slow, can't print this much
usb_audio_sync_feedback = feedback_accumulator >> usb_audio_sync_rshift; usb_audio_sync_feedback = feedback_accumulator >> usb_audio_sync_rshift;
usb_prepare_transfer(&sync_transfer, &usb_audio_sync_feedback, usb_audio_sync_nbytes, 0); usb_prepare_transfer(&sync_transfer, &usb_audio_sync_feedback, usb_audio_sync_nbytes, 0);
arm_dcache_delete(&usb_audio_sync_feedback, usb_audio_sync_nbytes);
arm_dcache_flush(&usb_audio_sync_feedback, usb_audio_sync_nbytes);
usb_transmit(AUDIO_SYNC_ENDPOINT, &sync_transfer); usb_transmit(AUDIO_SYNC_ENDPOINT, &sync_transfer);
} }


} }
memset(&rx_transfer, 0, sizeof(rx_transfer)); memset(&rx_transfer, 0, sizeof(rx_transfer));
usb_config_rx_iso(AUDIO_RX_ENDPOINT, AUDIO_RX_SIZE, 1, rx_event); usb_config_rx_iso(AUDIO_RX_ENDPOINT, AUDIO_RX_SIZE, 1, rx_event);
//rx_queue_transfer();
rx_event(NULL); rx_event(NULL);
memset(&sync_transfer, 0, sizeof(sync_transfer)); memset(&sync_transfer, 0, sizeof(sync_transfer));
usb_config_tx_iso(AUDIO_SYNC_ENDPOINT, usb_audio_sync_nbytes, 1, sync_event); usb_config_tx_iso(AUDIO_SYNC_ENDPOINT, usb_audio_sync_nbytes, 1, sync_event);
sync_event(NULL); sync_event(NULL);
memset(&tx_transfer, 0, sizeof(tx_transfer));
usb_config_tx_iso(AUDIO_TX_ENDPOINT, AUDIO_TX_SIZE, 1, tx_event);
tx_event(NULL);
} }


void AudioInputUSB::begin(void) void AudioInputUSB::begin(void)
__enable_irq(); __enable_irq();
if (f) { if (f) {
int diff = AUDIO_BLOCK_SAMPLES/2 - (int)c; int diff = AUDIO_BLOCK_SAMPLES/2 - (int)c;
feedback_accumulator += diff * 2;

//__disable_irq();
//printf("fb:%x\n", feedback_accumulator);
//__enable_irq();
feedback_accumulator += diff * 1;
//uint32_t feedback = (feedback_accumulator >> 8) + diff * 100; //uint32_t feedback = (feedback_accumulator >> 8) + diff * 100;
//usb_audio_sync_feedback = feedback; //usb_audio_sync_feedback = feedback;
//if (diff > 0) {
//serial_print(".");
//} else if (diff < 0) {
//serial_print("^");
//}

//printf(diff >= 0 ? "." : "^");
} }
//serial_phex(c); //serial_phex(c);
//serial_print("."); //serial_print(".");
if (!left || !right) { if (!left || !right) {
usb_audio_underrun_count++; usb_audio_underrun_count++;
printf("#"); // buffer underrun - PC sending too slow
//if (f) feedback_accumulator += 10 << 8;
//printf("#"); // buffer underrun - PC sending too slow
if (f) feedback_accumulator += 3500;
} }
if (left) { if (left) {
transmit(left, 0); transmit(left, 0);








#if 0
#if 1
bool AudioOutputUSB::update_responsibility; bool AudioOutputUSB::update_responsibility;
audio_block_t * AudioOutputUSB::left_1st; audio_block_t * AudioOutputUSB::left_1st;
audio_block_t * AudioOutputUSB::left_2nd; audio_block_t * AudioOutputUSB::left_2nd;
audio_block_t * AudioOutputUSB::right_2nd; audio_block_t * AudioOutputUSB::right_2nd;
uint16_t AudioOutputUSB::offset_1st; uint16_t AudioOutputUSB::offset_1st;


/*DMAMEM*/ uint16_t usb_audio_transmit_buffer[AUDIO_TX_SIZE/2] __attribute__ ((used, aligned(32)));


static void tx_event(transfer_t *t)
{
int len = usb_audio_transmit_callback();
usb_audio_sync_feedback = feedback_accumulator >> usb_audio_sync_rshift;
usb_prepare_transfer(&tx_transfer, usb_audio_transmit_buffer, len, 0);
arm_dcache_flush_delete(usb_audio_transmit_buffer, len);
usb_transmit(AUDIO_TX_ENDPOINT, &tx_transfer);
}


uint16_t usb_audio_transmit_buffer[AUDIO_TX_SIZE/2] DMABUFATTR;


void AudioOutputUSB::begin(void) void AudioOutputUSB::begin(void)
{ {
uint32_t avail, num, target, offset, len=0; uint32_t avail, num, target, offset, len=0;
audio_block_t *left, *right; audio_block_t *left, *right;


if (++count < 9) { // TODO: dynamic adjust to match USB rate
if (++count < 10) { // TODO: dynamic adjust to match USB rate
target = 44; target = 44;
} else { } else {
count = 0; count = 0;

Loading…
Cancel
Save