#include "hal_sy6970.h"

 
#define READ_SDA4   GPIO_ReadInputPins(GPIO_PORT_A,GPIO_PIN_12)

#define IIC_SDA4(n) (n?GPIO_SetPins(GPIO_PORT_A, GPIO_PIN_12):GPIO_ResetPins(GPIO_PORT_A, GPIO_PIN_12))
#define IIC_SCL4(n) (n?GPIO_SetPins(GPIO_PORT_A, GPIO_PIN_11):GPIO_ResetPins(GPIO_PORT_A, GPIO_PIN_11))

#define sy6970_speed 5
 
//需要示波器调1us的时间
static void delay_us(uint16_t time)
{
	uint16_t i;

	for(i=time;i>0;i--)
	{
		__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();__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();__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();__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();__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();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	}
}

static void iic4_init(void)
{
	stc_gpio_init_t  pstcGpioInit1;
	GPIO_StructInit(&pstcGpioInit1);
	
	pstcGpioInit1.u16PinDir = PIN_DIR_OUT;
	pstcGpioInit1.u16PinState = PIN_STAT_RST;
	GPIO_Init(GPIO_PORT_A, GPIO_PIN_11,&pstcGpioInit1); 
	GPIO_Init(GPIO_PORT_A, GPIO_PIN_12,&pstcGpioInit1); 
	
	GPIO_SetPins(GPIO_PORT_A, GPIO_PIN_11);
	GPIO_SetPins(GPIO_PORT_A, GPIO_PIN_12);
}

void sy6970_init(void)
{
	 iic4_init();
}	

static void SDA_IN4(void)
{
	 stc_gpio_init_t pstcGpioInit3;//iic的引脚
	 pstcGpioInit3.u16PinDir = PIN_DIR_IN;
	 //pstcGpioInit3.u16PinInputType = PIN_PU_ON;
	 GPIO_Init(GPIO_PORT_A, GPIO_PIN_12,&pstcGpioInit3);
}

static void SDA_OUT4(void)  
{
	stc_gpio_init_t pstcGpioInit3;
	pstcGpioInit3.u16PinDir = PIN_DIR_OUT;
	pstcGpioInit3.u16PinOutputType=PIN_OUT_TYPE_NMOS;
	GPIO_Init(GPIO_PORT_A, GPIO_PIN_12,&pstcGpioInit3);
}	
 
 

static void iic_start(void)
{
	SDA_OUT4();
	
	IIC_SDA4(1);
	IIC_SCL4(1);
	delay_us(sy6970_speed);
	
	IIC_SDA4(0);
	delay_us(sy6970_speed);
	IIC_SCL4(0);
}


static void iic_stop(void)
{
	SDA_OUT4();
	
	IIC_SCL4(0);
	IIC_SDA4(0);
	delay_us(sy6970_speed);
	
	IIC_SCL4(1);
	IIC_SDA4(1);
	delay_us(sy6970_speed);
}

static void iic_ack(void)
{
	SDA_OUT4();
	
	IIC_SCL4(0);
	IIC_SDA4(0);
	delay_us(sy6970_speed);
	
	IIC_SCL4(1);
	delay_us(sy6970_speed);
	IIC_SCL4(0);
}

static void iic_nack(void)
{
	SDA_OUT4();
	
	IIC_SCL4(0);
	IIC_SDA4(1);
	delay_us(sy6970_speed);
	
	IIC_SCL4(1);
	delay_us(sy6970_speed);
	IIC_SCL4(0);
}
 

static uint8_t iic_wait_ack(void)
{
	uint16_t t =200;
	SDA_OUT4();
	
	IIC_SDA4(1);delay_us(1);
	IIC_SCL4(1);delay_us(1);

	SDA_IN4();

	while(READ_SDA4) 
	{
		t--;
		
		if(t==0)
		{
			iic_stop();
			return 1;
		}
		delay_us(1);
	}
	IIC_SCL4(0);
		
	return 0;
}


