/** AVRDSP.c** Created: 08-Nov-19 12:16:58 PM* Author : Luke*** With this code and the ATmega32L board you can test* your Micro Apps 2 hardware.** This code uses an IIR filter to attenuate 1kHz frequencies* with a sample rate of 9.6kHz** Connections:* Input: PA0 (Pin 37)* SPI Clock: PB7 (Pin 3)* SPI MOSI: PB5 (Pin 1)* SPI CS: PB0 (Pin 40)* Don't forget to connect to GND!** If you want to measure how long the interrupt takes,* connect an oscilloscope to PD0 (Pin 9)**/
#include <avr/io.h>#include <avr/interrupt.h>void GPIOSetup();void ADCSetup();void SPISetup();void TimerSetup();
//2^14static int a[3] = {15374,-24421,15374};static int b[3] = {0,-24421,14364};volatile long y[3];volatile long x[3];int IIRFilter(int input);
int main(void){ GPIOSetup(); ADCSetup(); SPISetup(); TimerSetup(); sei(); while (1);}
void GPIOSetup(){ DDRA = 0x00; //Input PA0 - Analogue in DDRB = 0xFF; //SPI out DDRD = 0xFF; //PD0 oscilloscope check return;}
void ADCSetup(){ ADCSRA = 0xAC; //enable ADC - clk/2 - ADC to start on timer compare ADMUX = 0x40; //AVCC - Right Justifed - ADC0 SingleEnded SFIOR |= 0x60; //start conversion on timer compare return;}
void SPISetup(){ SPCR = 0x50; return;}
void TimerSetup(){ TCCR0 = (1<<WGM01); //CTC OCR0 = 103; //104.16666 = 9600Hz TIMSK = (1<<OCIE0); TCCR0 |= 2; //Prescaler 8 return;}
ISR(TIMER0_COMP_vect){ //Start interrupt on ADC conversion PORTD = 0x00; while(ADCSRA & 0x40); int16_t result = IIRFilter(ADC); unsigned char highres = result>>8; unsigned char lowres = result; PORTB = 0x00; SPDR = ((highres & 0x0F) | 0x10); while((SPSR & 0x80) == 0); highres = SPDR; SPDR = lowres; while((SPSR & 0x80) == 0); lowres = SPDR; PORTB = 0x01; PORTD = 0x01; return;}
int IIRFilter(int input){ //IIR x[0] = input; //Update Delay Lines //Difference Equation y[0] = (a[0] * x[0] + a[1] * x[1] + a[2] * x[2] - b[1] * y[1] - b[2] * y[2])>>14; x[2]=x[1]; x[1]=x[0]; y[2]=y[1]; y[1]=y[0]; //change to int int output = (int)y[0]<<2; return output; }