
#include "TW9990.h"
#include "dr7f701441.dvf.h"   
#include "GPIO.h"
#include "r_dev_api.h"
#include "Watchdog.h"
#include "r_gpio_api.h"

/*延时时间us*/
#define Delayus  6

//18
/*  将I2C0的SDA设置为输入*/
static void TW9990_SDA_IN(void)
{
	r_dev_PinConfig_t port_config;

    port_config.Port = 44;                    /*  port number*/
    port_config.Pin = 10;                     /*  pin number*/
    port_config.Func = 0;                     /*  pin function 0: GPIO, 1-4 alternative function*/
    port_config.Dir = R_DEV_PIN_IN;           /*  pin direction, see <r_dev_PinDirection_t>*/
    port_config.Feedback = 1;                 /*  1: physical (output) pin level provided to input register, 0: disabled*/
    port_config.Pull = R_DEV_PIN_PULLNO;      /*  internal pull up configuration, see <r_dev_PinPull_t>*/
    port_config.OpenDrain = 0;                /*  1: open drain emulation, 0: push-pull*/
    port_config.CurrLimit = 1;                /*  1: high level current limitation, 0: low level current limitation*/ 
    port_config.HiSpeed = 1;                  /*  1: Speed limitation disabled (drive strength control off), 0: Speed limit enabled*/  
    port_config.InputType = R_DEV_PIN_CMOS1;  /*  possible types of input characteristics, see <r_dev_PinInput_t>*/
	R_DEV_PinConfig(&port_config);
}

/* 将I2C0的SDA设置为输出*/
static void TW9990_SDA_OUT(void)
{
    r_dev_PinConfig_t port_config;

    port_config.Port = 44;                    /*  port number */
    port_config.Pin = 10;                     /*  pin number */
    port_config.Func = 0;                     /*  pin function 0: GPIO, 1-4 alternative function*/
    port_config.Dir = R_DEV_PIN_OUT;          /*  pin direction, see <r_dev_PinDirection_t>*/
    port_config.Feedback = 1;                 /*  1: physical (output) pin level provided to input register, 0: disabled*/
    port_config.Pull = R_DEV_PIN_PULLNO;      /*  internal pull up configuration, see <r_dev_PinPull_t>*/
    port_config.OpenDrain = 0;                /*  1: open drain emulation, 0: push-pull*/
    port_config.CurrLimit = 1;                /*  1: high level current limitation, 0: low level current limitation */
    port_config.HiSpeed = 1;                  /*  1: Speed limitation disabled (drive strength control off), 0: Speed limit enabled */
    port_config.InputType = R_DEV_PIN_CMOS1;  /*  possible types of input characteristics, see <r_dev_PinInput_t>*/
	R_DEV_PinConfig(&port_config);
}

static void TW9990_RSTB_OUT(void)
{
    r_dev_PinConfig_t port_config;

    port_config.Port = 42;                    /*  port number */
    port_config.Pin = 9;                      /*  pin number */
    port_config.Func = 0;                     /*  pin function 0: GPIO, 1-4 alternative function*/
    port_config.Dir = R_DEV_PIN_OUT;          /*  pin direction, see <r_dev_PinDirection_t>*/
    port_config.Feedback = 1;                 /*  1: physical (output) pin level provided to input register, 0: disabled*/
    port_config.Pull = R_DEV_PIN_PULLNO;      /*  internal pull up configuration, see <r_dev_PinPull_t>*/
    port_config.OpenDrain = 0;                /*  1: open drain emulation, 0: push-pull*/
    port_config.CurrLimit = 1;                /*  1: high level current limitation, 0: low level current limitation */
    port_config.HiSpeed = 1;                  /*  1: Speed limitation disabled (drive strength control off), 0: Speed limit enabled */
    port_config.InputType = R_DEV_PIN_CMOS1;  /*  possible types of input characteristics, see <r_dev_PinInput_t>*/
	R_DEV_PinConfig(&port_config);
}

uint8_t TW9990_SDA_GetValue(void)
{
    uint8_t i;
    i = R_GPIO_PinRead(44, 10);
    return i;
}

