// 串口驱动
// 杭州秒寻科技有限公司
// 周涛
// 2023-09-12

#include "includes.h"
#include "misc.h"

// 定义全局变量
static UART_RECEIVE_MANAGE_T gUart_stGuiReceive = {0};
static UART_RECEIVE_MANAGE_T gUart_stWifiReceive = {0};

// 初始化所有要使用的串口
void driver_uart_init()
{
    memset(&gUart_stGuiReceive, 0, sizeof(UART_RECEIVE_MANAGE_T));
    memset(&gUart_stWifiReceive, 0, sizeof(UART_RECEIVE_MANAGE_T));

    return;
}

// 初始化串口(调试串口)
void driver_uart_init_debug()
{
    GPIO_InitTypeDef stGpio = {0};
    USART_InitTypeDef stUsart = {0};
    NVIC_InitTypeDef stNvic = {0};

    RCC_AHB1PeriphClockCmd(DRIVER_DEBUG_GPIO_CLK, ENABLE); // 使能GPIO时钟
    stGpio.GPIO_Mode = GPIO_Mode_AF;
    stGpio.GPIO_Speed = GPIO_Fast_Speed;

    // 初始化GPIO脚(TX)
    GPIO_PinAFConfig(DRIVER_DEBUG_GPIO_TX_PORT, DRIVEr_DEBUG_AF_TX, DRIVER_DEBUG_AF); // 复用映射
    stGpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
    stGpio.GPIO_OType = GPIO_OType_PP; // 推挽
    stGpio.GPIO_Pin = DRIVER_DEBUG_GPIO_TX_PIN;
    GPIO_Init(DRIVER_DEBUG_GPIO_TX_PORT, &stGpio);

    // 初始化GPIO脚(RX)
    GPIO_PinAFConfig(DRIVER_DEBUG_GPIO_RX_PORT, DRIVEr_DEBUG_AF_RX, DRIVER_DEBUG_AF); // 复用映射
    stGpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
    stGpio.GPIO_Pin = DRIVER_DEBUG_GPIO_RX_PIN;
    GPIO_Init(DRIVER_DEBUG_GPIO_RX_PORT, &stGpio);

    // 初始化UART4
    RCC_APB1PeriphClockCmd(DRIVER_DEBUG_UART_CLK, ENABLE); // 使能串口时钟
    stUsart.USART_BaudRate = 115200;
    stUsart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    stUsart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 串口收发
    stUsart.USART_Parity = USART_Parity_No;
    stUsart.USART_StopBits = USART_StopBits_1;
    stUsart.USART_WordLength = USART_WordLength_8b;
    USART_Init(DRIVER_DEBUG_UART, &stUsart);

    // 开启串口接收中断
    USART_ITConfig(DRIVER_DEBUG_UART, USART_IT_RXNE, ENABLE);

    // 配置NVIC
    stNvic.NVIC_IRQChannel = DRIVER_DEBUG_NVIC_IRQ_CHANNEL;
    stNvic.NVIC_IRQChannelCmd = ENABLE;
    stNvic.NVIC_IRQChannelPreemptionPriority = 1;
    stNvic.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&stNvic);

    // 使能串口1
    USART_Cmd(DRIVER_DEBUG_UART, ENABLE);

    return;
}

// 初始化串口(对接本地网管)
void driver_uart_init_gui()
{
    GPIO_InitTypeDef stGpio = {0};
    USART_InitTypeDef stUsart = {0};
    NVIC_InitTypeDef stNvic = {0};

    RCC_AHB1PeriphClockCmd(DRIVER_GUI_GPIO_CLK, ENABLE); // 使能GPIO时钟
    stGpio.GPIO_Mode = GPIO_Mode_AF;
    stGpio.GPIO_Speed = GPIO_Fast_Speed;

    // 初始化GPIO脚(TX)
    GPIO_PinAFConfig(DRIVER_GUI_GPIO_TX_PORT, DRIVEr_GUI_AF_TX, DRIVER_GUI_AF); // 复用映射
    stGpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
    stGpio.GPIO_OType = GPIO_OType_PP; // 推挽
    stGpio.GPIO_Pin = DRIVER_GUI_GPIO_TX_PIN;
    GPIO_Init(DRIVER_GUI_GPIO_TX_PORT, &stGpio);

    // 初始化GPIO脚(RX)
    GPIO_PinAFConfig(DRIVER_GUI_GPIO_RX_PORT, DRIVEr_GUI_AF_RX, DRIVER_GUI_AF); // 复用映射
    stGpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
    stGpio.GPIO_Pin = DRIVER_GUI_GPIO_RX_PIN;
    GPIO_Init(DRIVER_GUI_GPIO_RX_PORT, &stGpio);

    // 初始化USART1
    RCC_APB2PeriphClockCmd(DRIVER_GUI_UART_CLK, ENABLE); // 使能串口时钟
    stUsart.USART_BaudRate = 115200;
    stUsart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    stUsart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 串口收发
    stUsart.USART_Parity = USART_Parity_No;
    stUsart.USART_StopBits = USART_StopBits_1;
    stUsart.USART_WordLength = USART_WordLength_8b;
    USART_Init(DRIVER_GUI_UART, &stUsart);

    // 开启串口接收中断
    USART_ITConfig(DRIVER_GUI_UART, USART_IT_RXNE, ENABLE);

    // 配置NVIC
    stNvic.NVIC_IRQChannel = DRIVER_GUI_NVIC_IRQ_CHANNEL;
    stNvic.NVIC_IRQChannelCmd = ENABLE;
    stNvic.NVIC_IRQChannelPreemptionPriority = 1;
    stNvic.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&stNvic);

    // 使能串口1
    USART_Cmd(DRIVER_GUI_UART, ENABLE);

    return;
}

