Contributing
Contributions are welcome: bug reports with serial logs, hardware bring-up notes for panel or module variants, documentation fixes, and code. This page is the local etiquette; none of it is exotic.
Before writing code
- Open or find an issue first for anything beyond a trivial fix; design conversations are cheaper than review rejections.
- Read the two foundation chapters (architecture, tasks and memory); most review feedback in this repo is one of their rules restated.
The rules the codebase actually enforces
- Components communicate through public headers or the event bus. A patch that includes another component's private header will be asked to add an API instead.
- Events are facts, function calls are commands (the distinction). New events belong in the enum with a name in the table, and the static assert will remind you.
- Memory placement is explicit. Big buffers say where they live (
EXT_RAM_BSS_ATTRor aheap_caps_mallocwith caps) and why; DMA-touched memory is internal, no exceptions (the rules). - Blocking budgets: nothing above priority 5 blocks on the network; nothing called from the audio task blocks on anything slower than the DAC.
- Every externally supplied value is validated at the REST boundary, not in components (validation).
- Em dashes are prohibited in this repository, code, comments, and docs alike; use commas, colons, or parentheses. House style, enforced in review.
Style
clang-format (config in-tree, CI-enforced) settles formatting arguments by ending them. Beyond formatting:
- C11, four-space indent,
snake_case,SCREAMING_CASEconstants. - Comments explain why, never what; a comment narrating the next line is deleted in review.
- Errors: return
esp_err_t, log at the failure site with context, and keep booting when degradation is survivable (the boot report exists for exactly this). - Log levels mean things:
Ebroke,Wdegraded,Istate changed,Ddiagnostics.
Commits and pull requests
- Conventional commits (
fix(audio): ...,feat(display): ...,docs(user): ...), imperative subject, body explaining why. The repository's history is the style guide; several commit messages double as postmortems. - One logical change per PR. Include: what, why, how verified (which tests, what hardware, what the serial log showed). "Verified: soak 30 min, zero underruns" is a sentence reviewers trust more than any diff.
- Firmware changes that alter RAM or flash footprint: mention the size report delta.
- Documentation accompanies behavior changes in the same PR; the masterclass stays truthful or it is worthless.
Testing expectations
Pure logic gets unit tests next to the existing suites (testing strategy); hardware-flavored changes get an instrumented verification note in the PR. If your change touches the decode path, the reviewers will ask for the host-harness replay; save a round trip and run it first.
Hardware variants
Ports to other panels, codecs, or modules are welcome as long as the reference build stays the reference: variant support goes behind Kconfig options that default to current hardware, with bring-up notes added to the docs. A variant PR that silently changes defaults for everyone will bounce. The ST7789 panel option is the template: one Kconfig choice, one CI variant build, docs updated in the same PR.
Roadmap
Ideas that have been considered and would be welcomed, roughly by value:
- A playback queue with next and previous for file playback, driven from the dashboard.
- A sleep timer (stop playback after N minutes), cheap next to the existing scheduler.
- ReplayGain-style volume normalization across reciters, whose recordings vary wildly in level.
- An Opus codec via
esp_audio_codec, for streams that offer it at lower bitrates. - A VBR seek-table cache on the SD card, so seeking large variable-bitrate files stops costing a prescan.
- Battery voltage calibration against a measured divider, per device, stored in NVS.
- Encoder acceleration (fast spins jump farther) in the input handler.
- BLE provisioning as a SoftAP alternative; the current flow uses the ESP SoftAP Provisioning app, and BLE transport would remove the manual network hop for the phone.
- OTA updates for the dashboard partition alone, so web fixes stop requiring a firmware reflash.
- Home Assistant discovery on top of the existing mDNS announcement and REST API.