A Rust library and command-line tool for PCB design calculations — impedance, current capacity, via properties, and more.
Formulas are implemented from the published literature and cited in the source.
Saturn PCB Toolkit was the starting point and is still a
useful cross-check, but it is not a specification — where it is wrong, we do not match it.
The second reference is the set of Mathcad worksheets shipped with Johnson & Graham's
High-Speed Digital Design, which is where the non-planar lines, Cohn's stripline, the
signal-integrity rules of thumb, loop inductance and plane spreading resistance come from.
See Relationship to Saturn PCB Toolkit below, and VALIDATION.md for what is verified
against what.
| Crate | Description |
|---|---|
pcb-toolkit |
Core library: calculators, material database, unit conversion |
pcb-toolkit-cli |
Command-line interface wrapping the library |
pcb-toolkit-desktop |
Tauri desktop GUI (apps/desktop) |
A GUI covering every calculator lives in apps/desktop:
cd apps/desktop
npm install
npm run tauri dev
See apps/desktop/README.md for building installers.
Requires Rust 1.85+ (edition 2024).
cargo build --workspace
The CLI binary is called pcb-toolkit. All commands support --json for
machine-readable output. Dimensional inputs accept units: 10mil, 0.254mm,
1GHz, 10nF, etc.
pcb-toolkit <COMMAND> [OPTIONS]
impedance Transmission line impedance (microstrip, stripline, embedded, coplanar)
differential Differential pair impedance (5 topologies)
current Conductor current capacity (IPC-2221A)
fusing Fusing current (Onderdonk equation)
via Via impedance and parasitic properties
inductor Planar spiral inductor
loop Single-turn loop inductance (circular or rectangular)
wire Round wire over a plane, coax, twisted pair
signal Knee frequency, critical length, reflections, Er from delay
resistance Plane spreading resistance
reactance Capacitive/inductive reactance and resonant frequency
wavelength Wavelength in a dielectric
ohms-law V=IR, LED bias, attenuators, series/parallel R/C/L
ppm PPM/Hz conversion, crystal load capacitance
padstack Padstack geometry (thru-hole, corner-to-corner)
spacing Conductor spacing (IPC-2221C)
wire-gauge AWG wire gauge properties
pdn PDN impedance calculator
thermal Thermal management (junction temperature)
crosstalk Crosstalk estimation (NEXT)
$ pcb-toolkit signal knee -t 0.35
Signal Edge Bandwidth
─────────────────────
Rise time = 0.3500 ns
F_knee = 1428.5714 MHz
A 350 ps edge is a 1.4 GHz design problem whatever the clock rate, and on FR-4 stripline the longest run you can leave unterminated is:
$ pcb-toolkit signal critical-length -t 0.35 --tpd 180
Critical Length
───────────────
L_crit = 0.3241 in
L_crit = 8.2315 mm
Flight = 0.0583 ns (= Tr/6)
Longer runs should be treated as transmission lines.
$ pcb-toolkit impedance microstrip -w 10 --height 5 --er 4.6
Microstrip Impedance
────────────────────
Zo = 44.8322 Ω
Er_eff = 3.3075
Tpd = 154.0858 ps/in
Lo = 6.9080 nH/in
Co = 3.4369 pF/in
$ pcb-toolkit differential edge-coupled-external -w 10 --spacing 10 --height 5 -t 1.4mil --er 4.6
Edge-Coupled External Differential
───────────────────────────────────
Zdiff = 76.3503 Ω
Zo = 41.0649 Ω
Zodd = 38.1751 Ω
Zeven = 44.1735 Ω
Kb = 0.072841
Kb = -22.7525 dB
Kb_term = 0.036469
Kb_term = -28.7616 dB
$ pcb-toolkit pdn --voltage 5 --current 2 --i-step 50 --v-ripple 5 --area 5 --er 4.6 --distance 2 --freq 1
PDN Impedance
─────────────
Z target = 0.250000 Ω
C plane = 2587.5000 pF
Xc = 61.509157 Ω
$ pcb-toolkit --json impedance microstrip -w 10 --height 5 --er 4.6
{
"zo": 44.8322367013137,
"er_eff": 3.307496138618308,
"tpd_ps_per_in": 154.08582451095563,
"lo_nh_per_in": 6.908012156792247,
"co_pf_per_in": 3.4369426075598972
}
Add the dependency:
[dependencies]
pcb-toolkit = "0.1"use pcb_toolkit::impedance::microstrip::{self, MicrostripInput};
let result = microstrip::calculate(&MicrostripInput {
width: 10.0, // mils
height: 5.0, // mils
thickness: 1.4, // mils (1 oz copper)
er: 4.6, // FR-4
frequency: 0.0, // Hz (0 = static)
}).unwrap();
println!("Zo = {:.2} Ohms", result.zo);
println!("Er_eff = {:.4}", result.er_eff);All public functions return Result<T, CalcError>. Inputs are validated at the
boundary — negative dimensions, out-of-range dielectric constants, and unknown
materials are rejected with descriptive errors.
45 built-in substrate materials with dielectric constant (Er), glass transition temperature (Tg), and surface roughness correction factor. Includes FR-4 variants, Rogers, Isola, Getek, Arlon, Nelco, Ventec, Panasonic, and Teflon.
use pcb_toolkit::materials;
let fr4 = materials::lookup("FR-4 STD").unwrap();
assert_eq!(fr4.er, 4.6);
assert_eq!(fr4.tg, Some(130.0));Lookup is case-insensitive. Custom Er values can be passed directly to calculator functions.
This project started by reverse-engineering Saturn PCB Toolkit, and Saturn is still a useful
source of formulas and test geometries. It is not a compatibility target — it is wrong in
places (its crosstalk calculator is high by 48×; its internal differential coefficient is a
transposition of the published value; it carries π = 3.14159 and c = 11.8 in/ns). We implement
the published model with full-precision constants, and document every divergence with its
numerical cause in docs/notes/18-v847-vs-rust-comparison.md.
Practically, that means our impedances run about 0.069% below Saturn's (we use µ₀c = 376.7303 Ω where it uses 120π) and our delays about 0.025% below (exact c, not 11.8 in/ns).
- f64 everywhere. IEEE 754 double precision for all calculations. No arbitrary-precision or unit-of-measure crates.
- Canonical internal units. Mils for length, Hz for frequency, Farads for
capacitance. Conversion happens at the API boundary via the
unitsmodule. - Minimal dependencies.
thiserror+serdefor the library.clap+anyhow+serde_json+tomlfor the CLI.
cargo test --workspace
Test a specific calculator:
cargo test -p pcb-toolkit impedance
Float comparisons use the approx crate (assert_relative_eq!). Reference vectors come from
the Saturn PCB Toolkit help PDF, from standard tables (AWG, IPC-2221C), and from closed forms
worked by hand; VALIDATION.md lists which calculators have which. The CLI has its own
integration tests in crates/pcb-toolkit-cli/tests/cli.rs that drive the real binary.
Licensed under either of Apache License, Version 2.0 or MIT License at your option.