pixalynx/usb3-hub-10g

A USB 3.2 Gen 2 six-port hub board with USB-C PD power input, regulated 5 V/3.3 V/1.15 V rails, one upstream and four protected downstream USB-A/USB-C ports, SuperSpeed muxes, ESD protection, and controlled port power.

Version
0.0.1
License
unset
Stars
0

lib/passives.tsx

import type { ReactElement } from "react"
import { JlcFootprint, type JlcKey } from "./jlc"
import { pcb } from "./place"
import { Cap0201Lane } from "./footprints"
import { CAD, type CadKey } from "./cad-models"
import { onSheet } from "./layout"

/** Two-terminal passives wired straight to their nets. Every value carries the JLCPCB part the BOM uses; the
 * table is keyed `${value}@${package}` so a value change is a one-line edit. Checked with scripts/passives.py
 * (jlcsearch) on 2026-09-29: B = JLC Basic, P = Preferred, others Extended. */
export const JLC: Record<string, string> = {
  // capacitors
  "100nF@0402": "C1525" /* B 16V X7R */, "100nF50V@0402": "C307331" /* B 50V X7R */, "1uF@0402": "C52923" /* B 25V */,
  "4.7uF@0402": "C23733" /* B 10V */, "10uF@0603": "C19702" /* B 10V */, "10uF@0805": "C15850" /* B 25V */,
  "22uF@0805": "C45783" /* B 25V */, "22uF@1206": "C12891" /* B 25V */, "10uF50V@1206": "C13585" /* B 50V */,
  "100nF50V@0603": "C14663" /* B */, "1uF50V@0603": "C15849" /* B */, "100nF@0201": "C76939" /* 25V X5R */, "100k@0201": "C270364", "10k@0201": "C106225" /* Yageo RC0201FR-0710KL */,
  "47nF@0402": "C285062", "150pF@0402": "C1527" /* P */, "18pF@0402": "C1549" /* B C0G */, "10nF@0402": "C15195" /* B */,
  "100uF@1206": "C15008" /* B 6.3V */,
  // resistors (1 %)
  "10k@0402": "C25744", "100k@0402": "C25741", "200k@0402": "C25764", "12k@0402": "C25752", "120k@0402": "C25750",
  "75k@0402": "C25798", "22k@0402": "C25768", "24k@0402": "C25769", "15k@0402": "C25756", "13.7k@0402": "C25854",
  "52.3k@0402": "C26982", "4.7k@0402": "C25900", "499k@0402": "C2998054", "887k@0402": "C409935", "1.5k@0402": "C25867",
  "5.1k@0402": "C25905", "1k@0402": "C11702", "1M@0402": "C26083", "49.9k@0402": "C25897",
}

export type Side = "top" | "bottom"
export type Place = { x?: number; y?: number; rot?: number; side?: Side; sx?: number; sy?: number; srot?: number; sec?: string }
type Two = Place & { name: string; v: string; a: string; b: string; fp?: string; jlc?: string; volts?: 50; horiz?: boolean; flip?: boolean }

const sel = (s: string) => (s.startsWith("net.") || s.includes(".") ? s : `net.${s}`)
const wires = (name: string, a: string, b: string) => [
  <trace key={`${name}a`} from={`${name}.pin1`} to={sel(a)} />,
  <trace key={`${name}b`} from={`${name}.pin2`} to={sel(b)} />,
]
const placeProps = (p: Place & { name: string }) => ({
  ...pcb(p.name, { x: p.x, y: p.y, rot: p.rot }), layer: p.side ?? "top",
  schX: p.sx, schY: p.sy, schRotation: p.srot ?? 0, schSectionName: p.sec, ...onSheet(p.sec),
})
/** Schematic default for resistors: vertical with pin1 (`a`, the supply or signal side) on top, so a pull-down reads
 * signal-over-ground and a pull-up supply-over-signal. */
const RES_SROT = -90
const jlcOf = (p: Two, fp: string) => p.jlc ?? JLC[`${p.v}${p.volts === 50 ? "50V" : ""}@${fp === "0201lane" ? "0201" : fp}`]

