//
// Created by dell on 24-12-20.
//

#ifndef I2C_H
#define I2C_H

#include "gd32e23x_it.h"
#include "gd32e23x.h"
#include "systick.h"
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "board_config.h"

/******************************************************************************/

#define I2C_SPEED           20000U         /* 20kHz */
#define I2C_TIME_OUT        5000U           /* 5000 loops timeout */
#define I2C_MAX_RETRY       3U              /* Maximum retry attempts */
#define I2C_DELAY_10US      10U             /* Delay in microseconds for bus reset */
#define I2C_RECOVERY_CLOCKS 9U              /* Clock pulses for bus recovery */
#define I2C_MASTER_ADDRESS  0x00U           /* Master address (not used) */

/* Legacy compatibility */
#define I2C_OK              1
#define I2C_FAIL            0
#define I2C_END             1

/******************************************************************************/

/* I2C result enumeration */
typedef enum {
    I2C_RESULT_SUCCESS = 0,     /* Operation successful */
    I2C_RESULT_TIMEOUT,         /* Timeout occurred */
    I2C_RESULT_NACK,            /* No acknowledge received */
    I2C_RESULT_BUS_BUSY,        /* Bus is busy */
    I2C_RESULT_ERROR,           /* General error */
    I2C_RESULT_INVALID_PARAM,   /* Invalid parameter */
    I2C_RECOVERY_OK,
    I2C_RECOVERY_SDA_STUCK_LOW,
    I2C_RECOVERY_SCL_STUCK_LOW
} i2c_result_t;

/* I2C state machine enumeration */
typedef enum {
    I2C_STATE_IDLE = 0,         /* Idle state */
    I2C_STATE_START,            /* Generate start condition */
    I2C_STATE_SEND_ADDRESS,     /* Send slave address */
    I2C_STATE_CLEAR_ADDRESS,    /* Clear address flag */
    I2C_STATE_TRANSMIT_REG,     /* Transmit register address */
    I2C_STATE_TRANSMIT_DATA,    /* Transmit data */
    I2C_STATE_RESTART,          /* Generate restart condition */
    I2C_STATE_RECEIVE_DATA,     /* Receive data */
    I2C_STATE_STOP,             /* Generate stop condition */
    I2C_STATE_ERROR,            /* Error state */
    I2C_STATE_END
} i2c_state_t;

/******************************************************************************/


/* Function declarations */
/*!
    \brief      configure the I2C interface
    \param[in]  none
    \param[out] none
    \retval     i2c_result_t
*/
i2c_result_t i2c_config(void);

/*!
    \brief      reset I2C bus with proper recovery
    \param[in]  none
    \param[out] none
    \retval     i2c_result_t
*/
i2c_result_t i2c_bus_reset(void);

/*!
    \brief      scan I2C bus for devices
    \param[in]  none
    \param[out] none
    \retval     none
*/
void i2c_scan(void);

/*!
    \brief      write 16-bit data to I2C device
    \param[in]  slave_addr: 7-bit slave address
    \param[in]  reg_addr: register address
    \param[in]  data: pointer to 2-byte data array
    \param[out] none
    \retval     i2c_result_t
*/
i2c_result_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]);

/*!
    \brief      read 16-bit data from I2C device
    \param[in]  slave_addr: 7-bit slave address
    \param[in]  reg_addr: register address
    \param[out] data: pointer to 2-byte data buffer
    \retval     i2c_result_t
*/
i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data);

/* Generic read/write functions with configurable length */
/*!
    \brief      write data to I2C device with configurable length
    \param[in]  slave_addr: slave device address (7-bit)
    \param[in]  reg_addr: register address
    \param[in]  data: pointer to data buffer
    \param[in]  length: number of bytes to write (1-255)
    \param[out] none
    \retval     i2c_result_t: operation result
*/
i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length);

/*!
    \brief      read data from I2C device with configurable length
    \param[in]  slave_addr: slave device address (7-bit)
    \param[in]  reg_addr: register address
    \param[out] data: pointer to data buffer
    \param[in]  length: number of bytes to read (1-255)
    \retval     i2c_result_t: operation result
*/
i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length);

#ifdef DEBUG_VERBOSE
/*!
    \brief      get status string for debugging
    \param[in]  status: i2c_result_t value
    \param[out] none
    \retval     const char* status string
*/
const char* i2c_get_status_string(i2c_result_t status);
#endif

#endif //I2C_H
