My Marlin configs for Fabrikator Mini and CTC i3 Pro B
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

motion.h 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #pragma once
  23. /**
  24. * motion.h
  25. *
  26. * High-level motion commands to feed the planner
  27. * Some of these methods may migrate to the planner class.
  28. */
  29. #include "../inc/MarlinConfig.h"
  30. #if IS_SCARA
  31. #include "scara.h"
  32. #endif
  33. // Error margin to work around float imprecision
  34. constexpr float fslop = 0.0001;
  35. extern bool relative_mode;
  36. extern xyze_pos_t current_position, // High-level current tool position
  37. destination; // Destination for a move
  38. // G60/G61 Position Save and Return
  39. #if SAVED_POSITIONS
  40. extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for HAS_I_AXIS
  41. extern xyze_pos_t stored_position[SAVED_POSITIONS];
  42. #endif
  43. // Scratch space for a cartesian result
  44. extern xyz_pos_t cartes;
  45. // Until kinematics.cpp is created, declare this here
  46. #if IS_KINEMATIC
  47. extern abce_pos_t delta;
  48. #endif
  49. #if HAS_ABL_NOT_UBL
  50. extern feedRate_t xy_probe_feedrate_mm_s;
  51. #define XY_PROBE_FEEDRATE_MM_S xy_probe_feedrate_mm_s
  52. #elif defined(XY_PROBE_FEEDRATE)
  53. #define XY_PROBE_FEEDRATE_MM_S MMM_TO_MMS(XY_PROBE_FEEDRATE)
  54. #else
  55. #define XY_PROBE_FEEDRATE_MM_S PLANNER_XY_FEEDRATE()
  56. #endif
  57. #if HAS_BED_PROBE
  58. constexpr feedRate_t z_probe_fast_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_FAST);
  59. #endif
  60. /**
  61. * Feed rates are often configured with mm/m
  62. * but the planner and stepper like mm/s units.
  63. */
  64. constexpr xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M;
  65. FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) {
  66. float v = TERN0(HAS_Z_AXIS, homing_feedrate_mm_m.z);
  67. #if DISABLED(DELTA)
  68. NUM_AXIS_CODE(
  69. if (a == X_AXIS) v = homing_feedrate_mm_m.x,
  70. else if (a == Y_AXIS) v = homing_feedrate_mm_m.y,
  71. else if (a == Z_AXIS) v = homing_feedrate_mm_m.z,
  72. else if (a == I_AXIS) v = homing_feedrate_mm_m.i,
  73. else if (a == J_AXIS) v = homing_feedrate_mm_m.j,
  74. else if (a == K_AXIS) v = homing_feedrate_mm_m.k,
  75. else if (a == U_AXIS) v = homing_feedrate_mm_m.u,
  76. else if (a == V_AXIS) v = homing_feedrate_mm_m.v,
  77. else if (a == W_AXIS) v = homing_feedrate_mm_m.w
  78. );
  79. #endif
  80. return MMM_TO_MMS(v);
  81. }
  82. feedRate_t get_homing_bump_feedrate(const AxisEnum axis);
  83. /**
  84. * The default feedrate for many moves, set by the most recent move
  85. */
  86. extern feedRate_t feedrate_mm_s;
  87. /**
  88. * Feedrate scaling is applied to all G0/G1, G2/G3, and G5 moves
  89. */
  90. extern int16_t feedrate_percentage;
  91. #define MMS_SCALED(V) ((V) * 0.01f * feedrate_percentage)
  92. // The active extruder (tool). Set with T<extruder> command.
  93. #if HAS_MULTI_EXTRUDER
  94. extern uint8_t active_extruder;
  95. #else
  96. constexpr uint8_t active_extruder = 0;
  97. #endif
  98. #if ENABLED(LCD_SHOW_E_TOTAL)
  99. extern float e_move_accumulator;
  100. #endif
  101. #ifdef __IMXRT1062__
  102. #define DEFS_PROGMEM
  103. #else
  104. #define DEFS_PROGMEM PROGMEM
  105. #endif
  106. inline float pgm_read_any(const float *p) { return TERN(__IMXRT1062__, *p, pgm_read_float(p)); }
  107. inline int8_t pgm_read_any(const int8_t *p) { return TERN(__IMXRT1062__, *p, pgm_read_byte(p)); }
  108. #define XYZ_DEFS(T, NAME, OPT) \
  109. inline T NAME(const AxisEnum axis) { \
  110. static const XYZval<T> NAME##_P DEFS_PROGMEM = NUM_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT, U_##OPT, V_##OPT, W_##OPT); \
  111. return pgm_read_any(&NAME##_P[axis]); \
  112. }
  113. XYZ_DEFS(float, base_min_pos, MIN_POS);
  114. XYZ_DEFS(float, base_max_pos, MAX_POS);
  115. XYZ_DEFS(float, base_home_pos, HOME_POS);
  116. XYZ_DEFS(float, max_length, MAX_LENGTH);
  117. XYZ_DEFS(int8_t, home_dir, HOME_DIR);
  118. inline float home_bump_mm(const AxisEnum axis) {
  119. static const xyz_pos_t home_bump_mm_P DEFS_PROGMEM = HOMING_BUMP_MM;
  120. return pgm_read_any(&home_bump_mm_P[axis]);
  121. }
  122. #if HAS_WORKSPACE_OFFSET
  123. void update_workspace_offset(const AxisEnum axis);
  124. #else
  125. inline void update_workspace_offset(const AxisEnum) {}
  126. #endif
  127. #if HAS_HOTEND_OFFSET
  128. extern xyz_pos_t hotend_offset[HOTENDS];
  129. void reset_hotend_offsets();
  130. #elif HOTENDS
  131. constexpr xyz_pos_t hotend_offset[HOTENDS] = { { 0 } };
  132. #else
  133. constexpr xyz_pos_t hotend_offset[1] = { { 0 } };
  134. #endif
  135. #if HAS_SOFTWARE_ENDSTOPS
  136. typedef struct {
  137. bool _enabled, _loose;
  138. bool enabled() { return _enabled && !_loose; }
  139. xyz_pos_t min, max;
  140. void get_manual_axis_limits(const AxisEnum axis, float &amin, float &amax) {
  141. amin = -100000; amax = 100000; // "No limits"
  142. #if HAS_SOFTWARE_ENDSTOPS
  143. if (enabled()) switch (axis) {
  144. case X_AXIS:
  145. TERN_(MIN_SOFTWARE_ENDSTOP_X, amin = min.x);
  146. TERN_(MAX_SOFTWARE_ENDSTOP_X, amax = max.x);
  147. break;
  148. #if HAS_Y_AXIS
  149. case Y_AXIS:
  150. TERN_(MIN_SOFTWARE_ENDSTOP_Y, amin = min.y);
  151. TERN_(MAX_SOFTWARE_ENDSTOP_Y, amax = max.y);
  152. break;
  153. #endif
  154. #if HAS_Z_AXIS
  155. case Z_AXIS:
  156. TERN_(MIN_SOFTWARE_ENDSTOP_Z, amin = min.z);
  157. TERN_(MAX_SOFTWARE_ENDSTOP_Z, amax = max.z);
  158. break;
  159. #endif
  160. #if HAS_I_AXIS
  161. case I_AXIS:
  162. TERN_(MIN_SOFTWARE_ENDSTOP_I, amin = min.i);
  163. TERN_(MIN_SOFTWARE_ENDSTOP_I, amax = max.i);
  164. break;
  165. #endif
  166. #if HAS_J_AXIS
  167. case J_AXIS:
  168. TERN_(MIN_SOFTWARE_ENDSTOP_J, amin = min.j);
  169. TERN_(MIN_SOFTWARE_ENDSTOP_J, amax = max.j);
  170. break;
  171. #endif
  172. #if HAS_K_AXIS
  173. case K_AXIS:
  174. TERN_(MIN_SOFTWARE_ENDSTOP_K, amin = min.k);
  175. TERN_(MIN_SOFTWARE_ENDSTOP_K, amax = max.k);
  176. break;
  177. #endif
  178. #if HAS_U_AXIS
  179. case U_AXIS:
  180. TERN_(MIN_SOFTWARE_ENDSTOP_U, amin = min.u);
  181. TERN_(MIN_SOFTWARE_ENDSTOP_U, amax = max.u);
  182. break;
  183. #endif
  184. #if HAS_V_AXIS
  185. case V_AXIS:
  186. TERN_(MIN_SOFTWARE_ENDSTOP_V, amin = min.v);
  187. TERN_(MIN_SOFTWARE_ENDSTOP_V, amax = max.v);
  188. break;
  189. #endif
  190. #if HAS_W_AXIS
  191. case W_AXIS:
  192. TERN_(MIN_SOFTWARE_ENDSTOP_W, amin = min.w);
  193. TERN_(MIN_SOFTWARE_ENDSTOP_W, amax = max.w);
  194. break;
  195. #endif
  196. default: break;
  197. }
  198. #endif
  199. }
  200. } soft_endstops_t;
  201. extern soft_endstops_t soft_endstop;
  202. void apply_motion_limits(xyz_pos_t &target);
  203. void update_software_endstops(const AxisEnum axis
  204. #if HAS_HOTEND_OFFSET
  205. , const uint8_t old_tool_index=0, const uint8_t new_tool_index=0
  206. #endif
  207. );
  208. #define SET_SOFT_ENDSTOP_LOOSE(loose) (soft_endstop._loose = loose)
  209. #else // !HAS_SOFTWARE_ENDSTOPS
  210. typedef struct {
  211. bool enabled() { return false; }
  212. void get_manual_axis_limits(const AxisEnum axis, float &amin, float &amax) {
  213. // No limits
  214. amin = current_position[axis] - 1000;
  215. amax = current_position[axis] + 1000;
  216. }
  217. } soft_endstops_t;
  218. extern soft_endstops_t soft_endstop;
  219. #define apply_motion_limits(V) NOOP
  220. #define update_software_endstops(...) NOOP
  221. #define SET_SOFT_ENDSTOP_LOOSE(V) NOOP
  222. #endif // !HAS_SOFTWARE_ENDSTOPS
  223. void report_real_position();
  224. void report_current_position();
  225. void report_current_position_projected();
  226. #if ENABLED(AUTO_REPORT_POSITION)
  227. #include "../libs/autoreport.h"
  228. struct PositionReport { static void report() { report_current_position_projected(); } };
  229. extern AutoReporter<PositionReport> position_auto_reporter;
  230. #endif
  231. #if EITHER(FULL_REPORT_TO_HOST_FEATURE, REALTIME_REPORTING_COMMANDS)
  232. #define HAS_GRBL_STATE 1
  233. /**
  234. * Machine states for GRBL or TinyG
  235. */
  236. enum M_StateEnum : uint8_t {
  237. M_INIT = 0, // 0 machine is initializing
  238. M_RESET, // 1 machine is ready for use
  239. M_ALARM, // 2 machine is in alarm state (soft shut down)
  240. M_IDLE, // 3 program stop or no more blocks (M0, M1, M60)
  241. M_END, // 4 program end via M2, M30
  242. M_RUNNING, // 5 motion is running
  243. M_HOLD, // 6 motion is holding
  244. M_PROBE, // 7 probe cycle active
  245. M_CYCLING, // 8 machine is running (cycling)
  246. M_HOMING, // 9 machine is homing
  247. M_JOGGING, // 10 machine is jogging
  248. M_ERROR // 11 machine is in hard alarm state (shut down)
  249. };
  250. extern M_StateEnum M_State_grbl;
  251. M_StateEnum grbl_state_for_marlin_state();
  252. void report_current_grblstate_moving();
  253. void report_current_position_moving();
  254. #if ENABLED(FULL_REPORT_TO_HOST_FEATURE)
  255. inline void set_and_report_grblstate(const M_StateEnum state, const bool force=true) {
  256. if (force || M_State_grbl != state) {
  257. M_State_grbl = state;
  258. report_current_grblstate_moving();
  259. }
  260. }
  261. #endif
  262. #if ENABLED(REALTIME_REPORTING_COMMANDS)
  263. void quickpause_stepper();
  264. void quickresume_stepper();
  265. #endif
  266. #endif
  267. void get_cartesian_from_steppers();
  268. void set_current_from_steppers_for_axis(const AxisEnum axis);
  269. void quickstop_stepper();
  270. /**
  271. * Set the planner/stepper positions directly from current_position with
  272. * no kinematic translation. Used for homing axes and cartesian/core syncing.
  273. */
  274. void sync_plan_position();
  275. #if HAS_EXTRUDERS
  276. void sync_plan_position_e();
  277. #endif
  278. /**
  279. * Move the planner to the current position from wherever it last moved
  280. * (or from wherever it has been told it is located).
  281. */
  282. void line_to_current_position(const_feedRate_t fr_mm_s=feedrate_mm_s);
  283. #if HAS_EXTRUDERS
  284. void unscaled_e_move(const_float_t length, const_feedRate_t fr_mm_s);
  285. #endif
  286. void prepare_line_to_destination();
  287. void _internal_move_to_destination(const_feedRate_t fr_mm_s=0.0f OPTARG(IS_KINEMATIC, const bool is_fast=false));
  288. inline void prepare_internal_move_to_destination(const_feedRate_t fr_mm_s=0.0f) {
  289. _internal_move_to_destination(fr_mm_s);
  290. }
  291. #if IS_KINEMATIC
  292. void prepare_fast_move_to_destination(const_feedRate_t scaled_fr_mm_s=MMS_SCALED(feedrate_mm_s));
  293. inline void prepare_internal_fast_move_to_destination(const_feedRate_t fr_mm_s=0.0f) {
  294. _internal_move_to_destination(fr_mm_s, true);
  295. }
  296. #endif
  297. /**
  298. * Blocking movement and shorthand functions
  299. */
  300. void do_blocking_move_to(NUM_AXIS_ARGS(const float), const_feedRate_t fr_mm_s=0.0f);
  301. void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
  302. void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
  303. void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
  304. void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s=0.0f);
  305. #if HAS_Y_AXIS
  306. void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s=0.0f);
  307. #endif
  308. #if HAS_Z_AXIS
  309. void do_blocking_move_to_z(const_float_t rz, const_feedRate_t fr_mm_s=0.0f);
  310. #endif
  311. #if HAS_I_AXIS
  312. void do_blocking_move_to_i(const_float_t ri, const_feedRate_t fr_mm_s=0.0f);
  313. void do_blocking_move_to_xyz_i(const xyze_pos_t &raw, const_float_t i, const_feedRate_t fr_mm_s=0.0f);
  314. #endif
  315. #if HAS_J_AXIS
  316. void do_blocking_move_to_j(const_float_t rj, const_feedRate_t fr_mm_s=0.0f);
  317. void do_blocking_move_to_xyzi_j(const xyze_pos_t &raw, const_float_t j, const_feedRate_t fr_mm_s=0.0f);
  318. #endif
  319. #if HAS_K_AXIS
  320. void do_blocking_move_to_k(const_float_t rk, const_feedRate_t fr_mm_s=0.0f);
  321. void do_blocking_move_to_xyzij_k(const xyze_pos_t &raw, const_float_t k, const_feedRate_t fr_mm_s=0.0f);
  322. #endif
  323. #if HAS_U_AXIS
  324. void do_blocking_move_to_u(const_float_t ru, const_feedRate_t fr_mm_s=0.0f);
  325. void do_blocking_move_to_xyzijk_u(const xyze_pos_t &raw, const_float_t u, const_feedRate_t fr_mm_s=0.0f);
  326. #endif
  327. #if HAS_V_AXIS
  328. void do_blocking_move_to_v(const_float_t rv, const_feedRate_t fr_mm_s=0.0f);
  329. void do_blocking_move_to_xyzijku_v(const xyze_pos_t &raw, const_float_t v, const_feedRate_t fr_mm_s=0.0f);
  330. #endif
  331. #if HAS_W_AXIS
  332. void do_blocking_move_to_w(const float rw, const feedRate_t &fr_mm_s=0.0f);
  333. void do_blocking_move_to_xyzijkuv_w(const xyze_pos_t &raw, const float w, const feedRate_t &fr_mm_s=0.0f);
  334. #endif
  335. #if HAS_Y_AXIS
  336. void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s=0.0f);
  337. void do_blocking_move_to_xy(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
  338. FORCE_INLINE void do_blocking_move_to_xy(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
  339. FORCE_INLINE void do_blocking_move_to_xy(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
  340. #endif
  341. #if HAS_Z_AXIS
  342. void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f);
  343. FORCE_INLINE void do_blocking_move_to_xy_z(const xyz_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
  344. FORCE_INLINE void do_blocking_move_to_xy_z(const xyze_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
  345. #endif
  346. void remember_feedrate_and_scaling();
  347. void remember_feedrate_scaling_off();
  348. void restore_feedrate_and_scaling();
  349. #if HAS_Z_AXIS
  350. void do_z_clearance(const_float_t zclear, const bool lower_allowed=false);
  351. #else
  352. inline void do_z_clearance(float, bool=false) {}
  353. #endif
  354. /**
  355. * Homing and Trusted Axes
  356. */
  357. typedef IF<(NUM_AXES > 8), uint16_t, uint8_t>::type main_axes_bits_t;
  358. constexpr main_axes_bits_t main_axes_mask = _BV(NUM_AXES) - 1;
  359. typedef IF<(NUM_AXES + EXTRUDERS > 8), uint16_t, uint8_t>::type e_axis_bits_t;
  360. constexpr e_axis_bits_t e_axis_mask = (_BV(EXTRUDERS) - 1) << NUM_AXES;
  361. void set_axis_is_at_home(const AxisEnum axis);
  362. #if HAS_ENDSTOPS
  363. /**
  364. * axes_homed
  365. * Flags that each linear axis was homed.
  366. * XYZ on cartesian, ABC on delta, ABZ on SCARA.
  367. *
  368. * axes_trusted
  369. * Flags that the position is trusted in each linear axis. Set when homed.
  370. * Cleared whenever a stepper powers off, potentially losing its position.
  371. */
  372. extern main_axes_bits_t axes_homed, axes_trusted;
  373. void homeaxis(const AxisEnum axis);
  374. void set_axis_never_homed(const AxisEnum axis);
  375. main_axes_bits_t axes_should_home(main_axes_bits_t axes_mask=main_axes_mask);
  376. bool homing_needed_error(main_axes_bits_t axes_mask=main_axes_mask);
  377. inline void set_axis_unhomed(const AxisEnum axis) { CBI(axes_homed, axis); }
  378. inline void set_axis_untrusted(const AxisEnum axis) { CBI(axes_trusted, axis); }
  379. inline void set_all_unhomed() { axes_homed = axes_trusted = 0; }
  380. inline void set_axis_homed(const AxisEnum axis) { SBI(axes_homed, axis); }
  381. inline void set_axis_trusted(const AxisEnum axis) { SBI(axes_trusted, axis); }
  382. inline void set_all_homed() { axes_homed = axes_trusted = main_axes_mask; }
  383. #else
  384. constexpr main_axes_bits_t axes_homed = main_axes_mask, axes_trusted = main_axes_mask; // Zero-endstop machines are always homed and trusted
  385. inline void homeaxis(const AxisEnum axis) {}
  386. inline void set_axis_never_homed(const AxisEnum) {}
  387. inline main_axes_bits_t axes_should_home(main_axes_bits_t=main_axes_mask) { return 0; }
  388. inline bool homing_needed_error(main_axes_bits_t=main_axes_mask) { return false; }
  389. inline void set_axis_unhomed(const AxisEnum axis) {}
  390. inline void set_axis_untrusted(const AxisEnum axis) {}
  391. inline void set_all_unhomed() {}
  392. inline void set_axis_homed(const AxisEnum axis) {}
  393. inline void set_axis_trusted(const AxisEnum axis) {}
  394. inline void set_all_homed() {}
  395. #endif
  396. inline bool axis_was_homed(const AxisEnum axis) { return TEST(axes_homed, axis); }
  397. inline bool axis_is_trusted(const AxisEnum axis) { return TEST(axes_trusted, axis); }
  398. inline bool axis_should_home(const AxisEnum axis) { return (axes_should_home() & _BV(axis)) != 0; }
  399. inline bool no_axes_homed() { return !axes_homed; }
  400. inline bool all_axes_homed() { return main_axes_mask == (axes_homed & main_axes_mask); }
  401. inline bool homing_needed() { return !all_axes_homed(); }
  402. inline bool all_axes_trusted() { return main_axes_mask == (axes_trusted & main_axes_mask); }
  403. void home_if_needed(const bool keeplev=false);
  404. #if ENABLED(NO_MOTION_BEFORE_HOMING)
  405. #define MOTION_CONDITIONS (IsRunning() && !homing_needed_error())
  406. #else
  407. #define MOTION_CONDITIONS IsRunning()
  408. #endif
  409. #define BABYSTEP_ALLOWED() ((ENABLED(BABYSTEP_WITHOUT_HOMING) || all_axes_trusted()) && (ENABLED(BABYSTEP_ALWAYS_AVAILABLE) || printer_busy()))
  410. /**
  411. * Workspace offsets
  412. */
  413. #if HAS_HOME_OFFSET || HAS_POSITION_SHIFT
  414. #if HAS_HOME_OFFSET
  415. extern xyz_pos_t home_offset;
  416. #endif
  417. #if HAS_POSITION_SHIFT
  418. extern xyz_pos_t position_shift;
  419. #endif
  420. #if HAS_HOME_OFFSET && HAS_POSITION_SHIFT
  421. extern xyz_pos_t workspace_offset;
  422. #define _WS workspace_offset
  423. #elif HAS_HOME_OFFSET
  424. #define _WS home_offset
  425. #else
  426. #define _WS position_shift
  427. #endif
  428. #define NATIVE_TO_LOGICAL(POS, AXIS) ((POS) + _WS[AXIS])
  429. #define LOGICAL_TO_NATIVE(POS, AXIS) ((POS) - _WS[AXIS])
  430. FORCE_INLINE void toLogical(xy_pos_t &raw) { raw += _WS; }
  431. FORCE_INLINE void toLogical(xyz_pos_t &raw) { raw += _WS; }
  432. FORCE_INLINE void toLogical(xyze_pos_t &raw) { raw += _WS; }
  433. FORCE_INLINE void toNative(xy_pos_t &raw) { raw -= _WS; }
  434. FORCE_INLINE void toNative(xyz_pos_t &raw) { raw -= _WS; }
  435. FORCE_INLINE void toNative(xyze_pos_t &raw) { raw -= _WS; }
  436. #else
  437. #define NATIVE_TO_LOGICAL(POS, AXIS) (POS)
  438. #define LOGICAL_TO_NATIVE(POS, AXIS) (POS)
  439. FORCE_INLINE void toLogical(xy_pos_t&) {}
  440. FORCE_INLINE void toLogical(xyz_pos_t&) {}
  441. FORCE_INLINE void toLogical(xyze_pos_t&) {}
  442. FORCE_INLINE void toNative(xy_pos_t&) {}
  443. FORCE_INLINE void toNative(xyz_pos_t&) {}
  444. FORCE_INLINE void toNative(xyze_pos_t&) {}
  445. #endif
  446. #define LOGICAL_X_POSITION(POS) NATIVE_TO_LOGICAL(POS, X_AXIS)
  447. #define RAW_X_POSITION(POS) LOGICAL_TO_NATIVE(POS, X_AXIS)
  448. #if HAS_Y_AXIS
  449. #define LOGICAL_Y_POSITION(POS) NATIVE_TO_LOGICAL(POS, Y_AXIS)
  450. #define RAW_Y_POSITION(POS) LOGICAL_TO_NATIVE(POS, Y_AXIS)
  451. #endif
  452. #if HAS_Z_AXIS
  453. #define LOGICAL_Z_POSITION(POS) NATIVE_TO_LOGICAL(POS, Z_AXIS)
  454. #define RAW_Z_POSITION(POS) LOGICAL_TO_NATIVE(POS, Z_AXIS)
  455. #endif
  456. #if HAS_I_AXIS
  457. #define LOGICAL_I_POSITION(POS) NATIVE_TO_LOGICAL(POS, I_AXIS)
  458. #define RAW_I_POSITION(POS) LOGICAL_TO_NATIVE(POS, I_AXIS)
  459. #endif
  460. #if HAS_J_AXIS
  461. #define LOGICAL_J_POSITION(POS) NATIVE_TO_LOGICAL(POS, J_AXIS)
  462. #define RAW_J_POSITION(POS) LOGICAL_TO_NATIVE(POS, J_AXIS)
  463. #endif
  464. #if HAS_K_AXIS
  465. #define LOGICAL_K_POSITION(POS) NATIVE_TO_LOGICAL(POS, K_AXIS)
  466. #define RAW_K_POSITION(POS) LOGICAL_TO_NATIVE(POS, K_AXIS)
  467. #endif
  468. #if HAS_U_AXIS
  469. #define LOGICAL_U_POSITION(POS) NATIVE_TO_LOGICAL(POS, U_AXIS)
  470. #define RAW_U_POSITION(POS) LOGICAL_TO_NATIVE(POS, U_AXIS)
  471. #endif
  472. #if HAS_V_AXIS
  473. #define LOGICAL_V_POSITION(POS) NATIVE_TO_LOGICAL(POS, V_AXIS)
  474. #define RAW_V_POSITION(POS) LOGICAL_TO_NATIVE(POS, V_AXIS)
  475. #endif
  476. #if HAS_W_AXIS
  477. #define LOGICAL_W_POSITION(POS) NATIVE_TO_LOGICAL(POS, W_AXIS)
  478. #define RAW_W_POSITION(POS) LOGICAL_TO_NATIVE(POS, W_AXIS)
  479. #endif
  480. /**
  481. * position_is_reachable family of functions
  482. */
  483. #if IS_KINEMATIC // (DELTA or SCARA)
  484. #if HAS_SCARA_OFFSET
  485. extern abc_pos_t scara_home_offset; // A and B angular offsets, Z mm offset
  486. #endif
  487. // Return true if the given point is within the printable area
  488. bool position_is_reachable(const_float_t rx, const_float_t ry, const float inset=0);
  489. inline bool position_is_reachable(const xy_pos_t &pos, const float inset=0) {
  490. return position_is_reachable(pos.x, pos.y, inset);
  491. }
  492. #else
  493. // Return true if the given position is within the machine bounds.
  494. bool position_is_reachable(const_float_t rx, const_float_t ry);
  495. inline bool position_is_reachable(const xy_pos_t &pos) {
  496. return position_is_reachable(pos.x, pos.y);
  497. }
  498. #endif
  499. /**
  500. * Duplication mode
  501. */
  502. #if HAS_DUPLICATION_MODE
  503. extern bool extruder_duplication_enabled; // Used in Dual X mode 2
  504. #endif
  505. /**
  506. * Dual X Carriage
  507. */
  508. #if ENABLED(DUAL_X_CARRIAGE)
  509. enum DualXMode : char {
  510. DXC_FULL_CONTROL_MODE,
  511. DXC_AUTO_PARK_MODE,
  512. DXC_DUPLICATION_MODE,
  513. DXC_MIRRORED_MODE
  514. };
  515. extern DualXMode dual_x_carriage_mode;
  516. extern float inactive_extruder_x, // Used in mode 0 & 1
  517. duplicate_extruder_x_offset; // Used in mode 2 & 3
  518. extern xyz_pos_t raised_parked_position; // Used in mode 1
  519. extern bool active_extruder_parked; // Used in mode 1, 2 & 3
  520. extern millis_t delayed_move_time; // Used in mode 1
  521. extern celsius_t duplicate_extruder_temp_offset; // Used in mode 2 & 3
  522. extern bool idex_mirrored_mode; // Used in mode 3
  523. FORCE_INLINE bool idex_is_duplicating() { return dual_x_carriage_mode >= DXC_DUPLICATION_MODE; }
  524. float x_home_pos(const uint8_t extruder);
  525. #define TOOL_X_HOME_DIR(T) ((T) ? X2_HOME_DIR : X_HOME_DIR)
  526. void set_duplication_enabled(const bool dupe, const int8_t tool_index=-1);
  527. void idex_set_mirrored_mode(const bool mirr);
  528. void idex_set_parked(const bool park=true);
  529. #else
  530. #if ENABLED(MULTI_NOZZLE_DUPLICATION)
  531. extern uint8_t duplication_e_mask;
  532. enum DualXMode : char { DXC_DUPLICATION_MODE = 2 };
  533. FORCE_INLINE void set_duplication_enabled(const bool dupe) { extruder_duplication_enabled = dupe; }
  534. #endif
  535. #define TOOL_X_HOME_DIR(T) X_HOME_DIR
  536. #endif
  537. #if HAS_M206_COMMAND
  538. void set_home_offset(const AxisEnum axis, const float v);
  539. #endif
  540. #if USE_SENSORLESS
  541. struct sensorless_t;
  542. sensorless_t start_sensorless_homing_per_axis(const AxisEnum axis);
  543. void end_sensorless_homing_per_axis(const AxisEnum axis, sensorless_t enable_stealth);
  544. #endif