mirror of
https://github.com/m5stack/M5PM1.git
synced 2026-05-20 11:49:32 -07:00
1. Add examples and fix some code
This commit is contained in:
@@ -8,7 +8,8 @@ M5PM1 is a dual-platform (ESP-IDF & Arduino) driver library for M5Stack PM1 Powe
|
||||
|
||||
## Related Link
|
||||
|
||||
- N/A
|
||||
- [README_FUNCTION_CN](README_FUNCTION_CN.md)
|
||||
- [README_FUNCTION_EN](README_FUNCTION_EN.md)
|
||||
|
||||
## Required Libraries:
|
||||
|
||||
@@ -18,8 +19,8 @@ M5PM1 is a dual-platform (ESP-IDF & Arduino) driver library for M5Stack PM1 Powe
|
||||
|
||||
- examples/basic_power_adc/basic_power_adc.ino
|
||||
- examples/gpio_pwm/gpio_pwm.ino
|
||||
- examples/interrupt_button_sleep/interrupt_button_sleep.ino
|
||||
- examples/neopixel/neopixel.ino
|
||||
- examples/usb_interrupt_sleep/usb_interrupt_sleep.ino
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+13
-9
@@ -4,7 +4,7 @@
|
||||
|
||||
- **版本**: 1.0.1
|
||||
- **默认 I2C 地址**: `0x6E`
|
||||
- **I2C 速度**: 默认 100 kHz,可切换 400 kHz(切换后需重新初始化 I2C)
|
||||
- **I2C 速度**: 默认 100 kHz,可切换 400 kHz(切换后库内部会处理 I2C 重建)
|
||||
|
||||
## 项目结构与角色
|
||||
|
||||
@@ -86,8 +86,8 @@
|
||||
### 10) 按钮
|
||||
|
||||
- `btnSetConfig`/`btnGetState`/`btnGetFlag`
|
||||
- `setSingleResetDisable`/`getSingleResetDisable`
|
||||
- `setDoubleOffDisable`/`getDoubleOffDisable`
|
||||
- `setSingleResetDisable`(高危)/`getSingleResetDisable`
|
||||
- `setDoubleOffDisable`(高危)/`getDoubleOffDisable`
|
||||
|
||||
### 11) 中断
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
### 12) 系统命令
|
||||
|
||||
- `sysCmd`/`shutdown`/`reboot`/`enterDownloadMode`
|
||||
- `setDownloadLock`/`getDownloadLock`
|
||||
- `setDownloadLock`(高危)/`getDownloadLock`
|
||||
|
||||
### 13) NeoPixel
|
||||
|
||||
@@ -134,17 +134,21 @@
|
||||
- `getCachedPowerConfig`/`getCachedButtonConfig`
|
||||
- `getCachedIrqMasks`/`getCachedIrqStatus`
|
||||
|
||||
## 注意事项
|
||||
|
||||
如果使用 `setDownloadLock`、`setSingleResetDisable`、`setDoubleOffDisable` 高危函数导致无法启用烧录、单击复位、双击关断,请拔插电池(内置电池设备可能损坏壳体和器件)或快速短接 BAT 和 GND(此操作可能损坏电池)。
|
||||
|
||||
## 引脚与功能限制
|
||||
|
||||
| 功能区域 | 说明 | 备注 |
|
||||
| :--- | :--- | :--- |
|
||||
| **GPIO 互斥** | GPIO0/2 共享 WAKE/IRQ 线;GPIO3/4 互斥 | GPIO0/2 互斥 |
|
||||
| **唤醒 (WAKE)** | GPIO0, GPIO2 支持唤醒 | GPIO1 不支持 WAKE |
|
||||
| **WAKE 互斥** | GPIO0/2 互斥;GPIO3/4 互斥 | 仅 WAKE 功能生效 |
|
||||
| **唤醒 (WAKE)** | GPIO0/2/3/4 支持唤醒 | GPIO1 不支持 WAKE |
|
||||
| **ADC 通道** | GPIO1=ADC1, GPIO2=ADC2 | 温度为内部通道 |
|
||||
| **PWM 通道** | GPIO3=PWM0, GPIO4=PWM1 | 频率全通道共享 |
|
||||
| **NeoPixel** | 数据区 0x60 - 0x9F | 刷新时 I2C 短暂不可中断 |
|
||||
| **I2C 休眠** | 空闲超时可进入低功耗 | PWM 使能或下载模式下禁止休眠 |
|
||||
| **寄存器区块** | 0x00 - 0x0C, 0x10 - 0x19, 0x20 - 0x2A, 0x30 - 0x35 0x38 - 0x3D, 0x40 - 0x45, 0x48 - 0x4A, 0x50 0x53, 0x60 - 0x9F, 0xA0 - 0xBF | 支持连续读写 |
|
||||
| **NeoPixel** | 仅 GPIO0 支持;LED 数量 1-31;数据区 0x60 - 0x9F | 刷新时 I2C 短暂不可中断 |
|
||||
| **I2C 休眠** | 空闲超时可进入低功耗 | PWM 使能或下载模式下休眠失效 |
|
||||
| **寄存器区块** | 0x00 - 0x0C, 0x10 - 0x19, 0x20 - 0x2A, 0x30 - 0x35, 0x38 - 0x3D, 0x40 - 0x45, 0x48 - 0x4A, 0x50, 0x53, 0x60 - 0x9F, 0xA0 - 0xBF | 支持连续读写 |
|
||||
|
||||
## 版本与依赖
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
# M5PM1 Function Overview (English)
|
||||
|
||||
Feature overview of the PM1 power management driver library for Arduino/ESP-IDF.
|
||||
|
||||
- **Version**: 1.0.1
|
||||
- **Default I2C address**: `0x6E`
|
||||
- **I2C speed**: Default 100 kHz, can switch to 400 kHz (the library rebuilds I2C internally after switching)
|
||||
|
||||
## Project Structure and Roles
|
||||
|
||||
- `src/M5PM1.h`: Public APIs, registers/enums, cache structure definitions.
|
||||
- `src/M5PM1.cpp`: Driver implementation, conflict checks, snapshot and cache logic.
|
||||
- `src/M5PM1_i2c_compat.h`: Arduino/ESP-IDF I2C compatibility wrapper.
|
||||
|
||||
## Examples
|
||||
|
||||
- `examples/basic_power_adc/basic_power_adc.ino`: Initialization, device info, VBAT/VIN/5V readings, ADC/temperature sampling, power rail control.
|
||||
- `examples/gpio_pwm/gpio_pwm.ino`: GPIO output/input reads and PWM breathing LED demo.
|
||||
- `examples/interrupt_button_sleep/interrupt_button_sleep.ino`: GPIO interrupt, button APIs, timer/wake, and shutdown demo.
|
||||
- `examples/neopixel/neopixel.ino`: NeoPixel rainbow demo.
|
||||
|
||||
## Feature Categories
|
||||
|
||||
### 1) Initialization and Logging
|
||||
|
||||
- **Initialization**
|
||||
- Arduino: `begin(TwoWire*, addr, sda, scl, speed)`
|
||||
- ESP-IDF: `begin(i2c_port_t, addr, sda, scl, speed)`
|
||||
- ESP-IDF: `begin(i2c_master_bus_handle_t, addr, speed)`
|
||||
- ESP-IDF: `begin(i2c_bus_handle_t, addr, speed)`
|
||||
- **Logging**
|
||||
- `setLogLevel`/`getLogLevel`
|
||||
|
||||
### 2) Device Information
|
||||
|
||||
- `getDeviceId`/`getDeviceModel`/`getHwVersion`/`getSwVersion`
|
||||
|
||||
### 3) GPIO Basics and Advanced Control
|
||||
|
||||
- **Arduino style**
|
||||
- `pinMode`/`digitalWrite`/`digitalRead`
|
||||
- **With return status**
|
||||
- `pinModeWithRes`/`digitalWriteWithRes`/`digitalReadWithRes`
|
||||
- **Advanced configuration**
|
||||
- `gpioSet`/`gpioSetFunc`/`gpioSetMode`/`gpioSetOutput`/`gpioGetInput`
|
||||
- `gpioSetPull`/`gpioSetDrive`/`ledEnSetDrive`
|
||||
- `gpioSetWakeEnable`/`gpioSetWakeEdge`
|
||||
- **Pin status and validation**
|
||||
- `dumpPinStatus`/`verifyPinConfig`/`getPinStatus`/`getPinStatusArray`
|
||||
|
||||
### 4) Power Hold
|
||||
|
||||
- `gpioSetPowerHold`/`gpioGetPowerHold`
|
||||
- `ldoSetPowerHold`/`ldoGetPowerHold`
|
||||
- `dcdcSetPowerHold`/`dcdcGetPowerHold`
|
||||
|
||||
### 5) ADC and Temperature
|
||||
|
||||
- `analogRead`/`isAdcBusy`/`disableAdc`/`readTemperature`
|
||||
|
||||
### 6) PWM
|
||||
|
||||
- `setPwmFrequency`/`getPwmFrequency`
|
||||
- `setPwmDuty`/`getPwmDuty` (0-100%)
|
||||
- `setPwmDuty12bit`/`getPwmDuty12bit` (0-4095)
|
||||
- `setPwmConfig`
|
||||
- `analogWrite` (0-255)
|
||||
|
||||
### 7) Voltage Reading
|
||||
|
||||
- `readVref`/`getRefVoltage`/`readVbat`/`readVin`/`read5VInOut`
|
||||
|
||||
### 8) Power Management and Battery
|
||||
|
||||
- `getPowerSource`
|
||||
- `getWakeSource`/`clearWakeSource`
|
||||
- `setPowerConfig`/`getPowerConfig`/`clearPowerConfig`
|
||||
- `setChargeEnable`/`setDcdcEnable`/`setLdoEnable`/`set5VInOutEnable`/`setLedEnLevel`
|
||||
- `setBatteryLvp`
|
||||
|
||||
### 9) Watchdog and Timer
|
||||
|
||||
- `wdtSet`/`wdtFeed`/`wdtGetCount`
|
||||
- `timerSet`/`timerClear`
|
||||
|
||||
### 10) Button
|
||||
|
||||
- `btnSetConfig`/`btnGetState`/`btnGetFlag`
|
||||
- `setSingleResetDisable` (High risk)/`getSingleResetDisable`
|
||||
- `setDoubleOffDisable` (High risk)/`getDoubleOffDisable`
|
||||
|
||||
### 11) Interrupts
|
||||
|
||||
- **Status read and clear**
|
||||
- `irqGetGpioStatus`/`irqClearGpio`
|
||||
- `irqGetSysStatus`/`irqClearSys`
|
||||
- `irqGetBtnStatus`/`irqClearBtn`
|
||||
- **Enum-style read**
|
||||
- `irqGetGpioStatusEnum`/`irqGetSysStatusEnum`/`irqGetBtnStatusEnum`
|
||||
- **Interrupt masks**
|
||||
- `irqSetGpioMask`/`irqGetGpioMask`/`irqSetGpioMaskAll`/`irqGetGpioMaskAll`
|
||||
- `irqSetSysMask`/`irqGetSysMask`/`irqSetSysMaskAll`/`irqGetSysMaskAll`
|
||||
- `irqSetBtnMask`/`irqGetBtnMask`/`irqSetBtnMaskAll`/`irqGetBtnMaskAll`
|
||||
|
||||
### 12) System Commands
|
||||
|
||||
- `sysCmd`/`shutdown`/`reboot`/`enterDownloadMode`
|
||||
- `setDownloadLock` (High risk)/`getDownloadLock`
|
||||
|
||||
### 13) NeoPixel
|
||||
|
||||
- `setLeds`/`setLedCount`/`setLedColor`/`refreshLeds`/`disableLeds`
|
||||
|
||||
### 14) AW8737A Pulse Control
|
||||
|
||||
- `setAw8737aPulse`/`refreshAw8737aPulse`
|
||||
|
||||
### 15) RTC RAM
|
||||
|
||||
- `writeRtcRAM`/`readRtcRAM`
|
||||
|
||||
### 16) I2C Configuration and Auto Wake
|
||||
|
||||
- `setI2cConfig`/`switchI2cSpeed`/`getI2cSpeed`
|
||||
- `setI2cSleepTime`/`getI2cSleepTime`
|
||||
- `setAutoWakeEnable`/`isAutoWakeEnabled`/`sendWakeSignal`
|
||||
- Compatibility layer: `M5PM1_i2c_compat.h`
|
||||
|
||||
### 17) State Snapshot/Cache/Validation
|
||||
|
||||
- `setAutoSnapshot`/`isAutoSnapshotEnabled`/`updateSnapshot`/`verifySnapshot`
|
||||
- `validateConfig`
|
||||
- `getCachedPwmFrequency`/`getCachedPwmState`/`getCachedAdcState`
|
||||
- `getCachedPowerConfig`/`getCachedButtonConfig`
|
||||
- `getCachedIrqMasks`/`getCachedIrqStatus`
|
||||
|
||||
## Precautions
|
||||
|
||||
If using high-risk functions `setDownloadLock`, `setSingleResetDisable`, or `setDoubleOffDisable` results in the inability to enable download mode, single-click reset, or double-click shutdown, please disconnect/reconnect the battery (devices with built-in batteries may risk damage to the casing and components) or quickly short BAT and GND (this operation may damage the battery).
|
||||
|
||||
## Pin and Function Limits
|
||||
|
||||
| Area | Description | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| **WAKE mutual exclusion** | GPIO0/2 are mutually exclusive; GPIO3/4 are mutually exclusive | Only for WAKE function |
|
||||
| **Wake (WAKE)** | GPIO0/2/3/4 support wake | GPIO1 does not support WAKE |
|
||||
| **ADC channels** | GPIO1=ADC1, GPIO2=ADC2 | Temperature is an internal channel |
|
||||
| **PWM channels** | GPIO3=PWM0, GPIO4=PWM1 | Frequency shared across channels |
|
||||
| **NeoPixel** | GPIO0 only; LED count 1-31; data area 0x60 - 0x9F | I2C briefly non-interruptible during refresh |
|
||||
| **I2C sleep** | Idle timeout can enter low power | Sleep is ineffective when PWM is enabled or in download mode |
|
||||
| **Register blocks** | 0x00 - 0x0C, 0x10 - 0x19, 0x20 - 0x2A, 0x30 - 0x35, 0x38 - 0x3D, 0x40 - 0x45, 0x48 - 0x4A, 0x50, 0x53, 0x60 - 0x9F, 0xA0 - 0xBF | Supports continuous read/write |
|
||||
|
||||
## Version and Dependencies
|
||||
|
||||
- **Version**: 1.0.1
|
||||
- **Platforms**: Arduino / ESP-IDF (>=4.4)
|
||||
- **Dependency**: espressif/i2c_bus
|
||||
+60
-57
@@ -8,14 +8,20 @@
|
||||
#include <M5PM1.h>
|
||||
|
||||
/*
|
||||
* 中断/按键/关机与唤醒示例。
|
||||
* Interrupt/button/sleep & wake demo.
|
||||
* USB拔插中断/关机与唤醒示例。
|
||||
* USB Plug/Unplug Interrupt/Shutdown & Wake Demo.
|
||||
*
|
||||
* IRQ_GPIO=GPIO2 用于外部中断/唤醒输入;GPIO0/2 共用线,勿同时启用唤醒。
|
||||
* IRQ_GPIO=GPIO2 for external IRQ/wake; GPIO0/2 share a line, don't enable both.
|
||||
* 功能:
|
||||
* 1. 启动时打印唤醒源。
|
||||
* 2. 运行时监听 USB (5VIN) 的拔插事件。
|
||||
* 3. 当检测到 USB 拔出 (5VIN Remove) 时,倒计时5秒后关机。
|
||||
* 4. 关机前设置10秒定时器唤醒,10秒后自动开机。
|
||||
*
|
||||
* 双击电源键触发 PM1 关机(延迟5秒),10 秒后定时唤醒。
|
||||
* Double-click power button triggers PM1 shutdown (5s delay); timer wakes after 10s.
|
||||
* Features:
|
||||
* 1. Print wake source on startup.
|
||||
* 2. Listen for USB (5VIN) plug/unplug events.
|
||||
* 3. When USB unplug (5VIN Remove) detected, shutdown after 5s countdown.
|
||||
* 4. Set 10s timer wake up before shutdown, auto wake up after 10s.
|
||||
*/
|
||||
|
||||
M5PM1 pm1;
|
||||
@@ -43,8 +49,7 @@ void IRAM_ATTR pm1_irq_handler()
|
||||
irqFlag = true;
|
||||
}
|
||||
|
||||
static const m5pm1_gpio_num_t IRQ_GPIO = M5PM1_GPIO_NUM_1;
|
||||
static const uint32_t WAKE_TIMER_SEC = 10;
|
||||
static const uint32_t WAKE_TIMER_SEC = 10;
|
||||
|
||||
static void printDivider()
|
||||
{
|
||||
@@ -65,23 +70,25 @@ static void printWakeSource(uint8_t src)
|
||||
|
||||
static void enterSleep()
|
||||
{
|
||||
LOGW("Prepare for shutdown with wake sources");
|
||||
LOGW("Prepare for shutdown...");
|
||||
|
||||
// 先配置10s的定时开机
|
||||
// Configure 10s timer wake up first
|
||||
pm1.timerSet(WAKE_TIMER_SEC, M5PM1_TIM_ACTION_POWERON);
|
||||
|
||||
// 触发双击后等待5s关机
|
||||
// Wait 5s before shutdown after double click
|
||||
LOGW("Wait 5s before shutdown...");
|
||||
delay(5000);
|
||||
// 等待5s关机
|
||||
// Wait 5s before shutdown
|
||||
for (int i = 5; i > 0; i--) {
|
||||
LOGW("Shutdown in %d s...", i);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// 关闭LED_EN灯显(将默认电平配置为低电平)
|
||||
// Turn off LED_EN indicator (by setting default level to LOW)
|
||||
pm1.setLedEnLevel(false);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
|
||||
LOGW("Shutdown now. Wake by GPIO%u or %us timer", IRQ_GPIO, WAKE_TIMER_SEC);
|
||||
LOGW("Shutdown now. Wake by %us timer", WAKE_TIMER_SEC);
|
||||
pm1.shutdown();
|
||||
}
|
||||
|
||||
@@ -90,7 +97,7 @@ void setup()
|
||||
Serial.begin(115200);
|
||||
delay(200);
|
||||
printDivider();
|
||||
LOGI("Interrupt + Button + Sleep demo start");
|
||||
LOGI("USB Interrupt + Sleep demo start");
|
||||
|
||||
m5pm1_err_t err = pm1.begin(&Wire, M5PM1_DEFAULT_ADDR, PM1_I2C_SDA, PM1_I2C_SCL, PM1_I2C_FREQ);
|
||||
if (err != M5PM1_OK) {
|
||||
@@ -111,35 +118,27 @@ void setup()
|
||||
// Clear timer settings to avoid mis-trigger.
|
||||
pm1.timerClear();
|
||||
|
||||
// 禁用单击复位/双击关机,避免与示例流程冲突。
|
||||
// Disable single-reset/double-off to avoid conflicts with demo flow.
|
||||
pm1.setSingleResetDisable(true);
|
||||
pm1.setDoubleOffDisable(true);
|
||||
|
||||
pm1.btnSetConfig(M5PM1_BTN_TYPE_CLICK, M5PM1_BTN_DELAY_250MS);
|
||||
pm1.btnSetConfig(M5PM1_BTN_TYPE_DOUBLE, M5PM1_BTN_DELAY_250MS);
|
||||
pm1.btnSetConfig(M5PM1_BTN_TYPE_LONG, M5PM1_BTN_DELAY_500MS);
|
||||
|
||||
pm1.gpioSetFunc(IRQ_GPIO, M5PM1_GPIO_FUNC_IRQ);
|
||||
pm1.gpioSetMode(IRQ_GPIO, M5PM1_GPIO_MODE_INPUT);
|
||||
pm1.gpioSetPull(IRQ_GPIO, M5PM1_GPIO_PULL_UP);
|
||||
|
||||
// 设置ESP32的中断引脚,用于接收PM1的IRQ信号。
|
||||
// Setup ESP32 interrupt pin to receive IRQ signal from PM1.
|
||||
pinMode(PM1_ESP_IRQ_GPIO, INPUT_PULLUP);
|
||||
attachInterrupt(PM1_ESP_IRQ_GPIO, pm1_irq_handler, FALLING);
|
||||
|
||||
// 启用 PM1 GPIO1 的中断输出(这里的Mask Disable代表允许产生中断)。
|
||||
// Enable PM1 GPIO1 IRQ output (Mask Disable means interrupt enabled).
|
||||
pm1.irqSetGpioMask(IRQ_GPIO, M5PM1_IRQ_MASK_DISABLE);
|
||||
|
||||
// 启用按钮中断输出。
|
||||
// Enable button IRQ output.
|
||||
pm1.irqSetBtnMaskAll(M5PM1_IRQ_MASK_DISABLE);
|
||||
// 屏蔽所有GPIO和按钮中断
|
||||
// Mask all GPIO and Button IRQs (disable them)
|
||||
pm1.irqSetGpioMaskAll(M5PM1_IRQ_MASK_ENABLE);
|
||||
pm1.irqSetSysMaskAll(M5PM1_IRQ_MASK_ENABLE);
|
||||
pm1.irqSetBtnMaskAll(M5PM1_IRQ_MASK_ENABLE);
|
||||
|
||||
// 配置系统中断:只启用 VIN 移除中断(也可以全部开启)
|
||||
// Configure System IRQs: Enable VIN remove interrupt
|
||||
pm1.irqSetSysMaskAll(M5PM1_IRQ_MASK_ENABLE); // 先全部屏蔽
|
||||
pm1.irqSetSysMask(M5PM1_IRQ_SYS_5VIN_REMOVE, M5PM1_IRQ_MASK_DISABLE); // 开启5VIN移除
|
||||
// pm1.irqSetSysMask(M5PM1_IRQ_SYS_5VIN_INSERT, M5PM1_IRQ_MASK_DISABLE); // 可选开启插入
|
||||
|
||||
// 注意:有些板子 TypeC 可能连接到 5VINOUT
|
||||
pm1.irqSetSysMask(M5PM1_IRQ_SYS_5VINOUT_REMOVE, M5PM1_IRQ_MASK_DISABLE);
|
||||
|
||||
printDivider();
|
||||
LOGI("Waiting for USB unplug event...");
|
||||
}
|
||||
|
||||
void loop()
|
||||
@@ -147,30 +146,34 @@ void loop()
|
||||
if (irqFlag) {
|
||||
irqFlag = false;
|
||||
|
||||
uint8_t gpioIrq = 0;
|
||||
if (pm1.irqGetGpioStatus(&gpioIrq, M5PM1_CLEAN_ONCE) == M5PM1_OK) {
|
||||
if (gpioIrq != M5PM1_IRQ_GPIO_NONE) {
|
||||
LOGI("GPIO IRQ status: 0x%02X", gpioIrq);
|
||||
if (gpioIrq & M5PM1_IRQ_GPIO0) LOGI("- GPIO0 IRQ triggered");
|
||||
if (gpioIrq & M5PM1_IRQ_GPIO1) LOGI("- GPIO1 IRQ triggered");
|
||||
if (gpioIrq & M5PM1_IRQ_GPIO2) LOGI("- GPIO2 IRQ triggered");
|
||||
if (gpioIrq & M5PM1_IRQ_GPIO3) LOGI("- GPIO3 IRQ triggered");
|
||||
if (gpioIrq & M5PM1_IRQ_GPIO4) LOGI("- GPIO4 IRQ triggered");
|
||||
uint8_t sysIrq = 0;
|
||||
if (pm1.irqGetSysStatus(&sysIrq, M5PM1_CLEAN_ONCE) == M5PM1_OK) {
|
||||
if (sysIrq != M5PM1_IRQ_SYS_NONE) {
|
||||
LOGI("System IRQ status: 0x%02X", sysIrq);
|
||||
|
||||
// 检测 5VIN 移除
|
||||
if (sysIrq & M5PM1_IRQ_SYS_5VIN_REMOVE) {
|
||||
LOGI("Event: 5VIN Removed");
|
||||
enterSleep();
|
||||
}
|
||||
|
||||
// 检测 5VINOUT 移除 (以防万一)
|
||||
if (sysIrq & M5PM1_IRQ_SYS_5VINOUT_REMOVE) {
|
||||
LOGI("Event: 5VINOUT Removed");
|
||||
enterSleep();
|
||||
}
|
||||
|
||||
if (sysIrq & M5PM1_IRQ_SYS_5VIN_INSERT) {
|
||||
LOGI("Event: 5VIN Inserted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t btnIrq = 0;
|
||||
if (pm1.irqGetBtnStatus(&btnIrq, M5PM1_CLEAN_ONCE) == M5PM1_OK) {
|
||||
if (btnIrq != M5PM1_IRQ_BTN_NONE) {
|
||||
LOGI("Button IRQ status: 0x%02X", btnIrq);
|
||||
if (btnIrq & M5PM1_IRQ_BTN_CLICK) LOGI("- Single Click triggered");
|
||||
if (btnIrq & M5PM1_IRQ_BTN_DOUBLE) {
|
||||
LOGI("- Double Click triggered");
|
||||
enterSleep();
|
||||
}
|
||||
if (btnIrq & M5PM1_IRQ_BTN_WAKE) LOGI("- Wake Button triggered");
|
||||
}
|
||||
}
|
||||
// 同时也清除任何可能的误触发(虽然我们mask了btn和gpio)
|
||||
uint8_t dummy;
|
||||
pm1.irqGetGpioStatus(&dummy, M5PM1_CLEAN_ALL);
|
||||
pm1.irqGetBtnStatus(&dummy, M5PM1_CLEAN_ALL);
|
||||
|
||||
} else if (digitalRead(PM1_ESP_IRQ_GPIO) == LOW) {
|
||||
// 存在未处理的中断信号,读取以清除(但忽略内容)
|
||||
// Unhandled IRQ signal exists, read to clear (but ignore content)
|
||||
@@ -3575,6 +3575,7 @@ m5pm1_err_t M5PM1::sysCmd(m5pm1_sys_cmd_t cmd)
|
||||
M5PM1_LOG_E(TAG, "Not initialized");
|
||||
return M5PM1_ERR_NOT_INIT;
|
||||
}
|
||||
M5PM1_DELAY_MS(100);
|
||||
uint8_t val = M5PM1_SYS_CMD_KEY | (uint8_t)cmd;
|
||||
if (!_writeReg(M5PM1_REG_SYS_CMD, val)) {
|
||||
return M5PM1_ERR_I2C_COMM;
|
||||
@@ -3606,6 +3607,13 @@ m5pm1_err_t M5PM1::setDownloadLock(bool lock)
|
||||
uint8_t regVal;
|
||||
if (!_readReg(M5PM1_REG_BTN_CFG_1, ®Val)) return M5PM1_ERR_I2C_COMM;
|
||||
|
||||
// 检查锁定逻辑: 一旦锁定(变为1),除断电外无法解锁(变为0)
|
||||
// Check lock logic: Once locked (set to 1), it cannot be unlocked (set to 0) until power cycle
|
||||
if ((regVal & 0x80) && !lock) {
|
||||
M5PM1_LOG_E(TAG, "Download lock is permanent until power cycle");
|
||||
return M5PM1_ERR_RULE_VIOLATION;
|
||||
}
|
||||
|
||||
if (lock) {
|
||||
regVal |= 0x80; // DL_LOCK is bit 7
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user