Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 63 additions & 34 deletions docs/src/code/code-notes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,12 @@ There are approximately 44 commands - this list is still under
construction.

[NOTE]
The cmd_code_t enumeration, in motion.h, contains 73 commands, but the switch
statement in command.c contemplates only 70 commands (as of 6/5/2020).
ENABLE_WATCHDOG / DISABLE_WATCHDOG commands are in motion-logger.c. Maybe they are obsolete.
The SET_TELEOP_VECTOR command only appears in motion-logger.c, with no effect other than its own log.
The cmd_code_t enumeration, in motion.h, contains 76 commands, but the switch

@grandixximo grandixximo Aug 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

76/73 and "as of 8/2026" will go stale exactly like 73/70 and 6/5/2020 did; naming the three unhandled commands without the arithmetic stays true indefinitely. Nothing in the tree sends them, see #4359.

statement in command.c handles only 73 distinct commands (as of 8/2026).
The three without a handler are unchanged since this note was first written
in 2020: ENABLE_WATCHDOG / DISABLE_WATCHDOG exist only in motion-logger.c
and are probably obsolete, and SET_TELEOP_VECTOR likewise only appears in
motion-logger.c, with no effect other than its own log.

=== ABORT

Expand Down Expand Up @@ -370,8 +372,10 @@ The ENABLE command enables the motion controller.

==== Requirements

