📄 fft.asm
字号:
.WORD 00BED0H
.WORD 003955H
.WORD 008327H
.WORD 0040D5H
.WORD 00C708H
.WORD 007C7AH
.WORD 00BF8CH
.WORD 003896H
.WORD 0083EAH
.WORD 00400EH
.WORD 00C7D2H
.WORD 007BACH
.WORD 00C05DH
.WORD 0037C1H
.WORD 0084C2H
.WORD 003F33H
.WORD 00C8B1H
.WORD 007ACAH
.WORD 00C142H
.WORD 0036D8H
.WORD 0085AEH
.WORD 003E43H
.WORD 00C9A4H
.WORD 0079D4H
.WORD 00C23CH
.WORD 0035DBH
.WORD 0086AFH
.WORD 003D3FH
.WORD 00CAABH
.WORD 0078CAH
.WORD 00C34AH
.WORD 0034CAH
.WORD 0087C3H
.WORD 003C28H
.WORD 00CBC6H
.WORD 0077ABH
.WORD 00C46BH
.WORD 0033A5H
.WORD 0088EBH
.WORD 003AFDH
.WORD 00CCF4H
.WORD 00767AH
.WORD 00C5A0H
.WORD 00326DH
.WORD 008A26H
.WORD 0039BEH
.WORD 00CE36H
.WORD 007535H
.WORD 00C6E8H
.WORD 003122H
.WORD 008B75H
.WORD 00386DH
.WORD 00CF8BH
.WORD 0073DDH
.WORD 00C843H
.WORD 002FC4H
.WORD 008CD6H
.WORD 003708H
.WORD 00D0F2H
.WORD 007273H
.WORD 00C9B1H
.WORD 002E54H
.WORD 008E49H
.WORD 003592H
.WORD 00D26BH
.WORD 0070F6H
.WORD 00CB30H
.WORD 002CD1H
.WORD 008FCFH
.WORD 00340AH
.WORD 00D3F7H
.WORD 006F68H
.WORD 00CCC1H
.WORD 002B3DH
.WORD 009166H
.WORD 003270H
.WORD 00D593H
.WORD 006DC8H
.WORD 00CE64H
.WORD 002998H
.WORD 00930EH
.WORD 0030C5H
.WORD 00D741H
.WORD 006C18H
.WORD 00D017H
.WORD 0027E2H
.WORD 0094C7H
.WORD 002F09H
.WORD 00D900H
.WORD 006A57H
.WORD 00D1DBH
.WORD 00261BH
.WORD 009690H
.WORD 002D3DH
.WORD 00DACEH
.WORD 006885H
.WORD 00D3AFH
.WORD 002444H
.WORD 009869H
.WORD 002B61H
.WORD 00DCADH
.WORD 0066A4H
.WORD 00D593H
.WORD 00225EH
.WORD 009A52H
.WORD 002976H
.WORD 00DE9BH
.WORD 0064B4H
.WORD 00D785H
.WORD 002069H
.WORD 009C4AH
.WORD 00277CH
.WORD 00E097H
.WORD 0062B5H
.WORD 00D987H
.WORD 001E65H
.WORD 009E50H
.WORD 002573H
.WORD 00E2A2H
.WORD 0060A8H
.WORD 00DB96H
.WORD 001C54H
.WORD 00A064H
.WORD 00235DH
.WORD 00E4BAH
.WORD 005E8DH
.WORD 00DDB3H
.WORD 001A34H
.WORD 00A285H
.WORD 002139H
.WORD 00E6E0H
.WORD 005C65H
.WORD 00DFDDH
.WORD 001808H
.WORD 00A4B4H
.WORD 001F09H
.WORD 00E913H
.WORD 005A31H
.WORD 00E214H
.WORD 0015CFH
.WORD 00A6EEH
.WORD 001CCCH
.WORD 00EB51H
.WORD 0057F0H
.WORD 00E456H
.WORD 00138BH
.WORD 00A935H
.WORD 001A84H
.WORD 00ED9CH
.WORD 0055A4H
.WORD 00E6A4H
.WORD 00113BH
.WORD 00AB86H
.WORD 001831H
.WORD 00EFF1H
.WORD 00534DH
.WORD 00E8FDH
.WORD 000EE1H
.WORD 00ADE2H
.WORD 0015D3H
.WORD 00F250H
.WORD 0050ECH
.WORD 00EB60H
.WORD 000C7CH
.WORD 00B049H
.WORD 00136BH
.WORD 00F4BAH
.WORD 004E81H
.WORD 00EDCCH
.WORD 000A0EH
.WORD 00B2B8H
.WORD 0010FAH
.WORD 00F72CH
.WORD 004C0DH
.WORD 00F042H
.WORD 000797H
.WORD 00B531H
.WORD 000E80H
.WORD 00F9A7H
.WORD 004990H
.WORD 00F2C0H
.WORD 000518H
.WORD 00B7B1H
.WORD 000BFEH
.WORD 00FC2BH
.WORD 00470CH
.WORD 00F545H
.WORD 000291H
.WORD 00BA39H
.WORD 000975H
.WORD 00FEB5H
.WORD 004480H
.WORD 00F7D2H
.WORD 000003H
data_output .usect "data_out",1024
.text
;256-Point Real FFT Initialization
.asg AR1,FFT_TWID_P
_c_int00:
; .sect "rfft_prg"
LD #FFT_DP,DP
STM #SYSTEM_STACK,SP
rfft_task:
; STM #sine,FFT_TWID_P
; RPT #K_FFT_SIZE-1 ; move FIR coeffs from program
; MVPD #sine_table,*FFT_TWID_P+ ; to data
; STM #cosine,FFT_TWID_P
; RPT #K_FFT_SIZE-1 ; move FIR coeffs from program
; MVPD #cos_table,*FFT_TWID_P+
STM #FFT_ORIGIN,AR3 ; to data
STM #data_input,AR4
RPT #K_FFT_SIZE*2-1
MVDD *AR4+,*AR3+
CALL bit_rev
CALL fft
CALL unpack
CALLD power
STM #K_ST1,ST1 ; restore the original contents of
NOP
STM 19F0H,AR6
NOP
XOR A,A
RPT #30
STL A,*AR6+
;CALL find
loop:
B loop
; ST1 since ASM field has changed
NOP
NOP
NOP
RET ; return to main program
;=========================================================
;Bit Reversal Routine
.asg AR2,REORDERED_DATA
.asg AR3,ORIGINAL_INPUT
.asg AR7,DATA_PROC_BUF
.def bit_rev
; .sect "rfft_prg"
bit_rev:
SSBX FRCT
; ST #FFT_ORIGIN,d_input_addr ; fractional mode is on
STM #FFT_ORIGIN,ORIGINAL_INPUT ; AR3 -> 1 st original input
STM #fft_data,DATA_PROC_BUF ; AR7 -> data processing buffer
MVMM DATA_PROC_BUF,REORDERED_DATA ; AR2 -> 1st bit-reversed data
STM #K_FFT_SIZE-1,BRC
RPTBD bit_rev_end-1
STM #K_FFT_SIZE,AR0 ; AR0 = 1/2 size of circ buffer
MVDD *ORIGINAL_INPUT+,*REORDERED_DATA+
MVDD *ORIGINAL_INPUT-,*REORDERED_DATA+
MAR *ORIGINAL_INPUT+0B
bit_rev_end:
RET ; return to Real FFT main module
;=====================================================
;256-Point Real FFT Routine
.asg AR1,GROUP_COUNTER
.asg AR2,PX
.asg AR3,QX
.asg AR4,WR
.asg AR5,WI
.asg AR6,BUTTERFLY_COUNTER
.asg AR7,DATA_PROC_BUF ; for Stages 1 & 2
.asg AR7,STAGE_COUNTER ; for the remaining stages
.def fft
; .sect "rfft_prg"
fft:
; Stage 1 --------------------------------------------
STM #K_ZERO_BK,BK ; BK=0 so that *ARn+0% == *ARn+0
LD #-1,ASM ; outputs div by 2 at each stage
MVMM DATA_PROC_BUF,PX ; PX -> PR
LD *PX,A ; A := PR
STM #fft_data+K_DATA_IDX_1,QX ; QX -> QR
STM #K_FFT_SIZE/2-1,BRC
RPTBD stage1end-1
STM #K_DATA_IDX_1+1,AR0
SUB *QX,16,A,B ; B := PR-QR
ADD *QX,16,A ; A := PR+QR
STH A,ASM,*PX+ ; PR’:= (PR+QR)/2
ST B,*QX+ ; QR’:= (PR-QR)/2
||LD *PX,A ; A := PI
SUB *QX,16,A,B ; B := PI-QI
ADD *QX,16,A ; A := PI+QI
STH A,ASM,*PX+0 ; PI’:= (PI+QI)/2
ST B,*QX+0% ; QI’:= (PI-QI)/2
||LD *PX,A ; A := next PR
stage1end:
; Stage 2 ----------------------------------------------------------------------
MVMM DATA_PROC_BUF,PX ; PX -> PR
STM #fft_data+K_DATA_IDX_2,QX ; QX -> QR
STM #K_FFT_SIZE/4-1,BRC
LD *PX,A ; A := PR
RPTBD stage2end-1
STM #K_DATA_IDX_2+1,AR0
; 1st butterfly
SUB *QX,16,A,B ; B := PR-QR
ADD *QX,16,A ; A := PR+QR
STH A,ASM,*PX+ ; PR’:= (PR+QR)/2
ST B,*QX+ ; QR’:= (PR-QR)/2
||LD *PX,A ; A := PI
SUB *QX,16,A,B ; B := PI-QI
ADD *QX,16,A ; A := PI+QI
STH A,ASM,*PX+ ; PI’:= (PI+QI)/2
STH B,ASM,*QX+ ; QI’:= (PI-QI)/2
; 2nd butterfly
MAR *QX+
ADD *PX,*QX,A ; A := PR+QI
SUB *PX,*QX-,B ; B := PR-QI
STH A,ASM,*PX+ ; PR’:= (PR+QI)/2
SUB *PX,*QX,A ; A := PI-QR
ST B,*QX ; QR’:= (PR-QI)/2
||LD *QX+,B ; B := QR
ST A, *PX ; PI’:= (PI-QR)/2
||ADD *PX+0%,A ; A := PI+QR
ST A,*QX+0% ; QI’:= (PI+QR)/2
||LD *PX,A ; A := PR
stage2end:
; Stage 3 thru Stage logN-1 ----------------------------------------------------
STM #K_TWID_TBL_SIZE,BK ; BK = twiddle table size always
ST #K_TWID_IDX_3,d_twid_idx ; init index of twiddle table
STM #K_TWID_IDX_3,AR0 ; AR0 = index of twiddle table
STM #cosine,WR ; init WR pointer
STM #sine,WI ; init WI pointer
STM #K_LOGN-2-1,STAGE_COUNTER ; init stage counter
ST #K_FFT_SIZE/8-1,d_grps_cnt ; init group counter
STM #K_FLY_COUNT_3-1,BUTTERFLY_COUNTER ; init butterfly counter
ST #K_DATA_IDX_3,d_data_idx ; init index for input data
stage:
STM #fft_data,PX ; PX -> PR
LD d_data_idx, A
ADD *(PX),A
STLM A,QX ; QX -> QR
MVDK d_grps_cnt,GROUP_COUNTER ; AR1 contains group counter
;A circular buffer of size R must start on a N-bit boundary (that is, the N LSBs
;of the base address of the circular buffer must be 0), where N is the smallest
;integer that satisfies 2 N > R. The value R must be loaded into BK.
group:
MVMD BUTTERFLY_COUNTER,BRC ; # of butterflies in each grp
RPTBD butterflyend-1
LD *WR,T ; T := WR
MPY *QX+,A ; A := QR*WR || QX->QI
MACR *WI+0%,*QX-,A ; A := QR*WR+QI*WI || QX->QR
ADD *PX,16,A,B ; B := (QR*WR+QI*WI)+PR
ST B,*PX ; PR’:=((QR*WR+QI*WI)+PR)/2
||SUB *PX+,B ; B := PR-(QR*WR+QI*WI) || PX->PI
ST B,*QX ; QR’:= (PR-(QR*WR+QI*WI))/2
||MPY *QX+,A ; A := QR*WI [T=WI] || QX->QI
MASR *QX,*WR+0%,A ; A := QR*WI-QI*WR
ADD *PX,16,A,B ; B := (QR*WI-QI*WR)+PI
ST B,*QX+ ; QI’:=((QR*WI-QI*WR)+PI)/2 || QX->QR
||SUB *PX,B ; B := PI-(QR*WI-QI*WR)
LD *WR,T ; T := WR
ST B,*PX+ ; PI’:= (PI-(QR*WI-QI*WR))/2 || PX->PR
||MPY *QX+,A ; A := QR*WR || QX->QI
butterflyend:
; Update pointers for next group
PSHM AR0 ; preserve AR0
MVDK d_data_idx,AR0
MAR *PX+0 ; increment PX for next group
MAR *QX+0 ; increment QX for next group
BANZD group,*GROUP_COUNTER-
POPM AR0 ; restore AR0
MAR *QX-
; Update counters and indices for next stage
LD d_data_idx,A
SUB #1,A,B ; B = A-1
STLM B,BUTTERFLY_COUNTER ; BUTTERFLY_COUNTER = #flies-1
STL A,1,d_data_idx ; double the index of data
LD d_grps_cnt,A
STL A,ASM,d_grps_cnt ; 1/2 the offset to next group
LD d_twid_idx,A
STL A,ASM,d_twid_idx ; 1/2 the index of twiddle table
BANZD stage,*STAGE_COUNTER-
MVDK d_twid_idx,AR0 ; AR0 = index of twiddle table
fft_end:
RET ; return to Real FFT main module
;=================================================
;Unpack 256-Point Real FFT Output
.def unpack
; .sect "rfft_prg"
unpack:
; Compute intermediate values RP, RM, IP, IM
.asg AR2,XP_k
.asg AR3,XP_Nminusk
.asg AR6,XM_k
.asg AR7,XM_Nminusk
STM #fft_data+2,XP_k ; AR2 -> R[k] (temp RP[k])
STM #fft_data+2*K_FFT_SIZE-2,XP_Nminusk ; AR3 -> R[N-k] (tempRP[N-k])
STM #fft_data+2*K_FFT_SIZE+3,XM_Nminusk ; AR7 -> temp RM[N-k]
STM #fft_data+4*K_FFT_SIZE-1,XM_k ; AR6 -> temp RM[k]
STM #-2+K_FFT_SIZE/2,BRC
RPTBD phase3end-1
STM #3,AR0
ADD *XP_k,*XP_Nminusk,A ; A := R[k]+R[N-k] =2*RP[k]
SUB *XP_k,*XP_Nminusk,B ; B := R[k]-R[N-k] =2*RM[k]
STH A,ASM,*XP_k+ ; store RP[k] at AR[k]
STH A,ASM,*XP_Nminusk+ ; store RP[N-k]=RP[k] at AR[N-k]
STH B,ASM,*XM_k- ; store RM[k] at AI[2N-k]
NEG B ; B := R[N-k]-R[k] =2*RM[N-k]
STH B,ASM,*XM_Nminusk- ; store RM[N-k] at AI[N+k]
ADD *XP_k,*XP_Nminusk,A ; A := I[k]+I[N-k] =2*IP[k]
SUB *XP_k,*XP_Nminusk,B ; B := I[k]-I[N-k] =2*IM[k]
STH A,ASM,*XP_k+ ; store IP[k] at AI[k]
STH A,ASM,*XP_Nminusk-0 ; store IP[N-k]=IP[k] at AI[N-k]
STH B,ASM,*XM_k- ; store IM[k] at AR[2N-k]
NEG B ; B := I[N-k]-I[k] =2*IM[N-k]
STH B,ASM,*XM_Nminusk+0 ; store IM[N-k] at AR[N+k]
phase3end:
ST #0,*XM_k- ; RM[N/2]=0
ST #0,*XM_k ; IM[N/2]=0
; Compute AR[0],AI[0], AR[N], AI[N]
.asg AR2,AX_k
.asg AR4,IP_0
.asg AR5,AX_N
STM #fft_data,AX_k ; AR2 -> AR[0] (tempRP[0])
STM #fft_data+1,IP_0 ; AR4 -> AI[0] (tempIP[0])
STM #fft_data+2*K_FFT_SIZE+1,AX_N ; AR5 -> AI[N]
ADD *AX_k,*IP_0,A ; A := RP[0]+IP[0]
SUB *AX_k,*IP_0,B ; B := RP[0]-IP[0]
STH A,ASM,*AX_k+ ; AR[0] = (RP[0]+IP[0])/2
ST #0,*AX_k ; AI[0] = 0
MVDD *AX_k+,*AX_N- ; AI[N] = 0
STH B,ASM,*AX_N ; AR[N] = (RP[0]-IP[0])/2
; Compute final output values AR[k], AI[k]
.asg AR3,AX_2Nminusk
.asg AR4,COS
.asg AR5,SIN
STM #fft_data+4*K_FFT_SIZE-1,AX_2Nminusk ; AR3 -> AI[2N-1](temp RM[1])
STM #cosine+K_TWID_TBL_SIZE/K_FFT_SIZE,COS ; AR4 -> cos(k*pi/N)
STM #sine+K_TWID_TBL_SIZE/K_FFT_SIZE,SIN ; AR5 -> sin(k*pi/N)
STM #K_FFT_SIZE-2,BRC
RPTBD phase4end-1
STM #K_TWID_TBL_SIZE/K_FFT_SIZE,AR0 ; index of twiddle tables
LD *AX_k+,16,A ; A := RP[k] ||AR2->IP[k]
MACR *COS,*AX_k,A ; A :=A+cos(k*pi/N)*IP[k]
MASR *SIN,*AX_2Nminusk-,A ; A := A-sin(k*pi/N)*RM[k] || AR3->IM[k]
LD *AX_2Nminusk+,16,B ; B := IM[k] ||AR3->RM[k]
MASR *SIN+0%,*AX_k-,B ; B := B-sin(k*pi/N)*IP[k] || AR2->RP[k]
MASR *COS+0%,*AX_2Nminusk,B ; B := B-cos(k*pi/N)*RM[k]
STH A,ASM,*AX_k+ ; AR[k] = A/2
STH B,ASM,*AX_k+ ; AI[k] = B/2
NEG B ; B := -B
STH B,ASM,*AX_2Nminusk- ; AI[2N-k] = -AI[k]= B/2
STH A,ASM,*AX_2Nminusk- ; AR[2N-k] = AR[k] = A/2
phase4end:
RET ; returntoRealFFTmain module
;=====================================================
;Compute the Power Spectrum of the Complex Output of the 256-Point Real FFT
.asg AR2,AX
.asg AR3,OUTPUT_BUF
.def power
; .sect "pwr_prog"
power:
STM #data_output,OUTPUT_BUF ; AR3 points to output buffer
STM #K_FFT_SIZE*2-1,BRC
RPTBD power_end-1
STM #fft_data,AX ; AR2 points to AR[0]
SQUR *AX+,A ; A := AR^2
SQURA *AX+,A ; A := AR^2 + AI^2
STH A,*OUTPUT_BUF+
power_end:
RET ; return to main program
.def find
.asg AR2,POWER
.asg AR3,STORE
.asg AR4,INDEX
find:
STM #data_output,POWER
STM #data_find,STORE
STM #data_index,INDEX
LD #0,A
LD #0,B
STL A,*STORE
STM #K_FFT_SIZE*2-1,BRC
RPTB find_end-1
SUB *POWER,*STORE,A
BC next,ALEQ
MVDD *POWER,*STORE
STL B,*INDEX
next:
MAR *POWER+
ADD #1,B
find_end:
RET
.end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -