6.8 KiB
CPL rotation corrections — re-bba-rb
re-bba-rb-cpl.csv is generated from kicad-cli pcb export pos (raw KiCad
rotation values), then hand-corrected for the parts below before each
regeneration. This file exists because that correction step is easy to lose
silently — regenerating the CPL "the normal way" wipes it out, and there is
no automated check that would catch that. Read this before touching the CPL.
Why this exists
KiCad's per-footprint rotation is measured from an arbitrary reference baked
into whoever drew that footprint — it does not reliably match what JLCPCB's
placement machine expects. This is a well-known, generic problem (see
cpl_rotations_db.csv from the JLCKicadTools / kicad-jlcpcb-tools projects
for the community's attempt at a fix), but the generic community
correction table was tried on this board and found wrong — it claims
LQFP-: 270°, but on this exact board/toolchain pairing (KiCad 10 +
kicad-cli pcb export pos, not the dedicated plugin) the raw LQFP/QFN
rotation is already correct. The generic table's values are calibrated
against that plugin's own raw-rotation baseline, which is not the same
baseline kicad-cli's raw CSV export produces (different Y-axis handling
between the two tools). Do not reapply the community table wholesale to
this board. Every correction below was derived per-part from direct visual
verification against JLCPCB's placement-preview render, not from that table.
Rotation sign convention
The CPL uses JLCPCB's Y-up coordinate frame (kicad-cli's csv pos format
already negates Y from KiCad's native Y-down). In that frame, increasing
rotation angle is counter-clockwise (standard math convention). So when
the user reports "needs N degrees clockwise", the correction applied is
new = (old - N) % 360, not +N. Get this backwards and every fix
lands 2×N off instead of correct.
How the correction was (re-)applied each time
import csv
corrections = { 'REF': degrees, ... } # positive = CCW, negative = CW
with open('re-bba-rb-cpl.csv', newline='') as f:
rows = list(csv.DictReader(f))
for r in rows:
if r['Designator'] in corrections:
old = float(r['Rotation'])
new = (old + corrections[r['Designator']]) % 360
r['Rotation'] = f"{new:.6f}"
with open('re-bba-rb-cpl.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['Designator','Mid X','Mid Y','Layer','Rotation'])
writer.writeheader()
writer.writerows(rows)
When regenerating the CPL from scratch (e.g. after a reroute or component
move), re-run kicad-cli pcb export pos for fresh positions, then
reapply every correction below — don't just diff/copy the old file, since
positions can legitimately change while rotations still need the same
correction offset applied on top.
Confirmed correct as-is — apply NO correction
- U8, U11 (LQFP-48/64), U9 (QFN-48) — "all large chips are right" (user, direct placement-preview check). Raw KiCad rotation is correct.
- U4 (SOT-23-5) — confirmed good after the -90° family correction below was applied (net rotation 270°, i.e. raw 0° − 90°).
- J2 (HR911105A magjack, rot=90° in the PCB file) — not a CPL-rotation question (J2 doesn't need per-part correction below, it's not in the CPL correction set), but its physical orientation was independently verified: the RJ45 signal pins (pins 1–8, footprint local +Y) map to absolute −X under the board's 90° placement rotation, which correctly faces the board's tongue/cable-exit edge. Pin 1 appearing to "face outside the board" in the placement render is expected, not a defect — the RJ45 contacts are always near the cable-insertion opening by construction.
Corrections applied (all currently in re-bba-rb-cpl.csv)
Each row: designator, package, raw→corrected, confidence.
| Ref | Package | Raw | Corrected | Confidence |
|---|---|---|---|---|
| U7 | SOIC-8 | 90° | 180° | Reconstructed hypothesis (see below) — not independently re-confirmed |
| U10 | SOIC-8 | 0° | 90° | Reconstructed hypothesis — not independently re-confirmed |
| D1 | SOT-23-6 | 0° | 270° | Reconstructed hypothesis — not independently re-confirmed |
| D4 | SOT-23-6 | 180° | 90° | Reconstructed hypothesis — not independently re-confirmed |
| D5 | SOT-23-6 | 180° | 90° | Reconstructed hypothesis — not independently re-confirmed |
| U12 | SOT-23-6 | 180° | 90° | Reconstructed hypothesis — not independently re-confirmed |
| U1 | SOT-23-5 | 180° | 0° (two corrections: -90° then another -90°, user-confirmed both times) | Confirmed by direct user feedback, twice |
| Q1 | SOT-23 (bottom layer) | -90° | 90° | Confirmed ("upside down" = 180°, direction-agnostic) |
| Q2 | SOT-23 (bottom layer) | -90° | 90° | Confirmed (same as Q1) |
| D2 | custom SON50P110X213X50-7 |
0° | 270° | Confirmed ("90° clockwise") |
| D3 | Diode_SMD:D_SMA |
180° | 0° | Confirmed ("180°", direction-agnostic) |
| C65 | Capacitor_SMD:CP_Elec_6.3x7.7 |
0° | 180° | Confirmed ("180°", direction-agnostic) |
| U2 | SOT-583-8 | 180° | 90° | Confirmed ("90° clockwise") |
"Reconstructed hypothesis" parts (U7, U10, D1, D4, D5, U12) explained: the user reported "SOIC and SOT chips are rotated 90°, direction unsure." Cross-referencing against earlier feedback in the same session — where a -90° correction had been applied to the top-layer SOT-23 parts and NOT flagged as wrong, while the same -90° applied to a SOIC part (U10) WAS flagged wrong — implies SOT-23 needs -90° and SOIC needs the opposite, +90°. This is indirect reasoning, not a fresh direct check, and U1 later proved that even within one confirmed-wrong-by-90°-family, the correction does NOT reliably generalize per package type (U1 and U4 are both SOT-23-5, both got the -90° family correction, but U1 needed a second -90° on top while U4 was already correct) — so treat every "reconstructed hypothesis" row above as worth a fresh placement-preview check, not settled fact, despite no contradicting feedback having come in since.
Parts never checked at all
Every 0402/0603/0805 passive (R/C/L), J1/J3/J4 connectors, the custom
U3 footprint (hardware:SOT95P280X110-6N), and anything else not listed
above is sitting at raw, unverified KiCad rotation in the CPL. Passives
in symmetric packages are usually fine raw (this matched observed behavior
for the ones implicitly checked), but this has not been confirmed
part-by-part the way the table above was.
Bottom line for whoever picks this up next
Before ordering assembly, re-check the entire board in JLCPCB's (or whatever assembler's) placement preview — this file only covers what's been individually verified so far, not a general guarantee the CPL is correct.