nx_gcode_emit_test.nx source
↩ module page · 111 lines · 4216 B
1// nx_gcode_emit_test.nx -- end-to-end compose: hand-built unit
2// square contour + Qidi X-Max 3 + Generic PLA -> emit full G-code
3// file structure (preamble + layer + postamble) + verify the output
4// contains expected G-code keywords.
5//
6// Closed-form invariants:
7// (a) Emitter constructs OK; filament_xsect precomputed sane
8// (positive Q14 value, ~39408 for 1.75mm filament).
9// (b) Preamble emits successfully; output contains "M104 S215"
10// (Generic PLA first-layer hotend) and "G28" (home all).
11// (c) Per-layer emit produces non-zero output length growth.
12// (d) Output contains "G1 X" (print moves).
13// (e) Output contains "E" (extruder accumulation).
14// (f) Postamble adds "M104 S0" (hotend off) and "M84" (motors off).
15// (g) E_acc_q14 is non-zero after layer emit (filament was fed).
16// (h) E_acc_q14 ~= perimeter_mm * E_per_mm; for a 1mm square
17// perimeter = 4mm, E_per_mm ~= 0.0333 mm filament/mm move,
18// so total E ~= 0.1332 mm ~= 2182 Q14 (±100 tolerance).
19// (i) Final length is reasonable (200..10000 bytes for this case).
20//
21// expect_exit: 0
22// license_tier: ORIGINAL
23
24import "nx_syscalls.nx"
25import "nx_polygon.nx"
26import "nx_slice_contour.nx"
27import "nx_machine_graph.nx"
28import "nx_material_profile.nx"
29import "nx_gcode_emit.nx"
30import "nx_gcode_extrude.nx"
31
32const Q14: i64 = 16384
33
34// Substring search: returns 1 if buf[0..len] contains needle.
35func smoke_contains(buf: *u8, len: i64, needle: *u8) -> i64 {
36 var nlen: i64 = 0
37 while needle[nlen] != 0 { nlen = nlen + 1 }
38 if nlen == 0 { return 1 }
39 if len < nlen { return 0 }
40 var i: i64 = 0
41 while i <= len - nlen {
42 var j: i64 = 0
43 var matched: i64 = 1
44 while j < nlen {
45 if buf[i + j] != needle[j] { matched = 0; j = nlen }
46 j = j + 1
47 }
48 if matched == 1 { return 1 }
49 i = i + 1
50 }
51 return 0
52}
53
54func main() -> i64 {
55 let machine: *NxMachineGraph = nx_machine_graph_qidi_xmax3()
56 let material: *NxMaterialProfile = nx_material_profile_generic_pla()
57
58 // 0.2mm layer, 0.4mm line width (both as Q14 mm)
59 let layer_h_q14: i64 = 3277 // 0.2 * 16384 ≈ 3276.8
60 let line_w_q14: i64 = 6554 // 0.4 * 16384 ≈ 6553.6
61
62 let e: *NxGcodeEmitter = nx_gemit_new(machine, material,
63 layer_h_q14, line_w_q14, 8192)
64 if (e as i64) == 0 { return 5 }
65
66 // --- (a) Construction ---
67 if e.filament_xsect_q14 < 39000 { return 10 }
68 if e.filament_xsect_q14 > 39800 { return 11 }
69 if e.verdict != NX_GEMIT_OK { return 12 }
70
71 // --- (b) Preamble ---
72 let len_pre: i64 = e.len
73 nx_gemit_preamble(e)
74 if e.len <= len_pre { return 20 }
75 if smoke_contains(e.buf, e.len, "M104 S215") != 1 { return 21 }
76 if smoke_contains(e.buf, e.len, "G28") != 1 { return 22 }
77 if smoke_contains(e.buf, e.len, "M109 S215") != 1 { return 23 }
78
79 // --- Build a synthetic single-polygon contour collection.
80 // Unit-mm square at (0,0)-(1mm,1mm).
81 let sq: *NxPolygon = nx_polygon_make_square(0, 0, Q14, Q14)
82 let contours: *NxSliceContours = nx_slice_contours_new(1)
83 nx_slice_contours_put(contours, 0, sq)
84 contours.n_polys = 1
85
86 // --- (c)(d)(e)(g)(h) Layer 0 emit ---
87 let len_after_pre: i64 = e.len
88 let E_before: i64 = e.E_acc_q14
89 nx_gemit_layer(e, contours, 0)
90 if e.len <= len_after_pre { return 30 }
91 if smoke_contains(e.buf, e.len, "G1 X") != 1 { return 31 }
92 if smoke_contains(e.buf, e.len, "E") != 1 { return 32 }
93 if e.E_acc_q14 <= E_before { return 33 }
94 // Expected E ~ 2182 Q14 (0.1332 mm) for 4mm perimeter
95 let E_delta: i64 = e.E_acc_q14 - E_before
96 if E_delta < 2050 { return 34 }
97 if E_delta > 2320 { return 35 }
98
99 // --- (f) Postamble ---
100 let len_pre_post: i64 = e.len
101 nx_gemit_postamble(e)
102 if e.len <= len_pre_post { return 40 }
103 if smoke_contains(e.buf, e.len, "M104 S0") != 1 { return 41 }
104 if smoke_contains(e.buf, e.len, "M84") != 1 { return 42 }
105
106 // --- (i) Reasonable total length ---
107 if e.len < 200 { return 50 }
108 if e.len > 10000 { return 51 }
109
110 return 0
111}