/** * @file hv_drv_GpioSimSWire.c * @brief gpio smulitaion single wire driver layer file. * @details This file provides the following functions: \n * (1) gpio simulate swire tx/rx \n * (2) gpio simulate swire init \n * * @author HiView SoC Software Team * @version 1.0.0 * @date 2023-12-16 * @copyright Copyright(c),2023-12, Hiview Software. All rights reserved. * @par History: * <table> * <tr><th>Author <th>Date <th>Change Description * </table> */ #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_GpioSimSWire.h" #define GPIOSIMSWIRE_DELAY 1U static GpioSimSWire s_stgpiosimswire[SIMSWIRE_ID_MAX] = { {INVALID_PARAM_UHCAR8, INVALID_PARAM_UHCAR8, 1, 1, 1}, }; #define SET_SCK_OUT(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimswire[uiIndex].ucSckPin, GPIO_DIR_OUTPUT) #define SET_SCK_IN(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimswire[uiIndex].ucSckPin, GPIO_DIR_INPUT) #define SET_SDT_OUT(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimswire[uiIndex].ucSdtPin, GPIO_DIR_OUTPUT) #define SET_SDT_IN(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimswire[uiIndex].ucSdtPin, GPIO_DIR_INPUT) #define SET_SCK_HIGH(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimswire[uiIndex].ucSckPin, GPIO_LEVEL_HIGH) #define SET_SCK_LOW(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimswire[uiIndex].ucSckPin, GPIO_LEVEL_LOW) #define SET_SDT_HIGH(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimswire[uiIndex].ucSdtPin, GPIO_LEVEL_HIGH) #define SET_SDT_LOW(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimswire[uiIndex].ucSdtPin, GPIO_LEVEL_LOW) #define GET_SDT_LEVEL(uiIndex) Hv_Cal_Gpio_GetPinLevel(s_stgpiosimswire[uiIndex].ucSdtPin) #define GET_SCK_TWHL(uiIndex) (s_stgpiosimswire[uiIndex].ucTWHL) #define GET_SDT_SCK_TSU(uiIndex) (s_stgpiosimswire[uiIndex].ucTSU) #define GET_SDT_SCK_THL(uiIndex) (s_stgpiosimswire[uiIndex].ucTHL) /* 1nop about 13 ns */ static inline VOID GpioSimSWire_Delay_Nop(UINT32 uiNop) { HV_ASSERT_TRUE_VOID(uiNop > 0); while(uiNop--) { asm("nop"); } return; } /** Initialize gpio simulate single wire * @param pstGpioSimSwire pointer to swire configuration parameters * @param enBus select sginle wire bus id * @return SUCCESS/FAILURE */ Status Hv_Drv_GpioSimSWire_Init(const GpioSimSWire *pstGpioSimSwire) { HV_ASSERT_VALID_PTR_RET(pstGpioSimSwire, HV_FAILURE); HV_ASSERT_TRUE(pstGpioSimSwire->enBus < SIMSWIRE_ID_MAX); memcpy(&s_stgpiosimswire[pstGpioSimSwire->enBus], pstGpioSimSwire, sizeof(GpioSimSWire)); SET_SCK_OUT(pstGpioSimSwire->enBus); SET_SDT_OUT(pstGpioSimSwire->enBus); SET_SCK_LOW(pstGpioSimSwire->enBus); SET_SDT_LOW(pstGpioSimSwire->enBus); return HV_SUCCESS; } /** Swire start signal *@SCK and SDT keep low */ VOID Hv_GpioSimSWire_Start(UINT32 uiIndex) { SET_SCK_OUT(uiIndex); SET_SDT_OUT(uiIndex); SET_SDT_LOW(uiIndex); SET_SCK_LOW(uiIndex); return; } /** Swire stop signal *@SCK and SDT keep Low */ VOID Hv_GpioSimSWire_Stop(UINT32 uiIndex) { SET_SCK_OUT(uiIndex); SET_SDT_OUT(uiIndex); SET_SDT_LOW(uiIndex); SET_SCK_LOW(uiIndex); return; } /** send data 1 byte *@ Send data bit by bit and MSB first; *@ When SCK keep high, data is valid; */ VOID Hv_GpioSimSWire_Send_Bit(UINT32 uiIndex, UCHAR8 ucBit) { SET_SDT_OUT(uiIndex); SET_SCK_LOW(uiIndex); if (ucBit) { SET_SDT_HIGH(uiIndex); } else { SET_SDT_LOW(uiIndex); } GpioSimSWire_Delay_Nop(GET_SDT_SCK_TSU(uiIndex)); SET_SCK_HIGH(uiIndex); GpioSimSWire_Delay_Nop(GET_SCK_TWHL(uiIndex)); SET_SCK_LOW(uiIndex); GpioSimSWire_Delay_Nop(GET_SDT_SCK_THL(uiIndex)); SET_SDT_LOW(uiIndex); return; } /** receive 1 bit *@Pull SCK high, to read SDT data from slave device bit by bit */ UCHAR8 Hv_GpioSimSWire_Recv_Bit(UINT32 uiIndex) { UCHAR8 ucBit = 0x0; UCHAR8 ucStep = 0; SET_SDT_IN(uiIndex); SET_SCK_LOW(uiIndex); GpioSimSWire_Delay_Nop(GPIOSIMSWIRE_DELAY); SET_SCK_HIGH(uiIndex); if (GET_SDT_LEVEL(uiIndex)) { ucBit = ucBit | 0x01; } GpioSimSWire_Delay_Nop(GPIOSIMSWIRE_DELAY); SET_SCK_LOW(uiIndex); return ucBit; } /** send data 1 byte *@ Send data bit by bit and MSB first; *@ When SCK keep high, data is valid; */ VOID Hv_GpioSimSWire_Send_Byte(UINT32 uiIndex, UCHAR8 ucByte) { UCHAR8 ucStep = 0; SET_SDT_OUT(uiIndex); SET_SCK_LOW(uiIndex); for (ucStep = 0;ucStep < 8; ucStep++) { if ((ucByte<<ucStep)&0x80) { SET_SDT_HIGH(uiIndex); } else { SET_SDT_LOW(uiIndex); } GpioSimSWire_Delay_Nop(GET_SDT_SCK_TSU(uiIndex)); SET_SCK_HIGH(uiIndex); GpioSimSWire_Delay_Nop(GET_SCK_TWHL(uiIndex)); SET_SCK_LOW(uiIndex); GpioSimSWire_Delay_Nop(GET_SDT_SCK_THL(uiIndex)); SET_SDT_LOW(uiIndex); } } /** receive 1 byte *@Pull SCK high, to read SDT data from slave device bit by bit */ UCHAR8 Hv_GpioSimSWire_Recv_Byte(UINT32 uiIndex) { UCHAR8 ucByte = 0x00; UCHAR8 ucStep = 0; SET_SDT_IN(uiIndex); for (ucStep = 0; ucStep < 8; ucStep++) { SET_SCK_LOW(uiIndex); GpioSimSWire_Delay_Nop(GPIOSIMSWIRE_DELAY); SET_SCK_HIGH(uiIndex); ucByte = ucByte<<1; if (GET_SDT_LEVEL(uiIndex)) { ucByte = ucByte | 0x01; } GpioSimSWire_Delay_Nop(GPIOSIMSWIRE_DELAY); } SET_SCK_LOW(uiIndex); return ucByte; } /** Send in master mode an amount of data * @param pucData pointer to data buffer to be transmited * @param usDataSize amount of data to be sent * @retval Status SUCESS/FAILURE */ Status Hv_Drv_GpioSimSWire_SendData(SWireID enBus, UCHAR8 *pucData, UINT32 uiDatasize) { HV_ASSERT_TRUE(enBus < SIMSWIRE_ID_MAX); HV_ASSERT_VALID_PTR_RET(pucData, HV_FAILURE); UINT32 uiSize = 0; //Start Hv_GpioSimSWire_Start(enBus); //Write Data for (uiSize = 0; uiSize < uiDatasize; uiSize++) { Hv_GpioSimSWire_Send_Byte(enBus, pucData[uiSize]); } //Stop Hv_GpioSimSWire_Stop(enBus); return HV_SUCCESS; } /** Receive in master mode an amount of data * @param ucDevAddr target device address * @param pucData pointer to data buffer to be transmited * @param usDataSize amount of data to be receive * @retval Status SUCESS/FAILURE */ Status Hv_Drv_GpioSimSWire_RecvData(SWireID enBus, UCHAR8 *pucData, USHORT16 usDataSize) { HV_ASSERT_TRUE(enBus < SIMSWIRE_ID_MAX); HV_ASSERT_VALID_PTR_RET(pucData, HV_FAILURE); UINT32 uiSize = 0; //Start Hv_GpioSimSWire_Start(enBus); for (uiSize = 0; uiSize < usDataSize; uiSize++) { pucData[uiSize] = Hv_GpioSimSWire_Recv_Byte(enBus); } //Stop Hv_GpioSimSWire_Stop(enBus); return HV_SUCCESS; }