FreeCalypso > hg > fc-magnetite
view src/cs/drivers/drv_app/fchg/fchg_process.c @ 334:d583a1f5bd6a
FCHG: charger plug and unplug functions implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 14 Dec 2017 19:54:18 +0000 |
parents | 8a90038c0173 |
children | 6c0659acf93e |
line wrap: on
line source
/* * 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_disch_thresh = 0; } static void handle_discharge(void) { UINT16 i; char trace[64]; /* first we need to find the current threshold we are at */ i = pwr_ctrl->curr_disch_thresh; /* 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_disch_thresh = i; sprintf(trace, "Battery fell through %u%% mark", pwr_ctrl->batt_thresholds[i].remain_capa); 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); } } void pwr_handle_timer(void) { if (pwr_ctrl->state != FCHG_STATE_PWR_PLUG_TIMER) return; rvf_send_trace("Timer expired, ready to charge", 30, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID); pwr_ctrl->state = FCHG_STATE_READY_TO_CHARGE; } void pwr_charger_plug(void) { if (pwr_ctrl->state != FCHG_STATE_NO_EXT_PWR) { rvf_send_trace("Charger plug event in unexpected state", 38, pwr_ctrl->state, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID); return; } if (!pwr_ctrl->config_present) { rvf_send_trace( "Charger plugged in, but no config: won't charge", 47, NULL_PARAM, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID); pwr_ctrl->state = FCHG_STATE_NO_CHARGING; return; } if (pwr_ctrl->config.start_delay) { rvf_send_trace("Charger plug, starting timer", 28, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); rvf_start_timer(FCHG_TIMER, RVF_MS_TO_TICKS(pwr_ctrl->config.start_delay), FALSE); pwr_ctrl->state = FCHG_STATE_PWR_PLUG_TIMER; } else { rvf_send_trace("Charger plug, ready to charge", 29, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); pwr_ctrl->state = FCHG_STATE_READY_TO_CHARGE; } } void pwr_charger_unplug(void) { switch (pwr_ctrl->state) { case FCHG_STATE_NO_EXT_PWR: rvf_send_trace("Charger unplug, already handled", 31, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID); /* nothing to do */ return; case FCHG_STATE_PWR_PLUG_TIMER: case FCHG_STATE_READY_TO_CHARGE: case FCHG_STATE_READY_TO_RECHARGE: case FCHG_STATE_I2V_CAL_1: case FCHG_STATE_NO_CHARGING: rvf_send_trace("Charger unplug", 14, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID); pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; return; case FCHG_STATE_I2V_CAL_2: case FCHG_STATE_CI_CHARGING: case FCHG_STATE_CV_CHARGING: ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); rvf_send_trace("Charger unplug, charging stopped", 32, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; pwr_init_discharge(); return; default: rvf_send_trace("Invalid state in pwr_charger_unplug()", 35, pwr_ctrl->state, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID); } }