Architecture Overview
This document provides an overview of the PolyBoard firmware architecture, including component relationships and data flow.
System Overview
Section titled “System Overview”PolyBoard is custom firmware for the Novation Launchpad Pro. It transforms the device into an isomorphic MIDI controller with configurable scales, intervals, and pages.
┌─────────────────────────────────────────────────────────────┐│ Launchpad Pro Hardware ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ ││ │ 64 Pads │ │ Controls │ │ RGB LEDs (100) │ ││ │ (pressure) │ │ (buttons) │ │ │ ││ └──────┬──────┘ └──────┬──────┘ └──────────▲──────────┘ │└─────────┼────────────────┼─────────────────────┼────────────┘ │ │ │ ▼ ▼ │┌─────────────────────────────────────────────────────────────┐│ SDK (launchpad_pro.a) ││ ┌──────────────────────────────────────────────────────┐ ││ │ HAL Functions: hal_plot_led, hal_send_midi, etc. │ ││ └──────────────────────────────────────────────────────┘ ││ ┌──────────────────────────────────────────────────────┐ ││ │ Callbacks: app_surface_event, app_timer_event, etc. │ ││ └──────────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────┐│ PolyBoard Firmware ││ ││ ┌──────────┐ ┌───────────┐ ┌──────────────────────┐ ││ │ app.c │───▶│ app_state │◀───│ layout.c │ ││ │ (entry) │ │ .c │ │ (LED rendering) │ ││ └────┬─────┘ └─────┬─────┘ └──────────────────────┘ ││ │ │ ││ ▼ ▼ ││ ┌──────────┐ ┌───────────┐ ┌──────────────────────┐ ││ │ page.c │◀──▶│ note.c │ │ flash.c │ ││ │ (pages) │ │ (scales) │ │ (persistence) │ ││ └──────────┘ └───────────┘ └──────────────────────┘ │└─────────────────────────────────────────────────────────────┘Data Flow
Section titled “Data Flow”Button Press to MIDI Output
Section titled “Button Press to MIDI Output”User presses pad │ ▼┌──────────────────┐│ app_surface_event│ SDK callback with pad index and velocity└────────┬─────────┘ │ ▼┌──────────────────┐│ handle_play_mode │ Route to appropriate handler└────────┬─────────┘ │ ▼┌──────────────────┐│ calculate_note │ Convert pad position to MIDI note│ │ (considers root, scale, interval, transpose)└────────┬─────────┘ │ ▼┌──────────────────┐│ send_note_on │ Send MIDI to configured channels└────────┬─────────┘ │ ▼┌──────────────────┐│ set_note_active │ Track active notes for visual feedback└────────┬─────────┘ │ ▼┌──────────────────┐│ update_pad_color │ Update LED to show active state└──────────────────┘Note Calculation Pipeline
Section titled “Note Calculation Pipeline”// 1. Get pad positionu8 row = index / 10 - 1; // 0-7u8 col = index % 10 - 1; // 0-7
// 2. Calculate semitone offset using intervalint semitone_offset = row * interval + col;
// 3. Apply scale-relative transposition (if any)if (transpose != 0) { semitone_offset = transpose_semitone_by_degree( semitone_offset, scale_type, transpose);}
// 4. Add root note and octaveint note = root + semitone_offset + octave * 12;
// 5. Clamp to MIDI range [0, 127]note = clamp(note, 0, 127);State Management
Section titled “State Management”AppState (Runtime)
Section titled “AppState (Runtime)”Volatile state that exists only during the current session:
typedef struct AppState { AppMode mode; // Current UI mode unsigned char active_notes[16]; // 128-bit bitmask unsigned char dirty; // Flash save pending unsigned char held_page; // Page button held unsigned char held_shift; // Shift modifier unsigned char scale_lock; // Global scale lock unsigned char in_setup_mode; unsigned char pad_notes[100]; // Note-to-pad mapping} AppState;PageManager (Persistent)
Section titled “PageManager (Persistent)”Configuration that can be saved to flash:
typedef struct Page { unsigned char root; // 0-11 (C through B) unsigned char scale_type; // 0-9 (10 scales) unsigned char octave; // 0-10 unsigned char interval_index; // 0-3 (m3, M3, P4, P5) unsigned short midi_channels; // 16-bit bitmask unsigned char aftertouch_mode; // 0=channel, 1=poly unsigned char velocity_curve; // 0-3 signed char transpose; // -7 to +7} Page;
typedef struct PageManager { Page pages[4]; unsigned char current_page;} PageManager;Mode State Machine
Section titled “Mode State Machine” ┌──────────────┐ ┌─────────▶│ MODE_PLAY │◀─────────┐ │ └──────┬───────┘ │ │ │ │ Circle released Circle pressed Double released │ │ │ │ ▼ │ │ ┌──────────────┐ │ └──────────│MODE_ROOT_SEL │ │ └──────────────┘ │ │ ┌──────────────┐ │ │MODE_SCALE_SEL│──────────┘ └──────────────┘ ▲ │ Double pressed │ ┌──────┴───────┐ │ MODE_PLAY │ └──────────────┘Component Responsibilities
Section titled “Component Responsibilities”| Component | Responsibility |
|---|---|
app.c | Event routing, MIDI I/O, initialization |
app_state.c | Runtime state management |
page.c | Page configuration and management |
note.c | Scale definitions, note calculations |
layout.c | LED rendering, display updates |
flash.c | Persistence, save/load configuration |
surface.c | Button/pad type detection |
Memory Layout
Section titled “Memory Layout”Flash (128KB)├── Bootloader (fixed)├── SDK Library (launchpad_pro.a)├── PolyBoard Firmware (~24KB)└── User Area (1KB) └── FlashData structure
RAM (20KB)├── Stack (~512 bytes)├── .data (initialized globals)│ └── led_cache[100] (400 bytes)├── .bss (zero-initialized)│ ├── AppState│ ├── PageManager│ └── render_pending└── SDK internal buffersSee Also
Section titled “See Also”- SDK Constraints - Hardware limitations
- Modules Reference - Detailed module documentation
- Contributing Guide - Build and test instructions