FreeCalypso > hg > fc-tourmaline
view src/cs/drivers/drv_app/pwr/pwr_cust.c @ 261:841a848ba762
SPI SWE: clear any pending boot-time interrupts in spi_init()
Charger plug/unplug hw logic in the Iota ABB has no built-in debouncing,
thus electrical contact bounce on the charging power connection interface
produces a lot of charger plug/unplug interrupts. When we boot in
charging mode (charging power present at boot time and is presumably
the cause of Switch-ON), some bounce may occur between the initial
Iota Switch-ON action and Calypso firmware booting. By clearing any
accumulated ITSTATREG interrupts on boot, we prevent these pre-boot
interrupts from generating charger plug/unplug events to FCHG, which
would upset smooth from-boot charging.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 14 May 2021 02:49:05 +0000 |
parents | 4e78acac3d88 |
children |
line wrap: on
line source
/******************************************************************************* * * 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 */