// Digital
Pre-Amplifier
// Will Tang and Clement Yu
// ECE 476 Spring 2003 Final Project
#include <Mega32.h>
#include <stdio.h> // sprintf
#include <delay.h> // delay_ms
#include <stdlib.h>
//I like these definitions
#define begin {
#define end
}
#define LCDwidth 16 //characters
// Low-pass filter state machine
enum { NoPass, LP1, LP2, LP3, LP4, LP5, LP6, LP7 };
char Ainl, Ainh, shiftedOut; //raw A to D number
unsigned int totalbits, index, lowPassed, State, poles;
unsigned int setlevel, sampCnt, sample, sampDelay;
int level, maxlevel, noLED, DSPen;
float vin[5], vout[5];
float a1, a2, a3, a4, a5, b1, b2, b3, b4, b5;
void main(void)
begin
// Since Aref is
turned on, we must pull the Aref pin off
ADMUX =
0b11000010; // Bit 6 set to 0
(ADLAR = 0, ADCL has lower 8 bits, ADCH has upper 2)
// ADC enabled,
conversion starts, interrupt disabled, last 3 bits for prescaler division (0b111
= 128)
ADCSR =
0b11000111; // prescaler division
(0b111 = 128)
//enable sleep
and choose ADC mode
MCUCR =
0b01010000;
// State machine
start with no filter
State = NoPass;
// PORTD as PWM
output, pin4 (OCR1B)
DDRD =
0xff;
// PORTB as
button input
DDRB =
0x00;
// PORTC as a
LED display
DDRC = 0xff;
// init
variables
sampCnt = 0; setlevel
= 0; sampDelay = 0;
maxlevel = 0;
noLED = 0; DSPen = 0;
// init DSP vars
for( index = 0;
index < 5; index++)
{
vout[index] =
0;
vin[index] =
0;
}
// PWM prescaler = 1, 8-bit Fast PWM
TCCR1A =
0b11110001;
TCCR1B =
0b00001001;
#asm
sei
#endasm
// measure and
display loop
while (1)
begin
//If ADCSR.6 =
1, then the ADC conversion has not been finished, wait in while loop
while( ADCSR.6
!= 0 )
{
;
}
// Save 10
conversion bytes after ADC is finished
Ainl = ADCL;
Ainh =
ADCH;
// start conv
again
ADCSR = ADCSR
| 0x40;
// 10 bit ADC
conversion (ADLAR = 0)
totalbits =
Ainh;
totalbits =
totalbits << 8;
totalbits =
totalbits | (0xff & Ainl);
// check for
button press to change state
if (PINB !=
0xff)
{
if (PINB == 0b11111110) State = NoPass;
else
if (PINB == 0b11111101) State = LP1;
else
if (PINB == 0b11111011) State = LP2;
else if (PINB == 0b11110111) State = LP3;
else if (PINB
== 0b11101111) State = LP4;
else if (PINB
== 0b11011111) State = LP5;
else
if (PINB == 0b10111111) State = LP6;
else
if (PINB == 0b01111111) { PORTC = 0xff; State = LP7; } // TURN led off
} // if
// Do DSP
calculations (or no calculations) to sampled values depending on desired state
switch(State)
{
case NoPass:
noLED =
0;
DSPen = 0;
break;
case
LP1:
// DSP
low-pass filter coeffs
//
butter(2, .1)
b1 = 0.0201; b2 = 0.0402; b3 = 0.0201;
a1 = 1; a2 = -1.561; a3 =
0.6414;
poles = 2;
noLED = 0;
DSPen = 1;
break;
case
LP2:
// DSP
low-pass filter coeffs
//
butter(2, .2)
b1 = 0.0675; b2 = 0.1349; b3 = 0.0675;
a1 =
1; a2 = -1.143; a3 = 0.4128;
poles = 2;
noLED = 0;
DSPen = 1;
break;
case
LP3:
// DSP
low-pass filter coeffs
//
butter(3, .2)
b1
= 0.0181; b2 = 0.0543; b3 = 0.0543; b4 =
0.0181;
a1 = 1; a2 = -1.76; a3 = 1.1829;
a4 = -0.2781;
poles = 3;
noLED = 0;
DSPen = 1;
break;
case
LP4:
// DSP
low-pass filter coeffs
//
butter(1, .1)
b1 = 0.1367; b2 = 0.1367;
a1 =
1; a2 = -0.7265;
poles =
1;
noLED = 0;
DSPen = 1;
break;
case LP5:
// DSP
low-pass filter coeffs
//
butter(1, .2)
b1 = 0.2452; b2 = 0.2452;
a1 = 1; a2
= -0.5095;
poles = 1;
noLED = 0;
DSPen = 1;
break;
case LP6:
// DSP
low-pass filter coeffs
//
butter(1, .5)
b1 = 0.5; b2 = 0.5;
a1 = 1; a2
= 0;
poles =
1;
noLED = 0;
DSPen = 1;
break;
case
LP7:
noLED = 1;
break;
} //
switch
if(DSPen) // DSP calculations
{
// DSP
filter calculation
for(index = 0; index < poles; index++)
{
vout[index+1] = vout[index];
vin[index+1] = vin[index];
}
vin[0] =
(float) totalbits;
vout[0] =
(b1 * vin[0]) + (b2 * vin[1]) - (a2 * vout[1]);
switch(poles)
{
case 2:
vout[0]
= vout[0] + (b3 * vin[2]) - (a3 * vout[2]);
break;
case
3:
vout[0]
= vout[0] + (b3 * vin[2]) + (b4 * vin[3]) - (a3 * vout[2]) - (a4 *
vout[3]);
break;
case
4:
vout[0]
= vout[0] + (b3 * vin[2]) + (b4 * vin[3]) + (b5 *vin[4])
- (a3 * vout[2]) - (a4 * vout[3])
- (a5 *vout[4]);
} //
switch
lowPassed = (int) vout[0];
}// if
State
else // Bypass DSP calculations
{
lowPassed =
totalbits;
}
// needed for
8-bit resolution PWM output. Shifted to convert 10-bit ADC input to 8-bit PWM
shiftedOut =
(char) (lowPassed >> 2);
OCR1BL =
shiftedOut;
// Normalizing
samples to a display level
if(!noLED)
{
sample = shiftedOut;
if(sample >= 180) level = 7;
else if(sample >= 170) level = 6;
else if(sample >= 160) level = 5;
else if(sample >= 150) level = 4;
else if(sample >= 140) level = 3;
else if(sample >= 130) level = 2;
else if(sample >= 120) level = 1;
else if(sample >= 110) level = 0;
// update
the maximum level
if(maxlevel
< level)
{
maxlevel =
level+1;
}
if(sampDelay++ >= 300)
{
sampDelay = 0;
maxlevel--;
switch(maxlevel)
{
case 0:
PORTC = ~0b10000000; break;
case 1:
PORTC = ~0b11000000; break;
case 2:
PORTC = ~0b11100000; break;
case 3:
PORTC = ~0b11110000; break;
case 4:
PORTC = ~0b11111000; break;
case 5:
PORTC = ~0b11111100; break;
case 6:
PORTC = ~0b11111110; break;
case 7:
PORTC = ~0b11111111; break;
} // switch
} // if
sampDelay
} // if
!noLED
PORTA.0 =
PORTA ^ 0b00000001;
end
end