Commit Graph

4 Commits

Author SHA1 Message Date
onur 4fa38e35bd Fix the RF launch: relieve the planes under J2 and put the ESD on the line
The 0.164/0.200 CPWG geometry was fine; the calculation just stopped at the
trace and never covered the connector launch, which is where the real
discontinuity was.

J2's centre land is 1.5 mm wide because that is what the connector's centre pin
needs mechanically. Sitting on solid L2_GND only 0.0994 mm below, that land is
a 10.7 ohm transmission line, not a 50 ohm one. The 1.84 mm of it over the
plane is 6.7 degrees at L1 and reflects 12 dB (VSWR 1.67) - by far the worst
discontinuity in the chain, and worse than everything the carefully built
0.164 mm line downstream avoids.

RF_LAUNCH_RELIEF voids L2_GND and L3_SIG under the land, (172.35, 40.95) to
(175.10, 43.05). The reference drops to L4_PWR - VCC3V0_RF, an AC ground -
0.587 mm below, which raises the launch to 37 ohm and 30 dB. L3 carried no
pour and no copper there, so only L2 actually had to go; the area covers L3 as
well so a later edit cannot fill the gap back in. It stops where the land ends
and the 0.164 mm line begins, verified: L2 GND is absent across the whole land
and present again at x = 172.0 and inboard.

D1's ESD clamp sat at the end of a 1.34 mm spur, where its 0.3 pF presented
-j228 ohm and cost 3.4 dB for nothing. D1 is rotated onto the run at
(171.30, 42.416) so pad 1 overlaps the line directly and pad 2 lands in the
RF ground pour; the spur is deleted.

Return loss, worst term first:
  SMA launch land      12.0 -> 30.0 dB   (10.7 -> 37.0 ohm)
  D1 ESD clamp         19.2 -> 22.6 dB   (now just the part's own 0.3 pF)
  C85 DNP tuning stub  25.5 dB unchanged, intentional provision
  C84 DNP land in line 30.1 dB unchanged, negligible
  worst-case coherent   7.0 -> 14.4 dB
The dominant term is now a component choice rather than a layout defect.

Verified: ERC 0/0, DRC 0 violations, 0 unconnected, every net one copper group,
parity unchanged at the 402 pre-existing warnings, RF still 10 segments all on
F.Cu at exactly 0.164 mm.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012KaTmCCxCEW4awsmXRNT1d
2026-09-01 12:55:49 +03:00
onur 95609a6b6a Complete the routing: 0 DRC violations, 0 unconnected
The board now routes end to end. Every net carrying two or more pads is a
single connected copper group (216 nets, 1175 pads); kicad-cli reports 0 DRC
violations and 0 unconnected items with zones refilled.

Freerouting was never the blocker. The 14 remaining opens were three separate
defects:

1. Obstacles in route_local_power.py modelled every pad as its axis-aligned
   bounding box. A 0.8-mm BGA dogbone site sits diagonally between four lands:
   true clearance 0.1407 mm, but the box test measured 0.4 mm from the box edge
   and rejected it, so no via could be placed anywhere in the Ti375 escape
   field. Replaced with an exact rounded-rectangle model, validated against
   KiCad's own SHAPE::Collide to 0.00 um over 14850 samples. Same 0 DRC and one
   fewer unconnected at the route_local_power stage.

2. CLOCK's 0.15-mm clearance cannot physically escape the BGA: two adjacent
   0.45-mm dogbone vias on 0.8-mm pitch leave a 0.35-mm channel and a 0.10-mm
   trace needs 0.40 mm. HARD_TCK and MAX_SCLK could never leave the package.
   New rule "Ti375 escape field copper clearance" relaxes clearance to the
   0.10 mm this field already uses, only where both objects are inside U1's
   courtyard. The clock trunk keeps 0.15 mm outside it.

3. RF_NO_DIGITAL was a rectangle reaching 7 mm past the RF line, covering the
   MAX2771's whole digital pin field and forcing every U21 output onto F.Cu
   alone. Narrowed to the corridor generate_pcb.py already reserves as
   TEMP_RF_LINE (y <= 43.7), clearing RF copper by 1.1 mm. The RF return path
   is guaranteed by the unrouted L2/L7 ground planes, not by this area.

scripts/close_remaining.py replaces the ad-hoc residual scripts: a multi-layer
maze over (x, y, layer) at 0.1 mm on all five routable layers, seeded from all
copper of both groups, exact clearances, 0.10-mm necking inside the escape
field, and reversible rip-up that rolls back entirely if a displaced net cannot
be put back. ~150 s for the whole board.

Also removes the regenerable intermediate boards, one-off session logs and the
superseded residual scripts, and tracks board_routed.* as the deliverable.

The 402 schematic-parity warnings are pre-existing and unchanged: 199
auto-named unconnected pins, 199 footprint library-nickname mismatches, and 4
mounting holes with no symbol. None affects connectivity or fabrication.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012KaTmCCxCEW4awsmXRNT1d
2026-09-01 11:58:41 +03:00
onur af7c43b2a8 Restack to four signal layers and route the board
The Ti375 fanout could not be resolved with three routing layers, so L5
stops being a dedicated 1.8-V plane and becomes a signal layer.  No rail
owns a whole layer any more: the supplies are split into zone islands on
L4 and L6, L2 and L7 stay solid and completely unrouted, and F.Cu, L3, L5
and B.Cu are all available for signals.

Routing is staged rather than handed to the autorouter wholesale.  The
BGA escape, the buck high-current loops, plane stitching and the local
power completion all run first and are locked; Freerouting then sees only
the ordinary digital classes, with everything else present as fixed
copper.  finalize_routing.py installs the audited RF and USB geometry and
closes whatever the autorouter left.

Four bugs behind the routing failures, all of them the same shape - a
layer list written down instead of read from the board, which was correct
while L5 was a plane and silently wrong afterwards:

- export_routing_stage.py emitted via keepouts for three layers only, so
  every existing via was invisible to the router on L5.  It drove traces
  straight through them: 102 shorting_items in DRC.
- route_local_power.py never used L5 at all, and picked up escape vias on
  two layers instead of all four.
- add_rf_ground() judged fence positions against vias and pads but not
  tracks.  It runs after the session import, when that region already has
  routed copper, and dropped a ground via on top of a signal trace.

route_local_power.py also grew a via cloud on every rail: reaching a
plane counted as progress even when it merged nothing, so the same pad
collected a via per pass, 0.4 mm further out each time.  Progress is now
measured by the group count actually falling, and groups already sitting
on their plane are skipped.  That removed 404 redundant vias.

The MAX2771 PLL loop filter was spread across three corners of the
package, which forced the charge-pump node onto an inner layer under the
GPS front end.  All three parts now sit in the pocket at U21's north-west
corner and the net stays on F.Cu.  A permanent RF_NO_DIGITAL area plus a
scoped rule keeps that region free of non-power copper on L3/L5/L6/B.Cu,
and the local router enforces the same restriction, since it is the one
stage that runs after the temporary keepout is deleted.

Also enables the solder-mask bridge check that was switched off
board-wide; the board passes it with no violations.

Final board: DRC clean - no shorts, clearance, disallowed-item or
dangling-copper violations - with 26 unconnected endpoints left.  Routing
is spread 37% L3, 27% F.Cu, 26% L5, 10% B.Cu over 6548 mm and 971 vias.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 01:41:43 +03:00
onur b706197667 Initial Ti375 GNSS IMU board design and documentation 2026-08-15 18:09:17 +03:00