/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ /* * High Level description: * http://www.ti.com/lit/ds/symlink/bq28400.pdf * Thechnical Reference: * http://www.ti.com/lit/ug/sluu431/sluu431.pdf */ #include "includes.h" #include "dflash_sf1.h" #include "device_param.h" #include "asutil.h" #include "console.h" #include "PL455_comm.h" #include "temp.h" #include "vi.h" #define SLEEP_VOLTAGE 4200 #define WAKEUP_VOLTAGE 4500 #define SLEEP_MODE_TIME 60 * 1000 #define CELL_DEVIATION_CHECK_VOLTAGE 4500 #define OCC_CRITICAL_CLEAR_TIME 60 * 1000 #define PRECHARGE_TIME_DEFAULT 2 * 1000 #define CV_DIFF_PROTECT_HOLD_TIME (24UL * 60UL * 60UL * 1000UL) // 24 hours in ms #define TEMP_DIFF_PROTECT_THRESHOLD 30 // 3.0C (0.1C unit) #define TEMP_DIFF_PROTECT_HOLD_TIME (24UL * 60UL * 60UL * 1000UL) // 24 hours in ms u8 SleepMode = false; u32 smode_tick = 60 * 1000; u32 PreChargeTime = PRECHARGE_TIME_DEFAULT; u32 OCCTime = 0; u32 OCDTime = 0; u32 CV_Diff_ProtectTime = CV_DIFF_PROTECT_HOLD_TIME; u32 CV_Diff_ProtectHoldTime = CV_DIFF_PROTECT_HOLD_TIME; // Default: 24 hours (configurable in RAM) u32 Temp_Diff_ProtectTime = TEMP_DIFF_PROTECT_HOLD_TIME; u32 Temp_Diff_ProtectHoldTime = TEMP_DIFF_PROTECT_HOLD_TIME; u16 Temp_Diff_Threshold = TEMP_DIFF_PROTECT_THRESHOLD; // Default: 30 (3.0 deg C) s32 OCC_Occur_Current; s32 OCD_Occur_Current; u32 OCC_CRITICAL_Tick = 60 * 1000; u8 OCC_Fail_Count = 0; u8 OCC_3Times_Fail = false; void dec_precharge_time(u32 tick); void dec_occ_time(u32 tick); void dec_occ_critical_time(u32 tick); void dec_ocd_time(u32 tick); void dec_sleepmode_time(u32 tick); void dec_cv_diff_time(u32 tick); void dec_temp_diff_time(u32 tick); void ProcessSafety_COV(void); void ProcessSafety_CUV(void); void ProcessSafety_OTA(void); void ProcessSafety_LTA(void); void ProcessSafety_OCC(void); void ProcessSafety_OCD(void); void ProcessSafety_SOC(void); void ProcessSafety_CellVoltageDiff(void); void ProcessSafety_TempDiff(void); void Process_FetControl(void); void ProcessStatusCheck(void); void ClearODCTick(void) { OCDTime = device_param.safety.current.OC_Dsg_Rec_Time * 1000; } void dec_alarm_tick(u32 tick) { dec_precharge_time(tick); dec_occ_time(tick); dec_occ_critical_time(tick); dec_ocd_time(tick); dec_cv_diff_time(tick); dec_temp_diff_time(tick); dec_sleepmode_time(tick); } void dec_sleepmode_time(u32 tick) { if (smode_tick > 0) { if (smode_tick > tick) smode_tick -= tick; else smode_tick = 0; } } u8 GetSleepMode(void) { return SleepMode; } void SetSleepMode(u8 mode) { SleepMode = mode; } void CheckSleepMode(void) { if (SleepMode == true) { if (device_status.op_status == 1) { SleepMode = false; smode_tick = SLEEP_MODE_TIME; } } else { if ((device_status.protection.bit.cell_under_voltage) || (device_status.protection.bit.under_voltage)) { if (smode_tick == 0) SleepMode = true; } else { smode_tick = SLEEP_MODE_TIME; } } } void ProcessAlarm(void) { if (device_status.battery_status.bit.INIT) { device_status.protection.bit.afe_fail = device_status.battery_status.bit.AFE | device_status.error.bit.afe_fail; if (device_status.battery_status.bit.AFE == false) { ProcessSafety_COV(); ProcessSafety_CUV(); } ProcessSafety_OTA(); ProcessSafety_LTA(); ProcessSafety_OCC(); ProcessSafety_OCD(); ProcessSafety_SOC(); ProcessSafety_CellVoltageDiff(); ProcessSafety_TempDiff(); Process_FetControl(); CheckSleepMode(); } ProcessStatusCheck(); } void dec_precharge_time(u32 tick) { if (PreChargeTime > 0) { if (PreChargeTime > tick) PreChargeTime -= tick; else PreChargeTime = 0; } } void ProcessSafety_COV(void) { /* Cell Over Voltage Check */ for (int i = 0; i < DEVICE_MAX_CELL; i++) { /* Cell Over Voltage Protection */ if (device_status.cov_protection_cell.uValue & BIT(i)) { // Release check if (device_value.Cell.voltage[i] < device_param.safety.voltage.COV_Recovery) device_status.cov_protection_cell.uValue &= ~BIT(i); } else { // Alarm check if (device_value.Cell.voltage[i] > device_param.safety.voltage.COV_Threshold) device_status.cov_protection_cell.uValue |= BIT(i); } /* Cell Over Voltage Warning */ if (device_status.cov_warning_cell.uValue & BIT(i)) { // Release check if (device_value.Cell.voltage[i] < device_param.safety.voltage.COV_Recovery) device_status.cov_warning_cell.uValue &= ~BIT(i); } else { // Alarm check if (device_value.Cell.voltage[i] > device_param.safety.voltage.COV_Warning) device_status.cov_warning_cell.uValue |= BIT(i); } } if (device_status.cov_protection_cell.uValue != 0) device_status.protection.bit.cell_over_voltage = true; else device_status.protection.bit.cell_over_voltage = false; if (device_status.cov_warning_cell.uValue != 0) device_status.warning.bit.cell_over_voltage = true; else device_status.warning.bit.cell_over_voltage = false; /* System Over charge protection */ if (device_status.protection.bit.over_voltage) { // Release check if (device_value.BatVoltage < device_param.safety.voltage.SOV_Recovery) device_status.protection.bit.over_voltage = false; } else { // Alarm check if (device_value.BatVoltage > device_param.safety.voltage.SOV_Threshold) device_status.protection.bit.over_voltage = true; } /* System Over Voltage Warning */ if (device_status.warning.bit.over_voltage) { // Release check if (device_value.BatVoltage < device_param.safety.voltage.SOV_Recovery) device_status.warning.bit.over_voltage = false; } else { // Alarm check if (device_value.BatVoltage > device_param.safety.voltage.SOV_Warning) device_status.warning.bit.over_voltage = true; } } void ProcessSafety_CUV(void) { /* Cell under voltage check */ for (int i = 0; i < DEVICE_MAX_CELL; i++) { /* Cell under voltage protection */ if (device_status.cuv_protection_cell.uValue & BIT(i)) { // Recovery Check if (device_value.Cell.voltage[i] > device_param.safety.voltage.CUV_Recovery) device_status.cuv_protection_cell.uValue &= ~BIT(i); } else { // Protection Check if (device_value.Cell.voltage[i] < device_param.safety.voltage.CUV_Threshold) device_status.cuv_protection_cell.uValue |= BIT(i); } /* Cell under voltage warning */ if (device_status.cuv_warning_cell.uValue & BIT(i)) { // Recovery Check if (device_value.Cell.voltage[i] > device_param.safety.voltage.CUV_Recovery) device_status.cuv_warning_cell.uValue &= ~BIT(i); } else { // Warning Check if (device_value.Cell.voltage[i] < device_param.safety.voltage.CUV_Warning) device_status.cuv_warning_cell.uValue |= BIT(i); } } if (device_status.cuv_protection_cell.uValue != 0) device_status.protection.bit.cell_under_voltage = true; else device_status.protection.bit.cell_under_voltage = false; if (device_status.cuv_warning_cell.uValue != 0) device_status.warning.bit.cell_under_voltage = true; else device_status.warning.bit.cell_under_voltage = false; /* Cell Voltage Fault Check (Below 1000mV or above 4500mV abnormal voltage cutoff charging) */ uint8_t cell_fault = false; for (int i = 0; i < DEVICE_MAX_CELL; i++) { if ((device_value.Cell.voltage[i] <= 1000) || (device_value.Cell.voltage[i] >= 4500)) { cell_fault = true; break; } } if (cell_fault) { device_status.error.bit.afe_fail = true; device_status.protection.bit.afe_fail = true; } else { device_status.error.bit.afe_fail = false; } /* System under voltage protection */ if (device_status.protection.bit.under_voltage) { // Release check if (device_value.BatVoltage > device_param.safety.voltage.SUV_Recovery) device_status.protection.bit.under_voltage = false; } else { // Alarm check if (device_value.BatVoltage < device_param.safety.voltage.SUV_Threshold) device_status.protection.bit.under_voltage = true; } /* System under voltage warning */ if (device_status.warning.bit.under_voltage) { // Release check if (device_value.BatVoltage > device_param.safety.voltage.SUV_Recovery) device_status.warning.bit.under_voltage = false; } else { // Alarm check if (device_value.BatVoltage < device_param.safety.voltage.SUV_Warning) device_status.warning.bit.under_voltage = true; } if (device_status.protection.bit.under_voltage) { if (device_status.op_status == 0x0001) { device_status.protection.bit.under_voltage = 0; } } } void ProcessSafety_OTA(void) { /* Temperature Sensor Fault Check */ if (IsTempSensorFailed()) { device_status.error.bit.temp_sensor = true; } else { device_status.error.bit.temp_sensor = false; } /* Charge High Temperature */ for (int i = 0; i < DEVICE_MAX_TEMP; i++) { if (ADState(i) != AD_FAIL) { s16 aTemp = device_value.Temp.temperature[i]; /* Over Temperature Charge Protection */ if (device_status.otc_protection_temp.uValue & BIT(i)) { // Recovery Check if (aTemp < device_param.safety.temperature.OT_Chg_Recovery) device_status.otc_protection_temp.uValue &= ~BIT(i); } else { // Protection Check, when charging if (device_status.battery_status.bit.MD == 0) { if (aTemp > device_param.safety.temperature.OT_Chg_Threshold) device_status.otc_protection_temp.uValue |= BIT(i); } } /* Over Temperature Charge Warning */ if (device_status.otc_warning_temp.uValue & BIT(i)) { // Recovery Check if (aTemp < device_param.safety.temperature.OT_Chg_Recovery) device_status.otc_warning_temp.uValue &= ~BIT(i); } else { // Warning Check, when charging if (device_status.battery_status.bit.MD == 0) { if (aTemp > device_param.safety.temperature.OT_Chg_Warning) device_status.otc_warning_temp.uValue |= BIT(i); } } } } /* OTC Protection */ if (device_status.otc_protection_temp.uValue != 0) device_status.protection.bit.chg_high_temp = true; else device_status.protection.bit.chg_high_temp = false; /* OTC Warning */ if (device_status.otc_warning_temp.uValue != 0) device_status.warning.bit.chg_high_temp = true; else device_status.warning.bit.chg_high_temp = false; /* High Temperature Discharge */ for (int i = 0; i < DEVICE_MAX_TEMP; i++) { if (ADState(i) != AD_FAIL) { s16 aTemp = device_value.Temp.temperature[i]; /* Over Temperature Discharge Protection */ if (device_status.otd_protection_temp.uValue & BIT(i)) { // Recovery Check if (aTemp < device_param.safety.temperature.OT_Dsg_Recovery) device_status.otd_protection_temp.uValue &= ~BIT(i); } else { // Protection Check, when charging if (device_status.battery_status.bit.MD == 1) { if (aTemp > device_param.safety.temperature.OT_Dsg_Threshold) device_status.otd_protection_temp.uValue |= BIT(i); } } /* Over Temperature Charge Warning */ if (device_status.otd_warning_temp.uValue & BIT(i)) { // Recovery Check if (aTemp < device_param.safety.temperature.OT_Dsg_Recovery) device_status.otd_warning_temp.uValue &= ~BIT(i); } else { // Warning Check, when charging if (device_status.battery_status.bit.MD == 1) { if (aTemp > device_param.safety.temperature.OT_Dsg_Warning) device_status.otd_warning_temp.uValue |= BIT(i); } } } } /* OTD Protection */ if (device_status.otd_protection_temp.uValue != 0) device_status.protection.bit.dsg_high_temp = true; else device_status.protection.bit.dsg_high_temp = false; /* OTD Warning */ if (device_status.otd_warning_temp.uValue != 0) device_status.warning.bit.dsg_high_temp = true; else device_status.warning.bit.dsg_high_temp = false; } void ProcessSafety_LTA(void) { /* Charge Low Temperature */ for (int i = 0; i < DEVICE_MAX_TEMP; i++) { if (ADState(i) != AD_FAIL) { s16 aTemp = device_value.Temp.temperature[i]; /* Over Temperature Charge Protection */ if (device_status.ltc_protection_temp.uValue & BIT(i)) { // Recovery Check if (aTemp > device_param.safety.temperature.LT_Chg_Recovery) device_status.ltc_protection_temp.uValue &= ~BIT(i); } else { // Protection Check, when charging if (device_status.battery_status.bit.MD == 0) { if (aTemp < device_param.safety.temperature.LT_Chg_Threshold) device_status.ltc_protection_temp.uValue |= BIT(i); } } /* Low Temperature Charge Warning */ if (device_status.ltc_warning_temp.uValue & BIT(i)) { // Recovery Check if (aTemp > device_param.safety.temperature.LT_Chg_Recovery) device_status.ltc_warning_temp.uValue &= ~BIT(i); } else { // Warning Check, when charging if (device_status.battery_status.bit.MD == 0) { if (aTemp < device_param.safety.temperature.LT_Chg_Warning) device_status.ltc_warning_temp.uValue |= BIT(i); } } } } /* LTC Protection */ if (device_status.ltc_protection_temp.uValue != 0) device_status.protection.bit.chg_low_temp = true; else device_status.protection.bit.chg_low_temp = false; /* LTC Warning */ if (device_status.ltc_warning_temp.uValue != 0) device_status.warning.bit.chg_low_temp = true; else device_status.warning.bit.chg_low_temp = false; /* Low Temperature Discharge */ for (int i = 0; i < DEVICE_MAX_TEMP; i++) { if (ADState(i) != AD_FAIL) { s16 aTemp = device_value.Temp.temperature[i]; /* Low Temperature Discharge Protection */ if (device_status.ltd_protection_temp.uValue & BIT(i)) { // Recovery Check if (aTemp > device_param.safety.temperature.LT_Dsg_Recovery) device_status.ltd_protection_temp.uValue &= ~BIT(i); } else { // Protection Check, when charging if (device_status.battery_status.bit.MD == 1) { if (aTemp < device_param.safety.temperature.LT_Dsg_Threshold) device_status.ltd_protection_temp.uValue |= BIT(i); } } /* Over Temperature Charge Warning */ if (device_status.ltd_warning_temp.uValue & BIT(i)) { // Recovery Check if (aTemp > device_param.safety.temperature.LT_Dsg_Recovery) device_status.ltd_warning_temp.uValue &= ~BIT(i); } else { // Warning Check, when charging if (device_status.battery_status.bit.MD == 1) { if (aTemp < device_param.safety.temperature.LT_Dsg_Warning) device_status.ltd_warning_temp.uValue |= BIT(i); } } } } /* LTD Protection */ if (device_status.ltd_protection_temp.uValue != 0) device_status.protection.bit.dsg_low_temp = true; else device_status.protection.bit.dsg_low_temp = false; /* LTD Warning */ if (device_status.ltd_warning_temp.uValue != 0) device_status.warning.bit.dsg_low_temp = true; else device_status.warning.bit.dsg_low_temp = false; } void dec_occ_time(u32 tick) { if (OCCTime > 0) { if (OCCTime > tick) OCCTime -= tick; else OCCTime = 0; } } void dec_occ_critical_time(u32 tick) { if (OCC_CRITICAL_Tick > 0) { if (OCC_CRITICAL_Tick > tick) OCC_CRITICAL_Tick -= tick; else OCC_CRITICAL_Tick = 0; } } void ProcessSafety_OCC(void) { /* Over charge current protection */ if (device_status.protection.bit.chg_over_current) { // release check: DO NOT auto-recover if repeated OCC fail occurred (Latched) if (OCC_3Times_Fail) { device_status.protection.bit.chg_over_current = true; } else { if ((device_value.Current / 1) < (device_param.safety.current.OC_Chg_Recovery * 10)) { if (OCCTime == 0) device_status.protection.bit.chg_over_current = false; } else { OCCTime = device_param.safety.current.OC_Chg_Rec_Time * 1000; OCC_CRITICAL_Tick = OCC_CRITICAL_CLEAR_TIME; } } } else { // alarm check if ((device_value.Current / 1) > (device_param.safety.current.OC_Chg_Threshold * 10)) { OCC_Occur_Current = device_value.Current; device_status.protection.bit.chg_over_current = true; OCCTime = device_param.safety.current.OC_Chg_Rec_Time * 1000; if (OCC_Fail_Count < 3) { OCC_Fail_Count++; OCC_CRITICAL_Tick = OCC_CRITICAL_CLEAR_TIME; } if (OCC_Fail_Count >= 3) { OCC_3Times_Fail = true; OCC_CRITICAL_Tick = OCC_CRITICAL_CLEAR_TIME; } } } if (OCC_3Times_Fail == false) { if (OCC_Fail_Count > 0) { if (OCC_CRITICAL_Tick == 0) { OCC_Fail_Count = 0; } } } device_status.battery_status.bit.TCA = OCC_3Times_Fail; device_status.protection.bit.critial_over_current = OCC_3Times_Fail; /* Over current charge warning */ if (device_status.warning.bit.chg_over_current) { // release check if ((device_value.Current / 1) < (device_param.safety.current.OC_Chg_Recovery * 10)) device_status.warning.bit.chg_over_current = false; } else { // alarm check if ((device_value.Current / 1) > (device_param.safety.current.OC_Chg_Warning * 10)) device_status.warning.bit.chg_over_current = true; } } void dec_ocd_time(u32 tick) { if (OCDTime > tick) OCDTime -= tick; else OCDTime = 0; } void ProcessSafety_OCD(void) { /* Over current discharge protection */ if (device_status.protection.bit.dsg_over_current) { // release check if ((device_value.Current / 1) > (device_param.safety.current.OC_Dsg_Recovery * 10)) { if (OCDTime == 0) device_status.protection.bit.dsg_over_current = false; } else OCDTime = device_param.safety.current.OC_Dsg_Rec_Time * 1000; } else { // alarm check if ((device_value.Current / 1) < (device_param.safety.current.OC_Dsg_Threshold * 10)) { OCD_Occur_Current = device_value.Current; device_status.protection.bit.dsg_over_current = true; OCDTime = device_param.safety.current.OC_Dsg_Rec_Time * 1000; } } /* Over current discharge warning */ if (device_status.warning.bit.dsg_over_current) { // release check if ((device_value.Current / 1) > (device_param.safety.current.OC_Dsg_Recovery * 10)) device_status.warning.bit.dsg_over_current = false; } else { // alarm check if ((device_value.Current / 1) < (device_param.safety.current.OC_Dsg_Warning * 10)) device_status.warning.bit.dsg_over_current = true; } } void ProcessSafety_SOC(void) { /* Low capacity warning */ if (device_status.warning.bit.low_capacity) { // release check if ((device_value.RelativeStateOfCharge) > (device_param.safety.soc.Low_Soc_Recovery * 10)) device_status.warning.bit.low_capacity = false; } else { // alarm check if ((device_value.RelativeStateOfCharge) < (device_param.safety.soc.Low_Soc_Warning * 10)) device_status.warning.bit.low_capacity = true; } } void dec_cv_diff_time(u32 tick) { if (CV_Diff_ProtectTime > tick) CV_Diff_ProtectTime -= tick; else CV_Diff_ProtectTime = 0; } u32 GetCvDiffTime(void) { return (CV_Diff_ProtectTime / 1000); } u32 GetTpDiffTime() { return (Temp_Diff_ProtectTime / 1000); } void ProcessSafety_CellVoltageDiff(void) { device_status.warning.bit.cell_voltage_diff = 0; if (device_value.BatVoltage >= CELL_DEVIATION_CHECK_VOLTAGE) { /* Cell Voltage Diff protection (Cutoff charge if diff >= 200mV holds for 24h, latch until MCU reset) */ if (device_status.protection.bit.cell_voltage_diff) { // KT Requirement: Once tripped, latch protection and do not auto-recover until MCU reset } else { // Alarm check: Cutoff charge if cell diff >= 200mV holds for CV_Diff_ProtectHoldTime (default 24h) if (device_value.Cell.avg.diff >= device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold) { if (CV_Diff_ProtectTime == 0) { device_status.protection.bit.cell_voltage_diff = true; } } else { CV_Diff_ProtectTime = CV_Diff_ProtectHoldTime; } } } else { if (device_status.protection.bit.cell_voltage_diff == false) { CV_Diff_ProtectTime = CV_Diff_ProtectHoldTime; } } } void Set_CV_Diff_ProtectHoldTime(u32 hold_time_ms) { if (hold_time_ms == 0) { CV_Diff_ProtectHoldTime = CV_DIFF_PROTECT_HOLD_TIME; } else { CV_Diff_ProtectHoldTime = hold_time_ms; } if (device_status.protection.bit.cell_voltage_diff == false) { CV_Diff_ProtectTime = CV_Diff_ProtectHoldTime; } } void dec_temp_diff_time(u32 tick) { if (Temp_Diff_ProtectTime > tick) Temp_Diff_ProtectTime -= tick; else Temp_Diff_ProtectTime = 0; } void ProcessSafety_TempDiff(void) { /* Temp Diff protection (24h continuous >= 3.0C diff cut off charging) */ if (device_status.protection.bit.temp_diff) { // Latch protection until reset } else { if ((device_status.error.bit.temp_sensor == false) && (device_value.Temp.avg.diff >= Temp_Diff_Threshold)) { if (Temp_Diff_ProtectTime == 0) { device_status.protection.bit.temp_diff = true; } } else { Temp_Diff_ProtectTime = Temp_Diff_ProtectHoldTime; } } } void Set_Temp_Diff_ProtectHoldTime(u32 hold_time_ms) { if (hold_time_ms == 0) { Temp_Diff_ProtectHoldTime = TEMP_DIFF_PROTECT_HOLD_TIME; } else { Temp_Diff_ProtectHoldTime = hold_time_ms; } if (device_status.protection.bit.temp_diff == false) { Temp_Diff_ProtectTime = Temp_Diff_ProtectHoldTime; } } void Set_Temp_Diff_Threshold(u16 th) { if (th == 0) Temp_Diff_Threshold = TEMP_DIFF_PROTECT_THRESHOLD; else Temp_Diff_Threshold = th; } u16 Get_Temp_Diff_Threshold(void) { return Temp_Diff_Threshold; } #define OP_STS_STANDBY 0x0000 #define OP_STS_CHARGING 0x0001 #define OP_STS_DISCHARGING 0x0002 #define OP_STS_WARMINUP 0x0003 void Process_FetControl(void) { if ((device_status.protection.bit.afe_fail) || (device_status.error.bit.temp_sensor)) { device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; device_status.battery_status.bit.ZVC_C = false; return; } // Charge Protection Check if (device_status.protection.bit.cell_over_voltage) // Cell Over Voltage { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protection.bit.over_voltage) // System Over Voltage { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protection.bit.chg_over_current) // Charge Over Current { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protection.bit.chg_high_temp) // Charge High Temperature { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protection.bit.chg_low_temp) // Charge Low Temperature { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } //u32 OCC_CRITICAL_Tick = 60 * 1000; //u8 OCC_Fail_Count = 0; //u8 OCC_3Times_Fail = false; else if (OCC_3Times_Fail || device_status.protection.bit.critial_over_current) { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protection.bit.cell_voltage_diff || device_status.protection.bit.temp_diff) // Cell Voltage Diff & Temp Diff Protection (Cutoff charge if held 24h) { device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.ZVC_C = false; } else { device_status.battery_status.bit.CHG_C = true; device_status.battery_status.bit.ZVC_C = false; } // Discharge Protection Check if (device_status.protection.bit.cell_under_voltage) // Cell Under Voltage { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else if (device_status.protection.bit.under_voltage) // System Under Voltage { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else if (device_status.protection.bit.dsg_over_current) // Discharge Over Current { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else if (device_status.protection.bit.dsg_high_temp) // Discharge High Temperature { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else if (device_status.protection.bit.dsg_low_temp) // Discharge Low Temperature { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else // No Protection { device_status.battery_status.bit.DSG_C = true; } if (device_status.protection.bit.cell_voltage_diff || device_status.protection.bit.temp_diff) { device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.ZVC_C = false; } } void ProcessStatusCheck(void) { // Alarm Status if (device_status.battery_status.bit.INIT == false) device_status.alarm_status = 0x0003; // Warming Up else if (device_status.protection.value != 0) device_status.alarm_status = 0x0002; // Protection else if (device_status.warning.value != 0) device_status.alarm_status = 0x0001; // Warning else device_status.alarm_status = 0x0000; // Normal // Operating Status if (device_status.battery_status.bit.INIT == false) { device_status.op_status = 0x0004; // Warming Up } else { if (device_status.battery_status.bit.RXM == false) { switch (device_status.op_status) { case OP_STS_STANDBY: // Standby case 0x0003: // Floating if (device_value.CCurrent > (device_param.chg_ctrl.current_thr.Charge_Detection_Threshold / 100)) { device_status.op_status = 0x0001; } else if (device_value.DCurrent > (device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold / 100)) { device_status.op_status = 0x0002; } break; case 0x0001: // Charging if (device_value.DCurrent > (device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold / 100)) { device_status.op_status = 0x0002; } else if ((device_value.CCurrent < ((device_param.chg_ctrl.current_thr.Charge_Detection_Threshold - 1000) / 100)) || (device_status.battery_status.bit.CHG_C == false)) { device_status.op_status = OP_STS_STANDBY; } break; case 0x0002: // Discharging if (device_value.CCurrent > (device_param.chg_ctrl.current_thr.Charge_Detection_Threshold / 100)) { device_status.op_status = 0x0001; } else if (device_value.DCurrent < ((device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold - 1000) / 100)) { device_status.op_status = OP_STS_STANDBY; // Standby } break; case 0x0004: // Warming Up device_status.op_status = 0x0000; // Standby break; default: device_status.op_status = 0x0000; // Standby break; } // if (device_status.op_status == 0x0004) // device_status.op_status = 0x0000; // Standby // else // { // if (device_value.CCurrent > (device_param.chg_ctrl.current_thr.Charge_Detection_Threshold / 100)) // { // device_status.op_status = 0x0001; // } // else if (device_value.DCurrent > (device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold / 100)) // { // device_status.op_status = 0x0002; // } // } } else { switch (device_status.op_status) { case 0x0000: // Stand by // if (device_value.BatVoltage >= (device_param.chg_ctrl.chg_cfg.ST_Chg_Voltage)) if (device_value.BatVoltage >= 5200) { if (device_status.protection.value == 0) device_status.op_status = 0x0003; // Floating } break; case 0x0003: // Float Charge // if (device_value.BatVoltage <= (device_param.chg_ctrl.chg_cfg.ST_Chg_Voltage - (device_param.chg_ctrl.term_cfg.Taper_Voltage / 10))) if (device_value.BatVoltage <= 5180) { device_status.op_status = 0x0000; // Floating } break; default: // if ((device_value.BatVoltage >= (device_param.chg_ctrl.chg_cfg.ST_Chg_Voltage)) if ((device_value.BatVoltage >= 5200) && (device_status.protection.value == 0)) device_status.op_status = 0x0003; // Floating else device_status.op_status = 0x0000; // Standby break; } } if (device_status.op_status == OP_STS_DISCHARGING) { device_status.battery_status.bit.CHG_C = true; } } }