#ifndef _FAULT_MANAGER_H_
#define _FAULT_MANAGER_H_

#ifdef __cplusplus
extern "C" {
#endif 

#include "kit_macro.h"
#include "run_status.h"

#define FAULT_PERIOD       			(100u)
#define FAULT_TICK_CONVERT(x)       ((x) / FAULT_PERIOD)
#define FAULT_RELAY_BOTH_OFF        (0x08u)


typedef enum
{
    kFaultData_SOC,       //0
    kFaultData_Current,
    kFaultData_Insulation,
    kFaultData_TotalVolt,
    kFaultData_MaxVolt,
    kFaultData_MinVolt,
    kFaultData_VoltDiff,
    kFaultData_MaxTemp,
    kFaultData_MinTemp,
    kFaultData_TempDiff,//9    
    kFaultData_VoltCable,  //10
    kFaultData_TempCable, //11
    kFaultData_MScomm, //主从通信
	
	kFaultData_T1Temp,
	kFaultData_T2Temp,	
	kFaultData_SupplyVolt,
	kFaultData_EnviTemp,
	kFaultData_TempRise,
    kFaultData_CmdHeart,
    kFaultData_HighVoltDiffer,
    kFaultData_MaxPoleTemp,
    kFaultData_MaxPackVolt,
    kFaultData_MinPackVolt,
    kFaultData_RlyFault, //0正常  1粘连 2开路
    kFaultData_End,
}FaultData;

typedef enum
{
    kFaultCode_Start = 0,
    kFaultCode_HighTotalVolt = kFaultCode_Start,      //总压过高
    kFaultCode_LowTotalVolt,      //总压过低
    kFaultCode_HighCellVolt,      //单体电压过高
    kFaultCode_LowCellVolt,       //单体电压过低
	kFaultCode_HighCellTemp,      //单体过温
    kFaultCode_LowCellTemp,       //单体低温
	kFaultCode_HighVoltDiff,      //压差高
    kFaultCode_HighTempDiff,      //温差高
    kFaultCode_HighCur,  	  	  //电流过大
    kFaultCode_HvDiffErr,         //高压异常 9
    
    kFaultCode_MSComm,      	  //主从通讯故障
	kFaultCode_VoltCable,	      //电压排线
    kFaultCode_TempCable,         //温度排线
    kFaultCode_HighSOC,           //SOC高
	kFaultCode_LowSOC,            //SOC低
    kFaultCode_LowISO,            //绝缘低
	
	kFaultCode_DoAdhesion,        //粘连
	kFaultCode_PreChg,      	  //预充失败 17
	
	kFaultCode_SupplyHighVolt,    //供电过高故障
	kFaultCode_SupplyLowVolt,     //供电过低故障
	kFaultCode_HighT1Temp,        //T1高温	
    kFaultCode_LowT1Temp,         //T1低温
	kFaultCode_HighT2Temp,        //T2高温	
    kFaultCode_LowT2Temp,         //T2低温
	kFaultCode_HighBalanceTemp,	  //均衡温度高
	kFaultCode_HighClusterCurDiff,//簇间电流差       ！！！
	kFaultCode_MSD,               //MSD故障
	kFaultCode_CurError,          //电流异常
	kFaultCode_HighPoleTemp,      //极柱过温
    kFaultCode_HighClusterTempDiff,//簇间温差 29     ！！！
	
	kFaultCode_ExterComm,         //外部通信故障     ！！！
	kFaultCode_PCSStatus,         //PCS状态  1通信+2故障
	kFaultCode_EMSStatus,         //EMS状态  1通信+2故障
	kFaultCode_FuseStatus,        //熔断器状态

	kFaultCode_AFE,         	  //模拟前端故障
    kFaultCode_Eeprom,      	  //EEPROM故障
	kFaultCode_Rtc,         	  //RTC故障
    kFaultCode_Adc,         	  //ADC故障
    kFaultCode_SD,          	  //SD故障
	kFaultCode_Feedback,    	  //反馈异常 检测DO与DI是否一致
	kFaultCode_HighTempRaise,     //温升过快
    kFaultCode_Exterme, 	      //极限故障
    kFaultCode_DoOpen,            //开路

    kFaultCode_Stop,    		  //急停 43
    kFaultCode_Fire,    		  //消防火警 1通信 2消防故障 3消防火灾或消防释放（喷洒）
    kFaultCode_CmdTimeout, 		  //控制指令超时
    kFaultCode_HighClusterVoltDiff,//簇间压差   ！！！
    kFaultCode_HeatOutOfCtrl,      //热失控
    
    kFaultCode_HighPackVolt,   //电池箱过压
    kFaultCode_LowPackVolt,   //电池箱欠压
    
    kFaultCode_Lightning,     //防雷器故障   1通信+2故障
    kFaultCode_AirCondition,  //空调故障     1通信+2故障
    kFaultCode_UPS,           //UPS故障 52   1通信+2故障
    
    kFaultCode_Water,   //水浸  1通信+2故障
    kFaultCode_Door,    //门禁  1通信+2故障
    kFaultCode_Gas,     //气体传感器  1通信+2故障
    
    kFaultCode_FireSpray,    	//消防喷洒        ！！！！
    kFaultCode_FireErr,    		//消防设备故障    ！！！！
    kFaultCode_SelfDefine3,
    kFaultCode_SelfDefine4,
    
    kFaultCode_End
}FaultCode;

typedef enum
{
    kExType_CellVolt = 0, //电压异常(可能排线脱落，也可能模拟前端异常) 或者充电单体下降
    kExType_CellTemp, //单体温度异常
    kExType_BalanceTemp,
    kExType_EEprom,   
    kExType_Afe,
    kExType_Adc,
    kExType_Shunt,
    kExType_Hall,
	kExType_TempRise,
    kExType_End,
}ExType;

typedef enum
{
    kExStatus_None = 0,
    kExStatus_Err,
    kExStatus_End,
}ExStatus;

typedef enum
{
    kCheckType_MoreThan = 0,
    kCheckType_LessThan,
    kCheckType_End,
}CheckType;

typedef enum
{
    kCondType_Alarm = 0,
    kCondType_Release,
}CondType;

typedef enum
{
	kFaultHandle_ForbidIdx = 0, //禁用
	kFaultHandle_AlarmIdx,		//报警
	kFaultHandle_CutRlyIdx,		//切断继电器
	kFaultHandle_CutNoRelIdx,	//切断继电器并重启释放
	kFaultHandleIdxEnd,
}FaultHandle;

//******报警级别******//
typedef enum
{
		kFaultLevel_Normal = 0,
		kFaultLevel_First,
    kFaultLevel_Second, 
    kFaultLevel_Third,
    kFaultLevel_End,
}FaultLevel;

typedef void (* FaultCall) (uint8_t level, uint16_t data, bool *cond, uint16_t *threshold);

typedef struct
{
    uint8_t   fauld_code;
    uint8_t   level;
    uint16_t  data_idx;
    uint16_t  threshold_idx;
    uint8_t   check_type; //Bit0-1两位为故障阈值检验类型 Bit3 为是否全断继电器
    FaultCall other_cond;
}FaultProp;

typedef struct
{
    uint16_t alarm_tick[3];
    uint16_t release_tick[3];
}FaultParam;

typedef struct
{
    uint16_t    fault_cnt;
    const FaultProp  *fault_prop_arr;
    FaultParam *fault_param_arr;
}FaultArray;


#define FAULT_STATIC_INIT(_name, _fault_prop)   \
    FaultParam _name##_fault_param[(sizeof(_fault_prop)/sizeof(FaultProp))]; \
    FaultArray _name =   \
    {   \
        (sizeof(_fault_prop)/sizeof(FaultProp)),    \
        (_fault_prop),   \
        _name##_fault_param,   \
    }   \

    
#define FAULT_STATIC_INIT_CCM(_name, _fault_prop)   \
    FaultParam _name##_fault_param[(sizeof(_fault_prop)/sizeof(FaultProp))]  __attribute__((section (".CCM_RAM"))); \
    FaultArray _name  __attribute__((section (".CCM_RAM"))) =   \
    {   \
        (sizeof(_fault_prop)/sizeof(FaultProp)),    \
        (_fault_prop),   \
        _name##_fault_param,   \
    }   \

bool bms_is_bsu_fault(void);
void bms_set_bsu_fault(bool is_fault);


void bms_update_fault_data(uint32_t base_time);
uint8_t bms_get_fault_cur_rate(RunStatus status); 
     
void bms_check_pwr_on_fault(uint32_t base_time);
void bms_check_chg_run_fault(RunStatus status, uint32_t base_time);
void bms_check_dis_run_fault(RunStatus status, uint32_t base_time);

void bms_clear_fault_code(RunStatus status);
uint16_t bms_get_fault_bit(uint8_t idx);
uint64_t bms_get_fault_relay_off_bit(void);
uint64_t bms_get_fault_relay_off_bit_by_status(RunStatus status);
    
FaultLevel bms_get_max_fault_level(void);
FaultLevel bms_get_min_fault_level(void);
FaultLevel bms_get_max_fault_level_by_status(RunStatus status);
    
FaultLevel bms_get_fault_level(FaultCode idx);
FaultLevel bms_get_fault_level_by_status(RunStatus status, FaultCode idx);
void bms_set_fault_level(FaultCode idx, FaultLevel level, FaultHandle handle);
void bms_set_fault_level_by_status(RunStatus status, FaultCode idx, FaultLevel level, FaultHandle handle);
uint16_t bms_get_fault_single_bit(uint8_t index, FaultLevel level);

ExStatus bms_get_ex_data(ExType idx);
void bms_set_ex_data(ExType idx, ExStatus st);

void bms_analyse_fault(RunStatus status, FaultArray *fault_array);
void bms_analyse_pwr_on_fault(RunStatus status, FaultArray *fault_array, uint32_t enable_bit);

void bms_clear_fault_relay_off_bit(FaultCode idx);
void bms_clear_fault_relay_off_bit_by_status(RunStatus status, FaultCode idx);

//总故障，总告警
uint32_t bms_get_total_alarm(uint16_t input);
uint32_t bms_get_total_fault(uint16_t input);

#ifdef __cplusplus
}
#endif

#endif
