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

📄 i2c.c

📁 Zoran VP2K731 DVD源代码,极具参考价值!
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************/
/* File:															   */
/*	  Copyright (c) 2000 ZORAN Corporation, All Rights Reserved		   */
/*	  THIS IS PROPRIETARY SOURCE CODE OF ZORAN CORPORATION             */
/*																	   */
/* ===========                                                         */
/* Descripton:                                                         */
/* ===========                                                         */
/*                                                                     */
/* Log:                                                                */
/* ===                                                                 */
/* $Name: V_1_16 V_1_15 V_1_14 V_1_13 V_1_12 NV_1_00 $                                                            
/* $Header: v:/dsg/rcs/dsg/vp2k/Customer/device/i2c/i2c.c 1.13 2001/07/23 02:48:33 cliff Exp $                                                          
/* $Log: i2c.c $										                       
/* Revision 1.13  2001/07/23 02:48:33  cliff										                       
/* Revision 1.12  2001/05/17 07:17:23  leslie										                       
/* Revision 1.11  2001/04/06 01:23:56  stephaneh										                       
/* Fixed Read / Write Problem for Milleno project										                       
/* Revision 1.9  2001/02/16 00:39:27  stephaneh										                       
/* Added semaphore lock while using EEPROM for Valino Drive										                       
/* Revision 1.8  2001/01/25 20:18:02  stephaneh										                       
/* Updated sdebug comment										                       
/* Revision 1.7  2001/01/25 20:12:46  stephaneh										                       
/* Modified i2c_write( ) to return FALSE when an error occured										                       
/* Revision 1.6  2000/12/11 07:14:58  cliff										                       
/* Revision 1.5  2000/12/06 10:43:58  cliff										                       
/* Revision 1.4  2000/11/09 04:07:28  cliff										                       
/***********************************************************************/
#define RELEASE_TRACE_MODULE

#ifdef RELEASE_TRACE_MODULE
#define _DEBUG
#endif

#ifdef _DEBUG
#ifdef RELEASE_TRACE_MODULE
#define IFTRACE if (1) 
#else
#define IFTRACE if (gTraceCore) 
extern int gTraceCore;
#endif
#endif


#include <sysdefs.h>

#define sda_set_input sda_hi
#define scl_set_input scl_hi

#include "i2c_io.h"
#include "..\..\..\playcore\timing\timing.h"

#ifdef MILLENO
#include "..\..\..\kernel\ker_api.h"	// ZRN SH0215:Needed for Semaphore definition
#include "..\..\..\drive\samsung\meml_ex.h"
BOOL EEPROM_ByteWrite(BYTE addr,BYTE data);
BYTE EEPROM_ByteRead(BYTE addr);
#endif

#define I2C_MAX_WAIT	5000L	/* in microseconds */
#ifndef I2C_WAIT_MORE_TIME
	#define HOLDING_TIME	10
#else
	#define HOLDING_TIME	50
#endif

#ifndef STANDARD_I2C_PROTOCOL//ZORAN LX0517
/*
 * These local functions wait for the other end the set the bit to a
 * certain level.
 */
static BOOL wait_sda_lo(void)
{
	int i = I2C_MAX_WAIT/5;
    sda_set_input();
    while(i && !is_sda_lo()) {
		i--;
		delay_us(5);		
	}

	return i?TRUE:FALSE;
}

static BOOL wait_sda_hi(void)
{
	int i = I2C_MAX_WAIT/5;
    sda_set_input();
    while(i && !is_sda_hi()) {
		i--;
		delay_us(5);		
	}
	return i?TRUE:FALSE;
}

static BOOL wait_scl_hi(void)
{
	int i = I2C_MAX_WAIT/5;

    scl_set_input();
    while(i && !is_scl_hi()) {
		i--;
		delay_us(5);		
	}
	return i?TRUE:FALSE;
}

/*
 * This function is called before an I2C transfer is started.  A start
 * condition is signified with a high-to-low transition of SDA while SCL
 * is high.
 */
