/********************************** (C) COPYRIGHT *******************************
* File Name          : IIC.c
* Author             :
* Version            : V1.0
* Date               : 2018/12/12
* Description        : I2C 读写
*******************************************************************************/

/*********************************************************************
 * INCLUDES
 */

#include "TouchCommon.h"
#include "iic.h"
#include "driver_gpio.h"

/* DATA ADDRESS Length Definition */
#define Address_8bit  0
#define Address_16bit  1
#define Address_32bit  2

#define CHECK_TIMES     (25)

#define IIC_TIMEOUT 50

#define IIC_SPEED_400   10
void NOP_DELAY(UINT16 num)
{
    while(num--)
    {
        asm("nop");
    }
}
void Touch_IIC_Init()
{
    gpio_init_typedef gpio_init_structure;

    gpio_init_structure.gpio_dir = GPIO_DIR_INPUT;
    gpio_init_structure.gpio_fen = GPIO_FEN_GPIO;
    gpio_init_structure.gpio_fdir = GPIO_FDIR_SELF;
    gpio_init_structure.gpio_mode = GPIO_MODE_DIGITAL;
    gpio_init_structure.gpio_pupd = GPIO_PUPD_PU10K;
    gpio_init_structure.gpio_drv = GPIO_DRV_6MA;

    gpio_init_structure.gpio_pin = IIC_SCL;
    gpio_init(GPIOA_REG, &gpio_init_structure);

    gpio_init_structure.gpio_pin = IIC_SDA;
    gpio_init(GPIOA_REG, &gpio_init_structure);

    gpio_reset_bits(GPIOA_REG, IIC_SCL);
    gpio_reset_bits(GPIOA_REG, IIC_SDA);
}

#define SCL_IN()            (gpio_read_data(GPIOA_REG)&IIC_SCL)
#define SCL_HIGH()          gpio_set_input(GPIOA_REG, IIC_SCL)
#define SCL_LOW()           gpio_set_out(GPIOA_REG, IIC_SCL)
#define SDA_IN()            (gpio_read_data(GPIOA_REG)&IIC_SDA)
#define SDA_HIGH()          gpio_set_input(GPIOA_REG, IIC_SDA)
#define SDA_LOW()           gpio_set_out(GPIOA_REG, IIC_SDA)

#define IIC_START()         {\
    SDA_HIGH();\
    SCL_HIGH();\
    NOP_DELAY(IIC_SPEED_400);\
    SDA_LOW();\
    NOP_DELAY(IIC_SPEED_400);\
    SCL_LOW();\
}

#define IIC_STOP()  {\
    SDA_LOW();\
    SCL_LOW();\
    NOP_DELAY(IIC_SPEED_400);\
    SCL_HIGH();\
    NOP_DELAY(IIC_SPEED_400);\
    SDA_HIGH();\
}

BOOL I2C_WaitForSclRelease(void)
{
    s8 nTryTimes = IIC_TIMEOUT;

    while( SCL_IN() == 0  && nTryTimes!=0)
    {
        --nTryTimes;
        NOP_DELAY(IIC_SPEED_400);
    }

    if(nTryTimes==0)
        return 0;
    return 1;
}

BOOL IIC_WRITE_DATA(UINT8 dat)
{
    BOOL nak;
    UINT8 bit_off = 0x80;
    do
    {
        if(bit_off & dat)
        {
            SDA_HIGH();
        }
        else
        {
            SDA_LOW();
        }
        NOP_DELAY(IIC_SPEED_400);
        SCL_HIGH();
        NOP_DELAY(IIC_SPEED_400);
        bit_off >>= 1;
        SCL_LOW();
    } while (bit_off);

    NOP_DELAY(IIC_SPEED_400);
    SDA_HIGH();
    SCL_HIGH();
    NOP_DELAY(IIC_SPEED_400);
    nak = SDA_IN();
    SCL_LOW();

    return nak==0;
}

