claude init

This commit is contained in:
Thaddeus Hughes
2026-04-03 21:47:22 -05:00
parent f3953d66ae
commit 9d2379205f
26 changed files with 2382 additions and 4243 deletions

View File

@@ -1,4 +1,5 @@
#!/bin/bash
# M101: Enable CNC Z-axis control via HAL signal (pair with M102 to disable)
halcmd sets z-override True
exit 0

View File

@@ -1,4 +1,5 @@
#!/bin/bash
# M102: Disable CNC Z-axis control for manual quill operation (pair with M101 to re-enable)
halcmd sets z-override False
exit 0

View File

@@ -1,3 +1,6 @@
; Helical bore subroutine - cuts a circular hole by helical interpolation
; Params: #1=x, #2=y, #3=diameter, #4=zstart, #5=zend, #6=stepdown
; Uses #<_td> (tool diameter) to compute offset radius
o<bore> sub
; x, y, d, stepdown, zstart, zend
G90
@@ -5,22 +8,22 @@ o<bore> sub
G0 X#1 Y#2
G0 Z#4
G1 X[#1+#3/2-#<_td>/2] Y[#2]
G1 X[#1+#3/2-#<_td>/2] Y[#2] ; move to bore edge, compensated for tool radius
G17
#<r> = [#3/2-#<_td>/2]
#<r> = [#3/2-#<_td>/2] ; effective bore radius (bore radius minus tool radius)
#<z> = [#4-#6]
o101 while [#<z> GT #5]
o101 while [#<z> GT #5] ; helical passes, one full circle per stepdown
G3 X[#1+#<r>] Y[#2] I[-#<r>] Z[#<z>] P1
#<z> = [#<z> - #6]
o101 endwhile
o102 if [#4 GT #5]
o102 if [#4 GT #5] ; partial final pass to reach exact zend
#<ang> = [[#<z>-#5]/#6*360]
#<ang> = [[#<z>-#5]/#6*360] ; angle where remaining depth is consumed
G3 X[#1+COS[#<ang>]*#<r>] Y[#2+SIN[#<ang>]*#<r>] I[-#<r>] Z[#5]
G3 X[#1+COS[#<ang>]*#<r>] Y[#2+SIN[#<ang>]*#<r>] I[-COS[#<ang>]*#<r>] J[-SIN[#<ang>]*#<r>] Z[#5]
G3 X[#1+COS[#<ang>]*#<r>] Y[#2+SIN[#<ang>]*#<r>] I[-COS[#<ang>]*#<r>] J[-SIN[#<ang>]*#<r>] Z[#5] ; cleanup pass at final depth
;G3 X#1 Y[#2+#3/2-#<_td>/2] J[-#3/2+#<_td>/2]
o102 endif

View File

@@ -1,3 +1,5 @@
; Peck drill subroutine - drills with retract cycles to clear chips
; Params: #1=x, #2=y, #3=zstart, #4=zend, #5=peck_depth
o<drill> sub
; x1, y1, zstart, zend, peckdp
; #1 #2 #3 #4 #5
@@ -20,9 +22,9 @@ o<drill> sub
o104 if [#5 NE 0] ; peck drilling
#<h> = #3
o101 while [#<h> GT #4]
G1 Z#<h>
G0 Z#3
G0 Z[#<h>+.02]
G1 Z#<h> ; drill to current peck depth
G0 Z#3 ; retract to clear chips
G0 Z[#<h>+.02] ; rapid back down, stopping just above previous depth
#<h> = [#<h>-#5]
o101 endwhile
o104 endif

View File

@@ -1,3 +1,5 @@
; Manual drill positioning - moves to X/Y, disables Z for manual quill, then pauses
; Params: #1=x, #2=y
o<drill_man> sub
; x1, y1
; #1 #2

View File

@@ -1,3 +1,6 @@
; Semi-manual drill with Z retract - positions X/Y, retracts Z, pauses for manual drill
; Params: #1=x, #2=y, #3=z_clearance
; BUG: endsub name (drill_man_retract) doesn't match sub name (drill_retr)
o<drill_retr> sub
; x1, y1, z_clr
; #1 #2, #3
@@ -12,12 +15,12 @@ o<drill_retr> sub
;;;;;;;;;; PROGRAM ;;;;;;;;;
M101
M101 ; enable Z for CNC retract
G0 Z#<z_clearance>
G0 X#1 Y#2
M102 ; disable Z-axis (M101 enables)
M0 ; pause
M101
M0 ; pause for manual drilling
M101 ; re-enable Z for retract
G0 Z#<z_clearance>
o<drill_man_retract> endsub

View File

@@ -1,3 +1,7 @@
; Circle perimeter cut - cuts inside or outside a circular profile
; Params: #1=x, #2=y, #3=diameter, #4=ztop, #5=zbot, #6=fincut, #7=mode
; Mode bitmask: bit0=conventional, bit1=bothways, bit2=plunge(vs helix), bit3=outside
; Uses arc lead-in/lead-out for smooth entry and exit
o<frame_circ> sub
; o<frame_circ> call [x][y] [diameter] [ztop][zbot] [fincut] [mode]
@@ -25,7 +29,7 @@ o<frame_circ> sub
o1 endif
#<r_entry> = #<tr>
#<r_entry> = #<tr> ; lead-in arc radius, capped at 15% of diameter
o10 if [#<r_entry> GT #3*0.15]
#<r_entry> = [#3*0.15]
o10 endif

View File

@@ -1,3 +1,6 @@
; Rectangle perimeter cut - cuts inside or outside a rectangular frame
; Params: #1=x1, #2=y1, #3=x2, #4=y2, #5=ztop, #6=zbot, #7=mode, #8=corner_radius
; Mode bitmask: bit0=conventional, bit1=bothways, bit2=plunge(vs helix), bit3=outside
o<frame_rect> sub
; o<frame_rect> call [x1][y1] [x2][y2] [ztop][zbot] [mode] [radius]
@@ -43,7 +46,7 @@ o<frame_rect> sub
o10 if [#<M_INSIDE> AND #<M_CONVENTIONAL>]
; plunge in center
; CW inside: plunge in center, traverse to wall, trace perimeter
G0 X[[#1+#3]/2] Y[[#2+#4]/2]
G0 Z#5
G1 Z#6
@@ -74,7 +77,7 @@ o<frame_rect> sub
G0 Z#5
o10 elseif [#<M_INSIDE> AND #<M_CLIMB>]
; CCW inside
; CCW inside: plunge in center, trace perimeter counterclockwise
G0 X[[#1+#3]/2] Y[[#2+#4]/2]
G0 Z#5
G1 Z#6
@@ -104,7 +107,7 @@ o<frame_rect> sub
G0 Z#5
o10 elseif [#<M_OUTSIDE> AND #<M_CONVENTIONAL>]
; plunge at corner
; CW outside: plunge at corner, trace perimeter offset outward
G0 X[#<minx>-#<tr>] Y[#<maxy>+#<tr>]
G0 Z#5
G1 Z#6
@@ -129,7 +132,7 @@ o<frame_rect> sub
G0 Z#5
o10 elseif [#<M_OUTSIDE> AND #<M_CLIMB>]
; plunge at corner
; CCW outside: plunge at corner, trace perimeter offset outward
G0 X[#<minx>-#<tr>] Y[#<miny>-#<tr>]
G0 Z#5
G1 Z#6

View File

@@ -1,26 +1,196 @@
# Modes
Default mode (0) is:
- Climb milling
- One-way milling
- Helix entry
- Inside
# Macros & Subroutines
+1: Conventional milling
+2: Both-ways milling
+4: Plunge entry
+8: Outside
Custom M-codes and G-code subroutines for the Lagun mill LinuxCNC configuration.
# Fun stuff
## Mode Flags (Bitmask)
Specifying a negative finish cut should cause macros to do all the roughing and leave the (positive) amount of material behind for a separate finishing op.
Several macros (`pocket_circ`, `pocket_rect`, `frame_rect`, `frame_circ`, `slot`) accept a `mode` parameter as a bitmask:
| Bit | Value | Set (1) | Clear (0) |
|-----|-------|---------|-----------|
| 0 | +1 | Conventional milling | Climb milling |
| 1 | +2 | Both-ways milling | One-way milling |
| 2 | +4 | Plunge entry | Helix entry |
| 3 | +8 | Outside | Inside |
Default mode (0) = climb, one-way, helix entry, inside.
## Global Named Parameters
These optional globals configure macro behavior when set before calling:
| Parameter | Description | Default |
|-----------|-------------|---------|
| `#<_td>` | Tool diameter (from tool table) | **Required** - used by all material-removal macros |
| `#<_z_clearance>` | Safe Z retract height | Falls back to ztop param |
| `#<_rampang>` | Ramp/helix entry angle in degrees | 5.0 |
| `#<_stepover>` | Stepover distance for spiral pocketing | 40% of tool diameter |
A negative `fincut` value causes macros to rough only, leaving material for a separate finishing pass.
## M-Codes (Shell Scripts)
### M101 - Enable Z-Axis
Sets HAL signal `z-override` to True, enabling CNC control of Z.
### M102 - Disable Z-Axis
Sets HAL signal `z-override` to False, allowing manual quill control.
## Drilling Subroutines
### drill.ngc - Peck Drill
Fully automatic drilling with optional peck cycle.
# Typical Header
```
#<_z_clearance> = 0.0 ; clearance height
#<_rampang> = 5.0 ; ramp angle in degrees for helical entry
o<drill> call [x][y] [ztop][zbot] [peck]
```
G10 L1 P1 Z0.0 R0.25 ; set tool P1 to Z-offset Z0.0 and radius R0.25
T1 ; set tool to T1
| # | Name | Description |
|---|------|-------------|
| #1 | X | Hole X position |
| #2 | Y | Hole Y position |
| #3 | Z Start | Top of material / start Z |
| #4 | Z End | Final drill depth |
| #5 | Peck | Depth per peck (0 = no peck) |
Calls M101 to enable Z-axis. Retracts to Z Start between pecks with 0.020" rapid-approach gap.
### drill_man.ngc - Manual Drill
Positions XY then pauses for operator to manually plunge.
```
o<drill_man> call [x][y]
```
Calls M102 to disable Z-axis, then M0 pause.
### drill_retr.ngc - Semi-Manual Drill with Retract
Positions XY, retracts Z to clearance, disables Z for manual plunge, then re-enables and retracts on resume.
```
o<drill_retr> call [x][y] [z_clearance]
```
## Material Removal Subroutines
### pocket_circ.ngc - Circular Pocket
Cuts a circular pocket using an outward spiral from center.
```
o<pocket_circ> call [x][y] [diameter] [ztop][zbot] [fincut] [mode]
```
| # | Name | Description |
|---|------|-------------|
| #1 | X | Center X |
| #2 | Y | Center Y |
| #3 | Diameter | Pocket diameter |
| #4 | Z Top | Start Z |
| #5 | Z Bottom | Final depth |
| #6 | Finish Cut | Finish allowance (negative = rough only) |
| #7 | Mode | Bitmask (see above) |
Supports helix or plunge entry. Spirals outward with stepover, then does a pre-finish circle and optional finish circle at full diameter.
### pocket_rect.ngc - Rectangular Pocket
Cuts a rectangular pocket. Uses helical or straight plunge, then an outward spiral that transitions to linear passes when the spiral hits the rectangle boundary.
```
o<pocket_rect> call [x1][y1] [x2][y2] [zstart][zend] [fincut] [mode]
```
| # | Name | Description |
|---|------|-------------|
| #1,#2 | X1, Y1 | First corner |
| #3,#4 | X2, Y2 | Opposite corner |
| #5 | Z Start | Start Z |
| #6 | Z End | Final depth |
| #7 | Finish Cut | Finish allowance |
| #8 | Mode | 0=CCW/helix, 1=CW/helix, 2=CCW/plunge, 3=CW/plunge |
Contains internal sub `o<xp>` for filling corners after the spiral exceeds the rectangle bounds.
### frame_rect.ngc - Rectangular Frame
Cuts along the perimeter of a rectangle (inside or outside).
```
o<frame_rect> call [x1][y1] [x2][y2] [ztop][zbot] [mode] [radius]
```
| # | Name | Description |
|---|------|-------------|
| #1,#2 | X1, Y1 | First corner |
| #3,#4 | X2, Y2 | Opposite corner |
| #5 | Z Top | Start Z |
| #6 | Z Bottom | Final depth |
| #7 | Mode | Bitmask |
| #8 | Radius | Corner radius (0 = sharp corners) |
Supports all four combinations of inside/outside and climb/conventional. Plunges at center (inside) or corner (outside), then traces the rectangle with optional corner radii.
### frame_circ.ngc - Circular Frame
Cuts along the perimeter of a circle (inside or outside).
```
o<frame_circ> call [x][y] [diameter] [ztop][zbot] [fincut] [mode]
```
| # | Name | Description |
|---|------|-------------|
| #1 | X | Center X |
| #2 | Y | Center Y |
| #3 | Diameter | Circle diameter |
| #4 | Z Top | Start Z |
| #5 | Z Bottom | Final depth |
| #6 | Finish Cut | Finish allowance |
| #7 | Mode | Bitmask |
Uses a small arc entry/exit move (capped at 15% of diameter) for smooth engagement.
### slot.ngc - Slot
Cuts a slot (obround/stadium shape) between two points.
```
o<slot> call [x1][y1] [x2][y2] [width] [ztop][zbot] [fincut] [mode]
```
| # | Name | Description |
|---|------|-------------|
| #1,#2 | X1, Y1 | Slot start center |
| #3,#4 | X2, Y2 | Slot end center |
| #5 | Width | Slot width |
| #6 | Z Top | Start Z |
| #7 | Z Bottom | Final depth |
| #8 | Finish Cut | Finish allowance |
| #9 | Mode | Bitmask |
Plunges at start, cuts to end, then traces the obround profile. Supports optional pre-finish pass when fincut > 0.
### bore.ngc - Helical Bore
Helical-interpolation boring subroutine.
```
o<bore> call [x][y] [d] [zstart][zend] [stepdown]
```
| # | Name | Description |
|---|------|-------------|
| #1 | X | Center X |
| #2 | Y | Center Y |
| #3 | D | Bore diameter |
| #4 | Z Start | Start Z |
| #5 | Z End | Final depth |
| #6 | Stepdown | Depth per helical pass |
Spirals down in full-circle passes, then does a partial-arc cleanup and spring pass at final depth. Returns to center and Z0.
## Typical Program Header
```
#<_z_clearance> = 0.0
#<_rampang> = 5.0
G10 L1 P1 Z0.0 R0.25 ; set tool P1 offset and radius
T1 ; select tool
M06 ; manual toolchange
M101 ; enable z-axis
@@ -30,26 +200,28 @@ G54 ; fixture #1
F5.0 ; feedrate
```
## Known Bugs
# Material removal
1. **drill_retr.ngc: Sub name mismatch.** Opened as `o<drill_retr>` (line 1) but closed as `o<drill_man_retract>` (line 23). This will cause a runtime error - LinuxCNC requires matching sub/endsub names.
o<pocket_rect> call
o<pocket_circ> call
2. **bore.ngc: Parameter comment is wrong.** The inline comment says `; x, y, d, stepdown, zstart, zend` but the actual parameter order used by the code is `x, y, d, zstart, zend, stepdown`. Anyone calling based on the comment would get wrong results.
o<frame_rect> call
o<frame_circ> call
3. **bore.ngc: Undocumented `#<_td>` dependency.** Uses global `#<_td>` for tool-diameter compensation but never validates it. If unset (defaults to 0), the bore toolpath radius becomes `D/2` instead of `(D - tool_dia)/2`, cutting an oversized bore.
o<slot> call [x1][y1] [x2][y2] [width] [ztop][zbot] [finishcut]
o<bore> call [x][y] [stepdown] [ztop][zbot]
4. **drill.ngc: First peck cycle is a no-op.** The loop initializes `#<h> = #3` (Z Start) then immediately does `G1 Z#<h>` - moving to where the tool already is. First real cut happens on the second iteration. Wastes one retract cycle.
# Drilling
5. **pocket_circ.ngc: Suspicious angle calculation.** Line 66 has a `TODO` comment from the author: `; TODO: what the heck is the denominator here doing?` The finish-plunge angle divides by `[#4-#5]` (ztop - zbot). If ztop is 0 this produces a division by a potentially small number, which may cause unexpected arc endpoints.
o<drill> call [x][y] [ztop][zbot] [(peck)]; fully automoatic drilling op; drills at x,y from ztop to zbot in optional increments of peck (full retraction)
6. **pocket_rect.ngc: Incomplete rectangular clearing.** The spiral-to-rectangle transition has commented-out code (lines 141-151) and a note saying "subroutines might be the best way to do this". The `o<xp>` helper sub attempts to fill the remaining area but uses a different algorithm. Corners may not be fully cleared depending on geometry.
o<drill_man> call [x][y] ; fully manual drilling op; z axis entirely disabled
o<drill_retr> call [x][y] ; semi-manual drilling op; z axis retracts, but disabled on downstroke
7. **slot.ngc: Test code after endsub.** Lines 79-83 contain hardcoded test calls that execute whenever the file is loaded. These should be removed or moved to a separate test file. The test calls also only provide 7 of 9 parameters (fincut and mode default to 0).
# Footer
```
M2 ; end program
```
8. **frame_circ.ngc: lead-in arcs can be larger than actual pocket size.** this causes overcutting. not good.
9. **some combination of values will cause hangs.** This is in several macros. linuxcnc does not have stall/timeout detection; if a macro gets stuck in an infinite loop, it hangs linuxcnc.
## Other Todos
1. Change macros to use UPPERCASE_WITH_UNDERSCORES naming (both the filenames, and the usage of them in all .ngc files)
2. Purge all .cnc programs
3. Maybe: Use tool diameter instead of the td global. (we will use tool change stuff)

View File

@@ -1,3 +1,6 @@
; Circular pocket - clears a round pocket using spiral toolpath
; Params: #1=x, #2=y, #3=diameter, #4=ztop, #5=zbot, #6=finishcut, #7=mode
; Mode bitmask: bit0=conventional, bit1=bothways, bit2=plunge(vs helix), bit3=outside
o<pocket_circ> sub
; o<pocket_circ> call [x][y] [diameter] [ztop][zbot] [finishcut] [mode]
@@ -33,15 +36,15 @@ o<pocket_circ> sub
#<stepover> = [#<td>*0.4]
o3 endif
o4 if [#<td> GT #3]
o4 if [#<td> GT #3] ; tool bigger than pocket, bail out
o5 return
o4 endif
#<a> = 0
#<r> = 0
o100 if [#<M_HELIX>] ; helical plunge
#<r> = [#<td>*0.3]
o115 if [[[#3-#<td>]/2-ABS[#6]] LE #<r>]
#<r> = [#<td>*0.3] ; helix radius = 30% of tool diameter
o115 if [[[#3-#<td>]/2-ABS[#6]] LE #<r>] ; shrink if helix would exceed pocket wall
#<r> = [[[#3-#<td>]/2-ABS[#6]]*0.8]
o115 endif
@@ -82,7 +85,7 @@ o<pocket_circ> sub
o100 endif
; do the spiral :)
; spiral outward from center to clear pocket, stopping short by finishcut amount
#<r_base> = #<r>
#<a_base> = #<a>
o105 while [#<r> LT [[#3-#<td>]/2-ABS[#6]]]
@@ -92,12 +95,12 @@ o<pocket_circ> sub
o106 else
G1 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>]
o106 endif
#<a> = [#<a>+1] ; next angle
#<a> = [#<a>+1] ; advance 1 degree per step
#<r> = [#<r_base>+[#<a>-#<a_base>]/360*#<stepover>] ; compute the radius accordingly
#<r> = [#<r_base>+[#<a>-#<a_base>]/360*#<stepover>] ; radius grows by stepover each revolution
o105 endwhile
; pre-finish cut
; pre-finish cut: full circle at pocket wall minus finishcut allowance
#<r> = [[#3-#<td>]/2-ABS[#6]]
o107 if [#<M_CLIMB>]
G1 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>]
@@ -107,18 +110,18 @@ o<pocket_circ> sub
G2 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>] I[#1] J[#2]
o107 endif
; finish cut
; finish cut: full circle at final pocket wall radius
o104 if [ABS[#6] GT 0.0]
#<r> = [[#3-#<td>]/2]
o108 if [#<M_CLIMB>]
G1 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>]
G3 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>] I[#1] J[#2]
#<r> = [[#3-#<td>]/2*0.9]
#<r> = [[#3-#<td>]/2*0.9] ; retract slightly inward before rapid out
G1 X[#1+COS[#<a>]*#<r>] Y[#2+SIN[#<a>]*#<r>]
o108 else
G1 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>]
G2 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>] I[#1] J[#2]
#<r> = [[#3-#<td>]/2*0.9]
#<r> = [[#3-#<td>]/2*0.9] ; retract slightly inward before rapid out
G1 X[#1+COS[#<a>]*#<r>] Y[#2-SIN[#<a>]*#<r>]
o108 endif
o104 endif

View File

@@ -1,9 +1,14 @@
; Rectangular pocket - clears using spiral then corner-clearing helper sub
; Params: #1=x1, #2=y1, #3=x2, #4=y2, #5=zstart, #6=zend, #7=fincut, #8=mode
; Mode: 0=CCW/ramp, 1=CW/ramp, 2=CCW/plunge, 3=CW/plunge
; pre-declare named params used across sub/helper scope
#<a> = 0
#<z> = 0
#<td> = 0
#<z_clearance> = 0
#<rampang> = 0
#<z_down> = 0
#<z_down> = 0
#<z_lift> = 0
#<minx> = 0
#<maxx> = 0
@@ -44,7 +49,7 @@ o<pocket_rect> sub
o3 endif
#<z_down> = #6
#<z_lift> = [#6+#<td>*0.1]
#<z_lift> = [#6+#<td>*0.1] ; slight lift for repositioning moves
#<minx> = #1
#<maxx> = #3
@@ -60,10 +65,10 @@ o<pocket_rect> sub
#<maxy> = #2
o12 endif
#<cx> = [[#<minx>+#<maxx>]/2]
#<cy> = [[#<miny>+#<maxy>]/2]
#<rx> = [[[#<maxx>-#<minx>]-#<td>]/2]
#<ry> = [[[#<maxy>-#<miny>]-#<td>]/2]
#<cx> = [[#<minx>+#<maxx>]/2] ; pocket center X
#<cy> = [[#<miny>+#<maxy>]/2] ; pocket center Y
#<rx> = [[[#<maxx>-#<minx>]-#<td>]/2] ; half-width minus tool radius
#<ry> = [[[#<maxy>-#<miny>]-#<td>]/2] ; half-height minus tool radius
G0 X#<cx> Y#<cy>
G1 X[#<cx>+#<rx>] Y[#<cy>-#<ry>]
@@ -109,7 +114,7 @@ o<pocket_rect> sub
o100 endif
; do the spiral :)
; spiral outward from center until hitting pocket boundary
#<r_base> = #<r>
#<a_base> = #<a>
o105 while [1]
@@ -152,7 +157,7 @@ o<pocket_rect> sub
o<xp> call
o<xp> call ; clear corners that the spiral couldn't reach
@@ -165,6 +170,8 @@ o<pocket_rect> endsub
; idea: bias the main spiral. then you're left with a section to hog out
; idea 2: make angle arbitrary (blowing up the code so it's not x-y specific). That'll be fun.
; Helper sub: clears rectangular corner material left by circular spiral
; Walks along the X-axis edge, tracing arcs that match the spiral boundary
o<xp> sub
#<ix> = 0
#<lastxx> = 0
@@ -174,7 +181,7 @@ o<xp> sub
G0 X#<cx> Y[#<cy> - #<ry>]
G1 Z#<z_down>
#<n_end> = FUP[sqrt[[#<ix>]**2 + [#<ry>]**2]/#<stepover>]
#<n_end> = FUP[sqrt[[#<ix>]**2 + [#<ry>]**2]/#<stepover>] ; spiral revolution number at this corner point
#<a> = ATAN[-#<ry>]/[#<ix>]
#<r_end> = [#<n_end>*#<stepover> + #<r_base>+[#<a>-#<a_base>]/360*#<stepover>]
#<r> = [#<ry>]

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,6 @@
; Slot/obround cut - cuts a slot (stadium shape) between two endpoints
; Params: #1=x1, #2=y1, #3=x2, #4=y2, #5=width, #6=ztop, #7=zbot, #8=fincut, #9=mode
; Mode bitmask: bit0=conventional, bit1=bothways, bit2=plunge(vs helix), bit3=outside
o<slot> sub
; o<slot> call [x1][y1] [x2][y2] [width] [ztop][zbot] [fincut] [mode]
@@ -24,20 +27,21 @@ o<slot> sub
#<z_clearance> = #5
o1 endif
#<a> = [ATAN[#4-#2]/[#3-#1]]
#<a> = [ATAN[#4-#2]/[#3-#1]] ; slot angle from p1 to p2
G0 Z#<z_clearance>
G0 X#1 Y#2
G0 Z#6
G1 Z#7
G1 X#3 Y#4
G1 Z#7 ; plunge to cut depth
G1 X#3 Y#4 ; cut centerline of slot
#<r> = [[#5-#<_td>]/2]
#<r> = [[#5-#<_td>]/2] ; offset from centerline to slot edge (compensated for tool)
; Trace obround perimeter: two straights + two semicircles at each end
o100 if [#<M_CLIMB>]
o101 if [#8 GT 0]
o101 if [#8 GT 0] ; pre-finish pass offset inward by fincut
G1 X[#3 +[SIN[#<a>]*[#<r>-#8]]] Y[#4 -[COS[#<a>]*[#<r>-#8]]] ; point 1
G3 X[#3 -[SIN[#<a>]*[#<r>-#8]]] Y[#4 +[COS[#<a>]*[#<r>-#8]]] I#3 J#4 ; point 2
G1 X[#1 -[SIN[#<a>]*[#<r>-#8]]] Y[#2 +[COS[#<a>]*[#<r>-#8]]] ; point 3