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

📄 fft1.asm

📁 dsp原理及电机控制应用代码 ( 刘和平).rar
💻 ASM
字号:
;(3) FFT应用子程序
; -------------------------------------------------------------------------------------------------
; 函数名:	void 	fft(void)
; 功能:实现32、64或128采样点的快速傅立叶变换
; 入口条件:	
;	_sintab		存放FFT运算中用到的sin和cosin函数值
;	_input		存放FFT运算中用到的数据,包括实部和虚部,按二进制反序排列
;				注意:由于"*BR0+"间接寻址方式对_input的地址有特殊的要求,
;				所以最好将数组_input放置在一个独立的块中,如B1块。
;	_nom			当_nom=0时,本函数将不对运算结果进行归一化。反之,将对每        
;				一步运算结果进行归一化处理,避免溢出,但是,它会使运算精度降低。
; 	N		 	常数,参与FFT运输的点数,用户可根据需要选择,例如,需要进行128点
;			 	FFT时,请在本函数中做出如下选择:
;	N	.set	128
;	M	.set	7
;	依此类推。
;	出口条件:
;	_input		存放FFT的运算结果
;	本函数可供C调用,请用户在C主程序中作以下声明:
;	extern	void fft(void);
;	const	int sintab[N]={...};		N为128、64或32
;	extern	int _input[2*N];
;	extern	int nom;
;--------------------------------------------------------------------------------------------------
	.def	_fft
; 基2时间抽取的128点FFT算法需要定义的各量
; N		.set	128				 ; 点数
; M		.set	7   				 ;  N=2**M
; 基2时间抽取的64点FFT算法需要定义的各量
; N		.set	64                	; 点数
; M		.set	6                 	; N=2**M
; 基2时间抽取的32点FFT算法需要定义的各量
N		.set	32                	; 点数
M		.set	5                 	; N=2**M
_input	.usect  ".data0",2*N     	;   输入数据       
;   		.bss	_sintab,N		     ;   SIN和COSIN函数的存储表				
		.bss	_nom,1            ;   当 _nom=1时,FFT需要归一化处理,为0时则不需要
		.global	_fft
		.global	_sintab
		.global	_input 
		.global _nom
		.text     
_fft:  
;   --------------------------------------
;   与C语言兼容的代码部分 
;   --------------------------------------
	   	POPD	*+   			;   存储返回地址ADDRESS
	   	SAR		AR6,*+          	;   存储 AR6
	   	SAR		AR7,*+          	;   存储 AR7
	   	SAR		AR0,*+          	;   存储 AR0
	   	SAR		AR1,*           	;   堆栈分布情况:ADDRESS/AR6/AR7/AR0/AR1
	   						     ;   ARP=AR1,AR1:AR1
	   	LAR		AR0,#08h           
	   	LAR		AR3,*0+,AR3   	;   AR3:FP,SP=SP+size(size=frame的长度)
	   					          ;   ARP=AR3
	   	LAR		AR2,*		     ;   AR2:AR1
	   	LAR		AR7,#_nom		;   AR7 指向 _nom
;   -----------------------------------------
;   初始化一些寄存器
;   ----------------------------------------- 		
		SPLK	#(N-1),*+ 			
		SPLK	#(M-1),*+		          
							     ;   堆栈分布情况:ADDRESS/AR6/AR7
;   /AR0/N/M/Y(其中Y为没有确定的量)
							     ;   ARP=AR3,AR2:N,AR3:Y
		SPLK	#1,*+,AR2		    	;   ID=1,ARP=AR2
							     ;   堆栈分布情况:ADDRESS/AR6/AR7/AR0/										;   N/M/ID/Y    ARP=AR2,AR2:N,AR3:
;   -----------------------------------------
;   FFT运算处理部分
;   -----------------------------------------									
 		SETC	OVM			      	;   使能溢出模式
		SETC	SXM				  	;   符号扩展使能
		SPM	     1			        ;   PREG寄存器的输出左移一位,
;   自动将两个Q15相乘后化为Q15的格式
		LACC	*+,AR3
		ADD	#1
		SACL	*+,1,AR2		    ;   IW=2*(N+1)
								    ;   堆栈分布情况:ADDRESS/AR6/AR7
							        ;   /AR0/N/M/ID/IW/Y   
