FreeCalypso > hg > fc-magnetite
diff src/cs/drivers/drv_app/fchg/fchg_process.c @ 331:8166b0afcf8c
FCHG: main ADC process implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 14 Dec 2017 16:22:30 +0000 |
parents | |
children | 8a90038c0173 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cs/drivers/drv_app/fchg/fchg_process.c Thu Dec 14 16:22:30 2017 +0000 @@ -0,0 +1,226 @@ +/* + * In this module we are going to implement the main process functions + * for FCHG. + */ + +#include "fchg/fchg_env.h" +#include "fchg/fchg_func_i.h" +#include "rv/rv_general.h" +#include "rvf/rvf_api.h" +#include "rvm/rvm_use_id_list.h" +#include "abb/abb.h" +#include <string.h> +#include <stdio.h> + +extern UINT16 madc_vbat_2_physical(UINT16 adc_val); + +void pwr_init_discharge(void) +{ + pwr_ctrl->curr_percent = pwr_ctrl->batt_thresholds[0].remain_capa; +} + +static void handle_discharge(void) +{ + UINT16 i; + char trace[64]; + + /* first we need to find the current threshold we are at */ + for (i = 0; i < pwr_ctrl->nb_thresholds; i++) + if (pwr_ctrl->batt_thresholds[i].remain_capa == + pwr_ctrl->curr_percent) + break; + /* is there one below? */ + if (++i == pwr_ctrl->nb_thresholds) + return; + /* are we crossing it? */ + if (pwr_ctrl->batt_mv >= pwr_ctrl->batt_thresholds[i].bat_voltage) + return; + /* yes, we crossed it - see if we fell even further down */ + while (i < pwr_ctrl->nb_thresholds && + pwr_ctrl->batt_mv < pwr_ctrl->batt_thresholds[i].bat_voltage) + i++; + /* the last one was it */ + i--; + pwr_ctrl->curr_percent = pwr_ctrl->batt_thresholds[i].remain_capa; + sprintf(trace, "Battery fell through %u%% mark", + pwr_ctrl->curr_percent); + rvf_send_trace(trace, strlen(trace), NULL_PARAM, + RV_TRACE_LEVEL_WARNING, FCHG_USE_ID); +} + +static void charge_progress_trace(char *mode, UINT16 ichg) +{ + char trace[64]; + + sprintf(trace, "%s charging: Vbat=%u Ichg=%u i2v=%u", mode, + pwr_ctrl->batt_mv, ichg, pwr_ctrl->i2v_offset); + rvf_send_trace(trace, strlen(trace), NULL_PARAM, + RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID); +} + +static void start_i2v_cal(void) +{ + UINT16 bciconf; + + rvf_send_trace("Calibrating i2v offset", 22, NULL_PARAM, + RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); + pwr_ctrl->state = FCHG_STATE_I2V_CAL_2; + bciconf = ABB_Read_Register_on_page(PAGE1, BCICONF); + bciconf &= 0x3E0; + bciconf |= pwr_ctrl->config.bciconf; + ABB_Write_Register_on_page(PAGE1, BCICONF, bciconf); + /* + * Set the CHDISPA bit and start the zero calibration routine + * of the I to V converter + */ + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0010); + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0019); +} + +static void start_ci_charging(void) +{ + rvf_send_trace("Start CI charging", 17, NULL_PARAM, + RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); + pwr_ctrl->state = FCHG_STATE_CI_CHARGING; + /* Select constant current charging. The charger is disabled */ + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0002); + /* Program the DAC with the constant current value */ + ABB_Write_Register_on_page(PAGE0, CHGREG, + pwr_ctrl->config.ci_current + pwr_ctrl->i2v_offset); + /* Enable the charger */ + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0003); +} + +static void start_cv_charging(UINT16 code) +{ + rvf_send_trace("Start CV charging", 17, NULL_PARAM, + RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); + pwr_ctrl->state = FCHG_STATE_CV_CHARGING; + /* Select constant voltage charging. The charger is disabled */ + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); + /* figure out the DAC code */ + while (code && + madc_vbat_2_physical(code) >= pwr_ctrl->config.charge_to_mv) + code--; + code++; + rvf_send_trace("Voltage (DAC code) ", 19, code, + RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID); + /* Program the DAC with the constant voltage value */ + ABB_Write_Register_on_page(PAGE0, CHGREG, code); + /* Enable the charger */ + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0001); +} + +static void start_charge_condition_met(void) +{ + rvf_send_trace("Charge start condition met", 26, NULL_PARAM, + RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); + if (pwr_ctrl->config.bciconf) + start_i2v_cal(); + else { + pwr_ctrl->i2v_offset = 0; + start_ci_charging(); + } +} + +static int overvoltage_end_charge_check(void) +{ + if (pwr_ctrl->batt_mv < pwr_ctrl->config.overvoltage) + return 0; + rvf_send_trace("Stopping charge by overvoltage condition", 40, + NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); + pwr_init_discharge(); + pwr_ctrl->state = FCHG_STATE_READY_TO_RECHARGE; + return 1; +} + +void pwr_process_adc(struct pwr_adc_ind_s *msg) +{ + pwr_ctrl->batt_mv = madc_vbat_2_physical(msg->data[0]); + + switch (pwr_ctrl->state) { + case FCHG_STATE_NO_EXT_PWR: + case FCHG_STATE_PWR_PLUG_TIMER: + case FCHG_STATE_NO_CHARGING: + handle_discharge(); + return; + case FCHG_STATE_READY_TO_CHARGE: + handle_discharge(); + if (!(msg->data[9] & CHGPRES)) { + pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; + return; + } + if (pwr_ctrl->batt_mv >= pwr_ctrl->config.start_thresh) + start_charge_condition_met(); + return; + case FCHG_STATE_READY_TO_RECHARGE: + handle_discharge(); + if (!(msg->data[9] & CHGPRES)) { + pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; + return; + } + if (pwr_ctrl->batt_mv >= pwr_ctrl->config.restart_thresh) + start_charge_condition_met(); + return; + case FCHG_STATE_I2V_CAL_1: + if (!(msg->data[9] & CHGPRES)) { + pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; + return; + } + if (pwr_ctrl->config.bciconf) + start_i2v_cal(); + else { + pwr_ctrl->i2v_offset = 0; + start_ci_charging(); + } + return; + case FCHG_STATE_I2V_CAL_2: + pwr_ctrl->i2v_offset = msg->data[2]; + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); + rvf_send_trace("i2v offset (MADC code) ", 23, + pwr_ctrl->i2v_offset, + RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID); + if (!(msg->data[9] & CHGPRES)) { + pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; + return; + } + start_ci_charging(); + return; + case FCHG_STATE_CI_CHARGING: + charge_progress_trace("CI", msg->data[2]); + if (!(msg->data[9] & CHGPRES)) { + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); + pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; + return; + } + if (overvoltage_end_charge_check()) + return; + if (pwr_ctrl->batt_mv >= pwr_ctrl->config.charge_to_mv) + start_cv_charging(msg->data[0]); + return; + case FCHG_STATE_CV_CHARGING: + charge_progress_trace("CV", msg->data[2]); + if (!(msg->data[9] & CHGPRES)) { + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); + pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; + return; + } + if (overvoltage_end_charge_check()) + return; + if (msg->data[2] >= + pwr_ctrl->config.end_current + pwr_ctrl->i2v_offset) + return; + rvf_send_trace("Stopping charge by low current condition", 40, + NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, + FCHG_USE_ID); + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); + pwr_init_discharge(); + pwr_ctrl->state = FCHG_STATE_READY_TO_RECHARGE; + return; + default: + rvf_send_trace("Invalid state in pwr_process_adc()", 32, + pwr_ctrl->state, RV_TRACE_LEVEL_ERROR, + FCHG_USE_ID); + } +}