feat(platform): adapt GPIO configuration to new board

This commit is contained in:
chenjintao
2026-10-23 15:37:22 +08:00
parent 6d103938ab
commit aede687dc9
10 changed files with 801 additions and 421 deletions
@@ -147,7 +147,7 @@ esp_err_t platform_battery_init(void)
};
esp_err_t gpio_err = gpio_config(&charge_config);
if (gpio_err != ESP_OK) {
ESP_LOGE(TAG, "Configure TP4057 status GPIO failed: %s", esp_err_to_name(gpio_err));
ESP_LOGE(TAG, "Configure charger status GPIO failed: %s", esp_err_to_name(gpio_err));
unlock_adc();
return gpio_err;
}
@@ -158,13 +158,15 @@ esp_err_t platform_battery_init(void)
esp_err_t err = adc_oneshot_io_to_channel(CONFIG_TQ_BATTERY_ADC_GPIO,
&unit,
&channel);
if (err != ESP_OK || unit != ADC_UNIT_1) {
/* 新板 GPIO17 属于 ADC2;通道和校准均使用 IDF 返回的实际单元。
* ADC2 仲裁/读取失败继续向上传播,不能把失败样本当作低电量。 */
if (err != ESP_OK) {
ESP_LOGE(TAG,
"Battery ADC GPIO%d is not a supported ADC1 input: %s",
"Battery ADC GPIO%d is not a supported ADC input: %s",
CONFIG_TQ_BATTERY_ADC_GPIO,
esp_err_to_name(err));
unlock_adc();
return err != ESP_OK ? err : ESP_ERR_NOT_SUPPORTED;
return err;
}
adc_oneshot_unit_init_cfg_t unit_config = {
@@ -26,7 +26,8 @@
#define PLATFORM_IO_EFFECTS_TASK_CORE ((BaseType_t)CONFIG_TQ_LOCAL_TASK_CORE)
#endif
/* GPIO4、GPIO5和22颗灯珠来自当前 PCB 布线/灯带布局,换板时必须同步核对原理图。 */
/* 旧板外接 GPIO4/5 与22颗灯珠方案;新板已将这两脚分配给 LCD,
* 平台初始化不再调用本模块。保留实现供历史参考,不作为新板马达驱动。 */
#define PLATFORM_RMT_GPIO GPIO_NUM_4
#define PLATFORM_PULSE_GPIO GPIO_NUM_5
@@ -283,10 +283,8 @@ esp_err_t platform_init(void)
platform_power_hold_init();
esp_err_t io_effects_err = platform_io_effects_init();
if (io_effects_err != ESP_OK) {
ESP_LOGW(TAG, "IO effects init failed: %s", esp_err_to_name(io_effects_err));
}
/* 新板 GPIO4/5 分别为 LCD BLK/CS;不启动旧灯带和脉冲任务。
* GPIO10 摇臂驱动尚未接入,保持硬件下拉关断。 */
#if CONFIG_TQ_STEPPER_ENABLE
err = platform_stepper_driver_init();
@@ -42,6 +42,14 @@ esp_err_t err = domain_runtime_request_expression(&request);
## 三、关键文件与职责
现有 LCD GPIO 与背光有效极性集中在 `menuconfig` 的
`TQ Cat Configuration -> Board Hardware Configuration (GPIO)` 页面,
与音频、输入、电机和电源引脚分区展示。显示功能、颜色、亮度及 GFX/性能日志
仍在原显示菜单。2026-10-23 已同步新板 LCD 映射:BLK/CS/DC/RES/MOSI/CLK
为 GPIO4/5/6/7/15/16;旧 GPIO4 RMT、GPIO5 脉冲不再随平台初始化启动。
配置名和依赖保持不变;未新增 GPIO8 充满检测或 GPIO10 摇臂控制选项。
BLK 按新图作为使能使用,默认 100%;调光与显示/电机/音频并行仍需实机验收。
| 文件 | 职责 |
| --- | --- |
| `components/platform/src/lcd_direct.c` | 面板初始化、请求播放、GFX 图层、眼型生成和缓存、时间轴、状态栏、传输及性能日志 |
@@ -460,3 +468,12 @@ python3 tools/test_lcd_fortune_gfx.py
此前缓存/时序及中文指南提交为 `89e8e3a`、`c0770ac`;本次基线包含 listening
接入及补充文档。完整状态机、任意中文字体、其他表情批量迁移、
资源清理/热替换是后续方向,不标成已经实现,也不推断用户已要求立即实施。
### 2026-10-23 新板 GPIO 映射验证
已更新现有 LCD/音频/按键/步进/电池引脚默认值和本地有效配置,保持现有 GFX
机制与资产不变;旧 GPIO4/5 输出模块不再启动。电池驱动允许 GPIO17 对应的 ADC2,
未新增 GPIO8/10 配置。五个显示回归脚本(含其 profiling 开/关分支)、电池 ADC
初始化主机测试和 ESP-IDF 5.5.4 构建通过。未烧录;仍需实机核对背光使能、
画面切换/取消、跨分钟、充电/唤醒,以及电机/音频/网络并行,不能据此声称新板
实测 FPS、触摸电平或 ADC 精度已验收。
+76 -90
View File
@@ -1,115 +1,101 @@
# Firmware Pin Usage
This document summarizes the GPIOs used by the current firmware configuration.
The primary source of truth is `sdkconfig.defaults`. Signal direction is from
the ESP32-S3 MCU perspective.
The current profile targets the new board in `schematic/电机-马达方案.pdf`
(upper board 2026-10-19; lower board 2026-10-12). Defaults are declared in
`sdkconfig.defaults` and `main/Kconfig.projbuild`; saved local settings in
`sdkconfig` must match. Directions below are from the ESP32-S3 perspective.
Existing GPIOs, active levels, pull resistors, and backlight polarity are on one
`menuconfig` page: `TQ Cat Configuration -> Board Hardware Configuration (GPIO)`.
Feature switches and behavior parameters remain in their original menus.
No new GPIO option has been added for full-charge sensing or the rocker motor.
## Configured Firmware Pins
| GPIO | Signal / Config | Direction | Subsystem | Runtime use | Electrical / logic notes |
| ---: | --- | --- | --- | --- | --- |
| 1 | `CONFIG_MULTIMODAL_AUDIO_I2C_SDA_GPIO` | Bidirectional | Audio codec | ES8311 I2C SDA | I2C port 0, codec control bus |
| 2 | `CONFIG_MULTIMODAL_AUDIO_I2C_SCL_GPIO` | Output | Audio codec | ES8311 I2C SCL | I2C port 0, codec control bus |
| 4 | IO4 RMT control | Output | RMT control | RMT output control | Reuses unconnected `TP_INT` on the 8-wire LCD setup |
| 5 | IO5 PWM control | Output | PWM control | PWM output control | Reuses unconnected `TP_SDA` on the 8-wire LCD setup |
| 6 | `CONFIG_TQ_SLOT_SWITCH_GPIO` | Input | Slot / key input | Rocker microswitch / original SW2 function | Uses the unconnected `TP_SCL` contact; active-low with internal pull-up |
| 7 | `CONFIG_TQ_SCREEN_BACKLIGHT_GPIO` | Output | LCD | LCD adapter backlight control | Active-high by default |
| 8 | `CONFIG_TQ_SCREEN_SPI_CLK_GPIO` | Output | LCD | ST7789P3 SPI clock / SCK | SPI2 host, 20 MHz default |
| 9 | `CONFIG_TQ_BATTERY_ADC_GPIO` | Analog input | Battery | Battery voltage through 100 kOhm / 100 kOhm divider | ADC1 input; do not configure as a power-hold output |
| 10 | `CONFIG_TQ_BATTERY_CHARGE_GPIO` | Input | Battery charger | TP4057 charge status | Active-low, internal pull-up enabled |
| 11 | `CONFIG_MULTIMODAL_AUDIO_PA_GPIO` | Output | Audio amplifier | PA enable | Managed by codec GPIO interface |
| 12 | `CONFIG_TQ_CALIBRATION_SWITCH_GPIO` | Input | Turntable calibration | Button 1 / SW1 direction calibration | Active-low, external and internal pull-up |
| 13 | `CONFIG_MULTIMODAL_PTT_BUTTON_GPIO` | Input | Keys / multimodal | Button 2 / K2 push-to-talk | Active-low, external and internal pull-up |
| 14 | `CONFIG_TQ_RESET_BUTTON_GPIO` | Input when enabled | Optional reset key | Hold to clear saved Wi-Fi credentials and restart | Disabled by default; active-low with internal pull-up when enabled |
| 15 | `CONFIG_TQ_SCREEN_SPI_CS_GPIO` | Output | LCD | ST7789P3 SPI chip select | SPI2 host |
| 16 | `CONFIG_TQ_SCREEN_DC_GPIO` | Output | LCD | ST7789P3 data/command select | Initialized low |
| 17 | `CONFIG_TQ_SCREEN_RESET_PIN` | Output | LCD | ST7789P3 panel reset | Active-low reset; `-1` disables hardware reset |
| 18 | `CONFIG_TQ_SCREEN_SPI_MOSI_GPIO` | Output | LCD | ST7789P3 SPI MOSI / SDA | SPI2 host |
| 21 | `CONFIG_TQ_STEPPER_IN4_GPIO` | Output | Turntable | ULN2003 stepper IN4 | Batched GPIO phase updates |
| 38 | `CONFIG_MULTIMODAL_AUDIO_I2S_MCLK_GPIO` | Output | Audio codec | ES8311 I2S MCLK | Enabled by `CONFIG_MULTIMODAL_AUDIO_USE_MCLK=y` |
| 39 | `CONFIG_MULTIMODAL_AUDIO_I2S_BCLK_GPIO` | Output | Audio codec | ES8311 I2S BCLK / SCLK | I2S port 0 |
| 40 | `CONFIG_MULTIMODAL_AUDIO_I2S_DOUT_GPIO` | Output | Audio codec | MCU PCM output to ES8311 DSDIN | I2S port 0 |
| 41 | `CONFIG_MULTIMODAL_AUDIO_I2S_WS_GPIO` | Output | Audio codec | ES8311 I2S WS / LRCK | I2S port 0 |
| 42 | `CONFIG_MULTIMODAL_AUDIO_I2S_DIN_GPIO` | Input | Audio codec | MCU PCM input from ES8311 ASDOUT | I2S port 0 |
| 45 | `CONFIG_TQ_STEPPER_IN1_GPIO` | Output | Turntable | ULN2003 stepper IN1 | Batched GPIO phase updates |
| 47 | `CONFIG_TQ_STEPPER_IN3_GPIO` | Output | Turntable | ULN2003 stepper IN3 | Batched GPIO phase updates |
| 48 | `CONFIG_TQ_STEPPER_IN2_GPIO` | Output | Turntable | ULN2003 stepper IN2 | Batched GPIO phase updates |
| GPIO | Config | Direction | Function / Notes |
| ---: | --- | --- | --- |
| 1 | `CONFIG_MULTIMODAL_AUDIO_I2C_SDA_GPIO` | Bidirectional | ES8311 control SDA |
| 2 | `CONFIG_MULTIMODAL_AUDIO_I2C_SCL_GPIO` | Output | ES8311 control SCL |
| 4 | `CONFIG_TQ_SCREEN_BACKLIGHT_GPIO` | Output | LCD BLK, active high; initial brightness 100%, validate dimming separately |
| 5 | `CONFIG_TQ_SCREEN_SPI_CS_GPIO` | Output | LCD CS |
| 6 | `CONFIG_TQ_SCREEN_DC_GPIO` | Output | LCD data/command; no old switch flying wire |
| 7 | `CONFIG_TQ_SCREEN_RESET_PIN` | Output | LCD reset, active low |
| 9 | `CONFIG_MULTIMODAL_AUDIO_PA_GPIO` | Output | Audio amplifier enable |
| 11 | `CONFIG_TQ_CALIBRATION_SWITCH_GPIO` | Input | Switch 1 / calibration, active low with pull-up |
| 12 | `CONFIG_TQ_SLOT_SWITCH_GPIO` | Input | Switch 2 / slot trigger, active low with pull-up |
| 13 | `CONFIG_MULTIMODAL_PTT_BUTTON_GPIO` | Input | TTP223 touch output / PTT; previous active-low/pull-up settings retained pending measured polarity |
| 14 | `CONFIG_TQ_STEPPER_IN1_GPIO` | Output | ULN2003 IN1; must not also be configured as Wi-Fi reset |
| 15 | `CONFIG_TQ_SCREEN_SPI_MOSI_GPIO` | Output | LCD SDA is SPI MOSI, not I2C |
| 16 | `CONFIG_TQ_SCREEN_SPI_CLK_GPIO` | Output | LCD SCL is SPI SCK; saved defaults use 40 MHz, not a measured performance guarantee |
| 17 | `CONFIG_TQ_BATTERY_ADC_GPIO` | Analog input | ADC2 channel 6; divider via Q5/Q6; R6/R11=100 kOhm each |
| 18 | `CONFIG_TQ_BATTERY_CHARGE_GPIO` | Input | TP4056 CHRG# via Q7; retain active low, verify on hardware |
| 21 | `CONFIG_TQ_STEPPER_IN2_GPIO` | Output | ULN2003 IN2 |
| 38 | `CONFIG_MULTIMODAL_AUDIO_I2S_MCLK_GPIO` | Output | ES8311 MCLK |
| 39 | `CONFIG_MULTIMODAL_AUDIO_I2S_BCLK_GPIO` | Output | ES8311 SCLK |
| 40 | `CONFIG_MULTIMODAL_AUDIO_I2S_DOUT_GPIO` | Output | ES8311 DSDIN |
| 41 | `CONFIG_MULTIMODAL_AUDIO_I2S_WS_GPIO` | Output | ES8311 LRCK |
| 42 | `CONFIG_MULTIMODAL_AUDIO_I2S_DIN_GPIO` | Input | ES8311 ASDOUT |
| 47 | `CONFIG_TQ_STEPPER_IN3_GPIO` | Output | ULN2003 IN3 |
| 48 | `CONFIG_TQ_STEPPER_IN4_GPIO` | Output | ULN2003 IN4 |
The rocker microswitch wiring is `CN2 pin 3 (TP_SCL/GPIO6) -> normally-open
switch -> GND` (`CN2 pin 11` is a local ground option). The switch must not be
connected to 3.3 V. GPIO6 cannot be used as a touch I2C clock while this wiring
is installed.
The old `platform_io_effects_init()` startup call has been removed: its GPIO4
RMT and GPIO5 pulse workers conflict with new LCD BLK/CS. The old implementation
is retained as source, but no startup path calls it. GPIO10 motor control has
not been enabled as a replacement.
## Disabled Or Not Connected In Defaults
| Config | Value | Meaning |
| --- | ---: | --- |
| `CONFIG_TQ_SCREEN_SPI_MISO_GPIO` | `-1` | LCD MISO is not connected or not used. |
| `CONFIG_TQ_SLOT_SWITCH_PULLDOWN` | unset | SW2 uses pull-up only. |
| `CONFIG_TQ_CALIBRATION_SWITCH_PULLDOWN` | unset | Calibration switch uses pull-up only. |
| `CONFIG_MULTIMODAL_PTT_BUTTON_PULLDOWN` | unset | Button 2 uses pull-up only. |
| `CONFIG_TQ_POWER_HOLD_GPIO` | `-1` | Legacy board power-hold output is disabled because GPIO9 is the battery ADC input. |
## Boot Hardware Test Profile
The current board profile enables `CONFIG_TQ_BOOT_TURNTABLE_CALIBRATION_ENABLE`.
After platform initialization, the stepper performs a bounded search for the
active-low KEY1/SW1 input on GPIO12. Serial logs report the configured motor
pins, the initial KEY1/SW1 state, switch detection, and the bounded no-switch
result before Wi-Fi bootstrap continues. After boot, the managed key-input task
keeps monitoring SW1 and logs its pressed, released, short-press, long-press,
and double-click events.
## Console / Factory CLI
The factory CLI uses `UART_NUM_0` through the ESP-IDF UART driver without
project-specific GPIO remapping. The board reference map routes the debug UART
to the `RXD0` / `TXD0` nets on connector `J2`.
| Interface | Direction | Use |
| Config / Pin | Value / Status | Meaning |
| --- | --- | --- |
| UART0 RX | Input | Factory CLI input and serial monitor input |
| UART0 TX | Output | ESP log output, factory CLI replies, serial monitor output |
| `CONFIG_TQ_SCREEN_SPI_MISO_GPIO` | -1 | LCD readback is not connected |
| `CONFIG_TQ_POWER_HOLD_GPIO` | -1 | No MCU power-hold net on the new board |
| `CONFIG_TQ_RESET_BUTTON_ENABLE` | Disabled | The old optional reset default GPIO14 now belongs to stepper IN1; configure separate physical wiring before enabling |
| `CONFIG_TQ_BATTERY_SHUTDOWN_WAKE_BUTTON_GPIO` | -1 | No additional deep-sleep wake button |
| GPIO8 / 充满检测 | Not consumed | Full-charge input exists on hardware; no option/driver added |
| GPIO10 / 马达控制 | Not consumed | Rocker-motor gate held off by external R30 pull-down; no new option/driver added |
| GPIO3 / 35 / 36 / 37 / 45 / 46 | NC on schematic | Do not infer arbitrary availability from NC |
## External Memory Pins
Mechanical switches use pull-up only. PTT and charger active levels are retained
from the previous configuration and require actual idle/active measurements.
Battery full-charge prompts still use voltage/percentage/time inference rather
than GPIO8. ADC divider gain/offset remain unchanged pending VBAT measurements.
The project enables external PSRAM in octal mode. These are generated ESP-IDF
memory-interface settings in `sdkconfig`, not normal application GPIOs.
## Boot Calibration And Sleep
| GPIO | Config | Direction | Use | Notes |
| ---: | --- | --- | --- | --- |
| 26 | `CONFIG_SPIRAM_CS_IO` / `CONFIG_DEFAULT_PSRAM_CS_IO` | Memory bus | PSRAM CS | Reserved by ESP32-S3 memory interface |
| 30 | `CONFIG_SPIRAM_CLK_IO` / `CONFIG_DEFAULT_PSRAM_CLK_IO` | Memory bus | PSRAM clock | Reserved by ESP32-S3 memory interface |
`CONFIG_TQ_BOOT_TURNTABLE_CALIBRATION_ENABLE` remains enabled. Boot searches for
switch 1 on GPIO11 with IN1/IN2/IN3/IN4 = 14/21/47/48. Verify motor direction,
mechanical limits and bounded stop on hardware.
Flash pins are controlled by the ESP32-S3 flash interface and are not assigned
by project GPIO configuration.
Charge-state edge interrupts and low-active deep-sleep wake both follow
`CONFIG_TQ_BATTERY_CHARGE_GPIO=18`. Verify charger insertion/removal and wake
behavior after changing the board.
## Board Nets Present But Not Used By Current Firmware
## System Interfaces
These nets exist in `docs/gpio-map.md`, but the current firmware does not assign
them to an active project feature.
USB D-/D+ remain GPIO19/20. UART0 uses default RXD0/TXD0 without application
remapping; connector CN5 labels are TX/RX from the opposite endpoint's
perspective. BOOT remains GPIO0 and is not an application input.
| GPIO / Net | Board function | Firmware status |
| --- | --- | --- |
| GPIO0 / K1 | Switch to GND, commonly boot/download related | Not consumed by application code |
| GPIO3 / `touch` | TTP223 touch output | Present on the board but not consumed by the current input policy |
| GPIO14 | Unassigned | Not used |
| GPIO35 | Unassigned | Not used |
| GPIO36 | Unassigned | Not used |
| GPIO37 | Unassigned | Not used |
| GPIO46 | Unassigned | Not used |
| GPIO19 / USB D- | USB | Board/system function; not configured by application code |
| GPIO20 / USB D+ | USB | Board/system function; not configured by application code |
The octal PSRAM/Flash interfaces remain owned by ESP-IDF and the module.
Generated memory settings such as PSRAM CS=26 and CLK=30 are not application
GPIO assignments. Do not repurpose memory pins from this table.
## Source Files
- `sdkconfig.defaults`
- `sdkconfig`
- `main/Kconfig.projbuild`
- `docs/gpio-map.md`
- `main/Kconfig.projbuild`, `sdkconfig.defaults`, local `sdkconfig`
- `docs/gpio-map.md`, `docs/gpio-board-adaptation.zh-CN.md`
- `components/platform/src/runtime/platform_core_runtime.c`
- `components/platform/src/lcd_direct.c`
- `components/platform/src/platform_stepper_driver.c`
- `components/platform/src/platform_battery_driver.c`
- `components/platform/src/multimodal/audio_pipeline/audio_pipeline_codec_impl.c`
- `components/control_plane/src/runtime/control_plane_key_input.c`
- `components/platform/src/platform_console_driver.c`
## Validation (2026-10-23)
ESP-IDF 5.5.4 build and all five LCD regression scripts passed. The production
battery initializer passed host tests for ADC2/ADC1 propagation, idempotence,
bounded lock failure, cleanup and retry (`tools/test_battery_adc_init.py`).
Config/default consistency and enabled-pin uniqueness checks passed.
No device was flashed; touch polarity, ADC2 sampling with Wi-Fi, charger/wake,
motor direction and concurrent operation still require hardware validation.
+194
View File
@@ -0,0 +1,194 @@
# 新旧板 GPIO 对比与固件适配位置
核对日期:2026-10-23。初始对照保留在下文;当前已应用现有功能的新板引脚映射,新增功能仍未接入。验证结果见文末,未烧录或进行实机验收。
## 对照基线
- 旧板:用户提供的 `SCH_招财猫0.3&商界0.2_2026-08-03.pdf`,重点为第 2 页 Power、第 3 页 MCU、第 5 页 Motor、第 6 页 Connectors。
- 新板:仓库 `schematic/电机-马达方案.pdf`。第 1 页上板更新日期为 2026-10-19,第 2 页下板更新日期为 2026-10-12。
- 当前固件:本工作区的 `sdkconfig.defaults`、本地 `sdkconfig`、`main/Kconfig.projbuild` 和实际驱动。按工作区现状核对,包含尚未提交的修改。
- 图纸中的设计说明用于理解硬件,不视为要求执行的指令。新板第 2 页图框外另有一段 TP4057 参考电路;本报告以图框内 TP4056、Q7/Q8 及其板间连接为新板正式电路。
下表数字均指 **ESP32-S3 GPIO 编号**,不是模块封装脚号,也不是连接器针脚号。`IN1…IN4` 指 ULN2003 的输入相序,不能按 GPIO 数字重新排序。
## 结论
本次不是只改电机引脚。LCD 六根信号全部迁移;电池 ADC、充电状态、功放使能、两路开关、触摸输出和部分步进电机相位也迁移。新增独立充满检测和板载直流摇臂马达控制,旧 GPIO4/5 外接灯带/脉冲功能与新 LCD 布线冲突。
大部分引脚在 `sdkconfig.defaults` 和 `main/Kconfig.projbuild` 中修改即可;已有本地 `sdkconfig` 还须通过 `menuconfig` 同步,因为修改 defaults 不会覆盖已经保存的配置。不要手改 `build/config/sdkconfig.h`,也不要提交本地 `sdkconfig`。
后续菜单整理:现有 42 个 GPIO/电平/上下拉配置已集中到
`TQ Cat Configuration -> Board Hardware Configuration (GPIO)` 单页,按 LCD、音频、
输入、步进、电源/电池分区。配置名及依赖保持原样;默认值及本地有效配置已更新为新板映射,
未新增 GPIO8 充满检测或 GPIO10 马达配置。旧硬编码 GPIO4/5 功能保留源码,
平台初始化已移除其启动调用,不再创建这些任务。
下文 Kconfig 旧行号属于对照时快照,搬迁后应按配置名定位。
## 逐信号对照及修改入口
表中的配置名省略 `CONFIG_` 前缀;“适配前值”记录修改前本地 `sdkconfig` 和 defaults 的共同值。
| 信号/功能 | 旧板 GPIO | 适配前固件值 | 新板 GPIO | 要修改的配置或源码 |
| --- | ---: | ---: | ---: | --- |
| LCD 背光 BLK | 7 | 7 | **4** | `TQ_SCREEN_BACKLIGHT_GPIO`;`lcd_direct.c` 背光初始化 |
| LCD CS | 15 | 15 | **5** | `TQ_SCREEN_SPI_CS_GPIO`;`lcd_direct.c` SPI panel IO |
| LCD DC | 16 | 16 | **6** | `TQ_SCREEN_DC_GPIO`;`lcd_direct.c` GPIO/panel IO |
| LCD RES | 17 | 17 | **7** | `TQ_SCREEN_RESET_PIN`;`lcd_direct.c` 面板复位 |
| LCD 数据 MOSI / 新板 SDA | 18 | 18 | **15** | `TQ_SCREEN_SPI_MOSI_GPIO`;`lcd_direct.c` SPI bus |
| LCD 时钟 CLK / 新板 SCL | 8 | 8 | **16** | `TQ_SCREEN_SPI_CLK_GPIO`;`lcd_direct.c` SPI bus |
| LCD MISO | 未接 | -1 | 未接 | `TQ_SCREEN_SPI_MISO_GPIO=-1` 保持 |
| 电池电压检测 Power_t / 电量检测 | 9 | 9 | **17** | `TQ_BATTERY_ADC_GPIO`;`platform_battery_driver.c` |
| 充电状态 Charge / 充电检测 | 10 | 10 | **18** | `TQ_BATTERY_CHARGE_GPIO`;电池驱动、充电边沿中断及深睡唤醒链路 |
| 独立充满检测 | 未接入 MCU | 无 | **8** | 当前无配置项;需新增采样配置和状态映射,见后文 |
| 功放 PA_CTRL | 11 | 11 | **9** | `MULTIMODAL_AUDIO_PA_GPIO`;音频 codec 初始化及运行时使能 |
| 开关1 / 原 SW1 | 12 | 校准输入 12 | **11** | 若保持开关1作校准:`TQ_CALIBRATION_SWITCH_GPIO` |
| 开关2 / 原 SW2 | 13 | 抽签输入 13 | **12** | 若保持开关2作抽签:`TQ_SLOT_SWITCH_GPIO` |
| TTP223 触摸输出 | 3 | PTT 输入 3 | **13** | 若保持触摸作 PTT:`MULTIMODAL_PTT_BUTTON_GPIO`;有效电平另核对 |
| ULN2003 IN1 | 45 | 45 | **14** | `TQ_STEPPER_IN1_GPIO`;`platform_stepper_driver.c` |
| ULN2003 IN2 | 48 | 48 | **21** | `TQ_STEPPER_IN2_GPIO`;同上 |
| ULN2003 IN3 | 47 | 47 | **47** | `TQ_STEPPER_IN3_GPIO`;保持 |
| ULN2003 IN4 | 21 | 21 | **48** | `TQ_STEPPER_IN4_GPIO`;不能与 IN2 互换 |
| 直流摇臂马达控制 | 旧图 Swing 与 LCD CLK 共 GPIO8 | 外接脉冲输出 GPIO5 | **10** | 当前无独立 Kconfig;改造 `platform_io_effects.c` 脉冲输出及初始化策略 |
| 外接 WS2812 灯带 | 旧 TP_INT/GPIO4 被固件复用 | 硬编码 4 | 新图无专用接口 | 必须禁用或另行确认外接布线,不能继续占用 GPIO4 |
| 旧外接脉冲输出 | 旧 TP_SDA/GPIO5 被固件复用 | 硬编码 5 | GPIO5 已作 LCD CS | 必须迁移/禁用;是否由新 GPIO10 马达替代,由实际机械用途确认 |
按键语义不是原理图决定的:图纸只定义开关1、开关2和触摸输出;上表延续当前固件“校准 / 抽签 / PTT”分工。如果产品要调整按键用途,应另改控制层事件策略。
## 按 GPIO 看新板占用
| GPIO | 新板功能 | 适配动作 |
| --- | --- | --- |
| 0 | BOOT | 保持系统下载用途,不分配业务功能 |
| 1 / 2 | ES8311 I2C SDA / SCL | 保持音频 I2C 配置 |
| 3 | MCU 标 NC | 迁走当前 PTT;不再等候 GPIO3 触摸事件 |
| 4 / 5 / 6 / 7 | LCD BLK / CS / DC / RES | 修改显示配置;释放旧 GPIO4/5 输出;不要恢复旧 GPIO6 开关飞线配置 |
| 8 | 充满检测 | 输入;不得再输出 LCD 时钟 |
| 9 | PA_CTRL | 输出;不得再按电池 ADC 初始化 |
| 10 | 摇臂马达 MOS 控制 | 输出;不得再按充电输入初始化 |
| 11 / 12 | 开关1 / 开关2 | 输入;不得把 GPIO11 继续交给功放 |
| 13 | TTP223 触摸输出 | 输入;迁移 PTT 后释放原抽签占用 |
| 14 | 步进 IN1 | 输出;不得启用旧默认 GPIO14 Wi-Fi 重置键 |
| 15 / 16 | LCD SDA(MOSI) / SCL(SCK) | 保持 SPI 协议,SDA/SCL 命名不表示改成 I2C |
| 17 | 电池 ADC | 模拟输入;不得再作为 LCD RESET 输出 |
| 18 | 充电检测 | 输入;不得再输出 LCD MOSI |
| 19 / 20 | USB D- / D+ | GPIO 不变;新板经 33Ω 电阻到板间 USB 网络 |
| 21 / 47 / 48 | 步进 IN2 / IN3 / IN4 | 按相位名称配置 |
| 35 / 36 / 37 / 45 / 46 | MCU 标 NC | GPIO45 已不再连接步进 IN1;其余不新增业务配置 |
| 38 / 39 / 40 / 41 / 42 | I2S MCLK / BCLK / DOUT / WS / DIN | 保持原配置 |
| TXD0 / RXD0 | UART0 | 管脚不变;CN5 的 TX/RX 网络名与 MCU 收发方向交叉,不按网络名盲目交换固件方向 |
以上只描述图纸连接;NC 不等于已经确认可自由使用,仍须核对模块与 PCB。
## 修改文件导航
| 文件 | 具体位置/职责 | 本次适配建议 |
| --- | --- | --- |
| [sdkconfig.defaults](../sdkconfig.defaults) | PTT 约 195 行;音频约 211 行;LCD/电机/电池约 298–346 行 | 保存新板默认引脚;保持其他未提交配置 |
| [main/Kconfig.projbuild](../main/Kconfig.projbuild) | 文件顶部 `Board Hardware Configuration (GPIO)` 菜单 | 已同步现有项新板默认值及帮助文案;新功能未加选项 |
| [lcd_direct.c](../components/platform/src/lcd_direct.c) | 约 1634 行背光、1660 行 GPIO、1680 行后 SPI/panel 初始化 | 引脚已有配置化,通常不改驱动;新图注明 BLK 仅作使能,先用 0/100% 验证,不能直接认定支持调光 |
| [platform_io_effects.c](../components/platform/src/platform_io_effects.c) | 30/31 行 GPIO4/5 硬编码;186 行脉冲任务;277 行初始化 | 这是必须处理的代码冲突。先禁用旧 RMT/脉冲启动,再决定马达 GPIO10 的受控实现 |
| [platform_core_runtime.c](../components/platform/src/runtime/platform_core_runtime.c) | `platform_init()` 电源保持初始化之后 | 已移除旧 GPIO4/5 功能的启动调用;GPIO10 马达未启用 |
| [platform_stepper_driver.c](../components/platform/src/platform_stepper_driver.c) | 34–37 行相位宏;331 行 GPIO 初始化 | 使用 Kconfig,不应改相位表来代替正确引脚配置 |
| [platform_battery_driver.c](../components/platform/src/platform_battery_driver.c) | 约 136 行状态输入;158 行 ADC 映射;296 行采样状态 | 迁移 ADC/充电输入;新增独立充满输入及原始样本处理 |
| [platform.h](../components/platform/include/platform.h) | 约 406 行电池硬件样本契约 | 如接入充满检测,扩展平台硬件样本,保留未知/无效状态 |
| [domain.h](../components/domain/include/domain.h) / [domain_battery_service.c](../components/domain/src/battery/domain_battery_service.c) | 领域电池语义;样本到领域状态映射;约 363 行深睡调用 | 领域层拥有充电/满电语义,不能由显示层直接读取 GPIO8 判断 |
| [control_plane_battery_service.c](../components/control_plane/src/runtime/control_plane_battery_service.c) | 104 行起充电中断;约 400 行后满电推断/提示 | 迁移充电引脚配置自动覆盖现有中断;若新增满电检测,调整确认/提示策略和相应事件来源 |
| [domain_runtime_adapters.c](../components/domain/src/runtime/domain_runtime_adapters.c) | 807 / 836 / 865 行三路数字输入映射 | 已读取配置,单纯迁脚通常无需改;核对 PTT 有效电平 |
| [control_plane_key_input.c](../components/control_plane/src/runtime/control_plane_key_input.c) | 158 行起 `s_key_configs` | 同步核对三路按键及可选 reset,不把两个功能配置到同一 GPIO |
| [audio_pipeline_codec_impl.c](../components/platform/src/multimodal/audio_pipeline/audio_pipeline_codec_impl.c) | 148 行 I2C;223 行 I2S;318 行 PA | I2C/I2S 不变,PA 配置迁移到 9 |
| [audio_pipeline_runtime_impl.c](../components/platform/src/multimodal/audio_pipeline/audio_pipeline_runtime_impl.c) | 约 1536 行 PA 开关 | 已使用 PA 配置;与 codec 初始化共同核对 |
| [platform_behavior_stubs.c](../components/platform/src/platform_behavior_stubs.c) | 57 行起 power hold | 保持 `TQ_POWER_HOLD_GPIO=-1`,新板没有 MCU 电源保持控制网 |
| [gpio-map.md](gpio-map.md) / [firmware-pin-usage.md](firmware-pin-usage.md) | 原有板级/固件引脚表 | 实施时按板型注明适用版本并同步,不把旧表直接当新板事实 |
行号为本次工作区快照,后续应优先按配置名或函数名搜索。
## 适配注意事项(原理与后续工作)
### 1. GPIO4/5 的后台输出冲突
保留的旧 `platform_io_effects_init()` 实现会创建 GPIO5 脉冲任务和 GPIO4 RMT 灯带任务。即使 LCD 已改成新引脚,这些任务仍可能持续改写 BLK/CS。因此只改屏幕六个配置不够,也不能只把 `PLATFORM_PULSE_GPIO` 改为 10 后继续让 RMT 占 GPIO4。
新图没有专用 WS2812 连接;不能自行选择一个 NC 引脚作为灯带接口。若迁移摇臂马达,应明确启动、停止、默认关闭和有界退出,不能把旧的无限脉冲循环直接视为已经完成的新电机驱动。
### 2. 电池电压采样
旧板为 GPIO9 的 Power_t。新板 GPIO17 对应 ESP32-S3 的 ADC2 通道6。驱动已去掉仅接受 ADC1 的旧限制,ADC 初始化与校准均使用 ESP-IDF 返回的单元/通道;读取失败继续返回错误,不把无效值当作低电量。
GPIO17 的“电量检测”来自下板 Q5/Q6 控制后的电池分压:R6、R11 均为 100kΩ,名义比例仍为 1:2;上板还有 C31 100nF 滤波。
`TQ_BATTERY_DIVIDER_HIGH_OHM/LOW_OHM` 可先保留 100000/100000。新电路有 MOS 开关,需实测上电、深睡和负载时检测点电压与真实 VBAT 的对应关系,再决定校准增益/偏移。不要因 GPIO 换位就修改 SOC 曲线。
### 3. 充电与充满检测
新下板正式电路使用 TP4056,CHRG#/STDBY# 经 Q7/Q8、3.3V 上拉后送至 GPIO18/GPIO8。按电路作用可预期状态拉低时对应输入低有效,但这属于图纸推断:首次上板应记录“未插电 / 正在充电 / 充满 / 无电池”的两路实际电平,再确定配置和异常组合处理。不能仅凭换了充电芯片就反转电平。
现有固件只有“未知 / 未充电 / 充电中”硬件充电状态,满电提示依赖电压、百分比、时间确认。`TQ_BATTERY_FULL_MIN_*` 是满电推断阈值,**不是 GPIO8 配置项**。
最小迁移可以先只使用 GPIO18,保留旧满电推断,并明确 GPIO8 尚未使用。要利用独立充满检测,需增加配置、平台原始采样、领域状态解释及控制层提示策略;不在上层 facade 复制平台类型,也不在 LCD 内读取原始 GPIO。
充电 GPIO 同时参与中断和深睡唤醒:`domain_battery_service.c` 将 `CONFIG_TQ_BATTERY_CHARGE_GPIO` 传给 `platform_power_enter_deep_sleep()`,实施时一并检查唤醒驱动对新引脚及有效电平的处理。
### 4. 两个机械开关与触摸 PTT
开关1/2均有外部 10kΩ 上拉、闭合接地,可沿用有效电平 0、内部上拉开启、下拉关闭。TTP223 是主动输出,触摸有效电平取决于实际模式/焊接配置;不能因当前 PTT 设置为低有效,就认定新 GPIO13 也低有效。需要实测空闲/触摸电平,并同步 `MULTIMODAL_PTT_BUTTON_ACTIVE_LEVEL` 及上下拉。
现有 `firmware-pin-usage.md` 写 PTT=13、抽签开关=6,但适配前 defaults、本地 sdkconfig 和 Kconfig 实际为 PTT=3、抽签=13。新板现已改为 PTT=13、抽签=12。新板 GPIO6 是 LCD DC,GPIO13 是触摸输出,旧文档的 GPIO6 飞线方案不可沿用。
`TQ_RESET_BUTTON_ENABLE` 当前关闭;其默认 GPIO14 已成为新步进 IN1。新板没有独立 reset 键接线时保持关闭,不要只因该配置存在就启用。
### 5. 电机电源与顺序
新板步进电机由下板 Boost-5V、ULN2003 驱动;直流摇臂马达由上板 3.3V、Q3 AO3400A 低侧控制,GPIO10 高电平导通,R30 100kΩ 下拉提供关断偏置。二者不是同一驱动,不能把 GPIO10 加进四相步进表。
新板步进顺序必须为 IN1=14、IN2=21、IN3=47、IN4=48。原 GPIO45 在新图为 NC。首次验证需确认方向、校准开关及有界停止;供电变化不能仅靠 GPIO 表验证。
## 已应用的新板配置
以下已有配置项均已写入 Kconfig 默认值、sdkconfig.defaults 和本地 sdkconfig。PTT 有效电平仍待实测,新增 GPIO8/10 功能未接入。
```ini
CONFIG_TQ_SCREEN_BACKLIGHT_GPIO=4
CONFIG_TQ_SCREEN_SPI_CS_GPIO=5
CONFIG_TQ_SCREEN_DC_GPIO=6
CONFIG_TQ_SCREEN_RESET_PIN=7
CONFIG_TQ_SCREEN_SPI_MOSI_GPIO=15
CONFIG_TQ_SCREEN_SPI_CLK_GPIO=16
CONFIG_TQ_SCREEN_SPI_MISO_GPIO=-1
CONFIG_TQ_BATTERY_ADC_GPIO=17
CONFIG_TQ_BATTERY_CHARGE_GPIO=18
CONFIG_MULTIMODAL_AUDIO_PA_GPIO=9
CONFIG_TQ_POWER_HOLD_GPIO=-1
CONFIG_TQ_CALIBRATION_SWITCH_GPIO=11
CONFIG_TQ_SLOT_SWITCH_GPIO=12
CONFIG_MULTIMODAL_PTT_BUTTON_GPIO=13
# CONFIG_TQ_RESET_BUTTON_ENABLE is not set
CONFIG_TQ_STEPPER_IN1_GPIO=14
CONFIG_TQ_STEPPER_IN2_GPIO=21
CONFIG_TQ_STEPPER_IN3_GPIO=47
CONFIG_TQ_STEPPER_IN4_GPIO=48
```
平台初始化已停止调用旧 GPIO4/5 输出模块;GPIO8 满电和 GPIO10 马达没有新增配置项。音频 SDA=1、SCL=2、MCLK=38、BCLK=39、DOUT=40、WS=41、DIN=42 保持。
## 实施顺序与验证边界
1. 先在新板配置下禁用旧 GPIO4/5 任务,保持马达默认关闭;必要时首次调试暂时关闭开机转盘校准。
2. 同步 defaults、Kconfig 和本地有效配置,核对 GPIO8/17/18 全部为输入用途、GPIO9 为 PA、GPIO14 无 reset 冲突。
3. 验证 LCD、音频、开关1/2及触摸有效电平,再分别验证步进相序和摇臂马达,最后启用开机校准。
4. 测量 ADC 与 VBAT、充电/充满两路真值表,验证拔插充电、满电提示、低电量及深睡唤醒。
5. 实施后执行 ESP-IDF 5.5.4 构建;修改显示配置/机制后执行仓库列出的五个显示回归脚本,并按实际变更补充检查。检查联网、语音与电机同时运行时的稳定性。
6. 同步 GPIO 两份说明和受影响的中文开发指南;保留旧板版本信息。涉及新增跨层状态时遵守现有电池契约所有权,不在 composition 添加硬件策略。
本次证据层级:两份 PDF 文本提取及关键连线视觉核对、工作区配置和源码静态核对。新板配置的构建与回归记录见下方;没有设备验证结果。
### 2026-10-23 重新切换新板后的验证记录
本次在保留 VAD 重复 PTT 修复和 kikivok.com 域名迁移的基础上重新应用;以下主机测试与构建均已重新执行。
- 现有 27 个 GPIO/PIN 选项数量未变;Kconfig 默认值、sdkconfig.defaults、本地 sdkconfig 一致,已启用的 GPIO 无重复,GPIO8/10 未分配新功能。
- 主机:五个显示回归脚本全部通过,包括脚本自带 profiling 开/关分支;`tools/test_battery_adc_init.py` 通过实际 C 初始化函数的 ADC2/ADC1 单元和通道传递、重复初始化、锁失败、通道/校准失败释放与重试。
- 构建:ESP-IDF 5.5.4 新板有效配置构建通过;应用镜像 3,154,064 B。首次受沙箱 sysctl 权限限制,放宽本地构建权限后完成;未修改工具链或组件管理器。
- 未增加运行时任务、像素/音频缓存或 DMA 缓冲;旧 GPIO4/5 输出任务不再创建。未烧录,尚未确认触摸电平、ADC2 在 Wi-Fi 负载下采样、充电/唤醒、步进方向及显示并行稳定性。
+27 -26
View File
@@ -1,40 +1,41 @@
# ESP32-S3 GPIO Map
This document defines the active firmware GPIO assignments for the current
battery-sensing ESP32-S3 board revision. Signal direction is described from the
MCU's perspective. Older 2026-07-24 drawings assigned GPIO9 to a legacy power
hold net; that assignment is not valid for the current board.
This document describes the new upper/lower board in
`schematic/电机-马达方案.pdf` (upper board updated 2026-10-19; lower board
updated 2026-10-12). Directions are from the MCU's perspective. Firmware GPIO
settings are collected under `TQ Cat Configuration -> Board Hardware
Configuration (GPIO)`; see [firmware usage](firmware-pin-usage.md).
## GPIO Table
| U5 Pin | GPIO | Net | Direction | Connection / Function | Notes |
| U11 Module Pin | GPIO | Net | Direction | Connection / Function | Notes |
| --- | --- | --- | --- | --- | --- |
| 1 | GND | GND | N/A | Ground reference | Ground reference |
| 2 | 3V3 | 3V3 | Power | 3.3 V supply rail | Power rail |
| 3 | EN/RST | EN | Input | Chip enable and reset input | Reset and enable |
| 4 | GPIO4 | TP_INT | Bidirectional | Optional touch interrupt / reusable IO | Not connected by the 8-wire LCD adapter |
| 5 | GPIO5 | TP_SDA | Bidirectional | Optional touch I2C SDA / reusable IO | Not connected by the 8-wire LCD adapter |
| 6 | GPIO6 | TP_SCL | Input | Rocker microswitch / original SW2 function | Reuses the touch-clock contact left open by the 8-wire LCD adapter; active-low with internal pull-up |
| 7 | GPIO7 | BLK | Output | LCD adapter backlight control | Active-high firmware default |
| 8 | GPIO15 | CS | Output | ST7789P3 SPI chip select | Active low |
| 9 | GPIO16 | DC | Output | ST7789P3 data/command select | Also named A0 by the panel specification |
| 10 | GPIO17 | RES | Output | ST7789P3 hardware reset | Active low |
| 11 | GPIO18 | MOSI | Output | ST7789P3 SPI data / SDA | 4-line SPI write data |
| 12 | GPIO8 | CLK / Swing | Output | ST7789P3 SPI clock | Do not drive the Swing function while the LCD is connected |
| 4 | GPIO4 | BLK | Output | LCD backlight enable | Active high; old RMT output is not started |
| 5 | GPIO5 | CS | Output | ST7789P3 SPI chip select | Old pulse output is not started |
| 6 | GPIO6 | DC | Output | ST7789P3 data/command | Do not use old microswitch wiring |
| 7 | GPIO7 | RES | Output | ST7789P3 reset | Active low |
| 8 | GPIO15 | SDA | Output | ST7789P3 SPI MOSI | SPI data, not I2C SDA |
| 9 | GPIO16 | SCL | Output | ST7789P3 SPI clock | SPI clock, not I2C SCL |
| 10 | GPIO17 | 电量检测 | Analog input | Battery voltage sense | Lower-board R6/R11=100 kOhm each, Q5/Q6 switching; upper-board C31 filter |
| 11 | GPIO18 | 充电检测 | Input | TP4056 CHRG# via Q7 | Low-active assumption requires hardware verification |
| 12 | GPIO8 | 充满检测 | Input | TP4056 STDBY# via Q8 | Not consumed by current firmware; no new option added |
| 13 | GPIO19 | ESP_D_N | Bidirectional | USB D- | Type-C |
| 14 | GPIO20 | ESP_D_P | Bidirectional | USB D+ | Type-C |
| 15 | GPIO3 | touch | Input | TTP223 touch-button output | Present on the board but not consumed by the current input policy |
| 15 | GPIO3 | NC | N/A | No assigned net | Old touch input moved to GPIO13 |
| 16 | GPIO46 | UNASSIGNED | N/A | No connection assigned | Reserved; no signal assigned |
| 17 | GPIO9 | Power_t | Analog input | Battery voltage sense | R17=100 kOhm from VBAT and R18=100 kOhm to GND; ADC voltage is one half of VBAT |
| 18 | GPIO10 | Charge | Input | TP4057 charger status | Active-low while charging; high means full or external power absent |
| 19 | GPIO11 | PA_CTRL | Output | Audio power-amplifier enable | Amplifier control |
| 20 | GPIO12 | SW1 | Input | Button 1 / turntable calibration switch | External 10 kOhm pull-up; active low |
| 21 | GPIO13 | SW2 | Input | Button 2 / K2 push-to-talk input | External 10 kOhm pull-up; active low |
| 22 | GPIO14 | UNASSIGNED / RESET_KEY | Optional input | Configurable Wi-Fi reset button | Unassigned and disabled by default; active-low with internal pull-up when enabled |
| 23 | GPIO21 | IN4 | Output | ULN2003 IN4 | Stepper motor phase control |
| 17 | GPIO9 | PA_CTRL | Output | Audio amplifier enable | Not a battery ADC input on this board |
| 18 | GPIO10 | 马达控制 | Output | Q3 low-side DC rocker-motor control | Not consumed by current firmware; external R30 pull-down |
| 19 | GPIO11 | 开关1 | Input | Turntable calibration switch | External 10 kOhm pull-up; active low |
| 20 | GPIO12 | 开关2 | Input | Slot/fortune input | External 10 kOhm pull-up; active low |
| 21 | GPIO13 | 触摸铜箔 | Input | TTP223 output / PTT | Verify actual touch polarity; firmware retains previous active-level setting |
| 22 | GPIO14 | IN1 | Output | ULN2003 IN1 | Optional Wi-Fi reset must remain disabled on this pin |
| 23 | GPIO21 | IN2 | Output | ULN2003 IN2 | Stepper phase control |
| 24 | GPIO47 | IN3 | Output | ULN2003 IN3 | Stepper motor phase control |
| 25 | GPIO48 | IN2 | Output | ULN2003 IN2 | Stepper motor phase control |
| 26 | GPIO45 | IN1 | Output | ULN2003 IN1 | Stepper motor phase control |
| 25 | GPIO48 | IN4 | Output | ULN2003 IN4 | Stepper phase control |
| 26 | GPIO45 | NC | N/A | No assigned net | No longer stepper IN1 |
| 27 | GPIO0 | BOOT | Input | Boot/download switch | 10 kOhm pull-up to 3V3 |
| 28 | GPIO35 | UNASSIGNED | N/A | No connection assigned | Reserved; no signal assigned |
| 29 | GPIO36 | UNASSIGNED | N/A | No connection assigned | Reserved; no signal assigned |
@@ -44,8 +45,8 @@ hold net; that assignment is not valid for the current board.
| 33 | GPIO40 | I2S_DSDIN | Output | ES8311 DSDIN | Audio interface |
| 34 | GPIO41 | I2S_LRCK | Output | ES8311 LRCK | Audio interface |
| 35 | GPIO42 | I2S_ASDOUT | Input | ES8311 ASDOUT | Audio interface |
| 36 | RXD0 | esp_tx | Input | Debug UART | Routed to J2 |
| 37 | TXD0 | esp_rx | Output | Debug UART | Routed to J2 |
| 36 | RXD0 | TX | Input | UART0 RX | Routed to CN5; connector net names reflect the opposite endpoint |
| 37 | TXD0 | RX | Output | UART0 TX | Routed to CN5; connector net names reflect the opposite endpoint |
| 38 | GPIO2 | IO2_I2C_SCL | Bidirectional | ES8311 control interface SCL | Audio codec |
| 39 | GPIO1 | IO1_I2C_SDA | Bidirectional | ES8311 control interface SDA | Audio codec |
| 40 | GND | GND | N/A | Ground reference | Ground reference |
+298 -281
View File
@@ -1,5 +1,302 @@
menu "TQ Cat Configuration"
menu "Board Hardware Configuration (GPIO)"
comment "LCD"
config TQ_SCREEN_RESET_PIN
int "Panel reset GPIO (-1 to disable hardware reset)"
default 7
range -1 48
help
The new upper board maps the ST7789P3 RES signal to IO7.
Use -1 only when panel reset is physically not connected.
config TQ_SCREEN_SPI_MISO_GPIO
int "LCD SPI MISO GPIO (-1 to disable)"
default -1
range -1 48
help
LCD SPI MISO GPIO. Use -1 when the panel does not connect MISO.
config TQ_SCREEN_SPI_MOSI_GPIO
int "LCD SPI MOSI GPIO"
default 15
range 0 48
help
LCD SPI MOSI GPIO.
config TQ_SCREEN_SPI_CLK_GPIO
int "LCD SPI clock GPIO"
default 16
range 0 48
help
LCD SPI clock GPIO.
config TQ_SCREEN_SPI_CS_GPIO
int "LCD SPI CS GPIO"
default 5
range 0 48
help
LCD SPI chip-select GPIO.
config TQ_SCREEN_DC_GPIO
int "LCD D/C GPIO"
default 6
range 0 48
help
LCD data/command GPIO.
config TQ_SCREEN_BACKLIGHT_GPIO
int "LCD backlight GPIO"
default 4
range 0 48
help
LCD backlight control GPIO.
config TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH
bool "Backlight active high"
default y
comment "Audio"
config MULTIMODAL_AUDIO_I2C_SCL_GPIO
int "I2C SCL GPIO"
default 2
help
Default from docs/gpio-map.md (ES8311 control SCL on GPIO2).
config MULTIMODAL_AUDIO_I2C_SDA_GPIO
int "I2C SDA GPIO"
default 1
help
Default from docs/gpio-map.md (ES8311 control SDA on GPIO1).
config MULTIMODAL_AUDIO_I2S_MCLK_GPIO
int "I2S MCLK GPIO"
default 38
help
Default from docs/gpio-map.md (I2S_MCLK on GPIO38).
config MULTIMODAL_AUDIO_I2S_BCLK_GPIO
int "I2S BCLK GPIO"
default 39
help
Default from docs/gpio-map.md (I2S_SCLK on GPIO39).
config MULTIMODAL_AUDIO_I2S_WS_GPIO
int "I2S WS GPIO"
default 41
help
Default from docs/gpio-map.md (I2S_LRCK on GPIO41).
config MULTIMODAL_AUDIO_I2S_DOUT_GPIO
int "I2S DOUT GPIO"
default 40
help
Default from docs/gpio-map.md (MCU output to ES8311 DSDIN on GPIO40).
config MULTIMODAL_AUDIO_I2S_DIN_GPIO
int "I2S DIN GPIO"
default 42
help
Default from docs/gpio-map.md (MCU input from ES8311 ASDOUT on GPIO42).
config MULTIMODAL_AUDIO_PA_GPIO
int "PA enable GPIO (-1 to disable)"
default 9
help
Default from docs/gpio-map.md (PA_CTRL on IO9).
comment "Buttons & Digital Inputs"
config MULTIMODAL_PTT_BUTTON_GPIO
int "Push-to-talk button GPIO"
default 13
range 0 48
help
The new board routes the TTP223 touch output to GPIO13.
Verify its idle/active levels on hardware before changing
the active-level and pull-resistor settings.
config MULTIMODAL_PTT_BUTTON_ACTIVE_LEVEL
int "Push-to-talk button active level"
default 0
range 0 1
help
Logic level that means the push-to-talk button is pressed.
config MULTIMODAL_PTT_BUTTON_PULLUP
bool "Enable push-to-talk button pull-up"
default y
help
Enable the internal pull-up when required by the button wiring.
config MULTIMODAL_PTT_BUTTON_PULLDOWN
bool "Enable push-to-talk button pull-down"
default n
help
Enable the internal pull-down when required by the button wiring.
config TQ_CALIBRATION_SWITCH_GPIO
int "Direction calibration switch GPIO"
default 11
range 0 48
help
GPIO used for switch 1 on IO11 and for turntable
direction calibration.
config TQ_CALIBRATION_SWITCH_ACTIVE_LEVEL
int "Direction calibration switch active level"
default 0
range 0 1
help
Logic level that means the calibration switch is active.
config TQ_CALIBRATION_SWITCH_PULLUP
bool "Enable direction calibration switch pull-up"
default y
help
Enable the internal pull-up for the default active-low wiring.
config TQ_CALIBRATION_SWITCH_PULLDOWN
bool "Enable direction calibration switch pull-down"
default n
help
Leave disabled for the default active-low wiring.
config TQ_SLOT_SWITCH_GPIO
int "Slot feature switch GPIO"
default 12
range 0 48
help
GPIO used by the input that triggers the slot machine feature.
config TQ_SLOT_SWITCH_ACTIVE_LEVEL
int "Slot feature switch active level"
default 0
range 0 1
help
Logic level that means the slot machine feature switch is active.
config TQ_SLOT_SWITCH_PULLUP
bool "Enable slot feature switch pull-up"
default y
help
Enable the internal pull-up for the default active-low slot switch wiring.
config TQ_SLOT_SWITCH_PULLDOWN
bool "Enable slot feature switch pull-down"
default n
help
Leave disabled for the default active-low slot switch wiring.
config TQ_RESET_BUTTON_GPIO
int "Wi-Fi reset button GPIO"
default 14
range 0 48
depends on TQ_RESET_BUTTON_ENABLE
help
GPIO used for the dedicated Wi-Fi reset button when enabled.
The new board uses GPIO14 for stepper IN1. Keep this feature
disabled unless a separate reset input is physically wired
and its GPIO configured without conflicts.
config TQ_RESET_BUTTON_ACTIVE_LEVEL
int "Wi-Fi reset button active level"
default 0
range 0 1
depends on TQ_RESET_BUTTON_ENABLE
help
Logic level that means the Wi-Fi reset button is pressed.
config TQ_RESET_BUTTON_PULLUP
bool "Enable Wi-Fi reset button pull-up"
default y
depends on TQ_RESET_BUTTON_ENABLE
help
Enable the internal pull-up for active-low wiring.
config TQ_RESET_BUTTON_PULLDOWN
bool "Enable Wi-Fi reset button pull-down"
default n
depends on TQ_RESET_BUTTON_ENABLE
help
Enable the internal pull-down for active-high wiring.
comment "Stepper Motor"
config TQ_STEPPER_IN1_GPIO
int "Turntable stepper IN1 GPIO"
default 14
range 0 48
help
GPIO connected to the turntable stepper driver IN1 input.
config TQ_STEPPER_IN2_GPIO
int "Turntable stepper IN2 GPIO"
default 21
range 0 48
help
GPIO connected to the turntable stepper driver IN2 input.
config TQ_STEPPER_IN3_GPIO
int "Turntable stepper IN3 GPIO"
default 47
range 0 48
help
GPIO connected to the turntable stepper driver IN3 input.
config TQ_STEPPER_IN4_GPIO
int "Turntable stepper IN4 GPIO"
default 48
range 0 48
help
GPIO connected to the turntable stepper driver IN4 input.
comment "Power & Battery"
config TQ_POWER_HOLD_GPIO
int "Power hold GPIO (-1 to disable)"
default -1
range -1 48
help
GPIO used to keep board power enabled after boot. The new
board has no MCU-controlled power-hold net; leave disabled.
config TQ_POWER_HOLD_ACTIVE_LEVEL
int "Power hold active level"
default 1
range 0 1
help
Logic level that keeps the external power-hold circuit active.
config TQ_BATTERY_ADC_GPIO
int "Battery voltage ADC GPIO"
default 17
range 0 48
depends on TQ_BATTERY_ENABLE
config TQ_BATTERY_CHARGE_GPIO
int "TP4056 charge status GPIO (-1 to disable)"
default 18
range -1 48
depends on TQ_BATTERY_ENABLE
config TQ_BATTERY_CHARGE_ACTIVE_LEVEL
int "TP4056 charging active level"
default 0
range 0 1
depends on TQ_BATTERY_ENABLE
config TQ_BATTERY_SHUTDOWN_WAKE_BUTTON_GPIO
int "Optional active-low deep-sleep wake button GPIO (-1 to disable)"
default -1
range -1 48
depends on TQ_BATTERY_CONTROLLED_SHUTDOWN_ENABLE
endmenu
menu "Legacy LCD Driver Options"
choice LCD_TYPE
@@ -549,37 +846,6 @@ menu "TQ Cat Configuration"
configured duration clears saved Wi-Fi credentials and then
restarts the device. Other persisted data is not changed.
config TQ_RESET_BUTTON_GPIO
int "Wi-Fi reset button GPIO"
default 14
range 0 48
depends on TQ_RESET_BUTTON_ENABLE
help
GPIO used for the dedicated Wi-Fi reset button when enabled.
GPIO14 is unassigned on the current board revision.
config TQ_RESET_BUTTON_ACTIVE_LEVEL
int "Wi-Fi reset button active level"
default 0
range 0 1
depends on TQ_RESET_BUTTON_ENABLE
help
Logic level that means the Wi-Fi reset button is pressed.
config TQ_RESET_BUTTON_PULLUP
bool "Enable Wi-Fi reset button pull-up"
default y
depends on TQ_RESET_BUTTON_ENABLE
help
Enable the internal pull-up for active-low wiring.
config TQ_RESET_BUTTON_PULLDOWN
bool "Enable Wi-Fi reset button pull-down"
default n
depends on TQ_RESET_BUTTON_ENABLE
help
Enable the internal pull-down for active-high wiring.
config TQ_RESET_BUTTON_LONG_PRESS_MS
int "Wi-Fi reset button hold duration (ms)"
default 5000
@@ -699,10 +965,6 @@ menu "TQ Cat Configuration"
bool "Swap RGB565 color bytes on bus"
default y
config TQ_SCREEN_BACKLIGHT_ACTIVE_HIGH
bool "Backlight active high"
default y
config TQ_SCREEN_BACKLIGHT_BRIGHTNESS_PERCENT
int "Default backlight brightness (percent)"
default 100
@@ -730,56 +992,6 @@ menu "TQ Cat Configuration"
default 0
range 0 320
config TQ_SCREEN_RESET_PIN
int "Panel reset GPIO (-1 to disable hardware reset)"
default 17
range -1 48
help
The 2026-07-24 board maps the ST7789P3 RES signal to IO17.
Use -1 only when panel reset is physically not connected.
config TQ_SCREEN_SPI_MISO_GPIO
int "LCD SPI MISO GPIO (-1 to disable)"
default -1
range -1 48
help
LCD SPI MISO GPIO. Use -1 when the panel does not connect MISO.
config TQ_SCREEN_SPI_MOSI_GPIO
int "LCD SPI MOSI GPIO"
default 18
range 0 48
help
LCD SPI MOSI GPIO.
config TQ_SCREEN_SPI_CLK_GPIO
int "LCD SPI clock GPIO"
default 8
range 0 48
help
LCD SPI clock GPIO.
config TQ_SCREEN_SPI_CS_GPIO
int "LCD SPI CS GPIO"
default 15
range 0 48
help
LCD SPI chip-select GPIO.
config TQ_SCREEN_DC_GPIO
int "LCD D/C GPIO"
default 16
range 0 48
help
LCD data/command GPIO.
config TQ_SCREEN_BACKLIGHT_GPIO
int "LCD backlight GPIO"
default 7
range 0 48
help
LCD backlight control GPIO.
config TQ_SCREEN_SPI_PIXEL_CLOCK_HZ
int "LCD SPI pixel clock (Hz)"
default 20000000
@@ -808,32 +1020,6 @@ menu "TQ Cat Configuration"
menu "Slot Machine"
config TQ_SLOT_SWITCH_GPIO
int "Slot feature switch GPIO"
default 13
range 0 48
help
GPIO used by the input that triggers the slot machine feature.
config TQ_SLOT_SWITCH_ACTIVE_LEVEL
int "Slot feature switch active level"
default 0
range 0 1
help
Logic level that means the slot machine feature switch is active.
config TQ_SLOT_SWITCH_PULLUP
bool "Enable slot feature switch pull-up"
default y
help
Enable the internal pull-up for the default active-low slot switch wiring.
config TQ_SLOT_SWITCH_PULLDOWN
bool "Enable slot feature switch pull-down"
default n
help
Leave disabled for the default active-low slot switch wiring.
config TQ_SLOT_SWITCH_ENABLE
bool "Enable slot feature switch worker"
default y
@@ -859,110 +1045,21 @@ menu "TQ Cat Configuration"
The motor searches for the active-low switch and stops after
the configured calibration sweep if the switch is not pressed.
config TQ_STEPPER_IN1_GPIO
int "Turntable stepper IN1 GPIO"
default 45
range 0 48
help
GPIO connected to the turntable stepper driver IN1 input.
config TQ_STEPPER_IN2_GPIO
int "Turntable stepper IN2 GPIO"
default 48
range 0 48
help
GPIO connected to the turntable stepper driver IN2 input.
config TQ_STEPPER_IN3_GPIO
int "Turntable stepper IN3 GPIO"
default 47
range 0 48
help
GPIO connected to the turntable stepper driver IN3 input.
config TQ_STEPPER_IN4_GPIO
int "Turntable stepper IN4 GPIO"
default 21
range 0 48
help
GPIO connected to the turntable stepper driver IN4 input.
config TQ_CALIBRATION_SWITCH_GPIO
int "Direction calibration switch GPIO"
default 12
range 0 48
help
GPIO used for Button 1 on the SW1/IO12 net and for turntable
direction calibration.
config TQ_CALIBRATION_SWITCH_ACTIVE_LEVEL
int "Direction calibration switch active level"
default 0
range 0 1
help
Logic level that means the calibration switch is active.
config TQ_CALIBRATION_SWITCH_PULLUP
bool "Enable direction calibration switch pull-up"
default y
help
Enable the internal pull-up for the default active-low wiring.
config TQ_CALIBRATION_SWITCH_PULLDOWN
bool "Enable direction calibration switch pull-down"
default n
help
Leave disabled for the default active-low wiring.
endmenu
menu "Power & Battery"
config TQ_POWER_HOLD_GPIO
int "Power hold GPIO (-1 to disable)"
default -1
range -1 48
help
GPIO used to keep board power enabled after boot. The current
battery-sensing board uses IO9 as an ADC input and therefore
disables the legacy power-hold output by default.
config TQ_POWER_HOLD_ACTIVE_LEVEL
int "Power hold active level"
default 1
range 0 1
help
Logic level that keeps the external power-hold circuit active.
config TQ_BATTERY_ENABLE
bool "Enable battery monitoring"
default y
config TQ_BATTERY_ADC_GPIO
int "Battery voltage ADC GPIO"
default 9
range 0 48
depends on TQ_BATTERY_ENABLE
config TQ_BATTERY_CHARGE_GPIO
int "TP4057 charge status GPIO (-1 to disable)"
default 10
range -1 48
depends on TQ_BATTERY_ENABLE
config TQ_BATTERY_CHARGE_ACTIVE_LEVEL
int "TP4057 charging active level"
default 0
range 0 1
depends on TQ_BATTERY_ENABLE
config TQ_BATTERY_FULL_MIN_VOLTAGE_MV
int "Minimum voltage for charge-complete prompt (mV)"
default 4150
range 4000 4200
depends on TQ_BATTERY_ENABLE
help
The TP4057 status pin cannot distinguish charge termination
The charging-status input alone cannot distinguish charge termination
from charger removal. Require at least this filtered battery
voltage before inferring that charging has completed.
@@ -1061,12 +1158,6 @@ menu "TQ Cat Configuration"
range 3000 4200
depends on TQ_BATTERY_CONTROLLED_SHUTDOWN_ENABLE
config TQ_BATTERY_SHUTDOWN_WAKE_BUTTON_GPIO
int "Optional active-low deep-sleep wake button GPIO (-1 to disable)"
default -1
range -1 48
depends on TQ_BATTERY_CONTROLLED_SHUTDOWN_ENABLE
config TQ_BATTERY_SHUTDOWN_PROMPT_FILE
string "Critical-battery shutdown prompt file"
default "audio_prompts/shutdown_power_empty.opus"
@@ -1383,32 +1474,6 @@ menu "TQ Cat Configuration"
Fixed to push2talk. Other upstream modes are intentionally not
supported by this firmware runtime.
config MULTIMODAL_PTT_BUTTON_GPIO
int "Push-to-talk button GPIO"
default 3
range 0 48
help
GPIO used for the push-to-talk button.
config MULTIMODAL_PTT_BUTTON_ACTIVE_LEVEL
int "Push-to-talk button active level"
default 0
range 0 1
help
Logic level that means the push-to-talk button is pressed.
config MULTIMODAL_PTT_BUTTON_PULLUP
bool "Enable push-to-talk button pull-up"
default y
help
Enable the internal pull-up when required by the button wiring.
config MULTIMODAL_PTT_BUTTON_PULLDOWN
bool "Enable push-to-talk button pull-down"
default n
help
Enable the internal pull-down when required by the button wiring.
config TQ_LOCAL_WAKE_ENABLE
bool "Enable local wake-word listener"
default y
@@ -1832,18 +1897,6 @@ menu "TQ Cat Configuration"
range 0 1
default 0
config MULTIMODAL_AUDIO_I2C_SCL_GPIO
int "I2C SCL GPIO"
default 2
help
Default from docs/gpio-map.md (ES8311 control SCL on GPIO2).
config MULTIMODAL_AUDIO_I2C_SDA_GPIO
int "I2C SDA GPIO"
default 1
help
Default from docs/gpio-map.md (ES8311 control SDA on GPIO1).
config MULTIMODAL_AUDIO_I2C_ADDR
hex "ES8311 I2C address"
default 0x18
@@ -1855,46 +1908,10 @@ menu "TQ Cat Configuration"
range 0 1
default 0
config MULTIMODAL_AUDIO_I2S_MCLK_GPIO
int "I2S MCLK GPIO"
default 38
help
Default from docs/gpio-map.md (I2S_MCLK on GPIO38).
config MULTIMODAL_AUDIO_I2S_BCLK_GPIO
int "I2S BCLK GPIO"
default 39
help
Default from docs/gpio-map.md (I2S_SCLK on GPIO39).
config MULTIMODAL_AUDIO_I2S_WS_GPIO
int "I2S WS GPIO"
default 41
help
Default from docs/gpio-map.md (I2S_LRCK on GPIO41).
config MULTIMODAL_AUDIO_I2S_DOUT_GPIO
int "I2S DOUT GPIO"
default 40
help
Default from docs/gpio-map.md (MCU output to ES8311 DSDIN on GPIO40).
config MULTIMODAL_AUDIO_I2S_DIN_GPIO
int "I2S DIN GPIO"
default 42
help
Default from docs/gpio-map.md (MCU input from ES8311 ASDOUT on GPIO42).
config MULTIMODAL_AUDIO_USE_MCLK
bool "Use external MCLK"
default y
config MULTIMODAL_AUDIO_PA_GPIO
int "PA enable GPIO (-1 to disable)"
default 11
help
Default from docs/gpio-map.md (PA_CTRL on IO11).
config MULTIMODAL_AUDIO_I2S_DMA_DESC_NUM
int "I2S DMA descriptor count"
default 4
+15 -15
View File
@@ -192,7 +192,7 @@ CONFIG_AUTH_V2_ENABLE=y
CONFIG_TQ_FACTORY_CLI_ENABLE=y
CONFIG_TQ_FACTORY_CLI_TASK_STACK_BYTES=7168
CONFIG_MULTIMODAL_UPSTREAM_MODE="push2talk"
CONFIG_MULTIMODAL_PTT_BUTTON_GPIO=3
CONFIG_MULTIMODAL_PTT_BUTTON_GPIO=13
CONFIG_MULTIMODAL_PTT_BUTTON_ACTIVE_LEVEL=0
CONFIG_MULTIMODAL_PTT_BUTTON_PULLUP=y
# CONFIG_MULTIMODAL_PTT_BUTTON_PULLDOWN is not set
@@ -295,24 +295,24 @@ CONFIG_TQ_SCREEN_MIRROR_X=y
CONFIG_TQ_SCREEN_SWAP_XY=y
CONFIG_TQ_SCREEN_X_GAP=0
CONFIG_TQ_SCREEN_Y_GAP=0
CONFIG_TQ_SCREEN_RESET_PIN=17
CONFIG_TQ_SCREEN_RESET_PIN=7
CONFIG_TQ_SCREEN_SPI_MISO_GPIO=-1
CONFIG_TQ_SCREEN_SPI_MOSI_GPIO=18
CONFIG_TQ_SCREEN_SPI_CLK_GPIO=8
CONFIG_TQ_SCREEN_SPI_CS_GPIO=15
CONFIG_TQ_SCREEN_DC_GPIO=16
CONFIG_TQ_SCREEN_BACKLIGHT_GPIO=7
CONFIG_TQ_SCREEN_SPI_MOSI_GPIO=15
CONFIG_TQ_SCREEN_SPI_CLK_GPIO=16
CONFIG_TQ_SCREEN_SPI_CS_GPIO=5
CONFIG_TQ_SCREEN_DC_GPIO=6
CONFIG_TQ_SCREEN_BACKLIGHT_GPIO=4
CONFIG_TQ_SCREEN_SPI_PIXEL_CLOCK_HZ=40000000
CONFIG_TQ_SLOT_SWITCH_GPIO=13
CONFIG_TQ_SLOT_SWITCH_GPIO=12
CONFIG_TQ_SLOT_SWITCH_ACTIVE_LEVEL=0
CONFIG_TQ_SLOT_SWITCH_PULLUP=y
# CONFIG_TQ_SLOT_SWITCH_PULLDOWN is not set
CONFIG_TQ_BOOT_TURNTABLE_CALIBRATION_ENABLE=y
CONFIG_TQ_STEPPER_IN1_GPIO=45
CONFIG_TQ_STEPPER_IN2_GPIO=48
CONFIG_TQ_STEPPER_IN1_GPIO=14
CONFIG_TQ_STEPPER_IN2_GPIO=21
CONFIG_TQ_STEPPER_IN3_GPIO=47
CONFIG_TQ_STEPPER_IN4_GPIO=21
CONFIG_TQ_CALIBRATION_SWITCH_GPIO=12
CONFIG_TQ_STEPPER_IN4_GPIO=48
CONFIG_TQ_CALIBRATION_SWITCH_GPIO=11
CONFIG_TQ_CALIBRATION_SWITCH_ACTIVE_LEVEL=0
CONFIG_TQ_CALIBRATION_SWITCH_PULLUP=y
# CONFIG_TQ_CALIBRATION_SWITCH_PULLDOWN is not set
@@ -321,8 +321,8 @@ CONFIG_TQ_SCREEN_COLOR_AUTOTEST_INTERVAL_MS=3000
CONFIG_TQ_POWER_HOLD_GPIO=-1
CONFIG_TQ_POWER_HOLD_ACTIVE_LEVEL=1
CONFIG_TQ_BATTERY_ENABLE=y
CONFIG_TQ_BATTERY_ADC_GPIO=9
CONFIG_TQ_BATTERY_CHARGE_GPIO=10
CONFIG_TQ_BATTERY_ADC_GPIO=17
CONFIG_TQ_BATTERY_CHARGE_GPIO=18
CONFIG_TQ_BATTERY_CHARGE_ACTIVE_LEVEL=0
CONFIG_TQ_BATTERY_FULL_MIN_VOLTAGE_MV=4150
CONFIG_TQ_BATTERY_FULL_MIN_PERCENT=95
@@ -343,4 +343,4 @@ CONFIG_TQ_BATTERY_EMERGENCY_VOLTAGE_MV=3350
CONFIG_TQ_BATTERY_WAKE_RECOVERY_VOLTAGE_MV=3550
CONFIG_TQ_BATTERY_SHUTDOWN_WAKE_BUTTON_GPIO=-1
CONFIG_TQ_BATTERY_SHUTDOWN_PROMPT_FILE="audio_prompts/shutdown_power_empty.opus"
CONFIG_MULTIMODAL_AUDIO_PA_GPIO=11
CONFIG_MULTIMODAL_AUDIO_PA_GPIO=9
+164
View File
@@ -0,0 +1,164 @@
#!/usr/bin/env python3
"""Run the production battery initializer with ADC1/ADC2 and failure stubs."""
from pathlib import Path
import re
import subprocess
import tempfile
ROOT = Path(__file__).resolve().parents[1]
SOURCE = ROOT / "components/platform/src/platform_battery_driver.c"
def initializer():
source = SOURCE.read_text()
start = source.index("esp_err_t platform_battery_init(void)")
body = source.index("{", start)
end, depth = body + 1, 1
while depth:
depth += (source[end] == "{") - (source[end] == "}")
end += 1
return source[start:end]
STUBS = r'''
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
typedef int esp_err_t;
typedef int adc_unit_t;
typedef int adc_channel_t;
typedef void *adc_oneshot_unit_handle_t;
#define ESP_OK 0
#define ESP_ERR_TIMEOUT 1
#define ESP_ERR_INVALID_ARG 2
#define ESP_ERR_NO_MEM 3
#define ESP_ERR_NOT_SUPPORTED 4
#define ADC_UNIT_1 0
#define ADC_UNIT_2 1
#define ADC_CHANNEL_0 0
#define GPIO_NUM_MAX 49
#define GPIO_MODE_INPUT 1
#define GPIO_PULLUP_ENABLE 1
#define GPIO_PULLDOWN_DISABLE 0
#define GPIO_INTR_DISABLE 0
#define ADC_ULP_MODE_DISABLE 0
#define ADC_ATTEN_DB_12 3
#define ADC_BITWIDTH_DEFAULT 0
#define CONFIG_TQ_BATTERY_DIVIDER_HIGH_OHM 100000
#define CONFIG_TQ_BATTERY_DIVIDER_LOW_OHM 100000
#define ESP_LOGE(...) ((void)0)
#define ESP_LOGI(...) ((void)0)
typedef struct {
uint64_t pin_bit_mask;
int mode, pull_up_en, pull_down_en, intr_type;
} gpio_config_t;
typedef struct { int unit_id, ulp_mode; } adc_oneshot_unit_init_cfg_t;
typedef struct { int atten, bitwidth; } adc_oneshot_chan_cfg_t;
static adc_oneshot_unit_handle_t s_adc_handle;
static adc_channel_t s_adc_channel;
static bool s_initialized, locked;
static int fail_lock, gpio_error, mapping_error, unit_error, channel_error, calibration_error;
static int gpio_calls, unit_calls, delete_calls, calibration_calls;
static int actual_unit, actual_channel;
static uint64_t charge_mask;
static bool lock_adc(void) {
if (fail_lock) return false;
assert(!locked); locked = true; return true;
}
static void unlock_adc(void) { assert(locked); locked = false; }
static uint64_t gpio_mask(int gpio) { return UINT64_C(1) << gpio; }
static esp_err_t gpio_config(const gpio_config_t *cfg) {
++gpio_calls; charge_mask = cfg->pin_bit_mask; return gpio_error;
}
static esp_err_t adc_oneshot_io_to_channel(int gpio, adc_unit_t *unit, adc_channel_t *channel) {
if (mapping_error) return mapping_error;
if (gpio == 17) { *unit = ADC_UNIT_2; *channel = 6; return ESP_OK; }
if (gpio == 9) { *unit = ADC_UNIT_1; *channel = 8; return ESP_OK; }
return ESP_ERR_INVALID_ARG;
}
static esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *cfg,
adc_oneshot_unit_handle_t *handle) {
++unit_calls; actual_unit = cfg->unit_id;
if (unit_error) return unit_error;
*handle = (void *)(uintptr_t)1; return ESP_OK;
}
static esp_err_t adc_oneshot_config_channel(adc_oneshot_unit_handle_t handle,
adc_channel_t channel,
const adc_oneshot_chan_cfg_t *cfg) {
assert(handle && cfg->atten == ADC_ATTEN_DB_12);
actual_channel = channel; return channel_error;
}
static esp_err_t create_calibration(adc_unit_t unit, adc_channel_t channel) {
++calibration_calls;
assert(unit == actual_unit && channel == actual_channel);
return calibration_error;
}
static esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle) {
assert(handle); ++delete_calls; return ESP_OK;
}
'''
TESTS = r'''
static void reset(void) {
assert(!locked);
s_initialized = false; s_adc_handle = NULL;
fail_lock = gpio_error = mapping_error = unit_error = channel_error = calibration_error = 0;
gpio_calls = unit_calls = delete_calls = calibration_calls = 0;
}
int main(void) {
reset();
assert(platform_battery_init() == ESP_OK);
assert(s_initialized && !locked);
assert(actual_unit == EXPECTED_UNIT && actual_channel == EXPECTED_CHANNEL);
assert(s_adc_channel == EXPECTED_CHANNEL && calibration_calls == 1);
assert(charge_mask == (UINT64_C(1) << CONFIG_TQ_BATTERY_CHARGE_GPIO));
assert(platform_battery_init() == ESP_OK && unit_calls == 1 && gpio_calls == 1);
reset(); fail_lock = 1;
assert(platform_battery_init() == ESP_ERR_TIMEOUT && !s_initialized && !unit_calls);
reset(); gpio_error = ESP_ERR_INVALID_ARG;
assert(platform_battery_init() == gpio_error && !locked && !unit_calls);
reset(); mapping_error = ESP_ERR_INVALID_ARG;
assert(platform_battery_init() == mapping_error && !locked && !unit_calls);
reset(); unit_error = ESP_ERR_NO_MEM;
assert(platform_battery_init() == unit_error && !locked && !s_initialized && !delete_calls);
reset(); channel_error = ESP_ERR_INVALID_ARG;
assert(platform_battery_init() == channel_error && !locked && !s_initialized);
assert(delete_calls == 1 && s_adc_handle == NULL && !calibration_calls);
channel_error = ESP_OK;
assert(platform_battery_init() == ESP_OK && s_initialized);
reset(); calibration_error = ESP_ERR_NOT_SUPPORTED;
assert(platform_battery_init() == calibration_error && !locked && !s_initialized);
assert(delete_calls == 1 && s_adc_handle == NULL);
calibration_error = ESP_OK;
assert(platform_battery_init() == ESP_OK && s_initialized);
puts("PASS: battery ADC unit/channel propagation, idempotence, bounded lock failure, cleanup and retry");
}
'''
def main():
defaults = dict(re.findall(r"^CONFIG_(\w+)=(.*)$", (ROOT / "sdkconfig.defaults").read_text(), re.M))
adc_gpio = int(defaults["TQ_BATTERY_ADC_GPIO"])
charge_gpio = int(defaults["TQ_BATTERY_CHARGE_GPIO"])
assert (adc_gpio, charge_gpio) == (17, 18), "new board must use ADC GPIO17 / charge GPIO18"
with tempfile.TemporaryDirectory(prefix="battery-adc-init-") as tmp:
path = Path(tmp)
source = path / "init.c"
source.write_text(STUBS + initializer() + TESTS)
for gpio, unit, channel in [(adc_gpio, 1, 6), (9, 0, 8)]:
binary = path / f"init-{gpio}"
subprocess.run([
"clang", "-std=c11", "-Wall", "-Wextra", "-Werror",
"-fsanitize=address,undefined", "-fno-omit-frame-pointer",
f"-DCONFIG_TQ_BATTERY_ADC_GPIO={gpio}",
f"-DCONFIG_TQ_BATTERY_CHARGE_GPIO={charge_gpio}",
f"-DEXPECTED_UNIT={unit}", f"-DEXPECTED_CHANNEL={channel}",
str(source), "-o", str(binary),
], check=True)
subprocess.run([str(binary)], check=True)
if __name__ == "__main__":
main()