/******************************************************************************
 * @file      bmu_adbms1818.h
 * @brief     LT6820-ADBMS1818菊花链采集
 * @version   V1.0
 * @author    Gary 2024-11-13
 * @copyright    
 ******************************************************************************/
#include "bmu_adbms1818.h"

__attribute__((section(".ccmram"))) BmuItem bmu_data;

static uint8_t adapt_falg = 0;
//adapt ic number
void bmu_adapt_ic_num(void)
{
	uint8_t i = 0;
	for(i = 0;i < 10;i++)
	{
		run_command(1,BMU_MAX_NUM*BMU_MAX_IC_NUM);
	}

	for(i = 0;i < BMU_MAX_NUM*BMU_MAX_IC_NUM;i++)
	{
		if(bmu_data.ic[i].config.rx_pec_match == 1)
		{
			bmu_data.total_ic_adapt_num = i + 1;
			break;
		}
	}
	
	bmu_data.total_ic_num = bmu_data.total_ic_adapt_num;
}

//
void bmu_adapt_volt_temp(void)
{
	uint16_t icIdx = 0,_cellIdx = 0,_ntcIdx = 0,i = 0;
	if(bmu_data.cellntc_nomatch == 1 || adapt_falg == 1)
	{
		for(icIdx = 0;icIdx < BMU_MAX_IC_NUM * BMU_MAX_NUM;icIdx++)
		{
			for(i = 0;i < IC_MAX_CELL_NUM;i++)
			{
				if(bmu_data.ic[icIdx].cells.c_codes[i] / 10 < IC_CROSS_CELL_VOLT)
				{
					//This condition indicates a crossover point
				}
				else
				{
					bmu_data.cell_actual_pos[_cellIdx] = i;
					bmu_data.cell_actual_ic[_cellIdx] = icIdx;
					_cellIdx++;
				}
			}
		}

		bmu_data.total_cell_num = _cellIdx;

		//calc temp data
		for(icIdx = 0;icIdx < BMU_MAX_IC_NUM * BMU_MAX_NUM;icIdx++)
		{
			for(i = 0;i < IC_MAX_NTC_NUM;i++)
			{
				if(bmu_data.ic[icIdx].aux.a_codes[i] / 10 > IC_CROSS_TEMP_FLOAT)
				{
					//This condition indicates a crossover point
				}
				else
				{
					bmu_data.ntc_actual_pos[_ntcIdx] = i;
					bmu_data.ntc_actual_ic[_ntcIdx] = icIdx;
					_ntcIdx++;
				}
			}
		}

		bmu_data.total_temp_num = _ntcIdx;
	}
	
	//bmu_ic_num is must be config right
	bmu_data.bmu_ic_num = get_eeprom_data(kEep_AfeNum_CellNum, kEepromDataType_High);
	
	bmu_data.bmu_cell_num = bmu_data.total_cell_num / bmu_data.bmu_ic_num;
	bmu_data.bmu_temp_num = bmu_data.total_temp_num / bmu_data.bmu_ic_num;
}

void bmu_init_isoSpi(void)
{
	drv_spi_init(kSpiDev_1, kSpiFreq_Div256, kSpiMode_C1E1, SpiFrame_MSBFirst, kGpioType_SPI1_Clk, kGpioType_SPI1_Miso, kGpioType_SPI1_Mosi);
	ADBMS1818_init(bmu_data.bmu_num * bmu_data.bmu_ic_num, bmu_data.ic);
}



//初始化bmu
void bmu_config_init(void)
{
	uint8_t idx = 0;//,NtcNum = 0;
	uint16_t cell_num =0, temp_num = 0;
	
	drv_gpio_set_pin_status(kGpioType_SP1_Cs_En2, kGpioStatus_Low);
	//drv_gpio_set_pin_status(kGpioType_SP1_Cs_En1, kGpioStatus_Low);
	bmu_data.bmu_num = get_eeprom_data(kEep_DevAddr_SlaverNum, kEepromDataType_Low);
	//bmu_data.bmu_num = 1;
	if (bmu_data.bmu_num > BMU_MAX_NUM || bmu_data.bmu_num == 0)
	{
		bmu_data.bmu_num = BMU_MAX_NUM;
	}
	//NtcNum = get_eeprom_data(kEep_reserver_NtcNum, kEepromDataType_Low);
	bmu_data.bmu_ic_num = get_eeprom_data(kEep_AfeNum_CellNum, kEepromDataType_High);
	bmu_data.total_ic_num = bmu_data.bmu_num * bmu_data.bmu_ic_num;
	bmu_data.ic = bsp_adbms1818_global();
	bmu_data.total_cell_num = get_eeprom_data(kEep_CellNum, kEepromDataType_Full);
	bmu_data.total_temp_num = get_eeprom_data(kEep_TempNum, kEepromDataType_Full);
	
	//bmu_data.total_cell_num = 16;
	//bmu_data.total_temp_num = 8;
	
	//set num from hmi =>adapt num for furture
	cell_num = bmu_data.total_cell_num / bmu_data.bmu_num;
	temp_num = bmu_data.total_temp_num / bmu_data.bmu_num;

	bmu_data.bmu_cell_num = cell_num;
	bmu_data.bmu_temp_num = temp_num;

	uint8_t i = 0;
	cell_num =0, temp_num = 0;
	
	//统计ic中的电压和ntc对应的真实序号
	uint32_t cell_actual_pos[IC_MAX_CELL_NUM] = {0},ntc_actual_pos[IC_MAX_CELL_NUM] = {0},low_value = 0,high_value = 0,order = 0;
	for(idx = 0;idx < bmu_data.bmu_ic_num;idx++)
	{
		low_value = get_eeprom_data(kEep_FirstIAfe_CellPos + idx * 2, kEepromDataType_Full);
		high_value = get_eeprom_data(kEep_FirstIAfe_CellPos + idx * 2 + 1, kEepromDataType_Full);
		cell_actual_pos[idx] =  low_value + (high_value << 16);
		
		for(i = 0; i < IC_MAX_CELL_NUM;i++)
		{
			if(KIT_GET_BIT_VAL(cell_actual_pos[idx],i) == 1)
			{
				bmu_data.cell_actual_pos[order] = i;
				bmu_data.cell_actual_ic[order] = idx;
				order++;
			}
		}
		//cell num of crossover configuration >= The configured number of cell
			//then Based on the configured number of voltages.
		if(order > bmu_data.bmu_cell_num)
		{
			bmu_data.cellntc_nomatch = 1;
			break;
		}
	}
	
	order = 0; //@wkun 刚才发现order没有给默认值0，受到上面处理影响
	
	//统计ic中的电压和ntc对应的真实序号
	for(idx = 0;idx < bmu_data.bmu_ic_num;idx++)
	{
		//@wkun 此处注意是需要上位机下发配置，告诉bms哪个位置接了温感，刚才发现次数全是ff所以不影响结果，最好上位机需要设置下，
		low_value = get_eeprom_data(kEep_FirstIAfe_NtcPos + idx * 2, kEepromDataType_Full);
		high_value = get_eeprom_data(kEep_FirstIAfe_NtcPos + idx * 2 + 1, kEepromDataType_Full);   
		ntc_actual_pos[idx] =  low_value + (high_value << 16);
		
		for(i = 0; i < IC_MAX_NTC_NUM;i++)
		{
			if(KIT_GET_BIT_VAL(ntc_actual_pos[idx],i) == 1)
			{
				bmu_data.ntc_actual_pos[order] = i;
				bmu_data.ntc_actual_ic[order] = idx;
				order++;
			}
		}
		//ntc num of crossover configuration >= The configured number of ntc
			//then Based on the configured number of ntc.
		if(order > bmu_data.bmu_temp_num)
		{
			bmu_data.cellntc_nomatch = 1;
			break;
		}
	}
}

void bmu_unit_data_handler()
{
	uint8_t i = 0;
	uint16_t cell_pos = 0, temp_pos = 0;
	for (i = 0; i < bmu_data.bmu_num; i++)
	{
		BmuUnit* pBmu = NULL;
		pBmu = &bmu_data.bmu_unit[i];
		pBmu->ic_num = get_eeprom_data(kEep_AfeNum_CellNum, kEepromDataType_High);
		
		pBmu->data[kBmuData_CellNum] = bmu_data.bmu_cell_num;
		pBmu->data[kBmuData_TempNum] = bmu_data.bmu_temp_num;
			
		pBmu->cell_volt_buf = &bmu_data.cell_volt_total_buf[cell_pos];
		pBmu->cell_temp_buf = &bmu_data.cell_temp_total_buf[temp_pos];

		cell_pos += bmu_data.bmu_cell_num;
		temp_pos += bmu_data.bmu_temp_num;
	}

	bmu_data.pole_temp_buf = &bmu_data.cell_temp_total_buf[temp_pos];
}


void bmu_comm_offline_check(uint32_t base_time)
{
	uint8_t i = 0;uint16_t timeout = 0;
	for (i = 0; i < bmu_data.bmu_num; i++)
	{
		uint8_t *buf = bmu_data.ic[i].cells.pec_match;
		if(kit_check_sum8(buf, 6) == 0)
		{
			bmu_data.bmu_unit[i].comm_fault = 1;
			bmu_data.bmu_unit[i].timeout += base_time;
			KIT_SET_BIT_MASK_32(bmu_data.bmu_unit[i].data[kBmuData_Status], kBmuStatus_Online);
		}
		else
		{
			bmu_data.bmu_unit[i].comm_fault = 1;
			bmu_data.bmu_unit[i].timeout += base_time;
			
			timeout = get_eeprom_data(kEep_MSCommAlarm1Dly,kEepromDataType_Full);
			if(bmu_data.bmu_unit[i].timeout > timeout)
			{
				KIT_CLR_BIT_32(bmu_data.bmu_unit[i].data[kBmuData_Status], kBmuStatus_Online);
			}
		}
	}
}


void bmu_vlot_breakline_check()
{
	
	
}

static int tempJudge_cnt[26][9] = {0};
//static int tempCellErr_cnt = 0;
//@wkun the here can add temp line break or connect
void bmu_temp_breakline_check(int value, int bmuIdx, int tempIdx)
{
	//核心逻辑是通过每个bmu中的温度是否大于60000来确定温感排线是否有问题，通过for循环，然后将故障塞入kFaultCode_TempCable对应的故障中
	//bms_get_bmu_fault_bit(kBmuFaultBit_TempCable)，将这个接口中的数据，如果有则置1，否则为0
	if (value > 6000)
	{
		tempJudge_cnt[bmuIdx][tempIdx]++;
	}
	if(tempJudge_cnt[bmuIdx][tempIdx] > 1)
	{
		//bms_set_bmu_fault_bit(kBmuFaultBit_TempCable, 1);
	}
}


bool bmu_is_cell_volt_valid(uint16_t value)
{
    bool res = false;
	if ((value >= 1000) || (value <= 4000))
	{
		res = true;
	}
	return res;
}

static void bmu_statistic_cell_volt(uint16_t bmuIdx)
{    
    uint32_t i, sum_value = 0, valid_num = 0;
    uint16_t value, max_value = 0, min_value = 0xFFFF, max_idx = 0, min_idx = 0;
    for (i = 0; i < bmu_data.bmu_cell_num; i++) //最高、最低温度
    {        
        value = bmu_data.bmu_unit[bmuIdx].cell_volt_buf[i];
		
				//实时计算防止个别电芯真放空为0，或者充满
				if(value > 1000 && value < 4000)
				{
						sum_value += value;
						valid_num++;
        }
        if(max_value < value)
        {
            max_idx = i;
            max_value = value;
        }
        
        if(min_value > value)
        {
            min_idx = i;
            min_value = value;
        }
    }
	
		bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_TotalVolt] =  sum_value;
    
    if(valid_num > 0)
    {
        sum_value /= valid_num;
    } 
	
		bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_AvgVolt] = sum_value;
    bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MaxVolt] = max_value;
    bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MaxVoltIdx] = max_idx;
    bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MinVolt] = min_value;
    bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MinVoltIdx] = min_idx;
}

bool bmu_is_cell_temp_valid(uint16_t value)
{
    bool res = false;
	//if ((value >= 60000) || (value <= KIT_NTC_TEMP_OPEN_VALUE))
	if ((value <= 60000))  //大于60000，不参与故障统计
	{
		res = true;
	}
	return res;
}


static void bmu_statistic_cell_temp(uint16_t bmuIdx)
{     
	uint32_t i, sum_value = 0, valid_num = 0;
    uint16_t value, max_value = 0, min_value = 0xFFFF, max_idx = 0, min_idx = 0;

    for (i = 0; i < bmu_data.bmu_temp_num; i++) 
    {        
        value = bmu_data.bmu_unit[bmuIdx].cell_temp_buf[i];
        if (bmu_is_cell_temp_valid(value) == false)
        {            
            continue;
        }
        
        sum_value += value;
        valid_num++;
        if(max_value < value)
        {
            max_idx = i;
            max_value = value;
        }           
        if(min_value > value)
        {
            min_idx = i;
            min_value = value;
        }
    }    
	
	bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_TotalTemp] = sum_value;
	
    if(valid_num > 0)
    {
        sum_value /= valid_num;
    }   

    //bms_set_ex_data(kExType_CellTemp, ex_st);
    bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_AvgTemp] = sum_value;
    bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MaxTemp] = max_value;
    bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MaxTempIdx] = max_idx;
    bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MinTemp] = min_value;
    bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MinTempIdx] = min_idx;      
}


//real-time calc bmu data
void bmu_data_handler(uint32_t base_time)
{
	uint8_t bmuIdx = 0,cellIdx = 0,_cellIdx = 0,_bmuIdx = 0,_ntcIdx = 0;
	uint16_t current = 0,load = 0, tempJudge = 0;
	//calc cell volt
	for(bmuIdx = 0;bmuIdx < bmu_data.total_ic_num;bmuIdx++)
	{
		for(cellIdx = 0;cellIdx < bmu_data.bmu_cell_num;cellIdx++)
		{
			_cellIdx = bmu_data.cell_actual_pos[cellIdx];
			_bmuIdx  = bmu_data.cell_actual_ic[cellIdx];
			bmu_data.bmu_unit[bmuIdx].cell_volt_buf[cellIdx] = bmu_data.ic[bmuIdx].cells.c_codes[_cellIdx] / 10;
		}
		//统计电压
		bmu_statistic_cell_volt(bmuIdx);
	}
	
	//calc temp data
	for(bmuIdx = 0;bmuIdx < bmu_data.total_ic_num;bmuIdx++)
	{
		for(cellIdx = 0;cellIdx < bmu_data.bmu_temp_num;cellIdx++)
		{
			_ntcIdx = bmu_data.ntc_actual_pos[cellIdx]; //@wkun 此处还是全0，不对，继续排查
			_bmuIdx  = bmu_data.ntc_actual_ic[cellIdx];
			current = KIT_MAX((3000 - (bmu_data.ic[bmuIdx].aux.a_codes[_ntcIdx] / 10)),0) / 10; //ma
			if(KIT_ABS_DIFF(current,0) < 0.0001)
			{
				current = 1;
			}
			load = (bmu_data.ic[bmuIdx].aux.a_codes[_ntcIdx] / 10) * 1000 / current; //修订索引错误
			tempJudge = (bms_get_linear_temp(load, kNtcType_CWFH708_H713) - 500) / 10;
			bmu_data.bmu_unit[bmuIdx].cell_temp_buf[cellIdx] = tempJudge;
			bmu_temp_breakline_check(tempJudge, bmuIdx, _ntcIdx);
		}
		//统计温度
		bmu_statistic_cell_temp(bmuIdx);
	}
	//alarm monitor
	//bmu_comm_offline_check(base_time);
	bmu_vlot_breakline_check();

}



void bms_bmu_init()
{
	 bmu_config_init();
     bmu_init_isoSpi();
	 bmu_unit_data_handler();
	
	 //Automatic Recognition
	 if(adapt_falg == 1)
	 {
		 bmu_adapt_ic_num();
		 bmu_adapt_volt_temp();
		 bmu_unit_data_handler();
	 }
	 
}



void bms_poll_bmu(uint32_t base_time)
{
	//Automatic Recognition
	if(adapt_falg == 1)
	{
		bmu_adapt_ic_num();
		bmu_adapt_volt_temp();
		bmu_unit_data_handler();
	}
	run_command(3,bmu_data.bmu_num*bmu_data.bmu_ic_num);
	run_command(4,bmu_data.bmu_num*bmu_data.bmu_ic_num);
	bmu_data_handler(base_time);
	
	run_command(5,bmu_data.bmu_num*bmu_data.bmu_ic_num);
	run_command(6,bmu_data.bmu_num*bmu_data.bmu_ic_num);
	bmu_data_handler(base_time);
	
	//温感检测是否脱落，加上了防抖，需要两次大于6000，才设置温感排线错误，温感排线错误显示的有点慢
	//温感的值最开始全是大于6000的，第二次才是采集值
	//memset(tempJudge_cnt, 0, sizeof(tempJudge_cnt));
	//2-5 @wangk add this line bcu statistic data is show
//	bms_poll_statistic(0);
//	//2-6 @wangk
//	bms_poll_run_status(base_time); 
//	//2-10 @wangk 
//	task_dido_ctrl_handle(1000);
}



