AnasSarkiz/magnetic-shutter-remote-r8
A USB‑C rechargeable battery-powered ESP32‑C3 wireless controller with Li‑ion charging, protected 3.3‑V buck‑boost regulation, thermal/safety monitoring, status LEDs, buttons, programming UART, crystal clock, and 2.4‑GHz antenna matching network.
- Version
- 0.4.0-prototype
- License
- unset
- Stars
- 0
src/r9-control-trace-paths.ts
import { upperV3BranchRoute } from "./r9-core-trace-paths";
import { z } from "zod";
import { applyToPoint, translate } from "transformation-matrix";
import type { FanoutTracePath } from "@tscircuit/core";
import {
r8MosfetPaths,
r8UsbDisablePaths,
r8PowerPaths,
r8TsBiasPaths,
sensorCapEscapePaths,
sensorEscapePaths,
r8ChargeStatPaths,
r8BatteryCapEscapePaths,
} from "./trace-paths";
// Same verified gate/drain escapes. The source ground now drops locally before
// the RF feed corridor, rather than crossing the antenna transmission line.
export const r9MosfetTracePaths: FanoutTracePath[] = [
...r8MosfetPaths.filter((path) => path.connection !== "Q2.pin2"),
{
connection: "Q2.pin2",
route: [
{
route_type: "wire",
x: 8.999998,
y: 6.94996,
width: 0.15,
layer: "top",
},
{ route_type: "wire", x: 9.95, y: 7.8, width: 0.15, layer: "top" },
{
route_type: "via",
x: 9.95,
y: 7.8,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
];
// Move ordinary via ends off wide capacitor/resistor lands; preserve all
// other manufacturer-reviewed R8 power/sensor escapes in the R9 candidate.
// VINA already touches C13 mid-path. Its saved fanout must expose the same
// input-reservoir exit, so the root router does not target that occupied pad.
const regulatorBiasSupplyPath = r8PowerPaths.find(
(path) => path.connection === "U3.pin8",
);
if (!regulatorBiasSupplyPath)
throw new Error("Missing retained regulator VINA path");
const regulatorBiasSupplyBranch = regulatorBiasSupplyPath.route.slice(2);
// Reserve the high-current battery trunk before signal routing. Board XY mm.
function batteryInputTrunkRoute(): FanoutTracePath["route"] {
return [
{ route_type: "wire", x: -10.999998, y: 0, width: 0.508, layer: "top" },
{ route_type: "wire", x: -10.999998, y: -1.5, width: 0.508, layer: "top" },
{
route_type: "via",
x: -10.999998,
y: -1.5,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
{
route_type: "wire",
x: -10.999998,
y: -1.5,
width: 0.508,
layer: "bottom",
},
{ route_type: "wire", x: -12, y: -2.5, width: 0.508, layer: "bottom" },
{ route_type: "wire", x: -14.0, y: -2.5, width: 0.508, layer: "bottom" },
{ route_type: "wire", x: -14.0, y: 11.2, width: 0.508, layer: "bottom" },
{
route_type: "wire",
x: -1.9998075,
y: 11.2,
width: 0.508,
layer: "bottom",
},
{
route_type: "wire",
x: -0.9998075,
y: 10.2,
width: 0.508,
layer: "bottom",
},
];
}
// Full 0.508mm regulated output feed, above the reservoir then around the
// switching input trunk. World XY mm; both copper layers only.
function regulatorOutputTrunkRoute(): FanoutTracePath["route"] {
return [
{ route_type: "wire", x: -10.999998, y: 8.5, width: 0.508, layer: "top" },
{ route_type: "wire", x: -10.999998, y: 9.9, width: 0.508, layer: "top" },
{
route_type: "via",
x: -10.999998,
y: 9.9,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
{
route_type: "wire",
x: -10.999998,
y: 9.9,
width: 0.508,
layer: "bottom",
},
{ route_type: "wire", x: -8.7, y: 9.9, width: 0.508, layer: "bottom" },
{ route_type: "wire", x: -8.7, y: -4.5, width: 0.508, layer: "bottom" },
{ route_type: "wire", x: -0.6, y: -4.5, width: 0.508, layer: "bottom" },
...upperV3BranchRoute().slice(5),
];
}
function regulatorOutputBypassRoute(): FanoutTracePath["route"] {
return [
{ route_type: "wire", x: -10.999998, y: 6, width: 0.6, layer: "top" },
...regulatorOutputTrunkRoute(),
];
}
const regulatorPowerLoopPaths: FanoutTracePath[] = [
{ connection: "C12.pin1", route: regulatorOutputTrunkRoute() },
{ connection: "C4.pin1", route: regulatorOutputBypassRoute() },
...r8PowerPaths.filter(
(path) => path.connection !== "C3.pin2" && path.connection !== "U3.pin6",
),
{ connection: "C13.pin1", route: regulatorBiasSupplyBranch },
{
connection: "C3.pin2",
route: [
{ route_type: "wire", x: -9.000002, y: 0, width: 0.15, layer: "top" },
{ route_type: "wire", x: -7.6, y: 0, width: 0.15, layer: "top" },
{
route_type: "via",
x: -7.6,
y: 0,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
{
connection: "U3.pin6",
route: [
{
route_type: "wire",
x: -8.842522,
y: 2.000002,
width: 0.15,
layer: "top",
},
{ route_type: "wire", x: -7.65, y: 1.1, width: 0.15, layer: "top" },
{
route_type: "via",
x: -7.65,
y: 1.1,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
];
export const r9PowerTracePaths: FanoutTracePath[] = regulatorPowerLoopPaths.map(
(path): FanoutTracePath => {
if (path.connection === "U3.pin1")
return {
...path,
route: [...path.route, ...regulatorOutputTrunkRoute().slice(1)],
};
if (path.connection === "U3.pin10")
return {
...path,
route: [...path.route, ...regulatorOutputBypassRoute().slice(1)],
};
if (path.connection === "C3.pin1")
return { ...path, route: batteryInputTrunkRoute() };
if (
["U3.pin5", "U3.pin8", "C11.pin1", "C13.pin1"].includes(path.connection)
) {
return {
...path,
route: [...path.route.slice(0, -1), ...batteryInputTrunkRoute()],
};
}
return path;
},
);
// Explicit physical region uses the measured original component bounds. Saved
// completed power branches may leave it; all component world poses are retained.
export const r9PowerLoopAnchor = { x: -11.12750065, y: 3.75 };
export const r9PowerLoopFanoutPaths: FanoutTracePath[] = r9PowerTracePaths.map(
(path) => ({
...path,
route: path.route.map((point) => ({
...point,
...applyToPoint(translate(-r9PowerLoopAnchor.x, -r9PowerLoopAnchor.y), {
x: z.number().parse(point.x),
y: z.number().parse(point.y),
}),
})),
}),
);
export const r9TsBiasTracePaths: FanoutTracePath[] = [
...r8TsBiasPaths.filter((path) => path.connection !== "R9.pin1"),
{
connection: "R9.pin1",
route: [
{ route_type: "wire", x: 0.246636, y: 17, width: 0.15, layer: "top" },
{ route_type: "wire", x: 0.05, y: 18.03, width: 0.15, layer: "top" },
{
route_type: "via",
x: 0.05,
y: 18.03,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
];
export const r9SensorCapTracePaths: FanoutTracePath[] = [
...sensorCapEscapePaths.filter((path) => path.connection !== "C7.pin1"),
{
connection: "C7.pin1",
route: [
{ route_type: "wire", x: 0.799976, y: 8.5, width: 0.15, layer: "top" },
{ route_type: "wire", x: 0.5, y: 9.55, width: 0.15, layer: "top" },
{
route_type: "via",
x: 0.5,
y: 9.55,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
];
// The qualified charge-status corridor remains clear of R9 RF/clock reference
// regions. Raise its ordinary via0.05mm to retain the declared0.35mm pad gap.
export const r9ChargeStatTracePaths: FanoutTracePath[] = r8ChargeStatPaths.map(
(path) => ({
...path,
route: path.route.map((point) =>
point.x === 7.249938 && point.y === 24 ? { ...point, y: 24.05 } : point,
),
}),
);
// Complete low-current charge LED connection, saved in the early phase so
// all following routers preserve its copper. Board XY mm,+Z top.
export const r9ChargeLedTracePaths: FanoutTracePath[] = [
{
connection: "R4.pin2",
route: [
{ route_type: "wire", x: 8.753364, y: 16.5, width: 0.15, layer: "top" },
{ route_type: "wire", x: 8.753364, y: 15.35, width: 0.15, layer: "top" },
{
route_type: "via",
x: 8.753364,
y: 15.35,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
{
route_type: "wire",
x: 8.753364,
y: 15.35,
width: 0.15,
layer: "bottom",
},
{
route_type: "wire",
x: 8.753364,
y: 23.65,
width: 0.15,
layer: "bottom",
},
{
route_type: "via",
x: 8.753364,
y: 23.65,
from_layer: "bottom",
to_layer: "top",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
{ route_type: "wire", x: 8.753364, y: 23.65, width: 0.15, layer: "top" },
{ route_type: "wire", x: 8.750062, y: 26, width: 0.15, layer: "top" },
],
},
];
// R4's1k LED feed carries <4.2mA even with a shorted LED. Share the already
// authored bypass branch and expose the same battery exit as C2.
export const r9ChargeVbatTracePaths: FanoutTracePath[] = [
{
connection: "R4.pin1",
route: [
{ route_type: "wire", x: 7.246636, y: 16.5, width: 0.15, layer: "top" },
{ route_type: "wire", x: 6.246636, y: 15.5, width: 0.15, layer: "top" },
{ route_type: "wire", x: 3, y: 15.5, width: 0.15, layer: "top" },
{ route_type: "wire", x: 2.8, y: 15.3, width: 0.15, layer: "top" },
{ route_type: "wire", x: 2.8, y: 11.5, width: 0.15, layer: "top" },
{ route_type: "wire", x: 3.799976, y: 11.5, width: 0.15, layer: "top" },
...r8BatteryCapEscapePaths[0].route
.slice(1)
.map((point) => ({ ...point })),
],
},
];
export const r9StatusLedTracePaths: FanoutTracePath[] = [
{
connection: "R7.pin2",
route: [
{ route_type: "wire", x: -15.753364, y: -5, width: 0.15, layer: "top" },
{ route_type: "wire", x: -18.249938, y: -5, width: 0.15, layer: "top" },
],
},
];
// Complete boot-strap connections; retained10k pull-ups and GPIO boot levels.
export const r9StrapTracePaths: FanoutTracePath[] = [
{
connection: "U1.pin14",
route: [
{
route_type: "wire",
x: -0.750062,
y: -8.022484,
width: 0.15,
layer: "top",
},
{
route_type: "wire",
x: -0.750062,
y: -7.449938,
width: 0.15,
layer: "top",
},
{ route_type: "wire", x: -1.2, y: -7, width: 0.15, layer: "top" },
{ route_type: "wire", x: -1.2, y: -5.546636, width: 0.15, layer: "top" },
{ route_type: "wire", x: -2, y: -4.746636, width: 0.15, layer: "top" },
],
},
{
connection: "U1.pin6",
route: [
{
route_type: "wire",
x: 2.477516,
y: -9.749938,
width: 0.15,
layer: "top",
},
{ route_type: "wire", x: 4.1, y: -9.78, width: 0.15, layer: "top" },
{
route_type: "via",
x: 4.1,
y: -9.78,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
{ route_type: "wire", x: 4.1, y: -9.78, width: 0.15, layer: "bottom" },
{ route_type: "wire", x: 4.8, y: -9.08, width: 0.15, layer: "bottom" },
{ route_type: "wire", x: 4.8, y: -5, width: 0.15, layer: "bottom" },
{ route_type: "wire", x: 5.4, y: -4.4, width: 0.15, layer: "bottom" },
{ route_type: "wire", x: 5.4, y: 0.4, width: 0.15, layer: "bottom" },
{ route_type: "wire", x: 4.4, y: 1.4, width: 0.15, layer: "bottom" },
{
route_type: "via",
x: 4.4,
y: 1.4,
from_layer: "bottom",
to_layer: "top",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
{ route_type: "wire", x: 4.4, y: 1.4, width: 0.15, layer: "top" },
{ route_type: "wire", x: 4.5, y: 0.253364, width: 0.15, layer: "top" },
],
},
];
// Local frame of the explicit R4 fanout; physical board geometry is unchanged.
export const r9ChargeLedFanoutPaths: FanoutTracePath[] = [
...r9ChargeVbatTracePaths,
...r9ChargeLedTracePaths,
].map((path) => ({
...path,
route: path.route.map((point) => ({
...point,
...applyToPoint(translate(-8, -16.5), {
x: z.number().parse(point.x),
y: z.number().parse(point.y),
}),
})),
}));
// Complete charger programming-current filter branch; board XY mm,+Z top.
export const r9ProgFilterTracePaths: FanoutTracePath[] = [
{
connection: "C9.pin1",
route: [
{ route_type: "wire", x: -4.299976, y: 11, width: 0.15, layer: "top" },
{ route_type: "wire", x: -3.3, y: 12.3, width: 0.15, layer: "top" },
{
route_type: "via",
x: -3.3,
y: 12.3,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
{ route_type: "wire", x: -3.3, y: 12.3, width: 0.15, layer: "bottom" },
{ route_type: "wire", x: -3.3, y: 16.7, width: 0.15, layer: "bottom" },
{
route_type: "wire",
x: -0.0003175,
y: 16.7,
width: 0.15,
layer: "bottom",
},
{
route_type: "wire",
x: -0.0003175,
y: 15.8,
width: 0.15,
layer: "bottom",
},
],
},
{
connection: "C9.pin2",
route: [
{ route_type: "wire", x: -5.700024, y: 11, width: 0.15, layer: "top" },
{ route_type: "wire", x: -6.7, y: 9.8, width: 0.15, layer: "top" },
{
route_type: "via",
x: -6.7,
y: 9.8,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
];
export const r9ProgFilterFanoutPaths: FanoutTracePath[] =
r9ProgFilterTracePaths.map((path) => ({
...path,
route: path.route.map((point) => ({
...point,
...applyToPoint(translate(5, -11), {
x: z.number().parse(point.x),
y: z.number().parse(point.y),
}),
})),
}));
export const r9UsbDisablePaths: FanoutTracePath[] = r8UsbDisablePaths.map(
(path): FanoutTracePath => {
if (path.connection !== "R6.pin2") return path;
return {
...path,
route: [
...path.route,
{
route_type: "via",
x: -1.5,
y: 3.3,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
};
},
);
// U5's saved top return reaches the same physical barrel as C7 ground.
// Expose that existing layer transition to the plane routing phase.
export const r9SensorTracePaths: FanoutTracePath[] = sensorEscapePaths.map(
(path) =>
path.connection === "U5.pin3"
? {
...path,
route: [
...path.route,
{
route_type: "via",
x: 3.2,
y: 8.5,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
}
: path,
);
const batteryGroundWorldPaths: FanoutTracePath[] = [
{
connection: "J2.pin1",
route: [
{
route_type: "wire",
x: -15.9999913,
y: 13.499999,
width: 0.508,
layer: "top",
},
{
route_type: "wire",
x: -14.6,
y: 13.499999,
width: 0.508,
layer: "top",
},
{
route_type: "via",
x: -14.6,
y: 13.499999,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
{
connection: "J2.pin3",
route: [
{
route_type: "wire",
x: -19.8750153,
y: 11.200029,
width: 0.3,
layer: "top",
},
{ route_type: "wire", x: -19.8750153, y: 9.9, width: 0.3, layer: "top" },
{
route_type: "via",
x: -19.8750153,
y: 9.9,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
{
connection: "J2.pin4",
route: [
{
route_type: "wire",
x: -19.8750153,
y: 14.799971,
width: 0.3,
layer: "top",
},
{ route_type: "wire", x: -19.8750153, y: 16.1, width: 0.3, layer: "top" },
{
route_type: "via",
x: -19.8750153,
y: 16.1,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
];
const switchFrameWorldPaths: FanoutTracePath[] = [
{
connection: "SW1.pin4_internal_1",
route: [
{
route_type: "wire",
x: 20.90602235,
y: 8.599942,
width: 0.3,
layer: "top",
},
{ route_type: "wire", x: 20.9, y: 9.8, width: 0.3, layer: "top" },
{
route_type: "via",
x: 20.9,
y: 9.8,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
];
export const r9BatteryGroundWorldPaths = batteryGroundWorldPaths;
export const r9SwitchFrameWorldPaths = switchFrameWorldPaths;
export const r9BatteryGroundPaths = batteryGroundWorldPaths.map((path) => ({
...path,
route: path.route.map((point) => {
const moved = applyToPoint(translate(18, -13), {
x: z.number().parse(point.x),
y: z.number().parse(point.y),
});
return {
...point,
x: z.number().parse(moved.x),
y: z.number().parse(moved.y),
};
}),
}));
export const r9SwitchFramePaths = switchFrameWorldPaths.map((path) => ({
...path,
route: path.route.map((point) => {
const moved = applyToPoint(translate(-19, -5), {
x: z.number().parse(point.x),
y: z.number().parse(point.y),
});
return {
...point,
x: z.number().parse(moved.x),
y: z.number().parse(moved.y),
};
}),
}));
export const r9ChargeStatFanoutPaths = r9ChargeStatTracePaths.map((path) => ({
...path,
route: path.route.map((point) => {
const moved = applyToPoint(translate(-8, -26), {
x: z.number().parse(point.x),
y: z.number().parse(point.y),
});
return { ...point, x: moved.x, y: moved.y };
}),
}));
export const r9StatusLedFanoutPaths = r9StatusLedTracePaths.map((path) => ({
...path,
route: path.route.map((point) => {
const moved = applyToPoint(translate(15, 5), {
x: z.number().parse(point.x),
y: z.number().parse(point.y),
});
return { ...point, x: moved.x, y: moved.y };
}),
}));
export const r9ProgramGroundPaths: FanoutTracePath[] = [
{
connection: "J3.pin5",
route: [
{
route_type: "wire",
x: 14.200157,
y: 14.7999897,
width: 0.3,
layer: "top",
},
{ route_type: "wire", x: 12.9, y: 14.7999897, width: 0.3, layer: "top" },
{
route_type: "via",
x: 12.9,
y: 14.7999897,
from_layer: "top",
to_layer: "bottom",
via_diameter: 0.45,
via_hole_diameter: 0.3,
},
],
},
];