Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from "./lib/XiaoBoard/XiaoReceiver.circuit"
export * from "./lib/ProMicroBoard/ProMicroBoard.circuit"
// export * from "./Common Boards/RaspberryPiHatBoard/RaspberryPiHatBoard.circuit"
export * from "./lib/ViaGridBoard/ViaGridBoard.circuit"
export * from "./lib/Esp32C3SuperMini/Esp32C3SuperMini.circuit"
84 changes: 84 additions & 0 deletions lib/Esp32C3SuperMini/Esp32C3SuperMini.circuit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import type { BoardProps, ChipProps } from "@tscircuit/props"
import { outlineBuilder } from "../../util/outlineBuilder"
import { Esp32C3SuperMiniFootprint } from "./Esp32C3SuperMiniFootprint"
import {
BOARD_LENGTH_MM,
BOARD_WIDTH_MM,
LEFT_PINS,
PINS_IN_FOOTPRINT_ORDER,
RIGHT_PINS,
} from "./pinout"

export type Esp32C3SuperMiniProps = {
boardProps?: BoardProps
chipProps?: Partial<ChipProps>
children?: any
}

const CORNER_RADIUS_MM = 1.5
const halfWidth = BOARD_WIDTH_MM / 2
const halfLength = BOARD_LENGTH_MM / 2

const pinLabels = Object.fromEntries(
PINS_IN_FOOTPRINT_ORDER.map((label, index) => [`pin${index + 1}`, label]),
)

const schPinArrangement = {
leftSide: { direction: "top-to-bottom" as const, pins: [...LEFT_PINS] },
rightSide: { direction: "top-to-bottom" as const, pins: [...RIGHT_PINS] },
}

/**
* The corner arcs go through Math.cos/sin, which are not required to be
* correctly rounded and differ by ~1 ULP between libm implementations. Snapping
* to a 1nm grid keeps the outline, and therefore the rendered snapshot,
* identical on every platform.
*/
const snapToNanometerGrid = ({ x, y }: { x: number; y: number }) => ({
x: Math.round(x * 1e6) / 1e6,
y: Math.round(y * 1e6) / 1e6,
})

/** 18 x 22.5mm outline with rounded corners; USB-C sits on the bottom edge. */
const outline = outlineBuilder(0, halfLength)
.lineTo(halfWidth, halfLength)
.corner({ radius: CORNER_RADIUS_MM, turn: "ccw" })
.lineTo(halfWidth, -halfLength)
.corner({ radius: CORNER_RADIUS_MM, turn: "ccw" })
.lineTo(-halfWidth, -halfLength)
.corner({ radius: CORNER_RADIUS_MM, turn: "ccw" })
.lineTo(-halfWidth, halfLength)
.corner({ radius: CORNER_RADIUS_MM, turn: "ccw" })
.lineTo(0, halfLength)
.toArray()
.map(snapToNanometerGrid)

/**
* ESP32-C3 SuperMini development board (18 x 22.5mm) as a reusable common board.
* Two rows of eight 2.54mm-pitch header pins carrying 5V/GND/3V3 and
* GPIO0-GPIO10, GPIO20 and GPIO21.
*/
export const Esp32C3SuperMini = ({
boardProps = {},
chipProps = {},
children,
}: Esp32C3SuperMiniProps) => {
const { name: resolvedName = "Esp32C3SuperMini", ...chipRest } = chipProps

return (
<board {...boardProps} outline={outline}>
<chip
{...chipRest}
name={resolvedName}
footprint={<Esp32C3SuperMiniFootprint />}
doNotPlace
pcbX={0}
pcbY={0}
pinLabels={pinLabels}
schWidth={1.4}
schPinArrangement={schPinArrangement}
/>
{children}
</board>
)
}
40 changes: 40 additions & 0 deletions lib/Esp32C3SuperMini/Esp32C3SuperMiniFootprint.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react"
import type { PlatedHoleProps } from "@tscircuit/props"
import { PINS_PER_SIDE, PIN_PITCH_MM, ROW_SPACING_MM } from "./pinout"

export interface Esp32C3SuperMiniFootprintProps {
holeDiameter?: number
outerDiameter?: number
}

/**
* Through-hole footprint for the ESP32-C3 SuperMini: two columns of eight
* 2.54mm-pitch pins, 15.24mm apart, matching the module's header rows.
* pin1-pin8 are the left column (top to bottom) and pin9-pin16 the right.
*/
export const Esp32C3SuperMiniFootprint = ({
holeDiameter = 1,
outerDiameter = 1.8,
}: Esp32C3SuperMiniFootprintProps = {}) => {
const topPinY = ((PINS_PER_SIDE - 1) / 2) * PIN_PITCH_MM
const columnXs = [-ROW_SPACING_MM / 2, ROW_SPACING_MM / 2]

const holes = columnXs.flatMap((columnX, column) =>
Array.from({ length: PINS_PER_SIDE }, (_, row) => {
const pin = `pin${column * PINS_PER_SIDE + row + 1}`
const holeProps: PlatedHoleProps = {
portHints: [pin],
shape: "circle",
holeDiameter,
outerDiameter,
pcbX: columnX,
pcbY: topPinY - row * PIN_PITCH_MM,
}
// tscircuit's JSX types don't accept React's `key`, so build the element
// directly rather than widening the props to `any`.
return React.createElement("platedhole", { key: pin, ...holeProps })
}),
)

return <footprint>{holes}</footprint>
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions lib/Esp32C3SuperMini/pinout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* ESP32-C3 SuperMini header pinout and mechanical constants.
*
* Pins are listed top to bottom exactly as they sit on the board, with the PCB
* antenna at the top and USB-C at the bottom.
*/
export const LEFT_PINS = [
"V5",
"GND",
"V3_3",
"IO4",
"IO3",
"IO2",
"IO1",
"IO0",
] as const

export const RIGHT_PINS = [
"IO5",
"IO6",
"IO7",
"IO8",
"IO9",
"IO10",
"IO20",
"IO21",
] as const

/** Footprint pin order: pin1-pin8 are the left column, pin9-pin16 the right. */
export const PINS_IN_FOOTPRINT_ORDER = [...LEFT_PINS, ...RIGHT_PINS]

export const PINS_PER_SIDE = LEFT_PINS.length
export const PIN_PITCH_MM = 2.54
export const ROW_SPACING_MM = 15.24
export const BOARD_WIDTH_MM = 18
export const BOARD_LENGTH_MM = 22.5
Loading