#include "r_typedefs.h"
#include "dr7f701684.dvf.h"
#include "UART.h"
#include "rh850_macros.h"

/*-----------------use for RH850_F1KM_S1 --------------------*/
/*******************************************************************/

#define UART_BASE_ADDRESS 0xFFCE2000UL
#define UART_CKSCLK_ILIN  40000000UL

/*******************************************************************/

uint32_t UART_Init(UART_Channel_en_t enUARTCh, UART_Channel_Config_st_t *penUARTCfg);
void     UART_Sleep_Init(UART_Channel_en_t enUARTCh);
/*******************************************************************/
/*******************************************************************/
/*******************************************************************/
#define UART_LSB_FIRST (0U << 1U)
#define UART_MSB_FIRST (1U << 1U)

#define UART_INT_AT_START  (0U << 3U)
#define UART_INT_AT_FINISH (1U << 3U)
/*******************************************************/
typedef struct
{
    uint8_t  u8UARTCount;      /*发送计数*/
    uint8_t  u8UARTLEN;        /*发送数据总长*/
    uint8_t  u8UARTTXBusyFlag; /*发送是否忙标志  0:idle  1:busy */
    uint8_t *pu8UARTDataBuf;   /*要发送数据的指针*/
} UART_Ctr_st_t;
/*******************************************************/

static UART_Ctr_st_t stUARTCtr0;
static UART_Ctr_st_t stUARTCtr1;
static UART_Ctr_st_t stUARTCtr2;
static UART_Ctr_st_t stUARTCtr3;

static UART_Channel_Config_st_t stUARTCh0Cfg;
static UART_Channel_Config_st_t stUARTCh1Cfg;
static UART_Channel_Config_st_t stUARTCh2Cfg;
static UART_Channel_Config_st_t stUARTCh3Cfg;

/*******************************************************/
static void UART_Variate_Init(void)
{
    stUARTCtr0.u8UARTCount      = 0U;
    stUARTCtr0.u8UARTLEN        = 0U;
    stUARTCtr0.u8UARTTXBusyFlag = 0U;
    stUARTCtr0.pu8UARTDataBuf   = 0U;

    stUARTCh0Cfg.u32UARTChEn            = 0U;
    stUARTCh0Cfg.u32UARTbps             = 0U;
    stUARTCh0Cfg.pfnUARTConfirmCallBack = 0U;
    stUARTCh0Cfg.pfnUARTReadMsgCallBack = 0U;

    stUARTCtr1.u8UARTCount      = 0U;
    stUARTCtr1.u8UARTLEN        = 0U;
    stUARTCtr1.u8UARTTXBusyFlag = 0U;
    stUARTCtr1.pu8UARTDataBuf   = 0U;

    stUARTCh1Cfg.u32UARTChEn            = 0U;
    stUARTCh1Cfg.u32UARTbps             = 0U;
    stUARTCh1Cfg.pfnUARTConfirmCallBack = 0U;
    stUARTCh1Cfg.pfnUARTReadMsgCallBack = 0U;

    stUARTCtr2.u8UARTCount      = 0U;
    stUARTCtr2.u8UARTLEN        = 0U;
    stUARTCtr2.u8UARTTXBusyFlag = 0U;
    stUARTCtr2.pu8UARTDataBuf   = 0U;

    stUARTCh2Cfg.u32UARTChEn            = 0U;
    stUARTCh2Cfg.u32UARTbps             = 0U;
    stUARTCh2Cfg.pfnUARTConfirmCallBack = 0U;
    stUARTCh2Cfg.pfnUARTReadMsgCallBack = 0U;

    stUARTCtr3.u8UARTCount      = 0U;
    stUARTCtr3.u8UARTLEN        = 0U;
    stUARTCtr3.u8UARTTXBusyFlag = 0U;
    stUARTCtr3.pu8UARTDataBuf   = 0U;

    stUARTCh3Cfg.u32UARTChEn            = 0U;
    stUARTCh3Cfg.u32UARTbps             = 0U;
    stUARTCh3Cfg.pfnUARTConfirmCallBack = 0U;
    stUARTCh3Cfg.pfnUARTReadMsgCallBack = 0U;
}

