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

📄 i2c.c

📁 视频601芯片的驱动源码,你可以完全掌控该芯片了,对于其它多媒体芯片的设计具有参考价值
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------

$Workfile: I2C.C $
$Date: 6/20/97 3:47p $
$Revision: 8 $
* Purpose:  
*           I2C bus read and write routines.            
* Notes:       
*           Routines in this file are used by other routines in
*           "ADV7111.C" and "SAA7111.C".
*
$History: I2C.C $
 * 
 * *****************  Version 8  *****************
 * User: Stevel       Date: 6/20/97    Time: 3:47p
 * Updated in $/601cman
 * Add new header vlab.h.
 * 
 * *****************  Version 7  *****************
 * User: Dstarr       Date: 8/26/96    Time: 10:14a
 * Updated in $/601cman
 * Modified to drive clock line high instead of tristating it.  This fixed
 * the interrmittant 7175 init failures.
 * 
 * *****************  Version 6  *****************
 * User: Dstarr       Date: 7/25/96    Time: 7:40a
 * Updated in $/601cman
 * I2c read and write do three retries on error before giving up and
 * returning FAILURE.
 * 
 * *****************  Version 5  *****************
 * User: Dstarr       Date: 4/09/96    Time: 9:40a
 * Updated in $/601cman
 * Catch 32 fix.  Clr and Set mscrbit routines converted from 32 bit to 16
 * bit.  the mcsr bit routines now only access the "PAL" register in the
 * hi word of port 3.  This prevents reading or writing the ADV601 status
 * register in the low word of port 3.  This fixes two problems.  Writes
 * of the ADv601 status register will hang (no ack) unless the ADV601 is
 * out of reset.  The reset bit is in the PAL, so you have to do a 16 bit
 * access to take the ADV601 out of reset before you can read the ADV601
 * register without getting hung.  Second potential problem,  Reads of the
 * ADV601 status register CLEAR the status bits.  Only the interrupt
 * service routine (which this is NOT)  should tinker with the interrupt
 * status bits.  We haven't actually experienced any trouble YET, but
 * doing it this way will eliminate any possibilty of trouble in the
 * future.
 *     The BIT definitions for things like reset and SDA have changed from
 * 32 bit wide to 16 bit wide.  Any callers (601 test.exe) should be
 * recompiled using the latest version of i2c.h
 * 
* 
* *****************  Version 4  *****************
* User: Dstarr       Date: 4/04/96    Time: 11:22a
* Updated in $/601cman
* set and clr mcsrbit now do a 16 bit only write, not a 32 bit one.  this
* avoids "catch32" in the eval card.
* 
* *****************  Version 3  *****************
* User: Dstarr       Date: 4/03/96    Time: 11:56a
* Updated in $/601cman
* clr_mcsr_bit and set mcsr_bit now return the bits they set into the
* main control and status register.  This is of interest to the
* diagnostic program only.
* 
* *****************  Version 2  *****************
* User: Stevel       Date: 3/10/96    Time: 10:13p
* Updated in $/601cman
* Add DLLEXPORT keyword to export function in this file for diagnostic
* test.
* 
* *****************  Version 1  *****************
* User: Stevel       Date: 3/06/96    Time: 8:04p
* Created in $/601cman
* Initial release


This code and information is provided "as is" without warranty of any
kind, either expressed or implied, including but not limited to the
implied warranties of merchantability and/or fitness for a particular
purpose.

1996 Analog Devices, Inc. 

-------------------------------------------------------------------------*/
#include <windows.h>
#include <stdio.h>
#include "globsym.h"
#include "vlab.h"
#include "i2c.h"

#define BADBIT  -1
#define MAXTRY  3
static dword *      pI2CReg;            /* 32 bit ptr to PAL&ADV601 Stat reg*/
static word * ptr2pal;                  /* 16 bit ptr to just the PAL */
/////////////////////////////////////////////////////////////////////
// Define a local variable used by halfperiod() to emulate the 
// I2C clock cylce timing.
/////////////////////////////////////////////////////////////////////
static long i2cbus_hperiod;

