Based on: FIR Filtering: Exercise for TI TMS320C54x by Douglas L. Jones, Swaroop Appadwedula, Matthew Berry, Mark Haun, Jake Janovetz, Michael Kramer, Dima Moussa, Daniel Sachs, Brian Wade
Summary: You will implement band-pass finite impulse-response (FIR) filters with time-domain processing.
在本练习中,你将用DSP汇编语言来完成一个FIR(有限脉冲相应)滤波器。在开始之前,先来学习一 个基本的FIR滤波器汇编代码 filter.asm.
| filter.asm |
|---|
|
filter.asm 将从输入通道1送来的信号用FIR滤波器处理后将结果送至输出通道1,并将原始信号送至输出通道2。
首先,在你的网络驱动器上创建一个工作目录来存放练习所需使用的文件,并将 filter.asm
和 core.asm
拷贝到该目录下。然后用MATLAB来产生两个20参数的FIR滤波器。第一个滤波器用以通过 4 kHz 和 8 kHz 之间的频段;第二个滤波器用以通过 8 kHz 和 12 kHz 之间的频段。两个滤波器频段边缘的过渡范围(transition band)都为1kHz。为生成滤波器,首先将频段边缘转化成基于系统 44.1 kHz 采样率的数字频率(digital frequencies),然后用MATLAB的
remez 命令来产生滤波器;你可以键入
help remez 来获取帮助信息。用
save_coef 命令将所产生的滤波器存为不同的文件。(注意在保存之前要将滤波器参数矢量倒置。)同时将你的滤波器存为MATLAB矩阵,以后生成检测矢量时需要用到。这些可以用MATLAB命令
save 来完成。在完成这些操作后,用
freqz 命令来显示每个滤波器的频率响应。
现在来实现通频带为 4 kHz 到 8 kHz 的滤波器。你需要编辑 filter.asm 来将该滤波器所需使用的参数加入到程序代码中。
首先,本练习中FIR滤波器的长度是20而不是8。所以你需要将 FIR_len 改为20。使用 .set 指令来给符号名 FIR_len 分配一个数值。相应的改变为 FIR_len .set 20。
其次,你要确认 .copy
指令正确地将相应的的参数拷贝到程序代码中。将指示滤波器参数的文件名改为相应的实际包含参数的文件的名字。
最后,你要对 .align 和
.space 指令作相应的调整。TI TMS320C54x DSP要求存放寄存器参数和状态的循环缓存(circular buffers)的起始地址是一个大于缓存长度的2的幂的整数倍。由于你现在所使用的是20参数的滤波器(相应的状态及参数缓存长度也为20),大于该数值的最小的2的幂的整数倍为32。所以你要将状态缓存和参数缓存的地址都设为32的倍数。(16元素缓存(16-element buffers)也要求地址为32的整数倍。)该操作可通过 .align 命令来实现。此外,要为状态缓存保留相应的内存空间。该操作可通过 .space 命令来实现,输入值为所要分配空间的位( bits )数。因此,要为20参数的滤波器分配空间应使用指令 .space 16*20,如下所示:
1 .align 32 % Align to a multiple of 32
2 coef .copy "filter1.asm" % Copy FIR filter coefficients
3
4 .align 32 % Align to a multiple of 32
5 state .space 16*20 % Allocate 20 words of data space
汇编你的代码,将 PMST 设为
0xFFE0,将DSP复位(reset),然后运行。确认所得到的频率响应正确。在确信该程序代码工作正常后,进入下一步骤。
首先,拷贝一份在 第一部分 中修改过的文件 filter.asm。在这个拷贝的基础上开始该部分练习,上一部分中的滤波器以后还要用到,不要作任何修改。
接下来,修改代码,使程序除了将经第一个滤波器(通频带 4 kHz 到 8 kHz)处理的结果送到输出通道1以及将未经滤波处理的信号送出通道2外,还将经第二个滤波器(通频带 8 kHz 到 12 kHz)处理的结果送到输出通道3。为此,你需要用 .align 和 .copy
指令将第二套参数载入到数据内存中。你还需要生成一个指向第二套参数的指针并进行第二个滤波器的有关运算。
你能不使用辅助寄存器 AR4 和
AR5 而实现双通道系统吗?为什么用这样的方法做会更困难?注意不能通过用 .asg 指令将
AR4 和 AR5 改名的方法来实现。
使用 DSP Development Environment: Introductory Exercise for TI TMS320C54x 中介绍的方法在MATLAB中产生一个合适的检测矢量和预期输出。然后使用 DSP Development Environment: Introductory Exercise for TI TMS320C54x 中介绍的检测矢量核心文件来找出在给定该检测矢量时的系统输出。在MATLAB中画出两个滤波器的预期输出和实际输出以及它们之间的差别。为什么DSP系统的输出和MATLAB的输出会有不同?
通过使用 firs 指令可通过另一途径实现单通道滤波器。修改 第一部分 中的代码,用
firs 来实现通频带为 4 kHz 到 8 kHz 的滤波器。
第一部分 中的代码和现在你将要写的代码之间有两个区别:(1)使用 firs 指令时参数是被载入程序内存(program memory)而非数据内存(data memory);(2) firs 要求状态(state)被分开并分别存在两个循环缓存中。关于 firs 的详细用法请参阅 Mnemonic
Instruction Set [link] 手册的 4-59页 以及位于 Applications
Guide [link]
4-5 至 4-8 页 中有关的描述和示例(分别是TMS320C54x DSP Reference
Set 的 Volume 2 和 Volume 4)。
AR0 需要设置成-1才能确保该代码正常工作。为什么?
COEFF 用于标示位于程序内存中的参数。请参阅关于
firs 的描述。
1 mvdd *AR2,*AR3+0% ; write x(-N/2) over x(-N)
2 sth A,*AR2 ; write x(0) over x(-N/2)
3 add *AR2+0%,*AR3+0%,A ; add x(0) and x(-(N-1))
4 ; (prepare for first multiply)
5
6 rptz B,#(FIR_len/2-1)
7 firs *AR2+0%,*AR3+0%,COEFF
8 mar ??????? ; Fill in these two instructions
9 mar ??????? ; They modify AR2 and AR3.
10
11 ; note that the result is now in the
12 ; B accumulator
由于现在使用了与前面不同的方法来处理状态和参数,你需要对指针的初始化作如下修改:
1 stm #(FIR_len/2),BK ; initialize circular buffer length
2 stm #firstate_,AR2 ; initialize location containing first
3 ; half of states
4
5 stm #-1,AR0 ; Initialize AR0 to -1
6
7 stm #firstate2_,AR3 ; initialize location containing last half
使用检测矢量核心文件来找到该系统在给定与前面所使用的相同的检测矢量时的输出。比较该代码的输出和使用mac指令的同一滤波器的输出。它们是否一致?原因是什么?确认滤波器的输出被送到输出通道1,而未经处理的信号仍被送到输出通道2。