;   ARP:AR2,AR2:M,AR3:Y,
		LAR	    AR5,*+			    ;   AR5=M,ARP:AR2,AR2:ID,
;   AR3:Y,AR5=M
LOOP3	 
		LAR	 AR6,#_input 		    ;   AR6:input-->Ri ,ARP:AR2,
;   AR2:ID,AR3:Y,AR5=M,AR6:input  
		LACC	*,1
		SACL    *+				    ;   ID=ID*2,ARP:AR2,AR2:IW,
;    AR3:Y,AR5=M,AR6:input
          LACC	*,15
          SACH	*				    ;   IW=IW/2
          LACC	*-,15,AR3
          SACH	*+,AR2		        ;   C2=IW/2
;   堆栈分布情况:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/Y
;   ARP:AR2,AR2:ID,AR3:Y,AR5=M,AR6:input
		 LAR	AR0,*			    ;   AR0=ID
LOOP2	
		 LAR	AR4,#_sintab		;   AR4:sintab
;  ARP:AR2,AR0=ID,AR2:ID,AR3:Y,AR4:sintab,AR5=M,AR6:input
    	 LACC	 *+,15,AR3
    	 SACH	 *+,AR6             ;   C1=ID/2=1
;   堆栈分布情况:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/Y
;  ARP:AR6,AR0=ID,AR2:IW,AR3:Y,AR4:sintab,AR5=M,AR6:input
	  	 MAR	*0+,AR4				
;  ARP:AR4,AR0=ID,AR2:IW,AR3:Y,AR4:sintab,AR5=M,AR6=AR6+ID-->Rj
LOOP1	
        LACC	 #0
		LT	*+,AR6                  ;   TREG=COSαlk
        MPY	*+,AR4		            ;   Rj* COSαlk,ARP=AR4,AR4:SINαlk,AR6:Ij
		LT		*,AR6
		MPYA 	*-,AR3		        ;   ACC=ACC+Rj*COSαlk,PREG=Ij*SINαlk
							        ;   ARP=AR3,AR4:SINαlk,AR6:Rj
		SPAC				        ;   ACC=ACC-Ij*SINαlk
		SACH    *+,AR4		        ;   XT=Rj*COSαlk-Ij*SINαlk
;   堆栈分布情况:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/XT/Y
;   ARP:AR4,AR0=ID,AR2:IW,AR3:Y,AR4:SINX,AR5=M,AR6:Q.X
  		LACC	#0
  		LT		*-,AR6
  		MPY		*+,AR4			    ;   Rj*SINαlk,ARP=AR4,AR4:COSαlk,AR6:Ij
  		LT		*,AR6
  		MPYA	*-,AR3 			    ;   ACC=ACC+Rj*SINαlk,PREG=Ij*COSαlk
  								    ;   ARP=AR3,AR4:COSαlk,AR6:Rj
  		APAC	
  		SACH	*-,AR7			    ;   YT=Rj*SINαlk+Ij*COSαlk
;   堆栈分布情况:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/XT/YT
;   ARP:AR7,AR0=ID,AR2:IW,AR3:XT,AR4:COSX,AR5=M,AR6:Q.X 
		LACC	*,AR6
		BCND	D2,NEQ		        ;   当_nom不为0时,需要在运算过程中进
;   行归一化操作
;   ----------------------------------------
;   不进行归一化操作程序部分
;   ----------------------------------------
		MAR		*0-				    ;   AR6=AR6-ID-->Ri 
		LACC	*,AR3
		ADD		*,AR6
		SACL	*0+,AR3			    ;   Ri=Ri+XT
;   ARP:AR3,AR0=ID,AR2:IW,AR3:XT,AR4:COSαlk,AR5=M,AR6:Rj
		SUB		*+,1,AR6
		SACL	*+				    ;   Rj= Ri+XT -XT*2=Ri-XT,AR6:Ij,AR3:YT
