#define F_CPU	8000000UL		// Clock Speed
//#define F_CPU	3686411UL
//#define BAUD	9600			// Baud rate
//#define MYUBRR	F_CPU/16/BAUD-1
#ifndef F_CPU
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 8000000"
#define F_CPU 8000000UL    // Systemtakt in Hz - Definition als unsigned long beachten >> Ohne ergeben Fehler in der Berechnung
#endif
 
#define BAUD 9600UL          // Baudrate
 
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
 
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
#endif

//#define UBRR_VAL F_CPU/16/BAUD-1

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "lcd.h"
//#include "i2cmaster.h"

#define keypress_dly    100             // delay in ms
#define key_mask        0xc             // 00001100 - PD2 (INT0) & PD3 (INT1)
#define RED	PORTB |= (1<<PB5)
//PORTB |= (1<<PB0);
#define NRED PORTB &= ~(1<<PB5)
//PORTB &= ~(1<<PB0);
#define GREEN PORTB |= (1<<PB5)	
//PORTB |= (1<<PB1);
#define NGREEN PORTB &= ~(1<<PB5)
//	PORTB &= ~(1<<PB1);

typedef unsigned char   BYTE;
typedef unsigned short  WORD;

/*
 * delay in ms
 */
void delay_ms(WORD ms){
    for(ms /= 10; ms > 0; ms--)
        _delay_ms(10);
}

inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
    if ( ! (*port & (1 << pin)) )
    {
        /* Pin wurde auf Masse gezogen, 100ms warten   */
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
        _delay_ms(50); 
        if ( *port & (1 << pin) )
        {
            /* Anwender Zeit zum Loslassen des Tasters geben */
            _delay_ms(50);
            _delay_ms(50); 
            return 1;
        }
    }
    return 0;
}

/* Initialization of USART */
void USART_Init( unsigned int baud )
{
  /* Set baud rate */
  UBRRH = (unsigned char)(baud>>8);
  UBRRL = (unsigned char)baud;
  /* Enable receiver and transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
  /* Set frame format: 8data, 2stop bit */
  UCSRC = (3<<UCSZ0);//(1<<USBS)|(3<<UCSZ0);
}


/* Send byte */
void USART_Transmit( unsigned char data )
{
  /* Wait for empty transmit buffer */
  while ( !( UCSRA & (1<<UDRE)) )
       ;
  /* Put data into buffer, sends the data */
  UDR = data;
}


/* Send string */
void uputs(char *s){
    while(*s)
	USART_Transmit(*s++);
}

/* Send byte als string */ 
void uputb(BYTE b){
char buf[3+1];
BYTE len = (b < 10)?1:(b < 100)?2:3;

    buf[len] = '\0';
    len--;
    buf[len] = '0';
    while(b > 0){
	buf[len--] = b%10 + '0';
	b /= 10;
    }
    uputs(buf);
}

/* Receive byte */
/* This function isn't used */
unsigned char USART_Receive( void )
{
  /* Wait for data to be received */
  while ( !(UCSRA & (1<<RXC)) )
       ;
  /* Get and return received data from buffer */
  return UDR;
}


/* Flush data */
void USART_Flush( void )
{
    unsigned char dummy;
    while ( UCSRA & (1 << RXC) ) 
        dummy = UDR;
}

/* Interrupt for USART, Rx Complete */
ISR(USART_RXC_vect){
	static BYTE rcv_data, status;
	NRED;
    /* 
      o: The two Buffer Registers of USART operate as a circular FIFO buffer.
         Therefore the UDR must only be read once for each incoming data!
      o: The status bits must always be read before the UDR Register is read.
         Otherwise the error status will be lost since the buffer state is lost.
    */

    status = UCSRA;
    rcv_data = UDR;
    
    /* Check for the error (High => error, Low => OK */
    /* Flags: FE - Frame Error; DOR - Data OverRun; PE - Parity Error */
    if( status & ((1 << FE) | (1 << DOR) | (1 << UPE)) ){
		lcd_puts("\r\nerror");
		RED;
		if( status & (1 << FE) ){
			lcd_puts(" fe\r\n");
		}if( status & (1 << DOR) ){
			lcd_puts(" dor\r\n");
		}if( status & (1 << UPE) ){
			lcd_puts(" pe\r\n");
		}return;
    }

/* Status LEDs (2.-4.) auschalten */
    NRED;

/* 
   Wenn empf. Byte gleich '1' ist, LED einschalten.
   Wenn empf. Byte gleich '0' ist, LED ausschalten.
*/
    if(rcv_data == '1')
		RED;
    if(rcv_data == '0')
		NRED;
//if(rcv_data == 'x' )
	lcd_clrscr();
	lcd_puts("\nreceived ");
	lcd_putc(rcv_data);
	lcd_putc("\n");
//	lcd_puts("\r\nreceived: ");
//	lcd_puts(rcv_data+"\r\n");
	uputb(rcv_data);
	/*if(rcv_data == 't'){
		uputs("\nTemperatur: ");
		sendComputeTemp();
		uputs("\n");
		sendComputeTemp2();
		uputs("\n");
	}*/
}
void sendComputeTemp(){
/*	i2c_init();
	if(i2c_start(0x90+I2C_READ)){
		return;
	}
	int8_t upper = i2c_readAck();
	int8_t lower = i2c_readNak();
	i2c_stop();
	char c[7];
	itoa(upper,c,10);
	uputs(c);
	uputs(".");
	uputs(lower > 0 ? "5 C" : "0 C");*/
}
void sendComputeTemp2(){
	/*i2c_init();
	if(i2c_start(152+I2C_READ)){
		return;
	}
	int8_t upper = i2c_readAck();
	int8_t lower = i2c_readNak();
	i2c_stop();
	char c[7];
	itoa(upper,c,10);
	uputs(c);
	uputs(".");
	uputs(lower > 0 ? "5 C" : "0 C");*/
}


