/*!
    \file  gd32f4xx_i2c.c
    \brief I2C driver

*/

/*
    Copyright (C) 2016 GigaDevice

    2016-08-15, V1.0.1, firmware for GD32F4xx
*/

#include "gd32f4xx_i2c.h"

#define I2CCLK_MAX                    0x3fU              /*!< i2cclk max value */
#define I2C_STATE_MASK                0x0000FFFFU        /*!< i2c state mask */

/*!
    \brief      reset I2C
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     none
*/
void i2c_deinit(uint32_t i2c_periph)
{
    switch(i2c_periph){
    case I2C0:
        rcu_periph_reset_enable(RCU_I2C0RST);
        rcu_periph_reset_disable(RCU_I2C0RST);
        break;
    case I2C1:
        rcu_periph_reset_enable(RCU_I2C1RST);
        rcu_periph_reset_disable(RCU_I2C1RST);
        break;
    case I2C2:
        rcu_periph_reset_enable(RCU_I2C2RST);
        rcu_periph_reset_disable(RCU_I2C2RST);
        break;
    default:
        break;
    
    }
}

/*!
    \brief      I2C clock configure
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  clkspeed: i2c clock speed   
    \param[in]  dutycyc: duty cycle in fast mode
      \arg        I2C_DTCY_2:    T_low/T_high=2 
      \arg        I2C_DTCY_16_9: T_low/T_high=16/9
    \param[out] none
    \retval     none
*/
void i2c_clock_config(uint32_t i2c_periph,uint32_t clkspeed,uint32_t dutycyc)
{
    uint32_t pclk1,clkc,freq,risetime;
    uint32_t temp;
    
    pclk1 = rcu_clock_freq_get(CK_APB1);
    /* I2C peripheral clock frequency */
    freq = (uint32_t)(pclk1/1000000U);
    if(freq >= I2CCLK_MAX){
        freq = I2CCLK_MAX;
    }
    
    temp = I2C_CTL1(i2c_periph);
    temp &= ~I2C_CTL1_I2CCLK;
    temp |= freq;
    
    I2C_CTL1(i2c_periph) = temp;
    
    if(100000U >= clkspeed){
        /* the maximum SCL rise time is 1000ns instandard mode */
        risetime = (uint32_t)((pclk1/1000000U)+1U);
        if(risetime >= I2CCLK_MAX){
            I2C_RT(i2c_periph) = I2CCLK_MAX;
        }else{
            I2C_RT(i2c_periph) = risetime;
        }
        clkc = (uint32_t)(pclk1/(clkspeed*2U)); 
        if(clkc < 0x04U){
            /* the CLKC in standard mode minmum value is 4 */
            clkc = 0x04U;
        }
        
        I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc);

    }else if(400000U >= clkspeed){
        /* the maximum SCL rise time is 300ns in fast mode */
        I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U);
        if(I2C_DTCY_2 == dutycyc){
            /* I2C_DutyCycle == 2 */
            clkc = (uint32_t)(pclk1/(clkspeed*3U));
            I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
        }else{
            /* I2C_DutyCycle == 16/9 */
            clkc = (uint32_t)(pclk1/(clkspeed*25U));
            I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
        }
        if(0U == (clkc & I2C_CKCFG_CLKC)){
            /* the CLKC in fast mode minmum value is 1 */
            clkc |= 0x0001;  
        }
        I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
        I2C_CKCFG(i2c_periph) |= clkc;
    }
}

/*!
    \brief      I2C address configure
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  i2cmod:
      \arg        I2C_I2CMODE_ENABLE:  I2C mode
      \arg        I2C_SMBUSMODE_ENABLE: SMBus mode
    \param[in]  addformat: 7bits or 10bits
      \arg        I2C_ADDFORMAT_7BITS:  7bits
      \arg        I2C_ADDFORMAT_10BITS: 10bits
    \param[in]  addr: I2C address
    \param[out] none
    \retval     none
*/
void i2c_mode_addr_config(uint32_t i2c_periph,uint32_t i2cmod,uint32_t addformat,uint32_t addr)
{
    /* SMBus/I2C mode selected */
    uint32_t ctl = 0U;
    ctl = I2C_CTL0(i2c_periph);
    ctl &= ~(I2C_CTL0_SMBEN); 
    ctl |= i2cmod;
    I2C_CTL0(i2c_periph) = ctl;
    /* configure address */
    I2C_SADDR0(i2c_periph) = (addformat|addr);
    
}

