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

📄 fft.asm

📁 基于tms320vc55*系列DSP常用算法
💻 ASM
字号:
;
;   fft.asm - Radix-2 complex FFT (for N=2^EXP points)
;             Using table lookup method
;                               
;   Prototype: void fft(complex *, int, complex *, int); 
;
;   Entry:  arg0: AR0-FFT input sample buffer pointer   
;           arg1: T0-number of FFT stage, EXP
;           arg2: AR1-twiddle factor array pointer     
;           arg3: T1-scale flag 
;                 if scale needed, (T1==1) SCALE=2;
;                 if don't need scale (T1==0) SCALE=1;
;                                                      
;   Note: 1. When used as the FFT routine it takes in time domain 
;         samples in Q15 and generates Q14 frequency domain samples
;         2. When used as the IFFT routine it takes in frequency domain 
;         samples in Q14 and generates Q15 time domain samples
;
;    Revised: Dec. 3, 2001
;             Add an instruction to copy XAR0 to XAR5 for addressing extended page

        .global _fft

;
;	Declare local variables in SP address mode for C-callable
;
ARGS    .set    0       ; Number of variables passed via stack

FFT_var .struct         ; Define local variable structure
d_temp      .int (2)    ; Temporary variables (Re, Im)
d_L         .int
d_N         .int  
d_T2        .int        ; Used to save content of T2
d_ST1       .int        ; Used to save content of ST1
d_ST3       .int        ; Used to save content of ST3
return_addr .int        ; Space for routine return address
Size        .endstruct
fft         .set 0
fft         .tag FFT_var  

    .sect "fft_code"       
	
_fft:
    aadd #(ARGS-Size+1),SP      ; Adjust stack for local vars

    mov  mmap(ST1_55),AR2       ; Save ST1,ST3
    mov  mmap(ST3_55),AR3   
    mov  AR2,fft.d_ST1
    mov  AR3,fft.d_ST3
    btst @#0,T1,TC1             ; Check SCALE flag set		
    mov  #0x6340,mmap(ST1_55)   ; Set CPL,XF,SATD,SXAM,FRCT (SCALE=1) 
    mov  #0x1f22,mmap(ST3_55)   ; Set: HINT,SATA,SMUL   
    xcc  do_scale,TC1
    mov  #0x6300,mmap(ST1_55)   ; Set CPL,XF,SATD,SXAM (SCALE=2) 
do_scale
    
    mov  T2,fft.d_T2            ; Save T2                     
||  mov  #1,AC0
    mov  AC0,fft.d_L            ; Initialize L=1
||  sfts AC0,T0                 ; T0=EXP
    mov  AC0,fft.d_N            ; N=1<<EXP
    mov  XAR1,XCDP              ; CDP = pointer to U[]
    mov  XSP,XAR4	
    add  #fft.d_temp,AR4        ; AR4 = pointer to temp
    mov  XAR0,XAR1              ; AR1 points to sample buffer
    mov  T0,T1
    mov  XAR0,XAR5              ; Copy externd bits to XAR5
			
outer_loop                      ; for (L=1; L<=EXP; L++)    
    mov  fft.d_L,T0             ; note: Since the buffer is
||  mov  #2,AC0                 ;       arranged in re,im pairs
    sfts AC0,T0                 ;       the index to the buffer
    neg  T0	                    ;       is doubled
||  mov  fft.d_N,AC1            ;       But the repeat coutners
    sftl AC1,T0                 ;       are not doubled
    mov  AC0,T0                 ; LE=2<<L 	
||  sfts AC0,#-1  
    mov  AC0,AR0                ; LE1=LE>>1           
||  sfts AC0,#-1                              
    sub  #1,AC0                 ; Init mid_loop counter
    mov  mmap(AC0L),BRC0        ;   BRC0=LE1-1
    sub  #1,AC1                 ; Init inner loop counter
    mov  mmap(AC1L),BRC1        ;   BRC1=(N>>L)-1   
    add  AR1,AR0   
    mov  #0,T2                  ; j=0 
||  rptblocal mid_loop-1        ; for (j=0; j<LE1;j++) 
    mov  T2,AR5                 ; AR5=id=i+LE1
    mov  T2,AR3	
    add  AR0,AR5                ; AR5 = pointer to X[id].re   
    add  #1,AR5,AR2             ; AR2 = pointer to X[id].im  
    add  AR1,AR3                ; AR3 = pointer to X[i].re 
||  rptblocal inner_loop-1      ; for(i=j; i<N; i+=LE) 
    mpy  *AR5+,*CDP+,AC0        ; AC0=(X[id].re*U.re
::  mpy  *AR2-,*CDP+,AC1        ;     -X[id].im*U.im)/SCALE	 
    masr *AR5-,*CDP-,AC0        ; AC1=(X[id].im*U.re                       
::  macr *AR2+,*CDP-,AC1        ;     +X[id].re*U.im)/SCALE
    mov  pair(hi(AC0)),dbl(*AR4); AC0H=temp.re AC1H=temp.im 
||  mov  dbl(*AR3),AC2
    xcc  scale,TC1
||  mov  AC2>>#1,dual(*AR3)     ; Scale X[i] by 1/SCALE
    mov  dbl(*AR3),AC2  
scale
    add  T0,AR2
||  sub  dual(*AR4),AC2,AC1     ; X[id].re=X[i].re/SCALE-temp.re
    mov  AC1,dbl(*(AR5+T0))     ; X[id].im=X[i].im/SCALE-temp.im
||  add  dual(*AR4),AC2         ; X[i].re=X[i].re/SCALE+temp.re
    mov  AC2,dbl(*(AR3+T0))     ; X[i].im=X[i].im/SCALE+temp.im
inner_loop                      ; End of inner loop       
    amar *CDP+
    amar *CDP+                  ; Update k for pointer to U[k]
||  add  #2,T2                  ; Update j    
mid_loop                        ; End of mid-loop      
    sub  #1,T1          
    add  #1,fft.d_L             ; Update L
    bcc  outer_loop,T1>0        ; End of outer-loop

    mov  fft.d_ST1,AR2          ; Restore ST1,ST3,T2
    mov  fft.d_ST3,AR3
    mov  AR2,mmap(ST1_55)
    mov  AR3,mmap(ST3_55)                              
    mov  fft.d_T2,T2
    aadd #(Size-ARGS-1),SP      ; Reset SP
    ret

    .end 

⌨️ 快捷键说明

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