📄 i2c.c
字号:
#include <system.h>
#include "sys/alt_stdio.h"
#include "global.h"
#include "unistd.h"
#include "utils.h"
typedef volatile struct {
unsigned int prescalerLO;
unsigned int prescalerHI;
unsigned int CTRLReg;
unsigned int TXRXReg;
unsigned int CMD_STATReg;
} OPENCORES_I2C;
static OPENCORES_I2C* c_I2C[] =
{
(OPENCORES_I2C*)I2C_HDMI_9353_BASE,
(OPENCORES_I2C*)I2C_HDMI_936_BASE,
(OPENCORES_I2C*)I2C_CS8406_BASE,
};
static OPENCORES_I2C* pI2C;
#define I2C_SPEED 100000
// control register
#define I2C_ENABLE 0x80
#define I2C_ENABLEIRQ 0x40
// command register
#define CMD_START 0x80
#define CMD_STOP 0x40
#define CMD_READ 0x20
#define CMD_WRITE 0x10
#define CMD_ACK 0x08
#define CMD_IACK 0x01
// status register
#define STAT_RXACK 0x80
#define STAT_BUSY 0x40
#define STAT_AL 0x20
#define STAT_TIP 0x02
#define STAT_IF 0x01
//*************************************************************
#define START()
#define STOP()
#define WRITE_ADDR(addr,write_bit)
#define WRITE_DATA(data)
#define READ_DATA(data)
#define ACK()
#define NAK()
//*************************************************************
static void setCurrent(int* i2c,int* bus_addr)
{
pI2C = c_I2C[*i2c];
}
//*************************************************************
static int waitTIP()
{
int timeout = (10*(ALT_CPU_FREQ/I2C_SPEED));
while((pI2C->CMD_STATReg & STAT_TIP) != 0)
{
if (timeout-- == 0)
{
return 0;
}
}
return 1;
}
//*************************************************************
static int waitAck()
{
waitTIP();
if (pI2C->CMD_STATReg & STAT_RXACK)
return 0;
return 1;
}
//*************************************************************
void I2C_Init(int i2c)
{
int addr = 0;
unsigned short prescaler = (ALT_CPU_FREQ/(5*I2C_SPEED))-1;
setCurrent(&i2c,&addr);
pI2C->CTRLReg &= ~I2C_ENABLEIRQ;
pI2C->CTRLReg &= ~I2C_ENABLE;
pI2C->prescalerHI = (prescaler>>8) & 0xFF;
pI2C->prescalerLO = (prescaler>>0) & 0xFF;
pI2C->CTRLReg |= I2C_ENABLE;
}
//*************************************************************
int I2C_Write_Explore(int i2c,unsigned char bus_addr,unsigned char reg_addr,unsigned char* i2cBuf,int len)
{
int err;
int ct;
DEBUG3("\r\n[Nios Audio] I2C_W [%x][%x][%x] > ",i2c,bus_addr,reg_addr);
setCurrent(&i2c,(int *)&bus_addr);
err = ERR_NOTRESPONDING;
ct = 0;
do
{
pI2C->TXRXReg = (bus_addr)& 0xFE;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
DEBUG("NO ACK 1w");
goto exception;
}
if (reg_addr != 0xFF)
{
pI2C->TXRXReg = reg_addr;
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 2w");
goto exception;
}
}
while(len > 0)
{
pI2C->TXRXReg = *i2cBuf;
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 4w");
goto exception;
}
i2cBuf++;
len--;
}
pI2C->CMD_STATReg = CMD_STOP;
if (!waitAck())
{
DEBUG("NO ACK 3w");
goto exception;
}
err = ERR_NONE;
goto exception1;
exception:
pI2C->CMD_STATReg = CMD_STOP;
waitTIP();
usleep(10000); //delay 10ms
exception1:
waitTIP();
}
while ( (ct++ < 3) && (err != ERR_NONE) );
return err;
}
//*************************************************************
int I2C_Read_Explore(int i2c,unsigned char bus_addr,unsigned char reg_addr,unsigned char* i2cBuf,int len)
{
int err;
int ct;
DEBUG3("\r\n[Nios Audio] I2C_R [%x][%x][%x] > ",i2c,bus_addr,reg_addr);
setCurrent(&i2c,(int *)&bus_addr);
err = ERR_NOTRESPONDING;
ct = 0;
do
{
pI2C->TXRXReg = (bus_addr)& 0xFE;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
DEBUG("NO ACK 1r");
goto exception;
}
if (reg_addr != 0xFF)
{
pI2C->TXRXReg = reg_addr;
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 2r");
goto exception;
}
}
pI2C->TXRXReg = (bus_addr)|0x01;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
DEBUG("NO ACK 3r");
goto exception;
}
while(len > 0)
{
//pI2C->TXRXReg = 0xFF;
pI2C->CMD_STATReg = CMD_READ; // in I2C bus ACK=1 means NAK
if (!waitAck())
{
DEBUG("NO ACK 5r");
goto exception;
}
*i2cBuf = pI2C->TXRXReg;
i2cBuf++;
len--;
}
pI2C->CMD_STATReg = CMD_STOP;
if (!waitAck())
{
DEBUG("NO ACK 6r");
goto exception;
}
err = ERR_NONE;
goto exception1;
exception:
pI2C->CMD_STATReg = CMD_STOP;
waitTIP();
usleep(10000); //delay 10ms
exception1:
waitTIP();
}
while ( (ct++ < 3) && (err != ERR_NONE) );
return err;
}
//*************************************************************
int I2C_Write_Explore936(int i2c,unsigned char bus_addr,unsigned char page_addr,unsigned char reg_addr, unsigned char* i2cBuf,int len)
{
DEBUG3("\r\n[Nios Audio] I2C_W [%x][%x][%x] > ",i2c,bus_addr,reg_addr);
setCurrent(&i2c,(int *)&bus_addr);
pI2C->TXRXReg = (bus_addr)& 0xFE;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
pI2C->CMD_STATReg = CMD_STOP;
usleep(10000);
pI2C->TXRXReg = (bus_addr)& 0xFE;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
DEBUG("NO ACK 1W");
goto exception;
}
}
pI2C->TXRXReg = reg_addr;
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 2w");
goto exception;
}
pI2C->TXRXReg = page_addr;
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 3w");
goto exception;
}
while(len > 0)
{
pI2C->TXRXReg = *i2cBuf;
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 4w");
goto exception;
}
i2cBuf++;
len--;
}
pI2C->CMD_STATReg = CMD_STOP;
if (!waitAck())
{
DEBUG("NO ACK 3w");
return ERR_NOTRESPONDING;
}
return ERR_NONE;
exception:
pI2C->CMD_STATReg = CMD_STOP;
waitTIP();
return ERR_NOTRESPONDING;
}
//*************************************************************
int I2C_Read_Explore936(int i2c,unsigned char bus_addr,unsigned char page_addr,unsigned char reg_addr, unsigned char* i2cBuf,int len)
{
DEBUG3("\r\n[Nios Audio] I2C_R [%x][%x][%x] > ",i2c,bus_addr,reg_addr);
setCurrent(&i2c,(int *)&bus_addr);
pI2C->TXRXReg = (bus_addr)& 0xFE;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
pI2C->CMD_STATReg = CMD_STOP;
usleep(10000);
pI2C->TXRXReg = (bus_addr)& 0xFE;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
DEBUG("NO ACK 1r");
goto exception;
}
}
pI2C->TXRXReg = reg_addr;
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 2aw");
goto exception;
}
pI2C->TXRXReg = page_addr;
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 2r");
goto exception;
}
pI2C->TXRXReg = (bus_addr)|0x01;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
DEBUG("NO ACK 3r");
goto exception;
}
while(len > 0)
{
//pI2C->TXRXReg = 0xFF;
pI2C->CMD_STATReg = CMD_READ; // in I2C bus ACK=1 means NAK
if (!waitAck())
{
DEBUG("NO ACK 5r");
goto exception;
}
*i2cBuf = pI2C->TXRXReg;
i2cBuf++;
len--;
}
pI2C->CMD_STATReg = CMD_STOP;
if (!waitAck())
{
DEBUG("NO ACK 6r");
goto exception;
}
return ERR_NONE;
exception:
pI2C->CMD_STATReg = CMD_STOP;
waitTIP();
return ERR_NOTRESPONDING;
}
//*************************************************************
int I2C_Write(int i2c,int bus_addr,int reg_addr,unsigned char* i2cBuf,int len)
{
char* _i2cBuf = i2cBuf;
int _len = len;
DEBUG3("\r\n[Nios Audio] I2C_W [%x][%x][%x] > ",i2c,bus_addr,reg_addr);
setCurrent(&i2c,&bus_addr);
pI2C->TXRXReg = (bus_addr<<1)|0x00;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
DEBUG("NO ACK 1");
goto exception;
}
if (reg_addr != -1)
{
pI2C->TXRXReg = reg_addr;
}
else
{
pI2C->TXRXReg = *i2cBuf;
i2cBuf++;
len--;
}
while(len > 0)
{
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 2");
goto exception;
}
pI2C->TXRXReg = *i2cBuf;
i2cBuf++;
len--;
}
pI2C->CMD_STATReg = CMD_WRITE|CMD_STOP;
if (!waitAck())
{
DEBUG("NO ACK 3");
return ERR_NOTRESPONDING;
}
while(_len > 0)
{
char hexBuf[4];
Utils_HexByteToStr(*_i2cBuf,hexBuf);
hexBuf[2] = 0;
DEBUG("[");
DEBUG(hexBuf);
DEBUG("]");
_i2cBuf++;
_len--;
}
//DEBUG("\r\n");
return ERR_NONE;
exception:
pI2C->CMD_STATReg = CMD_STOP;
waitTIP();
return ERR_NOTRESPONDING;
}
//*************************************************************
int I2C_Read(int i2c,int bus_addr,int reg_addr,unsigned char* i2cBuf,int len)
{
char* _i2cBuf = i2cBuf;
int _len = len;
DEBUG3("\r\n[Nios Audio] I2C_R [%x][%x][%x] > ",i2c,bus_addr,reg_addr);
setCurrent(&i2c,&bus_addr);
pI2C->TXRXReg = (bus_addr<<1)& 0xFE;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
DEBUG("NO ACK 1");
goto exception;
}
if (reg_addr != -1)
{
pI2C->TXRXReg = reg_addr;
pI2C->CMD_STATReg = CMD_WRITE;
if (!waitAck()) {
DEBUG("NO ACK 2");
goto exception;
}
}
pI2C->TXRXReg = (bus_addr<<1)|0x01;
pI2C->CMD_STATReg = CMD_START|CMD_WRITE;
if (!waitAck())
{
DEBUG("NO ACK 3");
goto exception;
}
while(len > 0)
{
if (len == 1)
pI2C->CMD_STATReg = CMD_READ|CMD_ACK; // in I2C bus ACK=1 means NAK
else
pI2C->CMD_STATReg = CMD_READ;
if (!waitTIP()) {
DEBUG("NO TIP 1");
goto exception;
}
*i2cBuf = pI2C->TXRXReg;
i2cBuf++;
len--;
}
pI2C->CMD_STATReg = CMD_STOP;
if (!waitTIP())
{
DEBUG("NO TIP 2");
goto err_done;
}
while(_len > 0)
{
char hexBuf[4];
Utils_HexByteToStr(*_i2cBuf,hexBuf);
hexBuf[2] = 0;
DEBUG("[");
DEBUG(hexBuf);
DEBUG("]");
_i2cBuf++;
_len--;
}
// DEBUG("\r\n");
return ERR_NONE;
exception:
pI2C->CMD_STATReg = CMD_STOP;
waitTIP();
err_done:
return ERR_NOTRESPONDING;
}
//END FILE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -