ClaudeDebug for Spin-Tools
ke4pjw
Posts: 1,293
I used Claude to create a powershell script that can receive P2 Debug data. It can present this data to Claude. Specifically I use Spin-Tools and Claude Code can program the P2 and call this script to review the debug data for integrations tests. The repo is located here:
https://griswoldfx.visualstudio.com/_git/ClaudeP2Debug
I hope others find this useful. I am sure it can easily adapted to Python for cross platform use, but I hate Python so someone else will need to do that. ![]()
P2 Debug Monitor
A headless debug monitor for the Parallax Propeller 2 (P2) microcontroller. Captures DEBUG serial output and emits structured JSON for automated testing and data capture.
Built for Windows users running Spin-Tools (the Spin2/PASM2 IDE and compiler).
What It Does
P2 programs use DEBUG() statements to output formatted text over a serial connection. Normally you view this output in the Spin-Tools IDE terminal. This monitor captures that same output programmatically and converts it into structured JSON lines (JSONL), making it possible to:
- Run automated integration tests against real P2 hardware
- Assert on specific debug values from PowerShell scripts
- Capture and log multi-cog debug output with timestamps
- Parse graphical display commands (SCOPE, PLOT, FFT, etc.) into structured data
- Detect test completion via sentinel strings
Requirements
- Windows 10/11
- PowerShell 5.1+ (included with Windows)
- Spin-Tools with
spinc.exeCLI compiler - Parallax Propeller 2 board connected via USB serial
- USB-serial adapter that supports 2 Mbaud (most FTDI/CH340 adapters work; the adapter built into Parallax P2 boards supports this rate)
Quick Start
1. Write a P2 test program
CON
_clkfreq = 200_000_000
PUB main() | value
waitms(5000) ' Wait for monitor to connect
debug("Hello from P2")
value := 42
debug("Result: ", udec(value))
debug("TEST_DONE") ' Sentinel signals completion
repeat
The waitms(5000) is important -- the P2 starts running immediately after loading, so the delay gives the monitor time to open the serial port.
2. Set up your paths
Define these once for your environment:
SPINC="C:\spin-tools\spinc.exe" MONITOR="./P2DebugMonitor.ps1" COM_PORT=COM4
3. Compile, load, and monitor
Compile and load to RAM, then start the monitor:
"$SPINC" -p $COM_PORT -d -r "MyTest.spin2"
Then immediately start the monitor (the sleep 1 gives spinc time to release the COM port):
sleep 1 && powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$MONITOR" -ComPort $COM_PORT -Sentinel "TEST_DONE" -TimeoutSeconds 20
Or chain both as a single command:
"$SPINC" -p $COM_PORT -d -r "MyTest.spin2" && sleep 1 && powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$MONITOR" -ComPort $COM_PORT -Sentinel "TEST_DONE" -TimeoutSeconds 20
Note:
spinc.exeruns directly from bash -- no PowerShell wrapping needed. Only.ps1scripts requirepowershell.exe -File.
4. Read the output
The monitor emits one JSON object per line to stdout:
{"type":"debug_text","line":1,"timestamp":"...","message":"Hello from P2","raw_line":"Cog0 Hello from P2","cog":0}
{"type":"debug_text","line":2,"timestamp":"...","message":"Result: 42 = 42","raw_line":"Cog0 Result: 42 = 42","cog":0,"values":{"Result":42}}
{"type":"sentinel_match","sentinel":"TEST_DONE","line":3,"message":"Sentinel string detected - ending monitor"}
Values are automatically extracted from P2 DEBUG format specifiers (UDEC, UHEX, SDEC, UBIN, FDEC, BOOL) and placed in the values field as typed JSON values.
Parameters
| Parameter | Default | Description |
|---|---|---|
-ComPort |
required | Serial port (e.g., COM4) |
-BaudRate |
2000000 |
Debug baud rate (P2 default is 2 Mbaud) |
-Sentinel |
"" |
Stop when this string appears in output |
-TimeoutSeconds |
30 |
Max runtime in seconds. 0 = run forever |
-ResetDTR |
$false |
Toggle DTR to reset P2 before monitoring |
-BinaryThreshold |
4 |
Non-printable byte count to trigger binary skip |
-RawMode |
$false |
Include raw hex bytes in output |
Event Types
| Event | Description |
|---|---|
monitor_start |
Startup with configuration |
connected |
Serial port opened |
cog_init |
Cog startup (first DEBUG call per cog) |
debug_text |
Parsed text debug line with extracted values |
display_setup |
Graphical display created (SCOPE, PLOT, etc.) |
display_data |
Data sent to a graphical display |
display_command |
Display lifecycle command (SAVE, CLOSE, CLEAR) |
sentinel_match |
Sentinel string detected |
timeout |
Timeout reached |
error |
Error occurred |
monitor_end |
Shutdown |
Supported DEBUG Formats
The monitor automatically parses values from all P2 DEBUG output commands:
| Spin2 Command | Wire Format | Parsed Value |
|---|---|---|
UDEC(x) |
x = 42 |
42 (integer) |
SDEC(x) |
x = -7 |
-7 (integer) |
UHEX(x) |
x = $DEAD_BEEF |
3735928559 (integer) |
UBIN(x) |
x = %10100101 |
165 (integer) |
FDEC(x) |
x = 3.300000e+00 |
3.3 (float) |
BOOL(x) |
x = TRUE |
true (boolean) |
UDEC_(x) |
42 |
{"val_0": 42} (standalone) |
UHEX_(x) |
$FF |
{"hex_0": 255} (standalone) |
Graphical Displays
The P2 supports 9 graphical debug display types. In Spin-Tools IDE these render as interactive windows. The monitor captures the underlying ASCII commands as structured events.
Spin2 syntax (type comes first, then name):
' Create a SCOPE display named "MyScope" debug(`SCOPE MyScope SAMPLES 10 SIZE 200 100 RANGE 0 255) ' Feed data to it (use just the name) debug(`MyScope `(value)) ' Lifecycle commands debug(`MyScope CLEAR) debug(`MyScope SAVE) debug(`MyScope CLOSE)
Supported types: SCOPE, SCOPE_XY, FFT, SPECTRO, PLOT, LOGIC, BITMAP, TERM, MIDI
The monitor parses these into display_setup, display_data, and display_command events with extracted parameters and sample values.
Scripting Example
# Capture all events
$jsonLines = .\P2DebugMonitor.ps1 -ComPort COM4 -Sentinel "DONE" -TimeoutSeconds 30
$events = $jsonLines | ForEach-Object { $_ | ConvertFrom-Json }
# Filter to text debug events
$debug = $events | Where-Object { $_.type -eq "debug_text" }
# Assert on a value
$result = $debug | Where-Object { $_.values.Result } | Select-Object -First 1
if ($result.values.Result -ne 42) {
throw "Expected Result=42, got $($result.values.Result)"
}
# Verify clean completion
$sentinel = $events | Where-Object { $_.type -eq "sentinel_match" }
if (-not $sentinel) { throw "Test did not complete" }
# Check for serial corruption (should not occur under normal operation)
$binarySkips = $events | Where-Object { $_.type -eq "binary_skipped" }
if ($binarySkips) { Write-Warning "Binary data detected - possible baud mismatch" }
Files
| File | Description |
|---|---|
P2DebugMonitor.ps1 |
The monitor script (self-contained, no dependencies) |
ClaudeDebug_Top.spin2 |
Test program exercising all debug output types |
P2DebugMonitor-UserGuide.md |
Full user documentation |
CLAUDE.md |
Developer context for Claude Code AI assistant |
README.md |
This file |
Documentation
See P2DebugMonitor-UserGuide.md for complete documentation including:
- Detailed setup instructions
- All event schemas with field descriptions
- Writing test programs with examples
- Scripted assertion patterns
- Multi-cog testing
- Graphical display capture
- Troubleshooting guide
Using with Claude Code
Within this project
The CLAUDE.md file in this folder gives Claude Code full context for compiling, loading, and testing P2 programs. All paths in CLAUDE.md are relative to this project directory, so Claude Code resolves them automatically from its working directory.
The key variables are defined at the top of CLAUDE.md:
PROJECT_DIR = (this file's directory) SPINC = "C:\spin-tools\spinc.exe" COM_PORT = COM4
From another project
To let Claude Code use the P2 Debug Monitor from a different project, add a section like this to that project's CLAUDE.md. Replace C:\YourPath\ClaudeDebug with wherever you placed this project:
## P2 Hardware Testing For compiling, loading, and capturing debug output from the Parallax Propeller 2, use the P2 Debug Monitor project. ### Paths ``` CLAUDEDEBUG_DIR = "C:\YourPath\ClaudeDebug" SPINC = "C:\spin-tools\spinc.exe" COM_PORT = COM4 ``` For full protocol docs, event schemas, and integration patterns, read the CLAUDE.md file in CLAUDEDEBUG_DIR. ### Compile and load (bash — spinc.exe runs directly, no PowerShell needed) ```bash "$SPINC" -p $COM_PORT -d -r "path/to/program.spin2" ``` ### Run debug monitor (bash — .ps1 scripts need powershell.exe -File) ```bash sleep 1 && powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$CLAUDEDEBUG_DIR/P2DebugMonitor.ps1" -ComPort $COM_PORT -Sentinel "TEST_COMPLETE" -TimeoutSeconds 30 ``` ### Chained compile + monitor ```bash "$SPINC" -p $COM_PORT -d -r "path/to/program.spin2" && sleep 1 && powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$CLAUDEDEBUG_DIR/P2DebugMonitor.ps1" -ComPort $COM_PORT -Sentinel "TEST_COMPLETE" -TimeoutSeconds 30 ``` ### Important - `spinc.exe` runs directly from bash (no PowerShell wrapping) - Only `.ps1` scripts need `powershell.exe -File` wrapping - P2 programs should include `waitms(5000)` at startup so the monitor can connect before output begins - The `sleep 1` gives spinc.exe time to release the COM port
Adjust the path values at the top to match your setup.
License
This project is provided as-is for use with Parallax Propeller 2 hardware.
