/**
 ******************************************************************************
 * @文件     led.c
 * @作者     阜阳师范大学物电学院
 * @版本     V0.3
 * @日期     2026-01-15
 * @简介     LED 驱动 - 基于结构体的高可移植性实现
 * @说明     通过修改LED配置数组即可适配不同的硬件连接，无需修改其他代码
 *           所有硬件相关参数（端口、引脚、极性、速度、上拉下拉）都集中在配置数组中
 ****
 */

#include "led.h"

/* ============================================================================
 * LED配置数组 - 在此处修改硬件连接配置
 * 格式说明：
 *   {端口, 引脚, 极性, 默认状态, 速度, 上拉下拉}
 * 
 * 示例：
 *   {GPIOA, GPIO_PIN_0, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}
 *   {GPIOB, GPIO_PIN_5, LED_POLARITY_HIGH_ACTIVE, GPIO_PIN_RESET, GPIO_SPEED_FREQ_MEDIUM, GPIO_NOPULL}
 * ============================================================================ */
static const LED_Config_t led_config[LED_COUNT] = {
    /* LED1 低电平有效 */
    {GPIOC, GPIO_PIN_8, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED2 低电平有效 */
    {GPIOC, GPIO_PIN_9, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED3 低电平有效 */
    {GPIOA, GPIO_PIN_9, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED4 低电平有效 */
    {GPIOA, GPIO_PIN_11, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED5 低电平有效 */
    {GPIOA, GPIO_PIN_15, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED6 低电平有效 */
    {GPIOC, GPIO_PIN_11, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED7 低电平有效 */
    {GPIOD, GPIO_PIN_0, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED8 低电平有效 */
    {GPIOD, GPIO_PIN_2, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED9 低电平有效 */
    {GPIOD, GPIO_PIN_4, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED10 低电平有效 */
    {GPIOD, GPIO_PIN_6, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED11 低电平有效 */
    {GPIOC, GPIO_PIN_7, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED12 低电平有效 */
    {GPIOA, GPIO_PIN_8, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED13 低电平有效 */
    {GPIOA, GPIO_PIN_10, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED14 低电平有效 */
    {GPIOA, GPIO_PIN_12, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED15 低电平有效 */
    {GPIOC, GPIO_PIN_10, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED16 低电平有效 */
    {GPIOC, GPIO_PIN_12, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED17 低电平有效 */
    {GPIOD, GPIO_PIN_1, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED18 低电平有效 */
    {GPIOD, GPIO_PIN_3, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED19 低电平有效 */
    {GPIOD, GPIO_PIN_5, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
    
    /* LED20 低电平有效 */
    {GPIOD, GPIO_PIN_7, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
};

/* LED状态数组 - 使用枚举类型提高类型安全性 */
static LED_State_t led_state[LED_COUNT];

/**
 * @brief  使能GPIO时钟
 * @param  port: GPIO端口
 * @retval 无
 * @note   使用switch-case结构，代码更简洁清晰，支持所有GPIO端口（A-G）
 */
static void LED_GPIO_ClockEnable(GPIO_TypeDef *port)
{
    switch ((uint32_t)port) {
        case (uint32_t)GPIOA: __HAL_RCC_GPIOA_CLK_ENABLE(); break;
        case (uint32_t)GPIOB: __HAL_RCC_GPIOB_CLK_ENABLE(); break;
        case (uint32_t)GPIOC: __HAL_RCC_GPIOC_CLK_ENABLE(); break;
        case (uint32_t)GPIOD: __HAL_RCC_GPIOD_CLK_ENABLE(); break;
        case (uint32_t)GPIOE: __HAL_RCC_GPIOE_CLK_ENABLE(); break;
        case (uint32_t)GPIOF: __HAL_RCC_GPIOF_CLK_ENABLE(); break;
        case (uint32_t)GPIOG: __HAL_RCC_GPIOG_CLK_ENABLE(); break;
        default: break;
    }
}

/**
 * @brief  LED初始化
 * @param  无
 * @retval 无
 * @note   自动初始化所有配置的LED，所有硬件参数从配置数组中读取
 *         无需手动逐个配置，修改硬件连接只需修改配置数组
 */
void LED_Init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    uint8_t i;
    
    /* 遍历配置数组，初始化所有LED */
    for (i = 0; i < LED_COUNT; i++) {
        /* 使能对应GPIO时钟 */
        LED_GPIO_ClockEnable(led_config[i].port);
        
        /* 从配置数组中读取GPIO参数 */
        gpio_init_struct.Pin = led_config[i].pin;
        gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;        /* 推挽输出模式 */
        gpio_init_struct.Speed = led_config[i].speed;       /* 速度配置 */
        gpio_init_struct.Pull = led_config[i].pull;         /* 上拉下拉配置 */
        
        /* 初始化GPIO引脚 */
        HAL_GPIO_Init(led_config[i].port, &gpio_init_struct);
        
        /* 设置默认状态 */
        HAL_GPIO_WritePin(led_config[i].port, led_config[i].pin, led_config[i].default_state);
        
        /* 初始化状态数组（根据默认状态和极性计算逻辑状态） */
        if (led_config[i].polarity == LED_POLARITY_LOW_ACTIVE) {
            led_state[i] = (led_config[i].default_state == GPIO_PIN_RESET) ? LED_ON : LED_OFF;
        } else {
            led_state[i] = (led_config[i].default_state == GPIO_PIN_SET) ? LED_ON : LED_OFF;
        }
    }
    LED_POW(LED_ON);                                        /*上电指示灯亮*/
}

/**
 * @brief  点亮LED
 * @param  led_id: LED ID (0 ~ LED_COUNT-1)
 * @retval 无
 */
void LED_On(uint8_t led_id)
{
    GPIO_PinState pin_state;
    
    if (led_id >= LED_COUNT) {
        return;
    }
    
    /* 根据极性设置引脚状态 */
    if (led_config[led_id].polarity == LED_POLARITY_LOW_ACTIVE) {
        pin_state = GPIO_PIN_RESET;  /* 低电平有效，输出低电平点亮 */
    } else {
        pin_state = GPIO_PIN_SET;    /* 高电平有效，输出高电平点亮 */
    }
    
    HAL_GPIO_WritePin(led_config[led_id].port, led_config[led_id].pin, pin_state);
    led_state[led_id] = LED_ON;
}

/**
 * @brief  熄灭LED
 * @param  led_id: LED ID (0 ~ LED_COUNT-1)
 * @retval 无
 */
void LED_Off(uint8_t led_id)
{
    GPIO_PinState pin_state;
    
    if (led_id >= LED_COUNT) {
        return;
    }
    
    /* 根据极性设置引脚状态 */
    if (led_config[led_id].polarity == LED_POLARITY_LOW_ACTIVE) {
        pin_state = GPIO_PIN_SET;    /* 低电平有效，输出高电平熄灭 */
    } else {
        pin_state = GPIO_PIN_RESET;  /* 高电平有效，输出低电平熄灭 */
    }
    
    HAL_GPIO_WritePin(led_config[led_id].port, led_config[led_id].pin, pin_state);
    led_state[led_id] = LED_OFF;
}

/**
 * @brief  翻转LED状态
 * @param  led_id: LED ID (0 ~ LED_COUNT-1)
 * @retval 无
 */
void LED_Toggle(uint8_t led_id)
{
    if (led_id >= LED_COUNT) {
        return;
    }
    
    HAL_GPIO_TogglePin(led_config[led_id].port, led_config[led_id].pin);
    /* 翻转LED状态 - 使用显式条件判断，提高类型安全性 */
    led_state[led_id] = (led_state[led_id] == LED_ON) ? LED_OFF : LED_ON;
}

/**
 * @brief  设置LED状态
 * @param  led_id: LED ID (0 ~ LED_COUNT-1)
 * @param  state: LED状态 (LED_ON 或 LED_OFF)
 * @retval 无
 */
void LED_Set(uint8_t led_id, LED_State_t state)
{
    if (state == LED_ON) {
        LED_On(led_id);
    } else {
        LED_Off(led_id);
    }
}

/**
 * @brief  获取LED状态
 * @param  led_id: LED ID (0 ~ LED_COUNT-1)
 * @retval LED状态 (LED_ON 或 LED_OFF)
 */
LED_State_t LED_GetState(uint8_t led_id)
{
    if (led_id >= LED_COUNT) {
        return LED_OFF;
    }
    return led_state[led_id];
}

/**
 * @brief  输出LED状态
 * @param  ledbuf 状态字节
 * @retval 无
 */
void LED_Printf(uint8_t* ledbuf)
{
    uint32_t leddata = (ledbuf[3]<<24) |(ledbuf[2]<<16) | (ledbuf[1]<<8) | ledbuf[0];
    uint32_t i = 0;
    LED_State_t state;           /* 使用枚举类型，提高类型安全性 */
    LED_POW(LED_ON);             /* 默认上电亮灯 */
  
    for(i=1; i<LED_COUNT; i++)
    {
        /* 将位掩码结果转换为枚举类型：非0 -> LED_ON, 0 -> LED_OFF */
         state = (leddata & (1UL << i)) ? LED_ON : LED_OFF;
         LED_Set((uint8_t)i, state);   
    }
}



