Index: firmware/App/Drivers/Battery.c =================================================================== diff -u -r84bb8663dae71170e1743a2bed37b0aa47465b47 -r098272da7396d05816a266142e7a34b40f4d93d3 --- firmware/App/Drivers/Battery.c (.../Battery.c) (revision 84bb8663dae71170e1743a2bed37b0aa47465b47) +++ firmware/App/Drivers/Battery.c (.../Battery.c) (revision 098272da7396d05816a266142e7a34b40f4d93d3) @@ -1,23 +1,24 @@ /************************************************************************** * -* Copyright (c) 2019-2021 Diality Inc. - All Rights Reserved. +* Copyright (c) 2021-2022 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * -* @file Battery.c +* @file Battery.c * -* @author (last) Quang Nguyen -* @date (last) 24-Feb-2021 +* @author (last) Dara Navaei +* @date (last) 24-May-2022 * -* @author (original) Quang Nguyen -* @date (original) 24-Feb-2021 +* @author (original) Quang Nguyen +* @date (original) 24-Feb-2021 * ***************************************************************************/ #include "i2c.h" #include "Battery.h" +#include "SystemCommMessages.h" #include "Timers.h" /** @@ -34,29 +35,37 @@ #define BATTERY_CHARGER_STATUS_AC_PRESENT_MASK 0x8000 ///< Battery charger status AC present bit mask. #define BATTERY_PACK_REL_STATE_OF_CHARGE_CMD 0x0D ///< Command to get battery pack relative state of charge. -#define BATTERY_PACK_REMAINING_CAPACITY_CMD 0x0F ///< Command to get battery pack remaining capacity. +#define BATTERY_PACK_STATUS_CMD 0x16 ///< Command to get battery pack status. +#define BATTERY_PACK_ERROR_BITS 0x0F ///< Error codes are in the first byte. +#define BATTERY_PACK_MIN_CHARGE_PCT 50 ///< Minimum battery pack state of charge in percentage. + #define BATTERY_COMM_TIME_OUT_MS 1 ///< Battery communication time out in ms. #define BATTERY_MONITOR_INTERVAL_MS 750 ///< Battery monitor interval in ms. #define AC_POWER_LOST_PERSISTENT_COUNT 3 ///< AC power lost persistent count before alarming. +#define BATTERY_COMM_FAULT_PERSISTENTCE_COUNT 5 ///< Battery communication fault persistent count before alarming. // ********** private data ********** -static U16 batteryStatus = 0; ///< Battery current status. -static U16 batteryRelStateOfCharge_pct = 0; ///< Battery pack relative state of charge. -static U32 lastBatteryMonitorTime = 0; ///< Previous battery monitor time. -static U32 lostACPowerPersistentCount = 0; ///< Persistent count for AC power lost alarm. -static BOOL hasBatteryChargerStatus = FALSE; ///< Flag indicates if battery charger status has been obtained. - +static U16 batteryStatus = 0; ///< Battery current status. +static OVERRIDE_U32_T batteryRelStateOfCharge_pct = { 0, 0, 0, 0 }; ///< Battery pack relative state of charge. +static U16 batteryPackStatus = 0; ///< Battery pack current status. +static U32 lastBatteryMonitorTime = 0; ///< Previous battery monitor time. +static U32 lostACPowerPersistentCount = 0; ///< Persistent count for AC power lost alarm. +static BOOL hasBatteryChargerStatus = FALSE; ///< Flag indicates if battery charger status has been obtained. +static U32 commFaultPersistentCount = 0; ///< Persistence count for battery comm fault. + // ********** private function prototypes ********** +static U32 getBatteryRemainingPercent( void ); static void setupI2CDriver( void ); -static BOOL startCommTx( U32 slaveAddr ); static BOOL waitForTxReady( void ); static BOOL waitForRxReady( void ); static BOOL waitForAccessReady( void ); static void generateStopCondition( void ); -static BOOL getBatteryData( U08 command, U16 * dataPtr ); +static BOOL getBatteryData( U32 slaveAddr, U08 command, U16 * dataPtr ); +static BOOL startCommTx( U32 slaveAddr ); +static BOOL getData( U08 command, U16 * dataPtr ); /*********************************************************************//** * @brief @@ -67,18 +76,29 @@ *************************************************************************/ void initBattery( void ) { + batteryStatus = 0; + batteryRelStateOfCharge_pct.data = 0; + batteryPackStatus = 0; + lastBatteryMonitorTime = 0; + lostACPowerPersistentCount = 0; + hasBatteryChargerStatus = FALSE; + commFaultPersistentCount = 0; + setupI2CDriver(); } /*********************************************************************//** * @brief * The execBatteryMonitor function monitors the battery status. - * @details Inputs: batteryMonitorTimerCounter + * @details Inputs: lastBatteryMonitorTime, hasBatteryChargerStatus, batteryStatus, + * batteryRelStateOfCharge_pct, batteryPackStatus * @details Outputs: monitor battery status * @return none *************************************************************************/ void execBatteryMonitor( void ) { + U16 relStateOfCharge_pct; + if ( TRUE == didTimeout( lastBatteryMonitorTime, BATTERY_MONITOR_INTERVAL_MS ) ) { lastBatteryMonitorTime = getMSTimerCount(); @@ -87,56 +107,80 @@ { hasBatteryChargerStatus = TRUE; - if ( TRUE == startCommTx( BATTERY_CHARGER_SLAVE_ADDRESS ) ) + if ( TRUE == getBatteryData( BATTERY_CHARGER_SLAVE_ADDRESS, BATTERY_CHARGER_STATUS_CMD, &batteryStatus ) ) { - if ( TRUE == getBatteryData( BATTERY_CHARGER_STATUS_CMD, &batteryStatus ) ) + if ( 0 == ( batteryStatus & BATTERY_CHARGER_STATUS_AC_PRESENT_MASK ) ) { - if ( ( batteryStatus & BATTERY_CHARGER_STATUS_AC_PRESENT_MASK ) == 0 ) + if ( ++lostACPowerPersistentCount > AC_POWER_LOST_PERSISTENT_COUNT ) { - if ( ++lostACPowerPersistentCount > AC_POWER_LOST_PERSISTENT_COUNT ) - { - #ifndef DISABLE_BATT_COMM - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_AC_POWER_LOST, batteryStatus ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_AC_POWER_LOST, batteryStatus ); #endif - } } - else - { - lostACPowerPersistentCount = 0; - } } + else + { + clearAlarmCondition( ALARM_ID_HD_AC_POWER_LOST ); + lostACPowerPersistentCount = 0; + } } } else { hasBatteryChargerStatus = FALSE; - if ( TRUE == startCommTx( BATTERY_PACK_SLAVE_ADDRESS ) ) + if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_REL_STATE_OF_CHARGE_CMD, &relStateOfCharge_pct ) ) { - getBatteryData( BATTERY_PACK_REL_STATE_OF_CHARGE_CMD, &batteryRelStateOfCharge_pct ); + batteryRelStateOfCharge_pct.data = (U32)relStateOfCharge_pct; } + + if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_STATUS_CMD, &batteryPackStatus ) ) + { + if ( 0 != ( batteryPackStatus & BATTERY_PACK_ERROR_BITS ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, batteryPackStatus ); + } + } } } } /*********************************************************************//** * @brief + * The isBatteryCharged function checks if the battery is charged. + * @details Inputs: batteryRelStateOfCharge_pct + * @details Outputs: none + * @return TRUE if battery is charged, otherwise FALSE + *************************************************************************/ +BOOL isBatteryCharged( void ) +{ + return ( getBatteryRemainingPercent() > BATTERY_PACK_MIN_CHARGE_PCT ? TRUE : FALSE ); +} + +/*********************************************************************//** + * @brief * The getBatteryRemainingPercent function returns the latest battery relative * state of charge percentage. - * @details Inputs: none + * @details Inputs: batteryRelStateOfCharge_pct * @details Outputs: none * @return battery relative state of charge percentage *************************************************************************/ -U16 getBatteryRemainingPercent( void ) +static U32 getBatteryRemainingPercent( void ) { - return batteryRelStateOfCharge_pct; + U32 result = batteryRelStateOfCharge_pct.data; + + if ( OVERRIDE_KEY == batteryRelStateOfCharge_pct.override ) + { + result = batteryRelStateOfCharge_pct.ovData; + } + + return result; } /*********************************************************************//** * @brief * The setupI2CDriver function setups i2c driver in repeat mode to be - * compatiable with SMBus protocol. + * compatible with SMBus protocol. * @details Inputs: none * @details Outputs: setup i2c driver in repeat mode * @return none @@ -150,52 +194,6 @@ /*********************************************************************//** * @brief - * The startComm function starts i2c communication and verifies slave devices ack. - * @details Inputs: none - * @details Outputs: starts i2c comm in master transmit mode - * @param slaveAddr slave device address - * @return none - *************************************************************************/ -static BOOL startCommTx( U32 slaveAddr ) -{ - BOOL result = FALSE; - - i2cSetSlaveAdd( i2cREG1, slaveAddr ); - - if ( FALSE == i2cIsBusBusy( i2cREG1 ) ) - { - i2cSetDirection( i2cREG1, I2C_TRANSMITTER ); - i2cSetMode( i2cREG1, I2C_MASTER ); - i2cSetStart( i2cREG1 ); - - if ( TRUE == waitForAccessReady() ) - { - if ( 0 == ( i2cREG1->STR & ( (U32)I2C_NACK | (U32)I2C_AL ) ) ) - { - result = TRUE; - } - else - { - generateStopCondition(); -#ifndef DISABLE_BATT_COMM - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BATTERY_COMM_FAULT, slaveAddr ); -#endif - } - } - - } - - if ( FALSE == result ) - { - // Reset i2c bus if cannot communicate with battery slave devices - setupI2CDriver(); - } - - return result; -} - -/*********************************************************************//** - * @brief * The waitForTxReady function checks for transmit ready status from i2c * driver with a timeout. * @details Inputs: none @@ -278,17 +276,92 @@ /*********************************************************************//** * @brief - * The getBatteryStatus function send command to smart battery charger controller - * interface to get battery status. + * The getBatteryData function starts i2c communication with battery device + * and get data based on given command. * @details Inputs: none + * @details Outputs: get data from battery device + * @param slaveAddr battery slave device address + * @param command command to send to the slave device + * @param dataPtr data pointer to store command response data + * @return none + *************************************************************************/ +static BOOL getBatteryData( U32 slaveAddr, U08 command, U16 * dataPtr ) +{ + BOOL result = FALSE; + + if ( TRUE == startCommTx( slaveAddr ) ) + { + if ( TRUE == getData( command, dataPtr ) ) + { + result = TRUE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The startCommTx function starts i2c communication and verifies slave devices ack. + * @details Inputs: i2cREG1 + * @details Outputs: starts i2c comm in master transmit mode + * @param slaveAddr slave device address + * @return TRUE if start communication successful, otherwise FALSE + *************************************************************************/ +static BOOL startCommTx( U32 slaveAddr ) +{ + BOOL result = FALSE; + + i2cSetSlaveAdd( i2cREG1, slaveAddr ); + + if ( FALSE == i2cIsBusBusy( i2cREG1 ) ) + { + i2cSetDirection( i2cREG1, I2C_TRANSMITTER ); + i2cSetMode( i2cREG1, I2C_MASTER ); + i2cSetStart( i2cREG1 ); + + if ( TRUE == waitForAccessReady() ) + { + if ( 0 == ( i2cREG1->STR & ( (U32)I2C_NACK | (U32)I2C_AL ) ) ) + { + commFaultPersistentCount = 0; + result = TRUE; + } + else + { + generateStopCondition(); + if ( ++commFaultPersistentCount > BATTERY_COMM_FAULT_PERSISTENTCE_COUNT ) + { +#ifndef DISABLE_BATT_COMM + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BATTERY_COMM_FAULT, slaveAddr ); +#endif + } + } + } + } + + if ( FALSE == result ) + { + // Reset i2c bus if cannot communicate with battery slave devices + setupI2CDriver(); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getData function send command to battery interface to get data. + * @details Inputs: none * @details Outputs: get the battery data based on given command * @param command command to send to the slave device * @param dataPtr data pointer to store command response data - * @return TRUE if received battery status, otherwise FALSE + * @return TRUE if received battery data, otherwise FALSE *************************************************************************/ -static BOOL getBatteryData( U08 command, U16 * dataPtr ) +static BOOL getData( U08 command, U16 * dataPtr ) { BOOL result = FALSE; + U16 batteryData = 0; if ( TRUE == waitForTxReady() ) { @@ -305,11 +378,12 @@ { // Due to the double buffer, the master must generate the stop condition after the (message size - 1)th data i2cSetStop( i2cREG1 ); - *dataPtr = i2cReceiveByte( i2cREG1); + batteryData = i2cReceiveByte( i2cREG1); if ( TRUE == waitForRxReady() ) { - *dataPtr = ( *dataPtr | ( i2cReceiveByte( i2cREG1) << 8 ) ); + batteryData = ( batteryData | ( i2cReceiveByte( i2cREG1) << 8 ) ); + *dataPtr = batteryData; result = TRUE; } } @@ -318,4 +392,56 @@ return result; } + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetBatteryRemainingPercentOverride function overrides the battery + * remaining percent value. + * @details Inputs: none + * @details Outputs: batteryRelStateOfCharge_pct + * @param value override battery remaining percent + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetBatteryRemainingPercentOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + batteryRelStateOfCharge_pct.ovData = value; + batteryRelStateOfCharge_pct.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSetBatteryRemainingPercentOverride function resets the + * override of the battery remaining percent value. + * @details Inputs: none + * @details Outputs: batteryRelStateOfCharge_pct + * @param value override battery remaining percent + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSetBatteryRemainingPercentOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + batteryRelStateOfCharge_pct.override = OVERRIDE_RESET; + batteryRelStateOfCharge_pct.ovData = batteryRelStateOfCharge_pct.ovInitData; + } + + return result; +} + /**@}*/