/*
返回设置成功的波特率，返回0xFFFFFFFF表示设置失败。
*/
uint32_t UART_Init(UART_Channel_en_t enUARTCh, UART_Channel_Config_st_t *penUARTCfg)
{
    // uint32_t u32UARTRealbps = 0xFFFFFFFFUL;
    uint32_t u32UARTAddressBase = 0UL;
    uint32_t u32UARTAddress     = 0UL;
    uint32_t u32UARTCalBuf      = 0UL;

    UART_Variate_Init( );

    if ( (enUARTCh < UART_RLIN_MAX) && (penUARTCfg->u32UARTChEn) && (penUARTCfg->u32UARTbps) )
    {
        u32UARTAddressBase = UART_BASE_ADDRESS + 0x40UL * enUARTCh;

        u32UARTAddress                     = u32UARTAddressBase + 0x20U;
        (*(( uint8_t * )(u32UARTAddress))) = 0X00U;
        //  RLN31LUOER = 0X00U;

        u32UARTAddress                     = u32UARTAddressBase + 0x08U;
        (*(( uint8_t * )(u32UARTAddress))) = 0X00U;
        // RLN31LMD = 0X0U;
        /*****LIN reset mode*/
        u32UARTAddress                     = u32UARTAddressBase + 0x0EU;
        (*(( uint8_t * )(u32UARTAddress))) = 0X00U;
        //  RLN31LCUC = 0X0U;
        u32UARTAddress = u32UARTAddressBase + 0x11U;
        while ( (*(( uint8_t * )(u32UARTAddress))) != 0U )
        //  while (RLN31LMST != 0U)
        {
        }

        /** baud rate**/
        u32UARTAddress                     = u32UARTAddressBase + 0x01U;
        (*(( uint8_t * )(u32UARTAddress))) = 0X50U;
        /*6 samplings  Prescaler Clock Select1/1*/
        // RLN31LWBR = 0X50U;

        u32UARTCalBuf = UART_CKSCLK_ILIN / 6UL / penUARTCfg->u32UARTbps;
        if ( u32UARTCalBuf )
        {
            u32UARTAddress                      = u32UARTAddressBase + 0x02U;
            (*(( uint16_t * )(u32UARTAddress))) = u32UARTCalBuf - 1U;
            // RLN31LBRP01 = u32UARTCalBuf - 1U;
            penUARTCfg->u32UARTbps = UART_CKSCLK_ILIN / 6UL / u32UARTCalBuf;
        }
        else
        {
            penUARTCfg->u32UARTbps = 0xFFFFFFFFUL;
        }

        /**The noise filter is enabled**/
        u32UARTAddress                     = u32UARTAddressBase + 0x08U;
        (*(( uint8_t * )(u32UARTAddress))) = 0X01U;
        // RLN31LMD = 0X01U;

        /**disable error detection.**/
        u32UARTAddress                     = u32UARTAddressBase + 0x0DU;
        (*(( uint8_t * )(u32UARTAddress))) = 0X00U;
        //  RLN31LEDE = 0U;
        /*** data format   N81*/
        u32UARTAddress                     = u32UARTAddressBase + 0x09U;
        (*(( uint8_t * )(u32UARTAddress))) = UART_LSB_FIRST;
        // RLN31LBFC = UART_MSB_FIRST;
        /*Transmission interrupt is generated at.*/
        u32UARTAddress                     = u32UARTAddressBase + 0x21U;
        (*(( uint8_t * )(u32UARTAddress))) = UART_INT_AT_FINISH;
        // RLN31LUOR1 = UART_INT_AT_FINISH;
        /******Exits from LIN reset mode***/
        u32UARTAddress                     = u32UARTAddressBase + 0x0EU;
        (*(( uint8_t * )(u32UARTAddress))) = 0X01U;
        // RLN31LCUC = 0X01U;

        u32UARTAddress = u32UARTAddressBase + 0x11U;
        while ( (*(( uint8_t * )(u32UARTAddress))) != 0X01U )
        //  while (RLN31LMST != 0X01U)
        {
        }

        u32UARTAddress                     = u32UARTAddressBase + 0x13U;
        (*(( uint8_t * )(u32UARTAddress))) = 0X0U;
        // RLN31LEST = 0X0U; /*clear Error Flag , it doesn't matter*/

        u32UARTAddress                     = u32UARTAddressBase + 0x20U;
        (*(( uint8_t * )(u32UARTAddress))) = 0X03U;
        //  RLN31LUOER = 0X03U; /*TX RX EN*/

        /***************************/
        /**********NO USE*****************/

        /***************************/

        if ( enUARTCh == UART_RLIN30 )
        {
            stUARTCh0Cfg = *penUARTCfg;
            peripheral_IRQ_enable(INTRLIN30UR0);
            peripheral_IRQ_enable(INTRLIN30UR1);
        }
        else if ( enUARTCh == UART_RLIN31 )
        {
            stUARTCh1Cfg = *penUARTCfg;
            peripheral_IRQ_enable(INTRLIN31UR0);
            peripheral_IRQ_enable(INTRLIN31UR1);
        }
        else if ( enUARTCh == UART_RLIN32 )
        {
            stUARTCh2Cfg = *penUARTCfg;
            peripheral_IRQ_enable(INTRLIN32UR0);
            peripheral_IRQ_enable(INTRLIN32UR1);
        }
        else if ( enUARTCh == UART_RLIN33 )
        {
            stUARTCh3Cfg = *penUARTCfg;
            peripheral_IRQ_enable(INTRLIN33UR0);
            peripheral_IRQ_enable(INTRLIN33UR1);
        }

        /***************************/
    }
    return penUARTCfg->u32UARTbps;
}

