📄 c_i2c.c
字号:
/*=================================================================
c_i2c.c:
Description:
This is a C implement of i2c.Compare to the previous IOP
implement,it is more fast and easy to modify by programer.
On the other hand,it consume more system time.So,delay must
be carefully considered.
This code is currently use by HD DVD,for we need such a high
speed I2C interface to initialize SPV311 and maintain the HDCP
protocol.
Read/Write operation for 24C02 is also using this way in HD
DVD case.For some types of 24C02 may not work well in high
speed,engineer should adjust some timming to improve the
capability.
huziqin 2004-11-23
================================================================*/
#include "config.h"
#include "regmap.h"
#include "global.h"
#include "user_init.h"
#include "gpio.h"
#if defined(DVI_I2C_SET)&&defined(SPHE8202)
#define K_loopMax 200//
#ifdef SPHE8202
#define I2C_SDA 56 /*pin 200*/
#define I2C_SCL 51 /*pin 194*/
#else
#define I2C_SDA 1 // GPIOE[0]
#define I2C_SCL 0 // GPIOE[1]
#endif
#ifdef SPHE8202
#ifdef NEW_HDDVD_GPIO//add by chenzhao on 2004-12-14 16:11
#define DDC_SDA 32
#define DDC_SCL 33
#else
#define DDC_SDA 44
#define DDC_SCL 43
#endif
#else
#error define
#define DDC_SDA // GPIOE[0]
#define DDC_SCL // GPIOE[1]
#endif
//======================================================
#define I2C_PULL_HIGH//Addedd by ChenZhao on 2004-10-13 13:59
#define I2C_SCL_SET(d) GPIO_O_SET(I2C_SCL,d)
#define I2C_SDA_SET(d) GPIO_O_SET(I2C_SDA,d)
#define I2C_SDA_GET() GPIO_I_GET(I2C_SDA)
#define I2C_SCL_IN() GPIO_E_SET(I2C_SCL,0)
#define I2C_SDA_IN() GPIO_E_SET(I2C_SDA,0)
#define I2C_SCL_OUT() GPIO_E_SET(I2C_SCL,1)
#define I2C_SDA_OUT() GPIO_E_SET(I2C_SDA,1)
#ifdef I2C_PULL_HIGH
#define I2C_SDA_H() GPIO_E_SET(I2C_SDA,0)
#define I2C_SDA_L() {I2C_SDA_SET(0);GPIO_E_SET(I2C_SDA,1);}
#define I2C_SCL_H() GPIO_E_SET(I2C_SCL,0)
#define I2C_SCL_L() {I2C_SCL_SET(0);GPIO_E_SET(I2C_SCL,1);}
#else
#define I2C_SDA_H() {I2C_SDA_SET(1);GPIO_E_SET(I2C_SDA,1);}
#define I2C_SDA_L() {I2C_SDA_SET(0);GPIO_E_SET(I2C_SDA,1);}
#define I2C_SCL_H() {I2C_SCL_SET(1);GPIO_E_SET(I2C_SCL,1);}
#define I2C_SCL_L() {I2C_SCL_SET(0);GPIO_E_SET(I2C_SCL,1);}
#endif//I2C_PULL_HIGH
#define DDC_PULL_HIGH//Addedd by ChenZhao on 2004-10-13 13:59
#define DDC_SCL_SET(d) GPIO_O_SET(DDC_SCL,d)
#define DDC_SDA_SET(d) GPIO_O_SET(DDC_SDA,d)
#define DDC_SDA_GET() GPIO_I_GET(DDC_SDA)
#define DDC_SCL_IN() GPIO_E_SET(DDC_SCL,0)
#define DDC_SDA_IN() GPIO_E_SET(DDC_SDA,0)
#define DDC_SCL_OUT() GPIO_E_SET(DDC_SCL,1)
#define DDC_SDA_OUT() GPIO_E_SET(DDC_SDA,1)
#ifdef DDC_PULL_HIGH
#define DDC_SDA_H() GPIO_E_SET(DDC_SDA,0)
#define DDC_SDA_L() {DDC_SDA_SET(0);GPIO_E_SET(DDC_SDA,1);}
#define DDC_SCL_H() GPIO_E_SET(DDC_SCL,0)
#define DDC_SCL_L() {DDC_SCL_SET(0);GPIO_E_SET(DDC_SCL,1);}
#else
#define DDC_SDA_H() {DDC_SDA_SET(1);GPIO_E_SET(DDC_SDA,1);}
#define DDC_SDA_L() {DDC_SDA_SET(0);GPIO_E_SET(DDC_SDA,1);}
#define DDC_SCL_H() {DDC_SCL_SET(1);GPIO_E_SET(DDC_SCL,1);}
#define DDC_SCL_L() {DDC_SCL_SET(0);GPIO_E_SET(DDC_SCL,1);}
#endif//DDC_PULL_HIGH
/*
BIT 1 ; NORMAL I2C BUS ERR
BIT 2 : DDC ERROR
*/
BYTE i2c_err_flag = 0;
void i2c_init_io_risc();
void i2c_init_io_iop();
void i2c_start_sig();
void i2c_stop_sig();
int i2c_byte_w(int data);
void i2c_stop(void);
void init_i2c(void);
unsigned char i2c_byte_r();
void write_i2c(unsigned char addr, unsigned char aa, unsigned char data);
unsigned char read_i2c(unsigned char addr, unsigned char aa);
static void ddc_start_sig();
static int ddc_byte_w(int data);
static void ddc_stop_sig();
static void ddc_stop(void);
static void init_ddc(void);
void write_ddc(unsigned char addr, unsigned char aa, unsigned char data);
static unsigned char ddc_byte_r();
unsigned char read_ddc(unsigned char addr, unsigned char aa);
static void delay_gpio(int i)
{
do {
int j =6;//kevin change add it to 100 it should be also OK if setted to 2 without HDCP
do {
asm volatile ("nop");
} while (--j>=0);
} while (--i>=0);
}
#define delay_i2c(i) delay_gpio(i)
#define i2c_delay() delay_i2c(1)
#define delay_ddc(i) delay_gpio(i)
#define ddc_delay() delay_ddc(1)
//
// i2c_start_sig()
// SCL: --
// SDA: -\_
//
void i2c_start_sig()
{
I2C_SCL_H();
I2C_SDA_H();
delay_i2c(1);
I2C_SDA_L();
delay_i2c(1);
}
//
// i2c_byte_w(data)
// SCL: _/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_
// SDA: _<D7><D6><D5><D4><D3><D2><D1><D0>ACK__
//
int i2c_byte_w(int data)
{ int i;
I2C_SCL_L()
delay_i2c(1);
for(i=8;i;i--)
{ if(data&0x80){I2C_SDA_H();}
else {I2C_SDA_L();}
delay_i2c(1); // scl -- low
I2C_SCL_H(); delay_i2c(1); //hawk // scl -> high
data<<=1;
I2C_SCL_L(); delay_i2c(1); // scl -> low
}
// Get ACK
I2C_SDA_IN(); delay_i2c(1); // scl -- low
I2C_SCL_H(); delay_i2c(1); // scl -> high
i= I2C_SDA_GET(); // 0 for no error
//printf(" state=%d ",i);
I2C_SCL_L(); delay_i2c(1); // scl -> low
return ((i)?1:0);
}
//
// i2c_stop_sig()
// SCL: _/-
// SDA: __/
//
void i2c_stop_sig()
{ I2C_SDA_L(); I2C_SCL_L();delay_i2c(1);
I2C_SCL_H(); delay_i2c(1);
I2C_SDA_H();
}
void i2c_stop(void)
{
I2C_SCL_L();
I2C_SDA_L();
i2c_delay();
I2C_SCL_H();
i2c_delay();
I2C_SDA_H();
i2c_delay();
I2C_SCL_L();
i2c_delay();
I2C_SCL_H();
I2C_SDA_H();
}
void init_i2c(void)
{
I2C_SCL_H();
I2C_SDA_H();
i2c_delay();
i2c_stop();
}
//
// i2c_byte_r()
// SCL: _/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_
// SDA: _<D7><D6><D5><D4><D3><D2><D1><D0>ACK____
//
unsigned char i2c_byte_r()
{ int i;
unsigned char data=0;
I2C_SCL_L();
I2C_SDA_IN(); delay_i2c(1); // scl -> low
for(i=8;i;i--)
{ I2C_SCL_IN(); delay_i2c(1); // scl -> high
data = (data<<1) | (I2C_SDA_GET() ? 1 : 0);
I2C_SCL_L(); delay_i2c(1); // scl -> low
}
// Set ACK !!
I2C_SDA_H(); // scl -- low
delay_i2c(1); // scl -- low
I2C_SCL_H(); delay_i2c(1); // scl -> high
I2C_SCL_L(); delay_i2c(1); // scl -> low
return data;
}
void write_i2c(unsigned char addr, unsigned char aa, unsigned char data)
{ int ret=0;
// Write Addr & DATA
unsigned char loop;
//i2c_init_io_risc();
for (loop=0;loop<K_loopMax;loop++)
{
ret=0;
init_i2c();
i2c_start_sig();
ret+=i2c_byte_w(addr); //W add data(addr<<1|0); //W add data
if(ret) continue;
ret+=i2c_byte_w(aa);
if(ret) continue;
ret+=i2c_byte_w(data);
if(ret) continue;
i2c_stop_sig();
break;
}
// if (loop == K_loopMax)
// {printf("\t I2C Write error ");printf("Sub-addr 0x%x\n",addr);}
//i2c_init_io_iop();
}
unsigned char read_i2c(unsigned char addr, unsigned char aa)
{
int ret=0;
unsigned char data=0;
// Write ADDR
unsigned char loop;
//i2c_init_io_risc();
for (loop=0;loop<K_loopMax;loop++)
{
ret=0;
init_i2c();
i2c_start_sig();
ret+=i2c_byte_w(addr); //W add
if(ret) continue;
ret+=i2c_byte_w(aa);
if(ret) continue;
// i2c_stop_sig();
// Read DATA
i2c_start_sig();
ret+=i2c_byte_w(addr|1); //R data
if(ret) continue;
//{
//printf("read_i2c error!\n");
//}
// else
// printf("read ok!\n");
data=i2c_byte_r();
i2c_stop_sig();
break;
}
// if (loop == K_loopMax) {printf("\t I2C Read error ");printf("Sub-addr 0x%x\n",addr);}
//i2c_init_io_iop();
return data;
}
//
// ddc_start_sig()
// SCL: --
// SDA: -\_
//
static void ddc_start_sig()
{
DDC_SCL_H();
DDC_SDA_H();
delay_ddc(1);
DDC_SDA_L();
delay_ddc(1);
}
//
// ddc_byte_w(data)
// SCL: _/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_
// SDA: _<D7><D6><D5><D4><D3><D2><D1><D0>ACK__
//
static int ddc_byte_w(int data)
{ int i;
DDC_SCL_L()
delay_ddc(1);
for(i=8;i;i--)
{ if(data&0x80){DDC_SDA_H();}
else {DDC_SDA_L();}
delay_ddc(1); // scl -- low
DDC_SCL_H(); delay_ddc(1); //hawk // scl -> high
data<<=1;
DDC_SCL_L(); delay_ddc(1); // scl -> low
}
// Get ACK
DDC_SDA_IN(); delay_ddc(1); // scl -- low
DDC_SCL_H(); delay_ddc(1); // scl -> high
i= DDC_SDA_GET(); // 0 for no error
//printf(" state=%d ",i);
DDC_SCL_L(); delay_ddc(1); // scl -> low
return ((i)?1:0);
}
//
// ddc_stop_sig()
// SCL: _/-
// SDA: __/
//
static void ddc_stop_sig()
{ DDC_SDA_L(); DDC_SCL_L();delay_ddc(1);
DDC_SCL_H(); delay_ddc(1);
DDC_SDA_H();
}
static void ddc_stop(void)
{
DDC_SCL_L();
DDC_SDA_L();
ddc_delay();
DDC_SCL_H();
ddc_delay();
DDC_SDA_H();
ddc_delay();
DDC_SCL_L();
ddc_delay();
DDC_SCL_H();
DDC_SDA_H();
}
static void init_ddc(void)
{
DDC_SCL_H();
DDC_SDA_H();
ddc_delay();
ddc_stop();
}
void write_ddc(unsigned char addr, unsigned char aa, unsigned char data)
{
int ret;
// Write Addr & DATA
unsigned char loop;
//ddc_init_io_risc();
for (loop=0;loop<K_loopMax;loop++)
{
init_ddc();
ddc_start_sig();
ret=ddc_byte_w(addr); //W add data(addr<<1|0); //W add data
if(ret) continue;
ret=ddc_byte_w(aa);
if(ret) continue;
ret=ddc_byte_w(data);
if(ret) continue;
ddc_stop_sig();
break;
}
// if (loop == K_loopMax)
{
// printf("\t DDC Write error ");printf("Sub-addr 0x%x\n",addr);
// ddc_stop_sig();
}
//ddc_init_io_iop();
}
//
// ddc_byte_r()
// SCL: _/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_
// SDA: _<D7><D6><D5><D4><D3><D2><D1><D0>ACK____
//
static unsigned char ddc_byte_r()
{ int i;
unsigned char data=0;
DDC_SCL_L();
DDC_SDA_IN(); delay_ddc(1); // scl -> low
for(i=8;i;i--)
{ DDC_SCL_IN(); delay_ddc(1); // scl -> high
data = (data<<1) | (DDC_SDA_GET() ? 1 : 0);
DDC_SCL_L(); delay_ddc(1); // scl -> low
}
// Set ACK !!
DDC_SDA_H(); // scl -- low
delay_ddc(1); // scl -- low
DDC_SCL_H(); delay_ddc(1); // scl -> high
DDC_SCL_L(); delay_ddc(1); // scl -> low
return data;
}
unsigned char read_ddc(unsigned char addr, unsigned char aa)
{
int ret;
unsigned char data=0;
// Write ADDR
unsigned char loop;
//ddc_init_io_risc();
for (loop=0;loop<K_loopMax;loop++)
{
init_ddc();
ddc_start_sig();
ret=ddc_byte_w(addr); //W add
if(ret) continue;
ret=ddc_byte_w(aa);
if(ret) continue;
// ddc_stop_sig();
// Read DATA
ddc_start_sig();
ret=ddc_byte_w(addr|1); //R data
if(ret) continue;
data=ddc_byte_r();
ddc_stop_sig();
break;
}
if (loop == K_loopMax)
{
i2c_err_flag |= 0x02;
// printf("\t DDC Read error ");printf("Sub-addr 0x%x\n",addr);
// ddc_stop_sig();
}
//ddc_init_io_iop();
return data;
}
#endif//#if defined(DVI_I2C_SET)&&defined(SPHE8202)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -