/********************************************************************************
Copyright (C), Sinowealth Electronic. Ltd.
Author: 	Sino
Version: 	V0.0
Date: 		2020/04/26
History:
	V2.0	2020/04/26		 Preliminary
********************************************************************************/
#include "Main.h"


U8	xdata	ucChgingCheckCnt;
U8	xdata	ucDsgingCheckCnt;

/*************************************************************************************************
* 函数名: CalcuTemp
* 参  数: 无
* 返回值: 无
* 描  述: 根据计算的阻值来查表，获取对应温度。温度变量保存的为开尔文温度*10
          例如摄氏度25°，温度变量保存的值为2731+250
*************************************************************************************************/
U16 CalcuTemp(U16 getdata)
{
	U8	i;
	U16	Temperature;
    U32 Tempcalcu;
 
#if (AFE_ID == 0x34)
    Tempcalcu = (U32)getdata*REF_RES_VAL/(32768-getdata);
#else
	Tempcalcu= (U32)getdata*REF_RES_VAL/(4096-getdata);     //calculte the resistance value of 103AT
    if(Tempcalcu > 10)
    {
        Tempcalcu -= 10;
    }   
#endif
 
	if(Tempcalcu >= NTC103AT[0])                            //look up table to find the resieter  correspond temp
	{
		Temperature = 2731+(TEMP_LOWER_LIMIT *10);			
	}
	else if(Tempcalcu <= NTC103AT[NTC103AT_ARRAY_LEN-1])
	{
		Temperature = 2731+(TEMP_UPPER_LIMIT *10);
	}
	else
	{
		i = ucTempeMiddle;                                  //the ucTempeMiddle must be initialized in InitVar()
		if(Tempcalcu > NTC103AT[i])
		{
			for(i=ucTempeMiddle-1; i>=0; i--)
			{
				if(Tempcalcu <= NTC103AT[i])                //NTC103AT[i+1]<resis<NTC103AT[i]
				{
					break;
				}
			}
		}
		else
		{
			for(i=ucTempeMiddle+1; i<NTC103AT_ARRAY_LEN-1; i++)
			{
				if(Tempcalcu > NTC103AT[i])                 //NTC103AT[i-1]<resis<NTC103AT[i]
				{
					break;
				}
			}
			i--;
		}
		ucTempeMiddle = i;
#if NTC_SL //SL热敏电阻
		Temperature = (U16)(ucTempeMiddle-20)*10+(NTC103AT[i]-Tempcalcu)*10/(NTC103AT[i]-NTC103AT[i+1])+2731;
#else 
		Temperature = (U16)(ucTempeMiddle-50)*10+(NTC103AT[i]-Tempcalcu)*10/(NTC103AT[i]-NTC103AT[i+1])+2731;
#endif	
	}
	return Temperature;	
}


/*************************************************************************************************
* 函数名: AfeGetVol、AfeGetTempe
* 参  数: 无
* 返回值: 无
* 描  述: 从AFE读取电压、温度采集数据
*************************************************************************************************/
BOOL AfeGetVol(void)
{
	U8  i;
	BOOL Result=1;

	for(i=ucCellNumOffset; i<(ucCellNum+ucCellNumOffset); i++)
    {
		if(!AFEReadReg(AFE_CELL1H+2*i, 2, (U8 xdata *)(&AFE.uiCell[i])))	//通过TWI读取VADC采集的电压值()
        {
			Result = 0;
			return Result;
		}
	}
	
	return Result;
}

BOOL AfeGetTempe(void)
{
	BOOL Result=1;
	
	if(!AFEReadReg(AFE_TS1H, 2, (U8 xdata *)&AFE.uiTS[0]))
	{
		Result = 0;
	}
	if(!AFEReadReg(AFE_TS2H, 2, (U8 xdata *)&AFE.uiTS[1]))
	{
		Result = 0;
    }
    
    if(!AFEReadReg(AFE_TEMP1H, 2, (U8 xdata *)&AFE.uiICTempe[0]))
	{
		Result = 0;
	}
    if(ucCellNum > 5)                                           //6~10串应用时
    {
        if(!AFEReadReg(AFE_TEMP2H, 2, (U8 xdata *)&AFE.uiICTempe[1]))
        {
            Result = 0;
        }
    }
	
	return Result;
}


