code wiki / (root) / nx_gcode_emit_test.nx

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}