/************************************************************************** * * Copyright (c) 2019-2021 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 * * @author (last) Quang Nguyen * @date (last) 24-Feb-2021 * * @author (original) Quang Nguyen * @date (original) 24-Feb-2021 * ***************************************************************************/ #include "i2c.h" #include "Battery.h" #include "Timers.h" /** * @addtogroup Battery * @{ */ // ********** private definitions ********** #define BATTERY_SLAVE_ADDRESS 0x9 ///< Battery charger controller device address. #define BATTERY_STATUS_CMD 0x13 ///< Command to get battery status. #define BATTERY_STATUS_AC_PRESENT_MASK 0x8000 ///< Battery status AC present bit mask. #define BATTERY_COMM_TIME_OUT_MS 1 ///< Battery communication time out in ms. #define BATTERY_MONITOR_INTERVAL_MS MS_PER_SECOND ///< Battery monitor interval in ms. #define AC_POWER_LOST_PERSISTENT_COUNT 3 ///< AC power lost persistent count before alarming. // ********** private data ********** static U16 batteryStatus = 0; ///< Battery current status. static U32 lastBatteryMonitorTime = 0; ///< Previous battery monitor time. static U32 lostACPowerPersistentCount = 0; ///< Persistent count for AC power lost alarm. // ********** private function prototypes ********** static void setupI2CDriver( void ); static BOOL waitForTxReady( void ); static BOOL getBatteryStatus( void ); /*********************************************************************//** * @brief * The initBattery function initializes the Battery module. * @details Inputs: none * @details Outputs: Battery module is initialized. * @return none *************************************************************************/ void initBattery( void ) { setupI2CDriver(); i2cSetSlaveAdd( i2cREG1, BATTERY_SLAVE_ADDRESS ); } /*********************************************************************//** * @brief * The execBatteryMonitor function monitors the battery status. * @details Inputs: batteryMonitorTimerCounter * @details Outputs: monitor battery status * @return none *************************************************************************/ void execBatteryMonitor( void ) { if ( TRUE == didTimeout( lastBatteryMonitorTime, BATTERY_MONITOR_INTERVAL_MS ) ) { lastBatteryMonitorTime = getMSTimerCount(); #ifndef DISABLE_BATT_COMM if ( TRUE == getBatteryStatus() ) { if ( ( batteryStatus & BATTERY_STATUS_AC_PRESENT_MASK ) == 0 ) { if ( ++lostACPowerPersistentCount >= AC_POWER_LOST_PERSISTENT_COUNT ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_AC_POWER_LOST, (U32)batteryStatus ); } } else { lostACPowerPersistentCount = 0; } } else { // Reset i2c bus if cannot communicate with battery charger setupI2CDriver(); } #endif } } /*********************************************************************//** * @brief * The setupI2CDriver function setups i2c driver in repeat mode to be * compatiable with SMBus protocol. * @details Inputs: none * @details Outputs: setup i2c driver in repeat mode * @return none *************************************************************************/ static void setupI2CDriver( void ) { i2cREG1->MDR = (U32)I2C_RESET_IN; i2cREG1->MDR = (U32)( I2C_MASTER | I2C_TRANSMITTER | I2C_7BIT_AMODE | I2C_REPEATMODE | I2C_8_BIT ); i2cREG1->MDR |= (U32)I2C_RESET_OUT; } /*********************************************************************//** * @brief * The waitForTxReady function checks for transmit ready status from i2c * driver with a timeout. * @details Inputs: none * @details Outputs: checked i2c transmit ready status * @return TRUE if timeout, otherwise FALSE *************************************************************************/ static BOOL waitForTxReady( void ) { U32 const startTime = getMSTimerCount(); BOOL timeout = FALSE; while ( ( 0 == i2cIsTxReady( i2cREG1 ) ) && ( FALSE == timeout ) ) { timeout = didTimeout( startTime, BATTERY_COMM_TIME_OUT_MS ); } return timeout; } /*********************************************************************//** * @brief * The waitForRxReady function checks for receive ready status from i2c * driver with a timeout. * @details Inputs: none * @details Outputs: checked i2c receive ready status * @return TRUE if timeout, otherwise FALSE *************************************************************************/ static BOOL waitForRxReady( void ) { U32 const startTime = getMSTimerCount(); BOOL timeout = FALSE; while ( ( 0 == i2cIsRxReady( i2cREG1 ) ) && ( FALSE == timeout ) ) { timeout = didTimeout( startTime, BATTERY_COMM_TIME_OUT_MS ); } return timeout; } /*********************************************************************//** * @brief * The getBatteryStatus function send command to smart battery charger controller * interface to get battery status. * @details Inputs: none * @details Outputs: get the current battery status * @return TRUE if received battery status, otherwise FALSE *************************************************************************/ static BOOL getBatteryStatus( void ) { BOOL result = FALSE; if ( FALSE == i2cIsBusBusy( i2cREG1 ) ) { i2cSetMode( i2cREG1, I2C_MASTER ); i2cSetDirection( i2cREG1, I2C_TRANSMITTER ); i2cSetStart( i2cREG1 ); if ( FALSE == waitForTxReady() ) { i2cSendByte( i2cREG1, BATTERY_STATUS_CMD ); } // Wait until command has been transmitted before start receiving command response if ( FALSE == waitForTxReady() ) { i2cSetDirection( i2cREG1, I2C_RECEIVER ); i2cSetStart( i2cREG1 ); if ( FALSE == waitForRxReady() ) { // Due to the double buffer, the master must generate the stop condition after the (message size - 1)th data i2cSetStop( i2cREG1 ); batteryStatus = i2cReceiveByte( i2cREG1); if ( FALSE == waitForRxReady() ) { batteryStatus = ( batteryStatus | ( i2cReceiveByte( i2cREG1) << 8 ) ); result = TRUE; } } } } return result; } /**@}*/