/************************************************************************** * * Copyright (c) 2021-2023 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) Sean Nash * @date (last) 03-Apr-2023 * * @author (original) Quang Nguyen * @date (original) 24-Feb-2021 * ***************************************************************************/ #include "i2c.h" #include "Battery.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "Timers.h" /** * @addtogroup Battery * @{ */ // ********** private definitions ********** #define BATTERY_CHARGER_SLAVE_ADDRESS 0x09 ///< Battery charger controller device address. #define BATTERY_PACK_SLAVE_ADDRESS 0x0B ///< Battery pack device address. #define BATTERY_CHARGER_STATUS_CMD 0x13 ///< Command to get battery charger status. #define BATTERY_CHARGER_STATUS_AC_PRESENT_MASK 0x8000 ///< Battery charger status AC present bit mask. #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 2 ///< Battery communication time out in ms. #define BATTERY_MONITOR_INTERVAL_MS 247 ///< Battery monitor interval in ms. #define AC_POWER_LOST_PERSISTENT_COUNT 3 ///< AC power lost persistent count before alarming. #define BATTERY_COMM_FAULT_PERSISTENCE_COUNT 4 ///< Battery communication fault persistent count before alarming. #define BATTERY_COMM_FAULT_PERSISTENCE_TIMER ( 10 * SEC_PER_MIN * MS_PER_SECOND ) ///< Battery communication fault persistence timer. #define BATTERY_MAH_2_MWH_FACTOR 14.7F ///< Conversion factor for mAh to mWh. #define BATTERY_MIN_CAPACITY_MWH 5000.0F ///< Minimum battery capacity for starting a treatment is 10 minutes (5 Wh @ 30W). // Battery logging #define BATTERY_PACK_ADDR_REMAINING_CAPACITY_ALARM 0x01 ///< Battery pack address remaining capacity alarm. #define BATTERY_PACK_ADDR_REMAINING_TIME_ALARM 0x02 ///< Battery pack address remaining time alarm. #define BATTERY_PACK_ADDR_BATTERY_MODE 0x03 ///< Battery pack address battery mode. #define BATTERY_PACK_ADDR_AT_RATE 0x04 ///< Battery pack address at rate. #define BATTERY_PACK_ADDR_AT_RATE_TIME_TO_FULL 0x05 ///< Battery pack address at rate time to full. #define BATTERY_PACK_ADDR_AT_RATE_TIME_TO_EMPTY 0x06 ///< Battery pack address at rate time to empty. #define BATTERY_PACK_ADDR_AT_RATE_OK 0x07 ///< Battery pack address at rate ok. #define BATTERY_PACK_ADDR_TEMPERATURE 0x08 ///< Battery pack address temperature. #define BATTERY_PACK_ADDR_VOLTAGE 0x09 ///< Battery pack address voltage. #define BATTERY_PACK_ADDR_CURRENT 0x0a ///< Battery pack address current. #define BATTERY_PACK_ADDR_AVERAGE_CURRENT 0x0b ///< Battery pack address average current. #define BATTERY_PACK_ADDR_MAX_ERROR 0x0c ///< Battery pack address max error. #define BATTERY_PACK_ADDR_RELATIVE_STATE_OF_CHARGE 0x0d ///< Battery pack address relative state of charge. #define BATTERY_PACK_ADDR_ABSOLUTE_STATE_OF_CHARGE 0x0e ///< Battery pack address absolute state of charge. #define BATTERY_PACK_ADDR_REMAINING_CAPACITY 0x0f ///< Battery pack address remaining capacity. #define BATTERY_PACK_ADDR_FULL_CHARGE_CAPACITY 0x10 ///< Battery pack address full charge capacity. #define BATTERY_PACK_ADDR_RUN_TIME_TO_EMPTY 0x11 ///< Battery pack address run time to empty. #define BATTERY_PACK_ADDR_AVERAGE_TIME_TO_EMPTY 0x12 ///< Battery pack address average time to empty. #define BATTERY_PACK_ADDR_AVERAGE_TIME_TO_FULL 0x13 ///< Battery pack address average time full. #define BATTERY_PACK_ADDR_CHARGING_CURRENT 0x14 ///< Battery pack address charging current. #define BATTERY_PACK_ADDR_CHARGING_VOLTAGE 0x15 ///< Battery pack address charging voltage. #define BATTERY_PACK_ADDR_BATTERY_STATUS 0x16 ///< Battery pack address battery status. #define BATTERY_PACK_ADDR_CYCLE_COUNT 0x17 ///< Battery pack address cycle count. #define BATTERY_PACK_ADDR_DESIGN_CAPACITY 0x18 ///< Battery pack address design capacity. #define BATTERY_PACK_ADDR_DESIGN_VOLTAGE 0x19 ///< Battery pack address design voltage. #define BATTERY_PACK_ADDR_SPECIFICATION_INFO 0x1a ///< Battery pack address specification information. #define BATTERY_PACK_ADDR_MANUFACTURE_DATE 0x1b ///< Battery pack address manufacture date. #define BATTERY_PACK_ADDR_SERIAL_NUMBER 0x1c ///< Battery pack address serial number. #define BATTERY_PACK_ADDR_MANUFACTURER_NAME 0x20 ///< Battery pack address manufacture name. #define BATTERY_PACK_ADDR_DEVICE_NAME 0x21 ///< Battery pack address device name. #define BATTERY_PACK_ADDR_DEVICE_CHEMISTRY 0x22 ///< Battery pack address device chemistry. /// Persist time (in ms) for battery pack status error condition. static const U32 BATT_STATUS_ERROR_PERSIST_MS = ( 5 * MS_PER_SECOND ); /// Enumeration of battery data to be read from the battery pack or battery charger in a round-robin fashion. typedef enum BatteryManagementEnum { BEGINNING_OF_LIST = 0, ///< Start of battery data list BATTERY_PACK_REMAINING_CAPACITY1, ///< Remaining battery capacity (in mWh) (first of 5 to increase frequency of reads) BATTERY_PACK_BATTERY_STATUS1, ///< Battery pack status (first of 5 to increase frequency of reads) BATTERY_CHARGER_STATUS1, ///< Battery charger status (first of 5 to increase frequency of reads) BATTERY_PACK_REMAINING_CAPACITY_ALARM, ///< Remaining battery capacity alarm BATTERY_PACK_REMAINING_TIME_ALARM, ///< Remaining battery time alarm BATTERY_PACK_BATTERY_MODE, ///< Battery pack mode BATTERY_PACK_AT_RATE, ///< Battery pack at rate BATTERY_PACK_AT_RATE_TIME_TO_FULL, ///< Battery pack at rate time to full BATTERY_PACK_REMAINING_CAPACITY2, ///< Remaining battery capacity (in mWh) (second of 5 to increase frequency of reads) BATTERY_PACK_BATTERY_STATUS2, ///< Battery pack status (second of 5 to increase frequency of reads) BATTERY_CHARGER_STATUS2, ///< Battery charger status (second of 5 to increase frequency of reads) BATTERY_PACK_AT_RATE_TIME_TO_EMPTY, ///< Battery pack at rate time to empty BATTERY_PACK_AT_RATE_OK, ///< Battery pack at rate ok (boolean) BATTERY_PACK_TEMPERATURE, ///< Battery pack temperature (in deg K) BATTERY_PACK_VOLTAGE, ///< Battery pack terminal voltage (in mV) BATTERY_PACK_CURRENT, ///< Battery pack terminal current (in mA) BATTERY_PACK_AVERAGE_CURRENT, ///< Battery pack average terminal current (in mA - 1 minute rolling avg) BATTERY_PACK_REMAINING_CAPACITY3, ///< Remaining battery capacity (in mWh) (third of 5 to increase frequency of reads) BATTERY_PACK_BATTERY_STATUS3, ///< Battery pack status (third of 5 to increase frequency of reads) BATTERY_CHARGER_STATUS3, ///< Battery charger status (third of 5 to increase frequency of reads) BATTERY_PACK_MAX_ERROR, ///< Battery pack expected margin of error (%) in the state of charge calculation BATTERY_PACK_RELATIVE_STATE_OF_CHARGE, ///< Battery pack relative state of charge (%) (relative to full charge capacity) BATTERY_PACK_ABSOLUTE_STATE_OF_CHARGE, ///< Battery pack absolute state of charge (%) (relative to design capacity) BATTERY_PACK_FULL_CHARGE_CAPACITY, ///< Battery pack full charge capacity (in mWh) BATTERY_PACK_RUN_TIME_TO_EMPTY, ///< Battery pack run time (in minutes) predicted based on present rate of discharge BATTERY_PACK_AVERAGE_TIME_TO_EMPTY, ///< Battery pack average time to empty (in minutes - 1 minute rolling avg) BATTERY_PACK_AVERAGE_TIME_TO_FULL, ///< Battery pack average time to full (in minutes - 1 minute rolling avg) BATTERY_PACK_REMAINING_CAPACITY4, ///< Remaining battery capacity (in mWh) (fourth of 5 to increase frequency of reads) BATTERY_PACK_BATTERY_STATUS4, ///< Battery pack status (fourth of 5 to increase frequency of reads) BATTERY_CHARGER_STATUS4, ///< Battery charger status (fourth of 5 to increase frequency of reads) BATTERY_PACK_CHARGING_CURRENT, ///< Battery pack desired charging current (in mA) BATTERY_PACK_CHARGING_VOLTAGE, ///< Battery pack desired charging voltage (in mV) BATTERY_PACK_CYCLE_COUNT, ///< Battery pack cycle count BATTERY_PACK_DESIGN_CAPACITY, ///< Battery pack design capacity (in mWh) BATTERY_PACK_DESIGN_VOLTAGE, ///< Battery pack design voltage (in mV) BATTERY_PACK_SPECIFICATION_INFO, ///< Version number of the smart battery specification the battery pack supports BATTERY_PACK_MANUFACTURE_DATE, ///< Battery pack mfg date ( [year - 1980] x 512 + month x 32 + day BATTERY_PACK_REMAINING_CAPACITY5, ///< Remaining battery capacity (in mWh) (fifth of 5 to increase frequency of reads) BATTERY_PACK_BATTERY_STATUS5, ///< Battery pack status (fifth of 5 to increase frequency of reads) BATTERY_CHARGER_STATUS5, ///< Battery charger status (fifth of 5 to increase frequency of reads) BATTERY_PACK_SERIAL_NUMBER, ///< Battery pack serial number BATTERY_PACK_MANUFACTURER_NAME, ///< Battery pack mfg name BATTERY_PACK_DEVICE_NAME, ///< Battery pack device name BATTERY_PACK_DEVICE_CHEMISTRY, ///< Battery pack device chemistry END_OF_LIST } BATTERY_MANAGEMENT_ENUM_T; // ********** private data ********** static OVERRIDE_F32_T batteryRemCapacity_mWh = { 0.0, 0.0, 0.0, 0 }; ///< Battery pack remaining capacity (in mWh). static OVERRIDE_U32_T batteryStatus = { 0, 0, 0, 0 }; ///< Battery status static OVERRIDE_U32_T batteryChargerStatus = { 0, 0, 0, 0 }; ///< Battery charger status static OVERRIDE_U32_T batteryI2CStatusRegister = { 0, 0, 0, 0 }; ///< Battery I2C Interrupt Status register static U32 lastBatteryMonitorTime; ///< Previous battery monitor time. static U32 commFaultPersistentCount; ///< Persistence count for battery comm fault. static BATTERY_MANAGEMENT_ENUM_T current_BM_value; ///< Index for which battery data to read now. static BATTERY_MANAGER_PAYLOAD_T BatteryManagerData; ///< Record with latest battery pack data updated at the slower frequency. static BATTERY_STATUS_PAYLOAD_T BatteryStatusData; ///< Record with latest battery pack/charger status data updated at the faster frequency. // ********** private function prototypes ********** static F32 getBatteryRemainingCapacity_mWh( void ); static U32 getBatteryStatus( void ); static U32 getBatteryChargerStatus( void ); static U32 getI2CStatusRegister( void ); static void setupI2CDriver( void ); static BOOL waitForTxReady( void ); static BOOL waitForRxReady( void ); static BOOL waitForAccessReady( void ); static void generateStopCondition( void ); static BOOL getBatteryData( U32 slaveAddr, U08 command, U32 * dataPtr ); static BOOL startCommTx( U32 slaveAddr ); static BOOL getData( U08 command, U16 * dataPtr ); // For logging static void getBatteryManagementData( void ); static void publishBatteryManagementData( void ); static void publishBatteryStatusData( void ); /*********************************************************************//** * @brief * The initBattery function initializes the Battery module. * @details Inputs: none * @details Outputs: Battery module is initialized. * @return none *************************************************************************/ void initBattery( void ) { lastBatteryMonitorTime = 0; commFaultPersistentCount = 0; current_BM_value = BEGINNING_OF_LIST; memset( &BatteryStatusData, 0, sizeof( BATTERY_STATUS_PAYLOAD_T ) ); memset( &BatteryManagerData, 0, sizeof( BATTERY_MANAGER_PAYLOAD_T ) ); // Initialize persistent alarm for battery pack status error initPersistentAlarm( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, 0, BATT_STATUS_ERROR_PERSIST_MS ); initPersistentAlarm( ALARM_ID_HD_BATTERY_COMM_FAULT, 0, BATTERY_COMM_FAULT_PERSISTENCE_TIMER ); setupI2CDriver(); } /*********************************************************************//** * @brief * The execBatteryMonitor function monitors the battery status. * @details Inputs: lastBatteryMonitorTime * @details Outputs: lastBatteryMonitorTime * @return none *************************************************************************/ void execBatteryMonitor( void ) { if ( TRUE == didTimeout( lastBatteryMonitorTime, BATTERY_MONITOR_INTERVAL_MS ) ) { lastBatteryMonitorTime = getMSTimerCount(); getBatteryManagementData(); } } /*********************************************************************//** * @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 ( getBatteryRemainingCapacity_mWh() > BATTERY_MIN_CAPACITY_MWH ? TRUE : FALSE ); } /*********************************************************************//** * @brief * The isACPowerLost function determines whether A/C power loss has been * detected. * @details Inputs: none * @details Outputs: none * @return TRUE if A/C power loss condition is in effect, FALSE if not *************************************************************************/ BOOL isACPowerLost( void ) { BOOL result = TRUE; if ( ( FALSE == isAlarmConditionDetected( ALARM_ID_HD_AC_POWER_LOST ) ) && ( FALSE == isAlarmConditionDetected( ALARM_ID_HD_AC_POWER_LOST_IN_TREATMENT ) ) ) { result = FALSE; } return result; } /*********************************************************************//** * @brief * The getI2CStatusRegister function returns the I2C status register * @details Inputs: batteryI2CStatusRegister, i2cREG1->STR * @details Outputs: none * @return I2C Interrupt Status. *************************************************************************/ static U32 getI2CStatusRegister( void ) { U32 result = i2cREG1->STR; if ( OVERRIDE_KEY == batteryI2CStatusRegister.override ) { result = batteryI2CStatusRegister.ovData; } return result; } /*********************************************************************//** * @brief * The getBatteryRemainingCapacity_mWh function returns the latest battery * remaining capacity (in mWh). * @details Inputs: batteryRemCapacity_mWh * @details Outputs: none * @return battery remaining capacity (in mWh). *************************************************************************/ static F32 getBatteryRemainingCapacity_mWh( void ) { F32 result = batteryRemCapacity_mWh.data; if ( OVERRIDE_KEY == batteryRemCapacity_mWh.override ) { result = batteryRemCapacity_mWh.ovData; } return result; } /*********************************************************************//** * @brief * The getBatteryStatus function returns the latest battery status * @details Inputs: batteryStatus * @details Outputs: none * @return battery status. *************************************************************************/ static U32 getBatteryStatus( void ) { U32 result = batteryStatus.data; if ( OVERRIDE_KEY == batteryStatus.override ) { result = batteryStatus.ovData; } return result; } /*********************************************************************//** * @brief * The getBatteryChargerStatus function returns the latest battery * charger status. * @details Inputs: batteryChargerStatus * @details Outputs: none * @return battery charger status. *************************************************************************/ static U32 getBatteryChargerStatus( void ) { U32 result = batteryChargerStatus.data; if ( OVERRIDE_KEY == batteryChargerStatus.override ) { result = batteryChargerStatus.ovData; } return result; } /*********************************************************************//** * @brief * The setupI2CDriver function setups i2c driver in repeat mode to be * compatible 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 i2c driver ready to transmit data, 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 ( TRUE == timeout ? FALSE : TRUE ); } /*********************************************************************//** * @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 i2c driver ready to receive data, 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 ( TRUE == timeout ? FALSE : TRUE ); } /*********************************************************************//** * @brief * The waitForAccessReady function checks if i2c registers are ready to be accessed. * @details Inputs: none * @details Outputs: checked i2c registers access ready status * @return TRUE if i2c driver registers are ready to be accessed, otherwise FALSE *************************************************************************/ static BOOL waitForAccessReady( void ) { U32 const startTime = getMSTimerCount(); BOOL timeout = FALSE; while ( ( 0 == ( i2cREG1->STR & (U32)I2C_ARDY ) ) && ( FALSE == timeout ) ) { timeout = didTimeout( startTime, BATTERY_COMM_TIME_OUT_MS ); } return ( TRUE == timeout ? FALSE : TRUE ); } /*********************************************************************//** * @brief * The generateStopCondition function generates a i2c stop condition and * waits until the stop condition is detected or timed out. * @details Inputs: none * @details Outputs: generated i2c stop condition * @return none *************************************************************************/ static void generateStopCondition( void ) { U32 const startTime = getMSTimerCount(); BOOL timeout = FALSE; i2cSetStop( i2cREG1 ); while ( ( 0 == i2cIsStopDetected( i2cREG1 ) ) && ( FALSE == timeout ) ) { timeout = didTimeout( startTime, BATTERY_COMM_TIME_OUT_MS ); } } /*********************************************************************//** * @brief * 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, U32 * dataPtr ) { BOOL result = FALSE; if ( TRUE == startCommTx( slaveAddr ) ) { U16 data = (U16)( (*dataPtr) & MASK_OFF_MSW ); if ( TRUE == getData( command, &data ) ) { *dataPtr = data; 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 == ( getI2CStatusRegister() & ( (U32)I2C_NACK | (U32)I2C_AL ) ) ) { commFaultPersistentCount = 0; result = TRUE; } else { generateStopCondition(); if ( TRUE == isPersistentAlarmTriggered(ALARM_ID_HD_BATTERY_COMM_FAULT, ++commFaultPersistentCount > BATTERY_COMM_FAULT_PERSISTENCE_COUNT ) ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_BATTERY_COMM_FAULT, slaveAddr, commFaultPersistentCount ); } } } } 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 data, otherwise FALSE *************************************************************************/ static BOOL getData( U08 command, U16 * dataPtr ) { BOOL result = FALSE; U16 batteryData = 0; if ( TRUE == waitForTxReady() ) { i2cSendByte( i2cREG1, command ); } // Wait until command has been transmitted before start receiving command response if ( TRUE == waitForTxReady() ) { i2cSetDirection( i2cREG1, I2C_RECEIVER ); i2cSetStart( i2cREG1 ); if ( TRUE == waitForRxReady() ) { // Due to the double buffer, the master must generate the stop condition after the (message size - 1)th data i2cSetStop( i2cREG1 ); batteryData = i2cReceiveByte( i2cREG1); if ( TRUE == waitForRxReady() ) { batteryData = ( batteryData | ( i2cReceiveByte( i2cREG1) << 8 ) ); *dataPtr = batteryData; result = TRUE; } } } if ( FALSE == result ) { if ( TRUE == isPersistentAlarmTriggered(ALARM_ID_HD_BATTERY_COMM_FAULT, ++commFaultPersistentCount > BATTERY_COMM_FAULT_PERSISTENCE_COUNT ) ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_BATTERY_COMM_FAULT, dataPtr, commFaultPersistentCount ); commFaultPersistentCount = 0; } } return result; } /*********************************************************************//** * @brief * The getBatteryManagementData function accumulates the battery management * and status data and publishes the two sets of values when complete. Also, * the battery remaining capacity is stored, the battery status alarm is set * if necessary, and the loss of AC power alarm is set if necessary. * @details Inputs: current_BM_value, BatteryStatusData * @details Outputs: batteryRemCapacity_mWh, BatteryManagerData * @return none *************************************************************************/ static void getBatteryManagementData(void) { HD_OP_MODE_T opMode = getCurrentOperationMode(); // Increment the position in the enum. Starting value is BEGINNING_OF_LIST (0), so on the first // cycle through this function it will be set to the first valid position (1) current_BM_value += 1; switch( current_BM_value ) { case BATTERY_PACK_REMAINING_CAPACITY1: case BATTERY_PACK_REMAINING_CAPACITY2: case BATTERY_PACK_REMAINING_CAPACITY3: case BATTERY_PACK_REMAINING_CAPACITY4: case BATTERY_PACK_REMAINING_CAPACITY5: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_REMAINING_CAPACITY, &BatteryStatusData.RemainingCapacity ); batteryRemCapacity_mWh.data = (F32)BatteryStatusData.RemainingCapacity * BATTERY_MAH_2_MWH_FACTOR; break; case BATTERY_PACK_BATTERY_STATUS1: case BATTERY_PACK_BATTERY_STATUS2: case BATTERY_PACK_BATTERY_STATUS3: case BATTERY_PACK_BATTERY_STATUS4: case BATTERY_PACK_BATTERY_STATUS5: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_BATTERY_STATUS, &BatteryStatusData.BatteryStatus ); batteryStatus.data = BatteryStatusData.BatteryStatus; if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, ( getBatteryStatus() & BATTERY_PACK_ERROR_BITS ) != 0 ) ) ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, getBatteryStatus(), BATTERY_PACK_ERROR_BITS ); } break; case BATTERY_PACK_REMAINING_CAPACITY_ALARM: getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_REMAINING_CAPACITY_ALARM, &BatteryManagerData.RemainingCapacityAlarm ); break; case BATTERY_PACK_REMAINING_TIME_ALARM: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_REMAINING_TIME_ALARM, &BatteryManagerData.RemainingTimeAlarm ); break; case BATTERY_PACK_BATTERY_MODE: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_BATTERY_MODE, &BatteryManagerData.BatteryMode ); break; case BATTERY_PACK_AT_RATE: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AT_RATE, &BatteryManagerData.AtRate ); break; case BATTERY_PACK_AT_RATE_TIME_TO_FULL: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AT_RATE_TIME_TO_FULL, &BatteryManagerData.AtRateTimeToFull ); break; case BATTERY_PACK_AT_RATE_TIME_TO_EMPTY: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AT_RATE_TIME_TO_EMPTY, &BatteryManagerData.AtRateTimeToEmpty ); break; case BATTERY_PACK_AT_RATE_OK: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AT_RATE_OK, &BatteryManagerData.AtRateOK ); break; case BATTERY_PACK_TEMPERATURE: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_TEMPERATURE, &BatteryManagerData.Temperature ); break; case BATTERY_PACK_VOLTAGE: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_VOLTAGE, &BatteryManagerData.Voltage ); break; case BATTERY_PACK_CURRENT: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_CURRENT, &BatteryManagerData.Current ); break; case BATTERY_PACK_AVERAGE_CURRENT: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AVERAGE_CURRENT, &BatteryManagerData.AverageCurrent ); break; case BATTERY_PACK_MAX_ERROR: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_MAX_ERROR, &BatteryManagerData.MaxError ); break; case BATTERY_PACK_RELATIVE_STATE_OF_CHARGE: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_RELATIVE_STATE_OF_CHARGE, &BatteryManagerData.RelativeStateOfCharge ); break; case BATTERY_PACK_ABSOLUTE_STATE_OF_CHARGE: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_ABSOLUTE_STATE_OF_CHARGE, &BatteryManagerData.AbsoluteStateOfCharge ); break; case BATTERY_PACK_FULL_CHARGE_CAPACITY: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_FULL_CHARGE_CAPACITY, &BatteryManagerData.FullChargeCapacity ); break; case BATTERY_PACK_RUN_TIME_TO_EMPTY: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_RUN_TIME_TO_EMPTY, &BatteryManagerData.RunTimeToEmpty ); break; case BATTERY_PACK_AVERAGE_TIME_TO_EMPTY: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AVERAGE_TIME_TO_EMPTY, &BatteryManagerData.AverageTimeToEmpty ); break; case BATTERY_PACK_AVERAGE_TIME_TO_FULL: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_AVERAGE_TIME_TO_FULL, &BatteryManagerData.AverageTimeToFull ); break; case BATTERY_PACK_CHARGING_CURRENT: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_CHARGING_CURRENT, &BatteryManagerData.ChargingCurrent ); break; case BATTERY_PACK_CHARGING_VOLTAGE: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_CHARGING_VOLTAGE, &BatteryManagerData.ChargingVoltage ); break; case BATTERY_PACK_CYCLE_COUNT: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_CYCLE_COUNT, &BatteryManagerData.CycleCount ); break; case BATTERY_PACK_DESIGN_CAPACITY: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_DESIGN_CAPACITY, &BatteryManagerData.DesignCapacity ); break; case BATTERY_PACK_DESIGN_VOLTAGE: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_DESIGN_VOLTAGE, &BatteryManagerData.DesignVoltage ); break; case BATTERY_PACK_SPECIFICATION_INFO: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_SPECIFICATION_INFO, &BatteryManagerData.SpecificationInfo ); break; case BATTERY_PACK_MANUFACTURE_DATE: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_MANUFACTURE_DATE, &BatteryManagerData.ManufactureDate ); break; case BATTERY_PACK_SERIAL_NUMBER: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_SERIAL_NUMBER, &BatteryManagerData.SerialNumber ); break; case BATTERY_PACK_MANUFACTURER_NAME: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_MANUFACTURER_NAME, &BatteryManagerData.ManufacturerName ); break; case BATTERY_PACK_DEVICE_NAME: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_DEVICE_NAME, &BatteryManagerData.DeviceName ); break; case BATTERY_PACK_DEVICE_CHEMISTRY: getBatteryData ( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_ADDR_DEVICE_CHEMISTRY, &BatteryManagerData.DeviceChemistry ); break; case BATTERY_CHARGER_STATUS1: case BATTERY_CHARGER_STATUS2: case BATTERY_CHARGER_STATUS3: case BATTERY_CHARGER_STATUS4: case BATTERY_CHARGER_STATUS5: if ( TRUE == getBatteryData( BATTERY_CHARGER_SLAVE_ADDRESS, BATTERY_CHARGER_STATUS_CMD, &BatteryStatusData.BatteryChargerStatus ) ) { batteryChargerStatus.data = BatteryStatusData.BatteryChargerStatus; } // Publish battery status data after reading battery charger status (last status read) publishBatteryStatusData(); break; case END_OF_LIST: current_BM_value = BEGINNING_OF_LIST; publishBatteryManagementData(); break; default: // TODO s/w fault break; } } /*********************************************************************//** * @brief * The publishBatteryManagementData function publishes the battery management data * @details Inputs: BatteryManagerData * @details Outputs: send battery management data * @return none *************************************************************************/ static void publishBatteryManagementData( void ) { broadcastData( MSG_ID_HD_BATTERY_MANAGEMENT_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&BatteryManagerData, sizeof( BATTERY_MANAGER_PAYLOAD_T ) ); } /*********************************************************************//** * @brief * The publishBatteryStatusData function publishes the battery status data * @details Inputs: BatteryStatusData * @details Outputs: none * @return none *************************************************************************/ static void publishBatteryStatusData( void ) { BATTERY_STATUS_PAYLOAD_T batteryStatusData; batteryStatusData.RemainingCapacity = (U32)getBatteryRemainingCapacity_mWh(); batteryStatusData.BatteryStatus = getBatteryStatus(); batteryStatusData.BatteryChargerStatus = getBatteryChargerStatus(); batteryStatusData.BatteryI2CStatus = getI2CStatusRegister(); broadcastData( MSG_ID_HD_BATTERY_STATUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&batteryStatusData, sizeof( BATTERY_STATUS_PAYLOAD_T ) ); } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetBatteryRemainingPercentOverride function overrides the battery * remaining percent value. * @details Inputs: none * @details Outputs: batteryRemCapacity_mWh * @param value override battery remaining percent * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBatteryRemainingCapacityOverride( F32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; batteryRemCapacity_mWh.ovData = value; batteryRemCapacity_mWh.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetBatteryRemainingPercentOverride function resets the * override of the battery remaining percent value. * @details Inputs: none * @details Outputs: batteryRemCapacity_mWh * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetBatteryRemainingCapacityOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; batteryRemCapacity_mWh.override = OVERRIDE_RESET; batteryRemCapacity_mWh.ovData = batteryRemCapacity_mWh.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetBatteryStatusOverride function overrides the battery * status value. * @details Inputs: none * @details Outputs: batteryStatus * @param value override battery status * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBatteryStatusOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; batteryStatus.ovData = value; batteryStatus.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetBatteryStatusOverride function resets the * override of the battery status value. * @details Inputs: none * @details Outputs: batteryStatus * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetBatteryStatusOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; batteryStatus.override = OVERRIDE_RESET; batteryStatus.ovData = batteryStatus.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetBatteryChargerStatusOverride function overrides the battery * charger status value. * @details Inputs: none * @details Outputs: batteryChargerStatus * @param value override battery charge status * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBatteryChargerStatusOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; batteryChargerStatus.ovData = value; batteryChargerStatus.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetBatteryChargerStatusOverride function resets the * override of the battery charger status. * @details Inputs: none * @details Outputs: batteryChargerStatus * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetBatteryChargerStatusOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; batteryChargerStatus.override = OVERRIDE_RESET; batteryChargerStatus.ovData = batteryChargerStatus.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetBatteryI2CStatusOverride function overrides the battery * i2c status register value. * @details Inputs: none * @details Outputs: batteryI2CStatusRegister * @param value override battery charge status * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBatteryI2CStatusOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; batteryI2CStatusRegister.ovData = value; batteryI2CStatusRegister.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetBatteryI2CStatusOverride function resets the * override of the battery i2c status register value. * @details Inputs: none * @details Outputs: batteryI2CStatusRegister * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetBatteryI2CStatusOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; batteryI2CStatusRegister.override = OVERRIDE_RESET; batteryI2CStatusRegister.ovData = batteryI2CStatusRegister.ovInitData; } return result; } /**@}*/