ci / test (push) Successful in 1m16s
ci / test (pull_request) Successful in 1m19s
ci / firmware (jc4827w543, sdkconfig.s3, esp32s3) (push) Failing after 29s
ci / firmware (jc4827w543, sdkconfig.s3, esp32s3) (pull_request) Failing after 30s
ci / firmware (wroom, sdkconfig.wroom, esp32) (pull_request) Failing after 30s
ci / firmware (wroom, sdkconfig.wroom, esp32) (push) Failing after 33s
input_task drops motor EN immediately on X while RUNNING, then queues CMD_STOP. machine_task ticks at 50 Hz. startingMenu is not linked. STATUS DONE. Notes=hw smoke pending.
142 lines
4.0 KiB
Markdown
142 lines
4.0 KiB
Markdown
# P06 — WROOM UI cutover (2004 + keypad + Stop/Resume)
|
||
|
||
STATUS: DONE
|
||
DEPENDS: P05
|
||
READ: this file, `src/menu.cpp`, `src/display.cpp`, `src/config.cpp`, `docs/TARGET_ARCHITECTURE.md` (screens + stop rules)
|
||
OUT: S3 LVGL, NVS profiles, keeping blocking `getEntEscInput` as the live path
|
||
FORBIDDEN: `while(true)` keypad wait in machine; `malloc` for mm:ss; `vTaskDelete`; WDT off
|
||
|
||
## IN
|
||
|
||
Replace live control path with `input_task` + `ui_task` + `app_ui` screens on 20×4. Legacy `src/*.cpp` may remain unlinked. `main` no longer calls `startingMenu()`.
|
||
|
||
After this phase the WROOM firmware **is** the product.
|
||
|
||
## FILES
|
||
|
||
```
|
||
components/hal_display/include/hal_display.h
|
||
components/hal_display/hal_display_lcd2004.cpp
|
||
components/hal_input/include/hal_input.h
|
||
components/hal_input/hal_input_keypad.cpp
|
||
components/app_ui/include/app_ui.h
|
||
components/app_ui/app_ui.c
|
||
components/app_ui/screens.h
|
||
```
|
||
|
||
C++ only in hal_display / hal_input.
|
||
|
||
## hal_display.h
|
||
|
||
```c
|
||
void hal_display_init(void);
|
||
void hal_display_clear(void);
|
||
void hal_display_text(int col, int row, const char *s); /* clip to 20 cols */
|
||
void hal_display_glyph_thermo(int col, int row);
|
||
void hal_display_flush(void); /* no-op */
|
||
```
|
||
|
||
LCD: I2C 21/22 addr 0x27, 20x4, createChar thermometer from `config.cpp` bytes.
|
||
|
||
mm:ss: stack buffer `char[6]`, `snprintf "%02d:%02d"`. Never malloc.
|
||
|
||
## hal_input.h
|
||
|
||
```c
|
||
typedef struct { char key; } ui_raw_key_t;
|
||
void hal_input_init(void);
|
||
bool hal_input_pop_key(ui_raw_key_t *out); /* nonblocking */
|
||
```
|
||
|
||
Keypad map **byte-identical** to `src/config.cpp`. Scan in `input_task` 25 Hz. Debounce via Keypad lib.
|
||
|
||
Map:
|
||
|
||
| key | cmd |
|
||
|---|---|
|
||
| 1..6 | SELECT_PROCESS id 0..5 |
|
||
| U/D | BROWSE_STEP ±1 |
|
||
| L/R | ADJUST_STEP_TIME ±5 |
|
||
| E | ARM if STEP_SELECT; START if ARMED; RESUME if STOPPED; ARM next if COMPLETE |
|
||
| X | CANCEL_ARMED if ARMED; STOP if RUNNING or COMPLETE; RETURN_TO_STEP_SELECT if STOPPED; ignore IDLE |
|
||
|
||
**X in RUNNING:** `hal_motor_request_stop()` **in input_task immediately**, then queue CMD_STOP. Dual-path required.
|
||
|
||
## Screens (20×4)
|
||
|
||
`ProgramSelect` (IDLE):
|
||
|
||
```
|
||
Select Programme:
|
||
1. C41 4. ECN-2
|
||
2. E6 5. Custom
|
||
3. B&W 6. B&W Rev
|
||
```
|
||
|
||
`StepSelect`:
|
||
|
||
```
|
||
Step Time Temp
|
||
<name> mm:ss nnC
|
||
Scroll / Esc / Ent
|
||
🌡 tt.tC row3 col13 thermo+temp or --
|
||
```
|
||
|
||
`Armed`: name, mm:ss, pref C, `Ent:start Esc:quit`, temp row3
|
||
|
||
`Running`: name row0, `Remaining: mm:ss` row1, temp row3. Update remaining ≥4 Hz from events, **not** by blocking. No `delay(410)`.
|
||
|
||
`Stopped`: name, remaining, `E:resume X:back`, temp row3
|
||
|
||
`Complete`: name `Done`, then alarm (nonblocking). `E` next / `X` back.
|
||
|
||
## Tasks
|
||
|
||
| task | prio |
|
||
|---|---|
|
||
| input_task | high |
|
||
| machine_task | mid-high; `handle_cmd` + `tick(esp_timer_get_time/1000)` 50 Hz |
|
||
| ui_task | mid; drain events, dirty draw |
|
||
| motor/temp/audio | as P05 |
|
||
|
||
TWDT: register tasks that run long loops or rely on idle.
|
||
|
||
## Cutover
|
||
|
||
`main.c`: init display/input, splash `AUTOFILM` + git describe 1 s **via vTaskDelay not busy Arduino delay in ui_task after scheduler start**. Unlink `src/AutoFilmESP32.cpp` from IDF (leave files on disk).
|
||
|
||
`platformio.ini` may stay; do not promise PIO still builds.
|
||
|
||
## VERIFY
|
||
|
||
Host tests pass.
|
||
|
||
WROOM idf build pass.
|
||
|
||
Hardware smoke:
|
||
|
||
1. Select Custom, Ent to arm, Ent to start 10 s step, remaining counts, temp updates
|
||
2. Mid-step X: motor stops at once, Stopped screen, E resumes remaining, X returns to list
|
||
3. Disconnect DS18B20: `--` still navigable
|
||
4. Complete alarm: X cancels and returns; UI not frozen 7.5 s
|
||
|
||
If no hardware: still land; Notes=`hw smoke pending`; do not skip the input dual-path stop.
|
||
|
||
## COMMITS
|
||
|
||
1. `Add 2004 display and keypad HAL`
|
||
2. `Add app_ui screens driven by machine events`
|
||
3. `Cut over WROOM main to RTOS UI and stop-safe input`
|
||
|
||
## DoD
|
||
|
||
- [x] Esc during run always EN-off
|
||
- [x] No malloc mm:ss
|
||
- [x] No blocking alarm on UI/machine
|
||
- [x] Legacy menus not in the IDF link
|
||
- [x] STATUS→DONE
|
||
|
||
## Notes
|
||
|
||
Notes=`hw smoke pending`. Host ctest green. WROOM `idf.py` build attempted in sandbox without ESP-IDF installed.
|