FreeCalypso > hg > fc-tourmaline
diff src/cs/drivers/drv_app/pwr/pwr_cust.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_cust.c Fri Oct 16 06:23:26 2020 +0000 @@ -0,0 +1,551 @@ +/******************************************************************************* + * + * pwr_cust.c + * + * Purpose: This file contains functions for battery management. + * These functions can be modified by the customer. + * + * 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 "abb/abb.h" +#include "rvm/rvm_use_id_list.h" +#include "pwr/pwr_messages.h" +#include "rvf/rvf_api.h" +#include "pwr/pwr_cust.h" +#include "pwr/pwr_env.h" +#include "pwr/pwr_analog_dev.h" +#include "spi/spi_env.h" +#include "spi/spi_task.h" +#include "pwr/pwr_liion_cha.h" +#include "pwr/pwr_disch.h" + +/* Caution: keep ascending order in the temperature arrays !!! */ + +const INT16 BAT_Celsius_temp_10uA[4]= +{ + -10, -5, 0, 5 +}; +const UINT16 BAT_MADC_temp_10uA[4]= +{ + 0x13F, 0x103, 0xCB, 0x9C +}; +const INT16 BAT_Celsius_temp_50uA[13]= +{ + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60 +}; +const UINT16 BAT_MADC_temp_50uA[13]= +{ + 0x351, 0x2AD, 0x22E, 0x1C4, 0x169, 0x128, 0xF9, 0xCB, 0x96, 0x83, 0x68, 0x58, 0x4A +}; + + +/* Correpondence between the battery voltage and the remaining capacity in the battery */ +/* The voltages have to be expressed in mV units */ +/* The capacities are percentages of the total capacity */ +/* Caution: keep this order in the array !!!! (in voltage (or capacity) descending order) */ + +const T_PWR_THRESHOLDS a_pwr_thresholds[NB_THRESHOLDS]= +{{4200,100}, {4000,75}, {3970,50}, {3950,25}, {3900,15}, {3870,10}}; + + + +/* Global variable */ +extern T_SPI_GBL_INFO *SPI_GBL_INFO_PTR; + + + +/******************************************************************************* +** Function pwr_adc_to_mvolt +** +** Description Converts the MADC voltage reading into voltage in mVolt +** +** Warning: The offsets are not taken into account !!! +** +*******************************************************************************/ +UINT16 pwr_adc_to_mvolt(UINT16 voltage_madc) +{ + UINT16 voltage_mvolt; + + /* Note: /1000 because MADC_VOLTAGE_STEP is expressed in uV */ + voltage_mvolt = (voltage_madc * MADC_VOLTAGE_STEP * 4) / 1000; + + /* return voltage in mVolt */ + return (voltage_mvolt); +} + + +/******************************************************************************* +** Function pwr_adc_to_mA +** +** Description Converts the MADC current reading into current in mA +** +** Warning: The offsets are not taken into account !!! +** +*******************************************************************************/ +UINT16 pwr_adc_to_mA(UINT16 current_madc) +{ +UINT16 current_mA; + + /* Note: /1000 because MADC_VOLTAGE_STEP is expressed in uA */ + current_mA = (current_madc * MADC_CURRENT_STEP) / 1000; + + /* return current in mA */ + return (current_mA); +} + + + + + +/******************************************************************************* +** Function pwr_bat_temp_within_limits +** +** Description Check if the battery temperature is within limits +** +** Parameter battery_temperature : battery temperature un Celsius degrees +** +*******************************************************************************/ +UINT8 pwr_bat_temp_within_limits(INT16 battery_temperature) +{ + rvf_send_trace("Battery temperature (Celsius degrees) ", 38, battery_temperature, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + if ((battery_temperature < BAT_TEMPERATURE_MAX) && + (battery_temperature > BAT_TEMPERATURE_MIN)) + { + rvf_send_trace("Battery temperature within limits",33, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, PWR_USE_ID); + return (TRUE); + } + + rvf_send_trace("Battery temperature outside limits",34, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_MEDIUM, PWR_USE_ID); + return (FALSE); +} + + + +/******************************************************************************* +** Function pwr_madc_to_Celius_conv +** +** Description Find the temperature in Celsius degrees corresponding +** to the value given by the MADC +** +*******************************************************************************/ +UINT8 pwr_madc_to_Celsius_conv(UINT8 bias_current, UINT16 madc_temp, INT16 *celsius_temp) +{ + UINT8 last_index, i; + const UINT16 *MADC_temp_array; + const INT16 *celsius_temp_array; + UINT16 madc_diff; + UINT16 madc_inc; + UINT16 celsius_inc; + + /* choose the table */ + switch(bias_current) + { + case THEN_10uA: + MADC_temp_array = BAT_MADC_temp_10uA; + celsius_temp_array = BAT_Celsius_temp_10uA; + /* get last index of the lookup table array(s) */ + last_index = sizeof(BAT_MADC_temp_10uA)/sizeof(BAT_MADC_temp_10uA[0]); + break; + + case THEN_50uA: + MADC_temp_array = BAT_MADC_temp_50uA; + celsius_temp_array = BAT_Celsius_temp_50uA; + /* get last index of the lookup table array(s) */ + last_index = sizeof(BAT_MADC_temp_50uA)/sizeof(BAT_MADC_temp_50uA[0]); + break; + + default: return (FALSE); + } + + /* check the limits */ + if((madc_temp > MADC_temp_array[0]) || (madc_temp < MADC_temp_array[last_index-1])) + { + return (FALSE); + } + + + /* find the two points between which the given point lies */ + for(i=0; i<last_index; i++) + { + if(madc_temp >= MADC_temp_array[i]) + { + if(i==0) + { + *celsius_temp = celsius_temp_array[0]; + return (TRUE); + } + + /* the value is between MADC_temp_array[i] and MADC_temp_array[i-1] */ + /* interpolate to get a more precise value */ + + madc_inc = MADC_temp_array[i-1] - MADC_temp_array[i]; + celsius_inc = celsius_temp_array[1] - celsius_temp_array[0]; /* positive value */ + + /* difference between the given point and the first madc value below this point */ + madc_diff = madc_temp - MADC_temp_array[i]; + + *celsius_temp = celsius_temp_array[i] - (madc_diff*celsius_inc)/madc_inc; + + return (TRUE); + } + + /* else, try a smaller value */ + } + + return (FALSE); +} + + + +/******************************************************************************* +** Function pwr_get_battery_temperature +** +** Description Start MADC temperature reading +** +** Note If the used battery does not allow to make a temperature +** measurement, the body of this function can be replaced +** by just a "return" with a temperature (in Celsius degrees) +** between BAT_TEMPERATURE_MIN and BAT_TEMPERATURE_MAX. +*******************************************************************************/ +void pwr_get_battery_temperature(void) +{ + + /* set the bias current to 50uA */ + ABB_Write_Register_on_page(PAGE0, BCICTL1, THEN_50uA); + rvf_delay(RVF_MS_TO_TICKS(5)); + + pwr_env_ctrl_blk->timer0_state = BATTERY_50UA_TEMP_TEST; + + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* start ADIN2REG channel conversion by writing in the result register */ + ABB_Write_Register_on_page(PAGE0, ADIN2REG, 0x0000); + rvf_start_timer (SPI_TIMER0, + RVF_MS_TO_TICKS (SPI_TIMER0_INTERVAL_1), + FALSE); + } + else /* The L1 asks for ADC conversions */ + { + /* 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 pwr_bat_50uA_temp_test_timer_process +** +** Description +** +** +*******************************************************************************/ +void pwr_bat_50uA_temp_test_timer_process(void) +{ + UINT16 bat_madc_temp; + + rvf_send_trace("TIMER0: Battery 50uA temp test",30, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + pwr_env_ctrl_blk->bat_celsius_temp = (INT16)(0xFFFF); + + /* Read ADC result */ + bat_madc_temp = ABB_Read_Register_on_page(PAGE0, ADIN2REG); + + /* MADC value to Celsius degrees conversion */ + if (!pwr_madc_to_Celsius_conv(THEN_50uA, bat_madc_temp, &(pwr_env_ctrl_blk->bat_celsius_temp))) + { + /* outside the 50uA temp range */ + /* set the bias current to 10uA */ + + pwr_env_ctrl_blk->timer0_state = BATTERY_10UA_TEMP_TEST; + + ABB_Write_Register_on_page(PAGE0, BCICTL1, THEN_10uA); + rvf_delay(RVF_MS_TO_TICKS(5)); + + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* start ADIN2REG channel conversion by writing in the result register */ + ABB_Write_Register_on_page(PAGE0, ADIN2REG, 0x0000); + rvf_start_timer (SPI_TIMER0, + RVF_MS_TO_TICKS (SPI_TIMER0_INTERVAL_1), + FALSE); + } + else /* The L1 asks for ADC conversions */ + { + /* 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 + { + /* The battery temp is inside the 50uA temp range */ + /* Turn OFF the current source */ + ABB_Write_Register_on_page(PAGE0, BCICTL1, MESBAT); + + /* Go ahead */ + if (pwr_env_ctrl_blk->charging_state == CI_CHARGE_STARTED) + { + /* temperature measurement during CI charge */ + pwr_CI_charge_process(); + } + else if (pwr_env_ctrl_blk->charging_state == CV_CHARGE_STARTED) + { + /* temperature measurement during CV charge */ + pwr_CV_charge_process(); + } + else if (pwr_env_ctrl_blk->charging_state == TESTING_BATTERY) + { + /* temperature measurement before calibration */ + pwr_calibration_process(); + } + else + { + /* temperature measurement for battery information */ + pwr_get_bat_info(); + } + } +} + + +/******************************************************************************* +** Function pwr_bat_10uA_temp_test_timer_process +** +** Description +** +** +*******************************************************************************/ +void pwr_bat_10uA_temp_test_timer_process(void) +{ + UINT16 bat_madc_temp; + + rvf_send_trace("TIMER0: Battery 10uA temp test",30, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + pwr_env_ctrl_blk->bat_celsius_temp = (INT16)(0xFFFF); + + bat_madc_temp = ABB_Read_Register_on_page(PAGE0, ADIN2REG); + + /* MADC value to Celsius degrees conversion */ + if (!pwr_madc_to_Celsius_conv(THEN_10uA, bat_madc_temp, &(pwr_env_ctrl_blk->bat_celsius_temp))) + { + /* ERROR: Reading out of limits */ + rvf_send_trace("Battery temperature reading out of limits", 41, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + /* turn OFF the current source */ + ABB_Write_Register_on_page(PAGE0, BCICTL1, MESBAT); + + pwr_stop_charging(); + + /* 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(); + } + } + + else + { + /* The battery temperature is inside the 10uA temp range */ + /* turn OFF the current source */ + ABB_Write_Register_on_page(PAGE0, BCICTL1, MESBAT); + + /* Go ahead */ + if (pwr_env_ctrl_blk->charging_state == CI_CHARGE_STARTED) + { + /* temperature measurement during CI charge */ + pwr_CI_charge_process(); + } + else if (pwr_env_ctrl_blk->charging_state == CV_CHARGE_STARTED) + { + /* temperature measurement during CV charge */ + pwr_CV_charge_process(); + } + else if (pwr_env_ctrl_blk->charging_state == TESTING_BATTERY) + { + /* temperature measurement before calibration */ + pwr_calibration_process(); + } + else + { + /* temperature measurement for battery information */ + pwr_get_bat_info(); + } + } +} + + + + +/******************************************************************************* +** Function pwr_get_battery_type +** +** Description Return the type of the battery +** +** Note If the used battery does not allow to make a battery type +** SW detection, the body of this function can be replaced +** by the last 2 lines +** +*******************************************************************************/ +void pwr_get_battery_type(void) +{ + + /* enable bias current for main battery type reading + ABB_Write_Register_on_page(PAGE0, BCICTL1, 0x0081); + rvf_delay(RVF_MS_TO_TICKS(5)); + + pwr_env_ctrl_blk->timer0_state = BATTERY_TYPE_TEST; + + if (SPI_GBL_INFO_PTR->is_adc_on == FALSE) + { + /* start ADIN1REG channel conversion by writing in the result register + ABB_Write_Register_on_page(PAGE0, ADIN1REG, 0x0000); + rvf_start_timer (SPI_TIMER0, + RVF_MS_TO_TICKS (SPI_TIMER0_INTERVAL_1), + FALSE); + } + else /* The L1 asks for ADC conversions + { + /* 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); + } + */ + + + + /****************************************/ + /* If the battery can not be detected, */ + /* the code above has to be replaced by */ + /* those 2 lines (with the type of the */ + /* used battery). */ + /****************************************/ + + pwr_env_ctrl_blk->bat_type = LI_ION; + + /* Check if the battery is OK */ + pwr_battery_qualification(); + + +} + + + +/******************************************************************************* +** Function pwr_type_test_timer_process +** +** Description +** +** +*******************************************************************************/ +void pwr_type_test_timer_process(void) +{ + UINT16 bat_type_voltage; + + rvf_send_trace("TIMER0: Battery type test",25, NULL_PARAM, RV_TRACE_LEVEL_WARNING, PWR_USE_ID); + + bat_type_voltage = ABB_Read_Register_on_page(PAGE0, ADIN1REG); + + /* turn OFF the current source */ + ABB_Write_Register_on_page(PAGE0, BCICTL1, MESBAT); + + if ((bat_type_voltage >= BAT_TYPE_LI_ION_MIN) && + (bat_type_voltage <= BAT_TYPE_LI_ION_MAX)) /* Li-ion batteries */ + { + pwr_env_ctrl_blk->bat_type = LI_ION; + + /* Check if the battery is OK */ + pwr_battery_qualification(); + + } + + else /* battery type unknown */ + { + pwr_env_ctrl_blk->bat_type = UNKNOWN; + + /* informs the upper layer that the battery type is unknown */ + pwr_send_charge_not_possible_event(BAT_TYPE_UNKNOWN); + 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_get_capacity_vs_voltage +** +** Description Compares the battery voltage with the thresholds given in the +** a_pwr_thresholds array and returns the remaining capacity +** corresponding to the threshold above this voltage. +** +** Parameters: UINT16 bat_voltage: battery voltage in mV !!! +** +*******************************************************************************/ +T_PWR_PERCENT pwr_get_capacity_vs_voltage(UINT16 bat_voltage) +{ + volatile UINT16 i; + T_PWR_PERCENT remaining_capacity; + + for(i=0; i<NB_THRESHOLDS; i++) + { + if(bat_voltage > a_pwr_thresholds[i].bat_voltage) + { + if(i==0) + { + remaining_capacity = a_pwr_thresholds[0].remain_capa; + } + else + { + remaining_capacity = a_pwr_thresholds[i-1].remain_capa; + } + + return (remaining_capacity); + } + /* else, try the next threshold */ + } + + if(i==NB_THRESHOLDS) + { + /* battery voltage below the last threshold */ + remaining_capacity = a_pwr_thresholds[i-1].remain_capa; + return (remaining_capacity); + } + + return 0; /* dummy return */ +} + +#endif /* #ifdef RVM_PWR_SWE */