FreeCalypso > hg > fc-tourmaline
diff src/cs/drivers/drv_app/pwr/pwr_liion_cha.c @ 0:4e78acac3d88
src/{condat,cs,gpf,nucleus}: import from Selenite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:23:26 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cs/drivers/drv_app/pwr/pwr_liion_cha.c Fri Oct 16 06:23:26 2020 +0000 @@ -0,0 +1,698 @@ +/******************************************************************************* + * + * pwr_liion_cha.c + * + * Purpose: This file contains functions for managing the Li-ion batteries + * charging process. + * + * Author Candice Bazanegue (c-brille@ti.com) + * + * + * (C) Texas Instruments 2001 + * + ******************************************************************************/ + +#include "rv/rv_defined_swe.h" // for RVM_PWR_SWE + +#ifdef RVM_PWR_SWE + +#include "rvm/rvm_use_id_list.h" +#include "spi/spi_task.h" +#include "spi/spi_api.h" +#include "pwr/pwr_cust.h" +#include "pwr/pwr_liion_cha.h" +#include "pwr/pwr_disch.h" +#include "spi/spi_env.h" +#include "rvf/rvf_api.h" +#include "pwr/pwr_analog_dev.h" +#include "pwr/pwr_messages.h" + +/* Global variable */ +extern T_SPI_GBL_INFO *SPI_GBL_INFO_PTR; + + +/******************************************************************************* +** Function pwr_start_CI_charging +** +** Description This function is used to start the constant current +** battery charging. +** +*******************************************************************************/ +void pwr_start_CI_charging(unsigned short charging_current) +{ + volatile unsigned short dac_current_code; + + + rvf_send_trace("Start CI charging",17, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + dac_current_code = (unsigned int)((1000 * charging_current)/DAC_CURRENT_STEP); + + /* 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, dac_current_code); + + /* Enable the charger */ + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0003); + + pwr_env_ctrl_blk->charging_state = CI_CHARGE_STARTED; + +} + + + +/******************************************************************************* +** Function pwr_start_CV_charging +** +** Description This function is used to start the constant voltage +** battery charging. +** +*******************************************************************************/ +void pwr_start_CV_charging(unsigned short charging_voltage) +{ + volatile unsigned short dac_voltage_code; + unsigned short dac_voltage; + + rvf_send_trace("Start CV charging",17, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + dac_voltage = charging_voltage + VOLTAGE_LOOP_OFFSET; + + dac_voltage_code = (unsigned int)((1000 * ((dac_voltage /4) - DAC_THRESHOLD))/DAC_VOLTAGE_STEP); + + rvf_send_trace("Voltage (DAC code) ", 19, dac_voltage_code, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + /* Select constant voltage charging. The charger is disabled */ + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); + + /* Program the DAC with the constant voltage value */ + ABB_Write_Register_on_page(PAGE0, CHGREG, dac_voltage_code); + + /* Enable the charger */ + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0x0001); + + pwr_env_ctrl_blk->charging_state = CV_CHARGE_STARTED; + +} + + + +/******************************************************************************* +** Function pwr_stop_charging +** +** Description This function is used to stop the battery charging process. +** +*******************************************************************************/ +void pwr_stop_charging(void) +{ + + rvf_send_trace("Stop charging process",21, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + ABB_Write_Register_on_page(PAGE0, BCICTL2, 0); + pwr_env_ctrl_blk->charging_state = CHARGE_STOPPED; +} + + + + +/******************************************************************************* +** Function pwr_current_loop_cal +** +** Description This function is used to evaluate the offset introduced +** by the current to voltage converter in the current loop. +** +** +*******************************************************************************/ +void pwr_current_loop_cal(void) +{ + rvf_send_trace("Current loop calibration",24, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + /* 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); + + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* start ICHG channel conversion by writing in the result register */ + ABB_Write_Register_on_page(PAGE0, ICHGREG, 0x0000); + + rvf_start_timer (SPI_TIMER0, + RVF_MS_TO_TICKS (SPI_TIMER0_INTERVAL_3), + FALSE); + } + else /* The L1 asks for ADC conversions */ + { + rvf_start_timer (SPI_TIMER0, + RVF_MS_TO_TICKS (SPI_TIMER0_INTERVAL_4), + FALSE); + } + +} + + + +/******************************************************************************* +** Function pwr_calibration_process +** +** Description +** +*******************************************************************************/ +void pwr_calibration_process(void) +{ + if (pwr_bat_temp_within_limits(pwr_env_ctrl_blk->bat_celsius_temp)) + { + pwr_env_ctrl_blk->timer0_state = BATTERY_CALIBRATION; + pwr_current_loop_cal(); + } + else + { + /* informs the upper layer that the battery temperature is not correct */ + pwr_send_charge_not_possible_event(BAT_TEMP_OUTSIDE_LIMITS); + if (SPI_GBL_INFO_PTR->is_gsm_on == FALSE) /* GSM OFF */ + { +#if (ANLG_FAM == 1) + ABB_Write_Register_on_page(PAGE0, VRPCCTL2, 0x00EE); +#elif (ANLG_FAM == 2) + ABB_Write_Register_on_page(PAGE0, VRPCDEV, 0x0001); +#endif + } + else + { + pwr_handle_discharge(); + } + } +} + + + + +/******************************************************************************* +** Function pwr_battery_qualification +** +** Description Battery open and short tests +** +*******************************************************************************/ +void pwr_battery_qualification(void) +{ + rvf_send_trace("Battery qualification",21, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + pwr_env_ctrl_blk->timer0_state = BATTERY_SHORT_TEST; + + /* Short test */ + pwr_start_CI_charging(CONSTANT_CURRENT_VALUE); + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* Start VBAT channel conversion by writing in the result register */ + ABB_Write_Register_on_page(PAGE0, VBATREG, 0x0000); + rvf_start_timer (SPI_TIMER0, + RVF_MS_TO_TICKS (SPI_TIMER0_INTERVAL_1), + FALSE); + } + else + { + /* Let time for the L1 to ask for new AD conversions */ + rvf_start_timer (SPI_TIMER0, + RVF_MS_TO_TICKS (SPI_TIMER0_INTERVAL_2), + FALSE); + } + +} + + + +/********************************************************************************/ +/* */ +/* Function Name: pwr_start_fast_charge */ +/* */ +/* Purpose: Starts the fast charging process for Li-ion batteries */ +/* */ +/* */ +/********************************************************************************/ +void pwr_start_fast_charge(void) +{ + UINT16 i2v_dac_offset_mA; + + /* Informs the upper layer that the charging process has started */ + pwr_send_CI_charge_start_event(); + + /* Connect resistive bridge to main battery */ + ABB_Write_Register_on_page(PAGE0, BCICTL1, MESBAT); + + /* Start the constant current charging */ + i2v_dac_offset_mA = (UINT16)((MADC_CURRENT_STEP*pwr_env_ctrl_blk->i2v_madc_offset)/1000); + + pwr_start_CI_charging((unsigned short)(CONSTANT_CURRENT_VALUE + i2v_dac_offset_mA)); + + rvf_start_timer (SPI_TIMER1, + RVF_MS_TO_TICKS (SPI_TIMER1_INTERVAL), + FALSE); +} + + + +/********************************************************************************/ +/* */ +/* Function Name: pwr_short_test_timer_process */ +/* */ +/* Purpose: */ +/* */ +/* */ +/********************************************************************************/ +void pwr_short_test_timer_process(void) +{ + UINT16 Vbat_test; + + rvf_send_trace("TIMER0: Battery short test",26, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + /* Read ADC result */ + Vbat_test = ABB_Read_Register_on_page(PAGE0, VBATREG); + rvf_send_trace("Vbat (MADC code) ",17, Vbat_test, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + pwr_stop_charging(); + + if (Vbat_test > 0) + { + pwr_env_ctrl_blk->timer0_state = BATTERY_OPEN_TEST; + + /* Start open test */ + pwr_start_CV_charging(CONSTANT_VOLTAGE_VALUE); + rvf_delay(RVF_MS_TO_TICKS(5)); + + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* start ICHG channel conversion by writing in the result register */ + ABB_Write_Register_on_page(PAGE0, ICHGREG, 0x0000); + rvf_start_timer (SPI_TIMER0, + RVF_MS_TO_TICKS (SPI_TIMER0_INTERVAL_1), + FALSE); + } + else + { + /* Let time for the L1 to ask for new AD conversions */ + rvf_start_timer (SPI_TIMER0, + RVF_MS_TO_TICKS (SPI_TIMER0_INTERVAL_2), + FALSE); + } + } + else + { + rvf_send_trace("Short battery",13, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + /* informs the upper layer that the short test has failed */ + pwr_send_charge_not_possible_event(BAT_SHORT_TEST_FAILED); + if (SPI_GBL_INFO_PTR->is_gsm_on == FALSE) /* GSM OFF */ + { +#if (ANLG_FAM == 1) + ABB_Write_Register_on_page(PAGE0, VRPCCTL2, 0x00EE); +#elif (ANLG_FAM == 2) + ABB_Write_Register_on_page(PAGE0, VRPCDEV, 0x0001); +#endif + } + else + { + pwr_handle_discharge(); + } + } +} + + + +/********************************************************************************/ +/* */ +/* Function Name: pwr_open_test_timer_process */ +/* */ +/* Purpose: */ +/* */ +/* */ +/********************************************************************************/ +void pwr_open_test_timer_process(void) +{ + UINT16 Ichg_test; + + rvf_send_trace("TIMER0: Battery open test",25, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + /* Read ADC result */ + Ichg_test = ABB_Read_Register_on_page(PAGE0, ICHGREG); + rvf_send_trace("Charge current (MADC code) ",27, Ichg_test, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + pwr_stop_charging(); + + if (Ichg_test > 0) /* Battery OK */ + { + rvf_send_trace("Battery OK",10, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + /* Check if the initial battery temperature is correct */ + pwr_env_ctrl_blk->charging_state = TESTING_BATTERY; + pwr_get_battery_temperature(); + } + + else /* Open battery */ + { + rvf_send_trace("Open battery",12, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + /* informs the upper layer that the open test has failed */ + pwr_send_charge_not_possible_event(BAT_OPEN_TEST_FAILED); + if (SPI_GBL_INFO_PTR->is_gsm_on == FALSE) /* GSM OFF */ + { +#if (ANLG_FAM == 1) + ABB_Write_Register_on_page(PAGE0, VRPCCTL2, 0x00EE); +#elif (ANLG_FAM == 2) + ABB_Write_Register_on_page(PAGE0, VRPCDEV, 0x0001); +#endif + } + else + { + pwr_handle_discharge(); + } + } +} + + + +/********************************************************************************/ +/* */ +/* Function Name: pwr_cal_timer_process */ +/* */ +/* Purpose: */ +/* */ +/* */ +/********************************************************************************/ +void pwr_cal_timer_process(void) +{ + rvf_send_trace("TIMER0: Battery calibration",27, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + pwr_env_ctrl_blk->i2v_madc_offset = ABB_Read_Register_on_page(PAGE0, ICHGREG); + + rvf_send_trace("i2v offset (MADC code) ", 23, pwr_env_ctrl_blk->i2v_madc_offset, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + pwr_stop_charging(); + +#if (ANLG_FAM == 2) + if (pwr_env_ctrl_blk->i2v_madc_offset == 0) + { + /* IOTA: the offset can be made positive and minimized programming */ + /* the OFFEN and OFFSN bits in the BCICONF register */ + ABB_Write_Register_on_page(PAGE1, BCICONF, 0x001F); + pwr_current_loop_cal(); + } + else + { + /* the i2v calibration must be done before this initialization */ + pwr_env_ctrl_blk->madc_eoc_current_code = (UINT16)(1000 * END_OF_CHARGE_I / MADC_CURRENT_STEP) + pwr_env_ctrl_blk->i2v_madc_offset; + + rvf_send_trace("End of charge current (MADC code) ", 34, pwr_env_ctrl_blk->madc_eoc_current_code, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + /* Start the fast charging cycle */ + pwr_start_fast_charge(); + } + +#elif (ANLG_FAM == 1) + /* the i2v calibration must be done before this initialization */ + pwr_env_ctrl_blk->madc_eoc_current_code = (UINT16)(1000 * END_OF_CHARGE_I / MADC_CURRENT_STEP) + pwr_env_ctrl_blk->i2v_madc_offset; + + rvf_send_trace("End of charge current (MADC code) ", 34, pwr_env_ctrl_blk->madc_eoc_current_code, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + /* Start the fast charging cycle */ + pwr_start_fast_charge(); + +#endif /* #if (ANLG_FAM == 2) */ +} + + + + +/********************************************************************************/ +/* */ +/* Function Name: pwr_CI_charge_process */ +/* */ +/* Purpose: */ +/* */ +/* */ +/********************************************************************************/ +void pwr_CI_charge_process(void) +{ + UINT16 vbat; + UINT16 ichg; + + /* Check if the battery temperature is still correct */ + if (pwr_bat_temp_within_limits(pwr_env_ctrl_blk->bat_celsius_temp)) + { + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* start VBAT channel conversion by writing in the result register */ + ABB_Write_Register_on_page(PAGE0, VBATREG, 0x0000); + rvf_delay(RVF_MS_TO_TICKS(5)); + vbat = ABB_Read_Register_on_page(PAGE0, VBATREG); + } + else + { + /* Use the ADC conversions results from the L1 */ + vbat = SPI_GBL_INFO_PTR->adc_result[0]; + } + + rvf_send_trace("TIMER1", 6, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + rvf_send_trace("Vbat (MADC code) ", 17, vbat, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + if (vbat < pwr_env_ctrl_blk->max_voltage_code) + { + rvf_start_timer (SPI_TIMER1, RVF_MS_TO_TICKS (SPI_TIMER1_INTERVAL), FALSE); + } + else + { + pwr_stop_charging(); + pwr_send_CV_charge_start_event(); + pwr_start_CV_charging(CONSTANT_VOLTAGE_VALUE); + rvf_start_timer (SPI_TIMER2, RVF_MS_TO_TICKS (SPI_TIMER2_INTERVAL), FALSE); + } + + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* start ICHG channel conversion by writing in the result register */ + ABB_Write_Register_on_page(PAGE0, ICHGREG, 0x0000); + rvf_delay(RVF_MS_TO_TICKS(5)); + ichg = ABB_Read_Register_on_page(PAGE0, ICHGREG); + } + else + { + ichg = SPI_GBL_INFO_PTR->adc_result[2]; + } + + rvf_send_trace("Ichg (MADC code) ", 17, ichg, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + } + + else /* battery temperature not correct !!! */ + { + pwr_stop_charging(); + rvf_send_trace("Battery temperature not correct! ",33, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + /* informs the upper layer that the battery temperature is not correct */ + pwr_send_charge_not_possible_event(BAT_TEMP_OUTSIDE_LIMITS); + + if (SPI_GBL_INFO_PTR->is_gsm_on == FALSE) /* GSM OFF */ + { +#if (ANLG_FAM == 1) + ABB_Write_Register_on_page(PAGE0, VRPCCTL2, 0x00EE); +#elif (ANLG_FAM == 2) + ABB_Write_Register_on_page(PAGE0, VRPCDEV, 0x0001); +#endif + } + else + { + pwr_handle_discharge(); + } + } + } + + + + +/********************************************************************************/ +/* */ +/* Function Name: pwr_CI_charge_timer_process */ +/* */ +/* Purpose: */ +/* */ +/* */ +/********************************************************************************/ +void pwr_CI_charge_timer_process(void) +{ + UINT16 status_value; + + status_value = ABB_Read_Status(); + if (status_value & CHGPRES) /* if the charger is still plugged */ + { + pwr_get_battery_temperature(); + } + else + { + /* informs the upper layer that the charging process has stopped */ + pwr_send_charge_stop_event(); + } +} + + + + +/********************************************************************************/ +/* */ +/* Function Name: pwr_CV_charge_process */ +/* */ +/* Purpose: */ +/* */ +/* */ +/********************************************************************************/ +void pwr_CV_charge_process(void) +{ + UINT16 vbat; + UINT16 ichg; + + /* Check if the battery temperature is still correct */ + if (pwr_bat_temp_within_limits(pwr_env_ctrl_blk->bat_celsius_temp)) + { + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* start ICHG channel conversion by writing in the result register */ + ABB_Write_Register_on_page(PAGE0, ICHGREG, 0x0000); + rvf_delay(RVF_MS_TO_TICKS(5)); + ichg = ABB_Read_Register_on_page(PAGE0, ICHGREG); + } + else + { + ichg = SPI_GBL_INFO_PTR->adc_result[2]; + } + + rvf_send_trace("TIMER2",6, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + rvf_send_trace("Ichg (MADC code) ", 17, ichg, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* start VBAT channel conversion by writing in the result register */ + ABB_Write_Register_on_page(PAGE0, VBATREG, 0x0000); + rvf_delay(RVF_MS_TO_TICKS(5)); + vbat = ABB_Read_Register_on_page(PAGE0, VBATREG); + } + else + { + /* Use the ADC results asked for by the layer 1 */ + vbat = SPI_GBL_INFO_PTR->adc_result[0]; + } + + rvf_send_trace("Vbat (MADC code) ", 17, vbat, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + if (ichg > pwr_env_ctrl_blk->madc_eoc_current_code) + { + rvf_start_timer (SPI_TIMER2, RVF_MS_TO_TICKS (SPI_TIMER2_INTERVAL), FALSE); + } + else + { + pwr_stop_charging(); + /* informs the upper layer that the charging process has stopped */ + pwr_send_charge_stop_event(); + rvf_send_trace("Fast charge termination criterion",33, NULL_PARAM, + RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + + if (SPI_GBL_INFO_PTR->is_gsm_on == FALSE) /* GSM OFF */ + { +#if (ANLG_FAM == 1) + ABB_Write_Register_on_page(PAGE0, VRPCCTL2, 0x00EE); +#elif (ANLG_FAM == 2) + ABB_Write_Register_on_page(PAGE0, VRPCDEV, 0x0001); +#endif + } + else + { + pwr_handle_discharge(); + } + } + } + + else /* Battery temperature not correct !!! */ + { + pwr_stop_charging(); + rvf_send_trace("Battery temperature not correct! ",33, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + /* informs the upper layer that the battery temperature is not correct */ + pwr_send_charge_not_possible_event(BAT_TEMP_OUTSIDE_LIMITS); + + if (SPI_GBL_INFO_PTR->is_gsm_on == FALSE) /* GSM OFF */ + { +#if (ANLG_FAM == 1) + ABB_Write_Register_on_page(PAGE0, VRPCCTL2, 0x00EE); +#elif (ANLG_FAM == 2) + ABB_Write_Register_on_page(PAGE0, VRPCDEV, 0x0001); +#endif + } + else + { + pwr_handle_discharge(); + } + } +} + + + + +/********************************************************************************/ +/* */ +/* Function Name: pwr_CV_charge_timer_process */ +/* */ +/* Purpose: */ +/* */ +/* */ +/********************************************************************************/ +void pwr_CV_charge_timer_process(void) +{ + UINT16 status_value; + + status_value = ABB_Read_Status(); + if (status_value & CHGPRES) /* if the charger is still plugged */ + { + /* Control the battery temperature */ + pwr_get_battery_temperature(); + } + else + { + /* informs the upper layer that the charging process has stopped */ + pwr_send_charge_stop_event(); + } +} + + + + +/********************************************************************************/ +/* */ +/* Function Name: pwr_bat_test_timer_process */ +/* */ +/* Purpose: */ +/* */ +/* */ +/********************************************************************************/ +void pwr_bat_test_timer_process(void) +{ + if (pwr_env_ctrl_blk->timer0_state == BATTERY_TYPE_TEST) + { + pwr_type_test_timer_process(); + } + else if (pwr_env_ctrl_blk->timer0_state == BATTERY_SHORT_TEST) + { + pwr_short_test_timer_process(); + } + else if (pwr_env_ctrl_blk->timer0_state == BATTERY_OPEN_TEST) + { + pwr_open_test_timer_process(); + } + else if (pwr_env_ctrl_blk->timer0_state == BATTERY_50UA_TEMP_TEST) + { + pwr_bat_50uA_temp_test_timer_process(); + } + else if (pwr_env_ctrl_blk->timer0_state == BATTERY_10UA_TEMP_TEST) + { + pwr_bat_10uA_temp_test_timer_process(); + } + else if (pwr_env_ctrl_blk->timer0_state == BATTERY_CALIBRATION) + { + /* end of current loop calibration */ + pwr_cal_timer_process(); + } +} + +#endif /* #ifdef RVM_PWR_SWE */ + +