/******************************************************************************
 * @file     i2c.c
 * @brief    I2C firmware functions.
 * @version  V4.0.1
 * @date     30-July-2026
 *
 * @note
 * Copyright (C) 2022 Spintrol Electronic Technology (Shanghai) Co., Ltd.. All rights reserved.
 *
 * @attention
 * THIS SOFTWARE JUST PROVIDES CUSTOMERS WITH CODING INFORMATION REGARDING
 * THEIR PRODUCTS, WHICH AIMS AT SAVING TIME FOR THEM. SPINTROL SHALL NOT BE
 * LIABLE FOR THE USE OF THE SOFTWARE. SPINTROL DOES NOT GUARANTEE THE
 * CORRECTNESS OF THIS SOFTWARE AND RESERVES THE RIGHT TO MODIFY THE SOFTWARE
 * WITHOUT NOTIFICATION.
 *
 ******************************************************************************/

#include "i2c.h"


#if defined(__CC_ARM)
    #pragma push
    #pragma O1
#endif




/******************************************************************************
 * @brief      Initializes I2C Speed
 *
 * @param[in]  I2Cx      :  Select the I2C module
 * @param[in]  u32Speed  :  Operation speed (bps)
 * @param[in]  eSpeedMode:  Operation speed mode
 *
 * @return     ErrorStatus:
 *                  ERROR if I2C clock is not fast enough to support the speed
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_SpeedInit(I2C_REGS *I2Cx, uint32_t u32Speed, I2C_SpeedModeEnum eSpeedMode)
{
    uint32_t u32PCnt;
    uint32_t u32HCnt;
    uint32_t u32LCnt;
    uint32_t u32SpikeLen;
    uint32_t u32ClkFreq;
    u32ClkFreq = CLOCK_GetModuleClock(I2C_MODULE);

    /*  Check minimum speed  */
    if (u32Speed <= 0)
    {
        return ERROR;
    }

    /*  Limit Maximum Speed  */
    if (I2C_SPEED_STANDARD == eSpeedMode)
    {
        if (u32Speed >= 100000)  
        {
            u32Speed = 100000;
        }
    }
    else if (I2C_SPEED_FAST == eSpeedMode)
    {
        if (u32Speed >= 400000)  
        {
            u32Speed = 400000;
        }
    }
    else if (I2C_SPEED_HIGH == eSpeedMode)
    {
        /* Maximum support 2 Mbps */
        if (u32Speed >= 2000000)  
        {
            u32Speed = 2000000;
        }
    }
    else
    {
        return ERROR;
    }

    u32PCnt = u32ClkFreq / u32Speed;

    /* Standard mode (100 kbps) */
    if (I2C_SPEED_STANDARD == eSpeedMode)
    {
        u32SpikeLen = u32ClkFreq / 20000000;
        if ((u32SpikeLen * 20000000) != u32ClkFreq)
        {
            u32SpikeLen = u32SpikeLen + 1;
        }

        if (u32PCnt < ((8 + 6 + 5) + 3 * u32SpikeLen))
        {
            return ERROR;
        }

        /* Calculate u32HCnt and  u32LCnt */
        u32PCnt = u32PCnt - (8 + 6 + 5) - 3 * u32SpikeLen;
        u32HCnt = (uint32_t)(u32PCnt / 2);
        u32LCnt = u32PCnt - u32HCnt + 8 + u32SpikeLen;
        u32HCnt = (6 + 5) + u32HCnt + 2 * u32SpikeLen;

        /* Check whether I2C clock is fast enough to support the speed */
        if ((u32LCnt < 9) || (u32HCnt < 13))
        {
            return ERROR;
        }

        /* Set I2C operating speed mode */
        I2Cx->I2CCTL.bit.SPEED = I2CCTL_BIT_SPEED_100K_BPS;

        /* Spike suppresion */
        I2Cx->I2CFSSPKLEN.all = u32SpikeLen;

        /* Standard mode SCL hold low time counter */
        I2Cx->I2CSSLCNT.all = u32LCnt - u32SpikeLen - 1;

        /* Standard mode SCL hold high time counter */
        I2Cx->I2CSSHCNT.all = u32HCnt - 5 - u32SpikeLen;

    }

    /* Fast mode (400 kbps) */
    else if (I2C_SPEED_FAST == eSpeedMode)
    {
        u32SpikeLen = u32ClkFreq / 20000000;
        if ((u32SpikeLen * 20000000) != u32ClkFreq)
        {
            u32SpikeLen = u32SpikeLen + 1;
        }

        if (u32PCnt < ((8 + 6 + 5) + 3 * u32SpikeLen))
        {
            return ERROR;
        }

        /* Calculate u32HCnt and  u32LCnt */
        u32PCnt = u32PCnt - (8 + 6 + 5) - 3 * u32SpikeLen;
        u32HCnt = (uint32_t)(u32PCnt / 2);
        u32LCnt = u32PCnt - u32HCnt + 8 + u32SpikeLen;
        u32HCnt = (6 + 5) + u32HCnt + 2 * u32SpikeLen;

        /* Check whether I2C clock is fast enough to support the speed */
        if ((u32LCnt < 9) || (u32HCnt < 13))
        {
            return ERROR;
        }

        /* Set I2C operating speed mode */
        I2Cx->I2CCTL.bit.SPEED = I2CCTL_BIT_SPEED_400K_BPS;

        /* Spike suppresion */
        I2Cx->I2CFSSPKLEN.all = u32SpikeLen;

        /* Fast mode SCL hold low time counter */
        I2Cx->I2CFSLCNT.all = u32LCnt - u32SpikeLen - 1;

        /* Fast mode SCL hold high time counter */
        I2Cx->I2CFSHCNT.all = u32HCnt - 5 - u32SpikeLen;
    }

    /* High speed mode (2 Mbps) */
    else if(I2C_SPEED_HIGH == eSpeedMode)
    {
        u32SpikeLen = u32ClkFreq / 100000000;
        if ((u32SpikeLen * 100000000) != u32ClkFreq)
        {
            u32SpikeLen = u32SpikeLen + 1;
        }

        if (u32PCnt < ((8 + 6 + 5) + 3 * u32SpikeLen))
        {
            return ERROR;
        }

        /* Calculate u32HCnt and  u32LCnt */
        u32PCnt = u32PCnt - (8 + 6 + 5) - 3 * u32SpikeLen;
        u32HCnt = (uint32_t)(u32PCnt / 2);
        u32LCnt = u32PCnt - u32HCnt + 8 + u32SpikeLen; 
        u32HCnt = (6 + 5) + u32HCnt + 2 * u32SpikeLen;

        /* Check whether I2C clock is fast enough to support the speed */
        if ((u32LCnt < 9) || (u32HCnt < 13))
        {
            return ERROR;
        }

        /* Set I2C operating speed mode */
        I2Cx->I2CCTL.bit.SPEED = I2CCTL_BIT_SPEED_3400K_BPS;

        /* Spike suppresion */
        I2Cx->I2CHSSPKLEN.all = u32SpikeLen;

        /* High mode SCL hold low time counter */
        I2Cx->I2CHSLCNT.all = u32LCnt - u32SpikeLen - 1;

        /* High mode SCL hold high time counter */
        I2Cx->I2CHSHCNT.all = u32HCnt - 5 - u32SpikeLen;
    }
    return SUCCESS;
}




