I am attempting to understand the USB feedback calculations used in the various asynchronous isochronous AudioStreaming sink examples (eg: audio_speaker and composite_hid_audio_unified). The code for all the examples appears to be essentially identical (USB_DeviceCalculateFeedback()), but I am either not correctly understanding it's operation or it seems to have a few fundamental flaws.
First, it appears the feedback is calculated based on the total amount of data send to the DAC (audioSendCount) and the total amount of data received via USB (totalFrameValue), with both values zeroed at the "start" of audio streaming. This basic approach seems to have at least two serious drawbacks:
- The calculated feedback value is a long-term average of the ratio between the two clock domains, and does not accurately represent the current clock ratio. If both clocks are perfectly stable, this would work fine, but if the clocks are drifting at all this long term average will not update properly.
- The feedback calculations eventually roll over or "wrap". This will only take about 6 hours for a 16-bit stereo 48 Khz samples (audioSendCount is only 32 bits), and can happen much faster with more channels, higher sample rates, and 24 or 32 bit samples.
If I understand the USB specifications correctly, the feedback value should be the actual measured local sample rate relative to the USB notion of time, i.e., the USB (micro)frame frequency. I do not understand why this isn't simply measured using one of the timers (eg: SCTimer clocked by the audio MCLK and using USBx_FRAME_TOGGLE as a capture trigger or similar).