static void iic_send_byte(uint8_t byte)
{
  uint8_t bit_cnt;
	SDA_OUT4();
	IIC_SCL4(0);
	 
	for(bit_cnt=0;bit_cnt<8;bit_cnt++)
	{	 
		if(byte&0x80)	
			IIC_SDA4(1); 
		else	
			IIC_SDA4(0);
		
		byte<<=1;
		delay_us(sy6970_speed);
		IIC_SCL4(1);
		delay_us(sy6970_speed);
		IIC_SCL4(0);
	}	
	
}
 

static uint8_t iic_recive_byte(unsigned char ack)
{
  uint8_t retc = 0;
  uint8_t bit_cnt;

	SDA_IN4(); 
	delay_us(1);
	
	for(bit_cnt=0;bit_cnt<8;bit_cnt++)
	{
		IIC_SCL4(0);
		delay_us(sy6970_speed);
		IIC_SCL4(1);
		
		retc=retc<<1;
		
		if(READ_SDA4)
			retc++;
		
		delay_us(sy6970_speed);
	}
 
	return(retc);
}
 
 

static void sy6970_write_byte(uint8_t dev_addr,uint8_t RAddr, uint8_t WData)
{
  iic_start();								 		 
  iic_send_byte(dev_addr); 
  iic_wait_ack();							 		 	
  iic_send_byte(RAddr);   		 		 
  iic_wait_ack(); 	 					 		 				  		   
  iic_send_byte(WData);      		 				   
  iic_wait_ack();  		    	   		 		 
  iic_stop();									 		 
}
 

static void sy6970_read_byte(uint8_t dev_addr,uint8_t RAddr, uint8_t *RData)
{
  iic_start();								 		 
  iic_send_byte(dev_addr); 
  iic_wait_ack();  						 		 
  iic_send_byte(RAddr);   		 		 
  iic_wait_ack();	    				 		 
  iic_start();  	 	   				 		 
  iic_send_byte(dev_addr|0x01);    
  iic_wait_ack();	 						 		 	
  *RData = iic_recive_byte(0);	 		    
  iic_stop();									 		 	
}


  
 
_Bool sy6970_write_bytes ( unsigned char SlaveAddr, unsigned char RegAddr, unsigned char *Buf, unsigned char Num )
{
	iic_start();						//起始信号
	//发送设备地址(写)
	iic_send_byte ( SlaveAddr );	//等待应答
	iic_wait_ack(); 

	//发送寄存器地址
	iic_send_byte ( RegAddr ) ;	//等待应答
	iic_wait_ack(); 
	while ( Num-- )								//循环写入数据
	{
		//发送数据
		iic_send_byte ( *Buf );	//等待应答
		iic_wait_ack(); 
		Buf++;									//数据指针偏移到下一个
		delay_us(10);
	}
	iic_stop();							//停止信号
	return 0;
}



 
_Bool sy6970_read_bytes ( unsigned char SlaveAddr, unsigned char RegAddr, unsigned char *Buf, unsigned char Num )
{
	iic_start();							//起始信号
	//发送设备地址(写)
	iic_send_byte ( SlaveAddr );		//等待应答
	iic_wait_ack(); 
	//发送寄存器地址
	iic_send_byte ( RegAddr );			//等待应答
	iic_wait_ack(); 
	iic_start();				   			//重启信号
	//发送设备地址(读)
	iic_send_byte ( SlaveAddr + 1 );	//等待应答
	iic_wait_ack(); 
	while ( Num-- )
	{
		//偏移到下一个数据存储地址
		if ( Num == 0 )
		{
			*Buf = iic_recive_byte ( 0 );	//最后一个数据需要回NOACK
		}
		else
		{
			*Buf = iic_recive_byte ( 1 );	//回应ACK
		}
		Buf++;
	}
	iic_stop();
	return 0;
}


#if 0

/**********************************************SY6970 操作函数****************************************************/
/*
 * 设置sy6970输入电流的大小
 *
 * set_val  需要操作的从机设备
	Fast Charge Current Limit:
	ICHG=[ICHG]*64mA
	Range:0mA(0000000)-5056mA(1001111)
	0000000=0mA(Disable Charge)
	0000001=64mA
	…
	0100000=2048mA(Default)
	…
	1001111~1111111=5056mA
 *
 * 返回值：void
 * */
