exocortex

Footprint verification: EXO-410 / EXO-420 land patterns

Checked 2026-10-27 against exo/pcb/footprints.py and exo/pcb/footprints.json (the two match: the JSON is exactly what FP serialises to). Net assignments come from exo/pcb/circuit.py. Placement and layer handling come from exo/pcb/place.py and pcb/tile.mjs. Paste and mask behaviour was read from the tscircuit and circuit-json-to-gerber sources in pcb/node_modules and checked against the generated out/pcb/*/circuit.json and gerbers.

Nothing was edited. This document only proposes changes. Each FIX gets one severity:

  • (a) cosmetic: harmless, or affects only docs or firmware conventions.
  • (b) fit risk: fix before ordering. The board would probably work but has a real yield or assembly risk.
  • (c) definite error: the board would fail.

Route impact is given for each item. Several of the most important fixes change only paste and mask. They can go into the gerber export step (pcb/export.mjs, pcb/tile.mjs) without touching copper, so the EXO-410 route stays valid.

Summary

# Footprint / topic Verdict Severity Copper change?
1 Solder paste everywhere (tscircuit default: paste = 0.7 x pad on each axis, 49 % of the area) FIX (b) no (export step)
2 SMT nut M1.6: paste is a Ø2.94 disc centred on the Ø2.5 NPTH, so most of it falls over the hole FIX (b), high priority no (export step)
3 Solder mask: opening = pad, with 0 expansion FIX (b) no (export step)
4 PAT9125EL pin 9 (TEST): no pad, which is correct, but no copper keep-out under it FIX (b) no pads; route keep-out
5 SMT nut NPTH Ø2.50 nominal; the maker's spec is 2.50 +0.08/-0 FIX (b), low drill only
6 HCTL FPC 12P: tab width is 0.30 in the drawing (it is dimensioned); we use 0.60 FIX (a) yes (EXO-420 only)
7 FPC pin-1 end and cable type: reversing the pinout shorts VIN (pins 1-2) to GND (pins 11-12) CHECK (b) system no
8 PAT9125EL pin-1 pad is 0.85 long with a chamfer in the drawing; ours is 0.75 FIX (a) yes
9 PAT9125EL footprint is the datasheet top view rotated 180° (not mirrored) note (a) firmware axis signs no
10 Hirose DF40C-10DS receptacle OK none none
11 Hirose DF40C-10DP header OK none none
12 DF40 stacking (pin k over pin k, every corner and both layers) OK none none
13 TI ADS131M08 RSN0032B (WQFN-32) OK (copper); EP paste covered by #1 none none
14 RP2040 QFN-56 OK (copper); EP paste covered by #1 none none
15 SC70-5 (MCP6V31U, SN74LVC1G17) non-IPC but works (a) yes (only if re-routing anyway)
16 Small notes: stale docstring, shape: "round" ignored, header fittings tied to GND, missing LCSC for the DF40 header FIX (a) no

No (c) items were found. Copper geometry and pin numbering are correct on every footprint, and the DF40 pairs mate pin for pin. The real risks are assembly yield, which is items 1-3 and the nut paste in particular, and the TEST pad keep-out (item 4).

Sources

Part Document URL
ADS131M08 TI SBAS950B (Feb 2021), Table 5-1, RSN0032B outline, example board layout and stencil (4219109/B) https://www.ti.com/lit/ds/symlink/ads131m08.pdf
RP2040 RP2040 datasheet §5.1.2 Fig. 167 "Recommended PCB Footprint"; §5.5.2.2 Table 615 pin list https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf
DF40 Hirose DF40 series catalogue (official link) https://www.hirose.com/en/product/document?clcode=&productname=&series=DF40&documenttype=Catalog&lang=en&documentid=en_DF40_CAT
DF40 Same catalogue, Aug 1 2019 edition (LCSC mirror, readable without JS): p. 4 receptacle, 1.5 mm stacking; p. 10 header https://datasheet.lcsc.com/datasheet/pdf/1bc3798b3f2b73ba5fac135b6f4f3547.pdf?productCode=C424638
DF40C-10DS-0.4V(51) DigiKey listing (status Active) https://www.digikey.com/en/products/detail/hirose-electric-co-ltd/DF40C-10DS-0-4V-51/1969478
DF40B-10DS-0.4V(51) DigiKey listing (the version with reinforcing fittings) https://www.digikey.com/en/products/detail/hirose-electric-co-ltd/DF40B-10DS-0-4V-51/1967921
DF40C-10DP-0.4V(51) LCSC C424635 https://www.lcsc.com/product-image/C424635.html
PAT9125EL PixArt datasheet v1.2 (31 May 2017): Fig. 2 pin configuration, Table 1, Fig. 9 package outline (p. 9) https://www.epsglobal.com/Media-Library/EPSGlobal/Products/files/pixart/PAT9125EL-TKITPAT9125EL-TKMT.pdf?ext=.pdf
HC-FPC-05-10-12RLTAG HCTL drawing HC-FPC-05-10-NRLTAG rev A, "Recommend PCB layout" (LCSC C5213732) https://datasheet.lcsc.com/datasheet/pdf/26ef689c5e1dc55416e27959755861d8.pdf?productCode=C5213732
SMTSO1615MTJ Sinhoo SMD nut datasheet (LCSC C2928168): metric table, "Stencil Masking Examples" https://datasheet.lcsc.com/datasheet/pdf/ece43b9c9581dc6ca2141ce7cea61a1e.pdf?productCode=C2928168
SMTSO-M1.6 PEM catalogue page, SMTSO metric (hole 2.5 +0.08, min. sheet 0.5) https://catalog.pemnet.com/viewitems/reelfast-micropem-surface-mount-nuts-standoffs/surface-mount-nuts---standoffs---br--type-smtso-me
SC70-5 (DCK) TI SN74LVC1G17, DCK0005A outline and example board layout (4214834/G) https://www.ti.com/lit/ds/symlink/sn74lvc1g17.pdf
MCP6V31U Microchip DS20005127B, Table 3-1 https://ww1.microchip.com/downloads/en/DeviceDoc/20005127B.pdf
tscircuit paste rule pcb/node_modules/@tscircuit/core/dist/index.js line 14564: padSize * 0.7 unless solderPasteMargin is set local

1. Global: solder paste (b)

tscircuit creates a pcb_solder_paste for every SMT pad at 0.7 x width and 0.7 x height (49 % of the area) unless the <smtpad> has solderPasteMargin. pcb/tile.mjs never sets it. Confirmed in the data: J210 pad 0.23 x 0.66 gets paste 0.161 x 0.462. In EXO-420/gerbers/B_Paste.gbr the RP2040 pads are 0.140 x 0.6125 and the EP is 2.24 x 2.24.

Area ratio (AR) = aperture area / aperture wall area, for a 0.10 mm stencil. IPC-7525 wants AR ≥ 0.66 for reliable release.

Pad Pad (mm) Paste now AR now Datasheet stencil AR at 1:1
RP2040 signal 0.20 x 0.875 0.14 x 0.6125 0.57 not specified 0.81
ADS131M08 signal 0.20 x 0.55 0.14 x 0.385 0.51 0.20 x 0.55 (1:1) 0.73
ADS131M08 EP 2.8 x 2.8 2.24² = 64 % n/a 4 x 1.23² = 77 % n/a
RP2040 EP 3.2 x 3.2 2.24² = 49 % n/a not specified (IPC: 50-80 %) n/a
DF40 receptacle 0.20 x 0.70 0.14 x 0.49 0.54 not in catalogue 0.78
DF40 header 0.23 x 0.66 0.161 x 0.462 0.60 not in catalogue 0.85
0201 (R/C x ~300 on EXO-410) 0.30 x 0.32 0.21 x 0.224 0.54 IPC: 1:1 0.77
PAT9125EL LGA 0.50 x 0.75 0.35 x 0.525 1.05 none 1.5

Every fine-pitch aperture is below 0.66, so expect opens on the QFN, DF40 and 0201 joints. The 49 % paste on the LGA leaves little solder under a 1.0 mm-thick no-lead part.

Proposed change (no copper change, so the route stays valid): post-process circuit.json before convertCircuitJsonToGerberFiles in both pcb/export.mjs (EXO-410, Freerouted) and pcb/tile.mjs (EXO-420):

// paste + mask per the land-pattern drawings (docs/footprint-verification.md #1-#3). Copper is untouched.
const MASK_MARGIN = 0.04            // TI: NSMD, 0.05 max all around (SBAS950B, SLUA271)
function fixPasteAndMask(cj) {
  const pads = new Map(cj.filter((e) => e.type === "pcb_smtpad").map((e) => [e.pcb_smtpad_id, e]))
  const holes = cj.filter((e) => e.type === "pcb_hole")
  const out = []
  for (const e of cj) {
    if (e.type === "pcb_smtpad") e.soldermask_margin = MASK_MARGIN
    if (e.type !== "pcb_solder_paste" || !e.pcb_smtpad_id) { out.push(e); continue }
    const p = pads.get(e.pcb_smtpad_id)
    if (p.shape === "circle") {
      const nut = holes.some((h) => Math.hypot(h.x - p.x, h.y - p.y) < 0.01)
      if (nut) out.push(...ringPaste(e, p, 1.35, 1.95, 4, 0.45))   // #2
      else out.push({ ...e, radius: p.radius })                     // test pads 1:1
      continue
    }
    const k = Math.min(p.width, p.height) >= 1.5 ? 0.88 : 1.0      // exposed pads: 0.88² = 77 % (TI RSN0032B); else 1:1
    out.push({ ...e, width: p.width * k, height: p.height * k })   // shape / rotation kept from e
  }
  return out
}
function ringPaste(e, p, r0, r1, n, web) {      // n ring segments between r0 and r1, webs `web` wide
  const segs = []
  for (let i = 0; i < n; i++) {
    const a0 = (2 * Math.PI * i) / n + web / r0 / 2 + Math.PI / 4
    const a1 = (2 * Math.PI * (i + 1)) / n - web / r0 / 2 + Math.PI / 4
    const arc = (r, rev) => Array.from({ length: 9 }, (_, t) => {
      const a = a0 + ((a1 - a0) * (rev ? 8 - t : t)) / 8
      return { x: p.x + r * Math.cos(a), y: p.y + r * Math.sin(a) }
    })
    segs.push({ ...e, pcb_solder_paste_id: `${e.pcb_solder_paste_id}_${i}`, shape: "polygon",
                points: [...arc(r1, false), ...arc(r0, true)] })
  }
  return segs
}
// usage: const cj = fixPasteAndMask(rawCj); convertCircuitJsonToGerberFiles(cj)

The gerber exporter supports polygon paste (it writes a region on *_Paste only) and honours soldermask_margin on SMT pads (circuit-json-to-gerber chunk lines 1840 and 4172). Regenerate gerbers only. Do not re-route.

The long-term home for this data is the land pattern itself. Add an optional "paste" key per footprint in footprints.py, e.g. "paste": {"ep": 0.88, "signal": 1.0}, and have tile.mjs pass it as solderPasteMargin. That changes footprints.json but not copper. Only do it after the route is done.

2. SMT nut M1.6 (SMT_Nut_M1.6_Hex3.18_Pad4.2)

Dimension Ours Datasheet (Sinhoo SMTSO1615MTJ / PEM SMTSO-M1.6) Delta Verdict
Thread / hex M1.6, hex 3.18 M1.6x0.35, H = 3.18 ±0.13 A/F 0 OK
Min. solder pad ØD Ø4.20 circle ≥ Ø4.19 +0.01 OK
Hole in sheet ØH NPTH Ø2.50 2.5 +0.08 / -0 (shank C max 2.41) nominal sits at the lower limit FIX (b), low (#5)
Plating of hole NPTH "Plated through hole not required" none OK
Min. board thickness 1.0 mm (tile.mjs) 0.5 mm none OK
Paste Ø2.94 disc centred on the hole (tscircuit 0.7 rule) annular, segmented ring on the pad ("Stencil Masking Examples": 8 dots, 4 or 8 ring segments) only r 1.25-1.47 lands on copper, about 21 % of the annulus, plus paste printed over the hole FIX (b)
Courtyard 4.4 none given none OK

Confirmed in out/pcb/EXO-410/circuit.json: J1 has pcb_smtpad circle r 2.1, pcb_solder_paste circle r 1.47 and pcb_hole Ø2.5, all at the same centre.

  • #2 (b), high priority. The nut is the contact's mechanical and electrical joint, and the ball-pin is torqued into it (rated 1.5 kgf·cm). With about 1.9 mm² of paste on copper there is no fillet beyond r ≈ 1.5, so a weak joint or pull-out under torque is likely across 60 nuts x 16 tiles. Fix: the 4-segment ring (r 1.35-1.95, 0.45 webs) from ringPaste above gives about 5.8 mm² (about 65 % of the annulus), close to the maker's examples. Export step only.
  • #5 (b), low. With a nominal Ø2.50 drill and the fab's ±0.05 NPTH tolerance, a hole can come out at 2.45, which is 0.04 over the 2.41 max shank. Combined with placement error, the shank can ride the hole edge and tilt the nut. Proposed change in footprints.py: "npth": [{"x": 0, "y": 0, "d": 2.54}] (was 2.5). This is drill-only, but route.py derives the hole keep-out from d, so it grows by 0.02 in radius. Apply after the route and re-run the DRC. If the DRC is clean, no re-route is needed.

3. Global: solder mask (b)

Mask apertures equal pad size: B_Mask.gbr has D15 = 0.875 x 0.200, the same as the copper. TI's RSN0032B and DCK layouts call for NSMD with a mask opening of "0.05 max all around" (0.07 for DCK). With 0 expansion, the fab's mask registration (±0.05 typical) can encroach on 0.20 mm pads and turn them solder-mask-defined on one side. Fix: soldermask_margin = 0.04 in the export step (snippet above). On the 0.4 mm-pitch DF40 header (0.23 pads, 0.17 gaps) this leaves a 0.09 dam, which JLCPCB may relieve into a gang opening. TI explicitly allows that for fine pitch. No copper change.

4. PixArt PAT9125EL (PixArt_PAT9125EL_LGA-8)

PixArt publishes the package pad geometry (Fig. 9, bottom view) but no land pattern. A 1:1 land is the usual choice for LGA.

Dimension Ours Datasheet Fig. 9 Delta Verdict
Body 3.5 x 3.2 3.50 ±0.1 x 3.20 ±0.1, 1.00 high 0 OK
Pad size (pins 2-8) 0.50 x 0.75 0.50 ±0.05 x 0.75 ±0.05 0 OK
Pad size (pin 1) 0.50 x 0.75 0.50 x 0.85 ±0.05, chamfered inner corner (pin-1 mark); extra 0.10 toward the centre -0.10 FIX (a) #8
Pitch 0.80 0.80 ±0.05 0 OK
First pad from body edge (x) centre ±1.20, i.e. 0.30 edge gap 0.30 0 OK
Row centres ±1.065 (2.13) 0.16 from edge + 0.75 pad → ±1.065 0 OK
Pin 9 TEST no pad Ø0.69 metal on the underside, on the x centreline about 1.1 mm from centre toward the pin 4/5 end (position read from drawing scale, not dimensioned). "Please do NOT connect it to any part of the PCB." no keep-out FIX (b) #4
Paste 0.35 x 0.525 (49 %) none covered by #1 (b) via #1
Courtyard 3.7 x 3.4 none none OK

Pin numbering and orientation. Fig. 9 is a bottom view: 1-4 along the top edge left to right, 8-5 along the bottom edge, pin 9 near the 4/5 end. Seen from the top (the PCB side), the correct land is: 1 (+1.2, +1.065), 2 (+0.4, +), 3 (-0.4, +), 4 (-1.2, +), 5 (-1.2, -), 6 (-0.4, -), 7 (+0.4, -), 8 (+1.2, -), TEST at (-1.1, 0). The Fig. 9 top view (4 top-left, 1 top-right, 5 bottom-left, 8 bottom-right) agrees. Our land is exactly that pattern rotated 180°: 1 (-1.2, -1.065) … 5 (+1.2, +1.065). It is not mirrored, so it is electrically correct. In our frame TEST sits at (+1.10, 0).

  • #9 (a). Because of the 180° rotation, the sensor's +X/+Y (Fig. 2) point along -x/-y of the footprint frame. Firmware has to negate both delta axes, or account for it when combined with the placement rotation. The VCSEL and sensor window is at the pin 1/8 end in PixArt's top view, which is the -x end in our frame. Keep that in mind for any optical-path or aperture work.
  • #4 (b). The bare TEST metal sits 0-0.1 mm above whatever is under it. A trace under it is covered by mask, so a short is unlikely but possible if the mask is thin or chipped. A via there would be bad. The datasheet says not to connect it to anything. Fix without touching pads: add an F-layer keep-out circle, Ø0.69 + 2 x 0.15 = Ø1.0 at footprint (+1.10, 0), for each US1-US4 in the Freerouting DSN. exo/pcb/route.py already writes (keepout … (circle …)) for holes and vias at lines 209-214, so add one per PAT at its rotated position. If the current route is already finished, check instead whether any F.Cu trace or via falls inside those four circles. If none does, nothing needs to change. Long term, add a footprint field in footprints.py that place.py/route.py honour: "keepout": [{"x": 1.10, "y": 0, "d": 1.0, "layer": "F"}].
  • #8 (a). Proposed change in footprints.py, pin 1 only: {"n": 1, "x": -1.2, "y": -1.015, "w": 0.5, "h": 0.85}. The pad grows 0.10 toward the centre, matching the package's pin-1 pad. The 1.29 mm row gap leaves plenty of clearance. Copper change, so apply only if the board is re-routed anyway.

Nets (circuit.py). 1 VLD → +3V3D (datasheet range 2.7-3.3 V, at the top of the range: OK). 2 VDDA → own 4.7 µF (datasheet: VDDA is the 1.8 V regulator output and needs 4.7 µF in the 2.1-3.6 V segment: OK). 3 VDD → +3V3D (OK). 4 VSS GND, 5 SCLK, 6 SDIO, 7 MOTION, 8 NCS: all match Table 1 (SPI column). 9 TEST: no pad, correct.

5. HCTL FPC 12P 0.5 mm (HCTL_FPC_12P_P0.5mm, HC-FPC-05-10-12RLTAG)

Dimension Ours HCTL "Recommend PCB layout" (tol ±0.05), n = 12 Delta Verdict
Signal pad 0.30 x 0.65 0.30 ±0.03 x 0.65 0 OK
Pitch / span B 0.5 / 5.5 0.50 / B = (n-1)·0.5 = 5.50 0 OK
Tab (leg) pad width 0.60 0.30 ±0.03 (it is dimensioned; the source note said it was not) +0.30 FIX (a) #6
Tab pad length 1.15 1.15 0 OK
Tab centre spacing D 7.27 (±3.635) D = n·0.5 + 1.27 = 7.27 0 OK
Tab y offset -2.81 (centre) signal-pad edge to tab edge 1.91 → 0.325 + 1.91 + 0.575 = 2.81 0 OK
Tab edge to body edge outer tab edge 3.935 body edge 0.25 outboard of the tab centre (3.885) 0.05 past the body (a)
Pin-1 end pin 1 at -x (left, contacts toward +y) not marked in the layout drawing unknown CHECK #7
  • #6 (a). The leg is a 0.12 mm strip. A 0.60 pad just gives it a wider fillet and pokes 0.05 past the body. It is not a fit failure. Proposed change in footprints.py: {"n": 13, "x": -3.635, "y": -2.81, "w": 0.30, "h": 1.15}, {"n": 14, "x": 3.635, "y": -2.81, "w": 0.30, "h": 1.15}, and source text "HCTL HC-FPC-05-10-NRLTAG rev A recommended PCB layout". This affects EXO-420 copper only. EXO-420 is routed by tscircuit and is not the board mid-autoroute, so it can be redone with node pcb/tile.mjs EXO-420 whenever convenient.
  • #7 (b), system. FPC_PINS is not reversal-safe. Pins 1-2 are VIN and pins 11-12 are GND, so a flipped pin order shorts the hub supply. The order at the hub depends on the cable (type A same-side vs type B opposite-side contacts) and on which end of this connector is pin 1. The HCTL layout does not mark pin 1. Before ordering, confirm pin 1 on a physical part or the 3D model (the housing usually carries a pin-1 mark or triangle), fix the cable type in the hub spec, or make the pinout symmetric. For example, put VIN on 6/7 with GND on both sides, or GND on 1 and 12.

6. Hirose DF40C-10DS-0.4V(51) receptacle and DF40C-10DP-0.4V(51) header

The concern was that the pads were "scaled from the 50-pin drawing". In fact the catalogue gives one recommended layout per family, dimensioned with B = (n/2 - 1)·0.4. Scaling is therefore exactly Hirose's definition, and the results are identical.

Receptacle (DS), catalogue p. 4, "DF40C (without reinforcing metal fitting)"

Dimension Ours Hirose Delta Verdict
Pad width 0.20 0.2 ±0.02 0 OK
Pitch 0.40 0.4 ±0.02 0 OK
Outer / inner row edges 3.78 / 2.38 (rows ±1.54, pad 0.70) 3.78 +0.05/0 / 2.38 0/-0.05 0 OK
Span B (pad 1 to pad 9 centres) 1.6 B = 1.6 (10 pos.) 0 OK
Resist coating mask = pad copper may extend inward to 1.5 MAX apart, but the part inside 2.38 must be under mask (hatched) none (our copper stops at 2.38) OK
Metal fittings none none on DF40C (DF40B has them) none OK, see note
Body A x width courtyard 4.8 x 3.6 4.6 (B + 3.0) x 3.38 inside OK
Polarisation n/a "This connector is NOT polarized" none OK

Note: the 2019 catalogue lists DF40C receptacles only from 20 positions up. At 10 positions it lists DF40B-10DS-0.4V(51), which has reinforcing fittings: extra pads 1.2 ±0.02 beyond the last contact centreline (x = ±2.0), in both rows, about 0.33 x 0.70 measured but not dimensioned. However, DigiKey lists DF40C-10DS-0.4V(51) as Active (link above), and it has no LCSC number, so JLC global sourcing or consignment is needed. Our footprint is right for DF40C-10DS. If purchasing ends up substituting DF40B-10DS, the fittings would land on bare board or traces. Add 4 pads {"x": ±2.0, "y": ±1.54, "w": 0.35, "h": 0.70} (confirm the width from Hirose's individual DF40B-10DS drawing), tied to GND or no net, and re-route around them. In that case it becomes a (b).

Header (DP), catalogue p. 10

Dimension Ours Hirose Delta Verdict
Pad width 0.23 0.23 ±0.02 0 OK
Pitch 0.40 0.4 ±0.02 0 OK
Outer / inner row edges 3.37 / 2.05 (rows ±1.355, pad 0.66) 3.37 +0.05/0 / 2.05 0/-0.05 0 OK
Span B 1.6 1.6 0 OK
Corner fitting pads 0.35 x 0.66 at x = ±1.275 0.35 ±0.02 wide; inner edge 0.3 and outer edge 0.65 from the last contact centreline → centre 0.475 → ±1.275 0 OK
Body courtyard 4.8 x 3.2 A 3.52 x 2.97 inside OK
Fittings usage MP (11-14) → GND "Use the contacts at the four corners as metal fittings. Do not use them as signal or power contacts." tied to GND but not relied on (a) #16

Pin mapping and stacking (circuit.py, check.py)

B2B10R and B2B10H both map pin k → pad k. check.py b2b only compares the net strings of J20s and J21s pad by pad, so I checked the geometry directly from the generated circuit.json of both boards:

  • tscircuit mirrors bottom-layer parts in x (composed as Rot(θ)·Mirror, so it holds at any rotation). The receptacle is on the contact board's bottom, so it is mirrored once. The header footprint is pre-mirrored (header=True) and placed on the controller's top. The result is that pad k of J20s and pad k of J21s land at the same board x, on the same side (+y or -y row). The only offset is the expected 0.185 in y, from the different row pitches (3.08 vs 2.71). This holds for all 4 corners, including J201/J211 at 90°:
corner rot pin 1 receptacle (EXO-410 B) pin 1 header (EXO-420 F)
0 0 (-16.353, -15.476) (-16.353, -15.661)
1 90 (-18.556, 17.953) (-18.371, 17.953)
2 0 (17.966, -15.526) (17.966, -15.711)
3 0 (17.966, 18.606) (17.966, 18.421)
  • DF40 is unpolarised and symmetric, so mating is purely positional: the contact at board (x, ±row) mates with the contact facing it. With pads coincident, receptacle pin k carries the same net as header pin k, which is what B2B_CORNERS assumes. Which way round the assembler places the physical part (pin-1 mark) makes no electrical difference.
  • The net check passes, the geometry check passes, and both catalogue land patterns match. OK.

7. TI ADS131M08 (TI_RSN_WQFN-32_4x4mm_P0.4mm_EP2.8mm)

Dimension Ours TI RSN0032B example board layout Delta Verdict
Pad 0.20 x 0.55 32X (0.2) x 32X (0.55) 0 OK
Pitch 0.40 28X (0.4) 0 OK
Row centres 3.85 (±1.925) (3.85) 0 OK
Thermal pad 2.8 x 2.8 (2.8) 0 OK
EP paste 2.24² (64 %) via the 0.7 rule 4 x 1.23² windows = 77 % -13 % (b) via #1
Signal paste 0.14 x 0.385 0.2 x 0.55 (1:1), 0.1 mm stencil -51 % (b) via #1
Thermal vias none optional, Ø0.2, filled/tented if used none OK (low power)
Mask 0 expansion NSMD, 0.05 max (b) via #3
Pin 1 / order 1 at top of left side, CCW: 1-8 down the left, 9-16 along the bottom, 17-24 up the right, 25-32 along the top same (land pattern view: 32…25 on top, 1 top-left) 0 OK
Courtyard 4.5 body 4.1 max none OK

Pin map in circuit.py against SBAS950B Table 5-1 (WQFN column): AIN2P 1, AIN2N 2, AIN3N 3, AIN3P 4, AIN4P 5, AIN4N 6, AIN5N 7, AIN5P 8, AIN6P 9, AIN6N 10, AIN7N 11, AIN7P 12, AGND 13/28, REFIN 14, AVDD 15, SYNC/RESET 16, CS 17, DRDY 18, SCLK 19, DOUT 20, DIN 21, XTAL2 22, CLKIN 23, CAP 24, DGND 25, DVDD 26, NC 27, AIN0P 29, AIN0N 30, AIN1N 31, AIN1P 32, thermal pad → AGND. All match. The EP is pad 33 → GND (single ground, consistent with "connect to AGND"). Note: REFIN has 100 nF (CF*). The datasheet says no capacitance on REFIN only if current-detect mode is used, so this is fine as long as that mode stays off.

8. RP2040 (RP2040_QFN-56_7x7mm_P0.4mm_EP3.2mm)

Dimension Ours RP2040 datasheet Fig. 167 Delta Verdict
Pad 0.20 x 0.875 0.20 x 0.875 0 OK
Pitch 0.40 0.40 0 OK
Outer / inner pad edges 7.75 / 6.00 → centres 6.875 7.75 / 6.00 0 OK
Row extent 5.2 + 0.2 = 5.40 5.40 (1.175 from the outer edge) 0 OK
EP 3.2 x 3.2 3.20 ("smaller than most", deliberately, so tracks can pass between EP and pads) 0 OK
EP paste 2.24² = 49 % not specified low (b) via #1 (77 % proposed)
Signal paste 0.14 x 0.6125 (AR 0.57) not specified low (b) via #1
Pin 1 / order top of left side, CCW standard QFN-56; Table 615 numbering 0 OK
Courtyard 7.85 body 7.0, pads 7.75 none OK

Pin map against Table 615 / §1.4: GPIO0-7 = 2-9, GPIO8-15 = 11-18, TESTEN 19, XIN 20, XOUT 21, IOVDD 1/10/22/33/42/49, DVDD 23/50, SWCLK 24, SWD 25, RUN 26, GPIO16-21 = 27-32, GPIO22-29 = 34-41, ADC_AVDD 43, VREG_VIN 44, VREG_VOUT 45, USB_DM 46, USB_DP 47, USB_VDD 48, QSPI_SD3 51, SCLK 52, SD0 53, SD2 54, SD1 55, SS 56, GND 57 (EP). All match T["RP2040"], so the PIN_SOURCES "verify" note can be closed.

9. SC70-5 (SC70-5: MCP6V31UT-E/LT x 62 on EXO-410, SN74LVC1G17DCKR x 2)

Dimension Ours TI DCK0005A example layout Delta Verdict
Pad 1.03 x 0.35 0.95 x 0.40 +0.08 / -0.05 (a)
Pitch 0.65 0.65 0 OK
Row centres 1.68 (±0.84) 2.2 (±1.1) -0.52 (a), see note
Pad extent (x) 0.325 … 1.355 0.625 … 1.575
Pin order 1-3 down the left, 4-5 up the right same 0 OK

Lead tips sit at ±0.90 … ±1.20 (E 1.8-2.4) with foot length 0.26-0.46. Under every tolerance combination the whole foot lands on our pad, with a toe of 0.155 to 0.455. The pad runs about 0.3 under the body instead of forming a heel fillet. It is non-IPC (narrower and toe-light) but solderable and self-centring. (a). If EXO-410 is ever re-routed, switch to TI's land, pads 0.95 x 0.40 at x = ±1.10: {"n": 1, "x": -1.10, "y": 0.65, "w": 0.95, "h": 0.40}, etc., courtyard [2.8, 2.0]. Do not re-route just for this.

Pinouts: MCP6V31U SC70 (DS20005127B Table 3-1): VIN+ 1, VSS 2, VIN- 3, VOUT 4, VDD 5 matches OPA1. SN74LVC1G17 DCK: NC 1, A 2, GND 3, Y 4, VCC 5 matches BUF1G17.

10. Small items (a)

  • #16a footprints.py docstring says "read by kicad_build.py". It is read by exo/pcb/place.py, then pcb/tile.mjs.
  • #16b qfn() sets "shape": "round". place.py passes it through, but tile.mjs only recognises "circle", so QFN pads are plain rectangles. TI shows R0.05 corners. This does not matter. Either drop the key or map it to a rounded rect later.
  • #16c DF40 header fittings (pads 11-14) are on GND. Hirose says not to use them as signal or power contacts. GND is harmless because nothing on the receptacle mates with them. Optionally give them their own MP net with no copper connection.
  • #16d T["B2B10H"] has no lcsc. DF40C-10DP-0.4V(51) is LCSC C424635. T["B2B10R"] (DF40C-10DS) has no LCSC listing, so source it from DigiKey and consign it.
  • #16e PIN_SOURCES["LDO"] "verify": TPS7A20 DBV is IN 1, GND 2, EN 3, NC 4, OUT 5, which matches T["LDO"]. That footprint is the standard SOT-23-5 in place.py, not part of footprints.py.
  1. Now, safe mid-route: add fixPasteAndMask (#1, #2, #3) to pcb/export.mjs and pcb/tile.mjs, then regenerate gerbers only. This covers every (b) item except #4, #5 and #7.
  2. When the EXO-410 route finishes: check the four PAT TEST keep-out circles (#4) for F.Cu copper. Apply the NPTH Ø2.54 (#5) and re-run the DRC.
  3. Before ordering: settle the FPC pin-1 end and the cable type (#7). Confirm with purchasing that DF40C-10DS (not DF40B) is what will be bought (§6 note).
  4. Next time EXO-420 is regenerated: FPC tab width 0.30 (#6).
  5. Only if a board is re-routed anyway: PAT pin-1 pad (#8), SC70 land (#15).