Contributing Guide
This guide covers setting up your development environment, building PolyBoard, running tests, and contributing changes.
Development Environment
Section titled “Development Environment”Prerequisites
Section titled “Prerequisites”PolyBoard uses Nix for reproducible builds. This ensures all developers use identical toolchains.
# Install Nixsh <(curl -L https://nixos.org/nix/install)
# Enable flakes (add to ~/.config/nix/nix.conf)experimental-features = nix-command flakes# Use WSL2 with Ubuntu, then install Nixwsl --install -d Ubuntu# Inside WSL:sh <(curl -L https://nixos.org/nix/install)Clone Repository
Section titled “Clone Repository”git clone --recursive https://github.com/b4nst/PolyBoard.gitcd PolyBoardBuilding
Section titled “Building”Using Nix (Recommended)
Section titled “Using Nix (Recommended)”# Enter development shellnix develop
# Or run commands directlynix run .#default -- makeBuild Commands
Section titled “Build Commands”# Full build (firmware + tests)make
# Build firmware onlymake build/polyboard.syx
# Clean build artifactsmake clean
# Build and run testsmake test
# Run lintermake lintBuild Outputs
Section titled “Build Outputs”| File | Description |
|---|---|
build/polyboard.elf | ELF binary with debug symbols |
build/polyboard.hex | Intel HEX format |
build/polyboard.syx | SysEx file for uploading |
Testing
Section titled “Testing”Running Tests
Section titled “Running Tests”# Run all testsmake test
# Run specific test file./build/tests/page_test.runTest Structure
Section titled “Test Structure”Tests use CMocka framework:
tests/├── mocks/│ └── hal.c # HAL function mocks├── app_state_test.c # Runtime state tests├── flash_test.c # Persistence tests├── layout_test.c # LED rendering tests├── note_test.c # Scale calculation tests├── page_test.c # Page management tests└── surface_test.c # Button detection testsWriting Tests
Section titled “Writing Tests”#include <stdarg.h>#include <stddef.h>#include <setjmp.h>#include <cmocka.h>#include "page.h"
static void test_change_page_valid(void **state) { (void)state;
// Setup app_state_init();
// Act const Page *page = change_page(2);
// Assert assert_non_null(page); assert_int_equal(get_current_page(), 2);}
int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_change_page_valid), }; return cmocka_run_group_tests(tests, NULL, NULL);}Mock HAL
Section titled “Mock HAL”Tests use mock HAL functions in tests/mocks/hal.c:
// Track LED state for assertionsstatic u32 mock_leds[100];
void hal_plot_led(u8 type, u8 index, u8 red, u8 green, u8 blue) { if (type == TYPEPAD && index < 100) { mock_leds[index] = (red << 16) | (green << 8) | blue; }}
u32 mock_get_led(u8 index) { return mock_leds[index];}Code Style
Section titled “Code Style”Formatting
Section titled “Formatting”PolyBoard uses LLVM style via clang-format:
# Check formattingmake lint
# Auto-format (run before committing)clang-format -i src/*.c include/*.hStyle Guidelines
Section titled “Style Guidelines”- Braces: K&R style (opening brace on same line)
- Indentation: 2 spaces (no tabs)
- Line length: 80 characters soft limit
- Naming:
- Functions:
snake_case - Constants:
UPPER_CASE - Types:
PascalCase
- Functions:
// Goodvoid change_page_root(unsigned char root) { if (root > 11) { return; } // ...}
// Badvoid ChangePageRoot(unsigned char root){ if(root>11) return;}Adding Features
Section titled “Adding Features”Adding a New Scale
Section titled “Adding a New Scale”-
Add to
note.h:enum ScaleIndex {// ... existing scalesSCALE_NEW_SCALE, // Add here};#define SCALE_COUNT 11 // Increment -
Add scale pattern to
scalesarray:// Scale pattern: 1=root, 0=in scale, -1=chromaticstatic const short scales[SCALE_COUNT][12] = {// ... existing// New Scale: semitones 0, 2, 4, 5, 7, 9, 10{1, -1, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1},}; -
Add degree count:
static const unsigned char SCALE_DEGREE_COUNT[SCALE_COUNT] = {// ... existing7, // New Scale}; -
Add degree-to-semitone mapping:
static const unsigned char DEGREE_TO_SEMITONE[SCALE_COUNT][7] = {// ... existing{0, 2, 4, 5, 7, 9, 10}, // New Scale}; -
Add color in
colors.h:#define COLOR_SCALE_NEW 0x3F003FU -
Add to scale selection map in
surface.c -
Add tests in
note_test.c
Adding a New Setting
Section titled “Adding a New Setting”-
Add field to
Pagestruct inpage.h:typedef struct Page {// ... existingunsigned char new_setting;} Page; -
Add default value:
#define DEFAULT_NEW_SETTING 0 -
Update
page.cinitialization -
Increment
FLASH_VERSIONinflash.h -
Add validation in
flash_load():if (data.pages[i].new_setting > MAX_VALUE) {data.pages[i].new_setting = DEFAULT_NEW_SETTING;} -
Add getter/setter functions
-
Add UI handling in
app.c(Setup mode) -
Add LED feedback in
layout.c -
Add tests
Adding a New Mode
Section titled “Adding a New Mode”-
Add to
mode.h:typedef enum {MODE_PLAY,MODE_ROOT_SELECT,MODE_SCALE_SELECT,MODE_SETUP,MODE_NEW_MODE, // Add here} AppMode; -
Add handler in
app.c:static void handle_new_mode(u8 index, u8 value) {// Handle button presses} -
Add to event routing:
switch (get_mode()) {// ... existingcase MODE_NEW_MODE:handle_new_mode(index, value);break;} -
Add renderer in
layout.c:void render_new_mode(void) {// LED layout} -
Add to
refresh_display():case MODE_NEW_MODE:render_new_mode();break; -
Add entry/exit triggers
-
Add tests
Uploading to Hardware
Section titled “Uploading to Hardware”Using Novation Updater
Section titled “Using Novation Updater”- Download Novation Components
- Put Launchpad Pro in bootloader mode (hold Setup while powering on)
- Drag
build/polyboard.syxto the updater
Using amidi (Linux)
Section titled “Using amidi (Linux)”# Find MIDI deviceamidi -l
# Upload firmwareamidi -p hw:1,0,0 -s build/polyboard.syxPull Request Process
Section titled “Pull Request Process”-
Create a feature branch:
Terminal window git checkout -b feature/my-feature -
Make changes and commit:
Terminal window git add .git commit -m "feat: add new feature" -
Ensure tests pass:
Terminal window make clean && make && make test -
Ensure code is formatted:
Terminal window make lint -
Push and create PR:
Terminal window git push -u origin feature/my-featuregh pr create
Commit Messages
Section titled “Commit Messages”Use Conventional Commits:
| Prefix | Usage |
|---|---|
feat: | New feature |
fix: | Bug fix |
refactor: | Code change that neither fixes nor adds |
docs: | Documentation only |
test: | Adding or fixing tests |
chore: | Build, CI, tooling changes |
See Also
Section titled “See Also”- Architecture Overview - System design
- SDK Constraints - Hardware limitations
- Modules Reference - Code documentation