Browse Source

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

main
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



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 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))); 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_receive_setting=0;
uint8_t usb_audio_transmit_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); 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); 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) void usb_audio_configure(void)
{ {
printf("usb_audio_configure\n"); 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)); 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_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) void AudioInputUSB::begin(void)
// but also because the PC may stop transmitting data, which // but also because the PC may stop transmitting data, which
// means we no longer get receive callbacks from usb.c // means we no longer get receive callbacks from usb.c
update_responsibility = false; 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) static void copy_to_buffers(const uint32_t *src, int16_t *left, int16_t *right, unsigned int len)
// Called from the USB interrupt when an isochronous packet arrives // Called from the USB interrupt when an isochronous packet arrives
// we must completely remove it from the receive buffer before returning // 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 #if 1
void usb_audio_receive_callback(unsigned int len) void usb_audio_receive_callback(unsigned int len)
{ {
if (AudioInputUSB::ready_left || AudioInputUSB::ready_right) { if (AudioInputUSB::ready_left || AudioInputUSB::ready_right) {
// buffer overrun, PC sending too fast // buffer overrun, PC sending too fast
AudioInputUSB::incoming_count = count + avail; AudioInputUSB::incoming_count = count + avail;
//if (len > 0) {
//serial_print("!");
if (len > 0) {
usb_audio_overrun_count++;
printf("!");
//serial_phex(len); //serial_phex(len);
//}
}
return; return;
} }
send: send:
__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 / 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; //usb_audio_sync_feedback = feedback;
//if (diff > 0) { //if (diff > 0) {
//serial_print("."); //serial_print(".");
//serial_phex(c); //serial_phex(c);
//serial_print("."); //serial_print(".");
if (!left || !right) { 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 (f) feedback_accumulator += 10 << 8;
} }
if (left) { if (left) {

+ 1
- 1
teensy4/usb_desc.c View File

0x11, // bmAttributes = isochronous, feedback 0x11, // bmAttributes = isochronous, feedback
4, 0, // wMaxPacketSize, 4 bytes 4, 0, // wMaxPacketSize, 4 bytes
4, // bInterval, 4 = 4 = every 8 micro-frames 4, // bInterval, 4 = 4 = every 8 micro-frames
5, // bRefresh, 5 = 32ms
7, // bRefresh,
0, // bSynchAddress 0, // bSynchAddress
#endif #endif



Loading…
Cancel
Save