Skip to content

Commit 15aa593

Browse files
committed
wrap feedback and compute to its own struct/union
1 parent e5113a1 commit 15aa593

File tree

2 files changed

+78
-82
lines changed

2 files changed

+78
-82
lines changed

src/class/audio/audio_device.c

Lines changed: 70 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -306,21 +306,29 @@ typedef struct
306306

307307
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
308308

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.
313313

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;
316316

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
319320

320-
float fb_float_val;
321+
struct {
322+
uint32_t sample_freq;
323+
uint32_t mclk_freq;
324+
}fixed;
321325

322-
uint32_t fb_sample_freq;
323-
uint32_t fb_mclk_freq;
326+
// struct {
327+
//
328+
// }fifo_count;
329+
}compute;
330+
331+
} feedback;
324332

325333
#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
326334
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
@@ -437,10 +445,6 @@ static inline uint8_t tu_desc_subtype(void const* desc)
437445
}
438446
#endif
439447

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-
444448
bool tud_audio_n_mounted(uint8_t func_id)
445449
{
446450
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
10591063
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
10601064
static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio)
10611065
{
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);
10631067
}
10641068
#endif
10651069

@@ -1564,8 +1568,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
15641568
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
15651569
usbd_edpt_close(rhport, audio->ep_fb);
15661570
audio->ep_fb = 0;
1567-
audio->fb_n_frames = 0;
1568-
1571+
tu_memclr(&audio->feedback, sizeof(audio->feedback));
15691572
#endif
15701573
}
15711574
#endif
@@ -1679,8 +1682,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
16791682
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) // Check if usage is explicit data feedback
16801683
{
16811684
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;
16841686

16851687
// Enable SOF interrupt if callback is implemented
16861688
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 *
17081710
// Prepare feedback computation if callback is available
17091711
if (tud_audio_feedback_params_cb)
17101712
{
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;
17151714

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)
17201719
{
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;
17231733
}
17241734
}
17251735
#endif
@@ -2034,46 +2044,43 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
20342044
return false;
20352045
}
20362046

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-
20442047
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
20452048

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)
20472050
{
20482051
// 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()
20502053

20512054
// 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
20522055
// this lower limit ensures the measures feedback value has sufficient precision
20532056
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 )
20552060
{
20562061
TU_LOG1(" UAC2 feedback interval too small\r\n"); TU_BREAKPOINT(); return false;
20572062
}
20582063

20592064
// Check if parameters really allow for a power of two division
20602065
if ((mclk_freq % sample_freq) == 0 && tu_is_power_of_two(mclk_freq / sample_freq))
20612066
{
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)
20652071
{
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
20682075
{
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;
20712078
}
20722079

20732080
// 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;
20772084

20782085
return true;
20792086
}
@@ -2083,20 +2090,20 @@ uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles)
20832090
audiod_function_t* audio = &_audiod_fct[func_id];
20842091
uint32_t feedback;
20852092

2086-
switch (audio->fb_compute_method)
2093+
switch (audio->feedback.compute_method)
20872094
{
20882095
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);
20902097
break;
20912098

20922099
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);
20942101
break;
20952102

20962103
case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED:
20972104
{
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);
21002107
}
21012108
break;
21022109

@@ -2107,8 +2114,8 @@ uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles)
21072114
// The size of isochronous packets created by the device must be within the limits specified in FMT-2.0 section 2.3.1.1.
21082115
// This means that the deviation of actual packet size from nominal size must not exceed +/- one audio slot
21092116
// (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;
21122119

21132120
tud_audio_n_fb_set(func_id, feedback);
21142121

@@ -2135,11 +2142,12 @@ void audiod_sof_isr (uint8_t rhport, uint32_t frame_count)
21352142

21362143
if (audio->ep_fb != 0)
21372144
{
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);
21402148
if ( 0 == (frame_count & (interval-1)) )
21412149
{
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);
21432151
}
21442152
}
21452153
}
@@ -2431,7 +2439,7 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
24312439
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION
24322440
if ( TUSB_SPEED_FULL == tud_speed_get() )
24332441
{
2434-
uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val;
2442+
uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].feedback.value;
24352443

24362444
// For FS format is 10.14
24372445
*(fb++) = (feedback >> 2) & 0xFF;
@@ -2443,7 +2451,7 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
24432451
#else
24442452
{
24452453
// 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;
24472455
}
24482456
#endif
24492457

src/class/audio/audio_device.h

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -487,11 +487,6 @@ TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id);
487487
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);
488488
static inline bool tud_audio_fb_set(uint32_t feedback);
489489

490-
uint8_t tud_audio_n_get_fb_n_frames(uint8_t func_id);
491-
static inline uint8_t tud_audio_get_fb_n_frames();
492-
493-
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
494-
495490
// Update feedback value with passed cycles since last time this update function is called.
496491
// Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented
497492
// This function will also call tud_audio_feedback_set()
@@ -511,8 +506,8 @@ typedef struct {
511506
uint8_t method;
512507
union {
513508
struct {
514-
uint32_t sample_freq;
515-
uint32_t mclk_freq;
509+
uint32_t sample_freq; // sample frequency in Hz
510+
uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on
516511
}frequency;
517512

518513
struct {
@@ -523,18 +518,16 @@ typedef struct {
523518
};
524519
}audio_feedback_params_t;
525520

526-
527-
// TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param);
528-
529-
// mclk_freq : Main clock frequency in Hz i.e. master clock to which sample clock is locked
530-
// sample_freq : sample frequency in Hz
531-
// fixed_point : 0 float (default), 1 fixed point (for mcu without FPU)
532-
TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, uint32_t* sample_freq, uint32_t* mclk_freq, uint8_t* fixed_point);
521+
// Invoked when needed to set feedback parameters
522+
TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param);
533523

534524
// Callback in ISR context, invoked periodically according to feedback endpoint bInterval.
535525
// Could be used to compute and update feedback value
536-
TU_ATTR_WEAK void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_log2);
526+
// frame_number : current SOF count
527+
// interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor
528+
TU_ATTR_WEAK void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift);
537529

530+
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
538531

539532
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
540533
TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied);
@@ -682,11 +675,6 @@ static inline bool tud_audio_fb_set(uint32_t feedback)
682675
return tud_audio_n_fb_set(0, feedback);
683676
}
684677

685-
static inline uint8_t tud_audio_get_fb_n_frames()
686-
{
687-
return tud_audio_n_get_fb_n_frames(0);
688-
}
689-
690678
#endif
691679

692680
//--------------------------------------------------------------------+

0 commit comments

Comments
 (0)