Repository navigation
Expand file tree
/
Copy pathconfig.html
More file actions
1497 lines (1408 loc) · 476 KB
/
Copy pathconfig.html
File metadata and controls
1497 lines (1408 loc) · 476 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!-- G-code & grblHAL Reference - configuration + reference browser.
ncSender shows this file in two places:
1. Settings > Plugins > configure (inside an iframe; the
__TOOL_MENU_LABEL__ token below is NOT replaced there)
2. Tools menu > "G-code Explorer" (or "G-code Navigator") (as a dialog; the server
replaces the token)
The full UI - Reference, G-code, Explorer, NC Manual and Settings tabs
(terminal-lookup options + About/sources) - lives in the shared
core below; this wrapper only picks the default tab per context. -->
<!-- G-code Reference UI core. {"gcodes":[{"code":"G0","aliases":["G00"],"name":"Rapid Positioning","category":"motion","modal":"Motion Mode","desc":"Moves at the machine's maximum travel rate to the target position. Non-cutting move used to reposition quickly between operations. The F word is ignored; speed comes from $110-$115 max rates.","syntax":"G0 <axes>","params":{"X":"Target X coordinate","Y":"Target Y coordinate","Z":"Target Z coordinate","A":"Target A (rotary) coordinate","B":"Target B coordinate","C":"Target C coordinate"},"example":"G90 G0 X100 Y50","tips":"Retract Z to a safe height before rapid XY moves. Modal: stays active until another motion command (G1/G2/G3...) is issued.","keywords":["rapid","move","travel","position","fast","jog"]},{"code":"G1","aliases":["G01"],"name":"Linear Interpolation (Feed Move)","category":"motion","modal":"Motion Mode","desc":"Straight-line move at the programmed feed rate. The primary command for cutting and engraving. All specified axes move in a coordinated straight line.","syntax":"G1 <axes> F<feed>","params":{"X":"Target X coordinate","Y":"Target Y coordinate","Z":"Target Z coordinate","A":"Target A coordinate","B":"Target B coordinate","C":"Target C coordinate","F":"Feed rate (units/min in G94)"},"example":"G1 X200 F500","tips":"F is modal — once set it applies to all following feed moves. A feed rate must be active or the move errors out.","keywords":["linear","cut","feed","straight","line","mill","engrave"]},{"code":"G2","aliases":["G02"],"name":"Arc — Clockwise","category":"motion","modal":"Motion Mode","desc":"Clockwise circular arc at the current feed rate on the active plane (G17/G18/G19). Adding the off-plane axis produces helical motion. Defined by center offsets (I/J/K) or radius (R).","syntax":"G2 X- Y- (I- J- | R-) F-","params":{"X":"Arc end X","Y":"Arc end Y","Z":"Arc end Z (helical if off-plane)","I":"X offset from start point to arc center","J":"Y offset from start point to arc center","K":"Z offset from start point to arc center","R":"Arc radius (alternative to IJK)","P":"Number of full circles","F":"Feed rate"},"example":"G17 G2 X10 Y10 I10 J0 F200","tips":"IJK center-offset form is preferred — it is unambiguous. In R form, positive R gives the shorter (<180°) arc, negative R the longer one.","keywords":["arc","circle","clockwise","cw","helix","helical","radius","curve"]},{"code":"G3","aliases":["G03"],"name":"Arc — Counter-Clockwise","category":"motion","modal":"Motion Mode","desc":"Counter-clockwise circular arc at the current feed rate on the active plane. Otherwise identical to G2, including IJK/R forms and helical motion.","syntax":"G3 X- Y- (I- J- | R-) F-","params":{"X":"Arc end X","Y":"Arc end Y","Z":"Arc end Z (helical if off-plane)","I":"X offset to arc center","J":"Y offset to arc center","K":"Z offset to arc center","R":"Arc radius (alternative to IJK)","P":"Number of full circles","F":"Feed rate"},"example":"G3 X20 Y0 R10 F200","tips":"Direction is judged looking at the active plane from the positive side of its normal axis (for G17, looking down at XY).","keywords":["arc","circle","counterclockwise","ccw","helix","curve"]},{"code":"G4","aliases":["G04"],"name":"Dwell (Pause)","category":"motion","modal":null,"desc":"Pauses motion for a set time. Spindle, coolant and other outputs keep their current state. Useful for letting a spindle spin up or clearing chips at hole bottom.","syntax":"G4 P<seconds>","params":{"P":"Dwell time in seconds (decimals allowed)"},"example":"M3 S18000\nG4 P2 ; wait 2s for spindle spin-up","tips":"Non-modal — only affects its own block. Any queued motion completes before the pause begins.","keywords":["dwell","pause","wait","delay","sleep","timer"]},{"code":"G5","aliases":["G5.1"],"name":"Spline Interpolation","category":"motion","modal":"Motion Mode","desc":"Moves along a quadratic (G5) or cubic (G5.1) spline defined by control points, producing smoother free-form curves than arcs. Nearly always generated by CAM rather than written by hand.","syntax":"G5 X- Y- I- J- P- | G5.1 X- Y- I- J- K- L-","params":{"X":"Spline end X","Y":"Spline end Y","Z":"Spline end Z","I":"Control point offset","J":"Control point offset","K":"Control point (cubic)","L":"Control point (cubic)","P":"Second control point (G5)","F":"Feed rate"},"example":"G5 X20 Y10 I10 J15 F100","tips":"Elliptical arcs cannot be produced by combining splines with G51 scaling.","keywords":["spline","curve","bezier","smooth","nurbs"]},{"code":"G7","aliases":[],"name":"Lathe Diameter Mode","category":"modes","modal":"Lathe Mode","desc":"Lathe only ($32=2): X-axis values are interpreted as workpiece diameters. G1 X50 moves the tool to produce a 50-unit diameter.","syntax":"G7","params":{},"example":"G7\nG0 X20 Z0","tips":"Most lathe CAM outputs diameter mode. Machine coordinates always display as radius.","keywords":["lathe","diameter","turning"]},{"code":"G8","aliases":[],"name":"Lathe Radius Mode","category":"modes","modal":"Lathe Mode","desc":"Lathe only ($32=2): X-axis values are interpreted as radii. G1 X25 produces a 50-unit diameter.","syntax":"G8","params":{},"example":"G8\nG0 X25 Z0","tips":"Set G7 or G8 explicitly at the top of every lathe program.","keywords":["lathe","radius","turning"]},{"code":"G10 L2","aliases":["G10"],"name":"Set WCS Origin (Absolute)","category":"coords","modal":null,"desc":"Programmatically sets a work coordinate system origin relative to the machine origin. P selects the WCS (P1=G54 ... P9=G59.3). Values persist across resets.","syntax":"G10 L2 P<1-9> <axes>","params":{"L":"Data mode: 2 = absolute from machine zero","P":"WCS number: 1=G54, 2=G55 ... 9=G59.3","X":"New origin X (machine coords)","Y":"New origin Y","Z":"New origin Z"},"example":"G10 L2 P2 X100 Y250.5 Z-20 ; set G55 origin","tips":"Omitted axes are left unchanged. Great for repeatable multi-fixture setups.","keywords":["work offset","wcs","zero","origin","coordinate","fixture","g54","set zero"]},{"code":"G10 L20","aliases":[],"name":"Set WCS Origin (From Current Position)","category":"coords","modal":null,"desc":"Sets a work coordinate system origin so the machine's current position becomes the given coordinate. \"Make here X0 Y0\" — this is what most senders send when you click Zero.","syntax":"G10 L20 P<1-9> <axes>","params":{"L":"Data mode: 20 = relative to current position","P":"WCS number: 1=G54 ... 9=G59.3","X":"Value current X should read","Y":"Value current Y should read","Z":"Value current Z should read"},"example":"G10 L20 P1 X0 Y0 ; current spot becomes G54 X0 Y0","tips":"Preferred over G92 for zeroing — the offset is stored in the WCS and survives resets.","keywords":["zero","touch off","work offset","wcs","origin","set zero","xyz zero"]},{"code":"G17","aliases":[],"name":"XY Plane Select","category":"modes","modal":"Plane Select","desc":"Selects the XY plane for arcs, cutter compensation and canned cycles. Default on startup. Arcs use I (X offset) and J (Y offset).","syntax":"G17","params":{},"example":"G17\nG2 X10 Y15 I5 J0 F300","tips":"Set the plane explicitly at program start; arcs on the wrong plane move in surprising directions.","keywords":["plane","xy","arc plane"]},{"code":"G18","aliases":[],"name":"XZ Plane Select","category":"modes","modal":"Plane Select","desc":"Selects the XZ plane (lathes, side profiling). Arcs use I (X offset) and K (Z offset).","syntax":"G18","params":{},"example":"G18\nG3 X20 Z-5 I10 K0 F250","tips":null,"keywords":["plane","xz","lathe plane"]},{"code":"G19","aliases":[],"name":"YZ Plane Select","category":"modes","modal":"Plane Select","desc":"Selects the YZ plane. Arcs use J (Y offset) and K (Z offset).","syntax":"G19","params":{},"example":"G19\nG2 Y10 Z-2 J5 K0 F250","tips":null,"keywords":["plane","yz"]},{"code":"G20","aliases":[],"name":"Inch Units","category":"modes","modal":"Units","desc":"All coordinates, offsets and feed rates are interpreted as inches (feeds in inches/min).","syntax":"G20","params":{},"example":"G20\nG1 X4 F20","tips":"Put G20 or G21 at the top of every file — a 10 mm move read as 10 inches is a crash. Display units are separate ($13).","keywords":["inch","inches","imperial","units"]},{"code":"G21","aliases":[],"name":"Millimeter Units","category":"modes","modal":"Units","desc":"All coordinates, offsets and feed rates are interpreted as millimeters (feeds in mm/min).","syntax":"G21","params":{},"example":"G21\nG1 X100 F500","tips":"Interpreter units only — does not change steps/mm calibration ($100-$102) or the report units ($13).","keywords":["mm","millimeter","metric","units"]},{"code":"G28","aliases":[],"name":"Go to Stored Position 1","category":"coords","modal":null,"desc":"Rapid move to the position stored by G28.1 (in machine coordinates). With axis words, first moves through that intermediate point, then to the stored position.","syntax":"G28 [<axes>]","params":{"X":"Intermediate X before final move","Y":"Intermediate Y","Z":"Intermediate Z"},"example":"G53 G0 Z0\nG28 ; retract, then go to park position","tips":"DANGER: only use on a homed machine — the stored position is in machine coordinates. G28 Z0 lifts Z (in the current WCS) before traveling.","keywords":["park","home position","stored position","safe position","predefined"]},{"code":"G28.1","aliases":[],"name":"Store Position 1","category":"coords","modal":null,"desc":"Saves the machine's current absolute position as the G28 target. Persists across resets and power cycles.","syntax":"G28.1","params":{},"example":"G53 G0 X-50 Y-50 Z-5\nG28.1","tips":"Move with G53 first so the stored spot is independent of work offsets. Takes no axis words.","keywords":["store","save position","park","set park"]},{"code":"G30","aliases":[],"name":"Go to Stored Position 2","category":"coords","modal":null,"desc":"Same as G28 but uses the second stored position (set by G30.1). Commonly used for a tool-change or probing location.","syntax":"G30 [<axes>]","params":{"X":"Intermediate X","Y":"Intermediate Y","Z":"Intermediate Z"},"example":"G30","tips":"Only use on a homed machine.","keywords":["park","second position","tool change position","stored position"]},{"code":"G30.1","aliases":[],"name":"Store Position 2","category":"coords","modal":null,"desc":"Saves the current absolute machine position as the G30 target.","syntax":"G30.1","params":{},"example":"G53 G0 X-200 Y-400 Z-10\nG30.1","tips":null,"keywords":["store","save position","set park"]},{"code":"G53","aliases":[],"name":"Move in Machine Coordinates","category":"coords","modal":null,"desc":"For one block only, moves in the absolute machine coordinate system, ignoring all work offsets, G92 and tool offsets. Must be combined with G0 or G1.","syntax":"G53 G0 <axes> | G53 G1 <axes> F-","params":{"X":"Machine X target","Y":"Machine Y target","Z":"Machine Z target","F":"Feed rate (with G1)"},"example":"G53 G0 Z0 ; retract Z fully, regardless of offsets","tips":"G53 G0 Z0 is one of the safest moves in G-code — but only on a homed machine. Reverts to the active WCS on the next line.","keywords":["machine coordinates","absolute","retract","safe move","ignore offsets"]},{"code":"G54","aliases":["G55","G56","G57","G58","G59","G59.1","G59.2","G59.3"],"name":"Work Coordinate Systems","category":"coords","modal":"WCS","desc":"Selects one of nine work coordinate systems (G54-G59.3), each with its own user-set origin. Separates the program zero from machine home. G54 is the default.","syntax":"G54 | G55 | ... | G59.3","params":{},"example":"G54\n(run part 1)\nG55\n(run same file on fixture 2)","tips":"Origins are set with G10 L2/L20 or the Zero buttons and are stored persistently. G59.3 doubles as the tool change position in tool change modes 2 & 3.","keywords":["wcs","work coordinate","offset","g55","g56","g57","g58","g59","fixture","datum"]},{"code":"G92","aliases":[],"name":"Temporary Coordinate Offset","category":"coords","modal":"G92 Offset","desc":"Applies a volatile offset so the current position reads as the given values (\"you are now X0 Y0\"). Applied on top of the active WCS. Cleared by G92.1.","syntax":"G92 <axes>","params":{"X":"Value current X should read","Y":"Value current Y should read","Z":"Value current Z should read","A":"Value current A should read"},"example":"G92 X0 Y0 Z0","tips":"Easy to forget and a common crash cause — prefer G10 L20 with a spare WCS. $384 controls whether the offset persists across resets.","keywords":["offset","temporary zero","shift","coordinate offset"]},{"code":"G92.1","aliases":["G92.2","G92.3"],"name":"Clear / Suspend / Restore G92","category":"coords","modal":"G92 Offset","desc":"G92.1 clears the G92 offset (and zeroes the stored values). G92.2 suspends it without erasing. G92.3 re-applies a suspended offset.","syntax":"G92.1 | G92.2 | G92.3","params":{},"example":"G92.1 ; back to the plain G54 system","tips":null,"keywords":["clear offset","cancel g92","reset offset"]},{"code":"G38.2","aliases":[],"name":"Probe Toward (Error on Miss)","category":"probing","modal":null,"desc":"Moves toward the target until the probe input triggers, then stops and records the trigger position. Raises an error if the target is reached without contact.","syntax":"G38.2 <axes> F<feed>","params":{"X":"Probe travel limit X","Y":"Probe travel limit Y","Z":"Probe travel limit Z","F":"Probing feed rate"},"example":"G91 G38.2 Z-20 F100 ; probe down max 20mm","tips":"Probe fast to find the surface, back off, then re-probe slowly for accuracy. The trigger position is reported and stored in probe parameters (see $# output, PRB).","keywords":["probe","touch","toolsetter","surface","zero probe","touch plate","probing"]},{"code":"G38.3","aliases":[],"name":"Probe Toward (No Error on Miss)","category":"probing","modal":null,"desc":"Like G38.2, but completing the move without contact is not an error. Useful for checking whether something is present.","syntax":"G38.3 <axes> F<feed>","params":{"X":"Probe travel limit X","Y":"Probe travel limit Y","Z":"Probe travel limit Z","F":"Probing feed rate"},"example":"G38.3 Z-10 F150","tips":"Check the probe result flag in the report to see whether contact happened.","keywords":["probe","optional","check","detect","probing"]},{"code":"G38.4","aliases":[],"name":"Probe Away (Error on Fail)","category":"probing","modal":null,"desc":"Moves away until the probe input releases (loses contact). Errors if the probe starts un-triggered or never releases within the move.","syntax":"G38.4 <axes> F<feed>","params":{"X":"Travel limit X","Y":"Travel limit Y","Z":"Travel limit Z","F":"Probing feed rate"},"example":"G91 G38.4 Z5 F100","tips":null,"keywords":["probe away","release","retract probe","probing"]},{"code":"G38.5","aliases":[],"name":"Probe Away (No Error on Fail)","category":"probing","modal":null,"desc":"Like G38.4 but does not error if the probe never releases within the move.","syntax":"G38.5 <axes> F<feed>","params":{"X":"Travel limit X","Y":"Travel limit Y","Z":"Travel limit Z","F":"Probing feed rate"},"example":"G38.5 G91 Z50 F200","tips":null,"keywords":["probe away","optional","probing"]},{"code":"G40","aliases":[],"name":"Cancel Cutter Compensation","category":"tool","modal":"Cutter Comp","desc":"Disables cutter radius compensation. This is the default state; full G41/G42 compensation is not in the grblHAL core (plugin territory), so G40 mainly guarantees a known state.","syntax":"G40","params":{},"example":"G40","tips":"Include in your safety preamble: G90 G21 G17 G40 G49 G80 G94.","keywords":["cutter compensation","comp","cancel","g41","g42"]},{"code":"G43.1","aliases":[],"name":"Dynamic Tool Length Offset","category":"tool","modal":"Tool Length Offset","desc":"Applies a tool length offset given directly in the command (usually Z). Typically issued after probing a new tool to shift the Z origin by the measured length difference.","syntax":"G43.1 Z<offset>","params":{"Z":"Offset to apply to Z","A":"Offset for A","B":"Offset for B"},"example":"G43.1 Z5.2 ; tool is 5.2mm longer than reference","tips":"Cancel with G49 before tool changes and at program end.","keywords":["tool length","tlo","offset","tool offset","length compensation"]},{"code":"G43","aliases":["G43.2"],"name":"Tool Length Offset from Tool Table","category":"tool","modal":"Tool Length Offset","desc":"With a tool table enabled, G43 H<n> applies the stored Z-length offset for tool n. G43.2 adds a second, stacked offset.","syntax":"G43 H<tool> | G43.2 <axes>","params":{"H":"Tool table entry whose offset to apply","Z":"Additional offset (G43.2)"},"example":"T1 M6\nG43 H1","tips":"H should normally match the active tool number.","keywords":["tool table","tool length","h word","offset"]},{"code":"G49","aliases":[],"name":"Cancel Tool Length Offset","category":"tool","modal":"Tool Length Offset","desc":"Removes any active tool length offset.","syntax":"G49","params":{},"example":"G49\nM6 T2","tips":"Issue before M6 and at program end.","keywords":["cancel","tool length","clear offset"]},{"code":"G50","aliases":[],"name":"Cancel Scaling","category":"modes","modal":"Scaling","desc":"Disables G51 coordinate scaling, restoring 1:1 motion. Default state.","syntax":"G50","params":{},"example":"G50","tips":"On lathes in G96 mode, G50 S<rpm> also sets the max spindle RPM cap (Mach3 style).","keywords":["scaling","cancel scale","unscale"]},{"code":"G51","aliases":[],"name":"Coordinate Scaling / Mirroring","category":"modes","modal":"Scaling","desc":"Scales subsequent motion per-axis. A factor of -1 mirrors that axis. Lets you resize or flip a program without editing it.","syntax":"G51 X<f> Y<f> Z<f>","params":{"X":"X scale factor (-1 mirrors)","Y":"Y scale factor","Z":"Z scale factor"},"example":"G51 X0.5 Y0.5 Z0.5\n(half-size part)\nG50","tips":"Unequal XY factors are not allowed with G2/G3 (no elliptical arcs). Always cancel with G50.","keywords":["scale","mirror","flip","resize"]},{"code":"G81","aliases":[],"name":"Drilling Cycle","category":"cycles","modal":"Motion Mode","desc":"Simple drill cycle: rapid to R plane, feed to Z depth, rapid retract. Once active, every new XY position drills a hole until G80 cancels.","syntax":"G81 Z<depth> R<retract> F<feed>","params":{"Z":"Final hole depth","R":"Retract plane (Z height to rapid to before feeding)","F":"Drilling feed rate","L":"Optional repeat count"},"example":"G99 G81 Z-10 R2 F150\nX10 Y10\nX20\nG80","tips":"Retract height between holes is controlled by G98 (initial Z) / G99 (R plane).","keywords":["drill","hole","canned cycle","drilling"]},{"code":"G82","aliases":[],"name":"Drilling Cycle with Dwell","category":"cycles","modal":"Motion Mode","desc":"Like G81 but dwells at the bottom of the hole for P seconds — improves hole-bottom finish (spot drilling, countersinking).","syntax":"G82 Z- R- P<sec> F-","params":{"Z":"Final depth","R":"Retract plane","P":"Dwell at bottom (seconds)","F":"Feed rate"},"example":"G82 Z-3 R2 P0.5 F100","tips":null,"keywords":["drill","dwell","spot","countersink","canned cycle"]},{"code":"G83","aliases":[],"name":"Peck Drilling (Full Retract)","category":"cycles","modal":"Motion Mode","desc":"Deep-hole peck drilling: after each peck of depth Q, the drill fully retracts out of the hole to clear chips, then returns.","syntax":"G83 Z- R- Q<peck> F-","params":{"Z":"Final depth","R":"Retract plane","Q":"Depth of each peck","F":"Feed rate"},"example":"G83 Z-25 R2 Q5 F120","tips":"Use for holes deeper than ~3x drill diameter.","keywords":["peck","deep hole","drill","chip clearing","canned cycle"]},{"code":"G73","aliases":[],"name":"Peck Drilling (Chip Break)","category":"cycles","modal":"Motion Mode","desc":"High-speed peck cycle: after each peck of depth Q, retracts a small fixed amount ($28) to snap the chip without leaving the hole.","syntax":"G73 Z- R- Q<peck> F-","params":{"Z":"Final depth","R":"Retract plane","Q":"Depth of each peck","F":"Feed rate"},"example":"G73 Z-15 R2 Q4 F150","tips":"Retract amount per peck comes from setting $28.","keywords":["peck","chip break","drill","canned cycle"]},{"code":"G85","aliases":[],"name":"Boring Cycle (Feed Out)","category":"cycles","modal":"Motion Mode","desc":"Feeds to depth and feeds back out — no rapid retract inside the hole, leaving a better surface finish (reaming/boring).","syntax":"G85 Z- R- F-","params":{"Z":"Final depth","R":"Retract plane","F":"Feed rate (both directions)"},"example":"G85 Z-12 R2 F80","tips":null,"keywords":["bore","ream","finish","canned cycle"]},{"code":"G86","aliases":[],"name":"Boring Cycle (Spindle Stop)","category":"cycles","modal":"Motion Mode","desc":"Feeds to depth, stops the spindle, then rapids out.","syntax":"G86 Z- R- F-","params":{"Z":"Final depth","R":"Retract plane","F":"Feed rate"},"example":"G86 Z-12 R2 F80","tips":null,"keywords":["bore","canned cycle"]},{"code":"G89","aliases":[],"name":"Boring Cycle with Dwell","category":"cycles","modal":"Motion Mode","desc":"Feeds to depth, dwells P seconds, feeds back out.","syntax":"G89 Z- R- P<sec> F-","params":{"Z":"Final depth","R":"Retract plane","P":"Dwell (seconds)","F":"Feed rate"},"example":"G89 Z-10 R2 P1 F80","tips":null,"keywords":["bore","dwell","canned cycle"]},{"code":"G76","aliases":[],"name":"Threading Cycle (Lathe)","category":"cycles","modal":"Motion Mode","desc":"Multi-pass lathe threading cycle. Requires a spindle encoder for spindle-synchronized motion; only a few grblHAL boards support the hardware.","syntax":"G76 Z- R- I- J- K- L- P- Q- F-","params":{"Z":"Thread end","P":"Thread pitch","I":"Thread peak offset","J":"Initial cut depth","K":"Full thread depth","Q":"Compound slide angle","L":"Taper mode","R":"Depth regression","F":"Feed"},"example":"(lathe threading — see grblHAL docs)","tips":"Related: G33 spindle-synchronized motion, also encoder-dependent.","keywords":["thread","threading","lathe","tap"]},{"code":"G80","aliases":[],"name":"Cancel Canned Cycle","category":"cycles","modal":"Motion Mode","desc":"Immediately ends any active canned cycle so later coordinates are not interpreted as more holes. Critical safety command after cycle blocks.","syntax":"G80","params":{},"example":"G81 Z-10 R2 F100\nX10\nX20\nG80","tips":"Any new motion command (G0/G1/G2/G3) also cancels an active cycle.","keywords":["cancel","canned cycle","end cycle"]},{"code":"G98","aliases":[],"name":"Cycle Retract to Initial Z","category":"cycles","modal":"Cycle Return","desc":"Between canned-cycle holes, retract all the way to the Z height held before the cycle started. Safest mode — clears clamps between holes.","syntax":"G98","params":{},"example":"G0 Z20\nG98 G81 Z-5 R2 F100","tips":null,"keywords":["retract","initial","canned cycle","return"]},{"code":"G99","aliases":[],"name":"Cycle Retract to R Plane","category":"cycles","modal":"Cycle Return","desc":"Between holes, retract only to the R plane. Faster on flat unobstructed surfaces.","syntax":"G99","params":{},"example":"G99 G81 Z-5 R2 F100","tips":null,"keywords":["retract","r plane","canned cycle","return"]},{"code":"G90","aliases":[],"name":"Absolute Distance Mode","category":"modes","modal":"Distance Mode","desc":"Coordinates are destinations measured from the active WCS origin. X10 means \"go to the X=10 line\". Default mode; what most CAM output uses.","syntax":"G90","params":{},"example":"G90\nG0 X10 Y20","tips":null,"keywords":["absolute","distance mode","positioning"]},{"code":"G91","aliases":[],"name":"Incremental Distance Mode","category":"modes","modal":"Distance Mode","desc":"Coordinates are distances from the current position. X10 means \"move +10 in X from here\". Ideal for macros and probing routines that must work anywhere.","syntax":"G91","params":{},"example":"G91\nG1 X50 F300\nG1 Y30","tips":"Forgetting to switch back to G90 is a classic crash. In G91, arc IJK offsets are still measured from the arc start point.","keywords":["incremental","relative","distance mode"]},{"code":"G93","aliases":[],"name":"Inverse Time Feed Mode","category":"modes","modal":"Feed Mode","desc":"F means 1/minutes: the move must complete in 1/F minutes. Used mainly for simultaneous multi-axis (4/5-axis) motion where tool-tip speed is complex.","syntax":"G93","params":{"F":"Move completes in 1/F minutes"},"example":"G93\nG1 X10 A90 F2 ; complete in 30 seconds","tips":"F must be given on every motion line in G93.","keywords":["inverse time","feed mode","5 axis","rotary feed"]},{"code":"G94","aliases":[],"name":"Units per Minute Feed Mode","category":"modes","modal":"Feed Mode","desc":"F is linear units (mm or inch) per minute. Standard for mills and routers; the default.","syntax":"G94","params":{"F":"Feed in units/min"},"example":"G94\nG1 X100 F500","tips":null,"keywords":["feed mode","units per minute","mm/min"]},{"code":"G95","aliases":[],"name":"Units per Revolution Feed Mode","category":"modes","modal":"Feed Mode","desc":"F is units per spindle revolution — the lathe standard, tying chip load directly to RPM. Needs spindle speed feedback.","syntax":"G95","params":{"F":"Feed in units/rev"},"example":"G95\nS1000 M3\nG1 Z-50 F0.2 ; effective 200mm/min","tips":null,"keywords":["feed per rev","lathe feed","units per revolution"]},{"code":"G96","aliases":[],"name":"Constant Surface Speed (Lathe)","category":"modes","modal":"Spindle Mode","desc":"S is a surface speed; the controller varies spindle RPM with the X diameter to hold it constant at the cutting edge. Lathe builds only.","syntax":"G96 S<surface speed> [D<max rpm>]","params":{"S":"Target surface speed (m/min or ft/min)","D":"Max RPM cap"},"example":"G50 S4000\nG96 S150 M3","tips":"Always cap RPM (G50 S / D word) — RPM rises sharply as diameter shrinks.","keywords":["css","surface speed","lathe","constant speed"]},{"code":"G97","aliases":[],"name":"Constant RPM Mode","category":"modes","modal":"Spindle Mode","desc":"S is plain revolutions per minute. Default; required for drilling, tapping and threading.","syntax":"G97 S<rpm>","params":{"S":"Spindle RPM"},"example":"G97 S800 M3","tips":null,"keywords":["rpm","spindle mode","constant rpm"]},{"code":"G61","aliases":["G61.1"],"name":"Exact Stop Path Mode","category":"modes","modal":"Path Control","desc":"Machine fully stops at the end of each move before starting the next — perfectly sharp corners at the cost of speed and smoothness.","syntax":"G61","params":{},"example":"G61\n(precise engraving moves)","tips":"Can leave witness marks/divots at corners due to the momentary stop. Continuous blending is the usual default.","keywords":["exact stop","path control","corners","sharp"]},{"code":"G65","aliases":[],"name":"Macro Call with Arguments","category":"program","modal":null,"desc":"Calls a macro (P<n>.macro on SD/LittleFS) and passes letter arguments as local variables. Requires NGC expressions enabled in the firmware. P1-P7 are reserved built-ins (settings read/write, tool offsets, machine state, probe select, spindle delay skip, Modbus messaging).","syntax":"G65 P<number> [L<repeat>] [A- B- C- ...]","params":{"P":"Macro number: P100+ user macros; P1-P7 built-ins","L":"Repeat count","A":"Argument (becomes #1)","B":"Argument (#2)","C":"Argument (#3)","Q":"Argument (built-ins: setting/tool/probe number)","R":"Argument (built-ins: register/axis)","S":"Argument (built-ins: value/slave address)","I":"Argument (P3: parameter number)","F":"Argument (P7: Modbus function code)"},"example":"G65 P100 A5.0 B200 ; call P100.macro with args\nG65 P1 Q110 ; built-in: read setting $110 into _value","tips":"Notable built-ins: P1 read/write settings, P4 machine state, P5 select probe input (0 probe, 1 toolsetter), P7 Modbus (talk to a VFD from G-code). Nesting G65 is not allowed.","keywords":["macro","subprogram","call","arguments","modbus","vfd","expression","p100"]},{"code":"G66","aliases":["G67"],"name":"Modal Macro Call / Cancel","category":"program","modal":"Modal Macro","desc":"G66 works like G65 but repeats the macro after every subsequent motion command until G67 cancels it — handy for custom drilling or probing cycles at many locations.","syntax":"G66 P<number> [args] ... G67","params":{"P":"Macro number","L":"Repeat count"},"example":"G66 P110 A2\nX10 Y10\nX20\nG67","tips":null,"keywords":["modal macro","repeat","custom cycle"]},{"code":"M0","aliases":["M00"],"name":"Program Stop","category":"program","modal":null,"desc":"Unconditionally pauses the program — motion, spindle and coolant stop. Cycle Start resumes from the next line. An optional (message) shows in the sender.","syntax":"M0 [(message)]","params":{},"example":"G0 Z20\nM0 (Clear chips, then press start)","tips":"Manual tool change setups often transform M6 into M0 with a message.","keywords":["stop","pause","hold","wait","operator"]},{"code":"M1","aliases":["M01"],"name":"Optional Stop","category":"program","modal":null,"desc":"Pauses like M0, but only when the Optional Stop switch is enabled in the sender/machine; ignored otherwise. Good for inspection points you don't need every run.","syntax":"M1 [(message)]","params":{},"example":"(finishing pass)\nM1","tips":null,"keywords":["optional stop","pause","inspection"]},{"code":"M2","aliases":["M02"],"name":"Program End","category":"program","modal":null,"desc":"Ends the program, resets the parser to defaults and leaves the machine idle.","syntax":"M2","params":{},"example":"M5\nM2","tips":null,"keywords":["end","program end","finish"]},{"code":"M30","aliases":[],"name":"Program End & Rewind","category":"program","modal":null,"desc":"The standard end-of-file: does everything M2 does and rewinds to the start, ready for the next part.","syntax":"M30","params":{},"example":"G0 Z20\nM5 M9\nM30","tips":"When running from SD card, $FR before start enables rewind-and-rerun on cycle start.","keywords":["end","rewind","program end","m30"]},{"code":"M3","aliases":["M03"],"name":"Spindle On — Clockwise","category":"spindle","modal":"Spindle","desc":"Starts the spindle clockwise at the last programmed S speed. In laser mode ($32=1), fires the laser at constant power while moving.","syntax":"M3 S<rpm>","params":{"S":"Spindle speed (RPM) or laser power"},"example":"S18000 M3","tips":"With spindle-at-speed enabled ($340 tolerance) the controller waits for the VFD to reach speed. For laser engraving prefer M4 dynamic power.","keywords":["spindle","on","clockwise","cw","start spindle","laser on"]},{"code":"M4","aliases":["M04"],"name":"Spindle On — CCW / Laser Dynamic","category":"spindle","modal":"Spindle","desc":"Starts the spindle counter-clockwise (left-hand tools). In laser mode ($32=1), enables dynamic power: output scales with actual velocity so accel/decel zones don't burn darker.","syntax":"M4 S<rpm>","params":{"S":"Spindle speed (RPM) or max laser power"},"example":"M4 S800 ; laser dynamic mode","tips":"This is the mode LightBurn's grbl profiles use for engraving.","keywords":["spindle","ccw","counterclockwise","laser","dynamic power","variable power"]},{"code":"M5","aliases":["M05"],"name":"Spindle / Laser Off","category":"spindle","modal":"Spindle","desc":"Stops spindle rotation (or laser output).","syntax":"M5","params":{},"example":"M5","tips":"$394 sets a spin-down delay so motion waits for the spindle to actually stop.","keywords":["spindle off","stop","laser off"]},{"code":"M6","aliases":["M06"],"name":"Tool Change","category":"tool","modal":null,"desc":"Executes a tool change to the tool selected by T. With an ATC, runs the tool change macro (tc.macro / P200.macro for RapidChange). Without one, behavior follows $341: pause like M0, move to a change position, and/or run the manual probe protocol ($TPW).","syntax":"T<n> M6 | M6 T<n>","params":{"T":"Tool number to load"},"example":"T2 M6\nG43 H2","tips":"T only selects; M6 performs the change. Apply the new length offset (G43/G43.1) afterward. See $341-$346 for tool change configuration.","keywords":["tool change","atc","change tool","m6","rapidchange","toolchange"]},{"code":"M7","aliases":["M07"],"name":"Mist Coolant On","category":"coolant","modal":"Coolant","desc":"Turns on the mist coolant output pin (air/oil mist). Often repurposed for an air blast or accessory relay.","syntax":"M7","params":{},"example":"M7","tips":null,"keywords":["mist","coolant","air","output"]},{"code":"M8","aliases":["M08"],"name":"Flood Coolant On","category":"coolant","modal":"Coolant","desc":"Turns on the flood coolant output pin — the primary coolant output. Commonly repurposed for dust collection or a dust boot.","syntax":"M8","params":{},"example":"M8\nG1 Z-5 F300","tips":null,"keywords":["flood","coolant","dust boot","dust collection","output"]},{"code":"M9","aliases":["M09"],"name":"All Coolant Off","category":"coolant","modal":"Coolant","desc":"Turns off both mist (M7) and flood (M8) outputs.","syntax":"M9","params":{},"example":"G0 Z20\nM9","tips":null,"keywords":["coolant off","mist off","flood off"]},{"code":"M48","aliases":[],"name":"Enable Overrides","category":"program","modal":"Override","desc":"Re-enables the real-time feed, rapid and spindle override controls (the default).","syntax":"M48","params":{},"example":"M48","tips":null,"keywords":["override","enable","feed override"]},{"code":"M49","aliases":[],"name":"Disable Overrides","category":"program","modal":"Override","desc":"Ignores all override controls; the program runs at exactly 100% of programmed feed, rapid and spindle values.","syntax":"M49","params":{},"example":"M49\nG1 X100 F150\nM48","tips":"Use sparingly — it removes the operator's ability to slow a bad cut.","keywords":["override","disable","lock feed"]},{"code":"M50","aliases":["M51","M53"],"name":"Selective Override Control","category":"program","modal":null,"desc":"Granular override disabling: M50 feed override off, M51 spindle override off, M53 rapid override off. M48 re-enables all.","syntax":"M50 | M51 | M53","params":{},"example":"M50 M51\n(critical finishing pass)\nM48","tips":null,"keywords":["override","feed","spindle","rapid","selective"]},{"code":"M56","aliases":[],"name":"Parking Motion Override","category":"program","modal":null,"desc":"Enables (P1) or disables (P0) automatic parking motion. Requires parking support plus this override option compiled into the firmware.","syntax":"M56 P<0|1>","params":{"P":"1 = enable parking motion, 0 = disable"},"example":"M56 P0\n(critical moves)\nM56 P1","tips":null,"keywords":["parking","park","override"]},{"code":"M61","aliases":[],"name":"Set Current Tool","category":"tool","modal":null,"desc":"Tells the controller which tool is currently loaded (Q word) without performing a change — used to sync state after manual swaps.","syntax":"M61 Q<tool>","params":{"Q":"Tool number now in the spindle"},"example":"M61 Q3","tips":null,"keywords":["set tool","current tool","sync tool"]},{"code":"M62","aliases":["M63"],"name":"Digital Output — Synced","category":"io","modal":null,"desc":"Queues a digital output change (M62 on, M63 off) to fire at the exact start of the next motion command. Ideal for laser gating, cameras, or anything that must align with motion.","syntax":"M62 P<port> | M63 P<port>","params":{"P":"Digital output port number"},"example":"M62 P1\nG1 X20 F500 ; output 1 goes high as this move starts\nM63 P1\nG0 X30","tips":"On the plasma/THC plugin these same codes toggle torch height control.","keywords":["digital output","synchronized","io","laser gate","output on","output off"]},{"code":"M64","aliases":["M65"],"name":"Digital Output — Immediate","category":"io","modal":null,"desc":"Sets a digital output high (M64) or low (M65) immediately when read, without waiting for motion.","syntax":"M64 P<port> | M65 P<port>","params":{"P":"Digital output port number"},"example":"M400\nM64 P1 ; trigger once fully stopped","tips":"Use $pins / $pinstate in the terminal to see which aux ports exist and their live state.","keywords":["digital output","immediate","io","relay","aux output"]},{"code":"M66","aliases":[],"name":"Wait for Input","category":"io","modal":null,"desc":"Pauses execution until a digital input reaches the requested state, or a timeout expires. Requires configured aux inputs.","syntax":"M66 P<port> L<0|1> [Q<timeout s>]","params":{"P":"Digital input port number","L":"State to wait for: 0 low, 1 high","Q":"Timeout in seconds (error if exceeded)"},"example":"M66 P2 L1 Q10 ; wait up to 10s for input 2 high","tips":null,"keywords":["wait","input","sensor","io","interlock"]},{"code":"M67","aliases":["M68"],"name":"Analog Output","category":"io","modal":null,"desc":"Sets an analog output value — M67 synchronized with the next motion, M68 immediately. Used for laser power ramps, flow control, etc.","syntax":"M67 P<port> Q<value> | M68 P<port> Q<value>","params":{"P":"Analog output port number","Q":"Target analog value (range depends on DAC/PWM resolution)","E":"Port (plasma plugin velocity-reduction variant)"},"example":"M67 P0 Q150\nG1 X20 F500","tips":null,"keywords":["analog output","pwm","dac","laser power","io"]},{"code":"M70","aliases":["M71","M72","M73"],"name":"Modal State Save/Restore","category":"program","modal":null,"desc":"Saves (M70) and restores (M72) the full modal state — active G modes, feed, spindle speed — so macros can change modes freely without disturbing the main program. M71 invalidates a saved state; M73 saves with auto-restore for subprograms.","syntax":"M70 ... M72","params":{},"example":"M70\nG91 G1 F100\n(probe moves)\nM72","tips":"Wrap any probing or tool change macro in M70/M72 — cheap insurance against leaving the machine in G91.","keywords":["save state","restore","modal","macro safety"]},{"code":"M98","aliases":[],"name":"Subroutine Call","category":"program","modal":null,"desc":"Calls a subroutine: with $700=1 it first looks for an O<n> sub label in the current file, otherwise (or if not found) runs external file P<n> from SD/LittleFS. L repeats the call.","syntax":"M98 P<number> [L<repeat>]","params":{"P":"Subroutine number or filename","L":"Repeat count"},"example":"M98 P100 L3\nM30\nO100 sub\nG91 G0 X10\nM99","tips":null,"keywords":["subroutine","call","subprogram","repeat"]},{"code":"M99","aliases":[],"name":"Return from Subroutine","category":"program","modal":null,"desc":"Ends a subroutine and returns to the line after the call. In a main program it acts as rewind-and-loop. Also terminates tool change macros.","syntax":"M99","params":{"P":"Optional return line (implementation-dependent)"},"example":"M99","tips":null,"keywords":["return","subroutine","end macro"]},{"code":"M42","aliases":[],"name":"Set Digital Output (OpenPNP)","category":"plugin","modal":null,"desc":"OpenPNP plugin: directly sets a digital I/O port state.","syntax":"M42 P<port> S<0|1>","params":{"P":"I/O port number","S":"0 = off, 1 = on"},"example":"M42 P1 S1","tips":null,"keywords":["digital output","openpnp","io","relay"]},{"code":"M104","aliases":[],"name":"Select Spindle","category":"plugin","modal":null,"desc":"Spindle plugin: selects which configured spindle (VFD, PWM, laser...) subsequent S/M3/M4 commands address. Essential on dual-spindle setups.","syntax":"M104 P<spindle>","params":{"P":"Spindle number (see $SPINDLES for the list)"},"example":"M104 P1 ; switch to spindle 1 (e.g. PWM laser)","tips":"Run $SPINDLES in the terminal to enumerate configured spindles and their numbers.","keywords":["spindle select","dual spindle","laser","vfd","switch spindle","multi spindle"]},{"code":"M106","aliases":["M107"],"name":"Fan Control","category":"plugin","modal":null,"desc":"Fan plugin: M106 turns a fan on with PWM speed 0-255; M107 turns it off.","syntax":"M106 P<fan> S<0-255> | M107 P<fan>","params":{"P":"Fan index","S":"PWM duty 0-255"},"example":"M106 P0 S255","tips":null,"keywords":["fan","cooling","pwm"]},{"code":"M114","aliases":[],"name":"Report Position (Encoder)","category":"plugin","modal":null,"desc":"Encoder plugin: reports current position, including spindle encoder data when available.","syntax":"M114","params":{},"example":"M114","tips":null,"keywords":["position","report","encoder"]},{"code":"M122","aliases":[],"name":"Trinamic Driver Report","category":"plugin","modal":null,"desc":"Motor plugin: dumps Trinamic stepper driver status/debug info for the given axes.","syntax":"M122 [axes]","params":{"X":"Report X driver","Y":"Report Y driver","Z":"Report Z driver"},"example":"M122","tips":"Related: M906 set RMS current, M569 StealthChop/SpreadCycle, M911/M912 prewarn flags, M913 hybrid threshold, M914 homing sensitivity.","keywords":["trinamic","stepper","driver","debug","tmc"]},{"code":"M150","aliases":[],"name":"RGB LED Control","category":"plugin","modal":null,"desc":"Misc plugin: sets color and brightness for an RGB/RGBW LED strip or a single LED by index. Used for status lighting on machines with LED rails/rings.","syntax":"M150 [R<0-255>] [U<0-255>] [B<0-255>] [W<0-255>] [P<0-255>] [I<index>] [S<strip>] [K]","params":{"R":"Red 0-255","U":"Green 0-255","B":"Blue 0-255","W":"White 0-255","P":"Brightness 0-255","I":"LED index for individual control","S":"Strip index (0 or 1)","K":"Keep unspecified components unchanged"},"example":"M150 R255 U0 B0 S1 ; strip 1 solid red\nM150 R0 U0 B0 S1 ; off","tips":"Note green is U, not G (G would parse as a G-code).","keywords":["led","rgb","light","strip","neopixel","status light"]},{"code":"M220","aliases":[],"name":"Set Feed Override %","category":"plugin","modal":null,"desc":"Sets the feed override percentage from G-code (Marlin heritage). B backs up the current value, R restores it, S sets a percentage.","syntax":"M220 [S<percent>] [B] [R]","params":{"S":"Feed override percent (100 = programmed feed)","B":"Backup current override","R":"Restore backed-up override"},"example":"M220 S50\n(difficult section)\nM220 S100","tips":null,"keywords":["feed override","percent","slow down","speed"]},{"code":"M280","aliases":[],"name":"Set Servo Position","category":"plugin","modal":null,"desc":"Servo plugin: moves a PWM servo to a position — typically 0-180 degrees. Used for probe deployers, dust shoes, clamps.","syntax":"M280 P<servo> S<position>","params":{"P":"Servo index","S":"Target position (deg or µs)"},"example":"M280 P0 S90 ; deploy\nM280 P0 S0 ; stow","tips":null,"keywords":["servo","deploy","position","pwm"]},{"code":"M400","aliases":[],"name":"Finish Moves","category":"plugin","modal":null,"desc":"Waits for the planner buffer to fully empty before the next command — the machine is completely stationary. Roughly a G4 P0.","syntax":"M400","params":{},"example":"G0 X50 Y50\nM400\nM64 P1","tips":null,"keywords":["wait","finish","buffer","sync"]},{"code":"M810","aliases":[],"name":"ATCi Keepout Zone Toggle (Sienci)","category":"plugin","modal":null,"desc":"Sienci ATCi plugin: runtime toggle for keepout-zone enforcement around the tool magazine. P1 enables protection, P0 disables it.","syntax":"M810 P<0|1>","params":{"P":"1 = enforce keepout zone, 0 = disable"},"example":"M810 P0","tips":null,"keywords":["sienci","atc","atci","keepout","magazine"]},{"code":"$TLS","aliases":[],"name":"Tool Length Set (ATC/MTC plugins)","category":"plugin","modal":null,"desc":"Runs the tool length setter probe cycle for the currently loaded tool: raises to safe Z, rapids to the configured TLS position, probes down (G38.2), applies the measured tool length offset, and retracts. Provided by the Rapid Change ATC, Manual Tool Changer, and Pneumatic ATC plugins - the exact motions come from that plugin's settings, including any Pre/Post TLS g-code hooks.","syntax":"$TLS","params":{},"example":"$TLS","tips":"Only works when one of the tool-changer plugins is installed and enabled. The macro expansion can be shown line by line by enabling \"show macro commands\" in the plugin settings.","keywords":["tool length","tls","tool setter","probe tool","rapidchange","atc","tool changer","offset"]},{"code":"$SLOT1","aliases":["$SLOT2","$SLOT<n>"],"name":"Go To Tool Slot n (Rapid Change ATC)","category":"plugin","modal":null,"desc":"Raises to safe Z, then rapids (G53 machine coordinates) to the XY position of magazine slot n as configured in the Rapid Change ATC plugin. $SLOT1, $slot2, $SLOT03 all work - leading zeros are tolerated. Slot numbers outside the configured pocket count are deliberately left alone (they fall through to the controller as unknown commands) so a typo cannot send the spindle to a nonexistent slot.","syntax":"$SLOT<n>","params":{},"example":"$SLOT3","tips":"Provided by the Rapid Change ATC plugin - only works when it is installed and enabled. Useful for aligning the magazine or verifying slot positions without a tool change.","keywords":["slot","pocket","magazine","rapidchange","atc","tool changer","position"]},{"code":"$POCKET1","aliases":[],"name":"Go To Pocket 1 (Manual Tool Changer)","category":"plugin","modal":null,"desc":"Raises to safe Z, then rapids (G53 machine coordinates) to the Pocket 1 XY position configured in the Manual Tool Changer plugin - the parking spot where manual tool swaps happen.","syntax":"$POCKET1","params":{},"example":"$POCKET1","tips":"Provided by the Manual Tool Changer plugin - only works when it is installed and enabled.","keywords":["pocket","manual tool change","tool changer","park","position"]},{"code":"$ADB_RETRACT","aliases":[],"name":"Retract Dust Boot (AutoDustboot)","category":"plugin","modal":null,"desc":"Retracts the pneumatic dust boot. The AutoDustboot plugin injects this automatically before tool changes (M6/M98) in a loaded job, but it can also be typed in the Console or embedded in your own macros.","syntax":"$ADB_RETRACT","params":{},"example":"$ADB_RETRACT","tips":"Provided by the AutoDustboot plugin - only works when it is installed and enabled.","keywords":["dust boot","dustboot","retract","pneumatic","adb"]},{"code":"$ADB_EXPAND","aliases":[],"name":"Expand Dust Boot (AutoDustboot)","category":"plugin","modal":null,"desc":"Expands (lowers) the pneumatic dust boot. The AutoDustboot plugin injects this automatically after the first rapid XY move following a tool change, and it can also be typed in the Console or embedded in macros.","syntax":"$ADB_EXPAND","params":{},"example":"$ADB_EXPAND","tips":"Provided by the AutoDustboot plugin - only works when it is installed and enabled.","keywords":["dust boot","dustboot","expand","deploy","pneumatic","adb"]}],"settings":[{"code":"$0","name":"Step pulse time","desc":"SLB-EXT default: 5 microseconds. Sets time length per step. Minimum 2 microseconds. This needs to be reduced from the default value of 10 when max. step rates exceed approximately 80 kHz.","keywords":["invert","pulse","signal","step","stepper","time"]},{"code":"$1","name":"Step idle delay","desc":"SLB-EXT default: 254 milliseconds. Sets a short hold delay when stopping to let dynamics settle before disabling steppers. Value 255 keeps motors enabled.","keywords":["delay","idle","invert","signal","step","stepper"]},{"code":"$2","name":"Step pulse invert","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Inverts the step signals (active low).","keywords":["invert","pulse","signal","step","stepper"]},{"code":"$3","name":"Step direction invert","desc":"SLB-EXT default: X: OFF Y: ON Z: ON A: OFF (6). Inverts the direction signals (active low).","keywords":["direction","invert","signal","step","stepper"]},{"code":"$4","name":"Invert stepper enable pin(s)","desc":"SLB-EXT default: X: ON Y: ON Z: ON A: ON (15). Inverts the stepper driver enable signals. Most drivers uses active low enable requiring inversion. NOTE: If the stepper drivers shares the same enable signal only X is used.","keywords":["enable","invert","pin","signal","stepper"]},{"code":"$5","name":"Invert limit pins","desc":"SLB-EXT default: X: ON Y: ON Z: ON A: ON (15). Inverts the axis limit input signals.","keywords":["invert","limit","pins","signal","stepper"]},{"code":"$6","name":"Invert probe pin","desc":"SLB-EXT default: Enabled (1). Inverts the probe input pin signal.","keywords":["invert","pin","probe","signal","stepper"]},{"code":"$7","name":"Deprecated","desc":"Deprecated","keywords":["deprecated"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$8","name":"Ganged axes direction invert","desc":"SLB-EXT default: Disabled (0). Inverts the direction signals for the second motor used for ganged axes. NOTE: This inversion will be applied in addition to the inversion from setting $3.","keywords":["axes","direction","ganged","invert","signal","stepper"]},{"code":"$9","name":"PWM Spindle","desc":"SLB-EXT default: Enable: ON RPM controls spindle en signal: OFF (1). Enable: Controls PWM output availability. RPM controls spindle enable signal: When M3 or M4 is active, S > 0 turns on spindle enable and S0 turns it off.","keywords":["invert","pwm","signal","spindle","stepper"]},{"code":"$10","name":"Status report options","desc":"SLB-EXT default: Position in machine coords: ON Buffer state: ON Line numbers: ON Feed & speed: ON Pin state: ON Work coord offset: ON Overrides: ON Probe coords: ON Buffer sync on WCO change: ON Parser state: OFF Alarm substatus: OFF Run substatus: OFF (511). Specifies optional data included in status reports. If Run substatus is enabled it may be used for simple probe protection. NOTE: Parser state will be sent separately after the status report and only on changes.","keywords":["options","report","status"]},{"code":"$11","name":"Junction deviation","desc":"SLB-EXT default: 0.010 mm. Sets how fast Grbl travels through consecutive motions. Lower value slows it down.","keywords":["deviation","junction"]},{"code":"$12","name":"Arc tolerance","desc":"SLB-EXT default: 0.002 mm. Sets the G2 and G3 arc tracing accuracy based on radial error. Beware: A very small value may effect performance.","keywords":["arc","tolerance"]},{"code":"$13","name":"Report in inches","desc":"SLB-EXT default: Disabled (0). Enables inch units when returning any position and rate value that is not a settings value.","keywords":["inches","report"]},{"code":"$14","name":"Invert control pins","desc":"SLB-EXT default: Reset: OFF Feed hold: ON Cycle start: ON Safety door: ON EStop: OFF (14). Inverts the control signals (active low). NOTE: Block delete, Optional stop, EStop and Probe connected are optional signals, availability is driver dependent.","keywords":["control","invert","pins"]},{"code":"$15","name":"Invert coolant pins","desc":"SLB-EXT default: Flood: OFF Mist: OFF (0). Inverts the coolant and mist signals (active low).","keywords":["coolant","invert","pins"]},{"code":"$16","name":"Invert spindle signals","desc":"SLB-EXT default: Spindle en: OFF Spindle dir: OFF PWM: OFF (0). Inverts the spindle on, counterclockwise and PWM signals (active low). NOTE: A hard reset of the controller is required after changing this setting.","keywords":["invert","signals","spindle"]},{"code":"$17","name":"Pullup disable control pins","desc":"SLB-EXT default: Reset: OFF Feed hold: OFF Cycle start: OFF Safety door: OFF EStop: OFF (0). Disable the control signals pullup resistors. Potentially enables pulldown resistor if available. NOTE: Block delete, Optional stop and EStop are optional signals, availability is driver dependent.","keywords":["control","disable","pins","pullup"]},{"code":"$18","name":"Pullup disable limit pins","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Disable the limit signals pullup resistors. Potentially enables pulldown resistor if available.","keywords":["disable","limit","pins","pullup"]},{"code":"$19","name":"Pullup disable probe pin","desc":"SLB-EXT default: Disabled (0). Disable the probe signal pullup resistor. Potentially enables pulldown resistor if available.","keywords":["disable","pin","probe","pullup"]},{"code":"$20","name":"Soft limits enable","desc":"SLB-EXT default: Disabled (0). Enables soft limits checks within machine travel and sets alarm when exceeded. Requires homing.","keywords":["enable","homing","limits","soft"]},{"code":"$21","name":"Hard limits enable","desc":"SLB-EXT default: Enable: OFF Strict mode: OFF (0). When enabled immediately halts motion and throws an alarm when a limit switch is triggered. In strict mode only homing is possible when a switch is engaged.","keywords":["enable","hard","homing","limits"]},{"code":"$22","name":"Homing cycle","desc":"SLB-EXT default: Enable: OFF Single axis commands: OFF Homing on startup: OFF Set machine origin: OFF Two switches share one input: OFF Allow manual: OFF Override locks: OFF Keep homed status on reset: OFF (0). Enables homing cycle. Requires limit switches on axes to be automatically homed. When `Enable single axis commands` is checked, single axis homing can be performed by $H<axis letter> commands. When `Allow manual` is checked, axes not homed automatically may be homed manually by $H or $H<axis letter> commands. `Override locks` is for allowing a soft reset to disable `Homing on startup required`.","keywords":["cycle","homing","limits"]},{"code":"$23","name":"Homing direction invert","desc":"SLB-EXT default: X: ON Y: ON Z: OFF A: ON (11). Homing searches for a switch in the positive direction. Set axis bit to search in negative direction.","keywords":["direction","homing","invert","limits"]},{"code":"$24","name":"Homing locate feed rate","desc":"SLB-EXT default: 150 mm/min. Feed rate to slowly engage limit switch to determine its location accurately.","keywords":["feed","homing","limits","locate","rate"]},{"code":"$25","name":"Homing search seek rate","desc":"SLB-EXT default: 4300 mm/min. Seek rate to quickly find the limit switch before the slower locating phase.","keywords":["homing","limits","rate","search","seek"]},{"code":"$26","name":"Homing switch debounce delay","desc":"SLB-EXT default: 25 milliseconds. Sets a short delay between phases of homing cycle to let a switch debounce.","keywords":["debounce","delay","homing","limits","switch"]},{"code":"$27","name":"Homing switch pull-off distance","desc":"SLB-EXT default: 1.5 mm. Retract distance after triggering switch to disengage it. Homing will fail if switch isn't cleared.","keywords":["distance","homing","limits","off","pull","switch"]},{"code":"$28","name":"G73 retract distance","desc":"SLB-EXT default: 0.1 mm. G73 retract distance (for chip breaking drilling).","keywords":["distance","retract"]},{"code":"$29","name":"Pulse delay","desc":"SLB-EXT default: 0 microseconds. Step pulse delay. Normally leave this at 0 as there is an implicit delay on direction changes when AMASS is active.","keywords":["delay","invert","pulse","signal","stepper"]},{"code":"$30","name":"Maximum spindle speed","desc":"SLB-EXT default: 24000 RPM. Maximum spindle speed, can be overridden by spindle plugins.","keywords":["maximum","speed","spindle"]},{"code":"$31","name":"Minimum spindle speed","desc":"SLB-EXT default: 7500 RPM. Minimum spindle speed, can be overridden by spindle plugins.","keywords":["minimum","speed","spindle"]},{"code":"$32","name":"Mode of operation","desc":"SLB-EXT default: Normal (0). Laser mode: consecutive G1/2/3 commands will not halt when spindle speed is changed. Lathe mode: allows use of G7, G8, G96 and G97.","keywords":["mode","operation","spindle"]},{"code":"$33","name":"Spindle PWM frequency","desc":"SLB-EXT default: 1000 Hz. Spindle PWM frequency.","keywords":["frequency","pwm","spindle"]},{"code":"$34","name":"Spindle PWM off value","desc":"SLB-EXT default: 0 percent. Spindle PWM off value in percent (duty cycle).","keywords":["off","pwm","spindle","value"]},{"code":"$35","name":"Spindle PWM min value","desc":"SLB-EXT default: 0 percent. Spindle PWM min value in percent (duty cycle).","keywords":["min","pwm","spindle","value"]},{"code":"$36","name":"Spindle PWM max value","desc":"SLB-EXT default: 100 percent. Spindle PWM max value in percent (duty cycle).","keywords":["max","pwm","spindle","value"]},{"code":"$37","name":"Steppers de-energize","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Specifies which steppers not to disable when stopped.","keywords":["energize","invert","signal","stepper","steppers"]},{"code":"$38","name":"Spindle pulses per revolution (PPR)","desc":"Spindle encoder pulses per revolution.","keywords":["spindle","pulses","per","revolution","ppr"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$39","name":"Enable legacy RT commands","desc":"SLB-EXT default: Enabled (1). Enables \"normal\" processing of ?, ! and ~ characters when part of $-setting or comment. If disabled then they are added to the input string instead.","keywords":["commands","enable","invert","legacy","signal","stepper"]},{"code":"$40","name":"Limit jog commands","desc":"SLB-EXT default: Enabled (1). Limit jog commands to machine limits for homed axes.","keywords":["commands","jog","limit"]},{"code":"$41","name":"Parking cycle","desc":"SLB-EXT default: Enable: ON Parking override control: OFF Deactivate upon init: OFF (1). Enables parking cycle, requires parking axis homed.","keywords":["cycle","parking"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$42","name":"Parking axis","desc":"SLB-EXT default: Z (2). Define which axis that performs the parking motion.","keywords":["axis","parking"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$43","name":"Homing passes","desc":"SLB-EXT default: 1. Number of homing passes. Minimum 1, maximum 128.","keywords":["homing","limits","passes"]},{"code":"$44","name":"Axes homing, first pass","desc":"SLB-EXT default: X: OFF Y: OFF Z: ON A: OFF (4). Axes to home in first pass.","keywords":["axes","first","homing","limits","pass"]},{"code":"$45","name":"Axes homing, second pass","desc":"SLB-EXT default: X: ON Y: ON Z: OFF A: OFF (3). Axes to home in second pass.","keywords":["axes","homing","limits","pass","second"]},{"code":"$46","name":"Axes homing, third pass","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Axes to home in third pass.","keywords":["axes","homing","limits","pass","third"]},{"code":"$47","name":"Axes homing, fourth pass","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Axes to home in fourth pass.","keywords":["axes","fourth","homing","limits","pass"]},{"code":"$48","name":"Axes homing, fifth phase","desc":"Axes to home in fifth phase.","keywords":["axes","homing","fifth","phase"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$49","name":"Axes homing, sixth phase","desc":"Axes to home in sixth phase.","keywords":["axes","homing","sixth","phase"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$56","name":"Parking pull-out distance","desc":"SLB-EXT default: 5 mm. Spindle pull-out and plunge distance in mm.Incremental distance.","keywords":["distance","out","parking","pull"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$57","name":"Parking pull-out rate","desc":"SLB-EXT default: 100 mm/min. Spindle pull-out/plunge slow feed rate in mm/min.","keywords":["out","parking","pull","rate"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$58","name":"Parking target","desc":"SLB-EXT default: -5 mm. Parking axis target. In mm, as machine coordinate [-max_travel, 0].","keywords":["parking","target"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$59","name":"Parking fast rate","desc":"SLB-EXT default: 500 mm/min. Parking fast rate to target after pull-out in mm/min.","keywords":["fast","parking","rate"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$60","name":"Restore overrides","desc":"SLB-EXT default: Enabled (1). Restore overrides to default values at program end.","keywords":["overrides","restore"]},{"code":"$61","name":"Safety door options","desc":"SLB-EXT default: Ignore when idle: ON Keep coolant state: ON (3). Enable this if it is desirable to open the safety door when in IDLE mode (eg. for jogging).","keywords":["door","options","safety"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$62","name":"Sleep enable","desc":"SLB-EXT default: Disabled (0). Enable sleep mode.","keywords":["enable","sleep"]},{"code":"$63","name":"Feed hold actions","desc":"SLB-EXT default: Disable laser: ON Restore spindle and coolant state: ON (3). Actions taken during feed hold and on resume from feed hold.","keywords":["actions","feed","hold"]},{"code":"$64","name":"Force init alarm","desc":"SLB-EXT default: Disabled (0). Starts Grbl in alarm mode after a cold reset.","keywords":["alarm","force","init"]},{"code":"$65","name":"Probing feed override","desc":"SLB-EXT default: Disabled (0). Allow feed override during probing.","keywords":["feed","override","probing"]},{"code":"$66","name":"Spindle linearisation, 1st point","desc":"Comma separated list of values: RPM_MIN, RPM_LINE_A1, RPM_LINE_B1, set to blank to disable.","keywords":["spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$67","name":"Spindle linearisation, 2nd point","desc":"Comma separated list of values: RPM_POINT12, RPM_LINE_A2, RPM_LINE_B2, set to blank to disable.","keywords":["spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$68","name":"Spindle linearisation, 3rd point","desc":"Comma separated list of values: RPM_POINT23, RPM_LINE_A3, RPM_LINE_B3, set to blank to disable.","keywords":["spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$69","name":"Spindle linearisation, 4th point","desc":"Comma separated list of values: RPM_POINT34, RPM_LINE_A4, RPM_LINE_B4, set to blank to disable.","keywords":["spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$70","name":"Network services","desc":"SLB-EXT default: Telnet: ON Websocket: ON FTP: ON (11). Network services/protocols to enable. NOTE: A hard reset of the controller is required after changing this setting.","keywords":["ethernet","ip","network","services"]},{"code":"$90","name":"Spindle sync P-gain","desc":"Spindle sync P-gain","keywords":["spindle","sync","gain"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$91","name":"Spindle sync I-gain","desc":"Spindle sync I-gain","keywords":["spindle","sync","gain"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$92","name":"Spindle sync D-gain","desc":"Spindle sync D-gain","keywords":["spindle","sync","gain"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$95","name":"Spindle sync PID max I error","desc":"Spindle sync PID max integrator error.","keywords":["spindle","sync","pid","max","error"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$100","name":"X-axis travel resolution","desc":"SLB-EXT default: 800 step/mm. Travel resolution in steps per millimeter.","keywords":["axis","calibration","motion","resolution","steps","travel"]},{"code":"$101","name":"Y-axis travel resolution","desc":"SLB-EXT default: 800 step/mm. Travel resolution in steps per millimeter.","keywords":["axis","calibration","motion","resolution","steps","travel"]},{"code":"$102","name":"Z-axis travel resolution","desc":"SLB-EXT default: 800 step/mm. Travel resolution in steps per millimeter.","keywords":["axis","calibration","motion","resolution","steps","travel"]},{"code":"$103","name":"A-axis travel resolution","desc":"SLB-EXT default: 79.012345679 step/deg. Travel resolution in steps per millimeter.","keywords":["axis","calibration","motion","resolution","steps","travel"]},{"code":"$110","name":"X-axis maximum rate","desc":"SLB-EXT default: 4000 mm/min. Maximum rate. Used as G0 rapid rate.","keywords":["axis","calibration","maximum","motion","rate","steps"]},{"code":"$111","name":"Y-axis maximum rate","desc":"SLB-EXT default: 4000 mm/min. Maximum rate. Used as G0 rapid rate.","keywords":["axis","calibration","maximum","motion","rate","steps"]},{"code":"$112","name":"Z-axis maximum rate","desc":"SLB-EXT default: 4000 mm/min. Maximum rate. Used as G0 rapid rate.","keywords":["axis","calibration","maximum","motion","rate","steps"]},{"code":"$113","name":"A-axis maximum rate","desc":"SLB-EXT default: 8000 deg/min. Maximum rate. Used as G0 rapid rate.","keywords":["axis","calibration","maximum","motion","rate","steps"]},{"code":"$120","name":"X-axis acceleration","desc":"SLB-EXT default: 750 mm/sec^2. Acceleration. Used for motion planning to not exceed motor torque and lose steps.","keywords":["acceleration","axis","calibration","motion","steps"]},{"code":"$121","name":"Y-axis acceleration","desc":"SLB-EXT default: 750 mm/sec^2. Acceleration. Used for motion planning to not exceed motor torque and lose steps.","keywords":["acceleration","axis","calibration","motion","steps"]},{"code":"$122","name":"Z-axis acceleration","desc":"SLB-EXT default: 750 mm/sec^2. Acceleration. Used for motion planning to not exceed motor torque and lose steps.","keywords":["acceleration","axis","calibration","motion","steps"]},{"code":"$123","name":"A-axis acceleration","desc":"SLB-EXT default: 1000 deg/sec^2. Acceleration. Used for motion planning to not exceed motor torque and lose steps.","keywords":["acceleration","axis","calibration","motion","steps"]},{"code":"$130","name":"X-axis maximum travel","desc":"SLB-EXT default: 810 mm. Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances.","keywords":["axis","calibration","maximum","motion","steps","travel"]},{"code":"$131","name":"Y-axis maximum travel","desc":"SLB-EXT default: 855 mm. Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances.","keywords":["axis","calibration","maximum","motion","steps","travel"]},{"code":"$132","name":"Z-axis maximum travel","desc":"SLB-EXT default: 120 mm. Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances.","keywords":["axis","calibration","maximum","motion","steps","travel"]},{"code":"$133","name":"A-axis maximum travel","desc":"SLB-EXT default: 0 deg. Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances.","keywords":["axis","calibration","maximum","motion","steps","travel"]},{"code":"$140","name":"X-axis motor current","desc":"SLB-EXT default: 2800 mA. Motor current in mA (RMS). NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","motor","trinamic"]},{"code":"$141","name":"Y-axis motor current","desc":"Motor current in mA (RMS). NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","motor","trinamic"]},{"code":"$142","name":"Z-axis motor current","desc":"Motor current in mA (RMS). NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","motor","trinamic"]},{"code":"$143","name":"A-axis motor current","desc":"SLB-EXT default: 0. Motor current in mA (RMS). NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","motor","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$150","name":"X-axis microsteps","desc":"SLB-EXT default: 32 steps. Microsteps per fullstep. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","microsteps","motor","trinamic"]},{"code":"$151","name":"Y-axis microsteps","desc":"Microsteps per fullstep. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","microsteps","motor","trinamic"]},{"code":"$152","name":"Z-axis microsteps","desc":"Microsteps per fullstep. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","microsteps","motor","trinamic"]},{"code":"$153","name":"A-axis microsteps","desc":"SLB-EXT default: 16. Microsteps per fullstep. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","microsteps","motor","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$180","name":"X-axis homing locate feed rate","desc":"SLB-EXT default: 150 mm/min. Feed rate to slowly engage limit switch to determine its location accurately. NOTE: Defaults to $24 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","feed","homing","limits","locate","rate"]},{"code":"$181","name":"Y-axis homing locate feed rate","desc":"Feed rate to slowly engage limit switch to determine its location accurately. NOTE: Defaults to $24 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","feed","homing","limits","locate","rate"]},{"code":"$182","name":"Z-axis homing locate feed rate","desc":"Feed rate to slowly engage limit switch to determine its location accurately. NOTE: Defaults to $24 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","feed","homing","limits","locate","rate"]},{"code":"$183","name":"A-axis homing locate feed rate","desc":"Feed rate to slowly engage limit switch to determine its location accurately. NOTE: Defaults to $24 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","feed","homing","limits","locate","rate"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$190","name":"X-axis homing search seek rate","desc":"SLB-EXT default: 4300 mm/min. Seek rate to quickly find the limit switch before the slower locating phase. NOTE: Defaults to $25 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","homing","limits","rate","search","seek"]},{"code":"$191","name":"Y-axis homing search seek rate","desc":"Seek rate to quickly find the limit switch before the slower locating phase. NOTE: Defaults to $25 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","homing","limits","rate","search","seek"]},{"code":"$192","name":"Z-axis homing search seek rate","desc":"Seek rate to quickly find the limit switch before the slower locating phase. NOTE: Defaults to $25 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","homing","limits","rate","search","seek"]},{"code":"$193","name":"A-axis homing search seek rate","desc":"Seek rate to quickly find the limit switch before the slower locating phase. NOTE: Defaults to $25 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","homing","limits","rate","search","seek"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$200","name":"X-axis StallGuard2 fast threshold","desc":"SLB-EXT default: 22. StallGuard threshold for fast (seek) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","fast","motor","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$201","name":"Y-axis StallGuard2 fast threshold","desc":"StallGuard threshold for fast (seek) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","fast","motor","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$202","name":"Z-axis StallGuard2 fast threshold","desc":"StallGuard threshold for fast (seek) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","fast","motor","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$203","name":"A-axis StallGuard2 fast threshold","desc":"StallGuard threshold for fast (seek) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","fast","motor","stallguard","threshold","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$210","name":"X-axis hold current","desc":"SLB-EXT default: 35 %. Motor current at standstill as a percentage of full current. NOTE: If grblHAL is configured to disable motors on standstill this setting has no use. Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","hold","motor","trinamic"]},{"code":"$211","name":"Y-axis hold current","desc":"Motor current at standstill as a percentage of full current. NOTE: If grblHAL is configured to disable motors on standstill this setting has no use. Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","hold","motor","trinamic"]},{"code":"$212","name":"Z-axis hold current","desc":"Motor current at standstill as a percentage of full current. NOTE: If grblHAL is configured to disable motors on standstill this setting has no use. Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","hold","motor","trinamic"]},{"code":"$213","name":"A-axis hold current","desc":"SLB-EXT default: 50. Motor current at standstill as a percentage of full current. NOTE: If grblHAL is configured to disable motors on standstill this setting has no use. Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","hold","motor","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$220","name":"X-axis stallGuard2 slow threshold","desc":"SLB-EXT default: 22. StallGuard threshold for slow (feed) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","motor","slow","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$221","name":"Y-axis stallGuard2 slow threshold","desc":"StallGuard threshold for slow (feed) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","motor","slow","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$222","name":"Z-axis stallGuard2 slow threshold","desc":"StallGuard threshold for slow (feed) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","motor","slow","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$223","name":"A-axis stallGuard2 slow threshold","desc":"StallGuard threshold for slow (feed) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","motor","slow","stallguard","threshold","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$300","name":"Hostname","desc":"SLB-EXT default: grblHAL. Network hostname. ~Controller reset required for setting change to take effect~","keywords":["ethernet","hostname","ip","network"]},{"code":"$301","name":"IP mode","desc":"SLB-EXT default: Static (0). IP mode. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ip","mode","network"]},{"code":"$302","name":"IP address","desc":"SLB-EXT default: 192.168.5.1. Static IP address. ~Controller reset required for setting change to take effect~","keywords":["address","ethernet","ip","network"]},{"code":"$303","name":"Gateway","desc":"SLB-EXT default: 192.168.5.1. Static gateway address. ~Controller reset required for setting change to take effect~","keywords":["ethernet","gateway","ip","network"]},{"code":"$304","name":"Netmask","desc":"SLB-EXT default: 255.255.255.0. Static netmask. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ip","netmask","network"]},{"code":"$305","name":"Telnet port","desc":"SLB-EXT default: 23. (Raw) Telnet port number listening for incoming connections. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ip","network","port","telnet"]},{"code":"$307","name":"Websocket port","desc":"SLB-EXT default: 80. Websocket port number listening for incoming connections. NOTE: WebUI requires this to be HTTP port number + 1. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ip","network","port","websocket"]},{"code":"$308","name":"FTP port","desc":"SLB-EXT default: 21. FTP port number listening for incoming connections. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ftp","ip","network","port"]},{"code":"$338","name":"Trinamic driver","desc":"SLB-EXT default: X: ON Y: ON Z: ON A: OFF (7). Enable SPI or UART controlled Trinamic drivers for axes.","keywords":["driver","ethernet","ip","motor","network","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$339","name":"Sensorless homing","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Enable sensorless homing for axes. Requires SPI or UART controlled Trinamic drivers.","keywords":["driver","ethernet","homing","ip","motor","network","sensorless","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$340","name":"Spindle at speed tolerance","desc":"SLB-EXT default: 0 percent. Spindle at speed tolerance as percentage deviation from programmed speed, set to 0 to disable. If not within tolerance when checked after spindle on delay ($392) alarm 14 is raised.","keywords":["speed","spindle","tolerance"]},{"code":"$341","name":"Tool change mode","desc":"SLB-EXT default: Normal (0). Normal: allows jogging for manual touch off. Set new position manually. Manual touch off: retracts tool axis to home position for tool change, use jogging or $TPW for touch off. Manual touch off @ G59.3: retracts tool axis to home position then to G59.3 position for tool change, use jogging or $TPW for touch off. Automatic touch off @ G59.3: retracts tool axis to home position for tool change, then to G59.3 position for automatic touch off. All modes except \"Normal\" and \"Ignore M6\" returns the tool (controlled point) to original position after touch off.","keywords":["change","mode","probe","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$342","name":"Tool change probing distance","desc":"SLB-EXT default: 30 mm. Maximum probing distance for automatic or $TPW touch off.","keywords":["change","distance","probe","probing","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$343","name":"Tool change locate feed rate","desc":"SLB-EXT default: 25 mm/min. Feed rate to slowly engage tool change sensor to determine the tool offset accurately.","keywords":["change","feed","locate","probe","rate","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$344","name":"Tool change search seek rate","desc":"SLB-EXT default: 200 mm/min. Seek rate to quickly find the tool change sensor before the slower locating phase.","keywords":["change","probe","rate","search","seek","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$345","name":"Tool change probe pull-off rate","desc":"SLB-EXT default: 200 mm/min. Pull-off rate for the retract move before the slower locating phase.","keywords":["change","off","probe","pull","rate","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$346","name":"Restore position after M6","desc":"SLB-EXT default: Enabled (1). When set the spindle is moved so that the controlled point (tool tip) is the same as before the M6 command, if not the spindle is only moved to the Z home position.","keywords":["after","position","probe","restore","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$347","name":"Dual axis length fail","desc":"(percent) Dual axis length fail in percent of axis max travel.","keywords":["dual","axis","length","fail"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$348","name":"Dual axis length fail min","desc":"(mm) Dual axis length fail minimum distance.","keywords":["dual","axis","length","fail","min"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$349","name":"Dual axis length fail max","desc":"(mm) Dual axis length fail maximum distance.","keywords":["dual","axis","length","fail","max"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$370","name":"Invert I/O Port inputs","desc":"SLB-EXT default: (0). Invert IOPort inputs.","keywords":["inputs","invert","port"]},{"code":"$372","name":"Invert I/O Port outputs","desc":"SLB-EXT default: (0). Invert IOPort output.","keywords":["invert","outputs","port"]},{"code":"$374","name":"Modbus baud rate","desc":"SLB-EXT default: 19200 (3).","keywords":["baud","modbus","rate","rs485","vfd"]},{"code":"$375","name":"Modbus RX timeout","desc":"SLB-EXT default: 50 milliseconds.","keywords":["modbus","rs485","timeout","vfd"]},{"code":"$376","name":"Rotational axes","desc":"SLB-EXT default: A-Axis: ON (1).","keywords":["axes","rotational"]},{"code":"$384","name":"Disable G92 persistence","desc":"SLB-EXT default: Disabled (0). Disables save/restore of G92 offset to non-volatile storage (NVS).","keywords":["disable","persistence"]},{"code":"$392","name":"Spindle on delay","desc":"SLB-EXT default: 11 s. Delay to allow spindle to spin up after safety door is opened.","keywords":["delay","spindle"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$393","name":"Coolant on delay","desc":"SLB-EXT default: 1 s. Delay to allow coolant to restart after safety door is opened.","keywords":["coolant","delay"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$394","name":"Spindle off delay (s)","desc":"grblHAL: pause after M5 — spin-down time.","keywords":["spindle","delay","spindown","off delay"]},{"code":"$395","name":"Default spindle","desc":"SLB-EXT default: SLB_SPINDLE (0). Spindle selected on startup.","keywords":["default","laser","spindle"]},{"code":"$398","name":"Planner buffer blocks","desc":"SLB-EXT default: 128. Number of blocks in the planner buffer. ~Controller reset required for setting change to take effect~","keywords":["blocks","buffer","planner"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$399","name":"CAN bus baud rate","desc":"CAN bus baud rate","keywords":["can","bus","baud","rate"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$450","name":"Button 1 action","desc":"SLB-EXT default: Cycle start (1). Assign a real-time action to button 1, or run your own macro g-code.","keywords":["action","button","macro"]},{"code":"$451","name":"Button 2 action","desc":"SLB-EXT default: Pause (2). Assign a real-time action to button 2, or run your own macro g-code.","keywords":["action","button","macro"]},{"code":"$452","name":"Button 3 action","desc":"SLB-EXT default: Halt (4). Assign a real-time action to button 3, or run your own macro g-code.","keywords":["action","button","macro"]},{"code":"$453","name":"Button 1 macro","desc":"SLB-EXT default: G4P0. Macro content, limited to 127 characters. Separate lines with the vertical bar character |.","keywords":["action","button","macro"]},{"code":"$454","name":"Button 2 macro","desc":"SLB-EXT default: G4P0. Macro content, limited to 127 characters. Separate lines with the vertical bar character |.","keywords":["action","button","macro"]},{"code":"$455","name":"Button 3 macro","desc":"SLB-EXT default: G4P0. Macro content, limited to 127 characters. Separate lines with the vertical bar character |.","keywords":["action","button","macro"]},{"code":"$456","name":"Aux output 0 trigger","desc":"SLB-EXT default: Spindle/Laser enable (0). A second, more common action can be assigned to trigger this output. M62/63 P# is always available as a buffered on/off or M64/65 P# as an immediate on/off.","keywords":["action","aux","button","macro","output","trigger"]},{"code":"$457","name":"Aux output 1 trigger","desc":"SLB-EXT default: Flood enable (2). A second, more common action can be assigned to trigger this output. M62/63 P# is always available as a buffered on/off or M64/65 P# as an immediate on/off.","keywords":["action","aux","button","macro","output","trigger"]},{"code":"$458","name":"Aux output 2 trigger","desc":"SLB-EXT default: Spindle/Laser enable (0). A second, more common action can be assigned to trigger this output. M62/63 P# is always available as a buffered on/off or M64/65 P# as an immediate on/off.","keywords":["action","aux","button","macro","output","trigger"]},{"code":"$459","name":"Aux output 3 trigger","desc":"SLB-EXT default: Flood enable (2). A second, more common action can be assigned to trigger this output. M62/63 P# is always available as a buffered on/off or M64/65 P# as an immediate on/off.","keywords":["action","aux","button","macro","output","trigger"]},{"code":"$462","name":"Run/stop register","desc":"SLB-EXT default: 8192 decimal. MODVFD register for run/stop.","keywords":["modbus","register","rs485","run","stop","vfd"]},{"code":"$463","name":"Frequency set register","desc":"SLB-EXT default: 8193 decimal. MODVFD register to set frequency.","keywords":["frequency","modbus","register","rs485","set","vfd"]},{"code":"$464","name":"Frequency get register","desc":"SLB-EXT default: 8451 decimal. MODVFD register to get frequency.","keywords":["frequency","get","modbus","register","rs485","vfd"]},{"code":"$465","name":"Run CW command","desc":"SLB-EXT default: 18 decimal. MODVFD command word for CW.","keywords":["command","modbus","rs485","run","vfd"]},{"code":"$466","name":"Run CCW command","desc":"SLB-EXT default: 34 decimal. MODVFD command word for CCW.","keywords":["ccw","command","modbus","rs485","run","vfd"]},{"code":"$467","name":"Stop command","desc":"SLB-EXT default: 1 decimal. MODVFD command word for stop.","keywords":["command","modbus","rs485","stop","vfd"]},{"code":"$468","name":"RPM input multiplier","desc":"SLB-EXT default: 50. MODVFD RPM value multiplier for programming RPM.","keywords":["input","modbus","multiplier","rpm","rs485","vfd"]},{"code":"$469","name":"RPM input divider","desc":"SLB-EXT default: 60. MODVFD RPM value divider for programming RPM.","keywords":["divider","input","modbus","rpm","rs485","vfd"]},{"code":"$470","name":"RPM output multiplier","desc":"SLB-EXT default: 60. MODVFD RPM value multiplier for reading RPM.","keywords":["modbus","multiplier","output","rpm","rs485","vfd"]},{"code":"$471","name":"RPM output divider","desc":"SLB-EXT default: 100. MODVFD RPM value divider for reading RPM.","keywords":["divider","modbus","output","rpm","rs485","vfd"]},{"code":"$478","name":"Spindle 2 Modbus address","desc":"SLB-EXT default: 3. Spindle 2 Modbus address.","keywords":["address","modbus","rs485","spindle","vfd"]},{"code":"$479","name":"Spindle 3 Modbus address","desc":"SLB-EXT default: 4. Spindle 3 Modbus address.","keywords":["address","modbus","rs485","spindle","vfd"]},{"code":"$481","name":"Autoreport interval","desc":"SLB-EXT default: 0 ms. Interval the real time report will be sent, set to 0 to disable. ~Controller reset required for setting change to take effect~","keywords":["autoreport","interval"]},{"code":"$482","name":"Timezone offset","desc":"Offset in hours from UTC.","keywords":["timezone","offset"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$484","name":"Unlock required after E-stop","desc":"SLB-EXT default: Enabled (1). If set, unlock (by sending $X) is required after resetting a cleared E-Stop condition.","keywords":["after","required","stop","unlock"]},{"code":"$485","name":"Keep tool number over reboot","desc":"Keep tool number over reboot","keywords":["keep","tool","number","over","reboot"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$486","name":"Lock coordinate systems","desc":"SLB-EXT default: G59.1: OFF G59.2: OFF G59.3: OFF (0). Lock coordinate systems against accidental changes.","keywords":["coordinate","lock","systems"]},{"code":"$487","name":"PWM2 spindle on port","desc":"On/off aux port.","keywords":["pwm","spindle","port"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$488","name":"PWM2 spindle direction port","desc":"Direction aux port, set to -1 if not required.","keywords":["pwm","spindle","direction","port"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$489","name":"PWM2 spindle PWM port","desc":"Spindle analog aux port. Must be PWM capable!","keywords":["pwm","spindle","port"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$511","name":"Spindle 1","desc":"SLB-EXT default: SLB_LASER (7). Spindle to use as spindle 1. ~Controller reset required for setting change to take effect~","keywords":["laser","spindle"]},{"code":"$512","name":"Spindle 2","desc":"SLB-EXT default: MODVFD (5). Spindle to use as spindle 2. ~Controller reset required for setting change to take effect~","keywords":["laser","spindle"]},{"code":"$513","name":"Spindle 3","desc":"SLB-EXT default: Disabled (8). Spindle to use as spindle 3. ~Controller reset required for setting change to take effect~","keywords":["laser","spindle"]},{"code":"$519","name":"Encoder spindle","desc":"Specifies which spindle has the encoder attached.","keywords":["encoder","spindle"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$520","name":"Spindle 0 tool number start","desc":"SLB-EXT default: 0. Start of tool numbers for selecting spindle 0 (default spindle). Normally leave this at 0.","keywords":["laser","number","spindle","start","tool"]},{"code":"$521","name":"Spindle 1 tool number start","desc":"SLB-EXT default: 0. Start of tool numbers for selecting spindle 1.","keywords":["laser","number","spindle","start","tool"]},{"code":"$522","name":"Spindle 2 tool number start","desc":"SLB-EXT default: 0. Start of tool numbers for selecting spindle 2.","keywords":["laser","number","spindle","start","tool"]},{"code":"$523","name":"Spindle 3 tool number start","desc":"SLB-EXT default: 0. Start of tool numbers for selecting spindle 3.","keywords":["laser","number","spindle","start","tool"]},{"code":"$534","name":"Output NGC debug messages","desc":"Example: (debug, metric mode: #<_metric>, coord system: #5220)","keywords":["output","ngc","debug","messages"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$536","name":"LED strip 1 length","desc":"Number of LEDS in strip 1.","keywords":["led","strip","length"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$537","name":"LED strip 2 length","desc":"Number of LEDS in strip 2.","keywords":["led","strip","length"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$538","name":"Fast rotary go to G28","desc":"Fast rotary go to G28","keywords":["fast","rotary"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$539","name":"Spindle off delay","desc":"(s) Spindle off delay","keywords":["spindle","off","delay"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$650","name":"Chopper toff","desc":"SLB-EXT default: 1. Off time. Duration of slow decay phase as a multiple of system clock periods: NCLK= 24 + (32 x TOFF). This will limit the maximum chopper frequency (0-15). 0: MOSFETs shut off, driver disabled. 1: Use with TBL of minimum 24 clocks.","keywords":["chopper","toff"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$651","name":"Chopper tbl","desc":"SLB-EXT default: 1. Blanking time interval in system clock periods (0-3 = 16,24,36,54). Needs to cover the switching event and the duration of the ringing on the sense resistor.","keywords":["chopper","tbl"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$652","name":"Chopper chm","desc":"SLB-EXT default: 0. Chopper mode. Affects HDEC, HEND, and HSTRT parameters. 0: Standard mode (SpreadCycle). 1: Constant TOFF with fast decay time. Fast decay is after on time. Fast decay time is also terminated when the negative nominal current is reached.","keywords":["chm","chopper"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$653","name":"Chopper hstr","desc":"SLB-EXT default: 2. CHM=0: Hysteresis start, offset from HEND (0-7 = 1-8). To be effective, HEND+HSTRT must be ≤15. CHM=1: Fast decay time. Three least-significant bits of the duration of the fast decay phase. The MSB is HDEC0. Fast decay time is a multiple of system clock periods: NCLK= 32 x (HDEC0+HSTRT).","keywords":["chopper","hstr"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$654","name":"Chopper hend","desc":"SLB-EXT default: 8. Can be either negative, zero, or positive, 0-15 = -3 to 12. CHM=0: Hysteresis end (low). Sets the hysteresis end value after a number of decrements, used for the hysteresis chopper and controlled by HDEC. HSTRT+HEND must be less than 16. 1/512 adds to the current setting. CHM=1: Sine wave offset. A positive offset corrects for zero crossing error. 1/512 adds to the absolute value of each sine wave entry.","keywords":["chopper","hend"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$655","name":"Chopper hdec","desc":"SLB-EXT default: 0. CHM=0: Hysteresis decrement interval period in system clock periods. Determines the slope of the hysteresis during on time from fast to very slow (0-3 = 16,32,48,64). CHM=1: Fast decay mode.","keywords":["chopper","hdec"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$656","name":"Chopper rndtf","desc":"SLB-EXT default: 1. Change from fixed to randomized TOFF times, by dNCLK= -24 to +6 clocks. Only for CHM=1.","keywords":["chopper","rndtf"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$657","name":"THRESH","desc":"SLB-EXT default: 22. StallGuard threshold.","keywords":["thresh"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$658","name":"CoolStep semin","desc":"SLB-EXT default: 7. Lower CoolStep threshold. If the SG value falls below SEMIN x 32, the coil current scaling factor is increased (0-15). 0: CoolStep disabled.","keywords":["coolstep","semin"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$659","name":"CoolStep seup","desc":"SLB-EXT default: 3. Number of increments of the coil current each time SG is sampled below the lower threshold (0-3 = 1,2,4,8).","keywords":["coolstep","seup"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$660","name":"CoolStep semax","desc":"SLB-EXT default: 0. Upper CoolStep threshold offset from lower threshold. If SG is sampled above (SEMIN+SEMAX+1)x32 enough times, the coil current scaling factor is decremented (0-15).","keywords":["coolstep","semax"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$661","name":"CoolStep sedn","desc":"SLB-EXT default: 3. Number of times SG must be sampled above the upper threshold before the coil current is decremented (0-3 = 32,8,2,1).","keywords":["coolstep","sedn"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$662","name":"CoolStep seimin","desc":"SLB-EXT default: 0. Minimum CoolStep current as a factor of the set motor current. 0: 1/2, 1: 1/4","keywords":["coolstep","seimin"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$663","name":"drvconf_reg","desc":"SLB-EXT default: 41759. DRVCONF register defaults 0xA31F. All protections enabled.","keywords":["drvconf","reg"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$664","name":"Ring pixels","desc":"SLB-EXT default: 0. Number of individual pixels or LEDs connected. ~Controller reset required for setting change to take effect~","keywords":["led","lights","pixels","ring"]},{"code":"$665","name":"Rail pixels","desc":"SLB-EXT default: 1. Number of individual pixels or LEDs connected. Include the onboard LED. ~Controller reset required for setting change to take effect~","keywords":["led","lights","pixels","rail"]},{"code":"$666","name":"Using add-ons","desc":"SLB-EXT default: (0). Sienci specific capability flags.","keywords":["add","ons","using"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$668","name":"Invert TLS input","desc":"SLB-EXT default: Enabled (1). Invert the TLS input ahead of the OR function. ~Controller reset required for setting change to take effect~","keywords":["input","invert","tls"]},{"code":"$671","name":"Invert home inputs","desc":"Inverts the axis home input signals.","keywords":["invert","home","inputs"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$673","name":"Coolant on delay","desc":"(s) Delay to allow coolant to start. 0 or 0.5 - 20s.","keywords":["coolant","delay"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$676","name":"Reset actions","desc":"Controls actions taken on a soft reset.","keywords":["reset","actions"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$680","name":"Stepper enable delay","desc":"(ms) Delay from stepper enable to first step output. The driver typically adds ~2ms to this.","keywords":["stepper","enable","delay"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$681","name":"ModBus serial format","desc":"ModBus serial format","keywords":["modbus","serial","format"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$700","name":"Subroutine options","desc":"Enable prescan for internal M98 subroutines.","keywords":["subroutine","options"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$709","name":"PWM2 spindle options","desc":"Options for the secondary PWM spindle output (PWM2, the SLB-EXT laser channel).","keywords":["laser","options","pwm","pwm2","spindle"]},{"code":"$716","name":"PWM2 spindle signals invert","desc":"Inverts the PWM2 (laser) enable, counterclockwise and PWM signals (active low). Hard reset required after changing.","keywords":["invert","laser","pwm","pwm2","signals","spindle"],"tips":"On older SLB 5.0.x firmware this lived at $743 (Invert laser signals)."},{"code":"$730","name":"Maximum laser power","desc":"SLB-EXT default: 255. Maximum S word power for laser.","keywords":["laser","maximum","power","pwm"]},{"code":"$731","name":"Minimum laser power","desc":"SLB-EXT default: 0. Minimum S word power for laser.","keywords":["laser","minimum","power","pwm"]},{"code":"$733","name":"Laser PWM frequency","desc":"SLB-EXT default: 1000 Hz. Laser PWM frequency.","keywords":["frequency","laser","pwm"]},{"code":"$734","name":"Laser PWM off value","desc":"SLB-EXT default: 0 percent. Laser PWM off value in percent (duty cycle).","keywords":["laser","off","pwm","value"]},{"code":"$735","name":"Laser PWM min value","desc":"SLB-EXT default: 0 percent. Laser PWM min value in percent (duty cycle).","keywords":["laser","min","pwm","value"]},{"code":"$736","name":"Laser PWM max value","desc":"SLB-EXT default: 100 percent. Laser PWM max value in percent (duty cycle).","keywords":["laser","max","pwm","value"]},{"code":"$737","name":"PWM2 spindle linearisation, 1st point","desc":"Comma separated list of values: RPM_MIN, RPM_LINE_A1, RPM_LINE_B1, set to blank to disable.","keywords":["pwm","spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$738","name":"PWM2 spindle linearisation, 2nd point","desc":"Comma separated list of values: RPM_POINT12, RPM_LINE_A2, RPM_LINE_B2, set to blank to disable.","keywords":["pwm","spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$739","name":"PWM2 spindle linearisation, 3rd point","desc":"Comma separated list of values: RPM_POINT23, RPM_LINE_A3, RPM_LINE_B3, set to blank to disable.","keywords":["pwm","spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$740","name":"PWM2 spindle linearisation, 4th point","desc":"Comma separated list of values: RPM_POINT34, RPM_LINE_A4, RPM_LINE_B4, set to blank to disable.","keywords":["pwm","spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$742","name":"Motor warning inputs enable","desc":"Enables the external stepper driver warning inputs per motor (SLB-EXT external drivers report warnings before faulting).","keywords":["alarm","driver","enable","fault","inputs","motor","warning"],"tips":"Current Main_grblHAL numbering. On older SLB 5.0.x firmware $742 was the Laser Y offset - that is now $771."},{"code":"$743","name":"Invert motor warning inputs","desc":"Inverts the motor warning input signals (active low).","keywords":["alarm","driver","fault","inputs","invert","motor","warning"],"tips":"On older SLB 5.0.x firmware $743 was Invert laser signals - that is now $716."},{"code":"$744","name":"Motor fault inputs enable","desc":"Enables the external stepper driver fault/alarm inputs per motor. A fault triggers an alarm and halts the machine.","keywords":["alarm","driver","enable","fault","inputs","motor"]},{"code":"$745","name":"Invert motor fault inputs","desc":"Inverts the motor fault input signals (active low).","keywords":["alarm","driver","fault","inputs","invert","motor"]},{"code":"$750","name":"Macro 0 content","desc":"G-code for aux-input macro 0. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $760) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$751","name":"Macro 1 content","desc":"G-code for aux-input macro 1. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $761) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$752","name":"Macro 2 content","desc":"G-code for aux-input macro 2. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $762) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$753","name":"Macro 3 content","desc":"G-code for aux-input macro 3. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $763) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$754","name":"Macro 4 content","desc":"G-code for aux-input macro 4. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $764) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$755","name":"Macro 5 content","desc":"G-code for aux-input macro 5. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $765) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$756","name":"Macro 6 content","desc":"G-code for aux-input macro 6. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $766) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$757","name":"Macro 7 content","desc":"G-code for aux-input macro 7. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $767) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$758","name":"Macro 8 content","desc":"G-code for aux-input macro 8. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $768) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$759","name":"Macro 9 content","desc":"G-code for aux-input macro 9. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $769) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$760","name":"Macro 0 trigger port","desc":"Aux input port number that triggers macro 0 (content in $750). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$761","name":"Macro 1 trigger port","desc":"Aux input port number that triggers macro 1 (content in $751). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$762","name":"Macro 2 trigger port","desc":"Aux input port number that triggers macro 2 (content in $752). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$763","name":"Macro 3 trigger port","desc":"Aux input port number that triggers macro 3 (content in $753). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$764","name":"Macro 4 trigger port","desc":"Aux input port number that triggers macro 4 (content in $754). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$765","name":"Macro 5 trigger port","desc":"Aux input port number that triggers macro 5 (content in $755). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$766","name":"Macro 6 trigger port","desc":"Aux input port number that triggers macro 6 (content in $756). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$767","name":"Macro 7 trigger port","desc":"Aux input port number that triggers macro 7 (content in $757). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$768","name":"Macro 8 trigger port","desc":"Aux input port number that triggers macro 8 (content in $758). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$769","name":"Macro 9 trigger port","desc":"Aux input port number that triggers macro 9 (content in $759). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$770","name":"Laser X offset","desc":"Laser offset from the spindle on the X axis, applied when switching between spindle and laser so files stay aligned. Pairs with gSender Spindle/Laser offset settings.","keywords":["alignment","laser","offset","pwm"],"tips":"Moved here in Main_grblHAL firmware - older SLB 5.0.x used $741."},{"code":"$771","name":"Laser Y offset","desc":"Laser offset from the spindle on the Y axis.","keywords":["alignment","laser","offset","pwm"],"tips":"Moved here in Main_grblHAL firmware - older SLB 5.0.x used $742."},{"code":"$772","name":"Laser offset options","desc":"Options controlling how the laser/spindle XY offset ($770/$771) is applied.","keywords":["laser","offset","options","pwm"]}],"system":[{"code":"$$","name":"View settings","desc":"Prints every numbered setting and its current value.","keywords":["settings","list","view","dump"]},{"code":"$#","name":"View G-code parameters","desc":"Shows WCS offsets (G54-G59.3), G28/G30 positions, G92 offset, tool length offset and last probe result (PRB).","keywords":["parameters","offsets","probe result","wcs","prb"]},{"code":"$G","name":"View parser state","desc":"Shows the active modal G-codes (motion mode, WCS, plane, units, distance mode...), plus current T, F and S.","keywords":["parser","state","modal","active modes"]},{"code":"$I","name":"Build info","desc":"Prints the firmware build/version string and enabled options.","keywords":["build","version","info","firmware"]},{"code":"$N","name":"View startup blocks","desc":"Shows the G-code lines run automatically at startup ($N0=, $N1= to set).","keywords":["startup","blocks","boot"]},{"code":"$X","name":"Kill alarm lock","desc":"Unlocks the machine from an alarm state without homing. Position may be unknown afterward — use with caution.","keywords":["unlock","alarm","kill","reset alarm"]},{"code":"$H","name":"Run homing cycle","desc":"Homes all configured axes per $22/$44-$47. $HX / $HY / $HZ home a single axis (grblHAL). Note: with the Rapid Change ATC or Manual Tool Changer plugin installed and \"perform TLS after home\" enabled, the plugin expands $H so that after homing, if a tool is loaded but has no length offset yet, an automatic $TLS probe cycle runs.","keywords":["home","homing","cycle","tls after home"]},{"code":"$J=","name":"Jog","desc":"Executes a jog move, e.g. $J=G91 X10 F1000. Jogs don't alter the G-code parser state and can be cancelled instantly (0x85).","keywords":["jog","jogging","move","manual"]},{"code":"$SLP","name":"Sleep","desc":"Puts the controller to sleep (steppers and spindle off). Wake with a soft reset. Requires $62=1.","keywords":["sleep","power down"]},{"code":"$TLR","name":"Set tool length reference","desc":"Tool change protocol: records the current tool offset as the job's reference after probing the first tool.","keywords":["tool length","reference","toolsetter","tool change"]},{"code":"$TPW","name":"Tool probe workpiece","desc":"Tool change protocol: probes the new tool to compute its dynamic offset. Available in tool change modes 1 and 2.","keywords":["tool probe","toolsetter","tool change"]},{"code":"$EA","name":"Enumerate alarms","desc":"Lists every alarm code with its description — decode alarm numbers here.","keywords":["alarms","codes","enumerate","list"]},{"code":"$EE","name":"Enumerate errors","desc":"Lists every error code with its description — decode error:NN messages here.","keywords":["errors","codes","enumerate","list"]},{"code":"$ES","name":"Enumerate settings","desc":"Lists every setting the build supports with type, range, unit and description — the authoritative settings reference for YOUR controller.","keywords":["settings","enumerate","describe","list"]},{"code":"$EG","name":"Enumerate setting groups","desc":"Lists the hierarchy of setting groups.","keywords":["groups","settings","enumerate"]},{"code":"$pins","name":"Enumerate pins","desc":"Lists processor pin assignments — which MCU pin does what.","keywords":["pins","mapping","enumerate"]},{"code":"$pinstate","name":"Pin states","desc":"Shows the live state of auxiliary pins — great for debugging wiring.","keywords":["pins","state","debug","aux"]},{"code":"$SPINDLES","name":"Enumerate spindles","desc":"Lists configured spindles and their numbers (for M104 P selection on multi-spindle setups).","keywords":["spindles","enumerate","list","dual spindle"]},{"code":"$F","name":"List files","desc":"Lists G-code files in the current directory on SD/LittleFS. $F+ lists all files; $F=<file> runs one; $FD=<file> deletes; $FM/$FU mount/unmount; $CWD= changes directory; $PWD prints it.","keywords":["files","sd card","list","run file","littlefs"]},{"code":"$RST","name":"Restore defaults","desc":"$RST=$ restores settings to defaults, $RST=# clears WCS/G28/G30 offsets, $RST=* resets everything. Irreversible — note your settings first.","keywords":["reset","restore","defaults","factory"]},{"code":"$REBOOT","name":"Reboot controller","desc":"Hard-resets the controller. The connection drops.","keywords":["reboot","restart","reset"]},{"code":"$TTLOAD","name":"Reload tool table","desc":"Reloads the tool table from storage.","keywords":["tool table","reload"]}],"letters":{"X":"X-axis coordinate/value","Y":"Y-axis coordinate/value","Z":"Z-axis coordinate/value","A":"A-axis (rotary) value","B":"B-axis value","C":"C-axis value","U":"U-axis value","V":"V-axis value","F":"Feed rate (modal — persists until changed)","S":"Spindle speed / laser power (used by M3/M4)","T":"Tool select (pre-selects for M6)","I":"Arc center offset from start, X direction","J":"Arc center offset from start, Y direction","K":"Arc center offset from start, Z direction","R":"Radius, or retract plane in canned cycles","P":"Parameter: dwell seconds, WCS/port/macro number (command-dependent)","Q":"Parameter: peck depth, value, tool number (command-dependent)","L":"Parameter: repeat count or data mode (command-dependent)","H":"Tool table index for length offset (G43)","D":"Parameter: max RPM cap (G96) or tool radius index","N":"Line number (ignored by execution)","E":"Analog port (plugin M-codes)","O":"Program label / subroutine number","W":"W-axis value, or white channel (M150)"},"initialTab":"reference","initialQuery":"","initialExplain":"","maxResults":8,"showSettingsTab":true} is replaced with the JSON data
bundle (database + initial state) either at plugin build time
(config.html) or at dialog-open time (commands.js). -->
<style>
.gref { font-family: system-ui, -apple-system, sans-serif;
color: var(--color-text-primary, #e8eaed);
display: flex; flex-direction: column;
/* dynamic with the window, capped so the category chips settle
into two rows maximum (top row wider than bottom). 960px is a
fallback - at boot the script measures the first 8 rendered
chips and pins max-width to exactly that row, so the cap
tracks the host app's real button sizing. Narrower windows
wrap chips onto more rows responsively. */
width: 92vw; max-width: 960px;
height: 75vh; min-height: 420px;
overflow-x: hidden; }
.gref * { box-sizing: border-box; }
.gref code, .gref .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
/* --- header: search --- */
.gref-head { padding: 12px 16px; border-bottom: 1px solid var(--color-border, #333a45);
display: flex; flex-direction: column; gap: 8px; }
.gref-search { width: 100%; padding: 10px 12px; font-size: 0.95rem;
background: var(--color-surface-muted, #232a33); color: var(--color-text-primary, #e8eaed);
border: 1px solid var(--color-border, #333a45); border-radius: var(--radius-small, 6px); }
.gref-search:focus { outline: none; border-color: var(--color-accent, #10b981); }
.gref-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.gref-chip { padding: 3px 10px; font-size: 0.75rem; border-radius: 999px;
border: 1px solid var(--color-border, #333a45); background: transparent;
color: var(--color-text-secondary, #9aa4b2); cursor: pointer; }
.gref-chip.active { background: var(--color-accent, #10b981); border-color: var(--color-accent, #10b981); color: #fff; }
/* --- results --- */
.gref-body { flex: 1; overflow-y: auto; padding: 16px; }
.gref-count { font-size: 0.75rem; color: var(--color-text-secondary, #9aa4b2); margin-bottom: 8px; }
.gref-card { border: 1px solid var(--color-border, #333a45); border-radius: var(--radius-small, 6px);
margin-bottom: 8px; background: var(--color-surface-muted, #232a33); overflow: hidden; }
.gref-card-head { display: flex; align-items: center; gap: 8px;
padding: 10px 12px; cursor: pointer; user-select: none; }
.gref-card-head:hover { background: var(--color-surface, #1a2027); }
.gref-codechip { font-family: ui-monospace, Menlo, Consolas, monospace; font-weight: 700;
font-size: 0.85rem; color: var(--color-accent, #10b981);
background: var(--color-surface, #1a2027); border: 1px solid var(--color-border, #333a45);
padding: 2px 8px; border-radius: var(--radius-small, 6px); white-space: nowrap; }
.gref-name { flex: 1; font-size: 0.9rem; }
.gref-badge { font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.05em;
color: var(--color-text-secondary, #9aa4b2); border: 1px solid var(--color-border, #333a45);
padding: 1px 7px; border-radius: 999px; white-space: nowrap; }
.gref-caret { color: var(--color-text-secondary, #9aa4b2); font-size: 0.7rem; transition: transform 0.15s; }
.gref-card.open .gref-caret { transform: rotate(90deg); }
.gref-detail { display: none; padding: 0 12px 12px; font-size: 0.85rem; line-height: 1.5; }
.gref-card.open .gref-detail { display: block; }
.gref-detail p { margin: 8px 0; }
.gref-label { font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.06em;
color: var(--color-text-secondary, #9aa4b2); margin: 10px 0 4px; }
.gref-pre { background: var(--color-surface, #1a2027); border: 1px solid var(--color-border, #333a45);
border-radius: var(--radius-small, 6px); padding: 8px 10px; margin: 4px 0;
font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.8rem;
white-space: pre-wrap; overflow-x: auto; }
.gref-params { width: 100%; border-collapse: collapse; margin: 4px 0; font-size: 0.8rem; }
.gref-params td { padding: 4px 8px; border-top: 1px solid var(--color-border, #333a45); vertical-align: top; }
.gref-params td:first-child { font-family: ui-monospace, Menlo, Consolas, monospace;
font-weight: 700; color: var(--color-accent, #10b981); width: 3.5em; }
.gref-tip { border-left: 3px solid var(--color-accent, #10b981); padding: 6px 10px; margin: 8px 0;
background: var(--color-surface, #1a2027); border-radius: 0 var(--radius-small, 6px) var(--radius-small, 6px) 0;
color: var(--color-text-secondary, #9aa4b2); font-size: 0.8rem; }
.gref-empty { text-align: center; color: var(--color-text-secondary, #9aa4b2); padding: 40px 20px; font-size: 0.9rem; }
.gref-settings { flex: 1; overflow-y: auto; padding: 12px 0; display: none; }
.gcfg { font-family: system-ui, -apple-system, sans-serif;
color: var(--color-text-primary, #e8eaed); }
.gcfg-card { border: 1px solid var(--color-border, #333a45);
border-radius: var(--radius-small, 6px);
background: var(--color-surface-muted, #232a33);
padding: 14px 16px; margin: 0 16px 12px; }
.gcfg-title { font-weight: 600; font-size: 0.9rem; margin-bottom: 8px; }
.gcfg-row { display: flex; align-items: center; gap: 10px; margin: 10px 0; font-size: 0.9rem; }
.gcfg-hint { color: var(--color-text-secondary, #9aa4b2); font-size: 0.78rem; margin: 2px 0 0 26px; }
.gcfg input[type="number"] { width: 90px !important; padding: 6px 8px; }
.gcfg code { font-family: ui-monospace, Menlo, Consolas, monospace;
background: var(--color-surface, #1a2027); border: 1px solid var(--color-border, #333a45);
padding: 1px 5px; border-radius: 4px; font-size: 0.8em; }
.gcfg-status { font-size: 0.75rem; color: var(--color-accent, #10b981); min-height: 1em; margin-left: 26px; }
/* --- explain tab --- */
.gref-exwrap { display: flex; flex-direction: column; gap: 8px; min-height: 100%; }
.gref-exinput { width: 100%; resize: vertical; padding: 10px 12px;
font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.85rem;
background: var(--color-surface-muted, #232a33); color: var(--color-text-primary, #e8eaed);
border: 1px solid var(--color-border, #333a45); border-radius: var(--radius-small, 6px); }
.gref-btn { align-self: flex-start; padding: 8px 20px; border: none; cursor: pointer;
background: var(--color-accent, #10b981); color: #fff; font-size: 0.85rem;
border-radius: var(--radius-small, 6px); }
.gref-exline { border: 1px solid var(--color-border, #333a45); border-radius: var(--radius-small, 6px);
background: var(--color-surface-muted, #232a33); margin-bottom: 8px; }
.gref-exline-src { padding: 8px 12px; border-bottom: 1px solid var(--color-border, #333a45);
font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.85rem;
color: var(--color-accent, #10b981);
white-space: pre-wrap; overflow-wrap: anywhere; }
.gref-exline-words { padding: 4px 0; }
.gref-word { display: flex; gap: 10px; padding: 5px 12px; font-size: 0.83rem; align-items: baseline; }
.gref-word + .gref-word { border-top: 1px dashed var(--color-border, #333a45); }
.gref-word-tok { font-family: ui-monospace, Menlo, Consolas, monospace; font-weight: 700;
min-width: 5.5em; color: var(--color-accent, #10b981); }
.gref-word-desc { flex: 1; color: var(--color-text-primary, #e8eaed); }
.gref-word-desc .sub { color: var(--color-text-secondary, #9aa4b2); }
.gref-word.unknown .gref-word-tok { color: var(--color-text-secondary, #9aa4b2); }
.gref-foot { padding: 8px 16px; border-top: 1px solid var(--color-border, #333a45);
font-size: 0.72rem; color: var(--color-text-secondary, #9aa4b2); }
.gref-foot code { background: var(--color-surface-muted, #232a33); padding: 1px 5px;
border-radius: 4px; border: 1px solid var(--color-border, #333a45); }
</style>
<div class="gref" id="gref-root">
<div class="gref-tabsbar" style="display:flex;gap:6px;padding:0 16px;border-bottom:1px solid var(--color-border, #333a45)">
<button class="gref-tab" id="gref-tab-reference" onclick="grefSwitchTab('reference')">
<span class="gref-tab-ic" style="display:inline-flex"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg></span>
<span>Reference</span>
</button>
<button class="gref-tab" id="gref-tab-explain" onclick="grefSwitchTab('explain')">
<span class="gref-tab-ic" style="display:inline-flex"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span>
<span>G-code</span>
</button>
<button class="gref-tab" id="gref-tab-navigator" onclick="grefSwitchTab('navigator')">
<span class="gref-tab-ic" style="display:inline-flex"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="3 11 22 2 13 21 11 13 3 11"/></svg></span>
<span>Explorer</span>
</button>
<button class="gref-tab" id="gref-tab-manual" onclick="grefSwitchTab('manual')">
<span class="gref-tab-ic" style="display:inline-flex"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg></span>
<span>NC Manual</span>
</button>
<button class="gref-tab" id="gref-tab-settings" style="display:none" onclick="grefSwitchTab('settings')">
<span class="gref-tab-ic" style="display:inline-flex"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span>
<span>Settings</span>
</button>
</div>
<div class="gref-head">
<div id="gref-panel-search">
<input class="gref-search" id="gref-search" type="text"
placeholder="Search: G38.2, $110, dwell, tool change, laser..."
autocomplete="off" spellcheck="false">
<div class="gref-chips" id="gref-chips" style="margin-top:8px"></div>
</div>
</div>
<div class="gref-settings" id="gref-settings">
<div class="gcfg">
<div class="gcfg-card">
<div class="gcfg-title">Terminal lookup</div>
<div class="gcfg-row">
<input type="checkbox" id="gcfg-terminal-lookup" style="width:auto !important">
<label for="gcfg-terminal-lookup" style="margin:0;font-weight:400">
Enable <code>?keyword</code> / <code>??line</code> in the Console
</label>
</div>
<div class="gcfg-hint">Typing <code>?dwell</code> or <code>??G1 X10 F500</code> opens documentation
instead of sending the text to the controller; <code>??</code> alone opens this reference unfiltered.
A bare <code>?</code> (status query) is never intercepted.
The dialog pauses command streaming while open, so avoid lookups mid-job.</div>
<div class="gcfg-status" id="gcfg-status"></div>
</div>
<div class="gcfg-card">
<div class="gcfg-title">About this reference</div>
<div style="font-size:0.83rem;line-height:1.55;color:var(--color-text-primary,#e8eaed)">
<p style="margin:6px 0"><b>Sources.</b> The documentation in this plugin is compiled from:</p>
<ul style="margin:4px 0 10px 18px;padding:0">
<li><a href="https://resources.sienci.com/view/slb-firmware-flashing/" target="_blank" rel="noopener" style="color:var(--color-accent,#10b981)">Sienci Labs SLB/SLB‑EXT firmware documentation</a> — the official settings tables, including SLB‑EXT factory defaults and Sienci’s “unused”/“advanced” notes.</li>
<li><a href="https://github.com/grblHAL/core" target="_blank" rel="noopener" style="color:var(--color-accent,#10b981)">grblHAL core source</a> — the canonical setting registry and descriptions for mainline (Main_grblHAL) builds, including settings the Sienci tables don’t cover and the current numbering (e.g. laser XY offset at $770/$771, formerly $741/$742 on SLB 5.0.x firmware).</li>
<li><a href="https://petervanderwalt.github.io/grblhal_docs/" target="_blank" rel="noopener" style="color:var(--color-accent,#10b981)">grblHAL community docs</a> — the complete G‑code and M‑code reference the command entries are based on.</li>
<li><a href="https://github.com/siganberg/ncSender" target="_blank" rel="noopener" style="color:var(--color-accent,#10b981)">ncSender</a> — the plugin API, and the <code>/api/firmware</code> endpoint (ncSender’s cache of your controller’s own <code>$ES</code>/<code>$$</code> enumeration) that powers the live “on this controller” check.</li>
<li><a href="https://plugins.octoprint.org/plugins/marlingcodedocumentation/" target="_blank" rel="noopener" style="color:var(--color-accent,#10b981)">OctoPrint Marlin G‑code Documentation</a> — the plugin that inspired this one.</li>
<li><a href="https://github.com/siganberg/ncsender-plugin-rapidchangeatc" target="_blank" rel="noopener" style="color:var(--color-accent,#10b981)">Rapid Change ATC</a>, <a href="https://github.com/siganberg/ncsender-plugin-manualtoolchanger" target="_blank" rel="noopener" style="color:var(--color-accent,#10b981)">Manual Tool Changer</a>, <a href="https://github.com/siganberg/ncsender-plugin-pneumaticatc" target="_blank" rel="noopener" style="color:var(--color-accent,#10b981)">Pneumatic ATC</a> and <a href="https://github.com/siganberg/ncsender-plugin-autodustboot" target="_blank" rel="noopener" style="color:var(--color-accent,#10b981)">AutoDustboot</a> plugin repositories — the source for the console commands documented under <em>Plugin codes</em> (<code>$TLS</code>, <code>$SLOT<n></code>, <code>$POCKET1</code>, <code>$ADB_RETRACT</code>/<code>$ADB_EXPAND</code>).</li>
</ul>
<p style="margin:6px 0"><b>Which controllers this applies to.</b> ncSender can drive both grblHAL and FluidNC machines; this reference is written for the grblHAL dialect:</p>
<ul style="margin:4px 0 6px 18px;padding:0">
<li><b>Sienci SLB / SLB‑EXT (grblHAL)</b> — fully covered. Defaults are labeled “SLB‑EXT default”, Sienci‑specific settings (button macros $450s, ring/rail LEDs $664/$665, spindle slots $511+) are included, and entries note where Main_grblHAL renumbered older SLB 5.0.x settings.</li>
<li><b>Other grblHAL boards</b> — core G/M‑codes and settings apply as documented; Sienci‑specific entries will simply be flagged “not on this controller” by the live check, since every grblHAL build only exposes the settings its features compile in.</li>
<li><b>FluidNC</b> — the basic G‑code entries (motion, coordinate systems, spindle/coolant M‑codes) largely apply since FluidNC descends from Grbl, but the numbered <code>$</code> settings do <b>not</b>: FluidNC is configured through a YAML file and <code>$/</code> tree commands instead. grblHAL extensions (G65 macros, M62–M68 I/O, canned cycles, plugin M‑codes, <code>$ES</code>) are unavailable there, and the live controller check will report “controller settings unavailable”.</li>
<li><b>Classic Grbl 1.1</b> — the $0–$132 settings and core G/M‑codes align; everything beyond that is grblHAL‑only.</li>
</ul>
<p style="margin:6px 0;color:var(--color-text-secondary,#9aa4b2)">The live check reads ncSender’s cached controller enumeration — after flashing new firmware, refresh ncSender’s Firmware tab once so the cache re‑queries, and this reference picks it up on next open.</p>
</div>
</div>
</div>
</div>
<div class="gref-manual" id="gref-manual" style="display:none;flex:1;flex-direction:column;min-height:0">
<div style="display:flex;align-items:center;gap:8px;padding:8px 16px;font-size:0.78rem;color:var(--color-text-secondary,#9aa4b2)">
<span>Browsing the official ncSender manual</span>
<span style="flex:1"></span>
<a href="https://siganberg.github.io/ncSender.manual/" target="_blank" rel="noopener"
style="color:var(--color-accent,#10b981);text-decoration:none">Open in new tab ↗</a>
</div>
<iframe id="gref-manual-frame" title="ncSender Manual"
style="flex:1;width:100%;border:0;border-top:1px solid var(--color-border,#333a45);background:#fff"></iframe>
</div>
<div class="gref-body" id="gref-body"></div>
<div id="gn-host" style="display:none;flex:1;min-height:0;min-width:0;overflow:hidden"></div>
<div class="gref-foot" id="gref-foot">
Terminal shortcuts: <code>?keyword</code> looks up docs (e.g. <code>?dwell</code>, <code>?$110</code>) ·
<code>??G1 X10 F500</code> explains a line word by word ·
<code>??</code> on its own opens this reference, unfiltered. Run <code>$ES</code> / <code>$EE</code> / <code>$EA</code> on the controller to enumerate everything your build supports.
</div>
</div>
<script>
(function () {
var DATA = {"gcodes":[{"code":"G0","aliases":["G00"],"name":"Rapid Positioning","category":"motion","modal":"Motion Mode","desc":"Moves at the machine's maximum travel rate to the target position. Non-cutting move used to reposition quickly between operations. The F word is ignored; speed comes from $110-$115 max rates.","syntax":"G0 <axes>","params":{"X":"Target X coordinate","Y":"Target Y coordinate","Z":"Target Z coordinate","A":"Target A (rotary) coordinate","B":"Target B coordinate","C":"Target C coordinate"},"example":"G90 G0 X100 Y50","tips":"Retract Z to a safe height before rapid XY moves. Modal: stays active until another motion command (G1/G2/G3...) is issued.","keywords":["rapid","move","travel","position","fast","jog"]},{"code":"G1","aliases":["G01"],"name":"Linear Interpolation (Feed Move)","category":"motion","modal":"Motion Mode","desc":"Straight-line move at the programmed feed rate. The primary command for cutting and engraving. All specified axes move in a coordinated straight line.","syntax":"G1 <axes> F<feed>","params":{"X":"Target X coordinate","Y":"Target Y coordinate","Z":"Target Z coordinate","A":"Target A coordinate","B":"Target B coordinate","C":"Target C coordinate","F":"Feed rate (units/min in G94)"},"example":"G1 X200 F500","tips":"F is modal — once set it applies to all following feed moves. A feed rate must be active or the move errors out.","keywords":["linear","cut","feed","straight","line","mill","engrave"]},{"code":"G2","aliases":["G02"],"name":"Arc — Clockwise","category":"motion","modal":"Motion Mode","desc":"Clockwise circular arc at the current feed rate on the active plane (G17/G18/G19). Adding the off-plane axis produces helical motion. Defined by center offsets (I/J/K) or radius (R).","syntax":"G2 X- Y- (I- J- | R-) F-","params":{"X":"Arc end X","Y":"Arc end Y","Z":"Arc end Z (helical if off-plane)","I":"X offset from start point to arc center","J":"Y offset from start point to arc center","K":"Z offset from start point to arc center","R":"Arc radius (alternative to IJK)","P":"Number of full circles","F":"Feed rate"},"example":"G17 G2 X10 Y10 I10 J0 F200","tips":"IJK center-offset form is preferred — it is unambiguous. In R form, positive R gives the shorter (<180°) arc, negative R the longer one.","keywords":["arc","circle","clockwise","cw","helix","helical","radius","curve"]},{"code":"G3","aliases":["G03"],"name":"Arc — Counter-Clockwise","category":"motion","modal":"Motion Mode","desc":"Counter-clockwise circular arc at the current feed rate on the active plane. Otherwise identical to G2, including IJK/R forms and helical motion.","syntax":"G3 X- Y- (I- J- | R-) F-","params":{"X":"Arc end X","Y":"Arc end Y","Z":"Arc end Z (helical if off-plane)","I":"X offset to arc center","J":"Y offset to arc center","K":"Z offset to arc center","R":"Arc radius (alternative to IJK)","P":"Number of full circles","F":"Feed rate"},"example":"G3 X20 Y0 R10 F200","tips":"Direction is judged looking at the active plane from the positive side of its normal axis (for G17, looking down at XY).","keywords":["arc","circle","counterclockwise","ccw","helix","curve"]},{"code":"G4","aliases":["G04"],"name":"Dwell (Pause)","category":"motion","modal":null,"desc":"Pauses motion for a set time. Spindle, coolant and other outputs keep their current state. Useful for letting a spindle spin up or clearing chips at hole bottom.","syntax":"G4 P<seconds>","params":{"P":"Dwell time in seconds (decimals allowed)"},"example":"M3 S18000\nG4 P2 ; wait 2s for spindle spin-up","tips":"Non-modal — only affects its own block. Any queued motion completes before the pause begins.","keywords":["dwell","pause","wait","delay","sleep","timer"]},{"code":"G5","aliases":["G5.1"],"name":"Spline Interpolation","category":"motion","modal":"Motion Mode","desc":"Moves along a quadratic (G5) or cubic (G5.1) spline defined by control points, producing smoother free-form curves than arcs. Nearly always generated by CAM rather than written by hand.","syntax":"G5 X- Y- I- J- P- | G5.1 X- Y- I- J- K- L-","params":{"X":"Spline end X","Y":"Spline end Y","Z":"Spline end Z","I":"Control point offset","J":"Control point offset","K":"Control point (cubic)","L":"Control point (cubic)","P":"Second control point (G5)","F":"Feed rate"},"example":"G5 X20 Y10 I10 J15 F100","tips":"Elliptical arcs cannot be produced by combining splines with G51 scaling.","keywords":["spline","curve","bezier","smooth","nurbs"]},{"code":"G7","aliases":[],"name":"Lathe Diameter Mode","category":"modes","modal":"Lathe Mode","desc":"Lathe only ($32=2): X-axis values are interpreted as workpiece diameters. G1 X50 moves the tool to produce a 50-unit diameter.","syntax":"G7","params":{},"example":"G7\nG0 X20 Z0","tips":"Most lathe CAM outputs diameter mode. Machine coordinates always display as radius.","keywords":["lathe","diameter","turning"]},{"code":"G8","aliases":[],"name":"Lathe Radius Mode","category":"modes","modal":"Lathe Mode","desc":"Lathe only ($32=2): X-axis values are interpreted as radii. G1 X25 produces a 50-unit diameter.","syntax":"G8","params":{},"example":"G8\nG0 X25 Z0","tips":"Set G7 or G8 explicitly at the top of every lathe program.","keywords":["lathe","radius","turning"]},{"code":"G10 L2","aliases":["G10"],"name":"Set WCS Origin (Absolute)","category":"coords","modal":null,"desc":"Programmatically sets a work coordinate system origin relative to the machine origin. P selects the WCS (P1=G54 ... P9=G59.3). Values persist across resets.","syntax":"G10 L2 P<1-9> <axes>","params":{"L":"Data mode: 2 = absolute from machine zero","P":"WCS number: 1=G54, 2=G55 ... 9=G59.3","X":"New origin X (machine coords)","Y":"New origin Y","Z":"New origin Z"},"example":"G10 L2 P2 X100 Y250.5 Z-20 ; set G55 origin","tips":"Omitted axes are left unchanged. Great for repeatable multi-fixture setups.","keywords":["work offset","wcs","zero","origin","coordinate","fixture","g54","set zero"]},{"code":"G10 L20","aliases":[],"name":"Set WCS Origin (From Current Position)","category":"coords","modal":null,"desc":"Sets a work coordinate system origin so the machine's current position becomes the given coordinate. \"Make here X0 Y0\" — this is what most senders send when you click Zero.","syntax":"G10 L20 P<1-9> <axes>","params":{"L":"Data mode: 20 = relative to current position","P":"WCS number: 1=G54 ... 9=G59.3","X":"Value current X should read","Y":"Value current Y should read","Z":"Value current Z should read"},"example":"G10 L20 P1 X0 Y0 ; current spot becomes G54 X0 Y0","tips":"Preferred over G92 for zeroing — the offset is stored in the WCS and survives resets.","keywords":["zero","touch off","work offset","wcs","origin","set zero","xyz zero"]},{"code":"G17","aliases":[],"name":"XY Plane Select","category":"modes","modal":"Plane Select","desc":"Selects the XY plane for arcs, cutter compensation and canned cycles. Default on startup. Arcs use I (X offset) and J (Y offset).","syntax":"G17","params":{},"example":"G17\nG2 X10 Y15 I5 J0 F300","tips":"Set the plane explicitly at program start; arcs on the wrong plane move in surprising directions.","keywords":["plane","xy","arc plane"]},{"code":"G18","aliases":[],"name":"XZ Plane Select","category":"modes","modal":"Plane Select","desc":"Selects the XZ plane (lathes, side profiling). Arcs use I (X offset) and K (Z offset).","syntax":"G18","params":{},"example":"G18\nG3 X20 Z-5 I10 K0 F250","tips":null,"keywords":["plane","xz","lathe plane"]},{"code":"G19","aliases":[],"name":"YZ Plane Select","category":"modes","modal":"Plane Select","desc":"Selects the YZ plane. Arcs use J (Y offset) and K (Z offset).","syntax":"G19","params":{},"example":"G19\nG2 Y10 Z-2 J5 K0 F250","tips":null,"keywords":["plane","yz"]},{"code":"G20","aliases":[],"name":"Inch Units","category":"modes","modal":"Units","desc":"All coordinates, offsets and feed rates are interpreted as inches (feeds in inches/min).","syntax":"G20","params":{},"example":"G20\nG1 X4 F20","tips":"Put G20 or G21 at the top of every file — a 10 mm move read as 10 inches is a crash. Display units are separate ($13).","keywords":["inch","inches","imperial","units"]},{"code":"G21","aliases":[],"name":"Millimeter Units","category":"modes","modal":"Units","desc":"All coordinates, offsets and feed rates are interpreted as millimeters (feeds in mm/min).","syntax":"G21","params":{},"example":"G21\nG1 X100 F500","tips":"Interpreter units only — does not change steps/mm calibration ($100-$102) or the report units ($13).","keywords":["mm","millimeter","metric","units"]},{"code":"G28","aliases":[],"name":"Go to Stored Position 1","category":"coords","modal":null,"desc":"Rapid move to the position stored by G28.1 (in machine coordinates). With axis words, first moves through that intermediate point, then to the stored position.","syntax":"G28 [<axes>]","params":{"X":"Intermediate X before final move","Y":"Intermediate Y","Z":"Intermediate Z"},"example":"G53 G0 Z0\nG28 ; retract, then go to park position","tips":"DANGER: only use on a homed machine — the stored position is in machine coordinates. G28 Z0 lifts Z (in the current WCS) before traveling.","keywords":["park","home position","stored position","safe position","predefined"]},{"code":"G28.1","aliases":[],"name":"Store Position 1","category":"coords","modal":null,"desc":"Saves the machine's current absolute position as the G28 target. Persists across resets and power cycles.","syntax":"G28.1","params":{},"example":"G53 G0 X-50 Y-50 Z-5\nG28.1","tips":"Move with G53 first so the stored spot is independent of work offsets. Takes no axis words.","keywords":["store","save position","park","set park"]},{"code":"G30","aliases":[],"name":"Go to Stored Position 2","category":"coords","modal":null,"desc":"Same as G28 but uses the second stored position (set by G30.1). Commonly used for a tool-change or probing location.","syntax":"G30 [<axes>]","params":{"X":"Intermediate X","Y":"Intermediate Y","Z":"Intermediate Z"},"example":"G30","tips":"Only use on a homed machine.","keywords":["park","second position","tool change position","stored position"]},{"code":"G30.1","aliases":[],"name":"Store Position 2","category":"coords","modal":null,"desc":"Saves the current absolute machine position as the G30 target.","syntax":"G30.1","params":{},"example":"G53 G0 X-200 Y-400 Z-10\nG30.1","tips":null,"keywords":["store","save position","set park"]},{"code":"G53","aliases":[],"name":"Move in Machine Coordinates","category":"coords","modal":null,"desc":"For one block only, moves in the absolute machine coordinate system, ignoring all work offsets, G92 and tool offsets. Must be combined with G0 or G1.","syntax":"G53 G0 <axes> | G53 G1 <axes> F-","params":{"X":"Machine X target","Y":"Machine Y target","Z":"Machine Z target","F":"Feed rate (with G1)"},"example":"G53 G0 Z0 ; retract Z fully, regardless of offsets","tips":"G53 G0 Z0 is one of the safest moves in G-code — but only on a homed machine. Reverts to the active WCS on the next line.","keywords":["machine coordinates","absolute","retract","safe move","ignore offsets"]},{"code":"G54","aliases":["G55","G56","G57","G58","G59","G59.1","G59.2","G59.3"],"name":"Work Coordinate Systems","category":"coords","modal":"WCS","desc":"Selects one of nine work coordinate systems (G54-G59.3), each with its own user-set origin. Separates the program zero from machine home. G54 is the default.","syntax":"G54 | G55 | ... | G59.3","params":{},"example":"G54\n(run part 1)\nG55\n(run same file on fixture 2)","tips":"Origins are set with G10 L2/L20 or the Zero buttons and are stored persistently. G59.3 doubles as the tool change position in tool change modes 2 & 3.","keywords":["wcs","work coordinate","offset","g55","g56","g57","g58","g59","fixture","datum"]},{"code":"G92","aliases":[],"name":"Temporary Coordinate Offset","category":"coords","modal":"G92 Offset","desc":"Applies a volatile offset so the current position reads as the given values (\"you are now X0 Y0\"). Applied on top of the active WCS. Cleared by G92.1.","syntax":"G92 <axes>","params":{"X":"Value current X should read","Y":"Value current Y should read","Z":"Value current Z should read","A":"Value current A should read"},"example":"G92 X0 Y0 Z0","tips":"Easy to forget and a common crash cause — prefer G10 L20 with a spare WCS. $384 controls whether the offset persists across resets.","keywords":["offset","temporary zero","shift","coordinate offset"]},{"code":"G92.1","aliases":["G92.2","G92.3"],"name":"Clear / Suspend / Restore G92","category":"coords","modal":"G92 Offset","desc":"G92.1 clears the G92 offset (and zeroes the stored values). G92.2 suspends it without erasing. G92.3 re-applies a suspended offset.","syntax":"G92.1 | G92.2 | G92.3","params":{},"example":"G92.1 ; back to the plain G54 system","tips":null,"keywords":["clear offset","cancel g92","reset offset"]},{"code":"G38.2","aliases":[],"name":"Probe Toward (Error on Miss)","category":"probing","modal":null,"desc":"Moves toward the target until the probe input triggers, then stops and records the trigger position. Raises an error if the target is reached without contact.","syntax":"G38.2 <axes> F<feed>","params":{"X":"Probe travel limit X","Y":"Probe travel limit Y","Z":"Probe travel limit Z","F":"Probing feed rate"},"example":"G91 G38.2 Z-20 F100 ; probe down max 20mm","tips":"Probe fast to find the surface, back off, then re-probe slowly for accuracy. The trigger position is reported and stored in probe parameters (see $# output, PRB).","keywords":["probe","touch","toolsetter","surface","zero probe","touch plate","probing"]},{"code":"G38.3","aliases":[],"name":"Probe Toward (No Error on Miss)","category":"probing","modal":null,"desc":"Like G38.2, but completing the move without contact is not an error. Useful for checking whether something is present.","syntax":"G38.3 <axes> F<feed>","params":{"X":"Probe travel limit X","Y":"Probe travel limit Y","Z":"Probe travel limit Z","F":"Probing feed rate"},"example":"G38.3 Z-10 F150","tips":"Check the probe result flag in the report to see whether contact happened.","keywords":["probe","optional","check","detect","probing"]},{"code":"G38.4","aliases":[],"name":"Probe Away (Error on Fail)","category":"probing","modal":null,"desc":"Moves away until the probe input releases (loses contact). Errors if the probe starts un-triggered or never releases within the move.","syntax":"G38.4 <axes> F<feed>","params":{"X":"Travel limit X","Y":"Travel limit Y","Z":"Travel limit Z","F":"Probing feed rate"},"example":"G91 G38.4 Z5 F100","tips":null,"keywords":["probe away","release","retract probe","probing"]},{"code":"G38.5","aliases":[],"name":"Probe Away (No Error on Fail)","category":"probing","modal":null,"desc":"Like G38.4 but does not error if the probe never releases within the move.","syntax":"G38.5 <axes> F<feed>","params":{"X":"Travel limit X","Y":"Travel limit Y","Z":"Travel limit Z","F":"Probing feed rate"},"example":"G38.5 G91 Z50 F200","tips":null,"keywords":["probe away","optional","probing"]},{"code":"G40","aliases":[],"name":"Cancel Cutter Compensation","category":"tool","modal":"Cutter Comp","desc":"Disables cutter radius compensation. This is the default state; full G41/G42 compensation is not in the grblHAL core (plugin territory), so G40 mainly guarantees a known state.","syntax":"G40","params":{},"example":"G40","tips":"Include in your safety preamble: G90 G21 G17 G40 G49 G80 G94.","keywords":["cutter compensation","comp","cancel","g41","g42"]},{"code":"G43.1","aliases":[],"name":"Dynamic Tool Length Offset","category":"tool","modal":"Tool Length Offset","desc":"Applies a tool length offset given directly in the command (usually Z). Typically issued after probing a new tool to shift the Z origin by the measured length difference.","syntax":"G43.1 Z<offset>","params":{"Z":"Offset to apply to Z","A":"Offset for A","B":"Offset for B"},"example":"G43.1 Z5.2 ; tool is 5.2mm longer than reference","tips":"Cancel with G49 before tool changes and at program end.","keywords":["tool length","tlo","offset","tool offset","length compensation"]},{"code":"G43","aliases":["G43.2"],"name":"Tool Length Offset from Tool Table","category":"tool","modal":"Tool Length Offset","desc":"With a tool table enabled, G43 H<n> applies the stored Z-length offset for tool n. G43.2 adds a second, stacked offset.","syntax":"G43 H<tool> | G43.2 <axes>","params":{"H":"Tool table entry whose offset to apply","Z":"Additional offset (G43.2)"},"example":"T1 M6\nG43 H1","tips":"H should normally match the active tool number.","keywords":["tool table","tool length","h word","offset"]},{"code":"G49","aliases":[],"name":"Cancel Tool Length Offset","category":"tool","modal":"Tool Length Offset","desc":"Removes any active tool length offset.","syntax":"G49","params":{},"example":"G49\nM6 T2","tips":"Issue before M6 and at program end.","keywords":["cancel","tool length","clear offset"]},{"code":"G50","aliases":[],"name":"Cancel Scaling","category":"modes","modal":"Scaling","desc":"Disables G51 coordinate scaling, restoring 1:1 motion. Default state.","syntax":"G50","params":{},"example":"G50","tips":"On lathes in G96 mode, G50 S<rpm> also sets the max spindle RPM cap (Mach3 style).","keywords":["scaling","cancel scale","unscale"]},{"code":"G51","aliases":[],"name":"Coordinate Scaling / Mirroring","category":"modes","modal":"Scaling","desc":"Scales subsequent motion per-axis. A factor of -1 mirrors that axis. Lets you resize or flip a program without editing it.","syntax":"G51 X<f> Y<f> Z<f>","params":{"X":"X scale factor (-1 mirrors)","Y":"Y scale factor","Z":"Z scale factor"},"example":"G51 X0.5 Y0.5 Z0.5\n(half-size part)\nG50","tips":"Unequal XY factors are not allowed with G2/G3 (no elliptical arcs). Always cancel with G50.","keywords":["scale","mirror","flip","resize"]},{"code":"G81","aliases":[],"name":"Drilling Cycle","category":"cycles","modal":"Motion Mode","desc":"Simple drill cycle: rapid to R plane, feed to Z depth, rapid retract. Once active, every new XY position drills a hole until G80 cancels.","syntax":"G81 Z<depth> R<retract> F<feed>","params":{"Z":"Final hole depth","R":"Retract plane (Z height to rapid to before feeding)","F":"Drilling feed rate","L":"Optional repeat count"},"example":"G99 G81 Z-10 R2 F150\nX10 Y10\nX20\nG80","tips":"Retract height between holes is controlled by G98 (initial Z) / G99 (R plane).","keywords":["drill","hole","canned cycle","drilling"]},{"code":"G82","aliases":[],"name":"Drilling Cycle with Dwell","category":"cycles","modal":"Motion Mode","desc":"Like G81 but dwells at the bottom of the hole for P seconds — improves hole-bottom finish (spot drilling, countersinking).","syntax":"G82 Z- R- P<sec> F-","params":{"Z":"Final depth","R":"Retract plane","P":"Dwell at bottom (seconds)","F":"Feed rate"},"example":"G82 Z-3 R2 P0.5 F100","tips":null,"keywords":["drill","dwell","spot","countersink","canned cycle"]},{"code":"G83","aliases":[],"name":"Peck Drilling (Full Retract)","category":"cycles","modal":"Motion Mode","desc":"Deep-hole peck drilling: after each peck of depth Q, the drill fully retracts out of the hole to clear chips, then returns.","syntax":"G83 Z- R- Q<peck> F-","params":{"Z":"Final depth","R":"Retract plane","Q":"Depth of each peck","F":"Feed rate"},"example":"G83 Z-25 R2 Q5 F120","tips":"Use for holes deeper than ~3x drill diameter.","keywords":["peck","deep hole","drill","chip clearing","canned cycle"]},{"code":"G73","aliases":[],"name":"Peck Drilling (Chip Break)","category":"cycles","modal":"Motion Mode","desc":"High-speed peck cycle: after each peck of depth Q, retracts a small fixed amount ($28) to snap the chip without leaving the hole.","syntax":"G73 Z- R- Q<peck> F-","params":{"Z":"Final depth","R":"Retract plane","Q":"Depth of each peck","F":"Feed rate"},"example":"G73 Z-15 R2 Q4 F150","tips":"Retract amount per peck comes from setting $28.","keywords":["peck","chip break","drill","canned cycle"]},{"code":"G85","aliases":[],"name":"Boring Cycle (Feed Out)","category":"cycles","modal":"Motion Mode","desc":"Feeds to depth and feeds back out — no rapid retract inside the hole, leaving a better surface finish (reaming/boring).","syntax":"G85 Z- R- F-","params":{"Z":"Final depth","R":"Retract plane","F":"Feed rate (both directions)"},"example":"G85 Z-12 R2 F80","tips":null,"keywords":["bore","ream","finish","canned cycle"]},{"code":"G86","aliases":[],"name":"Boring Cycle (Spindle Stop)","category":"cycles","modal":"Motion Mode","desc":"Feeds to depth, stops the spindle, then rapids out.","syntax":"G86 Z- R- F-","params":{"Z":"Final depth","R":"Retract plane","F":"Feed rate"},"example":"G86 Z-12 R2 F80","tips":null,"keywords":["bore","canned cycle"]},{"code":"G89","aliases":[],"name":"Boring Cycle with Dwell","category":"cycles","modal":"Motion Mode","desc":"Feeds to depth, dwells P seconds, feeds back out.","syntax":"G89 Z- R- P<sec> F-","params":{"Z":"Final depth","R":"Retract plane","P":"Dwell (seconds)","F":"Feed rate"},"example":"G89 Z-10 R2 P1 F80","tips":null,"keywords":["bore","dwell","canned cycle"]},{"code":"G76","aliases":[],"name":"Threading Cycle (Lathe)","category":"cycles","modal":"Motion Mode","desc":"Multi-pass lathe threading cycle. Requires a spindle encoder for spindle-synchronized motion; only a few grblHAL boards support the hardware.","syntax":"G76 Z- R- I- J- K- L- P- Q- F-","params":{"Z":"Thread end","P":"Thread pitch","I":"Thread peak offset","J":"Initial cut depth","K":"Full thread depth","Q":"Compound slide angle","L":"Taper mode","R":"Depth regression","F":"Feed"},"example":"(lathe threading — see grblHAL docs)","tips":"Related: G33 spindle-synchronized motion, also encoder-dependent.","keywords":["thread","threading","lathe","tap"]},{"code":"G80","aliases":[],"name":"Cancel Canned Cycle","category":"cycles","modal":"Motion Mode","desc":"Immediately ends any active canned cycle so later coordinates are not interpreted as more holes. Critical safety command after cycle blocks.","syntax":"G80","params":{},"example":"G81 Z-10 R2 F100\nX10\nX20\nG80","tips":"Any new motion command (G0/G1/G2/G3) also cancels an active cycle.","keywords":["cancel","canned cycle","end cycle"]},{"code":"G98","aliases":[],"name":"Cycle Retract to Initial Z","category":"cycles","modal":"Cycle Return","desc":"Between canned-cycle holes, retract all the way to the Z height held before the cycle started. Safest mode — clears clamps between holes.","syntax":"G98","params":{},"example":"G0 Z20\nG98 G81 Z-5 R2 F100","tips":null,"keywords":["retract","initial","canned cycle","return"]},{"code":"G99","aliases":[],"name":"Cycle Retract to R Plane","category":"cycles","modal":"Cycle Return","desc":"Between holes, retract only to the R plane. Faster on flat unobstructed surfaces.","syntax":"G99","params":{},"example":"G99 G81 Z-5 R2 F100","tips":null,"keywords":["retract","r plane","canned cycle","return"]},{"code":"G90","aliases":[],"name":"Absolute Distance Mode","category":"modes","modal":"Distance Mode","desc":"Coordinates are destinations measured from the active WCS origin. X10 means \"go to the X=10 line\". Default mode; what most CAM output uses.","syntax":"G90","params":{},"example":"G90\nG0 X10 Y20","tips":null,"keywords":["absolute","distance mode","positioning"]},{"code":"G91","aliases":[],"name":"Incremental Distance Mode","category":"modes","modal":"Distance Mode","desc":"Coordinates are distances from the current position. X10 means \"move +10 in X from here\". Ideal for macros and probing routines that must work anywhere.","syntax":"G91","params":{},"example":"G91\nG1 X50 F300\nG1 Y30","tips":"Forgetting to switch back to G90 is a classic crash. In G91, arc IJK offsets are still measured from the arc start point.","keywords":["incremental","relative","distance mode"]},{"code":"G93","aliases":[],"name":"Inverse Time Feed Mode","category":"modes","modal":"Feed Mode","desc":"F means 1/minutes: the move must complete in 1/F minutes. Used mainly for simultaneous multi-axis (4/5-axis) motion where tool-tip speed is complex.","syntax":"G93","params":{"F":"Move completes in 1/F minutes"},"example":"G93\nG1 X10 A90 F2 ; complete in 30 seconds","tips":"F must be given on every motion line in G93.","keywords":["inverse time","feed mode","5 axis","rotary feed"]},{"code":"G94","aliases":[],"name":"Units per Minute Feed Mode","category":"modes","modal":"Feed Mode","desc":"F is linear units (mm or inch) per minute. Standard for mills and routers; the default.","syntax":"G94","params":{"F":"Feed in units/min"},"example":"G94\nG1 X100 F500","tips":null,"keywords":["feed mode","units per minute","mm/min"]},{"code":"G95","aliases":[],"name":"Units per Revolution Feed Mode","category":"modes","modal":"Feed Mode","desc":"F is units per spindle revolution — the lathe standard, tying chip load directly to RPM. Needs spindle speed feedback.","syntax":"G95","params":{"F":"Feed in units/rev"},"example":"G95\nS1000 M3\nG1 Z-50 F0.2 ; effective 200mm/min","tips":null,"keywords":["feed per rev","lathe feed","units per revolution"]},{"code":"G96","aliases":[],"name":"Constant Surface Speed (Lathe)","category":"modes","modal":"Spindle Mode","desc":"S is a surface speed; the controller varies spindle RPM with the X diameter to hold it constant at the cutting edge. Lathe builds only.","syntax":"G96 S<surface speed> [D<max rpm>]","params":{"S":"Target surface speed (m/min or ft/min)","D":"Max RPM cap"},"example":"G50 S4000\nG96 S150 M3","tips":"Always cap RPM (G50 S / D word) — RPM rises sharply as diameter shrinks.","keywords":["css","surface speed","lathe","constant speed"]},{"code":"G97","aliases":[],"name":"Constant RPM Mode","category":"modes","modal":"Spindle Mode","desc":"S is plain revolutions per minute. Default; required for drilling, tapping and threading.","syntax":"G97 S<rpm>","params":{"S":"Spindle RPM"},"example":"G97 S800 M3","tips":null,"keywords":["rpm","spindle mode","constant rpm"]},{"code":"G61","aliases":["G61.1"],"name":"Exact Stop Path Mode","category":"modes","modal":"Path Control","desc":"Machine fully stops at the end of each move before starting the next — perfectly sharp corners at the cost of speed and smoothness.","syntax":"G61","params":{},"example":"G61\n(precise engraving moves)","tips":"Can leave witness marks/divots at corners due to the momentary stop. Continuous blending is the usual default.","keywords":["exact stop","path control","corners","sharp"]},{"code":"G65","aliases":[],"name":"Macro Call with Arguments","category":"program","modal":null,"desc":"Calls a macro (P<n>.macro on SD/LittleFS) and passes letter arguments as local variables. Requires NGC expressions enabled in the firmware. P1-P7 are reserved built-ins (settings read/write, tool offsets, machine state, probe select, spindle delay skip, Modbus messaging).","syntax":"G65 P<number> [L<repeat>] [A- B- C- ...]","params":{"P":"Macro number: P100+ user macros; P1-P7 built-ins","L":"Repeat count","A":"Argument (becomes #1)","B":"Argument (#2)","C":"Argument (#3)","Q":"Argument (built-ins: setting/tool/probe number)","R":"Argument (built-ins: register/axis)","S":"Argument (built-ins: value/slave address)","I":"Argument (P3: parameter number)","F":"Argument (P7: Modbus function code)"},"example":"G65 P100 A5.0 B200 ; call P100.macro with args\nG65 P1 Q110 ; built-in: read setting $110 into _value","tips":"Notable built-ins: P1 read/write settings, P4 machine state, P5 select probe input (0 probe, 1 toolsetter), P7 Modbus (talk to a VFD from G-code). Nesting G65 is not allowed.","keywords":["macro","subprogram","call","arguments","modbus","vfd","expression","p100"]},{"code":"G66","aliases":["G67"],"name":"Modal Macro Call / Cancel","category":"program","modal":"Modal Macro","desc":"G66 works like G65 but repeats the macro after every subsequent motion command until G67 cancels it — handy for custom drilling or probing cycles at many locations.","syntax":"G66 P<number> [args] ... G67","params":{"P":"Macro number","L":"Repeat count"},"example":"G66 P110 A2\nX10 Y10\nX20\nG67","tips":null,"keywords":["modal macro","repeat","custom cycle"]},{"code":"M0","aliases":["M00"],"name":"Program Stop","category":"program","modal":null,"desc":"Unconditionally pauses the program — motion, spindle and coolant stop. Cycle Start resumes from the next line. An optional (message) shows in the sender.","syntax":"M0 [(message)]","params":{},"example":"G0 Z20\nM0 (Clear chips, then press start)","tips":"Manual tool change setups often transform M6 into M0 with a message.","keywords":["stop","pause","hold","wait","operator"]},{"code":"M1","aliases":["M01"],"name":"Optional Stop","category":"program","modal":null,"desc":"Pauses like M0, but only when the Optional Stop switch is enabled in the sender/machine; ignored otherwise. Good for inspection points you don't need every run.","syntax":"M1 [(message)]","params":{},"example":"(finishing pass)\nM1","tips":null,"keywords":["optional stop","pause","inspection"]},{"code":"M2","aliases":["M02"],"name":"Program End","category":"program","modal":null,"desc":"Ends the program, resets the parser to defaults and leaves the machine idle.","syntax":"M2","params":{},"example":"M5\nM2","tips":null,"keywords":["end","program end","finish"]},{"code":"M30","aliases":[],"name":"Program End & Rewind","category":"program","modal":null,"desc":"The standard end-of-file: does everything M2 does and rewinds to the start, ready for the next part.","syntax":"M30","params":{},"example":"G0 Z20\nM5 M9\nM30","tips":"When running from SD card, $FR before start enables rewind-and-rerun on cycle start.","keywords":["end","rewind","program end","m30"]},{"code":"M3","aliases":["M03"],"name":"Spindle On — Clockwise","category":"spindle","modal":"Spindle","desc":"Starts the spindle clockwise at the last programmed S speed. In laser mode ($32=1), fires the laser at constant power while moving.","syntax":"M3 S<rpm>","params":{"S":"Spindle speed (RPM) or laser power"},"example":"S18000 M3","tips":"With spindle-at-speed enabled ($340 tolerance) the controller waits for the VFD to reach speed. For laser engraving prefer M4 dynamic power.","keywords":["spindle","on","clockwise","cw","start spindle","laser on"]},{"code":"M4","aliases":["M04"],"name":"Spindle On — CCW / Laser Dynamic","category":"spindle","modal":"Spindle","desc":"Starts the spindle counter-clockwise (left-hand tools). In laser mode ($32=1), enables dynamic power: output scales with actual velocity so accel/decel zones don't burn darker.","syntax":"M4 S<rpm>","params":{"S":"Spindle speed (RPM) or max laser power"},"example":"M4 S800 ; laser dynamic mode","tips":"This is the mode LightBurn's grbl profiles use for engraving.","keywords":["spindle","ccw","counterclockwise","laser","dynamic power","variable power"]},{"code":"M5","aliases":["M05"],"name":"Spindle / Laser Off","category":"spindle","modal":"Spindle","desc":"Stops spindle rotation (or laser output).","syntax":"M5","params":{},"example":"M5","tips":"$394 sets a spin-down delay so motion waits for the spindle to actually stop.","keywords":["spindle off","stop","laser off"]},{"code":"M6","aliases":["M06"],"name":"Tool Change","category":"tool","modal":null,"desc":"Executes a tool change to the tool selected by T. With an ATC, runs the tool change macro (tc.macro / P200.macro for RapidChange). Without one, behavior follows $341: pause like M0, move to a change position, and/or run the manual probe protocol ($TPW).","syntax":"T<n> M6 | M6 T<n>","params":{"T":"Tool number to load"},"example":"T2 M6\nG43 H2","tips":"T only selects; M6 performs the change. Apply the new length offset (G43/G43.1) afterward. See $341-$346 for tool change configuration.","keywords":["tool change","atc","change tool","m6","rapidchange","toolchange"]},{"code":"M7","aliases":["M07"],"name":"Mist Coolant On","category":"coolant","modal":"Coolant","desc":"Turns on the mist coolant output pin (air/oil mist). Often repurposed for an air blast or accessory relay.","syntax":"M7","params":{},"example":"M7","tips":null,"keywords":["mist","coolant","air","output"]},{"code":"M8","aliases":["M08"],"name":"Flood Coolant On","category":"coolant","modal":"Coolant","desc":"Turns on the flood coolant output pin — the primary coolant output. Commonly repurposed for dust collection or a dust boot.","syntax":"M8","params":{},"example":"M8\nG1 Z-5 F300","tips":null,"keywords":["flood","coolant","dust boot","dust collection","output"]},{"code":"M9","aliases":["M09"],"name":"All Coolant Off","category":"coolant","modal":"Coolant","desc":"Turns off both mist (M7) and flood (M8) outputs.","syntax":"M9","params":{},"example":"G0 Z20\nM9","tips":null,"keywords":["coolant off","mist off","flood off"]},{"code":"M48","aliases":[],"name":"Enable Overrides","category":"program","modal":"Override","desc":"Re-enables the real-time feed, rapid and spindle override controls (the default).","syntax":"M48","params":{},"example":"M48","tips":null,"keywords":["override","enable","feed override"]},{"code":"M49","aliases":[],"name":"Disable Overrides","category":"program","modal":"Override","desc":"Ignores all override controls; the program runs at exactly 100% of programmed feed, rapid and spindle values.","syntax":"M49","params":{},"example":"M49\nG1 X100 F150\nM48","tips":"Use sparingly — it removes the operator's ability to slow a bad cut.","keywords":["override","disable","lock feed"]},{"code":"M50","aliases":["M51","M53"],"name":"Selective Override Control","category":"program","modal":null,"desc":"Granular override disabling: M50 feed override off, M51 spindle override off, M53 rapid override off. M48 re-enables all.","syntax":"M50 | M51 | M53","params":{},"example":"M50 M51\n(critical finishing pass)\nM48","tips":null,"keywords":["override","feed","spindle","rapid","selective"]},{"code":"M56","aliases":[],"name":"Parking Motion Override","category":"program","modal":null,"desc":"Enables (P1) or disables (P0) automatic parking motion. Requires parking support plus this override option compiled into the firmware.","syntax":"M56 P<0|1>","params":{"P":"1 = enable parking motion, 0 = disable"},"example":"M56 P0\n(critical moves)\nM56 P1","tips":null,"keywords":["parking","park","override"]},{"code":"M61","aliases":[],"name":"Set Current Tool","category":"tool","modal":null,"desc":"Tells the controller which tool is currently loaded (Q word) without performing a change — used to sync state after manual swaps.","syntax":"M61 Q<tool>","params":{"Q":"Tool number now in the spindle"},"example":"M61 Q3","tips":null,"keywords":["set tool","current tool","sync tool"]},{"code":"M62","aliases":["M63"],"name":"Digital Output — Synced","category":"io","modal":null,"desc":"Queues a digital output change (M62 on, M63 off) to fire at the exact start of the next motion command. Ideal for laser gating, cameras, or anything that must align with motion.","syntax":"M62 P<port> | M63 P<port>","params":{"P":"Digital output port number"},"example":"M62 P1\nG1 X20 F500 ; output 1 goes high as this move starts\nM63 P1\nG0 X30","tips":"On the plasma/THC plugin these same codes toggle torch height control.","keywords":["digital output","synchronized","io","laser gate","output on","output off"]},{"code":"M64","aliases":["M65"],"name":"Digital Output — Immediate","category":"io","modal":null,"desc":"Sets a digital output high (M64) or low (M65) immediately when read, without waiting for motion.","syntax":"M64 P<port> | M65 P<port>","params":{"P":"Digital output port number"},"example":"M400\nM64 P1 ; trigger once fully stopped","tips":"Use $pins / $pinstate in the terminal to see which aux ports exist and their live state.","keywords":["digital output","immediate","io","relay","aux output"]},{"code":"M66","aliases":[],"name":"Wait for Input","category":"io","modal":null,"desc":"Pauses execution until a digital input reaches the requested state, or a timeout expires. Requires configured aux inputs.","syntax":"M66 P<port> L<0|1> [Q<timeout s>]","params":{"P":"Digital input port number","L":"State to wait for: 0 low, 1 high","Q":"Timeout in seconds (error if exceeded)"},"example":"M66 P2 L1 Q10 ; wait up to 10s for input 2 high","tips":null,"keywords":["wait","input","sensor","io","interlock"]},{"code":"M67","aliases":["M68"],"name":"Analog Output","category":"io","modal":null,"desc":"Sets an analog output value — M67 synchronized with the next motion, M68 immediately. Used for laser power ramps, flow control, etc.","syntax":"M67 P<port> Q<value> | M68 P<port> Q<value>","params":{"P":"Analog output port number","Q":"Target analog value (range depends on DAC/PWM resolution)","E":"Port (plasma plugin velocity-reduction variant)"},"example":"M67 P0 Q150\nG1 X20 F500","tips":null,"keywords":["analog output","pwm","dac","laser power","io"]},{"code":"M70","aliases":["M71","M72","M73"],"name":"Modal State Save/Restore","category":"program","modal":null,"desc":"Saves (M70) and restores (M72) the full modal state — active G modes, feed, spindle speed — so macros can change modes freely without disturbing the main program. M71 invalidates a saved state; M73 saves with auto-restore for subprograms.","syntax":"M70 ... M72","params":{},"example":"M70\nG91 G1 F100\n(probe moves)\nM72","tips":"Wrap any probing or tool change macro in M70/M72 — cheap insurance against leaving the machine in G91.","keywords":["save state","restore","modal","macro safety"]},{"code":"M98","aliases":[],"name":"Subroutine Call","category":"program","modal":null,"desc":"Calls a subroutine: with $700=1 it first looks for an O<n> sub label in the current file, otherwise (or if not found) runs external file P<n> from SD/LittleFS. L repeats the call.","syntax":"M98 P<number> [L<repeat>]","params":{"P":"Subroutine number or filename","L":"Repeat count"},"example":"M98 P100 L3\nM30\nO100 sub\nG91 G0 X10\nM99","tips":null,"keywords":["subroutine","call","subprogram","repeat"]},{"code":"M99","aliases":[],"name":"Return from Subroutine","category":"program","modal":null,"desc":"Ends a subroutine and returns to the line after the call. In a main program it acts as rewind-and-loop. Also terminates tool change macros.","syntax":"M99","params":{"P":"Optional return line (implementation-dependent)"},"example":"M99","tips":null,"keywords":["return","subroutine","end macro"]},{"code":"M42","aliases":[],"name":"Set Digital Output (OpenPNP)","category":"plugin","modal":null,"desc":"OpenPNP plugin: directly sets a digital I/O port state.","syntax":"M42 P<port> S<0|1>","params":{"P":"I/O port number","S":"0 = off, 1 = on"},"example":"M42 P1 S1","tips":null,"keywords":["digital output","openpnp","io","relay"]},{"code":"M104","aliases":[],"name":"Select Spindle","category":"plugin","modal":null,"desc":"Spindle plugin: selects which configured spindle (VFD, PWM, laser...) subsequent S/M3/M4 commands address. Essential on dual-spindle setups.","syntax":"M104 P<spindle>","params":{"P":"Spindle number (see $SPINDLES for the list)"},"example":"M104 P1 ; switch to spindle 1 (e.g. PWM laser)","tips":"Run $SPINDLES in the terminal to enumerate configured spindles and their numbers.","keywords":["spindle select","dual spindle","laser","vfd","switch spindle","multi spindle"]},{"code":"M106","aliases":["M107"],"name":"Fan Control","category":"plugin","modal":null,"desc":"Fan plugin: M106 turns a fan on with PWM speed 0-255; M107 turns it off.","syntax":"M106 P<fan> S<0-255> | M107 P<fan>","params":{"P":"Fan index","S":"PWM duty 0-255"},"example":"M106 P0 S255","tips":null,"keywords":["fan","cooling","pwm"]},{"code":"M114","aliases":[],"name":"Report Position (Encoder)","category":"plugin","modal":null,"desc":"Encoder plugin: reports current position, including spindle encoder data when available.","syntax":"M114","params":{},"example":"M114","tips":null,"keywords":["position","report","encoder"]},{"code":"M122","aliases":[],"name":"Trinamic Driver Report","category":"plugin","modal":null,"desc":"Motor plugin: dumps Trinamic stepper driver status/debug info for the given axes.","syntax":"M122 [axes]","params":{"X":"Report X driver","Y":"Report Y driver","Z":"Report Z driver"},"example":"M122","tips":"Related: M906 set RMS current, M569 StealthChop/SpreadCycle, M911/M912 prewarn flags, M913 hybrid threshold, M914 homing sensitivity.","keywords":["trinamic","stepper","driver","debug","tmc"]},{"code":"M150","aliases":[],"name":"RGB LED Control","category":"plugin","modal":null,"desc":"Misc plugin: sets color and brightness for an RGB/RGBW LED strip or a single LED by index. Used for status lighting on machines with LED rails/rings.","syntax":"M150 [R<0-255>] [U<0-255>] [B<0-255>] [W<0-255>] [P<0-255>] [I<index>] [S<strip>] [K]","params":{"R":"Red 0-255","U":"Green 0-255","B":"Blue 0-255","W":"White 0-255","P":"Brightness 0-255","I":"LED index for individual control","S":"Strip index (0 or 1)","K":"Keep unspecified components unchanged"},"example":"M150 R255 U0 B0 S1 ; strip 1 solid red\nM150 R0 U0 B0 S1 ; off","tips":"Note green is U, not G (G would parse as a G-code).","keywords":["led","rgb","light","strip","neopixel","status light"]},{"code":"M220","aliases":[],"name":"Set Feed Override %","category":"plugin","modal":null,"desc":"Sets the feed override percentage from G-code (Marlin heritage). B backs up the current value, R restores it, S sets a percentage.","syntax":"M220 [S<percent>] [B] [R]","params":{"S":"Feed override percent (100 = programmed feed)","B":"Backup current override","R":"Restore backed-up override"},"example":"M220 S50\n(difficult section)\nM220 S100","tips":null,"keywords":["feed override","percent","slow down","speed"]},{"code":"M280","aliases":[],"name":"Set Servo Position","category":"plugin","modal":null,"desc":"Servo plugin: moves a PWM servo to a position — typically 0-180 degrees. Used for probe deployers, dust shoes, clamps.","syntax":"M280 P<servo> S<position>","params":{"P":"Servo index","S":"Target position (deg or µs)"},"example":"M280 P0 S90 ; deploy\nM280 P0 S0 ; stow","tips":null,"keywords":["servo","deploy","position","pwm"]},{"code":"M400","aliases":[],"name":"Finish Moves","category":"plugin","modal":null,"desc":"Waits for the planner buffer to fully empty before the next command — the machine is completely stationary. Roughly a G4 P0.","syntax":"M400","params":{},"example":"G0 X50 Y50\nM400\nM64 P1","tips":null,"keywords":["wait","finish","buffer","sync"]},{"code":"M810","aliases":[],"name":"ATCi Keepout Zone Toggle (Sienci)","category":"plugin","modal":null,"desc":"Sienci ATCi plugin: runtime toggle for keepout-zone enforcement around the tool magazine. P1 enables protection, P0 disables it.","syntax":"M810 P<0|1>","params":{"P":"1 = enforce keepout zone, 0 = disable"},"example":"M810 P0","tips":null,"keywords":["sienci","atc","atci","keepout","magazine"]},{"code":"$TLS","aliases":[],"name":"Tool Length Set (ATC/MTC plugins)","category":"plugin","modal":null,"desc":"Runs the tool length setter probe cycle for the currently loaded tool: raises to safe Z, rapids to the configured TLS position, probes down (G38.2), applies the measured tool length offset, and retracts. Provided by the Rapid Change ATC, Manual Tool Changer, and Pneumatic ATC plugins - the exact motions come from that plugin's settings, including any Pre/Post TLS g-code hooks.","syntax":"$TLS","params":{},"example":"$TLS","tips":"Only works when one of the tool-changer plugins is installed and enabled. The macro expansion can be shown line by line by enabling \"show macro commands\" in the plugin settings.","keywords":["tool length","tls","tool setter","probe tool","rapidchange","atc","tool changer","offset"]},{"code":"$SLOT1","aliases":["$SLOT2","$SLOT<n>"],"name":"Go To Tool Slot n (Rapid Change ATC)","category":"plugin","modal":null,"desc":"Raises to safe Z, then rapids (G53 machine coordinates) to the XY position of magazine slot n as configured in the Rapid Change ATC plugin. $SLOT1, $slot2, $SLOT03 all work - leading zeros are tolerated. Slot numbers outside the configured pocket count are deliberately left alone (they fall through to the controller as unknown commands) so a typo cannot send the spindle to a nonexistent slot.","syntax":"$SLOT<n>","params":{},"example":"$SLOT3","tips":"Provided by the Rapid Change ATC plugin - only works when it is installed and enabled. Useful for aligning the magazine or verifying slot positions without a tool change.","keywords":["slot","pocket","magazine","rapidchange","atc","tool changer","position"]},{"code":"$POCKET1","aliases":[],"name":"Go To Pocket 1 (Manual Tool Changer)","category":"plugin","modal":null,"desc":"Raises to safe Z, then rapids (G53 machine coordinates) to the Pocket 1 XY position configured in the Manual Tool Changer plugin - the parking spot where manual tool swaps happen.","syntax":"$POCKET1","params":{},"example":"$POCKET1","tips":"Provided by the Manual Tool Changer plugin - only works when it is installed and enabled.","keywords":["pocket","manual tool change","tool changer","park","position"]},{"code":"$ADB_RETRACT","aliases":[],"name":"Retract Dust Boot (AutoDustboot)","category":"plugin","modal":null,"desc":"Retracts the pneumatic dust boot. The AutoDustboot plugin injects this automatically before tool changes (M6/M98) in a loaded job, but it can also be typed in the Console or embedded in your own macros.","syntax":"$ADB_RETRACT","params":{},"example":"$ADB_RETRACT","tips":"Provided by the AutoDustboot plugin - only works when it is installed and enabled.","keywords":["dust boot","dustboot","retract","pneumatic","adb"]},{"code":"$ADB_EXPAND","aliases":[],"name":"Expand Dust Boot (AutoDustboot)","category":"plugin","modal":null,"desc":"Expands (lowers) the pneumatic dust boot. The AutoDustboot plugin injects this automatically after the first rapid XY move following a tool change, and it can also be typed in the Console or embedded in macros.","syntax":"$ADB_EXPAND","params":{},"example":"$ADB_EXPAND","tips":"Provided by the AutoDustboot plugin - only works when it is installed and enabled.","keywords":["dust boot","dustboot","expand","deploy","pneumatic","adb"]}],"settings":[{"code":"$0","name":"Step pulse time","desc":"SLB-EXT default: 5 microseconds. Sets time length per step. Minimum 2 microseconds. This needs to be reduced from the default value of 10 when max. step rates exceed approximately 80 kHz.","keywords":["invert","pulse","signal","step","stepper","time"]},{"code":"$1","name":"Step idle delay","desc":"SLB-EXT default: 254 milliseconds. Sets a short hold delay when stopping to let dynamics settle before disabling steppers. Value 255 keeps motors enabled.","keywords":["delay","idle","invert","signal","step","stepper"]},{"code":"$2","name":"Step pulse invert","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Inverts the step signals (active low).","keywords":["invert","pulse","signal","step","stepper"]},{"code":"$3","name":"Step direction invert","desc":"SLB-EXT default: X: OFF Y: ON Z: ON A: OFF (6). Inverts the direction signals (active low).","keywords":["direction","invert","signal","step","stepper"]},{"code":"$4","name":"Invert stepper enable pin(s)","desc":"SLB-EXT default: X: ON Y: ON Z: ON A: ON (15). Inverts the stepper driver enable signals. Most drivers uses active low enable requiring inversion. NOTE: If the stepper drivers shares the same enable signal only X is used.","keywords":["enable","invert","pin","signal","stepper"]},{"code":"$5","name":"Invert limit pins","desc":"SLB-EXT default: X: ON Y: ON Z: ON A: ON (15). Inverts the axis limit input signals.","keywords":["invert","limit","pins","signal","stepper"]},{"code":"$6","name":"Invert probe pin","desc":"SLB-EXT default: Enabled (1). Inverts the probe input pin signal.","keywords":["invert","pin","probe","signal","stepper"]},{"code":"$7","name":"Deprecated","desc":"Deprecated","keywords":["deprecated"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$8","name":"Ganged axes direction invert","desc":"SLB-EXT default: Disabled (0). Inverts the direction signals for the second motor used for ganged axes. NOTE: This inversion will be applied in addition to the inversion from setting $3.","keywords":["axes","direction","ganged","invert","signal","stepper"]},{"code":"$9","name":"PWM Spindle","desc":"SLB-EXT default: Enable: ON RPM controls spindle en signal: OFF (1). Enable: Controls PWM output availability. RPM controls spindle enable signal: When M3 or M4 is active, S > 0 turns on spindle enable and S0 turns it off.","keywords":["invert","pwm","signal","spindle","stepper"]},{"code":"$10","name":"Status report options","desc":"SLB-EXT default: Position in machine coords: ON Buffer state: ON Line numbers: ON Feed & speed: ON Pin state: ON Work coord offset: ON Overrides: ON Probe coords: ON Buffer sync on WCO change: ON Parser state: OFF Alarm substatus: OFF Run substatus: OFF (511). Specifies optional data included in status reports. If Run substatus is enabled it may be used for simple probe protection. NOTE: Parser state will be sent separately after the status report and only on changes.","keywords":["options","report","status"]},{"code":"$11","name":"Junction deviation","desc":"SLB-EXT default: 0.010 mm. Sets how fast Grbl travels through consecutive motions. Lower value slows it down.","keywords":["deviation","junction"]},{"code":"$12","name":"Arc tolerance","desc":"SLB-EXT default: 0.002 mm. Sets the G2 and G3 arc tracing accuracy based on radial error. Beware: A very small value may effect performance.","keywords":["arc","tolerance"]},{"code":"$13","name":"Report in inches","desc":"SLB-EXT default: Disabled (0). Enables inch units when returning any position and rate value that is not a settings value.","keywords":["inches","report"]},{"code":"$14","name":"Invert control pins","desc":"SLB-EXT default: Reset: OFF Feed hold: ON Cycle start: ON Safety door: ON EStop: OFF (14). Inverts the control signals (active low). NOTE: Block delete, Optional stop, EStop and Probe connected are optional signals, availability is driver dependent.","keywords":["control","invert","pins"]},{"code":"$15","name":"Invert coolant pins","desc":"SLB-EXT default: Flood: OFF Mist: OFF (0). Inverts the coolant and mist signals (active low).","keywords":["coolant","invert","pins"]},{"code":"$16","name":"Invert spindle signals","desc":"SLB-EXT default: Spindle en: OFF Spindle dir: OFF PWM: OFF (0). Inverts the spindle on, counterclockwise and PWM signals (active low). NOTE: A hard reset of the controller is required after changing this setting.","keywords":["invert","signals","spindle"]},{"code":"$17","name":"Pullup disable control pins","desc":"SLB-EXT default: Reset: OFF Feed hold: OFF Cycle start: OFF Safety door: OFF EStop: OFF (0). Disable the control signals pullup resistors. Potentially enables pulldown resistor if available. NOTE: Block delete, Optional stop and EStop are optional signals, availability is driver dependent.","keywords":["control","disable","pins","pullup"]},{"code":"$18","name":"Pullup disable limit pins","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Disable the limit signals pullup resistors. Potentially enables pulldown resistor if available.","keywords":["disable","limit","pins","pullup"]},{"code":"$19","name":"Pullup disable probe pin","desc":"SLB-EXT default: Disabled (0). Disable the probe signal pullup resistor. Potentially enables pulldown resistor if available.","keywords":["disable","pin","probe","pullup"]},{"code":"$20","name":"Soft limits enable","desc":"SLB-EXT default: Disabled (0). Enables soft limits checks within machine travel and sets alarm when exceeded. Requires homing.","keywords":["enable","homing","limits","soft"]},{"code":"$21","name":"Hard limits enable","desc":"SLB-EXT default: Enable: OFF Strict mode: OFF (0). When enabled immediately halts motion and throws an alarm when a limit switch is triggered. In strict mode only homing is possible when a switch is engaged.","keywords":["enable","hard","homing","limits"]},{"code":"$22","name":"Homing cycle","desc":"SLB-EXT default: Enable: OFF Single axis commands: OFF Homing on startup: OFF Set machine origin: OFF Two switches share one input: OFF Allow manual: OFF Override locks: OFF Keep homed status on reset: OFF (0). Enables homing cycle. Requires limit switches on axes to be automatically homed. When `Enable single axis commands` is checked, single axis homing can be performed by $H<axis letter> commands. When `Allow manual` is checked, axes not homed automatically may be homed manually by $H or $H<axis letter> commands. `Override locks` is for allowing a soft reset to disable `Homing on startup required`.","keywords":["cycle","homing","limits"]},{"code":"$23","name":"Homing direction invert","desc":"SLB-EXT default: X: ON Y: ON Z: OFF A: ON (11). Homing searches for a switch in the positive direction. Set axis bit to search in negative direction.","keywords":["direction","homing","invert","limits"]},{"code":"$24","name":"Homing locate feed rate","desc":"SLB-EXT default: 150 mm/min. Feed rate to slowly engage limit switch to determine its location accurately.","keywords":["feed","homing","limits","locate","rate"]},{"code":"$25","name":"Homing search seek rate","desc":"SLB-EXT default: 4300 mm/min. Seek rate to quickly find the limit switch before the slower locating phase.","keywords":["homing","limits","rate","search","seek"]},{"code":"$26","name":"Homing switch debounce delay","desc":"SLB-EXT default: 25 milliseconds. Sets a short delay between phases of homing cycle to let a switch debounce.","keywords":["debounce","delay","homing","limits","switch"]},{"code":"$27","name":"Homing switch pull-off distance","desc":"SLB-EXT default: 1.5 mm. Retract distance after triggering switch to disengage it. Homing will fail if switch isn't cleared.","keywords":["distance","homing","limits","off","pull","switch"]},{"code":"$28","name":"G73 retract distance","desc":"SLB-EXT default: 0.1 mm. G73 retract distance (for chip breaking drilling).","keywords":["distance","retract"]},{"code":"$29","name":"Pulse delay","desc":"SLB-EXT default: 0 microseconds. Step pulse delay. Normally leave this at 0 as there is an implicit delay on direction changes when AMASS is active.","keywords":["delay","invert","pulse","signal","stepper"]},{"code":"$30","name":"Maximum spindle speed","desc":"SLB-EXT default: 24000 RPM. Maximum spindle speed, can be overridden by spindle plugins.","keywords":["maximum","speed","spindle"]},{"code":"$31","name":"Minimum spindle speed","desc":"SLB-EXT default: 7500 RPM. Minimum spindle speed, can be overridden by spindle plugins.","keywords":["minimum","speed","spindle"]},{"code":"$32","name":"Mode of operation","desc":"SLB-EXT default: Normal (0). Laser mode: consecutive G1/2/3 commands will not halt when spindle speed is changed. Lathe mode: allows use of G7, G8, G96 and G97.","keywords":["mode","operation","spindle"]},{"code":"$33","name":"Spindle PWM frequency","desc":"SLB-EXT default: 1000 Hz. Spindle PWM frequency.","keywords":["frequency","pwm","spindle"]},{"code":"$34","name":"Spindle PWM off value","desc":"SLB-EXT default: 0 percent. Spindle PWM off value in percent (duty cycle).","keywords":["off","pwm","spindle","value"]},{"code":"$35","name":"Spindle PWM min value","desc":"SLB-EXT default: 0 percent. Spindle PWM min value in percent (duty cycle).","keywords":["min","pwm","spindle","value"]},{"code":"$36","name":"Spindle PWM max value","desc":"SLB-EXT default: 100 percent. Spindle PWM max value in percent (duty cycle).","keywords":["max","pwm","spindle","value"]},{"code":"$37","name":"Steppers de-energize","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Specifies which steppers not to disable when stopped.","keywords":["energize","invert","signal","stepper","steppers"]},{"code":"$38","name":"Spindle pulses per revolution (PPR)","desc":"Spindle encoder pulses per revolution.","keywords":["spindle","pulses","per","revolution","ppr"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$39","name":"Enable legacy RT commands","desc":"SLB-EXT default: Enabled (1). Enables \"normal\" processing of ?, ! and ~ characters when part of $-setting or comment. If disabled then they are added to the input string instead.","keywords":["commands","enable","invert","legacy","signal","stepper"]},{"code":"$40","name":"Limit jog commands","desc":"SLB-EXT default: Enabled (1). Limit jog commands to machine limits for homed axes.","keywords":["commands","jog","limit"]},{"code":"$41","name":"Parking cycle","desc":"SLB-EXT default: Enable: ON Parking override control: OFF Deactivate upon init: OFF (1). Enables parking cycle, requires parking axis homed.","keywords":["cycle","parking"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$42","name":"Parking axis","desc":"SLB-EXT default: Z (2). Define which axis that performs the parking motion.","keywords":["axis","parking"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$43","name":"Homing passes","desc":"SLB-EXT default: 1. Number of homing passes. Minimum 1, maximum 128.","keywords":["homing","limits","passes"]},{"code":"$44","name":"Axes homing, first pass","desc":"SLB-EXT default: X: OFF Y: OFF Z: ON A: OFF (4). Axes to home in first pass.","keywords":["axes","first","homing","limits","pass"]},{"code":"$45","name":"Axes homing, second pass","desc":"SLB-EXT default: X: ON Y: ON Z: OFF A: OFF (3). Axes to home in second pass.","keywords":["axes","homing","limits","pass","second"]},{"code":"$46","name":"Axes homing, third pass","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Axes to home in third pass.","keywords":["axes","homing","limits","pass","third"]},{"code":"$47","name":"Axes homing, fourth pass","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Axes to home in fourth pass.","keywords":["axes","fourth","homing","limits","pass"]},{"code":"$48","name":"Axes homing, fifth phase","desc":"Axes to home in fifth phase.","keywords":["axes","homing","fifth","phase"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$49","name":"Axes homing, sixth phase","desc":"Axes to home in sixth phase.","keywords":["axes","homing","sixth","phase"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$56","name":"Parking pull-out distance","desc":"SLB-EXT default: 5 mm. Spindle pull-out and plunge distance in mm.Incremental distance.","keywords":["distance","out","parking","pull"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$57","name":"Parking pull-out rate","desc":"SLB-EXT default: 100 mm/min. Spindle pull-out/plunge slow feed rate in mm/min.","keywords":["out","parking","pull","rate"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$58","name":"Parking target","desc":"SLB-EXT default: -5 mm. Parking axis target. In mm, as machine coordinate [-max_travel, 0].","keywords":["parking","target"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$59","name":"Parking fast rate","desc":"SLB-EXT default: 500 mm/min. Parking fast rate to target after pull-out in mm/min.","keywords":["fast","parking","rate"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$60","name":"Restore overrides","desc":"SLB-EXT default: Enabled (1). Restore overrides to default values at program end.","keywords":["overrides","restore"]},{"code":"$61","name":"Safety door options","desc":"SLB-EXT default: Ignore when idle: ON Keep coolant state: ON (3). Enable this if it is desirable to open the safety door when in IDLE mode (eg. for jogging).","keywords":["door","options","safety"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$62","name":"Sleep enable","desc":"SLB-EXT default: Disabled (0). Enable sleep mode.","keywords":["enable","sleep"]},{"code":"$63","name":"Feed hold actions","desc":"SLB-EXT default: Disable laser: ON Restore spindle and coolant state: ON (3). Actions taken during feed hold and on resume from feed hold.","keywords":["actions","feed","hold"]},{"code":"$64","name":"Force init alarm","desc":"SLB-EXT default: Disabled (0). Starts Grbl in alarm mode after a cold reset.","keywords":["alarm","force","init"]},{"code":"$65","name":"Probing feed override","desc":"SLB-EXT default: Disabled (0). Allow feed override during probing.","keywords":["feed","override","probing"]},{"code":"$66","name":"Spindle linearisation, 1st point","desc":"Comma separated list of values: RPM_MIN, RPM_LINE_A1, RPM_LINE_B1, set to blank to disable.","keywords":["spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$67","name":"Spindle linearisation, 2nd point","desc":"Comma separated list of values: RPM_POINT12, RPM_LINE_A2, RPM_LINE_B2, set to blank to disable.","keywords":["spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$68","name":"Spindle linearisation, 3rd point","desc":"Comma separated list of values: RPM_POINT23, RPM_LINE_A3, RPM_LINE_B3, set to blank to disable.","keywords":["spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$69","name":"Spindle linearisation, 4th point","desc":"Comma separated list of values: RPM_POINT34, RPM_LINE_A4, RPM_LINE_B4, set to blank to disable.","keywords":["spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$70","name":"Network services","desc":"SLB-EXT default: Telnet: ON Websocket: ON FTP: ON (11). Network services/protocols to enable. NOTE: A hard reset of the controller is required after changing this setting.","keywords":["ethernet","ip","network","services"]},{"code":"$90","name":"Spindle sync P-gain","desc":"Spindle sync P-gain","keywords":["spindle","sync","gain"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$91","name":"Spindle sync I-gain","desc":"Spindle sync I-gain","keywords":["spindle","sync","gain"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$92","name":"Spindle sync D-gain","desc":"Spindle sync D-gain","keywords":["spindle","sync","gain"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$95","name":"Spindle sync PID max I error","desc":"Spindle sync PID max integrator error.","keywords":["spindle","sync","pid","max","error"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$100","name":"X-axis travel resolution","desc":"SLB-EXT default: 800 step/mm. Travel resolution in steps per millimeter.","keywords":["axis","calibration","motion","resolution","steps","travel"]},{"code":"$101","name":"Y-axis travel resolution","desc":"SLB-EXT default: 800 step/mm. Travel resolution in steps per millimeter.","keywords":["axis","calibration","motion","resolution","steps","travel"]},{"code":"$102","name":"Z-axis travel resolution","desc":"SLB-EXT default: 800 step/mm. Travel resolution in steps per millimeter.","keywords":["axis","calibration","motion","resolution","steps","travel"]},{"code":"$103","name":"A-axis travel resolution","desc":"SLB-EXT default: 79.012345679 step/deg. Travel resolution in steps per millimeter.","keywords":["axis","calibration","motion","resolution","steps","travel"]},{"code":"$110","name":"X-axis maximum rate","desc":"SLB-EXT default: 4000 mm/min. Maximum rate. Used as G0 rapid rate.","keywords":["axis","calibration","maximum","motion","rate","steps"]},{"code":"$111","name":"Y-axis maximum rate","desc":"SLB-EXT default: 4000 mm/min. Maximum rate. Used as G0 rapid rate.","keywords":["axis","calibration","maximum","motion","rate","steps"]},{"code":"$112","name":"Z-axis maximum rate","desc":"SLB-EXT default: 4000 mm/min. Maximum rate. Used as G0 rapid rate.","keywords":["axis","calibration","maximum","motion","rate","steps"]},{"code":"$113","name":"A-axis maximum rate","desc":"SLB-EXT default: 8000 deg/min. Maximum rate. Used as G0 rapid rate.","keywords":["axis","calibration","maximum","motion","rate","steps"]},{"code":"$120","name":"X-axis acceleration","desc":"SLB-EXT default: 750 mm/sec^2. Acceleration. Used for motion planning to not exceed motor torque and lose steps.","keywords":["acceleration","axis","calibration","motion","steps"]},{"code":"$121","name":"Y-axis acceleration","desc":"SLB-EXT default: 750 mm/sec^2. Acceleration. Used for motion planning to not exceed motor torque and lose steps.","keywords":["acceleration","axis","calibration","motion","steps"]},{"code":"$122","name":"Z-axis acceleration","desc":"SLB-EXT default: 750 mm/sec^2. Acceleration. Used for motion planning to not exceed motor torque and lose steps.","keywords":["acceleration","axis","calibration","motion","steps"]},{"code":"$123","name":"A-axis acceleration","desc":"SLB-EXT default: 1000 deg/sec^2. Acceleration. Used for motion planning to not exceed motor torque and lose steps.","keywords":["acceleration","axis","calibration","motion","steps"]},{"code":"$130","name":"X-axis maximum travel","desc":"SLB-EXT default: 810 mm. Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances.","keywords":["axis","calibration","maximum","motion","steps","travel"]},{"code":"$131","name":"Y-axis maximum travel","desc":"SLB-EXT default: 855 mm. Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances.","keywords":["axis","calibration","maximum","motion","steps","travel"]},{"code":"$132","name":"Z-axis maximum travel","desc":"SLB-EXT default: 120 mm. Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances.","keywords":["axis","calibration","maximum","motion","steps","travel"]},{"code":"$133","name":"A-axis maximum travel","desc":"SLB-EXT default: 0 deg. Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances.","keywords":["axis","calibration","maximum","motion","steps","travel"]},{"code":"$140","name":"X-axis motor current","desc":"SLB-EXT default: 2800 mA. Motor current in mA (RMS). NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","motor","trinamic"]},{"code":"$141","name":"Y-axis motor current","desc":"Motor current in mA (RMS). NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","motor","trinamic"]},{"code":"$142","name":"Z-axis motor current","desc":"Motor current in mA (RMS). NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","motor","trinamic"]},{"code":"$143","name":"A-axis motor current","desc":"SLB-EXT default: 0. Motor current in mA (RMS). NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","motor","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$150","name":"X-axis microsteps","desc":"SLB-EXT default: 32 steps. Microsteps per fullstep. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","microsteps","motor","trinamic"]},{"code":"$151","name":"Y-axis microsteps","desc":"Microsteps per fullstep. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","microsteps","motor","trinamic"]},{"code":"$152","name":"Z-axis microsteps","desc":"Microsteps per fullstep. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","microsteps","motor","trinamic"]},{"code":"$153","name":"A-axis microsteps","desc":"SLB-EXT default: 16. Microsteps per fullstep. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","microsteps","motor","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$180","name":"X-axis homing locate feed rate","desc":"SLB-EXT default: 150 mm/min. Feed rate to slowly engage limit switch to determine its location accurately. NOTE: Defaults to $24 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","feed","homing","limits","locate","rate"]},{"code":"$181","name":"Y-axis homing locate feed rate","desc":"Feed rate to slowly engage limit switch to determine its location accurately. NOTE: Defaults to $24 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","feed","homing","limits","locate","rate"]},{"code":"$182","name":"Z-axis homing locate feed rate","desc":"Feed rate to slowly engage limit switch to determine its location accurately. NOTE: Defaults to $24 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","feed","homing","limits","locate","rate"]},{"code":"$183","name":"A-axis homing locate feed rate","desc":"Feed rate to slowly engage limit switch to determine its location accurately. NOTE: Defaults to $24 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","feed","homing","limits","locate","rate"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$190","name":"X-axis homing search seek rate","desc":"SLB-EXT default: 4300 mm/min. Seek rate to quickly find the limit switch before the slower locating phase. NOTE: Defaults to $25 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","homing","limits","rate","search","seek"]},{"code":"$191","name":"Y-axis homing search seek rate","desc":"Seek rate to quickly find the limit switch before the slower locating phase. NOTE: Defaults to $25 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","homing","limits","rate","search","seek"]},{"code":"$192","name":"Z-axis homing search seek rate","desc":"Seek rate to quickly find the limit switch before the slower locating phase. NOTE: Defaults to $25 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","homing","limits","rate","search","seek"]},{"code":"$193","name":"A-axis homing search seek rate","desc":"Seek rate to quickly find the limit switch before the slower locating phase. NOTE: Defaults to $25 setting if axis isn't controlled by a Trinamic driver.","keywords":["axis","homing","limits","rate","search","seek"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$200","name":"X-axis StallGuard2 fast threshold","desc":"SLB-EXT default: 22. StallGuard threshold for fast (seek) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","fast","motor","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$201","name":"Y-axis StallGuard2 fast threshold","desc":"StallGuard threshold for fast (seek) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","fast","motor","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$202","name":"Z-axis StallGuard2 fast threshold","desc":"StallGuard threshold for fast (seek) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","fast","motor","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$203","name":"A-axis StallGuard2 fast threshold","desc":"StallGuard threshold for fast (seek) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","fast","motor","stallguard","threshold","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$210","name":"X-axis hold current","desc":"SLB-EXT default: 35 %. Motor current at standstill as a percentage of full current. NOTE: If grblHAL is configured to disable motors on standstill this setting has no use. Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","hold","motor","trinamic"]},{"code":"$211","name":"Y-axis hold current","desc":"Motor current at standstill as a percentage of full current. NOTE: If grblHAL is configured to disable motors on standstill this setting has no use. Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","hold","motor","trinamic"]},{"code":"$212","name":"Z-axis hold current","desc":"Motor current at standstill as a percentage of full current. NOTE: If grblHAL is configured to disable motors on standstill this setting has no use. Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","hold","motor","trinamic"]},{"code":"$213","name":"A-axis hold current","desc":"SLB-EXT default: 50. Motor current at standstill as a percentage of full current. NOTE: If grblHAL is configured to disable motors on standstill this setting has no use. Only used for axes controlled by a Trinamic driver.","keywords":["axis","current","driver","hold","motor","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$220","name":"X-axis stallGuard2 slow threshold","desc":"SLB-EXT default: 22. StallGuard threshold for slow (feed) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","motor","slow","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$221","name":"Y-axis stallGuard2 slow threshold","desc":"StallGuard threshold for slow (feed) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","motor","slow","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$222","name":"Z-axis stallGuard2 slow threshold","desc":"StallGuard threshold for slow (feed) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","motor","slow","stallguard","threshold","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$223","name":"A-axis stallGuard2 slow threshold","desc":"StallGuard threshold for slow (feed) homing phase. NOTE: Only used for axes controlled by a Trinamic driver.","keywords":["axis","driver","motor","slow","stallguard","threshold","trinamic"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$300","name":"Hostname","desc":"SLB-EXT default: grblHAL. Network hostname. ~Controller reset required for setting change to take effect~","keywords":["ethernet","hostname","ip","network"]},{"code":"$301","name":"IP mode","desc":"SLB-EXT default: Static (0). IP mode. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ip","mode","network"]},{"code":"$302","name":"IP address","desc":"SLB-EXT default: 192.168.5.1. Static IP address. ~Controller reset required for setting change to take effect~","keywords":["address","ethernet","ip","network"]},{"code":"$303","name":"Gateway","desc":"SLB-EXT default: 192.168.5.1. Static gateway address. ~Controller reset required for setting change to take effect~","keywords":["ethernet","gateway","ip","network"]},{"code":"$304","name":"Netmask","desc":"SLB-EXT default: 255.255.255.0. Static netmask. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ip","netmask","network"]},{"code":"$305","name":"Telnet port","desc":"SLB-EXT default: 23. (Raw) Telnet port number listening for incoming connections. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ip","network","port","telnet"]},{"code":"$307","name":"Websocket port","desc":"SLB-EXT default: 80. Websocket port number listening for incoming connections. NOTE: WebUI requires this to be HTTP port number + 1. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ip","network","port","websocket"]},{"code":"$308","name":"FTP port","desc":"SLB-EXT default: 21. FTP port number listening for incoming connections. ~Controller reset required for setting change to take effect~","keywords":["ethernet","ftp","ip","network","port"]},{"code":"$338","name":"Trinamic driver","desc":"SLB-EXT default: X: ON Y: ON Z: ON A: OFF (7). Enable SPI or UART controlled Trinamic drivers for axes.","keywords":["driver","ethernet","ip","motor","network","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$339","name":"Sensorless homing","desc":"SLB-EXT default: X: OFF Y: OFF Z: OFF A: OFF (0). Enable sensorless homing for axes. Requires SPI or UART controlled Trinamic drivers.","keywords":["driver","ethernet","homing","ip","motor","network","sensorless","trinamic"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$340","name":"Spindle at speed tolerance","desc":"SLB-EXT default: 0 percent. Spindle at speed tolerance as percentage deviation from programmed speed, set to 0 to disable. If not within tolerance when checked after spindle on delay ($392) alarm 14 is raised.","keywords":["speed","spindle","tolerance"]},{"code":"$341","name":"Tool change mode","desc":"SLB-EXT default: Normal (0). Normal: allows jogging for manual touch off. Set new position manually. Manual touch off: retracts tool axis to home position for tool change, use jogging or $TPW for touch off. Manual touch off @ G59.3: retracts tool axis to home position then to G59.3 position for tool change, use jogging or $TPW for touch off. Automatic touch off @ G59.3: retracts tool axis to home position for tool change, then to G59.3 position for automatic touch off. All modes except \"Normal\" and \"Ignore M6\" returns the tool (controlled point) to original position after touch off.","keywords":["change","mode","probe","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$342","name":"Tool change probing distance","desc":"SLB-EXT default: 30 mm. Maximum probing distance for automatic or $TPW touch off.","keywords":["change","distance","probe","probing","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$343","name":"Tool change locate feed rate","desc":"SLB-EXT default: 25 mm/min. Feed rate to slowly engage tool change sensor to determine the tool offset accurately.","keywords":["change","feed","locate","probe","rate","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$344","name":"Tool change search seek rate","desc":"SLB-EXT default: 200 mm/min. Seek rate to quickly find the tool change sensor before the slower locating phase.","keywords":["change","probe","rate","search","seek","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$345","name":"Tool change probe pull-off rate","desc":"SLB-EXT default: 200 mm/min. Pull-off rate for the retract move before the slower locating phase.","keywords":["change","off","probe","pull","rate","tool","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$346","name":"Restore position after M6","desc":"SLB-EXT default: Enabled (1). When set the spindle is moved so that the controlled point (tool tip) is the same as before the M6 command, if not the spindle is only moved to the Z home position.","keywords":["after","position","probe","restore","tool change","toolchange","touch off"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$347","name":"Dual axis length fail","desc":"(percent) Dual axis length fail in percent of axis max travel.","keywords":["dual","axis","length","fail"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$348","name":"Dual axis length fail min","desc":"(mm) Dual axis length fail minimum distance.","keywords":["dual","axis","length","fail","min"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$349","name":"Dual axis length fail max","desc":"(mm) Dual axis length fail maximum distance.","keywords":["dual","axis","length","fail","max"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$370","name":"Invert I/O Port inputs","desc":"SLB-EXT default: (0). Invert IOPort inputs.","keywords":["inputs","invert","port"]},{"code":"$372","name":"Invert I/O Port outputs","desc":"SLB-EXT default: (0). Invert IOPort output.","keywords":["invert","outputs","port"]},{"code":"$374","name":"Modbus baud rate","desc":"SLB-EXT default: 19200 (3).","keywords":["baud","modbus","rate","rs485","vfd"]},{"code":"$375","name":"Modbus RX timeout","desc":"SLB-EXT default: 50 milliseconds.","keywords":["modbus","rs485","timeout","vfd"]},{"code":"$376","name":"Rotational axes","desc":"SLB-EXT default: A-Axis: ON (1).","keywords":["axes","rotational"]},{"code":"$384","name":"Disable G92 persistence","desc":"SLB-EXT default: Disabled (0). Disables save/restore of G92 offset to non-volatile storage (NVS).","keywords":["disable","persistence"]},{"code":"$392","name":"Spindle on delay","desc":"SLB-EXT default: 11 s. Delay to allow spindle to spin up after safety door is opened.","keywords":["delay","spindle"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$393","name":"Coolant on delay","desc":"SLB-EXT default: 1 s. Delay to allow coolant to restart after safety door is opened.","keywords":["coolant","delay"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$394","name":"Spindle off delay (s)","desc":"grblHAL: pause after M5 — spin-down time.","keywords":["spindle","delay","spindown","off delay"]},{"code":"$395","name":"Default spindle","desc":"SLB-EXT default: SLB_SPINDLE (0). Spindle selected on startup.","keywords":["default","laser","spindle"]},{"code":"$398","name":"Planner buffer blocks","desc":"SLB-EXT default: 128. Number of blocks in the planner buffer. ~Controller reset required for setting change to take effect~","keywords":["blocks","buffer","planner"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$399","name":"CAN bus baud rate","desc":"CAN bus baud rate","keywords":["can","bus","baud","rate"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$450","name":"Button 1 action","desc":"SLB-EXT default: Cycle start (1). Assign a real-time action to button 1, or run your own macro g-code.","keywords":["action","button","macro"]},{"code":"$451","name":"Button 2 action","desc":"SLB-EXT default: Pause (2). Assign a real-time action to button 2, or run your own macro g-code.","keywords":["action","button","macro"]},{"code":"$452","name":"Button 3 action","desc":"SLB-EXT default: Halt (4). Assign a real-time action to button 3, or run your own macro g-code.","keywords":["action","button","macro"]},{"code":"$453","name":"Button 1 macro","desc":"SLB-EXT default: G4P0. Macro content, limited to 127 characters. Separate lines with the vertical bar character |.","keywords":["action","button","macro"]},{"code":"$454","name":"Button 2 macro","desc":"SLB-EXT default: G4P0. Macro content, limited to 127 characters. Separate lines with the vertical bar character |.","keywords":["action","button","macro"]},{"code":"$455","name":"Button 3 macro","desc":"SLB-EXT default: G4P0. Macro content, limited to 127 characters. Separate lines with the vertical bar character |.","keywords":["action","button","macro"]},{"code":"$456","name":"Aux output 0 trigger","desc":"SLB-EXT default: Spindle/Laser enable (0). A second, more common action can be assigned to trigger this output. M62/63 P# is always available as a buffered on/off or M64/65 P# as an immediate on/off.","keywords":["action","aux","button","macro","output","trigger"]},{"code":"$457","name":"Aux output 1 trigger","desc":"SLB-EXT default: Flood enable (2). A second, more common action can be assigned to trigger this output. M62/63 P# is always available as a buffered on/off or M64/65 P# as an immediate on/off.","keywords":["action","aux","button","macro","output","trigger"]},{"code":"$458","name":"Aux output 2 trigger","desc":"SLB-EXT default: Spindle/Laser enable (0). A second, more common action can be assigned to trigger this output. M62/63 P# is always available as a buffered on/off or M64/65 P# as an immediate on/off.","keywords":["action","aux","button","macro","output","trigger"]},{"code":"$459","name":"Aux output 3 trigger","desc":"SLB-EXT default: Flood enable (2). A second, more common action can be assigned to trigger this output. M62/63 P# is always available as a buffered on/off or M64/65 P# as an immediate on/off.","keywords":["action","aux","button","macro","output","trigger"]},{"code":"$462","name":"Run/stop register","desc":"SLB-EXT default: 8192 decimal. MODVFD register for run/stop.","keywords":["modbus","register","rs485","run","stop","vfd"]},{"code":"$463","name":"Frequency set register","desc":"SLB-EXT default: 8193 decimal. MODVFD register to set frequency.","keywords":["frequency","modbus","register","rs485","set","vfd"]},{"code":"$464","name":"Frequency get register","desc":"SLB-EXT default: 8451 decimal. MODVFD register to get frequency.","keywords":["frequency","get","modbus","register","rs485","vfd"]},{"code":"$465","name":"Run CW command","desc":"SLB-EXT default: 18 decimal. MODVFD command word for CW.","keywords":["command","modbus","rs485","run","vfd"]},{"code":"$466","name":"Run CCW command","desc":"SLB-EXT default: 34 decimal. MODVFD command word for CCW.","keywords":["ccw","command","modbus","rs485","run","vfd"]},{"code":"$467","name":"Stop command","desc":"SLB-EXT default: 1 decimal. MODVFD command word for stop.","keywords":["command","modbus","rs485","stop","vfd"]},{"code":"$468","name":"RPM input multiplier","desc":"SLB-EXT default: 50. MODVFD RPM value multiplier for programming RPM.","keywords":["input","modbus","multiplier","rpm","rs485","vfd"]},{"code":"$469","name":"RPM input divider","desc":"SLB-EXT default: 60. MODVFD RPM value divider for programming RPM.","keywords":["divider","input","modbus","rpm","rs485","vfd"]},{"code":"$470","name":"RPM output multiplier","desc":"SLB-EXT default: 60. MODVFD RPM value multiplier for reading RPM.","keywords":["modbus","multiplier","output","rpm","rs485","vfd"]},{"code":"$471","name":"RPM output divider","desc":"SLB-EXT default: 100. MODVFD RPM value divider for reading RPM.","keywords":["divider","modbus","output","rpm","rs485","vfd"]},{"code":"$478","name":"Spindle 2 Modbus address","desc":"SLB-EXT default: 3. Spindle 2 Modbus address.","keywords":["address","modbus","rs485","spindle","vfd"]},{"code":"$479","name":"Spindle 3 Modbus address","desc":"SLB-EXT default: 4. Spindle 3 Modbus address.","keywords":["address","modbus","rs485","spindle","vfd"]},{"code":"$481","name":"Autoreport interval","desc":"SLB-EXT default: 0 ms. Interval the real time report will be sent, set to 0 to disable. ~Controller reset required for setting change to take effect~","keywords":["autoreport","interval"]},{"code":"$482","name":"Timezone offset","desc":"Offset in hours from UTC.","keywords":["timezone","offset"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$484","name":"Unlock required after E-stop","desc":"SLB-EXT default: Enabled (1). If set, unlock (by sending $X) is required after resetting a cleared E-Stop condition.","keywords":["after","required","stop","unlock"]},{"code":"$485","name":"Keep tool number over reboot","desc":"Keep tool number over reboot","keywords":["keep","tool","number","over","reboot"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$486","name":"Lock coordinate systems","desc":"SLB-EXT default: G59.1: OFF G59.2: OFF G59.3: OFF (0). Lock coordinate systems against accidental changes.","keywords":["coordinate","lock","systems"]},{"code":"$487","name":"PWM2 spindle on port","desc":"On/off aux port.","keywords":["pwm","spindle","port"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$488","name":"PWM2 spindle direction port","desc":"Direction aux port, set to -1 if not required.","keywords":["pwm","spindle","direction","port"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$489","name":"PWM2 spindle PWM port","desc":"Spindle analog aux port. Must be PWM capable!","keywords":["pwm","spindle","port"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$511","name":"Spindle 1","desc":"SLB-EXT default: SLB_LASER (7). Spindle to use as spindle 1. ~Controller reset required for setting change to take effect~","keywords":["laser","spindle"]},{"code":"$512","name":"Spindle 2","desc":"SLB-EXT default: MODVFD (5). Spindle to use as spindle 2. ~Controller reset required for setting change to take effect~","keywords":["laser","spindle"]},{"code":"$513","name":"Spindle 3","desc":"SLB-EXT default: Disabled (8). Spindle to use as spindle 3. ~Controller reset required for setting change to take effect~","keywords":["laser","spindle"]},{"code":"$519","name":"Encoder spindle","desc":"Specifies which spindle has the encoder attached.","keywords":["encoder","spindle"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$520","name":"Spindle 0 tool number start","desc":"SLB-EXT default: 0. Start of tool numbers for selecting spindle 0 (default spindle). Normally leave this at 0.","keywords":["laser","number","spindle","start","tool"]},{"code":"$521","name":"Spindle 1 tool number start","desc":"SLB-EXT default: 0. Start of tool numbers for selecting spindle 1.","keywords":["laser","number","spindle","start","tool"]},{"code":"$522","name":"Spindle 2 tool number start","desc":"SLB-EXT default: 0. Start of tool numbers for selecting spindle 2.","keywords":["laser","number","spindle","start","tool"]},{"code":"$523","name":"Spindle 3 tool number start","desc":"SLB-EXT default: 0. Start of tool numbers for selecting spindle 3.","keywords":["laser","number","spindle","start","tool"]},{"code":"$534","name":"Output NGC debug messages","desc":"Example: (debug, metric mode: #<_metric>, coord system: #5220)","keywords":["output","ngc","debug","messages"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$536","name":"LED strip 1 length","desc":"Number of LEDS in strip 1.","keywords":["led","strip","length"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$537","name":"LED strip 2 length","desc":"Number of LEDS in strip 2.","keywords":["led","strip","length"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$538","name":"Fast rotary go to G28","desc":"Fast rotary go to G28","keywords":["fast","rotary"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$539","name":"Spindle off delay","desc":"(s) Spindle off delay","keywords":["spindle","off","delay"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$650","name":"Chopper toff","desc":"SLB-EXT default: 1. Off time. Duration of slow decay phase as a multiple of system clock periods: NCLK= 24 + (32 x TOFF). This will limit the maximum chopper frequency (0-15). 0: MOSFETs shut off, driver disabled. 1: Use with TBL of minimum 24 clocks.","keywords":["chopper","toff"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$651","name":"Chopper tbl","desc":"SLB-EXT default: 1. Blanking time interval in system clock periods (0-3 = 16,24,36,54). Needs to cover the switching event and the duration of the ringing on the sense resistor.","keywords":["chopper","tbl"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$652","name":"Chopper chm","desc":"SLB-EXT default: 0. Chopper mode. Affects HDEC, HEND, and HSTRT parameters. 0: Standard mode (SpreadCycle). 1: Constant TOFF with fast decay time. Fast decay is after on time. Fast decay time is also terminated when the negative nominal current is reached.","keywords":["chm","chopper"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$653","name":"Chopper hstr","desc":"SLB-EXT default: 2. CHM=0: Hysteresis start, offset from HEND (0-7 = 1-8). To be effective, HEND+HSTRT must be ≤15. CHM=1: Fast decay time. Three least-significant bits of the duration of the fast decay phase. The MSB is HDEC0. Fast decay time is a multiple of system clock periods: NCLK= 32 x (HDEC0+HSTRT).","keywords":["chopper","hstr"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$654","name":"Chopper hend","desc":"SLB-EXT default: 8. Can be either negative, zero, or positive, 0-15 = -3 to 12. CHM=0: Hysteresis end (low). Sets the hysteresis end value after a number of decrements, used for the hysteresis chopper and controlled by HDEC. HSTRT+HEND must be less than 16. 1/512 adds to the current setting. CHM=1: Sine wave offset. A positive offset corrects for zero crossing error. 1/512 adds to the absolute value of each sine wave entry.","keywords":["chopper","hend"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$655","name":"Chopper hdec","desc":"SLB-EXT default: 0. CHM=0: Hysteresis decrement interval period in system clock periods. Determines the slope of the hysteresis during on time from fast to very slow (0-3 = 16,32,48,64). CHM=1: Fast decay mode.","keywords":["chopper","hdec"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$656","name":"Chopper rndtf","desc":"SLB-EXT default: 1. Change from fixed to randomized TOFF times, by dNCLK= -24 to +6 clocks. Only for CHM=1.","keywords":["chopper","rndtf"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$657","name":"THRESH","desc":"SLB-EXT default: 22. StallGuard threshold.","keywords":["thresh"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$658","name":"CoolStep semin","desc":"SLB-EXT default: 7. Lower CoolStep threshold. If the SG value falls below SEMIN x 32, the coil current scaling factor is increased (0-15). 0: CoolStep disabled.","keywords":["coolstep","semin"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$659","name":"CoolStep seup","desc":"SLB-EXT default: 3. Number of increments of the coil current each time SG is sampled below the lower threshold (0-3 = 1,2,4,8).","keywords":["coolstep","seup"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$660","name":"CoolStep semax","desc":"SLB-EXT default: 0. Upper CoolStep threshold offset from lower threshold. If SG is sampled above (SEMIN+SEMAX+1)x32 enough times, the coil current scaling factor is decremented (0-15).","keywords":["coolstep","semax"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$661","name":"CoolStep sedn","desc":"SLB-EXT default: 3. Number of times SG must be sampled above the upper threshold before the coil current is decremented (0-3 = 32,8,2,1).","keywords":["coolstep","sedn"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$662","name":"CoolStep seimin","desc":"SLB-EXT default: 0. Minimum CoolStep current as a factor of the set motor current. 0: 1/2, 1: 1/4","keywords":["coolstep","seimin"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$663","name":"drvconf_reg","desc":"SLB-EXT default: 41759. DRVCONF register defaults 0xA31F. All protections enabled.","keywords":["drvconf","reg"],"tips":"Sienci marks this as advanced - supported, but change with care."},{"code":"$664","name":"Ring pixels","desc":"SLB-EXT default: 0. Number of individual pixels or LEDs connected. ~Controller reset required for setting change to take effect~","keywords":["led","lights","pixels","ring"]},{"code":"$665","name":"Rail pixels","desc":"SLB-EXT default: 1. Number of individual pixels or LEDs connected. Include the onboard LED. ~Controller reset required for setting change to take effect~","keywords":["led","lights","pixels","rail"]},{"code":"$666","name":"Using add-ons","desc":"SLB-EXT default: (0). Sienci specific capability flags.","keywords":["add","ons","using"],"tips":"Sienci marks this as currently unused on the SLB - it may still apply on the SLB-EXT; run $ES to check your build."},{"code":"$668","name":"Invert TLS input","desc":"SLB-EXT default: Enabled (1). Invert the TLS input ahead of the OR function. ~Controller reset required for setting change to take effect~","keywords":["input","invert","tls"]},{"code":"$671","name":"Invert home inputs","desc":"Inverts the axis home input signals.","keywords":["invert","home","inputs"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$673","name":"Coolant on delay","desc":"(s) Delay to allow coolant to start. 0 or 0.5 - 20s.","keywords":["coolant","delay"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$676","name":"Reset actions","desc":"Controls actions taken on a soft reset.","keywords":["reset","actions"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$680","name":"Stepper enable delay","desc":"(ms) Delay from stepper enable to first step output. The driver typically adds ~2ms to this.","keywords":["stepper","enable","delay"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$681","name":"ModBus serial format","desc":"ModBus serial format","keywords":["modbus","serial","format"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$700","name":"Subroutine options","desc":"Enable prescan for internal M98 subroutines.","keywords":["subroutine","options"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$709","name":"PWM2 spindle options","desc":"Options for the secondary PWM spindle output (PWM2, the SLB-EXT laser channel).","keywords":["laser","options","pwm","pwm2","spindle"]},{"code":"$716","name":"PWM2 spindle signals invert","desc":"Inverts the PWM2 (laser) enable, counterclockwise and PWM signals (active low). Hard reset required after changing.","keywords":["invert","laser","pwm","pwm2","signals","spindle"],"tips":"On older SLB 5.0.x firmware this lived at $743 (Invert laser signals)."},{"code":"$730","name":"Maximum laser power","desc":"SLB-EXT default: 255. Maximum S word power for laser.","keywords":["laser","maximum","power","pwm"]},{"code":"$731","name":"Minimum laser power","desc":"SLB-EXT default: 0. Minimum S word power for laser.","keywords":["laser","minimum","power","pwm"]},{"code":"$733","name":"Laser PWM frequency","desc":"SLB-EXT default: 1000 Hz. Laser PWM frequency.","keywords":["frequency","laser","pwm"]},{"code":"$734","name":"Laser PWM off value","desc":"SLB-EXT default: 0 percent. Laser PWM off value in percent (duty cycle).","keywords":["laser","off","pwm","value"]},{"code":"$735","name":"Laser PWM min value","desc":"SLB-EXT default: 0 percent. Laser PWM min value in percent (duty cycle).","keywords":["laser","min","pwm","value"]},{"code":"$736","name":"Laser PWM max value","desc":"SLB-EXT default: 100 percent. Laser PWM max value in percent (duty cycle).","keywords":["laser","max","pwm","value"]},{"code":"$737","name":"PWM2 spindle linearisation, 1st point","desc":"Comma separated list of values: RPM_MIN, RPM_LINE_A1, RPM_LINE_B1, set to blank to disable.","keywords":["pwm","spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$738","name":"PWM2 spindle linearisation, 2nd point","desc":"Comma separated list of values: RPM_POINT12, RPM_LINE_A2, RPM_LINE_B2, set to blank to disable.","keywords":["pwm","spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$739","name":"PWM2 spindle linearisation, 3rd point","desc":"Comma separated list of values: RPM_POINT23, RPM_LINE_A3, RPM_LINE_B3, set to blank to disable.","keywords":["pwm","spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$740","name":"PWM2 spindle linearisation, 4th point","desc":"Comma separated list of values: RPM_POINT34, RPM_LINE_A4, RPM_LINE_B4, set to blank to disable.","keywords":["pwm","spindle","linearisation","point"],"tips":"Core grblHAL setting - only present if your firmware build includes the feature. The reference flags whether your controller has it."},{"code":"$742","name":"Motor warning inputs enable","desc":"Enables the external stepper driver warning inputs per motor (SLB-EXT external drivers report warnings before faulting).","keywords":["alarm","driver","enable","fault","inputs","motor","warning"],"tips":"Current Main_grblHAL numbering. On older SLB 5.0.x firmware $742 was the Laser Y offset - that is now $771."},{"code":"$743","name":"Invert motor warning inputs","desc":"Inverts the motor warning input signals (active low).","keywords":["alarm","driver","fault","inputs","invert","motor","warning"],"tips":"On older SLB 5.0.x firmware $743 was Invert laser signals - that is now $716."},{"code":"$744","name":"Motor fault inputs enable","desc":"Enables the external stepper driver fault/alarm inputs per motor. A fault triggers an alarm and halts the machine.","keywords":["alarm","driver","enable","fault","inputs","motor"]},{"code":"$745","name":"Invert motor fault inputs","desc":"Inverts the motor fault input signals (active low).","keywords":["alarm","driver","fault","inputs","invert","motor"]},{"code":"$750","name":"Macro 0 content","desc":"G-code for aux-input macro 0. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $760) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$751","name":"Macro 1 content","desc":"G-code for aux-input macro 1. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $761) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$752","name":"Macro 2 content","desc":"G-code for aux-input macro 2. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $762) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$753","name":"Macro 3 content","desc":"G-code for aux-input macro 3. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $763) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$754","name":"Macro 4 content","desc":"G-code for aux-input macro 4. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $764) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$755","name":"Macro 5 content","desc":"G-code for aux-input macro 5. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $765) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$756","name":"Macro 6 content","desc":"G-code for aux-input macro 6. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $766) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$757","name":"Macro 7 content","desc":"G-code for aux-input macro 7. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $767) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$758","name":"Macro 8 content","desc":"G-code for aux-input macro 8. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $768) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$759","name":"Macro 9 content","desc":"G-code for aux-input macro 9. Separate lines with the vertical bar character |. Runs when the assigned aux input (set by $769) triggers; controller must be Idle.","keywords":["action","aux input","content","macro"]},{"code":"$760","name":"Macro 0 trigger port","desc":"Aux input port number that triggers macro 0 (content in $750). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$761","name":"Macro 1 trigger port","desc":"Aux input port number that triggers macro 1 (content in $751). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$762","name":"Macro 2 trigger port","desc":"Aux input port number that triggers macro 2 (content in $752). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$763","name":"Macro 3 trigger port","desc":"Aux input port number that triggers macro 3 (content in $753). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$764","name":"Macro 4 trigger port","desc":"Aux input port number that triggers macro 4 (content in $754). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$765","name":"Macro 5 trigger port","desc":"Aux input port number that triggers macro 5 (content in $755). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$766","name":"Macro 6 trigger port","desc":"Aux input port number that triggers macro 6 (content in $756). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$767","name":"Macro 7 trigger port","desc":"Aux input port number that triggers macro 7 (content in $757). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$768","name":"Macro 8 trigger port","desc":"Aux input port number that triggers macro 8 (content in $758). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$769","name":"Macro 9 trigger port","desc":"Aux input port number that triggers macro 9 (content in $759). Set to -1 to disable. The pin must be interrupt-capable.","keywords":["action","aux input","macro","port","trigger"]},{"code":"$770","name":"Laser X offset","desc":"Laser offset from the spindle on the X axis, applied when switching between spindle and laser so files stay aligned. Pairs with gSender Spindle/Laser offset settings.","keywords":["alignment","laser","offset","pwm"],"tips":"Moved here in Main_grblHAL firmware - older SLB 5.0.x used $741."},{"code":"$771","name":"Laser Y offset","desc":"Laser offset from the spindle on the Y axis.","keywords":["alignment","laser","offset","pwm"],"tips":"Moved here in Main_grblHAL firmware - older SLB 5.0.x used $742."},{"code":"$772","name":"Laser offset options","desc":"Options controlling how the laser/spindle XY offset ($770/$771) is applied.","keywords":["laser","offset","options","pwm"]}],"system":[{"code":"$$","name":"View settings","desc":"Prints every numbered setting and its current value.","keywords":["settings","list","view","dump"]},{"code":"$#","name":"View G-code parameters","desc":"Shows WCS offsets (G54-G59.3), G28/G30 positions, G92 offset, tool length offset and last probe result (PRB).","keywords":["parameters","offsets","probe result","wcs","prb"]},{"code":"$G","name":"View parser state","desc":"Shows the active modal G-codes (motion mode, WCS, plane, units, distance mode...), plus current T, F and S.","keywords":["parser","state","modal","active modes"]},{"code":"$I","name":"Build info","desc":"Prints the firmware build/version string and enabled options.","keywords":["build","version","info","firmware"]},{"code":"$N","name":"View startup blocks","desc":"Shows the G-code lines run automatically at startup ($N0=, $N1= to set).","keywords":["startup","blocks","boot"]},{"code":"$X","name":"Kill alarm lock","desc":"Unlocks the machine from an alarm state without homing. Position may be unknown afterward — use with caution.","keywords":["unlock","alarm","kill","reset alarm"]},{"code":"$H","name":"Run homing cycle","desc":"Homes all configured axes per $22/$44-$47. $HX / $HY / $HZ home a single axis (grblHAL). Note: with the Rapid Change ATC or Manual Tool Changer plugin installed and \"perform TLS after home\" enabled, the plugin expands $H so that after homing, if a tool is loaded but has no length offset yet, an automatic $TLS probe cycle runs.","keywords":["home","homing","cycle","tls after home"]},{"code":"$J=","name":"Jog","desc":"Executes a jog move, e.g. $J=G91 X10 F1000. Jogs don't alter the G-code parser state and can be cancelled instantly (0x85).","keywords":["jog","jogging","move","manual"]},{"code":"$SLP","name":"Sleep","desc":"Puts the controller to sleep (steppers and spindle off). Wake with a soft reset. Requires $62=1.","keywords":["sleep","power down"]},{"code":"$TLR","name":"Set tool length reference","desc":"Tool change protocol: records the current tool offset as the job's reference after probing the first tool.","keywords":["tool length","reference","toolsetter","tool change"]},{"code":"$TPW","name":"Tool probe workpiece","desc":"Tool change protocol: probes the new tool to compute its dynamic offset. Available in tool change modes 1 and 2.","keywords":["tool probe","toolsetter","tool change"]},{"code":"$EA","name":"Enumerate alarms","desc":"Lists every alarm code with its description — decode alarm numbers here.","keywords":["alarms","codes","enumerate","list"]},{"code":"$EE","name":"Enumerate errors","desc":"Lists every error code with its description — decode error:NN messages here.","keywords":["errors","codes","enumerate","list"]},{"code":"$ES","name":"Enumerate settings","desc":"Lists every setting the build supports with type, range, unit and description — the authoritative settings reference for YOUR controller.","keywords":["settings","enumerate","describe","list"]},{"code":"$EG","name":"Enumerate setting groups","desc":"Lists the hierarchy of setting groups.","keywords":["groups","settings","enumerate"]},{"code":"$pins","name":"Enumerate pins","desc":"Lists processor pin assignments — which MCU pin does what.","keywords":["pins","mapping","enumerate"]},{"code":"$pinstate","name":"Pin states","desc":"Shows the live state of auxiliary pins — great for debugging wiring.","keywords":["pins","state","debug","aux"]},{"code":"$SPINDLES","name":"Enumerate spindles","desc":"Lists configured spindles and their numbers (for M104 P selection on multi-spindle setups).","keywords":["spindles","enumerate","list","dual spindle"]},{"code":"$F","name":"List files","desc":"Lists G-code files in the current directory on SD/LittleFS. $F+ lists all files; $F=<file> runs one; $FD=<file> deletes; $FM/$FU mount/unmount; $CWD= changes directory; $PWD prints it.","keywords":["files","sd card","list","run file","littlefs"]},{"code":"$RST","name":"Restore defaults","desc":"$RST=$ restores settings to defaults, $RST=# clears WCS/G28/G30 offsets, $RST=* resets everything. Irreversible — note your settings first.","keywords":["reset","restore","defaults","factory"]},{"code":"$REBOOT","name":"Reboot controller","desc":"Hard-resets the controller. The connection drops.","keywords":["reboot","restart","reset"]},{"code":"$TTLOAD","name":"Reload tool table","desc":"Reloads the tool table from storage.","keywords":["tool table","reload"]}],"letters":{"X":"X-axis coordinate/value","Y":"Y-axis coordinate/value","Z":"Z-axis coordinate/value","A":"A-axis (rotary) value","B":"B-axis value","C":"C-axis value","U":"U-axis value","V":"V-axis value","F":"Feed rate (modal — persists until changed)","S":"Spindle speed / laser power (used by M3/M4)","T":"Tool select (pre-selects for M6)","I":"Arc center offset from start, X direction","J":"Arc center offset from start, Y direction","K":"Arc center offset from start, Z direction","R":"Radius, or retract plane in canned cycles","P":"Parameter: dwell seconds, WCS/port/macro number (command-dependent)","Q":"Parameter: peck depth, value, tool number (command-dependent)","L":"Parameter: repeat count or data mode (command-dependent)","H":"Tool table index for length offset (G43)","D":"Parameter: max RPM cap (G96) or tool radius index","N":"Line number (ignored by execution)","E":"Analog port (plugin M-codes)","O":"Program label / subroutine number","W":"W-axis value, or white channel (M150)"},"initialTab":"reference","initialQuery":"","initialExplain":"","maxResults":8,"showSettingsTab":true};
/* Per-category color keys with dark- and light-theme variants.
The dialog renders in ncSender's main document, so we detect the
active theme from the computed text color (dark text = light theme)
and pick the palette with proper contrast. Chips, entry code chips,
and badges all share these colors. */
var CATEGORIES = [
{ id: 'all', label: 'All', dark: '#10b981', light: '#047857', accent: true },
{ id: 'motion', label: 'Motion', dark: '#4da3ff', light: '#1565c0' },
{ id: 'coords', label: 'Coordinates', dark: '#b48cff', light: '#6a3ab2' },
{ id: 'probing', label: 'Probing', dark: '#ff9f43', light: '#c65a00' },
{ id: 'spindle', label: 'Spindle/Laser', dark: '#ff6b81', light: '#c62839' },
{ id: 'coolant', label: 'Coolant', dark: '#3ec1d3', light: '#00838f' },
{ id: 'tool', label: 'Tooling', dark: '#ffd166', light: '#8d6e00' },
{ id: 'cycles', label: 'Canned Cycles', dark: '#f78fb3', light: '#ad3b66' },
{ id: 'modes', label: 'Modes', dark: '#7bed9f', light: '#2e7d32' },
{ id: 'program', label: 'Program Flow', dark: '#c8d6e5', light: '#455a64' },
{ id: 'io', label: 'I/O', dark: '#70a1ff', light: '#3949ab' },
{ id: 'plugin', label: 'Plugin codes', dark: '#e77f67', light: '#bf360c' },
{ id: 'setting', label: '$ Settings', dark: '#2dd4bf', light: '#0f766e' },
{ id: 'system', label: '$ Commands', dark: '#48dbfb', light: '#0277bd' }
];
var IS_LIGHT = (function () {
try {
var el = document.getElementById('gref-root');
var c = (window.getComputedStyle ? window.getComputedStyle(el).color : '') || '';
var m = c.match(/(\d+)\D+(\d+)\D+(\d+)/);
if (!m) return false;
// dark text means light theme
return (0.2126 * m[1] + 0.7152 * m[2] + 0.0722 * m[3]) < 128;
} catch (e) { return false; }
})();
var CAT_COLOR = {};
CATEGORIES.forEach(function (c) { CAT_COLOR[c.id] = IS_LIGHT ? c.light : c.dark; });
function catColor(id) { return CAT_COLOR[id] || (IS_LIGHT ? '#455a64' : '#9aa4b2'); }
/* Build one unified entry list with a type tag. */
var ALL = [];
DATA.gcodes.forEach(function (e) { e._type = 'gcode'; ALL.push(e); });
DATA.settings.forEach(function (e) {
ALL.push({ _type: 'setting', code: e.code, aliases: [], name: e.name,
category: 'setting', modal: null, desc: e.desc, syntax: e.code + '=<value>',
params: {}, example: e.code + '=1', tips: null, keywords: e.keywords });
});
DATA.system.forEach(function (e) {
ALL.push({ _type: 'system', code: e.code, aliases: [], name: e.name,
category: 'system', modal: null, desc: e.desc, syntax: e.code,
params: {}, example: e.code, tips: null, keywords: e.keywords });
});
/* code -> entry lookup map (canonical codes + aliases, uppercased). */
var CODEMAP = {};
ALL.forEach(function (e) {
CODEMAP[e.code.toUpperCase()] = e;
(e.aliases || []).forEach(function (a) { CODEMAP[a.toUpperCase()] = e; });
});
var state = { tab: DATA.initialTab || 'reference', query: DATA.initialQuery || '',
category: 'all', explainText: DATA.initialExplain || '', open: {},
gfile: { status: 'idle', name: '', lines: [] },
gsel: { anchor: -1, from: -1, to: -1 }, gfocus: -1,
fsearch: { q: '', matches: [], cur: -1 },
src: 'file', paste: { text: '', lines: [] }, rendered: 0, splitPct: 42 };
// terminal ??<line> payloads open as pasted code so line numbers,
// click-to-locate and find all work on them
if (DATA.initialExplain) {
state.src = 'paste';
state.paste.text = DATA.initialExplain;
state.paste.lines = DATA.initialExplain.split(/\r?\n/);
state.gsel = { anchor: 0, from: 0, to: state.paste.lines.length - 1 };
}
/* ---------------- controller cross-check ----------------
ncSender caches the controller's own $ES/$$ enumeration and serves
it at /api/firmware. We use it to flag database settings that do
not exist on THIS machine's firmware build, and to show the live
value of the ones that do. Fails soft: no data, no flags. */
var MACHINE = { state: 'loading', has: {}, values: {}, fw: '' };
function apiBase() {
try {
if (window.ncSender && typeof window.ncSender.getApiBaseUrl === 'function')
return window.ncSender.getApiBaseUrl(null);
} catch (e) {}
try {
if (window.parent && window.parent.ncSender && typeof window.parent.ncSender.getApiBaseUrl === 'function')
return window.parent.ncSender.getApiBaseUrl(null);
} catch (e) {}
return '';
}
(function loadMachineSettings() {
if (typeof fetch === 'undefined') { MACHINE.state = 'unavailable'; return; }
try {
fetch(apiBase() + '/api/firmware')
.then(function (r) { return r && r.ok ? r.json() : null; })
.then(function (data) {
var settings = data && (data.settings || data.Settings);
if (settings && Object.keys(settings).length > 0) {
Object.keys(settings).forEach(function (k) {
if (!/^\d+$/.test(k)) return;
MACHINE.has[k] = true;
var v = settings[k] || {};
var val = (v.value !== undefined && v.value !== null) ? v.value
: (v.Value !== undefined && v.Value !== null) ? v.Value : null;
if (val !== null) MACHINE.values[k] = String(val);
});
MACHINE.fw = String(data.firmwareVersion || data.FirmwareVersion || '');
MACHINE.state = 'ready';
} else {
MACHINE.state = 'unavailable';
}
if (state.tab === 'reference') renderReference();
})
.catch(function () {
MACHINE.state = 'unavailable';
if (state.tab === 'reference') renderReference();
});
} catch (e) { MACHINE.state = 'unavailable'; }
})();
/* ---------------- search ---------------- */
function normalizeCode(letter, num) {
// G01 -> G1, M06 -> M6, G38.2 stays G38.2
var n = parseFloat(num);
if (isNaN(n)) return letter.toUpperCase();
return letter.toUpperCase() + (n % 1 === 0 ? String(Math.round(n)) : String(n));
}
function search(query, category) {
var q = (query || '').trim().toLowerCase();
var results = [];
ALL.forEach(function (e) {
if (category !== 'all' && e.category !== category) return;
if (!q) { results.push({ e: e, score: 1 }); return; }
var score = 0;
var codeU = e.code.toLowerCase();
var aliasHit = (e.aliases || []).some(function (a) { return a.toLowerCase() === q; });
// exact / prefix code match (also try normalized: "g01" -> "g1")
var m = q.match(/^([a-z])0*(\d+(?:\.\d+)?)$/);
var qNorm = m ? (m[1] + parseFloat(m[2])) : q;
if (codeU === q || codeU === qNorm || aliasHit) score = 100;
else if (codeU.indexOf(qNorm) === 0 || codeU.indexOf(q) === 0) score = 60;
else if ((e.keywords || []).some(function (k) { return k === q; })) score = 50;
else if ((e.keywords || []).some(function (k) { return k.indexOf(q) !== -1; })) score = 30;
else if (e.name.toLowerCase().indexOf(q) !== -1) score = 25;
else if ((e.desc || '').toLowerCase().indexOf(q) !== -1) score = 10;
if (score > 0) results.push({ e: e, score: score });
});
results.sort(function (a, b) { return b.score - a.score; });
return results.map(function (r) { return r.e; });
}
/* ---------------- explain ---------------- */
function explainLine(line) {
var words = [];
var work = line;
// pull out comments first - they are annotations, not commands
work = work.replace(/\(([^)]*)\)/g, function (mm, inner) {
words.push({ tok: '(' + inner + ')', desc: 'Comment - ignored by the controller', kind: 'comment' });
return ' ';
});
var semi = work.indexOf(';');
if (semi !== -1) {
words.push({ tok: work.slice(semi), desc: 'Comment - everything after ; is ignored', kind: 'comment' });
work = work.slice(0, semi);
}
// whole-line $ system commands ($H, $J=..., $110=500, $$, $SLOT3, $ADB_RETRACT ...)
var sysMatch = work.trim().match(/^(\$\d+=?|\$[A-Za-z][A-Za-z0-9_]*=?|\$[#$+]*=?)(.*)$/);
if (sysMatch && work.trim().charAt(0) === '$') {
var head = sysMatch[1].replace(/=$/, '');
var rest = (sysMatch[2] || '').trim();
var numSetting = head.match(/^\$(\d+)$/);
var entry = CODEMAP[head.toUpperCase()] || CODEMAP[head.toUpperCase() + '='] || null;
if (numSetting && !entry) entry = CODEMAP['$' + numSetting[1]];
if (!entry && /^\$H[XYZABC]$/i.test(head)) entry = CODEMAP['$H'];
if (!entry && /^\$SLOT0*\d+$/i.test(head)) entry = CODEMAP['$SLOT1']; // Rapid Change ATC slots
if (entry) {
words.push({ tok: head, desc: entry.name + ' - ' + entry.desc, kind: 'command' });
} else {
words.push({ tok: head, desc: 'grblHAL system command/setting (not in local DB - run $ES on the controller for details)', kind: 'unknown' });
}
if (head.toUpperCase() === '$J') {
// explain the jog body as G-code
var sub = explainLine(rest);
sub.forEach(function (w) { words.push(w); });
return words;
}
if (rest) {
words.push({ tok: rest, desc: numSetting ? 'New value for this setting' : 'Argument', kind: 'value' });
}
return words;
}
// tokenize letter+number words, tracking what each match consumes so
// anything left over can be flagged as not-G-code
var consumed = [];
function markSpan(from, len) { consumed.push([from, from + len]); }
// grblHAL macro / flow-control syntax is valid even though it isn't
// letter+number words: o-words, #<vars>, [expressions], keywords
var FLOW_RE = /(^[oO]\d+)|(#<[^>]*>)|(#\d+)|(\[[^\]]*\])|\b(IF|THEN|ELSE|ELSEIF|ENDIF|WHILE|ENDWHILE|DO|REPEAT|ENDREPEAT|SUB|ENDSUB|CALL|RETURN|EQ|NE|GT|GE|LT|LE|AND|OR|XOR|MOD)\b/g;
var fm;
while ((fm = FLOW_RE.exec(work)) !== null) {
markSpan(fm.index, fm[0].length);
words.push({ tok: fm[0], desc: 'grblHAL macro / expression syntax', kind: 'value' });
}
var re = /([A-Za-z])\s*([+-]?(?:\d+\.?\d*|\.\d+))/g;
var tokens = [];
var mtk;
while ((mtk = re.exec(work)) !== null) {
// skip letter+number pairs inside spans already claimed by flow syntax
var inFlow = false;
for (var fi = 0; fi < consumed.length; fi++) {
if (mtk.index >= consumed[fi][0] && mtk.index < consumed[fi][1]) { inFlow = true; break; }
}
if (inFlow) continue;
markSpan(mtk.index, mtk[0].length);
tokens.push({ letter: mtk[1].toUpperCase(), value: mtk[2] });
}
// first pass: identify command words (G/M with a DB entry),
// including two-word forms like "G10 L2" / "G10 L20"
var cmdEntries = [];
tokens.forEach(function (t) {
t.code = normalizeCode(t.letter, t.value);
if (t.letter === 'G' || t.letter === 'M') {
var entry = CODEMAP[t.code];
// special-case G10: combine with its L word for the right doc
if (t.code === 'G10') {
var lTok = null;
for (var li = 0; li < tokens.length; li++) {
if (tokens[li].letter === 'L') { lTok = tokens[li]; break; }
}
if (lTok) {
var combo = CODEMAP['G10 L' + parseFloat(lTok.value)];
if (combo) { entry = combo; lTok.consumedByG10 = true; }
}
}
if (entry) { t.entry = entry; cmdEntries.push(entry); }
}
if (t.letter === 'T') { t.entry = null; t.isT = true; }
});
// second pass: build word annotations
tokens.forEach(function (t) {
if (t.entry) {
words.push({ tok: t.letter + t.value,
desc: t.entry.name + (t.entry.modal ? ' [' + t.entry.modal + ']' : ''),
sub: t.entry.desc, kind: 'command' });
return;
}
if (t.letter === 'N') {
words.push({ tok: t.letter + t.value, desc: 'Line number ' + t.value + ' - ignored by execution', kind: 'value' });
return;
}
if (t.isT) {
words.push({ tok: 'T' + t.value, desc: 'Tool select - pre-selects tool ' + parseFloat(t.value) + ' for M6', kind: 'value' });
return;
}
if (t.consumedByG10) {
words.push({ tok: 'L' + t.value, desc: 'Data mode for G10 (' + parseFloat(t.value) + ')', kind: 'value' });
return;
}
// parameter: find the first command on the line documenting this letter
var meaning = null;
for (var ci = 0; ci < cmdEntries.length; ci++) {
if (cmdEntries[ci].params && cmdEntries[ci].params[t.letter]) {
meaning = cmdEntries[ci].params[t.letter] + ' (for ' + cmdEntries[ci].code + ')';
break;
}
}
if (!meaning) meaning = DATA.letters[t.letter] || 'Unrecognized word';
words.push({ tok: t.letter + t.value, desc: meaning + ' = ' + t.value,
kind: meaning === 'Unrecognized word' ? 'unknown' : 'value' });
});
// anything not consumed by comments, flow syntax, or recognized
// letter+number words is residue - flag it as not valid G-code
var mask = new Array(work.length);
consumed.forEach(function (span) {
for (var mi = span[0]; mi < span[1] && mi < work.length; mi++) mask[mi] = true;
});
var frag = '';
var frags = [];
for (var wi = 0; wi <= work.length; wi++) {
var chr = wi < work.length ? work.charAt(wi) : ' ';
if (wi < work.length && !mask[wi] && !/\s/.test(chr)) {
frag += chr;
} else if (frag) {
frags.push(frag); frag = '';
}
}
frags.slice(0, 6).forEach(function (f) {
words.push({ tok: f.length > 40 ? f.slice(0, 40) + '\u2026' : f,
desc: 'Not recognized as G-code', kind: 'invalid' });
});
if (words.length === 0) {
words.push({ tok: line.trim() || '(empty)', desc: 'Nothing recognizable on this line', kind: 'unknown' });
}
return words;
}
/* ---------------- rendering ---------------- */
function esc(s) {
return String(s == null ? '' : s)
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}
function badgeFor(e) {
var cat = null;
for (var i = 0; i < CATEGORIES.length; i++) {
if (CATEGORIES[i].id === e.category) { cat = CATEGORIES[i]; break; }
}
return cat ? cat.label : e.category;
}
function renderCard(e) {
var cc = catColor(e.category);
var absentColor = IS_LIGHT ? '#c62839' : '#ff6b81';
var open = state.open[e.code] ? ' open' : '';
// controller cross-check applies to numeric $ settings only
var mnum = e.code.match(/^\$(\d+)$/);
var onMachine = null, liveVal;
if (mnum && MACHINE.state === 'ready') {
onMachine = !!MACHINE.has[mnum[1]];
liveVal = MACHINE.values[mnum[1]];
}
var html = '<div class="gref-card' + open + '" data-code="' + esc(e.code) + '">';
html += '<div class="gref-card-head" onclick="grefToggle(this)"' + (onMachine === false ? ' style="opacity:0.55"' : '') + '>';
html += '<span class="gref-caret">▶</span>';
// code text matches its category filter color (association at a glance)
html += '<span class="gref-codechip" style="color:' + cc + ';border:1px solid ' + cc + '55;background:var(--color-surface,#1a2027)">' + esc(e.code) + '</span>';
html += '<span class="gref-name">' + esc(e.name) + '</span>';
if (onMachine === true && liveVal !== undefined) {
html += '<span class="gref-codechip" title="Current value on this controller" style="color:var(--color-accent,#10b981);border:1px solid var(--color-border,#333a45);background:var(--color-surface,#1a2027);font-weight:600">= ' + esc(liveVal) + '</span>';
}
if (onMachine === false) {
html += '<span class="gref-badge" style="color:' + absentColor + ';border:1px solid ' + absentColor + '55;opacity:0.9">not on this controller</span>';
}
html += '<span class="gref-badge" style="color:' + cc + ';border:1px solid ' + cc + '55;opacity:0.85">' + esc(badgeFor(e)) + '</span>';
html += '</div><div class="gref-detail">';
if (onMachine === true && liveVal !== undefined) {
html += '<div class="gref-label">Current value on this controller</div><div class="gref-pre">' + esc(e.code) + '=' + esc(liveVal) + '</div>';
}
if (onMachine === false) {
html += '<div class="gref-tip" style="border-left-color:' + absentColor + '">Your controller’s $ES enumeration does not include this setting — this firmware build does not have the feature compiled in, or its plugin is disabled.</div>';
}
html += '<p>' + esc(e.desc) + '</p>';
if (e.modal) html += '<p class="sub" style="color:var(--color-text-secondary,#9aa4b2);font-size:0.78rem">Modal group: ' + esc(e.modal) + '</p>';
if (e.syntax) { html += '<div class="gref-label">Syntax</div><div class="gref-pre">' + esc(e.syntax) + '</div>'; }
var pkeys = Object.keys(e.params || {});
if (pkeys.length) {
html += '<div class="gref-label">Parameters</div><table class="gref-params">';
pkeys.forEach(function (k) { html += '<tr><td>' + esc(k) + '</td><td>' + esc(e.params[k]) + '</td></tr>'; });
html += '</table>';
}
if (e.example) { html += '<div class="gref-label">Example</div><div class="gref-pre">' + esc(e.example) + '</div>'; }
if (e.tips) { html += '<div class="gref-tip">' + esc(e.tips) + '</div>'; }
html += '</div></div>';
return html;
}
function renderReference() {
var body = document.getElementById('gref-body');
var results = search(state.query, state.category);
var shown = results;
var html = '';
if (results.length === 0) {
html = '<div class="gref-empty">No matches for “' + esc(state.query) + '”.<br>' +
'Try a code (G38.2, $110, M6) or a keyword (dwell, probe, laser, tool change).</div>';
} else {
var status = '';
if (MACHINE.state === 'ready') {
status = ' · checked against your controller' + (MACHINE.fw ? ' (' + esc(MACHINE.fw) + ')' : '');
} else if (MACHINE.state === 'unavailable') {
status = ' · controller settings unavailable — cannot flag which exist on your machine';
}
html += '<div class="gref-count">' + shown.length +
(shown.length < results.length ? ' of ' + results.length : '') +
' entr' + (shown.length === 1 ? 'y' : 'ies') + status + '</div>';
// auto-expand the top hit of a terminal lookup
if (state.query && shown.length > 0) state.open[shown[0].code] = true;
shown.forEach(function (e) { html += renderCard(e); });
}
body.innerHTML = html;
}
var CHUNK_ROWS = 4000; // rows rendered per batch; scrolling/jumping loads more
var SEL_BG = 'rgba(16,185,129,0.18)';
/* ---- G-code syntax coloring ----
Replicates ncSender's G-Code Preview highlighter (highlightGcode in
ConsolePanel.vue): same rules, same gc-* palette. The preview's
sequential replacements effectively let chained words match (X0.5Y0.2
colors BOTH words, since wrapping X0.5 creates a boundary before Y),
so a word rule here only requires that the previous character is not
a letter. Unmatched bare numbers stay the default text color, exactly
like the preview. */
var GCODE_COLORS = IS_LIGHT ? {
comment: { c: '008000', i: 1 }, number: { c: '098658' },
rapid: { c: 'E67E22', b: 1 }, cutting: { c: '2E86C1', b: 1 },
g: { c: 'AF00DB' }, m: { c: '795E26' }, tool: { c: '267F99' },
spindle: { c: 'A31515' }, feed: { c: '098658' },
x: { c: 'C72828' }, y: { c: '267F99' }, z: { c: '2E86C1' },
other: { c: '0070C1' }, nline: { c: '999999' }
} : {
comment: { c: '6A9955', i: 1 }, number: { c: 'B5CEA8' },
rapid: { c: 'FF8C00', b: 1 }, cutting: { c: '569CD6', b: 1 },
g: { c: 'C586C0' }, m: { c: 'DCDCAA' }, tool: { c: '4EC9B0' },
spindle: { c: 'CE9178' }, feed: { c: 'B5CEA8' },
x: { c: 'F14C4C' }, y: { c: '4EC9B0' }, z: { c: '569CD6' },
other: { c: '9CDCFE' }, nline: { c: '858585' }
};
function gtok(kind, text) {
var s = GCODE_COLORS[kind];
return '<span style="color:#' + s.c + (s.b ? ';font-weight:600' : '') +
(s.i ? ';font-style:italic' : '') + '">' + esc(text) + '</span>';
}
var GCODE_WORD_RULES = [
// [first-char matcher, sticky pattern, token] in Monarch rule order
[/[Gg]/, /^[Gg]0*(?=[\sA-Za-z]|$)/, 'rapid'],
[/[Gg]/, /^[Gg][1-3](?![A-Za-z0-9_])/, 'cutting'],
[/[Gg]/, /^[Gg]\d+\.?\d*/, 'g'],
[/[Mm]/, /^[Mm]\d+/, 'm'],
[/[Tt]/, /^[Tt]\d+/, 'tool'],
[/[Ss]/, /^[Ss]\d+\.?\d*/, 'spindle'],
[/[Ff]/, /^[Ff]\d+\.?\d*/, 'feed'],
[/[Xx]/, /^[Xx]-?\d+\.?\d*/, 'x'],
[/[Yy]/, /^[Yy]-?\d+\.?\d*/, 'y'],
[/[Zz]/, /^[Zz]-?\d+\.?\d*/, 'z'],
[/[AaBbCcIiJjKk]/, /^[AaBbCcIiJjKk]-?\d+\.?\d*/, 'other'],
[/[Nn]/, /^[Nn]\d+/, 'nline']
];
function hlGcode(line) {
var out = '', i = 0, n = line.length;
while (i < n) {
var ch = line.charAt(i);
var rest = line.slice(i);
var m;
if (ch === ';') { out += gtok('comment', rest); break; }
if (ch === '(') {
m = rest.match(/^\(.*?\)/);
if (m) { out += gtok('comment', m[0]); i += m[0].length; continue; }
}
// preview semantics: a word matches unless glued to a preceding letter
var prevLetter = i > 0 && /[A-Za-z]/.test(line.charAt(i - 1));
if (!prevLetter && /[A-Za-z]/.test(ch)) {
var matched = false;
for (var r = 0; r < GCODE_WORD_RULES.length; r++) {
if (!GCODE_WORD_RULES[r][0].test(ch)) continue;
m = rest.match(GCODE_WORD_RULES[r][1]);
if (m) { out += gtok(GCODE_WORD_RULES[r][2], m[0]); i += m[0].length; matched = true; break; }
}
if (matched) continue;
}
out += esc(ch); i++;
}
return out;
}
// classify a single already-split token (for the explanation tables)
function gcodeTokenKind(tok) {
if (/^[;(]/.test(tok)) return 'comment';
if (!/^[A-Za-z$]/.test(tok)) return null;
for (var r = 0; r < GCODE_WORD_RULES.length; r++) {
var m = tok.match(GCODE_WORD_RULES[r][1]);
if (m && m[0].length === tok.length) return GCODE_WORD_RULES[r][2];
}
return null;
}
function loadGcodeFile() {
state.gfile.status = 'loading';
if (typeof fetch === 'undefined') {
state.gfile = { status: 'none', name: '', lines: [] };
return;
}
try {
// the loaded program itself
fetch(apiBase() + '/api/gcode-files/current/download')
.then(function (r) { return r && r.ok ? r.text() : null; })
.then(function (text) {
if (text === null || text === undefined) {
state.gfile = { status: 'none', name: '', lines: [] };
} else {
state.gfile = { status: 'ready', name: '', lines: text.split(/\r?\n/) };
}
if (state.tab === 'explain') renderExplain();
})
.catch(function () {
state.gfile = { status: 'none', name: '', lines: [] };
if (state.tab === 'explain') renderExplain();
});
// the loaded file's name (best effort - shown in the header)
fetch(apiBase() + '/api/gcode-job/status')
.then(function (r) { return r && r.ok ? r.json() : null; })
.then(function (s) {
if (!s) return;
var name = s.currentFile || s.CurrentFile || s.fileName || s.FileName ||
s.currentGcodeFile || s.CurrentGcodeFile || '';
if (name && state.gfile.status === 'ready') {
state.gfile.name = String(name).split(/[\\/]/).pop();
var head = document.getElementById('gref-filename');
if (head) head.innerHTML = esc(state.gfile.name);
}
})
.catch(function () {});
} catch (e) {
state.gfile = { status: 'none', name: '', lines: [] };
}
}
function activeSrc() {
if (state.src === 'paste') {
return { ready: state.paste.lines.length > 0, lines: state.paste.lines };
}
return { ready: state.gfile.status === 'ready', lines: state.gfile.lines };
}
function exStartLine() {
return (activeSrc().ready && state.gsel.from >= 0) ? state.gsel.from : null;
}
function updateJumpInput() {
var inp = document.getElementById('gref-jump');
if (!inp) return;
var s = state.gsel;
inp.value = s.from < 0 ? '' :
(s.from === s.to ? String(s.from + 1) : (s.from + 1) + '-' + (s.to + 1));
}
function updateExout() {
var el = document.getElementById('gref-exout');
if (el) el.innerHTML = renderExplainOutput(state.explainText, exStartLine());
updateJumpInput();
}
var SEL_FOCUS = 'rgba(16,185,129,0.38)';
function applySelectionHighlights() {
try {
var s = state.gsel;
var list = document.getElementById('gref-filelist');
var kids = list && list.children;
if (!kids) return;
for (var k = 0; k < kids.length; k++) {
var attr = kids[k].getAttribute && kids[k].getAttribute('data-i');
if (attr === null || attr === undefined) continue;
var idx = parseInt(attr, 10);
kids[k].style.background = idx === state.gfocus ? SEL_FOCUS
: (idx >= s.from && idx <= s.to) ? SEL_BG : 'transparent';
}
} catch (e) {}
}
window.grefOpenInNavigator = function (idx) {
state.tab = 'navigator';
render();
// give first-time activation a beat, then drive the navigator's own
// line input; its input/change listeners select the line on the map
setTimeout(function () {
try {
var inp = document.getElementById('gn-line-input');
if (!inp) return;
inp.value = String(idx + 1);
if (typeof Event === 'function' && inp.dispatchEvent) {
inp.dispatchEvent(new Event('input'));
inp.dispatchEvent(new Event('change'));
}
} catch (e) {}
}, 80);
};
window.grefExplainLineNum = function (v) {
var n = parseInt(v, 10);
if (isNaN(n) || n < 1) return;
state.tab = 'explain';
state.src = 'file';
state.pendingJump = n;
render();
// if the file is already loaded, jump immediately; otherwise
// renderExplain consumes pendingJump once the load lands
if (state.gfile.status === 'ready') {
state.pendingJump = null;
window.grefJump(String(n));
}
};
window.grefExFocus = function (idx, el) {
state.gfocus = idx;
applySelectionHighlights();
scrollToLine(idx);
// second-level highlight on the clicked explanation block too
try {
var sib = el && el.parentElement && el.parentElement.children;
if (sib) for (var k = 0; k < sib.length; k++) sib[k].style.boxShadow = '';
if (el) el.style.boxShadow = 'inset 0 0 0 1px var(--color-accent, #10b981)';
} catch (e) {}
};
function fileRowStyle(selected) {
return 'display:flex;gap:10px;padding:1px 8px;cursor:pointer;' +
'background:' + (selected ? SEL_BG : 'transparent') + ';';
}
function buildRows(lines, from, to, numW) {
var html = '';
for (var i = from; i < to; i++) {
var selected = i >= state.gsel.from && i <= state.gsel.to;
html += '<div data-i="' + i + '" onclick="grefLineClick(event,' + i + ')" style="' + fileRowStyle(selected) + '">' +
'<span style="color:var(--color-text-secondary,#9aa4b2);min-width:' + numW + 'ch;text-align:right;user-select:none">' + (i + 1) + '</span>' +
'<span style="flex:1;min-width:0;white-space:pre;overflow:hidden;text-overflow:ellipsis">' + (lines[i] ? hlGcode(lines[i]) : ' ') + '</span></div>';
}
return html;
}
function updateRenderNote() {
var el = document.getElementById('gref-rendernote');
if (!el) return;
var a = activeSrc();
if (a.ready && state.rendered < a.lines.length) {
el.style.display = '';
el.innerHTML = 'Rendered ' + state.rendered + ' of ' + a.lines.length +
' lines — scroll on, or jump/search/"end" to load the rest instantly';
} else {
el.style.display = 'none';
}
}
function appendChunk() {
var a = activeSrc();
if (!a.ready) return;
var list = document.getElementById('gref-filelist');
if (!list) return;
var n = a.lines.length;
if (state.rendered >= n) return;
var to = Math.min(n, state.rendered + CHUNK_ROWS);
var html = buildRows(a.lines, state.rendered, to, String(n).length);
if (typeof list.insertAdjacentHTML === 'function') list.insertAdjacentHTML('beforeend', html);
else list.innerHTML += html;
state.rendered = to;
updateRenderNote();
}
function ensureRendered(idx) {
var a = activeSrc();
if (!a.ready) return;
var guard = 0;
while (state.rendered <= idx && state.rendered < a.lines.length && guard++ < 2000) appendChunk();
}
window.grefListScroll = function (el) {
try {
if (el.scrollTop + el.clientHeight >= el.scrollHeight - 600) appendChunk();
} catch (e) {}
};
function renderExplain() {
var body = document.getElementById('gref-body');
var a = activeSrc();
state.rendered = 0;
var html = '<div class="gref-exwrap" id="gref-exwrap" style="display:flex;flex-direction:row;flex:1;min-height:0;min-width:0;max-width:100%">';
/* ---- left: source pane (loaded file OR pasted code) ---- */
html += '<div id="gref-leftpane" style="flex:0 0 ' + state.splitPct + '%;display:flex;flex-direction:column;min-width:0;min-height:0;' +
'border:1px solid var(--color-border,#333a45);border-radius:var(--radius-small,6px);overflow:hidden">';
// source toggle
function seg(src, label, active) {
return '<button onclick="grefSetSrc("' + src + '")" style="flex:1;padding:6px 0;font-size:0.75rem;' +
'cursor:pointer;border:none;border-radius:0;text-align:center;' +
(active ? 'background:var(--color-accent,#10b981);color:#fff;font-weight:600;'
: 'background:transparent;color:var(--color-text-secondary,#9aa4b2);') + '">' + label + '</button>';
}
html += '<div style="display:flex;border-bottom:1px solid var(--color-border,#333a45)">' +
seg('file', 'Loaded file', state.src === 'file') +
seg('paste', 'Paste code', state.src === 'paste') + '</div>';
var isPaste = state.src === 'paste';
var g = state.gfile;
if (!isPaste && (g.status === 'loading' || g.status === 'idle')) {
html += '<div class="gref-empty" style="padding:20px">Loading the current G-code file…</div>';
} else if (!isPaste && g.status === 'none') {
html += '<div class="gref-empty" style="padding:20px">No G-code file is loaded in ncSender ' +
'(<a href="#" onclick="grefReloadFile();return false" style="color:var(--color-accent,#10b981);text-decoration:none">check again</a>).' +
'<br><br>Switch to <b>Paste code</b> above to explain arbitrary G-code.</div>';
} else {
var n = a.lines.length;
var jv = state.gsel.from < 0 ? '' :
(state.gsel.from === state.gsel.to ? String(state.gsel.from + 1)
: (state.gsel.from + 1) + '-' + (state.gsel.to + 1));
// header: title | jump | of N lines | end | reload/clear
html += '<div style="padding:6px 10px;font-size:0.75rem;color:var(--color-text-secondary,#9aa4b2);' +
'border-bottom:1px solid var(--color-border,#333a45);display:flex;gap:8px;align-items:center">' +
'<span id="gref-filename" style="color:var(--color-text-primary,#e8eaed);font-weight:600">' +
(isPaste ? 'Pasted code' : (g.name ? esc(g.name) : 'Loaded file')) + '</span>' +
'<input id="gref-jump" value="' + esc(jv) + '" placeholder="line #" ' +
'title="Type a line number (or a range like 120-135) and press Enter to jump" ' +
'onkeydown="if(event.key==="Enter"){grefJump(this.value);}" onchange="grefJump(this.value)" ' +
'style="width:84px;padding:2px 6px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:0.74rem;' +
'background:var(--color-surface,#1a2027);color:var(--color-text-primary,#e8eaed);' +
'border:1px solid var(--color-border,#333a45);border-radius:4px;text-align:center">' +
'<span>of <span id="gref-linecount">' + n + '</span> lines</span>' +
'<a href="#" onclick="grefJumpEnd();return false" title="Jump to the last line" ' +
'style="color:var(--color-accent,#10b981);text-decoration:none">end ↓</a>' +
'<span style="flex:1"></span>' +
(isPaste
? '<a href="#" onclick="grefPasteClear();return false" style="color:var(--color-accent,#10b981);text-decoration:none">clear</a>'
: '<a href="#" onclick="grefReloadFile();return false" style="color:var(--color-accent,#10b981);text-decoration:none">reload</a>') +
'</div>';
// paste editor
if (isPaste) {
html += '<textarea id="gref-paste" spellcheck="false" oninput="grefPasteInput(this.value)" ' +
'placeholder="Paste one or more lines of G-code, e.g. G90 G21 G17 G1 X10 Y5 F500 M4 S800" ' +
'style="flex:0 0 auto;height:92px;margin:8px 8px 0;padding:6px 8px;resize:vertical;' +
'font-family:ui-monospace,Menlo,Consolas,monospace;font-size:0.76rem;' +
'background:var(--color-surface,#1a2027);color:var(--color-text-primary,#e8eaed);' +
'border:1px solid var(--color-border,#333a45);border-radius:4px">' + esc(state.paste.text) + '</textarea>';
}
// search row
var fbtn = 'background:transparent;border:1px solid var(--color-border,#333a45);' +
'color:var(--color-text-secondary,#9aa4b2);border-radius:4px;padding:2px 8px;cursor:pointer;font-size:0.72rem;';
html += '<div style="display:flex;gap:6px;align-items:center;padding:6px 8px;' +
'border-bottom:1px solid var(--color-border,#333a45)">' +
'<input id="gref-fsearch" placeholder="Find…" value="' + esc(state.fsearch.q) + '" ' +
'oninput="grefFileSearch(this.value)" ' +
'onkeydown="if(event.key==="Enter"){grefFileFind(event.shiftKey?-1:1);}" ' +
'style="flex:1;min-width:0;padding:3px 8px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:0.76rem;' +
'background:var(--color-surface,#1a2027);color:var(--color-text-primary,#e8eaed);' +
'border:1px solid var(--color-border,#333a45);border-radius:4px">' +
'<span id="gref-fsearch-count" style="min-width:70px;text-align:right;font-size:0.7rem;' +
'color:var(--color-text-secondary,#9aa4b2)"></span>' +
'<button title="Previous match (Shift+Enter)" onclick="grefFileFind(-1)" style="' + fbtn + '">▲</button>' +
'<button title="Next match (Enter)" onclick="grefFileFind(1)" style="' + fbtn + '">▼</button>' +
'<button title="Clear search" onclick="grefFileSearchClear()" style="' + fbtn + '">✕</button>' +
'</div>';
html += '<div style="padding:5px 10px;font-size:0.72rem;color:var(--color-text-secondary,#9aa4b2);' +
'border-bottom:1px solid var(--color-border,#333a45)">Click a line to explain it · Shift+click to explain a range</div>';
// the list itself: first chunk now, more on scroll / jump / search
html += '<div id="gref-filelist" onscroll="grefListScroll(this)" ' +
'style="flex:1;overflow-y:auto;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:0.78rem;line-height:1.45">';
if (n === 0) {
html += '<div class="gref-empty" style="padding:16px">Paste G-code above to browse and explain it.</div>';
} else {
var first = Math.min(n, CHUNK_ROWS);
html += buildRows(a.lines, 0, first, String(n).length);
}
html += '</div>';
html += '<div id="gref-rendernote" style="display:none;padding:4px 10px;font-size:0.7rem;' +
'color:var(--color-text-secondary,#9aa4b2);border-top:1px solid var(--color-border,#333a45)"></div>';
if (n > 0) state.rendered = Math.min(n, CHUNK_ROWS);
}
html += '</div>';
/* ---- draggable divider ---- */
html += '<div onmousedown="grefSplitStart(event)" title="Drag to resize the panes" ' +
'style="flex:0 0 6px;cursor:col-resize;align-self:stretch;margin:0 3px;border-radius:3px;' +
'background:var(--color-border,#333a45)"></div>';
/* ---- right: the word-by-word breakdown ---- */
html += '<div style="flex:1;display:flex;flex-direction:column;min-width:0;min-height:0;' +
'border:1px solid var(--color-border,#333a45);border-radius:var(--radius-small,6px);overflow:hidden">';
html += '<div style="padding:6px 10px;font-size:0.75rem;' +
'border-bottom:1px solid var(--color-border,#333a45);display:flex;align-items:center;min-height:29px">' +
'<span style="color:var(--color-text-primary,#e8eaed);font-weight:600">G-Code Definitions</span></div>';
html += '<div id="gref-exout" style="flex:1;overflow-y:auto;min-width:0;padding:8px">';
html += state.explainText.trim()
? renderExplainOutput(state.explainText, exStartLine())