3434// MACRO CONSTANT TYPEDEF PROTOTYPES
3535//--------------------------------------------------------------------+
3636
37- #ifndef AUDIO_SAMPLE_RATE
38- #define AUDIO_SAMPLE_RATE 48000
39- #endif
37+ // List of supported sample rates
38+ const uint32_t sample_rates [] = {44100 , 48000 , 88200 , 96000 };
39+ uint32_t current_sample_rate = 44100 ;
40+
41+ #define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates)
4042
4143/* Blink pattern
4244 * - 25 ms : streaming data
@@ -76,11 +78,16 @@ int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master chan
7678int16_t volume [CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1 ]; // +1 for master channel 0
7779
7880// Buffer for microphone data
79- int16_t mic_buf [1000 ];
81+ int32_t mic_buf [CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ / 4 ];
8082// Buffer for speaker data
81- int16_t spk_buf [1000 ];
83+ int32_t spk_buf [CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ / 4 ];
8284// Speaker data size received in the last frame
8385int spk_data_size ;
86+ // Resolution per format
87+ const uint8_t resolutions_per_format [CFG_TUD_AUDIO_FUNC_1_N_FORMATS ] = {CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX ,
88+ CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX };
89+ // Current resolution, update on format change
90+ uint8_t current_resolution ;
8491
8592void led_blinking_task (void );
8693void audio_task (void );
@@ -135,70 +142,76 @@ void tud_resume_cb(void)
135142 blink_interval_ms = BLINK_MOUNTED ;
136143}
137144
138- typedef struct TU_ATTR_PACKED
139- {
140- union
141- {
142- struct TU_ATTR_PACKED
143- {
144- uint8_t recipient : 5 ; ///< Recipient type tusb_request_recipient_t.
145- uint8_t type : 2 ; ///< Request type tusb_request_type_t.
146- uint8_t direction : 1 ; ///< Direction type. tusb_dir_t
147- } bmRequestType_bit ;
148-
149- uint8_t bmRequestType ;
150- };
151-
152- uint8_t bRequest ; ///< Request type audio_cs_req_t
153- uint8_t bChannelNumber ;
154- uint8_t bControlSelector ;
155- union
156- {
157- uint8_t bInterface ;
158- uint8_t bEndpoint ;
159- };
160- uint8_t bEntityID ;
161- uint16_t wLength ;
162- } audio_control_request_t ;
163-
164145// Helper for clock get requests
165146static bool tud_audio_clock_get_request (uint8_t rhport , audio_control_request_t const * request )
166147{
167148 TU_ASSERT (request -> bEntityID == UAC2_ENTITY_CLOCK );
168149
169- // Example supports only single frequency, same value will be used for current value and range
170150 if (request -> bControlSelector == AUDIO_CS_CTRL_SAM_FREQ )
171151 {
172152 if (request -> bRequest == AUDIO_CS_REQ_CUR )
173153 {
174- TU_LOG2 ("Clock get current freq %u\r\n" , AUDIO_SAMPLE_RATE );
154+ TU_LOG1 ("Clock get current freq %u\r\n" , current_sample_rate );
175155
176- audio_control_cur_4_t curf = { tu_htole32 (AUDIO_SAMPLE_RATE ) };
156+ audio_control_cur_4_t curf = { tu_htole32 (current_sample_rate ) };
177157 return tud_audio_buffer_and_schedule_control_xfer (rhport , (tusb_control_request_t const * )request , & curf , sizeof (curf ));
178158 }
179159 else if (request -> bRequest == AUDIO_CS_REQ_RANGE )
180160 {
181- audio_control_range_4_n_t (1 ) rangef =
161+ audio_control_range_4_n_t (N_SAMPLE_RATES ) rangef =
182162 {
183- .wNumSubRanges = tu_htole16 (1 ),
184- .subrange [0 ] = { tu_htole32 (AUDIO_SAMPLE_RATE ), tu_htole32 (AUDIO_SAMPLE_RATE ), 0 }
163+ .wNumSubRanges = tu_htole16 (N_SAMPLE_RATES )
185164 };
186- TU_LOG2 ("Clock get freq range (%d, %d, %d)\r\n" , (int )rangef .subrange [0 ].bMin , (int )rangef .subrange [0 ].bMax , (int )rangef .subrange [0 ].bRes );
165+ TU_LOG1 ("Clock get %d freq ranges\r\n" , N_SAMPLE_RATES );
166+ for (uint8_t i = 0 ; i < N_SAMPLE_RATES ; i ++ )
167+ {
168+ rangef .subrange [i ].bMin = sample_rates [i ];
169+ rangef .subrange [i ].bMax = sample_rates [i ];
170+ rangef .subrange [i ].bRes = 0 ;
171+ TU_LOG1 ("Range %d (%d, %d, %d)\r\n" , i , (int )rangef .subrange [i ].bMin , (int )rangef .subrange [i ].bMax , (int )rangef .subrange [i ].bRes );
172+ }
173+
187174 return tud_audio_buffer_and_schedule_control_xfer (rhport , (tusb_control_request_t const * )request , & rangef , sizeof (rangef ));
188175 }
189176 }
190177 else if (request -> bControlSelector == AUDIO_CS_CTRL_CLK_VALID &&
191178 request -> bRequest == AUDIO_CS_REQ_CUR )
192179 {
193180 audio_control_cur_1_t cur_valid = { .bCur = 1 };
194- TU_LOG2 ("Clock get is valid %u\r\n" , cur_valid .bCur );
181+ TU_LOG1 ("Clock get is valid %u\r\n" , cur_valid .bCur );
195182 return tud_audio_buffer_and_schedule_control_xfer (rhport , (tusb_control_request_t const * )request , & cur_valid , sizeof (cur_valid ));
196183 }
197184 TU_LOG1 ("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n" ,
198185 request -> bEntityID , request -> bControlSelector , request -> bRequest );
199186 return false;
200187}
201188
189+ // Helper for clock set requests
190+ static bool tud_audio_clock_set_request (uint8_t rhport , audio_control_request_t const * request , uint8_t const * buf )
191+ {
192+ (void )rhport ;
193+
194+ TU_ASSERT (request -> bEntityID == UAC2_ENTITY_CLOCK );
195+ TU_VERIFY (request -> bRequest == AUDIO_CS_REQ_CUR );
196+
197+ if (request -> bControlSelector == AUDIO_CS_CTRL_SAM_FREQ )
198+ {
199+ TU_VERIFY (request -> wLength == sizeof (audio_control_cur_4_t ));
200+
201+ current_sample_rate = ((audio_control_cur_4_t * )buf )-> bCur ;
202+
203+ TU_LOG1 ("Clock set current freq: %d\r\n" , current_sample_rate );
204+
205+ return true;
206+ }
207+ else
208+ {
209+ TU_LOG1 ("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n" ,
210+ request -> bEntityID , request -> bControlSelector , request -> bRequest );
211+ return false;
212+ }
213+ }
214+
202215// Helper for feature unit get requests
203216static bool tud_audio_feature_unit_get_request (uint8_t rhport , audio_control_request_t const * request )
204217{
@@ -207,7 +220,7 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req
207220 if (request -> bControlSelector == AUDIO_FU_CTRL_MUTE && request -> bRequest == AUDIO_CS_REQ_CUR )
208221 {
209222 audio_control_cur_1_t mute1 = { .bCur = mute [request -> bChannelNumber ] };
210- TU_LOG2 ("Get channel %u mute %d\r\n" , request -> bChannelNumber , mute1 .bCur );
223+ TU_LOG1 ("Get channel %u mute %d\r\n" , request -> bChannelNumber , mute1 .bCur );
211224 return tud_audio_buffer_and_schedule_control_xfer (rhport , (tusb_control_request_t const * )request , & mute1 , sizeof (mute1 ));
212225 }
213226 else if (UAC2_ENTITY_SPK_FEATURE_UNIT && request -> bControlSelector == AUDIO_FU_CTRL_VOLUME )
@@ -218,14 +231,14 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req
218231 .wNumSubRanges = tu_htole16 (1 ),
219232 .subrange [0 ] = { .bMin = tu_htole16 (- VOLUME_CTRL_50_DB ), tu_htole16 (VOLUME_CTRL_0_DB ), tu_htole16 (256 ) }
220233 };
221- TU_LOG2 ("Get channel %u volume range (%d, %d, %u) dB\r\n" , request -> bChannelNumber ,
234+ TU_LOG1 ("Get channel %u volume range (%d, %d, %u) dB\r\n" , request -> bChannelNumber ,
222235 range_vol .subrange [0 ].bMin / 256 , range_vol .subrange [0 ].bMax / 256 , range_vol .subrange [0 ].bRes / 256 );
223236 return tud_audio_buffer_and_schedule_control_xfer (rhport , (tusb_control_request_t const * )request , & range_vol , sizeof (range_vol ));
224237 }
225238 else if (request -> bRequest == AUDIO_CS_REQ_CUR )
226239 {
227240 audio_control_cur_2_t cur_vol = { .bCur = tu_htole16 (volume [request -> bChannelNumber ]) };
228- TU_LOG2 ("Get channel %u volume %u dB\r\n" , request -> bChannelNumber , cur_vol .bCur );
241+ TU_LOG1 ("Get channel %u volume %d dB\r\n" , request -> bChannelNumber , cur_vol .bCur / 256 );
229242 return tud_audio_buffer_and_schedule_control_xfer (rhport , (tusb_control_request_t const * )request , & cur_vol , sizeof (cur_vol ));
230243 }
231244 }
@@ -249,7 +262,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req
249262
250263 mute [request -> bChannelNumber ] = ((audio_control_cur_1_t * )buf )-> bCur ;
251264
252- TU_LOG2 ("Set channel %d Mute: %d\r\n" , request -> bChannelNumber , mute [request -> bChannelNumber ]);
265+ TU_LOG1 ("Set channel %d Mute: %d\r\n" , request -> bChannelNumber , mute [request -> bChannelNumber ]);
253266
254267 return true;
255268 }
@@ -259,7 +272,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req
259272
260273 volume [request -> bChannelNumber ] = ((audio_control_cur_2_t const * )buf )-> bCur ;
261274
262- TU_LOG2 ("Set channel %d volume: %d dB\r\n" , request -> bChannelNumber , volume [request -> bChannelNumber ] / 256 );
275+ TU_LOG1 ("Set channel %d volume: %d dB\r\n" , request -> bChannelNumber , volume [request -> bChannelNumber ] / 256 );
263276
264277 return true;
265278 }
@@ -299,7 +312,8 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
299312
300313 if (request -> bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT )
301314 return tud_audio_feature_unit_set_request (rhport , request , buf );
302-
315+ if (request -> bEntityID == UAC2_ENTITY_CLOCK )
316+ return tud_audio_clock_set_request (rhport , request , buf );
303317 TU_LOG1 ("Set request not handled, entity = %d, selector = %d, request = %d\r\n" ,
304318 request -> bEntityID , request -> bControlSelector , request -> bRequest );
305319
@@ -329,6 +343,13 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_reque
329343 if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt != 0 )
330344 blink_interval_ms = BLINK_STREAMING ;
331345
346+ // Clear buffer when streaming format is changed
347+ spk_data_size = 0 ;
348+ if (alt != 0 )
349+ {
350+ current_resolution = resolutions_per_format [alt - 1 ];
351+ }
352+
332353 return true;
333354}
334355
@@ -362,20 +383,40 @@ void audio_task(void)
362383{
363384 // When new data arrived, copy data from speaker buffer, to microphone buffer
364385 // and send it over
386+ // Only support speaker & headphone both have the same resolution
387+ // If one is 16bit another is 24bit be care of LOUD noise !
365388 if (spk_data_size )
366389 {
367- int16_t * src = spk_buf ;
368- int16_t * limit = spk_buf + spk_data_size / 2 ;
369- int16_t * dst = mic_buf ;
370- while (src < limit )
390+ if (current_resolution == 16 )
371391 {
372- // Combine two channels into one
373- int32_t left = * src ++ ;
374- int32_t right = * src ++ ;
375- * dst ++ = (int16_t )((left + right ) / 2 );
392+ int16_t * src = (int16_t * )spk_buf ;
393+ int16_t * limit = (int16_t * )spk_buf + spk_data_size / 2 ;
394+ int16_t * dst = (int16_t * )mic_buf ;
395+ while (src < limit )
396+ {
397+ // Combine two channels into one
398+ int32_t left = * src ++ ;
399+ int32_t right = * src ++ ;
400+ * dst ++ = (left >> 1 ) + (right >> 1 );
401+ }
402+ tud_audio_write ((uint8_t * )mic_buf , spk_data_size / 2 );
403+ spk_data_size = 0 ;
404+ }
405+ else if (current_resolution == 24 )
406+ {
407+ int32_t * src = spk_buf ;
408+ int32_t * limit = spk_buf + spk_data_size / 4 ;
409+ int32_t * dst = mic_buf ;
410+ while (src < limit )
411+ {
412+ // Combine two channels into one
413+ int32_t left = * src ++ ;
414+ int32_t right = * src ++ ;
415+ * dst ++ = ((left >> 1 ) + (right >> 1 )) & 0xffffff00 ;
416+ }
417+ tud_audio_write ((uint8_t * )mic_buf , spk_data_size / 2 );
418+ spk_data_size = 0 ;
376419 }
377- tud_audio_write ((uint8_t * )mic_buf , spk_data_size / 2 );
378- spk_data_size = 0 ;
379420 }
380421}
381422
0 commit comments