/*
 * RS232.c
 *
 * Created: 04.12.2016 20:02:48
 *  Author: Torsten
 */ 

#include <avr/io.h>
#include <stdlib.h>

#define F_CPU 8000000UL  

#define BAUD 9600UL      // Baudrate

#define UART_MAXSTRLEN 10

// 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

#include <util/delay.h>


volatile uint8_t uart_str_complete = 0;     // 1 .. String komplett empfangen
volatile uint8_t uart_str_count = 0;
volatile char uart_string[UART_MAXSTRLEN + 1] = "";

ISR(USART_RXC_vect)
{
	unsigned char nextChar;

	// Daten aus dem Puffer lesen
	nextChar = UDR;
	if( uart_str_complete == 0 ) {	// wenn uart_string gerade in Verwendung, neues Zeichen verwerfen

		// Daten werden erst in uart_string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
		if( nextChar != '\n' &&
		nextChar != '\r' &&
		uart_str_count < UART_MAXSTRLEN ) {
			uart_string[uart_str_count] = nextChar;
			uart_str_count++;
		}
		else {
			uart_string[uart_str_count] = '\0';
			uart_str_count = 0;
			uart_str_complete = 1;
		}
	}
}


void uart_init(void)
{
	UBRRH = UBRR_VAL >> 8;	//Baudrate festlegen
	UBRRL = UBRR_VAL & 0xFF;
	
	UCSRB |= (1 << TXEN) | (1<<RXEN);	//Senden einschatel TX
	UCSRC =  (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); //Asynchron 8N1
}

//Senden

int uart_putc(unsigned char c)
{
	while (!(UCSRA & (1<<UDRE))) //Warten bis senden möglich
	{}
	UDR = c;	//Zeichen senden
	
}

void uart_puts(char *s)
{
	while (*s)
	{// so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)"
		uart_putc(*s);
		s++;
	}
}


///Empfangen

uint8_t uart_getc(void)
{
	while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
	;
	return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
}

void uart_gets( char* Buffer, uint8_t MaxLen )
{
	uint8_t NextChar;
	uint8_t StringLen = 0;

	NextChar = uart_getc();         // Warte auf und empfange das nächste Zeichen

	// Sammle solange Zeichen, bis:
	// * entweder das String Ende Zeichen kam
	// * oder das aufnehmende Array voll ist
	while( NextChar != 'q' && StringLen < MaxLen - 1 ) {
		*Buffer++ = NextChar;
		StringLen++;
		NextChar = uart_getc();
	}

	// Noch ein '\0' anhängen um einen Standard
	// C-String daraus zu machen
	*Buffer = '\0';
}



