/******************************************************************************
*@file  : spl_i2c.h
*@brief : Header file of I2C SPL module.
******************************************************************************/

#ifndef __SPL_I2C_H__
#define __SPL_I2C_H__

#include "acm32g103_spl_conf.h"

/**************  Bit definition for I2C SLAVE ADDR2/3 register  **************/
#define I2C_ADDR3_EN                        BIT8
#define I2C_ADDR2_EN                        BIT0

/**************  Bit definition for I2C TIMEOUT register  **************/
#define I2C_TIMEOUT_EXTEN                   BIT31
#define I2C_TOUTB_INTEN                     BIT30
#define I2C_EXT_MODE                        BIT29
#define I2C_TIMEOUT_TIMOUTEN                BIT15
#define I2C_TOUTA_INTEN                     BIT14

/** @defgroup I2C_MODE
 *  @{
 */
#define    I2C_MODE_SLAVE     (0U)
#define    I2C_MODE_MASTER    (1U)
/**
  * @}
  */

/** @defgroup CLOCK_SPEED
 *  @{
 */
#define    CLOCK_SPEED_STANDARD     (100000U)
#define    CLOCK_SPEED_FAST         (400000U)
#define    CLOCK_SPEED_FAST_PLUS    (1000000U)
/**
  * @}
  */


/** @defgroup TX_AUTO_EN
 *  @{
 */
#define    TX_AUTO_DISABLE    (0U)
#define    TX_AUTO_ENABLE     (1U)
/**
  * @}
  */


/** @defgroup STRETCH_MODE
 *  @{
 */
#define    STRETCH_MODE_ENABLE      (0U)
#define    STRETCH_MODE_DISABLE    (1U)
/**
  * @}
  */
  
/** @defgroup FILTER_ALGO_ENABLE     
 *  @{
 */
#define    FILTER_ALGO_DISABLE      (0U)
#define    FILTER_ALGO_ENABLE       (1U)   
/**
  * @}
  */  

  
 /** @defgroup I2C_Memory_Address_Size I2C Memory Address Size
  * @{
  */
#define I2C_MEMADD_SIZE_8BIT            (0U)
#define I2C_MEMADD_SIZE_16BIT           (1U)
/**
  * @}
  */
 

/* Private macros ------------------------------------------------------------*/
/** @defgroup I2C_Private_Macros I2C Private Macros
  * @{
  */
#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)))
 
/**
  * @brief  I2C Configuration Structure definition
  */
  
#define _I2C_GET_FLAG(__HANDLE__, __FLAG__)   ((((__HANDLE__->SR) & (__FLAG__))  == (__FLAG__) ) ? 1 : 0) 


typedef struct
{
    uint32_t  I2C_Mode;             /* This parameter can be a value of @ref I2C_MODE */
    
    uint32_t  Tx_Auto_En;           /* This parameter can be a value of @ref TX_AUTO_EN */
    
    uint32_t  Stretch_Mode;         /* This parameter can be a value of @ref NO_STRETCH_MODE */
        
    uint32_t  Own_Address;          /* This parameter can be a 7-bit address */
    
    uint32_t  Clock_Speed;          /* This parameter can be a value of @ref CLOCK_SPEED */
    
    uint32_t  filter_enable;        /* This parameter can be a value of @ref FILTER_ALGO_DISABLE */    
} I2C_InitTypeDef;

/** @defgroup I2C_registers 
  * @{
  */

#define I2C_Register_ADDR1            ((uint8_t)0x00)
#define I2C_Register_CLKDIV           ((uint8_t)0x04)
#define I2C_Register_CR               ((uint8_t)0x08)
#define I2C_Register_SR               ((uint8_t)0x0C)
#define I2C_Register_DR               ((uint8_t)0x10)
#define I2C_Register_ADDR2_3          ((uint8_t)0x14)
#define I2C_Register_TIMEOUT          ((uint8_t)0x24)
#define IS_I2C_REGISTER(REGISTER) (((REGISTER) == I2C_Register_ADDR1) || \
                                   ((REGISTER) == I2C_Register_CLKDIV) || \
                                   ((REGISTER) == I2C_Register_CR) || \
                                   ((REGISTER) == I2C_Register_SR) || \
                                   ((REGISTER) == I2C_Register_DR) || \
                                   ((REGISTER) == I2C_Register_ADDR2_3) || \
                                   ((REGISTER) == I2C_Register_TIMEOUT))
/**
  * @}
  */



/** @defgroup I2C_transfer_direction 
  * @{
  */\
#define  I2C_Direction_Transmitter      ((uint8_t)0x00)
#define  I2C_Direction_Receiver         ((uint8_t)0x01)
#define  IS_I2C_DIRECTION(DIRECTION) (((DIRECTION) == I2C_Direction_Transmitter) || ((DIRECTION) == I2C_Direction_Receiver))
									 
/**
  * @}
  */
  
  
/** 
  * @brief  I2C_Exported_Constants 
  */
#define IS_I2C_MODE(I2C_MODE)    (((I2C_MODE) == I2C_MODE_SLAVE) || \
                                      ((I2C_MODE) == I2C_MODE_MASTER))

#define IS_I2C_CLOCK_SPEED(CLOCK_SPEED)    (((CLOCK_SPEED) > 0U) && ((CLOCK_SPEED) <=1000000U))

#define IS_I2C_TX_AUTO_EN(TX_AUTO_EN)      (((TX_AUTO_EN) == TX_AUTO_EN_DISABLE) || \
                                            ((TX_AUTO_EN) == TX_AUTO_EN_ENABLE))

#define IS_I2C_STRETCH_EN(STRETCH_EN)    (((STRETCH_EN) == NO_STRETCH_MODE_STRETCH) || \
                                          ((STRETCH_EN) == NO_STRETCH_MODE_NOSTRETCH))

#define IS_I2C_ALL_PERIPH(PERIPH) (((PERIPH) == I2C1) || ((PERIPH) == I2C2))

#define IS_I2C_CLEAR_FLAG(I2C_FLAG)    (((I2C_FLAG) == I2C_SR_STARTF)    || \
                                        ((I2C_FLAG) == I2C_SR_STOPF)     || \
                                        ((I2C_FLAG) == I2C_SR_TX_RX_FLAG)   || \
                                        ((I2C_FLAG) == I2C_SR_MTF)         || \
                                        ((I2C_FLAG) == I2C_SR_RX_ADDR1)   || \
                                        ((I2C_FLAG) == I2C_SR_TXE)   || \
                                        ((I2C_FLAG) == I2C_SR_RXNE)   || \
                                        ((I2C_FLAG) == I2C_SR_RX_ADDR2)   || \
                                        ((I2C_FLAG) == I2C_SR_DETR)   || \
                                        ((I2C_FLAG) == I2C_SR_RX_ADDR3)   || \
                                        ((I2C_FLAG) == I2C_SR_TIMEOUTAF)   || \
                                        ((I2C_FLAG) == I2C_SR_TIMEOUTBF))
                                        

/**
  * @}
  */


void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);
void I2C_DeInit(I2C_TypeDef* I2Cx);

void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
void I2C_ITConfig(I2C_TypeDef* I2Cx, uint32_t I2C_IT, FunctionalState NewState);

void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_GenerateNACK(I2C_TypeDef* I2Cx, FunctionalState NewState);

void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address);
void OwnAddress2Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_OwnAddress3Config(I2C_TypeDef* I2Cx, uint8_t Address);
void OwnAddress3Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

uint32_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register);

void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);

uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);


#endif
