#include "power.h"
#include "base/utility.h"
#include "gpio_cfg.h"
#include "base/delay.h"
#define PowerCurr_AD_BUF_LEN   40
#define POWER_SET_COUNT        20
static volatile CurrentSample_Range_eu latest_range = Current_Max;
static volatile PowerInfo_st def_power_st;
//static uint16_t PowerCurr_AD_buf[PowerCurr_AD_BUF_LEN];
static volatile float f_cur_k;
static volatile float f_cur_b;
static volatile uint8_t uc_power_cal_flag = 0;
volatile PowerInfo_st powerinfo_arrayst[POWER_SET_COUNT] ;


/*
@brief 获取内部基准1.2V电压对应的AD
*/
uint32_t Power_GetBaseVAD()
{
	// y1 = kx1+b  y2=kx2+b  y1-y2/x1-x2 
//	uint16_t adv_buf[10];
//	uint32_t temp_v;
//	GetADC0_Value(ADC_CHANNEL_17,adv_buf,10) ;
//	Bubble_Sort_u16(adv_buf,10);
//	return (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
	
	return (uint32_t)(1.2f/3.3f*4096);
}

void Power_CurCalibration()
{
	uint16_t adv_buf[10],adv2v5,adv1v25;
	uc_power_cal_flag = 1;
	GetADC1_Value(VCC_2V5_CH,adv_buf,10) ;
	Bubble_Sort_u16(adv_buf,10);
	adv2v5 = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
	
	GetADC1_Value(VCC_1V25_CH,adv_buf,10) ;
	Bubble_Sort_u16(adv_buf,10);
	adv1v25 = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
	
	f_cur_k = 1.245f/((adv2v5 - adv1v25)+1);
	f_cur_b = 2.49f-f_cur_k*adv2v5;
	
	
//	GetADC0_Value(VCC_1V25_CH,adv_buf,10) ;
//	Bubble_Sort_u16(adv_buf,10);
//	adv1v25 = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
//	
//	f_cur_k = 1.25f/((adv2v5 - adv1v25)+1);
//	f_cur_b = 2.5f-f_cur_k*adv2v5;
}
/*
@brief 将获取的ADC值转换为电压值
@param1 ul_adv 采样AD原始值
@rtv    返回AD采集到的电压值 扩大1000000倍
*/
uint32_t Power_ADVGetCalVal_106(uint16_t ul_adv)
{
	if(uc_power_cal_flag == 0)
	{
		Power_CurCalibration();
	}
	return (uint32_t)((f_cur_k*ul_adv+f_cur_b)*1000000);
}


 /*
@brief 采样高电平电压
*/
uint32_t Power_GetHPowerV()
{
	uint32_t adv;
	uint16_t adv_buf[10];
	Power_CurCalibration();
	GetADC1_Value(V_LA_H_CH,adv_buf,10) ;
	Bubble_Sort_u16(adv_buf,10);
	adv = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
	adv = Power_ADVGetCalVal_106(adv);
	adv = adv*V_PARAM_1/100000;
	return adv;
}

 /*
@brief 采样总线输出电压
*/
uint32_t Power_GetBousV()
{
	uint32_t abus_v,bbus_v;
	uint16_t adv_buf[10];
  uint32_t hbus_v=0;
	Power_CurCalibration();
	GetADC1_Value(AD_OUTA_CH,adv_buf,10) ;
	Bubble_Sort_u16(adv_buf,10);
	abus_v = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
	
	GetADC1_Value(AD_OUTB_CH,adv_buf,10) ;
	Bubble_Sort_u16(adv_buf,10);
	bbus_v = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
	
	if(bbus_v > abus_v)
	{
		abus_v = bbus_v;
	}
	
	abus_v = Power_ADVGetCalVal_106(abus_v);
	abus_v = abus_v*11/100000;
  
//  hbus_v=Power_GetHPowerV();
  
  //?  验证电压失调
  // 电压相差过大的时候输出一个离谱的值
//  if((hbus_v>abus_v+10)||(abus_v>hbus_v+10)){
//    abus_v=500;
//  }
  
	return abus_v;
}

