/**
 *********************************************************************************
 *
 * @file    hal_i2c.h
 * @brief   Header file of I2C driver
 *
 * @version V1.0
 * @date    15 Nov 2017
 * @author  AE Team
 * @note
 *
 * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
 *
 ********************************************************************************
 */

#ifndef __HAL_I2C_H__
#define __HAL_I2C_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "utils.h"
#include "hal_dma.h"
#include "hal_cmu.h"

#define I2C_FLAG_MASK  (0xffffffff)

/** @addtogroup ES32FXXX_HAL
  * @{
  */

/** @addtogroup I2C
  * @{
  */

/** @defgroup I2C_Public_Types I2C Public Types
  * @{
  */
/**
  * @brief I2C Error Code
  */
typedef enum {
	I2C_ERROR_NONE    = 0x0,  /**< No error */
	I2C_ERROR_BERR    = 0x1,  /**< Berr error */
	I2C_ERROR_ARLO    = 0x2,  /**< Arlo error */
	I2C_ERROR_AF      = 0x4,  /**< Af error */
	I2C_ERROR_OVR     = 0x8,  /**< Ovr error */
	I2C_ERROR_DMA     = 0x10, /**< Dma error */
	I2C_ERROR_TIMEOUT = 0x20  /**< Timeout error */
} i2c_error_t;

/**
  * @brief I2C state structure definition
  */
typedef enum {
	I2C_STATE_RESET   = 0x0,  /**< Peripheral is not yet Initialized */
	I2C_STATE_READY   = 0x20, /**< Peripheral Initialized and ready for use */
	I2C_STATE_BUSY    = 0x24, /**< An internal process is ongoing */
	I2C_STATE_BUSY_TX = 0x21, /**< Data Transmission process is ongoing */
	I2C_STATE_BUSY_RX = 0x22, /**< Data Reception process is ongoing */
	I2C_STATE_TIMEOUT = 0xA0, /**< timeout state */
	I2C_STATE_ERROR   = 0xE0  /**< Error */
} i2c_state_t;

/**
  * @brief I2C AutoEnd Mode
  */
typedef enum {
	I2C_AUTOEND_ENABLE     = 0x01, /**< 7 bit address */
	I2C_AUTOEND_DIAENABLE  = 0x00  /**< 10 bit address */
} i2c_autoend_t;

/**
  * @brief I2C Addressing Mode
  */
typedef enum {
	I2C_ADDRESSINGMODE_7BIT  = 0x0, /**< 7 bit address */
	I2C_ADDRESSINGMODE_10BIT = 0x01  /**< 10 bit address */
} i2c_addr_t;

/**
  * @brief I2C Address
  */
typedef enum {
	ADDRESS1  = 0x46, /**< 7 bit address */
	ADDRESS2  = 0x23  /**< 10 bit address */
} i2c_saddr_t;
/**
  * @brief I2C Dual Addressing Mode
  */
typedef enum {
	I2C_DUALADDRESS_DISABLE = 0x0, /**< dual address is disable */
	I2C_DUALADDRESS_ENABLE  = 0x1  /**< dual address is enable */
} i2c_dual_addr_t;

/**
  * @brief I2C General Call Addressing mode
  */
typedef enum {
	I2C_GENERALCALL_DISABLE = 0x0, /**< general call address is disable */
	I2C_GENERALCALL_ENABLE  = 0x1 /**< general call address is enable */
} i2c_general_addr_t;

/**
  * @brief I2C Nostretch Mode
  */
typedef enum {
	I2C_NOSTRETCH_DISABLE = 0x0, /**< Nostretch disable */
	I2C_NOSTRETCH_ENABLE  = 0x1 /**< Nostretch enable */
} i2c_nostretch_t;

/**
  * @brief I2C Memory Address Size
  */
typedef enum {
	I2C_MEMADD_SIZE_8BIT  = 0x1, /**< 8 bit memory address size */
	I2C_MEMADD_SIZE_16BIT = 0x10 /**< 10 bit memory address size */
} i2c_addr_size_t;

/**
  * @brief I2C Flag Definition
  */
typedef enum {
	I2C_FLAG_TXE  = (1U << 0), /**< Transmit data register empty Flag */
	I2C_FLAG_TXF  = (1U << 1), /**< Transmit data register full Flag  */
	I2C_FLAG_TXOV = (1U << 2), /**< Transmit data register overrun Flag */
	I2C_FLAG_TXUD = (1U << 3), /**< Transmit data register underrun Flag */
	I2C_FLAG_TXTH = (1U << 4), /**< Transmit data FIFO Threshold */
	I2C_FLAG_RXE  = (1U << 5), /**< Receive data register empty Flag  */
	I2C_FLAG_RXF  = (1U << 6), /**< Receive data register full Flag */
	I2C_FLAG_RXOV = (1U << 7), /**< Receive data register overrun Flag */
	I2C_FLAG_RXUD = (1U << 8), /**< Receive data register underrun Flag */
	I2C_FLAG_RXTH = (1U << 9), /**< Receive data data FIFO Threshold */
	I2C_FLAG_TC   = (1U << 10), /**< PEC Error in reception Flag */
	I2C_FLAG_TCR  = (1U << 11), /**< Timeout or tLOW detection Flag */
	I2C_FLAG_BUSY = (1U << 15), /**< Bus busy Flag */
	I2C_FLAG_DIR  = (1U << 16), /**< Transfer direction (slave mode) */
} i2c_flag_t;

/**
  * @brief I2C mode structure definition
  */
typedef enum
{
	I2C_MODE_NONE   = 0x0,  /**< No I2C communication on going */
	I2C_MODE_MASTER = 0x10, /**< I2C communication is in Master mode */
	I2C_MODE_SLAVE  = 0x20, /**< I2C communication is in Slave mode */
	I2C_MODE_MEM    = 0x40  /**< I2C communication is in Memory mode */
}i2c_mode_t;

/**
  * @brief I2C Clock
  */
typedef enum {
	I2C_STANDARD_MODE_MAX_CLK = 100000, /**< Standard mode clock */
	I2C_FAST_MODE_MAX_CLK     = 400000  /**< Fast mode clock */
} i2c_clock_t;

/**
  * @brief I2C CR1 Register
  */
typedef enum {
	I2C_FCR_TXFRST   = (1U << 5),
	I2C_FCR_RXFRST   = (1U << 13),
} i2c_fcr_t;

/**
  * @brief I2C CR2 Register
  */
