Lock P00–P08 with in/out scope, frozen APIs, verify commands, and one-phase-per-session protocol for the IDF modular UI work.
94 lines
5.4 KiB
Markdown
94 lines
5.4 KiB
Markdown
# Agent conventions — AutoFilm-ESP32
|
||
|
||
Instructions for humans and coding agents working in this repository.
|
||
|
||
## Product constraints
|
||
|
||
- Default temperatures, step times, and CW/CCW rotation counts for C41, E6, ECN-2, B&W, Custom, and B&WREV **do not change** unless a commit message explicitly says so and the recipe table in `docs/CURRENT_STATE.md` is updated in the same change.
|
||
- The machine **must always be stoppable** while a step is running: keypad Esc (`'X'`, 4 across / 4 down) and, on the S3 panel, a STOP control. Stop drops motor enable immediately, then offers Resume or return to step select.
|
||
- UI must not block on motor motion, OneWire conversion, or melody playback.
|
||
|
||
## Branch and docs
|
||
|
||
- Integration branch is **`develop`**. Feature and refactor work is done on a branch cut from `develop`, then opened as a PR **into `develop`**.
|
||
- Do not PR this work into `main`. `main` is not the day-to-day integration line.
|
||
- Active work branch for this refactor: `refactor/esp-idf-modular-ui` (rebase onto `develop` if the branch still points at `main`).
|
||
- Architecture intent: `docs/CURRENT_STATE.md`, `docs/TARGET_ARCHITECTURE.md`, `docs/CICD.md`.
|
||
- Implementation sessions: `docs/megaplans/REFACTOR-MEGAPLAN.md` then exactly one `docs/megaplans/refactor/Pxx-*.md`. Do not start the next phase in the same session.
|
||
- Do not commit secrets (Git tokens, Wi-Fi passwords, `sdkconfig` with provisioned keys).
|
||
|
||
## Layout
|
||
|
||
| Path | Role |
|
||
| --- | --- |
|
||
| `src/`, `include/` | Legacy Arduino sources; shrink, do not grow, except bugfixes needed for the port |
|
||
| `main/` | IDF entry |
|
||
| `components/app_*` | Application: process table, machine, UI |
|
||
| `components/ui_cmd` | Command/event types only |
|
||
| `components/hal_*` | Hardware adapters |
|
||
| `components/board_*` | Pin maps and board bring-up |
|
||
| `docs/` | Design notes |
|
||
| `.gitea/workflows/` | Gitea Actions (tests + firmware builds) |
|
||
|
||
New behaviour goes into `components/`, not into larger `menu.cpp` files.
|
||
|
||
## Framework policy
|
||
|
||
- Build system is **ESP-IDF**. PlatformIO + Arduino remains only until the IDF skeleton compiles both boards.
|
||
- **Arduino-as-component** is allowed as a bridge for AccelStepper, Keypad, LiquidCrystal_I2C, OneWire, DallasTemperature.
|
||
- Treat Arduino as debt:
|
||
- No Arduino types (`String`, `Keypad`, `AccelStepper`, `LiquidCrystal_I2C`) in headers of `app_machine`, `app_process`, or `ui_cmd`.
|
||
- Do not add new Arduino library dependencies.
|
||
- Prefer IDF drivers (GPIO, RMT, I2C, LEDC, `esp_timer`, `esp_lcd`) for new work.
|
||
- Two firmware flavours: `board_wroom` and `board_jc4827w543`. Gate pins and peripherals with board CMake, not `#ifdef` sprinkled through the state machine.
|
||
|
||
## Concurrency
|
||
|
||
- One responsibility per task: input, UI, machine, motor, temperature, audio.
|
||
- Cross-task data: FreeRTOS queues, task notifications, atomics. No unsynchronised use of `lcd` / `stepper` / `sensors`.
|
||
- ISR / stop path: set a flag, disable motor EN, `xQueueSendFromISR` / `xTaskNotifyFromISR`. No heap, no `delay`, no LCD from ISR.
|
||
- Do not `vTaskDelete` worker tasks after startup. Do not disable the task watchdog to “make it work”.
|
||
- `vTaskDelay` / `esp_timer` instead of busy-wait `millis()` loops.
|
||
|
||
## UI / machine split
|
||
|
||
- UI emits commands; machine emits events. See `docs/TARGET_ARCHITECTURE.md`.
|
||
- Touch and keypad are input adapters. They produce the same commands.
|
||
- Display adapters render events. Machine code must compile with no display driver linked (except in tests that stub HAL).
|
||
|
||
## Code style
|
||
|
||
- C11 for new IDF components; C++17 only where an existing Arduino library forces it, isolated in `hal_*`.
|
||
- `snake_case` for new functions and files; existing camelCase stays until that file is rewritten.
|
||
- 4-space indent to match the current tree.
|
||
- No raw `new` / `malloc` for per-frame strings. No `String` concatenation on the control path.
|
||
- Log with `ESP_LOGx` tags (`machine`, `motor`, `ui`, `temp`, `input`), not `Serial.print`.
|
||
- Errors are `esp_err_t` across HAL boundaries.
|
||
|
||
## Recipes
|
||
|
||
- Recipe tables live in `app_process` (or today’s `devSequence.cpp` until moved).
|
||
- Session time nudges (±5 s) are RAM overlays, not edits of the const defaults.
|
||
- Persistent custom profiles are out of scope until designed; do not half-add NVS.
|
||
|
||
## Hardware notes
|
||
|
||
- WROOM pins are defined in the legacy `config` headers; do not silently reuse them on the S3 panel.
|
||
- JC4827W543C: NV3041A 480×272 QSPI, GT911 on I²C, limited free IO. Confirm any new GPIO against the board pin table before assigning STEP/DIR/EN/1-Wire.
|
||
- Motor enable is active LOW on the current WROOM wiring. Safe state is disabled.
|
||
|
||
## Commits and review
|
||
|
||
- Cut work from `develop`. Open PRs against `develop`.
|
||
- Imperative commit subjects (`Add machine stop notify`, not `Added`).
|
||
- One concern per commit when practical (HAL wrap ≠ UI rewrite ≠ recipe move).
|
||
- Do not reformat whole legacy files in the same commit as a behaviour change.
|
||
- If defaults would change, fail the change unless the user explicitly asked.
|
||
|
||
## Tests
|
||
|
||
- Prefer host-side tests for `app_process` lookup and the machine state machine with a stub motor (`tests/host`, CMake + CTest).
|
||
- On-target smoke: select process, start a short Custom step, Esc mid-step, confirm EN high and Resume works.
|
||
- CI is Gitea Actions: host tests must pass before either firmware image is built. See `docs/CICD.md`.
|
||
- After `tests/host` exists, run it before push. After the IDF skeleton exists, a local `idf.py` build for the board you touched is expected.
|