#include "drv_i2c.h"
#include "drv_gpio.h"
#include "kit_data.h"
#include "kit_time.h"

typedef struct
{
	uint8_t     clk_dly; //单位us
	uint8_t     scl_io;
	uint8_t     sda_io;
	uint32_t	err_cnt;
}I2cItem;

I2cItem i2c_item[kI2cDev_End];

kit_ret_e drv_i2c_init(I2cDev dev, uint32_t freq, uint8_t scl_idx, uint8_t sda_idx)
{    
	I2cItem *item = &i2c_item[dev];
	
	item->scl_io = scl_idx;
	item->sda_io = sda_idx;
	
	item->clk_dly = 1000 / freq;

	return kKit_Ret_Ok;
}

void drv_i2c_start(I2cItem *item)
{

	drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High);
	drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High);
	kit_time_dly_us(item->clk_dly);
	drv_gpio_set_pin_status(item->sda_io, kGpioStatus_Low);;
	kit_time_dly_us(item->clk_dly);
	drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low);
	kit_time_dly_us(item->clk_dly);
}


void drv_i2c_stop(I2cItem *item)
{
	drv_gpio_set_pin_status(item->sda_io, kGpioStatus_Low);
	kit_time_dly_us(item->clk_dly);
	drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High);
	kit_time_dly_us(item->clk_dly);
	drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High);
}


kit_ret_e i2c_sync_write_byte(I2cItem *item, uint8_t data)
{
	kit_ret_e res = kKit_Ret_Error;
	uint32_t i;

	for(i = 0; i < 8; i++)
	{
		if((data & 0x80) == 0)
		{
			drv_gpio_set_pin_status(item->sda_io, kGpioStatus_Low);
		}			
		else
		{
			drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High);
		}
        kit_time_dly_us(2);
		drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High);
		kit_time_dly_us(item->clk_dly);
		drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low);
		data <<= 1;
		kit_time_dly_us(item->clk_dly);
	}	
	drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High);
	drv_gpio_set_pin_mode(item->sda_io, kGpioMode_Input_Floating);
	drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High);
	
	kit_time_dly_us(item->clk_dly);
	if(drv_gpio_get_pin_status(item->sda_io) == kGpioStatus_Low)
	{
		res = kKit_Ret_Ok;
	}
	else
	{
		item->err_cnt++;
	}

	drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low);
	drv_gpio_set_pin_mode(item->sda_io, kGpioMode_Output_PP);
	drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High);
	
	kit_time_dly_us(item->clk_dly);
	return res;
}

uint8_t i2c_sync_read_byte(I2cItem *item, bool is_ack)
{
	uint8_t data = 0;
	uint32_t i;
	
	drv_gpio_set_pin_mode(item->sda_io, kGpioMode_Input_Floating);
	kit_time_dly_us(1);
	for(i = 0; i < 8; i++)
	{
		data <<= 1;
		drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High);
		kit_time_dly_us(item->clk_dly);
		if(drv_gpio_get_pin_status(item->sda_io) == kGpioStatus_High)
		{
			data |= 0x01;
		}			
		drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low);
		
		kit_time_dly_us(item->clk_dly);
	}
	
	drv_gpio_set_pin_mode(item->sda_io, kGpioMode_Output_PP);
	if(is_ack == true)
	{
		drv_gpio_set_pin_status(item->sda_io, kGpioStatus_Low);;	
	}
	else
	{
		drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High);	
	}

	drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High);
	kit_time_dly_us(item->clk_dly);
	drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low);
	kit_time_dly_us(item->clk_dly);
	drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High);
	
	return data;
}


kit_ret_e drv_i2c_sync_write(I2cDev dev, uint8_t dev_addr, uint8_t reg_addr, uint8_t *buf, uint16_t len)
{
	uint32_t i;
	
	kit_ret_e res = kKit_Ret_Ok;
	I2cItem *item = &i2c_item[dev];
	uint8_t snd_buf[10];
    
	drv_i2c_start(item);
	
	snd_buf[0] = dev_addr << 1;
	snd_buf[1] = reg_addr;
	kit_copy_buf(&snd_buf[2], buf, len);
	
	len += 2;
	for(i = 0; i < len; i++)
	{
		res = i2c_sync_write_byte(item, snd_buf[i]);
		if(res != kKit_Ret_Ok)
		{
			break;
		}
	}

	drv_i2c_stop(item);
	
	return res;
}

kit_ret_e drv_i2c_sync_read(I2cDev dev, uint8_t dev_addr, uint8_t reg_addr, uint8_t *buf, uint16_t len)
{
	uint32_t i;
	
	kit_ret_e res = kKit_Ret_TimeOut;
	I2cItem *item = &i2c_item[dev];

	drv_i2c_start(item);
	
	if((i2c_sync_write_byte(item, dev_addr << 1) == kKit_Ret_Ok)
	&& (i2c_sync_write_byte(item, reg_addr) == kKit_Ret_Ok))
	{
//		drv_i2c_stop(item);
//		kit_time_dly_us(2);
		drv_i2c_start(item);
		if(i2c_sync_write_byte(item, dev_addr << 1 | 0x01) == kKit_Ret_Ok)
		{
			for(i = 0; i < len; i++)
			{
				buf[i] = i2c_sync_read_byte(item, (i != (len - 1)));
			}
			res = kKit_Ret_Ok;
		}
	}

	drv_i2c_stop(item);
	return res;
}

kit_ret_e drv_i2c_sync_write_then_read(I2cDev dev, uint8_t dev_addr, uint8_t *tx_buf, uint16_t tx_len, uint8_t *rx_buf, uint16_t rx_len)
{
	uint32_t i;
	
	kit_ret_e res = kKit_Ret_Ok;
	I2cItem *item = &i2c_item[dev];

	drv_i2c_start(item);
	
	res |= i2c_sync_write_byte(item, dev_addr << 1);
	for(i = 0; i < tx_len; i++)
	{
		res |= i2c_sync_write_byte(item, tx_buf[i]);
	}
	if(res == kKit_Ret_Ok)
	{
		drv_i2c_start(item);
		
		res = i2c_sync_write_byte(item, dev_addr << 1 | 0x01);
		if(res == kKit_Ret_Ok)
		{
			for(i = 0; i < rx_len; i++)
			{
				rx_buf[i] = i2c_sync_read_byte(item, (i != (rx_len - 1)));
			}
		}
	}
	
	drv_i2c_stop(item);
	return res;
}

kit_ret_e drv_i2c_sync_direct_read(I2cDev dev, uint8_t dev_addr, uint8_t reg_addr, uint8_t *buf, uint16_t len)
{
	uint32_t i;
	I2cItem *item = &i2c_item[dev];
	kit_ret_e res = kKit_Ret_TimeOut;

	drv_i2c_start(item);
	if(i2c_sync_write_byte(item, dev_addr << 1 | 0x01) == true)
	{
		for(i = 0; i < len; i++)
		{
			buf[i] = i2c_sync_read_byte(item, (i != (len - 1)));
		}
		res = kKit_Ret_Ok;
	}

	drv_i2c_stop(item);
	return res;
}