FreeCalypso > hg > ffs-editor
view src/cs/drivers/drv_app/pwr/pwr_liion_cha.c @ 23:3ca9a198c6ee
support new FC Tourmaline C139 aftermarket FFS config
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 18 Oct 2020 02:34:21 +0000 |
parents | 92470e5d0b9e |
children |
line wrap: on
line source
/******************************************************************************* * * 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 */