14#ifndef ARDUINO_USB_MODE
15#error This Microcontroller has no Native USB interface
17#if ARDUINO_USB_MODE == 1
18#error This sketch should be used when USB is in OTG mode
23#error This Microcontroller has no Native USB interface
27#include "AudioLogger.h"
32#include "device/usbd.h"
33#include "device/usbd_pvt.h"
37#define USB_DESCR_MAX_LEN 512
42#ifdef TUD_AUDIO20_DESC_IAD_LEN
43#define TUD_AUDIO_DESC_IAD_LEN TUD_AUDIO20_DESC_IAD_LEN
44#define AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL \
45 AUDIO20_CS_AC_INTERFACE_INPUT_TERMINAL
46#define AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL \
47 AUDIO20_CS_AC_INTERFACE_OUTPUT_TERMINAL
48#define AUDIO_CS_CTRL_SAM_FREQ AUDIO20_CS_CTRL_SAM_FREQ
49#define AUDIO_CS_CTRL_CLK_VALID AUDIO20_CS_CTRL_CLK_VALID
50#define AUDIO_CS_REQ_CUR AUDIO20_CS_REQ_CUR
51#define AUDIO_CS_REQ_RANGE AUDIO20_CS_REQ_RANGE
52#define AUDIO_CS_AS_INTERFACE_AS_GENERAL AUDIO20_CS_AS_INTERFACE_AS_GENERAL
53#define AUDIO_CS_AS_INTERFACE_FORMAT_TYPE AUDIO20_CS_AS_INTERFACE_FORMAT_TYPE
54#define audio_desc_cs_ac_interface_t audio20_desc_cs_ac_interface_t
55#define audio_desc_cs_as_interface_t audio20_desc_cs_as_interface_t
56#define audio_desc_type_I_format_t audio20_desc_type_I_format_t
58#define TUSB_EDPT_XFER(rp, ep, buf, sz) usbd_edpt_xfer(rp, ep, buf, sz, false)
59#define TUSB_EDPT_XFER_FIFO(rp, ep, ff, sz) \
60 usbd_edpt_xfer_fifo(rp, ep, ff, sz, false)
61#define TUSB_FIFO_CONFIG(f, buf, d, ov) tu_fifo_config(f, buf, d, ov)
64#define TUSB_EDPT_XFER(rp, ep, buf, sz) usbd_edpt_xfer(rp, ep, buf, sz)
65#define TUSB_EDPT_XFER_FIFO(rp, ep, ff, sz) usbd_edpt_xfer_fifo(rp, ep, ff, sz)
66#define TUSB_FIFO_CONFIG(f, buf, d, ov) tu_fifo_config(f, buf, d, 1, ov)
69#ifndef AUDIO10_CS_AC_INTERFACE_INPUT_TERMINAL
70#define AUDIO10_CS_AC_INTERFACE_INPUT_TERMINAL \
71 AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL
73#ifndef AUDIO_CS_CTRL_CLK_VALID
74#define AUDIO_CS_CTRL_CLK_VALID 0x02u
76#ifndef AUDIO_CS_REQ_RANGE
77#define AUDIO_CS_REQ_RANGE 0x02u
82#ifndef AUDIO_FU_CTRL_MUTE
83#define AUDIO_FU_CTRL_MUTE 0x01u
85#ifndef AUDIO_FU_CTRL_VOLUME
86#define AUDIO_FU_CTRL_VOLUME 0x02u
93 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000};
117 enum audio_format_type_t {
119 AUDIO_FORMAT_TYPE_II,
120 AUDIO_FORMAT_TYPE_III,
129 enum audio_feedback_method_t {
130 AUDIO_FEEDBACK_METHOD_DISABLED,
131 AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED,
132 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT,
133 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2,
134 AUDIO_FEEDBACK_METHOD_FIFO_COUNT
143 struct audiod_function_t {
164 bool format_correction;
184 audio_format_type_t format_type_tx;
195 std::vector<uint8_t> ctrl_buf;
196 std::vector<uint8_t> alt_setting;
197 std::vector<uint8_t> lin_buf_out;
198 std::vector<uint8_t> lin_buf_in;
199 std::vector<uint32_t> fb_buf;
200 std::vector<uint8_t> ep_in_sw_buf;
201 std::vector<uint8_t> ep_out_sw_buf;
210 struct audio_feedback_params_t {
260 LOGE(
"Unsupported bits_per_sample: %d (must be 16, 24, or 32)",
276 "Could not change channel count from %d to %d: channel count is "
282 "Could not change bits per sample from %d to %d: bits per sample is "
320 LOGE(
"Unsupported bits_per_sample: %d (must be 16, 24, or 32)",
350 LOGE(
"beginUSB failed");
412 LOGW(
"setVolume %f channel: %d",
vol, channel);
413 if (channel >=
volume_.size())
return false;
424 return (channel <
mute_.size()) ?
mute_[channel] :
false;
432 LOGW(
"setMute %s channel: %d", m ?
"true" :
"false", channel);
433 if (channel >=
mute_.size())
return false;
478 if (
fct.ep_in != 0)
return true;
486 if (
fct.ep_out != 0)
return true;
628 audio_feedback_params_t*)>
660 while (written < len) {
704 std::fill(audio.lin_buf_in.begin(), audio.lin_buf_in.end(), 0);
705 std::fill(audio.lin_buf_out.begin(), audio.lin_buf_out.end(), 0);
749 driver.name =
"AUDIO";
750 driver.init = [](
void) {
753 driver.deinit = [](
void) {
756 driver.reset = [](
uint8_t rhport) {
767 rhport,
stage, request);
942 if (
volume_.empty())
return 1.0f;
943 if (
mute_[0])
return 0.0f;
946 if (
mute_[channel])
return 0.0f;
950 template <
typename T>
953 for (
size_t i = 0; i < sample_count; i++) {
956 data[i] = (
T)(data[i] *
vol);
971 LOGW(
"Sample rate changed to %u Hz", rate);
1003 if (
vol >= 1.0f)
return 0;
1010 if (
v == (
int16_t)0x8000)
return 0.0f;
1011 if (
v >= 0)
return 1.0f;
1073 return bps == 16 ||
bps == 24 ||
bps == 32;
1090 while (p <
sz) p <<= 1;
1097 return offsetof(audiod_function_t, ctrl_buf_sz) +
1098 sizeof(((audiod_function_t*)0)->ctrl_buf_sz);
1108 switch (audio->feedback.compute_method) {
1109 case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: {
1112 audio->feedback.compute.fifo_count.fifo_lvl_avg =
1113 audio->feedback.compute.fifo_count.fifo_lvl_avg -
1114 (audio->feedback.compute.fifo_count.fifo_lvl_avg >> 8) +
1116 uint32_t avg = audio->feedback.compute.fifo_count.fifo_lvl_avg >> 8;
1117 uint32_t thr = audio->feedback.compute.fifo_count.fifo_lvl_thr;
1118 uint32_t nom = audio->feedback.compute.fifo_count.nom_value;
1120 audio->feedback.value =
1121 nom + (
uint32_t)audio->feedback.compute.fifo_count.rate_const[0] *
1125 (
uint32_t)audio->feedback.compute.fifo_count.rate_const[1] *
1127 audio->feedback.value =
1130 audio->feedback.value =
1131 TU_MIN(
TU_MAX(audio->feedback.value, audio->feedback.min_value),
1132 audio->feedback.max_value);
1135 case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
1136 audio->feedback.value = 1UL << audio->feedback.compute.power_of_2;
1139 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
1140 audio->feedback.value =
1141 (
uint32_t)(audio->feedback.compute.float_const *
1142 (
float)(1UL << (16u - (frame_shift - 1u))));
1145 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: {
1148 audio->feedback.value =
1149 (audio->feedback.compute.fixed.sample_freq << 16) /
frame_div;
1171 audio->ctrl_buf.resize(size);
1172 audio->ctrl_buf_sz = size;
1180 audio->lin_buf_in.resize(
max_pkt);
1193 audio->lin_buf_out.resize(
max_pkt);
1196 audio->fb_buf.resize(1);
1236 if (
itf_desc->bNumEndpoints == 1) {
1250 uint8_t ep_in = 0, ep_out = 0, ep_fb = 0;
1262 ep_fb =
desc_ep->bEndpointAddress;
1264 if (
desc_ep->bmAttributes.usage == 0) {
1267 ep_in =
desc_ep->bEndpointAddress;
1273 ep_out =
desc_ep->bEndpointAddress;
1292#ifdef TUP_DCD_EDPT_ISO_ALLOC
1300 LOGD(
"iso_activate+release OUT: done");
1324 desc_ep->bmAttributes.usage == 0 &&
1362 LOGE(
" UAC2: interrupt EP 0x%02x open failed",
ep_addr);
1397 switch (
p_request->bmRequestType_bit.recipient) {
1478 audio->alt_setting.size() != 0) {
1541 if (audio->ep_fb != 0) {
1545 1UL << (audio->feedback.frame_shift -
hs_adjust);
1546 if (0 == (frame_count & (
interval - 1))) {
1548 audio->feedback.frame_shift);
1579 memcpy(cb + 2 + i * 12, &
r, 4);
1580 memcpy(cb + 2 + i * 12 + 4, &
r, 4);
1581 memcpy(cb + 2 + i * 12 + 8, &
z, 4);
1590 memcpy(cb + 2, &rate, 4);
1591 memcpy(cb + 6, &rate, 4);
1608 cb[0] =
isMute(channel) ? 1 : 0;
1711 switch (
p_request->bmRequestType_bit.recipient) {
1738 ->bInterfaceNumber ==
itf) {
1804 ->bInterfaceNumber ==
itf) {
1821 if (audio->sample_rate_tx == 0)
1831 audio->n_channels_tx =
1833 audio->format_type_tx =
1841 AUDIO_FORMAT_TYPE_I) {
1842 audio->n_bytes_per_sample_tx =
1849 if (audio->n_channels_tx == 0) audio->n_channels_tx =
config_.
channels;
1850 if (audio->n_bytes_per_sample_tx == 0)
1852 if (audio->format_type_tx == 0) audio->format_type_tx = AUDIO_FORMAT_TYPE_I;
1865 if (audio->p_desc) {
1931 LOGI(
" Get itf: %u - current alt: %u",
itf,
1939 audio->feedback.format_correction;
1945 *(
fb++) = (audio->feedback.value >> 2) & 0xFF;
1946 *(
fb++) = (audio->feedback.value >> 10) & 0xFF;
1947 *(
fb++) = (audio->feedback.value >> 18) & 0xFF;
1950 audio->fb_buf[0] = audio->feedback.value;
1968 (
uint8_t*)audio->fb_buf.data(),
1976 audio->ep_in_as_intf_num = 0;
1977#ifndef TUP_DCD_EDPT_ISO_ALLOC
1986 audio->packet_sz_tx[0] = 0;
1987 audio->packet_sz_tx[1] = 0;
1988 audio->packet_sz_tx[2] = 0;
1996 audio->ep_out_as_intf_num = 0;
1997#ifndef TUP_DCD_EDPT_ISO_ALLOC
2006 tu_memclr(&audio->feedback,
sizeof(audio->feedback));
2014#ifdef TUP_DCD_EDPT_ISO_ALLOC
2033 audio->ep_in =
desc_ep->bEndpointAddress;
2034 audio->ep_in_as_intf_num =
itf;
2036 if (audio->ep_in_sz == 0)
return;
2044 audio->lin_buf_in.assign(audio->ep_in_sz, 0);
2053 LOGD(
"openEpOut: ep=0x%02x sz=%u",
desc_ep->bEndpointAddress,
2055 audio->ep_out =
desc_ep->bEndpointAddress;
2056 audio->ep_out_as_intf_num =
itf;
2058 if (audio->ep_out_sz == 0)
return;
2063 if (audio->lin_buf_out.size() < audio->ep_out_sz)
2064 audio->lin_buf_out.assign(audio->ep_out_sz, 0);
2066 audio->lin_buf_out.data(),
2068 LOGD(
" XFER armed: %s, buf=%p sz=%u",
xfer_ok ?
"OK" :
"FAIL",
2069 audio->lin_buf_out.data(), audio->ep_out_sz);
2074 LOGD(
" XFER_FIFO armed: %s",
xfer_ok ?
"OK" :
"FAIL");
2082 audio->ep_fb =
desc_ep->bEndpointAddress;
2083 audio->feedback.frame_shift =
desc_ep->bInterval - 1;
2090 audio_feedback_params_t
fb_param = {};
2091 fb_param.method = AUDIO_FEEDBACK_METHOD_FIFO_COUNT;
2095 audio->feedback.compute_method =
fb_param.method;
2099 audio->feedback.format_correction =
2108 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED:
2109 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
2110 case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
2114 case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: {
2119 audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_lvl_thr;
2120 audio->feedback.compute.fifo_count.fifo_lvl_avg =
2124 audio->feedback.compute.fifo_count.nom_value =
nominal;
2125 audio->feedback.compute.fifo_count.rate_const[0] =
2127 audio->feedback.compute.fifo_count.rate_const[1] =
2130 audio->feedback.compute.fifo_count.rate_const[0] /= 8;
2131 audio->feedback.compute.fifo_count.rate_const[1] /= 8;
2142 uint8_t const* p_desc = audio->p_desc;
2145 LOGD(
" openEPs: p_desc=%p end=%p len=%u itf=%u alt=%u",
2159 LOGD(
" scan: type=0x%02x len=%u offset=%d",
2160 p_desc[1], p_desc[0], (
int)(p_desc - audio->p_desc));
2165 LOGD(
" activating ep=0x%02x type=%u...",
2169 LOGD(
" activateEndpoint FAILED");
2173 LOGD(
" activated OK");
2182 desc_ep->bmAttributes.usage == 0x00)
2190 desc_ep->bmAttributes.usage == 1)
2215 LOGD(
"SET_ITF itf=%u alt=%u [start]",
itf,
alt);
2221 LOGD(
" AS interface %u not found",
itf);
2268 if ((((1UL <<
k) * sample_freq / mclk_freq) + 1) >
n_frame) {
2269 LOGE(
" UAC2 feedback interval too small");
2275 if ((mclk_freq % sample_freq) == 0 &&
2277 audio->feedback.compute_method =
2278 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2;
2279 audio->feedback.compute.power_of_2 =
2280 (
uint8_t)(16 - (audio->feedback.frame_shift - 1) -
2281 tu_log2(mclk_freq / sample_freq));
2282 }
else if (audio->feedback.compute_method ==
2283 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) {
2284 audio->feedback.compute.float_const =
2285 (
float)sample_freq / (
float)mclk_freq *
2286 (1UL << (16 - (audio->feedback.frame_shift - 1)));
2288 audio->feedback.compute.fixed.sample_freq = sample_freq;
2289 audio->feedback.compute.fixed.mclk_freq = mclk_freq;
2296 TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I);
2298 TU_VERIFY(audio->n_bytes_per_sample_tx);
2303 audio->tx_sample_acc = 0;
2306 ? audio->interval_tx
2307 : 1 << (audio->interval_tx - 1);
2318 audio->n_bytes_per_sample_tx);
2321 audio->n_bytes_per_sample_tx);
2324 audio->n_bytes_per_sample_tx);
2353 if (audio->sample_rate_tx == 0 || audio->n_channels_tx == 0 ||
2354 audio->n_bytes_per_sample_tx == 0) {
2356 return audio->ep_in_sz;
2359 const uint8_t iv = audio->interval_tx ? audio->interval_tx : 1;
2363 audio->tx_sample_acc += audio->sample_rate_tx *
interval;
2365 audio->tx_sample_acc -= samples *
denom;
2368 samples * audio->n_channels_tx * audio->n_bytes_per_sample_tx;
2369 if (
bytes > audio->ep_in_sz)
bytes = audio->ep_in_sz;
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define AUDIO_CS_CTRL_CLK_VALID
Definition USBAudioDeviceBase.h:74
#define TUSB_EDPT_XFER(rp, ep, buf, sz)
Definition USBAudioDeviceBase.h:64
#define TUSB_FIFO_CONFIG(f, buf, d, ov)
Definition USBAudioDeviceBase.h:66
#define AUDIO_FU_CTRL_VOLUME
Definition USBAudioDeviceBase.h:86
#define AUDIO_FU_CTRL_MUTE
Definition USBAudioDeviceBase.h:83
#define AUDIO_CS_REQ_RANGE
Definition USBAudioDeviceBase.h:77
#define USB_DESCR_MAX_LEN
Definition USBAudioDeviceBase.h:37
usbd_class_driver_t const * usbd_app_driver_get_cb(uint8_t *count)
Definition USBAudioDeviceBase.h:2395
#define TUSB_EDPT_XFER_FIFO(rp, ep, ff, sz)
Definition USBAudioDeviceBase.h:65
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:30
@ RXTX_MODE
Definition AudioTypes.h:30
@ TX_MODE
Definition AudioTypes.h:30
@ RX_MODE
Definition AudioTypes.h:30