/**
 ******************************************************************************
  * @file    kpm32xx_ddl_i2c.h
  * @author  Kiwi Software Team
  * @brief   Header file of I2C DDL module.
  * @note
 *		   V1.0.0, 2022/08/03.
 *
 * Copyright (c) 2024, Kiwi Instruments Co,. Ltd.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *	1. Redistributions of source code must retain the above copyright notice,
 *	   this list of conditions and the following disclaimer.
 *
 *	2. Redistributions in binary form must reproduce the above copyright notice,
 *	   this list of conditions and the following disclaimer in the documentation
 *	   and/or other materials provided with the distribution.
 *
 *	3. Neither the name of the copyright holder nor the names of its contributors
 *	   may be used to endorse or promote products derived from this software without
 *	   specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************
 */

#ifndef __KPM32xx_DDL_I2C_H
#define __KPM32xx_DDL_I2C_H

#ifdef __cplusplus
extern "C" {
#endif

#include "kpm32xx_ddl_def.h"

typedef struct
{
	uint32_t workMode;                   /* Master or Slave mode */
	uint32_t addrMode;                   /* address mode: 7bit or 10bit */
	uint32_t wakupEnable;                /* Enable Wakup CPU from STOP mode */
	uint32_t i2cFltEnable;               /* Enable I2C filter */
	uint32_t prescaler;         /*  are used for SCI I2C baudrate */
	uint32_t widthHigh;      /*  are used for SCI I2C baudrate */
	uint32_t widthLow;
	uint32_t  address1;                   /* 7Bit address or first 8Bit content of 10bit address */
	uint8_t  address2;                   /* Second 8Bit content of 10bit address */
} I2C_Init_T;


typedef enum
{
	I2C_ADDR_07BITS          = 0x00U,    /* 7 bit address mode */
	I2C_ADDR_10BITS          = 0x01U,    /* 10 bit address mode */
}I2C_Addr_T;


typedef enum
{
	I2C_MASTER_MODE          = 0x00U,    /* I2C Master mode */
	I2C_SLAVE_MODE           = 0x01U,    /* I2C Slave mode */
}I2C_WorkMode_T;

#define I2C_READ_DIRECTION                   0x00U
#define I2C_WRITE_DIRECTION                  0x01U
#define I2C_DMA_TRANSMIT					 0x03U

#define DDL_I2C_ERROR_NONE                                ((uint32_t)0x00000000U)    /* No error                */
#define DDL_I2C_ERROR_TRAN_NACK                           ((uint32_t)0x00000001U)    /* Transmission Error      */
#define DDL_I2C_ERROR_RECV_NACK                           ((uint32_t)0x00000002U)    /* Receive Error           */
#define DDL_I2C_ERROR_DMA                                 ((uint32_t)0x00000010U)    /* DMA transfer error      */

#define I2C_INTOCUR_ON8TH_CLK                             (0x0U << I2C_CTRL_WTIM_Pos)
#define I2C_INTOCUR_ON9TH_CLK                             (0x1U << I2C_CTRL_WTIM_Pos)

#define I2C_BAUDRATE_BPS_10K                              10000                      /*10kbps*/
#define I2C_BAUDRATE_BPS_100K                             100000                     /*100kbps*/
#define I2C_BAUDRATE_BPS_400K                             400000                     /*400kbps*/
#define I2C_BAUDRATE_BPS_1000K                            1000000                    /*1000kbps*/

/* I2C tx and rx mode */
#define I2C_MODE_RX                                       ((uint32_t)0x00000001U)    /* RX mode */
#define I2C_MODE_TX                                       ((uint32_t)0x00000002U)    /* TX mode */

/* 7bit or 10bit address mode */
#define IS_I2C_ADDRESS_MODE(__MODE__)                     (((__MODE__) == I2C_ADDR_07BITS) || ((__MODE__) == I2C_ADDR_10BITS))

/* Master or Slave address mode */
#define IS_I2C_WORK_MODE(__MODE__)                        (((__MODE__) == I2C_MASTER_MODE) || ((__MODE__) == I2C_SLAVE_MODE))

#define IS_I2C_INSTANCE(__INSTANCE__)                     ((__INSTANCE__) == I2C0 || (__INSTANCE__) == I2C1)

/* Only 10K, 100K, 400K, 1000K bps baudrate are supported */
#define IS_I2C_BAUDRATE(__BAUDRATE__)                     (((__BAUDRATE__) == I2C_BAUDRATE_BPS_10K)    || \
										                   ((__BAUDRATE__) == I2C_BAUDRATE_BPS_100K)   || \
										                   ((__BAUDRATE__) == I2C_BAUDRATE_BPS_400K)   || \
										                   ((__BAUDRATE__) == I2C_BAUDRATE_BPS_1000K))

