changes proposal to audio feedback computation
This commit is contained in:
@@ -261,6 +261,13 @@ osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum {
|
||||
FEEDBACK_COMPUTE_DISABLED,
|
||||
FEEDBACK_COMPUTE_FLOAT,
|
||||
FEEDBACK_COMPUTE_FIXED,
|
||||
FEEDBACK_COMPUTE_POWER_OF_2,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t rhport;
|
||||
@@ -305,38 +312,22 @@ typedef struct
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_NO_SOF_BY_USER
|
||||
uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format).
|
||||
uint8_t fb_n_frames; // Number of (micro)frames used to estimate feedback value
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
|
||||
volatile uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format).
|
||||
uint32_t fb_val_min; // Maximum allowed feedback value according to UAC2 FMT-2.0 section 2.3.1.1.
|
||||
uint32_t fb_val_max; // Maximum allowed feedback value according to UAC2 FMT-2.0 section 2.3.1.1.
|
||||
uint8_t fb_n_frames; // Number of (micro)frames used to estimate feedback value
|
||||
volatile uint8_t fb_n_frames_current; // Current (micro)frame number
|
||||
volatile uint32_t fb_n_cycles_old; // Old cycle count
|
||||
uint32_t * fb_param_p_cycle_count; // Pointer to cycle counter
|
||||
uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format).
|
||||
uint8_t fb_n_frames; // Number of (micro)frames used to estimate feedback value
|
||||
uint8_t fb_n_frames_shift;
|
||||
uint8_t fb_compute_method;
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_POWER_OF_TWO_SHIFT
|
||||
uint32_t fb_val_min; // Maximum allowed feedback value according to UAC2 FMT-2.0 section 2.3.1.1.
|
||||
uint32_t fb_val_max; // Maximum allowed feedback value according to UAC2 FMT-2.0 section 2.3.1.1.
|
||||
|
||||
// should be union
|
||||
uint8_t fb_power_of_two_val;
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_FLOAT
|
||||
float fb_float_val;
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_FIXED_POINT
|
||||
uint64_t fb_param_factor_N; // Numerator of feedback parameter coefficient
|
||||
uint64_t fb_param_factor_D; // Denominator of feedback parameter coefficient
|
||||
#endif
|
||||
#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER
|
||||
volatile uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format).
|
||||
uint8_t fb_n_frames; // Number of (micro)frames used to estimate feedback value
|
||||
#endif
|
||||
uint32_t fb_param_factor_N;
|
||||
uint32_t fb_param_factor_D;
|
||||
|
||||
#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
|
||||
@@ -453,8 +444,8 @@ static inline uint8_t tu_desc_subtype(void const* desc)
|
||||
}
|
||||
#endif
|
||||
|
||||
#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)
|
||||
static bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);
|
||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);
|
||||
#endif
|
||||
|
||||
bool tud_audio_n_mounted(uint8_t func_id)
|
||||
@@ -1695,16 +1686,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
|
||||
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) // Check if usage is explicit data feedback
|
||||
{
|
||||
audio->ep_fb = ep_addr;
|
||||
audio->fb_n_frames = desc_ep->bInterval;
|
||||
audio->fb_n_frames = 1 << (desc_ep->bInterval -1);
|
||||
audio->fb_n_frames_shift = desc_ep->bInterval -1;
|
||||
|
||||
#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))
|
||||
usbd_sof_enable(rhport, true); // Enable SOF interrupt
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
|
||||
audio->fb_n_frames_current = 0;
|
||||
audio->fb_n_cycles_old = 0;
|
||||
#endif
|
||||
// Enable SOF interrupt if callback is implemented
|
||||
if (tud_audio_sof_isr) usbd_sof_enable(rhport, true);
|
||||
|
||||
// // Invoke callback after ep_out is set
|
||||
// if (audio->ep_out != 0)
|
||||
@@ -1725,6 +1711,24 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
|
||||
// Invoke one callback for a final set interface
|
||||
if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
|
||||
|
||||
// Prepare feedback computation if callback is available
|
||||
if (tud_audio_feedback_params_cb)
|
||||
{
|
||||
uint32_t sample_freq = 0;
|
||||
uint32_t mclk_freq = 0;
|
||||
uint8_t fixed_point = 0;
|
||||
tud_audio_feedback_params_cb(func_id, alt, &sample_freq, &mclk_freq, &fixed_point);
|
||||
|
||||
if ( sample_freq == 0 || mclk_freq == 0 )
|
||||
{
|
||||
audio->fb_compute_method = FEEDBACK_COMPUTE_DISABLED;
|
||||
}else
|
||||
{
|
||||
audio->fb_compute_method = fixed_point ? FEEDBACK_COMPUTE_FIXED : FEEDBACK_COMPUTE_FLOAT;
|
||||
set_fb_params(audio, sample_freq, mclk_freq);
|
||||
}
|
||||
}
|
||||
|
||||
// We are done - abort loop
|
||||
break;
|
||||
}
|
||||
@@ -1734,22 +1738,17 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
|
||||
}
|
||||
|
||||
// Disable SOF interrupt if no driver has any enabled feedback EP
|
||||
#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))
|
||||
|
||||
bool disable = true;
|
||||
|
||||
for(uint8_t i=0; i < CFG_TUD_AUDIO; i++)
|
||||
{
|
||||
if (_audiod_fct[i].ep_fb != 0)
|
||||
{
|
||||
disable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (disable) usbd_sof_enable(rhport, false);
|
||||
|
||||
#endif
|
||||
|
||||
tud_control_status(rhport, p_request);
|
||||
|
||||
return true;
|
||||
@@ -2022,7 +2021,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
|
||||
// Transmission of feedback EP finished
|
||||
if (_audiod_fct[func_id].ep_fb == ep_addr)
|
||||
{
|
||||
if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
|
||||
if (tud_audio_fb_done_cb) tud_audio_fb_done_cb(func_id);
|
||||
|
||||
// Schedule a transmit with the new value if EP is not busy
|
||||
if (!usbd_edpt_busy(rhport, _audiod_fct[func_id].ep_fb))
|
||||
@@ -2038,81 +2037,93 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
|
||||
return false;
|
||||
}
|
||||
|
||||
#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))
|
||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
uint8_t tud_audio_n_get_fb_n_frames(uint8_t func_id)
|
||||
{
|
||||
return _audiod_fct[func_id].fb_n_frames;
|
||||
}
|
||||
#endif
|
||||
|
||||
#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)
|
||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
|
||||
// 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
|
||||
// uint8_t const itf = tu_u16_low(p_request->wIndex);
|
||||
// uint8_t const alt = tu_u16_low(p_request->wValue);
|
||||
// such that tud_audio_set_fb_params() gets called with the parameters corresponding to the defined interface and alternate setting
|
||||
// Also, start the main clock cycle counter (or reset its value) within tud_audio_set_itf_cb()
|
||||
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)
|
||||
static bool set_fb_params(audiod_function_t* audio, uint32_t f_s, uint32_t f_m)
|
||||
{
|
||||
audiod_function_t* audio = &_audiod_fct[func_id];
|
||||
audio->fb_param_p_cycle_count = p_cycle_count;
|
||||
|
||||
// Check if frame interval is within sane limits
|
||||
// The interval value audio->fb_n_frames was taken from the descriptors within audiod_set_interface()
|
||||
|
||||
// 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 - this lower limit ensures the measures feedback value has sufficient precision
|
||||
if ((TUSB_SPEED_FULL == tud_speed_get() && ((2^10 * f_s / f_m) + 1) > audio->fb_n_frames) || (TUSB_SPEED_HIGH == tud_speed_get() && ((2^13 * f_s / f_m) + 1) > audio->fb_n_frames))
|
||||
// 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
|
||||
// this lower limit ensures the measures feedback value has sufficient precision
|
||||
uint32_t const k = (TUSB_SPEED_FULL == tud_speed_get()) ? 10 : 13;
|
||||
if ( (((1UL << k) * f_s / f_m) + 1) > audio->fb_n_frames )
|
||||
{
|
||||
TU_LOG2(" UAC2 feedback interval too small\r\n"); TU_BREAKPOINT(); return false;
|
||||
TU_LOG1(" UAC2 feedback interval too small\r\n"); TU_BREAKPOINT(); return false;
|
||||
}
|
||||
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_POWER_OF_TWO_SHIFT
|
||||
// Check if parameters really allow for a power of two division
|
||||
if ((f_m % f_s) != 0 || !tu_is_power_of_two(audio->fb_n_frames * f_m / f_s))
|
||||
if ((f_m % f_s) == 0 && tu_is_power_of_two(f_m / f_s))
|
||||
{
|
||||
TU_LOG2(" FEEDBACK_DETERMINATION_MODE_POWER_OF_TWO_SHIFT not possible!\r\n"); TU_BREAKPOINT(); return false;
|
||||
audio->fb_compute_method = FEEDBACK_COMPUTE_POWER_OF_2;
|
||||
audio->fb_power_of_two_val = 16 - audio->fb_n_frames_shift - tu_log2(f_m / f_s);
|
||||
}else if ( audio->fb_compute_method == FEEDBACK_COMPUTE_FLOAT)
|
||||
{
|
||||
audio->fb_float_val = (float)f_s / f_m * (1UL << (16 - audio->fb_n_frames_shift));
|
||||
}else
|
||||
{
|
||||
audio->fb_param_factor_N = f_s;
|
||||
audio->fb_param_factor_D = f_m;
|
||||
}
|
||||
|
||||
audio->fb_power_of_two_val = 16 - tu_log2(audio->fb_n_frames * f_m / f_s);
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_FLOAT
|
||||
audio->fb_float_val = (float)f_s / audio->fb_n_frames / f_m * (1 << 16);
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_FIXED_POINT
|
||||
|
||||
// f_s max is 2^19-1 = 524287 Hz
|
||||
// f_m max is 2^29/(1 ms * n_frames) for full speed and 2^29/(125 us * n_frames) for high speed, this means for f_m fitting in an uint32, n_frames must be < 125 for full speed and < 1000 for high speed (1000 does not fit into uint8 so the maximum possible value cannot even be reached by UAC2 - we don't need to check for it)
|
||||
|
||||
if ((f_s > (2^19)-1) || (TUSB_SPEED_FULL == tud_speed_get() && (audio->fb_n_frames > 125)))
|
||||
{
|
||||
// If this check fails, not every thing is lost - you need to re-evaluate the scaling factors of the parameters such that the numbers fit into uint64 again. feedback = n_cycles * S_c / (n_frames * S_n) * f_s * S_s / (f_m * S_m). In the end S_c*S_s / (S_n * S_m) = 2^16 for a 16.16 fixed point precision. If you find something, define your own function of tud_audio_set_feedback_params_fm_fs() and audiod_sof() and use your values
|
||||
TU_LOG2(" FEEDBACK_DETERMINATION_MODE_FIXED_POINT not possible!\r\n"); TU_BREAKPOINT(); return false;
|
||||
}
|
||||
|
||||
audio->fb_param_factor_N = (uint64_t)f_s << 13;
|
||||
audio->fb_param_factor_D = (uint64_t)f_m * audio->fb_n_frames;
|
||||
#endif
|
||||
|
||||
audio->fb_val_min = ((TUSB_SPEED_FULL == tud_speed_get() ? (f_s/1000) : (f_s/8000)) - 1) << 16; // Minimal value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame)
|
||||
audio->fb_val_max = ((TUSB_SPEED_FULL == tud_speed_get() ? (f_s/1000) : (f_s/8000)) + 1) << 16; // Maximum value in 16.16 format
|
||||
// Minimal/Maximum value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame)
|
||||
uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000;
|
||||
audio->fb_val_min = (f_s/frame_div - 1) << 16;
|
||||
audio->fb_val_max = (f_s/frame_div + 1) << 16;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
TU_ATTR_WEAK void audiod_sof (uint8_t rhport, uint32_t frame_count)
|
||||
uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles)
|
||||
{
|
||||
audiod_function_t* audio = &_audiod_fct[func_id];
|
||||
uint32_t feedback;
|
||||
|
||||
switch (audio->fb_compute_method)
|
||||
{
|
||||
case FEEDBACK_COMPUTE_POWER_OF_2:
|
||||
feedback = cycles << audio->fb_power_of_two_val;
|
||||
break;
|
||||
|
||||
case FEEDBACK_COMPUTE_FLOAT:
|
||||
feedback = (uint32_t) ((float) cylces * audio->fb_float_val);
|
||||
break;
|
||||
|
||||
case FEEDBACK_COMPUTE_FIXED:
|
||||
{
|
||||
uint64_t fb64 = (((uint64_t) cycles) * audio->fb_param_factor_N) << (16 - audio->fb_n_frames_shift);
|
||||
feedback = (uint32_t) (fb64 / audio->fb_param_factor_D);
|
||||
}
|
||||
break;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
|
||||
// For Windows: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/usb-2-0-audio-drivers
|
||||
// The size of isochronous packets created by the device must be within the limits specified in FMT-2.0 section 2.3.1.1.
|
||||
// This means that the deviation of actual packet size from nominal size must not exceed +/- one audio slot
|
||||
// (audio slot = channel count samples).
|
||||
if ( feedback > audio->fb_val_max ) feedback = audio->fb_val_max;
|
||||
if ( feedback < audio->fb_val_min ) feedback = audio->fb_val_min;
|
||||
|
||||
tud_audio_n_fb_set(func_id, feedback);
|
||||
|
||||
return feedback;
|
||||
}
|
||||
|
||||
void audiod_sof_isr (uint8_t rhport, uint32_t frame_count)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) frame_count; // frame_count is not used since some devices may not provide the frame count value
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
|
||||
#if (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER)
|
||||
|
||||
// Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec
|
||||
// Boiled down, the feedback value Ff = n_samples / (micro)frame.
|
||||
// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s)
|
||||
@@ -2126,59 +2137,13 @@ TU_ATTR_WEAK void audiod_sof (uint8_t rhport, uint32_t frame_count)
|
||||
|
||||
if (audio->ep_fb != 0)
|
||||
{
|
||||
audio->fb_n_frames_current++;
|
||||
if (audio->fb_n_frames_current == audio->fb_n_frames)
|
||||
uint32_t const interval = (1UL << audio->fb_n_frames);
|
||||
if ( 0 == (frame_count & (interval-1)) )
|
||||
{
|
||||
uint32_t n_cylces = *audio->fb_param_p_cycle_count;
|
||||
uint32_t feedback;
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_POWER_OF_TWO_SHIFT
|
||||
feedback = (n_cylces - audio->fb_n_cycles_old) << audio->fb_power_of_two_val;
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_FLOAT
|
||||
feedback = (uint32_t)((float)(n_cylces - audio->fb_n_cycles_old) * audio->fb_float_val);
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_MODE_FIXED_POINT
|
||||
feedback = ((n_cylces - audio->fb_n_cycles_old) << 3) * audio->fb_param_factor_N / audio->fb_param_factor_D; // feeback_param_factor_N has scaling factor of 13 bits, n_cycles 3 and feeback_param_factor_D 1, hence 16.16 precision
|
||||
#endif
|
||||
|
||||
// For Windows: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/usb-2-0-audio-drivers
|
||||
// The size of isochronous packets created by the device must be within the limits specified in FMT-2.0 section 2.3.1.1. This means that the deviation of actual packet size from nominal size must not exceed +/- one audio slot (audio slot = channel count samples).
|
||||
|
||||
if (feedback > audio->fb_val_max){
|
||||
feedback = audio->fb_val_max;
|
||||
}
|
||||
if ( feedback < audio->fb_val_min) {
|
||||
feedback = audio->fb_val_min;
|
||||
}
|
||||
|
||||
// Buffer count checks ?
|
||||
|
||||
tud_audio_n_fb_set(i, feedback);
|
||||
audio->fb_n_frames_current = 0;
|
||||
audio->fb_n_cycles_old = n_cylces;
|
||||
if(tud_audio_sof_isr) tud_audio_sof_isr(i, frame_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER)
|
||||
|
||||
#if (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER)
|
||||
// Iterate over audio functions and call callback function
|
||||
for(uint8_t i=0; i < CFG_TUD_AUDIO; i++)
|
||||
{
|
||||
audiod_function_t* audio = &_audiod_fct[i];
|
||||
|
||||
if (audio->ep_fb != 0)
|
||||
{
|
||||
tud_audio_sof_isr_cb(i, frame_count);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // (CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_USER)
|
||||
|
||||
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
}
|
||||
|
||||
@@ -2459,11 +2424,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION == CFG_TUD_AUDIO_ENABLE_FEEDBACK_DETERMINATION_OPTION_SOF_BY_AUDIO_DRIVER
|
||||
static bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
|
||||
#else
|
||||
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
|
||||
#endif
|
||||
{
|
||||
TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL);
|
||||
|
||||
|
Reference in New Issue
Block a user