#include "bsp_uart.h"
#include "string.h"

/* RS485控制宏定义 */
#define RS485_1_RX HAL_GPIO_WritePin(RS485_1_EN_GPIO_Port, RS485_1_EN_Pin, GPIO_PIN_RESET)
#define RS485_1_TX HAL_GPIO_WritePin(RS485_1_EN_GPIO_Port, RS485_1_EN_Pin, GPIO_PIN_SET)
#define RS485_2_RX HAL_GPIO_WritePin(RS485_2_EN_GPIO_Port, RS485_2_EN_Pin, GPIO_PIN_RESET)
#define RS485_2_TX HAL_GPIO_WritePin(RS485_2_EN_GPIO_Port, RS485_2_EN_Pin, GPIO_PIN_SET)
#define RS485_3_RX HAL_GPIO_WritePin(RS485_3_EN_GPIO_Port, RS485_3_EN_Pin, GPIO_PIN_RESET)
#define RS485_3_TX HAL_GPIO_WritePin(RS485_3_EN_GPIO_Port, RS485_3_EN_Pin, GPIO_PIN_SET)
#define RS485_4_RX HAL_GPIO_WritePin(RS485_4_EN_GPIO_Port, RS485_4_EN_Pin, GPIO_PIN_RESET)
#define RS485_4_TX HAL_GPIO_WritePin(RS485_4_EN_GPIO_Port, RS485_4_EN_Pin, GPIO_PIN_SET)

/* 缓冲收发区大小 */
#define RX_TEMP_BUFF_NUM (128U)

/* UART缓冲区大小定义 */
#define UART1_TX_LEN (128U)
#define UART1_RX_LEN (128U)
               
#define UART2_TX_LEN (128U)
#define UART2_RX_LEN (128U)

#define UART3_TX_LEN (128U)
#define UART3_RX_LEN (128U)

#define UART4_TX_LEN (128U)
#define UART4_RX_LEN (128U)

#define UART6_TX_LEN (128U)
#define UART6_RX_LEN (128U)

/* 全局缓冲区变量 */
u8 uart1_tx_buff[UART1_TX_LEN];
u8 uart1_rx_buff[UART1_RX_LEN];

u8 uart2_tx_buff[UART2_TX_LEN];
u8 uart2_rx_buff[UART2_RX_LEN];

u8 uart3_tx_buff[UART3_TX_LEN];
u8 uart3_rx_buff[UART3_RX_LEN];

u8 uart4_tx_buff[UART4_TX_LEN];
u8 uart4_rx_buff[UART4_RX_LEN];

u8 uart6_tx_buff[UART6_TX_LEN];
u8 uart6_rx_buff[UART6_RX_LEN];

u8 rx_temp_buff[RX_TEMP_BUFF_NUM];

/* 函数声明 */
static void bsp_uart_init(bsp_uart_t *p_uart);
static void bsp_uart_send(bsp_uart_t *p_uart, u8 *p_data, u16 len);
static void bsp_uart_rx_idle_int(bsp_uart_t *p_uart);
static void bsp_uart_rx_time_increment(bsp_uart_t *p_uart, u16 time);
static void bsp_uart_rx_task(bsp_uart_t *p_uart);
static void bsp_uart_rx_time_start(bsp_uart_t *p_uart);
static void bsp_uart_tx_dma_tc_int(bsp_uart_t *p_uart);
static void bsp_uart_dma_send(bsp_uart_t *p_uart, u8 *p_data, u16 len); 
static void bsp_uart_baud_rate_set(bsp_uart_t *p_uart,u32 baud_rate);

/* 外部HAL句柄声明 */
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;
extern UART_HandleTypeDef huart4;
extern UART_HandleTypeDef huart6;

extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern DMA_HandleTypeDef hdma_usart3_rx;
extern DMA_HandleTypeDef hdma_usart3_tx;
extern DMA_HandleTypeDef hdma_uart4_rx;
extern DMA_HandleTypeDef hdma_uart4_tx;
extern DMA_HandleTypeDef hdma_usart6_rx;
extern DMA_HandleTypeDef hdma_usart6_tx;
/******************************************
 * 结构体: com_uart1
 * 功能: UART1控制实例
 * 描述: 定义UART1的硬件参数和回调函数
*******************************************/
bsp_uart_t com_uart1 =
{ 
    .rx_queue = queue(u8, UART1_RX_LEN),
    .uart = &huart1,
    
    .tx_dma = &hdma_usart1_tx,
    .rx_dma = &hdma_usart1_rx,
    
    .tx_dma_len = UART1_TX_LEN,
    .rx_dma_len = UART1_RX_LEN,
    
    .tx_addr = &uart1_tx_buff[0],
    .rx_addr = &uart1_rx_buff[0],
    
    .tx_dma_complete_flag = 1,
    .rx_time_over = 0,

    .relay.uart = NULL,
    
    .init = bsp_uart_init,
    .send = bsp_uart_send,
    
    .set  = bsp_uart_baud_rate_set,
    .tx_dma_tc_int = bsp_uart_tx_dma_tc_int,
    .rx_idle_int = bsp_uart_rx_idle_int,
    .rx_time_increment_int = bsp_uart_rx_time_increment,
    .rx_data_analysis = NULL,
    .rx_task = bsp_uart_rx_task,
 
};

