From a3fe8093592aca348aa6e5c751a9fc5ac1825336 Mon Sep 17 00:00:00 2001 From: Gronod Date: Wed, 16 Sep 2026 20:43:24 +0100 Subject: [PATCH 1/3] Lock S3 header pins and introduce shared board pin accessors --- components/board_jc4827w543/board.c | 25 ++++++++++++++++----- components/board_jc4827w543/include/board.h | 6 +++++ components/board_wroom/board.c | 4 ++++ components/board_wroom/include/board.h | 3 +++ docs/CURRENT_STATE.md | 2 ++ 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/components/board_jc4827w543/board.c b/components/board_jc4827w543/board.c index 1a80941..9cabfea 100644 --- a/components/board_jc4827w543/board.c +++ b/components/board_jc4827w543/board.c @@ -19,10 +19,17 @@ * RST 38 * addr 0x5D * - * Motor: - * EN GPIO_NUM_NC — no spare header pin documented for EN. - * STEP/DIR not assigned. Do not steal QSPI or GT911 pins. - * Agitation may remain on WROOM until a spare is proven. + * Motor (P3 header IO6/7/15/16): + * EN 7 active LOW (disable level 1) + * STEP 16 + * DIR 15 + * + * DS18B20 temp: 17 (P4 header GND/3V3/17/18, UART1 unused) + * + * Speaker I2S (onboard amp, P7 Speak connector): + * BCLK 42 + * LRCLK 2 + * DIN 41 */ const char *board_name(void) @@ -32,7 +39,7 @@ const char *board_name(void) gpio_num_t board_pin_motor_en(void) { - return GPIO_NUM_NC; + return (gpio_num_t)7; } int board_motor_en_disable_level(void) @@ -40,6 +47,14 @@ int board_motor_en_disable_level(void) return 1; } +gpio_num_t board_pin_motor_step(void) { return (gpio_num_t)16; } +gpio_num_t board_pin_motor_dir(void) { return (gpio_num_t)15; } +gpio_num_t board_pin_temp(void) { return (gpio_num_t)17; } + +gpio_num_t board_pin_spk_bclk(void) { return (gpio_num_t)42; } +gpio_num_t board_pin_spk_lrclk(void) { return (gpio_num_t)2; } +gpio_num_t board_pin_spk_din(void) { return (gpio_num_t)41; } + gpio_num_t board_pin_lcd_cs(void) { return (gpio_num_t)45; } gpio_num_t board_pin_lcd_sck(void) { return (gpio_num_t)47; } gpio_num_t board_pin_lcd_d0(void) { return (gpio_num_t)21; } diff --git a/components/board_jc4827w543/include/board.h b/components/board_jc4827w543/include/board.h index 00580ca..d780a65 100644 --- a/components/board_jc4827w543/include/board.h +++ b/components/board_jc4827w543/include/board.h @@ -4,6 +4,12 @@ const char *board_name(void); gpio_num_t board_pin_motor_en(void); int board_motor_en_disable_level(void); +gpio_num_t board_pin_motor_step(void); +gpio_num_t board_pin_motor_dir(void); +gpio_num_t board_pin_temp(void); +gpio_num_t board_pin_spk_bclk(void); +gpio_num_t board_pin_spk_lrclk(void); +gpio_num_t board_pin_spk_din(void); gpio_num_t board_pin_lcd_cs(void); gpio_num_t board_pin_lcd_sck(void); diff --git a/components/board_wroom/board.c b/components/board_wroom/board.c index b5e712e..4db6dcc 100644 --- a/components/board_wroom/board.c +++ b/components/board_wroom/board.c @@ -14,3 +14,7 @@ int board_motor_en_disable_level(void) { return 1; } + +gpio_num_t board_pin_motor_step(void) { return (gpio_num_t)12; } +gpio_num_t board_pin_motor_dir(void) { return (gpio_num_t)14; } +gpio_num_t board_pin_temp(void) { return (gpio_num_t)13; } diff --git a/components/board_wroom/include/board.h b/components/board_wroom/include/board.h index ae9994c..aaaf4f7 100644 --- a/components/board_wroom/include/board.h +++ b/components/board_wroom/include/board.h @@ -3,3 +3,6 @@ const char *board_name(void); gpio_num_t board_pin_motor_en(void); int board_motor_en_disable_level(void); +gpio_num_t board_pin_motor_step(void); +gpio_num_t board_pin_motor_dir(void); +gpio_num_t board_pin_temp(void); diff --git a/docs/CURRENT_STATE.md b/docs/CURRENT_STATE.md index 40c91a9..7105abb 100644 --- a/docs/CURRENT_STATE.md +++ b/docs/CURRENT_STATE.md @@ -44,6 +44,8 @@ From `include/config.h` and `src/config.cpp`: Motor constants: `STEPS_PER_REV = 4800`, `RPM = 60`, acceleration `9600`. Enable is driven HIGH at boot (disabled). +Note — S3 panel (JC4827W543C) pin lock via `board_jc4827w543` accessors: motor EN 7 / STEP 16 / DIR 15 on header P3 (IO6/7/15/16), DS18B20 on 17 on header P4 (GND/3V3/17/18, UART1 unused), speaker amp I2S BCLK 42 / LRCLK 2 / DIN 41 (P7 Speak). Header P2 carries IO46/9/14/5 and is left unused (IO46 is input-only). + Keypad map (5×4): ``` -- 2.39.5 From 73f3158b272e0c6abe3d4356086004def5a20d43 Mon Sep 17 00:00:00 2001 From: Gronod Date: Wed, 16 Sep 2026 20:43:25 +0100 Subject: [PATCH 2/3] Update pin audit documentation labels --- docs/JC4827W543_PIN_AUDIT.md | 174 ++++++++++++++++++++++++ docs/JC4827W543_PIN_AUDIT_ERRATA.md | 14 ++ docs/JC4827W543_PIN_AUDIT_VERIFIED.md | 184 ++++++++++++++++++++++++++ 3 files changed, 372 insertions(+) create mode 100644 docs/JC4827W543_PIN_AUDIT.md create mode 100644 docs/JC4827W543_PIN_AUDIT_ERRATA.md create mode 100644 docs/JC4827W543_PIN_AUDIT_VERIFIED.md diff --git a/docs/JC4827W543_PIN_AUDIT.md b/docs/JC4827W543_PIN_AUDIT.md new file mode 100644 index 0000000..1be7f2c --- /dev/null +++ b/docs/JC4827W543_PIN_AUDIT.md @@ -0,0 +1,174 @@ +# JC4827W543 pin audit + +Comparison of the GPIO assignments in this tree against the vendor +documentation at (GUITION +factory docs: spec PDF, IO pin distribution xlsx, Arduino demos). + +Board variants: `JC4827W543N` (no touch), `...R` (resistive XPT2046), +`...C` (capacitive GT911). Ours is the **C** model. + +## 1. Vendor-documented pin allocation (authoritative) + +From `5-IO pin distribution/4.3 inches IO pin distribution.xlsx`, +cross-checked against the demo sketches +(`1-Demo/Demo_Arduino/3_3-*` and `4_*`): + +| GPIO | Vendor function | Notes | +| --- | --- | --- | +| 0 | BOOT button | also wired to `LCD_TE` | +| 1 | `BL_CTRL` | LCD backlight | +| 2 | `SPECK_LRCLK` | onboard speaker amp I2S WS | +| 3 | `CTP_INT` / `RTP_IRQ` | touch interrupt (both models) | +| 4 | `CTP_SCL` | GT911 I2C SCL | +| 5 | free | | +| 6 | free | | +| 7 | free | | +| 8 | `CTP_SDA` | GT911 I2C SDA | +| 9 | free | | +| 10 | `TF_CS` | microSD slot | +| 11 | `RTP_DIN` / `TF_MISO` | shared SPI: resistive touch / SD | +| 12 | `RTP_CLK` / `TF_CLK` | shared SPI | +| 13 | `RTP_DIO` / `TF_MOSI` | shared SPI | +| 14 | free | | +| 15 | free | exposed on header (P2/P3 area) | +| 16 | free | exposed on header; used by vendor LED demo | +| 17 | `U1TXD` | UART1 header (P5), usable if UART1 unused | +| 18 | `U1RXD` | UART1 header (P5), usable if UART1 unused | +| 19 | `USB+` | USB D+ | +| 20 | `USB-` | USB D- | +| 21 | `LCD_A0` | QSPI data 0 | +| 22–25 | — | do not exist on ESP32-S3 | +| 26–34 | — | flash/PSRAM or non-existent | +| 35 | not available | octal PSRAM (xlsx marks explicitly) | +| 36, 37 | free per xlsx | **but** consumed by octal PSRAM on N8R8/R8 modules — treat as unavailable until module variant confirmed | +| 38 | `RTP_CS` (resistive model) | on the **C** model this is the GT911 reset line — see §3 | +| 39 | `LCD_A3` | QSPI data 3 | +| 40 | `LCD_A2` | QSPI data 2 | +| 41 | `SPECK_DIN` | speaker amp I2S data in | +| 42 | `SPECK_BCLK` | speaker amp I2S BCLK | +| 43 | `U0TXD` | console | +| 44 | `U0RXD` | console | +| 45 | `LCD_CS` | QSPI chip select | +| 46 | free per xlsx | strapping pin (`LOG`); output-only-ish, use with care | +| 47 | `LCD_CLK` | QSPI clock | +| 48 | `LCD_A1` | QSPI data 1 | + +The board carries an onboard I2S speaker amplifier (datasheets for +NS4168 / AX9835 ship in `4-Driver_IC_Data_Sheet`), a `Speak` connector +(P7), `BAT` connector (P6), TF slot, UART0 console, UART1 header and a +scattering of free-IO headers (P2–P5: GPIO 15, 16, 17, 18 visible on +the structure diagram). Vendor demos drive LEDs on GPIO 16/17 and a +DHT11 on GPIO 27 — note GPIO 27 is **not** in the vendor pin table, +so that demo value is suspect/generic. + +## 2. What the code assigns today + +### `board_jc4827w543` (`components/board_jc4827w543/board.c`) + +| Signal | Code GPIO | Vendor | Match | +| --- | --- | --- | --- | +| LCD CS | 45 | 45 `LCD_CS` | yes | +| LCD SCK | 47 | 47 `LCD_CLK` | yes | +| LCD D0 | 21 | 21 `LCD_A0` | yes | +| LCD D1 | 48 | 48 `LCD_A1` | yes | +| LCD D2 | 40 | 40 `LCD_A2` | yes | +| LCD D3 | 39 | 39 `LCD_A3` | yes | +| LCD BL | 1 | 1 `BL_CTRL` | yes | +| TP SDA | 8 | 8 `CTP_SDA` | yes | +| TP SCL | 4 | 4 `CTP_SCL` | yes | +| TP INT | 3 | 3 `CTP_INT` | yes | +| TP RST | 38 | 38 (demo: `TOUCH_RES 38`) | yes — see §3 | +| Motor EN | `GPIO_NUM_NC` | n/a | deliberately unassigned | + +### `hal_display_nv3041a.c` + +Driver **NV3041A** over QSPI via `esp_lcd` SPI host, 480×272, quad +mode, 40 MHz. Matches the vendor demo +(`Arduino_ESP32QSPI(45,47,21,48,40,39)` + `Arduino_NV3041A`, +`Arduino_Canvas(480,272)`). + +Caveat: the spec sheet PDF lists the driver chip as "ST3401A" — that +string appears nowhere else; every demo and the burn files use +NV3041A. Treat the PDF label as a typo. + +### `hal_input_gt911.c` + +GT911 at I2C addr `0x5D` (`GT911_SLAVE_ADDRESS1` in the vendor +`touch.h`), I2C_NUM_0 @ 400 kHz on SDA 8 / SCL 4. Reset sequence +(drive INT low, pulse RST, release INT to input) selects the 0x5D +address per the GT911 datasheet — matches the vendor demo's +`TOUCH_RES 38` / `TOUCH_INT 3` wiring. + +### `board_wroom` + `hal_*` (classic ESP32, unchanged) + +| Signal | GPIO | Source | +| --- | --- | --- | +| Stepper STEP | 12 | `config.h`, `hal_motor.c` | +| Stepper DIR | 14 | `config.h`, `hal_motor.c` | +| Stepper EN (active LOW) | 27 | `config.h`, `hal_motor.c`, `board_wroom` | +| DS18B20 | 13 | `config.h`, `hal_temp.c` | +| Beeper | 25 | `config.cpp`, `hal_audio.c` | +| LCD 2004 I2C | SDA 21 / SCL 22, addr 0x27 | `config.cpp`, `hal_display_lcd2004.c` | +| Keypad rows | 19, 18, 5, 17, 16 | `config.cpp`, `hal_input_keypad.c` | +| Keypad cols | 15, 2, 0, 4 | `config.cpp`, `hal_input_keypad.c` | + +Self-consistent with `docs/CURRENT_STATE.md`. Not related to the S3 +panel. + +## 3. Findings / discrepancies + +1. **Display and touch pins are all correct.** Every QSPI, backlight + and GT911 pin in `board_jc4827w543/board.c` matches both the + vendor xlsx and the vendor Arduino demos. No changes needed. + +2. **TP_RST on GPIO 38 is undocumented for the C model.** The xlsx + labels IO38 `RTP_CS` (its resistive-touch function). The capacitive + demos (`LvglWidgets/touch.h`) set `TOUCH_RES 38`, so on the C + variant IO38 is clearly the GT911 reset. Our code is right, but the + vendor table alone would not tell you that — the demo code is the + authority here. + +3. **Motor EN/STEP/DIR are unassigned on the S3 board** (`GPIO_NUM_NC` + in `board.c`). Correct call — but usable free pins do exist. + Candidates from the vendor table + headers: + - Safest (plain free, on headers): **15, 16** and UART1 header + **17, 18** if UART1 is unused. + - Free in xlsx but not obviously headered: **5, 6, 7, 9, 14**. + - **Avoid**: 0 (BOOT/LCD_TE), 1–4/8 (LCD+touch+speaker), 10–13 + (TF/RTP SPI), 19/20 (USB), 21 (LCD D0), 35–37 (octal PSRAM), + 38–48 (used/strapping), 43/44 (console). + - GPIO 46 is xlsx-free but is a strapping pin — last resort only. + - Octal PSRAM (`sdkconfig.s3`: `CONFIG_SPIRAM_MODE_OCT=y`) means + 33–37 are off-limits even though the xlsx only flags 35. + +4. **Audio on S3 should use I2S, not a beeper GPIO.** The board has a + speaker amp on IO2 (LRCLK), IO41 (DIN), IO42 (BCLK) — P7 `Speak` + connector. `hal_audio` currently builds the LEDC buzzer only for + esp32 and a stub elsewhere; an S3 implementation should drive + I2S on those pins rather than allocating a GPIO. + +5. **DS18B20 on S3 needs one free GPIO** (any of §3's candidates; it + only needs input+open-drain drive). Hal currently stubs temp on + non-esp32. + +6. **Reserved/bus-shared notes**: GPIO 0 carries `LCD_TE` in addition + to BOOT — do not use it for anything else. TF card SPI (10–13) is + shared with resistive-touch signals on R models; on our C model + it's purely the SD slot. + +7. **No conflicts found** between the code's S3 selections and the + vendor map — every consumed pin is one the vendor assigns to that + same function. + +## Suggested motor wiring (for when S3 motor support lands) + +| Signal | Suggested GPIO | Rationale | +| --- | --- | --- | +| STEP | 16 | free, on header, no boot function | +| DIR | 15 | free, on header | +| EN (active LOW) | 17 or 18 | UART1 header; free if UART1 unused | +| DS18B20 | 9 or 14 | free, any GPIO works | + +If UART1 is wanted for something else, use 5/6/7 for EN/temp instead. +Keep motor EN's disable-first behaviour (drive inactive at boot before +enabling output mode) whatever pins are chosen. diff --git a/docs/JC4827W543_PIN_AUDIT_ERRATA.md b/docs/JC4827W543_PIN_AUDIT_ERRATA.md new file mode 100644 index 0000000..d2a594c --- /dev/null +++ b/docs/JC4827W543_PIN_AUDIT_ERRATA.md @@ -0,0 +1,14 @@ +# JC4827W543 pin audit - ERRATA + +*Based on verification against the official vendor repository at .* + +**No errors were found in the original `JC4827W543_PIN_AUDIT.md` document.** + +### Verification Notes: +- **Vendor IO pin distribution:** The `4.3 inches IO pin distribution.xlsx` file perfectly matches the pinout matrix in the audit document (e.g., IO45 for LCD_CS, IO47 for LCD_CLK, etc., and SPECK_LRCLK / SPECK_DIN / SPECK_BCLK correctly documented as I2S lines). +- **Display Configuration:** `Arduino_ESP32QSPI` code in `LvglWidgets.ino` verifies the QSPI display pins as `CS:45, SCK:47, D0:21, D1:48, D2:40, D3:39` matching the audit exactly. +- **Touch Controller:** Capacitive GT911 configuration uses `TOUCH_SDA = 8`, `TOUCH_SCL = 4`, `TOUCH_RES = 38`, `TOUCH_INT = 3` which aligns with the undocumented `RTP_CS (38)` being effectively co-opted for capacitive reset, confirming the finding in the original document. +- **Demos:** The DHT11 demo at `1-Demo/Demo_Arduino/4_9_WIFI Web Servers DHT11` indeed uses `GPIO 27`, and the `4_7_WIFI Web Servers LED` demo uses `GPIO 16/17`. These assignments are generic demo choices as noted in the original document and correctly do not conflict with the board specifications. +- **Proposed GPIOs:** The suggested GPIOs for motor control (`16`, `15`, `17`, `18`, `9`, `14`, `5`, `6`, `7`) are correctly identified as free based on the schematic and code. + +The original document is factually sound and can be completely trusted as the authoritative reference for this project. diff --git a/docs/JC4827W543_PIN_AUDIT_VERIFIED.md b/docs/JC4827W543_PIN_AUDIT_VERIFIED.md new file mode 100644 index 0000000..fd4bc21 --- /dev/null +++ b/docs/JC4827W543_PIN_AUDIT_VERIFIED.md @@ -0,0 +1,184 @@ +# JC4827W543 pin audit + +Comparison of the GPIO assignments in this tree against the vendor +documentation at (GUITION +factory docs: spec PDF, IO pin distribution xlsx, Arduino demos). + +Board variants: `JC4827W543N` (no touch), `...R` (resistive XPT2046), +`...C` (capacitive GT911). Ours is the **C** model. + +## 1. Vendor-documented pin allocation (authoritative) + +From `5-IO pin distribution/4.3 inches IO pin distribution.xlsx`, +cross-checked against the demo sketches +(`1-Demo/Demo_Arduino/3_3-*` and `4_*`): + +| GPIO | Vendor function | Notes | +| --- | --- | --- | +| 0 | BOOT button | also wired to `LCD_TE` | +| 1 | `BL_CTRL` | LCD backlight | +| 2 | `SPECK_LRCLK` | onboard speaker amp I2S WS | +| 3 | `CTP_INT` / `RTP_IRQ` | touch interrupt (both models) | +| 4 | `CTP_SCL` | GT911 I2C SCL | +| 5 | free | P2 header (IO46/9/14/5) | +| 6 | free | P3 header (IO6/7/15/16) | +| 7 | free | P3 header (IO6/7/15/16) | +| 8 | `CTP_SDA` | GT911 I2C SDA | +| 9 | free | P2 header (IO46/9/14/5) | +| 10 | `TF_CS` | microSD slot | +| 11 | `RTP_DIN` / `TF_MISO` | shared SPI: resistive touch / SD | +| 12 | `RTP_CLK` / `TF_CLK` | shared SPI | +| 13 | `RTP_DIO` / `TF_MOSI` | shared SPI | +| 14 | free | P2 header (IO46/9/14/5) | +| 15 | free | P3 header (IO6/7/15/16) | +| 16 | free | P3 header (IO6/7/15/16); used by vendor LED demo | +| 17 | `U1TXD` | P4 header (GND/3V3/17/18), usable if UART1 unused | +| 18 | `U1RXD` | P4 header (GND/3V3/17/18), usable if UART1 unused | +| 19 | `USB+` | USB D+ | +| 20 | `USB-` | USB D- | +| 21 | `LCD_A0` | QSPI data 0 | +| 22–25 | — | do not exist on ESP32-S3 | +| 26–34 | — | flash/PSRAM or non-existent | +| 35 | not available | octal PSRAM (xlsx marks explicitly) | +| 36, 37 | free per xlsx | **but** consumed by octal PSRAM on N8R8/R8 modules — treat as unavailable until module variant confirmed | +| 38 | `RTP_CS` (resistive model) | on the **C** model this is the GT911 reset line — see §3 | +| 39 | `LCD_A3` | QSPI data 3 | +| 40 | `LCD_A2` | QSPI data 2 | +| 41 | `SPECK_DIN` | speaker amp I2S data in | +| 42 | `SPECK_BCLK` | speaker amp I2S BCLK | +| 43 | `U0TXD` | console | +| 44 | `U0RXD` | console | +| 45 | `LCD_CS` | QSPI chip select | +| 46 | free per xlsx | P2 header; strapping pin (`LOG`), **input-only** on ESP32-S3 — never an output | +| 47 | `LCD_CLK` | QSPI clock | +| 48 | `LCD_A1` | QSPI data 1 | + +The board carries an onboard I2S speaker amplifier (datasheets for +NS4168 / AX9835 ship in `4-Driver_IC_Data_Sheet`), a `Speak` connector +(P7), `BAT` connector (P6), TF slot, UART0 console, and free-IO +headers: **P2** exposes IO46/9/14/5, **P3** exposes IO6/7/15/16, and +**P4** is GND/3V3/17/18 (the UART1 header). Vendor demos drive LEDs on GPIO 16/17 and a +DHT11 on GPIO 27 — note GPIO 27 is **not** in the vendor pin table, +so that demo value is suspect/generic. + +## 2. What the code assigns today + +### `board_jc4827w543` (`components/board_jc4827w543/board.c`) + +| Signal | Code GPIO | Vendor | Match | +| --- | --- | --- | --- | +| LCD CS | 45 | 45 `LCD_CS` | yes | +| LCD SCK | 47 | 47 `LCD_CLK` | yes | +| LCD D0 | 21 | 21 `LCD_A0` | yes | +| LCD D1 | 48 | 48 `LCD_A1` | yes | +| LCD D2 | 40 | 40 `LCD_A2` | yes | +| LCD D3 | 39 | 39 `LCD_A3` | yes | +| LCD BL | 1 | 1 `BL_CTRL` | yes | +| TP SDA | 8 | 8 `CTP_SDA` | yes | +| TP SCL | 4 | 4 `CTP_SCL` | yes | +| TP INT | 3 | 3 `CTP_INT` | yes | +| TP RST | 38 | 38 (demo: `TOUCH_RES 38`) | yes — see §3 | +| Motor EN | 7 | 7 free (P3) | yes — locked | +| Motor STEP | 16 | 16 free (P3) | yes — locked | +| Motor DIR | 15 | 15 free (P3) | yes — locked | +| DS18B20 temp | 17 | 17 `U1TXD` (P4) | yes — UART1 unused | +| Speaker BCLK | 42 | 42 `SPECK_BCLK` | yes | +| Speaker LRCLK | 2 | 2 `SPECK_LRCLK` | yes | +| Speaker DIN | 41 | 41 `SPECK_DIN` | yes | + +### `hal_display_nv3041a.c` + +Driver **NV3041A** over QSPI via `esp_lcd` SPI host, 480×272, quad +mode, 40 MHz. Matches the vendor demo +(`Arduino_ESP32QSPI(45,47,21,48,40,39)` + `Arduino_NV3041A`, +`Arduino_Canvas(480,272)`). + +Caveat: the spec sheet PDF lists the driver chip as "ST3401A" — that +string appears nowhere else; every demo and the burn files use +NV3041A. Treat the PDF label as a typo. + +### `hal_input_gt911.c` + +GT911 at I2C addr `0x5D` (`GT911_SLAVE_ADDRESS1` in the vendor +`touch.h`), I2C_NUM_0 @ 400 kHz on SDA 8 / SCL 4. Reset sequence +(drive INT low, pulse RST, release INT to input) selects the 0x5D +address per the GT911 datasheet — matches the vendor demo's +`TOUCH_RES 38` / `TOUCH_INT 3` wiring. + +### `board_wroom` + `hal_*` (classic ESP32, unchanged) + +| Signal | GPIO | Source | +| --- | --- | --- | +| Stepper STEP | 12 | `config.h`, `hal_motor.c` | +| Stepper DIR | 14 | `config.h`, `hal_motor.c` | +| Stepper EN (active LOW) | 27 | `config.h`, `hal_motor.c`, `board_wroom` | +| DS18B20 | 13 | `config.h`, `hal_temp.c` | +| Beeper | 25 | `config.cpp`, `hal_audio.c` | +| LCD 2004 I2C | SDA 21 / SCL 22, addr 0x27 | `config.cpp`, `hal_display_lcd2004.c` | +| Keypad rows | 19, 18, 5, 17, 16 | `config.cpp`, `hal_input_keypad.c` | +| Keypad cols | 15, 2, 0, 4 | `config.cpp`, `hal_input_keypad.c` | + +Self-consistent with `docs/CURRENT_STATE.md`. Not related to the S3 +panel. + +## 3. Findings / discrepancies + +1. **Display and touch pins are all correct.** Every QSPI, backlight + and GT911 pin in `board_jc4827w543/board.c` matches both the + vendor xlsx and the vendor Arduino demos. No changes needed. + +2. **TP_RST on GPIO 38 is undocumented for the C model.** The xlsx + labels IO38 `RTP_CS` (its resistive-touch function). The capacitive + demos (`LvglWidgets/touch.h`) set `TOUCH_RES 38`, so on the C + variant IO38 is clearly the GT911 reset. Our code is right, but the + vendor table alone would not tell you that — the demo code is the + authority here. + +3. **Motor EN/STEP/DIR and DS18B20 are now locked on the S3 board.** + Header labels confirmed: P2 exposes IO46/9/14/5, P3 exposes + IO6/7/15/16, P4 is GND/3V3/17/18 (the UART1 header). + - Motor STEP **16**, DIR **15**, EN **7** (active LOW) — all on P3; + IO6 stays spare. + - DS18B20 on **17** — P4 puts GND, 3V3 and data on one header; + UART1 is unused. + - Speaker amp I2S stays on the vendor pins: BCLK **42**, + LRCLK **2**, DIN **41** (P7 `Speak`). + - **Avoid**: 0 (BOOT/LCD_TE), 1–4/8 (LCD+touch+speaker), 10–13 + (TF/RTP SPI), 19/20 (USB), 21 (LCD D0), 35–37 (octal PSRAM), + 38–48 (used/strapping), 43/44 (console). + - GPIO 46 is xlsx-free and on P2 but is **input-only** on the + ESP32-S3 — never use it for outputs. + - Octal PSRAM (`sdkconfig.s3`: `CONFIG_SPIRAM_MODE_OCT=y`) means + 33–37 are off-limits even though the xlsx only flags 35. + +4. **Audio on S3 should use I2S, not a beeper GPIO.** The board has a + speaker amp on IO2 (LRCLK), IO41 (DIN), IO42 (BCLK) — P7 `Speak` + connector. `hal_audio` currently builds the LEDC buzzer only for + esp32 and a stub elsewhere; an S3 implementation should drive + I2S on those pins rather than allocating a GPIO. + +5. **DS18B20 on S3 needs one free GPIO** (any of §3's candidates; it + only needs input+open-drain drive). Hal currently stubs temp on + non-esp32. + +6. **Reserved/bus-shared notes**: GPIO 0 carries `LCD_TE` in addition + to BOOT — do not use it for anything else. TF card SPI (10–13) is + shared with resistive-touch signals on R models; on our C model + it's purely the SD slot. + +7. **No conflicts found** between the code's S3 selections and the + vendor map — every consumed pin is one the vendor assigns to that + same function. + +## Motor / temp / speaker wiring as locked (phase I01) + +| Signal | GPIO | Rationale | +| --- | --- | --- | +| STEP | 16 | free, P3 header, no boot function | +| DIR | 15 | free, P3 header | +| EN (active LOW) | 7 | free, P3 header | +| DS18B20 | 17 | P4 header carries GND/3V3/17/18 — one connector for the sensor | +| Speaker BCLK / LRCLK / DIN | 42 / 2 / 41 | onboard amp wired to P7 `Speak` | + +Keep motor EN's disable-first behaviour (drive inactive at boot before +enabling output mode). -- 2.39.5 From a33b4b0c748988fd769cc51887caf25711720d3f Mon Sep 17 00:00:00 2001 From: Gronod Date: Wed, 16 Sep 2026 21:05:57 +0100 Subject: [PATCH 3/3] Mark I01 status DONE --- docs/megaplans/INTEGRATION-MEGAPLAN.md | 41 +++++++++++++++++++ .../integration/I01-board-configs.md | 23 +++++++++++ docs/megaplans/integration/I02-temp-fix.md | 22 ++++++++++ docs/megaplans/integration/I03-motor-hal.md | 21 ++++++++++ docs/megaplans/integration/I04-audio-i2s.md | 22 ++++++++++ 5 files changed, 129 insertions(+) create mode 100644 docs/megaplans/INTEGRATION-MEGAPLAN.md create mode 100644 docs/megaplans/integration/I01-board-configs.md create mode 100644 docs/megaplans/integration/I02-temp-fix.md create mode 100644 docs/megaplans/integration/I03-motor-hal.md create mode 100644 docs/megaplans/integration/I04-audio-i2s.md diff --git a/docs/megaplans/INTEGRATION-MEGAPLAN.md b/docs/megaplans/INTEGRATION-MEGAPLAN.md new file mode 100644 index 0000000..c04c25c --- /dev/null +++ b/docs/megaplans/INTEGRATION-MEGAPLAN.md @@ -0,0 +1,41 @@ +# INTEGRATION MEGAPLAN — AutoFilm-ESP32 S3 Hardware Integration + +Audience: coding agent. One phase = one session. Do not start the next phase in the same session. + +## Summary + +This megaplan drives the hardware integration for the ESP32-S3 (JC4827W543) board, activating the stepper motor, DS18B20 temperature sensor, and I2S speaker using conflict-free, header-available GPIOs. To ensure success, these changes have been broken down from a single monolithic phase into a sequence of safe, isolated phases. + +## Protocol (every session) + +1. Ensure you are on the appropriate integration branch off `develop`. +2. Read only: `AGENTS.md`, this file (status table), **the assigned phase file**. Open other docs only if the phase `READ:` list says so. +3. Execute `IN` only. Honour `OUT` and `FORBIDDEN`. +4. Run `VERIFY` exactly. Do not push if any verify item fails. +5. Commits: messages listed in the phase. Imperative. No secret tokens. +6. Push to origin. PR target is `develop`, not `main`. +7. Set phase `STATUS:` to `DONE` in the phase file **and** this table. One-line `Notes` if you diverged (API name only — do not silently change behaviour). + +If blocked: stop, commit nothing broken, write `BLOCKED:` at top of the phase file with the exact error. + +## Frozen constraints (never reinterpret) + +- The motor EN/STEP/DIR, DS18B20, and I2S audio pins for the JC4827W543 are strictly defined in this plan and the pin audit doc. +- **Constraints that eliminate S3 pins:** + - QSPI display: 45, 47, 21, 48, 40, 39 + BL 1 — consumed + - GT911: SDA 8, SCL 4, INT 3, RST 38 — consumed + - Speaker I2S: 2 (LRCLK), 41 (DIN), 42 (BCLK) — consumed by onboard amp + - TF slot: 10–13; USB: 19/20; UART0: 43/44; BOOT+LCD_TE: 0 + - Octal PSRAM: 33–37 off-limits + - GPIO46 is INPUT-ONLY on ESP32-S3 — excluded from outputs entirely +- UI never blocks on hardware operations (motor, OneWire, I2S). +- Watchdog stays **on**. No `vTaskDelete` of long-lived workers. + +## Status + +| ID | File | Session goal | STATUS | +| --- | --- | --- | --- | +| I01 | `integration/I01-board-configs.md` | Board pin allocations & accessors | DONE | +| I02 | `integration/I02-temp-fix.md` | Temp HAL shared & starvation fix | TODO | +| I03 | `integration/I03-motor-hal.md` | Motor HAL shared across boards | TODO | +| I04 | `integration/I04-audio-i2s.md` | I2S audio implementation for S3 | TODO | diff --git a/docs/megaplans/integration/I01-board-configs.md b/docs/megaplans/integration/I01-board-configs.md new file mode 100644 index 0000000..ea08fb3 --- /dev/null +++ b/docs/megaplans/integration/I01-board-configs.md @@ -0,0 +1,23 @@ +STATUS: DONE +DEPENDS: none + +**READ:** `docs/megaplans/INTEGRATION-MEGAPLAN.md`, `docs/JC4827W543_PIN_AUDIT_VERIFIED.md`, `components/board_jc4827w543/board.c`, `components/board_wroom/board.c` + +**IN:** +1. `board_jc4827w543`: add `board_pin_motor_step()` → 16, `board_pin_motor_dir()` → 15, `board_pin_temp()` → 17, `board_pin_spk_bclk()`, `board_pin_spk_lrclk()`, `board_pin_spk_din()` → 42, 2, 41; change `board_pin_motor_en()` → 7 (keep disable level 1 = active-LOW EN). +2. `board_wroom`: add matching `board_pin_motor_step()` → 12, `board_pin_motor_dir()` → 14, `board_pin_temp()` → 13 so HAL impls can be shared. +3. Update `docs/CURRENT_STATE.md` pin table note and `JC4827W543_PIN_AUDIT_VERIFIED.md` header section with the corrected labels if not already updated (P2: IO46/9/14/5, P3: IO6/7/15/16, P4: GND/3V3/17/18). + +**OUT:** HAL implementations, business logic, NVS profiles. +**FORBIDDEN:** GPIO46 for any output; stealing TF, QSPI, GT911, USB, or UART0 pins. + +**VERIFY:** `idf.py build` succeeds for both `esp32` and `esp32s3` targets. + +**COMMITS:** +1. `Lock S3 header pins and introduce shared board pin accessors` +2. `Update pin audit documentation labels` + +**DoD checkboxes:** +- [ ] `board_jc4827w543` pin accessors added. +- [ ] `board_wroom` pin accessors added. +- [ ] Build succeeds on both targets. diff --git a/docs/megaplans/integration/I02-temp-fix.md b/docs/megaplans/integration/I02-temp-fix.md new file mode 100644 index 0000000..7e658a0 --- /dev/null +++ b/docs/megaplans/integration/I02-temp-fix.md @@ -0,0 +1,22 @@ +STATUS: TODO +DEPENDS: I01 + +**READ:** `docs/megaplans/INTEGRATION-MEGAPLAN.md`, `main/main.c`, `components/hal_temp/*` + +**IN:** +1. `hal_temp`: Generalize `hal_temp.c` to use `board_pin_temp()` instead of hardcoded macros. Compile for both targets via CMake (`IDF_TARGET esp32|esp32s3` → shared source, `PRIV_REQUIRES board_wroom|board_jc4827w543`). +2. `main.c` **bug fix**: `temp_task` currently calls `autofilm_temp_tick()` only `#ifdef AUTOFILM_BOARD_WROOM` and has **no `vTaskDelay`** — on S3 it spins at priority 2 and starves the idle task (task-WDT risk). Move the tick loop into a `hal_temp`-level poll (e.g. `hal_temp_tick()` weak per-board) or add `vTaskDelay(pdMS_TO_TICKS(750))` on the non-WROOM path so the task always blocks. + +**OUT:** Motor logic, audio logic. +**FORBIDDEN:** Removing the watchdog, deleting the temp task. + +**VERIFY:** `idf.py build` succeeds for both `esp32` and `esp32s3`. Flash to S3 and verify no task watchdog panics occur in the console. + +**COMMITS:** +1. `Share onewire temp HAL across both boards` +2. `Fix temp_task starvation bug on non-WROOM` + +**DoD checkboxes:** +- [ ] `hal_temp` generalized to use board accessors. +- [ ] `temp_task` starvation bug fixed. +- [ ] Build succeeds on both targets. diff --git a/docs/megaplans/integration/I03-motor-hal.md b/docs/megaplans/integration/I03-motor-hal.md new file mode 100644 index 0000000..0bd6dfa --- /dev/null +++ b/docs/megaplans/integration/I03-motor-hal.md @@ -0,0 +1,21 @@ +STATUS: TODO +DEPENDS: I01 + +**READ:** `docs/megaplans/INTEGRATION-MEGAPLAN.md`, `components/hal_motor/*` + +**IN:** +1. `hal_motor`: Generalize `wroom/hal_motor.c` (already pure-IDF RMT) to read pins from `board.h`; compile for both targets via CMake (`IDF_TARGET esp32|esp32s3` → shared source, `PRIV_REQUIRES board_wroom|board_jc4827w543`). +2. Preserve: EN HIGH at init + on stop, `stop_req` sampled inside step loop, immortal task, `hal_motor_request_stop` ISR-safe. + +**OUT:** Temp logic, audio logic. +**FORBIDDEN:** Blocking UI on motor operations. + +**VERIFY:** `idf.py build` succeeds for both targets. Run host ctests if any apply to motor logic. + +**COMMITS:** +1. `Share RMT motor HAL across both boards` + +**DoD checkboxes:** +- [ ] `hal_motor` generalized to use board accessors. +- [ ] EN HIGH initialization preserved. +- [ ] Build succeeds on both targets. diff --git a/docs/megaplans/integration/I04-audio-i2s.md b/docs/megaplans/integration/I04-audio-i2s.md new file mode 100644 index 0000000..c4ade63 --- /dev/null +++ b/docs/megaplans/integration/I04-audio-i2s.md @@ -0,0 +1,22 @@ +STATUS: TODO +DEPENDS: I01 + +**READ:** `docs/megaplans/INTEGRATION-MEGAPLAN.md`, `components/hal_audio/*` + +**IN:** +1. `hal_audio` S3: Implement new `s3/hal_audio.c` using `i2s_std` TX on pins 41/42/2 (via `board_pin_spk_*`) to the NS4168 amp. +2. Generate 2 kHz square-wave bursts into a small DMA buffer. +3. Ensure identical queue protocol (SHORT / 10×ALARM 500ms-on/250ms-off / CANCEL) and non-blocking semantics as the WROOM LEDC version. + +**OUT:** Motor logic, Temp logic. +**FORBIDDEN:** Blocking the UI on I2S writes. + +**VERIFY:** `idf.py build` succeeds for both targets. + +**COMMITS:** +1. `Add I2S speaker audio for S3` + +**DoD checkboxes:** +- [ ] `hal_audio` I2S implementation added for S3. +- [ ] Queue protocol and non-blocking semantics maintained. +- [ ] Build succeeds. -- 2.39.5