diff --git a/examples/interrupt_hardware/interrupt_hardware.ino b/examples/interrupt_hardware/interrupt_hardware.ino index 6c0705a..d360da6 100644 --- a/examples/interrupt_hardware/interrupt_hardware.ino +++ b/examples/interrupt_hardware/interrupt_hardware.ino @@ -5,51 +5,63 @@ */ /* + * M5IOE1 硬件中断示例 * M5IOE1 Hardware Interrupt Example * + * 本示例演示如何使用 M5IOE1 库的硬件中断模式 * This example demonstrates how to use the M5IOE1 library in HARDWARE * interrupt mode with a physical INT pin connected to GPIO1 of the host MCU. * + * 硬件连接 * Hardware Connections: - * - M5IOE1 SDA -> GPIO 38 (default, configurable) - * - M5IOE1 SCL -> GPIO 39 (default, configurable) - * - M5IOE1 INT -> GPIO 1 (host MCU interrupt pin) - * - IO1 (M5IOE1) -> Button or switch (connect to GND for active LOW) + * - M5IOE1 SDA -> GPIO 38 (默认,可配置) (default, configurable) + * - M5IOE1 SCL -> GPIO 39 (默认,可配置) (default, configurable) + * - M5IOE1 INT -> GPIO 1 (主机 MCU 中断引脚) (host MCU interrupt pin) + * - IO1 (M5IOE1) -> 按钮或开关 (连接到 GND 为低电平有效) (Button or switch, connect to GND for active LOW) * + * 演示功能 * Features demonstrated: - * - Initializing M5IOE1 with hardware interrupt pin (INT_PIN) - * - Using HARDWARE interrupt mode for instant response - * - Attaching multiple interrupt callbacks to different pins - * - Using attachInterruptArg() for callback with custom data - * - Interrupt enable/disable control - * - Reading interrupt status registers + * - 使用硬件中断引脚初始化 M5IOE1 (INT_PIN) (Initializing M5IOE1 with hardware interrupt pin) + * - 使用硬件中断模式实现即时响应 (Using HARDWARE interrupt mode for instant response) + * - 为不同引脚附加多个中断回调 (Attaching multiple interrupt callbacks to different pins) + * - 使用 attachInterruptArg() 进行带自定义数据的回调 (Using attachInterruptArg() for callback with custom data) + * - 中断启用/禁用控制 (Interrupt enable/disable control) + * - 读取中断状态寄存器 (Reading interrupt status registers) */ #include +// M5IOE1 设备实例 // M5IOE1 device instance M5IOE1 ioe1; +// I2C 配置 // I2C configuration #define I2C_SDA_PIN 38 #define I2C_SCL_PIN 39 #define I2C_FREQ 400000 +// 主机 MCU 上的物理中断引脚 (默认为 GPIO1) // Physical interrupt pin on host MCU (GPIO1 as default) +// 将此引脚连接到 M5IOE1 的 INT 引脚 // Connect this pin to M5IOE1's INT pin #define INT_PIN 1 +// M5IOE1 I2C 地址 (默认 0x6F) // M5IOE1 I2C address (default 0x6F) #define I2C_ADDR M5IOE1_DEFAULT_ADDR +// M5IOE1 GPIO 引脚定义 // Pin definitions for M5IOE1 GPIOs -#define IOE1_PIN_1 M5IOE1_PIN_1 // IO1 on M5IOE1 (pin index 0) -#define IOE1_PIN_2 M5IOE1_PIN_2 // IO2 on M5IOE1 (pin index 1) +#define IOE1_PIN_1 M5IOE1_PIN_1 // M5IOE1 上的 IO1 (引脚索引 0) (IO1 on M5IOE1, pin index 0) +#define IOE1_PIN_2 M5IOE1_PIN_2 // M5IOE1 上的 IO2 (引脚索引 1) (IO2 on M5IOE1, pin index 1) +// 中断事件计数器 // Counter for interrupt events volatile int pin1Counter = 0; volatile int pin2Counter = 0; +// 用于带参数回调的自定义数据结构 // Custom data structure for callback with argument struct ButtonData { const char* name; @@ -60,17 +72,21 @@ struct ButtonData { ButtonData button1Data = {"Button 1", &pin1Counter, IOE1_PIN_1}; ButtonData button2Data = {"Button 2", &pin2Counter, IOE1_PIN_2}; +// 引脚 1 的简单回调 (无参数) // Simple callback for pin 1 (without argument) void IRAM_ATTR pin1Callback() { pin1Counter++; } +// 引脚 2 的带自定义数据参数的回调 // Callback with custom data argument for pin 2 void IRAM_ATTR pin2CallbackWithArg(void* arg) { ButtonData* data = static_cast(arg); if (data) { (*(data->counter))++; + // 注意:避免在 ISR 上下文中使用 Serial 打印 // Note: Avoid Serial prints in ISR context + // 这仅用于演示 - 在实际应用中,使用标志并在 loop 中处理 // This is just demonstration - in real apps, use flags and handle in loop } } @@ -83,10 +99,13 @@ void setup() { Serial.println("M5IOE1 Hardware Interrupt Example"); Serial.println("========================================\n"); + // 设置日志级别为 INFO // Set log level to INFO M5IOE1::setLogLevel(M5IOE1_LOG_LEVEL_INFO); + // 使用硬件中断引脚初始化 M5IOE1 // Initialize M5IOE1 with hardware interrupt pin + // 当提供 intPin 时,硬件中断是默认且最高效的模式 // When intPin is provided, HARDWARE mode is the default and most efficient Serial.println("Initializing M5IOE1 in HARDWARE interrupt mode..."); Serial.println(" I2C: SDA=" + String(I2C_SDA_PIN) + ", SCL=" + String(I2C_SCL_PIN)); @@ -105,6 +124,7 @@ void setup() { Serial.println("M5IOE1 initialized successfully!\n"); + // 读取并显示设备信息 // Read and display device information uint16_t uid; uint8_t version; @@ -124,17 +144,20 @@ void setup() { Serial.println(); + // 将 IO1 和 IO2 配置为带上拉电阻的输入 // Configure IO1 and IO2 as inputs with pull-up Serial.println("Configuring IO1 and IO2 as inputs with internal pull-up..."); ioe1.pinMode(IOE1_PIN_1, INPUT_PULLUP); ioe1.pinMode(IOE1_PIN_2, INPUT_PULLUP); Serial.println("Pins configured successfully!\n"); + // 为引脚 1 附加下降沿触发的中断 (简单回调) // Attach interrupt to pin 1 with FALLING edge trigger (simple callback) Serial.println("Attaching FALLING edge interrupt to IO1..."); ioe1.attachInterrupt(IOE1_PIN_1, pin1Callback, FALLING); Serial.println("IO1 interrupt attached (simple callback)!\n"); + // 为引脚 2 附加上升沿触发的中断 (带参数的回调) // Attach interrupt to pin 2 with RISING edge trigger (callback with argument) Serial.println("Attaching RISING edge interrupt to IO2..."); ioe1.attachInterruptArg(IOE1_PIN_2, pin2CallbackWithArg, &button2Data, RISING); @@ -157,24 +180,29 @@ void setup() { } void loop() { + // 存储当前计数器值以检测变化 // Store current counter values to detect changes static int lastPin1Counter = 0; static int lastPin2Counter = 0; + // 检查引脚 1 中断计数器是否发生变化 // Check if pin 1 interrupt counter changed if (pin1Counter != lastPin1Counter) { Serial.println(">>> IO1 INTERRUPT TRIGGERED! <<<"); Serial.println(" Count: " + String(pin1Counter)); Serial.println(" Edge: FALLING"); + // 读取 IO1 的当前状态 // Read current state of IO1 int pinState = ioe1.digitalRead(IOE1_PIN_1); Serial.println(" IO1 state: " + String(pinState == LOW ? "LOW" : "HIGH")); + // 读取并显示中断状态寄存器 // Read and display interrupt status register uint16_t status = ioe1.getInterruptStatus(); Serial.println(" INT status: 0b" + String(status, BIN)); + // 清除此引脚的中断 // Clear the interrupt for this pin ioe1.clearInterrupt(IOE1_PIN_1); Serial.println(" Interrupt cleared\n"); @@ -182,6 +210,7 @@ void loop() { lastPin1Counter = pin1Counter; } + // 检查引脚 2 中断计数器是否发生变化 // Check if pin 2 interrupt counter changed if (pin2Counter != lastPin2Counter) { Serial.println(">>> IO2 INTERRUPT TRIGGERED! <<<"); @@ -189,14 +218,17 @@ void loop() { Serial.println(" Edge: RISING"); Serial.println(" Callback: with argument (ButtonData)"); + // 读取 IO2 的当前状态 // Read current state of IO2 int pinState = ioe1.digitalRead(IOE1_PIN_2); Serial.println(" IO2 state: " + String(pinState == HIGH ? "HIGH" : "LOW")); + // 读取并显示中断状态寄存器 // Read and display interrupt status register uint16_t status = ioe1.getInterruptStatus(); Serial.println(" INT status: 0b" + String(status, BIN)); + // 清除此引脚的中断 // Clear the interrupt for this pin ioe1.clearInterrupt(IOE1_PIN_2); Serial.println(" Interrupt cleared\n"); @@ -204,18 +236,23 @@ void loop() { lastPin2Counter = pin2Counter; } + // 处理串口命令 // Handle serial commands if (Serial.available() > 0) { char cmd = Serial.read(); switch (cmd) { case 'e': + // 启用 IO1 上的中断 + // Enable interrupts on IO1 Serial.println("Enabling interrupts on IO1..."); ioe1.enableInterrupt(IOE1_PIN_1); Serial.println("IO1 interrupts enabled\n"); break; case 'd': + // 禁用 IO1 上的中断 + // Disable interrupts on IO1 Serial.println("Disabling interrupts on IO1..."); ioe1.disableInterrupt(IOE1_PIN_1); Serial.println("IO1 interrupts disabled\n"); @@ -223,6 +260,8 @@ void loop() { case 's': { + // 显示中断状态 + // Show interrupt status uint16_t status = ioe1.getInterruptStatus(); Serial.println("Interrupt Status:"); Serial.println(" Register: 0b" + String(status, BIN)); @@ -234,6 +273,8 @@ void loop() { break; case 'c': + // 清除所有中断标志 + // Clear all interrupt flags Serial.println("Clearing all interrupt flags..."); for (uint8_t i = 0; i < 14; i++) { ioe1.clearInterrupt(i); @@ -243,6 +284,7 @@ void loop() { case '\n': case '\r': + // 忽略换行符 // Ignore newlines break; @@ -253,5 +295,5 @@ void loop() { } } - delay(10); // Small delay + delay(10); // 小延迟 / Small delay } diff --git a/examples/interrupt_polling/interrupt_polling.ino b/examples/interrupt_polling/interrupt_polling.ino index 0feecaf..7358bb9 100644 --- a/examples/interrupt_polling/interrupt_polling.ino +++ b/examples/interrupt_polling/interrupt_polling.ino @@ -5,44 +5,54 @@ */ /* + * M5IOE1 轮询中断示例 * M5IOE1 Interrupt Polling Example * + * 本示例演示如何在没有物理中断引脚的情况下,以轮询模式使用 M5IOE1 库 * This example demonstrates how to use the M5IOE1 library in POLLING mode * without a physical interrupt pin. The library periodically polls the * interrupt status registers to detect GPIO changes. * + * 硬件连接 * Hardware Connections: - * - M5IOE1 SDA -> GPIO 38 (default, configurable) - * - M5IOE1 SCL -> GPIO 39 (default, configurable) - * - IO1 (M5IOE1) -> Button or switch (connect to GND for active LOW) + * - M5IOE1 SDA -> GPIO 38 (默认,可配置) (default, configurable) + * - M5IOE1 SCL -> GPIO 39 (默认,可配置) (default, configurable) + * - IO1 (M5IOE1) -> 按钮或开关 (连接到 GND 为低电平有效) (Button or switch, connect to GND for active LOW) * + * 演示功能 * Features demonstrated: - * - Initializing M5IOE1 in polling mode (no INT pin) - * - Attaching interrupt callback to pin 1 (IO1) with FALLING edge trigger - * - Reading device information (UID, version) - * - Using attachInterrupt() callback for event handling - * - Polling interval configuration + * - 以轮询模式初始化 M5IOE1 (无 INT 引脚) (Initializing M5IOE1 in polling mode, no INT pin) + * - 为引脚 1 (IO1) 附加下降沿触发的中断回调 (Attaching interrupt callback to pin 1 with FALLING edge) + * - 读取设备信息 (UID、版本) (Reading device information: UID, version) + * - 使用 attachInterrupt() 回调进行事件处理 (Using attachInterrupt() callback for event handling) + * - 轮询间隔配置 (Polling interval configuration) */ #include +// M5IOE1 设备实例 // M5IOE1 device instance M5IOE1 ioe1; +// I2C 配置 // I2C configuration #define I2C_SDA_PIN 38 #define I2C_SCL_PIN 39 #define I2C_FREQ 400000 +// M5IOE1 I2C 地址 (默认 0x6F) // M5IOE1 I2C address (default 0x6F) #define I2C_ADDR M5IOE1_DEFAULT_ADDR +// 引脚定义 // Pin definitions -#define IOE1_PIN_1 M5IOE1_PIN_1 // IO1 on M5IOE1 (pin index 0) +#define IOE1_PIN_1 M5IOE1_PIN_1 // M5IOE1 上的 IO1 (引脚索引 0) (IO1 on M5IOE1, pin index 0) +// 中断事件计数器 // Counter for interrupt events volatile int interruptCounter = 0; +// 引脚 1 下降沿中断的回调函数 // Callback function for pin 1 falling edge interrupt void IRAM_ATTR pin1FallingCallback() { interruptCounter++; @@ -56,10 +66,13 @@ void setup() { Serial.println("M5IOE1 Interrupt Polling Example"); Serial.println("========================================\n"); + // 设置日志级别为 INFO (默认) // Set log level to INFO (default) M5IOE1::setLogLevel(M5IOE1_LOG_LEVEL_INFO); + // 以轮询模式初始化 M5IOE1 (无物理 INT 引脚) // Initialize M5IOE1 in POLLING mode (no physical INT pin) + // 当未提供 intPin (或设置为 -1) 时,仅支持轮询和禁用模式 // When intPin is not provided (or set to -1), only POLLING and DISABLED modes are supported Serial.println("Initializing M5IOE1 in polling mode..."); @@ -74,6 +87,7 @@ void setup() { Serial.println("M5IOE1 initialized successfully!\n"); + // 读取并显示设备信息 // Read and display device information uint16_t uid; uint8_t version; @@ -93,19 +107,24 @@ void setup() { Serial.println(); + // 将 IO1 配置为带上拉电阻的输入 // Configure IO1 as input with pull-up Serial.println("Configuring IO1 as input with internal pull-up..."); ioe1.pinMode(IOE1_PIN_1, INPUT_PULLUP); Serial.println("IO1 configured successfully!\n"); + // 为引脚 1 附加下降沿触发的中断 // Attach interrupt to pin 1 with FALLING edge trigger + // 在轮询模式下,库会定期检查中断状态,并在 IO1 上检测到下降沿时调用此回调 // In polling mode, the library will periodically check the interrupt status // and call this callback when a falling edge is detected on IO1 Serial.println("Attaching interrupt callback to IO1 (FALLING edge)..."); ioe1.attachInterrupt(IOE1_PIN_1, pin1FallingCallback, FALLING); Serial.println("Interrupt attached successfully!\n"); + // 设置轮询间隔为 1 秒 (1000ms) // Set polling interval to 1 second (1000ms) + // 默认为 5000ms。更短的间隔 = 更快的响应,但 CPU 使用率更高。 // Default is 5000ms. Shorter intervals = faster response but more CPU usage. Serial.println("Setting polling interval to 1.0 second..."); if (ioe1.setPollingInterval(1.0f)) { @@ -126,32 +145,40 @@ void setup() { } void loop() { + // 存储当前计数器值以检测变化 // Store current counter value to detect changes static int lastCounter = 0; + // 检查中断计数器是否发生变化 // Check if interrupt counter changed if (interruptCounter != lastCounter) { Serial.println(">>> INTERRUPT TRIGGERED! Count: " + String(interruptCounter) + " <<<"); lastCounter = interruptCounter; + // 读取 IO1 的当前状态 // Read current state of IO1 int pinState = ioe1.digitalRead(IOE1_PIN_1); Serial.println(" IO1 state: " + String(pinState == LOW ? "LOW (pressed)" : "HIGH (released)")); + // 读取并显示中断状态寄存器 // Read and display interrupt status register uint16_t status = ioe1.getInterruptStatus(); Serial.println(" Interrupt status register: 0b" + String(status, BIN) + "\n"); + // 清除此引脚的中断 // Clear the interrupt for this pin ioe1.clearInterrupt(IOE1_PIN_1); } + // 可选:手动轮询检查 (库会在后台自动执行此操作) // Optional: Manual polling check (the library does this automatically in background) + // 这仅用于演示 - 库会自动处理轮询 // This is just for demonstration - the library handles polling automatically static unsigned long lastStatusCheck = 0; if (millis() - lastStatusCheck > 5000) { lastStatusCheck = millis(); + // 显示当前轮询模式信息 // Display current polling mode info Serial.println("--- Status Update ---"); Serial.println(" Total interrupts: " + String(interruptCounter)); @@ -159,5 +186,5 @@ void loop() { Serial.println(" Polling mode: ACTIVE (background task)\n"); } - delay(100); // Small delay to prevent excessive CPU usage + delay(100); // 小延迟以防止过度的 CPU 使用 / Small delay to prevent excessive CPU usage } diff --git a/src/M5IOE1.cpp b/src/M5IOE1.cpp index 73eb065..c5dd223 100644 --- a/src/M5IOE1.cpp +++ b/src/M5IOE1.cpp @@ -13,7 +13,8 @@ static const char* TAG = "M5IOE1"; #include #define M5IOE1_DELAY_MS(ms) delay(ms) - // Arduino 日志级别控制 / Arduino log level control + // Arduino 日志级别控制 + // Arduino log level control static m5ioe1_log_level_t _m5ioe1_log_level = M5IOE1_LOG_LEVEL_INFO; #define M5IOE1_LOG_I(tag, fmt, ...) do { \ @@ -44,12 +45,14 @@ static const char* TAG = "M5IOE1"; #define M5IOE1_LOG_W(tag, fmt, ...) ESP_LOGW(tag, fmt, ##__VA_ARGS__) #define M5IOE1_LOG_E(tag, fmt, ...) ESP_LOGE(tag, fmt, ##__VA_ARGS__) - // ESP-IDF 平台日志级别控制 / ESP-IDF platform log level control + // ESP-IDF 平台日志级别控制 + // ESP-IDF platform log level control static m5ioe1_log_level_t _m5ioe1_current_log_level = M5IOE1_LOG_LEVEL_INFO; #endif // ============================ -// 全局日志级别控制 / Global Log Level Control +// 全局日志级别控制 +// Global Log Level Control // ============================ void M5IOE1::setLogLevel(m5ioe1_log_level_t level) { @@ -58,7 +61,8 @@ void M5IOE1::setLogLevel(m5ioe1_log_level_t level) { #else _m5ioe1_current_log_level = level; - // 将 M5IOE1 日志级别映射到 ESP-IDF 日志级别 / Map M5IOE1 log level to ESP-IDF log level + // 将 M5IOE1 日志级别映射到 ESP-IDF 日志级别 + // Map M5IOE1 log level to ESP-IDF log level esp_log_level_t esp_level; switch (level) { case M5IOE1_LOG_LEVEL_NONE: @@ -101,7 +105,8 @@ void M5IOE1::enableDefaultInterruptLog(bool enable) { } // ============================ -// 构造函数 / 析构函数 / Constructor / Destructor +// 构造函数 +// 析构函数 // ============================ M5IOE1::M5IOE1() { @@ -152,10 +157,12 @@ M5IOE1::~M5IOE1() { #else _cleanupInterrupt(); - // 根据驱动类型进行清理 / Cleanup based on driver type + // 根据驱动类型进行清理 + // Cleanup based on driver type switch (_i2cDriverType) { case M5IOE1_I2C_DRIVER_SELF_CREATED: - // 自创建:先删除设备,再删除总线 / Self-created: delete device first, then bus + // 自创建:先删除设备,再删除总线 + // Self-created: delete device first, then bus if (_i2c_master_dev) { i2c_master_bus_rm_device(_i2c_master_dev); _i2c_master_dev = nullptr; @@ -167,7 +174,8 @@ M5IOE1::~M5IOE1() { break; case M5IOE1_I2C_DRIVER_MASTER: - // 外部 i2c_master:总是删除我们创建的设备句柄,但不删除总线 / External i2c_master: always delete the device handle we created, but not the bus + // 外部 i2c_master:总是删除我们创建的设备句柄,但不删除总线 + // External i2c_master: always delete the device handle we created, but not the bus if (_i2c_master_dev) { i2c_master_bus_rm_device(_i2c_master_dev); _i2c_master_dev = nullptr; @@ -175,7 +183,8 @@ M5IOE1::~M5IOE1() { break; case M5IOE1_I2C_DRIVER_BUS: - // 外部 i2c_bus:总是删除我们创建的设备句柄,但不删除总线 / External i2c_bus: always delete the device handle we created, but not the bus + // 外部 i2c_bus:总是删除我们创建的设备句柄,但不删除总线 + // External i2c_bus: always delete the device handle we created, but not the bus if (_i2c_device) { i2c_bus_device_delete(&_i2c_device); _i2c_device = nullptr; @@ -189,7 +198,8 @@ M5IOE1::~M5IOE1() { } // ============================ -// 初始化函数 / Initialization Functions +// 初始化函数 +// Initialization Functions // ============================ #ifdef ARDUINO @@ -197,11 +207,12 @@ M5IOE1::~M5IOE1() { bool M5IOE1::begin(TwoWire *wire, uint8_t addr, uint8_t sda, uint8_t scl, uint32_t speed, m5ioe1_int_mode_t mode) { _wire = wire; _addr = addr; - _sda = sda; // 保存 SDA 引脚用于 I2C 重新初始化 / Save SDA pin for I2C re-initialization - _scl = scl; // 保存 SCL 引脚用于 I2C 重新初始化 / Save SCL pin for I2C re-initialization + _sda = sda; // 保存 SDA 引脚用于 I2C 重新初始化 + _scl = scl; // 保存 SCL 引脚用于 I2C 重新初始化 _intPin = -1; - // 验证 I2C 频率 - M5IOE1 仅支持 100KHz 或 400KHz / Validate I2C frequency - M5IOE1 only supports 100KHz or 400KHz + // 验证 I2C 频率 - M5IOE1 仅支持 100KHz 或 400KHz + // Validate I2C frequency - M5IOE1 only supports 100KHz or 400KHz if (!_isValidI2cFrequency(speed)) { M5IOE1_LOG_W(TAG, "Invalid I2C frequency: %lu Hz. M5IOE1 only supports 100KHz or 400KHz. Falling back to 100KHz.", speed); _requestedSpeed = M5IOE1_I2C_FREQ_100K; @@ -209,20 +220,24 @@ bool M5IOE1::begin(TwoWire *wire, uint8_t addr, uint8_t sda, uint8_t scl, uint32 _requestedSpeed = speed; } - // 始终以 100KHz 开始 - M5IOE1 在上电/复位后默认为 100KHz / Always start with 100KHz - M5IOE1 defaults to 100KHz after power-on/reset + // 始终以 100KHz 开始 - M5IOE1 在上电/复位后默认为 100KHz + // Always start with 100KHz - M5IOE1 defaults to 100KHz after power-on/reset M5IOE1_LOG_I(TAG, "Initializing M5IOE1 with 100KHz (device default)"); - // 在开始新的 I2C 会话之前结束之前的会话(修复 ESP_ERR_INVALID_STATE)/ End any previous I2C session before starting new one (fixes ESP_ERR_INVALID_STATE) + // 在开始新的 I2C 会话之前结束之前的会话(修复 ESP_ERR_INVALID_STATE) + // End any previous I2C session before starting new one (fixes ESP_ERR_INVALID_STATE) _wire->end(); M5IOE1_DELAY_MS(10); - // 初始化 I2C 总线并检查返回值 / Initialize I2C bus and check return value + // 初始化 I2C 总线并检查返回值 + // Initialize I2C bus and check return value if (!_wire->begin(sda, scl, M5IOE1_I2C_FREQ_100K)) { M5IOE1_LOG_E(TAG, "Failed to initialize I2C bus (SDA=%d, SCL=%d)", sda, scl); return false; } - // 给 I2C 总线时间在初始化后稳定 / Give the I2C bus time to stabilize after initialization + // 给 I2C 总线时间在初始化后稳定 + // Give the I2C bus time to stabilize after initialization M5IOE1_DELAY_MS(50); if (!_initDevice()) { @@ -232,13 +247,15 @@ bool M5IOE1::begin(TwoWire *wire, uint8_t addr, uint8_t sda, uint8_t scl, uint32 _initialized = true; - // 获取初始快照 / Take initial snapshot + // 获取初始快照 + // Take initial snapshot _snapshotPinStates(); _snapshotPwmStates(); _snapshotAdcState(); _snapshotI2cConfig(); - // 如果用户请求 400KHz,切换到高速模式 / If user requested 400KHz, switch to high-speed mode + // 如果用户请求 400KHz,切换到高速模式 + // If user requested 400KHz, switch to high-speed mode if (_requestedSpeed == M5IOE1_I2C_FREQ_400K) { if (!_switchTo400K()) { M5IOE1_LOG_W(TAG, "Failed to switch to 400KHz, remaining at 100KHz"); @@ -247,7 +264,8 @@ bool M5IOE1::begin(TwoWire *wire, uint8_t addr, uint8_t sda, uint8_t scl, uint32 M5IOE1_LOG_I(TAG, "M5IOE1 initialized at address 0x%02X (I2C: %lu Hz)", _addr, _requestedSpeed); - // 如果未禁用,设置中断模式 / Set interrupt mode if not disabled + // 如果未禁用,设置中断模式 + // Set interrupt mode if not disabled if (mode != M5IOE1_INT_MODE_DISABLED) { setInterruptMode(mode); } @@ -279,7 +297,8 @@ bool M5IOE1::begin(i2c_port_t port, uint8_t addr, int sda, int scl, uint32_t spe _sda = sda; _scl = scl; - // 验证 I2C 频率 - M5IOE1 仅支持 100KHz 或 400KHz / Validate I2C frequency - M5IOE1 only supports 100KHz or 400KHz + // 验证 I2C 频率 - M5IOE1 仅支持 100KHz 或 400KHz + // Validate I2C frequency - M5IOE1 only supports 100KHz or 400KHz if (!_isValidI2cFrequency(speed)) { M5IOE1_LOG_W(TAG, "Invalid I2C frequency: %lu Hz. M5IOE1 only supports 100KHz or 400KHz. Falling back to 100KHz.", speed); _requestedSpeed = M5IOE1_I2C_FREQ_100K; @@ -287,10 +306,12 @@ bool M5IOE1::begin(i2c_port_t port, uint8_t addr, int sda, int scl, uint32_t spe _requestedSpeed = speed; } - // 始终以 100KHz 开始 - M5IOE1 在上电/复位后默认为 100KHz / Always start with 100KHz - M5IOE1 defaults to 100KHz after power-on/reset + // 始终以 100KHz 开始 - M5IOE1 在上电/复位后默认为 100KHz + // Always start with 100KHz - M5IOE1 defaults to 100KHz after power-on/reset M5IOE1_LOG_I(TAG, "Initializing M5IOE1 with 100KHz (device default)"); - // 使用 ESP-IDF 原生驱动创建 I2C 主总线 / Create I2C master bus using ESP-IDF native driver + // 使用 ESP-IDF 原生驱动创建 I2C 主总线 + // Create I2C master bus using ESP-IDF native driver i2c_master_bus_config_t bus_config = { .i2c_port = port, .sda_io_num = (gpio_num_t)sda, @@ -311,7 +332,8 @@ bool M5IOE1::begin(i2c_port_t port, uint8_t addr, int sda, int scl, uint32_t spe return false; } - // 在 100KHz 创建设备句柄 / Create device handle at 100KHz + // 在 100KHz 创建设备句柄 + // Create device handle at 100KHz i2c_device_config_t dev_config = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = _addr, @@ -322,6 +344,8 @@ bool M5IOE1::begin(i2c_port_t port, uint8_t addr, int sda, int scl, uint32_t spe }, }; + // 在 100KHz 创建设备句柄 + // Create device handle at 100KHz ret = i2c_master_bus_add_device(_i2c_master_bus, &dev_config, &_i2c_master_dev); if (ret != ESP_OK) { M5IOE1_LOG_E(TAG, "Failed to add I2C device: %s", esp_err_to_name(ret)); @@ -341,13 +365,15 @@ bool M5IOE1::begin(i2c_port_t port, uint8_t addr, int sda, int scl, uint32_t spe _initialized = true; - // 获取初始快照 / Take initial snapshot + // 获取初始快照 + // Take initial snapshot _snapshotPinStates(); _snapshotPwmStates(); _snapshotAdcState(); _snapshotI2cConfig(); - // 如果用户请求 400KHz,切换到高速模式 / If user requested 400KHz, switch to high-speed mode + // 如果用户请求 400KHz,切换到高速模式 + // If user requested 400KHz, switch to high-speed mode if (_requestedSpeed == M5IOE1_I2C_FREQ_400K) { if (!_switchTo400K()) { M5IOE1_LOG_W(TAG, "Failed to switch to 400KHz, remaining at 100KHz"); @@ -356,7 +382,8 @@ bool M5IOE1::begin(i2c_port_t port, uint8_t addr, int sda, int scl, uint32_t spe M5IOE1_LOG_I(TAG, "M5IOE1 initialized at address 0x%02X (I2C: %lu Hz)", _addr, _requestedSpeed); - // 如果未禁用,设置中断模式 / Set interrupt mode if not disabled + // 如果未禁用,设置中断模式 + // Set interrupt mode if not disabled if (mode != M5IOE1_INT_MODE_DISABLED) { setInterruptMode(mode); } @@ -388,10 +415,12 @@ bool M5IOE1::begin(i2c_master_bus_handle_t bus, uint8_t addr, uint32_t speed, m5 _i2cDriverType = M5IOE1_I2C_DRIVER_MASTER; _intPin = -1; _i2c_master_bus = bus; - _sda = -1; // 外部总线未知 / Unknown for external bus + _sda = -1; // 外部总线未知 + // Unknown for external bus _scl = -1; - // 验证 I2C 频率 / Validate I2C frequency + // 验证 I2C 频率 + // Validate I2C frequency if (!_isValidI2cFrequency(speed)) { M5IOE1_LOG_W(TAG, "Invalid I2C frequency: %lu Hz. Falling back to 100KHz.", speed); _requestedSpeed = M5IOE1_I2C_FREQ_100K; @@ -401,7 +430,8 @@ bool M5IOE1::begin(i2c_master_bus_handle_t bus, uint8_t addr, uint32_t speed, m5 M5IOE1_LOG_I(TAG, "Initializing M5IOE1 with 100KHz (device default)"); - // 在 100KHz 创建设备句柄 / Create device handle at 100KHz + // 在 100KHz 创建设备句柄 + // Create device handle at 100KHz i2c_device_config_t dev_config = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = _addr, @@ -412,6 +442,8 @@ bool M5IOE1::begin(i2c_master_bus_handle_t bus, uint8_t addr, uint32_t speed, m5 }, }; + // 在 100KHz 创建设备句柄 + // Create device handle at 100KHz esp_err_t ret = i2c_master_bus_add_device(_i2c_master_bus, &dev_config, &_i2c_master_dev); if (ret != ESP_OK) { M5IOE1_LOG_E(TAG, "Failed to add I2C device: %s", esp_err_to_name(ret)); @@ -427,13 +459,15 @@ bool M5IOE1::begin(i2c_master_bus_handle_t bus, uint8_t addr, uint32_t speed, m5 _initialized = true; - // 获取初始快照 / Take initial snapshot + // 获取初始快照 + // Take initial snapshot _snapshotPinStates(); _snapshotPwmStates(); _snapshotAdcState(); _snapshotI2cConfig(); - // 如果用户请求 400KHz,切换到高速模式 / If user requested 400KHz, switch to high-speed mode + // 如果用户请求 400KHz,切换到高速模式 + // If user requested 400KHz, switch to high-speed mode if (_requestedSpeed == M5IOE1_I2C_FREQ_400K) { if (!_switchTo400K()) { M5IOE1_LOG_W(TAG, "Failed to switch to 400KHz, remaining at 100KHz"); @@ -473,10 +507,12 @@ bool M5IOE1::begin(i2c_bus_handle_t bus, uint8_t addr, uint32_t speed, m5ioe1_in _i2cDriverType = M5IOE1_I2C_DRIVER_BUS; _intPin = -1; _i2c_bus = bus; - _sda = -1; // 外部总线未知 / Unknown for external bus + _sda = -1; // 外部总线未知 + // Unknown for external bus _scl = -1; - // 验证 I2C 频率 / Validate I2C frequency + // 验证 I2C 频率 + // Validate I2C frequency if (!_isValidI2cFrequency(speed)) { M5IOE1_LOG_W(TAG, "Invalid I2C frequency: %lu Hz. Falling back to 100KHz.", speed); _requestedSpeed = M5IOE1_I2C_FREQ_100K; @@ -486,7 +522,8 @@ bool M5IOE1::begin(i2c_bus_handle_t bus, uint8_t addr, uint32_t speed, m5ioe1_in M5IOE1_LOG_I(TAG, "Initializing M5IOE1 with 100KHz (device default)"); - // 在 100KHz 创建设备句柄 / Create device handle at 100KHz + // 在 100KHz 创建设备句柄 + // Create device handle at 100KHz _i2c_device = i2c_bus_device_create(_i2c_bus, _addr, M5IOE1_I2C_FREQ_100K); if (_i2c_device == nullptr) { M5IOE1_LOG_E(TAG, "Failed to create I2C device"); @@ -502,13 +539,15 @@ bool M5IOE1::begin(i2c_bus_handle_t bus, uint8_t addr, uint32_t speed, m5ioe1_in _initialized = true; - // 获取初始快照 / Take initial snapshot + // 获取初始快照 + // Take initial snapshot _snapshotPinStates(); _snapshotPwmStates(); _snapshotAdcState(); _snapshotI2cConfig(); - // 如果用户请求 400KHz,切换到高速模式 / If user requested 400KHz, switch to high-speed mode + // 如果用户请求 400KHz,切换到高速模式 + // If user requested 400KHz, switch to high-speed mode if (_requestedSpeed == M5IOE1_I2C_FREQ_400K) { if (!_switchTo400K()) { M5IOE1_LOG_W(TAG, "Failed to switch to 400KHz, remaining at 100KHz"); @@ -552,7 +591,8 @@ bool M5IOE1::setInterruptMode(m5ioe1_int_mode_t mode, uint32_t pollingIntervalMs return _setupPollingArduino(); } // Arduino 上的硬件中断模式需要 attachInterrupt - // 这更复杂且特定于平台 / Hardware interrupt mode on Arduino would require attachInterrupt + // 这更复杂且特定于平台 + // Hardware interrupt mode on Arduino would require attachInterrupt // which is more complex and platform-specific #else _cleanupInterrupt(); @@ -580,7 +620,8 @@ bool M5IOE1::setPollingInterval(float seconds) { uint32_t intervalMs = (uint32_t)(seconds * 1000.0f); _pollingInterval = intervalMs; - // 如果当前处于轮询模式,使用新间隔重新启动 / If currently in polling mode, restart with new interval + // 如果当前处于轮询模式,使用新间隔重新启动 + // If currently in polling mode, restart with new interval if (_intMode == M5IOE1_INT_MODE_POLLING) { #ifdef ARDUINO _cleanupPollingArduino(); @@ -596,7 +637,8 @@ bool M5IOE1::setPollingInterval(float seconds) { } // ============================ -// 设备信息 / Device Information +// 设备信息 +// Device Information // ============================ bool M5IOE1::getUID(uint16_t* uid) { @@ -615,7 +657,8 @@ bool M5IOE1::getRefVoltage(uint16_t* voltage_mv) { } // ============================ -// GPIO 功能 / GPIO Functions +// GPIO 功能 +// GPIO Functions // ============================ void M5IOE1::pinMode(uint8_t pin, uint8_t mode) { @@ -654,7 +697,8 @@ void M5IOE1::pinMode(uint8_t pin, uint8_t mode) { _pinStates[pin].pull = 2; break; case OUTPUT: - // 如果此引脚上启用了 PWM 则禁用 / Disable PWM if enabled on this pin + // 如果此引脚上启用了 PWM 则禁用 + // Disable PWM if enabled on this pin if (_isPwmPin(pin)) { uint8_t ch = _getPwmChannel(pin); uint8_t regL = M5IOE1_REG_PWM1_DUTY_L + ch * 2; @@ -669,7 +713,8 @@ void M5IOE1::pinMode(uint8_t pin, uint8_t mode) { modeReg |= (1 << pin); puReg &= ~(1 << pin); pdReg &= ~(1 << pin); - drvReg &= ~(1 << pin); // 推挽 / Push-pull + drvReg &= ~(1 << pin); // 推挽 + // Push-pull _pinStates[pin].isOutput = true; _pinStates[pin].drive = 0; break; @@ -718,7 +763,8 @@ int M5IOE1::digitalRead(uint8_t pin) { } // ============================ -// 高级 GPIO 功能 / Advanced GPIO Functions +// 高级 GPIO 功能 +// Advanced GPIO Functions // ============================ bool M5IOE1::setPullMode(uint8_t pin, uint8_t pullMode) { @@ -777,13 +823,15 @@ bool M5IOE1::getInputState(uint8_t pin, uint8_t* state) { } // ============================ -// 中断功能 / Interrupt Functions +// 中断功能 +// Interrupt Functions // ============================ void M5IOE1::attachInterrupt(uint8_t pin, m5ioe1_callback_t callback, uint8_t mode) { if (!_isValidPin(pin) || callback == nullptr || !_initialized) return; - // 检查冲突的中断 / Check for conflicting interrupts + // 检查冲突的中断 + // Check for conflicting interrupts if (_hasConflictingInterrupt(pin)) { M5IOE1_LOG_E(TAG, "Interrupt conflict on pin %d", pin); return; @@ -795,13 +843,15 @@ void M5IOE1::attachInterrupt(uint8_t pin, m5ioe1_callback_t callback, uint8_t mo _callbacks[pin].enabled = true; _callbacks[pin].rising = (mode == RISING); - // 将引脚配置为输入 / Configure pin as input + // 将引脚配置为输入 + // Configure pin as input uint16_t modeReg = 0; _readReg16(M5IOE1_REG_GPIO_MODE_L, &modeReg); modeReg &= ~(1 << pin); _writeReg16(M5IOE1_REG_GPIO_MODE_L, modeReg); - // 配置中断 / Configure interrupt + // 配置中断 + // Configure interrupt uint16_t ieReg = 0, itReg = 0; _readReg16(M5IOE1_REG_GPIO_IE_L, &ieReg); _readReg16(M5IOE1_REG_GPIO_IP_L, &itReg); @@ -834,13 +884,15 @@ void M5IOE1::attachInterruptArg(uint8_t pin, m5ioe1_callback_arg_t callback, voi _callbacks[pin].enabled = true; _callbacks[pin].rising = (mode == RISING); - // 将引脚配置为输入 / Configure pin as input + // 将引脚配置为输入 + // Configure pin as input uint16_t modeReg = 0; _readReg16(M5IOE1_REG_GPIO_MODE_L, &modeReg); modeReg &= ~(1 << pin); _writeReg16(M5IOE1_REG_GPIO_MODE_L, modeReg); - // 配置中断 / Configure interrupt + // 配置中断 + // Configure interrupt uint16_t ieReg = 0, itReg = 0; _readReg16(M5IOE1_REG_GPIO_IE_L, &ieReg); _readReg16(M5IOE1_REG_GPIO_IP_L, &itReg); @@ -902,17 +954,20 @@ bool M5IOE1::clearInterrupt(uint8_t pin) { } // ============================ -// ADC 功能 / ADC Functions +// ADC 功能 +// ADC Functions // ============================ bool M5IOE1::analogRead(uint8_t channel, uint16_t* result) { if (result == nullptr || channel < 1 || channel > 4 || !_initialized) return false; - // 开始转换 / Start conversion + // 开始转换 + // Start conversion uint8_t ctrl = (channel & M5IOE1_ADC_CH_MASK) | M5IOE1_ADC_START; if (!_writeReg(M5IOE1_REG_ADC_CTRL, ctrl)) return false; - // 等待完成 / Wait for completion + // 等待完成 + // Wait for completion uint8_t reg = 0; int tries = 0; do { @@ -946,7 +1001,8 @@ bool M5IOE1::disableAdc() { } // ============================ -// 温度传感器 / Temperature Sensor +// 温度传感器 +// Temperature Sensor // ============================ bool M5IOE1::readTemperature(uint16_t* temperature) { @@ -978,7 +1034,8 @@ bool M5IOE1::isTemperatureBusy() { } // ============================ -// PWM 功能 / PWM Functions +// PWM 功能 +// PWM Functions // ============================ bool M5IOE1::setPwmFrequency(uint16_t frequency) { @@ -999,7 +1056,8 @@ bool M5IOE1::getPwmFrequency(uint16_t* frequency) { bool M5IOE1::setPwmDuty(uint8_t channel, uint8_t duty, bool polarity, bool enable) { if (channel > 3 || duty > 100 || !_initialized) return false; - // 将百分比转换为 12 位 (0-4095) / Convert percentage to 12-bit (0-4095) + // 将百分比转换为 12 位 (0-4095) + // Convert percentage to 12-bit (0-4095) uint16_t duty12 = (uint16_t)((duty * 0x0FFF) / 100); return setPwmDuty12bit(channel, duty12, polarity, enable); } @@ -1007,7 +1065,8 @@ bool M5IOE1::setPwmDuty(uint8_t channel, uint8_t duty, bool polarity, bool enabl bool M5IOE1::setPwmDuty12bit(uint8_t channel, uint16_t duty12, bool polarity, bool enable) { if (channel > 3 || duty12 > 0x0FFF || !_initialized) return false; - // 获取对应的引脚 / Get corresponding pin + // 获取对应的引脚 + // Get corresponding pin uint8_t pin = (channel == 0) ? 8 : (channel == 1) ? 7 : (channel == 2) ? 10 : 9; uint8_t regL = M5IOE1_REG_PWM1_DUTY_L + (channel * 2); @@ -1021,7 +1080,8 @@ bool M5IOE1::setPwmDuty12bit(uint8_t channel, uint16_t duty12, bool polarity, bo if (!_writeBytes(regL, buf, 2)) return false; if (enable) { - // 将引脚设置为输出模式 / Set pin to output mode + // 将引脚设置为输出模式 + // Set pin to output mode uint16_t modeReg = 0; if (_readReg16(M5IOE1_REG_GPIO_MODE_L, &modeReg)) { modeReg |= (1 << pin); @@ -1055,7 +1115,8 @@ bool M5IOE1::getPwmDuty(uint8_t channel, uint8_t* duty, bool* polarity, bool* en } // ============================ -// NeoPixel LED 功能 / NeoPixel LED Functions +// NeoPixel LED 功能 +// NeoPixel LED Functions // ============================ bool M5IOE1::setLedCount(uint8_t count) { @@ -1071,7 +1132,8 @@ bool M5IOE1::setLedCount(uint8_t count) { bool M5IOE1::setLedColor(uint8_t index, uint8_t r, uint8_t g, uint8_t b) { if (index >= M5IOE1_MAX_LED_COUNT || !_initialized) return false; - // 转换为 RGB565 / Convert to RGB565 + // 转换为 RGB565 + // Convert to RGB565 uint16_t r5 = (r >> 3) & 0x1F; uint16_t g6 = (g >> 2) & 0x3F; uint16_t b5 = (b >> 3) & 0x1F; @@ -1108,7 +1170,8 @@ bool M5IOE1::disableLeds() { } // ============================ -// AW8737A 脉冲功能 / AW8737A Pulse Functions +// AW8737A 脉冲功能 +// AW8737A Pulse Functions // ============================ bool M5IOE1::setAw8737aPulse(uint8_t pin, m5ioe1_aw8737a_pulse_num_t pulseNum, @@ -1118,26 +1181,32 @@ bool M5IOE1::setAw8737aPulse(uint8_t pin, m5ioe1_aw8737a_pulse_num_t pulseNum, return false; } - // 验证引脚范围 (0-13) / Validate pin range (0-13) + // 验证引脚范围 (0-13) + // Validate pin range (0-13) if (pin >= M5IOE1_MAX_GPIO_PINS) { M5IOE1_LOG_E(TAG, "Invalid pin number: %d (valid range: 0-%d)", pin, M5IOE1_MAX_GPIO_PINS - 1); return false; } - // 验证脉冲编号 (0-3) / Validate pulse number (0-3) + // 验证脉冲编号 (0-3) + // Validate pulse number (0-3) if (pulseNum > M5IOE1_AW8737A_PULSE_NUM_3) { M5IOE1_LOG_E(TAG, "Invalid pulse number: %d (valid range: 0-3)", pulseNum); return false; } // 构建寄存器值 - // [7] REFRESH | [6:5] NUM[1:0] | [4:0] GPIO[4:0] / Build register value + // [7] REFRESH | [6:5] NUM[1:0] | [4:0] GPIO[4:0] + // Build register value // [7] REFRESH | [6:5] NUM[1:0] | [4:0] GPIO[4:0] uint8_t regValue = 0; - regValue |= (pin & M5IOE1_AW8737A_GPIO_MASK); // 位[4:0]: GPIO 选择 / Bits[4:0]: GPIO selection - regValue |= ((pulseNum & M5IOE1_AW8737A_NUM_MASK) << M5IOE1_AW8737A_NUM_SHIFT); // 位[6:5]: 脉冲编号 / Bits[6:5]: Pulse number + regValue |= (pin & M5IOE1_AW8737A_GPIO_MASK); // 位[4:0]: GPIO 选择 + // Bits[4:0]: GPIO selection + regValue |= ((pulseNum & M5IOE1_AW8737A_NUM_MASK) << M5IOE1_AW8737A_NUM_SHIFT); // 位[6:5]: 脉冲编号 + // Bits[6:5]: Pulse number if (refresh == M5IOE1_AW8737A_REFRESH_NOW) { - regValue |= M5IOE1_AW8737A_REFRESH; // 位[7]: 刷新标志 / Bit[7]: Refresh flag + regValue |= M5IOE1_AW8737A_REFRESH; // 位[7]: 刷新标志 + // Bit[7]: Refresh flag } bool ok = _writeReg(M5IOE1_REG_AW8737A_PULSE, regValue); @@ -1149,7 +1218,8 @@ bool M5IOE1::setAw8737aPulse(uint8_t pin, m5ioe1_aw8737a_pulse_num_t pulseNum, M5IOE1_LOG_I(TAG, "AW8737A pulse set: pin=%d, num=%d, refresh=%d (reg=0x%02X)", pin, pulseNum, refresh, regValue); - // 如果设置了 REFRESH 位 (REFRESH_NOW),等待 20ms,因为它会影响 I2C 通信 / If REFRESH bit was set (REFRESH_NOW), wait 20ms as it affects I2C communication + // 如果设置了 REFRESH 位 (REFRESH_NOW),等待 20ms,因为它会影响 I2C 通信 + // If REFRESH bit was set (REFRESH_NOW), wait 20ms as it affects I2C communication if (refresh == M5IOE1_AW8737A_REFRESH_NOW) { M5IOE1_DELAY_MS(20); } @@ -1163,14 +1233,16 @@ bool M5IOE1::refreshAw8737aPulse() { return false; } - // 读取当前寄存器值 / Read current register value + // 读取当前寄存器值 + // Read current register value uint8_t regValue = 0; if (!_readReg(M5IOE1_REG_AW8737A_PULSE, ®Value)) { M5IOE1_LOG_E(TAG, "Failed to read AW8737A pulse register"); return false; } - // 将位 7 设置为 1 / Set bit 7 to 1 + // 将位 7 设置为 1 + // Set bit 7 to 1 regValue |= M5IOE1_AW8737A_REFRESH; if (!_writeReg(M5IOE1_REG_AW8737A_PULSE, regValue)) { @@ -1180,14 +1252,16 @@ bool M5IOE1::refreshAw8737aPulse() { M5IOE1_LOG_I(TAG, "AW8737A pulse refresh triggered (reg=0x%02X)", regValue); - // 写入位 7 后等待 20ms,因为它会影响 I2C 通信 / Wait 20ms after writing bit 7, as it affects I2C communication + // 写入位 7 后等待 20ms,因为它会影响 I2C 通信 + // Wait 20ms after writing bit 7, as it affects I2C communication M5IOE1_DELAY_MS(20); return true; } // ============================ -// RTC RAM 功能 / RTC RAM Functions +// RTC RAM 功能 +// RTC RAM Functions // ============================ bool M5IOE1::writeRtcRAM(uint8_t offset, const uint8_t* data, uint8_t length) { @@ -1211,7 +1285,8 @@ bool M5IOE1::readRtcRAM(uint8_t offset, uint8_t* data, uint8_t length) { } // ============================ -// 系统配置 / System Configuration +// 系统配置 +// System Configuration // ============================ bool M5IOE1::setI2cConfig(uint8_t sleepTime, bool speed400k, bool wakeRising, bool pullOff) { @@ -1252,7 +1327,8 @@ bool M5IOE1::factoryReset() { } // ============================ -// 状态快照功能 / State Snapshot Functions +// 状态快照功能 +// State Snapshot Functions // ============================ void M5IOE1::setAutoSnapshot(bool enable) { @@ -1274,7 +1350,8 @@ bool M5IOE1::updateSnapshot() { } // ============================ -// 调试功能 / Debug Functions +// 调试功能 +// Debug Functions // ============================ bool M5IOE1::getModeReg(uint16_t* reg) { @@ -1308,13 +1385,15 @@ bool M5IOE1::getDriveReg(uint16_t* reg) { } // ============================ -// 配置验证 / Configuration Validation +// 配置验证 +// Configuration Validation // ============================ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t configType, bool enable) { m5ioe1_validation_t result = {false, {0}, 0xFF}; - // 基本验证 / Basic validation + // 基本验证 + // Basic validation if (!_isValidPin(pin)) { snprintf(result.error_msg, sizeof(result.error_msg), "Invalid pin %d", pin); return result; @@ -1325,7 +1404,8 @@ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t con return result; } - // 如果禁用,无需冲突检查 / If disabling, no conflict check needed + // 如果禁用,无需冲突检查 + // If disabling, no conflict check needed if (!enable) { result.valid = true; return result; @@ -1336,7 +1416,8 @@ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t con switch (configType) { case M5IOE1_CONFIG_GPIO_INPUT: case M5IOE1_CONFIG_GPIO_OUTPUT: - // 检查引脚是否用于特殊功能 / Check if pin is being used for special functions + // 检查引脚是否用于特殊功能 + // Check if pin is being used for special functions if (_hasActivePwm(pin)) { snprintf(result.error_msg, sizeof(result.error_msg), "Pin %d is used for PWM. Disable first (e.g. setPwmDuty)", pin); @@ -1355,7 +1436,8 @@ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t con break; case M5IOE1_CONFIG_GPIO_INTERRUPT: - // 检查中断互斥约束 / Check interrupt mutex constraint + // 检查中断互斥约束 + // Check interrupt mutex constraint if (_getInterruptMutexPin(pin, &mutexPin)) { if (_hasActiveInterrupt(mutexPin)) { snprintf(result.error_msg, sizeof(result.error_msg), @@ -1364,7 +1446,8 @@ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t con return result; } } - // 检查 IO5 的 I2C 睡眠模式冲突 / Check I2C sleep mode conflict for IO5 + // 检查 IO5 的 I2C 睡眠模式冲突 + // Check I2C sleep mode conflict for IO5 if (pin == 4 && _hasI2cSleepEnabled()) { // IO5 is pin index 4 snprintf(result.error_msg, sizeof(result.error_msg), "IO5 interrupt disabled when I2C sleep enabled"); @@ -1373,13 +1456,15 @@ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t con break; case M5IOE1_CONFIG_ADC: - // 检查引脚是否支持 ADC / Check if pin supports ADC + // 检查引脚是否支持 ADC + // Check if pin supports ADC if (!_isAdcPin(pin)) { snprintf(result.error_msg, sizeof(result.error_msg), "Pin %d does not support ADC", pin); return result; } - // 检查引脚是否配置为输出 / Check if pin is configured as output + // 检查引脚是否配置为输出 + // Check if pin is configured as output if (_pinStatesValid && _pinStates[pin].isOutput) { snprintf(result.error_msg, sizeof(result.error_msg), "Pin %d is configured as output", pin); @@ -1388,7 +1473,8 @@ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t con break; case M5IOE1_CONFIG_PWM: - // 检查引脚是否支持 PWM / Check if pin supports PWM + // 检查引脚是否支持 PWM + // Check if pin supports PWM if (!_isPwmPin(pin)) { snprintf(result.error_msg, sizeof(result.error_msg), "Pin %d does not support PWM", pin); @@ -1397,19 +1483,22 @@ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t con break; case M5IOE1_CONFIG_NEOPIXEL: - // NeoPixel 仅在 IO14 上工作(引脚索引 13)/ NeoPixel only works on IO14 (pin index 13) + // NeoPixel 仅在 IO14 上工作(引脚索引 13) + // NeoPixel only works on IO14 (pin index 13) if (!_isNeopixelPin(pin)) { snprintf(result.error_msg, sizeof(result.error_msg), "NeoPixel only supported on IO14 (pin 13)"); return result; } - // 检查引脚是否有活动中断 / Check if pin has active interrupt + // 检查引脚是否有活动中断 + // Check if pin has active interrupt if (_hasActiveInterrupt(pin)) { snprintf(result.error_msg, sizeof(result.error_msg), "IO14 has active interrupt, conflicts with NeoPixel"); return result; } - // 检查中断互斥(IO10 和 IO14 是互斥的)/ Check interrupt mutex (IO10 and IO14 are mutex) + // 检查中断互斥(IO10 和 IO14 是互斥的) + // Check interrupt mutex (IO10 and IO14 are mutex) if (_getInterruptMutexPin(pin, &mutexPin)) { if (_hasActiveInterrupt(mutexPin)) { snprintf(result.error_msg, sizeof(result.error_msg), @@ -1421,7 +1510,8 @@ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t con break; case M5IOE1_CONFIG_I2C_SLEEP: - // I2C 睡眠模式禁用 IO5 中断 / I2C sleep mode disables IO5 interrupt + // I2C 睡眠模式禁用 IO5 中断 + // I2C sleep mode disables IO5 interrupt if (_hasActiveInterrupt(4)) { // IO5 is pin index 4 snprintf(result.error_msg, sizeof(result.error_msg), "I2C sleep mode will disable IO5 interrupt"); @@ -1440,7 +1530,8 @@ m5ioe1_validation_t M5IOE1::validateConfig(uint8_t pin, m5ioe1_config_type_t con } // ============================ -// 内部辅助函数 / Internal Helper Functions +// 内部辅助函数 +// Internal Helper Functions // ============================ bool M5IOE1::_writeReg(uint8_t reg, uint8_t value) { @@ -1544,12 +1635,14 @@ bool M5IOE1::_isValidPin(uint8_t pin) { } bool M5IOE1::_isAdcPin(uint8_t pin) { - // ADC 引脚:IO2(1), IO4(3), IO5(4), IO7(6) / ADC pins: IO2(1), IO4(3), IO5(4), IO7(6) + // ADC 引脚:IO2(1), IO4(3), IO5(4), IO7(6) + // ADC pins: IO2(1), IO4(3), IO5(4), IO7(6) return (pin == 1 || pin == 3 || pin == 4 || pin == 6); } bool M5IOE1::_isPwmPin(uint8_t pin) { - // PWM 引脚:IO8(7), IO9(8), IO10(9), IO11(10) / PWM pins: IO8(7), IO9(8), IO10(9), IO11(10) + // PWM 引脚:IO8(7), IO9(8), IO10(9), IO11(10) + // PWM pins: IO8(7), IO9(8), IO10(9), IO11(10) return (pin == 7 || pin == 8 || pin == 9 || pin == 10); } @@ -1673,14 +1766,16 @@ bool M5IOE1::_switchTo400K() { return false; } - // 步骤 1:读取当前 I2C 配置 / Step 1: Read current I2C config + // 步骤 1:读取当前 I2C 配置 + // Step 1: Read current I2C config uint8_t i2cCfg = 0; if (!_readReg(M5IOE1_REG_I2C_CFG, &i2cCfg)) { M5IOE1_LOG_E(TAG, "Failed to read I2C config register"); return false; } - // 步骤 2:在设备中设置 400KHz 模式位 / Step 2: Set 400KHz mode bit in device + // 步骤 2:在设备中设置 400KHz 模式位 + // Step 2: Set 400KHz mode bit in device i2cCfg |= M5IOE1_I2C_SPEED_400K; if (!_writeReg(M5IOE1_REG_I2C_CFG, i2cCfg)) { M5IOE1_LOG_E(TAG, "Failed to write I2C config register for 400KHz mode"); @@ -1689,23 +1784,28 @@ bool M5IOE1::_switchTo400K() { M5IOE1_LOG_I(TAG, "M5IOE1 I2C config set to 400KHz mode"); - // 步骤 3:短暂延迟以允许设备处理配置更改 / Step 3: Small delay to allow device to process the configuration change + // 步骤 3:短暂延迟以允许设备处理配置更改 + // Step 3: Small delay to allow device to process the configuration change M5IOE1_DELAY_MS(5); - // 步骤 4:将主机 I2C 总线切换到 400KHz / Step 4: Switch host I2C bus to 400KHz + // 步骤 4:将主机 I2C 总线切换到 400KHz + // Step 4: Switch host I2C bus to 400KHz #ifdef ARDUINO if (_wire != nullptr) { // 必须使用 Wire.end() + Wire.begin() 在 ESP32 上正确切换 I2C 频率 - // 仅使用 setClock() 会在较新的 ESP32 Arduino 核心上导致 ESP_ERR_INVALID_STATE / Must use Wire.end() + Wire.begin() to properly switch I2C frequency on ESP32 + // 仅使用 setClock() 会在较新的 ESP32 Arduino 核心上导致 ESP_ERR_INVALID_STATE + // Must use Wire.end() + Wire.begin() to properly switch I2C frequency on ESP32 // Using only setClock() causes ESP_ERR_INVALID_STATE on newer ESP32 Arduino cores _wire->end(); - M5IOE1_DELAY_MS(10); // 允许 I2C 总线稳定 / Allow I2C bus to settle + M5IOE1_DELAY_MS(10); // 允许 I2C 总线稳定 + // Allow I2C bus to settle if (!_wire->begin(_sda, _scl, M5IOE1_I2C_FREQ_400K)) { M5IOE1_LOG_E(TAG, "Failed to re-initialize I2C bus at 400KHz"); // Try to recover with 100KHz _wire->begin(_sda, _scl, M5IOE1_I2C_FREQ_100K); _requestedSpeed = M5IOE1_I2C_FREQ_100K; - // 恢复设备配置 / Revert device config + // 恢复设备配置 + // Revert device config i2cCfg &= ~M5IOE1_I2C_SPEED_400K; _writeReg(M5IOE1_REG_I2C_CFG, i2cCfg); return false; @@ -1714,13 +1814,15 @@ bool M5IOE1::_switchTo400K() { M5IOE1_LOG_I(TAG, "Host I2C bus switched to 400KHz"); } #else - // ESP-IDF:处理不同的驱动类型 / ESP-IDF: Handle different driver types + // ESP-IDF:处理不同的驱动类型 + // ESP-IDF: Handle different driver types esp_err_t ret; switch (_i2cDriverType) { case M5IOE1_I2C_DRIVER_SELF_CREATED: case M5IOE1_I2C_DRIVER_MASTER: - // 对于 i2c_master 驱动:删除设备并以新速度重新添加 / For i2c_master driver: remove device and add with new speed + // 对于 i2c_master 驱动:删除设备并以新速度重新添加 + // For i2c_master driver: remove device and add with new speed if (_i2c_master_dev != nullptr) { ret = i2c_master_bus_rm_device(_i2c_master_dev); if (ret != ESP_OK) { @@ -1728,8 +1830,9 @@ bool M5IOE1::_switchTo400K() { return false; } _i2c_master_dev = nullptr; - - // 以 400KHz 重新创建设备句柄 / Recreate device handle with 400KHz + + // 以 400KHz 重新创建设备句柄 + // Recreate device handle with 400KHz i2c_device_config_t dev_config = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = _addr, @@ -1743,7 +1846,8 @@ bool M5IOE1::_switchTo400K() { ret = i2c_master_bus_add_device(_i2c_master_bus, &dev_config, &_i2c_master_dev); if (ret != ESP_OK) { M5IOE1_LOG_E(TAG, "Failed to add I2C device at 400KHz: %s", esp_err_to_name(ret)); - // 尝试以 100KHz 恢复 / Try to recover with 100KHz + // 尝试以 100KHz 恢复 + // Try to recover with 100KHz dev_config.scl_speed_hz = M5IOE1_I2C_FREQ_100K; i2c_master_bus_add_device(_i2c_master_bus, &dev_config, &_i2c_master_dev); _requestedSpeed = M5IOE1_I2C_FREQ_100K; @@ -1754,19 +1858,22 @@ bool M5IOE1::_switchTo400K() { break; case M5IOE1_I2C_DRIVER_BUS: - // 对于 i2c_bus 驱动:删除设备并以新速度创建 / For i2c_bus driver: delete device and create with new speed + // 对于 i2c_bus 驱动:删除设备并以新速度创建 + // For i2c_bus driver: delete device and create with new speed if (_i2c_device != nullptr) { ret = i2c_bus_device_delete(&_i2c_device); if (ret != ESP_OK) { M5IOE1_LOG_E(TAG, "Failed to delete I2C device: %s", esp_err_to_name(ret)); return false; } - - // 以 400KHz 重新创建设备句柄 / Recreate device handle with 400KHz + + // 以 400KHz 重新创建设备句柄 + // Recreate device handle with 400KHz _i2c_device = i2c_bus_device_create(_i2c_bus, _addr, M5IOE1_I2C_FREQ_400K); if (_i2c_device == nullptr) { M5IOE1_LOG_E(TAG, "Failed to create I2C device at 400KHz"); - // 尝试以 100KHz 恢复 / Try to recover with 100KHz + // 尝试以 100KHz 恢复 + // Try to recover with 100KHz _i2c_device = i2c_bus_device_create(_i2c_bus, _addr, M5IOE1_I2C_FREQ_100K); _requestedSpeed = M5IOE1_I2C_FREQ_100K; return false; @@ -1781,23 +1888,27 @@ bool M5IOE1::_switchTo400K() { } #endif - // 步骤 5:验证通信仍然有效 / Step 5: Verify communication still works + // 步骤 5:验证通信仍然有效 + // Step 5: Verify communication still works uint16_t uid = 0; if (!_readReg16(M5IOE1_REG_UID_L, &uid)) { M5IOE1_LOG_E(TAG, "Communication failed after switching to 400KHz, reverting to 100KHz"); - // 恢复设备配置 / Revert device config + // 恢复设备配置 + // Revert device config i2cCfg &= ~M5IOE1_I2C_SPEED_400K; #ifdef ARDUINO if (_wire != nullptr) { - // 以 100KHz 重新初始化 I2C 总线 / Re-initialize I2C bus at 100KHz + // 以 100KHz 重新初始化 I2C 总线 + // Re-initialize I2C bus at 100KHz _wire->end(); M5IOE1_DELAY_MS(10); _wire->begin(_sda, _scl, M5IOE1_I2C_FREQ_100K); M5IOE1_DELAY_MS(10); } #else - // 根据驱动类型恢复 / Revert based on driver type + // 根据驱动类型恢复 + // Revert based on driver type switch (_i2cDriverType) { case M5IOE1_I2C_DRIVER_SELF_CREATED: case M5IOE1_I2C_DRIVER_MASTER: @@ -1828,7 +1939,8 @@ bool M5IOE1::_switchTo400K() { return false; } - // 更新 I2C 配置缓存 / Update I2C config cache + // 更新 I2C 配置缓存 + // Update I2C config cache _i2cConfig.speed400k = true; _requestedSpeed = M5IOE1_I2C_FREQ_400K; @@ -1837,7 +1949,8 @@ bool M5IOE1::_switchTo400K() { } bool M5IOE1::_initDevice() { - // 读取设备信息以验证通信 / Read device info to verify communication + // 读取设备信息以验证通信 + // Read device info to verify communication uint16_t uid = 0; uint8_t version = 0; @@ -1875,7 +1988,8 @@ void M5IOE1::_handleInterrupt() { } bool M5IOE1::_pinsConflict(uint8_t a, uint8_t b) { - // 中断冲突对(1-based IO 编号):/ Interrupt conflict pairs (1-based IO numbers): + // 中断冲突对(1-based IO 编号): + // Interrupt conflict pairs (1-based IO numbers): // (1,6), (2,3), (7,12), (8,9), (10,14), (11,13) uint8_t A = a + 1, B = b + 1; @@ -1897,13 +2011,15 @@ bool M5IOE1::_hasConflictingInterrupt(uint8_t pin) { } // ============================ -// 配置验证辅助函数 / Configuration Validation Helpers +// 配置验证辅助函数 +// Configuration Validation Helpers // ============================ bool M5IOE1::_getInterruptMutexPin(uint8_t pin, uint8_t* mutexPin) { if (mutexPin == nullptr) return false; - // 中断互斥对(0-based 引脚索引):/ Interrupt mutex pairs (0-based pin indices): + // 中断互斥对(0-based 引脚索引): + // Interrupt mutex pairs (0-based pin indices): // IO1(0) <-> IO6(5) // IO2(1) <-> IO3(2) // IO7(6) <-> IO12(11) @@ -1935,7 +2051,8 @@ bool M5IOE1::_getInterruptMutexPin(uint8_t pin, uint8_t* mutexPin) { } bool M5IOE1::_isNeopixelPin(uint8_t pin) { - // NeoPixel LED 功能仅在 IO14 上可用(引脚索引 13)/ NeoPixel LED function only available on IO14 (pin index 13) + // NeoPixel LED 功能仅在 IO14 上可用(引脚索引 13) + // NeoPixel LED function only available on IO14 (pin index 13) return (pin == 13); } @@ -1949,7 +2066,8 @@ bool M5IOE1::_hasActiveAdc(uint8_t pin) { if (!_isAdcPin(pin)) return false; if (!_adcStateValid) return false; - // 检查 ADC 当前是否正在使用此引脚的通道 / Check if the ADC is currently using this pin's channel + // 检查 ADC 当前是否正在使用此引脚的通道 + // Check if the ADC is currently using this pin's channel uint8_t channel = _getAdcChannel(pin); return (_adcState.activeChannel == channel); } @@ -1972,7 +2090,8 @@ bool M5IOE1::_isLedEnabled() { } // ============================ -// I2C 配置快照 / I2C Config Snapshot +// I2C 配置快照 +// I2C Config Snapshot // ============================ void M5IOE1::_clearI2cConfig() { @@ -1992,7 +2111,8 @@ bool M5IOE1::_snapshotI2cConfig() { _i2cConfig.pullOff = (cfg & M5IOE1_I2C_PULL_OFF) != 0; _i2cConfigValid = true; - // 同时快照 LED 配置 / Also snapshot LED config + // 同时快照 LED 配置 + // Also snapshot LED config uint8_t ledCfg = 0; if (_readReg(M5IOE1_REG_LED_CFG, &ledCfg)) { _ledCount = ledCfg & M5IOE1_LED_NUM_MASK; @@ -2003,7 +2123,8 @@ bool M5IOE1::_snapshotI2cConfig() { } // ============================ -// 快照验证 / Snapshot Verification +// 快照验证 +// Snapshot Verification // ============================ m5ioe1_snapshot_verify_t M5IOE1::verifySnapshot() { @@ -2014,14 +2135,16 @@ m5ioe1_snapshot_verify_t M5IOE1::verifySnapshot() { return result; } - // 验证 GPIO 寄存器 / Verify GPIO registers + // 验证 GPIO 寄存器 + // Verify GPIO registers if (_pinStatesValid) { uint16_t actualMode = 0, actualOutput = 0; if (_readReg16(M5IOE1_REG_GPIO_MODE_L, &actualMode) && _readReg16(M5IOE1_REG_GPIO_OUT_L, &actualOutput)) { - // 从缓存构建期望值 / Build expected values from cache + // 从缓存构建期望值 + // Build expected values from cache uint16_t expectedMode = 0, expectedOutput = 0; for (uint8_t i = 0; i < M5IOE1_MAX_GPIO_PINS; i++) { if (_pinStates[i].isOutput) { @@ -2046,7 +2169,8 @@ m5ioe1_snapshot_verify_t M5IOE1::verifySnapshot() { } } - // 验证 PWM 寄存器 / Verify PWM registers + // 验证 PWM 寄存器 + // Verify PWM registers if (_pwmStatesValid) { uint16_t actualFreq = 0; if (_readReg16(M5IOE1_REG_PWM_FREQ_L, &actualFreq)) { @@ -2074,7 +2198,8 @@ m5ioe1_snapshot_verify_t M5IOE1::verifySnapshot() { } } - // 验证 ADC 寄存器 / Verify ADC registers + // 验证 ADC 寄存器 + // Verify ADC registers if (_adcStateValid) { uint8_t ctrl = 0; if (_readReg(M5IOE1_REG_ADC_CTRL, &ctrl)) { @@ -2090,7 +2215,8 @@ m5ioe1_snapshot_verify_t M5IOE1::verifySnapshot() { } // ============================ -// 缓存状态查询函数 / Cached State Query Functions +// 缓存状态查询函数 +// Cached State Query Functions // ============================ bool M5IOE1::getCachedPwmFrequency(uint16_t* frequency) { @@ -2136,7 +2262,8 @@ bool M5IOE1::getCachedPinState(uint8_t pin, bool* isOutput, uint8_t* level, uint } // ============================ -// 平台特定函数 / Platform-Specific Functions +// 平台特定函数 +// Platform-Specific Functions // ============================ #ifdef ARDUINO @@ -2231,7 +2358,8 @@ bool M5IOE1::_setupHardwareInterrupt() { return false; } - // 创建任务以处理中断 / Create task to handle interrupts + // 创建任务以处理中断 + // Create task to handle interrupts xTaskCreatePinnedToCore( [](void* arg) { M5IOE1* self = static_cast(arg); @@ -2267,9 +2395,10 @@ void M5IOE1::_cleanupInterrupt() { _intrQueue = nullptr; } if (_intPin >= 0) { - // 移除 GPIO ISR handler / Remove GPIO ISR handler + // 移除 GPIO ISR handler + // Remove GPIO ISR handler // 如果返回错误(如"GPIO isr service is not installed")可忽略 - // 该错误表示当前未安装 ISR service,无需移除,属于预期行为 / The returned error (e.g., "GPIO isr service is not installed") can be ignored + // The returned error (e.g., "GPIO isr service is not installed") can be ignored // This error indicates that the ISR service is not currently installed and does not need to be removed, which is expected behavior esp_err_t err = gpio_isr_handler_remove((gpio_num_t)_intPin); if (err != ESP_OK) { diff --git a/src/M5IOE1.h b/src/M5IOE1.h index 7c30b20..98826ad 100644 --- a/src/M5IOE1.h +++ b/src/M5IOE1.h @@ -12,9 +12,11 @@ #include #ifdef ARDUINO -// Arduino:FreeRTOS 头文件通过 Arduino 框架包含 / Arduino: FreeRTOS headers included via Arduino framework +// Arduino:FreeRTOS 头文件通过 Arduino 框架包含 +// Arduino: FreeRTOS headers included via Arduino framework #else -// ESP-IDF 专用包含文件 / ESP-IDF specific includes +// ESP-IDF 专用包含文件 +// ESP-IDF specific includes #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" @@ -22,7 +24,8 @@ #endif // ============================ -// IO 引脚定义 / IO Pin Definitions +// IO 引脚定义 +// IO Pin Definitions // ============================ typedef enum { M5IOE1_PIN_NC = -1, @@ -43,7 +46,8 @@ typedef enum { } m5ioe1_pin_t; // ============================ -// 设备常量 / Device Constants +// 设备常量 +// Device Constants // ============================ #define M5IOE1_DEFAULT_ADDR 0x6F #define M5IOE1_MAX_GPIO_PINS 14 @@ -53,14 +57,16 @@ typedef enum { #define M5IOE1_RTC_RAM_SIZE 32 // ============================ -// I2C 频率常量 / I2C Frequency Constants +// I2C 频率常量 +// I2C Frequency Constants // ============================ #define M5IOE1_I2C_FREQ_100K 100000 #define M5IOE1_I2C_FREQ_400K 400000 #define M5IOE1_I2C_FREQ_DEFAULT M5IOE1_I2C_FREQ_100K // ============================ -// 寄存器地址 / Register Addresses +// 寄存器地址 +// Register Addresses // ============================ // System #define M5IOE1_REG_UID_L 0x00 // R [7:0] UID Low Byte @@ -119,7 +125,8 @@ typedef enum { #define M5IOE1_REG_AW8737A_PULSE 0x90 // R/W [7] REFRESH | [6:5] NUM | [4:0] GPIO // ============================ -// 位定义 / Bit Definitions +// 位定义 +// Bit Definitions // ============================ // ADC Control #define M5IOE1_ADC_CH_MASK 0x07 @@ -148,7 +155,8 @@ typedef enum { #define M5IOE1_AW8737A_REFRESH (1 << 7) // ============================ -// ADC 通道定义(支持 ADC 的 IO 引脚)/ ADC Channel Definitions (IO pins that support ADC) +// ADC 通道定义(支持 ADC 的 IO 引脚) +// ADC Channel Definitions (IO pins that support ADC) // ============================ #define M5IOE1_ADC_CH1 1 // IO2 (pin index 1) #define M5IOE1_ADC_CH2 2 // IO4 (pin index 3) @@ -156,7 +164,8 @@ typedef enum { #define M5IOE1_ADC_CH4 4 // IO7 (pin index 6) // ============================ -// PWM 通道定义(支持 PWM 的 IO 引脚)/ PWM Channel Definitions (IO pins that support PWM) +// PWM 通道定义(支持 PWM 的 IO 引脚) +// PWM Channel Definitions (IO pins that support PWM) // ============================ #define M5IOE1_PWM_CH1 0 // IO9 (pin index 8) #define M5IOE1_PWM_CH2 1 // IO8 (pin index 7) @@ -164,7 +173,8 @@ typedef enum { #define M5IOE1_PWM_CH4 3 // IO10 (pin index 9) // ============================ -// GPIO 模式定义(Arduino 兼容)/ GPIO Mode Definitions (Arduino-compatible) +// GPIO 模式定义(Arduino 兼容) +// GPIO Mode Definitions (Arduino-compatible) // ============================ #ifndef INPUT #define INPUT 0x00 @@ -180,7 +190,8 @@ typedef enum { #endif // ============================ -// GPIO 电平定义 / GPIO Level Definitions +// GPIO 电平定义 +// GPIO Level Definitions // ============================ #ifndef LOW #define LOW 0 @@ -190,7 +201,8 @@ typedef enum { #endif // ============================ -// 中断模式定义 / Interrupt Mode Definitions +// 中断模式定义 +// Interrupt Mode Definitions // ============================ #ifndef RISING #define RISING 0x01 @@ -200,72 +212,102 @@ typedef enum { #endif // ============================ -// 上拉/下拉模式定义 / Pull Mode Definitions +// 上拉/下拉模式定义 +// Pull Mode Definitions // ============================ #define M5IOE1_PULL_NONE 0x00 #define M5IOE1_PULL_UP 0x01 #define M5IOE1_PULL_DOWN 0x02 // ============================ -// 驱动模式定义 / Drive Mode Definitions +// 驱动模式定义 +// Drive Mode Definitions // ============================ #define M5IOE1_DRIVE_PUSHPULL 0x00 #define M5IOE1_DRIVE_OPENDRAIN 0x01 // ============================ -// AW8737A 脉冲刷新类型 / AW8737A PULSE Refresh Types +// AW8737A 脉冲刷新类型 +// AW8737A PULSE Refresh Types // ============================ typedef enum { - M5IOE1_AW8737A_REFRESH_WAIT = 0, // 不刷新,等待下一次触发 / No refresh, wait for next trigger - M5IOE1_AW8737A_REFRESH_NOW = 1 // 刷新并立即执行 / Refresh and execute immediately + M5IOE1_AW8737A_REFRESH_WAIT = 0, // 不刷新,等待下一次触发 + // No refresh, wait for next trigger + M5IOE1_AW8737A_REFRESH_NOW = 1 // 刷新并立即执行 + // Refresh and execute immediately } m5ioe1_aw8737a_refresh_t; // ============================ -// AW8737A 脉冲数量类型 / AW8737A PULSE NUM Types +// AW8737A 脉冲数量类型 +// AW8737A PULSE NUM Types // ============================ typedef enum { - M5IOE1_AW8737A_PULSE_NUM_0 = 0, // 0 个脉冲 / 0 pulse - M5IOE1_AW8737A_PULSE_NUM_1 = 1, // 1 个脉冲 / 1 pulse - M5IOE1_AW8737A_PULSE_NUM_2 = 2, // 2 个脉冲 / 2 pulses - M5IOE1_AW8737A_PULSE_NUM_3 = 3 // 3 个脉冲 / 3 pulses + M5IOE1_AW8737A_PULSE_NUM_0 = 0, // 0 个脉冲 + // 0 pulse + M5IOE1_AW8737A_PULSE_NUM_1 = 1, // 1 个脉冲 + // 1 pulse + M5IOE1_AW8737A_PULSE_NUM_2 = 2, // 2 个脉冲 + // 2 pulses + M5IOE1_AW8737A_PULSE_NUM_3 = 3 // 3 个脉冲 + // 3 pulses } m5ioe1_aw8737a_pulse_num_t; // ============================ -// 中断处理模式 / Interrupt Handling Mode +// 中断处理模式 +// Interrupt Handling Mode // ============================ typedef enum { - M5IOE1_INT_MODE_DISABLED = 0, // 中断处理已禁用 / Interrupt handling disabled - M5IOE1_INT_MODE_POLLING, // 轮询模式(默认)/ Polling mode (default) - M5IOE1_INT_MODE_HARDWARE // 硬件中断模式 / Hardware interrupt mode + M5IOE1_INT_MODE_DISABLED = 0, // 中断处理已禁用 + // Interrupt handling disabled + M5IOE1_INT_MODE_POLLING, // 轮询模式(默认) + // Polling mode (default) + M5IOE1_INT_MODE_HARDWARE // 硬件中断模式 + // Hardware interrupt mode } m5ioe1_int_mode_t; // ============================ -// 日志级别定义 / Log Level Definitions +// 日志级别定义 +// Log Level Definitions // ============================ typedef enum { - M5IOE1_LOG_LEVEL_NONE = 0, // 无日志输出 / No log output - M5IOE1_LOG_LEVEL_ERROR, // 仅错误消息 / Error messages only - M5IOE1_LOG_LEVEL_WARN, // 警告和错误消息 / Warning and error messages - M5IOE1_LOG_LEVEL_INFO, // 信息、警告和错误消息(默认)/ Info, warning and error messages (default) - M5IOE1_LOG_LEVEL_DEBUG, // 调试、信息、警告和错误消息 / Debug, info, warning and error messages - M5IOE1_LOG_LEVEL_VERBOSE // 所有消息包括详细输出 / All messages including verbose + M5IOE1_LOG_LEVEL_NONE = 0, // 无日志输出 + // No log output + M5IOE1_LOG_LEVEL_ERROR, // 仅错误消息 + // Error messages only + M5IOE1_LOG_LEVEL_WARN, // 警告和错误消息 + // Warning and error messages + M5IOE1_LOG_LEVEL_INFO, // 信息、警告和错误消息(默认) + // Info, warning and error messages (default) + M5IOE1_LOG_LEVEL_DEBUG, // 调试、信息、警告和错误消息 + // Debug, info, warning and error messages + M5IOE1_LOG_LEVEL_VERBOSE // 所有消息包括详细输出 + // All messages including verbose } m5ioe1_log_level_t; // ============================ -// 用于验证的配置类型 / Configuration Type for Validation +// 用于验证的配置类型 +// Configuration Type for Validation // ============================ typedef enum { - M5IOE1_CONFIG_GPIO_INPUT = 0, // GPIO 输入模式 / GPIO input mode - M5IOE1_CONFIG_GPIO_OUTPUT, // GPIO 输出模式 / GPIO output mode - M5IOE1_CONFIG_GPIO_INTERRUPT, // GPIO 中断模式 / GPIO interrupt mode - M5IOE1_CONFIG_ADC, // ADC 功能 / ADC function - M5IOE1_CONFIG_PWM, // PWM 功能 / PWM function - M5IOE1_CONFIG_NEOPIXEL, // NeoPixel LED 功能(仅 IO14)/ NeoPixel LED function (IO14 only) - M5IOE1_CONFIG_I2C_SLEEP // I2C 睡眠模式配置 / I2C sleep mode configuration + M5IOE1_CONFIG_GPIO_INPUT = 0, // GPIO 输入模式 + // GPIO input mode + M5IOE1_CONFIG_GPIO_OUTPUT, // GPIO 输出模式 + // GPIO output mode + M5IOE1_CONFIG_GPIO_INTERRUPT, // GPIO 中断模式 + // GPIO interrupt mode + M5IOE1_CONFIG_ADC, // ADC 功能 + // ADC function + M5IOE1_CONFIG_PWM, // PWM 功能 + // PWM function + M5IOE1_CONFIG_NEOPIXEL, // NeoPixel LED 功能(仅 IO14) + // NeoPixel LED function (IO14 only) + M5IOE1_CONFIG_I2C_SLEEP // I2C 睡眠模式配置 + // I2C sleep mode configuration } m5ioe1_config_type_t; // ============================ -// RGB 颜色结构 / RGB Color Structure +// RGB 颜色结构 +// RGB Color Structure // ============================ typedef struct { uint8_t r; @@ -274,7 +316,8 @@ typedef struct { } m5ioe1_rgb_t; // ============================ -// 配置验证结果 / Configuration Validation Result +// 配置验证结果 +// Configuration Validation Result // ============================ typedef struct { bool valid; @@ -283,27 +326,38 @@ typedef struct { } m5ioe1_validation_t; // ============================ -// 快照验证结果 / Snapshot Verification Result +// 快照验证结果 +// Snapshot Verification Result // ============================ typedef struct { - bool consistent; // 如果所有缓存值与硬件寄存器匹配则为 true / true if all cached values match hardware registers - bool gpio_mismatch; // 如果 GPIO 寄存器与缓存不匹配则为 true / true if GPIO registers don't match cache - bool pwm_mismatch; // 如果 PWM 寄存器与缓存不匹配则为 true / true if PWM registers don't match cache - bool adc_mismatch; // 如果 ADC 寄存器与缓存不匹配则为 true / true if ADC registers don't match cache - uint16_t expected_mode; // 缓存的 GPIO 模式寄存器值 / cached GPIO mode register value - uint16_t actual_mode; // 实际的 GPIO 模式寄存器值 / actual GPIO mode register value - uint16_t expected_output; // 缓存的 GPIO 输出寄存器值 / cached GPIO output register value - uint16_t actual_output; // 实际的 GPIO 输出寄存器值 / actual GPIO output register value + bool consistent; // 如果所有缓存值与硬件寄存器匹配则为 true + // true if all cached values match hardware registers + bool gpio_mismatch; // 如果 GPIO 寄存器与缓存不匹配则为 true + // true if GPIO registers don't match cache + bool pwm_mismatch; // 如果 PWM 寄存器与缓存不匹配则为 true + // true if PWM registers don't match cache + bool adc_mismatch; // 如果 ADC 寄存器与缓存不匹配则为 true + // true if ADC registers don't match cache + uint16_t expected_mode; // 缓存的 GPIO 模式寄存器值 + // cached GPIO mode register value + uint16_t actual_mode; // 实际的 GPIO 模式寄存器值 + // actual GPIO mode register value + uint16_t expected_output; // 缓存的 GPIO 输出寄存器值 + // cached GPIO output register value + uint16_t actual_output; // 实际的 GPIO 输出寄存器值 + // actual GPIO output register value } m5ioe1_snapshot_verify_t; // ============================ -// 回调类型 / Callback Types +// 回调类型 +// Callback Types // ============================ typedef void (*m5ioe1_callback_t)(void); typedef void (*m5ioe1_callback_arg_t)(void*); // ============================ -// M5IOE1 类 / M5IOE1 Class +// M5IOE1 类 +// M5IOE1 Class // ============================ class M5IOE1 { public: @@ -311,7 +365,8 @@ public: ~M5IOE1(); // ======================== - // 初始化 / Initialization + // 初始化 + // Initialization // ======================== #ifdef ARDUINO /** @@ -476,28 +531,32 @@ public: static m5ioe1_log_level_t getLogLevel(); // ======================== - // 设备信息 / Device Information + // 设备信息 + // Device Information // ======================== bool getUID(uint16_t* uid); bool getVersion(uint8_t* version); bool getRefVoltage(uint16_t* voltage_mv); // ======================== - // GPIO 功能(Arduino 风格)/ GPIO Functions (Arduino-style) + // GPIO 功能(Arduino 风格) + // GPIO Functions (Arduino-style) // ======================== void pinMode(uint8_t pin, uint8_t mode); void digitalWrite(uint8_t pin, uint8_t value); int digitalRead(uint8_t pin); // ======================== - // 高级 GPIO 功能 / Advanced GPIO Functions + // 高级 GPIO 功能 + // Advanced GPIO Functions // ======================== bool setPullMode(uint8_t pin, uint8_t pullMode); bool setDriveMode(uint8_t pin, uint8_t driveMode); bool getInputState(uint8_t pin, uint8_t* state); // ======================== - // 中断功能 / Interrupt Functions + // 中断功能 + // Interrupt Functions // ======================== void attachInterrupt(uint8_t pin, m5ioe1_callback_t callback, uint8_t mode); void attachInterruptArg(uint8_t pin, m5ioe1_callback_arg_t callback, void* arg, uint8_t mode); @@ -508,7 +567,8 @@ public: bool clearInterrupt(uint8_t pin); // ======================== - // ADC 功能 / ADC Functions + // ADC 功能 + // ADC Functions // ======================== /** * @brief Read ADC value @@ -521,13 +581,15 @@ public: bool disableAdc(); // ======================== - // 温度传感器 / Temperature Sensor + // 温度传感器 + // Temperature Sensor // ======================== bool readTemperature(uint16_t* temperature); bool isTemperatureBusy(); // ======================== - // PWM 功能 / PWM Functions + // PWM 功能 + // PWM Functions // ======================== /** * @brief Set PWM frequency (shared by all channels) @@ -559,7 +621,8 @@ public: bool getPwmDuty(uint8_t channel, uint8_t* duty, bool* polarity, bool* enable); // ======================== - // NeoPixel LED 功能 / NeoPixel LED Functions + // NeoPixel LED 功能 + // NeoPixel LED Functions // ======================== bool setLedCount(uint8_t count); bool setLedColor(uint8_t index, uint8_t r, uint8_t g, uint8_t b); @@ -568,7 +631,8 @@ public: bool disableLeds(); // ======================== - // AW8737A 脉冲功能 / AW8737A Pulse Functions + // AW8737A 脉冲功能 + // AW8737A Pulse Functions // ======================== /** * @brief Set AW8737A pulse output configuration @@ -592,26 +656,30 @@ public: bool refreshAw8737aPulse(); // ======================== - // RTC RAM 功能 / RTC RAM Functions + // RTC RAM 功能 + // RTC RAM Functions // ======================== bool writeRtcRAM(uint8_t offset, const uint8_t* data, uint8_t length); bool readRtcRAM(uint8_t offset, uint8_t* data, uint8_t length); // ======================== - // 系统配置 / System Configuration + // 系统配置 + // System Configuration // ======================== bool setI2cConfig(uint8_t sleepTime, bool speed400k = false, bool wakeRising = false, bool pullOff = false); bool factoryReset(); // ======================== - // 状态快照功能 / State Snapshot Functions + // 状态快照功能 + // State Snapshot Functions // ======================== void setAutoSnapshot(bool enable); bool isAutoSnapshotEnabled() const; bool updateSnapshot(); // ======================== - // 调试功能 / Debug Functions + // 调试功能 + // Debug Functions // ======================== bool getModeReg(uint16_t* reg); bool getOutputReg(uint16_t* reg); @@ -621,7 +689,8 @@ public: bool getDriveReg(uint16_t* reg); // ======================== - // 配置验证 / Configuration Validation + // 配置验证 + // Configuration Validation // ======================== /** * @brief Validate pin configuration before applying @@ -633,7 +702,8 @@ public: m5ioe1_validation_t validateConfig(uint8_t pin, m5ioe1_config_type_t configType, bool enable = true); // ======================== - // 快照验证 / Snapshot Verification + // 快照验证 + // Snapshot Verification // ======================== /** * @brief Verify that cached state matches actual hardware registers @@ -642,7 +712,8 @@ public: m5ioe1_snapshot_verify_t verifySnapshot(); // ======================== - // 缓存状态查询函数 / Cached State Query Functions + // 缓存状态查询函数 + // Cached State Query Functions // ======================== /** * @brief Get cached PWM frequency @@ -687,49 +758,68 @@ public: void enableDefaultInterruptLog(bool enable); private: - // 设备状态 / Device state + // 设备状态 + // Device state uint8_t _addr; bool _initialized; bool _autoSnapshot; bool _enableDefaultIsrLog; - uint32_t _requestedSpeed; // 用户请求的 I2C 速度(用于 400K 切换)/ User requested I2C speed (for 400K switch) + uint32_t _requestedSpeed; // 用户请求的 I2C 速度(用于 400K 切换) + // User requested I2C speed (for 400K switch) - // 中断模式 / Interrupt mode + // 中断模式 + // Interrupt mode m5ioe1_int_mode_t _intMode; int8_t _intPin; uint32_t _pollingInterval; #ifdef ARDUINO TwoWire *_wire; - uint8_t _sda; // SDA 引脚编号,用于 I2C 重新初始化 / SDA pin number for I2C re-initialization - uint8_t _scl; // SCL 引脚编号,用于 I2C 重新初始化 / SCL pin number for I2C re-initialization + uint8_t _sda; // SDA 引脚编号,用于 I2C 重新初始化 + // SDA pin number for I2C re-initialization + uint8_t _scl; // SCL 引脚编号,用于 I2C 重新初始化 + // SCL pin number for I2C re-initialization #else - // I2C 驱动类型选择 / I2C driver type selection + // I2C 驱动类型选择 + // I2C driver type selection m5ioe1_i2c_driver_t _i2cDriverType; - // I2C 句柄(根据驱动类型仅使用一对)/ I2C handles (only one pair is used based on driver type) - // M5IOE1_I2C_DRIVER_SELF_CREATED: 使用 _i2c_master_bus + _i2c_master_dev / uses _i2c_master_bus + _i2c_master_dev - // M5IOE1_I2C_DRIVER_MASTER: 使用 _i2c_master_bus + _i2c_master_dev / uses _i2c_master_bus + _i2c_master_dev - // M5IOE1_I2C_DRIVER_BUS: 使用 _i2c_bus + _i2c_device / uses _i2c_bus + _i2c_device - i2c_master_bus_handle_t _i2c_master_bus; // ESP-IDF 原生驱动/自创建 / ESP-IDF native driver / self-created - i2c_master_dev_handle_t _i2c_master_dev; // ESP-IDF 原生驱动/自创建 / ESP-IDF native driver / self-created - i2c_bus_handle_t _i2c_bus; // esp-idf-lib 组件 / esp-idf-lib component - i2c_bus_device_handle_t _i2c_device; // esp-idf-lib 组件 / esp-idf-lib component + // I2C 句柄(根据驱动类型仅使用一对) + // I2C handles (only one pair is used based on driver type) + // M5IOE1_I2C_DRIVER_SELF_CREATED: 使用 _i2c_master_bus + _i2c_master_dev + // uses _i2c_master_bus + _i2c_master_dev + // M5IOE1_I2C_DRIVER_MASTER: 使用 _i2c_master_bus + _i2c_master_dev + // uses _i2c_master_bus + _i2c_master_dev + // M5IOE1_I2C_DRIVER_BUS: 使用 _i2c_bus + _i2c_device + // uses _i2c_bus + _i2c_device + i2c_master_bus_handle_t _i2c_master_bus; // ESP-IDF 原生驱动/自创建 + // ESP-IDF native driver / self-created + i2c_master_dev_handle_t _i2c_master_dev; // ESP-IDF 原生驱动/自创建 + // ESP-IDF native driver / self-created + i2c_bus_handle_t _i2c_bus; // esp-idf-lib 组件 + // esp-idf-lib component + i2c_bus_device_handle_t _i2c_device; // esp-idf-lib 组件 + // esp-idf-lib component - // I2C 管理标志 / I2C management flags - bool _busExternal; // 如果总线句柄由外部提供则为 true / true if bus handle is provided externally + // I2C 管理标志 + // I2C management flags + bool _busExternal; // 如果总线句柄由外部提供则为 true + // true if bus handle is provided externally - // 自创建总线的 I2C 引脚(用于频率切换)/ I2C pins for self-created bus (for frequency switching) + // 自创建总线的 I2C 引脚(用于频率切换) + // I2C pins for self-created bus (for frequency switching) int _sda; int _scl; i2c_port_t _port; - // 中断处理 / Interrupt handling + // 中断处理 + // Interrupt handling TaskHandle_t _pollTask; QueueHandle_t _intrQueue; #endif - // 中断回调 / Interrupt callbacks + // 中断回调 + // Interrupt callbacks struct { m5ioe1_callback_t callback; m5ioe1_callback_arg_t callbackArg; @@ -738,19 +828,23 @@ private: bool rising; } _callbacks[M5IOE1_MAX_GPIO_PINS]; - // 缓存的引脚状态 / Cached pin states + // 缓存的引脚状态 + // Cached pin states struct { bool isOutput; uint8_t outputLevel; uint8_t inputLevel; - uint8_t pull; // 0:无, 1:上拉, 2:下拉 / 0:none, 1:up, 2:down - uint8_t drive; // 0:推挽, 1:开漏 / 0:push-pull, 1:open-drain + uint8_t pull; // 0:无, 1:上拉, 2:下拉 + // 0:none, 1:up, 2:down + uint8_t drive; // 0:推挽, 1:开漏 + // 0:push-pull, 1:open-drain bool intrEnabled; bool intrRising; } _pinStates[M5IOE1_MAX_GPIO_PINS]; bool _pinStatesValid; - // 缓存的 PWM 状态 / Cached PWM states + // 缓存的 PWM 状态 + // Cached PWM states struct { uint16_t duty12; bool enabled; @@ -759,7 +853,8 @@ private: uint16_t _pwmFrequency; bool _pwmStatesValid; - // 缓存的 ADC 状态 / Cached ADC state + // 缓存的 ADC 状态 + // Cached ADC state struct { uint8_t activeChannel; bool busy; @@ -767,21 +862,28 @@ private: } _adcState; bool _adcStateValid; - // 缓存的 I2C 配置状态(用于睡眠模式检测)/ Cached I2C config state (for sleep mode detection) + // 缓存的 I2C 配置状态(用于睡眠模式检测) + // Cached I2C config state (for sleep mode detection) struct { - uint8_t sleepTime; // 0=禁用, 1-15=睡眠时间 / 0=disabled, 1-15=sleep time - bool speed400k; // I2C 速度模式 / I2C speed mode - bool wakeRising; // 唤醒边沿模式 / Wake edge mode - bool pullOff; // 内部上拉关闭 / Internal pull-up off + uint8_t sleepTime; // 0=禁用, 1-15=睡眠时间 + // 0=disabled, 1-15=sleep time + bool speed400k; // I2C 速度模式 + // I2C speed mode + bool wakeRising; // 唤醒边沿模式 + // Wake edge mode + bool pullOff; // 内部上拉关闭 + // Internal pull-up off } _i2cConfig; bool _i2cConfigValid; - // NeoPixel 状态 / NeoPixel state + // NeoPixel 状态 + // NeoPixel state uint8_t _ledCount; bool _ledEnabled; // ======================== - // 内部辅助函数 / Internal Helper Functions + // 内部辅助函数 + // Internal Helper Functions // ======================== bool _writeReg(uint8_t reg, uint8_t value); bool _writeReg16(uint8_t reg, uint16_t value); @@ -807,15 +909,18 @@ private: bool _initDevice(); void _handleInterrupt(); - // I2C 频率验证和切换 / I2C frequency validation and switching + // I2C 频率验证和切换 + // I2C frequency validation and switching bool _isValidI2cFrequency(uint32_t speed); bool _switchTo400K(); - // 中断互斥对检查 / Interrupt mutex pairs check + // 中断互斥对检查 + // Interrupt mutex pairs check static bool _pinsConflict(uint8_t a, uint8_t b); bool _hasConflictingInterrupt(uint8_t pin); - // 配置验证辅助函数 / Configuration validation helpers + // 配置验证辅助函数 + // Configuration validation helpers bool _getInterruptMutexPin(uint8_t pin, uint8_t* mutexPin); bool _isNeopixelPin(uint8_t pin); bool _hasActiveInterrupt(uint8_t pin); @@ -824,17 +929,20 @@ private: bool _hasI2cSleepEnabled(); bool _isLedEnabled(); - // I2C 配置快照 / I2C config snapshot + // I2C 配置快照 + // I2C config snapshot void _clearI2cConfig(); bool _snapshotI2cConfig(); #ifdef ARDUINO - // Arduino 专用 / Arduino specific + // Arduino 专用 + // Arduino specific bool _setupPollingArduino(); void _cleanupPollingArduino(); static void _pollTaskArduino(void* arg); #else - // ESP-IDF 专用 / ESP-IDF specific + // ESP-IDF 专用 + // ESP-IDF specific static void _pollTaskFunc(void* arg); static void IRAM_ATTR _isrHandler(void* arg); bool _setupHardwareInterrupt(); diff --git a/src/M5IOE1_i2c_compat.h b/src/M5IOE1_i2c_compat.h index 39dd858..9f80254 100644 --- a/src/M5IOE1_i2c_compat.h +++ b/src/M5IOE1_i2c_compat.h @@ -16,7 +16,8 @@ #include "Wire.h" // ============================ -// Arduino I2C 功能 / Arduino I2C Functions +// Arduino I2C 功能 +// Arduino I2C Functions // ============================ #ifndef M5IOE1_I2C_READ_BYTE @@ -57,7 +58,8 @@ static inline bool M5IOE1_I2C_READ_REG16(TwoWire *wire, uint8_t addr, uint8_t re if (!M5IOE1_I2C_READ_BYTES(wire, addr, reg, 2, buf)) { return false; } - // 小端模式:低字节在前 / Little-endian: low byte first + // 小端模式:低字节在前 + // Little-endian: low byte first *data = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8); return true; } @@ -92,7 +94,8 @@ static inline bool M5IOE1_I2C_WRITE_BYTES(TwoWire *wire, uint8_t addr, uint8_t s #ifndef M5IOE1_I2C_WRITE_REG16 static inline bool M5IOE1_I2C_WRITE_REG16(TwoWire *wire, uint8_t addr, uint8_t reg, uint16_t data) { uint8_t buf[2]; - // 小端模式:低字节在前 / Little-endian: low byte first + // 小端模式:低字节在前 + // Little-endian: low byte first buf[0] = (uint8_t)(data & 0xFF); buf[1] = (uint8_t)((data >> 8) & 0xFF); return M5IOE1_I2C_WRITE_BYTES(wire, addr, reg, 2, buf); @@ -110,17 +113,23 @@ extern "C" { #endif // ============================ -// I2C 驱动类型选择 / I2C Driver Type Selection +// I2C 驱动类型选择 +// I2C Driver Type Selection // ============================ typedef enum { - M5IOE1_I2C_DRIVER_NONE = 0, // 未初始化 / Not initialized - M5IOE1_I2C_DRIVER_SELF_CREATED, // 使用 i2c_port_t 自创建 / Self-created using i2c_port_t - M5IOE1_I2C_DRIVER_MASTER, // ESP-IDF 原生 i2c_master 驱动 / ESP-IDF native i2c_master driver - M5IOE1_I2C_DRIVER_BUS // esp-idf-lib i2c_bus 组件 / esp-idf-lib i2c_bus component + M5IOE1_I2C_DRIVER_NONE = 0, // 未初始化 + // Not initialized + M5IOE1_I2C_DRIVER_SELF_CREATED, // 使用 i2c_port_t 自创建 + // Self-created using i2c_port_t + M5IOE1_I2C_DRIVER_MASTER, // ESP-IDF 原生 i2c_master 驱动 + // ESP-IDF native i2c_master driver + M5IOE1_I2C_DRIVER_BUS // esp-idf-lib i2c_bus 组件 + // esp-idf-lib i2c_bus component } m5ioe1_i2c_driver_t; // ============================ -// ESP-IDF I2C 函数 / ESP-IDF I2C Functions (i2c_bus) +// ESP-IDF I2C 函数 (i2c_bus) +// ESP-IDF I2C Functions (i2c_bus) // ============================ #ifndef M5IOE1_I2C_READ_BYTE @@ -140,7 +149,8 @@ static inline esp_err_t M5IOE1_I2C_READ_REG16(i2c_bus_device_handle_t dev, uint8 uint8_t buf[2]; esp_err_t ret = i2c_bus_read_bytes(dev, reg, 2, buf); if (ret == ESP_OK) { - // 小端模式:低字节在前 / Little-endian: low byte first + // 小端模式:低字节在前 + // Little-endian: low byte first *data = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8); } return ret; @@ -162,7 +172,8 @@ static inline esp_err_t M5IOE1_I2C_WRITE_BYTES(i2c_bus_device_handle_t dev, uint #ifndef M5IOE1_I2C_WRITE_REG16 static inline esp_err_t M5IOE1_I2C_WRITE_REG16(i2c_bus_device_handle_t dev, uint8_t reg, uint16_t data) { uint8_t buf[2]; - // 小端模式:低字节在前 / Little-endian: low byte first + // 小端模式:低字节在前 + // Little-endian: low byte first buf[0] = (uint8_t)(data & 0xFF); buf[1] = (uint8_t)((data >> 8) & 0xFF); return i2c_bus_write_bytes(dev, reg, 2, buf); @@ -170,7 +181,8 @@ static inline esp_err_t M5IOE1_I2C_WRITE_REG16(i2c_bus_device_handle_t dev, uint #endif // ============================ -// ESP-IDF I2C 函数 (i2c_master - 原生驱动) / ESP-IDF I2C Functions (i2c_master - native driver) +// ESP-IDF I2C 函数 (i2c_master - 原生驱动) +// ESP-IDF I2C Functions (i2c_master - native driver) // ============================ #ifndef M5IOE1_I2C_MASTER_READ_BYTE @@ -190,7 +202,8 @@ static inline esp_err_t M5IOE1_I2C_MASTER_READ_REG16(i2c_master_dev_handle_t dev uint8_t buf[2]; esp_err_t ret = i2c_master_transmit_receive(dev, ®, 1, buf, 2, -1); if (ret == ESP_OK) { - // 小端模式:低字节在前 / Little-endian: low byte first + // 小端模式:低字节在前 + // Little-endian: low byte first *data = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8); } return ret; @@ -206,7 +219,8 @@ static inline esp_err_t M5IOE1_I2C_MASTER_WRITE_BYTE(i2c_master_dev_handle_t dev #ifndef M5IOE1_I2C_MASTER_WRITE_BYTES static inline esp_err_t M5IOE1_I2C_MASTER_WRITE_BYTES(i2c_master_dev_handle_t dev, uint8_t start_reg, size_t len, const uint8_t *data) { - // 需要在数据前添加寄存器地址 / Need to prepend register address + // 需要在数据前添加寄存器地址 + // Need to prepend register address uint8_t *buf = (uint8_t*)malloc(len + 1); if (buf == NULL) return ESP_ERR_NO_MEM; buf[0] = start_reg; @@ -221,7 +235,8 @@ static inline esp_err_t M5IOE1_I2C_MASTER_WRITE_BYTES(i2c_master_dev_handle_t de static inline esp_err_t M5IOE1_I2C_MASTER_WRITE_REG16(i2c_master_dev_handle_t dev, uint8_t reg, uint16_t data) { uint8_t buf[3]; buf[0] = reg; - // 小端模式:低字节在前 / Little-endian: low byte first + // 小端模式:低字节在前 + // Little-endian: low byte first buf[1] = (uint8_t)(data & 0xFF); buf[2] = (uint8_t)((data >> 8) & 0xFF); return i2c_master_transmit(dev, buf, 3, -1);