📄 i2cdrv.c
字号:
/* Copyright 2001, ESS Technology, Inc. *//* SCCSID @(#)i2cdrv.c 1.32 06/06/03 *//* * $Log$ */#ifdef IIC/****************************************************************** This is a single generic I2C driver with api.*******************************************************************//* Header Files */#include "mvd.h"#include "common.h"#include "util.h"#include "ioport.h"#include "debug.h"#include "i2cdrv.h" /* my header */#if defined(BD_ABELA3) || defined(BD_HERTZ)#include "vfd.cfg"#endif#define SET_RDS_SDA SET_AUX0#define CLEAR_RDS_SDA CLEAR_AUX0#define TRISTATE_RDS_SDA TRISTATE_AUX0#define RDS_SDA_IS_HIGH AUX0_HIGH#define SET_RDS_SCL SET_AUX1#define CLEAR_RDS_SCL CLEAR_AUX1#define TRISTATE_RDS_SCL TRISTATE_AUX1#define RDS_CLK_IS_HIGH AUX1_HIGH#if 1/*********************************************************************** * I2C SDA and SCL pins * When there are multiple I2C buses, each one will have a different * set of these functions. ***********************************************************************/void set_sda(int high){ if (high) { TRISTATE_RDS_SDA; } else { CLEAR_RDS_SDA; }}void set_scl(int high){ if (high) { TRISTATE_RDS_SCL; } else { CLEAR_RDS_SCL; }}int sense_sda(){ return((RDS_SDA_IS_HIGH) ? 1:0);}int sense_scl(){ return((RDS_CLK_IS_HIGH) ? 1:0);}#endif/****************************************************************** Various Defines.*******************************************************************/#define CHEAT#ifndef PRINTF#define PRINTF(x)#endif#define I2C_DEV_MAX 3 /* maximum no. of device */#if defined(TVLIVE) && defined(REAL_TIME_CLK)#define I2C_DEV_MAX 5 /* maximum no. of device */#elif defined(TVLIVE) || defined(REAL_TIME_CLK)#define I2C_DEV_MAX 4 /* maximum no. of device */#endif#define TRY_COUNT 5 /* retry if no ack */#define I2C_TIME_NUM 13 /* total no. of time config */#define UPLIMIT (0x80000000/(3*CPUCLK)) /* for ackpolling */#define wait_timer(x) RISC_sleep_nsec(x) /* waiting time *//* device specification */typedef struct { int dev_addr; /* device I2C address */ void (*SCL_set)(int); /* SCL_set fn ptr */ void (*SDA_set)(int); /* SDA_set fn ptr */ int (*SCL_sense)(); /* SCL_sense fn ptr */ int (*SDA_sense)(); /* SDA_sense fn ptr */ /* timing info */ int tAA; /* SCL Low to SDA Data Out Valid. */ int tBUF; /* Time the Bus Must be Free before a New Transmission Can Start. */ int tHD_STA; /* Start Condition Hold Time. */ int tSU_STA; /* Start Condition Setup Time (for a Repeated Start Condition). */ int tLOW; /* Clock Low Time. */ int tHIGH; /* Clock High Time. */ int tHD_DAT; /* Data In Hold Time. */ int tSU_DAT; /* Data In Setup Time. */ int tR; /* SDA and SCL Rise Time. */ int tF; /* SDA and SCL Fall Time. */ int tSU_STO; /* Stop Condition Setup Time. */ int tDH; /* Data Out Hold Time. */ int tWR; /* Write Cycle Time. */ /* timeout periods */ int poll_wtime; /* ack-polling timeout */ int ack_wtime; /* ack timeout */} IIC_CONFIG;/****************************************************************** Variables.*******************************************************************/static IIC_CONFIG i2c_dev[I2C_DEV_MAX]; /* device parameters */ static int i2c_dev_num = -1; /* device id used so far */static int timeout = 0; /* acknowledge timeout */static int need_to_stop = 0; /* stop if no ack *//* for debug */static int yes_ack = 0;static int no_ack = 0;/****************************************************************** Local Function Declarations.*******************************************************************/static void i2c_raise_scl(IIC_CONFIG *cptr);static void i2c_start(IIC_CONFIG *cptr); /* start condition */static void i2c_stop(IIC_CONFIG *cptr); /* stop condition */static void i2c_writebyte(IIC_CONFIG *cptr, uchar c);static int i2c_ack(IIC_CONFIG *cptr, int mode);static uchar i2c_readbyte(IIC_CONFIG *cptr);/****************************************************************** Function Definitions (Local and Global).*******************************************************************//**************************************************** Set up i2c parameters for each device and assign a device id. arguments: dev_addr i2c device address SCL_set function to toggle SCL pin SDA_set function to toggle SDA pin SCL_sense function to sense SCL pin SDA_sense function to sense SDA pin *time_array devicetiming info return: dev_id device id assigned *****************************************************/int I2C_config( int dev_addr, void (*SCL_set)(int), void (*SDA_set)(int), int (*SCL_sense)(), int (*SDA_sense)(), int *time_array){ int i; int *p; IIC_CONFIG *cptr; PRINTF(( "I2C_config 0x%x\n", dev_addr )); i2c_dev_num++; if (i2c_dev_num >= I2C_DEV_MAX) { EPRINTF(("I2C_config: exceed max no. of devices!\n")); return(-1); } /* configure device parameters */ cptr = i2c_dev + i2c_dev_num; cptr->dev_addr = dev_addr; cptr->SCL_set = SCL_set; cptr->SDA_set = SDA_set; cptr->SCL_sense = SCL_sense; cptr->SDA_sense = SDA_sense; p = &(cptr->tAA); /* ptr to the first timing parameter */ for (i = 0; i < I2C_TIME_NUM; i++) /* load timing parameters */ *(p++) = *(time_array++); /* calculate wait time for I2C_ackpolling */ if (cptr->tWR >= UPLIMIT) cptr->poll_wtime = 3 * ((cptr->tWR)/10000) * CPUCLK; /* if tWR is large */ else cptr->poll_wtime = 3 * (cptr->tWR) * CPUCLK / 10000; /* calculate wait time for i2c_ack */ cptr->ack_wtime = (cptr->tHIGH) * CPUCLK / 10000; /* To confirm the device */ for (i=0; i<TRY_COUNT; i++) { timeout = 0; wait_timer(cptr->tBUF); i2c_start(cptr); i2c_writebyte(cptr, cptr->dev_addr); i2c_stop(cptr); wait_timer(cptr->tWR); if (!timeout) return(i2c_dev_num); } i2c_dev_num--; return (-1);}/**************************************************** Write a byte to the i2c device specified by its device id. arguments: dev_id device id addr address to be written ( ignore if < 0 ) data data to be written return: 0 okay (got ack) -1 error (no ack) *****************************************************/int I2C_bytewrite(int dev_id, int addr, uchar data){ int i; uchar w_addr = (uchar)(addr & 0xff); IIC_CONFIG *cptr; #ifdef BIG_E2PROM uchar hw_addr = (uchar)(((addr & 0x700)>>7)&0x0e);#endif /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (i = 0; i < TRY_COUNT; i++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time: both SCL and SDA are high */ i2c_start(cptr); /* start condition */#ifdef BIG_E2PROM{ if(addr>255) { i2c_writebyte(cptr, (cptr->dev_addr)|hw_addr); } else i2c_writebyte(cptr, cptr->dev_addr);}#else i2c_writebyte(cptr, cptr->dev_addr); /* control byte */#endif if( addr >= 0 ) { i2c_writebyte(cptr, w_addr); /* word address */ } i2c_writebyte(cptr, data); /* data */ i2c_stop(cptr); /* stop condition */#ifndef CHEAT wait_timer(cptr->tWR); /* write cycle time */#endif if (!timeout) return(0); } return(-1); /* timeout without acknowledge after several attempts */} #ifdef REAL_TIME_CLK/**************************************************** Write a byte to the i2c device specified by its device id. arguments: dev_id device id addr address to be written ( ignore if < 0 ) data data to be written return: 0 okay (got ack) -1 error (no ack) *****************************************************/int RtcI2CByteWrite(int dev_id, int addr, uchar data){ int i; uchar w_addr = (uchar)(addr & 0xff); IIC_CONFIG *cptr; /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (i = 0; i < TRY_COUNT; i++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time: both SCL and SDA are high */ i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, cptr->dev_addr); /* control byte */ if( addr >= 0 ) { i2c_writebyte(cptr, 0x0); /* word address */ i2c_writebyte(cptr, w_addr); /* word address */ } i2c_writebyte(cptr, data); /* data */ i2c_stop(cptr); /* stop condition */#ifndef CHEAT wait_timer(cptr->tWR); /* write cycle time */#endif if (!timeout) return(0); } return(-1); /* timeout without acknowledge after several attempts */} #endif /* REAL_TIME_CLK */ /**************************************************** Read a byte from the i2c device specified by its device id. arguments: dev_id device id addr address to be read (ignore if < 0 ) return: >= 0 data read -1 error (no ack)*****************************************************/int I2C_byteread(int dev_id, int addr){ int i; uchar b; uchar w_addr = (uchar)(addr & 0xff); IIC_CONFIG *cptr; #ifdef BIG_E2PROM uchar hw_addr = (uchar)(((addr & 0x700)>>7)&0x0e);#endif /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (i = 0; i < TRY_COUNT; i++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time: both SCL and SDA are high */ if( addr >= 0 ) { i2c_start(cptr); /* start condition */#ifdef BIG_E2PROM if(addr>255) { i2c_writebyte(cptr, (cptr->dev_addr)|hw_addr); } else i2c_writebyte(cptr, cptr->dev_addr);#else i2c_writebyte(cptr, cptr->dev_addr); /* control byte: for write */#endif i2c_writebyte(cptr, w_addr); /* word address */ } i2c_start(cptr); /* start condition */#ifdef BIG_E2PROM if(addr>255) { i2c_writebyte(cptr, ((cptr->dev_addr)|hw_addr) | 0x01 ); } else i2c_writebyte(cptr, (cptr->dev_addr) | 0x01);#else i2c_writebyte(cptr, (cptr->dev_addr) | 0x01);#endif /* control byte: for read */ b = i2c_readbyte(cptr); /* read one byte of data */ /* ack clock cycle: no ack is needed for read */ i2c_ack(cptr, 0); i2c_stop(cptr); /* stop condition */ if (!timeout) return(b); /* data read */ } return(-1); /* timeout without acknowledge after several attempts */}#ifdef REAL_TIME_CLK/**************************************************** Read a byte from the i2c device specified by its device id. arguments: dev_id device id addr address to be read (ignore if < 0 ) return: >= 0 data read -1 error (no ack)*****************************************************/int RtcI2CByteRead(int dev_id, int addr){ int i; uchar b; uchar w_addr = (uchar)(addr & 0xff); IIC_CONFIG *cptr; /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (i = 0; i < TRY_COUNT; i++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time: both SCL and SDA are high */ if( addr >= 0 ) { i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, cptr->dev_addr); /* control byte: for write */ i2c_writebyte(cptr, 0x0); /* word address */ i2c_writebyte(cptr, w_addr); /* word address */ } i2c_start(cptr); /* start condition */ i2c_writebyte(cptr, (cptr->dev_addr) | 0x01); /* control byte: for read */ b = i2c_readbyte(cptr); /* read one byte of data */ /* ack clock cycle: no ack is needed for read */ i2c_ack(cptr, 0); i2c_stop(cptr); /* stop condition */ if (!timeout) return(b); /* data read */ } return(-1); /* timeout without acknowledge after several attempts */}#endif /* REAL_TIME_CLK *//**************************************************** Write n bytes to the i2c device specified by its device id. arguments: dev_id device id addr starting address to be written ( ignore if < 0 ) n no. of bytes to be written s array of n data to be written return: 0 okay (got ack) -1 error (no ack)*****************************************************/int I2C_arraywrite(int dev_id, int addr, int n, uchar *s){ int i, rt; uchar w_addr = (uchar)(addr & 0xff); IIC_CONFIG *cptr;#ifdef BIG_E2PROM uchar hw_addr = (uchar)(((addr & 0x700)>>7)&0x0e);#endif /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (rt = 0; rt < TRY_COUNT; rt++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time: both SCL and SDA are high */ i2c_start(cptr); /* start condition */#ifdef BIG_E2PROM{ if(addr>255) { i2c_writebyte(cptr, (cptr->dev_addr)|hw_addr); } else i2c_writebyte(cptr, cptr->dev_addr);}#else i2c_writebyte(cptr, cptr->dev_addr); /* control byte */#endif if( addr >= 0 ) { i2c_writebyte(cptr, w_addr); /* starting address */ } for (i = 0; i < n; i++) { i2c_writebyte(cptr, s[i]); } i2c_stop(cptr); /* stop condition */ wait_timer(cptr->tWR); /* write cycle time */ if (!timeout) return(0); } return(-1);}#ifdef REAL_TIME_CLK/**************************************************** Write n bytes to the i2c device specified by its device id. arguments: dev_id device id addr starting address to be written ( ignore if < 0 ) n no. of bytes to be written s array of n data to be written return: 0 okay (got ack) -1 error (no ack)*****************************************************/int RtcI2CArrayWrite(int dev_id, int addr, int n, uchar *s){ int i, rt; uchar w_addr = (uchar)(addr & 0xff); IIC_CONFIG *cptr; /* ptr to device parameters */ cptr = i2c_dev + dev_id; for (rt = 0; rt < TRY_COUNT; rt++) { /* try again if no ack */ timeout = 0; /* reset timeout */ wait_timer(cptr->tBUF); /* bus free time:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -