MustafaMulla29/rp2040-bldc-motor-controller-new

A USB‑C PD–powered RP2040 BLDC motor controller PCB with 3.3 V logic, MCT8329A sensorless commutation, three MOSFET half-bridges, protected power switching, USB data, controls, and motor connectors.

Version
0.3.82
License
unset
Stars
0

circuit/helpers.tsx

import { type ReactNode } from "react"
import type { ChipProps } from "@tscircuit/props"
import { assemblyProps } from "./assembly-parts"
import placement from "./placement.json"
import schematicLayout from "./schematic-layout.json"
import { MMBT3904_7_F } from "../imports/MMBT3904_7_F"

export const net = (name: string) => `net.${name}`
// Component origins are ordinary native pcbX/pcbY props, centralized for layout review.
const locations = Object.fromEntries(placement.pcb_placements.map(p => [p.selector, p.center]))
const pcbOverrides: Record<string, {rotation?: number; layer?: "top" | "bottom"}> = Object.fromEntries(placement.pcb_placements.map(p => {
  const { rotation, layer } = p
  if (layer !== undefined && layer !== "top" && layer !== "bottom") throw new Error(`Invalid placement layer for ${p.selector}: ${layer}`)
  return [p.selector, { rotation, layer }]
}))
const schematicLocations: Record<string, { x: number; y: number; sheet: string; section: string; rotation?: number; width?: number; height?: number; showRatings?: boolean; pinArrangement?: unknown; pinStyle?: ChipProps["schPinStyle"] }> = schematicLayout.components
export const schAt = (name: string, schX: number, schY: number) => {
  const p = locations[name]
  if (!p) throw new Error(`No PCB placement for ${name}`)
  const s = schematicLocations[name]
  if (!s) throw new Error(`No schematic placement for ${name}`)
  return { ...assemblyProps(name), pcbX: p.x, pcbY: p.y, ...(pcbOverrides[name]?.rotation === undefined ? {} : { pcbRotation: pcbOverrides[name].rotation }), ...(pcbOverrides[name]?.layer === undefined ? {} : { layer: pcbOverrides[name].layer }), schX: s.x, schY: s.y,
    schSheetName: s.sheet,
    // Native sections keep local circuits wired and use named nets between functions.
    // This only controls the schematic representation; PCB props come from placement.json.
    schSectionName: s.section,
    ...(s.rotation === undefined ? {} : { schRotation: s.rotation }),
    ...(s.width === undefined ? {} : { schWidth: s.width }),
    ...(s.height === undefined ? {} : { schHeight: s.height }),
    ...(s.pinArrangement === undefined ? {} : { schPinArrangement: s.pinArrangement as ChipProps["schPinArrangement"] }),
    ...(s.pinStyle === undefined ? {} : { schPinStyle: s.pinStyle }),
  }
}
export const pcbRotations: Record<string, number> = Object.fromEntries(
  Object.entries(pcbOverrides).filter(([,p]) => p.rotation !== undefined).map(([name,p]) => [name,p.rotation!])
)
export type Passive = {
  name: string
  kind: "R" | "C"
  value: string
  a: string
  b: string
  x: number
  y: number
  layer?: "top" | "bottom"
  footprint?: string
  volts?: number
  note?: string
  maxDecouplingTraceLength?: number
  connections?: { pin1?: string; pin2?: string }
}

// Schematic placement is independent of the retained PCB placement and copper.
export function Passives({ parts, sx, sy }: { parts: Passive[]; sx: number; sy: number }) {
  return <>{parts.map(p => {
    const pos = { ...schAt(p.name, sx, sy), layer: pcbOverrides[p.name]?.layer ?? p.layer,
      pcbRotation: pcbRotations[p.name] ?? 0,
      schRotation: schematicLocations[p.name].rotation ?? -90 }
    return p.kind === "R"
      ? <resistor key={p.name} name={p.name} resistance={p.value} tolerance="1%"
          footprint={p.footprint ?? "0603"} {...pos}
          connections={{ pin1: net(p.a), pin2: net(p.b) }} />
      : <capacitor key={p.name} name={p.name} capacitance={p.value}
          maxVoltageRating={p.volts ?? 25} schShowRatings={schematicLocations[p.name].showRatings ?? true}
          maxDecouplingTraceLength={p.maxDecouplingTraceLength}
          footprint={p.footprint ?? "0603"} {...pos}
          connections={p.connections ?? { pin1: net(p.a), pin2: net(p.b) }} />
  })}</>
}

export function Npn({ name, base, collector, emitter = "GND", x, y, sx, sy }: {
  name: string; base: string; collector: string; emitter?: string; x: number; y: number; sx: number; sy: number
}) {
  return <MMBT3904_7_F name={name} pcbRotation={pcbRotations[name] ?? 0} {...schAt(name, sx, sy)}
    connections={{ pin1: net(base), pin2: net(emitter), pin3: net(collector) }} />
}

export function BlockTitle({ x, y, children }: { x: number; y: number; children: ReactNode }) {
  // Titles now come from the native schematic sheets and sections.
  return null
}