/* 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
 * @retval HAL status code
 */
static hal_ret_t 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
    };
    return hal_gpio_configure_pin(&gpio_config);
}

/**
 * @brief Default button initialization function
 * @param config: Button configuration structure
 * @retval HAL status code
 */
static hal_ret_t default_button_init(const void* config) {
    const bsp_buttons_config_t* buttons_config = (const bsp_buttons_config_t*)config;
    uint8_t i;
    hal_ret_t status = HAL_RET_OK;
    
    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
        };
        status = hal_gpio_configure_pin(&gpio_config);
        if (status != HAL_RET_OK) {
            break;
        }
    }
    
    return status;
}

/**
 * @brief Default UART initialization function
 * @param config: UART configuration structure
 * @retval HAL status code
 */
static hal_ret_t 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
    };
    return hal_uart_config(&uart_cfg);
}

/**
 * @brief Default SPI initialization function
 * @param config: SPI configuration structure
 * @retval HAL status code
 */
static hal_ret_t default_spi_init(const void* config) {
    const bsp_spi_config_t* spi_config = (const bsp_spi_config_t*)config;
    hal_spi_config_t spi_cfg = {
        .instance = spi_config->instance,
        .mode = spi_config->mode,
        .baudrate = spi_config->baudrate,
        .polarity = spi_config->polarity,
        .phase = spi_config->phase,
        .databits = spi_config->databits
    };
    return hal_spi_init(spi_config->instance, &spi_cfg);
}

/**
 * @brief Default I2C initialization function
 * @param config: I2C configuration structure
 * @retval HAL status code
 */
static hal_ret_t default_i2c_init(const void* config) {
    /* TODO: Implement default I2C initialization */
    return HAL_RET_OK;
}

/**
 * @brief Default CAN initialization function
 * @param config: CAN configuration structure
 * @retval HAL status code
 */
static hal_ret_t default_can_init(const void* config) {
    /* TODO: Implement default CAN initialization */
    return HAL_RET_OK;
}

/**
 * @brief Default ADC initialization function
 * @param config: ADC configuration structure
 * @retval HAL status code
 */
static hal_ret_t default_adc_init(const void* config) {
    /* TODO: Implement default ADC initialization */
    return HAL_RET_OK;
}

/**
 * @brief Default W25QXX initialization function
 * @param config: W25QXX configuration structure
 * @retval HAL status code
 */
static hal_ret_t default_w25qxx_init(const void* config) {
    const bsp_w25qxx_config_t* w25qxx_config = (const bsp_w25qxx_config_t*)config;
    hal_ret_t status = HAL_RET_OK;
    
    /* 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
    };
    status = hal_gpio_configure_pin(&gpio_config);
    if (status != HAL_RET_OK) {
        return status;
    }
    
    /* Deselect chip initially */
    status = hal_gpio_write_pin(w25qxx_config->cs_port, w25qxx_config->cs_pin, HAL_GPIO_PIN_SET);
    if (status != HAL_RET_OK) {
        return status;
    }
    
    /* SPI instance is now just an index, actual SPI initialization is handled separately */
    return status;
}

/**
 * @brief STM32F407VET6 board button configurations
 */
