Browse Source

USB audio on Teensy 4.0 (even yet more still work in progress)

teensy4-core
PaulStoffregen 4 years ago
parent
commit
a26d0af0f1
2 changed files with 55 additions and 30 deletions
  1. +54
    -29
      teensy4/usb_audio.cpp
  2. +1
    -1
      teensy4/usb_desc.c

+ 54
- 29
teensy4/usb_audio.cpp View File

@@ -47,33 +47,66 @@ 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 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)));
DMAMEM static uint8_t rx_buffer[AUDIO_RX_SIZE] __attribute__ ((aligned(32)));

//#define DMABUFATTR __attribute__ ((section(".dmabuffers"), aligned (4)))
//uint16_t usb_audio_receive_buffer[AUDIO_RX_SIZE/2] DMABUFATTR;
//uint32_t usb_audio_sync_feedback DMABUFATTR;
DMAMEM uint32_t usb_audio_sync_feedback;

uint8_t usb_audio_receive_setting=0;
uint8_t usb_audio_transmit_setting=0;
uint8_t usb_audio_sync_nbytes;
uint8_t usb_audio_sync_rshift;

uint32_t feedback_accumulator;

static uint32_t feedback_accumulator = 185042824;
volatile uint32_t usb_audio_underrun_count;
volatile uint32_t usb_audio_overrun_count;


static void rx_queue_transfer(void)
static void rx_event(transfer_t *t)
{
if (t) {
int len = AUDIO_RX_SIZE - ((rx_transfer.status >> 16) & 0x7FFF);
//printf("rx %u\n", len);
usb_audio_receive_callback(len);
}
usb_prepare_transfer(&rx_transfer, rx_buffer, AUDIO_RX_SIZE, 0);
arm_dcache_delete(&rx_transfer, AUDIO_RX_SIZE);
arm_dcache_delete(&rx_buffer, AUDIO_RX_SIZE);
usb_receive(AUDIO_RX_ENDPOINT, &rx_transfer);
}

static void sync_event(transfer_t *t)
{
// USB 2.0 Specification, 5.12.4.2 Feedback, pages 73-75
//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);
usb_transmit(AUDIO_SYNC_ENDPOINT, &sync_transfer);
}

void usb_audio_configure(void)
{
printf("usb_audio_configure\n");
usb_audio_underrun_count = 0;
usb_audio_overrun_count = 0;
feedback_accumulator = 739875226; // 44.1 * 2^24
if (usb_high_speed) {
usb_audio_sync_nbytes = 4;
usb_audio_sync_rshift = 8;
} else {
usb_audio_sync_nbytes = 3;
usb_audio_sync_rshift = 10;
}
memset(&rx_transfer, 0, sizeof(rx_transfer));
usb_config_rx_iso(AUDIO_RX_ENDPOINT, AUDIO_RX_SIZE, 1, rx_event);
rx_queue_transfer();
//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);
}

void AudioInputUSB::begin(void)
@@ -90,7 +123,6 @@ void AudioInputUSB::begin(void)
// but also because the PC may stop transmitting data, which
// means we no longer get receive callbacks from usb.c
update_responsibility = false;
//usb_audio_sync_feedback = feedback_accumulator >> 8;
}

static void copy_to_buffers(const uint32_t *src, int16_t *left, int16_t *right, unsigned int len)
@@ -121,16 +153,6 @@ static void copy_to_buffers(const uint32_t *src, int16_t *left, int16_t *right,
// Called from the USB interrupt when an isochronous packet arrives
// we must completely remove it from the receive buffer before returning
//
static void rx_event(transfer_t *t)
{
unsigned int len = AUDIO_RX_SIZE - ((t->status >> 16) & 0x7FFF);
//int len = AUDIO_RX_SIZE - ((rx_transfer.status >> 16) & 0x7FFF);
printf("rx %u\n", len);
// TODO: actually move the data from USB to audio lib
usb_audio_receive_callback(len);
rx_queue_transfer();
}

#if 1
void usb_audio_receive_callback(unsigned int len)
{
@@ -168,10 +190,11 @@ void usb_audio_receive_callback(unsigned int len)
if (AudioInputUSB::ready_left || AudioInputUSB::ready_right) {
// buffer overrun, PC sending too fast
AudioInputUSB::incoming_count = count + avail;
//if (len > 0) {
//serial_print("!");
if (len > 0) {
usb_audio_overrun_count++;
printf("!");
//serial_phex(len);
//}
}
return;
}
send:
@@ -220,11 +243,12 @@ void AudioInputUSB::update(void)
__enable_irq();
if (f) {
int diff = AUDIO_BLOCK_SAMPLES/2 - (int)c;
feedback_accumulator += diff / 3;
uint32_t feedback = (feedback_accumulator >> 8) + diff * 100;
#ifdef MACOSX_ADAPTIVE_LIMIT
if (feedback > 722698) feedback = 722698;
#endif
feedback_accumulator += diff * 2;

//__disable_irq();
//printf("fb:%x\n", feedback_accumulator);
//__enable_irq();
//uint32_t feedback = (feedback_accumulator >> 8) + diff * 100;
//usb_audio_sync_feedback = feedback;
//if (diff > 0) {
//serial_print(".");
@@ -235,7 +259,8 @@ void AudioInputUSB::update(void)
//serial_phex(c);
//serial_print(".");
if (!left || !right) {
//serial_print("#"); // buffer underrun - PC sending too slow
usb_audio_underrun_count++;
printf("#"); // buffer underrun - PC sending too slow
//if (f) feedback_accumulator += 10 << 8;
}
if (left) {

+ 1
- 1
teensy4/usb_desc.c View File

@@ -1400,7 +1400,7 @@ PROGMEM const uint8_t usb_config_descriptor_480[CONFIG_DESC_SIZE] = {
0x11, // bmAttributes = isochronous, feedback
4, 0, // wMaxPacketSize, 4 bytes
4, // bInterval, 4 = 4 = every 8 micro-frames
5, // bRefresh, 5 = 32ms
7, // bRefresh,
0, // bSynchAddress
#endif


Loading…
Cancel
Save