/*
@brief 采样中电平电压
*/
uint32_t Power_GetMPowerV()
{
	int32_t adv;
	uint16_t adv_buf[10];
	GetADC1_Value(V_LA_M_CH,adv_buf,10) ;
	Bubble_Sort_u16(adv_buf,10);
	adv = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
	adv = Power_ADVGetCalVal_106(adv);
	adv = adv*V_PARAM_1/100000;
	return adv;
}

/*
typedef enum{
	R510_0uA_32uA_UC 		= (uint8_t)0,//x201
	R510_0uA_580uA_MC 	= (uint8_t)1,//x11
	R100_0uA_160uA_UC   = (uint8_t)2,//x201
	R100_0p2mA_3mA_MC		= (uint8_t)3,//x11
	R10_0p1mA_1p6mA_UC	= (uint8_t)4,//x201
	R10_2mA_30mA_MC			= (uint8_t)5,//x11
	Current_Max 				= (uint8_t)6,
	Current_SampleR_OFF = (uint8_t)9,
} CurrentSample_Range_eu;
*/
/*
@brief 通过采样adc，换算电流
@param adv adc 采样值
@param rang 采样电阻
@rtv uint32_t 电流值 0.1uA
*/
uint32_t Power_ConvCur(uint16_t adv,CurrentSample_Range_eu range)
{
	uint32_t ul_R,ul_Mut;
	uint32_t ul_adv = Power_ADVGetCalVal_106(adv);
	switch(range)
	{
		case R510_0uA_32uA_UC: 	  ul_R = 510; ul_Mut = 201 ; break;
		case R510_0uA_580uA_MC: 	ul_R = 510; ul_Mut = 11; break;
		case R100_0uA_160uA_UC: 	ul_R = 100; ul_Mut = 201; break;
		case R100_0p2mA_3mA_MC: 	ul_R = 100; ul_Mut = 11;  break;
		case R10_0p1mA_1p6mA_UC: 	ul_R = 10; 	ul_Mut = 201; break;
		case R10_2mA_30mA_MC: 		ul_R = 10; 	ul_Mut = 11;  break;
		case Current_Max: 				ul_R = 10;  ul_Mut = 1; break;
		case Current_SampleR_OFF: ul_R = 510; ul_Mut = 1;break;
		default:  ul_R = 510; ul_Mut = 1;break;
	}
  ul_adv = 	(ul_adv*100 / ul_R /ul_Mut+4)/10;
  return ul_adv;
}
//根据电流大小的范围，设置采样电阻
CurrentSample_Range_eu  Power_SetSampleCurrentRange(CurrentSample_Range_eu range)	
{
	
	switch(range)
	{
		case R510_0uA_32uA_UC: 			R510_SW_ON;	R100_SW_OFF;		R10_SW_OFF; break;
		case R510_0uA_580uA_MC: 		R510_SW_ON;	R100_SW_OFF;		R10_SW_OFF; break;
		case R100_0uA_160uA_UC: 		R100_SW_ON; R510_SW_OFF;		R10_SW_OFF; break;
		case R100_0p2mA_3mA_MC: 		R100_SW_ON;	R510_SW_OFF;		R10_SW_OFF; break;
		case R10_0p1mA_1p6mA_UC: 		R10_SW_ON;	R510_SW_OFF;		R100_SW_OFF; break;
		case R10_2mA_30mA_MC: 			R10_SW_ON;	R510_SW_OFF;		R100_SW_OFF; break;
		case Current_Max: 					R510_SW_ON;	R100_SW_ON; 		R10_SW_ON;break;
		case Current_SampleR_OFF:   R510_SW_OFF;R100_SW_OFF;		R10_SW_OFF;break;
		default:  range = Current_Max; R510_SW_ON;		R100_SW_ON; 		R10_SW_ON;break;
	}
	latest_range = range;
	return latest_range;
}

