@@ -728,6 +728,24 @@ void usb_config_tx(uint32_t ep, uint32_t packet_size, int do_zlp, void (*cb)(tra | |||
if (cb) endpointN_notify_mask |= (1 << (ep + 16)); | |||
} | |||
void usb_config_rx_iso(uint32_t ep, uint32_t packet_size, int mult, void (*cb)(transfer_t *)) | |||
{ | |||
if (mult < 1 || mult > 3) return; | |||
uint32_t config = (packet_size << 16) | (mult << 30); | |||
if (ep < 2 || ep > NUM_ENDPOINTS) return; | |||
usb_endpoint_config(endpoint_queue_head + ep * 2, config, cb); | |||
if (cb) endpointN_notify_mask |= (1 << ep); | |||
} | |||
void usb_config_tx_iso(uint32_t ep, uint32_t packet_size, int mult, void (*cb)(transfer_t *)) | |||
{ | |||
if (mult < 1 || mult > 3) return; | |||
uint32_t config = (packet_size << 16) | (mult << 30); | |||
if (ep < 2 || ep > NUM_ENDPOINTS) return; | |||
usb_endpoint_config(endpoint_queue_head + ep * 2 + 1, config, cb); | |||
if (cb) endpointN_notify_mask |= (1 << (ep + 16)); | |||
} | |||
void usb_prepare_transfer(transfer_t *transfer, const void *data, uint32_t len, uint32_t param) |
@@ -30,15 +30,11 @@ | |||
#include <Arduino.h> | |||
#include "usb_dev.h" | |||
#include "usb_audio.h" | |||
#include "debug/printf.h" | |||
#ifdef AUDIO_INTERFACE | |||
// Uncomment this to work around a limitation in Macintosh adaptive rates | |||
// This is not a perfect solution. Details here: | |||
// https://forum.pjrc.com/threads/34855-Distorted-audio-when-using-USB-input-on-Teensy-3-1 | |||
//#define MACOSX_ADAPTIVE_LIMIT | |||
bool AudioInputUSB::update_responsibility; | |||
audio_block_t * AudioInputUSB::incoming_left; | |||
audio_block_t * AudioInputUSB::incoming_right; | |||
@@ -53,8 +49,7 @@ extern volatile uint8_t usb_high_speed; | |||
static void rx_event(transfer_t *t); | |||
static transfer_t rx_transfer __attribute__ ((used, aligned(32))); | |||
/*DMAMEM*/ static uint8_t rx_buffer[AUDIO_RX_SIZE_12] __attribute__ ((aligned(32))); | |||
static uint16_t rx_max_size; | |||
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; | |||
@@ -68,23 +63,19 @@ static uint32_t feedback_accumulator = 185042824; | |||
static void rx_queue_transfer(void) | |||
{ | |||
usb_prepare_transfer(&rx_transfer, rx_buffer, rx_max_size, 0); | |||
arm_dcache_delete(&rx_transfer, rx_max_size); | |||
usb_prepare_transfer(&rx_transfer, rx_buffer, AUDIO_RX_SIZE, 0); | |||
arm_dcache_delete(&rx_transfer, AUDIO_RX_SIZE); | |||
usb_receive(AUDIO_RX_ENDPOINT, &rx_transfer); | |||
} | |||
void usb_audio_configure(void) | |||
{ | |||
printf("usb_audio_configure\n"); | |||
memset(&rx_transfer, 0, sizeof(rx_transfer)); | |||
rx_max_size = usb_high_speed ? AUDIO_RX_SIZE_480 : AUDIO_RX_SIZE_12; | |||
usb_config_rx(AUDIO_RX_ENDPOINT, rx_max_size, 0, rx_event); | |||
usb_config_rx_iso(AUDIO_RX_ENDPOINT, AUDIO_RX_SIZE, 1, rx_event); | |||
rx_queue_transfer(); | |||
} | |||
void AudioInputUSB::begin(void) | |||
{ | |||
incoming_count = 0; | |||
@@ -127,18 +118,20 @@ 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) | |||
{ | |||
int len = rx_max_size - ((t->status >> 16) & 0x7FFF); | |||
printf("rx event, len=%d\n", len); | |||
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(); | |||
} | |||
// Called from the USB interrupt when an isochronous packet arrives | |||
// we must completely remove it from the receive buffer before returning | |||
// | |||
#if 0 | |||
#if 1 | |||
void usb_audio_receive_callback(unsigned int len) | |||
{ | |||
unsigned int count, avail; | |||
@@ -147,7 +140,7 @@ void usb_audio_receive_callback(unsigned int len) | |||
AudioInputUSB::receive_flag = 1; | |||
len >>= 2; // 1 sample = 4 bytes: 2 left, 2 right | |||
data = (const uint32_t *)usb_audio_receive_buffer; | |||
data = (const uint32_t *)rx_buffer; | |||
count = AudioInputUSB::incoming_count; | |||
left = AudioInputUSB::incoming_left; |
@@ -1321,8 +1321,8 @@ PROGMEM const uint8_t usb_config_descriptor_480[CONFIG_DESC_SIZE] = { | |||
5, // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR | |||
AUDIO_TX_ENDPOINT | 0x80, // bEndpointAddress | |||
0x09, // bmAttributes = isochronous, adaptive | |||
LSB(AUDIO_TX_SIZE_480), MSB(AUDIO_TX_SIZE_480), // wMaxPacketSize | |||
1, // bInterval, 1 = every frame | |||
LSB(AUDIO_TX_SIZE), MSB(AUDIO_TX_SIZE), // wMaxPacketSize | |||
4, // bInterval, 4 = every 8 micro-frames | |||
0, // bRefresh | |||
0, // bSynchAddress | |||
// Class-Specific AS Isochronous Audio Data Endpoint Descriptor | |||
@@ -1380,8 +1380,8 @@ PROGMEM const uint8_t usb_config_descriptor_480[CONFIG_DESC_SIZE] = { | |||
5, // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR | |||
AUDIO_RX_ENDPOINT, // bEndpointAddress | |||
0x05, // bmAttributes = isochronous, asynchronous | |||
LSB(AUDIO_RX_SIZE_480), MSB(AUDIO_RX_SIZE_480), // wMaxPacketSize | |||
1, // bInterval, 1 = every frame | |||
LSB(AUDIO_RX_SIZE), MSB(AUDIO_RX_SIZE), // wMaxPacketSize | |||
4, // bInterval, 4 = every 8 micro-frames | |||
0, // bRefresh | |||
AUDIO_SYNC_ENDPOINT | 0x80, // bSynchAddress | |||
// Class-Specific AS Isochronous Audio Data Endpoint Descriptor | |||
@@ -1399,7 +1399,7 @@ PROGMEM const uint8_t usb_config_descriptor_480[CONFIG_DESC_SIZE] = { | |||
AUDIO_SYNC_ENDPOINT | 0x80, // bEndpointAddress | |||
0x11, // bmAttributes = isochronous, feedback | |||
4, 0, // wMaxPacketSize, 4 bytes | |||
1, // bInterval, 1 = every frame | |||
4, // bInterval, 4 = 4 = every 8 micro-frames | |||
5, // bRefresh, 5 = 32ms | |||
0, // bSynchAddress | |||
#endif | |||
@@ -2155,7 +2155,7 @@ PROGMEM const uint8_t usb_config_descriptor_12[CONFIG_DESC_SIZE] = { | |||
5, // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR | |||
AUDIO_TX_ENDPOINT | 0x80, // bEndpointAddress | |||
0x09, // bmAttributes = isochronous, adaptive | |||
LSB(AUDIO_TX_SIZE_12), MSB(AUDIO_TX_SIZE_12), // wMaxPacketSize | |||
LSB(AUDIO_TX_SIZE), MSB(AUDIO_TX_SIZE), // wMaxPacketSize | |||
1, // bInterval, 1 = every frame | |||
0, // bRefresh | |||
0, // bSynchAddress | |||
@@ -2214,7 +2214,7 @@ PROGMEM const uint8_t usb_config_descriptor_12[CONFIG_DESC_SIZE] = { | |||
5, // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR | |||
AUDIO_RX_ENDPOINT, // bEndpointAddress | |||
0x05, // bmAttributes = isochronous, asynchronous | |||
LSB(AUDIO_RX_SIZE_12), MSB(AUDIO_RX_SIZE_12), // wMaxPacketSize | |||
LSB(AUDIO_RX_SIZE), MSB(AUDIO_RX_SIZE), // wMaxPacketSize | |||
1, // bInterval, 1 = every frame | |||
0, // bRefresh | |||
AUDIO_SYNC_ENDPOINT | 0x80, // bSynchAddress |
@@ -653,11 +653,13 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define SEREMU_RX_INTERVAL 2 | |||
#define AUDIO_INTERFACE 1 // Audio (uses 3 consecutive interfaces) | |||
#define AUDIO_TX_ENDPOINT 3 | |||
#define AUDIO_TX_SIZE_12 180 | |||
#define AUDIO_TX_SIZE_480 24 | |||
#define AUDIO_TX_SIZE 180 | |||
//#define AUDIO_TX_SIZE_12 180 | |||
//#define AUDIO_TX_SIZE_480 24 | |||
#define AUDIO_RX_ENDPOINT 3 | |||
#define AUDIO_RX_SIZE_12 180 | |||
#define AUDIO_RX_SIZE_480 24 | |||
#define AUDIO_RX_SIZE 180 | |||
//#define AUDIO_RX_SIZE_12 180 | |||
//#define AUDIO_RX_SIZE_480 24 | |||
#define AUDIO_SYNC_ENDPOINT 4 | |||
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_INTERRUPT + ENDPOINT_TRANSMIT_INTERRUPT | |||
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS + ENDPOINT_TRANSMIT_ISOCHRONOUS |
@@ -22,6 +22,8 @@ void usb_init_serialnumber(void); | |||
void usb_config_rx(uint32_t ep, uint32_t packet_size, int do_zlp, void (*cb)(transfer_t *)); | |||
void usb_config_tx(uint32_t ep, uint32_t packet_size, int do_zlp, void (*cb)(transfer_t *)); | |||
void usb_config_rx_iso(uint32_t ep, uint32_t packet_size, int mult, void (*cb)(transfer_t *)); | |||
void usb_config_tx_iso(uint32_t ep, uint32_t packet_size, int mult, void (*cb)(transfer_t *)); | |||
void usb_prepare_transfer(transfer_t *transfer, const void *data, uint32_t len, uint32_t param); | |||
void usb_transmit(int endpoint_number, transfer_t *transfer); |