/*  Declare private functions           */
//=================================================================
// I2C Inline function
//=================================================================

void halfperiod();
int clockhigh ();
void clocklow();

//===================================================================
// 
// Initialize the I2C Bus
//
//===================================================================
DLLEXPORT int I2CInit(dword * ptr)
{

    pI2CReg = ptr;
    ptr2pal = (word*) ptr;
    ptr2pal +=1;                        /* get the hi word  */
    clr_mcsrbit (SCL | SDA + SCL_OE + SDA_OE);

    // setup the emulate clock constant
    ClockCycleCalibrate();
    return SUCCESS;
}


//===================================================================
// 
// Clock Cycle Calibration for I2C Bus.
// 
// Return # of loops to ellase 1 usec.
//===================================================================

#define LOTTATIME   1000000L

DLLEXPORT dword ClockCycleCalibrate()
{
    long    runtime;
    long    TimeStart, TimeEnd;

    i2cbus_hperiod = LOTTATIME;         /* try something big    */
    TimeStart = GetTickCount();         /* read start time from system clock*/
    halfperiod();                       /* do LOTTATIME iterations */
    TimeEnd = GetTickCount();           /* read stop time from system clk*/
    runtime = TimeEnd - TimeStart;      /* compute elapsed time in millisec */
    runtime *= 1000L;                   /* convert runtime to microseconds */
    i2cbus_hperiod = (6L * LOTTATIME) / runtime;/* 6 usec delay loop  */
    if (i2cbus_hperiod < 1)
        i2cbus_hperiod = 1;             /* safety first */
    /*  Gives 10 usec period in 100 Mhz Pentium */
    i2cbus_hperiod = 100;               /* above code no work, so fake it  */  
    /*  Gives 100 usec period in 100 Mhz Pentium */
    i2cbus_hperiod = 1000;              /* above code no work, so fake it  */  
    return (i2cbus_hperiod);


}

//===================================================================
// 
// Emulate one clock cycle for I2C.
// The maximum speed of I2C bus is 100 KHz. That means the fast
// is 0.01 msec (10 usec). This routine is currently hard coded to
// emulate 100 usec clock cycle.  
//
//===================================================================
void halfperiod()
{
    long    i;
    long    twiddle = 0;

    for (i= 0; i < i2cbus_hperiod; i++)
        twiddle++;                      /* Optimizer might kill empty loop */
    return;
}


//===================================================================
// 
// Delay
//
//===================================================================
DLLEXPORT void Delay(int cycle)
{
    int i;

    for(i=0; i<cycle; i++)
        halfperiod();
    return;
}


DLLEXPORT int rite_i2c_chip(void * hisptr, int subaddr,int nreg )
/******************************************************************
Processing:     Do an I2C bus transmit of the register struct *ptr.
                A subset may be sent by setting subaddr to the desired byte
                to start at and indicating the number of bytes to send
                (excluding chip address and sub address bytes.  
Inputs:         ptr is address of register structure to transmit
                subaddr is the register to start with.  0 = 1st reg
                nreg is the number of data bytes to send after chip addr
                & sub address.
Outputs:        return success or failure  if no acknowledge from target chip
Side-effects    None
*******************************************************************/
{


    int rtnvar;
    byte * ptr;
    byte    chip_addr;
    int i,j;

    for (j = 0; j < MAXTRY; j++)
    {
        ptr = (byte*) hisptr;           /* defeat strong typing     */
        chip_addr = *ptr++;
        chip_addr &= 0xFE;              /* clear chip address Read bit  */
        I2CStart();
        rtnvar = I2CWriteData(chip_addr);/* send the chip address       */
        if (rtnvar == SUCCESS)
        {
            *ptr++= subaddr;
            rtnvar = I2CWriteData((byte) subaddr);   // Send  SubAddress
            if (rtnvar == SUCCESS)
            {
                ptr += subaddr;         /* point to 1st reg to xmit     */
                for (i = 0; i < nreg; i++)
                {
                    rtnvar = I2CWriteData(*ptr++); // Xmit data byte by byte
                    if (rtnvar != SUCCESS)
                        break;
                }
            }
        }
        I2CStop();
        if (rtnvar == SUCCESS)
            break;
    }
    return rtnvar;

}

