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

📄 simd_fir_demo.asm

📁 ADSP-21160下的数字带通滤波器实现的汇编代码。 开发环境为 Visual Dsp 4.5++。
💻 ASM
字号:
//---------------------------------------------------------------------------------------------------------
// 
// (C) Copyright 2002 - Analog Devices, Inc.  All rights reserved.
//
// File Name:		FIR_Demo.asm
// 
// Date Modified:	4/11/02		Rev 1.0
// 
// Purpose:	   		21160 EZ-KIT LITE SIMDFIR digital filter
//
//    				Receives input from the AD1881 A/D's via the 21160 serial port (SPORT0),
//    				Filters the data using a Finite Impuse Response Filter, and then stores the
//    				output for the SPORT0 ISR to transmit the data back to the AD1881 D/A's.
//                                                                                                                                                                      /
//    				The samples from the AD1881 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 SPORT0 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-21160 System Register bit definitions 
#include 	<def21160.h>
.EXTERN		Left_Channel_In;
.EXTERN		Left_Channel_Out;
.EXTERN		Right_Channel_In;
.EXTERN		Right_Channel_Out;


// *** C preprocessor declarations (defines, includes, etc.) *** 
#define FILTER_TAPS 67
#define DOUBLE_FILTER_TAPS 132

.segment /dm    seg_dmda;

.VAR	filtering = 1;						// default is start off filtering 
.VAR	filter_counter = 2;						// default is low-pass filter 
.ALIGN 2;
.VAR    dline [DOUBLE_FILTER_TAPS];       		// delay line of input samples 

.GLOBAL filtering;
.endseg;

//---------------------------------------------------------------------------

.segment /pm	  seg_pmda;

.ALIGN 2;
.VAR    coef_bp_800Hz[FILTER_TAPS] = "Filter_BP_800_67.dat";  // declare and initialize the bandpass filter coefficients
.ALIGN 2;
.VAR	coef_bp_2000Hz[FILTER_TAPS] = "Filter_BP_2000_67.dat";	// declare and initialize the bandpass filter coefficients		
.ALIGN 2;
.VAR    coef_bp_4kHz[FILTER_TAPS] = "Filter_BP_4000_67.dat";   	// declare and initialize the bandpass filter coefficients

				
.endseg;


.segment /pm seg_pmco;

.GLOBAL		init_fir_filter;
.GLOBAL		fir;
.GLOBAL		change_filter_coeffs;
.GLOBAL		toggle_filtering;


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_bp_800Hz;	l9 = @coef_bp_800Hz;   	// pointer to the bandpass filter coefficients  
	m9 = 1 ;

	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_In);				// get left input sample 
	r1 = DM(Right_Channel_In);				// 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 

do_filtering:
	dm(i0,m1)=f0 (LW);

	// Enable broadcast mode and also set the PEYEN.
	bit set mode1 PEYEN | BDCST9;
	bit clr mode1 IRPTEN;

	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_Out) = r8; 			// send result to AD1881 DACs 
	DM(Right_Channel_Out) = r9;

	rts;

fir.end:

// ------------------------------------------------------------------------------------ 
//                                                                                      
//                      IRQ2 Pushbutton Interrupt Service Routine                       
//                                                                                      
// 	This routine determines which FIR filter routine to execute.                      	
// 	Pressing the IRQ2 pushbutton will toggle between each filter. The default           
//	is a bandpass filter(800Hz)                                                               
//                                                                                      
//	To listen to unfiltered signal, hit the IRQ 1 pushbutton                           
// ------------------------------------------------------------------------------------ 

change_filter_coeffs:
    bit set mode1 SRRFH;				// enable background register file 
	NOP; 								// 1 CYCLE LATENCY FOR WRITING TO MODE1 REGISER!!   

	r11 = 3;
	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 

filter_select_1:						// count therefore, is == 2 if you are here 
	b9 = coef_bp_800Hz;	l9 = @coef_bp_800Hz;   	// load 300 Hz lowpass filter coefficients  
	flags=0x9;
    jump exit_IRQ_routine;

filter_select_2:
	b9 = coef_bp_2000Hz;	l9 = @coef_bp_2000Hz;	// load 600 Hz lowpass filter coefficients  
	flags=0xA;		
    jump exit_IRQ_routine;

filter_select_3:					
	b9 = coef_bp_4kHz;	l9 = @coef_bp_4kHz;   	// load 4000 Hz highpass filter coefficients  
	flags=0xC;
    jump exit_IRQ_routine;		

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

change_filter_coeffs.end:


// ------------------------------------------------------------------------------------ 
//                                                                                      
//                      IRQ1 Pushbutton Interrupt Service Routine                       
//                                                                                      
// 	This routine will toggle between a filter and no filter								
//                                                                                      
// ------------------------------------------------------------------------------------ 
toggle_filtering:
    bit set mode1 SRRFH;				// enable background register file
	NOP;
	
	R1 = 0x0;							// clear R1					
	R0 = dm(filtering);					// get previous value
	comp(R0,R1);						// compare the values
	if eq jump set_filtering;			// if they are equal then set to filtering

	R0 = 0x0;							// set to no filtering
	dm(filtering) = R0;
	jump exit_toggle_filtering;


set_filtering:
	R0 = 0x1;							// set to filtering
	dm(filtering) = R0;

exit_toggle_filtering:
	rti(db);
	bit clr mode1 SRRFH;				// switch back to primary register set
	nop;


toggle_filtering.end:

.endseg;

⌨️ 快捷键说明

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