/*************************************************************************************************
* 函数名: AfeCalcuTempe
* 参  数: 无
* 返回值: 无
* 描  述: 计算温度，更新uiTempeMax、uiTempeMin
*************************************************************************************************/
void AfeCalcuTempe(void)
{
    U16 TempeData;

	if(AfeGetTempe())
	{
		TempeData = CalcuTemp(AFE.uiTS[0]) + E2siTS0Offset;		//计算外部温度1
		#if	(UART0_DEFINE != 0)	
		IrqUart0Dis();
		#endif
		#if	(UART1_DEFINE != 0)
		IrqUart1Dis();
		#endif
		#if	(UART2_DEFINE != 0)
		IrqUart2Dis();
		#endif
		Info.uiTS[0] = TempeData;
		#if	(UART0_DEFINE != 0)			
		IrqUart0En();						       		//开启uart0中断						        
		#endif	
		#if	(UART1_DEFINE != 0)			
		IrqUart1En();						       		//开启uart1中断						        
		#endif	
		#if	(UART2_DEFINE != 0)
		IrqUart2En();						        //初始化UART2中断使能，根据具体使用UART模块来进行选择
		#endif
		TempeData = (U32)AFE.uiICTempe[0]*17/10+31;               //计算内部温度1
		#if	(UART0_DEFINE != 0)	
		IrqUart0Dis();
		#endif
		#if	(UART1_DEFINE != 0)
		IrqUart1Dis();
		#endif
		#if	(UART2_DEFINE != 0)
		IrqUart2Dis();
		#endif
		Info.uiICTempe[0] = TempeData;
		
		#if	(UART0_DEFINE != 0)			
		IrqUart0En();						       		//开启uart0中断						        
		#endif	
		#if	(UART1_DEFINE != 0)			
		IrqUart1En();						       		//开启uart1中断						        
		#endif
		#if	(UART2_DEFINE != 0)
		IrqUart2En();						        //初始化UART2中断使能，根据具体使用UART模块来进行选择
		#endif
	  
		if(ucCellNum > 5)										//6~10串应用时
		{    
			TempeData = (U32)AFE.uiICTempe[1]*17/10+31;           //计算内部温度2
			#if	(UART0_DEFINE != 0)	
			IrqUart0Dis();
			#endif
			#if	(UART1_DEFINE != 0)
			IrqUart1Dis();
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2Dis();
			#endif
			Info.uiICTempe[1] = TempeData;
			#if	(UART0_DEFINE != 0)			
			IrqUart0En();						       		//开启uart0中断						        
			#endif	
			#if	(UART1_DEFINE != 0)			
			IrqUart1En();						       		//开启uart1中断						        
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2En();						        //初始化UART2中断使能，根据具体使用UART模块来进行选择
			#endif
		}
	 
		uiTempeMin = Info.uiTS[0];
		uiTempeMax = Info.uiTS[0];
		if(bTempNum)
		{
			TempeData = CalcuTemp(AFE.uiTS[1]) + E2siTS1Offset; //计算外部温度2
			#if	(UART0_DEFINE != 0)	
			IrqUart0Dis();
			#endif
			#if	(UART1_DEFINE != 0)
			IrqUart1Dis();
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2Dis();
			#endif
			Info.uiTS[1] = TempeData;
			#if	(UART0_DEFINE != 0)			
			IrqUart0En();						       		//开启uart0中断						        
			#endif	
			#if	(UART1_DEFINE != 0)			
			IrqUart1En();						       		//开启uart1中断						        
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2En();						        //初始化UART2中断使能，根据具体使用UART模块来进行选择
			#endif
			
			if(TempeData < uiTempeMin)
			{
				uiTempeMin = TempeData;
			}
			else
			{
				uiTempeMax = TempeData;
			}
		}
	}
}


/*************************************************************************************************
* 函数名: AfeCalcuVol
* 参  数: 无
* 返回值: 无
* 描  述: 计算电压，同步更新最大值最小值uiVadcVmax、uiVadcVmin，用于断线判断
          当没有平衡时，才更新uiCellVmax、uiCellVmin，用于保护判断
*************************************************************************************************/
void AfeCalcuVol(void)
{
	U8 i;
	U32 TempPackVol=0, TempCellVol=0;
	uiVadcVmax = 0;					  
	uiVadcVmin = 6000;

	if(AfeGetVol())
	{
		for(i=ucCellNumOffset; i<(ucCellNum+ucCellNumOffset); i++)
		{
			TempCellVol = (U32)AFE.uiCell[i]*CALIVOL/E2uiVPackGain;
		
			if(TempCellVol > uiVadcVmax)            //计算最大值&最小值
			{
				uiVadcVmax = TempCellVol;
			}
			if(TempCellVol < uiVadcVmin)
			{
				uiVadcVmin = TempCellVol;
			}

			if(!bBalancingFlg)                      //if bCellOpenDecFlag this data will throw away
			{
				#if	(UART0_DEFINE != 0)	
				IrqUart0Dis();
				#endif
				#if	(UART1_DEFINE != 0)
				IrqUart1Dis();
				#endif
				#if	(UART2_DEFINE != 0)
				IrqUart2Dis();
				#endif
				Info.uiVCell[i] = TempCellVol;
				#if	(UART0_DEFINE != 0)			
				IrqUart0En();						       		//开启uart0中断						        
				#endif	
				#if	(UART1_DEFINE != 0)			
				IrqUart1En();						       		//开启uart1中断						        
				#endif
				#if	(UART2_DEFINE != 0)
				IrqUart2En();						        //初始化UART2中断使能，根据具体使用UART模块来进行选择
				#endif
				TempPackVol += TempCellVol;
			}
		}

		if(!bBalancingFlg)
		{
			uiCellVmax = uiVadcVmax;
			uiCellVmin = uiVadcVmin;
			
			#if	(UART0_DEFINE != 0)	
			IrqUart0Dis();
			#endif
			#if	(UART1_DEFINE != 0)
			IrqUart1Dis();
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2Dis();
			#endif
			Info.ulVoltage = TempPackVol;           //Calculate the total voltage
			#if	(UART0_DEFINE != 0)			
			IrqUart0En();						       		//开启uart0中断						        
			#endif	
			#if	(UART1_DEFINE != 0)			
			IrqUart1En();						       		//开启uart1中断						        
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2En();						        //初始化UART2中断使能，根据具体使用UART模块来进行选择
			#endif
		}
	}
}


/*************************************************************************************************
* 函数名: CurTempOffset
* 参  数: 无
* 返回值: 无
* 描  述: 不同芯片温度下ADC的补偿值
*************************************************************************************************/
S16 code siCurTempOffset[2][13]=
{   /**0****1****2****3***4***5***6***7***8***9**10**11**12**/
    {-40, -30, -20, -10,  0, 10, 25, 35, 45, 55, 65, 75, 85},
    { -5,  -4,  -3,  -2, -1, -1,  0,  1,  1,  2,  3,  4,  5},
};

/*************************************************************************************************
* 函数名: OffsetCalculate()
* 参  数: 无
* 返回值: 无
* 描  述: 根据芯片内部温度实时调整0电流补偿值，以便消除温度对ADC采集产生的影响
*************************************************************************************************/
S16 OffsetCalculate(void)
{
    S16 xdata siCadcTempOffset=0;			//20220620
    U8 xdata i;
    
    for(i=0; i<12; i++)
    {
        if(Info.uiICTempe[0] <= (((S32)siCurTempOffset[0][i] + siCurTempOffset[0][i+1]) / 2 * 10 + 2731))
        {
            siCadcTempOffset = siCurTempOffset[1][i];
            break;
        }
    }
    return siCadcTempOffset;
}