void sy6970_set_input_current_limit(uint8_t set_val)
{
	set_val&= 0x7F;
	sy6970_write_byte(SY6970_ADDR,0x04,set_val);
}



/*
 * 设置sy6970输入电压的大小
 *
 * set_val  需要操作的从机设备
  Charge Voltage Limit:
	VREG=3.840V+[VREG]*16mV
	Range:3.840V-4.608V(110000)
	000000=3.840V
	000001=3.856V
	…
	010111=4.208V(Default)
	…
	110000~111111=4.608V
 *
 * 返回值：void
 * */
void sy6970_set_input_voltage_limit(uint8_t set_val)
{
	set_val&= 0xFC;
	sy6970_write_byte(SY6970_ADDR,0x06,set_val);
}

/*充电使能*/
void sy6970_charge_enable(void)
{
	uint8_t set_val = 0x00;
	set_val&= 0x01<<4;
	sy6970_write_byte(SY6970_ADDR,0x03,set_val);
}

/*充电不使能*/
void sy6970_charge_disable(void)
{
	uint8_t set_val = 0x00;
	set_val&= 0x00<<4;
	sy6970_write_byte(SY6970_ADDR,0x03,set_val);
}


/*充电状态查询
返回值：
00-Not Charging
01-Pre-charge (VBAT <VBATLOWV)
10-Fast Charging
11-Charge Termination Done
*/
uint8_t sy6970_charge_status(void)
{
	uint8_t status = 0;
	sy6970_read_byte(SY6970_ADDR,0x0b,&status);
	status >>=3;
	status &=0x03;
	return status;
}

uint8_t statusx = 0;
#endif


#include "FreeRTOS.h"
#include "task.h"
uint16 batt_voltage = 0, sys_voltage = 0;
uint8 charge_status = 0;
uint8 charge_ctl = 0;
REG_SYS_CONFIG reg[0X15];
REG_SYS_CONFIG regRead;
uint8 ntc_error = 0, bus_state = 0, current_limit = 0;
uint16 charge_voltage = 0, charge_current = 0, inutcharg = 0, charge_current_read = 0;

uint8 charge_flag = 0;


/**********************************************SY6970 操作函数****************************************************/
/*
 * 设置sy6970输入电流的大小
 *
 * set_val  需要操作的从机设备
	Fast Charge Current Limit:
	ICHG=[ICHG]*64mA
	Range:0mA(0000000)-5056mA(1001111)
	0000000=0mA(Disable Charge)
	0000001=64mA
	…
	0100000=2048mA(Default)
	…
	1001111~1111111=5056mA
 *
 * 返回值：void
 * */
void sy6970_set_input_current_limit(uint8_t set_val)
{
	set_val&= 0x7F;
	sy6970_write_byte(SY6970_ADDR,0x04,set_val);
}



/*
 * 设置sy6970输入电压的大小
 *
 * set_val  需要操作的从机设备
  Charge Voltage Limit:
	VREG=3.840V+[VREG]*16mV
	Range:3.840V-4.608V(110000)
	000000=3.840V
	000001=3.856V
	…
	010111=4.208V(Default)
	…
	110000~111111=4.608V
 *
 * 返回值：void
 * */
void sy6970_set_input_voltage_limit(uint8_t set_val)
{
	set_val &= 0xFC;
	sy6970_write_byte(SY6970_ADDR,0x06,set_val);
}

/*充电使能*/
void sy6970_set_reg03_charge(void)
{
	REG_SYS_CONFIG bat_config = {0};

	bat_config.reg03_config.bat_load_en = 0;
	bat_config.reg03_config.wd_rst = 1;
	bat_config.reg03_config.otg_config = 0;
	bat_config.reg03_config.chg_config = 1;
	bat_config.reg03_config.sys_min = 5;

	sy6970_write_byte(SY6970_ADDR,0x03, bat_config.data_uint8);
}
/*获取 */
REG_SYS_CONFIG sy6970_get_reg_config(uint8_t cmd)
{
	REG_SYS_CONFIG bat_read = {0};
	sy6970_read_byte(SY6970_ADDR, cmd, &bat_read.data_uint8);
	return bat_read;
}

