Signed-off-by: kevin <kevin@lmve.net>
This commit is contained in:
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 2,
|
|
||||||
"sessions": {
|
|
||||||
"17e27f37a08d4079971bed834cd7a702": [
|
|
||||||
{
|
|
||||||
"expertId": "EmbeddedFirmwareEngineer",
|
|
||||||
"name": "固件通",
|
|
||||||
"profession": "嵌入式固件工程师",
|
|
||||||
"avatarUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/avatars/02-Engineering/EmbeddedFirmwareEngineer/EmbeddedFirmwareEngineer.png",
|
|
||||||
"promptUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/experts/02-Engineering/EmbeddedFirmwareEngineer/EmbeddedFirmwareEngineer_zh.md",
|
|
||||||
"usedAt": 1776444279306,
|
|
||||||
"industryId": "all"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"lastUpdated": 1776444603959
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-04-26 工作日志
|
||||||
|
|
||||||
|
## 固件工程架构梳理
|
||||||
|
- 工程路径:`code/firmware-2.7.15.567b8ea`
|
||||||
|
- 版本:Meshtastic v2.7.15,基于 PlatformIO 构建
|
||||||
|
- 支持平台:ESP32 / nRF52 / RP2040 / RP2350 / Linux (Portduino)
|
||||||
|
- 路由层级:ReliableRouter → NextHopRouter → FloodingRouter → Router
|
||||||
|
- 定制点:TCA9535 I²C IO 扩展器用于代理 LoRa RST(P1.4)、GPS EN(P1.7)和 POWER_EN 引脚控制
|
||||||
|
- 自定义文件:`src/input/TCA9535ButtonThread.cpp/.h`(I²C 按键驱动,约16KB+12KB)
|
||||||
|
- main.cpp 中有 TCA9535GpioHal 自定义 HAL 类,拦截虚拟引脚转发到 I²C
|
||||||
|
|
||||||
|
## P1.6 振子震动功能实现
|
||||||
|
- 变体:`variants/esp32c3/diy/esp32c3_moonshine_travelers_3`
|
||||||
|
- P1.6 原为 GPS RST,改为振子(VIBRATOR),高电平震动,低电平停止
|
||||||
|
- 改动文件:
|
||||||
|
- `src/input/TCA9535ButtonThread.h`:`tca9535GpsReset()` → `tca9535Vibrate()`,添加 `_vibrateOn`/`_vibrateStartMs` 成员
|
||||||
|
- `src/input/TCA9535ButtonThread.cpp`:init() 开机后触发 300ms 震动;runOnce() 关机时触发 300ms 震动;振子超时自动停止逻辑在 runOnce() 开头
|
||||||
|
- `variants/.../variant.h`:注释更新
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# MEMORY.md - 项目长期记忆
|
||||||
|
|
||||||
|
## 当前固件工程
|
||||||
|
|
||||||
|
- **路径**:`code/firmware-2.7.15.567b8ea`
|
||||||
|
- **版本**:Meshtastic v2.7.15(PlatformIO 工程)
|
||||||
|
- **支持平台**:ESP32 / nRF52 / RP2040 / RP2350 / Linux(Portduino)
|
||||||
|
- **构建系统**:PlatformIO,默认目标 `tbeam`,variants/ 目录存放各板型配置
|
||||||
|
|
||||||
|
## 自定义硬件扩展(重要!)
|
||||||
|
|
||||||
|
### TCA9535 I²C IO 扩展器
|
||||||
|
用于代理几个不能直连 MCU GPIO 的关键引脚:
|
||||||
|
- **P1.4** → LoRa 模块 RST(通过 `TCA9535GpioHal` 自定义 HAL 拦截 RadioLib 调用)
|
||||||
|
- **P1.6** → 振子 VIBRATOR(高电平震动):开机/关机各震动 300ms(变体 esp32c3_moonshine_travelers_3)
|
||||||
|
- **P1.7** → GPS 使能引脚(`GpioTca9535GpsEnPin` 包装)
|
||||||
|
- **POWER_EN** → 上电保持(早期 boot 时即拉高,防止松开按键后 MOS 断电)
|
||||||
|
|
||||||
|
### 自定义文件
|
||||||
|
- `src/input/TCA9535ButtonThread.cpp` / `.h`:I²C 按键驱动(~16KB + ~12KB)
|
||||||
|
- `src/main.cpp`:含 TCA9535GpioHal 类定义、GPS EN 替换逻辑、TCA9535 按键线程初始化
|
||||||
|
|
||||||
|
## 工程架构要点
|
||||||
|
|
||||||
|
- **路由层级**:ReliableRouter → NextHopRouter → FloodingRouter → Router
|
||||||
|
- **Mesh 服务**:MeshService 连接射频收发、手机 API、GPS、模块系统
|
||||||
|
- **模块系统**:setupModules() 统一初始化,各模块通过 MeshModule 订阅数据包端口
|
||||||
|
- **线程调度**:基于 concurrency::OSThread + Periodic,loop() 中 mainController.runOrDelay()
|
||||||
|
- **消息协议**:Protobuf(protobufs/ 目录),生成代码在 src/mesh/generated/
|
||||||
|
|||||||
Binary file not shown.
@@ -85,15 +85,13 @@ TCA9535ButtonThread::TCA9535ButtonThread(const char *name, TwoWire *wire)
|
|||||||
|
|
||||||
bool TCA9535ButtonThread::init()
|
bool TCA9535ButtonThread::init()
|
||||||
{
|
{
|
||||||
// ===================================================================
|
// P1 口方向注释:
|
||||||
// 第一步:配置 P1 口方向
|
// P1.0=输出(键盘背光), P1.1=输入(CHARGE_DET), P1.2=输出(POWER_EN),
|
||||||
// P1.0=输出(未用), P1.1=输入(CHARGE_DET), P1.2=输出(POWER_EN),
|
|
||||||
// P1.3=输入(POWER_BOOT), P1.4=输出(LoRa RST), P1.5=输出(状态灯),
|
// P1.3=输入(POWER_BOOT), P1.4=输出(LoRa RST), P1.5=输出(状态灯),
|
||||||
// P1.6=输出(GPS RST), P1.7=输出(GPS EN)
|
// P1.6=输出(振子 VIBRATOR), P1.7=输出(GPS EN)
|
||||||
// Configuration 寄存器:1=input, 0=output
|
// P1 口配置寄存器:1=input, 0=output
|
||||||
// bit: P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
|
// bit: P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
|
||||||
// 0 0 0 0 1 0 1 0 = 0x0A
|
// 0 0 0 0 1 0 1 0 = 0x0A
|
||||||
// ===================================================================
|
|
||||||
if (!writeReg(TCA9535_REG_CONFIG_P1, 0x0A)) {
|
if (!writeReg(TCA9535_REG_CONFIG_P1, 0x0A)) {
|
||||||
LOG_WARN("TCA9535: P1 config write failed");
|
LOG_WARN("TCA9535: P1 config write failed");
|
||||||
return false;
|
return false;
|
||||||
@@ -109,8 +107,8 @@ bool TCA9535ButtonThread::init()
|
|||||||
// P1.5 状态灯默认熄灭(高电平)
|
// P1.5 状态灯默认熄灭(高电平)
|
||||||
tca9535StatusLed(false);
|
tca9535StatusLed(false);
|
||||||
|
|
||||||
// P1.6 GPS RST 默认释放(高电平 = 正常工作)
|
// P1.6 振子默认关闭(低电平)
|
||||||
tca9535GpsReset(true);
|
tca9535Vibrate(false);
|
||||||
|
|
||||||
// P1.7 GPS EN 默认打开(高电平 = GPS 上电)
|
// P1.7 GPS EN 默认打开(高电平 = GPS 上电)
|
||||||
tca9535GpsEn(true);
|
tca9535GpsEn(true);
|
||||||
@@ -118,11 +116,17 @@ bool TCA9535ButtonThread::init()
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
// 第三步:POWER_EN 已由 main.cpp 在 Wire.begin() 后立即拉高,
|
// 第三步:POWER_EN 已由 main.cpp 在 Wire.begin() 后立即拉高,
|
||||||
// 并等待 P1.3 持续按住 2 秒确认开机(超时 3 秒则断电关机)。
|
// 并等待 P1.3 持续按住 2 秒确认开机(超时 3 秒则断电关机)。
|
||||||
// 此处只需确认状态机进入 RUNNING。
|
// 此处只需确认状态机进入 RUNNING,并触发开机震动 300ms。
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
LOG_INFO("TCA9535: Boot already confirmed in early boot, state=RUNNING");
|
LOG_INFO("TCA9535: Boot already confirmed in early boot, state=RUNNING");
|
||||||
_powerState = TCA9535PowerState::RUNNING;
|
_powerState = TCA9535PowerState::RUNNING;
|
||||||
|
|
||||||
|
// 开机震动 300ms
|
||||||
|
tca9535Vibrate(true);
|
||||||
|
_vibrateOn = true;
|
||||||
|
_vibrateStartMs = millis();
|
||||||
|
LOG_DEBUG("TCA9535: Boot vibration started (300ms)");
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
// 第四步:配置 P0 口方向(矩阵键盘)
|
// 第四步:配置 P0 口方向(矩阵键盘)
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@@ -177,6 +181,13 @@ int32_t TCA9535ButtonThread::runOnce()
|
|||||||
if (held >= TCA9535_POWER_BOOT_HOLD_MS) {
|
if (held >= TCA9535_POWER_BOOT_HOLD_MS) {
|
||||||
LOG_WARN("TCA9535: Power button held %lu ms -> SHUTDOWN", held);
|
LOG_WARN("TCA9535: Power button held %lu ms -> SHUTDOWN", held);
|
||||||
_powerBtnPressStart = 0;
|
_powerBtnPressStart = 0;
|
||||||
|
// 关机震动 300ms,震动结束后由振子超时逻辑触发 SHUTDOWN 事件
|
||||||
|
if (!_vibrateOn) {
|
||||||
|
tca9535Vibrate(true);
|
||||||
|
_vibrateOn = true;
|
||||||
|
_vibrateStartMs = millis();
|
||||||
|
LOG_DEBUG("TCA9535: Shutdown vibration started (300ms)");
|
||||||
|
}
|
||||||
dispatchEvent(INPUT_BROKER_SHUTDOWN);
|
dispatchEvent(INPUT_BROKER_SHUTDOWN);
|
||||||
}
|
}
|
||||||
} else if (!pressed && _powerBtnPressStart != 0) {
|
} else if (!pressed && _powerBtnPressStart != 0) {
|
||||||
@@ -188,6 +199,15 @@ int32_t TCA9535ButtonThread::runOnce()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// P1.6 振子超时停止:震动 300ms 后自动关闭
|
||||||
|
// ===================================================================
|
||||||
|
if (_vibrateOn && millis() - _vibrateStartMs >= 300) {
|
||||||
|
_vibrateOn = false;
|
||||||
|
tca9535Vibrate(false);
|
||||||
|
LOG_DEBUG("TCA9535: Vibration stopped");
|
||||||
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
// P1.5 状态灯闪烁:500ms 亮 + 500ms 灭 = 1 秒周期
|
// P1.5 状态灯闪烁:500ms 亮 + 500ms 灭 = 1 秒周期
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
* - P1.3:电源开机按钮(POWER_BOOT),输入,低电平有效(按键按下接地)
|
* - P1.3:电源开机按钮(POWER_BOOT),输入,低电平有效(按键按下接地)
|
||||||
* - P1.4:LoRa RST 输出(通过 I²C 控制 RadioLib 复位序列)
|
* - P1.4:LoRa RST 输出(通过 I²C 控制 RadioLib 复位序列)
|
||||||
* - P1.5:状态指示灯,低电平点亮
|
* - P1.5:状态指示灯,低电平点亮
|
||||||
|
* - P1.6:振子(VIBRATOR),高电平震动,低电平停止
|
||||||
* P1 Config 寄存器 = 0x0A(P1.1、P1.3 为输入,其余为输出)
|
* P1 Config 寄存器 = 0x0A(P1.1、P1.3 为输入,其余为输出)
|
||||||
*
|
*
|
||||||
* 电源管理逻辑:
|
* 电源管理逻辑:
|
||||||
@@ -88,7 +89,7 @@
|
|||||||
#define TCA9535_BIT_P13 (1u << 3) // POWER_BOOT 输入
|
#define TCA9535_BIT_P13 (1u << 3) // POWER_BOOT 输入
|
||||||
#define TCA9535_BIT_P14 (1u << 4) // LoRa RST 输出
|
#define TCA9535_BIT_P14 (1u << 4) // LoRa RST 输出
|
||||||
#define TCA9535_BIT_P15 (1u << 5) // 状态指示灯输出(低电平点亮)
|
#define TCA9535_BIT_P15 (1u << 5) // 状态指示灯输出(低电平点亮)
|
||||||
#define TCA9535_BIT_P16 (1u << 6) // GPS RST 输出
|
#define TCA9535_BIT_P16 (1u << 6) // 振子输出(VIBRATOR,高电平震动)
|
||||||
#define TCA9535_BIT_P17 (1u << 7) // GPS EN 输出(高电平有效)
|
#define TCA9535_BIT_P17 (1u << 7) // GPS EN 输出(高电平有效)
|
||||||
|
|
||||||
#ifdef TCA9535_CHARGE_DET_PIN
|
#ifdef TCA9535_CHARGE_DET_PIN
|
||||||
@@ -240,10 +241,11 @@ static inline bool tca9535Backlight(bool on)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过 I²C 控制 TCA9535 P1.6 上的 GPS RST。
|
* 通过 I²C 控制 TCA9535 P1.6 上的振子(VIBRATOR)。
|
||||||
* @param high true=释放复位(高电平),false=触发复位(低电平)
|
* 高电平震动,低电平停止。
|
||||||
|
* @param on true=震动(高电平),false=停止(低电平)
|
||||||
*/
|
*/
|
||||||
static inline bool tca9535GpsReset(bool high)
|
static inline bool tca9535Vibrate(bool on)
|
||||||
{
|
{
|
||||||
Wire.beginTransmission(TCA9535_I2C_ADDR);
|
Wire.beginTransmission(TCA9535_I2C_ADDR);
|
||||||
Wire.write(TCA9535_REG_OUTPUT_P1);
|
Wire.write(TCA9535_REG_OUTPUT_P1);
|
||||||
@@ -253,10 +255,10 @@ static inline bool tca9535GpsReset(bool high)
|
|||||||
return false;
|
return false;
|
||||||
uint8_t p1Out = Wire.read();
|
uint8_t p1Out = Wire.read();
|
||||||
|
|
||||||
if (high)
|
if (on)
|
||||||
p1Out |= TCA9535_BIT_P16; // 拉高 = 释放复位
|
p1Out |= TCA9535_BIT_P16; // 拉高 = 震动
|
||||||
else
|
else
|
||||||
p1Out &= ~TCA9535_BIT_P16; // 拉低 = 触发复位
|
p1Out &= ~TCA9535_BIT_P16; // 拉低 = 停止
|
||||||
|
|
||||||
Wire.beginTransmission(TCA9535_I2C_ADDR);
|
Wire.beginTransmission(TCA9535_I2C_ADDR);
|
||||||
Wire.write(TCA9535_REG_OUTPUT_P1);
|
Wire.write(TCA9535_REG_OUTPUT_P1);
|
||||||
@@ -343,6 +345,10 @@ class TCA9535ButtonThread : public Observable<const InputEvent *>, public concur
|
|||||||
bool _backlightOn = false;
|
bool _backlightOn = false;
|
||||||
uint32_t _backlightLastMs = 0;
|
uint32_t _backlightLastMs = 0;
|
||||||
|
|
||||||
|
// P1.6 振子控制(开机/关机震动 300ms)
|
||||||
|
bool _vibrateOn = false;
|
||||||
|
uint32_t _vibrateStartMs = 0; // 震动开始时刻,0 = 未在震动
|
||||||
|
|
||||||
// 写寄存器
|
// 写寄存器
|
||||||
bool writeReg(uint8_t reg, uint8_t val);
|
bool writeReg(uint8_t reg, uint8_t val);
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -42,7 +42,8 @@
|
|||||||
// 开机:持续按住 2 秒 → POWER_EN 拉高维持供电
|
// 开机:持续按住 2 秒 → POWER_EN 拉高维持供电
|
||||||
// 关机:运行中持续按住 2 秒 → POWER_EN 拉低断电
|
// 关机:运行中持续按住 2 秒 → POWER_EN 拉低断电
|
||||||
// - P1.4 LoRa RST 输出(通过 I²C 控制 RadioLib 复位序列)
|
// - P1.4 LoRa RST 输出(通过 I²C 控制 RadioLib 复位序列)
|
||||||
// - P1.6 GPS_RST 输出(通过 tca9535GpsReset() 控制,init 中释放)
|
// - P1.6 振子(VIBRATOR),高电平震动,低电平停止
|
||||||
|
// 开机确认后震动 300ms,关机时震动 300ms
|
||||||
// - P1.7 GPS_EN 输出(高电平有效,通过 enablePin 桥接到 TCA9535)
|
// - P1.7 GPS_EN 输出(高电平有效,通过 enablePin 桥接到 TCA9535)
|
||||||
// - P1.1 CHARGE_DET 输入(高电平=正在充电)
|
// - P1.1 CHARGE_DET 输入(高电平=正在充电)
|
||||||
// - 中断引脚 GPIO5,低电平有效,下降沿触发
|
// - 中断引脚 GPIO5,低电平有效,下降沿触发
|
||||||
|
|||||||
Reference in New Issue
Block a user