From d15756d8fab2ee0389acd9f687a069bef9560750 Mon Sep 17 00:00:00 2001 From: Tobias Jaster Date: Fri, 24 May 2024 14:27:40 +0200 Subject: [PATCH] Add BQ24295 library files --- inc/bq24295.h | 504 +++++++++++++ library.json | 22 + src/bq24295.cpp | 1886 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2412 insertions(+) create mode 100644 inc/bq24295.h create mode 100644 library.json create mode 100644 src/bq24295.cpp diff --git a/inc/bq24295.h b/inc/bq24295.h new file mode 100644 index 0000000..cfd5749 --- /dev/null +++ b/inc/bq24295.h @@ -0,0 +1,504 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 u-blox + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BATTERY_CHARGER_BQ24295_H +#define BATTERY_CHARGER_BQ24295_H + +#include "mbed.h" + +/** + * @file battery_charger_bq24295.h + * This file defines the API to the TI BQ24295 battery charger chip. + */ + +/* ---------------------------------------------------------------- + * COMPILE-TIME MACROS + * -------------------------------------------------------------- */ + +/** Device I2C address. */ +#define BATTERY_CHARGER_BQ24295_ADDRESS 0x6B + +/* ---------------------------------------------------------------- + * CLASSES + * -------------------------------------------------------------- */ + +/** BQ27441 battery charger driver. */ +class BatteryChargerBq24295 { +public: + /** Charger state. */ + typedef enum { + CHARGER_STATE_UNKNOWN, + CHARGER_STATE_DISABLED, + CHARGER_STATE_NO_EXTERNAL_POWER, + CHARGER_STATE_NOT_CHARGING, + CHARGER_STATE_PRECHARGE, + CHARGER_STATE_FAST_CHARGE, + CHARGER_STATE_COMPLETE, + MAX_NUM_CHARGER_STATES + } ChargerState; + + /** Charger faults as a bitmap that matches the chip REG09 definitions. */ + typedef enum { + CHARGER_FAULT_NONE = 0x00, + CHARGER_FAULT_THERMISTOR_TOO_HOT = 0x01, + CHARGER_FAULT_THERMISTOR_TOO_COLD = 0x02, + // Value 0x04 is reserved + CHARGER_FAULT_BATTERY_OVER_VOLTAGE = 0x08, + CHARGER_FAULT_INPUT_FAULT = 0x10, //!< Note that the value of CHARGER_FAULT_CHARGE_TIMER_EXPIRED overlaps this, be careful when testing the bitmap. + CHARGER_FAULT_THERMAL_SHUTDOWN = 0x20, //!< Note that the value of CHARGER_FAULT_CHARGE_TIMER_EXPIRED overlaps this, be careful when testing the bitmap. + CHARGER_FAULT_CHARGE_TIMER_EXPIRED = 0x30, //!< This looks odd as it overlaps the two above but it matches the register meaning as defined by the chip. + CHARGER_FAULT_OTG = 0x40, + CHARGER_FAULT_WATCHDOG_EXPIRED = 0x80, + MAX_NUM_CHARGER_FAULTS + } ChargerFault; + + /** Constructor. */ + BatteryChargerBq24295(void); + /** Destructor. */ + ~BatteryChargerBq24295(void); + + /** Initialise the BQ24295 chip. + * After initialisation the chip will be put into its lowest + * power state and should be configured if the default settings + * are not satisfactory. + * Note: the BQ24295 charging chip will automonously charge a + * LiPo cell that is connected to it, without host interaction. + * This class is only required where the configuration of the + * chip needs to be changed or the charger state is to be monitored. + * @param pI2c a pointer to the I2C instance to use. + * @param address 7-bit I2C address of the battery charger chip. + * @return true if successful, otherwise false. + */ + bool init (I2C * pI2c, uint8_t address = BATTERY_CHARGER_BQ24295_ADDRESS); + + /** Get the charger state. + * Note: on a u-blox C030 board with no battery connected this will report + * CHARGER_STATE_COMPLETE or CHARGER_STATE_FAST_CHARGE rather than + * CHARGER_STATE_NOT_CHARGING. + * @return the charge state. + */ + ChargerState getChargerState(void); + + /** Get whether external power is present or not. + * @return true if external power is present, otherwise false. + */ + bool isExternalPowerPresent(void); + + /** Enable charging. + * Default is disabled. + * @return true if successful, otherwise false. + */ + bool enableCharging (void); + + /** Disable charging. + * Default is disabled. + * @return true if successful, otherwise false. + */ + bool disableCharging (void); + + /** Get the state of charging (enabled or disabled). + * @return true if charging is enabled, otherwise false. + */ + bool isChargingEnabled (void); + + /** Enable OTG charging. + * Default is enabled. + * @return true if successful, otherwise false. + */ + bool enableOtg (void); + + /** Disable OTG charging. + * Default is enabled. + * @return true if successful, otherwise false. + */ + bool disableOtg (void); + + /** Determine whether OTG charging is enabled or not. + * @return true if OTG charging is enabled, otherwise false. + */ + bool isOtgEnabled (void); + + /** Set the system voltage (the voltage which the + * chip will attempt to maintain the system at). + * @param voltageMV the voltage limit, in milliVolts. + * Range is 3000 mV to 3700 mV, default 3500 mV. + * @return true if successful, otherwise false. + */ + bool setSystemVoltage (int32_t voltageMV); + + /** Get the system voltage. + * @param pVoltageMV a place to put the system voltage limit. + * @return true if successful, otherwise false. + */ + bool getSystemVoltage (int32_t *pVoltageMV); + + /** Set the fast charging current limit. + * @param currentMA the fast charging current limit, in milliAmps. + * Range is 512 mA to 3008 mA, default 1024 mA. + * @return true if successful, otherwise false. + */ + bool setFastChargingCurrentLimit (int32_t currentMA); + + /** Get the fast charging current limit. + * @param pCurrentMA a place to put the fast charging current limit. + * @return true if successful, otherwise false. + */ + bool getFastChargingCurrentLimit (int32_t *pCurrentMA); + + /** Set the fast charging safety timer. + * @param timerHours the charging safety timer value. + * Use a value of 0 to indicate that the timer should be disabled. + * Timer values will be translated to the nearest (lower) value + * out of 5, 8, 12, and 20 hours, default 12 hours. + * @return true if successful, otherwise false. + */ + bool setFastChargingSafetyTimer (int32_t timerHours); + + /** Get the fast charging safety timer value. + * @param pTimerHours a place to put the charging safety timer value. + * Returned value is zero if the fast charging safety timer is disabled. + * @return true if charging termination is enabled, otherwise false. + */ + bool getFastChargingSafetyTimer (int32_t *pTimerHours); + + /** Set ICHG/IPRECH margin (see section 8.3.3.5 of the chip data sheet). + * Default is disabled. + * @return true if successful, otherwise false. + */ + bool enableIcghIprechMargin (void); + + /** Clear the ICHG/IPRECH margin (see section 8.3.3.5 of the chip data sheet). + * Default is disabled. + * @return true if successful, otherwise false. + */ + bool disableIcghIprechMargin (void); + + /** Check if the ICHG/IPRECH margin is set (see section 8.3.3.5 of + * the chip data sheet). + * @return true if the ICHG/IPRECH margin is enabled, otherwise false. + */ + bool isIcghIprechMarginEnabled (void); + + /** Set the charging termination current. + * @param currentMA the charging termination current, in milliAmps. + * Range is 128 mA to 2048 mA, default is 256 mA. + * @return true if successful, otherwise false. + */ + bool setChargingTerminationCurrent (int32_t currentMA); + + /** Get the charging termination current. + * @param pCurrentMA a place to put the charging termination current. + * @return true if successful, otherwise false. + */ + bool getChargingTerminationCurrent (int32_t *pCurrentMA); + + /** Enable charging termination. + * Default is enabled. + * @return true if successful, otherwise false. + */ + bool enableChargingTermination (void); + + /** Disable charging termination. + * Default is enabled. + * @return true if successful, otherwise false. + */ + bool disableChargingTermination (void); + + /** Get the state of charging termination (enabled or disabled). + * @return true if charging termination is enabled, otherwise false. + */ + bool isChargingTerminationEnabled (void); + + /** Set the pre-charging current limit. + * @param currentMA the pre-charging current limit, in milliAmps. + * Range is 128 mA to 2048 mA, default is 256 mA. + * @return true if successful, otherwise false. + */ + bool setPrechargingCurrentLimit (int32_t currentMA); + + /** Get the pre-charging current limit. + * @param pCurrentMA a place to put the pre-charging current limit. + * @return true if successful, otherwise false. + */ + bool getPrechargingCurrentLimit (int32_t *pCurrentMA); + + /** Set the charging voltage limit. + * @param voltageMV the charging voltage limit, in milliVolts. + * Range is 3504 mV to 4400 mV, default is 4208 mV. + * @return true if successful, otherwise false. + */ + bool setChargingVoltageLimit (int32_t voltageMV); + + /** Get the charging voltage limit. + * @param pVoltageMV a place to put the charging voltage limit, + * in milliVolts. + * @return true if successful, otherwise false. + */ + bool getChargingVoltageLimit (int32_t *pVoltageMV); + + /** Set the pre-charge to fast-charge voltage threshold. + * @param voltageMV the threshold, in milliVolts. + * Values will be translated to the nearest (highest) + * voltage out of 2800 mV and 3000 mV, default is 3000 mV. + * @return true if successful, otherwise false. + */ + bool setFastChargingVoltageThreshold (int32_t voltageMV); + + /** Get the pre-charge to fast-charge voltage threshold. + * @param pVoltageMV a place to put the threshold, in milliVolts. + * @return true if successful, otherwise false. + */ + bool getFastChargingVoltageThreshold (int32_t *pVoltageMV); + + /** Set the recharging voltage threshold. + * @param voltageMV the recharging voltage threshold, in milliVolts. + * Values will be translated to the nearest (highest) + * voltage out of 100 mV and 300 mV, default is 100 mV. + * @return true if successful, otherwise false. + */ + bool setRechargingVoltageThreshold (int32_t voltageMV); + + /** Get the recharging voltage threshold. + * @param pVoltageMV a place to put the charging voltage threshold, in milliVolts. + * @return true if successful, otherwise false. + */ + bool getRechargingVoltageThreshold (int32_t *pVoltageMV); + + /** Set the boost voltage. + * @param voltageMV the boost voltage, in milliVolts. + * Range is 4550 mV to 5510 mV, default is 5126 mV. + * @return true if successful, otherwise false. + */ + bool setBoostVoltage (int32_t voltageMV); + + /** Get the boost voltage. + * @param pVoltageMV a place to put the boost voltage, in milliVolts. + * @return true if successful, otherwise false. + */ + bool getBoostVoltage (int32_t *pVoltageMV); + + /** Set the boost mode upper temperature limit. + * @param temperatureC the temperature in C. + * Values will be translated to the nearest (lower) + * of 55 C, 60 C and 65 C (disabled by default). + * @return true if successful, otherwise false. + */ + bool setBoostUpperTemperatureLimit (int32_t temperatureC); + + /** Get the boost mode upper temperature limit. + * If the boost mode upper temperature limit is not + * enabled then pTemperatureC will remain untouched and false + * will be returned. + * @param pTemperatureC a place to put the temperature. + * @return true if successful and a limit was set, otherwise false. + */ + bool getBoostUpperTemperatureLimit (int32_t *pTemperatureC); + + /** Check whether the boost mode upper temperature limit is enabled. + * @return true if successful, otherwise false. + */ + bool isBoostUpperTemperatureLimitEnabled (void); + + /** Disable the boost mode upper temperature limit. + * Default is disabled. + * @return true if successful, otherwise false. + */ + bool disableBoostUpperTemperatureLimit (void); + + /** Set the boost mode low temperature limit. + * @param temperatureC the temperature in C. + * Values will be translated to the nearest (higher) + * of -10 C and -20 C, default is -10 C. + * @return true if successful, otherwise false. + */ + bool setBoostLowerTemperatureLimit (int32_t temperatureC); + + /** Get the boost mode low temperature limit. + * @param pTemperatureC a place to put the temperature. + * @return true if successful, otherwise false. + */ + bool getBoostLowerTemperatureLimit (int32_t *pTemperatureC); + + /** Set the input voltage limit. If the input falls below + * this level then charging will be ramped down. The limit + * does not take effect until enableInputLimits() is called + * (default setting is disabled). + * @param voltageMV the input voltage limit, in milliVolts. + * Range is 3880 mV to 5080 mV, default is 4760 mV. + * @return true if successful, otherwise false. + */ + bool setInputVoltageLimit (int32_t voltageMV); + + /** Get the input voltage limit. + * @param pVoltageMV a place to put the input voltage limit. + * @return true if successful, otherwise false. + */ + bool getInputVoltageLimit (int32_t *pVoltageMV); + + /** Set the input current limit. If the current drawn + * goes above this limit then charging will be ramped down. + * The limit does not take effect until enableInputLimits() + * is called (default setting is disabled). + * @param currentMA the input current limit, in milliAmps. + * Range is 100 mA to 3000 mA, default depends upon + * hardware configuration, see section 8.3.1.4.3 of + * the data sheet. + * @return true if successful, otherwise false. + */ + bool setInputCurrentLimit (int32_t currentMA); + + /** Get the input current limit. + * @param pCurrentMA a place to put the input current limit. + * @return true if successful, otherwise false. + */ + bool getInputCurrentLimit (int32_t *pCurrentMA); + + /** Enable input voltage and current limits. + * Default is disabled. + * @return true if successful, otherwise false. + */ + bool enableInputLimits (void); + + /** Remove any input voltage or current limits. + * Default is disabled. + * @return true if successful, otherwise false. + */ + bool disableInputLimits (void); + + /** Check whether input limits are enabled. + * @return true if input limits are enabled, otherwise false. + */ + bool areInputLimitsEnabled (void); + + /** Set the thermal regulation threshold for the chip. + * @param temperatureC the temperature in C. + * Values will be translated to the nearest (lower) + * of 60 C, 80 C, 100 C and 120 C, default 120 C. + * @return true if successful, otherwise false. + */ + bool setChipThermalRegulationThreshold (int32_t temperatureC); + + /** Get the thermal regulation threshold for the chip. + * @param pTemperatureC a place to put the temperature. + * @return true if successful, otherwise false. + */ + bool getChipThermalRegulationThreshold (int32_t *pTemperatureC); + + /** Get the charger faults. + * Note: as with all the other API functions here, this should + * not be called from an interrupt function as the comms with the + * chip over I2C will take too long. + * @return a bit-map of that can be tested against ChargerFault. + */ + char getChargerFaults(void); + + /** Feed the watchdog timer. + * Use this if it is necessary to keep the BQ24295 chip in Host + * mode (see section 8.4.1 of the data sheet for details). + * @return true if successful, otherwise false. + */ + bool feedWatchdog(void); + + /** Get the watchdog timer of the BQ24295 chip. + * @param pWatchdogS a place to put the watchdog timer (in seconds). + * @return true if successful, otherwise false. + */ + bool getWatchdog (int32_t *pWatchdogS); + + /** Set the watchdog timer of the BQ24295 chip. + * @param watchdogS the watchdog timer (in seconds), 0 to disable, + * max 160 seconds. + * @return true if successful, otherwise false. + */ + bool setWatchdog (int32_t watchdogS); + + /** Enable shipping mode. + * In shipping mode the battery is disconnected from the system + * to avoid leakage. Default is disabled. + * @return true if successful, otherwise false. + */ + bool enableShippingMode (void); + + /** Disable shipping mode. + * In shipping mode the battery is disconnected from the system + * to avoid leakage. Default is disabled. + * @return true if successful, otherwise false. + */ + bool disableShippingMode (void); + + /** Check whether shipping mode is enabled. + * @return true if input limits are enabled, otherwise false. + */ + bool isShippingModeEnabled (void); + + /** Advanced function to read a register on the chip. + * @param address the address to read from. + * @param pValue a place to put the returned value. + * @return true if successful, otherwise false. + */ + bool advancedGet(char address, char *pValue); + + /** Advanced function to set a register on the chip. + * @param address the address to write to. + * @param value the value to write. + * @return true if successful, otherwise false. + */ + bool advancedSet(char address, char value); + +protected: + /** Pointer to the I2C interface. */ + I2C * gpI2c; + /** The address of the device. */ + uint8_t gAddress; + /** Flag to indicate device is ready */ + bool gReady; + + /** Read a register. + * Note: gpI2c should be locked before this is called. + * @param address the address to read from. + * @param pValue a place to put the returned value. + * @return true if successful, otherwise false. + */ + bool getRegister(char address, char *pValue); + + /** Set a register. + * Note: gpI2c should be locked before this is called. + * @param address the address to write to. + * @param value the value to write. + * @return true if successful, otherwise false. + */ + bool setRegister(char address, char value); + + /** Set a mask of bits in a register. + * Note: gpI2c should be locked before this is called. + * @param address the address to write to. + * @param mask the mask of bits to set. + * @return true if successful, otherwise false. + */ + bool setRegisterBits(char address, char mask); + + /** Clear a mask of bits in a register. + * Note: gpI2c should be locked before this is called. + * @param address the address to write to. + * @param mask the mask of bits to clear. + * @return true if successful, otherwise false. + */ + bool clearRegisterBits(char address, char mask); +}; + +#endif + +/* End Of File */ diff --git a/library.json b/library.json new file mode 100644 index 0000000..76c9739 --- /dev/null +++ b/library.json @@ -0,0 +1,22 @@ +{ + "name": "BQ24295", + "version": "0.1.0", + "description": "MBED OS Library for BQ24295 LiIon Battery Charger", + "keywords": "BQ24295, Battery, mbed os", + "repository": + { + "type": "git", + "url": "https://github.com/jaster-prj/mbed-bq24295.git" + }, + "authors": + [ + { + "name": "Tobias Jaster", + "email": "t.jaster@posteo.de", + "maintainer": true + } + ], + "license": "Apache-2.0", + "frameworks": "mbed", + "platforms": "*" +} diff --git a/src/bq24295.cpp b/src/bq24295.cpp new file mode 100644 index 0000000..c36c879 --- /dev/null +++ b/src/bq24295.cpp @@ -0,0 +1,1886 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 u-blox + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file bq24295.cpp + * This file defines the API to the TI BQ24295 battery charging chip. + */ + +// Define this to print debug information +//#define DEBUG_BQ24295 + +#include + +#ifdef DEBUG_BQ24295 +# include +#endif + +/* ---------------------------------------------------------------- + * COMPILE-TIME MACROS + * -------------------------------------------------------------- */ + +/* ---------------------------------------------------------------- + * PRIVATE VARIABLES + * -------------------------------------------------------------- */ + +/* ---------------------------------------------------------------- + * GENERIC PRIVATE FUNCTIONS + * -------------------------------------------------------------- */ + +// Read from a register. +bool BatteryChargerBq24295::getRegister(char address, char *pValue) +{ + bool success = false; + + if (gpI2c != NULL) { + // Move the address pointer + if (gpI2c->write(gAddress, &address, 1) == 0) { + if (pValue != NULL) { + // Read from the address + if (gpI2c->read(gAddress, pValue, 1) == 0) { + success = true; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): read 0x%02x from register 0x%02x.\r\n", gAddress >> 1, *pValue, address); +#endif + } + } else { + success = true; + } + } + } + + return success; +} + +// Write to a register. +bool BatteryChargerBq24295::setRegister(char address, char value) +{ + bool success = false; + char data[2]; + + if (gpI2c != NULL) { + data[0] = address; + data[1] = value; + if (gpI2c->write(gAddress, &(data[0]), 2) == 0) { + success = true; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): wrote 0x%02x to register 0x%02x.\r\n", gAddress >> 1, value, address); +#endif + } + } + + return success; +} + +// Set a mask of bits in a register. +bool BatteryChargerBq24295::setRegisterBits(char address, char mask) +{ + bool success = false; + char value; + + if (getRegister(address, &value)) { + value |= mask; + if (setRegister(address, value)) { + success = true; + } + } + + return success; +} + +// Clear a mask of bits in a register. +bool BatteryChargerBq24295::clearRegisterBits(char address, char mask) +{ + bool success = false; + char value; + + if (getRegister(address, &value)) { + value &= ~mask; + if (setRegister(address, value)) { + success = true; + } + } + + return success; +} + +/* ---------------------------------------------------------------- + * PUBLIC FUNCTIONS + * -------------------------------------------------------------- */ + +// Constructor. +BatteryChargerBq24295::BatteryChargerBq24295(void) +{ + gpI2c = NULL; + gReady = false; +} + +// Destructor. +BatteryChargerBq24295::~BatteryChargerBq24295(void) +{ +} + +// Initialise ourselves. +bool BatteryChargerBq24295::init (I2C * pI2c, uint8_t address) +{ + char reg; + + gpI2c = pI2c; + gAddress = address << 1; + + if (gpI2c != NULL) { + gpI2c->lock(); + + // Read the revision status register + if (getRegister(0x0a, ®)) { + // The expected response is 0xc0 + if (reg == 0xc0) { + gReady = true; + } + } + gpI2c->unlock(); + } + +#ifdef DEBUG_BQ24295 + if (gReady) { + printf("BatteryChargerBq24295 (I2C 0x%02x): handler initialised.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): chip NOT initialised.\r\n", gAddress >> 1); + } +#endif + + return gReady; +} + +// Get the charge state. +BatteryChargerBq24295::ChargerState BatteryChargerBq24295::getChargerState(void) +{ + BatteryChargerBq24295::ChargerState chargerState = CHARGER_STATE_UNKNOWN; + char powerOnConfiguration; + char systemStatus; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the power-on configuration register + if (getRegister(0x01, &powerOnConfiguration)) { + // Read the system status register + if (getRegister(0x08, &systemStatus)) { + // Check the charge enable bit + if ((powerOnConfiguration & (1 << 4)) == 0) { + chargerState = CHARGER_STATE_DISABLED; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): charging is disabled.\r\n", gAddress >> 1); +#endif + } else { + // BatteryCharger is not disabled, so see if we have + // external power (bit 3) + if ((systemStatus & 0x04) == 0) { + chargerState = CHARGER_STATE_NO_EXTERNAL_POWER; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): no external power.\r\n", gAddress >> 1); +#endif + } else { + // Have power, so see how we're cooking (bits 4 & 5) + switch ((systemStatus >> 4) & 0x03) { + case 0: + chargerState = CHARGER_STATE_NOT_CHARGING; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): not charging.\r\n", gAddress >> 1); +#endif + break; + case 1: + chargerState = CHARGER_STATE_PRECHARGE; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): pre-charge.\r\n", gAddress >> 1); +#endif + break; + case 2: + chargerState = CHARGER_STATE_FAST_CHARGE; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): fast charge.\r\n", gAddress >> 1); +#endif + break; + case 3: + chargerState = CHARGER_STATE_COMPLETE; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): charging complete.\r\n", gAddress >> 1); +#endif + break; + default: + break; + } + } + } + } + } + gpI2c->unlock(); + } + + return chargerState; +} + +// Get whether external power is present or not. +bool BatteryChargerBq24295::isExternalPowerPresent(void) +{ + bool isPresent = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the system status register + if (getRegister(0x08, ®)) { + // See if we have external power (bit 3) + if ((reg & 0x04) != 0) { + isPresent = true; + } + +#ifdef DEBUG_BQ24295 + if (isPresent) { + printf("BatteryChargerBq24295 (I2C 0x%02x): external power is present.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): external power is NOT present.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return isPresent; +} + +// Enable charging. +bool BatteryChargerBq24295::enableCharging (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Charge enable is bit 4 of the power-on configuration register + success = setRegisterBits(0x01, (1 << 4)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging now ENABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Disable charging. +bool BatteryChargerBq24295::disableCharging (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Charge enable is bit 4 of the power-on configuration register + success = clearRegisterBits(0x01, (1 << 4)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging now DISABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Get the whether charging is enabled or disabled. +bool BatteryChargerBq24295::isChargingEnabled (void) +{ + bool isEnabled = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the power-on configuration register + if (getRegister(0x01, ®)) { + // Charge enable is bit 4 of the power-on configuration register + if ((reg & (1 << 4)) != 0) { + isEnabled = true; + } +#ifdef DEBUG_BQ24295 + if (isEnabled) { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging is ENABLED.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging is DISABLED.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return isEnabled; +} + +// Enable OTG charging. +bool BatteryChargerBq24295::enableOtg (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // OTG enable is bit 5 of the power-on configuration register + success = setRegisterBits(0x01, (1 << 5)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): OTG charging now ENABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Disable OTG charging. +bool BatteryChargerBq24295::disableOtg (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // OTG enable is bit 5 of the power-on configuration register + success = clearRegisterBits(0x01, (1 << 5)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): OTG charging now DISABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Get whether OTG charging is enabled or not. +bool BatteryChargerBq24295::isOtgEnabled (void) +{ + bool isEnabled = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the power-on configuration register + if (getRegister(0x01, ®)) { + // OTG enable is bit 5 of the power-on configuration register + if ((reg & (1 << 5)) != 0) { + isEnabled = true; + } +#ifdef DEBUG_BQ24295 + if (isEnabled) { + printf("BatteryChargerBq24295 (I2C 0x%02x): OTG charging is ENABLED.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): OTG charging is DISABLED.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return isEnabled; +} + +// Set the system voltage. +bool BatteryChargerBq24295::setSystemVoltage (int32_t voltageMV) +{ + bool success = false; + char reg; + int32_t codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the power-on configuration register + if (getRegister(0x01, ®)) { + // System voltage is in bits 1 to 3, + // coded to base "100 mV" with + // an offset of 3000 mV. + if ((voltageMV >= 3000) && (voltageMV <= 3700)) { + codedValue = voltageMV; + codedValue = (codedValue - 3000) / 100; + // If the voltage minus the base is not an exact multiple of 100, + // add one to the coded value to make sure we don't + // go under the requested system voltage + if ((voltageMV - 3000) % 100 != 0) { + codedValue++; + } + + reg &= ~(0x07 << 1); + reg |= (char) ((codedValue & 0x07) << 1); + + // Write to the power-on configuration register + success = setRegister (0x01, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): system voltage now set to %.3f V.\r\n", gAddress >> 1, (float) voltageMV / 1000); + } +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the system voltage. +bool BatteryChargerBq24295::getSystemVoltage (int32_t *pVoltageMV) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the power-on configuration register + if (getRegister(0x01, ®)) { + success = true; + if (pVoltageMV != NULL) { + // Input voltage limit is in bits 1 to 3 + // Base voltage + *pVoltageMV = 3000; + // Shift reg down and add the number of multiples + // of 100 mV + reg = (reg >> 1) & 0x07; + *pVoltageMV += ((int32_t) reg) * 100; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): system voltage is %.3f V.\r\n", gAddress >> 1, (float) *pVoltageMV / 1000); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Set the fast charging current limit. +bool BatteryChargerBq24295::setFastChargingCurrentLimit (int32_t currentMA) +{ + bool success = false; + char reg; + int32_t codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the charge current control register + if (getRegister(0x02, ®)) { + // Fast charging current limit is in + // bits 2 to 7, coded to base "64 mA" with + // an offset of 512 mA. + if ((currentMA >= 512) && (currentMA <= 3008)) { + codedValue = currentMA; + codedValue = (codedValue - 512) / 64; + + reg &= ~(0x3f << 2); + reg |= (char) ((codedValue & 0x3f) << 2); + + // Write to the charge current control register + success = setRegister (0x02, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): fast charging current limit now set to %.3f A.\r\n", gAddress >> 1, (float) currentMA / 1000); + } +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the fast charging current limit. +bool BatteryChargerBq24295::getFastChargingCurrentLimit (int32_t *pCurrentMA) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the charge current control register + if (getRegister(0x02, ®)) { + success = true; + if (pCurrentMA != NULL) { + // Fast charging current limit is in bits 2 to 7 + // Base current + *pCurrentMA = 512; + // Shift reg down and add the number of multiples + // of 64 mA + reg = (reg >> 2) & 0x3f; + *pCurrentMA += ((int32_t) reg) * 64; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): fast charge current limit is %.3f A.\r\n", gAddress >> 1, (float) *pCurrentMA / 1000); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Enable the ICHG/IPRECH margin. +bool BatteryChargerBq24295::enableIcghIprechMargin (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // FORCE_20PCT is bit 0 of the charge current control register + success = setRegisterBits(0x02, (1 << 0)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): ICGH/IPRECH margin now ENABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Disable the ICHG/IPRECH margin. +bool BatteryChargerBq24295::disableIcghIprechMargin (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // FORCE_20PCT is bit 0 of the charge current control register + success = clearRegisterBits(0x02, (1 << 0)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): ICGH/IPRECH margin now DISABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Check if the ICHG/IPRECH margin is set. +bool BatteryChargerBq24295::isIcghIprechMarginEnabled (void) +{ + bool isEnabled = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the charge current control register + if (getRegister(0x02, ®)) { + // FORCE_20PCT is bit 0 + if ((reg & (1 << 0)) != 0) { + isEnabled = true; + } +#ifdef DEBUG_BQ24295 + if (isEnabled) { + printf("BatteryChargerBq24295 (I2C 0x%02x): ICGH/IPRECH margin is ENABLED.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): ICGH/IPRECH margin is DISABLED.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return isEnabled; +} + +// Set the fast charging safety timer. +bool BatteryChargerBq24295::setFastChargingSafetyTimer (int32_t timerHours) +{ + bool success = false; + char reg; + int32_t codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Mustn't be silly + if (timerHours >= 0) { + // Read the charge termination/timer control register + if (getRegister(0x05, ®)) { + // Timer setting is in bits 1 & 2, enable is in bit 3 + if (timerHours == 0) { + reg &= ~(1 << 3); + } else { + reg |= (1 << 3); + if (timerHours < 8) { + codedValue = 0; + } else if (timerHours < 12) { + codedValue = 1; + } else if (timerHours < 20) { + codedValue = 2; + } else { + codedValue = 3; + } + reg &= ~(0x03 << 1); + reg |= (char) (codedValue << 1); + } + // Write to the charge termination/timer control register + success = setRegister (0x05, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): fast charging safety timer now set to %d hours.\r\n", gAddress >> 1, (int) timerHours); + } +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the value of the fast charging safety timer. +bool BatteryChargerBq24295::getFastChargingSafetyTimer (int32_t *pTimerHours) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the charge termination/timer control register + if (getRegister(0x05, ®)) { + success = true; + if (pTimerHours != NULL) { + *pTimerHours = 0; + // Timer enable is in bit 3 + if ((reg & (1 << 3)) != 0) { + // Timer value is in bits 1 & 2 + switch ((reg >> 1) & 0x03) { + case 0: + *pTimerHours = 5; + break; + case 1: + *pTimerHours = 8; + break; + case 2: + *pTimerHours = 12; + break; + case 3: + *pTimerHours = 20; + break; + default: + MBED_ASSERT(false); + break; + } + } +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): fast charging safety timer is %d hours.\r\n", gAddress >> 1, (int) *pTimerHours); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Set the charging termination current. +bool BatteryChargerBq24295::setChargingTerminationCurrent (int32_t currentMA) +{ + bool success = false; + char reg; + int32_t codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the pre-charge/termination current control register + if (getRegister(0x03, ®)) { + // Charging termination current limit is in + // bits 0 to 3, coded to base "128 mA" with + // an offset of 128 mA. + if ((currentMA >= 128) && (currentMA <= 2048)) { + codedValue = currentMA; + codedValue = (codedValue - 128) / 128; + + reg &= ~0x0f; + reg |= (char) (codedValue & 0x0f); + + // Write to the pre-charge/termination current control register + success = setRegister (0x03, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination current now set to %.3f A.\r\n", gAddress >> 1, (float) currentMA / 1000); + } +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the charging termination current. +bool BatteryChargerBq24295::getChargingTerminationCurrent (int32_t *pCurrentMA) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the pre-charge/termination current control register + if (getRegister(0x03, ®)) { + success = true; + if (pCurrentMA != NULL) { + // Pre-charging current limit is in bits 0 to 3 + // Base current + *pCurrentMA = 128; + // Add the number of multiples of 128 mA + reg = reg & 0x0f; + *pCurrentMA += ((int32_t) reg) * 128; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination current is %.3f A.\r\n", gAddress >> 1, (float) *pCurrentMA / 1000); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Enable charging termination. +bool BatteryChargerBq24295::enableChargingTermination (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // EN_TERM is bit 7 of the charge termination/timer control register + success = setRegisterBits(0x05, (1 << 7)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination now ENABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Disable charging termination. +bool BatteryChargerBq24295::disableChargingTermination (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // EN_TERM is bit 7 of the charge termination/timer control register + success = clearRegisterBits(0x05, (1 << 7)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination now DISABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Get the state of charging termination (enabled or disabled) +bool BatteryChargerBq24295::isChargingTerminationEnabled (void) +{ + bool isEnabled = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the charge termination/timer control register + if (getRegister(0x05, ®)) { + // EN_TERM is bit 7 + if ((reg & (1 << 7)) != 0) { + isEnabled = true; + } +#ifdef DEBUG_BQ24295 + if (isEnabled) { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination is ENABLED.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination is DISABLED.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return isEnabled; +} + +// Set the pre-charging current limit. +bool BatteryChargerBq24295::setPrechargingCurrentLimit (int32_t currentMA) +{ + bool success = false; + char reg; + int32_t codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the pre-charge/termination current control register + if (getRegister(0x03, ®)) { + // Pre-charging current limit is in + // bits 4 to 7, coded to base "128 mA" with + // an offset of 128 mA. + if ((currentMA >= 128) && (currentMA <= 2048)) { + codedValue = currentMA; + codedValue = (codedValue - 128) / 128; + + reg &= ~(0x0f << 4); + reg |= (char) ((codedValue & 0x0f) << 4); + + // Write to the pre-charge/termination current control register + success = setRegister (0x03, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): pre-charging current limit now set to %.3f A.\r\n", gAddress >> 1, (float) currentMA / 1000); + } +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the pre-charging current limit. +bool BatteryChargerBq24295::getPrechargingCurrentLimit (int32_t *pCurrentMA) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the pre-charge/termination current control register + if (getRegister(0x03, ®)) { + success = true; + if (pCurrentMA != NULL) { + // Pre-charging current limit is in bits 4 to 7 + // Base current + *pCurrentMA = 128; + // Shift reg down and add the number of multiples + // of 128 mA + reg = (reg >> 4) & 0x0f; + *pCurrentMA += ((int32_t) reg) * 128; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): pre-charging current limit is %.3f A.\r\n", gAddress >> 1, (float) *pCurrentMA / 1000); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Set the charging voltage limit. +bool BatteryChargerBq24295::setChargingVoltageLimit (int32_t voltageMV) +{ + bool success = false; + char reg; + int32_t codedLimit; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the charging voltage control register + if (getRegister(0x04, ®)) { + // Charging voltage limit is in bits 2 to 7 + // but it is coded to base "16 mV" with + // an offset of 3504 mV. + if ((voltageMV >= 3504) && (voltageMV <= 4400)) { + codedLimit = voltageMV; + codedLimit = (codedLimit - 3504) / 16; + + reg &= ~(0x3f << 2); + reg |= (char) ((codedLimit & 0x3f) << 2); + + // Write to the charging voltage control register + success = setRegister (0x04, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): charging voltage limit now set to %.3f V.\r\n", gAddress >> 1, (float) voltageMV / 1000); + } +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the charging voltage limit. +bool BatteryChargerBq24295::getChargingVoltageLimit (int32_t *pVoltageMV) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the charging voltage control register + if (getRegister(0x04, ®)) { + success = true; + if (pVoltageMV != NULL) { + // Charging voltage limit is in bits 2 to 7 + // Base voltage + *pVoltageMV = 3504; + // Shift reg down and add the number of multiples + // of 16 mV + reg = (reg >> 2) & 0x3f; + *pVoltageMV += ((int32_t) reg) * 16; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): charging voltage limit is %.3f V.\r\n", gAddress >> 1, (float) *pVoltageMV / 1000); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Set the pre-charge to fast-charge voltage threshold. +bool BatteryChargerBq24295::setFastChargingVoltageThreshold (int32_t voltageMV) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // There are only two possible values, 2.8 V and 3.0 V. + // BATLOWV is bit 1 of the charging voltage control register + if (voltageMV > 2800) { + success = setRegisterBits(0x04, (1 << 1)); +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold now set to 3.000 V.\r\n", gAddress >> 1); +#endif + } else { + success = clearRegisterBits(0x04, (1 << 1)); +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold now set to 2.800 V.\r\n", gAddress >> 1); +#endif + } + gpI2c->unlock(); + } + + return success; +} + +// Get the pre-charge to fast-charge voltage threshold. +bool BatteryChargerBq24295::getFastChargingVoltageThreshold (int32_t *pVoltageMV) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // BATLOWV is bit 1 of the charging voltage control register + if (getRegister(0x04, ®)) { + success = true; + if (pVoltageMV != NULL) { + *pVoltageMV = 2800; + if ((reg & (1 << 1)) != 0) { + *pVoltageMV = 3000; + } + } + } + +#ifdef DEBUG_BQ24295 + if (reg & (1 << 1)) { + printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold is 3.000 V.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold is 2.800 V.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Set the recharging voltage threshold. +bool BatteryChargerBq24295::setRechargingVoltageThreshold (int32_t voltageMV) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // There are only two possible values, 100 mV and 300 mV. + // VRECHG is bit 0 of the charging voltage control register + if (voltageMV > 100) { + success = setRegisterBits(0x04, (1 << 0)); +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold now set to 0.300 V.\r\n", gAddress >> 1); +#endif + } else { + success = clearRegisterBits(0x04, (1 << 0)); +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold now set to 0.100 V.\r\n", gAddress >> 1); +#endif + } + gpI2c->unlock(); + } + + return success; +} + +// Get the recharging voltage threshold. +bool BatteryChargerBq24295::getRechargingVoltageThreshold (int32_t *pVoltageMV) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // VRECHG is bit 0 of the charging voltage control register + if (getRegister(0x04, ®)) { + success = true; + if (pVoltageMV != NULL) { + *pVoltageMV = 100; + if ((reg & (1 << 0)) != 0) { + *pVoltageMV = 300; + } + } + } + +#ifdef DEBUG_BQ24295 + if (reg & (1 << 1)) { + printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold is 0.300 V.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold is 0.100 V.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Set the boost voltage. +bool BatteryChargerBq24295::setBoostVoltage (int32_t voltageMV) +{ + bool success = false; + char reg; + int32_t codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the boost voltage/thermal regulation control register + if (getRegister(0x06, ®)) { + // Boost voltage is in bits 4 to 7, coded to base "64 mV" + // with an offset of 4550 mV. + if ((voltageMV >= 4550) && (voltageMV <= 5510)) { + codedValue = voltageMV; + codedValue = (codedValue - 4550) / 64; + // If the voltage minus the base is not an exact multiple of 64, + // add one to the coded value to make sure we don't + // go under the requested boost voltage + if ((voltageMV - 4550) % 64 != 0) { + codedValue++; + } + + reg &= ~(0x0f << 4); + reg |= (char) ((codedValue & 0x0f) << 4); + + // Write to the boost voltage/thermal regulation control register + success = setRegister (0x06, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): boost voltage now set to %.3f V.\r\n", gAddress >> 1, (float) voltageMV / 1000); + } +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the boost voltage. +bool BatteryChargerBq24295::getBoostVoltage (int32_t *pVoltageMV) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the boost voltage/thermal regulation control register + if (getRegister(0x06, ®)) { + success = true; + if (pVoltageMV != NULL) { + // Boost voltage is in bits 4 to 7 + // Base voltage + *pVoltageMV = 4550; + // Shift reg down and add the number of multiples + // of 64 mV + reg = (reg >> 4) & 0x0f; + *pVoltageMV += ((int32_t) reg) * 64; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): boost voltage is %.3f V.\r\n", gAddress >> 1, (float) *pVoltageMV / 1000); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Set the boost mode low temperature limit. +bool BatteryChargerBq24295::setBoostUpperTemperatureLimit (int32_t temperatureC) +{ + bool success = false; + char reg; + char codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the boost voltage/thermal regulation control register + if (getRegister(0x06, ®)) { + // BHOT is in bits 2 & 3 + if (temperatureC < 60) { + codedValue = 0; + } else if (temperatureC < 65) { + codedValue = 1; + } else { + codedValue = 2; + } + reg &= ~(0x03 << 2); + reg |= (char) (codedValue << 2); + // Write to boost voltage/thermal regulation control register + success = setRegister (0x06, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit now set to %d C.\r\n", gAddress >> 1, (int) temperatureC); + } +#endif + } + gpI2c->unlock(); + } + + return success; +} + +// Get the boost mode upper temperature limit. +bool BatteryChargerBq24295::getBoostUpperTemperatureLimit (int32_t *pTemperatureC) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // BHOT is in bits 2 & 3 of the boost voltage/thermal regulation control register + if (getRegister(0x06, ®)) { + // Only proceed (and return true) if the limit is enabled + if (((reg >> 2) & 0x03) != 0x03) { + success = true; + if (pTemperatureC != NULL) { + switch ((reg >> 2) & 0x03) { + case 0: + *pTemperatureC = 55; + break; + case 1: + *pTemperatureC = 60; + break; + case 2: + *pTemperatureC = 65; + break; + default: + MBED_ASSERT(false); + break; + } +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode upper temperature limit is %d C.\r\n", gAddress >> 1, (int) *pTemperatureC); +#endif + } + } + } + gpI2c->unlock(); + } + + return success; +} + +// Check whether the boost mode upper temperature limit is enabled. +bool BatteryChargerBq24295::isBoostUpperTemperatureLimitEnabled (void) +{ + bool isEnabled = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // BHOT is in bits 2 & 3 of the boost voltage/thermal regulation control register + // and it is enabled if any bit is 0 + if (getRegister(0x06, ®)) { + if (((reg >> 2) & 3) != 3) { + isEnabled = true; + } +#ifdef DEBUG_BQ24295 + if (isEnabled) { + printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode upper temperature limit is ENABLED.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode upper temperature limit is DISABLED.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return isEnabled; +} + +// Disable the boost mode upper temperature limit. +bool BatteryChargerBq24295::disableBoostUpperTemperatureLimit (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // BHOT is in bits 2 & 3 of the boost voltage/thermal regulation control register + // and setting all the bits indicates disabled + success = setRegisterBits(0x06, (3 << 2)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode upper temperature limit now DISABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Set the boost mode upper temperature limit. +bool BatteryChargerBq24295::setBoostLowerTemperatureLimit (int32_t temperatureC) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // There are only two possible values, -10 C and -20 C. + // BCOLD is bit 1 of the charge current control register + if (temperatureC < -10) { + success = setRegisterBits(0x02, (1 << 1)); +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit now set to -20 C.\r\n", gAddress >> 1); +#endif + } else { + success = clearRegisterBits(0x02, (1 << 1)); +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit now set to -10 C.\r\n", gAddress >> 1); +#endif + } + gpI2c->unlock(); + } + + return success; +} + +// Get the boost mode low temperature limit. +bool BatteryChargerBq24295::getBoostLowerTemperatureLimit (int32_t *pTemperatureC) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // BCOLD is bit 1 of the charge current control register + if (getRegister(0x02, ®)) { + success = true; + if (pTemperatureC != NULL) { + *pTemperatureC = -10; + if ((reg & (1 << 1)) != 0) { + *pTemperatureC = -20; + } + } + } + +#ifdef DEBUG_BQ24295 + if (reg & (1 << 1)) { + printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit is -20 C.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit is -10 C.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Set the input voltage limit. +bool BatteryChargerBq24295::setInputVoltageLimit (int32_t voltageMV) +{ + bool success = false; + char reg; + int32_t codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the input source control register + if (getRegister(0x00, ®)) { + // Input voltage limit is in bits 3 to 6 + // but it is coded to base "80 mV" with + // an offset of 3880 mV. + if ((voltageMV >= 3880) && (voltageMV <= 5080)) { + codedValue = voltageMV; + codedValue = (codedValue - 3880) / 80; + + reg &= ~(0x0f << 3); + reg |= (char) ((codedValue & 0x0f) << 3); + + // Write to the input source control register + success = setRegister (0x00, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): input voltage limit now set to %.3f V.\r\n", gAddress >> 1, (float) voltageMV / 1000); + } +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the input voltage limit. +bool BatteryChargerBq24295::getInputVoltageLimit (int32_t *pVoltageMV) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the input source control register + if (getRegister(0x00, ®)) { + success = true; + if (pVoltageMV != NULL) { + // Input voltage limit is in bits 3 to 6 + // Base voltage + *pVoltageMV = 3880; + // Shift reg down and add the number of multiples + // of 80 mV + reg = (reg >> 3) & 0x0f; + *pVoltageMV += ((int32_t) reg) * 80; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): input voltage limit is %.3f V.\r\n", gAddress >> 1, (float) *pVoltageMV / 1000); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Set the input current limit. +bool BatteryChargerBq24295::setInputCurrentLimit (int32_t currentMA) +{ + bool success = false; + char reg; + char codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the input source control register + if (getRegister(0x00, ®)) { + // Input current limit is in bits 0 to 2, coded + // such that the smallest limit is applied for + // a range (e.g. 120 mA ends up as 100 mA rather + // than 150 mA) + if ((currentMA >= 100) && (currentMA <= 3000)) { + if (currentMA < 150) { + codedValue = 0; + } else if (currentMA < 500) { + codedValue = 1; + } else if (currentMA < 900) { + codedValue = 2; + } else if (currentMA < 1000) { + codedValue = 3; + } else if (currentMA < 1500) { + codedValue = 4; + } else if (currentMA < 2000) { + codedValue = 5; + } else if (currentMA < 3000) { + codedValue = 6; + } else { + codedValue = 7; + } + reg &= ~(0x07 << 0); + reg |= codedValue; + + // Write to the input source control register + success = setRegister (0x00, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): input current limit now set to %.3f A.\r\n", gAddress >> 1, (float) currentMA / 1000); + } +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the input current limit. +bool BatteryChargerBq24295::getInputCurrentLimit (int32_t *pCurrentMA) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the input source control register + if (getRegister(0x00, ®)) { + success = true; + if (pCurrentMA != NULL) { + *pCurrentMA = 0; + // Input current limit is in bits 0 to 2 + switch (reg & 0x07) { + case 0: + *pCurrentMA = 100; + break; + case 1: + *pCurrentMA = 150; + break; + case 2: + *pCurrentMA = 500; + break; + case 3: + *pCurrentMA = 900; + break; + case 4: + *pCurrentMA = 1000; + break; + case 5: + *pCurrentMA = 1500; + break; + case 6: + *pCurrentMA = 2000; + break; + case 7: + *pCurrentMA = 3000; + break; + default: + MBED_ASSERT(false); + break; + } +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): input current limit is %.3f A.\r\n", gAddress >> 1, (float) *pCurrentMA / 1000); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Enable input voltage or current limits. +bool BatteryChargerBq24295::enableInputLimits (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Input limit enable is bit 7 of the source control register + success = setRegisterBits(0x00, (1 << 7)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): input limits now ENABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Remove any input voltage or current limits. +bool BatteryChargerBq24295::disableInputLimits (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Input limit enable is bit 7 of the source control register + success = clearRegisterBits(0x00, (1 << 7)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): input limits now DISABLED.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Check if input limits are enabled. +bool BatteryChargerBq24295::areInputLimitsEnabled (void) +{ + bool areEnabled = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the input source control register + if (getRegister(0x00, ®)) { + // Input limit enable is bit 7 of the source control register + if ((reg & (1 << 7)) != 0) { + areEnabled = true; + } +#ifdef DEBUG_BQ24295 + if (areEnabled) { + printf("BatteryChargerBq24295 (I2C 0x%02x): input limits are ENABLED.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): input limits are DISABLED.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return areEnabled; +} + +// Set the thermal regulation threshold for the chip. +bool BatteryChargerBq24295::setChipThermalRegulationThreshold (int32_t temperatureC) +{ + bool success = false; + char reg; + char codedValue; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the boost voltage/thermal regulation control register + if (getRegister(0x06, ®)) { + // TREG is in bits 0 & 1 + if (temperatureC < 80) { + codedValue = 0; + } else if (temperatureC < 100) { + codedValue = 1; + } else if (temperatureC < 120) { + codedValue = 2; + } else { + codedValue = 3; + } + reg &= ~0x03; + reg |= (char) codedValue; + // Write to boost voltage/thermal regulation control register + success = setRegister (0x06, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): chip thermal regulation threshold now set to %d C.\r\n", gAddress >> 1, (int) temperatureC); + } +#endif + } + gpI2c->unlock(); + } + + return success; +} + +// Get the thermal regulation threshold for the chip. +bool BatteryChargerBq24295::getChipThermalRegulationThreshold (int32_t *pTemperatureC) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + /// TREG is in bits 0 & 1 of the boost voltage/thermal regulation control register + if (getRegister(0x06, ®)) { + success = true; + if (pTemperatureC != NULL) { + switch (reg & 0x03) { + case 0: + *pTemperatureC = 60; + break; + case 1: + *pTemperatureC = 80; + break; + case 2: + *pTemperatureC = 100; + break; + case 3: + *pTemperatureC = 120; + break; + default: + MBED_ASSERT(false); + break; + } +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): chip thermal regulation threshold is %d C.\r\n", gAddress >> 1, (int) *pTemperatureC); +#endif + } + } + gpI2c->unlock(); + } + + return success; +} + +// Get the charger fault status as a bitmap. +char BatteryChargerBq24295::getChargerFaults(void) +{ + char bitmap = (char) CHARGER_FAULT_NONE; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the fault register + if (getRegister(0x09, ®)) { + bitmap = reg; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): charge fault register 0x%02x.\r\n", gAddress >> 1, bitmap); +#endif + } + gpI2c->unlock(); + } + + return bitmap; +} + +// Feed the watchdog timer of the BQ24295 chip. +bool BatteryChargerBq24295::feedWatchdog (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Watchdog reset is done by setting bit 6 of the power on control register + // to 1 + success = setRegisterBits(0x01, (1 << 6)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): watchdog fed.\r\n", gAddress >> 1); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +// Get the watchdog timer of the BQ24295 chip. +bool BatteryChargerBq24295::getWatchdog (int32_t *pWatchdogS) +{ + bool success = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Watchdog timer is in bits 4 and 5 of the charger termination/timer control + // register, where 0 is disabled 01 is 40 secs, 10 is 80 secs and 11 is 160 secs + success = getRegister(0x05, ®); + if (pWatchdogS != NULL) { + switch ((reg >> 4) & 0x03) { + case 0x00: + *pWatchdogS = 0; + break; + case 0x01: + *pWatchdogS = 40; + break; + case 0x02: + *pWatchdogS = 80; + break; + case 0x03: + *pWatchdogS = 160; + break; + default: + MBED_ASSERT(false); + break; + } +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): watchdog is %d seconds.\r\n", gAddress >> 1, (int) *pWatchdogS); + } +#endif + } + gpI2c->unlock(); + } + + return success; +} + +// Set the watchdog timer of the BQ24295 chip. +bool BatteryChargerBq24295::setWatchdog (int32_t watchdogS) +{ + bool success = false; + char reg; + char regValue = 0; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Watchdog timer is in bits 4 and 5 of the charger termination/timer control + // register, where 0 is disabled 01 is 40 secs, 10 is 80 secs and 11 is 160 secs + if (watchdogS > 80) { + regValue = 0x03; + } else if (watchdogS > 40) { + regValue = 0x02; + } else if (watchdogS > 0) { + regValue = 0x01; + } + if (getRegister(0x05, ®)) { + // Clear the bits then set them + reg &= ~(0x03 << 4); + reg |= regValue << 4; + success = setRegister(0x05, reg); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): watchdog set to %d seconds.\r\n", gAddress >> 1, (int) watchdogS); + } +#endif + } + gpI2c->unlock(); + } + + return success; +} + +// Enable shipping mode. +bool BatteryChargerBq24295::enableShippingMode (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Have to disable the watchdog (bits 4 & 5 of charge termination/timer control register) + if (clearRegisterBits(0x05, (1 << 4) || (1 << 5))) { + // Now disable the BATFET, bit 5 of the misc operation control register + success = setRegisterBits(0x07, (1 << 5)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): shipping mode is now ENABLED.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return success; +} + +// Disable shipping mode. +bool BatteryChargerBq24295::disableShippingMode (void) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Set the watchdog timer back to default (bit 4 of charge termination/timer control register) + if (setRegisterBits(0x05, (1 << 4))) { + // Now enable the BATFET, bit 5 of the misc operation control register + success = clearRegisterBits(0x07, (1 << 5)); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): shipping mode is now DISABLED.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return success; +} + +// Check if shipping mode is enabled. +bool BatteryChargerBq24295::isShippingModeEnabled (void) +{ + bool isEnabled = false; + char reg; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // To be in shipping mode the watchdog has to be disabled + if (getRegister(0x05, ®)) { + // Check bits 4 & 5 of the charge termination/timer control register for zero + if ((reg & ((1 << 4) || (1 << 5))) == 0) { + // Now see if the BATFET is disabled (bit 5 of the misc operation control register) + if (getRegister(0x07, ®) && ((reg & (1 << 5)) != 0)) { + isEnabled = true; + } + } +#ifdef DEBUG_BQ24295 + if (isEnabled) { + printf("BatteryChargerBq24295 (I2C 0x%02x): shipping mode is ENABLED.\r\n", gAddress >> 1); + } else { + printf("BatteryChargerBq24295 (I2C 0x%02x): shipping mode is DISABLED.\r\n", gAddress >> 1); + } +#endif + } + gpI2c->unlock(); + } + + return isEnabled; +} + +// Read a register on the chip. +bool BatteryChargerBq24295::advancedGet(char address, char *pValue) +{ + bool success = false; + char value; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Read the register + if (getRegister(address, &value)) { + success = true; +#ifdef DEBUG_BQ24295 + printf("BatteryChargerBq24295 (I2C 0x%02x): read 0x%02x from address 0x%02x.\n", gAddress >> 1, value, address); +#endif + if (pValue != NULL) { + *pValue = value; + } + } + gpI2c->unlock(); + } + + return success; +} + +// Set a register on the chip. +// TODO test +bool BatteryChargerBq24295::advancedSet(char address, char value) +{ + bool success = false; + + if (gReady && (gpI2c != NULL)) { + gpI2c->lock(); + // Set the register + success = setRegister (address, value); +#ifdef DEBUG_BQ24295 + if (success) { + printf("BatteryChargerBq24295 (I2C 0x%02x): wrote 0x%02x to address 0x%02x.\n", gAddress >> 1, value, address); + } +#endif + gpI2c->unlock(); + } + + return success; +} + +/* End Of File */