/*==================================================================================================
*   Project              : RTD AUTOSAR 4.4
*   Platform             : CORTEXM
*   Peripheral           : LPI2C
*   Dependencies         : none
*
*   Autosar Version      : 4.4.0
*   Autosar Revision     : ASR_REL_4_4_REV_0000
*   Autosar Conf.Variant :
*   SW Version           : 0.9.0
*   Build Version        : S32K3_RTD_0_9_0__ASR_REL_4_4_REV_0000_20210326
*
*   (c) Copyright 2020 - 2021 NXP Semiconductors
*   All Rights Reserved.
*
*   NXP Confidential. This software is owned or controlled by NXP and may only be
*   used strictly in accordance with the applicable license terms. By expressly
*   accepting such terms or by downloading, installing, activating and/or otherwise
*   using the software, you are agreeing that you have read, and that you agree to
*   comply with and are bound by, such license terms. If you do not agree to be
*   bound by the applicable license terms, then you may not retain, install,
*   activate or otherwise use the software.
==================================================================================================*/

/**
*     @file
*
*     @addtogroup LPI2C_DRIVER Lpi2c Driver
*     @{
*/

#ifdef __cplusplus
extern "C"{
#endif

 /*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "Lpi2c_Ip_HwAccess.h"
#include "Lpi2c_Ip_Features.h"
#include "Osif.h"
#include "Lpi2c_Ip.h"

#if (STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
    #include "Dma_Ip.h"
#endif /* (STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE) */

#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    #include "Devassert.h"
#endif /* (STD_ON == LPI2C_IP_DEV_ERROR_DETECT) */

/*==================================================================================================
*                              SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#define LPI2C_IP_VENDOR_ID_C                      43
#define LPI2C_IP_AR_RELEASE_MAJOR_VERSION_C       4
#define LPI2C_IP_AR_RELEASE_MINOR_VERSION_C       4
#define LPI2C_IP_AR_RELEASE_REVISION_VERSION_C    0
#define LPI2C_IP_SW_MAJOR_VERSION_C               0
#define LPI2C_IP_SW_MINOR_VERSION_C               9
#define LPI2C_IP_SW_PATCH_VERSION_C               0

/*==================================================================================================
*                                     FILE VERSION CHECKS
==================================================================================================*/
/* Checks against Lpi2c_Ip.h */
#if (LPI2C_IP_VENDOR_ID_C !=  LPI2C_IP_VENDOR_ID)
    #error "Lpi2c_Ip.c and Lpi2c_Ip.h have different vendor ids"
#endif
#if (( LPI2C_IP_AR_RELEASE_MAJOR_VERSION_C    !=  LPI2C_IP_AR_RELEASE_MAJOR_VERSION) || \
     ( LPI2C_IP_AR_RELEASE_MINOR_VERSION_C    !=  LPI2C_IP_AR_RELEASE_MINOR_VERSION) || \
     ( LPI2C_IP_AR_RELEASE_REVISION_VERSION_C !=  LPI2C_IP_AR_RELEASE_REVISION_VERSION))
     #error "AUTOSAR Version Numbers of Lpi2c_Ip.c and Lpi2c_Ip.h are different"
#endif
#if (( LPI2C_IP_SW_MAJOR_VERSION_C !=  LPI2C_IP_SW_MAJOR_VERSION) || \
     ( LPI2C_IP_SW_MINOR_VERSION_C !=  LPI2C_IP_SW_MINOR_VERSION) || \
     ( LPI2C_IP_SW_PATCH_VERSION_C !=  LPI2C_IP_SW_PATCH_VERSION))
    #error "Software Version Numbers of Lpi2c_Ip.c and Lpi2c_Ip.h are different"
#endif

/* Checks against Lpi2c_Ip_HwAccess.h */
#if (LPI2C_IP_VENDOR_ID_C !=  LPI2C_IP_HWACCESS_VENDOR_ID)
    #error "Lpi2c_Ip.c and Lpi2c_Ip_HwAccess.h have different vendor ids"
#endif
#if (( LPI2C_IP_AR_RELEASE_MAJOR_VERSION_C    !=  LPI2C_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION) || \
     ( LPI2C_IP_AR_RELEASE_MINOR_VERSION_C    !=  LPI2C_IP_HWACCESS_AR_RELEASE_MINOR_VERSION) || \
     ( LPI2C_IP_AR_RELEASE_REVISION_VERSION_C !=  LPI2C_IP_HWACCESS_AR_RELEASE_REVISION_VERSION))
     #error "AUTOSAR Version Numbers of Lpi2c_Ip.c and Lpi2c_Ip_HwAccess.h are different"
#endif
#if (( LPI2C_IP_SW_MAJOR_VERSION_C !=  LPI2C_IP_HWACCESS_SW_MAJOR_VERSION) || \
     ( LPI2C_IP_SW_MINOR_VERSION_C !=  LPI2C_IP_HWACCESS_SW_MINOR_VERSION) || \
     ( LPI2C_IP_SW_PATCH_VERSION_C !=  LPI2C_IP_HWACCESS_SW_PATCH_VERSION))
    #error "Software Version Numbers of LPI2C_Ip.c and Lpi2c_Ip_HwAccess.h are different"
#endif

/* Checks against Lpi2c_Ip_Features.h */
#if (LPI2C_IP_VENDOR_ID_C !=  LPI2C_IP_FEATURES_VENDOR_ID)
    #error "Lpi2c_Ip.c and Lpi2c_Ip_Features.h have different vendor ids"
#endif
#if (( LPI2C_IP_AR_RELEASE_MAJOR_VERSION_C    !=  LPI2C_IP_FEATURES_AR_RELEASE_MAJOR_VERSION) || \
     ( LPI2C_IP_AR_RELEASE_MINOR_VERSION_C    !=  LPI2C_IP_FEATURES_AR_RELEASE_MINOR_VERSION) || \
     ( LPI2C_IP_AR_RELEASE_REVISION_VERSION_C !=  LPI2C_IP_FEATURES_AR_RELEASE_REVISION_VERSION))
     #error "AUTOSAR Version Numbers of Lpi2c_Ip.c and Lpi2c_Ip_Features.h are different"
#endif
#if (( LPI2C_IP_SW_MAJOR_VERSION_C !=  LPI2C_IP_FEATURES_SW_MAJOR_VERSION) || \
     ( LPI2C_IP_SW_MINOR_VERSION_C !=  LPI2C_IP_FEATURES_SW_MINOR_VERSION) || \
     ( LPI2C_IP_SW_PATCH_VERSION_C !=  LPI2C_IP_FEATURES_SW_PATCH_VERSION))
    #error "Software Version Numbers of LPI2C_Ip.c and Lpi2c_Ip_Features.h are different"
#endif

#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
    /* Checks against Mcal.h */
    #if ((LPI2C_IP_AR_RELEASE_MAJOR_VERSION_C != MCAL_AR_RELEASE_MAJOR_VERSION) || \
         (LPI2C_IP_AR_RELEASE_MINOR_VERSION_C != MCAL_AR_RELEASE_MINOR_VERSION))
        #error "AUTOSAR Version Numbers of Lpi2c_Ip.h and Mcal.h are different"
    #endif
#endif

/*******************************************************************************
 * Variables
 ******************************************************************************/

/** @cond DRIVER_INTERNAL_USE_ONLY */

/* Constraints used for baud rate computation */
#define CLKHI_MIN_VALUE 1U
#define CLKLO_MIN_VALUE 3U
#define CLKHI_MAX_VALUE ((1U << LPI2C_MCCR0_CLKHI_WIDTH) - 1U)
#define CLKLO_MAX_VALUE CLKHI_MAX_VALUE
#define DATAVD_MIN_VALUE 1U
#define SETHOLD_MIN_VALUE 2U

/* DMA definitions */
#define I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_MASTER  (10U)
#define I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_SLAVE   (9U)

#define I2C_START_SEC_CONST_UNSPECIFIED
#include "I2c_MemMap.h"

/* Table of base addresses for LPI2C instances. */
static LPI2C_Type * const g_lpi2cBase[LPI2C_INSTANCE_COUNT] = LPI2C_BASE_PTRS;

#define I2C_STOP_SEC_CONST_UNSPECIFIED
#include "I2c_MemMap.h"

#if(LPI2C_IP_NUMBER_OF_MASTER_INSTANCES != 0U)
    
#define I2C_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

Lpi2c_Ip_MasterStateType Lpi2c_Ip_MasterState[LPI2C_IP_NUMBER_OF_MASTER_INSTANCES];

#define I2C_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

#endif

#if(LPI2C_IP_NUMBER_OF_SLAVE_INSTANCES != 0U)
    
#define I2C_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

Lpi2c_Ip_SlaveStateType Lpi2c_Ip_SlaveState[LPI2C_IP_NUMBER_OF_SLAVE_INSTANCES];

#define I2C_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

#endif

#define I2C_START_SEC_VAR_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

/* Pointer to runtime state structure.*/
static Lpi2c_Ip_MasterStateType* g_lpi2cMasterStatePtr[LPI2C_INSTANCE_COUNT] = {NULL_PTR,NULL_PTR};
static Lpi2c_Ip_SlaveStateType* g_lpi2cSlaveStatePtr[LPI2C_INSTANCE_COUNT] = {NULL_PTR,NULL_PTR};

#define I2C_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

#define I2C_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

#if (STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
/* Structures for configuration the master DMA channel */
static Dma_Ip_LogicChannelTransferListType dmaChannelTransferListReceive[I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_MASTER];
static Dma_Ip_LogicChannelTransferListType dmaChannelTransferListSend[I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_MASTER];

/* Structures for configuration the master DMA channel */
static Dma_Ip_LogicChannelTransferListType dmaSlaveChTransferListReceive[I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_SLAVE];
static Dma_Ip_LogicChannelTransferListType dmaSlaveChTransferListSend[I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_SLAVE];
#endif /* LPI2C_IP_DMA_FEATURE_AVAILABLE */

#define I2C_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
/* Callback for master DMA transfer done.*/
static void Lpi2c_Ip_MasterCompleteDMATransfer(uint32 u32Instance);
#endif

/** @brief Direction of a LPI2C transfer - transmit or receive. */
typedef enum
{
   LPI2C_TX_REQ = 0,    /**< The driver will perform an I2C transmit transfer */
   LPI2C_RX_REQ = 1,    /**< The driver will perform an I2C receive transfer */
} Lpi2c_Ip_TransferDirectionType;

#define I2C_START_SEC_CODE
#include "I2c_MemMap.h"
/*******************************************************************************
 * API
 ******************************************************************************/

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterCmdQueueEmpty
 * Description   : checks if there are any commands in the master software queue
 *
 *END**************************************************************************/
