6 #include "../M5Unified.hpp"
8 #if !defined (M5UNIFIED_PC_BUILD)
11 #include <esp_sleep.h>
12 #include <sdkconfig.h>
14 #include <esp_adc_cal.h>
15 #include <soc/adc_channel.h>
17 #if __has_include (<esp_idf_version.h>)
18 #include <esp_idf_version.h>
19 #if ESP_IDF_VERSION_MAJOR >= 4
20 #define NON_BREAK ;[[fallthrough]];
32 static constexpr
const uint32_t i2c_freq = 100000;
33 #if defined (CONFIG_IDF_TARGET_ESP32S3)
34 static constexpr
int aw9523_i2c_addr = 0x58;
36 #elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
37 static constexpr
int CoreInk_POWER_HOLD_PIN = 12;
38 static constexpr
int M5Paper_POWER_HOLD_PIN = 2;
39 static constexpr
int TimerCam_POWER_HOLD_PIN = 33;
40 static constexpr
int TimerCam_LED_PIN = 2;
41 static constexpr
int M5Paper_EXT5V_ENABLE_PIN = 5;
42 static constexpr
int StickCPlus2_POWER_HOLD_PIN = 4;
43 static constexpr
int StickCPlus2_LED_PIN = 19;
48 _pmic = pmic_t::pmic_unknown;
50 #if !defined (M5UNIFIED_PC_BUILD)
51 #if defined (CONFIG_IDF_TARGET_ESP32S3)
59 case board_t::board_M5StackCoreS3:
61 _pmic = Power_Class::pmic_t::pmic_axp2101;
63 static constexpr std::uint8_t reg_data_array[] =
76 case board_t::board_M5Dial:
77 _pwrHoldPin = GPIO_NUM_46;
80 case board_t::board_M5Capsule:
81 _pwrHoldPin = GPIO_NUM_46;
82 _batAdc = (adc1_channel_t) ADC1_GPIO6_CHANNEL;
83 _pmic = pmic_t::pmic_adc;
87 case board_t::board_M5DinMeter:
88 _pwrHoldPin = GPIO_NUM_46;
90 case board_t::board_M5Cardputer:
91 _batAdc = (adc1_channel_t) ADC1_GPIO10_CHANNEL;
92 _pmic = pmic_t::pmic_adc;
97 #elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
105 case board_t::board_M5TimerCam:
106 _pwrHoldPin = TimerCam_POWER_HOLD_PIN;
107 m5gfx::pinMode(TimerCam_POWER_HOLD_PIN, m5gfx::pin_mode_t::output);
108 m5gfx::gpio_hi(TimerCam_POWER_HOLD_PIN);
109 m5gfx::pinMode(TimerCam_LED_PIN, m5gfx::pin_mode_t::output);
110 m5gfx::gpio_lo(TimerCam_LED_PIN);
111 _batAdc = (adc1_channel_t) ADC1_GPIO38_CHANNEL;
112 _pmic = pmic_t::pmic_adc;
116 case board_t::board_M5StackCoreInk:
117 _pwrHoldPin = CoreInk_POWER_HOLD_PIN;
118 _wakeupPin = GPIO_NUM_27;
119 _rtcIntPin = GPIO_NUM_19;
120 _batAdc = (adc1_channel_t) ADC1_GPIO35_CHANNEL;
121 _pmic = pmic_t::pmic_adc;
122 _adc_ratio = 25.1f / 5.1f;
125 case board_t::board_M5Paper:
126 _pwrHoldPin = M5Paper_POWER_HOLD_PIN;
127 m5gfx::pinMode(M5Paper_EXT5V_ENABLE_PIN, m5gfx::pin_mode_t::output);
128 _wakeupPin = GPIO_NUM_36;
129 _batAdc = (adc1_channel_t) ADC1_GPIO35_CHANNEL;
130 _pmic = pmic_t::pmic_adc;
134 case board_t::board_M5Tough:
135 case board_t::board_M5StackCore2:
136 _wakeupPin = GPIO_NUM_39;
137 _pmic = Power_Class::pmic_t::pmic_axp192;
140 case board_t::board_M5Station:
141 m5gfx::pinMode(GPIO_NUM_12, m5gfx::pin_mode_t::output);
142 _pmic = Power_Class::pmic_t::pmic_axp192;
145 case board_t::board_M5StickC:
146 case board_t::board_M5StickCPlus:
147 _rtcIntPin = GPIO_NUM_35;
148 _pmic = Power_Class::pmic_t::pmic_axp192;
151 case board_t::board_M5StickCPlus2:
152 _pwrHoldPin = StickCPlus2_POWER_HOLD_PIN;
153 m5gfx::pinMode(StickCPlus2_LED_PIN, m5gfx::pin_mode_t::output);
154 _batAdc = (adc1_channel_t) ADC1_GPIO38_CHANNEL;
155 _pmic = pmic_t::pmic_adc;
159 case board_t::board_M5Stack:
160 _pmic = pmic_t::pmic_ip5306;
163 static constexpr std::uint8_t reg_data_array[] =
225 if (_pmic == Power_Class::pmic_t::pmic_axp192) {
228 _pmic = Power_Class::pmic_t::pmic_axp2101;
233 if (_pmic == Power_Class::pmic_t::pmic_axp192)
235 static constexpr std::uint8_t reg_data_array[] =
289 case board_t::board_M5StickC:
290 case board_t::board_M5StickCPlus:
296 case board_t::board_M5StackCore2:
305 case board_t::board_M5Tough:
311 case board_t::board_M5Station:
313 static constexpr std::uint8_t reg92h_96h[] =
328 else if (_pmic == Power_Class::pmic_t::pmic_axp2101)
331 static constexpr std::uint8_t reg_data_array[] =
350 if (_pwrHoldPin < GPIO_NUM_MAX)
352 gpio_hold_en( (gpio_num_t)_pwrHoldPin );
355 return (_pmic != pmic_t::pmic_unknown);
358 #if defined (CONFIG_IDF_TARGET_ESP32S3)
360 static constexpr
const uint32_t _core_s3_bus_en = 0b00000010;
361 static constexpr
const uint32_t _core_s3_usb_en = 0b00100000;
362 static void _core_s3_output(uint8_t mask,
bool enable)
364 static constexpr
const uint8_t port0_reg = 0x02;
366 static constexpr
const uint32_t port1_bitmask_boost = 0b10000000;
372 uint8_t p0 = buf[0] | mask;
373 uint8_t p1 = buf[1] | port1_bitmask_boost;
378 if (0 == (p0 & _core_s3_bus_en))
380 p1 &= ~port1_bitmask_boost;
399 #if defined (M5UNIFIED_PC_BUILD)
400 #elif defined (CONFIG_IDF_TARGET_ESP32S3)
401 case board_t::board_M5StackCoreS3:
403 _core_s3_output(_core_s3_bus_en, enable);
407 #elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
408 case board_t::board_M5Paper:
409 if (enable) { m5gfx::gpio_hi(M5Paper_EXT5V_ENABLE_PIN); }
410 else { m5gfx::gpio_lo(M5Paper_EXT5V_ENABLE_PIN); }
413 case board_t::board_M5StackCore2:
414 case board_t::board_M5Tough:
434 ESP_LOGW(
"Power",
"setExtPower(true) is canceled.");
440 case board_t::board_M5StickC:
441 case board_t::board_M5StickCPlus:
445 case board_t::board_M5Station:
446 for (
int i = 0; i < 5; ++i)
452 if (enable) { m5gfx::gpio_hi(GPIO_NUM_12); }
453 else { m5gfx::gpio_lo(GPIO_NUM_12); }
470 #if defined (M5UNIFIED_PC_BUILD)
471 #elif defined (CONFIG_IDF_TARGET_ESP32S3)
472 case board_t::board_M5StackCoreS3:
474 static constexpr
const uint32_t port0_bitmask = 0b00000010;
475 static constexpr
const uint8_t port0_reg = 0x02;
480 #elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
481 case board_t::board_M5Paper:
482 return m5gfx::gpio_in(M5Paper_EXT5V_ENABLE_PIN);
485 case board_t::board_M5StackCore2:
491 case board_t::board_M5Tough:
492 case board_t::board_M5StickC:
493 case board_t::board_M5StickCPlus:
494 case board_t::board_M5Station:
507 #if defined (CONFIG_IDF_TARGET_ESP32S3)
510 case board_t::board_M5StackCoreS3:
511 _core_s3_output(_core_s3_usb_en, enable);
522 #if defined (CONFIG_IDF_TARGET_ESP32S3)
525 case board_t::board_M5StackCoreS3:
527 static constexpr
const uint8_t reg = 0x02;
541 #if defined (M5UNIFIED_PC_BUILD)
542 #elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
543 static std::unique_ptr<m5gfx::Light_PWM> led;
547 case board_t::board_M5StackCore2:
551 case board_t::board_M5StackCoreInk:
552 case board_t::board_M5StickC:
553 case board_t::board_M5StickCPlus:
554 case board_t::board_M5StickCPlus2:
555 case board_t::board_M5TimerCam:
557 if (led.get() ==
nullptr)
559 led.reset(
new m5gfx::Light_PWM());
560 auto cfg = led->config();
566 case board_t::board_M5StickCPlus2:
567 cfg.pin_bl = StickCPlus2_LED_PIN;
572 case board_t::board_M5TimerCam:
573 cfg.pin_bl = TimerCam_LED_PIN;
578 cfg.pin_bl = GPIO_NUM_10;
582 led->init(brightness);
584 led->setBrightness(brightness);
594 void Power_Class::_powerOff(
bool withTimer)
596 #if !defined (M5UNIFIED_PC_BUILD)
597 bool use_deepsleep =
true;
598 if (withTimer && _rtcIntPin < GPIO_NUM_MAX)
600 gpio_num_t pin = (gpio_num_t)_rtcIntPin;
601 #if SOC_PM_SUPPORT_EXT_WAKEUP
602 if (ESP_OK != esp_sleep_enable_ext0_wakeup( pin,
false))
605 gpio_wakeup_enable( pin, gpio_int_type_t::GPIO_INTR_LOW_LEVEL);
606 esp_sleep_enable_gpio_wakeup();
607 use_deepsleep =
false;
614 #if defined (CONFIG_IDF_TARGET_ESP32C3)
616 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
618 case pmic_t::pmic_axp192:
622 case pmic_t::pmic_ip5306:
628 case pmic_t::pmic_axp2101:
634 case pmic_t::pmic_unknown:
640 if (_pwrHoldPin < GPIO_NUM_MAX)
642 m5gfx::gpio_lo( _pwrHoldPin );
645 if (use_deepsleep) { esp_deep_sleep_start(); }
646 esp_light_sleep_start();
651 void Power_Class::_timerSleep(
void)
653 #if !defined (M5UNIFIED_PC_BUILD)
655 if (_pwrHoldPin < GPIO_NUM_MAX)
657 gpio_hold_dis( (gpio_num_t)_pwrHoldPin );
662 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
665 case board_t::board_M5StickC:
666 case board_t::board_M5StickCPlus:
671 m5gfx::pinMode(GPIO_NUM_35, m5gfx::pin_mode_t::input);
672 for (
int i = 1; i >= 0; --i) {
674 if (m5gfx::gpio_in(GPIO_NUM_35)) {
break; }
676 esp_sleep_enable_ext0_wakeup(GPIO_NUM_35, 0);
677 esp_deep_sleep_start();
681 case board_t::board_M5StackCore2:
682 case board_t::board_M5Tough:
698 #if !defined (M5UNIFIED_PC_BUILD)
699 ESP_LOGD(
"Power",
"deepSleep");
700 #if defined (CONFIG_IDF_TARGET_ESP32C3)
704 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
705 if (_pmic == pmic_t::pmic_ip5306)
711 uint_fast8_t wpin = _wakeupPin;
712 if (touch_wakeup && wpin < GPIO_NUM_MAX)
714 esp_sleep_enable_ext0_wakeup((gpio_num_t)wpin,
false);
715 while (m5gfx::gpio_in(wpin) ==
false)
720 if (micro_seconds > 0)
722 esp_sleep_enable_timer_wakeup(micro_seconds);
726 esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
729 esp_deep_sleep_start();
735 #if !defined (M5UNIFIED_PC_BUILD)
736 ESP_LOGD(
"Power",
"lightSleep");
737 #if defined (CONFIG_IDF_TARGET_ESP32C3)
741 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
742 if (_pmic == pmic_t::pmic_ip5306)
748 uint_fast8_t wpin = _wakeupPin;
749 if (touch_wakeup && wpin < GPIO_NUM_MAX)
751 esp_sleep_enable_ext0_wakeup((gpio_num_t)wpin,
false);
752 esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO);
753 while (m5gfx::gpio_in(wpin) ==
false)
758 if (micro_seconds > 0){
759 esp_sleep_enable_timer_wakeup(micro_seconds);
761 esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
764 esp_light_sleep_start();
779 #if !defined (M5UNIFIED_PC_BUILD)
780 esp_sleep_enable_timer_wakeup(seconds * 1000000ULL);
799 #if !defined (M5UNIFIED_PC_BUILD)
801 static std::int32_t getBatteryAdcRaw(adc1_channel_t adc_ch)
803 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32) || defined (CONFIG_IDF_TARGET_ESP32S3)
804 static constexpr
int BASE_VOLATAGE = 3600;
806 static esp_adc_cal_characteristics_t* adc_chars =
nullptr;
807 if (adc_chars ==
nullptr)
809 adc1_config_width(ADC_WIDTH_BIT_12);
810 adc1_config_channel_atten(adc_ch, ADC_ATTEN_DB_11);
811 adc_chars = (esp_adc_cal_characteristics_t*)calloc(1,
sizeof(esp_adc_cal_characteristics_t));
812 esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, BASE_VOLATAGE, adc_chars);
814 return esp_adc_cal_raw_to_voltage(adc1_get_raw(adc_ch), adc_chars);
824 #if !defined (M5UNIFIED_PC_BUILD)
828 #if defined (CONFIG_IDF_TARGET_ESP32C3)
830 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
831 case pmic_t::pmic_ip5306:
834 case pmic_t::pmic_axp192:
839 case pmic_t::pmic_axp2101:
844 case pmic_t::pmic_adc:
845 return getBatteryAdcRaw(_batAdc) * _adc_ratio;
856 #if defined (M5UNIFIED_PC_BUILD)
863 #if defined (CONFIG_IDF_TARGET_ESP32C3)
865 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
866 case pmic_t::pmic_ip5306:
869 case pmic_t::pmic_axp192:
875 case pmic_t::pmic_axp2101:
881 case pmic_t::pmic_adc:
882 mv = getBatteryAdcRaw(_batAdc) * _adc_ratio;
889 int level = (mv - 3300) * 100 / (
float)(4150 - 3350);
891 return (level < 0) ? 0
892 : (level >= 100) ? 100
901 #if defined (CONFIG_IDF_TARGET_ESP32C3)
903 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
904 case pmic_t::pmic_ip5306:
908 case pmic_t::pmic_axp192:
914 case pmic_t::pmic_axp2101:
929 #if defined (CONFIG_IDF_TARGET_ESP32C3)
931 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
932 case pmic_t::pmic_ip5306:
936 case pmic_t::pmic_axp192:
942 case pmic_t::pmic_axp2101:
957 #if defined (CONFIG_IDF_TARGET_ESP32C3)
960 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
961 case pmic_t::pmic_axp192:
965 if (res < dsc) res = -dsc;
970 case pmic_t::pmic_axp2101:
972 #if defined (CONFIG_IDF_TARGET_ESP32S3)
994 #if defined (CONFIG_IDF_TARGET_ESP32C3)
996 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
998 case pmic_t::pmic_ip5306:
1002 case pmic_t::pmic_axp192:
1008 case pmic_t::pmic_axp2101:
1023 #if defined (CONFIG_IDF_TARGET_ESP32C3)
1025 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
1027 case pmic_t::pmic_ip5306:
1028 return Ip5306.
isCharging() ? is_charging_t::is_charging : is_charging_t::is_discharging;
1030 case pmic_t::pmic_axp192:
1031 return Axp192.
isCharging() ? is_charging_t::is_charging : is_charging_t::is_discharging;
1035 case pmic_t::pmic_axp2101:
1036 return Axp2101.
isCharging() ? is_charging_t::is_charging : is_charging_t::is_discharging;
1042 return is_charging_t::charge_unknown;
1051 #if defined (CONFIG_IDF_TARGET_ESP32C3)
1053 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
1055 case pmic_t::pmic_axp192:
1060 case pmic_t::pmic_axp2101:
1072 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
1073 if (
M5.
getBoard() == board_t::board_M5StackCore2)
1075 uint32_t mv = level ? 480 + level * 12 : 0;
1078 case pmic_t::pmic_axp192:
1082 case pmic_t::pmic_axp2101:
m5::M5Unified M5
global instance.
float getBatteryVoltage(void)
void setDCDC3(int voltage)
void setLDO2(int voltage)
void setGPIO(uint8_t gpio_num, bool state)
std::int8_t getBatteryLevel(void)
std::uint8_t getPekPress(void)
float getVBUSCurrent(void)
void setLDO3(int voltage)
bool isCharging(void)
Get whether the battery is currently charging or not.
void setChargeCurrent(std::uint16_t max_mA)
void setBatteryCharge(bool enable)
void setChargeVoltage(std::uint16_t max_mV)
float getBatteryChargeCurrent(void)
void setGPIO2(bool state)
void setEXTEN(bool enable)
float getBatteryDischargeCurrent(void)
float getBatteryVoltage(void)
std::uint8_t getPekPress(void)
bool isCharging(void)
Get whether the battery is currently charging or not.
void setBatteryCharge(bool enable)
std::int8_t getBatteryLevel(void)
void setChargeCurrent(std::uint16_t max_mA)
void setDLDO1(int voltage)
bool getBLDO2Enabled(void)
void setChargeVoltage(std::uint16_t max_mV)
void setBLDO2(int voltage)
std::uint8_t readRegister8(std::uint8_t address, std::uint8_t reg, std::uint32_t freq) const
bool bitOn(std::uint8_t address, std::uint8_t reg, std::uint8_t data, std::uint32_t freq) const
bool writeRegister(std::uint8_t address, std::uint8_t reg, const std::uint8_t *data, std::size_t length, std::uint32_t freq) const
bool readRegister(std::uint8_t address, std::uint8_t reg, std::uint8_t *result, std::size_t length, std::uint32_t freq) const
bool writeRegister8Array(const std::uint8_t *reg_data_array, std::size_t length) const
bool writeRegister8(std::uint8_t reg, std::uint8_t data) const
bool writeRegister(std::uint8_t reg, const std::uint8_t *data, std::size_t length) const
bool setINTPinActiveLogic(bool level)
float getShuntVoltage(uint8_t channel)
float getCurrent(uint8_t channel)
std::int8_t getBatteryLevel(void)
void setChargeVoltage(std::uint16_t max_mV)
void setBatteryCharge(bool enable)
void setChargeCurrent(std::uint16_t max_mA)
bool isCharging(void)
Get whether the battery is currently charging or not.
bool setPowerBoostKeepOn(bool en)
Set whether or not to continue supplying power even at low loads.
board_t getBoard(void) const
I2C_Class & In_I2C
for internal I2C device
void setExtOutput(bool enable, ext_port_mask_t port_mask=(ext_port_mask_t) 0xFF)
void timerSleep(int seconds)
std::int32_t getBatteryLevel(void)
int32_t getBatteryCurrent(void)
void setChargeCurrent(std::uint16_t max_mA)
void setVibration(uint8_t level)
void deepSleep(std::uint64_t micro_seconds=0, bool touch_wakeup=true)
void setLed(uint8_t brightness=255)
is_charging_t isCharging(void)
void lightSleep(std::uint64_t micro_seconds=0, bool touch_wakeup=true)
void setUsbOutput(bool enable)
int16_t getBatteryVoltage(void)
uint8_t getKeyState(void)
void setBatteryCharge(bool enable)
void powerOff(void)
all power off.
void setChargeVoltage(std::uint16_t max_mV)
int setAlarmIRQ(int afterSeconds)