/******************************************************************************
文 件 名：Simulated_IIC_Master.c
功能描述：IO端口模拟的IIC(I2C)主机函数库文件
作    者：张暄
版    本：V1.0
日    期：2016.12.21
******************************************************************************/

#include "Simulated_IIC_2_Master.h"
#include "rh850_macros.h"
#include "dr7f701401.dvf.h"

#define SIMULATED_IIC_2_SCL     SDB_LED_SCL        // SCL信号
#define SIMULATED_IIC_2_SCL_DIR SDB_LED_SCL_DIR    // SCL方向
#define SIMULATED_IIC_2_OUT_SDA SDB_LED_SDA        // SDA信号
#define SIMULATED_IIC_2_IN_SDA  SDB_LED_SDA_IN
#define SIMULATED_IIC_2_SDA_DIR SDB_LED_SDA_DIR    // SDA方向

uint8_t u8SimulatedIIC2ReceivedACK;

typedef enum
{
    GPIO_DIR_OUT = 0U,
    GPIO_DIR_IN
} GPIO_Direction_en_t;

/******************************************************************************
函数名：IIC_Init
功  能：初始化IIC总线
参  数：无
返回值：无
******************************************************************************/
void Simulated_IIC_2_Init(void)
{
    SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_IN;    // SCL被设置为输入,IO口为高阻状态,总线上SCL信号由上拉电阻拉高,此时SCL = 1
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_IN;    // SDA被设置为输入,IO口为高阻状态,总线上SDA信号由上拉电阻拉高,此时SDA = 1
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    u8SimulatedIIC2ReceivedACK = SIMULATED_IIC_2_INVALID_ACK;
}

/******************************************************************************
函数名：IIC_Start
功  能：在IIC总线上发送起始信号,发起一次IIC通信
参  数：无
返回值：无
******************************************************************************/
void Simulated_IIC_2_Start(void)
{
    u8SimulatedIIC2ReceivedACK = SIMULATED_IIC_2_INVALID_ACK;

    SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_IN;    // SDA被设置为输入,IO口为高阻状态,总线上SDA信号由上拉电阻拉高,此时SDA = 1
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_IN;    // SCL被设置为输入,IO口为高阻状态,总线上SCL信号由上拉电阻拉高,此时SCL = 1
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_OUT;    // SDA输出0,此时SDA = 0
    SIMULATED_IIC_2_OUT_SDA = 0;
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
    SIMULATED_IIC_2_SCL     = 0;
    Simulated_IIC_2_Delay( );
}

/******************************************************************************
函数名：IIC_Stop
功  能：在IIC总线上发送停止信号,终止当前IIC通信
参  数：无
返回值：无
******************************************************************************/
void Simulated_IIC_2_Stop(void)
{
    u8SimulatedIIC2ReceivedACK = SIMULATED_IIC_2_INVALID_ACK;

    SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_OUT;    // SDA输出0,此时SDA = 0
    SIMULATED_IIC_2_OUT_SDA = 0;
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_IN;    // SCL被设置为输入,IO口为高阻状态,总线上SCL信号由上拉电阻拉高,此时SCL = 1
    SIMULATED_IIC_2_SCL = 0;
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_IN;    // SDA被设置为输入,IO口为高阻状态,总线上SDA信号由上拉电阻拉高,此时SDA = 1
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );
}

/******************************************************************************
函数名：IIC_Transmit_Data
功  能：向IIC总线上发送1字节数据
参  数：Data：发送的数据
返回值：总线上器件的确认(ACK)  0 - ACK  1 - NAK
******************************************************************************/
void Simulated_IIC_2_Transmit_Data(uint8_t Data)
{
    uint8_t i;

    u8SimulatedIIC2ReceivedACK = SIMULATED_IIC_2_INVALID_ACK;

    for ( i = 0; i < 8; i++ )
    {
        if ( Data & 0x80 )
            SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_IN;    // SDA被设置为输入,IO口为高阻状态,总线上SDA信号由上拉电阻拉高,此时SDA = 1
        else
        {
            SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_OUT;    // SDA输出0,此时SDA = 0
            SIMULATED_IIC_2_OUT_SDA = 0;
        }
        Simulated_IIC_2_Delay( );
        Simulated_IIC_2_Delay( );

        SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_IN;    // SCL被设置为输入,IO口为高阻状态,总线上SCL信号由上拉电阻拉高,此时SCL = 1
        Simulated_IIC_2_Delay( );
        Simulated_IIC_2_Delay( );

        SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
        SIMULATED_IIC_2_SCL     = 0;
        Simulated_IIC_2_Delay( );

        Data <<= 1;
    }

    SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_IN;    // 设置SDA为输入状态
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_IN;    // SCL被设置为输入,IO口为高阻状态,总线上SCL信号由上拉电阻拉高,此时SCL = 1
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    u8SimulatedIIC2ReceivedACK = SIMULATED_IIC_2_IN_SDA;

    SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
    SIMULATED_IIC_2_SCL     = 0;
    Simulated_IIC_2_Delay( );
}