/******************************************
 * 结构体: com_uart2
 * 功能: UART2控制实例
 * 描述: 定义UART2的硬件参数和回调函数
*******************************************/
bsp_uart_t com_uart2 =
{ 
    .rx_queue = queue(u8, UART2_RX_LEN),
    .uart = &huart2,
    
    .tx_dma = &hdma_usart2_tx,
    .rx_dma = &hdma_usart2_rx,
    
    .tx_dma_len = UART2_TX_LEN,
    .rx_dma_len = UART2_RX_LEN,
    
    .tx_addr = &uart2_tx_buff[0],
    .rx_addr = &uart2_rx_buff[0],
    
    .tx_dma_complete_flag = 1,
    .rx_time_over = 0,

    .relay.uart = &com_uart4,
    
    .set  = bsp_uart_baud_rate_set,
    .init = bsp_uart_init,
    .send = bsp_uart_send,
    .tx_dma_tc_int = bsp_uart_tx_dma_tc_int,
    .rx_idle_int = bsp_uart_rx_idle_int,
    .rx_time_increment_int = bsp_uart_rx_time_increment,
    .rx_data_analysis = NULL,
    .rx_task = bsp_uart_rx_task,
};

/******************************************
 * 结构体: com_uart3
 * 功能: UART2控制实例
 * 描述: 定义UART2的硬件参数和回调函数
*******************************************/
bsp_uart_t com_uart3 =
{ 
    .rx_queue = queue(u8, UART3_RX_LEN),
    .uart = &huart3,
    
    .tx_dma = &hdma_usart3_tx,
    .rx_dma = &hdma_usart3_rx,
    
    .tx_dma_len = UART3_TX_LEN,
    .rx_dma_len = UART3_RX_LEN,
    
    .tx_addr = &uart3_tx_buff[0],
    .rx_addr = &uart3_rx_buff[0],
    
    .tx_dma_complete_flag = 1,
    .rx_time_over = 0,

    .relay.uart = &com_uart3,
    
    .set  = bsp_uart_baud_rate_set,
    .init = bsp_uart_init,
    .send = bsp_uart_send,
    .tx_dma_tc_int = bsp_uart_tx_dma_tc_int,
    .rx_idle_int = bsp_uart_rx_idle_int,
    .rx_time_increment_int = bsp_uart_rx_time_increment,
    .rx_data_analysis = NULL,
    .rx_task = bsp_uart_rx_task,
};



/******************************************
 * 结构体: com_uart4
 * 功能: UART4控制实例
 * 描述: 定义UART4的硬件参数和回调函数
*******************************************/
bsp_uart_t com_uart4 =
{ 
    .rx_queue = queue(u8, UART4_RX_LEN),
    .uart = &huart4,
    
    .tx_dma = &hdma_uart4_tx,
    .rx_dma = &hdma_uart4_rx,
    
    .tx_dma_len = UART4_TX_LEN,
    .rx_dma_len = UART4_RX_LEN,
    
    .tx_addr = &uart4_tx_buff[0],
    .rx_addr = &uart4_rx_buff[0],
    
    .tx_dma_complete_flag = 1,
    .rx_time_over = 0,

    .relay.uart = NULL,

    .set  = bsp_uart_baud_rate_set,
    .init = bsp_uart_init,
    .send = bsp_uart_send,
    .tx_dma_tc_int = bsp_uart_tx_dma_tc_int,
    .rx_idle_int = bsp_uart_rx_idle_int,
    .rx_time_increment_int = bsp_uart_rx_time_increment,
    .rx_data_analysis = NULL,
    .rx_task = bsp_uart_rx_task,
};

