/*
 * uart.c
 *
 * Created: 20.02.2019 20:50:13
 *  Author: jens
 */ 

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

#include "uart.h"

void uart_init(uint32_t baudrate)
{
	uint16_t prescale8 = UART_PRESCALE(baudrate, 8UL);
	uint16_t prescale16 = UART_PRESCALE(baudrate, 16UL);
	
	uint32_t baud8 = ((prescale8+1) * 8);
	uint32_t baud16 = ((prescale16+1) * 16);
	
	uint32_t err8 = abs(baudrate - baud8);
	uint32_t err16 = abs(baudrate - baud16);
	
	uint16_t prescale = prescale16;
	if (err8 < err16)
	{
		prescale = prescale8;
		
		// Double UART speed
		UCSR0A |= 1 << U2X0;
	}
	
	// Set baud rate
	UBRR0L  = (uint8_t)prescale;
	UBRR0H = (uint8_t)(prescale >> 8);
	
	// Enable receiver and transmitter
	UCSR0B = (1<<TXEN0)|(1<<RXEN0);
}

void uart_putc(char c)
{
	while((UCSR0A & (1<<UDRE0)) == 0)
	{
	}
	UDR0 = c;
}

char uart_getc()
{
	while ((UCSR0A & (1 << RXC0)) == 0)
	{
	}
	return UDR0;
}

void uart_puts(char const *str)
{
	while(*str)
	{
		char c = *(str++);
		uart_putc(c);
		if (c == 0x0A)
		{
			uart_putc(0x0D);
		}
	}
}

void print_byte(char byte)
{
	int i;
	unsigned char c, nibble;

	for (i=0; i < 2; i++)
	{
		nibble = (char)((byte >> 4) & 0xF);
		byte <<= 4;

		if (nibble < 10)
		c = nibble + '0';
		else
		c = nibble + 'A' - 10;

		uart_putc(c);
	}
}

void print_word(uint16_t word)
{
	int i;
	unsigned char c;

	for (i=0; i < 2; i++)
	{
		c = (char) (word >> 8);
		print_byte(c);
		word <<= 8;
	}
}
