code wiki / _hdl_build / nx_slicer.nx
nx_slicer.nx source
↩ module page · 92 lines · 3383 B
1// nx_slicer.nx -- sovereign STL -> G-code slicer (CLI / MCP organ).
2//
3// nx_slicer slice <stl-path> <gcode-out-path> [layer_h_um] [infill_pct]
4//
5// Reads a binary STL, slices it through the sovereign stack (nx_slicer_lib ->
6// nx_stl + nx_gemit + nx_slice_pipe_run_v2 on the QIDI X-Max 3 machine profile
7// + generic PLA), writes the G-code file, and emits a summary JSON. The
8// sovereign alternative to third-party slicers -- our own geometry->toolpath.
9//
10// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
11import "nx_syscalls.nx"
12import "nx_gcode_emit.nx"
13import "nx_slicer_lib.nx"
14const SL_MAGIC_4096: i64 = 4096
15
16const SL_LH_DEFAULT: i64 = 3277 // 0.2 mm in the slicer's Q14 units
17const SL_Q_PER_MM: i64 = 16384
18
19func slw(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
20
21func main(argc: i64, argv: *i64) -> i64 {
22 if argc < 4 {
23 slw(2, "usage: nx_slicer slice <stl-path> <gcode-out-path> [layer_h_um] [infill_pct]\n" as *u8)
24 sys_exit(2)
25 return 2
26 }
27 let stl_path: *u8 = argv[2] as *u8
28 let out_path: *u8 = argv[3] as *u8
29 var layer_h: i64 = SL_LH_DEFAULT
30 if argc > 4 {
31 let um: i64 = sl_atoi(argv[4] as *u8)
32 if um > 0 { layer_h = (um * SL_Q_PER_MM) / 1000 }
33 }
34 var infill: i64 = 20
35 if argc > 5 {
36 let inf: i64 = sl_atoi(argv[5] as *u8)
37 if inf >= 0 { infill = inf }
38 }
39
40 let out: *u8 = sys_mmap(SL_MAGIC_4096)
41 let lenp: *i64 = sys_mmap(8) as *i64
42 let stl: *u8 = sys_read_file(stl_path, lenp)
43 if (stl as i64) == 0 {
44 let eo: i64 = sl_cat(out, 0, "{\"verb\":\"slice\",\"verdict\":\"READ_FAIL\",\"stl\":\"" as *u8)
45 let eo2: i64 = sl_cat(out, eo, stl_path)
46 let eo3: i64 = sl_cat(out, eo2, "\"}\n" as *u8)
47 sys_write(1, out, eo3)
48 sys_exit(1)
49 return 1
50 }
51 let stl_len: i64 = lenp[0]
52
53 let nl: *i64 = sys_mmap(8) as *i64
54 let nt: *i64 = sys_mmap(8) as *i64
55 let e: *NxGcodeEmitter = sl_slice_stl(stl, stl_len, layer_h, infill, nl, nt)
56 if (e as i64) == 0 {
57 let eo: i64 = sl_cat(out, 0, "{\"verb\":\"slice\",\"verdict\":\"SLICE_FAIL\",\"note\":\"STL parse or slice produced no layers\"}\n" as *u8)
58 sys_write(1, out, eo)
59 sys_exit(1)
60 return 1
61 }
62
63 let fd: i64 = sys_openat_wr(out_path, 0x1a4)
64 if fd < 0 {
65 let eo: i64 = sl_cat(out, 0, "{\"verb\":\"slice\",\"verdict\":\"WRITE_FAIL\"}\n" as *u8)
66 sys_write(1, out, eo)
67 sys_exit(1)
68 return 1
69 }
70 sys_write(fd, e.buf, e.len)
71 sys_close(fd)
72
73 var o: i64 = 0
74 o = sl_cat(out, o, "{\"verb\":\"slice\",\"verdict\":\"OK\",\"stl\":\"" as *u8)
75 o = sl_cat(out, o, stl_path)
76 o = sl_cat(out, o, "\",\"gcode\":\"" as *u8)
77 o = sl_cat(out, o, out_path)
78 o = sl_cat(out, o, "\",\"n_tris\":" as *u8)
79 o = sl_catn(out, o, nt[0])
80 o = sl_cat(out, o, ",\"n_layers\":" as *u8)
81 o = sl_catn(out, o, nl[0])
82 o = sl_cat(out, o, ",\"gcode_bytes\":" as *u8)
83 o = sl_catn(out, o, e.len)
84 o = sl_cat(out, o, ",\"layer_h_q14\":" as *u8)
85 o = sl_catn(out, o, layer_h)
86 o = sl_cat(out, o, ",\"infill_pct\":" as *u8)
87 o = sl_catn(out, o, infill)
88 o = sl_cat(out, o, ",\"machine\":\"qidi-xmax3\",\"material\":\"pla\"}\n" as *u8)
89 sys_write(1, out, o)
90 sys_exit(0)
91 return 0
92}