page 132 ;****************************************************** ;****************************************************** ;* * ;* DUAL 10-BAND IIR BAND- * ;* PASS FILTER GRAPHIC EQUALIZER * ;* * ;****************************************************** ;****************************************************** ; ;************************************************************************** ; This program was originally available on the Motorola DSP bulletin board ; and is provided under a DISCLAIMER OF WARRANTY available from Motorola ; DSP Operation, 6501 William Cannon Dr. W Austin, Texas 78735-8598. ;************************************************************************** ;-------------------------------------------------------------------------- ;******************************** ;* SSI and other I/O EQUATES * ;******************************** START EQU $0040 M_IPR EQU $FFFF M_BCR EQU $FFFE M_CRA EQU $FFEC M_CRB EQU $FFED M_PCC EQU $FFE1 M_SR EQU $FFEE M_TX EQU $FFEF M_RX EQU $FFEF ;******************************** ;* RESET VECTOR * ;******************************** ORG P:$0000 JMP START ;******************************** ;* SSI RCV INTERRUPT VECTOR * ;******************************** ORG P:$000C JSR LRTEST ORG P:$000E JSR LRTEST ;******************************** ;* MAIN PROGRAM * ;******************************** ORG P:START ;------------------- ; Mask Interrupts ;------------------- ORI #$03,MR ;----------------------- ; Initialize SSI Port ;----------------------- MOVEP #$3300,X:M_BCR ;3 wait states for ADC and MUX. MOVEP #$3000,X:M_IPR ;SSI RCV INT priority level. MOVEP #$6000,X:M_CRA ;Set SSI word length = 24. MOVEP #$3200,X:M_CRB ;Set SSI to synchronous, ;and enable RE and TE. MOVEP #$01FF,X:M_PCC ;Turn on SSI Port. ;----------------------------------------------- ; Move constants from P:mem to X:mem and Y:mem ;----------------------------------------------- MOVE #$18D,R2 ;** Filter Coefficients. MOVE #$20,R3 ;Table located at X:$20. DO #30,COLOOP ;Length of table = 30. MOVE P:(R2)+,X0 ;Order is ... beta, alpha, MOVE X0,X:(R3)+ ;gamma for each band. COLOOP MOVE #$1AB,R2 ;** Filter Gain Look-up. MOVE #$40,R3 ;Table located at X:$40. DO #32,FGLOOP ;Length of table = 32 (5 bits). MOVE P:(R2)+,X0 ;Minimum value is -.2, maximum MOVE X0,X:(R3)+ ;value is 0.999, center value is 0. FGLOOP MOVE #$1CB,R2 ;** Volume Gain Look-up. MOVE #$60,R3 ;Table located at X:$60. DO #32,VGLOOP ;Length of table = 32 (5 bits). MOVE P:(R2)+,X0 ;Minimum value is 0, maximum MOVE X0,X:(R3)+ ;value is 0.9999. VGLOOP MOVE #$1EB,R2 ;** Mux Sel Address. MOVE #0,R3 ;Table located at Y:$00. DO #21,MSLOOP ;Length of table = 21. MOVE P:(R2)+,X0 ;These are the MUX select addresses MOVE X0,Y:(R3)+ ;for each of the 21 slide pots. MSLOOP ;------------------------- ; Set runtime variables ;------------------------- MOVE #$200000,X0 ;Constants used for data scaling. MOVE X0,X:>$1D MOVE #>$80,X0 MOVE X0,X:>$1E ;------------------------------------ ; Clear x(n) and y(n) table arrays ;------------------------------------ CLR A ;Clear Y:$20 to Y:$BF. MOVE #$20,R2 ;This area is used for runtime DO #$A0,XYNCLR ;tables, x(n) and y(n). MOVE A,Y:(R2)+ ;X:$20..$22 - x(n) left chan. XYNCLR ;X:$40..$42 - y(n) left chan. 31 Hz. ;X:$44..$46 - y(n) left chan. 62 Hz. ; .... ;X:$60..$62 - y(n) left chan. 16 kHz. ;X:$30..$32 - x(n) right chan. ;X:$80..$82 - y(n) right chan. 31 Hz. ;X:$84..$86 - y(n) right chan. 62 Hz. ; .... ;X:$A0..$A2 - y(n) right chan. 16 kHz. ;------------------------------- ; Clear g(n) and SP(n) arrays ;------------------------------- CLR A ;Clear X:$00 to X:$14. MOVE #0,R2 ;This is gain array which contains ;fractional gain value from look-up DO #21,GNCLR ;table used to scale filtered band. MOVE A,X:(R2)+ GNCLR MOVE #$80,R2 ;Clear X:$80 to X:$94. ;This is 8-bit value read from DO #21,SWNCLR ;ADC slide pots. This value when MOVE A,X:(R2)+ ;reduced to 5 bits is used as an SWNCLR ;index into gain lookup table at ;X:$40. The value from lookup table ;is a 24-bit fraction which is stored ;at X:$00..$X:$14. ;-------------------------------------------------- ; Setup Register Defaults for Interrupt Routines ;-------------------------------------------------- MOVE #$40,R4 ;** Yi(n):L-ch MOVE #4,N4 MOVE #$80,R6 ;** Yi(n):R-ch MOVE #4,N6 MOVE #$20,R5 ;** X(n):L-ch MOVE #2,M5 MOVE #$30,R7 ;** X(n):R-ch MOVE #2,M7 MOVE #$20,R0 ;** IIR Coeff MOVE #29,M0 MOVE #0,R3 ;** Gain Coeff MOVE #20,M3 MOVE #$80,N3 ;----------------------- ; Init SSI Interrupt ;----------------------- MOVEP #$B200,X:M_CRB ;Enable SSI (RIE) interrupt. ANDI #$FC,MR ;Unmask all interrupts. ;----------------------------------- ; Main Loop to Monitor Slide Pots ;----------------------------------- LOOP1 MOVE #$40,R2 ;R2 points to gain lookup table. DO #21,BPCHAN ;Scan all 21 pots. MOVE Y:(R3),Y1 ;MUX select address of pot. MOVE Y1,Y:$8000 ;Select MUX channel. DO #200,ADC_RD1 ;Wait for analog MUX to stabilize. NOP ADC_RD1 MOVE Y:$1000,B ;WR strobe to ADC (starts data NOP ;conversion). NOP ;Note: A15 tied to WR of ADC. MOVE Y:$8000,B DO #500,ADC_RD2 ;Wait for conversion ADC conversion. NOP ADC_RD2 CLR B MOVE Y:$8000,B ;Read slide pot data from ADC. MOVE #>$FF,X1 ;Mask off upper 16 bits. AND X1,B MOVE B1,X1 ;X1 now contains 8-bit pot value. MOVE X:(R3+N3),Y1 ;Previous pot value. SUB Y1,B ABS B ;If absolute value of difference MOVE #>9,Y1 ;is less than 9, then skip. CMP Y1,B ;Note: 9 is rather arbitrary. JMI SKIP MOVE X1,X:(R3+N3) ;If greater than 9, than update SKIP MOVE (R3)+ ;X:($80+pot_index). BPCHAN ;This comparsion eliminates jitter NOP ;about a point. ;End of 21 pot scan. DO #20,BPCHAN2 ;For all pots except volume control. MOVE X:(R3+N3),X1 ;Load X1 with slide pot value. MOVE X1,B ASR B ;Reduce to 5-bit value for gain ASR B ;table lookup. ASR B MOVE B1,N2 NOP MOVE X:(R2+N2),X1 ;Load X1 with fractional value ;from table lookup. MOVE X:(R3),B ;Compare gain fraction to previous CMP X1,B ;value in X:(R3). JEQ NOCHNG ;Skip if no change. JGT NSLOPE ;If new value is greater than ;previous value, go to negative ;slope routine. PSLOPE MOVE #0.0001,Y1 ;Positive slope routine. PRAMP ADD Y1,B ;Increment previous gain value MOVE B,X:(R3) ;by 0.0001 towards latest value ;read from slide pot. CMP X1,B ;Continue updating this value JLT PRAMP ;until previous value exceeds ;new value. JMP NOCHNG ;Exit positive slope routine. ;Note: In the course of this loop, ;the SSI interrupt will occur many ;times, so that the band-pass ;filter response gain will be ramped ;smoothly to its new value. Thus, ;clicking noises generated from a ;coarse 5-bit gain table will be ;eliminated. NSLOPE MOVE #-0.0001,Y1 ;Negative slope routine. NRAMP ADD Y1,B ;Same as above but negative ramp MOVE B,X:(R3) ;to new gain value. CMP X1,B JGT NRAMP NOCHNG MOVE X1,X:(R3) ;Update gain table with latest value MOVE (R3)+ ;read from slide pot. BPCHAN2 ;Continue for the all 20 of the ;band-pass slide pots. VOLUME MOVE #$60,R2 ;Pot 21 (volume) is treated MOVE X:$94,B ;seperately since it uses a different ASR B ;gain lookup table. ASR B ;Reduce 8-bit value from ADC volume ASR B ;slide pot to 5-bits. MOVE B1,N2 ;Use this value for index into NOP ;lookup table. MOVE X:(R2+N2),X1 ;X1 now contains volume gain ;fraction. MOVE Y:$1E,B ;Y:$1E is previous value of volume CMP X1,B ;gain. JEQ NOCHNG2 ;If it has not changed, jump. JGT NSLOPE2 ;If it is different, decide whether ;to ramp negative or positive. PSLOPE2 MOVE #0.00005,Y1 ;Positive slope routine for volume. PRAMP2 ADD Y1,B ;Increment previous value by 0.00005 MOVE B,Y:$1E ;towards new value until it has CMP X1,B ;passed new value. Then exit loop. JLT PRAMP2 ;Note: As before, this loop will be ;interrupted many times by the SSI ;receive flag full. The volume gain ;stored at Y:$1E will ramp smoothly ;towards its new value. JMP NOCHNG2 NSLOPE2 MOVE #-0.00005,Y1 ;Negative slope routine for volume. NRAMP2 ADD Y1,B ;Same as before, but ramps in the MOVE B,Y:$1E ;opposite direction. CMP X1,B JGT NRAMP2 NOCHNG2 MOVE X1,Y:$1E ;Update volume gain value with MOVE (R3)+ ;newest value read from slide pot. JMP LOOP1 ;Do everything all over again... ;continuing slide pot scan loop. ;******************************** ; MAIN INTERRUPT ROUTINE * ;******************************** LRTEST JSET #0,X:M_SR,RIGHT ;Check SC0 (LRCLK from CDP) to ;determine which channel to process. ;******************************** ; LEFT CHANNEL SERVICE * ;******************************** ;Save registers LEFT MOVE B,L:$1F ;Save register B. ;Recieve data MOVEP X:M_RX,B ;Read SSI data. MOVE B,Y0 ;Copy SSI data to Y0. MOVE #2,M4 ;Set y(n) modulo for 3 words. MOVE #10,R1 ;Set R1 index to filter gain values ;for the left channel. CLR A X:$1E,X0 ;X:$1E = $000080 MPY X0,Y0,B (R4)+ ;Scale input data MOVE B0,Y:(R5) ;by 2^16. ORI #$08,MR ;Set scale mode to ;scale up (left ;shift) when data is ;moved from B to X0. ;---------------------- ; All 10 Filters ... ;---------------------- DO #10,LFBAND ;For all 10 bands of ;left channel. CLR B X:(R0)+,X0 Y:(R4)+,Y0 ;X0=beta;Y0=y(n-2). MAC -X0,Y0,B X:(R0)+,X0 Y:(R5)+,Y0 ;X0=alpha;Y0=x(n). MAC X0,Y0,B Y:(R5)-,Y0 ;X0=alpha;Y0=x(n-2). MAC -X0,Y0,B X:(R0)+,X0 Y:(R4)+,Y0 ;X0=gamma;Y0=y(n-1). MACR X0,Y0,B X:(R1)+,Y0 ;Y0=gain for scaling. MOVE B,X0 B,Y:(R4)+ ;X0=filter reponse. MAC X0,Y0,A (R4)+N4 ;A=scaled response. LFBAND ;Continue for all ;10 left chan bands. ANDI #$F7,MR ;Turn off scale mode. MOVE #43,M4 ;Set Yi(n) modulo to wrap around to ;start of entire y(n) buffer. ;------------------ ; Volume Scaling ;------------------ MOVE X:$1D,X0 ;X:$1D=$200000. MOVE Y:(R5)+,Y0 ;Y0=x(n). MAC X0,Y0,A Y:$1E,Y0 ;scale x(n) down MOVE A,X0 ;by 2^-2. Add this ;in to the total ;filter response. MPY X0,Y0,B ;Y0=volume gain. ;Scale total left ;data by volume. ASL B (R4)+N4 ASL B ;Scale result by ;2^2. MOVE B,X0 #>$8000,Y0 ;Now, move B to X0 MPY X0,Y0,B ;to force limiting. ;Scale result down ;---------------------------- ;by 2^-8. ; Output Data to CD Player ;---------------------------- LXMIT MOVEP B,X:M_TX ;Write result to SSI. MOVE L:$1F,B ;Retrieve B register and return. RTI ;******************************** ; RIGHT CHANNEL SERVICE * ;******************************** RIGHT MOVE B,L:$1F ;Right channel process ;identical to Left channel, MOVEP X:M_RX,B ;except right channel index MOVE B,Y0 ;registers (R6 and R7), and MOVE #2,M6 ;first 10 gain table values MOVE #0,R1 ;are used instead. CLR A X:$1E,X0 MPY X0,Y0,B (R6)+ MOVE B0,Y:(R7) ORI #$08,MR ;---------------------- ; All 10 Filters ... ;---------------------- DO #10,RFBAND CLR B X:(R0)+,X0 Y:(R6)+,Y0 MAC -X0,Y0,B X:(R0)+,X0 Y:(R7)+,Y0 MAC X0,Y0,B Y:(R7)-,Y0 MAC -X0,Y0,B X:(R0)+,X0 Y:(R6)+,Y0 MACR X0,Y0,B X:(R1)+,Y0 MOVE B,X0 B,Y:(R6)+ MAC X0,Y0,A (R6)+N6 RFBAND ANDI #$F7,MR MOVE #43,M6 ;------------------ ; Volume Scaling ;------------------ MOVE X:$1D,X0 MOVE Y:(R7)+,Y0 MAC X0,Y0,A Y:$1E,Y0 MOVE A,X0 MPY X0,Y0,B ASL B (R6)+N6 ASL B MOVE B,X0 #>$8000,Y0 MPY X0,Y0,B ;---------------------------- ; Output Data to CD Player ;---------------------------- RXMIT MOVEP B,X:M_TX MOVE L:$1F,B RTI ;******************************** ;* DATA VARIABLES and CONSTANTS * ;******************************** ORG P:$18D ;-------------------- ; IIR Coefficients ;-------------------- ; 31 Hz DC .4984587 ;beta DC .0007706594 ;alpha DC .9984491 ;gamma ; 62 Hz DC .496876 DC .001562013 DC .9968368 ; 125 Hz DC .4937405 DC .003129769 DC .9935817 ; 250 Hz DC .4876357 DC .006182143 DC .9870087 ; 500 Hz DC .4757282 DC .01213592 DC .9732514 ; 1000 Hz DC .4531951 DC .02340247 DC .9435273 ; 2000 Hz DC .4128511 DC .04357446 DC .8760584 ; 4000 Hz DC .3474929 DC .07625358 DC .7136286 ; 8000 Hz DC .2601072 DC .1199464 DC .3176087 ; 16000 Hz DC .180994 DC .159503 DC -.4435172 ;-------------------------------- ; Filter Gain (G) Coefficients ;-------------------------------- DC -0.200 DC -0.187 DC -0.171 DC -0.160 DC -0.150 DC -0.137 DC -0.114 DC -0.103 DC -0.092 DC -0.080 DC -0.067 DC -0.051 DC -0.039 DC -0.027 DC -0.015 DC 0.000 DC 0.000 DC 0.030 DC 0.060 DC 0.090 DC 0.120 DC 0.150 DC 0.180 DC 0.210 DC 0.250 DC 0.290 DC 0.340 DC 0.380 DC 0.460 DC 0.540 DC 0.750 DC 0.999 ;-------------------------------- ; Volume Gain (V) Coefficients ;-------------------------------- DC 0.0000 DC 0.0000 DC 0.0002 DC 0.0005 DC 0.0010 DC 0.0030 DC 0.0100 DC 0.0150 DC 0.0200 DC 0.0300 DC 0.0400 DC 0.0600 DC 0.0800 DC 0.1000 DC 0.1200 DC 0.1500 DC 0.2000 DC 0.2500 DC 0.3000 DC 0.3500 DC 0.4000 DC 0.4500 DC 0.5000 DC 0.6000 DC 0.7000 DC 0.8000 DC 0.9000 DC 0.9999 DC 0.9999 DC 0.9999 DC 0.9999 DC 0.9999 ;--------------------- ; Slide Pot Addresses ;--------------------- DC $70 DC $71 DC $72 DC $73 DC $74 DC $75 DC $76 DC $77 DC $68 DC $69 DC $6A DC $6B DC $6C DC $6D DC $6E DC $6F DC $58 DC $59 DC $5A DC $5B DC $5C END