/******************************************************************************
 * @brief      Sets the high speed master code
 *
 * @param[in]  I2Cx         :  Select the I2C module
 * @param[in]  u32MasterCode:  High speed master code
 *
 * @return     ErrorStatus:
 *                  SUCCESS if the operation is successful
 *                  ERROR if the operation fails
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_SetHighSpeedMasterCode(I2C_REGS *I2Cx, uint32_t u32MasterCode)
{
    uint32_t u32PCnt;
    uint32_t u32HCnt;
    uint32_t u32LCnt;
    uint32_t u32SpikeLen;
    uint32_t u32ClkFreq;
    uint32_t u32FastSpeed;

    u32ClkFreq = CLOCK_GetModuleClock(I2C_MODULE);

    /* Disable I2C */
    I2Cx->I2CENABLE.all = 0;
    
    u32FastSpeed = 400000;  // High speed mode requires setting the fast speed mode
    u32PCnt = u32ClkFreq / u32FastSpeed;

    u32SpikeLen = u32ClkFreq / 20000000;
    if ((u32SpikeLen * 20000000) != u32ClkFreq)
    {
        u32SpikeLen = u32SpikeLen + 1;
    }

    if (u32PCnt < ((8 + 6 + 5) + 3 * u32SpikeLen))
    {
        return ERROR;
    }

    /* Calculate u32HCnt and  u32LCnt */
    u32PCnt = u32PCnt - (8 + 6 + 5) - 3 * u32SpikeLen;
    u32HCnt = (uint32_t)(u32PCnt / 2);
    u32LCnt = u32PCnt - u32HCnt + 8 + u32SpikeLen;
    u32HCnt = (6 + 5) + u32HCnt + 2 * u32SpikeLen;

    /* Check whether I2C clock is fast enough to support the speed */
    if ((u32LCnt < 9) || (u32HCnt < 13))
    {
        return ERROR;
    }

    /* Spike suppresion */
    I2Cx->I2CFSSPKLEN.all = u32SpikeLen;

    /* Fast mode SCL hold low time counter */
    I2Cx->I2CFSLCNT.all = u32LCnt - u32SpikeLen - 1;

    /* Fast mode SCL hold high time counter */
    I2Cx->I2CFSHCNT.all = u32HCnt - 5 - u32SpikeLen;

    /* Set the high speed master code */
    if (u32MasterCode > 0x7)
    {
        return ERROR;  // Master code should be within 3 bits
    }
    else
    {
        I2Cx->I2CHSMADDR.all = u32MasterCode;  // Set the master code (3 bits)

        /* Enable I2C */
        I2Cx->I2CENABLE.all = I2CENABLE_ALL_EN_ENABLE;
        return SUCCESS;
    }
}