/*!
    \brief      SMBus type selection
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  ack:
      \arg        I2C_SMBUS_DEVICE: device
      \arg        I2C_SMBUS_HOST: host
    \param[out] none
    \retval     none
*/
void i2c_smbus_type_config(uint32_t i2c_periph,uint32_t type)
{
    if(I2C_SMBUS_HOST == type){
       I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL;  
    }else{
       I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL);  
    } 
}

/*!
    \brief      whether or not to send an ACK
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  ack:
      \arg        I2C_ACK_ENABLE: ACK will be sent  
      \arg        I2C_ACK_DISABLE: ACK will not be sent    
    \param[out] none
    \retval     none
*/
void i2c_ack_config(uint32_t i2c_periph,uint8_t ack)
{
    if(I2C_ACK_ENABLE == ack){
       I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN;  
    }else{
       I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN);  
    } 
}

/*!
    \brief      I2C POAP position configure
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  pos:
      \arg        I2C_ACK_ENABLE: ACK will be sent  
      \arg        I2C_ACK_DISABLE: ACK will not be sent
    \param[out] none
    \retval     none
*/
void i2c_ackpos_config(uint32_t i2c_periph,uint8_t pos)
{
    /* configure i2c POAP position */
    if(I2C_ACKPOS_NEXT == pos){
       I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP;  
    }else{
       I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP);  
    } 

}

/*!
    \brief      master send slave address
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  addr: slave address  
    \param[in]  trandirection: transmitter or receiver
      \arg        I2C_TRANSMITTER: transmitter  
      \arg        I2C_RECEIVER:    receiver  
    \param[out] none
    \retval     none
*/
void i2c_master_addressing(uint32_t i2c_periph,uint8_t addr,uint32_t trandirection)
{
    if(I2C_TRANSMITTER==trandirection){
        addr = (uint8_t)((uint32_t)addr & I2C_TRANSMITTER);
    }else{
        addr = (uint8_t)((uint32_t)addr|I2C_RECEIVER);
    }
    I2C_DATA(i2c_periph) = addr;
}

/*!
    \brief      dual-address mode switch
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  dualaddr:
      \arg        I2C_DUADEN_DISABLE: dual-address mode disabled  
      \arg        I2C_DUADEN_ENABLE: dual-address mode enabled
    \param[out] none
    \retval     none
*/
void i2c_dualaddr_enable(uint32_t i2c_periph,uint8_t dualaddr)
{
    if(I2C_DUADEN_ENABLE == dualaddr){
       I2C_SADDR1(i2c_periph) |= I2C_SADDR1_DUADEN;  
    }else{
       I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN);  
    }        
}

/*!
    \brief      enable i2c
    \param[in]  i2c_periph: I2Cx(x=0,1,2) 
    \param[out] none
    \retval     none
*/
void i2c_enable(uint32_t i2c_periph)
{
    I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN;
}

/*!
    \brief      disable i2c
    \param[in]  i2c_periph: I2Cx(x=0,1,2) 
    \param[out] none
    \retval     none
*/
void i2c_disable(uint32_t i2c_periph)
{
    I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN);
    
}

/*!
    \brief      generate a START condition on I2C bus
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     none
*/
void i2c_start_on_bus(uint32_t i2c_periph)
{
    I2C_CTL0(i2c_periph) |= I2C_CTL0_START;
}

/*!
    \brief      generate a STOP condition on I2C bus
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     none
*/
void i2c_stop_on_bus(uint32_t i2c_periph)
{
    I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP;
}

/*!
    \brief      i2c transmit data function
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  data: data of transmission 
    \param[out] none
    \retval     none
*/
void i2c_transmit_data(uint32_t i2c_periph,uint8_t data)
{
    I2C_DATA(i2c_periph) = data;
}

/*!
    \brief      i2c receive data function
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     data of received
*/
uint8_t i2c_receive_data(uint32_t i2c_periph)
{
    return (uint8_t)I2C_DATA(i2c_periph); 
}

/*!
    \brief      I2C DMA mode enable
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  dmastste: 
      \arg        I2C_DMA_ON: DMA mode enabled
      \arg        I2C_DMA_OFF: DMA mode disabled
    \param[out] none
    \retval     none
*/
void i2c_dma_enable(uint32_t i2c_periph,uint32_t dmastste)
{
    /* configure i2c DMA function */
    uint32_t ctl = 0U;
    ctl = I2C_CTL1(i2c_periph);
    ctl &= ~(I2C_CTL1_DMAON); 
    ctl |= dmastste;
    I2C_CTL1(i2c_periph) = ctl;

}