/*获取REG02配置*/
REG_SYS_CONFIG sy6970_get_reg02_config(void)
{
	REG_SYS_CONFIG bat_read = {0};
	sy6970_read_byte(SY6970_ADDR,0x02, &bat_read.data_uint8);
	return bat_read;
}

/*获取充电配置*/
REG_SYS_CONFIG sy6970_get_reg03_config(void)
{
	REG_SYS_CONFIG bat_read = {0};
	sy6970_read_byte(SY6970_ADDR,0x03, &bat_read.data_uint8);
	return bat_read;
}
/*配置reg0D*/
void sy6970_reg0d_vindpm_config(void)
{
	REG_SYS_CONFIG bat_config = {0};
	bat_config.reg0D_config.VINDPM_MODE = 1;
	bat_config.reg0D_config.VINDPM = 100;
	sy6970_write_byte(SY6970_ADDR,0x0D, bat_config.data_uint8);
}

/*获取reg0D配置*/
REG_SYS_CONFIG sy6970_get_reg0d_vindpm_config(void)
{
	REG_SYS_CONFIG bat_read = {0};
	sy6970_read_byte(SY6970_ADDR,0x0D, &bat_read.data_uint8);
	return bat_read;
}

/*
 *
 * 获取reg11数据
 * 包括
 * 	bus状态
 * 	BUSV
 * */
REG_SYS_CONFIG sy6970_get_reg11_bus_status(void)
{
	REG_SYS_CONFIG bat_status = {0};
	sy6970_read_byte(SY6970_ADDR, 0x11, &(bat_status.data_uint8));
	return bat_status;
}

/*充电不使能*/
void sy6970_reg03_charge_disable(void)
{
	REG_SYS_CONFIG bat_status = {0};
	//bat_status.reg03_config.
	//sy6970_read_byte(SY6970_ADDR, 0x11, &(bat_status.data));
	//return bat_status;
}


/*
*/
REG_SYS_CONFIG sy6970_get_reg0b_charge_status(void)
{
	REG_SYS_CONFIG bat_read = {0};
	sy6970_read_byte(SY6970_ADDR,0x0b, &bat_read.data_uint8);
	return bat_read;
}


/*
 * 电池电压查询
返回值：
	电池电压
	单位mv
*/
uint16_t sy6970_get_batv(void)
{
	uint8_t data = 0;
	sy6970_read_byte(SY6970_ADDR,0x0E,&data);
	return 2304 + 20 * (data & 0X7F);
}

uint16_t sy6970_set_reg(uint8 cmd, uint16 cmd_data)
{
	REG_SYS_CONFIG bat_config = {0};
	switch(cmd)
	{
		case 0X00:
			bat_config.re00_config.EN_HIZ = 0;
			bat_config.re00_config.EN_ILIM = 1;

			bat_config.re00_config.IINLIM = (cmd_data - 100) / 50;
			break;
		case 0X02:
			bat_config.reg02_config.conv_start = 1;
			bat_config.reg02_config.conv_rate = 0;
			bat_config.reg02_config.boost_freq = 0;
			bat_config.reg02_config.aicl_en = 1;
			bat_config.reg02_config.hvdcp_en = 1;
			bat_config.reg02_config.hv_type = 1;
			bat_config.reg02_config.force_dpdm = 0;
			bat_config.reg02_config.auto_dpdm_en = 0;
			break;
		case 0X03:
			switch(cmd_data)
			{
				case 0X00:
					bat_config.reg03_config.bat_load_en = 0;
					bat_config.reg03_config.wd_rst = 0;
					bat_config.reg03_config.otg_config = 0;
					bat_config.reg03_config.chg_config = 0;
					bat_config.reg03_config.sys_min = 5;
					break;
				case 0X01:
					bat_config.reg03_config.bat_load_en = 0;
					bat_config.reg03_config.wd_rst = 0;
					bat_config.reg03_config.otg_config = 0;
					bat_config.reg03_config.chg_config = 1;
					bat_config.reg03_config.sys_min = 5;
					break;
				default:
					return 1;
			}
			break;
		case 0X04://充电电流设置
			cmd_data = cmd_data/64;
			bat_config.reg04_config.EN_PUMPX = 0;
			bat_config.reg04_config.ICHG = cmd_data;
			break;
		case 0X06:
			if(cmd_data < 3804)
				return 0;
			else
			{}
			cmd_data = (cmd_data - 4208) >= 0 ? (cmd_data - 3840)/16 : 23;
			//bat_config.
			bat_config.reg06_config.VREG = cmd_data;
			bat_config.reg06_config.BATLOWV = 1;
			bat_config.reg06_config.VRECHG = 0;
			break;
		default:
			return 1;
	}
	sy6970_write_byte(SY6970_ADDR, cmd ,bat_config.data_uint8);
	return 0;
}
/*
 * system电压查询
返回值：
	system电压
	单位mv
*/
uint16_t sy6970_get_sysv(void)
{
	uint8_t data = 0;
	sy6970_read_byte(SY6970_ADDR,0x0F,&data);
	return 2304 + 20 * (data & 0X7F);
}