void UART_Sleep_Init(UART_Channel_en_t enUARTCh)
{

    uint32_t u32UARTAddressBase = 0UL;
    uint32_t u32UARTAddress     = 0UL;

    if ( (enUARTCh < UART_RLIN_MAX) )
    {
        u32UARTAddressBase = UART_BASE_ADDRESS + 0x40UL * enUARTCh;

        u32UARTAddress                     = u32UARTAddressBase + 0x20U;
        (*(( uint8_t * )(u32UARTAddress))) = 0X00U;
        //  RLN31LUOER = 0X00U;

        u32UARTAddress                     = u32UARTAddressBase + 0x08U;
        (*(( uint8_t * )(u32UARTAddress))) = 0X00U;
        // RLN31LMD = 0X0U;
        /*****LIN reset mode*/
        u32UARTAddress                     = u32UARTAddressBase + 0x0EU;
        (*(( uint8_t * )(u32UARTAddress))) = 0X00U;
        //  RLN31LCUC = 0X0U;
        u32UARTAddress = u32UARTAddressBase + 0x11U;
        while ( (*(( uint8_t * )(u32UARTAddress))) != 0U )
        //  while (RLN31LMST != 0U)
        {
        }
    }
    UART_Variate_Init( );
}
/*
0：idle
1：busy
*/
uint8_t UART_Ch0_Get_TX_Busy_Flag(void)
{
    uint8_t u8Status = 0U;
    if ( (RLN30LST & 0x10U) || (stUARTCtr0.u8UARTTXBusyFlag) )
    {
        u8Status = 1U;
    }
    return u8Status;
}
uint8_t UART_Ch1_Get_TX_Busy_Flag(void)
{
    uint8_t u8Status = 0U;
    if ( (RLN31LST & 0x10U) || (stUARTCtr1.u8UARTTXBusyFlag) )
    {
        u8Status = 1U;
    }
    return u8Status;
}
uint8_t UART_Ch2_Get_TX_Busy_Flag(void)
{
    uint8_t u8Status = 0U;
    if ( (RLN32LST & 0x10U) || (stUARTCtr2.u8UARTTXBusyFlag) )
    {
        u8Status = 1U;
    }
    return u8Status;
}
uint8_t UART_Ch3_Get_TX_Busy_Flag(void)
{
    uint8_t u8Status = 0U;
    if ( (RLN33LST & 0x10U) || (stUARTCtr3.u8UARTTXBusyFlag) )
    {
        u8Status = 1U;
    }
    return u8Status;
}
/*
Data：要发送数据的指针，
请确认是全局变量的指针，且指向的数据在发送完成之前不会被改变。
*/
void UART_Ch0_Send_Multiple_Byte(uint8_t *Data, uint8_t Len)
{
    if ( UART_Ch0_Get_TX_Busy_Flag( ) == 0U )
    {
        stUARTCtr0.u8UARTCount      = 1U;
        stUARTCtr0.u8UARTLEN        = Len;
        stUARTCtr0.u8UARTTXBusyFlag = 1U;
        stUARTCtr0.pu8UARTDataBuf   = Data;
        RLN30LUTDR                  = stUARTCtr0.pu8UARTDataBuf [ 0U ];
    }
}
uint8_t UART_Ch1_Send_Multiple_Byte(uint8_t *Data, uint8_t Len)
{
    uint8_t Ret= 0U;
    if ( UART_Ch1_Get_TX_Busy_Flag( ) == 0U )
    {
        stUARTCtr1.u8UARTCount      = 1U;
        stUARTCtr1.u8UARTLEN        = Len;
        stUARTCtr1.u8UARTTXBusyFlag = 1U;
        stUARTCtr1.pu8UARTDataBuf   = Data;
        RLN31LUTDR                  = stUARTCtr1.pu8UARTDataBuf [ 0U ];
        Ret= 0U;
    }else
    {
        Ret= 1U;
    }
    return Ret;
}
void UART_Ch2_Send_Multiple_Byte(uint8_t *Data, uint8_t Len)
{
    if ( UART_Ch2_Get_TX_Busy_Flag( ) == 0U )
    {
        stUARTCtr2.u8UARTCount      = 1U;
        stUARTCtr2.u8UARTLEN        = Len;
        stUARTCtr2.u8UARTTXBusyFlag = 1U;
        stUARTCtr2.pu8UARTDataBuf   = Data;
        RLN32LUTDR                  = stUARTCtr2.pu8UARTDataBuf [ 0U ];
    }
}
void UART_Ch3_Send_Multiple_Byte(uint8_t *Data, uint8_t Len)
{
    if ( UART_Ch3_Get_TX_Busy_Flag( ) == 0U )
    {
        stUARTCtr3.u8UARTCount      = 1U;
        stUARTCtr3.u8UARTLEN        = Len;
        stUARTCtr3.u8UARTTXBusyFlag = 1U;
        stUARTCtr3.pu8UARTDataBuf   = Data;
        RLN33LUTDR                  = stUARTCtr3.pu8UARTDataBuf [ 0U ];
    }
}

