Lock P00–P08 with in/out scope, frozen APIs, verify commands, and one-phase-per-session protocol for the IDF modular UI work.
3.9 KiB
P06 — WROOM UI cutover (2004 + keypad + Stop/Resume)
STATUS: TODO
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
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
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:
- Select Custom, Ent to arm, Ent to start 10 s step, remaining counts, temp updates
- Mid-step X: motor stops at once, Stopped screen, E resumes remaining, X returns to list
- Disconnect DS18B20:
--still navigable - 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
Add 2004 display and keypad HALAdd app_ui screens driven by machine eventsCut over WROOM main to RTOS UI and stop-safe input
DoD
- Esc during run always EN-off
- No malloc mm:ss
- No blocking alarm on UI/machine
- Legacy menus not in the IDF link
- STATUS→DONE