/******************************************************************************
 * @brief      Initializes the I2C master
 *
 * @param[in]  I2Cx      :  Select the I2C module
 * @param[in]  u32Speed  :  Operation speed (bps)
 * @param[in]  eSpeedMode:  Operation speed mode
 *
 * @return     ErrorStatus:
 *                  ERROR if I2C clock is not fast enough to support the speed
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_MasterInit(I2C_REGS *I2Cx, uint32_t u32Speed, I2C_SpeedModeEnum eSpeedMode)
{
    /* Enable I2C Module Clock */
    CLOCK_EnableModule(I2C_MODULE);

    /* Disable I2C */
    I2Cx->I2CENABLE.all = 0;

    /* Slave is diable */
    I2Cx->I2CCTL.bit.SLVDIS = I2CCTL_BIT_SLVDIS_SLAVE_DISABLE;

    /* Master enable */
    I2Cx->I2CCTL.bit.MASTER = I2CCTL_BIT_MASTER_ENABLE;

    /* Restart enable */
    I2Cx->I2CCTL.bit.RESTARTEN = I2CCTL_BIT_RESTARTEN_ENABLE;

    /* Init I2C Speed */
    if (I2C_SpeedInit(I2Cx, u32Speed, eSpeedMode) == SUCCESS)
    {
        /* Enable I2C */
        I2Cx->I2CENABLE.all = I2CENABLE_ALL_EN_ENABLE;
        return SUCCESS;
    }
    else
    {
        return ERROR;
    }
}




/******************************************************************************
 * @brief      Initializes the I2C slave
 *
 * @param[in]  I2Cx      :  Select the I2C module
 * @param[in]  eAddrMode :  Address mode
 *                          See I2C_AddrModeEnum for details
 *                           - \ref I2C_ADDR_7BIT
 *                           - \ref I2C_ADDR_10BIT
 * @param[in]  u16SlvAddr:  Slave address
 * @param[in]  u32Speed  :  Operation speed (bps)
 * @param[in]  eSpeedMode:  Operation speed mode
 *
 * @return     ErrorStatus:
 *                  ERROR if I2C clock is not fast enough to support the speed
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_SlaveInit(I2C_REGS *I2Cx, I2C_AddrModeEnum eAddrMode, uint16_t u16SlvAddr, uint32_t u32Speed, I2C_SpeedModeEnum eSpeedMode)
{
    uint32_t u32SDASetup;

    /* Enable I2C Module Clock */
    CLOCK_EnableModule(I2C_MODULE);

    /* Disable I2C */
    I2Cx->I2CENABLE.all = 0;

    /* Slave is enable */
    I2Cx->I2CCTL.bit.SLVDIS = I2CCTL_BIT_SLVDIS_SLAVE_ENABLE;

    /* Master disable */
    I2Cx->I2CCTL.bit.MASTER = I2CCTL_BIT_MASTER_DISABLE;

    /* Restart enable */
    I2Cx->I2CCTL.bit.RESTARTEN = I2CCTL_BIT_RESTARTEN_ENABLE;

    /* Slave address mode */
    I2Cx->I2CCTL.bit.SLVADDR10B = eAddrMode;

    /* Slave address */
    I2Cx->I2CSLVADDR.all = u16SlvAddr;

    if (u32Speed <= 100000)
    {
        /* SDA Minimum Set Up Delay 250ns */
        u32SDASetup = CLOCK_GetModuleClock(I2C_MODULE) / 4000000 + 1;
    }
    else if (u32Speed <= 400000)
    {
        /* SDA Minimum Set Up Delay 100ns */
        u32SDASetup = CLOCK_GetModuleClock(I2C_MODULE) / 10000000 + 1;
    }
    else
    {
        /* SDA Minimum Set Up Delay 30ns */
        u32SDASetup = CLOCK_GetModuleClock(I2C_MODULE) * 3 / 100000000 + 1;
    }

    /* Check whether I2C clock is fast enough to support the speed */
    if (u32SDASetup < 2)
    {
        return ERROR;
    }
    else
    {
        I2Cx->I2CSDASETUP.all = u32SDASetup;
    }

    if (I2C_SPEED_STANDARD == eSpeedMode)
    {
        /* Set I2C operating speed mode */
        I2Cx->I2CCTL.bit.SPEED = I2CCTL_BIT_SPEED_100K_BPS;
    }
    else if (I2C_SPEED_FAST == eSpeedMode)
    {
        /* Set I2C operating speed mode */
        I2Cx->I2CCTL.bit.SPEED = I2CCTL_BIT_SPEED_400K_BPS;
    }
    else if (I2C_SPEED_HIGH == eSpeedMode)
    {
        /* Set I2C operating speed mode */
        I2Cx->I2CCTL.bit.SPEED = I2CCTL_BIT_SPEED_3400K_BPS;
    }
    else
    {
        return ERROR;
    }

    /* Enable I2C */
    I2Cx->I2CENABLE.all = I2CENABLE_ALL_EN_ENABLE;

    return SUCCESS;
}




