Design document, for discussion and comment
We define a job as sequence of related GCode block or FluidNC commands that accomplish some task. A GCode file, which could be executed from an SD card or sent from a sender, would be a job. So would a macro. The key point is that the items in the sequence are meant to be executed from beginning to end, not as unrelated individual items.
Classic GRBL has no notion of a job. When it receives a GCode block or a $ command, it executes it, with no implied relationship to commands that come before or after. The one “grouping” concept is that, if a GCode block arrives when motion is already in progress, GRBL tries to “splice” the new motion onto previously-planned motion so that the machine does not come to a complete stop between the execution of the old and new commands - except in the case of “synchronous” commands that imply a complete stop.
This works reasonably well in the conventional situation where the commands are coming from a single “sender” over a single communication channel (typically a serial port). In that scenario, the sender can take care of higher-level relationships such as the notion that lines within a GCode file are a related sequence with a beginning and an end.
FluidNC can accept commands from multiple communication channels, execute GCode files from a filesystem on, for example, an SD card, and execute macros that are stored locally in memory or on a filesystem. At present, its only notion of grouping is the knowledge that an SD card file is currently one of the input sources. That knowledge is hard-coded in an ad-hoc fashion, with no formalism of a “job” and only a weak form of reporting that a job is underway. (The status report contains an ‘SD:’ field that says that input is coming from an SD card file, but the synchronization is poor. When the last line from the file has been sent to the planner, the final SD: field is issued, possibly long before the motion implied by all of the lines from the file is finished.)
This design intends to add job context management to FluidNC, so that a sequence of related lines (a “job”) can be tracked and executed as a group, with controlled interaction between disparate jobs. Interacting jobs are treated like subroutines in a programming language - when a job finishes, the job that initiated it is resumed after the place that initiated the “interior” job.
Some use cases/goals:
For starters, I intend to create a “Job Channel” abstraction that can apply to SD files and FluidNC macros. Instead of the current status quo where there can be a single SD card input file that is interleaved with input from all other channels, and macros that are similarly interleaved into the Channel multiplexor, there will be a stack of active JobChannels. When that stack in non-empty, line-oriented input will come only from the top of that stack - but other interactive channels can still issue realtime characters for things like overrides and feedhold. When the end of file is reached on that JobChannel, the stack will be popped (and execution synchronized), so input from the previous job will resume.
Eventually, we may design a bracketing protocol that senders could use to apply the same sort of grouping to jobs being sent from outside.
The Jobs branch has a first cut at job context management. From a gcode stream, file (SD or localfs) run, or a macro (or the startup line), you can invoke another job, and when it finishes, input from the previous context will resume.
So, for example, you could have:
macros:
startup: G20&$macros/run=0&G21
macro0: $macros/run=1&$sd/run=foo.nc&$sd/run=foo.nc
macro1: (msg_Running macro1)&G1 X100
The calling and resuming works, but there is a feature I would like to add - state reporting that is synchronized with the execution of the lines from a job. The current status quo is that the status report tells you which lines have been sent to the planner, not what has actually been executed. So when all the lines from a job source have been sent, you get a "job succeeded" message. It would be nice to know when all the motion is done. You can sort of infer that if you add a synchronizing command like G4 at the end, but there should be a better way.
“startup_line0: and “…line1” have been replaced by just “startup”. Having 2 lines is unnecessary since we can now splice together as many lines as we want using &.
What should these modes be.