@@ -306,21 +306,29 @@ typedef struct
306
306
307
307
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
308
308
309
- uint32_t fb_val ; // Feedback value for asynchronous mode (in 16.16 format).
310
- uint8_t fb_n_frames ; // Number of (micro)frames used to estimate feedback value
311
- uint8_t fb_n_frames_shift ;
312
- uint8_t fb_compute_method ;
309
+ struct {
310
+ uint32_t value ; // Feedback value for asynchronous mode (in 16.16 format).
311
+ uint32_t min_value ; // min value according to UAC2 FMT-2.0 section 2.3.1.1.
312
+ uint32_t max_value ; // max value according to UAC2 FMT-2.0 section 2.3.1.1.
313
313
314
- uint32_t fb_val_min ; // Maximum allowed feedback value according to UAC2 FMT-2.0 section 2.3.1.1.
315
- uint32_t fb_val_max ; // Maximum allowed feedback value according to UAC2 FMT-2.0 section 2.3.1.1.
314
+ uint8_t frame_shift ; // bInterval-1 in unit of frame (FS), micro-frame (HS)
315
+ uint8_t compute_method ;
316
316
317
- // should be union
318
- uint8_t fb_power_of_two_val ;
317
+ union {
318
+ uint8_t power_of_2 ; // pre-computed power of 2 shift
319
+ float float_const ; // pre-computed float constant
319
320
320
- float fb_float_val ;
321
+ struct {
322
+ uint32_t sample_freq ;
323
+ uint32_t mclk_freq ;
324
+ }fixed ;
321
325
322
- uint32_t fb_sample_freq ;
323
- uint32_t fb_mclk_freq ;
326
+ // struct {
327
+ //
328
+ // }fifo_count;
329
+ }compute ;
330
+
331
+ } feedback ;
324
332
325
333
#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
326
334
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
@@ -437,10 +445,6 @@ static inline uint8_t tu_desc_subtype(void const* desc)
437
445
}
438
446
#endif
439
447
440
- #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
441
- bool tud_audio_n_fb_set (uint8_t func_id , uint32_t feedback );
442
- #endif
443
-
444
448
bool tud_audio_n_mounted (uint8_t func_id )
445
449
{
446
450
TU_VERIFY (func_id < CFG_TUD_AUDIO );
@@ -1059,7 +1063,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
1059
1063
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
1060
1064
static inline bool audiod_fb_send (uint8_t rhport , audiod_function_t * audio )
1061
1065
{
1062
- return usbd_edpt_xfer (rhport , audio -> ep_fb , (uint8_t * ) & audio -> fb_val , 4 );
1066
+ return usbd_edpt_xfer (rhport , audio -> ep_fb , (uint8_t * ) & audio -> feedback . value , 4 );
1063
1067
}
1064
1068
#endif
1065
1069
@@ -1564,8 +1568,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
1564
1568
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
1565
1569
usbd_edpt_close (rhport , audio -> ep_fb );
1566
1570
audio -> ep_fb = 0 ;
1567
- audio -> fb_n_frames = 0 ;
1568
-
1571
+ tu_memclr (& audio -> feedback , sizeof (audio -> feedback ));
1569
1572
#endif
1570
1573
}
1571
1574
#endif
@@ -1679,8 +1682,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
1679
1682
if (tu_edpt_dir (ep_addr ) == TUSB_DIR_IN && desc_ep -> bmAttributes .usage == 1 ) // Check if usage is explicit data feedback
1680
1683
{
1681
1684
audio -> ep_fb = ep_addr ;
1682
- audio -> fb_n_frames = 1U << (desc_ep -> bInterval - 1 ); // TODO correctly set USB frame interval for SOF (not micro-frame)
1683
- audio -> fb_n_frames_shift = desc_ep -> bInterval - 1 ;
1685
+ audio -> feedback .frame_shift = desc_ep -> bInterval - 1 ;
1684
1686
1685
1687
// Enable SOF interrupt if callback is implemented
1686
1688
if (tud_audio_feedback_interval_isr ) usbd_sof_enable (rhport , true);
@@ -1708,18 +1710,26 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
1708
1710
// Prepare feedback computation if callback is available
1709
1711
if (tud_audio_feedback_params_cb )
1710
1712
{
1711
- uint32_t sample_freq = 0 ;
1712
- uint32_t mclk_freq = 0 ;
1713
- uint8_t fixed_point = 0 ;
1714
- tud_audio_feedback_params_cb (func_id , alt , & sample_freq , & mclk_freq , & fixed_point );
1713
+ audio_feedback_params_t fb_param ;
1715
1714
1716
- if ( sample_freq == 0 || mclk_freq == 0 )
1717
- {
1718
- audio -> fb_compute_method = AUDIO_FEEDBACK_METHOD_DISABLED ;
1719
- } else
1715
+ tud_audio_feedback_params_cb ( func_id , alt , & fb_param );
1716
+ audio -> feedback . compute_method = fb_param . method ;
1717
+
1718
+ switch ( fb_param . method )
1720
1719
{
1721
- audio -> fb_compute_method = fixed_point ? AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED : AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT ;
1722
- set_fb_params (audio , sample_freq , mclk_freq );
1720
+ case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED :
1721
+ case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT :
1722
+ case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2 :
1723
+ set_fb_params_freq (audio , fb_param .frequency .sample_freq , fb_param .frequency .mclk_freq );
1724
+ break ;
1725
+
1726
+ case AUDIO_FEEDBACK_METHOD_FIFO_COUNT_FIXED :
1727
+ case AUDIO_FEEDBACK_METHOD_FIFO_COUNT_FLOAT :
1728
+ // TODO feedback by fifo count
1729
+ break ;
1730
+
1731
+ // nothing to do
1732
+ default : break ;
1723
1733
}
1724
1734
}
1725
1735
#endif
@@ -2034,46 +2044,43 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
2034
2044
return false;
2035
2045
}
2036
2046
2037
- #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
2038
- uint8_t tud_audio_n_get_fb_n_frames (uint8_t func_id )
2039
- {
2040
- return _audiod_fct [func_id ].fb_n_frames ;
2041
- }
2042
- #endif
2043
-
2044
2047
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
2045
2048
2046
- static bool set_fb_params (audiod_function_t * audio , uint32_t sample_freq , uint32_t mclk_freq )
2049
+ static bool set_fb_params_freq (audiod_function_t * audio , uint32_t sample_freq , uint32_t mclk_freq )
2047
2050
{
2048
2051
// Check if frame interval is within sane limits
2049
- // The interval value audio->fb_n_frames was taken from the descriptors within audiod_set_interface()
2052
+ // The interval value n_frames was taken from the descriptors within audiod_set_interface()
2050
2053
2051
2054
// n_frames_min is ceil(2^10 * f_s / f_m) for full speed and ceil(2^13 * f_s / f_m) for high speed
2052
2055
// this lower limit ensures the measures feedback value has sufficient precision
2053
2056
uint32_t const k = (TUSB_SPEED_FULL == tud_speed_get ()) ? 10 : 13 ;
2054
- if ( (((1UL << k ) * sample_freq / mclk_freq ) + 1 ) > audio -> fb_n_frames )
2057
+ uint32_t const n_frame = (1UL << audio -> feedback .frame_shift );
2058
+
2059
+ if ( (((1UL << k ) * sample_freq / mclk_freq ) + 1 ) > n_frame )
2055
2060
{
2056
2061
TU_LOG1 (" UAC2 feedback interval too small\r\n" ); TU_BREAKPOINT (); return false;
2057
2062
}
2058
2063
2059
2064
// Check if parameters really allow for a power of two division
2060
2065
if ((mclk_freq % sample_freq ) == 0 && tu_is_power_of_two (mclk_freq / sample_freq ))
2061
2066
{
2062
- audio -> fb_compute_method = AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2 ;
2063
- audio -> fb_power_of_two_val = 16 - audio -> fb_n_frames_shift - tu_log2 (mclk_freq / sample_freq );
2064
- }else if ( audio -> fb_compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT )
2067
+ audio -> feedback .compute_method = AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2 ;
2068
+ audio -> feedback .compute .power_of_2 = 16 - audio -> feedback .frame_shift - tu_log2 (mclk_freq / sample_freq );
2069
+ }
2070
+ else if ( audio -> feedback .compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT )
2065
2071
{
2066
- audio -> fb_float_val = (float )sample_freq / mclk_freq * (1UL << (16 - audio -> fb_n_frames_shift ));
2067
- }else
2072
+ audio -> feedback .compute .float_const = (float )sample_freq / mclk_freq * (1UL << (16 - audio -> feedback .frame_shift ));
2073
+ }
2074
+ else
2068
2075
{
2069
- audio -> fb_sample_freq = sample_freq ;
2070
- audio -> fb_mclk_freq = mclk_freq ;
2076
+ audio -> feedback . compute . fixed . sample_freq = sample_freq ;
2077
+ audio -> feedback . compute . fixed . mclk_freq = mclk_freq ;
2071
2078
}
2072
2079
2073
2080
// Minimal/Maximum value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame)
2074
- uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get ()) ? 1000 : 8000 ;
2075
- audio -> fb_val_min = (sample_freq /frame_div - 1 ) << 16 ;
2076
- audio -> fb_val_max = (sample_freq /frame_div + 1 ) << 16 ;
2081
+ uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get ()) ? 1000 : 8000 ;
2082
+ audio -> feedback . min_value = (sample_freq /frame_div - 1 ) << 16 ;
2083
+ audio -> feedback . max_value = (sample_freq /frame_div + 1 ) << 16 ;
2077
2084
2078
2085
return true;
2079
2086
}
@@ -2083,20 +2090,20 @@ uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles)
2083
2090
audiod_function_t * audio = & _audiod_fct [func_id ];
2084
2091
uint32_t feedback ;
2085
2092
2086
- switch (audio -> fb_compute_method )
2093
+ switch (audio -> feedback . compute_method )
2087
2094
{
2088
2095
case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2 :
2089
- feedback = (cycles << audio -> fb_power_of_two_val );
2096
+ feedback = (cycles << audio -> feedback . compute . power_of_2 );
2090
2097
break ;
2091
2098
2092
2099
case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT :
2093
- feedback = (uint32_t ) ((float ) cylces * audio -> fb_float_val );
2100
+ feedback = (uint32_t ) ((float ) cycles * audio -> feedback . compute . float_const );
2094
2101
break ;
2095
2102
2096
2103
case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED :
2097
2104
{
2098
- uint64_t fb64 = (((uint64_t ) cycles ) * audio -> fb_sample_freq ) << (16 - audio -> fb_n_frames_shift );
2099
- feedback = (uint32_t ) (fb64 / audio -> fb_mclk_freq );
2105
+ uint64_t fb64 = (((uint64_t ) cycles ) * audio -> feedback . compute . fixed . sample_freq ) << (16 - audio -> feedback . frame_shift );
2106
+ feedback = (uint32_t ) (fb64 / audio -> feedback . compute . fixed . mclk_freq );
2100
2107
}
2101
2108
break ;
2102
2109
@@ -2107,8 +2114,8 @@ uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles)
2107
2114
// The size of isochronous packets created by the device must be within the limits specified in FMT-2.0 section 2.3.1.1.
2108
2115
// This means that the deviation of actual packet size from nominal size must not exceed +/- one audio slot
2109
2116
// (audio slot = channel count samples).
2110
- if ( feedback > audio -> fb_val_max ) feedback = audio -> fb_val_max ;
2111
- if ( feedback < audio -> fb_val_min ) feedback = audio -> fb_val_min ;
2117
+ if ( feedback > audio -> feedback . max_value ) feedback = audio -> feedback . max_value ;
2118
+ if ( feedback < audio -> feedback . min_value ) feedback = audio -> feedback . min_value ;
2112
2119
2113
2120
tud_audio_n_fb_set (func_id , feedback );
2114
2121
@@ -2135,11 +2142,12 @@ void audiod_sof_isr (uint8_t rhport, uint32_t frame_count)
2135
2142
2136
2143
if (audio -> ep_fb != 0 )
2137
2144
{
2138
- // TODO hs need to be adjusted to frame (SOF event is not generated for micro-frame)
2139
- uint32_t const interval = (1UL << audio -> fb_n_frames_shift );
2145
+ // HS shift need to be adjusted since SOF event is generated for frame only
2146
+ uint8_t const hs_adjust = (TUSB_SPEED_HIGH == tud_speed_get ()) ? 3 : 0 ;
2147
+ uint32_t const interval = 1UL << (audio -> feedback .frame_shift - hs_adjust );
2140
2148
if ( 0 == (frame_count & (interval - 1 )) )
2141
2149
{
2142
- if (tud_audio_feedback_interval_isr ) tud_audio_feedback_interval_isr (i , frame_count , audio -> fb_n_frames_shift );
2150
+ if (tud_audio_feedback_interval_isr ) tud_audio_feedback_interval_isr (i , frame_count , audio -> feedback . frame_shift );
2143
2151
}
2144
2152
}
2145
2153
}
@@ -2431,7 +2439,7 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
2431
2439
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION
2432
2440
if ( TUSB_SPEED_FULL == tud_speed_get () )
2433
2441
{
2434
- uint8_t * fb = (uint8_t * ) & _audiod_fct [func_id ].fb_val ;
2442
+ uint8_t * fb = (uint8_t * ) & _audiod_fct [func_id ].feedback . value ;
2435
2443
2436
2444
// For FS format is 10.14
2437
2445
* (fb ++ ) = (feedback >> 2 ) & 0xFF ;
@@ -2443,7 +2451,7 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
2443
2451
#else
2444
2452
{
2445
2453
// Send value as-is, caller will choose the appropriate format
2446
- _audiod_fct [func_id ].fb_val = feedback ;
2454
+ _audiod_fct [func_id ].feedback . value = feedback ;
2447
2455
}
2448
2456
#endif
2449
2457
0 commit comments