mirror of
https://github.com/hathach/tinyusb.git
synced 2025-02-15 12:39:50 +00:00
Merge pull request #2282 from HiFiPhile/uac_interl
UAC IN transfer improvements
This commit is contained in:
commit
a2390802f8
@ -69,8 +69,13 @@ uint8_t clkValid;
|
|||||||
audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state
|
audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state
|
||||||
audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state
|
audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_ENCODING
|
||||||
// Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2
|
// Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2
|
||||||
uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ/2]; // Ensure half word aligned
|
uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ/2]; // Ensure half word aligned
|
||||||
|
#else
|
||||||
|
// Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3
|
||||||
|
uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_EP_SZ_IN]; // Ensure half word aligned
|
||||||
|
#endif
|
||||||
|
|
||||||
void led_blinking_task(void);
|
void led_blinking_task(void);
|
||||||
void audio_task(void);
|
void audio_task(void);
|
||||||
@ -97,6 +102,7 @@ int main(void)
|
|||||||
sampleFreqRng.subrange[0].bRes = 0;
|
sampleFreqRng.subrange[0].bRes = 0;
|
||||||
|
|
||||||
// Generate dummy data
|
// Generate dummy data
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_ENCODING
|
||||||
uint16_t * p_buff = i2s_dummy_buffer[0];
|
uint16_t * p_buff = i2s_dummy_buffer[0];
|
||||||
uint16_t dataVal = 1;
|
uint16_t dataVal = 1;
|
||||||
for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++)
|
for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++)
|
||||||
@ -116,6 +122,23 @@ int main(void)
|
|||||||
float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000);
|
float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000);
|
||||||
*p_buff++ = (uint16_t)(sinf(t) * 25) + 200;
|
*p_buff++ = (uint16_t)(sinf(t) * 25) + 200;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
uint16_t * p_buff = i2s_dummy_buffer;
|
||||||
|
uint16_t dataVal = 1;
|
||||||
|
for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++)
|
||||||
|
{
|
||||||
|
// CH0 saw wave
|
||||||
|
*p_buff++ = dataVal;
|
||||||
|
// CH1 inverted saw wave
|
||||||
|
*p_buff++ = 60 + AUDIO_SAMPLE_RATE/1000 - dataVal;
|
||||||
|
dataVal++;
|
||||||
|
// CH3 square wave
|
||||||
|
*p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 120:170;
|
||||||
|
// CH4 sinus wave
|
||||||
|
float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000);
|
||||||
|
*p_buff++ = (uint16_t)(sinf(t) * 25) + 200;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@ -384,7 +407,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *
|
|||||||
{
|
{
|
||||||
case AUDIO_CS_REQ_CUR:
|
case AUDIO_CS_REQ_CUR:
|
||||||
TU_LOG2(" Get Sample Freq.\r\n");
|
TU_LOG2(" Get Sample Freq.\r\n");
|
||||||
return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq));
|
// Buffered control transfer is needed for IN flow control to work
|
||||||
|
return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq));
|
||||||
|
|
||||||
case AUDIO_CS_REQ_RANGE:
|
case AUDIO_CS_REQ_RANGE:
|
||||||
TU_LOG2(" Get Sample Freq. range\r\n");
|
TU_LOG2(" Get Sample Freq. range\r\n");
|
||||||
@ -429,12 +453,15 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u
|
|||||||
// tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO);
|
// tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_ENCODING
|
||||||
// Write I2S buffer into FIFO
|
// Write I2S buffer into FIFO
|
||||||
for (uint8_t cnt=0; cnt < 2; cnt++)
|
for (uint8_t cnt=0; cnt < 2; cnt++)
|
||||||
{
|
{
|
||||||
tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX);
|
tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,11 @@ if __name__ == '__main__':
|
|||||||
# print(sd.query_devices())
|
# print(sd.query_devices())
|
||||||
|
|
||||||
fs = 48000 # Sample rate
|
fs = 48000 # Sample rate
|
||||||
duration = 20e-3 # Duration of recording
|
duration = 1 # Duration of recording
|
||||||
|
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
# WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows)
|
# WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows)
|
||||||
device = 'Microphone (MicNode_4_Ch), Windows WDM-KS'
|
device = 'Microphone (MicNode_4_Ch), Windows WASAPI'
|
||||||
elif platform.system() == 'Darwin':
|
elif platform.system() == 'Darwin':
|
||||||
device = 'MicNode_4_Ch'
|
device = 'MicNode_4_Ch'
|
||||||
else:
|
else:
|
||||||
@ -28,8 +28,7 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
time = np.arange(0, duration, 1 / fs) # time vector
|
time = np.arange(0, duration, 1 / fs) # time vector
|
||||||
# strip starting zero
|
# strip starting zero
|
||||||
myrecording = myrecording[100:]
|
|
||||||
time = time[100:]
|
|
||||||
plt.plot(time, myrecording)
|
plt.plot(time, myrecording)
|
||||||
plt.xlabel('Time [s]')
|
plt.xlabel('Time [s]')
|
||||||
plt.ylabel('Amplitude')
|
plt.ylabel('Amplitude')
|
||||||
|
@ -114,14 +114,26 @@ extern "C" {
|
|||||||
#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup
|
#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup
|
||||||
#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup
|
#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup
|
||||||
#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
|
#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
|
||||||
|
|
||||||
|
#define CFG_TUD_AUDIO_ENABLE_ENCODING 1
|
||||||
|
#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_ENCODING
|
||||||
|
|
||||||
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN
|
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN
|
||||||
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN
|
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN
|
||||||
|
|
||||||
#define CFG_TUD_AUDIO_ENABLE_ENCODING 1
|
|
||||||
#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 1
|
#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 1
|
||||||
#define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value
|
#define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value
|
||||||
#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX)
|
#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX)
|
||||||
#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO)
|
#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 4 * (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) // Minimum 4*EP size is needed for flow control
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN
|
||||||
|
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 4 * CFG_TUD_AUDIO_EP_SZ_IN // Minimum 4*EP size is needed for flow control
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -110,24 +110,36 @@
|
|||||||
#error Maximum number of audio functions restricted to three!
|
#error Maximum number of audio functions restricted to three!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Put sw_buf in USB section only if necessary
|
||||||
|
#if USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING
|
||||||
|
#define IN_SW_BUF_MEM_SECTION
|
||||||
|
#else
|
||||||
|
#define IN_SW_BUF_MEM_SECTION CFG_TUD_MEM_SECTION
|
||||||
|
#endif
|
||||||
|
#if USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING
|
||||||
|
#define OUT_SW_BUF_MEM_SECTION
|
||||||
|
#else
|
||||||
|
#define OUT_SW_BUF_MEM_SECTION CFG_TUD_MEM_SECTION
|
||||||
|
#endif
|
||||||
|
|
||||||
// EP IN software buffers and mutexes
|
// EP IN software buffers and mutexes
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
|
||||||
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0
|
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ];
|
IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO
|
osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO
|
||||||
#endif
|
#endif
|
||||||
#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0
|
#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0
|
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ];
|
IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO
|
osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO
|
||||||
#endif
|
#endif
|
||||||
#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0
|
#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0
|
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ];
|
IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO
|
osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO
|
||||||
#endif
|
#endif
|
||||||
@ -154,21 +166,21 @@
|
|||||||
// EP OUT software buffers and mutexes
|
// EP OUT software buffers and mutexes
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING
|
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING
|
||||||
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
|
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ];
|
OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO
|
osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO
|
||||||
#endif
|
#endif
|
||||||
#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
|
#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0
|
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ];
|
OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO
|
osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO
|
||||||
#endif
|
#endif
|
||||||
#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0
|
#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0
|
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ];
|
OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO
|
osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO
|
||||||
#endif
|
#endif
|
||||||
@ -217,7 +229,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
|
|||||||
// Software encoding/decoding support FIFOs
|
// Software encoding/decoding support FIFOs
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
|
||||||
#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0
|
#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ];
|
CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ];
|
||||||
tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO];
|
tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
|
osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
|
||||||
@ -225,7 +237,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0
|
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ];
|
CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ];
|
||||||
tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO];
|
tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
|
osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
|
||||||
@ -233,7 +245,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0
|
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ];
|
CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ];
|
||||||
tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO];
|
tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
|
osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
|
||||||
@ -243,7 +255,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
|
|||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
|
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
|
||||||
#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0
|
#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ];
|
CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ];
|
||||||
tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO];
|
tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
|
osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
|
||||||
@ -251,7 +263,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0
|
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ];
|
CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ];
|
||||||
tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO];
|
tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
|
osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
|
||||||
@ -259,7 +271,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0
|
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0
|
||||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ];
|
CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ];
|
||||||
tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO];
|
tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO];
|
||||||
#if CFG_FIFO_MUTEX
|
#if CFG_FIFO_MUTEX
|
||||||
osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
|
osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
|
||||||
@ -364,14 +376,21 @@ typedef struct
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
uint32_t sample_rate_tx;
|
||||||
|
uint16_t packet_sz_tx[3];
|
||||||
|
uint8_t bclock_id_tx;
|
||||||
|
uint8_t interval_tx;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Encoding parameters - parameters are set when alternate AS interface is set by host
|
// Encoding parameters - parameters are set when alternate AS interface is set by host
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL)
|
||||||
audio_format_type_t format_type_tx;
|
audio_format_type_t format_type_tx;
|
||||||
uint8_t n_channels_tx;
|
uint8_t n_channels_tx;
|
||||||
|
uint8_t n_bytes_per_sampe_tx;
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
|
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
|
||||||
audio_data_format_type_I_t format_type_I_tx;
|
audio_data_format_type_I_t format_type_I_tx;
|
||||||
uint8_t n_bytes_per_sampe_tx;
|
|
||||||
uint8_t n_channels_per_ff_tx;
|
uint8_t n_channels_per_ff_tx;
|
||||||
uint8_t n_ff_used_tx;
|
uint8_t n_ff_used_tx;
|
||||||
#endif
|
#endif
|
||||||
@ -444,7 +463,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id);
|
|||||||
static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id);
|
static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id);
|
||||||
static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio);
|
static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio);
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING
|
#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING)
|
||||||
static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf);
|
static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf);
|
||||||
|
|
||||||
static inline uint8_t tu_desc_subtype(void const* desc)
|
static inline uint8_t tu_desc_subtype(void const* desc)
|
||||||
@ -453,6 +472,11 @@ static inline uint8_t tu_desc_subtype(void const* desc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
static bool audiod_calc_tx_packet_sz(audiod_function_t* audio);
|
||||||
|
static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t max_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||||
static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq);
|
static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq);
|
||||||
#endif
|
#endif
|
||||||
@ -821,7 +845,6 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint1
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission.
|
// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission.
|
||||||
// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write.
|
// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write.
|
||||||
|
|
||||||
@ -886,9 +909,12 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
// No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule
|
// No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule
|
||||||
|
#if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
// packet_sz_tx is based on total packet size, here we want size for each support buffer.
|
||||||
|
n_bytes_tx = audiod_tx_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, audio->ep_in_sz);
|
||||||
|
#else
|
||||||
n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO
|
n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO
|
||||||
|
#endif
|
||||||
#if USE_LINEAR_BUFFER_TX
|
#if USE_LINEAR_BUFFER_TX
|
||||||
tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx);
|
tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx);
|
||||||
TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx));
|
TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx));
|
||||||
@ -987,8 +1013,6 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
|
|||||||
|
|
||||||
// Determine amount of samples
|
// Determine amount of samples
|
||||||
uint8_t const n_ff_used = audio->n_ff_used_tx;
|
uint8_t const n_ff_used = audio->n_ff_used_tx;
|
||||||
uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx;
|
|
||||||
uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes
|
|
||||||
uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]);
|
uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]);
|
||||||
uint8_t cnt_ff;
|
uint8_t cnt_ff;
|
||||||
|
|
||||||
@ -1001,14 +1025,23 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there is enough
|
#if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
const uint16_t norm_packet_sz_tx[3] = {audio->packet_sz_tx[0] / n_ff_used,
|
||||||
|
audio->packet_sz_tx[1] / n_ff_used,
|
||||||
|
audio->packet_sz_tx[2] / n_ff_used};
|
||||||
|
// packet_sz_tx is based on total packet size, here we want size for each support buffer.
|
||||||
|
nBytesPerFFToSend = audiod_tx_packet_size(norm_packet_sz_tx, nBytesPerFFToSend, audio->tx_supp_ff[0].depth, audio->ep_in_sz / n_ff_used);
|
||||||
|
// Check if there is enough data
|
||||||
|
if (nBytesPerFFToSend == 0) return 0;
|
||||||
|
#else
|
||||||
|
// Check if there is enough data
|
||||||
if (nBytesPerFFToSend == 0) return 0;
|
if (nBytesPerFFToSend == 0) return 0;
|
||||||
|
|
||||||
// Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT!
|
// Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT!
|
||||||
nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF);
|
nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, audio->ep_in_sz / n_ff_used);
|
||||||
|
|
||||||
// Round to full number of samples (flooring)
|
// Round to full number of samples (flooring)
|
||||||
nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy;
|
uint16_t const nSlotSize = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx;
|
||||||
|
nBytesPerFFToSend = (nBytesPerFFToSend / nSlotSize) * nSlotSize;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Encode
|
// Encode
|
||||||
uint8_t * dst;
|
uint8_t * dst;
|
||||||
@ -1271,7 +1304,7 @@ void audiod_init(void)
|
|||||||
#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
|
#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
|
||||||
|
|
||||||
// Set encoding parameters for Type_I formats
|
// Set encoding parameters for Type_I formats
|
||||||
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
|
||||||
switch (i)
|
switch (i)
|
||||||
{
|
{
|
||||||
#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0
|
#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0
|
||||||
@ -1451,81 +1484,114 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if USE_ISO_EP_ALLOCATION
|
#if USE_ISO_EP_ALLOCATION
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN
|
|
||||||
uint8_t ep_in = 0;
|
|
||||||
uint16_t ep_in_size = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
|
||||||
uint8_t ep_out = 0;
|
|
||||||
uint16_t ep_out_size = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
||||||
uint8_t ep_fb = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t const *p_desc = _audiod_fct[i].p_desc;
|
|
||||||
uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
|
|
||||||
while (p_desc < p_desc_end)
|
|
||||||
{
|
{
|
||||||
if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
|
|
||||||
{
|
|
||||||
tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
|
|
||||||
if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
|
|
||||||
{
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
||||||
// Explicit feedback EP
|
|
||||||
if (desc_ep->bmAttributes.usage == 1)
|
|
||||||
{
|
|
||||||
ep_fb = desc_ep->bEndpointAddress;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Data EP
|
|
||||||
if (desc_ep->bmAttributes.usage == 0)
|
|
||||||
{
|
|
||||||
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
|
|
||||||
{
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN
|
||||||
ep_in = desc_ep->bEndpointAddress;
|
uint8_t ep_in = 0;
|
||||||
ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
|
uint16_t ep_in_size = 0;
|
||||||
#endif
|
#endif
|
||||||
} else
|
|
||||||
{
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
||||||
ep_out = desc_ep->bEndpointAddress;
|
uint8_t ep_out = 0;
|
||||||
ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
|
uint16_t ep_out_size = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||||
|
uint8_t ep_fb = 0;
|
||||||
|
#endif
|
||||||
|
uint8_t const *p_desc = _audiod_fct[i].p_desc;
|
||||||
|
uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
|
||||||
|
while (p_desc < p_desc_end)
|
||||||
|
{
|
||||||
|
if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
|
||||||
|
{
|
||||||
|
tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
|
||||||
|
if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
|
||||||
|
{
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||||
|
// Explicit feedback EP
|
||||||
|
if (desc_ep->bmAttributes.usage == 1)
|
||||||
|
{
|
||||||
|
ep_fb = desc_ep->bEndpointAddress;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Data EP
|
||||||
|
if (desc_ep->bmAttributes.usage == 0)
|
||||||
|
{
|
||||||
|
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
|
||||||
|
{
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN
|
||||||
|
ep_in = desc_ep->bEndpointAddress;
|
||||||
|
ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
||||||
|
ep_out = desc_ep->bEndpointAddress;
|
||||||
|
ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p_desc = tu_desc_next(p_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN
|
||||||
|
if (ep_in)
|
||||||
|
{
|
||||||
|
usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
||||||
|
if (ep_out)
|
||||||
|
{
|
||||||
|
usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||||
|
if (ep_fb)
|
||||||
|
{
|
||||||
|
usbd_edpt_iso_alloc(rhport, ep_fb, 4);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif // USE_ISO_EP_ALLOCATION
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
{
|
||||||
|
uint8_t const *p_desc = _audiod_fct[i].p_desc;
|
||||||
|
uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
|
||||||
|
while (p_desc < p_desc_end)
|
||||||
|
{
|
||||||
|
if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
|
||||||
|
{
|
||||||
|
tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
|
||||||
|
if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
|
||||||
|
{
|
||||||
|
if (desc_ep->bmAttributes.usage == 0)
|
||||||
|
{
|
||||||
|
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
|
||||||
|
{
|
||||||
|
_audiod_fct[i].interval_tx = desc_ep->bInterval;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL)
|
||||||
|
{
|
||||||
|
if(tu_unaligned_read16(p_desc + 4) == AUDIO_TERM_TYPE_USB_STREAMING)
|
||||||
|
{
|
||||||
|
_audiod_fct[i].bclock_id_tx = p_desc[8];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
p_desc = tu_desc_next(p_desc);
|
||||||
}
|
}
|
||||||
p_desc = tu_desc_next(p_desc);
|
|
||||||
}
|
}
|
||||||
|
#endif // CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN
|
|
||||||
if (ep_in)
|
|
||||||
{
|
|
||||||
usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
|
||||||
if (ep_out)
|
|
||||||
{
|
|
||||||
usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
|
||||||
if (ep_fb)
|
|
||||||
{
|
|
||||||
usbd_edpt_iso_alloc(rhport, ep_fb, 4);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // USE_ISO_EP_ALLOCATION
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1607,6 +1673,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
|
|||||||
|
|
||||||
audio->ep_in = 0; // Necessary?
|
audio->ep_in = 0; // Necessary?
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
audio->packet_sz_tx[0] = 0;
|
||||||
|
audio->packet_sz_tx[1] = 0;
|
||||||
|
audio->packet_sz_tx[2] = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif // CFG_TUD_AUDIO_ENABLE_EP_IN
|
#endif // CFG_TUD_AUDIO_ENABLE_EP_IN
|
||||||
|
|
||||||
@ -1657,7 +1728,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
|
|||||||
// Find correct interface
|
// Find correct interface
|
||||||
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt)
|
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt)
|
||||||
{
|
{
|
||||||
#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING
|
#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
uint8_t const * p_desc_parse_for_params = p_desc;
|
uint8_t const * p_desc_parse_for_params = p_desc;
|
||||||
#endif
|
#endif
|
||||||
// From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary
|
// From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary
|
||||||
@ -1686,12 +1757,13 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
|
|||||||
audio->ep_in_sz = tu_edpt_packet_size(desc_ep);
|
audio->ep_in_sz = tu_edpt_packet_size(desc_ep);
|
||||||
|
|
||||||
// If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters
|
// If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters
|
||||||
#if CFG_TUD_AUDIO_ENABLE_ENCODING
|
#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf);
|
audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf);
|
||||||
|
|
||||||
// Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap
|
// Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap
|
||||||
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
|
#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
|
||||||
const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx);
|
const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx))
|
||||||
|
* (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx));
|
||||||
for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++)
|
for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++)
|
||||||
{
|
{
|
||||||
tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true);
|
tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true);
|
||||||
@ -1823,6 +1895,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
|
|||||||
if (disable) usbd_sof_enable(rhport, false);
|
if (disable) usbd_sof_enable(rhport, false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
audiod_calc_tx_packet_sz(audio);
|
||||||
|
#endif
|
||||||
|
|
||||||
tud_control_status(rhport, p_request);
|
tud_control_status(rhport, p_request);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2265,6 +2341,19 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req
|
|||||||
// Copy into buffer
|
// Copy into buffer
|
||||||
TU_VERIFY(0 == tu_memcpy_s(_audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz, data, (size_t)len));
|
TU_VERIFY(0 == tu_memcpy_s(_audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz, data, (size_t)len));
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
// Find data for sampling_frequency_control
|
||||||
|
if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE)
|
||||||
|
{
|
||||||
|
uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
|
||||||
|
uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
|
||||||
|
if (_audiod_fct[func_id].bclock_id_tx == entityID && ctrlSel == AUDIO_CS_CTRL_SAM_FREQ && p_request->bRequest == AUDIO_CS_REQ_CUR)
|
||||||
|
{
|
||||||
|
_audiod_fct[func_id].sample_rate_tx = tu_unaligned_read32(_audiod_fct[func_id].ctrl_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Schedule transmit
|
// Schedule transmit
|
||||||
return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len);
|
return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len);
|
||||||
}
|
}
|
||||||
@ -2404,7 +2493,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING
|
#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING)
|
||||||
// p_desc points to the AS interface of alternate setting zero
|
// p_desc points to the AS interface of alternate setting zero
|
||||||
// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter
|
// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter
|
||||||
// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for!
|
// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for!
|
||||||
@ -2442,7 +2531,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
|
||||||
if (as_itf == audio->ep_out_as_intf_num)
|
if (as_itf == audio->ep_out_as_intf_num)
|
||||||
{
|
{
|
||||||
audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels;
|
audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels;
|
||||||
@ -2455,7 +2544,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats)
|
// Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats)
|
||||||
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING
|
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING
|
||||||
if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I)
|
if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I)
|
||||||
{
|
{
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT
|
||||||
@ -2475,7 +2564,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
|
||||||
if (as_itf == audio->ep_out_as_intf_num)
|
if (as_itf == audio->ep_out_as_intf_num)
|
||||||
{
|
{
|
||||||
audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize;
|
audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize;
|
||||||
@ -2491,6 +2580,96 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
|
||||||
|
static bool audiod_calc_tx_packet_sz(audiod_function_t* audio)
|
||||||
|
{
|
||||||
|
TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I);
|
||||||
|
TU_VERIFY(audio->n_channels_tx);
|
||||||
|
TU_VERIFY(audio->n_bytes_per_sampe_tx);
|
||||||
|
TU_VERIFY(audio->interval_tx);
|
||||||
|
TU_VERIFY(audio->sample_rate_tx);
|
||||||
|
|
||||||
|
const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL) ? audio->interval_tx : 1 << (audio->interval_tx - 1);
|
||||||
|
|
||||||
|
const uint16_t sample_normimal = (uint16_t)(audio->sample_rate_tx * interval / ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
|
||||||
|
const uint16_t sample_reminder = (uint16_t)(audio->sample_rate_tx * interval % ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
|
||||||
|
|
||||||
|
const uint16_t packet_sz_tx_min = (uint16_t)((sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx);
|
||||||
|
const uint16_t packet_sz_tx_norm = (uint16_t)(sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sampe_tx);
|
||||||
|
const uint16_t packet_sz_tx_max = (uint16_t)((sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx);
|
||||||
|
|
||||||
|
// Endpoint size must larger than packet size
|
||||||
|
TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz);
|
||||||
|
|
||||||
|
// Frmt20.pdf 2.3.1.1 USB Packets
|
||||||
|
if (sample_reminder)
|
||||||
|
{
|
||||||
|
// All virtual frame packets must either contain INT(nav) audio slots (small VFP) or INT(nav)+1 (large VFP) audio slots
|
||||||
|
audio->packet_sz_tx[0] = packet_sz_tx_norm;
|
||||||
|
audio->packet_sz_tx[1] = packet_sz_tx_norm;
|
||||||
|
audio->packet_sz_tx[2] = packet_sz_tx_max;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// In the case where nav = INT(nav), ni may vary between INT(nav)-1 (small VFP), INT(nav)
|
||||||
|
// (medium VFP) and INT(nav)+1 (large VFP).
|
||||||
|
audio->packet_sz_tx[0] = packet_sz_tx_min;
|
||||||
|
audio->packet_sz_tx[1] = packet_sz_tx_norm;
|
||||||
|
audio->packet_sz_tx[2] = packet_sz_tx_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t max_depth)
|
||||||
|
{
|
||||||
|
// Flow control need a FIFO size of at least 4*Navg
|
||||||
|
if(norminal_size[1] && norminal_size[1] <= fifo_depth * 4)
|
||||||
|
{
|
||||||
|
// Use blackout to prioritize normal size packet
|
||||||
|
static int ctrl_blackout = 0;
|
||||||
|
uint16_t packet_size;
|
||||||
|
uint16_t slot_size = norminal_size[2] - norminal_size[1];
|
||||||
|
if (data_count < norminal_size[0])
|
||||||
|
{
|
||||||
|
// If you get here frequently, then your I2S clock deviation is too big !
|
||||||
|
packet_size = 0;
|
||||||
|
} else
|
||||||
|
if (data_count < fifo_depth / 2 - slot_size && !ctrl_blackout)
|
||||||
|
{
|
||||||
|
packet_size = norminal_size[0];
|
||||||
|
ctrl_blackout = 10;
|
||||||
|
} else
|
||||||
|
if (data_count > fifo_depth / 2 + slot_size && !ctrl_blackout)
|
||||||
|
{
|
||||||
|
packet_size = norminal_size[2];
|
||||||
|
if(norminal_size[0] == norminal_size[1])
|
||||||
|
{
|
||||||
|
// nav > INT(nav), eg. 44.1k, 88.2k
|
||||||
|
ctrl_blackout = 0;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// nav = INT(nav), eg. 48k, 96k
|
||||||
|
ctrl_blackout = 10;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
packet_size = norminal_size[1];
|
||||||
|
if (ctrl_blackout)
|
||||||
|
{
|
||||||
|
ctrl_blackout--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Normally this cap is not necessary
|
||||||
|
return tu_min16(packet_size, max_depth);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return tu_min16(data_count, max_depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||||
|
|
||||||
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
|
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
|
||||||
|
@ -181,6 +181,11 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// (For TYPE-I format only) Flow control is necessary to allow IN ep send correct amount of data, unless it's a virtual device where data is perfectly synchronized to USB clock.
|
||||||
|
#ifndef CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
|
||||||
|
#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
// Enable/disable feedback EP (required for asynchronous RX applications)
|
// Enable/disable feedback EP (required for asynchronous RX applications)
|
||||||
#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||||
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1
|
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1
|
||||||
@ -392,6 +397,7 @@ tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_i
|
|||||||
uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len);
|
uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Application API (Interface0)
|
// Application API (Interface0)
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
Loading…
x
Reference in New Issue
Block a user