ESP32-PaxCounter/lib/AXP202X/src/axp20x.cpp
2019-09-02 16:53:39 +02:00

1160 lines
28 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/////////////////////////////////////////////////////////////////
/*
MIT License
Copyright (c) 2019 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.
axp20x.cpp - Arduino library for X-Power AXP202 chip.
Created by Lewis he on April 1, 2019.
github:https://github.com/lewisxhe/AXP202X_Libraries
*/
/////////////////////////////////////////////////////////////////
#include "axp20x.h"
#include <math.h>
const uint8_t AXP20X_Class::startupParams[] = {
0b00000000,
0b01000000,
0b10000000,
0b11000000
};
const uint8_t AXP20X_Class::longPressParams[] = {
0b00000000,
0b00010000,
0b00100000,
0b00110000
};
const uint8_t AXP20X_Class::shutdownParams[] = {
0b00000000,
0b00000001,
0b00000010,
0b00000011
};
const uint8_t AXP20X_Class::targetVolParams[] = {
0b00000000,
0b00100000,
0b01000000,
0b01100000
};
// Power Output Control register
uint8_t AXP20X_Class::_outputReg;
int AXP20X_Class::begin(TwoWire &port, uint8_t addr)
{
_i2cPort = &port; //Grab which port the user wants us to use
_address = addr;
_readByte(AXP202_IC_TYPE, 1, &_chip_id);
AXP_DEBUG("chip id detect 0x%x\n", _chip_id);
if (_chip_id == AXP202_CHIP_ID || _chip_id == AXP192_CHIP_ID) {
AXP_DEBUG("Detect CHIP :%s\n", _chip_id == AXP202_CHIP_ID ? "AXP202" : "AXP192");
_readByte(AXP202_LDO234_DC23_CTL, 1, &_outputReg);
AXP_DEBUG("OUTPUT Register 0x%x\n", _outputReg);
_init = true;
}
return _init ? AXP_PASS : AXP_FAIL;
}
//Only axp192 chip
bool AXP20X_Class::isDCDC1Enable()
{
if (_chip_id == AXP192_CHIP_ID)
return IS_OPEN(_outputReg, AXP192_DCDC1);
return false;
}
//Only axp192 chip
bool AXP20X_Class::isExtenEnable()
{
if (_chip_id == AXP192_CHIP_ID)
return IS_OPEN(_outputReg, AXP192_EXTEN);
return false;
}
bool AXP20X_Class::isLDO2Enable()
{
//axp192 same axp202 ldo2 bit
return IS_OPEN(_outputReg, AXP202_LDO2);
}
bool AXP20X_Class::isLDO3Enable()
{
if (_chip_id == AXP192_CHIP_ID)
return IS_OPEN(_outputReg, AXP192_LDO3);
else if (_chip_id == AXP202_CHIP_ID)
return IS_OPEN(_outputReg, AXP202_LDO3);
return false;
}
bool AXP20X_Class::isLDO4Enable()
{
if (_chip_id == AXP202_CHIP_ID)
return IS_OPEN(_outputReg, AXP202_LDO4);
return false;
}
bool AXP20X_Class::isDCDC2Enable()
{
//axp192 same axp202 dc2 bit
return IS_OPEN(_outputReg, AXP202_DCDC2);
}
bool AXP20X_Class::isDCDC3Enable()
{
//axp192 same axp202 dc3 bit
return IS_OPEN(_outputReg, AXP202_DCDC3);
}
int AXP20X_Class::setPowerOutPut(uint8_t ch, bool en)
{
uint8_t data;
uint8_t val = 0;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_LDO234_DC23_CTL, 1, &data);
if (en) {
data |= (1 << ch);
} else {
data &= (~(1 << ch));
}
FORCED_OPEN_DCDC3(data); //! Must be forced open in T-Watch
_writeByte(AXP202_LDO234_DC23_CTL, 1, &data);
delay(1);
_readByte(AXP202_LDO234_DC23_CTL, 1, &val);
if (data == val) {
_outputReg = val;
return AXP_PASS;
}
return AXP_FAIL;
}
bool AXP20X_Class::isChargeing()
{
uint8_t reg;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_MODE_CHGSTATUS, 1, &reg);
return IS_OPEN(reg, 6);
}
bool AXP20X_Class::isBatteryConnect()
{
uint8_t reg;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_MODE_CHGSTATUS, 1, &reg);
return IS_OPEN(reg, 5);
}
float AXP20X_Class::getAcinVoltage()
{
if (!_init)return AXP_NOT_INIT;
return _getRegistResult(AXP202_ACIN_VOL_H8, AXP202_ACIN_VOL_L4) * AXP202_ACIN_VOLTAGE_STEP;
}
float AXP20X_Class::getAcinCurrent()
{
if (!_init)return AXP_NOT_INIT;
float rslt;
uint8_t hv, lv;
return _getRegistResult(AXP202_ACIN_CUR_H8, AXP202_ACIN_CUR_L4) * AXP202_ACIN_CUR_STEP;
}
float AXP20X_Class::getVbusVoltage()
{
if (!_init)return AXP_NOT_INIT;
return _getRegistResult(AXP202_VBUS_VOL_H8, AXP202_VBUS_VOL_L4) * AXP202_VBUS_VOLTAGE_STEP;
}
float AXP20X_Class::getVbusCurrent()
{
if (!_init)return AXP_NOT_INIT;
return _getRegistResult(AXP202_VBUS_CUR_H8, AXP202_VBUS_CUR_L4) * AXP202_VBUS_CUR_STEP;
}
float AXP20X_Class::getTemp()
{
if (!_init)return AXP_NOT_INIT;
uint8_t hv, lv;
_readByte(AXP202_INTERNAL_TEMP_H8, 1, &hv);
_readByte(AXP202_INTERNAL_TEMP_L4, 1, &lv);
float rslt = hv << 8 | (lv & 0xF);
return rslt / 1000;
}
float AXP20X_Class::getTSTemp()
{
if (!_init)return AXP_NOT_INIT;
return _getRegistResult(AXP202_TS_IN_H8, AXP202_TS_IN_L4) * AXP202_TS_PIN_OUT_STEP;
}
float AXP20X_Class::getGPIO0Voltage()
{
if (!_init)return AXP_NOT_INIT;
return _getRegistResult(AXP202_GPIO0_VOL_ADC_H8, AXP202_GPIO0_VOL_ADC_L4) * AXP202_GPIO0_STEP;
}
float AXP20X_Class::getGPIO1Voltage()
{
if (!_init)return AXP_NOT_INIT;
return _getRegistResult(AXP202_GPIO1_VOL_ADC_H8, AXP202_GPIO1_VOL_ADC_L4) * AXP202_GPIO1_STEP;
}
/*
Note: the battery power formula:
Pbat =2* register value * Voltage LSB * Current LSB / 1000.
(Voltage LSB is 1.1mV; Current LSB is 0.5mA, and unit of calculation result is mW.)
*/
float AXP20X_Class::getBattInpower()
{
float rslt;
uint8_t hv, mv, lv;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_BAT_POWERH8, 1, &hv);
_readByte(AXP202_BAT_POWERM8, 1, &mv);
_readByte(AXP202_BAT_POWERL8, 1, &lv);
rslt = (hv << 16) | (mv << 8) | lv;
rslt = 2 * rslt * 1.1 * 0.5 / 1000;
return rslt;
}
float AXP20X_Class::getBattVoltage()
{
if (!_init)return AXP_NOT_INIT;
return _getRegistResult(AXP202_BAT_AVERVOL_H8, AXP202_BAT_AVERVOL_L4) * AXP202_BATT_VOLTAGE_STEP;
}
float AXP20X_Class::getBattChargeCurrent()
{
if (!_init)return AXP_NOT_INIT;
switch (_chip_id) {
case AXP202_CHIP_ID:
return _getRegistResult(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L4) * AXP202_BATT_CHARGE_CUR_STEP;
case AXP192_CHIP_ID:
return _getRegistH8L5(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L4) * AXP202_BATT_CHARGE_CUR_STEP;
default:
break;
}
}
float AXP20X_Class::getBattDischargeCurrent()
{
float rslt;
uint8_t hv, lv;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_BAT_AVERDISCHGCUR_H8, 1, &hv);
_readByte(AXP202_BAT_AVERDISCHGCUR_L5, 1, &lv);
rslt = (hv << 5) | (lv & 0x1F);
return rslt * AXP202_BATT_DISCHARGE_CUR_STEP;
}
float AXP20X_Class::getSysIPSOUTVoltage()
{
float rslt;
uint8_t hv, lv;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_APS_AVERVOL_H8, 1, &hv);
_readByte(AXP202_APS_AVERVOL_L4, 1, &lv);
rslt = (hv << 4) | (lv & 0xF);
return rslt;
}
/*
Coulomb calculation formula:
C= 65536 * current LSB *charge coulomb counter value - discharge coulomb counter value /
3600 / ADC sample rate. Refer to REG84H setting for ADC sample ratethe current LSB is
0.5mAunit of the calculation result is mAh.
*/
uint32_t AXP20X_Class::getBattChargeCoulomb()
{
uint8_t buffer[4];
if (!_init)return AXP_NOT_INIT;
_readByte(0xB1, 4, buffer);
return buffer[0] << 24 + buffer[1] << 16 + buffer[2] << 8 + buffer[3];
}
uint32_t AXP20X_Class::getBattDischargeCoulomb()
{
uint8_t buffer[4];
if (!_init)return AXP_NOT_INIT;
_readByte(0xB4, 4, buffer);
return buffer[0] << 24 + buffer[1] << 16 + buffer[2] << 8 + buffer[3];
}
float AXP20X_Class::getCoulombData()
{
if (!_init)return AXP_NOT_INIT;
uint32_t charge = getBattChargeCoulomb();
uint32_t discharge = getBattDischargeCoulomb();
uint8_t rate = getAdcSamplingRate();
float result = 65536.0 * 0.5 * (charge - discharge) / 3600.0 / rate;
return result;
}
uint8_t AXP20X_Class::getAdcSamplingRate()
{
//axp192 same axp202 aregister address 0x84
if (!_init)return AXP_NOT_INIT;
uint8_t val;
_readByte(AXP202_ADC_SPEED, 1, &val);
return 25 * (int)pow(2, (val & 0xC0) >> 6);
}
int AXP20X_Class::setAdcSamplingRate(axp_adc_sampling_rate_t rate)
{
//axp192 same axp202 aregister address 0x84
if (!_init)return AXP_NOT_INIT;
if (rate > AXP_ADC_SAMPLING_RATE_200HZ) return AXP_FAIL;
uint8_t val;
_readByte(AXP202_ADC_SPEED, 1, &val);
uint8_t rw = rate;
val &= 0x3F;
val |= (rw << 6);
_writeByte(AXP202_ADC_SPEED, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::adc1Enable(uint16_t params, bool en)
{
if (!_init)return AXP_NOT_INIT;
uint8_t val;
_readByte(AXP202_ADC_EN1, 1, &val);
if (en)
val |= params;
else
val &= ~(params);
_writeByte(AXP202_ADC_EN1, 1, &val);
_readByte(AXP202_ADC_EN1, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::adc2Enable(uint16_t params, bool en)
{
if (!_init)return AXP_NOT_INIT;
uint8_t val;
_readByte(AXP202_ADC_EN2, 1, &val);
if (en)
val |= params;
else
val &= ~(params);
_writeByte(AXP202_ADC_EN2, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::enableIRQ(uint32_t params, bool en)
{
if (!_init)return AXP_NOT_INIT;
uint8_t val, val1;
if (params & 0xFF) {
val1 = params & 0xFF;
_readByte(AXP202_INTEN1, 1, &val);
if (en)
val |= val1;
else
val &= ~(val1);
AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN1, val);
_writeByte(AXP202_INTEN1, 1, &val);
}
if (params & 0xFF00) {
val1 = params >> 8;
_readByte(AXP202_INTEN2, 1, &val);
if (en)
val |= val1;
else
val &= ~(val1);
AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN2, val);
_writeByte(AXP202_INTEN2, 1, &val);
}
if (params & 0xFF0000) {
val1 = params >> 16;
_readByte(AXP202_INTEN3, 1, &val);
if (en)
val |= val1;
else
val &= ~(val1);
AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN3, val);
_writeByte(AXP202_INTEN3, 1, &val);
}
if (params & 0xFF000000) {
val1 = params >> 24;
_readByte(AXP202_INTEN4, 1, &val);
if (en)
val |= val1;
else
val &= ~(val1);
AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN4, val);
_writeByte(AXP202_INTEN4, 1, &val);
}
return AXP_PASS;
}
int AXP20X_Class::readIRQ()
{
if (!_init)return AXP_NOT_INIT;
switch (_chip_id) {
case AXP192_CHIP_ID:
for (int i = 0; i < 4; ++i) {
_readByte(AXP192_INTSTS1 + i, 1, &_irq[i]);
}
_readByte(AXP192_INTSTS5, 1, &_irq[4]);
return AXP_PASS;
case AXP202_CHIP_ID:
for (int i = 0; i < 5; ++i) {
_readByte(AXP202_INTSTS1 + i, 1, &_irq[i]);
}
return AXP_PASS;
default:
return AXP_FAIL;
}
}
void AXP20X_Class::clearIRQ()
{
uint8_t val = 0xFF;
switch (_chip_id) {
case AXP192_CHIP_ID:
for (int i = 0; i < 3; i++) {
_writeByte(AXP192_INTSTS1 + i, 1, &val);
}
_writeByte(AXP192_INTSTS5, 1, &val);
break;
case AXP202_CHIP_ID:
for (int i = 0; i < 5; i++) {
_writeByte(AXP202_INTSTS1 + i, 1, &val);
}
break;
default:
break;
}
memset(_irq, 0, sizeof(_irq));
}
bool AXP20X_Class::isAcinOverVoltageIRQ()
{
return (bool)(_irq[0] & BIT_MASK(7));
}
bool AXP20X_Class::isAcinPlugInIRQ()
{
return (bool)(_irq[0] & BIT_MASK(6));
}
bool AXP20X_Class::isAcinRemoveIRQ()
{
return (bool)(_irq[0] & BIT_MASK(5));
}
bool AXP20X_Class::isVbusOverVoltageIRQ()
{
return (bool)(_irq[0] & BIT_MASK(4));
}
bool AXP20X_Class::isVbusPlugInIRQ()
{
return (bool)(_irq[0] & BIT_MASK(3));
}
bool AXP20X_Class::isVbusRemoveIRQ()
{
return (bool)(_irq[0] & BIT_MASK(2));
}
bool AXP20X_Class::isVbusLowVHOLDIRQ()
{
return (bool)(_irq[0] & BIT_MASK(1));
}
bool AXP20X_Class::isBattPlugInIRQ()
{
return (bool)(_irq[1] & BIT_MASK(7));
}
bool AXP20X_Class::isBattRemoveIRQ()
{
return (bool)(_irq[1] & BIT_MASK(6));
}
bool AXP20X_Class::isBattEnterActivateIRQ()
{
return (bool)(_irq[1] & BIT_MASK(5));
}
bool AXP20X_Class::isBattExitActivateIRQ()
{
return (bool)(_irq[1] & BIT_MASK(4));
}
bool AXP20X_Class::isChargingIRQ()
{
return (bool)(_irq[1] & BIT_MASK(3));
}
bool AXP20X_Class::isChargingDoneIRQ()
{
return (bool)(_irq[1] & BIT_MASK(2));
}
bool AXP20X_Class::isBattTempLowIRQ()
{
return (bool)(_irq[1] & BIT_MASK(1));
}
bool AXP20X_Class::isBattTempHighIRQ()
{
return (bool)(_irq[1] & BIT_MASK(0));
}
bool AXP20X_Class::isPEKShortPressIRQ()
{
return (bool)(_irq[2] & BIT_MASK(1));
}
bool AXP20X_Class::isPEKLongtPressIRQ()
{
return (bool)(_irq[2] & BIT_MASK(0));
}
bool AXP20X_Class::isVBUSPlug()
{
if (!_init)return AXP_NOT_INIT;
uint8_t val;
_readByte(AXP202_STATUS, 1, &val);
return (bool)(_irq[2] & BIT_MASK(5));
}
int AXP20X_Class::setDCDC2Voltage(uint16_t mv)
{
if (!_init)return AXP_NOT_INIT;
if (mv < 700) {
AXP_DEBUG("DCDC2:Below settable voltage:700mV~2275mV");
mv = 700;
}
if (mv > 2275) {
AXP_DEBUG("DCDC2:Above settable voltage:700mV~2275mV");
mv = 2275;
}
uint8_t val = (mv - 700) / 25;
_writeByte(AXP202_DC2OUT_VOL, 1, &val);
return AXP_PASS;
}
uint16_t AXP20X_Class::getDCDC2Voltage()
{
uint8_t val = 0;
_readByte(AXP202_DC2OUT_VOL, 1, &val);
return val * 25 + 700;
}
uint16_t AXP20X_Class::getDCDC3Voltage()
{
uint8_t val = 0;
_readByte(AXP202_DC3OUT_VOL, 1, &val);
return val * 25 + 700;
}
int AXP20X_Class::setDCDC3Voltage(uint16_t mv)
{
if (!_init)return AXP_NOT_INIT;
if (mv < 700) {
AXP_DEBUG("DCDC3:Below settable voltage:700mV~3500mV");
mv = 700;
}
if (mv > 3500) {
AXP_DEBUG("DCDC3:Above settable voltage:700mV~3500mV");
mv = 3500;
}
uint8_t val = (mv - 700) / 25;
_writeByte(AXP202_DC3OUT_VOL, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::setLDO2Voltage(uint16_t mv)
{
uint8_t rVal, wVal;
if (!_init)return AXP_NOT_INIT;
if (mv < 1800) {
AXP_DEBUG("LDO2:Below settable voltage:1800mV~3300mV");
mv = 1800;
}
if (mv > 3300) {
AXP_DEBUG("LDO2:Above settable voltage:1800mV~3300mV");
mv = 3300;
}
wVal = (mv - 1800) / 100;
if (_chip_id == AXP202_CHIP_ID ) {
_readByte(AXP202_LDO24OUT_VOL, 1, &rVal);
rVal &= 0x0F;
rVal |= (wVal << 4);
_writeByte(AXP202_LDO24OUT_VOL, 1, &rVal);
return AXP_PASS;
} else if (_chip_id == AXP192_CHIP_ID) {
_readByte(AXP192_LDO23OUT_VOL, 1, &rVal);
rVal &= 0x0F;
rVal |= (wVal << 4);
_writeByte(AXP192_LDO23OUT_VOL, 1, &rVal);
return AXP_PASS;
}
return AXP_FAIL;
}
uint16_t AXP20X_Class::getLDO2Voltage()
{
uint8_t rVal;
if (_chip_id == AXP202_CHIP_ID ) {
_readByte(AXP202_LDO24OUT_VOL, 1, &rVal);
rVal &= 0xF0;
rVal >>= 4;
return rVal * 100 + 1800;
} else if (_chip_id == AXP192_CHIP_ID) {
_readByte(AXP192_LDO23OUT_VOL, 1, &rVal);
AXP_DEBUG("get result:%x\n", rVal);
rVal &= 0xF0;
rVal >>= 4;
return rVal * 100 + 1800;
}
return 0;
}
int AXP20X_Class::setLDO3Voltage(uint16_t mv)
{
uint8_t rVal;
if (!_init)return AXP_NOT_INIT;
if (_chip_id == AXP202_CHIP_ID && mv < 700) {
AXP_DEBUG("LDO3:Below settable voltage:700mV~2275mV");
mv = 700;
} else if (_chip_id == AXP192_CHIP_ID && mv < 1800) {
AXP_DEBUG("LDO3:Below settable voltage:1800mV~3300mV");
mv = 1800;
}
if (_chip_id == AXP202_CHIP_ID && mv > 2275) {
AXP_DEBUG("LDO3:Above settable voltage:700mV~2275mV");
mv = 2275;
} else if (_chip_id == AXP192_CHIP_ID && mv > 3300) {
AXP_DEBUG("LDO3:Above settable voltage:1800mV~3300mV");
mv = 3300;
}
if (_chip_id == AXP202_CHIP_ID ) {
_readByte(AXP202_LDO3OUT_VOL, 1, &rVal);
rVal &= 0x80;
rVal |= ((mv - 700) / 25);
_writeByte(AXP202_LDO3OUT_VOL, 1, &rVal);
return AXP_PASS;
} else if (_chip_id == AXP192_CHIP_ID) {
_readByte(AXP192_LDO23OUT_VOL, 1, &rVal);
rVal &= 0xF0;
rVal |= ((mv - 1800) / 100);
_writeByte(AXP192_LDO23OUT_VOL, 1, &rVal);
return AXP_PASS;
}
return AXP_FAIL;
}
uint16_t AXP20X_Class::getLDO3Voltage()
{
uint8_t rVal;
if (!_init)return AXP_NOT_INIT;
if (_chip_id == AXP202_CHIP_ID ) {
_readByte(AXP202_LDO3OUT_VOL, 1, &rVal);
if (rVal & 0x80) {
//! According to the hardware N_VBUSEN Pin selection
return getVbusVoltage() * 1000;
} else {
return (rVal & 0x7F) * 25 + 700;
}
} else if (_chip_id == AXP192_CHIP_ID) {
_readByte(AXP192_LDO23OUT_VOL, 1, &rVal);
rVal &= 0x0F;
return rVal * 100 + 1800;
}
return 0;
}
//! Only axp202 support
int AXP20X_Class::setLDO4Voltage(axp_ldo4_table_t param)
{
if (!_init)return AXP_NOT_INIT;
if (_chip_id != AXP202_CHIP_ID ) return AXP_FAIL;
if (param >= AXP202_LDO4_MAX)return AXP_INVALID;
uint8_t val;
_readByte(AXP202_LDO24OUT_VOL, 1, &val);
val &= 0xF0;
val |= param;
_writeByte(AXP202_LDO24OUT_VOL, 1, &val);
return AXP_PASS;
}
//! Only AXP202 support
// 0 : LDO 1 : DCIN
int AXP20X_Class::setLDO3Mode(uint8_t mode)
{
uint8_t val;
if (_chip_id != AXP202_CHIP_ID ) return AXP_FAIL;
_readByte(AXP202_LDO3OUT_VOL, 1, &val);
if (mode) {
val |= BIT_MASK(7);
} else {
val &= (~BIT_MASK(7));
}
_writeByte(AXP202_LDO3OUT_VOL, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::setStartupTime(uint8_t param)
{
uint8_t val;
if (!_init)return AXP_NOT_INIT;
if (param > sizeof(startupParams) / sizeof(startupParams[0]))return AXP_INVALID;
_readByte(AXP202_POK_SET, 1, &val);
val &= (~0b11000000);
val |= startupParams[param];
_writeByte(AXP202_POK_SET, 1, &val);
}
int AXP20X_Class::setlongPressTime(uint8_t param)
{
uint8_t val;
if (!_init)return AXP_NOT_INIT;
if (param > sizeof(longPressParams) / sizeof(longPressParams[0]))return AXP_INVALID;
_readByte(AXP202_POK_SET, 1, &val);
val &= (~0b00110000);
val |= longPressParams[param];
_writeByte(AXP202_POK_SET, 1, &val);
}
int AXP20X_Class::setShutdownTime(uint8_t param)
{
uint8_t val;
if (!_init)return AXP_NOT_INIT;
if (param > sizeof(shutdownParams) / sizeof(shutdownParams[0]))return AXP_INVALID;
_readByte(AXP202_POK_SET, 1, &val);
val &= (~0b00000011);
val |= shutdownParams[param];
_writeByte(AXP202_POK_SET, 1, &val);
}
int AXP20X_Class::setTimeOutShutdown(bool en)
{
uint8_t val;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_POK_SET, 1, &val);
if (en)
val |= (1 << 3);
else
val &= (~(1 << 3));
_writeByte(AXP202_POK_SET, 1, &val);
}
int AXP20X_Class::shutdown()
{
uint8_t val;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_OFF_CTL, 1, &val);
val |= (1 << 7);
_writeByte(AXP202_OFF_CTL, 1, &val);
}
float AXP20X_Class::getSettingChargeCurrent()
{
uint8_t val;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_CHARGE1, 1, &val);
val &= 0b00000111;
float cur = 300.0 + val * 100.0;
AXP_DEBUG("Setting Charge current : %.2f mA\n", cur);
return cur;
}
bool AXP20X_Class::isChargeingEnable()
{
uint8_t val;
if (!_init)return false;
_readByte(AXP202_CHARGE1, 1, &val);
if (val & (1 << 7)) {
AXP_DEBUG("Charging enable is enable\n");
val = true;
} else {
AXP_DEBUG("Charging enable is disable\n");
val = false;
}
return val;
}
int AXP20X_Class::enableChargeing(bool en)
{
uint8_t val;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_CHARGE1, 1, &val);
val |= (1 << 7);
_writeByte(AXP202_CHARGE1, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::setChargingTargetVoltage(axp_chargeing_vol_t param)
{
uint8_t val;
if (!_init)return AXP_NOT_INIT;
if (param > sizeof(targetVolParams) / sizeof(targetVolParams[0]))return AXP_INVALID;
_readByte(AXP202_CHARGE1, 1, &val);
val &= ~(0b01100000);
val |= targetVolParams[param];
_writeByte(AXP202_CHARGE1, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::getBattPercentage()
{
if (!_init)return AXP_NOT_INIT;
uint8_t val;
_readByte(AXP202_BATT_PERCENTAGE, 1, &val);
if (!(val & BIT_MASK(7))) {
return val & (~BIT_MASK(7));
}
return 0;
}
int AXP20X_Class::setChgLEDMode(uint8_t mode)
{
uint8_t val;
_readByte(AXP202_OFF_CTL, 1, &val);
val |= BIT_MASK(3);
switch (mode) {
case AXP20X_LED_OFF:
val &= 0b11001111;
_writeByte(AXP202_OFF_CTL, 1, &val);
break;
case AXP20X_LED_BLINK_1HZ:
val &= 0b11001111;
val |= 0b00010000;
_writeByte(AXP202_OFF_CTL, 1, &val);
break;
case AXP20X_LED_BLINK_4HZ:
val &= 0b11001111;
val |= 0b00100000;
_writeByte(AXP202_OFF_CTL, 1, &val);
break;
case AXP20X_LED_LOW_LEVEL:
val &= 0b11001111;
val |= 0b00110000;
_writeByte(AXP202_OFF_CTL, 1, &val);
break;
default:
break;
}
return AXP_PASS;
}
int AXP20X_Class::debugCharging()
{
uint8_t val;
_readByte(AXP202_CHARGE1, 1, &val);
AXP_DEBUG("SRC REG:0x%x\n", val);
if (val & (1 << 7)) {
AXP_DEBUG("Charging enable is enable\n");
} else {
AXP_DEBUG("Charging enable is disable\n");
}
AXP_DEBUG("Charging target-voltage : 0x%x\n", ((val & 0b01100000) >> 5 ) & 0b11);
if (val & (1 << 4)) {
AXP_DEBUG("end when the charge current is lower than 15%% of the set value\n");
} else {
AXP_DEBUG(" end when the charge current is lower than 10%% of the set value\n");
}
val &= 0b00000111;
float cur = 300.0 + val * 100.0;
AXP_DEBUG("Charge current : %.2f mA\n", cur);
}
int AXP20X_Class::debugStatus()
{
if (!_init)return AXP_NOT_INIT;
uint8_t val, val1, val2;
_readByte(AXP202_STATUS, 1, &val);
_readByte(AXP202_MODE_CHGSTATUS, 1, &val1);
_readByte(AXP202_IPS_SET, 1, &val2);
AXP_DEBUG("AXP202_STATUS: AXP202_MODE_CHGSTATUS AXP202_IPS_SET\n");
AXP_DEBUG("0x%x\t\t\t 0x%x\t\t\t 0x%x\n", val, val1, val2);
}
int AXP20X_Class::limitingOff()
{
if (!_init)return AXP_NOT_INIT;
uint8_t val;
_readByte(AXP202_IPS_SET, 1, &val);
if (_chip_id == AXP202_CHIP_ID) {
val |= 0x03;
} else {
val &= ~(1 << 1);
}
_writeByte(AXP202_IPS_SET, 1, &val);
return AXP_PASS;
}
// Only AXP129 chip
int AXP20X_Class::setDCDC1Voltage(uint16_t mv)
{
if (!_init)return AXP_NOT_INIT;
if (_chip_id != AXP192_CHIP_ID) return AXP_FAIL;
if (mv < 700) {
AXP_DEBUG("DCDC1:Below settable voltage:700mV~3500mV");
mv = 700;
}
if (mv > 3500) {
AXP_DEBUG("DCDC1:Above settable voltage:700mV~3500mV");
mv = 3500;
}
uint8_t val = (mv - 700) / 25;
_writeByte(AXP192_DC1_VLOTAGE, 1, &val);
return AXP_PASS;
}
// Only AXP129 chip
uint16_t AXP20X_Class::getDCDC1Voltage()
{
if (_chip_id != AXP192_CHIP_ID) return AXP_FAIL;
uint8_t val = 0;
_readByte(AXP192_DC1_VLOTAGE, 1, &val);
return val * 25 + 700;
}
int AXP20X_Class::setGPIO0Voltage(uint8_t param)
{
uint8_t params[] = {
0b11111000,
0b11111001,
0b11111010,
0b11111011,
0b11111100,
0b11111101,
0b11111110,
0b11111111,
};
if (!_init)return AXP_NOT_INIT;
if (param > sizeof(params) / sizeof(params[0]))return AXP_INVALID;
uint8_t val = 0;
_readByte(AXP202_GPIO0_VOL, 1, &val);
val &= 0b11111000;
val |= params[param];
_writeByte(AXP202_GPIO0_VOL, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::setGPIO0Level(uint8_t level)
{
uint8_t val = 0;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_GPIO0_CTL, 1, &val);
val = level ? val & 0b11111000 : (val & 0b11111000) | 0b00000001;
_writeByte(AXP202_GPIO0_CTL, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::setGPIO1Level(uint8_t level)
{
uint8_t val = 0;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_GPIO1_CTL, 1, &val);
val = level ? val & 0b11111000 : (val & 0b11111000) | 0b00000001;
_writeByte(AXP202_GPIO1_CTL, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::readGpioStatus()
{
uint8_t val = 0;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_GPIO012_SIGNAL, 1, &val);
_gpio[0] = val & BIT_MASK(4);
_gpio[1] = val & BIT_MASK(5);
_gpio[2] = val & BIT_MASK(6);
_readByte(AXP202_GPIO3_CTL, 1, &val);
_gpio[3] = val & 1;
return AXP_PASS;
}
int AXP20X_Class::readGpio0Level()
{
return _gpio[0];
}
int AXP20X_Class::readGpio1Level()
{
return _gpio[1];
}
int AXP20X_Class::readGpio2Level()
{
return _gpio[2];
}
int AXP20X_Class::setGpio2Mode(uint8_t mode)
{
uint8_t params[] = {
0b11111000,
0b11111001,
0b11111010,
};
if (!_init)return AXP_NOT_INIT;
if (mode > sizeof(params) / sizeof(params[0]))return AXP_INVALID;
uint8_t val = 0;
_readByte(AXP202_GPIO2_CTL, 1, &val);
val &= params[0];
val |= params[mode];
_writeByte(AXP202_GPIO2_CTL, 1, &val);
return AXP_PASS;
}
int AXP20X_Class::setGpio3Mode(uint8_t mode)
{
uint8_t val = 0;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_GPIO3_CTL, 1, &val);
if (mode == AXP202_GPIO3_DIGITAL_INPUT) {
val |= BIT_MASK(2);
} else if (mode == AXP202_GPIO3_OPEN_DRAIN_OUTPUT) {
val &= ~BIT_MASK(2);
} else {
return AXP_INVALID;
}
return AXP_PASS;
}
int AXP20X_Class::setGpio3Level(uint8_t level)
{
uint8_t val = 0;
if (!_init)return AXP_NOT_INIT;
_readByte(AXP202_GPIO3_CTL, 1, &val);
if (!(val & BIT_MASK(2))) {
return AXP_FAIL;
}
val = level ? val & (~BIT_MASK(1)) : val | BIT_MASK(1);
_writeByte(AXP202_GPIO3_CTL, 1, &val);
}
int AXP20X_Class::_setGpioInterrupt(uint8_t *val, int mode, bool en)
{
switch (mode) {
case RISING:
*val = en ? *val | BIT_MASK(7) : *val & (~BIT_MASK(7));
break;
case FALLING:
*val = en ? *val | BIT_MASK(6) : *val & (~BIT_MASK(6));
break;
default:
break;
}
}
int AXP20X_Class::setGpioInterruptMode(uint8_t gpio, int mode, bool en)
{
uint8_t val = 0;
if (!_init)return AXP_NOT_INIT;
switch (gpio) {
case AXP202_GPIO0:
_readByte(AXP202_GPIO0_CTL, 1, &val);
_setGpioInterrupt(&val, mode, en);
break;
case AXP202_GPIO1:
_readByte(AXP202_GPIO1_CTL, 1, &val);
_setGpioInterrupt(&val, mode, en);
break;
case AXP202_GPIO2:
_readByte(AXP202_GPIO2_CTL, 1, &val);
_setGpioInterrupt(&val, mode, en);
break;
case AXP202_GPIO3:
_readByte(AXP202_GPIO3_CTL, 1, &val);
_setGpioInterrupt(&val, mode, en);
break;
}
}
int AXP20X_Class::gpio0Setting(axp192_gpio0_mode_t mode)
{
uint8_t rVal;
if (!_init)return AXP_NOT_INIT;
if (_chip_id == AXP192_CHIP_ID ) {
_readByte(AXP192_GPIO0_CTL, 1, &rVal);
rVal &= 0xF8;
rVal |= mode;
_writeByte(AXP192_GPIO0_CTL, 1, &rVal);
return AXP_PASS;
}
return AXP_FAIL;
}
int AXP20X_Class::gpio0SetVoltage(axp192_gpio_voltage_t vol)
{
uint8_t rVal;
if (!_init)return AXP_NOT_INIT;
if (_chip_id == AXP192_CHIP_ID) {
_readByte(AXP192_GPIO0_VOL, 1, &rVal);
rVal &= 0x0F;
rVal |= (vol << 4);
_writeByte(AXP192_GPIO0_VOL, 1, &rVal);
return AXP_PASS;
}
return AXP_FAIL;
}
uint16_t AXP20X_Class::gpio0GetVoltage()
{
uint8_t rVal;
if (!_init)return AXP_NOT_INIT;
if (_chip_id == AXP192_CHIP_ID) {
_readByte(AXP192_GPIO0_VOL, 1, &rVal);
rVal &= 0xF0;
rVal >>= 4;
return rVal;
}
return 0;
}