soldermaskdocs

Symbols and pins

The model must never tell the pipeline that pin 3 is VIN. That is recall; it is silently wrong sometimes, and nothing downstream can catch it. So the model names pin functions, and symbols.py turns them into pad numbers using the KiCad symbol library.

The library

github.com/KiCad/kicad-symbols in the legacy .lib format, vendored into .cache/kicad-symbols: 203 libraries, several thousand symbols, no KiCad install required. A parsed index of every DEF/ALIAS block is cached in .cache/symbol_index.json (about 42 MB) so a lookup does not touch the files.

Matching a part to a symbol

find(query, pin_count) requires an exact name match or a shared prefix of at least five characters, and a pin count within two of the footprint's pad count (a tab or mounting pad is normal). ICs, transistors and the like are matched; passives, connectors and switches use positional pin names and need no symbol.

When nothing matches, two fallbacks are tried in order and both are reported as notes rather than silently used:

  1. Substitute — a pinout borrowed from a pin-compatible family: symbols in the same package with the same pin count whose pinouts all agree (at least five voters, 90 % agreement, every wanted pin resolvable). The note reads no symbol for 'X', so the pinout is taken from Y — 7 of 7 pin-compatible SOIC-8 parts in Amplifier_Operational wire it this way. Assumed, not verified: check it against the datasheet before ordering. A refusal that quietly became a guess would ship wrong boards rather than reported gaps, so the thresholds are strict.
  2. The part's own symbol — EasyEDA's pinout for the exact LCSC part ordered.

With no symbol at all the board carries a gap: no KiCad symbol matches 'X' — pin functions cannot be verified.

Resolving a pin

resolve_pin(symbol, "VIN") maps a function to a pad. Unit-qualified names (A.OUT, B.-) address multi-unit parts; an unqualified name that exists on several units is refused with a note asking for the unit. Common aliases are accepted — VIN also matches VI, IN, VCC, VDD, V+, VBUS; VOUT, GND, EN, A, K, SDA, SCL, SHIELD likewise — and a loose alias produces a note saying which pin it resolved to.

Where the symbol is the vendor's (an EasyEDA pinout for a FROM_PART part), its names are decorated with everything the pin does — (PCINT0/CLKO/ICP1)PB0, PD0-OSC_IN, LOAD(CS#) — and a design names the pin the way the datasheet's table does. resolve_pins reads those structurally rather than from a table (since 13 Sep 2026, when that gap was 30 of the 130 connections the 11 Sep suite dropped):

  • Spellings of one name. Inversion markers (~{RESET}, ~RESET~, RESET#, nRESET, /RESET, RESET_N), an en-dash for a dash, KiCad's _ for -, a separator inside a name (SEG_A, SEG A), a polarity sign at either end (+IN, IN+) or as a letter (INA+, INPA), and V+/VS+ are the same pin. A match through one of these resolves with a note saying which vendor name it landed on.
  • Tokens of a decorated name. A name split on / ( ) , and on a dash between two names — PB0 finds (PCINT0/CLKO/ICP1)PB0, PD0 finds PD0-OSC_IN. A token is two or more characters and not a bare number, so 1 cannot find A1B12. A token that lands on two pads is refused with both names, the way every other rung refuses a choice.
  • One supply on several pins. GND on a DS3231M is nine pads, VSS on an STM32 is VSS_1, VSS_2, VSS_3; a supply name (GND, VSS, VDD, VCC, VBAT, … with a prefix or number) that lands on several pads of one unit is connected to every one of them, with a note. A signal name on several pads is still a choice and still refused.
  • The datasheet's names beside the vendor's. When the library has the exact part (symbols.exact — the part number, allowing an ordering suffix and KiCad's x), its pins are laid beside the vendor's under the same pad numbers, so VREG_VIN resolves on an RP2040 whose vendor symbol says VREG_IN.
  • USB-C by position. On a connector, A1/B12, A4/B9 and the rest resolve through the standard's table (symbols.USB_C) to the signal the position carries, and every pad found is connected; the design's D+/D- go through the aliases above, which report the reversible-pair choice rather than resolving it quietly.
  • The sheet's own names beside the vendor's (since 21 Sep 2026, datasheets.py). For every vendor symbol with four or more pins, the part's datasheet is fetched from the listing's link, its pin table transcribed once by the design stage's model, and every name the sheet gives a pin — its name and its aliases — laid on the symbol under that number. So VREG_VIN resolves on an RP2040 whose vendor symbol says VREG_IN whether or not KiCad has the part, IO20 on an ESP32-C3 module lands on the pin the vendor calls RXD (the sheet's alias GPIO20), and CS on a DW01A lands on pin 2 (the sheet's other name for VM). A name the symbol already uses for a different number is not added — the sheet's GND alias on a VSS pin would tie two rails. The symbol is compared to the sheet pin by pin at the same time: a pin the two name differently is a note (the datasheet names pin 44 VREG_VIN; the symbol calls it VREG_IN — both names answer), and a swap — the sheet's name for pin 3 is the symbol's name for pin 6 — is a gap that holds both pads back from wiring, because that is what a wrong symbol looks like and wiring it on the symbol's word could short the signal to whatever the sheet says is there. A rail on several pins (GND, IOVDD, VBUS) is never a swap, and a table most of whose pins are swapped is another package's table and is not held against the symbol. Measured on the 226 parts the replay orders: 543 pins compared, 502 the same name, 36 another spelling, 5 a different name, none a different pin. The sheet cannot be read where the pinout is a drawing (most two- and three-pin parts, the Pico's, some ICs) or the PDF is scanned.
  • The last rung. A name still refused after all of the above is looked for in the sheet's function text (a signal named only in a pin's description), and then put to Jev — TypeSafe's closed-question model, jev.py, optional, keyed by TYPESAFE_API_KEY — with the sheet's table beside the symbol, and its answer taken at confidence 0.6 or above with a note saying so and that it is assumed, not verified. Below the floor the refusal stands.

A raw pin number on a part that has a symbol is rejected as unverifiable: pin '3' given as a raw number for a part with a known pinout — symbol says pin 3 is 'VO'; use the function name instead. A number that is a pad the symbol does not model is accepted as a tab or mounting pad, with a note. Two exceptions, both two-pad parts: a crystal, resistor, capacitor or inductor takes 1 and 2 for its ends whatever the symbol calls them, and a switch or connector whose vendor footprint letters its two pads A/B takes 1 and 2 for them with a note. A four-pad crystal's 2 is still refused — its pins 2 and 4 are ground.

Drawing the schematic

The same library supplies the drawings. graphics(name) parses a symbol's DRAW block into rectangles, polylines, arcs, text and pins (in KiCad mils, y up); default_graphics(kind, …) picks a stock symbol for parts that have none — Device:R, Device:C (or C_Polarized for tantalum and electrolytic packages), Device:LED, D_Schottky/D_Zener/D_TVS by value, Crystal_GND24 for four-pin crystals, Connector_Generic:Conn_01x0N. The board carries one symbol table and each component a key into it, so ten resistors are one drawing.

On this page