#include "boot_uart.h"

UART_HandleTypeDef huart_boot;

/**
  * @brief  Инициализация UART для бутлоадера
  * @note   Использует USART3, PB10 (TX), PB11 (RX)
  */
void MX_BOOT_UART_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* Включаем тактирование */
    __RCC_UART_BOOT_CLK_ENABLE();
    __RCC_UART_PORT_CLK_ENABLE();

    /* Настройка GPIO TX/RX */
    GPIO_InitStruct.Pin = UART_PIN_TX | UART_PIN_RX;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(UART_PORT, &GPIO_InitStruct);

    /* Настройка UART */
    huart_boot.Instance = UART_BOOT;
    huart_boot.Init.BaudRate = UART_SPEED;
    huart_boot.Init.WordLength = UART_WORDLENGTH_8B;
    huart_boot.Init.StopBits = UART_STOPBITS_1;
    huart_boot.Init.Parity = UART_PARITY_NONE;
    huart_boot.Init.Mode = UART_MODE_TX_RX;
    huart_boot.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart_boot.Init.OverSampling = UART_OVERSAMPLING_16;

    if (HAL_UART_Init(&huart_boot) != HAL_OK)
    {
        Error_Handler(); // твоя функция обработки ошибок
    }
}

// -----------------------------
// UART: приём страницы + CRC
// -----------------------------
void Bootloader_UART_Receive_Page(Bootloader_t *bl)
{
  uint16_t bytes_received = 0;
  uint8_t crc_buf[4];
  HAL_StatusTypeDef res;
  uint32_t start_tick = HAL_GetTick(); // старт таймера

  // Приём данных страницы
  while(bytes_received < PAGE_SIZE)
  {
    uint8_t byte = 0;
    res = HAL_UART_Receive(bl->huart, &byte, 1, 100); // блокирующий приём 100ms

    if(res == HAL_OK)
    {
      bl->fw_buffer[bytes_received++] = byte;
      start_tick = HAL_GetTick(); // сброс таймера при успешном приёме
    }
    else
    {
      // проверка таймаута
      if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS)
      {
        bl->error.bit.timeout_receive = 1;
        bl->state = BL_STATE_ERROR;  // превышен таймаут
        return;
      }
      // иначе просто ждем следующего байта
    }
  }

  // Приём CRC (4 байта)
  for(uint8_t i = 0; i < 4; i++)
  {
    res = HAL_UART_Receive(bl->huart, &crc_buf[i], 1, 100);
    if(res == HAL_OK)
    {
      start_tick = HAL_GetTick(); // сброс таймера
    }
    else
    {
      if(HAL_GetTick() - start_tick >= FW_RECEIVE_TIMEOUT_MS)
      {
        bl->error.bit.timeout_receive = 1;
        bl->state = BL_STATE_ERROR;
        return;
      }
    }
  }

  // Сохраняем CRC в структуру
  bl->fw_crc = (crc_buf[0] << 24) | (crc_buf[1] << 16) | (crc_buf[2] << 8) | crc_buf[3];
  bl->fw_len = bytes_received;
  bl->state = BL_STATE_IDLE;
}
