Fix IDEX layer shift and DIR states (#19756)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
		| @@ -223,8 +223,7 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l | |||||||
|   #if ENABLED(DUAL_X_CARRIAGE) |   #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|     const int8_t saved_ext        = active_extruder; |     const int8_t saved_ext        = active_extruder; | ||||||
|     const bool saved_ext_dup_mode = extruder_duplication_enabled; |     const bool saved_ext_dup_mode = extruder_duplication_enabled; | ||||||
|     active_extruder = DXC_ext; |     set_duplication_enabled(false, DXC_ext); | ||||||
|     extruder_duplication_enabled = false; |  | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   // Slow Load filament |   // Slow Load filament | ||||||
| @@ -245,9 +244,7 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   #if ENABLED(DUAL_X_CARRIAGE)      // Tie the two extruders movement back together. |   #if ENABLED(DUAL_X_CARRIAGE)      // Tie the two extruders movement back together. | ||||||
|     active_extruder = saved_ext; |     set_duplication_enabled(saved_ext_dup_mode, saved_ext); | ||||||
|     extruder_duplication_enabled = saved_ext_dup_mode; |  | ||||||
|     stepper.set_directions(); |  | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   #if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE) |   #if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE) | ||||||
| @@ -439,17 +436,14 @@ bool pause_print(const float &retract, const xyz_pos_t &park_point, const float | |||||||
|   #if ENABLED(DUAL_X_CARRIAGE) |   #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|     const int8_t saved_ext        = active_extruder; |     const int8_t saved_ext        = active_extruder; | ||||||
|     const bool saved_ext_dup_mode = extruder_duplication_enabled; |     const bool saved_ext_dup_mode = extruder_duplication_enabled; | ||||||
|     active_extruder = DXC_ext; |     set_duplication_enabled(false, DXC_ext); | ||||||
|     extruder_duplication_enabled = false; |  | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   if (unload_length)   // Unload the filament |   if (unload_length)   // Unload the filament | ||||||
|     unload_filament(unload_length, show_lcd, PAUSE_MODE_CHANGE_FILAMENT); |     unload_filament(unload_length, show_lcd, PAUSE_MODE_CHANGE_FILAMENT); | ||||||
|  |  | ||||||
|   #if ENABLED(DUAL_X_CARRIAGE) |   #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|     active_extruder = saved_ext; |     set_duplication_enabled(saved_ext_dup_mode, saved_ext); | ||||||
|     extruder_duplication_enabled = saved_ext_dup_mode; |  | ||||||
|     stepper.set_directions(); |  | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   return true; |   return true; | ||||||
| @@ -495,8 +489,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep | |||||||
|   #if ENABLED(DUAL_X_CARRIAGE) |   #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|     const int8_t saved_ext        = active_extruder; |     const int8_t saved_ext        = active_extruder; | ||||||
|     const bool saved_ext_dup_mode = extruder_duplication_enabled; |     const bool saved_ext_dup_mode = extruder_duplication_enabled; | ||||||
|     active_extruder = DXC_ext; |     set_duplication_enabled(false, DXC_ext); | ||||||
|     extruder_duplication_enabled = false; |  | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   // Wait for filament insert by user and press button |   // Wait for filament insert by user and press button | ||||||
| @@ -550,9 +543,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep | |||||||
|     idle_no_sleep(); |     idle_no_sleep(); | ||||||
|   } |   } | ||||||
|   #if ENABLED(DUAL_X_CARRIAGE) |   #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|     active_extruder = saved_ext; |     set_duplication_enabled(saved_ext_dup_mode, saved_ext); | ||||||
|     extruder_duplication_enabled = saved_ext_dup_mode; |  | ||||||
|     stepper.set_directions(); |  | ||||||
|   #endif |   #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -89,10 +89,11 @@ bool pause_print(const float &retract, const xyz_pos_t &park_point, const float | |||||||
|  |  | ||||||
| void wait_for_confirmation(const bool is_reload=false, const int8_t max_beep_count=0 DXC_PARAMS); | void wait_for_confirmation(const bool is_reload=false, const int8_t max_beep_count=0 DXC_PARAMS); | ||||||
|  |  | ||||||
| void resume_print(const float &slow_load_length=0, const float &fast_load_length=0, const float &extrude_length=ADVANCED_PAUSE_PURGE_LENGTH, const int8_t max_beep_count=0, int16_t targetTemp=0 DXC_PARAMS); | void resume_print(const float &slow_load_length=0, const float &fast_load_length=0, const float &extrude_length=ADVANCED_PAUSE_PURGE_LENGTH, | ||||||
|  |                     const int8_t max_beep_count=0, int16_t targetTemp=0 DXC_PARAMS); | ||||||
|  |  | ||||||
| bool load_filament(const float &slow_load_length=0, const float &fast_load_length=0, const float &extrude_length=0, const int8_t max_beep_count=0, const bool show_lcd=false, | bool load_filament(const float &slow_load_length=0, const float &fast_load_length=0, const float &extrude_length=0, const int8_t max_beep_count=0, | ||||||
|                           const bool pause_for_user=false, const PauseMode mode=PAUSE_MODE_PAUSE_PRINT DXC_PARAMS); |                     const bool show_lcd=false, const bool pause_for_user=false, const PauseMode mode=PAUSE_MODE_PAUSE_PRINT DXC_PARAMS); | ||||||
|  |  | ||||||
| bool unload_filament(const float &unload_length, const bool show_lcd=false, const PauseMode mode=PAUSE_MODE_PAUSE_PRINT | bool unload_filament(const float &unload_length, const bool show_lcd=false, const PauseMode mode=PAUSE_MODE_PAUSE_PRINT | ||||||
|   #if BOTH(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER) |   #if BOTH(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER) | ||||||
|   | |||||||
| @@ -237,7 +237,7 @@ class FilamentSensorBase { | |||||||
|         #if NUM_RUNOUT_SENSORS == 1 |         #if NUM_RUNOUT_SENSORS == 1 | ||||||
|           UNUSED(extruder); |           UNUSED(extruder); | ||||||
|         #else |         #else | ||||||
|           if ( !TERN0(DUAL_X_CARRIAGE, dxc_is_duplicating()) |           if ( !TERN0(DUAL_X_CARRIAGE, idex_is_duplicating()) | ||||||
|             && !TERN0(MULTI_NOZZLE_DUPLICATION, extruder_duplication_enabled) |             && !TERN0(MULTI_NOZZLE_DUPLICATION, extruder_duplication_enabled) | ||||||
|           ) return TEST(runout_states, extruder); // A specific extruder ran out |           ) return TEST(runout_states, extruder); // A specific extruder ran out | ||||||
|         #endif |         #endif | ||||||
|   | |||||||
| @@ -110,9 +110,8 @@ void GcodeSuite::G35() { | |||||||
|     tool_change(0, true); |     tool_change(0, true); | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   #if HAS_DUPLICATION_MODE |   // Disable duplication mode on homing | ||||||
|     extruder_duplication_enabled = false; |   TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false)); | ||||||
|   #endif |  | ||||||
|  |  | ||||||
|   // Home all before this procedure |   // Home all before this procedure | ||||||
|   home_all_axes(); |   home_all_axes(); | ||||||
|   | |||||||
| @@ -134,8 +134,8 @@ | |||||||
|  |  | ||||||
|       if (DEBUGGING(LEVELING)) DEBUG_POS("home_z_safely", destination); |       if (DEBUGGING(LEVELING)) DEBUG_POS("home_z_safely", destination); | ||||||
|  |  | ||||||
|       // This causes the carriage on Dual X to unpark |       // Free the active extruder for movement | ||||||
|       TERN_(DUAL_X_CARRIAGE, active_extruder_parked = false); |       TERN_(DUAL_X_CARRIAGE, idex_set_parked(false)); | ||||||
|  |  | ||||||
|       TERN_(SENSORLESS_HOMING, safe_delay(500)); // Short delay needed to settle |       TERN_(SENSORLESS_HOMING, safe_delay(500)); // Short delay needed to settle | ||||||
|  |  | ||||||
| @@ -282,7 +282,7 @@ void GcodeSuite::G28() { | |||||||
|     tool_change(0, true); |     tool_change(0, true); | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   TERN_(HAS_DUPLICATION_MODE, extruder_duplication_enabled = false); |   TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false)); | ||||||
|  |  | ||||||
|   remember_feedrate_scaling_off(); |   remember_feedrate_scaling_off(); | ||||||
|  |  | ||||||
| @@ -342,16 +342,14 @@ void GcodeSuite::G28() { | |||||||
|         homeaxis(X_AXIS); |         homeaxis(X_AXIS); | ||||||
|  |  | ||||||
|         // Remember this extruder's position for later tool change |         // Remember this extruder's position for later tool change | ||||||
|         inactive_extruder_x_pos = current_position.x; |         inactive_extruder_x = current_position.x; | ||||||
|  |  | ||||||
|         // Home the 1st (left) extruder |         // Home the 1st (left) extruder | ||||||
|         active_extruder = 0; |         active_extruder = 0; | ||||||
|         homeaxis(X_AXIS); |         homeaxis(X_AXIS); | ||||||
|  |  | ||||||
|         // Consider the active extruder to be parked |         // Consider the active extruder to be in its "parked" position | ||||||
|         raised_parked_position = current_position; |         idex_set_parked(); | ||||||
|         delayed_move_time = 0; |  | ||||||
|         active_extruder_parked = true; |  | ||||||
|  |  | ||||||
|       #else |       #else | ||||||
|  |  | ||||||
| @@ -392,7 +390,7 @@ void GcodeSuite::G28() { | |||||||
|    */ |    */ | ||||||
|   #if ENABLED(DUAL_X_CARRIAGE) |   #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|  |  | ||||||
|     if (dxc_is_duplicating()) { |     if (idex_is_duplicating()) { | ||||||
|  |  | ||||||
|       TERN_(IMPROVE_HOMING_RELIABILITY, slow_homing = begin_slow_homing()); |       TERN_(IMPROVE_HOMING_RELIABILITY, slow_homing = begin_slow_homing()); | ||||||
|  |  | ||||||
| @@ -401,19 +399,17 @@ void GcodeSuite::G28() { | |||||||
|       homeaxis(X_AXIS); |       homeaxis(X_AXIS); | ||||||
|  |  | ||||||
|       // Remember this extruder's position for later tool change |       // Remember this extruder's position for later tool change | ||||||
|       inactive_extruder_x_pos = current_position.x; |       inactive_extruder_x = current_position.x; | ||||||
|  |  | ||||||
|       // Home the 1st (left) extruder |       // Home the 1st (left) extruder | ||||||
|       active_extruder = 0; |       active_extruder = 0; | ||||||
|       homeaxis(X_AXIS); |       homeaxis(X_AXIS); | ||||||
|  |  | ||||||
|       // Consider the active extruder to be parked |       // Consider the active extruder to be parked | ||||||
|       raised_parked_position = current_position; |       idex_set_parked(); | ||||||
|       delayed_move_time = 0; |  | ||||||
|       active_extruder_parked = true; |  | ||||||
|       extruder_duplication_enabled = IDEX_saved_duplication_state; |  | ||||||
|       dual_x_carriage_mode = IDEX_saved_mode; |       dual_x_carriage_mode = IDEX_saved_mode; | ||||||
|       stepper.set_directions(); |       set_duplication_enabled(IDEX_saved_duplication_state); | ||||||
|  |  | ||||||
|       TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(slow_homing)); |       TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(slow_homing)); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -113,7 +113,7 @@ void GcodeSuite::G34() { | |||||||
|       tool_change(0, true); |       tool_change(0, true); | ||||||
|     #endif |     #endif | ||||||
|  |  | ||||||
|     TERN_(HAS_DUPLICATION_MODE, extruder_duplication_enabled = false); |     TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false)); | ||||||
|  |  | ||||||
|     // In BLTOUCH HS mode, the probe travels in a deployed state. |     // In BLTOUCH HS mode, the probe travels in a deployed state. | ||||||
|     // Users of G34 might have a badly misaligned bed, so raise Z by the |     // Users of G34 might have a badly misaligned bed, so raise Z by the | ||||||
|   | |||||||
| @@ -68,7 +68,7 @@ | |||||||
|       const DualXMode previous_mode = dual_x_carriage_mode; |       const DualXMode previous_mode = dual_x_carriage_mode; | ||||||
|  |  | ||||||
|       dual_x_carriage_mode = (DualXMode)parser.value_byte(); |       dual_x_carriage_mode = (DualXMode)parser.value_byte(); | ||||||
|       mirrored_duplication_mode = false; |       idex_set_mirrored_mode(false); | ||||||
|  |  | ||||||
|       if (dual_x_carriage_mode == DXC_MIRRORED_MODE) { |       if (dual_x_carriage_mode == DXC_MIRRORED_MODE) { | ||||||
|         if (previous_mode != DXC_DUPLICATION_MODE) { |         if (previous_mode != DXC_DUPLICATION_MODE) { | ||||||
| @@ -77,8 +77,7 @@ | |||||||
|           dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; |           dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
|         mirrored_duplication_mode = true; |         idex_set_mirrored_mode(true); | ||||||
|         stepper.set_directions(); |  | ||||||
|         float x_jog = current_position.x - .1; |         float x_jog = current_position.x - .1; | ||||||
|         for (uint8_t i = 2; --i;) { |         for (uint8_t i = 2; --i;) { | ||||||
|           planner.buffer_line(x_jog, current_position.y, current_position.z, current_position.e, feedrate_mm_s, 0); |           planner.buffer_line(x_jog, current_position.y, current_position.z, current_position.e, feedrate_mm_s, 0); | ||||||
| @@ -102,10 +101,8 @@ | |||||||
|           dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; |           dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; | ||||||
|           break; |           break; | ||||||
|       } |       } | ||||||
|       active_extruder_parked = false; |       idex_set_parked(false); | ||||||
|       extruder_duplication_enabled = false; |       set_duplication_enabled(false); | ||||||
|       stepper.set_directions(); |  | ||||||
|       delayed_move_time = 0; |  | ||||||
|     } |     } | ||||||
|     else if (!parser.seen('W'))  // if no S or W parameter, the DXC mode gets reset to the user's default |     else if (!parser.seen('W'))  // if no S or W parameter, the DXC mode gets reset to the user's default | ||||||
|       dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; |       dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; | ||||||
| @@ -125,7 +122,7 @@ | |||||||
|         if (!active_extruder_parked) DEBUG_ECHOPGM(" NOT "); |         if (!active_extruder_parked) DEBUG_ECHOPGM(" NOT "); | ||||||
|         DEBUG_ECHOPGM(" parked."); |         DEBUG_ECHOPGM(" parked."); | ||||||
|         DEBUG_ECHOPAIR("\nactive_extruder_x_pos: ", current_position.x); |         DEBUG_ECHOPAIR("\nactive_extruder_x_pos: ", current_position.x); | ||||||
|         DEBUG_ECHOPAIR("\ninactive_extruder_x_pos: ", inactive_extruder_x_pos); |         DEBUG_ECHOPAIR("\ninactive_extruder_x: ", inactive_extruder_x); | ||||||
|         DEBUG_ECHOPAIR("\nextruder_duplication_enabled: ", int(extruder_duplication_enabled)); |         DEBUG_ECHOPAIR("\nextruder_duplication_enabled: ", int(extruder_duplication_enabled)); | ||||||
|         DEBUG_ECHOPAIR("\nduplicate_extruder_x_offset: ", duplicate_extruder_x_offset); |         DEBUG_ECHOPAIR("\nduplicate_extruder_x_offset: ", duplicate_extruder_x_offset); | ||||||
|         DEBUG_ECHOPAIR("\nduplicate_extruder_temp_offset: ", duplicate_extruder_temp_offset); |         DEBUG_ECHOPAIR("\nduplicate_extruder_temp_offset: ", duplicate_extruder_temp_offset); | ||||||
| @@ -166,7 +163,7 @@ | |||||||
|       if (parser.seenval('P')) duplication_e_mask = parser.value_int();   // Set the mask directly |       if (parser.seenval('P')) duplication_e_mask = parser.value_int();   // Set the mask directly | ||||||
|       else if (parser.seenval('E')) duplication_e_mask = pow(2, parser.value_int() + 1) - 1; // Set the mask by E index |       else if (parser.seenval('E')) duplication_e_mask = pow(2, parser.value_int() + 1) - 1; // Set the mask by E index | ||||||
|       ena = (2 == parser.intval('S', extruder_duplication_enabled ? 2 : 0)); |       ena = (2 == parser.intval('S', extruder_duplication_enabled ? 2 : 0)); | ||||||
|       extruder_duplication_enabled = ena && (duplication_e_mask >= 3); |       set_duplication_enabled(ena && (duplication_e_mask >= 3)); | ||||||
|     } |     } | ||||||
|     SERIAL_ECHO_START(); |     SERIAL_ECHO_START(); | ||||||
|     SERIAL_ECHOPGM(STR_DUPLICATION_MODE); |     SERIAL_ECHOPGM(STR_DUPLICATION_MODE); | ||||||
|   | |||||||
| @@ -87,7 +87,7 @@ void GcodeSuite::M600() { | |||||||
|     if (!parser.seen('T')) {  // If no tool index is specified, M600 was (probably) sent in response to filament runout. |     if (!parser.seen('T')) {  // If no tool index is specified, M600 was (probably) sent in response to filament runout. | ||||||
|                               // In this case, for duplicating modes set DXC_ext to the extruder that ran out. |                               // In this case, for duplicating modes set DXC_ext to the extruder that ran out. | ||||||
|       #if HAS_FILAMENT_SENSOR && NUM_RUNOUT_SENSORS > 1 |       #if HAS_FILAMENT_SENSOR && NUM_RUNOUT_SENSORS > 1 | ||||||
|         if (dxc_is_duplicating()) |         if (idex_is_duplicating()) | ||||||
|           DXC_ext = (READ(FIL_RUNOUT2_PIN) == FIL_RUNOUT_STATE) ? 1 : 0; |           DXC_ext = (READ(FIL_RUNOUT2_PIN) == FIL_RUNOUT_STATE) ? 1 : 0; | ||||||
|       #else |       #else | ||||||
|         DXC_ext = active_extruder; |         DXC_ext = active_extruder; | ||||||
| @@ -108,7 +108,7 @@ void GcodeSuite::M600() { | |||||||
|   #if HAS_MULTI_EXTRUDER |   #if HAS_MULTI_EXTRUDER | ||||||
|     // Change toolhead if specified |     // Change toolhead if specified | ||||||
|     const uint8_t active_extruder_before_filament_change = active_extruder; |     const uint8_t active_extruder_before_filament_change = active_extruder; | ||||||
|     if (active_extruder != target_extruder && TERN1(DUAL_X_CARRIAGE, !dxc_is_duplicating())) |     if (active_extruder != target_extruder && TERN1(DUAL_X_CARRIAGE, !idex_is_duplicating())) | ||||||
|       tool_change(target_extruder, false); |       tool_change(target_extruder, false); | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -94,7 +94,7 @@ void GcodeSuite::M104() { | |||||||
|     thermalManager.setTargetHotend(temp, target_extruder); |     thermalManager.setTargetHotend(temp, target_extruder); | ||||||
|  |  | ||||||
|     #if ENABLED(DUAL_X_CARRIAGE) |     #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|       if (dxc_is_duplicating() && target_extruder == 0) |       if (idex_is_duplicating() && target_extruder == 0) | ||||||
|         thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1); |         thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1); | ||||||
|     #endif |     #endif | ||||||
|  |  | ||||||
| @@ -172,7 +172,7 @@ void GcodeSuite::M109() { | |||||||
|     thermalManager.setTargetHotend(temp, target_extruder); |     thermalManager.setTargetHotend(temp, target_extruder); | ||||||
|  |  | ||||||
|     #if ENABLED(DUAL_X_CARRIAGE) |     #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|       if (dxc_is_duplicating() && target_extruder == 0) |       if (idex_is_duplicating() && target_extruder == 0) | ||||||
|         thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1); |         thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1); | ||||||
|     #endif |     #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -62,11 +62,11 @@ const uint8_t L64XX_Marlin::index_to_dir[MAX_L64XX] = { | |||||||
|   INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR |   INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR | ||||||
|   , (INVERT_X_DIR)                            // X2 |   , (INVERT_X_DIR)                            // X2 | ||||||
|     #if ENABLED(X_DUAL_STEPPER_DRIVERS) |     #if ENABLED(X_DUAL_STEPPER_DRIVERS) | ||||||
|       ^ (INVERT_X2_VS_X_DIR) |       ^ ENABLED(INVERT_X2_VS_X_DIR) | ||||||
|     #endif |     #endif | ||||||
|   , (INVERT_Y_DIR)                            // Y2 |   , (INVERT_Y_DIR)                            // Y2 | ||||||
|     #if ENABLED(Y_DUAL_STEPPER_DRIVERS) |     #if ENABLED(Y_DUAL_STEPPER_DRIVERS) | ||||||
|       ^ (INVERT_Y2_VS_Y_DIR) |       ^ ENABLED(INVERT_Y2_VS_Y_DIR) | ||||||
|     #endif |     #endif | ||||||
|   , INVERT_Z_DIR, INVERT_Z_DIR, INVERT_Z_DIR  // Z2,Z3,Z4 |   , INVERT_Z_DIR, INVERT_Z_DIR, INVERT_Z_DIR  // Z2,Z3,Z4 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -569,7 +569,7 @@ void restore_feedrate_and_scaling() { | |||||||
|           soft_endstop.min.x = X2_MIN_POS; |           soft_endstop.min.x = X2_MIN_POS; | ||||||
|           soft_endstop.max.x = dual_max_x; |           soft_endstop.max.x = dual_max_x; | ||||||
|         } |         } | ||||||
|         else if (dxc_is_duplicating()) { |         else if (idex_is_duplicating()) { | ||||||
|           // In Duplication Mode, T0 can move as far left as X1_MIN_POS |           // In Duplication Mode, T0 can move as far left as X1_MIN_POS | ||||||
|           // but not so far to the right that T1 would move past the end |           // but not so far to the right that T1 would move past the end | ||||||
|           soft_endstop.min.x = X1_MIN_POS; |           soft_endstop.min.x = X1_MIN_POS; | ||||||
| @@ -932,8 +932,7 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { | |||||||
| #endif // !UBL_SEGMENTED | #endif // !UBL_SEGMENTED | ||||||
|  |  | ||||||
| #if HAS_DUPLICATION_MODE | #if HAS_DUPLICATION_MODE | ||||||
|   bool extruder_duplication_enabled, |   bool extruder_duplication_enabled; | ||||||
|        mirrored_duplication_mode; |  | ||||||
|   #if ENABLED(MULTI_NOZZLE_DUPLICATION) |   #if ENABLED(MULTI_NOZZLE_DUPLICATION) | ||||||
|     uint8_t duplication_e_mask; // = 0 |     uint8_t duplication_e_mask; // = 0 | ||||||
|   #endif |   #endif | ||||||
| @@ -942,12 +941,13 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { | |||||||
| #if ENABLED(DUAL_X_CARRIAGE) | #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|  |  | ||||||
|   DualXMode dual_x_carriage_mode         = DEFAULT_DUAL_X_CARRIAGE_MODE; |   DualXMode dual_x_carriage_mode         = DEFAULT_DUAL_X_CARRIAGE_MODE; | ||||||
|   float inactive_extruder_x_pos          = X2_MAX_POS,                    // used in mode 0 & 1 |   float inactive_extruder_x              = X2_MAX_POS,                    // Used in mode 0 & 1 | ||||||
|         duplicate_extruder_x_offset      = DEFAULT_DUPLICATION_X_OFFSET;  // used in mode 2 |         duplicate_extruder_x_offset      = DEFAULT_DUPLICATION_X_OFFSET;  // Used in mode 2 | ||||||
|   xyz_pos_t raised_parked_position;                                       // used in mode 1 |   xyz_pos_t raised_parked_position;                                       // Used in mode 1 | ||||||
|   bool active_extruder_parked            = false;                         // used in mode 1 & 2 |   bool active_extruder_parked            = false;                         // Used in mode 1 & 2 | ||||||
|   millis_t delayed_move_time             = 0;                             // used in mode 1 |   millis_t delayed_move_time             = 0;                             // Used in mode 1 | ||||||
|   int16_t duplicate_extruder_temp_offset = 0;                             // used in mode 2 |   int16_t duplicate_extruder_temp_offset = 0;                             // Used in mode 2 | ||||||
|  |   bool idex_mirrored_mode                = false;                         // Used in mode 3 | ||||||
|  |  | ||||||
|   float x_home_pos(const uint8_t extruder) { |   float x_home_pos(const uint8_t extruder) { | ||||||
|     if (extruder == 0) |     if (extruder == 0) | ||||||
| @@ -962,6 +962,23 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { | |||||||
|       return hotend_offset[1].x > 0 ? hotend_offset[1].x : X2_HOME_POS; |       return hotend_offset[1].x > 0 ? hotend_offset[1].x : X2_HOME_POS; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void idex_set_mirrored_mode(const bool mirr) { | ||||||
|  |     idex_mirrored_mode = mirr; | ||||||
|  |     stepper.set_directions(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void set_duplication_enabled(const bool dupe, const int8_t tool_index/*=-1*/) { | ||||||
|  |     extruder_duplication_enabled = dupe; | ||||||
|  |     if (tool_index >= 0) active_extruder = tool_index; | ||||||
|  |     stepper.set_directions(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void idex_set_parked(const bool park/*=true*/) { | ||||||
|  |     delayed_move_time = 0; | ||||||
|  |     active_extruder_parked = park; | ||||||
|  |     if (park) raised_parked_position = current_position;  // Remember current raised toolhead position for use by unpark | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Prepare a linear move in a dual X axis setup |    * Prepare a linear move in a dual X axis setup | ||||||
|    * |    * | ||||||
| @@ -970,9 +987,10 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { | |||||||
|   inline bool dual_x_carriage_unpark() { |   inline bool dual_x_carriage_unpark() { | ||||||
|     if (active_extruder_parked) { |     if (active_extruder_parked) { | ||||||
|       switch (dual_x_carriage_mode) { |       switch (dual_x_carriage_mode) { | ||||||
|         case DXC_FULL_CONTROL_MODE: |  | ||||||
|           break; |         case DXC_FULL_CONTROL_MODE: break; | ||||||
|         case DXC_AUTO_PARK_MODE: |  | ||||||
|  |         case DXC_AUTO_PARK_MODE: { | ||||||
|           if (current_position.e == destination.e) { |           if (current_position.e == destination.e) { | ||||||
|             // This is a travel move (with no extrusion) |             // This is a travel move (with no extrusion) | ||||||
|             // Skip it, but keep track of the current position |             // Skip it, but keep track of the current position | ||||||
| @@ -984,23 +1002,27 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { | |||||||
|               return true; |               return true; | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|           // unpark extruder: 1) raise, 2) move into starting XY position, 3) lower |           // | ||||||
|  |           // Un-park the active extruder | ||||||
|  |           // | ||||||
|  |           const feedRate_t fr_zfast = planner.settings.max_feedrate_mm_s[Z_AXIS]; | ||||||
|  |           #define CURPOS current_position | ||||||
|  |           #define RAISED raised_parked_position | ||||||
|  |           //  1. Move to the raised parked XYZ. Presumably the tool is already at XY. | ||||||
|  |           if (planner.buffer_line(RAISED.x, RAISED.y, RAISED.z, CURPOS.e, fr_zfast, active_extruder)) { | ||||||
|  |             //  2. Move to the current native XY and raised Z. Presumably this is a null move. | ||||||
|  |             if (planner.buffer_line(CURPOS.x, CURPOS.y, RAISED.z, CURPOS.e, PLANNER_XY_FEEDRATE(), active_extruder)) { | ||||||
|  |               //  3. Lower Z back down | ||||||
|  |               line_to_current_position(fr_zfast); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |           planner.synchronize(); // paranoia | ||||||
|  |           stepper.set_directions(); | ||||||
|  |  | ||||||
|             #define CUR_X    current_position.x |           idex_set_parked(false); | ||||||
|             #define CUR_Y    current_position.y |           if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("idex_set_parked(false)"); | ||||||
|             #define CUR_Z    current_position.z |         } break; | ||||||
|             #define CUR_E    current_position.e |  | ||||||
|             #define RAISED_X raised_parked_position.x |  | ||||||
|             #define RAISED_Y raised_parked_position.y |  | ||||||
|             #define RAISED_Z raised_parked_position.z |  | ||||||
|  |  | ||||||
|             if (  planner.buffer_line(RAISED_X, RAISED_Y, RAISED_Z, CUR_E, planner.settings.max_feedrate_mm_s[Z_AXIS], active_extruder)) |  | ||||||
|               if (planner.buffer_line(   CUR_X,    CUR_Y, RAISED_Z, CUR_E, PLANNER_XY_FEEDRATE(),             active_extruder)) |  | ||||||
|                   line_to_current_position(planner.settings.max_feedrate_mm_s[Z_AXIS]); |  | ||||||
|           delayed_move_time = 0; |  | ||||||
|           active_extruder_parked = false; |  | ||||||
|           if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Clear active_extruder_parked"); |  | ||||||
|           break; |  | ||||||
|         case DXC_MIRRORED_MODE: |         case DXC_MIRRORED_MODE: | ||||||
|         case DXC_DUPLICATION_MODE: |         case DXC_DUPLICATION_MODE: | ||||||
|           if (active_extruder == 0) { |           if (active_extruder == 0) { | ||||||
| @@ -1008,22 +1030,23 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { | |||||||
|             if (dual_x_carriage_mode == DXC_DUPLICATION_MODE) |             if (dual_x_carriage_mode == DXC_DUPLICATION_MODE) | ||||||
|               new_pos.x += duplicate_extruder_x_offset; |               new_pos.x += duplicate_extruder_x_offset; | ||||||
|             else |             else | ||||||
|               new_pos.x = inactive_extruder_x_pos; |               new_pos.x = inactive_extruder_x; | ||||||
|             // move duplicate extruder into correct duplication position. |             // Move duplicate extruder into correct duplication position. | ||||||
|             if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Set planner X", inactive_extruder_x_pos, " ... Line to X", new_pos.x); |             if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Set planner X", inactive_extruder_x, " ... Line to X", new_pos.x); | ||||||
|             planner.set_position_mm(inactive_extruder_x_pos, current_position.y, current_position.z, current_position.e); |             planner.set_position_mm(inactive_extruder_x, current_position.y, current_position.z, current_position.e); | ||||||
|             if (!planner.buffer_line(new_pos, planner.settings.max_feedrate_mm_s[X_AXIS], 1)) break; |             if (!planner.buffer_line(new_pos, planner.settings.max_feedrate_mm_s[X_AXIS], 1)) break; | ||||||
|  |  | ||||||
|             planner.synchronize(); |             planner.synchronize(); | ||||||
|             sync_plan_position(); |             sync_plan_position(); | ||||||
|             extruder_duplication_enabled = true; |  | ||||||
|             active_extruder_parked = false; |             set_duplication_enabled(true); | ||||||
|             if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Set extruder_duplication_enabled\nClear active_extruder_parked"); |             idex_set_parked(false); | ||||||
|  |             if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("set_duplication_enabled(true)\nidex_set_parked(false)"); | ||||||
|           } |           } | ||||||
|           else if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Active extruder not 0"); |           else if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Active extruder not 0"); | ||||||
|           break; |           break; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     stepper.set_directions(); |  | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -384,8 +384,7 @@ bool homing_needed_error(uint8_t axis_bits=0x07); | |||||||
|  * Duplication mode |  * Duplication mode | ||||||
|  */ |  */ | ||||||
| #if HAS_DUPLICATION_MODE | #if HAS_DUPLICATION_MODE | ||||||
|   extern bool extruder_duplication_enabled,       // Used in Dual X mode 2 |   extern bool extruder_duplication_enabled;       // Used in Dual X mode 2 | ||||||
|               mirrored_duplication_mode;          // Used in Dual X mode 3 |  | ||||||
|   #if ENABLED(MULTI_NOZZLE_DUPLICATION) |   #if ENABLED(MULTI_NOZZLE_DUPLICATION) | ||||||
|     extern uint8_t duplication_e_mask; |     extern uint8_t duplication_e_mask; | ||||||
|   #endif |   #endif | ||||||
| @@ -404,23 +403,29 @@ bool homing_needed_error(uint8_t axis_bits=0x07); | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   extern DualXMode dual_x_carriage_mode; |   extern DualXMode dual_x_carriage_mode; | ||||||
|   extern float inactive_extruder_x_pos,           // Used in mode 0 & 1 |   extern float inactive_extruder_x,               // Used in mode 0 & 1 | ||||||
|                duplicate_extruder_x_offset;       // Used in mode 2 & 3 |                duplicate_extruder_x_offset;       // Used in mode 2 & 3 | ||||||
|   extern xyz_pos_t raised_parked_position;        // Used in mode 1 |   extern xyz_pos_t raised_parked_position;        // Used in mode 1 | ||||||
|   extern bool active_extruder_parked;             // Used in mode 1, 2 & 3 |   extern bool active_extruder_parked;             // Used in mode 1, 2 & 3 | ||||||
|   extern millis_t delayed_move_time;              // Used in mode 1 |   extern millis_t delayed_move_time;              // Used in mode 1 | ||||||
|   extern int16_t duplicate_extruder_temp_offset;  // Used in mode 2 & 3 |   extern int16_t duplicate_extruder_temp_offset;  // Used in mode 2 & 3 | ||||||
|  |   extern bool idex_mirrored_mode;                 // Used in mode 3 | ||||||
|  |  | ||||||
|   FORCE_INLINE bool dxc_is_duplicating() { return dual_x_carriage_mode >= DXC_DUPLICATION_MODE; } |   FORCE_INLINE bool idex_is_duplicating() { return dual_x_carriage_mode >= DXC_DUPLICATION_MODE; } | ||||||
|  |  | ||||||
|   float x_home_pos(const uint8_t extruder); |   float x_home_pos(const uint8_t extruder); | ||||||
|  |  | ||||||
|   FORCE_INLINE int x_home_dir(const uint8_t extruder) { return extruder ? X2_HOME_DIR : X_HOME_DIR; } |   FORCE_INLINE int x_home_dir(const uint8_t extruder) { return extruder ? X2_HOME_DIR : X_HOME_DIR; } | ||||||
|  |  | ||||||
|  |   void set_duplication_enabled(const bool dupe, const int8_t tool_index=-1); | ||||||
|  |   void idex_set_mirrored_mode(const bool mirr); | ||||||
|  |   void idex_set_parked(const bool park=true); | ||||||
|  |  | ||||||
| #else | #else | ||||||
|  |  | ||||||
|   #if ENABLED(MULTI_NOZZLE_DUPLICATION) |   #if ENABLED(MULTI_NOZZLE_DUPLICATION) | ||||||
|     enum DualXMode : char { DXC_DUPLICATION_MODE = 2 }; |     enum DualXMode : char { DXC_DUPLICATION_MODE = 2 }; | ||||||
|  |     FORCE_INLINE void set_duplication_enabled(const bool dupe) { extruder_duplication_enabled = dupe; } | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   FORCE_INLINE int x_home_dir(const uint8_t) { return home_dir(X_AXIS); } |   FORCE_INLINE int x_home_dir(const uint8_t) { return home_dir(X_AXIS); } | ||||||
|   | |||||||
| @@ -348,7 +348,7 @@ xyze_int8_t Stepper::count_direction{0}; | |||||||
|   } |   } | ||||||
|  |  | ||||||
| #if ENABLED(X_DUAL_STEPPER_DRIVERS) | #if ENABLED(X_DUAL_STEPPER_DRIVERS) | ||||||
|   #define X_APPLY_DIR(v,Q) do{ X_DIR_WRITE(v); X2_DIR_WRITE((v) != INVERT_X2_VS_X_DIR); }while(0) |   #define X_APPLY_DIR(v,Q) do{ X_DIR_WRITE(v); X2_DIR_WRITE((v) ^ ENABLED(INVERT_X2_VS_X_DIR)); }while(0) | ||||||
|   #if ENABLED(X_DUAL_ENDSTOPS) |   #if ENABLED(X_DUAL_ENDSTOPS) | ||||||
|     #define X_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(X,v) |     #define X_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(X,v) | ||||||
|   #else |   #else | ||||||
| @@ -356,7 +356,7 @@ xyze_int8_t Stepper::count_direction{0}; | |||||||
|   #endif |   #endif | ||||||
| #elif ENABLED(DUAL_X_CARRIAGE) | #elif ENABLED(DUAL_X_CARRIAGE) | ||||||
|   #define X_APPLY_DIR(v,ALWAYS) do{ \ |   #define X_APPLY_DIR(v,ALWAYS) do{ \ | ||||||
|     if (extruder_duplication_enabled || ALWAYS) { X_DIR_WRITE(v); X2_DIR_WRITE(mirrored_duplication_mode ? !(v) : v); } \ |     if (extruder_duplication_enabled || ALWAYS) { X_DIR_WRITE(v); X2_DIR_WRITE((v) ^ idex_mirrored_mode); } \ | ||||||
|     else if (last_moved_extruder) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \ |     else if (last_moved_extruder) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \ | ||||||
|   }while(0) |   }while(0) | ||||||
|   #define X_APPLY_STEP(v,ALWAYS) do{ \ |   #define X_APPLY_STEP(v,ALWAYS) do{ \ | ||||||
| @@ -369,7 +369,7 @@ xyze_int8_t Stepper::count_direction{0}; | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if ENABLED(Y_DUAL_STEPPER_DRIVERS) | #if ENABLED(Y_DUAL_STEPPER_DRIVERS) | ||||||
|   #define Y_APPLY_DIR(v,Q) do{ Y_DIR_WRITE(v); Y2_DIR_WRITE((v) != INVERT_Y2_VS_Y_DIR); }while(0) |   #define Y_APPLY_DIR(v,Q) do{ Y_DIR_WRITE(v); Y2_DIR_WRITE((v) ^ ENABLED(INVERT_Y2_VS_Y_DIR)); }while(0) | ||||||
|   #if ENABLED(Y_DUAL_ENDSTOPS) |   #if ENABLED(Y_DUAL_ENDSTOPS) | ||||||
|     #define Y_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Y,v) |     #define Y_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Y,v) | ||||||
|   #else |   #else | ||||||
| @@ -1605,10 +1605,9 @@ void Stepper::pulse_phase_isr() { | |||||||
|               PAGE_SEGMENT_UPDATE(Z, high >> 4); |               PAGE_SEGMENT_UPDATE(Z, high >> 4); | ||||||
|               PAGE_SEGMENT_UPDATE(E, high & 0xF); |               PAGE_SEGMENT_UPDATE(E, high & 0xF); | ||||||
|  |  | ||||||
|               if (dm != last_direction_bits) { |               if (dm != last_direction_bits) | ||||||
|                 last_direction_bits = dm; |                 set_directions(dm); | ||||||
|                 set_directions(); |  | ||||||
|               } |  | ||||||
|             } break; |             } break; | ||||||
|  |  | ||||||
|             default: break; |             default: break; | ||||||
| @@ -2131,9 +2130,7 @@ uint32_t Stepper::block_phase_isr() { | |||||||
|         MIXER_STEPPER_SETUP(); |         MIXER_STEPPER_SETUP(); | ||||||
|       #endif |       #endif | ||||||
|  |  | ||||||
|       #if HAS_MULTI_EXTRUDER |       TERN_(HAS_MULTI_EXTRUDER, stepper_extruder = current_block->extruder); | ||||||
|         stepper_extruder = current_block->extruder; |  | ||||||
|       #endif |  | ||||||
|  |  | ||||||
|       // Initialize the trapezoid generator from the current block. |       // Initialize the trapezoid generator from the current block. | ||||||
|       #if ENABLED(LIN_ADVANCE) |       #if ENABLED(LIN_ADVANCE) | ||||||
| @@ -2152,16 +2149,13 @@ uint32_t Stepper::block_phase_isr() { | |||||||
|       #endif |       #endif | ||||||
|  |  | ||||||
|       if ( ENABLED(HAS_L64XX)       // Always set direction for L64xx (Also enables the chips) |       if ( ENABLED(HAS_L64XX)       // Always set direction for L64xx (Also enables the chips) | ||||||
|  |         || ENABLED(DUAL_X_CARRIAGE) // TODO: Find out why this fixes "jittery" small circles | ||||||
|         || current_block->direction_bits != last_direction_bits |         || current_block->direction_bits != last_direction_bits | ||||||
|         || TERN(MIXING_EXTRUDER, false, stepper_extruder != last_moved_extruder) |         || TERN(MIXING_EXTRUDER, false, stepper_extruder != last_moved_extruder) | ||||||
|       ) { |       ) { | ||||||
|         last_direction_bits = current_block->direction_bits; |         TERN_(HAS_MULTI_EXTRUDER, last_moved_extruder = stepper_extruder); | ||||||
|         #if HAS_MULTI_EXTRUDER |  | ||||||
|           last_moved_extruder = stepper_extruder; |  | ||||||
|         #endif |  | ||||||
|  |  | ||||||
|         TERN_(HAS_L64XX, L64XX_OK_to_power_up = true); |         TERN_(HAS_L64XX, L64XX_OK_to_power_up = true); | ||||||
|         set_directions(); |         set_directions(current_block->direction_bits); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       #if ENABLED(LASER_POWER_INLINE) |       #if ENABLED(LASER_POWER_INLINE) | ||||||
| @@ -2583,12 +2577,9 @@ void Stepper::init() { | |||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   // Init direction bits for first moves |   // Init direction bits for first moves | ||||||
|   last_direction_bits = 0 |   set_directions((INVERT_X_DIR ? _BV(X_AXIS) : 0) | ||||||
|     | (INVERT_X_DIR ? _BV(X_AXIS) : 0) |  | ||||||
|                | (INVERT_Y_DIR ? _BV(Y_AXIS) : 0) |                | (INVERT_Y_DIR ? _BV(Y_AXIS) : 0) | ||||||
|     | (INVERT_Z_DIR ? _BV(Z_AXIS) : 0); |                | (INVERT_Z_DIR ? _BV(Z_AXIS) : 0)); | ||||||
|  |  | ||||||
|   set_directions(); |  | ||||||
|  |  | ||||||
|   #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM |   #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||||
|     initialized = true; |     initialized = true; | ||||||
|   | |||||||
| @@ -514,9 +514,15 @@ class Stepper { | |||||||
|       static void refresh_motor_power(); |       static void refresh_motor_power(); | ||||||
|     #endif |     #endif | ||||||
|  |  | ||||||
|     // Set direction bits for all steppers |     // Update direction states for all steppers | ||||||
|     static void set_directions(); |     static void set_directions(); | ||||||
|  |  | ||||||
|  |     // Set direction bits and update all stepper DIR states | ||||||
|  |     static void set_directions(const uint8_t bits) { | ||||||
|  |       last_direction_bits = bits; | ||||||
|  |       set_directions(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|   private: |   private: | ||||||
|  |  | ||||||
|     // Set the current position in steps |     // Set the current position in steps | ||||||
|   | |||||||
| @@ -61,6 +61,10 @@ | |||||||
|   #include "../gcode/gcode.h" |   #include "../gcode/gcode.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|  |   #include "stepper.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #if ANY(SWITCHING_EXTRUDER, SWITCHING_NOZZLE, SWITCHING_TOOLHEAD) | #if ANY(SWITCHING_EXTRUDER, SWITCHING_NOZZLE, SWITCHING_TOOLHEAD) | ||||||
|   #include "servo.h" |   #include "servo.h" | ||||||
| #endif | #endif | ||||||
| @@ -701,6 +705,13 @@ inline void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_a | |||||||
|  |  | ||||||
| #if ENABLED(DUAL_X_CARRIAGE) | #if ENABLED(DUAL_X_CARRIAGE) | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * @brief Dual X Tool Change | ||||||
|  |    * @details Change tools, with extra behavior based on current mode | ||||||
|  |    * | ||||||
|  |    * @param new_tool Tool index to activate | ||||||
|  |    * @param no_move Flag indicating no moves should take place | ||||||
|  |    */ | ||||||
|   inline void dualx_tool_change(const uint8_t new_tool, bool &no_move) { |   inline void dualx_tool_change(const uint8_t new_tool, bool &no_move) { | ||||||
|  |  | ||||||
|     DEBUG_ECHOPGM("Dual X Carriage Mode "); |     DEBUG_ECHOPGM("Dual X Carriage Mode "); | ||||||
| @@ -711,17 +722,16 @@ inline void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_a | |||||||
|       case DXC_MIRRORED_MODE:     DEBUG_ECHOLNPGM("MIRRORED");     break; |       case DXC_MIRRORED_MODE:     DEBUG_ECHOLNPGM("MIRRORED");     break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Get the home position of the currently-active tool | ||||||
|     const float xhome = x_home_pos(active_extruder); |     const float xhome = x_home_pos(active_extruder); | ||||||
|     if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE |  | ||||||
|         && IsRunning() && !no_move |     if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE                  // If Auto-Park mode is enabled | ||||||
|         && (delayed_move_time || current_position.x != xhome) |         && IsRunning() && !no_move                                  // ...and movement is permitted | ||||||
|  |         && (delayed_move_time || current_position.x != xhome)       // ...and delayed_move_time is set OR not "already parked"... | ||||||
|     ) { |     ) { | ||||||
|  |  | ||||||
|       DEBUG_ECHOLNPAIR("MoveX to ", xhome); |       DEBUG_ECHOLNPAIR("MoveX to ", xhome); | ||||||
|  |  | ||||||
|       // Park old head |  | ||||||
|       current_position.x = xhome; |       current_position.x = xhome; | ||||||
|       line_to_current_position(planner.settings.max_feedrate_mm_s[X_AXIS]); |       line_to_current_position(planner.settings.max_feedrate_mm_s[X_AXIS]);   // Park the current head | ||||||
|       planner.synchronize(); |       planner.synchronize(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -736,20 +746,21 @@ inline void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_a | |||||||
|     switch (dual_x_carriage_mode) { |     switch (dual_x_carriage_mode) { | ||||||
|       case DXC_FULL_CONTROL_MODE: |       case DXC_FULL_CONTROL_MODE: | ||||||
|         // New current position is the position of the activated extruder |         // New current position is the position of the activated extruder | ||||||
|         current_position.x = inactive_extruder_x_pos; |         current_position.x = inactive_extruder_x; | ||||||
|         // Save the inactive extruder's position (from the old current_position) |         // Save the inactive extruder's position (from the old current_position) | ||||||
|         inactive_extruder_x_pos = destination.x; |         inactive_extruder_x = destination.x; | ||||||
|  |         DEBUG_ECHOLNPAIR("DXC Full Control curr.x=", current_position.x, " dest.x=", destination.x); | ||||||
|         break; |         break; | ||||||
|       case DXC_AUTO_PARK_MODE: |       case DXC_AUTO_PARK_MODE: | ||||||
|         // record current raised toolhead position for use by unpark |         idex_set_parked(); | ||||||
|         raised_parked_position = current_position; |  | ||||||
|         active_extruder_parked = true; |  | ||||||
|         delayed_move_time = 0; |  | ||||||
|         break; |         break; | ||||||
|       default: |       default: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Ensure X axis DIR pertains to the correct carriage | ||||||
|  |     stepper.set_directions(); | ||||||
|  |  | ||||||
|     DEBUG_ECHOLNPAIR("Active extruder parked: ", active_extruder_parked ? "yes" : "no"); |     DEBUG_ECHOLNPAIR("Active extruder parked: ", active_extruder_parked ? "yes" : "no"); | ||||||
|     DEBUG_POS("New extruder (parked)", current_position); |     DEBUG_POS("New extruder (parked)", current_position); | ||||||
|   } |   } | ||||||
| @@ -875,7 +886,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { | |||||||
|     planner.synchronize(); |     planner.synchronize(); | ||||||
|  |  | ||||||
|     #if ENABLED(DUAL_X_CARRIAGE)  // Only T0 allowed if the Printer is in DXC_DUPLICATION_MODE or DXC_MIRRORED_MODE |     #if ENABLED(DUAL_X_CARRIAGE)  // Only T0 allowed if the Printer is in DXC_DUPLICATION_MODE or DXC_MIRRORED_MODE | ||||||
|       if (new_tool != 0 && dxc_is_duplicating()) |       if (new_tool != 0 && idex_is_duplicating()) | ||||||
|          return invalid_extruder_error(new_tool); |          return invalid_extruder_error(new_tool); | ||||||
|     #endif |     #endif | ||||||
|  |  | ||||||
| @@ -1151,7 +1162,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { | |||||||
|           } |           } | ||||||
|         #endif |         #endif | ||||||
|  |  | ||||||
|         TERN_(DUAL_X_CARRIAGE, active_extruder_parked = false); |         TERN_(DUAL_X_CARRIAGE, idex_set_parked(false)); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       #if ENABLED(SWITCHING_NOZZLE) |       #if ENABLED(SWITCHING_NOZZLE) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user