/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : stm32f407vet6_board.c
  * @brief          : STM32F407VET6 board configuration implementation
  ******************************************************************************
  */
/* USER CODE END Header */

#include "bsp_board.h"
#include "bsp_config.h"
#include "hal_gpio.h"
#include "hal_uart.h"
#include "hal_spi.h"

/**
 * @brief Default LED initialization function
 * @param config: LED configuration structure
 */
static void default_led_init(const void* config) {
    const bsp_led_config_t* led_config = (const bsp_led_config_t*)config;
    hal_gpio_config_t gpio_config = {
        .port = led_config->port,
        .pin = led_config->pin,
        .mode = led_config->mode,
        .speed = led_config->speed,
        .pull = led_config->pull
    };
    hal_gpio_configure_pin(&gpio_config);
}

/**
 * @brief STM32F407VET6 board button configurations
 */
static const bsp_button_config_t stm32f407vet6_buttons[] = {
    /* KEY0 - PE4, active low */
    {
        .port = BSP_KEY0_PORT,
        .pin = BSP_KEY0_PIN,
        .mode = HAL_GPIO_MODE_INPUT,
        .speed = HAL_GPIO_SPEED_LOW,
        .pull = HAL_GPIO_PULL_UP,
        .active_high = 0
    },
    /* KEY1 - PE3, active low */
    {
        .port = BSP_KEY1_PORT,
        .pin = BSP_KEY1_PIN,
        .mode = HAL_GPIO_MODE_INPUT,
        .speed = HAL_GPIO_SPEED_LOW,
        .pull = HAL_GPIO_PULL_UP,
        .active_high = 0
    },
    /* WKUP - PA0, active high */
    {
        .port = BSP_WKUP_PORT,
        .pin = BSP_WKUP_PIN,
        .mode = HAL_GPIO_MODE_INPUT,
        .speed = HAL_GPIO_SPEED_LOW,
        .pull = HAL_GPIO_PULL_DOWN,
        .active_high = 1
    }
};

/**
 * @brief STM32F407VET6 buttons configuration
 */
static const bsp_buttons_config_t stm32f407vet6_buttons_config = {
    .count = sizeof(stm32f407vet6_buttons) / sizeof(bsp_button_config_t),
    .buttons = stm32f407vet6_buttons
};

/**
 * @brief Default button initialization function
 * @param config: Button configuration structure
 */
static void default_button_init(const void* config) {
    const bsp_buttons_config_t* buttons_config = (const bsp_buttons_config_t*)config;
    uint8_t i;
    
    for (i = 0; i < buttons_config->count; i++) {
        const bsp_button_config_t* button_config = &buttons_config->buttons[i];
        hal_gpio_config_t gpio_config = {
            .port = button_config->port,
            .pin = button_config->pin,
            .mode = button_config->mode,
            .speed = button_config->speed,
            .pull = button_config->pull
        };
        hal_gpio_configure_pin(&gpio_config);
    }
}

/**
 * @brief Default UART initialization function
 * @param config: UART configuration structure
 */
static void default_uart_init(const void* config) {
    const bsp_uart_config_t* uart_config = (const bsp_uart_config_t*)config;
    hal_uart_config_t uart_cfg = {
        .instance = (hal_uart_instance_t)uart_config->instance,
        .baudrate = uart_config->baudrate,
        .parity = uart_config->parity,
        .stopbits = uart_config->stopbits,
        .databits = uart_config->databits
    };
    hal_uart_config(&uart_cfg);
}

/**
 * @brief Default W25QXX initialization function
 * @param config: W25QXX configuration structure
 */
static void default_w25qxx_init(const void* config) {
    const bsp_w25qxx_config_t* w25qxx_config = (const bsp_w25qxx_config_t*)config;
    
    /* Initialize CS pin */
    hal_gpio_config_t gpio_config = {
        .port = w25qxx_config->cs_port,
        .pin = w25qxx_config->cs_pin,
        .mode = HAL_GPIO_MODE_OUTPUT_PP,
        .speed = HAL_GPIO_SPEED_HIGH,
        .pull = HAL_GPIO_PULL_NO
    };
    hal_gpio_configure_pin(&gpio_config);
    
    /* Deselect chip initially */
    hal_gpio_write_pin(w25qxx_config->cs_port, w25qxx_config->cs_pin, HAL_GPIO_PIN_SET);
    
    /* Initialize SPI */
    hal_spi_config_t spi_config = {
        .instance = w25qxx_config->spi_config.instance,
        .mode = w25qxx_config->spi_config.mode,
        .baudrate = w25qxx_config->spi_config.baudrate,
        .polarity = w25qxx_config->spi_config.polarity,
        .phase = w25qxx_config->spi_config.phase,
        .databits = w25qxx_config->spi_config.databits
    };
    hal_spi_init(w25qxx_config->spi_config.instance, &spi_config);
}

/**
 * @brief STM32F407VET6 board configuration
 */
const bsp_board_config_t stm32f407vet6_board_config = {
    .name = BOARD_NAME,
    .led = {
        .port = BSP_LED_PORT,
        .pin = BSP_LED_PIN,
        .mode = HAL_GPIO_MODE_OUTPUT_PP,
        .speed = HAL_GPIO_SPEED_MEDIUM,
        .pull = HAL_GPIO_PULL_NO
    },
    .buttons = stm32f407vet6_buttons_config,
    .uart = {
        .instance = BSP_UART_INSTANCE,
        .baudrate = BSP_UART_BAUDRATE,
        .parity = BSP_UART_PARITY,
        .stopbits = BSP_UART_STOPBITS,
        .databits = BSP_UART_DATABITS,
        .tx_port = HAL_GPIO_PORT_A,  /* USART1_TX - PA9 */
        .tx_pin = HAL_GPIO_PIN_9,
        .rx_port = HAL_GPIO_PORT_A,  /* USART1_RX - PA10 */
        .rx_pin = HAL_GPIO_PIN_10
    },
    .w25qxx = {
        .cs_port = HAL_GPIO_PORT_B,
        .cs_pin = HAL_GPIO_PIN_0,
        .spi_config = {
            .instance = HAL_SPI_INSTANCE_1,
            .mode = HAL_SPI_MODE_MASTER,
            .baudrate = 1000000, /* 1 MHz */
            .polarity = HAL_SPI_POLARITY_LOW,
            .phase = HAL_SPI_PHASE_1EDGE,
            .databits = HAL_SPI_DATABITS_8
        }
    },
    .led_init = default_led_init,
    .button_init = default_button_init,
    .uart_init = default_uart_init,
    .w25qxx_init = default_w25qxx_init,
    .clock_speed = 168000000,  /* 168 MHz */
    .uart_count = 6
};

/**
 * @brief Get board name
 * @retval Board name string
 */
const char* bsp_board_get_name(void) {
    return stm32f407vet6_board_config.name;
}