typedef enum {
	I2C_CR1_PE        = (1U << 0),  /**< Peripheral enable bit 0 */
	I2C_CR1_TXDMAEN   = (1U << 14), /**< DMA transmission requests bit 14 */
	I2C_CR1_RXDMAEN   = (1U << 15), /**< DMA reception requests bit 15 */
	I2C_CR1_SBC       = (1U << 16), /**< Slave byte control bit 16 */
	I2C_CR1_NOSTRETCH = (1U << 17), /**< Clock stretching bit 17 */
	I2C_CR1_GCEN      = (1U << 19),  /**< General call enable bit 19 */
	I2C_CR1_SMBHEN    = (1U << 20),  /**< SMBus Host address enable bit 20 */
	I2C_CR1_SMBDEN    = (1U << 21),  /**< SMBus Device Default address enable bit 21 */
	I2C_CR1_ALERTEN   = (1U << 22),  /**< SMBus alert enable bit 22 */
	I2C_CR1_PECEN     = (1U << 23)  /**< PEC enable bit 23 */
} i2c_cr1_t;

/**
  * @brief I2C CR2 Register
  */
typedef enum {
	I2C_CR2_SADD0    = (1U << 0),  /**< Slave address bit 0 */
	I2C_CR2_SADD1    = (1U << 1),  /**< Slave address bit 1 */
	I2C_CR2_SADD2    = (1U << 2),  /**< Slave address bit 2 */
	I2C_CR2_SADD3    = (1U << 3),  /**< Slave address bit 3 */
	I2C_CR2_SADD4    = (1U << 4),  /**< Slave address bit 4 */
	I2C_CR2_SADD5    = (1U << 5),  /**< Slave address bit 5 */
	I2C_CR2_SADD6    = (1U << 6),  /**< Slave address bit 6 */
	I2C_CR2_SADD7    = (1U << 7),  /**< Slave address bit 7 */
	I2C_CR2_SADD8    = (1U << 8),  /**< Slave address bit 8 */
	I2C_CR2_SADD9    = (1U << 9),  /**< Slave address bit 9 */
	I2C_CR2_RD_WRN   = (1U << 10), /**< Master Transfer direction bit 10 */
	I2C_CR2_ADD10    = (1U << 11), /**< Master 10-bit addressing mode bit 11 */
	I2C_CR2_HEAD10R  = (1U << 12), /**< Master 10-bit address headr Read mode bit 12 */
	I2C_CR2_START    = (1U << 13), /**< Master mode Start generation bit 13 */
	I2C_CR2_STOP     = (1U << 14), /**< Master mode Stop generation bit 14 */
	I2C_CR2_NACK     = (1U << 15), /**< Slave mode NACK generation bit 15 */
	I2C_CR2_NBYTES0  = (1U << 16), /**< Number of bytes don't care in slave mode with SBC = 0 bit 16 */
	I2C_CR2_NBYTES1  = (1U << 17), /**< Number of bytes don't care in slave mode with SBC = 0 bit 17 */ 
	I2C_CR2_NBYTES2  = (1U << 18), /**< Number of bytes don't care in slave mode with SBC = 0 bit 18 */ 
	I2C_CR2_NBYTES3  = (1U << 19), /**< Number of bytes don't care in slave mode with SBC = 0 bit 19 */ 
	I2C_CR2_NBYTES4  = (1U << 20), /**< Number of bytes don't care in slave mode with SBC = 0 bit 20 */ 
	I2C_CR2_NBYTES5  = (1U << 21), /**< Number of bytes don't care in slave mode with SBC = 0 bit 21 */ 
	I2C_CR2_NBYTES6  = (1U << 22), /**< Number of bytes don't care in slave mode with SBC = 0 bit 22 */ 
	I2C_CR2_NBYTES7  = (1U << 23), /**< Number of bytes don't care in slave mode with SBC = 0 bit 23 */
	I2C_CR2_RELOAD   = (1U << 24), /**< NBYTES reload mode bit 24 */
	I2C_CR2_AUTOEND  = (1U << 25), /**< Master Automatic end mode bit 25*/	
	I2C_CR2_PECBYTE	 = (1U << 26), /**< Packet error checking bit 26 */
	I2C_CR2_HOLDACK	 = (1U << 28), /**< Packet error checking bit 26 */
	I2C_CR2_ACK_UPD	 = (1U << 29) /**< Packet error checking bit 26 */
} i2c_cr2_t;

/**
  * @brief I2C OAR1 Register
  */
typedef enum {
	I2C_OAR1_ADD0    = (1U << 0), /**< ADD0 BIT */
	I2C_OAR1_ADD1    = (1U << 1), /**< ADD1 BIT */
	I2C_OAR1_ADD2    = (1U << 2), /**< ADD2 BIT */
	I2C_OAR1_ADD3    = (1U << 3), /**< ADD3 BIT */
	I2C_OAR1_ADD4    = (1U << 4), /**< ADD4 BIT */
	I2C_OAR1_ADD5    = (1U << 5), /**< ADD5 BIT */
	I2C_OAR1_ADD6    = (1U << 6), /**< ADD6 BIT */
	I2C_OAR1_ADD7    = (1U << 7), /**< ADD7 BIT */
	I2C_OAR1_ADD8    = (1U << 8), /**< ADD8 BIT */
	I2C_OAR1_ADD9    = (1U << 9), /**< ADD9 BIT */
	I2C_OAR1_ADDMODE = (1U << 15) /**< ADDMODE BIT */
} i2c_oar1_t;

/**
  * @brief I2C OAR2 Register
  */
typedef enum {
	I2C_OAR2_ENDUAL = (1U << 0), /**< ENDUAL BIT */
	I2C_OAR2_ADD2   = (1U << 1)  /**< ADD2 BIT */
} i2c_oar2_t;

/**
  * @brief Interrupt Configuration Definition
  */
typedef enum {
	I2C_IT_TXE   = (1U << 0), /**< Transmit buffer empty interrupt */
	I2C_IT_TXOV  = (1U << 2), /**< Transmit buffer empty interrupt */
	I2C_IT_TXUD  = (1U << 3), /**< Transmit buffer empty interrupt */
	I2C_IT_TXTH  = (1U << 4), /**< Transmit buffer empty interrupt */
	I2C_IT_RXF   = (1U << 6), /**< Receive buffer not empty interrupt */
	I2C_IT_RXOV  = (1U << 7), /**< Address matched interrupt(salve mode) */
	I2C_IT_RXUD  = (1U << 8), /**< NACK reception interrupt (master mode)*/
	I2C_IT_RXTH  = (1U << 9), /**< Stop detection interrupt*/
	I2C_IT_TC    = (1U << 10), /**< Transfer complete interrupt */
	I2C_IT_TCR   = (1U << 11), /**< Transfer complete and Reload interrupt */
	I2C_IT_ADDR  = (1U << 12),
	I2C_IT_NACK  = (1U << 13),
	I2C_IT_STOP  = (1U << 14),
	I2C_IT_BERR  = (1U << 16), /**< Bus error interrupt */
	I2C_IT_ARLO  = (1U << 17), /**< Arbitration loss interrupt */
	I2C_IT_PEC   = (1U << 18), /**< PEC error interrupt */
	I2C_IT_TOUT  = (1U << 19), /**< Timeout interrupt */
	I2C_IT_ALERT = (1U << 20), /**< SMBus Alert interrupt */
} i2c_interrupt_t;

