⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c_hal.c

📁 SigmDesign SMP8634 media decode chip development SDK
💻 C
字号:
/* * * Copyright (c) Sigma Designs, Inc. 2002. All rights reserved. * *//**	@file i2c.c	@brief implemetation for I2C - using PIOs	@author Aurelia Popa-Radu, Christian Wolff*/#include "../../../rmdef/rmdef.h"#include "../../../llad/include/gbus.h"#include "../../include/emhwlib_registers.h"#include "../include/i2c_hal.h"#define XTAL_REG (REG_BASE_system_block + SYS_xtal_in_cnt)  // Location of the XTal counter register#define XTAL_MHZ 27       // XTal frequency (in MHz)#define ACK_TIMEOUT 10    // Waiting-for-Acknowlede Timeout, in uSec#define ARB_TIMEOUT 1000  // Arbitration Timeout, in uSec#define MASK_0 0x00010000#define MASK_1 0x00010001// --- time functionsstatic RMuint32 I2C_RM27MicroSecondElapsed(struct gbus* pGBus, RMuint32 t0){	RMuint32 t1;	t1 = gbus_read_uint32(pGBus, XTAL_REG);	if (t1 >= t0) return t1 - t0;	else return 0xFFFFFFFF - t0 + t1 + 1;}static void I2C_RMMicroSecondSleep(struct gbus* pGBus, RMuint32 t0, RMuint32 us){	// implementation safe for delays smaller than 0xFFFFFFFF/27 us = 159 sec	// if SYS_xtal_in_cnt doesn't work - hang here !! 	while (I2C_RM27MicroSecondElapsed(pGBus, t0) < XTAL_MHZ * us);}// --- media level functions with arbitration detection// all operations, on encountering an error, release the bus by tri-stating data and clockstatic RMstatus I2C_Clock(struct i2c* pI2C, RMbool clock){	RMuint32 t0;	t0 = gbus_read_uint32(pI2C->pGBus, XTAL_REG);	if (clock) {  // read from clock line, wait until high		gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_dir,			MASK_0 << pI2C->PioClock);  // input		while ((gbus_read_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_data) & (1 << pI2C->PioClock)) == 0) {			if (I2C_RM27MicroSecondElapsed(pI2C->pGBus, t0) > XTAL_MHZ * ARB_TIMEOUT) {  // timeout 1 ms				// tri-state data and clock line				gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_dir,					(MASK_0 << pI2C->PioData) | (MASK_0 << pI2C->PioClock));  // input				return RM_TIMEOUT;			}		}	} else {  // write low to clock line		gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_data,			MASK_0 << pI2C->PioClock);		gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_dir,			MASK_1 << pI2C->PioClock);  // output	}	if (pI2C->DelayUs)		I2C_RMMicroSecondSleep(pI2C->pGBus, t0, pI2C->DelayUs);	// The delay is too long but is not system dependent		return RM_OK;}static RMstatus I2C_Data(struct i2c* pI2C, RMbool data){	RMuint32 t0;	t0 = gbus_read_uint32(pI2C->pGBus, XTAL_REG);	if (data) {  // read from data line, wait until high		gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_dir,			MASK_0 << pI2C->PioData);  // input		while ((gbus_read_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_data) & (1 << pI2C->PioData)) == 0) {			if (I2C_RM27MicroSecondElapsed(pI2C->pGBus, t0) > XTAL_MHZ * ARB_TIMEOUT) {  // timeout 1 ms				// tri-state data and clock line				gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_dir,					(MASK_0 << pI2C->PioData) | (MASK_0 << pI2C->PioClock));  // input				return RM_TIMEOUT;			}		}	} else {  // write low to data line		gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_data,			MASK_0 << pI2C->PioData);		gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_dir,			MASK_1 << pI2C->PioData);  // output	}	if (pI2C->DelayUs)		I2C_RMMicroSecondSleep(pI2C->pGBus, t0, pI2C->DelayUs);	// The delay is too long but is not system dependent		return RM_OK;}// --- bit level functions// all operations, except Stop, end with Clock==low, blocking the bus for other mastersstatic RMstatus I2C_WrBit(struct i2c* pI2C, RMbool data){// send one bit//        _// Ck   _| |_//       ___// Data X___X	RMstatus err;		if (RMFAILED(err = I2C_Data(pI2C, data))) return err;	if (RMFAILED(err = I2C_Clock(pI2C, 1))) return err;	if (RMFAILED(err = I2C_Clock(pI2C, 0))) return err;		return RM_OK;}static RMstatus I2C_RdBit(struct i2c* pI2C, RMbool *data){// read one bit//        _// Ck   _| |_//       ___// Data X___X	RMstatus err;		gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_dir,		MASK_0 << pI2C->PioData);  // input	if (RMFAILED(err = I2C_Clock(pI2C, 1))) return err;	*data = (gbus_read_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_data) & (1 << pI2C->PioData)) ? 1 : 0;	if (RMFAILED(err = I2C_Clock(pI2C, 0))) return err;		return RM_OK;}static RMstatus I2C_Start( struct i2c* pI2C ){// Data goes high-to-low while Ck is high//        ___// Ck   _|   |_//      ___// Data    |___	RMstatus err;		// start sequence	if (RMFAILED(err = I2C_Data(pI2C, 1))) return err;	if (RMFAILED(err = I2C_Clock(pI2C, 1))) return err;	if (RMFAILED(err = I2C_Data(pI2C, 0))) return err;	if (RMFAILED(err = I2C_Clock(pI2C, 0))) return err;		return RM_OK;}static RMstatus I2C_Stop( struct i2c* pI2C ){// Data goes low-to-high while Ck is high//        __// Ck   _|//         _// Data __|	RMstatus err;		// stop sequence	if (RMFAILED(err = I2C_Data(pI2C, 0))) return err;	if (RMFAILED(err = I2C_Clock(pI2C, 1))) return err;	if (RMFAILED(err = I2C_Data(pI2C, 1))) return err;		return RM_OK;}static RMstatus I2C_SendNack(struct i2c* pI2C){// Not-Acknowledge from master//        _// Ck   _| |_//      _____// Data 	return I2C_WrBit(pI2C, 1);}static RMstatus I2C_SendAck( struct i2c* pI2C ){// Acknowledge from master//        _// Ck   _| |_//      // Data _____	return I2C_WrBit(pI2C, 0);}static RMstatus I2C_WaitAck( struct i2c* pI2C ){//        __// Ck   _|  |_//      // Data XX____	RMstatus err;	RMuint32 t0;		t0 = gbus_read_uint32(pI2C->pGBus, XTAL_REG);		gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_dir,		MASK_0 << pI2C->PioData);  // input	if (RMFAILED(err = I2C_Clock(pI2C, 1))) return err;	while (gbus_read_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_data) & (1 << pI2C->PioData)) {		if (I2C_RM27MicroSecondElapsed(pI2C->pGBus, t0) > XTAL_MHZ * ACK_TIMEOUT) {  // timeout 10 us			// tri-state data and clock line			gbus_write_uint32(pI2C->pGBus, pI2C->RegBase + SYS_gpio_dir,				(MASK_0 << pI2C->PioData) | (MASK_0 << pI2C->PioClock));  // input			return RM_TIMEOUT;		}	}	if (RMFAILED(err = I2C_Clock(pI2C, 0))) return err;	return RM_OK;}// --- byte level functionsstatic RMstatus I2C_WrByte(struct i2c* pI2C, RMuint8 ByteIn){//        _   _   _   _   _   _   _   _// Ck   _| |_| |_| |_| |_| |_| |_| |_| |_//       ___ ___ ___ ___ ___ ___ ___ ___ // Data X___X___X___X___X___X___X___X___	RMuint32 i;	RMstatus err;		for (i = 0; i < 8; i++) {		if (RMFAILED(err = I2C_WrBit(pI2C, ByteIn & 0x80))) return err;		ByteIn <<= 1;	}	return RM_OK;}static RMstatus I2C_RdByte(struct i2c* pI2C, RMuint8 *data){//        _   _   _   _   _   _   _   _// Ck   _| |_| |_| |_| |_| |_| |_| |_| |_//       ___ ___ ___ ___ ___ ___ ___ ___ // Data X___X___X___X___X___X___X___X___	RMuint32 i;	RMbool bit;	RMstatus err;		for (i = 0; i < 8; i++) {		if (RMFAILED(err = I2C_RdBit(pI2C, &bit))) return err;		*data = (*data << 1) | (bit ? 1 : 0);	}	return RM_OK;}// --- externally available byte block functionsRMstatus I2C_Write(struct i2c* pI2C, RMuint8 SubAddress, RMuint8* pData, RMuint32 n){	RMuint32 i;	RMstatus err;	// Start,WrByte(WrAddress),WaitAck,WrByte(SubAddress),WaitAck,	if (RMFAILED(err = I2C_Start(pI2C))) return err;	if (RMFAILED(err = I2C_WrByte(pI2C, pI2C->WrAddr))) return err;	if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;	if (RMFAILED(err = I2C_WrByte(pI2C, SubAddress))) return err;	if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;		// if not last byte repeat(WrByte,WaitAck),Stop	for (i = 0; i < n; i++) {		if (RMFAILED(err = I2C_WrByte( pI2C, pData[i]))) return err;		if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;	}	if (RMFAILED(err = I2C_Stop(pI2C))) return err;	return RM_OK;}RMstatus I2C_Read(struct i2c* pI2C, RMuint8 SubAddress, RMuint8* pData, RMuint32 n){	RMuint32 i;	RMstatus err;		if (n < 1) return RM_ERROR;		// Start,WrByte(WrAddress),WaitAck,WrByte(SubAddress),WaitAck,	if (RMFAILED(err = I2C_Start(pI2C))) return err;	if (RMFAILED(err = I2C_WrByte(pI2C, pI2C->WrAddr))) return err;	if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;	if (RMFAILED(err = I2C_WrByte(pI2C, SubAddress))) return err;	if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;		// Start,WrByte(RdAddress),WaitAck,	if (RMFAILED(err = I2C_Start(pI2C))) return err;	if (RMFAILED(err = I2C_WrByte(pI2C, pI2C->RdAddr))) return err;	if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;		// if not last byte repeat(RdByte,Ack),RdByte(last),Nack,Stop	for (i = 0; i < n; i++) {		if (RMFAILED(err = I2C_RdByte(pI2C, &(pData[i])))) return err;		if (i == (n - 1)) {			if (RMFAILED(err = I2C_SendNack(pI2C))) return err;		} else {			if (RMFAILED(err = I2C_SendAck(pI2C))) return err;		}	}		if (RMFAILED(err = I2C_Stop(pI2C))) return err;		return RM_OK;}RMstatus I2C_Write_NoSubAddr(struct i2c* pI2C, RMuint8* pData, RMuint32 n){	RMuint32 i;	RMstatus err;		if (RMFAILED(err = I2C_Start(pI2C))) return err;	if (RMFAILED(err = I2C_WrByte(pI2C, pI2C->WrAddr))) return err;	if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;		for (i = 0; i < n; i++) {		if (RMFAILED(err = I2C_WrByte(pI2C, pData[i]))) return err;		if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;	}	if (RMFAILED(err = I2C_Stop(pI2C))) return err;		return RM_OK;}RMstatus I2C_Read_NoSubAddr(struct i2c* pI2C, RMuint8* pData, RMuint32 n){	RMuint32 i;	RMstatus err;	if (n < 1) return RM_ERROR;	if (RMFAILED(err = I2C_Start(pI2C))) return err;	if (RMFAILED(err = I2C_WrByte(pI2C, pI2C->RdAddr))) return err;	if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;		for (i = 0; i < n; i++) {		if (RMFAILED(err = I2C_RdByte(pI2C, &(pData[i])))) return err;		if (i == (n - 1)) {			if (RMFAILED(err = I2C_SendNack(pI2C))) return err;		} else {			if (RMFAILED(err = I2C_SendAck(pI2C))) return err;		}	}	if (RMFAILED(err = I2C_Stop(pI2C))) return err;		return RM_OK;}RMstatus I2C_Select_Segment( struct i2c* pI2C, RMuint8 SegmentAddr, RMuint8 Segment ){	RMstatus err;		if (RMFAILED(err = I2C_Start(pI2C))) return err;	if (RMFAILED(err = I2C_WrByte(pI2C, SegmentAddr))) return err;	if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;		if (RMFAILED(err = I2C_WrByte(pI2C, Segment))) return err;	if (RMFAILED(err = I2C_WaitAck(pI2C))) return err;		return RM_OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -