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

// 全局变量定义 - 双缓冲区实现
volatile LTC2508_BufferTypeDef g_adc_buffers[LTC2508_BUFFER_COUNT] = {0};
volatile uint8_t g_adc_data_ready_flag = 0;
volatile uint8_t g_dma_complete_count = 0;
volatile uint8_t g_current_write_buffer = 0;
volatile uint8_t g_current_read_buffer = 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 是否初始化
  * @retval 0-未初始化 1-已初始化
  */
uint32_t LTC2508_IsInited()
{
	return (g_hspi1 != NULL && g_hspi2 != NULL && 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;
    g_current_write_buffer = 0;
    g_current_read_buffer = 0;
    
    // 初始化双缓冲区
    for (int i = 0; i < LTC2508_BUFFER_COUNT; i++) {
        memset((void*)&g_adc_buffers[i], 0, sizeof(LTC2508_BufferTypeDef));
        g_adc_buffers[i].state = LTC2508_BUFFER_EMPTY;
        g_adc_buffers[i].dma_complete_count = 0;
    }
    
    // 重置统计信息
    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;
    }
    
    // 检查当前写入缓冲区是否可用
    volatile LTC2508_BufferTypeDef *current_buffer = &g_adc_buffers[g_current_write_buffer];
    
    if (current_buffer->state == LTC2508_BUFFER_EMPTY)
    {
        // 设置缓冲区状态为填充中
        current_buffer->state = LTC2508_BUFFER_FILLING;
        current_buffer->dma_complete_count = 0;
        current_buffer->timestamp = HAL_GetTick();
        
        // SPI2 和 SPI3 作为从机只接收；必须在 SPI1（主机）启动时钟前挂好 DMA，否则从机会丢失前几个时钟
        if (HAL_SPI_Receive_DMA(g_hspi2, (uint8_t*)current_buffer->data[1], LTC2508_DATA_LEN) != HAL_OK)
        {
            current_buffer->state = LTC2508_BUFFER_EMPTY;
            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*)current_buffer->data[2], LTC2508_DATA_LEN) != HAL_OK)
        {
            current_buffer->state = LTC2508_BUFFER_EMPTY;
            HAL_SPI_DMAStop(g_hspi2);
            g_ltc2508_stats.dma_error_count++;
            g_ltc2508_stats.error_count++;
            g_ltc2508_stats.last_error = LTC2508_ERROR_DMA;
            return LTC2508_ERROR_DMA;
        }

        // static：DMA 传输异步完成，必须保证缓冲区生命周期覆盖整个传输过程
        static uint16_t s_dummy_tx[LTC2508_DATA_LEN] = {0};
        if (HAL_SPI_TransmitReceive_DMA(g_hspi1, (uint8_t*)s_dummy_tx, (uint8_t*)current_buffer->data[0], LTC2508_DATA_LEN) != HAL_OK)
        {
            current_buffer->state = LTC2508_BUFFER_EMPTY;
            HAL_SPI_DMAStop(g_hspi2);
            HAL_SPI_DMAStop(g_hspi3);
            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)
    {
        volatile LTC2508_BufferTypeDef *current_buffer = &g_adc_buffers[g_current_write_buffer];
        
        // 增加当前缓冲区的DMA完成计数
        current_buffer->dma_complete_count++;
        
        // 检查是否所有SPI的DMA传输都完成
        if (current_buffer->dma_complete_count >= NUM_LTC2508)
        {
            // 标记当前缓冲区为准备就绪
            current_buffer->state = LTC2508_BUFFER_READY;
            g_ltc2508_stats.total_samples++;
            
            // 自动切换到下一个缓冲区
            LTC2508_SwapBuffers();
        }
    }
}

/**
  * @brief SPI DMA 传输错误回调函数
  * @param hspi: SPI 句柄指针
  * @retval None
  */
void LTC2508_ErrorCallback(SPI_HandleTypeDef *hspi)
{
    if (hspi == g_hspi1 || hspi == g_hspi2 || hspi == g_hspi3)
    {
        volatile LTC2508_BufferTypeDef *current_buffer = &g_adc_buffers[g_current_write_buffer];
        
        g_ltc2508_stats.dma_error_count++;
        g_ltc2508_stats.error_count++;
        g_ltc2508_stats.last_error = LTC2508_ERROR_DMA;
        
        // 重置当前缓冲区状态
        current_buffer->state = LTC2508_BUFFER_EMPTY;
        current_buffer->dma_complete_count = 0;
    }
}

