/*!
 * @file        g32a10xx_gpio_i2c.c
 *
 * @brief       This file contains all the functions for the GPIO I2C peripheral
 *
 * @version     V1.0.0
 *
 * @date        2026-02-25
 *
 * @attention
 *
 *  Copyright (C) 2026 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (Geehy Semiconductor Software License Agreement).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be useful and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the Geehy Semiconductor Software License Agreement for the governing permissions
 *  and limitations under the License.
 */

/* Includes */
#include "g32a10xx_gpio_i2c.h"
#include "at24cxx.h"
#include "Board.h"

/** @addtogroup Examples
  @{
  */

/** @addtogroup I2C_Examples
  @{
  */

/** @addtogroup GPIO_I2C
  @{
  */

/** @defgroup GPIO_I2C_HOST_Variables
  @{
  */

/**@} end of group GPIO_I2C_HOST_Variables */

/** @defgroup GPIO_I2C_Functions
  @{
  */


#ifdef AT24C02  

/*!
 * @brief       AT24C02 write one byte
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
void I2c_At24c02_WriteByte(uint8_t Addr, uint8_t Data)
{
    EEPROM_WP_DISABLE();
    I2c_Start();
    I2c_SendByte(AT24C02_ADDR & 0xFEU);
    I2c_WaitAck();
    I2c_SendByte(Addr);
    I2c_WaitAck();
    I2c_SendByte(Data);
    I2c_WaitAck();
    I2c_Stop();
    I2c_DelayMs(5); // wait 5ms at least
    EEPROM_WP_ENABLE();
}

/*!
 * @brief       AT24C02 read one byte
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
uint8_t I2c_At24c02_ReadByte(uint8_t Addr)
{
    uint8_t data;
    I2c_Start();
    I2c_SendByte(AT24C02_ADDR & 0xFEU);
    I2c_WaitAck();
    I2c_SendByte(Addr);
    I2c_WaitAck();

    I2c_Start();
    I2c_SendByte(AT24C02_ADDR | 0x01U);
    I2c_WaitAck();
    data = I2c_ReadByte(0);
    I2c_Stop();
    return data;
}

/*!
 * @brief       AT24C02 write one page
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
void I2c_At24c02_WritePage(uint8_t Addr, uint8_t *BufPtr, uint8_t Len)
{
    if(Len > AT24C02_PAGE_SIZE) 
    {
        Len = AT24C02_PAGE_SIZE;
    }
    else
    {
        // nothing
    }
    
    EEPROM_WP_DISABLE();
    I2c_Start();
    I2c_SendByte(AT24C02_ADDR & 0xFEU);
    I2c_WaitAck();
    I2c_SendByte(Addr);
    I2c_WaitAck();

    while(Len--)
    {
        I2c_SendByte(*BufPtr);
        I2c_WaitAck();
        BufPtr++;
    }
    I2c_Stop();
    I2c_DelayMs(5); // wait 5ms at least
    EEPROM_WP_ENABLE();
}

/*!
 * @brief       AT24C02 read multiple bytes
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
void I2c_At24c02_ReadData(uint8_t Addr, uint8_t *BufPtr, uint8_t Len)
{
    I2c_Start();
    I2c_SendByte(AT24C02_ADDR & 0xFEU);
    I2c_WaitAck();
    I2c_SendByte(Addr);
    I2c_WaitAck();

    I2c_Start();
    I2c_SendByte(AT24C02_ADDR | 0x01U);
    I2c_WaitAck();

    while(Len--)
    {
        if(Len == 0)
        {
            *BufPtr = I2c_ReadByte(0);
        }
        else
        {
            *BufPtr = I2c_ReadByte(1);
        }
        BufPtr++;
    }
    I2c_Stop();
}

#else
/*!
 * @brief       AT24C32 write one byte
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
void I2c_At24c32_WriteByte(uint16_t Addr, uint8_t Data)
{
    EEPROM_WP_DISABLE();
    I2c_Start();
    I2c_SendByte(AT24C32_ADDR & 0xFEU);
    I2c_WaitAck();
    I2c_SendByte((uint8_t)(Addr>>8));//first word address
    I2c_WaitAck();
    I2c_SendByte((uint8_t)Addr);//second word address
    I2c_WaitAck();
    I2c_SendByte(Data);
    I2c_WaitAck();
    I2c_Stop();
    I2c_DelayMs(5);  // wait 5ms at least
    EEPROM_WP_ENABLE();
}

/*!
 * @brief       AT24C32 read one byte
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
uint8_t I2c_At24c32_ReadByte(uint16_t Addr)
{
    uint8_t data;
    I2c_Start();
    I2c_SendByte(AT24C32_ADDR & 0xFEU);
    I2c_WaitAck();
    I2c_SendByte((uint8_t)(Addr>>8));//first word address
    I2c_WaitAck();
    I2c_SendByte((uint8_t)Addr);//second word address
    I2c_WaitAck();

    I2c_Start();
    I2c_SendByte(AT24C32_ADDR | 0x01U);
    I2c_WaitAck();
    data = I2c_ReadByte(0);
    I2c_Stop();
    return data;
}

/*!
 * @brief       AT24C32 write one page
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
void I2c_At24c32_WritePage(uint16_t Addr, const uint8_t *BufPtr, uint8_t Len)
{
    const uint8_t *buffer = BufPtr;
    uint8_t leng = Len;

    if(leng > AT24C32_PAGE_SIZE)
    {        
        leng = AT24C32_PAGE_SIZE;
    }
    else
    {
        /* nothing */
    }
    
    EEPROM_WP_DISABLE();
    I2c_Start();
    I2c_SendByte((uint8_t)AT24C32_ADDR & 0xFEU);
    I2c_WaitAck();
    I2c_SendByte((uint8_t)(Addr>>8));//first word address
    I2c_WaitAck();
    I2c_SendByte((uint8_t)Addr);//second word address
    I2c_WaitAck();

    while(leng != 0U)
    {
        leng = leng - 1U;
        I2c_SendByte(*buffer);
        I2c_WaitAck();
        buffer++;
    }
    I2c_Stop();
    I2c_DelayMs(5); // wait 5ms at least
    EEPROM_WP_ENABLE();
}

/*!
 * @brief       AT24C32 read multiple bytes
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
void I2c_At24c32_ReadData(uint16_t Addr, uint8_t *BufPtr, uint8_t Len)
{
    uint8_t *buffer = BufPtr;
    uint8_t leng = Len;

    I2c_Start();
    I2c_SendByte((uint8_t)AT24C32_ADDR & 0xFEU);
    I2c_WaitAck();
    I2c_SendByte((uint8_t)(Addr>>8));//first word address
    I2c_WaitAck();
    I2c_SendByte((uint8_t)Addr);//second word address
    I2c_WaitAck();

    I2c_Start();
    I2c_SendByte((uint8_t)AT24C32_ADDR | 0x01U);
    I2c_WaitAck();

    while(leng != 0U)
    {
        leng = leng - 1U;

        if(leng == 0U)
        {
            *buffer = I2c_ReadByte(0);
        }
        else
        {
            *buffer = I2c_ReadByte(1);
        }
        buffer++;
    }
    I2c_Stop();
}
#endif

/**@} end of group GPIO_I2C_Functions */
/**@} end of group GPIO_I2C */
/**@} end of group I2C_Examples */
/**@} end of group Examples */