/******************************************
 * 结构体: com_uart6
 * 功能: UART6控制实例
 * 描述: 定义UART4的硬件参数和回调函数
*******************************************/
bsp_uart_t com_uart6 =
{ 
    .rx_queue = queue(u8, UART6_RX_LEN),
    .uart = &huart6,
    
    .tx_dma = &hdma_usart6_tx,
    .rx_dma = &hdma_usart6_rx,
    
    .tx_dma_len = UART6_TX_LEN,
    .rx_dma_len = UART6_RX_LEN,
    
    .tx_addr = &uart6_tx_buff[0],
    .rx_addr = &uart6_rx_buff[0],
    
    .tx_dma_complete_flag = 1,
    .rx_time_over = 0,

    .relay.uart = NULL,

    .set  = bsp_uart_baud_rate_set,
    
    .init = bsp_uart_init,
    .send = bsp_uart_send,
    .tx_dma_tc_int = bsp_uart_tx_dma_tc_int,
    .rx_idle_int = bsp_uart_rx_idle_int,
    .rx_time_increment_int = bsp_uart_rx_time_increment,
    .rx_data_analysis = NULL,
    .rx_task = bsp_uart_rx_task,
};



/******************************************
 * 函数: bsp_uart_init
 * 功能: UART初始化
 * 参数: p_uart - 指向UART结构体的指针
 * 返回: 无
 * 描述: 初始化UART，使能空闲中断和DMA接收
*******************************************/
static void bsp_uart_init(bsp_uart_t *p_uart)
{  
    /* 启用空闲中断 */
    __HAL_UART_ENABLE_IT(p_uart->uart, UART_IT_IDLE);
    
    /* 重新启动接收，使用空闲中断模式 */
    HAL_UARTEx_ReceiveToIdle_DMA(p_uart->uart, p_uart->rx_addr, p_uart->rx_dma_len);
}

static void bsp_uart_baud_rate_set(bsp_uart_t *p_uart,u32 baud_rate)
{
    p_uart->uart->Init.BaudRate = baud_rate;
    HAL_UART_Init(p_uart->uart);
}

static void bsp_uart_tx_begin_call_back(bsp_uart_t *p_uart)
{
    /* RS485切换到发送模式 */
    if(p_uart == &com_uart4)
    {
        RS485_1_TX;
    }
    else if(p_uart == &com_uart2)
    {
        RS485_2_TX;
    }
    else if(p_uart == &com_uart3)
    {
        RS485_3_TX;
    }
    else if(p_uart == &com_uart6)
    {
        RS485_4_TX;
    }
}

static void bsp_uart_tx_end_call_back(bsp_uart_t *p_uart)
{
    /* RS485切换到发送模式 */
    if(p_uart == &com_uart4)
    {
        RS485_1_RX;
    }
    else if(p_uart == &com_uart2)
    {
        RS485_2_RX;
    }
    else if(p_uart == &com_uart3)
    {
        RS485_3_RX;
    }
    else if(p_uart == &com_uart6)
    {
        RS485_4_RX;
    }
}


/******************************************
 * 函数: bsp_uart_dma_send
 * 功能: DMA发送函数
 * 参数: p_uart - 指向UART结构体的指针
 *       p_data - 要发送的数据指针
 *       len - 要发送的数据长度
 * 返回: 无
 * 描述: 使用DMA发送数据，带有超时检测
*******************************************/
static void bsp_uart_dma_send(bsp_uart_t *p_uart, u8 *p_data, u16 len)
{
    u32 tick_start, tick;
    
    p_uart->tx_dma_complete_flag = 0;      
    
    /* 如果请求发送的长度大于缓冲区长度，则截断 */
    if(p_uart->tx_dma_len < len)
        len = p_uart->tx_dma_len;
    
    /* 拷贝数据到发送缓冲区 */
    memcpy(p_uart->tx_addr, p_data, len);
    
    HAL_UART_Transmit(p_uart->uart, p_uart->tx_addr, len,50);
//    /* 启动DMA发送 */
//    HAL_UART_Transmit_DMA(p_uart->uart, p_uart->tx_addr, len);
//    
//    /* 等待发送完成，带超时检测 */
//    tick_start = HAL_GetTick();
//    while(!p_uart->tx_dma_complete_flag)
//    {
//        tick = HAL_GetTick();
//        if((tick - tick_start) > 200)  /* 200ms超时 */
//        {
//            p_uart->tx_dma_complete_flag = 1;
//            break;
//        }
//    }
}

