|
@@ -46,8 +46,22 @@
|
|
|
//--------------------------------------------------------------------+
|
|
//--------------------------------------------------------------------+
|
|
|
// MACRO CONSTANT TYPEDEF
|
|
// MACRO CONSTANT TYPEDEF
|
|
|
//--------------------------------------------------------------------+
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
+
|
|
|
|
|
+#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
|
|
|
+#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT
|
|
|
|
|
+#define CFG_TUD_AUDIO_TX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_TX
|
|
|
|
|
+#endif
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
|
|
|
+#ifndef CFG_TUD_AUDIO_RX_FIFO_COUNT
|
|
|
|
|
+#define CFG_TUD_AUDIO_RX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_RX
|
|
|
|
|
+#endif
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
typedef struct
|
|
typedef struct
|
|
|
{
|
|
{
|
|
|
|
|
+ uint8_t rhport;
|
|
|
uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function
|
|
uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN
|
|
@@ -80,18 +94,18 @@ typedef struct
|
|
|
|
|
|
|
|
// FIFO
|
|
// FIFO
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
|
- tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX];
|
|
|
|
|
- CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE * CFG_TUD_AUDIO_TX_ITEMSIZE];
|
|
|
|
|
|
|
+ tu_fifo_t tx_ff[CFG_TUD_AUDIO_TX_FIFO_COUNT];
|
|
|
|
|
+ CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_TX_FIFO_COUNT][CFG_TUD_AUDIO_TX_FIFO_SIZE];
|
|
|
#if CFG_FIFO_MUTEX
|
|
#if CFG_FIFO_MUTEX
|
|
|
- osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX];
|
|
|
|
|
|
|
+ osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_TX_FIFO_COUNT];
|
|
|
#endif
|
|
#endif
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
|
- tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX];
|
|
|
|
|
- CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE * CFG_TUD_AUDIO_RX_ITEMSIZE];
|
|
|
|
|
|
|
+ tu_fifo_t rx_ff[CFG_TUD_AUDIO_RX_FIFO_COUNT];
|
|
|
|
|
+ CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_RX_FIFO_COUNT][CFG_TUD_AUDIO_RX_FIFO_SIZE];
|
|
|
#if CFG_FIFO_MUTEX
|
|
#if CFG_FIFO_MUTEX
|
|
|
- osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX];
|
|
|
|
|
|
|
+ osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_RX_FIFO_COUNT];
|
|
|
#endif
|
|
#endif
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
@@ -107,10 +121,9 @@ typedef struct
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT
|
|
|
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here)
|
|
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here)
|
|
|
|
|
|
|
|
- // TODO: required?
|
|
|
|
|
- //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
|
|
|
- // uint16_t fb_val; // Feedback value for asynchronous mode!
|
|
|
|
|
- //#endif
|
|
|
|
|
|
|
+#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
|
|
|
+ uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format).
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
@@ -134,7 +147,7 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO];
|
|
|
extern const uint16_t tud_audio_desc_lengths[];
|
|
extern const uint16_t tud_audio_desc_lengths[];
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT
|
|
|
-static audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t const* buffer, uint32_t bufsize);
|
|
|
|
|
|
|
+static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize);
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN
|
|
@@ -189,7 +202,7 @@ bool tud_audio_n_mounted(uint8_t itf)
|
|
|
//--------------------------------------------------------------------+
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
|
-
|
|
|
|
|
|
|
+#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
|
|
|
uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId)
|
|
uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId)
|
|
|
{
|
|
{
|
|
|
TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX);
|
|
TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX);
|
|
@@ -204,10 +217,25 @@ uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t
|
|
|
|
|
|
|
|
void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId)
|
|
void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId)
|
|
|
{
|
|
{
|
|
|
- TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX);
|
|
|
|
|
|
|
+ TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, );
|
|
|
tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]);
|
|
tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]);
|
|
|
}
|
|
}
|
|
|
|
|
+#else
|
|
|
|
|
+uint16_t tud_audio_n_available(uint8_t itf)
|
|
|
|
|
+{
|
|
|
|
|
+ return tu_fifo_count(&_audiod_itf[itf].rx_ff[0]);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
+uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize)
|
|
|
|
|
+{
|
|
|
|
|
+ return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[0], buffer, bufsize);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void tud_audio_n_read_flush (uint8_t itf)
|
|
|
|
|
+{
|
|
|
|
|
+ tu_fifo_clear(&_audiod_itf[itf].rx_ff[0]);
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
|
|
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
|
|
@@ -282,12 +310,14 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t*
|
|
|
|
|
|
|
|
// The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0
|
|
// The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0
|
|
|
#if CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
#if CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
|
|
|
+#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
|
|
|
static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize)
|
|
static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize)
|
|
|
{
|
|
{
|
|
|
(void) rhport;
|
|
(void) rhport;
|
|
|
|
|
|
|
|
// We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel
|
|
// We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel
|
|
|
- if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) {
|
|
|
|
|
|
|
+ if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0)
|
|
|
|
|
+ {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -316,7 +346,23 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a
|
|
|
chId = 0;
|
|
chId = 0;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-} }
|
|
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+#else
|
|
|
|
|
+static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *audio, uint8_t *buffer, uint16_t bufsize)
|
|
|
|
|
+{
|
|
|
|
|
+ (void) rhport;
|
|
|
|
|
+
|
|
|
|
|
+ // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel
|
|
|
|
|
+ if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ tu_fifo_write_n(&audio->rx_ff[0], buffer, bufsize);
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+#endif // CFG_TUD_AUDIO_RX_FIFO_COUNT > 1
|
|
|
#endif //CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
#endif //CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
//--------------------------------------------------------------------+
|
|
@@ -334,9 +380,9 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a
|
|
|
* \param[in] len: # of array elements to copy
|
|
* \param[in] len: # of array elements to copy
|
|
|
* \return Number of bytes actually written
|
|
* \return Number of bytes actually written
|
|
|
*/
|
|
*/
|
|
|
-
|
|
|
|
|
|
|
+#if CFG_TUD_AUDIO_EPSIZE_IN
|
|
|
|
|
+#if !CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
|
/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers
|
|
/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers
|
|
|
-#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
|
|
|
uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len)
|
|
uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len)
|
|
|
{
|
|
{
|
|
|
audiod_interface_t* audio = &_audiod_itf[itf];
|
|
audiod_interface_t* audio = &_audiod_itf[itf];
|
|
@@ -363,11 +409,23 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t
|
|
|
// Return number of bytes written
|
|
// Return number of bytes written
|
|
|
return len;
|
|
return len;
|
|
|
}
|
|
}
|
|
|
-#endif
|
|
|
|
|
-
|
|
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
-#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
|
|
|
|
|
+#else
|
|
|
|
|
+
|
|
|
|
|
+#if CFG_TUD_AUDIO_TX_FIFO_COUNT == 1
|
|
|
|
|
+uint16_t tud_audio_n_write(uint8_t itf, void const* data, uint16_t len)
|
|
|
|
|
+{
|
|
|
|
|
+ {
|
|
|
|
|
+ audiod_interface_t* audio = &_audiod_itf[itf];
|
|
|
|
|
+ if (audio->p_desc == NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ return tu_fifo_write_n(&audio->tx_ff[0], data, len);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+#else
|
|
|
uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len)
|
|
uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len)
|
|
|
{
|
|
{
|
|
|
audiod_interface_t* audio = &_audiod_itf[itf];
|
|
audiod_interface_t* audio = &_audiod_itf[itf];
|
|
@@ -379,6 +437,23 @@ uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, ui
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied);
|
|
|
|
|
+
|
|
|
|
|
+uint16_t tud_audio_n_write_flush(uint8_t itf)
|
|
|
|
|
+{
|
|
|
|
|
+ audiod_interface_t *audio = &_audiod_itf[itf];
|
|
|
|
|
+ if (audio->p_desc == NULL) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ uint16_t n_bytes_copied;
|
|
|
|
|
+ TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied));
|
|
|
|
|
+ return n_bytes_copied;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#endif
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0
|
|
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0
|
|
|
uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize)
|
|
uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize)
|
|
|
{
|
|
{
|
|
@@ -475,6 +550,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_
|
|
|
#endif //CFG_TUD_AUDIO_EPSIZE_IN
|
|
#endif //CFG_TUD_AUDIO_EPSIZE_IN
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
#if CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
|
|
|
+#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE)
|
|
|
static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio)
|
|
static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio)
|
|
|
{
|
|
{
|
|
|
// We encode directly into IN EP's buffer - abort if previous transfer not complete
|
|
// We encode directly into IN EP's buffer - abort if previous transfer not complete
|
|
@@ -482,15 +558,15 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t*
|
|
|
|
|
|
|
|
// Determine amount of samples
|
|
// Determine amount of samples
|
|
|
uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX;
|
|
uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX;
|
|
|
- uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]);
|
|
|
|
|
|
|
+ uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]) / CFG_TUD_AUDIO_TX_ITEMSIZE;
|
|
|
uint16_t nBytesToSend;
|
|
uint16_t nBytesToSend;
|
|
|
uint8_t cntChannel;
|
|
uint8_t cntChannel;
|
|
|
|
|
|
|
|
for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++)
|
|
for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++)
|
|
|
{
|
|
{
|
|
|
- if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend)
|
|
|
|
|
|
|
+ if (audio->tx_ff[cntChannel].count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend)
|
|
|
{
|
|
{
|
|
|
- nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count;
|
|
|
|
|
|
|
+ nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count * CFG_TUD_AUDIO_TX_ITEMSIZE;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -522,7 +598,7 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t*
|
|
|
for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++)
|
|
for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++)
|
|
|
{
|
|
{
|
|
|
// Get sample from buffer
|
|
// Get sample from buffer
|
|
|
- tu_fifo_read(&audio->tx_ff[cntChannel], &sample);
|
|
|
|
|
|
|
+ tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_TX_ITEMSIZE);
|
|
|
|
|
|
|
|
// Put it into EP's buffer - Let alignment problems be handled by memcpy
|
|
// Put it into EP's buffer - Let alignment problems be handled by memcpy
|
|
|
memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX);
|
|
memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX);
|
|
@@ -537,23 +613,80 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t*
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+#else
|
|
|
|
|
+static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio)
|
|
|
|
|
+{
|
|
|
|
|
+ // We encode directly into IN EP's buffer - abort if previous transfer not complete
|
|
|
|
|
+ TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in));
|
|
|
|
|
+
|
|
|
|
|
+ // Determine amount of samples
|
|
|
|
|
+ uint16_t nByteCount = tu_fifo_count(&audio->tx_ff[0]);
|
|
|
|
|
+
|
|
|
|
|
+ nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EPSIZE_IN);
|
|
|
|
|
+
|
|
|
|
|
+ // Check if there is enough
|
|
|
|
|
+ if (nByteCount == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount);
|
|
|
|
|
+ audio->epin_buf_cnt = nByteCount;
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+#endif // CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE)
|
|
|
|
|
+
|
|
|
#endif //CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
#endif //CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
|
|
|
|
|
|
// This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent
|
|
// This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
|
-static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio)
|
|
|
|
|
|
|
+static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio)
|
|
|
{
|
|
{
|
|
|
- (void) rhport;
|
|
|
|
|
- (void) audio;
|
|
|
|
|
|
|
+ uint8_t fb[4];
|
|
|
|
|
+ uint16_t len;
|
|
|
|
|
|
|
|
- // Here we need to return the feedback value
|
|
|
|
|
-#error RETURN YOUR FEEDBACK VALUE HERE!
|
|
|
|
|
|
|
+ if (audio->fb_val == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ len = 0;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ len = 4;
|
|
|
|
|
+ // Here we need to return the feedback value
|
|
|
|
|
+ if (rhport == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ // For FS format is 10.14
|
|
|
|
|
+ fb[0] = (audio->fb_val >> 2) & 0xFF;
|
|
|
|
|
+ fb[1] = (audio->fb_val >> 10) & 0xFF;
|
|
|
|
|
+ fb[2] = (audio->fb_val >> 18) & 0xFF;
|
|
|
|
|
+ // 4th byte is needed to work correctly with MS Windows
|
|
|
|
|
+ fb[3] = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // For HS format is 16.16
|
|
|
|
|
+ fb[0] = (audio->fb_val >> 0) & 0xFF;
|
|
|
|
|
+ fb[1] = (audio->fb_val >> 8) & 0xFF;
|
|
|
|
|
+ fb[2] = (audio->fb_val >> 16) & 0xFF;
|
|
|
|
|
+ fb[3] = (audio->fb_val >> 24) & 0xFF;
|
|
|
|
|
+ }
|
|
|
|
|
+ return usbd_edpt_xfer(rhport, audio->ep_fb, fb, len);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
|
|
|
|
|
- return 0;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+//static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio)
|
|
|
|
|
+//{
|
|
|
|
|
+// (void) rhport;
|
|
|
|
|
+// (void) audio;
|
|
|
|
|
+//
|
|
|
|
|
+// if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
|
|
|
|
|
+// return 0;
|
|
|
|
|
+//}
|
|
|
|
|
+
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
// This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send
|
|
// This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send
|
|
@@ -586,7 +719,6 @@ static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uin
|
|
|
//--------------------------------------------------------------------+
|
|
//--------------------------------------------------------------------+
|
|
|
void audiod_init(void)
|
|
void audiod_init(void)
|
|
|
{
|
|
{
|
|
|
- uint8_t cnt;
|
|
|
|
|
tu_memclr(_audiod_itf, sizeof(_audiod_itf));
|
|
tu_memclr(_audiod_itf, sizeof(_audiod_itf));
|
|
|
|
|
|
|
|
for(uint8_t i=0; i<CFG_TUD_AUDIO; i++)
|
|
for(uint8_t i=0; i<CFG_TUD_AUDIO; i++)
|
|
@@ -595,9 +727,9 @@ void audiod_init(void)
|
|
|
|
|
|
|
|
// Initialize TX FIFOs if required
|
|
// Initialize TX FIFOs if required
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
|
- for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++)
|
|
|
|
|
|
|
+ for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++)
|
|
|
{
|
|
{
|
|
|
- tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true);
|
|
|
|
|
|
|
+ tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, 1, true);
|
|
|
#if CFG_FIFO_MUTEX
|
|
#if CFG_FIFO_MUTEX
|
|
|
tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt]));
|
|
tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt]));
|
|
|
#endif
|
|
#endif
|
|
@@ -605,9 +737,9 @@ void audiod_init(void)
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
|
- for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++)
|
|
|
|
|
|
|
+ for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++)
|
|
|
{
|
|
{
|
|
|
- tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true);
|
|
|
|
|
|
|
+ tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, 1, true);
|
|
|
#if CFG_FIFO_MUTEX
|
|
#if CFG_FIFO_MUTEX
|
|
|
tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt]));
|
|
tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt]));
|
|
|
#endif
|
|
#endif
|
|
@@ -632,16 +764,15 @@ void audiod_reset(uint8_t rhport)
|
|
|
audiod_interface_t* audio = &_audiod_itf[i];
|
|
audiod_interface_t* audio = &_audiod_itf[i];
|
|
|
tu_memclr(audio, ITF_MEM_RESET_SIZE);
|
|
tu_memclr(audio, ITF_MEM_RESET_SIZE);
|
|
|
|
|
|
|
|
- uint8_t cnt;
|
|
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE
|
|
|
- for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++)
|
|
|
|
|
|
|
+ for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++)
|
|
|
{
|
|
{
|
|
|
tu_fifo_clear(&audio->tx_ff[cnt]);
|
|
tu_fifo_clear(&audio->tx_ff[cnt]);
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE
|
|
|
- for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++)
|
|
|
|
|
|
|
+ for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++)
|
|
|
{
|
|
{
|
|
|
tu_fifo_clear(&audio->rx_ff[cnt]);
|
|
tu_fifo_clear(&audio->rx_ff[cnt]);
|
|
|
}
|
|
}
|
|
@@ -673,6 +804,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
|
|
|
if (!_audiod_itf[i].p_desc)
|
|
if (!_audiod_itf[i].p_desc)
|
|
|
{
|
|
{
|
|
|
_audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one
|
|
_audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one
|
|
|
|
|
+ _audiod_itf[i].rhport = rhport;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -818,7 +950,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
|
- if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback
|
|
|
|
|
|
|
+ if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback
|
|
|
{
|
|
{
|
|
|
_audiod_itf[idxDriver].ep_fb = ep_addr;
|
|
_audiod_itf[idxDriver].ep_fb = ep_addr;
|
|
|
|
|
|
|
@@ -1115,13 +1247,9 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
|
|
|
// Transmission of feedback EP finished
|
|
// Transmission of feedback EP finished
|
|
|
if (_audiod_itf[idxDriver].ep_fb == ep_addr)
|
|
if (_audiod_itf[idxDriver].ep_fb == ep_addr)
|
|
|
{
|
|
{
|
|
|
- if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver]))
|
|
|
|
|
- {
|
|
|
|
|
- // Load with ZLP
|
|
|
|
|
- return usbd_edpt_xfer(rhport, ep_addr, NULL, 0);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
|
|
|
|
|
|
|
|
- return true;
|
|
|
|
|
|
|
+ return audio_fb_send(rhport, &_audiod_itf[idxDriver]);
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
#endif
|
|
#endif
|
|
@@ -1303,4 +1431,16 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver)
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
|
|
|
+bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback)
|
|
|
|
|
+{
|
|
|
|
|
+ audiod_interface_t *audio = &_audiod_itf[0];
|
|
|
|
|
+
|
|
|
|
|
+ audio->fb_val = feedback;
|
|
|
|
|
+ TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_fb), true);
|
|
|
|
|
+
|
|
|
|
|
+ return audio_fb_send(rhport, audio);
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO
|
|
#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO
|