Lock P00–P08 with in/out scope, frozen APIs, verify commands, and one-phase-per-session protocol for the IDF modular UI work.
5.4 KiB
5.4 KiB
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.mdis 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 fromdevelop, then opened as a PR intodevelop. - Do not PR this work into
main.mainis not the day-to-day integration line. - Active work branch for this refactor:
refactor/esp-idf-modular-ui(rebase ontodevelopif the branch still points atmain). - Architecture intent:
docs/CURRENT_STATE.md,docs/TARGET_ARCHITECTURE.md,docs/CICD.md. - Implementation sessions:
docs/megaplans/REFACTOR-MEGAPLAN.mdthen exactly onedocs/megaplans/refactor/Pxx-*.md. Do not start the next phase in the same session. - Do not commit secrets (Git tokens, Wi-Fi passwords,
sdkconfigwith 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 ofapp_machine,app_process, orui_cmd. - Do not add new Arduino library dependencies.
- Prefer IDF drivers (GPIO, RMT, I2C, LEDC,
esp_timer,esp_lcd) for new work.
- No Arduino types (
- Two firmware flavours:
board_wroomandboard_jc4827w543. Gate pins and peripherals with board CMake, not#ifdefsprinkled 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, nodelay, no LCD from ISR. - Do not
vTaskDeleteworker tasks after startup. Do not disable the task watchdog to “make it work”. vTaskDelay/esp_timerinstead of busy-waitmillis()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_casefor new functions and files; existing camelCase stays until that file is rewritten.- 4-space indent to match the current tree.
- No raw
new/mallocfor per-frame strings. NoStringconcatenation on the control path. - Log with
ESP_LOGxtags (machine,motor,ui,temp,input), notSerial.print. - Errors are
esp_err_tacross HAL boundaries.
Recipes
- Recipe tables live in
app_process(or today’sdevSequence.cppuntil 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
configheaders; 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 againstdevelop. - Imperative commit subjects (
Add machine stop notify, notAdded). - 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_processlookup 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/hostexists, run it before push. After the IDF skeleton exists, a localidf.pybuild for the board you touched is expected.