STM #fft_data+K_DATA_IDX_1,QX STM #K_FFT_SIZE/2-1,BRC RPTBD stage1end-1
;QX指向参加蝶形结运算的第二个数的实部(QR) ;设置块循环计数器
;语句重复执行的范围到地址stage1end-1处 ;延迟执行的两字节的指令(该指令不重复执行) ;BH := PR-QR ;AH := PR+QR ;PR':= (PR+QR)/2 ;QR':= (PR-QR)/2 ;AH := PI ;BH := PI-QI ;AH := PI+QI ;PI':= (PI+QI)/2 ;QI':= (PI-QI)/2 ;AH := next PR
STM #K_DATA_IDX_1+1,AR0 SUB *QX,16,A,B ADD *QX,16,A
STH A,ASM,*PX+ ST B,*QX+ ||LD *PX,A
SUB *QX,16,A,B ADD *QX,16,A
STH A,ASM,*PX+0% ST B,*QX+0% ||LD *PX,A
stage1end:
; -------Stage 2 :计算FFT的第二步,四点的FFT MVMM DATA_PROC_BUF,PX
;PX 指向参加蝶形结运算第一个数据的实部(PR) ;QX 指向参加蝶形结运算第二个数据的实部(QR) ;设置块循环计数器 ;AH := PR
;语句重复执行的范围到地址stage1end-1处 ;初始化AR0以被循环寻址
STM #fft_data+K_DATA_IDX_2,QX STM #K_FFT_SIZE/4-1,BRC LD *PX,16,A
RPTBD stage2end-1
STM #K_DATA_IDX_2+1,AR0
;以下是第二步运算的第一个蝶形结运算过程 SUB *QX,16,A,B ADD *QX,16,A
;BH := PR-QR ;AH := PR+QR ;PR':= (PR+QR)/2 ;QR':= (PR-QR)/2 126
STH A,ASM,*PX+ ST B,*QX+
||LD *PX,A
;AH := PI ;BH := PI-QI ;AH := PI+QI ;PI':= (PI+QI)/2 ;QI':= (PI-QI)/2
SUB *QX,16,A,B ADD *QX,16,A
STH A,ASM,*PX+ STH B,ASM,*QX+
; 以下是第二步运算的第二个蝶形结运算过程 MAR *QX+
;QX中的地址加一 ;AH := PR+QI ;BH := PR-QI ;PR':= (PR+QI)/2 ;AH := PI-QR ;QR':= (PR-QI)/2 ;BH := QR ;PI':= (PI-QR)/2 ;AH := PI+QR ;QI':= (PI+QR)/2 ;AH := PR
ADD *PX,*QX,A SUB *PX,*QX-,B
STH A,ASM,*PX+ SUB *PX,*QX,A ST B,*QX
||LD *QX+,B ST A, *PX
||ADD *PX+0%,A ST A,*QX+0% ||LD *PX,A stage2end:
; Stage 3 thru Stage logN-1:从第三步到第六步的过程如下 STM #K_TWID_TBL_SIZE,BK ST #K_TWID_IDX_3,d_twid_idx STM #K_TWID_IDX_3,AR0 STM #cos_table,WR STM #sine_table,WI
;BK = 旋转因子表格的大小值 ;初始化旋转表格索引值 ;AR0 = 旋转表格初始索引值 ;初始化 WR 指针 ;初始化 WI 指针
STM #K_LOGN-2-1,STAGE_COUNTER ;初始化步骤指针 ST #K_FFT_SIZE/8-1,d_grps_cnt
;初始化组指针
;初始化蝶形结指针
STM #K_FLY_COUNT_3-1,BUTTERFLY_COUNTER ST #K_DATA_IDX_3,d_data_idx stage:
;初始化输入数据的索引 ;以下是每一步的运算过程 127
STM #fft_data,PX LD d_data_idx, A ADD *(PX),A STLM A,QX
MVDK d_grps_cnt,GROUP_COUNTER group:
MVMD BUTTERFLY_COUNTER,BRC RPTBD butterflyend-1
LD *WR,T MPY *QX+,A
MAC *WI+0%,*QX-,A ADD *PX,16,A,B
ST B,*PX
||SUB *PX+,B ST B,*QX
||MPY *QX+,A
MAS *QX,*WR+0%,A ADD *PX,16,A,B ST B,*QX+
||SUB *PX,B LD *WR,T ST B,*PX+
||MPY *QX+,A
butterflyend:
;更新指针以准备下一组蝶形结的运算
;PX 指向参加蝶形结运算第一个数据的实部(PR)
;QX 指向参加蝶形结运算第二个数据的实部(QR) ;AR1 是组个数计数器: ;以下是每一组的运算过程
;将每一组中的蝶形结的个数装入BRC ;重复执行至butterflyend-1处
;A := QR*WR || QX*QI ;A := QR*WR+QI*WI ;B := (QR*WR+QI*WI)+PR
; || QX指向QR ;PR':=((QR*WR+QI*WI)+PR)/2 ;B := PR-(QR*WR+QI*WI) ;QR':= (PR-(QR*WR+QI*WI))/2 ;A := QR*WI [T=WI]
; || QX指向QI ;A := QR*WI-QI*WR ;B := (QR*WI-QI*WR)+PI ;QI':=((QR*WI-QI*WR)+PI)/2
; || QX指向QR ;B := PI-(QR*WI-QI*WR) ;T := WR
;PI':= (PI-(QR*WI-QI*WR))/2
; || PX指向PR ;A := QR*WR || QX指向QI
128
PSHM AR0
;保存AR0
;AR0中装入在该步运算中每一组所用的蝶形结的数目
;增加PX准备进行下一组的运算
MVDK d_data_idx,AR0 MAR *PX+0 MAR *QX+0
;增加QX准备进行下一组的运算
;当组计数器减一后不等于零时,延迟跳转至group处 ;恢复AR0(一字节) ;修改QX以适应下一组的运算
BANZD group,*GROUP_COUNTER- POPM AR0 MAR *QX- ;
;更新指针和其他索引数据以变进入下一个步骤的运算 LD d_data_idx,A SUB #1,A,B
;B = A-1
;修改蝶形结个数计数器
STLM B,BUTTERFLY_COUNTER STL A,1,d_data_idx LD d_grps_cnt,A STL A,-1,d_grps_cnt LD d_twid_idx,A STL A,-1,d_twid_idx
;下一步计算的数据索引翻倍
;下一步计算的组数目减少一半
;下一步计算的旋转因子索引减少一半
BANZD stage,*STAGE_COUNTER- MVDK d_twid_idx,AR0
popm bk popm ar0 popm st0 fft_end: RET
;恢复环境变量
;AR0 = 旋转因子索引(两字节)
第三步,分离复数FFT的输出为奇部分和偶部分
分离FFT输出为相关的四个序列:RP、RM、IP和IM,即偶实数,奇实数、偶虚数和奇虚数四部分,以便第四步形成最终结果。
① 利用信号分析的理论我们把D[k]通过下面的公式分为偶实数RP[k]、奇实数
129
RM[k]、偶虚数IP[k]和奇虚数IM[k]: RP[k] = RP[N-k] = 0.5 * (R[k] + R[N-k]) RM[k] = -RM[N-k] = 0.5 * (R[k] - R[N-k]) IP[k] = IP[N-k] = 0.5 * (I[k] + I[N-k]) IM[k] = -IM[N-k] = 0.5 * (I[k] - I[N-k]) RP[0] = R[0] IP[0] = I[0]
RM[0] = IM[0] = RM[N/2] = IM[N/2] = 0 RP[N/2] = R[N/2] IP[N/2] = I[N/2]
130