/*
@brief 设置电阻采样通道和AD采样配置
*/
CurrentSample_Range_eu Power_SetSampleRange_Seep(CurrentSample_Range_eu range , uint32_t speed)
{
	switch(range)
	{
		case R510_0uA_32uA_UC: 	ADC_CurChnnelSet(AN_UA_CH,speed); break;
		case R510_0uA_580uA_MC: 		ADC_CurChnnelSet(AN_MAL_CH,speed); break;
		case R100_0uA_160uA_UC: 		ADC_CurChnnelSet(AN_UA_CH,speed); break;
		case R100_0p2mA_3mA_MC: 	ADC_CurChnnelSet(AN_MAL_CH,speed); break;
		case R10_0p1mA_1p6mA_UC: 		ADC_CurChnnelSet(AN_UA_CH,speed); break;
		case R10_2mA_30mA_MC: 	ADC_CurChnnelSet(AN_MAL_CH,speed); break;
		case Current_Max: 		ADC_CurChnnelSet(AN_MAL_CH,speed); break;
		case Current_SampleR_OFF:   ADC_CurChnnelSet(AN_MAL_CH,speed);break;
		default:  ADC_CurChnnelSet(AN_MAL_CH,speed);break;
	}
	return Power_SetSampleCurrentRange(range);
}


//获取总线电流
uint32_t Power_GetCurrent(void)
{
	uint32_t adv;
	uint32_t count;
	CurrentSample_Range_eu range = latest_range;//档位保存
	CurrentSample_Range_eu set_range;
	uint32_t adv_base =  Power_GetBaseVAD();
	if(adv_base < 500)
		return 0;
	set_range = Power_SetSampleCurrentRange(R10_2mA_30mA_MC);
	StartADC2Channel(AN_MAL_CH,ADC_SPEED_SLOW);
	delay_us(300);
	GetADC_Fast(ADC_CURR_DE);
	adv = 0;
	for(count = 0; count < 4; count++)
	{
		adv +=  GetADC_Fast(ADC_CURR_DE);
	}
	adv >>= 2;
	if(adv > 250){
		adv = Power_ConvCur(adv,set_range);//0.1uA
		adv = (adv+4)/10;
		Power_SetSampleCurrentRange(range);
		return adv;
	}
	set_range = Power_SetSampleCurrentRange(R100_0p2mA_3mA_MC);
	StartADC2Channel(AN_MAL_CH,ADC_SPEED_SLOW);
	delay_us(300);
	GetADC_Fast(ADC_CURR_DE);
	adv = 0;
	for(count = 0; count < 4; count++)
	{
		adv +=  GetADC_Fast(ADC_CURR_DE);
	}
	adv >>= 2;
	if(adv > 250){
		adv = Power_ConvCur(adv,set_range);//0.1uA
		adv = (adv+4)/10;
		Power_SetSampleCurrentRange(range);
		return adv;
	}
	
	set_range = Power_SetSampleCurrentRange(R10_0p1mA_1p6mA_UC);
	StartADC2Channel(AN_UA_CH,ADC_SPEED_SLOW);
	delay_ms(2);
	GetADC_Fast(ADC_CURR_DE);
	adv = 0;
	for(count = 0; count < 4; count++)
	{
		adv +=  GetADC_Fast(ADC_CURR_DE);
	}	
	adv >>= 2;
	if(adv > 250){
		adv = Power_ConvCur(adv,set_range);//0.1uA
		adv = (adv+4)/10;
		Power_SetSampleCurrentRange(range);
		return adv;
	}
	set_range = Power_SetSampleCurrentRange(R100_0uA_160uA_UC);
	StartADC2Channel(AN_UA_CH,ADC_SPEED_SLOW);
	delay_ms(3);
	GetADC_Fast(ADC_CURR_DE);
	adv = 0;
	for(count = 0; count < 8; count++)
	{
		adv +=  GetADC_Fast(ADC_CURR_DE);
	}	
	adv >>= 3;
	adv = Power_ConvCur(adv,set_range);//0.1uA
	adv = (adv+4)/10;
	Power_SetSampleCurrentRange(range);
	return adv;
}

/*
@brief 电源调压准备，计数频率和电压的线性关系
@rtv 返回值：0 成功 其他失败
*/

