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 */