📄 simd_fir_demo.asm
字号:
//---------------------------------------------------------------------------------------------------------
//
// (C) Copyright 2002 - Analog Devices, Inc. All rights reserved.
//
// File Name: FIR_Demo.asm
//
// Date Modified: 4/11/02 Rev 1.0
//
// Purpose: 21160 EZ-KIT LITE SIMDFIR digital filter
//
// Receives input from the AD1881 A/D's via the 21160 serial port (SPORT0),
// Filters the data using a Finite Impuse Response Filter, and then stores the
// output for the SPORT0 ISR to transmit the data back to the AD1881 D/A's.
// /
// The samples from the AD1881 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 SPORT0 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-21160 System Register bit definitions
#include <def21160.h>
.EXTERN Left_Channel_In;
.EXTERN Left_Channel_Out;
.EXTERN Right_Channel_In;
.EXTERN Right_Channel_Out;
// *** C preprocessor declarations (defines, includes, etc.) ***
#define FILTER_TAPS 67
#define DOUBLE_FILTER_TAPS 132
.segment /dm seg_dmda;
.VAR filtering = 1; // default is start off filtering
.VAR filter_counter = 2; // default is low-pass filter
.ALIGN 2;
.VAR dline [DOUBLE_FILTER_TAPS]; // delay line of input samples
.GLOBAL filtering;
.endseg;
//---------------------------------------------------------------------------
.segment /pm seg_pmda;
.ALIGN 2;
.VAR coef_bp_800Hz[FILTER_TAPS] = "Filter_BP_800_67.dat"; // declare and initialize the bandpass filter coefficients
.ALIGN 2;
.VAR coef_bp_2000Hz[FILTER_TAPS] = "Filter_BP_2000_67.dat"; // declare and initialize the bandpass filter coefficients
.ALIGN 2;
.VAR coef_bp_4kHz[FILTER_TAPS] = "Filter_BP_4000_67.dat"; // declare and initialize the bandpass filter coefficients
.endseg;
.segment /pm seg_pmco;
.GLOBAL init_fir_filter;
.GLOBAL fir;
.GLOBAL change_filter_coeffs;
.GLOBAL toggle_filtering;
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_bp_800Hz; l9 = @coef_bp_800Hz; // pointer to the bandpass filter coefficients
m9 = 1 ;
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_In); // get left input sample
r1 = DM(Right_Channel_In); // 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
do_filtering:
dm(i0,m1)=f0 (LW);
// Enable broadcast mode and also set the PEYEN.
bit set mode1 PEYEN | BDCST9;
bit clr mode1 IRPTEN;
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_Out) = r8; // send result to AD1881 DACs
DM(Right_Channel_Out) = r9;
rts;
fir.end:
// ------------------------------------------------------------------------------------
//
// IRQ2 Pushbutton Interrupt Service Routine
//
// This routine determines which FIR filter routine to execute.
// Pressing the IRQ2 pushbutton will toggle between each filter. The default
// is a bandpass filter(800Hz)
//
// To listen to unfiltered signal, hit the IRQ 1 pushbutton
// ------------------------------------------------------------------------------------
change_filter_coeffs:
bit set mode1 SRRFH; // enable background register file
NOP; // 1 CYCLE LATENCY FOR WRITING TO MODE1 REGISER!!
r11 = 3;
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;
if eq jump filter_select_3; // check for count == 1
filter_select_1: // count therefore, is == 2 if you are here
b9 = coef_bp_800Hz; l9 = @coef_bp_800Hz; // load 300 Hz lowpass filter coefficients
flags=0x9;
jump exit_IRQ_routine;
filter_select_2:
b9 = coef_bp_2000Hz; l9 = @coef_bp_2000Hz; // load 600 Hz lowpass filter coefficients
flags=0xA;
jump exit_IRQ_routine;
filter_select_3:
b9 = coef_bp_4kHz; l9 = @coef_bp_4kHz; // load 4000 Hz highpass filter coefficients
flags=0xC;
jump exit_IRQ_routine;
exit_IRQ_routine:
rti(db);
bit clr mode1 SRRFH; // switch back to primary register set
nop;
change_filter_coeffs.end:
// ------------------------------------------------------------------------------------
//
// IRQ1 Pushbutton Interrupt Service Routine
//
// This routine will toggle between a filter and no filter
//
// ------------------------------------------------------------------------------------
toggle_filtering:
bit set mode1 SRRFH; // enable background register file
NOP;
R1 = 0x0; // clear R1
R0 = dm(filtering); // get previous value
comp(R0,R1); // compare the values
if eq jump set_filtering; // if they are equal then set to filtering
R0 = 0x0; // set to no filtering
dm(filtering) = R0;
jump exit_toggle_filtering;
set_filtering:
R0 = 0x1; // set to filtering
dm(filtering) = R0;
exit_toggle_filtering:
rti(db);
bit clr mode1 SRRFH; // switch back to primary register set
nop;
toggle_filtering.end:
.endseg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -