Summary: You will implement band-pass finite impulse-response (FIR) filters with time-domain processing.
filtercode.asm.ARMS_off ;enable assembler for ARMS=0 .CPL_on ;enable assembler for CPL=1 .mmregs ;enable mem mapped register names .global _filter .global _inPtr .global _outPtr .copy "macro.asm" ; Copy in macro declaration .sect ".data" FIR_len1 .set 8 ; This is a 8-tap filter .align 32 ; Align to a multiple of 16 coef1 ; assign label "coef1" .copy "coef.asm" ; Copy in coefficients .align 32 firState1 .space 16*FIR_len1 ; Allocate 8 words of storage for ; filter state. firState1Index ; Allocate storage to save index .word 0 ; in firState .copy "testvect.asm" .sect ".text2" _filter ENTER_ASM ; Call macro. Prepares registers for assembly MOV #0, AC0 ; Clears AC0 and XAR3 MOV AC0, XAR3 ; XAR3 needs to be cleared due to a bug MOV dbl (*(#_inPtr)), XAR6 ; XAR6 contains address to input MOV dbl (*(#_outPtr)), XAR7 ; AR7 contains address to output BSET AR2LC ; sets circular addressing for AR2 MOV #firState1, AR2 ; State pointer is in AR2 MOV #firState1Index, AR4 ; State index pointer is in AR4 MOV mmap(AR2), BSA23 ; BSA23 contains address of firState1 MOV *AR4, AR2 ; AR2 contains the index of oldest state MOV #coef1, AR1 ; initialize coefficient pointer MOV #FIR_len1, BK03 ; initialize circular buffer length for register 0-3 MOV *AR6+ << #16, AC0 ; Receive ch1 into AC0 accumulator MOV AC0, AC1 ; Transfer AC0 into AC1 for safekeeping MOV HI(AC0), *AR2+ ; store current input into state buffer MOV #0, AC0 ; Clear AC0 RPT #FIR_len1-1 ; Repeat next instruction FIR_len1 times MACM *AR1+,*AR2+,AC0,AC0 ; multiply coef. by state & accumulate round AC0 ; Round off value in 'AC0' to 16 bits MOV HI(AC0), *AR7+ ; Store filter output (from AC0) into ch1 MOV HI(AC1), *AR7+ ; Store saved input (from AC1) into ch2 MOV HI(AC0), *AR7+ MOV HI(AC1), *AR7+ MOV AR2, *AR4 ; Save the index of the latest state back into firState1Index LEAVE_ASM ; Call macro to restore registers RET Figure 1 |
filtercode.asm applies an FIR filter to the signal
from input channel 1 and sends the resulting output to output
channel 1. It also sends the original signal to output
channel 2.
v:\ece420\55x\filter to your work directory. Then, use MATLAB
to generate two 20-tap FIR filters. The first filter should
pass signals from 4 kHz to 8 kHz; the second filter should
pass from 8 kHz to 12 kHz. For both filters, allow a 1 kHz
transition band on each edge of the filter passband. To
create these filters, first convert these band edges to
digital frequencies based on the 48 kHz sample rate of the
system, then use the MATLAB command firpm to
generate this filter; you can type help firpm for
more information. Use the save_coef command to
save each of these filters into different files. (Make sure
you reverse the vectors of filter coefficients before you save
them.) Also save your filters as a MATLAB matrix, since you
will need them later to generate test vectors. This can be
done using the MATLAB save command. Once this is
done, use the freqz command to plot the frequency
response of each filter.
filtercode.asm to use the
coefficients for this filter by making several changes.
FIR_len1 to
20. FIR_len1 is set using the .set
directive, which assigns a number to a symbolic name. You will
need to change this to FIR_len1 .set 20.
.copy
directive brings in the correct coefficients. Change the
filename to point to the file that contains the coefficients
for your first filter.
.align and
.space directives appropriately. The TI
TMS320C55x DSP requires that circular buffers, which are used
for the FIR filter coefficient and state buffers, be aligned
so that they begin at an address that is a multiple of a power
of two greater than the length of the buffer. Since you are
using a 20-tap filter (which uses 20-element state and
coefficient buffers), the next greater power of two is 32.
Therefore, you will need to align both the state and
coefficient buffers to an address that is a multiple of 32.
(16-element buffers would also require alignment to a multiple
of 32.) This is done with the .align command. In
addition, memory must be reserved for the state buffer. This
is done using the .space directive, which takes
as its input the number of bits of space
to allocate. Therefore, to allocate 20 words of storage, use
the directive .space 16*20 as shown below:
1 .align 32 % Align to a multiple of 32
2 coef1 .copy "coef1.asm" % Copy FIR filter coefficients
3
4 .align 32 % Align to a multiple of 32
5 firState1 .space 16*20 % Allocate 20 words of data space
filtercode.asm
file from Part 1. Work from this
copy; do not modify your working filter from the previous
part. You will use that code again later.
.align and .copy
directives to load the second set of coefficients into data
memory. You will also need to add instructions to initialize
a pointer to the second set of coefficients and to perform the
calculations for the second filter.
AR4 and
AR5? Why is this more difficult? Renaming
AR4 and AR5 using the
.asg directive does not count!
firsadd instruction. Modify
your code from Part 1 to implement
the filter with a 4 kHz to 8 kHz passband using the
firsadd.
firsadd requires the states
to be broken up into two separate circular buffers. Refer to
the firsadd instruction on page 5-152 in
the Mnemonic
Instruction Set manual.
1 mov *AR1, *AR2- ; write x(-N/2) over x(-N)
2 mov HI(AC0), *AR1 ; write x(0) over x(-N/2)
3 add *AR1-, *AR2-, AC0 ; add x(0) and x(-(N-1))
4 ; (prepare for first multiply)
5 rpt #(FIR_len1/2-1)
6 firsadd *AR1-, *AR2-, *CDP+, AC0, AC1
7 round AC1
8 amar ???????????????? ; Fill in these two instructions
9 amar ????? ; They modify AR1 and AR2
10
11 ; note that the result is now in the
12 ; AC1 accumulator
1 bset AR1LC ; sets circular addressing for AR1
2 bset AR2LC ; sets circular addressing for AR2
3
4
5 mov #firState1, AR1
6 mov #firState1Index, AR4
7 mov mmap(AR1), BSA01
8 mov *AR4, AR1 ; get pointer to oldest delayBuf in AR1
9
10 mov #firState2, AR2
11 mov #firState2Index, AR5
12 mov mmap(AR2), BSA23
13 mov *AR5, AR2
14
15
16 mov #(FIR_len1/2), BKC
17 mov #(FIR_len1/2), BK03 ; initialize circular buffer length for register 0-3
18 mov #coef1, CDP ; CDP contains address of coefficients
19 mov *AR6 << #16, AC0 ; copy input into AC0
firsadd instruction works to make the necessary changes. Hint: Make sure accumulator usage (AC0, AC1, AC2) and what is sent to output is correct.mac instruction. Are the results the same? Why or
why not? Ensure that the filtered output is sent to output
channel 1, and that the unmodified output is still sent to
output channel 2..asm file ready to
demonstrate each. Of the 4 points, you get 0.5 points for a
single 20-tap filter, 2 points for the two-filter system,
and 1.5 points for the system using the firs
opcode.Comments, questions, feedback, criticisms?