Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Push/Pull V-Tool, Report All Mixes via M165 R, and full E support #26922

Draft
wants to merge 33 commits into
base: bugfix-2.1.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
cd49d72
Add J and K factors
Glodigit Feb 24, 2024
45f7fa2
Config that compiles
Glodigit Feb 24, 2024
63ee552
Revert "Config that compiles"
Glodigit Feb 24, 2024
70643e0
.gitignore .vscode/extensions.json
Glodigit Feb 24, 2024
6df4ec2
Update comment in configuration.h
Glodigit Feb 24, 2024
2c6dee1
Add config setting and add notes
Glodigit Feb 24, 2024
4518f94
Fixed "ABCDHIJK" comments
Glodigit Feb 24, 2024
eb2a62e
Add M167 commands
Glodigit Feb 24, 2024
476a202
fixed missing LIST_N(MIXING_STEPPERS...) parameters
Glodigit Feb 24, 2024
25a1943
Start on M165_report
Glodigit Feb 25, 2024
67c1679
Remove REPORT_VTOOLS_MIX
Glodigit Feb 25, 2024
514656b
Merge branch 'PR-8-Extruder-Mixing' into PR-Report-Virtual-Tools
Glodigit Feb 25, 2024
b9dae21
Implemented M165_report
Glodigit Feb 25, 2024
5f154ec
remove '.vscode/extensions.json' from .gitignore
Glodigit Feb 25, 2024
740506b
fix missing last tool. attempt to fix missing first tool.
Glodigit Feb 25, 2024
673b785
Compact M165 report and fix BTT TFT terminal bug
Glodigit Feb 25, 2024
67c8b10
remove trailing whitespace
Glodigit Feb 25, 2024
c550e68
Add PUSH_PULL_TOOLCHANGE to Config.h
Glodigit Mar 23, 2024
58193fd
Write initial mixing.h implementation for pushpull toolchange, and sl…
Glodigit Mar 26, 2024
024bd8b
Clean up pushpull code.
Glodigit Mar 26, 2024
45bc8e1
Implement T_pushpull, thus mixing extruder directions are now decoupl…
Glodigit Mar 30, 2024
c4f8082
T_pushpull - fix compilation errors and improve config.h comment read…
Glodigit Mar 30, 2024
135e9dd
T_pushpull compile fix: enable Mixer::mix for pushpull toolchange
Glodigit Mar 30, 2024
3e0e9a9
Split T_pushpull() to update_pushpull() and code in tool_change(), so…
Glodigit Mar 30, 2024
a766b71
Fix toggling same v-tool and 1/2 pushpull speed and distance bug.
Glodigit Mar 30, 2024
aa9d589
Merge branch 'bugfix-2.1.x' of https://github.com/MarlinFirmware/Marl…
Glodigit Mar 30, 2024
0bc60d7
remove implementation plan comment
Glodigit Mar 30, 2024
42c3d64
Remove extra do...while(0) from E_APPLY_DIR macro
Glodigit Mar 31, 2024
4a63676
Fix scaling, e.g. from v-tool A5 B5 C0 D0 to A0 B0 C5 D5
Glodigit Mar 31, 2024
0b3d99e
pushpull_t cleanup
Glodigit Mar 31, 2024
3536c07
pushpull code cleanup
Glodigit Mar 31, 2024
1e65cb4
Avoid G3 crash (and potential G1 issues with I/J/K axes) by changing …
Glodigit Mar 31, 2024
9a34f0b
reset pushpull.scale, minor cleanup
Glodigit Apr 1, 2024
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
7 changes: 6 additions & 1 deletion Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,12 +351,17 @@
#if ENABLED(MIXING_EXTRUDER)
#define MIXING_STEPPERS 2 // Number of steppers in your mixing extruder
#define MIXING_VIRTUAL_TOOLS 16 // Use the Virtual Tool method with M163 and M164
//#define DIRECT_MIXING_IN_G1 // Allow ABCDHI mix factors in G1 movement commands
//#define DIRECT_MIXING_IN_G1 // Allow ABCDLMNO mix factors in G1 movement commands, and R for reporting all V-tool mixes
//#define GRADIENT_MIX // Support for gradient mixing with M166 and LCD
//#define MIXING_PRESETS // Assign 8 default V-tool presets for 2 or 3 MIXING_STEPPERS
//#define PUSH_PULL_TOOLCHANGE // Simultaneously push the new V-tool and pull the old V-tool into the melt chamber
#if ENABLED(GRADIENT_MIX)
//#define GRADIENT_VTOOL // Add M166 T to use a V-tool index as a Gradient alias
#endif
#if ENABLED(PUSH_PULL_TOOLCHANGE)
#define MIXING_PUSH_PULL_MM 3 // (mm) Maximum length for a single extruder to push/pull
#define MIXING_PUSH_PULL_FEEDRATE 300 // (mm/min) V-tool extruder feedrate
#endif
#endif

