/**
 * @file rs485_driver.h
 * @brief Header file for RS-485 communication driver.
 *
 * This driver provides functions to configure and control RS-485 communication
 * using USART with RTS pin as TX enable. Each device has an 8-bit address
 * defined by 4 bits on PB12-PB15 (upper nibble) and 4 bits on PA2-PA5 (lower nibble),
 * all with pull-up resistors enabled.
 *
 * @note Based on STM32F103C8T6 microcontroller and USART configuration
 */

#ifndef INC_RS485_DRIVER_H_
#define INC_RS485_DRIVER_H_

#include <stdint.h>
#include "stm32f1xx_hal.h"
#include "stm32f1xx_ll_gpio.h"

#ifdef __cplusplus
extern "C" {
#endif


/* --- TX Enable Pin Configuration --- */
#define RS485_TX_EN_PORT              GPIOA
#define RS485_TX_EN_PIN               GPIO_PIN_12 /*!< RTS pin for TX enable */

#define	RS485_ADDR_MASK_LOW			0x0000003C  // GPIOA bits 2,3,4,5
#define	RS485_ADDR_MASK_HIGH		0x0000F000	// GPIOB bits 12,13,14,15

#define	RS485_ADDR_BIT_SET_LOW		2
#define	RS485_ADDR_BIT_SET_HIGH		8

/**
 * @brief RS-485 device address structure.
 */
typedef struct {
    uint8_t nibble_high;  /*!< High nibble of the address (PB12-PB15) */
    uint8_t nibble_low;   /*!< Low nibble of the address (PA2-PA5) */
    uint8_t full_address; /*!< Full 8-bit address */
} rs485_address_t;


/* --- Function Prototypes --- */

/**
 * @brief Initializes the RS-485 driver.
 * @note This function configures GPIOs for address detection and USART1 for communication.
 */
void rs485_init(void);

/**
 * @brief Gets the current device address from GPIOs.
 * @return The 8-bit device address.
 */
uint8_t rs485_get_address(void);

/**
 * @brief Sends data to a specific RS-485 address.
 * @param address Target device address.
 * @param data Pointer to the data buffer.
 * @param length Number of bytes to send.
 * @retval HAL_OK on success, otherwise error code.
 */
HAL_StatusTypeDef rs485_send_to_address(uint8_t address, uint8_t* data, uint16_t length);


/**
 * @brief Sends data to all devices (broadcast).
 * @param data Pointer to the data buffer.
 * @param length Number of bytes to send.
 * @retval HAL_OK on success, otherwise error code.
 */
HAL_StatusTypeDef rs485_send_broadcast(uint8_t* data, uint16_t length);


/**
 * @brief Receives data from RS-485 bus.
 * @param data Pointer to the receive buffer.
 * @param length Maximum number of bytes to receive.
 * @retval Number of bytes received, or 0 on error.
 */
uint16_t rs485_receive(uint8_t* data, uint16_t length);

/**
 * @brief Enables transmission mode on RS-485 transceiver.
 */
void rs485_enable_tx(void);

/**
 * @brief Disables transmission mode on RS-485 transceiver.
 */
void rs485_disable_tx(void);

#ifdef __cplusplus
}
#endif

#endif /* INC_RS485_DRIVER_H_ */
