diff options
-rw-r--r-- | common/ocpc.c | 151 |
1 files changed, 114 insertions, 37 deletions
diff --git a/common/ocpc.c b/common/ocpc.c index b6ec4e4ab6..92ee2ab532 100644 --- a/common/ocpc.c +++ b/common/ocpc.c @@ -41,6 +41,12 @@ do { \ if (debug_output) \ cprints(CC_CHARGER, format, ## args); \ } while (0) +#define CPRINTF_DBG(format, args...) \ +do { \ + if (debug_output) \ + cprintf(CC_CHARGER, format, ## args); \ +} while (0) + /* Code refactor will be needed if more than 2 charger chips are present */ BUILD_ASSERT(CHARGER_NUM == 2); @@ -55,14 +61,25 @@ static int debug_output; static int viz_output; #define NUM_RESISTANCE_SAMPLES 8 -static int resistance_tbl[NUM_RESISTANCE_SAMPLES] = { - CONFIG_OCPC_DEF_RBATT_MOHMS +#define COMBINED_IDX 0 +#define RBATT_IDX 1 +#define RSYS_IDX 2 +static int resistance_tbl[NUM_RESISTANCE_SAMPLES][3] = { + /* Rsys+Rbatt Rbatt Rsys */ + {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0}, + {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0}, + {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0}, + {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0}, + {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0}, + {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0}, + {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0}, + {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0}, }; static int resistance_tbl_idx; -static int mean_resistance; -static int stddev_resistance; -static int ub; -static int lb; +static int mean_resistance[3]; +static int stddev_resistance[3]; +static int ub[3]; +static int lb[3]; enum phase { PHASE_UNKNOWN = -1, @@ -78,28 +95,71 @@ __overridable void board_ocpc_init(struct ocpc_data *ocpc) static enum ec_error_list ocpc_precharge_enable(bool enable); -static void calc_resistance_stats(void) +static void calc_resistance_stats(struct ocpc_data *ocpc) { int i; - int sum = 0; + int j; + int sum; + int cols = 3; + int act_chg = ocpc->active_chg_chip; + + /* Only perform separate stats on Rsys and Rbatt if necessary. */ + if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) + cols = 1; /* Calculate mean */ - for (i = 0; i < NUM_RESISTANCE_SAMPLES; i++) - sum += resistance_tbl[i]; - - mean_resistance = sum / NUM_RESISTANCE_SAMPLES; - - /* Calculate standard deviation */ - sum = 0; - for (i = 0; i < NUM_RESISTANCE_SAMPLES; i++) - sum += POW2(resistance_tbl[i] - mean_resistance); - - stddev_resistance = fp_sqrtf(INT_TO_FP(sum / NUM_RESISTANCE_SAMPLES)); - stddev_resistance = FP_TO_INT(stddev_resistance); - CPRINTS_DBG("Rbatt+Rsys: mean: %d stddev: %d", mean_resistance, - stddev_resistance); - lb = MAX(0, mean_resistance - (3 * stddev_resistance)); - ub = mean_resistance + (3 * stddev_resistance); + for (i = 0; i < cols; i++) { + sum = 0; + for (j = 0; j < NUM_RESISTANCE_SAMPLES; j++) { + sum += resistance_tbl[j][i]; + CPRINTF_DBG("%d ", resistance_tbl[j][i]); + } + CPRINTF_DBG("\n"); + + mean_resistance[i] = sum / NUM_RESISTANCE_SAMPLES; + + /* Calculate standard deviation */ + sum = 0; + for (j = 0; j < NUM_RESISTANCE_SAMPLES; j++) + sum += POW2(resistance_tbl[j][i] - mean_resistance[i]); + + stddev_resistance[i] = fp_sqrtf(INT_TO_FP(sum / + NUM_RESISTANCE_SAMPLES)); + stddev_resistance[i] = FP_TO_INT(stddev_resistance[i]); + /* + * Don't let our stddev collapse to 0 to continually consider + * new values. + */ + stddev_resistance[i] = MAX(stddev_resistance[i], 1); + CPRINTS_DBG("%d: mean: %d stddev: %d", i, mean_resistance[i], + stddev_resistance[i]); + lb[i] = MAX(0, mean_resistance[i] - (3 * stddev_resistance[i])); + ub[i] = mean_resistance[i] + (3 * stddev_resistance[i]); + } +} + +static bool is_within_range(struct ocpc_data *ocpc, int combined, int rbatt, + int rsys) +{ + int act_chg = ocpc->active_chg_chip; + bool valid; + + /* Discard measurements not within a 6 std. dev. window. */ + if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) { + /* We only know the combined Rsys+Rbatt */ + valid = (combined > 0) && + (combined <= ub[COMBINED_IDX]) && + (combined >= lb[COMBINED_IDX]); + } else { + valid = (rsys <= ub[RSYS_IDX]) && (rsys >= lb[RSYS_IDX]) && + (rbatt <= ub[RBATT_IDX]) && (rbatt >= lb[RBATT_IDX]) && + (rsys > 0) && (rbatt > 0); + } + + if (!valid) + CPRINTS_DBG("Discard Rc:%d Rb:%d Rs:%d", combined, rbatt, rsys); + + return valid; } enum ec_error_list ocpc_calc_resistances(struct ocpc_data *ocpc, @@ -108,7 +168,9 @@ enum ec_error_list ocpc_calc_resistances(struct ocpc_data *ocpc, int act_chg = ocpc->active_chg_chip; static bool seeded; static int initial_samples; - int val; + int combined; + int rsys = -1; + int rbatt = -1; /* * In order to actually calculate the resistance, we need to make sure @@ -133,30 +195,45 @@ enum ec_error_list ocpc_calc_resistances(struct ocpc_data *ocpc, * There's no provision to measure Isys, so we cannot separate * out Rsys from Rbatt. */ - val = ((ocpc->vsys_aux_mv - battery->voltage) * 1000) / - battery->current; + combined = ((ocpc->vsys_aux_mv - battery->voltage) * 1000) / + battery->current; } else { - ocpc->rsys_mo = ((ocpc->vsys_aux_mv - ocpc->vsys_mv) * 1000) / + rsys = ((ocpc->vsys_aux_mv - ocpc->vsys_mv) * 1000) / ocpc->isys_ma; - ocpc->rbatt_mo = ((ocpc->vsys_mv - battery->voltage) * 1000) / + rbatt = ((ocpc->vsys_mv - battery->voltage) * 1000) / battery->current; - val = ocpc->rsys_mo + ocpc->rbatt_mo; - CPRINTS_DBG("Rsys: %dmOhm Rbatt: %dmOhm", ocpc->rsys_mo, - ocpc->rbatt_mo); + combined = rsys + rbatt; } /* Discard measurements not within a 6 std dev window. */ if ((!seeded) || - (seeded && ((val <= ub) && (val >= lb)))) { - resistance_tbl[resistance_tbl_idx] = val; - calc_resistance_stats(); + (seeded && is_within_range(ocpc, combined, rbatt, rsys))) { + if (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) { + resistance_tbl[resistance_tbl_idx][RSYS_IDX] = + MAX(rsys, 0); + resistance_tbl[resistance_tbl_idx][RBATT_IDX] = + MAX(rbatt, CONFIG_OCPC_DEF_RBATT_MOHMS); + } + resistance_tbl[resistance_tbl_idx][COMBINED_IDX] = + MAX(combined, CONFIG_OCPC_DEF_RBATT_MOHMS); + calc_resistance_stats(ocpc); resistance_tbl_idx = (resistance_tbl_idx + 1) % NUM_RESISTANCE_SAMPLES; } if (seeded) { - ocpc->combined_rsys_rbatt_mo = MAX(mean_resistance, - CONFIG_OCPC_DEF_RBATT_MOHMS); + ocpc->combined_rsys_rbatt_mo = + MAX(mean_resistance[COMBINED_IDX], + CONFIG_OCPC_DEF_RBATT_MOHMS); + + if (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) { + ocpc->rsys_mo = mean_resistance[RSYS_IDX]; + ocpc->rbatt_mo = MAX(mean_resistance[RBATT_IDX], + CONFIG_OCPC_DEF_RBATT_MOHMS); + CPRINTS_DBG("Rsys: %dmOhm Rbatt: %dmOhm", + ocpc->rsys_mo, ocpc->rbatt_mo); + } + CPRINTS_DBG("Rsys+Rbatt: %dmOhm", ocpc->combined_rsys_rbatt_mo); } else { seeded = ++initial_samples >= (2 * NUM_RESISTANCE_SAMPLES) ? |