#include "chip.h"
#include "lprintf.h"


int lprintf_uart_init(uint32_t baud, uint8_t databits, t_lprintf_uart_parity parity) {
    int err = 0;
    uint8_t len_bits = 0;
    uint8_t par_bits = 0;

    if (databits == 5) {
        len_bits = CHIP_REGFLDVAL_UCSR_UCSZ_5;
    } else if (databits == 6) {
        len_bits = CHIP_REGFLDVAL_UCSR_UCSZ_6;
    } else if (databits == 7) {
        len_bits = CHIP_REGFLDVAL_UCSR_UCSZ_7;
    } else if (databits == 8) {
        len_bits = CHIP_REGFLDVAL_UCSR_UCSZ_8;
    } else if (databits == 9) {
        len_bits = CHIP_REGFLDVAL_UCSR_UCSZ_9;
    } else {
        err = -1;
    }

    if (!err) {
        if (parity == LPRINTF_UART_PARITY_NONE) {
            par_bits = CHIP_REGFLDVAL_UCSRC_UPM_DIS;
        } else if (parity == LPRINTF_UART_PARITY_EVEN) {
            par_bits = CHIP_REGFLDVAL_UCSRC_UPM_EVEN;
        } else if (parity == LPRINTF_UART_PARITY_ODD) {
            par_bits = CHIP_REGFLDVAL_UCSRC_UPM_ODD;
        } else {
            err = -2;
        }
    }

    if (!err) {
        uint16_t uartdiv = (CHIP_CLK_SYS_FREQ/16 + baud/2) / baud - 1;
        CHIP_REG_UBRRL = uartdiv & 0xFF;
        CHIP_REG_UBRRH = (uartdiv >> 8) & 0xFF;

    }


    CHIP_REG_UCSRC = LBITFIELD_SET(CHIP_REGFLD_UCSRC_UCSZ_10, len_bits)
            | LBITFIELD_SET(CHIP_REGFLD_UCSRC_UPM, par_bits)
            | LBITFIELD_SET(CHIP_REGFLD_UCSRC_UMSEL, CHIP_REGFLDVAL_UCSRC_UMSEL_ASYNC)
            | LBITFIELD_SET(CHIP_REGFLD_UCSRC_USBS, CHIP_REGFLDVAL_UCSRC_USBS_1);
    CHIP_REG_UCSRB = LBITFIELD_SET(CHIP_REGFLD_UCSRB_UCSZ_2, (len_bits >> 2) & 1);
    CHIP_REG_UCSRB |= CHIP_REGFLD_UCSRB_TX_EN;

    return err;
}


void lprintf_close(void) {
    /* ожидание завершения передачи */
    while (lprintf_uart_busy())
        continue;



    CHIP_REG_UCSRB = 0;
    CHIP_REG_UCSRC = 0;
    CHIP_REG_UCSRA = 0;
}

void lprintf_putchar(char c) {
    while ((CHIP_REG_UCSRA & CHIP_REGFLD_UCSRA_UDRE) == 0) {
        continue;
    }
    CHIP_REG_UCSRA = CHIP_REGFLD_UCSRA_TXC; /* для использования TXC его нужно сбрасывать каждый раз
                                               перед передачей записью 1.
                                               Тут учитываем, что остальные биты настроек всегда 0. */
    CHIP_REG_UDR = c;
}

int lprintf_uart_busy(void) {
    return !(CHIP_REG_UCSRA & CHIP_REGFLD_UCSRA_TXC);
}
