#include <avr/io.h>
#include <avr/interrupt.h>
#include "usart.h"

namespace usart
{
    namespace {
        static FILE mystdout;
    }
    
    void init( unsigned long baud) {
        fdev_setup_stream(&mystdout, put_printf, NULL, _FDEV_SETUP_WRITE);
        stdout = &mystdout;
        const unsigned int ubrr =  F_CPU/8/baud-1;

        /*Set baud rate */
        
        
        #if defined __AVR_ATmega328P__
            UBRR0H = (unsigned char)(ubrr>>8);
            UBRR0L = (unsigned char)ubrr;
            UCSR0A |= (1<<U2X0);
            //Enable receiver and transmitter 
            UCSR0B = (1<<RXEN0)|(1<<TXEN0);
            //UCSRB |= (1<< RXCIE)|(1<<TXCIE);
            /* Set frame format: 8data, 2stop bit */
            UCSR0C = (1<<USBS0)|(3<<UCSZ00);
        #elif defined  __AVR_ATmega32__ || defined __AVR_ATmega16__
            UBRRH = (unsigned char)(ubrr>>8);
            UBRRL = (unsigned char)ubrr;
            UCSRA |= (1<<U2X);
            //Enable receiver and transmitter 
            UCSRB = (1<<RXEN)|(1<<TXEN);
            //UCSRB |= (1<< RXCIE)|(1<<TXCIE);
            /* Set frame format: 8data, 2stop bit */
            UCSRC = (1 << URSEL)|(3<<UCSZ0);
        #endif
    
    }

    void put(char data) {
        #if defined __AVR_ATmega328P__
            while ( !( UCSR0A & (1<<UDRE0)) ); UDR0 = data;
        #elif defined  __AVR_ATmega32__ || defined __AVR_ATmega16__
            while ( !( UCSRA & (1<<UDRE)) ); UDR = data;
        #endif
        
       
    }

    char get( void ) {
        #if defined __AVR_ATmega328P__
            while ( !(UCSR0A & (1<<RXC0)) ); return UDR0;
        #elif defined  __AVR_ATmega32__ || defined __AVR_ATmega16__
            while ( !(UCSRA & (1<<RXC)) ); return UDR;
        #endif
    }       
   
    int put_printf(char var, FILE *stream) {
        put(var);
        return 0;
    }
} // namespace usart