/******************************************
 * 函数: bsp_uart_send
 * 功能: UART发送函数
 * 参数: p_uart - 指向UART结构体的指针
 *       p_data - 要发送的数据指针
 *       len - 要发送的数据长度
 * 返回: 无
 * 描述: 大数据量发送函数，支持分块发送
*******************************************/
static void bsp_uart_send(bsp_uart_t *p_uart, u8 *p_data, u16 len)
{
    u16 i, send_num;
    
   bsp_uart_tx_begin_call_back(p_uart);

    
    /* 计算需要发送的次数 */
    send_num = len / p_uart->tx_dma_len;
    
    /* 分块发送数据 */
    for(i = 0; i < send_num; i++)
    {
        bsp_uart_dma_send(p_uart, &p_data[p_uart->tx_dma_len * i], p_uart->tx_dma_len);
    }
    
    /* 发送剩余数据 */
    len -= p_uart->tx_dma_len * i;
    if(0 != len)
    {
        bsp_uart_dma_send(p_uart, &p_data[p_uart->tx_dma_len * i], len);
    }
    bsp_uart_tx_end_call_back(p_uart);
}

/******************************************
 * 函数: bsp_uart_tx_dma_tc_int
 * 功能: DMA发送完成中断处理
 * 参数: p_uart - 指向UART结构体的指针
 * 返回: 无
 * 描述: 在DMA发送完成中断中调用，设置发送完成标志
*******************************************/
static void bsp_uart_tx_dma_tc_int(bsp_uart_t *p_uart)
{
    p_uart->tx_dma_complete_flag = 1;
}

/******************************************
 * 函数: bsp_uart_rx_idle_int
 * 功能: 空闲中断处理
 * 参数: p_uart - 指向UART结构体的指针
 * 返回: 无
 * 描述: 处理UART空闲中断，将接收到的数据存入队列
*******************************************/
static void bsp_uart_rx_idle_int(bsp_uart_t *p_uart)
{
    u16 rx_length, i;
    
    /* 停止接收 */
    HAL_UART_DMAStop(p_uart->uart);    

    /* 计算接收到的数据长度 */
    rx_length = p_uart->rx_dma_len - __HAL_DMA_GET_COUNTER(p_uart->rx_dma);
    
    /* 如果长度为0，直接返回 */
    if (rx_length == 0) 
    {
        return;
    }
   
    /* 将接收到的数据存入队列 */
    for (i = 0; i < rx_length; i++) 
    {
        queue_push_back(p_uart->rx_queue, (void *)&p_uart->rx_addr[i]);
    }
    
    /* 开始接收超时计时 */
    bsp_uart_rx_time_start(p_uart);
    
    /* 重新启动接收 */
    HAL_UARTEx_ReceiveToIdle_DMA(p_uart->uart, p_uart->rx_addr, p_uart->rx_dma_len);
}

/******************************************
 * 函数: bsp_uart_rx_time_increment
 * 功能: 接收超时时间递增
 * 参数: p_uart - 指向UART结构体的指针
 *       time - 增加的时间值
 * 返回: 无
 * 描述: 在中断中调用，递增接收超时计数器
*******************************************/
static void bsp_uart_rx_time_increment(bsp_uart_t *p_uart, u16 time)
{
    /* 如果已经开始计数，则增加时间 */
    if(1 == p_uart->rx_start_flag)
    {
        p_uart->rx_time_count += time;
    }
}

/******************************************
 * 函数: bsp_uart_rx_time_start
 * 功能: 启动接收超时计时
 * 参数: p_uart - 指向UART结构体的指针
 * 返回: 无
 * 描述: 开始接收超时计数
*******************************************/
static void bsp_uart_rx_time_start(bsp_uart_t *p_uart)
{
    p_uart->rx_start_flag = 1;
    p_uart->rx_time_count = 0;
}

/******************************************
 * 函数: bsp_uart_rx_time_stop
 * 功能: 停止接收超时计时
 * 参数: p_uart - 指向UART结构体的指针
 * 返回: 无
 * 描述: 停止接收超时计数
*******************************************/
static void bsp_uart_rx_time_stop(bsp_uart_t *p_uart)
{
    p_uart->rx_start_flag = 0;
    p_uart->rx_time_count = 0;
}

