#include "ltc2508_driver.h"
#include <string.h> // For memset

// 全局变量定义
volatile uint16_t g_adc_data[NUM_LTC2508][LTC2508_DATA_LEN] = {0};
volatile uint8_t g_adc_data_ready_flag = 0;
volatile uint8_t g_dma_complete_count = 0;

// 错误统计信息
LTC2508_StatsTypeDef g_ltc2508_stats = {0};

// SPI 句柄指针
static SPI_HandleTypeDef *g_hspi1 = NULL;
static SPI_HandleTypeDef *g_hspi2 = NULL;
static SPI_HandleTypeDef *g_hspi3 = NULL;

/**
  * @brief 初始化 LTC2508 驱动
  * @param hspi1: SPI1 句柄指针
  * @param hspi2: SPI2 句柄指针
  * @param hspi3: SPI3 句柄指针
  * @retval LTC2508_StatusTypeDef
  */
LTC2508_StatusTypeDef LTC2508_Init(SPI_HandleTypeDef *hspi1, SPI_HandleTypeDef *hspi2, SPI_HandleTypeDef *hspi3)
{
    // 参数检查
    if (hspi1 == NULL || hspi2 == NULL || hspi3 == NULL) {
        g_ltc2508_stats.error_count++;
        g_ltc2508_stats.last_error = LTC2508_ERROR_INIT;
        return LTC2508_ERROR_INIT;
    }
    
    g_hspi1 = hspi1;
    g_hspi2 = hspi2;
    g_hspi3 = hspi3;
    g_adc_data_ready_flag = 0;
    g_dma_complete_count = 0;
    memset((void*)g_adc_data, 0, sizeof(g_adc_data));
    
    // 重置统计信息
    memset(&g_ltc2508_stats, 0, sizeof(g_ltc2508_stats));

    // 可以在这里添加对 LTC2508 的配置，如果需要通过 SPI 发送配置字
    // 例如：HAL_SPI_Transmit(g_hspi1, &config_word, 1, 100);
    
    return LTC2508_OK;
}

/**
  * @brief 触发三路 SPI 通过 DMA 读取数据
  * @param None
  * @retval LTC2508_StatusTypeDef
  */
LTC2508_StatusTypeDef LTC2508_TriggerDmaRead(void)
{
    // 检查SPI句柄是否有效
    if (g_hspi1 == NULL || g_hspi2 == NULL || g_hspi3 == NULL) {
        g_ltc2508_stats.error_count++;
        g_ltc2508_stats.last_error = LTC2508_ERROR_INIT;
        return LTC2508_ERROR_INIT;
    }
    
    if (g_adc_data_ready_flag == 0 && g_dma_complete_count == 0) // 确保上次数据已处理且 DMA 未在进行
    {
        g_dma_complete_count = 0; // 重置计数

        // SPI2 和 SPI3 作为从机只接收
        if (HAL_SPI_Receive_DMA(g_hspi2, (uint8_t*)g_adc_data[1], LTC2508_DATA_LEN * 2) != HAL_OK)
        {
            g_ltc2508_stats.dma_error_count++;
            g_ltc2508_stats.error_count++;
            g_ltc2508_stats.last_error = LTC2508_ERROR_DMA;
            return LTC2508_ERROR_DMA;
        }

        if (HAL_SPI_Receive_DMA(g_hspi3, (uint8_t*)g_adc_data[2], LTC2508_DATA_LEN * 2) != HAL_OK)
        {
            g_ltc2508_stats.dma_error_count++;
            g_ltc2508_stats.error_count++;
            g_ltc2508_stats.last_error = LTC2508_ERROR_DMA;
            return LTC2508_ERROR_DMA;
        }

        // SPI1 作为主机收发，先发一个 dummy 数据触发时钟
        uint16_t dummy_tx[LTC2508_DATA_LEN] = {0}; // 可以是任意值
        if (HAL_SPI_TransmitReceive_DMA(g_hspi1, (uint8_t*)dummy_tx, (uint8_t*)g_adc_data[0], LTC2508_DATA_LEN * 2) != HAL_OK)
        {
            g_ltc2508_stats.dma_error_count++;
            g_ltc2508_stats.error_count++;
            g_ltc2508_stats.last_error = LTC2508_ERROR_DMA;
            return LTC2508_ERROR_DMA;
        }
        
        return LTC2508_OK;
    }
    
    return LTC2508_ERROR_TIMEOUT; // 上次数据未处理完成
}

/**
  * @brief SPI DMA 传输完成回调函数
  * @param hspi: SPI 句柄指针
  * @retval None
  */
void LTC2508_DmaComplete_Callback(SPI_HandleTypeDef *hspi)
{
    if (hspi == g_hspi1 || hspi == g_hspi2 || hspi == g_hspi3)
    {
        g_dma_complete_count++;
        if (g_dma_complete_count >= NUM_LTC2508)
        {
            g_adc_data_ready_flag = 1;
            g_dma_complete_count = 0; // 为下一次读取做准备
            g_ltc2508_stats.total_samples++;
        }
    }
}

/**
  * @brief SPI DMA 传输错误回调函数
  * @param hspi: SPI 句柄指针
  * @retval None
  */
void LTC2508_ErrorCallback(SPI_HandleTypeDef *hspi)
{
    if (hspi == g_hspi1 || hspi == g_hspi2 || hspi == g_hspi3)
    {
        g_ltc2508_stats.dma_error_count++;
        g_ltc2508_stats.error_count++;
        g_ltc2508_stats.last_error = LTC2508_ERROR_DMA;
        
        // 重置DMA状态
        g_dma_complete_count = 0;
        g_adc_data_ready_flag = 0;
    }
}

/**
  * @brief 验证ADC数据有效性
  * @param channel: ADC通道 (0-2)
  * @retval LTC2508_StatusTypeDef
  */
LTC2508_StatusTypeDef LTC2508_ValidateData(uint8_t channel)
{
    if (channel >= NUM_LTC2508) {
        return LTC2508_ERROR_DATA_INVALID;
    }
    
    // 检查数据是否为全0或全1 (可能的错误状态)
    uint32_t combined_data = ((uint32_t)g_adc_data[channel][0] << 16) | g_adc_data[channel][1];
    
    if (combined_data == 0x00000000 || combined_data == 0xFFFFFFFF) {
        g_ltc2508_stats.error_count++;
        g_ltc2508_stats.last_error = LTC2508_ERROR_DATA_INVALID;
        return LTC2508_ERROR_DATA_INVALID;
    }
    
    return LTC2508_OK;
}

/**
  * @brief 获取统计信息
  * @param stats: 统计信息结构体指针
  * @retval None
  */
void LTC2508_GetStats(LTC2508_StatsTypeDef *stats)
{
    if (stats != NULL) {
        memcpy(stats, &g_ltc2508_stats, sizeof(LTC2508_StatsTypeDef));
    }
}

/**
  * @brief 重置统计信息
  * @param None
  * @retval None
  */
void LTC2508_ResetStats(void)
{
    memset(&g_ltc2508_stats, 0, sizeof(LTC2508_StatsTypeDef));
}