uint8_t PowerCalPrapare(void)
{
	//YM硬件直接由公式计算
	return 0;
}
//防止突然上电，导致电源崩溃
static void PowerUpFilter(uint16_t tag_dac)
{
	uint16_t us_lastdac_h = DAC_GetDataOutputValue(DAC_Channel_1);
	if(us_lastdac_h > (tag_dac + 200))
	{
		while(us_lastdac_h > tag_dac)
		{
			if((tag_dac + 100) < us_lastdac_h)
			{
				us_lastdac_h -= 50;
				C_H_DAC_Set(us_lastdac_h);
			}else{
				us_lastdac_h = tag_dac;
				C_H_DAC_Set(us_lastdac_h);
			}
			delay_ms(10);
		}
	}
}

//电压调节的关系为线性函数
void PowerCalibration(PowerInfo_st* info_st)
{
	
	float vlp,vlm,v_adc_h,v_adc_m;
	uint16_t us_basedac_h,us_basedac_m;
	uint16_t us_lastdac_h,us_lastdac_m;
	uint16_t us_powderv;
	uint16_t us_timeout ;
	uint32_t diff=0;
	uint16_t ok_flg = 0;
	uint8_t uc_down_up_flag = 0;
	if(info_st->V_LAH < info_st->V_LAM )
	{
		info_st->V_LAH_DAC = 0;
		info_st->V_LAM_DAC = 0;
		return ;
	}
	PAout(LAVC_M_Pin_Nu)=0;PBout(OUTAH_Pin_Nu)=0;
	PBout(OUTBL_Pin_Nu)=0;PBout(OUTAL_Pin_Nu)=0;
	PCout(POWER_ON_Pin_Nu) = 1;
	vlp = info_st->V_LAH;
	vlp /= 10;
	//(VLP-1.229V)/178K + (VDAC-1.229V)/20K = 0.1229mA
	v_adc_h =( 0.1229- (vlp-1.229)/V_PARAM_2)*20+1.229;
	us_timeout = 80;
	info_st->V_LAH_DAC = 0;
	us_basedac_h = (uint16_t)( v_adc_h/3.3 * 4096);
	PowerUpFilter(us_basedac_h);
	us_lastdac_h = 0;
	//us_basedac_h = 250;
	ok_flg = 0;
	uc_down_up_flag = 0;
	while(us_timeout > 0)
	{
		us_timeout--;
		C_H_DAC_Set(us_basedac_h);
		us_lastdac_h = us_basedac_h;
		switch(uc_down_up_flag)
		{
			case 0:delay_os_ms(100);break;//首次调压
			case 1:delay_os_ms(50);break;//降压
			case 2:delay_os_ms(10);break;//升压
		}
		us_powderv = Power_GetHPowerV();
		diff = us_powderv > info_st->V_LAH?us_powderv-info_st->V_LAH:info_st->V_LAH-us_powderv;
		if(diff < 2)
		{
			ok_flg++;
			if(ok_flg > 2)
			{
				info_st->V_LAH_DAC = us_basedac_h;
				break;
			}else{
				continue;
			}
		
		}
		diff = diff *2;
		ok_flg = 0;
		if( us_powderv > info_st->V_LAH)
		{
			us_basedac_h += diff;
			uc_down_up_flag = 1;
		}else{
			us_basedac_h -= diff;
			uc_down_up_flag = 2;
		}
		
		
		if(us_basedac_h < 20)
			us_basedac_h = 20;
		if(us_basedac_h > 4050)
			us_basedac_h = 4050;
		
	}
	if(info_st->V_LAH_DAC == 0)
		return;
	
	//(VM-2.5V)/20k+(VDAC-2.5V)/4.7K = 0.25mA
	us_timeout = 100;
	info_st->V_LAM_DAC = 0;
	vlm = info_st->V_LAM ;
	vlm /= 10;
	v_adc_m =( 0.25- (vlm-2.5)/20)*4.7+2.5;
	us_basedac_m = (uint16_t)(v_adc_m / 3.3 * 4096);
	//us_lastdac_m = 250;
	ok_flg = 0;
	uc_down_up_flag = 0;
	while( us_timeout > 0)
	{
		us_timeout--;
		C_M_DAC_Set(us_basedac_m);
		us_lastdac_m = us_basedac_m;
		switch(uc_down_up_flag)
		{
			case 0:delay_os_ms(50);break;//首次调压
			case 1:delay_os_ms(40);break;//降压
			case 2:delay_os_ms(30);break;//升压
			default:delay_os_ms(50);break;
		}
		us_powderv = Power_GetMPowerV();
		diff = us_powderv > info_st->V_LAM?us_powderv-info_st->V_LAM:info_st->V_LAM-us_powderv;
		if(diff < 2)
		{
			ok_flg++;
			if(ok_flg > 2)
			{
				info_st->V_LAM_DAC = us_basedac_m;
				break;
			}
			else{
				continue;
			}
		}
		ok_flg = 0;
		diff = diff *10;
		if( us_powderv > info_st->V_LAM)
		{
			us_basedac_m += diff;
			uc_down_up_flag = 1;
		}else{
			uc_down_up_flag = 2;
			us_basedac_m -= diff;
		}
		if(us_basedac_m < 100)
			us_basedac_m = 100;
		if(us_basedac_m > 4050)
			us_basedac_m = 4050;
	}
	
}
//设置总线电压
void PowerSetVoltage(PowerInfo_st* info_st)
{
	memcpy((void *)&def_power_st,info_st,sizeof(PowerInfo_st));
	PowerUpFilter(info_st->V_LAH_DAC);
	C_H_DAC_Set(info_st->V_LAH_DAC);
	C_M_DAC_Set(info_st->V_LAM_DAC);
	POWER_ON;
  //?  验证电压失调
//	delay_ms(5);
//	C_H_DAC_Set(info_st->V_LAH_DAC);
//	C_M_DAC_Set(info_st->V_LAM_DAC);
}
//获取当前电压配置值
void PowerGetSet(PowerInfo_st* info_st)
{
	uint16_t h_dac = DAC_GetDataOutputValue(DAC_Channel_1);
	uint16_t m_dac = DAC_GetDataOutputValue(DAC_Channel_2);
	info_st->V_LAH = 0;
	info_st->V_LAH_DAC = h_dac;
	if(h_dac == def_power_st.V_LAH_DAC)
	{
		info_st->V_LAH = def_power_st.V_LAH;
	}
	info_st->V_LAM = 0;
	info_st->V_LAM_DAC = h_dac;
	if(m_dac == def_power_st.V_LAM_DAC)
	{
		info_st->V_LAM_DAC = m_dac;
	}
}
/*
@brief 设置总线电压
@param h_v/10 设置高电平电压
@param m_v/10 设置中电平电压
@rtv  0 执行成功 1 执行失败
*/
	
