//----------------------------------------------------------------------------------------------------
// ID Code      : I2c.c No.0000
// Update Note  :
//
//----------------------------------------------------------------------------------------------------

#define __I2C__

#include "Core\Header\Include.h"

//#undef CONFIG_VBI_ENABLE
//----------------------------------------------------------------------------------------------------
// I2C communication basic function
//----------------------------------------------------------------------------------------------------
void Delay5us(void)
{
#if(_MCU_TYPE == _REALTEK_RTD2662_EMCU)
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
#else
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
#endif		
}

BYTE CI2cStart(BYTE ucDeviceAddr)
{

#if  0
	//ET1 = 0;
#endif
    SETI2CSCL();
    Delay5us();
    while(!(CHECKI2CSCL()));
    SETI2CSDA();
    CLRI2CSDA();
    Delay5us();
    CLRI2CSCL();

    return CI2cSendByte(ucDeviceAddr);
}

void CI2cStop(void)
{
    CLRI2CSDA();
    SETI2CSCL();
    Delay5us();
    SETI2CSDA();
#if  0
	//if (bVBI_INT_Enable)
	//	ET1 = 1;
#endif
}

BYTE CI2cGetAck(void)
{
    BYTE ack;

    SETI2CSDA();
    SETI2CSCL();
    Delay5us();
    ack = CHECKI2CSDA();
    CLRI2CSCL();
    SETI2CSDA();

    return ack;
}

void CI2cSendAck(void)
{
    CLRI2CSDA();
    SETI2CSCL();
    Delay5us();
    CLRI2CSCL();
}

void CI2cSendNoAck(void)
{
    SETI2CSDA();
    SETI2CSCL();
    Delay5us();
    CLRI2CSCL();
}

BYTE CI2cSendByte(BYTE ucValue)
{
    BYTE cnt;

    for(cnt=0;cnt<8;cnt++)
    {
        if((bit)(ucValue & 0x80))
            SETI2CSDA();
        else
            CLRI2CSDA();
        SETI2CSCL();
        Delay5us();
        CLRI2CSCL();
        ucValue = ucValue << 1;
    }
    if(CI2cGetAck())
    {
        CI2cStop();
        return _I2C_BUSY;
    }
    else
    {
        return _I2C_OK;
    }
}

BYTE CI2cGetByte(void)
{
    BYTE cnt, value;

    value = 0;
    SETI2CSDA();
    for(cnt=0;cnt<8;cnt++)
    {
        SETI2CSCL();
        Delay5us();
        value = (value << 1) | CHECKI2CSDA();
        CLRI2CSCL();
    }
    return value;
}

bit CI2cWriteStart(BYTE ucDeviceAddr, BYTE ucStartAddr)
{
    BYTE timeoutcnt, control;

#if  0
   //ET1 = 0;
#endif

    timeoutcnt  = _I2C_TIMEOUT_LIMIT;
    control     = ucDeviceAddr | _I2C_WR;
    while(CI2cStart(control) != _I2C_OK)
    {
        timeoutcnt--;
        if(!timeoutcnt) {
#if  0
		//if (bVBI_INT_Enable)
		//	ET1 = 1;
#endif
			return _FAIL;
        }
    }
    if(CI2cSendByte(ucStartAddr) != _I2C_OK)
        return _FAIL;
    return _SUCCESS;
}


//--------------------------------------------------
// Description  : Read data from the selected device by I2C protocol
// Input Value  : ucDeviceAddr  --> Device address
//                ucStartAddr   --> Start address of selected device
//                usLength      --> Numbers of data we want to read
//                pReadArray    --> Result array
// Output Value : Reading result (Fail/Success)
//--------------------------------------------------
bit CI2cRead(BYTE ucDeviceAddr, BYTE ucStartAddr, WORD usLength, BYTE *pReadArray)
{
    BYTE control;

    if(usLength == 0)
        return _FAIL;

    if(CI2cWriteStart(ucDeviceAddr, ucStartAddr) == _FAIL)
        return _FAIL;

    control = ucDeviceAddr | _I2C_RD;

    if(CI2cStart(control) != _I2C_OK)
        return _FAIL;

    while(--usLength)
    {
        *pReadArray++ = CI2cGetByte();
        CI2cSendAck();
    }

    *pReadArray++ = CI2cGetByte();

    CI2cSendNoAck();
    CI2cStop();

    return _SUCCESS;
}

