/*!
    \file    i2c.c
    \brief   the i2c configuration file

*/

#include "lisoc_test.h"
#include "i2c.h"

#define IMX415_ID 0x1A
#define VCM_ID 		0x0C

void i2c_Enable(I2C_Register_Table_s *LISOC_I2C)
{
  // clear the interrupt by reading EOI    
  LISOC_I2C->IC_ENABLE.ENABLE = 0x1u;
}

void i2c_Disable(I2C_Register_Table_s *LISOC_I2C)
{
  // clear the interrupt by reading EOI    
  LISOC_I2C->IC_ENABLE.ENABLE = 0x0u;
}

void i2c_Config(I2C_Register_Table_s *LISOC_I2C,uint8_t freq,uint16_t addr)
{
  //  1. Set IC_SLAVE_DISABLE to 1 ¨C Slave 
  //   disabled
  //  2. Set IC_RESTART_EN to 1 ¨C Enable 
  //   restart mode
  //  3. Set IC_10BITADDR_MASTER to 0 ¨C 
  //   7-bit addressing
  //  4. Set IC_10BITADDR_SLAVE to 0 ¨C 7-bit 
  //   addressing
  //  5. Set IC_MAX_SPEED_MODE to 1 ¨C 
  //   Standard mode
  //  6. Set IC_MASTER_MODE to 1 ¨C Master 
  //   enabled

  //    wdata = wdata |(1<<6) | (1<<5) (1<<1)|1;
  //I2C0_CON = 0x61 | (speed << 1);  //IC_CON to xxx
  LISOC_I2C->IC_CON_W = 0;
  LISOC_I2C->IC_CON.MASTER_MODE = 1;
  LISOC_I2C->IC_CON.SPEED = SPEED_FAST;
  LISOC_I2C->IC_CON.IC_RESTART_EN = 1;
  LISOC_I2C->IC_CON.IC_SLAVE_DISABLE = 1;

  //I2C0_TAR = 0x45;  //TAR to 0x45
  LISOC_I2C->IC_TAR.IC_TAR = addr;

  if(freq == FREQ_100K){
    LISOC_I2C->IC_FS_SCL_HCNT_W = (3000)*27/1000 - 5 - 7;
    LISOC_I2C->IC_FS_SCL_LCNT_W = (7000 - 300)*27/1000 - 1;
  }else{
    // Write to IC_SS_HCNT to set HIGH period of SCL
    //I2C0_SS_SCL_HCNT = (5000)*27/1000 - 5 - 7;
    // 400k =  2500ns duty 2:1 1700:800
    // Write to IC_SS_LCNT to set LOW period of SCL
    //I2C0_SS_SCL_LCNT = (5000)*27/1000 - 5 - 7;
    LISOC_I2C->IC_FS_SCL_HCNT_W = (800)*27/1000 - 5 - 7; 
    LISOC_I2C->IC_FS_SCL_LCNT_W = (1700 - 300)*27/1000 - 1;//scl_rise_time:300ns
  }

  // Write to IC_INTR_MASK to disable all interrupts
  //I2C0_INTR_MASK = 0x0;
  LISOC_I2C->IC_INTR_MASK_W = 0;

  // Write to IC_RX_TL to set Rx FIFO threshold leve
  //I2C0_RX_TL = 0x3;
  LISOC_I2C->IC_RX_TL_W = 0x3;

  // Write to IC_TX_TL to set Tx FIFO threshold level
  //I2C0_TX_TL = 0x3;
  LISOC_I2C->IC_TX_TL_W = 0x3;

}

void i2c_Write(I2C_Register_Table_s *LISOC_I2C,uint8_t reg)
{
  //I2C0_DATA_CMD = 0x200 | ID_REG;
  LISOC_I2C->IC_DAT_CMD_W = 0x200 | reg;

  //LISOC_I2C->IC_DAT_CMD.STOP = 1;
  //LISOC_I2C->IC_DAT_CMD.CMD = 0; // write
  //LISOC_I2C->IC_DAT_CMD.DAT = ID_REG;

  //while((I2C0_STATUS & 0x7) != 0x6 ) {
  while(LISOC_I2C->IC_STATUS.TFNF != 1 || LISOC_I2C->IC_STATUS.TFE != 1 || LISOC_I2C->IC_STATUS.ACTIVITY != 0) {
    ;
  }
}

