/* /////////////////////////////////////////////////////////////////////////////////// / FIR_Demo.asm 21161 EZ-KIT LITE SIMDFIR digital filter / / / / Receives input from the AD1836 A/D's via the 21161 serial port (SPORT1), / / Filters the data using a Finite Impuse Response Filter, and then stores the / / output for the SPORT1 ISR to transmit the data back to the AD1836 D/A's. / / / / The digital filter coefficients are in the files "high1.dat" and "low1.dat" / / / / The samples from the AD1836 are 24-bits and are are converted to / / floating point numbers. The values are also scaled to the range +/-1.0 / / with the integer to float conversion (f0 = float r0 by r1). / / / / The digital filtering takes place in the SPORT1 transmit interrupt service / / routine. / / / / See the "ADSP-21000 Family Applications Handbook Vol. 1" for more information / / regarding the implementation of digital filters (chapter 4) / / / / / /////////////////////////////////////////////////////////////////////////////////// */ /* ADSP-21161 System Register bit definitions */ #include "def21161.h" /* *** C preprocessor declarations (defines, includes, etc.) *** */ #define DOUBLE_FILTER_TAPS 130 #define FILTER_TAPS 65 .section /dm dm_data; .VAR filter_counter = 0; /* default is low-pass filter */ .ALIGN 2; .VAR dline [DOUBLE_FILTER_TAPS]; /* delay line of input samples */ /*---------------------------------------------------------------------------*/ .section /pm pm_data; /* declare and initialize the interleaved lowpass & highpass filter coefficients*/ .ALIGN 2; .VAR coef_lo[DOUBLE_FILTER_TAPS] = "interleaved_coeffsLP_300&600Hz.dat"; .ALIGN 2; .VAR coef_hi[DOUBLE_FILTER_TAPS] = "interleaved_coeffsHP_4&8kHz.dat"; /* "interleaved_coeffsLP_300&600Hz.dat" contains the coefficients for a stereo/interleaved low pass filter and "interleaved_coeffsHP_4&8kHz.dat" contains the coefficients for a stereo/interleaved high pass filter */ .section /pm pm_code; .GLOBAL init_fir_filter; .GLOBAL fir; .GLOBAL change_filter_coeffs; .EXTERN RX_left_flag; .EXTERN Left_Channel_In1; .EXTERN Right_Channel_In1; .EXTERN Left_Channel_Out0; .EXTERN Right_Channel_Out0; .EXTERN Left_Channel_Out1; .EXTERN Right_Channel_Out1; init_fir_filter: bit set mode1 CBUFEN ; nop ; /* initialize the DAGS */ b0 = dline; l0 = @dline; /* pointer to the samples (delay line) */ m1 = 2; b9 = coef_lo; l9 = @coef_lo; /* pointer to the highpass filter coefficients */ m9 = 2 ; i3=dline; l3=@dline; r12=r12 xor r12; /* clear the delay line */ bit set mode1 PEYEN ; lcntr=FILTER_TAPS, do clear until lce; clear: dm(i3,2)=f12; bit clr mode1 PEYEN ; rts; init_fir_filter.end: /* //////////////////////////////////////////////////////////////////////////////// * * FIR filter subroutine * * //////////////////////////////////////////////////////////////////////////////// */ fir: /* process Left Channel Input */ r2 = -31; /* scale the sample to the range of +/-1.0 */ r0 = DM(Left_Channel_In1); /* get left input sample */ r1 = DM(Right_Channel_In1); /* get right input sample */ f0 = float r0 by r2 ; /* and convert to floating point */ f1 = float r1 by r2 ; /* and convert to floating point */ f8 = f0; /* in case we are in bypass mode, copy to output */ f9 = f1; /* in case we are in bypass mode, copy to output */ if FLAG2_IN jump exit_filter; do_filtering: dm(i0,m1)=f0 (LW); // Enable broadcast mode and also set the PEYEN, disable I9 Broadcast Mode since we have interleaved coeffs bit set mode1 PEYEN; bit clr mode1 IRPTEN | BDCST9; r12=r12 xor r12; /* clear f12,put sample in delay line */ f8=pass f12, f0=dm(i0,m1), f4=pm(i9,m9);/* clear f8,get data & coef */ lcntr=FILTER_TAPS-1, do macloop until lce; macloop: f12=f0*f4, f8=f8+f12, f0=dm(i0,m1), f4=pm(i9,m9); f12=f0*f4, f8=f8+f12; /* perform the last multiply */ f8=f8+f12; /* perform the last accumulate */ bit clr mode1 PEYEN | BDCST9; bit set mode1 IRPTEN; r9 = s8; exit_filter: r1 = 31; /* scale the result back up to MSBs */ r8 = fix f8 by r1; /* convert back to fixed point */ r9 = fix f9 by r1; /* Convert back to fixed point */ DM(Left_Channel_Out0) = r8; /* send result to AD1836 DACs */ DM(Right_Channel_Out0) = r9; DM(Left_Channel_Out1) = r8; /* send result to AD1836 DACs */ DM(Right_Channel_Out1) = r9; rts; fir.end: /* ------------------------------------------------------------------------------------ */ /* */ /* IRQ2 Pushbutton Interrupt Service Routine */ /* */ /* This routine determines which FIR filter routine to execute. */ /* Pressing the IRQ1 pushbutton will toggle between each filter. The default */ /* is a lowpass filter */ /* */ /* To listen to unfiltered signal, hit the FLAG 3 pushbutton */ /* ------------------------------------------------------------------------------------ */ change_filter_coeffs: bit set mode1 SRRFH; /* enable background register file */ NOP; /* 1 CYCLE LATENCY FOR WRITING TO MODE1 REGISER!! */ r11 = 2; r10 = DM(filter_counter); /* get last count from memory */ r10 = r10 + 1; /* increment preset */ comp (r10, r11); /* compare current count to max count */ if ge r10 = r10 - r10; /* if count equals max, reset to zero and start over */ DM(filter_counter) = r10; /* save updated count */ r15 = pass r10; /* get FIR filter preset mode ID */ if eq jump filter_select_2; /* check for count == 0 */ r10 = r10 - 1; r10 = pass r10; filter_select_1: /* count therefore, is == 1 if you are here */ b9 = coef_lo; l9 = @coef_lo; /* pointer to the interleaved lowpass filter coefficients */ ustat1=dm(IOFLAG); bit clr ustat1 0x3E; /* turn on Flag4 LED */ bit set ustat1 0x01; dm(IOFLAG)=ustat1; jump exit_IRQ_routine; filter_select_2: b9 = coef_hi; l9 = @coef_hi; /* pointer to the interleaved lowpass filter coefficients */ ustat1=dm(IOFLAG); bit clr ustat1 0x3D; /* turn on Flag5 LED */ bit set ustat1 0x02; dm(IOFLAG)=ustat1; exit_IRQ_routine: rti(db); bit clr mode1 SRRFH; /* switch back to primary register set */ nop; change_filter_coeffs.end: