#include "usart1.h"
#include "buzz.h"
#include "pwm.h"

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

/**
  * @brief  启动串口接收
  */
void USART1_Config_Init(void)
{
    /* 使用扩展接收函数：接收到 RX_BUF_SIZE 个字节，或者遇到空闲中断时停止并回调 */
    HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxBuffer, RX_BUF_SIZE);
    printf("USART1 Multi-Byte Mode Ready.\r\n");
}

/**
  * @brief  printf 重定向 (保持不变)
  */
#ifdef __GNUC__
int __io_putchar(int ch) {
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}
#else
int fputc(int ch, FILE *f) {
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}
#endif

/**
  * @brief  这是处理变长数据的关键回调函数
  * @param  huart: 串口句柄
  * @param  Size: 实际接收到的字节数
  */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart->Instance == USART1)
    {
        // 1. 处理接收到的一包数据
        USART1_Process_Packet(RxBuffer, Size);

        // 2. 接收完成后，必须再次开启监听
        HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxBuffer, RX_BUF_SIZE);
    }
}

/**
  * @brief  业务逻辑：解析数据包
  * @param  pData: 指向接收缓冲区的指针
  * @param  Size: 接收到的有效数据长度
  */
void USART1_Process_Packet(uint8_t *pData, uint16_t Size)
{
    // 基础长度检查
    if (len < 8) return; 

    for (int i = 0; i <= len - 8; i++) {
        // 1. 检查帧头和帧尾
        if (buf[i] == 0x01 && buf[i+7] == 0xFF) {
            
            uint8_t r_mode  = buf[i+1];
            uint8_t r_value = buf[i+2];
            uint8_t r_check = buf[i+6];
            
            // 2. 计算校验和
            uint8_t cal_check = (buf[i+1] + buf[i+2] + buf[i+3] + buf[i+4] + buf[i+5]) & 0xFF;
            
            // 3. 校验比对
            if (cal_check == r_check) {
                // 校验通过，执行控制指令
                pwm_control_territory(r_mode, r_value);
                return; // 处理完一帧就退出
            } else {
                // 校验失败，可能是干扰
                printf("Check Error!\n");
            }
        }
    }
}

/**
  * @brief  如果发生错误（如溢出），在此重启接收
  */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1)
    {
        HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxBuffer, RX_BUF_SIZE);
    }
}
