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

@@ -560,17 +560,29 @@ static void endpoint0_setup(uint64_t setupdata)
case 0x0221:
case 0x0321:
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 0x82A1:
case 0x83A1:
case 0x84A1:
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;
}*/
}
}
break;
case 0x81A2: // GET_CUR (wValue=0, wIndex=interface, wLength=len)
@@ -673,7 +685,7 @@ static void endpoint0_complete(void)
setup_t setup;

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
if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
memcpy(usb_cdc_line_coding, endpoint0_buffer, 7);
@@ -700,7 +712,10 @@ static void endpoint0_complete(void)
}
#endif
#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
}


+ 27
- 22
teensy4/usb_audio.cpp View File

@@ -47,12 +47,14 @@ struct usb_audio_features_struct AudioInputUSB::features = {0,0,FEATURE_MAX_VOLU

extern volatile uint8_t usb_high_speed;
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 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 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_transmit_setting=0;
@@ -69,7 +71,7 @@ static void rx_event(transfer_t *t)
{
if (t) {
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_prepare_transfer(&rx_transfer, rx_buffer, AUDIO_RX_SIZE, 0);
@@ -83,7 +85,7 @@ static void sync_event(transfer_t *t)
//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_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);
}

@@ -102,11 +104,13 @@ void usb_audio_configure(void)
}
memset(&rx_transfer, 0, sizeof(rx_transfer));
usb_config_rx_iso(AUDIO_RX_ENDPOINT, AUDIO_RX_SIZE, 1, rx_event);
//rx_queue_transfer();
rx_event(NULL);
memset(&sync_transfer, 0, sizeof(sync_transfer));
usb_config_tx_iso(AUDIO_SYNC_ENDPOINT, usb_audio_sync_nbytes, 1, sync_event);
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)
@@ -243,25 +247,18 @@ void AudioInputUSB::update(void)
__enable_irq();
if (f) {
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;
//usb_audio_sync_feedback = feedback;
//if (diff > 0) {
//serial_print(".");
//} else if (diff < 0) {
//serial_print("^");
//}

//printf(diff >= 0 ? "." : "^");
}
//serial_phex(c);
//serial_print(".");
if (!left || !right) {
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) {
transmit(left, 0);
@@ -289,9 +286,7 @@ void AudioInputUSB::update(void)





#if 0
#if 1
bool AudioOutputUSB::update_responsibility;
audio_block_t * AudioOutputUSB::left_1st;
audio_block_t * AudioOutputUSB::left_2nd;
@@ -299,8 +294,18 @@ audio_block_t * AudioOutputUSB::right_1st;
audio_block_t * AudioOutputUSB::right_2nd;
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)
{
@@ -388,7 +393,7 @@ unsigned int usb_audio_transmit_callback(void)
uint32_t avail, num, target, offset, len=0;
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;
} else {
count = 0;

Loading…
Cancel
Save