usb audio --异步反馈的实现(3)

来源:互联网 发布:让其响彻 动作数据 编辑:程序博客网 时间:2024/06/02 02:32

Usb device固件中异步传输支持实现:

固件算法基于stm32f407平台,参考了ST官方的usb audio demo,但原始工程使用的是基于SOF的同步方式,需要更改。
源代码Github链接(基于MDK工程): https://github.com/zizimumu/usb_audio

反馈值:

反馈值可以是device端实际的播放速率,如48K的音频文件,实际播放速率为47K。也可以根据device端实际算法需求更改成虚假播放速率,但无论哪种方法,前提是反馈机制保证device buff数据的稳定性为目的,即buff中的数据不能出现over run 和 under run 的情况。
实际算法中为了保证host 端数据快速响应,反馈的是虚拟播放速率。

这里写图片描述

反馈算法实现:

硬件平台数据流向如上图。假定DMA buff总空间100KB, 定义可用空间是即DMA读指针到USB写指针的距离,定义可用空间50KB时为临界点,定义Low thresholk 与High threshold为可用空间平衡区间看,如下图。这里写图片描述

当buff可用空间(注意: 可用空间是相对DMA读指针而言)在 Low threshold 与 High threshold之间时反馈值固定为usb device预设定值播放速;

如果可用空间超过 High threshold,说明数据写入过快(或者数据读取过慢),device反馈值与预设定值小,usb host会减少数据发送量,device端buff可用空间会慢慢减少,直到可用空间范围在 low threshold 与 50K之间,这时将反馈值恢复正常,即设定为预设定播放速率。

当可用空间低于Low threshold,device反馈值比预设定值大,usb host会增大数据发送量,device端buff可用空间会慢慢增加,直到可用空间范围在 HIgh threshold 与 50K之间,这时将反馈值恢复正常,即设定为预设定播放速率。

反馈值范围:

反馈的播放速率是有范围限制的,过大或者过小host 端的usb driver都会认为反馈值不合理而直接丢弃掉。Linux usb audio驱动中freq反馈值的范围为 min <= freq <= max,其中
Min = normal - normal/8
Max = mormal + normal /4
关于max值与同步OUT端点的最大包长度是有关联的,比如对于2 channel ,16bit,48K 模式下,如果同步out端点最大包长度为192,那么意味值每个微帧内最多传输 192B数据,即48 frames 音频文件,即最大播放速率为48K,此时Max=48K;当包最大长度为256时就不会有这样的限制了。

反馈值格式:

反馈值占用3Byte数据,对于usb full speed设备,反馈值格式为 10:14,对于high speed 设备,格式为16:16。
比如48123Hz,在full speed 设备上,转换成反馈值为: ((48123/1000)<<14) | ((48123%1000)<<4)

实际效果:

加入反馈后可用空间的曲线图如下(在linux主机下测试得到),device 预设定播放速率为48K,由于device内部I2S时钟生成器的关系,实际的播放速率要比48K要小一点,也就意味着dma读取的速度小于usb数据写入速率,因此可以看到,刚开始时,可用空间是不断增加的,直到增大到High Threshold点,device反馈最大播放速率60K(非实际播放速率),可以看到,这个最大播放速率的反馈值效果是很显著的: 可用空间基本上是直线掉到DMA BUFF/2与 Low Threshold之间的位置。

这里写图片描述

原创粉丝点击