#include "periph_uart.h"


// 串口初始化函数
void UART_Init(UART_Type* UARTx, UART_InitTypeDef* UART_InitStruct)
{
    uint16_t tmpreg = 0x00;
    uint16_t div    = 0x00;
    uint16_t divn   = 0x00;
    uint8_t  divf   = 0x00;

    /* DeInit first */
    UART_DeInit(UARTx);

    /* CLK */
    REG_WRT_BITS(0x40000020, 5, 5, 1);
    if((int)UARTx == UART0_BASE) REG_WRT_BITS(0x40000028, 6, 6, 1);
    else REG_WRT_BITS(0x40000028, 7, 7, 1);

    /* Clear and set the UART check bit and stop bit */
    tmpreg = UARTx->LCR;
    tmpreg &= UART_LCR_CLEAR;
    tmpreg |= (uint8_t)UART_InitStruct->UART_Parity | UART_InitStruct->UART_StopBits;

    /* select the length of data */
	switch(UART_InitStruct->UART_WordLength)
    {
	    case UART_WORD_LENGTH_5BIT:
            UARTx->LCR_EXT = UART_9BIT_DATA_TRANSFER_DISABLE;
            tmpreg |= UART_WORD_LENGTH_5BIT;
            break;
        case UART_WORD_LENGTH_6BIT: 
            UARTx->LCR_EXT = UART_9BIT_DATA_TRANSFER_DISABLE;
            tmpreg |= UART_WORD_LENGTH_6BIT;
            break;
        case UART_WORD_LENGTH_7BIT:
            UARTx->LCR_EXT = UART_9BIT_DATA_TRANSFER_DISABLE;
            tmpreg |= UART_WORD_LENGTH_7BIT;
            break;
        case UART_WORD_LENGTH_8BIT:
            UARTx->LCR_EXT = UART_9BIT_DATA_TRANSFER_DISABLE;
            tmpreg |= UART_WORD_LENGTH_8BIT;
            break;
        case UART_WORD_LENGTH_9BIT:
            UARTx->LCR_EXT = UART_9BIT_DATA_TRANSFER_ENABLE;
            break;
    }
    UARTx->LCR = (uint8_t)tmpreg;

    /* FIF0 Enable */
    tmpreg = UARTx->FCR;
    tmpreg &= UART_FCR_FIFO_CLEAR;
    tmpreg |= (uint8_t)UART_InitStruct->UART_FIFO;
    UARTx->FCR = (uint8_t)tmpreg;

    /* Auto Flow Control Enable */
    if (UART_InitStruct->UART_FIFO == UART_FIFO_ENABLE)
    {
        if(UART_InitStruct->UART_HardwareFlowControl != UART_HARDWARE_FLOW_CONTROL_DISABLE)
        {
            UARTx->MCR = UART_HARDWARE_FLOW_CONTROL_ENABLE;
        }
        else
        {
            UARTx->MCR = UART_HARDWARE_FLOW_CONTROL_DISABLE;
        }
    }

    /* Set the baud rate of the UART */
    if( SYS_CTRL->SYS_CLKSEL_b.REG_UART_CLK_SEL == 2)
    {    
        div = ((48000000 << 4) / UART_InitStruct->UART_BaudRate);
    }
    else
    {
        div = ((24000000 << 4) / UART_InitStruct->UART_BaudRate);
    }
    divn = (div >> (4 + 4));
    divf = ((div + ((1 << 4) - 1)) >> 4);
    while ((UARTx->USR & UART_USR_BUSY)); // LCR[7] is writeable only when UART is not busy (USR[0] is zero)
    UARTx->LCR |= UART_LCR_DLAB; 
    UARTx->DLL = (divn >> 0) & 0xFF;         
    UARTx->DLH = (divn >> 8) & 0xFF;	
    UARTx->DLF = divf & 0x0f;
    UARTx->LCR &= (~UART_LCR_DLAB);
}

// 结构体初始化
void UART_StructInit(UART_InitTypeDef* UART_InitStruct)
{
    UART_InitStruct->UART_BaudRate = UART_BAUDRATE_115200;
    UART_InitStruct->UART_WordLength = UART_WORD_LENGTH_8BIT;
    UART_InitStruct->UART_StopBits = UART_STOPBITS_1BIT;
    UART_InitStruct->UART_Parity = UART_PARITY_NONE;
	UART_InitStruct->UART_FIFO = UART_FIFO_ENABLE;
    UART_InitStruct->UART_HardwareFlowControl = UART_HARDWARE_FLOW_CONTROL_DISABLE;
}