/**
  * @brief 验证ADC数据有效性
  * @param buffer: 缓冲区指针
  * @param channel: ADC通道 (0-2)
  * @retval LTC2508_StatusTypeDef
  */
LTC2508_StatusTypeDef LTC2508_ValidateData(LTC2508_BufferTypeDef *buffer, uint8_t channel)
{
    if (buffer == NULL || channel >= NUM_LTC2508) {
        return LTC2508_ERROR_DATA_INVALID;
    }
    
    // 检查数据是否为全0或全1 (可能的错误状态)
    uint32_t combined_data = ((uint32_t)buffer->data[channel][0] << 16) | buffer->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));
}

/**
  * @brief 缓冲区切换函数
  * @param None
  * @retval LTC2508_StatusTypeDef
  */
LTC2508_StatusTypeDef LTC2508_SwapBuffers(void)
{
    uint8_t next_write_buffer = (g_current_write_buffer + 1) % LTC2508_BUFFER_COUNT;
    
    // 检查下一个写入缓冲区是否可用
    if (g_adc_buffers[next_write_buffer].state == LTC2508_BUFFER_EMPTY) {
        g_current_write_buffer = next_write_buffer;
        return LTC2508_OK;
    }
    
    // 如果下一个缓冲区不可用，说明缓冲区溢出
    g_ltc2508_stats.buffer_overflow_count++;
    g_ltc2508_stats.error_count++;
    g_ltc2508_stats.last_error = LTC2508_ERROR_BUFFER_OVERFLOW;
    return LTC2508_ERROR_BUFFER_OVERFLOW;
}

/**
  * @brief 获取当前写入缓冲区索引
  * @param None
  * @retval uint8_t 当前写入缓冲区索引
  */
uint8_t LTC2508_GetCurrentWriteBuffer(void)
{
    return g_current_write_buffer;
}

/**
  * @brief 获取当前读取缓冲区索引
  * @param None
  * @retval uint8_t 当前读取缓冲区索引
  */
uint8_t LTC2508_GetCurrentReadBuffer(void)
{
    return g_current_read_buffer;
}

/**
  * @brief 检查指定缓冲区是否准备就绪
  * @param buffer_index: 缓冲区索引
  * @retval LTC2508_StatusTypeDef
  */
LTC2508_StatusTypeDef LTC2508_IsBufferReady(uint8_t buffer_index)
{
    if (buffer_index >= LTC2508_BUFFER_COUNT) {
        return LTC2508_ERROR_DATA_INVALID;
    }
    
    if (g_adc_buffers[buffer_index].state == LTC2508_BUFFER_READY) {
        return LTC2508_OK;
    }
    
    return LTC2508_ERROR_TIMEOUT;
}

/**
  * @brief 获取准备好的数据缓冲区
  * @param buffer: 返回缓冲区指针
  * @retval LTC2508_StatusTypeDef
  */
LTC2508_StatusTypeDef LTC2508_GetReadyBuffer(LTC2508_BufferTypeDef **buffer)
{
    if (buffer == NULL) {
        return LTC2508_ERROR_DATA_INVALID;
    }
    
    // 检查读取缓冲区是否有准备好的数据
    if (g_adc_buffers[g_current_read_buffer].state == LTC2508_BUFFER_READY) {
        g_adc_buffers[g_current_read_buffer].state = LTC2508_BUFFER_PROCESSING;
        *buffer = (LTC2508_BufferTypeDef*)&g_adc_buffers[g_current_read_buffer];
        return LTC2508_OK;
    }
    
    return LTC2508_ERROR_TIMEOUT; // 没有准备好的数据
}

/**
  * @brief 释放缓冲区
  * @param buffer_index: 缓冲区索引
  * @retval None
  */
void LTC2508_ReleaseBuffer(uint8_t buffer_index)
{
    if (buffer_index < LTC2508_BUFFER_COUNT) {
        g_adc_buffers[buffer_index].state = LTC2508_BUFFER_EMPTY;
        g_adc_buffers[buffer_index].dma_complete_count = 0;
        
        // 如果释放的是当前读取缓冲区，切换到下一个
        if (buffer_index == g_current_read_buffer) {
            g_current_read_buffer = (g_current_read_buffer + 1) % LTC2508_BUFFER_COUNT;
        }
    }
}
