/** * @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<