Serial uploader was crashing the Pico when launching games because
it accessed SD card (SPI) while Core 1 was refreshing display (also SPI).
Display and SD card share the same SPI bus and cannot be accessed
simultaneously.
Split game launch into prepare and execute phases:
- prepare: Re-scan games directory (safe, SD access done immediately)
- execute: Load Lua script from SD (deferred until display is idle)
Main loop now checks !is_refresh_in_progress() before completing
launch, preventing SPI conflicts.
Also updated SD card best practices skill to document SPI bus
contention as the #1 most critical issue to avoid.
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a complete serial upload workflow that allows uploading and
immediately testing Lua games via USB serial connection.
New Components:
- SerialUploader: Receives files via serial, writes to SD card
- upload_game.py: Python tool for sending files from host computer
- Protocol: Text-based with base64 encoding for reliability
Key Features:
- Uploads file to /games folder on SD card
- Overwrites existing files (FA_CREATE_ALWAYS)
- Auto-launches uploaded game immediately
- Proper memory cleanup (prevents Lua state conflicts)
SD Card Fixes:
- Fixed SPI speed management (12.5MHz for SD, 32MHz for display)
- Fixed SD write protocol (poll for data response token)
- Added speed switching wrappers around all FatFS operations
- Cleaned up excessive debug output
Game Launcher Improvements:
- Added clear_games() to prevent duplicate registrations
- Added cleanup in select_game_by_name() to delete old instances
- Added exact match priority in game selection
- LuaGameLoader now has clear_factory_data() for memory cleanup
Integration:
- Added serial_uploader to CMakeLists.txt
- Integrated into main loop in basic1.cpp
- Re-scans games after upload to pick up new files
Documentation:
- UPLOAD_TOOL.md: Usage instructions
- sd_card_best_practices.md: Critical lessons learned
Known Issues:
- Game launch after upload occasionally causes freeze (needs investigation)
- Display may not refresh properly after upload
Usage:
python upload_game.py games/lua_examples/2048.lua /dev/tty.usbmodem101
Co-Authored-By: Claude <noreply@anthropic.com>
lua_bindings.cpp:
- Added new lua_renderer_text_scaled() function
- Wraps renderer->draw_string_scaled() with proper scale support
- Registered as renderer.text_scaled(x, y, text, on, scale)
- Scale parameter defaults to 1 if omitted
Updated all 4 games to use text_scaled():
- simon_says.lua: All text now uses text_scaled with scale=2
- tic_tac_toe.lua: All text now uses text_scaled with scale=2
- memory_match.lua: All text now uses text_scaled with scale=2
- 2048.lua: All text now uses text_scaled with scale=2
This properly uses the C++ renderer's scaled text rendering instead of
workarounds in Lua, providing better performance and consistency.
All 4 games (simon_says, tic_tac_toe, memory_match, 2048):
- Changed sizing to use min(width, height) instead of just width
- Grids now scale proportionally on both axes
- All UI text now uses text_scale=2 for better visibility
- Games fill more of the screen properly on portrait mode
Fixes:
- Simon Says buttons now square grid on any orientation
- Tic-Tac-Toe grid centered vertically using full screen height
- Memory Match cards use smallest dimension for square sizing
- 2048 tiles scale and center on both axes
- All text (scores, menus, game over) now 2x larger
2048.lua:
- Removed hardcoded TILE_SIZE and TILE_SPACING constants
- Added get_tile_size() function that calculates tile dimensions based on screen width
- Added get_grid_start_x/y() to center grid
- Updated draw() to use dynamic sizing for all tiles
- 4x4 grid now scales proportionally on any screen size