/*********************************************************************
 * INCLUDES
 */
#include "hal_battery.h"
/*********************************************************************
 * DEFINITIONS
 */
 #if BATTERY_CAPACITY ==0

#define BAT_100_P 4100
#define BAT_90_P 4030
#define BAT_80_P 3930
#define BAT_70_P 3880
#define BAT_60_P 3820
#define BAT_50_P 3720
#define BAT_40_P 3650
#define BAT_30_P 3610
#define BAT_20_P 3540
#define BAT_10_P 3450
#define BAT_0_P  3200

#elif BATTERY_CAPACITY ==1

//#define BAT_100_P 4150
//#define BAT_90_P 3980
//#define BAT_80_P 3930
//#define BAT_70_P 3880
//#define BAT_60_P 3830
//#define BAT_50_P 3800
//#define BAT_40_P 3770
//#define BAT_30_P 3740
//#define BAT_20_P 3700
//#define BAT_10_P 3670
//#define BAT_0_P  3200

#define BAT_100_P 4150
#define BAT_90_P 4040
#define BAT_80_P 4000
#define BAT_70_P 3940

#define BAT_60_P 3870
#define BAT_50_P 3840
#define BAT_40_P 3800
#define BAT_30_P 3760
#define BAT_20_P 3720
#define BAT_10_P 3670
#define BAT_0_P  3200

#endif

#define ADC_REF_VOLTAGE_IN_MILLIVOLTS   600					/**< Reference voltage (in milli volts) used by ADC while doing conversion. */
#define ADC_PRE_SCALING_COMPENSATION    6					/**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
#define ADC_RES_10BIT                   4096				/**< Maximum digital value for 10-bit ADC conversion. */