// 初始化串口(对接wifi模块)
void driver_uart_init_wifi()
{
    GPIO_InitTypeDef stGpio = {0};
    USART_InitTypeDef stUsart = {0};
    NVIC_InitTypeDef stNvic = {0};

    RCC_AHB1PeriphClockCmd(DRIVER_WIFI_GPIO_CLK, ENABLE); // 使能GPIO时钟
    stGpio.GPIO_Mode = GPIO_Mode_AF;
    stGpio.GPIO_Speed = GPIO_Fast_Speed;

    // 初始化GPIO(TX)
    GPIO_PinAFConfig(DRIVER_WIFI_GPIO_TX_PORT, DRIVEr_WIFI_AF_TX, DRIVER_WIFI_AF); // 复用映射
    stGpio.GPIO_OType = GPIO_OType_PP;                                             // 推挽
    stGpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
    stGpio.GPIO_Pin = DRIVER_WIFI_GPIO_TX_PIN;
    GPIO_Init(DRIVER_WIFI_GPIO_TX_PORT, &stGpio);

    // 初始化GPIO(RX)
    GPIO_PinAFConfig(DRIVER_WIFI_GPIO_RX_PORT, DRIVEr_WIFI_AF_RX, DRIVER_WIFI_AF); // 复用映射                                         // 开路
    stGpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
    stGpio.GPIO_Pin = DRIVER_WIFI_GPIO_RX_PIN;
    GPIO_Init(DRIVER_WIFI_GPIO_RX_PORT, &stGpio);

    // 初始化USART2
    RCC_APB1PeriphClockCmd(DRIVER_WIFI_UART_CLK, ENABLE); // 使能串口2时钟
    stUsart.USART_BaudRate = 115200;
    stUsart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    stUsart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 串口收发
    stUsart.USART_Parity = USART_Parity_No;
    stUsart.USART_StopBits = USART_StopBits_1;
    stUsart.USART_WordLength = USART_WordLength_8b;
    USART_Init(DRIVER_WIFI_UART, &stUsart);

    // 开启接收中断
    USART_ITConfig(DRIVER_WIFI_UART, USART_IT_RXNE, ENABLE);

    // 配置NVIC
    stNvic.NVIC_IRQChannel = DRIVER_WIFI_NVIC_IRQ_CHANNEL;
    stNvic.NVIC_IRQChannelCmd = ENABLE;
    stNvic.NVIC_IRQChannelPreemptionPriority = 1;
    stNvic.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&stNvic);

    // 使能串口2
    USART_Cmd(DRIVER_WIFI_UART, ENABLE);

    return;
}

// 将串口编号，转换成串口地址
// byComNum:串口编号，从1到8
USART_TypeDef *driver_uart_change_com_num(uint8 byComNum)
{
    USART_TypeDef *pstUsart = NULL;
    if (byComNum == UART_DEBUG)
    { // 本地网管
        pstUsart = DRIVER_DEBUG_UART;
    }
    else if (byComNum == UART_GUI)
    { // 本地网管
        pstUsart = DRIVER_GUI_UART;
    }
    else if (byComNum == UART_WIFI)
    { // wifi模块
        pstUsart = DRIVER_WIFI_UART;
    }

    return pstUsart;
}

// 发送一个字节到串口
// pstUART：串口地址
// byData:数据
void driver_uart_send_byte(USART_TypeDef *pstUART, uint8 byData)
{
    // 发送数据
    USART_SendData(pstUART, (uint16)byData);

    // 等待数据全部转移至移位寄存器
    while (USART_GetFlagStatus(pstUART, USART_FLAG_TXE) == RESET)
    {
        ;
    }

    return;
}

