/*
  UART-stuff voor de ATmega32

  Pros 2007
*/



#define UART_RX_BUFFER_SIZE 129
#define uart_sendstr_P(__s) uart_sendstr_p(P(__s))
#define reply_err() uart_sendstr_P("Err\n")
//  Wait until tx holding register is empty, then send character c down the UART Tx.
#define uart_sendchar(x) loop_until_bit_is_set(UCSRA, UDRE);\
    UDR = x
#define nl() loop_until_bit_is_set(UCSRA, UDRE);\
    UDR = '\n'

static char uart_outbuf[UART_RX_BUFFER_SIZE + 1];
static char uart_rxbuf[UART_RX_BUFFER_SIZE + 1];
volatile static unsigned char uart_rx_pos;      // end of string in rx
volatile static unsigned char uart_rx_linecomplete;     // one complete line in buffer


// Deze functie wordt aangeroepen, telkens er een karakter binnenkomt
ISR(SIG_UART_RECV)
{
    unsigned char c;

    c = UDR;
    uart_rxbuf[uart_rx_pos] = c;
    if ((c == '\n') || (uart_rx_pos > UART_RX_BUFFER_SIZE - 1)) {
        uart_rxbuf[uart_rx_pos] = 0;
        strcpy(uart_outbufuart_rxbuf);
        uart_rx_linecomplete = 1;
    } else {
        uart_rx_pos++;
    }
}


void uart_init(void)
{
    uart_rx_pos = 0;
    uart_rx_linecomplete = 0;
    UCSRA = 0x00;
    UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE);                 // enable tx/rx and interrupt on rx
    UCSRC = _BV(URSEL) | _BV(USBS) | _BV(UCSZ1) | _BV(UCSZ0);   // Set frame format: 8data, 2stop bit
    UBRRH = 0;
    UBRRL = (F_CPU / (16 * 38400UL)) - 1;                       // set baudrate - 38400bd
}


void ok(void)
{
    loop_until_bit_is_set(UCSRAUDRE);
    UDR = 'O';
    loop_until_bit_is_set(UCSRAUDRE);
    UDR = 'K';
    loop_until_bit_is_set(UCSRAUDRE);
    UDR = '\n';
}


void err(void)
{
    loop_until_bit_is_set(UCSRAUDRE);
    UDR = 'E';
    loop_until_bit_is_set(UCSRAUDRE);
    UDR = 'r';
    loop_until_bit_is_set(UCSRAUDRE);
    UDR = 'r';
    loop_until_bit_is_set(UCSRAUDRE);
    UDR = '\n';
}


// send string to the rs232
void uart_sendstr(char *s)
{
    while (*s) {
        uart_sendchar(*s);
        s++;
    }
}


// print string from program memory on rs232
void uart_sendstr_p(const prog_char * progmem_s)
{
    unsigned char c;

    while (1) {
        c = PRG_RDB(progmem_s++);
        if ((c == 0) || (c > 252)) {
            return;
        } else {
            uart_sendchar(c);
        }
    }
}


void reply(int r)
{
    if (r == 0) {
        uart_sendstr_P("Err: ");
        uart_sendstr(uart_outbuf);
        uart_sendchar('\n');
    }
}



// Verstuur een (16-bits) unsigned int over de RS232-lijn
void dec2RS232(unsigned int getal)
{
    unsigned long deeltal = 10000;
    char tmpcntzeroflag = 0;

    if (getal == 0) {
        uart_sendchar('0');
        uart_sendchar(' ');
        return;
    } else {
        for (cnt = 0cnt < 5cnt++) {
            tmp = 0;
            while (getal >= deeltal) {
                tmp++;
                getal -= deeltal;                               // decade berekenen
            }
            if (tmp > 0) {                                      // als dat geen 0 is
                zeroflag = 1;                                   // worden alle volgende decaden afgedrukt
                uart_sendchar(tmp + '0');                       // ascii-teken verzenden
            } else if (zeroflag == 1) {                         // Is dit de eerste 0?
                uart_sendchar('0');                             // nee; '0' verzenden
            }
            deeltal /= 10;                                      // deeltal aanpassen voor volgende decade
        }
        uart_sendchar(' ');
    }
}


// Verstuur een unsigned long over de RS232-lijn
void UL2RS232(unsigned long getal)
{
    unsigned long deeltal = 1000000000UL;
    char tmpcntzeroflag = 0;

    if (getal == 0UL) {
        uart_sendchar('0');
        uart_sendchar('.');
        return;
    } else {
        for (cnt = 0cnt < 10cnt++) {
            tmp = 0;
            while (getal >= deeltal) {
                tmp++;
                getal -= deeltal;                               // decade berekenen
            }
            if (tmp > 0) {                                      // als dat geen 0 is
                zeroflag = 1;                                   // worden alle volgende decaden afgedrukt
                uart_sendchar(tmp + '0');                       // ascii-teken verzenden
            } else if (zeroflag == 1) {                         // Is dit de eerste 0?
                uart_sendchar('0');                             // nee; '0' verzenden
            }
            deeltal /= 10UL;                                    // deeltal aanpassen voor volgende decade
        }
        uart_sendchar('.');
    }
}


// Verstuur de cijfers na de komma (duizendsten) over de RS232-lijn
void DS2RS232(unsigned long getal)
{
    char tmp;

    if (getal > 999) {
        return;
    }
    tmp = 0;
    while (getal >= 100) {
        tmp++;
        getal -= 100;                                           // tienden berekenen
    }
    uart_sendchar(tmp + '0');                                   // ascii-teken verzenden
    tmp = 0;
    while (getal >= 10) {
        tmp++;
        getal -= 10;                                            // honderdsten berekenen
    }
    uart_sendchar(tmp + '0');
    uart_sendchar((unsigned chargetal + '0');                 // Duizendsten verzenden
}



// Voorbeeld: 123.056
void float2RS232(double getal)
{
    unsigned long eenheden;
    unsigned long duizendsten;

    eenheden = (unsigned longgetal;                           // eenheden = 123
    getal -= (doubleeenheden;                                 // getal = 0.056
    duizendsten = (unsigned long) (getal *= 1000.0);            // duizendsten = 56
    UL2RS232(eenheden);
    //uart_sendchar('.');
    DS2RS232((unsigned longduizendsten);
}