static BOOL i2c_start(void)
{
//	scl_lo();					// SEC LEE0216 :
	scl_hi();					// SEC LEE0216
    delay_us(HOLDING_TIME);

    sda_hi();
//	scl_hi();					// SEC LEE0216
    if (!wait_scl_hi())
		return FALSE;

    sda_lo();			/* this triggers the start */
    delay_us(HOLDING_TIME);
    scl_lo();
	return TRUE;
}

/*
 * The function is used to tell the device the the transmission is over.
 * The stop condition is signified by a low-to-high transition of SDA
 * while SCL is high.
 */
static BOOL i2c_stop(void)
{
    scl_lo();
    delay_us(HOLDING_TIME);

    sda_lo();
    scl_hi();
    delay_us(HOLDING_TIME);
	if (!wait_scl_hi())
		return FALSE;

    sda_hi();			/* this triggers the stop */
	if (!wait_sda_hi())
		return FALSE;
	return TRUE;
}

/*
 * This function sends one byte on the I2C bus. The bits in the byte are
 * sent in the order of the high bit first and the lowest bit last.
 */

static unsigned i2c_putc(unsigned char d)
{
    unsigned char mask;
    unsigned ack;

    for (mask = 0x80; mask; mask >>= 1)
    {
		if (d & mask)
		    sda_hi();
		else
		    sda_lo();

		delay_us(HOLDING_TIME);		// SEC LEE0216 
		scl_hi();
		delay_us(HOLDING_TIME);
		scl_lo();
		delay_us(HOLDING_TIME);
    }

    sda_hi();			/* ack handshake after every byte */
    delay_us(HOLDING_TIME);

    scl_hi();
    delay_us(HOLDING_TIME);

    if (is_sda_lo())		/* sda low means an ack */
		ack = TRUE;
    else
		ack = FALSE;

    scl_lo();
    delay_us(HOLDING_TIME);		// SEC LEE0216

    return ack;
}

/*
 * This function is used to get data from another I2C device. The |rdack|
 * parameter is used to tell the device if we want to read more bytes. If
 * |rdack| is true then we want to receive the byte at the next address,
 * otherwise we don't want anymore bytes.
 */

static unsigned char i2c_getc(unsigned rdack)
{
    unsigned char d;
    unsigned char i;

    sda_hi();			/* don't drive the data line */


    for (i = 0, d = 0; i < 8; i++) {
	d <<= 1;

	scl_hi();		/* drive clock high to get data */
	delay_us(HOLDING_TIME);
	
	if (!wait_scl_hi())
		return 0xFF; /* i2c error */

	if (is_sda_hi())
	    d |= 1;		/* bit is a one */

	scl_lo();		/* drive clock back down */
	delay_us(HOLDING_TIME);
    }

    if (rdack)
	sda_lo();		/* send an ack */

    scl_hi();

	if (!wait_scl_hi())
		return 0xFF; /* i2c error */
    scl_lo();

    if (rdack)
	sda_hi();		/* release if set */

    return d;
}


static BOOL i2c_select_device( unsigned char addr, unsigned char subaddr )
{
	if (!i2c_start())
	{
#ifdef NO_C_STDLIB
		rtouts("\nError sending I2C start");
#else
		dbprintf("Error sending I2C start\n");
#endif
		return FALSE;
	}
	if (!i2c_putc(addr)){
#ifdef NO_C_STDLIB
		rtouts("\nError writing I2C address");
#else
		dbprintf("Error writing I2C address\n");
#endif
		return FALSE;
	}
	if (!i2c_putc(subaddr)){
#ifdef NO_C_STDLIB
		rtouts("\nError writing I2C subaddress");
#else
		dbprintf("Error writing I2C subaddress\n");
#endif
		return FALSE;
	}
	return TRUE;
}

/*
 * This function writes address, subaddr, and data on the I2C bus. 
 * The bits in the byte are
 * sent in the order of the high bit first and the lowest bit last.
 */