static inline boolean Lpi2c_Ip_MasterCmdQueueEmpty(const Lpi2c_Ip_MasterStateType * master)
{
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    return (master->cmdQueue.writeIdx == master->cmdQueue.readIdx);
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterResetQueue
 * Description   : resets the master software queue
 *
 *END**************************************************************************/
static inline void Lpi2c_Ip_MasterResetQueue(Lpi2c_Ip_MasterStateType * master)
{
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    master->cmdQueue.readIdx = 0U;
    master->cmdQueue.writeIdx = 0U;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterQueueCmd
 * Description   : queues a command in the hardware FIFO or in the master software queue
 *
 *END**************************************************************************/
static inline void Lpi2c_Ip_MasterQueueCmd(LPI2C_Type *baseAddr,
                                            Lpi2c_Ip_MasterStateType * master,
                                            Lpi2c_Ip_MasterCommandType cmd,
                                            uint8 data)
{
    uint16 txFIFOCount;
    uint16 txFIFOSize;

#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
    DevAssert(baseAddr != NULL_PTR);
#endif

    txFIFOCount = LPI2C_Get_MasterTxFIFOCount(baseAddr);
    txFIFOSize = LPI2C_Get_MasterTxFIFOSize(baseAddr);

    /* Check if there is room in the hardware FIFO */
    if (txFIFOCount < txFIFOSize)
    {
        LPI2C_Cmd_MasterTransmit(baseAddr, cmd, data);
    }
    else
    {
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
        /* Hardware FIFO full, use software FIFO */
        DevAssert(master->cmdQueue.writeIdx < LPI2C_MASTER_CMD_QUEUE_SIZE);
#endif
        master->cmdQueue.cmd[master->cmdQueue.writeIdx] = cmd;
        master->cmdQueue.data[master->cmdQueue.writeIdx] = data;
        master->cmdQueue.writeIdx++;
    }
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterSendQueuedCmd
 * Description   : transfers commands from the master software queue to the hardware FIFO
 *
 *END**************************************************************************/
static inline void Lpi2c_Ip_MasterSendQueuedCmd(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType * master)
{
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
    DevAssert(baseAddr != NULL_PTR);
#endif
    uint16 txFIFOCount = LPI2C_Get_MasterTxFIFOCount(baseAddr);
    uint16 txFifoSize = LPI2C_Get_MasterTxFIFOSize(baseAddr);

    while ((!Lpi2c_Ip_MasterCmdQueueEmpty(master)) && (txFIFOCount < txFifoSize))
    {
        LPI2C_Cmd_MasterTransmit(baseAddr,
                                    master->cmdQueue.cmd[master->cmdQueue.readIdx],
                                    master->cmdQueue.data[master->cmdQueue.readIdx]);
        master->cmdQueue.readIdx++;

        txFIFOCount = LPI2C_Get_MasterTxFIFOCount(baseAddr);
    }

    if (Lpi2c_Ip_MasterCmdQueueEmpty(master))
    {
        /* Reset queue */
        Lpi2c_Ip_MasterResetQueue(master);
    }
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterSendAddress
 * Description   : send start event and slave address
 *                 parameter receive specifies the direction of the transfer
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterSendAddress(LPI2C_Type *baseAddr,
                                        Lpi2c_Ip_MasterStateType * master,
                                        boolean receive)
{
    uint8 addrByte;
    Lpi2c_Ip_MasterCommandType startCommand;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
    DevAssert(baseAddr != NULL_PTR);
#endif

    if ((master->operatingMode == LPI2C_HIGHSPEED_MODE) && (master->highSpeedInProgress == FALSE))
    {
        /* Initiating High-speed mode - send master code first */
        Lpi2c_Ip_MasterQueueCmd(baseAddr, master, LPI2C_MASTER_COMMAND_START_NACK, master->masterCode);
        master->highSpeedInProgress = TRUE;
    }

    if (master->highSpeedInProgress == TRUE)
    {
        /* Use high-speed settings after start event in High Speed mode */
        startCommand = LPI2C_MASTER_COMMAND_START_HS;
    }
    else
    {
        /* Normal START command */
        startCommand = LPI2C_MASTER_COMMAND_START;
    }

    if (master->is10bitAddr)
    {
        /* 10-bit addressing */
        /* First address byte: 1111 0XXD, where XX are bits 10 and 9 of address, and D = 0(transmit) */
        addrByte = (uint8)(0xF0U + ((master->slaveAddress >> 7U) & 0x6U) + (uint8)0U);
        Lpi2c_Ip_MasterQueueCmd(baseAddr, master, startCommand, addrByte);
        /* Second address byte: Remaining 8 bits of address */
        addrByte = (uint8)(master->slaveAddress & 0xFFU);
        Lpi2c_Ip_MasterQueueCmd(baseAddr, master, LPI2C_MASTER_COMMAND_TRANSMIT, addrByte);
        if (receive == TRUE)
        {
            /* Receiving from 10-bit slave - must send repeated start and resend first address byte */
            /* First address byte: 1111 0XXD, where XX are bits 10 and 9 of address, and D = 1 (receive) */
            addrByte = (uint8)(0xF0U + ((master->slaveAddress >> 7U) & 0x6U) + (uint8)1U);
            Lpi2c_Ip_MasterQueueCmd(baseAddr, master, startCommand, addrByte);
        }
    }
    else
    {
        /* 7-bit addressing */
        /* Address byte: slave 7-bit address + D = 0(transmit) or 1 (receive) */
        addrByte = (uint8)((master->slaveAddress << 1U) + (uint8)receive);
        Lpi2c_Ip_MasterQueueCmd(baseAddr, master, startCommand, addrByte);
    }
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterQueueData
 * Description   : queues transmit data in the LPI2C tx fifo until it is full
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterQueueData(LPI2C_Type *baseAddr,
                                      Lpi2c_Ip_MasterStateType * master)
{

#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
    DevAssert(baseAddr != NULL_PTR);
#endif

    uint16 txFIFOCount = LPI2C_Get_MasterTxFIFOCount(baseAddr);
    uint16 txFifoSize = LPI2C_Get_MasterTxFIFOSize(baseAddr);

    /* Don't queue any data if there are commands in the software queue */
    if (Lpi2c_Ip_MasterCmdQueueEmpty(master))
    {
        while ((master->bufferSize > 0U) && (txFIFOCount < txFifoSize))
        {
            LPI2C_Cmd_MasterTransmit(baseAddr, LPI2C_MASTER_COMMAND_TRANSMIT, master->dataBuffer[0U]);
            master->dataBuffer++;
            master->bufferSize--;

            txFIFOCount = LPI2C_Get_MasterTxFIFOCount(baseAddr);
        }
    }
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterEndTransfer
 * Description   : ends current transmission or reception
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterEndTransfer(LPI2C_Type *baseAddr,
                                        Lpi2c_Ip_MasterStateType * master,
                                        boolean sendStop,
                                        boolean resetFIFO)
{
#if(STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
    DevAssert(baseAddr != NULL_PTR);
#endif

    /* Disable all events */
    LPI2C_Set_MasterInt(baseAddr, LPI2C_MASTER_FIFO_ERROR_INT |
                                     LPI2C_MASTER_ARBITRATION_LOST_INT |
                                     LPI2C_MASTER_NACK_DETECT_INT |
                                     LPI2C_MASTER_TRANSMIT_DATA_INT |
                                     LPI2C_MASTER_PIN_LOW_TIMEOUT_INT |
                                     LPI2C_MASTER_RECEIVE_DATA_INT,
                           FALSE);

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
    if (master->transferType == LPI2C_USING_DMA)
    {       
        /* Disable LPI2C DMA request. */
        if (LPI2C_IP_RECEIVE == master->direction)
        {
            (void)LPI2C_Set_MasterRxDMA(baseAddr, FALSE);
        }
        else
        {
            (void)LPI2C_Set_MasterTxDMA(baseAddr, FALSE);
        }
    }
#endif

    if (resetFIFO == TRUE)
    {
        /* Reset FIFOs if requested */
        LPI2C_Reset_MasterTxFIFOCmd(baseAddr);
        LPI2C_Reset_MasterRxFIFOCmd(baseAddr);
    }

    /* Queue STOP command if requested */
    if (sendStop == TRUE)
    {
        LPI2C_Cmd_MasterTransmit(baseAddr, LPI2C_MASTER_COMMAND_STOP, 0U);

        master->highSpeedInProgress = FALSE; /* High-speed transfers end at STOP condition */

    }

    master->dataBuffer = NULL_PTR;
    master->bufferSize = 0U;
    master->i2cIdle = TRUE;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterSetOperatingMode
 * Description   : sets the operating mode of the I2C master
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterSetOperatingMode(uint32 instance, Lpi2c_Ip_ModeType operatingMode)
{
    LPI2C_Type *baseAddr;
    Lpi2c_Ip_MasterStateType * master;

    baseAddr = g_lpi2cBase[instance];
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif

#if(LPI2C_HAS_ULTRA_FAST_MODE)
    if (operatingMode == LPI2C_ULTRAFAST_MODE)
    {
        LPI2C_Set_MasterPinConfig(baseAddr, LPI2C_CFG_2PIN_OUTPUT_ONLY);
        LPI2C_Set_MasterNACKConfig(baseAddr, LPI2C_NACK_IGNORE);
    }
    else
#endif
    {
        LPI2C_Set_MasterPinConfig(baseAddr, LPI2C_CFG_2PIN_OPEN_DRAIN);
        LPI2C_Set_MasterNACKConfig(baseAddr, LPI2C_NACK_RECEIVE);
    }

    master->operatingMode = operatingMode;
}

#if(LPI2C_HAS_ULTRA_FAST_MODE)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveConfigureUltraFastMode
 * Description   : configures slave in ultra fast mode
 *
 *END**************************************************************************/	
static void Lpi2c_Ip_SlaveConfigureUltraFastMode(LPI2C_Type *baseAddr)
{
	/* ignore NACK received */
	LPI2C_Set_SlaveIgnoreNACK(baseAddr, LPI2C_SLAVE_NACK_CONTINUE_TRANSFER);
    /* Transmit NACK */
	LPI2C_Set_SlaveTransmitNACK(baseAddr, LPI2C_SLAVE_TRANSMIT_NACK);
    /* Disable all clock stretching in ultra-fast mode */
    LPI2C_Set_SlaveACKStall(baseAddr, FALSE);
    LPI2C_Set_SlaveTXDStall(baseAddr, FALSE);
    LPI2C_Set_SlaveRXStall(baseAddr, FALSE);
    LPI2C_Set_SlaveAddrStall(baseAddr, FALSE);
}
#endif

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveConfigureNormalMode
 * Description   : configures slave for normal operations
 *
 *END**************************************************************************/	
static void Lpi2c_Ip_SlaveConfigureNormalMode(LPI2C_Type *baseAddr)
{
	/* End transfer when NACK is received */
    LPI2C_Set_SlaveIgnoreNACK(baseAddr, LPI2C_SLAVE_NACK_END_TRANSFER);
    /* Transmit ACK */
	LPI2C_Set_SlaveTransmitNACK(baseAddr, LPI2C_SLAVE_TRANSMIT_ACK);
    /* Enable clock stretching except ACKSTALL (we don't need to send ACK/NACK manually) */
    LPI2C_Set_SlaveACKStall(baseAddr, FALSE);
    LPI2C_Set_SlaveTXDStall(baseAddr, TRUE);
    LPI2C_Set_SlaveRXStall(baseAddr, TRUE);
    LPI2C_Set_SlaveAddrStall(baseAddr, TRUE);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveSetOperatingMode
 * Description   : sets the operating mode of the I2C slave
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveSetOperatingMode(uint32 instance, Lpi2c_Ip_ModeType operatingMode)
{
    LPI2C_Type *baseAddr;
    Lpi2c_Ip_SlaveStateType * slave;
    boolean bHighSpeedMode = FALSE; 
    baseAddr = g_lpi2cBase[instance];
    slave = g_lpi2cSlaveStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(slave != NULL_PTR);
#endif

#if(LPI2C_HAS_ULTRA_FAST_MODE)
    if (operatingMode == LPI2C_ULTRAFAST_MODE)
    {
        Lpi2c_Ip_SlaveConfigureUltraFastMode(baseAddr);
    }
    else
#endif
    {
        Lpi2c_Ip_SlaveConfigureNormalMode(baseAddr);
    }

    if (operatingMode == LPI2C_HIGHSPEED_MODE)
    {
		/* Enable detection of high speed mode */
		bHighSpeedMode = TRUE;
    }

	 /* Enable/disable detection of the High-speed Mode master code */
	LPI2C_Set_SlaveHighSpeedModeDetect(baseAddr, bHighSpeedMode);
	
    slave->operatingMode = operatingMode;
}

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterCompleteDMATransfer
 * Description   : Finish up a transfer DMA for master. The main purpose of
 *                 this function is to create a function compatible with DMA
 *                 callback type
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterCompleteDMATransfer(uint32 u32Instance)
{
    LPI2C_Type *baseAddr;
    Lpi2c_Ip_MasterStateType *master;

    baseAddr = g_lpi2cBase[u32Instance];
    master = g_lpi2cMasterStatePtr[u32Instance];

    
    if((master->bufferSize > 0U) && (LPI2C_IP_SEND == master->direction))
    {
        master->bufferSize = 0U;

        LPI2C_Set_MasterTxFIFOWatermark(baseAddr, 0U);

        /* Disable transmit data DMA requests */
        (void)LPI2C_Set_MasterTxDMA(baseAddr, FALSE);

        /* Activate transmit data events */
        LPI2C_Set_MasterInt(baseAddr, (uint32)LPI2C_MASTER_TRANSMIT_DATA_INT, TRUE);
    } 
    else
    {
        /* Signal transfer end for blocking transfers */
        Lpi2c_Ip_MasterEndTransfer(baseAddr, master, master->sendStop, FALSE);

        master->status = STATUS_LPI2C_IP_SUCCESS;    

        if (master->masterCallback != NULL_PTR)
        {
            master->masterCallback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
        }
    }
}
#endif

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterConfigureTxDmaChannel
 * Description   : configures the Tx dma channel 
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterConfigureTxDmaChannel(uint32 instance)
{
	LPI2C_Type *baseAddr = g_lpi2cBase[instance];
    const Lpi2c_Ip_MasterStateType *master = g_lpi2cMasterStatePtr[instance];
	
	 /* Configure watermarks for transmit DMA for master */
    uint32 txBytes = LPI2C_Get_MasterTxFIFOSize(baseAddr);

    if (txBytes > master->bufferSize)
    {
        txBytes = master->bufferSize;
    }
    LPI2C_Set_MasterTxFIFOWatermark(baseAddr, (uint16)(txBytes - 1U));

    /* Set source address and major loop transfer size */
    dmaChannelTransferListSend[0u].Value = (uint32)(&(master->dataBuffer[0]));
    dmaChannelTransferListSend[3u].Value = (uint32)(&(baseAddr->MTDR));
    dmaChannelTransferListSend[7u].Value = master->bufferSize;

    (void)Dma_Ip_SetLogicChannelTransferList(master->dmaTxChannel, dmaChannelTransferListSend, I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_MASTER);
    /* Start DMA channel */
    (void)Dma_Ip_SetLogicChannelCommand(master->dmaTxChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
}	
#endif

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterConfigureRxDmaChannel
 * Description   : configures the Rx dma channel 
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterConfigureRxDmaChannel(uint32 instance)
{
	LPI2C_Type *baseAddr = g_lpi2cBase[instance];
    const Lpi2c_Ip_MasterStateType *master = g_lpi2cMasterStatePtr[instance];
	
	/* Configure watermarks for receive DMA for master */
    LPI2C_Set_MasterRxFIFOWatermark(baseAddr, 0U);
	
    /* Set destination address and major loop transfer size */
    dmaChannelTransferListReceive[0u].Value = (uint32) (&(baseAddr->MRDR));
    dmaChannelTransferListReceive[3u].Value = (uint32)(&(master->dataBuffer[0]));
    dmaChannelTransferListReceive[7u].Value = master->bufferSize;

    (void)Dma_Ip_SetLogicChannelTransferList(master->dmaRxChannel, dmaChannelTransferListReceive, I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_MASTER);
    /* Start DMA channel */
    (void)Dma_Ip_SetLogicChannelCommand(master->dmaRxChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
}
#endif

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterStartDmaTransfer
 * Description   : starts the DMA transfer for master
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterStartDmaTransfer(uint32 instance)
{
    LPI2C_Type *baseAddr = g_lpi2cBase[instance];
    Lpi2c_Ip_MasterStateType *master = g_lpi2cMasterStatePtr[instance];
    boolean receive = FALSE;

    if (LPI2C_IP_SEND == master->direction)
    {
		/* Configure dma TX channel */
        Lpi2c_Ip_MasterConfigureTxDmaChannel(instance);
    }
    else
    {
        receive = TRUE;
        
		/* Configure dma RX channel */
		Lpi2c_Ip_MasterConfigureRxDmaChannel(instance);
    }

	/* Send address */
    Lpi2c_Ip_MasterSendAddress(baseAddr, master, receive);

    /* Enable transmit/receive DMA requests */
    if (LPI2C_IP_SEND == master->direction)
    {
        (void)LPI2C_Set_MasterTxDMA(baseAddr, TRUE);
    }
    else
    {
        Lpi2c_Ip_MasterQueueCmd(baseAddr, master, LPI2C_MASTER_COMMAND_RECEIVE, (uint8)(master->bufferSize - 1U));
        (void)LPI2C_Set_MasterRxDMA(baseAddr, TRUE);
    }
}
#endif

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveStartDmaTransfer
 * Description   : starts the DMA transfer for slave
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveStartDmaTransfer(uint32 instance)
{
    LPI2C_Type *baseAddr = g_lpi2cBase[instance];
    const Lpi2c_Ip_SlaveStateType *slave = g_lpi2cSlaveStatePtr[instance];

    if(LPI2C_IP_SEND == slave->direction)
    {
        /* Set source address and major loop transfer size */
        dmaSlaveChTransferListSend[0u].Value = (uint32)(&(slave->dataBuffer[0]));
        dmaSlaveChTransferListSend[3u].Value = (uint32)(&(baseAddr->STDR));
        dmaSlaveChTransferListSend[7u].Value = slave->bufferSize;
        dmaSlaveChTransferListSend[8u].Value = slave->bufferSize;

        (void)Dma_Ip_SetLogicChannelTransferList(slave->dmaTxChannel, dmaSlaveChTransferListSend, I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_SLAVE);
        /* Start DMA channel */
        (void)Dma_Ip_SetLogicChannelCommand(slave->dmaTxChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
    }
    else
    {
        /* Set destination address and major loop transfer size */
        dmaSlaveChTransferListReceive[0u].Value = (uint32) (&(baseAddr->SRDR));
        dmaSlaveChTransferListReceive[3u].Value = (uint32)(&(slave->dataBuffer[0]));
        dmaSlaveChTransferListReceive[7u].Value = slave->bufferSize;
        dmaSlaveChTransferListReceive[8u].Value = 0U;

        (void)Dma_Ip_SetLogicChannelTransferList(slave->dmaRxChannel, dmaSlaveChTransferListReceive, I2C_DMA_CHANNEL_CONFIG_LIST_SIZE_SLAVE);
        /* Start DMA channel */
        (void)Dma_Ip_SetLogicChannelCommand(slave->dmaRxChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
    }

    /* Enable transmit/receive DMA requests */
    if(LPI2C_IP_SEND == slave->direction)
    {
        (void)LPI2C_Set_SlaveTxDMA(baseAddr, TRUE);
    }
    else
    {
        (void)LPI2C_Set_SlaveRxDMA(baseAddr, TRUE);
    }
}
#endif

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterHandleTransmitDataRequest
 * Description   : handle a transmit request for master
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterHandleTransmitDataRequest(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType *master)
{
    /* More data needed for transmission */
    if (!Lpi2c_Ip_MasterCmdQueueEmpty(master))
    {
        /* If there are queued commands, send them */
        Lpi2c_Ip_MasterSendQueuedCmd(baseAddr, master);
    }
    else if ((master->dataBuffer != NULL_PTR) && (master->direction == LPI2C_IP_SEND))
    {
        /* A transmission is in progress */
        if (master->bufferSize == 0U)
        {
            /* There is no more data in buffer, the transmission is over */
            Lpi2c_Ip_MasterEndTransfer(baseAddr, master, master->sendStop, FALSE);

            master->status = STATUS_LPI2C_IP_SUCCESS;

            if (master->masterCallback != NULL_PTR)
            {
                master->masterCallback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
            }
        }
        else
        {
            /* Queue data bytes to fill tx fifo */
            Lpi2c_Ip_MasterQueueData(baseAddr, master);
        }
    }
    else
    {
        /* No more commands and no transmission in progress - disable tx event */
        LPI2C_Set_MasterInt(baseAddr, (uint32)LPI2C_MASTER_TRANSMIT_DATA_INT, FALSE);
    }
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterHandleReceiveDataRequest
 * Description   : handle a receive request for master
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterHandleReceiveDataReadyEvent(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType *master)
{
    /* Received data ready */
#if(STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master->dataBuffer != NULL_PTR);
#endif

    /* Transfer received data to user buffer */
    while ((LPI2C_Get_MasterRxFIFOCount(baseAddr) > 0U) && (master->bufferSize > 0U))
    {
        master->dataBuffer[0U] = LPI2C_Get_MasterRxData(baseAddr);
        master->dataBuffer++;
        master->bufferSize--;
    }

    if (master->bufferSize == 0U)
    {
        /* Done receiving */
        Lpi2c_Ip_MasterEndTransfer(baseAddr, master, master->sendStop, FALSE);

        master->status = STATUS_LPI2C_IP_SUCCESS;

        if (master->masterCallback != NULL_PTR)
        {
            master->masterCallback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
        }
    }
    else if (master->bufferSize <= LPI2C_Get_MasterRxFIFOWatermark(baseAddr))
    {
        /* Reduce rx watermark to receive the last few bytes */
        LPI2C_Set_MasterRxFIFOWatermark(baseAddr, (uint16)(master->bufferSize - 1U));
    }
    else
    {
        /* Continue reception */
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveHandleAddressValidEvent
 * Description   : handle an address valid event for slave
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveHandleAddressValidEvent(uint32 instance, const LPI2C_Type *baseAddr, Lpi2c_Ip_SlaveStateType *slave)
{
    uint16 receivedAddr;

    receivedAddr = LPI2C_Get_SlaveReceivedAddr(baseAddr);
    if ((receivedAddr & 1U) != (uint16)0U)
    {
        /* Request from master to transmit data */
        slave->direction = LPI2C_IP_SEND;

        if (slave->slaveCallback != NULL_PTR)
        {
            slave->slaveCallback(I2C_SLAVE_EVENT_TX_REQ, slave->callbackParam);
        }

#if defined(ERRATA_E10792)
        if (slave->transferType == LPI2C_USING_INTERRUPTS) {
            /* Enable interrupt for transmitting data */
            LPI2C_Set_SlaveInt(g_lpi2cBase[instance], (uint32)LPI2C_SLAVE_TRANSMIT_DATA_INT, TRUE);
        }
#endif

        slave->txUnderrunWarning = FALSE;

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
        if (slave->transferType == LPI2C_USING_DMA)
        {
            (void)Lpi2c_Ip_SlaveStartDmaTransfer(instance);
        }
#endif
    }
    else
    {
        /* Request from master to receive data */
        slave->direction = LPI2C_IP_RECEIVE;

        if (slave->slaveCallback != NULL_PTR)
        {
            slave->slaveCallback(I2C_SLAVE_EVENT_RX_REQ, slave->callbackParam);
        }
#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
        if (slave->transferType == LPI2C_USING_DMA)
        {
            (void)Lpi2c_Ip_SlaveStartDmaTransfer(instance);
        }
#endif
    }
    
    (void) instance;
    slave->status = STATUS_LPI2C_IP_BUSY;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveHandleTransmitDataEvent
 * Description   : handle a transmit data event for slave
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveHandleTransmitDataEvent(LPI2C_Type *baseAddr, Lpi2c_Ip_SlaveStateType *slave)
{
    if (slave->txUnderrunWarning == TRUE)
    {
        /* Another Tx event after underflow warning means the dummy char was sent */
        slave->status = STATUS_LPI2C_IP_TX_UNDERRUN;

#if (STD_ON == LPI2C_IP_EVENT_ERROR_DETECT)
        if (slave->slaveCallback != NULL_PTR)
        {
            slave->slaveCallback(I2C_SLAVE_EVENT_UNDERRUN, slave->callbackParam);
        }
#endif
    }

    if(slave->bufferSize == 0U)
    {
        /* Out of data, call callback to allow user to provide a new buffer */
        if (slave->slaveCallback != NULL_PTR)
        {
            slave->slaveCallback(I2C_SLAVE_EVENT_TX_EMPTY, slave->callbackParam);
        }
    }

    if (slave->bufferSize == 0U)
    {
        /*
         * Still no data, record tx underflow event and send dummy char.
         * Special case after the last tx byte: the device will ask for more data
         * but the dummy char will not be sent if NACK and then STOP condition are
         * received from master. So only record a "warning" for now.
         */
        slave->txUnderrunWarning = TRUE;
        LPI2C_Transmit_SlaveData(baseAddr, (uint8)0xFFU);
    }
    else
    {
        LPI2C_Transmit_SlaveData(baseAddr, slave->dataBuffer[0U]);
        slave->dataBuffer++;
        slave->bufferSize--;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveHandleReceiveDataEvent
 * Description   : handle a receive data event for slave
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveHandleReceiveDataEvent(const LPI2C_Type *baseAddr, Lpi2c_Ip_SlaveStateType *slave)
{
    if (slave->bufferSize == 0U)
    {
        /* No more room for data, call callback to allow user to provide a new buffer */
        if (slave->slaveCallback != NULL_PTR)
        {
            slave->slaveCallback(I2C_SLAVE_EVENT_RX_FULL, slave->callbackParam);
        }
    }

    if (slave->bufferSize == 0U)
    {
        /* Still no room for data, record rx overrun event and dummy read data */
        slave->status = STATUS_LPI2C_IP_RX_OVERRUN;
        (void)LPI2C_Get_SlaveData(baseAddr);

#if (STD_ON == LPI2C_IP_EVENT_ERROR_DETECT)
        if (slave->slaveCallback != NULL_PTR)
        {
            slave->slaveCallback(I2C_SLAVE_EVENT_OVERRUN, slave->callbackParam);
        }
#endif
    }
    else
    {
        slave->dataBuffer[0U] = LPI2C_Get_SlaveData(baseAddr);
        slave->dataBuffer++;
        slave->bufferSize--;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : LPI2C_Get_MasterFIFOErrorEventHandler
 * Description   : handles master fifo error
 *
 *END**************************************************************************/
static void LPI2C_Get_MasterFIFOErrorEventHandler(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType * master)
{
    /* FIFO error */
    LPI2C_Clear_MasterFIFOErrorEvent(baseAddr);
    
    if(master->operatingMode == LPI2C_HIGHSPEED_MODE)
    {
        /* High-speed transfers end at STOP condition */
        master->highSpeedInProgress = FALSE;
    }
    
    master->status = STATUS_LPI2C_IP_ERROR;
    
    /* End transfer: no stop generation (the module will handle that by itself
       if needed), reset FIFOs */
    Lpi2c_Ip_MasterEndTransfer(baseAddr, master, FALSE, TRUE);
    
    if (master->masterCallback != NULL_PTR)
    {
#if (STD_ON == LPI2C_IP_EVENT_ERROR_DETECT)
        master->masterCallback(I2C_MASTER_EVENT_ERROR_FIFO, master->callbackParam);
#else
        master->masterCallback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
#endif
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : LPI2C_Get_MasterNACKDetectEventHandler
 * Description   : handles master NACK detection event
 *
 *END**************************************************************************/
static void LPI2C_Get_MasterNACKDetectEventHandler(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType * master)
{

#if(LPI2C_HAS_ULTRA_FAST_MODE)
    /* Ignore NACK in Ultra Fast mode */
    if (master->operatingMode != LPI2C_ULTRAFAST_MODE)
    {
#endif

        /* High-speed transfers end at STOP condition */
        master->highSpeedInProgress = FALSE;
        
        master->status = STATUS_LPI2C_IP_RECEIVED_NACK;
        
        /* End transfer: no stop generation (the module will handle that by itself
           if needed), reset FIFOs */
        Lpi2c_Ip_MasterEndTransfer(baseAddr, master, FALSE, TRUE);
        
        if (master->masterCallback != NULL_PTR)
        {
#if (STD_ON == LPI2C_IP_EVENT_ERROR_DETECT)
            master->masterCallback(I2C_MASTER_EVENT_NACK, master->callbackParam);
#else
            master->masterCallback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
#endif
        }

        /* Clear NACK flag */
        LPI2C_Clear_MasterNACKDetectEvent(baseAddr);
#if(LPI2C_HAS_ULTRA_FAST_MODE)
    }
#endif	
}

/*FUNCTION**********************************************************************
 *
 * Function Name : LPI2C_Get_MasterArbitrationLostEventHandler
 * Description   : handles master arbitration lost event
 *
 *END**************************************************************************/
static void LPI2C_Get_MasterArbitrationLostEventHandler(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType * master)
{
    /* Arbitration lost */
    LPI2C_Clear_MasterArbitrationLostEvent(baseAddr);
    
    /* End transfer: no stop generation (the module will handle that by itself
       if needed), reset FIFOs */
    Lpi2c_Ip_MasterEndTransfer(baseAddr, master, FALSE, TRUE);
    
    master->status = STATUS_LPI2C_IP_ARBITRATION_LOST;
    
    if (master->masterCallback != NULL_PTR)
    {
#if (STD_ON == LPI2C_IP_EVENT_ERROR_DETECT)
        master->masterCallback(I2C_MASTER_EVENT_ARBITRATION_LOST, master->callbackParam);
#else
        master->masterCallback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
#endif
    }	
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterCheckErrorEvents
 * Description   : checks error events for master module
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterCheckErrorEvents(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType * master)
{
    if (LPI2C_Get_MasterFIFOErrorEvent(baseAddr))
    {
		/* Handle FIFO error event */
        LPI2C_Get_MasterFIFOErrorEventHandler(baseAddr, master);
    }

    if (LPI2C_Get_MasterArbitrationLostEvent(baseAddr))
    {
		/* Handle arbitration lost event */
        LPI2C_Get_MasterArbitrationLostEventHandler(baseAddr, master);
    }

    if (LPI2C_Get_MasterNACKDetectEvent(baseAddr))
    {
        /* Handle Received NACK */
        LPI2C_Get_MasterNACKDetectEventHandler(baseAddr, master);
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterSend
 * Description   : sync send transfer handler
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterSend(uint32 instance)
{
    LPI2C_Type *baseAddr;
    Lpi2c_Ip_MasterStateType * master;
    boolean masterCmdQueueEmpty = FALSE;
    
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    baseAddr = g_lpi2cBase[instance];
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    /* Check which event caused the interrupt */
    if (LPI2C_Get_MasterTransmitDataRequestEvent(baseAddr))
    {
        /* More data needed for transmission */
        if (!Lpi2c_Ip_MasterCmdQueueEmpty(master))
        {
            /* If there are queued commands, send them */
            Lpi2c_Ip_MasterSendQueuedCmd(baseAddr, master);
        }
        else
        {
            masterCmdQueueEmpty = TRUE;
        }
    }
    
    if(masterCmdQueueEmpty)
    {
        if (master->dataBuffer != NULL_PTR)
        {
            /* A transmission is in progress */
            if (master->bufferSize == 0U)
            {
                /* There is no more data in buffer, the transmission is over */
                Lpi2c_Ip_MasterEndTransfer(baseAddr, master, master->sendStop, FALSE);

                master->status = STATUS_LPI2C_IP_SUCCESS;

                if (master->masterCallback != NULL_PTR)
                {
                    master->masterCallback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
                }
            }
            else
            {
                /* Queue data bytes to fill tx fifo */
                Lpi2c_Ip_MasterQueueData(baseAddr, master);
            }
        }
        else
        {
            /* else case */
        }
    }

	/* Check error event */
    Lpi2c_Ip_MasterCheckErrorEvents(baseAddr, master);
	
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterGetReceivedData
 * Description   : read data receive from RX FIFO
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterGetReceivedData(const LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType * master)
{
	/* Read data from RX FIFO */
    while ((LPI2C_Get_MasterRxFIFOCount(baseAddr) > 0U) && (master->bufferSize > 0U))
    {
        master->dataBuffer[0U] = LPI2C_Get_MasterRxData(baseAddr);
        master->dataBuffer++;
        master->bufferSize--;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterReceive
 * Description   : sync receive transfer handler
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterReceive(uint32 instance)
{
    LPI2C_Type *baseAddr;
    Lpi2c_Ip_MasterStateType * master;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    baseAddr = g_lpi2cBase[instance];
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    if ((LPI2C_Get_MasterReceiveDataReadyEvent(baseAddr)))
    {
        /* Read data from RX FIFO */
        Lpi2c_Ip_MasterGetReceivedData(baseAddr, master);

        if (master->bufferSize == 0U)
        {
            /* Done receiving */
            Lpi2c_Ip_MasterEndTransfer(baseAddr, master, master->sendStop, FALSE);

            master->status = STATUS_LPI2C_IP_SUCCESS;

            if (master->masterCallback != NULL_PTR)
            {
                master->masterCallback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
            }
        }
        else if (master->bufferSize <= LPI2C_Get_MasterRxFIFOWatermark(baseAddr))
        {
            LPI2C_Set_MasterRxFIFOWatermark(baseAddr, (uint16)(master->bufferSize - 1U));
        }
        else
        {
            /* Continue reception */
        }
    }

	/* Check error event */
    Lpi2c_Ip_MasterCheckErrorEvents(baseAddr, master);
	
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_BaudRateConfig
 * Description   : configures MCCR0 register
 *
 *END**************************************************************************/
static void Lpi2c_Ip_BaudRateConfig(LPI2C_Type *baseAddr, const Lpi2c_Ip_BaudRateType * baudRate)
{
	/* Set prescaler */
	LPI2C_Set_MasterPrescaler(baseAddr, baudRate->prescaler);
    /* Set hold delay */
	LPI2C_Set_MasterSetupHoldDelay(baseAddr, (uint8)baudRate->setHold);
    /* Set data valid delay */
	LPI2C_Set_MasterDataValidDelay(baseAddr, (uint8)baudRate->dataValid);
    /* Set clock HIGH period */
	LPI2C_Set_MasterClockHighPeriod(baseAddr, (uint8)baudRate->clkHI);
    /* Set clock low period */
	LPI2C_Set_MasterClockLowPeriod(baseAddr, (uint8)baudRate->clkLO);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_HSBaudRateConfig
 * Description   : configures MCCR1 register
 *
 *END**************************************************************************/
static void Lpi2c_Ip_HSBaudRateConfig(LPI2C_Type *baseAddr, const Lpi2c_Ip_BaudRateType * baudRate)
{
	 /* Set data valid delay */
    LPI2C_Set_MasterDataValidDelayHS(baseAddr, (uint8)baudRate->setHoldHS);
	/* Set hold delay */
    LPI2C_Set_MasterSetupHoldDelayHS(baseAddr, (uint8)baudRate->dataValidHS);
	/* Set clock HIGH period */
    LPI2C_Set_MasterClockHighPeriodHS(baseAddr, (uint8)baudRate->clkHIHS);
    /* Set clock low period */
	LPI2C_Set_MasterClockLowPeriodHS(baseAddr, (uint8)baudRate->clkLOHS);
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterSetBaudRate
 * Description   : set the baud rate for any subsequent I2C communication
 *
 * Implements : Lpi2c_Ip_MasterSetBaudRate_Activity
 *END**************************************************************************/
 Lpi2c_Ip_StatusType Lpi2c_Ip_MasterSetBaudRate(uint32 instance,
                                                Lpi2c_Ip_ModeType operatingMode,
                                                uint32 baudrate,
                                                uint32 inputClock)
{
    LPI2C_Type *baseAddr;
    const Lpi2c_Ip_MasterStateType * master;
	Lpi2c_Ip_BaudRateType baudRateParams;
    uint32 minPrescaler = 0U;
    uint32 prescaler;
    uint32 clkTotal;
    uint32 clkLo;
    uint32 clkHi;
    uint32 setHold;
    uint32 dataVd;
    Lpi2c_Ip_StatusType retStatus = STATUS_LPI2C_IP_BUSY;
    
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif

    baseAddr = g_lpi2cBase[instance];
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif

    /* Check if driver is busy */
    if(master->i2cIdle)
    {
        /* Disable master */
        LPI2C_Set_MasterEnable(baseAddr, FALSE);

        /* Ignoring the glitch filter, the baud rate formula is:
                SCL_freq = Input_freq / (2^PRESCALER * (CLKLO + CLKHI + 2))
                Assume CLKLO = CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2
        */
        if (baudrate != 0U)
        {
            /* Compute minimum prescaler for which CLKLO and CLKHI values are in valid range. Always round up. */
            minPrescaler = ((inputClock - 1U) / ((baudrate) * (CLKHI_MAX_VALUE + CLKLO_MAX_VALUE + 2U))) + (uint32)1U;
            for (prescaler = 0U; prescaler < 7U; prescaler++)
            {
                if (((uint32)1U << prescaler) >= minPrescaler)
                {
                    break;
                }
            }
            /* Compute CLKLO and CLKHI values for this prescaler. Round to nearest integer. */
            clkTotal = (inputClock + ((baudrate << prescaler) >> 1U)) / (baudrate << prescaler);
        }
        else
        {
            prescaler = 7U;
            clkTotal = (CLKHI_MAX_VALUE + CLKLO_MAX_VALUE + 2U);
        }

        if (clkTotal > (CLKHI_MAX_VALUE + CLKLO_MAX_VALUE + 2U))
        {
            clkTotal = (CLKHI_MAX_VALUE + CLKLO_MAX_VALUE + 2U);
        }

        /*
         * If we try to compute clk high and low values using clkTotal equal with 0
         * (this is the case when the baudrate is 0), we will get negative values for
         * them, so we set them to 0 for this case.
         */
        if (clkTotal <= 1U)
        {
            clkHi = 0U;
            clkLo = 0U;
        }
        else
        {
            clkHi = (clkTotal - 2U) / 2U;
            clkLo = clkTotal - 2U - clkHi;
        }

        if (clkHi < CLKHI_MIN_VALUE)
        {
            clkHi = CLKHI_MIN_VALUE;
        }
        if (clkLo < CLKLO_MIN_VALUE)
        {
            clkLo = CLKLO_MIN_VALUE;
        }

        /* Compute DATAVD and SETHOLD */
        setHold = clkHi;
        dataVd = clkHi >> 1U;
        if (setHold < SETHOLD_MIN_VALUE)
        {
            setHold = SETHOLD_MIN_VALUE;
        }
        if (dataVd < DATAVD_MIN_VALUE)
        {
            dataVd = DATAVD_MIN_VALUE;
        }

		/* Init baud rate params */
		baudRateParams.prescaler = (Lpi2c_Ip_MasterPrescalerType) prescaler;
		baudRateParams.dataValid = dataVd;
		baudRateParams.setHold = setHold;
		baudRateParams.clkHI = clkHi;
		baudRateParams.clkLO = clkLo;
		
        /* Apply settings */
        Lpi2c_Ip_BaudRateConfig(baseAddr, &baudRateParams);

        /* Perform other settings related to the chosen operating mode */
        Lpi2c_Ip_MasterSetOperatingMode(instance, operatingMode);

        /* Re-enable master */
        LPI2C_Set_MasterEnable(baseAddr, TRUE);
        retStatus = STATUS_LPI2C_IP_SUCCESS;
    }
    (void) minPrescaler;
    (void)master;

    return retStatus;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterSetBaudRateInit
 * Description   : set the baud rate for any subsequent I2C communication
 *
 * Implements : Lpi2c_Ip_MasterSetBaudRateInit_Activity
 *END**************************************************************************/
static Lpi2c_Ip_StatusType Lpi2c_Ip_MasterSetBaudRateInit(uint32 instance,
                                const Lpi2c_Ip_ModeType operatingMode,
                                const Lpi2c_Ip_BaudRateType * baudRate)
{

    LPI2C_Type *baseAddr;
    const Lpi2c_Ip_MasterStateType *master;
    Lpi2c_Ip_StatusType retStatus = STATUS_LPI2C_IP_BUSY;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    master = g_lpi2cMasterStatePtr[instance];
    baseAddr = g_lpi2cBase[instance];

    /* Check if driver is busy */
    if(master->i2cIdle)
    {
        /* Disable master */
        LPI2C_Set_MasterEnable(baseAddr, FALSE);

        /* Apply settings */
        Lpi2c_Ip_BaudRateConfig(baseAddr, baudRate);

        /* Apply High-speed settings */
        Lpi2c_Ip_HSBaudRateConfig(baseAddr, baudRate);
        
        /* Perform other settings related to the chosen operating mode */
        Lpi2c_Ip_MasterSetOperatingMode(instance, operatingMode);

        /* Re-enable master */
        LPI2C_Set_MasterEnable(baseAddr, TRUE);
        retStatus = STATUS_LPI2C_IP_SUCCESS;
    }

    return retStatus;
}

#if (STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
/*FUNCTION**********************************************************************
 *
 * Function Name : I2c_Ip_SlaveCmdDmaTcdInit
 * Description   : This function configures the TCD for I2C DMA transfers
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveCmdDmaTcdInit(void)
{
    /* Configure DMA channel for send transfers */
    /* Source  configuration parameters  */
    dmaSlaveChTransferListSend[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
    dmaSlaveChTransferListSend[1u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
    dmaSlaveChTransferListSend[2u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
    /* Destination configuration parameters */
    dmaSlaveChTransferListSend[3u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
    dmaSlaveChTransferListSend[4u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
    dmaSlaveChTransferListSend[5u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
    /* Minor/Major Loop parameters */
    dmaSlaveChTransferListSend[6u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
    dmaSlaveChTransferListSend[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
    /* Adjustment added to source address at the beginning of TX buffer */
    dmaSlaveChTransferListSend[8u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_LAST_ADDR_ADJ;

    /* Source  configuration values */
    dmaSlaveChTransferListSend[1u].Value = 1U;
    dmaSlaveChTransferListSend[2u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    /* Destination configuration values */
    dmaSlaveChTransferListSend[4u].Value = 0U;
    dmaSlaveChTransferListSend[5u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    /* Minor/Major Loop values */
    dmaSlaveChTransferListSend[6u].Value = 1U;

    /* Configure DMA channel for receive transfers*/
    /* Source  configuration parameters  */
    dmaSlaveChTransferListReceive[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
    dmaSlaveChTransferListReceive[1u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
    dmaSlaveChTransferListReceive[2u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
    /* Destination configuration parameters  */
    dmaSlaveChTransferListReceive[3u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
    dmaSlaveChTransferListReceive[4u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
    dmaSlaveChTransferListReceive[5u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
    /* Minor/Major Loop parameters */
    dmaSlaveChTransferListReceive[6u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
    dmaSlaveChTransferListReceive[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
    /* Adjustment added to source address at the beginning of TX buffer */
    dmaSlaveChTransferListReceive[8u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_LAST_ADDR_ADJ;

    /* Source  configuration values */
    dmaSlaveChTransferListReceive[1u].Value = 0U;
    dmaSlaveChTransferListReceive[2u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    /* Destination configuration values */
    dmaSlaveChTransferListReceive[4u].Value = 1U;
    dmaSlaveChTransferListReceive[5u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    /* Minor/Major Loop values */
    dmaSlaveChTransferListReceive[6u].Value = 1U;
}
#endif /* STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE */


#if (STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
/*FUNCTION**********************************************************************
 *
 * Function Name : I2c_Ip_CmdDmaTcdInit
 * Description   : This function configures the TCD for I2C DMA transfers
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterCmdDmaTcdInit(void)
{
    /* Configure DMA channel for send transfers */
    /* Source  configuration parameters  */
    dmaChannelTransferListSend[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
    dmaChannelTransferListSend[1u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
    dmaChannelTransferListSend[2u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
    /* Destination configuration parameters */
    dmaChannelTransferListSend[3u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
    dmaChannelTransferListSend[4u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
    dmaChannelTransferListSend[5u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
    /* Minor/Major Loop parameters */
    dmaChannelTransferListSend[6u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
    dmaChannelTransferListSend[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
    /* Disable Hw auto request and enable interrupts */
    dmaChannelTransferListSend[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
    dmaChannelTransferListSend[9u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;

    /* Source  configuration values */
    dmaChannelTransferListSend[1u].Value = 1U;
    dmaChannelTransferListSend[2u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    /* Destination configuration values */
    dmaChannelTransferListSend[4u].Value = 0U;
    dmaChannelTransferListSend[5u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    /* Minor/Major Loop values */
    dmaChannelTransferListSend[6u].Value = 1U;
    /* Disable Hw auto request and enable interrupts */
    dmaChannelTransferListSend[8u].Value = 1U;
    dmaChannelTransferListSend[9u].Value = 1U;

    /* Configure DMA channel for receive transfers*/
    /* Source  configuration parameters  */
    dmaChannelTransferListReceive[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
    dmaChannelTransferListReceive[1u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
    dmaChannelTransferListReceive[2u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
    /* Destination configuration parameters  */
    dmaChannelTransferListReceive[3u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
    dmaChannelTransferListReceive[4u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
    dmaChannelTransferListReceive[5u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
    /* Minor/Major Loop parameters */
    dmaChannelTransferListReceive[6u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
    dmaChannelTransferListReceive[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
    /* Disable Hw auto request and enable interrupts */
    dmaChannelTransferListReceive[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
    dmaChannelTransferListReceive[9u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;

    /* Source  configuration values */
    dmaChannelTransferListReceive[1u].Value = 0U;
    dmaChannelTransferListReceive[2u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    /* Destination configuration values */
    dmaChannelTransferListReceive[4u].Value = 1U;
    dmaChannelTransferListReceive[5u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
    /* Minor/Major Loop values */
    dmaChannelTransferListReceive[6u].Value = 1U;
    /* Disable Hw auto request and enable interrupts */
    dmaChannelTransferListReceive[8u].Value = 1U;
    dmaChannelTransferListReceive[9u].Value = 1U;
}
#endif /* STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE */

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterInitModule
 * Description   : resets software queue and resets master FIFOs
 *END**************************************************************************/
static void Lpi2c_Ip_MasterInitModule(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType * master)
{
    /* Reset software queue */
    Lpi2c_Ip_MasterResetQueue(master);

    /* Initialize module */
    LPI2C_Init(baseAddr);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterConfigFeatures
 * Description   : configures glitch filter for SDA and SCL, bus idle and pin low timeout
 *END**************************************************************************/
static void Lpi2c_Ip_MasterConfigFeatures(LPI2C_Type *baseAddr, const Lpi2c_Ip_MasterConfigType * userConfigPtr)
{
	/* Set glitch filters for SDA and SCL */
    LPI2C_Set_MasterGlitchFilterSDA(baseAddr, userConfigPtr->u32GlitchFilterSDA);
    LPI2C_Set_MasterGlitchFilterSCL(baseAddr, userConfigPtr->u32GlitchFilterSCL);	
	
	/* Set bus idle timeout */
	LPI2C_Set_MasterBusIdleTimeout(baseAddr, userConfigPtr->u32BusIdleTimeout);
	
    /* Configure pin low timeout for both SDA and SCL */
    LPI2C_Set_MasterPinLowTimeoutConfiguration(baseAddr, TRUE);
    
    /* Configure Pin Low Timeout  */
    LPI2C_Set_MasterPinLowTimeout(baseAddr, userConfigPtr->u32PinLowTimeout);	
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterInit
 * Description   : initialize the I2C master mode driver
 *
 * Implements : Lpi2c_Ip_MasterInit_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_MasterInit(uint32 instance,
                                    const Lpi2c_Ip_MasterConfigType * userConfigPtr)
{
    LPI2C_Type *baseAddr;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(userConfigPtr != NULL_PTR);
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
    /* Check to see if the LPI2C master instance is already initialized */
    DevAssert(g_lpi2cMasterStatePtr[instance] == NULL_PTR);
#endif

    baseAddr = g_lpi2cBase[instance];
    g_lpi2cMasterStatePtr[instance] = userConfigPtr->masterState;
    Lpi2c_Ip_MasterStateType * master =  g_lpi2cMasterStatePtr[instance];

    /* Initialize driver status structure */
    master->direction = LPI2C_IP_SEND;
    master->dataBuffer = NULL_PTR;
    master->bufferSize = 0U;
    master->status = STATUS_LPI2C_IP_SUCCESS;
    master->i2cIdle = TRUE;
    master->slaveAddress = userConfigPtr->slaveAddress;
    master->is10bitAddr = userConfigPtr->is10bitAddr;
    master->transferType = userConfigPtr->transferType;
    /* Store DMA channel number used in transfer */
    master->dmaTxChannel = userConfigPtr->dmaTxChannel;
    master->dmaRxChannel = userConfigPtr->dmaRxChannel;
    master->masterCallback = userConfigPtr->masterCallback;
    master->callbackParam = userConfigPtr->callbackParam;
    master->masterCode = userConfigPtr->masterCode;
    master->highSpeedInProgress = FALSE;

    master->baudrateParams = userConfigPtr->baudrateParams;

	/* Init/enable master module */
    Lpi2c_Ip_MasterInitModule(baseAddr, master);

#if (STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
    if(master->transferType == LPI2C_USING_DMA)
    {
        Lpi2c_Ip_MasterCmdDmaTcdInit();
    }
#endif /* STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE */
    
    /* Configure glitch filter, bus idle and pin low timeout */
    Lpi2c_Ip_MasterConfigFeatures(baseAddr, userConfigPtr);

    /* Set baud rate */
    (void)Lpi2c_Ip_MasterSetBaudRateInit(instance, userConfigPtr->operatingMode, master->baudrateParams);

    /* Set slave address */
    Lpi2c_Ip_MasterSetSlaveAddr(instance, userConfigPtr->slaveAddress, userConfigPtr->is10bitAddr);
	
    
    /* Enable LPI2C master */
    LPI2C_Set_MasterEnable(baseAddr, TRUE);
	
    return STATUS_LPI2C_IP_SUCCESS;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterDeinit
 * Description   : deinitialize the I2C master mode driver
 *
 * Implements : Lpi2c_Ip_MasterDeinit_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_MasterDeinit(uint32 instance)
{
    LPI2C_Type *baseAddr;
    const Lpi2c_Ip_MasterStateType *master;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    baseAddr = g_lpi2cBase[instance];
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif

    g_lpi2cMasterStatePtr[instance] = NULL_PTR;

    /* Disable master */
    LPI2C_Set_MasterEnable(baseAddr, FALSE);

    (void) master;
    return STATUS_LPI2C_IP_SUCCESS;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterGetBaudRate
 * Description   : returns the currently configured baud rate
 *
 * Implements : Lpi2c_Ip_MasterGetBaudRate_Activity
 *END**************************************************************************/
void Lpi2c_Ip_MasterGetBaudRate(uint32 instance, uint32 inputClock, uint32 *baudRate)
{
    const LPI2C_Type *baseAddr;
    const Lpi2c_Ip_MasterStateType *master;
    uint32 prescaler;
    uint32 clkLo;
    uint32 clkHi;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    baseAddr = g_lpi2cBase[instance];
    master = g_lpi2cMasterStatePtr[instance];

    /* Ignoring the glitch filter, the baud rate formula is:
            SCL_freq = Input_freq / (2^PRESCALER * (CLKLO + CLKHI + 2))
    */
    prescaler = (uint32)LPI2C_Get_MasterPrescaler(baseAddr);
    clkHi = (uint32)LPI2C_Get_MasterClockHighPeriod(baseAddr);
    clkLo = (uint32)LPI2C_Get_MasterClockLowPeriod(baseAddr);

    *baudRate = inputClock / (((uint32)1U << prescaler) * (clkLo + clkHi + (uint32)2U));

    if (master->operatingMode == LPI2C_HIGHSPEED_MODE)
    {
        clkHi = LPI2C_Get_MasterClockHighPeriodHS(baseAddr);
        clkLo = LPI2C_Get_MasterClockLowPeriodHS(baseAddr);

        *baudRate = inputClock / (((uint32)1U << prescaler) * (clkLo + clkHi + (uint32)2U));
    }

}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterSetSlaveAddr
 * Description   : set the slave address for any subsequent I2C communication
 *
 * Implements : Lpi2c_Ip_MasterSetSlaveAddr_Activity
 *END**************************************************************************/
void Lpi2c_Ip_MasterSetSlaveAddr(uint32 instance, const uint16 address, const boolean is10bitAddr)
{
    Lpi2c_Ip_MasterStateType * master;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif

    master->slaveAddress = address;
    master->is10bitAddr = is10bitAddr;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterSendData
 * Description   : perform a non-blocking send transaction on the I2C bus
 *
 * Implements : Lpi2c_Ip_MasterSendData_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_MasterSendData(uint32 instance,
                                            uint8 * txBuff,
                                            uint32 txSize,
                                            boolean sendStop)
{
    LPI2C_Type *baseAddr;
    Lpi2c_Ip_MasterStateType *master;
    Lpi2c_Ip_StatusType retStatus = STATUS_LPI2C_IP_BUSY;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
    DevAssert(txBuff != NULL_PTR);
    DevAssert(txSize > 0U);
#endif

    baseAddr = g_lpi2cBase[instance];
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    /* Check if driver is busy */
    if(master->i2cIdle)
    {
        /* Copy parameters to driver state structure */
        master->bufferSize = txSize;
        master->dataBuffer = txBuff;
        master->direction = LPI2C_IP_SEND;
        master->sendStop = sendStop;
        master->i2cIdle = FALSE;
        master->status = STATUS_LPI2C_IP_BUSY;

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
        if (master->transferType == LPI2C_USING_DMA)
        {
            LPI2C_Set_MasterInt(baseAddr, LPI2C_MASTER_FIFO_ERROR_INT |
                                             LPI2C_MASTER_ARBITRATION_LOST_INT |
                                             LPI2C_MASTER_NACK_DETECT_INT,
                                   TRUE);

            Lpi2c_Ip_MasterStartDmaTransfer(instance);
        }
        else
        {
#endif
            /* Initiate communication */
            Lpi2c_Ip_MasterSendAddress(baseAddr, master, FALSE);

            /* Queue data bytes to fill tx fifo */
            Lpi2c_Ip_MasterQueueData(baseAddr, master);

            /* Set tx FIFO watermark */
            LPI2C_Set_MasterTxFIFOWatermark(baseAddr, 0U);

            /* Enable relevant events */
#if(LPI2C_HAS_ULTRA_FAST_MODE)
            if (master->operatingMode == LPI2C_ULTRA_FAST_MODE)
            {
                /* Do not enable NACK event reporting in ultra-fast mode */
                LPI2C_Set_MasterInt(baseAddr, LPI2C_MASTER_FIFO_ERROR_INT |
                                                 LPI2C_MASTER_ARBITRATION_LOST_INT |
                                                 LPI2C_MASTER_TRANSMIT_DATA_INT,
                                       TRUE);
            }
            else
#endif
            {
                LPI2C_Set_MasterInt(baseAddr, LPI2C_MASTER_FIFO_ERROR_INT |
                                                 LPI2C_MASTER_ARBITRATION_LOST_INT |
                                                 LPI2C_MASTER_NACK_DETECT_INT |
                                                 LPI2C_MASTER_PIN_LOW_TIMEOUT_INT |
                                                 LPI2C_MASTER_TRANSMIT_DATA_INT,
                                       TRUE);
            }
#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
        }
#endif
        retStatus = STATUS_LPI2C_IP_SUCCESS;
    }

    return retStatus;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterInitSendTransfer
 * Description   : initializes send transfer

 *END**************************************************************************/
static void Lpi2c_Ip_MasterInitSendTransfer(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType *master)
{
    /* Initiate communication */
    Lpi2c_Ip_MasterSendAddress(baseAddr, master, FALSE);
    
    /* Queue data bytes to fill tx fifo */
    Lpi2c_Ip_MasterQueueData(baseAddr, master);
    
    /* Set tx FIFO watermark */
    LPI2C_Set_MasterTxFIFOWatermark(baseAddr, 0U);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterSendDataBlocking
 * Description   : perform a blocking send transaction on the I2C bus
 *
 * Implements : Lpi2c_Ip_MasterSendDataBlocking_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_MasterSendDataBlocking(uint32 instance,
                                    uint8 * txBuff,
                                    uint32 txSize,
                                    boolean sendStop,
                                    uint32 timeout)
{
    uint32 CurrentTicks = 0u;
    uint32 ElapsedTicks = 0u;
    uint32 TimeoutTicks = OsIf_MicrosToTicks(timeout, I2C_TIMEOUT_TYPE);
    Lpi2c_Ip_StatusType retStatus = STATUS_LPI2C_IP_BUSY;
    
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
    DevAssert(txBuff != NULL_PTR);
    DevAssert(txSize > 0U);
#endif
    LPI2C_Type *baseAddr;
    baseAddr = g_lpi2cBase[instance];

    Lpi2c_Ip_MasterStateType *master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    /* Check if driver is busy */
    if(master->i2cIdle)
    {
        master->bufferSize = txSize;
        master->dataBuffer = txBuff;
        master->direction = LPI2C_IP_SEND;
        master->sendStop = sendStop;
        master->i2cIdle = FALSE;
        master->status = STATUS_LPI2C_IP_BUSY;

        /* Initiate send transfer */
		Lpi2c_Ip_MasterInitSendTransfer(baseAddr, master);
        
		/* Get current ticks */
        CurrentTicks = OsIf_GetCounter(I2C_TIMEOUT_TYPE);
        
        do
        {
            /* Master send data */
            Lpi2c_Ip_MasterSend(instance);
            ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, I2C_TIMEOUT_TYPE);

        }while((Lpi2c_Ip_MasterGetTransferStatus(instance, NULL_PTR) == STATUS_LPI2C_IP_BUSY) && (ElapsedTicks < TimeoutTicks));

		/* Check timeout */
        if(ElapsedTicks >= TimeoutTicks)
        {
            master->status = STATUS_LPI2C_IP_TIMEOUT;
        }
        retStatus = master->status;
    }
	
    return retStatus;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterInterruptReceiveInit
 * Description   : configures interrupt receive transfer
 *END**************************************************************************/
static void Lpi2c_Ip_MasterInterruptReceiveInit(uint32 instance, uint32 rxSize)
{
    LPI2C_Type *baseAddr = g_lpi2cBase[instance];
    Lpi2c_Ip_MasterStateType *master = g_lpi2cMasterStatePtr[instance];
    uint16 rxBytes;
	
	/* Send Address */
	Lpi2c_Ip_MasterSendAddress(baseAddr, master, TRUE);
    
	/* Queue receive command for rxSize bytes */
    Lpi2c_Ip_MasterQueueCmd(baseAddr, master, LPI2C_MASTER_COMMAND_RECEIVE, (uint8)(rxSize - 1U));

    /* Set rx FIFO watermark */
    rxBytes = LPI2C_Get_MasterRxFIFOSize(baseAddr);
    if (rxBytes > rxSize)
    {
        rxBytes = (uint8)rxSize;
    }

	/* Set RX watermark */
    LPI2C_Set_MasterRxFIFOWatermark(baseAddr, (uint16)(rxBytes - 1U));
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterReceiveData
 * Description   : perform a non-blocking receive transaction on the I2C bus
 *
 * Implements : Lpi2c_Ip_MasterReceiveData_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_MasterReceiveData(uint32  instance,
                                       uint8 * rxBuff,
                                       uint32 rxSize,
                                       boolean sendStop)
{
    LPI2C_Type *baseAddr;
    Lpi2c_Ip_MasterStateType * master;
    Lpi2c_Ip_StatusType retStatus = STATUS_LPI2C_IP_BUSY;

#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
    DevAssert(rxBuff != NULL_PTR);
    DevAssert(rxSize > 0U);
    DevAssert(rxSize <= 256U);
#endif

    baseAddr = g_lpi2cBase[instance];
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    /* Check if driver is busy */
    if(!master->i2cIdle)
    {
        retStatus = STATUS_LPI2C_IP_BUSY;
    }
    else
    {
    #if(LPI2C_HAS_ULTRA_FAST_MODE)
        if (master->operatingMode == LPI2C_ULTRAFAST_MODE)
        {
            /* No reception possible in ultra-fast mode */
            retStatus = STATUS_LPI2C_IP_ERROR;
        }
        else
        {
    #endif
            retStatus = STATUS_LPI2C_IP_SUCCESS;
            /* Copy parameters to driver state structure */
            master->bufferSize = rxSize;
            master->i2cIdle = FALSE;
            master->sendStop = sendStop;
            master->dataBuffer = rxBuff;
            master->direction = LPI2C_IP_RECEIVE;
            master->status = STATUS_LPI2C_IP_BUSY;

        #if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
            if (master->transferType == LPI2C_USING_DMA)
            {
                LPI2C_Set_MasterInt(baseAddr, LPI2C_MASTER_FIFO_ERROR_INT |
                                                 LPI2C_MASTER_ARBITRATION_LOST_INT |
                                                 LPI2C_MASTER_NACK_DETECT_INT,
                                       TRUE);

                Lpi2c_Ip_MasterStartDmaTransfer(instance);
            }
            else
            {
        #endif
                
				/* Init interrupt receive transfer */
				Lpi2c_Ip_MasterInterruptReceiveInit(instance, rxSize);

                /* Enable relevant events */
                if (!Lpi2c_Ip_MasterCmdQueueEmpty(master))
                {
                    /* Enable tx event too if there are commands in the software FIFO */
                    LPI2C_Set_MasterInt(baseAddr, LPI2C_MASTER_FIFO_ERROR_INT |
                                                     LPI2C_MASTER_ARBITRATION_LOST_INT |
                                                     LPI2C_MASTER_NACK_DETECT_INT |
                                                     LPI2C_MASTER_TRANSMIT_DATA_INT |
                                                     LPI2C_MASTER_RECEIVE_DATA_INT,
                                           TRUE);
                }
                else
                {
                    LPI2C_Set_MasterInt(baseAddr, LPI2C_MASTER_FIFO_ERROR_INT |
                                                     LPI2C_MASTER_ARBITRATION_LOST_INT |
                                                     LPI2C_MASTER_NACK_DETECT_INT |
                                                     LPI2C_MASTER_RECEIVE_DATA_INT,
                                           TRUE);
                }
        #if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
            }
        #endif
    #if(LPI2C_HAS_ULTRA_FAST_MODE)
        }
    #endif
    }
    
    return retStatus;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterReceiveDataBlocking
 * Description   : perform a blocking receive transaction on the I2C bus
 *
 * Implements : Lpi2c_Ip_MasterReceiveDataBlocking_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_MasterReceiveDataBlocking(uint32 instance,
                                           uint8 * rxBuff,
                                           uint32 rxSize,
                                           boolean sendStop,
                                           uint32 timeout)
{
    Lpi2c_Ip_MasterStateType * master;
    
    uint32 CurrentTicks = 0u;
    uint32 ElapsedTicks = 0u;
    uint32 TimeoutTicks = OsIf_MicrosToTicks(timeout, I2C_TIMEOUT_TYPE);
    Lpi2c_Ip_StatusType retStatus = STATUS_LPI2C_IP_BUSY;
    
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
    DevAssert(rxBuff != NULL_PTR);
    DevAssert(rxSize > 0U);
    DevAssert(rxSize <= 256U);
#endif
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif

    /* Check if driver is busy */
    if(master->i2cIdle)
    {
        master->bufferSize = rxSize;
        master->dataBuffer = rxBuff;
        master->direction = LPI2C_IP_RECEIVE;
        master->sendStop = sendStop;
        master->i2cIdle = FALSE;
        master->status = STATUS_LPI2C_IP_BUSY;

        /* Initiate communication */
        Lpi2c_Ip_MasterInterruptReceiveInit(instance, rxSize);
        
        CurrentTicks = OsIf_GetCounter(I2C_TIMEOUT_TYPE);
        
        do
        {
            /* Master send data */
            Lpi2c_Ip_MasterReceive(instance);
            ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, I2C_TIMEOUT_TYPE);

        }while((Lpi2c_Ip_MasterGetTransferStatus(instance, NULL_PTR) == STATUS_LPI2C_IP_BUSY) && (ElapsedTicks < TimeoutTicks));

        if(ElapsedTicks >= TimeoutTicks)
        {
            master->status = STATUS_LPI2C_IP_TIMEOUT;
        }
        retStatus = master->status;
    }
    
    return retStatus;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterGetTransferStatus
 * Description   : return the current status of the I2C master transfer
 *
 * When performing an a-sync (non-blocking) transfer, the user can call this function
 * to ascertain the state of the current transfer. In addition, if the transfer is still
 * in progress, the user can get the number of words that should be receive.
 *
 * Implements : Lpi2c_Ip_MasterGetTransferStatus_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_MasterGetTransferStatus(uint32 instance,
                                                uint32 *bytesRemaining)
{
    const Lpi2c_Ip_MasterStateType * master;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    if ((bytesRemaining != NULL_PTR) && (master->transferType == LPI2C_USING_INTERRUPTS))
    {
            *bytesRemaining = master->bufferSize;
    }

    return master->status;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterCheckDataTxRxEvent
 * Description   : checks if data send or data receive event occurred
 *
 *END**************************************************************************/
static void Lpi2c_Ip_MasterCheckDataTxRxEvent(LPI2C_Type *baseAddr, Lpi2c_Ip_MasterStateType * master)
{
	
    if (LPI2C_Get_MasterTransmitDataRequestEvent(baseAddr))
    {   /* Send data event */
        Lpi2c_Ip_MasterHandleTransmitDataRequest(baseAddr, master);
    }

    if ((LPI2C_Get_MasterReceiveDataReadyEvent(baseAddr)))
    {
		/* Receive data event */
        Lpi2c_Ip_MasterHandleReceiveDataReadyEvent(baseAddr, master);
    }	
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_MasterIRQHandler
 * Description   : handle non-blocking master operation when I2C interrupt occurs
 *
 *END**************************************************************************/
void Lpi2c_Ip_MasterIRQHandler(uint32 instance)
{
    LPI2C_Type *baseAddr;
    Lpi2c_Ip_MasterStateType * master;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    baseAddr = g_lpi2cBase[instance];
    master = g_lpi2cMasterStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    /* Check which event caused the interrupt */
    Lpi2c_Ip_MasterCheckDataTxRxEvent(baseAddr, master);

	/* Master check error events */
    Lpi2c_Ip_MasterCheckErrorEvents(baseAddr, master);

    /* Check Pin Timeout Flag */
    if(LPI2C_Get_MasterPinLowTimeoutEvent(baseAddr))
    {
        if (master->masterCallback != NULL_PTR)
        {
            master->masterCallback(I2C_MASTER_EVENT_PIN_LOW_TIMEOUT, master->callbackParam);
        }

        /* Clear pin low timeout flag */
        LPI2C_Clear_MasterPinLowTimeoutEvent(baseAddr);
    }
}

static void Lpi2c_Ip_SlaveActivateEvents(uint32 instance)
{
    LPI2C_Type *baseAddr;
    baseAddr = g_lpi2cBase[instance];
    const Lpi2c_Ip_SlaveStateType *slave = g_lpi2cSlaveStatePtr[instance];
    
    if (slave->transferType == LPI2C_USING_DMA)
    {
       /* Activate events */
       LPI2C_Set_SlaveInt(baseAddr, LPI2C_SLAVE_BIT_ERROR_INT |
                                    LPI2C_SLAVE_FIFO_ERROR_INT |
                                    LPI2C_SLAVE_STOP_DETECT_INT |
                                    LPI2C_SLAVE_REPEATED_START_INT |
                                    LPI2C_SLAVE_ADDRESS_VALID_INT,
                                    TRUE);
    }
    
    if (slave->transferType == LPI2C_USING_INTERRUPTS)
    {
           /* Activate events */
#if defined(ERRATA_E10792)
        LPI2C_Set_SlaveInt(baseAddr, LPI2C_SLAVE_BIT_ERROR_INT |
                                     LPI2C_SLAVE_FIFO_ERROR_INT |
                                     LPI2C_SLAVE_STOP_DETECT_INT |
                                     LPI2C_SLAVE_REPEATED_START_INT |
                                     LPI2C_SLAVE_ADDRESS_VALID_INT |
                                     LPI2C_SLAVE_RECEIVE_DATA_INT,
                                     TRUE);
        
#else       
        LPI2C_Set_SlaveInt(baseAddr, LPI2C_SLAVE_BIT_ERROR_INT |
                                     LPI2C_SLAVE_FIFO_ERROR_INT |
                                     LPI2C_SLAVE_STOP_DETECT_INT |
                                     LPI2C_SLAVE_REPEATED_START_INT |
                                     LPI2C_SLAVE_ADDRESS_VALID_INT |
                                     LPI2C_SLAVE_RECEIVE_DATA_INT |
                                     LPI2C_SLAVE_TRANSMIT_DATA_INT,
                                     TRUE);
        
#endif

    }
    
    /* Enable LPI2C slave */
    LPI2C_Set_SlaveEnable(baseAddr, TRUE);
    
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveConigureAddress
 * Description   : configures slave address 
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveConigureAddress(LPI2C_Type *baseAddr, uint16 slaveAddr, boolean is10bitAddr)
{
    LPI2C_Set_SlaveAddr0(baseAddr, slaveAddr);
	
    if (is10bitAddr)
    {
        LPI2C_Set_SlaveAddrConfig(baseAddr, LPI2C_SLAVE_ADDR_MATCH_0_10BIT);
    }
    else
    {
        LPI2C_Set_SlaveAddrConfig(baseAddr, LPI2C_SLAVE_ADDR_MATCH_0_7BIT);
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveConfigureGlitchFilter
 * Description   : configures slave glitch filter
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveConfigureGlitchFilter(LPI2C_Type *baseAddr, uint32 u32GlitchFilterSDA, uint32 u32GlitchFilterSCL)
{
	/* Set SDA glitch filter */
    LPI2C_Set_SlaveGlitchFilterSDA(baseAddr, u32GlitchFilterSDA);
    /* Set SCL glitch filter */
	LPI2C_Set_SlaveGlitchFilterSCL(baseAddr, u32GlitchFilterSCL);	
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveInit
 * Description   : initialize the I2C slave mode driver
 *
 * Implements : Lpi2c_Ip_SlaveInit_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_SlaveInit(uint32 instance,
                                   const Lpi2c_Ip_SlaveConfigType * userConfigPtr)
{
    LPI2C_Type *baseAddr;

#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(userConfigPtr != NULL_PTR);
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
    DevAssert(g_lpi2cSlaveStatePtr[instance] == NULL_PTR);
#endif

    baseAddr = g_lpi2cBase[instance];
    g_lpi2cSlaveStatePtr[instance] = userConfigPtr->slaveState;
    Lpi2c_Ip_SlaveStateType * slave = g_lpi2cSlaveStatePtr[instance];

    /* Initialize driver status structure */
    slave->status = STATUS_LPI2C_IP_SUCCESS;
    slave->slaveCallback = userConfigPtr->slaveCallback;
    slave->callbackParam = userConfigPtr->callbackParam;
    slave->dataBuffer = NULL_PTR;
    slave->bufferSize = 0U;
    slave->direction = LPI2C_IP_SEND;
    slave->transferType = userConfigPtr->transferType;
    /* Store DMA channel number used in transfer */
    slave->dmaTxChannel = userConfigPtr->dmaTxChannel;
    slave->dmaRxChannel = userConfigPtr->dmaRxChannel;
    slave->isTransferInProgress = FALSE;
    slave->is10bitAddress = userConfigPtr->is10bitAddr;
    slave->repeatedStarts = 0U;
    slave->slaveListening = userConfigPtr->slaveListening;

    /* Initialize module */
    LPI2C_Init(baseAddr);
    
#if (STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
    if(slave->transferType == LPI2C_USING_DMA)
    {
        Lpi2c_Ip_SlaveCmdDmaTcdInit();
    }
#endif
    
    /* Configure slave address */
	Lpi2c_Ip_SlaveConigureAddress(baseAddr, userConfigPtr->slaveAddress, userConfigPtr->is10bitAddr);

    /* Configure operating mode */
    Lpi2c_Ip_SlaveSetOperatingMode(instance, userConfigPtr->operatingMode);

    /* Set glitch filters for SDA and SCL */
    Lpi2c_Ip_SlaveConfigureGlitchFilter(baseAddr, userConfigPtr->u32GlitchFilterSDA, userConfigPtr->u32GlitchFilterSCL);
	
    if(slave->slaveListening)
    {
        Lpi2c_Ip_SlaveActivateEvents(instance);
    }
   
    return STATUS_LPI2C_IP_SUCCESS;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_StartListening
 * Description   : Makes a slave channel available for processing request in case
 *                 slave is in not listening mode
 * Implements    : I2c_Ip_StartListening_Activity
 *
 *END**************************************************************************/
void Lpi2c_Ip_StartListening(uint32 u32Instance)
{
    const Lpi2c_Ip_SlaveStateType * slave;
    slave = g_lpi2cSlaveStatePtr[u32Instance];

#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(slave != NULL_PTR);
    DevAssert(!slave->slaveListening);
#endif

    Lpi2c_Ip_SlaveActivateEvents(u32Instance);
    (void) slave;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveDeinit
 * Description   : de-initialize the I2C slave mode driver
 *
 * Implements : Lpi2c_Ip_SlaveDeinit_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_SlaveDeinit(uint32 instance)
{
    LPI2C_Type *baseAddr;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    baseAddr = g_lpi2cBase[instance];
    const Lpi2c_Ip_SlaveStateType *slave = g_lpi2cSlaveStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(slave != NULL_PTR);
#endif
    if ((slave->transferType == LPI2C_USING_DMA) && (TRUE == slave->slaveListening))
    {
        /* Disable LPI2C DMA requests. */
        (void)LPI2C_Set_SlaveRxDMA(baseAddr, FALSE);
        (void)LPI2C_Set_SlaveTxDMA(baseAddr, FALSE);
    }

    g_lpi2cSlaveStatePtr[instance] = NULL_PTR;

    /* Disable LPI2C slave */
    LPI2C_Set_SlaveEnable(baseAddr, FALSE);

    return STATUS_LPI2C_IP_SUCCESS;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveSetTxBuffer
 * Description   : Provide a buffer for transmitting data.
 *
 * Implements : Lpi2c_Ip_SlaveSetTxBuffer_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_SlaveSetBuffer(uint32 instance,
                                                 uint8 * dataBuff,
                                                 uint32 dataSize)
{
    Lpi2c_Ip_SlaveStateType * slave;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
    DevAssert(dataBuff != NULL_PTR);
    DevAssert(dataSize > 0U);
#endif
    slave = g_lpi2cSlaveStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(slave != NULL_PTR);
#endif
    slave->dataBuffer = dataBuff;
    slave->bufferSize = dataSize;

    return STATUS_LPI2C_IP_SUCCESS;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveGetTransferStatus
 * Description   : return the current status of the I2C slave transfer
 *
 * When performing an a-sync (non-blocking) transfer, the user can call this function
 * to ascertain the state of the current transfer. In addition, if the transfer is still
 * in progress, the user can get the number of words that should be receive.
 *
 * Implements : Lpi2c_Ip_SlaveGetTransferStatus_Activity
 *END**************************************************************************/
Lpi2c_Ip_StatusType Lpi2c_Ip_SlaveGetTransferStatus(uint32 instance,
                                               uint32 *bytesRemaining)
{
    const Lpi2c_Ip_SlaveStateType *slave;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    slave = g_lpi2cSlaveStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(slave != NULL_PTR);
#endif
    if ((bytesRemaining != NULL_PTR) && (slave->transferType == LPI2C_USING_INTERRUPTS))
    {
        *bytesRemaining = slave->bufferSize;
    }

    return slave->status;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : LPI2C_DRV_SlaveEndTransfer
 * Description   : ends current transmission or reception
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveEndTransfer(LPI2C_Type *baseAddr)
{
    /* Deactivate events */

    LPI2C_Set_SlaveInt(baseAddr, LPI2C_SLAVE_BIT_ERROR_INT |
                                    LPI2C_SLAVE_FIFO_ERROR_INT |
                                    LPI2C_SLAVE_STOP_DETECT_INT |
                                    LPI2C_SLAVE_REPEATED_START_INT |
                                    LPI2C_SLAVE_ADDRESS_VALID_INT |
                                    LPI2C_SLAVE_RECEIVE_DATA_INT |
                                    LPI2C_SLAVE_TRANSMIT_DATA_INT,
                          FALSE);

    /* Disable LPI2C slave */
    LPI2C_Set_SlaveEnable(baseAddr, FALSE);
    
    
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveEndTransferHandler
 * Description   : handle slave end transfer operations
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveEndTransferHandler(const Lpi2c_Ip_SlaveStateType *slave, LPI2C_Type *baseAddr)
{
    /* Check slave state */
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(slave != NULL_PTR);
#endif

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)
    /* Stop DMA channel if slave is transferring data in DMA mode */
    if (slave->transferType == LPI2C_USING_DMA)
    {
        if(slave->direction == LPI2C_IP_SEND)
        {
            /* Stop TX DMA channel */
            (void)Dma_Ip_SetLogicChannelCommand(slave->dmaTxChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
        }
        else
        {
            /* Stop RX DMA channel */
            (void)Dma_Ip_SetLogicChannelCommand(slave->dmaRxChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);           
        }
    }
#endif

    if (!slave->slaveListening)
    {
        Lpi2c_Ip_SlaveEndTransfer(baseAddr);
    }

    if(slave->slaveCallback != NULL_PTR)
    {
        slave->slaveCallback(I2C_SLAVE_EVENT_STOP, slave->callbackParam);
    }
    
    (void) baseAddr;

}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveCheckDataEvent
 * Description   : check slave adress valid and tx/rx event
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveCheckDataEvent(uint32 instance, LPI2C_Type *baseAddr, Lpi2c_Ip_SlaveStateType * slave)
{
	boolean slaveInterrupt = FALSE;
	
    /* Check which event caused the interrupt */
    if (LPI2C_Get_SlaveAddressValidEvent(baseAddr))
    {
        Lpi2c_Ip_SlaveHandleAddressValidEvent(instance, baseAddr, slave);
    }
	
	/* Check transmit event */
	if (LPI2C_Get_SlaveTransmitDataEvent(baseAddr))
    {
        slaveInterrupt = LPI2C_Get_SlaveInt(baseAddr, (uint32)LPI2C_SLAVE_TRANSMIT_DATA_INT);
        if (slaveInterrupt)
        {
			/* Handle transmit event */
            Lpi2c_Ip_SlaveHandleTransmitDataEvent(baseAddr, slave);
        }
    }

	/* Check receive event */
    if (LPI2C_Get_SlaveReceiveDataEvent(baseAddr))
    {
        slaveInterrupt = LPI2C_Get_SlaveInt(baseAddr, (uint32)LPI2C_SLAVE_RECEIVE_DATA_INT);
        if (slaveInterrupt)
        {
			/* Handle receive event */
            Lpi2c_Ip_SlaveHandleReceiveDataEvent(baseAddr, slave);
        }
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveStopDetectHandler
 * Description   : handles stop/repeated start event
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveStopDetectHandler(LPI2C_Type *baseAddr, Lpi2c_Ip_SlaveStateType * slave)
{
    /* Either STOP or repeated START have the same meaning here: the current transfer is over */
    LPI2C_Clear_SlaveSTOPDetectEvent(baseAddr);
    LPI2C_Clear_SlaveRepeatedStartEvent(baseAddr);

#if defined(ERRATA_E10792)
    /* Deactivate interrupts for transmitting data */
    LPI2C_Set_SlaveInt(baseAddr, (uint32)LPI2C_SLAVE_TRANSMIT_DATA_INT, FALSE);
#endif

    if (slave->status == STATUS_LPI2C_IP_BUSY)
    {
        /* Report success if no error was recorded */
        slave->status = STATUS_LPI2C_IP_SUCCESS;
    }

    Lpi2c_Ip_SlaveEndTransferHandler(slave, baseAddr);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveBitErrorEventHandler
 * Description   : handles slave bit error event 
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveBitErrorEventHandler(LPI2C_Type *baseAddr, Lpi2c_Ip_SlaveStateType * slave)
{
    slave->status = STATUS_LPI2C_IP_ERROR;
    
	LPI2C_Clear_SlaveBitErrorEvent(baseAddr);

#if (STD_ON == LPI2C_IP_EVENT_ERROR_DETECT)
    if (slave->slaveCallback != NULL_PTR)
    {
        slave->slaveCallback(I2C_SLAVE_EVENT_ERROR_BIT, slave->callbackParam);
    }
#endif

#if defined(ERRATA_E10792)
    /* Deactivate interrupts for transmitting data */
    LPI2C_Set_SlaveInt(baseAddr, (uint32)LPI2C_SLAVE_TRANSMIT_DATA_INT, FALSE);
#endif

    /* Slave end transfer */ 
    Lpi2c_Ip_SlaveEndTransferHandler(slave, baseAddr);	
}

#if(LPI2C_HAS_ULTRA_FAST_MODE)
/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveFIFOErrorEventHandler
 * Description   : handles slave FIFO error event 
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveFIFOErrorEventHandler(LPI2C_Type *baseAddr, Lpi2c_Ip_SlaveStateType * slave)
{
    /* In Ultra-Fast mode clock stretching is disabled, so it is possible to get
       this event if the slave can't keep up */
    slave->status = STATUS_LPI2C_IP_RX_OVERRUN;
    LPI2C_Clear_SlaveFIFOErrorEvent(baseAddr);

#if defined(ERRATA_E10792)
    /* Deactivate interrupts for transmitting data */
    LPI2C_Set_SlaveInt(baseAddr, LPI2C_SLAVE_TRANSMIT_DATA_INT, FALSE);
#endif

    Lpi2c_Ip_SlaveEndTransferHandler(slave, baseAddr);	
}
#endif 

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveCheckErrorEvent
 * Description   : checks for slave errors 
 *
 *END**************************************************************************/
static void Lpi2c_Ip_SlaveCheckErrorEvent(LPI2C_Type *baseAddr, Lpi2c_Ip_SlaveStateType * slave)
{
    if (LPI2C_Get_SlaveBitErrorEvent(baseAddr))
    {
		/* Handle slave bit error event */
        Lpi2c_Ip_SlaveBitErrorEventHandler(baseAddr, slave);
    }

#if(LPI2C_HAS_ULTRA_FAST_MODE)
    if (LPI2C_Get_SlaveFIFOErrorEvent(baseAddr))
    {
		/* Handle slave FIFO error event */
        Lpi2c_Ip_SlaveFIFOErrorEventHandler(baseAddr, slave);
    }
#endif	
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SlaveIRQHandler
 * Description   : handle non-blocking slave operation when I2C interrupt occurs
 *
 *END**************************************************************************/
void Lpi2c_Ip_SlaveIRQHandler(uint32 instance)
{
    LPI2C_Type *baseAddr;
    Lpi2c_Ip_SlaveStateType * slave;
    boolean stopDetect = FALSE, repeatStartDetect = FALSE;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif
    baseAddr = g_lpi2cBase[instance];
    slave = g_lpi2cSlaveStatePtr[instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(slave != NULL_PTR);
#endif

	/* Check address valid and tx/rx event */
	Lpi2c_Ip_SlaveCheckDataEvent(instance, baseAddr, slave);
	
    stopDetect =  LPI2C_Get_SlaveSTOPDetectEvent(baseAddr);
    repeatStartDetect = LPI2C_Get_SlaveRepeatedStartEvent(baseAddr);

    if (repeatStartDetect)
    {
        slave->repeatedStarts++;

        if ((slave->repeatedStarts == 1U) && (slave->is10bitAddress))
        {
            repeatStartDetect = FALSE;
            LPI2C_Clear_SlaveRepeatedStartEvent(baseAddr);
        }
    }

    if ((stopDetect == TRUE) || (repeatStartDetect == TRUE))
    {
		/* Stop/repeated start detected */
        Lpi2c_Ip_SlaveStopDetectHandler(baseAddr, slave);
        
        if (stopDetect == TRUE)
        {
			/* reset repetead starts for a new transfer */
            slave->repeatedStarts = 0U;
        }       
    }
	
	/* Check for slave errors */
	Lpi2c_Ip_SlaveCheckErrorEvent(baseAddr, slave);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_ModuleIRQHandler
 * Description   : handle events for lpi2c module 
 *
 *END**************************************************************************/
void Lpi2c_Ip_ModuleIRQHandler(uint32 instance)
{
    LPI2C_Type *baseAddr;
    uint32 u32MasterIsrEnable = 0u; 
    uint32 u32MasterIsrStatus = 0u; 
    uint32 u32SlaveIsrEnable = 0u; 
    uint32 u32SlaveIsrStatus = 0u; 

#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(instance < LPI2C_INSTANCE_COUNT);
#endif

    baseAddr = g_lpi2cBase[instance];

    /* Check spurious interrupt */
    if ((NULL_PTR != g_lpi2cSlaveStatePtr[instance]) || (NULL_PTR != g_lpi2cMasterStatePtr[instance]))
    {
        /* the driver has been initialized */
        /* Check i2c interrupts */
        u32MasterIsrEnable = baseAddr->MIER & (LPI2C_MIER_DMIE_MASK | LPI2C_MIER_PLTIE_MASK | LPI2C_MIER_FEIE_MASK | LPI2C_MIER_ALIE_MASK | LPI2C_MIER_NDIE_MASK |  
                                               LPI2C_MIER_SDIE_MASK | LPI2C_MIER_EPIE_MASK | LPI2C_MIER_RDIE_MASK | LPI2C_MIER_TDIE_MASK);
        
        u32MasterIsrStatus = baseAddr->MSR & ( LPI2C_MSR_DMF_MASK | LPI2C_MSR_PLTF_MASK | LPI2C_MSR_FEF_MASK | LPI2C_MSR_ALF_MASK | LPI2C_MSR_NDF_MASK | 
                                               LPI2C_MSR_SDF_MASK | LPI2C_MSR_EPF_MASK | LPI2C_MSR_RDF_MASK | LPI2C_MSR_TDF_MASK);
        
        u32SlaveIsrEnable = baseAddr->SIER & (LPI2C_SIER_SARIE_MASK | LPI2C_SIER_GCIE_MASK | LPI2C_SIER_AM0IE_MASK | LPI2C_SIER_FEIE_MASK | 
                                              LPI2C_SIER_BEIE_MASK | LPI2C_SIER_SDIE_MASK | LPI2C_SIER_RSIE_MASK | LPI2C_SIER_TAIE_MASK |  
                                              LPI2C_SIER_AVIE_MASK | LPI2C_SIER_RDIE_MASK | LPI2C_SIER_TDIE_MASK | LPI2C_SIER_AM1IE_MASK);
        
        u32SlaveIsrStatus = baseAddr->SSR & (LPI2C_SSR_SARF_MASK | LPI2C_SSR_GCF_MASK | LPI2C_SSR_AM1F_MASK | LPI2C_SSR_AM0F_MASK | LPI2C_SSR_FEF_MASK | 
                                             LPI2C_SSR_BEF_MASK | LPI2C_SSR_SDF_MASK | LPI2C_SSR_RSF_MASK | LPI2C_SSR_TAF_MASK | LPI2C_SSR_AVF_MASK | 
                                             LPI2C_SSR_RDF_MASK | LPI2C_SSR_TDF_MASK);
                                              
        if (((0u != u32MasterIsrEnable) && (0u != u32MasterIsrStatus)) || ((0u != u32SlaveIsrEnable) && (0u != u32SlaveIsrStatus)))
        {           
            /* Check if module is master or slave */
            if (g_lpi2cSlaveStatePtr[instance] == NULL_PTR)
            {
                Lpi2c_Ip_MasterIRQHandler(instance);
            }
            else
            {
                Lpi2c_Ip_SlaveIRQHandler(instance);
            }
        }
        else
        {
            /* Clear all flags */
            baseAddr->MSR &= (uint32)0xFFFFFFFFU;
            baseAddr->SSR &= (uint32)0xFFFFFFFFU;
        }
    }
    else
    {
        /* Clear all flags */
        baseAddr->MSR &= (uint32)0xFFFFFFFFU;
        baseAddr->SSR &= (uint32)0xFFFFFFFFU;
    }
    
    /* Cast to void to avoid compiler warnings */
    (void) u32MasterIsrEnable; 
    (void) u32MasterIsrStatus;
    (void) u32SlaveIsrEnable;
    (void) u32SlaveIsrStatus;
}

#if(STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE)

#if (LPI2C_INSTANCE_COUNT >= 1U)
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C0_DmaCompleteNotification
 * Description   : Dma complete notification for instance 0
 *
 *END**************************************************************************/
void LPI2C0_DmaCompleteNotification(void)
{
#ifdef LPI2C_ENABLE_USER_MODE_SUPPORT
  #if (STD_ON == LPI2C_ENABLE_USER_MODE_SUPPORT)
    OsIf_Trusted_Call1param(Lpi2c_Ip_MasterCompleteDMATransfer,(0U));
  #else
    Lpi2c_Ip_MasterCompleteDMATransfer(0U);
  #endif
#endif
}
#endif /* LPI2C_INSTANCE_COUNT >= 1U */

#if (LPI2C_INSTANCE_COUNT >= 2U)
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C1_DmaCompleteNotification
 * Description   : Dma complete notification for instance 1
 *
 *END**************************************************************************/
void LPI2C1_DmaCompleteNotification(void)
{
#ifdef LPI2C_ENABLE_USER_MODE_SUPPORT
  #if (STD_ON == LPI2C_ENABLE_USER_MODE_SUPPORT)
    OsIf_Trusted_Call1param(Lpi2c_Ip_MasterCompleteDMATransfer,(1U));
  #else
    Lpi2c_Ip_MasterCompleteDMATransfer(1U);
  #endif
#endif
}
#endif /* LPI2C_INSTANCE_COUNT >= 2U */

#endif /* STD_ON == LPI2C_IP_DMA_FEATURE_AVAILABLE */

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SetMasterCallback
 * Description   : Sets the master callback
 *
 *END**************************************************************************/
void Lpi2c_Ip_SetMasterCallback(uint32 u32Instance, Lpi2c_Ip_MasterCallbackType masterCallback)
{
    Lpi2c_Ip_MasterStateType * master;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(u32Instance < LPI2C_INSTANCE_COUNT);
#endif
    master = g_lpi2cMasterStatePtr[u32Instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    
    master->masterCallback = masterCallback; 
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SetSlaveCallback
 * Description   : Sets the slave callback
 *
 *END**************************************************************************/
void Lpi2c_Ip_SetSlaveCallback(uint32 u32Instance, Lpi2c_Ip_SlaveCallbackType slaveCallback)
{
    Lpi2c_Ip_SlaveStateType * slave;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(u32Instance < LPI2C_INSTANCE_COUNT);
#endif
    slave = g_lpi2cSlaveStatePtr[u32Instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(slave != NULL_PTR);
#endif
    
    slave->slaveCallback = slaveCallback;   
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpi2c_Ip_SetMasterHighSpeedMode
 * Description   : Sets high speed mode for master 
 *
 *END**************************************************************************/
void Lpi2c_Ip_SetMasterHighSpeedMode(uint32 u32Instance, boolean bHighSpeedEnabled)
{
    Lpi2c_Ip_MasterStateType * master;
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(u32Instance < LPI2C_INSTANCE_COUNT);
#endif
    master = g_lpi2cMasterStatePtr[u32Instance];
#if (STD_ON == LPI2C_IP_DEV_ERROR_DETECT)
    DevAssert(master != NULL_PTR);
#endif
    
	if (TRUE == bHighSpeedEnabled)
	{
		/* Set high speed operating mode */
        master->operatingMode = LPI2C_HIGHSPEED_MODE;
    }
    else
	{
		/* High speed mode is not selected */
		master->operatingMode = LPI2C_STANDARD_MODE;
	}		
}

#define I2C_STOP_SEC_CODE
#include "I2c_MemMap.h"

#ifdef __cplusplus
}
#endif

/** @} */

/*******************************************************************************
 * EOF
 ******************************************************************************/