/******************************************************************************
函数名：IIC_Receive_Data
功  能：从IIC总线上接收1字节数据
参  数：无
返回值：接收到的数据
******************************************************************************/
uint8_t Simulated_IIC_2_Receive_Data(void)
{
    uint8_t i;
    uint8_t Data;

    Data = 0;

    SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_IN;    // 设置SDA为输入状态
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    for ( i = 0; i < 8; i++ )
    {
        Data <<= 1;

        SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_IN;    // SCL被设置为输入,IO口为高阻状态,总线上SCL信号由上拉电阻拉高,此时SCL = 1
        Simulated_IIC_2_Delay( );
        Simulated_IIC_2_Delay( );
        Simulated_IIC_2_Delay( );

        Data |= SIMULATED_IIC_2_IN_SDA;

        SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
        SIMULATED_IIC_2_SCL     = 0;
        Simulated_IIC_2_Delay( );
        Simulated_IIC_2_Delay( );
    }

    return Data;
}

/******************************************************************************
函数名：IIC_Transmit_ACK
功  能：向IIC总线上发送确认信号
参  数：ACK：确认信号的类型： SIMULATED_IIC_2_ACK  肯定应答
                              IIC_NAK  否定应答
返回值：无
******************************************************************************/
void Simulated_IIC_2_Transmit_ACK(uint8_t ACK)
{
    u8SimulatedIIC2ReceivedACK = SIMULATED_IIC_2_INVALID_ACK;

    if ( ACK > SIMULATED_IIC_2_NAK )
        return;

    if ( ACK )
        SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_IN;    // SDA被设置为输入,IO口为高阻状态,总线上SDA信号由上拉电阻拉高,此时SDA = 1
    else
    {
        SIMULATED_IIC_2_SDA_DIR = GPIO_DIR_OUT;    // SDA输出0,此时SDA = 0
        SIMULATED_IIC_2_OUT_SDA = 0;
    }
    Simulated_IIC_2_Delay( );

    SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_IN;    // SCL被设置为输入,IO口为高阻状态,总线上SCL信号由上拉电阻拉高,此时SCL = 1
    Simulated_IIC_2_Delay( );
    Simulated_IIC_2_Delay( );

    SIMULATED_IIC_2_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
    SIMULATED_IIC_2_SCL     = 0;
    Simulated_IIC_2_Delay( );
}

/******************************************************************************
函数名：IIC_Receive_ACK
功  能：获取从总线上接收到的确认信号
参  数：无
返回值：总线上器件的确认信号类型：Simulated_IIC_ACK        肯定应答
                                  SIMULATED_IIC_2_NAK         否定应答
                                  IIC_INVALID_ACK 无效的应答信号(应答信号还未收到)
******************************************************************************/
uint8_t Simulated_IIC_2_Receive_ACK(void)
{
    uint8_t ACK;

    ACK                        = u8SimulatedIIC2ReceivedACK;
    u8SimulatedIIC2ReceivedACK = SIMULATED_IIC_2_INVALID_ACK;

    return ACK;
}

/******************************************************************************
函数名：IIC_Delay
功  能：延时5us,用于收发过程中的时序控制
        注意：必须调整IIC_5us_DELAY_CALIBRATION参数校准延时时间在5us左右
参  数：ACK：确认信号的类型  0 - ACK  1 - NAK
返回值：无
******************************************************************************/
void Simulated_IIC_2_Delay(void)
{
    uint8_t i;

    for ( i = 0; i < SIMULATED_IIC_2_FREQ_CALIBRATION; i++ )
    {
        nop( );
    }
}