BOOL i2c_write(unsigned char addr, 
				   unsigned char subaddr, 
				   unsigned char dat)
{
	BOOL res;

#ifdef MILLENO
		res = EEPROM_ByteWrite(subaddr,dat);
#else


#ifdef VALINO_DRIVE
	semaphore_set(SEM_EEPROM);	// ZRN SH0215:Avoid conflict between Core and Drive
#endif

	if (res = i2c_select_device( addr, subaddr )){ 
		if (!(res = i2c_putc(dat)))
		{
#ifdef NO_C_STDLIB
			rtouts("\nError writing data");
#else
			dbprintf("Error writing data\n");
#endif
		}
	}

	/* <<< ZRN SH0125: Modified to return FALSE if an error occured */
	if(res == FALSE)
		i2c_stop();
	else
		res = i2c_stop();			/* done */
	/* >>> */

    if (!res)	{	/* sda low means an ack */
#ifdef NO_C_STDLIB
        rtouts("\nI2C WRITE ERROR\n");
#else
        dbprintf("I2C WRITE ERROR\n\0");
#endif
	}

#ifdef VALINO_DRIVE
	semaphore_clear(SEM_EEPROM);
#endif
#endif // MILLENO

	return res;
}

BOOL i2c_write_string( unsigned char addr, unsigned char subaddr, int count, unsigned char *data )
{
//	int retry = 10;					// SEC LEE0216
	unsigned char retry = 10;		// SEC LEE0216

	while (count&&retry){
		if (i2c_write(addr, subaddr, *data)){
			subaddr++;
			data++;
			count--;
			retry = 10;
		}
		else 
			retry--;
		delay_us(1000L); /* wait 1 ms */
	}
	return retry?TRUE:FALSE;
}

BOOL i2c_read_string( unsigned char addr, unsigned char subaddr, int count, unsigned char *data )
{
	BOOL res;

#ifdef MILLENO
	while (--count)
		*data++ = EEPROM_ByteRead(subaddr++);
	*data = EEPROM_ByteRead(subaddr);

	res = TRUE;
#else
#ifdef VALINO_DRIVE
	semaphore_set(SEM_EEPROM);
#endif
	
	if (res = i2c_select_device( addr, subaddr )){ 
		if (!i2c_start())		/* another start for read */
			return FALSE;
		i2c_putc((unsigned char)(addr|1));		/* set up for a read */
		while (--count)
			*data++ = i2c_getc(1);
		*data = i2c_getc(0);
	}
	i2c_stop();

#ifdef VALINO_DRIVE
	semaphore_clear(SEM_EEPROM);
#endif
#endif // MILLENO

	return res;
}


#ifdef MILLENO

BOOL is24_wr(BYTE data);
void ack_wr(void);


BOOL EEPROM_ByteWrite(BYTE addr,BYTE data){

	BYTE	i;
	BOOL	bRes = TRUE;

	semaphore_set(SEM_EEPROM);	// ZRN SH0215:Avoid conflict between Core and Drive

	ack_wr();						//device address set
	if(!is24_wr(addr))
	{
		bRes = FALSE;
		rtouts("\nEW Addr ERROR");	// sub address set
	}

	if(!is24_wr(data))				//data set
	{
		bRes = FALSE;
		rtouts("\nEW Data ERROR");
	}

	scl_lo();	//ECK clear
	for(i=0;i<4;i++);
	sda_lo();	//EDT clear
	for(i=0;i<4;i++);
	scl_hi();	//ECK set
	for(i=0;i<4;i++);
	sda_hi();	//EDT set
	for(i=0;i<4;i++);

	semaphore_clear(SEM_EEPROM);	// ZRN SH0215:Avoid conflict between Core and Drive

	return bRes;
}


// Return TRUE if OK, FALSE otherwise
BOOL is24_wr(BYTE data){

	BYTE	count,i;
	BOOL	bRes = TRUE;

	__DI();
//	*PTR(&P7CR_shadow) |= 0x08;
//	P7CR = *PTR(&P7CR_shadow);		//edt output port
	
	for(count=0;count<8;count++){
		scl_lo();//ECK clear
		for(i=0;i<4;i++);

		if(data&0x80)
			sda_hi();//EDT set	
		else
			sda_lo();//EDT clear

		for(i=0;i<4;i++);
		scl_hi();//ECK set
		for(i=0;i<4;i++);
		data = data<<1;

⌨️ 快捷键说明

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