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

📄 i2c.c

📁 opencore i2c to niosII
💻 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 + -