crosspad-hil 1.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crosspad_hil-1.8.0/LICENSE +21 -0
- crosspad_hil-1.8.0/PKG-INFO +147 -0
- crosspad_hil-1.8.0/README.md +103 -0
- crosspad_hil-1.8.0/crosspad_hil/__init__.py +5 -0
- crosspad_hil-1.8.0/crosspad_hil/analyze.py +1553 -0
- crosspad_hil-1.8.0/crosspad_hil/audio_nodes.py +535 -0
- crosspad_hil-1.8.0/crosspad_hil/audio_state.py +459 -0
- crosspad_hil-1.8.0/crosspad_hil/bench.py +641 -0
- crosspad_hil-1.8.0/crosspad_hil/ble.py +961 -0
- crosspad_hil-1.8.0/crosspad_hil/board_state.py +115 -0
- crosspad_hil-1.8.0/crosspad_hil/capture.py +821 -0
- crosspad_hil-1.8.0/crosspad_hil/card_hold.py +168 -0
- crosspad_hil-1.8.0/crosspad_hil/cdc.py +626 -0
- crosspad_hil-1.8.0/crosspad_hil/cli.py +1911 -0
- crosspad_hil-1.8.0/crosspad_hil/console.py +476 -0
- crosspad_hil-1.8.0/crosspad_hil/daw_launcher.py +239 -0
- crosspad_hil-1.8.0/crosspad_hil/devices.py +801 -0
- crosspad_hil-1.8.0/crosspad_hil/diagnose.py +774 -0
- crosspad_hil-1.8.0/crosspad_hil/duplex.py +596 -0
- crosspad_hil-1.8.0/crosspad_hil/errors.py +68 -0
- crosspad_hil-1.8.0/crosspad_hil/fixtures.py +296 -0
- crosspad_hil-1.8.0/crosspad_hil/fl_template.py +189 -0
- crosspad_hil-1.8.0/crosspad_hil/fpc.py +745 -0
- crosspad_hil-1.8.0/crosspad_hil/fs.py +262 -0
- crosspad_hil-1.8.0/crosspad_hil/fw_catalog.py +155 -0
- crosspad_hil-1.8.0/crosspad_hil/fw_server.py +662 -0
- crosspad_hil-1.8.0/crosspad_hil/host_gain.py +190 -0
- crosspad_hil-1.8.0/crosspad_hil/host_report.py +74 -0
- crosspad_hil-1.8.0/crosspad_hil/hub_core.py +287 -0
- crosspad_hil-1.8.0/crosspad_hil/hub_ipc.py +327 -0
- crosspad_hil-1.8.0/crosspad_hil/hub_link.py +268 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/__init__.py +13 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/actions.py +134 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/analysis.py +613 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/attribute.py +296 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/bands.py +181 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/bounce.py +102 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/calibration.py +120 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/clocks.py +274 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/control.py +225 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/detect.py +1000 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/model.py +1159 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/monitor.py +119 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/performer.py +273 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/pilot.py +418 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/render.py +184 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/report.py +248 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/restore.py +325 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/script.py +607 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/spec.py +507 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/synth.py +243 -0
- crosspad_hil-1.8.0/crosspad_hil/jam/telemetry.py +259 -0
- crosspad_hil-1.8.0/crosspad_hil/kits.py +346 -0
- crosspad_hil-1.8.0/crosspad_hil/knowledge/__init__.py +43 -0
- crosspad_hil-1.8.0/crosspad_hil/knowledge/cdc.yaml +250 -0
- crosspad_hil-1.8.0/crosspad_hil/knowledge/markers.yaml +84 -0
- crosspad_hil-1.8.0/crosspad_hil/knowledge/sysex.yaml +126 -0
- crosspad_hil-1.8.0/crosspad_hil/latency_math.py +308 -0
- crosspad_hil-1.8.0/crosspad_hil/locks.py +234 -0
- crosspad_hil-1.8.0/crosspad_hil/midi.py +700 -0
- crosspad_hil-1.8.0/crosspad_hil/midi_hub.py +809 -0
- crosspad_hil-1.8.0/crosspad_hil/msc.py +116 -0
- crosspad_hil-1.8.0/crosspad_hil/ota.py +277 -0
- crosspad_hil-1.8.0/crosspad_hil/padmix.py +623 -0
- crosspad_hil-1.8.0/crosspad_hil/parsers.py +988 -0
- crosspad_hil-1.8.0/crosspad_hil/pins.py +111 -0
- crosspad_hil-1.8.0/crosspad_hil/reaper_setup.py +159 -0
- crosspad_hil-1.8.0/crosspad_hil/record.py +285 -0
- crosspad_hil-1.8.0/crosspad_hil/resources.py +33 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/__init__.py +65 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/_audio.py +455 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/_deps.py +180 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/app_churn.py +398 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/audio_loopback.py +620 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/back_churn.py +936 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/base.py +513 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/beat.py +1195 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/beat_session.py +595 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/beat_to_song.py +250 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/ble_midi.py +501 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/daw_control.py +333 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/firmware_app.py +677 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/fs_transfer.py +160 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/fw_switch.py +284 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/fw_update.py +581 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/kit_churn.py +634 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/kit_swap_audio.py +678 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/latency.py +1117 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/led_state.py +110 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/live_jam.py +1313 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/live_set.py +1297 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/midi_bench.py +270 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/midi_clock.py +147 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/midi_stress.py +179 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/midi_trs_loop.py +407 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/pad_edit_sticky.py +205 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/perf.py +566 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/pitched_kit.py +717 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/power_state.py +239 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/release_check.py +440 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/release_gate.py +751 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/rt_glitch.py +559 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/sampler_record.py +621 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/seq_kit_change.py +115 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/smoke.py +166 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/song_bounce.py +189 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/song_elements.py +944 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/speaker_acoustic.py +340 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/speedtest.py +262 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/stability.py +521 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/studio_session.py +1273 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/usb_mode_cycle.py +329 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/velocity.py +383 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/waveform_cache.py +204 -0
- crosspad_hil-1.8.0/crosspad_hil/scenarios/wifi.py +340 -0
- crosspad_hil-1.8.0/crosspad_hil/serial_open.py +332 -0
- crosspad_hil-1.8.0/crosspad_hil/serve.py +1369 -0
- crosspad_hil-1.8.0/crosspad_hil/snapshot.py +180 -0
- crosspad_hil-1.8.0/crosspad_hil/stim.py +814 -0
- crosspad_hil-1.8.0/crosspad_hil/ui.py +365 -0
- crosspad_hil-1.8.0/crosspad_hil/usbmode.py +200 -0
- crosspad_hil-1.8.0/crosspad_hil/verbs.py +2076 -0
- crosspad_hil-1.8.0/crosspad_hil/workflows/__init__.py +157 -0
- crosspad_hil-1.8.0/crosspad_hil/workflows/beat.yaml +285 -0
- crosspad_hil-1.8.0/crosspad_hil/workflows/beat_audio.py +270 -0
- crosspad_hil-1.8.0/crosspad_hil/workflows/beat_fixture.py +134 -0
- crosspad_hil-1.8.0/crosspad_hil.egg-info/PKG-INFO +147 -0
- crosspad_hil-1.8.0/crosspad_hil.egg-info/SOURCES.txt +205 -0
- crosspad_hil-1.8.0/crosspad_hil.egg-info/dependency_links.txt +1 -0
- crosspad_hil-1.8.0/crosspad_hil.egg-info/entry_points.txt +2 -0
- crosspad_hil-1.8.0/crosspad_hil.egg-info/requires.txt +20 -0
- crosspad_hil-1.8.0/crosspad_hil.egg-info/top_level.txt +1 -0
- crosspad_hil-1.8.0/pyproject.toml +75 -0
- crosspad_hil-1.8.0/setup.cfg +4 -0
- crosspad_hil-1.8.0/tests/test_analyze.py +420 -0
- crosspad_hil-1.8.0/tests/test_analyze_sine.py +182 -0
- crosspad_hil-1.8.0/tests/test_analyze_tone_tracks.py +299 -0
- crosspad_hil-1.8.0/tests/test_audio_nodes.py +301 -0
- crosspad_hil-1.8.0/tests/test_audio_state.py +312 -0
- crosspad_hil-1.8.0/tests/test_bench.py +393 -0
- crosspad_hil-1.8.0/tests/test_ble.py +446 -0
- crosspad_hil-1.8.0/tests/test_ble_alsa.py +206 -0
- crosspad_hil-1.8.0/tests/test_board_state.py +55 -0
- crosspad_hil-1.8.0/tests/test_capture.py +626 -0
- crosspad_hil-1.8.0/tests/test_card_hold.py +137 -0
- crosspad_hil-1.8.0/tests/test_cdc.py +591 -0
- crosspad_hil-1.8.0/tests/test_cli.py +500 -0
- crosspad_hil-1.8.0/tests/test_cli_capture.py +254 -0
- crosspad_hil-1.8.0/tests/test_console.py +422 -0
- crosspad_hil-1.8.0/tests/test_console_timed.py +42 -0
- crosspad_hil-1.8.0/tests/test_daw_launcher.py +140 -0
- crosspad_hil-1.8.0/tests/test_devices.py +622 -0
- crosspad_hil-1.8.0/tests/test_diagnose.py +398 -0
- crosspad_hil-1.8.0/tests/test_duplex_source.py +54 -0
- crosspad_hil-1.8.0/tests/test_ensure_kits.py +295 -0
- crosspad_hil-1.8.0/tests/test_errors.py +60 -0
- crosspad_hil-1.8.0/tests/test_fakes.py +89 -0
- crosspad_hil-1.8.0/tests/test_fixtures.py +138 -0
- crosspad_hil-1.8.0/tests/test_fl_template.py +112 -0
- crosspad_hil-1.8.0/tests/test_fpc.py +282 -0
- crosspad_hil-1.8.0/tests/test_fw_catalog.py +229 -0
- crosspad_hil-1.8.0/tests/test_fw_server.py +502 -0
- crosspad_hil-1.8.0/tests/test_host_gain.py +155 -0
- crosspad_hil-1.8.0/tests/test_host_report.py +55 -0
- crosspad_hil-1.8.0/tests/test_hub_core.py +254 -0
- crosspad_hil-1.8.0/tests/test_hub_ipc.py +278 -0
- crosspad_hil-1.8.0/tests/test_hub_link.py +218 -0
- crosspad_hil-1.8.0/tests/test_kits.py +191 -0
- crosspad_hil-1.8.0/tests/test_knowledge.py +298 -0
- crosspad_hil-1.8.0/tests/test_latency_units.py +465 -0
- crosspad_hil-1.8.0/tests/test_locks.py +162 -0
- crosspad_hil-1.8.0/tests/test_midi.py +450 -0
- crosspad_hil-1.8.0/tests/test_midi_hub.py +938 -0
- crosspad_hil-1.8.0/tests/test_msc.py +70 -0
- crosspad_hil-1.8.0/tests/test_ota.py +333 -0
- crosspad_hil-1.8.0/tests/test_padmix.py +216 -0
- crosspad_hil-1.8.0/tests/test_parsers_cdc.py +619 -0
- crosspad_hil-1.8.0/tests/test_parsers_console.py +347 -0
- crosspad_hil-1.8.0/tests/test_parsers_enc.py +73 -0
- crosspad_hil-1.8.0/tests/test_parsers_song.py +56 -0
- crosspad_hil-1.8.0/tests/test_pins.py +48 -0
- crosspad_hil-1.8.0/tests/test_reaper_setup.py +118 -0
- crosspad_hil-1.8.0/tests/test_record.py +193 -0
- crosspad_hil-1.8.0/tests/test_resources.py +33 -0
- crosspad_hil-1.8.0/tests/test_scenario_app_churn.py +472 -0
- crosspad_hil-1.8.0/tests/test_scenario_back_churn.py +703 -0
- crosspad_hil-1.8.0/tests/test_scenario_firmware_app.py +333 -0
- crosspad_hil-1.8.0/tests/test_scenario_fw_switch.py +343 -0
- crosspad_hil-1.8.0/tests/test_scenario_fw_update.py +258 -0
- crosspad_hil-1.8.0/tests/test_scenario_kit_churn.py +545 -0
- crosspad_hil-1.8.0/tests/test_scenario_kit_swap_audio.py +348 -0
- crosspad_hil-1.8.0/tests/test_scenario_led_state.py +127 -0
- crosspad_hil-1.8.0/tests/test_scenario_perf.py +440 -0
- crosspad_hil-1.8.0/tests/test_scenario_release_gate.py +395 -0
- crosspad_hil-1.8.0/tests/test_scenario_smoke.py +226 -0
- crosspad_hil-1.8.0/tests/test_scenario_usb_mode_cycle.py +352 -0
- crosspad_hil-1.8.0/tests/test_scenario_waveform_cache.py +118 -0
- crosspad_hil-1.8.0/tests/test_scenario_wifi.py +172 -0
- crosspad_hil-1.8.0/tests/test_scenarios_base.py +537 -0
- crosspad_hil-1.8.0/tests/test_serial_open.py +156 -0
- crosspad_hil-1.8.0/tests/test_serve.py +461 -0
- crosspad_hil-1.8.0/tests/test_serve_capture.py +218 -0
- crosspad_hil-1.8.0/tests/test_snapshot.py +195 -0
- crosspad_hil-1.8.0/tests/test_stim.py +524 -0
- crosspad_hil-1.8.0/tests/test_ui.py +122 -0
- crosspad_hil-1.8.0/tests/test_usbmode.py +193 -0
- crosspad_hil-1.8.0/tests/test_verbs.py +1231 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CrossPad contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: crosspad-hil
|
|
3
|
+
Version: 1.8.0
|
|
4
|
+
Summary: Talk to a CrossPad: discovery, console, CDC verbs, MIDI SysEx, USB mode, OTA, HIL scenarios, CLI and NDJSON daemon
|
|
5
|
+
Author: CrossPad contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/CrossPad/crosspad-hil
|
|
8
|
+
Project-URL: Repository, https://github.com/CrossPad/crosspad-hil
|
|
9
|
+
Project-URL: Issues, https://github.com/CrossPad/crosspad-hil/issues
|
|
10
|
+
Keywords: crosspad,hil,hardware-in-the-loop,midi,sysex,esp32,embedded,testing
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: MIDI
|
|
21
|
+
Classifier: Topic :: Software Development :: Embedded Systems
|
|
22
|
+
Classifier: Topic :: Software Development :: Testing
|
|
23
|
+
Classifier: Topic :: System :: Hardware
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: pyserial>=3.5
|
|
28
|
+
Requires-Dist: python-rtmidi>=1.5
|
|
29
|
+
Requires-Dist: pydantic>=2
|
|
30
|
+
Requires-Dist: pyyaml>=6
|
|
31
|
+
Provides-Extra: audio
|
|
32
|
+
Requires-Dist: sounddevice>=0.4; extra == "audio"
|
|
33
|
+
Requires-Dist: numpy>=1.24; extra == "audio"
|
|
34
|
+
Requires-Dist: scipy>=1.10; extra == "audio"
|
|
35
|
+
Provides-Extra: ble
|
|
36
|
+
Requires-Dist: bleak>=0.21; extra == "ble"
|
|
37
|
+
Provides-Extra: all
|
|
38
|
+
Requires-Dist: crosspad-hil[audio,ble]; extra == "all"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-xdist>=3.6; extra == "dev"
|
|
42
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# crosspad-hil
|
|
46
|
+
|
|
47
|
+
Python library, CLI and NDJSON daemon that talks to a CrossPad (ESP32-S3 pad
|
|
48
|
+
controller): device discovery, the STM32-bridge console with boot/fatal
|
|
49
|
+
parsers, CDC verbs, MIDI SysEx, USB profile switching, OTA flashing, a lease
|
|
50
|
+
for sharing one board, and the hardware-in-the-loop scenario suite. Every
|
|
51
|
+
hardware trap (DTR/RTS reboots the ESP, `OK` is not your ack, CDC vanishes in
|
|
52
|
+
UAC2 mode, `F0 7D 19 01 F7` hangs the STM bridge) is encoded once here and
|
|
53
|
+
inherited by the CLI, the scenarios and crosspad-mcp.
|
|
54
|
+
|
|
55
|
+
Not on PyPI yet; install from git (Python 3.10 or newer; the Windows commands
|
|
56
|
+
are on the site):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python3 -m venv .venv && . .venv/bin/activate
|
|
60
|
+
pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"
|
|
61
|
+
crosspad-hil doctor
|
|
62
|
+
crosspad-hil devices
|
|
63
|
+
crosspad-hil run smoke
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Documentation
|
|
67
|
+
|
|
68
|
+
The docs live at **https://crosspad.app/docs/**:
|
|
69
|
+
|
|
70
|
+
- Install and first smoke test: [Set up the toolchain](https://crosspad.app/docs/start-here/1-toolchain/), [Check it works](https://crosspad.app/docs/start-here/4-check/)
|
|
71
|
+
- Run scenarios, read reports, share a bench: [Test on hardware (HIL)](https://crosspad.app/docs/how-to/hil-testing/)
|
|
72
|
+
- Every command and its common options: [Command-line tools § crosspad-hil](https://crosspad.app/docs/reference/cli/#crosspad-hil)
|
|
73
|
+
- When it fails: [Troubleshooting § Checks and tests](https://crosspad.app/docs/troubleshooting/#checks-and-tests)
|
|
74
|
+
- The firmware side: [Hardware-in-the-loop testing](https://crosspad.app/docs/subsystems/hil-testing/)
|
|
75
|
+
|
|
76
|
+
In this repo: [docs/bench.md](docs/bench.md) (the bench lease and the hub in full),
|
|
77
|
+
[docs/padmix.md](docs/padmix.md) (levelling kits from the computer),
|
|
78
|
+
[docs/host-tools.md](docs/host-tools.md) (`kit push`, FPC presets,
|
|
79
|
+
`companion`, `midi hub`, `audio nodes`, `fl template`) and the scenario notes
|
|
80
|
+
under [docs/](docs/). Design: [the crosspad-mcp v10 spec](https://github.com/CrossPad/crosspad-mcp/blob/master/docs/superpowers/specs/2026-08-25-crosspad-hil-and-mcp-v10-design.md).
|
|
81
|
+
|
|
82
|
+
## Scenarios
|
|
83
|
+
|
|
84
|
+
This list is the reference for `crosspad-hil run`, so it stays here: it
|
|
85
|
+
mirrors the registry in `crosspad_hil/scenarios/__init__.py`, and a new
|
|
86
|
+
scenario adds its row in the same change. `crosspad-hil run <name> --help`
|
|
87
|
+
lists a scenario's flags. Exit code **0** passed, **1** the firmware failed,
|
|
88
|
+
**2** the bench is wrong; audio, BLE and raw-ALSA scenarios need the `[all]`
|
|
89
|
+
extras and exit 2 naming what is missing without them.
|
|
90
|
+
`platform-idf/tools/hil_*.py` are thin shims over these.
|
|
91
|
+
|
|
92
|
+
| Scenario | What it does |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `app_churn` | open/close every app repeatedly; per-app internal-heap slope + crash watch |
|
|
95
|
+
| `audio_loopback` | play a multitone through the UAC2 endpoints and judge the return signal; it sets the host gain and the jack's preamp itself, see [docs/scenarios/audio_loopback.md](docs/scenarios/audio_loopback.md) |
|
|
96
|
+
| `back_churn` | descend into every app (and the sampler's file explorer, Settings, the drawer) and click the power button back out, one level per click; crash / core-dump watch + per-target heap slope |
|
|
97
|
+
| `beat` | make a beat end to end from one YAML (`crosspad_hil/workflows/beat.yaml`, also played on the simulator): a loop it writes itself is sliced in the Slicer, exported as a kit, loaded, recorded as a pattern in a song of its own, bounced and checked hit by hit, plus the theme; `--depth quick` (a few minutes) / `medium` (pad editor, overdub, x2, mixer, song edits) / `full` (erase, scenes, a song of scenes, an import, a Live-set export); the song, kit, app, desk and theme are put back |
|
|
98
|
+
| `ble_midi` | drive BLE MIDI both ways from this PC's radio, in both of the board's roles |
|
|
99
|
+
| `daw_control` | DAW Control app over the ESP MIDI port: hello reply, `led_all` painting matches `LED_STATE`, a simulated pad press/release turns into NoteOn/NoteOff, `text` doesn't upset the app |
|
|
100
|
+
| `firmware_app` | the Firmware app end to end, driven with the encoder and read through `FW_UI`: 30 test packages pushed to the card and listed in the Library, a kit card (pin, unpin, delete from card), a Store download in a normal boot and in network mode, the PSRAM budget, churn |
|
|
101
|
+
| `fs_transfer` | round-trip a file over CDC: proves host and device CRCs agree and that framing returns to text after a binary stream; `--assets` reflashes the assets partition |
|
|
102
|
+
| `fw_switch` | install a package for the running build from the SD card (`FW_INSTALL`), switch OTA slots and back (`FW_SWITCH`), and check the same image comes back (`APP_SHA`); the package must already be on the card |
|
|
103
|
+
| `fw_update` | firmware updates end to end: serves CI-signed packages of the board's kit and revision from this machine (`crosspad_hil.fw_server`), points the board at it with `FW_UPD_URL`, and checks the catalog, resumable verified downloads, signature refusals, cleanup, install and the network-mode fallback; the bench WiFi comes from `$CROSSPAD_WIFI_SSID` / `$CROSSPAD_WIFI_PASS` |
|
|
104
|
+
| `kit_churn` | swap kits while the pads keep firing; `--rapid` spins the selector |
|
|
105
|
+
| `kit_swap_audio` | swap kits while pads fire, recorded through UAC2, scored per tone: every hit audible, no hole over `--max-gap-ms`, no pad reloaded mid-sample; builds and pushes its own sine fixtures when the card lacks them (`--no-provision` to refuse) |
|
|
106
|
+
| `latency` | pad -> jack and host -> jack: notes on the STM bridge and noise bursts into UAC OUT, timed on the board's own DAC->ADC loop by a duplex stream with a clock log; median/p95/max per path, the capture ring the board reports (`SPK #` cap_ring) subtracted, underruns split out; `--max-pad-ms` / `--max-host-ms` gate. Puts back the kit, app and Mixer desk. See [docs/latency.md](docs/latency.md) for what it does and does not measure |
|
|
107
|
+
| `led_state` | dump the LED controller model (colours, brightness, anim, power state) |
|
|
108
|
+
| `live_jam` | A live setup, listened to sample by sample (~20 min): the host streams a pilot + timecode through the board's mixer while a beat is built and performed (REC with count-in, overdub, scenes, DOUBLE/ERASE, song, MIDI clock Stop/Continue/Start), pads in every style, every kit feature (pitch, reverse, filters, pan, volume, choke, hold, loop, layers, slice), sampler and pitched swaps, previews, desk presets, an app switch, a stream pause, bounces over SysEx and CDC, the Recorder; USB IN recorded digitally (`sampler` bus) and every voice held against a model of the engines: each glitch with its frame, wall clock, board log ms, step, action and cause; counters gated at zero; everything put back (sequences.json, desk/NVS, preset slots, project) and journalled first. `crosspad-hil jam script|analyze|synth|kits` without a board. See [docs/scenarios/live_jam.md](docs/scenarios/live_jam.md) |
|
|
109
|
+
| `live_set` | the full live setup (~30 min): per phase (one pad fast / four pads / all 16 + chords / pitched) a bounce window in the default profile (a scene of the phase's pads at 120 BPM, bounced while the pads play, the file pulled and scored, the scene restarted) and a live block in USB audio (host stream on `crosspad_out`, USB IN recorded with the board's own routing and checked for clicks, holes and every struck pad audible, kit swaps incl. sampler↔pitched); zero tolerance on SPK under/refused, engine underrun/noblock, swap late/dropped hits and rt_gap, pad-path drops, resets; normalises the bench first and puts everything back |
|
|
110
|
+
| `midi_bench` | echo-frame throughput and latency on the ESP port, the STM bridge, and both |
|
|
111
|
+
| `midi_clock` | send a host MIDI clock at several tempos (`--bpms`, default 90,120,174): the board follows it (`CLOCK_STATUS` src=host, bpm within 0.1 %, every tick counted), then takes over on its own clock when the host stops |
|
|
112
|
+
| `midi_stress` | burst SysEx queries at the ESP MIDI port and count the replies (RX loss) |
|
|
113
|
+
| `pad_edit_sticky` | the Sampler's pad editor: a setting in edit mode (CHOKE) stays in edit mode across pad hits, and one detent changes it on the next pad |
|
|
114
|
+
| `perf` | kit swap HIL SINE A↔B timed by the device (`KIT_SWAP_LOG` median `done_ms`): over CDC, then in the USB-audio profile with `pw-play` streaming into the board (swaps via companion `KIT_LOAD`); plus the sample engine's init at boot (`EngineHandoff` control block → started). FAIL with the numbers above `--max-cdc-ms` (2000), `--max-uac-ratio` (1.2× CDC) or `--max-init-ms` (500) |
|
|
115
|
+
| `pitched_kit` | load the pitched-instrument fixture kit, record it through UAC2 and check each pad's pitch, a 16-pad chord and `PITCHED_STATUS` (steals, RT budget, root detection) |
|
|
116
|
+
| `power_state` | STM power path without a person: BQ25895 profile held past its 80 s watchdog, no profile re-apply, no STM reset, no stuck USB_SUSPENDED / SHIP_PENDING, LED1 in AUTO (STM 1.9 power debug words via `STM_REG`) |
|
|
117
|
+
| `release_check` | a published release seen from the bench board: crosspad.app lists the tag for its revision and kit, `FW_CHECK` over CDC and SysEx, `FW_UPD_STATUS` / `FW_LATEST` name it; `--install` (or a board already on that tag) downloads it into the other slot, switches in, checks `APP_VERSIONS` against the release and switches back |
|
|
118
|
+
| `release_gate` | the whole chain in one report: smoke → power_state → app_churn → back_churn → kit_churn → perf → usb_mode_cycle → ble_midi → audio_loopback → stability; per-step budgets from the rounds, a stuck step is cancelled then abandoned, the USB profile is restored before every step; `--quick` for a CI-length dry run, `--keep-going` overnight |
|
|
119
|
+
| `rt_glitch` | phased UAC2 capture: clicks under pad/LED load that a held pad does not have |
|
|
120
|
+
| `sampler_record` | record the sampler through the board's own UAC2 endpoint and score it |
|
|
121
|
+
| `seq_kit_change` | record a take in a scene of its own, load another kit while it plays and then the first one back: every hit stays, and the scenes are stored outside the kits folder |
|
|
122
|
+
| `smoke` | reset, capture the boot log, check markers / E-lines / fatals / boot loops |
|
|
123
|
+
| `song_bounce` | record a scene, bounce it to the audio song (`ASONG BOUNCE`), play the song, then STOP/PLAY it hard: no underruns, every clip opens, no reset (`RESET_LOG`) |
|
|
124
|
+
| `speaker_acoustic` | record the built-in mics while the sampler plays; did the speaker sound? |
|
|
125
|
+
| `speedtest` | ramp the pad hit rate until the device drops hits, per pad set |
|
|
126
|
+
| `stability` | soak: watch the console for resets, fatals, stalls, bad boots and heap drift |
|
|
127
|
+
| `studio_session` | the studio session of 21.10.2026 played on the screen (`--fixture`): kit, pad trims and copies, a pattern, a bounce into a new song, line-in onto the arrangement, a chopped sample, the mix and an Ableton Live Set export; every control found with `UI_TREE` and tapped, the knob turned, the pads hit; state verbs only read the result, and the song, kit and take are deleted afterwards |
|
|
128
|
+
| `usb_mode_cycle` | cycle CDC+MIDI <-> MIDI+UAC2 and watch enumeration, heap and faults |
|
|
129
|
+
| `velocity` | sweep pad velocity and measure loudness, monotonicity and trigger jitter |
|
|
130
|
+
| `waveform_cache` | load kits and check every pad layer gets its waveform cached (`WAVE_STATUS`); `--play` keeps the pads firing meanwhile |
|
|
131
|
+
| `wifi` | WiFi on demand in a normal boot: join, ping, a wrong password fails cleanly, the memory comes back, BLE hands over and back; then one pass through network mode (`NET_MODE`); the bench network comes from `$CROSSPAD_WIFI_SSID` / `$CROSSPAD_WIFI_PASS` |
|
|
132
|
+
|
|
133
|
+
## Development
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
python3 -m venv .venv && . .venv/bin/activate
|
|
137
|
+
pip install -e ".[dev,audio]"
|
|
138
|
+
ruff check . && pytest
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Tests need no hardware: `tests/fakes.py` provides `FakeSerial`, `FakeMidiOut`
|
|
142
|
+
and `FakeMidiIn`. A change that breaks a docs page (command, output, path)
|
|
143
|
+
opens an issue in CrossPad/crosspad-docs.
|
|
144
|
+
|
|
145
|
+
## License
|
|
146
|
+
|
|
147
|
+
MIT, see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# crosspad-hil
|
|
2
|
+
|
|
3
|
+
Python library, CLI and NDJSON daemon that talks to a CrossPad (ESP32-S3 pad
|
|
4
|
+
controller): device discovery, the STM32-bridge console with boot/fatal
|
|
5
|
+
parsers, CDC verbs, MIDI SysEx, USB profile switching, OTA flashing, a lease
|
|
6
|
+
for sharing one board, and the hardware-in-the-loop scenario suite. Every
|
|
7
|
+
hardware trap (DTR/RTS reboots the ESP, `OK` is not your ack, CDC vanishes in
|
|
8
|
+
UAC2 mode, `F0 7D 19 01 F7` hangs the STM bridge) is encoded once here and
|
|
9
|
+
inherited by the CLI, the scenarios and crosspad-mcp.
|
|
10
|
+
|
|
11
|
+
Not on PyPI yet; install from git (Python 3.10 or newer; the Windows commands
|
|
12
|
+
are on the site):
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
python3 -m venv .venv && . .venv/bin/activate
|
|
16
|
+
pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"
|
|
17
|
+
crosspad-hil doctor
|
|
18
|
+
crosspad-hil devices
|
|
19
|
+
crosspad-hil run smoke
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Documentation
|
|
23
|
+
|
|
24
|
+
The docs live at **https://crosspad.app/docs/**:
|
|
25
|
+
|
|
26
|
+
- Install and first smoke test: [Set up the toolchain](https://crosspad.app/docs/start-here/1-toolchain/), [Check it works](https://crosspad.app/docs/start-here/4-check/)
|
|
27
|
+
- Run scenarios, read reports, share a bench: [Test on hardware (HIL)](https://crosspad.app/docs/how-to/hil-testing/)
|
|
28
|
+
- Every command and its common options: [Command-line tools § crosspad-hil](https://crosspad.app/docs/reference/cli/#crosspad-hil)
|
|
29
|
+
- When it fails: [Troubleshooting § Checks and tests](https://crosspad.app/docs/troubleshooting/#checks-and-tests)
|
|
30
|
+
- The firmware side: [Hardware-in-the-loop testing](https://crosspad.app/docs/subsystems/hil-testing/)
|
|
31
|
+
|
|
32
|
+
In this repo: [docs/bench.md](docs/bench.md) (the bench lease and the hub in full),
|
|
33
|
+
[docs/padmix.md](docs/padmix.md) (levelling kits from the computer),
|
|
34
|
+
[docs/host-tools.md](docs/host-tools.md) (`kit push`, FPC presets,
|
|
35
|
+
`companion`, `midi hub`, `audio nodes`, `fl template`) and the scenario notes
|
|
36
|
+
under [docs/](docs/). Design: [the crosspad-mcp v10 spec](https://github.com/CrossPad/crosspad-mcp/blob/master/docs/superpowers/specs/2026-08-25-crosspad-hil-and-mcp-v10-design.md).
|
|
37
|
+
|
|
38
|
+
## Scenarios
|
|
39
|
+
|
|
40
|
+
This list is the reference for `crosspad-hil run`, so it stays here: it
|
|
41
|
+
mirrors the registry in `crosspad_hil/scenarios/__init__.py`, and a new
|
|
42
|
+
scenario adds its row in the same change. `crosspad-hil run <name> --help`
|
|
43
|
+
lists a scenario's flags. Exit code **0** passed, **1** the firmware failed,
|
|
44
|
+
**2** the bench is wrong; audio, BLE and raw-ALSA scenarios need the `[all]`
|
|
45
|
+
extras and exit 2 naming what is missing without them.
|
|
46
|
+
`platform-idf/tools/hil_*.py` are thin shims over these.
|
|
47
|
+
|
|
48
|
+
| Scenario | What it does |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `app_churn` | open/close every app repeatedly; per-app internal-heap slope + crash watch |
|
|
51
|
+
| `audio_loopback` | play a multitone through the UAC2 endpoints and judge the return signal; it sets the host gain and the jack's preamp itself, see [docs/scenarios/audio_loopback.md](docs/scenarios/audio_loopback.md) |
|
|
52
|
+
| `back_churn` | descend into every app (and the sampler's file explorer, Settings, the drawer) and click the power button back out, one level per click; crash / core-dump watch + per-target heap slope |
|
|
53
|
+
| `beat` | make a beat end to end from one YAML (`crosspad_hil/workflows/beat.yaml`, also played on the simulator): a loop it writes itself is sliced in the Slicer, exported as a kit, loaded, recorded as a pattern in a song of its own, bounced and checked hit by hit, plus the theme; `--depth quick` (a few minutes) / `medium` (pad editor, overdub, x2, mixer, song edits) / `full` (erase, scenes, a song of scenes, an import, a Live-set export); the song, kit, app, desk and theme are put back |
|
|
54
|
+
| `ble_midi` | drive BLE MIDI both ways from this PC's radio, in both of the board's roles |
|
|
55
|
+
| `daw_control` | DAW Control app over the ESP MIDI port: hello reply, `led_all` painting matches `LED_STATE`, a simulated pad press/release turns into NoteOn/NoteOff, `text` doesn't upset the app |
|
|
56
|
+
| `firmware_app` | the Firmware app end to end, driven with the encoder and read through `FW_UI`: 30 test packages pushed to the card and listed in the Library, a kit card (pin, unpin, delete from card), a Store download in a normal boot and in network mode, the PSRAM budget, churn |
|
|
57
|
+
| `fs_transfer` | round-trip a file over CDC: proves host and device CRCs agree and that framing returns to text after a binary stream; `--assets` reflashes the assets partition |
|
|
58
|
+
| `fw_switch` | install a package for the running build from the SD card (`FW_INSTALL`), switch OTA slots and back (`FW_SWITCH`), and check the same image comes back (`APP_SHA`); the package must already be on the card |
|
|
59
|
+
| `fw_update` | firmware updates end to end: serves CI-signed packages of the board's kit and revision from this machine (`crosspad_hil.fw_server`), points the board at it with `FW_UPD_URL`, and checks the catalog, resumable verified downloads, signature refusals, cleanup, install and the network-mode fallback; the bench WiFi comes from `$CROSSPAD_WIFI_SSID` / `$CROSSPAD_WIFI_PASS` |
|
|
60
|
+
| `kit_churn` | swap kits while the pads keep firing; `--rapid` spins the selector |
|
|
61
|
+
| `kit_swap_audio` | swap kits while pads fire, recorded through UAC2, scored per tone: every hit audible, no hole over `--max-gap-ms`, no pad reloaded mid-sample; builds and pushes its own sine fixtures when the card lacks them (`--no-provision` to refuse) |
|
|
62
|
+
| `latency` | pad -> jack and host -> jack: notes on the STM bridge and noise bursts into UAC OUT, timed on the board's own DAC->ADC loop by a duplex stream with a clock log; median/p95/max per path, the capture ring the board reports (`SPK #` cap_ring) subtracted, underruns split out; `--max-pad-ms` / `--max-host-ms` gate. Puts back the kit, app and Mixer desk. See [docs/latency.md](docs/latency.md) for what it does and does not measure |
|
|
63
|
+
| `led_state` | dump the LED controller model (colours, brightness, anim, power state) |
|
|
64
|
+
| `live_jam` | A live setup, listened to sample by sample (~20 min): the host streams a pilot + timecode through the board's mixer while a beat is built and performed (REC with count-in, overdub, scenes, DOUBLE/ERASE, song, MIDI clock Stop/Continue/Start), pads in every style, every kit feature (pitch, reverse, filters, pan, volume, choke, hold, loop, layers, slice), sampler and pitched swaps, previews, desk presets, an app switch, a stream pause, bounces over SysEx and CDC, the Recorder; USB IN recorded digitally (`sampler` bus) and every voice held against a model of the engines: each glitch with its frame, wall clock, board log ms, step, action and cause; counters gated at zero; everything put back (sequences.json, desk/NVS, preset slots, project) and journalled first. `crosspad-hil jam script|analyze|synth|kits` without a board. See [docs/scenarios/live_jam.md](docs/scenarios/live_jam.md) |
|
|
65
|
+
| `live_set` | the full live setup (~30 min): per phase (one pad fast / four pads / all 16 + chords / pitched) a bounce window in the default profile (a scene of the phase's pads at 120 BPM, bounced while the pads play, the file pulled and scored, the scene restarted) and a live block in USB audio (host stream on `crosspad_out`, USB IN recorded with the board's own routing and checked for clicks, holes and every struck pad audible, kit swaps incl. sampler↔pitched); zero tolerance on SPK under/refused, engine underrun/noblock, swap late/dropped hits and rt_gap, pad-path drops, resets; normalises the bench first and puts everything back |
|
|
66
|
+
| `midi_bench` | echo-frame throughput and latency on the ESP port, the STM bridge, and both |
|
|
67
|
+
| `midi_clock` | send a host MIDI clock at several tempos (`--bpms`, default 90,120,174): the board follows it (`CLOCK_STATUS` src=host, bpm within 0.1 %, every tick counted), then takes over on its own clock when the host stops |
|
|
68
|
+
| `midi_stress` | burst SysEx queries at the ESP MIDI port and count the replies (RX loss) |
|
|
69
|
+
| `pad_edit_sticky` | the Sampler's pad editor: a setting in edit mode (CHOKE) stays in edit mode across pad hits, and one detent changes it on the next pad |
|
|
70
|
+
| `perf` | kit swap HIL SINE A↔B timed by the device (`KIT_SWAP_LOG` median `done_ms`): over CDC, then in the USB-audio profile with `pw-play` streaming into the board (swaps via companion `KIT_LOAD`); plus the sample engine's init at boot (`EngineHandoff` control block → started). FAIL with the numbers above `--max-cdc-ms` (2000), `--max-uac-ratio` (1.2× CDC) or `--max-init-ms` (500) |
|
|
71
|
+
| `pitched_kit` | load the pitched-instrument fixture kit, record it through UAC2 and check each pad's pitch, a 16-pad chord and `PITCHED_STATUS` (steals, RT budget, root detection) |
|
|
72
|
+
| `power_state` | STM power path without a person: BQ25895 profile held past its 80 s watchdog, no profile re-apply, no STM reset, no stuck USB_SUSPENDED / SHIP_PENDING, LED1 in AUTO (STM 1.9 power debug words via `STM_REG`) |
|
|
73
|
+
| `release_check` | a published release seen from the bench board: crosspad.app lists the tag for its revision and kit, `FW_CHECK` over CDC and SysEx, `FW_UPD_STATUS` / `FW_LATEST` name it; `--install` (or a board already on that tag) downloads it into the other slot, switches in, checks `APP_VERSIONS` against the release and switches back |
|
|
74
|
+
| `release_gate` | the whole chain in one report: smoke → power_state → app_churn → back_churn → kit_churn → perf → usb_mode_cycle → ble_midi → audio_loopback → stability; per-step budgets from the rounds, a stuck step is cancelled then abandoned, the USB profile is restored before every step; `--quick` for a CI-length dry run, `--keep-going` overnight |
|
|
75
|
+
| `rt_glitch` | phased UAC2 capture: clicks under pad/LED load that a held pad does not have |
|
|
76
|
+
| `sampler_record` | record the sampler through the board's own UAC2 endpoint and score it |
|
|
77
|
+
| `seq_kit_change` | record a take in a scene of its own, load another kit while it plays and then the first one back: every hit stays, and the scenes are stored outside the kits folder |
|
|
78
|
+
| `smoke` | reset, capture the boot log, check markers / E-lines / fatals / boot loops |
|
|
79
|
+
| `song_bounce` | record a scene, bounce it to the audio song (`ASONG BOUNCE`), play the song, then STOP/PLAY it hard: no underruns, every clip opens, no reset (`RESET_LOG`) |
|
|
80
|
+
| `speaker_acoustic` | record the built-in mics while the sampler plays; did the speaker sound? |
|
|
81
|
+
| `speedtest` | ramp the pad hit rate until the device drops hits, per pad set |
|
|
82
|
+
| `stability` | soak: watch the console for resets, fatals, stalls, bad boots and heap drift |
|
|
83
|
+
| `studio_session` | the studio session of 21.10.2026 played on the screen (`--fixture`): kit, pad trims and copies, a pattern, a bounce into a new song, line-in onto the arrangement, a chopped sample, the mix and an Ableton Live Set export; every control found with `UI_TREE` and tapped, the knob turned, the pads hit; state verbs only read the result, and the song, kit and take are deleted afterwards |
|
|
84
|
+
| `usb_mode_cycle` | cycle CDC+MIDI <-> MIDI+UAC2 and watch enumeration, heap and faults |
|
|
85
|
+
| `velocity` | sweep pad velocity and measure loudness, monotonicity and trigger jitter |
|
|
86
|
+
| `waveform_cache` | load kits and check every pad layer gets its waveform cached (`WAVE_STATUS`); `--play` keeps the pads firing meanwhile |
|
|
87
|
+
| `wifi` | WiFi on demand in a normal boot: join, ping, a wrong password fails cleanly, the memory comes back, BLE hands over and back; then one pass through network mode (`NET_MODE`); the bench network comes from `$CROSSPAD_WIFI_SSID` / `$CROSSPAD_WIFI_PASS` |
|
|
88
|
+
|
|
89
|
+
## Development
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
python3 -m venv .venv && . .venv/bin/activate
|
|
93
|
+
pip install -e ".[dev,audio]"
|
|
94
|
+
ruff check . && pytest
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Tests need no hardware: `tests/fakes.py` provides `FakeSerial`, `FakeMidiOut`
|
|
98
|
+
and `FakeMidiIn`. A change that breaks a docs page (command, output, path)
|
|
99
|
+
opens an issue in CrossPad/crosspad-docs.
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT, see [LICENSE](LICENSE).
|