astra/f1c100s

The code defines the physical pin layout, labels, and footprint for the F1C100S system-on-chip (SoC) component used in electronic devices.

Version
0.9.2
License
unset
Stars
0

scripts/check-conventions.ts

import type { CircuitJson } from "circuit-json";

/** Inspect emitted copper, rather than relying on router settings. */
export function checkConventionalRouting(json: CircuitJson): string[] {
	const errors: string[] = [];
	for (const t of json as any[])
		if (t.type === "pcb_trace") {
			for (let i = 1; i < t.route.length; i++) {
				const a = t.route[i - 1],
					b = t.route[i];
				// Include wire-to-via approaches as well as wire-to-wire runs.
				// A layer change at one via has zero XY length.
				const dx = Math.abs(b.x - a.x),
					dy = Math.abs(b.y - a.y);
				if (Math.min(dx, dy, Math.abs(dx - dy)) > 1e-6)
					errors.push(`${t.pcb_trace_id}[${i}]: non-45-degree segment`);
			}
		}
	for (const e of json as any[]) {
		if (
			(e.type === "pcb_component" || e.type === "pcb_smtpad") &&
			e.layer !== "top"
		)
			errors.push(`${e.type}: component copper is not on top`);
	}
	const nets = (json as any[]).filter(
		(e) => e.type === "source_trace" && /^N_HOSC[IO]$/.test(e.name),
	);
	for (const net of nets) {
		const routes = (json as any[]).filter(
			(e) =>
				e.type === "pcb_trace" && e.source_trace_id === net.source_trace_id,
		);
		if (
			routes.some((t) =>
				t.route.some((p: any) => p.route_type !== "wire" || p.layer !== "top"),
			)
		)
			errors.push(
				`${net.name}: crystal signal must remain on top without vias`,
			);
		for (const t of routes) {
			const length = t.route.reduce(
				(sum: number, b: any, i: number) =>
					i
						? sum + Math.hypot(b.x - t.route[i - 1].x, b.y - t.route[i - 1].y)
						: sum,
				0,
			);
			if (length > 10) errors.push(`${net.name}: crystal route exceeds 10 mm`);
		}
	}
	return errors;
}