/**
  ******************************************************************************
  * @file    SHAL_TIM.h
  * @author  Luca Lizaranzu
  * @brief   Related to USART and SHAL_UART abstractions
  ******************************************************************************
  */


#include "SHAL_UART.h"
#include "SHAL_GPIO.h"
#include "SHAL_UART_REG.h"

void SHAL_UART::init(const UART_Pair_Key pair){

    m_key = pair;

    auto uartPair = getUARTPair(pair); //Get the UART_PAIR information to be initialized

    //Get the SHAL_GPIO pins for this SHAL_UART setup
    const GPIO_Key Tx_Key = uartPair.TxKey; //Tx pin
    const GPIO_Key Rx_Key = uartPair.RxKey; //Rx pin

    GET_GPIO(Tx_Key).setPinMode(PinMode::ALTERNATE_FUNCTION_MODE);
    GET_GPIO(Rx_Key).setPinMode(PinMode::ALTERNATE_FUNCTION_MODE);

    GET_GPIO(Tx_Key).setAlternateFunction(uartPair.TxAlternateFunctionMask);
    GET_GPIO(Rx_Key).setAlternateFunction(uartPair.RxAlternateFunctionMask);


    SHAL_UART_Enable_Register pairUARTEnable = getUARTEnableReg(pair); //Register and mask to enable the SHAL_UART channel

    SHAL_apply_bitmask(pairUARTEnable.reg,pairUARTEnable.mask);


}

void SHAL_UART::begin(uint32_t baudRate, SHAL_USART_Word_Length wordLength) const volatile {

    auto CR  = getUARTControlRegister1(m_key);
    auto BRR = getUARTBaudRateRegister(m_key); // fix this

    SHAL_clear_bitmask(CR.reg, CR.usart_enable_mask);

    SHAL_apply_bitmask(CR.reg, static_cast<uint32_t>(wordLength));
    SHAL_apply_bitmask(CR.reg, CR.receive_enable_mask);
    SHAL_apply_bitmask(CR.reg, CR.transmit_enable_mask);
    SHAL_apply_bitmask(CR.reg, CR.Rx_interrupt_enable_mask);

    SHAL_set_register_value(getUARTTransmitDataRegister(m_key).reg,0); //Clear TDR

    uint16_t baud = SystemCoreClock / (1 * baudRate);
    SHAL_set_bits_16(BRR.reg, 16, baud, 0);

    SHAL_apply_bitmask(CR.reg, CR.usart_enable_mask); //Enable
}

void SHAL_UART::sendString(const char *s) const volatile {
    const auto ISR = getUARTISR(m_key);

    while (*s) sendChar(*s++); //Send chars while we haven't reached end of s

    if (!SHAL_wait_for_bit_set_us(ISR.reg, ISR.transmit_data_register_empty_mask, 500)) {
        assert(false);
    }
}

void SHAL_UART::sendChar(const char c) const volatile {

    const auto ISR = getUARTISR(m_key);

    SHAL_wait_for_bit_set_us(ISR.reg,ISR.transmit_data_register_empty_mask,500);

    SHAL_set_register_value(getUARTTransmitDataRegister(m_key).reg,static_cast<uint32_t>(c));
}



SHAL_UART& UARTManager::get(uint8_t uart) {

    if(uart > NUM_USART_LINES - 1){
        assert(false);
        //Memory fault
    }

    return m_UARTs[uart];
}
