Index: firmware/App/Drivers/Battery.c =================================================================== diff -u -rd2d9f19fd458bad756c2468ea10fceb0c11d4200 -r54ee9a1d1778fd6f33735082a5e4e58facce5292 --- firmware/App/Drivers/Battery.c (.../Battery.c) (revision d2d9f19fd458bad756c2468ea10fceb0c11d4200) +++ firmware/App/Drivers/Battery.c (.../Battery.c) (revision 54ee9a1d1778fd6f33735082a5e4e58facce5292) @@ -51,8 +51,12 @@ // ********** private function prototypes ********** static void setupI2CDriver( void ); +static BOOL startCommTx( U32 slaveAddr ); static BOOL waitForTxReady( void ); -static BOOL getBatteryData( U32 slaveAddr, U08 command, U16 * dataPtr ); +static BOOL waitForRxReady( void ); +static BOOL waitForAccessReady( void ); +static void generateStopCondition( void ); +static BOOL getBatteryData( U08 command, U16 * dataPtr ); /*********************************************************************//** * @brief @@ -84,33 +88,31 @@ { hasBatteryChargerStatus = TRUE; - if ( TRUE == getBatteryData( BATTERY_CHARGER_SLAVE_ADDRESS, BATTERY_CHARGER_STATUS_CMD, &batteryStatus ) ) + if ( TRUE == startCommTx( BATTERY_CHARGER_SLAVE_ADDRESS ) ) { - if ( ( batteryStatus & BATTERY_CHARGER_STATUS_AC_PRESENT_MASK ) == 0 ) + if ( TRUE == getBatteryData( BATTERY_CHARGER_STATUS_CMD, &batteryStatus ) ) { - if ( ++lostACPowerPersistentCount > AC_POWER_LOST_PERSISTENT_COUNT ) + if ( ( batteryStatus & BATTERY_CHARGER_STATUS_AC_PRESENT_MASK ) == 0 ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_AC_POWER_LOST, batteryStatus ); + if ( ++lostACPowerPersistentCount > AC_POWER_LOST_PERSISTENT_COUNT ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_AC_POWER_LOST, batteryStatus ); + } } + else + { + lostACPowerPersistentCount = 0; + } } - else - { - lostACPowerPersistentCount = 0; - } } - else - { - // Reset i2c bus if cannot communicate with battery charger - setupI2CDriver(); - } } else { hasBatteryChargerStatus = FALSE; - if ( FALSE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_REL_STATE_OF_CHARGE_CMD, &batteryRelStateOfCharge_pct ) ) + if ( TRUE == startCommTx( BATTERY_PACK_SLAVE_ADDRESS ) ) { - setupI2CDriver(); + getBatteryData( BATTERY_PACK_REL_STATE_OF_CHARGE_CMD, &batteryRelStateOfCharge_pct ); } } #endif @@ -147,11 +149,54 @@ /*********************************************************************//** * @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(); + } + } + + } + + 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 * @details Outputs: checked i2c transmit ready status - * @return TRUE if timeout, otherwise FALSE + * @return TRUE if i2c driver ready to transmit data, otherwise FALSE *************************************************************************/ static BOOL waitForTxReady( void ) { @@ -163,7 +208,7 @@ timeout = didTimeout( startTime, BATTERY_COMM_TIME_OUT_MS ); } - return timeout; + return ( TRUE == timeout ? FALSE : TRUE ); } /*********************************************************************//** @@ -172,7 +217,7 @@ * driver with a timeout. * @details Inputs: none * @details Outputs: checked i2c receive ready status - * @return TRUE if timeout, otherwise FALSE + * @return TRUE if i2c driver ready to receive data, otherwise FALSE *************************************************************************/ static BOOL waitForRxReady( void ) { @@ -184,53 +229,84 @@ timeout = didTimeout( startTime, BATTERY_COMM_TIME_OUT_MS ); } - return timeout; + 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 getBatteryStatus function send command to smart battery charger controller * interface to get battery status. * @details Inputs: none * @details Outputs: get the battery data based on given command - * @param slaveAddr slave device address * @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 *************************************************************************/ -static BOOL getBatteryData( U32 slaveAddr, U08 command, U16 * dataPtr ) +static BOOL getBatteryData( U08 command, U16 * dataPtr ) { BOOL result = FALSE; - i2cSetSlaveAdd( i2cREG1, slaveAddr ); + if ( TRUE == waitForTxReady() ) + { + i2cSendByte( i2cREG1, command ); + } - if ( FALSE == i2cIsBusBusy( i2cREG1 ) ) + // Wait until command has been transmitted before start receiving command response + if ( TRUE == waitForTxReady() ) { - i2cSetMode( i2cREG1, I2C_MASTER ); - i2cSetDirection( i2cREG1, I2C_TRANSMITTER ); + i2cSetDirection( i2cREG1, I2C_RECEIVER ); i2cSetStart( i2cREG1 ); - if ( FALSE == waitForTxReady() ) + if ( TRUE == waitForRxReady() ) { - i2cSendByte( i2cREG1, command ); - } + // Due to the double buffer, the master must generate the stop condition after the (message size - 1)th data + i2cSetStop( i2cREG1 ); + *dataPtr = i2cReceiveByte( i2cREG1); - // Wait until command has been transmitted before start receiving command response - if ( FALSE == waitForTxReady() ) - { - i2cSetDirection( i2cREG1, I2C_RECEIVER ); - i2cSetStart( i2cREG1 ); - - if ( FALSE == waitForRxReady() ) + if ( TRUE == waitForRxReady() ) { - // Due to the double buffer, the master must generate the stop condition after the (message size - 1)th data - i2cSetStop( i2cREG1 ); - *dataPtr = i2cReceiveByte( i2cREG1); - - if ( FALSE == waitForRxReady() ) - { - *dataPtr = ( *dataPtr | ( i2cReceiveByte( i2cREG1) << 8 ) ); - result = TRUE; - } + *dataPtr = ( *dataPtr | ( i2cReceiveByte( i2cREG1) << 8 ) ); + result = TRUE; } } }