/******************************************************************************
 * @brief      Enable I2C General Call function
 *
 * @param[in]  I2Cx:  Select the I2C module
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void I2C_EnableGeneralCall(I2C_REGS *I2Cx)
{
    I2Cx->I2CMASTERADDR.bit.SPECIAL = 1;
    I2Cx->I2CMASTERADDR.bit.GCORSTART = 0;
}




/******************************************************************************
 * @brief      Disable I2C General Call function
 *
 * @param[in]  I2Cx:  Select the I2C module
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void I2C_DisableGeneralCall(I2C_REGS *I2Cx)
{
    I2Cx->I2CMASTERADDR.bit.SPECIAL = 0;
}




/******************************************************************************
 * @brief      Enable I2C START BYTE function
 *
 * @param[in]  I2Cx:  Select the I2C module
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void I2C_EnableStartByte(I2C_REGS *I2Cx)
{
    I2Cx->I2CMASTERADDR.bit.SPECIAL = 1;
    I2Cx->I2CMASTERADDR.bit.GCORSTART = 1;
}




/******************************************************************************
 * @brief      Disable I2C START BYTE function
 *
 * @param[in]  I2Cx:  Select the I2C module
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void I2C_DisableStartByte(I2C_REGS *I2Cx)
{
    I2Cx->I2CMASTERADDR.bit.SPECIAL = 0;
}




/******************************************************************************
 * @brief      Clear specified interrupt flag
 *
 * @param[in]  I2Cx    :  Select the I2C module
 * @param[in]  eIntType:  Specified interrupt type
 *                        See I2C_IntEnum for details
 *                         - \ref I2C_INT_RX_UNDER
 *                         - \ref I2C_INT_RX_OVER
 *                         - \ref I2C_INT_TX_OVER
 *                         - \ref I2C_INT_RD_REQ
 *                         - \ref I2C_INT_TX_ABORT
 *                         - \ref I2C_INT_RX_DONE
 *                         - \ref I2C_INT_ACTIVITY
 *                         - \ref I2C_INT_STOP_DET
 *                         - \ref I2C_INT_START_DET
 *                         - \ref I2C_INT_GEN_CALL
 *                         - \ref I2C_INT_ALL
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void I2C_ClearInt(I2C_REGS *I2Cx, I2C_IntEnum eIntType)
{
    volatile uint32_t dummyData;

    switch (eIntType)
    {
        case I2C_INT_RX_UNDER:
            dummyData = I2Cx->I2CRXUDFCLR.all;
            break;

        case I2C_INT_RX_OVER:
            dummyData = I2Cx->I2CRXOVFCLR.all;
            break;

        case I2C_INT_TX_OVER:
            dummyData = I2Cx->I2CTXOVFCLR.all;
            break;

        case I2C_INT_RD_REQ:
            dummyData = I2Cx->I2CRDREQCLR.all;
            break;

        case I2C_INT_TX_ABORT:
            dummyData = I2Cx->I2CTXABRTCLR.all;
            break;

        case I2C_INT_RX_DONE:
            dummyData = I2Cx->I2CRXDONECLR.all;
            break;

        case I2C_INT_ACTIVITY:
            dummyData = I2Cx->I2CACTCLR.all;
            break;

        case I2C_INT_STOP_DET:
            dummyData = I2Cx->I2CSTOPDETCLR.all;
            break;

        case I2C_INT_START_DET:
            dummyData = I2Cx->I2CSTARTDETCLR.all;
            break;

        case I2C_INT_GEN_CALL:
            dummyData = I2Cx->I2CGENCALLCLR.all;
            break;

        case I2C_INT_ALL:
            dummyData = I2Cx->I2CINTCLR.all;
            break;

        default:
            break;
    }
}




/******************************************************************************
 * @brief      I2C Master Mode Send Data function
 *
 * @param[in]  I2Cx          :  Select the I2C module
 * @param[in]  eAddrMode     :  Address mode
 *                              See I2C_AddrModeEnum for details
 *                               - \ref I2C_ADDR_7BIT
 *                               - \ref I2C_ADDR_10BIT
 * @param[in]  u16TargetAddr :  Target Slave address
 * @param[in]  pu8WriteBuffer:  Pointer to the buffer that stored the data to be sent
 * @param[in]  u32Count      :  Number of data to be sent or received
 *
 * @return     SUCCESS or ERROR
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_MasterWrite(I2C_REGS *I2Cx, I2C_AddrModeEnum eAddrMode,
                     uint16_t u16TargetAddr, uint8_t *pu8WriteBuffer, uint32_t u32Count)
{
    uint32_t i;
    uint64_t u64TimeOut = 0;

    /* Set Address Mode */
    I2Cx->I2CMASTERADDR.bit.MASTERADDR10B = eAddrMode;

    /* Set Target Slave Address*/
    I2Cx->I2CMASTERADDR.bit.TARADDR = u16TargetAddr;

    for (i = 0; i < u32Count; i++)
    {
        /* Write TxFIFO, Send Address and Send Data If Master Get ACK */
        I2C_WriteByte(I2Cx, pu8WriteBuffer[i]);

        /* Wait Slave Receive Data And Send ACK Again,
         * Then Master Stop Bus Because of TxFIFO Empty
         */

        /* Wait Until TxFIFO Empty */
        /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
           bps = 8bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms.
           Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
           In total, approximately 21 * 16 = 336 ms. In 1 ms, CPU executes 200,000 instructions. Thus, in 336 ms, 
           a total of 67,200,000 instructions are executed. */
        for (u64TimeOut = 67200000UL; u64TimeOut > 0UL; u64TimeOut--)
        {
            if (I2C_IsTxEmpty(I2Cx))
            {
                break;
            }
        }
        
        /* Wait Until TxFIFO Empty Timeout*/
        if (u64TimeOut == 0)
        {
            return ERROR;
        }

        /* Wait I2C Bus Idle */
        /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
           bps = 4bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms.
           Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth.
           In total, approximately 21 * 16 = 336 ms. In an extreme scenario, with a total of 1023 master on the i2c bus, 
           the waiting time would be 336 * 1023 = 343,728 ms. In 1 ms, CPU executes 200,000 instructions.
           Thus, in 343,728 ms, a total of 68,745,600,000 instructions are executed. */
        for (u64TimeOut = 68745600000; u64TimeOut > 0UL; u64TimeOut--)
        {
            if (!I2C_IsActivity(I2Cx))
            {
                break;
            }
        }

        /* I2C Bus Wait Timeout*/
        if (u64TimeOut == 0)
        {
            return ERROR;
        }

        /* Do Not Get ACK, Master Abort Send Data, Flush TxFIFO, Send Stop Signal */
        if (I2C_GetTxAbortIntRawFlag(I2Cx))
        {
            /* Return error when tx abort*/
            return ERROR;
        }
    }
    return SUCCESS;
}




