1447 lines
43 KiB
C++
1447 lines
43 KiB
C++
/**
|
||
*
|
||
* @license MIT License
|
||
*
|
||
* Copyright (c) 2024 lewis he
|
||
*
|
||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
* of this software and associated documentation files (the "Software"), to deal
|
||
* in the Software without restriction, including without limitation the rights
|
||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
* copies of the Software, and to permit persons to whom the Software is
|
||
* furnished to do so, subject to the following conditions:
|
||
*
|
||
* The above copyright notice and this permission notice shall be included in all
|
||
* copies or substantial portions of the Software.
|
||
*
|
||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
* SOFTWARE.
|
||
*
|
||
* @file PowersBQ25896.tpp
|
||
* @author Lewis He (lewishe@outlook.com)
|
||
* @date 2024-10-29
|
||
*
|
||
*/
|
||
#if defined(ARDUINO)
|
||
#include <Arduino.h>
|
||
#else
|
||
#include <math.h>
|
||
#endif /*ARDUINO*/
|
||
#include "XPowersCommon.tpp"
|
||
#include "REG/GeneralPPMConstants.h"
|
||
#include "REG/BQ25896Constants.h"
|
||
|
||
class PowersBQ25896 :
|
||
public XPowersCommon<PowersBQ25896>
|
||
{
|
||
friend class XPowersCommon<PowersBQ25896>;
|
||
public:
|
||
|
||
enum BusStatus {
|
||
BUS_STATE_NOINPUT,
|
||
BUS_STATE_USB_SDP,
|
||
BUS_STATE_ADAPTER,
|
||
BUS_STATE_OTG
|
||
} ;
|
||
|
||
enum ChargeStatus {
|
||
CHARGE_STATE_NO_CHARGE,
|
||
CHARGE_STATE_PRE_CHARGE,
|
||
CHARGE_STATE_FAST_CHARGE,
|
||
CHARGE_STATE_DONE,
|
||
CHARGE_STATE_UNKOWN,
|
||
} ;
|
||
|
||
enum NTCStatus {
|
||
BUCK_NTC_NORMAL = 0,
|
||
BUCK_NTC_WARM = 2,
|
||
BUCK_NTC_COOL = 3,
|
||
BUCK_NTC_COLD = 5,
|
||
BUCK_NTC_HOT = 6,
|
||
};
|
||
|
||
enum BoostNTCStatus {
|
||
BOOST_NTC_NORMAL = 0,
|
||
BOOST_NTC_COLD = 5,
|
||
BOOST_NTC_HOT = 6,
|
||
};
|
||
|
||
enum WatchdogConfig {
|
||
TIMER_OUT_40SEC, //40 Second
|
||
TIMER_OUT_80SEC, //80 Second
|
||
TIMER_OUT_160SEC, //160 Second
|
||
} ;
|
||
|
||
enum MeasureMode {
|
||
ONE_SHORT,
|
||
CONTINUOUS,
|
||
};
|
||
|
||
enum BoostFreq {
|
||
BOOST_FREQ_1500KHZ,
|
||
BOOST_FREQ_500KHZ,
|
||
};
|
||
|
||
enum ExitBoostModeVolt {
|
||
MINI_VOLT_2V9,
|
||
MINI_VOLT_2V5
|
||
};
|
||
|
||
enum FastChargeThreshold {
|
||
FAST_CHG_THR_2V8,
|
||
FAST_CHG_THR_3V0
|
||
};
|
||
|
||
enum RechargeThresholdOffset {
|
||
RECHARGE_OFFSET_100MV,
|
||
RECHARGE_OFFSET_200MV
|
||
};
|
||
|
||
enum FastChargeTimer {
|
||
FAST_CHARGE_TIMER_5H,
|
||
FAST_CHARGE_TIMER_8H,
|
||
FAST_CHARGE_TIMER_12H,
|
||
FAST_CHARGE_TIMER_20H,
|
||
};
|
||
|
||
enum JeitaLowTemperatureCurrent {
|
||
JEITA_LOW_TEMP_50, //50% of ICHG (REG04[6:0])
|
||
JEITA_LOW_TEMP_20, //20% of ICHG (REG04[6:0])
|
||
};
|
||
|
||
enum BoostCurrentLimit {
|
||
BOOST_CUR_LIMIT_500MA,
|
||
BOOST_CUR_LIMIT_750MA,
|
||
BOOST_CUR_LIMIT_1200MA,
|
||
BOOST_CUR_LIMIT_1400MA,
|
||
BOOST_CUR_LIMIT_1650MA,
|
||
BOOST_CUR_LIMIT_1875MA,
|
||
BOOST_CUR_LIMIT_2150MA,
|
||
} ;
|
||
|
||
#if defined(ARDUINO)
|
||
PowersBQ25896(TwoWire &w, int sda = SDA, int scl = SCL, uint8_t addr = BQ25896_SLAVE_ADDRESS)
|
||
{
|
||
__wire = &w;
|
||
__sda = sda;
|
||
__scl = scl;
|
||
__addr = addr;
|
||
}
|
||
#endif
|
||
|
||
PowersBQ25896(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback)
|
||
{
|
||
thisReadRegCallback = readRegCallback;
|
||
thisWriteRegCallback = writeRegCallback;
|
||
__addr = addr;
|
||
}
|
||
|
||
PowersBQ25896()
|
||
{
|
||
#if defined(ARDUINO)
|
||
__wire = &Wire;
|
||
__sda = SDA;
|
||
__scl = SCL;
|
||
#endif
|
||
__addr = BQ25896_SLAVE_ADDRESS;
|
||
}
|
||
|
||
~PowersBQ25896()
|
||
{
|
||
log_d("~PowersBQ25896");
|
||
deinit();
|
||
}
|
||
|
||
#if defined(ARDUINO)
|
||
bool init(TwoWire &w, int sda = SDA, int scl = SCL, uint8_t addr = BQ25896_SLAVE_ADDRESS)
|
||
{
|
||
__wire = &w;
|
||
__sda = sda;
|
||
__scl = scl;
|
||
__addr = addr;
|
||
__irq_mask = 0;
|
||
return begin();
|
||
}
|
||
#endif
|
||
|
||
const char *getChipName()
|
||
{
|
||
return getChipID() == BQ25896_DEV_REV ? "BQ25896" : "Unknown";
|
||
}
|
||
|
||
bool init()
|
||
{
|
||
return begin();
|
||
}
|
||
|
||
void deinit()
|
||
{
|
||
end();
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_00H ✅
|
||
**************************************************/
|
||
// USB input path is disabled and can only be reset by disconnecting
|
||
// the power supply, otherwise the power cannot be turned on
|
||
void enterHizMode()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_00H, 7);
|
||
}
|
||
|
||
void exitHizMode()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_00H, 7);
|
||
}
|
||
|
||
bool isHizMode()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_00H, 7);
|
||
}
|
||
|
||
// Enable ILIM Pin
|
||
void enableCurrentLimitPin()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_00H, 6);
|
||
}
|
||
|
||
void disableCurrentLimitPin()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_00H, 6);
|
||
}
|
||
|
||
bool isEnableCurrentLimitPin()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_00H, 6);
|
||
}
|
||
|
||
// Input Current Limit
|
||
// Offset: 100mA
|
||
// Range: 100mA (000000) – 3.25A (111111)
|
||
// Default:0001000 (500mA)
|
||
// (Actual input current limit is the lower of I2C or ILIM pin)
|
||
// IINLIM bits are changed automaticallly after input source
|
||
// type detection is completed
|
||
// bq25896
|
||
// PSEL = Hi (USB500) = 500mA
|
||
// PSEL = Lo = 3.25A
|
||
bool setInputCurrentLimit(uint16_t milliampere)
|
||
{
|
||
if (milliampere % POWERS_BQ25896_IN_CURRENT_STEP) {
|
||
log_e("Mistake ! The steps is must %u mA", POWERS_BQ25896_IN_CURRENT_STEP);
|
||
return false;
|
||
}
|
||
if (milliampere < POWERS_BQ25896_IN_CURRENT_MIN) {
|
||
milliampere = POWERS_BQ25896_IN_CURRENT_MIN;
|
||
}
|
||
if (milliampere > POWERS_BQ25896_IN_CURRENT_MAX) {
|
||
milliampere = POWERS_BQ25896_IN_CURRENT_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_00H);
|
||
if (val == -1)
|
||
return false;
|
||
val &= 0xC0;
|
||
milliampere = ((milliampere - POWERS_BQ25896_IN_CURRENT_MIN) / POWERS_BQ25896_IN_CURRENT_STEP);
|
||
val |= milliampere;
|
||
return writeRegister(POWERS_PPM_REG_00H, val) != -1;
|
||
}
|
||
|
||
uint32_t getInputCurrentLimit()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_00H);
|
||
if (val == -1)
|
||
return false;
|
||
val &= 0x3F;
|
||
return (val * POWERS_BQ25896_IN_CURRENT_STEP) + POWERS_BQ25896_IN_CURRENT_MIN;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_01H ✅
|
||
**************************************************/
|
||
|
||
// Boost Mode Hot Temperature Monitor Threshold
|
||
// 0x0 – VBHOT1 Threshold (34.75%) (default)
|
||
// 0x01 – VBHOT0 Threshold (Typ. 37.75%)
|
||
// 0x02 – VBHOT2 Threshold (Typ. 31.25%)
|
||
// 0x03 – Disable boost mode thermal protection
|
||
void setBoostModeHotTemperatureMonitorThreshold(uint8_t params)
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_01H);
|
||
if (val == -1)return;
|
||
val &= 0x3F;
|
||
val |= (params << 6);
|
||
writeRegister(POWERS_PPM_REG_01H, val);
|
||
}
|
||
|
||
// Boost Mode Cold Temperature Monitor Threshold
|
||
// 0 – VBCOLD0 Threshold (Typ. 77%) (default)
|
||
// 1 – VBCOLD1 Threshold (Typ. 80%)
|
||
void setBoostModeColdTemperatureMonitorThreshold(uint8_t params)
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_01H);
|
||
if (val == -1)return;
|
||
val &= 0xDF;
|
||
val |= ((params & 0x01) << 5);
|
||
writeRegister(POWERS_PPM_REG_01H, val);
|
||
}
|
||
|
||
// Input Voltage Limit Offset
|
||
// Default: 600mV (00110)
|
||
// Range: 0mV – 3100mV
|
||
// Minimum VINDPM threshold is clamped at 3.9V
|
||
// Maximum VINDPM threshold is clamped at 15.3V
|
||
// When VBUS at noLoad is ≤ 6V, the VINDPM_OS is used to calculate VINDPM threhold
|
||
// When VBUS at noLoad is > 6V, the VINDPM_OS multiple by 2 is used to calculate VINDPM threshold.
|
||
void setInputVoltageLimitOffset(uint16_t millivolt)
|
||
{
|
||
if (millivolt % POWERS_BQ25896_IN_CURRENT_OFFSET_STEP) {
|
||
log_e("Mistake ! The steps is must %u mA", POWERS_BQ25896_IN_CURRENT_OFFSET_STEP);
|
||
return;
|
||
}
|
||
if (millivolt > POWERS_BQ25896_IN_CURRENT_OFFSET_MAX) {
|
||
millivolt = POWERS_BQ25896_IN_CURRENT_OFFSET_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_01H);
|
||
val &= 0xE0;
|
||
millivolt = (millivolt / POWERS_BQ25896_IN_CURRENT_OFFSET_STEP);
|
||
val |= millivolt;
|
||
writeRegister(POWERS_PPM_REG_01H, val);
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_02H ✅
|
||
**************************************************/
|
||
bool enableMeasure(MeasureMode mode = CONTINUOUS)
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_02H);
|
||
switch (mode) {
|
||
case CONTINUOUS:
|
||
val |= _BV(6);
|
||
break;
|
||
case ONE_SHORT:
|
||
val &= (~_BV(6));
|
||
default:
|
||
break;
|
||
}
|
||
val |= _BV(7);
|
||
return writeRegister(POWERS_PPM_REG_02H, val) != -1;
|
||
}
|
||
|
||
bool disableMeasure()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_02H);
|
||
if (val == -1) {
|
||
return false;
|
||
}
|
||
val &= (~_BV(7));
|
||
val &= (~_BV(6));
|
||
return writeRegister(POWERS_PPM_REG_02H, val) != 1;
|
||
}
|
||
|
||
bool setBoostFreq(BoostFreq freq)
|
||
{
|
||
switch (freq) {
|
||
case BOOST_FREQ_500KHZ:
|
||
return setRegisterBit(POWERS_PPM_REG_02H, 5);
|
||
case BOOST_FREQ_1500KHZ:
|
||
return clrRegisterBit(POWERS_PPM_REG_02H, 5);
|
||
default:
|
||
break;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
BoostFreq getBoostFreq()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_02H, 5) ?
|
||
BOOST_FREQ_500KHZ :
|
||
BOOST_FREQ_1500KHZ;
|
||
}
|
||
|
||
// Input Current Optimizer (ICO) Enable
|
||
void enableInputCurrentOptimizer()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_02H, 4);
|
||
}
|
||
|
||
// Input Current Optimizer (ICO) Disable
|
||
void disableInputCurrentOptimizer()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_02H, 4);
|
||
}
|
||
|
||
// Enable Force Input Detection , Force PSEL detection
|
||
void enableInputDetection()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_02H, 1);
|
||
}
|
||
|
||
// Disable Force Input Detection , Not in PSEL detection (default)
|
||
void disableInputDetection()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_02H, 1);
|
||
}
|
||
|
||
// Get Force DP/DM detection
|
||
bool isEnableInputDetection()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_02H, 1);
|
||
}
|
||
|
||
// Enable PSEL detection when VBUS is plugged-in (default)
|
||
void enableAutomaticInputDetection()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_02H, 0);
|
||
}
|
||
|
||
// Disable PSEL detection when VBUS is plugged-in
|
||
void disableAutomaticInputDetection()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_02H, 0);
|
||
}
|
||
|
||
// Get DPDM detection when BUS is plugged-in.
|
||
bool isEnableAutomaticInputDetection()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_02H, 0);
|
||
}
|
||
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_03H ✅
|
||
**************************************************/
|
||
|
||
// Return Battery Load status
|
||
bool isEnableBatLoad()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_03H, 7);
|
||
}
|
||
|
||
// Battery Load Disable
|
||
void disableBatLoad()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_03H, 7);
|
||
}
|
||
|
||
// Battery Load Enable
|
||
void enableBatLoad()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_03H, 7);
|
||
}
|
||
|
||
void feedWatchdog()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_03H, 6);
|
||
}
|
||
|
||
bool isEnableOTG()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_03H, 5);
|
||
}
|
||
|
||
void disableOTG()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_03H, 5);
|
||
/*
|
||
* After turning on the OTG function, the charging function will
|
||
* be automatically disabled. If the user does not disable the charging
|
||
* function, the charging function will be automatically enabled after
|
||
* turning off the OTG output.
|
||
* */
|
||
if (!__user_disable_charge) {
|
||
setRegisterBit(POWERS_PPM_REG_03H, 4);
|
||
}
|
||
}
|
||
|
||
bool enableOTG()
|
||
{
|
||
if (isVbusIn())
|
||
return false;
|
||
return setRegisterBit(POWERS_PPM_REG_03H, 5);
|
||
}
|
||
|
||
bool isEnableCharge()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_03H, 4);
|
||
}
|
||
|
||
void disableCharge()
|
||
{
|
||
__user_disable_charge = true;
|
||
clrRegisterBit(POWERS_PPM_REG_03H, 4);
|
||
}
|
||
|
||
void enableCharge()
|
||
{
|
||
__user_disable_charge = false;
|
||
setRegisterBit(POWERS_PPM_REG_03H, 4);
|
||
}
|
||
|
||
bool setSysPowerDownVoltage(uint16_t millivolt)
|
||
{
|
||
if (millivolt % POWERS_BQ25896_SYS_VOL_STEPS) {
|
||
log_e("Mistake ! The steps is must %u mV", POWERS_BQ25896_SYS_VOL_STEPS);
|
||
return false;
|
||
}
|
||
if (millivolt < POWERS_BQ25896_SYS_VOFF_VOL_MIN) {
|
||
log_e("Mistake ! SYS minimum output voltage is %umV", POWERS_BQ25896_SYS_VOFF_VOL_MIN);
|
||
return false;
|
||
} else if (millivolt > POWERS_BQ25896_SYS_VOFF_VOL_MAX) {
|
||
log_e("Mistake ! SYS maximum output voltage is %umV", POWERS_BQ25896_SYS_VOFF_VOL_MAX);
|
||
return false;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_03H);
|
||
if (val == -1)return false;
|
||
val &= 0xF1;
|
||
val |= (millivolt - POWERS_BQ25896_SYS_VOFF_VOL_MIN) / POWERS_BQ25896_SYS_VOL_STEPS;
|
||
val <<= 1;
|
||
return 0 == writeRegister(POWERS_PPM_REG_03H, val);
|
||
|
||
}
|
||
|
||
uint16_t getSysPowerDownVoltage()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_03H);
|
||
if (val == -1)return 0;
|
||
val &= 0x0E;
|
||
val >>= 1;
|
||
return (val * POWERS_BQ25896_SYS_VOL_STEPS) + POWERS_BQ25896_SYS_VOFF_VOL_MIN;
|
||
}
|
||
|
||
// Minimum Battery Voltage (falling) to exit boost mode
|
||
void setExitBoostModeVoltage(enum ExitBoostModeVolt params)
|
||
{
|
||
switch (params) {
|
||
case MINI_VOLT_2V9:
|
||
clrRegisterBit(POWERS_PPM_REG_03H, 0);
|
||
break;
|
||
case MINI_VOLT_2V5:
|
||
setRegisterBit(POWERS_PPM_REG_03H, 0);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_04H ✅
|
||
**************************************************/
|
||
|
||
void enableCurrentPulseControl()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_04H, 7);
|
||
}
|
||
|
||
void disableCurrentPulseControl()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_04H, 7);
|
||
}
|
||
|
||
uint16_t getChargerConstantCurr()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_04H);
|
||
val &= 0x7F;
|
||
return val * POWERS_BQ25896_FAST_CHG_CUR_STEP;
|
||
}
|
||
|
||
/**
|
||
* @brief setChargerConstantCurr
|
||
* @note
|
||
* @param milliampere: Range:0~3008 mA / step:64mA
|
||
* @retval true : success false : failed
|
||
*/
|
||
bool setChargerConstantCurr(uint16_t milliampere)
|
||
{
|
||
if (milliampere % POWERS_BQ25896_FAST_CHG_CUR_STEP) {
|
||
log_e("Mistake ! The steps is must %u mA", POWERS_BQ25896_FAST_CHG_CUR_STEP);
|
||
return false;
|
||
}
|
||
if (milliampere > POWERS_BQ25896_FAST_CHG_CURRENT_MAX) {
|
||
milliampere = POWERS_BQ25896_FAST_CHG_CURRENT_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_04H);
|
||
val &= 0x80;
|
||
val |= (milliampere / POWERS_BQ25896_FAST_CHG_CUR_STEP);
|
||
return writeRegister(POWERS_PPM_REG_04H, val) != -1;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_05H ✅
|
||
**************************************************/
|
||
|
||
//Precharge Current Limit Range: 64mA ~ 1024mA ,step:64mA
|
||
bool setPrechargeCurr(uint16_t milliampere)
|
||
{
|
||
if (milliampere % POWERS_BQ25896_PRE_CHG_CUR_STEP) {
|
||
log_e("Mistake ! The steps is must %u mA", POWERS_BQ25896_PRE_CHG_CUR_STEP);
|
||
return false;
|
||
}
|
||
if (milliampere < POWERS_BQ25896_PRE_CHG_CURRENT_MIN) {
|
||
milliampere = POWERS_BQ25896_PRE_CHG_CURRENT_MIN;
|
||
}
|
||
if (milliampere > POWERS_BQ25896_PRE_CHG_CURRENT_MAX) {
|
||
milliampere = POWERS_BQ25896_PRE_CHG_CURRENT_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_05H);
|
||
val &= 0x0F;
|
||
milliampere = ((milliampere - POWERS_BQ25896_PRE_CHG_CUR_BASE) / POWERS_BQ25896_PRE_CHG_CUR_STEP);
|
||
val |= milliampere << 4;
|
||
return writeRegister(POWERS_PPM_REG_05H, val) != -1;
|
||
}
|
||
|
||
uint16_t getPrechargeCurr(void)
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_05H);
|
||
val &= 0xF0;
|
||
val >>= 4;
|
||
return POWERS_BQ25896_PRE_CHG_CUR_STEP + (val * POWERS_BQ25896_PRE_CHG_CUR_STEP);
|
||
}
|
||
|
||
//Precharge Current Limit Range: 64mA ~ 1024mA ,step:64mA
|
||
bool setTerminationCurr(uint16_t milliampere)
|
||
{
|
||
if (milliampere % POWERS_BQ25896_TERM_CHG_CUR_STEP) {
|
||
log_e("Mistake ! The steps is must %u mA", POWERS_BQ25896_TERM_CHG_CUR_STEP);
|
||
return false;
|
||
}
|
||
if (milliampere < POWERS_BQ25896_TERM_CHG_CURRENT_MIN) {
|
||
milliampere = POWERS_BQ25896_TERM_CHG_CURRENT_MIN;
|
||
}
|
||
if (milliampere > POWERS_BQ25896_TERM_CHG_CURRENT_MAX) {
|
||
milliampere = POWERS_BQ25896_TERM_CHG_CURRENT_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_05H);
|
||
val &= 0xF0;
|
||
milliampere = ((milliampere - POWERS_BQ25896_TERM_CHG_CUR_BASE) / POWERS_BQ25896_TERM_CHG_CUR_STEP);
|
||
val |= milliampere;
|
||
return writeRegister(POWERS_PPM_REG_05H, val) != -1;
|
||
}
|
||
|
||
uint16_t getTerminationCurr(void)
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_05H);
|
||
val &= 0x0F;
|
||
return POWERS_BQ25896_TERM_CHG_CUR_STEP + (val * POWERS_BQ25896_TERM_CHG_CUR_STEP);
|
||
}
|
||
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_06H ✅
|
||
**************************************************/
|
||
uint16_t getChargeTargetVoltage()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_06H);
|
||
val = (val & 0xFC) >> 2;
|
||
if (val > 0x30) {
|
||
return POWERS_BQ25896_FAST_CHG_VOL_MAX;
|
||
}
|
||
return val * POWERS_BQ25896_CHG_VOL_STEP + POWERS_BQ25896_CHG_VOL_BASE;
|
||
}
|
||
|
||
// Charge Voltage Limit Range:3840 ~ 4608mV ,step:16 mV
|
||
bool setChargeTargetVoltage(uint16_t millivolt)
|
||
{
|
||
if (millivolt % POWERS_BQ25896_CHG_VOL_STEP) {
|
||
log_e("Mistake ! The steps is must %u mV", POWERS_BQ25896_CHG_VOL_STEP);
|
||
return false;
|
||
}
|
||
if (millivolt < POWERS_BQ25896_FAST_CHG_VOL_MIN) {
|
||
millivolt = POWERS_BQ25896_FAST_CHG_VOL_MIN;
|
||
}
|
||
if (millivolt > POWERS_BQ25896_FAST_CHG_VOL_MAX) {
|
||
millivolt = POWERS_BQ25896_FAST_CHG_VOL_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_06H);
|
||
val &= 0x03;
|
||
val |= (((millivolt - POWERS_BQ25896_CHG_VOL_BASE) / POWERS_BQ25896_CHG_VOL_STEP) << 2);
|
||
return writeRegister(POWERS_PPM_REG_06H, val) != -1;
|
||
}
|
||
|
||
// Battery Precharge to Fast Charge Threshold
|
||
void setFastChargeThreshold(enum FastChargeThreshold threshold)
|
||
{
|
||
switch (threshold) {
|
||
case FAST_CHG_THR_2V8:
|
||
clrRegisterBit(POWERS_PPM_REG_06H, 1);
|
||
break;
|
||
case FAST_CHG_THR_3V0:
|
||
setRegisterBit(POWERS_PPM_REG_06H, 1);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Battery Recharge Threshold Offset(below Charge Voltage Limit)
|
||
void setBatteryRechargeThresholdOffset(enum RechargeThresholdOffset offset)
|
||
{
|
||
switch (offset) {
|
||
case RECHARGE_OFFSET_100MV:
|
||
clrRegisterBit(POWERS_PPM_REG_06H, 0);
|
||
break;
|
||
case RECHARGE_OFFSET_200MV:
|
||
setRegisterBit(POWERS_PPM_REG_06H, 0);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_07H ✅
|
||
**************************************************/
|
||
|
||
// Charging Termination Enable
|
||
void enableChargingTermination()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_07H, 7);
|
||
}
|
||
|
||
// Charging Termination Enable
|
||
void disableChargingTermination()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_07H, 7);
|
||
}
|
||
|
||
// Charging Termination Enable
|
||
bool isEnableChargingTermination()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_07H, 7);
|
||
}
|
||
|
||
// STAT Pin function
|
||
void disableStatPin()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_07H, 6);
|
||
}
|
||
|
||
void enableStatPin()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_07H, 6);
|
||
}
|
||
|
||
bool isEnableStatPin()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_07H, 6) == false;
|
||
}
|
||
|
||
// I2C Watchdog Timer Setting
|
||
bool isEnableWatchdog()
|
||
{
|
||
int regVal = readRegister(POWERS_PPM_REG_07H);
|
||
if (regVal == -1) {
|
||
log_e("Config watch dog failed!");
|
||
return false;
|
||
}
|
||
regVal >>= 4;
|
||
return regVal & 0x03;
|
||
}
|
||
|
||
void disableWatchdog()
|
||
{
|
||
int regVal = readRegister(POWERS_PPM_REG_07H);
|
||
regVal &= 0xCF;
|
||
writeRegister(POWERS_PPM_REG_07H, regVal);
|
||
}
|
||
|
||
void enableWatchdog(enum WatchdogConfig val)
|
||
{
|
||
int regVal = readRegister(POWERS_PPM_REG_07H);
|
||
regVal &= 0xCF;
|
||
switch (val) {
|
||
case TIMER_OUT_40SEC:
|
||
writeRegister(POWERS_PPM_REG_07H, regVal | 0x10);
|
||
break;
|
||
case TIMER_OUT_80SEC:
|
||
writeRegister(POWERS_PPM_REG_07H, regVal | 0x20);
|
||
break;
|
||
case TIMER_OUT_160SEC:
|
||
writeRegister(POWERS_PPM_REG_07H, regVal | 0x30);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void disableChargingSafetyTimer()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_07H, 3);
|
||
}
|
||
|
||
void enableChargingSafetyTimer()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_07H, 3);
|
||
}
|
||
|
||
bool isEnableChargingSafetyTimer()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_07H, 3);
|
||
}
|
||
|
||
void setFastChargeTimer(FastChargeTimer timer)
|
||
{
|
||
int val;
|
||
switch (timer) {
|
||
case FAST_CHARGE_TIMER_5H:
|
||
case FAST_CHARGE_TIMER_8H:
|
||
case FAST_CHARGE_TIMER_12H:
|
||
case FAST_CHARGE_TIMER_20H:
|
||
val = readRegister(POWERS_PPM_REG_07H);
|
||
if (val == -1)
|
||
return;
|
||
val &= 0xF1;
|
||
val |= (timer << 1);
|
||
writeRegister(POWERS_PPM_REG_07H, val);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
FastChargeTimer getFastChargeTimer()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_07H);
|
||
return static_cast<FastChargeTimer>((val & 0x0E) >> 1);
|
||
}
|
||
|
||
// JEITA Low Temperature Current Setting
|
||
// JEITA(Japan Electronics and Information Technology Industries Association)
|
||
// https://en.wikipedia.org/wiki/Japan_Electronics_and_Information_Technology_Industries_Association
|
||
void setJeitaLowTemperatureCurrent(enum JeitaLowTemperatureCurrent params)
|
||
{
|
||
switch (params) {
|
||
case JEITA_LOW_TEMP_50:
|
||
clrRegisterBit(POWERS_PPM_REG_07H, 0);
|
||
break;
|
||
case JEITA_LOW_TEMP_20:
|
||
setRegisterBit(POWERS_PPM_REG_07H, 0);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_08H ✅
|
||
**************************************************/
|
||
// IR Compensation Resistor Setting
|
||
// Range: 0 – 140mΩ
|
||
// Default: 0Ω (000) (i.e. Disable IRComp)
|
||
void setIRCompensationResistor(uint16_t params)
|
||
{
|
||
if (params % POWERS_BQ25896_BAT_COMP_STEPS) {
|
||
log_e("Mistake ! The steps is must %u mA", POWERS_BQ25896_BAT_COMP_STEPS);
|
||
return;
|
||
}
|
||
if (params > POWERS_BQ25896_TERM_CHG_CURRENT_MAX) {
|
||
params = POWERS_BQ25896_TERM_CHG_CURRENT_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_08H);
|
||
if (val == -1)return;
|
||
val &= 0x1F;
|
||
params = (params / POWERS_BQ25896_BAT_COMP_STEPS);
|
||
val |= (params << 5);
|
||
writeRegister(POWERS_PPM_REG_08H, val);
|
||
}
|
||
|
||
// IR Compensation Voltage Clamp
|
||
// above VREG (REG06[7:2])
|
||
// Offset: 0mV
|
||
// Range: 0-224mV
|
||
// Default: 0mV (000)
|
||
void setIRCompensationVoltageClamp(uint16_t params)
|
||
{
|
||
if (params % POWERS_BQ25896_VCLAMP_STEPS) {
|
||
log_e("Mistake ! The steps is must %u mA", POWERS_BQ25896_VCLAMP_STEPS);
|
||
return;
|
||
}
|
||
if (params > POWERS_BQ25896_TERM_CHG_CURRENT_MAX) {
|
||
params = POWERS_BQ25896_TERM_CHG_CURRENT_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_08H);
|
||
if (val == -1)return;
|
||
val &= 0xE3;
|
||
params = (params / POWERS_BQ25896_VCLAMP_STEPS);
|
||
val |= (params << 2);
|
||
writeRegister(POWERS_PPM_REG_08H, val);
|
||
}
|
||
|
||
// Thermal Regulation Threshold
|
||
// 0x0 – 60°C
|
||
// 0x1 – 80°C
|
||
// 0x2 – 100°C
|
||
// 0x3 – 120°C (default)
|
||
void setThermalRegulationThreshold(uint8_t params)
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_08H);
|
||
if (val == -1)return;
|
||
val &= 0xE3;
|
||
val |= (params);
|
||
writeRegister(POWERS_PPM_REG_08H, val);
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_09H
|
||
**************************************************/
|
||
// Force Start Input Current Optimizer (ICO)
|
||
// 0 – Do not force ICO (default)
|
||
// 1 – Force ICO
|
||
// Note: This bit is can only be set only and always returns to 0 after ICO starts
|
||
void forceInputCurrentOptimizer(bool force)
|
||
{
|
||
force ? setRegisterBit(POWERS_PPM_REG_09H, 7) : clrRegisterBit(POWERS_PPM_REG_09H, 7);
|
||
}
|
||
|
||
// Safety Timer Setting during DPM or Thermal Regulation
|
||
// 0 – Safety timer not slowed by 2X during input DPM or thermal regulation
|
||
// 1 – Safety timer slowed by 2X during input DPM or thermal regulation (default)
|
||
void setThermalRegulation(uint8_t params)
|
||
{
|
||
params ? setRegisterBit(POWERS_PPM_REG_09H, 6) : clrRegisterBit(POWERS_PPM_REG_09H, 6) ;
|
||
}
|
||
|
||
|
||
// Turn off the battery power supply path. It can only be turned off when the
|
||
// battery is powered. It cannot be turned off when USB is connected.
|
||
// The device can only be powered on by pressing the PWR button or by connecting the power supply.
|
||
void shutdown()
|
||
{
|
||
disableBatterPowerPath();
|
||
}
|
||
|
||
// Close battery power path
|
||
void disableBatterPowerPath()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_09H, 5); //Force BATFET Off : BATFET_DIS
|
||
}
|
||
|
||
// Enable battery power path
|
||
void enableBatterPowerPath()
|
||
{
|
||
clrRegisterBit(POWERS_PPM_REG_09H, 5); //Force BATFET Off : BATFET_DIS
|
||
}
|
||
|
||
// JEITA High Temperature Voltage Setting
|
||
// JEITA(Japan Electronics and Information Technology Industries Association)
|
||
// https://en.wikipedia.org/wiki/Japan_Electronics_and_Information_Technology_Industries_Association
|
||
// 0 – Set Charge Voltage to VREG-200mV during JEITA hig temperature(default)
|
||
// 1 – Set Charge Voltage to VREG during JEITA high temperature
|
||
void setJeitaHighTemperature(uint8_t params)
|
||
{
|
||
params ? setRegisterBit(POWERS_PPM_REG_09H, 4) : clrRegisterBit(POWERS_PPM_REG_09H, 4) ;
|
||
}
|
||
|
||
// BATFET turn off delay control
|
||
// 0 – BATFET turn off immediately when BATFET_DIS bit is set (default)
|
||
// 1 – BATFET turn off delay by tSM_DLY when BATFET_DIS bit is set
|
||
void setTurnOffDelay(uint8_t params)
|
||
{
|
||
params ? setRegisterBit(POWERS_PPM_REG_09H, 3) : clrRegisterBit(POWERS_PPM_REG_09H, 3) ;
|
||
}
|
||
|
||
// BATFET full system reset enable
|
||
// 0 – Disable BATFET full system reset
|
||
// 1 – Enable BATFET full system reset (default)
|
||
void setFullSystemReset(uint8_t params)
|
||
{
|
||
params ? setRegisterBit(POWERS_PPM_REG_09H, 2) : clrRegisterBit(POWERS_PPM_REG_09H, 2) ;
|
||
}
|
||
|
||
// Current pulse control voltage up enable
|
||
// 0 – Disable (default)
|
||
// 1 – Enable
|
||
// Note: This bit is can only be set when EN_PUMPX bit is set and returns to 0 after current pulse control sequence is completed
|
||
void setCurrentPulseControlVoltageUp(uint8_t params)
|
||
{
|
||
params ? setRegisterBit(POWERS_PPM_REG_09H, 1) : clrRegisterBit(POWERS_PPM_REG_09H, 1) ;
|
||
}
|
||
|
||
// Current pulse control voltage down enable
|
||
// 0 – Disable (default)
|
||
// 1 – Enable
|
||
// Note: This bit is can only be set when EN_PUMPX bit is set and returns to 0 after current pulse control sequence is completed
|
||
void setCurrentPulseControlVoltageDown(uint8_t params)
|
||
{
|
||
params ? setRegisterBit(POWERS_PPM_REG_09H, 0) : clrRegisterBit(POWERS_PPM_REG_09H, 0) ;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_0AH ✅
|
||
**************************************************/
|
||
|
||
// Boost Mode Voltage Regulation: 4550mV ~ 5510mV
|
||
bool setBoostVoltage(uint16_t millivolt)
|
||
{
|
||
if (millivolt % POWERS_BQ25896_BOOTS_VOL_STEP) {
|
||
log_e("Mistake ! The steps is must %u mV", POWERS_BQ25896_BOOTS_VOL_STEP);
|
||
return false;
|
||
}
|
||
if (millivolt < POWERS_BQ25896_BOOST_VOL_MIN) {
|
||
millivolt = POWERS_BQ25896_BOOST_VOL_MIN;
|
||
}
|
||
if (millivolt > POWERS_BQ25896_BOOST_VOL_MAX) {
|
||
millivolt = POWERS_BQ25896_BOOST_VOL_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_0AH);
|
||
val &= 0xF0;
|
||
val |= (((millivolt - POWERS_BQ25896_BOOTS_VOL_BASE) / POWERS_BQ25896_BOOTS_VOL_STEP) << 4);
|
||
return writeRegister(POWERS_PPM_REG_0AH, val) != -1;
|
||
}
|
||
|
||
// Boost Current Limit: 500mA ~ 150 mA
|
||
bool setBoostCurrentLimit(BoostCurrentLimit milliampere)
|
||
{
|
||
if (milliampere > BOOST_CUR_LIMIT_2150MA) {
|
||
return false;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_0AH);
|
||
val &= 0x03;
|
||
val |= milliampere;
|
||
return writeRegister(POWERS_PPM_REG_0AH, val) != -1;
|
||
}
|
||
|
||
// PFM mode allowed in boost mode
|
||
// 0 – Allow PFM in boost mode (default)
|
||
// 1 – Disable PFM in boost mode
|
||
void setBoostModeUsePFM(bool enable)
|
||
{
|
||
enable ? clrRegisterBit(POWERS_PPM_REG_0AH, 3) : setRegisterBit(POWERS_PPM_REG_0AH, 3);
|
||
}
|
||
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_0BH ✅
|
||
**************************************************/
|
||
|
||
bool isOTG()
|
||
{
|
||
return getBusStatus() == BUS_STATE_OTG;
|
||
}
|
||
|
||
bool isCharging(void)
|
||
{
|
||
return chargeStatus() != CHARGE_STATE_NO_CHARGE;
|
||
}
|
||
|
||
bool isChargeDone()
|
||
{
|
||
return chargeStatus() == CHARGE_STATE_DONE;
|
||
}
|
||
|
||
bool isPowerGood()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_0BH, 2);
|
||
}
|
||
|
||
BusStatus getBusStatus()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_0BH);
|
||
return static_cast<BusStatus>((val >> 5) & 0x07);
|
||
}
|
||
|
||
const char *getBusStatusString()
|
||
{
|
||
BusStatus status = getBusStatus();
|
||
switch (status) {
|
||
case BUS_STATE_NOINPUT:
|
||
return "No input";
|
||
case BUS_STATE_USB_SDP:
|
||
return "USB Host SDP";
|
||
case BUS_STATE_ADAPTER:
|
||
return "Adapter";
|
||
case BUS_STATE_OTG:
|
||
return "OTG";
|
||
default:
|
||
return "Unknown";
|
||
}
|
||
}
|
||
|
||
ChargeStatus chargeStatus()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_0BH);
|
||
if (val == -1)return CHARGE_STATE_UNKOWN;
|
||
return static_cast<ChargeStatus>((val >> 3) & 0x03);
|
||
}
|
||
|
||
const char *getChargeStatusString()
|
||
{
|
||
ChargeStatus status = chargeStatus();
|
||
switch (status) {
|
||
case CHARGE_STATE_NO_CHARGE:
|
||
return "Not Charging";
|
||
case CHARGE_STATE_PRE_CHARGE:
|
||
return "Pre-charge";
|
||
case CHARGE_STATE_FAST_CHARGE:
|
||
return "Fast Charging";
|
||
case CHARGE_STATE_DONE:
|
||
return "Charge Termination Done";
|
||
default:
|
||
return "Unknown";
|
||
}
|
||
}
|
||
|
||
// VSYS Regulation Status
|
||
// 0 – Not in VSYSMIN regulation (BAT > VSYSMIN)
|
||
// 1 – In VSYSMIN regulation (BAT < VSYSMIN)
|
||
bool getVsysRegulationStatus()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_0BH, 0);
|
||
}
|
||
|
||
const char *getVsysRegulationStatusString()
|
||
{
|
||
if (getVsysRegulationStatus()) {
|
||
return "BAT < VSYSMIN";
|
||
}
|
||
return "BAT > VSYSMIN";
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_0CH ✅
|
||
**************************************************/
|
||
|
||
// After reading the register, all will be cleared
|
||
uint8_t getFaultStatus(void)
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_0CH);
|
||
if (val == -1) {
|
||
return 0;
|
||
}
|
||
__irq_mask = val;
|
||
return __irq_mask;
|
||
}
|
||
|
||
// Watchdog Fault Status
|
||
// 0 – Normal
|
||
// 1- Watchdog timer expiration
|
||
bool isWatchdogFault()
|
||
{
|
||
return POWERS_BQ25896_IRQ_WTD_FAULT(__irq_mask);
|
||
}
|
||
|
||
// Boost Mode Fault Status
|
||
// 0 – Normal
|
||
// 1 – VBUS overloaded in OTG, or VBUS OVP, or battery is too low in boost mode
|
||
bool isBoostFault()
|
||
{
|
||
return POWERS_BQ25896_IRQ_BOOST_FAULT(__irq_mask);
|
||
}
|
||
|
||
// Charge Fault Status
|
||
// 00 – Normal
|
||
// 01 – Input fault (VBUS > VACOV or VBAT < VBUS < VVBUSMIN(typical 3.8V)
|
||
// 10 - Thermal shutdown
|
||
// 11 – Charge Safety Timer Expiration
|
||
uint8_t isChargeFault()
|
||
{
|
||
return POWERS_BQ25896_IRQ_CHG_FAULT(__irq_mask);
|
||
}
|
||
|
||
// Battery Fault Status
|
||
// 0 – Normal
|
||
// 1 – BATOVP (VBAT > VBATOVP)
|
||
bool isBatteryFault()
|
||
{
|
||
return POWERS_BQ25896_IRQ_BAT_FAULT(__irq_mask);
|
||
}
|
||
|
||
// NTC Fault Status
|
||
bool isNTCFault()
|
||
{
|
||
return POWERS_BQ25896_IRQ_NTC_FAULT(__irq_mask);
|
||
}
|
||
|
||
// NTC Fault Status string
|
||
uint8_t getNTCStatus()
|
||
{
|
||
return (__irq_mask & 0x07);
|
||
}
|
||
|
||
const char *getNTCStatusString()
|
||
{
|
||
uint8_t status = getNTCStatus();
|
||
if (isOTG()) {
|
||
// Boost mode
|
||
switch (status) {
|
||
case BOOST_NTC_NORMAL:
|
||
return "Boost mode NTC normal";
|
||
case BOOST_NTC_COLD:
|
||
return "Boost mode NTC cold";
|
||
case BOOST_NTC_HOT:
|
||
return "Boost mode NTC hot";
|
||
default:
|
||
break;
|
||
}
|
||
} else {
|
||
// Buck mode
|
||
switch (status) {
|
||
case BUCK_NTC_NORMAL:
|
||
return "Buck mode NTC normal";
|
||
case BUCK_NTC_WARM:
|
||
return "Buck mode NTC warm";
|
||
case BUCK_NTC_COOL:
|
||
case BUCK_NTC_COLD:
|
||
return "Buck mode NTC cold";
|
||
case BUCK_NTC_HOT:
|
||
return "Buck mode NTC hot";
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
return "Unknown";
|
||
}
|
||
|
||
// Debug
|
||
void getReadOnlyRegisterValue()
|
||
{
|
||
#ifdef ARDUINO //debug ..
|
||
static uint8_t last_val[8] = {0};
|
||
const uint8_t regis[] = {
|
||
POWERS_PPM_REG_0BH,
|
||
POWERS_PPM_REG_0CH,
|
||
// POWERS_PPM_REG_0EH, //BATTERY VOLTAGE
|
||
// POWERS_PPM_REG_0FH, //SYSTEM VOLTAGE
|
||
// POWERS_PPM_REG_10H, //NTC PERCENTAGE
|
||
// POWERS_PPM_REG_11H, //VBUS VOLTAGE
|
||
POWERS_PPM_REG_12H,
|
||
POWERS_PPM_REG_13H
|
||
};
|
||
Serial.println();
|
||
Serial.println("-------------------------");
|
||
for (uint32_t i = 0; i < sizeof(regis) / sizeof(regis[0]); ++i) {
|
||
int val = readRegister(regis[i]);
|
||
if (val == -1) {
|
||
continue;
|
||
}
|
||
if (last_val[i] != val) {
|
||
Serial.printf("\t---> REG%02X Prev:0x%02X ", regis[i], last_val[i]);
|
||
Serial.print(" BIN:"); Serial.print(last_val[i], BIN);
|
||
Serial.printf(" Curr: 0x%02X", val);
|
||
Serial.print(" BIN:"); Serial.println(val, BIN);
|
||
last_val[i] = val;
|
||
}
|
||
Serial.printf("\tREG%02XH:0x%X BIN:0b", regis[i], val);
|
||
Serial.println(val, BIN);
|
||
}
|
||
Serial.println("-------------------------");
|
||
#endif
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_0DH ✅
|
||
**************************************************/
|
||
// VINDPM Threshold Setting Method
|
||
// 0 – Run Relative VINDPM Threshold (default)
|
||
// 1 – Run Absolute VINDPM Threshold
|
||
// Note: Register is reset to default value when input source is plugged-in
|
||
void setVinDpmThresholdSetting(bool relative)
|
||
{
|
||
relative ? clrRegisterBit(POWERS_PPM_REG_0DH, 7) : setRegisterBit(POWERS_PPM_REG_0DH, 7);
|
||
}
|
||
|
||
// Absolute VINDPM Threshold
|
||
bool setVinDpmThreshold(uint16_t millivolt)
|
||
{
|
||
if (millivolt % POWERS_BQ25896_VINDPM_VOL_STEPS) {
|
||
log_e("Mistake ! The steps is must %u mV", POWERS_BQ25896_VINDPM_VOL_STEPS);
|
||
return false;
|
||
}
|
||
if (millivolt < POWERS_BQ25896_VINDPM_VOL_MIN) {
|
||
millivolt = POWERS_BQ25896_VINDPM_VOL_MIN;
|
||
}
|
||
if (millivolt > POWERS_BQ25896_VINDPM_VOL_MAX) {
|
||
millivolt = POWERS_BQ25896_VINDPM_VOL_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_0DH);
|
||
val &= 0x80;
|
||
val |= (((millivolt - POWERS_BQ25896_VINDPM_VOL_BASE) / POWERS_BQ25896_VINDPM_VOL_STEPS));
|
||
return writeRegister(POWERS_PPM_REG_0DH, val) != -1;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_0EH ✅
|
||
**************************************************/
|
||
// Thermal Regulation Status
|
||
// true – Normal
|
||
// false – In Thermal Regulation
|
||
bool isThermalRegulationNormal()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_0EH, 7) == false;
|
||
}
|
||
|
||
// ADC conversion of Battery Voltage /mv
|
||
uint16_t getBattVoltage()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_0EH);
|
||
if (val == -1)return 0;
|
||
val = POWERS_BQ25896_VBAT_MASK_VAL(val);
|
||
if (val == 0)return 0;
|
||
return (val * POWERS_BQ25896_VBAT_VOL_STEP) + POWERS_BQ25896_VBAT_BASE_VAL;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_0FH ✅
|
||
**************************************************/
|
||
|
||
// ADC conversion of System Voltage (VSYS)
|
||
uint16_t getSystemVoltage()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_0FH);
|
||
if (val == -1 || val == 0)return 0;
|
||
return (POWERS_BQ25896_VSYS_MASK_VAL(val) * POWERS_BQ25896_VSYS_VOL_STEP) + POWERS_BQ25896_VSYS_BASE_VAL;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_10H ✅
|
||
**************************************************/
|
||
|
||
// ADC conversion of TS Voltage (TS) as percentage of REGN
|
||
float getNTCPercentage()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_10H);
|
||
if (val == -1)return 0;
|
||
return (POWERS_BQ25896_NTC_MASK_VAL(val) * POWERS_BQ25896_NTC_VOL_STEP) + POWERS_BQ25896_NTC_BASE_VAL;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_11H ✅
|
||
**************************************************/
|
||
|
||
// VBUS Good Status
|
||
bool isVbusIn()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_11H, 7);
|
||
}
|
||
|
||
// ADC conversion of VBUS voltage (VBUS)
|
||
uint16_t getVbusVoltage()
|
||
{
|
||
if (!isVbusIn()) {
|
||
return 0;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_11H);
|
||
return (POWERS_BQ25896_VBUS_MASK_VAL(val) * POWERS_BQ25896_VBUS_VOL_STEP) + POWERS_BQ25896_VBUS_BASE_VAL;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_12H ✅
|
||
**************************************************/
|
||
|
||
// ADC conversion of Charge Current (IBAT) when VBAT > VBATSHORT
|
||
//* If the charger is disconnected, the value in the register
|
||
//* will remain the last value and will not be updated to 0.
|
||
uint16_t getChargeCurrent()
|
||
{
|
||
ChargeStatus status = chargeStatus();
|
||
if (status == CHARGE_STATE_NO_CHARGE) {
|
||
log_e("CHARGE_STATE_NO_CHARGE...");
|
||
return 0;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_12H);
|
||
if (val == 0 || val == -1) {
|
||
log_e("read reg failed !...");
|
||
return 0;
|
||
}
|
||
val = (val & 0x7F);
|
||
return (val * POWERS_BQ25896_CHG_STEP_VAL) ;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_13H ✅
|
||
**************************************************/
|
||
// VINDPM Status : DynamicPower-Path Management and Dynamic Power Management
|
||
bool isDynamicPowerManagement()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_13H, 7);
|
||
}
|
||
|
||
// IINDPM Status
|
||
bool isInputCurrentLimit()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_13H, 6);
|
||
}
|
||
|
||
// Input Current Limit in effect while Input Current Optimizer (ICO) is enabled
|
||
// Range: 100 ~ 3250 mA
|
||
bool setInputCurrentLimitOptimizer(uint16_t milliampere)
|
||
{
|
||
if (milliampere % POWERS_BQ25896_IN_CURRENT_OPT_STEP) {
|
||
log_e("Mistake ! The steps is must %u mA", POWERS_BQ25896_IN_CURRENT_OPT_STEP);
|
||
return false;
|
||
}
|
||
if (milliampere < POWERS_BQ25896_IN_CURRENT_OPT_MIN) {
|
||
milliampere = POWERS_BQ25896_IN_CURRENT_OPT_MIN;
|
||
}
|
||
if (milliampere > POWERS_BQ25896_IN_CURRENT_OPT_MAX) {
|
||
milliampere = POWERS_BQ25896_IN_CURRENT_OPT_MAX;
|
||
}
|
||
int val = readRegister(POWERS_PPM_REG_13H);
|
||
if (val == -1)
|
||
return false;
|
||
val &= 0x3F;
|
||
milliampere = ((milliampere - POWERS_BQ25896_IN_CURRENT_OPT_MIN) / POWERS_BQ25896_IN_CURRENT_STEP);
|
||
val |= milliampere;
|
||
return writeRegister(POWERS_PPM_REG_13H, val) != -1;
|
||
}
|
||
|
||
/***************************************************
|
||
* POWERS_PPM_REG_14H ✅
|
||
**************************************************/
|
||
void resetDefault()
|
||
{
|
||
setRegisterBit(POWERS_PPM_REG_14H, 7);
|
||
}
|
||
|
||
// Input Current Optimizer (ICO) Status
|
||
// true – Optimization is in progress
|
||
// false – Maximum Input Current Detected
|
||
bool isInputCurrentOptimizer()
|
||
{
|
||
return getRegisterBit(POWERS_PPM_REG_14H, 6) ;
|
||
}
|
||
|
||
// Device Revision:Default 10
|
||
uint8_t getChipID()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_14H);
|
||
if (val == -1)return 0;
|
||
return (val & 0x03);
|
||
}
|
||
|
||
// Device Configuration
|
||
uint8_t getDeviceConfig()
|
||
{
|
||
int val = readRegister(POWERS_PPM_REG_14H);
|
||
if (val == -1)return 0;
|
||
return (val >> 3) & 0x03;
|
||
}
|
||
|
||
private:
|
||
|
||
bool initImpl()
|
||
{
|
||
__user_disable_charge = false;
|
||
|
||
uint8_t rev = getChipID();
|
||
if (rev != BQ25896_DEV_REV) {
|
||
return false;
|
||
}
|
||
// Set the minimum operating voltage. Below this voltage, the PMU will protect
|
||
// setSysPowerDownVoltage(3300);
|
||
|
||
//Default disable Watchdog
|
||
disableWatchdog();
|
||
|
||
return true;
|
||
}
|
||
|
||
bool __user_disable_charge;
|
||
uint32_t __irq_mask;
|
||
};
|
||
|