//--------------------------------------------------
// Description  : Write data to the selected device by I2C protocol
// Input Value  : ucDeviceAddr  --> Device address
//                ucStartAddr   --> Start address of selected device
//                usLength      --> Numbers of data we want to write
//                pWriteArray   --> Writing data array
// Output Value : Write result (Fail/Success)
//--------------------------------------------------
bit CI2cWrite(BYTE ucDeviceAddr, BYTE ucStartAddr, WORD usLength, BYTE *pWriteArray)
{
    BYTE control;

    if(usLength == 0)
        return _FAIL;
    while(usLength > 0)
    {
        if(CI2cWriteStart(ucDeviceAddr, ucStartAddr) == _FAIL){
            return _FAIL;
        }

        control = _I2C_WRITE_SIZE - (ucStartAddr & 0x0f);

        if(usLength > control)
        {
            usLength -= control;
            if(ucStartAddr >= 0xf0)
                ucDeviceAddr += 2;
            ucStartAddr += control;
        }
        else
        {
            control = usLength;
            usLength = 0;
        }

        while(control--)
        {
            if(CI2cSendByte(*pWriteArray++) != _I2C_OK){
                return _FAIL;
            }
        }

        CI2cStop();
    }

    return _SUCCESS;
}

//==============================================================================
// by sky
/*
{
    _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
    _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
    _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
    _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
}
*/

#if 0
void I2CRead(unsigned char addr, unsigned char index, unsigned char count)
{
    unsigned char   n;

    if (count)
    {
        I2CSendAddr(addr, index, 0);

        I2CSendAddr(addr, 0, 1);

        count   = count - 1;

        for (n = 0; n < count; n++)     pData[n] = I2CGetByte(0);

        pData[count] = I2CGetByte(1);

        I2CSendStop();
    }
}

void I2CWrite(unsigned char *array)
{
    unsigned char   n, len;

    if (3 <= array[0])
    {
        len     = array[0];
        I2CSendAddr(array[1], array[2], 0);

        for (n = 3; n < len; n++)   I2CSendByte(array[n]);

        I2CSendStop();
    }
}

unsigned char I2CGetByte(unsigned char ack)
{
    unsigned char   r, m;

    r = 0;

    for (m = 0; m < 8; m++)         // Each bit at a time, MSB first
    {
        bIIC_SCL    = 1;
		Delay5us();//BitDly();                   // Delay

        r   = (r << 1) | bIIC_SDA;

        bIIC_SCL    = 0;
		Delay5us();//BitDly();                   // Delay
    }

    // Send ACK according to 'ack'
    bIIC_SDA    = (bit)(ack & 0x01);
	Delay5us();//BitDly();                       // Delay

    bIIC_SCL    = 1;
	Delay5us();//BitDly();                       // Delay

    bIIC_SCL    = 0;
	Delay5us();//BitDly();                       // Delay

    bIIC_SDA    = 1;

    return (r);
}

void I2CSendByte(unsigned char send)
{
    unsigned char   m;

    for (m = 0; m < 8; m++)
    {
        bIIC_SDA    = (bit)(send & 0x80);   // Send each bit, MSB first
		Delay5us();//BitDly();

        bIIC_SCL    = 1;
		Delay5us();//BitDly();

        bIIC_SCL    = 0;

        send    = send << 1;
    }

    bIIC_SDA    = 1;
    bIIC_SCL    = 1;
	Delay5us();//BitDly();

    bIIC_SCL    = 0;
	Delay5us();//BitDly();
}

void I2CSendAddr(unsigned char addr, unsigned char index, unsigned char rd)
{
	//ET1 = 0;
    bIIC_SCL    = 1;
    bIIC_SDA    = 0;    // Start
	Delay5us();//BitDly();

    bIIC_SCL    = 0;
    I2CSendByte(addr + rd);             // Send address byte

    if (0 == rd)    I2CSendByte(index); // Send index byte
}

void I2CSendStop(void)
{
    bIIC_SDA    = 0;
	Delay5us();//BitDly();

    bIIC_SCL    = 1;
	Delay5us();//BitDly();

    bIIC_SDA    = 1;
	Delay5us();//BitDly();

#if  0
	//if (bVBI_INT_Enable)
	//	ET1 = 1;
#endif

}

void CI2cWriteArray(BYTE dev_addr, BYTE *array)
{
	BYTE n;

	while(1)
	{
		if(array[0]==0)
			break;

		I2CSendAddr(dev_addr, array[1], 0);

		for (n = 2; n < array[0]; n++)
			I2CSendByte(array[n]);

		I2CSendStop();
		array += n;
	}
}

void I2CByteWrite(unsigned char index,unsigned char address,unsigned char value)
{
    UINT8 xdata ucTemp[4];
/*
    pData[0]=4;
    pData[1]=address;
    pData[2]=index;
    pData[3]=value;
    */
    ucTemp[0]=4;
    ucTemp[1]=address;
    ucTemp[2]=index;
    ucTemp[3]=value;
    I2CWrite(ucTemp);
    CTimerDelayXms(8);
}
#endif

