skill
EDA Bridge Standard: one way for an AI to drive every PCB tool
Public Made by Adomby adom
The standard every Adom EDA bridge follows so one AI can drive Altium, KiCad, Fusion 360 and any future PCB tool the same way: shared verb names in tiers, the board model JSON, reply and refusal conventions, and a coverage table of each bridge against the Altium reference.
← Commit history
Merge PR #321: altium-lane: marking font, D and B no longer read as IO and 8 (body3d)
1 file changed
+19−1
engine/src/writers/body3d.rs+19−1@@ -312,10 +312,16 @@ fn glyph(c: char) -> Option<&'static [((f64, f64), (f64, f64))]> { const DBL: ((f64, f64), (f64, f64)) = (MM, BL); const DBR: ((f64, f64), (f64, f64)) = (MM, BR); const LB: ((f64, f64), (f64, f64)) = (ML, BM); const RB: ((f64, f64), (f64, f64)) = (MR, BM); const DOT: ((f64, f64), (f64, f64)) = ((0.4, 0.0), (0.6, 0.0));+ // D and B: the left side full and the right corners cut, so D does not read as I and O side by side (it was a+ // box with a centre bar: "ADOM" read "AIOM" on a QFN in Altium, 2026-10-28) and B is not an 8+ const KT: (f64, f64) = (0.75, 2.0); const KM: (f64, f64) = (0.75, 1.0); const KB: (f64, f64) = (0.75, 0.0);+ const RT: (f64, f64) = (1.0, 1.75); const RU: (f64, f64) = (1.0, 1.25); const RL: (f64, f64) = (1.0, 0.75); const RB0: (f64, f64) = (1.0, 0.25);+ const DG: &[((f64, f64), (f64, f64))] = &[F, E, (TL, KT), (KT, RT), (RT, RB0), (RB0, KB), (BL, KB)];+ const BG: &[((f64, f64), (f64, f64))] = &[F, E, (TL, KT), (KT, RT), (RT, RU), (RU, KM), (ML, KM), (KM, RL), (RL, RB0), (RB0, KB), (BL, KB)]; Some(match c.to_ascii_uppercase() { '0' => &[A, B, C, D, E, F, DTR, DBL], '1' => &[V], '2' => &[A, B, G, E, D], '3' => &[A, B, G2, C, D], '4' => &[F, G, B, C], '5' => &[A, F, G, C, D], '6' => &[A, F, E, D, C, G], '7' => &[A, B, C], '8' => &[A, B, C, D, E, F, G],- '9' => &[A, B, C, D, F, G], 'A' => &[E, F, A, B, C, G], 'B' => &[A, B, C, D, V, G2], 'C' => &[A, F, E, D], 'D' => &[A, B, C, D, V],+ '9' => &[A, B, C, D, F, G], 'A' => &[E, F, A, B, C, G], 'B' => BG, 'C' => &[A, F, E, D], 'D' => DG, 'E' => &[A, F, E, D, G1], 'F' => &[A, F, E, G1], 'G' => &[A, F, E, D, C, G2], 'H' => &[F, E, B, C, G], 'I' => &[A, V, D], 'J' => &[B, C, D, E], 'K' => &[F, E, G1, DTR, DBR], 'L' => &[F, E, D], 'M' => &[E, F, B, C, DTL, DTR], 'N' => &[E, F, B, C, DTL, DBR], 'O' => &[A, B, C, D, E, F], 'P' => &[A, B, F, E, G], 'Q' => &[A, B, C, D, E, F, DBR], 'R' => &[A, B, F, E, G, DBR],@@ -520,4 +526,16 @@ mod tests { // pins is the total in a BGA too: 64 balls are an 8 x 8 grid assert_eq!(package("bga", json!({"pins": 64}).as_object().unwrap()).unwrap().len(), 65); }++ #[test]+ fn d_and_b_are_not_i_o_or_8() {+ // D was a box with a centre bar and read as "IO"; B was an 8 with a bar+ assert_ne!(glyph('D'), glyph('O'));+ assert_ne!(glyph('B'), glyph('8'));+ for c in ['D', 'B'] {+ let g = glyph(c).unwrap();+ assert!(g.iter().all(|s| s.0 .0 != 0.5 || s.1 .0 != 0.5), "{c} has no centre bar");+ assert!(!g.iter().any(|s| (s.0 == (1.0, 2.0)) || (s.1 == (1.0, 2.0))), "{c}'s top-right corner is cut");+ }+ } }