(version 1)

# Custom Design Rules (DRC) for KiCAD 9.0 (Stored in '<project>.kicad_dru' file).
#
# Matching JLCPCB capabilities: https://jlcpcb.com/capabilities/pcb-capabilities
#
# KiCad documentation: https://docs.kicad.org/master/id/pcbnew/pcbnew_advanced.html#custom_design_rules
#
# Inspiration
# - https://gist.github.com/darkxst/f713268e5469645425eed40115fb8b49 (with comments)
# - https://gist.github.com/denniskupec/e163d13b0a64c2044bd259f64659485e (with comments)
# - https://github.com/labtroll/KiCad-DesignRules/blob/main/JLCPCB/JLCPCB.kicad_dru

# ======================================================================================================
# Drilling and Pads

# Minimum Drill Diameter (All Holes)
# Note that JLCPCB supports drills down to 0.15mm for multilayer boards, but it incurs additional
# cost. This design rule assumes the 0.2mm "preferred" minimum via size callout.
(rule "Hole Diameter"
	(constraint hole_size (min 0.2mm) (max 6.3mm))
)

# Blind/Buried Vias Not Supported
(rule "No Blind or Buried Vias"
	(constraint disallow buried_via)
)

# Minimum Via Diameter
# JLCPCB: "Multilayer: 0.15 mm hole size / 0.25 mm via diameter"
#         "1. Via diameter should be 0.1mm (0.15mm preferred) larger than Via hole size."
#         "2. Preferred Min. Via hole size: 0.2mm"
(rule "Via Diameter"
	(layer outer)
	(condition "A.isPlated() && A.Type == 'Via'")
	(constraint annular_width (min 0.05mm) (opt 0.075mm))
)

# Minimum NPTH
# JLCPCB: "Please draw NPTHs in the mechanical layer or keep out layer."
(rule "Hole (NPTH) Diameter"
	(condition "!A.isPlated()")
	(constraint hole_size (min 0.5mm))
)

# Minimum Plated Slot Width
# JLCPCB: "The minimum plated slot width is 0.5mm, which is drawn with a pad."
(rule "Plated Slot Size"
	(constraint hole_size (min 0.5mm))
	(condition "A.isPlated() && A.Hole_Size_X != A.Hole_Size_Y")
)

# TODO: Plated Slot Minimum Aspect Ratio
# JLCPCB: "The length of the slot should be at least 2 times of the width."

# Minimum Unplated Slot Width
# JLCPCB: "The minimum Non-Plated Slot Width is 1.0mm, please draw the slot outline in the mechanical layer (GM1 or GKO)"
(rule "Unplated Slot Size"
	(constraint hole_size (min 1.0mm))
	(condition "!A.isPlated() && A.Hole_Size_X != A.Hole_Size_Y")
)

# Via Hole-to-Hole Spacing
(rule "Clearance: Via Hole to Hole"
	(layer outer)
	(condition "A.isPlated() && B.isPlated() && A.Type == 'Via' && B.Type == 'Via' && A.Net != B.Net")
	(constraint hole_to_hole (min 0.2mm))
)

# Pad Hole-to-Hole Spacing
(rule "Clearance: Pad Hole to Hole"
	(layer outer)
	(condition "A.isPlated() && B.isPlated() && A.Type == 'Pad' && B.Type == 'Pad' && A.Net != B.Net")
	(constraint hole_to_hole (min 0.45mm))
)

# Castellated Hole Size
# JLCPCB: "Hole diameter (Φ): ≥ 0.5 mm"
# JLCPCB: "Hole to hole (D): ≥ 0.5 mm"
(rule "Castellated Hole Diameter and Spacing"
	(layer outer)
	(condition "A.Type == 'Pad' && A.Fabrication_Property == 'Castellated pad'")
	(constraint hole_size (min 0.5mm))
	(constraint hole_to_hole (min 0.5mm))
)

# TODO: Castellated Hole to Board Edge
# JLCPCB: "Hole to board edge (L): ≥ 1 mm"

# TODO: Castellated Hole Minimum Board Size
# JLCPCB: "Min. PCB size：10 × 10 mm"

# TODO: Castellated Hole Minimum Board Thickness
# JLCPCB: "Min. PCB thickness: 0.6 mm"

# TODO: Blind Slots

# TODO: Slot Minimum Radius
# JLCPCB: "Rectangular holes and slots without rounded corners are not supported."

# ======================================================================================================
# Traces

# Track Width and Spacing (1oz copper outer / 0.5oz copper inner)
# JLCPCB: "Multilayer: 0.09 / 0.09 mm (3.5 / 3.5 mil). 3 mil is acceptable in BGA fan-outs."
# Adjust these down when doing BGA breakouts
(rule "Track Width, Outer Layer, 1oz Copper"
	(layer outer)
	(condition "A.Type == 'track'")
	(constraint track_width (min 0.1mm))
)

(rule "Track Spacing, Outer Layer, 1oz Copper"
	(layer outer)
	(condition "A.Type == 'track' && B.Type == A.Type")
	(constraint clearance (min 0.1mm))
)

(rule "Track Width, Inner Layer, 0.5oz Copper"
	(layer inner)
	(condition "A.Type == 'track'")
	(constraint track_width (min 0.09mm))
)

(rule "Track Spacing, Inner Layer, 0.5oz Copper"
	(layer inner)
	(condition "A.Type == 'track' && B.Type == A.Type")
	(constraint clearance (min 0.09mm))
)

# PTH Annular Ring
# JLCPCB: "1 oz: Recommended 0.20 mm or above; absolute minimum 0.15 mm"
(rule "Annular Ring (PTH), 1.0oz Copper"
	(layer outer)
	(condition "A.isPlated() && A.Type == 'Pad'")
	(constraint annular_width (min 0.15mm) (opt 0.2mm))
)

# NPTH Annular Ring
# JLCPCB: "Recommended 0.45 mm or more. This is to allow a 0.2 mm ring of copper to be removed around the hole for the sealing film to attach. Pad sizes smaller than the recommended value can result in the annular ring being very thin or completely missing."
(rule "Annular Ring (NPTH)"
	(layer outer)
	(condition "!A.isPlated() && A.Type == 'Pad'")
	(constraint annular_width (min 0.45mm))
)

# TODO: BGA Pad Size
# JLCPCB: "1. BGA pad diameter ≥ 0.25 mm"
#         "2. BGA pad to trace clearance ≥ 0.1 mm (min. 0.09 mm for multilayer boards)"
#         "3. Vias can be placed within BGA pads using filled and plated-over vias"

# TODO: Same-Net Track Spacing

# Inner Layer Via to Trace Clearance
(rule "Via to Trace Clearance (Inner Layer)"
	(layer inner)
	(condition "A.Type == 'Via' && B.Type == 'Track' && A.Net != B.Net")
	(constraint hole_clearance (min 0.2mm))
)

# Inner Layer PTH to Trace Clearance
(rule "Hole to Trace Clearance (Inner Layer)"
	(layer inner)
	(condition "A.Type == 'Pad' && B.Type == 'Track' && A.Net != B.Net")
	(constraint hole_clearance (min 0.3mm))
)

# Outer Layer Pad to Track Clearance
# JLCPCB: "Min. 0.1 mm (stay well above if possible). Min. 0.09 mm locally for BGA pads"
(rule "Pad to Trace Clearance (Outer Layer)"
	(layer outer)
	(condition "A.Type == 'Pad' && B.Type == 'Track' && A.Net != B.Net")
	(constraint clearance (min 0.1mm))
)

# SMD Pad-to-Pad Clearance
(rule "Pad to Pad Clearance"
	(layer outer)
	(condition "A.Type == 'Pad' && B.Type == A.Type && A.Net != B.Net")
	(constraint clearance (min 0.15mm))
)

# Outer Layer Via Hole to Trace Clearance
(rule "Via to Trace Clearance (Outer Layer)"
	(layer outer)
	(condition "A.Type == 'Via' && B.Type == 'Track' && A.Net != B.Net")
	(constraint hole_clearance (min 0.2mm))
)

# Outer Layer PTH to Trace Clearance
(rule "PTH to Trace Clearance (Outer Layer)"
	(layer outer)
	(condition "A.isPlated() && A.Type != 'Via' && B.Type == 'Track' && A.Net != B.Net")
	(constraint hole_clearance (min 0.28mm))
)

# Outer Layer NPTH to Trace Clearance
(rule "NPTH to Trace Clearance (Outer Layer)"
	(layer outer)
	(condition "!A.isPlated() && B.Type == 'Track'")
	(constraint hole_clearance (min 0.2mm))
)

# ======================================================================================================
# Silkscreen

# Minimum Line Width
(rule "Silkscreen Minimum Width (Lines)"
	(layer "?.Silkscreen")
	(condition "A.Type == 'Graphic' && A.Line_Width <= 0.153mm")
	(constraint disallow graphic)
)

# Minimum Text Width / Height
(rule "Silkscreen Minimum Width (Text)"
	(layer "?.Silkscreen")
	(condition "A.Type == 'Text' || A.Type == 'TextBox'")
	(constraint text_thickness (min 0.15mm))
	(constraint text_height (min 1mm))
)

# Pad to Silkscreen Clearance
(rule "Pad to Sillkscreen Clearance"
	(layer outer)
	(condition "A.Type == 'Pad' && B.Layer == '?.Silkscreen'")
	(constraint silk_clearance (min 0.15mm))
)

# ======================================================================================================
# Outline

# Copper to Edge Clearance
(rule "Copper to Routed Edge Clearance"
	(condition "A.Type == 'track'")
	(constraint edge_clearance (min 0.2mm))
)

# Copper to V-Cut Clearance
# (rule "Copper to V-Cut Edge Clearance"
# 	(condition "A.Type == 'track'")
# 	(constraint edge_clearance (min 0.4mm))
# )