void UART_CH0_RX_ISR(void)
{
    /*If no error is detected*/
    if ( stUARTCh0Cfg.pfnUARTReadMsgCallBack )
    {
        stUARTCh0Cfg.pfnUARTReadMsgCallBack(RLN30LURDR);
    }
}
void UART_CH1_RX_ISR(void)
{
    /*If no error is detected*/
    if ( stUARTCh1Cfg.pfnUARTReadMsgCallBack )
    {
        stUARTCh1Cfg.pfnUARTReadMsgCallBack(RLN31LURDR);
    }
}
void UART_CH2_RX_ISR(void)
{
    /*If no error is detected*/
    if ( stUARTCh2Cfg.pfnUARTReadMsgCallBack )
    {
        stUARTCh2Cfg.pfnUARTReadMsgCallBack(RLN32LURDR);
    }
}
void UART_CH3_RX_ISR(void)
{
    /*If no error is detected*/
    if ( stUARTCh3Cfg.pfnUARTReadMsgCallBack )
    {
        stUARTCh3Cfg.pfnUARTReadMsgCallBack(RLN33LURDR);
    }
}

void UART_CH0_TX_ISR(void)
{
    if ( stUARTCtr0.u8UARTCount < stUARTCtr0.u8UARTLEN )
    {
        RLN30LUTDR = stUARTCtr0.pu8UARTDataBuf [ stUARTCtr0.u8UARTCount++ ];
    }
    else
    {
        stUARTCtr0.u8UARTTXBusyFlag = 0U;
        if ( stUARTCh0Cfg.pfnUARTConfirmCallBack )
        {
            stUARTCh0Cfg.pfnUARTConfirmCallBack( );
        }
    }
}
void UART_CH1_TX_ISR(void)
{
    if ( stUARTCtr1.u8UARTCount < stUARTCtr1.u8UARTLEN )
    {
        RLN31LUTDR = stUARTCtr1.pu8UARTDataBuf [ stUARTCtr1.u8UARTCount++ ];
    }
    else
    {
        stUARTCtr1.u8UARTTXBusyFlag = 0U;
        if ( stUARTCh1Cfg.pfnUARTConfirmCallBack )
        {
            stUARTCh1Cfg.pfnUARTConfirmCallBack( );
        }
    }
}
void UART_CH2_TX_ISR(void)
{
    if ( stUARTCtr2.u8UARTCount < stUARTCtr2.u8UARTLEN )
    {
        RLN32LUTDR = stUARTCtr2.pu8UARTDataBuf [ stUARTCtr2.u8UARTCount++ ];
    }
    else
    {
        stUARTCtr2.u8UARTTXBusyFlag = 0U;
        if ( stUARTCh2Cfg.pfnUARTConfirmCallBack )
        {
            stUARTCh2Cfg.pfnUARTConfirmCallBack( );
        }
    }
}
void UART_CH3_TX_ISR(void)
{
    if ( stUARTCtr3.u8UARTCount < stUARTCtr3.u8UARTLEN )
    {
        RLN33LUTDR = stUARTCtr3.pu8UARTDataBuf [ stUARTCtr3.u8UARTCount++ ];
    }
    else
    {
        stUARTCtr3.u8UARTTXBusyFlag = 0U;
        if ( stUARTCh3Cfg.pfnUARTConfirmCallBack )
        {
            stUARTCh3Cfg.pfnUARTConfirmCallBack( );
        }
    }
}

uint8_t Get_Uart_BusyFlash(void)
{
    return UART_Ch1_Get_TX_Busy_Flag( );
}
