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-core-trace-paths.ts

import type { FanoutTracePath } from "@tscircuit/core";

// Authored board-world XY in mm, X right/Y up, +Z top. The containing fanout
// has a zero anchor. Terminals come from the unchanged supplier footprints.
function topPath({
	connection,
	pointsMm,
	widthMm = 0.15,
}: {
	connection: string;
	pointsMm: [number, number][];
	widthMm?: number;
}): FanoutTracePath {
	return {
		connection,
		route: pointsMm.map(([x, y]) => ({
			route_type: "wire",
			x,
			y,
			width: widthMm,
			layer: "top",
		})),
	};
}
function groundReturn({
	connection,
	pointsMm,
}: {
	connection: string;
	pointsMm: [number, number][];
}): FanoutTracePath {
	const route = topPath({ connection, pointsMm, widthMm: 0.3 });
	const [x, y] = pointsMm[pointsMm.length - 1];
	route.route.push({
		route_type: "via",
		x,
		y,
		from_layer: "top",
		to_layer: "bottom",
		via_diameter: 0.45,
		via_hole_diameter: 0.3,
	});
	return route;
}
// These supply terminals share one completed physical branch. Each saved
// fanout path must expose the same exit; touching another pad mid-path does
// not give that pad an exit in tscircuit's fanout contract.
function lowerV3BranchRoute(): FanoutTracePath["route"] {
	return [
		{ route_type: "wire", x: 1.449976, y: -14.75, width: 0.2, layer: "top" },
		{ route_type: "wire", x: 1.449976, y: -15.49, width: 0.2, layer: "top" },
		{ route_type: "wire", x: 4.1, y: -15.49, width: 0.2, layer: "top" },
		{ route_type: "wire", x: 4.1, y: -15.520116, width: 0.2, layer: "top" },
		{ route_type: "wire", x: 4.9, y: -15.520116, width: 0.508, layer: "top" },
		{ route_type: "wire", x: 9.2, y: -15.520116, width: 0.508, layer: "top" },
		{
			route_type: "via",
			x: 9.2,
			y: -15.520116,
			from_layer: "top",
			to_layer: "bottom",
			via_diameter: 0.45,
			via_hole_diameter: 0.3,
		},
		{
			route_type: "wire",
			x: 9.2,
			y: -15.520116,
			width: 0.508,
			layer: "bottom",
		},
		{ route_type: "wire", x: 9.2, y: -21.7, width: 0.508, layer: "bottom" },
		{ route_type: "wire", x: 8.4, y: -22.5, width: 0.508, layer: "bottom" },
		{ route_type: "wire", x: -7.3, y: -22.5, width: 0.508, layer: "bottom" },
		{ route_type: "wire", x: -8.1, y: -21.7, width: 0.508, layer: "bottom" },
		{
			route_type: "wire",
			x: -8.1,
			y: -8.299976,
			width: 0.508,
			layer: "bottom",
		},
		...lowerToUpperV3BridgeRoute().slice(4),
	];
}
function lowerV3SupplyPath({
	connection,
	pointsMm,
}: {
	connection: string;
	pointsMm: [number, number][];
}): FanoutTracePath {
	const path = topPath({ connection, pointsMm, widthMm: 0.3 });
	path.route.splice(-1, 1, ...lowerV3BranchRoute());
	return path;
}

