UAC2 explicit feedback

524 views
Skip to first unread message

AlemV

unread,
Jan 16, 2019, 10:00:11 AM1/16/19
to Audio-Widget
Hello,

I unsuccessfully try to get native Windows 10 UAC2 driver to work with the explicit feedback from STM32 USB-DAC, and I use the Audio widget source code (audio-widget-experimental branch) as a study guide.

Could you explain why with FS mode and HS mode the same FB_rate is sent to the host?
I agree with comment that it's needed right-shift once for 16.16 per 125µs microframe, but where does the 250 µs microframe?

Thanks,
Vladimir

Børge Strand-Bergesen

unread,
Jan 17, 2019, 2:46:53 AM1/17/19
to audio-...@googlegroups.com
Hi Vladimir, 

I'm curious about ports to other CPUs! Please let us know where we can find the repo. 

The Audio Widget is set up to use 250µs microframes, not 125µs. That is a part of the USB descriptor for the UAC2 code, I believe line 191 of the attachment. The decision was made long before I joined the project, and is probably a very good one. It reduces the poll rate in sequensial code while permitting the needed bandwidth (250µs worth of 192ksps stereo 32-bit samples = 384 bytes) to fit inside the 512-byte endpoint buffer of the AVR32. 

If your processor has access to larger endpoint buffers, you can reduse the frame rate further. That can only be a good thing, since with lower poll rate the CPU has time to do more tricks. (One thing I'd like to explore is adding jitter to the timing of the state machine to smear its noise impact.)

The frame rate of the feedback endpoint is rediculously high (line 210). At the time that part of the code was verified, not all OSes supported slower than 1ms polling on that IN EP. I haven't re-checked that lately.

As for HS and FS, that is also on my list to do better. As of the RC11 firmware (newly committed), UAC2 FS only supports 44.1 and 48ksps, since anything more won't fit into USB 1.1 timing and the HW endpoint buffers. However, the FS code isn't well tested. We'd have to get some USB 1.1 hardware to do that. 

UAC1 support is less and less important these days, and it's tied to USB 1.1 in our code base anyway. So I'd like to strip out HS code from the UAC1 image and descriptors. 


Cheers,
Børge


--
You received this message because you are subscribed to the Google Groups "Audio-Widget" group.
To unsubscribe from this group and stop receiving emails from it, send an email to audio-widget...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
UAC2_descriptor_RC11.txt

AlemV

unread,
Jan 18, 2019, 2:17:50 AM1/18/19
to Audio-Widget
Hi, Børge,

Thank you for your answer and for the descriptors report.

This is not the port of the Audio Widget, I use a very simple DAC at a rate of 44.1kHz x 16-bit for the test purposes. Source codes are not open yet, because I am only at the research stage. I could not find a single working open source UAC2 project with an explicit feedback other than Audio Widget, and I use your project source code as a great tutorial.

At the current stage, I'm just trying to get the Win10 UAC2 driver to send packets with the size required in explicit feedback. I have tried FS and HS modes but so far I have not succeeded. I decided that the Win10 UAC2 driver does not support explicit feedback, but they write, that "For the asynchronous OUT case the driver supports explicit feedback only."

In my HS test the UAC2 driver persistently sends 44 samples in every micro-frame, except for every 40th in which it sends 48 samples. As if there is no feedback at all. Although every 1 ms is sent 4 bytes of feedback, such as 0x002C1BAB or similar, since the actual frequency of the DAC is 44.108073 kHz.
For the FS mode the UAC2 driver always sends 176 samples in every 1ms frame, except for every 10th in which it sends 180 samples. My feedback value is 0x000B06EA or similar, sent each 1ms.

I am totaly confused. Could you please view the attached descriptor files, maybe some inconsistency will be evident.

I have a few questions more:
1. The bmChannelConfig in the AC Input Terminal Descriptor and AS Interface Descriptor in your project are not defined (equal to 0). Is this intentional?
2. Is there a need for a Device Qualifier Descriptor and Other Speed Configuration Descriptor for UAC2? I ask this question because I noticed that the Other Speed Configuration Descriptor for FS is the same as the Configuration Descriptor for HS, which, in my opinion, is not quite true.
3. Have you tried the device (UAC2, FS and HS, explicit feedback) with Win10 x64? The latest version of usbaudio2.sys is 10.0.17763.1 Dec 15 2018.

Vladimir


четверг, 17 января 2019 г., 10:46:53 UTC+3 пользователь Børge Strand-Bergesen написал:
UAC2-HS-44100x16-DTV.txt
UAC2-FS-44100x16-DTV.txt
UAC2-HS-44100x16-TDD.txt
UAC2-FS-44100x16-TDD.txt

Børge Strand-Bergesen

unread,
Jan 18, 2019, 3:44:50 AM1/18/19
to audio-...@googlegroups.com
Hi Vladimir, 

I'll try to fill in some of your blanks here.
 
This is not the port of the Audio Widget, I use a very simple DAC at a rate of 44.1kHz x 16-bit for the test purposes. Source codes are not open yet, because I am only at the research stage. I could not find a single working open source UAC2 project with an explicit feedback other than Audio Widget, and I use your project source code as a great tutorial.

I'm looking forward to you opening the source code for views and edits, preferably alongside device schematics. The port I'd like the most to see would be one for the NXP crossover processors.
 
At the current stage, I'm just trying to get the Win10 UAC2 driver to send packets with the size required in explicit feedback. I have tried FS and HS modes but so far I have not succeeded. I decided that the Win10 UAC2 driver does not support explicit feedback, but they write, that "For the asynchronous OUT case the driver supports explicit feedback only."

UAC1 and UAC2 work with one OUT endpoint for playback and one IN endpoint for feedback. I have tested this extensively on multiple OSes, including Win10-64 and Win10-32.

However, all the tests have defaulted to HS, so I don't know much about FS performance and code validity. 
 
In my HS test the UAC2 driver persistently sends 44 samples in every micro-frame, except for every 40th in which it sends 48 samples. As if there is no feedback at all. Although every 1 ms is sent 4 bytes of feedback, such as 0x002C1BAB or similar, since the actual frequency of the DAC is 44.108073 kHz.
For the FS mode the UAC2 driver always sends 176 samples in every 1ms frame, except for every 10th in which it sends 180 samples. My feedback value is 0x000B06EA or similar, sent each 1ms.

The feedback value is supposedly the DAC's current sample rate. In reality we use it to make the Host speed up or slow down. I'm sure you have seen the state machine in uacX_device_audio_task.c 

Your system obviously uses different sample rates in UAC1 (44.1 ksps) and UAC2 (176.4 ksps). 180 samples x 4 bytes x 2 channels is 1440 bytes. That is quite a lot for an endpoint buffer. You may want to check if the buffer can hold that. 

To get a ballpark feeling for your 0x000B06EA feedback value, I copied it into excel, did a hex2dec() and then divided the decimal number by 2 a number of times. After 12 right-shifts I got to 176.4321289. Similarly, 0x002C1BAB takes 16 right-shifts to become 44.108078. I don't remember off the top of my head if that is the correct number of right-shifts in the two modes. 
 
I am totaly confused. Could you please view the attached descriptor files, maybe some inconsistency will be evident.

Descriptor parsing is a hassle. I often hire people to do it. Let me know if you'd want the contact details. Before looking at the descriptors I'd suggest implementing feedback with static frequency data in order to check if that information is correctly received by the host. And I'd check the amount of data stuffed into each packet.

Linux has a good reporting feature for how a DAC actually responds. Off the top of my head I don't remember the Linux DAC status file which you can cat repeatedly to see which sample rate the DAC reports. My Linux machine is tucked away at the moment. 
 
I have a few questions more:
1. The bmChannelConfig in the AC Input Terminal Descriptor and AS Interface Descriptor in your project are not defined (equal to 0). Is this intentional?

Haven't thought much about it. Have you checked with USB.org's Audio2.0_final.zip UAC2 specification?
 
2. Is there a need for a Device Qualifier Descriptor and Other Speed Configuration Descriptor for UAC2? I ask this question because I noticed that the Other Speed Configuration Descriptor for FS is the same as the Configuration Descriptor for HS, which, in my opinion, is not quite true.

To be honest I haven't worked much with FS vs HS. I've been putting it off until I got FS test gear.
 
3. Have you tried the device (UAC2, FS and HS, explicit feedback) with Win10 x64? The latest version of usbaudio2.sys is 10.0.17763.1 Dec 15 2018.

Yes, it works very well. It's picky when it comes to sample rate triplets. You need one triplet for each frequency, no ranges. The Win10 device driver is a huge thing. It is frequently discussed at wdmau...@freelists.org. There is an ASIO driver for the Audio Widget which implements a subset of UAC in libusbK for Win7. Seriously, there shouldn't be a need for you to go into driver land. If you need the Host's view of the details, I'd suggest a USB debugger first, Linux kernel next, and Windows kernel if all else fails. But avoid it all if you can!


Børge

AlemV

unread,
Jan 20, 2019, 9:58:24 AM1/20/19
to Audio-Widget
Hi Børge,

I'm looking forward to you opening the source code for views and edits, preferably alongside device schematics.

Nothing special about schematics. It's just STM32F7 Cortex-M7 open board connected to the external HS PHY module and cheap I2S DAC board.
 
The feedback value is supposedly the DAC's current sample rate. In reality we use it to make the Host speed up or slow down. I'm sure you have seen the state machine in uacX_device_audio_task.c 

Yes, I understand. I count the DAC master clock per 32 SOFs in the firmware, so the feedback value is count more or less correct.
 

Your system obviously uses different sample rates in UAC1 (44.1 ksps) and UAC2 (176.4 ksps). 180 samples x 4 bytes x 2 channels is 1440 bytes. That is quite a lot for an endpoint buffer. You may want to check if the buffer can hold that. 

Here, of course, I confused samples with bytes.

Linux has a good reporting feature for how a DAC actually responds. Off the top of my head I don't remember the Linux DAC status file which you can cat repeatedly to see which sample rate the DAC reports. My Linux machine is tucked away at the moment. 

Thank you for your advice. Testing with Linux is much more productive.
Linux, unlike Windows, correctly reacts to the feedback value and correctly changes the number of audio samples in the USB frame. For example, for HS:

root@nanopineo:~# cat /proc/asound/card1/stream0
Open source USB stack for STM32 UAC2 I2S-DAC demo at usb-1c1d000.usb-1, high sp : USB Audio

Playback:
 
Status: Running
   
Interface = 1
   
Altset = 1
   
Packet Size = 48
   
Momentary freq = 44108 Hz (0x5.8376)
   
Feedback Format = 16.16
 
Interface 1
   
Altset 1
   
Format: S16_LE
   
Channels: 2
   
Endpoint: 1 OUT (ASYNC)
   
Rates: 44100
   
Data packet interval: 250 us


 
I have a few questions more:
1. The bmChannelConfig in the AC Input Terminal Descriptor and AS Interface Descriptor in your project are not defined (equal to 0). Is this intentional?

Haven't thought much about it. Have you checked with USB.org's Audio2.0_final.zip UAC2 specification?

Yes. It tells:
4.1 Audio Channel Cluster Descriptor
...
The audio channel cluster descriptor contains the following fields:
...
bmChannelConfig: a bitmap field that indicates which spatial locations are occupied by the channels
present
in the cluster. The bit allocations are as follows:
D0: Front Left - FL
D1: Front Right - FR
...

4.7.2.4 Input Terminal Descriptor
...
The bNrChannels, bmChannelConfig and iChannelNames fields together constitute the cluster descriptor. They characterize the cluster that leaves the Input Terminal over the single Output Pin
(‘downstream connection). For a detailed description of the cluster descriptor, see Section 4.1, Audio Channel Cluster Descriptor”.

etc.


3. Have you tried the device (UAC2, FS and HS, explicit feedback) with Win10 x64? The latest version of usbaudio2.sys is 10.0.17763.1 Dec 15 2018.

Yes, it works very well. It's picky when it comes to sample rate triplets. You need one triplet for each frequency, no ranges. The Win10 device driver is a huge thing. It is frequently discussed at wdmau...@freelists.org. There is an ASIO driver for the Audio Widget which implements a subset of UAC in libusbK for Win7. Seriously, there shouldn't be a need for you to go into driver land. If you need the Host's view of the details, I'd suggest a USB debugger first, Linux kernel next, and Windows kernel if all else fails. But avoid it all if you can!

Thank you, I will continue to "fight" with Windows. With Linux, everything is ok now.

Vladimir

Børge Strand-Bergesen

unread,
Jan 20, 2019, 10:10:30 AM1/20/19
to audio-...@googlegroups.com
Hi Vladimir, 

There was a discovery way before my time that Windows need to se a difference in feedback value of at least +-64 in order to relate to it. I don't know if that is still the case, but the Audio Widget state machine uses that. 

Also, the poll rate of the feedback EP needs to be 1ms for Windows to consider it. The different OSes respond non-linearly to feedback EP poll rate.

Both of these issues may be resolved in various OSes now, I don't know. But their fixes linger in AW code.


Best,
Børge



--

AlemV

unread,
Jan 23, 2019, 1:20:30 AM1/23/19
to Audio-Widget
Hi Børge,

Thanks to this article, I was finally able to read the Windows driver log. After analyzing it, I can report that Windows 10 UAC2 driver usbaudio2.sys 10.0.17763.1 Dec 15 2018 has the following requirements:
Valid feedback format
16.16 if bInterval of Async OUT endpoint = 1 (FS/HS)
17.13 if bInterval of Async OUT endpoint = 2 (HS)
Valid feedback interval
44100 Hz - 0x000B0000, 0x000C0000
48000 Hz - 0x000B0000, 0x000D0000
88200 Hz - 0x00160000, 0x00170000
96000 Hz - 0x00170000, 0x00190000
176400 Hz - 0x002C0000, 0x002D0000
192000 Hz - 0x002F0000, 0x00310000
The Linux driver is more flexible, so for a universal firmware, Windows requirements are decisive.

There was a discovery way before my time that Windows need to se a difference in feedback value of at least +-64 in order to relate to it. I don't know if that is still the case, but the Audio Widget state machine uses that. 

I tried using different values within the valid feedback interval and it worked.
 
Also, the poll rate of the feedback EP needs to be 1ms for Windows to consider it. The different OSes respond non-linearly to feedback EP poll rate.

I agree with you, 1 ms is the best interval for HS.
 
It will take me a few more weeks to polish the code and create new examples for uac2-adc, after the end I can post a link to the source code here, if you are, of course, still interested.

Thanks for your help
and the best regards,
Vladimir Alemasov

Børge Strand-Bergesen

unread,
Jan 23, 2019, 11:31:14 AM1/23/19
to audio-...@googlegroups.com
Hi Vladimir,

I was not aware of the article or the limits. Thanks!

Please share your code when you are ready.

Best,
Børge
--
You received this message because you are subscribed to the Google Groups "Audio-Widget" group.
To unsubscribe from this group and stop receiving emails from it, send an email to audio-widget+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages