Skip to content

espp 1.4.2: espp::Audio (playback only), no DPI DMA2D, frame_buffers(), aligned TPM state I/O, menu save/load soak - #14

Merged
finger563 merged 6 commits into
mainfrom
feat/espp-1.4
Nov 8, 2026
Merged

finger563 merged 6 commits into
mainfrom
feat/espp-1.4

Conversation

@finger563

@finger563 finger563 commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

What

  • espp 1.4.2 (m5stack-tab5 >= 1.4.2; every espp component resolves to 1.4.2).
    • The PPA draws into the DPI panel's frame buffer, which now comes from the new frame_buffers() accessor (since 1.4.0) instead of the BSP's protected panel handle.
    • Audio goes through espp::Audio: initialize_audio() starts from default_audio_config() at 48 kHz with recording off, so there's no microphone DMA ring or task in internal RAM.
    • initialize_lcd({.dma2d_enabled = false}): every LVGL flush here is rotated, so it goes through the PPA and DMA2D never ran.
    • The logger no longer creates a mutex per tag, which saves about 150 internal allocations at boot.
  • TPM save states go through an aligned 64 KB block buffer. On 1.4.0, saving from the pause menu failed (sdmmc_cmd: allocate_dma_buf: not enough mem). FATFS got the header and memory regions at arbitrary addresses and offsets, so the SD driver bounced every write through internal DMA memory, and 1.4.0 left little of it free. Saves now take 0.7–1.0 s (was 1.3 s) and loads 0.33 s (was 0.49 s).
  • Test aid TAB5_EMU_AUTOQUIT_STATES. During the launch/quit soak, it opens the pause menu over each game and clicks Save a third of the way in and Load two thirds in, the same way a tap does (Menu::click). The soak's saves go to saves-soak/, so real saves aren't touched.

Internal RAM on the board (boot log)

free after the GUI espp 1.3.11 espp 1.4.0 espp 1.4.2 + this PR
internal ~73.4 KB 56.9 KB 87.9 KB
DMA-capable ~34 KB 17.5 KB 48.5 KB
blocks allocated 783 633

1.4.0 had cost about 16.5 KB of DMA-capable RAM: the I2S rings doubled, including the unused RX one, and DMA2D was turned on. With recording and DMA2D off, 1.4.2 more than wins that back.

Tested on the Tab5

  • espp 1.4.0 soak (90 s per game, menu save and load each time): TPM, Jedi Knight, MGS, Chrono Trigger, EarthBound, Minish Cap, Metroid Fusion and Sonic 2. 16 sessions, no crashes or errors, and no internal-RAM leak over 2 rounds.
  • espp 1.4.2: boots, and the SD card mounts. Audio was played across the games and sounded good.
  • Known and not new: pausing JK during a cutscene garbles its sound after resuming. The cutscene clock counts the pause as lag. A fix in OpenJKDF2 is being tested and will come separately.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY

finger563 and others added 4 commits October 26, 2026 21:59
The Phantom Menace and Metal Gear Solid save to a memory card in port 1:
saves/tpm_card1.mcd and saves/mgs_card1.mcd, raw 128 KB card images as PC
emulators use, made the first time the game looks. Unlike save states,
which hold raw memory and load only into the build that wrote them, these
survive firmware updates.

- tpm-decomp fea7648..d51af21: libmcrd natively on the card image (tested
  on the desktop and the board: a save from one build loaded into another);
  recomp.py treats a jr to the function's own return address as a return
  (the save screen's bit packer returns through $a3)
- psyz 3245d54: mcd, the card image and the BIOS's buXX: device
- mgs_reversing 6d58e9f: the port's bu00: device and memcard.c on it (the
  game finds the card at boot)
- Cart::get_memory_card_path names the image after the game's directory

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
The BSP now exposes the DPI panel's frame buffers, so the PPA's target no
longer comes from its protected panel handle.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
The header and the game's memory regions went to FATFS at any address and
file offset, so the SD driver bounced every write through internal DMA
memory. With espp 1.4.0 (deeper I2S DMA rings, DMA2D for the panel) about
16 KB less of it is free, and a save from the pause menu failed outright
(allocate_dma_buf: not enough mem). Through one 128-byte-aligned PSRAM block
at block-multiple file offsets, as the disc's read-ahead does, nothing is
bounced: saves 707-969 ms (1295 ms before), loads 330 ms (489 ms).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
TAB5_EMU_AUTOQUIT_STATES: a third of the way into each auto-started game the
pause menu opens over it and Save is clicked, two thirds in Load, the same
way taps do (Menu::click). The soak's saves go to saves-soak/ so the
player's own are left alone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
Copilot AI balanced review requested due to automatic review settings November 3, 2026 16:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Automatic quitting can occur before Load is exercised when a short deadline or slow save causes Save to overrun it, so quitting must wait for both state actions to complete when AUTOQUIT_STATES is enabled.

1 open issue
What changed in this PR

Updates the Tab5 integration for espp 1.4.0, improves TPM save-state I/O under limited DMA memory, and adds automated menu save/load exercises.

Changes:

  • Uses the public BSP frame-buffer accessor and raises the minimum dependency version.
  • Routes TPM state reads and writes through an aligned 64 KB buffer.
  • Adds save/load actions to the launch/quit soak, with saves isolated in saves-soak/.
File Description
main/​main.cpp Schedules menu save/load actions during automated runs.
main/​Kconfig.projbuild Adds the save/load soak option.
main/​cart.hpp Drives automated menu actions and isolates soak saves.
components/​tpm/​src/​tpm_engine.cpp Adds aligned, buffered state-file I/O.
components/​tab5-emu/​src/​tab5-emu.cpp Replaces protected BSP access with public frame-buffer APIs.
components/​tab5-emu/​idf_component.yml Requires espp m5stack-tab5 1.4.0 or later.
components/​menu/​src/​menu.cpp Implements programmatic menu-button clicks.
components/​menu/​include/​menu.hpp Declares the menu click API.

Review effort: Balanced

Comment thread main/main.cpp
state_step++;
}
#endif
if (std::chrono::steady_clock::now() >= quit_at) {
Base automatically changed from feat/memory-cards to main November 8, 2026 05:38
finger563 and others added 2 commits November 7, 2026 23:54
…I DMA2D

initialize_audio() takes the BSP's AudioConfig (espp::Audio::AppConfig) with
recording off: no RX DMA ring or microphone task in internal RAM.
initialize_lcd() turns the panel's DMA2D copies off: every LVGL flush is
rotated, so it goes through the PPA and DMA2D never ran (~3 KB of internal
DMA-capable RAM). 1.4.2 also brings the logger without a mutex per tag.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFCMzomCZ5wRHJN4sxwkvY
@finger563 finger563 changed the title espp 1.4.0: frame_buffers(), aligned TPM state I/O, menu save/load soak espp 1.4.2: espp::Audio (playback only), no DPI DMA2D, frame_buffers(), aligned TPM state I/O, menu save/load soak Nov 8, 2026
@finger563
finger563 merged commit 8447339 into main Nov 8, 2026
1 check passed
@finger563
finger563 deleted the feat/espp-1.4 branch November 8, 2026 05:57
@github-actions

github-actions Bot commented Nov 8, 2026

Copy link
Copy Markdown

ESP-IDF Size Report for 'Tab5 Emu'

Metric Base PR Delta
FLASH 0 bytes (0.00%) 0 bytes (0.00%) 0 bytes (0.00%)
DRAM 267,418 bytes (60.60%) 267,418 bytes (60.60%) 0 bytes (0.00%)
IRAM 0 bytes 0 bytes 0 bytes
RAM (DRAM+IRAM) 267,418 bytes 267,418 bytes 0 bytes (0.00%)

FLASH uses app .bin size or json2 flash sum. RAM sums DRAM+IRAM via idf_size. Percentages shown when totals are available.
DRAM/IRAM usage does not include memory used by the heap allocator at runtime.
This report was generated by esp-idf-size-delta.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants