Karaoke for guitar players, on the Free Wili 2 (RP2350B). It scrolls a song's lyrics with the chords positioned above them, auto-scrolling at an adjustable rate so you can play hands-free.
Chords over scrolling lyrics on the device. Songs load from ROM or a USB thumb drive, and can be grouped into auto-advancing playlists — see the merged song list below.
Status: Milestone 3 complete & hardware-verified — load songs from a USB thumb drive (
/songs) and auto-advancing playlists (/playlists), merged with the 3 baked-in ROM songs, with crash-safe scroll-rate save back to USB files and full hot-plug. Built on M2a (touch selector + transport) and M1 (ROM render + smooth scroll). Verified on hardware: the native USB-host MSC stack enumerates a drive and mounts FatFS; USB songs + a mixed ROM/USB playlist load and play; scroll-save writes back to the file; setlist auto-advance + hot-plug work; ROM fallback (no/empty drive) works. Sample drive content insamples/usb-drive/. The 14 hardware buttons over UART (M2b) and the metronome (M4) are later milestones.
-
Song files (
songs/*.txt) are plain text, easily editable. They support two interchangeable chord styles, auto-detected per song:- ChordPro inline:
I [G]once was lost but [D]now am found - Positional two-line: a chord line directly above its lyric line.
- ChordPro inline:
-
Section reuse: define a section once (
[Chorus]+ body); replay it later by naming it with an empty body ([Chorus]). Repeat it N times to play it N times. Seesongs/red_river_valley.txt. -
Parser (
src/songfmt/) is hardware-free and host-unit-tested. It normalizes both styles into a canonicalRowmodel (lyric + chords with character columns). The renderer never sees the file style. -
Rendering (
src/ui/ui_perform.c) uses LVGL 9.2 with the monospaceunscii_16font so chord columns land exactly over their characters. Each display line is its own colored label (amber header / blue chord / white lyric) — we avoid LVGL recolor markup because sharp chords (F#) contain a literal#that would corrupt it. The whole content column is moved up by a sub-pixel velocity accumulator each frame for a smooth teleprompter scroll. -
ROM songs:
tools/gen_rom_songs.ps1bakessongs/*.txtinto C string literals (src/songs_rom/) compiled into firmware flash. -
Input (M2a): the FT6336U touch controller (proven
sensorviewdriver) drives everything via LVGL. The selector is a touch list; the perform screen reveals a transport overlay on tap (auto-hides after 3 s). Scroll speed/pause live in a pure, host-testedtransportmodule (step ±2 px/s, clamp 4–60). The 14 hardware buttons (UART) arrive in M2b once their serial protocol is known.
Infrastructure (CMake, Pico SDK, ST7796 SPI1+DMA driver, LVGL port, board
bring-up at 153.6 MHz, SEGGER RTT, build/flash scripts) is reused from the
companion sensorview project. Touch adds the PCAL6524 IO-expander + I2C1.
Tooling: Windows PowerShell + the Raspberry Pi Pico VS Code extension toolchain (
~/.pico-sdk, SDK 2.2.0). No serial stdio — diagnostics are over SEGGER RTT (USB is host-mode).
# Re-bake ROM songs after editing songs/*.txt
powershell -File tools/gen_rom_songs.ps1
# Host unit tests (parser logic, system gcc)
powershell -File tools/run_host_tests.ps1
# Build (always -Clean before a hardware verify; Dropbox rewrites mtimes)
powershell -File tools/build.ps1 -Clean
# Flash + reset over the CMSIS-DAP debug probe (OpenOCD, no BOOTSEL dance)
Get-Process openocd -ErrorAction SilentlyContinue | Stop-Process -Force
powershell -File tools/flash.ps1
# Live RTT console
powershell -File tools/rtt.ps1 -Seconds 10Build dir: C:/buildfiles/guitarman. Firmware runs from flash/XIP (LVGL .text
is too large to copy into SRAM).
- Host tests:
song_parse_test(9 cases: header, F#/slash chord grammar, section define/reference/repeat, ChordPro + positional column math, instrumental rows, malformed input) androm_parse_smoke— all pass. - On device: RTT reports
ioexp: init ok,ft6336: init ok id=0x64, andopen song: <name> ok=1 ...on selection. An eMeet camera confirms the selector lists all three songs (title — artist) and that tapping a row opens the perform screen, which renders chords-over-lyrics and scrolls.- Live transport confirmed over RTT: tapping the lyrics reveals the overlay,
and the controls log
speed=14→12→10→8→6(step),pause=1/0, andopen song: house_rising_sun(List → selector → reopen) as they're used.
- Live transport confirmed over RTT: tapping the lyrics reveals the overlay,
and the controls log
The panel uses the ST7796 MADCTL=0x2C from the reference driver and renders
upright on the device. (Early bench captures looked 180° flipped only because
the verification camera is mounted upside-down relative to the board — the
display itself is correct.)
Edit songs/<name>.txt, then re-run tools/gen_rom_songs.ps1 and rebuild.
Header keys (all optional): title, artist, key, scroll (px/sec).
The song selector: a "Practice Set" playlist on top, then the three built-in songs and two songs loaded from the USB drive — all in one list.
- Full song & playlist authoring guide:
docs/song-and-playlist-format.md. - Put songs at
/songs/*.txtand playlists at/playlists/*.txton a FAT32 drive. ROM songs still appear when no drive is present (fallback), and USB songs merge into the same selector. Seesamples/usb-drive/for ready-to-copy examples. - Playlists are plain text: an optional
name:/dwell:header then one song filename per line (resolves to/songsfirst, then a ROM song by name). A playlist is an auto-advancing setlist;dwell:sets the seconds between songs (0= immediate,hold= wait for a tap). - Scroll-rate save: change the speed on a USB song and it's written back to
that file's
scroll:header when you leave (crash-safe temp-file + rename); ROM songs are read-only. Full hot-plug (insert/remove while running). - USB host is the reused native-RP2350 MSC stack + FatFS (single volume); hub power is gated via the PCAL6524 (HP1/HP2).
- Design spec (overall):
docs/superpowers/specs/2026-06-30-guitarman-design.md - M2a design:
docs/superpowers/specs/2026-06-30-guitarman-m2-design.md - M3 design:
docs/superpowers/specs/2026-06-30-guitarman-m3-design.md - Implementation plans:
docs/superpowers/plans/2026-06-30-guitarman-m1.md,-m2.md,-m3.md - Contributor / agent guide:
AGENTS.md
MIT — see LICENSE.
Infrastructure patterns (CMake, ST7796 driver, LVGL port, board bring-up) and the
native USB-host MSC stack are reused from the author's companion Free Wili 2
projects. Bundled third-party code under third_party/ (LVGL, SEGGER RTT) and
src/storage/fatfs/ (FatFS) retains its own upstream license.

