#include "lks32mc09x_uart.h"
#include "lks32mc09x_sys.h"

/**
 * @brief 初始化UART模块
 * @param UARTx UART模块指针
 * @param UART_InitStruct 初始化结构体指针
 */
void UART_Init(UART_TypeDef *UARTx, UART_InitTypeDef *UART_InitStruct)
{
    // 使能UART模块时钟
    if (UARTx == UART0)
    {
        SYS_ModuleClockCmd(SYS_MODULE_UART0, ENABLE);
    }
    else if (UARTx == UART1)
    {
        SYS_ModuleClockCmd(SYS_MODULE_UART1, ENABLE);
    }
    else if (UARTx == UART2)
    {
        SYS_ModuleClockCmd(SYS_MODULE_UART2, ENABLE);
    }

    UART_SetBaud(UARTx, UART_InitStruct->BaudRate);
    // 配置UART控制寄存器
    UARTx->CTRL = (UART_InitStruct->DUPLEX << 7) |
                  (UART_InitStruct->LIN_EN << 6) |
                  (UART_InitStruct->MultiDropEna << 5) |
                  (UART_InitStruct->CK_EN << 4) |
                  (UART_InitStruct->ParityMode << 3) |
                  (UART_InitStruct->FirstSend << 2) |
                  (UART_InitStruct->StopBits << 1) |
                  (UART_InitStruct->WordLength);

    // 配置中断使能寄存器
    UARTx->IE = UART_InitStruct->IRQEna;

    // 配置DMA请求使能寄存器
    UARTx->RE = UART_InitStruct->DMARE;

    // 配置IO极性
    UARTx->IOC =
        (UART_InitStruct->LBDL << 6) |   ///< LIN同步段检测长度 0:10bits 1:11bits
        (UART_InitStruct->ABD_EN << 4) | ///< LIN波特率自适应使能
        (UART_InitStruct->TXD_INV << 1) |
        (UART_InitStruct->RXD_INV) |
        0;
    UARTx->IF = 0x3ff;
}

/**
 * @brief 初始化UART结构体为默认值
 * @param UART_InitStruct 初始化结构体指针
 */
void UART_StructInit(UART_InitTypeDef *UART_InitStruct)
{
    for (int i = 0; i < sizeof(UART_InitTypeDef); i++)
    {
        ((uint8_t *)UART_InitStruct)[i] = 0;
    }

    // 默认配置
    UART_InitStruct->WordLength   = UART_WORDLENGTH_8b;
    UART_InitStruct->StopBits     = UART_STOPBITS_1b;
    UART_InitStruct->FirstSend    = UART_FIRSTSEND_LSB;
    UART_InitStruct->ParityMode   = UART_Parity_NO;
    UART_InitStruct->MultiDropEna = DISABLE;
    UART_InitStruct->DUPLEX       = 0; // 全双工
}

/**
 * @brief 发送数据
 * @param UARTx UART模块指针
 * @param n 要发送的数据
 */
void UART_SendData(UART_TypeDef *UARTx, uint32_t n)
{
    UARTx->BUFF = n & 0xFF;
    while ((UARTx->STT & BIT0) == 0)
    {
        // 等待发送完成
    }
}

/**
 * @brief 读取接收到的数据
 * @param UARTx UART模块指针
 * @return 接收到的数据
 */
uint32_t UART_ReadData(UART_TypeDef *UARTx)
{
    return UARTx->BUFF;
}

/**
 * @brief 发送指定长度的数据
 * @param UARTx UART模块指针
 * @param sendData 要发送的数据指针
 * @param len 数据长度
 */
void UART_SendnData(UART_TypeDef *UARTx, char *sendData, uint32_t len)
{
    for (uint32_t i = 0; i < len; i++)
    {
        UART_SendData(UARTx, sendData[i]);
        // 等待发送完成（简单实现，实际可能需要更复杂的逻辑）
        while (!(UARTx->STT & 0x01));
    }
}

/**
 * @brief 接收指定长度的数据
 * @param UARTx UART模块指针
 * @param recvData 接收数据缓冲区指针
 * @param maxlen 最大接收长度
 */
void UART_RecvnData(UART_TypeDef *UARTx, char *recvData, uint32_t maxlen)
{
    for (uint32_t i = 0; i < maxlen; i++)
    {
        // 等待接收完成（简单实现，实际可能需要更复杂的逻辑）
        while (!(UARTx->STT & 0x02));
        recvData[i] = UART_ReadData(UARTx);
    }
}

/**
 * @brief 清除指定的中断标志
 * @param UARTx UART模块指针
 * @param tempFlag 要清除的中断标志
 */
void UART_ClearIRQFlag(UART_TypeDef *UARTx, uint32_t tempFlag)
{
    UARTx->IF = tempFlag;
}

/**
 * @brief 获取指定的中断标志状态
 * @param UARTx UART模块指针
 * @param tempFlag 要获取的中断标志
 * @return 中断标志状态
 */
uint32_t UART_GetIRQFlag(UART_TypeDef *UARTx, uint32_t tempFlag)
{
    return UARTx->IF & tempFlag;
}

/**
 * @brief 在485模式下发送地址
 * @param UARTx UART模块指针
 * @param n 要发送的地址
 * @return 发送状态（简单实现，总是返回成功）
 */
uint8_t UART_SendAddr_485(UART_TypeDef *UARTx, uint8_t n)
{
    UART_SendData(UARTx, n);
    return 1; // 简单实现，总是返回成功
}

/**
 * @brief 在485模式下发送数据
 * @param UARTx UART模块指针
 * @param n 要发送的数据
 * @return 发送状态（简单实现，总是返回成功）
 */
uint8_t UART_SendData_485(UART_TypeDef *UARTx, uint8_t n)
{
    UART_SendData(UARTx, n);
    return 1; // 简单实现，总是返回成功
}

/**
 * @brief 设置波特率
 * @param UARTx UART模块
 * @param Baud 波特率范围
 * @return 实际波特率（不考虑时钟误差）
 */
uint32_t UART_SetBaud(UART_TypeDef *UARTx, uint32_t Baud)
{
    uint32_t uartclk = SYS_ReadMcuClk() / (SYS->CLK_DIV2 + 1); // 串口的时钟频率
    uint32_t div     = uartclk / Baud - 1;
    if (div > 0xffff)
    {
        div = 0xffff;
    }
    else
    {
        __NOP();
    }
    UARTx->DIVL = div & 0xFF;
    UARTx->DIVH = (div & 0xFF00) >> 8;
    Baud        = uartclk / (div + 1);
    return Baud;
}

uint32_t UART_ReadBaud(UART_TypeDef *UARTx)
{
    uint32_t baud;
    baud = SYS_ReadMcuClk() / (SYS->CLK_DIV2 + 1) / (1 + 256 * UARTx->DIVH + UARTx->DIVL);
    return baud;
}

/**
 * @brief 设置uart时钟分频
 * @param div 分频系数，0对应不分频，1对应2分频
 */
void UART_SetClkDiv(uint32_t div)
{
    SYS_UartClkDiv(div);
}
