用SP061A实现心电数据的FFT与压缩
3 FFT变换及低通滤波
FFT将时域序列{χ[i],i∈0…2N}变换为频域序列{F[i],i∈0…2N}。为了实现低通滤波,仅须保留{F[i]}中≤75Hz的频率分量。当N=9时,应保留{F[i]}中的前77个低频分量;当N=10时,则应保留{F[i]}中的前154个低频分量。这也同时减少了计算量,加快了计算速度;存放周转量所需的片内RAM也能得到保证。
为叙述简便,以N=3为例,研究FFT的计算结构,如图3所示。
图3中,W[k]是复因子,W[k]=COS[(2kπ)/N ]+jsin[(2kπ)/N],k=0…2N-1。将W[k]的实部和虚部都乘2 14,取整后制成表,存于FLASH ROM中,供程序查表获得其值;而W[k]与某数相乘,将32位运算结果右移14位作为积。这就使全部运算为整数运算,适应SP061A的硬件乘法功能。
由图3知,第一层的计算仅涉及实部加减,虚部保持为0,可单独进行。从第二层开始有复数乘,但是,当只需计算{F[i]}中的低频分量时,许多中间结果可不计算。例如,如果需计算出F[0]和F[1](即保留原始信号的直流分量和1次谐波),则仅需计算χ[0]3、χ[4]3和χ[1]、χ[5]3。计算层数N越多,减少的运算也越多。
图4
复数乘可利用SP061A的内积功能实现。例如,要计算χ[i]×W[j],设χ[i]×W[j]=(a+jb)×(c+jd)=ac+(-bd)+j(bc+ad)。显然,结果的实部和虚部均为内积形式,只是设置操作数时须注意符号和排列顺序。
上述方法使计算量显著减少。以512点FFT为例,计算出全部频率分量需要512×log2 512=4608次运算,其中含有2048次复数乘。若计算77个低频分量,则只有3611次运算,其中含有1767次复数乘。
当N=10时,计算点数达1024,片内RAM不够用。此时,应按1024点的整序次序取数,先对χ[0]1~χ[511]1,进行FFT,算出F1[0]~F1[153],暂存于片内RAM中的一个缓冲区;再对χ[512]1~χ[1023]1进行FFT,算出F2[0]~F2[153];则最终结果为:F[i]=Fl[i]+F2[i],i=0…153。
为避免计算中产生数据溢出,从第三层开始,对χ[i]4~χ[i]9都算术右移1位。操作的累积结果使F[i]缩小了64倍,故在重建时应扩大64倍。如此操作实际上降低了运算精度,但实验表明,重建的波形完全满足医学观察要求。
4 数据压缩
采取如下简易格式实现数据压缩:
对于F[0],因虚部为0,仅用一个字存放实部,重建时默认虚部为0;
对于F[i],i>0,若实部在—64~63范围内且虚部在—128~127范围内,则用2个字节存放,格式如下:
两种格式由第1字节的最高位区分。
5 实验结果与分析
用自行研发的心电信号采集器进行实验,对采集到的4个样本进行处理,实验结果如表1。表1中,PRD为均方根误差,CC为相关系数,计算公式为:
《用SP061A实现心电数据的FFT与压缩(第2页)》