static const bsp_button_config_t stm32f407vet6_buttons[] = {
    /* KEY0 - PE4, active low */
    {
        .port = HAL_GPIO_PORT_E,
        .pin = HAL_GPIO_PIN_4,
        .mode = HAL_GPIO_MODE_INPUT,
        .speed = HAL_GPIO_SPEED_LOW,
        .pull = HAL_GPIO_PULL_UP,
        .active_high = 0
    },
    /* KEY1 - PE3, active low */
    {
        .port = HAL_GPIO_PORT_E,
        .pin = HAL_GPIO_PIN_3,
        .mode = HAL_GPIO_MODE_INPUT,
        .speed = HAL_GPIO_SPEED_LOW,
        .pull = HAL_GPIO_PULL_UP,
        .active_high = 0
    },
    /* WKUP - PA0, active high */
    {
        .port = HAL_GPIO_PORT_A,
        .pin = HAL_GPIO_PIN_0,
        .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 = {
    .enable = 1,
    .count = sizeof(stm32f407vet6_buttons) / sizeof(bsp_button_config_t),
    .buttons = stm32f407vet6_buttons
};

/**
 * @brief STM32F407VET6 board UART configurations
 */
static const bsp_uart_config_t stm32f407vet6_uarts[] = {
    /* USART1 - PA9(TX), PA10(RX) */
    {
        .enable = 1,
        .instance = BSP_UART_INSTANCE_1,
        .baudrate = 115200,
        .parity = HAL_UART_PARITY_NONE,
        .stopbits = HAL_UART_STOPBITS_1,
        .databits = HAL_UART_DATABITS_8,
        .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
    }
};

/**
 * @brief STM32F407VET6 board SPI configurations
 */
static const bsp_spi_config_t stm32f407vet6_spis[] = {
    /* SPI1 - PA5(SCK), PA6(MISO), PA7(MOSI) */
    {
        .enable = 1,
        .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,
        .sck_port = HAL_GPIO_PORT_A,
        .sck_pin = HAL_GPIO_PIN_5,
        .miso_port = HAL_GPIO_PORT_A,
        .miso_pin = HAL_GPIO_PIN_6,
        .mosi_port = HAL_GPIO_PORT_A,
        .mosi_pin = HAL_GPIO_PIN_7
    }
};

/**
 * @brief STM32F407VET6 board I2C configurations
 */
static const bsp_i2c_config_t stm32f407vet6_i2cs[] = {
    /* I2C1 - PB6(SCL), PB7(SDA) */
    {
        .enable = 0, /* Disabled by default */
        .instance = HAL_I2C_INSTANCE_1,
        .speed = HAL_I2C_SPEED_STANDARD,
        .address_mode = HAL_I2C_ADDRESS_7BIT,
        .dutycycle = HAL_I2C_DUTYCYCLE_2,
        .own_address1 = 0x00,
        .scl_port = HAL_GPIO_PORT_B,
        .scl_pin = HAL_GPIO_PIN_6,
        .sda_port = HAL_GPIO_PORT_B,
        .sda_pin = HAL_GPIO_PIN_7
    }
};

/**
 * @brief STM32F407VET6 board CAN configurations
 */
static const bsp_can_config_t stm32f407vet6_cans[] = {
    /* CAN1 - PA11(RX), PA12(TX) */
    {
        .enable = 0, /* Disabled by default */
        .instance = HAL_CAN_INSTANCE_1,
        .mode = HAL_CAN_MODE_NORMAL,
        .prescaler = 6, /* 168MHz / 6 = 28MHz */
        .sync_jump_width = 1,
        .time_segment1 = 13,
        .time_segment2 = 2,
        .rx_port = HAL_GPIO_PORT_A,
        .rx_pin = HAL_GPIO_PIN_11,
        .tx_port = HAL_GPIO_PORT_A,
        .tx_pin = HAL_GPIO_PIN_12
    }
};

/**
 * @brief STM32F407VET6 board ADC channel configurations
 */
static const bsp_adc_channel_config_t stm32f407vet6_adc_channels[] = {
    /* ADC1 Channel 0 - PA0 */
    {
        .enable = 0, /* Disabled by default */
        .channel = HAL_ADC_CHANNEL_0,
        .sampletime = HAL_ADC_SAMPLETIME_56CYCLES,
        .rank = 1
    }
};

/**
 * @brief STM32F407VET6 board ADC configurations
 */
static const bsp_adc_config_t stm32f407vet6_adcs[] = {
    /* ADC1 */
    {
        .enable = 0, /* Disabled by default */
        .instance = HAL_ADC_INSTANCE_1,
        .resolution = HAL_ADC_RESOLUTION_12B,
        .scan_conversion_mode = 0,
        .continuous_conversion_mode = 0,
        .channel_count = sizeof(stm32f407vet6_adc_channels) / sizeof(bsp_adc_channel_config_t),
        .channels = stm32f407vet6_adc_channels
    }
};

/**
 * @brief STM32F407VET6 board configuration
 */
const bsp_board_config_t stm32f407vet6_board_config = {
    .version = BSP_CONFIG_VERSION,
    .name = "STM32F407VET6",
    .description = "STM32F407VET6 Development Board",
    .id = {
        .vendor_id = 0x0483,      /* STMicroelectronics */
        .product_id = 0x374B,      /* STM32F4 Series */
        .serial_number = 0x00000001 /* Default serial number */
    },
    
    /* Board features */
    .features = (
        BSP_BOARD_FEATURE_LED | 
        BSP_BOARD_FEATURE_BUTTON | 
        BSP_BOARD_FEATURE_UART | 
        BSP_BOARD_FEATURE_SPI | 
        BSP_BOARD_FEATURE_I2C | 
        BSP_BOARD_FEATURE_CAN | 
        BSP_BOARD_FEATURE_ADC | 
        BSP_BOARD_FEATURE_W25QXX
    ),
    
    /* Hardware information */
    .hw_info = {
        .clock_speed = 168000000,  /* 168 MHz */
        .flash_size = 512 * 1024,  /* 512 KB */
        .ram_size = 192 * 1024,     /* 192 KB */
        .eeprom_size = 0,           /* No internal EEPROM */
        .sram_size = 64 * 1024,     /* 64 KB SRAM */
        .cpu_core = 0x0F,           /* Cortex-M4 */
        .cpu_bits = 32              /* 32-bit CPU */
    },
    
    /* Peripheral configurations */
    .led = {
        .enable = 1,
        .port = HAL_GPIO_PORT_E,
        .pin = HAL_GPIO_PIN_5,
        .mode = HAL_GPIO_MODE_OUTPUT_PP,
        .speed = HAL_GPIO_SPEED_MEDIUM,
        .pull = HAL_GPIO_PULL_NO
    },
    .buttons = stm32f407vet6_buttons_config,
    .w25qxx = {
        .enable = 1,
        .cs_port = HAL_GPIO_PORT_B,
        .cs_pin = HAL_GPIO_PIN_0,
        .spi_instance = 0  /* Use SPI instance 0 */
    },
    
    /* Peripheral arrays */
    .periphs = {
        /* UART configurations */
        .uart_count = 1,
        .uarts = stm32f407vet6_uarts,
        
        /* SPI configurations */
        .spi_count = 1,
        .spis = stm32f407vet6_spis,
        
        /* I2C configurations */
        .i2c_count = 1,
        .i2cs = stm32f407vet6_i2cs,
        
        /* CAN configurations */
        .can_count = 1,
        .cans = stm32f407vet6_cans,
        
        /* ADC configurations */
        .adc_count = 1,
        .adcs = stm32f407vet6_adcs
    },
    
    /* Initialization function pointers */
    .init_funcs = {
        .led_init = default_led_init,
        .button_init = default_button_init,
        .uart_init = default_uart_init,
        .spi_init = default_spi_init,
        .i2c_init = default_i2c_init,
        .can_init = default_can_init,
        .adc_init = default_adc_init,
        .w25qxx_init = default_w25qxx_init
    },
    
    /* Additional board-specific configuration */
    .custom_config = NULL,
    .custom_config_size = 0,
    
    /* Board revision information */
    .major_rev = 1,
    .minor_rev = 0,
    .patch_rev = 0,
    .revision_desc = "Original release"
};

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

/**
 * @brief Get board configuration
 * @retval Pointer to board configuration structure
 */
const bsp_board_config_t* bsp_board_get_config(void) {
    return &stm32f407vet6_board_config;
}
