Build an app
SDK 1.xWritten for core 1.53+ and gui 1.23+.
Goal: an app of your own that runs on the CrossPad and in the PC simulator, opens cleanly on every visit, and can be installed by anyone.
You need: Start here done, or only the PC simulator to begin with. You know C++; you do not need to know CrossPad’s insides. LVGL, the UI library every screen is built with, is explained where a recipe uses it.
A CrossPad app is two C++ functions, one that builds the app’s screen and one that takes it down, plus one line that registers them. The same source builds into the firmware and into the simulator. Apps are compiled in, not loaded at run time: you add the app to a firmware or simulator checkout and rebuild.
What you can build
Section titled “What you can build”Four kinds of app, and the recipes that show each one. Every recipe is one small, complete app from the examples repo (about 150 to 250 lines of C++), and the page walks through its code.
| You want | It does | Start with |
|---|---|---|
| An instrument | Plays sound from the pads and lights them | Pads and LEDs, then Play a sample |
| A MIDI controller | Turns pads and tilting the board into MIDI for a computer or a synth | MIDI out, then Motion and vibration |
| A sequencer or tool | Follows the tempo and answers PLAY and STOP | Tempo and transport |
| An app with a UI | Screens, buttons and dialogs that look like the rest of the CrossPad | Hello screen, then UI kit |
What each recipe teaches:
| Recipe | You learn |
|---|---|
| Hello screen | REGISTER_APP, building and tearing down a screen, the encoder, the power button, closing the app from inside |
| Pads and LEDs | REGISTER_APP_PL, IPadLogicHandler, pad colours, PadAnimator, passing pad data to the screen safely |
| Play a sample | The current kit (IKitManager), postSamplePlayback, playing through the Sampler’s pad logic |
| MIDI out | getMidiOutput(): notes, control change, pitch bend, and no hanging notes |
| Tempo and transport | transportTempo, TempoChanged (EventTypes), the smallest ITransportTarget, claiming PLAY and giving it back |
| Motion and vibration | MotionGesture events (EventData), reading IImu, IVibration presets, running without the sensors |
| UI kit | CrossPad’s design tokens (cp_design), toasts (ui_toast), a confirm dialog (ui_modal), ui_back_push, postToGui from another task |
More recipes are on the way.
The path
Section titled “The path”-
Hello screen. Build the smallest app and run it in the simulator and on the board: Hello screen.
-
How an app works. The lifecycle in the order the framework runs it, which task runs your code, and the memory rules: How an app works. Read it before your app does more than draw a screen: its rules keep an app reliable from the first visit to the hundredth.
-
The recipe for your kind of app. Pick it from the table above. Hardware for apps maps every part of the board to the API that reaches it.
-
Make it your own. Copy the example closest to your idea and give it its own id, name and repo: Make an example your own. Or begin from an empty app: Start from the template.
-
Publish. Get your app into the app catalog: Publish an app.
Where the examples live
Section titled “Where the examples live”Every recipe’s app is in crosspad-examples, one folder per recipe (examples/01-hello-screen/ and so on). Each folder is a complete app with its manifest, icon, sources and a host test. tools/install.py copies examples into a simulator or firmware checkout, where the build finds them like any other app.
git clone https://github.com/CrossPad/crosspad-examples.gitcd crosspad-examplespython3 tools/install.py --target pc ~/crosspad-pc # every example, into the simulatorpython3 tools/install.py --target pc ~/crosspad-pc hello-screen # or one, by its namepython3 tools/install.py --target idf ~/CrossPad # into the firmware projectgit clone https://github.com/CrossPad/crosspad-examples.gitcd crosspad-examplespython tools\install.py --target pc C:\crosspad-pc # every example, into the simulatorpython tools\install.py --target pc C:\crosspad-pc hello-screen # or one, by its namepython tools\install.py --target idf C:\CrossPad\firmware # into the firmware projectYou should see: one line per example, such as installed example-hello-screen -> …/src/apps/crosspad-example-hello-screen (simulator) or …/components/crosspad-example-hello-screen (firmware).
Each copy carries a .crosspad-example marker file. --remove takes the examples out again and touches only folders with that marker. The build finds new apps only when it configures from scratch: rebuild the simulator with cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug && cmake --build build, and the firmware after idf.py -B build_v2 fullclean (v2 board) or idf.py -B build_v1 fullclean (v1). Each recipe’s “Run it” sections give the full commands.
The board holds at most 24 apps, built-in ones included. A firmware with every bundled app registers 15, which leaves room for 9 more, so install the examples you want to try. The firmware build prints Generated app_registry_init.cpp with N apps: … while it configures (one more, Power OFF, is added at run time); Limits has the details.
Opening an app
Section titled “Opening an app”- Simulator: every app has a tile in the simulator’s launcher. Click it, or choose it with the simulated encoder: roll the mouse wheel (one notch per tile, row by row) and press the middle mouse button. Escape puts the launcher’s choice back on its first tile.
- CrossPad: hit pad 1 on the MODE map to open the Sampler, then start your app over USB with
crosspad-hil app start YourApp, from the crosspad-hil venv of 1. Set up the toolchain. Each recipe’s “Run it on the CrossPad” section has the full step. From another app, open yours withmode_overlay_open_app("YourApp").
The App API
Section titled “The App API”The App API reference lists every header an app uses, generated from crosspad-core and crosspad-gui: pads and LEDs, events, MIDI, transport, samples, platform services, the app base, dialogs and the MODE map. Every recipe links the parts it uses.
To turn an example into an app of your own, see Make an example your own. To start from an empty app instead, see Start from the template.