code wiki / (root) / nx_pcb_drill_gate.nx

nx_pcb_drill_gate.nx source

↩ module page · 148 lines · 5891 B

1// nx_pcb_drill_gate.nx -- R1b GATE of the Omniforge PCB/EDA leg: Excellon drill export. 2// Builds a drill program for the demo board (2 tools, 3 holes at the pad centres), emits via 3// nx_pcb_drill, writes the real .drl artifact, then VERIFIES by reconstructing the canonical ASCII 4// for every tool def + hole from the integer model and asserting EXACT presence (integer round-trip, 5// no float drift). Checks M48/FMAT,2/METRIC/M30 headers, counts hole lines, and a NEGATIVE CONTROL: 6// a hole off by 1um must be ABSENT. Together with nx_pcb_gerber_gate this proves a COMPLETE fab 7// package (copper + drills). 100% sovereign, integer-only. 8// license_tier: ORIGINAL expect_exit: 0 9import "nx_syscalls.nx" 10import "nx_pcb_drill.nx" 11 12func sw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 13func sn(v: i64) -> i64 { 14 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 15 var m: i64 = v 16 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 17 let d: *u8 = sys_mmap(24); var k: i64 = 0 18 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 19 let o: *u8 = sys_mmap(24); var i: i64 = 0 20 while i < k { o[i] = d[k - 1 - i]; i = i + 1 } 21 sys_write(1, o, k); return 0 22} 23 24func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 25 26func contains(hay: *u8, haylen: i64, needle: *u8) -> i64 { 27 let nl: i64 = slen(needle) 28 if nl == 0 { return 1 } 29 var i: i64 = 0 30 while i + nl <= haylen { 31 var j: i64 = 0 32 var ok: i64 = 1 33 while j < nl { if hay[i + j] != needle[j] { ok = 0; j = nl } else { j = j + 1 } } 34 if ok == 1 { return 1 } 35 i = i + 1 36 } 37 return 0 38} 39 40func count_occur(hay: *u8, haylen: i64, needle: *u8) -> i64 { 41 let nl: i64 = slen(needle) 42 if nl == 0 { return 0 } 43 var c: i64 = 0 44 var i: i64 = 0 45 while i + nl <= haylen { 46 var j: i64 = 0 47 var ok: i64 = 1 48 while j < nl { if hay[i + j] != needle[j] { ok = 0; j = nl } else { j = j + 1 } } 49 if ok == 1 { c = c + 1; i = i + nl } else { i = i + 1 } 50 } 51 return c 52} 53 54// build expected "X<mm>Y<mm>" (NUL-terminated) into nb using the SHARED g_mm6 formatter 55func expect_hole(nb: *u8, x_um: i64, y_um: i64) -> i64 { 56 let len: *i64 = sys_mmap(8) as *i64 57 len[0] = 0 58 g_puts(nb, len, "X" as *u8); g_mm6(nb, len, x_um) 59 g_puts(nb, len, "Y" as *u8); g_mm6(nb, len, y_um) 60 nb[len[0]] = 0 as u8 61 return 0 62} 63 64// build expected tool def "Tn C<mm>" (NUL-terminated) into nb 65func expect_tool(nb: *u8, tcode: i64, dia_um: i64) -> i64 { 66 let len: *i64 = sys_mmap(8) as *i64 67 len[0] = 0 68 g_puts(nb, len, "T" as *u8); g_puti(nb, len, tcode) 69 g_puts(nb, len, "C" as *u8); g_mm6(nb, len, dia_um) 70 nb[len[0]] = 0 as u8 71 return 0 72} 73 74func check(name: *u8, cond: i64, tot: *i64) -> i64 { 75 if cond == 1 { sw(" ok " as *u8); tot[0] = tot[0] + 1 } 76 else { sw(" FAIL " as *u8); tot[1] = tot[1] + 1 } 77 sw(name); sw("\n" as *u8) 78 return 0 79} 80 81func main() -> i64 { 82 let tot: *i64 = sys_mmap(16) as *i64 83 tot[0] = 0; tot[1] = 0 84 85 sw("=== nx_pcb_drill_gate R1b -- PCB/EDA Excellon drill export (integer-only round-trip) ===\n" as *u8) 86 87 // ---- drill model: 2 tools (0.8mm, 1.0mm), 3 holes at the demo-board pad centres ---- 88 let tool_dia: *i64 = sys_mmap(64) as *i64 89 tool_dia[0] = 800; tool_dia[1] = 1000 90 let n_tool: i64 = 2 91 92 let hole_tool: *i64 = sys_mmap(64) as *i64 93 let hole_x: *i64 = sys_mmap(64) as *i64 94 let hole_y: *i64 = sys_mmap(64) as *i64 95 hole_tool[0] = 0; hole_x[0] = 1000; hole_y[0] = 1000 96 hole_tool[1] = 0; hole_x[1] = 9000; hole_y[1] = 1000 97 hole_tool[2] = 1; hole_x[2] = 9000; hole_y[2] = 6000 98 let n_hole: i64 = 3 99 100 let cap: i64 = 65536 101 let out: *u8 = sys_mmap(cap) 102 let dlen: i64 = excellon_emit(tool_dia, n_tool, hole_tool, hole_x, hole_y, n_hole, out) 103 sw(" emitted Excellon bytes=" as *u8); sn(dlen); sw("\n" as *u8) 104 105 let fd: i64 = sys_openat_wr("knowledge/nx_omniforge_demo.drl" as *u8, 0x1a4) 106 if fd >= 0 { sys_write(fd, out, dlen); sys_close(fd); sw(" wrote knowledge/nx_omniforge_demo.drl\n" as *u8) } 107 else { sw(" (artifact write skipped: open failed)\n" as *u8) } 108 109 // headers 110 check("header M48 present" as *u8, contains(out, dlen, "M48" as *u8), tot) 111 check("FMAT,2 present" as *u8, contains(out, dlen, "FMAT,2" as *u8), tot) 112 check("METRIC units present" as *u8, contains(out, dlen, "METRIC" as *u8), tot) 113 check("end-of-program M30 present" as *u8, contains(out, dlen, "M30" as *u8), tot) 114 115 // tool defs round-trip 116 let nb: *u8 = sys_mmap(64) 117 expect_tool(nb, 1, tool_dia[0]) 118 check("tool T1 C0.800000 round-trip exact" as *u8, contains(out, dlen, nb), tot) 119 expect_tool(nb, 2, tool_dia[1]) 120 check("tool T2 C1.000000 round-trip exact" as *u8, contains(out, dlen, nb), tot) 121 122 // every hole round-trip exact 123 var allh: i64 = 1 124 var i: i64 = 0 125 while i < n_hole { 126 expect_hole(nb, hole_x[i], hole_y[i]) 127 if contains(out, dlen, nb) == 0 { allh = 0 } 128 i = i + 1 129 } 130 check("all 3 drill hits round-trip exact" as *u8, allh, tot) 131 132 // hole-line count (each hit line starts with newline+X; nothing else does) 133 var ch: i64 = count_occur(out, dlen, "\nX" as *u8) 134 var okc: i64 = 0 135 if ch == n_hole { okc = 1 } 136 check("drill-hit line count == n_hole (3)" as *u8, okc, tot) 137 138 // NEGATIVE CONTROL: a hole off by 1um must be ABSENT 139 expect_hole(nb, hole_x[0] + 1, hole_y[0]) 140 var neg_absent: i64 = 0 141 if contains(out, dlen, nb) == 0 { neg_absent = 1 } 142 check("NEG-CONTROL: off-by-1um hole is ABSENT (round-trip has teeth)" as *u8, neg_absent, tot) 143 144 sw("=== VERDICT pass=" as *u8); sn(tot[0]); sw(" fail=" as *u8); sn(tot[1]); sw(" ===\n" as *u8) 145 if tot[1] == 0 { sys_exit(0) } 146 sys_exit(1) 147 return 1 148}