/****************************************************************************** Cfft2_2191.ASM ADSP-2191 Radix-2 DIT Complex FFT Performs a radix-2 DIT FFT of length 64 or greater on input data x(n). N Real part of normal-ordered complex input stored in DM N Imaginary part of normal-ordered complex input stored in PM N Real part of fft stored in DM N/2 Sin table stored in DM N/2 Cos table stored in PM Calling Information: pm(twid_real[N/2]) - sin(2pi*n/N) table in bitreversed order dm(twid_imag[N/2]) - cos(2pi*n/N) table in bitreversed order dm(Inputreal[N]) - Real part of complex input array stored in dm pm(Inputimag[N]) - Imaginary part of complex input array stored in pm Results: dm(Refft[N]) - Real FFT results ordered sequentially dm(Inputreal[N]) - Imaginary FFT results ordered sequentially Benchmarks: FFT Length cycles time (us) 160MHz ---------- ------------- --------------- 1024 24160 151 Memory Usage: PM code(24-bit) = 92 words PM data(24-bit) = N + 2 + N/2 words DM data(16-bit) = 2N + 4 + N + 1 words ******************************************************************************/ /**********The constants below must be changed for different length FFTs******* N = number of points in the FFT, must be a power of 2 log2N = log2(N) Mod_Value = 2^(16-LOG2N) Refft_Bitrev = bitrev addr of output real in dm Inputreal_Bitrev = bitrev addr of output imag in dm ******************************************************************************/ /* Set Constants for N-point FFT */ #define N 1024 #define Ndiv2 (N/2) #define log2N 10 #define Mod_Value 64 #define Refft_Bitrev 0x0001 #define Inputreal_Bitrev 0x0009 /* DM data */ .section/data data1; .VAR twid_imag [Ndiv2] = "twid_sin.dat"; .VAR groups = 1; .VAR node_space = Ndiv2; /* DM data */ .section/data seg_buf1; .VAR Inputreal [N+2] = "inreal.dat"; /* DM data */ .section/data seg_buf2; .VAR Refft[N+2]; /* PM data */ .section/pm data2; .VAR/init24 twid_real [Ndiv2] = "twid_cos.dat"; .VAR Inputimag [N+2] = "inimag.dat"; /* PM interrupt vector code */ .section/pm IVreset; JUMP start; NOP; NOP; /* Program Code */ .section/pm program; start: dmpg2 = page(twid_real); /* Initialize page for PM data */ M0 = 0; L0 = length(twid_imag); /* Initialize twid_imag circular buffer */ AX1 = twid_imag; REG(b0) = AX1; /* Initialize pointer to twid_imag */ M1 = 1; L1 = 0; /* Initialize for modulo addressing */ M4 = 0; L4 = length(twid_real); /* Initialize twid_real circular buffer */ AX1 = twid_real; REG(b4) = AX1; /* Initialize pointer to twid_real */ M5 = 1; L5 = 0; /* Initialize for modulo addressing */ M6 = -1; L6 = 0; /* Initialize for modulo addressing */ L2 = 0; L3 = 0; L7 = 0; CNTR = log2N -1; /* Initialize Stage Counter */ DO stage_loop UNTIL CE; /* Compute all stages in FFT */ I0 = twid_imag; /* I0 --> (-S) of W0 */ I1 = Inputreal; /* I1 --> x1 in 1st group of stage */ I2 = Inputreal; /* I2 --> x0 in 1st group of stage */ I4 = twid_real; /* I4 --> C of W0 */ I5 = Inputimag; /* I5 --> y1 in 1st group of stage */ I6 = Inputimag; /* I6 --> y0 in 1st group of stage */ SI = DM(groups); CNTR = SI; /* CNTR = # of groups in stage */ SR = LSHIFT SI BY 1(LO); DM(groups) = SR0; SI = DM(node_space); /* SI = node_space modifier */ M2 =SI; M7 =SI; MODIFY(I1,M2); /* I1 --> x1 in 1st group of stage */ MODIFY(I5,M7); /* I5 --> y1 in 1st group of stage */ DO group_loop UNTIL CE; MY0 = PM(I4,M5), MX0 = DM(I1,M0); /* MY0=C, MX0=x1 */ MR = MX0*MY0(SS), MX1 = PM(I5,M4); /* MR=C*x1,MX1=y1 */ MY1 = DM(I0,M1); /* MY1 = (-S) */ CNTR = SI; /* CNTR = butterfly counter */ DO bfly_loop UNTIL CE; MR = MR-MX1*MY1(RND), AY0 = DM(I2,M0); /* MR=x1*C-y1*-S, AY0=x0 */ AR = MR1+AY0, AX1 = PM(I5,M5); /* AR=x0'=x0+(x1*C-y1*-S) */ DM(I2,M1) = AR, AR = AY0-MR1; /* DM=x0', AR=x1'=x0-(x1*C-y1*(-S)) */ MR = MX0*MY1(SS), DM(I1,M1) = AR; /* MR=x1*(-S), DM=x1' */ MR = MR+MX1*MY0(RND), AY1 = PM(I6,M4), MX0 = DM(I1,M0); /*MR=x1*(-S)+y1*C, AY1=y0, MX0=next x1*/ AR = MR1+AY1, MX1 = PM(I5,M6); /* AR=y0'=y0+(y1*C+x1*(-S)), MX1= next y1 */ PM(I6,M5) = AR, AR = AY1-MR1; /* PM=y0', AR=y1'=y0-(y1*C+x1*(-S)) */ bfly_loop: MR = MX0*MY0(SS), PM(I5,M5) = AR; /* PM=y1' */ MY0 = PM(I5,M7), MX0 = DM(I1,M2); group_loop: MY0=PM(I6,M7), MX0=DM(I2,M2); SR=ASHIFT SI BY -1 (LO); stage_loop: DM(node_space)=SR0; I0 = twid_imag; /* I0 --> (-S) */ I1 = Inputreal; /* I1 --> x1 */ I2 = Inputreal; /* I2 --> x0 */ M2 = 2; I3 = Refft_Bitrev; /* Refft bitreversed */ M3 = Mod_Value; /* Bitreversed modifier */ I4 = twid_real; /* I4 --> C */ I5 = Inputimag; /* I5 --> y1 */ I6 = Inputimag; /* I6 --> y0 */ M6 = 2; MODIFY(I1,M1); /* I1 -->x1 */ MODIFY(I5,M5); /* I5 -->y1 */ MY0 = PM(I4,M5), MX0 = DM(I1,M2); /* MY0=C, MX0=x1 */ MR = MX0*MY0(SS), MX1 = PM(I5,M6); /* MR = C*x1, MX1 = y1 */ MY1 = DM(I0,M1); /* MY1 = (-S) */ CNTR = Ndiv2; DO last_loop UNTIL CE; MR = MR-MX1*MY1(RND), AY0 = DM(I2,M2); /* MR=x1*C-y1*(-S), AY0=x0 */ AR = MR1+AY0, AY1 = PM(I6,M4); /* AR=x0'=x0+(x1*C-y1*(-S)), AY1=y0 */ ENA BIT_REV; DM(I3,M3) = AR, AR = AY0-MR1; /* Read real data */ MR = MX0*MY1(SS), DM(I3,M3) = AR; /* Place in sequential order(using bit-reversal) */ DIS BIT_REV; MR = MR+MX1*MY0(RND), MY0 = PM(I4,M5), MX0 = DM(I1,M2); AR = MR1+AY1, MX1 = PM(I5,M6); /* AR=y0'=y0+(y1*C+x1*(-S)), MX1= next y1 */ PM(I6,M5) = AR, AR = AY1-MR1; /* PM=y0', AR=y1'=y0-(y1*C+x1*(-S)) */ MY1 = DM(I0,M1); /* MY1 = (-S) */ last_loop: MR = MX0*MY0(SS), PM(I6,M5) = AR; /*PM=y1' */ I3 = Inputreal_Bitrev; M3 = Mod_Value; /* Bitreversed modifier */ I5 = Inputimag; ENA BIT_REV; CNTR = N; DO bit_rev_imag UNTIL CE; AX0 = PM(I5,M5); /* Read imaginary data */ bit_rev_imag: DM(I3,M3) = AX0; /* Place in sequential order */ DIS BIT_REV; looping: JUMP looping;