void printTemp(int8_t upper, int8_t lower){
	char c[7];
	itoa(upper,c,10);
	lcd_puts(c);
	lcd_puts(".");
	lcd_puts(lower > 0 ? "5 C" : "0 C");
}
void sendTemp(int8_t upper, int8_t lower){
	char c[7];
	itoa(upper,c,10);
	uputs(c);
	uputs(".");
	uputs(lower > 0 ? "5 C" : "0 C");
}
int main( void ){
	lcd_init(LCD_DISP_ON);
	BYTE cnt=0;
    //DDRB Register fuer LEDs als Ausgang konfigurieren
   // DDRB = 1 << PIN0 | 1 << PIN1 ;	// 1 - for output; 0 -for input
	DDRB = 1<<PIN5;
    DDRB &= ~( 1 << PB4 );              
    DDRD &= ~( 1 << PB3 );          
	NGREEN;
	NRED;
   // PORTB &= ~(((1 << PIN0) & (1 << PIN1)));
	lcd_puts("init UART\n");
	lcd_puts(UBRR_VAL);
	lcd_puts("done\n");
	

	//lcd_init(LCD_DISP_ON);
	// Zeile ausgeben
    //lcd_puts("Test\n");
	USART_Flush();
	USART_Transmit('a');
	USART_Flush();
	for(;;){
		delay_ms(1000);
		USART_Transmit('a');
		RED;
		delay_ms(1000);
		NRED;
	}
	for(;;){
		lcd_putc(USART_Receive());
	}
//	uputs("External Device initialized . . .\n");
	// Hilfsvariablen
	
    sei();
	for(;;);
	return;
	int8_t upper = 42;
	uint8_t lower = 42;
   
	for(;;){
		if(debounce(&PINB, PB4)){
			GREEN;
			NRED;
			lcd_puts("Taste 1 gedrueckt\n");
			for(cnt=0;cnt<10;cnt++){
				uputb(cnt);
				lcd_putc(cnt+'0');
				delay_ms(1000);
			}lcd_putc('\n');
			USART_Transmit('\n');
		}else if(debounce(&PIND, PD3)){
			USART_Transmit('\n');
			RED;
			NGREEN;
			lcd_puts("Taste 2 gedrueckt\n");
			/*for(cnt=0;cnt<10;cnt++){
				uputb(cnt);
				delay_ms(1000);
				lcd_putc(cnt+'0');
			}lcd_putc('\n');*/
			lcd_clrscr();
			lcd_home();
			lcd_puts("I2C\n");
			lcd_puts("read1: ");
			/*i2c_init();
			if(i2c_start(144+I2C_READ)){
				lcd_puts("\nconnection failed\n");
				continue;
			}
			upper = i2c_readAck();
			lower = i2c_readNak();
			printTemp(upper,lower);
			sendTemp(upper,lower);
			USART_Transmit('\n');
			lcd_puts("\nread2: ");
			if(i2c_start(152+I2C_READ)){
				lcd_puts("\nconnection failed\n");
				continue;
			}
			upper = i2c_readAck();
			lower = i2c_readNak();
			//lower >>= 3;
			i2c_stop();
			printTemp(upper,lower);
			sendTemp(upper,lower);*/
			USART_Transmit('\n');
			lcd_puts("\n");
			lcd_puts("finished reading I2C\n");
			}
    }
    return 0;

}
