/*
 * lcd_i2c.h
 *
 *  Created on: Oct 16, 2025
 *      Author: ew_05
 */

#ifndef LCD_I2C_H
#define LCD_I2C_H

#ifdef __cplusplus
extern "C" {
#endif

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

/* --------- Build-time configuration (override in project settings if needed) --------- */
// 7-bit LCD I2C expander address (PCF8574 boards are commonly 0x27 or 0x3F)
#ifndef LCD_I2C_ADDRESS_7B
#define LCD_I2C_ADDRESS_7B    (0x27U)
#endif

// Timeouts (ms)
#ifndef LCD_I2C_TIMEOUT_MS
#define LCD_I2C_TIMEOUT_MS        (100U)
#endif

#ifndef LCD_OP_TIMEOUT_MS
#define LCD_OP_TIMEOUT_MS         (20U)
#endif

#ifndef LCD_BUS_RECOVERY_DELAY_MS
#define LCD_BUS_RECOVERY_DELAY_MS (10U)
#endif

typedef enum {
    LCD_STATE_READY = 0,
    LCD_STATE_BUSY,
    LCD_STATE_ERROR
} lcd_state_t;

/* ------------------------------ Public API --------------------------------- */

/**
 * @brief  Provide the I2C handle used by the LCD driver (call once after MX_I2C_Init).
 */
void lcd_i2c_attach(I2C_HandleTypeDef *hi2c);

/**
 * @brief  Initialize the HD44780-compatible LCD via PCF8574 I2C expander.
 * @return HAL_OK on success, else HAL error code.
 */
HAL_StatusTypeDef lcd_init(void);

/**
 * @brief  Clear display.
 */
HAL_StatusTypeDef lcd_clear(void);

/**
 * @brief  Set cursor position.
 * @param  row: 0..3 (only 0..1 for 16x2)
 * @param  col: column index
 */
HAL_StatusTypeDef lcd_put_cur(uint8_t row, uint8_t col);

/**
 * @brief  Write a single character at current position.
 */
HAL_StatusTypeDef lcd_write_char(char c);

/**
 * @brief  Write a zero-terminated string starting at (row,col).
 * @note   Safe for short strings; for big buffers, call put_cur() then stream chars.
 */
HAL_StatusTypeDef lcd_write(uint8_t row, uint8_t col, const char *str);

/**
 * @brief  Turn backlight on/off.
 */
HAL_StatusTypeDef lcd_backlight_on(void);
HAL_StatusTypeDef lcd_backlight_off(void);

/**
 * @brief  Access driver status/counters (optional).
 */
void lcd_get_status(uint8_t *i2c_errors, lcd_state_t *state);

/**
 * @brief  Attempt to recover I2C bus and internal driver state after error.
 */
void lcd_recover_bus(void);

#ifdef __cplusplus
}
#endif

#endif /* LCD_I2C_H */

