Skip to content

Commit 7094ff7

Browse files
author
Reinhard Panhuber
committed
Introduce 3 fb calc options: NO_SOF_BY_USER, SOF_BY_AUDIO_D, SOF_BY_USER
1 parent 65b6b79 commit 7094ff7

File tree

2 files changed

+116
-36
lines changed

2 files changed

+116
-36
lines changed

src/class/audio/audio_device.c

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,12 @@ typedef struct
305305
#endif
306306

307307
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
308-
#if !CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
308+
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER
309309
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
310311
#endif
311312

312-
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
313+
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
313314
volatile uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format).
314315
uint8_t fb_n_frames; // Number of (micro)frames used to estimate feedback value
315316
volatile uint8_t fb_n_frames_current; // Current (micro)frame number
@@ -328,10 +329,15 @@ typedef struct
328329
uint64_t fb_param_factor_N; // Numerator of feedback parameter coefficient
329330
uint64_t fb_param_factor_D; // Denominator of feedback parameter coefficient
330331
#endif
331-
#endif
332+
#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
332333

334+
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER
335+
volatile uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format).
336+
uint8_t fb_n_frames; // Number of (micro)frames used to estimate feedback value
333337
#endif
334-
#endif
338+
339+
#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
340+
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
335341

336342
#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
337343
tu_fifo_t ep_in_ff;
@@ -445,7 +451,7 @@ static inline uint8_t tu_desc_subtype(void const* desc)
445451
}
446452
#endif
447453

448-
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
454+
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER)
449455
static bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);
450456
#endif
451457

@@ -1572,6 +1578,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
15721578
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
15731579
usbd_edpt_close(rhport, audio->ep_fb);
15741580
audio->ep_fb = 0;
1581+
audio->fb_n_frames = 0;
1582+
15751583
#endif
15761584
}
15771585
#endif
@@ -1631,7 +1639,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
16311639

16321640
#endif
16331641
// Invoke callback - can be used to trigger data sampling if not already running
1634-
// if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
1642+
// if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
16351643

16361644
// Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded
16371645
// It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there
@@ -1665,10 +1673,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
16651673

16661674
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
16671675
// In case of asynchronous EP, call Cb after ep_fb is set
1668-
// if ( !(desc_ep->bmAttributes.sync == 0x01 && audio->ep_fb == 0) )
1669-
// {
1670-
// if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
1671-
// }
1676+
// if ( !(desc_ep->bmAttributes.sync == 0x01 && audio->ep_fb == 0) )
1677+
// {
1678+
// if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
1679+
// }
16721680
#else
16731681
// Invoke callback
16741682
if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
@@ -1685,19 +1693,22 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
16851693
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) // Check if usage is explicit data feedback
16861694
{
16871695
audio->ep_fb = ep_addr;
1696+
audio->fb_n_frames = desc_ep->bInterval;
16881697

1689-
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
1698+
#if ((CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER) || (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER))
16901699
usbd_sof_enable(rhport, true); // Enable SOF interrupt
1691-
audio->fb_n_frames = desc_ep->bInterval;
1700+
#endif
1701+
1702+
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
16921703
audio->fb_n_frames_current = 0;
16931704
audio->fb_n_cycles_old = 0;
16941705
#endif
16951706

1696-
// // Invoke callback after ep_out is set
1697-
// if (audio->ep_out != 0)
1698-
// {
1699-
// if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
1700-
// }
1707+
// // Invoke callback after ep_out is set
1708+
// if (audio->ep_out != 0)
1709+
// {
1710+
// if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
1711+
// }
17011712
}
17021713
#endif
17031714
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
@@ -1721,7 +1732,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
17211732
}
17221733

17231734
// Disable SOF interrupt if no driver has any enabled feedback EP
1724-
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
1735+
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && ((CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER) || (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER))
17251736

17261737
bool disable = true;
17271738

@@ -2025,7 +2036,14 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
20252036
return false;
20262037
}
20272038

2028-
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
2039+
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && ((CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER) || (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER))
2040+
uint8_t tud_audio_n_get_fb_n_frames(uint8_t func_id)
2041+
{
2042+
return _audiod_fct[func_id].fb_n_frames;
2043+
}
2044+
#endif
2045+
2046+
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER)
20292047

20302048
// This function must be called from the user within the tud_audio_set_itf_cb(rhport, p_request) callback function, where p_request needs to be checked as
20312049
// uint8_t const itf = tu_u16_low(p_request->wIndex);
@@ -2081,12 +2099,14 @@ TU_ATTR_WEAK bool tud_audio_set_fb_params(uint8_t func_id, uint32_t f_m, uint32_
20812099
}
20822100
#endif
20832101

2084-
void audiod_sof (uint8_t rhport, uint32_t frame_count)
2102+
TU_ATTR_WEAK void audiod_sof (uint8_t rhport, uint32_t frame_count)
20852103
{
20862104
(void) rhport;
20872105
(void) frame_count; // frame_count is not used since some devices may not provide the frame count value
20882106

2089-
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
2107+
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
2108+
2109+
#if (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER)
20902110

20912111
// Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec
20922112
// Boiled down, the feedback value Ff = n_samples / (micro)frame.
@@ -2136,7 +2156,23 @@ void audiod_sof (uint8_t rhport, uint32_t frame_count)
21362156
}
21372157
}
21382158

2139-
#endif
2159+
#endif // (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER)
2160+
2161+
#if (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER)
2162+
// Iterate over audio functions and call callback function
2163+
for(uint8_t i=0; i < CFG_TUD_AUDIO; i++)
2164+
{
2165+
audiod_function_t* audio = &_audiod_fct[i];
2166+
2167+
if (audio->ep_fb != 0)
2168+
{
2169+
tud_audio_sof_isr_cb(i, frame_count);
2170+
}
2171+
}
2172+
2173+
#endif // (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER)
2174+
2175+
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
21402176
}
21412177