// VP = (RESULT * REFERENCE / 2^10) * 6
#define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE)\
        ((((ADC_VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLTS) / ADC_RES_10BIT) * ADC_PRE_SCALING_COMPENSATION)
/*********************************************************************
 * LOCAL VARIABLES
 */
const int16_t filterLen = 100;
static uint8_t vol = 0;
static uint8_t displayvol = 0,SourceDisplayvol =0 ;
static uint32_t displaytim=0;
static int16_t real_battery =0;
/*********************************************************************
 * LOCAL FUNCTIONS
 */
static void Bubble_int16(int16_t a[],int16_t m)
{
	//冒泡排序
	int16_t i,j;
	int16_t t;
	for(i=0;i<m-1;i++){//n个数的数列总共扫描n-1次
		for(j=0;j<m-i-1;j++){//每一趟扫描到a[n-i-2]与a[n-i-1]比较为止结束
			if(a[j]>a[j+1]){//后一位数比前一位数小的话，就交换两个数的位置（升序）
				t=a[j+1];
				a[j+1]=a[j];
				a[j]=t;
			}
		}
	}
}
static int16_t MediumFilter(int16_t val)
{
	static int16_t filterArr[filterLen];
	static int16_t filterDex = 0;
	static int16_t res = 0;
	filterArr[filterDex] = val;
	if(++filterDex>=filterLen){filterDex = 0;
//		SEGGER_RTT_printf(0,"filterArr:"); for(int i=0;i<filterLen;i++){SEGGER_RTT_printf(0,"%d,",filterArr[i]);} SEGGER_RTT_printf(0,"\n");
		Bubble_int16(filterArr,filterLen);
//		SEGGER_RTT_printf(0,"filterArr:"); for(int i=0;i<filterLen;i++){SEGGER_RTT_printf(0,"%d,",filterArr[i]);} SEGGER_RTT_printf(0,"\n");
		res = filterArr[filterLen/2];
	}
	return res;
}
static int16_t Charging_voltage_calibration(int16_t batteryVoltage,uint8_t interval_time_MS){
	
	uint32_t charge_state_c =0;
	static uint32_t full_charge_temp = 0;
	static uint32_t chargechange = 0;
	static uint16_t henyatime = 0;
	int16_t bat_cal =0;
	static uint8_t behind_vol = 0;
	
	charge_state_c = nrf_gpio_pin_read(PIN_POWER_EN);
	if(chargechange != charge_state_c){//插入充电,跳变
		 chargechange = charge_state_c;
		 if(charge_state_c){
			 full_charge_temp =0 ;
			 #if BATTERY_CAPACITY == 0
			 if(vol <= 70)henyatime = 60;
			 else if(vol == 80)henyatime = 140;
			 else if(vol == 90)henyatime = 162;
			 else if(vol == 100)henyatime = 0;
			 #elif BATTERY_CAPACITY == 1
			 if(vol <= 70)henyatime = 90;
			 else if(vol == 80)henyatime = 200;
			 else if(vol == 90)henyatime = 220;
			 else if(vol == 100)henyatime = 0;
			 #endif
			 behind_vol = vol;
			 SEGGER_RTT_printf(0,"Charging_voltage_calibration %d,%d\n",vol,henyatime);
		 }
	}

	if(charge_state_c){
			 #if BATTERY_CAPACITY == 0
			 if(batteryVoltage >= 4170){//恒压
			 #elif BATTERY_CAPACITY == 1
			 if(batteryVoltage >= 4200){//恒压
			 #endif
				if(full_charge_temp < 0xFFFFFFFF)full_charge_temp += interval_time_MS; 
			  switch(behind_vol){
					case 100:
						   batteryVoltage = BAT_100_P+20;
						   break;
					case 90:
						   if(full_charge_temp/1000 > henyatime){
									full_charge_temp =0;
								  batteryVoltage = BAT_100_P+20;
								  behind_vol = 100;
								  henyatime = 0;
							 }
					     else batteryVoltage = BAT_90_P+20;
						   break;
				  case 80:
						   if(full_charge_temp/1000 > henyatime){
								  behind_vol = 90;
									batteryVoltage = BAT_90_P+20;
								  #if BATTERY_CAPACITY == 0
									henyatime = 160;
								  #elif BATTERY_CAPACITY == 1
									henyatime = 220;
								  #endif
								  
								  SEGGER_RTT_printf(0,"henya:%d,%d,%d\n",behind_vol,henyatime,full_charge_temp);
								  full_charge_temp =0;
							 }
							 else batteryVoltage = BAT_80_P+20;
						   break;
					case 70:
						   if(full_charge_temp/1000 > henyatime){
									batteryVoltage = BAT_80_P+20;
								  behind_vol = 80;
								  #if BATTERY_CAPACITY == 0
									henyatime = 140;
								  #elif BATTERY_CAPACITY == 1
								  henyatime = 200;
								  #endif
									SEGGER_RTT_printf(0,"henya:%d,%d,%d\n",behind_vol,henyatime,full_charge_temp);
								  full_charge_temp =0;
							 }
					     else batteryVoltage = BAT_70_P+20;
						   break;
					default:
						   if(full_charge_temp/1000 > henyatime){
									batteryVoltage = BAT_70_P+20;
								  behind_vol = 70;
								  #if BATTERY_CAPACITY == 0
									henyatime = 60;
								  #elif BATTERY_CAPACITY == 1
								  henyatime = 90;
								  #endif
									
								  SEGGER_RTT_printf(0,"henya:%d,%d,%d\n",behind_vol,henyatime,full_charge_temp);
								  full_charge_temp =0;
							 }
					     else batteryVoltage = BAT_60_P+20;

               break;						
				}
		 }else{//恒流
				full_charge_temp =0;
			  #if BATTERY_CAPACITY == 0
				if(batteryVoltage >= 3810)batteryVoltage -= 320;
			  else if(batteryVoltage < 3810 && batteryVoltage >= BAT_0_P)batteryVoltage -= 400;
        #elif BATTERY_CAPACITY == 1	 
			  if(batteryVoltage >= 3900)batteryVoltage -= 310;
			  else if(batteryVoltage >= BAT_0_P)batteryVoltage -= 400;
        #endif
				else if(batteryVoltage < BAT_0_P)batteryVoltage = BAT_0_P;		 
		 }
	}
	else full_charge_temp =0;
	
	bat_cal = batteryVoltage;
	return bat_cal;
}
static uint8_t GetBatteryPersent(int16_t batteryVoltage)
{
		uint8_t vol_t = 0;
		if(batteryVoltage >= BAT_100_P)vol_t = 100;
		else if(batteryVoltage >= BAT_90_P)vol_t = 90;
		else if(batteryVoltage >= BAT_80_P)vol_t = 80;
		else if(batteryVoltage >= BAT_70_P)vol_t = 70;
		else if(batteryVoltage >= BAT_60_P)vol_t = 60;
		else if(batteryVoltage >= BAT_50_P)vol_t = 50;
		else if(batteryVoltage >= BAT_40_P)vol_t = 40;
		else if(batteryVoltage >= BAT_30_P)vol_t = 30;
		else if(batteryVoltage >= BAT_20_P)vol_t = 20;
		else if(batteryVoltage >= BAT_10_P)vol_t = 10;
		else if(batteryVoltage < BAT_10_P && batteryVoltage >= BAT_0_P)vol_t = ((batteryVoltage-BAT_0_P)/((BAT_10_P - BAT_0_P)/10));
		else if(batteryVoltage < BAT_0_P)vol_t = 0;
		return vol_t;
}
static void cb_batteryWakeup(uint32_t t)
{
	nrf_gpio_cfg_output(PIN_ADC_EN);		nrf_gpio_pin_write(PIN_ADC_EN,0);
}

static void cb_batterySleep(uint32_t t)
{
	nrf_gpio_cfg_output(PIN_ADC_EN);		nrf_gpio_pin_write(PIN_ADC_EN,1);
}
/*********************************************************************
 * PUBLIC FUNCTIONS
 */
int16_t ADC_GetValue(uint32_t channel)
{
	int16_t temp=0;
	ADC_Read(channel, &temp);
	return temp;
}
/**********************************************************
 * 函数名字：GetBatteryCurrentPersen
 * 函数作用：获取电池电量百分比
 * 函数参数：adcvalue ：读取到ADC值
 * 函数返回值：电量值
 ***********************************************************/
uint8_t Battery_GetBatteryPersent(void)
{
	 return displayvol;
}
void displayvol_process(void){
	
	uint32_t charge_state_c =0;
	
	charge_state_c = nrf_gpio_pin_read(PIN_POWER_EN);
	if(charge_state_c){
		 if(SourceDisplayvol > displayvol){
					  if(displayvol >=10 && displayvol < 100){
							if(TIME_GetTicks()-displaytim >= 2000){ 
								displaytim = TIME_GetTicks();
								displayvol+=1;
								SEGGER_RTT_printf(0,"1 displayvol_process:%d,%d,%d\n",SourceDisplayvol,displayvol,vol);
							}
						}
					  else if(displayvol < 10){
							if(TIME_GetTicks()-displaytim >= 2000){ 
								displaytim = TIME_GetTicks();
								displayvol+=1;
								SEGGER_RTT_printf(0,"2 displayvol_process:%d,%d,%d\n",SourceDisplayvol,displayvol,vol);
							}
						}
	      }
	}
	else{
		 if(SourceDisplayvol < displayvol){
			  if(TIME_GetTicks()-displaytim >= 60000){ displaytim = TIME_GetTicks();
					  if(displayvol > 10 && displayvol <= 100)displayvol -= 10;
					  else if(displayvol <= 10 && displayvol >0)displayvol -=1;
					  SEGGER_RTT_printf(0,"3 displayvol_process:%d,%d,%d\n",SourceDisplayvol,displayvol,vol);
	      }
		 }
	}
}
uint8_t Battery_BatteryIs_0(void)
{
	 if(real_battery <= BAT_0_P)return 1;
	 else return 0;
}
void battery_process(void)
{
	static uint32_t tim=0;
	static uint32_t tim_charge=100;
	
	int16_t batteryVoltage;
	int16_t adcVal;
	int16_t volTemp;

	displayvol_process();
	
	if(TIME_GetTicks()-tim >= tim_charge){ tim = TIME_GetTicks();
				if( nrf_gpio_pin_read(PIN_POWER_EN)) 	tim_charge = 10;  
				else tim_charge = 100;
		
				adcVal = ADC_GetValue(PIN_ADC_CHANNEL);
				volTemp = ADC_RESULT_IN_MILLI_VOLTS(adcVal)*5/3; // 电池电压转换计算
				
				batteryVoltage = MediumFilter(volTemp);
				real_battery = batteryVoltage;
		    batteryVoltage = Charging_voltage_calibration(batteryVoltage,tim_charge);
		
		    static uint32_t t = 0;
				if(t != TIME_GetTicks()/1000){
					t = TIME_GetTicks()/1000;
					SEGGER_RTT_printf(0,"%d,%d,%d,%d,%d\n",adcVal,volTemp,batteryVoltage,displayvol,t);
				}
				
				vol = GetBatteryPersent(batteryVoltage);
				
				if(SourceDisplayvol != vol){
					SourceDisplayvol = vol;
					displaytim = TIME_GetTicks();
				}
				
				static uint8_t vol_temp =0;
				if(vol_temp != displayvol){
					vol_temp =displayvol;
					SEGGER_RTT_printf(0,"&&&&&&&&&&>vol:%d(%d),tim:%d\n\n\n",batteryVoltage,displayvol,TIME_GetTicks()/1000);
				}
	  }
}
void Battery_Initialize(void)
{
	ADC_SetPinChannel(PIN_ADC_IN, PIN_ADC_CHANNEL);
	Process_Start(0,battery_process);
	
	Wakeup_Regist(cb_batteryWakeup);
	Sleep_Regist(cb_batterySleep);
}
/**********************************************************
 * 函数名字：User_SAADC_DisOrEnable
 * 函数作用：SAADC的打开和关闭
 * 函数参数：无
 * 函数返回值：无
 ***********************************************************/
void Battery_Enable(bool value)
{
	static bool battery_Open_Flag =false;
	int16_t batteryVoltage;
	if(value == battery_Open_Flag)return;
	if(value){
		nrf_gpio_cfg_output(PIN_ADC_EN);		nrf_gpio_pin_write(PIN_ADC_EN,0);
		for(int i=0;i<filterLen;i++){
			MediumFilter(ADC_RESULT_IN_MILLI_VOLTS(ADC_GetValue(PIN_ADC_CHANNEL))*5/3);
		}
		batteryVoltage = (ADC_RESULT_IN_MILLI_VOLTS(ADC_GetValue(PIN_ADC_CHANNEL))*5/3);
		batteryVoltage = Charging_voltage_calibration(batteryVoltage,0);
		vol = GetBatteryPersent(batteryVoltage);
		displayvol = vol;
		SourceDisplayvol = vol;
		
		SEGGER_RTT_printf(0,"Battery_Enable,%d,%d,%d\n",batteryVoltage,vol,displayvol);
		
	}else{
		nrf_gpio_cfg_output(PIN_ADC_EN);		nrf_gpio_pin_write(PIN_ADC_EN,1);
	}
	battery_Open_Flag = value;
}