DLLEXPORT int read_i2c_chip(void * hisptr, int subaddr,int nreg )
/******************************************************************
Processing:     Do an I2C bus read int0 the register struct *ptr.
                A subset may be sent by setting subaddr to the desired byte
                to start at and indicating the number of bytes to read
                (excluding chip address and sub address bytes.  
Inputs:         ptr is address of register structure to write into.
                subaddr is the register to start with.  0 = 1st reg
                nreg is the number of data bytes to read after chip
                addr & sub address.
Outputs:        return success or failure if no acknowledge from target chip.
Side-effects    None.
*******************************************************************/
{


    int rtnvar;
    int i,j;
    byte *ptr;
    byte    chip_addr;

    for (j = 0; j < MAXTRY; j++)
    {        
        ptr = (byte*) hisptr;           /* defeat strong typing */
        chip_addr = *ptr++;
        chip_addr &= ~1;                /* clr chip address Read bit */
        I2CStart();
        rtnvar = I2CWriteData(chip_addr); /* send the chip address       */
        if (rtnvar == SUCCESS)
        {
            *ptr++ = subaddr;           /* put sub address into struct */
            rtnvar = I2CWriteData((byte) subaddr);  // Send  SubAddress
            if (rtnvar == SUCCESS)
            {
                I2CStart();

                chip_addr |= 1;         /* set chip address Read bit */
                rtnvar = I2CWriteData(chip_addr);/* send the chip address*/
                if (rtnvar == SUCCESS)
                {
                    ptr += subaddr;     /* point to 1st reg to xmit */
                    for (i = 0; i < nreg - 1; i++)
                    {
                        *ptr++ =I2CReadData(); // Fetch data  byte by byte
                        I2CReadAck();   /* ack all but last byte*/
                    }
                    *ptr++ = I2CReadData(); // Fetch last byte 
                                        /* and DON't Ack it */
                }
            }
        }

        I2CStop();
        if (rtnvar == SUCCESS)
            break;
    }
    return rtnvar;

}


DLLEXPORT int readhard_i2c_chip(void * hisptr, int subaddr,int nreg )
/******************************************************************
Processing:     Do an I2C bus read int0 the register struct *ptr.
                A subset may be sent by setting subaddr to the desired byte
                to start at and indicating the number of bytes to read
                (excluding chip address and sub address bytes.
                This routine is a debug version of read_i2c_chip() above.
                It presses on rather than bailing out after a No Ack
                from the IIC bus target device which helps scope out problems.


Inputs:         ptr is address of register structure to write into.
                subaddr is the register to start with.  0 = 1st reg
                nreg is the number of data bytes to read after chip
                addr & sub address.
Outputs:        return success or failure.  Ignore negative acks and press on.
Side-effects    None.
*******************************************************************/
{


    int rtnvar;
    int i;
    byte *ptr;
    byte    chip_addr;

    ptr = (byte*) hisptr;           /* defeat strong typing */
    chip_addr = *ptr++;
    chip_addr &= ~1;                /* clr chip address Read bit */
    I2CStart();
    rtnvar = I2CWriteData(chip_addr);/* send the chip address       */
    *ptr++ = subaddr;               /* put sub address into struct */
    rtnvar |= I2CWriteData((byte) subaddr);  // Send  SubAddress
    /*  I2CStop(); */ /* 7175 won't work with this in */
    I2CStart();

    chip_addr |= 1;                 /* set chip address Read bit */
    rtnvar |= I2CWriteData(chip_addr);/* send the chip address*/
    ptr += subaddr;                 /* point to 1st reg to xmit */
    for (i = 0; i < nreg - 1; i++)

⌨️ 快捷键说明

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