Summary: You will implement band-pass finite impulse-response (FIR) filters with time-domain processing.
filter.asm1 .copy "core.asm" ; Copy in core file 2 ; This initializes DSP and jumps to "main" 3 4 FIR_len .set 8 ; This is an 8-tap filter. 5 6 .sect ".data" ; Flag following as data declarations 7 8 .align 16 ; Align to a multiple of 16 9 coef ; assign label "coeff" 10 .copy "coef.asm" ; Copy in coefficients 11 12 .align 16 13 firstate 14 .space 16*8 ; Allocate 8 words of storage for 15 ; filter state. 16 17 .sect ".text" ; Flag the following as program code 18 main 19 ; Initialize various pointers 20 stm #FIR_len,BK ; initialize circular buffer length 21 stm #coef,AR2 ; initialize coefficient pointer 22 stm #firstate,AR3 ; initialize state pointer 23 stm #1,AR0 ; initialize AR0 for pointer increment 24 25 loop 26 ; Wait for a new block of 64 samples to come in 27 WAITDATA 28 29 ; BlockLen = the number of samples that come from WAITDATA (64) 30 stm #BlockLen-1, BRC ; Put repeat count into repeat counter 31 rptb endblock-1 ; Repeat between here and 'endblock' 32 33 ld *AR6,16, A ; Receive ch1 into A accumulator 34 mar *+AR6(2) ; Rcv data is in every other channel 35 ld *AR6,16, B ; Receive ch2 into B accumulator 36 mar *+AR6(2) ; Rcv data is in every other channel 37 38 ld A,B ; Transfer A into B for safekeeping 39 40 ; The following code executes a single FIR filter. 41 42 sth A,*AR3+% ; store current input into state buffer 43 rptz A,(FIR_len-1) ; clear A and repeat 44 mac *AR2+0%,*AR3+0%,A ; multiply coef. by state & accumulate 45 46 rnd A ; Round off value in 'A' to 16 bits 47 48 ; end of FIR filter code. Output is in the high part of 'A.' 49 50 sth A, *AR7+ ; Store filter output (from A) into ch1 51 sth B, *AR7+ ; Store saved input (from B) into ch2 52 53 sth B, *AR7+ ; Store saved input to ch3...ch6 also 54 sth B, *AR7+ ; ch4 55 sth B, *AR7+ ; ch5 56 sth B, *AR7+ ; ch6 57 58 endblock: 59 b loop Figure 1 |
filter.asm 将从输入通道1送来的信号用FIR滤波器处理后将结果送至输出通道1,并将原始信号送至输出通道2。
remez 命令来产生滤波器;你可以键入
help remez 来获取帮助信息。用
save_coef 命令将所产生的滤波器存为不同的文件。(注意在保存之前要将滤波器参数矢量倒置。)同时将你的滤波器存为MATLAB矩阵,以后生成检测矢量时需要用到。这些可以用MATLAB命令
save 来完成。在完成这些操作后,用
freqz 命令来显示每个滤波器的频率响应。
filter.asm 来将该滤波器所需使用的参数加入到程序代码中。
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。在这个拷贝的基础上开始该部分练习,上一部分中的滤波器以后还要用到,不要作任何修改。
.align 和 .copy
指令将第二套参数载入到数据内存中。你还需要生成一个指向第二套参数的指针并进行第二个滤波器的有关运算。
AR4 和
AR5 而实现双通道系统吗?为什么用这样的方法做会更困难?注意不能通过用 .asg 指令将
AR4 和 AR5 改名的方法来实现。
firs 指令时参数是被载入程序内存(program memory)而非数据内存(data memory);(2) firs 要求状态(state)被分开并分别存在两个循环缓存中。关于 firs 的详细用法请参阅 Mnemonic
Instruction Set 手册的 4-59页 以及位于 Applications
Guide
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