// 发送数据
// byComNum:串口编号（1-8号）
// pbyData：待发送数据
// wLen：待发送数据长度
uint8 driver_uart_send_data(uint8 byComNum, uint8 *pbyData, uint16 wLen)
{
    uint8 *pbyTmp = pbyData;
    USART_TypeDef *pstUART = NULL;

    // 数据容错处理
    if (byComNum <= 0 || byComNum > 8 || pbyData == NULL || wLen <= 0)
    {
        return 0;
    }

    // 转换串口编号为串口地址
    pstUART = driver_uart_change_com_num(byComNum);
    if (pstUART == NULL)
    {
        return 0;
    }

    // 发送数据
    for (uint16 i = 0; i < wLen; i++)
    {
        driver_uart_send_byte(pstUART, *pbyTmp);
        pbyTmp++;
    }

    return 1;
}

// 接收数据（消费数据）
// byComNum:串口编号（1-8号）
// pbyData：上层数据缓存(返回参数)
// dwLen：本次要接收数据长度
// 返回值：读取了多个字节
uint32 driver_uart_receive_data(uint8 byComNum, uint8 *pbyData, uint32 dwLen)
{
    uint8 *pbyTmp = pbyData;
    uint32 dwCounter = 0;
    uint32 dwGenerateIndex = 0;

    // 数据容错处理
    if (pbyData == NULL || dwLen <= 0)
    {
        return 0;
    }

    // 本地网管
    if (byComNum == UART_GUI)
    {
        dwGenerateIndex = gUart_stGuiReceive.dwGenerateIndex; // 生产指针
        while (gUart_stGuiReceive.dwConsumeIndex != dwGenerateIndex)
        {
            *pbyTmp = gUart_stGuiReceive.abyData[gUart_stGuiReceive.dwConsumeIndex];
            pbyTmp++;

            gUart_stGuiReceive.dwConsumeIndex++; // 消费索引加1
            if (gUart_stGuiReceive.dwConsumeIndex >= DRIVER_UART_RXBUF_SIZE)
            {
                gUart_stGuiReceive.dwConsumeIndex = 0;
            }

            dwCounter++;
            if (dwCounter >= dwLen)
            {
                break;
            }
        }
    }
    // 网管中心
    else if (byComNum == UART_WIFI)
    {
        dwGenerateIndex = gUart_stWifiReceive.dwGenerateIndex; // 生产指针
        while (gUart_stWifiReceive.dwConsumeIndex != dwGenerateIndex)
        {
            *pbyTmp = gUart_stWifiReceive.abyData[gUart_stWifiReceive.dwConsumeIndex];
            pbyTmp++;

            gUart_stWifiReceive.dwConsumeIndex++; // 消费索引加1
            if (gUart_stWifiReceive.dwConsumeIndex >= DRIVER_UART_RXBUF_SIZE)
            {
                gUart_stWifiReceive.dwConsumeIndex = 0;
            }

            dwCounter++;
            if (dwCounter >= dwLen)
            {
                break;
            }
        }
    }
    else
    {
        return 0;
    }

    return dwCounter;
}

// 串口1（GUI）中断服务函数(生产数据)
void USART1_IRQHandler(void)
{
    uint8 byData = 0;

    // 收到数据
    if (USART_GetITStatus(DRIVER_GUI_UART, USART_IT_RXNE) == SET)
    {
        // 从串口接收数据
        byData = (uint8)USART_ReceiveData(DRIVER_GUI_UART);

        // 保存数据
        gUart_stGuiReceive.abyData[gUart_stGuiReceive.dwGenerateIndex] = byData;
        gUart_stGuiReceive.dwGenerateIndex++; // 生产索引加1

        // 队列掉头
        if (gUart_stGuiReceive.dwGenerateIndex >= DRIVER_UART_RXBUF_SIZE)
        {
            gUart_stGuiReceive.dwGenerateIndex = 0;
        }

        USART_ClearITPendingBit(DRIVER_GUI_UART, USART_IT_RXNE); // 清除中断标识符
    }

    return;
}

// 串口2（WIFI）中断服务函数(生产数据)
void USART2_IRQHandler(void)
{
    uint8 byData = 0;

    // 收到数据
    if (USART_GetITStatus(DRIVER_WIFI_UART, USART_IT_RXNE) == SET)
    {
        // 从串口接收数据
        byData = (uint8)USART_ReceiveData(DRIVER_WIFI_UART);

        // 保存数据
        gUart_stWifiReceive.abyData[gUart_stWifiReceive.dwGenerateIndex] = byData;
        gUart_stWifiReceive.dwGenerateIndex++; // 生产索引加1

        // 队列掉头
        if (gUart_stWifiReceive.dwGenerateIndex >= DRIVER_UART_RXBUF_SIZE)
        {
            gUart_stWifiReceive.dwGenerateIndex = 0;
        }

        USART_ClearITPendingBit(DRIVER_WIFI_UART, USART_IT_RXNE); // 清除中断标识符
    }

    return;
}