From aede687dc9e2011e6dd3d9c815f64d58008cb0d5 Mon Sep 17 00:00:00 2001 From: chenjintao Date: Fri, 23 Oct 2026 15:37:22 +0800 Subject: [PATCH] feat(platform): adapt GPIO configuration to new board --- .../platform/src/platform_battery_driver.c | 10 +- components/platform/src/platform_io_effects.c | 3 +- .../src/runtime/platform_core_runtime.c | 6 +- docs/GFX表情显示应用与开发指南.md | 17 + docs/firmware-pin-usage.md | 166 +++-- docs/gpio-board-adaptation.zh-CN.md | 194 ++++++ docs/gpio-map.md | 53 +- main/Kconfig.projbuild | 579 +++++++++--------- sdkconfig.defaults | 30 +- tools/test_battery_adc_init.py | 164 +++++ 10 files changed, 801 insertions(+), 421 deletions(-) create mode 100644 docs/gpio-board-adaptation.zh-CN.md create mode 100644 tools/test_battery_adc_init.py diff --git a/components/platform/src/platform_battery_driver.c b/components/platform/src/platform_battery_driver.c index b6aa343..4f436f8 100644 --- a/components/platform/src/platform_battery_driver.c +++ b/components/platform/src/platform_battery_driver.c @@ -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 = { diff --git a/components/platform/src/platform_io_effects.c b/components/platform/src/platform_io_effects.c index e5a074d..bef1631 100644 --- a/components/platform/src/platform_io_effects.c +++ b/components/platform/src/platform_io_effects.c @@ -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 diff --git a/components/platform/src/runtime/platform_core_runtime.c b/components/platform/src/runtime/platform_core_runtime.c index 2b38fd0..e035dcc 100644 --- a/components/platform/src/runtime/platform_core_runtime.c +++ b/components/platform/src/runtime/platform_core_runtime.c @@ -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(); diff --git a/docs/GFX表情显示应用与开发指南.md b/docs/GFX表情显示应用与开发指南.md index 7639b76..3126843 100644 --- a/docs/GFX表情显示应用与开发指南.md +++ b/docs/GFX表情显示应用与开发指南.md @@ -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 精度已验收。 diff --git a/docs/firmware-pin-usage.md b/docs/firmware-pin-usage.md index bf9dd07..0662137 100644 --- a/docs/firmware-pin-usage.md +++ b/docs/firmware-pin-usage.md @@ -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. diff --git a/docs/gpio-board-adaptation.zh-CN.md b/docs/gpio-board-adaptation.zh-CN.md new file mode 100644 index 0000000..ed46000 --- /dev/null +++ b/docs/gpio-board-adaptation.zh-CN.md @@ -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 负载下采样、充电/唤醒、步进方向及显示并行稳定性。 diff --git a/docs/gpio-map.md b/docs/gpio-map.md index a33c2d9..c74afb0 100644 --- a/docs/gpio-map.md +++ b/docs/gpio-map.md @@ -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 | diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index f49cfa7..e760e9a 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -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 diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 7909e50..66c3b1b 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -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 diff --git a/tools/test_battery_adc_init.py b/tools/test_battery_adc_init.py new file mode 100644 index 0000000..368318f --- /dev/null +++ b/tools/test_battery_adc_init.py @@ -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 +#include +#include +#include +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()