上一篇:《为 SensorTile 工程引入 DSP 库》
虽然 SensorTile 拥有 FPU 加速浮点运算,但由于传感器输出的数据不是浮点数,我还是作死地想用 DSP 的定点数试一试。
定点数有许多种标准。CMSIS-DSP 库使用的定点数类型为 Q 型(也叫 Qm.n),这是一个
很方便能够直接用于传感器数据的定点数类型。网络上资料不好找,但是在 Wikipedia 也有一些信息:
Q (number format)
Q7, Q15, Q31 ……都是什么玩意儿?
Qm.n 表示一个占用 (m+n) 比特的Q型定点数。
简单地理解就是 Qm.n 能够告诉 DSP 库这个整数和实际数值之间的比值:2 的 n 次方。如果 m=1 可以简写为 Qn,比如 Q1.15 可以简写为 Q15,但是它占用的还是 16bits,也就是2字节。因此,很多地方采用 (signed) short 来表示 Q15,因为只需要除以一个常数(见下文),就可以得到对应的浮点数了,超方便。
在 CMSIS-DSP 常用的是 Q15,Q31等等,分别表示除以 32768,除以 2147483648 就可以得到实际的浮点数。
反之,乘以这个倍数,然后取整,就可以得到 Q15、Q31格式的表示。
Q型定点数的取值范围
这就引入了一个问题:数值范围。大家都知道一个 signed short 范围是 –32,768 到 32,767,除以那个比例关系(32768),则可得知:一个 Q15 表示的实数范围是 [-1, 1.99997]
如果遇到 FFT 这种一言不合就10的N次方数量级的算法, Q15 表示范围太小显然不够使用!!那么怎么办?
不要忘记 Q15 只是 Q1.15 的简写。我们还有:
- Q2.14,比例系数16384,表示范围大约是 [-2, 2)
- Q3.13,比例系数8192,表示范围大约是 [-4, 4)
- Q4.12,比例系数4096,表示范围大约是 [-8, 8)
- Q5.11,比例系数2048,表示范围大约是 [-16, 16)
- ……
因此,有一个很重要的坑就是:
在 CMSIS-DSP 库的定点数 FFT 中,你输入一堆 Q15 的数据,出来的数据格式不是 Q15,而且还和数据长度有关系!
以下是定点数 FFT 的输入-输出数据格式对照表,要点是前三列。第四列表示比例系数被缩小了 2 的多少次方倍:
iFFT 运算也会变类型(虽然感觉这个表格有点问题)……这是在定点数的游戏规则下不得已的办法。
在CMSIS-DSP中与浮点数型互相转换
前面第二节已经说过如何与浮点数互相转换了:除以/乘以比例系数即可。简单地手写一个循环即可。如果想要偷懒, CMSIS-DSP 也有对应的函数,比如:
arm_float_to_q31(float *src, short *dst, int count) 可以转换浮点数组为 Q31 数组。
更多偷懒函数可以在
https://www.keil.com/pack/doc/CMSIS/DSP/html/group__groupSupport.html 查到。