/*!
 * @file       apm32f10x_i2c.h
 *
 * @brief      This file contains all the functions prototypes for the I2C firmware library
 *
 * @version    V1.0.0
 *
 * @date       2019-8-6
 *
 */

#ifndef __APM32F10x_CRC_H
#define __APM32F10x_CRC_H

#ifdef __cplusplus
extern "C" {
#endif

#include "apm32f10x.h"

/**
 * @brief I2C Mode
 */
typedef enum
{
  I2C_MODE_I2C = 0x0000,
  I2C_MODE_SMBUUSDEVICE = 0x0002,
  I2C_MODE_SMBUSHOST = 0x000A
} I2C_MODE_T;

/**
 * @brief I2C duty cycle in fast mode
 */
typedef enum
{
  I2C_DUTYCYCLE_16_9 = 0x4000,
  I2C_DUTYCYCLE_2 = 0xBFFF
} I2C_DUTYCYCLE_T;

/**
 * @brief I2C acknowledgement
 */
typedef enum
{
  I2C_ACK_DISABLE,
  I2C_ACK_ENABLE
} I2C_ACK_T;

/**
 * @brief I2C acknowledged address
 */
typedef enum
{
  I2C_ACKNOWLEDFEADDRESS_7BIT = 0x4000,
  I2C_ACKNOWLEDFEADDRESS_10BIT = 0xC000
} I2C_ACKNOWLEDFEADDRESS_T;



/**
 * @brief I2C Config structure definition
 */
typedef struct
{
  uint32_t I2C_CLOCKSPEED;
  I2C_MODE_T I2C_MODE;
  I2C_DUTYCYCLE_T I2C_DUTYCYCLE;
  uint16_t I2C_OWNADDRESS1;
  I2C_ACK_T I2C_ACK;
  I2C_ACKNOWLEDFEADDRESS_T I2C_ACKNOWLEDFEADDRESS;
} I2C_CONFIG_T;

/**
 * @brief I2C interrupts definition
 */
typedef enum
{
  I2C_INT_BUF = 0x0400,
  I2C_INT_EVT = 0x0200,
  I2C_INT_ERR = 0x0100
} I2C_INT_CONFIG_T;

/**
 * @brief I2C transfer direction
 */

typedef enum
{
  I2C_DIRECTION_TRANSMITTER,
  I2C_DIRECTION_RECEIVER
} I2C_TRANSFER_DIRECTION_T;

/**
 * @brief I2C Register
 */
typedef enum
{
  I2C_REGISTER_CTRL1,
  I2C_REGISTER_CTRL2,
  I2C_REGISTER_ADD1,
  I2C_REGISTER_ADD2,
  I2C_REGISTER_DATA,
  I2C_REGISTER_STS1,
  I2C_REGISTER_STS2,
  I2C_REGISTER_CLKCTRL,
  I2C_REGISTER_TRISE,
  I2C_REGISTER_SWITCH
} I2C_REGISTER_T;

/**
 * @brief I2C NCAK position
 */
typedef enum
{
  I2C_NACK_POSITION_NEXT ,
  I2C_NACK_POSITION_CURRENT
} I2C_NACK_POSITION_T;

/**
 * @brief I2C SMBus alert pin level
 */
typedef enum
{
  I2C_SMBUSALER_LOW,
  I2C_SMBUSALER_HIGH
} I2C_SMBUSALER_T;

/**
 * @brief I2C TPEC position
 */
typedef enum
{
  I2C_TPEC_POSITION_NEXT,
  I2C_TPEC_POSITION_CURRENT
} I2C_TPEC_POSITION_T;

/**
 * @brief I2C Events
 */
typedef enum
{
  /* --EV5 */
  I2C_EVENT_MASTER_MODE_SELECT                       = 0x00030001,  /* BUSY, MSL and SB flag */

  /* --EV6 */
  I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED         = 0x00070082,  /* BUSY, MSL, ADDR, TXE and TRA flags */
  I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED            = 0x00030002,  /* BUSY, MSL and ADDR flags */
  /* --EV9 */
  I2C_EVENT_MASTER_MODE_ADDRESS10                    = 0x00030008,  /* BUSY, MSL and ADD10 flags */

  /* Master RECEIVER mode -----------------------------*/
  /* --EV7 */
  I2C_EVENT_MASTER_BYTE_RECEIVED                     = 0x00030040,  /* BUSY, MSL and RXNE flags */

  /* Master TRANSMITTER mode --------------------------*/
  /* --EV8 */
  I2C_EVENT_MASTER_BYTE_TRANSMITTING                  = 0x00070080, /* TRA, BUSY, MSL, TXE flags */
  /* --EV8_2 */
  I2C_EVENT_MASTER_BYTE_TRANSMITTED                  = 0x00070084,  /* TRA, BUSY, MSL, TXE and BTF flags */


  /* --EV1  (all the events below are variants of EV1, */
  /* 1, Case of One Single Address managed by the slave */
  I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED           = 0x00020002, /* BUSY and ADDR flags */
  I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED        = 0x00060082, /* TRA, BUSY, TXE and ADDR flags */

  /* 2, Case of Dual address managed by the slave */
  I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED     = 0x00820000,  /* DUALF and BUSY flags */
  I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED  = 0x00860080,  /* DUALF, TRA, BUSY and TXE flags */

  /* 3, Case of General Call enabled for the slave */
  I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED         = 0x00120000,  /* GENCALL and BUSY flags */


  /* Slave RECEIVER mode --------------------------*/
  /* --EV2 */
  I2C_EVENT_SLAVE_BYTE_RECEIVED                      = 0x00020040,  /* BUSY and RXNE flags */
  /* --EV4  */
  I2C_EVENT_SLAVE_STOP_DETECTED                      = 0x00000010,  /* STOPF flag */

  /* Slave TRANSMITTER mode -----------------------*/
  /* --EV3 */
  I2C_EVENT_SLAVE_BYTE_TRANSMITTED                   = 0x00060084,  /* TRA, BUSY, TXE and BTF flags */
  I2C_EVENT_SLAVE_BYTE_TRANSMITTING                  = 0x00060080,  /* TRA, BUSY and TXE flags */
  /* --EV3_2 */
  I2C_EVENT_SLAVE_ACK_FAILURE                        = 0x00000400,  /* AF flag */

} I2C_EVENT_T;

/**
 * @brief I2C  flags
 */
typedef enum
{
  /**
   * @brief  SR2 register flags
   */

  I2C_FLAG_DAMF,
  I2C_FLAG_SMB_HHF ,
  I2C_FLAG_SMB_DAF ,
  I2C_FLAG_RBF ,
  I2C_FLAG_RWMF ,
  I2C_FLAG_BUSYF,
  I2C_FLAG_MMF,

  /**
   * @brief  SR1 register flags
   */

  I2C_FLAG_SMB_ALTF,
  I2C_FLAG_TIMEOUT,
  I2C_FLAG_PECEF,
  I2C_FLAG_OUR,
  I2C_FLAG_AEF,
  I2C_FLAG_ALF,
  I2C_FLAG_BEF,
  I2C_FLAG_TXBEF,
  I2C_FLAG_RXBENF,
  I2C_FLAG_SBDF,
  I2C_FLAG_ADDR10F,
  I2C_FLAG_BTCF,
  I2C_FLAG_ADDRF,
  I2C_FLAG_SBTCF,
} I2C_FLAG_T;

/**
 * @brief I2C interrupt
 */
typedef enum
{
  I2C_INT_SMB_ALTF = 0x01008000,
  I2C_INT_TIMEOUT  = 0x01004000,
  I2C_INT_PECEF    = 0x01001000,
  I2C_INT_OUR      = 0x01000800,
  I2C_INT_AEF      = 0x01000400,
  I2C_INT_ALF      = 0x01000200,
  I2C_INT_BEF      = 0x01000100,
  I2C_INT_TXBEF    = 0x06000080,
  I2C_INT_RXBENF   = 0x06000040,
  I2C_INT_SBDF     = 0x02000010,
  I2C_INT_ADDR10F  = 0x02000008,
  I2C_INT_BTCF     = 0x02000004,
  I2C_INT_ADDRF    = 0x02000002,
  I2C_INT_SBTCF    = 0x02000001,
} I2C_INT_T;

/*  Function used to set the I2C configuration to the default reset state *****/
void I2C_Reset(I2C_T* I2Cx);

/* Initialization and Configuration functions *********************************/
void I2C_Config(I2C_T* I2Cx, I2C_CONFIG_T* i2c_Config);
void I2C_StructInit(I2C_CONFIG_T* i2c_Config);
void I2C_Enable(I2C_T* I2Cx);
void I2C_Disable(I2C_T* I2Cx);
void I2C_EnableGenerateSTART(I2C_T* I2Cx);
void I2C_DisableGenerateSTART(I2C_T* I2Cx);
void I2C_EnableGenerateSTOP(I2C_T* I2Cx);
void I2C_DisableGenerateSTOP(I2C_T* I2Cx);
void I2C_EnableAcknowledge(I2C_T* I2Cx);
void I2C_DisableAcknowledge(I2C_T* I2Cx);
void I2C_SetOwnAddress2(I2C_T* I2Cx, uint8_t address);
void I2C_EnableDualAddress(I2C_T* I2Cx);
void I2C_DisableDualAddress(I2C_T* I2Cx);
void I2C_EnableGeneralCall(I2C_T* I2Cx);
void I2C_DisableGeneralCall(I2C_T* I2Cx);

/* Transmit Configuration functions *********************************************************/
void I2C_SendData(I2C_T* I2Cx, uint8_t data);
uint8_t I2C_RecevieData(I2C_T* I2Cx);
void I2C_Send7bitAddress(I2C_T* I2Cx, uint8_t address, I2C_TRANSFER_DIRECTION_T i2c_Direction);
uint16_t I2C_ReadRegister(I2C_T* I2Cx, I2C_REGISTER_T i2c_register);
void I2C_ResetSoftwareEnable(I2C_T* I2Cx);
void I2C_ResetSoftwareDisable(I2C_T* I2Cx);
void I2C_NACKPositionConfig(I2C_T* I2Cx, I2C_NACK_POSITION_T i2c_NACKPosition);
void I2C_SMBusAlertConfig(I2C_T* I2Cx, I2C_SMBUSALER_T i2c_SMBus_State);
void I2C_EnableTransmitTPEC(I2C_T* I2Cx);
void I2C_DisableTransmitTPEC(I2C_T* I2Cx);
void I2C_TPECPositionConfig(I2C_T* I2Cx, I2C_TPEC_POSITION_T i2c_TPECPosition);
void I2C_EnableCalculatePEC(I2C_T* I2Cx);
void I2C_DisableCalculatePEC(I2C_T* I2Cx);
uint8_t I2C_ReadPEC(I2C_T* I2Cx);
void I2C_EnableARP(I2C_T* I2Cx);
void I2C_DisableARP(I2C_T* I2Cx);
void I2C_EnableStretchClock(I2C_T* I2Cx);
void I2C_DisableStretchClock(I2C_T* I2Cx);
void I2C_FastModeDutyCycleConfig(I2C_T* I2Cx, I2C_DUTYCYCLE_T i2c_dutyCycle);

/* DMA functions *********************************************************/
void I2C_EnableDMA(I2C_T* I2Cx);
void I2C_DisableDMA(I2C_T* I2Cx);
void I2C_DMALastTransferEnable(I2C_T* I2Cx);
void I2C_DMALastTransferDisable(I2C_T* I2Cx);

/* Interrupts and flags management functions **********************************/
void I2C_EnableInt(I2C_T* I2Cx, I2C_INT_CONFIG_T i2c_INT);
void I2C_DisableInt(I2C_T* I2Cx, I2C_INT_CONFIG_T i2c_INT);
uint8_t  I2C_CheckEvent(I2C_T* I2Cx, I2C_EVENT_T i2c_Event);
uint32_t I2C_ReadLastEvent(I2C_T* I2Cx);
uint8_t I2C_ReadFlagStatus(I2C_T* I2Cx, I2C_FLAG_T i2c_Flag);
void I2C_ClearFlag(I2C_T* I2Cx, I2C_FLAG_T i2c_Flag);
uint8_t I2C_ReadINTStatus(I2C_T* I2Cx, I2C_INT_T i2c_INT);
void I2C_ClearINTFlag(I2C_T* I2Cx, I2C_INT_T i2c_INT);
 

#ifdef __cplusplus
}
#endif

#endif /* __APM32F10x_I2C_H */