/* I2C Module Enable and Disable */
#define __DDL_I2C_ENABLE(__INSTANCE__)                      SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_I2CEN)
#define __DDL_I2C_DISABLE(__INSTANCE__)                     CLEAR_BIT((__INSTANCE__)->CTRL, I2C_CTRL_I2CEN)
/* I2C Module Enable and Disable */
#define __DDL_SMBUS_ENABLE(__INSTANCE__)                    SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_SMBUS)
#define __DDL_SMBUS_DISABLE(__INSTANCE__)                   CLEAR_BIT((__INSTANCE__)->CTRL, I2C_CTRL_SMBUS)

/* I2C filter On and Off Control */
#define __DDL_I2C_FILTER_ON(__INSTANCE__)                   SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_FLTEN)
#define __DDL_I2C_FILTER_OFF(__INSTANCE__)                  CLEAR_BIT((__INSTANCE__)->CTRL, I2C_CTRL_FLTEN)

/* I2C DMA Enable and Disable */
#define __DDL_I2C_DMA_ENABLE(__INSTANCE__)                  SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_DMAEN)
#define __DDL_I2C_DMA_DISABLE(__INSTANCE__)                 CLEAR_BIT((__INSTANCE__)->CTRL, I2C_CTRL_DMAEN)

/* I2C ACK and NACK Generate */
#define __DDL_I2C_ACK_GENERATE(__INSTANCE__)                SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_ACKEN)
#define __DDL_I2C_NACK_GENERATE(__INSTANCE__)               CLEAR_BIT((__INSTANCE__)->CTRL, I2C_CTRL_ACKEN)

/* I2C Interrupt happens on 8th or 9th Clock */
#define __DDL_I2C_WTIMINT_ENABLE(__INSTANCE__)              SET_BIT((__INSTANCE__)->INTEN, I2C_INTEN_WTIMEN)
#define __DDL_I2C_WTIMINT_DISABLE(__INSTANCE__)             CLEAR_BIT((__INSTANCE__)->INTEN, I2C_INTEN_WTIMEN)

/* I2C DATA transmit direction */
#define __DDL_I2C_WRITE_CONFIG(__INSTANCE__)                CLEAR_BIT((__INSTANCE__)->CTRL, I2C_CTRL_DATADIR)
#define __DDL_I2C_READ_CONFIG(__INSTANCE__)                 SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_DATADIR)

/* I2C 7bit or 10bit ADMOD_SEL set */
#define __DDL_I2C_7BIT_ADMOD_SET(__INSTANCE__)              CLEAR_BIT((__INSTANCE__)->CTRL, I2C_CTRL_ADMOD)
#define __DDL_I2C_10BIT_ADMOD_SET(__INSTANCE__)             SET_BIT ((__INSTANCE__)->CTRL, I2C_CTRL_ADMOD)

/* I2C Interrupt happens on 8th or 9th Clock:  I2C_INTOCUR_ON8TH_CLK or I2C_INTOCUR_ON9TH_CLK */
#define __DDL_I2C_WTIM_8OR9THCLK_CONFIG(__INSTANCE__, __8OR9THCLK__)      MODIFY_REG((__INSTANCE__)->CTRL, I2C_CTRL_WTIM_Msk, __8OR9THCLK__)

/* I2C Stop Signal Generate */
#define __DDL_I2C_STP_GENERATE(__INSTANCE__)                SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_SPT)

/* I2C Start Signal Generate */
#define __DDL_I2C_STT_GENERATE(__INSTANCE__)                SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_STT)

/* I2C ACK Enable: Generate ACK in Slave mode */
#define __DDL_I2C_ACKGEN_ENABLE(__INSTANCE__)               SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_ACKEN)
#define __DDL_I2C_ACKGEN_DISABLE(__INSTANCE__)              CLEAR_BIT((__INSTANCE__)->CTRL, I2C_CTRL_ACKEN)

/* I2C Interrupt Rises Enable on Stop Signal detected, usually in Slave mode */
#define __DDL_I2C_STPINT_ENABLE(__INSTANCE__)               SET_BIT((__INSTANCE__)->INTEN, I2C_INTEN_STOPINT)
#define __DDL_I2C_STPINT_DISABLE(__INSTANCE__)              CLEAR_BIT((__INSTANCE__)->INTEN, I2C_INTEN_STOPINT)

/* I2C quit wait */
#define __DDL_I2C_WAIT_QUIT_SET(__INSTANCE__)               SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_WREL)

/* I2C communication quits, usually in Slave mode */
#define __DDL_I2C_COMM_QUIT_SET(__INSTANCE__)               SET_BIT((__INSTANCE__)->CTRL, I2C_CTRL_LREL)

/* I2C High and Low Level Width Configure */
#define __DDL_I2C_HIGHANDLOW_LVL_CONFIG(__INSTANCE__, __HCLK__, __LCLK__) WRITE_REG((__INSTANCE__)->WID, ((__HCLK__ << I2C_WID_HL_Pos) | (__LCLK__ << I2C_WID_LL_Pos)))