/**
 * @brief I2C Configuration Structure definition
 */
typedef struct {
	uint32_t clock_speed;                 /**< Specifies the clock frequency */
	i2c_autoend_t autoend_mode;           /**< Specifies the I2C autoend mode is selected */
	uint32_t own_address1;                /**< Specifies the first device own address */
	i2c_addr_t addressing_mode;           /**< Specifies addressing mode */
	i2c_dual_addr_t dual_address_mode;    /**< Specifies if dual addressing mode is selected */
	uint32_t own_address2;                /**< Specifies the second device own address */
	i2c_general_addr_t general_call_mode; /**< Specifies if general call mode is selected */
	i2c_nostretch_t no_stretch_mode;      /**< Specifies if nostretch mode is selected */
}i2c_init_t;

/**
  * @brief  I2C handle Structure definition
  */
typedef struct can_handle_s {
	I2C_TypeDef *perh;        /**< I2C registers base address */
	i2c_init_t init;          /**< I2C communication parameters */
	uint8_t *p_buff;          /**< Pointer to I2C transfer buffer */
	uint16_t xfer_size;       /**< I2C transfer size */
	__IO uint16_t xfer_count; /**< I2C transfer counter */
#ifdef HAL_DMA
	dma_handle_t hdmatx;      /**< I2C Tx DMA handle parameters */
	dma_handle_t hdmarx;      /**< I2C Rx DMA handle parameters */
#endif
	lock_state_t lock;        /**< I2C locking object */
	__IO i2c_state_t state;   /**< I2C communication state */
	__IO i2c_mode_t mode;     /**< I2C communication mode */
	__IO uint32_t error_code; /**< I2C Error code */

	void (*master_tx_cplt_cbk)(struct can_handle_s *arg); /**< Master Tx completed callback */
	void (*master_rx_cplt_cbk)(struct can_handle_s *arg); /**< Master Rx completed callback */
	void (*slave_tx_cplt_cbk)(struct can_handle_s *arg);  /**< Slave Tx completed callback */
	void (*slave_rx_cplt_cbk)(struct can_handle_s *arg);  /**< Slave Rx completed callback */
	void (*mem_tx_cplt_cbk)(struct can_handle_s *arg);    /**< Tx to Memory completed callback */
	void (*mem_rx_cplt_cbk)(struct can_handle_s *arg);    /**< Rx from Memory completed callback */
	void (*error_callback)(struct can_handle_s *arg);     /**< Error callback */
} i2c_handle_t;

/**
 * @}
 */

/** @defgroup I2C_Public_Macro I2C Public Macros
  * @{
  */
#define I2C_RESET_HANDLE_STATE(x) ((x)->state = I2C_STATE_RESET)
#define I2C_ENABLE_IT(x,y)   ((SET_BIT((x)->perh->IER.Word, (y))))				
#define I2C_DISABLE_IT(x,y)  (SET_BIT((x)->perh->IDR.Word, (y)))
#define I2C_CLEAR_IT(x,y)  (SET_BIT((x)->perh->ICR.Word, (y)))
#define I2C_GET_IT_SOURCE(x, y) ((((x)->perh->IFM.Word & (y))  == (y)) ? SET : RESET)
#define I2C_GET_IT_FLAG(x, y) ((((x)->perh->RIF.Word & (y))  == (y)) ? SET : RESET)
#define I2C_GET_FLAG(x, y) ((((x)->perh->SR.Word) & ((y) & I2C_FLAG_MASK)) != 0)
#define I2C_GET_DIR(x, y) ((((x)->perh->CR2.Word) & ((y) & I2C_FLAG_MASK)) != 0)
#define I2C_CLEAR_FLAG(x, y)  ((x)->perh->SR.Word = (((x)->perh->SR.Word) & (~((y) & I2C_FLAG_MASK))))
#define I2C_CLEAR_FCRFLAG(x, y) (((x)->perh->FCR.Word) = (((x)->perh->FCR.Word) | (y))) 
#define __I2C_CLEAR_STOPFLAG(x)                 \
do{                                             \
	__IO uint32_t tmpreg;                       \
	tmpreg = (x)->perh->SR1.Word;               \
	tmpreg = (x)->perh->CR1.Word |= I2C_CR1_PE; \
	UNUSED(tmpreg);                             \
}while(0)
#define __I2C_ENABLE(x)  ((x)->perh->CR1.PE = 1)
#define __I2C_DISABLE(x) ((x)->perh->CR1.PE = 0)
/**
  * @}
  */

/** @defgroup I2C_Private_Macro I2C Private Macros
  * @{
  */
#define IS_I2C_ADDRESSING_MODE(ADDRESS)				(((ADDRESS) == I2C_ADDRESSINGMODE_7BIT) || \
	((ADDRESS) == I2C_ADDRESSINGMODE_10BIT))
#define IS_I2C_DUAL_ADDRESS(ADDRESS)				(((ADDRESS) == I2C_DUALADDRESS_DISABLE) || \
	((ADDRESS) == I2C_DUALADDRESS_ENABLE))
#define IS_I2C_GENERAL_CALL(CALL)				(((CALL)    == I2C_GENERALCALL_DISABLE) || \
	((CALL)    == I2C_GENERALCALL_ENABLE))
#define IS_I2C_MEMADD_size(size)				(((size)    == I2C_MEMADD_SIZE_8BIT) || \
	((size)    == I2C_MEMADD_SIZE_16BIT))
#define IS_I2C_NO_STRETCH(STRETCH)				(((STRETCH) == I2C_NOSTRETCH_DISABLE) || \
	((STRETCH) == I2C_NOSTRETCH_ENABLE))
//#define IS_I2C_OWN_ADDRESS1(ADDRESS1)				(((ADDRESS1) & (uint32_t)(0xFFFFFC00)) == 0)
#define IS_I2C_OWN_ADDRESS1(ADDRESS1)				((ADDRESS1) != 0x00)
//#define IS_I2C_OWN_ADDRESS2(ADDRESS2)				(((ADDRESS2) & (uint32_t)(0xFFFFFF01)) == 0)
#define IS_I2C_OWN_ADDRESS2(ADDRESS2)				((ADDRESS1) != 0)
#define IS_I2C_CLOCK_SPEED(SPEED)				(((SPEED) > 0) && ((SPEED) == I2C_FAST_MODE_MAX_CLK) || \
	((SPEED) > 0) && ((SPEED) == I2C_STANDARD_MODE_MAX_CLK))
