/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : hal_uart.c
  * @brief          : UART hardware abstraction layer source file
  ******************************************************************************
  */
/* USER CODE END Header */

#include "hal.h"
#include "hal_uart.h"

/**
 * @brief Initialize UART hardware
 * @retval HAL status code
 */
hal_ret_t hal_uart_init(void) {
    /* Call architecture specific UART initialization */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F1
    hal_stm32f1_uart_init();
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    hal_stm32f4_uart_init();
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F7
    hal_stm32f7_uart_init();
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32L4
    hal_stm32l4_uart_init();
#else
#error "Unsupported HAL architecture"
    return HAL_RET_ERROR;
#endif
    return HAL_RET_OK;
}

/**
 * @brief Configure UART parameters for specific instance
 * @param config: UART configuration structure
 * @retval HAL status code
 */
hal_ret_t hal_uart_config(const hal_uart_config_t *config) {
    if (config == NULL) {
        return HAL_RET_INVALID_PARAM;
    }
    
    if (config->instance >= HAL_UART_INSTANCE_MAX) {
        return HAL_RET_INVALID_PARAM;
    }
    
    /* Call architecture specific UART configuration */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F1
    hal_stm32f1_uart_config(config);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    hal_stm32f4_uart_config(config);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F7
    hal_stm32f7_uart_config(config);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32L4
    hal_stm32l4_uart_config(config);
#else
#error "Unsupported HAL architecture"
    return HAL_RET_ERROR;
#endif
    return HAL_RET_OK;
}

/**
 * @brief Send data over specific UART instance
 * @param instance: UART instance identifier
 * @param data: Pointer to data buffer
 * @param length: Data length in bytes
 * @retval HAL status code
 */
hal_ret_t hal_uart_send(hal_uart_instance_t instance, const uint8_t *data, size_t length) {
    if (data == NULL || length == 0) {
        return HAL_RET_INVALID_PARAM;
    }
    
    if (instance >= HAL_UART_INSTANCE_MAX) {
        return HAL_RET_INVALID_PARAM;
    }
    
    /* Call architecture specific UART send implementation */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F1
    hal_stm32f1_uart_send(instance, data, length);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    hal_stm32f4_uart_send(instance, data, length);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F7
    hal_stm32f7_uart_send(instance, data, length);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32L4
    hal_stm32l4_uart_send(instance, data, length);
#else
#error "Unsupported HAL architecture"
    return HAL_RET_ERROR;
#endif
    return HAL_RET_OK;
}

/**
 * @brief Receive data from specific UART instance
 * @param instance: UART instance identifier
 * @param data: Pointer to data buffer
 * @param length: Data length to receive in bytes
 * @param received: Pointer to store number of bytes received
 * @retval HAL status code
 */
hal_ret_t hal_uart_receive(hal_uart_instance_t instance, uint8_t *data, size_t length, size_t *received) {
    if (data == NULL || received == NULL || length == 0) {
        return HAL_RET_INVALID_PARAM;
    }
    
    if (instance >= HAL_UART_INSTANCE_MAX) {
        return HAL_RET_INVALID_PARAM;
    }
    
    /* Call architecture specific UART receive implementation */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F1
    *received = hal_stm32f1_uart_receive(instance, data, length);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    *received = hal_stm32f4_uart_receive(instance, data, length);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F7
    *received = hal_stm32f7_uart_receive(instance, data, length);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32L4
    *received = hal_stm32l4_uart_receive(instance, data, length);
#else
#error "Unsupported HAL architecture"
    return HAL_RET_ERROR;
#endif
    return HAL_RET_OK;
}

/**
 * @brief Check if specific UART instance is ready to send
 * @param instance: UART instance identifier
 * @param ready: Pointer to store ready status (1 if ready, 0 otherwise)
 * @retval HAL status code
 */
hal_ret_t hal_uart_is_tx_ready(hal_uart_instance_t instance, uint8_t *ready) {
    if (ready == NULL) {
        return HAL_RET_INVALID_PARAM;
    }
    
    if (instance >= HAL_UART_INSTANCE_MAX) {
        return HAL_RET_INVALID_PARAM;
    }
    
    /* Call architecture specific UART TX ready check */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F1
    *ready = hal_stm32f1_uart_is_tx_ready(instance);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    *ready = hal_stm32f4_uart_is_tx_ready(instance);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F7
    *ready = hal_stm32f7_uart_is_tx_ready(instance);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32L4
    *ready = hal_stm32l4_uart_is_tx_ready(instance);
#else
#error "Unsupported HAL architecture"
    return HAL_RET_ERROR;
#endif
    return HAL_RET_OK;
}

/**
 * @brief Check if specific UART instance has data to receive
 * @param instance: UART instance identifier
 * @param ready: Pointer to store ready status (1 if data available, 0 otherwise)
 * @retval HAL status code
 */
hal_ret_t hal_uart_is_rx_ready(hal_uart_instance_t instance, uint8_t *ready) {
    if (ready == NULL) {
        return HAL_RET_INVALID_PARAM;
    }
    
    if (instance >= HAL_UART_INSTANCE_MAX) {
        return HAL_RET_INVALID_PARAM;
    }
    
    /* Call architecture specific UART RX ready check */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F1
    *ready = hal_stm32f1_uart_is_rx_ready(instance);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    *ready = hal_stm32f4_uart_is_rx_ready(instance);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32F7
    *ready = hal_stm32f7_uart_is_rx_ready(instance);
#elif HAL_TARGET_ARCH == HAL_ARCH_STM32L4
    *ready = hal_stm32l4_uart_is_rx_ready(instance);
#else
#error "Unsupported HAL architecture"
    return HAL_RET_ERROR;
#endif
    return HAL_RET_OK;
}