Skip to content

freewili/guitarman

Repository files navigation

GuitarMan

License: MIT

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.

GuitarMan performing a song on the Free Wili 2

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 in samples/usb-drive/. The 14 hardware buttons over UART (M2b) and the metronome (M4) are later milestones.

How it works

  • 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.
  • 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. See songs/red_river_valley.txt.

  • Parser (src/songfmt/) is hardware-free and host-unit-tested. It normalizes both styles into a canonical Row model (lyric + chords with character columns). The renderer never sees the file style.

  • Rendering (src/ui/ui_perform.c) uses LVGL 9.2 with the monospace unscii_16 font 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.ps1 bakes songs/*.txt into C string literals (src/songs_rom/) compiled into firmware flash.

  • Input (M2a): the FT6336U touch controller (proven sensorview driver) 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-tested transport module (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.

Build, flash, test

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 10

Build dir: C:/buildfiles/guitarman. Firmware runs from flash/XIP (LVGL .text is too large to copy into SRAM).

Verification (Milestone 1)

  • Host tests: song_parse_test (9 cases: header, F#/slash chord grammar, section define/reference/repeat, ChordPro + positional column math, instrumental rows, malformed input) and rom_parse_smoke — all pass.
  • On device: RTT reports ioexp: init ok, ft6336: init ok id=0x64, and open 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, and open song: house_rising_sun (List → selector → reopen) as they're used.

Display orientation

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.)

Editing songs

Edit songs/<name>.txt, then re-run tools/gen_rom_songs.ps1 and rebuild. Header keys (all optional): title, artist, key, scroll (px/sec).

USB thumb-drive songs & playlists (M3)

The selector merging a playlist, built-in songs, and USB songs

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/*.txt and playlists at /playlists/*.txt on a FAT32 drive. ROM songs still appear when no drive is present (fallback), and USB songs merge into the same selector. See samples/usb-drive/ for ready-to-copy examples.
  • Playlists are plain text: an optional name:/dwell: header then one song filename per line (resolves to /songs first, 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).

Docs

  • 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

License

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.

About

Karaoke for guitar players on the Free Wili 2 (RP2350B): scrolls lyrics with chords above them, USB thumb-drive songs + auto-advancing playlists, touch UI.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages