rushabhcodes/usb-audio-dac

A tscircuit package created by rushabhcodes.

Version
1.1.2
License
unset
Stars
0

index.circuit.tsx

PCBPCB preview for index.circuit.tsx
SchematicSchematic preview for index.circuit.tsx
import { Fragment } from "react"
import { assembly } from "tscircuit"
import { SnapFitEnclosure, mountingPoints } from "./enclosure"
import { glyphLineAlphabet, glyphAdvanceRatio } from "@tscircuit/alphabet"
import {
  UsbCReceptacle, UsbEsdProtection, UsbDac, Regulator3V3,
  HeadphoneAmplifier, HeadphoneJack, Crystal12MHz, PowerFerriteBead,
  Resistor22Ohm, Resistor1k5, Resistor5k1, Resistor100k, Resistor1M,
  Capacitor100nF, Capacitor1uF, Capacitor2u2, Capacitor10uF, Capacitor33pF,
  Capacitor22nF,
} from "./imports"

const GND = "net.GND"
const VBUS = "net.USB_5V"
const V5 = "net.FILTERED_5V"
const V3 = "net.AMP_3V3"
const DVDD = "net.DAC_DVDD"
const active = "net.USB_ACTIVE"

const referenceStyle = { pcbSx: { "& silkscreentext": { visibility: "hidden" } } } as const
const referenceLabels = [
  ["J1", -24, 6.7],
  ["J2", 23, 6.7],
  ["R1", -18.5, 6.1],
  ["R2", -18.5, -6.1],
  ["U1", -16, 2.7],
  ["C1", -16.15, -2.4],
  ["R3", -7.5, -10],
  ["R4", -4, -10],
  ["R5", -11, -10.3],
  ["FB1", -19, -10.8],
  ["C2", -15.5, -12],
  ["U2", -8, -14.8],
  ["C3", -1.5, -12],
  ["U3", -5.5, 1],
  ["R6", -16, -8.1],
  ["C4", -7.5, -5.5],
  ["C5", -6.6, 9],
  ["C6", 0.2, -4],
  ["C7", 0.5, 7.5],
  ["C8", -3.225, 13.6],
  ["C9", -0.5, -10.1],
  ["X1", -16, 4.5],
  ["R7", -14.5, -5.3],
  ["C10", -12.5, 6.5],
  ["C11", -11, -5.5],
  ["R9", 3, -4],
  ["R10", 4.5, 11],
  ["C18", 5, -9],
  ["C19", 10.8, 9.5],
  ["C12", 3, 3.3],
  ["C13", 3, -2.5],
  ["U4", 7, 7.2],
  ["R8", 4, 7.5],
  ["C14", 10.5, 6.5],
  ["C15", 13.8, 6],
  ["C16", 14, 0.75],
  ["C17", 9, -4.5],
] as const

const dacPosition = { pcbX: -5.5, pcbY: 1, pcbRotation: 0 }
const crystalPosition = { pcbX: -13, pcbY: 1, pcbRotation: 270 }

// One millimetre characters with 0.15 mm ink meet JLCPCB's legend limits.
function SilkLabel({ text, x, y }: { text: string; x: number; y: number }) {
  let advance = 0
  const lines = [...text].flatMap((char) => {
    const offset = advance
    advance += glyphAdvanceRatio[char] ?? 0.7
    return (glyphLineAlphabet[char] ?? []).map((line) => ({
      x1: line.x1 + offset, y1: line.y1, x2: line.x2 + offset, y2: line.y2,
    }))
  })
  const left = Math.min(...lines.flatMap((p) => [p.x1, p.x2]))
  const right = Math.max(...lines.flatMap((p) => [p.x1, p.x2]))
  const bottom = Math.min(...lines.flatMap((p) => [p.y1, p.y2]))
  const top = Math.max(...lines.flatMap((p) => [p.y1, p.y2]))
  const scale = 1 / (top - bottom)
  const point = (px: number, py: number) => ({
    x: x + (px - (left + right) / 2) * scale,
    y: y + (py - (bottom + top) / 2) * scale,
  })
  return <>{lines.map((p, i) => <Fragment key={i}><silkscreenpath strokeWidth={0.15}
    route={[point(p.x1, p.y1), point(p.x2, p.y2)]} /></Fragment>)}</>
}

// tscircuit pcbPath points are relative to the starting component's footprint.
function relativePath(at: typeof dacPosition, points: { x: number; y: number }[]) {
  const angle = -at.pcbRotation * Math.PI / 180
  return points.map(({ x, y }) => ({
    x: (x - at.pcbX) * Math.cos(angle) - (y - at.pcbY) * Math.sin(angle),
    y: (x - at.pcbX) * Math.sin(angle) + (y - at.pcbY) * Math.cos(angle),
  }))
}

/** Svara USB revision B. See README.md for design assumptions and release checks. */
export default function SvaraUsb() {
  return (
    <assembly.device name="SvaraUsb">
    <board name="B1" width="54mm" height="32mm" layers={2} thickness="1.6mm"
      minTraceWidth="0.15mm" autorouter={{ preset: "auto_local", traceClearance: 0.2 }}
      schLayout={{ layoutMode: "none" }}
      minViaHoleDiameter={0.3} minViaPadDiameter={0.6}
      minTraceToHoleEdgeClearance={0.25} minTraceToPadEdgeClearance={0.15} minPadEdgeToPadEdgeClearance={0.15}>
      <schematicsheet name="Svara USB revision B" sheetSize="ANSI_B" sheetWidth={650} sheetHeight={340}>
      <net name="GND" isGroundNet nominalTraceWidth="0.2mm" />
      <net name="USB_5V" isPowerNet nominalTraceWidth="0.15mm" />
      <net name="FILTERED_5V" isPowerNet nominalTraceWidth="0.15mm" />
      <net name="AMP_3V3" isPowerNet nominalTraceWidth="0.2mm" />
      <net name="DAC_DVDD" isPowerNet />
      <net name="DAC_VCCP" isPowerNet />
      <net name="DAC_VCCL" isPowerNet />
      <net name="DAC_VCCR" isPowerNet />

      {/* USB-C USB 2.0 sink: separate Rd resistors, duplicated data contacts. */}
      <UsbCReceptacle {...referenceStyle} name="J1" allowOffBoard pcbX={-23.1} pcbY={0} pcbRotation={270}
        schX={-24} schY={5} schWidth={3} schHeight={7}
        connections={{
          EH1: GND, EH2: GND, EH3: GND, EH4: GND, GND1: GND, GND2: GND,
          VBUS1: VBUS, VBUS2: VBUS, CC1: "net.CC1", CC2: "net.CC2",
          DP1: "net.USB_DP", DP2: "net.USB_DP", DN1: "net.USB_DM", DN2: "net.USB_DM",
        }} />
      <Resistor5k1 {...referenceStyle} name="R1" pcbX={-18.5} pcbY={4} pcbRotation={90} schX={-26} schY={-2}
        connections={{ pin1: "net.CC1", pin2: GND }} />
      <Resistor5k1 {...referenceStyle} name="R2" pcbX={-18.5} pcbY={-4} pcbRotation={90} schX={-22} schY={-2}
        connections={{ pin1: "net.CC2", pin2: GND }} />
      {/* USBLC6: feed-through channels 1/6, 3/4; 2=GND, 5=VBUS. */}
      <UsbEsdProtection {...referenceStyle} name="U1" pcbX={-17.5} pcbY={0} pcbRotation={270}
        schX={-18} schY={5}
        connections={{ pin1: "net.USB_DP", pin6: "net.USB_DP",
          pin3: "net.USB_DM", pin4: "net.USB_DM", pin2: GND, pin5: VBUS }} />
      <Capacitor100nF {...referenceStyle} name="C1" pcbX={-16.15} pcbY={-4}
        schX={-18} schY={1} schRotation={270}
        connections={{ pin1: VBUS, pin2: GND }} />
      <Resistor22Ohm {...referenceStyle} name="R3" pcbX={-7.5} pcbY={-8} pcbRotation={90}
        schX={-12} schY={5.5}
        connections={{ pin1: "net.USB_DM", pin2: "net.DAC_DM" }} />
      <Resistor22Ohm {...referenceStyle} name="R4" pcbX={-4} pcbY={-8} pcbRotation={90}
        schX={-12} schY={4}
        connections={{ pin1: "net.USB_DP", pin2: "net.DAC_DP" }} />
      {/* Pull-up on cable side of the series resistor, powered by DAC VDD. */}
      <Resistor1k5 {...referenceStyle} name="R5" pcbX={-11} pcbY={-8} pcbRotation={90}
        schX={-15} schY={8} schRotation={270}
        connections={{ pin1: DVDD, pin2: "net.USB_DP" }} />

      {/* DAC uses internal regulators; LP5907 powers only the amplifier. */}
      <PowerFerriteBead {...referenceStyle} name="FB1" pcbX={-19} pcbY={-9} schX={-24} schY={-8}
        connections={{ pin1: VBUS, pin2: V5 }} />
      <Capacitor1uF {...referenceStyle} name="C2" pcbX={-13} pcbY={-12} pcbRotation={90}
        schX={-21} schY={-10} schRotation={270}
        connections={{ pin1: V5, pin2: GND }} />
      <Regulator3V3 {...referenceStyle} name="U2" pcbX={-8} pcbY={-12} pcbRotation={180}
        schX={-16} schY={-8} schWidth={3}
        connections={{ IN: V5, EN: V5, GND, OUT: V3 }} />
      <Capacitor1uF {...referenceStyle} name="C3" pcbX={-4} pcbY={-12} pcbRotation={90}
        schX={-12} schY={-10} schRotation={270}
        connections={{ pin1: V3, pin2: GND }} />

      {/* PCM2704C bus-powered, 100 mA descriptor, default USB identity.
          Its four 3.3 V output rails are intentionally separate. */}
      <UsbDac {...referenceStyle} name="U3" {...dacPosition}
        schX={0} schY={3} schWidth={5} schHeight={9}
        schPinArrangement={{
          leftSide: [8, 9, 28, 1, 3, 2, 4, 21, 25, 26, 22, 23, 24],
          rightSide: [14, 15, 27, 5, 18], topSide: [10, 7, 20, 13, 16],
          bottomSide: [6, 11, 12, 17, 19],
        }}
        connections={{
          VBUS: V5, VDD: DVDD, VCCP: "net.DAC_VCCP", VCCL: "net.DAC_VCCL",
          VCCR: "net.DAC_VCCR", VCOM: "net.DAC_VCOM",
          DGND: GND, ZGND: GND, AGNDL: GND, AGNDR: GND, PGND: GND,
          D_NEG: "net.DAC_DM", D_POS: "net.DAC_DP", XTI: "net.XTI", XTO: "net.XTO",
          DT: "net.ROM_DATA", PSEL: DVDD, HOST: GND, TEST0: DVDD, TEST1: DVDD,
          HID0: GND, HID1: GND, HID2: GND, N_SSPND: active,
          VOUTL: "net.DAC_L", VOUTR: "net.DAC_R",
        }} />
      <Resistor100k {...referenceStyle} name="R6" pcbX={-16} pcbY={-6.5}
        schX={-7} schY={7} schRotation={270}
        connections={{ pin1: DVDD, pin2: "net.ROM_DATA" }} />
      <Capacitor1uF {...referenceStyle} name="C4" pcbX={-5.825} pcbY={-5.5} pcbRotation={270}
        schX={-6} schY={13} schRotation={270}
        connections={{ pin1: DVDD, pin2: GND }} />
      <Capacitor1uF {...referenceStyle} name="C5" pcbX={-4.525} pcbY={7.5} pcbRotation={90}
        schX={-3} schY={13} schRotation={270}
        connections={{ pin1: "net.DAC_VCCP", pin2: GND }} />
      <Capacitor1uF {...referenceStyle} name="C6" pcbX={-1.925} pcbY={-5.5} pcbRotation={270}
        schX={0} schY={13} schRotation={270}
        connections={{ pin1: "net.DAC_VCCL", pin2: GND }} />
      <Capacitor1uF {...referenceStyle} name="C7" pcbX={-1.925} pcbY={7.5} pcbRotation={90}
        schX={3} schY={13} schRotation={270}
        connections={{ pin1: "net.DAC_VCCR", pin2: GND }} />
      <Capacitor10uF {...referenceStyle} name="C8" pcbX={-3.225} pcbY={11} pcbRotation={90}
        schX={6} schY={13} schRotation={270}
        connections={{ pin1: "net.DAC_VCOM", pin2: GND }} />
      <Capacitor1uF {...referenceStyle} name="C9" pcbX={-0.5} pcbY={-8} pcbRotation={90}
        schX={-9} schY={13} schRotation={270}
        connections={{ pin1: V5, pin2: GND }} />

      {/* CL ≈ 33 pF / 2 + 3.5 pF stray = 20 pF; verify on the prototype. */}
      <Crystal12MHz {...referenceStyle} name="X1" {...crystalPosition}
        schX={-1} schY={-9}
        connections={{ pin1: "net.XTI", pin3: "net.XTO", pin2: GND, pin4: GND }} />
      <Resistor1M {...referenceStyle} name="R7" pcbX={-13} pcbY={-2}
        schX={-1} schY={-6}
        connections={{ pin1: "net.XTI", pin2: "net.XTO" }} />
      <Capacitor33pF {...referenceStyle} name="C10" pcbX={-12.5} pcbY={5}
        schX={-5} schY={-11} schRotation={270}
        connections={{ pin1: "net.XTI", pin2: GND }} />
      <Capacitor33pF {...referenceStyle} name="C11" pcbX={-12.5} pcbY={-3.8}
        schX={3} schY={-11} schRotation={270}
        connections={{ pin1: "net.XTO", pin2: GND }} />

      {/* Keep all oscillator branches on the top layer. */}
      <trace name="CLK_IN" from="U3.XTI" to="X1.pin1" width={0.15}
        pcbPath={relativePath(dacPosition, [{ x: -9.725036, y: 4.455162 }, { x: -11, y: 4.455162 },
          { x: -11, y: 3.6 }, { x: -13.850011, y: 3.6 }, { x: -13.850011, y: 2.100074 }])} />
      <trace name="CLK_OUT" from="U3.XTO" to="X1.pin3" width={0.15}
        pcbPath={relativePath(dacPosition, [{ x: -9.725036, y: -2.455162 }, { x: -11, y: -2.455162 },
          { x: -11, y: -0.100074 }, { x: -12.149989, y: -0.100074 }])} />
      <trace name="CLK_LOAD_IN" from="X1.pin1" to="C10.pin1" width={0.15}
        pcbPath={relativePath(crystalPosition, [{ x: -13.850011, y: 2.100074 }, { x: -14.8, y: 3.05 },
          { x: -14.8, y: 5 }, { x: -13.200024, y: 5 }])} />
      <trace name="CLK_LOAD_OUT" from="X1.pin3" to="C11.pin1" width={0.15}
        pcbPath={relativePath(crystalPosition, [{ x: -12.149989, y: -0.100074 }, { x: -12.149989, y: -2.8 }, { x: -13.200024, y: -3.8 }])} />
      <trace name="CLK_BIAS_IN" from="X1.pin1" to="R7.pin1" width={0.15}
        pcbPath={relativePath(crystalPosition, [{ x: -13.850011, y: 2.100074 }, { x: -15.2, y: 2.100074 }, { x: -15.2, y: -2 }, { x: -13.7, y: -2 }])} />
      <trace name="CLK_BIAS_OUT" from="X1.pin3" to="R7.pin2" width={0.15}
        pcbPath={relativePath(crystalPosition, [{ x: -12.149989, y: -0.100074 }, { x: -12.149989, y: -2 }, { x: -12.3, y: -2 }])} />

      {/* 22 ohm/22 nF RF filters, then AC coupling (fc ≈ 8 Hz at 0 dB gain).
          DirectPath outputs need no output coupling capacitors. */}
      <Resistor22Ohm {...referenceStyle} name="R9" pcbX={2} pcbY={-5.5}
        schX={8} schY={7}
        connections={{ pin1: "net.DAC_L", pin2: "net.FILTER_L" }} />
      <Resistor22Ohm {...referenceStyle} name="R10" pcbX={4.5} pcbY={9.5}
        schX={8} schY={4}
        connections={{ pin1: "net.DAC_R", pin2: "net.FILTER_R" }} />
      <Capacitor22nF {...referenceStyle} name="C18" pcbX={5} pcbY={-7} pcbRotation={90}
        schX={10} schY={5.5} schRotation={270}
        connections={{ pin1: "net.FILTER_L", pin2: GND }} />
      <Capacitor22nF {...referenceStyle} name="C19" pcbX={8} pcbY={9.5} pcbRotation={90}
        schX={10} schY={2.5} schRotation={270}
        connections={{ pin1: "net.FILTER_R", pin2: GND }} />
      <Capacitor1uF {...referenceStyle} name="C12" pcbX={3} pcbY={1.75}
        schX={12} schY={7}
        connections={{ pin1: "net.FILTER_L", pin2: "net.AMP_INL" }} />
      <Capacitor1uF {...referenceStyle} name="C13" pcbX={3} pcbY={-0.75}
        schX={12} schY={4}
        connections={{ pin1: "net.FILTER_R", pin2: "net.AMP_INR" }} />
      <HeadphoneAmplifier {...referenceStyle} name="U4" pcbX={7} pcbY={1}
        schX={19} schY={3} schWidth={4} schHeight={6}
        schPinArrangement={{ leftSide: [1, 4, 2, 3, 13, 6, 7],
          rightSide: [16, 5, 11, 9, 8, 12], topSide: [14], bottomSide: [15, 10, 17] }}
        connections={{
          INL_NEG: "net.AMP_INL", INR_NEG: "net.AMP_INR", INL_POS: GND, INR_POS: GND,
          VDD: V3, EN: active, G0: V3, G1: GND, // G0=1, G1=0: 0 dB.
          SGND: GND, PGND: GND, EP: GND, CPP: "net.CP_POS", CPN: "net.CP_NEG",
          HPVDD: "net.HPVDD", HPVSS: "net.HPVSS", OUTL: "net.HP_L", OUTR: "net.HP_R",
        }} />
      <Resistor100k {...referenceStyle} name="R8" pcbX={4} pcbY={6}
        schX={12} schY={-1} schRotation={270}
        connections={{ pin1: active, pin2: GND }} />
      <Capacitor2u2 {...referenceStyle} name="C14" pcbX={7} pcbY={5} pcbRotation={90}
        schX={13} schY={12} schRotation={270}
        connections={{ pin1: V3, pin2: GND }} />
      {/* HPVDD is internally generated. Never connect to AMP_3V3. */}
      <Capacitor2u2 {...referenceStyle} name="C15" pcbX={11} pcbY={4}
        schX={26} schY={-5} schRotation={270}
        connections={{ pin1: "net.HPVDD", pin2: GND }} />
      <Capacitor1uF {...referenceStyle} name="C16" pcbX={11} pcbY={0.75} pcbRotation={90}
        schX={22} schY={-5}
        connections={{ pin1: "net.CP_NEG", pin2: "net.CP_POS" }} />
      <Capacitor1uF {...referenceStyle} name="C17" pcbX={9} pcbY={-3}
        schX={18} schY={-5} schRotation={270}
        connections={{ pin1: "net.HPVSS", pin2: GND }} />
      {/* PJ-320D: 2=tip L, 3=ring R, 4=second ring, 1=sleeve.
          Ground both return contacts for TRS headphones; no microphone input. */}
      <HeadphoneJack {...referenceStyle} name="J2" allowOffBoard pcbX={20.9} pcbY={0} pcbRotation={180}
        schX={29} schY={5}
        connections={{ pin2: "net.HP_L", pin3: "net.HP_R", pin1: GND, pin4: GND }} />

      {mountingPoints.map(([x, y], i) => <Fragment key={`mount-${i}`}>
        <hole name={`H${i + 1}`} pcbX={x} pcbY={y} diameter={2.2} />
        <keepout shape="circle" pcbX={x} pcbY={y} radius={2.7} layers={["top", "bottom"]} />
      </Fragment>)}

      <copperpour layer="bottom" connectsTo={GND} clearance={0.25} cutoutMargin={0.3} boardEdgeMargin={0.3} />

      {referenceLabels.map(([name, x, y]) => (
        <Fragment key={name}><SilkLabel text={name} x={x} y={y} /></Fragment>
      ))}
      <SilkLabel text="SVARA USB B" x={3} y={-14} />
      <schematictext text="USB-C / ESD / full-speed interface" schX={-20} schY={12} fontSize={0.6} />
      <schematictext text="Filtered USB power / amplifier LDO" schX={-19} schY={-5} fontSize={0.6} />
      <schematictext text="PCM2704C / 16-bit stereo / 48 kHz max" schX={0} schY={17} fontSize={0.6} />
      <schematictext text="12 MHz crystal" schX={0} schY={-4} fontSize={0.6} />
      <schematictext text="TPA6132A2 / 0 dB / ground-referenced output" schX={21} schY={16} fontSize={0.6} />
      </schematicsheet>
    </board>
    <SnapFitEnclosure />
    </assembly.device>
  )
}