/******************************************
 * 函数: bsp_uart_rx_task
 * 功能: UART接收任务
 * 参数: p_uart - 指向UART结构体的指针
 * 返回: 无
 * 描述: 检查接收超时，处理接收到的数据帧
*******************************************/
static void bsp_uart_rx_task(bsp_uart_t *p_uart)
{
    /* 检查是否超时，接收到一帧数据 */
    if(p_uart->rx_time_over < p_uart->rx_time_count)
    {
        /* 获取队列中数据长度 */
        p_uart->rx_len = queue_size(p_uart->rx_queue);
        
        /* 停止计时 */
        bsp_uart_rx_time_stop(p_uart);
        
        /* 检查数据长度是否有效 */
        if(p_uart->rx_len <= p_uart->rx_dma_len && (0 != p_uart->rx_len))
        {
            /* 如果数据长度超过临时缓冲区大小，则清空队列 */
            if(RX_TEMP_BUFF_NUM < p_uart->rx_len)
            {
                 queue_clear(p_uart->rx_queue);
            }
            else
            {
                /* 从队列中取出数据到临时缓冲区 */
                for(u16 i = 0; i < p_uart->rx_len; i++)
                {
                    queue_pop(p_uart->rx_queue, &rx_temp_buff[i]);
                }
                
                /* 如果有数据解析函数，则调用解析函数 */
                if(NULL != p_uart->rx_data_analysis)
                {
                    p_uart->rx_data_analysis(rx_temp_buff, p_uart->rx_len, p_uart);
                }
//                if(p_uart == &com_uart6)
//                {
//                    p_uart->send(p_uart, rx_temp_buff, p_uart->rx_len);
//                }
            }
        }
    }
}





// 错误回调函数中处理ORE
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) 
{
    bsp_uart_t *p_uart = NULL;
    if (huart->Instance == USART1) 
    {
        p_uart = &com_uart1;
    }
    else if (huart->Instance == USART2) 
    {
        p_uart = &com_uart2;
    }
    else if (huart->Instance == USART3) 
    {
        p_uart = &com_uart3;
    }
    else if (huart->Instance == UART4) 
    {
        p_uart = &com_uart4;
    }
    else if (huart->Instance == USART6) 
    {
        p_uart = &com_uart6;
    }
    
        // 检查具体错误类型
    if(huart->ErrorCode & HAL_UART_ERROR_NE)
    {
        // 处理噪声错误
        __HAL_UART_CLEAR_NEFLAG(huart);
    }
    if(huart->ErrorCode & HAL_UART_ERROR_FE)
    {
        // 处理帧错误
        __HAL_UART_CLEAR_FEFLAG(huart);
    }
    // 其他错误处理...
    if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) 
     {
         __HAL_UART_CLEAR_OREFLAG(huart); // 清除ORE标志
     }
        if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET) 
     {
         __HAL_UART_CLEAR_FEFLAG(huart); // 清除ORE标志
     }
        
//    
    if(p_uart != NULL)
    {
//        HAL_UART_DeInit(huart);
//        HAL_UART_Init(huart);
//        HAL_UART_DMAStop(p_Uart->Uart);
        HAL_UARTEx_ReceiveToIdle_DMA(p_uart->uart, p_uart->rx_addr, p_uart->rx_dma_len);
    }
}

// 实现空闲中断回调
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart->Instance == USART1) 
    {
        bsp_uart_rx_idle_int(&com_uart1);
    } 
    else if (huart->Instance == USART2) 
    {
        bsp_uart_rx_idle_int(&com_uart2);
    } 
    else if (huart->Instance == USART3) 
    {
        bsp_uart_rx_idle_int(&com_uart3);
    } 
    else if (huart->Instance == UART4) 
    {
        bsp_uart_rx_idle_int(&com_uart4);
    }
    else if (huart->Instance == USART6) 
    {
        bsp_uart_rx_idle_int(&com_uart6);
    } 
}

/* 串口接收完成回调函数 - 处理空闲中断 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//    if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE)) 
//    {
//        __HAL_UART_CLEAR_IDLEFLAG(huart);

//        if (huart->Instance == USART1) 
//        {
//            bsp_Uart_Rx_IdleInt(&COM_Uart1);
//        } 
//        else if (huart->Instance == USART2) 
//        {
//            bsp_Uart_Rx_IdleInt(&COM_Uart2);
//        } 
//        else if (huart->Instance == UART4) 
//        {
//            bsp_Uart_Rx_IdleInt(&COM_Uart4);
//        }
//    }
}


void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) 
{
    if (huart->Instance == USART1) 
    {
        bsp_uart_tx_dma_tc_int(&com_uart1);
    }
    else if (huart->Instance == USART2) 
    {
        bsp_uart_tx_dma_tc_int(&com_uart2);
    }
    else if (huart->Instance == USART3) 
    {
        bsp_uart_tx_dma_tc_int(&com_uart3);
    }
    else if (huart->Instance == UART4) 
    {
        bsp_uart_tx_dma_tc_int(&com_uart4);
    }
    else if (huart->Instance == USART6) 
    {
        bsp_uart_tx_dma_tc_int(&com_uart6);
    }
}