/*!
    \brief      flag indicating DMA last transfer
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  dmastste: 
      \arg        I2C_DMALST_ON: next DMA EOT is the last transfer
      \arg        I2C_DMALST_OFF: next DMA EOT is not the last transfer
    \param[out] none
    \retval     none
*/
void i2c_dma_last_transfer_enable(uint32_t i2c_periph,uint32_t dmalast)
{
    /* configure DMA last transfer */
    uint32_t ctl = 0U;
    ctl = I2C_CTL1(i2c_periph);
    ctl &= ~(I2C_CTL1_DMALST); 
    ctl |= dmalast;
    I2C_CTL1(i2c_periph) = ctl;

}

/*!
    \brief      whether to stretch SCL low when data is not ready in slave mode 
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  stretchpara:
      \arg        I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled
      \arg        I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled
    \param[out] none
    \retval     none
*/
void i2c_stretch_scl_low_config(uint32_t i2c_periph,uint32_t stretchpara)
{
    /* configure I2C SCL strerching enable or disable */
    uint32_t ctl = 0U;
    ctl = I2C_CTL0(i2c_periph);
    ctl &= ~(I2C_CTL0_DISSTRC); 
    ctl |= stretchpara;
    I2C_CTL0(i2c_periph) = ctl;
}

/*!
    \brief      whether or not to response to a general Cal 
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  gcallpara:
      \arg        I2C_GCEN_ENABLE: slave will response to a general call
      \arg        I2C_GCEN_DISABLE: slave will not response to a general call
    \param[out] none
    \retval     none
*/
void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara)
{
    /* configure slave response to a general call enable or disable */
    uint32_t ctl = 0U;
    ctl = I2C_CTL0(i2c_periph);
    ctl &= ~(I2C_CTL0_GCEN); 
    ctl |= gcallpara;
    I2C_CTL0(i2c_periph) = ctl;
}

/*!
    \brief      software reset I2C 
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  sreset:
      \arg        I2C_SRESET_SET: I2C is under reset
      \arg        I2C_SRESET_RESET: I2C is not under reset
    \param[out] none
    \retval     none
*/
void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset)
{
    /* modify CTL0 and configure software reset I2C state */
    uint32_t ctl = 0U;
    ctl = I2C_CTL0(i2c_periph);
    ctl &= ~(I2C_CTL0_SRESET); 
    ctl |= sreset;
    I2C_CTL0(i2c_periph) = ctl;
}

/*!
    \brief      check i2c state
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  state:
      \arg        I2C_SBSEND: start condition send out 
      \arg        I2C_ADDSEND: address is sent in master mode or received and matches in slave mode
      \arg        I2C_BTC: byte transmission finishes
      \arg        I2C_ADD10SEND: header of 10-bit address is sent in master mode
      \arg        I2C_STPDET: etop condition detected in slave mode
      \arg        I2C_RBNE: I2C_DATA is not Empty during receiving
      \arg        I2C_TBE: I2C_DATA is empty during transmitting
      \arg        I2C_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
      \arg        I2C_LOSTARB: arbitration lost in master mode
      \arg        I2C_AERR: acknowledge error
      \arg        I2C_OUERR: over-run or under-run situation occurs in slave mode
      \arg        I2C_PECERR: PEC error when receiving data
      \arg        I2C_SMBTO: timeout signal in SMBus mode
      \arg        I2C_SMBALT: SMBus alert status
      \arg        I2C_MASTER: a flag indicating whether I2C block is in master or slave mode
      \arg        I2C_I2CBSY: busy flag
      \arg        I2C_TRS: whether the I2C is a transmitter or a receiver
      \arg        I2C_RXGC: general call address (00h) received
      \arg        I2C_DEFSMB: default address of SMBus device
      \arg        I2C_HSTSMB: SMBus host header detected in slave mode
      \arg        I2C_DUMODF: dual flag in slave mode indicating which address is matched in dual-address mode
    \param[out] none
    \retval     state of i2c
*/
FlagStatus i2c_flag_get(uint32_t i2c_periph,uint32_t state )
{
    uint32_t reg = 0U;
    FlagStatus regstate = RESET;
    /* get the state in which register */
    reg = (BIT(31) & state);
    if((BIT(31) == reg)){
        if((I2C_STAT1(i2c_periph)&(state & I2C_STATE_MASK))){
            regstate = SET;
        }else{
            regstate = RESET;
        }
    }else{
        if((I2C_STAT0(i2c_periph)&(state & I2C_STATE_MASK))){
            regstate = SET;
        }else{
            regstate = RESET;
        }        
    }
    /* return the state */
    return regstate;
}

