nx_print_session.nx source
↩ module page · 133 lines · 4710 B
1// nx_print_session.nx -- ALL-IN-ONE push-and-play operator entry.
2//
3// Single function takes (mesh, machine, material, layer_h, line_w,
4// infill_pct, output_buffer_capacity) and:
5//
6// 1. nx_preflight_check (5 sanity gates; refuse on UNSAFE)
7// 2. nx_gemit_new + preamble
8// 3. nx_slice_pipe_run (multi-layer slice + perim + infill)
9// (slice_pipe internally calls skirt + postamble)
10// 4. Returns NxPrintSession with:
11// verdict (SAFE_PRINT / REFUSED)
12// preflight_reason (if REFUSED)
13// emitter pointer (G-code bytes in emitter.buf)
14// layer count
15//
16// Per cardinal feedback-engineering-sciences-bits-up-3d-print-first
17// + NISHI_3D_PRINT_BULLETPROOF_PREFLIGHT_ROADMAP: this is the
18// operator-facing "push and play" API. Instead of orchestrating 5+
19// primitives by hand, operator calls one function -- substrate
20// refuses to emit G-code if any sanity gate fails.
21//
22// Composes EVERY shipped pre-print primitive:
23// nx_preflight (gate)
24// nx_machine_graph (machine envelope)
25// nx_material_profile (material spec)
26// nx_gcode_emit (orchestrator)
27// nx_slice_pipeline (multi-layer)
28//
29// Smoke verifies SAFE case (tetrahedron + Qidi + PLA = G-code
30// produced) + REFUSED case (oversize mesh → no G-code emitted, code
31// fails-loud + verdict carries reason).
32//
33// license_tier: ORIGINAL
34
35import "nx_syscalls.nx"
36import "nx_mesh.nx"
37import "nx_machine_graph.nx"
38import "nx_material_profile.nx"
39import "nx_preflight.nx"
40import "nx_gcode_emit.nx"
41import "nx_slice_pipeline.nx"
42
43// ===== sealed-enum verdicts ========================================
44
45const NX_SESSION_OK: i64 = 0
46const NX_SESSION_REFUSED: i64 = 1
47const NX_SESSION_EMIT_ERR: i64 = 2
48
49func nx_session_verdict_name(v: i64) -> *u8 {
50 if v == NX_SESSION_OK { return "OK" }
51 if v == NX_SESSION_REFUSED { return "REFUSED" }
52 if v == NX_SESSION_EMIT_ERR { return "EMIT_ERR" }
53 return "UNKNOWN"
54}
55
56// ===== result struct ===============================================
57
58struct NxPrintSession {
59 verdict: i64,
60 preflight_reason: i64, // NX_PFR_* code; OK if verdict == OK
61 emitter: *NxGcodeEmitter,
62 n_layers: i64,
63}
64
65const NX_PRINT_SESSION_BYTES: i64 = 32
66
67// ===== run =========================================================
68//
69// All-in-one push-and-play. Returns NxPrintSession pointer with:
70// verdict == NX_SESSION_OK + emitter populated + n_layers > 0
71// -> G-code in emitter.buf[0..emitter.len], operator can upload.
72// verdict == NX_SESSION_REFUSED + preflight_reason set
73// -> Substrate refused; operator must fix the input.
74// verdict == NX_SESSION_EMIT_ERR
75// -> G-code emission failed mid-way (capacity exceeded etc).
76
77func nx_print_session_run(mesh: *NxMesh,
78 machine: *NxMachineGraph,
79 material: *NxMaterialProfile,
80 layer_height_q14: i64,
81 line_width_q14: i64,
82 infill_density_pct: i64,
83 buf_capacity: i64) -> *NxPrintSession {
84 let s: *NxPrintSession = (sys_mmap(NX_PRINT_SESSION_BYTES)) as *NxPrintSession
85 s.verdict = NX_SESSION_OK
86 s.preflight_reason = NX_PFR_OK
87 s.emitter = 0 as *NxGcodeEmitter
88 s.n_layers = 0
89
90 // Step 1: preflight gate
91 let pf: *NxPreflightResult = nx_preflight_check(mesh, machine, material,
92 layer_height_q14,
93 line_width_q14,
94 material.print_speed_mms)
95 if pf.verdict != NX_PREFLIGHT_SAFE {
96 s.verdict = NX_SESSION_REFUSED
97 s.preflight_reason = pf.first_reason
98 return s
99 }
100
101 // Step 2: emitter
102 let e: *NxGcodeEmitter = nx_gemit_new(machine, material,
103 layer_height_q14,
104 line_width_q14,
105 buf_capacity)
106 if (e as i64) == 0 {
107 s.verdict = NX_SESSION_EMIT_ERR
108 return s
109 }
110 s.emitter = e
111
112 // Step 3: preamble + slice pipeline (which calls skirt + per-layer
113 // perimeter+infill + postamble internally)
114 nx_gemit_preamble(e)
115 if e.verdict != NX_GEMIT_OK {
116 s.verdict = NX_SESSION_EMIT_ERR
117 return s
118 }
119
120 let n: i64 = nx_slice_pipe_run(e, mesh, infill_density_pct)
121 if n <= 0 {
122 s.verdict = NX_SESSION_EMIT_ERR
123 return s
124 }
125 s.n_layers = n
126
127 if e.verdict != NX_GEMIT_OK {
128 s.verdict = NX_SESSION_EMIT_ERR
129 return s
130 }
131
132 return s
133}