// 重置UART
void UART_DeInit(UART_Type* UARTx)
{
    volatile int i;
    if (UARTx == UART0)
    {
        SYS_CTRL->SYS_RESET |= (1 << 10);
        for(i=0; i<10; i++);
        SYS_CTRL->SYS_RESET &= (~(1 << 10));
        /* CLK */
        REG_WRT_BITS(0x40000028, 6, 6, 0);
    }
    else if (UARTx == UART1)
    {
        SYS_CTRL->SYS_RESET |= (1 << 11);
        for(i=0; i<10; i++);
        SYS_CTRL->SYS_RESET &= (~(1 << 11));
        /* CLK */
        REG_WRT_BITS(0x40000028, 7, 7, 0);
    }
    // if both uart are disabled, turn off uart clock
    if(((*(volatile int *)(0x40000028)) & (0x3<<6)) == 0) REG_WRT_BITS(0x40000020, 5, 5, 0);
}

/**
 * 配置UART中断
 * param: UART_IT取值
 *              #define UART_IT_THRE 
                #define UART_IT_MSR 
                #define UART_IT_ELSI  
                #define UART_IT_TXE  
                #define UART_IT_RXF  
                #define UART_IT_ALL 
 *  */ 
void UART_ITConfig(UART_Type* UARTx, uint8_t UART_IT, FunctionalState NewState)
{
    if (NewState != DISABLE)
    {
        UARTx->IER |= UART_IT;
    }
    else
    {
        UARTx->IER &= ~UART_IT;
    }
}

/**
 * 获取UART指定中断ID
 * param: UART_IT取值
                #define UART_IT_FLAG_MODEM_STATUS
                #define UART_IT_FLAG_THR_EMPTY 
                #define UART_IT_FLAG_RECEIVED_AVAILABLE
                #define UART_IT_FLAG_RECEIVER_LINE_STATUS
                #define UART_IT_FLAG_BUSY_DETECT
                #define UART_IT_FLAG_CHARACTER_TIMEOUT
 *  */ 
ITStatus UART_GetITStatus(UART_Type* UARTx, uint8_t ITFlag)
{
    uint8_t bitpos = 0x00;
    ITStatus bitstatus = RESET;
    bitpos = UARTx->IIR & ITFlag;
    if (bitpos != RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;  
}

// 串口发送函数
void UART_SendData(UART_Type* UARTx, uint16_t Data)
{
    /* Transmit Data */
	UARTx->THR = (Data & 0x01FF);
}

// 串口接收函数
uint16_t UART_ReceiveData(UART_Type* UARTx)
{
    /* Receive Data */
    return (UARTx-> RBR & 0x01FF);
}

/**
 * 获取UART的线路状态
 * param: LineFlag:
                #define UART_LINE_FLAG_RFE
                #define UART_LINE_FLAG_TE
                #define UART_LINE_FLAG_THRE
                #define UART_LINE_FLAG_BI
                #define UART_LINE_FLAG_FE
                #define UART_LINE_FLAG_PE
                #define UART_LINE_FLAG_OE
                #define UART_LINE_FLAG_DR
 */
FlagStatus UART_GetLineStatus(UART_Type* UARTx, uint8_t LineFlag)
{ 
	FlagStatus bitstatus = RESET;

    if ((UARTx->LSR & LineFlag) != RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;
}

/**
 * 检查UART标志位
 * param： Flag：
                #define UART_FLAG_RFF 
                #define UART_FLAG_RFNE 
                #define UART_FLAG_TFE
                #define UART_FLAG_TFNF
                #define UART_FLAG_BUSY
 * 
 */
FlagStatus UART_GetUsrStatus(UART_Type* UARTx, uint8_t Flag)
{ 
	FlagStatus bitstatus = RESET;

    if ((UARTx->USR & Flag) != RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;
}

/**
 * 检查UARTModem标志位
 * param： Flag：
                #define UART_MSR_DCD
                #define UART_MSR_RI
                #define UART_MSR_DSR
                #define UART_MSR_CTS
                #define UART_MSR_DDCD
                #define UART_MSR_TERI
                #define UART_MSR_DDSR
                #define UART_MSR_DCTS
 * 
 */
FlagStatus UART_GetMsrStatus(UART_Type* UARTx, uint8_t Flag)
{ 
	FlagStatus bitstatus = RESET;

    if ((UARTx->MSR & Flag) != RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;
}



/**
 * 发送/接收FIFO配置
 * param:RxTrig:
                #define UART_RX_FIFO_ALMOST_FULL
                #define UART_RX_FIFO_HALF_FULL
                #define UART_RX_FIFO_QUARTER_FULL
                #define UART_RX_FIFO_CHAR_1
        TxTrig:
                #define UART_TX_FIFO_HALF_FULL 
                #define UART_TX_FIFO_QUARTER_FULL
                #define UART_TX_FIFO_CHAR_2
                #define UART_TX_FIFO_EMPTY
 * 
 */
void UART_FIFOTrigConfig(UART_Type* UARTx, uint8_t RxTrig, uint8_t TxTrig)
{
    uint8_t tmpreg;
    tmpreg = UARTx->FCR;
    tmpreg &= 0x0F;
    tmpreg |= (RxTrig | TxTrig);
    UARTx->FCR = (uint8_t)tmpreg;
}


