Platform parity
The PC simulator runs the same crosspad-core and crosspad-gui code as the firmware, so app logic, UI and settings behave the same on both. The differences are in the hardware edges: the simulator replaces pads, LEDs, storage, MIDI and audio with desktop equivalents, and has no co-processor, firmware update or sensor hardware. Develop in the simulator first, then confirm on the board. The layers themselves are in Architecture.
Why the edges differ
Section titled “Why the edges differ”Parity comes from the layer split. Everything above the platform interfaces is the same source code on both targets. Everything below them is an adapter: Esp* classes on the firmware, Pc* classes in the simulator. When the two platforms behave differently, look at the adapter first.
Both platforms also pin the core and gui versions they were written against. A major mismatch stops the build, and minor drift prints a warning. So a difference you see is usually a real platform difference, not two different copies of core.
Feature matrix
Section titled “Feature matrix”| Feature | Hardware (platform-idf) | Simulator (crosspad-pc) |
|---|---|---|
| UI, apps | crosspad-gui on the LCD; apps open from the MODE map | same crosspad-gui in an SDL2 window; apps open from the launcher |
| Pads | STM32 scan over UART SysEx | keyboard and mouse in the STM32 emulator window |
| Encoder | hardware encoder | mouse wheel (turn) and middle click (press) |
| LED strip | EspLedStrip | PcLedStrip |
| Settings storage | NVS (NvsSettingsStore) | PcKeyValueStore: ~/.crosspad/preferences.json (%USERPROFILE%\.crosspad\ on Windows) |
| Settings categories | 10–11 built-in from crosspad-gui, plus Motion MIDI, BLE MIDI, WiFi and Updates | the same built-ins except Analog / Velocity and USB, plus USB / UART and Bluetooth MIDI |
| USB MIDI | TinyUSB MIDI, plus MIDI through the STM32 (EspStm32Midi*) | PcMidi (RtMidi) |
| BLE MIDI | EspBleMidi | PcBleMidi (SimpleBLE) |
| Audio out / in | codec over I2S, USB audio (UAC2) | RtAudio; on Linux also virtual PipeWire/PulseAudio devices |
| Vibration | DRV2605 driver, instantiated | none |
| IMU | EspImu (see Hardware for apps) | none |
| Firmware update | CDC OTA and delta OTA | not applicable (PcUpdater updates the simulator itself from GitHub Releases) |
| STM32 firmware | bundled in the ESP image, updated at boot | not applicable |
| Remote control for tools | USB CDC commands | TCP on 127.0.0.1:19840 |
A few rows need a word of explanation.
Pads and encoder. The simulator draws the whole device in one window: LCD, pad grid and encoder. You press pads with the keyboard or the mouse, turn the encoder with the mouse wheel and press it with a middle click. The firmware gets the same events from the STM32 over UART SysEx, so your app sees no difference.
Settings. Both platforms store settings through IKeyValueStore, so a setting your app saves works on both. The settings screen is not identical. The simulator hides Analog / Velocity and USB, because it has no STM32 to configure and no USB audio. It adds its own USB / UART and Bluetooth MIDI pages instead. The firmware adds Motion MIDI, BLE MIDI, WiFi and Updates.
Audio. The firmware plays through the codec over I2S and through USB audio. The simulator uses RtAudio on every desktop. On Linux it also creates virtual PipeWire or PulseAudio devices, so you can route its audio into other programs. Windows and macOS get RtAudio only.
Updates. The firmware updates itself over CDC OTA, including delta updates, and updates the STM32 from the bundled image at boot. The simulator has no firmware to update. Its PcUpdater updates the simulator program itself from GitHub Releases.
What the simulator does not have
Section titled “What the simulator does not have”The simulator has no STM32 co-processor. It has no IStm32Transport, no charger and no power path. It also has no vibration motor and no IMU, so it implements neither IVibration nor IImu. An app that uses them checks isAvailable() first, and runs in the simulator without them.
The bundled apps differ between the two platforms. Each platform pulls its own list of apps in as submodules: platform-idf’s .gitmodules on main for the firmware, crosspad-pc’s .gitmodules on master for the simulator.
| Platform | Bundled apps |
|---|---|
| Firmware (platform-idf, components) | instructions, sampler, mixer, dawcontrol, arrange, pad-mixer, song, sequencer, recorder, slicer, pitchplay |
| Simulator (crosspad-pc, submodules) | piano, instructions, appstore, serial-monitor, mixer, sampler, dawcontrol, pad-mixer, arrange, sequencer, song |
Most apps are on both. Recorder, slicer and pitchplay are on the firmware only. Piano, appstore and serial-monitor are in the simulator only, and the App Store app is part of development builds of the simulator. To add a catalog app to your firmware, see Install and remove apps.
Apps you write, and the examples, build into both from the same source. Where they open differs: the simulator gives every app a tile in its launcher; on the board each bundled app has its own pad on the MODE map. Opening an app shows how to open yours, and Build an app starts there.
The App catalog lists the platforms of every registry app.
The sampler runs with full audio on the firmware. The Synthesizer app is part of the Arduino variant.
Host platforms for the simulator
Section titled “Host platforms for the simulator”The simulator targets Linux and Windows first. Its releases ship a Windows zip and a Linux AppImage, and the PC simulator page covers building it on both.
The simulator also builds and runs on macOS; Linux and Windows are the primary targets. Its virtual serial ports (USB/UART) are available on Windows.
What only the board can tell you
Section titled “What only the board can tell you”The simulator answers the question “does my app logic work?”. It cannot answer questions about the hardware. Timing, audio latency, power and charging, and the STM32 link need a real board.
Run those checks on hardware before you call a feature done. Test on hardware (HIL) checks them automatically. For where your code should live so that it runs on both platforms, see Where code belongs.