code wiki / _hdl_build / nx_contour_print.nx

nx_contour_print.nx source

↩ module page · 121 lines · 5565 B

1// nx_contour_print.nx -- LIB: the UNIFIED multi-material contour emitter (3D-printing R1b). Generalises from a 2// hardcoded rectangle to ANY closed polygon contour, so arbitrary geometry (not just a wall) prints in any 3// material through ONE function. (Production contours come from the mature nx_slice_* pipeline; this proves the 4// emitter accepts arbitrary polygons + makes the R-ECO cistern ROUND.) Material family selects the deltas: 5// FILAMENT = hot hotend (M104/M109), METAL = arc (M3/M5) + inter-layer cooling dwell (G4), PASTE = cold; the 6// contour-tracing + layering is shared. No float: a 12-point integer circle table + Newton integer sqrt for 7// path length. CARDINAL 26: motion + extrusion/arc/hotend-temp only; no firmware/EEPROM. license_tier: ORIGINAL 8import "nx_print_material.nx" 9import "nx_food_science.nx" 10import "nx_seg_store.nx" 11import "nx_syscalls.nx" 12 13// integer microns -> "D.DDD" mm (valid Z for every firmware; whole-mm shows as e.g. 10.000) 14func cp_um_to_mm(dst: *u8, off: i64, um: i64) -> i64 { 15 var o: i64 = off 16 o = fd_apnum(dst, o, um / 1000) 17 dst[o] = 46 as u8; o = o + 1 18 let frac: i64 = um % 1000 19 dst[o] = (48 + (frac / 100)) as u8; o = o + 1 20 dst[o] = (48 + ((frac / 10) % 10)) as u8; o = o + 1 21 dst[o] = (48 + (frac % 10)) as u8; o = o + 1 22 return o 23} 24// Newton integer sqrt 25func cp_isqrt(nn: i64) -> i64 { 26 if nn <= 0 { return 0 } 27 var x: i64 = nn 28 var y: i64 = (x + 1) / 2 29 while y < x { x = y; y = (x + nn / x) / 2 } 30 return x 31} 32func cp_seglen(x0: i64, y0: i64, x1: i64, y1: i64) -> i64 { 33 let dx: i64 = x1 - x0 34 let dy: i64 = y1 - y0 35 return cp_isqrt(dx * dx + dy * dy) 36} 37func cp_move(out: *u8, off: i64, x: i64, y: i64, e: i64) -> i64 { 38 var o: i64 = off 39 o = as_append(out, o, "G1 X" as *u8); o = fd_apnum(out, o, x) 40 o = as_append(out, o, " Y" as *u8); o = fd_apnum(out, o, y) 41 o = as_append(out, o, " E" as *u8); o = fd_apnum(out, o, e) 42 o = as_append(out, o, " F1200\n" as *u8) 43 return o 44} 45 46// ---- geometry generators (contours; any polygon works) ---- 47func cg_rect(xs: *i64, ys: *i64, w: i64, d: i64) -> i64 { 48 xs[0] = 0; ys[0] = 0 49 xs[1] = w; ys[1] = 0 50 xs[2] = w; ys[2] = d 51 xs[3] = 0; ys[3] = d 52 return 4 53} 54// 12-gon approximating a circle (no trig): unit cos/sin x1000, scaled by r about (cx,cy) 55func cg_circle(xs: *i64, ys: *i64, cx: i64, cy: i64, r: i64) -> i64 { 56 let co: *i64 = sys_mmap(8 * 16) as *i64 57 let si: *i64 = sys_mmap(8 * 16) as *i64 58 co[0] = 1000; si[0] = 0 59 co[1] = 866; si[1] = 500 60 co[2] = 500; si[2] = 866 61 co[3] = 0; si[3] = 1000 62 co[4] = 0 - 500; si[4] = 866 63 co[5] = 0 - 866; si[5] = 500 64 co[6] = 0 - 1000; si[6] = 0 65 co[7] = 0 - 866; si[7] = 0 - 500 66 co[8] = 0 - 500; si[8] = 0 - 866 67 co[9] = 0; si[9] = 0 - 1000 68 co[10] = 500; si[10] = 0 - 866 69 co[11] = 866; si[11] = 0 - 500 70 var i: i64 = 0 71 while i < 12 { xs[i] = cx + r * co[i] / 1000; ys[i] = cy + r * si[i] / 1000; i = i + 1 } 72 return 12 73} 74 75// emit `h`-tall prism of an arbitrary polygon (xs/ys, npts) in `mat_id`. Returns byte length. 76func cp_emit_prism(prefix: *u8, mat_id: *u8, xs: *i64, ys: *i64, npts: i64, h: i64, out: *u8) -> i64 { 77 let fam: *u8 = sys_mmap(24); pm_field_str(prefix, mat_id, 1, fam) 78 var hot: i64 = 0; var arc: i64 = 0 79 if pm_streq(fam, "FILAMENT" as *u8) == 1 { hot = 1 } 80 if pm_streq(fam, "METAL" as *u8) == 1 { arc = 1 } 81 let temp: i64 = pm_field_int(prefix, mat_id, 5) 82 var layer_um: i64 = pm_field_int(prefix, mat_id, 4); if layer_um <= 0 { layer_um = 200 } 83 let nm: *u8 = sys_mmap(48); pm_field_str(prefix, mat_id, 0, nm) 84 85 var o: i64 = 0 86 o = as_append(out, o, "; Nishi multi-material contour G-code -- " as *u8); o = as_append(out, o, nm); out[o] = 10 as u8; o = o + 1 87 o = as_append(out, o, "; NEVER-BRICK (Cardinal 26): motion + extrusion/arc/hotend-temp only; no firmware/EEPROM\n" as *u8) 88 if hot == 1 { 89 o = as_append(out, o, "M104 S" as *u8); o = fd_apnum(out, o, temp); out[o] = 10 as u8; o = o + 1 90 o = as_append(out, o, "M140 S60\nM190 S60\n" as *u8) 91 o = as_append(out, o, "M109 S" as *u8); o = fd_apnum(out, o, temp); out[o] = 10 as u8; o = o + 1 92 } 93 o = as_append(out, o, "G21\nG90\nG28\nG92 E0\n" as *u8) 94 95 let nlayers: i64 = h * 1000 / layer_um 96 var e: i64 = 0 97 var li: i64 = 0 98 while li < nlayers { 99 let zum: i64 = (li + 1) * layer_um 100 o = as_append(out, o, ";LAYER:" as *u8); o = fd_apnum(out, o, li); out[o] = 10 as u8; o = o + 1 101 o = as_append(out, o, "G1 Z" as *u8); o = cp_um_to_mm(out, o, zum); o = as_append(out, o, " F600\n" as *u8) 102 if arc == 1 { o = as_append(out, o, "M3 S150\n" as *u8) } 103 o = as_append(out, o, "G0 X" as *u8); o = fd_apnum(out, o, xs[0]); o = as_append(out, o, " Y" as *u8); o = fd_apnum(out, o, ys[0]); out[o] = 10 as u8; o = o + 1 104 var k: i64 = 1 105 while k < npts { 106 e = e + cp_seglen(xs[k - 1], ys[k - 1], xs[k], ys[k]) 107 o = cp_move(out, o, xs[k], ys[k], e) 108 k = k + 1 109 } 110 e = e + cp_seglen(xs[npts - 1], ys[npts - 1], xs[0], ys[0]) 111 o = cp_move(out, o, xs[0], ys[0], e) 112 if arc == 1 { o = as_append(out, o, "M5\nG4 P2000\n" as *u8) } 113 li = li + 1 114 } 115 o = as_append(out, o, "; end\n" as *u8) 116 if hot == 1 { o = as_append(out, o, "M104 S0\nM140 S0\n" as *u8) } 117 if arc == 1 { o = as_append(out, o, "M5\n" as *u8) } 118 o = as_append(out, o, "M84\n" as *u8) 119 out[o] = 0 as u8 120 return o 121}