;   ARP:AR6,AR0=ID,AR2:IW,AR3:YT,AR4:COSαlk ,AR5=M,AR6:Ij
		MAR		*0-       			  ;   AR6:Ii
		LACC	*,AR3               
		ADD		*-,AR6
		SACL	*0+,AR3			    ;   Ii= Ii +YT,AR6:Ij
;   ARP:AR3,AR0=ID,AR2:IW,AR3:XT,AR4:COSαlk,AR5=M,AR6:Ij
		SUB		*,1,AR6				
		SACL	*+,0,AR2	        ;   Ij= Ii +YT -YT*2=Ii-YT 
;   STACK:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/XT/YT
;   ARP:AR2,AR0=ID,AR2:IW,AR3:XT,AR4:COSαlk,AR5=M,AR6:NEXT Rj
		B		D                   ;   AR6 指向下一个Rj
;   ---------------------------------------
;   归一化处理程序部分
;   ---------------------------------------
D2		MAR		*0-				    ;   AR6-->Ri
		LAC		*,15,AR3
		ADD		*,15,AR6				
		SACH	*0+,AR3			    ;   Ri =( Ri +XT)/2
;   ARP:AR3,AR0=ID,AR2:IW,AR3:XT,AR4:COSαlk,AR5=M,AR6:Rj	
	    SUB		*+,16,AR6
		SACH	*+				    ;   Rj=Ri-XT,AR6:Ij,AR3:YT
;  ARP:AR6,AR0=ID,AR2:IW,AR3:YT,AR4:COSαlk,AR5=M,AR6:Ij
		MAR		*0-				    ;   AR6:Ii
		LACC	*,15,AR3
		ADD		*,15,AR6
		SACH	*0+,AR3             ;   Ii=(Ii+YT)/2,AR6:Ij
;  ARP:AR3,AR0=ID,AR2:IW,AR3:YT,AR4:COSαlk,AR5=M,AR6:Ij
		SUB		*-,16,AR6
		SACH	*+,0,AR2		    ;   Ij=Ii-YT
;   STACK:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/XT/YT
;   ARP:AR2,AR0=ID,AR2:IW,AR3:XT,AR4:COSαlk,AR5=M,AR6:下一个Rj
D		
        LAR		AR0,*-,AR4		    ;   AR0=IW
;  ARP=AR4,AR0=IW,AR2:ID,AR3:XT,AR4:COSαlk,AR5=M,AR6:下一个Rj
		MAR		*0+,AR2			    ;   AR4=AR4+IW-->下一个COSαlk
		LAR		AR0,*			    ;   AR0=ID
		ADRK	#3				    ;   AR2:C1
;  ARP=AR2,AR0=ID,AR2:C1,AR3:XT,AR4:下一个COSαlk,AR5=M,AR6:Rj
	    LACC	*
	    SUB		#1
	    SACL	*-					;   C1=C1-1
;   ARP=AR2,AR0=ID,AR2:C2,AR3:XT,AR4:COSαlk,AR5=M,AR6:Rj
	   	BCND	LOOP4,LEQ		    ;   跳转至LOOP4,IF C1<0
	   	MAR		*-,AR4			    ;   AR2:IW
;   ARP=AR4,AR0=ID,AR2:IW,AR3:XT,AR4:下一个COSαlk,AR5=M,AR6:Rj
	   	B		LOOP1                
LOOP4	LACC	*
		SUB		#1
		SACL	*-,AR3
		MAR     *-,AR2				
;   ARP=AR2,AR0=ID,AR2:IW,AR3:C1,AR4:下一个COSαlk,AR5=M,AR6:Ri
		MAR		*-
        BCND	LOOP2,GT
        MAR     *,AR3
        MAR		*-,AR5              
;   ARP=AR5,AR0=ID,AR2:IW,AR3:C2,AR4下一个COSαlk,AR5=M,AR6:Ri
        BANZ	LOOP3,*-,AR2
;   ------------------------------------
;   与C语言兼容的代码部分
;   ------------------------------------
	    CLRC	OVM
	    SPM		0           
        MAR		*,AR1
        SBRK	#09
        LAR		AR0,*-
        LAR		AR7,*-
        LAR		AR6,*-
        PSHD	*
        RET

⌨️ 快捷键说明

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