#include "Simulated_IIC_1_Master.h"
#include "Port_Cfg.h"
#include "Port.h"
#include "Dio.h"

uint8_t u8SimulatedIIC1ReceivedACK;

/*
SDA:P22-3
SCL:P22-4
*/
/*时钟输入*/
void SGM4591Q_Clock1_Input(void)
{
  Port_SetPinDirection(Port_Config_PortGroup22_PortPin4, PORT_PIN_IN);
}
/*时钟输出低*/
void SGM4591Q_Clock1_Output(void)
{
  Port_SetPinDirection(Port_Config_PortGroup22_PortPin4, PORT_PIN_OUT);
  Dio_WriteChannel(DioConf_DioChannel_P22_04, STD_LOW);
}

/*数据设置输入*/
void SGM4591Q_Data1_Input(void)
{
  Port_SetPinDirection(Port_Config_PortGroup22_PortPin3, PORT_PIN_IN);
}
/*数据输入高低电平*/
uint8_t SGM4591Q_Data1_Input_Value(void)
{
  uint8_t Data;

  Data = Dio_ReadChannel(Port_Config_PortGroup22_PortPin3);

  return Data;
}
/*数据输出低*/
void SGM4591Q_Data1_Output_Low(void)
{
  Port_SetPinDirection(Port_Config_PortGroup22_PortPin3, PORT_PIN_OUT);
  Dio_WriteChannel(DioConf_DioChannel_P22_03, STD_LOW);
}

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

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

  u8SimulatedIIC1ReceivedACK = SIMULATED_IIC_1_INVALID_ACK;
}

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

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

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

  // SIMULATED_IIC_1_SDA_DIR = GPIO_DIR_OUT;    // SDA输出0,此时SDA = 0
  // SIMULATED_IIC_1_OUT_SDA = 0;
  SGM4591Q_Data1_Output_Low();
  Simulated_IIC_1_Delay();
  Simulated_IIC_1_Delay();

  // SIMULATED_IIC_1_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
  // SIMULATED_IIC_1_SCL     = 0;
  SGM4591Q_Clock1_Output();
  Simulated_IIC_1_Delay();
}

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

  // SIMULATED_IIC_1_SDA_DIR = GPIO_DIR_OUT;    // SDA输出0,此时SDA = 0
  // SIMULATED_IIC_1_OUT_SDA = 0;
  SGM4591Q_Data1_Output_Low();
  Simulated_IIC_1_Delay();
  Simulated_IIC_1_Delay();

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

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

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

  u8SimulatedIIC1ReceivedACK = SIMULATED_IIC_1_INVALID_ACK;

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

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

    // SIMULATED_IIC_1_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
    // SIMULATED_IIC_1_SCL     = 0;
    SGM4591Q_Clock1_Output();
    Simulated_IIC_1_Delay();

    Data <<= 1;
  }

  // SIMULATED_IIC_1_SDA_DIR = GPIO_DIR_IN;    // 设置SDA为输入状态
  SGM4591Q_Data1_Input();
  Simulated_IIC_1_Delay();
  Simulated_IIC_1_Delay();

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

  // u8SimulatedIIC1ReceivedACK = SIMULATED_IIC_1_IN_SDA;
  u8SimulatedIIC1ReceivedACK = SGM4591Q_Data1_Input_Value();

  // SIMULATED_IIC_1_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
  // SIMULATED_IIC_1_SCL     = 0;
  SGM4591Q_Clock1_Output();
  Simulated_IIC_1_Delay();
}

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

  Data = 0;

  // SIMULATED_IIC_1_SDA_DIR = GPIO_DIR_IN;    // 设置SDA为输入状态
  SGM4591Q_Data1_Input();
  Simulated_IIC_1_Delay();
  Simulated_IIC_1_Delay();

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

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

    // Data |= SIMULATED_IIC_1_IN_SDA;
    Data |= SGM4591Q_Data1_Input_Value();

    // SIMULATED_IIC_1_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
    // SIMULATED_IIC_1_SCL     = 0;
    SGM4591Q_Clock1_Output();
    Simulated_IIC_1_Delay();
    Simulated_IIC_1_Delay();
  }

  return Data;
}

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

  if (ACK > SIMULATED_IIC_1_NAK)
  {
    return;
  }

  if (ACK != 0U)
  {
    // SIMULATED_IIC_1_SDA_DIR = GPIO_DIR_IN;    // SDA被设置为输入,IO口为高阻状态,总线上SDA信号由上拉电阻拉高,此时SDA = 1
    SGM4591Q_Data1_Input();
  }
  else
  {
    // SIMULATED_IIC_1_SDA_DIR = GPIO_DIR_OUT;    // SDA输出0,此时SDA = 0
    // SIMULATED_IIC_1_OUT_SDA = 0;
    SGM4591Q_Data1_Output_Low();
  }
  Simulated_IIC_1_Delay();

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

  // SIMULATED_IIC_1_SCL_DIR = GPIO_DIR_OUT;    // SCL输出0,此时SCL = 0
  // SIMULATED_IIC_1_SCL     = 0;
  SGM4591Q_Clock1_Output();
  Simulated_IIC_1_Delay();
}

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

  ACK = u8SimulatedIIC1ReceivedACK;
  u8SimulatedIIC1ReceivedACK = SIMULATED_IIC_1_INVALID_ACK;

  return ACK;
}

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

  for (i = 0; i < SIMULATED_IIC_1_FREQ_CALIBRATION; i++)
  {
    NOP();
  }
}
