/**
 * @brief           I2C Primitive
 * @author          AXELL CORPORATION
 * @description     I2C Primitive Layer
 * @note            none
 * @history         2017_02_22  初版
 * @history         2017_10_26  Ver2.0
 */
/* DOM-IGNORE-BEGIN */
/*
 * This program was created by AXELL CORPORATION.
 * Copyright (C) 2017 AXELL CORPORATION, all rights reserved.
 */
/* DOM-IGNORE-END */

#include "AG903_errno.h"
#include "AG903_common.h"
#include "i2c/i2cprm.h"
#include "register/AG903_i2creg.h"

#define    AG903_I2C_READ_REG(CH,REG)            (AG903_IICn(CH)->REG)
#define    AG903_I2C_WRITE_REG(CH,REG,VAL)        (AG903_IICn(CH)->REG  = (uint32_t)(VAL))
#define    AG903_I2C_CLR_REG(CH,REG,VAL)        (AG903_IICn(CH)->REG &= (uint32_t)(~VAL))
#define    AG903_I2C_SET_REG(CH,REG,VAL)        (AG903_IICn(CH)->REG |= (uint32_t)(VAL))

/**
 * @brief           IICnCRレジスタのI2C_RSTビットSet
 * @param           ch [in] I2Cチャネル
 * @return          void
 * @description     IICnCRレジスタのI2C_RSTビットSet
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_I2CPrmResetController(uint8_t ch)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    AG903_I2C_SET_REG(ch,CR,(1<<AG903_IICn_CR_I2C_RST_POS));
    return;
}

/**
 * @brief           IICnCRレジスタのI2C_RSTビットRead
 * @param           ch [in] I2Cチャネル
 * @param           status [out] 状態（I2C_RST値）
 * @return          void
 * @description     IICnCRレジスタのI2C_RSTビットRead
*/
void AG903_I2CPrmGetResetStatus(uint8_t ch, uint8_t* status)
{
    uint32_t val;

    ASSERT(AG903_I2C_CH_NUM > ch);
    val = AG903_I2C_READ_REG(ch,CR);
    (*status) = (uint8_t)(val&AG903_IICn_CR_I2C_RST_MSK);
    return;
}

/**
 * @brief           IICnCRのレジスタWrite(指定ビットをSet)
 * @param           ch [in] I2Cチャネル
 * @param           ctrlbit [in] 制御指定（ビット指定）
 * @return          void
 * @description     IICnCRのレジスタWrite(指定ビットをSet)
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_I2CPrmSetControl(uint8_t ch, uint32_t setbit)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    AG903_I2C_SET_REG(ch,CR,setbit);
    return;
}

/**
 * @brief           IICnCRのレジスタWrite(指定ビットをClear)
 * @param           ch [in] I2Cチャネル
 * @param           ctrlbit [in] 制御指定（ビット指定）
 * @return          void
 * @description     IICnCRのレジスタWrite(指定ビットをClear)
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_I2CPrmClearControl(uint8_t ch, uint32_t clrbit)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    AG903_I2C_CLR_REG(ch,CR,clrbit);
    return;
}

/**
 * @brief           IICnSRのレジスタRead
 * @param           ch [in] I2Cチャネル
 * @param           status [out] 状態（SR値）
 * @return          void
 * @description     IICnSRのレジスタRead
*/
void AG903_I2CPrmGetStatus(uint8_t ch, uint32_t* status)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    (*status) = AG903_I2C_READ_REG(ch,SR);
    return;
}

/**
 * @brief           IICnDRのレジスタWrite
 * @param           ch [in] I2Cチャネル
 * @param           data [in] 書込みデータ
 * @return          void
 * @description     IICnDRのレジスタWrite
*/
void AG903_I2CPrmWriteData(uint8_t ch, uint8_t data)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    AG903_I2C_WRITE_REG(ch,DR,data);
    return;
}

/**
 * @brief           IICnDRのレジスタRead
 * @param           ch [in] I2Cチャネル
 * @param           data [out] 読込みデータ
 * @return          void
 * @description     IICnDRのレジスタRead
*/
void AG903_I2CPrmReadData(uint8_t ch, uint8_t* data)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    (*data) = AG903_I2C_READ_REG(ch,DR);
    return;
}

/**
 * @brief           IICnCDRのレジスタWrite
 * @param           ch [in] I2Cチャネル
 * @param           cdr [in] CDR設定値
 * @return          void
 * @description     IICnCDRのレジスタWrite
*/
void AG903_I2CPrmSetClockDivision(uint8_t ch, uint32_t cdr)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    AG903_I2C_WRITE_REG(ch,CDR,cdr);
    return;
}

/**
 * @brief           IICnTGSRのレジスタWrite
 * @param           ch [in] I2Cチャネル
 * @param           tsr [in] TSR値
 * @param           gsr [in] GSR値
 * @return          void
 * @description     IICnTGSRのレジスタWrite
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_I2CPrmSetGlitchSuppression(uint8_t ch, uint16_t tsr, uint8_t gsr)
{
    
    ASSERT(AG903_I2C_CH_NUM > ch);
    
    AG903_I2C_CLR_REG(ch,TGSR,AG903_IICn_TGSR_TSR_MSK);
    AG903_I2C_CLR_REG(ch,TGSR,AG903_IICn_TGSR_GSR_MSK);
    AG903_I2C_SET_REG(ch,TGSR,(tsr<<AG903_IICn_TGSR_TSR_POS));
    AG903_I2C_SET_REG(ch,TGSR,(gsr<<AG903_IICn_TGSR_GSR_POS));
    return;
}

/**
 * @brief           IICnSARレジスタのEN10ビットSet
 * @param           ch [in] I2Cチャネル
 * @return          void
 * @description     IICnSARレジスタのEN10ビットSet
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_I2CPrmSetExtAddrMode(uint8_t ch)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    AG903_I2C_SET_REG(ch,SAR,(1<<AG903_IICn_SAR_EN10_POS));
    return;
}

/**
 * @brief           IICnSARレジスタのEN10ビットClear
 * @param           ch [in] I2Cチャネル
 * @return          void
 * @description     IICnSARレジスタのEN10ビットClear
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_I2CPrmClearExtAddrMode(uint8_t ch)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    AG903_I2C_CLR_REG(ch,SAR,AG903_IICn_SAR_EN10_MSK);
    return;
}

/**
 * @brief           IICnSARのレジスタWrite
 * @param           ch [in] I2Cチャネル
 * @param           saddr [in] スレーブアドレス
 * @return          void
 * @description     IICnSARのレジスタWrite
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_I2CPrmSetSlaveAddr(uint8_t ch, uint16_t saddr)
{
    ASSERT(AG903_I2C_CH_NUM > ch);
    
    if(0x0380 & saddr) {
        AG903_I2C_SET_REG(ch,SAR,(1<<AG903_IICn_SAR_EN10_POS));
        AG903_I2C_CLR_REG(ch,SAR,AG903_IICn_SAR_SAR_MSK);
        AG903_I2C_SET_REG(ch,SAR,(saddr<<AG903_IICn_SAR_SAR_POS));
    }
    else {
        AG903_I2C_CLR_REG(ch,SAR,AG903_IICn_SAR_EN10_MSK);
        AG903_I2C_CLR_REG(ch,SAR,AG903_IICn_SAR_SAR_MSK);
        AG903_I2C_SET_REG(ch,SAR,(saddr<<AG903_IICn_SAR_SAR_POS));
    }
    return;
}

