📄 ci2c.c
字号:
/****************************************************************************** CI2C.c : Implementation of the I2C interface* REALmagic Quasar Hardware Library* Created by Aurelia Popa-Radu* Copyright Sigma Designs Inc* Sigma Designs Proprietary and confidential* Created on 8/27/99* Description:*****************************************************************************/#include "pch.h"#include "ci2c.h"///////////////////////////////////////////////////////////////////////////// CreateInstancevoid CI2C__CreateInstance(void **pv, DWORD dwInstance){ CI2C__New((CI2C **)pv, TEXT("I2C through Quasar"), TRUE, dwInstance);}// constructionvoid CI2C__New ( CI2C** ppCI2C, TCHAR *pName, BOOL bAllocate, DWORD dwInstance){ CI2C *this = *ppCI2C ; if (bAllocate) { // Allocate CI2C *ppCI2C = OSmalloc(sizeof(CI2C)); this = (CI2C*) *ppCI2C; if(this == NULL) return; OSmemset(this, 0, sizeof(CI2C)); } // Call CObject constructor with bAllocate = FALSE CObject__New ((CObject**)ppCI2C, pName, FALSE, dwInstance); // Initialize virtual table#if defined EM85XX_OBJECT // 85xx has I2C implemented in hardware this->VTableI2C.Delete = CI2C__Delete; this->VTableI2C.Init = CEM85xxI2C__Init; this->VTableI2C.Write = CEM85xxI2C__Write; this->VTableI2C.Read = CEM85xxI2C__Read; this->VTableI2C.Write_NoSubAddr = CEM85xxI2C__Write_NoSubAddr; this->VTableI2C.Read_NoSubAddr = CEM85xxI2C__Read_NoSubAddr; this->VTableI2C.SetI2CAddress = CI2C__SetI2CAddress; this->VTableI2C.InitPropertySet = CI2C__InitPropertySet;#else // 84xx has I2C implemented with 2 PIOs this->VTableI2C.Delete = CI2C__Delete; this->VTableI2C.Init = CI2C__Init; this->VTableI2C.Write = CI2C__Write; this->VTableI2C.Read = CI2C__Read; this->VTableI2C.Write_NoSubAddr = CI2C__Write_NoSubAddr; this->VTableI2C.Read_NoSubAddr = CI2C__Read_NoSubAddr; this->VTableI2C.SetI2CAddress = CI2C__SetI2CAddress; this->VTableI2C.InitPropertySet = CI2C__InitPropertySet;#endif // Initialize members this->lpVtbl = &this->VTableI2C; QueryInterface(this->m_dwInstance, IID_ISETI2CPIO, (void**)&(this->pISetI2CpIO));}// destructionvoid CI2C__Delete ( II2C* pII2C, BOOL bDeleteObject ){ CI2C *this = (CI2C*) pII2C ; if (this == NULL) return; // Call CObject Destructor CObject__Delete ((IObject*)this, FALSE); if (bDeleteObject) { // Delete CI2C OSfree(pII2C); }}void CI2C__Init ( II2C* pII2C ){ CI2C *this = (CI2C*) pII2C ; I2CPARAMS* pI2Cparams; ISetI2CpIO_GetI2C_params(this->pISetI2CpIO, (void**)&pI2Cparams); this->m_dwData0 = pI2Cparams->m_dwData0; this->m_dwData1 = pI2Cparams->m_dwData1; this->m_dwDataIN = pI2Cparams->m_dwDataIN; this->m_dwDataOUT = pI2Cparams->m_dwDataOUT; this->m_dwClock0 = pI2Cparams->m_dwClock0; this->m_dwClock1 = pI2Cparams->m_dwClock1; this->m_dwClkIN = pI2Cparams->m_dwClkIN; this->m_dwClkOUT = pI2Cparams->m_dwClkOUT;}////////////////////////////////////////////////////////////////////////////////////////////// I2C functions to program any I2C device ( TvEncoder, EEPROM )void CI2C__SetI2CAddress( II2C* pII2C, BYTE WriteAddr, BYTE ReadAddr, int bDelay){ CI2C *this = (CI2C*) pII2C ; this->m_bI2cWriteAddr = WriteAddr; this->m_bI2cReadAddr = ReadAddr; this->m_bDelay = bDelay;}void CI2C__I2C( II2C* pII2C, BOOL clock, BOOL data ){ CI2C *this = (CI2C*) pII2C ; if(clock) ISetI2CpIO_WrClock(this->pISetI2CpIO, this->m_dwClock1); else ISetI2CpIO_WrClock(this->pISetI2CpIO, this->m_dwClock0); if(this->m_bDelay) OSTimeDelay(this->m_bDelay); // The delay is too long but is not system dependent if(data) ISetI2CpIO_WrData(this->pISetI2CpIO, this->m_dwData1); else ISetI2CpIO_WrData(this->pISetI2CpIO, this->m_dwData0); if(this->m_bDelay) OSTimeDelay(this->m_bDelay); // The delay is too long but is not system dependent}void CI2C__I2CR( II2C* pII2C, BOOL clock) // used only for read sequence{ CI2C *this = (CI2C*) pII2C ; if(clock) ISetI2CpIO_WrClock(this->pISetI2CpIO, this->m_dwClock1); else ISetI2CpIO_WrClock(this->pISetI2CpIO, this->m_dwClock0); if(this->m_bDelay) OSTimeDelay(this->m_bDelay); // The delay is too long but is not system dependent}void CI2C__I2CStart( II2C* pII2C ){ CI2C *this = (CI2C*) pII2C ; ISetI2CpIO_WrClock( this->pISetI2CpIO, this->m_dwClock1 ); ISetI2CpIO_WrData( this->pISetI2CpIO, this->m_dwData1 ); ISetI2CpIO_SetClockDir( this->pISetI2CpIO, this->m_dwClkOUT ); ISetI2CpIO_SetDataDir(this->pISetI2CpIO, this->m_dwDataOUT ); CI2C__I2C( pII2C, 1, 1 ); CI2C__I2C( pII2C, 1, 0 ); CI2C__I2C( pII2C, 0, 0 );}void CI2C__I2CStop( II2C* pII2C ){ CI2C *this = (CI2C*) pII2C ; CI2C__I2C( pII2C, 0, 0 ); CI2C__I2C( pII2C, 1, 0 ); CI2C__I2C( pII2C, 1, 1 ); ISetI2CpIO_SetClockDir( this->pISetI2CpIO, this->m_dwClkIN ); ISetI2CpIO_SetDataDir( this->pISetI2CpIO, this->m_dwDataIN );}BOOL CI2C__I2CAck( II2C* pII2C ){ CI2C *this = (CI2C*) pII2C ; DWORD ulTimeOut = 0x1000; ISetI2CpIO_SetDataDir( this->pISetI2CpIO, this->m_dwDataIN ); CI2C__I2C( pII2C, 1, 0 ); // wait until data becomes 0 while(--ulTimeOut && (ISetI2CpIO_RdData(this->pISetI2CpIO, this->m_dwData0)) ); if(!ulTimeOut) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("I2CAckTO"))); return FALSE; } CI2C__I2C( pII2C, 0, 0 ); return TRUE;}void CI2C__I2CByte( II2C* pII2C, BYTE b ){ CI2C *this = (CI2C*) pII2C ; int i; BYTE bit; ISetI2CpIO_SetDataDir( this->pISetI2CpIO, this->m_dwDataOUT ); for ( i=0; i<8; i++ ) { bit = (b&0x80)>>7; CI2C__I2C( pII2C, 0, bit ); CI2C__I2C( pII2C, 1, bit ); CI2C__I2C( pII2C, 0, bit ); b <<= 1; } ISetI2CpIO_SetDataDir( this->pISetI2CpIO, this->m_dwDataIN );}BYTE CI2C__I2CRead( II2C* pII2C ){ CI2C *this = (CI2C*) pII2C ; int i; DWORD bit; DWORD ret = 0; ISetI2CpIO_SetDataDir( this->pISetI2CpIO, this->m_dwDataIN ); for ( i=0;i<8;i++) { CI2C__I2CR( pII2C, 1 ); bit = ISetI2CpIO_RdData(this->pISetI2CpIO, this->m_dwData0); CI2C__I2CR( pII2C, 0 ); ret = (ret<<1) + bit; } return (BYTE)ret;}// I2CStart__I2CByte(I2c_WriteAddress)__I2CAck__I2CByte(SubAddress)__I2CAck__{I2CByte(pData[i])__I2CAck}__I2CStopBOOL CI2C__Write( II2C* pII2C, BYTE adr, BYTE* pData, int n ){// "adr" = address of first register to write// "pData" = pointer to "n" consecutive bytes to write CI2C *this = (CI2C*) pII2C ; int i, TimeOutError = 0; CI2C__I2CStart( pII2C); CI2C__I2CByte( pII2C, this->m_bI2cWriteAddr); if( !CI2C__I2CAck(pII2C) ) TimeOutError++; CI2C__I2CByte( pII2C, adr); if( !CI2C__I2CAck(pII2C) ) TimeOutError++; for(i=0; i<n;i++) { CI2C__I2CByte( pII2C, pData[i]); if( !CI2C__I2CAck(pII2C) ) TimeOutError++; } ISetI2CpIO_SetDataDir( this->pISetI2CpIO, this->m_dwDataOUT ); CI2C__I2CStop( pII2C ); return TimeOutError ? FALSE:TRUE ;}// I2CStart__I2CByte(I2c_WriteAddress)__I2CAck__I2CByte(SubAddress)__I2CStart__I2CByte(I2c_ReadAddress)__I2CAck__I2CByte(SubAddress)__I2CAck__{I2CByte(pData[i])__Nack}__I2CByte(last)__Ack__I2CStopBOOL CI2C__Read( II2C* pII2C, BYTE adr, BYTE* pData, int n ){// "adr" = address of first register to write// "pData" = pointer to "n" consecutive bytes to write CI2C *this = (CI2C*) pII2C ; int i, TimeOutError = 0; if (n < 1) return FALSE; CI2C__I2CStart( pII2C ); CI2C__I2CByte( pII2C, this->m_bI2cWriteAddr); if( !CI2C__I2CAck(pII2C) ) TimeOutError++; CI2C__I2CByte( pII2C, adr); if( !CI2C__I2CAck(pII2C) ) TimeOutError++; //delay(1000);// this delay is very important if the pull-up resistor on I2C Data is not equipped CI2C__I2CStart( pII2C ); CI2C__I2CByte( pII2C, this->m_bI2cReadAddr); if( !CI2C__I2CAck(pII2C) ) TimeOutError++; // fix reading consecutive registers sending NACK in between 2 reads for( i=0; i < n; i++ ) { pData[i] = CI2C__I2CRead( pII2C ); ISetI2CpIO_SetDataDir( this->pISetI2CpIO, this->m_dwDataOUT ); if(i == (n-1)) { //Not-Acknowledge from master CI2C__I2C( pII2C, 0, 1 ); CI2C__I2C( pII2C, 1, 1 ); CI2C__I2C( pII2C, 0, 1 ); } else { //Acknowledge from master CI2C__I2C( pII2C, 0, 0 ); CI2C__I2C( pII2C, 1, 0 ); CI2C__I2C( pII2C, 0, 0 ); } } CI2C__I2CStop( pII2C ); return TimeOutError ? FALSE:TRUE ;}BOOL CI2C__Write_NoSubAddr( II2C* pII2C, BYTE* pData, int n ){// "adr" = address of first register to write// "pData" = pointer to "n" consecutive bytes to write CI2C *this = (CI2C*) pII2C ; int i, TimeOutError = 0; CI2C__I2CStart( pII2C); CI2C__I2CByte( pII2C, this->m_bI2cWriteAddr); if( !CI2C__I2CAck(pII2C) ) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("(hmwl->ci2c) Failed to transmit %x!\n"), this->m_bI2cWriteAddr)); TimeOutError++; } for(i=0; i<n;i++) { CI2C__I2CByte( pII2C, pData[i]); if( !CI2C__I2CAck(pII2C) ) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("(hmwl->ci2c) Failed to transmit %x!\n"), pData[i])); TimeOutError++; } } ISetI2CpIO_SetDataDir( this->pISetI2CpIO, this->m_dwDataOUT ); CI2C__I2CStop( pII2C ); return TimeOutError ? FALSE:TRUE ;}BOOL CI2C__Read_NoSubAddr( II2C* pII2C, BYTE* pData, int n ){// "adr" = address of first register to write// "pData" = pointer to "n" consecutive bytes to write CI2C *this = (CI2C*) pII2C ; int i, TimeOutError = 0; if (n < 1) return FALSE; CI2C__I2CStart( pII2C ); CI2C__I2CByte( pII2C, this->m_bI2cWriteAddr); if( !CI2C__I2CAck(pII2C) ) TimeOutError++; //delay(1000);// this delay is very important if the pull-up resistor on I2C Data is not equipped CI2C__I2CStart( pII2C ); CI2C__I2CByte( pII2C, this->m_bI2cReadAddr); if( !CI2C__I2CAck(pII2C) ) TimeOutError++; // fix reading consecutive registers sending NACK in between 2 reads for( i=0; i < n; i++ ) { pData[i] = CI2C__I2CRead( pII2C ); ISetI2CpIO_SetDataDir( this->pISetI2CpIO, this->m_dwDataOUT ); if(i == (n-1)) { //Not-Acknowledge from master CI2C__I2C( pII2C, 0, 1 ); CI2C__I2C( pII2C, 1, 1 ); CI2C__I2C( pII2C, 0, 1 ); } else { //Acknowledge from master CI2C__I2C( pII2C, 0, 0 ); CI2C__I2C( pII2C, 1, 0 ); CI2C__I2C( pII2C, 0, 0 ); } } CI2C__I2CStop( pII2C ); return TimeOutError ? FALSE:TRUE ;}QRESULT CI2C__SetProperty( II2C* pII2C, DWORD PropSet, DWORD PropId, DWORD Flags, void* pData, DWORD dwSizeIn, DWORD* pdwSizeOut){ CI2C* this = (CI2C*) pII2C; switch(PropId) { case eI2cInit: { I2cInit_type* pI2cInit = (I2cInit_type*)pData; CHECK_SIZE(I2cInit) QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("CI2C__SetProperty_eI2cInit: clock=%x data=%x"), pI2cInit->PIO_clock, pI2cInit->PIO_data)); ISetI2CpIO_SetI2C_params(this->pISetI2CpIO, (BYTE)pI2cInit->PIO_data, (BYTE)pI2cInit->PIO_clock); CI2C__Init(pII2C); } break; case eI2cAccess: { I2cReadWrite_type* pI2cReadWrite = (I2cReadWrite_type*)pData; if(pdwSizeOut) *pdwSizeOut = sizeof(I2cReadWrite_type); if(dwSizeIn <= sizeof(I2cReadWrite_type)) // no place for data to read or write return E_INVALID_PROPERTY_BUFFER; if( dwSizeIn < (sizeof(I2cReadWrite_type) + pI2cReadWrite->nBytes) ) // not enough place for data to read or write return E_INVALID_PROPERTY_BUFFER; CI2C__SetI2CAddress( pII2C, (BYTE)(pI2cReadWrite->I2c_WriteAddress), (BYTE)(pI2cReadWrite->I2c_ReadAddress), pI2cReadWrite->I2c_usDelay); if(pI2cReadWrite->SubAddress == 0xFFFF) // no subaddress required { return (II2C_Write_NoSubAddr(pII2C, (BYTE*)pI2cReadWrite + sizeof(I2cReadWrite_type), pI2cReadWrite->nBytes)) ? Q_OK:Q_FAIL; } else { return (II2C_Write(pII2C, (BYTE)pI2cReadWrite->SubAddress, (BYTE*)pI2cReadWrite + sizeof(I2cReadWrite_type), pI2cReadWrite->nBytes)) ? Q_OK:Q_FAIL; } } break; default: return E_NOT_SUPPORTED; } return Q_OK;}QRESULT CI2C__GetProperty( II2C* pII2C, DWORD PropSet, DWORD PropId, DWORD Flags, void* pData, DWORD dwSizeIn, DWORD* pdwSizeOut){ // CI2C* this = (CI2C*) pII2C; switch(PropId) { case eI2cAccess: { I2cReadWrite_type* pI2cReadWrite = (I2cReadWrite_type*)pData; if(pdwSizeOut) *pdwSizeOut = sizeof(I2cReadWrite_type); if( dwSizeIn <= sizeof(I2cReadWrite_type) ) // no place for data to read or write return E_INVALID_PROPERTY_BUFFER; if( dwSizeIn < (sizeof(I2cReadWrite_type) + pI2cReadWrite->nBytes) ) // not enough place for data to read or write return E_INVALID_PROPERTY_BUFFER; CI2C__SetI2CAddress( pII2C, (BYTE)(pI2cReadWrite->I2c_WriteAddress), (BYTE)(pI2cReadWrite->I2c_ReadAddress), pI2cReadWrite->I2c_usDelay); if(pI2cReadWrite->SubAddress == 0xFFFF) // no subaddress required { return (II2C_Read_NoSubAddr(pII2C, (BYTE*)pI2cReadWrite + sizeof(I2cReadWrite_type), pI2cReadWrite->nBytes)) ? Q_OK:Q_FAIL; } else { return (II2C_Read(pII2C, (BYTE)pI2cReadWrite->SubAddress, (BYTE*)pI2cReadWrite + sizeof(I2cReadWrite_type), pI2cReadWrite->nBytes)) ? Q_OK:Q_FAIL; } } break; default: return E_NOT_SUPPORTED; } return Q_OK;}void CI2C__InitPropertySet(II2C* pII2C, void* pPropSet, DWORD dwSize){ CI2C* this = (CI2C*) pII2C; if(dwSize != sizeof(PROPERTY_SET_ITEM)) return; InitPropSet(pII2C, pPropSet, I2C_SET, eI2cMax,\ this->I2CPropertyList, CI2C__SetProperty, CI2C__GetProperty)}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -