muse/book-reading-clip-lamp

A Wi‑Fi/USB‑C ESP32‑S3 reading lamp with OV5640 camera, microphone, speaker amplifier, rechargeable Li‑Po power management, six-LED boost light, USB protection/charging detection, and a clip/gooseneck enclosure with external FlexPIFA antenna.

Version
0.4.3
License
unset
Stars
0

index.circuit.tsx

PCBPCB preview for index.circuit.tsx
SchematicSchematic preview for index.circuit.tsx
import { BQ24392RSER } from "./imports/BQ24392RSER"
import { TUSB320LAIRWBR } from "./imports/TUSB320LAIRWBR"
import { SN74LVC1G14DBVR } from "./imports/SN74LVC1G14DBVR"
import { SN74LVC1G332DBVR } from "./imports/SN74LVC1G332DBVR"
import { TLV75533PDBVR } from "./imports/TLV75533PDBVR"
import { pcbMounting } from "./pcb-mounting"
import { replaySavedRoutes } from "./saved-routing"
import type { AutorouterConfig } from "@tscircuit/props"
import { withFunctionalSchematicSheets } from "./schematic-layout"
import React from "react"
import { MBR0540T1G } from "./imports/MBR0540T1G"
import { ESP32S3 } from "./mcu-parts"
import { BQ24074, TPS63021, TPS61165, PowerInductor, LedInductor, VbusDetectorFet } from "./power-parts"
import { INMP441Microphone as INMP441, MAX98357Amplifier as MAX98357A } from "./camera-audio-parts"
import { CameraFpcConnector, Camera2V8, Camera1V8, CameraInputBuffer, CameraOutputBuffer, CameraControlTranslator } from "./camera-fpc-parts"
import { B8B_XH_A_LF__SN_ } from "./imports/B8B_XH_A_LF__SN_"
import { AskButton } from "./controls-parts"
import { usbConnectorProps } from "./usb-connector"
import { XL_1608SYGC_06 } from "./imports/XL_1608SYGC_06"
import { XL_1608UOC_06 } from "./imports/XL_1608UOC_06"
import { ReadingLED, UsbESD } from "./indicator-parts"
import { assembly } from "@tscircuit/core"
import { LampEnclosure } from "./lamp-enclosure"

// Rev B: 60 mm head controller. Top = rear/electronics; bottom = page/LEDs.
// Seeed 114993115 OV5640 autofocus camera on a 24-pin FPC; 1.8 V I/O.
// No Muse credentials or finished firmware are included in this hardware design.
const outline = Array.from({length: 96}, (_,i) => ({x:30*Math.cos(i*Math.PI/48),y:30*Math.sin(i*Math.PI/48)}))
const netLinks = (ref:string, pins:Record<string,string>) => Object.entries(pins).map(([pin,net]) =>
  <trace key={`${ref}-${pin}`} from={`${ref}.${pin}`} to={`net.${net}`} schDisplayLabel={net} />)

type Passive = [string,string,string,string,number,number,string,number,number,number?]
// reference, value, net1, net2, PCB x/y, schematic section, schematic x/y, rotation
const resistors:Passive[] = [
 ["R3","22","USB_DP_DETECTED","USB_DP",-15.3,2,"USB",-30,4],
 ["R4","22","USB_DM_DETECTED","USB_DM",-16,4,"USB",-25,4],
 ["R5","1.78k","ISET","GND",-21.3,-12.2,"Charger",-31,-13],
 ["R6","1.62k","ILIM","GND",-16.5,-13,"Charger",-26,-13],
 ["R7","46.4k","TMR","GND",-13,-13,"Charger",-21,-13],
 ["R8","100k","USB_500MA","GND",-26,-7.5,"Charger",-16,-13,90],
 ["R9","10k","EN","V3V3",-12,10,"MCU",-6,13,90],
 ["R10","10k","BOOT","V3V3",12,10,"MCU",0,13,90],
 ["R11","10k","STRAP45","GND",10,0,"MCU",6,13],
 ["R12","10k","STRAP46","GND",7,0,"MCU",12,13],
 ["R13","10k","USB_SUSPEND","GND",4,0,"MCU",18,13],
 ["R14","100k","AMP_SD","GND",13,-11.5,"Audio",25,-11],
 ["R15","100k","MIC_DATA","GND",20.5,-4.2,"Audio",30,-11,90],
 ["R16","100k","LED_PWM","GND",12,7,"Light",25,14],
 ["R17","13.3","LED_SENSE","GND",19,3,"Light",30,14],
 ["R18","10k","ASK","V3V3",-16.3,-18.3,"Controls",-6,-26],
 ["R19","10k","LIGHT_KEY","V3V3",16,-19,"Controls",0,-26],
 ["R20","470k","VBAT","BAT_ADC",15,1,"Controls",6,-26],
 ["R21","470k","BAT_ADC","GND",15,-1,"Controls",12,-26],
 ["R22","1k","STATUS_A","GND",13,16,"Controls",18,-26,180],
 ["R24","2k","AMP_EN","AMP_SD",10,-9,"Audio",35,-11],
 ["R23","1k","SYS","CHG_LED_A",-25,-13.5,"Charger",-11,-13,90],
]
resistors.push(
 ["R25","100k","SYS","SYS_EN",0,-10,"Regulator",-26,-25],
 ["R26","10k","VBUS","VBUS_GATE",-18,5.5,"USB",-30,-1],
 ["R27","100k","VBUS_GATE","GND",-18,12,"USB",-25,-1],
 ["R28","47k","V3V3","VBUS_DRAIN",-16,15,"USB",-20,-1,180],
 ["R29","2k","VBUS_DRAIN","VBUS_N",-14,5.5,"USB",-15,-1],
 ["R35","1k","ASK_REMOTE","ASK",-17,-21.5,"Controls",-6,-21,180],
 ["R36","1k","PWR_REMOTE","SYS_EN",-19,-20,"Regulator",-26,-29],
)
const capacitors:Passive[] = [
 ["C1","4.7uF","VBUS","GND",-17,-5.5,"Charger",-31,-17],
 ["C2","10uF","VBAT","GND",-21.3,-8,"Charger",-26,-17],
 ["C3","22uF","SYS","GND",-13,-8,"Charger",-21,-17],
 ["C4","10uF","SYS","GND",-4,-4,"Regulator",-31,-34],
 ["C5","10uF","SYS","GND",-4.8,-7,"Regulator",-26,-34],
 ["C6","100nF","SYS","GND",-8,-0.5,"Regulator",-21,-34],
 ["C7","22uF","V3V3","GND",-12.3,-3.5,"Regulator",-16,-34],
 ["C8","22uF","V3V3","GND",-15.85,-3.5,"Regulator",-11,-34],
 ["C9","22uF","V3V3","GND",-12,-0.5,"Regulator",-6,-34],
 ["C10","10uF","V3V3","GND",-12,18,"MCU",-6,17],
 ["C11","100nF","V3V3","GND",-12,16,"MCU",0,17],
 ["C12","1uF","EN","GND",-12,13,"MCU",6,17],
 ["C36","10nF","ASK","GND",-9.5,-25.5,"Controls",-6,-30],
 ["C37","100nF","SYS_EN","GND",-16.2,-16,"Regulator",-22,-29],
 ["C15","10uF","SYS","GND",18,-8,"Audio",25,-15],
 ["C16","100nF","SYS","GND",18,-6,"Audio",30,-15],
 ["C17","100nF","V3V3","GND",23,4.9,"Audio",35,-15],
 ["C18","4.7uF","SYS","GND",12,4,"Light",25,18],
 ["C19","220nF","LED_COMP","GND",20,5.5,"Light",30,18],
 ["C20","1uF","LED_ANODE","GND",24,12.5,"Light",35,18],
 ["C21","100nF","BAT_ADC","GND",17.5,-3,"Controls",12,-30],
]

const cameraResistors:Passive[] = [
 ["R30","100k","CAM_XCLK","GND",11,-15,"Camera",-13,-10],
 ["R31","100k","CAM_RESET","GND",13,-16.5,"Camera",-8,-10],
 ["R32","10k","CAM_PWDN","V3V3",14,-18,"Camera",-3,-10],
 ["R33","33","FPC_XCLK_DRV","FPC_XCLK",11,-7,"Camera",-10,-5],
 ["R34","10k","CAM1V8","CAM_AVDD_EN",-10,9,"CameraPower",-3,4],
]
const cameraCapacitors:Passive[] = [
 ["C13","10uF","V3V3","GND",-17.5,12,"CameraPower",-12,-3],
 ["C14","100nF","CAM2V8","GND",0,-17,"CameraPower",-5.4,-7],
 ["C22","4.7uF","CAM2V8","GND",-10.5,12,"CameraPower",-7.8,-7],
 ["C23","1uF","V3V3","GND",-10.5,16,"CameraPower",-9,-3],
 ["C24","2.2uF","CAM_CORE_INTERNAL","GND",-6,-17,"CameraPower",8,-3],
 ["C25","100nF","CAM_CORE_INTERNAL","GND",-3.3,-17,"CameraPower",11,-3],
 ["C26","4.7uF","CAM2V8","GND",8,-16.5,"CameraPower",-3,-7],
 ["C27","100nF","V3V3","GND",-18.3,4,"Camera",-4.8,-13],
 ["C28","100nF","V3V3","GND",18.3,4,"Camera",-2.4,-13],
 ["C29","100nF","CAM1V8","GND",21,-10,"Camera",0,-16],
 ["C30","100nF","CAM1V8","GND",-18.5,-10,"Camera",1.5,-16],
 ["C31","100nF","V3V3","GND",-17,-13,"Camera",0,-13],
 ["C32","1uF","CAM_AVDD_EN","GND",-10,7,"CameraPower",-3,-3],
 ["C33","100nF","CAM1V8","GND",-10,5,"Camera",3,-16],
 ["C34","100nF","CAM1V8","GND",17.5,6.5,"Camera",4.5,-16],
 ["C35","4.7uF","CAM1V8","GND",-3.5,16,"CameraPower",5,-7],
]

// Only detector current flows through R39; the charger retains its direct VBUS feed.
// R1/R2 are intentionally removed: TUSB320LAI provides both CC sink terminations.
const usbDetectionResistors:Passive[] = [
 ["R37","2.2","USB_DP_CONN","BC_DP",.5,0,"USBPower",-7,3.5],
 ["R38","2.2","USB_DM_CONN","BC_DM",-1.5,0,"USBPower",-7,1],
 ["R39","2.2","VBUS","VBUS_BC",-1.8,-4.2,"USBPower",-7,7],
 ["R40","887k","VBUS","CC_VBUS_DET",0,-8,"USBPower",-7,-7],
 ["R41","10k","USB_LOGIC_3V3","CC_HIGH_N",3,-7.5,"USBPower",6,-1.5],
 ["R42","10k","CHG_EN1","GND",7,-13.6,"USBPower",21,1],
]
const usbDetectionCapacitors:Passive[] = [
 ["C38","100nF","VBUS_BC","GND",-2.8,-1.5,"USBPower",-11,7],
 ["C39","1uF","VBUS_BC","GND",-5,1,"USBPower",-13,7,0],
 ["C40","100nF","USB_LOGIC_3V3","GND",-2.7,-6,"USBPower",6,-10],
 ["C41","100nF","USB_LOGIC_3V3","GND",6,-2.5,"USBPower",8,-10],
 ["C42","100nF","USB_LOGIC_3V3","GND",9.3,-11,"USBPower",10,-10],
 ["C43","1uF","VBUS","GND",-3.9,-14,"USBPower",-5,11],
 ["C44","1uF","USB_LOGIC_3V3","GND",3.9,-14,"USBPower",5,11],
]

export default function LampHead({ routeAlgorithm = replaySavedRoutes }: { routeAlgorithm?: AutorouterConfig["algorithmFn"] } = {}) {
 return <assembly.device name="BookReadingClipLamp">
 {withFunctionalSchematicSheets(<board title="Lamp Clip - Seeed OV5640 Head PCB" width={60} height={60} outline={outline}
   layers={4} thickness={1.6} allowBlindAndBuriedVias={false} isViaInPadAllowed doubleSidedAssembly solderMaskColor="black" silkscreenColor="white"
   minTraceWidth={0.15} minBoardEdgeClearance={0.3} minViaEdgeToPadEdgeClearance={0.15} minViaHoleDiameter={0.3} minViaPadDiameter={0.45}
   autorouter={{local:true,traceClearance:0.15,algorithmFn:routeAlgorithm}} pcbStyle={{silkscreenFontSize:0.7}}>
  <net name="GND" isGroundNet nominalTraceWidth={0.3}/>
  {["VBUS","VBAT","SYS","V3V3","CAM2V8","CAM1V8","USB_LOGIC_3V3","VBUS_BC"].map(n=><net name={n} isPowerNet nominalTraceWidth={0.4}/>)}

  {["BUCK_L1","BUCK_L2"].map(n=><net name={n} isPowerNet nominalTraceWidth={0.8}/>)}
  {["SPK_P","SPK_N","LED_SW"].map(n=><net name={n} isPowerNet nominalTraceWidth={0.4}/>)}
  <connector standard="usb_c" {...usbConnectorProps} name="J1" pcbX={-25.1} pcbY={0} pcbRotation={270} allowOffBoard
   schSectionName="USB" schX={-31} schY={15} />
  {netLinks("J1",{VBUS1:"VBUS",VBUS2:"VBUS",GND1:"GND",GND2:"GND",SHELL1:"GND",SHELL2:"GND",SHELL3:"GND",SHELL4:"GND",CC1:"CC1",CC2:"CC2",DP1:"USB_DP_CONN",DP2:"USB_DP_CONN",DM1:"USB_DM_CONN",DM2:"USB_DM_CONN"})}
  <UsbESD name="U7" pcbX={-19} pcbY={0} schSectionName="USB" schX={-20} schY={15}/>
  {netLinks("U7",{pin1:"USB_DP_CONN",pin2:"GND",pin3:"USB_DM_CONN",pin4:"USB_DM_CONN",pin5:"VBUS",pin6:"USB_DP_CONN"})}

  {/* BC1.2 detection precedes the MCU's USB termination; CC uses U15's internal Rd. */}
  <BQ24392RSER name="U14" pcbX={0} pcbY={-2} schSectionName="USBPower" schX={0} schY={3}
    schWidth={2.6} schHeight={1.3} noConnect={["pin1","pin4"]}
    schPinArrangement={{leftSide:[9,5,7,8],rightSide:[3,2,10,4,1],bottomSide:[6]}}/>
  {netLinks("U14",{pin2:"USB_DM_DETECTED",pin3:"USB_DP_DETECTED",pin5:"VBUS_BC",pin6:"GND",pin7:"BC_DP",pin8:"BC_DM",pin9:"VBUS_BC",pin10:"BC_FAST"})}
  <TUSB320LAIRWBR name="U15" pcbX={0} pcbY={-6} schSectionName="USBPower" schX={0} schY={-5}
    schWidth={2.4} schHeight={1.4} noConnect={["pin5","pin6","pin8","pin9"]}
    schPinArrangement={{leftSide:[12,1,2,4],rightSide:[7,8,6,9,5],bottomSide:[3,10,11]}}/>
  {netLinks("U15",{pin1:"CC1",pin2:"CC2",pin3:"GND",pin4:"CC_VBUS_DET",pin7:"CC_HIGH_N",pin10:"GND",pin11:"GND",pin12:"USB_LOGIC_3V3"})}
  <SN74LVC1G14DBVR name="U16" pcbX={6} pcbY={-5} schSectionName="USBPower" schX={6} schY={-5}
    schWidth={1.5} schHeight={1} noConnect={["pin1"]}
    schPinArrangement={{leftSide:[2],rightSide:[4,1],topSide:[5],bottomSide:[3]}}/>
  {netLinks("U16",{pin2:"CC_HIGH_N",pin3:"GND",pin4:"CC_FAST",pin5:"USB_LOGIC_3V3"})}
  <SN74LVC1G332DBVR name="U17" pcbX={6} pcbY={-11} schSectionName="USBPower" schX={10} schY={-1}
    schWidth={1.3} schHeight={1.2} schPinArrangement={{leftSide:[1,3,6],rightSide:[4],topSide:[5],bottomSide:[2]}}/>
  {netLinks("U17",{pin1:"BC_FAST",pin2:"GND",pin3:"CC_FAST",pin4:"CHG_EN1",pin5:"USB_LOGIC_3V3",pin6:"USB_500MA"})}
  <TLV75533PDBVR name="U18" pcbX={0} pcbY={-14} schSectionName="USBPower" schX={0} schY={11}
    schWidth={1.6} schHeight={0.7} noConnect={["pin4"]}
    schPinArrangement={{leftSide:[1,3],rightSide:[5,4],bottomSide:[2]}}/>
  {netLinks("U18",{pin1:"VBUS",pin2:"GND",pin3:"VBUS",pin5:"USB_LOGIC_3V3"})}
  {usbDetectionResistors.map(([ref,value,a,b,x,y,section,sx,sy,rot])=><React.Fragment key={ref}>
    <resistor name={ref} resistance={value} footprint="0402" pcbX={x} pcbY={y} pcbRotation={rot??0}
      schSectionName={section} schX={sx} schY={sy} schRotation={ref==="R37"||ref==="R38"?0:-90}/>
    {netLinks(ref,{pin1:a,pin2:b})}
  </React.Fragment>)}
  {usbDetectionCapacitors.map(([ref,value,a,b,x,y,section,sx,sy,rot])=><React.Fragment key={ref}>
    <capacitor name={ref} capacitance={value} maxVoltageRating="10V" footprint={value==="100nF"?"0402":"0603"}
      pcbX={x} pcbY={y} pcbRotation={rot??0} schSectionName={section} schX={sx} schY={sy} schRotation={-90}/>
    {netLinks(ref,{pin1:a,pin2:b})}
  </React.Fragment>)}

  <VbusDetectorFet name="Q1" pcbX={-18} pcbY={8.5} pcbRotation={180} schSectionName="USB" schX={-16} schY={8}/>
  {netLinks("Q1",{pin1:"VBUS_GATE",pin2:"GND",pin3:"VBUS_DRAIN"})}
  <ESP32S3 name="U1" pcbX={0} pcbY={12} schSectionName="MCU" schX={5} schY={4} schWidth={2.8} schHeight={4.2}/>
  {netLinks("U1",{pin1:"GND",pin2:"V3V3",pin3:"EN",pin4:"I2S_BCLK",pin5:"I2S_WS",pin6:"SPK_DATA",pin7:"MIC_DATA",pin8:"CAM_D0",pin9:"CAM_D3",pin10:"CAM_D1",pin11:"CAM_D2",pin12:"AMP_EN",pin13:"USB_DM",pin14:"USB_DP",pin15:"USB_SUSPEND",pin16:"STRAP46",pin17:"LED_PWM",pin18:"CAM_XCLK",pin19:"CAM_D6",pin20:"CAM_D5",pin21:"CAM_PCLK",pin22:"CAM_D4",pin23:"USB_500MA",pin24:"CAM_HREF",pin25:"CAM_D7",pin26:"STRAP45",pin27:"BOOT",pin31:"CAM_VSYNC",pin32:"CAM_SCL",pin33:"CAM_SDA",pin34:"CAM_RESET",pin35:"CAM_PWDN",pin36:"ASK",pin37:"VBUS_N",pin38:"LIGHT_KEY",pin39:"BAT_ADC",pin40:"GND",pin41:"GND"})}

  <BQ24074 name="U2" pcbX={-17} pcbY={-9.5} schSectionName="Charger" schX={-22} schY={-6} schHeight={1.8}/>
  {netLinks("U2",{pin1:"NTC",pin2:"VBAT",pin3:"VBAT",pin4:"GND",pin5:"USB_SUSPEND",pin6:"CHG_EN1",pin8:"GND",pin9:"CHG_N",pin10:"SYS",pin11:"SYS",pin12:"ILIM",pin13:"VBUS",pin14:"TMR",pin16:"ISET",pin17:"GND"})}
  <TPS63021 name="U3" pcbX={-8} pcbY={-4} pcbRotation={270} schSectionName="Regulator" schX={-21} schY={-26} schHeight={1.6}/>
  {netLinks("U3",{pin1:"SYS",pin2:"GND",pin3:"V3V3",pin4:"V3V3",pin5:"V3V3",pin6:"BUCK_L2",pin7:"BUCK_L2",pin8:"BUCK_L1",pin9:"BUCK_L1",pin10:"SYS",pin11:"SYS",pin12:"SYS_EN",pin13:"GND",pin15:"GND"})}
  <PowerInductor name="L1" pcbX={-8} pcbY={-9} pcbRotation={180} schSectionName="Regulator" schX={-12} schY={-25}/>
  {netLinks("L1",{pin1:"BUCK_L1",pin2:"BUCK_L2"})}

  <CameraFpcConnector name="J2" pcbX={0} pcbY={-12} layer="bottom" schSectionName="Camera" schX={-12} schY={3} schWidth={2.6} schHeight={3}/>
  {netLinks("J2",{pin2:"GND",pin3:"FPC_SDA",pin4:"CAM2V8",pin5:"FPC_SCL",pin6:"FPC_RESET",pin7:"FPC_VSYNC",pin8:"FPC_PWDN",pin9:"FPC_HREF",pin10:"CAM_CORE_INTERNAL",pin11:"CAM1V8",pin12:"FPC_D7",pin13:"FPC_XCLK",pin14:"FPC_D6",pin15:"GND",pin16:"FPC_D5",pin17:"FPC_PCLK",pin18:"FPC_D4",pin19:"FPC_D0",pin20:"FPC_D3",pin21:"FPC_D1",pin22:"FPC_D2",pin23:"GND",pin24:"CAM2V8",pin25:"GND",pin26:"GND"})}
  <Camera2V8 name="U8" pcbX={-14} pcbY={12} layer="bottom" schSectionName="CameraPower" schX={-8} schY={4}/>
  {netLinks("U8",{pin1:"V3V3",pin2:"GND",pin3:"CAM_AVDD_EN",pin5:"CAM2V8"})}
  <Camera1V8 name="U9" pcbX={-7} pcbY={16} layer="bottom" schSectionName="CameraPower" schX={8} schY={4}/>
  {netLinks("U9",{pin1:"V3V3",pin2:"GND",pin3:"V3V3",pin5:"CAM1V8"})}
  <CameraInputBuffer name="U10" pcbX={-13} pcbY={0} layer="bottom" schSectionName="Camera" schX={0} schY={3} schWidth={2} schHeight={2.55}/>
  {netLinks("U10",{pin1:"V3V3",pin2:"GND",pin3:"CAM_D0",pin4:"CAM_D1",pin5:"CAM_D2",pin6:"CAM_D3",pin7:"CAM_D4",pin8:"CAM_D5",pin9:"CAM_D6",pin10:"CAM_D7",pin11:"GND",pin12:"GND",pin13:"GND",pin14:"FPC_D7",pin15:"FPC_D6",pin16:"FPC_D5",pin17:"FPC_D4",pin18:"FPC_D3",pin19:"FPC_D2",pin20:"FPC_D1",pin21:"FPC_D0",pin22:"CAM_PWDN",pin23:"CAM1V8",pin24:"CAM1V8"})}
  <CameraInputBuffer name="U11" pcbX={13} pcbY={0} layer="bottom" schSectionName="Camera" schX={10} schY={3} schWidth={2} schHeight={2.55} noConnect={["pin6","pin7","pin8","pin9","pin10"]}/>
  {netLinks("U11",{pin1:"V3V3",pin2:"GND",pin3:"CAM_PCLK",pin4:"CAM_VSYNC",pin5:"CAM_HREF",pin11:"GND",pin12:"GND",pin13:"GND",pin14:"GND",pin15:"GND",pin16:"GND",pin17:"GND",pin18:"GND",pin19:"FPC_HREF",pin20:"FPC_VSYNC",pin21:"FPC_PCLK",pin22:"CAM_PWDN",pin23:"CAM1V8",pin24:"CAM1V8"})}
  <CameraOutputBuffer name="U12" pcbX={17} pcbY={-8.8} layer="bottom" schSectionName="Camera" schX={-2} schY={-5} schWidth={1.7} schHeight={1.6} noConnect={["pin11"]}/>
  {netLinks("U12",{pin1:"GND",pin2:"CAM_XCLK",pin3:"FPC_XCLK_DRV",pin4:"GND",pin5:"CAM_RESET",pin6:"FPC_RESET",pin7:"GND",pin8:"FPC_PWDN",pin9:"CAM_PWDN",pin10:"GND",pin12:"GND",pin13:"CAM1V8",pin14:"CAM1V8"})}
  <CameraControlTranslator name="U13" pcbX={-14} pcbY={-10} layer="bottom" schSectionName="Camera" schX={10} schY={-5} schWidth={1.5} schHeight={1.2}/>
  {netLinks("U13",{pin1:"CAM_SCL",pin2:"GND",pin3:"CAM1V8",pin4:"FPC_SCL",pin5:"FPC_SDA",pin6:"FPC_RESET",pin7:"V3V3",pin8:"CAM_SDA"})}
  {/* Camera-side rails and signal conditioning stay on the page-facing side. */}
  {cameraResistors.map(([ref,value,a,b,x,y,section,sx,sy,rot])=><React.Fragment key={ref}>
   <resistor name={ref} resistance={value} footprint="0402" pcbX={x} pcbY={y} pcbRotation={rot??0} layer="bottom" schSectionName={section} schX={sx} schY={sy} schRotation={ref==="R32"?90:ref==="R33"?0:-90}/>
   {netLinks(ref,{pin1:a,pin2:b})}
  </React.Fragment>)}
  {cameraCapacitors.map(([ref,value,a,b,x,y,section,sx,sy])=><React.Fragment key={ref}>
   <capacitor name={ref} capacitance={value} maxVoltageRating="10V" footprint={value==="100nF"?"0402":"0603"} pcbX={x} pcbY={y} pcbRotation={["C26","C34"].includes(ref)?180:0} layer="bottom" schSectionName={section} schX={sx} schY={sy} schRotation={-90}/>
   {netLinks(ref,{pin1:a,pin2:b})}
  </React.Fragment>)}

  <INMP441 name="U4" pcbX={22} pcbY={0} pcbRotation={180} schSectionName="Audio" schX={32} schY={-4} schHeight={1}/>
  {netLinks("U4",{pin1:"I2S_BCLK",pin2:"MIC_DATA",pin3:"I2S_WS",pin4:"GND",pin5:"GND",pin6:"GND",pin7:"V3V3",pin8:"V3V3",pin9:"GND"})}
  <MAX98357A name="U5" pcbX={14} pcbY={-8} schSectionName="Audio" schX={24} schY={-4} schHeight={1.8}/>
  {netLinks("U5",{pin1:"SPK_DATA",pin3:"GND",pin4:"AMP_SD",pin7:"SYS",pin8:"SYS",pin9:"SPK_P",pin10:"SPK_N",pin11:"GND",pin14:"I2S_WS",pin15:"GND",pin16:"I2S_BCLK",pin17:"GND"})}

  <TPS61165 name="U6" pcbX={16} pcbY={7} pcbRotation={0} schSectionName="Light" schX={27} schY={7}/>
  {netLinks("U6",{pin1:"SYS",pin2:"LED_PWM",pin3:"LED_SW",pin4:"GND",pin5:"LED_COMP",pin6:"LED_SENSE"})}
  <LedInductor name="L2" pcbX={18} pcbY={12} schSectionName="Light" schX={34} schY={8}/>
  {netLinks("L2",{pin1:"SYS",pin2:"LED_SW"})}
  <MBR0540T1G name="D1" pcbX={21.7} pcbY={7.7} pcbRotation={180}
   schSectionName="Light" schX={34} schY={4}/>
  {netLinks("D1",{anode:"LED_SW",cathode:"LED_ANODE"})}
  {Array.from({length:6},(_,i)=>{
   const a=i*Math.PI/3; const ref=`LED${i+1}`
   return <React.Fragment key={ref}>
    <ReadingLED name={ref} pcbX={25*Math.cos(a)} pcbY={25*Math.sin(a)} pcbRotation={i*60} layer="bottom"
      schSectionName="Light" schX={24+(i%3)*5} schY={25+Math.floor(i/3)*3}/>
    {netLinks(ref,{pin1:i===5?"LED_SENSE":`LED_LINK_${i+1}`,pin2:i===0?"LED_ANODE":`LED_LINK_${i}`})}
   </React.Fragment>
  })}

  {/* Keyed removable gooseneck harness: exact JLCSearch C157972 footprint/CAD. */}
  <B8B_XH_A_LF__SN_ name="J3" pcbX={0} pcbY={-20.3} pcbRotation={180}
   schSectionName="Charger" schX={-11} schY={-6} schWidth={1.8} schHeight={1}/>
  {netLinks("J3",{pin1:"VBAT",pin2:"GND",pin3:"NTC",pin4:"GND",pin5:"SPK_P",pin6:"SPK_N",pin7:"ASK_REMOTE",pin8:"PWR_REMOTE"})}

  {[{name:"SW2",net:"LIGHT_KEY",x:24,sx:0}].map(b=><React.Fragment key={b.name}>
   <AskButton name={b.name} pcbX={b.x} pcbY={-8} pcbRotation={90} schSectionName="Controls" schX={b.sx} schY={-21}/>
   {netLinks(b.name,{pin1:b.net,pin2:"GND"})}
  </React.Fragment>)}
  <XL_1608SYGC_06 name="LED7" color="green" pcbRotation={180} pcbX={13} pcbY={19} schSectionName="Controls" schX={18} schY={-21} schRotation={-90}/>
  {netLinks("LED7",{anode:"V3V3",cathode:"STATUS_A"})}
  <XL_1608UOC_06 name="LED8" color="orange" pcbRotation={180} pcbX={-24} pcbY={-10} schSectionName="Charger" schX={-11} schY={-17}/>
  {netLinks("LED8",{anode:"CHG_LED_A",cathode:"CHG_N"})}

  {resistors.map(([name,value,a,b,x,y,section,sx,sy,rotation])=><React.Fragment key={name}>
   <resistor name={name} resistance={value} footprint="0603" pcbX={x} pcbY={y} pcbRotation={rotation??0}
    schSectionName={section} schX={sx} schY={sy} schRotation={b==="V3V3"?90:(a==="USB_DP_DETECTED"||a==="USB_DM_DETECTED"||a==="AMP_EN")?0:-90}/> 
   {netLinks(name,{pin1:a,pin2:b})}
  </React.Fragment>)}
  {capacitors.map(([name,value,a,b,x,y,section,sx,sy])=><React.Fragment key={name}>
   <capacitor name={name} capacitance={value} footprint={value==="22uF"||name==="C20"?"0805":"0603"}
    maxVoltageRating={name==="C20"?"50V":"10V"} pcbX={x} pcbY={y} pcbRotation={["C8"].includes(name)?180:["C3","C4","C5","C20"].includes(name)?90:0} schSectionName={section} schX={sx} schY={sy} schRotation={-90}/>
   {netLinks(name,{pin1:a,pin2:b})}
  </React.Fragment>)}
  {["GND","V3V3","SYS","BOOT","EN","VBUS_N"].map((net,i)=><React.Fragment key={`TP${i+1}`}>
   <testpoint name={`TP${i+1}`} footprintVariant="pad" padDiameter={1.2} pcbX={-15+i*2.5} pcbY={24-(i<2?2:0)}
    schSectionName="Controls" schX={-6+i*4.8} schY={-35}/>
   {netLinks(`TP${i+1}`,{pin1:net})}
  </React.Fragment>)}
  {pcbMounting.centers.map(([x,y],i)=><React.Fragment key={`mount-${i}`}>
   <hole name={`H${i+1}`} pcbX={x} pcbY={y} diameter={pcbMounting.clearanceDiameter}/>
   {/* Both exposed surfaces stay clear of the support post and M3 screw head. */}
   {(["top","bottom"] as const).map(layer=><keepout shape="circle" pcbX={x} pcbY={y} radius={pcbMounting.surfaceKeepoutRadius} layer={layer}/>)}
  </React.Fragment>)}
  {/* Interior ground pours provide short returns; final stackup/USB impedance must be agreed with the fabricator. */}
  <copperpour connectsTo="net.GND" layer="inner1" clearance={0.2} boardEdgeMargin={0.4}/>
  <copperpour connectsTo="net.GND" layer="inner2" clearance={0.2} boardEdgeMargin={0.4}/>
  {/* Grounded exposed-pad vias. Filled/capped processing or stencil review required. */}
  {[[-16.8,-9.5],[-7.8,-4],[14.2,-8],[-4.5,13.325]].map(([x,y],i)=><via name={`VG${i+1}`} connectsTo="net.GND" pcbX={x} pcbY={y} fromLayer="top" toLayer="bottom" holeDiameter={0.3} outerDiameter={0.45}/>)}
  {/* Explicit short links associate each thermal pad with its plane via. pcbPath points are relative to the source component. */}
  <trace name="EP_GND_1" from="U2.pin17" to="VG1.top" thickness={0.3} pcbPath={[{x:0,y:0},{x:0.2,y:0}]}/>
  <trace name="EP_GND_2" from="U3.pin15" to="VG2.top" thickness={0.3} pcbPath={[{x:0,y:0},{x:0.2,y:0}]}/>
  <trace name="EP_GND_3" from="U5.pin17" to="VG3.top" thickness={0.3} pcbPath={[{x:0.000127,y:-0.000127},{x:0.2,y:0}]}/>
  <silkscreentext text="LAMP CLIP / SEEED" pcbX={0} pcbY={26} fontSize={1}/>
  <silkscreentext text="J3: 1 BAT+ / 8 PWR" pcbX={0} pcbY={-15.2} fontSize={0.65}/>
  <silkscreentext text="XHP-8 CABLE" pcbX={-5} pcbY={-25.2} fontSize={0.6}/>
  <silkscreentext text="LIGHT" pcbX={24} pcbY={-13.5} fontSize={0.75}/>
  <silkscreenrect pcbX={0} pcbY={3.5} width={9} height={9} layer="bottom" strokeWidth={0.15}/>
  <silkscreentext text="OV5640 AF / ALIGN LENS" pcbX={0} pcbY={10} layer="bottom" fontSize={0.8}/>
 </board>)}
 <LampEnclosure />
 </assembly.device>
}