#define IS_I2C_DUTY_CYCLE(CYCLE)				(((CYCLE) == I2C_DUTYCYCLE_2) || \
	((CYCLE) == I2C_DUTYCYCLE_16_9))
#define I2C_FREQ_RANGE(__PCLK__)				((__PCLK__)/1000000)
#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__)			(((__SPEED__) <= I2C_STANDARD_MODE_MAX_CLK) ? ((__FREQRANGE__) + 1) :\
        ((((__FREQRANGE__) * 300) / 1000) + 1))
#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__)			(((((__PCLK__)/((__SPEED__) << 1)) & I2C_CCR_CCR) < 4)? 4:\
	((__PCLK__) / ((__SPEED__) << 1)))
#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__)	(((__DUTYCYCLE__) == I2C_DUTYCYCLE_2)? ((__PCLK__) / ((__SPEED__) * 3)) :\
        (((__PCLK__) / ((__SPEED__) * 25)) | I2C_DUTYCYCLE_16_9))
#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__)		(((__SPEED__) <= 100000)? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) :\
	((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0)? 1 : \
        ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS))
#define I2C_MEM_ADD_MSB(__ADDRESS__)				((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) &\
        (uint16_t)(0xFF00))) >> 8)))
#define I2C_MEM_ADD_LSB(__ADDRESS__)				((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FF))))
#define I2C_7BIT_ADD_WRITE(__ADDRESS__)				((uint8_t)((__ADDRESS__) & (~I2C_OAR1_ADD0)))
#define I2C_7BIT_ADD_READ(__ADDRESS__)				((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0))
#define I2C_10BIT_ADDRESS(__ADDRESS__)				((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FF))))
#define I2C_10BIT_HEADER_WRITE(__ADDRESS__)			((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) &\
        (uint16_t)(0x0300))) >> 7) | (uint16_t)(0xF0))))
#define I2C_10BIT_HEADER_READ(__ADDRESS__)			((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) &\
       (uint16_t)(0x0300))) >> 7) | (uint16_t)(0xF1))))
/**
  * @}
  */

/** @addtogroup I2C_Public_Functions
  * @{
  */

/** @addtogroup I2C_Public_Functions_Group1 Initialization and de-initialization functions
  * @{
  */
hal_status_t i2c_init(i2c_handle_t *hperh);
hal_status_t i2c_reset(i2c_handle_t *hperh);

/**
 * @}
 */

/** @addtogroup I2C_Public_Functions_Group2 Input and Output operation functions
 * @{
 */
 /** Blocking mode: Polling */