None. The command can be issued at any time, and will always be
accepted.
The command is rejected with an error message ("can't enable motion,
enable input is false") if the motion.enable HAL pin is low. The

@grandixximo grandixximo Aug 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

motion.enable is created with default value 1 (motion.c:528), so unconnected reads TRUE and this is never hit on a normal machine; "the hardware enable chain must be satisfied" overstates it.

hardware enable chain must be satisfied before the controller can be
enabled.

==== Results

Expand Down Expand Up @@ -500,10 +504,24 @@ future.

=== PAUSE

The PAUSE command stops the trajectory planner. It has no effect in
free or teleop mode. At this point I don't know if it pauses all motion
immediately, or if it completes the current move and then pauses before
pulling another move from the queue.
The PAUSE command pauses the trajectory planner. It has no effect in
free or teleop mode.

The machine neither stops instantly nor completes the current move: the

@grandixximo grandixximo Aug 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is planner behaviour rather than PAUSE-command behaviour; two sentences plus the synchronized-motion exception would cover what a Code Notes reader needs.

planner treats pause as a request to bring the feed to zero, so the
machine decelerates to a stop within the current segment, at that
segment's acceleration limit, and halts wherever the deceleration ramp
ends. The run-down is jerk-limited only on machines configured for the
S-curve planner ([TRAJ]PLANNER_TYPE = 1 with a non-zero MAX_JERK); both

@grandixximo grandixximo Aug 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicates ini-config.adoc:947, and the threshold is MAX_JERK < 1.0 (inihal.cc:302 and :320), not non-zero.

default to off, so a stock machine decelerates on a trapezoidal profile.

Pause is ignored while the active segment is position-synchronized with
the spindle (spindle-synchronized motion such as G33 threading and
rigid tapping): for those segments the planner forces full feed and
bypasses both pause and feed override, because tool position is slaved
to spindle angle and pausing mid-thread would destroy the work.
The pause takes effect when the synchronized segment ends.
Velocity-synchronized segments (G96 style) can be paused normally.

@grandixximo grandixximo Aug 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is G95, not G96: TC_SYNC_VELOCITY comes from velocity_mode = 1 at emccanon.cc:521 and :530.


==== Requirements

Expand All @@ -512,7 +530,10 @@ accepted.

==== Results

The trajectory planner pauses.
The planner's pausing flag is set. Motion ramps down to zero velocity
within the current segment (except during position-synchronized
segments, see above) and the planner stops pulling new segments from
the queue until RESUME or STEP.

=== RESUME

Expand All @@ -531,15 +552,15 @@ The trajectory planner resumes.
=== STEP

The STEP command restarts the trajectory planner if it is paused, and
tells the planner to stop again when it reaches a specific point. It
has no effect in free or teleop mode. At this point I don't know
exactly how this works. I'll add more documentation here when I dig
deeper into the trajectory planner.
tells the planner to pause again when the executing motion id changes
(i.e. after the current line of the program completes). It has no
effect in free or teleop mode.

==== Requirements

None. The command can be issued at any time, and will always be
accepted.
The planner must already be paused. If motion is executing, the
command is rejected with an error message ("can't STEP while already
executing").

==== Results

Expand Down Expand Up @@ -577,10 +598,12 @@ accepted. (I think it should only work in free mode.)

==== Results

Limits on all joints are over-ridden until the end of the next JOG
command. (This is currently broken... once an OVERRIDE_LIMITS command
is received, limits are ignored until another OVERRIDE_LIMITS command
re-enables them.)
Limits that are currently tripped are over-ridden until the end of the
next jog command, at which point they are automatically re-enabled.
Only the tripped limits are over-ridden: the command handler builds a
mask from each joint's negative/positive hard-limit flags, so joints
that are not on a limit keep their protection. Issuing the command
with a negative joint number cancels an override explicitly.

=== HOME

Expand Down Expand Up @@ -761,10 +784,14 @@ iocontrol. These are relatively low speed events, high speed coordinated I/O is

emctaskmain.cc sends I/O commands via taskclass.cc.

iocontrol main loop process:
Historically this was a separate process named iocontrol, talking to
task over its own NML channels; the HAL component is still named
iocontrol.0 (and the INI section [EMCIO]) for compatibility, but the
code now runs inside the task process. On each pass through the task
loop it:

- checks to see it HAL inputs have changed
- checks if read_tool_inputs() indicates the tool change is finished and set emcioStatus.status
- checks whether the iocontrol HAL input pins have changed
- checks if read_tool_inputs() indicates the tool change is finished and sets emcioStatus.status

== User Interfaces

Expand Down Expand Up @@ -887,7 +914,10 @@ The original NIST format of the buffer line is:
* 'B name type host size neut RPC# buffer# max_procs key [type specific configs]'
* 'B' - identifies this line as a Buffer configuration.
* 'name' - is the identifier of the buffer.
* 'type' - describes the buffer type - SHMEM, LOCMEM, FILEMEM, PHANTOM, or GLOBMEM.
* 'type' - describes the buffer type - SHMEM, LOCMEM, or PHANTOM.
(Older RCS documents also list FILEMEM, GLOBMEM and RTLMEM; none of these is

@grandixximo grandixximo Aug 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trimming the list is right, but the parenthetical puts the document back to tracking its own history; also "recognise" is the only British spelling in the file.

implemented in src/libnml/ - cms_config() rejects RTLMEM explicitly and does
not recognise the other two at all.)
* 'host' - is either an IP address or host name for the NML server
* 'size' - is the size of the buffer
* 'neut' - a boolean to indicate if the data in the buffer is encoded in a
Expand Down Expand Up @@ -945,12 +975,10 @@ The original NIST format of the process line is:
=== Configuration Comments

Some of the configuration combinations are invalid, whilst others
imply certain constraints. On a Linux system, GLOBMEM is obsolete,
whilst PHANTOM is only really useful in the testing stage of an
application, likewise for FILEMEM. LOCMEM is of little use for a
multi-process application, and only offers limited performance
advantages over SHMEM. This leaves SHMEM as the only buffer type to use
with LinuxCNC.
imply certain constraints. PHANTOM is only really useful in the testing
stage of an application. LOCMEM is of little use for a multi-process
application, and only offers limited performance advantages over SHMEM.
This leaves SHMEM as the only buffer type to use with LinuxCNC.

The neut option is only of use in a multi-processor system where
different (and incompatible) architectures are sharing a block of
Expand Down Expand Up @@ -1387,9 +1415,10 @@ FIXME: `axis_mask` and `axes` overspecify the number of axes
An array of `EMCMOT_MAX_JOINTS` joint structures.
`joint[0]` through `joint[joints-1]` are valid, the others do not exist on this machine and must be ignored.

Things are not this way currently in the joints-axes branch, but deviations from this design are considered bugs.
For an example of such a bug, see the treatment of axes in src/emc/ini/initraj.cc:loadTraj().
There are undoubtedly more, and I need your help to find them and fix them.
Deviations from this design are considered bugs; if you find one,
please report it. (An earlier revision of this document pointed at the

@grandixximo grandixximo Aug 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, the parenthetical keeps the removed bug report alive; the sentence before it is enough on its own.

treatment of axes in src/emc/ini/initraj.cc:loadTraj() as an example;
that code has since been fixed to handle all nine axes.)

=== In Motion

Expand Down
24 changes: 16 additions & 8 deletions docs/src/gcode/g-code.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1109,9 +1109,10 @@ M2 (end program)
It is an error if:

* All axis words are omitted.
* The spindle is not turning when this command is executed.
* The requested linear motion exceeds machine velocity limits
due to the spindle speed.
* No K word is given.
* An F word is given (the feed follows from K and the spindle speed).

@grandixximo grandixximo Aug 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additions check out (interp_check.cc:376 and :377). Could the deleted velocity-limit line stay as a NOTE though? It is real behaviour when pitch times RPM exceeds the axis limit, and it was the only mention in the manual.

* The selected spindle is not commanded to turn (M3 or M4 active) when
this command is executed.

[[gcode:g33.1]]
== G33.1 Rigid Tapping(((G33.1 Rigid Tapping)))
Expand All @@ -1123,6 +1124,7 @@ G33.1 X- Y- Z- K- I- $-

* 'K' - distance per revolution
* 'I' - optional spindle speed multiplier for faster return move
(values less than 1 are treated as 1)
* '$' - optional spindle selector

[WARNING]
Expand Down Expand Up @@ -1175,9 +1177,10 @@ M2 (end program)
It is an error if:

* All axis words are omitted.
* The spindle is not turning when this command is executed
* The requested linear motion exceeds machine velocity limits
due to the spindle speed
* No K word is given.
* An F word is given (the feed follows from K and the spindle speed).
* The selected spindle is not commanded to turn (M3 or M4 active) when
this command is executed.

[[gcode:g38]]
== G38._n_ Straight Probe(((G38.n Probe)))
Expand Down Expand Up @@ -1677,6 +1680,11 @@ G64 <P- <Q->>

It is a good idea to include a path control specification in the preamble of each G-code file.

It is an error if:

* The path control mode is changed (G61, G61.1 or G64) while cutter
radius compensation is active.

.G64 P- Q- Example Line
[source,ngc]
----
Expand Down Expand Up @@ -2720,7 +2728,8 @@ G96 <D-> S- <$-> (Constant Surface Speed Mode)
G97 S- <$-> (RPM Mode)
----

. 'D' - maximum rotation speed (RPM), optional
. 'D' - maximum rotation speed (RPM), optional. Without D the spindle
speed in CSS mode is not limited by the interpreter.
. 'S' - spindle speed
. '$' - the spindle of which the speed will be varied, optional.

Expand All @@ -2747,7 +2756,6 @@ G96 D2500 S250 (set CSS with a max rpm of 2500 and a surface speed of 250)
It is an error if:

* S is not specified with G96
* A feed move is specified in G96 mode while the spindle is not turning

[[gcode:g98-g99]]
== G98, G99 Canned Cycle Return Level(((G98, G99 Canned Cycle Return)))
Expand Down
4 changes: 2 additions & 2 deletions docs/src/hal/basic-hal.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ addf mux4.0 servo-thread

(((HAL initf,initf)))
The `initf` command registers a function to run once in realtime context, on a dedicated init cycle of the thread before the cyclic function list runs.
It is the realtime-thread analogue of `addf`, intended for one-shot setup that must execute in the realtime task (for example EtherCAT master activation via `lcec.0.activate`).
It is the realtime-thread analogue of `addf`, intended for one-shot setup that must execute in the realtime task (for example EtherCAT master activation via `lcec.activate`).

`initf` adds function _functname_ to the init list of thread _threadname_.
The init list runs once on the first cycle after `start`, then is drained.
Expand All @@ -109,7 +109,7 @@ Once the init cycle has run, further `initf` calls on that thread are rejected.
[source,{hal}]
----
initf <function> <thread>
initf lcec.0.activate servo-thread
initf lcec.activate servo-thread
----

[[sub:hal-loadusr]]
Expand Down
Loading