BOOL IIC_READ_DATA(UINT8* dat, BOOL nack)
{
    UINT8 bit_off = 0x80;

    SDA_HIGH();
    SCL_HIGH();
    NOP_DELAY(IIC_SPEED_400);
    if(!I2C_WaitForSclRelease())
    {
        return 0;
    }

    while(1)
    {
        if(SDA_IN())
        {
            *dat |=  bit_off;
        }
        else
        {
            *dat &=  ~bit_off;
        }

        SCL_LOW();
        NOP_DELAY(IIC_SPEED_400);
        bit_off >>= 1;

        if(bit_off)
        {
            SCL_HIGH();
            NOP_DELAY(IIC_SPEED_400);
            continue;
        }
        break;
    };

    if(nack)
    {
        SDA_HIGH();
    }
    else
    {
        SDA_LOW();
    }
    SCL_HIGH();
    NOP_DELAY(IIC_SPEED_400 + 2);
    SCL_LOW();
    return 1;
}

BOOL GT_Check_I2C_Address(UINT8 Address)
{
    BOOL nack;

    IIC_START();

    nack = IIC_WRITE_DATA(Address);

    IIC_STOP();

    return nack;
}

BOOL  WriteAddress(UINT32 dwAddr)
{
   if(isBerlinSeries || bIsJDSeries)
   {
      IIC_WRITE_DATA((UINT8)(dwAddr>>24) );

      IIC_WRITE_DATA((UINT8)(dwAddr>>16) );
   }
   IIC_WRITE_DATA((UINT8)(dwAddr>>8) );

   IIC_WRITE_DATA((UINT8)(dwAddr) );

   return 1;
}

u8 IICReadOneByte(UINT32 ReadAddr)
{
    UINT8 temp=0;
    IIC_START();
    IIC_WRITE_DATA(GT_CMD_WR);
    if(!WriteAddress(ReadAddr)) return 0;
      NOP_DELAY(4);
    IIC_START();
     IIC_WRITE_DATA(GT_CMD_RD);
     NOP_DELAY(4);
    IIC_READ_DATA(&temp, 1);
    IIC_STOP();
    return temp;
}

BOOL IICReadBytes(UINT32 ReadAddr,UINT8 *pBuffer,UINT16 Length)
{
    BOOL ret = 1;
    IIC_START();
    if(!IIC_WRITE_DATA(GT_CMD_WR))
        return 0;
    if(!WriteAddress(ReadAddr)) return 0;
    NOP_DELAY(4);
    IIC_START();
    IIC_WRITE_DATA(GT_CMD_RD);

    for(; Length > 1; --Length)
    {
        NOP_DELAY(4);
        ret = IIC_READ_DATA(pBuffer, 0);

        if(!ret)
        {
            break;
        }

        pBuffer++;
    }

    if(ret)
    {
        NOP_DELAY(4);
        IIC_READ_DATA(pBuffer, 1);
    }

    IIC_STOP();

    return ret;
}


BOOL IICWriteOneByte(UINT32 WriteAddr,UINT8 DataToWrite)
{
    BOOL ret;
    IIC_START();
    ret = IIC_WRITE_DATA(GT_CMD_WR);
    if(ret)
    {
        if(!WriteAddress(WriteAddr)) return 0;
        ret = IIC_WRITE_DATA(DataToWrite);
    }
    IIC_STOP();
    return ret;
}

BOOL IICWriteBytes(UINT32 WriteAddr,UINT8 *pBuffer,UINT16 Length)
{
    BOOL ret;

    IIC_START();
    ret = IIC_WRITE_DATA(GT_CMD_WR);
    if(ret)
    {
        if(!WriteAddress(WriteAddr)) return 0;

        while (Length--)
        {
            IIC_WRITE_DATA(*pBuffer);
            pBuffer++;
        }
    }
    IIC_STOP();
    return ret;
}


/*********************************************************************
*********************************************************************/
