//
// AVR USART common operations
// Homelab library
//
// Department of Mechatronics
// Tallinn University of Technology
// ITT Group
// © Copyrights 2014
//

#include <stdio.h>
#include <stdarg.h>
#include "xmega/clksys_driver.h"
#include "usart.h"

usart port = USART(0);

#if defined (__AVR_ATxmega128A1U__)
//
// Initializing USART
//
void usart_init_async(	uint8_t port,
                        usart_databits data_bits,
                        usart_stopbits stop_bits,
                        usart_parity parity,
                        uint32_t baudrate)
{
    if(_sys_freq == 2)
        Homelab_clock_init();

    //define port directions
    if(port == 0)
    {
        PORTD_DIRSET |= (1<<3);	// TXD0
        PORTD_DIRCLR = (1<<2);	// RXD0

        USART0.CTRLC = (uint8_t) data_bits | (parity<<4) | stop_bits;
        USART0.BAUDCTRLA = baudrate;

        USART0.CTRLB |= USART_RXEN_bm | USART_TXEN_bm;
    }
    else if(port == 1)
    {
        PORTC_DIRSET |= (1<<7);	// TXC1
        PORTC_DIRCLR = (1<<6);	// RXC1

        USART1.CTRLC = (uint8_t) data_bits | (parity<<4) | stop_bits;
        USART1.BAUDCTRLA = baudrate;

        USART1.CTRLB |= USART_RXEN_bm | USART_TXEN_bm;
    }
}

//
// Sending character
//
void usart_send_char(uint8_t port, char symbol)
{
    if(port == 0)
    {
        // Transmit a character, first wait for the previous to be sent
        while( (USART0.STATUS & USART_DREIF_bm) == 0 ) {}
        // Now, transmit the character
        USART0.DATA = symbol;
    }
    else if(port == 1)
    {
        // Transmit a character, first wait for the previous to be sent
        while( (USART1.STATUS & USART_DREIF_bm) == 0 ) {}
        // Now, transmit the character
        USART1.DATA = symbol;
    }
}

//
// Reading character
//
bool usart_try_read_char(uint8_t port, char *symbol)
{
    if (!usart_has_data(port))
    {
        return false;
    }

    *symbol = usart_read_char(port);

    return true;
}

//
// Sending string
//
void usart_send_string(uint8_t port, char *text)
{
    //
    // Send every character in string (exept the null terminator)
    //
    while (*text != 0)
    {
        usart_send_char(port, *text++);
    }
}

//
// Send formatted string
//
void usart_send_stringf(uint8_t port, const char *format, ...)
{
    va_list args;
    char text[64];
    unsigned char i, len;

    va_start(args, format);
    len = vsprintf (text, format, args);
    va_end(args);

    // Send all the characters
    for (i = 0; i < len; i++)
    {
        usart_send_char(port, text[i]);
    }
}

//
// Reading string with maxlen length or until \r char
//
void usart_read_string(uint8_t port, char *data, unsigned int maxlen)
{
    int i;

    for (i=0; i< maxlen-1; i++)
    {
        //wait for char arriving
        while (!usart_has_data(port)) {}

        //save char and look for end indicator
        if ((*data = usart_read_char(port))  == '\r')
        {
            *data = 0; //string terminator
            return;
        }

        //move pointer
        data++;
    }

    //string terminator
    *data = 0;
}


#endif

