/** * * @license MIT License * * Copyright (c) 2022 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 XPowersAXP192.tpp * @author Lewis He (lewishe@outlook.com) * @date 2022-05-07 * */ #if defined(ARDUINO) #include #else #include #endif /*ARDUINO*/ #include "XPowersCommon.tpp" #include "REG/AXP192Constants.h" #include "XPowersLibInterface.hpp" typedef enum { XPOWERS_AXP192_BOOT_TIME_128MS, XPOWERS_AXP192_BOOT_TIME_512MS, XPOWERS_AXP192_BOOT_TIME_1S, XPOWERS_AXP192_BOOT_TIME_2S, } xpowers_axp192_boot_time_t; typedef enum { XPOWERS_AXP192_CHG_ITERM_LESS_10_PERCENT, XPOWERS_AXP192_CHG_ITERM_LESS_15_PERCENT, } xpowers_axp192_chg_iterm_t; typedef enum { XPOWERS_AXP192_PRECHG_TIMEOUT_30MIN, XPOWERS_AXP192_PRECHG_TIMEOUT_40MIN, XPOWERS_AXP192_PRECHG_TIMEOUT_50MIN, XPOWERS_AXP192_PRECHG_TIMEOUT_60MIN, } xpoers_axp192_prechg_to_t; typedef enum { XPOWERS_AXP192_POWEROFF_4S, XPOWERS_AXP192_POWEROFF_65, XPOWERS_AXP192_POWEROFF_8S, XPOWERS_AXP192_POWEROFF_10S, } xpowers_axp192_pekey_poweroff_arg_t; typedef enum { XPOWERS_AXP192_LONGPRESS_1000MS, XPOWERS_AXP192_LONGPRESS_1500MS, XPOWERS_AXP192_LONGPRESS_2000MS, XPOWERS_AXP192_LONGPRESS_2500MS, } xpowers_axp192_pekey_long_press_t; typedef enum { XPOWERS_AXP192_CHG_CONS_TIMEOUT_7H, XPOWERS_AXP192_CHG_CONS_TIMEOUT_8H, XPOWERS_AXP192_CHG_CONS_TIMEOUT_9H, XPOWERS_AXP192_CHG_CONS_TIMEOUT_10H, } xpowers_axp192_chg_cons_to_t; typedef enum { XPOWERS_AXP192_BACKUP_BAT_VOL_3V1, XPOWERS_AXP192_BACKUP_BAT_VOL_3V, XPOWERS_AXP192_BACKUP_BAT_VOL_3V0, //!NEED FIX,DATASHEET ERROR! XPOWERS_AXP192_BACKUP_BAT_VOL_2V5, } xpowers_axp192_backup_batt_vol_t; typedef enum { XPOWERS_AXP192_BACKUP_BAT_CUR_50UA, XPOWERS_AXP192_BACKUP_BAT_CUR_100UA, XPOWERS_AXP192_BACKUP_BAT_CUR_200UA, XPOWERS_AXP192_BACKUP_BAT_CUR_400UA, } xpowers_axp192_backup_batt_curr_t; typedef struct { uint8_t mode; } xpowers_axp192_gpio_t; class XPowersAXP192 : public XPowersCommon, public XPowersLibInterface { friend class XPowersCommon; typedef enum { PMU_GPIO0, PMU_GPIO1, PMU_GPIO2, PMU_GPIO3, PMU_GPIO4, PMU_GPIO5, PMU_TS_PIN } xpowers_axp192_num_t; typedef enum { MONITOR_TS_PIN = _BV(0), MONITOR_APS_VOLTAGE = _BV(1), MONITOR_USB_CURRENT = _BV(2), MONITOR_USB_VOLTAGE = _BV(3), MONITOR_AC_CURRENT = _BV(4), MONITOR_AC_VOLTAGE = _BV(5), MONITOR_BAT_CURRENT = _BV(6), MONITOR_BAT_VOLTAGE = _BV(7), MONITOR_ADC_IO3 = _BV(8), MONITOR_ADC_IO2 = _BV(9), MONITOR_ADC_IO1 = _BV(10), MONITOR_ADC_IO0 = _BV(11), MONITOR_TEMPERATURE = _BV(16), } axp192_adc_func_t; typedef struct { uint8_t mode; } xpowers_gpio_t; public: #if defined(ARDUINO) XPowersAXP192(TwoWire &w, int sda = SDA, int scl = SCL, uint8_t addr = AXP192_SLAVE_ADDRESS) { __wire = &w; __sda = sda; __scl = scl; __addr = addr; } #endif XPowersAXP192(uint8_t addr, iic_fptr_t readRegCallback, iic_fptr_t writeRegCallback) { thisReadRegCallback = readRegCallback; thisWriteRegCallback = writeRegCallback; __addr = addr; } XPowersAXP192() { #if defined(ARDUINO) __wire = &Wire; __sda = SDA; __scl = SCL; #endif __addr = AXP192_SLAVE_ADDRESS; } ~XPowersAXP192() { log_i("~XPowersAXP192"); deinit(); } #if defined(ARDUINO) bool init(TwoWire &w, int sda = SDA, int scl = SCL, uint8_t addr = AXP192_SLAVE_ADDRESS) { __wire = &w; __sda = sda; __scl = scl; __addr = addr; return begin(); } #endif bool init() { return begin(); } void deinit() { end(); } uint16_t status() { return readRegister(XPOWERS_AXP192_STATUS); } bool isAcinVbusStart() { return getRegisterBit(XPOWERS_AXP192_STATUS, 0); } bool isDischarge() { return !getRegisterBit(XPOWERS_AXP192_STATUS, 2); } bool isVbusIn(void) { return getRegisterBit(XPOWERS_AXP192_STATUS, 5); } bool isAcinEfficient() { return getRegisterBit(XPOWERS_AXP192_STATUS, 6); } bool isAcinIn() { return getRegisterBit(XPOWERS_AXP192_STATUS, 7); } bool isOverTemperature() { return getRegisterBit(XPOWERS_AXP192_MODE_CHGSTATUS, 7); } bool isCharging(void) { return getRegisterBit(XPOWERS_AXP192_MODE_CHGSTATUS, 6); } bool isBatteryConnect(void) { return getRegisterBit(XPOWERS_AXP192_MODE_CHGSTATUS, 5); } bool isBattInActiveMode() { return getRegisterBit(XPOWERS_AXP192_MODE_CHGSTATUS, 3); } bool isChargeCurrLessPreset() { return getRegisterBit(XPOWERS_AXP192_MODE_CHGSTATUS, 2); } void enableVbusVoltageLimit() { setRegisterBit(XPOWERS_AXP192_IPS_SET, 6); } void disableVbusVoltageLimit() { clrRegisterBit(XPOWERS_AXP192_IPS_SET, 6); } /** * @brief Set VBUS Voltage Input Limit. * @param opt: View the related chip type xpowers_axp192_vbus_vol_limit_t enumeration * parameters in "XPowersParams.hpp" */ void setVbusVoltageLimit(uint8_t opt) { int val = readRegister(XPOWERS_AXP192_IPS_SET); if (val == -1)return; val &= 0xC7; writeRegister(XPOWERS_AXP192_IPS_SET, val | (opt << 3)); } /** * @brief Get VBUS Voltage Input Limit. * @retval View the related chip type xpowers_axp192_vbus_vol_limit_t enumeration * parameters in "XPowersParams.hpp" */ uint8_t getVbusVoltageLimit(void) { return (readRegister(XPOWERS_AXP192_IPS_SET) >> 3 ) & 0x7; } /** * @brief Set VBUS Current Input Limit. * @param opt: View the related chip type xpowers_axp192_vbus_cur_limit_t enumeration * parameters in "XPowersParams.hpp" * @retval true valid false invalid */ bool setVbusCurrentLimit(uint8_t opt) { switch (opt) { case XPOWERS_AXP192_VBUS_CUR_LIM_500MA: setRegisterBit(XPOWERS_AXP192_IPS_SET, 1); return clrRegisterBit(XPOWERS_AXP192_IPS_SET, 0); case XPOWERS_AXP192_VBUS_CUR_LIM_100MA: setRegisterBit(XPOWERS_AXP192_IPS_SET, 1); return setRegisterBit(XPOWERS_AXP192_IPS_SET, 0); case XPOWERS_AXP192_VBUS_CUR_LIM_OFF: return clrRegisterBit(XPOWERS_AXP192_IPS_SET, 1); default: break; } return false; } /** * @brief Get VBUS Current Input Limit. * @retval View the related chip type xpowers_axp192_vbus_cur_limit_t enumeration * parameters in "XPowersParams.hpp" */ uint8_t getVbusCurrentLimit(void) { if (getRegisterBit(XPOWERS_AXP192_IPS_SET, 1) == 0) { return XPOWERS_AXP192_VBUS_CUR_LIM_OFF; } if (getRegisterBit(XPOWERS_AXP192_IPS_SET, 0)) { return XPOWERS_AXP192_VBUS_CUR_LIM_100MA; } return XPOWERS_AXP192_VBUS_CUR_LIM_500MA; } // Set the minimum system operating voltage inside the PMU, // below this value will shut down the PMU,Adjustment range 2600mV ~ 3300mV bool setSysPowerDownVoltage(uint16_t millivolt) { if (millivolt % XPOWERS_AXP192_SYS_VOL_STEPS) { log_e("Mistake ! The steps is must %u mV", XPOWERS_AXP192_SYS_VOL_STEPS); return false; } if (millivolt < XPOWERS_AXP192_VOFF_VOL_MIN) { log_e("Mistake ! SYS minimum output voltage is %umV", XPOWERS_AXP192_VOFF_VOL_MIN); return false; } else if (millivolt > XPOWERS_AXP192_VOFF_VOL_MAX) { log_e("Mistake ! SYS maximum output voltage is %umV", XPOWERS_AXP192_VOFF_VOL_MAX); return false; } int val = readRegister(XPOWERS_AXP192_VOFF_SET); if (val == -1)return false; val &= 0xF8; val |= (millivolt - XPOWERS_AXP192_VOFF_VOL_MIN) / XPOWERS_AXP192_SYS_VOL_STEPS; return 0 == writeRegister(XPOWERS_AXP192_VOFF_SET, val); } uint16_t getSysPowerDownVoltage() { int val = readRegister(XPOWERS_AXP192_VOFF_SET); if (val == -1)return 0; val &= 0x07; return (val * XPOWERS_AXP192_SYS_VOL_STEPS) + XPOWERS_AXP192_VOFF_VOL_MIN; } /** * @brief Set shutdown, calling shutdown will turn off all power channels, * only VRTC belongs to normal power supply * @retval None */ void shutdown() { setRegisterBit(XPOWERS_AXP192_OFF_CTL, 7); } /* * Charge setting */ void enableCharge() { setRegisterBit(XPOWERS_AXP192_CHARGE1, 7); } void disableCharge() { clrRegisterBit(XPOWERS_AXP192_CHARGE1, 7); } /** * @brief Set charge target voltage. * @param opt: See xpowers_axp192_chg_vol_t enum for details. * @retval */ bool setChargeTargetVoltage(uint8_t opt) { if (opt >= XPOWERS_AXP192_CHG_VOL_MAX)return false; int val = readRegister(XPOWERS_AXP192_CHARGE1); if (val == -1) return false; val &= 0x9F; return 0 == writeRegister(XPOWERS_AXP192_CHARGE1, val | (opt << 5)); } /** * @brief Get charge target voltage settings. * @retval See xpowers_axp192_chg_vol_t enum for details. */ uint8_t getChargeTargetVoltage() { int val = readRegister(XPOWERS_AXP192_CHARGE1); if (val == -1) return 0; return (val & 0x60) >> 5; } /** * @brief Set charge current settings. * @retval See xpowers_axp192_chg_curr_t enum for details. */ bool setChargerConstantCurr(uint8_t opt) { if (opt > 0x0F)return false; int val = readRegister(XPOWERS_AXP192_CHARGE1); if (val == -1) { return false; } val &= 0xF0; return 0 == writeRegister(XPOWERS_AXP192_CHARGE1, val | opt); } /** * @brief Get charge current settings. * @retval See xpowers_axp192_chg_curr_t enum for details. */ uint8_t getChargerConstantCurr(void) { int val = readRegister(XPOWERS_AXP192_CHARGE1) & 0x0F; if (val == -1)return XPOWERS_AXP192_CHG_CUR_780MA; return val; } void setChargerTerminationCurr(xpowers_axp192_chg_iterm_t opt) { switch (opt) { case XPOWERS_AXP192_CHG_ITERM_LESS_10_PERCENT: clrRegisterBit(XPOWERS_AXP192_CHARGE1, 0); break; case XPOWERS_AXP192_CHG_ITERM_LESS_15_PERCENT: setRegisterBit(XPOWERS_AXP192_CHARGE1, 0); break; default: break; } } uint8_t getChargerTerminationCurr() { return getRegisterBit(XPOWERS_AXP192_CHARGE1, 4); } bool setPrechargeTimeout(xpoers_axp192_prechg_to_t opt) { int val = readRegister(XPOWERS_AXP192_CHARGE2); if (val == -1)return false; val &= 0x3F; return 0 == writeRegister(XPOWERS_AXP192_CHARGE2, val | (opt << 6)); } // External channel charge current setting,Range:300~1000mA bool setChargerExternChannelCurr(uint16_t milliampere) { if (milliampere % XPOWERS_AXP192_CHG_EXT_CURR_STEP) { log_e("Mistake ! The steps is must %u mV", XPOWERS_AXP192_CHG_EXT_CURR_STEP); return false; } if (milliampere < XPOWERS_AXP192_CHG_EXT_CURR_MIN) { log_e("Mistake ! The minimum external path charge current setting is: %umA", XPOWERS_AXP192_CHG_EXT_CURR_MIN); return false; } else if (milliampere > XPOWERS_AXP192_CHG_EXT_CURR_MAX) { log_e("Mistake ! The maximum external channel charge current setting is: %umA", XPOWERS_AXP192_CHG_EXT_CURR_MAX); return false; } int val = readRegister(XPOWERS_AXP192_CHARGE2); if (val == -1)return false; val &= 0xC7; val |= ((milliampere - XPOWERS_AXP192_CHG_EXT_CURR_MIN ) / XPOWERS_AXP192_CHG_EXT_CURR_STEP); return 0 == writeRegister(XPOWERS_AXP192_CHARGE2, val); } bool enableChargerExternChannel() { return setRegisterBit(XPOWERS_AXP192_CHARGE2, 2); } bool disableChargerExternChannel() { return clrRegisterBit(XPOWERS_AXP192_CHARGE2, 2); } // Timeout setting in constant current mode bool setChargerConstantTimeout(xpowers_axp192_chg_cons_to_t opt) { int val = readRegister(XPOWERS_AXP192_CHARGE2); if (val == -1)return false; val &= 0xFC; return 0 == writeRegister(XPOWERS_AXP192_CHARGE2, val | opt); } bool enableBackupBattCharger() { return setRegisterBit(XPOWERS_AXP192_BACKUP_CHG, 7); } bool disableBackupBattCharger() { return clrRegisterBit(XPOWERS_AXP192_BACKUP_CHG, 7); } bool isEnableBackupCharger() { return getRegisterBit(XPOWERS_AXP192_BACKUP_CHG, 7); } bool setBackupBattChargerVoltage(xpowers_axp192_backup_batt_vol_t opt) { int val = readRegister(XPOWERS_AXP192_BACKUP_CHG); if (val == -1)return false; val &= 0x9F; return 0 == writeRegister(XPOWERS_AXP192_BACKUP_CHG, val | (opt << 5)); } bool setBackupBattChargerCurr(xpowers_axp192_backup_batt_curr_t opt) { int val = readRegister(XPOWERS_AXP192_BACKUP_CHG); if (val == -1)return false; val &= 0xFC; return 0 == writeRegister(XPOWERS_AXP192_BACKUP_CHG, val | opt); } /* * Temperature 12-bit ADC */ float getTemperature(uint16_t * raw_ptr = nullptr) { uint16_t raw = readRegisterH8L4(XPOWERS_AXP192_INTERNAL_TEMP_H8, XPOWERS_AXP192_INTERNAL_TEMP_L4); if (raw == UINT16_MAX || raw > 4095) return NAN; if (raw_ptr) *raw_ptr = raw; return raw * XPOWERS_AXP192_INTERNAL_TEMP_STEP - XPOWERS_AXP192_INTERNAL_TEMP_OFFSET; } bool enableTemperatureMeasure() { return setRegisterBit(XPOWERS_AXP192_ADC_EN2, 7); } bool disableTemperatureMeasure() { return clrRegisterBit(XPOWERS_AXP192_ADC_EN2, 7); } /* * Power control LDOio functions */ bool isEnableLDOio(void) { int val = readRegister(XPOWERS_AXP192_GPIO0_CTL); return (val & 0x02); } bool enableLDOio(void) { int val = readRegister(XPOWERS_AXP192_GPIO0_CTL) & 0xF8; return 0 == writeRegister(XPOWERS_AXP192_GPIO0_CTL, val | 0x02); } bool disableLDOio(void) { int val = readRegister(XPOWERS_AXP192_GPIO0_CTL) & 0xF8; return 0 == writeRegister(XPOWERS_AXP192_GPIO0_CTL, val); } bool setLDOioVoltage(uint16_t millivolt) { if (millivolt % XPOWERS_AXP192_LDOIO_VOL_STEPS) { log_e("Mistake ! The steps is must %u mV", XPOWERS_AXP192_LDOIO_VOL_STEPS); return false; } if (millivolt < XPOWERS_AXP192_LDOIO_VOL_MIN) { log_e("Mistake ! LDOIO minimum output voltage is %umV", XPOWERS_AXP192_LDOIO_VOL_MIN); return false; } else if (millivolt > XPOWERS_AXP192_LDOIO_VOL_MAX) { log_e("Mistake ! LDOIO maximum output voltage is %umV", XPOWERS_AXP192_LDOIO_VOL_MAX); return false; } int val = readRegister(XPOWERS_AXP192_GPIO0_VOL); if (val == -1)return false; val |= (((millivolt - XPOWERS_AXP192_LDOIO_VOL_MIN) / XPOWERS_AXP192_LDOIO_VOL_STEPS) << 4); return 0 == writeRegister(XPOWERS_AXP192_GPIO0_VOL, val); } uint16_t getLDOioVoltage(void) { int val = readRegister(XPOWERS_AXP192_GPIO0_VOL); if (val == -1)return 0; val >>= 4; val *= XPOWERS_AXP192_LDOIO_VOL_STEPS; val += XPOWERS_AXP192_LDOIO_VOL_MIN; return val; } /* * Power control LDO2 functions */ bool isEnableLDO2(void) { return getRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 2); } bool enableLDO2(void) { return setRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 2); } bool disableLDO2(void) { return clrRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 2); } bool setLDO2Voltage(uint16_t millivolt) { if (millivolt % XPOWERS_AXP192_LDO2_VOL_STEPS) { log_e("Mistake ! The steps is must %u mV", XPOWERS_AXP192_LDO2_VOL_STEPS); return false; } if (millivolt < XPOWERS_AXP192_LDO2_VOL_MIN) { log_e("Mistake ! LDO2 minimum output voltage is %umV", XPOWERS_AXP192_LDO2_VOL_MIN); return false; } else if (millivolt > XPOWERS_AXP192_LDO2_VOL_MAX) { log_e("Mistake ! LDO2 maximum output voltage is %umV", XPOWERS_AXP192_LDO2_VOL_MAX); return false; } int val = readRegister(XPOWERS_AXP192_LDO23OUT_VOL); if (val == -1) return false; val &= 0x0F; return 0 == writeRegister(XPOWERS_AXP192_LDO23OUT_VOL, val | (((millivolt - XPOWERS_AXP192_LDO2_VOL_MIN) / XPOWERS_AXP192_LDO2_VOL_STEPS) << XPOWERS_AXP192_LDO2_VOL_BIT_MASK)); } uint16_t getLDO2Voltage(void) { int val = readRegister(XPOWERS_AXP192_LDO23OUT_VOL) & 0xF0; return (val >> XPOWERS_AXP192_LDO2_VOL_BIT_MASK) * XPOWERS_AXP192_LDO2_VOL_STEPS + XPOWERS_AXP192_LDO2_VOL_MIN; } /* * Power control LDO3 functions */ bool isEnableLDO3(void) { return getRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 3); } bool enableLDO3(void) { return setRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 3); } bool disableLDO3(void) { return clrRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 3); } bool setLDO3Voltage(uint16_t millivolt) { if (millivolt % XPOWERS_AXP192_LDO3_VOL_STEPS) { log_e("Mistake ! The steps is must %u mV", XPOWERS_AXP192_LDO3_VOL_STEPS); return false; } if (millivolt < XPOWERS_AXP192_LDO3_VOL_MIN) { log_e("Mistake ! LDO3 minimum output voltage is %umV", XPOWERS_AXP192_LDO3_VOL_MIN); return false; } else if (millivolt > XPOWERS_AXP192_LDO3_VOL_MAX) { log_e("Mistake ! LDO3 maximum output voltage is %umV", XPOWERS_AXP192_LDO3_VOL_MAX); return false; } int val = readRegister(XPOWERS_AXP192_LDO23OUT_VOL) & 0xF0; return 0 == writeRegister(XPOWERS_AXP192_LDO23OUT_VOL, val | ((millivolt - XPOWERS_AXP192_LDO3_VOL_MIN) / XPOWERS_AXP192_LDO3_VOL_STEPS)); } uint16_t getLDO3Voltage(void) { int val = readRegister(XPOWERS_AXP192_LDO23OUT_VOL); if (val == -1)return 0; val &= 0x0F; return (val * XPOWERS_AXP192_LDO3_VOL_STEPS) + XPOWERS_AXP192_LDO3_VOL_MIN; } /* * Power control DCDC1 functions */ void setDC1PwmMode(void) { int val = readRegister(XPOWERS_AXP192_DCDC_MODESET) & 0xF7; writeRegister(XPOWERS_AXP192_DCDC_MODESET, val | 0x08); } void setDC1AutoMode(void) { int val = readRegister(XPOWERS_AXP192_DCDC_MODESET) & 0xF7; writeRegister(XPOWERS_AXP192_DCDC_MODESET, val); } bool isEnableDC1(void) { return getRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 0); } bool enableDC1(void) { return setRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 0); } bool disableDC1(void) { return clrRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 0); } bool setDC1Voltage(uint16_t millivolt) { if (millivolt % XPOWERS_AXP192_DC1_VOL_STEPS) { log_e("Mistake ! The steps is must %u mV", XPOWERS_AXP192_DC1_VOL_STEPS); return false; } if (millivolt < XPOWERS_AXP192_DC1_VOL_STEPS) { log_e("Mistake ! DCDC1 minimum output voltage is %umV", XPOWERS_AXP192_DC1_VOL_STEPS); return false; } else if (millivolt > XPOWERS_AXP192_DC1_VOL_MAX) { log_e("Mistake ! DCDC1 maximum output voltage is %umV", XPOWERS_AXP192_DC1_VOL_MAX); return false; } int val = readRegister(XPOWERS_AXP192_DC1_VLOTAGE); if (val == -1)return false; val &= 0x80; val |= (millivolt - XPOWERS_AXP192_DC1_VOL_MIN) / XPOWERS_AXP192_DC1_VOL_STEPS; return 0 == writeRegister(XPOWERS_AXP192_DC1_VLOTAGE, val); } uint16_t getDC1Voltage(void) { int val = readRegister(XPOWERS_AXP192_DC1_VLOTAGE) & 0x7F; return val * XPOWERS_AXP192_DC1_VOL_STEPS + XPOWERS_AXP192_DC1_VOL_MIN; } /* * Power control DCDC2 functions */ void setDC2PwmMode(void) { int val = readRegister(XPOWERS_AXP192_DCDC_MODESET) & 0xFB; writeRegister(XPOWERS_AXP192_DCDC_MODESET, val | 0x04); } void setDC2AutoMode(void) { int val = readRegister(XPOWERS_AXP192_DCDC_MODESET) & 0xFB; writeRegister(XPOWERS_AXP192_DCDC_MODESET, val); } void enableDC2VRC(void) { int val = readRegister(XPOWERS_AXP192_DC2_DVM); writeRegister(XPOWERS_AXP192_DC2_DVM, val | 0x04); } void disableDC2VRC(void) { int val = readRegister(XPOWERS_AXP192_DC2_DVM); writeRegister(XPOWERS_AXP192_DC2_DVM, val & 0xFB); } bool setDC2VRC(uint8_t opts) { if (opts > 1) { return false; } int val = readRegister(XPOWERS_AXP192_DC2_DVM) & 0xFE; writeRegister(XPOWERS_AXP192_DC2_DVM, val | opts); } bool isEnableDC2VRC(void) { return (readRegister(XPOWERS_AXP192_DC2_DVM) & 0x04) == 0x04; } bool isEnableDC2(void) { return getRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 4); } bool enableDC2(void) { return setRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 4); } bool disableDC2(void) { return clrRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 4); } bool setDC2Voltage(uint16_t millivolt) { if (millivolt % XPOWERS_AXP192_DC2_VOL_STEPS) { log_e("Mistake ! The steps is must %u mV", XPOWERS_AXP192_DC2_VOL_STEPS); return false; } if (millivolt < XPOWERS_AXP192_DC2_VOL_MIN) { log_e("Mistake ! DCDC2 minimum output voltage is %umV", XPOWERS_AXP192_DC2_VOL_MIN); return false; } else if (millivolt > XPOWERS_AXP192_DC2_VOL_MAX) { log_e("Mistake ! DCDC2 maximum output voltage is %umV", XPOWERS_AXP192_DC2_VOL_MAX); return false; } int val = readRegister(XPOWERS_AXP192_DC2OUT_VOL); if (val == -1)return false; val &= 0x80; val |= (millivolt - XPOWERS_AXP192_DC2_VOL_MIN) / XPOWERS_AXP192_DC2_VOL_STEPS; return 0 == writeRegister(XPOWERS_AXP192_DC2OUT_VOL, val); } uint16_t getDC2Voltage(void) { int val = readRegister(XPOWERS_AXP192_DC2OUT_VOL); if (val == -1)return 0; return (val * XPOWERS_AXP192_DC2_VOL_STEPS) + XPOWERS_AXP192_DC2_VOL_MIN; } /* * Power control DCDC3 functions */ void setDC3PwmMode(void) { int val = readRegister(XPOWERS_AXP192_DCDC_MODESET) & 0xFD; writeRegister(XPOWERS_AXP192_DCDC_MODESET, val | 0x02); } void setDC3AutoMode(void) { int val = readRegister(XPOWERS_AXP192_DCDC_MODESET) & 0xFD; writeRegister(XPOWERS_AXP192_DCDC_MODESET, val); } bool isEnableDC3(void) { return getRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 1); } bool enableDC3(void) { return setRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 1); } bool disableDC3(void) { return clrRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 1); } bool setDC3Voltage(uint16_t millivolt) { if (millivolt % XPOWERS_AXP192_DC3_VOL_STEPS) { log_e("Mistake ! The steps is must %u mV", XPOWERS_AXP192_DC3_VOL_STEPS); return false; } if (millivolt < XPOWERS_AXP192_DC3_VOL_MIN) { log_e("Mistake ! DCDC3 minimum output voltage is %umV", XPOWERS_AXP192_DC3_VOL_MIN); return false; } else if (millivolt > XPOWERS_AXP192_DC3_VOL_MAX) { log_e("Mistake ! DCDC3 maximum output voltage is %umV", XPOWERS_AXP192_DC3_VOL_MAX); return false; } return 0 == writeRegister(XPOWERS_AXP192_DC3OUT_VOL, (millivolt - XPOWERS_AXP192_DC3_VOL_MIN) / XPOWERS_AXP192_DC3_VOL_STEPS); } uint16_t getDC3Voltage(void) { int val = readRegister(XPOWERS_AXP192_DC3OUT_VOL); if (val == -1)return 0; return (val * XPOWERS_AXP192_DC3_VOL_STEPS) + XPOWERS_AXP192_DC3_VOL_MIN; } /* * Power control EXTEN functions */ bool enableExternalPin(void) { return setRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 6); } bool disableExternalPin(void) { return clrRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 6); } bool isEnableExternalPin(void) { return getRegisterBit(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, 6); } /* * Interrupt status functions */ /** * @brief Get the interrupt controller mask value. * @retval Mask value corresponds to xpowers_axp192_irq_t , */ uint64_t getIrqStatus(void) { statusRegister[0] = readRegister(XPOWERS_AXP192_INTSTS1); statusRegister[1] = readRegister(XPOWERS_AXP192_INTSTS2); statusRegister[2] = readRegister(XPOWERS_AXP192_INTSTS3); statusRegister[3] = readRegister(XPOWERS_AXP192_INTSTS4); statusRegister[4] = readRegister(XPOWERS_AXP192_INTSTS5); return ((uint64_t)statusRegister[4]) << 32 | ((uint64_t)statusRegister[3]) << 24 | ((uint64_t)statusRegister[2]) << 16 | ((uint64_t)statusRegister[1]) << 8 | ((uint64_t)statusRegister[0]); } /** * @brief Clear interrupt controller state. */ void clearIrqStatus(void) { for (int i = 0; i < 4; i++) { writeRegister(XPOWERS_AXP192_INTSTS1 + i, 0xFF); } writeRegister(XPOWERS_AXP192_INTSTS5, 0xFF); } /** * @brief Enable PMU interrupt control mask . * @param opt: View the related chip type xpowers_axp192_irq_t enumeration * parameters in "XPowersParams.hpp" * @retval */ bool enableIRQ(uint64_t opt) { return setInterruptImpl(opt, true); } /** * @brief Disable PMU interrupt control mask . * @param opt: View the related chip type xpowers_axp192_irq_t enumeration * parameters in "XPowersParams.hpp" * @retval */ bool disableIRQ(uint64_t opt) { return setInterruptImpl(opt, false); } bool isAcinOverVoltageIrq(void) { return (bool)(statusRegister[0] & _BV(7)); } bool isAcinInserIrq(void) { return (bool)(statusRegister[0] & _BV(6)); } bool isAcinRemoveIrq(void) { return (bool)(statusRegister[0] & _BV(5)); } bool isVbusOverVoltageIrq(void) { return (bool)(statusRegister[0] & _BV(4)); } bool isVbusInsertIrq(void) { return (bool)(statusRegister[0] & _BV(3)); } bool isVbusRemoveIrq(void) { return (bool)(statusRegister[0] & _BV(2)); } bool isVbusLowVholdIrq(void) { return (bool)(statusRegister[0] & _BV(1)); } bool isBatInsertIrq(void) { return (bool)(statusRegister[1] & _BV(7)); } bool isBatRemoveIrq(void) { return (bool)(statusRegister[1] & _BV(6)); } bool isBattEnterActivateIrq(void) { return (bool)(statusRegister[1] & _BV(5)); } bool isBattExitActivateIrq(void) { return (bool)(statusRegister[1] & _BV(4)); } bool isBatChargeStartIrq(void) { return (bool)(statusRegister[1] & _BV(3)); } bool isBatChargeDoneIrq(void) { return (bool)(statusRegister[1] & _BV(2)); } bool isBattTempHighIrq(void) { return (bool)(statusRegister[1] & _BV(1)); } bool isBattTempLowIrq(void) { return (bool)(statusRegister[1] & _BV(0)); } bool isChipOverTemperatureIrq(void) { return (bool)(statusRegister[2] & _BV(7)); } bool isChargingCurrentLessIrq(void) { return (bool)(statusRegister[2] & _BV(6)); } bool isDC1VoltageLessIrq(void) { return (bool)(statusRegister[2] & _BV(5)); } bool isDC2VoltageLessIrq(void) { return (bool)(statusRegister[2] & _BV(4)); } bool isDC3VoltageLessIrq(void) { return (bool)(statusRegister[2] & _BV(3)); } bool isPekeyShortPressIrq(void) { return (bool)(statusRegister[2] & _BV(1)); } bool isPekeyLongPressIrq(void) { return (bool)(statusRegister[2] & _BV(0)); } bool isNOEPowerOnIrq(void) { return (bool)(statusRegister[3] & _BV(7)); } bool isNOEPowerDownIrq(void) { return (bool)(statusRegister[3] & _BV(6)); } bool isVbusEffectiveIrq(void) { return (bool)(statusRegister[3] & _BV(5)); } bool isVbusInvalidIrq(void) { return (bool)(statusRegister[3] & _BV(4)); } bool isVbusSessionIrq(void) { return (bool)(statusRegister[3] & _BV(3)); } bool isVbusSessionEndIrq(void) { return (bool)(statusRegister[3] & _BV(2)); } bool isLowVoltageLevel2Irq(void) { return (bool)(statusRegister[3] & _BV(0)); } //IRQ5 REGISTER : bool isWdtExpireIrq(void) { return (bool)(statusRegister[4] & _BV(7)); } bool isGpio2EdgeTriggerIrq(void) { return (bool)(statusRegister[4] & _BV(2)); } bool isGpio1EdgeTriggerIrq(void) { return (bool)(statusRegister[4] & _BV(1)); } bool isGpio0EdgeTriggerIrq(void) { return (bool)(statusRegister[4] & _BV(0)); } /* * ADC Functions */ bool enableBattDetection() { return setRegisterBit(XPOWERS_AXP192_OFF_CTL, 6); } bool disableBattDetection() { return clrRegisterBit(XPOWERS_AXP192_OFF_CTL, 6); } bool enableVbusVoltageMeasure() { return setSignalCaptureImpl(MONITOR_USB_CURRENT | MONITOR_USB_VOLTAGE, true); } bool disableVbusVoltageMeasure() { return setSignalCaptureImpl(MONITOR_USB_CURRENT | MONITOR_USB_VOLTAGE, false); } bool enableBattVoltageMeasure() { return setSignalCaptureImpl(MONITOR_BAT_CURRENT | MONITOR_BAT_VOLTAGE, true); } bool disableBattVoltageMeasure() { return setSignalCaptureImpl(MONITOR_BAT_CURRENT | MONITOR_BAT_VOLTAGE, false); } bool enableSystemVoltageMeasure() { return setSignalCaptureImpl(MONITOR_APS_VOLTAGE, true); } bool disableSystemVoltageMeasure() { return setSignalCaptureImpl(MONITOR_APS_VOLTAGE, false); } bool enableTSPinMeasure() { return setSignalCaptureImpl(MONITOR_TS_PIN, true); } bool disableTSPinMeasure() { return setSignalCaptureImpl(MONITOR_TS_PIN, false); } bool enableAdcChannel(uint32_t opts) { return setSignalCaptureImpl(opts, true); } bool disableAdcChannel(uint32_t opts) { return setSignalCaptureImpl(opts, false); } uint16_t getVbusVoltage() { if (!isVbusIn()) { return 0; } return readRegisterH8L4(XPOWERS_AXP192_VBUS_VOL_H8, XPOWERS_AXP192_VBUS_VOL_L4 ) * XPOWERS_AXP192_VBUS_VOLTAGE_STEP; } float getVbusCurrent() { if (!isVbusIn()) { return 0; } return readRegisterH8L4(XPOWERS_AXP192_VBUS_CUR_H8, XPOWERS_AXP192_VBUS_CUR_L4 ) * XPOWERS_AXP192_VBUS_CUR_STEP; } uint16_t getBattVoltage() { if (!isBatteryConnect()) { return 0; } return readRegisterH8L4(XPOWERS_AXP192_BAT_AVERVOL_H8, XPOWERS_AXP192_BAT_AVERVOL_L4 ) * XPOWERS_AXP192_BATT_VOLTAGE_STEP; } float getBattDischargeCurrent() { if (!isBatteryConnect()) { return 0; } return readRegisterH8L5(XPOWERS_AXP192_BAT_AVERDISCHGCUR_H8, XPOWERS_AXP192_BAT_AVERDISCHGCUR_L5) * XPOWERS_AXP192_BATT_DISCHARGE_CUR_STEP; } uint16_t getAcinVoltage() { if (!isAcinIn()) { return 0; } return readRegisterH8L4(XPOWERS_AXP192_ACIN_VOL_H8, XPOWERS_AXP192_ACIN_VOL_L4) * XPOWERS_AXP192_ACIN_VOLTAGE_STEP; } float getAcinCurrent() { if (!isAcinIn()) { return 0; } return readRegisterH8L4(XPOWERS_AXP192_ACIN_CUR_H8, XPOWERS_AXP192_ACIN_CUR_L4) * XPOWERS_AXP192_ACIN_CUR_STEP; } uint16_t getSystemVoltage() { return readRegisterH8L4(XPOWERS_AXP192_APS_AVERVOL_H8, XPOWERS_AXP192_APS_AVERVOL_L4) * XPOWERS_AXP192_APS_VOLTAGE_STEP; } /* * Timer Control */ void setTimerout(uint8_t minute) { writeRegister(XPOWERS_AXP192_TIMER_CTL, 0x80 | minute); } void disableTimer() { writeRegister(XPOWERS_AXP192_TIMER_CTL, 0x80); } void clearTimerFlag() { setRegisterBit(XPOWERS_AXP192_TIMER_CTL, 7); } /* * Data Buffer */ bool writeDataBuffer(uint8_t *data, uint8_t size) { if (size > XPOWERS_AXP192_DATA_BUFFER_SIZE)return false; for (int i = 0; i < size; ++i) { writeRegister(XPOWERS_AXP192_DATA_BUFFER1 + i, data[i]); } return true; } bool readDataBuffer(uint8_t *data, uint8_t size) { if (size > XPOWERS_AXP192_DATA_BUFFER_SIZE)return false; for (int i = 0; i < size; ++i) { data[i] = readRegister(XPOWERS_AXP192_DATA_BUFFER1 + i); } return true; } /* * Charge led functions */ /** * @brief Set charging led mode. * @retval See xpowers_chg_led_mode_t enum for details. */ void setChargingLedMode(uint8_t mode) { int val; switch (mode) { case XPOWERS_CHG_LED_OFF: case XPOWERS_CHG_LED_BLINK_1HZ: case XPOWERS_CHG_LED_BLINK_4HZ: case XPOWERS_CHG_LED_ON: val = readRegister(XPOWERS_AXP192_OFF_CTL); if (val == -1)return; val &= 0xC7; val |= 0x08; //use manual ctrl val |= (mode << 4); writeRegister(XPOWERS_AXP192_OFF_CTL, val); break; case XPOWERS_CHG_LED_CTRL_CHG: clrRegisterBit(XPOWERS_AXP192_OFF_CTL, 3); break; default: break; } } uint8_t getChargingLedMode() { if (!getRegisterBit(XPOWERS_AXP192_OFF_CTL, 3)) { return XPOWERS_CHG_LED_CTRL_CHG; } int val = readRegister(XPOWERS_AXP192_OFF_CTL); if (val == -1)return XPOWERS_CHG_LED_OFF; val &= 0x30; return val >> 4; } /* * Coulomb counter control */ void enableCoulomb() { setRegisterBit(XPOWERS_AXP192_COULOMB_CTL, 7); } void disableCoulomb() { clrRegisterBit(XPOWERS_AXP192_COULOMB_CTL, 7); } void stopCoulomb() { setRegisterBit(XPOWERS_AXP192_COULOMB_CTL, 6); } void clearCoulomb() { setRegisterBit(XPOWERS_AXP192_COULOMB_CTL, 5); } uint32_t getBattChargeCoulomb() { int data[4]; data[0] = readRegister(XPOWERS_AXP192_BAT_CHGCOULOMB3); data[1] = readRegister(XPOWERS_AXP192_BAT_CHGCOULOMB2); data[2] = readRegister(XPOWERS_AXP192_BAT_CHGCOULOMB1); data[3] = readRegister(XPOWERS_AXP192_BAT_CHGCOULOMB0); for (int i = 0; i < 4; ++i) { if (data[i] == -1)return 0; } return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) | ((uint32_t)data[2] << 8) | (uint32_t)data[3]; } uint32_t getBattDischargeCoulomb() { int data[4]; data[0] = readRegister(XPOWERS_AXP192_BAT_DISCHGCOULOMB3); data[1] = readRegister(XPOWERS_AXP192_BAT_DISCHGCOULOMB2); data[2] = readRegister(XPOWERS_AXP192_BAT_DISCHGCOULOMB1); data[3] = readRegister(XPOWERS_AXP192_BAT_DISCHGCOULOMB0); for (int i = 0; i < 4; ++i) { if (data[i] == -1)return 0; } return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) | ((uint32_t)data[2] << 8) | (uint32_t)data[3]; } uint8_t getAdcSamplingRate(void) { int val = readRegister(XPOWERS_AXP192_ADC_SPEED); if (val == -1)return 0; return 25 * (int)pow(2, (val & 0xC0) >> 6); } float getCoulombData(void) { uint32_t charge = getBattChargeCoulomb(), discharge = getBattDischargeCoulomb(); uint8_t rate = getAdcSamplingRate(); float result = 65536.0 * 0.5 * ((float)charge - (float)discharge) / 3600.0 / rate; return result; } /* * GPIO control functions */ float getBatteryChargeCurrent(void) { return readRegisterH8L5( XPOWERS_AXP192_BAT_AVERCHGCUR_H8, XPOWERS_AXP192_BAT_AVERCHGCUR_L5 ) * XPOWERS_AXP192_BATT_CHARGE_CUR_STEP; } uint16_t getGpio0Voltage() { return readRegisterH8L4(XPOWERS_AXP192_GPIO0_VOL_ADC_H8, XPOWERS_AXP192_GPIO0_VOL_ADC_L4) * XPOWERS_AXP192_GPIO0_STEP * 1000; } uint16_t getGpio1Voltage() { return readRegisterH8L4(XPOWERS_AXP192_GPIO1_VOL_ADC_H8, XPOWERS_AXP192_GPIO1_VOL_ADC_L4) * XPOWERS_AXP192_GPIO1_STEP * 1000; } int8_t pwmSetup(uint8_t channel, uint8_t freq, uint16_t duty) { // PWM输出频率 = 2.25MHz / (X+1) / Y1 // PWM输出占空比 = Y2 / Y1 switch (channel) { case 0: writeRegister(XPOWERS_AXP192_PWM1_FREQ_SET, freq); writeRegister(XPOWERS_AXP192_PWM1_DUTY_SET1, duty >> 8); writeRegister(XPOWERS_AXP192_PWM1_DUTY_SET2, duty & 0xFF); break; case 1: writeRegister(XPOWERS_AXP192_PWM2_FREQ_SET, freq); writeRegister(XPOWERS_AXP192_PWM2_DUTY_SET1, duty >> 8); writeRegister(XPOWERS_AXP192_PWM2_DUTY_SET2, duty & 0xFF); break; default: return -1; break; } return 0; } int8_t pwmEnable(uint8_t channel) { int val = 0; switch (channel) { case 0: val = readRegister(XPOWERS_AXP192_GPIO1_CTL) & 0xF8; writeRegister(XPOWERS_AXP192_GPIO1_CTL, val | 0x02); return 0; case 1: val = readRegister(XPOWERS_AXP192_GPIO2_CTL) & 0xF8; writeRegister(XPOWERS_AXP192_GPIO2_CTL, val | 0x02); return 0; default: break; } return -1; } int getBatteryPercent(void) { if (!isBatteryConnect()) { return -1; } const static int table[11] = { 3000, 3650, 3700, 3740, 3760, 3795, 3840, 3910, 3980, 4070, 4150 }; uint16_t voltage = getBattVoltage(); if (voltage < table[0]) return 0; for (int i = 0; i < 11; i++) { if (voltage < table[i]) return i * 10 - (10UL * (int)(table[i] - voltage)) / (int)(table[i] - table[i - 1]);; } return 100; } uint8_t getChipID(void) { return readRegister(XPOWERS_AXP192_IC_TYPE); } /* * GPIO setting */ int8_t pinMode(uint8_t pin, uint8_t mode) { int val = 0; switch (pin) { case PMU_GPIO0: /* * 000: NMOS open-drain output * 001: Universal input function * 010: Low noise LDO * 011: reserved * 100: ADC input * 101: Low output * 11X: Floating * * */ if (mode == INPUT || mode == INPUT_PULLDOWN) { if (gpio[pin].mode != INPUT) { gpio[pin].mode = INPUT; } val = readRegister(XPOWERS_AXP192_GPIO0_CTL) & 0xF8; writeRegister(XPOWERS_AXP192_GPIO0_CTL, val | 0x01); //Set pull-down mode val = readRegister(XPOWERS_AXP192_GPIO012_PULLDOWN) & 0xFE; if (mode == INPUT_PULLDOWN ) { writeRegister(XPOWERS_AXP192_GPIO012_PULLDOWN, val | 0x01); } else { writeRegister(XPOWERS_AXP192_GPIO012_PULLDOWN, val); } } break; case PMU_GPIO1: /* * 000: NMOS open-drain output * 001: Universal input function * 010: PWM1 output, high level is VINT, not Can add less than 100K pull-down resistance * 011: reserved * 100: ADC input * 101: Low output * 11X: Floating * * */ if (mode == INPUT || mode == INPUT_PULLDOWN) { if (gpio[pin].mode != INPUT) { gpio[pin].mode = INPUT; } val = readRegister(XPOWERS_AXP192_GPIO1_CTL) & 0xF8; writeRegister(XPOWERS_AXP192_GPIO1_CTL, val | 0x01); //Set pull-down mode val = readRegister(XPOWERS_AXP192_GPIO012_PULLDOWN) & 0xFD; if (mode == INPUT_PULLDOWN ) { writeRegister(XPOWERS_AXP192_GPIO012_PULLDOWN, val | 0x02); } else { writeRegister(XPOWERS_AXP192_GPIO012_PULLDOWN, val); } } break; case PMU_GPIO2: /* * 000: NMOS open-drain output * 001: Universal input function * 010: PWM2 output, high level is VINT, not Can add less than 100K pull-down resistance * 011: reserved * 100: ADC input * 101: Low output * 11X: Floating * */ if (mode == INPUT || mode == INPUT_PULLDOWN) { if (gpio[pin].mode != INPUT) { gpio[pin].mode = INPUT; } val = readRegister(XPOWERS_AXP192_GPIO2_CTL) & 0xF8; writeRegister(XPOWERS_AXP192_GPIO2_CTL, val | 0x01); //Set pull-down mode val = readRegister(XPOWERS_AXP192_GPIO012_PULLDOWN) & 0xFB; if (mode == INPUT_PULLDOWN ) { writeRegister(XPOWERS_AXP192_GPIO012_PULLDOWN, val | 0x04); } else { writeRegister(XPOWERS_AXP192_GPIO012_PULLDOWN, val); } } break; case PMU_GPIO3: /* * 00: External charging control * 01: NMOS open-drain output port 3 * 10: Universal input port 3 * 11: ADC input * * */ if (mode == INPUT) { if (gpio[pin].mode != INPUT) { gpio[pin].mode = INPUT; } val = readRegister(XPOWERS_AXP192_GPIO34_CTL) & 0xFC; writeRegister(XPOWERS_AXP192_GPIO34_CTL, val | 0x82 ); } break; case PMU_GPIO4: /* * 00: External charging control * 01: NMOS open-drain output port 4 * 10: Universal input port 4 * 11: undefined * * */ if (mode == INPUT) { if (gpio[pin].mode != INPUT) { gpio[pin].mode = INPUT; } val = readRegister(XPOWERS_AXP192_GPIO34_CTL) & 0xF3; writeRegister(XPOWERS_AXP192_GPIO34_CTL, val | 0x88 ); } break; case PMU_GPIO5: if (mode == INPUT) { if (gpio[pin].mode != INPUT) { gpio[pin].mode = INPUT; } val = readRegister(XPOWERS_AXP192_GPIO5_CTL) & 0xBF; writeRegister(XPOWERS_AXP192_GPIO5_CTL, val | 0x40); } break; default: break; } return 0; } uint8_t digitalRead(uint8_t pin) { switch (pin) { case PMU_GPIO0: return getRegisterBit(XPOWERS_AXP192_GPIO012_SIGNAL, 4); case PMU_GPIO1: return getRegisterBit(XPOWERS_AXP192_GPIO012_SIGNAL, 5); case PMU_GPIO2: return getRegisterBit(XPOWERS_AXP192_GPIO012_SIGNAL, 6); case PMU_GPIO3: return getRegisterBit(XPOWERS_AXP192_GPIO34_SIGNAL, 4); case PMU_GPIO4: return getRegisterBit(XPOWERS_AXP192_GPIO34_SIGNAL, 5); case PMU_GPIO5: return getRegisterBit(XPOWERS_AXP192_GPIO5_CTL, 4); default: break; } return 0; } void digitalWrite(uint8_t pin, uint8_t val) { int reg = 0; switch (pin) { case PMU_GPIO0: if (gpio[pin].mode != OUTPUT) { gpio[pin].mode = OUTPUT; } reg = readRegister(XPOWERS_AXP192_GPIO0_CTL) & 0xFE; writeRegister(XPOWERS_AXP192_GPIO0_CTL, val ? (reg | 0x01) : reg); break; case PMU_GPIO1: if (gpio[pin].mode != OUTPUT) { gpio[pin].mode = OUTPUT; } reg = readRegister(XPOWERS_AXP192_GPIO1_CTL) & 0xFD; writeRegister(XPOWERS_AXP192_GPIO1_CTL, val ? (reg | 0x01) : reg); break; case PMU_GPIO2: if (gpio[pin].mode != OUTPUT) { gpio[pin].mode = OUTPUT; } reg = readRegister(XPOWERS_AXP192_GPIO2_CTL) & 0xFB; writeRegister(XPOWERS_AXP192_GPIO2_CTL, val ? (reg | 0x01) : reg); break; case PMU_GPIO3: if (gpio[pin].mode != OUTPUT) { gpio[pin].mode = OUTPUT; reg = readRegister(XPOWERS_AXP192_GPIO34_CTL) & 0xFC; writeRegister(XPOWERS_AXP192_GPIO34_CTL, reg | 0x01); } reg = readRegister(XPOWERS_AXP192_GPIO34_SIGNAL) & 0xF7; writeRegister(XPOWERS_AXP192_GPIO34_SIGNAL, val ? (val | 0x08) : reg); break; case PMU_GPIO4: if (gpio[pin].mode != OUTPUT) { gpio[pin].mode = OUTPUT; reg = readRegister(XPOWERS_AXP192_GPIO34_CTL) & 0xF3; writeRegister(XPOWERS_AXP192_GPIO34_CTL, reg | 0x04); } reg = readRegister(XPOWERS_AXP192_GPIO34_SIGNAL) & 0xEF; writeRegister(XPOWERS_AXP192_GPIO34_SIGNAL, val ? (val | 0x10) : reg); break; case PMU_GPIO5: if (gpio[pin].mode != OUTPUT) { gpio[pin].mode = OUTPUT; reg = readRegister(XPOWERS_AXP192_GPIO5_CTL) & 0xBF; writeRegister(XPOWERS_AXP192_GPIO5_CTL, reg); } reg = readRegister(XPOWERS_AXP192_GPIO5_CTL) & 0xDF; writeRegister(XPOWERS_AXP192_GPIO5_CTL, val ? (reg | 0x20) : reg); break; default: break; } } #if 0 // ! Need FIX uint16_t analogRead(uint8_t pin) { switch (pin) { case PMU_GPIO0: if (gpio[pin].mode != ANALOG) { // Enable GPIO ADC Function uint8_t val = readRegister(XPOWERS_AXP192_GPIO0_CTL) & 0xF8; writeRegister(XPOWERS_AXP192_GPIO0_CTL, val | 0x04); //Enable ADC2 / GPIO0 // val = readRegister(XPOWERS_AXP192_ADC_EN2) | 0x08; // writeRegister(XPOWERS_AXP192_ADC_EN2, val ); setRegisterBit(XPOWERS_AXP192_ADC_EN2, 3); // Set adc input range 0~2.0475V val = readRegister(XPOWERS_AXP192_ADC_INPUTRANGE) & 0xFE; writeRegister(XPOWERS_AXP192_ADC_INPUTRANGE, val); gpio[pin].mode = ANALOG; } return readRegisterH8L4(XPOWERS_AXP192_GPIO0_VOL_ADC_H8, XPOWERS_AXP192_GPIO0_VOL_ADC_L4); case PMU_GPIO1: if (gpio[pin].mode != ANALOG) { // Enable GPIO ADC Function uint8_t val = readRegister(XPOWERS_AXP192_GPIO1_CTL) & 0xF8; writeRegister(XPOWERS_AXP192_GPIO1_CTL, val | 0x04); //Enable ADC2 / GPIO1 // val = readRegister(XPOWERS_AXP192_ADC_EN2) | 0x04; // writeRegister(XPOWERS_AXP192_ADC_EN2, val ); setRegisterBit(XPOWERS_AXP192_ADC_EN2, 2); // Set adc input range 0~2.0475V val = readRegister(XPOWERS_AXP192_ADC_INPUTRANGE) & 0xFD; writeRegister(XPOWERS_AXP192_ADC_INPUTRANGE, val); gpio[pin].mode = ANALOG; } return readRegisterH8L4(XPOWERS_AXP192_GPIO1_VOL_ADC_H8, XPOWERS_AXP192_GPIO1_VOL_ADC_L4); case PMU_GPIO2: if (gpio[pin].mode != ANALOG) { // Enable GPIO ADC Function uint8_t val = readRegister(XPOWERS_AXP192_GPIO1_CTL) & 0xF8; writeRegister(XPOWERS_AXP192_GPIO1_CTL, val | 0x04); //Enable ADC2 / GPIO1 // val = readRegister(XPOWERS_AXP192_ADC_EN2) | 0x02; // writeRegister(XPOWERS_AXP192_ADC_EN2, val ); setRegisterBit(XPOWERS_AXP192_ADC_EN2, 1); // Set adc input range 0~2.0475V val = readRegister(XPOWERS_AXP192_ADC_INPUTRANGE) & 0xFB; writeRegister(XPOWERS_AXP192_ADC_INPUTRANGE, val); gpio[pin].mode = ANALOG; } return readRegisterH8L4(XPOWERS_AXP192_GPIO2_VOL_ADC_H8, XPOWERS_AXP192_GPIO2_VOL_ADC_L4); case PMU_GPIO3: if (gpio[pin].mode != ANALOG) { // Enable GPIO ADC Function uint8_t val = readRegister(XPOWERS_AXP192_GPIO1_CTL) & 0xF8; writeRegister(XPOWERS_AXP192_GPIO1_CTL, val | 0x04); //Enable ADC2 / GPIO1 // val = readRegister(XPOWERS_AXP192_ADC_EN2) | 0X01; // writeRegister(XPOWERS_AXP192_ADC_EN2, val ); setRegisterBit(XPOWERS_AXP192_ADC_EN2, 0); // Set adc input range 0~2.0475V val = readRegister(XPOWERS_AXP192_ADC_INPUTRANGE) & 0xF7; writeRegister(XPOWERS_AXP192_ADC_INPUTRANGE, val); gpio[pin].mode = ANALOG; } return readRegisterH8L4(XPOWERS_AXP192_GPIO3_VOL_ADC_H8, XPOWERS_AXP192_GPIO3_VOL_ADC_L4); case PMU_TS_PIN: if (gpio[pin].mode != ANALOG) { // Enable TS PIN ADC Function setRegisterBit(XPOWERS_AXP192_ADC_SPEED, 2); // uint8_t val = readRegister(XPOWERS_AXP192_ADC_SPEED) & 0xFB; // writeRegister(XPOWERS_AXP192_ADC_SPEED, val | 0x04); gpio[pin].mode = ANALOG; } return readRegisterH8L4(XPOWERS_AXP192_TS_IN_H8, XPOWERS_AXP192_TS_IN_L4); break; default: break; } return 0; } #endif /** * Sleep function */ bool enableSleep() { return setRegisterBit(XPOWERS_AXP192_VOFF_SET, 3); } /* * Pekey function */ /** * @brief Set the PEKEY power-on long press time. * @param opt: See xpowers_press_on_time_t enum for details. * @retval */ bool setPowerKeyPressOnTime(uint8_t opt) { int val = readRegister(XPOWERS_AXP192_POK_SET); if (val == -1)return false; return 0 == writeRegister(XPOWERS_AXP192_POK_SET, (val & 0x3F) | (opt << 6)); } /** * @brief Get the PEKEY power-on long press time. * @retval See xpowers_press_on_time_t enum for details. */ uint8_t getPowerKeyPressOnTime() { int val = readRegister(XPOWERS_AXP192_POK_SET); if (val == -1)return 0; return (val & 0xC0) >> 6; } /** * @brief Set the PEKEY power-off long press time. * @param opt: See xpowers_press_off_time_t enum for details. * @retval */ bool setPowerKeyPressOffTime(uint8_t opt) { int val = readRegister(XPOWERS_AXP192_POK_SET); if (val == -1)return false; return 0 == writeRegister(XPOWERS_AXP192_POK_SET, (val & 0xFC) | opt); } /** * @brief Get the PEKEY power-off long press time. * @retval See xpowers_press_off_time_t enum for details. */ uint8_t getPowerKeyPressOffTime() { int val = readRegister(XPOWERS_AXP192_POK_SET); if (val == -1)return 0; return (val & 0x03); } void setPowerKeyLongPressOnTime(xpowers_axp192_pekey_long_press_t opt) { int val = readRegister(XPOWERS_AXP192_POK_SET); if (val == -1)return; writeRegister(XPOWERS_AXP192_POK_SET, (val & 0xCF) | (opt << 4)); } void enablePowerKeyLongPressPowerOff() { setRegisterBit(XPOWERS_AXP192_POK_SET, 3); } void disablePowerKeyLongPressPowerOff() { clrRegisterBit(XPOWERS_AXP192_POK_SET, 3); } protected: uint16_t getPowerChannelVoltage(uint8_t channel) { switch (channel) { case XPOWERS_DCDC1: return getDC1Voltage(); case XPOWERS_DCDC2: return getDC2Voltage(); case XPOWERS_DCDC3: return getDC3Voltage(); case XPOWERS_LDO2: return getLDO2Voltage(); case XPOWERS_LDO3: return getLDO3Voltage(); case XPOWERS_LDOIO: return getLDOioVoltage(); default: break; } return 0; } bool inline enablePowerOutput(uint8_t channel) { /* return 0 == writeRegister(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, val | readRegister(XPOWERS_AXP192_LDO23_DC123_EXT_CTL)); */ switch (channel) { case XPOWERS_DCDC1: return enableDC1(); case XPOWERS_DCDC2: return enableDC2(); case XPOWERS_DCDC3: return enableDC3(); case XPOWERS_LDO2: return enableLDO2(); case XPOWERS_LDO3: return enableLDO3(); case XPOWERS_LDOIO: return enableLDOio(); case XPOWERS_VBACKUP: return enableBackupBattCharger(); default: break; } return false; } bool inline disablePowerOutput(uint8_t channel) { /* return 0 == writeRegister(XPOWERS_AXP192_LDO23_DC123_EXT_CTL, val & readRegister(XPOWERS_AXP192_LDO23_DC123_EXT_CTL)); */ if (getProtectedChannel(channel)) { log_e("Failed to disable the power channel, the power channel has been protected"); return false; } switch (channel) { case XPOWERS_DCDC1: return disableDC1(); case XPOWERS_DCDC2: return disableDC2(); case XPOWERS_DCDC3: return disableDC3(); case XPOWERS_LDO2: return disableLDO2(); case XPOWERS_LDO3: return disableLDO3(); case XPOWERS_LDOIO: return disableLDOio(); case XPOWERS_VBACKUP: return disableBackupBattCharger(); default: break; } return false; } bool inline isPowerChannelEnable(uint8_t channel) { switch (channel) { case XPOWERS_DCDC1: return isEnableDC1(); case XPOWERS_DCDC2: return isEnableDC2(); case XPOWERS_DCDC3: return isEnableDC3(); case XPOWERS_LDO2: return isEnableLDO2(); case XPOWERS_LDO3: return isEnableLDO3(); case XPOWERS_LDOIO: return isEnableLDOio(); case XPOWERS_VBACKUP: return isEnableBackupCharger(); default: break; } return false; } bool inline setPowerChannelVoltage(uint8_t channel, uint16_t millivolt) { if (getProtectedChannel(channel)) { log_e("Failed to set the power channel, the power channel has been protected"); return false; } switch (channel) { case XPOWERS_DCDC1: return setDC1Voltage(millivolt); case XPOWERS_DCDC2: return setDC2Voltage(millivolt); case XPOWERS_DCDC3: return setDC3Voltage(millivolt); case XPOWERS_LDO2: return setLDO2Voltage(millivolt); case XPOWERS_LDO3: return setLDO3Voltage(millivolt); case XPOWERS_LDOIO: return setLDOioVoltage(millivolt); case XPOWERS_VBACKUP: //TODO: // return setBackupBattChargerVoltage(millivolt); default: break; } return false; } bool inline getPowerEnable(uint8_t val) { return (bool)(readRegister(XPOWERS_AXP192_LDO23_DC123_EXT_CTL) & val); } bool initImpl() { if (getChipID() == XPOWERS_AXP192_CHIP_ID) { setChipModel(XPOWERS_AXP192); return true; } return false; } /* * Interrupt control functions */ bool setInterruptImpl(uint64_t opts, bool enable) { int res = 0; int data = 0, value = 0; log_d("%s %s - 0x%llx\n", __func__, enable ? "ENABLE" : "DISABLE", opts); if (opts & 0xFF) { value = opts & 0xFF; data = readRegister(XPOWERS_AXP192_INTEN1); res |= writeRegister(XPOWERS_AXP192_INTEN1, enable ? (data | value) : (data & (~value))); } if (opts & 0xFF00) { value = opts >> 8; data = readRegister(XPOWERS_AXP192_INTEN2); res |= writeRegister(XPOWERS_AXP192_INTEN2, enable ? (data | value) : (data & (~value))); } if (opts & 0xFF0000) { value = opts >> 16; data = readRegister(XPOWERS_AXP192_INTEN3); res |= writeRegister(XPOWERS_AXP192_INTEN3, enable ? (data | value) : (data & (~value))); } if (opts & 0xFF000000) { value = opts >> 24; data = readRegister(XPOWERS_AXP192_INTEN4); res |= writeRegister(XPOWERS_AXP192_INTEN4, enable ? (data | value) : (data & (~value))); } if (opts & 0xFF00000000) { value = opts >> 32; data = readRegister(XPOWERS_AXP192_INTEN5); res |= writeRegister(XPOWERS_AXP192_INTEN5, enable ? (data | value) : (data & (~value))); } return res == 0; } /* * Signal Capture control functions */ bool setSignalCaptureImpl(uint32_t opts, bool enable) { int value = 0; if (opts & 0xFF) { value = readRegister(XPOWERS_AXP192_ADC_EN1); writeRegister(XPOWERS_AXP192_ADC_EN1, enable ? (value | opts) : (value & (~opts))); } if (opts & 0xFF00) { opts >>= 8; value = readRegister(XPOWERS_AXP192_ADC_EN2); writeRegister(XPOWERS_AXP192_ADC_EN2, enable ? (value | opts) : (value & (~opts))); } return true; } const char *getChipNameImpl(void) { return "AXP192"; } private: const uint16_t chargeTargetVol[4] = {4100, 4150, 4200, 4360}; uint8_t statusRegister[5]; xpowers_gpio_t gpio[6]; };