// Offset of the extruders (uncomment if using more than one and relying on firmware to position when changing).
Expand Down
2 changes: 2 additions & 0 deletions Marlin/src/core/language.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
#define STR_ERR_COLD_EXTRUDE_STOP " cold extrusion prevented"
#define STR_ERR_LONG_EXTRUDE_STOP " too long extrusion prevented"
#define STR_ERR_HOTEND_TOO_COLD "Hotend too cold"
#define STR_ERR_PUSHPULL_TOO_COLD "V-tool switched without push/pull"
#define STR_ERR_EEPROM_WRITE "Error writing to EEPROM!"
#define STR_ERR_EEPROM_CORRUPT "EEPROM Corrupt"

Expand Down Expand Up @@ -321,6 +322,7 @@
#define STR_TEMPERATURE_UNITS "Temperature Units"
#define STR_USER_THERMISTORS "User thermistors"
#define STR_DELAYED_POWEROFF "Delayed poweroff"
#define STR_CURRENT_VTOOLS "Current virtual tool mixes"

//
// Endstop Names used by Endstops::report_states
Expand Down
9 changes: 8 additions & 1 deletion Marlin/src/feature/mixing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ int_fast8_t Mixer::runner = 0;
mixer_comp_t Mixer::s_color[MIXING_STEPPERS];
mixer_accu_t Mixer::accu[MIXING_STEPPERS] = { 0 };

#if ANY(HAS_DUAL_MIXING, GRADIENT_MIX)
#if ANY(HAS_DUAL_MIXING, GRADIENT_MIX, PUSH_PULL_TOOLCHANGE)
mixer_perc_t Mixer::mix[MIXING_STEPPERS];
#endif