hal_status_t i2c_master_send(i2c_handle_t *hperh, uint16_t dev_addr,
                                 uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_master_recv(i2c_handle_t *hperh, uint16_t dev_addr,
                                uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_slave_send(i2c_handle_t *hperh, uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_slave_recv(i2c_handle_t *hperh, uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_mem_write(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                           i2c_addr_size_t add_size, uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_mem_read(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                          i2c_addr_size_t add_size, uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_is_device_ready(i2c_handle_t *hperh, uint16_t dev_addr, uint32_t trials, uint32_t timeout);

 /** Non-Blocking mode: Interrupt */
hal_status_t i2c_master_send_by_it(i2c_handle_t *hperh, uint16_t dev_addr, uint8_t *buf, uint16_t size);
hal_status_t i2c_master_recv_by_it(i2c_handle_t *hperh, uint16_t dev_addr, uint8_t *buf, uint16_t size);
hal_status_t i2c_slave_send_by_it(i2c_handle_t *hperh, uint8_t *buf, uint16_t size);
hal_status_t i2c_slave_recv_by_it(i2c_handle_t *hperh, uint8_t *buf, uint16_t size);
hal_status_t i2c_mem_write_by_it(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                              i2c_addr_size_t add_size, uint8_t *buf, uint16_t size);
hal_status_t i2c_mem_read_by_it(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                             i2c_addr_size_t add_size, uint8_t *buf, uint16_t size);

#ifdef HAL_DMA
 /** Non-Blocking mode: DMA */
hal_status_t i2c_master_send_by_dma(i2c_handle_t *hperh, uint16_t dev_addr,
                                     uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_master_recv_by_dma(i2c_handle_t *hperh, uint16_t dev_addr,
                                    uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_slave_send_by_dma(i2c_handle_t *hperh, uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_slave_recv_by_dma(i2c_handle_t *hperh, uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_mem_write_by_dma(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr, i2c_addr_size_t add_size,
                                 uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_mem_read_by_dma(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                                i2c_addr_size_t add_size, uint8_t *buf, uint16_t size, uint8_t channel);
#endif
/**
 * @}
 */

/** @addtogroup I2C_Public_Functions_Group3 Peripheral state and Errors functions
  * @{
  */
i2c_state_t i2c_get_state(i2c_handle_t *hperh);
uint32_t    i2c_get_error(i2c_handle_t *hperh);
/**
 * @}
 */

/** @addtogroup I2C_Public_Functions_Group4 IRQ Handler and Callbacks
 * @{
 */
void i2c_ev_irq_handler(i2c_handle_t *hperh);
void i2c_er_irq_handler(i2c_handle_t *hperh);
/**
 * @}
 */

/**
 * @}
 */

/**
  * @}
  */

/**
 * @}
 */
#ifdef __cplusplus
}
#endif

#endif /* __HAL_I2C_H__ */

/**
 *********************************************************************************
 *
 * @file    hal_i2c.h
 * @brief   Header file of I2C driver
 *
 * @version V1.0
 * @date    15 Nov 2017
 * @author  AE Team
 * @note
 *
 * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
 *
 ********************************************************************************
 */

#ifndef __HAL_I2C_H__
#define __HAL_I2C_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "utils.h"
#include "hal_dma.h"
#include "hal_cmu.h"

/** @addtogroup ES32FXXX_HAL
  * @{
  */

/** @addtogroup I2C
  * @{
  */

/** @defgroup I2C_Public_Types I2C Public Types
  * @{
  */
/**
  * @brief I2C Error Code
  */
typedef enum {
	I2C_ERROR_NONE    = 0x0,  /**< No error */
	I2C_ERROR_BERR    = 0x1,  /**< Berr error */
	I2C_ERROR_ARLO    = 0x2,  /**< Arlo error */
	I2C_ERROR_AF      = 0x4,  /**< Af error */
	I2C_ERROR_OVR     = 0x8,  /**< Ovr error */
	I2C_ERROR_DMA     = 0x10, /**< Dma error */
	I2C_ERROR_TIMEOUT = 0x20  /**< Timeout error */
} i2c_error_t;

/**
  * @brief I2C state structure definition
  */
typedef enum {
	I2C_STATE_RESET   = 0x0,  /**< Peripheral is not yet Initialized */
	I2C_STATE_READY   = 0x20, /**< Peripheral Initialized and ready for use */
	I2C_STATE_BUSY    = 0x24, /**< An internal process is ongoing */
	I2C_STATE_BUSY_TX = 0x21, /**< Data Transmission process is ongoing */
	I2C_STATE_BUSY_RX = 0x22, /**< Data Reception process is ongoing */
	I2C_STATE_TIMEOUT = 0xA0, /**< timeout state */
	I2C_STATE_ERROR   = 0xE0  /**< Error */
} i2c_state_t;

/**
  * @brief I2C Duty Cycle
  */
typedef enum {
	I2C_DUTYCYCLE_2    = 0x0,   /**< duty cycle is 2 */
	I2C_DUTYCYCLE_16_9 = 0x8000 /**< duty cycle is 16/9 */	
} i2c_duty_t;

/**
  * @brief I2C Addressing Mode
  */
typedef enum {
	I2C_ADDRESSINGMODE_7BIT  = 0x0, /**< 7 bit address */
	I2C_ADDRESSINGMODE_10BIT = 0x01  /**< 10 bit address */
} i2c_addr_t;

/**
  * @brief I2C Address
  */
typedef enum {
	ADDRESS1  = 0x46, /**< 7 bit address */
	ADDRESS2  = 0x23  /**< 10 bit address */
} i2c_saddr_t;
/**
  * @brief I2C Dual Addressing Mode
  */
typedef enum {
	I2C_DUALADDRESS_DISABLE = 0x0, /**< dual address is disable */
	I2C_DUALADDRESS_ENABLE  = 0x1  /**< dual address is enable */
} i2c_dual_addr_t;

/**
  * @brief I2C General Call Addressing mode
  */
typedef enum {
	I2C_GENERALCALL_DISABLE = 0x0, /**< general call address is disable */
	I2C_GENERALCALL_ENABLE  = 0x1 /**< general call address is enable */
} i2c_general_addr_t;

/**
  * @brief I2C Nostretch Mode
  */
typedef enum {
	I2C_NOSTRETCH_DISABLE = 0x0, /**< Nostretch disable */
	I2C_NOSTRETCH_ENABLE  = 0x1 /**< Nostretch enable */
} i2c_nostretch_t;

/**
  * @brief I2C Memory Address Size
  */
typedef enum {
	I2C_MEMADD_SIZE_8BIT  = 0x1, /**< 8 bit memory address size */
	I2C_MEMADD_SIZE_16BIT = 0x10 /**< 10 bit memory address size */
} i2c_addr_size_t;

/**
  * @brief I2C Flag Definition
  */
typedef enum {
	I2C_FLAG_TXE     = 0x00001, /**< Transmit data register empty Flag */
	I2C_FLAG_RXNE    = 0x00004, /**< Receive data register not empty Flag */
	I2C_FLAG_ADDR    = 0x00008, /**< Address matched (slave mode) Flag */
	I2C_FLAG_NACKF   = 0x00010, /**< Not Acknowledge received Flag */
	I2C_FLAG_STOPF   = 0x00020, /**< Stop detection Flag */
	I2C_FLAG_TC      = 0x00040, /**< Transfer Complete (master mode) Flag */
	I2C_FLAG_TCR     = 0x00080, /**< Transfer Complete Reload Flag */
	I2C_FLAG_BERR    = 0x00100, /**< Bus error Flag */
	I2C_FLAG_ARLO    = 0x00200, /**< Arbitration lost Flag */
	I2C_FLAG_OVR     = 0x00400, /**< Overrun/Underrun (slave mode) Flag */
	I2C_FLAG_PECERR  = 0x00800, /**< PEC Error in reception Flag */
	I2C_FLAG_TIMEOUT = 0x01000, /**< Timeout or tLOW detection Flag */
	I2C_FLAG_ALERT   = 0x02000, /**< SMBus alert Flag */
	I2C_FLAG_BUSY    = 0x08000, /**< Bus busy Flag */
	I2C_FLAG_DIR     = 0x10000, /**< Transfer direction (slave mode) */
	I2C_FLAG_MASK    = 0xFFFFF
} i2c_flag_t;

/**
  * @brief I2C mode structure definition
  */
typedef enum
{
	I2C_MODE_NONE   = 0x0,  /**< No I2C communication on going */
	I2C_MODE_MASTER = 0x10, /**< I2C communication is in Master mode */
	I2C_MODE_SLAVE  = 0x20, /**< I2C communication is in Slave mode */
	I2C_MODE_MEM    = 0x40  /**< I2C communication is in Memory mode */
}i2c_mode_t;

/**
  * @brief I2C Clock
  */
typedef enum {
	I2C_STANDARD_MODE_MAX_CLK = 100000, /**< Standard mode clock */
	I2C_FAST_MODE_MAX_CLK     = 400000  /**< Fast mode clock */
} i2c_clock_t;

/**
  * @brief I2C CR1 Register
  */
typedef enum {
	I2C_CFR_ADDRCF   = (1U << 3),  /**< ADDR Matched BIT */
	I2C_CFR_NACKCF   = (1U << 4),  /**< Not Acknowledge BIT */
	I2C_CFR_STOPCF   = (1U << 5),  /**< Stop detection  BIT */
	I2C_CFR_BERRCF   = (1U << 8),  /**< Bus error BIT */
	I2C_CFR_ARLOCF   = (1U << 9),  /**< Arbitration Lost BIT */
	I2C_CFR_OVRCF    = (1U << 10), /**< Overrun/Underrun  BIT */
	I2C_CFR_ALERTCF  = (1U << 13), /**< PEC Error BIT */
	I2C_CFR_TIMOUTCF = (1U << 12), /**< Timeout detection BIT */
	I2C_CFR_PECCF    = (1U << 11)  /**< Aler BIT */
} i2c_cfr_t;

/**
  * @brief I2C CR2 Register
  */
typedef enum {
	I2C_CR1_PE        = (1U << 0),  /**< Peripheral enable bit 0 */
	I2C_CR1_TXDMAEN   = (1U << 14), /**< DMA transmission requests bit 14 */
	I2C_CR1_RXDMAEN   = (1U << 15), /**< DMA reception requests bit 15 */
	I2C_CR1_SBC       = (1U << 16), /**< Slave byte control bit 16 */
	I2C_CR1_NOSTRETCH = (1U << 17), /**< Clock stretching bit 17 */
	I2C_CR1_GCEN      = (1U << 19),  /**< General call enable bit 19 */
	I2C_CR1_SMBHEN    = (1U << 20),  /**< SMBus Host address enable bit 20 */
	I2C_CR1_SMBDEN    = (1U << 21),  /**< SMBus Device Default address enable bit 21 */
	I2C_CR1_ALERTEN   = (1U << 22),  /**< SMBus alert enable bit 22 */
	I2C_CR1_PECEN     = (1U << 23),  /**< PEC enable bit 23 */
} i2c_cr1_t;

/**
  * @brief I2C CR2 Register
  */
typedef enum {
	I2C_CR2_SADD0    = (1U << 0),  /**< Slave address bit 0 */
	I2C_CR2_SADD1    = (1U << 1),  /**< Slave address bit 1 */
	I2C_CR2_SADD2    = (1U << 2),  /**< Slave address bit 2 */
	I2C_CR2_SADD3    = (1U << 3),  /**< Slave address bit 3 */
	I2C_CR2_SADD4    = (1U << 4),  /**< Slave address bit 4 */
	I2C_CR2_SADD5    = (1U << 5),  /**< Slave address bit 5 */
	I2C_CR2_SADD6    = (1U << 6),  /**< Slave address bit 6 */
	I2C_CR2_SADD7    = (1U << 7),  /**< Slave address bit 7 */
	I2C_CR2_SADD8    = (1U << 8),  /**< Slave address bit 8 */
	I2C_CR2_SADD9    = (1U << 9),  /**< Slave address bit 9 */
	I2C_CR2_RD_WRN   = (1U << 10), /**< Master Transfer direction bit 10 */
	I2C_CR2_ADD10    = (1U << 11), /**< Master 10-bit addressing mode bit 11 */
	I2C_CR2_HEAD10R  = (1U << 12), /**< Master 10-bit address headr Read mode bit 12 */
	I2C_CR2_START    = (1U << 13), /**< Master mode Start generation bit 13 */
	I2C_CR2_STOP     = (1U << 14), /**< Master mode Stop generation bit 14 */
	I2C_CR2_NACK     = (1U << 15), /**< Slave mode NACK generation bit 15 */
	I2C_CR2_NBYTES0  = (1U << 16), /**< Number of bytes don't care in slave mode with SBC = 0 bit 16 */
	I2C_CR2_NBYTES1  = (1U << 17), /**< Number of bytes don't care in slave mode with SBC = 0 bit 17 */ 
	I2C_CR2_NBYTES2  = (1U << 18), /**< Number of bytes don't care in slave mode with SBC = 0 bit 18 */ 
	I2C_CR2_NBYTES3  = (1U << 19), /**< Number of bytes don't care in slave mode with SBC = 0 bit 19 */ 
	I2C_CR2_NBYTES4  = (1U << 20), /**< Number of bytes don't care in slave mode with SBC = 0 bit 20 */ 
	I2C_CR2_NBYTES5  = (1U << 21), /**< Number of bytes don't care in slave mode with SBC = 0 bit 21 */ 
	I2C_CR2_NBYTES6  = (1U << 22), /**< Number of bytes don't care in slave mode with SBC = 0 bit 22 */ 
	I2C_CR2_NBYTES7  = (1U << 23), /**< Number of bytes don't care in slave mode with SBC = 0 bit 23 */
	I2C_CR2_RELOAD   = (1U << 24), /**< NBYTES reload mode bit 24 */
	I2C_CR2_AUTOEND  = (1U << 25), /**< Master Automatic end mode bit 25*/	
	I2C_CR2_PECBYTE	 = (1U << 26), /**< Packet error checking bit 26 */
} i2c_cr2_t;

/**
  * @brief I2C OAR1 Register
  */
typedef enum {
	I2C_OAR1_ADD0    = (1U << 0), /**< ADD0 BIT */
	I2C_OAR1_ADD1    = (1U << 1), /**< ADD1 BIT */
	I2C_OAR1_ADD2    = (1U << 2), /**< ADD2 BIT */
	I2C_OAR1_ADD3    = (1U << 3), /**< ADD3 BIT */
	I2C_OAR1_ADD4    = (1U << 4), /**< ADD4 BIT */
	I2C_OAR1_ADD5    = (1U << 5), /**< ADD5 BIT */
	I2C_OAR1_ADD6    = (1U << 6), /**< ADD6 BIT */
	I2C_OAR1_ADD7    = (1U << 7), /**< ADD7 BIT */
	I2C_OAR1_ADD8    = (1U << 8), /**< ADD8 BIT */
	I2C_OAR1_ADD9    = (1U << 9), /**< ADD9 BIT */
	I2C_OAR1_ADDMODE = (1U << 15) /**< ADDMODE BIT */
} i2c_oar1_t;

/**
  * @brief I2C OAR2 Register
  */
typedef enum {
	I2C_OAR2_ENDUAL = (1U << 0), /**< ENDUAL BIT */
	I2C_OAR2_ADD2   = (1U << 1)  /**< ADD2 BIT */
} i2c_oar2_t;

/**
  * @brief I2C SR1 Register
  */
typedef enum {
	I2C_SR1_SB       = (1U << 0),  /**< SB BIT */
	I2C_SR1_ADDR     = (1U << 1),  /**< ADDR  BIT */
	I2C_SR1_BTF      = (1U << 2),  /**< BTF BIT */
	I2C_SR1_ADD10    = (1U << 3),  /**< ADD10 BIT */
	I2C_SR1_STOPF    = (1U << 4),  /**< STOPF BIT */
	I2C_SR1_RXNE     = (1U << 6),  /**< RXNE BIT */
	I2C_SR1_TXE      = (1U << 7),  /**< TXE BIT */
	I2C_SR1_BERR     = (1U << 8),  /**< BERR BIT */
	I2C_SR1_ARLO     = (1U << 9),  /**< ARLO BIT */
	I2C_SR1_AF       = (1U << 10), /**< AF BIT */
	I2C_SR1_OVR      = (1U << 11), /**< OVR BIT */
	I2C_SR1_PECERR   = (1U << 12), /**< PECERR BIT */
	I2C_SR1_TIMEOUT  = (1U << 14), /**< TIMEOUT BIT */
	I2C_SR1_SMBALERT = (1U << 15)  /**< SMBALERT BIT */
} i2c_sr1_t;

/**
  * @brief I2C SR2 Register
  */
typedef enum {
	I2C_SR2_MSL        = (1U << 0), /**< MSL BIT */
	I2C_SR2_BUSY       = (1U << 1), /**< BUSY  BIT */
	I2C_SR2_TRA        = (1U << 2), /**< TRA BIT */
	I2C_SR2_GENCALL    = (1U << 4), /**< GENCALL BIT */
	I2C_SR2_SMBDEFAULT = (1U << 5), /**< SMBDEFAULT BIT */
	I2C_SR2_SMBHOST    = (1U << 6), /**< SMBHOST BIT */
	I2C_SR2_DUALF      = (1U << 7), /**< DUALF BIT */
	I2C_SR2_PEC        = (1U << 8)  /**< PEC BIT */
} i2c_sr2_t;

/**
  * @brief Interrupt Configuration Definition
  */
typedef enum {
	I2C_IT_TXE   = (1U << 0), /**< Transmit buffer empty interrupt */
	I2C_IT_RXNE  = (1U << 2), /**< Receive buffer not empty interrupt */
	I2C_IT_ADDR  = (1U << 3), /**< Address matched interrupt(salve mode) */
	I2C_IT_NACK  = (1U << 4), /**< NACK reception interrupt (master mode)*/
	I2C_IT_STOP  = (1U << 5), /**< Stop detection interrupt*/
	I2C_IT_TC    = (1U << 6), /**< Transfer complete interrupt */
	I2C_IT_TCR   = (1U << 7), /**< Transfer complete and Reload interrupt */
	I2C_IT_BERR  = (1U << 8), /**< Bus error interrupt */
	I2C_IT_ARLO  = (1U << 9), /**< Arbitration loss interrupt */
	I2C_IT_OVR   = (1U << 10), /**< Overrun/Underrun interrupt */
	I2C_IT_PEC   = (1U << 11), /**< PEC error interrupt */
	I2C_IT_TOUT  = (1U << 12), /**< Timeout interrupt */
	I2C_IT_ALERT = (1U << 13), /**< SMBus Alert interrupt */
} i2c_interrupt_t;

/**
  * @brief I2C TRISE Register
  */
typedef enum {
	I2C_TRISE_TRISE = 0x3F /**< TRISE BITS */
} i2c_trise_t;

/**
 * @brief I2C Configuration Structure definition
 */
typedef struct {
	uint32_t clock_speed;                 /**< Specifies the clock frequency */
//	i2c_duty_t duty_cycle;                /**< Specifies the I2C fast mode duty cycle */
	uint32_t own_address1;                /**< Specifies the first device own address */
	i2c_addr_t addressing_mode;           /**< Specifies addressing mode */
	i2c_dual_addr_t dual_address_mode;    /**< Specifies if dual addressing mode is selected */
	uint32_t own_address2;                /**< Specifies the second device own address */
	i2c_general_addr_t general_call_mode; /**< Specifies if general call mode is selected */
	i2c_nostretch_t no_stretch_mode;      /**< Specifies if nostretch mode is selected */
}i2c_init_t;

/**
  * @brief  I2C handle Structure definition
  */
typedef struct i2c_handle_s {
	I2C_TypeDef *perh;        /**< I2C registers base address */
	i2c_init_t init;          /**< I2C communication parameters */
	uint8_t *p_buff;          /**< Pointer to I2C transfer buffer */
	uint16_t xfer_size;       /**< I2C transfer size */
	__IO uint16_t xfer_count; /**< I2C transfer counter */
#ifdef HAL_DMA
	dma_handle_t hdmatx;      /**< I2C Tx DMA handle parameters */
	dma_handle_t hdmarx;      /**< I2C Rx DMA handle parameters */
#endif
	lock_state_t lock;        /**< I2C locking object */
	__IO i2c_state_t state;   /**< I2C communication state */
	__IO i2c_mode_t mode;     /**< I2C communication mode */
	__IO uint32_t error_code; /**< I2C Error code */

	void (*master_tx_cplt_cbk)(struct i2c_handle_s *arg); /**< Master Tx completed callback */
	void (*master_rx_cplt_cbk)(struct i2c_handle_s *arg); /**< Master Rx completed callback */
	void (*slave_tx_cplt_cbk)(struct i2c_handle_s *arg);  /**< Slave Tx completed callback */
	void (*slave_rx_cplt_cbk)(struct i2c_handle_s *arg);  /**< Slave Rx completed callback */
	void (*mem_tx_cplt_cbk)(struct i2c_handle_s *arg);    /**< Tx to Memory completed callback */
	void (*mem_rx_cplt_cbk)(struct i2c_handle_s *arg);    /**< Rx from Memory completed callback */
	void (*error_callback)(struct i2c_handle_s *arg);     /**< Error callback */
} i2c_handle_t;

/**
 * @}
 */

/** @defgroup I2C_Public_Macro I2C Public Macros
  * @{
  */
#define I2C_RESET_HANDLE_STATE(x) ((x)->state = I2C_STATE_RESET)
#define I2C_ENABLE_IT(x,y)   ((SET_BIT((x)->perh->IER.Word, (y))))				
#define I2C_DISABLE_IT(x,y)  (SET_BIT((x)->perh->IDR.Word, (y)))
#define I2C_CLEAR_IT(x,y)  (SET_BIT((x)->perh->ICR.Word, (y)))
#define I2C_GET_IT_SOURCE(x, y) ((((x)->perh->IFM.Word & (y))  == (y)) ? SET : RESET)
#define I2C_GET_FLAG(x, y) ((((x)->perh->SR.Word) & ((y) & I2C_FLAG_MASK)) != 0)
#define I2C_GET_DIR(x, y) ((((x)->perh->CR2.Word) & ((y) & I2C_FLAG_MASK)) != 0)
#define I2C_CLEAR_FLAG(x, y)  ((x)->perh->SR.Word = (((x)->perh->SR.Word) & (~((y) & I2C_FLAG_MASK))))
#define I2C_CLEAR_CFRFLAG(x, y) (((x)->perh->CFR.Word) = (((x)->perh->CFR.Word) | (y))) 
#define __I2C_CLEAR_STOPFLAG(x)                 \
do{                                             \
	__IO uint32_t tmpreg;                       \
	tmpreg = (x)->perh->SR1.Word;               \
	tmpreg = (x)->perh->CR1.Word |= I2C_CR1_PE; \
	UNUSED(tmpreg);                             \
}while(0)
#define __I2C_ENABLE(x)  ((x)->perh->CR1.PE = 1)
#define __I2C_DISABLE(x) ((x)->perh->CR1.PE = 0)
/**
  * @}
  */

/** @defgroup I2C_Private_Macro I2C Private Macros
  * @{
  */
#define IS_I2C_ADDRESSING_MODE(ADDRESS)				(((ADDRESS) == I2C_ADDRESSINGMODE_7BIT) || \
	((ADDRESS) == I2C_ADDRESSINGMODE_10BIT))
#define IS_I2C_DUAL_ADDRESS(ADDRESS)				(((ADDRESS) == I2C_DUALADDRESS_DISABLE) || \
	((ADDRESS) == I2C_DUALADDRESS_ENABLE))
#define IS_I2C_GENERAL_CALL(CALL)				(((CALL)    == I2C_GENERALCALL_DISABLE) || \
	((CALL)    == I2C_GENERALCALL_ENABLE))
#define IS_I2C_MEMADD_size(size)				(((size)    == I2C_MEMADD_SIZE_8BIT) || \
	((size)    == I2C_MEMADD_SIZE_16BIT))
#define IS_I2C_NO_STRETCH(STRETCH)				(((STRETCH) == I2C_NOSTRETCH_DISABLE) || \
	((STRETCH) == I2C_NOSTRETCH_ENABLE))
//#define IS_I2C_OWN_ADDRESS1(ADDRESS1)				(((ADDRESS1) & (uint32_t)(0xFFFFFC00)) == 0)
#define IS_I2C_OWN_ADDRESS1(ADDRESS1)				((ADDRESS1) != 0x00)
//#define IS_I2C_OWN_ADDRESS2(ADDRESS2)				(((ADDRESS2) & (uint32_t)(0xFFFFFF01)) == 0)
#define IS_I2C_OWN_ADDRESS2(ADDRESS2)				((ADDRESS1) != 0)
#define IS_I2C_CLOCK_SPEED(SPEED)				(((SPEED) > 0) && ((SPEED) == I2C_FAST_MODE_MAX_CLK) || \
	((SPEED) > 0) && ((SPEED) == I2C_STANDARD_MODE_MAX_CLK))
#define IS_I2C_DUTY_CYCLE(CYCLE)				(((CYCLE) == I2C_DUTYCYCLE_2) || \
	((CYCLE) == I2C_DUTYCYCLE_16_9))
#define I2C_FREQ_RANGE(__PCLK__)				((__PCLK__)/1000000)
#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__)			(((__SPEED__) <= I2C_STANDARD_MODE_MAX_CLK) ? ((__FREQRANGE__) + 1) :\
        ((((__FREQRANGE__) * 300) / 1000) + 1))
#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__)			(((((__PCLK__)/((__SPEED__) << 1)) & I2C_CCR_CCR) < 4)? 4:\
	((__PCLK__) / ((__SPEED__) << 1)))
#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__)	(((__DUTYCYCLE__) == I2C_DUTYCYCLE_2)? ((__PCLK__) / ((__SPEED__) * 3)) :\
        (((__PCLK__) / ((__SPEED__) * 25)) | I2C_DUTYCYCLE_16_9))