/******************************************************************************
 * @brief      I2C Slave Mode Receive Data function
 *
 * @param[in]  I2Cx         :  Select the I2C module
 * @param[in]  pu8ReadBuffer:  Pointer to the buffer that stored the received data
 * @param[in]  u32Count     :  Number of data to be sent or received
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void I2C_SlaveRead(I2C_REGS *I2Cx, uint8_t *pu8ReadBuffer, uint32_t u32Count)
{
    uint32_t i;

    for (i = 0; i < u32Count; i++)
    {
        /* Slave Receive Data, And Send ACK */

        /* Wait Until RxFIFO Not Empty */
        while (!I2C_IsRxNotEmpty(I2Cx)) { }

        /* Read RxFIFO, Read Data */
        pu8ReadBuffer[i] = I2C_ReadByte(I2Cx);
    }
}




/******************************************************************************
 * @brief      I2C Master Mode Receive Data function
 *
 * @param[in]  I2Cx         :  Select the I2C module
 * @param[in]  eAddrMode    :  Address mode
 *                             See I2C_AddrModeEnum for details
 *                              - \ref I2C_ADDR_7BIT
 *                              - \ref I2C_ADDR_10BIT
 * @param[in]  u16TargetAddr:  Target Slave address
 * @param[in]  pu8ReadBuffer:  Pointer to the buffer that stored the received data
 * @param[in]  u32Count     :  Number of data to be sent or received
 *
 * @return     SUCCESS or ERROR
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_MasterRead(I2C_REGS *I2Cx, I2C_AddrModeEnum eAddrMode,
                    uint16_t u16TargetAddr, uint8_t *pu8ReadBuffer, uint32_t u32Count)
{
    uint32_t i;
    uint64_t u64TimeOut;

    /* Set Address Mode */
    I2Cx->I2CMASTERADDR.bit.MASTERADDR10B = eAddrMode;

    /* Set Target Slave Address*/
    I2Cx->I2CMASTERADDR.bit.TARADDR = u16TargetAddr;

    for (i = 0; i < u32Count; i++)
    {
        /* Write TxFIFO, Send Read Comamnd */
        I2C_MasterReadCmd(I2Cx);

        /* Wait Slave Send Data If Master Get ACK,
         * Then Master Receive One Data,
         * Send NACK and Stop Bus Because of TxFIFO Empty;
         */

        /* Wait Until RxFIFO Not Empty */
        /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
           bps = 8bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms.
           Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
           In total, approximately 21 * 16 = 336 ms. In 1 ms, CPU executes 200,000 instructions. Thus, in 336 ms, 
           a total of 67,200,000 instructions are executed.  */
        for (u64TimeOut = 67200000UL; (u64TimeOut > 0U) && (!I2C_IsRxNotEmpty(I2Cx)); u64TimeOut--)
        {
            /* Do Not Get ACK, Master Abort Send Data, Flush TxFIFO, Send Stop Signal */
            if (I2C_GetTxAbortIntRawFlag(I2Cx))
            {
                /* Return error when tx abort*/
                return ERROR;
            }
        }

        /* Read RxFIFO, Read Data */
        pu8ReadBuffer[i] = I2C_ReadByte(I2Cx);

        if (u64TimeOut == 0)
        {
            return ERROR;
        }

        /* Wait I2C Bus Idle */
        /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
           bps = 8bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms.
           Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. In total, approximately 21 * 16 = 336 ms. 
           In an extreme scenario, with a total of 1023 master on the i2c bus, the waiting time would be 336 * 1023 = 343,728 ms.
           In 1 ms, CPU executes 200,000 instructions. Thus, in 343,728 ms, a total of 68,745,600,000 instructions are executed.  */
        for (u64TimeOut = 68745600000; u64TimeOut > 0U; u64TimeOut--)
        {
            if (!I2C_IsActivity(I2Cx))
            {
                break;
            }
        }

        /* I2C Bus Wait Timeout */
        if (u64TimeOut == 0)
        {
            return ERROR;
        }
    }
    return SUCCESS;
}