21422178
bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len)
@@ -2416,7 +2452,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
24162452

24172453
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
24182454

2419-
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
2455+
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
24202456
static bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
24212457
#else
24222458
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)

src/class/audio/audio_device.h

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,24 @@
191191
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1
192192
#endif
193193

194+
// Possible options for determination of feedback value
195+
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER 1 // Feedback value must be determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 8 frames), i.e. a larger delay is introduced.
196+
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER 2 // Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter) - see tud_audio_set_fb_params(). Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller (e.g. 2 frames) and thus a smaller delay is possible, disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. This option is a great starting point to try the SOF ISR option but depending on your hardware setup (performance of the CPU) it might not work. If so, figure out why and use the next option. (The most critical point is the reading of the cycle counter value of f_m. It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced).
197+
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER 3 // Feedback value is determined by the user by use of SOF interrupt. The user may use tud_audio_sof_isr_cb() which is called every SOF (of course only invoked when an alternate interface other than zero was set). The number of frames used to determine the feedback value for the currently active alternate setting can be get by tud_audio_get_fb_n_frames(). The feedback value must be set by use of tud_audio_n_fb_set().
198+
194199
// Determine feedback value within SOF ISR within audio driver - if disabled the user has to call tud_audio_n_fb_set() with a suitable feedback value on its own. If done within audio driver SOF ISR, tud_audio_n_fb_set() is disabled for user
195-
#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
196-
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR 0 // 0 or 1
200+
#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION
201+
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER
202+
#endif
203+
204+
#ifdef CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION
205+
#if (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION != CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER && CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION != CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER && CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION != CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER)
206+
#error Unknown CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION. Possible choices are: CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER, CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER, or CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER!
207+
#endif
197208
#endif
198209

199210
// Feeback calculation mode
200-
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
211+
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
201212

202213
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_POWER_OF_TWO_SHIFT 1
203214
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_FLOAT 2
@@ -484,6 +495,8 @@ TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_byte
484495
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
485496
TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport);
486497

498+
#if (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER)
499+
487500
// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed.
488501
//
489502
// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default,
@@ -494,15 +507,16 @@ TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport);
494507
// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format.
495508

496509
// Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the feature is used, the user can not set the feedback value.
497-
# if !CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
510+
498511
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);
499512
static inline bool tud_audio_fb_set(uint32_t feedback);
500-
# else
501513

502-
// This callback function is called once the feedback value needs to be updated within the SOF ISR in the audio class. To determine the feedback value, some
503-
// parameters need to be given. The user must implement this callback function and provide the current cycle count of the master clock.
504-
// The feedback endpoint number can be used to identify the correct audio function in case multiple audio functions were defined.
505-
TU_ATTR_WEAK uint32_t tud_audio_n_get_fm_n_cycles_cb(uint8_t rhport, uint8_t ep_fb);
514+
uint8_t tud_audio_n_get_fb_n_frames(uint8_t func_id);
515+
static inline uint8_t tud_audio_get_fb_n_frames();
516+
517+
#endif // (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER)
518+
519+
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
506520

507521
// f_m : Main clock frequency in Hz i.e. master clock to which sample clock is locked
508522
// f_s : Current sample rate in Hz
@@ -513,10 +527,34 @@ TU_ATTR_WEAK uint32_t tud_audio_n_get_fm_n_cycles_cb(uint8_t rhport, uint8_t ep_
513527
// uint8_t const alt = tu_u16_low(p_request->wValue);
514528
// such that tud_audio_set_fb_params() gets called with the parameters corresponding to the defined interface and alternate setting
515529
// Also, start the main clock cycle counter (or reset its value) within tud_audio_set_itf_cb()
516-
TU_ATTR_WEAK bool tud_audio_set_fb_params(uint8_t func_id, uint32_t f_m, uint32_t f_s, uint32_t * p_cycle_count);
517-
#endif
530+
bool tud_audio_set_fb_params(uint8_t func_id, uint32_t f_m, uint32_t f_s, uint32_t * p_cycle_count);
518531

519-
#endif
532+
#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
533+
534+
#if (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER)
535+
536+
// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed.
537+
//
538+
// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default,
539+
// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb
540+
// expects 16.16 format and handles the conversion to 10.14 on FS.
541+
//
542+
// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the
543+
// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format.
544+
545+
// Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the feature is used, the user can not set the feedback value.
546+
547+
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);
548+
static inline bool tud_audio_fb_set(uint32_t feedback);
549+
550+
uint8_t tud_audio_n_get_fb_n_frames(uint8_t func_id);
551+
static inline uint8_t tud_audio_get_fb_n_frames();
552+
553+
TU_ATTR_WEAK void tud_audio_sof_isr_cb(uint8_t func_id, uint32_t frame);
554+
555+
#endif // (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER)
556+
557+
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
520558

521559
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
522560
TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied);
@@ -657,11 +695,17 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t l
657695
}
658696
#endif
659697

660-
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && !CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_WITHIN_SOF_ISR
698+
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP && ((CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER) || (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER))
661699
static inline bool tud_audio_fb_set(uint32_t feedback)
662700
{
663701
return tud_audio_n_fb_set(0, feedback);
664702
}
703+
704+
static inline uint8_t tud_audio_get_fb_n_frames()
705+
{
706+
return tud_audio_n_get_fb_n_frames(0);
707+
}
708+
665709
#endif
666710

667711
//--------------------------------------------------------------------+

0 commit comments

Comments
 (0)