#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__)		(((__SPEED__) <= 100000)? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) :\
	((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0)? 1 : \
        ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS))
#define I2C_MEM_ADD_MSB(__ADDRESS__)				((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) &\
        (uint16_t)(0xFF00))) >> 8)))
#define I2C_MEM_ADD_LSB(__ADDRESS__)				((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FF))))
#define I2C_7BIT_ADD_WRITE(__ADDRESS__)				((uint8_t)((__ADDRESS__) & (~I2C_OAR1_ADD0)))
#define I2C_7BIT_ADD_READ(__ADDRESS__)				((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0))
#define I2C_10BIT_ADDRESS(__ADDRESS__)				((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FF))))
#define I2C_10BIT_HEADER_WRITE(__ADDRESS__)			((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) &\
        (uint16_t)(0x0300))) >> 7) | (uint16_t)(0xF0))))
#define I2C_10BIT_HEADER_READ(__ADDRESS__)			((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) &\
       (uint16_t)(0x0300))) >> 7) | (uint16_t)(0xF1))))
/**
  * @}
  */

/** @addtogroup I2C_Public_Functions
  * @{
  */

/** @addtogroup I2C_Public_Functions_Group1 Initialization and de-initialization functions
  * @{
  */
hal_status_t i2c_init(i2c_handle_t *hperh);
hal_status_t i2c_reset(i2c_handle_t *hperh);

