With Marlin version 2.0.9.x or higher, Laser improvements were introduced that enhance inline functionality. Previously the inline feature option was not operational without enabling and recompiling the source. Also with inline enabled the base features are not functional. With v2.0.9.x new functionality is added which allows the standard and inline modes to be G-Code selectable and also compatible with each other. Additionally an experimental dynamic mode is also available. Spindle operational features are available with defines and recompiling.
Laser selectable feature capability is defined through 4 global mode flags within G-code ,laser/spindle, planner and stepper routines. The default mode maintains the standard laser function. G-Codes are received, processed and parsed to determine what mode to set through M3, M4 and M5 commands. When the inline mode parameter set is detected, laser power processing will be driven through the planner and stepper routines. Handling of the initial power values and settings are performed by G-Code parsing and the laser/spindle routines.
Inline power feeds from the block->inline_power variable into the planner's laser.power when in continuous power mode. Further power adjustment will be applied if the laser power trap feature is active otherwise laser.power is used as set in the stepper for the entire block. When laser power trap is active the power levels are step incremented during acceleration and step decremented during deceleration.
Two additional power sets are fed in the planner by features laser power sync and laser fan power sync. Both of these power sets are done with planner sync block bit flags. With laser power sync, when the bit flag is matched the global block laser.power value is updated from laser/spindle standard M3 S-Value power sets. For laser fan sync, power values are updated into the planner block->fan_speed[i] variable from fan G-Code S-Value sets.
With dynamic inline power mode, F-Value feedrate sets are processed with cutter.calc_dynamic_power() and fed into the planner laser.power value.
Irrespective of what laser power value source is used, the final laser output pin is always updated using the laser/spindle code. Specifically the apply_power(value) call is used to set the laser or spindle output. This call permits safe power control in the event that a sensor fault occurs.
Note: Spindle operation is not selectable with G-Codes at this time.
The following flow charts depict the flow control logic for spindle and laser operations in the code base.
When LASER_FEATURE and LASER_POWER_TRAP are defined, planner calculations are performed and applied to the incoming laser power S-Value. The power will be factored and distributed across trapezoid acceleration and deceleration movements.
When the laser.power > 0
We set a minimum power if defined in SPEED_POWER_MIN it's fed into the planner block as laser_power_floor.
A reduced entry laser power factor is based on the entry step rate to cruise step rate ratio for acceleration.
block entry laser power = laser power * ( entry step rate / cruise step rate )
Dynamic mode will calculate laser power based on the F-Value feedrate. The method uses bit shifting to set a power level from 0 to 255. It's simple and fast and we can use a scaler to shift the laser power output to center on a given power level.
#### Spindle/Laser Code:
```
// Dynamic mode rate calculation
static inline uint8_t calc_dynamic_power() {
if (feedrate_mm_m > 65535) return 255; // Too fast, go always on
uint16_t rate = uint16_t(feedrate_mm_m); // 16 bits from the G-code parser float input
rate >>= 8; // Take the G-code input e.g. F40000 and shift off the lower bits to get an OCR value from 1-255