Expand Down Expand Up @@ -154,6 +154,13 @@ void Mixer::refresh_collector(const float proportion/*=1.0*/, const uint8_t t/*=
//SERIAL_EOL();
}

#if ENABLED(PUSH_PULL_TOOLCHANGE)
pushpull_t Mixer::pushpull = {
0, // e_directions
0, // scale
};
#endif

#if ENABLED(GRADIENT_MIX)

#include "../module/motion.h"
Expand Down
62 changes: 52 additions & 10 deletions Marlin/src/feature/mixing.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,16 @@ enum MixTool {
#if HAS_MIXER_SYNC_CHANNEL
, MIXER_AUTORETRACT_TOOL
#endif
#if ENABLED(PUSH_PULL_TOOLCHANGE)
, MIXER_PUSHPULL_TOOL
#endif
, NR_MIXING_VIRTUAL_TOOLS
};

#define MAX_VTOOLS TERN(HAS_MIXER_SYNC_CHANNEL, 254, 255)
#define MAX_VTOOLS (255 TERN_(PUSH_PULL_TOOLCHANGE, -1) TERN_(HAS_MIXER_SYNC_CHANNEL, -1))
static_assert(NR_MIXING_VIRTUAL_TOOLS <= MAX_VTOOLS, "MIXING_VIRTUAL_TOOLS must be <= " STRINGIFY(MAX_VTOOLS) "!");

#define VTOOLS_LOOP(VAR) for (uint_fast8_t VAR = 0; VAR < MIXING_VIRTUAL_TOOLS; VAR++)
#define MIXER_STEPPER_LOOP(VAR) for (uint_fast8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++)

#if ENABLED(GRADIENT_MIX)
Expand All @@ -75,6 +79,13 @@ static_assert(NR_MIXING_VIRTUAL_TOOLS <= MAX_VTOOLS, "MIXING_VIRTUAL_TOOLS must

#endif

#if ENABLED(PUSH_PULL_TOOLCHANGE)
typedef struct {
uint8_t direction_bits; // Extruder direction, where 1 is negative
float scale; // The scale to multiply the extruder speed and length
} pushpull_t;
#endif

/**
* @brief Mixer class
* @details Contains data and behaviors for a Mixing Extruder
Expand Down Expand Up @@ -118,24 +129,24 @@ class Mixer {
MIXER_STEPPER_LOOP(i) s_color[i] = b_color[i];
}

#if ANY(HAS_DUAL_MIXING, GRADIENT_MIX)
#if ANY(PUSH_PULL_TOOLCHANGE, HAS_DUAL_MIXING, GRADIENT_MIX)

static mixer_perc_t mix[MIXING_STEPPERS]; // Scratch array for the Mix in proportion to 100

static void copy_mix_to_color(mixer_comp_t (&tcolor)[MIXING_STEPPERS]) {
// Scale each component to the largest one in terms of COLOR_A_MASK
// So the largest component will be COLOR_A_MASK and the other will be in proportion to it
const float scale = (COLOR_A_MASK) * RECIPROCAL(_MAX(
LIST_N(MIXING_STEPPERS, mix[0], mix[1], mix[2], mix[3], mix[4], mix[5])
LIST_N(MIXING_STEPPERS, mix[0], mix[1], mix[2], mix[3], mix[4], mix[5], mix[6], mix[7])
));

// Scale all values so their maximum is COLOR_A_MASK
MIXER_STEPPER_LOOP(i) tcolor[i] = mix[i] * scale;

#ifdef MIXER_NORMALIZER_DEBUG
SERIAL_ECHOLN(
F("Mix [ "), LIST_N(MIXING_STEPPERS, mix[0], mix[1], mix[2], mix[3], mix[4], mix[5]),
F(" ] to Color [ "), LIST_N(MIXING_STEPPERS, tcolor[0], tcolor[1], tcolor[2], tcolor[3], tcolor[4], tcolor[5]),
F("Mix [ "), LIST_N(MIXING_STEPPERS, mix[0], mix[1], mix[2], mix[3], mix[4], mix[5], mix[6], mix[7]),
F(" ] to Color [ "), LIST_N(MIXING_STEPPERS, tcolor[0], tcolor[1], tcolor[2], tcolor[3], tcolor[4], tcolor[5], tcolor[6], tcolor[7]),
F(" ]")
);
#endif
Expand All @@ -148,13 +159,43 @@ class Mixer {

#ifdef MIXER_NORMALIZER_DEBUG
SERIAL_ECHOLN(F("V-tool "), j,
F(" [ "), LIST_N(MIXING_STEPPERS, color[j][0], color[j][1], color[j][2], color[j][3], color[j][4], color[j][5]),
F(" ] to Mix [ "), LIST_N(MIXING_STEPPERS, mix[0], mix[1], mix[2], mix[3], mix[4], mix[5]), F(" ]")
F(" [ "), LIST_N(MIXING_STEPPERS, color[j][0], color[j][1], color[j][2], color[j][3], color[j][4], color[j][5], color[j][6], color[j][7]),
F(" ] to Mix [ "), LIST_N(MIXING_STEPPERS, mix[0], mix[1], mix[2], mix[3], mix[4], mix[5], mix[6], mix[7]), F(" ]")
);
#endif
}

#endif // HAS_DUAL_MIXING || GRADIENT_MIX
#endif // PUSH_PULL_TOOLCHANGE || HAS_DUAL_MIXING || GRADIENT_MIX

#if ENABLED(PUSH_PULL_TOOLCHANGE)
static pushpull_t pushpull;

// Outputs true for positive direction. Used in Stepper.
FORCE_INLINE static bool e_dir(uint_fast8_t VAR) { return !TEST(pushpull.direction_bits, VAR); }

// Update the push/pull v-tool, its direction bits and scale factor
static void update_pushpull_tool(const uint_fast8_t new_vtool){
pushpull.direction_bits = 0; pushpull.scale = 0;
if (new_vtool == selected_vtool) return;

mixer_perc_t pull_mix[MIXING_STEPPERS] = {0};
update_mix_from_vtool();
MIXER_STEPPER_LOOP(i) pull_mix[i] = mix[i];
update_mix_from_vtool(new_vtool);
MIXER_STEPPER_LOOP(i) {
mix[i] -= pull_mix[i];
if (mix[i] < 0) {
SBI(pushpull.direction_bits, i);
mix[i] *= -1.0f;
}
}
copy_mix_to_color(color[MIXER_PUSHPULL_TOOL]);

float ctot = 0;
MIXER_STEPPER_LOOP(i) ctot += color[MIXER_PUSHPULL_TOOL][i];
pushpull.scale = ctot / (COLOR_A_MASK);
}
#endif // PUSH_PULL_TOOLCHANGE

#if HAS_DUAL_MIXING

Expand Down Expand Up @@ -192,8 +233,9 @@ class Mixer {

#ifdef MIXER_NORMALIZER_DEBUG
SERIAL_ECHOLN(
F("Gradient [ "), LIST_N(MIXING_STEPPERS, gradient.color[0], gradient.color[1], gradient.color[2], gradient.color[3], gradient.color[4], gradient.color[5]),
F(" ] to Mix [ "), LIST_N(MIXING_STEPPERS, mix[0], mix[1], mix[2], mix[3], mix[4], mix[5]), F(" ]")
F("Gradient [ "), LIST_N(MIXING_STEPPERS, gradient.color[0], gradient.color[1], gradient.color[2], gradient.color[3],
gradient.color[4], gradient.color[5], gradient.color[6], gradient.color[7]),
F(" ] to Mix [ "), LIST_N(MIXING_STEPPERS, mix[0], mix[1], mix[2], mix[3], mix[4], mix[5], mix[6], mix[7]), F(" ]")
);
#endif
}
Expand Down
29 changes: 26 additions & 3 deletions Marlin/src/gcode/feature/mixing/M163-M165.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,16 @@ void GcodeSuite::M164() {
* B[factor] Mix factor for extruder stepper 2
* C[factor] Mix factor for extruder stepper 3
* D[factor] Mix factor for extruder stepper 4
* H[factor] Mix factor for extruder stepper 5
* I[factor] Mix factor for extruder stepper 6
* L[factor] Mix factor for extruder stepper 5
* M[factor] Mix factor for extruder stepper 6
* N[factor] Mix factor for extruder stepper 7
* O[factor] Mix factor for extruder stepper 8
*/
void GcodeSuite::M165() {
// Get mixing parameters from the G-Code
// The total "must" be 1.0 (but it will be normalized)
// If no mix factors are given, the old mix is preserved
const char mixing_codes[] = { LIST_N(MIXING_STEPPERS, 'A', 'B', 'C', 'D', 'H', 'I') };
const char mixing_codes[] = { LIST_N(MIXING_STEPPERS, 'A', 'B', 'C', 'D', 'L', 'M', 'N', 'O') };
uint8_t mix_bits = 0;
MIXER_STEPPER_LOOP(i) {
if (parser.seenval(mixing_codes[i])) {
Expand All @@ -94,6 +96,27 @@ void GcodeSuite::M164() {
if (!TEST(mix_bits, i)) mixer.set_collector(i, 0.0f);
mixer.normalize();
}
// Report the latest V-tool mixes
if (parser.seen_test('R')) M165_report();
}

void GcodeSuite::M165_report(const bool forReplay/*=true*/) {
gcode.report_heading_etc(forReplay, F(STR_CURRENT_VTOOLS));
VTOOLS_LOOP(i) {
// Get mixes from all tools as a percentage
mixer.refresh_collector(100.0, i);
SERIAL_ECHO(F(" V"), i, ":"); // Avoid using 'Tn:' substring so output is fully visible on
// BTT Touchscreen terminal.
SERIAL_ECHOLNPGM(LIST_N(DOUBLE(MIXING_STEPPERS),
" A", p_float_t(mixer.collector[0], 1),
" B", p_float_t(mixer.collector[1], 1),
" C", p_float_t(mixer.collector[2], 1),
" D", p_float_t(mixer.collector[3], 1),
" L", p_float_t(mixer.collector[4], 1),
" M", p_float_t(mixer.collector[5], 1),
" N", p_float_t(mixer.collector[6], 1),
" O", p_float_t(mixer.collector[7], 1)));
}
}

#endif // DIRECT_MIXING_IN_G1
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/gcode/gcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ void GcodeSuite::get_destination_from_command() {
print_job_timer.incFilamentUsed(destination.e - current_position.e);
#endif

// Get ABCDHI mixing factors
// Get ABCDLMNO mixing factors
#if ALL(MIXING_EXTRUDER, DIRECT_MIXING_IN_G1)
M165();
#endif
Expand Down
3 changes: 2 additions & 1 deletion Marlin/src/gcode/gcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
* M155 - Auto-report temperatures with interval of S<seconds>. (Requires AUTO_REPORT_TEMPERATURES)
* M163 - Set a single proportion for a mixing extruder. (Requires MIXING_EXTRUDER)
* M164 - Commit the mix and save to a virtual tool (current, or as specified by 'S'). (Requires MIXING_EXTRUDER)
* M165 - Set the mix for the mixing extruder (and current virtual tool) with parameters ABCDHI. (Requires MIXING_EXTRUDER and DIRECT_MIXING_IN_G1)
* M165 - Set the mix for the mixing extruder (and current virtual tool) with parameters ABCDLMNO. (Requires MIXING_EXTRUDER and DIRECT_MIXING_IN_G1)
* M166 - Set the Gradient Mix for the mixing extruder. (Requires GRADIENT_MIX)
* M190 - Set bed target temperature and wait. R<temp> Set target temperature and wait. S<temp> Set, but only wait when heating. (Requires TEMP_SENSOR_BED)
* M192 - Wait for probe to reach target temperature. (Requires TEMP_SENSOR_PROBE)
Expand Down Expand Up @@ -848,6 +848,7 @@ class GcodeSuite {
static void M164();
#if ENABLED(DIRECT_MIXING_IN_G1)
static void M165();
static void M165_report(const bool forReplay=true);
#endif
#if ENABLED(GRADIENT_MIX)
static void M166();
Expand Down
6 changes: 5 additions & 1 deletion Marlin/src/module/stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,11 @@ xyze_int8_t Stepper::count_direction{0};
//#define E7_APPLY_DIR(FWD) do{ (FWD) ? FWD_E_DIR(7) : REV_E_DIR(7); }while(0)

#if ENABLED(MIXING_EXTRUDER)
#define E_APPLY_DIR(FWD,Q) do{ if (FWD) { MIXER_STEPPER_LOOP(j) FWD_E_DIR(j); } else { MIXER_STEPPER_LOOP(j) REV_E_DIR(j); } }while(0)
#if ENABLED(PUSH_PULL_TOOLCHANGE)
#define E_APPLY_DIR(FWD,Q) MIXER_STEPPER_LOOP(j) do{ if (FWD == mixer.e_dir(j)) { FWD_E_DIR(j); } else { REV_E_DIR(j); } }while(0)
#else
#define E_APPLY_DIR(FWD,Q) do{ if (FWD) { MIXER_STEPPER_LOOP(j) FWD_E_DIR(j); } else { MIXER_STEPPER_LOOP(j) REV_E_DIR(j); } }while(0)
#endif
#else
#define E_APPLY_STEP(FWD,Q) E_STEP_WRITE(stepper_extruder, FWD)
#define E_APPLY_DIR(FWD,Q) do{ if (FWD) { FWD_E_DIR(stepper_extruder); } else { REV_E_DIR(stepper_extruder); } }while(0)
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/module/stepper/indirection.h
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,7 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#if ENABLED(MIXING_EXTRUDER)

/**
* Mixing steppers keep all their enable (and direction) states synchronized
* Mixing steppers keep all their enable states synchronized
*/
#define _CALL_ENA_E(N) ENABLE_STEPPER_E##N () ;
#define _CALL_DIS_E(N) DISABLE_STEPPER_E##N () ;
Expand Down
55 changes: 41 additions & 14 deletions Marlin/src/module/tool_change.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@

#if ENABLED(MIXING_EXTRUDER)
#include "../feature/mixing.h"
#if ENABLED(PUSH_PULL_TOOLCHANGE)
#include "stepper.h"
#endif
#endif

#if HAS_LEVELING
Expand Down Expand Up @@ -892,6 +895,22 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.

#endif // DUAL_X_CARRIAGE

#if ANY(TOOLCHANGE_FILAMENT_SWAP, MIXING_EXTRUDER)
/**
* Check if too cold to move the specified tool
*
* Returns TRUE if too cold to move (also echos message: STR_ERR_HOTEND_TOO_COLD)
* Returns FALSE if able to move.
*/
bool too_cold(uint8_t toolID){
if (!DEBUGGING(DRYRUN) && thermalManager.targetTooColdToExtrude(toolID)) {
SERIAL_ECHO_MSG(STR_ERR_HOTEND_TOO_COLD);
return true;
}
return false;
}
#endif // TOOLCHANGE_FILAMENT_SWAP || MIXING_EXTRUDER

/**
* Prime active tool using TOOLCHANGE_FILAMENT_SWAP settings
*/
Expand All @@ -916,20 +935,6 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
#endif
}

/**
* Check if too cold to move the specified tool
*
* Returns TRUE if too cold to move (also echos message: STR_ERR_HOTEND_TOO_COLD)
* Returns FALSE if able to move.
*/
bool too_cold(uint8_t toolID){
if (!DEBUGGING(DRYRUN) && thermalManager.targetTooColdToExtrude(toolID)) {
SERIAL_ECHO_MSG(STR_ERR_HOTEND_TOO_COLD);
return true;
}
return false;
}

/**
* Cutting recovery -- Recover from cutting retraction that occurs at the end of nozzle priming
*
Expand Down Expand Up @@ -1118,6 +1123,28 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
return invalid_extruder_error(new_tool);

#if MIXING_VIRTUAL_TOOLS > 1
#if ENABLED(PUSH_PULL_TOOLCHANGE)
if (too_cold(active_extruder)) SERIAL_ECHO_MSG(STR_ERR_PUSHPULL_TOO_COLD);
else {
mixer.update_pushpull_tool(new_tool);

if (mixer.pushpull.scale > 0) {
// Enable Push/Pull V-Tool
stepper.apply_directions();
mixer.T(MIXER_PUSHPULL_TOOL);

// Extrude
float resume_current_e = current_position.e;
unscaled_e_move(MIXING_PUSH_PULL_MM * mixer.pushpull.scale,
MMM_TO_MMS(MIXING_PUSH_PULL_FEEDRATE) * mixer.pushpull.scale);

// Reset
mixer.pushpull.direction_bits = 0; stepper.apply_directions();
current_position.e = resume_current_e; sync_plan_position_e();
}
}
#endif

// T0-Tnnn: Switch virtual tool by changing the index to the mix
mixer.T(new_tool);
#endif
Expand Down