/******************************************************************************
 * @brief      I2C Slave Mode Send Data function
 *
 * @param[in]  I2Cx          :  Select the I2C module
 * @param[in]  pu8WriteBuffer:  Pointer to the buffer that stored the data to be sent
 * @param[in]  u32Count      :  Number of data to be sent or received
 *
 * @return     SUCCESS or ERROR
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_SlaveWrite(I2C_REGS *I2Cx, uint8_t *pu8WriteBuffer, uint32_t u32Count)
{
    uint32_t i;
    volatile uint32_t u32TimeOut = 0;

    for (i = 0; i < u32Count; i++)
    {
        /* Slave Send ACK If Master Request Address Matched
        */

        /* Wait Until Detect Read Request */
        while (!I2C_GetReadRequestIntRawFlag(I2Cx)) { }

        /* Clear Event Flag */
        I2C_ClearInt(I2Cx, I2C_INT_RD_REQ);

        /* Write TxFIFO, Send Data */
        I2C_WriteByte(I2Cx, pu8WriteBuffer[i]);

        /* Wait Master Send ACK/NACK
         */

        /* Wait Until Master Receiver Done, Slave Get NACK */
        /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
           The Slave waits for the Master's NACK (1 bit), leaving a residual time of 4 bits.
           bps = 4 bit * 10^9ns / 50Mhz * (65536 * 2) = 10.48576 ms, approximately 10.5 ms. In 1 ms, 
           CPU executes 200,000 instructions. Thus, in 10.5 ms, a total of 2,100,000 instructions are executed. */
        for (u32TimeOut = 2100000UL; u32TimeOut > 0UL; u32TimeOut--)
        {
            if (I2C_GetRxDoneIntRawFlag(I2Cx))
            {
                break;
            }
        }
        if (u32TimeOut == 0)
        {
            return ERROR;
        }

        /* Clear Event Flag */
        I2C_ClearInt(I2Cx, I2C_INT_RX_DONE);
    }

    return SUCCESS;
}




/******************************************************************************
 * @brief      I2C Master Mode Bulk Send Data function
 *
 * @param[in]  I2Cx          :  Select the I2C module
 * @param[in]  eAddrMode     :  Address mode
 *                              See I2C_AddrModeEnum for details
 *                               - \ref I2C_ADDR_7BIT
 *                               - \ref I2C_ADDR_10BIT
 * @param[in]  u16TargetAddr :  Target Slave address
 * @param[in]  pu8WriteBuffer:  Pointer to the buffer that stored the data to be sent
 * @param[in]  u32Count      :  Number of data to be sent or received
 *
 * @return     SUCCESS or ERROR
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_MasterBulkWrite(I2C_REGS *I2Cx, I2C_AddrModeEnum eAddrMode,
                         uint16_t u16TargetAddr, uint8_t *pu8WriteBuffer, uint32_t u32Count)
{
    uint32_t i;
    uint64_t u64TimeOut;

    /* Set Address Mode */
    I2Cx->I2CMASTERADDR.bit.MASTERADDR10B = eAddrMode;

    /* Set Target Slave Address*/
    I2Cx->I2CMASTERADDR.bit.TARADDR = u16TargetAddr;

    /* TxFIFO Can Not Empty During Bulk Transmit */
    for (i = 0; i < u32Count; i++)
    {
        /* Wait Until TxFIFO not Full */
        /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536. 
           bps = 8bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms. In 1 ms, 
           CPU executes 200,000 instructions. Thus, in 21ms, a total of 4,200,000 instructions are executed. */
        for (u64TimeOut = 4200000UL; (u64TimeOut > 0U) && (!I2C_IsTxNotFull(I2Cx)); u64TimeOut--)
        {
            /* Do Not Get ACK, Master Abort Send Data, Flush TxFIFO, Send Stop Signal */
            if (I2C_GetTxAbortIntRawFlag(I2Cx))
            {
                /* Return error when tx abort*/
                return ERROR;
            }
        }

        if (u64TimeOut == 0)
        {
            return ERROR;
        }

        /* Write TxFIFO, Send Data If Master Get ACK */
        I2C_WriteByte(I2Cx, pu8WriteBuffer[i]);
    }

    /* Wait Slave Receive Data And Send ACK Again,
       * Until Master Stop Bus Because of TxFIFO Empty
       */

    /* Wait Until TxFIFO Empty */
    /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
           bps = 8bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms.
           Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
           In total, approximately 21 * 16 = 336 ms. In 1 ms, CPU executes 200,000 instructions. Thus, in 336 ms, 
           a total of 67,200,000 instructions are executed. */
    for (u64TimeOut = 67200000UL; u64TimeOut > 0U; u64TimeOut--)
    {
        if (I2C_IsTxEmpty(I2Cx))
        {
            break;
        }
    }

    if(u64TimeOut == 0)
    {
        return ERROR;
    }

    /* Wait I2C Bus Idle */
    /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
       bps = 8bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms.
       Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth.
       In total, approximately 21 * 16 = 336 ms. In an extreme scenario, with a total of 1023 master on the i2c bus, 
       the waiting time would be 336 * 1023 = 343,728 ms. In 1 ms, CPU executes 200,000 instructions.
       Thus, in 343,728 ms, a total of 68,745,600,000 instructions are executed. */
    for (u64TimeOut = 68745600000; u64TimeOut > 0U; u64TimeOut--)
    {
        if (!I2C_IsActivity(I2Cx))
        {
            break;
        }
    }

    /* I2C Bus Wait Timeout*/
    if (u64TimeOut == 0)
    {
        return ERROR;
    }

    /* Do Not Get ACK, Master Abort Send Data, Flush TxFIFO, Send Stop Signal */
    if (I2C_GetTxAbortIntRawFlag(I2Cx))
    {
        /* Return error when tx abort*/
        return ERROR;
    }
    return SUCCESS;
}




