From e03bb921a4b0af91628abdcb1ae840440ef8a087 Mon Sep 17 00:00:00 2001 From: 916BGAI <916772719@qq.com> Date: Thu, 7 Nov 2024 17:30:32 +0800 Subject: [PATCH] add pmu module and axp2101 driver --- components/ext_dev/CMakeLists.txt | 2 + components/ext_dev/include/maix_axp2101.hpp | 329 +++++ components/ext_dev/include/maix_pmu.hpp | 161 +++ components/ext_dev/src/axp2101/axp2101.h | 40 + .../ext_dev/src/axp2101/maix_axp2101.cpp | 1091 +++++++++++++++++ components/ext_dev/src/maix_pmu.cpp | 205 ++++ components/nn/include/maix_nn_speech.hpp | 2 +- examples/maix_pmu/.gitignore | 7 + examples/maix_pmu/README.md | 9 + examples/maix_pmu/app.yaml | 10 + examples/maix_pmu/main/CMakeLists.txt | 73 ++ examples/maix_pmu/main/Kconfig | 0 examples/maix_pmu/main/include/main.h | 3 + examples/maix_pmu/main/src/main.cpp | 45 + 14 files changed, 1976 insertions(+), 1 deletion(-) create mode 100644 components/ext_dev/include/maix_axp2101.hpp create mode 100644 components/ext_dev/include/maix_pmu.hpp create mode 100644 components/ext_dev/src/axp2101/axp2101.h create mode 100644 components/ext_dev/src/axp2101/maix_axp2101.cpp create mode 100644 components/ext_dev/src/maix_pmu.cpp create mode 100644 examples/maix_pmu/.gitignore create mode 100644 examples/maix_pmu/README.md create mode 100644 examples/maix_pmu/app.yaml create mode 100644 examples/maix_pmu/main/CMakeLists.txt create mode 100644 examples/maix_pmu/main/Kconfig create mode 100644 examples/maix_pmu/main/include/main.h create mode 100644 examples/maix_pmu/main/src/main.cpp diff --git a/components/ext_dev/CMakeLists.txt b/components/ext_dev/CMakeLists.txt index 84d5d8f1..b450475d 100644 --- a/components/ext_dev/CMakeLists.txt +++ b/components/ext_dev/CMakeLists.txt @@ -6,6 +6,7 @@ list(APPEND ADD_INCLUDE "src/qmi8658") list(APPEND ADD_INCLUDE "src/qmi8658/ALICHOUCHENE_Qmi8658c") list(APPEND ADD_INCLUDE "src/tmc2209") list(APPEND ADD_INCLUDE "src/tmc2209/janelia-arduino_TMC2209") +list(APPEND ADD_INCLUDE "src/axp2101") append_srcs_dir(ADD_SRCS "src") append_srcs_dir(ADD_SRCS "src/bm8563") append_srcs_dir(ADD_SRCS "src/bm8563/tuupola_bm8563") @@ -13,6 +14,7 @@ append_srcs_dir(ADD_SRCS "src/qmi8658") append_srcs_dir(ADD_SRCS "src/qmi8658/ALICHOUCHENE_Qmi8658c") append_srcs_dir(ADD_SRCS "src/tmc2209") append_srcs_dir(ADD_SRCS "src/tmc2209/janelia-arduino_TMC2209") +append_srcs_dir(ADD_SRCS "src/axp2101") list(APPEND ADD_REQUIREMENTS basic peripheral) # if (PLATFORM_LINUX) diff --git a/components/ext_dev/include/maix_axp2101.hpp b/components/ext_dev/include/maix_axp2101.hpp new file mode 100644 index 00000000..d922c653 --- /dev/null +++ b/components/ext_dev/include/maix_axp2101.hpp @@ -0,0 +1,329 @@ +/** + * @author 916BGAI + * @copyright Sipeed Ltd 2024- + * @license Apache 2.0 + * @update 2024.10.28: Add framework, create this file. + */ + +#pragma once +#include "maix_basic.hpp" +#include "axp2101.h" + +namespace maix::ext_dev::axp2101 { + + /** + * @brief charger status + * @maixpy maix.ext_dev.axp2101.ChargerStatus + */ + enum class ChargerStatus { + CHG_TRI_STATE, //tri_charge + CHG_PRE_STATE, //pre_charge + CHG_CC_STATE, //constant charge + CHG_CV_STATE, //constant voltage + CHG_DONE_STATE, //charge done + CHG_STOP_STATE, //not charge + }; + + /** + * @brief charger current + * @maixpy maix.ext_dev.axp2101.ChargerCurrent + */ + enum class ChargerCurrent { + CHG_CUR_0MA, + CHG_CUR_100MA = 4, + CHG_CUR_125MA, + CHG_CUR_150MA, + CHG_CUR_175MA, + CHG_CUR_200MA, + CHG_CUR_300MA, + CHG_CUR_400MA, + CHG_CUR_500MA, + CHG_CUR_600MA, + CHG_CUR_700MA, + CHG_CUR_800MA, + CHG_CUR_900MA, + CHG_CUR_1000MA, + }; + + /** + * @brief power channel + * @maixpy maix.ext_dev.axp2101.PowerChannel + */ + enum class PowerChannel { + DCDC1, + DCDC2, + DCDC3, + DCDC4, + DCDC5, + ALDO1, + ALDO2, + ALDO3, + ALDO4, + BLDO1, + BLDO2, + DLDO1, + DLDO2, + VBACKUP, + CPULDO, + }; + + /** + * @brief power off time + * @maixpy maix.ext_dev.axp2101.PowerOffTime + */ + enum class PowerOffTime { + POWEROFF_4S, + POWEROFF_6S, + POWEROFF_8S, + POWEROFF_10S, + POWEROFF_DISABLE = 65535, + }; + + /** + * @brief power on time + * @maixpy maix.ext_dev.axp2101.PowerOnTime + */ + enum class PowerOnTime { + POWERON_128MS, + POWERON_512MS, + POWERON_1S, + POWERON_2S, + }; + + /** + * Peripheral AXP2101 class + * @maixpy maix.ext_dev.axp2101.AXP2101 + */ + class AXP2101 { + public: + /** + * @brief AXP2101 constructor. + * @param i2c_bus i2c bus number. + * @param addr pmu device addr. + * @maixpy maix.ext_dev.axp2101.AXP2101.__init__ + */ + AXP2101(int i2c_bus = -1, uint8_t addr = 0x34); + ~AXP2101(); + + /** + * @brief Initialise the AXP2101. + * @return err::Err type, if init success, return err::ERR_NONE. + * @maixpy maix.ext_dev.axp2101.AXP2101.init + */ + err::Err init(); + + /** + * @brief Poweroff immediately. + * @return err::Err type, if init success, return err::ERR_NONE. + * @maixpy maix.ext_dev.axp2101.AXP2101.poweroff + */ + err::Err poweroff(); + + /** + * @brief Is the battery connected. + * @return bool type, if battery is connected, return true. + * @maixpy maix.ext_dev.axp2101.AXP2101.is_bat_connect + */ + bool is_bat_connect(); + + /** + * @brief Is the power adapter connected. + * @return bool type, if power adapter is connected, return true. + * @maixpy maix.ext_dev.axp2101.AXP2101.is_vbus_in + */ + bool is_vbus_in(); + + /** + * @brief Is bat charging. + * @return bool type, if bat is charging, return true. + * @maixpy maix.ext_dev.axp2101.AXP2101.is_charging + */ + bool is_charging(); + + /** + * @brief Get the battery percentage. + * @return int type, return battery percentage. + * @maixpy maix.ext_dev.axp2101.AXP2101.get_bat_percent + */ + int get_bat_percent(); + + /** + * @brief Get the battery charging status. + * @return int type, return battery charging status. + * @maixpy maix.ext_dev.axp2101.AXP2101.get_charger_status + */ + ext_dev::axp2101::ChargerStatus get_charger_status(); + + /** + * @brief Get the battery voltage. + * @return uint16_t type, return battery voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.get_charger_status + */ + uint16_t get_bat_vol(); + + /** + * @brief Clear interrupt flag. + * @return err::Err type, if clean success, return err::ERR_NONE. + * @maixpy maix.ext_dev.axp2101.AXP2101.clean_irq + */ + err::Err clean_irq(); + + /** + * @brief Set the battery charging current. + * @param current The current to be set. + * The available values are 0mA, 100mA, 125mA, 150mA, 175mA, + * 200mA, 300mA, 400mA, 500mA, 600mA, 700mA, 800mA, 900mA, and 1000mA. + * @return err::Err type, if set success, return err::ERR_NONE. + * @maixpy maix.ext_dev.axp2101.AXP2101.set_bat_charging_cur + */ + err::Err set_bat_charging_cur(ext_dev::axp2101::ChargerCurrent current); + + /** + * @brief Get the battery charging current. + * @return ChargerCurrent, return the currently set charging current. + * @maixpy maix.ext_dev.axp2101.AXP2101.get_bat_charging_cur + */ + ext_dev::axp2101::ChargerCurrent get_bat_charging_cur(); + + /** + * @brief Set and get the PMU DCDC1 voltage. + * @param voltage The voltage to be set, + * voltage range is 1500mV~3400mV(step 20mV). + * @return int, return the PMU DCDC1 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.dcdc1 + */ + int dcdc1(int voltage = -1); + + /** + * @brief Set and get the PMU DCDC2 voltage. + * @param voltage The voltage to be set, + * voltage range is 500mV~1200mV(step 10mV) and 1220mV~1540mV(step 20mV). + * @return int, return the PMU DCDC2 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.dcdc2 + */ + int dcdc2(int voltage = -1); + + /** + * @brief Set and get the PMU DCDC3 voltage. + * @param voltage The voltage to be set, + * voltage range is 500mV~1200mV(step 10mV) and 1220mV~1540mV(step 20mV). + * @return int, return the PMU DCDC3 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.dcdc3 + */ + int dcdc3(int voltage = -1); + + /** + * @brief Set and get the PMU DCDC4 voltage. + * @param voltage The voltage to be set, + * voltage range is 500mV~1200mV(step 10mV) and 1220mV~1840mV(step 20mV). + * @return int, return the PMU DCDC4 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.dcdc4 + */ + int dcdc4(int voltage = -1); + + /** + * @brief Set and get the PMU DCDC5 voltage. + * @param voltage The voltage to be set, + * voltage range is 1400mV~3700mV(step 100mV). + * @return int, return the PMU DCDC5 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.dcdc5 + */ + int dcdc5(int voltage = -1); + + /** + * @brief Set and get the PMU ALDO1 voltage. + * @param voltage The voltage to be set, + * voltage range is 500mV~3500mV(step 100mV). + * @return int, return the PMU ALDO1 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.aldo1 + */ + int aldo1(int voltage = -1); + + /** + * @brief Set and get the PMU ALDO2 voltage. + * @param voltage The voltage to be set, + * voltage range is 500mV~3500mV(step 100mV). + * @return int, return the PMU ALDO2 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.aldo2 + */ + int aldo2(int voltage = -1); + + /** + * @brief Set and get the PMU ALDO3 voltage. + * @param voltage The voltage to be set, + * voltage range is 500mV~3500mV(step 100mV). + * @return int, return the PMU ALDO3 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.aldo3 + */ + int aldo3(int voltage = -1); + + /** + * @brief Set and get the PMU ALDO4 voltage. + * @param voltage The voltage to be set, + * voltage range is 500mV~3500mV(step 100mV). + * @return int, return the PMU ALDO4 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.aldo4 + */ + int aldo4(int voltage = -1); + + /** + * @brief Set and get the PMU BLDO1 voltage. + * @param voltage The voltage to be set, + * voltage range is 500mV~3500mV(step 100mV). + * @return int, return the PMU BLDO1 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.bldo1 + */ + int bldo1(int voltage = -1); + + /** + * @brief Set and get the PMU BLDO2 voltage. + * @param voltage The voltage to be set, + * voltage range is 500mV~3500mV(step 100mV). + * @return int, return the PMU BLDO2 voltage. + * @maixpy maix.ext_dev.axp2101.AXP2101.bldo2 + */ + int bldo2(int voltage = -1); + + /** + * @brief Set power-off time, The device will shut down + * if the power button is held down longer than this time. + * @param tm The time to be set, you can set it to 4s, 6s, 8s, or 10s. + * @return err::Err type, if set success, return err::ERR_NONE. + * @maixpy maix.ext_dev.axp2101.AXP2101.set_poweroff_time + */ + err::Err set_poweroff_time(ext_dev::axp2101::PowerOffTime tm); + + /** + * @brief Get power-off time. + * @return PowerOffTime, return power-off time. + * @maixpy maix.ext_dev.axp2101.AXP2101.get_poweroff_time + */ + ext_dev::axp2101::PowerOffTime get_poweroff_time(); + + /** + * @brief Set power-on time, The device will power on + * if the power button is held down longer than this time. + * @param tm The time to be set, you can set it to 128ms, 512ms, 1s, or 2s. + * @return err::Err type, if set success, return err::ERR_NONE. + * @maixpy maix.ext_dev.axp2101.AXP2101.set_poweron_time + */ + err::Err set_poweron_time(ext_dev::axp2101::PowerOnTime tm); + + /** + * @brief Get power-on time. + * @return PowerOnTime, return power-on time. + * @maixpy maix.ext_dev.axp2101.AXP2101.get_poweron_time + */ + ext_dev::axp2101::PowerOnTime get_poweron_time(); + + private: + err::Err deinit(); + err::Err inline set_register_bit(uint8_t registers, uint8_t bit); + err::Err inline clear_register_bit(uint8_t registers, uint8_t bit); + bool inline get_register_bit(uint8_t registers, uint8_t bit); + bool is_vbus_good(void); + err::Err enable_power_channel(PowerChannel channel); + err::Err disable_power_channel(PowerChannel channel); + bool is_enable_channel(PowerChannel channel); + }; +} \ No newline at end of file diff --git a/components/ext_dev/include/maix_pmu.hpp b/components/ext_dev/include/maix_pmu.hpp new file mode 100644 index 00000000..0fad71f6 --- /dev/null +++ b/components/ext_dev/include/maix_pmu.hpp @@ -0,0 +1,161 @@ +/** + * @author 916BGAI + * @copyright Sipeed Ltd 2024- + * @license Apache 2.0 + * @update 2024.10.28: Add framework, create this file. + */ + +#pragma once +#include "maix_basic.hpp" + +namespace maix::ext_dev::pmu { + +/** + * @brief charger status + * @maixpy maix.ext_dev.pmu.ChargerStatus + */ +enum class ChargerStatus { + CHG_TRI_STATE, //tri_charge + CHG_PRE_STATE, //pre_charge + CHG_CC_STATE, //constant charge + CHG_CV_STATE, //constant voltage + CHG_DONE_STATE, //charge done + CHG_STOP_STATE, //not charge +}; + +/** + * @brief power channel + * @maixpy maix.ext_dev.pmu.PowerChannel + */ +enum class PowerChannel { + DCDC1, + DCDC2, + DCDC3, + DCDC4, + DCDC5, + ALDO1, + ALDO2, + ALDO3, + ALDO4, + BLDO1, + BLDO2, + DLDO1, + DLDO2, + VBACKUP, + CPULDO, +}; + +/** + * PMU driver class + * @maixpy maix.ext_dev.pmu.PMU + */ +class PMU { + +public: + /** + * @brief Construct a new PMU object, will open PMU. + * + * @param driver driver name, only support "axp2101". + * @param i2c_bus i2c bus number. Automatically selects the on-board pmu when -1 is passed in. + * @param addr PMU i2c addr. + * + * @maixpy maix.ext_dev.pmu.PMU.__init__ + */ + PMU(std::string driver = "axp2101", int i2c_bus = -1, int addr = 0x34); + ~PMU(); + + /** + * @brief Poweroff immediately. + * @return err::Err type, if init success, return err::ERR_NONE. + * @maixpy maix.ext_dev.pmu.PMU.poweroff + */ + err::Err poweroff(); + + /** + * @brief Is the battery connected. + * @return bool type, if battery is connected, return true. + * @maixpy maix.ext_dev.pmu.PMU.is_bat_connect + */ + bool is_bat_connect(); + + /** + * @brief Is the power adapter connected. + * @return bool type, if power adapter is connected, return true. + * @maixpy maix.ext_dev.pmu.PMU.is_vbus_in + */ + bool is_vbus_in(); + + /** + * @brief Is bat charging. + * @return bool type, if bat is charging, return true. + * @maixpy maix.ext_dev.pmu.PMU.is_charging + */ + bool is_charging(); + + /** + * @brief Get the battery percentage. + * @return int type, return battery percentage. + * @maixpy maix.ext_dev.pmu.PMU.get_bat_percent + */ + int get_bat_percent(); + + /** + * @brief Get the battery charging status. + * @return int type, return battery charging status. + * @maixpy maix.ext_dev.pmu.PMU.get_charger_status + */ + ext_dev::pmu::ChargerStatus get_charger_status(); + + /** + * @brief Get the battery voltage. + * @return uint16_t type, return battery voltage. + * @maixpy maix.ext_dev.pmu.PMU.get_vat_vol + */ + uint16_t get_bat_vol(); + + /** + * @brief Clear interrupt flag. + * @return err::Err type, if clean success, return err::ERR_NONE. + * @maixpy maix.ext_dev.pmu.PMU.clean_irq + */ + err::Err clean_irq(); + + /** + * @brief Set the battery charging current. + * @param current The current to be set. + * @return err::Err type, if set success, return err::ERR_NONE. + * @maixpy maix.ext_dev.pmu.PMU.set_bat_charging_cur + */ + err::Err set_bat_charging_cur(int current); + + /** + * @brief Get the battery charging current. + * @return int, return the currently set charging current. + * @maixpy maix.ext_dev.pmu.PMU.get_bat_charging_cur + */ + int get_bat_charging_cur(); + + /** + * @brief Set the PMU channel voltage. + * You can retrieve the available channel from ext_dev.pmu.PowerChannel. + * @param voltage The voltage to be set. + * @return int, return the channel voltage. + * @maixpy maix.ext_dev.pmu.PMU.set_vol + */ + err::Err set_vol(ext_dev::pmu::PowerChannel channel, int voltage); + + /** + * @brief Get the PMU channel voltage. + * You can retrieve the available channel from ext_dev.pmu.PowerChannel. + * @return err::Err type, if set success, return err::ERR_NONE. + * @maixpy maix.ext_dev.pmu.PMU.get_vol + */ + int get_vol(ext_dev::pmu::PowerChannel channel); + +private: + std::string _driver; + void* _param; + bool _is_opened; +}; + +} \ No newline at end of file diff --git a/components/ext_dev/src/axp2101/axp2101.h b/components/ext_dev/src/axp2101/axp2101.h new file mode 100644 index 00000000..c8c24124 --- /dev/null +++ b/components/ext_dev/src/axp2101/axp2101.h @@ -0,0 +1,40 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define AXP2101_CHIP_ID (0x47) +#define AXP2101_CHIP_ID_B (0x4a) + +#define AXP2101_STATUS1 (0x00) +#define AXP2101_STATUS2 (0x01) +#define AXP2101_VERSION (0x03) +#define AXP2101_COM_CFG (0x10) +#define AXP2101_CHARGE_GAUGE_WDT_CTRL (0x18) +#define AXP2101_PWROFF_EN (0x22) +#define AXP2101_IRQ_OFF_ON_LEVEL_CTRL (0x27) +#define AXP2101_ADC_DATA_RELUST0 (0x34) +#define AXP2101_ADC_DATA_RELUST1 (0x35) +#define AXP2101_INT_STATUS1 (0x48) +#define AXP2101_ICC_CHG_SET (0x62) +#define AXP2101_DC_ONOFF_DVM_CTRL (0x80) +#define AXP2101_DC_VOL0_CTRL (0x82) +#define AXP2101_DC_VOL1_CTRL (0x83) +#define AXP2101_DC_VOL2_CTRL (0x84) +#define AXP2101_DC_VOL3_CTRL (0x85) +#define AXP2101_DC_VOL4_CTRL (0x86) +#define AXP2101_LDO_ONOFF_CTRL0 (0x90) +#define AXP2101_LDO_ONOFF_CTRL1 (0x91) +#define AXP2101_LDO_VOL0_CTRL (0x92) +#define AXP2101_LDO_VOL1_CTRL (0x93) +#define AXP2101_LDO_VOL2_CTRL (0x94) +#define AXP2101_LDO_VOL3_CTRL (0x95) +#define AXP2101_LDO_VOL3_CTRL (0x95) +#define AXP2101_LDO_VOL4_CTRL (0x96) +#define AXP2101_LDO_VOL5_CTRL (0x97) +#define AXP2101_BAT_PERCENT_DATA (0xA4) + +#ifdef __cplusplus +} +#endif diff --git a/components/ext_dev/src/axp2101/maix_axp2101.cpp b/components/ext_dev/src/axp2101/maix_axp2101.cpp new file mode 100644 index 00000000..b90e07f7 --- /dev/null +++ b/components/ext_dev/src/axp2101/maix_axp2101.cpp @@ -0,0 +1,1091 @@ +/** + * @author 916BGAI + * @copyright Sipeed Ltd 2024- + * @license Apache 2.0 + * @update 2024.10.28: Add framework, create this file. + */ + +#include "maix_i2c.hpp" +#include "maix_axp2101.hpp" +#include +#include + +#define _BV(b) (1ULL << (uint64_t)(b)) + +namespace maix::ext_dev::axp2101::priv { + +static const int DEFAULT_I2C_BUS_NUM = 4; +static const char* TAG = "AXP2101"; + +static std::recursive_mutex mtx; +static ::maix::peripheral::i2c::I2C* i2cdev{nullptr}; +static int32_t dev_num{0}; +static uint8_t dev_addr{0}; + +static err::Err maix_i2c_read(uint8_t address, uint8_t reg, uint8_t *buffer, uint16_t size) +{ + ::maix::Bytes* res = nullptr; + + { + std::lock_guard lock(mtx); + i2cdev->writeto((int)address, ®, 1); + res = i2cdev->readfrom((int)address, (int)size); + } + + if (res == nullptr) return err::Err::ERR_READ; + + std::copy(res->data, res->data+res->data_len, buffer); + + delete res; + return err::Err::ERR_NONE; +} + +static err::Err maix_i2c_write(uint8_t address, uint8_t reg, const uint8_t *buffer, uint16_t size) +{ + auto buff = new uint8_t[size+1]; + buff[0] = reg; + std::copy(buffer, buffer+size, buff+1); + + { + std::lock_guard lock(mtx); + i2cdev->writeto((int)address, buff, size+1); + } + + delete[] buff; + return err::Err::ERR_NONE; +} + +static void maix_i2c_init(int bus, uint8_t addr) +{ + if (i2cdev) { + dev_num++; + log::warn("[%s]: AXP2101 already init, finish...", TAG); + return; + } + std::lock_guard lock(mtx); + if (bus < 0) + i2cdev = new ::maix::peripheral::i2c::I2C(DEFAULT_I2C_BUS_NUM, ::maix::peripheral::i2c::MASTER); + else + i2cdev = new ::maix::peripheral::i2c::I2C(bus, ::maix::peripheral::i2c::MASTER); + dev_num ++; + dev_addr = addr; +} + +static err::Err maix_i2c_deinit() +{ + std::lock_guard lock(mtx); + dev_num--; + if (dev_num > 0) return err::Err::ERR_NONE; + dev_addr = 0; + dev_num = 0; + delete i2cdev; + i2cdev = nullptr; + return err::Err::ERR_NONE; +} + +} + +namespace maix::ext_dev::axp2101 { + +AXP2101::AXP2101(int i2c_bus, uint8_t addr) +{ + priv::maix_i2c_init(i2c_bus, addr); + err::Err ret = this->init(); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: AXP2101 init failed. Error code:%d", priv::TAG, ret); + } else { + log::info("[%s]: AXP2101 init success.", priv::TAG); + } +} + +AXP2101::~AXP2101() +{ + err::Err ret = this->deinit(); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: ~AXP2101 failed. Error code:%d", priv::TAG, ret); + } +} + +err::Err inline AXP2101::set_register_bit(uint8_t registers, uint8_t bit) +{ + uint8_t buffer; + err::Err ret = priv::maix_i2c_read(priv::dev_addr, registers, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + return ret; + } + buffer |= (_BV(bit)); + ret = priv::maix_i2c_write(priv::dev_addr, registers, &buffer, 1); + return ret; +} + +err::Err inline AXP2101::clear_register_bit(uint8_t registers, uint8_t bit) +{ + uint8_t buffer; + err::Err ret = priv::maix_i2c_read(priv::dev_addr, registers, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + return ret; + } + buffer &= (~_BV(bit)); + ret = priv::maix_i2c_write(priv::dev_addr, registers, &buffer, 1); + return ret; +} + +bool inline AXP2101::get_register_bit(uint8_t registers, uint8_t bit) +{ + uint8_t buffer; + err::Err ret = priv::maix_i2c_read(priv::dev_addr, registers, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + return false; + } + return buffer & _BV(bit); +} + +err::Err AXP2101::init() +{ + uint8_t buffer; + err::Err ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_VERSION, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } + + buffer &= 0xCF; + if (buffer == AXP2101_CHIP_ID || buffer == AXP2101_CHIP_ID_B) { + log::info("[%s]: Find AXP2101 PMU, chip version: 0x%x.", priv::TAG, buffer); + return err::Err::ERR_NONE; + } else { + log::error("[%s]: Don't find AXP2101 PMU. Error code:%d", priv::TAG); + return err::Err::ERR_RUNTIME; + } +} + +err::Err AXP2101::deinit() +{ + return priv::maix_i2c_deinit(); +} + +err::Err AXP2101::poweroff() +{ + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_COM_CFG, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } + buffer |= 0x01; + system("sync"); + ret = priv::maix_i2c_write(priv::dev_addr, AXP2101_COM_CFG, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_write failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } else { + return err::Err::ERR_NONE; + } +} + +bool AXP2101::is_bat_connect() +{ + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_STATUS1, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return false; + } + return buffer & _BV(3); +} + +bool AXP2101::is_vbus_good() +{ + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_STATUS1, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return false; + } + return buffer & _BV(5); +} + +bool AXP2101::is_vbus_in() +{ + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_STATUS2, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return false; + } + return (buffer & _BV(3)) == 0 && is_vbus_good(); +} + +bool AXP2101::is_charging() +{ + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_STATUS2, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return false; + } + return (buffer >> 5) == 0x01; +} + +int AXP2101::get_bat_percent() +{ + if (!is_bat_connect()) { + return -1; + } + + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_BAT_PERCENT_DATA, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return false; + } + return buffer; +} + +ext_dev::axp2101::ChargerStatus AXP2101::get_charger_status() +{ + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_STATUS2, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return ext_dev::axp2101::ChargerStatus::CHG_STOP_STATE; + } + buffer &= 0x07; + return (ext_dev::axp2101::ChargerStatus)buffer; +} + +uint16_t AXP2101::get_bat_vol() +{ + uint8_t val_h, val_l; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_ADC_DATA_RELUST0, &val_h, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return false; + } + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_ADC_DATA_RELUST1, &val_l, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return false; + } + if (val_h == -1 || val_l == -1) + return 0; + return ((val_h & 0x1F) << 8) | val_l; +} + +err::Err AXP2101::clean_irq() +{ + const uint8_t buffer = 0xFF; + err::Err ret; + for (int i = 0; i < 3; i++) { + ret = priv::maix_i2c_write(priv::dev_addr, AXP2101_INT_STATUS1+i, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_write failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } + } + return err::Err::ERR_NONE; +} + +err::Err AXP2101::set_bat_charging_cur(ext_dev::axp2101::ChargerCurrent current) +{ + if (((int)current < 4 || (int)current > 16) && (int)current != 0) { + log::error("[%s]: The available values are 0mA, 100mA, 125mA, 150mA, 175mA, " + "200mA, 300mA, 400mA, 500mA, 600mA, 700mA, 800mA, 900mA, and 1000mA.", priv::TAG); + return err::Err::ERR_ARGS; + } + + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_ICC_CHG_SET, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } + buffer &= 0xE0; + buffer |= (int)current; + ret = priv::maix_i2c_write(priv::dev_addr, AXP2101_ICC_CHG_SET, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_write failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } else { + return err::Err::ERR_NONE; + } +} + +ext_dev::axp2101::ChargerCurrent AXP2101::get_bat_charging_cur() +{ + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_ICC_CHG_SET, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return ext_dev::axp2101::ChargerCurrent::CHG_CUR_0MA; + } + return (ext_dev::axp2101::ChargerCurrent)(buffer & 0x1F); +} + +err::Err AXP2101::enable_power_channel(PowerChannel channel) { + switch (channel) { + case PowerChannel::DCDC1: + return set_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 0); + case PowerChannel::DCDC2: + return set_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 1); + case PowerChannel::DCDC3: + return set_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 2); + case PowerChannel::DCDC4: + return set_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 3); + case PowerChannel::DCDC5: + return set_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 4); + case PowerChannel::ALDO1: + return set_register_bit(AXP2101_LDO_ONOFF_CTRL0, 0); + case PowerChannel::ALDO2: + return set_register_bit(AXP2101_LDO_ONOFF_CTRL0, 1); + case PowerChannel::ALDO3: + return set_register_bit(AXP2101_LDO_ONOFF_CTRL0, 2); + case PowerChannel::ALDO4: + return set_register_bit(AXP2101_LDO_ONOFF_CTRL0, 3); + case PowerChannel::BLDO1: + return set_register_bit(AXP2101_LDO_ONOFF_CTRL0, 4); + case PowerChannel::BLDO2: + return set_register_bit(AXP2101_LDO_ONOFF_CTRL0, 5); + case PowerChannel::DLDO1: + return set_register_bit(AXP2101_LDO_ONOFF_CTRL0, 7); + case PowerChannel::DLDO2: + return set_register_bit(AXP2101_LDO_ONOFF_CTRL1, 0); + case PowerChannel::VBACKUP: + return set_register_bit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 2); + default: + break; + } + return err::ERR_NONE; +} + +err::Err AXP2101::disable_power_channel(PowerChannel channel) { + switch (channel) { + case PowerChannel::DCDC1: + return clear_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 0); + case PowerChannel::DCDC2: + return clear_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 1); + case PowerChannel::DCDC3: + return clear_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 2); + case PowerChannel::DCDC4: + return clear_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 3); + case PowerChannel::DCDC5: + return clear_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 4); + case PowerChannel::ALDO1: + return clear_register_bit(AXP2101_LDO_ONOFF_CTRL0, 0); + case PowerChannel::ALDO2: + return clear_register_bit(AXP2101_LDO_ONOFF_CTRL0, 1); + case PowerChannel::ALDO3: + return clear_register_bit(AXP2101_LDO_ONOFF_CTRL0, 2); + case PowerChannel::ALDO4: + return clear_register_bit(AXP2101_LDO_ONOFF_CTRL0, 3); + case PowerChannel::BLDO1: + return clear_register_bit(AXP2101_LDO_ONOFF_CTRL0, 4); + case PowerChannel::BLDO2: + return clear_register_bit(AXP2101_LDO_ONOFF_CTRL0, 5); + case PowerChannel::DLDO1: + return clear_register_bit(AXP2101_LDO_ONOFF_CTRL0, 7); + case PowerChannel::DLDO2: + return clear_register_bit(AXP2101_LDO_ONOFF_CTRL1, 0); + case PowerChannel::VBACKUP: + return clear_register_bit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 2); + default: + break; + } + return err::ERR_NONE; +} + +bool AXP2101::is_enable_channel(PowerChannel channel) { + switch (channel) { + case PowerChannel::DCDC1: + return get_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 0); + case PowerChannel::DCDC2: + return get_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 1); + case PowerChannel::DCDC3: + return get_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 2); + case PowerChannel::DCDC4: + return get_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 3); + case PowerChannel::DCDC5: + return get_register_bit(AXP2101_DC_ONOFF_DVM_CTRL, 4); + case PowerChannel::ALDO1: + return get_register_bit(AXP2101_LDO_ONOFF_CTRL0, 0); + case PowerChannel::ALDO2: + return get_register_bit(AXP2101_LDO_ONOFF_CTRL0, 1); + case PowerChannel::ALDO3: + return get_register_bit(AXP2101_LDO_ONOFF_CTRL0, 2); + case PowerChannel::ALDO4: + return get_register_bit(AXP2101_LDO_ONOFF_CTRL0, 3); + case PowerChannel::BLDO1: + return get_register_bit(AXP2101_LDO_ONOFF_CTRL0, 4); + case PowerChannel::BLDO2: + return get_register_bit(AXP2101_LDO_ONOFF_CTRL0, 5); + case PowerChannel::DLDO1: + return get_register_bit(AXP2101_LDO_ONOFF_CTRL0, 7); + case PowerChannel::DLDO2: + return get_register_bit(AXP2101_LDO_ONOFF_CTRL1, 0); + case PowerChannel::VBACKUP: + return get_register_bit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 2); + default: + break; + } + return false; +} + +int AXP2101::dcdc1(int voltage) +{ + uint8_t buffer; + if (voltage > 0) { + if (voltage % 100) { + log::error("[%s]: DCDC1: The steps is must %d mV", priv::TAG, 100); + return -1; + } + if (voltage < 1500) { + log::error("[%s]: DCDC1: Minimum voltage is %d mV", priv::TAG, 1500); + return -1; + } else if (voltage > 3400) { + log::error("[%s]: DCDC1: Maximum voltage is %d mV", priv::TAG, 3400); + return -1; + } + + buffer = (voltage - 1500) / 100; + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_DC_VOL0_CTRL, &buffer, 1)) { + log::error("[%s]: DCDC1: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::DCDC1) != true) { + if(enable_power_channel(PowerChannel::DCDC1)) { + log::error("[%s]: DCDC1: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::DCDC1)) { + log::error("[%s]: DCDC1: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::DCDC1) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_DC_VOL0_CTRL, &buffer, 1); + voltage = (buffer & 0x1F) * 100 + 1500; + } + + return voltage; +} + +int AXP2101::dcdc2(int voltage) +{ + uint8_t buffer; + if (priv::maix_i2c_read(priv::dev_addr, AXP2101_DC_VOL1_CTRL, &buffer, 1)) { + return -1; + } + buffer &= 0x80; + + if (voltage > 0) { + if (voltage >= 500 && voltage <= 1200) { + if (voltage % 10) { + log::error("[%s]: DCDC2: The steps is must %d mV", priv::TAG, 10); + return -1; + } + buffer |= ((voltage - 500) / 10); + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_DC_VOL1_CTRL, &buffer, 1)) { + log::error("[%s]: DCDC2: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + } else if (voltage >= 1220 && voltage <= 1540) { + if (voltage % 20) { + log::error("[%s]: DCDC2: The steps is must %d mV", priv::TAG, 20); + return -1; + } + buffer |= ((voltage - 1220) / 20 + 71); + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_DC_VOL1_CTRL, &buffer, 1)) { + log::error("[%s]: DCDC2: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + } else { + log::error("[%s]: DCDC2: The voltage setting range is" + "500mV~1200mV(step 10mV) and 1220mV~1540mV(step 20mV).", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::DCDC2) != true) { + if(enable_power_channel(PowerChannel::DCDC2)) { + log::error("[%s]: DCDC2: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::DCDC2)) { + log::error("[%s]: DCDC2: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::DCDC2) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_DC_VOL1_CTRL, &buffer, 1); + buffer &= 0x7F; + if (buffer < 71) { + voltage = buffer * 10 + 500; + } else { + voltage = buffer * 20 - 200; + } + } + + return voltage; +} + +int AXP2101::dcdc3(int voltage) +{ + uint8_t buffer; + if (priv::maix_i2c_read(priv::dev_addr, AXP2101_DC_VOL2_CTRL, &buffer, 1)) { + return -1; + } + buffer &= 0x80; + + if (voltage > 0) { + if (voltage >= 500 && voltage <= 1200) { + if (voltage % 10) { + log::error("[%s]: DCDC3: The steps is must %d mV", priv::TAG, 10); + return -1; + } + buffer |= ((voltage - 500) / 10); + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_DC_VOL2_CTRL, &buffer, 1)) { + log::error("[%s]: DCDC3: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + } else if (voltage >= 1220 && voltage <= 1540) { + if (voltage % 20) { + log::error("[%s]: DCDC3: The steps is must %d mV", priv::TAG, 20); + return -1; + } + buffer |= ((voltage - 1220) / 20 + 71); + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_DC_VOL2_CTRL, &buffer, 1)) { + log::error("[%s]: DCDC3: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + } else { + log::error("[%s]: DCDC3: The voltage setting range is" + "500mV~1200mV(step 10mV) and 1220mV~1540mV(step 20mV).", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::DCDC3) != true) { + if(enable_power_channel(PowerChannel::DCDC3)) { + log::error("[%s]: DCDC3: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::DCDC3)) { + log::error("[%s]: DCDC3: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::DCDC3) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_DC_VOL2_CTRL, &buffer, 1); + buffer &= 0x7F; + if (buffer < 71) { + voltage = buffer * 10 + 500; + } else { + voltage = buffer * 20 - 200; + } + } + + return voltage; +} + +int AXP2101::dcdc4(int voltage) +{ + uint8_t buffer; + if (priv::maix_i2c_read(priv::dev_addr, AXP2101_DC_VOL3_CTRL, &buffer, 1)) { + return -1; + } + buffer &= 0x80; + + if (voltage > 0) { + if (voltage >= 500 && voltage <= 1200) { + if (voltage % 10) { + log::error("[%s]: DCDC4: The steps is must %d mV", priv::TAG, 10); + return -1; + } + buffer |= ((voltage - 500) / 10); + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_DC_VOL3_CTRL, &buffer, 1)) { + log::error("[%s]: DCDC4: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + } else if (voltage >= 1220 && voltage <= 1840) { + if (voltage % 20) { + log::error("[%s]: DCDC4: The steps is must %d mV", priv::TAG, 20); + return -1; + } + buffer |= ((voltage - 1220) / 20 + 71); + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_DC_VOL3_CTRL, &buffer, 1)) { + log::error("[%s]: DCDC4: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + } else { + log::error("[%s]: DCDC4: The voltage setting range is" + "500mV~1200mV(step 10mV) and 1220mV~1840mV(step 20mV).", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::DCDC4) != true) { + if(enable_power_channel(PowerChannel::DCDC4)) { + log::error("[%s]: DCDC4: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::DCDC4)) { + log::error("[%s]: DCDC4: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::DCDC4) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_DC_VOL3_CTRL, &buffer, 1); + buffer &= 0x7F; + if (buffer < 71) { + voltage = buffer * 10 + 500; + } else { + voltage = buffer * 20 - 200; + } + } + + return voltage; +} + +int AXP2101::dcdc5(int voltage) +{ + uint8_t buffer; + if (voltage > 0) { + if (voltage % 100) { + log::error("[%s]: DCDC5: The steps is must %d mV", priv::TAG, 100); + return -1; + } + if (voltage != 1200 && voltage < 1400) { + log::error("[%s]: DCDC5: Minimum voltage is %d mV", priv::TAG, 1400); + return -1; + } else if (voltage > 3700) { + log::error("[%s]: DCDC5: Maximum voltage is %d mV", priv::TAG, 3700); + return -1; + } + + if (priv::maix_i2c_read(priv::dev_addr, AXP2101_DC_VOL4_CTRL, &buffer, 1)) { + return -1; + } + buffer &= 0xE0; + if (voltage == 1200) { + buffer |= 0x19; + } else { + buffer |= (voltage - 1400) / 100; + } + + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_DC_VOL4_CTRL, &buffer, 1)) { + log::error("[%s]: DCDC5: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::DCDC5) != true) { + if(enable_power_channel(PowerChannel::DCDC5)) { + log::error("[%s]: DCDC5: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::DCDC5)) { + log::error("[%s]: DCDC5: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::DCDC5) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_DC_VOL4_CTRL, &buffer, 1); + buffer &= 0x1F; + if (buffer == 0x19) { + voltage = 1200; + } else { + voltage = buffer * 100 + 1400; + } + } + + return voltage; +} + +int AXP2101::aldo1(int voltage) +{ + uint8_t buffer; + if (voltage > 0) { + if (voltage % 100) { + log::error("[%s]: ALDO1: The steps is must %d mV", priv::TAG, 100); + return -1; + } + if (voltage < 500) { + log::error("[%s]: ALDO1: Minimum voltage is %d mV", priv::TAG, 500); + return -1; + } else if (voltage > 3500) { + log::error("[%s]: ALDO1: Maximum voltage is %d mV", priv::TAG, 3500); + return -1; + } + + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL0_CTRL, &buffer, 1); + buffer &= 0xE0; + buffer = (voltage - 500) / 100; + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_LDO_VOL0_CTRL, &buffer, 1)) { + log::error("[%s]: ALDO1: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::ALDO1) != true) { + if(enable_power_channel(PowerChannel::ALDO1)) { + log::error("[%s]: ALDO1: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::ALDO1)) { + log::error("[%s]: ALDO1: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::ALDO1) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL0_CTRL, &buffer, 1); + voltage = (buffer & 0x1F) * 100 + 500; + } + + return voltage; +} + +int AXP2101::aldo2(int voltage) +{ + uint8_t buffer; + if (voltage > 0) { + if (voltage % 100) { + log::error("[%s]: ALDO2: The steps is must %d mV", priv::TAG, 100); + return -1; + } + if (voltage < 500) { + log::error("[%s]: ALDO2: Minimum voltage is %d mV", priv::TAG, 500); + return -1; + } else if (voltage > 3500) { + log::error("[%s]: ALDO2: Maximum voltage is %d mV", priv::TAG, 3500); + return -1; + } + + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL1_CTRL, &buffer, 1); + buffer &= 0xE0; + buffer = (voltage - 500) / 100; + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_LDO_VOL1_CTRL, &buffer, 1)) { + log::error("[%s]: ALDO2: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::ALDO2) != true) { + if(enable_power_channel(PowerChannel::ALDO2)) { + log::error("[%s]: ALDO2: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::ALDO2)) { + log::error("[%s]: ALDO2: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::ALDO2) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL1_CTRL, &buffer, 1); + voltage = (buffer & 0x1F) * 100 + 500; + } + + return voltage; +} + +int AXP2101::aldo3(int voltage) +{ + uint8_t buffer; + if (voltage > 0) { + if (voltage % 100) { + log::error("[%s]: ALDO3: The steps is must %d mV", priv::TAG, 100); + return -1; + } + if (voltage < 500) { + log::error("[%s]: ALDO3: Minimum voltage is %d mV", priv::TAG, 500); + return -1; + } else if (voltage > 3500) { + log::error("[%s]: ALDO3: Maximum voltage is %d mV", priv::TAG, 3500); + return -1; + } + + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL2_CTRL, &buffer, 1); + buffer &= 0xE0; + buffer = (voltage - 500) / 100; + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_LDO_VOL2_CTRL, &buffer, 1)) { + log::error("[%s]: ALDO3: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::ALDO3) != true) { + if(enable_power_channel(PowerChannel::ALDO3)) { + log::error("[%s]: ALDO3: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::ALDO3)) { + log::error("[%s]: ALDO3: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::ALDO3) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL2_CTRL, &buffer, 1); + voltage = (buffer & 0x1F) * 100 + 500; + } + + return voltage; +} + +int AXP2101::aldo4(int voltage) +{ + uint8_t buffer; + if (voltage > 0) { + if (voltage % 100) { + log::error("[%s]: ALDO4: The steps is must %d mV", priv::TAG, 100); + return -1; + } + if (voltage < 500) { + log::error("[%s]: ALDO4: Minimum voltage is %d mV", priv::TAG, 500); + return -1; + } else if (voltage > 3500) { + log::error("[%s]: ALDO4: Maximum voltage is %d mV", priv::TAG, 3500); + return -1; + } + + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL3_CTRL, &buffer, 1); + buffer &= 0xE0; + buffer = (voltage - 500) / 100; + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_LDO_VOL3_CTRL, &buffer, 1)) { + log::error("[%s]: ALDO4: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::ALDO4) != true) { + if(enable_power_channel(PowerChannel::ALDO4)) { + log::error("[%s]: ALDO4: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::ALDO4)) { + log::error("[%s]: ALDO4: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::ALDO4) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL3_CTRL, &buffer, 1); + voltage = (buffer & 0x1F) * 100 + 500; + } + + return voltage; +} + +int AXP2101::bldo1(int voltage) +{ + uint8_t buffer; + if (voltage > 0) { + if (voltage % 100) { + log::error("[%s]: BLDO1: The steps is must %d mV", priv::TAG, 100); + return -1; + } + if (voltage < 500) { + log::error("[%s]: BLDO1: Minimum voltage is %d mV", priv::TAG, 500); + return -1; + } else if (voltage > 3500) { + log::error("[%s]: BLDO1: Maximum voltage is %d mV", priv::TAG, 3500); + return -1; + } + + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL4_CTRL, &buffer, 1); + buffer &= 0xE0; + buffer = (voltage - 500) / 100; + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_LDO_VOL4_CTRL, &buffer, 1)) { + log::error("[%s]: BLDO1: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::BLDO1) != true) { + if(enable_power_channel(PowerChannel::BLDO1)) { + log::error("[%s]: BLDO1: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::BLDO1)) { + log::error("[%s]: BLDO1: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::BLDO1) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL4_CTRL, &buffer, 1); + voltage = (buffer & 0x1F) * 100 + 500; + } + + return voltage; +} + +int AXP2101::bldo2(int voltage) +{ + uint8_t buffer; + if (voltage > 0) { + if (voltage % 100) { + log::error("[%s]: BLDO2: The steps is must %d mV", priv::TAG, 100); + return -1; + } + if (voltage < 500) { + log::error("[%s]: BLDO2: Minimum voltage is %d mV", priv::TAG, 500); + return -1; + } else if (voltage > 3500) { + log::error("[%s]: BLDO2: Maximum voltage is %d mV", priv::TAG, 3500); + return -1; + } + + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL5_CTRL, &buffer, 1); + buffer &= 0xE0; + buffer = (voltage - 500) / 100; + if(priv::maix_i2c_write(priv::dev_addr, AXP2101_LDO_VOL5_CTRL, &buffer, 1)) { + log::error("[%s]: BLDO2: Set voltage %d mV error", priv::TAG, voltage); + return -1; + } + + if (is_enable_channel(PowerChannel::BLDO2) != true) { + if(enable_power_channel(PowerChannel::BLDO2)) { + log::error("[%s]: BLDO2: Enable dcdc channel error", priv::TAG); + return -1; + } + } + } else if (voltage == 0) { + if(disable_power_channel(PowerChannel::BLDO2)) { + log::error("[%s]: BLDO2: Disable dcdc channel error", priv::TAG); + return -1; + } + } + + if (is_enable_channel(PowerChannel::BLDO2) != true) { + return 0; + } else { + priv::maix_i2c_read(priv::dev_addr, AXP2101_LDO_VOL5_CTRL, &buffer, 1); + voltage = (buffer & 0x1F) * 100 + 500; + } + + return voltage; +} + +err::Err AXP2101::set_poweroff_time(ext_dev::axp2101::PowerOffTime tm) +{ + if (tm == PowerOffTime::POWEROFF_DISABLE) { + return clear_register_bit(AXP2101_PWROFF_EN, 1); + } else { + set_register_bit(AXP2101_PWROFF_EN, 1); + } + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_IRQ_OFF_ON_LEVEL_CTRL, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } + buffer &= 0xF3; + buffer |= ((int)tm << 2); + ret = priv::maix_i2c_write(priv::dev_addr, AXP2101_IRQ_OFF_ON_LEVEL_CTRL, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_write failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } else { + return err::Err::ERR_NONE; + } +} + +ext_dev::axp2101::PowerOffTime AXP2101::get_poweroff_time() +{ + if (get_register_bit(AXP2101_PWROFF_EN, 1) == false) { + return PowerOffTime::POWEROFF_DISABLE; + } + + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_IRQ_OFF_ON_LEVEL_CTRL, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return PowerOffTime::POWEROFF_DISABLE; + } + return (PowerOffTime)((buffer & 0x0C) >> 2); +} + +err::Err AXP2101::set_poweron_time(ext_dev::axp2101::PowerOnTime tm) +{ + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_IRQ_OFF_ON_LEVEL_CTRL, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } + buffer &= 0xFC; + buffer |= (int)tm; + ret = priv::maix_i2c_write(priv::dev_addr, AXP2101_IRQ_OFF_ON_LEVEL_CTRL, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_write failed. Error code:%d", priv::TAG, ret); + return err::Err::ERR_RUNTIME; + } else { + return err::Err::ERR_NONE; + } +} + +ext_dev::axp2101::PowerOnTime AXP2101::get_poweron_time() +{ + uint8_t buffer; + err::Err ret; + ret = priv::maix_i2c_read(priv::dev_addr, AXP2101_IRQ_OFF_ON_LEVEL_CTRL, &buffer, 1); + if (ret != err::Err::ERR_NONE) { + log::error("[%s]: maix_i2c_read failed. Error code:%d", priv::TAG, ret); + return PowerOnTime::POWERON_128MS; + } + return (PowerOnTime)(buffer & 0x03); +} + +} \ No newline at end of file diff --git a/components/ext_dev/src/maix_pmu.cpp b/components/ext_dev/src/maix_pmu.cpp new file mode 100644 index 00000000..286ff413 --- /dev/null +++ b/components/ext_dev/src/maix_pmu.cpp @@ -0,0 +1,205 @@ + +#include "maix_basic.hpp" +#include "maix_pmu.hpp" +#include "maix_axp2101.hpp" + +namespace maix::ext_dev::pmu { + +typedef struct { + union { + maix::ext_dev::axp2101::AXP2101 *axp2101; + } driver; +} pmu_param_t; + +PMU::PMU(std::string driver, int i2c_bus, int addr) +{ + err::check_bool_raise(driver == "axp2101", "Only support axp2101 now"); + pmu_param_t *param = (pmu_param_t *)malloc(sizeof(pmu_param_t)); + err::check_null_raise(param, "Failed to malloc param"); + + param->driver.axp2101 = new maix::ext_dev::axp2101::AXP2101(i2c_bus, addr); + _param = (void *)param; + _driver = driver; +} + +PMU::~PMU() +{ + if (_param) { + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + delete param->driver.axp2101; + param->driver.axp2101 = NULL; + } + free(_param); + _param = NULL; + } +} + +err::Err PMU::poweroff() +{ + err::Err err = err::Err::ERR_NOT_IMPL; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + err = param->driver.axp2101->poweroff(); + } + return err; +} + +bool PMU::is_bat_connect() +{ + bool ret = false; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + ret = param->driver.axp2101->is_bat_connect(); + } + return ret; +} + +bool PMU::is_vbus_in() +{ + bool ret = false; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + ret = param->driver.axp2101->is_vbus_in(); + } + return ret; +} + +bool PMU::is_charging() +{ + bool ret = false; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + ret = param->driver.axp2101->is_charging(); + } + return ret; +} + +int PMU::get_bat_percent() +{ + int ret = -1; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + ret = param->driver.axp2101->get_bat_percent(); + } + return ret; +} + +ext_dev::pmu::ChargerStatus PMU::get_charger_status() +{ + ext_dev::pmu::ChargerStatus ret = ext_dev::pmu::ChargerStatus::CHG_STOP_STATE; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + ret = (ext_dev::pmu::ChargerStatus)param->driver.axp2101->get_charger_status(); + } + return ret; +} + +uint16_t PMU::get_bat_vol() +{ + uint16_t ret = 0; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + ret = param->driver.axp2101->get_bat_vol(); + } + return ret; +} + +err::Err PMU::clean_irq() +{ + err::Err err = err::Err::ERR_NOT_IMPL; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + err = param->driver.axp2101->clean_irq(); + } + return err; +} + +err::Err PMU::set_bat_charging_cur(int current) +{ + err::Err err = err::Err::ERR_NOT_IMPL; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + if (current <= 200) { + current = current * 0.04; + } else { + current = (current - 200) * 0.01 + 8; + } + err = param->driver.axp2101->set_bat_charging_cur((axp2101::ChargerCurrent)current); + } + return err; +} + +int PMU::get_bat_charging_cur() +{ + int ret = 0; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + ret = (int)param->driver.axp2101->get_bat_charging_cur(); + if (ret <= 8) { + ret = ret * 25; + } else { + ret = (ret - 8) * 100 + 200; + } + } + return ret; +} + +err::Err PMU::set_vol(ext_dev::pmu::PowerChannel channel, int voltage) +{ + err::Err err = err::Err::ERR_NOT_IMPL; + int ret = -1; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + switch (channel) { + case PowerChannel::DCDC1: ret = param->driver.axp2101->dcdc1(voltage); break; + case PowerChannel::DCDC2: ret = param->driver.axp2101->dcdc2(voltage); break; + case PowerChannel::DCDC3: ret = param->driver.axp2101->dcdc3(voltage); break; + case PowerChannel::DCDC4: ret = param->driver.axp2101->dcdc4(voltage); break; + case PowerChannel::DCDC5: ret = param->driver.axp2101->dcdc5(voltage); break; + case PowerChannel::ALDO1: ret = param->driver.axp2101->aldo1(voltage); break; + case PowerChannel::ALDO2: ret = param->driver.axp2101->aldo2(voltage); break; + case PowerChannel::ALDO3: ret = param->driver.axp2101->aldo3(voltage); break; + case PowerChannel::ALDO4: ret = param->driver.axp2101->aldo4(voltage); break; + case PowerChannel::BLDO1: ret = param->driver.axp2101->bldo1(voltage); break; + case PowerChannel::BLDO2: ret = param->driver.axp2101->bldo2(voltage); break; + default: + log::error("[%s]: Channel not support.", _driver.c_str()); + return err::Err::ERR_NOT_IMPL; + if (ret != voltage) { + log::error("Set voltage error. ret=%d", ret); + err = err::Err::ERR_RUNTIME; + } else { + err = err::Err::ERR_NONE; + } + } + } + return err; +} + +int PMU::get_vol(ext_dev::pmu::PowerChannel channel) +{ + int ret = -1; + pmu_param_t *param = (pmu_param_t *)_param; + if (_driver == "axp2101") { + switch (channel) { + case PowerChannel::DCDC1: ret = param->driver.axp2101->dcdc1(); break; + case PowerChannel::DCDC2: ret = param->driver.axp2101->dcdc2(); break; + case PowerChannel::DCDC3: ret = param->driver.axp2101->dcdc3(); break; + case PowerChannel::DCDC4: ret = param->driver.axp2101->dcdc4(); break; + case PowerChannel::DCDC5: ret = param->driver.axp2101->dcdc5(); break; + case PowerChannel::ALDO1: ret = param->driver.axp2101->aldo1(); break; + case PowerChannel::ALDO2: ret = param->driver.axp2101->aldo2(); break; + case PowerChannel::ALDO3: ret = param->driver.axp2101->aldo3(); break; + case PowerChannel::ALDO4: ret = param->driver.axp2101->aldo4(); break; + case PowerChannel::BLDO1: ret = param->driver.axp2101->bldo1(); break; + case PowerChannel::BLDO2: ret = param->driver.axp2101->bldo2(); break; + default: + log::error("[%s]: Channel not support.", _driver.c_str()); + return -1; + } + } + return ret; +} + +} \ No newline at end of file diff --git a/components/nn/include/maix_nn_speech.hpp b/components/nn/include/maix_nn_speech.hpp index e8e0644e..af0ffeff 100644 --- a/components/nn/include/maix_nn_speech.hpp +++ b/components/nn/include/maix_nn_speech.hpp @@ -891,7 +891,7 @@ enum SpeechDecoder { */ std::pair vocab() { - return {"", 0}; + return {nullptr, 0}; } /** diff --git a/examples/maix_pmu/.gitignore b/examples/maix_pmu/.gitignore new file mode 100644 index 00000000..6c93fbbf --- /dev/null +++ b/examples/maix_pmu/.gitignore @@ -0,0 +1,7 @@ +build +dist +.config.mk +.flash.conf.json +data +/CMakeLists.txt +__pycache__ diff --git a/examples/maix_pmu/README.md b/examples/maix_pmu/README.md new file mode 100644 index 00000000..99b3512f --- /dev/null +++ b/examples/maix_pmu/README.md @@ -0,0 +1,9 @@ +maix_pmu Project based on MaixCDK +==== + + + + + +This is a project based on MaixCDK, build method please visit [MaixCDK](https://github.com/sipeed/MaixCDK) + diff --git a/examples/maix_pmu/app.yaml b/examples/maix_pmu/app.yaml new file mode 100644 index 00000000..77f66d6b --- /dev/null +++ b/examples/maix_pmu/app.yaml @@ -0,0 +1,10 @@ +id: maix_pmu +name: maix_pmu +name[zh]: +version: 1.0.0 +#icon: assets/hello.png +author: +desc: +desc[zh]: +files: + # assets: assets diff --git a/examples/maix_pmu/main/CMakeLists.txt b/examples/maix_pmu/main/CMakeLists.txt new file mode 100644 index 00000000..4be5a698 --- /dev/null +++ b/examples/maix_pmu/main/CMakeLists.txt @@ -0,0 +1,73 @@ +############### Add include ################### +list(APPEND ADD_INCLUDE "include" + ) +list(APPEND ADD_PRIVATE_INCLUDE "") +############################################### + +############ Add source files ################# +# list(APPEND ADD_SRCS "src/main.c" +# "src/test.c" +# ) +append_srcs_dir(ADD_SRCS "src") # append source file in src dir to var ADD_SRCS +# list(REMOVE_ITEM COMPONENT_SRCS "src/test2.c") +# FILE(GLOB_RECURSE EXTRA_SRC "src/*.c") +# FILE(GLOB EXTRA_SRC "src/*.c") +# list(APPEND ADD_SRCS ${EXTRA_SRC}) +# aux_source_directory(src ADD_SRCS) # collect all source file in src dir, will set var ADD_SRCS +# append_srcs_dir(ADD_SRCS "src") # append source file in src dir to var ADD_SRCS +# list(REMOVE_ITEM COMPONENT_SRCS "src/test.c") +# set(ADD_ASM_SRCS "src/asm.S") +# list(APPEND ADD_SRCS ${ADD_ASM_SRCS}) +# SET_PROPERTY(SOURCE ${ADD_ASM_SRCS} PROPERTY LANGUAGE C) # set .S ASM file as C language +# SET_SOURCE_FILES_PROPERTIES(${ADD_ASM_SRCS} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp -D BBBBB") +############################################### + +###### Add required/dependent components ###### +list(APPEND ADD_REQUIREMENTS basic ext_dev) +############################################### + +###### Add link search path for requirements/libs ###### +# list(APPEND ADD_LINK_SEARCH_PATH "${CONFIG_TOOLCHAIN_PATH}/lib") +# list(APPEND ADD_REQUIREMENTS pthread m) # add system libs, pthread and math lib for example here +# set (OpenCV_DIR opencv/lib/cmake/opencv4) +# find_package(OpenCV REQUIRED) +############################################### + +############ Add static libs ################## +# list(APPEND ADD_STATIC_LIB "lib/libtest.a") +############################################### + +#### Add compile option for this component #### +#### Just for this component, won't affect other +#### modules, including component that depend +#### on this component +# list(APPEND ADD_DEFINITIONS_PRIVATE -DAAAAA=1) + +#### Add compile option for this component +#### and components depend on this component +# list(APPEND ADD_DEFINITIONS -DAAAAA222=1 +# -DAAAAA333=1) +############################################### + +############ Add static libs ################## +#### Update parent's variables like CMAKE_C_LINK_FLAGS +# set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group libmaix/libtest.a -ltest2 -Wl,--end-group" PARENT_SCOPE) +############################################### + +######### Add files need to download ######### +# list(APPEND ADD_FILE_DOWNLOADS "{ +# 'url': 'https://*****/abcde.tar.xz', +# 'urls': [], # backup urls, if url failed, will try urls +# 'sites': [], # download site, user can manually download file and put it into dl_path +# 'sha256sum': '', +# 'filename': 'abcde.tar.xz', +# 'path': 'toolchains/xxxxx', +# }" +# ) +# +# then extracted file in ${DL_EXTRACTED_PATH}/toolchains/xxxxx, +# you can directly use then, for example use it in add_custom_command +############################################## + +# register component, DYNAMIC or SHARED flags will make component compiled to dynamic(shared) lib +register_component() diff --git a/examples/maix_pmu/main/Kconfig b/examples/maix_pmu/main/Kconfig new file mode 100644 index 00000000..e69de29b diff --git a/examples/maix_pmu/main/include/main.h b/examples/maix_pmu/main/include/main.h new file mode 100644 index 00000000..45dcbb04 --- /dev/null +++ b/examples/maix_pmu/main/include/main.h @@ -0,0 +1,3 @@ +#pragma once + + diff --git a/examples/maix_pmu/main/src/main.cpp b/examples/maix_pmu/main/src/main.cpp new file mode 100644 index 00000000..852c4162 --- /dev/null +++ b/examples/maix_pmu/main/src/main.cpp @@ -0,0 +1,45 @@ + +#include "maix_basic.hpp" +#include "maix_pmu.hpp" +#include "main.h" + +using namespace maix; +using namespace ext_dev; + +int _main(int argc, char* argv[]) +{ + pmu::PMU pmu("axp2101"); + + // Get battery percent + log::info("Battery percent: %d%%", pmu.get_bat_percent()); + + // Set the max battery charging current + pmu.set_bat_charging_cur(1000); + log::info("Max charging current: %dmA", pmu.get_bat_charging_cur()); + + // Set DCDC1 voltage + pmu.set_vol(pmu::PowerChannel::DCDC1, 3300); + log::info("Set DCDC1 voltage: %dmV", pmu.get_vol(pmu::PowerChannel::DCDC1)); + + // Get all channel voltage + log::info("------ All channel voltage: ------"); + log::info("DCDC1: %d", pmu.get_vol(pmu::PowerChannel::DCDC1)); + log::info("DCDC2: %d", pmu.get_vol(pmu::PowerChannel::DCDC2)); + log::info("DCDC3: %d", pmu.get_vol(pmu::PowerChannel::DCDC3)); + log::info("DCDC4: %d", pmu.get_vol(pmu::PowerChannel::DCDC4)); + log::info("DCDC5: %d", pmu.get_vol(pmu::PowerChannel::DCDC5)); + log::info("ALDO1: %d", pmu.get_vol(pmu::PowerChannel::ALDO1)); + log::info("ALDO2: %d", pmu.get_vol(pmu::PowerChannel::ALDO2)); + log::info("ALDO3: %d", pmu.get_vol(pmu::PowerChannel::ALDO3)); + log::info("ALDO4: %d", pmu.get_vol(pmu::PowerChannel::ALDO4)); + log::info("BLDO1: %d", pmu.get_vol(pmu::PowerChannel::BLDO1)); + log::info("BLDO2: %d", pmu.get_vol(pmu::PowerChannel::BLDO2)); + log::info("----------------------------------"); + return 0; +} + +int main(int argc, char* argv[]) +{ + sys::register_default_signal_handle(); + CATCH_EXCEPTION_RUN_RETURN(_main, -1, argc, argv); +}