/*!
    \brief      clear i2c state
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  state: state type 
      \@arg       I2C_STAT0_SMBALT: SMBus Alert status
      \@arg       I2C_STAT0_SMBTO: timeout signal in SMBus mode
      \@arg       I2C_STAT0_PECERR: PEC error when receiving data
      \@arg       I2C_STAT0_OUERR: over-run or under-run situation occurs in slave mode    
      \@arg       I2C_STAT0_AERR: acknowledge error
      \@arg       I2C_STAT0_LOSTARB: arbitration lost in master mode   
      \@arg       I2C_STAT0_BERR: a bus error   
      \@arg       I2C_STAT0_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1
    \param[out] none
    \retval     none
*/
void i2c_flag_clear(uint32_t i2c_periph,uint32_t state)
{
    if(I2C_STAT0_ADDSEND == state){
        /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
        I2C_STAT0(i2c_periph);
        I2C_STAT1(i2c_periph);
    }else{
        I2C_STAT0(i2c_periph) &= ~(state);
    }
}

/*!
    \brief      enable i2c interrupt
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  inttype:      interrupt type 
      \arg        I2C_CTL1_ERRIE: error interrupt enable 
      \arg        I2C_CTL1_EVIE:  event interrupt enable 
      \arg        I2C_CTL1_BUFIE: buffer interrupt enable   
    \param[out] none
    \retval     none
*/
void i2c_interrupt_enable(uint32_t i2c_periph,uint32_t inttype)
{
    I2C_CTL1(i2c_periph) |= (inttype);   
}

/*!
    \brief      disable i2c interrupt
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  inttype: interrupt type 
      \arg        I2C_CTL1_ERRIE: error interrupt enable 
      \arg        I2C_CTL1_EVIE: event interrupt enable 
      \arg        I2C_CTL1_BUFIE: buffer interrupt enable   
    \param[out] none
    \retval     none
*/
void i2c_interrupt_disable(uint32_t i2c_periph,uint32_t inttype)
{
    I2C_CTL1(i2c_periph) &= ~(inttype);   
}

/*!
    \brief      I2C PEC calculation on or off
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  pecpara:
      \arg        I2C_PEC_ENABLE: PEC calculation on 
      \arg        I2C_PEC_DISABLE: PEC calculation off 
    \param[out] none
    \retval     none
*/
void i2c_pec_enable(uint32_t i2c_periph,uint32_t pecstate)
{
    /* on/off PEC calculation */
    uint32_t ctl = 0U;
    ctl = I2C_CTL0(i2c_periph);
    ctl &= ~(I2C_CTL0_PECEN); 
    ctl |= pecstate;
    I2C_CTL0(i2c_periph) = ctl;
}

/*!
    \brief      I2C whether to transfer PEC value
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  pecpara:
      \arg        I2C_PECTRANS_ENABLE: transfer PEC 
      \arg        I2C_PECTRANS_DISABLE: not transfer PEC 
    \param[out] none
    \retval     none
*/
void i2c_pec_transfer_enable(uint32_t i2c_periph,uint32_t pecpara)
{
    /* whether to transfer PEC */
    uint32_t ctl = 0U;
    ctl = I2C_CTL0(i2c_periph);
    ctl &= ~(I2C_CTL0_PECTRANS); 
    ctl |= pecpara;
    I2C_CTL0(i2c_periph) = ctl;
}

/*!
    \brief      packet error checking value 
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     PEC value
*/
uint8_t i2c_pec_value(uint32_t i2c_periph)
{
    return  (uint8_t)((I2C_STAT1(i2c_periph) &I2C_STAT1_ECV)>>8);
}

/*!
    \brief      I2C issue alert through SMBA pin 
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  smbuspara:
      \arg        I2C_SALTSEND_ENABLE: issue alert through SMBA pin 
      \arg        I2C_SALTSEND_DISABLE: not issue alert through SMBA pin 
    \param[out] none
    \retval     none
*/
void i2c_smbus_alert_issue(uint32_t i2c_periph,uint32_t smbuspara)
{
    /* issue alert through SMBA pin configure*/
    uint32_t ctl = 0U;
    ctl = I2C_CTL0(i2c_periph);
    ctl &= ~(I2C_CTL0_SALT); 
    ctl |= smbuspara;
    I2C_CTL0(i2c_periph) = ctl;
}

/*!
    \brief      I2C ARP protocol in SMBus switch enable or disable 
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  smbuspara:
      \arg        I2C_ARP_ENABLE: ARP is enabled 
      \arg        I2C_ARP_DISABLE: ARP is disabled 
    \param[out] none
    \retval     none
*/
void i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate)
{
    /* enable or disable I2C ARP protocol*/
    uint32_t ctl = 0U;
    ctl = I2C_CTL0(i2c_periph);
    ctl &= ~(I2C_CTL0_ARPEN); 
    ctl |= arpstate;
    I2C_CTL0(i2c_periph) = ctl;
}