/*************************************************************************************************
* 函数名: AfeCalcuCurr
* 参  数: 无
* 返回值: 无
* 描  述: 计算CADC采集的电流数据
*************************************************************************************************/
void AfeCalcuCurr(void)
{
	U8 i;
	S32 Tempdata=0;

	AFEReadReg(AFE_CURH, 2, (U8 xdata *)&AFE.siCurr);	//通过TWI读取CADC采集的电流值

	if((AFE.siCurr&0x1000) != 0)					//根据bit12判断是否为负数(放电电流为负值)，如为负值高位补0
	{
		AFE.siCurr|=0xE000;
	}
	slCadcCurrent = (S32)CALICUR*(AFE.siCurr-E2siCadcOffset+OffsetCalculate())/E2siCadcGain;

	slCadcCurBuf[ucCadcCnt] = slCadcCurrent;		//对连续采集的16次电流取平均值，作为当前电流值
	if(++ucCadcCnt >= 16)
	{
		ucCadcCnt = 0;
	}
	for(i=0; i<16; i++)
	{
		Tempdata += slCadcCurBuf[i];
	}
	slCadcCurAverage = Tempdata/16;
   
	bDSGING = 0;									//根据电流判定充放电状态
	bCHGING = 0;
	if(slCadcCurAverage < (-E2siDfilterCur))
	{
		if(++ucDsgingCheckCnt >= TIME_50MS_500MS)	//充放电状态检测延时10*50mS
		{
			ucDsgingCheckCnt = TIME_50MS_500MS;
			bDSGING = 1;
			#if	(UART0_DEFINE != 0)	
			IrqUart0Dis();
			#endif
			#if	(UART1_DEFINE != 0)
			IrqUart1Dis();
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2Dis();
			#endif
			Info.slCurr = slCadcCurAverage;
			#if	(UART0_DEFINE != 0)			
			IrqUart0En();						       		//开启uart0中断						        
			#endif	
			#if	(UART1_DEFINE != 0)			
			IrqUart1En();						       		//开启uart1中断						        
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2En();						        //初始化UART2中断使能，根据具体使用UART模块来进行选择
			#endif
		}
	}
	else if(slCadcCurAverage > E2siDfilterCur)
	{
		if(++ucChgingCheckCnt >= TIME_50MS_500MS)	//充放电状态检测延时10*50mS
		{
			ucChgingCheckCnt = TIME_50MS_500MS;
			bCHGING = 1;	 	
			McuPWM2Set(4000, 100);			
			#if	(UART0_DEFINE != 0)	
			IrqUart0Dis();
			#endif
			#if	(UART1_DEFINE != 0)
			IrqUart1Dis();
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2Dis();
			#endif
			Info.slCurr = slCadcCurAverage;
			#if	(UART0_DEFINE != 0)			
			IrqUart0En();						       		//开启uart0中断						        
			#endif	
			#if	(UART1_DEFINE != 0)			
			IrqUart1En();						       		//开启uart1中断						        
			#endif
			#if	(UART2_DEFINE != 0)
			IrqUart2En();						        //初始化UART2中断使能，根据具体使用UART模块来进行选择
			#endif
		}
	}
	else
	{
		#if	(UART0_DEFINE != 0)	
		IrqUart0Dis();
		#endif
		#if	(UART1_DEFINE != 0)
		IrqUart1Dis();
		#endif
		#if	(UART2_DEFINE != 0)
		IrqUart2Dis();
		#endif
		Info.slCurr = 0;
		#if	(UART0_DEFINE != 0)			
		IrqUart0En();						       		//开启uart0中断						        
		#endif	
		#if	(UART1_DEFINE != 0)			
		IrqUart1En();						       		//开启uart1中断						        
		#endif
		#if	(UART2_DEFINE != 0)
		IrqUart2En();						        //初始化UART2中断使能，根据具体使用UART模块来进行选择
		#endif
	}
}


/*************************************************************************************************
* 函数名: AFEInfoProcess
* 参  数: 无
* 返回值: 无
* 描  述: 每50mS读取AFE信息，并更新电压、电流、温度数据
*************************************************************************************************/
void AFEInfoProcess(void)
{
	AFERdFlg();
	
    bVADCFlg = 0;
    AfeCalcuVol();
    AfeCalcuTempe();

	if(bCADCFlg)				//当CADC转换完成后，才读取AFE电流信息并计算
	{
		bCADCFlg = 0;
		AfeCalcuCurr();
	}
}