/** Resistor from `a` (pin1) to `b` (pin2); `a`/`b` are net names ("GND", "net.GND") or port selectors ("U1.RBIAS"). */
export const R = (p: Two): ReactElement => {
  const fp = p.fp ?? "0402"
  const jlc = jlcOf(p, fp)
  return (
    <>
      <resistor name={p.name} resistance={p.v} footprint={fp === "0201lane" ? <Cap0201Lane /> : fp} cadModel={fp === "0201lane" ? CAD.res0201 : undefined} {...placeProps({ ...p, srot: p.srot ?? RES_SROT })} supplierPartNumbers={jlc ? { jlcpcb: [jlc] } : undefined} />
      {wires(p.name, p.a, p.b)}
    </>
  )
}
/** Capacitor from `a` (pin1) to `b` (pin2). Drawn vertically with pin1 on top (`flip`: pin1 at the bottom, to keep a
 * supply rail on top), or horizontally (pin1 left) with `horiz` for series parts such as AC-coupling caps. */
export const C = (p: Two): ReactElement => {
  const fp = p.fp ?? "0402"
  const jlc = jlcOf(p, fp)
  const footprint = fp === "poscapB" ? <JlcFootprint part={fp as JlcKey} /> : fp === "0201lane" ? <Cap0201Lane /> : fp
  return (
    <>
      <capacitor name={p.name} capacitance={p.v} footprint={footprint} {...placeProps(p)} schOrientation={p.horiz ? "horizontal" : p.flip ? "pos_bottom" : "vertical"}
        cadModel={fp === "poscapB" ? CAD.poscapB : fp === "0201lane" ? CAD.cap0201 : undefined}
        supplierPartNumbers={jlc ? { jlcpcb: [jlc] } : undefined} />
      {wires(p.name, p.a, p.b)}
    </>
  )
}
/** Body courtyards wider than the land extent (footprint frame, mm): the IHLP-4040 body is 10.2 x 10.2 around its pads. */
const BODY: Partial<Record<JlcKey, [number, number, number, number]>> = { ihlp4040: [-5.8, -5.35, 5.8, 5.35] }
/** Inductor on one of JLC's land patterns. */
export const L = (p: Two & { part: JlcKey; mpn: string }): ReactElement => (
  <>
    <inductor name={p.name} inductance={p.v} footprint={<JlcFootprint part={p.part} body={BODY[p.part]} />} cadModel={CAD[p.part as CadKey]} {...placeProps(p)}
      manufacturerPartNumber={p.mpn} supplierPartNumbers={p.jlc ? { jlcpcb: [p.jlc] } : undefined} />
    {wires(p.name, p.a, p.b)}
  </>
)
/** White 0603 status LED (JLC Basic C2290, pad 1 = anode) with its series resistor from `rail`. On the schematic the
 * resistor (at sx, sy) stands on the LED's anode, rail on top and the cathode to ground below, joined by a 0.1 wire:
 * the unnamed resistor-anode net needs no label. */
const LED_DROP = 0.94   // resistor half-length 0.3 + LED half-length 0.54, plus a 0.1 wire so the bodies don't touch
export const Led = (p: Place & { name: string; rname: string; rail: string; r?: string; rx?: number; ry?: number; rrot?: number }): ReactElement => (
  <>
    <led name={p.name} color="white" footprint={<JlcFootprint part="led0603" />} cadModel={CAD.led0603} pinLabels={{ pin1: ["anode"], pin2: ["cathode"] }}
      {...placeProps({ ...p, sx: p.sx, sy: (p.sy ?? 0) - LED_DROP, srot: -90 })} supplierPartNumbers={{ jlcpcb: ["C2290"] }} />
    {R({ name: p.rname, v: p.r ?? "1.5k", a: p.rail, b: `${p.name}.pin1`, x: p.rx, y: p.ry, rot: p.rrot, side: p.side, sx: p.sx, sy: p.sy, sec: p.sec })}
    <trace from={`${p.name}.pin2`} to="net.GND" />
  </>
)