/*
* LED_fading_04.c
* with 10bit valuetable and phasecorrect pwm
* Controller: ATmega88 @ 1MHz
*/
#include <avr/io.h>
#include <util/delay.h>

#define button_down (!(PIND & (1<<PIND2)))
#define button_up (PIND & (1<<PIND2))

void taster_low_entprellen(void)	// Funktion zum Entprellen des gedrückten Tasters
{
	for (uint8_t i=0; i<100; i++)	// Schleife mit 100 Durchläufen
	{
		_delay_us(10);				// Prellzeit abwarten
		if (button_down)			// Wenn Taster noch immer gedrückt ist
			asm ("NOP");			// nichts tun (Assembleranweisung NOP = No Operation)
		else
			i = 0;					// setze i zurück wenn in der Prellzeit ein High detektiert wurde
	}
}

void taster_high_entprellen(void)	// Funktion zum Entprellen des losgelassenen Tasters
{
	for (uint8_t i=0; i<100; i++)	// Schleife mit 100 Durchläufen
	{
		_delay_us(10);				// Prellzeit abwarten
		if (button_up)				// Wenn Taster losgelassen ist
			asm ("NOP");			// nichts tun (Assembleranweisung NOP = No Operation)
		else
			i = 0;					// setze i zurück wenn in der Prellzeit ein Low detektiert wurde
	}
}

const unsigned int pwm_table_10[64] =
{
	0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10,
	11, 12, 13, 15, 17, 19, 21, 23, 26, 29, 32, 36, 40, 44, 49, 55,
	61, 68, 76, 85, 94, 105, 117, 131, 146, 162, 181, 202, 225, 250,
	279, 311, 346, 386, 430, 479, 534, 595, 663, 739, 824, 918, 1023
};

enum button {down, up} state;		// down=0, up=1
	
int main(void)
{
	DDRD = ~(1<<PIND2);				// PIN D2 = Eingang für Taster
	DDRB |= (1<<PB1);				// OC1A = output
	ICR1 = 1023;					// ICR1 = Top Value
	
	// Mode 10: PWM, Phase Correct, Prescaler = 1, Clear OC1A on compare match
	TCCR1A = (1 << COM1A1) + (1 << WGM11);
	TCCR1B = (1 << WGM13) + (1 << CS10);
	
	uint8_t i = 0;
	
	while(1)
	{
		if (button_down)				// Wenn Taster gedrückt ist
		{
			taster_low_entprellen();	// Funktion Taster entprellen aufrufen
			
			if (state == down)			// Wenn Zustand zuvor down war -> rauf dimmen
			{
				while (button_down)		// Solange Taster gedrückt ist
				{
					if (i < 63)			// i bis max. Tabellenwert inkrementieren
					{
						i++;
						OCR1A = pwm_table_10[i]; // Tabellenwert i dem OCR1A zuweisen
						_delay_ms(10);
					}
				}
				
				taster_high_entprellen();	// Funktion Taster entprellen aufrufen
				state = up;					// Flag für neuen Zustand setzen
			}
			
			else if (state == up)			// Wenn Zustand zuvor up war -> runter dimmen
			{
				while (button_down)			// Solange Taste gedrückt ist
				{
					if (i > 0)				// i bis min. Tabellenwert dekrementieren
					{
						i--;
						OCR1A = pwm_table_10[i]; // Tabellenwert i dem OCR1A zuweisen
						_delay_ms(10);
					}
				}
				
				taster_high_entprellen();	// Funktion Taster entprellen aufrufen
				state = down;				// Flag für neuen Zustand setzen
			}
		}
	}
}