void TW9990_IIC_Start(void)
{
    TW9990_SDA_OUT();
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SDA_HIGH;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SCL_HIGH;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SDA_LOW;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SCL_LOW;
    TW9990_IIC_DelayUs(300);
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_IIC_Stop
* Description    : stop
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void TW9990_IIC_Stop(void)
{
    TW9990_SDA_OUT();
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SCL_LOW;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SDA_LOW;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SCL_HIGH;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SDA_HIGH;
    TW9990_IIC_DelayUs(300);
}

void TW9990_IIC_DelayUs(uint32_t time)
{
    uint32_t i;
    for (i = 0; i < (time *2); i++) 
    {            
        R_DEV_Nop();
        WDT_Clear();
    }
}

void TW9990_IIC_ACK(void)
{
    TW9990_SDA_OUT();
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SDA_LOW;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SCL_HIGH;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SCL_LOW;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SDA_HIGH;
    TW9990_IIC_DelayUs(Delayus);
}

void TW9990_IIC_NACK(void)
{
    TW9990_SDA_OUT();
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SDA_HIGH;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SCL_HIGH;
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SCL_LOW;
    TW9990_IIC_DelayUs(Delayus);
}

uint8_t TW9990_IIC_WaitAck(void)
{
    uint8_t ack = 0x01;
    uint16_t i = IIC_WaitOverTime;

    TW9990_SDA_IN();
    TW9990_IIC_DelayUs(Delayus);
 
    TW9990_IIC_SCL_HIGH;
    TW9990_IIC_DelayUs(Delayus);

    while ((ack) && (--i != 0)) 
    {
        
        ack = TW9990_SDA_GetValue();
 
        WDT_Clear();
    }
    
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SCL_LOW;
    TW9990_IIC_DelayUs(Delayus);
    
    return (ack);
}

uint8_t TW9990_IIC_SendByte(uint8_t Data)
{
    uint8_t temp;
    uint8_t d = Data;
    
    TW9990_SDA_OUT();
    TW9990_IIC_DelayUs(Delayus);
    
    for (temp = 8; temp != 0; temp--) 
    {
        if (d & 0x80)                            
        {
            TW9990_IIC_SDA_HIGH;
        } 
        else 
        {
            TW9990_IIC_SDA_LOW;
        }
        
        TW9990_IIC_DelayUs(Delayus);
        TW9990_IIC_SCL_HIGH;
        TW9990_IIC_DelayUs(Delayus);
        TW9990_IIC_SCL_LOW;
        TW9990_IIC_DelayUs(Delayus);
        d = d <<1;
        TW9990_IIC_DelayUs(Delayus);
    }
    
    TW9990_IIC_DelayUs(Delayus);
    return 1;
}

uint8_t TW9990_IIC_ReadByte(void)
{
    uint8_t temp;
    uint8_t rbyte = 0;
    uint8_t SDA = 0;
    
    TW9990_SDA_IN();
    TW9990_IIC_DelayUs(Delayus);

    for (temp = 8; temp != 0; temp--)
    {
        TW9990_IIC_SCL_HIGH;
        TW9990_IIC_DelayUs(Delayus);
        rbyte = rbyte << 1;
        TW9990_IIC_DelayUs(Delayus);
        SDA = TW9990_SDA_GetValue();
        rbyte = rbyte | ((uint8_t)(SDA));
        TW9990_IIC_DelayUs(Delayus);
        TW9990_IIC_SCL_LOW;
        TW9990_IIC_DelayUs(Delayus);
    }
    
    return(rbyte);
}
 
uint8_t TW9990_IIC_WritePage(uint8_t PhyAdd, uint8_t MemAdd, uint8_t *Data, uint8_t len)
{
    uint8_t  b = 3;
    uint8_t  i;
    uint8_t  *OldData;
    OldData = Data;

    do 
    {
        Data = OldData;
        TW9990_IIC_Start();
        TW9990_IIC_SendByte(PhyAdd);
        
        if (TW9990_IIC_WaitAck()) 
        {
            TW9990_IIC_Stop();
            b--;
            if (b)
            {
                continue;
            } 
            else 
            {
                break;
            }
        }

        TW9990_IIC_SendByte(MemAdd);
        
        if (TW9990_IIC_WaitAck()) 
        {
            TW9990_IIC_Stop();
            b--;
            
            if (b) 
            {
                continue;
            } 
            else 
            {
                break;
            }
        }
        
        for (i = 0; i < len; i++) 
        {
            TW9990_IIC_SendByte(*Data);
            
            if (TW9990_IIC_WaitAck()) 
            {
                TW9990_IIC_Stop();
                break;
            }
            Data++;
        }
        
        TW9990_IIC_Stop();
        return 1;
    } while (1);
    
    return 0;
}

uint8_t TW9990_IIC_ReadPage(uint8_t PhyAdd, uint8_t MemAdd, uint8_t *Data, uint8_t len)
{
    uint8_t  b = 3;
    uint8_t  i;
    
    do
    {
        TW9990_IIC_Start();
        TW9990_IIC_SendByte(PhyAdd);
        
        if (TW9990_IIC_WaitAck()) 
        {
            TW9990_IIC_Stop();
            b--;
            if (b) 
            {
                continue;
            } 
            else 
            {
                break;
            }
        }
        
        TW9990_IIC_SendByte(MemAdd);
        
        if (TW9990_IIC_WaitAck()) 
        {
            TW9990_IIC_Stop();
            b--;
            
            if (b) 
            {
                continue;
            } 
            else 
            {
                break;
            }
        }
        
        TW9990_IIC_Start();
        TW9990_IIC_SendByte(PhyAdd | 0x01);
        
        if (TW9990_IIC_WaitAck()) 
        {
            TW9990_IIC_Stop();
            b--;
            
            if (b) 
            {
                continue;
            } 
            else 
            {
                break;
            }
        }
        
        for (i = 0 ; i < (len - 1); i++) 
        {
            *Data = TW9990_IIC_ReadByte();
            TW9990_IIC_ACK();
            Data++;
        }
        
        *Data = TW9990_IIC_ReadByte();
        TW9990_IIC_NACK();
        TW9990_IIC_Stop();
        
        return 1;
    } while (1);
    
    return 0;
}

static void WriteReg(uint8_t addr, uint8_t data)
{
    TW9990_IIC_WritePage(0x8a, addr, &data, 1);
}

static uint8_t ReadReg(uint8_t addr)
{
    uint8_t data;
    TW9990_IIC_ReadPage(0x8a, addr, &data, 1);
    return data;
}

static msm_camera_i2c_reg_conf_t TW9992_PAL_Int[] = 
{
    0x8a, 0x00,  //for now is same as NTSC_Int
    0x02, 0x40,
    0x03, 0xa0,
    0x12, 0x21,
    0x1A, 0x0A,
    0x20, 0xA0,
    0x2C, 0x40,
    0x35, 0xA0,
    0xff, 0xff
};

void I2C_INIT(void)
{
    DC12V_EN_MCU = 0;
    VCC18_EN_MCU = 0;
    TW9990_IIC_DelayUs(Delayus * 100);

    DC12V_EN_MCU = 1;        /* 24V转12V使能 */
    TW9990_IIC_DelayUs(Delayus * 100);

    VCC18_EN_MCU = 1;        /* 5V转1.8V使能 */
    TW9990_IIC_DelayUs(Delayus * 1000);

    TW9990_RSTB = 0;
    TW9990_IIC_DelayUs(Delayus * 1000);
    TW9990_IIC_DelayUs(Delayus * 1000);
    TW9990_RSTB = 1;
}

unsigned char TW9990_CCIR_NTSC_DataSet[] = 
{
    0x8a, 0x00,  //for now is same as NTSC_Int
    0x02, 0x40,
    0x03, 0xa0,
    0x12, 0x21,
    0x1A, 0x0A,
    0x20, 0xA0,
    0x2C, 0x40,
    0x35, 0xA0,
    0x2B, 0x99, //20211027 增加(芯片厂技术支持说能增强抗干扰)
    0x4C, 0xE0, //20211027 增加(芯片厂技术支持说能增强抗干扰)
    0xff, 0xff
};

void I2CDeviceInitialize(unsigned char *RegSet)
{
    unsigned char index, val;
    
    RegSet += 2;

    while (( RegSet[0] != 0xFF ) || ( RegSet[1] != 0xFF ))
    {   // 0xff, 0xff is end of data
        index = *RegSet;
        val = *(RegSet + 1);
        
        TW9990_IIC_WritePage(0x8a, index, &val, 1);

        RegSet += 2;
    }
}

void STBoff(void)
{
    WriteReg(0xAF, 0x80);
    WriteReg(0xB0, 0x00);
    WriteReg(0x0F, 0x00);
    //Printf("\n===== STB OFF =====");
}

//uint8_t EEE = 50;

void InitTW9990(void)
{
    I2CDeviceInitialize(TW9990_CCIR_NTSC_DataSet);
    //EEE = ReadReg(0x6f);
}

void TW9990_IIC_Sleep(void)
{
    TW9990_SDA_OUT();
    TW9990_IIC_DelayUs(Delayus);
    TW9990_IIC_SDA_HIGH;
    TW9990_IIC_SCL_HIGH;
}