#ifndef APP_RS485_1_H
#define APP_RS485_1_H

enum
{
	OP_NONE,
	OP_BOND,
	OP_WRITE_SN,
	OP_PAIR,
	OP_UPDATE_PAIR,
	OP_READ_INFO,
	OP_ALARM_TIMES,
	OP_CELL_VOL,//0x07
	OP_TEMP_OTHER,//0x08
	
	OP_OPEN_FET = 0x0B,

	OP_CLEAR_PAIR = OP_TEMP_OTHER + 1,
	OP_UPDATE_SOFTWARE_REQ = 0x0E,
	OP_UPDATE_SOFTWARE = 0x0F,
	OP_MAX
};

typedef struct
{	
	uint8_t operate;
	uint8_t op_result;
	uint16_t resver;
	uint32_t param;
}SUB_BMS_CMD;


#define RS485_COM_TIMEOUT     (150)
#define RS485_COM_ERROR     (3)
#define RS485_COM_UPDATE_TIMEOUT     (1500)
/*******************************************通用帧头-start*********************************************************/
#pragma  pack (push,1)  
typedef struct
{
//整个包大小
	uint8_t size;
//命令设备
	uint8_t type;
//协议类型
	uint8_t protocol;
//命令类型
	uint8_t cmd;
//命令校验
	uint16_t checksum;
//命令处理调用
	uint8_t dir;
//命令返回状态
	uint8_t bStatus;
//命令数据部分	
}COMMAND_BODY;
#pragma pack(pop)

//
#define BMS_STA_BOND       (0x01)
#define BMS_STA_D_OPEN     (0x02)
#define BMS_STA_C_OPEN     (0x04)
#define BMS_STA_S_OPEN     (0x08)
#define BMS_STA_C_FULL     (0x10)
#define BMS_STA_S_BAHU     (0x20)
#define BMS_STA_JIAO_YAN   (0x40)
/*******************************************通用帧头-end*********************************************************/

/*******************************************BMS帧头-start*********************************************************/
#define SBU_BMS_ADDRESS               (0x30)
#define SUB_BMS_ADDRESS_0             (SBU_BMS_ADDRESS)
#define SUB_BMS_ADDRESS_1             (SBU_BMS_ADDRESS + 1)
#define SUB_BMS_ADDRESS_2             (SBU_BMS_ADDRESS + 1)

#define BMS_DIR                              (0x16)
#define SET_COMMAND                          (0x10)
#define GET_COMMAND                          (0x20)
#define ACK_COMMAND                          (0x30)
#define ENG_COMMAND                          (0x40)

/*******************************************BMS帧头-end*********************************************************/
#pragma  pack (push,1)  
typedef struct
{
	uint8_t yjkxslc;
	uint8_t m_percent;
	uint8_t yjcdwcsj;
	uint8_t charge_flag;
	
	int32_t m_current;
	
	uint32_t m_total_vol;
	
	uint8_t bms_temp;
	uint16_t work_status;
	uint32_t banlance_cell;

	uint8_t bms_status;
	
	uint8_t operate_result;
}PACKET_COMMON;

#define SERIAL_NUM_SIZE                      18
#define SOFTWARE_SIZE                        20
typedef struct
{
	uint8_t sn[SERIAL_NUM_SIZE];
	uint8_t soft_ver[SOFTWARE_SIZE];
	
}BATTERY_DEV_INFO;

typedef struct
{
	uint16_t dcsmxs;
	uint32_t charge_times;
	uint32_t charge_over_vol_times;
	uint32_t discharge_under_vol_times;
	uint32_t charge_over_cur_times;
	uint32_t discharge_under_cur_times;
	uint32_t short_times;
	uint32_t charge_under_temp_times;
	uint32_t discharge_under_temp_times;
	uint32_t charge_over_temp_times;
	uint32_t discharge_over_temp_times;
}BATTERY_TIMES;

#define CELL_NUM_MAX	   (15u)  
typedef struct
{
	uint8_t cv_cell_num;
	uint16_t cv_cell_vol[CELL_NUM_MAX];
}CELL_VOL;

#define THERMISTOR_NUM_MAX				(4u)
typedef struct
{
	int8_t to_temp_num[THERMISTOR_NUM_MAX];
	uint8_t to_fet;
}TEMP_OTHER;
#pragma pack(pop)

typedef struct
{
	PACKET_COMMON packet_common;
	BATTERY_DEV_INFO bat_dev_info;
	BATTERY_TIMES bat_times;
	CELL_VOL cell_vol;
	TEMP_OTHER temp_other;
	SUB_BMS_CMD sub_bms_cmd;
	
	uint8_t rs485_connect;
	uint8_t rs485_time_out;
}SUB_BMS_INFO;

extern SUB_BMS_INFO sub_bms_info_1;
extern SUB_BMS_INFO sub_bms_info_2;


typedef struct
{
	uint8_t set;
	uint16_t count;

	uint8_t com_err_flag;
	uint32_t com_err_count;
}SUB_BMS_COM;
extern SUB_BMS_COM sub_rs485_time_out_1;
extern SUB_BMS_COM sub_rs485_time_out_2;

extern uint8_t RS485_busy_1;
extern uint8_t RS485_busy_2;

#if 0
_inline void Sub_BMS_1_RS485_Com_Time_Out(void)
{
	if(sub_rs485_time_out_1.set)
	{
		if(++sub_rs485_time_out_1.count >= RS485_COM_TIMEOUT)
		{
			
			RS485_busy_1 = 0;
			sub_rs485_time_out_1.set = 0;
			sub_rs485_time_out_1.count = 0;
			if(sub_rs485_time_out_1.com_err_flag == 0)
			{
				sub_rs485_time_out_1.com_err_flag = 1;
				sub_rs485_time_out_1.com_err_count = 1;
			}
			else
			{
				if(++sub_rs485_time_out_1.com_err_count >= 5)
				{
					sub_rs485_time_out_1.com_err_count = 0;
					g_event |= SUB_BMS_1_RS485_DISC_EVENT;
				}
			}
		}
	}
}

__inline void Sub_BMS_2_RS485_Com_Time_Out(void)
{
	if(sub_rs485_time_out_2.set)
	{
		if(++sub_rs485_time_out_2.count >= RS485_COM_TIMEOUT)
		{
			
			RS485_busy_2 = 0;
			sub_rs485_time_out_2.set = 0;
			sub_rs485_time_out_2.count = 0;
			if(sub_rs485_time_out_2.com_err_flag == 0)
			{
				sub_rs485_time_out_2.com_err_flag = 1;
				sub_rs485_time_out_2.com_err_count = 1;
			}
			else
			{
				if(++sub_rs485_time_out_2.com_err_count >= 5)
				{
					sub_rs485_time_out_2.com_err_count = 0;
					g_event |= SUB_BMS_2_RS485_DISC_EVENT;
				}
			}
		}
	}
}
#endif

extern DELAY_COMMON send_delay;
__inline void Send_Sub_BMS_CMD_Delay(void)
{
	if(send_delay.set)
	{
		++send_delay.count;
		if(send_delay.count >= 400)
		{
			send_delay.count = 0;
			g_event |= SUB_BMS_2_SEND_CMD_EVENT;
		}
		else if(send_delay.count == 200)
		{
			g_event |= SUB_BMS_1_SEND_CMD_EVENT;
		}
	}
}


extern uint8_t sub_bms_1_connect;
extern uint8_t sub_bms_2_connect;

enum
{
	SUB_BMS_INVALID_STATUS,
	SUB_BMS_DISC_NO485,
	SUB_BMS_DISC_HV485,
	SUB_BMS_CONT_HV485,
	SUB_BMS_CONT_NO485,
};
extern uint8_t sub_bms_1_lt_state;
extern uint8_t sub_bms_2_lt_state;

enum
{
	CW_NONE,
	CW_CHONG_DIAN_ZUO,
	CW_CHE_SHANG_CHARGER,
	CW_CHE_SHANG_NO_CHARGER,
	
	CW_MAX
};
extern uint8_t cang_wei;

extern uint16_t bms_1_work_status ;
extern uint16_t bms_2_work_status ;
extern uint8_t bms_1_test_define_error;
extern uint8_t bms_2_test_define_error;

void Check_Sub_BMS_1(void);

void Check_Sub_BMS_2(void);

int8_t Handle_RS485_1_Data(void);

int8_t Handle_RS485_2_Data(void);

void RS485_Communication_Time_Out_1(void);

void RS485_Communication_Time_Out_2(void);

void Send_Sub_BMS_1_CMD(void);

void Send_Sub_BMS_2_CMD(void);

void Sub_BMS_1_Initial(void);

void Sub_BMS_2_Initial(void);

void  Sub_BMS_1_lt_State(void);

void  Sub_BMS_2_lt_State(void);

uint8_t Is_Sub_BMS_1_Normal(void);

uint8_t Is_Sub_BMS_2_Normal(void);

int8_t Operate_Sub_BMS_1_CD(uint8_t on);

int8_t Operate_Sub_BMS_2_CD(uint8_t on);

uint8_t Sub_BMS_1_COM_Finish(void);

uint8_t Sub_BMS_2_COM_Finish(void);

uint8_t SUB_BMS_1_DEC(void);

uint8_t SUB_BMS_2_DEC(void);

int8_t Update_Sub_BMS_1_Software(uint8_t step);

int8_t Update_Sub_BMS_2_Software(uint8_t step);

extern void RS485_Print(uint8_t dest,uint8_t * dbuf,uint16_t dbuf_len);

#endif

