app
Adom Chipsmith
Public Made by Adomby adom
STEP-native chip validator — 5-source cross-validation, OCCT-generated copyright-free 3D models with embedded signal annotations, datasheet-to-STEP pipeline.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
use crate::cli::{err, hint, ok, DEFAULT_PORT};
use crate::cli::eval::eval_snippet;
use anyhow::Result;
use clap::Parser;
/// Place a synthetic pin-1 indicator on the chip's top face — the CLI
/// counterpart to the Pin-1 tab's mode + shape pickers. Three placement
/// modes (one is required):
///
/// --corner NW|NE|SW|SE pick a corner manually
/// --from-fp-marker project the silkscreen pin-1 marker from
/// the first available footprint source onto
/// the body top, snap to nearest corner —
/// chip + silkscreen agree by construction
/// --xy <x> <y> click-style placement at (x,y) mm relative
/// to chip body center
///
/// Three indicator shapes (--shape):
/// dimple (default) recessed cylinder, Ø 0.40 × 0.05 mm
/// raisedDot protruding cylinder, Ø 0.40 × 0.05 mm
/// chamfer angled cut on the body's top corner edge
#[derive(Parser)]
pub struct Args {
#[arg(long, conflicts_with_all = &["from_fp_marker", "xy"])]
pub corner: Option<String>,
#[arg(long, conflicts_with_all = &["corner", "xy"])]
pub from_fp_marker: bool,
/// Two values: <x> <y> in mm relative to chip body center.
#[arg(long, num_args = 2, value_names = &["X_MM", "Y_MM"], conflicts_with_all = &["corner", "from_fp_marker"])]
pub xy: Option<Vec<f64>>,
#[arg(long, default_value = "dimple")]
pub shape: String,
#[arg(long, default_value_t = DEFAULT_PORT)]
pub port: u16,
}
pub fn run(args: Args) -> Result<()> {
if args.corner.is_none() && !args.from_fp_marker && args.xy.is_none() {
err("place-pin1 needs --corner, --from-fp-marker, or --xy".to_string());
hint("e.g. adom-chipsmith place-pin1 --corner NE --shape dimple".to_string());
return Err(anyhow::anyhow!("missing mode arg"));
}
let shape = args.shape;
let snippet = if let Some(corner) = &args.corner {
let c = corner.to_uppercase();
if !matches!(c.as_str(), "NW" | "NE" | "SW" | "SE") {
err(format!("invalid --corner '{c}', expected NW|NE|SW|SE"));
return Err(anyhow::anyhow!("bad corner"));
}
format!(
"return window.adomChipsmith.placePin1({{mode:'corner', corner:'{c}', shape:'{shape}'}});"
)
} else if args.from_fp_marker {
format!("return window.adomChipsmith.placePin1({{mode:'fpMarker', shape:'{shape}'}});")
} else if let Some(xy) = &args.xy {
let x = xy[0];
let y = xy[1];
format!("return window.adomChipsmith.placePin1({{mode:'click', xyMm:[{x},{y}], shape:'{shape}'}});")
} else {
return Err(anyhow::anyhow!("unreachable"));
};
let v = eval_snippet(&snippet, 5, args.port, true)?;
if let Some(e) = v.get("error").and_then(|x| x.as_str()) {
err(format!("placePin1: {e}"));
return Err(anyhow::anyhow!("place failed"));
}
ok(format!("pin-1 placed: {}", serde_json::to_string(&v).unwrap_or_default()));
Ok(())
}