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}