UAC Feedback端点
下面转一段对USB feedback的理解:
这段时间一直在做USB Audio Device(UAC)设备的开发工作。由于UAC采用的是isochronous endpoint来传输数据,对时钟的要求较高。但无奈我们的嵌入式平台的时钟并不准,数据同步就成了问题。经过研究,发现只能使用异步模式来解决这个问题。
所谓异步模式,就是建立一个feedback endpoint在一个固定的时间间隔反馈本地时钟给host, 从而使得host端能够实时的了解client端的时钟变化,调节数据包的长度,从而避免接收或者发送缓冲溢出。
USB 2.0 spec在5.12.4.2中明确的定义了如何提供feedback给host, 个人觉得写得有点复杂,特总结如下:
- Feedback endpoint数据长度为3字节,发送间隔由bRefresh决定。
- Fm = Fs * 2^P, Fm是本地的时钟频率,Fs是采样频率。
- Tmeas=2^K/2^P=2^(K-P), Tmeas是测量时间, 对于full speed, K= 10, 对于high speed, K=13
- 在每Tmeasframe/subframe时间间隔,把本地的clock数写入feedback endpoint。
上面的一大段看起来很复杂,其实基本的思想很简单。不就是时钟不同步嘛,要想让大家同步,怎么办呢?比如说采样率是48000,如果时钟同步,那么1s的时间内,就应该有48000个sample。如果不同步,那么就测量1s, 把1s内的实际sample数返回给host端就可以了。上面的公式实际要表达的就是这个意思。至于要注意的是返回的格式,spec上面说是对于full speed, 数据格式是10.14,对于high speed, 数据格式是16.16。如果你的UAC设备是1.0 version,那么就算是你把它定义成一个high speed的设备,返回数据格式还是10.14的。
例如:
48000 采样率 –> feedback (48 * 2^14) = 0xc0000
47000 采样率 –> feedback (47 * 2^14) = 0xbc000
计算10.14格式采样率代码(audio 1.0)
这里反馈端点反馈的数据是3个字节的。
/*该设备为:44.1K采样率,10.14格式*/
uint8_t audioFeedBackBuffer[4] = {0x40,0x06,0x0b};
void SetFeedBackSampleRate(uint32_t Rata)
{
Rata = ((Rata / 1000) << 14) | ((Rata % 1000) << 4);
audioFeedBackBuffer[0] = Rata;
audioFeedBackBuffer[1] = Rata>>8;
audioFeedBackBuffer[2] = Rata>>16;
}
计算16.16格式采样率代码(audio 2.0)
这部分代码是 通过USB声卡反推出来的,实测可以用。感觉跟USB2.0规范描述不一样。
这里反馈端点反馈的数据是4个字节的。
uint8_t audioFeedBackBuffer[4];
void SetFeedBackSampleRate(uint32_t Rata)
{
Rata = ((Rata / 1000) << 13) | ((Rata % 1000) << 3);
audioFeedBackBuffer[0] = Rata;
audioFeedBackBuffer[1] = Rata>>8;
audioFeedBackBuffer[2] = Rata>>16;
audioFeedBackBuffer[4] = Rata>>24;
}
相关链接:
https://blog.csdn.net/huangkangying/article/details/53152956
https://zhuanlan.zhihu.com/p/166661061