{___________________________________________________________________________ INTFFIR.ASM This demo allows the user to interactively specify a FIR filter and see its results. ___________________________________________________________________________} #include "demo.h" .EXTERN rfft2, irfft2; .EXTERN exponential; .EXTERN win_dat, log_mag; .GLOBAL intffir; .SEGMENT/PM pm_sram; .VAR retrans[PNTS/2+1]; {ffir real transfer func} .EXTERN odreal; .EXTERN imfft; .ENDSEG; .SEGMENT/DM dm_sram; .VAR imtrans[PNTS/2+1]; {ffir imag transfer func} .EXTERN inbufptr; {points to nxt sample spot in *inleft*} .EXTERN fullbuf; {signals if outbuffer is full or not} .EXTERN orgvalue; {original value of freq bin that the cursor points to} .EXTERN inleft; {audio left channel input buffer} .EXTERN inright; {audio right channel input buffer} .EXTERN tmpright; {temporary storage} .EXTERN outleft; {audio left channel output buffer} .EXTERN outright; {audio right channel output buffer} .EXTERN real; .EXTERN refft; {this better be on a boundry!} .EXTERN adacbuf; {output buffer for DAC A} .EXTERN bdacbuf; {output buffer for DAC B} .EXTERN aadc_dat; {input sample for ADC A} .EXTERN badc_dat; {input sample for ADC A} .ENDSEG; .SEGMENT/PM pm_sram; intffir: do (pc,3) until not flag0_in; {wait for flag0 depressed} nop; nop; nop; ustat1=CNFG_FFIR; {setup ustat1 for this routine} r1=0; r1=UNITY*0x1000000; b1=bdacbuf; {initialization for cursor routine} l1=PNTS/2+1; dm(curbin)=i1; dm(curbuffer)=i1; dm(orgvalue)=r0; lcntr=PNTS/2+1, do (pc,1) until lce; {clear bdacbuf} dm(i1,1)=r1; lcntr=TAPS/2+1, do (pc,1) until lce; {zero freq field} dm(i1,1)=r0; {modify buffer lengths of hip_rnt} bit set mode1 SRD1L|SRRFL; {set alternate DAG 0-3} nop; b2=outleft; l2=2*SEG; b3=outright; l3=l2; r3=SEG; bit clr mode1 SRD1L|SRRFL; {back to regular DAG 0-3, R(0-7) registers} nop; again: r0=0x0; do waitloop until forever; {wait for output buffer to be outputed} bit tst ustat1 OUTBH; if tf jump (pc,3) (la), r0=pass r0; bit tst ustat1 OUTBF; waitloop: if tf jump (pc,1) (la), r0=r0+1; cont: bit set astat FLG1; {turn-on analog load meter} dm(fullbuf)=r0; {signal if buffer is full} {move data out of input buffer} r0=dm(inbufptr); {get the inaudio buffer pointer} b6 = inleft; i6 = r0; l6 = PNTS; b7 = real; l7 = 0; m1 = 1; r15=-32; r1=dm(i6,m1); lcntr=PNTS, do (pc,2) until lce; f2=float r1 by r15, r1=dm(i6,m1); dm(i7,m1)=f2; {do the fft} call rfft2; {do the N/2+1 complex multiplications with the transfer funct.} i0=refft; i1=imtrans; i2=refft; l0=0x0; l1=l0; l2=l0; m1=1; i8=retrans; i9=imfft; i10=imfft; l8=0x0; l9=l8; l10=l8; m8=1; f0=dm(i0,m1), f4=pm(i8,m8); f8=f0*f4, f5=dm(i1,m1), f1=pm(i9,m8); f12=f1*f5; f9=f0*f5, f11=f8-f12; f13=f1*f4, f0=dm(i0,m1), f4=pm(i8,m8); lcntr=PNTS/2, do multil until lce; f8=f0*f4, f15=f9+f13, f5=dm(i1,m1), f1=pm(i9,m8); f12=f1*f5, dm(i2,m1)=f11; f9=f0*f5, f11=f8-f12, pm(i10,m8)=f15; multil: f13=f1*f4, f0=dm(i0,m1), f4=pm(i8,m8); f15=f9+f13, dm(i2,m1)=f11; pm(i10,m8)=f15; {do the inverse fft} call irfft2; {move the results to the output buffer} i2=outleft; {put data in outleft or outleft+SEG? } r1=outleft+SEG; r0=dm(fullbuf); r0=pass r0; if ne i2=r1; {if full buffer, put data in outleft+SEG} i0 = real+TAPS/2; m1 = 1; i8 = odreal+TAPS/2; m8 = 1; l0 = 0x0; l8 = l0; l2 = l0; r15= -LOGPNTS+1+32; {-LOGPNTS+1 for 2/N inv FFT scaling} r3=SEG; {test if SEG is even or odd} btst r3 by 0x0; if sz jump even; odd: f1=pm(-1,i8); {get the odd sample} r9=fix f1 by r15; {convert it and write it} dm(i2,m1)=r9; even: f0=dm(i0,m1), f1=pm(i8,m8); r8=fix f0 by r15; r9=fix f1 by r15; lcntr=SEG/2, do (pc,3) until lce; f0=dm(i0,m1), f1=pm(i8,m8); r8=fix f0 by r15, dm(i2,m1)=r8; r9=fix f1 by r15, dm(i2,m1)=r9; {Display spectrum of the output} call shw_spect; {Update FFIR filter transfer functions} call newffir; bit tst ustat1 IRQED; if not tf jump clnup; {irq1 clears out the filter} bit clr ustat1 IRQED; b1=bdacbuf; {initialization for cursor routine} l1=PNTS/2+1; r0=0; lcntr=TAPS/2+1, do (pc,1) until lce; {zero freq field} dm(i1,1)=r0; dm(orgvalue)=r0; {also clear orgvalue} clnup: bit clr astat FLG1; {turn-off analog load meter} bit tst ustat1 FLIRQ; if not tf jump again; {do it again if not finished} {restore the normal operation of the hip routine} bit set mode1 SRD1L|SRRFL; {set alternate DAG 0-3} nop; l2=2*PNTS; l3=l2; r3=PNTS; bit clr mode1 SRD1L|SRRFL; {back to regular DAG 0-3, R(0-7) registers} nop; rts; nop; nop; {___________________________________________________________________________ SHW_SPECT This routine shows the logrithmic Spectrum of the output signal. ____________________________________________________________________________} shw_spect: {move left audio data in *outleft* to *real* buffer} b0=outleft; {src pointer to *outleft*} r1=outleft+SEG; b4=real; {destination ptr to *real*} r0=dm(fullbuf); {find out if it is a full buffer or not} r0=pass r0; if eq i0=r1; {if half buffer, start getting data at the half} l0=2*SEG; l4=PNTS; m1=1; {Move data to processing buffers, do fixed to float conversion} r15=FSCL; r0=dm(i0,m1); lcntr=PNTS, do fconv until lce; f4=float r0 by r15, r0=dm(i0,m1); fconv: dm(i4,m1)=f4; {perform Blackman-Harris windowing on left audio data in *real*} b0=real; {src pointer to *real*} l0=PNTS; i4=real+PNTS-1; {src backward pointer to *real*} l4=0; call win_dat; {perform the FFT of the left audio data} call rfft2; {do 2*log2 on FFT data and put it in adacbuf} b1=adacbuf; {destination buffer} l1=PNTS/2+1; call log_mag; rts; nop; nop; {___________________________________________________________________________ NEWFFIR This routine gets data from the first half of *bdacbuf* (put there by the cursor routine), shows its time domain transform, and recalculates the ffir coefficients specified by the data. ____________________________________________________________________________} newffir: {unlog and scale data in *bdacbuf* and place it in *refft*, zero *imfft*} b0=bdacbuf; l0=0; b1=refft; l1=0; m1=1; b8=imfft; m8=1; l3=0; {This is for the exponential routine} r5=UNITY; {Define log(1.0) level } f6=(DRNG/(256.0*20.0))*2.30258509299; {ln(10)= 2.30258509299 } {coeff to convert from db to a loge } f13=(2.0/PNTS)*(PNTS/(TAPS-1)); {inv FFT scaling } r14=-24; r15=0x0; {zeros to fill *imfft*} r9=dm(i0,m1); r4=lshift r9 by -24; {shift data down for calcs} r3=r4-r5; {apply log bias} lcntr=TAPS/2, do unlog_re until lce; call exponential (db); {calc exp(f0) } f1=float r3; {convert to float} f0=f1*f6,r9=dm(i0,m1); {translate to from db to loge} f0=f0*f13; r4=lshift r9 by r14, dm(i1,m1)=f0, pm(i8,m8)=f15; {store it} lcntr=(PNTS/(TAPS-1))-1, do (pc,1) until lce; dm(i1,m1)=f15, pm(i8,m8)=f15; {expand spectra filling FFT length} unlog_re: r3=r4-r5; {apply log bias} {write PNTS/2+1 th point of FFT} call exponential (db); {calc exp(f0) } f1=float r3; {convert to float} f0=f1*f6; {translate to from db to loge} f0=f0*f13; dm(i1,m1)=f0, pm(i8,m8)=f15; {store it} {do the inverse FFT} call irfft2; {display the taps and move it to *real* in prep for FFT} b0=real; i0=real+TAPS/4; l0=TAPS/2; b1=tmpright; l1=0; b2=bdacbuf; i2=bdacbuf+PNTS/4; l2=PNTS/2+1; m1=1; b8=odreal; i8=odreal+TAPS/4; l8=TAPS/2; m8=1; f2=0.5; r11=TAPSCL; { tap display scaling } r13=24; r14=0xf0; r15=0x78; f0=dm(i0,m1); f0=f0*f2; {to split center tap} lcntr=TAPS/2, do taplp until lce; {do even sample} r4=fix f0 by r11; r8=r4+r15, dm(i1,m1)=f0; r8=clip r8 by r14; r9=lshift r8 by r13, f0=pm(i8,m8); {do odd sample} r4=fix f0 by r11, dm(i2,m1)=r9; r8=r4+r15, dm(i1,m1)=f0; r8=clip r8 by r14; r9=lshift r8 by r13, f0=dm(i0,m1); taplp: dm(i2,m1)=r9; {do the last (split) tap} f0=f0*f2; {split center tap} r4=fix f0 by r11, dm(i1,m1)=f0; r8=r4+r15; r8=clip r8 by r14; r9=lshift r8 by r13; dm(i2,m1)=r9; {load-up *real* in prep for FFT to get FFIR coeffiecients} i0=real; l0=0; i1=tmpright; r15=0x0; lcntr=TAPS, do (pc,2) until lce; f0=dm(i1,m1); dm(i0,m1)=f0; {fill the rest of *real* with zeros} lcntr=PNTS-TAPS, do (pc,1) until lce; dm(i0,m1)=f15; {do the fft} call rfft2; {transfer the new FFIR coefficients to *retrans* and *imtrans*} b0=refft; l0=0; b1=imtrans; l1=0; m1=1; b8=imfft; l8=0; b9=retrans; l9=0; m8=1; lcntr=PNTS/2+1, do (pc,2) until lce; f0=dm(i0,m1), f8=pm(i8,m8); dm(i1,m1)=f8, pm(i9,m8)=f0; rts; nop; nop; .ENDSEG;