/******************************************************************************
 * @brief      I2C Slave Mode Bulk Receive Data function
 *
 * @param[in]  I2Cx         :  Select the I2C module
 * @param[in]  pu8ReadBuffer:  Pointer to the buffer that stored the received data
 * @param[in]  u32Count     :  Number of data to be sent or received
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void I2C_SlaveBulkRead(I2C_REGS *I2Cx, uint8_t *pu8ReadBuffer, uint32_t u32Count)
{
    uint32_t i;

    for (i = 0; i < u32Count; i++)
    {
        /* Slave Receive Data, And Send ACK
         */

        /* Wait Until RxFIFO Not Empty */
        while (!I2C_IsRxNotEmpty(I2Cx)) { }

        /* Read RxFIFO, Read Data */
        pu8ReadBuffer[i] = I2C_ReadByte(I2Cx);
    }
}




/******************************************************************************
 * @brief      I2C Master Mode Bulk Receive Data function
 *
 * @param[in]  I2Cx         :  Select the I2C module
 * @param[in]  eAddrMode    :  Address mode
 *                             See I2C_AddrModeEnum for details
 *                              - \ref I2C_ADDR_7BIT
 *                              - \ref I2C_ADDR_10BIT
 * @param[in]  u16TargetAddr:  Target Slave address
 * @param[in]  pu8ReadBuffer:  Pointer to the buffer that stored the received data
 * @param[in]  u32Count     :  Number of data to be sent or received
 *
 * @return     SUCCESS or ERROR
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_MasterBulkRead(I2C_REGS *I2Cx, I2C_AddrModeEnum eAddrMode,
                        uint16_t u16TargetAddr, uint8_t *pu8ReadBuffer, uint32_t u32Count)
{
    uint32_t u32RxCnt = 0;
    uint32_t u32TxCnt = 0;
    uint64_t u64TxTimeOut = 0;
    uint64_t u64RxTimeOut = 0;

    /* Set Address Mode */
    I2Cx->I2CMASTERADDR.bit.MASTERADDR10B = eAddrMode;

    /* Set Target Slave Address*/
    I2Cx->I2CMASTERADDR.bit.TARADDR = u16TargetAddr;

    /* Master Send Address, Wait Slave Send Data If Master Get ACK;
     * Then Master Receive Datas and Send ACK;
     * Send NACK and Stop Bus When TxFIFO Empty;
     */

    /* TxFIFO Can Not Empty During Bulk Transmit */
    /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
       bps = 8bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms.
       Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
       In total, approximately 21 * 16 = 336 ms. In 1 ms, CPU executes 200,000 instructions. Thus, in 336 ms, 
       a total of 67,200,000 instructions are executed. */
    u64TxTimeOut = 67200000UL;
    u64RxTimeOut = 67200000UL;
    while (u32TxCnt < u32Count)
    {
        /* TxFIFO not Full */
        if ((--u64TxTimeOut > 0U) && (I2C_IsTxNotFull(I2Cx)))
        {
            /* Write TxFIFO, Send Read Comamnd */
            I2C_MasterReadCmd(I2Cx);
            u32TxCnt++;
            u64TxTimeOut = 67200000UL;
        }
        if (u64TxTimeOut == 0)
        {
            return ERROR;
        }

        /* RxFIFO Not Empty */
        if ((--u64RxTimeOut > 0U) && (I2C_IsRxNotEmpty(I2Cx)))
        {
            /* Read RxFIFO, Read Data */
            *pu8ReadBuffer++ = I2C_ReadByte(I2Cx);
            u32RxCnt++;
            u64RxTimeOut = 67200000UL;
        }
        if (u64RxTimeOut == 0)
        {
            return ERROR;
        }

        /* Do Not Get ACK, Master Abort Send Data, Flush TxFIFO, Send Stop Signal */
        if (I2C_GetTxAbortIntRawFlag(I2Cx))
        {
            /* Return error when tx abort*/
            return  ERROR;
        }
    }

    /* Read the Rest of Data */
    while (u32RxCnt < u32Count)
    {
        /* RxFIFO Not Empty */
        if (I2C_IsRxNotEmpty(I2Cx))
        {
            /* Read RxFIFO, Read Data */
            *pu8ReadBuffer++ = I2C_ReadByte(I2Cx);
            u32RxCnt++;
        }
    }

    /* Wait Until TxFIFO Empty */
    /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
       bps = 8bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms.
       Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth. 
       In total, approximately 21 * 16 = 336 ms. In 1 ms, CPU executes 200,000 instructions. Thus, in 336 ms, 
       a total of 67,200,000 instructions are executed. */
    for (u64TxTimeOut = 67200000UL; u64TxTimeOut > 0U; u64TxTimeOut--)
    {
        if(I2C_IsTxEmpty(I2Cx))
        {
            break;
        }
    }

    if(u64TxTimeOut == 0)
    {
        return ERROR;
    }

    /* Wait I2C Bus Idle */
    /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
           bps = 8bit * 10^9ns / 50Mhz * (65536 * 2) = 20.97152 ms, approximately 21 ms.
           Taking FIFO usage into consideration, the timeout period should be multiplied by the FIFO depth.
           In total, approximately 21 * 16 = 336 ms. In an extreme scenario, with a total of 1023 master on the i2c bus, 
           the waiting time would be 336 * 1023 = 343,728 ms. In 1 ms, CPU executes 200,000 instructions.
           Thus, in 343,728 ms, a total of 68,745,600,000 instructions are executed. */
    for (u64TxTimeOut = 68745600000; u64TxTimeOut > 0U; u64TxTimeOut--)
    {
        if(!I2C_IsActivity(I2Cx))
        {
            break;
        }
    }

    /* I2C Bus Wait Timeout*/
    if(u64TxTimeOut == 0)
    {
        return ERROR;
    }

    return SUCCESS; 
}