/*!
    \brief      analog noise filter disable
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     none
*/
void i2c_analog_noise_filter_disable(uint32_t i2c_periph)
{
    I2C_FCTL(i2c_periph) |= I2C_FCTL_AFD;  
}

/*!
    \brief      analog noise filter enable
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     none
*/
void i2c_analog_noise_filter_enable(uint32_t i2c_periph)
{
    I2C_FCTL(i2c_periph) &= ~(I2C_FCTL_AFD);  
}

/*!
    \brief      digital noise filter configuration
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  dfilterpara: refer to enum i2c_gcall_config_enum
    \param[out] none
    \retval     none
*/
void i2c_digital_noise_filter_config(uint32_t i2c_periph,i2c_digital_filter_enum dfilterpara)
{
    I2C_FCTL(i2c_periph) |= dfilterpara;  
}

/*!
    \brief      enable SAM_V interface
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     none
*/
void i2c_sam_enable(uint32_t i2c_periph)
{
    I2C_SAMCS(i2c_periph) |= I2C_SAMCS_SAMEN;  
}

/*!
    \brief      disable SAM_V interface
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     none
*/
void i2c_sam_disable(uint32_t i2c_periph)
{
    I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_SAMEN);  
}

/*!
    \brief      enable SAM_V interface timeout detect
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     none
*/
void i2c_sam_timeout_enable(uint32_t i2c_periph)
{
    I2C_SAMCS(i2c_periph) |= I2C_SAMCS_STOEN;  
}

/*!
    \brief      disable SAM_V interface timeout detect
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[out] none
    \retval     none
*/
void i2c_sam_timeout_disable(uint32_t i2c_periph)
{
    I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_STOEN);  
}

/*!
    \brief      enable the specified I2C SAM interrupt
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  inttype: interrupt type 
      \@arg       I2C_SAMCS_TFFIE: txframe fall interrupt
      \@arg       I2C_SAMCS_TFRIE: txframe rise interrupt
      \@arg       I2C_SAMCS_RFFIE: rxframe fall interrupt
      \@arg       I2C_SAMCS_RFRIE: rxframe rise interrupt   
    \param[out]  none
    \retval      none
*/
void i2c_sam_interrupt_enable(uint32_t i2c_periph,uint32_t inttype)
{
    I2C_SAMCS(i2c_periph) |= (inttype);   
}

/*!
    \brief      disable i2c interrupt
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  inttype:      interrupt type 
      \@arg       I2C_SAMCS_TFFIE: txframe fall interrupt
      \@arg       I2C_SAMCS_TFRIE: txframe rise interrupt
      \@arg       I2C_SAMCS_RFFIE: rxframe fall interrupt
      \@arg       I2C_SAMCS_RFRIE: rxframe rise interrupt    
    \param[out] none
    \retval     none
*/
void i2c_sam_interrupt_disable(uint32_t i2c_periph,uint32_t inttype)
{
    I2C_SAMCS(i2c_periph) &= ~(inttype);   
}

/*!
    \brief      check i2c SAM state
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  samstate: state type 
      \@arg       I2C_SAMCS_TXF: level of txframe signal
      \@arg       I2C_SAMCS_RXF: level of rxframe signal
      \@arg       I2C_SAMCS_TFF: txframe fall flag
      \@arg       I2C_SAMCS_TFR: txframe rise flag    
      \@arg       I2C_SAMCS_RFF: rxframe fall flag
      \@arg       I2C_SAMCS_RFR: rxframe rise flag   
    \param[out] none
    \retval     state of i2c SAM
*/
FlagStatus i2c_sam_flag_get(uint32_t i2c_periph,uint32_t samstate)
{
    FlagStatus reg = RESET;
    if(I2C_SAMCS(i2c_periph)&samstate){
        reg =SET;
    }else{
        reg =RESET; 
    }
    return reg;
}

/*!
    \brief      clear i2c SAM state
    \param[in]  i2c_periph: I2Cx(x=0,1,2)
    \param[in]  samstate: state type 
      \@arg       I2C_SAMCS_TFF: txframe fall flag
      \@arg       I2C_SAMCS_TFR: txframe rise flag    
      \@arg       I2C_SAMCS_RFF: rxframe fall flag
      \@arg       I2C_SAMCS_RFR: rxframe rise flag   
    \param[out] none
    \retval     none
*/
void i2c_sam_flag_clear(uint32_t i2c_periph,uint32_t samstate)
{
    I2C_SAMCS(i2c_periph) &= ~(samstate);
  
}

