Files
2026-08-28 17:17:54 +02:00

158 lines
7.7 KiB
Plaintext

(version 1)
# SP1 edge-connector (J3): the gold fingers must reach the board edge to make
# contact in the GameCube slot, so copper-to-edge clearance is intentionally
# relaxed for this footprint only. This is by design, not a defect.
# Test BOTH items because the violated pair is (Edge.Cuts segment of J3) vs (pad
# of J3) - the edge segment is item A, the pad is item B.
(rule "SP1 gold fingers - allow copper to board edge"
(condition "A.memberOfFootprint('J3') || B.memberOfFootprint('J3')")
(constraint edge_clearance (min -0.5mm)))
# Reverse-mount LED light-windows (D6/D7/D8/D9/D11/D12/D13, Everlight 24-21).
# Each footprint has an Edge.Cuts light-window cutout under the LED body; the
# datasheet land places the solder pads ~0.15mm from that cutout - below the
# JLCPCB 0.3mm copper-to-edge default, but the intended, manufacturer-recommended
# geometry (the copper sits under the part, not exposed). Relax edge_clearance to
# 0.1mm for these footprints so the deliberate geometry doesn't spam DRC, while
# still catching a genuinely-too-tight future edit (<0.1mm). Test BOTH items: the
# violated pair is (pad) vs (the footprint's own Edge.Cuts window segment).
(rule "Reverse-mount LED light-window - allow pad-to-cutout clearance"
(condition "A.memberOfFootprint('D6') || A.memberOfFootprint('D7') || A.memberOfFootprint('D8') || A.memberOfFootprint('D9') || A.memberOfFootprint('D11') || A.memberOfFootprint('D12') || A.memberOfFootprint('D13') || B.memberOfFootprint('D6') || B.memberOfFootprint('D7') || B.memberOfFootprint('D8') || B.memberOfFootprint('D9') || B.memberOfFootprint('D11') || B.memberOfFootprint('D12') || B.memberOfFootprint('D13')")
(constraint edge_clearance (min 0.1mm)))
# Power-integrity: flag any power-rail track narrower than its netclass width.
# A netclass "track width" is only the DEFAULT for new routing - KiCad does NOT
# enforce it - so without these rules an under-width power trace passes DRC
# silently. These make DRC surface every thin power segment so they don't have to
# be found by eye. Severity is "warning" (not error) so an unavoidable neck into a
# fine-pitch pin is flagged for review but never blocks fab export.
(rule "Power rail minimum width (0.3mm)"
(severity warning)
(condition "A.NetClass == 'Power'")
(constraint track_width (min 0.3mm)))
(rule "Low-current power rail minimum width (0.25mm)"
(severity warning)
(condition "A.NetClass == 'PowerLV'")
(constraint track_width (min 0.25mm)))
# ---------------------------------------------------------------------------
# JLCPCB manufacturing capability floor (standard multi-layer tier), pulled
# from jlcpcb.com/capabilities/pcb-capabilities. These are "the board cannot
# physically be made this way" limits, not house-style margins - severity is
# "error" because violating one means a rejected/reworked fab order, not just
# a style nit. They sit BELOW the netclass defaults above (0.2-0.3mm), so on
# a board routed to house style they should never fire; they exist as a
# backstop for hand-tweaked geometry (e.g. necking into a fine-pitch pin)
# that dips below what JLCPCB can actually etch/drill.
#
# NOT covered here (no DRC constraint type exists for these - check manually
# before ordering):
# - Board thickness: JLCPCB stocks 0.6/0.8/1.0/1.2/1.6/2.0mm. This board's
# stackup sums to 1.1412mm, which is NOT one of those - confirm with
# JLCPCB's stackup tool (their impedance-controlled 4-layer config can
# produce non-stock totals like this deliberately) before ordering.
# - Solder mask minimum bridge/dam width (0.10mm standard, 0.13mm black/
# white): no matching KiCad custom-rule constraint type as of this
# version.
# - NPTH minimum hole size (0.50mm): skipped - no confirmed condition
# syntax to select NPTH-only pads without risking a rule that silently
# never matches; the general hole_size floor below still catches any
# NPTH hole below the PTH/via floor, just not the tighter 0.50mm NPTH-
# specific one.
(rule "JLCPCB min copper trace width (0.09mm)"
(severity error)
(constraint track_width (min 0.09mm)))
(rule "JLCPCB min copper clearance (0.09mm)"
(severity error)
(constraint clearance (min 0.09mm)))
(rule "JLCPCB min via/PTH drill (0.15mm)"
(severity error)
(constraint hole_size (min 0.15mm)))
(rule "JLCPCB min via pad diameter (0.25mm)"
(severity error)
(constraint via_diameter (min 0.25mm)))
(rule "JLCPCB min hole-to-hole spacing (0.2mm)"
(severity error)
(constraint hole_to_hole (min 0.2mm)))
(rule "JLCPCB min hole-to-copper clearance (0.2mm)"
(severity error)
(constraint hole_clearance (min 0.2mm)))
(rule "JLCPCB min silkscreen line/text thickness (0.15mm, front)"
(severity warning)
(layer "F.SilkS")
(constraint text_thickness (min 0.15mm)))
(rule "JLCPCB min silkscreen line/text thickness (0.15mm, back)"
(severity warning)
(layer "B.SilkS")
(constraint text_thickness (min 0.15mm)))
(rule "JLCPCB min silkscreen text height (1.0mm, front)"
(severity warning)
(layer "F.SilkS")
(constraint text_height (min 1.0mm)))
(rule "JLCPCB min silkscreen text height (1.0mm, back)"
(severity warning)
(layer "B.SilkS")
(constraint text_height (min 1.0mm)))
(rule "JLCPCB min silkscreen-to-pad clearance (0.15mm, front)"
(severity warning)
(layer "F.SilkS")
(constraint silk_clearance (min 0.15mm)))
(rule "JLCPCB min silkscreen-to-pad clearance (0.15mm, back)"
(severity warning)
(layer "B.SilkS")
(constraint silk_clearance (min 0.15mm)))
# ---------------------------------------------------------------------------
# Differential pair geometry vs calculated target impedance. The USB_DP/ETH_DP
# netclasses (0.25/0.15mm, 0.2/0.14mm) only set the DEFAULT for new routing -
# same caveat as the power-rail rules above, KiCad does not enforce a
# netclass's width/gap on already-routed copper. These rules close that gap:
# they check the geometry actually laid down, not just what a fresh route
# would use, so re-routing to the wrong default (the original bug that had
# USB sitting at ~113ohm on the Default netclass's 0.2/0.25mm) gets caught by
# DRC instead of requiring another hand calculation to notice.
#
# Target values and their impedance were derived by hand (IPC-2141-style
# edge-coupled microstrip formula) from this board's actual stackup - F.Cu/
# B.Cu are symmetric microstrip over In1.Cu/In2.Cu respectively (both 0.2104mm
# FR4 dielectrics, same εr), so one target pair covers a net whether it's
# routed on F.Cu or briefly detours to B.Cu for a crossover. Severity is
# "error": these two nets only exist to hit a controlled-impedance target, so
# missing it isn't a style nit like the power-rail/silkscreen rules above -
# it's the one thing the routing was actually for.
# USB_DP: 0.25mm width / 0.15mm gap -> ~91ohm (target 90ohm +/-15%)
# ETH_DP: 0.20mm width / 0.14mm gap -> ~100ohm (target 100ohm +/-15%)
# track_width +/-0.02mm tolerance bands are routing precision, not re-derived
# targets. diff_pair_gap has a min (catches traces routed too close, below fab
# clearance) and opt, but intentionally NO max: a gap-max false-flags normal pad
# fanout, where P/N necessarily diverge over a sub-mm stub right at the pads
# before converging into the coupled run - KiCad can't tell that apart from a
# genuinely uncoupled long run (a length-matching/loss question, not one this
# board-wide per-segment rule can judge). Do NOT re-add a diff_pair_gap max.
(rule "USB differential pair width/gap (target ~90ohm)"
(severity error)
(condition "A.NetClass == 'USB_DP'")
(constraint track_width (min 0.23mm) (opt 0.25mm) (max 0.27mm))
(constraint diff_pair_gap (min 0.13mm) (opt 0.15mm)))
(rule "Ethernet differential pair width/gap (target ~100ohm)"
(severity error)
(condition "A.NetClass == 'ETH_DP'")
(constraint track_width (min 0.18mm) (opt 0.20mm) (max 0.22mm))
(constraint diff_pair_gap (min 0.12mm) (opt 0.14mm)))