#include "usart.h" // 确保包含 huart2 定义所在的头文件
#include "pwm.h"
#include <string.h>

// 接收缓冲区
uint8_t RxBuffer[RX_BUF_SIZE]; 

/**
  * @brief  启动串口2接收（初始化调用）
  */
void USART2_Config_Init(void)
{
    /* 使用扩展接收函数：接收到 RX_BUF_SIZE 个字节，或者遇到空闲中断时停止并回调 */
    HAL_UARTEx_ReceiveToIdle_IT(&huart2, RxBuffer, RX_BUF_SIZE);
}

/**
  * @brief  符合协议的二进制发送函数
  * @param  mode: 模式 (0-10)
  * @param  value: 速度值 (0-100)
  */
void USART2_Send_Command(uint8_t mode, uint8_t value)
{
    uint8_t frame[8];
    frame[0] = 0x01;          // 帧头
    frame[1] = mode;          // 数据位1
    frame[2] = value;         // 数据位2
    frame[3] = 0x00;          // 预留
    frame[4] = 0x00;          // 预留
    frame[5] = 0x00;          // 预留
    
    // 生成和校验 (Sum Check)
    frame[6] = (uint8_t)((frame[1] + frame[2] + frame[3] + frame[4] + frame[5]) & 0xFF);
    
    frame[7] = 0xFF;          // 停止位
    
    // 阻塞式发送 8 字节二进制数据
    HAL_UART_Transmit(&huart2, frame, 8, 100);
}

/**
  * @brief  串口接收回调函数 (处理串口空闲中断)
  * @param  huart: 串口句柄
  * @param  Size: 实际接收到的字节数
  */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart->Instance == USART2)
    {
        // 1. 处理接收到的二进制数据包
        USART2_Process_Packet(RxBuffer, Size);

        // 2. 必须再次开启监听，以便下一次接收
        HAL_UARTEx_ReceiveToIdle_IT(&huart2, RxBuffer, RX_BUF_SIZE);
    }
}

/**
  * @brief  解析 8 字节协议帧
  * @param  pData: 指向接收缓冲区的指针
  * @param  Size: 接收到的有效数据长度
  */
void USART2_Process_Packet(uint8_t *pData, uint16_t Size)
{
    // 基础长度检查，如果一包数据连 8 字节都不到，直接丢弃
    if (Size < 8) return; 

    // 遍历缓冲区寻找合法帧（防止数据发生偏移）
    for (int i = 0; i <= Size - 8; i++) 
    {
        // 1. 匹配帧头 0x01 和 帧尾 0xFF
        if (pData[i] == 0x01 && pData[i+7] == 0xFF) 
        {
            uint8_t r_mode  = pData[i+1];
            uint8_t r_value = pData[i+2];
            uint8_t r_check = pData[i+6];
            
            // 2. 计算接收到的数据位和校验
            uint8_t cal_check = (uint8_t)((pData[i+1] + pData[i+2] + pData[i+3] + pData[i+4] + pData[i+5]) & 0xFF);
            
            // 3. 校验比对
            if (cal_check == r_check) 
            {
                // 校验通过，执行麦轮控制逻辑
                pwm_control_territory(r_mode, r_value);
                
                // 如果一包里只有一帧数据，处理完可以直接返回
                return; 
            }
        }
    }
}

/**
  * @brief  错误回调，防止串口因为溢出等错误停止接收
  */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART2)
    {
        HAL_UARTEx_ReceiveToIdle_IT(&huart2, RxBuffer, RX_BUF_SIZE);
    }
}