/******************************************************************************
 * @brief      I2C Slave Mode Bulk Send Data function
 *
 * @param[in]  I2Cx          :  Select the I2C module
 * @param[in]  pu8WriteBuffer:  Pointer to the buffer that stored the data to be sent
 * @param[in]  u32Count      :  Number of data to be sent or received
 *
 * @return     SUCCESS or ERROR
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
ErrorStatus I2C_SlaveBulkWrite(I2C_REGS *I2Cx, uint8_t *pu8WriteBuffer, uint32_t u32Count)
{
    uint32_t i = 0;
    volatile uint32_t u32TimeOut = 0;

    /* Slave Send ACK If Master Request Address Matched
     */

    /* Wait Until Detect Read Request */
    while (!I2C_GetReadRequestIntRawFlag(I2Cx)) { }

    /* Clear Event Flag */
    I2C_ClearInt(I2Cx, I2C_INT_RD_REQ);

    while (i < u32Count)
    {
        /* I2C Bus Idle */
        if (!I2C_IsActivity(I2Cx))
        {
            return ERROR;
        }

        /* TxFIFO not Full */
        if (I2C_IsTxNotFull(I2Cx))
        {
            /* Write TxFIFO, Send Data */
            I2C_WriteByte(I2Cx, pu8WriteBuffer[i]);
            i++;
        }
    }

    /* Wait Until Master Receiver Done, Slave Get NACK */
    /* When CPU is 200MHz and I2C is 50MHz, The maximum value of I2CSSHCNT and I2CSSLCNT is 65536.
           The Slave waits for the Master's NACK (1 bit), leaving a residual time of 4 bits.
           bps = 4 bit * 10^9ns / 50Mhz * (65536 * 2) = 10.48576 ms, approximately 10.5 ms. In 1 ms, 
           CPU executes 200,000 instructions. Thus, in 10.5 ms, a total of 2,100,000 instructions are executed. */

    for (u32TimeOut = 2100000UL; u32TimeOut > 0UL; u32TimeOut--)
    {
        if (I2C_GetRxDoneIntRawFlag(I2Cx))
        {
            break;
        }
    }
    if (u32TimeOut == 0)
    {
        return ERROR;
    }
    /* Clear Event Flag */
    I2C_ClearInt(I2Cx, I2C_INT_RX_DONE);

    /* Clear Event Flag */
    I2C_ClearInt(I2Cx, I2C_INT_RD_REQ);

    return SUCCESS;
}


#if defined(__CC_ARM)
    #pragma pop
#endif


/******************* Copyright (C) 2022 Spintrol Electronic Technology (Shanghai) Co., Ltd. ***** END OF FILE ****/