export function upperV3BranchRoute(): FanoutTracePath["route"] {
	return [
		{ route_type: "wire", x: 0.7, y: -6.200024, width: 0.3, layer: "top" },
		{ route_type: "wire", x: 0.3, y: -6.200024, width: 0.3, layer: "top" },
		{ route_type: "wire", x: -0.6, y: -5.3, width: 0.3, layer: "top" },
		{
			route_type: "via",
			x: -0.6,
			y: -5.3,
			from_layer: "top",
			to_layer: "bottom",
			via_diameter: 0.45,
			via_hole_diameter: 0.3,
		},
		{ route_type: "wire", x: -0.6, y: -5.3, width: 0.508, layer: "bottom" },
		{ route_type: "wire", x: -0.6, y: -2.4, width: 0.508, layer: "bottom" },
		{ route_type: "wire", x: 4.55, y: -2.4, width: 0.508, layer: "bottom" },
		{
			route_type: "via",
			x: 4.55,
			y: -2.4,
			from_layer: "bottom",
			to_layer: "top",
			via_diameter: 0.45,
			via_hole_diameter: 0.3,
		},
		{ route_type: "wire", x: 4.55, y: -2.4, width: 0.508, layer: "top" },
		{ route_type: "wire", x: 5.9, y: -2.4, width: 0.508, layer: "top" },
		{ route_type: "wire", x: 5.9, y: -7.7, width: 0.508, layer: "top" },
		{ route_type: "wire", x: 5.845084, y: -7.7, width: 0.508, layer: "top" },
	];
}

// Complete the 0.508mm inter-bank trunk around the upper edge of the QFN
// ground-reference region. Reuse the existing lower-bank barrel and upper trunk.
function lowerToUpperV3BridgeRoute(): FanoutTracePath["route"] {
	return [
		{ route_type: "wire", x: -5.5, y: -8.299976, width: 0.508, layer: "top" },
		{ route_type: "wire", x: -8.1, y: -8.299976, width: 0.508, layer: "top" },
		{
			route_type: "via",
			x: -8.1,
			y: -8.299976,
			from_layer: "top",
			to_layer: "bottom",
			via_diameter: 0.45,
			via_hole_diameter: 0.3,
		},
		{
			route_type: "wire",
			x: -8.1,
			y: -8.299976,
			width: 0.508,
			layer: "bottom",
		},
		{ route_type: "wire", x: -8.1, 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 upperV3SupplyPath({
	connection,
	pointsMm,
}: {
	connection: string;
	pointsMm: [number, number][];
}): FanoutTracePath {
	const path = topPath({ connection, pointsMm, widthMm: 0.3 });
	path.route.splice(-1, 1, ...upperV3BranchRoute());
	return path;
}

// The two10k boot pull-ups are low-current leaves, not MCU supply trunks.
function bootPullupSupplyBranchRoute(): FanoutTracePath["route"] {
	return [
		{ route_type: "wire", x: -2, y: -6.253364, width: 0.15, layer: "top" },
		{ route_type: "wire", x: -3.2, y: -6.8, width: 0.15, layer: "top" },
		{ route_type: "wire", x: -3.2, y: -6.8, width: 0.15, layer: "top" },
		{
			route_type: "via",
			x: -3.2,
			y: -6.8,
			from_layer: "top",
			to_layer: "bottom",
			via_diameter: 0.45,
			via_hole_diameter: 0.3,
		},
		{ route_type: "wire", x: -3.2, y: -6.8, width: 0.15, layer: "bottom" },
		{ route_type: "wire", x: -3.2, y: -5.3, width: 0.15, layer: "bottom" },
		{ route_type: "wire", x: -0.6, y: -5.3, width: 0.15, layer: "bottom" },
		...upperV3BranchRoute().slice(4),
	];
}

// Physical top-only RF feed; both component terminals expose the antenna exit.
const rfAntennaFeedRoute: FanoutTracePath["route"] = [
	{ route_type: "wire", x: 6.245084, y: -12.65, width: 0.3, layer: "top" },
	{ route_type: "wire", x: 7.5, y: -12.649884, width: 0.3, layer: "top" },
	{ route_type: "wire", x: 9, y: -12.649884, width: 0.3, layer: "top" },
	{ route_type: "wire", x: 9.5, y: -12.65, width: 1.139, layer: "top" },
	{ route_type: "wire", x: 11, y: -12.65, width: 1.139, layer: "top" },
	{ route_type: "wire", x: 11, y: 17.921898, width: 1.139, layer: "top" },
	{ route_type: "wire", x: 15.5, y: 22.421898, width: 1.139, layer: "top" },
];

const coreTracePaths: FanoutTracePath[] = [
	{
		connection: "R14.pin1",
		route: [
			{ route_type: "wire", x: 4.5, y: -1.253364, width: 0.15, layer: "top" },
			{ route_type: "wire", x: 4.55, y: -2.4, width: 0.15, layer: "top" },
			...upperV3BranchRoute().slice(8),
		],
	},
	{
		connection: "R17.pin1",
		route: [
			{ route_type: "wire", x: 8.5, y: -10.253364, width: 0.15, layer: "top" },
			{ route_type: "wire", x: 9.2, y: -9.553364, width: 0.15, layer: "top" },
			{ route_type: "wire", x: 9.2, y: -7.7, width: 0.15, layer: "top" },
			{ route_type: "wire", x: 5.845084, y: -7.7, width: 0.15, layer: "top" },
		],
	},

	{ connection: "C15.pin1", route: lowerToUpperV3BridgeRoute() },
	{
		connection: "U1.pin15",
		route: [
			{
				route_type: "wire",
				x: -1.249934,
				y: -8.022484,
				width: 0.15,
				layer: "top",
			},
			{ route_type: "wire", x: -1.249934, y: -7.4, width: 0.15, layer: "top" },
			{ route_type: "wire", x: -4.3, y: -7.4, width: 0.15, layer: "top" },
			{
				route_type: "via",
				x: -4.3,
				y: -7.4,
				from_layer: "top",
				to_layer: "bottom",
				via_diameter: 0.45,
				via_hole_diameter: 0.3,
			},
		],
	},
	{
		connection: "U1.pin33",
		route: [
			{ route_type: "wire", x: 0, y: -10.5, width: 0.3, layer: "top" },
			{ route_type: "wire", x: 0.5, y: -10, width: 0.3, layer: "top" },
		],
	},

	{ connection: "R15.pin1", route: bootPullupSupplyBranchRoute() },
	{
		connection: "U1.pin27",
		route: [
			{
				route_type: "wire",
				x: -0.750062,
				y: -12.977516,
				width: 0.15,
				layer: "top",
			},
			{
				route_type: "wire",
				x: -0.750062,
				y: -13.45,
				width: 0.15,
				layer: "top",
			},
			{ route_type: "wire", x: -1.2, y: -13.9, width: 0.15, layer: "top" },
			{
				route_type: "via",
				x: -1.2,
				y: -13.9,
				from_layer: "top",
				to_layer: "bottom",
				via_diameter: 0.45,
				via_hole_diameter: 0.3,
			},
		],
	},
	{ connection: "C14.pin1", route: upperV3BranchRoute() },
	{
		connection: "U1.pin12",
		route: [
			{
				route_type: "wire",
				x: 0.249936,
				y: -8.022484,
				width: 0.15,
				layer: "top",
			},
			{ route_type: "wire", x: 0.249936, y: -7.2, width: 0.15, layer: "top" },
			{ route_type: "wire", x: -0.4, y: -6.550064, width: 0.15, layer: "top" },
			{
				route_type: "via",
				x: -0.4,
				y: -6.550064,
				from_layer: "top",
				to_layer: "bottom",
				via_diameter: 0.45,
				via_hole_diameter: 0.3,
			},
		],
	},
	{
		connection: "R16.pin1",
		route: [
			{ route_type: "wire", x: -5.3, y: -6.353364, width: 0.15, layer: "top" },
			{ route_type: "wire", x: -2.1, y: -6.353364, width: 0.15, layer: "top" },
			...bootPullupSupplyBranchRoute(),
		],
	},
	{
		connection: "U1.pin7",
		// EN/reset escape outside the continuous chip ground-reference region.
		route: [
			{
				route_type: "wire",
				x: 2.477516,
				y: -9.250066,
				width: 0.15,
				layer: "top",
			},
			{ route_type: "wire", x: 4.1, y: -9.250066, width: 0.15, layer: "top" },
			{ route_type: "wire", x: 4.1, y: -8.95, width: 0.15, layer: "top" },
			{
				route_type: "via",
				x: 4.1,
				y: -8.95,
				from_layer: "top",
				to_layer: "bottom",
				via_diameter: 0.45,
				via_hole_diameter: 0.3,
			},
			{ route_type: "wire", x: 4.1, y: -8.95, width: 0.15, layer: "bottom" },
			{ route_type: "wire", x: 3, y: -7.1, width: 0.15, layer: "bottom" },
			{
				route_type: "via",
				x: 3,
				y: -7.1,
				from_layer: "bottom",
				to_layer: "top",
				via_diameter: 0.45,
				via_hole_diameter: 0.3,
			},
		],
	},
	{ connection: "C17.pin1", route: lowerV3BranchRoute() },
	{ connection: "C18.pin1", route: lowerV3BranchRoute().slice(3) },
	{
		connection: "U1.pin9",
		// Side shutter GPIO4 escape above the chip ground-reference region.
		route: [
			{
				route_type: "wire",
				x: 1.75006,
				y: -8.022484,
				width: 0.15,
				layer: "top",
			},
			{
				route_type: "wire",
				x: 1.75006,
				y: -7.49994,
				width: 0.15,
				layer: "top",
			},
			{ route_type: "wire", x: 1.95, y: -6.85, width: 0.15, layer: "top" },
			{
				route_type: "via",
				x: 1.95,
				y: -6.85,
				from_layer: "top",
				to_layer: "bottom",
				via_diameter: 0.45,
				via_hole_diameter: 0.3,
			},
		],
	},
	{
		connection: "U1.pin28",
		// UART TX escapes left of the continuous crystal ground reference.
		route: [
			{
				route_type: "wire",
				x: -0.249936,
				y: -12.977516,
				width: 0.15,
				layer: "top",
			},
			{ route_type: "wire", x: -0.249936, y: -14.4, width: 0.15, layer: "top" },
			{ route_type: "wire", x: -4.5, y: -14.4, width: 0.15, layer: "top" },
			{ route_type: "wire", x: -6, y: -16.0, width: 0.15, layer: "top" },
			{
				route_type: "via",
				x: -6,
				y: -16.0,
				from_layer: "top",
				to_layer: "bottom",
				via_diameter: 0.45,
				via_hole_diameter: 0.3,
			},
		],
	},
	{
		connection: "U1.pin10",
		// GPIO5 pairing escape clears the local bypass lands and reaches bottom
		// above the reserved continuous ground reference under the chip.
		route: [
			{
				route_type: "wire",
				x: 1.249934,
				y: -8.022484,
				width: 0.15,
				layer: "top",
			},
			{ route_type: "wire", x: 1.249934, y: -7.3, width: 0.15, layer: "top" },
			{ route_type: "wire", x: 1.4, y: -7.149934, width: 0.15, layer: "top" },
			{ route_type: "wire", x: 1.4, y: -5.8, width: 0.15, layer: "top" },
			{ route_type: "wire", x: 1.8, y: -5.4, width: 0.15, layer: "top" },
			{
				route_type: "via",
				x: 1.8,
				y: -5.4,
				from_layer: "top",
				to_layer: "bottom",
				via_diameter: 0.45,
				via_hole_diameter: 0.3,
			},
		],
	},
	topPath({
		connection: "U1.pin1",
		widthMm: 0.2,
		pointsMm: [
			[2.477516, -12.25006],
			[3.05, -12.25006],
			[3.449824, -12.649884],
			[3.9, -12.649884],
		],
	}),
	topPath({
		connection: "C21.pin1",
		widthMm: 0.2,
		pointsMm: [
			[3.9, -12.649884],
			[5.154916, -12.65],
		],
	}),
	{ connection: "L4.pin1", route: rfAntennaFeedRoute },
	{ connection: "C22.pin1", route: rfAntennaFeedRoute.slice(1) },
	groundReturn({
		connection: "C21.pin2",
		pointsMm: [
			[3.9, -13.490116],
			[5.4, -13.490116],
			[5.4, -14.1],
		],
	}),
	groundReturn({
		connection: "C22.pin2",
		pointsMm: [
			[7.5, -13.490116],
			[7.5, -14.4],
		],
	}),
	// Both clock signals stay on top, with their reference plane reserved below.
	topPath({
		connection: "U1.pin30",
		pointsMm: [
			[0.750062, -12.977516],
			[0.750062, -16.65],
			[4.559984, -16.65],
			[4.559984, -17.2],
		],
	}),
	topPath({
		connection: "L3.pin2",
		pointsMm: [
			[6.340016, -17.2],
			[6.340016, -18.4],
			[3, -18.4],
			[3, -17.799976],
			[0.94996, -17.749938],
		],
	}),
	topPath({
		connection: "U1.pin29",
		pointsMm: [
			[0.249936, -12.977516],
			[0.249936, -14.4],
			[-1.2, -15.849936],
			[-2.05, -15.849936],
			[-2.05, -19.200024],
			[-0.94996, -19.250062],
		],
	}),
	topPath({
		connection: "C20.pin1",
		pointsMm: [
			[-3, -19.200024],
			[-2.05, -19.200024],
		],
	}),
	topPath({
		connection: "C19.pin1",
		pointsMm: [
			[3, -17.799976],
			[0.94996, -17.749938],
		],
	}),
	groundReturn({
		connection: "Y1.pin4",
		pointsMm: [
			[0.94996, -19.250062],
			[1.7, -20.000102],
			[1.7, -20.65],
		],
	}),
	topPath({
		connection: "C19.pin2",
		widthMm: 0.3,
		pointsMm: [
			[3, -19.200024],
			[3, -20.3],
			[2.65, -20.65],
			[1.7, -20.65],
		],
	}),
	groundReturn({
		connection: "Y1.pin2",
		pointsMm: [
			[-0.94996, -17.749938],
			[-0.94996, -16.45],
		],
	}),
	groundReturn({
		connection: "C20.pin2",
		pointsMm: [
			[-3, -17.799976],
			[-4.2, -17.799976],
		],
	}),
	// Low-inductance local supply paths; global supply trunks remain 0.508mm intent.
	topPath({
		connection: "U1.pin2",
		widthMm: 0.3,
		pointsMm: [
			[2.477516, -11.749934],
			[3.25, -11.749934],
			[4.099976, -10.899958],
			[5.199976, -10.899958],
			[5.199976, -9.4],
		],
	}),
	topPath({
		connection: "U1.pin3",
		widthMm: 0.3,
		pointsMm: [
			[2.477516, -11.250062],
			[3.25, -11.250062],
			[4.099976, -10.400086],
			[5.199976, -10.400086],
			[5.199976, -9.4],
		],
	}),
	topPath({
		connection: "L2.pin2",
		widthMm: 0.508,
		pointsMm: [
			[4.754916, -7.7],
			[4.754916, -8.5],
			[5.199976, -8.94506],
			[5.199976, -9.4],
		],
	}),
	topPath({
		connection: "C10.pin1",
		widthMm: 0.508,
		pointsMm: [
			[3.2, -5.799998],
			[4.754916, -7.354914],
			[4.754916, -7.7],
		],
	}),
	groundReturn({
		connection: "C5.pin2",
		pointsMm: [
			[6.600024, -9.4],
			[6.600024, -11.4],
		],
	}),
	groundReturn({
		connection: "C10.pin2",
		pointsMm: [
			[3.2, -3.800002],
			[4.6, -3.800002],
		],
	}),
	upperV3SupplyPath({
		connection: "U1.pin11",
		pointsMm: [
			[0.750062, -8.022484],
			[0.750062, -7.5],
			[0.7, -7.449938],
			[0.7, -6.200024],
		],
	}),
	groundReturn({
		connection: "C14.pin2",
		pointsMm: [
			[0.7, -4.799976],
			[0.7, -3.6],
		],
	}),
	topPath({
		connection: "U1.pin17",
		widthMm: 0.3,
		pointsMm: [
			[-2.477516, -8.74994],
			[-3.8, -8.74994],
			[-4.249964, -8.299976],
			[-5.5, -8.299976],
		],
	}),
	groundReturn({
		connection: "C15.pin2",
		pointsMm: [
			[-5.5, -9.700024],
			[-7, -9.700024],
		],
	}),
	topPath({
		connection: "U1.pin18",
		widthMm: 0.25,
		pointsMm: [
			[-2.477516, -9.250066],
			[-3.25, -9.250066],
			[-3.85, -9.850066],
			[-3.85, -11.599976],
			[-5.5, -11.599976],
		],
	}),
	groundReturn({
		connection: "C16.pin2",
		pointsMm: [
			[-5.5, -13.000024],
			[-7, -13.000024],
		],
	}),
	lowerV3SupplyPath({
		connection: "U1.pin31",
		pointsMm: [
			[1.249934, -12.977516],
			[1.249934, -13.7],
			[1.449976, -13.900042],
			[1.449976, -14.75],
		],
	}),
	lowerV3SupplyPath({
		connection: "U1.pin32",
		pointsMm: [
			[1.75006, -12.977516],
			[1.75006, -13.7],
			[1.449976, -14.000084],
			[1.449976, -14.75],
		],
	}),
	topPath({
		connection: "C17.pin2",
		widthMm: 0.3,
		pointsMm: [
			[2.850024, -14.75],
			[3.500024, -14.1],
			[5.4, -14.1],
		],
	}),
	topPath({
		connection: "C18.pin2",
		widthMm: 0.3,
		pointsMm: [
			[4.1, -14.679884],
			[4.1, -14.1],
			[5.4, -14.1],
		],
	}),
];

// Expose the existing shared ground barrels on the target plane for each
// connected bypass terminal. Core deduplicates identical physical vias.
export const r9CoreTracePaths: FanoutTracePath[] = coreTracePaths.map(
	(path): FanoutTracePath => {
		if (path.connection === "U1.pin10")
			return {
				...path,
				route: [
					...path.route,
					{ route_type: "wire", x: 1.8, y: -5.4, width: 0.15, layer: "bottom" },
					{ route_type: "wire", x: 1.6, y: -5.2, width: 0.15, layer: "bottom" },
					{ route_type: "wire", x: 1.6, y: -3.4, width: 0.15, layer: "bottom" },
					{
						route_type: "via",
						x: 1.6,
						y: -3.4,
						from_layer: "bottom",
						to_layer: "top",
						via_diameter: 0.45,
						via_hole_diameter: 0.3,
					},
				],
			};
		if (path.connection === "U1.pin12")
			return {
				...path,
				route: [
					...path.route,
					{
						route_type: "wire",
						x: -0.4,
						y: -6.550064,
						width: 0.15,
						layer: "bottom",
					},
					{
						route_type: "wire",
						x: -1.4,
						y: -7.3,
						width: 0.15,
						layer: "bottom",
					},
					{
						route_type: "wire",
						x: -3.5,
						y: -7.3,
						width: 0.15,
						layer: "bottom",
					},
					{
						route_type: "wire",
						x: -3.8,
						y: -6.7,
						width: 0.15,
						layer: "bottom",
					},
					{
						route_type: "wire",
						x: -3.8,
						y: -5.4,
						width: 0.15,
						layer: "bottom",
					},
					{
						route_type: "via",
						x: -3.8,
						y: -5.4,
						from_layer: "bottom",
						to_layer: "top",
						via_diameter: 0.45,
						via_hole_diameter: 0.3,
					},
				],
			};
		if (path.connection === "U1.pin17")
			return {
				...path,
				route: [...path.route, ...lowerToUpperV3BridgeRoute().slice(1)],
			};
		if (!["C17.pin2", "C18.pin2", "C19.pin2"].includes(path.connection))
			return path;
		const last = path.route.at(-1);
		if (!last || last.route_type !== "wire")
			throw new Error("Shared ground return requires a wire endpoint");
		return {
			...path,
			route: [
				...path.route,
				{
					route_type: "via",
					x: last.x,
					y: last.y,
					from_layer: "top",
					to_layer: "bottom",
					via_diameter: 0.45,
					via_hole_diameter: 0.3,
				},
			],
		};
	},
);