My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

trinamic.cpp 34KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  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. /**
  23. * stepper/trinamic.cpp
  24. * Stepper driver indirection for Trinamic
  25. */
  26. #include "../../inc/MarlinConfig.h"
  27. #if HAS_TRINAMIC_CONFIG
  28. #include "trinamic.h"
  29. #include "../stepper.h"
  30. #include <HardwareSerial.h>
  31. #include <SPI.h>
  32. enum StealthIndex : uint8_t {
  33. LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K, STEALTH_AXIS_U, STEALTH_AXIS_V, STEALTH_AXIS_W)
  34. };
  35. #define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE, ST##_HOLD_MULTIPLIER)
  36. // IC = TMC model number
  37. // ST = Stepper object letter
  38. // L = Label characters
  39. // AI = Axis Enum Index
  40. // SWHW = SW/SH UART selection
  41. #if ENABLED(TMC_USE_SW_SPI)
  42. #define __TMC_SPI_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_CS_PIN, float(ST##_RSENSE), TMC_SW_MOSI, TMC_SW_MISO, TMC_SW_SCK, ST##_CHAIN_POS)
  43. #else
  44. #define __TMC_SPI_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_CS_PIN, float(ST##_RSENSE), ST##_CHAIN_POS)
  45. #endif
  46. #if ENABLED(TMC_SERIAL_MULTIPLEXER)
  47. #define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS, SERIAL_MUL_PIN1, SERIAL_MUL_PIN2)
  48. #else
  49. #define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
  50. #endif
  51. #define TMC_UART_SW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_SERIAL_RX_PIN, ST##_SERIAL_TX_PIN, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
  52. #define _TMC_SPI_DEFINE(IC, ST, AI) __TMC_SPI_DEFINE(IC, ST, TMC_##ST##_LABEL, AI)
  53. #define TMC_SPI_DEFINE(ST, AI) _TMC_SPI_DEFINE(ST##_DRIVER_TYPE, ST, AI##_AXIS)
  54. #define _TMC_UART_DEFINE(SWHW, IC, ST, AI) TMC_UART_##SWHW##_DEFINE(IC, ST, TMC_##ST##_LABEL, AI)
  55. #define TMC_UART_DEFINE(SWHW, ST, AI) _TMC_UART_DEFINE(SWHW, ST##_DRIVER_TYPE, ST, AI##_AXIS)
  56. #if ENABLED(DISTINCT_E_FACTORS)
  57. #define TMC_SPI_DEFINE_E(AI) TMC_SPI_DEFINE(E##AI, E##AI)
  58. #define TMC_UART_DEFINE_E(SWHW, AI) TMC_UART_DEFINE(SWHW, E##AI, E##AI)
  59. #else
  60. #define TMC_SPI_DEFINE_E(AI) TMC_SPI_DEFINE(E##AI, E)
  61. #define TMC_UART_DEFINE_E(SWHW, AI) TMC_UART_DEFINE(SWHW, E##AI, E)
  62. #endif
  63. // Stepper objects of TMC2130/TMC2160/TMC2660/TMC5130/TMC5160 steppers used
  64. #if AXIS_HAS_SPI(X)
  65. TMC_SPI_DEFINE(X, X);
  66. #endif
  67. #if AXIS_HAS_SPI(X2)
  68. TMC_SPI_DEFINE(X2, X);
  69. #endif
  70. #if AXIS_HAS_SPI(Y)
  71. TMC_SPI_DEFINE(Y, Y);
  72. #endif
  73. #if AXIS_HAS_SPI(Y2)
  74. TMC_SPI_DEFINE(Y2, Y);
  75. #endif
  76. #if AXIS_HAS_SPI(Z)
  77. TMC_SPI_DEFINE(Z, Z);
  78. #endif
  79. #if AXIS_HAS_SPI(Z2)
  80. TMC_SPI_DEFINE(Z2, Z);
  81. #endif
  82. #if AXIS_HAS_SPI(Z3)
  83. TMC_SPI_DEFINE(Z3, Z);
  84. #endif
  85. #if AXIS_HAS_SPI(Z4)
  86. TMC_SPI_DEFINE(Z4, Z);
  87. #endif
  88. #if AXIS_HAS_SPI(I)
  89. TMC_SPI_DEFINE(I, I);
  90. #endif
  91. #if AXIS_HAS_SPI(J)
  92. TMC_SPI_DEFINE(J, J);
  93. #endif
  94. #if AXIS_HAS_SPI(K)
  95. TMC_SPI_DEFINE(K, K);
  96. #endif
  97. #if AXIS_HAS_SPI(U)
  98. TMC_SPI_DEFINE(U, U);
  99. #endif
  100. #if AXIS_HAS_SPI(V)
  101. TMC_SPI_DEFINE(V, V);
  102. #endif
  103. #if AXIS_HAS_SPI(W)
  104. TMC_SPI_DEFINE(W, W);
  105. #endif
  106. #if AXIS_HAS_SPI(E0)
  107. TMC_SPI_DEFINE_E(0);
  108. #endif
  109. #if AXIS_HAS_SPI(E1)
  110. TMC_SPI_DEFINE_E(1);
  111. #endif
  112. #if AXIS_HAS_SPI(E2)
  113. TMC_SPI_DEFINE_E(2);
  114. #endif
  115. #if AXIS_HAS_SPI(E3)
  116. TMC_SPI_DEFINE_E(3);
  117. #endif
  118. #if AXIS_HAS_SPI(E4)
  119. TMC_SPI_DEFINE_E(4);
  120. #endif
  121. #if AXIS_HAS_SPI(E5)
  122. TMC_SPI_DEFINE_E(5);
  123. #endif
  124. #if AXIS_HAS_SPI(E6)
  125. TMC_SPI_DEFINE_E(6);
  126. #endif
  127. #if AXIS_HAS_SPI(E7)
  128. TMC_SPI_DEFINE_E(7);
  129. #endif
  130. #ifndef TMC_BAUD_RATE
  131. // Reduce baud rate for boards not already overriding TMC_BAUD_RATE for software serial.
  132. // Testing has shown that 115200 is not 100% reliable on AVR platforms, occasionally
  133. // failing to read status properly. 32-bit platforms typically define an even lower
  134. // TMC_BAUD_RATE, due to differences in how SoftwareSerial libraries work on different
  135. // platforms.
  136. #define TMC_BAUD_RATE TERN(HAS_TMC_SW_SERIAL, 57600, 115200)
  137. #endif
  138. #ifndef TMC_X_BAUD_RATE
  139. #define TMC_X_BAUD_RATE TMC_BAUD_RATE
  140. #endif
  141. #ifndef TMC_X2_BAUD_RATE
  142. #define TMC_X2_BAUD_RATE TMC_BAUD_RATE
  143. #endif
  144. #ifndef TMC_Y_BAUD_RATE
  145. #define TMC_Y_BAUD_RATE TMC_BAUD_RATE
  146. #endif
  147. #ifndef TMC_Y2_BAUD_RATE
  148. #define TMC_Y2_BAUD_RATE TMC_BAUD_RATE
  149. #endif
  150. #ifndef TMC_Z_BAUD_RATE
  151. #define TMC_Z_BAUD_RATE TMC_BAUD_RATE
  152. #endif
  153. #ifndef TMC_Z2_BAUD_RATE
  154. #define TMC_Z2_BAUD_RATE TMC_BAUD_RATE
  155. #endif
  156. #ifndef TMC_Z3_BAUD_RATE
  157. #define TMC_Z3_BAUD_RATE TMC_BAUD_RATE
  158. #endif
  159. #ifndef TMC_Z4_BAUD_RATE
  160. #define TMC_Z4_BAUD_RATE TMC_BAUD_RATE
  161. #endif
  162. #ifndef TMC_I_BAUD_RATE
  163. #define TMC_I_BAUD_RATE TMC_BAUD_RATE
  164. #endif
  165. #ifndef TMC_J_BAUD_RATE
  166. #define TMC_J_BAUD_RATE TMC_BAUD_RATE
  167. #endif
  168. #ifndef TMC_K_BAUD_RATE
  169. #define TMC_K_BAUD_RATE TMC_BAUD_RATE
  170. #endif
  171. #ifndef TMC_U_BAUD_RATE
  172. #define TMC_U_BAUD_RATE TMC_BAUD_RATE
  173. #endif
  174. #ifndef TMC_V_BAUD_RATE
  175. #define TMC_V_BAUD_RATE TMC_BAUD_RATE
  176. #endif
  177. #ifndef TMC_W_BAUD_RATE
  178. #define TMC_W_BAUD_RATE TMC_BAUD_RATE
  179. #endif
  180. #ifndef TMC_E0_BAUD_RATE
  181. #define TMC_E0_BAUD_RATE TMC_BAUD_RATE
  182. #endif
  183. #ifndef TMC_E1_BAUD_RATE
  184. #define TMC_E1_BAUD_RATE TMC_BAUD_RATE
  185. #endif
  186. #ifndef TMC_E2_BAUD_RATE
  187. #define TMC_E2_BAUD_RATE TMC_BAUD_RATE
  188. #endif
  189. #ifndef TMC_E3_BAUD_RATE
  190. #define TMC_E3_BAUD_RATE TMC_BAUD_RATE
  191. #endif
  192. #ifndef TMC_E4_BAUD_RATE
  193. #define TMC_E4_BAUD_RATE TMC_BAUD_RATE
  194. #endif
  195. #ifndef TMC_E5_BAUD_RATE
  196. #define TMC_E5_BAUD_RATE TMC_BAUD_RATE
  197. #endif
  198. #ifndef TMC_E6_BAUD_RATE
  199. #define TMC_E6_BAUD_RATE TMC_BAUD_RATE
  200. #endif
  201. #ifndef TMC_E7_BAUD_RATE
  202. #define TMC_E7_BAUD_RATE TMC_BAUD_RATE
  203. #endif
  204. #if HAS_DRIVER(TMC2130)
  205. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  206. void tmc_init(TMCMarlin<TMC2130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
  207. st.begin();
  208. CHOPCONF_t chopconf{0};
  209. chopconf.tbl = 0b01;
  210. chopconf.toff = chop_init.toff;
  211. chopconf.intpol = interpolate;
  212. chopconf.hend = chop_init.hend + 3;
  213. chopconf.hstrt = chop_init.hstrt - 1;
  214. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  215. st.CHOPCONF(chopconf.sr);
  216. st.rms_current(mA, hold_multiplier);
  217. st.microsteps(microsteps);
  218. st.iholddelay(10);
  219. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  220. st.en_pwm_mode(stealth);
  221. st.stored.stealthChop_enabled = stealth;
  222. PWMCONF_t pwmconf{0};
  223. pwmconf.pwm_freq = 0b01; // f_pwm = 2/683 f_clk
  224. pwmconf.pwm_autoscale = true;
  225. pwmconf.pwm_grad = 5;
  226. pwmconf.pwm_ampl = 180;
  227. st.PWMCONF(pwmconf.sr);
  228. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  229. st.GSTAT(); // Clear GSTAT
  230. }
  231. #endif // TMC2130
  232. #if HAS_DRIVER(TMC2160)
  233. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  234. void tmc_init(TMCMarlin<TMC2160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
  235. st.begin();
  236. CHOPCONF_t chopconf{0};
  237. chopconf.tbl = 0b01;
  238. chopconf.toff = chop_init.toff;
  239. chopconf.intpol = interpolate;
  240. chopconf.hend = chop_init.hend + 3;
  241. chopconf.hstrt = chop_init.hstrt - 1;
  242. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  243. st.CHOPCONF(chopconf.sr);
  244. st.rms_current(mA, hold_multiplier);
  245. st.microsteps(microsteps);
  246. st.iholddelay(10);
  247. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  248. st.en_pwm_mode(stealth);
  249. st.stored.stealthChop_enabled = stealth;
  250. TMC2160_n::PWMCONF_t pwmconf{0};
  251. pwmconf.pwm_lim = 12;
  252. pwmconf.pwm_reg = 8;
  253. pwmconf.pwm_autograd = true;
  254. pwmconf.pwm_autoscale = true;
  255. pwmconf.pwm_freq = 0b01;
  256. pwmconf.pwm_grad = 14;
  257. pwmconf.pwm_ofs = 36;
  258. st.PWMCONF(pwmconf.sr);
  259. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  260. st.GSTAT(); // Clear GSTAT
  261. }
  262. #endif // TMC2160
  263. //
  264. // TMC2208/2209 Driver objects and inits
  265. //
  266. #if HAS_TMC220x
  267. #if AXIS_HAS_UART(X)
  268. #ifdef X_HARDWARE_SERIAL
  269. TMC_UART_DEFINE(HW, X, X);
  270. #define X_HAS_HW_SERIAL 1
  271. #else
  272. TMC_UART_DEFINE(SW, X, X);
  273. #define X_HAS_SW_SERIAL 1
  274. #endif
  275. #endif
  276. #if AXIS_HAS_UART(X2)
  277. #ifdef X2_HARDWARE_SERIAL
  278. TMC_UART_DEFINE(HW, X2, X);
  279. #define X2_HAS_HW_SERIAL 1
  280. #else
  281. TMC_UART_DEFINE(SW, X2, X);
  282. #define X2_HAS_SW_SERIAL 1
  283. #endif
  284. #endif
  285. #if AXIS_HAS_UART(Y)
  286. #ifdef Y_HARDWARE_SERIAL
  287. TMC_UART_DEFINE(HW, Y, Y);
  288. #define Y_HAS_HW_SERIAL 1
  289. #else
  290. TMC_UART_DEFINE(SW, Y, Y);
  291. #define Y_HAS_SW_SERIAL 1
  292. #endif
  293. #endif
  294. #if AXIS_HAS_UART(Y2)
  295. #ifdef Y2_HARDWARE_SERIAL
  296. TMC_UART_DEFINE(HW, Y2, Y);
  297. #define Y2_HAS_HW_SERIAL 1
  298. #else
  299. TMC_UART_DEFINE(SW, Y2, Y);
  300. #define Y2_HAS_SW_SERIAL 1
  301. #endif
  302. #endif
  303. #if AXIS_HAS_UART(Z)
  304. #ifdef Z_HARDWARE_SERIAL
  305. TMC_UART_DEFINE(HW, Z, Z);
  306. #define Z_HAS_HW_SERIAL 1
  307. #else
  308. TMC_UART_DEFINE(SW, Z, Z);
  309. #define Z_HAS_SW_SERIAL 1
  310. #endif
  311. #endif
  312. #if AXIS_HAS_UART(Z2)
  313. #ifdef Z2_HARDWARE_SERIAL
  314. TMC_UART_DEFINE(HW, Z2, Z);
  315. #define Z2_HAS_HW_SERIAL 1
  316. #else
  317. TMC_UART_DEFINE(SW, Z2, Z);
  318. #define Z2_HAS_SW_SERIAL 1
  319. #endif
  320. #endif
  321. #if AXIS_HAS_UART(Z3)
  322. #ifdef Z3_HARDWARE_SERIAL
  323. TMC_UART_DEFINE(HW, Z3, Z);
  324. #define Z3_HAS_HW_SERIAL 1
  325. #else
  326. TMC_UART_DEFINE(SW, Z3, Z);
  327. #define Z3_HAS_SW_SERIAL 1
  328. #endif
  329. #endif
  330. #if AXIS_HAS_UART(Z4)
  331. #ifdef Z4_HARDWARE_SERIAL
  332. TMC_UART_DEFINE(HW, Z4, Z);
  333. #define Z4_HAS_HW_SERIAL 1
  334. #else
  335. TMC_UART_DEFINE(SW, Z4, Z);
  336. #define Z4_HAS_SW_SERIAL 1
  337. #endif
  338. #endif
  339. #if AXIS_HAS_UART(I)
  340. #ifdef I_HARDWARE_SERIAL
  341. TMC_UART_DEFINE(HW, I, I);
  342. #define I_HAS_HW_SERIAL 1
  343. #else
  344. TMC_UART_DEFINE(SW, I, I);
  345. #define I_HAS_SW_SERIAL 1
  346. #endif
  347. #endif
  348. #if AXIS_HAS_UART(J)
  349. #ifdef J_HARDWARE_SERIAL
  350. TMC_UART_DEFINE(HW, J, J);
  351. #define J_HAS_HW_SERIAL 1
  352. #else
  353. TMC_UART_DEFINE(SW, J, J);
  354. #define J_HAS_SW_SERIAL 1
  355. #endif
  356. #endif
  357. #if AXIS_HAS_UART(K)
  358. #ifdef K_HARDWARE_SERIAL
  359. TMC_UART_DEFINE(HW, K, K);
  360. #define K_HAS_HW_SERIAL 1
  361. #else
  362. TMC_UART_DEFINE(SW, K, K);
  363. #define K_HAS_SW_SERIAL 1
  364. #endif
  365. #endif
  366. #if AXIS_HAS_UART(U)
  367. #ifdef U_HARDWARE_SERIAL
  368. TMC_UART_DEFINE(HW, U, U);
  369. #define U_HAS_HW_SERIAL 1
  370. #else
  371. TMC_UART_DEFINE(SW, U, U);
  372. #define U_HAS_SW_SERIAL 1
  373. #endif
  374. #endif
  375. #if AXIS_HAS_UART(V)
  376. #ifdef V_HARDWARE_SERIAL
  377. TMC_UART_DEFINE(HW, V, V);
  378. #else
  379. TMC_UART_DEFINE(SW, V, V);
  380. #define V_HAS_SW_SERIAL 1
  381. #endif
  382. #endif
  383. #if AXIS_HAS_UART(W)
  384. #ifdef W_HARDWARE_SERIAL
  385. TMC_UART_DEFINE(HW, W, W);
  386. #define W_HAS_HW_SERIAL 1
  387. #else
  388. TMC_UART_DEFINE(SW, W, W);
  389. #define W_HAS_SW_SERIAL 1
  390. #endif
  391. #endif
  392. #if AXIS_HAS_UART(E0)
  393. #ifdef E0_HARDWARE_SERIAL
  394. TMC_UART_DEFINE_E(HW, 0);
  395. #define E0_HAS_HW_SERIAL 1
  396. #else
  397. TMC_UART_DEFINE_E(SW, 0);
  398. #define E0_HAS_SW_SERIAL 1
  399. #endif
  400. #endif
  401. #if AXIS_HAS_UART(E1)
  402. #ifdef E1_HARDWARE_SERIAL
  403. TMC_UART_DEFINE_E(HW, 1);
  404. #define E1_HAS_HW_SERIAL 1
  405. #else
  406. TMC_UART_DEFINE_E(SW, 1);
  407. #define E1_HAS_SW_SERIAL 1
  408. #endif
  409. #endif
  410. #if AXIS_HAS_UART(E2)
  411. #ifdef E2_HARDWARE_SERIAL
  412. TMC_UART_DEFINE_E(HW, 2);
  413. #define E2_HAS_HW_SERIAL 1
  414. #else
  415. TMC_UART_DEFINE_E(SW, 2);
  416. #define E2_HAS_SW_SERIAL 1
  417. #endif
  418. #endif
  419. #if AXIS_HAS_UART(E3)
  420. #ifdef E3_HARDWARE_SERIAL
  421. TMC_UART_DEFINE_E(HW, 3);
  422. #define E3_HAS_HW_SERIAL 1
  423. #else
  424. TMC_UART_DEFINE_E(SW, 3);
  425. #define E3_HAS_SW_SERIAL 1
  426. #endif
  427. #endif
  428. #if AXIS_HAS_UART(E4)
  429. #ifdef E4_HARDWARE_SERIAL
  430. TMC_UART_DEFINE_E(HW, 4);
  431. #define E4_HAS_HW_SERIAL 1
  432. #else
  433. TMC_UART_DEFINE_E(SW, 4);
  434. #define E4_HAS_SW_SERIAL 1
  435. #endif
  436. #endif
  437. #if AXIS_HAS_UART(E5)
  438. #ifdef E5_HARDWARE_SERIAL
  439. TMC_UART_DEFINE_E(HW, 5);
  440. #define E5_HAS_HW_SERIAL 1
  441. #else
  442. TMC_UART_DEFINE_E(SW, 5);
  443. #define E5_HAS_SW_SERIAL 1
  444. #endif
  445. #endif
  446. #if AXIS_HAS_UART(E6)
  447. #ifdef E6_HARDWARE_SERIAL
  448. TMC_UART_DEFINE_E(HW, 6);
  449. #define E6_HAS_HW_SERIAL 1
  450. #else
  451. TMC_UART_DEFINE_E(SW, 6);
  452. #define E6_HAS_SW_SERIAL 1
  453. #endif
  454. #endif
  455. #if AXIS_HAS_UART(E7)
  456. #ifdef E7_HARDWARE_SERIAL
  457. TMC_UART_DEFINE_E(HW, 7);
  458. #define E7_HAS_HW_SERIAL 1
  459. #else
  460. TMC_UART_DEFINE_E(SW, 7);
  461. #define E7_HAS_SW_SERIAL 1
  462. #endif
  463. #endif
  464. #define _EN_ITEM(N) , E##N
  465. enum TMCAxis : uint8_t { NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL };
  466. #undef _EN_ITEM
  467. void tmc_serial_begin() {
  468. #if HAS_TMC_HW_SERIAL
  469. struct {
  470. const void *ptr[TMCAxis::TOTAL];
  471. bool began(const TMCAxis a, const void * const p) {
  472. LOOP_L_N(i, a) if (p == ptr[i]) return true;
  473. ptr[a] = p; return false;
  474. };
  475. } sp_helper;
  476. #define HW_SERIAL_BEGIN(A) do{ if (!sp_helper.began(TMCAxis::A, &A##_HARDWARE_SERIAL)) \
  477. A##_HARDWARE_SERIAL.begin(TMC_##A##_BAUD_RATE); }while(0)
  478. #endif
  479. #if AXIS_HAS_UART(X)
  480. #ifdef X_HARDWARE_SERIAL
  481. HW_SERIAL_BEGIN(X);
  482. #else
  483. stepperX.beginSerial(TMC_BAUD_RATE);
  484. #endif
  485. #endif
  486. #if AXIS_HAS_UART(X2)
  487. #ifdef X2_HARDWARE_SERIAL
  488. HW_SERIAL_BEGIN(X2);
  489. #else
  490. stepperX2.beginSerial(TMC_BAUD_RATE);
  491. #endif
  492. #endif
  493. #if AXIS_HAS_UART(Y)
  494. #ifdef Y_HARDWARE_SERIAL
  495. HW_SERIAL_BEGIN(Y);
  496. #else
  497. stepperY.beginSerial(TMC_BAUD_RATE);
  498. #endif
  499. #endif
  500. #if AXIS_HAS_UART(Y2)
  501. #ifdef Y2_HARDWARE_SERIAL
  502. HW_SERIAL_BEGIN(Y2);
  503. #else
  504. stepperY2.beginSerial(TMC_BAUD_RATE);
  505. #endif
  506. #endif
  507. #if AXIS_HAS_UART(Z)
  508. #ifdef Z_HARDWARE_SERIAL
  509. HW_SERIAL_BEGIN(Z);
  510. #else
  511. stepperZ.beginSerial(TMC_BAUD_RATE);
  512. #endif
  513. #endif
  514. #if AXIS_HAS_UART(Z2)
  515. #ifdef Z2_HARDWARE_SERIAL
  516. HW_SERIAL_BEGIN(Z2);
  517. #else
  518. stepperZ2.beginSerial(TMC_BAUD_RATE);
  519. #endif
  520. #endif
  521. #if AXIS_HAS_UART(Z3)
  522. #ifdef Z3_HARDWARE_SERIAL
  523. HW_SERIAL_BEGIN(Z3);
  524. #else
  525. stepperZ3.beginSerial(TMC_BAUD_RATE);
  526. #endif
  527. #endif
  528. #if AXIS_HAS_UART(Z4)
  529. #ifdef Z4_HARDWARE_SERIAL
  530. HW_SERIAL_BEGIN(Z4);
  531. #else
  532. stepperZ4.beginSerial(TMC_BAUD_RATE);
  533. #endif
  534. #endif
  535. #if AXIS_HAS_UART(I)
  536. #ifdef I_HARDWARE_SERIAL
  537. HW_SERIAL_BEGIN(I);
  538. #else
  539. stepperI.beginSerial(TMC_BAUD_RATE);
  540. #endif
  541. #endif
  542. #if AXIS_HAS_UART(J)
  543. #ifdef J_HARDWARE_SERIAL
  544. HW_SERIAL_BEGIN(J);
  545. #else
  546. stepperJ.beginSerial(TMC_BAUD_RATE);
  547. #endif
  548. #endif
  549. #if AXIS_HAS_UART(K)
  550. #ifdef K_HARDWARE_SERIAL
  551. HW_SERIAL_BEGIN(K);
  552. #else
  553. stepperK.beginSerial(TMC_BAUD_RATE);
  554. #endif
  555. #endif
  556. #if AXIS_HAS_UART(U)
  557. #ifdef U_HARDWARE_SERIAL
  558. HW_SERIAL_BEGIN(U);
  559. #else
  560. stepperU.beginSerial(TMC_BAUD_RATE);
  561. #endif
  562. #endif
  563. #if AXIS_HAS_UART(V)
  564. #ifdef V_HARDWARE_SERIAL
  565. HW_SERIAL_BEGIN(V);
  566. #else
  567. stepperV.beginSerial(TMC_BAUD_RATE);
  568. #endif
  569. #endif
  570. #if AXIS_HAS_UART(W)
  571. #ifdef W_HARDWARE_SERIAL
  572. HW_SERIAL_BEGIN(W);
  573. #else
  574. stepperW.beginSerial(TMC_BAUD_RATE);
  575. #endif
  576. #endif
  577. #if AXIS_HAS_UART(E0)
  578. #ifdef E0_HARDWARE_SERIAL
  579. HW_SERIAL_BEGIN(E0);
  580. #else
  581. stepperE0.beginSerial(TMC_BAUD_RATE);
  582. #endif
  583. #endif
  584. #if AXIS_HAS_UART(E1)
  585. #ifdef E1_HARDWARE_SERIAL
  586. HW_SERIAL_BEGIN(E1);
  587. #else
  588. stepperE1.beginSerial(TMC_BAUD_RATE);
  589. #endif
  590. #endif
  591. #if AXIS_HAS_UART(E2)
  592. #ifdef E2_HARDWARE_SERIAL
  593. HW_SERIAL_BEGIN(E2);
  594. #else
  595. stepperE2.beginSerial(TMC_BAUD_RATE);
  596. #endif
  597. #endif
  598. #if AXIS_HAS_UART(E3)
  599. #ifdef E3_HARDWARE_SERIAL
  600. HW_SERIAL_BEGIN(E3);
  601. #else
  602. stepperE3.beginSerial(TMC_BAUD_RATE);
  603. #endif
  604. #endif
  605. #if AXIS_HAS_UART(E4)
  606. #ifdef E4_HARDWARE_SERIAL
  607. HW_SERIAL_BEGIN(E4);
  608. #else
  609. stepperE4.beginSerial(TMC_BAUD_RATE);
  610. #endif
  611. #endif
  612. #if AXIS_HAS_UART(E5)
  613. #ifdef E5_HARDWARE_SERIAL
  614. HW_SERIAL_BEGIN(E5);
  615. #else
  616. stepperE5.beginSerial(TMC_BAUD_RATE);
  617. #endif
  618. #endif
  619. #if AXIS_HAS_UART(E6)
  620. #ifdef E6_HARDWARE_SERIAL
  621. HW_SERIAL_BEGIN(E6);
  622. #else
  623. stepperE6.beginSerial(TMC_BAUD_RATE);
  624. #endif
  625. #endif
  626. #if AXIS_HAS_UART(E7)
  627. #ifdef E7_HARDWARE_SERIAL
  628. HW_SERIAL_BEGIN(E7);
  629. #else
  630. stepperE7.beginSerial(TMC_BAUD_RATE);
  631. #endif
  632. #endif
  633. }
  634. #endif
  635. #if HAS_DRIVER(TMC2208)
  636. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  637. void tmc_init(TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
  638. TMC2208_n::GCONF_t gconf{0};
  639. gconf.pdn_disable = true; // Use UART
  640. gconf.mstep_reg_select = true; // Select microsteps with UART
  641. gconf.i_scale_analog = false;
  642. gconf.en_spreadcycle = !stealth;
  643. st.GCONF(gconf.sr);
  644. st.stored.stealthChop_enabled = stealth;
  645. TMC2208_n::CHOPCONF_t chopconf{0};
  646. chopconf.tbl = 0b01; // blank_time = 24
  647. chopconf.toff = chop_init.toff;
  648. chopconf.intpol = interpolate;
  649. chopconf.hend = chop_init.hend + 3;
  650. chopconf.hstrt = chop_init.hstrt - 1;
  651. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  652. st.CHOPCONF(chopconf.sr);
  653. st.rms_current(mA, hold_multiplier);
  654. st.microsteps(microsteps);
  655. st.iholddelay(10);
  656. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  657. TMC2208_n::PWMCONF_t pwmconf{0};
  658. pwmconf.pwm_lim = 12;
  659. pwmconf.pwm_reg = 8;
  660. pwmconf.pwm_autograd = true;
  661. pwmconf.pwm_autoscale = true;
  662. pwmconf.pwm_freq = 0b01;
  663. pwmconf.pwm_grad = 14;
  664. pwmconf.pwm_ofs = 36;
  665. st.PWMCONF(pwmconf.sr);
  666. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  667. st.GSTAT(0b111); // Clear
  668. delay(200);
  669. }
  670. #endif // TMC2208
  671. #if HAS_DRIVER(TMC2209)
  672. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  673. void tmc_init(TMCMarlin<TMC2209Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
  674. TMC2208_n::GCONF_t gconf{0};
  675. gconf.pdn_disable = true; // Use UART
  676. gconf.mstep_reg_select = true; // Select microsteps with UART
  677. gconf.i_scale_analog = false;
  678. gconf.en_spreadcycle = !stealth;
  679. st.GCONF(gconf.sr);
  680. st.stored.stealthChop_enabled = stealth;
  681. TMC2208_n::CHOPCONF_t chopconf{0};
  682. chopconf.tbl = 0b01; // blank_time = 24
  683. chopconf.toff = chop_init.toff;
  684. chopconf.intpol = interpolate;
  685. chopconf.hend = chop_init.hend + 3;
  686. chopconf.hstrt = chop_init.hstrt - 1;
  687. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  688. st.CHOPCONF(chopconf.sr);
  689. st.rms_current(mA, hold_multiplier);
  690. st.microsteps(microsteps);
  691. st.iholddelay(10);
  692. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  693. TMC2208_n::PWMCONF_t pwmconf{0};
  694. pwmconf.pwm_lim = 12;
  695. pwmconf.pwm_reg = 8;
  696. pwmconf.pwm_autograd = true;
  697. pwmconf.pwm_autoscale = true;
  698. pwmconf.pwm_freq = 0b01;
  699. pwmconf.pwm_grad = 14;
  700. pwmconf.pwm_ofs = 36;
  701. st.PWMCONF(pwmconf.sr);
  702. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  703. st.GSTAT(0b111); // Clear
  704. delay(200);
  705. }
  706. #endif // TMC2209
  707. #if HAS_DRIVER(TMC2660)
  708. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  709. void tmc_init(TMCMarlin<TMC2660Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t, const bool, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
  710. st.begin();
  711. TMC2660_n::CHOPCONF_t chopconf{0};
  712. chopconf.tbl = 0b01;
  713. chopconf.toff = chop_init.toff;
  714. chopconf.hend = chop_init.hend + 3;
  715. chopconf.hstrt = chop_init.hstrt - 1;
  716. st.CHOPCONF(chopconf.sr);
  717. st.sdoff(0);
  718. st.rms_current(mA);
  719. st.microsteps(microsteps);
  720. TERN_(SQUARE_WAVE_STEPPING, st.dedge(true));
  721. st.intpol(interpolate);
  722. st.diss2g(true); // Disable short to ground protection. Too many false readings?
  723. TERN_(TMC_DEBUG, st.rdsel(0b01));
  724. }
  725. #endif // TMC2660
  726. #if HAS_DRIVER(TMC5130)
  727. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  728. void tmc_init(TMCMarlin<TMC5130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
  729. st.begin();
  730. CHOPCONF_t chopconf{0};
  731. chopconf.tbl = 0b01;
  732. chopconf.toff = chop_init.toff;
  733. chopconf.intpol = interpolate;
  734. chopconf.hend = chop_init.hend + 3;
  735. chopconf.hstrt = chop_init.hstrt - 1;
  736. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  737. st.CHOPCONF(chopconf.sr);
  738. st.rms_current(mA, hold_multiplier);
  739. st.microsteps(microsteps);
  740. st.iholddelay(10);
  741. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  742. st.en_pwm_mode(stealth);
  743. st.stored.stealthChop_enabled = stealth;
  744. PWMCONF_t pwmconf{0};
  745. pwmconf.pwm_freq = 0b01; // f_pwm = 2/683 f_clk
  746. pwmconf.pwm_autoscale = true;
  747. pwmconf.pwm_grad = 5;
  748. pwmconf.pwm_ampl = 180;
  749. st.PWMCONF(pwmconf.sr);
  750. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  751. st.GSTAT(); // Clear GSTAT
  752. }
  753. #endif // TMC5130
  754. #if HAS_DRIVER(TMC5160)
  755. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  756. void tmc_init(TMCMarlin<TMC5160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate, float hold_multiplier) {
  757. st.begin();
  758. CHOPCONF_t chopconf{0};
  759. chopconf.tbl = 0b01;
  760. chopconf.toff = chop_init.toff;
  761. chopconf.intpol = interpolate;
  762. chopconf.hend = chop_init.hend + 3;
  763. chopconf.hstrt = chop_init.hstrt - 1;
  764. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  765. st.CHOPCONF(chopconf.sr);
  766. st.rms_current(mA, hold_multiplier);
  767. st.microsteps(microsteps);
  768. st.iholddelay(10);
  769. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  770. st.en_pwm_mode(stealth);
  771. st.stored.stealthChop_enabled = stealth;
  772. TMC2160_n::PWMCONF_t pwmconf{0};
  773. pwmconf.pwm_lim = 12;
  774. pwmconf.pwm_reg = 8;
  775. pwmconf.pwm_autograd = true;
  776. pwmconf.pwm_autoscale = true;
  777. pwmconf.pwm_freq = 0b01;
  778. pwmconf.pwm_grad = 14;
  779. pwmconf.pwm_ofs = 36;
  780. st.PWMCONF(pwmconf.sr);
  781. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  782. st.GSTAT(); // Clear GSTAT
  783. }
  784. #endif // TMC5160
  785. void restore_trinamic_drivers() {
  786. #if AXIS_IS_TMC(X)
  787. stepperX.push();
  788. #endif
  789. #if AXIS_IS_TMC(X2)
  790. stepperX2.push();
  791. #endif
  792. #if AXIS_IS_TMC(Y)
  793. stepperY.push();
  794. #endif
  795. #if AXIS_IS_TMC(Y2)
  796. stepperY2.push();
  797. #endif
  798. #if AXIS_IS_TMC(Z)
  799. stepperZ.push();
  800. #endif
  801. #if AXIS_IS_TMC(Z2)
  802. stepperZ2.push();
  803. #endif
  804. #if AXIS_IS_TMC(Z3)
  805. stepperZ3.push();
  806. #endif
  807. #if AXIS_IS_TMC(Z4)
  808. stepperZ4.push();
  809. #endif
  810. #if AXIS_IS_TMC(I)
  811. stepperI.push();
  812. #endif
  813. #if AXIS_IS_TMC(J)
  814. stepperJ.push();
  815. #endif
  816. #if AXIS_IS_TMC(K)
  817. stepperK.push();
  818. #endif
  819. #if AXIS_IS_TMC(U)
  820. stepperU.push();
  821. #endif
  822. #if AXIS_IS_TMC(V)
  823. stepperV.push();
  824. #endif
  825. #if AXIS_IS_TMC(W)
  826. stepperW.push();
  827. #endif
  828. #if AXIS_IS_TMC(E0)
  829. stepperE0.push();
  830. #endif
  831. #if AXIS_IS_TMC(E1)
  832. stepperE1.push();
  833. #endif
  834. #if AXIS_IS_TMC(E2)
  835. stepperE2.push();
  836. #endif
  837. #if AXIS_IS_TMC(E3)
  838. stepperE3.push();
  839. #endif
  840. #if AXIS_IS_TMC(E4)
  841. stepperE4.push();
  842. #endif
  843. #if AXIS_IS_TMC(E5)
  844. stepperE5.push();
  845. #endif
  846. #if AXIS_IS_TMC(E6)
  847. stepperE6.push();
  848. #endif
  849. #if AXIS_IS_TMC(E7)
  850. stepperE7.push();
  851. #endif
  852. }
  853. void reset_trinamic_drivers() {
  854. static constexpr bool stealthchop_by_axis[] = LOGICAL_AXIS_ARRAY(
  855. ENABLED(STEALTHCHOP_E),
  856. ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_Z),
  857. ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K),
  858. ENABLED(STEALTHCHOP_U), ENABLED(STEALTHCHOP_V), ENABLED(STEALTHCHOP_W)
  859. );
  860. #if AXIS_IS_TMC(X)
  861. TMC_INIT(X, STEALTH_AXIS_X);
  862. #endif
  863. #if AXIS_IS_TMC(X2)
  864. TMC_INIT(X2, STEALTH_AXIS_X);
  865. #endif
  866. #if AXIS_IS_TMC(Y)
  867. TMC_INIT(Y, STEALTH_AXIS_Y);
  868. #endif
  869. #if AXIS_IS_TMC(Y2)
  870. TMC_INIT(Y2, STEALTH_AXIS_Y);
  871. #endif
  872. #if AXIS_IS_TMC(Z)
  873. TMC_INIT(Z, STEALTH_AXIS_Z);
  874. #endif
  875. #if AXIS_IS_TMC(Z2)
  876. TMC_INIT(Z2, STEALTH_AXIS_Z);
  877. #endif
  878. #if AXIS_IS_TMC(Z3)
  879. TMC_INIT(Z3, STEALTH_AXIS_Z);
  880. #endif
  881. #if AXIS_IS_TMC(Z4)
  882. TMC_INIT(Z4, STEALTH_AXIS_Z);
  883. #endif
  884. #if AXIS_IS_TMC(I)
  885. TMC_INIT(I, STEALTH_AXIS_I);
  886. #endif
  887. #if AXIS_IS_TMC(J)
  888. TMC_INIT(J, STEALTH_AXIS_J);
  889. #endif
  890. #if AXIS_IS_TMC(K)
  891. TMC_INIT(K, STEALTH_AXIS_K);
  892. #endif
  893. #if AXIS_IS_TMC(U)
  894. TMC_INIT(U, STEALTH_AXIS_U);
  895. #endif
  896. #if AXIS_IS_TMC(V)
  897. TMC_INIT(V, STEALTH_AXIS_V);
  898. #endif
  899. #if AXIS_IS_TMC(W)
  900. TMC_INIT(W, STEALTH_AXIS_W);
  901. #endif
  902. #if AXIS_IS_TMC(E0)
  903. TMC_INIT(E0, STEALTH_AXIS_E);
  904. #endif
  905. #if AXIS_IS_TMC(E1)
  906. TMC_INIT(E1, STEALTH_AXIS_E);
  907. #endif
  908. #if AXIS_IS_TMC(E2)
  909. TMC_INIT(E2, STEALTH_AXIS_E);
  910. #endif
  911. #if AXIS_IS_TMC(E3)
  912. TMC_INIT(E3, STEALTH_AXIS_E);
  913. #endif
  914. #if AXIS_IS_TMC(E4)
  915. TMC_INIT(E4, STEALTH_AXIS_E);
  916. #endif
  917. #if AXIS_IS_TMC(E5)
  918. TMC_INIT(E5, STEALTH_AXIS_E);
  919. #endif
  920. #if AXIS_IS_TMC(E6)
  921. TMC_INIT(E6, STEALTH_AXIS_E);
  922. #endif
  923. #if AXIS_IS_TMC(E7)
  924. TMC_INIT(E7, STEALTH_AXIS_E);
  925. #endif
  926. #if USE_SENSORLESS
  927. TERN_(X_SENSORLESS, stepperX.homing_threshold(X_STALL_SENSITIVITY));
  928. TERN_(X2_SENSORLESS, stepperX2.homing_threshold(CAT(TERN(X2_SENSORLESS, X2, X), _STALL_SENSITIVITY)));
  929. TERN_(Y_SENSORLESS, stepperY.homing_threshold(Y_STALL_SENSITIVITY));
  930. TERN_(Y2_SENSORLESS, stepperY2.homing_threshold(CAT(TERN(Y2_SENSORLESS, Y2, Y), _STALL_SENSITIVITY)));
  931. TERN_(Z_SENSORLESS, stepperZ.homing_threshold(Z_STALL_SENSITIVITY));
  932. TERN_(Z2_SENSORLESS, stepperZ2.homing_threshold(CAT(TERN(Z2_SENSORLESS, Z2, Z), _STALL_SENSITIVITY)));
  933. TERN_(Z3_SENSORLESS, stepperZ3.homing_threshold(CAT(TERN(Z3_SENSORLESS, Z3, Z), _STALL_SENSITIVITY)));
  934. TERN_(Z4_SENSORLESS, stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY)));
  935. TERN_(I_SENSORLESS, stepperI.homing_threshold(I_STALL_SENSITIVITY));
  936. TERN_(J_SENSORLESS, stepperJ.homing_threshold(J_STALL_SENSITIVITY));
  937. TERN_(K_SENSORLESS, stepperK.homing_threshold(K_STALL_SENSITIVITY));
  938. TERN_(U_SENSORLESS, stepperU.homing_threshold(U_STALL_SENSITIVITY));
  939. TERN_(V_SENSORLESS, stepperV.homing_threshold(V_STALL_SENSITIVITY));
  940. TERN_(W_SENSORLESS, stepperW.homing_threshold(W_STALL_SENSITIVITY));
  941. #endif
  942. #ifdef TMC_ADV
  943. TMC_ADV()
  944. #endif
  945. stepper.set_directions();
  946. }
  947. // TMC Slave Address Conflict Detection
  948. //
  949. // Conflict detection is performed in the following way. Similar methods are used for
  950. // hardware and software serial, but the implementations are independent.
  951. //
  952. // 1. Populate a data structure with UART parameters and addresses for all possible axis.
  953. // If an axis is not in use, populate it with recognizable placeholder data.
  954. // 2. For each axis in use, static_assert using a constexpr function, which counts the
  955. // number of matching/conflicting axis. If the value is not exactly 1, fail.
  956. #if ANY_AXIS_HAS(HW_SERIAL)
  957. // Hardware serial names are compared as strings, since actually resolving them cannot occur in a constexpr.
  958. // Using a fixed-length character array for the port name allows this to be constexpr compatible.
  959. struct SanityHwSerialDetails { const char port[20]; uint32_t address; };
  960. #define TMC_HW_DETAIL_ARGS(A) TERN(A##_HAS_HW_SERIAL, STRINGIFY(A##_HARDWARE_SERIAL), ""), TERN0(A##_HAS_HW_SERIAL, A##_SLAVE_ADDRESS)
  961. #define TMC_HW_DETAIL(A) { TMC_HW_DETAIL_ARGS(A) }
  962. constexpr SanityHwSerialDetails sanity_tmc_hw_details[] = {
  963. TMC_HW_DETAIL(X), TMC_HW_DETAIL(X2),
  964. TMC_HW_DETAIL(Y), TMC_HW_DETAIL(Y2),
  965. TMC_HW_DETAIL(Z), TMC_HW_DETAIL(Z2), TMC_HW_DETAIL(Z3), TMC_HW_DETAIL(Z4),
  966. TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K), TMC_HW_DETAIL(U), TMC_HW_DETAIL(V), TMC_HW_DETAIL(W),
  967. TMC_HW_DETAIL(E0), TMC_HW_DETAIL(E1), TMC_HW_DETAIL(E2), TMC_HW_DETAIL(E3), TMC_HW_DETAIL(E4), TMC_HW_DETAIL(E5), TMC_HW_DETAIL(E6), TMC_HW_DETAIL(E7)
  968. };
  969. // constexpr compatible string comparison
  970. constexpr bool str_eq_ce(const char * a, const char * b) {
  971. return *a == *b && (*a == '\0' || str_eq_ce(a+1,b+1));
  972. }
  973. constexpr bool sc_hw_done(size_t start, size_t end) { return start == end; }
  974. constexpr bool sc_hw_skip(const char *port_name) { return !(*port_name); }
  975. constexpr bool sc_hw_match(const char *port_name, uint32_t address, size_t start, size_t end) {
  976. return !sc_hw_done(start, end) && !sc_hw_skip(port_name) && (address == sanity_tmc_hw_details[start].address && str_eq_ce(port_name, sanity_tmc_hw_details[start].port));
  977. }
  978. constexpr int count_tmc_hw_serial_matches(const char *port_name, uint32_t address, size_t start, size_t end) {
  979. return sc_hw_done(start, end) ? 0 : ((sc_hw_skip(port_name) ? 0 : (sc_hw_match(port_name, address, start, end) ? 1 : 0)) + count_tmc_hw_serial_matches(port_name, address, start + 1, end));
  980. }
  981. #define TMC_HWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_HARDWARE_SERIAL"
  982. #define SA_NO_TMC_HW_C(A) static_assert(1 >= count_tmc_hw_serial_matches(TMC_HW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_hw_details)), TMC_HWSERIAL_CONFLICT_MSG(A));
  983. SA_NO_TMC_HW_C(X); SA_NO_TMC_HW_C(X2);
  984. SA_NO_TMC_HW_C(Y); SA_NO_TMC_HW_C(Y2);
  985. SA_NO_TMC_HW_C(Z); SA_NO_TMC_HW_C(Z2); SA_NO_TMC_HW_C(Z3); SA_NO_TMC_HW_C(Z4);
  986. SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K); SA_NO_TMC_HW_C(U); SA_NO_TMC_HW_C(V); SA_NO_TMC_HW_C(W);
  987. SA_NO_TMC_HW_C(E0); SA_NO_TMC_HW_C(E1); SA_NO_TMC_HW_C(E2); SA_NO_TMC_HW_C(E3); SA_NO_TMC_HW_C(E4); SA_NO_TMC_HW_C(E5); SA_NO_TMC_HW_C(E6); SA_NO_TMC_HW_C(E7);
  988. #endif
  989. #if ANY_AXIS_HAS(SW_SERIAL)
  990. struct SanitySwSerialDetails { int32_t txpin; int32_t rxpin; uint32_t address; };
  991. #define TMC_SW_DETAIL_ARGS(A) TERN(A##_HAS_SW_SERIAL, A##_SERIAL_TX_PIN, -1), TERN(A##_HAS_SW_SERIAL, A##_SERIAL_RX_PIN, -1), TERN0(A##_HAS_SW_SERIAL, A##_SLAVE_ADDRESS)
  992. #define TMC_SW_DETAIL(A) TMC_SW_DETAIL_ARGS(A)
  993. constexpr SanitySwSerialDetails sanity_tmc_sw_details[] = {
  994. TMC_SW_DETAIL(X), TMC_SW_DETAIL(X2),
  995. TMC_SW_DETAIL(Y), TMC_SW_DETAIL(Y2),
  996. TMC_SW_DETAIL(Z), TMC_SW_DETAIL(Z2), TMC_SW_DETAIL(Z3), TMC_SW_DETAIL(Z4),
  997. TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K), TMC_SW_DETAIL(U), TMC_SW_DETAIL(V), TMC_SW_DETAIL(W),
  998. TMC_SW_DETAIL(E0), TMC_SW_DETAIL(E1), TMC_SW_DETAIL(E2), TMC_SW_DETAIL(E3), TMC_SW_DETAIL(E4), TMC_SW_DETAIL(E5), TMC_SW_DETAIL(E6), TMC_SW_DETAIL(E7)
  999. };
  1000. constexpr bool sc_sw_done(size_t start, size_t end) { return start == end; }
  1001. constexpr bool sc_sw_skip(int32_t txpin) { return txpin < 0; }
  1002. constexpr bool sc_sw_match(int32_t txpin, int32_t rxpin, uint32_t address, size_t start, size_t end) {
  1003. return !sc_sw_done(start, end) && !sc_sw_skip(txpin) && (txpin == sanity_tmc_sw_details[start].txpin || rxpin == sanity_tmc_sw_details[start].rxpin) && (address == sanity_tmc_sw_details[start].address);
  1004. }
  1005. constexpr int count_tmc_sw_serial_matches(int32_t txpin, int32_t rxpin, uint32_t address, size_t start, size_t end) {
  1006. return sc_sw_done(start, end) ? 0 : ((sc_sw_skip(txpin) ? 0 : (sc_sw_match(txpin, rxpin, address, start, end) ? 1 : 0)) + count_tmc_sw_serial_matches(txpin, rxpin, address, start + 1, end));
  1007. }
  1008. #define TMC_SWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_SERIAL_RX_PIN or " STRINGIFY(A) "_SERIAL_TX_PIN"
  1009. #define SA_NO_TMC_SW_C(A) static_assert(1 >= count_tmc_sw_serial_matches(TMC_SW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_sw_details)), TMC_SWSERIAL_CONFLICT_MSG(A));
  1010. SA_NO_TMC_SW_C(X); SA_NO_TMC_SW_C(X2);
  1011. SA_NO_TMC_SW_C(Y); SA_NO_TMC_SW_C(Y2);
  1012. SA_NO_TMC_SW_C(Z); SA_NO_TMC_SW_C(Z2); SA_NO_TMC_SW_C(Z3); SA_NO_TMC_SW_C(Z4);
  1013. SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K); SA_NO_TMC_SW_C(U); SA_NO_TMC_SW_C(V); SA_NO_TMC_SW_C(W);
  1014. SA_NO_TMC_SW_C(E0); SA_NO_TMC_SW_C(E1); SA_NO_TMC_SW_C(E2); SA_NO_TMC_SW_C(E3); SA_NO_TMC_SW_C(E4); SA_NO_TMC_SW_C(E5); SA_NO_TMC_SW_C(E6); SA_NO_TMC_SW_C(E7);
  1015. #endif
  1016. #endif // HAS_TRINAMIC_CONFIG