Metadata-Version: 2.4
Name: pcb-crossing-optimizer
Version: 0.4.0
Summary: Multi-layer crossing minimization for PCB connector pin assignment
Author: Asher Garland
License-Expression: MIT
Project-URL: Homepage, https://github.com/ashergarland/pcb-crossing-optimizer
Project-URL: Repository, https://github.com/ashergarland/pcb-crossing-optimizer
Keywords: pcb,kicad,eda,skidl,crossing,routing,pin-assignment
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# PCB Crossing Optimizer

Multi-layer crossing minimization for PCB connector pin assignment. Detects trace crossings in SKiDL-generated KiCad netlists and computes optimal pin orderings for single-layer routing using Sugiyama-style barycenter sweep.

## Installation

```
pip install pcb-crossing-optimizer
```

After installation, the `pcb-crossing-optimizer` command is available on your PATH.

## Usage

The tool has two subcommands: `analyze` (default) and `plan-footprint`.

### analyze (default)

Analyze crossings between component layers. This is the original behavior and remains the default when no subcommand is given.

```
pcb-crossing-optimizer [analyze] <netlist.net> --layers "L0_refs | L1_refs | L2_refs" --reorderable REF [REF ...] [--exclude REF:PIN ...] [--json] [--quiet]
```

Analyze the microSD breakout with passives in the middle layer:
```
pcb-crossing-optimizer examples/microsd_breakout.net --layers "J1 | R1,R2,C1 | J2" --reorderable J2 --exclude J1:SH
```

Simple two-connector case (just use two layers):
```
pcb-crossing-optimizer examples/i2c_breakout.net --layers "J1 | J2" --reorderable J2
```

JSON output for tooling integration:
```
pcb-crossing-optimizer examples/i2c_breakout.net --layers "J1 | J2" --reorderable J2 --json
```

Quiet mode for CI (exit code 0 = no crossings, 1 = crossings remain):
```
pcb-crossing-optimizer examples/i2c_breakout.net --layers "J1 | J2" --reorderable J2 --quiet
```

### plan-footprint

Compute an optimal pin map for a custom footprint. Given a target component (whose footprint you are designing), fixed anchor components, and optional pin locks, it runs the crossing sweep and produces a complete pin-to-net assignment proposal.

```
pcb-crossing-optimizer plan-footprint <netlist.net> \
    --target J1 \
    --anchors "J2,U1 | R1,R2,R3,C1" \
    --lock 1=NC 2=NC 3=GND_EARLY_A \
    --unmatched end \
    --exclude-nets GND \
    [--json] [--quiet]
```

Options:
- `--target REF`: Component whose footprint is being designed
- `--anchors "..."`: Fixed components organized in layers separated by `|`
- `--lock PIN=NET`: Lock specific pins to nets (use `PIN=NC` for no-connect)
- `--unmatched start|end|split`: Where to place pins with no anchor connections (default: `end`)
- `--exclude-nets NET [NET ...]`: Nets to exclude from analysis (e.g. ground pours)

Nets spanning non-adjacent layers (e.g., J1 to J2 through a passive layer)
are handled automatically via virtual pass-through nodes.

## How it works

1. Parses a KiCad .net file (S-expression format generated by SKiDL)
2. Extracts pin-to-net connectivity for specified components
3. Sugiyama-style barycenter sweep across all layers:
   - Inserts virtual nodes for long edges spanning non-adjacent layers
   - Reorders both pins within reorderable components and components within layers
   - Iterates forward/backward sweeps until convergence
4. Reports current crossings, recommended reordering, and remaining crossings

## Project structure

```
src/crossing_analyzer.py    Core logic + CLI
tests/                      pytest tests
examples/                   Sample netlists for testing
```

## Running tests

```
pip install pytest
pytest -v
```

## Roadmap

- Passive placement optimizer (assign positions to resistors/caps in routing channel)
- F.Cu/B.Cu layer assignment for unavoidable crossings
- Migration to skidl-vscode extension (core/crossing.py + MCP tool + VS Code command)

## Python import

The PyPI package name is `pcb-crossing-optimizer`, but the importable module is `crossing_analyzer`:

```python
from crossing_analyzer import sweep_optimize, PinColumn, format_multilayer_report
```
