code wiki / _hdl_build / nx_contour_print.nx

nx_contour_print.nx source

↩ module page · 116 lines · 5470 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" 12import "nx_vecmath.nx" 13 14// integer microns -> "D.DDD" mm (valid Z for every firmware; whole-mm shows as e.g. 10.000) 15func cp_um_to_mm(dst: *u8, off: i64, um: i64) -> i64 { 16 var o: i64 = off 17 o = fd_apnum(dst, o, um / 1000) 18 dst[o] = 46 as u8; o = o + 1 19 let frac: i64 = um % 1000 20 dst[o] = (48 + (frac / 100)) as u8; o = o + 1 21 dst[o] = (48 + ((frac / 10) % 10)) as u8; o = o + 1 22 dst[o] = (48 + (frac % 10)) as u8; o = o + 1 23 return o 24} 25// Newton integer sqrt 26func cp_isqrt(nn: i64) -> i64 { return vm_isqrt(nn) } 27func cp_seglen(x0: i64, y0: i64, x1: i64, y1: i64) -> i64 { 28 let dx: i64 = x1 - x0 29 let dy: i64 = y1 - y0 30 return cp_isqrt(dx * dx + dy * dy) 31} 32func cp_move(out: *u8, off: i64, x: i64, y: i64, e: i64) -> i64 { 33 var o: i64 = off 34 o = as_append(out, o, "G1 X" as *u8); o = fd_apnum(out, o, x) 35 o = as_append(out, o, " Y" as *u8); o = fd_apnum(out, o, y) 36 o = as_append(out, o, " E" as *u8); o = fd_apnum(out, o, e) 37 o = as_append(out, o, " F1200\n" as *u8) 38 return o 39} 40 41// ---- geometry generators (contours; any polygon works) ---- 42func cg_rect(xs: *i64, ys: *i64, w: i64, d: i64) -> i64 { 43 xs[0] = 0; ys[0] = 0 44 xs[1] = w; ys[1] = 0 45 xs[2] = w; ys[2] = d 46 xs[3] = 0; ys[3] = d 47 return 4 48} 49// 12-gon approximating a circle (no trig): unit cos/sin x1000, scaled by r about (cx,cy) 50func cg_circle(xs: *i64, ys: *i64, cx: i64, cy: i64, r: i64) -> i64 { 51 let co: *i64 = sys_mmap(8 * 16) as *i64 52 let si: *i64 = sys_mmap(8 * 16) as *i64 53 co[0] = 1000; si[0] = 0 54 co[1] = 866; si[1] = 500 55 co[2] = 500; si[2] = 866 56 co[3] = 0; si[3] = 1000 57 co[4] = 0 - 500; si[4] = 866 58 co[5] = 0 - 866; si[5] = 500 59 co[6] = 0 - 1000; si[6] = 0 60 co[7] = 0 - 866; si[7] = 0 - 500 61 co[8] = 0 - 500; si[8] = 0 - 866 62 co[9] = 0; si[9] = 0 - 1000 63 co[10] = 500; si[10] = 0 - 866 64 co[11] = 866; si[11] = 0 - 500 65 var i: i64 = 0 66 while i < 12 { xs[i] = cx + r * co[i] / 1000; ys[i] = cy + r * si[i] / 1000; i = i + 1 } 67 return 12 68} 69 70// emit `h`-tall prism of an arbitrary polygon (xs/ys, npts) in `mat_id`. Returns byte length. 71func cp_emit_prism(prefix: *u8, mat_id: *u8, xs: *i64, ys: *i64, npts: i64, h: i64, out: *u8) -> i64 { 72 let fam: *u8 = sys_mmap(24); pm_field_str(prefix, mat_id, 1, fam) 73 var hot: i64 = 0; var arc: i64 = 0 74 if pm_streq(fam, "FILAMENT" as *u8) == 1 { hot = 1 } 75 if pm_streq(fam, "METAL" as *u8) == 1 { arc = 1 } 76 let temp: i64 = pm_field_int(prefix, mat_id, 5) 77 var layer_um: i64 = pm_field_int(prefix, mat_id, 4); if layer_um <= 0 { layer_um = 200 } 78 let nm: *u8 = sys_mmap(48); pm_field_str(prefix, mat_id, 0, nm) 79 80 var o: i64 = 0 81 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 82 o = as_append(out, o, "; NEVER-BRICK (Cardinal 26): motion + extrusion/arc/hotend-temp only; no firmware/EEPROM\n" as *u8) 83 if hot == 1 { 84 o = as_append(out, o, "M104 S" as *u8); o = fd_apnum(out, o, temp); out[o] = 10 as u8; o = o + 1 85 o = as_append(out, o, "M140 S60\nM190 S60\n" as *u8) 86 o = as_append(out, o, "M109 S" as *u8); o = fd_apnum(out, o, temp); out[o] = 10 as u8; o = o + 1 87 } 88 o = as_append(out, o, "G21\nG90\nG28\nG92 E0\n" as *u8) 89 90 let nlayers: i64 = h * 1000 / layer_um 91 var e: i64 = 0 92 var li: i64 = 0 93 while li < nlayers { 94 let zum: i64 = (li + 1) * layer_um 95 o = as_append(out, o, ";LAYER:" as *u8); o = fd_apnum(out, o, li); out[o] = 10 as u8; o = o + 1 96 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) 97 if arc == 1 { o = as_append(out, o, "M3 S150\n" as *u8) } 98 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 99 var k: i64 = 1 100 while k < npts { 101 e = e + cp_seglen(xs[k - 1], ys[k - 1], xs[k], ys[k]) 102 o = cp_move(out, o, xs[k], ys[k], e) 103 k = k + 1 104 } 105 e = e + cp_seglen(xs[npts - 1], ys[npts - 1], xs[0], ys[0]) 106 o = cp_move(out, o, xs[0], ys[0], e) 107 if arc == 1 { o = as_append(out, o, "M5\nG4 P2000\n" as *u8) } 108 li = li + 1 109 } 110 o = as_append(out, o, "; end\n" as *u8) 111 if hot == 1 { o = as_append(out, o, "M104 S0\nM140 S0\n" as *u8) } 112 if arc == 1 { o = as_append(out, o, "M5\n" as *u8) } 113 o = as_append(out, o, "M84\n" as *u8) 114 out[o] = 0 as u8 115 return o 116}