diff --git a/README.md b/README.md index 8f414aab..c8bebf56 100644 --- a/README.md +++ b/README.md @@ -392,7 +392,7 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 0 = BME data off 1 = BME data on, sends BME data on port 7 [default] -0x15 set battery data on/off +0x16 set battery data on/off 0 = battery data off [default] 1 = battery data on, sends voltage on port 8 diff --git a/include/i2cscan.h b/include/i2cscan.h new file mode 100644 index 00000000..b834b34f --- /dev/null +++ b/include/i2cscan.h @@ -0,0 +1,12 @@ +#ifndef _I2CSCAN_H +#define _I2CSCAN_H + +#include +#ifdef HAS_PMU +#include "axp20x.h" +#endif + +int i2c_scan(void); +void AXP192_init(void); + +#endif \ No newline at end of file diff --git a/include/main.h b/include/main.h index bce12e51..ddc49d5d 100644 --- a/include/main.h +++ b/include/main.h @@ -7,6 +7,7 @@ #include // needed for showing coex sw version #include "globals.h" +#include "i2cscan.h" #include "blescan.h" #include "wifiscan.h" #include "configmanager.h" diff --git a/lib/AXP202X/.gitignore b/lib/AXP202X/.gitignore new file mode 100644 index 00000000..6d0ee45d --- /dev/null +++ b/lib/AXP202X/.gitignore @@ -0,0 +1,2 @@ +.vscode +.DS_Store \ No newline at end of file diff --git a/lib/AXP202X/LICENSE b/lib/AXP202X/LICENSE new file mode 100644 index 00000000..3b7bfa9f --- /dev/null +++ b/lib/AXP202X/LICENSE @@ -0,0 +1,21 @@ +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. diff --git a/lib/AXP202X/README.md b/lib/AXP202X/README.md new file mode 100644 index 00000000..8623bc5a --- /dev/null +++ b/lib/AXP202X/README.md @@ -0,0 +1,9 @@ +AXP202X_Library +===================================== +- axp192 partial support, the function is not fully tested, please refer to the manual +- The `setPowerOutPut` function has forced DCDC3 to be turned on and cannot be controlled because T-Watch uses DCDC3 as the esp32 to power the main chip. If it is turned off, the hardware cannot be programmed. + + +TTGO invests time and resources to provide this open source code, please support TTGO and open source hardware by purchasing products from TTGO! + +Written by Lewis He for TTGO. MIT license, all text above must be included in any redistribution \ No newline at end of file diff --git a/lib/AXP202X/keywords.txt b/lib/AXP202X/keywords.txt new file mode 100644 index 00000000..55ffde3f --- /dev/null +++ b/lib/AXP202X/keywords.txt @@ -0,0 +1,163 @@ +####################################### +# Syntax Coloring Map For X-Power AXP20X Library By lewis He +# github:https://github.com/lewisxhe +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### +AXP20X_Class KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +isChargeing KEYWORD2 +isLDO2Enable KEYWORD2 +isLDO3Enable KEYWORD2 +isLDO4Enable KEYWORD2 +isDCDC3Enable KEYWORD2 +isDCDC2Enable KEYWORD2 +isChargeingEnable KEYWORD2 +isAcinOverVoltageIRQ KEYWORD2 +isAcinPlugInIRQ KEYWORD2 +isAcinRemoveIRQ KEYWORD2 +isVbusOverVoltageIRQ KEYWORD2 +isVbusPlugInIRQ KEYWORD2 +isVbusRemoveIRQ KEYWORD2 +isVbusLowVHOLDIRQ KEYWORD2 +isBattPlugInIRQ KEYWORD2 +isBattRemoveIRQ KEYWORD2 +isBattEnterActivateIRQ KEYWORD2 +isBattExitActivateIRQ KEYWORD2 +isChargingIRQ KEYWORD2 +isChargingDoneIRQ KEYWORD2 +isBattTempLowIRQ KEYWORD2 +isBattTempHighIRQ KEYWORD2 +isPEKShortPressIRQ KEYWORD2 +isPEKLongtPressIRQ KEYWORD2 +getAcinVoltage KEYWORD2 +getAcinCurrent KEYWORD2 +getVbusVoltage KEYWORD2 +getVbusCurrent KEYWORD2 +getTemp KEYWORD2 +getTSTemp KEYWORD2 +getGPIO0Voltage KEYWORD2 +getGPIO1Voltage KEYWORD2 +getBattInpower KEYWORD2 +getBattVoltage KEYWORD2 +getBattChargeCurrent KEYWORD2 +getBattDischargeCurrent KEYWORD2 +getSysIPSOUTVoltage KEYWORD2 +getBattChargeCoulomb KEYWORD2 +getBattDischargeCoulomb KEYWORD2 +getSettingChargeCurrent KEYWORD2 +setChargingTargetVoltage KEYWORD2 +enableChargeing KEYWORD2 +adc1Enable KEYWORD2 +adc2Enable KEYWORD2 +setStartupTime KEYWORD2 +setlongPressTime KEYWORD2 +setShutdownTime KEYWORD2 +setTimeOutShutdown KEYWORD2 +enableIRQ KEYWORD2 +readIRQ KEYWORD2 +clearIRQ KEYWORD2 +setDCDC2Voltage KEYWORD2 +setDCDC3Voltage KEYWORD2 +setLDO2Voltage KEYWORD2 +setLDO3Voltage KEYWORD2 +setLDO4Voltage KEYWORD2 +getBattPercentage KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + + +####################################### +# Constants (LITERAL1) +####################################### +AXP202_LDO4_1250MV LITERAL1 +AXP202_LDO4_1300MV LITERAL1 +AXP202_LDO4_1400MV LITERAL1 +AXP202_LDO4_1500MV LITERAL1 +AXP202_LDO4_1600MV LITERAL1 +AXP202_LDO4_1700MV LITERAL1 +AXP202_LDO4_1800MV LITERAL1 +AXP202_LDO4_1900MV LITERAL1 +AXP202_LDO4_2000MV LITERAL1 +AXP202_LDO4_2500MV LITERAL1 +AXP202_LDO4_2700MV LITERAL1 +AXP202_LDO4_2800MV LITERAL1 +AXP202_LDO4_3000MV LITERAL1 +AXP202_LDO4_3100MV LITERAL1 +AXP202_LDO4_3200MV LITERAL1 +AXP202_LDO4_3300MV LITERAL1 + +AXP202_VBUS_VHOLD_LOW_IRQ LITERAL1 +AXP202_VBUS_REMOVED_IRQ LITERAL1 +AXP202_VBUS_CONNECT_IRQ LITERAL1 +AXP202_VBUS_OVER_VOL_IRQ LITERAL1 +AXP202_ACIN_REMOVED_IRQ LITERAL1 +AXP202_ACIN_CONNECT_IRQ LITERAL1 +AXP202_ACIN_OVER_VOL_IRQ LITERAL1 +AXP202_BATT_LOW_TEMP_IRQ LITERAL1 +AXP202_BATT_OVER_TEMP_IRQ LITERAL1 +AXP202_CHARGING_FINISHED_IRQ LITERAL1 +AXP202_CHARGING_IRQ LITERAL1 +AXP202_BATT_EXIT_ACTIVATE_IRQ LITERAL1 +AXP202_BATT_ACTIVATE_IRQ LITERAL1 +AXP202_BATT_REMOVED_IRQ LITERAL1 +AXP202_BATT_CONNECT_IRQ LITERAL1 +AXP202_PEK_LONGPRESS_IRQ LITERAL1 +AXP202_PEL_SHORTPRESS_IRQ LITERAL1 +AXP202_LDO3_LOW_VOL_IRQ LITERAL1 +AXP202_DC3_LOW_VOL_IRQ LITERAL1 +AXP202_DC2_LOW_VOL_IRQ LITERAL1 +AXP202_CHARGE_LOW_CUR_IRQ LITERAL1 +AXP202_CHIP_TEMP_HIGH_IRQ LITERAL1 +AXP202_APS_LOW_VOL_LEVEL2_IRQ LITERAL1 +APX202_APS_LOW_VOL_LEVEL1_IRQ LITERAL1 +AXP202_VBUS_SESSION_END_IRQ LITERAL1 +AXP202_VBUS_SESSION_AB_IRQ LITERAL1 +AXP202_VBUS_INVALID_IRQ LITERAL1 +AXP202_VBUS_VAILD_IRQ LITERAL1 +AXP202_NOE_OFF_IRQ LITERAL1 +AXP202_NOE_ON_IRQ LITERAL1 + +AXP202_TEMP_MONITORING_ADC2 LITERAL1 +AXP202_GPIO1_FUNC_ADC2 LITERAL1 +AXP202_GPIO0_FUNC_ADC2 LITERAL1 + +AXP202_BATT_VOL_ADC1 LITERAL1 +AXP202_BATT_CUR_ADC1 LITERAL1 +AXP202_ACIN_VOL_ADC1 LITERAL1 +AXP202_ACIN_CUR_ADC1 LITERAL1 +AXP202_VBUS_VOL_ADC1 LITERAL1 +AXP202_VBUS_CUR_ADC1 LITERAL1 +AXP202_APS_VOL_ADC1 LITERAL1 +AXP202_TS_PIN_ADC1 LITERAL1 + +AXP202_TARGET_VOL_4_1V LITERAL1 +AXP202_TARGET_VOL_4_15V LITERAL1 +AXP202_TARGET_VOL_4_2V LITERAL1 +AXP202_TARGET_VOL_4_36V LITERAL1 +AXP202_STARTUP_TIME_128MS LITERAL1 +AXP202_STARTUP_TIME_3S LITERAL1 +AXP202_STARTUP_TIME_1S LITERAL1 +AXP202_STARTUP_TIME_2S LITERAL1 +AXP202_STARTUP_TIME LITERAL1 +AXP202_LONGPRESS_TIME LITERAL1 +AXP202_SHUTDOWN_EXCEEDS_TIME LITERAL1 +AXP202_PWROK_SIGNAL_DELAY LITERAL1 +AXP202_SHUTDOWN_TIME LITERAL1 + + +AXP202_EXTEN LITERAL1 +AXP202_DCDC3 LITERAL1 +AXP202_LDO2 LITERAL1 +AXP202_LDO4 LITERAL1 +AXP202_DCDC2 LITERAL1 +AXP202_LDO3 LITERAL1 \ No newline at end of file diff --git a/lib/AXP202X/library.properties b/lib/AXP202X/library.properties new file mode 100644 index 00000000..9824467d --- /dev/null +++ b/lib/AXP202X/library.properties @@ -0,0 +1,10 @@ +name=AXP202X_Library +version=1.0.0 +author=Lewis He +maintainer=Lewis He +sentence=Arduino library for X-Power AXP202 chip +paragraph=Arduino library for X-Power AXP202 chip. Tested with ESP32 +category=Communication +url=https://github.com/lewisxhe/AXP202X_Library +architectures=* +architectures=esp32 \ No newline at end of file diff --git a/lib/AXP202X/src/axp20x.cpp b/lib/AXP202X/src/axp20x.cpp new file mode 100644 index 00000000..2293f2f6 --- /dev/null +++ b/lib/AXP202X/src/axp20x.cpp @@ -0,0 +1,1160 @@ +///////////////////////////////////////////////////////////////// +/* +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 + +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, ®); + return IS_OPEN(reg, 6); +} + +bool AXP20X_Class::isBatteryConnect() +{ + uint8_t reg; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_MODE_CHGSTATUS, 1, ®); + 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 rate;the current LSB is +0.5mA;unit 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; +} \ No newline at end of file diff --git a/lib/AXP202X/src/axp20x.h b/lib/AXP202X/src/axp20x.h new file mode 100644 index 00000000..e86a4714 --- /dev/null +++ b/lib/AXP202X/src/axp20x.h @@ -0,0 +1,766 @@ +///////////////////////////////////////////////////////////////// +/* +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.h - Arduino library for X-Power AXP202 chip. +Created by Lewis he on April 1, 2019. +github:https://github.com/lewisxhe/AXP202X_Libraries +*/ +///////////////////////////////////////////////////////////////// +#pragma once + +#include +#include + +// #define AXP_DEBUG_PORT Serial +#ifdef AXP_DEBUG_PORT +#define AXP_DEBUG(fmt, ...) AXP_DEBUG_PORT.printf_P( (PGM_P)PSTR(fmt), ## __VA_ARGS__ ) +#else +#define AXP_DEBUG(...) +#endif + +#ifndef RISING +#define RISING 0x01 +#endif + +#ifndef FALLING +#define FALLING 0x02 +#endif + +//! Error Code +#define AXP_PASS 0 +#define AXP_FAIL -1 +#define AXP_INVALID -2 +#define AXP_NOT_INIT -3 + +//! Chip Address +#define AXP202_SLAVE_ADDRESS (0x35) +#define AXP192_SLAVE_ADDRESS (0x34) + +//! Chip ID +#define AXP202_CHIP_ID 0x41 +#define AXP192_CHIP_ID 0x03 + +//! REG MAP +#define AXP202_STATUS (0x00) +#define AXP202_MODE_CHGSTATUS (0x01) +#define AXP202_OTG_STATUS (0x02) +#define AXP202_IC_TYPE (0x03) +#define AXP202_DATA_BUFFER1 (0x04) +#define AXP202_DATA_BUFFER2 (0x05) +#define AXP202_DATA_BUFFER3 (0x06) +#define AXP202_DATA_BUFFER4 (0x07) +#define AXP202_DATA_BUFFER5 (0x08) +#define AXP202_DATA_BUFFER6 (0x09) +#define AXP202_DATA_BUFFER7 (0x0A) +#define AXP202_DATA_BUFFER8 (0x0B) +#define AXP202_DATA_BUFFER9 (0x0C) +#define AXP202_DATA_BUFFERA (0x0D) +#define AXP202_DATA_BUFFERB (0x0E) +#define AXP202_DATA_BUFFERC (0x0F) +#define AXP202_LDO234_DC23_CTL (0x12) +#define AXP202_DC2OUT_VOL (0x23) +#define AXP202_LDO3_DC2_DVM (0x25) +#define AXP202_DC3OUT_VOL (0x27) +#define AXP202_LDO24OUT_VOL (0x28) +#define AXP202_LDO3OUT_VOL (0x29) +#define AXP202_IPS_SET (0x30) +#define AXP202_VOFF_SET (0x31) +#define AXP202_OFF_CTL (0x32) +#define AXP202_CHARGE1 (0x33) +#define AXP202_CHARGE2 (0x34) +#define AXP202_BACKUP_CHG (0x35) +#define AXP202_POK_SET (0x36) +#define AXP202_DCDC_FREQSET (0x37) +#define AXP202_VLTF_CHGSET (0x38) +#define AXP202_VHTF_CHGSET (0x39) +#define AXP202_APS_WARNING1 (0x3A) +#define AXP202_APS_WARNING2 (0x3B) +#define AXP202_TLTF_DISCHGSET (0x3C) +#define AXP202_THTF_DISCHGSET (0x3D) +#define AXP202_DCDC_MODESET (0x80) +#define AXP202_ADC_EN1 (0x82) +#define AXP202_ADC_EN2 (0x83) +#define AXP202_ADC_SPEED (0x84) +#define AXP202_ADC_INPUTRANGE (0x85) +#define AXP202_ADC_IRQ_RETFSET (0x86) +#define AXP202_ADC_IRQ_FETFSET (0x87) +#define AXP202_TIMER_CTL (0x8A) +#define AXP202_VBUS_DET_SRP (0x8B) +#define AXP202_HOTOVER_CTL (0x8F) +#define AXP202_GPIO0_CTL (0x90) +#define AXP202_GPIO0_VOL (0x91) +#define AXP202_GPIO1_CTL (0x92) +#define AXP202_GPIO2_CTL (0x93) +#define AXP202_GPIO012_SIGNAL (0x94) +#define AXP202_GPIO3_CTL (0x95) +#define AXP202_INTEN1 (0x40) +#define AXP202_INTEN2 (0x41) +#define AXP202_INTEN3 (0x42) +#define AXP202_INTEN4 (0x43) +#define AXP202_INTEN5 (0x44) +#define AXP202_INTSTS1 (0x48) +#define AXP202_INTSTS2 (0x49) +#define AXP202_INTSTS3 (0x4A) +#define AXP202_INTSTS4 (0x4B) +#define AXP202_INTSTS5 (0x4C) + +//Irq control register +#define AXP192_INTEN1 (0x40) +#define AXP192_INTEN2 (0x41) +#define AXP192_INTEN3 (0x42) +#define AXP192_INTEN4 (0x43) +#define AXP192_INTEN5 (0x4A) +//Irq status register +#define AXP192_INTSTS1 (0x44) +#define AXP192_INTSTS2 (0x45) +#define AXP192_INTSTS3 (0x46) +#define AXP192_INTSTS4 (0x47) +#define AXP192_INTSTS5 (0x4D) + + +#define AXP192_DC1_VLOTAGE (0x26) +#define AXP192_LDO23OUT_VOL (0x28) +#define AXP192_GPIO0_CTL (0x90) +#define AXP192_GPIO0_VOL (0x91) + + +/* axp 20 adc data register */ +#define AXP202_BAT_AVERVOL_H8 (0x78) +#define AXP202_BAT_AVERVOL_L4 (0x79) +#define AXP202_BAT_AVERCHGCUR_H8 (0x7A) +#define AXP202_BAT_AVERCHGCUR_L4 (0x7B) +#define AXP202_BAT_VOL_H8 (0x50) +#define AXP202_BAT_VOL_L4 (0x51) +#define AXP202_ACIN_VOL_H8 (0x56) +#define AXP202_ACIN_VOL_L4 (0x57) +#define AXP202_ACIN_CUR_H8 (0x58) +#define AXP202_ACIN_CUR_L4 (0x59) +#define AXP202_VBUS_VOL_H8 (0x5A) +#define AXP202_VBUS_VOL_L4 (0x5B) +#define AXP202_VBUS_CUR_H8 (0x5C) +#define AXP202_VBUS_CUR_L4 (0x5D) +#define AXP202_INTERNAL_TEMP_H8 (0x5E) +#define AXP202_INTERNAL_TEMP_L4 (0x5F) +#define AXP202_TS_IN_H8 (0x62) +#define AXP202_TS_IN_L4 (0x63) +#define AXP202_GPIO0_VOL_ADC_H8 (0x64) +#define AXP202_GPIO0_VOL_ADC_L4 (0x65) +#define AXP202_GPIO1_VOL_ADC_H8 (0x66) +#define AXP202_GPIO1_VOL_ADC_L4 (0x67) + +#define AXP202_BAT_AVERDISCHGCUR_H8 (0x7C) +#define AXP202_BAT_AVERDISCHGCUR_L5 (0x7D) +#define AXP202_APS_AVERVOL_H8 (0x7E) +#define AXP202_APS_AVERVOL_L4 (0x7F) +#define AXP202_INT_BAT_CHGCUR_H8 (0xA0) +#define AXP202_INT_BAT_CHGCUR_L4 (0xA1) +#define AXP202_EXT_BAT_CHGCUR_H8 (0xA2) +#define AXP202_EXT_BAT_CHGCUR_L4 (0xA3) +#define AXP202_INT_BAT_DISCHGCUR_H8 (0xA4) +#define AXP202_INT_BAT_DISCHGCUR_L4 (0xA5) +#define AXP202_EXT_BAT_DISCHGCUR_H8 (0xA6) +#define AXP202_EXT_BAT_DISCHGCUR_L4 (0xA7) +#define AXP202_BAT_CHGCOULOMB3 (0xB0) +#define AXP202_BAT_CHGCOULOMB2 (0xB1) +#define AXP202_BAT_CHGCOULOMB1 (0xB2) +#define AXP202_BAT_CHGCOULOMB0 (0xB3) +#define AXP202_BAT_DISCHGCOULOMB3 (0xB4) +#define AXP202_BAT_DISCHGCOULOMB2 (0xB5) +#define AXP202_BAT_DISCHGCOULOMB1 (0xB6) +#define AXP202_BAT_DISCHGCOULOMB0 (0xB7) +#define AXP202_COULOMB_CTL (0xB8) +#define AXP202_BAT_POWERH8 (0x70) +#define AXP202_BAT_POWERM8 (0x71) +#define AXP202_BAT_POWERL8 (0x72) + +#define AXP202_VREF_TEM_CTRL (0xF3) +#define AXP202_BATT_PERCENTAGE (0xB9) + + +/* bit definitions for AXP events ,irq event */ +/* AXP202 */ +#define AXP202_IRQ_USBLO (1) +#define AXP202_IRQ_USBRE (2) +#define AXP202_IRQ_USBIN (3) +#define AXP202_IRQ_USBOV (4) +#define AXP202_IRQ_ACRE (5) +#define AXP202_IRQ_ACIN (6) +#define AXP202_IRQ_ACOV (7) + +#define AXP202_IRQ_TEMLO (8) +#define AXP202_IRQ_TEMOV (9) +#define AXP202_IRQ_CHAOV (10) +#define AXP202_IRQ_CHAST (11) +#define AXP202_IRQ_BATATOU (12) +#define AXP202_IRQ_BATATIN (13) +#define AXP202_IRQ_BATRE (14) +#define AXP202_IRQ_BATIN (15) + +#define AXP202_IRQ_POKLO (16) +#define AXP202_IRQ_POKSH (17) +#define AXP202_IRQ_LDO3LO (18) +#define AXP202_IRQ_DCDC3LO (19) +#define AXP202_IRQ_DCDC2LO (20) +#define AXP202_IRQ_CHACURLO (22) +#define AXP202_IRQ_ICTEMOV (23) + +#define AXP202_IRQ_EXTLOWARN2 (24) +#define AXP202_IRQ_EXTLOWARN1 (25) +#define AXP202_IRQ_SESSION_END (26) +#define AXP202_IRQ_SESS_AB_VALID (27) +#define AXP202_IRQ_VBUS_UN_VALID (28) +#define AXP202_IRQ_VBUS_VALID (29) +#define AXP202_IRQ_PDOWN_BY_NOE (30) +#define AXP202_IRQ_PUP_BY_NOE (31) + +#define AXP202_IRQ_GPIO0TG (32) +#define AXP202_IRQ_GPIO1TG (33) +#define AXP202_IRQ_GPIO2TG (34) +#define AXP202_IRQ_GPIO3TG (35) +#define AXP202_IRQ_PEKFE (37) +#define AXP202_IRQ_PEKRE (38) +#define AXP202_IRQ_TIMER (39) + + +//Signal Capture +#define AXP202_BATT_VOLTAGE_STEP (1.1F) +#define AXP202_BATT_DISCHARGE_CUR_STEP (0.5F) +#define AXP202_BATT_CHARGE_CUR_STEP (0.5F) +#define AXP202_ACIN_VOLTAGE_STEP (1.7F) +#define AXP202_ACIN_CUR_STEP (0.625F) +#define AXP202_VBUS_VOLTAGE_STEP (1.7F) +#define AXP202_VBUS_CUR_STEP (0.375F) +#define AXP202_INTENAL_TEMP_STEP (0.1F) +#define AXP202_APS_VOLTAGE_STEP (1.4F) +#define AXP202_TS_PIN_OUT_STEP (0.8F) +#define AXP202_GPIO0_STEP (0.5F) +#define AXP202_GPIO1_STEP (0.5F) + + + + +#define FORCED_OPEN_DCDC3(x) (x |= AXP202_DCDC3) +#define BIT_MASK(x) (1 << x) +#define IS_OPEN(reg,channel) (bool)(reg & BIT_MASK(channel)) + +#define AXP202_ON 1 +#define AXP202_OFF 0 + + +enum { + AXP202_EXTEN = 0, + AXP202_DCDC3 = 1, + AXP202_LDO2 = 2, + AXP202_LDO4 = 3, + AXP202_DCDC2 = 4, + AXP202_LDO3 = 6, + AXP202_OUTPUT_MAX, +}; + + +enum { + AXP192_DCDC1 = 0, + AXP192_DCDC3 = 1, + AXP192_LDO2 = 2, + AXP192_LDO3 = 3, + AXP192_DCDC2 = 4, + AXP192_EXTEN = 6, + AXP192_OUTPUT_MAX, +}; + + +typedef enum { + AXP202_STARTUP_TIME_128MS, + AXP202_STARTUP_TIME_3S, + AXP202_STARTUP_TIME_1S, + AXP202_STARTUP_TIME_2S, +} axp202_startup_time_t; + + +typedef enum { + AXP192_STARTUP_TIME_128MS, + AXP192_STARTUP_TIME_512MS, + AXP192_STARTUP_TIME_1S, + AXP192_STARTUP_TIME_2S, +} axp192_startup_time_t; + + + +typedef enum { + AXP_LONGPRESS_TIME_1S, + AXP_LONGPRESS_TIME_1S5, + AXP_LONGPRESS_TIME_2S, + AXP_LONGPRESS_TIME_2S5, +} axp_loonPress_time_t; + + +typedef enum { + AXP_POWER_OFF_TIME_4S, + AXP_POWER_OFF_TIME_65, + AXP_POWER_OFF_TIME_8S, + AXP_POWER_OFF_TIME_16S, +} axp_poweroff_time_t; + +//REG 33H: Charging control 1 Charging target-voltage setting +typedef enum { + AXP202_TARGET_VOL_4_1V, + AXP202_TARGET_VOL_4_15V, + AXP202_TARGET_VOL_4_2V, + AXP202_TARGET_VOL_4_36V +} axp_chargeing_vol_t; + +//REG 82H: ADC Enable 1 register Parameter +typedef enum { + AXP202_BATT_VOL_ADC1 = 1 << 7, + AXP202_BATT_CUR_ADC1 = 1 << 6, + AXP202_ACIN_VOL_ADC1 = 1 << 5, + AXP202_ACIN_CUR_ADC1 = 1 << 4, + AXP202_VBUS_VOL_ADC1 = 1 << 3, + AXP202_VBUS_CUR_ADC1 = 1 << 2, + AXP202_APS_VOL_ADC1 = 1 << 1, + AXP202_TS_PIN_ADC1 = 1 << 0 +} axp_adc1_func_t; + +// REG 83H: ADC Enable 2 register Parameter +typedef enum { + AXP202_TEMP_MONITORING_ADC2 = 1 << 7, + AXP202_GPIO1_FUNC_ADC2 = 1 << 3, + AXP202_GPIO0_FUNC_ADC2 = 1 << 2 +} axp_adc2_func_t; + +typedef enum { + AXP202_LDO3_MODE_LDO, + AXP202_LDO3_MODE_DCIN +} axp202_ldo3_mode_t; + + +typedef enum { + //IRQ1 + AXP202_VBUS_VHOLD_LOW_IRQ = 1 << 1, + AXP202_VBUS_REMOVED_IRQ = 1 << 2, + AXP202_VBUS_CONNECT_IRQ = 1 << 3, + AXP202_VBUS_OVER_VOL_IRQ = 1 << 4, + AXP202_ACIN_REMOVED_IRQ = 1 << 5, + AXP202_ACIN_CONNECT_IRQ = 1 << 6, + AXP202_ACIN_OVER_VOL_IRQ = 1 << 7, + //IRQ2 + AXP202_BATT_LOW_TEMP_IRQ = 1 << 8, + AXP202_BATT_OVER_TEMP_IRQ = 1 << 9, + AXP202_CHARGING_FINISHED_IRQ = 1 << 10, + AXP202_CHARGING_IRQ = 1 << 11, + AXP202_BATT_EXIT_ACTIVATE_IRQ = 1 << 12, + AXP202_BATT_ACTIVATE_IRQ = 1 << 13, + AXP202_BATT_REMOVED_IRQ = 1 << 14, + AXP202_BATT_CONNECT_IRQ = 1 << 15, + //IRQ3 + AXP202_PEK_LONGPRESS_IRQ = 1 << 16, + AXP202_PEK_SHORTPRESS_IRQ = 1 << 17, + AXP202_LDO3_LOW_VOL_IRQ = 1 << 18, + AXP202_DC3_LOW_VOL_IRQ = 1 << 19, + AXP202_DC2_LOW_VOL_IRQ = 1 << 20, + AXP202_CHARGE_LOW_CUR_IRQ = 1 << 21, + AXP202_CHIP_TEMP_HIGH_IRQ = 1 << 22, + + //IRQ4 + AXP202_APS_LOW_VOL_LEVEL2_IRQ = 1 << 24, + APX202_APS_LOW_VOL_LEVEL1_IRQ = 1 << 25, + AXP202_VBUS_SESSION_END_IRQ = 1 << 26, + AXP202_VBUS_SESSION_AB_IRQ = 1 << 27, + AXP202_VBUS_INVALID_IRQ = 1 << 28, + AXP202_VBUS_VAILD_IRQ = 1 << 29, + AXP202_NOE_OFF_IRQ = 1 << 30, + AXP202_NOE_ON_IRQ = 1 << 31, + AXP202_ALL_IRQ = 0xFFFF + +} axp_irq_t; + +typedef enum { + AXP202_LDO4_1250MV, + AXP202_LDO4_1300MV, + AXP202_LDO4_1400MV, + AXP202_LDO4_1500MV, + AXP202_LDO4_1600MV, + AXP202_LDO4_1700MV, + AXP202_LDO4_1800MV, + AXP202_LDO4_1900MV, + AXP202_LDO4_2000MV, + AXP202_LDO4_2500MV, + AXP202_LDO4_2700MV, + AXP202_LDO4_2800MV, + AXP202_LDO4_3000MV, + AXP202_LDO4_3100MV, + AXP202_LDO4_3200MV, + AXP202_LDO4_3300MV, + AXP202_LDO4_MAX, +} axp_ldo4_table_t; + +typedef enum { + AXP20X_LED_OFF, + AXP20X_LED_BLINK_1HZ, + AXP20X_LED_BLINK_4HZ, + AXP20X_LED_LOW_LEVEL, +} axp_chgled_mode_t; + + +typedef enum { + AXP202_GPIO_1V8, + AXP202_GPIO_2V5, + AXP202_GPIO_2V8, + AXP202_GPIO_3V0, + AXP202_GPIO_3V1, + AXP202_GPIO_3V3, + AXP202_GPIO_3V4, + AXP202_GPIO_3V5, +} axp202_gpio_voltage_t; + +typedef enum { + AXP202_GPIO2_OUTPUT_LOW, + AXP202_GPIO2_FLOATING, + AXP202_GPIO3_INPUT, +} axp202_gpio2_mode_t; + +typedef enum { + AXP202_GPIO3_DIGITAL_INPUT, + AXP202_GPIO3_OPEN_DRAIN_OUTPUT, +} axp202_gpio3_mode_t; + +typedef enum { + AXP202_GPIO3_OUTPUT_LOW, + AXP202_GPIO3_FLOATING, +} axp202_gpio3_output_t; + + +typedef enum { + AXP202_GPIO0, + AXP202_GPIO1, + AXP202_GPIO2, + AXP202_GPIO3, +} axp202_gpio_t; + + +typedef enum { + AXP_ADC_SAMPLING_RATE_25HZ = 0, + AXP_ADC_SAMPLING_RATE_50HZ = 1, + AXP_ADC_SAMPLING_RATE_100HZ = 2, + AXP_ADC_SAMPLING_RATE_200HZ = 3, +} axp_adc_sampling_rate_t; + + +typedef enum { + AXP192_GPIO0_NMOD_OUTPUT = 0, + AXP192_GPIO0_INPUT = 1, + AXP192_GPIO0_LDO_OUTPUT = 2, + AXP192_GPIO0_ADC_INPUT = 4, + AXP192_GPIO0_OUTPUT_LOW = 5, + AXP192_GPIO0_FLOATING = 7 +} axp192_gpio0_mode_t; + + +typedef enum { + AXP192_GPIO_1V8, + AXP192_GPIO_1V9, + AXP192_GPIO_2V0, + AXP192_GPIO_2V1, + AXP192_GPIO_2V2, + AXP192_GPIO_2V3, + AXP192_GPIO_2V4, + AXP192_GPIO_2V5, + AXP192_GPIO_2V6, + AXP192_GPIO_2V7, + AXP192_GPIO_2V8, + AXP192_GPIO_2V9, + AXP192_GPIO_3V0, + AXP192_GPIO_3V1, + AXP192_GPIO_3V2, + AXP192_GPIO_3V3, +} axp192_gpio_voltage_t; + + +class AXP20X_Class +{ +public: + int begin(TwoWire &port = Wire, uint8_t addr = AXP202_SLAVE_ADDRESS); + + // Power Output Control + int setPowerOutPut(uint8_t ch, bool en); + + bool isBatteryConnect(); + bool isChargeing(); + bool isLDO2Enable(); + bool isLDO3Enable(); + bool isLDO4Enable(); + bool isDCDC3Enable(); + bool isDCDC2Enable(); + bool isChargeingEnable(); + bool isVBUSPlug(); + + //Only axp192 chip + bool isDCDC1Enable(); + //Only axp192 chip + bool isExtenEnable(); + + //IRQ Status + bool isAcinOverVoltageIRQ(); + bool isAcinPlugInIRQ(); + bool isAcinRemoveIRQ(); + bool isVbusOverVoltageIRQ(); + bool isVbusPlugInIRQ(); + bool isVbusRemoveIRQ(); + bool isVbusLowVHOLDIRQ(); + + bool isBattPlugInIRQ(); + bool isBattRemoveIRQ(); + bool isBattEnterActivateIRQ(); + bool isBattExitActivateIRQ(); + bool isChargingIRQ(); + bool isChargingDoneIRQ(); + bool isBattTempLowIRQ(); + bool isBattTempHighIRQ(); + + bool isPEKShortPressIRQ(); + bool isPEKLongtPressIRQ(); + + //! Group4 ADC data + float getAcinVoltage(); + float getAcinCurrent(); + float getVbusVoltage(); + float getVbusCurrent(); + float getTemp(); + float getTSTemp(); + float getGPIO0Voltage(); + float getGPIO1Voltage(); + float getBattInpower(); + float getBattVoltage(); + float getBattChargeCurrent(); + float getBattDischargeCurrent(); + float getSysIPSOUTVoltage(); + uint32_t getBattChargeCoulomb(); + uint32_t getBattDischargeCoulomb(); + float getSettingChargeCurrent(); + + int setChargingTargetVoltage(axp_chargeing_vol_t param); + int enableChargeing(bool en); + + int adc1Enable(uint16_t params, bool en); + int adc2Enable(uint16_t params, bool en); + + /** + * param: axp202_startup_time_t or axp192_startup_time_t + */ + int setStartupTime(uint8_t param); + + /** + * param: axp_loonPress_time_t + */ + int setlongPressTime(uint8_t param); + + /** + * @param param: axp_poweroff_time_t + */ + int setShutdownTime(uint8_t param); + + + int setTimeOutShutdown(bool en); + + int shutdown(); + + /** + * params: axp_irq_t + */ + int enableIRQ(uint32_t params, bool en); + int readIRQ(); + void clearIRQ(); + + + int setDCDC1Voltage(uint16_t mv); //! Only AXP192 support + // return mv + uint16_t getDCDC1Voltage(); //! Only AXP192 support + + + // ----------------- + int setDCDC2Voltage(uint16_t mv); + int setDCDC3Voltage(uint16_t mv); + int setLDO2Voltage(uint16_t mv); + int setLDO3Voltage(uint16_t mv); + + + int setLDO4Voltage(axp_ldo4_table_t param); //! Only axp202 support + + // return mv + uint16_t getLDO2Voltage(); + uint16_t getLDO3Voltage(); + uint16_t getDCDC2Voltage(); + uint16_t getDCDC3Voltage(); + + + /** + * @param mode: axp_chgled_mode_t + */ + int setChgLEDMode(uint8_t mode); + + + /** + * @param mode: axp202_ldo3_mode_t + */ + int setLDO3Mode(uint8_t mode); //! Only AXP202 support + + int getBattPercentage(); + + int debugCharging(); + int debugStatus(); + int limitingOff(); + + int setAdcSamplingRate(axp_adc_sampling_rate_t rate); + uint8_t getAdcSamplingRate(); + float getCoulombData(); + + + int gpio0Setting(axp192_gpio0_mode_t mode); //! Only axp192 + int gpio0SetVoltage(axp192_gpio_voltage_t vol); + uint16_t gpio0GetVoltage(); + + //! The following features have not been tested + /** + * @brief setGPIO0Voltage + * @note + * @param mv: axp202_gpio_voltage_t enum + * @retval + */ + int setGPIO0Voltage(uint8_t mv); + + /** + * @brief setGPIO0Level + * @note + * @param level: 0 or 1 + * @retval + */ + int setGPIO0Level(uint8_t level); + + /** + * @brief setGPIO1Level + * @note + * @param level: 0 or 1 + * @retval + */ + int setGPIO1Level(uint8_t level); + + /** + * @brief readGpioStatus + * @note + * @retval + */ + int readGpioStatus(); + + int readGpio0Level(); + + int readGpio1Level(); + + int readGpio2Level(); + + int setGpio2Mode(uint8_t mode); + + /** + * @brief setGpio3Mode + * @note Set GPIO3 mode, can only be set to output low level, floating, can not output high level + * @param mode: axp202_gpio3_mode_t enum + * @retval + */ + int setGpio3Mode(uint8_t mode); + + /** + * @brief setGpio3Level + * @note Can only be set when GPIO3 is configured as output mode + * @param level: axp202_gpio3_output_t enum + * @retval + */ + int setGpio3Level(uint8_t level); + + + /** + * @brief setGpioInterruptMode + * @note Interrupt can only be set when GPIO is configured as input mode + * @param gpio: axp202_gpio_t enum + * @param mode: RISING or FALLING + * @param en: true or false + * @retval + */ + int setGpioInterruptMode(uint8_t gpio, int mode, bool en); + +private: + + uint16_t _getRegistH8L5(uint8_t regh8, uint8_t regl4) + { + uint8_t hv, lv; + _readByte(regh8, 1, &hv); + _readByte(regl4, 1, &lv); + return (hv << 5) | (lv & 0x1F); + } + + uint16_t _getRegistResult(uint8_t regh8, uint8_t regl4) + { + uint8_t hv, lv; + _readByte(regh8, 1, &hv); + _readByte(regl4, 1, &lv); + return (hv << 4) | (lv & 0xF); + } + + int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data) + { + if (nbytes == 0 || !data) return -1; + _i2cPort->beginTransmission(_address); + _i2cPort->write(reg); + _i2cPort->endTransmission(); + _i2cPort->requestFrom(_address, nbytes); + uint8_t index = 0; + while (_i2cPort->available()) + data[index++] = _i2cPort->read(); + return 0; + } + + int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data) + { + if (nbytes == 0 || !data) return -1; + _i2cPort->beginTransmission(_address); + _i2cPort->write(reg); + for (uint8_t i = 0; i < nbytes; i++) { + _i2cPort->write(data[i]); + } + _i2cPort->endTransmission(); + return 0; + } + + int _setGpioInterrupt(uint8_t *val, int mode, bool en); + static const uint8_t startupParams[]; + static const uint8_t longPressParams[]; + static const uint8_t shutdownParams[]; + static const uint8_t targetVolParams[]; + static uint8_t _outputReg; + + uint8_t _address; + bool _init = false; + TwoWire *_i2cPort; + uint8_t _irq[5]; + uint8_t _chip_id; + uint8_t _gpio[4]; +}; diff --git a/platformio.ini b/platformio.ini index 0fddc0b8..9b3f27da 100644 --- a/platformio.ini +++ b/platformio.ini @@ -19,6 +19,7 @@ halfile = generic.h ;halfile = ttgov21new.h ;halfile = ttgofox.h ;halfile = ttgobeam.h +;halfile = ttgobeam10.h ;halfile = fipy.h ;halfile = lopy.h ;halfile = lopy4.h @@ -42,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.0 +release_version = 1.8.01 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 diff --git a/src/battery.cpp b/src/battery.cpp index 3af874d9..39b78683 100644 --- a/src/battery.cpp +++ b/src/battery.cpp @@ -52,6 +52,10 @@ uint16_t read_voltage() { digitalWrite(EXT_POWER_SW, EXT_POWER_OFF); #endif +#ifdef HAS_PMU + voltage = axp.getBattVoltage(); +#endif + return (uint16_t)voltage; #else return 0; diff --git a/src/hal/ttgobeam10.h b/src/hal/ttgobeam10.h new file mode 100644 index 00000000..95820098 --- /dev/null +++ b/src/hal/ttgobeam10.h @@ -0,0 +1,45 @@ +// clang-format off +// upload_speed 921600 +// board ttgo-t-beam + +#ifndef _TTGOBEAM_H +#define _TTGOBEAM_H + +#include + +// Hardware related definitions for TTGO T-Beam board +// (only) for newer T-Beam version T22_V10 +// pinouts taken from https://github.com/lewisxhe/TTGO-T-Beam + +#define HAS_LORA 1 // comment out if device shall not send data via LoRa +#define CFG_sx1276_radio 1 // HPD13A LoRa SoC +#define BOARD_HAS_PSRAM // use extra 4MB external RAM +#define HAS_BUTTON GPIO_NUM_36 // on board button (next to reset) +#define HAS_PMU 1 // AXP192 power management chip +#define PMU_INT GPIO_NUM_36 // AXP192 interrupt + +#define HAS_LED NOT_A_PIN + +// GPS settings +#define HAS_GPS 1 // use on board GPS +#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_34, GPIO_NUM_12 // UBlox NEO 6M + +// enable only if device has these sensors, otherwise comment these lines +// BME680 sensor on I2C bus +//#define HAS_BME 1 // Enable BME sensors in general +//#define HAS_BME680 SDA, SCL +//#define BME680_ADDR BME680_I2C_ADDR_PRIMARY // !! connect SDIO of BME680 to GND !! + +// display (if connected) +#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +#define MY_OLED_SDA SDA +#define MY_OLED_SCL SCL +#define MY_OLED_RST U8X8_PIN_NONE +//#define DISPLAY_FLIP 1 // use if display is rotated + +// user defined sensors (if connected) +//#define HAS_SENSORS 1 // comment out if device has user defined sensors + +//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature + +#endif diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp new file mode 100644 index 00000000..fb07d034 --- /dev/null +++ b/src/i2cscan.cpp @@ -0,0 +1,102 @@ +// Basic config +#include "globals.h" +#include "i2cscan.h" + +// Local logging tag +static const char TAG[] = __FILE__; + +#define SSD1306_PRIMARY_ADDRESS (0x3D) +#define SSD1306_SECONDARY_ADDRESS (0x3C) +#define BME_PRIMARY_ADDRESS (0x77) +#define BME_SECONDARY_ADDRESS (0x76) +#define AXP192_PRIMARY_ADDRESS (0x34) +#define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) + +int i2c_scan(void) { + + int i2c_ret, addr; + int devices = 0; + + ESP_LOGI(TAG, "Starting I2C bus scan..."); + + for (addr = 8; addr <= 119; addr++) { + + // scan i2c bus with no more to 100KHz + Wire.begin(SDA, SCL, 100000); + Wire.beginTransmission(addr); + Wire.write(addr); + i2c_ret = Wire.endTransmission(); + + if (i2c_ret == 0) { + devices++; + + switch (addr) { + + case SSD1306_PRIMARY_ADDRESS: + case SSD1306_SECONDARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: SSD1306 Display controller", addr); + break; + + case BME_PRIMARY_ADDRESS: + case BME_SECONDARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: Bosch BME MEMS", addr); + break; + + case AXP192_PRIMARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: AXP192 power management", addr); +#ifdef HAS_PMU + AXP192_init(); +#endif + break; + + case MCP_24AA02E64_PRIMARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: 24AA02E64 serial EEPROM", addr); + break; + + default: + ESP_LOGI(TAG, "0x%X: Unknown device", addr); + break; + } + } // switch + } // for loop + + ESP_LOGI(TAG, "I2C scan done, %u devices found.", devices); + + return devices; +} + +#ifdef HAS_PMU + +void AXP192_init(void) { + + AXP20X_Class axp; + + if (axp.begin(Wire, AXP192_PRIMARY_ADDRESS)) + ESP_LOGI(TAG, "AXP192 PMU initialization failed"); + else { + + axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); + axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); + axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + axp.setChgLEDMode(AXP20X_LED_OFF); + //axp.setChgLEDMode(LED_BLINK_4HZ); + + /* + axp.setDCDC1Voltage(3300); + + pinMode(PMU_IRQ, INPUT_PULLUP); + attachInterrupt(PMU_IRQ, [] { pmu_irq = true; }, FALLING); + + axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); + axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | + AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, + 1); + axp.clearIRQ(); + */ + + ESP_LOGI(TAG, "AXP192 PMU initialized."); + } +#endif // HAS_PMU +} \ No newline at end of file diff --git a/src/lorawan.cpp b/src/lorawan.cpp index b8cbc1b4..fcba037a 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -151,7 +151,7 @@ void get_hard_deveui(uint8_t *pdeveui) { uint8_t i2c_ret; // Init this just in case, no more to 100KHz - Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 100000); + Wire.begin(SDA, SCL, 100000); Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS); Wire.write(MCP_24AA02E64_MAC_ADDRESS); i2c_ret = Wire.endTransmission(); diff --git a/src/main.cpp b/src/main.cpp index f0a34b14..0dc90395 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -169,6 +169,8 @@ void setup() { ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); #endif + i2c_scan(); + #endif // verbose // read (and initialize on first run) runtime settings from NVRAM