⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simd_fir_demo.asm

📁 语音信号进行Fir滤波
💻 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 FILTER_TAPS 130
#define ONEHALF_FILTER_TAPS 65


.segment /dm    dm_data;
.VAR	dummy_variable=0;
.ALIGN 2;
.VAR    dline [FILTER_TAPS];       				/* delay line of input samples */
.VAR	dummy_variable2 = 0;
.VAR	filter_counter = 2;						/* default is low-pass filter */

.endseg;

/*---------------------------------------------------------------------------*/

.segment /pm	  pm_data;

.ALIGN 2;
.VAR    coef_lo_300Hz[FILTER_TAPS] = "coeffs129_300Hz.dat";  	/* declare and initialize the higpass filter coefficients*/
.ALIGN 2;
.VAR	coef_lo_600Hz[FILTER_TAPS] = "coeffs129_600Hz.dat";		/* declare and initialize the lowpass filter coefficients*/		
.ALIGN 2;
.VAR    coef_hi_4kHz[FILTER_TAPS] = "coeffs129_4kHz.dat";   	/* declare and initialize the higpass filter coefficients*/
.ALIGN 2;
.VAR	coef_hi_8kHz[FILTER_TAPS] = "coeffs129_8kHz.dat";		/* declare and initialize the lowpass filter coefficients*/		


/* "coeffs129_300Hz.dat" & "coeffs129_600Hz.dat" contains the coefficients for a low pass filter and
   "coeffs129_4kHz.dat" & "coeffs129_4kHz.dat" contains the coefficients for a high pass filter */
				
.endseg;


.segment /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 = 1; m2 = -1; m3 = 2;

	b9 = coef_hi_4kHz;	l9 = @coef_hi_4kHz;   	/* pointer to the highpass filter coefficients  */
	m9 = 2;

	B3=dline;	l3=@dline;	r12=0; 				/* clear the delay line */
   	lcntr=FILTER_TAPS, do clear until lce;
clear:    dm(i3,2)=r12;

   	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 */
	f0 = f0 + f1;							/* add both left and right channels together */
	f2 = 0.7;
	f0 = f0 * f2; 							/* turn down the volume slightly */

	if flag2_in jump exit_filter;

do_filtering:
//	Circular Buffering Issue:
//	Because SIMD or Long word access transfer two 32-bit words, programs
//	must be careful when using these accesses in circular buffering.
//	It is important that SIMD or Long word accesses do not cross a circular
//	buffer boundary.  If a SIMD	mode access occurs using a circular buffer
//	index register that points to the last location in the circular buffer
//	(end of buffer), the resulting access transfers the last location in
//	the circular buffer and the	first location outside the buffer (end of buffer + 1).

	bit clr mode1 BDCST9;						/* disable broadcast mode, we have 2 sets of coeffs */

	// process filter on left and right channels
	s0 = dm(i0, m1);							/* move pointer to delay[1] */

	// Enable the Y processing element for SIMD mode
	bit set mode1 PEYEN;	
	
	s0 = dm(i0, m2);							/* load s0 with the value of delay[1] for SIMD store, move pointer to delay[0] */

	dm(i0,m3)=f0, f4 = pm(i9,m9);				/* transfer sample to delayline, done in SIMD to load end of buffer + 1 */
												/* to compensate for circular buffer issue described above, read 2 coeffs */										

	f8=f0*f4, f0=dm(i0,m3), f4=pm(i9,m9);		/* samples * coeffs, read 2 samples, read 2 coeffs */
	f12=f0*f4, f0=dm(i0,m3), f4=pm(i9,m9);		/* samples * coeffs, read 2 samples, read 2 coeffs */

	lcntr= ONEHALF_FILTER_TAPS - 3, do macloop until lce;	/* FIR loop */
macloop:   f12=f0*f4, f8=f8+f12, f0=dm(i0,m3), f4=pm(i9,m9);	/* samples * coeffs, accum, read 2 samples, read 2 coeffs */

	f12=f0*f4, f8=f8+f12, s0=dm(i0,m2);	   		/* samples * coeffs, accum, dummy read to move pointer to oldest sample */
	f8=f8+f12;									/* perform the last SIMD accumulate */

	bit clr mode1 PEYEN;
	f12 = s8;									/* move PEy total into PEx register file */
	f8 = f8 + f12;								/* last accum... add PEx and PEy partial results */

exit_filter:
	r1 = 31;									/* scale the result back up to MSBs */
	r8 = fix f8 by r1;							/* Convert back to fixed point */
	DM(Left_Channel_Out0) = r8; 				/* send result to AD1836 DACs */
	DM(Right_Channel_Out0) = r8;
	DM(Left_Channel_Out1) = r8; 			
	DM(Right_Channel_Out1) = r8;

	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 = 4;
	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;						
	if eq jump filter_select_3;			/* check for count == 1 */
	r10 = r10 - 1;
	r10 = pass r10;						
	if eq jump filter_select_4;			/* check for count == 2 */

filter_select_1:						/* count therefore, is == 3 if you are here */
	b9 = coef_lo_300Hz;	l9 = @coef_lo_300Hz;   	/* load 300 Hz 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_lo_600Hz;	l9 = @coef_lo_600Hz;	/* load 600 Hz lowpass filter coefficients  */
	ustat1=dm(IOFLAG);
	bit clr ustat1 0x3D;						/* turn on Flag5 LED */
	bit set ustat1 0x02;
	dm(IOFLAG)=ustat1;		
    jump exit_IRQ_routine;

filter_select_3:					
	b9 = coef_hi_4kHz;	l9 = @coef_hi_4kHz;   	/* load 4000 Hz highpass filter coefficients  */
	ustat1=dm(IOFLAG);
	bit clr ustat1 0x3B;						/* turn on Flag6 LED */
	bit set ustat1 0x04;
	dm(IOFLAG)=ustat1;
    jump exit_IRQ_routine;

filter_select_4:
	b9 = coef_hi_8kHz;	l9 = @coef_hi_8kHz;   	/* load 8000 Hz highpass filter coefficients */
	ustat1=dm(IOFLAG);
	bit clr ustat1 0x37;						/* turn on Flag7 LED */
	bit set ustat1 0x08;
	dm(IOFLAG)=ustat1;		

exit_IRQ_routine:	
	rti(db);
	bit clr mode1 SRRFH;						/* switch back to primary register set */
	nop;
change_filter_coeffs.end:

.endseg;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -