#ifndef APP_RS485_1_H
#define APP_RS485_1_H

#define CONFIG_TX_BUFF_SIZE		256
#define CONFIG_RX_BUFF_SIZE		256
#define CONFIG_UART_GOOD		12
#define CONFIG_UART_PING		(CONFIG_UART_GOOD - 1)
#define CONFIG_UART_TIMEOUT		100
#define CONFIG_UART_POLL_DELAY	500

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)

#define BMS_POWER_FULL		(BMS_STA_D_OPEN | BMS_STA_C_OPEN)
#define BMS_POWER_SMALL		(BMS_STA_S_OPEN)
#define BMS_POWER_ALL		(BMS_POWER_FULL | BMS_POWER_SMALL)

/*******************************************通用帧头-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*********************************************************/

typedef enum {
	SHARK_BMS_VGS_ACC2 = 1 << 0,
	SHARK_BMS_VGS_FV = 1 << 1,
	SHARK_BMS_VGS_ALL = 0xFF
} shark_bms_vgs_t;

typedef enum {
	SHARK_BATT_POWER_FAULT,
	SHARK_BATT_POWER_ANY,
	SHARK_BATT_POWER_OFF,
	SHARK_BATT_POWER_SMALL,
	SHARK_BATT_POWER_FULL,
	SHARK_BATT_POWER_ALL,
} shark_battery_power_t;

typedef enum {
	SHARK_BATT_EXIT_SUCCESS,
	SHARK_BATT_EXIT_UPGRADE,
	SHARK_BATT_EXIT_POWER,
	SHARK_BATT_EXIT_SHAKE,
	SHARK_BATT_EXIT_ERROR,
	SHARK_BATT_EXIT_SOAK,
	SHARK_BATT_EXIT_485,
} shark_battery_exit_t;

typedef enum {
	SHARK_BATT_MASK_NONE = 0,
	SHARK_BATT_MASK_BAT1 = 1 << 0,
	SHARK_BATT_MASK_BAT2 = 1 << 1,
	SHARK_BATT_MASK_BOTH = SHARK_BATT_MASK_BAT1 | SHARK_BATT_MASK_BAT2
} shark_battery_mask_t;

typedef enum {
	SHARK_BATT_INFO_VERTION = 1 << 0,
	SHARK_BATT_INFO_TIMES = 1 << 1,
	SHARK_BATT_INFO_CELL_VOL = 1 << 2,
	SHARK_BATT_INFO_TEMP = 1 << 3,
} shark_battery_info_t;

#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 enum {
	SHARK_SEND_IDLE,
	SHARK_SEND_PENDING,
	SHARK_SEND_SUCCESS,
	SHARK_SEND_TIMEOUT,
} shark_send_state_t;

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;

	u32 uart;
	u8 address;
	u8 connected;
	u8 exit_times;
	shark_bool used;
	shark_send_state_t send_state;
	shark_battery_exit_t exit_code;

	u8 update_mask;
	u16 update_ticks;

	u8 rx_buff[CONFIG_RX_BUFF_SIZE];
	u8 tx_buff[CONFIG_TX_BUFF_SIZE];

	u16 rx_length;
	u16 tx_length;
	u16 tx_index;

	shark_bool rx_pending;
	shark_bool tx_pending;
	u8 rx_busy;
	u8 tx_busy;

	u8 define_error;
	u8 test_error;
}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;

#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

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

typedef struct
{
	uint32_t bms_err_timeout_cnt;
	uint16_t bms_err_cnt;
	uint16_t bms_err_num;
}BMS_ERROR;

#define TI_VALID_FLAG_KEY   (0x0327)
typedef struct
{
	uint16_t ti_flag;
	uint16_t ti_set;
	BMS_ERROR ti_bms_1;
	BMS_ERROR ti_bms_2;
	
}TEST_INFO;

extern TEST_INFO test_info;

int8_t Handle_RS485_1_Data(void);

int8_t Handle_RS485_2_Data(void);

void Sub_BMS_1_Initial(void);

shark_battery_exit_t Is_Sub_BMS_1_Normal(void);

shark_battery_exit_t Is_Sub_BMS_2_Normal(void);

void Initial_Test_Info(void);

void Save_Test_Info(void);

void Ca_Chu_Test_Info(void);

void Check_Enable_Test_Info(void);

shark_battery_exit_t shark_battery_is_normal(SUB_BMS_INFO *info, shark_battery_power_t power);
void shark_bms_set_vgs(shark_bms_vgs_t vgs, shark_bool enable);
void shark_bms_set_mos(shark_bool ss, shark_bool s11, shark_bool s21);
shark_battery_mask_t shark_battery_set_power(shark_battery_power_t power1, shark_battery_power_t power2, shark_battery_mask_t mask);
shark_battery_power_t shark_battery_get_power(SUB_BMS_INFO *info);
shark_bool shark_battery_check_power(SUB_BMS_INFO *info, shark_battery_power_t power);
shark_battery_mask_t shark_battery_detect(u8 times);
shark_bool shark_battery_ping(u8 times);
u32 shark_battery_get_voltage(SUB_BMS_INFO *info);
u32 shark_battery_get_voltage_delta(void);
u32 shark_battery_get_voltage_min(void);
u32 shark_battery_get_voltage_max(void);
void shark_battery_clear(SUB_BMS_INFO *info);
shark_bool shark_battery_process(SUB_BMS_INFO *info, const u8 *buff, u8 length);
shark_bool shark_battery_send_command(SUB_BMS_INFO *info);

static inline void shark_bms_set_mos_close(void)
{
	shark_bms_set_mos(shark_false, shark_false, shark_false);
}

static inline void shark_bms_set_mos_bat1(void)
{
	shark_bms_set_mos(shark_false, shark_false, shark_true);
}

static inline void shark_bms_set_mos_bat2(void)
{
	shark_bms_set_mos(shark_false, shark_true, shark_false);
}

static inline void shark_bms_set_mos_series(void)
{
	shark_bms_set_mos(shark_true, shark_false, shark_false);
}

static inline void shark_bms_set_mos_parrallel(void)
{
	shark_bms_set_mos(shark_false, shark_true, shark_true);
}

static inline shark_battery_exit_t shark_battery_is_normal_power_on(SUB_BMS_INFO *info)
{
	return shark_battery_is_normal(info, SHARK_BATT_POWER_FULL);
}

static inline u32 shark_battery_get_voltage1(void)
{
	return shark_battery_get_voltage(&sub_bms_info_1);
}

static inline u32 shark_battery_get_voltage2(void)
{
	return shark_battery_get_voltage(&sub_bms_info_2);
}

static inline u8 shark_battery_get_capacity(SUB_BMS_INFO *info)
{
	return info->packet_common.m_percent;
}

static inline u8 shark_battery_get_capacity1(void)
{
	return shark_battery_get_capacity(&sub_bms_info_1);
}

static inline u8 shark_battery_get_capacity2(void)
{
	return shark_battery_get_capacity(&sub_bms_info_2);
}

static inline s32 shark_battery_get_current(SUB_BMS_INFO *info)
{
	return info->packet_common.m_current;
}

static inline s32 shark_battery_get_current1(void)
{
	return shark_battery_get_current(&sub_bms_info_1);
}

static inline s32 shark_battery_get_current2(void)
{
	return shark_battery_get_current(&sub_bms_info_2);
}

static inline s32 shark_battery_get_current12(void)
{
	return shark_battery_get_current1() + shark_battery_get_current2();
}

static inline shark_bool shark_battery_charge_complete(SUB_BMS_INFO *info)
{
	return (info->packet_common.bms_status & BMS_STA_C_FULL) != 0;
}

static inline shark_bool shark_battery_charge_complete1(void)
{
	return shark_battery_charge_complete(&sub_bms_info_1);
}

static inline shark_bool shark_battery_charge_complete2(void)
{
	return shark_battery_charge_complete(&sub_bms_info_2);
}

static inline shark_bool shark_battery_charge_in(SUB_BMS_INFO *info)
{
	return info->packet_common.charge_flag != 0;
}

static inline shark_bool shark_battery_charge_in1(void)
{
	return shark_battery_charge_in(&sub_bms_info_1);
}

static inline shark_bool shark_battery_charge_in2(void)
{
	return shark_battery_charge_in(&sub_bms_info_2);
}

static inline shark_bool shark_battery_send_pending(SUB_BMS_INFO *info)
{
	return info->send_state == SHARK_SEND_PENDING;
}

static inline shark_bool shark_battery_send_success(SUB_BMS_INFO *info)
{
	return info->send_state == SHARK_SEND_SUCCESS;
}

static inline u8 shark_battery_get_rs485_state(SUB_BMS_INFO *info)
{
	return info->connected ? 3 : 2;
}

static inline shark_bool shark_battery_is_discharge(SUB_BMS_INFO *info)
{
	return (info->packet_common.work_status & ST_DISCHRG_CUR) != 0;
}

static inline shark_bool shark_battery_is_discharge1(void)
{
	return shark_battery_is_discharge(&sub_bms_info_1);
}

static inline shark_bool shark_battery_is_discharge2(void)
{
	return shark_battery_is_discharge(&sub_bms_info_2);
}

#endif

