FFTR2BF macro points,passes,data,twiddle,temp ; ; Radix 2 Decimation-in-Time In-Place Block Floating Point ; Fast Fourier Transform Macro ; ; Version with 2 butterflies, scratch storage ; ; Complex input and output data ; Real data in X memory ; Imaginary data in Y memory ; Normally ordered input data ; Bit reversed output data ; Twiddle factors lookup table ; Cosine value in X memory ; -Sine value in Y memory ; ; Macro Call - FFTR2BF points,passes,data,twiddle ; ; points number of points (4-32768, power of 2) ; passes number of fft passes (log2 points) ; data start of data buffer ; twiddle start of sine/cosine table ; temp low address of four consecutive x:y scratch memory ; (should be internal memory for fast program operation) ; on output, x:(temp)+2 contains the number of bits scaled; ; x:(temp)+3 shows, in base-4, the number of bits scaled per ; each stage ; ; Alters Data ALU Registers ; x1 x0 y1 y0 ; a2 a1 a0 a ; b2 b1 b0 b ; ; Alters Address Registers ; r0 n0 m0 ; r1 n1 m1 ; r2 n2 m2 ; r3 n3 m3 ; ; r4 n4 m4 ; r5 n5 m5 ; r6 n6 m6 ; r7 n7 m7 ; ; Alters Program Control Registers ; pc sr ; ; Uses 11 locations on System Stack ; ; Latest Revision - June 13, 1988 ; move #temp+2,r2 ;initialize temporary data storage pointer clr a ;initialize the number of bits scaled to zero move a,x:(r2)+ move a,x:(r2) move #1,n2 ;initialize groups per pass nop move n2,y:(r2) ;initialize stage overflow indicator move #temp,r2 ;initialize temporary data storage pointer move #points,n0 ;initialize butterflies per group move #-1,m0 ;initialize address modifier for linear addressing move #points/4,n6 ;initialize twiddle offset move m0,m1 ;initialize address modifiers for linear addressing move m0,m4 move m0,m5 move m0,m2 move m0,m3 move m0,m7 move #0,m6 ;initialize twiddle factor address modifier ; for reverse carry (bit reversed) addressing ; ; Perform all FFT passes with triple nested DO loop ; do #passes,_end_pass move n0,a1 ;divide butterflies per group by two lsr a #data,r0 ;and initialize A input pointer move a1,n0 ;update butterflies per group move r0,r4 ;initialize A output pointer lua (r0)+n0,r1 ;initialize B input pointer move n0,n1 move r1,r5 ;initialize B output pointer move n0,n4 ;initialize pointer offsets move n0,n5 move x:(r0),x0 ;clear downshift flag movec sr,x:(r0) bclr #10,x:(r0) movec x:(r0),sr move x0,x:(r0) move n2,r6 ;get group count move m0,m6 ;set linear addressing move y:(r0),b ;do t.f.=1 butterflies move y:(r1),a sub a,b ab,l:(r2)+ do n0,_end_bf0 addl b,a x:(r0)+,b b,y:(r5) move x:(r1)+,a a,y:(r4) sub a,b ab,l:(r2)- addl b,a b,x:(r5)+ y:(r0),b move a,x:(r4)+ y:(r1),a jls _ov_bf0_go ;test for overflow--FORCE SHORT JUMP WHEN POSSIBLE _ov_bf0_ret sub a,b ab,l:(r2)+ _end_bf0 lua (r2)-,r2 lua (r6)-,r6 ;update pointers and test for no more groups lua (r4)+n4,r4 move #0,m6 ;set bit-reverse mode for t.f. move r6,a move r6,n7 ;save group counter move #twiddle,r6 lua (r0)+n0,r0 lua (r1)+n1,r1 lua (r6)+n6,r6 tst a (r5)+n5 jle _sk_grp do n7,_end_grp ;do the normal butterflies move r2,r7 ;set pointer to temp storage move x:(r1),x1 y:(r6),y0 ;lookup -sine value move x:(r6)+n6,x0 y:(r0),b ;lookup cosine value mac x1,y0,b b,x:(r7)+ y:(r1)+,y1 ;Radix 2 DIT butterfly kernel do n0,_end_bf2 macr x0,y1,b x1,x:(r7)- y:(r0),a subl b,a x:(r0),b b,y:(r4) mac x1,x0,b x:(r1),x1 b,y:(r7) macr -y1,y0,b x:(r0)+,a a,y:(r5) subl b,a b,x:(r4)+ move a,x:(r5)+ y:(r0),b jls _ov_bf2_go ;test for overflow --FORCE SHORT JUMP WHEN POSSIBLE _ov_bf2_ret mac x1,y0,b b,x:(r7)+ y:(r1)+,y1 _end_bf2 lua (r1)-,r1 lua (r5)+n5,r5 ;update data pointers lua (r1)+n1,r1 lua (r0)+n0,r0 lua (r4)+n4,r4 _end_grp _sk_grp move n2,a1 lsl a ;multiply groups per pass by two move a1,n2 ;update groups per pass move #temp+3,r2 nop move y:(r2),a1 lsl a lsl a move a1,y:(r2) move #temp,r2 _end_pass move x:(r0),x0 ;clear downshift flag movec sr,x:(r0) bclr #10,x:(r0) movec x:(r0),sr move x0,x:(r0) jmp _bsfft_end ; ; OVERFLOW MANAGEMENT CODE ; ; ; overflow correction code, full butterfly ; _ov_bf2_go lua (r4)-,r7 lua (r5)-,r3 movec sr,y:(r7) ;reset limit flag bclr #6,y:(r7) movec y:(r7),sr jclr #10,y:(r7),_bf2_ndov ;double overflow, previous overflow jsr _c_ov ;increment the scaling counter jsr _d_sc ;scale all the data lua (r5)-,r3 move y1,a ;scale down data element move x:(r2)+,b a,y1 ;recompute butterfly move x:(r2)-,a move a,x1 mac x1,y0,b macr x0,y1,b x:(r2),a subl b,a b,y:(r7) move y:(r2),b mac x1,x0,b a,y:(r3) macr -y1,y0,b y:(r2),a subl b,a b,x:(r7) move a,x:(r3) move x:(r1),x1 ;reload data for next butterfly move y:(r0),b move r2,r7 ;recover temp storage pointer jmp _ov_bf2_ret _bf2_ndov bset #10,y:(r7) ;set downshift movec y:(r7),sr jsr _c_ov ;increment the scaling counter move x:(r2)+,b ;recompute butterfly move x:(r2)-,x1 mac x1,y0,b macr x0,y1,b x:(r2),a subl b,a b,y:(r7) move y:(r2),b mac x1,x0,b a,y:(r3) macr -y1,y0,b y:(r2),a subl b,a b,x:(r7) move a,x:(r3) jlc _bf2_sk_1 ;double overflow, NO previous overflow movec sr,y:(r7) ;reset limit bit bclr #6,y:(r7) movec y:(r7),sr jsr _c_ov ;increment the scaling counter jsr _d_sc ;scale all the data down by one bit lua (r5)-,r3 move x:(r2)+,b ;recompute butterfly move x:(r2)-,x1 mac x1,y0,b macr x0,y1,b x:(r2),a asr b asr a subl b,a b,y:(r7) move y:(r2),b mac x1,x0,b a,y:(r3) macr -y1,y0,b y:(r2),a asr b asr a subl b,a b,x:(r7) move a,x:(r3) _bf2_sk_1 jsr _pb_sc ;scale previously completed butterflies move x:(r1),x1 ;reload data for next butterfly move y:(r0),b move r2,r7 ;recover temp storage pointer jmp _ov_bf2_ret ;return to the butterfly loop ; ; butterfly 0 overflow correction code ; _ov_bf0_go lua (r4)-,r7 ;recover data addresses lua (r5)-,r3 movec sr,x:(r7) ;reset limit flag bclr #6,x:(r7) bset #10,x:(r7) ;set downshift movec x:(r7),sr jsr _c_ov ;increment the scaling counter move l:(r2)+,ab ;recompute butterfly sub a,b addl b,a b,y:(r3) move a,y:(r7) move l:(r2)-,ab sub a,b addl b,a b,x:(r3) move a,x:(r7) move #data,r3 ;set index registers move n0,n3 move n0,n7 lua (r3)+n3,r7 move lc,a ;get butterfly loop count move n0,b ;compute number of butterflies to scale sub a,b jle _bf0_b_sk lsl b ;precorrect for shift do b,_bf0_spb ;scale these butterflies move x:(r3),a y:(r7),b move a,x:(r3) b,y:(r7) move y:(r3),a x:(r7),b move a,y:(r3)+ b,x:(r7)+ _bf0_spb _bf0_b_sk move y:(r0),b ;recover data for next butterfly move y:(r1),a jmp _ov_bf0_ret ;return to the butterfly loop ; ; SUBROUTINES ; ; _d_sc: Subroutine to scale down the entire stage by a factor of ; two in the event of a second overflow in a stage. ; _d_sc move #data,r3 ;set pointer to start of data do #points,_sc_lp move l:(r3),ab move ab,l:(r3)+ _sc_lp rts ; ; _pb_sc Subroutine to scale previously completed butterflies ; _pb_sc move #2,r3 ;set stack pointer to group loop counter movec sp,a move r3,b movec sp,r3 ;save stack pointer sub b,a lsl a movec a,sp move n2,a ;compute number of completed groups movec ssl,b move n2,a sub b,a movec r3,sp ;restore stack pointer move #data,r3 ;set index registers move n0,n3 move n0,n7 lua (r3)+n3,r7 jle _pb_g_sk lsl a ;precorrect loop count for shift do a,_pb_glp ;scale down these groups do n0,_pb_blp_1 move x:(r3),a y:(r7),b move a,x:(r3) b,y:(r7) move y:(r3),a x:(r7),b move a,y:(r3)+ b,x:(r7)+ _pb_blp_1 lua (r3)+n3,r3 lua (r7)+n7,r7 _pb_glp _pb_g_sk move lc,a ;get butterfly loop count move n0,b ;compute number of butterflies to scale sub a,b jle _pb_b_sk lsl b ;precorrect for shift do b,_pb_blp_2 ;scale these butterflies move x:(r3),a y:(r7),b move a,x:(r3) b,y:(r7) move y:(r3),a x:(r7),b move a,y:(r3)+ b,x:(r7)+ _pb_blp_2 _pb_b_sk rts ; ; _c_ov: Subroutine to increment the number-of-bits-scaled counter ; _c_ov move #temp+2,r2 ;change pointer to (temp)+2 nop move r3,y:(r2) ;save r3 move x:(r2),r3 ;increment number-of-bits-scaled nop lua (r3)+,r3 nop move r3,x:(r2) ;store number-of-bits-scaled move y:(r2)+,r3 ;restore r3 and reset (temp) pointer move l:(r2),ab add b,a lsl a move a,x:(r2) move #temp,r2 rts _bsfft_end endm^Z