/**
* @file hv_drv_GpioSmutI2c.c
* @brief gpio smulitaion i2c driver layer file.
* @details This file provides the following functions: \n
* (1) gpio simulate i2c master tx/rx \n
* (2) gpio simulate i2c init \n
*
* @author HiView SoC Software Team
* @version 1.0.0
* @date 2023-06-06
* @copyright Copyright(c),2023-6, Hiview Software. All rights reserved.
* @par History:
*
* Author | Date | Change Description
* |
---|
*/
#include "Common/hv_comm_DataType.h"
#include "Common/Assert/hv_comm_Assert.h"
#include "hv_comm_Define.h"
#include "hv_cal_Gpio.h"
#include "hv_vos_Comm.h"
#include "hv_drv_GpioSimI2c.h"
static GpioSimI2c s_stgpiosimi2c[SIMI2CMAX-SIMI2C0] = {
{INVALID_PARAM_UHCAR8, INVALID_PARAM_UHCAR8},
{INVALID_PARAM_UHCAR8, INVALID_PARAM_UHCAR8},
{INVALID_PARAM_UHCAR8, INVALID_PARAM_UHCAR8}
};
#define SET_SCL_OUT(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimi2c[uiIndex].ucSclPin, GPIO_DIR_OUTPUT)
#define SET_SCL_IN(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimi2c[uiIndex].ucSclPin, GPIO_DIR_INPUT)
#define SET_SDA_OUT(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimi2c[uiIndex].ucSdaPin, GPIO_DIR_OUTPUT)
#define SET_SDA_IN(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimi2c[uiIndex].ucSdaPin, GPIO_DIR_INPUT)
#define SET_SCL_HIGH(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimi2c[uiIndex].ucSclPin, GPIO_LEVEL_HIGH)
#define SET_SCL_LOW(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimi2c[uiIndex].ucSclPin, GPIO_LEVEL_LOW)
#define SET_SDA_HIGH(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimi2c[uiIndex].ucSdaPin, GPIO_LEVEL_HIGH)
#define SET_SDA_LOW(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimi2c[uiIndex].ucSdaPin, GPIO_LEVEL_LOW)
#define GET_SDA_LEVEL(uiIndex) Hv_Cal_Gpio_GetPinLevel(s_stgpiosimi2c[uiIndex].ucSdaPin)
#define GPIOSIMI2C_DELAY 2U
#define GPIOSIMI2C_WAIT_ACK_TIMES 200U
#define GPIOSIMI2C_ADDR_WRITE 0x00
#define GPIOSIMI2C_ADDR_READ 0x01
/** Initialize i2c
* @param pstInitParam pointer to i2c configuration parameters
* @return SUCCESS/FAILURE
*/
Status Hv_Drv_GpioSimI2c_Init(I2cBusID enBus, const GpioSimI2c *pstGpioSimI2c)
{
HV_ASSERT_VALID_PTR_RET(pstGpioSimI2c, HV_FAILURE);
if (enBus < SIMI2C0)
{
return HV_FAILURE;
}
UINT32 uiIndex = enBus - SIMI2C0;
memcpy(&s_stgpiosimi2c[uiIndex], pstGpioSimI2c, sizeof(GpioSimI2c));
SET_SCL_OUT(uiIndex);
SET_SDA_OUT(uiIndex);
SET_SCL_HIGH(uiIndex);
SET_SDA_HIGH(uiIndex);
return HV_SUCCESS;
}
/** I2c start signal
*@SCL keep high, SDA change from high to low
*/
static VOID Hv_GpioSimI2c_Start(UINT32 uiIndex)
{
SET_SDA_OUT(uiIndex);
SET_SCL_HIGH(uiIndex);
SET_SDA_HIGH(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SDA_LOW(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SCL_LOW(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
}
/** I2c stop signal
*@SCL keep high, SDA change from low to high
*/
static VOID Hv_GpioSimI2c_Stop(UINT32 uiIndex)
{
SET_SDA_OUT(uiIndex);
SET_SDA_LOW(uiIndex);
SET_SCL_LOW(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SCL_HIGH(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SDA_HIGH(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
}
/** master wait Ack signal
*@Pull up SCL high, to read SDA level high or low
*/
static Status Hv_GpioSimI2c_Wait_Ack(UINT32 uiIndex)
{
UINT32 uiWaitTime = 0;
SET_SDA_IN(uiIndex);
SET_SCL_LOW(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SCL_HIGH(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
while (GET_SDA_LEVEL(uiIndex))
{
if (uiWaitTime > GPIOSIMI2C_WAIT_ACK_TIMES)
{
Hv_GpioSimI2c_Stop(uiIndex);
HV_LOGW("wait ack timeout!\n");
return HV_FAILURE;
}
uiWaitTime++;
}
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SCL_LOW(uiIndex);
return HV_SUCCESS;
}
/** send Ack signal
*@SCL keep high, SDA create a valid low level
*/
static VOID Hv_GpioSimI2c_Send_Ack(UINT32 uiIndex)
{
SET_SDA_OUT(uiIndex);
SET_SCL_LOW(uiIndex);
SET_SDA_LOW(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SCL_HIGH(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SCL_LOW(uiIndex);
}
/** send NAck signal
*@SCL keep high, SDA create a valid high level
*/
static VOID Hv_GpioSimI2c_Send_Nack(UINT32 uiIndex)
{
SET_SDA_OUT(uiIndex);
SET_SCL_LOW(uiIndex);
SET_SDA_HIGH(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SCL_HIGH(uiIndex);
Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
SET_SCL_LOW(uiIndex);
}
/** send data 1 byte
*@ Send data bit by bit and MSB first;
*@ When SCL keep high, data is valid;
*@ when SCL change to low, SDA permited to change.
*/
static VOID Hv_GpioSimI2c_Write_Byte(UINT32 uiIndex, UCHAR8 ucByte)
{
UCHAR8 ucStep = 0;
SET_SDA_OUT(uiIndex);
SET_SCL_LOW(uiIndex);
for (ucStep = 0;ucStep < 8; ucStep++)
{
if ((ucByte<