/* Clear I2C THRE Interrupt CTRL */
#define __DDL_I2C_CLOSE_FIFOTHRE_INTR(__INSTANCE__)         CLEAR_BIT((__INSTANCE__)->CTRL, I2C_INTEN_FIFOTHRE)

/* Clear I2C Stop Interrupt Status */
#define __DDL_I2C_CLEAR_STOP_INTR(__INSTANCE__)             WRITE_REG((__INSTANCE__)->INTSR, I2C_INTSR_STP)

/* Clear I2C DATA Interrupt Status */
#define __DDL_I2C_CLEAR_DATA_INTR(__INSTANCE__)             WRITE_REG((__INSTANCE__)->INTSR, I2C_INTSR_DATA)

/* Clear I2C FIFO CTRL Status */
#define __DDL_I2C_CLEAR_FIFO(__INSTANCE__)                  SET_BIT((__INSTANCE__)->FIFOCTL, I2C_FIFOCTL_FIFOCLR)

/* Clear I2C TCNTDONE Interrupt Status */
#define __DDL_I2C_CLEAR_TCNTDONE_INTR(__INSTANCE__)         WRITE_REG((__INSTANCE__)->INTSR, I2C_INTSR_TCNTDONE)

/* Clear I2C address Interrupt Status */
#define __DDL_I2C_CLEAR_ADDR_INTR(__INSTANCE__)             WRITE_REG((__INSTANCE__)->INTSR, I2C_INTSR_ADDR)

/* Clear I2C address Interrupt Status */
#define __DDL_I2C_CLEAR_NACK_INTR(__INSTANCE__)             WRITE_REG((__INSTANCE__)->INTSR, I2C_INTSR_NACK)

/* Disable individual interrupt source */
#define __DDL_I2C_INTDISABLE(__INSTANCE__, __INTERRUPT__)  CLEAR_BIT((__INSTANCE__)->INTEN, __INTERRUPT__)

/* Enable individual interrupt source */
#define __DDL_I2C_INTENABLE(__INSTANCE__, __INTERRUPT__)   SET_BIT((__INSTANCE__)->INTEN, __INTERRUPT__)

/* Clear DMA Error Flags */
#define __DDL_I2C_CLEAR_DMAERR_FLAG(__INSTANCE__)           WRITE_REG((__INSTANCE__)->SR, I2C_SR_DMAERR)

/**
  * @brief  Enable IIC interrupt.
  *
  * @param  I2Cx Pointer to IIC instance.
  * @param  intrMask IIC mask.
  *
  * @retval None
  */
void DDL_IIC_IntEnable(I2C_Type *I2Cx, uint32_t intrMask);

/**
  * @brief  Disable IIC interrupt.
  *
  * @param  I2Cx Pointer to IIC instance.
  * @param  intrMask IIC mask.
  *
  * @retval None
  */
void DDL_IIC_IntDisable(I2C_Type *I2Cx, uint32_t intrMask);

/**
  * @brief  Configure the elements of structure I2C_Init_T to default values.
  *         where, for example:(Fclk 200M)
  *         Baud        prescaler	widthHigh	widthLow
  *         1000000     1           17  	    17
  *         400000      1           53          53
  *         100000      1           240         241
  *         10000       20          233         233
  * @param  pI2CStruct Pointer to a I2C_Init_T structure that contains
  *                  the configuration information for the given I2C module.
  *
  * @retval None
  */
void DDL_I2C_StructInit(I2C_Init_T *pI2CStruct);


/**
  * @brief  Initializes the I2C by the specified parameters
  *         in the I2C_Init_T and initialize the associated handle.
  * @param  I2Cx     Pointer to IIC instance.
  * @param  pI2CStruct   pointer to a I2C_Init_T structure that contains
  *                the configuration information for the specified I2C.
  *
  * @retval None
  */
void DDL_I2C_Init(I2C_Type *I2Cx, I2C_Init_T *pI2CStruct);

/**
  * @brief  I2C as master transmits an amount of data in polling mode.
  * @param  SCIx Pointer to IIC instance.
  *         slvAddr address to be sent.
  *         pData   pointer to data buffer.
  *         size    the amount of data to be sent.
  *         timeout specify the max wait time.
  * @retval DDL status
  */
DDL_Status_T DDL_I2C_Master_Transmit(I2C_Type *I2Cx, uint16_t slvAddr, uint8_t *pData, uint16_t size, uint32_t timeout);

/**
  * @brief  I2C as master receive an amount of data with polling.
  * @param  SCIx Pointer to IIC instance.
  *         slvAddr address to be sent.
  *         pData  pointer to data buffer.
  *         size   the amount of data to be sent.
  *         timeout specify the max wait time.
  * @retval DDL status
  */
DDL_Status_T DDL_I2C_Master_Receive(I2C_Type *I2Cx, uint16_t slvAddr, uint8_t *pData, uint16_t size, uint32_t timeout);





#ifdef __cplusplus
}
#endif
#endif /* __KPM32xx_DDL_I2C_H */
