mirror of
https://github.com/m5stack/M5PM1.git
synced 2026-05-20 11:49:32 -07:00
1. Support for the M5Unified I2C_Class driver
This commit is contained in:
@@ -7,3 +7,7 @@ idf_component_register(
|
||||
"driver"
|
||||
"espressif__i2c_bus"
|
||||
)
|
||||
|
||||
# M5Unified 为可选依赖:组件存在时自动添加,否则静默跳过
|
||||
# M5Unified is optional: added automatically if present, silently ignored otherwise.
|
||||
idf_component_optional_requires(PRIVATE M5Unified)
|
||||
|
||||
+131
-9
@@ -172,6 +172,10 @@ M5PM1::M5PM1()
|
||||
_sda = -1;
|
||||
_scl = -1;
|
||||
_port = I2C_NUM_0;
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
_m5_i2c = nullptr;
|
||||
_commFreq = M5PM1_I2C_FREQ_100K;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -824,6 +828,84 @@ m5pm1_err_t M5PM1::begin(i2c_bus_handle_t bus, uint8_t addr, uint32_t speed)
|
||||
}
|
||||
#endif // M5PM1_HAS_I2C_BUS
|
||||
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
m5pm1_err_t M5PM1::begin(m5::I2C_Class* i2c, uint8_t addr, uint32_t speed)
|
||||
{
|
||||
if (i2c == nullptr || !i2c->isEnabled()) {
|
||||
M5PM1_LOG_E(TAG, "M5Unified I2C_Class is null or not initialized");
|
||||
return M5PM1_ERR_I2C_CONFIG;
|
||||
}
|
||||
|
||||
_addr = addr;
|
||||
_m5_i2c = i2c;
|
||||
_busExternal = true;
|
||||
_i2cDriverType = M5PM1_I2C_DRIVER_M5UNIFIED;
|
||||
|
||||
// 步骤1:校验用户频率并记录
|
||||
// Step 1: Validate requested speed
|
||||
if (!_isValidI2cFrequency(speed)) {
|
||||
M5PM1_LOG_W(TAG, "Invalid I2C frequency: %lu Hz. Falling back to 100KHz.", (unsigned long)speed);
|
||||
_requestedSpeed = M5PM1_I2C_FREQ_100K;
|
||||
} else {
|
||||
_requestedSpeed = speed;
|
||||
}
|
||||
|
||||
// 步骤2:以 100KHz 发送唤醒信号
|
||||
// Step 2: Send wake signal at 100KHz
|
||||
_commFreq = M5PM1_I2C_FREQ_100K;
|
||||
M5PM1_M5UNIFIED_SEND_WAKE(_m5_i2c, _addr, _commFreq);
|
||||
M5PM1_DELAY_MS(10);
|
||||
|
||||
// 步骤3:验证设备通信(失败则等待 800ms 重试一次)
|
||||
// Step 3: Verify device communication (retry once after 800ms)
|
||||
if (!_initDevice()) {
|
||||
M5PM1_LOG_W(TAG, "Device init failed, retrying after 800ms...");
|
||||
M5PM1_DELAY_MS(800);
|
||||
M5PM1_M5UNIFIED_SEND_WAKE(_m5_i2c, _addr, _commFreq);
|
||||
M5PM1_DELAY_MS(10);
|
||||
if (!_initDevice()) {
|
||||
// 100K 再次失败,尝试 400K
|
||||
// 100K failed again, try 400K
|
||||
M5PM1_LOG_W(TAG, "Device init failed at 100KHz (retry), trying 400KHz...");
|
||||
_commFreq = M5PM1_I2C_FREQ_400K;
|
||||
M5PM1_M5UNIFIED_SEND_WAKE(_m5_i2c, _addr, _commFreq);
|
||||
M5PM1_DELAY_MS(10);
|
||||
if (!_initDevice()) {
|
||||
M5PM1_LOG_E(TAG, "Failed at 100KHz (twice) and 400KHz");
|
||||
_i2cDriverType = M5PM1_I2C_DRIVER_NONE;
|
||||
_m5_i2c = nullptr;
|
||||
return M5PM1_ERR_I2C_COMM;
|
||||
}
|
||||
}
|
||||
}
|
||||
_initialized = true;
|
||||
|
||||
// 步骤4:配置设备 I2C 参数(关闭睡眠 + 目标频率)
|
||||
// Step 4: Configure device I2C (disable sleep + target speed)
|
||||
m5pm1_i2c_speed_t targetSpeed =
|
||||
(_requestedSpeed == M5PM1_I2C_FREQ_400K) ? M5PM1_I2C_SPEED_400K : M5PM1_I2C_SPEED_100K;
|
||||
if (setI2cConfig(0, targetSpeed) != M5PM1_OK) {
|
||||
M5PM1_LOG_W(TAG, "Failed to set I2C config");
|
||||
}
|
||||
|
||||
// 步骤5:切换通信频率到目标亟(M5Unified 无需重装驱动,直接更新 _commFreq)
|
||||
// Step 5: Switch to target frequency (no driver reinstall needed; update _commFreq only)
|
||||
_commFreq = _requestedSpeed;
|
||||
|
||||
// 步骤6:刷新快照并完成初始化
|
||||
// Step 6: Refresh snapshot and finish initialization
|
||||
_lastCommTime = M5PM1_GET_TIME_MS();
|
||||
if (!_snapshotAll()) {
|
||||
_clearAll();
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
M5PM1_LOG_I(TAG, "M5PM1 initialized via M5Unified I2C at address 0x%02X (%lu Hz)", _addr,
|
||||
(unsigned long)_requestedSpeed);
|
||||
return M5PM1_OK;
|
||||
}
|
||||
#endif // M5PM1_HAS_M5UNIFIED_I2C
|
||||
|
||||
#endif // ARDUINO
|
||||
|
||||
// ============================
|
||||
@@ -1393,6 +1475,11 @@ bool M5PM1::_writeReg(uint8_t reg, uint8_t value)
|
||||
case M5PM1_I2C_DRIVER_LEGACY:
|
||||
success = M5PM1_I2C_LEGACY_WRITE_BYTE(_port, _addr, reg, value) == ESP_OK;
|
||||
break;
|
||||
#endif
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
case M5PM1_I2C_DRIVER_M5UNIFIED:
|
||||
success = M5PM1_M5UNIFIED_WRITE_BYTE(_m5_i2c, _addr, reg, value, _commFreq);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
success = false;
|
||||
@@ -1434,6 +1521,11 @@ bool M5PM1::_writeReg16(uint8_t reg, uint16_t value)
|
||||
case M5PM1_I2C_DRIVER_LEGACY:
|
||||
success = M5PM1_I2C_LEGACY_WRITE_REG16(_port, _addr, reg, value) == ESP_OK;
|
||||
break;
|
||||
#endif
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
case M5PM1_I2C_DRIVER_M5UNIFIED:
|
||||
success = M5PM1_M5UNIFIED_WRITE_REG16(_m5_i2c, _addr, reg, value, _commFreq);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
success = false;
|
||||
@@ -1475,6 +1567,11 @@ bool M5PM1::_readReg(uint8_t reg, uint8_t* value)
|
||||
case M5PM1_I2C_DRIVER_LEGACY:
|
||||
success = M5PM1_I2C_LEGACY_READ_BYTE(_port, _addr, reg, value) == ESP_OK;
|
||||
break;
|
||||
#endif
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
case M5PM1_I2C_DRIVER_M5UNIFIED:
|
||||
success = M5PM1_M5UNIFIED_READ_BYTE(_m5_i2c, _addr, reg, value, _commFreq);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
success = false;
|
||||
@@ -1516,6 +1613,11 @@ bool M5PM1::_readReg16(uint8_t reg, uint16_t* value)
|
||||
case M5PM1_I2C_DRIVER_LEGACY:
|
||||
success = M5PM1_I2C_LEGACY_READ_REG16(_port, _addr, reg, value) == ESP_OK;
|
||||
break;
|
||||
#endif
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
case M5PM1_I2C_DRIVER_M5UNIFIED:
|
||||
success = M5PM1_M5UNIFIED_READ_REG16(_m5_i2c, _addr, reg, value, _commFreq);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
success = false;
|
||||
@@ -1557,6 +1659,11 @@ bool M5PM1::_writeBytes(uint8_t reg, const uint8_t* data, uint8_t len)
|
||||
case M5PM1_I2C_DRIVER_LEGACY:
|
||||
success = M5PM1_I2C_LEGACY_WRITE_BYTES(_port, _addr, reg, len, data) == ESP_OK;
|
||||
break;
|
||||
#endif
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
case M5PM1_I2C_DRIVER_M5UNIFIED:
|
||||
success = M5PM1_M5UNIFIED_WRITE_BYTES(_m5_i2c, _addr, reg, len, data, _commFreq);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
success = false;
|
||||
@@ -1598,6 +1705,11 @@ bool M5PM1::_readBytes(uint8_t reg, uint8_t* data, uint8_t len)
|
||||
case M5PM1_I2C_DRIVER_LEGACY:
|
||||
success = M5PM1_I2C_LEGACY_READ_BYTES(_port, _addr, reg, len, data) == ESP_OK;
|
||||
break;
|
||||
#endif
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
case M5PM1_I2C_DRIVER_M5UNIFIED:
|
||||
success = M5PM1_M5UNIFIED_READ_BYTES(_m5_i2c, _addr, reg, len, data, _commFreq);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
success = false;
|
||||
@@ -2392,7 +2504,7 @@ m5pm1_err_t M5PM1::boostSetPowerHold(bool enable)
|
||||
if (!_readReg(M5PM1_REG_HOLD_CFG, ®Val)) return M5PM1_ERR_I2C_COMM;
|
||||
|
||||
if (enable) {
|
||||
regVal |= (1 << 6); // DCDC bit
|
||||
regVal |= (1 << 6); // BOOST bit
|
||||
} else {
|
||||
regVal &= ~(1 << 6);
|
||||
}
|
||||
@@ -2767,9 +2879,11 @@ m5pm1_err_t M5PM1::setPwmConfig(m5pm1_pwm_channel_t channel, bool enable, bool p
|
||||
}
|
||||
}
|
||||
|
||||
m5pm1_err_t err = setPwmDuty12bit(channel, duty12, polarity, enable);
|
||||
// 先设频率再设 duty,避免频率设置失败时 duty 已以旧频率写入
|
||||
// Set frequency first, then duty, to avoid duty being written with old frequency if frequency fails
|
||||
m5pm1_err_t err = setPwmFrequency(frequency);
|
||||
if (err != M5PM1_OK) return err;
|
||||
return setPwmFrequency(frequency);
|
||||
return setPwmDuty12bit(channel, duty12, polarity, enable);
|
||||
}
|
||||
|
||||
m5pm1_err_t M5PM1::analogWrite(m5pm1_pwm_channel_t channel, uint8_t value)
|
||||
@@ -4157,8 +4271,9 @@ m5pm1_err_t M5PM1::setAw8737aPulse(m5pm1_gpio_num_t pin, m5pm1_aw8737a_pulse_t n
|
||||
|
||||
// 检查引脚是否为输出模式,如果不是则自动配置为推挽输出
|
||||
// Check if pin is output mode, if not auto-configure as push-pull output
|
||||
if (_pinStatus[pin].mode != M5PM1_GPIO_MODE_OUTPUT) {
|
||||
M5PM1_LOG_I(TAG, "AW8737A: Pin %d not output mode, auto-configuring as push-pull output", pin);
|
||||
if (!_cacheValid || _pinStatus[pin].mode != M5PM1_GPIO_MODE_OUTPUT) {
|
||||
M5PM1_LOG_I(TAG, "AW8737A: Pin %d not output mode (or cache invalid), auto-configuring as push-pull output",
|
||||
pin);
|
||||
pinMode(pin, OUTPUT);
|
||||
}
|
||||
|
||||
@@ -4228,8 +4343,9 @@ m5pm1_err_t M5PM1::refreshAw8737aPulse()
|
||||
|
||||
// 检查引脚是否为输出模式,如果不是则自动配置为推挽输出
|
||||
// Check if pin is output mode, if not auto-configure as push-pull output
|
||||
if (_pinStatus[_aw8737aPin].mode != M5PM1_GPIO_MODE_OUTPUT) {
|
||||
M5PM1_LOG_I(TAG, "AW8737A: Pin %d not output mode, auto-configuring as push-pull output", _aw8737aPin);
|
||||
if (!_cacheValid || _pinStatus[_aw8737aPin].mode != M5PM1_GPIO_MODE_OUTPUT) {
|
||||
M5PM1_LOG_I(TAG, "AW8737A: Pin %d not output mode (or cache invalid), auto-configuring as push-pull output",
|
||||
_aw8737aPin);
|
||||
pinMode(_aw8737aPin, OUTPUT);
|
||||
}
|
||||
|
||||
@@ -4729,6 +4845,10 @@ m5pm1_err_t M5PM1::sendWakeSignal()
|
||||
#if !M5PM1_HAS_I2C_MASTER && !M5PM1_HAS_I2C_BUS
|
||||
case M5PM1_I2C_DRIVER_LEGACY:
|
||||
return M5PM1_I2C_LEGACY_SEND_WAKE(_port, _addr);
|
||||
#endif
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
case M5PM1_I2C_DRIVER_M5UNIFIED:
|
||||
return M5PM1_M5UNIFIED_SEND_WAKE(_m5_i2c, _addr, _commFreq) ? M5PM1_OK : M5PM1_ERR_I2C_COMM;
|
||||
#endif
|
||||
default:
|
||||
return M5PM1_ERR_INTERNAL;
|
||||
@@ -4764,7 +4884,7 @@ m5pm1_err_t M5PM1::updateSnapshot()
|
||||
|
||||
m5pm1_snapshot_verify_t M5PM1::verifySnapshot()
|
||||
{
|
||||
m5pm1_snapshot_verify_t result = {0};
|
||||
m5pm1_snapshot_verify_t result = {};
|
||||
result.consistent = true;
|
||||
|
||||
if (!_initialized) {
|
||||
@@ -4844,7 +4964,9 @@ m5pm1_snapshot_verify_t M5PM1::verifySnapshot()
|
||||
uint8_t actualChannel = (ctrl >> 1) & 0x07;
|
||||
bool actualBusy = (ctrl & 0x01) != 0;
|
||||
|
||||
if (actualChannel != _adcState.channel || actualBusy != _adcState.busy || value != _adcState.lastValue) {
|
||||
// 仅比较 channel 和 busy 状态,不比较 lastValue(ADC 活跃时值持续变化会导致误报)
|
||||
// Only compare channel and busy status, not lastValue (active ADC causes false positives)
|
||||
if (actualChannel != _adcState.channel || actualBusy != _adcState.busy) {
|
||||
result.adc_mismatch = true;
|
||||
result.consistent = false;
|
||||
}
|
||||
|
||||
+24
@@ -1089,6 +1089,22 @@ public:
|
||||
return M5PM1_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
/**
|
||||
* @brief Initialize with M5Unified I2C_Class instance (ESP-IDF)
|
||||
* @note The I2C bus must already be initialized (i2c->begin() called) by the caller.
|
||||
* M5PM1 borrows the I2C_Class; caller retains ownership and lifecycle.
|
||||
* 不负责驱动安装或释放,I2C 由调用方全程管理。
|
||||
* @param i2c 已 begin() 的 m5::I2C_Class 指针
|
||||
* Pointer to an already begin()-ed m5::I2C_Class
|
||||
* @param addr I2C 地址 / I2C address (default 0x6E)
|
||||
* @param speed I2C 速率(Hz,100000 或 400000)/ I2C speed in Hz (100000 or 400000)
|
||||
* @return M5PM1_OK on success, error code otherwise
|
||||
*/
|
||||
m5pm1_err_t begin(m5::I2C_Class* i2c, uint8_t addr = M5PM1_DEFAULT_ADDR, uint32_t speed = M5PM1_I2C_FREQ_DEFAULT);
|
||||
#endif // M5PM1_HAS_M5UNIFIED_I2C
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -2909,6 +2925,14 @@ private:
|
||||
int _sda;
|
||||
int _scl;
|
||||
i2c_port_t _port;
|
||||
|
||||
// M5Unified I2C_Class 借用句柄及当前通信频率
|
||||
// Borrowed M5Unified I2C_Class handle and current communication frequency
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
m5::I2C_Class* _m5_i2c;
|
||||
uint32_t _commFreq; // M5UNIFIED 路径专用:init 时从 100K 起,完成后切换至 _requestedSpeed
|
||||
// M5UNIFIED path: starts at 100K during init, switches to _requestedSpeed after
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 内部辅助函数
|
||||
|
||||
+103
-3
@@ -177,10 +177,10 @@ static inline void M5PM1_I2C_ARDUINO_SEND_WAKE(TwoWire *wire, uint8_t addr)
|
||||
// IDF >= 5.3.0
|
||||
#if defined(CONFIG_I2C_BUS_BACKWARD_CONFIG)
|
||||
#define M5PM1_HAS_I2C_BUS 1 // BACKWARD_CONFIG:i2c_bus.h 使用 driver/i2c.h,无冲突 / no conflict
|
||||
#elif defined(_DRIVER_I2C_H_)
|
||||
#elif defined(_DRIVER_I2C_H_) || (defined(__cplusplus) && __has_include(<utility/I2C_Class.hpp>))
|
||||
#define M5PM1_HAS_I2C_BUS \
|
||||
0 // driver/i2c.h 已提前包含 + 无 BACKWARD_CONFIG → 冲突风险,禁用
|
||||
// driver/i2c.h already included + no BACKWARD_CONFIG → conflict risk, disabled
|
||||
0 // driver/i2c.h 已包含或 M5Unified 可用(将包含 driver/i2c.h)→ i2c_config_t 冲突风险,禁用
|
||||
// driver/i2c.h already included or M5Unified available (will include driver/i2c.h) → conflict risk, disabled
|
||||
#else
|
||||
#define M5PM1_HAS_I2C_BUS 1 // driver/i2c.h 尚未包含,无冲突风险 / driver/i2c.h not yet included, no conflict
|
||||
#endif
|
||||
@@ -211,6 +211,10 @@ static inline void M5PM1_I2C_ARDUINO_SEND_WAKE(TwoWire *wire, uint8_t addr)
|
||||
#define M5PM1_HAS_I2C_MASTER 0
|
||||
#endif
|
||||
|
||||
// ============================
|
||||
// M5Unified I2C_Class 检测
|
||||
// M5Unified I2C_Class Detection
|
||||
// ============================
|
||||
#if M5PM1_HAS_I2C_BUS
|
||||
#include <i2c_bus.h>
|
||||
#else
|
||||
@@ -220,6 +224,20 @@ typedef void *i2c_bus_handle_t;
|
||||
typedef void *i2c_bus_device_handle_t;
|
||||
#endif
|
||||
|
||||
//
|
||||
// 仅 C++ 环境下检测 M5Unified 的 I2C_Class 是否可用。
|
||||
// Detects whether M5Unified's I2C_Class is available (C++ only).
|
||||
// 启用条件:__cplusplus 已定义(即编译单元为 C++)且 utility/I2C_Class.hpp 可被 include。
|
||||
// Enabled when: __cplusplus is defined (i.e., C++ TU) AND utility/I2C_Class.hpp is reachable.
|
||||
// 注意:i2c_bus.h 必须先于 I2C_Class.hpp 包含,避免 i2c_config_t typedef 冲突。
|
||||
// Note: i2c_bus.h must be included before I2C_Class.hpp to avoid i2c_config_t typedef conflict.
|
||||
#if defined(__cplusplus) && __has_include(<utility/I2C_Class.hpp>)
|
||||
#define M5PM1_HAS_M5UNIFIED_I2C 1
|
||||
#include <utility/I2C_Class.hpp>
|
||||
#else
|
||||
#define M5PM1_HAS_M5UNIFIED_I2C 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -241,6 +259,10 @@ typedef enum {
|
||||
M5PM1_I2C_DRIVER_LEGACY, // 传统 driver/i2c.h API(IDF < 5.3.0 且无 i2c_bus)
|
||||
// Legacy driver/i2c.h API (IDF < 5.3.0 without i2c_bus)
|
||||
#endif
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
M5PM1_I2C_DRIVER_M5UNIFIED, // 借用 M5Unified I2C_Class 通信(不负责驱动安装/释放)
|
||||
// Borrow M5Unified I2C_Class for communication (no driver lifecycle)
|
||||
#endif
|
||||
} m5pm1_i2c_driver_t;
|
||||
|
||||
// ============================
|
||||
@@ -504,6 +526,84 @@ static inline esp_err_t M5PM1_I2C_MASTER_SEND_WAKE(i2c_master_bus_handle_t bus,
|
||||
}
|
||||
#endif
|
||||
|
||||
// ============================
|
||||
// M5Unified I2C_Class 通信封装
|
||||
// M5Unified I2C_Class Communication Wrappers
|
||||
// (C++ only — m5::I2C_Class is a C++ class)
|
||||
// ============================
|
||||
#if M5PM1_HAS_M5UNIFIED_I2C
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifndef M5PM1_M5UNIFIED_READ_BYTE
|
||||
static inline bool M5PM1_M5UNIFIED_READ_BYTE(m5::I2C_Class *i2c, uint8_t addr, uint8_t reg, uint8_t *data,
|
||||
uint32_t freq)
|
||||
{
|
||||
return i2c->readRegister(addr, reg, data, 1, freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_M5UNIFIED_READ_BYTES
|
||||
static inline bool M5PM1_M5UNIFIED_READ_BYTES(m5::I2C_Class *i2c, uint8_t addr, uint8_t reg, size_t len, uint8_t *data,
|
||||
uint32_t freq)
|
||||
{
|
||||
return i2c->readRegister(addr, reg, data, len, freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_M5UNIFIED_READ_REG16
|
||||
static inline bool M5PM1_M5UNIFIED_READ_REG16(m5::I2C_Class *i2c, uint8_t addr, uint8_t reg, uint16_t *data,
|
||||
uint32_t freq)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
if (!i2c->readRegister(addr, reg, buf, 2, freq)) return false;
|
||||
// 小端模式:低字节在前 / Little-endian: low byte first
|
||||
*data = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_M5UNIFIED_WRITE_BYTE
|
||||
static inline bool M5PM1_M5UNIFIED_WRITE_BYTE(m5::I2C_Class *i2c, uint8_t addr, uint8_t reg, uint8_t data,
|
||||
uint32_t freq)
|
||||
{
|
||||
return i2c->writeRegister8(addr, reg, data, freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_M5UNIFIED_WRITE_BYTES
|
||||
static inline bool M5PM1_M5UNIFIED_WRITE_BYTES(m5::I2C_Class *i2c, uint8_t addr, uint8_t reg, size_t len,
|
||||
const uint8_t *data, uint32_t freq)
|
||||
{
|
||||
return i2c->writeRegister(addr, reg, data, len, freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_M5UNIFIED_WRITE_REG16
|
||||
static inline bool M5PM1_M5UNIFIED_WRITE_REG16(m5::I2C_Class *i2c, uint8_t addr, uint8_t reg, uint16_t data,
|
||||
uint32_t freq)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
// 小端模式:低字节在前 / Little-endian: low byte first
|
||||
buf[0] = (uint8_t)(data & 0xFF);
|
||||
buf[1] = (uint8_t)((data >> 8) & 0xFF);
|
||||
return i2c->writeRegister(addr, reg, buf, 2, freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_M5UNIFIED_SEND_WAKE
|
||||
// 产生 I2C START 信号以唤醒处于睡眠的 PM1
|
||||
// Generate I2C START signal to wake PM1 from sleep
|
||||
static inline bool M5PM1_M5UNIFIED_SEND_WAKE(m5::I2C_Class *i2c, uint8_t addr, uint32_t freq)
|
||||
{
|
||||
i2c->start(addr, false, freq);
|
||||
i2c->stop();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // M5PM1_HAS_M5UNIFIED_I2C
|
||||
|
||||
#endif // ARDUINO
|
||||
|
||||
#endif // __M5PM1_I2C_COMPAT_H__
|
||||
|
||||
Reference in New Issue
Block a user