/* tastenfeld_01.c ATmega88 @ 1MHz */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> // Einbinden der Headerdatei für Interrupts

/* ADC-Wertebereiche zu den gedrückten Tasten zuordnen */
#define Taste_1 ((ADC_Wert >=168) && (ADC_Wert <=174))
#define Taste_2 ((ADC_Wert >=89) && (ADC_Wert <=95))
#define Taste_3 ((ADC_Wert >=0) && (ADC_Wert <=3))
#define Taste_4 ((ADC_Wert >=185) && (ADC_Wert <=191))
#define Taste_5 ((ADC_Wert >=113) && (ADC_Wert <=119))
#define Taste_6 ((ADC_Wert >=22) && (ADC_Wert <=28))
#define Taste_7 ((ADC_Wert >=202) && (ADC_Wert <=208))
#define Taste_8 ((ADC_Wert >=131) && (ADC_Wert <=137))
#define Taste_9 ((ADC_Wert >=46) && (ADC_Wert <=52))
#define Taste_10 ((ADC_Wert >=218) && (ADC_Wert <=224))
#define Taste_11 ((ADC_Wert >=150) && (ADC_Wert <=156))
#define Taste_12 ((ADC_Wert >=70) && (ADC_Wert <=76))

void Init_ADC (void) // Funktion zur Initialisierung der AD-Wandlung
{
	uint8_t x;
	DDRC &= ~(1<<PC5);					// PC5 = Eingang (ADC5)
	ADCSRA |= (1<<ADEN);				// ADC aktivieren
	ADCSRA |= (1<<ADPS0)|(1<<ADPS1);	// Prescaler = 8
	ADMUX |= (1<<REFS0)|(1<<REFS1);		// Uref = Internal 1,1V
	ADMUX |= (1<<MUX2)|(1<<MUX0);		// ADC5 (PIN PC5) = ADC channel
	ADMUX |= (1<<ADLAR);				// Ausgabe linksbündig
	DIDR0 |= (1<<ADC5D);				// Digital Kanal ADC3 deaktivieren (spart Strom)
	
	ADCSRA |= (1<<ADSC);				// Start 1. ADC-Wandlung zum "Warmlaufen" des ADC
	while (ADCSRA & (1<<ADSC));			// Auf Abschluss der Konvertierung warten
	x = ADC;							// Ergebnis der 1. AD-Wandlung in x speichern und verwerfen
}

void Init_INT0 (void) // Funktion zur Initialisierung von Interrupt 0
{
	DDRD &= ~(1<<PD2);		// PD2 = Eingang (INT0)
	EICRA |= (1<<ISC01);	// Int0 wird durch eine fallende Flanke ausgelöst
	EIMSK |= (1<<INT0);		// Ext. Int0 aktivieren
	sei();					// Alle Interrupts aktivieren
}

volatile uint16_t ADC_Wert;

int main(void)
{
	DDRB |= 0xFF;	// PORTB = Ausgang
	Init_ADC();		// Funktion Init_ADC() aufrufen
	Init_INT0();	// Funktion Init_INT0() aufrufen
	
	while(1)
	{
		/* Tasten zuordnen und Tastenwert am PORTB ausgeben */
		if (Taste_1) PORTB = 1;
		else if (Taste_2) PORTB = 2;
		else if (Taste_3) PORTB = 3;
		else if (Taste_4) PORTB = 4;
		else if (Taste_5) PORTB = 5;
		else if (Taste_6) PORTB = 6;
		else if (Taste_7) PORTB = 7;
		else if (Taste_8) PORTB = 8;
		else if (Taste_9) PORTB = 9;
		else if (Taste_10) PORTB = 10;
		else if (Taste_11) PORTB = 11;
		else if (Taste_12) PORTB = 12;
		else PORTB = 0;		// Wenn nichts zutrifft...
		ADC_Wert = 0;		// ADC_Wert zurücksetzen
	}
}

ISR (INT0_vect) // Einsprung der ISR für den ext. Int0
{
	/***** 1. AD-Wandlung durchführen *****/
	ADCSRA |= (1<<ADSC);			// Start ADC-Wandlung
	while (ADCSRA &(1<<ADSC));		// Auf Abschluss der Konvertierung warten
	ADC_Wert += ADCH;				// Inhalt von ADCH in ADC_Wert aufsummieren
	
	/***** 2. AD-Wandlung durchführen *****/
	ADCSRA |= (1<<ADSC);			// Start ADC-Wandlung
	while (ADCSRA &(1<<ADSC));		// Auf Abschluss der Konvertierung warten
	ADC_Wert += ADCH;				// Inhalt von ADCH in ADC_Wert aufsummieren
	
	/***** 3. AD-Wandlung durchführen *****/
	ADCSRA |= (1<<ADSC);			// Start ADC-Wandlung
	while (ADCSRA &(1<<ADSC));		// Auf Abschluss der Konvertierung warten
	ADC_Wert += ADCH;				// Inhalt von ADCH in ADC_Wert aufsummieren
	ADC_Wert = ADC_Wert / 3;		// ADC Mittelwert von 3 Messungen bilden
}