📄 simd_fir_demo.asm
字号:
/* ///////////////////////////////////////////////////////////////////////////////////
/ FIR_Demo.asm 21161 EZ-KIT LITE SIMDFIR digital filter /
/ /
/ Receives input from the AD1836 A/D's via the 21161 serial port (SPORT1), /
/ Filters the data using a Finite Impuse Response Filter, and then stores the /
/ output for the SPORT1 ISR to transmit the data back to the AD1836 D/A's. /
/ /
/ The digital filter coefficients are in the files "high1.dat" and "low1.dat" /
/ /
/ The samples from the AD1836 are 24-bits and are are converted to /
/ floating point numbers. The values are also scaled to the range +/-1.0 /
/ with the integer to float conversion (f0 = float r0 by r1). /
/ /
/ The digital filtering takes place in the SPORT1 transmit interrupt service /
/ routine. /
/ /
/ See the "ADSP-21000 Family Applications Handbook Vol. 1" for more information /
/ regarding the implementation of digital filters (chapter 4) /
/ /
/ /
/////////////////////////////////////////////////////////////////////////////////// */
/* ADSP-21161 System Register bit definitions */
#include "def21161.h"
/* *** C preprocessor declarations (defines, includes, etc.) *** */
#define DOUBLE_FILTER_TAPS 130
#define FILTER_TAPS 65
.section /dm dm_data;
.VAR filter_counter = 0; /* default is low-pass filter */
.ALIGN 2;
.VAR dline [DOUBLE_FILTER_TAPS]; /* delay line of input samples */
/*---------------------------------------------------------------------------*/
.section /pm pm_data;
/* declare and initialize the interleaved lowpass & highpass filter coefficients*/
.ALIGN 2;
.VAR coef_lo[DOUBLE_FILTER_TAPS] = "interleaved_coeffsLP_300&600Hz.dat";
.ALIGN 2;
.VAR coef_hi[DOUBLE_FILTER_TAPS] = "interleaved_coeffsHP_4&8kHz.dat";
/* "interleaved_coeffsLP_300&600Hz.dat" contains the coefficients for a stereo/interleaved low pass filter and
"interleaved_coeffsHP_4&8kHz.dat" contains the coefficients for a stereo/interleaved high pass filter */
.section /pm pm_code;
.GLOBAL init_fir_filter;
.GLOBAL fir;
.GLOBAL change_filter_coeffs;
.EXTERN RX_left_flag;
.EXTERN Left_Channel_In1;
.EXTERN Right_Channel_In1;
.EXTERN Left_Channel_Out0;
.EXTERN Right_Channel_Out0;
.EXTERN Left_Channel_Out1;
.EXTERN Right_Channel_Out1;
init_fir_filter:
bit set mode1 CBUFEN ;
nop ;
/* initialize the DAGS */
b0 = dline; l0 = @dline; /* pointer to the samples (delay line) */
m1 = 2;
b9 = coef_lo; l9 = @coef_lo; /* pointer to the highpass filter coefficients */
m9 = 2 ;
i3=dline; l3=@dline; r12=r12 xor r12; /* clear the delay line */
bit set mode1 PEYEN ;
lcntr=FILTER_TAPS, do clear until lce;
clear: dm(i3,2)=f12;
bit clr mode1 PEYEN ;
rts;
init_fir_filter.end:
/* //////////////////////////////////////////////////////////////////////////////// *
* FIR filter subroutine *
* //////////////////////////////////////////////////////////////////////////////// */
fir:
/* process Left Channel Input */
r2 = -31; /* scale the sample to the range of +/-1.0 */
r0 = DM(Left_Channel_In1); /* get left input sample */
r1 = DM(Right_Channel_In1); /* get right input sample */
f0 = float r0 by r2 ; /* and convert to floating point */
f1 = float r1 by r2 ; /* and convert to floating point */
f8 = f0; /* in case we are in bypass mode, copy to output */
f9 = f1; /* in case we are in bypass mode, copy to output */
if FLAG2_IN jump exit_filter;
do_filtering:
dm(i0,m1)=f0 (LW);
// Enable broadcast mode and also set the PEYEN, disable I9 Broadcast Mode since we have interleaved coeffs
bit set mode1 PEYEN;
bit clr mode1 IRPTEN | BDCST9;
r12=r12 xor r12; /* clear f12,put sample in delay line */
f8=pass f12, f0=dm(i0,m1), f4=pm(i9,m9);/* clear f8,get data & coef */
lcntr=FILTER_TAPS-1, do macloop until lce;
macloop: f12=f0*f4, f8=f8+f12, f0=dm(i0,m1), f4=pm(i9,m9);
f12=f0*f4, f8=f8+f12; /* perform the last multiply */
f8=f8+f12; /* perform the last accumulate */
bit clr mode1 PEYEN | BDCST9;
bit set mode1 IRPTEN;
r9 = s8;
exit_filter:
r1 = 31; /* scale the result back up to MSBs */
r8 = fix f8 by r1; /* convert back to fixed point */
r9 = fix f9 by r1; /* Convert back to fixed point */
DM(Left_Channel_Out0) = r8; /* send result to AD1836 DACs */
DM(Right_Channel_Out0) = r9;
DM(Left_Channel_Out1) = r8; /* send result to AD1836 DACs */
DM(Right_Channel_Out1) = r9;
rts;
fir.end:
/* ------------------------------------------------------------------------------------ */
/* */
/* IRQ2 Pushbutton Interrupt Service Routine */
/* */
/* This routine determines which FIR filter routine to execute. */
/* Pressing the IRQ1 pushbutton will toggle between each filter. The default */
/* is a lowpass filter */
/* */
/* To listen to unfiltered signal, hit the FLAG 3 pushbutton */
/* ------------------------------------------------------------------------------------ */
change_filter_coeffs:
bit set mode1 SRRFH; /* enable background register file */
NOP; /* 1 CYCLE LATENCY FOR WRITING TO MODE1 REGISER!! */
r11 = 2;
r10 = DM(filter_counter); /* get last count from memory */
r10 = r10 + 1; /* increment preset */
comp (r10, r11); /* compare current count to max count */
if ge r10 = r10 - r10; /* if count equals max, reset to zero and start over */
DM(filter_counter) = r10; /* save updated count */
r15 = pass r10; /* get FIR filter preset mode ID */
if eq jump filter_select_2; /* check for count == 0 */
r10 = r10 - 1;
r10 = pass r10;
filter_select_1: /* count therefore, is == 1 if you are here */
b9 = coef_lo; l9 = @coef_lo; /* pointer to the interleaved lowpass filter coefficients */
ustat1=dm(IOFLAG);
bit clr ustat1 0x3E; /* turn on Flag4 LED */
bit set ustat1 0x01;
dm(IOFLAG)=ustat1;
jump exit_IRQ_routine;
filter_select_2:
b9 = coef_hi; l9 = @coef_hi; /* pointer to the interleaved lowpass filter coefficients */
ustat1=dm(IOFLAG);
bit clr ustat1 0x3D; /* turn on Flag5 LED */
bit set ustat1 0x02;
dm(IOFLAG)=ustat1;
exit_IRQ_routine:
rti(db);
bit clr mode1 SRRFH; /* switch back to primary register set */
nop;
change_filter_coeffs.end:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -