FreeCalypso > hg > fc-magnetite
view src/cs/drivers/drv_app/fchg/fchg_process.c @ 624:012028896cfb
FFS dev.c, Leonardo target: Fujitsu MB84VF5F5F4J2 #if 0'ed out
The FFS code we got from TI/Openmoko had a stanza for "Fujitsu MB84VF5F5F4J2
stacked device", using a fake device ID code that would need to be patched
manually into cfgffs.c (suppressing and overriding autodetection) and using
an FFS base address in the nCS2 bank, indicating that this FFS config was
probably meant for the MCP version of Leonardo which allows for 16 MiB flash
with a second bank on nCS2.
We previously had this FFS config stanza conditionalized under
CONFIG_TARGET_LEONARDO because the base address contained therein is invalid
for other targets, but now that we actually have a Leonardo build target in
FC Magnetite, I realize that the better approach is to #if 0 out this stanza
altogether: it is already non-functional because it uses a fake device ID
code, thus it is does not add support for more Leonardo board variants,
instead it is just noise.
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sun, 22 Dec 2019 21:24:29 +0000 |
| parents | 92dbfa906f66 |
| children | 94cb5e76b3b5 |
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 "fc-target.h" #include <string.h> #include <stdio.h> extern UINT16 madc_vbat_2_physical(UINT16 adc_val); extern UINT16 madc_vbat_inverse(UINT16 mv); #if defined(CONFIG_TARGET_C155) || defined(CONFIG_TARGET_J100) #define LEDC 0x20 #else #define LEDC 0 #endif 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 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 | LEDC); /* The total charging time starts now */ pwr_ctrl->start_time = rvf_get_tick_count(); } static void start_cv_charging(void) { 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 */ code = madc_vbat_inverse(pwr_ctrl->config.cv_init_set); 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 | LEDC); /* CV control loop state init */ pwr_ctrl->cv_dac_init = code; pwr_ctrl->cv_dac_curr = code; pwr_ctrl->cv_high_vbat_count = 0; pwr_ctrl->cv_low_vbat_count = 0; /* Ichg averaging state init */ pwr_ctrl->ichg_fill_level = 0; pwr_ctrl->ichg_ring_ptr = 0; pwr_ctrl->ichg_low_count = 0; } 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 void ci_progress_trace(UINT16 ichg) { char trace[64]; sprintf(trace, "CI charging: Vbat=%u Ichg=%u i2v=%u", 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 int cv_ichg_process(UINT16 ichg_new) { UINT16 ichg_clip, ichg_entry; UINT32 ichg_accum; UINT16 i; char trace[64]; if (pwr_ctrl->ichg_fill_level < ICHG_AVG_WINDOW) pwr_ctrl->ichg_avg_buf[pwr_ctrl->ichg_fill_level++] = ichg_new; else { ichg_clip = pwr_ctrl->ichg_average + pwr_ctrl->config.ichg_max_spike; if (ichg_new > ichg_clip) ichg_entry = ichg_clip; else ichg_entry = ichg_new; pwr_ctrl->ichg_avg_buf[pwr_ctrl->ichg_ring_ptr++] = ichg_entry; if (pwr_ctrl->ichg_ring_ptr >= ICHG_AVG_WINDOW) pwr_ctrl->ichg_ring_ptr = 0; } ichg_accum = 0; for (i = 0; i < pwr_ctrl->ichg_fill_level; i++) ichg_accum += pwr_ctrl->ichg_avg_buf[i]; pwr_ctrl->ichg_average = ichg_accum / pwr_ctrl->ichg_fill_level; sprintf(trace, "CV charging: Vbat=%u Ichg=%u Ichg_avg=%u i2v=%u", pwr_ctrl->batt_mv, ichg_new, pwr_ctrl->ichg_average, pwr_ctrl->i2v_offset); rvf_send_trace(trace, strlen(trace), NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, FCHG_USE_ID); if (pwr_ctrl->ichg_average > (pwr_ctrl->config.end_current + pwr_ctrl->i2v_offset)) { pwr_ctrl->ichg_low_count = 0; return 0; } pwr_ctrl->ichg_low_count++; if (pwr_ctrl->ichg_low_count < pwr_ctrl->config.ichg_samples_needed) return 0; 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 1; } static int overvoltage_end_charge_check(void) { if (pwr_ctrl->batt_mv < pwr_ctrl->config.overvoltage) return 0; if (pwr_ctrl->cv_dac_curr != (pwr_ctrl->cv_dac_init - pwr_ctrl->config.cv_dac_max_decr)) return 0; rvf_send_trace("Stopping charge by overvoltage condition", 40, NULL_PARAM, RV_TRACE_LEVEL_WARNING, FCHG_USE_ID); ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); pwr_init_discharge(); pwr_ctrl->state = FCHG_STATE_READY_TO_RECHARGE; return 1; } static void cv_ctrl_loop_high_check(void) { if (pwr_ctrl->batt_mv < pwr_ctrl->config.cv_ctrl_loop_high) { pwr_ctrl->cv_high_vbat_count = 0; return; } pwr_ctrl->cv_high_vbat_count++; if (pwr_ctrl->cv_high_vbat_count < pwr_ctrl->config.cv_samples_needed) return; if (pwr_ctrl->cv_dac_curr == (pwr_ctrl->cv_dac_init - pwr_ctrl->config.cv_dac_max_decr)) return; pwr_ctrl->cv_dac_curr--; ABB_Write_Register_on_page(PAGE0, CHGREG, pwr_ctrl->cv_dac_curr); rvf_send_trace("Sub CV DAC", 10, pwr_ctrl->cv_dac_curr, RV_TRACE_LEVEL_DEBUG_MEDIUM, FCHG_USE_ID); pwr_ctrl->cv_high_vbat_count = 0; } static void cv_ctrl_loop_low_check(void) { if (pwr_ctrl->batt_mv >= pwr_ctrl->config.cv_ctrl_loop_low) { pwr_ctrl->cv_low_vbat_count = 0; return; } pwr_ctrl->cv_low_vbat_count++; if (pwr_ctrl->cv_low_vbat_count < pwr_ctrl->config.cv_samples_needed) return; if (pwr_ctrl->cv_dac_curr == (pwr_ctrl->cv_dac_init + pwr_ctrl->config.cv_dac_max_incr)) return; pwr_ctrl->cv_dac_curr++; ABB_Write_Register_on_page(PAGE0, CHGREG, pwr_ctrl->cv_dac_curr); rvf_send_trace("Add CV DAC", 10, pwr_ctrl->cv_dac_curr, RV_TRACE_LEVEL_DEBUG_MEDIUM, FCHG_USE_ID); pwr_ctrl->cv_low_vbat_count = 0; } static int charging_time_limit_check(void) { if ((rvf_get_tick_count() - pwr_ctrl->start_time) < RVF_SECS_TO_TICKS(pwr_ctrl->config.charge_time_limit)) return 0; rvf_send_trace("Stopping charge by time exceeded condition", 42, NULL_PARAM, RV_TRACE_LEVEL_WARNING, FCHG_USE_ID); ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); pwr_init_discharge(); pwr_ctrl->state = FCHG_STATE_RECHARGE_TIMER; pwr_ctrl->start_time = rvf_get_tick_count(); 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: ci_progress_trace(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 (charging_time_limit_check()) return; if (pwr_ctrl->batt_mv >= pwr_ctrl->config.ci2cv_thresh) start_cv_charging(); return; case FCHG_STATE_CV_CHARGING: if (!(msg->data[9] & CHGPRES)) { ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); pwr_ctrl->state = FCHG_STATE_NO_EXT_PWR; return; } if (cv_ichg_process(msg->data[2])) return; if (overvoltage_end_charge_check()) return; if (charging_time_limit_check()) return; cv_ctrl_loop_high_check(); cv_ctrl_loop_low_check(); return; case FCHG_STATE_RECHARGE_TIMER: handle_discharge(); if ((rvf_get_tick_count() - pwr_ctrl->start_time) < RVF_SECS_TO_TICKS(pwr_ctrl->config.recharge_delay)) return; rvf_send_trace("Restart time met, allowing new charging", 39, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); 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_RECHARGE_TIMER: 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); } } void pwr_charge_start_req(void) { switch (pwr_ctrl->state) { case FCHG_STATE_NO_EXT_PWR: rvf_send_trace("Cannot charge without a power source", 36, NULL_PARAM, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID); return; case FCHG_STATE_NO_CHARGING: if (!pwr_ctrl->config_present) { rvf_send_trace("No config set, cannot charge", 28, NULL_PARAM, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID); return; } /* FALL THRU */ case FCHG_STATE_PWR_PLUG_TIMER: case FCHG_STATE_READY_TO_CHARGE: case FCHG_STATE_READY_TO_RECHARGE: case FCHG_STATE_RECHARGE_TIMER: rvf_send_trace("Starting charge on user request", 31, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); pwr_ctrl->state = FCHG_STATE_I2V_CAL_1; return; case FCHG_STATE_I2V_CAL_1: case FCHG_STATE_I2V_CAL_2: case FCHG_STATE_CI_CHARGING: case FCHG_STATE_CV_CHARGING: rvf_send_trace( "Charging already in progress, start request ignored", 51, NULL_PARAM, RV_TRACE_LEVEL_WARNING, FCHG_USE_ID); return; default: rvf_send_trace("Invalid state in pwr_charge_start_req()", 37, pwr_ctrl->state, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID); } } void pwr_charge_stop_req(void) { switch (pwr_ctrl->state) { case FCHG_STATE_NO_EXT_PWR: case FCHG_STATE_NO_CHARGING: /* 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_RECHARGE_TIMER: rvf_send_trace("Charging disabled by user request", 33, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); pwr_ctrl->state = FCHG_STATE_NO_CHARGING; 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("Charging stopped by user request", 32, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, FCHG_USE_ID); pwr_ctrl->state = FCHG_STATE_NO_CHARGING; pwr_init_discharge(); return; default: rvf_send_trace("Invalid state in pwr_charge_stop_req()", 36, pwr_ctrl->state, RV_TRACE_LEVEL_ERROR, FCHG_USE_ID); } }
