Motor de consola — ESP32-S3 (16 MB PSRAM)
Motor de consola — ESP32-S3 (16 MB PSRAM)
Motor gráfico 2D + mode 7 + binding Lua para una consola portátil estilo
Playdate/PicoSystem, corriendo sobre ESP32-S3 con 16 MB de PSRAM octal.
Estructura
consola-esp32/
├── src/
│ ├── main.cpp # arranque + game loop + input GPIO
│ └── motor/
│ ├── motor.hpp/.cpp # NÚCLEO: framebuffer, blitter, mode 7, texto
│ ├── pantalla.hpp # capa hardware (LovyanGFX, DMA, doble buffer)
│ └── lua_api.hpp/.cpp # binding de la API a Lua 5.4
├── tests/
│ └── test_motor.cpp # verificación del núcleo (compila en PC)
├── games/pong/main.lua # juego de ejemplo
└── docs/ # documentación y diagramas
Hardware: ESP32-S3 con PSRAM octal de 16 MB
La configuración clave está en platformio.ini:
board_build.arduino.memory_type = qio_opi
16 MB de PSRAM en el ESP32-S3 es siempre octal (OPI). qio_opi activa
CONFIG_SPIRAM_MODE_OCT en el SDK y enlaza los scripts correctos. Con quad
(8 MB) usarías qio_qspi.
Todo el consumo de memoria va a PSRAM:
- Framebuffer doble →
heap_caps_malloc(..., MALLOC_CAP_SPIRAM)explícito. - Heap de Lua →
lua_newstate(luaPsramAlloc, ...)con realloc en PSRAM.
Con 16 MB hay sitio de sobra para framebuffer 480×320 (×2), texturas de mode 7,
y que cada juego Lua cargue tablas/sprites grandes sin tocar la RAM interna
(que queda libre para el stack y el sistema).
Verificar el núcleo en el Mac (sin hardware)
clang++ -std=c++17 -O2 -Isrc/motor tests/test_motor.cpp src/motor/motor.cpp -o /tmp/test_motor
/tmp/test_motor
18 pruebas: clear, rect con recorte, sprite con transparencia/flip/recorte,
line, texto, y mode 7 (horizonte, textura, rotación). Todo debe dar "TODAS
LAS PRUEBAS DEL MOTOR PASARON".
Compilar para el ESP32-S3
- Instala PlatformIO (
pip install platformioo extensión de VS Code). cd consola-esp32 && pio runpio run -t upload
Diseño del motor (resumen)
- Framebuffer en PSRAM (doble buffer): se pinta en uno, se muestra el otro.
- RGB565 (16 bits/píxel): el estándar de las pantallas SPI.
- Color key magenta = transparente en sprites.
- Mode 7 por software: plano de suelo con perspectiva, punto fijo 16.16,
textura potencia-de-dos con wrap por máscara. - Lua embebido: el juego es un
main.luaconinit(),update(dt)y
onButton(n). El juego nunca toca el hardware, solo llama a la API.
API pública (Lua, naming estándar inglés)
clear(), rect(), line(), text(), textWidth(), spr(), sprSize(),
mode7(), btn(), btnp(), dt().
Consulta docs/api.md para la documentación completa de cada función.