Compare commits

..

216 Commits

Author SHA1 Message Date
Scott Lahteine d2a0d2c43a Merge branch 'bugfix-2.1.x' into pr/26943 2026-03-25 18:20:53 -05:00
thinkyhead ed66cebb33 [cron] Bump distribution date (2026-03-19) 2026-03-19 06:29:00 +00:00
ellensp e915349bc7 🩹 Fix REPETIER_GCODE M360 (#28353) 2026-03-18 23:44:27 -05:00
Scott Lahteine 02c3bf0302 📝 Fix Thermistor 13 comment
Fixes #28046
2026-03-18 21:38:27 -05:00
Scott Lahteine 6537174e1c 🔨 Tweak config branch choice 2026-03-18 20:01:34 -05:00
thinkyhead 95cbcdc655 [cron] Bump distribution date (2026-03-16) 2026-03-16 06:41:17 +00:00
Axel Sepúlveda 76283bf616 MightyBoard Rev G / H (MakerBot Replicator 2 / 2X) (#28089)
Co-authored-by: ellensp <530024+ellensp@users.noreply.github.com>
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-03-15 20:46:50 -05:00
thinkyhead 0e5da486a8 [cron] Bump distribution date (2026-03-15) 2026-03-15 00:49:35 +00:00
ellensp 6999985333 🧑‍💻 Refactor UBL G29 code (#28299)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-03-13 23:24:15 -05:00
Scott Lahteine 4d0dc3518c 🎨 Fix touch delay defines
Followup to c73245a3d9
2026-03-13 23:19:09 -05:00
Scott Lahteine d9acf9f01f SENSORLESS_HOMING_TEST_MENU_ITEMS 2026-03-13 22:10:27 -05:00
thinkyhead 5eae93e4ab [cron] Bump distribution date (2026-03-14) 2026-03-14 00:40:28 +00:00
Scott Lahteine c73245a3d9 🎨 Touch code formatting 2026-03-13 17:26:55 -05:00
thinkyhead 7a226ad73b [cron] Bump distribution date (2026-03-13) 2026-03-13 12:19:37 +00:00
Andrew 9139c1bd0d 🩹 Fix memory visualizer, ProUI conditionals (#28360) 2026-03-13 02:48:41 -05:00
thinkyhead 7cc8b157c0 [cron] Bump distribution date (2026-03-09) 2026-03-09 00:44:45 +00:00
Scott Lahteine 48b7279b9d 📝 Update rambo test label 2026-03-08 17:54:12 -05:00
Scott Lahteine 33735ffe01 🧑‍💻 ProUI is ExtUI 2026-03-08 17:28:12 -05:00
Andrew 12f0fa1a57 📺 Closer parity with ProUI (#26761)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-03-08 17:09:41 -05:00
Scott Lahteine b869afd4b2 🧑‍💻 Clarify MKS UI flags 2026-03-08 13:31:54 -05:00
thinkyhead a6ebfe14cc [cron] Bump distribution date (2026-02-28) 2026-02-28 00:37:49 +00:00
narno2202 71d5661fe4 🩹 Fix DGUS LCD + FT_MOTION compile (#28322) 2026-02-27 15:29:34 -06:00
schnurly cf347df937 🐛 Fix MKS UI + WiFi consecutive upload file corruption (#28346) 2026-02-27 15:28:06 -06:00
ellensp 10967373aa 🌐 Indonesian, Hindi-Latin (hg) (#28305) 2026-02-27 15:06:25 -06:00
thinkyhead b553c0e62a [cron] Bump distribution date (2026-02-22) 2026-02-22 00:44:01 +00:00
Scott Lahteine da7cfd1551 🧑‍💻 LCD code style 2026-02-20 20:43:54 -06:00
Scott Lahteine ca1dc3e81e 🧑‍💻 Pin comparison 2026-02-20 20:42:53 -06:00
thinkyhead 07b95a3c1b [cron] Bump distribution date (2026-02-21) 2026-02-21 00:40:53 +00:00
Scott Lahteine 63ca8f0a42 🔧 Allow override DOGM FORCE_SOFT_SPI 2026-02-20 15:51:17 -06:00
Scott Lahteine 9fc25dfe29 🧑‍💻 Macro OBJZERO 2026-02-20 13:41:40 -06:00
Scott Lahteine fcf9f67f5f 🧑‍💻 Clarify card dive 2026-02-20 13:41:33 -06:00
thinkyhead 4d41e46481 [cron] Bump distribution date (2026-02-20) 2026-02-20 00:40:56 +00:00
schnurly 58405e3901 🐛 Fix MKS TFT UI filament change resume w/ PARK_HEAD_ON_PAUSE (#28344)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-02-19 15:29:24 -06:00
thinkyhead b7a1abfa2d [cron] Bump distribution date (2026-02-19) 2026-02-19 06:29:39 +00:00
Scott Lahteine 3ec17b3bdc 🧑‍💻 Replace %lu => %" PRIu32 "
Fixes #28325
2026-02-18 19:15:28 -06:00
Scott Lahteine f6eee956a5 Move stm_flash_drive STM32 platform 2026-02-18 19:10:52 -06:00
thinkyhead 55070498db [cron] Bump distribution date (2026-02-18) 2026-02-18 18:22:20 +00:00
Scott Lahteine 55b5971739 ♻️ Motion encapsulation (3) 2026-02-18 07:45:38 -06:00
Scott Lahteine fed6eb36c7 Move BIQU BX STM32 platform 2026-02-16 16:46:50 -06:00
thinkyhead 2a1b3fd181 [cron] Bump distribution date (2026-02-14) 2026-02-14 12:14:21 +00:00
Andrew a74237306f 🐛 Fix ProUI Homing FR edit, etc. (#28336) 2026-02-14 01:23:52 -06:00
narno2202 c50c71a33c ♻️ Motion encapsulation (2) (#28341)
Followup to #27866
2026-02-14 01:05:22 -06:00
thinkyhead ab9e452d40 [cron] Bump distribution date (2026-02-11) 2026-02-11 00:48:18 +00:00
Scott Lahteine 59bcaca96b ♻️ Motion encapsulation (#27866) 2026-02-10 01:16:41 -06:00
ellensp f8cc1a0b4b 🧑‍💻 Memory Map Visualizer (#28301) 2026-02-10 00:45:01 -06:00
thinkyhead ba9606694d [cron] Bump distribution date (2026-02-10) 2026-02-10 00:49:22 +00:00
Scott Lahteine 0aded84207 📝 Update AxisEnum notes 2026-02-09 15:59:05 -06:00
ellensp 097fc30201 🐛 Fix FT Motion motion+dir for endstops (#28326)
Co-Authored-By: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-02-09 15:35:40 -06:00
Scott Lahteine 5b71e64a77 🐛 Fix endstops_trigsteps value 2026-02-09 10:56:22 -06:00
Scott Lahteine eba2e7b669 🧑‍💻 Rename plan pos elements 2026-02-09 10:06:33 -06:00
thinkyhead 0e4d82b680 [cron] Bump distribution date (2026-02-09) 2026-02-09 00:44:53 +00:00
Scott Lahteine bdc57af40c 🌐 Language export -l argument 2026-02-08 14:39:25 -06:00
Scott Lahteine 544f9e6104 ️ Run motion logic before UI 2026-02-08 14:39:25 -06:00
David Buezas e524a98418 ️ Buffer Runtime for FT Motion (#28327) 2026-02-08 14:19:14 -06:00
thinkyhead 4eea9e5d7b [cron] Bump distribution date (2026-02-08) 2026-02-08 06:23:41 +00:00
Scott Lahteine 12ee7e45f1 🎨 Misc. endstop-related tweaks 2026-02-07 19:47:14 -06:00
thinkyhead 8da0d0871c [cron] Bump distribution date (2026-02-07) 2026-02-07 00:40:14 +00:00
ellensp 7f51e49b08 🩹 Fix LED menu conditions (#28304) 2026-02-05 19:52:47 -06:00
thinkyhead 20d035d78c [cron] Bump distribution date (2026-02-06) 2026-02-06 00:40:25 +00:00
Scott Lahteine f9d6093051 🩹 Center UBL measure_business_card_thickness 2026-02-05 17:52:39 -06:00
jaysuk 6561ecfcf5 Mellow Fly E3 Pro V3 (STM32F407VG) (#26214) 2026-02-05 13:37:36 -06:00
thinkyhead a6a5be0ad4 [cron] Bump distribution date (2026-02-03) 2026-02-03 00:56:04 +00:00
Scott Lahteine 643704e318 🩹 Show Linear Advance for FT Motion (#28306)
Followup to 5a0923ed, #21827
2026-02-02 18:40:14 -06:00
Scott Lahteine 488bd82db0 🎨 stepper.ne => stepper.nle 2026-02-02 18:36:12 -06:00
Kadin Le 3f98310004 🐛 Fix FTM Linear Advance toggle (#28311) 2026-02-02 18:07:49 -06:00
thinkyhead 6179563e0b [cron] Bump distribution date (2026-02-02) 2026-02-02 06:31:17 +00:00
Scott Lahteine d92f2e2f20 🌐 Language Export, then Re-import (#28316) 2026-02-01 22:04:14 -06:00
Scott Lahteine 8add6b12f5 🧑‍💻 Language export – LLM translation (#28303) 2026-02-01 21:27:34 -06:00
thinkyhead 18b5301c0d [cron] Bump distribution date (2026-01-28) 2026-01-28 00:35:56 +00:00
narno2202 3f4b22fef5 🩹 Apply 'M493 C' to specified axes (#28241) 2026-01-26 23:54:50 -06:00
Chris e4eb1b5943 🔨 Update HC32 environments (#28286) 2026-01-26 20:00:46 -06:00
thinkyhead 3ac92f243c [cron] Bump distribution date (2026-01-27) 2026-01-27 00:37:53 +00:00
Harald Wagener 384ce42a45 🐛 Fix RP2040 timer trigger, FT Motion (#28288) 2026-01-26 15:48:08 -06:00
thinkyhead 05af2a49ed [cron] Bump distribution date (2026-01-25) 2026-01-25 06:11:36 +00:00
Scott Lahteine c8207fbc15 🔧 No SHAPING_MENU without standard shapers 2026-01-24 23:15:21 -06:00
ellensp b1fe363f2f 🐛 Fix G28 clearance needed check (#28298)
Followup to #28275
2026-01-24 20:23:11 -06:00
thinkyhead 16913e0163 [cron] Bump distribution date (2026-01-23) 2026-01-23 06:12:24 +00:00
Vovodroid 91a91562c2 🔧 Allow FTM + Nonlinear Extrusion (#28250)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-01-22 21:14:42 -06:00
ellensp 2e456cea8f 📝 Fix endif comment (#28293) 2026-01-22 21:11:54 -06:00
ellensp 981f54a78e 🩹 Fix MMU2 build (#28292)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-01-22 21:10:51 -06:00
ellensp a68f7a0426 🔧 Check for maximum NeoPixels (#28276) 2026-01-22 20:06:01 -06:00
David Buezas 99768cffbe ️ FTM: Reuse trapezoid code in other traj. generators (#28249) 2026-01-22 19:59:37 -06:00
Scott Lahteine ae6c9c154c 🔧 Fix some ProUI builds 2026-01-22 18:59:12 -06:00
thinkyhead 5ba219a1d0 [cron] Bump distribution date (2026-01-22) 2026-01-22 18:11:11 +00:00
Andrivet 3ac64db2ae 🐛 Fix TFT LVGL UI + Y-DIR conflict (#28291)
Fixes #22967
2026-01-22 10:41:28 -06:00
thinkyhead fc641d39b6 [cron] Bump distribution date (2026-01-21) 2026-01-21 06:13:25 +00:00
DerAndere 7c29cdb685 SOFT_FEED_HOLD (#28265) 2026-01-20 21:58:28 -06:00
thinkyhead 367e2219e3 [cron] Bump distribution date (2026-01-18) 2026-01-18 06:11:21 +00:00
Scott Lahteine 1f4445a096 🔧 Clarify REINIT_NOISY_LCD warning 2026-01-17 18:44:22 -06:00
thinkyhead ae5ae96e62 [cron] Bump distribution date (2026-01-17) 2026-01-17 06:10:52 +00:00
Andrew 803b78f196 📝 Apply Markdown formatting (#28283) 2026-01-16 19:49:42 -06:00
Andrew dc5fabe3a9 🔨 Update use_example_configs refs (#28285) 2026-01-16 19:43:04 -06:00
thinkyhead 1692996979 [cron] Bump distribution date (2026-01-16) 2026-01-16 06:12:22 +00:00
Scott Lahteine 3791ca788b 🔨 Drop obsolete env STM32F103CB_malyan_maple 2026-01-15 19:31:12 -06:00
Scott Lahteine 4ba13912b7 🔨 Fix build env chitu_f103_maple 2026-01-15 18:31:26 -06:00
thinkyhead 2aa4baa5f8 [cron] Bump distribution date (2026-01-15) 2026-01-15 06:12:17 +00:00
ellensp 834241dfb5 🐛 Fix ADC calculation (#28279)
Followup to 89379cd
2026-01-14 20:19:45 -06:00
thinkyhead d897251c17 [cron] Bump distribution date (2026-01-14) 2026-01-14 00:36:29 +00:00
Scott Lahteine e0f73f51ee 🧑‍💻 Macros *_AXIS_ANY/ALL/NONE (#28275) 2026-01-13 17:50:05 -06:00
David Buezas a73b08eba5 🐛 Fix FTM E value overflow; 🔧 FTM_DIR_CHANGE_HOLD_* (#28277)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-01-13 17:27:20 -06:00
Reimnop 2048e8b173 Permit disable REINIT_NOISY_LCD (#28273)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-01-13 16:28:16 -06:00
thinkyhead c1e01eee35 [cron] Bump distribution date (2026-01-12) 2026-01-12 00:37:14 +00:00
Scott Lahteine 3bf6b3dee9 🐛 Fix FT Motion TMC2208 shutdown (2)
Followup to #28257
2026-01-11 01:06:49 -06:00
thinkyhead 6ec2a395e1 [cron] Bump distribution date (2026-01-11) 2026-01-11 06:11:29 +00:00
Scott Lahteine 468ad6f79e 🎨 Apostrophe 2026-01-10 20:24:13 -06:00
narno2202 a5a6732508 🐛 Fix FT Motion M496 processing, etc. (#28261)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-01-10 19:57:20 -06:00
David Buezas 1e457650f3 🐛 Fix FT Motion TMC2208 shutdown (#28257)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-01-10 19:44:51 -06:00
thinkyhead 75f0939b44 [cron] Bump distribution date (2026-01-10) 2026-01-10 01:14:45 +00:00
narno2202 33cd1e0767 🐛 Fix, optimize FTM Resonance Test (#28266) 2026-01-09 17:30:20 -06:00
Scott Lahteine 561c409d59 🧑‍💻 Adjust CardReader conditions 2026-01-09 15:58:58 -06:00
Scott Lahteine 606b6fe64f 🌐 Wide Preheat strings 2026-01-09 15:58:58 -06:00
thinkyhead 4447c3e445 [cron] Bump distribution date (2026-01-09) 2026-01-09 00:34:57 +00:00
Scott Lahteine e966b83bb2 🧑‍💻 Casual types casting 2026-01-08 16:40:22 -06:00
Scott Lahteine ffa5adb077 🩹 Skip One-Click on EEPROM error (#28260)
Fixes #28095
2026-01-08 16:37:44 -06:00
Scott Lahteine f2532ec07a 📝 README (and other .md) updates (#28272) 2026-01-08 16:27:51 -06:00
thinkyhead bc97723e02 [cron] Bump distribution date (2026-01-08) 2026-01-08 06:12:37 +00:00
ellensp 65b62a900f 🔨 More specific preprocess exception (#28256)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-01-07 22:20:53 -06:00
thinkyhead e61469f8c1 [cron] Bump distribution date (2026-01-05) 2026-01-05 00:38:17 +00:00
ellensp 4489832bf3 AtomStack FB5 V2 board (#28242) 2026-01-04 17:52:38 -06:00
ellensp 868843fc89 🔧 Creality 4.2.5 FAN1/2 and LED pins (#28232) 2026-01-04 17:45:51 -06:00
ellensp 5cb9474a7d 🧑‍💻 Old macros cleanup (2) (#28262)
Followup to ba8b685
2026-01-04 17:42:38 -06:00
narno2202 777bc842de ️ Optimize FTM resonance test (#28263)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2026-01-04 17:17:01 -06:00
thinkyhead 04416f8cc3 [cron] Bump distribution date (2025-12-30) 2025-12-30 12:13:53 +00:00
David Buezas d9ed6f0e5f 🩹 Ensure safe change of XYZ smoothing (#28247) 2025-12-30 02:40:40 -06:00
thinkyhead c45354a38c [cron] Bump distribution date (2025-12-25) 2025-12-25 00:34:04 +00:00
Scott Lahteine 3ac9068e0e 🔨 Add build_example --noxfer flag 2025-12-24 17:02:28 -06:00
Scott Lahteine 4fccfa14e9 🔨 Match build env index, skip "_xfer" in MANY loop 2025-12-24 12:25:44 -06:00
thinkyhead d22e61a12c [cron] Bump distribution date (2025-12-23) 2025-12-23 00:34:00 +00:00
ellensp a595c48526 🔨 Pins 'find.py' script for Windows (#28195) 2025-12-22 14:41:21 +00:00
thinkyhead 0ca11bc2f0 [cron] Bump distribution date (2025-12-22) 2025-12-22 00:36:26 +00:00
Scott Lahteine c346b07b91 🧑‍💻 Make action to Check URLs 2025-12-21 17:45:00 -06:00
Scott Lahteine 8d54de83d3 📝 Update other dead links 2025-12-21 17:40:10 -06:00
Scott Lahteine 6d416b34f6 📝 Update SVG dead links 2025-12-21 17:40:10 -06:00
ellensp aa889ad8d4 🌐 Update Swedish language (#28219) 2025-12-21 13:34:06 -06:00
Scott Lahteine e08f8498d2 🔧 Update settings sections (#28240) 2025-12-21 00:42:28 -06:00
thinkyhead f8c6ba224f [cron] Bump distribution date (2025-12-21) 2025-12-21 00:37:13 +00:00
Scott Lahteine cc3269a50b 🩹 Use E_TERN_ macros 2025-12-19 23:42:38 -06:00
Scott Lahteine b28ad90d0e 📝 Comments for MarlinUI, etc. 2025-12-19 20:08:38 -06:00
Scott Lahteine c81e74b478 🩹 FT Motion : Update E index 2025-12-19 20:06:37 -06:00
thinkyhead 574332c3d3 [cron] Bump distribution date (2025-12-20) 2025-12-20 00:32:37 +00:00
David Buezas e561058051 🐛 Fix FT Motion edit with UI (#28233)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-19 17:33:44 -06:00
thinkyhead a47f53b8a6 [cron] Bump distribution date (2025-12-19) 2025-12-19 00:34:07 +00:00
ellensp 1a2bb68f85 ️ RP2040 HAL Improvements (#28215) 2025-12-17 18:56:59 -06:00
thinkyhead fc519143fe [cron] Bump distribution date (2025-12-18) 2025-12-18 00:31:10 +00:00
Scott Lahteine 5a9ce77ab3 🔧 FT Motion keep MULTISTEPPING_LIMIT 2025-12-17 15:31:04 -06:00
Scott Lahteine 47fed759b6 📝 "Hisense" thermistor 13 2025-12-16 20:24:23 -06:00
David Buezas 07565d9016 🚸 Safer FTMotion parameter editing (#28191)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-16 20:05:55 -06:00
thinkyhead b73ebafa0f [cron] Bump distribution date (2025-12-17) 2025-12-17 00:40:16 +00:00
David Buezas 3e6a0ab713 🐛 FT Motion fix and refine (#28220)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-16 17:25:37 -06:00
ellensp ec752068a5 🩹 Fix up SD card sorting (#28218)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-16 00:10:40 -06:00
Andrew 54dfe6237c 🔨 Fix and improve schema.py (#28228) 2025-12-15 23:34:18 -06:00
Scott Lahteine c39f32c542 🧑‍💻 More MString debugging 2025-12-15 22:19:23 -06:00
Scott Lahteine 53c27cdd66 🎨 MMU3 cleanup 2025-12-15 22:19:17 -06:00
thinkyhead 3ba633a9e2 [cron] Bump distribution date (2025-12-16) 2025-12-16 00:34:34 +00:00
narno2202 6cf98d0f82 🩹 Ensure consistent FT Motion TICKS_BITS (#28223)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-15 04:06:08 -06:00
Scott Lahteine 9aade7f5df 🔧 Reduce code for unused shapers
Followup to #28217
2025-12-15 02:04:48 -06:00
Scott Lahteine 0952a372b6 🔨 Preflight check MOTHERBOARD (#28221) 2025-12-14 20:26:08 -06:00
thinkyhead 44948ebc1f [cron] Bump distribution date (2025-12-15) 2025-12-15 00:36:26 +00:00
Scott Lahteine 1b194088e1 🔨 Single precision float (3) 2025-12-14 15:20:29 -06:00
Scott Lahteine f74713da0c 📝 Specify mm for NOZZLE_TO_PROBE_OFFSET 2025-12-13 20:02:38 -06:00
Scott Lahteine 575136a82a 🎨 Clean up HAL/timers 2025-12-13 20:02:34 -06:00
thinkyhead bcece89ad0 [cron] Bump distribution date (2025-12-14) 2025-12-14 00:37:23 +00:00
Scott Lahteine 02e1199d51 🔨 Single precision float (2) 2025-12-12 19:45:18 -06:00
thinkyhead 6f653f5993 [cron] Bump distribution date (2025-12-13) 2025-12-13 00:32:35 +00:00
Scott Lahteine 89379cd373 🔨 Single precision float 2025-12-12 17:29:11 -06:00
Scott Lahteine b99f5c3618 🔧 Group motion conditionals 2025-12-12 17:09:10 -06:00
Harald Wagener e434fd0aef FTM_SHAPER_* options (#28217)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-11 20:50:13 -06:00
thinkyhead 7816f5dc46 [cron] Bump distribution date (2025-12-12) 2025-12-12 00:34:09 +00:00
narno2202 f2ac2e7cad 🚸 Optimize FTM menu code, use some setters (#28170)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-11 16:15:49 -06:00
narno2202 4cd972c3bb 🐛 FT Motion - Set moving_axis_flag for each block (#28214) 2025-12-11 15:33:35 -06:00
David Buezas 9eb82d8894 🐛 Limit FTM reset-on-threshold E pos to maintain precision (#28192) 2025-12-11 15:30:17 -06:00
thinkyhead a889336b25 [cron] Bump distribution date (2025-12-11) 2025-12-11 00:34:17 +00:00
Harald Wagener 9c29c634b7 NO_STANDARD_MOTION (#28212)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-10 18:09:05 -06:00
thinkyhead 6b18b1bb8a [cron] Bump distribution date (2025-12-09) 2025-12-09 06:11:47 +00:00
Scott Lahteine 0e5a4cacf8 🧑‍💻 Remove unused servo fields 2025-12-08 21:04:01 -06:00
Miguel Risco-Castillo 2cee78634c 🎨 e3v2 -> dwin (#28211) 2025-12-08 19:58:13 -06:00
thinkyhead 19d7cd1a16 [cron] Bump distribution date (2025-12-07) 2025-12-07 00:37:23 +00:00
Harald Wagener d56fbe21fc 🩹 Fix FTM without FTM_POLYS build (#28209) 2025-12-06 13:42:52 -06:00
Scott Lahteine d14b8e4435 🔧 Clean up TEMP_SENSOR conditionals, SKRat fix 2025-12-06 12:56:03 -06:00
Naomi Rennie-Waldock ef2fbcd2b6 🔨 Fix configuration.py URL fetch (#28208) 2025-12-06 11:26:21 -06:00
Miguel Risco-Castillo 3551a2613d 🩹 Consistent FTM timer types (#28204)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-06 11:01:43 -06:00
thinkyhead 1acaa6dc15 [cron] Bump distribution date (2025-12-06) 2025-12-06 00:31:28 +00:00
Scott Lahteine f139ffed75 REMAINING_TIME_PRIME 2025-12-05 00:56:33 -06:00
Scott Lahteine 98875d424f 🚸 Show estimated remaining time 2025-12-05 00:56:33 -06:00
Scott Lahteine a995cbef50 🧑‍💻 Seconds units 2025-12-05 00:56:33 -06:00
Scott Lahteine 5f9205ef8f 🚸 Immediate Buttons and Menu Items (2)
Followup to #28180
2025-12-05 00:56:33 -06:00
thinkyhead 54f26e61dc [cron] Bump distribution date (2025-12-05) 2025-12-05 00:33:49 +00:00
Scott Lahteine e42059f34a 🎨 Misc. cleanup Dec 4 2025-12-04 11:57:20 -06:00
thinkyhead e819ba832e [cron] Bump distribution date (2025-12-04) 2025-12-04 00:35:26 +00:00
Scott Lahteine d23ac65dd4 🐛 Fix Controller Fan Soft PWM speed
Co-Authored-By: wrathernaut <97267123+wrathernaut@users.noreply.github.com>
2025-12-03 18:33:01 -06:00
Scott Lahteine 938d3db36f 🎨 PSTR() => F() 2025-12-03 18:10:40 -06:00
Scott Lahteine 4cb827b51e 🧑‍💻 Editorconfig for contributed lib-uhs3 2025-12-03 18:10:40 -06:00
Scott Lahteine 92da094c9f 🧑‍💻 Editorconfig for contributed HAL/DUE/usb 2025-12-03 16:58:27 -06:00
Scott Lahteine 09e943a10c 🧑‍💻 duration_t::remainingEstimate 2025-12-03 00:58:58 -06:00
thinkyhead a6d8c6d5b0 [cron] Bump distribution date (2025-12-03) 2025-12-03 00:32:57 +00:00
Scott Lahteine 3ee18bc667 🧑‍💻 FT Motion accessors, G-code style 2025-12-02 16:10:58 -06:00
Scott Lahteine 291a90ace4 🩹 Trajectory FTM_POLYS followup
Followup to #28197
2025-12-02 16:10:58 -06:00
Andrew dd02b5ff0a 🩹 Fix and clean up some stuff (#28201) 2025-12-02 15:42:25 -06:00
David Buezas 14bed5aee8 ️ FTMotion optimized timing (#28187)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-02 15:35:54 -06:00
Scott Lahteine 0265975178 FT_MOTION > FTM_POLYS (2)
Followup to #28197
2025-12-02 15:16:44 -06:00
Scott Lahteine 61a1c05d3a 🎨 Consistent tests paths 2025-12-02 15:13:07 -06:00
InsanityAutomation bfe9885603 🚸 Extra parsing of safety commands (#26944)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2025-12-02 15:12:35 -06:00
Scott Lahteine e98d36555b some dgus need center 2025-11-17 15:59:06 -06:00
Scott Lahteine e81433f46f apply to IA_CREALITY 2025-11-17 15:50:09 -06:00
Scott Lahteine cf0e921f3e Apply to E3S1PRO 2025-11-17 15:50:09 -06:00
Scott Lahteine 0c98019093 apply to ProUI 2025-11-17 15:50:09 -06:00
Scott Lahteine ba27dce42d apply to DGUS Reloaded 2025-11-17 15:09:50 -06:00
Scott Lahteine 7e5ac3f38f common tramming header 2025-11-17 14:34:06 -06:00
Scott Lahteine 5e3f61cc7c config, sanity, rts 2025-11-10 00:35:14 -06:00
Scott Lahteine 80a1c129f1 Merge remote-tracking branch 'upstream/bugfix-2.1.x' into pr/26943 2025-11-10 00:19:47 -06:00
Scott Lahteine 629d262ed3 fix and clean up 2025-11-10 00:16:47 -06:00
Scott Lahteine df12f6d723 Merge branch 'bugfix-2.1.x' into pr/26943 2025-11-08 17:27:59 -06:00
Scott Lahteine 21499f1c74 tweaks 2025-11-08 17:25:50 -06:00
InsanityAutomation 7d40f2b29d More g30 2024-04-07 14:06:23 -04:00
InsanityAutomation a701b9bc60 tweaks to probe tramming 2024-04-07 14:05:34 -04:00
InsanityAutomation a349550924 Allow bed tramming with probe to automatically calculate points by probe limits 2024-04-07 13:59:48 -04:00
610 changed files with 29654 additions and 25137 deletions
+10 -10
View File
@@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
+58 -53
View File
@@ -11,18 +11,21 @@ The following is a set of guidelines for contributing to Marlin, hosted by the [
[I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question)
[How Can I Contribute?](#how-can-i-contribute)
* [Reporting Bugs](#reporting-bugs)
* [Suggesting Features or Changes](#suggesting-features-or-changes)
* [Your First Code Contribution](#your-first-code-contribution)
* [Pull Requests](#pull-requests)
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Features or Changes](#suggesting-features-or-changes)
- [Your First Code Contribution](#your-first-code-contribution)
- [Pull Requests](#pull-requests)
[Styleguides](#styleguides)
* [Git Commit Messages](#git-commit-messages)
* [C++ Coding Standards](#c++-coding-standards)
* [Documentation Styleguide](#documentation)
- [Git Commit Messages](#git-commit-messages)
- [C++ Coding Standards](#c++-coding-standards)
- [Documentation Styleguide](#documentation)
[Additional Notes](#additional-notes)
* [Issue and Pull Request Labels](#issue-and-pull-request-labels)
- [Issue and Pull Request Labels](#issue-and-pull-request-labels)
## Code of Conduct
@@ -31,6 +34,7 @@ This project and everyone participating in it is governed by the [Marlin Code of
## I don't want to read this whole thing I just have a question!!!
> [!NOTE]
>
> Please don't file an issue to ask a question. You'll get faster results by using the resources below.
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
@@ -43,10 +47,10 @@ We have a Message Board and a Facebook group where our knowledgable user communi
If chat is more your speed, you can join the MarlinFirmware Discord server:
* Use the link https://discord.com/servers/marlin-firmware-461605380783472640 to join up as a General User.
* Even though our Discord is pretty active, it may take a while for community members to respond &mdash; please be patient!
* Use the `#general` channel for general questions or discussion about Marlin.
* Other channels exist for certain topics or are limited to Patrons. Check the channel list.
- Use the link https://discord.com/servers/marlin-firmware-461605380783472640 to join up as a General User.
- Even though our Discord is pretty active, it may take a while for community members to respond &mdash; please be patient!
- Use the `#general` channel for general questions or discussion about Marlin.
- Other channels exist for certain topics or are limited to Patrons. Check the channel list.
## How Can I Contribute?
@@ -57,6 +61,7 @@ This section guides you through submitting a Bug Report for Marlin. Following th
Before creating a Bug Report, please test the "nightly" development branch, as you might find out that you don't need to create one. When you are creating a Bug Report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](ISSUE_TEMPLATE/bug_report.yml), the information it asks for helps us resolve issues faster.
> [!NOTE]
>
> Regressions can happen. If you find a **Closed** issue that seems like your issue, go ahead and open a new issue and include a link to the original issue in the body of your new one. All you need to create a link is the issue number, preceded by #. For example, #8888.
#### How Do I Submit A (Good) Bug Report?
@@ -65,29 +70,29 @@ Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/).
Explain the problem and include additional details to help maintainers reproduce the problem:
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started Marlin, e.g. which command exactly you used in the terminal, or how you started Marlin otherwise. When listing steps, **don't just say what you did, but explain how you did it**. For example, if you moved the cursor to the end of a line, explain if you used the mouse, or a keyboard shortcut or an Marlin command, and if so which one?
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets or log output in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
* **Include detailed log output** especially for probing and leveling. See below for usage of `DEBUG_LEVELING_FEATURE`.
* **Include screenshots, links to videos, etc.** which clearly demonstrate the problem.
* **Include G-code** (if relevant) that reliably causes the problem to show itself.
* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.
- **Use a clear and descriptive title** for the issue to identify the problem.
- **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started Marlin, e.g. which command exactly you used in the terminal, or how you started Marlin otherwise. When listing steps, **don't just say what you did, but explain how you did it**. For example, if you moved the cursor to the end of a line, explain if you used the mouse, or a keyboard shortcut or an Marlin command, and if so which one?
- **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets or log output in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
- **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
- **Explain which behavior you expected to see instead and why.**
- **Include detailed log output** especially for probing and leveling. See below for usage of `DEBUG_LEVELING_FEATURE`.
- **Include screenshots, links to videos, etc.** which clearly demonstrate the problem.
- **Include G-code** (if relevant) that reliably causes the problem to show itself.
- **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.
Provide more context:
* **Can you reproduce the problem with a minimum of options enabled?**
* **Did the problem start happening recently** (e.g. after updating to a new version of Marlin) or was this always a problem?
* If the problem started happening recently, **can you reproduce the problem in an older version of Marlin?** What's the most recent version in which the problem doesn't happen? You can download older versions of Marlin from [the releases page](https://github.com/MarlinFirmware/Marlin/releases).
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
- **Can you reproduce the problem with a minimum of options enabled?**
- **Did the problem start happening recently** (e.g. after updating to a new version of Marlin) or was this always a problem?
- If the problem started happening recently, **can you reproduce the problem in an older version of Marlin?** What's the most recent version in which the problem doesn't happen? You can download older versions of Marlin from [the releases page](https://github.com/MarlinFirmware/Marlin/releases).
- **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
Include details about your configuration and environment:
* **Which version of Marlin are you using?** Marlin's exact version and build date can be seen in the startup message when a host connects to Marlin, or in the LCD Info menu (if enabled).
* **What kind of 3D Printer and electronics are you using**?
* **What kind of add-ons (probe, filament sensor) do you have**?
* **Include your Configuration files.** Make a ZIP file containing `Configuration.h` and `Configuration_adv.h` and drop it on your reply.
- **Which version of Marlin are you using?** Marlin's exact version and build date can be seen in the startup message when a host connects to Marlin, or in the LCD Info menu (if enabled).
- **What kind of 3D Printer and electronics are you using**?
- **What kind of add-ons (probe, filament sensor) do you have**?
- **Include your Configuration files.** Make a ZIP file containing `Configuration.h` and `Configuration_adv.h` and drop it on your reply.
### Suggesting Features or Changes
@@ -97,52 +102,52 @@ Before creating a suggestion, please check [this list](https://github.com/Marlin
#### Before Submitting a Feature Request
* **Check the [Marlin website](https://marlinfw.org/)** for tips — you might discover that the feature is already included. Most importantly, check if you're using [the latest version of Marlin](https://github.com/MarlinFirmware/Marlin/releases) and if you can get the desired behavior by changing [Marlin's config settings](https://marlinfw.org/docs/configuration/configuration.html).
* **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- **Check the [Marlin website](https://marlinfw.org/)** for tips — you might discover that the feature is already included. Most importantly, check if you're using [the latest version of Marlin](https://github.com/MarlinFirmware/Marlin/releases) and if you can get the desired behavior by changing [Marlin's config settings](https://marlinfw.org/docs/configuration/configuration.html).
- **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Feature Request?
Feature Requests are tracked as [GitHub issues](https://guides.github.com/features/issues/). Please follow these guidelines in your request:
* **Use a clear and descriptive title** for the issue to identify the suggestion.
* **Provide a step-by-step description of the requested feature** in as much detail as possible.
* **Provide specific examples to demonstrate the steps**.
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
* **Include screenshots and links to videos** which demonstrate the feature or point out the part of Marlin to which the request is related.
* **Explain why this feature would be useful** to most Marlin users.
* **Name other firmwares that have this feature, if any.**
- **Use a clear and descriptive title** for the issue to identify the suggestion.
- **Provide a step-by-step description of the requested feature** in as much detail as possible.
- **Provide specific examples to demonstrate the steps**.
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
- **Include screenshots and links to videos** which demonstrate the feature or point out the part of Marlin to which the request is related.
- **Explain why this feature would be useful** to most Marlin users.
- **Name other firmwares that have this feature, if any.**
### Your First Code Contribution
Unsure where to begin contributing to Marlin? You can start by looking through these `good-first-issue` and `help-wanted` issues:
* [Beginner issues][good-first-issue] - issues which should only require a few lines of code, and a test or two.
* [Help Wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues.
- [Beginner issues][good-first-issue] - issues which should only require a few lines of code, and a test or two.
- [Help Wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues.
### Pull Requests
Pull Requests should always be targeted to working branches (e.g., `bugfix-2.1.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
Pull Requests should always be targeted to working branches (e.g., `bugfix-2.1.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and GitHub's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
* Fill in [the required template](pull_request_template.md).
* Don't include issue numbers in the PR title.
* Include pictures, diagrams, and links to videos in your Pull Request to demonstrate your changes, if needed.
* Follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website.
* Document new code with clear and concise comments.
* End all files with a newline.
- Fill in [the required template](pull_request_template.md).
- Don't include issue numbers in the PR title.
- Include pictures, diagrams, and links to videos in your Pull Request to demonstrate your changes, if needed.
- Follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website.
- Document new code with clear and concise comments.
- End all files with a newline.
## Styleguides
### Git Commit Messages
* Use the present tense ("Add feature" not "Added feature").
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...").
* Limit the first line to 72 characters or fewer.
* Reference issues and Pull Requests liberally after the first line.
- Use the present tense ("Add feature" not "Added feature").
- Use the imperative mood ("Move cursor to..." not "Moves cursor to...").
- Limit the first line to 72 characters or fewer.
- Reference issues and Pull Requests liberally after the first line.
### C++ Coding Standards
* Please read and follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests.
- Please read and follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests.
### Documentation
* Guidelines for documentation are still under development. In-general, be clear, concise, and to-the-point.
- Guidelines for documentation are still under development. In-general, be clear, concise, and to-the-point.
+12 -7
View File
@@ -1,4 +1,5 @@
SCRIPTS_DIR := buildroot/share/scripts
MAKESCRIPTS_DIR := buildroot/share/make
CONTAINER_RT_BIN := docker
CONTAINER_RT_OPTS := --rm -v $(PWD):/code -v platformio-cache:/root/.platformio
CONTAINER_IMAGE := marlin-dev
@@ -8,9 +9,8 @@ UNIT_TEST_CONFIG ?= default
ifeq ($(OS),Windows_NT)
# Windows: use `where` fall back through the three common names
PYTHON := $(shell which python 2>nul || which python3 2>nul || which py 2>nul)
# Windows: Use cmd tools to find pins files
PINS_RAW := $(shell cmd //c "dir /s /b Marlin\src\pins\*.h 2>nul | findstr /r ".*Marlin\\\\src\\\\pins\\\\.*\\\\pins_.*\.h"")
PINS := $(subst \,/,$(PINS_RAW))
# Windows: Use Python script to find pins files
PINS := $(shell $(PYTHON) $(MAKESCRIPTS_DIR)/find.py Marlin/src/pins -mindepth 2 -name 'pins_*.h')
else
# POSIX: use `command -v` prefer python3 over python
PYTHON := $(shell command -v python3 2>/dev/null || command -v python 2>/dev/null)
@@ -36,6 +36,7 @@ help:
@echo "make validate-lines -j : Validate line endings, fails on trailing whitespace, etc."
@echo "make validate-pins -j : Validate all pins files, fails if any require reformatting"
@echo "make validate-boards -j : Validate boards.h and pins.h for standards compliance"
@echo "make validate-urls : Validate URLs in source files"
@echo "make tests-single-ci : Run a single test from inside the CI"
@echo "make tests-single-local : Run a single test locally"
@echo "make tests-single-local-docker : Run a single test locally, using docker"
@@ -88,7 +89,7 @@ tests-all-local:
@$(PYTHON) -c "import yaml" 2>/dev/null || (echo 'pyyaml module is not installed. Install it with "$(PYTHON) -m pip install pyyaml"' && exit 1)
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
&& for TEST_TARGET in $$($(PYTHON) $(SCRIPTS_DIR)/get_test_targets.py) ; do \
&& for TEST_TARGET in $$($(PYTHON) $(MAKESCRIPTS_DIR)/get_test_targets.py) ; do \
if [ "$$TEST_TARGET" = "linux_native" ] && [ "$$(uname)" = "Darwin" ]; then \
echo "Skipping tests for $$TEST_TARGET on macOS" ; \
continue ; \
@@ -151,7 +152,7 @@ validate-pins: format-pins
@echo "Validating pins files"
@git diff --exit-code || (git status && echo "\nError: Pins files are not formatted correctly. Run \"make format-pins\" to fix.\n" && exit 1)
.PHONY: format-lines validate-lines
.PHONY: format-lines validate-lines validate-urls
format-lines:
@echo "Formatting all sources"
@@ -160,7 +161,11 @@ format-lines:
validate-lines:
@echo "Validating text formatting"
@npx prettier --check . --editorconfig --object-wrap preserve
@npx prettier --check . --editorconfig --object-wrap preserve --prose-wrap never
validate-urls:
@echo "Checking URLs in source files"
@$(MAKESCRIPTS_DIR)/check-urls.sh
BOARDS_FILE := Marlin/src/core/boards.h
@@ -168,4 +173,4 @@ BOARDS_FILE := Marlin/src/core/boards.h
validate-boards:
@echo "Validating boards.h file"
@$(PYTHON) $(SCRIPTS_DIR)/validate_boards.py $(BOARDS_FILE) || (echo "\nError: boards.h file is not valid. Please check and correct it.\n" && exit 1)
@$(PYTHON) $(MAKESCRIPTS_DIR)/validate_boards.py $(BOARDS_FILE) || (echo "\nError: boards.h file is not valid. Please check and correct it.\n" && exit 1)
+26 -16
View File
@@ -61,7 +61,7 @@
// @section info
// Author info of this build printed to the host during boot and M115
#define STRING_CONFIG_H_AUTHOR "(none, default config)" // Original author or contributor.
#define STRING_CONFIG_H_AUTHOR "(MarlinFirmware)" // Original author or contributor.
//#define CUSTOM_VERSION_FILE Version.h // Path from the root directory (no quotes)
// @section machine
@@ -468,7 +468,7 @@
//===========================================================================
//============================= Thermal Settings ============================
//===========================================================================
// @section temperature
// @section temperature sensors
/**
* Temperature Sensors:
@@ -500,8 +500,8 @@
* 10 : 100kΩ RS PRO 198-961
* 11 : 100kΩ Keenovo AC silicone mats, most Wanhao i3 machines - beta 3950, 1%
* 12 : 100kΩ Vishay 0603 SMD NTCS0603E3104FXT (#8) - calibrated for Makibox hot bed
* 13 : 100kΩ Hisens up to 300°C - for "Simple ONE" & "All In ONE" hotend - beta 3950, 1%
* 14 : 100kΩ (R25), 4092K (beta25), 4.7kΩ pull-up, bed thermistor as used in Ender-5 S1
* 13 : 100kΩ Hisense up to 300°C - for "Simple ONE" & "All In ONE" hotend - R25 = 100 kOhm, beta25 = 4100 K, 4.7kΩ pull-up
* 14 : 100kΩ (R25), 4092K (beta25), 4.7kΩ pull-up, bed thermistor (as used in Ender-5 S1)
* 15 : 100kΩ Calibrated for JGAurora A5 hotend
* 17 : 100kΩ Dagoma NTC white thermistor
* 18 : 200kΩ ATC Semitec 204GT-2 Dagoma.Fr - MKS_Base_DKU001327
@@ -652,6 +652,8 @@
#define TEMP_SENSOR_REDUNDANT_MAX_DIFF 10 // (°C) Temperature difference that will trigger a print abort.
#endif
// @section temperature
// Below this temperature the heater will be switched off
// because it probably indicates a broken thermistor wire.
#define HEATER_0_MINTEMP 5
@@ -1661,7 +1663,7 @@
* Nozzle-to-Probe offsets { X, Y, Z }
*
* X and Y offset
* Use a caliper or ruler to measure the distance from the tip of
* Use a caliper or ruler to measure the distance (in mm) from the tip of
* the Nozzle to the center-point of the Probe in the X and Y axes.
*
* Z offset
@@ -1697,7 +1699,7 @@
* | [-] |
* O-- FRONT --+
*/
#define NOZZLE_TO_PROBE_OFFSET { 10, 10, 0 }
#define NOZZLE_TO_PROBE_OFFSET { 10, 10, 0 } // (mm) X, Y, Z distance from Nozzle tip to Probe trigger-point
// Enable and set to use a specific tool for probing. Disable to allow any tool.
#define PROBING_TOOL 0
@@ -1860,15 +1862,12 @@
//#define DISABLE_V
//#define DISABLE_W
// Turn off the display blinking that warns about possible accuracy reduction
//#define DISABLE_REDUCED_ACCURACY_WARNING
// @section extruder
//#define DISABLE_E // Disable the extruder when not stepping
#define DISABLE_OTHER_EXTRUDERS // Keep only the active extruder enabled
// @section motion
// @section stepper drivers
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
#define INVERT_X_DIR false
@@ -1881,8 +1880,6 @@
//#define INVERT_V_DIR false
//#define INVERT_W_DIR false
// @section extruder
// For direct drive extruder v9 set to true, for geared extruder set to false.
#define INVERT_E0_DIR false
#define INVERT_E1_DIR false
@@ -2349,7 +2346,6 @@
//#define LCD_BED_TRAMMING
#if ENABLED(LCD_BED_TRAMMING)
#define BED_TRAMMING_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
#define BED_TRAMMING_HEIGHT 0.0 // (mm) Z height of nozzle at tramming points
#define BED_TRAMMING_Z_HOP 4.0 // (mm) Z raise between tramming points
//#define BED_TRAMMING_INCLUDE_CENTER // Move to the center after the last corner
@@ -2358,6 +2354,8 @@
#define BED_TRAMMING_PROBE_TOLERANCE 0.1 // (mm)
#define BED_TRAMMING_VERIFY_RAISED // After adjustment triggers the probe, re-probe to verify
//#define BED_TRAMMING_AUDIO_FEEDBACK
#else
#define BED_TRAMMING_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
#endif
/**
@@ -2527,7 +2525,7 @@
//
//#define TEMPERATURE_UNITS_SUPPORT
// @section temperature
// @section temperature presets
//
// Preheat Constants - Up to 10 are supported without changes
@@ -2757,10 +2755,10 @@
*
* Select the language to display on the LCD. These languages are available:
*
* en, an, bg, ca, cz, da, de, el, el_CY, es, eu, fi, fr, gl, hr, hu, it,
* en, an, bg, ca, cz, da, de, el, el_CY, es, eu, fi, fr, gl, hg, hr, hu, id, it,
* jp_kana, ko_KR, nl, pl, pt, pt_br, ro, ru, sk, sv, tr, uk, vi, zh_CN, zh_TW
*
* :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek (Greece)', 'el_CY':'Greek (Cyprus)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hr':'Croatian', 'hu':'Hungarian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ro':'Romanian', 'ru':'Russian', 'sk':'Slovak', 'sv':'Swedish', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)' }
* :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek (Greece)', 'el_CY':'Greek (Cyprus)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hg':'Hinglish (Hindi-Latin)', 'hr':'Croatian', 'hu':'Hungarian', 'id':'Indonesian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ro':'Romanian', 'ru':'Russian', 'sk':'Slovak', 'sv':'Swedish', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)' }
*/
#define LCD_LANGUAGE en
@@ -3045,6 +3043,18 @@
//
//#define FF_INTERFACEBOARD
//
// MightyBoard LCD and Interface
//
//#define MIGHTYBOARD_LCD
#if ENABLED(MIGHTYBOARD_LCD)
//#define MIGHTYBOARD_DEBUG // Lightweight debug output for buttons and encoder
//#define MIGHTYBOARD_DISABLE_ENC_PULLUP // Enable if the encoder button is unreliable
//#define MIGHTYBOARD_BUTTON_PULLUPS // Enable if other buttons are unreliable
//#define MIGHTYBOARD_BACK_STATUS_BUTTONS // Use LEFT/RIGHT buttons for Back / Home.
// Otherwise they act like encoder down / up.
#endif
//
// TFT GLCD Panel with Marlin UI
// Panel connected to main board by SPI or I2C interface.
+124 -30
View File
@@ -1160,9 +1160,26 @@
#if ENABLED(FT_MOTION)
//#define FTM_IS_DEFAULT_MOTION // Use FT Motion as the factory default?
//#define FT_MOTION_MENU // Provide a MarlinUI menu to set M493 and M494 parameters
//#define FTM_HOME_AND_PROBE // Use FT Motion for homing / probing. Disable if FT Motion breaks these functions.
#define FTM_DEFAULT_DYNFREQ_MODE dynFreqMode_DISABLED // Default mode of dynamic frequency calculation. (DISABLED, Z_BASED, MASS_BASED)
//#define NO_STANDARD_MOTION // Disable the standard motion system entirely to save Flash and RAM
#if DISABLED(NO_STANDARD_MOTION)
//#define FTM_HOME_AND_PROBE // Use FT Motion for homing / probing. Disable if FT Motion breaks these functions.
#endif
//#define FTM_DYNAMIC_FREQ // Enable for linear adjustment of XY shaping frequency according to Z or E
#if ENABLED(FTM_DYNAMIC_FREQ)
#define FTM_DEFAULT_DYNFREQ_MODE dynFreqMode_DISABLED // Default mode of dynamic frequency calculation. (DISABLED, Z_BASED, MASS_BASED)
#endif
// Disable unused shapers if you need more free space
#define FTM_SHAPER_ZV
#define FTM_SHAPER_ZVD
#define FTM_SHAPER_ZVDD
#define FTM_SHAPER_ZVDDD
#define FTM_SHAPER_EI
#define FTM_SHAPER_2HEI
#define FTM_SHAPER_3HEI
#define FTM_SHAPER_MZV
#define FTM_DEFAULT_SHAPER_X ftMotionShaper_NONE // Default shaper mode on X axis (NONE, ZV, ZVD, ZVDD, ZVDDD, EI, 2HEI, 3HEI, MZV)
#define FTM_SHAPING_DEFAULT_FREQ_X 37.0f // (Hz) Default peak frequency used by input shapers
@@ -1219,9 +1236,27 @@
#define FTM_BUFFER_SIZE 128 // Window size for trajectory generation, must be a power of 2 (e.g 64, 128, 256, ...)
// The total buffered time in seconds is (FTM_BUFFER_SIZE/FTM_FS)
#define FTM_FS 1000 // (Hz) Frequency for trajectory generation.
#define FTM_STEPPER_FS 2'000'000 // (Hz) Time resolution of stepper I/O update. Shouldn't affect CPU much (slower board testing needed)
#define FTM_MIN_SHAPE_FREQ 20 // (Hz) Minimum shaping frequency, lower consumes more RAM
/**
* TMC2208 / TMC2208_STANDALONE drivers require a brief pause after a DIR change
* to prevent a standstill shutdown when using StealthChop (the standalone default).
* These options cause FT Motion to delay for > 750µs after a DIR change on a given axis.
* Disable only if you are certain that this can never happen with your TMC2208s.
*/
#if AXIS_DRIVER_TYPE_X(TMC2208) || AXIS_DRIVER_TYPE_X(TMC2208_STANDALONE)
#define FTM_DIR_CHANGE_HOLD_X
#endif
#if AXIS_DRIVER_TYPE_Y(TMC2208) || AXIS_DRIVER_TYPE_Y(TMC2208_STANDALONE)
#define FTM_DIR_CHANGE_HOLD_Y
#endif
#if AXIS_DRIVER_TYPE_Z(TMC2208) || AXIS_DRIVER_TYPE_Z(TMC2208_STANDALONE)
#define FTM_DIR_CHANGE_HOLD_Z
#endif
#if HAS_E_DRIVER(TMC2208) || HAS_E_DRIVER(TMC2208_STANDALONE)
#define FTM_DIR_CHANGE_HOLD_E
#endif
#endif // FT_MOTION
/**
@@ -1510,6 +1545,9 @@
// @section lcd
// Turn off the display blinking that warns about possible accuracy reduction
//#define DISABLE_REDUCED_ACCURACY_WARNING
#if HAS_MANUAL_MOVE_MENU
#define MANUAL_FEEDRATE { 50*60, 50*60, 4*60, 2*60 } // (mm/min) Feedrates for manual moves along X, Y, Z, E from panel
#define FINE_MANUAL_MOVE 0.025 // (mm) Smallest manual move (< 0.1mm) applying to Z on most machines
@@ -1579,7 +1617,7 @@
#define XATC_Z_OFFSETS { 0, 0, 0 } // Z offsets for X axis sample points
#endif
#endif
#endif // HAS_BED_PROBE
// Include a page of printer information in the LCD Main Menu
//#define LCD_INFO_MENU
@@ -1763,6 +1801,12 @@
*/
//#define SD_SPI_SPEED SPI_HALF_SPEED
/**
* Reinit the LCD after SD Card insert/remove or when entering the menu.
* Required for some LCDs that use shared SPI with an external SD Card reader.
*/
#define REINIT_NOISY_LCD
// The standard SD detect circuit reads LOW when media is inserted and HIGH when empty.
// Enable this option and set to HIGH if your SD cards are incorrectly detected.
//#define SD_DETECT_STATE HIGH
@@ -1797,6 +1841,14 @@
#define PE_LEDS_COMPLETED_TIME (30*60) // (seconds) Time to keep the LED "done" color before restoring normal illumination
#endif
/**
* Priming for the Remaining Time estimate
* Long processes at the start of a G-code file can skew the Remaining Time estimate.
* Enable these options to start this estimation at a later point in the G-code file.
*/
//#define REMAINING_TIME_PRIME // Provide G-code 'M75 R' to prime the Remaining Time estimate
//#define REMAINING_TIME_AUTOPRIME // Prime the Remaining Time estimate later (e.g., at the end of 'M109')
/**
* Continue after Power-Loss (Creality3D)
*
@@ -1863,17 +1915,21 @@
// SD Card Sorting options
#if ENABLED(SDCARD_SORT_ALPHA)
#define SDSORT_REVERSE false // Default to sorting file names in reverse order.
#define SDSORT_LIMIT 40 // Maximum number of sorted items (10-256). Costs 27 bytes each.
#define SDSORT_FOLDERS -1 // -1=above 0=none 1=below
#define SDSORT_GCODE false // Enable G-code M34 to set sorting behaviors: M34 S<-1|0|1> F<-1|0|1>
#define SDSORT_USES_RAM false // Pre-allocate a static array for faster pre-sorting.
#define SDSORT_USES_STACK false // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
#define SDSORT_CACHE_NAMES false // Keep sorted items in RAM longer for speedy performance. Most expensive option.
#define SDSORT_DYNAMIC_RAM false // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!
#define SDSORT_CACHE_VFATS 2 // Maximum number of 13-byte VFAT entries to use for sorting.
// Note: Only affects SCROLL_LONG_FILENAMES with SDSORT_CACHE_NAMES but not SDSORT_DYNAMIC_RAM.
#define SDSORT_QUICK true // Use Quick Sort as a sorting algorithm. Otherwise use Bubble Sort.
#define SDSORT_QUICK true // Use Quick Sort as a sorting algorithm. Otherwise use Bubble Sort.
#define SDSORT_REVERSE false // Default to sorting file names in reverse order.
#define SDSORT_LIMIT 40 // Maximum number of sorted items (10-256). Costs 27 bytes each.
#define SDSORT_FOLDERS -1 // -1=above 0=none 1=below
#define SDSORT_GCODE false // Enable G-code M34 to set sorting behaviors: M34 S<-1|0|1> F<-1|0|1>
#define SDSORT_USES_STACK false // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
#define SDSORT_USES_RAM false // Pre-allocate a static array for faster pre-sorting.
#if ENABLED(SDSORT_USES_RAM)
#define SDSORT_CACHE_NAMES false // Keep sorted items in RAM longer for speedy performance. Most expensive option.
#if ENABLED(SDSORT_CACHE_NAMES)
#define SDSORT_DYNAMIC_RAM false // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!
#define SDSORT_CACHE_VFATS 2 // Maximum number of 13-byte VFAT entries to use for sorting.
// Note: Only affects SCROLL_LONG_FILENAMES with SDSORT_CACHE_NAMES but not SDSORT_DYNAMIC_RAM.
#endif
#endif
#endif
// Allow international symbols in long filenames. To display correctly, the
@@ -2327,7 +2383,7 @@
//#define WATCHDOG_RESET_MANUAL
#endif
// @section lcd
// @section baby-stepping
/**
* Babystepping enables movement of the axes by tiny increments without changing
@@ -2580,13 +2636,15 @@
#endif
#endif // PTC_PROBE || PTC_BED || PTC_HOTEND
// @section extras
// @section gcode
//
// G60/G61 Position Save and Return
//
//#define SAVED_POSITIONS 1 // Each saved position slot costs 12 bytes
// @section motion
//
// G2/G3 Arc Support
//
@@ -2618,6 +2676,8 @@
*/
//#define DIRECT_STEPPING
// @section calibrate
/**
* G38 Probe Target
*
@@ -2739,6 +2799,11 @@
// Enable this option to collect and display the number
// of dropped bytes after a file transfer to SD.
//#define SERIAL_STATS_DROPPED_RX
// Enable this option to collect and display framing errors.
// Framing errors occur when invalid start/stop bits or other
// serial protocol violations are detected.
//#define SERIAL_STATS_RX_FRAMING_ERRORS
#endif
// Monitor RX buffer usage
@@ -2766,8 +2831,8 @@
*
* Adds support for commands:
* S000 : Report State and Position while moving.
* P000 : Instant Pause / Hold while moving.
* R000 : Resume from Pause / Hold.
* P000 : Instant Pause / Hold while moving. Enable SOFT_FEED_HOLD for soft deceleration.
* R000 : Resume from Pause / Hold. Enable SOFT_FEED_HOLD for soft acceleration.
*
* - During Hold all Emergency Parser commands are available, as usual.
* - Enable NANODLP_Z_SYNC and NANODLP_ALL_AXIS for move command end-state reports.
@@ -2824,7 +2889,7 @@
*/
//#define EXTRA_FAN_SPEED
// @section gcode
// @section firmware retraction
/**
* Firmware-based and LCD-controlled retract
@@ -3544,7 +3609,13 @@
//#define SPI_ENDSTOPS // TMC2130, TMC2240, and TMC5160
//#define IMPROVE_HOMING_RELIABILITY
//#define SENSORLESS_STALLGUARD_DELAY 0 // (ms) Delay to allow drivers to settle
#endif
#if HAS_MARLINUI_MENU
// Convenient homing menu items next to Sensorless Homing edit items
//#define SENSORLESS_HOMING_TEST_MENU_ITEMS
#endif
#endif // SENSORLESS_HOMING || SENSORLESS_PROBING
// @section tmc/config
@@ -3641,7 +3712,7 @@
//#define PHOTO_RETRACT_MM 6.5 // (mm) E retract/recover for the photo move (M240 R S)
// Canon RC-1 or homebrew digital camera trigger
// Data from: https://www.doc-diy.net/photo/rc-1_hacked/
// Data from: https://web.archive.org/web/20250327153953/www.doc-diy.net/photo/rc-1_hacked/
//#define PHOTOGRAPH_PIN 23
// Canon Hack Development Kit
@@ -4212,7 +4283,7 @@
#define BUTTON1_WHEN_PRINTING false // Button allowed to trigger during printing?
#define BUTTON1_GCODE "G28"
#define BUTTON1_DESC "Homing" // Optional string to set the LCD status
//#define BUTTON1_IMMEDIATE // Skip the queue and run the G-code immediately. Rarely needed.
//#define BUTTON1_IMMEDIATE // Skip the queue and execute immediately. Rarely needed.
#endif
//#define BUTTON2_PIN -1
@@ -4278,7 +4349,7 @@
* Developed by Chris Barr at Aus3D.
*
* Wiki: https://wiki.aus3d.com.au/Magnetic_Encoder
* Github: https://github.com/Aus3D/MagneticEncoder
* GitHub: https://github.com/Aus3D/MagneticEncoder
*
* Supplier: https://aus3d.com.au/products/magnetic-encoder-module
* Alternative Supplier: https://reliabuild3d.com/
@@ -4397,15 +4468,38 @@
#endif
/**
* Instant freeze / unfreeze functionality
* Potentially useful for rapid stop that allows being resumed. Halts stepper movement.
* Note this does NOT pause spindles, lasers, fans, heaters or any other auxiliary device.
* @section interface
* Freeze / Unfreeze
*
* Pause / Hold that keeps power available and does not stop the spindle can be initiated by
* the FREEZE_PIN. Halts instantly (default) or performs a soft feed hold that decelerates and
* halts movement at FREEZE_JERK (requires SOFT_FEED_HOLD).
* Motion can be resumed by using the FREEZE_PIN.
*
* NOTE: Controls Laser PWM but does NOT pause Spindle, Fans, Heaters or other devices.
* @section freeze
*/
//#define FREEZE_FEATURE
#if ENABLED(FREEZE_FEATURE)
//#define FREEZE_PIN 41 // Override the default (KILL) pin here
#define FREEZE_STATE LOW // State of pin indicating freeze
//#define FREEZE_PIN -1 // Override the default (KILL) pin here
#define FREEZE_STATE LOW // State of pin indicating freeze
#endif
#if ANY(FREEZE_FEATURE, REALTIME_REPORTING_COMMANDS)
/**
* Command P000 (REALTIME_REPORTING_COMMANDS and EMERGENCY_PARSER) or
* FREEZE_PIN (FREEZE_FEATURE) initiates a soft feed hold that keeps
* power available and does not stop the spindle.
*
* The soft feed hold decelerates and halts movement at FREEZE_JERK.
* Motion can be resumed with command R000 (requires REALTIME_REPORTING_COMMANDS) or
* by using the FREEZE_PIN (requires FREEZE_FEATURE).
*
* NOTE: Affects Laser PWM but DOES NOT pause Spindle, Fans, Heaters or other devices.
*/
//#define SOFT_FEED_HOLD
#if ENABLED(SOFT_FEED_HOLD)
#define FREEZE_JERK 2 // (mm/s) Completely halt when motion has decelerated below this value
#endif
#endif
/**
+2 -2
View File
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
//#define STRING_DISTRIBUTION_DATE "2025-12-02"
//#define STRING_DISTRIBUTION_DATE "2026-03-19"
/**
* The protocol for communication to the host. Protocol indicates communication
@@ -58,7 +58,7 @@
/**
* The SOURCE_CODE_URL is the location where users will find the Marlin Source
* Code which is installed on the device. In most cases —unless the manufacturer
* has a distinct Github fork— the Source Code URL should just be the main
* has a distinct GitHub fork— the Source Code URL should just be the main
* Marlin repository.
*/
//#define SOURCE_CODE_URL "github.com/MarlinFirmware/Marlin"
+1 -1
View File
@@ -96,7 +96,7 @@ void MarlinHAL::init() {
// Might disable other peripherals using the pin; to circumvent that please undefine one of the above things!
// The true culprit is the AVR ArduinoCore that enables peripherals redundantly.
// (USART1 on the GeeeTech GT2560)
// https://www.youtube.com/watch?v=jMgCvRXkexk
// https://youtube.be/jMgCvRXkexk
_ATmega_savePinAlternate(BEEPER_PIN);
OUT_WRITE(BEEPER_PIN, LOW);
+1 -1
View File
@@ -45,7 +45,7 @@
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
#if MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14)
#if MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14, MIGHTYBOARD_REVG)
#define AVR_ATmega2560_FAMILY_PLUS_70 1
#endif
+1 -1
View File
@@ -25,7 +25,7 @@
* Structures for 2560 family boards that use more than 70 pins
*/
#if MB(BQ_ZUM_MEGA_3D, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14)
#if MB(BQ_ZUM_MEGA_3D, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14, MIGHTYBOARD_REVG)
#undef NUM_DIGITAL_PINS
#define NUM_DIGITAL_PINS 85
#elif MB(MIGHTYBOARD_REVE)
+2 -3
View File
@@ -28,7 +28,7 @@
// ------------------------
typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFU
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT16_MAX)
// ------------------------
// Defines
@@ -50,10 +50,9 @@ typedef uint16_t hal_timer_t;
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_PRESCALE 8
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
+1 -1
View File
@@ -24,7 +24,7 @@
/**
* Description: Tone function for Arduino Due and compatible (SAM3X8E)
* Derived from https://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
* Derived from https://forum.arduino.cc/t/arduino-due-and-tone/133302/13
*/
#ifdef ARDUINO_ARCH_SAM
+1 -2
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX)
#define HAL_TIMER_PRESCALER 2
#define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals
@@ -59,7 +59,6 @@ typedef uint32_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+5
View File
@@ -0,0 +1,5 @@
# editorconfig.org
[{*.c,*.cpp,*.h}]
indent_style = tab
indent_size = 4
+2 -1
View File
@@ -271,7 +271,8 @@ void MarlinHAL::adc_start(const pin_t pin) {
uint32_t mv;
esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv);
adc_result = mv * isr_float_t(1023) / isr_float_t(ADC_REFERENCE_VOLTAGE) / isr_float_t(1000);
static constexpr uint32_t adc_divisor = uint32_t((ADC_REFERENCE_VOLTAGE) * 1000UL);
adc_result = (mv * 1023UL) / adc_divisor;
// Change the attenuation level based on the new reading
adc_atten_t atten;
-1
View File
@@ -76,7 +76,6 @@
// Types
// ------------------------
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef int16_t pin_t;
typedef struct pwm_pin {
+1 -1
View File
@@ -24,7 +24,7 @@
/**
* Description: Tone function for ESP32
* Derived from https://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
* Derived from https://forum.arduino.cc/t/arduino-due-and-tone/133302/13
*/
#ifdef ARDUINO_ARCH_ESP32
+28 -23
View File
@@ -156,38 +156,43 @@ void stepperTask(void *parameter) {
while (dma.rw_pos < DMA_SAMPLE_COUNT) {
#if ENABLED(FT_MOTION)
if (using_ftMotion) {
if (using_ftMotion) {
#if ENABLED(FT_MOTION)
if (!nextMainISR) stepper.ftMotion_stepper();
nextMainISR = 0;
}
#endif
#endif
}
else {
if (!using_ftMotion) {
if (!nextMainISR) {
stepper.pulse_phase_isr();
nextMainISR = stepper.block_phase_isr();
}
#if ENABLED(LIN_ADVANCE)
else if (!nextAdvanceISR) {
stepper.advance_isr();
nextAdvanceISR = stepper.la_interval;
#if HAS_STANDARD_MOTION
if (!nextMainISR) {
stepper.pulse_phase_isr();
nextMainISR = stepper.block_phase_isr();
}
#endif
else
i2s_push_sample();
#if ENABLED(LIN_ADVANCE)
else if (!nextAdvanceISR) {
stepper.advance_isr();
nextAdvanceISR = stepper.la_interval;
}
#endif
else
i2s_push_sample();
nextMainISR--;
nextMainISR--;
#if ENABLED(LIN_ADVANCE)
if (nextAdvanceISR == stepper.LA_ADV_NEVER)
nextAdvanceISR = stepper.la_interval;
#if ENABLED(LIN_ADVANCE)
if (nextAdvanceISR == stepper.LA_ADV_NEVER)
nextAdvanceISR = stepper.la_interval;
if (nextAdvanceISR && nextAdvanceISR != stepper.LA_ADV_NEVER)
nextAdvanceISR--;
#endif
#endif // HAS_STANDARD_MOTION
if (nextAdvanceISR && nextAdvanceISR != stepper.LA_ADV_NEVER)
nextAdvanceISR--;
#endif
}
}
}
+1 -1
View File
@@ -57,7 +57,7 @@
#endif
#if ALL(I2S_STEPPER_STREAM, LIN_ADVANCE) && DISABLED(EXPERIMENTAL_I2S_LA)
#error "I2S stream is currently incompatible with LIN_ADVANCE."
#error "I2S stream is currently incompatible with LIN_ADVANCE. Enable EXPERIMENTAL_I2S_LA to proceed anyway."
#endif
#if ALL(I2S_STEPPER_STREAM, PRINTCOUNTER) && PRINTCOUNTER_SAVE_INTERVAL > 0 && DISABLED(PRINTCOUNTER_SYNC)
+1 -2
View File
@@ -30,7 +30,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint64_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFF'FFFF'FFFF'FFFFULL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT64_MAX)
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 0 // Timer Index for Stepper
@@ -66,7 +66,6 @@ typedef uint64_t hal_timer_t;
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define TONE_TIMER_PRESCALE 1000 // Arbitrary value, no idea what i'm doing here
-1
View File
@@ -57,7 +57,6 @@
#define __bss_end __bss_end__
// Types
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef uint8_t pin_t; // Parity with mfl platform
// Servo
+4 -7
View File
@@ -69,10 +69,6 @@
#endif
#endif
#ifndef HAL_TIMER_RATE
#define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
#ifndef STEP_TIMER
#define STEP_TIMER MF_TIMER_STEP
#endif
@@ -121,9 +117,10 @@ void HAL_timer_start(const uint8_t timer_number, const uint32_t frequency) {
if (is_step) {
timer.setPrescaler(STEPPER_TIMER_PRESCALE);
timer.setRolloverValue(_MIN(static_cast<hal_timer_t>(HAL_TIMER_TYPE_MAX),
(HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE)),
TimerFormat::TICK);
timer.setRolloverValue(
_MIN(HAL_TIMER_TYPE_MAX, hal_timer_t((HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE))),
TimerFormat::TICK
);
is_step_timer_initialized = true;
}
else {
+10 -7
View File
@@ -34,21 +34,24 @@
#define MF_TIMER_TEMP 1
#define MF_TIMER_PULSE MF_TIMER_STEP
#define hal_timer_t uint32_t
#define HAL_TIMER_TYPE_MAX UINT16_MAX
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT16_MAX)
extern uint32_t GetStepperTimerClkFreq();
#ifndef HAL_TIMER_RATE
extern uint32_t GetStepperTimerClkFreq();
#define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
// Timer configuration constants
#define STEPPER_TIMER_RATE 2000000
#define TEMP_TIMER_FREQUENCY 1000
// Timer prescaler calculations
#define STEPPER_TIMER_PRESCALE (GetStepperTimerClkFreq() / STEPPER_TIMER_RATE) // Prescaler = 30
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define STEPPER_TIMER_PRESCALE ((HAL_TIMER_RATE) / (STEPPER_TIMER_RATE)) // Prescaler = 30
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
// Pulse Timer (counter) calculations
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
// Timer interrupt priorities
+18 -13
View File
@@ -30,17 +30,17 @@
* it would not make sense to parse G-Code from TMC responses
*/
constexpr bool serial_handles_emergency(int port) {
return false
return (false
#ifdef SERIAL_PORT
|| (SERIAL_PORT) == port
|| (SERIAL_PORT) == port
#endif
#ifdef SERIAL_PORT_2
|| (SERIAL_PORT_2) == port
|| (SERIAL_PORT_2) == port
#endif
#ifdef LCD_SERIAL_PORT
|| (LCD_SERIAL_PORT) == port
|| (LCD_SERIAL_PORT) == port
#endif
;
);
}
//
@@ -48,7 +48,7 @@ constexpr bool serial_handles_emergency(int port) {
//
// serial port where RX and TX use IRQs
#define DEFINE_IRQ_SERIAL_MARLIN(name, n) \
#define DEFINE_IRQ_SERIAL_MARLIN(name, n) \
MSerialT name(serial_handles_emergency(n), \
&USART##n##_config, \
BOARD_USART##n##_TX_PIN, \
@@ -57,7 +57,7 @@ constexpr bool serial_handles_emergency(int port) {
// serial port where RX uses DMA and TX uses IRQs
// all serial ports use DMA1
// since there are 4 USARTs and 4 DMA channels, we can use the USART number as the DMA channel
#define DEFINE_DMA_SERIAL_MARLIN(name, n) \
#define DEFINE_DMA_SERIAL_MARLIN(name, n) \
MSerialT name(serial_handles_emergency(n), \
&USART##n##_config, \
BOARD_USART##n##_TX_PIN, \
@@ -67,12 +67,17 @@ constexpr bool serial_handles_emergency(int port) {
#define DEFINE_SERIAL_MARLIN(name, n) TERN(SERIAL_DMA, DEFINE_DMA_SERIAL_MARLIN(name, n), DEFINE_IRQ_SERIAL_MARLIN(name, n))
DEFINE_SERIAL_MARLIN(MSerial1, 1);
DEFINE_SERIAL_MARLIN(MSerial2, 2);
// TODO: remove this warning when SERIAL_DMA has been tested some more
#if ENABLED(SERIAL_DMA)
#warning "SERIAL_DMA may be unstable on HC32F460."
#if PINS_EXIST(BOARD_USART1_RX, BOARD_USART1_TX)
DEFINE_SERIAL_MARLIN(MSerial1, 1);
#endif
#if PINS_EXIST(BOARD_USART2_RX, BOARD_USART2_TX)
DEFINE_SERIAL_MARLIN(MSerial2, 2);
#endif
#if PINS_EXIST(BOARD_USART3_RX, BOARD_USART3_TX)
DEFINE_SERIAL_MARLIN(MSerial3, 3);
#endif
#if PINS_EXIST(BOARD_USART4_RX, BOARD_USART4_TX)
DEFINE_SERIAL_MARLIN(MSerial4, 4);
#endif
//
+2
View File
@@ -92,3 +92,5 @@ typedef Serial1Class<MarlinSerial> MSerialT;
extern MSerialT MSerial1;
extern MSerialT MSerial2;
extern MSerialT MSerial3;
extern MSerialT MSerial4;
+1 -1
View File
@@ -33,7 +33,7 @@
// Shared by both panic and PostMortem debugging
//
static void minserial_begin() {
#if !WITHIN(SERIAL_PORT, 1, 3)
#if !WITHIN(SERIAL_PORT, 1, 4)
#warning "MinSerial requires a physical UART port for output."
#warning "Disabling MinSerial because the used serial port is not a HW port."
#else
+13 -10
View File
@@ -6,7 +6,7 @@ This document provides notes on the HAL for the HC32F460 MCU.
The HC32F460 HAL is designed to be generic enough for any HC32F460-based board. Adding support for a new HC32F460-based board will require the following steps:
1. Follow [the usual instructions](https://marlinfw.org/docs/development/boards.html#adding-a-new-board) to add a new board to Marlin. (i.e., Add a pins file, edit `boards.h` and `pins.h`, etc.)
1. Follow [the usual instructions](//marlinfw.org/docs/development/boards.html#adding-a-new-board) to add a new board to Marlin. (i.e., Add a pins file, edit `boards.h` and `pins.h`, etc.)
2. Determine the flash size your board uses:
- Examine the board's main processor. (Refer the naming key in `hc32.ini`.)
- Extend the `HC32F460C_common` base env for 256K, or `HC32F460E_common` for 512K.
@@ -50,10 +50,12 @@ SCB->VTOR = ((uint32_t) APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk);
Just searching for `SCB->VTOR` should yield some results. From there, you just need to look at the value that's assigned to it. The example uses `APP_START_ADDRESS`.
> [!NOTE]
>
> Some vendors publish incomplete source code. But they sometimes leave version control related files in the repo, which can contain previous version of files that were removed. Find these by including folders like `.git` or `.svn` in your search.
> [!NOTE]
> The example is based on the [Voxelab-64/Aquila_X2](https://github.com/Voxelab-64/Aquila_X2/blob/d1f23adf96920996b979bc31023d1dce236d05db/firmware/Sources/.svn/pristine/ec/ec82bcb480b511906bc3e6658450e3a803ab9813.svn-base#L96) which actually includes deleted files in its repo.
>
> The example is based on the [Voxelab-64/Aquila_X2](//github.com/Voxelab-64/Aquila_X2/blob/main/firmware/Sources/.svn/pristine/ec/ec82bcb480b511906bc3e6658450e3a803ab9813.svn-base#L96) which actually includes deleted files in its repo.
2. Using a linker script
@@ -72,7 +74,8 @@ MEMORY
```
> [!NOTE]
> This example is based on [Voxelab-64/Aquila_X2](https://github.com/Voxelab-64/Aquila_X2/blob/d1f23adf96920996b979bc31023d1dce236d05db/firmware/Sources/main/hdsc32core/hc32f46x_flash.ld#L55)
>
> This example is based on [Voxelab-64/Aquila_X2](//github.com/Voxelab-64/Aquila_X2/blob/d1f23adf96920996b979bc31023d1dce236d05db/firmware/Sources/main/hdsc32core/hc32f46x_flash.ld#L55)
## Documentation on the HC32F460
@@ -96,15 +99,15 @@ Contact me on Discord (@shadow578) if you need it.
This HAL depends on the following projects:
- [shadow578/platform-hc32f46x](https://github.com/shadow578/platform-hc32f46x) (PlatformIO platform for HC32F46x)
- [shadow578/framework-arduino-hc32f46x](https://github.com/shadow578/framework-arduino-hc32f46x) (Arduino framework for HC32F46x)
- [shadow578/framework-hc32f46x-ddl](https://github.com/shadow578/framework-hc32f46x-ddl) (HC32F46x DDL framework)
- [shadow578/platform-hc32f46x](//github.com/shadow578/platform-hc32f46x) (PlatformIO platform for HC32F46x)
- [shadow578/framework-arduino-hc32f46x](//github.com/shadow578/framework-arduino-hc32f46x) (Arduino framework for HC32F46x)
- [shadow578/framework-hc32f46x-ddl](//github.com/shadow578/framework-hc32f46x-ddl) (HC32F46x DDL framework)
## Credits
This HAL wouldn't be possible without the following projects:
- [Voxelab-64/Aquila_X2](https://github.com/Voxelab-64/Aquila_X2) (original implementation)
- [alexqzd/Marlin-H32](https://github.com/alexqzd/Marlin-H32) (misc. fixes to the original implementation)
- [kgoveas/Arduino-Core-Template](https://github.com/kgoveas/Arduino-Core-Template) (template for Arduino headers)
- [stm32duino/Arduino_Core_STM32](https://github.com/stm32duino/Arduino_Core_STM32) (misc. Arduino functions)
- [Voxelab-64/Aquila_X2](//github.com/Voxelab-64/Aquila_X2) (original implementation)
- [alexqzd/Marlin-H32](//github.com/alexqzd/Marlin-H32) (misc. fixes to the original implementation)
- [kgoveas/Arduino-Core-Template](//github.com/kgoveas/Arduino-Core-Template) (template for Arduino headers)
- [stm32duino/Arduino_Core_STM32](//github.com/stm32duino/Arduino_Core_STM32) (misc. Arduino functions)
+3
View File
@@ -58,6 +58,9 @@
#define USART_RX_DMA_SUPPORT 1
#endif
// SoftwareSerial uses STM32duino API compatibility mode
#define SOFTWARE_SERIAL_STM32_API_COMPATIBILITY 1
//
// Misc.
//
+5 -2
View File
@@ -43,8 +43,11 @@
#error "FAST_PWM_FAN is not yet implemented for this platform."
#endif
#if !defined(HAVE_SW_SERIAL) && HAS_TMC_SW_SERIAL
#error "Missing SoftwareSerial implementation."
// SoftwareSerial introduced in arduino core version 1.3.1
#if ARDUINO_CORE_VERSION_INT < GET_VERSION_INT(1, 3, 1)
#if !defined(HAVE_SW_SERIAL) && HAS_TMC_SW_SERIAL
#error "Missing SoftwareSerial implementation."
#endif
#endif
#if ENABLED(SDCARD_EEPROM_EMULATION) && !HAS_MEDIA
+2 -2
View File
@@ -109,7 +109,7 @@ bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
WITH_RETRY(SDIO_READ_RETRIES, {
en_result_t rc = SDCARD_ReadBlocks(handle, block, 1, dst, SDIO_READ_TIMEOUT);
if (rc == Ok) return true;
printf("SDIO_ReadBlock error (rc=%u; ErrorCode=%lu)\n", rc, handle->u32ErrorCode);
printf("SDIO_ReadBlock error (rc=%u; ErrorCode=%" PRIu32 ")\n", rc, handle->u32ErrorCode);
})
return false;
@@ -122,7 +122,7 @@ bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
WITH_RETRY(SDIO_WRITE_RETRIES, {
en_result_t rc = SDCARD_WriteBlocks(handle, block, 1, (uint8_t *)src, SDIO_WRITE_TIMEOUT);
if (rc == Ok) return true;
printf("SDIO_WriteBlock error (rc=%u; ErrorCode=%lu)\n", rc, handle->u32ErrorCode);
printf("SDIO_WriteBlock error (rc=%u; ErrorCode=%" PRIu32 ")\n", rc, handle->u32ErrorCode);
})
return false;
+1 -1
View File
@@ -204,7 +204,7 @@ void core_hook_sysclock_init() {
power_mode_update_post(F_SYSTEM_CLOCK);
// Verify clocks match expected values (at runtime)
#if ENABLED(MARLIN_DEV_MODE) || ENABLED(ALWAYS_VALIDATE_CLOCKS)
#if ANY(MARLIN_DEV_MODE, ALWAYS_VALIDATE_CLOCKS)
validate_system_clocks();
#endif
+4 -4
View File
@@ -27,7 +27,7 @@
//
typedef Timer0 *timer_channel_t;
typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFU
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT16_MAX)
//
// Timer instances
@@ -69,9 +69,9 @@ extern Timer0 step_timer;
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // Integer 3
// Pulse timer (== stepper timer)
#define MF_TIMER_PULSE MF_TIMER_STEP
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define MF_TIMER_PULSE MF_TIMER_STEP
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
//
// HAL functions
+1 -2
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX)
#define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals
@@ -56,7 +56,6 @@ typedef uint32_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
-4
View File
@@ -40,10 +40,6 @@
* SPI sharing pins. The SCK, MOSI & MISO pins can NOT be set/cleared with
* WRITE nor digitalWrite when the hardware SPI module within the LPC17xx is
* active. If any of these pins are shared then the software SPI must be used.
*
* A more sophisticated hardware SPI can be found at the following link.
* This implementation has not been fully debugged.
* https://github.com/MarlinFirmware/Marlin/tree/071c7a78f27078fd4aee9a3ef365fcf5e143531e
*/
#ifdef TARGET_LPC1768
@@ -22,7 +22,7 @@
/**
* digipot_mcp4451_I2C_routines.c
* Adapted from https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
* Adapted from https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
*/
#ifdef TARGET_LPC1768
@@ -23,7 +23,7 @@
/**
* digipot_mcp4451_I2C_routines.h
* Adapted from https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
* Adapted from https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
*/
#ifdef __cplusplus
+4 -5
View File
@@ -57,7 +57,7 @@
#define _HAL_TIMER_ISR(T) __HAL_TIMER_ISR(T)
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX)
#define HAL_TIMER_RATE ((F_CPU) / 4) // (Hz) Frequency of timers peripherals
@@ -77,12 +77,11 @@ typedef uint32_t hal_timer_t;
#define TEMP_TIMER_RATE 1000000 // 1MHz
#define TEMP_TIMER_FREQUENCY 1000 // (Hz) Temperature ISR frequency
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // (Hz) Frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // (Hz) Frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
@@ -21,7 +21,7 @@
*/
// adapted from I2C/master/master.c example
// https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
// https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
#ifdef TARGET_LPC1768
@@ -41,8 +41,8 @@ if pioutil.is_pio_build():
from ctypes import windll
from pathlib import PureWindowsPath
# getting list of drives
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
# Getting a list of drives
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-windows-drives
drives = []
bitmask = windll.kernel32.GetLogicalDrives()
for letter in string.ascii_uppercase:
+4 -5
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint64_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFF'FFFF'FFFF'FFFFULL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT64_MAX)
#define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals
@@ -55,12 +55,11 @@ typedef uint64_t hal_timer_t;
#define TEMP_TIMER_RATE 1'000'000 // (Hz) Temperature Timer count rate
#define TEMP_TIMER_FREQUENCY 1000 // (Hz) Temperature ISR call frequency
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // (Hz) Frequency of Stepper Timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1'000'000) // (MHz) Stepper Timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // (Hz) Frequency of Stepper Timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1'000'000) // (MHz) Stepper Timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
@@ -21,7 +21,7 @@
*/
// adapted from I2C/master/master.c example
// https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
// https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
#ifdef __PLAT_NATIVE_SIM__
+64 -68
View File
@@ -28,6 +28,7 @@
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
#include "../../module/temperature.h" // For OVERSAMPLENR
extern "C" {
#include "pico/bootrom.h"
@@ -41,50 +42,38 @@ extern "C" {
#include "msc_sd.h"
#endif
// Core 1 watchdog configuration
#define CORE1_MAX_RESETS 5 // Maximum number of Core 1 resets before halting system
// ------------------------
// Public Variables
// ------------------------
volatile uint32_t adc_accumulators[5] = {0}; // Accumulators for oversampling (sum of readings)
volatile uint8_t adc_counts[5] = {0}; // Count of readings accumulated per channel
volatile uint16_t adc_values[5] = {512, 512, 512, 512, 512}; // Final oversampled ADC values (averages) - initialized to mid-range
volatile uint16_t adc_values[5] = {4095, 4095, 4095, 4095, 4095}; // Averaged ADC values (single reading equivalent) - initialized to max (open circuit)
// Core 1 watchdog monitoring
// Core monitoring for watchdog
volatile uint32_t core0_last_heartbeat = 0; // Timestamp of Core 0's last activity
volatile uint32_t core1_last_heartbeat = 0; // Timestamp of Core 1's last activity
volatile bool core1_watchdog_triggered = false; // Flag to indicate Core 1 reset
volatile uint8_t core1_reset_count = 0; // Count of Core 1 resets - halt system if >= CORE1_MAX_RESETS
#if ENABLED(MARLIN_DEV_MODE)
volatile bool core1_freeze_test = false; // Flag to freeze Core 1 for watchdog testing
#endif
volatile uint8_t current_pin;
volatile bool MarlinHAL::adc_has_result;
volatile uint8_t adc_channels_enabled[5] = {false}; // Track which ADC channels are enabled
// Helper function for LED blinking patterns
void blink_led_pattern(uint8_t blink_count, uint32_t blink_duration_us = 100000) {
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
for (uint8_t i = 0; i < blink_count; i++) {
WRITE(LED_PIN, HIGH);
busy_wait_us(blink_duration_us);
WRITE(LED_PIN, LOW);
if (i < blink_count - 1) { // Don't delay after the last blink
busy_wait_us(blink_duration_us);
}
}
#endif
}
// Core 1 ADC reading task - dynamically reads all enabled channels with oversampling
void core1_adc_task() {
static uint32_t last_led_toggle = 0;
const uint8_t OVERSAMPLENR = 16; // Standard Marlin oversampling count
// Signal successful Core 1 startup/restart
SERIAL_ECHO_MSG("Core 1 ADC task started");
static uint32_t last_temp_update = 0;
while (true) {
// Update heartbeat timestamp at start of each scan cycle
core1_last_heartbeat = time_us_32();
#if ENABLED(MARLIN_DEV_MODE)
// Check if we should freeze for watchdog test
if (core1_freeze_test) {
// Stop updating heartbeat and spin forever
while (core1_freeze_test) {
busy_wait_us(100000); // 100ms delay
}
}
#endif
// Scan all enabled ADC channels
for (uint8_t channel = 0; channel < 5; channel++) {
@@ -114,11 +103,9 @@ void core1_adc_task() {
adc_accumulators[channel] += reading;
adc_counts[channel]++;
// Update the averaged value with current accumulation (provides immediate valid data)
adc_values[channel] = adc_accumulators[channel] / adc_counts[channel];
// When we reach the full oversampling count, reset accumulator for next cycle
// When we reach the full oversampling count, calculate averaged value (Marlin ISR does its own oversampling)
if (adc_counts[channel] >= OVERSAMPLENR) {
adc_values[channel] = adc_accumulators[channel] / OVERSAMPLENR; // Return single-reading equivalent
adc_accumulators[channel] = 0;
adc_counts[channel] = 0;
}
@@ -129,17 +116,19 @@ void core1_adc_task() {
}
}
// Core 1 LED indicator: Double blink every 2 seconds to show Core 1 is active
// Core 1 just provides ADC readings - don't trigger temperature updates from here
// Let Marlin's main temperature ISR on Core 0 handle the timing and updates
uint32_t now = time_us_32();
if (now - last_led_toggle >= 2000000) { // 2 seconds
last_led_toggle = now;
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
// Triple blink pattern if watchdog was triggered (shows Core 1 was reset)
if (core1_watchdog_triggered) {
core1_watchdog_triggered = false; // Clear flag
blink_led_pattern(3); // Triple blink for watchdog reset
} else {
blink_led_pattern(2); // Normal double blink
if (now - last_temp_update >= 100000) { // 100ms = 100000 microseconds
last_temp_update = now;
#if ENABLED(USE_WATCHDOG)
// Refresh watchdog here like AVR ISR does indirectly via temperature updates
// Use 2 second delay to allow watchdog_init to be called during boot
static uint32_t core1_start_time = 0;
if (core1_start_time == 0) core1_start_time = time_us_32();
if (time_us_32() - core1_start_time > 2000000) {
hal.watchdog_refresh(1); // Refresh from Core 1
}
#endif
}
@@ -219,37 +208,42 @@ void MarlinHAL::reboot() { watchdog_reboot(0, 0, 1); }
void MarlinHAL::watchdog_init() {
#if DISABLED(DISABLE_WATCHDOG_INIT)
static_assert(WDT_TIMEOUT_US > 1000, "WDT Timeout is too small, aborting");
// Initialize Core 0 heartbeat
core0_last_heartbeat = time_us_32();
watchdog_enable(WDT_TIMEOUT_US/1000, true);
#endif
}
void MarlinHAL::watchdog_refresh() {
// If Core 1 has reset CORE1_MAX_RESETS+ times, stop updating watchdog to halt system
if (core1_reset_count >= CORE1_MAX_RESETS) {
SERIAL_ECHO_MSG("Core 1 reset limit exceeded (", core1_reset_count, " resets) - halting system for safety");
return; // Don't update watchdog - system will halt
void MarlinHAL::watchdog_refresh(const uint8_t core/*=0*/) {
if (core == 0) {
// Update Core 0 heartbeat
core0_last_heartbeat = time_us_32();
// Check if Core 1 is alive (2 second timeout)
if (time_us_32() - core1_last_heartbeat < 2000000) {
watchdog_update(); // Only refresh if Core 1 is responding
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
TOGGLE(LED_PIN); // Heartbeat indicator
#endif
}
// If Core 1 is stuck, don't refresh - let watchdog reset the system
}
else {
// Update Core 1 heartbeat
core1_last_heartbeat = time_us_32();
watchdog_update();
// Check Core 1 watchdog (15 second timeout)
uint32_t now = time_us_32();
if (now - core1_last_heartbeat > 15000000) { // 15 seconds
// Core 1 appears stuck - reset it
multicore_reset_core1();
multicore_launch_core1(core1_adc_task);
core1_watchdog_triggered = true; // Signal for LED indicator
core1_reset_count++; // Increment reset counter
SERIAL_ECHO_MSG("Core 1 ADC watchdog triggered - resetting Core 1 (attempt ", core1_reset_count, ")");
// Check if Core 0 is alive (2 second timeout)
if (time_us_32() - core0_last_heartbeat < 2000000) {
watchdog_update(); // Only refresh if Core 0 is responding
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
TOGGLE(LED_PIN); // Heartbeat indicator
#endif
}
// If Core 0 is stuck, don't refresh - let watchdog reset the system
}
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
// Core 0 LED indicator: Single toggle every watchdog refresh (shows Core 0 activity)
TOGGLE(LED_PIN);
#endif
}
#endif
#endif // USE_WATCHDOG
// ------------------------
// ADC
@@ -290,13 +284,15 @@ void flashFirmware(const int16_t) { hal.reboot(); }
extern "C" {
void * _sbrk(int incr);
extern unsigned int __bss_end__; // end of bss section
extern unsigned int __StackLimit; // Lowest address the stack can grow to
}
// Return free memory between end of heap (or end bss) and whatever is current
// Return free memory between end of heap and start of stack
int freeMemory() {
int free_memory, heap_end = (int)_sbrk(0);
return (int)&free_memory - (heap_end ?: (int)&__bss_end__);
void* heap_end = _sbrk(0);
// Use the linker-provided stack limit instead of a local variable
// __StackLimit is the lowest address the stack can grow to
return (char*)&__StackLimit - (char*)heap_end;
}
#endif // __PLAT_RP2040__
+23 -1
View File
@@ -51,6 +51,28 @@
#include "MarlinSerial.h"
#if !WITHIN(SERIAL_PORT, -1, 1)
#error "SERIAL_PORT must be from -1 to 1."
#endif
#ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 1)
#error "SERIAL_PORT_2 must be from -1 to 1."
#endif
#endif
#ifdef SERIAL_PORT_3
#if !WITHIN(SERIAL_PORT_3, -1, 1)
#error "SERIAL_PORT_3 must be from -1 to 1."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if !WITHIN(LCD_SERIAL_PORT, -1, 1)
#error "LCD_SERIAL_PORT must be from -1 to 1."
#endif
#endif
// ------------------------
// Defines
// ------------------------
@@ -131,7 +153,7 @@ public:
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh(const uint8_t=0) IF_DISABLED(USE_WATCHDOG, {});
static void init(); // Called early in setup()
static void init_board() {} // Called less early in setup()
+9 -9
View File
@@ -44,15 +44,15 @@ static void TXBegin() {
#endif
}
static void TX(char b){
#if SERIAL_PORT == -1
USBSerial
#elif SERIAL_PORT == 0
USBSerial
#elif SERIAL_PORT == 1
Serial1
#endif
.write(b);
static void TX(char b) {
#if SERIAL_PORT == -1
USBSerial
#elif SERIAL_PORT == 0
USBSerial
#elif SERIAL_PORT == 1
Serial1
#endif
.write(b);
}
// A SW memory barrier, to ensure GCC does not overoptimize loops
+34 -4
View File
@@ -30,10 +30,40 @@
#include "../../feature/e_parser.h"
#endif
#define _IMPLEMENT_SERIAL(X) DefaultSerial##X MSerial##X(false, Serial##X)
#define IMPLEMENT_SERIAL(X) _IMPLEMENT_SERIAL(X)
#if WITHIN(SERIAL_PORT, 0, 3)
IMPLEMENT_SERIAL(SERIAL_PORT);
#include <HardwareSerial.h>
// Marlin uses: -1=USB, 0=UART0, 1=UART1
// Arduino uses: Serial=USB, Serial1=UART0, Serial2=UART1
//
// To remap Arduino's numbering to Marlin's convention, we create MarlinSerial0/MarlinSerial1
// as new UART instances with custom pins.
//
// We use distinct names (MarlinSerial0/MarlinSerial1) to avoid symbol conflicts with
// the Arduino framework's pre-defined Serial1/Serial2 objects, which use the same
// underlying hardware (_UART0_ and _UART1_).
// Create Serial0 as UART0 with custom or default pins
arduino::UART MarlinSerial0(
#if PINS_EXIST(SERIAL0_TX, SERIAL0_RX)
SERIAL0_TX_PIN, SERIAL0_RX_PIN // Custom pins for UART0 (Marlin Serial0)
#else
0, 1 // Default UART0 pins (GP0/GP1)
#endif
);
// Not using PINS_EXIST(SERIAL1_TX, SERIAL1_RX) because SERIAL1_TX and SERIAL1_RX
// are defined in framework-arduino-mbed/variants/RASPBERRY_PI_PICO/pins_arduino.h
// Create Serial1 as UART1 with custom or default pins
#if defined(SERIAL1_TX_PIN) && defined(SERIAL1_RX_PIN)
arduino::UART MarlinSerial1(SERIAL1_TX_PIN, SERIAL1_RX_PIN); // Custom pins for UART1 (Marlin Serial1)
#endif
// Wrap the serial ports for Marlin
DefaultSerial0 MSerial0(false, MarlinSerial0); // Marlin Serial0 = UART0
#if defined(SERIAL1_TX_PIN) && defined(SERIAL1_RX_PIN)
DefaultSerial1 MSerial1(false, MarlinSerial1); // Marlin Serial1 = UART1
#endif
DefaultSerial2 MSerial2(false, Serial); // Marlin Serial2 = USB (-1)
#endif // __PLAT_RP2040__
+36 -6
View File
@@ -29,20 +29,50 @@
#include "../../core/serial_hook.h"
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
extern DefaultSerial1 MSerial0;
/**
* Serial Port Configuration for RP2040 (Raspberry Pi Pico)
*
* Arduino-Pico Core Serial Objects:
* - Serial: USB Serial (CDC ACM)
* - Serial1: Hardware UART0
* - Serial2: Hardware UART1
* - SerialUSB: Alias for Serial (USB)
*
* Marlin Serial Wrappers:
* - MSerial0: Wrapper for MarlinSerial0 (UART0), used as Serial0
* - MSerial1: Wrapper for MarlinSerial1 (UART1), declared dynamically if used
* - MSerial2: Wrapper for Serial (USB)
* - USBSerial: Wrapper for SerialUSB (USB)
*
* How it all joins together:
* - Configuration defines SERIAL_PORT, SERIAL_PORT_2, etc. (-1 to 1 range)
* - shared/serial_ports.h maps these to MYSERIAL1, MYSERIAL2, etc.
* - MYSERIAL1 uses MSerialX based on the port index
* - USB ports (-1) use USB_SERIAL_PORT (MSerial2)
*/
// Forward declare our custom Serial objects (defined in MarlinSerial.cpp)
namespace arduino { class UART; }
extern arduino::UART MarlinSerial0; // Always declared
extern arduino::UART MarlinSerial1; // Custom Marlin Serial1 to avoid conflict
typedef ForwardSerial1Class< decltype(MarlinSerial0) > DefaultSerial0;
extern DefaultSerial0 MSerial0;
typedef ForwardSerial1Class< decltype(MarlinSerial1) > DefaultSerial1;
extern DefaultSerial1 MSerial1;
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial2;
extern DefaultSerial2 MSerial2;
typedef ForwardSerial1Class<decltype(SerialUSB)> USBSerialType;
extern USBSerialType USBSerial;
#define Serial0 Serial
#define _DECLARE_SERIAL(X) \
typedef ForwardSerial1Class<decltype(Serial##X)> DefaultSerial##X; \
typedef ForwardSerial1Class<decltype(MarlinSerial##X)> DefaultSerial##X; \
extern DefaultSerial##X MSerial##X
#define DECLARE_SERIAL(X) _DECLARE_SERIAL(X)
#define SERIAL_INDEX_MIN 0
#define SERIAL_INDEX_MAX 6
#define USB_SERIAL_PORT(...) MSerial0
#define SERIAL_INDEX_MAX 1
#define USB_SERIAL_PORT(...) MSerial2
#include "../shared/serial_ports.h"
#if defined(LCD_SERIAL_PORT) && ANY(HAS_DGUS_LCD, EXTENSIBLE_UI)
+1 -1
View File
@@ -137,7 +137,7 @@ int8_t digital_pin_to_analog_pin(pin_t pin) {
}
bool isAnalogPin(const pin_t pin) {
return digital_pin_to_analog_pin(pin) != -1;
return digital_pin_to_analog_pin(pin) >= 0;
}
#define digitalRead_mod(A) extDigitalRead(A) // must use Arduino pin numbers when doing reads
+5 -6
View File
@@ -41,7 +41,7 @@
#define _HAL_TIMER_ISR(T) __HAL_TIMER_ISR(T)
typedef uint64_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFF'FFFF'FFFF'FFFFULL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT64_MAX)
#define HAL_TIMER_RATE (1'000'000ULL) // fixed value as we use a microsecond timesource
#ifndef MF_TIMER_STEP
@@ -65,7 +65,6 @@ typedef uint64_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (10)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
@@ -129,16 +128,16 @@ FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, hal_time
switch (timer_num) {
case 0:
alarm_pool_add_alarm_in_us(HAL_timer_pool_0, compare, HAL_timer_alarm_pool_0_callback, 0, false);
alarm_pool_add_alarm_in_us(HAL_timer_pool_0, compare, HAL_timer_alarm_pool_0_callback, 0, true);
break;
case 1:
alarm_pool_add_alarm_in_us(HAL_timer_pool_1, compare, HAL_timer_alarm_pool_1_callback, 0, false);
alarm_pool_add_alarm_in_us(HAL_timer_pool_1, compare, HAL_timer_alarm_pool_1_callback, 0, true);
break;
case 2:
alarm_pool_add_alarm_in_us(HAL_timer_pool_2, compare, HAL_timer_alarm_pool_2_callback, 0, false);
alarm_pool_add_alarm_in_us(HAL_timer_pool_2, compare, HAL_timer_alarm_pool_2_callback, 0, true);
break;
case 3:
alarm_pool_add_alarm_in_us(HAL_timer_pool_3, compare, HAL_timer_alarm_pool_3_callback, 0, false);
alarm_pool_add_alarm_in_us(HAL_timer_pool_3, compare, HAL_timer_alarm_pool_3_callback, 0, true);
break;
}
}
+1 -1
View File
@@ -32,7 +32,7 @@
* On SAMD21, all pins support external interrupt capability.
* Any pin can be used for external interrupts, but there are some restrictions.
* At most 16 different external interrupts can be used at one time.
* Further, you cant just pick any 16 pins to use. This is because every pin on the SAMD21
* Further, you can't just pick any 16 pins to use. This is because every pin on the SAMD21
* connects to what is called an EXTINT line, and only one pin per EXTINT line can be used for external
* interrupts at a time
*/
+1 -1
View File
@@ -50,7 +50,7 @@
#define getPinByIndex(x) pin_array[x].pin
#define getPinIsDigitalByIndex(x) pin_array[x].is_digital
#define isValidPin(P) (P >= 0 && P < pin_t(NUMBER_PINS_TOTAL))
#define isAnalogPin(P) (digitalPinToAnalogIndex(P) != -1)
#define isAnalogPin(P) (digitalPinToAnalogIndex(P) >= 0)
#define pwm_status(P) digitalPinHasPWM(P)
#define MULTI_NAME_PAD 27 // space needed to be pretty if not first name assigned to a pin
+2 -4
View File
@@ -33,7 +33,7 @@
// --------------------------------------------------------------------------
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX)
#define HAL_TIMER_RATE F_CPU // frequency of timers peripherals
@@ -56,7 +56,6 @@ typedef uint32_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
@@ -143,9 +142,8 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
Rtc * const rtc = timer_config[timer_num].pRtc;
// Clear interrupt flag
rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0| RTC_MODE0_INTFLAG_OVF;
}
else if (timer_config[timer_num].type == TimerType::tcc){
else if (timer_config[timer_num].type == TimerType::tcc) {
Tcc * const tc = timer_config[timer_num].pTcc;
// Clear interrupt flag
tc->INTFLAG.reg = TCC_INTFLAG_OVF;
@@ -25,7 +25,7 @@
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
*/
// adapted from I2C/master/master.c example
// https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
// https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
#ifdef __SAMD21__
+1 -1
View File
@@ -31,7 +31,7 @@
* On SAMD51, all pins support external interrupt capability.
* Any pin can be used for external interrupts, but there are some restrictions.
* At most 16 different external interrupts can be used at one time.
* Further, you cant just pick any 16 pins to use. This is because every pin on the SAMD51
* Further, you can't just pick any 16 pins to use. This is because every pin on the SAMD51
* connects to what is called an EXTINT line, and only one pin per EXTINT line can be used for external
* interrupts at a time
*/
+1 -1
View File
@@ -50,7 +50,7 @@
#define getPinByIndex(x) pin_array[x].pin
#define getPinIsDigitalByIndex(x) pin_array[x].is_digital
#define isValidPin(P) (P >= 0 && P < pin_t(NUMBER_PINS_TOTAL))
#define isAnalogPin(P) (digitalPinToAnalogIndex(P) != -1)
#define isAnalogPin(P) (digitalPinToAnalogIndex(P) >= 0)
#define pwm_status(P) digitalPinHasPWM(P)
#define MULTI_NAME_PAD 27 // space needed to be pretty if not first name assigned to a pin
+1 -2
View File
@@ -32,7 +32,7 @@
// --------------------------------------------------------------------------
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX)
#define HAL_TIMER_RATE F_CPU // frequency of timers peripherals
@@ -55,7 +55,6 @@ typedef uint32_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
-2
View File
@@ -63,8 +63,6 @@
// Types
// ------------------------
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef int32_t pin_t; // Parity with platform/ststm32
class libServo;
+6 -2
View File
@@ -39,12 +39,16 @@ static void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb, u
void MarlinSPI::setClockDivider(uint8_t _div) {
_speed = spi_getClkFreq(&_spi);// / _div;
_clockDivider = _div;
if (_clockDivider != _div) {
_clockDivider = _div;
_mustInit = true;
}
}
void MarlinSPI::begin(void) {
//TODO: only call spi_init if any parameter changed!!
if (!_mustInit) return;
spi_init(&_spi, _speed, _dataMode, _bitOrder, _dataSize);
_mustInit = false;
}
void MarlinSPI::setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc) {
+12 -3
View File
@@ -76,15 +76,23 @@ public:
/* These methods are deprecated and kept for compatibility.
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
*/
void setBitOrder(BitOrder _order) { _bitOrder = _order; }
void setBitOrder(BitOrder order) {
if (_bitOrder == order) return;
_bitOrder = order;
_mustInit = true;
}
void setDataMode(uint8_t _mode) {
switch (_mode) {
void setDataMode(uint8_t mode) {
auto previous_mode = _dataMode;
switch (mode) {
case SPI_MODE0: _dataMode = SPI_MODE_0; break;
case SPI_MODE1: _dataMode = SPI_MODE_1; break;
case SPI_MODE2: _dataMode = SPI_MODE_2; break;
case SPI_MODE3: _dataMode = SPI_MODE_3; break;
default: return;
}
if (previous_mode != _dataMode)
_mustInit = true;
}
void setClockDivider(uint8_t _div);
@@ -104,4 +112,5 @@ private:
pin_t _misoPin;
pin_t _sckPin;
pin_t _ssPin;
bool _mustInit = true;
};
+3 -3
View File
@@ -88,9 +88,9 @@ void USBHost::setUsbTaskState(uint8_t state) {
capacity = info.capacity.block_nbr / 2000;
block_size = info.capacity.block_size;
block_count = info.capacity.block_nbr;
//SERIAL_ECHOLNPGM("info.capacity.block_nbr : %ld\n", info.capacity.block_nbr);
//SERIAL_ECHOLNPGM("info.capacity.block_size: %d\n", info.capacity.block_size);
//SERIAL_ECHOLNPGM("capacity : %d MB\n", capacity);
//SERIAL_ECHOLNPGM("info.capacity.block_nbr : ", info.capacity.block_nbr);
//SERIAL_ECHOLNPGM("info.capacity.block_size: ", info.capacity.block_size);
//SERIAL_ECHOLNPGM("capacity : ", capacity, "MB");
}
};
+1 -5
View File
@@ -81,10 +81,6 @@
#define MCU_TEMP_TIMER 14 // TIM7 is consumed by Software Serial if used.
#endif
#ifndef HAL_TIMER_RATE
#define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
#ifndef STEP_TIMER
#define STEP_TIMER MCU_STEP_TIMER
#endif
@@ -141,7 +137,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
*/
timer_instance[timer_num]->setPrescaleFactor(STEPPER_TIMER_PRESCALE); //the -1 is done internally
timer_instance[timer_num]->setOverflow(_MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE) /* /frequency */), TICK_FORMAT);
timer_instance[timer_num]->setOverflow(_MIN(HAL_TIMER_TYPE_MAX, hal_timer_t((HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE) /* / frequency */)), TICK_FORMAT);
break;
case MF_TIMER_TEMP: // TEMP TIMER - any available 16bit timer
timer_instance[timer_num] = new HardwareTimer(TEMP_TIMER_DEV);
+13 -8
View File
@@ -48,16 +48,21 @@
#define TIMER_INDEX_(T) TIMER##T##_INDEX // TIMER#_INDEX enums (timer_index_t) depend on TIM#_BASE defines.
#define TIMER_INDEX(T) TIMER_INDEX_(T) // Convert Timer ID to HardwareTimer_Handle index.
#define TEMP_TIMER_FREQUENCY 1000 // Temperature::isr() is expected to be called at around 1kHz
#ifndef HAL_TIMER_RATE
extern uint32_t GetStepperTimerClkFreq();
#define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
// TODO: get rid of manual rate/prescale/ticks/cycles taken for procedures in stepper.cpp
#define STEPPER_TIMER_RATE 2000000 // 2 Mhz
extern uint32_t GetStepperTimerClkFreq();
#define STEPPER_TIMER_PRESCALE (GetStepperTimerClkFreq() / (STEPPER_TIMER_RATE))
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
// Timer configuration constants
#define STEPPER_TIMER_RATE 2000000
#define TEMP_TIMER_FREQUENCY 1000 // Temperature::isr() should run at ~1kHz
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
// Timer prescaler calculations
#define STEPPER_TIMER_PRESCALE ((HAL_TIMER_RATE) / (STEPPER_TIMER_RATE))
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (ticks/μs) Stepper Timer ticks per µs
// Pulse Timer (counter) calculations
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+1 -1
View File
@@ -27,7 +27,7 @@
* On STM32F, all pins support external interrupt capability.
* Any pin can be used for external interrupts, but there are some restrictions.
* At most 16 different external interrupts can be used at one time.
* Further, you cant just pick any 16 pins to use. This is because every pin on the STM32
* Further, you can't just pick any 16 pins to use. This is because every pin on the STM32
* connects to what is called an EXTI line, and only one pin per EXTI line can be used for external interrupts at a time
* Check the Reference Manual of the MCU to confirm which line is used by each pin
*/
+2 -2
View File
@@ -84,7 +84,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
timer_set_prescaler(STEP_TIMER_DEV, (uint16_t)(STEPPER_TIMER_PRESCALE - 1));
timer_set_reload(STEP_TIMER_DEV, 0xFFFF);
timer_oc_set_mode(STEP_TIMER_DEV, STEP_TIMER_CHAN, TIMER_OC_MODE_FROZEN, TIMER_OC_NO_PRELOAD); // no output pin change
timer_set_compare(STEP_TIMER_DEV, STEP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (STEPPER_TIMER_RATE) / frequency));
timer_set_compare(STEP_TIMER_DEV, STEP_TIMER_CHAN, _MIN(HAL_TIMER_TYPE_MAX, hal_timer_t((STEPPER_TIMER_RATE) / frequency)));
timer_no_ARR_preload_ARPE(STEP_TIMER_DEV); // Need to be sure no preload on ARR register
timer_attach_interrupt(STEP_TIMER_DEV, STEP_TIMER_CHAN, stepTC_Handler);
HAL_timer_set_interrupt_priority(MF_TIMER_STEP, STEP_TIMER_IRQ_PRIO);
@@ -97,7 +97,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
timer_set_count(TEMP_TIMER_DEV, 0);
timer_set_prescaler(TEMP_TIMER_DEV, (uint16_t)(TEMP_TIMER_PRESCALE - 1));
timer_set_reload(TEMP_TIMER_DEV, 0xFFFF);
timer_set_compare(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (F_CPU) / (TEMP_TIMER_PRESCALE) / frequency));
timer_set_compare(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, _MIN(HAL_TIMER_TYPE_MAX, hal_timer_t((F_CPU) / (TEMP_TIMER_PRESCALE) / frequency)));
timer_attach_interrupt(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, tempTC_Handler);
HAL_timer_set_interrupt_priority(MF_TIMER_TEMP, TEMP_TIMER_IRQ_PRIO);
timer_generate_update(TEMP_TIMER_DEV);
+1 -2
View File
@@ -40,7 +40,7 @@
*/
typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFU
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT16_MAX)
#define HAL_TIMER_RATE uint32_t(F_CPU) // frequency of timers peripherals
@@ -103,7 +103,6 @@ typedef uint16_t hal_timer_t;
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
timer_dev* HAL_get_timer_dev(int number);
-2
View File
@@ -31,7 +31,5 @@ class libServo : public Servo {
void move(const int value);
private:
typedef Servo super;
uint16_t min_ticks;
uint16_t max_ticks;
uint8_t servoIndex; // index into the channel data for this servo
};
+2 -3
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX)
#define FTM0_TIMER_PRESCALE 8
#define FTM1_TIMER_PRESCALE 4
@@ -59,11 +59,10 @@ typedef uint32_t hal_timer_t;
#define TEMP_TIMER_FREQUENCY 1000
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
-2
View File
@@ -35,7 +35,5 @@ class libServo : public Servo {
void move(const int value);
private:
typedef Servo super;
uint16_t min_ticks;
uint16_t max_ticks;
uint8_t servoIndex; // Index into the channel data for this servo
};
+2 -3
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX)
#define FTM0_TIMER_PRESCALE 8
#define FTM1_TIMER_PRESCALE 4
@@ -59,11 +59,10 @@ typedef uint32_t hal_timer_t;
#define TEMP_TIMER_FREQUENCY 1000
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
-2
View File
@@ -37,7 +37,5 @@ class libServo : public PWMServo {
private:
typedef PWMServo super;
uint8_t servoPin;
uint16_t min_ticks;
uint16_t max_ticks;
uint8_t servoIndex; // Index into the channel data for this servo
};
+1 -1
View File
@@ -41,7 +41,7 @@
#error "POSTMORTEM_DEBUGGING is not yet supported for Teensy 4.0/4.1."
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED) || ENABLED(SERIAL_STATS_DROPPED_RX) || ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS) || ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
#if ANY(SERIAL_STATS_MAX_RX_QUEUED, SERIAL_STATS_DROPPED_RX, SERIAL_STATS_RX_FRAMING_ERRORS, SERIAL_STATS_RX_BUFFER_OVERRUNS)
#error "SERIAL_STATS_* features not supported on Teensy 4.0/4.1."
#endif
+5 -6
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFEUL
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX-1UL)
#define GPT_TIMER_RATE (F_CPU / 4) // 150MHz (Can't use F_BUS_ACTUAL because it's extern volatile)
@@ -57,13 +57,12 @@ typedef uint32_t hal_timer_t;
#define TEMP_TIMER_RATE 1000000
#define TEMP_TIMER_FREQUENCY 1000
#define HAL_TIMER_RATE GPT1_TIMER_RATE
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL)
#define STEPPER_TIMER_PRESCALE (GPT_TIMER_RATE / STEPPER_TIMER_RATE)
#define HAL_TIMER_RATE GPT1_TIMER_RATE
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL)
#define STEPPER_TIMER_PRESCALE (GPT_TIMER_RATE / STEPPER_TIMER_RATE)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+1 -1
View File
@@ -85,7 +85,7 @@
}
else {
// Enable DWT counter
// From https://stackoverflow.com/a/41188674/1469714
// From https://stackoverflow.com/questions/36378280/stm32-how-to-enable-dwt-cycle-counter/41188674#41188674
HW_REG(_DEM_CR) = HW_REG(_DEM_CR) | 0x01000000; // Enable trace
#if __CORTEX_M == 7
HW_REG(_LAR) = 0xC5ACCE55; // Unlock access to DWT registers, see https://developer.arm.com/documentation/ihi0029/e/ section B2.3.10
@@ -66,7 +66,7 @@ void * hook_get_usagefault_vector_address(unsigned vtor) { return (void*)(vtor +
void * hook_get_reserved_vector_address(unsigned vtor) { return (void*)(vtor + 0x07); }
// Common exception frame for ARM, should work for all ARM CPU
// Described here (modified for convenience): https://interrupt.memfault.com/blog/cortex-m-fault-debug
// Described here (modified for convenience): https://interrupt.memfault.com/blog/cortex-m-hardfault-debug
struct __attribute__((packed)) ContextStateFrame {
uint32_t r0;
uint32_t r1;
+51 -41
View File
@@ -74,11 +74,11 @@
#endif
#if HAS_DWIN_E3V2
#include "lcd/e3v2/common/encoder.h"
#include "lcd/dwin/common/encoder.h"
#if ENABLED(DWIN_CREALITY_LCD)
#include "lcd/e3v2/creality/dwin.h"
#include "lcd/dwin/creality/dwin.h"
#elif ENABLED(DWIN_CREALITY_LCD_JYERSUI)
#include "lcd/e3v2/jyersui/dwin.h"
#include "lcd/dwin/jyersui/dwin.h"
#elif ENABLED(SOVOL_SV06_RTS)
#include "lcd/sovol_rts/sovol_rts.h"
#endif
@@ -260,6 +260,10 @@
#include "feature/rs485.h"
#endif
#if ENABLED(SOFT_FEED_HOLD)
#include "feature/e_parser.h"
#endif
/**
* Spin in place here while keeping temperature processing alive
*/
@@ -282,7 +286,7 @@ Marlin marlin;
#endif
// Global state of the firmware
MarlinState Marlin::state = MarlinState::MF_INITIALIZING;
MarlinState Marlin::state = MF_INITIALIZING;
// For M109 and M190, this flag may be cleared (by M108) to exit the wait loop
bool Marlin::wait_for_heatup = false;
@@ -370,7 +374,7 @@ void Marlin::startOrResumeJob() {
if (!printingIsPaused()) {
TERN_(GCODE_REPEAT_MARKERS, repeat.reset());
TERN_(CANCEL_OBJECTS, cancelable.reset());
TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator = 0);
TERN_(LCD_SHOW_E_TOTAL, motion.e_move_accumulator = 0);
TERN_(SET_REMAINING_TIME, ui.reset_remaining_time());
TERN_(HAS_PRUSA_MMU3, MMU3::operation_statistics.reset_per_print_stats());
}
@@ -384,7 +388,7 @@ void Marlin::startOrResumeJob() {
card.abortFilePrintNow(TERN_(SD_RESORT, true));
queue.clear();
quickstop_stepper();
motion.quickstop_stepper();
print_job_timer.abort();
@@ -404,8 +408,8 @@ void Marlin::startOrResumeJob() {
}
inline void finishSDPrinting() {
if (queue.enqueue_one(F("M1001"))) { // Keep trying until it gets queued
marlin.setState(MarlinState::MF_RUNNING); // Signal to stop trying
if (queue.enqueue_one(F("M1001"))) { // Keep trying until it gets queued
marlin.setState(MF_RUNNING); // Signal to stop trying
TERN_(PASSWORD_AFTER_SD_PRINT_END, password.lock_machine());
TERN_(DGUS_LCD_UI_MKS, screen.sdPrintingFinished());
}
@@ -514,8 +518,14 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
}
#endif
#if ENABLED(FREEZE_FEATURE)
stepper.frozen = READ(FREEZE_PIN) == FREEZE_STATE;
// Handle the FREEZE button
#if ANY(FREEZE_FEATURE, SOFT_FEED_HOLD)
stepper.set_frozen_triggered(
TERN0(FREEZE_FEATURE, READ(FREEZE_PIN) == FREEZE_STATE)
#if ALL(SOFT_FEED_HOLD, REALTIME_REPORTING_COMMANDS)
|| realtime_ramping_pause_flag
#endif
);
#endif
#if HAS_HOME
@@ -699,19 +709,19 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
#endif
#if ENABLED(EXTRUDER_RUNOUT_PREVENT)
if (thermalManager.degHotend(active_extruder) > (EXTRUDER_RUNOUT_MINTEMP)
if (thermalManager.degHotend(motion.extruder) > (EXTRUDER_RUNOUT_MINTEMP)
&& ELAPSED(ms, gcode.previous_move_ms, SEC_TO_MS(EXTRUDER_RUNOUT_SECONDS))
&& !planner.has_blocks_queued()
) {
const int8_t e_stepper = TERN(HAS_SWITCHING_EXTRUDER, active_extruder >> 1, active_extruder);
const int8_t e_stepper = TERN(HAS_SWITCHING_EXTRUDER, motion.extruder / 2, motion.extruder);
const bool e_off = !stepper.AXIS_IS_ENABLED(E_AXIS, e_stepper);
if (e_off) stepper.ENABLE_EXTRUDER(e_stepper);
const float olde = current_position.e;
current_position.e += EXTRUDER_RUNOUT_EXTRUDE;
line_to_current_position(MMM_TO_MMS(EXTRUDER_RUNOUT_SPEED));
current_position.e = olde;
planner.set_e_position_mm(olde);
const float olde = motion.position.e;
motion.position.e += EXTRUDER_RUNOUT_EXTRUDE;
motion.goto_current_position(MMM_TO_MMS(EXTRUDER_RUNOUT_SPEED));
motion.position.e = olde;
motion.sync_plan_position_e();
planner.synchronize();
if (e_off) stepper.DISABLE_EXTRUDER(e_stepper);
@@ -722,11 +732,11 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
#if ENABLED(DUAL_X_CARRIAGE)
// handle delayed move timeout
if (delayed_move_time && ELAPSED(ms, delayed_move_time) && isRunning()) {
if (motion.delayed_move_time && ELAPSED(ms, motion.delayed_move_time) && isRunning()) {
// travel moves have been received so enact them
delayed_move_time = 0xFFFFFFFFUL; // force moves to be done
destination = current_position;
prepare_line_to_destination();
motion.delayed_move_time = UINT32_MAX; // force moves to be done
motion.destination = motion.position;
motion.prepare_line_to_destination();
planner.synchronize();
}
#endif
@@ -803,10 +813,10 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {
TERN_(MAX7219_DEBUG, max7219.idle_tasks());
// Return if setup() isn't completed
if (state == MarlinState::MF_INITIALIZING) goto IDLE_DONE;
if (is(MF_INITIALIZING)) goto IDLE_DONE;
// TODO: Still causing errors
TERN_(TOOL_SENSOR, (void)check_tool_sensor_stats(active_extruder, true));
TERN_(TOOL_SENSOR, (void)check_tool_sensor_stats(motion.extruder, true));
// Handle filament runout sensors
#if HAS_FILAMENT_SENSOR
@@ -843,6 +853,17 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {
// Update the Beeper queue
TERN_(HAS_BEEPER, buzzer.tick());
// Async Babystepping via the Emergency Parser
#if ALL(EP_BABYSTEPPING, EMERGENCY_PARSER)
babystep.do_ep_steps();
#endif
// Direct Stepping
TERN_(DIRECT_STEPPING, page_manager.write_responses());
// Manage Fixed-time Motion Control
TERN_(FT_MOTION, ftMotion.loop());
// Handle UI input / draw events
#if ENABLED(SOVOL_SV06_RTS)
RTS_Update();
@@ -870,7 +891,7 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {
TERN_(AUTO_REPORT_TEMPERATURES, thermalManager.auto_reporter.tick());
TERN_(AUTO_REPORT_FANS, fan_check.auto_reporter.tick());
TERN_(AUTO_REPORT_SD_STATUS, card.auto_reporter.tick());
TERN_(AUTO_REPORT_POSITION, position_auto_reporter.tick());
TERN_(AUTO_REPORT_POSITION, motion.position_auto_reporter.tick());
TERN_(BUFFER_MONITORING, queue.auto_report_buffer_statistics());
}
#endif
@@ -885,20 +906,9 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {
// Handle Joystick jogging
TERN_(POLL_JOG, joystick.inject_jog_moves());
// Async Babystepping via the Emergency Parser
#if ALL(EP_BABYSTEPPING, EMERGENCY_PARSER)
babystep.do_ep_steps();
#endif
// Direct Stepping
TERN_(DIRECT_STEPPING, page_manager.write_responses());
// Update the LVGL interface
TERN_(HAS_TFT_LVGL_UI, LV_TASK_HANDLER());
// Manage Fixed-time Motion Control
TERN_(FT_MOTION, ftMotion.loop());
IDLE_DONE:
TERN_(MARLIN_DEV_MODE, idle_depth--);
@@ -996,7 +1006,7 @@ void Marlin::stop() {
SERIAL_ERROR_MSG(STR_ERR_STOPPED);
LCD_MESSAGE(MSG_STOPPED);
safe_delay(350); // Allow enough time for messages to get out before stopping
state = MarlinState::MF_STOPPED;
setState(MF_STOPPED);
}
} // Marlin::stop()
@@ -1221,7 +1231,7 @@ void setup() {
#endif
#endif
#if ENABLED(FREEZE_FEATURE)
#if ENABLED(FREEZE_FEATURE) && DISABLED(NO_FREEZE_PIN)
SETUP_LOG("FREEZE_PIN");
#if FREEZE_STATE
SET_INPUT_PULLDOWN(FREEZE_PIN);
@@ -1401,9 +1411,9 @@ void setup() {
SETUP_RUN(touchBt.init());
#endif
TERN_(HAS_HOME_OFFSET, current_position += home_offset); // Init current position based on home_offset
TERN_(HAS_HOME_OFFSET, motion.position += motion.home_offset); // Init current position based on home_offset
sync_plan_position(); // Vital to init stepper/planner equivalent for current_position
motion.sync_plan_position(); // Vital to init stepper/planner equivalent for motion.position
SETUP_RUN(thermalManager.init()); // Initialize temperature loop
@@ -1709,7 +1719,7 @@ void setup() {
SETUP_RUN(ftMotion.init());
#endif
marlin.setState(MarlinState::MF_RUNNING);
marlin.setState(MF_RUNNING);
#ifdef STARTUP_TUNE
// Play a short startup tune before continuing.
@@ -1741,7 +1751,7 @@ void loop() {
#if HAS_MEDIA
if (card.flag.abort_sd_printing) abortSDPrinting();
if (marlin.is(MarlinState::MF_SD_COMPLETE)) finishSDPrinting();
if (marlin.is(MF_SD_COMPLETE)) finishSDPrinting();
#endif
queue.advance();
+3 -3
View File
@@ -28,7 +28,7 @@
#include <stdlib.h>
// Global State of the firmware
enum class MarlinState : uint8_t {
enum MarlinState : uint8_t {
MF_INITIALIZING = 0,
MF_STOPPED,
MF_KILLED,
@@ -54,8 +54,8 @@ public:
static MarlinState state;
static void setState(const MarlinState s) { state = s; }
static bool is(const MarlinState s) { return state == s; }
static bool isStopped() { return is(MarlinState::MF_STOPPED); }
static bool isRunning() { return state >= MarlinState::MF_RUNNING; }
static bool isStopped() { return is(MF_STOPPED); }
static bool isRunning() { return state >= MF_RUNNING; }
static bool printingIsActive();
static bool printJobOngoing();
+13 -10
View File
@@ -187,6 +187,7 @@
#define BOARD_MALYAN_M180 1333 // Malyan M180 Mainboard Version 2 (no display function, direct G-code only)
#define BOARD_PROTONEER_CNC_SHIELD_V3 1334 // Mega controller & Protoneer CNC Shield V3.00
#define BOARD_WEEDO_62A 1335 // WEEDO 62A board (TINA2, Monoprice Cadet, etc.)
#define BOARD_MIGHTYBOARD_REVG 1336 // Makerbot Mightyboard Revision G and H
//
// ATmega1281, ATmega2561
@@ -419,6 +420,7 @@
#define BOARD_MD_D301 5068 // Mingda D2 DZ301 V1.0 (STM32F103ZE)
#define BOARD_VOXELAB_AQUILA 5069 // Voxelab Aquila V1.0.0/V1.0.1 (GD32F103RC / N32G455RE / STM32F103RE)
#define BOARD_SPRINGER_CONTROLLER 5070 // ORCA 3D SPRINGER Modular Controller (STM32F103VC)
#define BOARD_ATOMSTACK_FB5_V2 5071 // Atomstack FB5 V2.0 (STM32F103RCT6)
//
// ARM Cortex-M4F
@@ -483,16 +485,17 @@
#define BOARD_BLACKPILL_CUSTOM 5249 // Custom board based on STM32F401CDU6.
#define BOARD_I3DBEEZ9_V1 5250 // I3DBEEZ9 V1 (STM32F407ZG)
#define BOARD_MELLOW_FLY_E3_V2 5251 // Mellow Fly E3 V2 (STM32F407VG)
#define BOARD_BLACKBEEZMINI_V1 5252 // BlackBeezMini V1 (STM32F401CCU6)
#define BOARD_XTLW_CLIMBER_8TH 5253 // XTLW Climber-8th (STM32F407VGT6)
#define BOARD_FLY_RRF_E3_V1 5254 // Fly RRF E3 V1.0 (STM32F407VG)
#define BOARD_FLY_SUPER8 5255 // Fly SUPER8 (STM32F407ZGT6)
#define BOARD_FLY_D8 5256 // FLY D8 (STM32F407VG)
#define BOARD_FLY_CDY_V3 5257 // FLY CDY V3 (STM32F407VGT6)
#define BOARD_ZNP_ROBIN_NANO 5258 // Elegoo Neptune 2 v1.2 board
#define BOARD_ZNP_ROBIN_NANO_V1_3 5259 // Elegoo Neptune 2 v1.3 board
#define BOARD_MKS_NEPTUNE_X 5260 // Elegoo Neptune X
#define BOARD_MKS_NEPTUNE_3 5261 // Elegoo Neptune 3
#define BOARD_MELLOW_FLY_E3_PRO_V3 5252 // Mellow Fly E3 Pro V3 (STM32F407VG)
#define BOARD_BLACKBEEZMINI_V1 5253 // BlackBeezMini V1 (STM32F401CCU6)
#define BOARD_XTLW_CLIMBER_8TH 5254 // XTLW Climber-8th (STM32F407VGT6)
#define BOARD_FLY_RRF_E3_V1 5255 // Fly RRF E3 V1.0 (STM32F407VG)
#define BOARD_FLY_SUPER8 5256 // Fly SUPER8 (STM32F407ZGT6)
#define BOARD_FLY_D8 5257 // FLY D8 (STM32F407VG)
#define BOARD_FLY_CDY_V3 5258 // FLY CDY V3 (STM32F407VGT6)
#define BOARD_ZNP_ROBIN_NANO 5259 // Elegoo Neptune 2 v1.2 board
#define BOARD_ZNP_ROBIN_NANO_V1_3 5260 // Elegoo Neptune 2 v1.3 board
#define BOARD_MKS_NEPTUNE_X 5261 // Elegoo Neptune X
#define BOARD_MKS_NEPTUNE_3 5262 // Elegoo Neptune 3
//
// Other ARM Cortex-M4
+1 -1
View File
@@ -41,6 +41,6 @@ private:
SERIAL_ECHO(fpre);
if (the_msg) SERIAL_ECHO(C(' '), the_msg);
SERIAL_CHAR(' ');
print_xyz(xyz_pos_t(current_position));
print_xyz(xyz_pos_t(motion.position));
}
};
+5 -3
View File
@@ -57,8 +57,10 @@
// fr French
// fr_na French without accents (DWIN T5UID1 touchscreen)
// gl Galician
// hg Hinglish (Hindi in Latin script)
// hr Croatian
// hu Hungarian
// id Indonesian (Bahasa)
// it Italian
// jp_kana Japanese
// ko_KR Korean (South Korea)
@@ -366,17 +368,17 @@
#define STR_Z2 STR_C "2"
#define STR_Z3 STR_C "3"
#define STR_Z4 STR_C "4"
#if CORE_IS_XY || CORE_IS_XZ
#if ANY(HAS_REAL_X, IS_SCARA, DELTA)
#define STEPPER_A_NAME 'A'
#else
#define STEPPER_A_NAME 'X'
#endif
#if CORE_IS_XY || CORE_IS_YZ
#if ANY(HAS_REAL_Y, IS_SCARA, DELTA, POLAR)
#define STEPPER_B_NAME 'B'
#else
#define STEPPER_B_NAME 'Y'
#endif
#if CORE_IS_XZ || CORE_IS_YZ
#if ANY(HAS_REAL_Z, DELTA)
#define STEPPER_C_NAME 'C'
#else
#define STEPPER_C_NAME 'Z'
+1
View File
@@ -256,6 +256,7 @@
// Array shorthand
#define COUNT(a) (sizeof(a)/sizeof(*a))
#define ZERO(a) memset((void*)a,0,sizeof(a))
#define OBJZERO(a) memset(&a,0,sizeof(a))
#define COPY(a,b) do{ \
static_assert(sizeof(a[0]) == sizeof(b[0]), "COPY: '" STRINGIFY(a) "' and '" STRINGIFY(b) "' types (sizes) don't match!"); \
memcpy(&a[0],&b[0],_MIN(sizeof(a),sizeof(b))); \
+9 -9
View File
@@ -158,16 +158,16 @@ public:
MString& append_P(PGM_P const s) { int sz = length(); if (sz < SIZE) strlcpy_P(str + sz, s, SIZE - sz + 1); debug(F("pstring")); return *this; }
MString& append(FSTR_P const f) { return append_P(FTOP(f)); }
MString& append(const bool &b) { return append(b ? F("true") : F("false")); }
MString& append(const char c) { int sz = length(); if (sz < SIZE) { str[sz] = c; if (sz < SIZE - 1) str[sz + 1] = '\0'; } return *this; }
MString& append(const char c) { int sz = length(); if (sz < SIZE) { str[sz] = c; if (sz < SIZE - 1) str[sz + 1] = '\0'; } debug(F("char")); return *this; }
#if ENABLED(FASTER_APPEND)
MString& append(const int8_t &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); return *this; }
MString& append(const short &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); return *this; }
MString& append(const int &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); return *this; }
MString& append(const long &l) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%ld", l); return *this; }
MString& append(const unsigned char &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); return *this; }
MString& append(const unsigned short &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); return *this; }
MString& append(const unsigned int &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); return *this; }
MString& append(const unsigned long &l) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%lu", l); return *this; }
MString& append(const int8_t &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); debug(F("int8_t")); return *this; }
MString& append(const short &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); debug(F("short")); return *this; }
MString& append(const int &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); debug(F("int")); return *this; }
MString& append(const long &l) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%ld", l); debug(F("long")); return *this; }
MString& append(const unsigned char &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); debug(F("uchar")); return *this; }
MString& append(const unsigned short &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); debug(F("ushort")); return *this; }
MString& append(const unsigned int &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); debug(F("uint")); return *this; }
MString& append(const unsigned long &l) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%lu", l); debug(F("ulong")); return *this; }
#else
MString& append(const int8_t &i) { char buf[ 5]; sprintf(buf, "%d", i); return append(buf); }
MString& append(const short &i) { char buf[12]; sprintf(buf, "%d", i); return append(buf); }
+162 -84
View File
@@ -52,6 +52,11 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define MAIN_AXIS_NAMES_LC NUM_AXIS_LIST(x, y, z, i, j, k, u, v, w)
#define NUM_AXIS_CALL(G) do { NUM_AXIS_CODE(G(X_AXIS), G(Y_AXIS), G(Z_AXIS), G(I_AXIS), G(J_AXIS), G(K_AXIS), G(U_AXIS), G(V_AXIS), G(W_AXIS)); } while(0)
#define STR_AXES_MAIN NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)
#define NUM_AXIS_ANY(x, y, z, i, j, k, u, v, w) (false \
NUM_AXIS_GANG(|| (x), || (y), || (z), || (i), || (j), || (k), || (u), || (v), || (w)))
#define NUM_AXIS_ALL(x, y, z, i, j, k, u, v, w) ((NUM_AXES > 0) \
NUM_AXIS_GANG(&& (x), && (y), && (z), && (i), && (j), && (k), && (u), && (v), && (w)))
#define NUM_AXIS_NONE(V...) !NUM_AXIS_ANY(V)
#define LOGICAL_AXIS_GANG(N,V...) NUM_AXIS_GANG(V) GANG_ITEM_E(N)
#define LOGICAL_AXIS_CODE(N,V...) NUM_AXIS_CODE(V) CODE_ITEM_E(N)
@@ -71,6 +76,11 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define LOGICAL_AXIS_MAP_LC(F) MAP(F, LOGICAL_AXIS_NAMES_LC)
#define LOGICAL_AXIS_CALL(G) do { LOGICAL_AXIS_CODE(G(E_AXIS), G(X_AXIS), G(Y_AXIS), G(Z_AXIS), G(I_AXIS), G(J_AXIS), G(K_AXIS), G(U_AXIS), G(V_AXIS), G(W_AXIS)); } while(0)
#define STR_AXES_LOGICAL LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)
#define LOGICAL_AXIS_ANY(e, x, y, z, i, j, k, u, v, w) (false \
LOGICAL_AXIS_GANG(|| (e), || (x), || (y), || (z), || (i), || (j), || (k), || (u), || (v), || (w)))
#define LOGICAL_AXIS_ALL(e, x, y, z, i, j, k, u, v, w) ((LOGICAL_AXES > 0) \
LOGICAL_AXIS_GANG(&& (e), && (x), && (y), && (z), && (i), && (j), && (k), && (u), && (v), && (w)))
#define LOGICAL_AXIS_NONE(V...) !LOGICAL_AXIS_ANY(V)
#define NUM_AXIS_PAIRED_LIST(V...) LIST_N(DOUBLE(NUM_AXES), V)
#define LOGICAL_AXIS_PAIRED_LIST(EA,EB,V...) NUM_AXIS_PAIRED_LIST(V) LIST_ITEM_E(EA) LIST_ITEM_E(EB)
@@ -145,10 +155,14 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define XY_ARRAY(V...) ARRAY_N(XY_COUNT, V)
#define XY_CODE(V...) CODE_N(XY_COUNT, V)
#define XY_GANG(V...) GANG_N(XY_COUNT, V)
#define XY_ANY(x,y) (false XY_GANG(|| (x), || (y)))
#define XY_ALL(x,y) ((NUM_AXES > 0) XY_GANG(&& (x), && (y)))
#define XYZ_LIST(V...) LIST_N(XYZ_COUNT, V)
#define XYZ_ARRAY(V...) ARRAY_N(XYZ_COUNT, V)
#define XYZ_CODE(V...) CODE_N(XYZ_COUNT, V)
#define XYZ_GANG(V...) GANG_N(XYZ_COUNT, V)
#define XYZ_ANY(x,y,z) (false XYZ_GANG(|| (x), || (y), || (z)))
#define XYZ_ALL(x,y,z) ((NUM_AXES > 0) XYZ_GANG(&& (x), && (y), && (z)))
#if HAS_ROTATIONAL_AXES
#define ROTATIONAL_AXIS_GANG(V...) GANG_N(ROTATIONAL_AXES, V)
@@ -177,6 +191,7 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define CARTES_CODE(x,y,z,e) XYZ_CODE(x,y,z) CODE_ITEM_E(e)
#define CARTES_GANG(x,y,z,e) XYZ_GANG(x,y,z) GANG_ITEM_E(e)
#define CARTES_AXIS_NAMES CARTES_LIST(X,Y,Z,E)
#define CARTES_AXIS_NAMES_LC CARTES_LIST(x,y,z,e)
#define CARTES_MAP(F) MAP(F, CARTES_AXIS_NAMES)
#if CARTES_COUNT
#define CARTES_COMMA ,
@@ -335,9 +350,9 @@ typedef struct {
//
// Enumerated axis indices
//
// - X_AXIS, Y_AXIS, and Z_AXIS should be used for axes in Cartesian space
// - A_AXIS, B_AXIS, and C_AXIS should be used for Steppers, corresponding to XYZ on Cartesians
// - X_HEAD, Y_HEAD, and Z_HEAD should be used for axes on Core kinematics
// - X_REAL, Y_REAL, and Z_REAL should be used for axes in Cartesian space
// - A_AXIS, B_AXIS, and C_AXIS should be used for Steppers
// - X_AXIS, Y_AXIS, and Z_AXIS are now more generic interchangeble indexes
//
enum AxisEnum : uint8_t {
@@ -349,8 +364,14 @@ enum AxisEnum : uint8_t {
#undef _EN_ITEM
// Core also keeps toolhead directions
#if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
X_HEAD, Y_HEAD, Z_HEAD,
#if HAS_REAL_X
X_REAL,
#endif
#if HAS_REAL_Y
Y_REAL,
#endif
#if HAS_REAL_Z
Z_REAL,
#endif
// Distinct axes, including all E and Core
@@ -359,6 +380,10 @@ enum AxisEnum : uint8_t {
// Most of the time we refer only to the single E_AXIS
#if HAS_EXTRUDERS
E_AXIS = E0_AXIS,
E_REAL = E_AXIS,
#define _EN_REAL(N) E##N##_REAL = E##N##_AXIS,
REPEAT(EXTRUDERS, _EN_REAL)
#undef _EN_REAL
#endif
// A, B, and C are for DELTA, SCARA, etc.
@@ -372,6 +397,35 @@ enum AxisEnum : uint8_t {
C_AXIS = Z_AXIS,
#endif
// Aliases to distinguish tool axes from stepper indexes
#if HAS_X_AXIS && !HAS_REAL_X
X_REAL = X_AXIS,
#endif
#if HAS_Y_AXIS && !HAS_REAL_Y
Y_REAL = Y_AXIS,
#endif
#if HAS_Z_AXIS && !HAS_REAL_Z
Z_REAL = Z_AXIS,
#endif
#if HAS_I_AXIS
I_REAL = I_AXIS,
#endif
#if HAS_J_AXIS
J_REAL = J_AXIS,
#endif
#if HAS_K_AXIS
K_REAL = K_AXIS,
#endif
#if HAS_U_AXIS
U_REAL = U_AXIS,
#endif
#if HAS_V_AXIS
V_REAL = V_AXIS,
#endif
#if HAS_W_AXIS
W_REAL = W_AXIS,
#endif
// To refer to all or none
ALL_AXES_ENUM = 0xFE, NO_AXIS_ENUM = 0xFF
};
@@ -556,7 +610,7 @@ struct XYval {
#endif
// Length reduced to one dimension
FI constexpr T magnitude() const { return (T)sqrtf(x*x + y*y); }
FI constexpr T magnitude() const { return (T)SQRT(x*x + y*y); }
// Pointer to the data as a simple array
explicit FI operator T* () { return pos; }
// If any element is true then it's true
@@ -578,7 +632,7 @@ struct XYval {
FI constexpr XYval<uint32_t> asUInt32() const { return { uint32_t(x), uint32_t(y) }; }
FI constexpr XYval<int64_t> asInt64() const { return { int64_t(x), int64_t(y) }; }
FI constexpr XYval<uint64_t> asUInt64() const { return { uint64_t(x), uint64_t(y) }; }
FI constexpr XYval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y) }; }
FI constexpr XYval<float> asFloat() const { return { float(x), float(y) }; }
// Marlin workspace shifting is done with G92 and M206
FI XYval<float> asLogical() const { XYval<float> o = asFloat(); toLogical(o); return o; }
@@ -645,8 +699,8 @@ struct XYval {
// Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYval<T> &rs) const { return x == rs.x && y == rs.y; }
FI bool operator==(const XYZval<T> &rs) const { return ENABLED(HAS_X_AXIS) XY_GANG(&& x == rs.x, && y == rs.y); }
FI bool operator==(const XYZEval<T> &rs) const { return ENABLED(HAS_X_AXIS) XY_GANG(&& x == rs.x, && y == rs.y); }
FI bool operator==(const XYZval<T> &rs) const { return XY_ALL(x == rs.x, y == rs.y); }
FI bool operator==(const XYZEval<T> &rs) const { return XY_ALL(x == rs.x, y == rs.y); }
FI bool operator!=(const XYval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
@@ -660,15 +714,15 @@ struct XYval {
FI bool operator> (const XYval<T> &rs) const { return x > rs.x && y > rs.y; }
FI bool operator>=(const XYval<T> &rs) const { return x >= rs.x && y >= rs.y; }
FI bool operator< (const XYZval<T> &rs) const { return true XY_GANG(&& x < rs.x, && y < rs.y); }
FI bool operator<=(const XYZval<T> &rs) const { return true XY_GANG(&& x <= rs.x, && y <= rs.y); }
FI bool operator> (const XYZval<T> &rs) const { return true XY_GANG(&& x > rs.x, && y > rs.y); }
FI bool operator>=(const XYZval<T> &rs) const { return true XY_GANG(&& x >= rs.x, && y >= rs.y); }
FI bool operator< (const XYZval<T> &rs) const { return XY_ALL(x < rs.x, y < rs.y); }
FI bool operator<=(const XYZval<T> &rs) const { return XY_ALL(x <= rs.x, y <= rs.y); }
FI bool operator> (const XYZval<T> &rs) const { return XY_ALL(x > rs.x, y > rs.y); }
FI bool operator>=(const XYZval<T> &rs) const { return XY_ALL(x >= rs.x, y >= rs.y); }
FI bool operator< (const XYZEval<T> &rs) const { return true XY_GANG(&& x < rs.x, && y < rs.y); }
FI bool operator<=(const XYZEval<T> &rs) const { return true XY_GANG(&& x <= rs.x, && y <= rs.y); }
FI bool operator> (const XYZEval<T> &rs) const { return true XY_GANG(&& x > rs.x, && y > rs.y); }
FI bool operator>=(const XYZEval<T> &rs) const { return true XY_GANG(&& x >= rs.x, && y >= rs.y); }
FI bool operator< (const XYZEval<T> &rs) const { return XY_ALL(x < rs.x, y < rs.y); }
FI bool operator<=(const XYZEval<T> &rs) const { return XY_ALL(x <= rs.x, y <= rs.y); }
FI bool operator> (const XYZEval<T> &rs) const { return XY_ALL(x > rs.x, y > rs.y); }
FI bool operator>=(const XYZEval<T> &rs) const { return XY_ALL(x >= rs.x, y >= rs.y); }
};
@@ -708,36 +762,36 @@ struct XYZval {
// Setters with fewer elements leave the rest untouched
#if HAS_Y_AXIS
FI void set(const T px) { x = px; }
FI void set(const T px) { x = px; }
#endif
#if HAS_Z_AXIS
FI void set(const T px, const T py) { x = px; y = py; }
FI void set(const T px, const T py) { set(px); y = py; }
#endif
#if HAS_I_AXIS
FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; }
FI void set(const T px, const T py, const T pz) { set(px, py); z = pz; }
#endif
#if HAS_J_AXIS
FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; }
FI void set(const T px, const T py, const T pz, const T pi) { set(px, py, pz); i = pi; }
#endif
#if HAS_K_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj) { set(px, py, pz, pi); j = pj; }
#endif
#if HAS_U_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { set(px, py, pz, pi, pj); k = pk; }
#endif
#if HAS_V_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { set(px, py, pz, pi, pj, pk); u = pu; }
#endif
#if HAS_W_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { set(px, py, pz, pi, pj, pk, pu); v = pv; }
#endif
// Length reduced to one dimension
FI constexpr T magnitude() const { return (T)TERN(HAS_X_AXIS, sqrtf(NUM_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)), 0); }
FI constexpr T magnitude() const { return (T)TERN(HAS_X_AXIS, SQRT(NUM_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)), 0); }
// Pointer to the data as a simple array
explicit FI operator T* () { return pos; }
// If any element is true then it's true
FI constexpr operator bool() const { return 0 NUM_AXIS_GANG(|| x, || y, || z, || i, || j, || k, || u, || v, || w); }
FI constexpr operator bool() const { return NUM_AXIS_ANY(x, y, z, i, j, k, u, v, w); }
// Smallest element
FI constexpr T small() const { return TERN0(HAS_X_AXIS, _MIN(NUM_AXIS_LIST(x, y, z, i, j, k, u, v, w))); }
// Largest element
@@ -755,13 +809,13 @@ struct XYZval {
FI constexpr XYZval<uint32_t> asUInt32() const { return NUM_AXIS_ARRAY(uint32_t(x), uint32_t(y), uint32_t(z), uint32_t(i), uint32_t(j), uint32_t(k), uint32_t(u), uint32_t(v), uint32_t(w)); }
FI constexpr XYZval<int64_t> asInt64() const { return NUM_AXIS_ARRAY(int64_t(x), int64_t(y), int64_t(z), int64_t(i), int64_t(j), int64_t(k), int64_t(u), int64_t(v), int64_t(w)); }
FI constexpr XYZval<uint64_t> asUInt64() const { return NUM_AXIS_ARRAY(uint64_t(x), uint64_t(y), uint64_t(z), uint64_t(i), uint64_t(j), uint64_t(k), uint64_t(u), uint64_t(v), uint64_t(w)); }
FI constexpr XYZval<float> asFloat() const { return NUM_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
FI constexpr XYZval<float> asFloat() const { return NUM_AXIS_ARRAY(float(x), float(y), float(z), float(i), float(j), float(k), float(u), float(v), float(w)); }
// Marlin workspace shifting is done with G92 and M206
FI XYZval<float> asLogical() const { XYZval<float> o = asFloat(); toLogical(o); return o; }
FI XYZval<float> asNative() const { XYZval<float> o = asFloat(); toNative(o); return o; }
// In-place cast to types having fewer fields
// In-place reinterpret-cast to types having fewer fields
FI operator XYval<T>&() { return *(XYval<T>*)this; }
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
@@ -816,29 +870,29 @@ struct XYZval {
FI XYZval<T>& operator-=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
FI XYZval<T>& operator*=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
FI XYZval<T>& operator/=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
FI XYZval<T>& operator*=(const float p) { NUM_AXIS_CODE(x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; }
FI XYZval<T>& operator*=(const float &p) { NUM_AXIS_CODE(x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; }
FI XYZval<T>& operator*=(const int &p) { NUM_AXIS_CODE(x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; }
FI XYZval<T>& operator/=(const float p) { NUM_AXIS_CODE(x /= p, y /= p, z /= p, i /= p, j /= p, k /= p, u /= p, v /= p, w /= p); return *this; }
FI XYZval<T>& operator/=(const float &p) { NUM_AXIS_CODE(x /= p, y /= p, z /= p, i /= p, j /= p, k /= p, u /= p, v /= p, w /= p); return *this; }
FI XYZval<T>& operator>>=(const int &p) { NUM_AXIS_CODE(_RSE(x), _RSE(y), _RSE(z), _RSE(i), _RSE(j), _RSE(k), _RSE(u), _RSE(v), _RSE(w)); return *this; }
FI XYZval<T>& operator<<=(const int &p) { NUM_AXIS_CODE(_LSE(x), _LSE(y), _LSE(z), _LSE(i), _LSE(j), _LSE(k), _LSE(u), _LSE(v), _LSE(w)); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYZEval<T> &rs) const { return ENABLED(HAS_X_AXIS) NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x == rs.x, y == rs.y, z == rs.z, i == rs.i, j == rs.j, k == rs.k, u == rs.u, v == rs.v, w == rs.w); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
// Exact comparison to a single value
FI bool operator==(const T &p) const { return ENABLED(HAS_X_AXIS) NUM_AXIS_GANG(&& x == p, && y == p, && z == p, && i == p, && j == p, && k == p, && u == p, && v == p, && w == p); }
FI bool operator==(const T &p) const { return NUM_AXIS_ALL(x == p, y == p, z == p, i == p, j == p, k == p, u == p, v == p, w == p); }
FI bool operator!=(const T &p) const { return !operator==(p); }
FI bool operator< (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
FI bool operator<=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
FI bool operator> (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
FI bool operator>=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
FI bool operator< (const XYZval<T> &rs) const { return NUM_AXIS_ALL(x < rs.x, y < rs.y, z < rs.z, i < rs.i, j < rs.j, k < rs.k, u < rs.u, v < rs.v, w < rs.w); }
FI bool operator<=(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x <= rs.x, y <= rs.y, z <= rs.z, i <= rs.i, j <= rs.j, k <= rs.k, u <= rs.u, v <= rs.v, w <= rs.w); }
FI bool operator> (const XYZval<T> &rs) const { return NUM_AXIS_ALL(x > rs.x, y > rs.y, z > rs.z, i > rs.i, j > rs.j, k > rs.k, u > rs.u, v > rs.v, w > rs.w); }
FI bool operator>=(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x >= rs.x, y >= rs.y, z >= rs.z, i >= rs.i, j >= rs.j, k >= rs.k, u >= rs.u, v >= rs.v, w >= rs.w); }
FI bool operator< (const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
FI bool operator<=(const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
FI bool operator> (const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
FI bool operator>=(const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
FI bool operator< (const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x < rs.x, y < rs.y, z < rs.z, i < rs.i, j < rs.j, k < rs.k, u < rs.u, v < rs.v, w < rs.w); }
FI bool operator<=(const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x <= rs.x, y <= rs.y, z <= rs.z, i <= rs.i, j <= rs.j, k <= rs.k, u <= rs.u, v <= rs.v, w <= rs.w); }
FI bool operator> (const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x > rs.x, y > rs.y, z > rs.z, i > rs.i, j > rs.j, k > rs.k, u > rs.u, v > rs.v, w > rs.w); }
FI bool operator>=(const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x >= rs.x, y >= rs.y, z >= rs.z, i >= rs.i, j >= rs.j, k >= rs.k, u >= rs.u, v >= rs.v, w >= rs.w); }
};
@@ -857,7 +911,7 @@ struct XYZEval {
T pos[LOGICAL_AXES];
};
// Reset all to 0
FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; }
FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; }
// Setters taking struct types and arrays
FI void set(const XYval<T> &pxy) { XY_CODE(x = pxy.x, y = pxy.y); }
@@ -882,33 +936,33 @@ struct XYZEval {
FI void set(const T px) { x = px; }
#endif
#if HAS_Z_AXIS
FI void set(const T px, const T py) { x = px; y = py; }
FI void set(const T px, const T py) { set(px); y = py; }
#endif
#if HAS_I_AXIS
FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; }
FI void set(const T px, const T py, const T pz) { set(px, py); z = pz; }
#endif
#if HAS_J_AXIS
FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; }
FI void set(const T px, const T py, const T pz, const T pi) { set(px, py, pz); i = pi; }
#endif
#if HAS_K_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj) { set(px, py, pz, pi); j = pj; }
#endif
#if HAS_U_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { set(px, py, pz, pi, pj); k = pk; }
#endif
#if HAS_V_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { set(px, py, pz, pi, pj, pk); u = pu; }
#endif
#if HAS_W_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { set(px, py, pz, pi, pj, pk, pu); v = pv; }
#endif
// Length reduced to one dimension
FI constexpr T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); }
FI constexpr T magnitude() const { return (T)SQRT(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); }
// Pointer to the data as a simple array
explicit FI operator T* () { return pos; }
// If any element is true then it's true
FI constexpr operator bool() const { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k, || u, || v, || w); }
FI constexpr operator bool() const { return LOGICAL_AXIS_ANY(e, x, y, z, i, j, k, u, v, w); }
// Smallest element
FI constexpr T small() const { return _MIN(LOGICAL_AXIS_LIST(e, x, y, z, i, j, k, u, v, w)); }
// Largest element
@@ -926,13 +980,13 @@ struct XYZEval {
FI constexpr XYZEval<uint32_t> asUInt32() const { return LOGICAL_AXIS_ARRAY(uint32_t(e), uint32_t(x), uint32_t(y), uint32_t(z), uint32_t(i), uint32_t(j), uint32_t(k), uint32_t(u), uint32_t(v), uint32_t(w)); }
FI constexpr XYZEval<int64_t> asInt64() const { return LOGICAL_AXIS_ARRAY(int64_t(e), int64_t(x), int64_t(y), int64_t(z), int64_t(i), int64_t(j), int64_t(k), int64_t(u), int64_t(v), int64_t(w)); }
FI constexpr XYZEval<uint64_t> asUInt64() const { return LOGICAL_AXIS_ARRAY(uint64_t(e), uint64_t(x), uint64_t(y), uint64_t(z), uint64_t(i), uint64_t(j), uint64_t(k), uint64_t(u), uint64_t(v), uint64_t(w)); }
FI constexpr XYZEval<float> asFloat() const { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
FI constexpr XYZEval<float> asFloat() const { return LOGICAL_AXIS_ARRAY(float(e), float(x), float(y), float(z), float(i), float(j), float(k), float(u), float(v), float(w)); }
// Marlin workspace shifting is done with G92 and M206
FI XYZEval<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
FI XYZEval<float> asNative() const { XYZEval<float> o = asFloat(); toNative(o); return o; }
// In-place cast to types having fewer fields
// In-place reinterpret-cast to types having fewer fields
FI operator XYval<T>&() { return *(XYval<T>*)this; }
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
FI operator XYZval<T>&() { return *(XYZval<T>*)this; }
@@ -997,24 +1051,24 @@ struct XYZEval {
FI XYZEval<T>& operator<<=(const int &p) { LOGICAL_AXIS_CODE(_LSE(e), _LSE(x), _LSE(y), _LSE(z), _LSE(i), _LSE(j), _LSE(k), _LSE(u), _LSE(v), _LSE(w)); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYZval<T> &rs) const { return ENABLED(HAS_X_AXIS) NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZEval<T> &rs) const { return ANY(HAS_X_AXIS, HAS_EXTRUDERS) LOGICAL_AXIS_GANG(&& e == rs.e, && x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x == rs.x, y == rs.y, z == rs.z, i == rs.i, j == rs.j, k == rs.k, u == rs.u, v == rs.v, w == rs.w); }
FI bool operator==(const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e == rs.e, x == rs.x, y == rs.y, z == rs.z, i == rs.i, j == rs.j, k == rs.k, u == rs.u, v == rs.v, w == rs.w); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
// Exact comparison to a single value
FI bool operator==(const T &p) const { return ENABLED(HAS_X_AXIS) LOGICAL_AXIS_GANG(&& e == p, && x == p, && y == p, && z == p, && i == p, && j == p, && k == p, && u == p, && v == p, && w == p); }
FI bool operator==(const T &p) const { return LOGICAL_AXIS_ALL(e == p, x == p, y == p, z == p, i == p, j == p, k == p, u == p, v == p, w == p); }
FI bool operator!=(const T &p) const { return !operator==(p); }
FI bool operator< (const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e < rs.e, && x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
FI bool operator<=(const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e <= rs.e, && x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
FI bool operator> (const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e > rs.e, && x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
FI bool operator>=(const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e >= rs.e, && x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
FI bool operator< (const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e < rs.e, x < rs.x, y < rs.y, z < rs.z, i < rs.i, j < rs.j, k < rs.k, u < rs.u, v < rs.v, w < rs.w); }
FI bool operator<=(const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e <= rs.e, x <= rs.x, y <= rs.y, z <= rs.z, i <= rs.i, j <= rs.j, k <= rs.k, u <= rs.u, v <= rs.v, w <= rs.w); }
FI bool operator> (const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e > rs.e, x > rs.x, y > rs.y, z > rs.z, i > rs.i, j > rs.j, k > rs.k, u > rs.u, v > rs.v, w > rs.w); }
FI bool operator>=(const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e >= rs.e, x >= rs.x, y >= rs.y, z >= rs.z, i >= rs.i, j >= rs.j, k >= rs.k, u >= rs.u, v >= rs.v, w >= rs.w); }
FI bool operator< (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
FI bool operator<=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
FI bool operator> (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
FI bool operator>=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
FI bool operator< (const XYZval<T> &rs) const { return NUM_AXIS_ALL(x < rs.x, y < rs.y, z < rs.z, i < rs.i, j < rs.j, k < rs.k, u < rs.u, v < rs.v, w < rs.w); }
FI bool operator<=(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x <= rs.x, y <= rs.y, z <= rs.z, i <= rs.i, j <= rs.j, k <= rs.k, u <= rs.u, v <= rs.v, w <= rs.w); }
FI bool operator> (const XYZval<T> &rs) const { return NUM_AXIS_ALL(x > rs.x, y > rs.y, z > rs.z, i > rs.i, j > rs.j, k > rs.k, u > rs.u, v > rs.v, w > rs.w); }
FI bool operator>=(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x >= rs.x, y >= rs.y, z >= rs.z, i >= rs.i, j >= rs.j, k >= rs.k, u >= rs.u, v >= rs.v, w >= rs.w); }
};
@@ -1044,28 +1098,28 @@ struct XYZarray {
// Setters with fewer elements leave the rest untouched
#if HAS_Y_AXIS
FI void set(const int n, const T px) { x[n] = px; }
FI void set(const int n, const T px) { x[n] = px; }
#endif
#if HAS_Z_AXIS
FI void set(const int n, const T px, const T py) { x[n] = px; y[n] = py; }
FI void set(const int n, const T px, const T py) { set(n, px); y[n] = py; }
#endif
#if HAS_I_AXIS
FI void set(const int n, const T px, const T py, const T pz) { x[n] = px; y[n] = py; z[n] = pz; }
FI void set(const int n, const T px, const T py, const T pz) { set(n, px, py); z[n] = pz; }
#endif
#if HAS_J_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; }
FI void set(const int n, const T px, const T py, const T pz, const T pi) { set(n, px, py, pz); i[n] = pi; }
#endif
#if HAS_K_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; j[n] = pj; }
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj) { set(n, px, py, pz, pi); j[n] = pj; }
#endif
#if HAS_U_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; j[n] = pj; k[n] = pk; }
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk) { set(n, px, py, pz, pi, pj); k[n] = pk; }
#endif
#if HAS_V_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; j[n] = pj; k[n] = pk; u[n] = pu; }
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { set(n, px, py, pz, pi, pj, pk); u[n] = pu; }
#endif
#if HAS_W_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; j[n] = pj; k[n] = pk; u[n] = pu; v[n] = pv; }
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { set(n, px, py, pz, pi, pj, pk, pu); v[n] = pv; }
#endif
FI XYZval<T> operator[](const int n) const { return XYZval<T>(NUM_AXIS_ARRAY(x[n], y[n], z[n], i[n], j[n], k[n], u[n], v[n], w[n])); }
@@ -1130,7 +1184,7 @@ public:
typedef bits_t(NUM_AXIS_HEADS) el;
union {
el bits;
// Axes x, y, z ... e0, e1, e2 ... hx, hy, hz
// Axes x, y, z ... e0, e1, e2 ... rx, ry, rz
struct {
#if NUM_AXES
bool NUM_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1, u:1, v:1, w:1);
@@ -1138,11 +1192,17 @@ public:
#define _EN_ITEM(N) bool e##N:1;
REPEAT(EXTRUDERS,_EN_ITEM)
#undef _EN_ITEM
#if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
bool hx:1, hy:1, hz:1;
#if HAS_REAL_X
bool rx:1;
#endif
#if HAS_REAL_Y
bool ry:1;
#endif
#if HAS_REAL_Z
bool rz:1;
#endif
};
// Axes X, Y, Z ... E0, E1, E2 ... HX, HY, HZ
// Axes X, Y, Z ... E0, E1, E2 ... RX, RY, RZ
struct {
#if NUM_AXES
bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W:1);
@@ -1150,11 +1210,17 @@ public:
#define _EN_ITEM(N) bool E##N:1;
REPEAT(EXTRUDERS,_EN_ITEM)
#undef _EN_ITEM
#if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
bool HX:1, HY:1, HZ:1;
#if HAS_REAL_X
bool RX:1;
#endif
#if HAS_REAL_Y
bool RY:1;
#endif
#if HAS_REAL_Z
bool RZ:1;
#endif
};
// a, b, c, e ... ha, hb, hc
// a, b, c, e ... ra, rb, rc
struct {
bool LOGICAL_AXIS_LIST(e:1, a:1, b:1, c:1, ii:1, jj:1, kk:1, uu:1, vv:1, ww:1);
#if EXTRUDERS > 1
@@ -1162,11 +1228,17 @@ public:
REPEAT_S(1,EXTRUDERS,_EN_ITEM)
#undef _EN_ITEM
#endif
#if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
bool ha:1, hb:1, hc:1;
#if HAS_REAL_X
bool ra:1;
#endif
#if HAS_REAL_Y
bool rb:1;
#endif
#if HAS_REAL_Z
bool rc:1;
#endif
};
// A, B, C, E ... HA, HB, HC
// A, B, C, E ... RA, RB, RC
struct {
bool LOGICAL_AXIS_LIST(E:1, A:1, B:1, C:1, II:1, JJ:1, KK:1, UU:1, VV:1, WW:1);
#if EXTRUDERS > 1
@@ -1174,8 +1246,14 @@ public:
REPEAT_S(1,EXTRUDERS,_EN_ITEM)
#undef _EN_ITEM
#endif
#if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
bool HA:1, HB:1, HC:1;
#if HAS_REAL_X
bool RA:1;
#endif
#if HAS_REAL_Y
bool RB:1;
#endif
#if HAS_REAL_Z
bool RC:1;
#endif
};
};
+5 -5
View File
@@ -133,7 +133,7 @@
SERIAL_ECHOPGM("ABL Adjustment");
LOOP_NUM_AXES(a) {
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]));
serial_offset(planner.get_axis_position_mm((AxisEnum)a) - current_position[a]);
serial_offset(planner.get_axis_position_mm((AxisEnum)a) - motion.position[a]);
}
#else
#if ENABLED(AUTO_BED_LEVELING_UBL)
@@ -141,11 +141,11 @@
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
SERIAL_ECHOPGM("ABL Adjustment Z");
#endif
const float rz = bedlevel.get_z_correction(current_position);
const float rz = bedlevel.get_z_correction(motion.position);
SERIAL_ECHO(ftostr43sign(rz, '+'));
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
if (planner.z_fade_height)
SERIAL_ECHO(F(" ("), ftostr43sign(rz * planner.fade_scaling_factor_for_z(current_position.z), '+'), C(')'));
SERIAL_ECHO(F(" ("), ftostr43sign(rz * planner.fade_scaling_factor_for_z(motion.position.z), '+'), C(')'));
#endif
#endif
}
@@ -160,11 +160,11 @@
if (planner.leveling_active) {
SERIAL_ECHOLNPGM(" (enabled)");
const float z_offset = bedlevel.get_z_offset(),
z_correction = bedlevel.get_z_correction(current_position);
z_correction = bedlevel.get_z_correction(motion.position);
SERIAL_ECHOPGM("MBL Adjustment Z", ftostr43sign(z_offset + z_correction, '+'));
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
if (planner.z_fade_height) {
SERIAL_ECHO(F(" ("), ftostr43sign(z_offset + z_correction * planner.fade_scaling_factor_for_z(current_position.z), '+'), C(')'));
SERIAL_ECHO(F(" ("), ftostr43sign(z_offset + z_correction * planner.fade_scaling_factor_for_z(motion.position.z), '+'), C(')'));
}
#endif
}
+2 -2
View File
@@ -59,7 +59,7 @@ void Babystep::add_mm(const AxisEnum axis, const float mm) {
#if ENABLED(BD_SENSOR)
void Babystep::set_mm(const AxisEnum axis, const float mm) {
//if (DISABLED(BABYSTEP_WITHOUT_HOMING) && axis_should_home(axis)) return;
//if (DISABLED(BABYSTEP_WITHOUT_HOMING) && motion.axis_should_home(axis)) return;
const int16_t distance = mm * planner.settings.axis_steps_per_mm[axis];
accum = distance; // Count up babysteps for the UI
steps[BS_AXIS_IND(axis)] = distance;
@@ -70,7 +70,7 @@ void Babystep::add_mm(const AxisEnum axis, const float mm) {
#endif
bool Babystep::can_babystep(const AxisEnum axis) {
return (ENABLED(BABYSTEP_WITHOUT_HOMING) || !axis_should_home(axis));
return (ENABLED(BABYSTEP_WITHOUT_HOMING) || !motion.axis_should_home(axis));
}
void Babystep::add_steps(const AxisEnum axis, const int16_t distance) {
+8 -8
View File
@@ -29,7 +29,7 @@
#include "../module/motion.h"
#include "../module/planner.h"
AxisBits Backlash::last_direction_bits;
AxisBits Backlash::last_direction;
xyz_long_t Backlash::residual_error{0};
#ifdef BACKLASH_DISTANCE_MM
@@ -64,7 +64,7 @@ Backlash backlash;
*/
void Backlash::add_correction_steps(const xyze_long_t &dist, const AxisBits dm, block_t * const block) {
AxisBits changed_dir = last_direction_bits ^ dm;
AxisBits changed_dir = last_direction ^ dm;
// Ignore direction change unless steps are taken in that direction
#if DISABLED(CORE_BACKLASH) || ANY(MARKFORGED_XY, MARKFORGED_YX)
if (!dist.a) changed_dir.x = false;
@@ -83,7 +83,7 @@ void Backlash::add_correction_steps(const xyze_long_t &dist, const AxisBits dm,
if (!(dist.b - dist.c)) changed_dir.z = false;
if (!dist.a) changed_dir.x = false;
#endif
last_direction_bits ^= changed_dir;
last_direction ^= changed_dir;
if (!correction && !residual_error) return;
@@ -167,7 +167,7 @@ void Backlash::add_correction_steps(const xyze_long_t &dist, const AxisBits dm,
int32_t Backlash::get_applied_steps(const AxisEnum axis) {
if (axis >= NUM_AXES) return 0;
const bool forward = last_direction_bits[axis];
const bool forward = last_direction[axis];
const int32_t residual_error_axis = residual_error[axis];
@@ -224,12 +224,12 @@ class Backlash::StepAdjuster {
void Backlash::measure_with_probe() {
if (measured_count.z == 255) return;
const float start_height = current_position.z;
while (current_position.z < (start_height + BACKLASH_MEASUREMENT_LIMIT) && PROBE_TRIGGERED())
do_blocking_move_to_z(current_position.z + BACKLASH_MEASUREMENT_RESOLUTION, MMM_TO_MMS(BACKLASH_MEASUREMENT_FEEDRATE));
const float start_height = motion.position.z;
while (motion.position.z < (start_height + BACKLASH_MEASUREMENT_LIMIT) && PROBE_TRIGGERED())
motion.blocking_move_z(motion.position.z + BACKLASH_MEASUREMENT_RESOLUTION, MMM_TO_MMS(BACKLASH_MEASUREMENT_FEEDRATE));
// The backlash from all probe points is averaged, so count the number of measurements
measured_mm.z += current_position.z - start_height;
measured_mm.z += motion.position.z - start_height;
measured_count.z++;
}
+1 -1
View File
@@ -29,7 +29,7 @@ public:
static constexpr uint8_t all_on = 0xFF, all_off = 0x00;
private:
static AxisBits last_direction_bits;
static AxisBits last_direction;
static xyz_long_t residual_error;
#if ENABLED(BACKLASH_GCODE)
+32 -24
View File
@@ -37,12 +37,12 @@
LevelingBilinear bedlevel;
xy_pos_t LevelingBilinear::grid_spacing,
LevelingBilinear::grid_start;
xy_float_t LevelingBilinear::grid_factor;
xy_pos_t LevelingBilinear::grid_spacing,
LevelingBilinear::grid_start,
LevelingBilinear::cached_rel;
xy_int8_t LevelingBilinear::cached_g;
bed_mesh_t LevelingBilinear::z_values;
xy_pos_t LevelingBilinear::cached_rel;
xy_int8_t LevelingBilinear::cached_g;
/**
* Extrapolate a single point from its neighbors
@@ -106,9 +106,17 @@ void LevelingBilinear::reset() {
}
}
/**
* Set grid spacing and start position
*/
void LevelingBilinear::set_grid(const xy_pos_t& _grid_spacing, const xy_pos_t& _grid_start) {
grid_spacing = _grid_spacing;
grid_start = _grid_start;
#if HAS_PROUI_MESH_EDIT
grid_spacing.set(MESH_X_DIST, MESH_Y_DIST);
grid_start = mesh_min;
#else
grid_spacing = _grid_spacing;
grid_start = _grid_start;
#endif
grid_factor = grid_spacing.reciprocal();
}
@@ -371,8 +379,8 @@ float LevelingBilinear::get_z_correction(const xy_pos_t &raw) {
*/
void LevelingBilinear::line_to_destination(const feedRate_t scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
// Get current and destination cells for this line
xy_int_t c1 { CELL_INDEX(x, current_position.x), CELL_INDEX(y, current_position.y) },
c2 { CELL_INDEX(x, destination.x), CELL_INDEX(y, destination.y) };
xy_int_t c1 { CELL_INDEX(x, motion.position.x), CELL_INDEX(y, motion.position.y) },
c2 { CELL_INDEX(x, motion.destination.x), CELL_INDEX(y, motion.destination.y) };
LIMIT(c1.x, 0, ABL_BG_POINTS_X - 2);
LIMIT(c1.y, 0, ABL_BG_POINTS_Y - 2);
LIMIT(c2.x, 0, ABL_BG_POINTS_X - 2);
@@ -380,12 +388,12 @@ float LevelingBilinear::get_z_correction(const xy_pos_t &raw) {
// Start and end in the same cell? No split needed.
if (c1 == c2) {
current_position = destination;
line_to_current_position(scaled_fr_mm_s);
motion.position = motion.destination;
motion.goto_current_position(scaled_fr_mm_s);
return;
}
#define LINE_SEGMENT_END(A) (current_position.A + (destination.A - current_position.A) * normalized_dist)
#define LINE_SEGMENT_END(A) (motion.position.A + (motion.destination.A - motion.position.A) * normalized_dist)
float normalized_dist;
xyze_pos_t end;
@@ -396,36 +404,36 @@ float LevelingBilinear::get_z_correction(const xy_pos_t &raw) {
if (c2.x != c1.x && TEST(x_splits, gc.x)) {
// Split on the X grid line
CBI(x_splits, gc.x);
end = destination;
destination.x = grid_start.x + ABL_BG_SPACING(x) * gc.x;
normalized_dist = (destination.x - current_position.x) / (end.x - current_position.x);
destination.y = LINE_SEGMENT_END(y);
end = motion.destination;
motion.destination.x = grid_start.x + ABL_BG_SPACING(x) * gc.x;
normalized_dist = (motion.destination.x - motion.position.x) / (end.x - motion.position.x);
motion.destination.y = LINE_SEGMENT_END(y);
}
// Crosses on the Y and not already split on this Y?
else if (c2.y != c1.y && TEST(y_splits, gc.y)) {
// Split on the Y grid line
CBI(y_splits, gc.y);
end = destination;
destination.y = grid_start.y + ABL_BG_SPACING(y) * gc.y;
normalized_dist = (destination.y - current_position.y) / (end.y - current_position.y);
destination.x = LINE_SEGMENT_END(x);
end = motion.destination;
motion.destination.y = grid_start.y + ABL_BG_SPACING(y) * gc.y;
normalized_dist = (motion.destination.y - motion.position.y) / (end.y - motion.position.y);
motion.destination.x = LINE_SEGMENT_END(x);
}
else {
// Must already have been split on these border(s)
// This should be a rare case.
current_position = destination;
line_to_current_position(scaled_fr_mm_s);
motion.position = motion.destination;
motion.goto_current_position(scaled_fr_mm_s);
return;
}
destination.z = LINE_SEGMENT_END(z);
destination.e = LINE_SEGMENT_END(e);
motion.destination.z = LINE_SEGMENT_END(z);
motion.destination.e = LINE_SEGMENT_END(e);
// Do the split and look for more borders
line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
// Restore destination from stack
destination = end;
motion.destination = end;
line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
}
+14 -14
View File
@@ -72,8 +72,8 @@ void BDS_Leveling::init(uint8_t _sda, uint8_t _scl, uint16_t delay_s) {
config_state = BDS_IDLE;
const int ret = BD_I2C_SENSOR.i2c_init(_sda, _scl, BD_SENSOR_I2C_ADDR, delay_s);
if (ret != 1) SERIAL_ECHOLNPGM("BD Sensor Init Fail (", ret, ")");
sync_plan_position();
pos_zero_offset = planner.get_axis_position_mm(Z_AXIS) - current_position.z;
motion.sync_plan_position();
pos_zero_offset = planner.get_axis_position_mm(Z_AXIS) - motion.position.z;
SERIAL_ECHOLNPGM("BD Sensor Zero Offset:", pos_zero_offset);
}
@@ -119,7 +119,7 @@ void BDS_Leveling::process() {
uint16_t tmp = 0;
const float cur_z = planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset;
static float old_cur_z = cur_z, old_buf_z = current_position.z;
static float old_cur_z = cur_z, old_buf_z = motion.position.z;
tmp = BD_I2C_SENSOR.BD_i2c_read();
if (BD_I2C_SENSOR.BD_Check_OddEven(tmp) && good_data(tmp)) {
const float z_sensor = interpret(tmp);
@@ -127,11 +127,11 @@ void BDS_Leveling::process() {
if (config_state > 0) {
if (cur_z < config_state * 0.1f
&& old_cur_z == cur_z
&& old_buf_z == current_position.z
&& old_buf_z == motion.position.z
&& z_sensor < (MAX_BD_HEIGHT) - 0.1f
) {
babystep.set_mm(Z_AXIS, cur_z - z_sensor);
DEBUG_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", current_position.z);
DEBUG_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", motion.position.z);
}
else
babystep.set_mm(Z_AXIS, 0);
@@ -139,7 +139,7 @@ void BDS_Leveling::process() {
#endif
old_cur_z = cur_z;
old_buf_z = current_position.z;
old_buf_z = motion.position.z;
endstops.bdp_state_update(z_sensor <= BD_SENSOR_HOME_Z_POSITION);
#if HAS_STATUS_MESSAGE
@@ -158,7 +158,7 @@ void BDS_Leveling::process() {
marlin.kill(F("BDsensor connect Err!"));
}
DEBUG_ECHOLNPGM("BD:", tmp & 0x3FF, " Z:", cur_z, "|", current_position.z);
DEBUG_ECHOLNPGM("BD:", tmp & 0x3FF, " Z:", cur_z, "|", motion.position.z);
if (TERN0(DEBUG_OUT_BD, BD_I2C_SENSOR.BD_Check_OddEven(tmp) == 0)) DEBUG_ECHOLNPGM("CRC error");
if (!good_data(tmp)) {
@@ -204,15 +204,15 @@ void BDS_Leveling::process() {
SERIAL_ECHOLNPGM("c_z0:", planner.get_axis_position_mm(Z_AXIS), "-", pos_zero_offset);
// Move the z axis instead of enabling the Z axis with M17
// TODO: Use do_blocking_move_to_z for synchronized move.
current_position.z = 0;
sync_plan_position();
// TODO: Use motion.blocking_move_z for synchronized move.
motion.position.z = 0;
motion.sync_plan_position();
gcode.process_subcommands_now(F("G1Z0.05"));
safe_delay(300);
gcode.process_subcommands_now(F("G1Z0.00"));
safe_delay(300);
current_position.z = 0;
sync_plan_position();
motion.position.z = 0;
motion.sync_plan_position();
//safe_delay(1000);
while ((planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset) > 0.00001f) {
@@ -235,10 +235,10 @@ void BDS_Leveling::process() {
}
else {
char tmp_1[32];
// TODO: Use prepare_internal_move_to_destination to guarantee machine space
// TODO: Use motion.prepare_internal_move_to_destination to guarantee machine space
sprintf_P(tmp_1, PSTR("G1Z%d.%d"), int(zpos), int(zpos * 10) % 10);
gcode.process_subcommands_now(tmp_1);
SERIAL_ECHO(tmp_1); SERIAL_ECHOLNPGM(", Z:", current_position.z);
SERIAL_ECHO(tmp_1); SERIAL_ECHOLNPGM(", Z:", motion.position.z);
uint16_t failcount = 300;
for (float tmp_k = 0; abs(zpos - tmp_k) > 0.006f && failcount--;) {
tmp_k = planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset;
+28 -18
View File
@@ -46,8 +46,18 @@
#include "../../lcd/extui/ui_api.h"
#endif
#if ALL(HAS_MESH, DWIN_LCD_PROUI)
#include "../../lcd/dwin/proui/bedlevel_tools.h"
#endif
bool leveling_is_valid() {
return TERN1(HAS_MESH, bedlevel.mesh_is_valid());
return (
#if ALL(HAS_MESH, DWIN_LCD_PROUI)
bedLevelTools.meshValidate()
#else
TERN1(HAS_MESH, bedlevel.mesh_is_valid())
#endif
);
}
/**
@@ -66,9 +76,9 @@ void set_bed_leveling_enabled(const bool enable/*=true*/) {
auto _report_leveling = []{
if (DEBUGGING(LEVELING)) {
if (planner.leveling_active)
DEBUG_POS("Leveling ON", current_position);
DEBUG_POS("Leveling ON", motion.position);
else
DEBUG_POS("Leveling OFF", current_position);
DEBUG_POS("Leveling OFF", motion.position);
}
};
@@ -76,11 +86,11 @@ void set_bed_leveling_enabled(const bool enable/*=true*/) {
planner.synchronize();
// Get the corrected leveled / unleveled position
planner.apply_modifiers(current_position, true); // Physical position with all modifiers
FLIP(planner.leveling_active); // Toggle leveling between apply and unapply
planner.unapply_modifiers(current_position, true); // Logical position with modifiers removed
planner.apply_modifiers(motion.position, true); // Physical position with all modifiers
FLIP(planner.leveling_active); // Toggle leveling between apply and unapply
planner.unapply_modifiers(motion.position, true); // Logical position with modifiers removed
sync_plan_position();
motion.sync_plan_position();
_report_leveling();
}
}
@@ -101,10 +111,10 @@ TemporaryBedLevelingState::TemporaryBedLevelingState(const bool enable) : saved(
planner.set_z_fade_height(zfh);
if (leveling_was_active) {
const xyz_pos_t oldpos = current_position;
const xyz_pos_t oldpos = motion.position;
set_bed_leveling_enabled(true);
if (do_report && oldpos != current_position)
report_current_position();
if (do_report && oldpos != motion.position)
motion.report_position();
}
}
@@ -198,16 +208,16 @@ void reset_bed_level() {
#else
#warning "It's recommended to set some MANUAL_PROBE_START_Z value for manual leveling."
#endif
#if Z_CLEARANCE_BETWEEN_MANUAL_PROBES > 0 // A probe/obstacle clearance exists so there is a raise:
#if Z_CLEARANCE_BETWEEN_MANUAL_PROBES > 0 // A probe/obstacle clearance exists so there is a raise:
#ifndef MANUAL_PROBE_START_Z
const float finalz = current_position.z; // - Use the current Z for starting-Z if no MANUAL_PROBE_START_Z was provided
const float finalz = motion.position.z; // - Use the current Z for starting-Z if no MANUAL_PROBE_START_Z was provided
#endif
do_blocking_move_to_xy_z(pos, Z_CLEARANCE_BETWEEN_MANUAL_PROBES); // - Raise Z, then move to the new XY
do_blocking_move_to_z(finalz); // - Lower down to the starting Z height, ready for adjustment!
#elif defined(MANUAL_PROBE_START_Z) // A starting-Z was provided, but there's no raise:
do_blocking_move_to_xy_z(pos, finalz); // - Move in XY then down to the starting Z height, ready for adjustment!
#else // Zero raise and no starting Z height either:
do_blocking_move_to_xy(pos); // - Move over with no raise, ready for adjustment!
motion.blocking_move_xy_z(pos, Z_CLEARANCE_BETWEEN_MANUAL_PROBES); // - Raise Z, then move to the new XY
motion.blocking_move_z(finalz); // - Lower down to the starting Z height, ready for adjustment!
#elif defined(MANUAL_PROBE_START_Z) // A starting-Z was provided, but there's no raise:
motion.blocking_move_xy_z(pos, finalz); // - Move in XY then down to the starting Z height, ready for adjustment!
#else // Zero raise and no starting Z height either:
motion.blocking_move_xy(pos); // - Move over with no raise, ready for adjustment!
#endif
TERN_(LCD_BED_LEVELING, ui.wait_for_move = false);
@@ -102,8 +102,8 @@ bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_pt
*/
bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) {
// Find closest grid intersection
const uint8_t grid_x = LROUND(constrain(float(pos.x - (MESH_MIN_X)) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1));
const uint8_t grid_y = LROUND(constrain(float(pos.y - (MESH_MIN_Y)) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1));
const uint8_t grid_x = LROUND(constrain((pos.x - mesh_min.x) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1));
const uint8_t grid_y = LROUND(constrain((pos.y - mesh_min.y) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1));
return search_from(grid_x, grid_y, func, data);
}
@@ -39,14 +39,21 @@
mesh_bed_leveling::index_to_xpos[GRID_MAX_POINTS_X],
mesh_bed_leveling::index_to_ypos[GRID_MAX_POINTS_Y];
mesh_bed_leveling::mesh_bed_leveling() {
mesh_bed_leveling::mesh_bed_leveling() { initialize(); }
void mesh_bed_leveling::initialize() {
for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i)
index_to_xpos[i] = MESH_MIN_X + i * (MESH_X_DIST);
index_to_xpos[i] = mesh_min.x + i * (MESH_X_DIST);
for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; ++i)
index_to_ypos[i] = MESH_MIN_Y + i * (MESH_Y_DIST);
index_to_ypos[i] = mesh_min.y + i * (MESH_Y_DIST);
reset();
}
void mesh_bed_leveling::report_mesh() {
SERIAL_ECHOLN(F(STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_Y) " mesh. Z offset: "), p_float_t(z_offset, 5), F("\nMeasured points:"));
print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 5, z_values[0]);
}
void mesh_bed_leveling::reset() {
z_offset = 0;
ZERO(z_values);
@@ -63,7 +70,7 @@
*/
void mesh_bed_leveling::line_to_destination(const feedRate_t scaled_fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
// Get current and destination cells for this line
xy_uint8_t scel = cell_indexes(current_position), ecel = cell_indexes(destination);
xy_uint8_t scel = cell_indexes(motion.position), ecel = cell_indexes(motion.destination);
NOMORE(scel.x, GRID_MAX_CELLS_X - 1);
NOMORE(scel.y, GRID_MAX_CELLS_Y - 1);
NOMORE(ecel.x, GRID_MAX_CELLS_X - 1);
@@ -71,12 +78,12 @@
// Start and end in the same cell? No split needed.
if (scel == ecel) {
current_position = destination;
line_to_current_position(scaled_fr_mm_s);
motion.position = motion.destination;
motion.goto_current_position(scaled_fr_mm_s);
return;
}
#define MBL_SEGMENT_END(A) (current_position.A + (destination.A - current_position.A) * normalized_dist)
#define MBL_SEGMENT_END(A) (motion.position.A + (motion.destination.A - motion.position.A) * normalized_dist)
float normalized_dist;
xyze_pos_t dest;
@@ -87,44 +94,39 @@
if (ecel.x != scel.x && TEST(x_splits, gcx)) {
// Split on the X grid line
CBI(x_splits, gcx);
dest = destination;
destination.x = index_to_xpos[gcx];
normalized_dist = (destination.x - current_position.x) / (dest.x - current_position.x);
destination.y = MBL_SEGMENT_END(y);
dest = motion.destination;
motion.destination.x = index_to_xpos[gcx];
normalized_dist = (motion.destination.x - motion.position.x) / (dest.x - motion.position.x);
motion.destination.y = MBL_SEGMENT_END(y);
}
// Crosses on the Y and not already split on this Y?
else if (ecel.y != scel.y && TEST(y_splits, gcy)) {
// Split on the Y grid line
CBI(y_splits, gcy);
dest = destination;
destination.y = index_to_ypos[gcy];
normalized_dist = (destination.y - current_position.y) / (dest.y - current_position.y);
destination.x = MBL_SEGMENT_END(x);
dest = motion.destination;
motion.destination.y = index_to_ypos[gcy];
normalized_dist = (motion.destination.y - motion.position.y) / (dest.y - motion.position.y);
motion.destination.x = MBL_SEGMENT_END(x);
}
else {
// Must already have been split on these border(s)
// This should be a rare case.
current_position = destination;
line_to_current_position(scaled_fr_mm_s);
motion.position = motion.destination;
motion.goto_current_position(scaled_fr_mm_s);
return;
}
destination.z = MBL_SEGMENT_END(z);
destination.e = MBL_SEGMENT_END(e);
motion.destination.z = MBL_SEGMENT_END(z);
motion.destination.e = MBL_SEGMENT_END(e);
// Do the split and look for more borders
line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
// Restore destination from stack
destination = dest;
motion.destination = dest;
line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
}
#endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
void mesh_bed_leveling::report_mesh() {
SERIAL_ECHOLN(F(STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_Y) " mesh. Z offset: "), p_float_t(z_offset, 5), F("\nMeasured points:"));
print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 5, z_values[0]);
}
#endif // MESH_BED_LEVELING
@@ -32,8 +32,7 @@ enum MeshLevelingState : char {
MeshReset // G29 S5
};
#define MESH_X_DIST (float((MESH_MAX_X) - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
#define MESH_Y_DIST (float((MESH_MAX_Y) - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
#include "../../../module/motion.h"
class mesh_bed_leveling {
public:
@@ -44,10 +43,12 @@ public:
mesh_bed_leveling();
static void report_mesh();
static void reset();
static void initialize();
static void report_mesh();
FORCE_INLINE static bool has_mesh() {
GRID_LOOP(x, y) if (z_values[x][y]) return true;
return false;
@@ -73,11 +74,11 @@ public:
static float get_mesh_y(const uint8_t i) { return index_to_ypos[i]; }
static uint8_t cell_index_x(const float x) {
int8_t cx = (x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST);
const int8_t cx = (x - mesh_min.x) * RECIPROCAL(MESH_X_DIST);
return constrain(cx, 0, GRID_MAX_CELLS_X - 1);
}
static uint8_t cell_index_y(const float y) {
int8_t cy = (y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST);
const int8_t cy = (y - mesh_min.y) * RECIPROCAL(MESH_Y_DIST);
return constrain(cy, 0, GRID_MAX_CELLS_Y - 1);
}
static xy_uint8_t cell_indexes(const float x, const float y) {
@@ -86,11 +87,11 @@ public:
static xy_uint8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); }
static int8_t probe_index_x(const float x) {
int8_t px = (x - (MESH_MIN_X) + 0.5f * (MESH_X_DIST)) * RECIPROCAL(MESH_X_DIST);
const int8_t px = (x - mesh_min.x + 0.5f * (MESH_X_DIST)) * RECIPROCAL(MESH_X_DIST);
return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1;
}
static int8_t probe_index_y(const float y) {
int8_t py = (y - (MESH_MIN_Y) + 0.5f * (MESH_Y_DIST)) * RECIPROCAL(MESH_Y_DIST);
const int8_t py = (y - mesh_min.y + 0.5f * (MESH_Y_DIST)) * RECIPROCAL(MESH_Y_DIST);
return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1;
}
static xy_int8_t probe_indexes(const float x, const float y) {
+24 -21
View File
@@ -63,23 +63,25 @@ void unified_bed_leveling::report_state() {
int8_t unified_bed_leveling::storage_slot;
float unified_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
bed_mesh_t unified_bed_leveling::z_values;
#define _GRIDPOS(A,N) (MESH_MIN_##A + N * (MESH_##A##_DIST))
#if !HAS_PROUI_MESH_EDIT
#define _GRIDPOS(A,N) (MESH_MIN_##A + N * (MESH_##A##_DIST))
const float
unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X,
_GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3),
_GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7),
_GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11),
_GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15)
),
unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y,
_GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3),
_GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7),
_GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11),
_GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15)
);
const float
unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X,
_GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3),
_GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7),
_GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11),
_GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15)
),
unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y,
_GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3),
_GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7),
_GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11),
_GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15)
);
#endif
volatile int16_t unified_bed_leveling::encoder_diff;
@@ -93,7 +95,7 @@ void unified_bed_leveling::reset() {
#if ENABLED(EXTENSIBLE_UI)
GRID_LOOP(x, y) ExtUI::onMeshUpdate(x, y, 0);
#endif
if (was_enabled) report_current_position();
if (was_enabled) motion.report_position();
}
void unified_bed_leveling::invalidate() {
@@ -173,8 +175,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
SERIAL_ECHOPGM("\nBed Topography Report");
if (human) {
SERIAL_ECHOLNPGM(":\n");
serial_echo_xy(4, MESH_MIN_X, MESH_MAX_Y);
serial_echo_xy(twixt, MESH_MAX_X, MESH_MAX_Y);
serial_echo_xy(4, mesh_min.x, mesh_max.y);
serial_echo_xy(twixt, mesh_max.x, mesh_max.y);
SERIAL_EOL();
serial_echo_column_labels(eachsp - 2);
}
@@ -184,7 +186,7 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
// Add XY probe offset from extruder because probe.probe_at_point() subtracts them when
// moving to the XY position to be measured. This ensures better agreement between
// the current Z position after G28 and the mesh values.
const xy_int8_t curr = closest_indexes(xy_pos_t(current_position) + probe.offset_xy);
const xy_int8_t curr = closest_indexes(xy_pos_t(motion.position) + probe.offset_xy);
if (!lcd) SERIAL_EOL();
for (int8_t j = (GRID_MAX_POINTS_Y) - 1; j >= 0; j--) {
@@ -207,6 +209,7 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
const float f = z_values[i][j];
if (lcd) {
// TODO: Display on Graphical LCD
TERN_(DWIN_LCD_PROUI, dwinMeshViewer());
}
else if (isnan(f))
SERIAL_ECHO(human ? F(" . ") : F("NAN"));
@@ -231,8 +234,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
if (human) {
serial_echo_column_labels(eachsp - 2);
SERIAL_EOL();
serial_echo_xy(4, MESH_MIN_X, MESH_MIN_Y);
serial_echo_xy(twixt, MESH_MAX_X, MESH_MIN_Y);
serial_echo_xy(4, mesh_min.x, mesh_min.y);
serial_echo_xy(twixt, mesh_max.x, mesh_min.y);
SERIAL_EOL();
SERIAL_EOL();
}
+34 -16
View File
@@ -38,9 +38,6 @@ enum MeshPointType : char { INVALID, REAL, SET_IN_BITMAP, CLOSEST };
struct mesh_index_pair;
#define MESH_X_DIST (float((MESH_MAX_X) - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
#define MESH_Y_DIST (float((MESH_MAX_Y) - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
#if ENABLED(OPTIMIZED_MESH_STORAGE)
typedef int16_t mesh_store_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
#endif
@@ -83,6 +80,16 @@ private:
return smart_fill_one(pos.x, pos.y, dir.x, dir.y);
}
// G29 sub-function handlers
static void G29_handle_homing_and_setup();
static void G29_handle_invalidate();
static bool G29_handle_test_patterns();
#if HAS_BED_PROBE
static void G29_handle_tilt_mesh();
#endif
static bool G29_handle_phase_ops();
static void G29_handle_post_processing();
#if ENABLED(UBL_DEVEL_DEBUGGING)
static void g29_what_command();
static void g29_eeprom_dump();
@@ -116,8 +123,11 @@ public:
static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values);
static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values);
#endif
static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X],
_mesh_index_to_ypos[GRID_MAX_POINTS_Y];
#if !HAS_PROUI_MESH_EDIT
static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X],
_mesh_index_to_ypos[GRID_MAX_POINTS_Y];
#endif
#if HAS_MARLINUI_MENU
static bool lcd_map_control;
@@ -133,11 +143,11 @@ public:
FORCE_INLINE static void set_z(const int8_t px, const int8_t py, const float z) { z_values[px][py] = z; }
static int8_t cell_index_x_raw(const float x) {
return FLOOR((x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST));
return FLOOR((x - mesh_min.x) * RECIPROCAL(MESH_X_DIST));
}
static int8_t cell_index_y_raw(const float y) {
return FLOOR((y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST));
return FLOOR((y - mesh_min.y) * RECIPROCAL(MESH_Y_DIST));
}
static bool cell_index_x_valid(const float x) {
@@ -162,11 +172,11 @@ public:
static xy_uint8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); }
static int8_t closest_x_index(const float x) {
const int8_t px = (x - (MESH_MIN_X) + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST);
const int8_t px = (x - mesh_min.x + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST);
return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1;
}
static int8_t closest_y_index(const float y) {
const int8_t py = (y - (MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST);
const int8_t py = (y - mesh_min.y + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST);
return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1;
}
static xy_int8_t closest_indexes(const xy_pos_t &xy) {
@@ -259,7 +269,7 @@ public:
* UBL_Z_RAISE_WHEN_OFF_MESH is specified, that value is returned.
*/
#ifdef UBL_Z_RAISE_WHEN_OFF_MESH
if (!WITHIN(rx0, MESH_MIN_X, MESH_MAX_X) || !WITHIN(ry0, MESH_MIN_Y, MESH_MAX_Y))
if (!WITHIN(rx0, mesh_min.x, mesh_max.x) || !WITHIN(ry0, mesh_min.y, mesh_max.y))
return UBL_Z_RAISE_WHEN_OFF_MESH;
#endif
@@ -287,12 +297,20 @@ public:
static constexpr float get_z_offset() { return 0.0f; }
static float get_mesh_x(const uint8_t i) {
return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
}
static float get_mesh_y(const uint8_t i) {
return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
}
static float _get_mesh_x(const uint8_t i) { return mesh_min.x + i * (MESH_X_DIST); }
static float _get_mesh_y(const uint8_t i) { return mesh_min.y + i * (MESH_Y_DIST); }
#if HAS_PROUI_MESH_EDIT
static float get_mesh_x(const uint8_t i) { return _get_mesh_x(i); }
static float get_mesh_y(const uint8_t i) { return _get_mesh_y(i); }
#else
static float get_mesh_x(const uint8_t i) {
return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : _get_mesh_x(i);
}
static float get_mesh_y(const uint8_t i) {
return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : _get_mesh_y(i);
}
#endif
#if UBL_SEGMENTED
static bool line_to_destination_segmented(const feedRate_t scaled_fr_mm_s);
+414 -354
View File
@@ -43,6 +43,10 @@
#include "../../../lcd/extui/ui_api.h"
#endif
#if ENABLED(DWIN_LCD_PROUI)
#include "../../../lcd/dwin/proui/meshviewer.h"
#endif
#if ENABLED(UBL_HILBERT_CURVE)
#include "../hilbert_curve.h"
#endif
@@ -315,305 +319,31 @@ void unified_bed_leveling::G29() {
// Potentially disable Fixed-Time Motion for probing
TERN_(FT_MOTION, FTM_DISABLE_IN_SCOPE());
// Check for commands that require the printer to be homed
if (may_move) {
planner.synchronize();
#if ALL(DWIN_LCD_PROUI, ZHOME_BEFORE_LEVELING)
save_ubl_active_state_and_disable();
gcode.process_subcommands_now(F("G28Z"));
restore_ubl_active_state(false); // ...without telling ExtUI "done"
#else
// Send 'N' to force homing before G29 (internal only)
if (axes_should_home() || parser.seen_test('N')) gcode.home_all_axes();
#endif
probe.use_probing_tool();
// Handle homing and initial setup
if (may_move) G29_handle_homing_and_setup();
#ifdef EVENT_GCODE_BEFORE_G29
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Before G29 G-code: ", EVENT_GCODE_BEFORE_G29);
gcode.process_subcommands_now(F(EVENT_GCODE_BEFORE_G29));
#endif
// Handle mesh invalidation (I parameter)
if (parser.seen('I')) G29_handle_invalidate();
// Position bed horizontally and Z probe vertically.
#if HAS_SAFE_BED_LEVELING
xyze_pos_t safe_position = current_position;
#ifdef SAFE_BED_LEVELING_START_X
safe_position.x = SAFE_BED_LEVELING_START_X;
#endif
#ifdef SAFE_BED_LEVELING_START_Y
safe_position.y = SAFE_BED_LEVELING_START_Y;
#endif
#ifdef SAFE_BED_LEVELING_START_Z
safe_position.z = SAFE_BED_LEVELING_START_Z;
#endif
#ifdef SAFE_BED_LEVELING_START_I
safe_position.i = SAFE_BED_LEVELING_START_I;
#endif
#ifdef SAFE_BED_LEVELING_START_J
safe_position.j = SAFE_BED_LEVELING_START_J;
#endif
#ifdef SAFE_BED_LEVELING_START_K
safe_position.k = SAFE_BED_LEVELING_START_K;
#endif
#ifdef SAFE_BED_LEVELING_START_U
safe_position.u = SAFE_BED_LEVELING_START_U;
#endif
#ifdef SAFE_BED_LEVELING_START_V
safe_position.v = SAFE_BED_LEVELING_START_V;
#endif
#ifdef SAFE_BED_LEVELING_START_W
safe_position.w = SAFE_BED_LEVELING_START_W;
#endif
do_blocking_move_to(safe_position);
#endif // HAS_SAFE_BED_LEVELING
}
// Invalidate one or more nearby mesh points, possibly all.
if (parser.seen('I')) {
grid_count_t count = parser.has_value() ? parser.value_ushort() : 1;
bool invalidate_all = count >= GRID_MAX_POINTS;
if (!invalidate_all) {
while (count--) {
if ((count & 0x0F) == 0x0F) marlin.idle();
const mesh_index_pair closest = find_closest_mesh_point_of_type(REAL, param.XY_pos);
// No more REAL mesh points to invalidate? Assume the user meant
// to invalidate the ENTIRE mesh, which can't be done with
// find_closest_mesh_point (which only returns REAL points).
if (closest.pos.x < 0) { invalidate_all = true; break; }
z_values[closest.pos.x][closest.pos.y] = NAN;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(closest.pos, 0.0f));
}
}
if (invalidate_all) {
invalidate();
SERIAL_ECHOPGM("Entire Mesh");
}
else
SERIAL_ECHOPGM("Locations");
SERIAL_ECHOLNPGM(" invalidated.\n");
}
if (parser.seen('Q')) {
const int16_t test_pattern = parser.has_value() ? parser.value_int() : -99;
if (!WITHIN(test_pattern, TERN0(UBL_DEVEL_DEBUGGING, -1), 2)) {
SERIAL_ECHOLN(F("?Invalid "), F("(Q) test pattern. (" TERN(UBL_DEVEL_DEBUGGING, "-1", "0") " to 2)\n"));
return;
}
SERIAL_ECHOLNPGM("Applying test pattern.\n");
switch (test_pattern) {
default:
case -1: TERN_(UBL_DEVEL_DEBUGGING, g29_eeprom_dump()); break;
case 0:
GRID_LOOP(x, y) { // Create a bowl shape similar to a poorly-calibrated Delta
const float p1 = 0.5f * (GRID_MAX_POINTS_X) - x,
p2 = 0.5f * (GRID_MAX_POINTS_Y) - y;
z_values[x][y] += 2.0f * HYPOT(p1, p2);
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
break;
case 1:
for (uint8_t x = 0; x < GRID_MAX_POINTS_X; ++x) { // Create a diagonal line several Mesh cells thick that is raised
const uint8_t x2 = x + (x < (GRID_MAX_POINTS_Y) - 1 ? 1 : -1);
z_values[x][x] += 9.999f;
z_values[x][x2] += 9.999f; // We want the altered line several mesh points thick
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(x, x, z_values[x][x]);
ExtUI::onMeshUpdate(x, x2, z_values[x][x2]);
#endif
}
break;
case 2:
// Allow the user to specify the height because 10mm is a little extreme in some cases.
for (uint8_t x = (GRID_MAX_POINTS_X) / 3; x < 2 * (GRID_MAX_POINTS_X) / 3; x++) // Create a rectangular raised area in
for (uint8_t y = (GRID_MAX_POINTS_Y) / 3; y < 2 * (GRID_MAX_POINTS_Y) / 3; y++) { // the center of the bed
z_values[x][y] += parser.seen_test('C') ? param.C_constant : 9.99f;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
break;
}
}
// Handle test patterns (Q parameter)
if (parser.seen('Q') && !G29_handle_test_patterns()) return;
// Handle tilt mesh (J parameter)
#if HAS_BED_PROBE
if (parser.seen_test('J')) G29_handle_tilt_mesh();
#endif
if (parser.seen_test('J')) {
save_ubl_active_state_and_disable();
tilt_mesh_based_on_probed_grid(param.J_grid_size == 0); // Zero size does 3-Point
restore_ubl_active_state();
#if ENABLED(UBL_G29_J_RECENTER)
do_blocking_move_to_xy(0.5f * ((MESH_MIN_X) + (MESH_MAX_X)), 0.5f * ((MESH_MIN_Y) + (MESH_MAX_Y)));
#endif
report_current_position();
SET_PROBE_DEPLOYED(true);
}
// Handle phase operations (P parameter)
if (parser.seen_test('P') && !G29_handle_phase_ops()) return;
#endif // HAS_BED_PROBE
if (parser.seen_test('P')) {
if (WITHIN(param.P_phase, 0, 1) && storage_slot == -1) {
storage_slot = 0;
SERIAL_ECHOLNPGM("Default storage slot 0 selected.");
}
switch (param.P_phase) {
case 0:
//
// Zero Mesh Data
//
reset();
SERIAL_ECHOLNPGM("Mesh zeroed.");
break;
#if HAS_BED_PROBE
case 1: {
//
// Invalidate Entire Mesh and Automatically Probe Mesh in areas that can be reached by the probe
//
if (!parser.seen_test('C')) {
invalidate();
SERIAL_ECHOLNPGM("Mesh invalidated. Probing mesh.");
}
if (param.V_verbosity > 1)
SERIAL_ECHOLN(F("Probing around ("), param.XY_pos.x, C(','), param.XY_pos.y, F(").\n"));
probe_entire_mesh(param.XY_pos, parser.seen_test('T'), parser.seen_test('E'), parser.seen_test('U'));
report_current_position();
SET_PROBE_DEPLOYED(true);
} break;
#endif // HAS_BED_PROBE
case 2: {
#if HAS_MARLINUI_MENU
//
// Manually Probe Mesh in areas that can't be reached by the probe
//
SERIAL_ECHOLNPGM("Manually probing unreachable points.");
do_z_clearance(Z_CLEARANCE_BETWEEN_PROBES);
if (parser.seen_test('C') && !param.XY_seen) {
/**
* Use a good default location for the path.
* The flipped > and < operators in these comparisons is intentional.
* It should cause the probed points to follow a nice path on Cartesian printers.
* It may make sense to have Delta printers default to the center of the bed.
* Until that is decided, this can be forced with the X and Y parameters.
*/
param.XY_pos.set(
#if IS_KINEMATIC
X_HOME_POS, Y_HOME_POS
#else
probe.offset_xy.x > 0 ? X_BED_SIZE : 0,
probe.offset_xy.y < 0 ? Y_BED_SIZE : 0
#endif
);
}
if (parser.seen('B')) {
param.B_shim_thickness = parser.has_value() ? parser.value_float() : measure_business_card_thickness();
if (ABS(param.B_shim_thickness) > 1.5f) {
SERIAL_ECHOLNPGM("?Error in Business Card measurement.");
return;
}
SET_PROBE_DEPLOYED(true);
}
if (!position_is_reachable(param.XY_pos)) {
SERIAL_ECHOLNPGM("XY outside printable radius.");
return;
}
const float height = parser.floatval('H', Z_CLEARANCE_BETWEEN_PROBES);
manually_probe_remaining_mesh(param.XY_pos, height, param.B_shim_thickness, parser.seen_test('T'));
SERIAL_ECHOLNPGM("G29 P2 finished.");
report_current_position();
#else
SERIAL_ECHOLNPGM("?P2 is only available when an LCD is present.");
return;
#endif
} break;
case 3: {
/**
* Populate invalid mesh areas. Proceed with caution.
* Two choices are available:
* - Specify a constant with the 'C' parameter.
* - Allow 'G29 P3' to choose a 'reasonable' constant.
*/
if (param.C_seen) {
if (param.R_repetition >= GRID_MAX_POINTS) {
set_all_mesh_points_to_value(param.C_constant);
}
else {
while (param.R_repetition--) { // this only populates reachable mesh points near
const mesh_index_pair closest = find_closest_mesh_point_of_type(INVALID, param.XY_pos);
const xy_int8_t &cpos = closest.pos;
if (cpos.x < 0) {
// No more REAL INVALID mesh points to populate, so we ASSUME
// user meant to populate ALL INVALID mesh points to value
GRID_LOOP(x, y) if (isnan(z_values[x][y])) z_values[x][y] = param.C_constant;
break; // No more invalid Mesh Points to populate
}
else {
z_values[cpos.x][cpos.y] = param.C_constant;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(cpos, param.C_constant));
}
}
}
}
else {
const float cvf = parser.value_float();
switch ((int)TRUNC(cvf * 10.0f) - 30) { // 3.1 -> 1
#if ENABLED(UBL_G29_P31)
case 1: {
// P3.1 use least squares fit to fill missing mesh values
// P3.10 zero weighting for distance, all grid points equal, best fit tilted plane
// P3.11 10X weighting for nearest grid points versus farthest grid points
// P3.12 100X distance weighting
// P3.13 1000X distance weighting, approaches simple average of nearest points
const float weight_power = (cvf - 3.10f) * 100.0f, // 3.12345 -> 2.345
weight_factor = weight_power ? POW(10.0f, weight_power) : 0;
smart_fill_wlsf(weight_factor);
}
break;
#endif
case 0: // P3 or P3.0
default: // and anything P3.x that's not P3.1
smart_fill_mesh(); // Do a 'Smart' fill using nearby known values
break;
}
}
break;
}
case 4: // Fine Tune (i.e., Edit) the Mesh
#if HAS_MARLINUI_MENU
fine_tune_mesh(param.XY_pos, parser.seen_test('T'));
#else
SERIAL_ECHOLNPGM("?P4 is only available when an LCD is present.");
return;
#endif
break;
case 5: adjust_mesh_to_mean(param.C_seen, param.C_constant); break;
case 6: shift_mesh_height(param.C_constant); break;
}
}
// Handle post-processing and cleanup
G29_handle_post_processing();
}
/**
* Handle post-processing and cleanup
*/
void unified_bed_leveling::G29_handle_post_processing() {
#if ENABLED(UBL_DEVEL_DEBUGGING)
//
@@ -661,7 +391,7 @@ void unified_bed_leveling::G29() {
// Store a Mesh in the EEPROM
//
if (parser.seen('S')) { // Store (or Save) Current Mesh Data
else if (parser.seen('S')) { // Store (or Save) Current Mesh Data
param.KLS_storage_slot = parser.has_value() ? (int8_t)parser.value_int() : storage_slot;
if (param.KLS_storage_slot == -1) // Special case: 'Export' the mesh to the
@@ -706,7 +436,337 @@ void unified_bed_leveling::G29() {
#endif
probe.use_probing_tool(false);
return;
}
/**
* Handle phase operations (P parameter)
* @return true if successful, false if error occurred
*/
bool unified_bed_leveling::G29_handle_phase_ops() {
if (WITHIN(param.P_phase, 0, 1) && storage_slot == -1) {
storage_slot = 0;
SERIAL_ECHOLNPGM("Default storage slot 0 selected.");
}
switch (param.P_phase) {
case 0:
//
// Zero Mesh Data
//
reset();
SERIAL_ECHOLNPGM("Mesh zeroed.");
break;
#if HAS_BED_PROBE
case 1: {
//
// Invalidate Entire Mesh and Automatically Probe Mesh in areas that can be reached by the probe
//
if (!parser.seen_test('C')) {
invalidate();
SERIAL_ECHOLNPGM("Mesh invalidated. Probing mesh.");
}
if (param.V_verbosity > 1)
SERIAL_ECHOLN(F("Probing around ("), param.XY_pos.x, C(','), param.XY_pos.y, F(").\n"));
probe_entire_mesh(param.XY_pos, parser.seen_test('T'), parser.seen_test('E'), parser.seen_test('U'));
motion.report_position();
SET_PROBE_DEPLOYED(true);
} break;
#endif // HAS_BED_PROBE
case 2: {
#if HAS_MARLINUI_MENU
//
// Manually Probe Mesh in areas that can't be reached by the probe
//
SERIAL_ECHOLNPGM("Manually probing unreachable points.");
motion.do_z_clearance(Z_CLEARANCE_BETWEEN_PROBES);
if (parser.seen_test('C') && !param.XY_seen) {
/**
* Use a good default location for the path.
* The flipped > and < operators in these comparisons is intentional.
* It should cause the probed points to follow a nice path on Cartesian printers.
* It may make sense to have Delta printers default to the center of the bed.
* Until that is decided, this can be forced with the X and Y parameters.
*/
param.XY_pos.set(
#if IS_KINEMATIC
X_HOME_POS, Y_HOME_POS
#else
probe.offset_xy.x > 0 ? X_BED_SIZE : 0,
probe.offset_xy.y < 0 ? Y_BED_SIZE : 0
#endif
);
}
if (parser.seen('B')) {
param.B_shim_thickness = parser.has_value() ? parser.value_float() : measure_business_card_thickness();
if (ABS(param.B_shim_thickness) > 1.5f) {
SERIAL_ECHOLNPGM("?Error in Business Card measurement.");
return false;
}
SET_PROBE_DEPLOYED(true);
}
if (!motion.can_reach(param.XY_pos)) {
SERIAL_ECHOLNPGM("XY outside printable radius.");
return false;
}
const float height = parser.floatval('H', Z_CLEARANCE_BETWEEN_PROBES);
manually_probe_remaining_mesh(param.XY_pos, height, param.B_shim_thickness, parser.seen_test('T'));
SERIAL_ECHOLNPGM("G29 P2 finished.");
motion.report_position();
#else
SERIAL_ECHOLNPGM("?P2 is only available when an LCD is present.");
return false;
#endif
} break;
case 3: {
/**
* Populate invalid mesh areas. Proceed with caution.
* Two choices are available:
* - Specify a constant with the 'C' parameter.
* - Allow 'G29 P3' to choose a 'reasonable' constant.
*/
if (param.C_seen) {
if (param.R_repetition >= GRID_MAX_POINTS) {
set_all_mesh_points_to_value(param.C_constant);
}
else {
while (param.R_repetition--) { // this only populates reachable mesh points near
const mesh_index_pair closest = find_closest_mesh_point_of_type(INVALID, param.XY_pos);
const xy_int8_t &cpos = closest.pos;
if (cpos.x < 0) {
// No more REAL INVALID mesh points to populate, so we ASSUME
// user meant to populate ALL INVALID mesh points to value
GRID_LOOP(x, y) if (isnan(z_values[x][y])) z_values[x][y] = param.C_constant;
break; // No more invalid Mesh Points to populate
}
else {
z_values[cpos.x][cpos.y] = param.C_constant;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(cpos, param.C_constant));
}
}
}
}
else {
const float cvf = parser.value_float();
switch ((int)TRUNC(cvf * 10.0f) - 30) { // 3.1 -> 1
#if ENABLED(UBL_G29_P31)
case 1: {
// P3.1 use least squares fit to fill missing mesh values
// P3.10 zero weighting for distance, all grid points equal, best fit tilted plane
// P3.11 10X weighting for nearest grid points versus farthest grid points
// P3.12 100X distance weighting
// P3.13 1000X distance weighting, approaches simple average of nearest points
const float weight_power = (cvf - 3.10f) * 100.0f, // 3.12345 -> 2.345
weight_factor = weight_power ? POW(10.0f, weight_power) : 0;
smart_fill_wlsf(weight_factor);
}
break;
#endif
case 0: // P3 or P3.0
default: // and anything P3.x that's not P3.1
smart_fill_mesh(); // Do a 'Smart' fill using nearby known values
break;
}
}
break;
}
case 4: // Fine Tune (i.e., Edit) the Mesh
#if HAS_MARLINUI_MENU
fine_tune_mesh(param.XY_pos, parser.seen_test('T'));
#else
SERIAL_ECHOLNPGM("?P4 is only available when an LCD is present.");
return false;
#endif
break;
case 5: adjust_mesh_to_mean(param.C_seen, param.C_constant); break;
case 6: shift_mesh_height(param.C_constant); break;
default:
SERIAL_ECHOLNPGM("?Invalid P value.\n");
return false;
}
return true;
}
/**
* Handle homing and initial setup for G29 command
* @param may_move Whether the command requires printer movement
* @return true if successful, false if error occurred
*/
void unified_bed_leveling::G29_handle_homing_and_setup() {
planner.synchronize();
#if ALL(DWIN_LCD_PROUI, ZHOME_BEFORE_LEVELING)
save_ubl_active_state_and_disable();
gcode.process_subcommands_now(F("G28Z"));
restore_ubl_active_state(false); // ...without telling ExtUI "done"
#else
// Send 'N' to force homing before G29 (internal only)
if (motion.axes_should_home() || parser.seen_test('N')) gcode.home_all_axes();
#endif
probe.use_probing_tool();
#ifdef EVENT_GCODE_BEFORE_G29
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Before G29 G-code: ", EVENT_GCODE_BEFORE_G29);
gcode.process_subcommands_now(F(EVENT_GCODE_BEFORE_G29));
#endif
// Position bed horizontally and Z probe vertically.
#if HAS_SAFE_BED_LEVELING
xyze_pos_t safe_position = motion.position;
#ifdef SAFE_BED_LEVELING_START_X
safe_position.x = SAFE_BED_LEVELING_START_X;
#endif
#ifdef SAFE_BED_LEVELING_START_Y
safe_position.y = SAFE_BED_LEVELING_START_Y;
#endif
#ifdef SAFE_BED_LEVELING_START_Z
safe_position.z = SAFE_BED_LEVELING_START_Z;
#endif
#ifdef SAFE_BED_LEVELING_START_I
safe_position.i = SAFE_BED_LEVELING_START_I;
#endif
#ifdef SAFE_BED_LEVELING_START_J
safe_position.j = SAFE_BED_LEVELING_START_J;
#endif
#ifdef SAFE_BED_LEVELING_START_K
safe_position.k = SAFE_BED_LEVELING_START_K;
#endif
#ifdef SAFE_BED_LEVELING_START_U
safe_position.u = SAFE_BED_LEVELING_START_U;
#endif
#ifdef SAFE_BED_LEVELING_START_V
safe_position.v = SAFE_BED_LEVELING_START_V;
#endif
#ifdef SAFE_BED_LEVELING_START_W
safe_position.w = SAFE_BED_LEVELING_START_W;
#endif
motion.blocking_move(safe_position);
#endif // HAS_SAFE_BED_LEVELING
}
/**
* Handle mesh invalidation (I parameter)
*/
void unified_bed_leveling::G29_handle_invalidate() {
// Invalidate one or more nearby mesh points, possibly all.
grid_count_t count = parser.has_value() ? parser.value_ushort() : 1;
bool invalidate_all = count >= GRID_MAX_POINTS;
if (!invalidate_all) {
while (count--) {
if ((count & 0x0F) == 0x0F) marlin.idle();
const mesh_index_pair closest = find_closest_mesh_point_of_type(REAL, param.XY_pos);
// No more REAL mesh points to invalidate? Assume the user meant
// to invalidate the ENTIRE mesh, which can't be done with
// find_closest_mesh_point (which only returns REAL points).
if (closest.pos.x < 0) { invalidate_all = true; break; }
z_values[closest.pos.x][closest.pos.y] = NAN;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(closest.pos, 0.0f));
}
}
if (invalidate_all) {
invalidate();
SERIAL_ECHOPGM("Entire Mesh");
}
else
SERIAL_ECHOPGM("Locations");
SERIAL_ECHOLNPGM(" invalidated.\n");
}
#if HAS_BED_PROBE
/**
* Handle tilt mesh (J parameter)
*/
void unified_bed_leveling::G29_handle_tilt_mesh() {
save_ubl_active_state_and_disable();
tilt_mesh_based_on_probed_grid(param.J_grid_size == 0); // Zero size does 3-Point
restore_ubl_active_state();
#if ENABLED(UBL_G29_J_RECENTER)
motion.blocking_move_xy(0.5f * (mesh_min.x + mesh_max.x), 0.5f * (mesh_min.y + mesh_max.y));
#endif
motion.report_position();
SET_PROBE_DEPLOYED(true);
}
#endif // HAS_BED_PROBE
/**
* Handle test patterns (Q parameter)
* @return true if successful, false if error occurred
*/
bool unified_bed_leveling::G29_handle_test_patterns() {
const int16_t test_pattern = parser.has_value() ? parser.value_int() : -99;
if (!WITHIN(test_pattern, TERN0(UBL_DEVEL_DEBUGGING, -1), 2)) {
SERIAL_ECHOLN(F("?Invalid "), F("(Q) test pattern. (" TERN(UBL_DEVEL_DEBUGGING, "-1", "0") " to 2)\n"));
return false;
}
SERIAL_ECHOLNPGM("Applying test pattern.\n");
switch (test_pattern) {
default:
case -1: TERN_(UBL_DEVEL_DEBUGGING, g29_eeprom_dump()); break;
case 0:
// Create a bowl shape similar to a poorly-calibrated Delta
GRID_LOOP(x, y) {
const float p1 = 0.5f * (GRID_MAX_POINTS_X) - x,
p2 = 0.5f * (GRID_MAX_POINTS_Y) - y;
z_values[x][y] += 2.0f * HYPOT(p1, p2);
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
break;
case 1:
// Create a diagonal line several Mesh cells thick that is raised
for (uint8_t x = 0; x < GRID_MAX_POINTS_X; ++x) {
const uint8_t x2 = x + (x < (GRID_MAX_POINTS_Y) - 1 ? 1 : -1);
z_values[x][x] += 9.999f;
z_values[x][x2] += 9.999f; // We want the altered line several mesh points thick
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(x, x, z_values[x][x]);
ExtUI::onMeshUpdate(x, x2, z_values[x][x2]);
#endif
}
break;
case 2:
// Allow the user to specify the height because 10mm is a little extreme in some cases.
for (uint8_t x = (GRID_MAX_POINTS_X) / 3; x < 2 * (GRID_MAX_POINTS_X) / 3; x++) // Create a rectangular raised area in
for (uint8_t y = (GRID_MAX_POINTS_Y) / 3; y < 2 * (GRID_MAX_POINTS_Y) / 3; y++) { // the center of the bed
z_values[x][y] += parser.seen_test('C') ? param.C_constant : 9.99f;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
break;
}
return true;
}
void unified_bed_leveling::shift_mesh_height(const float zoffs) {
GRID_LOOP(x, y)
if (!isnan(z_values[x][y])) {
z_values[x][y] += zoffs;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
}
/**
@@ -747,17 +807,6 @@ void unified_bed_leveling::adjust_mesh_to_mean(const bool cflag, const float off
}
}
/**
* G29 P6 C<offset> : Shift Mesh Height by a uniform constant.
*/
void unified_bed_leveling::shift_mesh_height(const float zoffs) {
GRID_LOOP(x, y)
if (!isnan(z_values[x][y])) {
z_values[x][y] += zoffs;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
}
#if HAS_BED_PROBE
/**
* G29 P1 T<maptype> V<verbosity> : Probe Entire Mesh
@@ -783,6 +832,10 @@ void unified_bed_leveling::shift_mesh_height(const float zoffs) {
TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), point_num, int(GRID_MAX_POINTS)));
TERN_(HAS_BACKLIGHT_TIMEOUT, ui.refresh_backlight_timeout());
#if ENABLED(DWIN_LCD_PROUI)
if (!hmiFlag.cancel_lev) dwinRedrawScreen(); else break;
#endif
#if HAS_MARLINUI_MENU
if (ui.button_pressed()) {
ui.quick_feedback(false); // Preserve button state for click-and-hold
@@ -816,6 +869,9 @@ void unified_bed_leveling::shift_mesh_height(const float zoffs) {
} while (best.pos.x >= 0 && --count);
if (TERN0(DWIN_LCD_PROUI, hmiFlag.cancel_lev))
goto EXIT_PROBE_MESH;
GRID_LOOP(x, y) if (z_values[x][y] == HUGE_VALF) z_values[x][y] = NAN; // Restore NAN for HUGE_VALF marks
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_FINISH));
@@ -827,10 +883,16 @@ void unified_bed_leveling::shift_mesh_height(const float zoffs) {
probe.move_z_after_probing();
do_blocking_move_to_xy(
constrain(nearby.x - probe.offset_xy.x, MESH_MIN_X, MESH_MAX_X),
constrain(nearby.y - probe.offset_xy.y, MESH_MIN_Y, MESH_MAX_Y)
);
#if ENABLED(DWIN_LCD_PROUI)
bedlevel.smart_fill_mesh();
#else
motion.blocking_move_xy(
constrain(nearby.x - probe.offset_xy.x, mesh_min.x, mesh_max.x),
constrain(nearby.y - probe.offset_xy.y, mesh_min.y, mesh_max.y)
);
#endif
EXIT_PROBE_MESH:
restore_ubl_active_state();
}
@@ -874,7 +936,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
marlin.idle();
gcode.reset_stepper_timeout(); // Keep steppers powered
if (encoder_diff) {
do_blocking_move_to_z(current_position.z + float(encoder_diff) * multiplier);
motion.blocking_move_z(motion.position.z + float(encoder_diff) * multiplier);
encoder_diff = 0;
}
}
@@ -884,7 +946,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
KEEPALIVE_STATE(PAUSED_FOR_USER);
const float z_step = 0.01f;
move_z_with_encoder(z_step);
return current_position.z;
return motion.position.z;
}
static void echo_and_take_a_measurement() { SERIAL_ECHOLNPGM(" and take a measurement."); }
@@ -893,10 +955,10 @@ void set_message_with_feedback(FSTR_P const fstr) {
ui.capture();
save_ubl_active_state_and_disable(); // Disable bed level correction for probing
do_blocking_move_to(
motion.blocking_move(
xyz_pos_t({
0.5f * ((MESH_MAX_X) - (MESH_MIN_X)),
0.5f * ((MESH_MAX_Y) - (MESH_MIN_Y)),
0.5f * (mesh_min.x + mesh_max.x),
0.5f * (mesh_min.y + mesh_max.y),
MANUAL_PROBE_START_Z
#ifdef SAFE_BED_LEVELING_START_I
, SAFE_BED_LEVELING_START_I
@@ -927,14 +989,14 @@ void set_message_with_feedback(FSTR_P const fstr) {
echo_and_take_a_measurement();
const float z1 = measure_point_with_encoder();
do_z_clearance_by(SIZE_OF_LITTLE_RAISE);
motion.do_z_clearance_by(SIZE_OF_LITTLE_RAISE);
SERIAL_ECHOPGM("Remove shim");
LCD_MESSAGE(MSG_UBL_BC_REMOVE);
echo_and_take_a_measurement();
const float z2 = measure_point_with_encoder();
do_z_clearance_by(Z_CLEARANCE_BETWEEN_PROBES);
motion.do_z_clearance_by(Z_CLEARANCE_BETWEEN_PROBES);
const float thickness = ABS(z1 - z2);
@@ -956,7 +1018,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart());
save_ubl_active_state_and_disable(); // No bed level correction so only raw data is obtained
do_blocking_move_to_xy_z(current_position, z_clearance);
motion.blocking_move_xy_z(motion.position, z_clearance);
ui.return_to_status();
@@ -969,12 +1031,12 @@ void set_message_with_feedback(FSTR_P const fstr) {
const xyz_pos_t ppos = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), z_clearance };
if (!position_is_reachable(ppos)) break; // SHOULD NOT OCCUR (find_closest_mesh_point only returns reachable points)
if (!motion.can_reach(ppos)) break; // SHOULD NOT OCCUR (find_closest_mesh_point only returns reachable points)
LCD_MESSAGE(MSG_UBL_MOVING_TO_NEXT);
do_blocking_move_to(ppos);
do_z_clearance(z_clearance);
motion.blocking_move(ppos);
motion.do_z_clearance(z_clearance);
KEEPALIVE_STATE(PAUSED_FOR_USER);
ui.capture();
@@ -995,11 +1057,11 @@ void set_message_with_feedback(FSTR_P const fstr) {
if (_click_and_hold([]{
SERIAL_ECHOLNPGM("\nMesh only partially populated.");
do_z_clearance(Z_CLEARANCE_DEPLOY_PROBE);
motion.do_z_clearance(Z_CLEARANCE_DEPLOY_PROBE);
})) return restore_ubl_active_state();
// Store the Z position minus the shim height
z_values[lpos.x][lpos.y] = current_position.z - thick;
z_values[lpos.x][lpos.y] = motion.position.z - thick;
// Tell the external UI to update
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(location, z_values[lpos.x][lpos.y]));
@@ -1012,7 +1074,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
if (do_ubl_mesh_map) display_map(param.T_map_type); // show user where we're probing
restore_ubl_active_state();
do_blocking_move_to_xy_z(pos, Z_CLEARANCE_DEPLOY_PROBE);
motion.blocking_move_xy_z(pos, Z_CLEARANCE_DEPLOY_PROBE);
}
/**
@@ -1033,7 +1095,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
mesh_index_pair location;
if (!position_is_reachable(pos)) {
if (!motion.can_reach(pos)) {
SERIAL_ECHOLNPGM("(X,Y) outside printable radius.");
return;
}
@@ -1043,7 +1105,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
LCD_MESSAGE(MSG_UBL_FINE_TUNE_MESH);
ui.capture(); // Take over control of the LCD encoder
do_blocking_move_to_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE); // Move to the given XY with probe clearance
motion.blocking_move_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE); // Move to the given XY with probe clearance
MeshFlags done_flags{0};
const xy_int8_t &lpos = location.pos;
@@ -1062,18 +1124,18 @@ void set_message_with_feedback(FSTR_P const fstr) {
// location is used on the next loop
const xyz_pos_t raw = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), Z_TWEEN_SAFE_CLEARANCE };
if (!position_is_reachable(raw)) break; // SHOULD NOT OCCUR (find_closest_mesh_point_of_type only returns reachable)
if (!motion.can_reach(raw)) break; // SHOULD NOT OCCUR (find_closest_mesh_point_of_type only returns reachable)
do_blocking_move_to(raw); // Move the nozzle to the edit point with probe clearance
motion.blocking_move(raw); // Move the nozzle to the edit point with probe clearance
TERN_(UBL_MESH_EDIT_MOVES_Z, do_blocking_move_to_z(h_offset)); // Move Z to the given 'H' offset before editing
TERN_(UBL_MESH_EDIT_MOVES_Z, motion.blocking_move_z(h_offset)); // Move Z to the given 'H' offset before editing
KEEPALIVE_STATE(PAUSED_FOR_USER);
if (do_ubl_mesh_map) display_map(param.T_map_type); // Display the current point
#if IS_TFTGLCD_PANEL
ui.ubl_plot(lpos.x, lpos.y); // update plot screen
ui.ubl_plot(lpos.x, lpos.y); // Update plot screen
#endif
ui.refresh();
@@ -1084,23 +1146,23 @@ void set_message_with_feedback(FSTR_P const fstr) {
ui.ubl_mesh_edit_start(new_z);
SET_SOFT_ENDSTOP_LOOSE(true);
motion.set_soft_endstop_loose(true);
do {
marlin.idle_no_sleep();
new_z = ui.ubl_mesh_value();
TERN_(UBL_MESH_EDIT_MOVES_Z, do_blocking_move_to_z(h_offset + new_z)); // Move the nozzle as the point is edited
TERN_(UBL_MESH_EDIT_MOVES_Z, motion.blocking_move_z(h_offset + new_z)); // Move the nozzle as the point is edited
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
} while (!ui.button_pressed());
SET_SOFT_ENDSTOP_LOOSE(false);
motion.set_soft_endstop_loose(false);
if (!lcd_map_control) ui.return_to_status(); // Just editing a single point? Return to status
// Button held down? Abort editing
if (_click_and_hold([]{
ui.return_to_status();
do_z_clearance(Z_TWEEN_SAFE_CLEARANCE);
motion.do_z_clearance(Z_TWEEN_SAFE_CLEARANCE);
set_message_with_feedback(GET_TEXT_F(MSG_EDITING_STOPPED));
})) break;
@@ -1120,7 +1182,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
if (do_ubl_mesh_map) display_map(param.T_map_type);
restore_ubl_active_state();
do_blocking_move_to_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE);
motion.blocking_move_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE);
LCD_MESSAGE(MSG_UBL_DONE_EDITING_MESH);
SERIAL_ECHOLNPGM("Done Editing Mesh");
@@ -1191,9 +1253,9 @@ bool unified_bed_leveling::G29_parse_parameters() {
}
param.XY_seen.x = parser.seenval('X');
float sx = param.XY_seen.x ? parser.value_float() : current_position.x;
float sx = param.XY_seen.x ? parser.value_float() : DIFF_TERN(HAS_BED_PROBE, motion.position.x, probe.offset.x);
param.XY_seen.y = parser.seenval('Y');
float sy = param.XY_seen.y ? parser.value_float() : current_position.y;
float sy = param.XY_seen.y ? parser.value_float() : DIFF_TERN(HAS_BED_PROBE, motion.position.y, probe.offset.y);
if (param.XY_seen.x != param.XY_seen.y) {
SERIAL_ECHOLNPGM("Both X & Y locations must be specified.\n");
@@ -1202,8 +1264,8 @@ bool unified_bed_leveling::G29_parse_parameters() {
// If X or Y are not valid, use center of the bed values
// (for UBL_HILBERT_CURVE default to lower-left corner instead)
if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = TERN(UBL_HILBERT_CURVE, 0, X_CENTER);
if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = TERN(UBL_HILBERT_CURVE, 0, Y_CENTER);
if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = TERN(UBL_HILBERT_CURVE, 0, DIFF_TERN(HAS_BED_PROBE, X_CENTER, probe.offset.x));
if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = TERN(UBL_HILBERT_CURVE, 0, DIFF_TERN(HAS_BED_PROBE, Y_CENTER, probe.offset.y));
if (err_flag) return UBL_ERR;
@@ -1358,7 +1420,7 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
// Also for round beds, there are grid points outside the bed the nozzle can't reach.
// Prune them from the list and ignore them till the next Phase (manual nozzle probing).
if (!(d->probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
if (!(d->probe_relative ? probe.can_reach(mpos) : motion.can_reach(mpos)))
return false;
d->closest.pos.set(i, j);
return true;
@@ -1402,12 +1464,12 @@ mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const Mesh
// Also for round beds, there are grid points outside the bed the nozzle can't reach.
// Prune them from the list and ignore them till the next Phase (manual nozzle probing).
if (!(probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
if (!(probe_relative ? probe.can_reach(mpos) : motion.can_reach(mpos)))
continue;
// Reachable. Check if it's the best_so_far location to the nozzle.
const xy_pos_t diff = current_position - mpos;
const xy_pos_t diff = motion.position - mpos;
const float distance = (ref - mpos).magnitude() + diff.magnitude() * 0.1f;
// factor in the distance from the current location for the normal case
@@ -1535,10 +1597,10 @@ void unified_bed_leveling::smart_fill_mesh() {
#ifndef G29J_MESH_TILT_MARGIN
#define G29J_MESH_TILT_MARGIN 0
#endif
const float x_min = _MAX((X_MIN_POS) + (G29J_MESH_TILT_MARGIN), MESH_MIN_X, probe.min_x()),
x_max = _MIN((X_MAX_POS) - (G29J_MESH_TILT_MARGIN), MESH_MAX_X, probe.max_x()),
y_min = _MAX((Y_MIN_POS) + (G29J_MESH_TILT_MARGIN), MESH_MIN_Y, probe.min_y()),
y_max = _MIN((Y_MAX_POS) - (G29J_MESH_TILT_MARGIN), MESH_MAX_Y, probe.max_y()),
const float x_min = _MAX((X_MIN_POS) + (G29J_MESH_TILT_MARGIN), mesh_min.x, probe.min_x()),
x_max = _MIN((X_MAX_POS) - (G29J_MESH_TILT_MARGIN), mesh_max.x, probe.max_x()),
y_min = _MAX((Y_MIN_POS) + (G29J_MESH_TILT_MARGIN), mesh_min.y, probe.min_y()),
y_max = _MIN((Y_MAX_POS) - (G29J_MESH_TILT_MARGIN), mesh_max.y, probe.max_y()),
dx = (x_max - x_min) / (param.J_grid_size - 1),
dy = (y_max - y_min) / (param.J_grid_size - 1);
@@ -1760,25 +1822,23 @@ void unified_bed_leveling::smart_fill_mesh() {
SERIAL_ECHOLNPGM("Probe Offset M851 Z", p_float_t(probe.offset.z, 7));
#endif
SERIAL_ECHOLNPGM("MESH_MIN_X " STRINGIFY(MESH_MIN_X) "=", MESH_MIN_X); serial_delay(50);
SERIAL_ECHOLNPGM("MESH_MIN_Y " STRINGIFY(MESH_MIN_Y) "=", MESH_MIN_Y); serial_delay(50);
SERIAL_ECHOLNPGM("MESH_MAX_X " STRINGIFY(MESH_MAX_X) "=", MESH_MAX_X); serial_delay(50);
SERIAL_ECHOLNPGM("MESH_MAX_Y " STRINGIFY(MESH_MAX_Y) "=", MESH_MAX_Y); serial_delay(50);
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X); serial_delay(50);
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y); serial_delay(50);
SERIAL_ECHOLNPGM("mesh_min ", mesh_min.x, ", ", mesh_min.y); serial_delay(50);
SERIAL_ECHOLNPGM("mesh_max ", mesh_max.x, ", ", mesh_max.y); serial_delay(50);
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X); serial_delay(50);
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y); serial_delay(50);
SERIAL_ECHOLNPGM("MESH_X_DIST ", MESH_X_DIST);
SERIAL_ECHOLNPGM("MESH_Y_DIST ", MESH_Y_DIST); serial_delay(50);
SERIAL_ECHOLNPGM("MESH_Y_DIST ", MESH_Y_DIST); serial_delay(50);
SERIAL_ECHOPGM("X-Axis Mesh Points at: ");
for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i) {
SERIAL_ECHO(p_float_t(LOGICAL_X_POSITION(get_mesh_x(i)), 3), F(" "));
SERIAL_ECHO(p_float_t(motion.logical_x(get_mesh_x(i)), 3), F(" "));
serial_delay(25);
}
SERIAL_EOL();
SERIAL_ECHOPGM("Y-Axis Mesh Points at: ");
for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; ++i) {
SERIAL_ECHO(p_float_t(LOGICAL_Y_POSITION(get_mesh_y(i)), 3), F(" "));
SERIAL_ECHO(p_float_t(motion.logical_y(get_mesh_y(i)), 3), F(" "));
serial_delay(25);
}
SERIAL_EOL();
+24 -24
View File
@@ -53,11 +53,11 @@
* just do the required Z-Height correction, call the Planner's buffer_line() routine, and leave
*/
#if HAS_POSITION_MODIFIERS
xyze_pos_t start = current_position, end = destination;
xyze_pos_t start = motion.position, end = motion.destination;
planner.apply_modifiers(start);
planner.apply_modifiers(end);
#else
const xyze_pos_t &start = current_position, &end = destination;
const xyze_pos_t &start = motion.position, &end = motion.destination;
#endif
const xy_uint8_t istart = cell_indexes(start), iend = cell_indexes(end);
@@ -78,7 +78,7 @@
end.z += UBL_Z_RAISE_WHEN_OFF_MESH;
planner.buffer_segment(end, scaled_fr_mm_s, extruder);
current_position = destination;
motion.position = motion.destination;
return;
}
#endif
@@ -96,7 +96,7 @@
// Replace NAN corrections with 0.0 to prevent NAN propagation.
if (!isnan(z0)) end.z += z0;
planner.buffer_segment(end, scaled_fr_mm_s, extruder);
current_position = destination;
motion.position = motion.destination;
return;
}
@@ -190,10 +190,10 @@
}
// At the final destination? Usually not, but when on a Y Mesh Line it's completed.
if (xy_pos_t(current_position) != xy_pos_t(end))
if (xy_pos_t(motion.position) != xy_pos_t(end))
goto FINAL_MOVE;
current_position = destination;
motion.position = motion.destination;
return;
}
@@ -240,10 +240,10 @@
DEBUG_ECHOLNPGM("[ubl] skip Y segment");
}
if (xy_pos_t(current_position) != xy_pos_t(end))
if (xy_pos_t(motion.position) != xy_pos_t(end))
goto FINAL_MOVE;
current_position = destination;
motion.position = motion.destination;
return;
}
@@ -324,10 +324,10 @@
if (cnt.x < 0 || cnt.y < 0) break; // Too far! Exit the loop and go to FINAL_MOVE
}
if (xy_pos_t(current_position) != xy_pos_t(end))
if (xy_pos_t(motion.position) != xy_pos_t(end))
goto FINAL_MOVE;
current_position = destination;
motion.position = motion.destination;
}
#else // UBL_SEGMENTED
@@ -347,15 +347,15 @@
/**
* Prepare a segmented linear move for DELTA/SCARA/CARTESIAN with UBL and FADE semantics.
* This calls planner.buffer_segment multiple times for small incremental moves.
* Returns true if did NOT move, false if moved (requires current_position update).
* Returns true if did NOT move, false if moved (requires motion.position update).
*/
bool __O2 unified_bed_leveling::line_to_destination_segmented(const feedRate_t scaled_fr_mm_s) {
if (!position_is_reachable(destination)) // fail if moving outside reachable boundary
return true; // did not move, so current_position still accurate
if (!motion.can_reach(motion.destination)) // Fail if moving outside reachable boundary
return true; // Did not move, so motion.position still accurate
const xyze_pos_t total = destination - current_position;
const xyze_pos_t total = motion.destination - motion.position;
const float cart_xy_mm_2 = HYPOT2(total.x, total.y),
cart_xy_mm = SQRT(cart_xy_mm_2); // Total XY distance
@@ -383,22 +383,22 @@
// Note that E segment distance could vary slightly as z mesh height
// changes for each segment, but small enough to ignore.
xyze_pos_t raw = current_position;
xyze_pos_t raw = motion.position;
// Just do plain segmentation if UBL is inactive or the target is above the fade height
if (!planner.leveling_active || !planner.leveling_active_at_z(destination.z)) {
if (!planner.leveling_active || !planner.leveling_active_at_z(motion.destination.z)) {
while (--segments) {
raw += diff;
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints);
planner.buffer_line(raw, scaled_fr_mm_s, motion.extruder, hints);
}
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, hints);
planner.buffer_line(motion.destination, scaled_fr_mm_s, motion.extruder, hints);
return false; // Did not set current from destination
}
// Otherwise perform per-segment leveling
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
const float fade_scaling_factor = planner.fade_scaling_factor_for_z(destination.z);
const float fade_scaling_factor = planner.fade_scaling_factor_for_z(motion.destination.z);
#endif
// Move to first segment destination
@@ -414,8 +414,8 @@
// for mesh inset area.
xy_int8_t icell = {
int8_t((raw.x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST)),
int8_t((raw.y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST))
int8_t((raw.x - mesh_min.x) * RECIPROCAL(MESH_X_DIST)),
int8_t((raw.y - mesh_min.y) * RECIPROCAL(MESH_Y_DIST))
};
LIMIT(icell.x, 0, GRID_MAX_CELLS_X);
LIMIT(icell.y, 0, GRID_MAX_CELLS_Y);
@@ -456,13 +456,13 @@
for (;;) { // for all segments within this mesh cell
if (--segments == 0) raw = destination; // if this is last segment, use destination for exact
if (--segments == 0) raw = motion.destination; // If this is last segment, use destination for exact
const float z_cxcy = (z_cxy0 + z_cxym * cell.y) // interpolated mesh z height along cell.x at cell.y
TERN_(ENABLE_LEVELING_FADE_HEIGHT, * fade_scaling_factor); // apply fade factor to interpolated height
const float oldz = raw.z; raw.z += z_cxcy;
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints);
planner.buffer_line(raw, scaled_fr_mm_s, motion.extruder, hints);
raw.z = oldz;
if (segments == 0) // done with last segment
@@ -483,7 +483,7 @@
} // segment loop
} // cell loop
return false; // caller will update current_position
return false; // caller will update motion.position
}
#endif // UBL_SEGMENTED
+1 -1
View File
@@ -134,7 +134,7 @@ void ControllerFan::update() {
} while (0)
#if ENABLED(FAN_SOFT_PWM)
soft_pwm_speed = speed;
soft_pwm_speed = speed >> 1; // Controller Fan Soft PWM uses 0-127 as 0-100% so cut the 0-255 range in half.
#else
SET_CONTROLLER_FAN();
#if PIN_EXISTS(CONTROLLER_FAN2)
+9 -8
View File
@@ -54,10 +54,11 @@ EmergencyParser emergency_parser;
#endif
#if ENABLED(REALTIME_REPORTING_COMMANDS)
// From motion.h, which cannot be included here
void report_current_position_moving();
void quickpause_stepper();
void quickresume_stepper();
#include "../module/motion.h"
#endif
#if ENABLED(SOFT_FEED_HOLD)
bool realtime_ramping_pause_flag = false;
#endif
void EmergencyParser::update(EmergencyParser::State &state, const uint8_t c) {
@@ -150,7 +151,7 @@ void EmergencyParser::update(EmergencyParser::State &state, const uint8_t c) {
case EP_M4:
switch (c) {
case '1' :state = EP_M41; break;
#if ENABLED(FT_MOTION_RESONANCE_TEST)
#if ENABLED(FTM_RESONANCE_TEST)
case '9': state = EP_M49; break;
#endif
default: state = EP_IGNORE;
@@ -222,9 +223,9 @@ void EmergencyParser::update(EmergencyParser::State &state, const uint8_t c) {
case EP_M876SN: hostui.handle_response(M876_reason); break;
#endif
#if ENABLED(REALTIME_REPORTING_COMMANDS)
case EP_GRBL_STATUS: report_current_position_moving(); break;
case EP_GRBL_PAUSE: quickpause_stepper(); break;
case EP_GRBL_RESUME: quickresume_stepper(); break;
case EP_GRBL_STATUS: motion.report_position_moving(); break;
case EP_GRBL_PAUSE: TERN(SOFT_FEED_HOLD, realtime_ramping_pause_flag = true, motion.quickpause_stepper()); break;
case EP_GRBL_RESUME: TERN(SOFT_FEED_HOLD, realtime_ramping_pause_flag = false, motion.quickresume_stepper()); break;
#endif
#if ENABLED(SOFT_RESET_VIA_SERIAL)
case EP_KILL: hal.reboot(); break;
+4
View File
@@ -93,3 +93,7 @@ private:
};
extern EmergencyParser emergency_parser;
#if ENABLED(SOFT_FEED_HOLD)
extern bool realtime_ramping_pause_flag;
#endif
+1 -1
View File
@@ -136,7 +136,7 @@ void EasythreedUI::loadButton() {
if (READ(BTN_RETRACT) && READ(BTN_FEED)) { // Switch in center position (stop)
flag = false; // Restore flag to false
filament_status = FS_IDLE; // Go back to idle state
quickstop_stepper(); // Hard-stop all the steppers ... now!
motion.quickstop_stepper(); // Hard-stop all the steppers ... now!
thermalManager.disable_all_heaters(); // And disable all the heaters
blink_interval_ms = LED_ON;
}
+6 -6
View File
@@ -318,9 +318,9 @@ bool I2CPositionEncoder::test_axis() {
// Only works on XYZ Cartesian machines for the time being
if (!(encoderAxis == X_AXIS || encoderAxis == Y_AXIS || encoderAxis == Z_AXIS)) return false;
const float startPosition = soft_endstop.min[encoderAxis] + 10,
endPosition = soft_endstop.max[encoderAxis] - 10;
const feedRate_t fr_mm_s = FLOOR(homing_feedrate(encoderAxis));
const float startPosition = motion.soft_endstop.min[encoderAxis] + 10,
endPosition = motion.soft_endstop.max[encoderAxis] - 10;
const feedRate_t fr_mm_s = FLOOR(motion.homing_feedrate(encoderAxis));
ec = false;
@@ -373,13 +373,13 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
int32_t startCount, stopCount;
const feedRate_t fr_mm_s = homing_feedrate(encoderAxis);
const feedRate_t fr_mm_s = motion.homing_feedrate(encoderAxis);
bool oldec = ec;
ec = false;
startDistance = 20;
endDistance = soft_endstop.max[encoderAxis] - 20;
endDistance = motion.soft_endstop.max[encoderAxis] - 20;
travelDistance = endDistance - startDistance;
xyze_pos_t startCoord, endCoord;
@@ -400,7 +400,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
delay(250);
startCount = get_position();
//do_blocking_move_to(endCoord);
//motion.blocking_move(endCoord);
TERN_(HAS_EXTRUDERS, endCoord.e = planner.get_axis_position_mm(E_AXIS));
planner.buffer_line(endCoord, fr_mm_s, 0);
+21 -22
View File
@@ -92,14 +92,14 @@ void FWRetract::reset() {
*/
void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/)) {
// Prevent two retracts or recovers in a row
if (retracted[active_extruder] == retracting) return;
if (retracted[motion.extruder] == retracting) return;
// Prevent two swap-retract or recovers in a row
#if HAS_MULTI_EXTRUDER
// Allow G10 S1 only after G11
if (swapping && retracted_swap[active_extruder] == retracting) return;
if (swapping && retracted_swap[motion.extruder] == retracting) return;
// G11 priority to recover the long retract if activated
if (!retracting) swapping = retracted_swap[active_extruder];
if (!retracting) swapping = retracted_swap[motion.extruder];
#else
constexpr bool swapping = false;
#endif
@@ -108,7 +108,7 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
SERIAL_ECHOLNPGM(
"retracting ", AS_DIGIT(retracting),
" swapping ", swapping,
" active extruder ", active_extruder
" active extruder ", motion.extruder
);
EXTRUDER_LOOP() {
SERIAL_ECHOLNPGM("retracted[", e, "] ", AS_DIGIT(retracted[e]));
@@ -116,8 +116,8 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
SERIAL_ECHOLNPGM("retracted_swap[", e, "] ", AS_DIGIT(retracted_swap[e]));
#endif
}
SERIAL_ECHOLNPGM("current_position.z ", current_position.z);
SERIAL_ECHOLNPGM("current_position.e ", current_position.e);
SERIAL_ECHOLNPGM("motion.position.z ", motion.position.z);
SERIAL_ECHOLNPGM("motion.position.e ", motion.position.e);
SERIAL_ECHOLNPGM("current_hop ", current_hop);
//*/
@@ -125,7 +125,7 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
* (swapping ? settings.swap_retract_length : settings.retract_length);
// The current position will be the destination for E and Z moves
destination = current_position;
motion.destination = motion.position;
#if ENABLED(RETRACT_SYNC_MIXING)
const uint8_t old_mixing_tool = mixer.get_current_vtool();
@@ -135,8 +135,8 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
const feedRate_t fr_max_z = planner.settings.max_feedrate_mm_s[Z_AXIS];
if (retracting) {
// Retract by moving from a faux E position back to the current E position
current_retract[active_extruder] = base_retract;
prepare_internal_move_to_destination( // set current from destination
current_retract[motion.extruder] = base_retract;
motion.prepare_internal_move_to_destination( // Set current from destination
MUL_TERN(RETRACT_SYNC_MIXING, settings.retract_feedrate_mm_s, MIXING_STEPPERS)
);
@@ -144,7 +144,7 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
if (!current_hop && settings.retract_zraise > 0.01f) { // Apply hop only once
current_hop += settings.retract_zraise; // Add to the hop total (again, only once)
// Raise up, set_current_to_destination. Maximum Z feedrate
prepare_internal_move_to_destination(fr_max_z);
motion.prepare_internal_move_to_destination(fr_max_z);
}
}
else {
@@ -152,43 +152,42 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
if (current_hop) {
current_hop = 0;
// Lower Z, set_current_to_destination. Maximum Z feedrate
prepare_internal_move_to_destination(fr_max_z);
motion.prepare_internal_move_to_destination(fr_max_z);
}
// Adjust the current E position by the extra amount to recover
// Sync the planner position so the extra amount is recovered
const float extra_recover = swapping ? settings.swap_retract_recover_extra : settings.retract_recover_extra;
if (extra_recover) {
current_position.e -= extra_recover; // Adjust the current E position by the extra amount to recover
sync_plan_position_e(); // Sync the planner position so the extra amount is recovered
}
if (extra_recover) motion.set_and_sync_e(motion.position.e - extra_recover);
current_retract[active_extruder] = 0;
current_retract[motion.extruder] = 0;
// Recover E, set_current_to_destination
const feedRate_t fr_mm_s = swapping ? settings.swap_retract_recover_feedrate_mm_s : settings.retract_recover_feedrate_mm_s;
prepare_internal_move_to_destination(MUL_TERN(RETRACT_SYNC_MIXING, fr_mm_s, MIXING_STEPPERS));
motion.prepare_internal_move_to_destination(MUL_TERN(RETRACT_SYNC_MIXING, fr_mm_s, MIXING_STEPPERS));
}
TERN_(RETRACT_SYNC_MIXING, mixer.T(old_mixing_tool)); // Restore original mixing tool
retracted.set(active_extruder, retracting); // Active extruder now retracted / recovered
retracted.set(motion.extruder, retracting); // Active extruder now retracted / recovered
// If swap retract/recover update the retracted_swap flag too
#if HAS_MULTI_EXTRUDER
if (swapping) retracted_swap.set(active_extruder, retracting);
if (swapping) retracted_swap.set(motion.extruder, retracting);
#endif
/* // debugging
SERIAL_ECHOLNPGM("retracting ", AS_DIGIT(retracting));
SERIAL_ECHOLNPGM("swapping ", AS_DIGIT(swapping));
SERIAL_ECHOLNPGM("active_extruder ", active_extruder);
SERIAL_ECHOLNPGM("motion.extruder ", motion.extruder);
EXTRUDER_LOOP() {
SERIAL_ECHOLNPGM("retracted[", e, "] ", AS_DIGIT(retracted[e]));
#if HAS_MULTI_EXTRUDER
SERIAL_ECHOLNPGM("retracted_swap[", e, "] ", AS_DIGIT(retracted_swap[e]));
#endif
}
SERIAL_ECHOLNPGM("current_position.z ", current_position.z);
SERIAL_ECHOLNPGM("current_position.e ", current_position.e);
SERIAL_ECHOLNPGM("motion.position.z ", motion.position.z);
SERIAL_ECHOLNPGM("motion.position.e ", motion.position.e);
SERIAL_ECHOLNPGM("current_hop ", current_hop);
//*/
}

Some files were not shown because too many files have changed in this diff Show More