uint8_t  PowerCalibration_set(uint16_t h_v,uint16_t m_v)
{
	uint32_t ul_index = 0;
	PowerInfo_st powerinfo_st;
	rt_memset(&powerinfo_st,0,sizeof(PowerInfo_st));
	while(ul_index < POWER_SET_COUNT)
	{
		//if( powerinfo_arrayst[ul_index].V_LAH == h_v && powerinfo_arrayst[ul_index].V_LAM == m_v)
		if( powerinfo_arrayst[ul_index].V_LAH == h_v)
		{
			break;
		}
		ul_index++;
	}
	//在现有电压列表中能够查询到校准后的电压
	if(ul_index < POWER_SET_COUNT)
	{
		memcpy((void *)&powerinfo_st,(void *)&powerinfo_arrayst[ul_index],sizeof(PowerInfo_st));
	  PowerSetVoltage(&powerinfo_st);
		return 0;
	}
	
	powerinfo_st.V_LAH = h_v;
	powerinfo_st.V_LAM = m_v;
	PowerCalibration(&powerinfo_st);
	if(powerinfo_st.V_LAH_DAC == 0 || powerinfo_st.V_LAM_DAC == 0)
	{
		LED1_Out = 1;
		return 1;
	}
	//校准完成后，设置总线电压
	PowerSetVoltage(&powerinfo_st);
	//查找为使用的配置缓存，将新设置的电压保存
	ul_index = 0;
	while(ul_index < POWER_SET_COUNT)
	{
		if( powerinfo_arrayst[ul_index].V_LAH_DAC == 0 || powerinfo_arrayst[ul_index].V_LAM_DAC == 0)
		{
			memcpy((void *)&powerinfo_arrayst[ul_index],&powerinfo_st,sizeof(PowerInfo_st));
			break;
		}
		ul_index++;
	}
	
	return 0;
}