void sy6970_task(void *argv)
{

	/*Buck Mode:
	000-Normal
	010-NTC Warm
	011-NTC Cool
	101-NTC Cold
	110-NTC Hot
	Boost Mode:
	000-NTC Normal
	101-NTC Cold
	110-NTC Hot*/
	//charge_status = sy6970_charge_status();//		value_v = data * 0.02 + 2.304;

	charge_current = 1024;
	charge_voltage = 4208;
	inutcharg = 1000;
	sy6970_set_reg(REG_ADC_START_CTR, 0);
	sy6970_set_reg(REG_INPUT_CURRENT_CTR, inutcharg);
	sy6970_set_reg(REG_CURRENT_CHARGE_CTR, charge_current);
	sy6970_set_reg(REG_VOLTAGE_CHARGE_CTR, charge_voltage);
	//sy6970_set_reg(REG_ADC_START_CTR, inutcharg);
	while(1)
	{
		regRead = sy6970_get_reg_config(REG_VOLTAGE_READ);
		batt_voltage = regRead.reg0e_batt_info.BATV * 20 + 2304;
		regRead = sy6970_get_reg_config(REG_SYS_VOLTAGE_READ);
		sys_voltage = regRead.reg0f_sysv_info.SYSV * 20 + 2304;
		regRead = sy6970_get_reg_config(REG_CHARGE_STATUS_READ);
		charge_status = regRead.reg0b_onre_status.charg_stat;
		regRead = sy6970_get_reg_config(REG_NTC_STATUS_READ);
		ntc_error = regRead.reg0c_tem_info.NTC_FAULT;

		regRead = sy6970_get_reg_config(REG_CHARGE_CURRENT_READ);
		charge_current_read = regRead.reg12_charge_info.ICHGR * 50;

		regRead = sy6970_get_reg_config(REG_CURRENT_STATUS_READ);
		current_limit = regRead.reg13_current_input_info.CurrentInputLimit;

		if(batt_voltage >  4224 && 1 == charge_flag)
		{
			sy6970_set_reg(REG_CHARGE_CTR, DISABLE);
			charge_flag = 0;
		}
		else if(batt_voltage < 4000 && 0 == charge_flag)
		{
			sy6970_set_reg(REG_CHARGE_CTR, ENABLE);
			charge_flag = 1;
		}
		else{;}
			
		sy6970_set_reg(REG_ADC_START_CTR, 0);
		vTaskDelay(pdMS_TO_TICKS(1000));
//3.872  **  xian 3884
		for(uint8 i = 0; i <= 0X14; i++)
		{
			reg[i] = sy6970_get_reg_config(i);
		}
//
//		batt_voltage = reg[0X0E].reg0e_batt_info.BATV * 20 + 2304;
//		sys_voltage = reg[0X0F].reg0f_sysv_info.SYSV * 20 + 2304;
//		charge_status = reg[0X0B].reg0b_onre_status.charg_stat;
//		bus_state = reg[0X11].r11_bus_info.bus_gd;
//		bus_v = reg[0X11].reg11_bus_info.busv * 100 + 2600;
//		charge_current = reg[0X12].reg12_charge_info.ICHGR;
//		ntc_error = reg[0X0C].reg0c_tem_info.NTC_FAULT;

	}
}