/**
 * @}
 */

/** @addtogroup I2C_Public_Functions_Group2 Input and Output operation functions
 * @{
 */
 /** Blocking mode: Polling */
hal_status_t i2c_master_send(i2c_handle_t *hperh, uint16_t dev_addr,
                                 uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_master_recv(i2c_handle_t *hperh, uint16_t dev_addr,
                                uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_slave_send(i2c_handle_t *hperh, uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_slave_recv(i2c_handle_t *hperh, uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_mem_write(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                           i2c_addr_size_t add_size, uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_mem_read(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                          i2c_addr_size_t add_size, uint8_t *buf, uint16_t size, uint32_t timeout);
hal_status_t i2c_is_device_ready(i2c_handle_t *hperh, uint16_t dev_addr, uint32_t trials, uint32_t timeout);

 /** Non-Blocking mode: Interrupt */
hal_status_t i2c_master_send_by_it(i2c_handle_t *hperh, uint16_t dev_addr, uint8_t *buf, uint16_t size);
hal_status_t i2c_master_recv_by_it(i2c_handle_t *hperh, uint16_t dev_addr, uint8_t *buf, uint16_t size);
hal_status_t i2c_slave_send_by_it(i2c_handle_t *hperh, uint8_t *buf, uint16_t size);
hal_status_t i2c_slave_recv_by_it(i2c_handle_t *hperh, uint8_t *buf, uint16_t size);
hal_status_t i2c_mem_write_by_it(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                              i2c_addr_size_t add_size, uint8_t *buf, uint16_t size);
hal_status_t i2c_mem_read_by_it(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                             i2c_addr_size_t add_size, uint8_t *buf, uint16_t size);

#ifdef HAL_DMA
 /** Non-Blocking mode: DMA */
hal_status_t i2c_master_send_by_dma(i2c_handle_t *hperh, uint16_t dev_addr,
                                     uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_master_recv_by_dma(i2c_handle_t *hperh, uint16_t dev_addr,
                                    uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_slave_send_by_dma(i2c_handle_t *hperh, uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_slave_recv_by_dma(i2c_handle_t *hperh, uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_mem_write_by_dma(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr, i2c_addr_size_t add_size,
                                 uint8_t *buf, uint16_t size, uint8_t channel);
hal_status_t i2c_mem_read_by_dma(i2c_handle_t *hperh, uint16_t dev_addr, uint16_t mem_addr,
                                i2c_addr_size_t add_size, uint8_t *buf, uint16_t size, uint8_t channel);
#endif
/**
 * @}
 */

/** @addtogroup I2C_Public_Functions_Group3 Peripheral state and Errors functions
  * @{
  */
i2c_state_t i2c_get_state(i2c_handle_t *hperh);
uint32_t    i2c_get_error(i2c_handle_t *hperh);
/**
 * @}
 */

/** @addtogroup I2C_Public_Functions_Group4 IRQ Handler and Callbacks
 * @{
 */
void i2c_ev_irq_handler(i2c_handle_t *hperh);
void i2c_er_irq_handler(i2c_handle_t *hperh);
/**
 * @}
 */

/**
 * @}
 */

/**
  * @}
  */

/**
 * @}
 */
#ifdef __cplusplus
}
#endif

#endif /* __HAL_I2C_H__ */