uint16_t i2c_Read(I2C_Register_Table_s *LISOC_I2C)
{
  uint16_t rdata = 0;

#if 0
  //I2C0_DATA_CMD = 0x100;
  LISOC_I2C->IC_DAT_CMD_W = 0x100;

  //LISOC_I2C->IC_DAT_CMD.STOP = 0;
  //LISOC_I2C->IC_DAT_CMD.CMD = 1; // read
  //LISOC_I2C->IC_DAT_CMD.DAT = 0;

  //while((I2C0_STATUS & 0x8) != 0x8 ) {
  while(LISOC_I2C->IC_STATUS.RFNE != 1) {
    ;
  }

  //rdata = (uint8_t)I2C0_DATA_CMD;
  rdata = (uint8_t)LISOC_I2C->IC_DAT_CMD.DAT;

#endif
  //I2C0_DATA_CMD = 0x300;
  LISOC_I2C->IC_DAT_CMD_W = 0x300;
  //LISOC_I2C->IC_DAT_CMD.STOP = 1;
  //LISOC_I2C->IC_DAT_CMD.CMD = 1; // read
  //LISOC_I2C->IC_DAT_CMD.DAT = 0;

  //while((I2C0_STATUS & 0x8) != 0x8 ) {
  while(LISOC_I2C->IC_STATUS.RFNE != 1) {
    ;
  }
  rdata <<= 8u;
  rdata |= (uint8_t)LISOC_I2C->IC_DAT_CMD.DAT;

  return rdata;
}

void i2c_reg16_read(I2C_Register_Table_s *LISOC_I2C,uint16_t addr,uint8_t *data)
{
  LISOC_I2C->IC_DAT_CMD_W = (addr >> 8);
  LISOC_I2C->IC_DAT_CMD_W = 0x200 | (addr & 0x00FF);
  while((I2C0_STATUS & 0x7) != 0x6 ) ;

  LISOC_I2C->IC_DAT_CMD_W = 0x300;
  while((I2C0_STATUS & 0x8) != 0x8 ) ;

  //rdata = (uint8_t)I2C0_DATA_CMD;
  *data = (uint8_t)LISOC_I2C->IC_DAT_CMD.DAT;
}

void i2c_reg16_write(I2C_Register_Table_s *LISOC_I2C,uint16_t addr,uint8_t data)
{
  LISOC_I2C->IC_DAT_CMD_W = (addr >> 8);
  LISOC_I2C->IC_DAT_CMD_W = (addr & 0x00FF);
  LISOC_I2C->IC_DAT_CMD_W = 0x200 | data;
  while((I2C0_STATUS & 0x7) != 0x6 ) ;
}

void i2c_vcm_read(I2C_Register_Table_s *LISOC_I2C,uint8_t addr,uint16_t *data)
{
	i2c_Disable(LISOC_I2C0);  //IC_ENABLE to 0
  i2c_Config(LISOC_I2C0, FREQ_400K, VCM_ID);
  i2c_Enable(LISOC_I2C0);
	
  LISOC_I2C->IC_DAT_CMD_W = 0x200 | addr;
  while((I2C0_STATUS & 0x7) != 0x6 ) ;

  LISOC_I2C->IC_DAT_CMD_W = 0x300;
  while((I2C0_STATUS & 0x8) != 0x8 ) ;

  //rdata = (uint8_t)I2C0_DATA_CMD;
  *data = (uint8_t)LISOC_I2C->IC_DAT_CMD.DAT;
	*data <<= 8;
	
	LISOC_I2C->IC_DAT_CMD_W = 0x300;
  while((I2C0_STATUS & 0x8) != 0x8 ) ;
	*data |= (uint8_t)LISOC_I2C->IC_DAT_CMD.DAT;
	
	i2c_Disable(LISOC_I2C0);  //IC_ENABLE to 0
  i2c_Config(LISOC_I2C0, FREQ_400K, IMX415_ID);
  i2c_Enable(LISOC_I2C0);
}

void i2c_vcm_write(I2C_Register_Table_s *LISOC_I2C,uint16_t data)
{
	i2c_Disable(LISOC_I2C0);  //IC_ENABLE to 0
  i2c_Config(LISOC_I2C0, FREQ_400K, VCM_ID);
  i2c_Enable(LISOC_I2C0);
	
  LISOC_I2C->IC_DAT_CMD_W = data >> 8;
  LISOC_I2C->IC_DAT_CMD_W = 0x200 | (data & 0xff);
  while((I2C0_STATUS & 0x7) != 0x6 ) ;
	
	i2c_Disable(LISOC_I2C0);  //IC_ENABLE to 0
  i2c_Config(LISOC_I2C0, FREQ_400K, IMX415_ID);
  i2c_Enable(LISOC_I2C0);
}
