;-----------------------------------------------------------; ; HOSTSPEC.ASM ; ; Written By: Keith Larson ; ; TMS320Cxx DSP Applications Engineer ; ; Texas Instruments ; ; ; ; USE WITH THE DSKL [G]RAPH OPTION. THIS OPTION IS DESIGNED; ; TO RECEIVE A BYTE FROM THE DSK AND OUTPUT IT GRAPHICLY. ; ; RUNNING THIS PROGRAM ON DSKD WILL CRASH THE DEBUGGER! ; ; ; ; A spectrum analyzer using the DSK and your Host PC. ; ; This code does NOT work with DSKD! It is run from within ; ; DSKL using DSK_COMM to send data to the host via the RS232; ; link. It is slower than DSK_SPEC, but you do not need an ; ; oscilliscope! ; ; ; ; To run this program, first assemble it using DSKA. ; ; Then start DSKL, select 'X' for load and execute. Then ; ; select 'G' for graphics. To exit, hit any key (except Q) ; ; since the keyboard is not flushed and 'Q' will quit DSKL ; ; entirely! ; ;-----------------------------------------------------------; YES .set 1 ; NO .set 0 ; FFT_S .set 256 ; FFT_S-1 .set 255 ; FFT_S/2 .set 128 ; (FFT_S/2)-1 .set 127 ; ;-----------------------------------------------------------; AIC_1 .set 0x0C18 ;TB =TA = 6 0000110000011000=0x0C18 AIC_2 .set 0x0205 ;TA'=TA'= 1 0000001000000101=0x0205 AIC_3 .set 0x264e ;RB =TB = 0x13 0010011001001110=0x264c 44 khz AIC_CMD .set 0x0003 ; COMMAND 0000000000000011=0x0083 ;-----------------------------------------------------------; BCMD .set 0xFA10 ;JUMP CMD BXMIT .set 0xFA12 ;JUMP XMIT BXMIT16 .set 0xFA14 ;JUMP XMIT16 BRECV .set 0xFA16 ;JUMP RECV BRECV16 .set 0xFA18 ;JUMP RECV16 BCXMIT .set 0xFA1A ;JUMP CXMIT ;---------------------------------------------------------- STAT1 .set 0x72 ; ACCU_lo .set 0x78 ; ACCU_hi .set 0x79 ; REAL .set 0x7a ; IMAG .set 0x7b ; TEMPX .set 0x7c ; AUX0 .set 0x7d AUX1 .set 0x7e ;---------------------------------------------------------------- ; SECONDARY VECTOR TABLE LOACTED IN B0 PROGRAM RAM ;---------------------------------------------------------------- .include "mmregs.asm" ; > USERCODE SHOULD NOT OVERWRITE DSKD < .ps 0xfa00 ; > VECTORS. ON LOAD, INT2 IS RESTORED < ;B start ;RS > BY DSKD, BUT TRAP IS NOT < ;B start ;INT0 ;B start ;INT1 ;B start ;INT2 > DSKD LOAD IGNORES INT2 VECTOR ;B start ;TINT .ps 0fa0ah ; B RINT ;RINT Branch to receive interrupt routine eint ;XINT XINT is only for timing, so just return ret ; ; Begin TRAP/DSKD Kernal ;DSKD load does not restore this code! ;---------------------------------------------------------------- ; APPLICATION CODE IS LOCATED ABOVE DSKD KERNAL ;---------------------------------------------------------------- .ps 0xFB00 ; .entry ; ;---------------------------------------------------------------- start: sxf ssxm sovm ; catch accumulator overflows ldpk 0 ; All direct addressing is to MMRs and B2 fort 0 ; Serial port : 16 bit rtxm ; : ext. FSX sfsm ; ; burst mode lack 0x80 ; AIC reset by pulsing /BR (Global Data) sach DXR ; send 0 to DXR (AIC) sacl GREG ; 256 * 100 nS /BR pulse lrlk AR0,0xFFFF ; rptk 255 ; read junk from address 0xFFFF lac *,0,AR0 ; conf 1 ; B1,B3 as DRAM if direct bootload ;-------------------------------- AIC_RS lack 0x20 ; Turn on XINT sacl IMR ; idle ; lalk AIC_1 ; Load each AIC configuration word call AIC_2nd ; and load it into the AIC lalk AIC_2 ; call AIC_2nd ; lalk AIC_3 ; call AIC_2nd ; lalk AIC_CMD ; call AIC_2nd ; ;---------------------------------------------------------------- lark AR7,0 ; Buffer initialy filled lack 0x10 ; AIC RINT sacl IMR ; where INT0 indicates EOC (End Of Conv) ;--------------------------------------------------------------- lark AR7,0 ; Buffer initialy filled FFT: lrlk AR0,FFT_S/2 ; larp AR0 ; start FFT with AR0=FFTSize new_stg lrlk AR1,_D_base ; AR1 is the TOP BFLY address lrlk AR2,_D_base ; AR2 is the BOT BFLY address lrlk AR3,_T_base+1 ; AR3 is the TWiddle pointer lrlk AR4,FFT_S/2 ; AR4 counts DFT blocks b n_DFT2,*,AR1 ; DFT: mar *BR0+,AR5 ; complete circular buffer for TW's lark AR5,1 ; set up DFT loop with *BR0+/BANZ mar *BR0+,AR1 ; using 1 cuts *BR0+ loop in half! ;---------------------------------------- ; AR1=Top AR2=Bottom AR3=Twiddle ;---------------------------------------- BFLY: lac *,14,AR2 ;(imag1+imag2)/4 add *,14,AR1 ; sach *+,1,AR2 ;store TOP imag sub *,15 ;(imag1-imag2)/2 sach *+,1,AR1 ;store BOT imag lac *,14,AR2 ;(real1+real2)/4 add *,14,AR1 ; sach *+,1,AR2 ;store TOP real sub *,15 ;(real1-real2)/2 sach *,1,AR5 ;store BOT real banz OK,*BR0+,AR3 ;If at DFT end quit early ;------------------------ mar *+,AR2 ;clean up TW base (xxx0000+1) mar *+ ;modify BOTom DATA pointer mar *0+ ; mar *0+,AR1 ; n_DFT2: mar *0+ ;modify the TOP pointer mar *0+,AR4 ; banz DFT,*0-,AR3 ;dec DFT block count AR4 by OFFset larp AR0 ; mar *BR0+ ; banz new_stg,* ;if OFFset was 1, now cleared b endFFT ; ;------------------------- OK lt *-,AR2 ;TREG=TWR *NOTE* Twiddles are Q15 mpy *- ;PREG=REAL*TWR ltp *+,AR3 ;TREG=IMAG ACCU=REAL*TWR mpy * ;PREG=IMAG*TWI AR2=R AR3=I lts *+,AR2 ;TREG=TWI ACCU=REAL*TWR-IMAG*TWI mpy * ;PREG=REAL*TWI sach *-,1,AR2 ;<<; ltp *,AR3 ;TREG=IMAG ACCU=REAL*TWI mpy *BR0+,AR2 ;PREG=IMAG*TWR apac ; ACCU=IMAG*TWR+REAL*TWI sach *+,1,AR2 ;<<; b BFLY,*+,AR1 ; ;------------------------------------------------------------ endFFT: larp AR2 ;Transform REAL & IMAG to log magnitude lrlk AR2,_D_base ;AR3=FFT data pointer lrlk AR3,FFT_S-1 ;AR5=FFT loop counter lrlk AR0,FFT_S ;-----------------------------------------------------------; ; WINDOW: Performs post FFT raised cosine windowing! ; ; This is done by using the frequency coefficients of the ; ; window in a convolution filter of the spectrum. ; ;-----------------------------------------------------------; ;mar *BR0+ ; don't start at DC more_MAG mar *BR0- ; -IMAG[-1] 1-COS(nwt/N) + 1 lac *BR0+,15 ; IMAG[-0] filter by post | subh *BR0+ ; +IMAG[+1] convolution <--+++--> add *BR0-,15 ; IMAG + + -.5 sach IMAG ; mar *+ ; REAL mar *BR0- ; -REAL[-1] lac *BR0+,15 ; REAL[-0] X[-1] -2*X[0] + X[1] subh *BR0+ ; +REAL[+1] add *BR0-,15,AR1 ; REAL sach REAL ; sqra IMAG ;IMAG & REAL can be at most 0x7fff Q15 ltp REAL ;MPY will result (at most) in max positive mpy REAL ; apac ;output is positive Q30 addk 0x1 ;Set up a floor value; log(0) not legal! lark AR1,22 ;pre-scaling exponent shifts Y axis rptk 31 ; norm *- ; larp AR2 ; mar *BR0- ;-REAL;dump log(f) into oldest REAL (odd addr) sach *,2 ;clr explicit 1.0 and sign bit from mant zals * ;load into ACCU_lo sar AR1,* ;then append exponent (AR1) addh * ; rptk 10 ;jam result into ACCU_hi sfl ;If needed, Use ADDH to saturate overflow ; sach * ; ; addh * ; sach * ; lac * ; andk 0xfffc,0 ; sacl *BR0+ ; REAL mar *- ; IMAG mar *BR0+,AR3 ;+IMAG banz more_MAG,*-,AR2 ;keep going until all done ;-------------------------------------------------------- BITREV: lrlk AR0,FFT_S ;Now perform Output bit reversal lrlk AR1,_D_base ;by moving the magnitude, which lrlk AR2,_D_base+1 ;is in the REAL slots, into the lrlk AR3,FFT_S-1 ;IMAG slots of the FFT data array more_BR lac *+ ;load the magnitude mar *+,AR1 ; sacl *BR0+,0,AR3 ;move it to an open IMAG slot banz more_BR,*-,AR2 ;more data to move? ;-------------------------------------------------------- MOVE_IO larp AR7 ;wait until buffer is full banz MOVE_IO,*,AR2 ;(AR7 is decremented by ISR) ;------------------------ lrlk AR3,_D_base ;AR3=FFT data pointer lrlk AR4,_B_base ;AR4=BUFF data pointer lrlk AR5,FFT_S-1 ;AR5=FFT loop counter lrlk AR6,_B_base ;AR6=ISR BUFF data pointer lrlk AR7,FFT_S-1 ;AR7=ISR BUFF loop counter ;------------------------- dint zac call DAT2HOST larp AR2 more_IO lar AR2,*,AR3 ;Get A/D value from buffer lac *,0,AR4 ;ACCU= log magnitude (from even address) sacl *+,0,AR3 ; rptk 7 sfr ork 1 call DAT2HOST larp AR3 zac ; sach *+,0 ;IMAG=0 sar AR2,*+,AR5 ; banz more_IO,*-,AR4 ; eint ; BUFF clear so enable INT's b FFT ; ;----------------------------------------------------------------- RINT: sst1 STAT1 ;Recover ARP from ARB by LST1 last larp AR7 ;AR6 = current buffer position banz more_buf,*-,AR6 ;if buffer is full RET w/o EINT lark AR7,0 ; lst1 STAT1 ; ret ; more_buf ; sacl ACCU_lo ;Use NORM start val to adj Y offset sach ACCU_hi ;post log convert scaling ajsts magnitude zalh * ;Get value sach DXR ; ;------------------------ lac DRR ; bit TEMPX,15 ;Inverting every other input aliases the bbz NO_NVRT ;frequency domain, swapping DC and Nyquist! neg ; NO_NVRT ; sacl *+ ;<<< store DRR, and point to next lac TEMPX ; xork 1 ; sacl TEMPX ; zalh ACCU_hi ; adds ACCU_lo ; lst1 STAT1 ; eint ; ret ; ****************************************************************** AIC_2nd adlk 6,15 ;set ACCU_hi = 3 for secondary XMIT idle ;Wait for a XINT sach DXR ; idle ;ACCU_hi requests 2nd XMIT sacl DXR ; idle ;ACCU_lo sets up registers sacl DXR,2 ;close command with LSB = 00 idle ; eint ; ret ; ******************************************************************** DAT2HOST sacl ACCU_lo ; sach ACCU_hi ; sar AR0,AUX0 ; sar AR1,AUX1 ; call BXMIT ; zals ACCU_lo ; addh ACCU_hi ; lar AR0,AUX0 ; lar AR1,AUX1 ; ret ; ;==================================================================== .listoff ; .ds 0x400 ;NOTE: Twiddles are relocated to .include "dsk_twid.asm" ; 0x400 (B2) using CONF 1 .liston .end