Compare commits

...

169 Commits

Author SHA1 Message Date
Scott Lahteine
b878127ea0 Marlin 2.0.9.1 2021-06-28 19:50:00 -05:00
Katelyn Schiesser
6ea6556d09 🐛 Use setTargetHotend in menus (#22247) 2021-06-28 19:50:00 -05:00
Scott Lahteine
2b37a71eba ♻️ Refactor status screen timeout 2021-06-28 19:50:00 -05:00
Cytown
e3ae76d76d 🚸 Expand box in draw_boxed_string (#22209) 2021-06-28 19:50:00 -05:00
Katelyn Schiesser
b24508907e 🐛 No HOTEND_LOOP with EXTRUDERS 0 (#22245) 2021-06-28 19:50:00 -05:00
Sébastien Gariépy
ec3daadf43 🌐 MSG_MOVE_100MM (#22242) 2021-06-28 19:50:00 -05:00
Cytown
ae76011e75 🐛 Fix wide glyph characters display (#22237) 2021-06-28 19:50:00 -05:00
Scott Lahteine
34066c1717 📝 Update probe heating value 2021-06-27 11:54:28 -05:00
ellensp
19fe3d5e79 🚸 MarlinUI Move Z >= 1000 (#22192) 2021-06-27 11:32:14 -05:00
Scott Lahteine
ec518e6e7b 🎨 Small tweak, ms => now 2021-06-27 11:25:58 -05:00
Scott Lahteine
003ce25acf 🎨 Format onboard_sd.cpp 2021-06-27 11:25:48 -05:00
ellensp
3e5d867276 🐛 Fix Z_MULTI_ENDSTOPS + NUM_Z_STEPPER_DRIVERS 4 compile (#22203) 2021-06-27 11:25:36 -05:00
cr20-123
b1bcb387fa Update/extend Quiet Probing (#22205) 2021-06-27 11:25:07 -05:00
ellensp
0fbd8c52bb 🔧 Fix E.S.T. sanity-check errors (#22224) 2021-06-27 11:24:54 -05:00
Marcio T
08895e6cb0 🎨 Fix and improve FTDI Eve Touch UI (#22223) 2021-06-27 11:24:43 -05:00
Keith Bennett
38e775496a 📝 Update TMC SPI endstops comment (#22221) 2021-06-27 11:24:33 -05:00
Scott Lahteine
47631167f9 🐛 Trigger existing endstops on G38 hit 2021-06-27 11:24:22 -05:00
bwspath
185e0dc7b7 🐛 Fix Octopus build on case-sensitive FS (#22206) 2021-06-27 11:23:56 -05:00
Serhiy-K
bcf6ca59df 🌐 Update Russian language (#22193) 2021-06-27 11:23:42 -05:00
Marcio T
1ba694cebb 🎨 Fix and enhance FTDI Eve Touch UI (#22189) 2021-06-27 11:22:20 -05:00
Scott Lahteine
906fa05bd6 🐛🌐 Fix extra axis translations 2021-06-27 11:21:33 -05:00
Scott Lahteine
651f15f833 🎨 Cosmetic cleanup 2021-06-21 16:26:38 -05:00
Katelyn Schiesser
ef41c1f452 🐛 Fix IJK axis references, E stepper indices (#22176)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2021-06-21 16:26:38 -05:00
Grumpy
8050813d32 🐛 Fix dual Neopixels (#22174) 2021-06-21 16:26:38 -05:00
ellensp
25e7e2fce0 🐛 Fix heater display options/compile (#22185) 2021-06-21 16:26:38 -05:00
Scott Lahteine
a0f7f0e9e2 🐛 Fix compact sensitive pins array (#22184) 2021-06-21 16:26:38 -05:00
Serhiy-K
f3e0bc7a4b 🌐 Update Ukrainian language (#22183) 2021-06-21 16:26:38 -05:00
Giuliano Zaro
49ff1e837a 🌐 Update Italian language (#22182) 2021-06-21 16:26:38 -05:00
Katelyn Schiesser
4f8191b481 🐛 Redundant Temp Sensor followup (#22173) 2021-06-20 16:44:01 -05:00
Scott Lahteine
927a1a1738 🐛 Fix LCD define typos 2021-06-20 16:40:50 -05:00
Scott Lahteine
f2f23e8097 🎨 Cosmetic changes for G28 2021-06-20 16:40:23 -05:00
Scott Lahteine
cce585f6ca 🐛 Define 'HEAD' axes for Markforged
Fixes #22167
2021-06-18 13:13:27 -05:00
Ari-SSO
5bfb465ab4 🚸 Include 'H' value in M412 report (#22138)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2021-06-18 12:26:12 -05:00
Katelyn Schiesser
ce7bbafb8f 💡 Add G28 L description (#22144) 2021-06-18 12:26:10 -05:00
Keith Bennett
5ffc4bfe3a 🐛 TFT encoder pin for BTT GTR (#22162) 2021-06-18 12:25:42 -05:00
Mike La Spina
3ecc99e95d 🐛 Fix Air Assist (#22159)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2021-06-18 12:25:05 -05:00
gjdodd
f22c5d3cc6 🩹 Extruders 0 patch for PWM Motor Current (#22163) 2021-06-18 12:24:54 -05:00
Victor Oliveira
d8df8e0eed 🐛 Fix env validation for 1280/2560 boards (#22150)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2021-06-18 12:24:47 -05:00
Victor Oliveira
e38958f256 🐛 Fix MKS Robin E3 build (#22149) 2021-06-18 12:23:46 -05:00
Scott Lahteine
d7c77403fd Marlin 2.0.9 2021-06-15 20:45:37 -05:00
ellensp
c8898b5ca0 Redundant Part Cooling Fan (#21888)
Co-authored-by: Scott Lahteine <github@thinkyhead.com>
2021-06-15 00:12:35 -05:00
Scott Lahteine
781257bc64 🐛 Prevent stepper sleep during long UBL idle (#22137) 2021-06-15 00:12:30 -05:00
qwewer0
dec083dcc1 ️ Home Z (and maybe XY) at the start of G35 (#22060) 2021-06-15 00:12:27 -05:00
ellensp
cdd9507493 🚑️ Prevent BFT unaligned compressed data corruption (#22134) 2021-06-15 00:12:23 -05:00
Bo Herrmannsen
dba877311e Extruder with Dual Stepper Drivers (#21403) 2021-06-15 00:12:20 -05:00
Victor Oliveira
31fd3be6eb 🔥 Remove Chitu default Touch Calibration (#22133) 2021-06-15 00:12:16 -05:00
Victor Oliveira
2b4284df81 MULTI_VOLUME for Color UI and MarlinUI (#22004) 2021-06-15 00:12:01 -05:00
InsanityAutomation
d84e2d6e29 🎨 ExtUI "user click" and other tweaks (#22122)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2021-06-15 00:11:57 -05:00
Victor Oliveira
56355159c6 🐛 Include common TFT driver macros (#22125) 2021-06-15 00:11:54 -05:00
Katelyn Schiesser
a7135d429b 🐛 Fix UBL 'R' parameter and adjust 'P' (#22129) 2021-06-15 00:11:50 -05:00
Sola
3b0a40cd5d 🐛 Fix ExtUI/DGUS Celsius display (#22121) 2021-06-15 00:11:46 -05:00
Scott Lahteine
83c74802f8 🎨 General cleanup of extui/dgus
In relation to #22121
2021-06-15 00:11:42 -05:00
Victor Oliveira
adc17933cd 🔨 Fix Serial+MSC for _USB envs (#22116) 2021-06-15 00:11:39 -05:00
Katelyn Schiesser
68c52673d6 🐛 Use whole PROBE_TEMP_COMPENSATION values (#22130) 2021-06-15 00:11:34 -05:00
Scott Lahteine
2aa35577f2 🏗️ Refactor build encrypt / rename (#22124) 2021-06-15 00:11:29 -05:00
Scott Lahteine
14ffc66c45 🩹 Use #pragma once in pins files 2021-06-15 00:11:26 -05:00
Scott Lahteine
2ea0832e0f 📝 Number SKR EXP headers 2021-06-15 00:11:22 -05:00
Scott Lahteine
ab050878e9 🎨 Clean up LPC1768 SPI init 2021-06-15 00:11:18 -05:00
Scott Lahteine
707a04022e 🔨 Remove obsolete ON_BOARD_SPI_DEVICE 2021-06-15 00:11:15 -05:00
mrv96
d12c357793 🔨 Robin Nano V3 overridable POWER_LOSS_PIN (#22123) 2021-06-15 00:11:11 -05:00
Scott Lahteine
ddf8668e16 📝 Describe G12 XYZ 2021-06-15 00:11:06 -05:00
Victor Oliveira
3491e49c5f 🐛 Fix boot / SD for STM32 (F103Rx) boards (#22087) 2021-06-15 00:10:02 -05:00
Katelyn Schiesser
d322e495b2 More flexible redundant temp sensor (#22085) 2021-06-15 00:09:52 -05:00
Keith Bennett
5d80f7006a 🔨 Envs for BTT SKR Mini with RET6 (512K) (#22050) 2021-06-15 00:09:52 -05:00
Zs.Antal
3e7a9e5d20 🌐 Update Hungarian language (#22083) 2021-06-15 00:09:52 -05:00
grauerfuchs
33e8769226 🔨 MightyBoard envs for A.B.M. (#22100) 2021-06-15 00:09:52 -05:00
Radek
59842edbcb 🔧 EEPROM options for BTT SKR 1.4 (#22092) 2021-06-15 00:09:52 -05:00
Marcio T
507e1e436e 🎨 Fix and improve FTDI Eve Touch UI (#22093) 2021-06-15 00:09:52 -05:00
ellensp
b27447ef48 🔧 Enforce BLTouch settings (#22086) 2021-06-15 00:09:52 -05:00
Scott Lahteine
c9a3ba99be 🎨 Adjust some conditionals 2021-06-15 00:09:52 -05:00
Scott Lahteine
967942460e ️ Optimize Sensitive Pins array (except STM32) (#22080) 2021-06-15 00:09:52 -05:00
Kyle Repinski
bfa257902e 🐛 Fix small/huge I2C EEPROM address (#22081) 2021-06-15 00:09:52 -05:00
Scott Lahteine
3f103c91f0 🎨 Laser Ammeter followup (#22079)
Followup to #21835
2021-06-15 00:09:52 -05:00
Mike La Spina
2fd9971f41 Add Laser Based I2C Ammeter Feature (#21835) 2021-06-15 00:09:52 -05:00
ellensp
a3063a9392 expose hidden BLTOUCH setting changes (#22069) 2021-06-15 00:09:52 -05:00
Marcio T
d8a02bbbdb 🎨 Reorganize FTDI Touch UI variants (#22066) 2021-06-15 00:09:52 -05:00
ellensp
76d4a395d1 🩹 Fallback ID for MKS TS35 V2.0 (#22031) 2021-06-15 00:09:52 -05:00
7FM
c515bfb5fb 👽️ Include <EEPROM.h> in STM32 (for now) (#22054) 2021-06-15 00:09:52 -05:00
ellensp
83430be580 📦️ Malyan M200 with HAL/STM32 (#22052) 2021-06-15 00:09:52 -05:00
George Fu
9bd9f91722 📌 Update FYSETC E4 to espressif32@2.1.0 (#22049) 2021-06-15 00:09:52 -05:00
Victor Oliveira
e6ef43e51a ⚰️ Remove obsolete CUSTOM_SPI_PINS (#22058) 2021-06-15 00:09:52 -05:00
ellensp
16bca67f2d 🔧 Check G29_RETRY_AND_RECOVER requirements (#21921) 2021-06-15 00:09:52 -05:00
Scott Lahteine
d65eea550c 🔧 FOAMCUTTER_XYUV moved to custom config 2021-06-15 00:09:52 -05:00
DerAndere
46080b367a ✏️ Six Linear Axes followup (Fix M503) (#22112) 2021-06-15 00:09:52 -05:00
Marcio T
317afae37c ✏️ Six Linear Axes followup (typos) (#22094) 2021-06-15 00:08:32 -05:00
ellensp
930a608236 🎨 IJK auto-allocation (#22075) 2021-06-15 00:07:40 -05:00
DerAndere
6e3c45580c ✏️ Six Linear Axes followup (Hybrid Threshold init) (#22068) 2021-06-15 00:07:06 -05:00
DerAndere
e3df7d7bc8 ✏️ Followup to Six Linear Axes (#22056) 2021-06-15 00:05:52 -05:00
DerAndere
c1fca91103 🏗️ Support for up to 6 linear axes (#19112)
Co-authored-by: Scott Lahteine <github@thinkyhead.com>
2021-06-15 00:05:03 -05:00
Scott Lahteine
d3c56a76e7 ♻️ Patches for Zero Extruders (with TMC) 2021-06-15 00:04:47 -05:00
Scott Lahteine
4194cdda5b ♻️ Refactor Linear / Logical / Distinct Axes (#21953)
* More patches supporting EXTRUDERS 0
* Extend types in prep for more axes
2021-06-15 00:03:55 -05:00
Marcio T
f5f999d7bf 📺 Fix and enhance FTDI EVE Touch UI (#22047) 2021-06-14 23:52:14 -05:00
Keith Bennett
b4b607681c BigTreeTech Octopus V1.1 (#22042) 2021-06-14 23:52:05 -05:00
ellensp
1e75eba27b 🐛 Fix STM3R / BEAST envs (#22028) 2021-06-14 23:51:52 -05:00
Victor Oliveira
f3f3d202ac 📦️ STM32F103RE_btt(_USB) with HAL/STM32 (#22040) 2021-06-14 23:51:46 -05:00
Scott Lahteine
c90fa530db Update G34 for 4x Z steppers (#22039) 2021-06-14 23:51:40 -05:00
Taylor Talkington
aeb8097cbc 🐛 Fix M140 print job timer autostart (#22046) 2021-06-14 23:51:23 -05:00
Giuliano Zaro
04bea72787 🐛 Fix MMU compile with >5 EXTRUDERS (#22036) 2021-06-14 23:51:17 -05:00
ldursw
ce95f56ac8 🔨 MKS Robin E3 for HAL/STM32 (#21927) 2021-06-14 23:51:10 -05:00
Scott Lahteine
aff45fd455 ✏️ Remove whitespace 2021-06-14 23:51:00 -05:00
ellensp
c8f28d9d09 🐛 Fix Creality v4 servo timer (#22021)
Followup to #21999
2021-06-14 23:51:00 -05:00
Keith Bennett
f3697e5e02 🔨 Consolidate BTT linker scripts followup (#22038) 2021-06-14 23:51:00 -05:00
Scott Lahteine
557ba20ff4 🔨 Consolidate BTT linker scripts
Originally from #22022
2021-06-14 23:50:17 -05:00
ellensp
dd0e5c26d1 🐛 Fix env:STM32F103RE maple/unified split-up (#22019)
Followup to #21999
2021-06-14 23:50:11 -05:00
Scott Lahteine
c9a3f41152 📝 Update G61 comment 2021-06-14 23:49:57 -05:00
ellensp
d13ffa0aba 🔨 Creality v4 with STM32 HAL (#21999)
- New STM32 env for Creality V4 boards.
- Separate Libmaple targets into their own `ini` file.
- Temporarily remove unusable targets from `pins.h`.

Co-authored-by: ellensp <ellensp@hotmsil.com>
Co-authored-by: Scott Lahteine <github@thinkyhead.com>
2021-06-14 23:49:26 -05:00
Scott Lahteine
fb0be29604 🔨 Move FLY_MINI env to stm32f1.ini 2021-06-14 23:49:21 -05:00
hannesweisbach
7ca1550775 TMC Driver distinct baudrates (#22008) 2021-06-14 23:49:16 -05:00
Scott Lahteine
665a71b471 🔧 Treat TPARA like SCARA in mfconfig 2021-06-14 23:49:10 -05:00
Roman Moravčík
9268a4b28c 🌐 Update Slovak language (#22000) 2021-06-14 23:49:04 -05:00
Krzysztof Błażewicz
529bbfad10 ⚗️ 32-bit float constants (STM32F1) (#21996) 2021-06-14 23:46:12 -05:00
Scott Lahteine
e7945c2277 🐛 Fix Z endstop enum
Followup to 92dea8e6cc
2021-06-11 18:34:01 -05:00
Scott Lahteine
5ee91c73ed 👷 Add caching to CI workflow 2021-06-06 03:58:59 -05:00
hannesweisbach
2116e4202b 🐛 Fix Probe Temp Calibration compile (#22032) 2021-06-04 23:39:57 -05:00
Taylor Talkington
19521d16cd 🐛 Fix M140 print job timer autostart (#22046) 2021-06-04 23:33:19 -05:00
Victor Oliveira
057302b936 👽️ Fix usb-host-msc-cdc-msc issue (#22025) 2021-06-04 23:33:19 -05:00
Scott Lahteine
d62619c9c8 📌 Use U8glib-HAL@~0.4.5 2021-06-04 23:33:19 -05:00
Scott Lahteine
9c80a89597 🎨 Reorganize BTT_E3_RRF_IDEX_BOARD 2021-06-04 23:33:19 -05:00
Scott Lahteine
00834ef03d 🎨 Clean up stops, sdss pins 2021-06-04 23:33:19 -05:00
Scott Lahteine
5b7b065b96 Marlin 2.0.8.2 2021-05-29 16:01:38 -05:00
Timo
a739af823f Malyan M180 (#21992) 2021-05-29 16:01:32 -05:00
Pascal de Bruijn
493eb446b7 MEDIA_MENU_AT_TOP for MarlinUI (#21925) 2021-05-29 15:19:40 -05:00
charlespick
1b45b3802a Independent baud rates (#21949)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2021-05-29 15:19:40 -05:00
Krzysztof Błażewicz
7898307d78 🌐 Update Polish language (#21993) 2021-05-29 15:13:05 -05:00
ellensp
8da8aa140f 🥅 Add MESH_EDIT_MENU sanity check (#21922) 2021-05-29 15:12:57 -05:00
Andy Barratt
4572af2bce 🚸 cap:HOST_ACTION_COMMANDS (#21987) 2021-05-29 15:11:57 -05:00
Allen Bauer
6dc17f0e6e 🐛 Fix BTT002 variant MMU2 serial pins 🧩 (#21980) 2021-05-29 15:11:50 -05:00
ellensp
3fcf3f69ca ♻️ LEDs refactor and extend (#21962)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2021-05-29 15:11:32 -05:00
LawnMo
a9fd2769f3 🩹 Fix multi_volume + SDIO onboard compile (#21975) 2021-05-29 15:11:13 -05:00
LawnMo
9adaf92674 🩹 Improved SKR2 12864 LCD Delays (#21956) 2021-05-29 15:09:48 -05:00
Scott Lahteine
e75c3b6c54 🎨 Macros for optional arguments (#21969) 2021-05-29 15:09:07 -05:00
ellensp
61f2bb1228 ️ PIO filters for M117, M300 and M414 (#21972) 2021-05-29 15:08:30 -05:00
Scott Lahteine
d1502f74ea 🎨 Null heating message method 2021-05-29 15:07:49 -05:00
Scott Lahteine
83f9413196 🐛 Fix Selena Compact probe pin 2021-05-29 15:06:38 -05:00
Scott Lahteine
cdc3e18d99 Use another PR close action 2021-05-28 19:47:06 -05:00
BigTreeTech
55a6315862 🐛 Fix Octopus HS USB (#21961) 2021-05-24 01:59:46 -05:00
gjdodd
cf447a5442 🐛 Fix flowmeter calculation (#21959) 2021-05-24 01:54:39 -05:00
Scott Lahteine
7597b4fb40 🎨 Apply shorthand and cleanups 2021-05-23 02:17:41 -05:00
Scott Lahteine
7cd0f2a32a 🎨 pause => pause_heaters 2021-05-23 02:17:31 -05:00
Scott Lahteine
4dae5890e9 ♻️ Refactor, comment endstop/probe enums 2021-05-23 02:09:04 -05:00
Danol
738ae4be33 🐛 Fix wrong Z_ENDSTOP flag bit (#21963)
Bug introduced in #18424
2021-05-23 01:11:48 -05:00
Scott Lahteine
e573611021 🎨 Combine M104/M109 and M140/M190 code 2021-05-22 19:09:51 -05:00
Scott Lahteine
f60965a107 📝 Update ExtUI example 2021-05-22 16:19:02 -05:00
Scott Lahteine
3995e8373c 🎨 Shorten lcd relative paths 2021-05-22 16:18:59 -05:00
Scott Lahteine
ddc82b84e2 📝 Document diveToFile, printListing 2021-05-22 16:18:55 -05:00
Scott Lahteine
87a943756a 🎨 Move HAS_EXTRUDERS 2021-05-22 16:18:42 -05:00
Scott Lahteine
8e28731f96 🎨 Update a condition 2021-05-22 16:18:42 -05:00
Scott Lahteine
cdbd438a04 🎨 Rename all/no axis enums 2021-05-22 16:18:42 -05:00
Scott Lahteine
3220c49f1b Add a test for SAVED_POSITIONS 2021-05-22 16:18:42 -05:00
Scott Lahteine
94e67a036a 🐛 Fix compile with PREVENT_COLD_EXTRUSION off 2021-05-22 16:18:42 -05:00
Scott Lahteine
c977e82074 🎨 MULTI_MANUAL => MULTI_E_MANUAL 2021-05-22 16:18:42 -05:00
Moonglow
9878a5ab58 🐛 Fix Toshiba FlashAir (SDCARD_COMMANDS_SPLIT) (#21944) 2021-05-22 16:18:42 -05:00
Scott Lahteine
2de914c38c 🎨 Move switch sensor strings 2021-05-22 16:09:20 -05:00
Scott Lahteine
49b05ba989 🎨 Flags for homing directions 2021-05-22 16:09:18 -05:00
Scott Lahteine
85fa8c55c9 🐛 Fix DELTA with SENSORLESS_PROBING 2021-05-22 16:09:17 -05:00
Scott Lahteine
57eef65d9c ♻️ Refactor axis homing/trusted state bits 2021-05-22 16:08:46 -05:00
Scott Lahteine
894c954e8f ♻️ Minimize endstop bits 2021-05-22 16:08:43 -05:00
Scott Lahteine
046bac6769 Fix tests for EXTRUDERS 0 2021-05-22 16:08:26 -05:00
Scott Lahteine
765720e98b ♻️ Simplify TMC utilities for more axes 2021-05-22 16:08:09 -05:00
Scott Lahteine
26a244325b ♻️ Refactor axis counts and loops 2021-05-22 16:08:08 -05:00
Scott Lahteine
f7d28ce1d6 🎨 Misc cleanup and fixes 2021-05-22 16:08:03 -05:00
Scott Lahteine
c85633b47f 🎨 Use defined strings 2021-05-22 16:03:19 -05:00
Alvaro Segura Del Barco
6861b1ec82 🐛 Fix Teensy PINS_DEBUGGING compile (#21958)
Followup to 84a11cfedc
2021-05-22 15:55:08 -05:00
Roger D. Winans
003cb20b9f 📝 Add Configurations section to README (#21955)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2021-05-21 23:14:25 -05:00
Scott Lahteine
f1f622de01 Fix 'G29 K' value 2021-05-19 22:02:53 -05:00
ellensp
dbb8f3db09 Fix EEPROM_CHITCHAT (#21934)
Fix #21929
2021-05-18 18:08:22 -05:00
ellensp
5d7c72db5a Fix envs using mks_encrypt.py (#21933)
Fix #21928
2021-05-17 18:25:11 -05:00
thisiskeithb
755adb8973 Update Configurations URL (2.0.8.1) 2021-05-16 14:07:29 -05:00
ekef
0977429138 Fix MKS Robin E3 BLTOUCH and Fan PWM timer conflicts (#21889) 2021-05-15 18:22:30 -05:00
610 changed files with 13465 additions and 8286 deletions

View File

@@ -20,10 +20,8 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: peter-evans/close-pull@v1 - uses: superbrothers/close-pull-request@v3
with: with:
token: ${{ github.token }}
delete-branch: false
comment: > comment: >
Thanks for your contribution! Unfortunately we can't accept PRs directed at release branches. We make patches to the bugfix branches and only later do we push them out as releases. Thanks for your contribution! Unfortunately we can't accept PRs directed at release branches. We make patches to the bugfix branches and only later do we push them out as releases.

View File

@@ -56,29 +56,31 @@ jobs:
# STM32F1 (Maple) Environments # STM32F1 (Maple) Environments
- STM32F103RC_btt #- STM32F103RC_btt_maple
- STM32F103RC_btt_USB - STM32F103RC_btt_USB_maple
- STM32F103RE_btt
- STM32F103RE_btt_USB
- STM32F103RC_fysetc - STM32F103RC_fysetc
- STM32F103RC_meeb - STM32F103RC_meeb
- jgaurora_a5s_a1 - jgaurora_a5s_a1
- STM32F103VE_longer - STM32F103VE_longer
- mks_robin #- mks_robin_maple
- mks_robin_lite - mks_robin_lite
- mks_robin_pro - mks_robin_pro
- STM32F103RET6_creality #- mks_robin_nano35_maple
- mks_robin_nano35 #- STM32F103RET6_creality_maple
# STM32 (ST) Environments # STM32 (ST) Environments
- STM32F103RC_btt_stm32 - STM32F103RC_btt
#- STM32F103RC_btt_USB
- STM32F103RE_btt
- STM32F103RE_btt_USB
- STM32F103RET6_creality
- STM32F407VE_black - STM32F407VE_black
- STM32F401VE_STEVAL - STM32F401VE_STEVAL
- BIGTREE_BTT002 - BIGTREE_BTT002
- BIGTREE_SKR_PRO - BIGTREE_SKR_PRO
- BIGTREE_GTR_V1_0 - BIGTREE_GTR_V1_0
- mks_robin_stm32 - mks_robin
- ARMED - ARMED
- FYSETC_S6 - FYSETC_S6
- STM32F070CB_malyan - STM32F070CB_malyan
@@ -88,7 +90,7 @@ jobs:
- rumba32 - rumba32
- LERDGEX - LERDGEX
- LERDGEK - LERDGEK
- mks_robin_nano35_stm32 - mks_robin_nano35
- NUCLEO_F767ZI - NUCLEO_F767ZI
- REMRAM_V1 - REMRAM_V1
- BTT_SKR_SE_BX - BTT_SKR_SE_BX
@@ -107,8 +109,25 @@ jobs:
steps: steps:
- name: Check out the PR
uses: actions/checkout@v2
- name: Cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache PlatformIO
uses: actions/cache@v2
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Select Python 3.7 - name: Select Python 3.7
uses: actions/setup-python@v1 uses: actions/setup-python@v2
with: with:
python-version: '3.7' # Version range or exact version of a Python version to use, using semvers version range syntax. python-version: '3.7' # Version range or exact version of a Python version to use, using semvers version range syntax.
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
@@ -118,9 +137,6 @@ jobs:
pip install -U https://github.com/platformio/platformio-core/archive/develop.zip pip install -U https://github.com/platformio/platformio-core/archive/develop.zip
platformio update platformio update
- name: Check out the PR
uses: actions/checkout@v2
- name: Run ${{ matrix.test-platform }} Tests - name: Run ${{ matrix.test-platform }} Tests
run: | run: |
make tests-single-ci TEST_TARGET=${{ matrix.test-platform }} make tests-single-ci TEST_TARGET=${{ matrix.test-platform }}

View File

@@ -35,7 +35,7 @@
* *
* Advanced settings can be found in Configuration_adv.h * Advanced settings can be found in Configuration_adv.h
*/ */
#define CONFIGURATION_H_VERSION 02000801 #define CONFIGURATION_H_VERSION 02000901
//=========================================================================== //===========================================================================
//============================= Getting Started ============================= //============================= Getting Started =============================
@@ -105,21 +105,9 @@
#define SERIAL_PORT 0 #define SERIAL_PORT 0
/** /**
* Select a secondary serial port on the board to use for communication with the host. * Serial Port Baud Rate
* Currently Ethernet (-2) is only supported on Teensy 4.1 boards. * This is the default communication speed for all serial ports.
* :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7] * Set the baud rate defaults for additional serial ports below.
*/
//#define SERIAL_PORT_2 -1
/**
* Select a third serial port on the board to use for communication with the host.
* Currently only supported for AVR, DUE, LPC1768/9 and STM32/STM32F1
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_3 1
/**
* This setting determines the communication speed of the printer.
* *
* 250000 works in most cases, but you might try a lower speed if * 250000 works in most cases, but you might try a lower speed if
* you commonly experience drop-outs during host printing. * you commonly experience drop-outs during host printing.
@@ -128,6 +116,23 @@
* :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000] * :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000]
*/ */
#define BAUDRATE 250000 #define BAUDRATE 250000
//#define BAUD_RATE_GCODE // Enable G-code M575 to set the baud rate
/**
* Select a secondary serial port on the board to use for communication with the host.
* Currently Ethernet (-2) is only supported on Teensy 4.1 boards.
* :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_2 -1
//#define BAUDRATE_2 250000 // Enable to override BAUDRATE
/**
* Select a third serial port on the board to use for communication with the host.
* Currently only supported for AVR, DUE, LPC1768/9 and STM32/STM32F1
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_3 1
//#define BAUDRATE_3 250000 // Enable to override BAUDRATE
// Enable the Bluetooth serial interface on AT90USB devices // Enable the Bluetooth serial interface on AT90USB devices
//#define BLUETOOTH //#define BLUETOOTH
@@ -144,6 +149,45 @@
// Choose your own or use a service like https://www.uuidgenerator.net/version4 // Choose your own or use a service like https://www.uuidgenerator.net/version4
//#define MACHINE_UUID "00000000-0000-0000-0000-000000000000" //#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
/**
* Define the number of coordinated linear axes.
* See https://github.com/DerAndere1/Marlin/wiki
* Each linear axis gets its own stepper control and endstop:
*
* Steppers: *_STEP_PIN, *_ENABLE_PIN, *_DIR_PIN, *_ENABLE_ON
* Endstops: *_STOP_PIN, USE_*MIN_PLUG, USE_*MAX_PLUG
* Axes: *_MIN_POS, *_MAX_POS, INVERT_*_DIR
* Planner: DEFAULT_AXIS_STEPS_PER_UNIT, DEFAULT_MAX_FEEDRATE
* DEFAULT_MAX_ACCELERATION, AXIS_RELATIVE_MODES,
* MICROSTEP_MODES, MANUAL_FEEDRATE
*
* :[3, 4, 5, 6]
*/
//#define LINEAR_AXES 3
/**
* Axis codes for additional axes:
* This defines the axis code that is used in G-code commands to
* reference a specific axis.
* 'A' for rotational axis parallel to X
* 'B' for rotational axis parallel to Y
* 'C' for rotational axis parallel to Z
* 'U' for secondary linear axis parallel to X
* 'V' for secondary linear axis parallel to Y
* 'W' for secondary linear axis parallel to Z
* Regardless of the settings, firmware-internal axis IDs are
* I (AXIS4), J (AXIS5), K (AXIS6).
*/
#if LINEAR_AXES >= 4
#define AXIS4_NAME 'A' // :['A', 'B', 'C', 'U', 'V', 'W']
#endif
#if LINEAR_AXES >= 5
#define AXIS5_NAME 'B' // :['A', 'B', 'C', 'U', 'V', 'W']
#endif
#if LINEAR_AXES >= 6
#define AXIS6_NAME 'C' // :['A', 'B', 'C', 'U', 'V', 'W']
#endif
// @section extruder // @section extruder
// This defines the number of extruders // This defines the number of extruders
@@ -428,6 +472,7 @@
#define TEMP_SENSOR_PROBE 0 #define TEMP_SENSOR_PROBE 0
#define TEMP_SENSOR_CHAMBER 0 #define TEMP_SENSOR_CHAMBER 0
#define TEMP_SENSOR_COOLER 0 #define TEMP_SENSOR_COOLER 0
#define TEMP_SENSOR_REDUNDANT 0
// Dummy thermistor constant temperature readings, for use with 998 and 999 // Dummy thermistor constant temperature readings, for use with 998 and 999
#define DUMMY_THERMISTOR_998_VALUE 25 #define DUMMY_THERMISTOR_998_VALUE 25
@@ -439,11 +484,6 @@
//#define MAX31865_SENSOR_OHMS_1 100 //#define MAX31865_SENSOR_OHMS_1 100
//#define MAX31865_CALIBRATION_OHMS_1 430 //#define MAX31865_CALIBRATION_OHMS_1 430
// Use temp sensor 1 as a redundant sensor with sensor 0. If the readings
// from the two sensors differ too much the print will be aborted.
//#define TEMP_SENSOR_1_AS_REDUNDANT
#define MAX_REDUNDANT_TEMP_SENSOR_DIFF 10
#define TEMP_RESIDENCY_TIME 10 // (seconds) Time to wait for hotend to "settle" in M109 #define TEMP_RESIDENCY_TIME 10 // (seconds) Time to wait for hotend to "settle" in M109
#define TEMP_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer #define TEMP_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target #define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
@@ -456,6 +496,28 @@
#define TEMP_CHAMBER_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer #define TEMP_CHAMBER_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_CHAMBER_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target #define TEMP_CHAMBER_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
/**
* Redundant Temperature Sensor (TEMP_SENSOR_REDUNDANT)
*
* Use a temp sensor as a redundant sensor for another reading. Select an unused temperature sensor, and another
* sensor you'd like it to be redundant for. If the two thermistors differ by TEMP_SENSOR_REDUNDANT_MAX_DIFF (°C),
* the print will be aborted. Whichever sensor is selected will have its normal functions disabled; i.e. selecting
* the Bed sensor (-1) will disable bed heating/monitoring.
*
* Use the following to select temp sensors:
* -5 : Cooler
* -4 : Probe
* -3 : not used
* -2 : Chamber
* -1 : Bed
* 0-7 : E0 through E7
*/
#if TEMP_SENSOR_REDUNDANT
#define TEMP_SENSOR_REDUNDANT_SOURCE 1 // The sensor that will provide the redundant reading.
#define TEMP_SENSOR_REDUNDANT_TARGET 0 // The sensor that we are providing a redundant reading for.
#define TEMP_SENSOR_REDUNDANT_MAX_DIFF 10 // (°C) Temperature difference that will trigger a print abort.
#endif
// Below this temperature the heater will be switched off // Below this temperature the heater will be switched off
// because it probably indicates a broken thermistor wire. // because it probably indicates a broken thermistor wire.
#define HEATER_0_MINTEMP 5 #define HEATER_0_MINTEMP 5
@@ -686,9 +748,15 @@
#define USE_XMIN_PLUG #define USE_XMIN_PLUG
#define USE_YMIN_PLUG #define USE_YMIN_PLUG
#define USE_ZMIN_PLUG #define USE_ZMIN_PLUG
//#define USE_IMIN_PLUG
//#define USE_JMIN_PLUG
//#define USE_KMIN_PLUG
//#define USE_XMAX_PLUG //#define USE_XMAX_PLUG
//#define USE_YMAX_PLUG //#define USE_YMAX_PLUG
//#define USE_ZMAX_PLUG //#define USE_ZMAX_PLUG
//#define USE_IMAX_PLUG
//#define USE_JMAX_PLUG
//#define USE_KMAX_PLUG
// Enable pullup for all endstops to prevent a floating state // Enable pullup for all endstops to prevent a floating state
#define ENDSTOPPULLUPS #define ENDSTOPPULLUPS
@@ -697,9 +765,15 @@
//#define ENDSTOPPULLUP_XMAX //#define ENDSTOPPULLUP_XMAX
//#define ENDSTOPPULLUP_YMAX //#define ENDSTOPPULLUP_YMAX
//#define ENDSTOPPULLUP_ZMAX //#define ENDSTOPPULLUP_ZMAX
//#define ENDSTOPPULLUP_IMAX
//#define ENDSTOPPULLUP_JMAX
//#define ENDSTOPPULLUP_KMAX
//#define ENDSTOPPULLUP_XMIN //#define ENDSTOPPULLUP_XMIN
//#define ENDSTOPPULLUP_YMIN //#define ENDSTOPPULLUP_YMIN
//#define ENDSTOPPULLUP_ZMIN //#define ENDSTOPPULLUP_ZMIN
//#define ENDSTOPPULLUP_IMIN
//#define ENDSTOPPULLUP_JMIN
//#define ENDSTOPPULLUP_KMIN
//#define ENDSTOPPULLUP_ZMIN_PROBE //#define ENDSTOPPULLUP_ZMIN_PROBE
#endif #endif
@@ -710,9 +784,15 @@
//#define ENDSTOPPULLDOWN_XMAX //#define ENDSTOPPULLDOWN_XMAX
//#define ENDSTOPPULLDOWN_YMAX //#define ENDSTOPPULLDOWN_YMAX
//#define ENDSTOPPULLDOWN_ZMAX //#define ENDSTOPPULLDOWN_ZMAX
//#define ENDSTOPPULLDOWN_IMAX
//#define ENDSTOPPULLDOWN_JMAX
//#define ENDSTOPPULLDOWN_KMAX
//#define ENDSTOPPULLDOWN_XMIN //#define ENDSTOPPULLDOWN_XMIN
//#define ENDSTOPPULLDOWN_YMIN //#define ENDSTOPPULLDOWN_YMIN
//#define ENDSTOPPULLDOWN_ZMIN //#define ENDSTOPPULLDOWN_ZMIN
//#define ENDSTOPPULLDOWN_IMIN
//#define ENDSTOPPULLDOWN_JMIN
//#define ENDSTOPPULLDOWN_KMIN
//#define ENDSTOPPULLDOWN_ZMIN_PROBE //#define ENDSTOPPULLDOWN_ZMIN_PROBE
#endif #endif
@@ -720,9 +800,15 @@
#define X_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define X_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Y_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Y_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Z_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Z_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define I_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define J_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define K_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define X_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define X_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Y_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Y_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Z_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Z_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define I_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define J_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define K_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Z_MIN_PROBE_ENDSTOP_INVERTING false // Set to true to invert the logic of the probe. #define Z_MIN_PROBE_ENDSTOP_INVERTING false // Set to true to invert the logic of the probe.
/** /**
@@ -751,6 +837,9 @@
//#define Z2_DRIVER_TYPE A4988 //#define Z2_DRIVER_TYPE A4988
//#define Z3_DRIVER_TYPE A4988 //#define Z3_DRIVER_TYPE A4988
//#define Z4_DRIVER_TYPE A4988 //#define Z4_DRIVER_TYPE A4988
//#define I_DRIVER_TYPE A4988
//#define J_DRIVER_TYPE A4988
//#define K_DRIVER_TYPE A4988
#define E0_DRIVER_TYPE A4988 #define E0_DRIVER_TYPE A4988
//#define E1_DRIVER_TYPE A4988 //#define E1_DRIVER_TYPE A4988
//#define E2_DRIVER_TYPE A4988 //#define E2_DRIVER_TYPE A4988
@@ -804,14 +893,14 @@
/** /**
* Default Axis Steps Per Unit (steps/mm) * Default Axis Steps Per Unit (steps/mm)
* Override with M92 * Override with M92
* X, Y, Z, E0 [, E1[, E2...]] * X, Y, Z [, I [, J [, K]]], E0 [, E1[, E2...]]
*/ */
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 500 } #define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 500 }
/** /**
* Default Max Feed Rate (mm/s) * Default Max Feed Rate (mm/s)
* Override with M203 * Override with M203
* X, Y, Z, E0 [, E1[, E2...]] * X, Y, Z [, I [, J [, K]]], E0 [, E1[, E2...]]
*/ */
#define DEFAULT_MAX_FEEDRATE { 300, 300, 5, 25 } #define DEFAULT_MAX_FEEDRATE { 300, 300, 5, 25 }
@@ -824,7 +913,7 @@
* Default Max Acceleration (change/s) change = mm/s * Default Max Acceleration (change/s) change = mm/s
* (Maximum start speed for accelerated moves) * (Maximum start speed for accelerated moves)
* Override with M201 * Override with M201
* X, Y, Z, E0 [, E1[, E2...]] * X, Y, Z [, I [, J [, K]]], E0 [, E1[, E2...]]
*/ */
#define DEFAULT_MAX_ACCELERATION { 3000, 3000, 100, 10000 } #define DEFAULT_MAX_ACCELERATION { 3000, 3000, 100, 10000 }
@@ -858,6 +947,9 @@
#define DEFAULT_XJERK 10.0 #define DEFAULT_XJERK 10.0
#define DEFAULT_YJERK 10.0 #define DEFAULT_YJERK 10.0
#define DEFAULT_ZJERK 0.3 #define DEFAULT_ZJERK 0.3
//#define DEFAULT_IJERK 0.3
//#define DEFAULT_JJERK 0.3
//#define DEFAULT_KJERK 0.3
//#define TRAVEL_EXTRA_XYJERK 0.0 // Additional jerk allowance for all travel moves //#define TRAVEL_EXTRA_XYJERK 0.0 // Additional jerk allowance for all travel moves
@@ -1156,7 +1248,8 @@
//#define WAIT_FOR_HOTEND // Wait for hotend to heat back up between probes (to improve accuracy & prevent cold extrude) //#define WAIT_FOR_HOTEND // Wait for hotend to heat back up between probes (to improve accuracy & prevent cold extrude)
#endif #endif
//#define PROBING_FANS_OFF // Turn fans off when probing //#define PROBING_FANS_OFF // Turn fans off when probing
//#define PROBING_STEPPERS_OFF // Turn steppers off (unless needed to hold position) when probing //#define PROBING_ESTEPPERS_OFF // Turn all extruder steppers off when probing
//#define PROBING_STEPPERS_OFF // Turn all steppers off (unless needed to hold position) when probing (including extruders)
//#define DELAY_BEFORE_PROBING 200 // (ms) To prevent vibrations from triggering piezo sensors //#define DELAY_BEFORE_PROBING 200 // (ms) To prevent vibrations from triggering piezo sensors
// Require minimum nozzle and/or bed temperature for probing // Require minimum nozzle and/or bed temperature for probing
@@ -1172,12 +1265,18 @@
#define Y_ENABLE_ON 0 #define Y_ENABLE_ON 0
#define Z_ENABLE_ON 0 #define Z_ENABLE_ON 0
#define E_ENABLE_ON 0 // For all extruders #define E_ENABLE_ON 0 // For all extruders
//#define I_ENABLE_ON 0
//#define J_ENABLE_ON 0
//#define K_ENABLE_ON 0
// Disable axis steppers immediately when they're not being stepped. // Disable axis steppers immediately when they're not being stepped.
// WARNING: When motors turn off there is a chance of losing position accuracy! // WARNING: When motors turn off there is a chance of losing position accuracy!
#define DISABLE_X false #define DISABLE_X false
#define DISABLE_Y false #define DISABLE_Y false
#define DISABLE_Z false #define DISABLE_Z false
//#define DISABLE_I false
//#define DISABLE_J false
//#define DISABLE_K false
// Turn off the display blinking that warns about possible accuracy reduction // Turn off the display blinking that warns about possible accuracy reduction
//#define DISABLE_REDUCED_ACCURACY_WARNING //#define DISABLE_REDUCED_ACCURACY_WARNING
@@ -1193,6 +1292,9 @@
#define INVERT_X_DIR false #define INVERT_X_DIR false
#define INVERT_Y_DIR true #define INVERT_Y_DIR true
#define INVERT_Z_DIR false #define INVERT_Z_DIR false
//#define INVERT_I_DIR false
//#define INVERT_J_DIR false
//#define INVERT_K_DIR false
// @section extruder // @section extruder
@@ -1228,6 +1330,9 @@
#define X_HOME_DIR -1 #define X_HOME_DIR -1
#define Y_HOME_DIR -1 #define Y_HOME_DIR -1
#define Z_HOME_DIR -1 #define Z_HOME_DIR -1
//#define I_HOME_DIR -1
//#define J_HOME_DIR -1
//#define K_HOME_DIR -1
// @section machine // @section machine
@@ -1242,6 +1347,12 @@
#define X_MAX_POS X_BED_SIZE #define X_MAX_POS X_BED_SIZE
#define Y_MAX_POS Y_BED_SIZE #define Y_MAX_POS Y_BED_SIZE
#define Z_MAX_POS 200 #define Z_MAX_POS 200
//#define I_MIN_POS 0
//#define I_MAX_POS 50
//#define J_MIN_POS 0
//#define J_MAX_POS 50
//#define K_MIN_POS 0
//#define K_MAX_POS 50
/** /**
* Software Endstops * Software Endstops
@@ -1258,6 +1369,9 @@
#define MIN_SOFTWARE_ENDSTOP_X #define MIN_SOFTWARE_ENDSTOP_X
#define MIN_SOFTWARE_ENDSTOP_Y #define MIN_SOFTWARE_ENDSTOP_Y
#define MIN_SOFTWARE_ENDSTOP_Z #define MIN_SOFTWARE_ENDSTOP_Z
#define MIN_SOFTWARE_ENDSTOP_I
#define MIN_SOFTWARE_ENDSTOP_J
#define MIN_SOFTWARE_ENDSTOP_K
#endif #endif
// Max software endstops constrain movement within maximum coordinate bounds // Max software endstops constrain movement within maximum coordinate bounds
@@ -1266,6 +1380,9 @@
#define MAX_SOFTWARE_ENDSTOP_X #define MAX_SOFTWARE_ENDSTOP_X
#define MAX_SOFTWARE_ENDSTOP_Y #define MAX_SOFTWARE_ENDSTOP_Y
#define MAX_SOFTWARE_ENDSTOP_Z #define MAX_SOFTWARE_ENDSTOP_Z
#define MAX_SOFTWARE_ENDSTOP_I
#define MAX_SOFTWARE_ENDSTOP_J
#define MAX_SOFTWARE_ENDSTOP_K
#endif #endif
#if EITHER(MIN_SOFTWARE_ENDSTOPS, MAX_SOFTWARE_ENDSTOPS) #if EITHER(MIN_SOFTWARE_ENDSTOPS, MAX_SOFTWARE_ENDSTOPS)
@@ -1577,6 +1694,9 @@
//#define MANUAL_X_HOME_POS 0 //#define MANUAL_X_HOME_POS 0
//#define MANUAL_Y_HOME_POS 0 //#define MANUAL_Y_HOME_POS 0
//#define MANUAL_Z_HOME_POS 0 //#define MANUAL_Z_HOME_POS 0
//#define MANUAL_I_HOME_POS 0
//#define MANUAL_J_HOME_POS 0
//#define MANUAL_K_HOME_POS 0
// Use "Z Safe Homing" to avoid homing with a Z probe outside the bed area. // Use "Z Safe Homing" to avoid homing with a Z probe outside the bed area.
// //
@@ -1819,11 +1939,20 @@
/** /**
* Print Job Timer * Print Job Timer
* *
* Automatically start and stop the print job timer on M104/M109/M190. * Automatically start and stop the print job timer on M104/M109/M140/M190/M141/M191.
* The print job timer will only be stopped if the bed/chamber target temp is
* below BED_MINTEMP/CHAMBER_MINTEMP.
* *
* M104 (hotend, no wait) - high temp = none, low temp = stop timer * M104 (hotend, no wait) - high temp = none, low temp = stop timer
* M109 (hotend, wait) - high temp = start timer, low temp = stop timer * M109 (hotend, wait) - high temp = start timer, low temp = stop timer
* M190 (bed, wait) - high temp = start timer, low temp = none * M140 (bed, no wait) - high temp = none, low temp = stop timer
* M190 (bed, wait) - high temp = start timer, low temp = none
* M141 (chamber, no wait) - high temp = none, low temp = stop timer
* M191 (chamber, wait) - high temp = start timer, low temp = none
*
* For M104/M109, high temp is anything over EXTRUDE_MINTEMP / 2.
* For M140/M190, high temp is anything over BED_MINTEMP.
* For M141/M191, high temp is anything over CHAMBER_MINTEMP.
* *
* The timer can also be controlled with the following commands: * The timer can also be controlled with the following commands:
* *
@@ -2685,7 +2814,7 @@
//#define NEOPIXEL_LED //#define NEOPIXEL_LED
#if ENABLED(NEOPIXEL_LED) #if ENABLED(NEOPIXEL_LED)
#define NEOPIXEL_TYPE NEO_GRBW // NEO_GRBW / NEO_GRB - four/three channel driver type (defined in Adafruit_NeoPixel.h) #define NEOPIXEL_TYPE NEO_GRBW // NEO_GRBW / NEO_GRB - four/three channel driver type (defined in Adafruit_NeoPixel.h)
#define NEOPIXEL_PIN 4 // LED driving pin //#define NEOPIXEL_PIN 4 // LED driving pin
//#define NEOPIXEL2_TYPE NEOPIXEL_TYPE //#define NEOPIXEL2_TYPE NEOPIXEL_TYPE
//#define NEOPIXEL2_PIN 5 //#define NEOPIXEL2_PIN 5
#define NEOPIXEL_PIXELS 30 // Number of LEDs in the strip. (Longest strip when NEOPIXEL2_SEPARATE is disabled.) #define NEOPIXEL_PIXELS 30 // Number of LEDs in the strip. (Longest strip when NEOPIXEL2_SEPARATE is disabled.)
@@ -2703,10 +2832,11 @@
//#define NEOPIXEL2_INSERIES // Default behavior is NeoPixel 2 in parallel //#define NEOPIXEL2_INSERIES // Default behavior is NeoPixel 2 in parallel
#endif #endif
// Use a single NeoPixel LED for static (background) lighting // Use some of the NeoPixel LEDs for static (background) lighting
//#define NEOPIXEL_BKGD_LED_INDEX 0 // Index of the LED to use //#define NEOPIXEL_BKGD_INDEX_FIRST 0 // Index of the first background LED
//#define NEOPIXEL_BKGD_COLOR { 255, 255, 255, 0 } // R, G, B, W //#define NEOPIXEL_BKGD_INDEX_LAST 5 // Index of the last background LED
//#define NEOPIXEL_BKGD_ALWAYS_ON // Keep the backlight on when other NeoPixels are off //#define NEOPIXEL_BKGD_COLOR { 255, 255, 255, 0 } // R, G, B, W
//#define NEOPIXEL_BKGD_ALWAYS_ON // Keep the backlight on when other NeoPixels are off
#endif #endif
/** /**

View File

@@ -30,7 +30,7 @@
* *
* Basic settings can be found in Configuration.h * Basic settings can be found in Configuration.h
*/ */
#define CONFIGURATION_ADV_H_VERSION 02000801 #define CONFIGURATION_ADV_H_VERSION 02000901
//=========================================================================== //===========================================================================
//============================= Thermal Settings ============================ //============================= Thermal Settings ============================
@@ -125,6 +125,12 @@
#define PROBE_BETA 3950 // Beta value #define PROBE_BETA 3950 // Beta value
#endif #endif
#if TEMP_SENSOR_REDUNDANT == 1000
#define REDUNDANT_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
#define REDUNDANT_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
#define REDUNDANT_BETA 3950 // Beta value
#endif
// //
// Hephestos 2 24V heated bed upgrade kit. // Hephestos 2 24V heated bed upgrade kit.
// https://store.bq.com/en/heated-bed-kit-hephestos2 // https://store.bq.com/en/heated-bed-kit-hephestos2
@@ -196,7 +202,7 @@
#define COOLER_MAXTEMP 26 // (°C) #define COOLER_MAXTEMP 26 // (°C)
#define COOLER_DEFAULT_TEMP 16 // (°C) #define COOLER_DEFAULT_TEMP 16 // (°C)
#define TEMP_COOLER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target #define TEMP_COOLER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
#define COOLER_PIN 8 // Laser cooler on/off pin used to control power to the cooling element e.g. TEC, External chiller via relay #define COOLER_PIN 8 // Laser cooler on/off pin used to control power to the cooling element (e.g., TEC, External chiller via relay)
#define COOLER_INVERTING false #define COOLER_INVERTING false
#define TEMP_COOLER_PIN 15 // Laser/Cooler temperature sensor pin. ADC is required. #define TEMP_COOLER_PIN 15 // Laser/Cooler temperature sensor pin. ADC is required.
#define COOLER_FAN // Enable a fan on the cooler, Fan# 0,1,2,3 etc. #define COOLER_FAN // Enable a fan on the cooler, Fan# 0,1,2,3 etc.
@@ -526,6 +532,11 @@
//#define USE_OCR2A_AS_TOP //#define USE_OCR2A_AS_TOP
#endif #endif
/**
* Use one of the PWM fans as a redundant part-cooling fan
*/
//#define REDUNDANT_PART_COOLING_FAN 2 // Index of the fan to sync with FAN 0.
// @section extruder // @section extruder
/** /**
@@ -671,6 +682,12 @@
#endif #endif
#endif #endif
// Drive the E axis with two synchronized steppers
//#define E_DUAL_STEPPER_DRIVERS
#if ENABLED(E_DUAL_STEPPER_DRIVERS)
//#define INVERT_E1_VS_E0_DIR // Enable if the E motors need opposite DIR states
#endif
/** /**
* Dual X Carriage * Dual X Carriage
* *
@@ -734,7 +751,7 @@
* the position of the toolhead relative to the workspace. * the position of the toolhead relative to the workspace.
*/ */
//#define SENSORLESS_BACKOFF_MM { 2, 2 } // (mm) Backoff from endstops before sensorless homing //#define SENSORLESS_BACKOFF_MM { 2, 2, 0 } // (mm) Backoff from endstops before sensorless homing
#define HOMING_BUMP_MM { 5, 5, 2 } // (mm) Backoff from endstops after first bump #define HOMING_BUMP_MM { 5, 5, 2 } // (mm) Backoff from endstops after first bump
#define HOMING_BUMP_DIVISOR { 2, 2, 4 } // Re-Bump Speed Divisor (Divides the Homing Feedrate) #define HOMING_BUMP_DIVISOR { 2, 2, 4 } // Re-Bump Speed Divisor (Divides the Homing Feedrate)
@@ -918,6 +935,9 @@
#define INVERT_X_STEP_PIN false #define INVERT_X_STEP_PIN false
#define INVERT_Y_STEP_PIN false #define INVERT_Y_STEP_PIN false
#define INVERT_Z_STEP_PIN false #define INVERT_Z_STEP_PIN false
#define INVERT_I_STEP_PIN false
#define INVERT_J_STEP_PIN false
#define INVERT_K_STEP_PIN false
#define INVERT_E_STEP_PIN false #define INVERT_E_STEP_PIN false
/** /**
@@ -929,6 +949,9 @@
#define DISABLE_INACTIVE_X true #define DISABLE_INACTIVE_X true
#define DISABLE_INACTIVE_Y true #define DISABLE_INACTIVE_Y true
#define DISABLE_INACTIVE_Z true // Set 'false' if the nozzle could fall onto your printed part! #define DISABLE_INACTIVE_Z true // Set 'false' if the nozzle could fall onto your printed part!
#define DISABLE_INACTIVE_I true
#define DISABLE_INACTIVE_J true
#define DISABLE_INACTIVE_K true
#define DISABLE_INACTIVE_E true #define DISABLE_INACTIVE_E true
// Default Minimum Feedrates for printing and travel moves // Default Minimum Feedrates for printing and travel moves
@@ -969,7 +992,7 @@
#if ENABLED(BACKLASH_COMPENSATION) #if ENABLED(BACKLASH_COMPENSATION)
// Define values for backlash distance and correction. // Define values for backlash distance and correction.
// If BACKLASH_GCODE is enabled these values are the defaults. // If BACKLASH_GCODE is enabled these values are the defaults.
#define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (mm) #define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (mm) One value for each linear axis
#define BACKLASH_CORRECTION 0.0 // 0.0 = no correction; 1.0 = full correction #define BACKLASH_CORRECTION 0.0 // 0.0 = no correction; 1.0 = full correction
// Add steps for motor direction changes on CORE kinematics // Add steps for motor direction changes on CORE kinematics
@@ -1040,6 +1063,13 @@
#define CALIBRATION_MEASURE_LEFT #define CALIBRATION_MEASURE_LEFT
#define CALIBRATION_MEASURE_BACK #define CALIBRATION_MEASURE_BACK
//#define CALIBRATION_MEASURE_IMIN
//#define CALIBRATION_MEASURE_IMAX
//#define CALIBRATION_MEASURE_JMIN
//#define CALIBRATION_MEASURE_JMAX
//#define CALIBRATION_MEASURE_KMIN
//#define CALIBRATION_MEASURE_KMAX
// Probing at the exact top center only works if the center is flat. If // Probing at the exact top center only works if the center is flat. If
// probing on a screwhead or hollow washer, probe near the edges. // probing on a screwhead or hollow washer, probe near the edges.
//#define CALIBRATION_MEASURE_AT_TOP_EDGES //#define CALIBRATION_MEASURE_AT_TOP_EDGES
@@ -1301,6 +1331,8 @@
//#define BROWSE_MEDIA_ON_INSERT // Open the file browser when media is inserted //#define BROWSE_MEDIA_ON_INSERT // Open the file browser when media is inserted
//#define MEDIA_MENU_AT_TOP // Force the media menu to be listed on the top of the main menu
#define EVENT_GCODE_SD_ABORT "G28XY" // G-code to run on SD Abort Print (e.g., "G28XY" or "G27") #define EVENT_GCODE_SD_ABORT "G28XY" // G-code to run on SD Abort Print (e.g., "G28XY" or "G27")
#if ENABLED(PRINTER_EVENT_LEDS) #if ENABLED(PRINTER_EVENT_LEDS)
@@ -1562,7 +1594,7 @@
*/ */
//#define STATUS_COMBINE_HEATERS // Use combined heater images instead of separate ones //#define STATUS_COMBINE_HEATERS // Use combined heater images instead of separate ones
//#define STATUS_HOTEND_NUMBERLESS // Use plain hotend icons instead of numbered ones (with 2+ hotends) //#define STATUS_HOTEND_NUMBERLESS // Use plain hotend icons instead of numbered ones (with 2+ hotends)
#define STATUS_HOTEND_INVERTED // Show solid nozzle bitmaps when heating (Requires STATUS_HOTEND_ANIM) #define STATUS_HOTEND_INVERTED // Show solid nozzle bitmaps when heating (Requires STATUS_HOTEND_ANIM for numbered hotends)
#define STATUS_HOTEND_ANIM // Use a second bitmap to indicate hotend heating #define STATUS_HOTEND_ANIM // Use a second bitmap to indicate hotend heating
#define STATUS_BED_ANIM // Use a second bitmap to indicate bed heating #define STATUS_BED_ANIM // Use a second bitmap to indicate bed heating
#define STATUS_CHAMBER_ANIM // Use a second bitmap to indicate chamber heating #define STATUS_CHAMBER_ANIM // Use a second bitmap to indicate chamber heating
@@ -1940,30 +1972,30 @@
//#define USE_TEMP_EXT_COMPENSATION //#define USE_TEMP_EXT_COMPENSATION
// Probe temperature calibration generates a table of values starting at PTC_SAMPLE_START // Probe temperature calibration generates a table of values starting at PTC_SAMPLE_START
// (e.g. 30), in steps of PTC_SAMPLE_RES (e.g. 5) with PTC_SAMPLE_COUNT (e.g. 10) samples. // (e.g., 30), in steps of PTC_SAMPLE_RES (e.g., 5) with PTC_SAMPLE_COUNT (e.g., 10) samples.
//#define PTC_SAMPLE_START 30.0f //#define PTC_SAMPLE_START 30 // (°C)
//#define PTC_SAMPLE_RES 5.0f //#define PTC_SAMPLE_RES 5 // (°C)
//#define PTC_SAMPLE_COUNT 10U //#define PTC_SAMPLE_COUNT 10
// Bed temperature calibration builds a similar table. // Bed temperature calibration builds a similar table.
//#define BTC_SAMPLE_START 60.0f //#define BTC_SAMPLE_START 60 // (°C)
//#define BTC_SAMPLE_RES 5.0f //#define BTC_SAMPLE_RES 5 // (°C)
//#define BTC_SAMPLE_COUNT 10U //#define BTC_SAMPLE_COUNT 10
// The temperature the probe should be at while taking measurements during bed temperature // The temperature the probe should be at while taking measurements during bed temperature
// calibration. // calibration.
//#define BTC_PROBE_TEMP 30.0f //#define BTC_PROBE_TEMP 30 // (°C)
// Height above Z=0.0f to raise the nozzle. Lowering this can help the probe to heat faster. // Height above Z=0.0 to raise the nozzle. Lowering this can help the probe to heat faster.
// Note: the Z=0.0f offset is determined by the probe offset which can be set using M851. // Note: the Z=0.0 offset is determined by the probe offset which can be set using M851.
//#define PTC_PROBE_HEATING_OFFSET 0.5f //#define PTC_PROBE_HEATING_OFFSET 0.5
// Height to raise the Z-probe between heating and taking the next measurement. Some probes // Height to raise the Z-probe between heating and taking the next measurement. Some probes
// may fail to untrigger if they have been triggered for a long time, which can be solved by // may fail to untrigger if they have been triggered for a long time, which can be solved by
// increasing the height the probe is raised to. // increasing the height the probe is raised to.
//#define PTC_PROBE_RAISE 15U //#define PTC_PROBE_RAISE 15
// If the probe is outside of the defined range, use linear extrapolation using the closest // If the probe is outside of the defined range, use linear extrapolation using the closest
// point and the PTC_LINEAR_EXTRAPOLATION'th next point. E.g. if set to 4 it will use data[0] // point and the PTC_LINEAR_EXTRAPOLATION'th next point. E.g. if set to 4 it will use data[0]
@@ -2078,7 +2110,7 @@
// @section motion // @section motion
// The number of linear moves that can be in the planner at once. // The number of linear moves that can be in the planner at once.
// The value of BLOCK_BUFFER_SIZE must be a power of 2 (e.g. 8, 16, 32) // The value of BLOCK_BUFFER_SIZE must be a power of 2 (e.g., 8, 16, 32)
#if BOTH(SDSUPPORT, DIRECT_STEPPING) #if BOTH(SDSUPPORT, DIRECT_STEPPING)
#define BLOCK_BUFFER_SIZE 8 #define BLOCK_BUFFER_SIZE 8
#elif ENABLED(SDSUPPORT) #elif ENABLED(SDSUPPORT)
@@ -2114,9 +2146,6 @@
//#define SERIAL_XON_XOFF //#define SERIAL_XON_XOFF
#endif #endif
// Add M575 G-code to change the baud rate
//#define BAUD_RATE_GCODE
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
// Enable this option to collect and display the maximum // Enable this option to collect and display the maximum
// RX queue usage after transferring a file to SD. // RX queue usage after transferring a file to SD.
@@ -2237,6 +2266,13 @@
//#define EVENT_GCODE_AFTER_TOOLCHANGE "G12X" // Extra G-code to run after tool-change //#define EVENT_GCODE_AFTER_TOOLCHANGE "G12X" // Extra G-code to run after tool-change
#endif #endif
/**
* Extra G-code to run while executing tool-change commands. Can be used to use an additional
* stepper motor (I axis, see option LINEAR_AXES in Configuration.h) to drive the tool-changer.
*/
//#define EVENT_GCODE_TOOLCHANGE_T0 "G28 A\nG1 A0" // Extra G-code to run while executing tool-change command T0
//#define EVENT_GCODE_TOOLCHANGE_T1 "G1 A10" // Extra G-code to run while executing tool-change command T1
/** /**
* Tool Sensors detect when tools have been picked up or dropped. * Tool Sensors detect when tools have been picked up or dropped.
* Requires the pins TOOL_SENSOR1_PIN, TOOL_SENSOR2_PIN, etc. * Requires the pins TOOL_SENSOR1_PIN, TOOL_SENSOR2_PIN, etc.
@@ -2414,6 +2450,24 @@
#define Z4_MICROSTEPS Z_MICROSTEPS #define Z4_MICROSTEPS Z_MICROSTEPS
#endif #endif
#if AXIS_DRIVER_TYPE_I(TMC26X)
#define I_MAX_CURRENT 1000
#define I_SENSE_RESISTOR 91
#define I_MICROSTEPS 16
#endif
#if AXIS_DRIVER_TYPE_J(TMC26X)
#define J_MAX_CURRENT 1000
#define J_SENSE_RESISTOR 91
#define J_MICROSTEPS 16
#endif
#if AXIS_DRIVER_TYPE_K(TMC26X)
#define K_MAX_CURRENT 1000
#define K_SENSE_RESISTOR 91
#define K_MICROSTEPS 16
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X) #if AXIS_DRIVER_TYPE_E0(TMC26X)
#define E0_MAX_CURRENT 1000 #define E0_MAX_CURRENT 1000
#define E0_SENSE_RESISTOR 91 #define E0_SENSE_RESISTOR 91
@@ -2564,6 +2618,33 @@
//#define Z4_INTERPOLATE true //#define Z4_INTERPOLATE true
#endif #endif
#if AXIS_IS_TMC(I)
#define I_CURRENT 800
#define I_CURRENT_HOME I_CURRENT
#define I_MICROSTEPS 16
#define I_RSENSE 0.11
#define I_CHAIN_POS -1
//#define I_INTERPOLATE true
#endif
#if AXIS_IS_TMC(J)
#define J_CURRENT 800
#define J_CURRENT_HOME J_CURRENT
#define J_MICROSTEPS 16
#define J_RSENSE 0.11
#define J_CHAIN_POS -1
//#define J_INTERPOLATE true
#endif
#if AXIS_IS_TMC(K)
#define K_CURRENT 800
#define K_CURRENT_HOME K_CURRENT
#define K_MICROSTEPS 16
#define K_RSENSE 0.11
#define K_CHAIN_POS -1
//#define K_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E0) #if AXIS_IS_TMC(E0)
#define E0_CURRENT 800 #define E0_CURRENT 800
#define E0_MICROSTEPS 16 #define E0_MICROSTEPS 16
@@ -2639,6 +2720,10 @@
//#define Y2_CS_PIN -1 //#define Y2_CS_PIN -1
//#define Z2_CS_PIN -1 //#define Z2_CS_PIN -1
//#define Z3_CS_PIN -1 //#define Z3_CS_PIN -1
//#define Z4_CS_PIN -1
//#define I_CS_PIN -1
//#define J_CS_PIN -1
//#define K_CS_PIN -1
//#define E0_CS_PIN -1 //#define E0_CS_PIN -1
//#define E1_CS_PIN -1 //#define E1_CS_PIN -1
//#define E2_CS_PIN -1 //#define E2_CS_PIN -1
@@ -2678,6 +2763,9 @@
//#define Z2_SLAVE_ADDRESS 0 //#define Z2_SLAVE_ADDRESS 0
//#define Z3_SLAVE_ADDRESS 0 //#define Z3_SLAVE_ADDRESS 0
//#define Z4_SLAVE_ADDRESS 0 //#define Z4_SLAVE_ADDRESS 0
//#define I_SLAVE_ADDRESS 0
//#define J_SLAVE_ADDRESS 0
//#define K_SLAVE_ADDRESS 0
//#define E0_SLAVE_ADDRESS 0 //#define E0_SLAVE_ADDRESS 0
//#define E1_SLAVE_ADDRESS 0 //#define E1_SLAVE_ADDRESS 0
//#define E2_SLAVE_ADDRESS 0 //#define E2_SLAVE_ADDRESS 0
@@ -2702,6 +2790,9 @@
*/ */
#define STEALTHCHOP_XY #define STEALTHCHOP_XY
#define STEALTHCHOP_Z #define STEALTHCHOP_Z
#define STEALTHCHOP_I
#define STEALTHCHOP_J
#define STEALTHCHOP_K
#define STEALTHCHOP_E #define STEALTHCHOP_E
/** /**
@@ -2773,6 +2864,9 @@
#define Z2_HYBRID_THRESHOLD 3 #define Z2_HYBRID_THRESHOLD 3
#define Z3_HYBRID_THRESHOLD 3 #define Z3_HYBRID_THRESHOLD 3
#define Z4_HYBRID_THRESHOLD 3 #define Z4_HYBRID_THRESHOLD 3
#define I_HYBRID_THRESHOLD 3
#define J_HYBRID_THRESHOLD 3
#define K_HYBRID_THRESHOLD 3
#define E0_HYBRID_THRESHOLD 30 #define E0_HYBRID_THRESHOLD 30
#define E1_HYBRID_THRESHOLD 30 #define E1_HYBRID_THRESHOLD 30
#define E2_HYBRID_THRESHOLD 30 #define E2_HYBRID_THRESHOLD 30
@@ -2798,7 +2892,7 @@
* *
* It is recommended to set HOMING_BUMP_MM to { 0, 0, 0 }. * It is recommended to set HOMING_BUMP_MM to { 0, 0, 0 }.
* *
* SPI_ENDSTOPS *** Beta feature! *** TMC2130 Only *** * SPI_ENDSTOPS *** Beta feature! *** TMC2130/TMC5160 Only ***
* Poll the driver through SPI to determine load when homing. * Poll the driver through SPI to determine load when homing.
* Removes the need for a wire from DIAG1 to an endstop pin. * Removes the need for a wire from DIAG1 to an endstop pin.
* *
@@ -2819,6 +2913,9 @@
//#define Z2_STALL_SENSITIVITY Z_STALL_SENSITIVITY //#define Z2_STALL_SENSITIVITY Z_STALL_SENSITIVITY
//#define Z3_STALL_SENSITIVITY Z_STALL_SENSITIVITY //#define Z3_STALL_SENSITIVITY Z_STALL_SENSITIVITY
//#define Z4_STALL_SENSITIVITY Z_STALL_SENSITIVITY //#define Z4_STALL_SENSITIVITY Z_STALL_SENSITIVITY
//#define I_STALL_SENSITIVITY 8
//#define J_STALL_SENSITIVITY 8
//#define K_STALL_SENSITIVITY 8
//#define SPI_ENDSTOPS // TMC2130 only //#define SPI_ENDSTOPS // TMC2130 only
//#define IMPROVE_HOMING_RELIABILITY //#define IMPROVE_HOMING_RELIABILITY
#endif #endif
@@ -2959,6 +3056,33 @@
#define Z4_SLEW_RATE 1 #define Z4_SLEW_RATE 1
#endif #endif
#if AXIS_DRIVER_TYPE_I(L6470)
#define I_MICROSTEPS 128
#define I_OVERCURRENT 2000
#define I_STALLCURRENT 1500
#define I_MAX_VOLTAGE 127
#define I_CHAIN_POS -1
#define I_SLEW_RATE 1
#endif
#if AXIS_DRIVER_TYPE_J(L6470)
#define J_MICROSTEPS 128
#define J_OVERCURRENT 2000
#define J_STALLCURRENT 1500
#define J_MAX_VOLTAGE 127
#define J_CHAIN_POS -1
#define J_SLEW_RATE 1
#endif
#if AXIS_DRIVER_TYPE_K(L6470)
#define K_MICROSTEPS 128
#define K_OVERCURRENT 2000
#define K_STALLCURRENT 1500
#define K_MAX_VOLTAGE 127
#define K_CHAIN_POS -1
#define K_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E0) #if AXIS_IS_L64XX(E0)
#define E0_MICROSTEPS 128 #define E0_MICROSTEPS 128
#define E0_OVERCURRENT 2000 #define E0_OVERCURRENT 2000
@@ -3308,8 +3432,18 @@
#define SPINDLE_LASER_POWERDOWN_DELAY 50 // (ms) Delay to allow the spindle to stop #define SPINDLE_LASER_POWERDOWN_DELAY 50 // (ms) Delay to allow the spindle to stop
#endif #endif
//
// Laser I2C Ammeter (High precision INA226 low/high side module)
//
//#define I2C_AMMETER
#if ENABLED(I2C_AMMETER)
#define I2C_AMMETER_IMAX 0.1 // (Amps) Calibration value for the expected current range
#define I2C_AMMETER_SHUNT_RESISTOR 0.1 // (Ohms) Calibration shunt resistor value
#endif
#endif #endif
#endif #endif // SPINDLE_FEATURE || LASER_FEATURE
/** /**
* Synchronous Laser Control with M106/M107 * Synchronous Laser Control with M106/M107

View File

@@ -28,7 +28,7 @@
/** /**
* Marlin release version identifier * Marlin release version identifier
*/ */
//#define SHORT_BUILD_VERSION "2.0.8.1" //#define SHORT_BUILD_VERSION "2.0.9.1"
/** /**
* Verbose version identifier which should contain a reference to the location * Verbose version identifier which should contain a reference to the location
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release * here we define this default string as the date where the latest release
* version was tagged. * version was tagged.
*/ */
//#define STRING_DISTRIBUTION_DATE "2021-05-15" //#define STRING_DISTRIBUTION_DATE "2021-06-27"
/** /**
* Defines a generic printer name to be output to the LCD after booting Marlin. * Defines a generic printer name to be output to the LCD after booting Marlin.

View File

@@ -186,7 +186,7 @@ inline void HAL_adc_init() {
#define GET_PIN_MAP_INDEX(pin) pin #define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
#define HAL_SENSITIVE_PINS 0, 1 #define HAL_SENSITIVE_PINS 0, 1,
#ifdef __AVR_AT90USB1286__ #ifdef __AVR_AT90USB1286__
#define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0) #define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)

View File

@@ -168,6 +168,51 @@ void setup_endstop_interrupts() {
pciSetup(Z_MIN_PIN); pciSetup(Z_MIN_PIN);
#endif #endif
#endif #endif
#if HAS_I_MAX
#if (digitalPinToInterrupt(I_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(I_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(I_MAX_PIN), "I_MAX_PIN is not interrupt-capable");
pciSetup(I_MAX_PIN);
#endif
#elif HAS_I_MIN
#if (digitalPinToInterrupt(I_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(I_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(I_MIN_PIN), "I_MIN_PIN is not interrupt-capable");
pciSetup(I_MIN_PIN);
#endif
#endif
#if HAS_J_MAX
#if (digitalPinToInterrupt(J_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(J_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(J_MAX_PIN), "J_MAX_PIN is not interrupt-capable");
pciSetup(J_MAX_PIN);
#endif
#elif HAS_J_MIN
#if (digitalPinToInterrupt(J_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(J_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(J_MIN_PIN), "J_MIN_PIN is not interrupt-capable");
pciSetup(J_MIN_PIN);
#endif
#endif
#if HAS_K_MAX
#if (digitalPinToInterrupt(K_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(K_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(K_MAX_PIN), "K_MAX_PIN is not interrupt-capable");
pciSetup(K_MAX_PIN);
#endif
#elif HAS_K_MIN
#if (digitalPinToInterrupt(K_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(K_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(K_MIN_PIN), "K_MIN_PIN is not interrupt-capable");
pciSetup(K_MIN_PIN);
#endif
#endif
#if HAS_X2_MAX #if HAS_X2_MAX
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MAX_PIN); _ATTACH(X2_MAX_PIN);
@@ -256,6 +301,5 @@ void setup_endstop_interrupts() {
pciSetup(Z_MIN_PROBE_PIN); pciSetup(Z_MIN_PROBE_PIN);
#endif #endif
#endif #endif
// If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI. // If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI.
} }

View File

@@ -38,7 +38,7 @@
// portModeRegister takes a different argument // portModeRegister takes a different argument
#define digitalPinToTimer_DEBUG(p) digitalPinToTimer(p) #define digitalPinToTimer_DEBUG(p) digitalPinToTimer(p)
#define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask(p) #define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask(p)
#define digitalPinToPort_DEBUG(p) digitalPinToPort_Teensy(p) #define digitalPinToPort_DEBUG(p) digitalPinToPort(p)
#define GET_PINMODE(pin) (*portModeRegister(pin) & digitalPinToBitMask_DEBUG(pin)) #define GET_PINMODE(pin) (*portModeRegister(pin) & digitalPinToBitMask_DEBUG(pin))
#elif AVR_ATmega2560_FAMILY_PLUS_70 // So we can access/display all the pins on boards using more than 70 #elif AVR_ATmega2560_FAMILY_PLUS_70 // So we can access/display all the pins on boards using more than 70

View File

@@ -64,4 +64,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN)); TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
} }

View File

@@ -59,4 +59,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN)); TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
} }

View File

@@ -25,43 +25,6 @@
#include "../../../gcode/parser.h" #include "../../../gcode/parser.h"
uint8_t analog_offset = NUM_DIGITAL_PINS - NUM_ANALOG_INPUTS;
// Get the digital pin for an analog index
pin_t analogInputToDigitalPin(const int8_t p) {
return (WITHIN(p, 0, NUM_ANALOG_INPUTS) ? analog_offset + p : P_NC);
}
// Return the index of a pin number
int16_t GET_PIN_MAP_INDEX(const pin_t pin) {
return pin;
}
// Test whether the pin is valid
bool VALID_PIN(const pin_t p) {
return WITHIN(p, 0, NUM_DIGITAL_PINS);
}
// Get the analog index for a digital pin
int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t p) {
return (WITHIN(p, analog_offset, NUM_DIGITAL_PINS) ? p - analog_offset : P_NC);
}
// Test whether the pin is PWM
bool PWM_PIN(const pin_t p) {
return false;
}
// Test whether the pin is interruptable
bool INTERRUPT_PIN(const pin_t p) {
return false;
}
// Get the pin number at the given index
pin_t GET_PIN_MAP_PIN(const int16_t ind) {
return ind;
}
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) { int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
return parser.intval(code, dval); return parser.intval(code, dval);
} }

View File

@@ -34,26 +34,32 @@ constexpr uint8_t NUM_ANALOG_INPUTS = 16;
#define HAL_SENSITIVE_PINS #define HAL_SENSITIVE_PINS
constexpr uint8_t analog_offset = NUM_DIGITAL_PINS - NUM_ANALOG_INPUTS;
// Get the digital pin for an analog index // Get the digital pin for an analog index
pin_t analogInputToDigitalPin(const int8_t p); constexpr pin_t analogInputToDigitalPin(const int8_t p) {
return (WITHIN(p, 0, NUM_ANALOG_INPUTS) ? analog_offset + p : P_NC);
// Return the index of a pin number }
int16_t GET_PIN_MAP_INDEX(const pin_t pin);
// Test whether the pin is valid
bool VALID_PIN(const pin_t p);
// Get the analog index for a digital pin // Get the analog index for a digital pin
int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t p); constexpr int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t p) {
return (WITHIN(p, analog_offset, NUM_DIGITAL_PINS) ? p - analog_offset : P_NC);
}
// Return the index of a pin number
constexpr int16_t GET_PIN_MAP_INDEX(const pin_t pin) { return pin; }
// Test whether the pin is valid
constexpr bool VALID_PIN(const pin_t p) { return WITHIN(p, 0, NUM_DIGITAL_PINS); }
// Test whether the pin is PWM // Test whether the pin is PWM
bool PWM_PIN(const pin_t p); constexpr bool PWM_PIN(const pin_t p) { return false; }
// Test whether the pin is interruptable // Test whether the pin is interruptable
bool INTERRUPT_PIN(const pin_t p); constexpr bool INTERRUPT_PIN(const pin_t p) { return false; }
// Get the pin number at the given index // Get the pin number at the given index
pin_t GET_PIN_MAP_PIN(const int16_t ind); constexpr pin_t GET_PIN_MAP_PIN(const int16_t ind) { return ind; }
// Parse a G-code word into a pin index // Parse a G-code word into a pin index
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval); int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);

View File

@@ -198,7 +198,7 @@ constexpr pin_t GET_PIN_MAP_PIN(const int16_t index) {
// Parse a G-code word into a pin index // Parse a G-code word into a pin index
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval); int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
// P0.6 thru P0.9 are for the onboard SD card // P0.6 thru P0.9 are for the onboard SD card
#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09 #define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09,
#define HAL_IDLETASK 1 #define HAL_IDLETASK 1
void HAL_idletask(); void HAL_idletask();

View File

@@ -66,11 +66,7 @@
#include <SoftwareSPI.h> #include <SoftwareSPI.h>
#ifndef HAL_SPI_SPEED static uint8_t SPI_speed = SPI_FULL_SPEED;
#define HAL_SPI_SPEED SPI_FULL_SPEED
#endif
static uint8_t SPI_speed = HAL_SPI_SPEED;
static uint8_t spiTransfer(uint8_t b) { static uint8_t spiTransfer(uint8_t b) {
return swSpiTransfer(b, SPI_speed, SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN); return swSpiTransfer(b, SPI_speed, SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
@@ -106,15 +102,13 @@
#else #else
#ifndef HAL_SPI_SPEED #ifdef SD_SPI_SPEED
#ifdef SD_SPI_SPEED #define INIT_SPI_SPEED SD_SPI_SPEED
#define HAL_SPI_SPEED SD_SPI_SPEED #else
#else #define INIT_SPI_SPEED SPI_FULL_SPEED
#define HAL_SPI_SPEED SPI_FULL_SPEED
#endif
#endif #endif
void spiBegin() { spiInit(HAL_SPI_SPEED); } // Set up SCK, MOSI & MISO pins for SSP0 void spiBegin() { spiInit(INIT_SPI_SPEED); } // Set up SCK, MOSI & MISO pins for SSP0
void spiInit(uint8_t spiRate) { void spiInit(uint8_t spiRate) {
#if SD_MISO_PIN == BOARD_SPI1_MISO_PIN #if SD_MISO_PIN == BOARD_SPI1_MISO_PIN

View File

@@ -122,4 +122,37 @@ void setup_endstop_interrupts() {
#endif #endif
_ATTACH(Z_MIN_PROBE_PIN); _ATTACH(Z_MIN_PROBE_PIN);
#endif #endif
#if HAS_I_MAX
#if !LPC1768_PIN_INTERRUPT_M(I_MAX_PIN)
#error "I_MAX_PIN is not INTERRUPT-capable."
#endif
_ATTACH(I_MAX_PIN);
#elif HAS_I_MIN
#if !LPC1768_PIN_INTERRUPT_M(I_MIN_PIN)
#error "I_MIN_PIN is not INTERRUPT-capable."
#endif
_ATTACH(I_MIN_PIN);
#endif
#if HAS_J_MAX
#if !LPC1768_PIN_INTERRUPT_M(J_MAX_PIN)
#error "J_MAX_PIN is not INTERRUPT-capable."
#endif
_ATTACH(J_MAX_PIN);
#elif HAS_J_MIN
#if !LPC1768_PIN_INTERRUPT_M(J_MIN_PIN)
#error "J_MIN_PIN is not INTERRUPT-capable."
#endif
_ATTACH(J_MIN_PIN);
#endif
#if HAS_K_MAX
#if !LPC1768_PIN_INTERRUPT_M(K_MAX_PIN)
#error "K_MAX_PIN is not INTERRUPT-capable."
#endif
_ATTACH(K_MAX_PIN);
#elif HAS_K_MIN
#if !LPC1768_PIN_INTERRUPT_M(K_MIN_PIN)
#error "K_MIN_PIN is not INTERRUPT-capable."
#endif
_ATTACH(K_MIN_PIN);
#endif
} }

View File

@@ -144,7 +144,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#error "Serial port pins (2) conflict with Z4 pins!" #error "Serial port pins (2) conflict with Z4 pins!"
#elif ANY_RX(2, X_DIR_PIN, Y_DIR_PIN) #elif ANY_RX(2, X_DIR_PIN, Y_DIR_PIN)
#error "Serial port pins (2) conflict with other pins!" #error "Serial port pins (2) conflict with other pins!"
#elif Y_HOME_DIR < 0 && IS_TX2(Y_STOP_PIN) #elif Y_HOME_TO_MIN && IS_TX2(Y_STOP_PIN)
#error "Serial port pins (2) conflict with Y endstop pin!" #error "Serial port pins (2) conflict with Y endstop pin!"
#elif HAS_CUSTOM_PROBE_PIN && IS_TX2(Z_MIN_PROBE_PIN) #elif HAS_CUSTOM_PROBE_PIN && IS_TX2(Z_MIN_PROBE_PIN)
#error "Serial port pins (2) conflict with probe pin!" #error "Serial port pins (2) conflict with probe pin!"

View File

@@ -54,7 +54,7 @@ enum XPTCoordinate : uint8_t {
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE, XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
}; };
#if !defined(XPT2046_Z1_THRESHOLD) #ifndef XPT2046_Z1_THRESHOLD
#define XPT2046_Z1_THRESHOLD 10 #define XPT2046_Z1_THRESHOLD 10
#endif #endif

View File

@@ -47,80 +47,38 @@
#include "../../module/endstops.h" #include "../../module/endstops.h"
#define MATCH_EILINE(P1,P2) (P1 != P2 && PIN_TO_EILINE(P1) == PIN_TO_EILINE(P2)) #define MATCH_EILINE(P1,P2) (P1 != P2 && PIN_TO_EILINE(P1) == PIN_TO_EILINE(P2))
#if HAS_X_MAX #define MATCH_X_MAX_EILINE(P) TERN0(HAS_X_MAX, DEFER4(MATCH_EILINE)(P, X_MAX_PIN))
#define MATCH_X_MAX_EILINE(P) MATCH_EILINE(P, X_MAX_PIN) #define MATCH_X_MIN_EILINE(P) TERN0(HAS_X_MIN, DEFER4(MATCH_EILINE)(P, X_MIN_PIN))
#else #define MATCH_Y_MAX_EILINE(P) TERN0(HAS_Y_MAX, DEFER4(MATCH_EILINE)(P, Y_MAX_PIN))
#define MATCH_X_MAX_EILINE(P) false #define MATCH_Y_MIN_EILINE(P) TERN0(HAS_Y_MIN, DEFER4(MATCH_EILINE)(P, Y_MIN_PIN))
#endif #define MATCH_Z_MAX_EILINE(P) TERN0(HAS_Z_MAX, DEFER4(MATCH_EILINE)(P, Z_MAX_PIN))
#if HAS_X_MIN #define MATCH_Z_MIN_EILINE(P) TERN0(HAS_Z_MIN, DEFER4(MATCH_EILINE)(P, Z_MIN_PIN))
#define MATCH_X_MIN_EILINE(P) MATCH_EILINE(P, X_MIN_PIN) #define MATCH_I_MAX_EILINE(P) TERN0(HAS_I_MAX, DEFER4(MATCH_EILINE)(P, I_MAX_PIN))
#else #define MATCH_I_MIN_EILINE(P) TERN0(HAS_I_MIN, DEFER4(MATCH_EILINE)(P, I_MIN_PIN))
#define MATCH_X_MIN_EILINE(P) false #define MATCH_J_MAX_EILINE(P) TERN0(HAS_J_MAX, DEFER4(MATCH_EILINE)(P, J_MAX_PIN))
#endif #define MATCH_J_MIN_EILINE(P) TERN0(HAS_J_MIN, DEFER4(MATCH_EILINE)(P, J_MIN_PIN))
#if HAS_Y_MAX #define MATCH_K_MAX_EILINE(P) TERN0(HAS_K_MAX, DEFER4(MATCH_EILINE)(P, K_MAX_PIN))
#define MATCH_Y_MAX_EILINE(P) MATCH_EILINE(P, Y_MAX_PIN) #define MATCH_K_MIN_EILINE(P) TERN0(HAS_K_MIN, DEFER4(MATCH_EILINE)(P, K_MIN_PIN))
#else #define MATCH_Z2_MAX_EILINE(P) TERN0(HAS_Z2_MAX, DEFER4(MATCH_EILINE)(P, Z2_MAX_PIN))
#define MATCH_Y_MAX_EILINE(P) false #define MATCH_Z2_MIN_EILINE(P) TERN0(HAS_Z2_MIN, DEFER4(MATCH_EILINE)(P, Z2_MIN_PIN))
#endif #define MATCH_Z3_MAX_EILINE(P) TERN0(HAS_Z3_MAX, DEFER4(MATCH_EILINE)(P, Z3_MAX_PIN))
#if HAS_Y_MIN #define MATCH_Z3_MIN_EILINE(P) TERN0(HAS_Z3_MIN, DEFER4(MATCH_EILINE)(P, Z3_MIN_PIN))
#define MATCH_Y_MIN_EILINE(P) MATCH_EILINE(P, Y_MIN_PIN) #define MATCH_Z4_MAX_EILINE(P) TERN0(HAS_Z4_MAX, DEFER4(MATCH_EILINE)(P, Z4_MAX_PIN))
#else #define MATCH_Z4_MIN_EILINE(P) TERN0(HAS_Z4_MIN, DEFER4(MATCH_EILINE)(P, Z4_MIN_PIN))
#define MATCH_Y_MIN_EILINE(P) false #define MATCH_Z_MIN_PROBE_EILINE(P) TERN0(HAS_Z_MIN_PROBE_PIN, DEFER4(MATCH_EILINE)(P, Z_MIN_PROBE_PIN))
#endif
#if HAS_Z_MAX #define AVAILABLE_EILINE(P) ( PIN_TO_EILINE(P) != -1 \
#define MATCH_Z_MAX_EILINE(P) MATCH_EILINE(P, Z_MAX_PIN) && !MATCH_X_MAX_EILINE(P) && !MATCH_X_MIN_EILINE(P) \
#else && !MATCH_Y_MAX_EILINE(P) && !MATCH_Y_MIN_EILINE(P) \
#define MATCH_Z_MAX_EILINE(P) false && !MATCH_Z_MAX_EILINE(P) && !MATCH_Z_MIN_EILINE(P) \
#endif && !MATCH_I_MAX_EILINE(P) && !MATCH_I_MIN_EILINE(P) \
#if HAS_Z_MIN && !MATCH_J_MAX_EILINE(P) && !MATCH_J_MIN_EILINE(P) \
#define MATCH_Z_MIN_EILINE(P) MATCH_EILINE(P, Z_MIN_PIN) && !MATCH_K_MAX_EILINE(P) && !MATCH_K_MIN_EILINE(P) \
#else && !MATCH_Z2_MAX_EILINE(P) && !MATCH_Z2_MIN_EILINE(P) \
#define MATCH_Z_MIN_EILINE(P) false && !MATCH_Z3_MAX_EILINE(P) && !MATCH_Z3_MIN_EILINE(P) \
#endif && !MATCH_Z4_MAX_EILINE(P) && !MATCH_Z4_MIN_EILINE(P) \
#if HAS_Z2_MAX && !MATCH_Z_MIN_PROBE_EILINE(P) )
#define MATCH_Z2_MAX_EILINE(P) MATCH_EILINE(P, Z2_MAX_PIN)
#else
#define MATCH_Z2_MAX_EILINE(P) false
#endif
#if HAS_Z2_MIN
#define MATCH_Z2_MIN_EILINE(P) MATCH_EILINE(P, Z2_MIN_PIN)
#else
#define MATCH_Z2_MIN_EILINE(P) false
#endif
#if HAS_Z3_MAX
#define MATCH_Z3_MAX_EILINE(P) MATCH_EILINE(P, Z3_MAX_PIN)
#else
#define MATCH_Z3_MAX_EILINE(P) false
#endif
#if HAS_Z3_MIN
#define MATCH_Z3_MIN_EILINE(P) MATCH_EILINE(P, Z3_MIN_PIN)
#else
#define MATCH_Z3_MIN_EILINE(P) false
#endif
#if HAS_Z4_MAX
#define MATCH_Z4_MAX_EILINE(P) MATCH_EILINE(P, Z4_MAX_PIN)
#else
#define MATCH_Z4_MAX_EILINE(P) false
#endif
#if HAS_Z4_MIN
#define MATCH_Z4_MIN_EILINE(P) MATCH_EILINE(P, Z4_MIN_PIN)
#else
#define MATCH_Z4_MIN_EILINE(P) false
#endif
#if HAS_Z_MIN_PROBE_PIN
#define MATCH_Z_MIN_PROBE_EILINE(P) MATCH_EILINE(P, Z_MIN_PROBE_PIN)
#else
#define MATCH_Z_MIN_PROBE_EILINE(P) false
#endif
#define AVAILABLE_EILINE(P) (PIN_TO_EILINE(P) != -1 \
&& !MATCH_X_MAX_EILINE(P) && !MATCH_X_MIN_EILINE(P) \
&& !MATCH_Y_MAX_EILINE(P) && !MATCH_Y_MIN_EILINE(P) \
&& !MATCH_Z_MAX_EILINE(P) && !MATCH_Z_MIN_EILINE(P) \
&& !MATCH_Z2_MAX_EILINE(P) && !MATCH_Z2_MIN_EILINE(P) \
&& !MATCH_Z3_MAX_EILINE(P) && !MATCH_Z3_MIN_EILINE(P) \
&& !MATCH_Z4_MAX_EILINE(P) && !MATCH_Z4_MIN_EILINE(P) \
&& !MATCH_Z_MIN_PROBE_EILINE(P))
// One ISR for all EXT-Interrupts // One ISR for all EXT-Interrupts
void endstop_ISR() { endstops.update(); } void endstop_ISR() { endstops.update(); }
@@ -204,5 +162,37 @@ void setup_endstop_interrupts() {
#error "Z_MIN_PROBE_PIN has no EXTINT line available." #error "Z_MIN_PROBE_PIN has no EXTINT line available."
#endif #endif
_ATTACH(Z_MIN_PROBE_PIN); _ATTACH(Z_MIN_PROBE_PIN);
#elif HAS_I_MAX
#if !AVAILABLE_EILINE(I_MAX_PIN)
#error "I_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(I_MAX_PIN, endstop_ISR, CHANGE);
#elif HAS_I_MIN
#if !AVAILABLE_EILINE(I_MIN_PIN)
#error "I_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(I_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_J_MAX
#if !AVAILABLE_EILINE(J_MAX_PIN)
#error "J_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(J_MAX_PIN, endstop_ISR, CHANGE);
#elif HAS_J_MIN
#if !AVAILABLE_EILINE(J_MIN_PIN)
#error "J_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(J_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_K_MAX
#if !AVAILABLE_EILINE(K_MAX_PIN)
#error "K_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(K_MAX_PIN, endstop_ISR, CHANGE);
#elif HAS_K_MIN
#if !AVAILABLE_EILINE(K_MIN_PIN)
#error "K_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(K_MIN_PIN, endstop_ISR, CHANGE);
#endif #endif
} }

View File

@@ -195,6 +195,7 @@ uint16_t HAL_adc_get_result();
#ifdef STM32F1xx #ifdef STM32F1xx
#define JTAG_DISABLE() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_JTAGDISABLE) #define JTAG_DISABLE() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_JTAGDISABLE)
#define JTAGSWD_DISABLE() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_DISABLE) #define JTAGSWD_DISABLE() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_DISABLE)
#define JTAGSWD_RESET() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_RESET); // Reset: FULL SWD+JTAG
#endif #endif
#define PLATFORM_M997_SUPPORT #define PLATFORM_M997_SUPPORT

View File

@@ -163,11 +163,9 @@ static SPISettings spiConfig;
} }
spiConfig = SPISettings(clock, MSBFIRST, SPI_MODE0); spiConfig = SPISettings(clock, MSBFIRST, SPI_MODE0);
#if ENABLED(CUSTOM_SPI_PINS) SPI.setMISO(SD_MISO_PIN);
SPI.setMISO(SD_MISO_PIN); SPI.setMOSI(SD_MOSI_PIN);
SPI.setMOSI(SD_MOSI_PIN); SPI.setSCLK(SD_SCK_PIN);
SPI.setSCLK(SD_SCK_PIN);
#endif
SPI.begin(); SPI.begin();
} }

View File

@@ -0,0 +1,82 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef STM32F1
/**
* PersistentStore for Arduino-style EEPROM interface
* with simple implementations supplied by Marlin.
*/
#include "../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
//
// PersistentStore
//
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for IIC_BL24CXX_EEPROM."
#endif
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t v = *value;
uint8_t * const p = (uint8_t * const)pos;
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
}
}
crc16(crc, &v, 1);
pos++;
value++;
}
return false;
}
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
uint8_t * const p = (uint8_t * const)pos;
uint8_t c = eeprom_read_byte(p);
if (writing) *value = c;
crc16(crc, &c, 1);
pos++;
value++;
} while (--size);
return false;
}
#endif // IIC_BL24CXX_EEPROM
#endif // STM32F1

View File

@@ -28,6 +28,10 @@
#include "../shared/eeprom_api.h" #include "../shared/eeprom_api.h"
// Better: "utility/stm32_eeprom.h", but only after updating stm32duino to 2.0.0
// Use EEPROM.h for compatibility, for now.
#include <EEPROM.h>
/** /**
* The STM32 HAL supports chips that deal with "pages" and some with "sectors" and some that * The STM32 HAL supports chips that deal with "pages" and some with "sectors" and some that
* even have multiple "banks" of flash. * even have multiple "banks" of flash.

View File

@@ -0,0 +1,54 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Platform-independent Arduino functions for I2C EEPROM.
* Enable USE_SHARED_EEPROM if not supplied by the framework.
*/
#ifdef STM32F1
#include "../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../../libs/BL24CXX.h"
#include "../shared/eeprom_if.h"
void eeprom_init() { BL24CXX::init(); }
// ------------------------
// Public functions
// ------------------------
void eeprom_write_byte(uint8_t *pos, uint8_t value) {
const unsigned eeprom_address = (unsigned)pos;
return BL24CXX::writeOneByte(eeprom_address, value);
}
uint8_t eeprom_read_byte(uint8_t *pos) {
const unsigned eeprom_address = (unsigned)pos;
return BL24CXX::readOneByte(eeprom_address);
}
#endif // IIC_BL24CXX_EEPROM
#endif // STM32F1

View File

@@ -46,4 +46,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN)); TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
} }

View File

@@ -21,7 +21,7 @@
*/ */
#pragma once #pragma once
#if defined(USBD_USE_CDC_MSC) && DISABLED(NO_SD_HOST_DRIVE) #if BOTH(SDSUPPORT, USBD_USE_CDC_MSC) && DISABLED(NO_SD_HOST_DRIVE)
#define HAS_SD_HOST_DRIVE 1 #define HAS_SD_HOST_DRIVE 1
#endif #endif
@@ -30,3 +30,6 @@
#undef F_CPU #undef F_CPU
#define F_CPU BOARD_F_CPU #define F_CPU BOARD_F_CPU
#endif #endif
// The Sensitive Pins array is not optimizable
#define RUNTIME_ONLY_ANALOG_TO_DIGITAL

View File

@@ -33,9 +33,9 @@ public:
DiskIODriver* diskIODriver() { DiskIODriver* diskIODriver() {
#if ENABLED(MULTI_VOLUME) #if ENABLED(MULTI_VOLUME)
#if SHARED_VOLUME_IS(SD_ONBOARD) #if SHARED_VOLUME_IS(SD_ONBOARD)
return &card.media_sd_spi; return &card.media_driver_sdcard;
#elif SHARED_VOLUME_IS(USB_FLASH_DRIVE) #elif SHARED_VOLUME_IS(USB_FLASH_DRIVE)
return &card.media_usbFlashDrive; return &card.media_driver_usbFlash;
#endif #endif
#else #else
return card.diskIODriver(); return card.diskIODriver();

View File

@@ -125,12 +125,20 @@ void TFT_SPI::DataTransferBegin(uint16_t DataSize) {
WRITE(TFT_CS_PIN, LOW); WRITE(TFT_CS_PIN, LOW);
} }
#ifdef TFT_DEFAULT_DRIVER
#include "../../../lcd/tft_io/tft_ids.h"
#endif
uint32_t TFT_SPI::GetID() { uint32_t TFT_SPI::GetID() {
uint32_t id; uint32_t id;
id = ReadID(LCD_READ_ID); id = ReadID(LCD_READ_ID);
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF) {
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = ReadID(LCD_READ_ID4); id = ReadID(LCD_READ_ID4);
#ifdef TFT_DEFAULT_DRIVER
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = TFT_DEFAULT_DRIVER;
#endif
}
return id; return id;
} }

View File

@@ -56,7 +56,7 @@ enum XPTCoordinate : uint8_t {
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE, XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
}; };
#if !defined(XPT2046_Z1_THRESHOLD) #ifndef XPT2046_Z1_THRESHOLD
#define XPT2046_Z1_THRESHOLD 10 #define XPT2046_Z1_THRESHOLD 10
#endif #endif

View File

@@ -167,6 +167,15 @@ constexpr bool IsSerialClassAllowed(const HardwareSerial&) { return false; }
#if AXIS_HAS_HW_SERIAL(Z4) #if AXIS_HAS_HW_SERIAL(Z4)
CHECK_AXIS_SERIAL(Z4); CHECK_AXIS_SERIAL(Z4);
#endif #endif
#if AXIS_HAS_HW_SERIAL(I)
CHECK_AXIS_SERIAL(I);
#endif
#if AXIS_HAS_HW_SERIAL(J)
CHECK_AXIS_SERIAL(J);
#endif
#if AXIS_HAS_HW_SERIAL(K)
CHECK_AXIS_SERIAL(K);
#endif
#if AXIS_HAS_HW_SERIAL(E0) #if AXIS_HAS_HW_SERIAL(E0)
CHECK_AXIS_SERIAL(E0); CHECK_AXIS_SERIAL(E0);
#endif #endif

View File

@@ -11,6 +11,7 @@ if __name__ == "__main__":
"-fsigned-char", "-fsigned-char",
"-fno-move-loop-invariants", "-fno-move-loop-invariants",
"-fno-strict-aliasing", "-fno-strict-aliasing",
"-fsingle-precision-constant",
"--specs=nano.specs", "--specs=nano.specs",
"--specs=nosys.specs", "--specs=nosys.specs",

View File

@@ -71,4 +71,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN)); TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
} }

View File

@@ -38,8 +38,8 @@
#define SPI_CLOCK_MAX SPI_BAUD_PCLK_DIV_2 #define SPI_CLOCK_MAX SPI_BAUD_PCLK_DIV_2
#endif #endif
#define CS_LOW() WRITE(ONBOARD_SD_CS_PIN, LOW) /* Set OnboardSPI cs low */ #define CS_LOW() WRITE(ONBOARD_SD_CS_PIN, LOW) // Set OnboardSPI cs low
#define CS_HIGH() WRITE(ONBOARD_SD_CS_PIN, HIGH) /* Set OnboardSPI cs high */ #define CS_HIGH() WRITE(ONBOARD_SD_CS_PIN, HIGH) // Set OnboardSPI cs high
#define FCLK_FAST() ONBOARD_SD_SPI.setClockDivider(SPI_CLOCK_MAX) #define FCLK_FAST() ONBOARD_SD_SPI.setClockDivider(SPI_CLOCK_MAX)
#define FCLK_SLOW() ONBOARD_SD_SPI.setClockDivider(SPI_BAUD_PCLK_DIV_256) #define FCLK_SLOW() ONBOARD_SD_SPI.setClockDivider(SPI_BAUD_PCLK_DIV_256)
@@ -49,32 +49,32 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* MMC/SD command */ /* MMC/SD command */
#define CMD0 (0) /* GO_IDLE_STATE */ #define CMD0 (0) // GO_IDLE_STATE
#define CMD1 (1) /* SEND_OP_COND (MMC) */ #define CMD1 (1) // SEND_OP_COND (MMC)
#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */ #define ACMD41 (0x80+41) // SEND_OP_COND (SDC)
#define CMD8 (8) /* SEND_IF_COND */ #define CMD8 (8) // SEND_IF_COND
#define CMD9 (9) /* SEND_CSD */ #define CMD9 (9) // SEND_CSD
#define CMD10 (10) /* SEND_CID */ #define CMD10 (10) // SEND_CID
#define CMD12 (12) /* STOP_TRANSMISSION */ #define CMD12 (12) // STOP_TRANSMISSION
#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */ #define ACMD13 (0x80+13) // SD_STATUS (SDC)
#define CMD16 (16) /* SET_BLOCKLEN */ #define CMD16 (16) // SET_BLOCKLEN
#define CMD17 (17) /* READ_SINGLE_BLOCK */ #define CMD17 (17) // READ_SINGLE_BLOCK
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ #define CMD18 (18) // READ_MULTIPLE_BLOCK
#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */ #define CMD23 (23) // SET_BLOCK_COUNT (MMC)
#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */ #define ACMD23 (0x80+23) // SET_WR_BLK_ERASE_COUNT (SDC)
#define CMD24 (24) /* WRITE_BLOCK */ #define CMD24 (24) // WRITE_BLOCK
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */ #define CMD25 (25) // WRITE_MULTIPLE_BLOCK
#define CMD32 (32) /* ERASE_ER_BLK_START */ #define CMD32 (32) // ERASE_ER_BLK_START
#define CMD33 (33) /* ERASE_ER_BLK_END */ #define CMD33 (33) // ERASE_ER_BLK_END
#define CMD38 (38) /* ERASE */ #define CMD38 (38) // ERASE
#define CMD48 (48) /* READ_EXTR_SINGLE */ #define CMD48 (48) // READ_EXTR_SINGLE
#define CMD49 (49) /* WRITE_EXTR_SINGLE */ #define CMD49 (49) // WRITE_EXTR_SINGLE
#define CMD55 (55) /* APP_CMD */ #define CMD55 (55) // APP_CMD
#define CMD58 (58) /* READ_OCR */ #define CMD58 (58) // READ_OCR
static volatile DSTATUS Stat = STA_NOINIT; /* Physical drive status */ static volatile DSTATUS Stat = STA_NOINIT; // Physical drive status
static volatile UINT timeout; static volatile UINT timeout;
static BYTE CardType; /* Card type flags */ static BYTE CardType; // Card type flags
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Send/Receive data to the MMC (Platform dependent) */ /* Send/Receive data to the MMC (Platform dependent) */
@@ -82,7 +82,7 @@ static BYTE CardType; /* Card type flags */
/* Exchange a byte */ /* Exchange a byte */
static BYTE xchg_spi ( static BYTE xchg_spi (
BYTE dat /* Data to send */ BYTE dat // Data to send
) { ) {
BYTE returnByte = ONBOARD_SD_SPI.transfer(dat); BYTE returnByte = ONBOARD_SD_SPI.transfer(dat);
return returnByte; return returnByte;
@@ -90,18 +90,18 @@ static BYTE xchg_spi (
/* Receive multiple byte */ /* Receive multiple byte */
static void rcvr_spi_multi ( static void rcvr_spi_multi (
BYTE *buff, /* Pointer to data buffer */ BYTE *buff, // Pointer to data buffer
UINT btr /* Number of bytes to receive (16, 64 or 512) */ UINT btr // Number of bytes to receive (16, 64 or 512)
) { ) {
ONBOARD_SD_SPI.dmaTransfer(0, const_cast<uint8_t*>(buff), btr); ONBOARD_SD_SPI.dmaTransfer(0, const_cast<uint8_t*>(buff), btr);
} }
#if _DISKIO_WRITE #if _DISKIO_WRITE
/* Send multiple bytes */ // Send multiple bytes
static void xmit_spi_multi ( static void xmit_spi_multi (
const BYTE *buff, /* Pointer to the data */ const BYTE *buff, // Pointer to the data
UINT btx /* Number of bytes to send (multiple of 16) */ UINT btx // Number of bytes to send (multiple of 16)
) { ) {
ONBOARD_SD_SPI.dmaSend(const_cast<uint8_t*>(buff), btx); ONBOARD_SD_SPI.dmaSend(const_cast<uint8_t*>(buff), btx);
} }
@@ -112,16 +112,15 @@ static void rcvr_spi_multi (
/* Wait for card ready */ /* Wait for card ready */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static int wait_ready ( /* 1:Ready, 0:Timeout */ static int wait_ready ( // 1:Ready, 0:Timeout
UINT wt /* Timeout [ms] */ UINT wt // Timeout [ms]
) { ) {
BYTE d; BYTE d;
timeout = millis() + wt; timeout = millis() + wt;
do { do {
d = xchg_spi(0xFF); d = xchg_spi(0xFF);
/* This loop takes a while. Insert rot_rdq() here for multitask environment. */ // This loop takes a while. Insert rot_rdq() here for multitask environment.
} while (d != 0xFF && (timeout > millis())); /* Wait for card goes ready or timeout */ } while (d != 0xFF && (timeout > millis())); // Wait for card goes ready or timeout
return (d == 0xFF) ? 1 : 0; return (d == 0xFF) ? 1 : 0;
} }
@@ -131,21 +130,21 @@ static int wait_ready ( /* 1:Ready, 0:Timeout */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static void deselect() { static void deselect() {
CS_HIGH(); /* CS = H */ CS_HIGH(); // CS = H
xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */ xchg_spi(0xFF); // Dummy clock (force DO hi-z for multiple slave SPI)
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Select card and wait for ready */ /* Select card and wait for ready */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static int select() { /* 1:OK, 0:Timeout */ static int select() { // 1:OK, 0:Timeout
CS_LOW(); /* CS = L */ CS_LOW(); // CS = L
xchg_spi(0xFF); /* Dummy clock (force DO enabled) */ xchg_spi(0xFF); // Dummy clock (force DO enabled)
if (wait_ready(500)) return 1; /* Leading busy check: Wait for card ready */ if (wait_ready(500)) return 1; // Leading busy check: Wait for card ready
deselect(); /* Timeout */ deselect(); // Timeout
return 0; return 0;
} }
@@ -153,16 +152,18 @@ static int select() { /* 1:OK, 0:Timeout */
/* Control SPI module (Platform dependent) */ /* Control SPI module (Platform dependent) */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static void power_on() { /* Enable SSP module and attach it to I/O pads */ // Enable SSP module and attach it to I/O pads
static void sd_power_on() {
ONBOARD_SD_SPI.setModule(ONBOARD_SPI_DEVICE); ONBOARD_SD_SPI.setModule(ONBOARD_SPI_DEVICE);
ONBOARD_SD_SPI.begin(); ONBOARD_SD_SPI.begin();
ONBOARD_SD_SPI.setBitOrder(MSBFIRST); ONBOARD_SD_SPI.setBitOrder(MSBFIRST);
ONBOARD_SD_SPI.setDataMode(SPI_MODE0); ONBOARD_SD_SPI.setDataMode(SPI_MODE0);
OUT_WRITE(ONBOARD_SD_CS_PIN, HIGH); /* Set CS# high */ OUT_WRITE(ONBOARD_SD_CS_PIN, HIGH); // Set CS# high
} }
static void power_off() { /* Disable SPI function */ // Disable SPI function
select(); /* Wait for card ready */ static void sd_power_off() {
select(); // Wait for card ready
deselect(); deselect();
} }
@@ -170,23 +171,23 @@ static void power_off() { /* Disable SPI function */
/* Receive a data packet from the MMC */ /* Receive a data packet from the MMC */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static int rcvr_datablock ( /* 1:OK, 0:Error */ static int rcvr_datablock ( // 1:OK, 0:Error
BYTE *buff, /* Data buffer */ BYTE *buff, // Data buffer
UINT btr /* Data block length (byte) */ UINT btr // Data block length (byte)
) { ) {
BYTE token; BYTE token;
timeout = millis() + 200; timeout = millis() + 200;
do { /* Wait for DataStart token in timeout of 200ms */ do { // Wait for DataStart token in timeout of 200ms
token = xchg_spi(0xFF); token = xchg_spi(0xFF);
/* This loop will take a while. Insert rot_rdq() here for multitask environment. */ // This loop will take a while. Insert rot_rdq() here for multitask environment.
} while ((token == 0xFF) && (timeout > millis())); } while ((token == 0xFF) && (timeout > millis()));
if (token != 0xFE) return 0; /* Function fails if invalid DataStart token or timeout */ if (token != 0xFE) return 0; // Function fails if invalid DataStart token or timeout
rcvr_spi_multi(buff, btr); /* Store trailing data to the buffer */ rcvr_spi_multi(buff, btr); // Store trailing data to the buffer
xchg_spi(0xFF); xchg_spi(0xFF); /* Discard CRC */ xchg_spi(0xFF); xchg_spi(0xFF); // Discard CRC
return 1; /* Function succeeded */ return 1; // Function succeeded
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@@ -195,25 +196,25 @@ static int rcvr_datablock ( /* 1:OK, 0:Error */
#if _DISKIO_WRITE #if _DISKIO_WRITE
static int xmit_datablock ( /* 1:OK, 0:Failed */ static int xmit_datablock( // 1:OK, 0:Failed
const BYTE *buff, /* Ponter to 512 byte data to be sent */ const BYTE *buff, // Pointer to 512 byte data to be sent
BYTE token /* Token */ BYTE token // Token
) { ) {
BYTE resp; BYTE resp;
if (!wait_ready(500)) return 0; /* Leading busy check: Wait for card ready to accept data block */ if (!wait_ready(500)) return 0; // Leading busy check: Wait for card ready to accept data block
xchg_spi(token); /* Send token */ xchg_spi(token); // Send token
if (token == 0xFD) return 1; /* Do not send data if token is StopTran */ if (token == 0xFD) return 1; // Do not send data if token is StopTran
xmit_spi_multi(buff, 512); /* Data */ xmit_spi_multi(buff, 512); // Data
xchg_spi(0xFF); xchg_spi(0xFF); /* Dummy CRC */ xchg_spi(0xFF); xchg_spi(0xFF); // Dummy CRC
resp = xchg_spi(0xFF); /* Receive data resp */ resp = xchg_spi(0xFF); // Receive data resp
return (resp & 0x1F) == 0x05 ? 1 : 0; /* Data was accepted or not */ return (resp & 0x1F) == 0x05 ? 1 : 0; // Data was accepted or not
/* Busy check is done at next transmission */ // Busy check is done at next transmission
} }
#endif // _DISKIO_WRITE #endif // _DISKIO_WRITE
@@ -222,43 +223,43 @@ static int rcvr_datablock ( /* 1:OK, 0:Error */
/* Send a command packet to the MMC */ /* Send a command packet to the MMC */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static BYTE send_cmd ( /* Return value: R1 resp (bit7==1:Failed to send) */ static BYTE send_cmd( // Return value: R1 resp (bit7==1:Failed to send)
BYTE cmd, /* Command index */ BYTE cmd, // Command index
DWORD arg /* Argument */ DWORD arg // Argument
) { ) {
BYTE n, res; BYTE n, res;
if (cmd & 0x80) { /* Send a CMD55 prior to ACMD<n> */ if (cmd & 0x80) { // Send a CMD55 prior to ACMD<n>
cmd &= 0x7F; cmd &= 0x7F;
res = send_cmd(CMD55, 0); res = send_cmd(CMD55, 0);
if (res > 1) return res; if (res > 1) return res;
} }
/* Select the card and wait for ready except to stop multiple block read */ // Select the card and wait for ready except to stop multiple block read
if (cmd != CMD12) { if (cmd != CMD12) {
deselect(); deselect();
if (!select()) return 0xFF; if (!select()) return 0xFF;
} }
/* Send command packet */ // Send command packet
xchg_spi(0x40 | cmd); /* Start + command index */ xchg_spi(0x40 | cmd); // Start + command index
xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */ xchg_spi((BYTE)(arg >> 24)); // Argument[31..24]
xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */ xchg_spi((BYTE)(arg >> 16)); // Argument[23..16]
xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */ xchg_spi((BYTE)(arg >> 8)); // Argument[15..8]
xchg_spi((BYTE)arg); /* Argument[7..0] */ xchg_spi((BYTE)arg); // Argument[7..0]
n = 0x01; /* Dummy CRC + Stop */ n = 0x01; // Dummy CRC + Stop
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */ if (cmd == CMD0) n = 0x95; // Valid CRC for CMD0(0)
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */ if (cmd == CMD8) n = 0x87; // Valid CRC for CMD8(0x1AA)
xchg_spi(n); xchg_spi(n);
/* Receive command resp */ // Receive command response
if (cmd == CMD12) xchg_spi(0xFF); /* Diacard following one byte when CMD12 */ if (cmd == CMD12) xchg_spi(0xFF); // Discard the following byte when CMD12
n = 10; /* Wait for response (10 bytes max) */ n = 10; // Wait for response (10 bytes max)
do do
res = xchg_spi(0xFF); res = xchg_spi(0xFF);
while ((res & 0x80) && --n); while ((res & 0x80) && --n);
return res; /* Return received response */ return res; // Return received response
} }
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
@@ -270,49 +271,52 @@ static BYTE send_cmd ( /* Return value: R1 resp (bit7==1:Failed to send) */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
DSTATUS disk_initialize ( DSTATUS disk_initialize (
BYTE drv /* Physical drive number (0) */ BYTE drv // Physical drive number (0)
) { ) {
BYTE n, cmd, ty, ocr[4]; BYTE n, cmd, ty, ocr[4];
if (drv) return STA_NOINIT; /* Supports only drive 0 */ if (drv) return STA_NOINIT; // Supports only drive 0
power_on(); /* Initialize SPI */ sd_power_on(); // Initialize SPI
if (Stat & STA_NODISK) return Stat; /* Is a card existing in the soket? */ if (Stat & STA_NODISK) return Stat; // Is a card existing in the soket?
FCLK_SLOW(); FCLK_SLOW();
for (n = 10; n; n--) xchg_spi(0xFF); /* Send 80 dummy clocks */ for (n = 10; n; n--) xchg_spi(0xFF); // Send 80 dummy clocks
ty = 0; ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Put the card SPI state */ if (send_cmd(CMD0, 0) == 1) { // Put the card SPI state
timeout = millis() + 1000; /* Initialization timeout = 1 sec */ timeout = millis() + 1000; // Initialization timeout = 1 sec
if (send_cmd(CMD8, 0x1AA) == 1) { /* Is the catd SDv2? */ if (send_cmd(CMD8, 0x1AA) == 1) { // Is the catd SDv2?
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get 32 bit return value of R7 resp */ for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); // Get 32 bit return value of R7 resp
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* Does the card support 2.7-3.6V? */ if (ocr[2] == 0x01 && ocr[3] == 0xAA) { // Does the card support 2.7-3.6V?
while ((timeout > millis()) && send_cmd(ACMD41, 1UL << 30)) ; /* Wait for end of initialization with ACMD41(HCS) */ while ((timeout > millis()) && send_cmd(ACMD41, 1UL << 30)); // Wait for end of initialization with ACMD41(HCS)
if ((timeout > millis()) && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ if ((timeout > millis()) && send_cmd(CMD58, 0) == 0) { // Check CCS bit in the OCR
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* Check if the card is SDv2 */ ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; // Check if the card is SDv2
} }
} }
} else { /* Not an SDv2 card */ }
if (send_cmd(ACMD41, 0) <= 1) { /* SDv1 or MMCv3? */ else { // Not an SDv2 card
ty = CT_SD1; cmd = ACMD41; /* SDv1 (ACMD41(0)) */ if (send_cmd(ACMD41, 0) <= 1) { // SDv1 or MMCv3?
} else { ty = CT_SD1; cmd = ACMD41; // SDv1 (ACMD41(0))
ty = CT_MMC; cmd = CMD1; /* MMCv3 (CMD1(0)) */
} }
while ((timeout > millis()) && send_cmd(cmd, 0)) ; /* Wait for the card leaves idle state */ else {
if (!(timeout > millis()) || send_cmd(CMD16, 512) != 0) /* Set block length: 512 */ ty = CT_MMC; cmd = CMD1; // MMCv3 (CMD1(0))
}
while ((timeout > millis()) && send_cmd(cmd, 0)); // Wait for the card leaves idle state
if (!(timeout > millis()) || send_cmd(CMD16, 512) != 0) // Set block length: 512
ty = 0; ty = 0;
} }
} }
CardType = ty; /* Card type */ CardType = ty; // Card type
deselect(); deselect();
if (ty) { /* OK */ if (ty) { // OK
FCLK_FAST(); /* Set fast clock */ FCLK_FAST(); // Set fast clock
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */ Stat &= ~STA_NOINIT; // Clear STA_NOINIT flag
} else { /* Failed */ }
power_off(); else { // Failed
sd_power_off();
Stat = STA_NOINIT; Stat = STA_NOINIT;
} }
@@ -324,10 +328,10 @@ DSTATUS disk_initialize (
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
DSTATUS disk_status ( DSTATUS disk_status (
BYTE drv /* Physical drive number (0) */ BYTE drv // Physical drive number (0)
) { ) {
if (drv) return STA_NOINIT; /* Supports only drive 0 */ if (drv) return STA_NOINIT; // Supports only drive 0
return Stat; /* Return disk status */ return Stat; // Return disk status
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@@ -335,28 +339,28 @@ DSTATUS disk_status (
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
DRESULT disk_read ( DRESULT disk_read (
BYTE drv, /* Physical drive number (0) */ BYTE drv, // Physical drive number (0)
BYTE *buff, /* Pointer to the data buffer to store read data */ BYTE *buff, // Pointer to the data buffer to store read data
DWORD sector, /* Start sector number (LBA) */ DWORD sector, // Start sector number (LBA)
UINT count /* Number of sectors to read (1..128) */ UINT count // Number of sectors to read (1..128)
) { ) {
BYTE cmd; BYTE cmd;
if (drv || !count) return RES_PARERR; /* Check parameter */ if (drv || !count) return RES_PARERR; // Check parameter
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */ if (Stat & STA_NOINIT) return RES_NOTRDY; // Check if drive is ready
if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ot BA conversion (byte addressing cards) */ if (!(CardType & CT_BLOCK)) sector *= 512; // LBA ot BA conversion (byte addressing cards)
FCLK_FAST(); FCLK_FAST();
cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */ cmd = count > 1 ? CMD18 : CMD17; // READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK
if (send_cmd(cmd, sector) == 0) { if (send_cmd(cmd, sector) == 0) {
do { do {
if (!rcvr_datablock(buff, 512)) break; if (!rcvr_datablock(buff, 512)) break;
buff += 512; buff += 512;
} while (--count); } while (--count);
if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */ if (cmd == CMD18) send_cmd(CMD12, 0); // STOP_TRANSMISSION
} }
deselect(); deselect();
return count ? RES_ERROR : RES_OK; /* Return result */ return count ? RES_ERROR : RES_OK; // Return result
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@@ -366,36 +370,36 @@ DRESULT disk_read (
#if _DISKIO_WRITE #if _DISKIO_WRITE
DRESULT disk_write( DRESULT disk_write(
BYTE drv, /* Physical drive number (0) */ BYTE drv, // Physical drive number (0)
const BYTE *buff, /* Ponter to the data to write */ const BYTE *buff, // Pointer to the data to write
DWORD sector, /* Start sector number (LBA) */ DWORD sector, // Start sector number (LBA)
UINT count /* Number of sectors to write (1..128) */ UINT count // Number of sectors to write (1..128)
) { ) {
if (drv || !count) return RES_PARERR; /* Check parameter */ if (drv || !count) return RES_PARERR; // Check parameter
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check drive status */ if (Stat & STA_NOINIT) return RES_NOTRDY; // Check drive status
if (Stat & STA_PROTECT) return RES_WRPRT; /* Check write protect */ if (Stat & STA_PROTECT) return RES_WRPRT; // Check write protect
FCLK_FAST(); FCLK_FAST();
if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ==> BA conversion (byte addressing cards) */ if (!(CardType & CT_BLOCK)) sector *= 512; // LBA ==> BA conversion (byte addressing cards)
if (count == 1) { /* Single sector write */ if (count == 1) { // Single sector write
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */ if ((send_cmd(CMD24, sector) == 0) // WRITE_BLOCK
&& xmit_datablock(buff, 0xFE)) { && xmit_datablock(buff, 0xFE)) {
count = 0; count = 0;
} }
} }
else { /* Multiple sector write */ else { // Multiple sector write
if (CardType & CT_SDC) send_cmd(ACMD23, count); /* Predefine number of sectors */ if (CardType & CT_SDC) send_cmd(ACMD23, count); // Predefine number of sectors
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */ if (send_cmd(CMD25, sector) == 0) { // WRITE_MULTIPLE_BLOCK
do { do {
if (!xmit_datablock(buff, 0xFC)) break; if (!xmit_datablock(buff, 0xFC)) break;
buff += 512; buff += 512;
} while (--count); } while (--count);
if (!xmit_datablock(0, 0xFD)) count = 1; /* STOP_TRAN token */ if (!xmit_datablock(0, 0xFD)) count = 1; // STOP_TRAN token
} }
} }
deselect(); deselect();
return count ? RES_ERROR : RES_OK; /* Return result */ return count ? RES_ERROR : RES_OK; // Return result
} }
#endif // _DISKIO_WRITE #endif // _DISKIO_WRITE
@@ -407,9 +411,9 @@ DRESULT disk_read (
#if _DISKIO_IOCTL #if _DISKIO_IOCTL
DRESULT disk_ioctl ( DRESULT disk_ioctl (
BYTE drv, /* Physical drive number (0) */ BYTE drv, // Physical drive number (0)
BYTE cmd, /* Control command code */ BYTE cmd, // Control command code
void *buff /* Pointer to the conrtol data */ void *buff // Pointer to the conrtol data
) { ) {
DRESULT res; DRESULT res;
BYTE n, csd[16], *ptr = (BYTE *)buff; BYTE n, csd[16], *ptr = (BYTE *)buff;
@@ -420,22 +424,23 @@ DRESULT disk_read (
UINT dc; UINT dc;
#endif #endif
if (drv) return RES_PARERR; /* Check parameter */ if (drv) return RES_PARERR; // Check parameter
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */ if (Stat & STA_NOINIT) return RES_NOTRDY; // Check if drive is ready
res = RES_ERROR; res = RES_ERROR;
FCLK_FAST(); FCLK_FAST();
switch (cmd) { switch (cmd) {
case CTRL_SYNC: /* Wait for end of internal write process of the drive */ case CTRL_SYNC: // Wait for end of internal write process of the drive
if (select()) res = RES_OK; if (select()) res = RES_OK;
break; break;
case GET_SECTOR_COUNT: /* Get drive capacity in unit of sector (DWORD) */ case GET_SECTOR_COUNT: // Get drive capacity in unit of sector (DWORD)
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */ if ((csd[0] >> 6) == 1) { // SDC ver 2.00
csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1; csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
*(DWORD*)buff = csize << 10; *(DWORD*)buff = csize << 10;
} else { /* SDC ver 1.XX or MMC ver 3 */ }
else { // SDC ver 1.XX or MMC ver 3
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2; n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1; csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(DWORD*)buff = csize << (n - 9); *(DWORD*)buff = csize << (n - 9);
@@ -444,21 +449,23 @@ DRESULT disk_read (
} }
break; break;
case GET_BLOCK_SIZE: /* Get erase block size in unit of sector (DWORD) */ case GET_BLOCK_SIZE: // Get erase block size in unit of sector (DWORD)
if (CardType & CT_SD2) { /* SDC ver 2.00 */ if (CardType & CT_SD2) { // SDC ver 2.00
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */ if (send_cmd(ACMD13, 0) == 0) { // Read SD status
xchg_spi(0xFF); xchg_spi(0xFF);
if (rcvr_datablock(csd, 16)) { /* Read partial block */ if (rcvr_datablock(csd, 16)) { // Read partial block
for (n = 64 - 16; n; n--) xchg_spi(0xFF); /* Purge trailing data */ for (n = 64 - 16; n; n--) xchg_spi(0xFF); // Purge trailing data
*(DWORD*)buff = 16UL << (csd[10] >> 4); *(DWORD*)buff = 16UL << (csd[10] >> 4);
res = RES_OK; res = RES_OK;
} }
} }
} else { /* SDC ver 1.XX or MMC */ }
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */ else { // SDC ver 1.XX or MMC
if (CardType & CT_SD1) { /* SDC ver 1.XX */ if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { // Read CSD
if (CardType & CT_SD1) { // SDC ver 1.XX
*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1); *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
} else { /* MMC */ }
else { // MMC
*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1); *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
} }
res = RES_OK; res = RES_OK;
@@ -466,47 +473,47 @@ DRESULT disk_read (
} }
break; break;
case CTRL_TRIM: /* Erase a block of sectors (used when _USE_TRIM in ffconf.h is 1) */ case CTRL_TRIM: // Erase a block of sectors (used when _USE_TRIM in ffconf.h is 1)
if (!(CardType & CT_SDC)) break; /* Check if the card is SDC */ if (!(CardType & CT_SDC)) break; // Check if the card is SDC
if (disk_ioctl(drv, MMC_GET_CSD, csd)) break; /* Get CSD */ if (disk_ioctl(drv, MMC_GET_CSD, csd)) break; // Get CSD
if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */ if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; // Check if sector erase can be applied to the card
dp = (DWORD *)buff; st = dp[0]; ed = dp[1]; /* Load sector block */ dp = (DWORD *)buff; st = dp[0]; ed = dp[1]; // Load sector block
if (!(CardType & CT_BLOCK)) { if (!(CardType & CT_BLOCK)) {
st *= 512; ed *= 512; st *= 512; ed *= 512;
} }
if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) { /* Erase sector block */ if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) { // Erase sector block
res = RES_OK; /* FatFs does not check result of this command */ res = RES_OK; // FatFs does not check result of this command
} }
break; break;
/* Following commands are never used by FatFs module */ // The following commands are never used by FatFs module
case MMC_GET_TYPE: /* Get MMC/SDC type (BYTE) */ case MMC_GET_TYPE: // Get MMC/SDC type (BYTE)
*ptr = CardType; *ptr = CardType;
res = RES_OK; res = RES_OK;
break; break;
case MMC_GET_CSD: /* Read CSD (16 bytes) */ case MMC_GET_CSD: // Read CSD (16 bytes)
if (send_cmd(CMD9, 0) == 0 && rcvr_datablock(ptr, 16)) { /* READ_CSD */ if (send_cmd(CMD9, 0) == 0 && rcvr_datablock(ptr, 16)) {
res = RES_OK; res = RES_OK;
} }
break; break;
case MMC_GET_CID: /* Read CID (16 bytes) */ case MMC_GET_CID: // Read CID (16 bytes)
if (send_cmd(CMD10, 0) == 0 && rcvr_datablock(ptr, 16)) { /* READ_CID */ if (send_cmd(CMD10, 0) == 0 && rcvr_datablock(ptr, 16)) {
res = RES_OK; res = RES_OK;
} }
break; break;
case MMC_GET_OCR: /* Read OCR (4 bytes) */ case MMC_GET_OCR: // Read OCR (4 bytes)
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */ if (send_cmd(CMD58, 0) == 0) {
for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF); for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF);
res = RES_OK; res = RES_OK;
} }
break; break;
case MMC_GET_SDSTAT: /* Read SD status (64 bytes) */ case MMC_GET_SDSTAT: // Read SD status (64 bytes)
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */ if (send_cmd(ACMD13, 0) == 0) {
xchg_spi(0xFF); xchg_spi(0xFF);
if (rcvr_datablock(ptr, 64)) res = RES_OK; if (rcvr_datablock(ptr, 64)) res = RES_OK;
} }

View File

@@ -90,12 +90,20 @@ void TFT_SPI::DataTransferBegin(uint16_t DataSize) {
TFT_CS_L; TFT_CS_L;
} }
#ifdef TFT_DEFAULT_DRIVER
#include "../../../lcd/tft_io/tft_ids.h"
#endif
uint32_t TFT_SPI::GetID() { uint32_t TFT_SPI::GetID() {
uint32_t id; uint32_t id;
id = ReadID(LCD_READ_ID); id = ReadID(LCD_READ_ID);
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF) {
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = ReadID(LCD_READ_ID4); id = ReadID(LCD_READ_ID4);
#ifdef TFT_DEFAULT_DRIVER
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = TFT_DEFAULT_DRIVER;
#endif
}
return id; return id;
} }

View File

@@ -54,7 +54,7 @@ enum XPTCoordinate : uint8_t {
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE, XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
}; };
#if !defined(XPT2046_Z1_THRESHOLD) #ifndef XPT2046_Z1_THRESHOLD
#define XPT2046_Z1_THRESHOLD 10 #define XPT2046_Z1_THRESHOLD 10
#endif #endif

View File

@@ -80,7 +80,7 @@ typedef uint16_t hal_timer_t;
//#define TEMP_TIMER_NUM 4 // 2->4, Timer 2 for Stepper Current PWM //#define TEMP_TIMER_NUM 4 // 2->4, Timer 2 for Stepper Current PWM
#endif #endif
#if MB(BTT_SKR_MINI_E3_V1_0, BTT_SKR_E3_DIP, BTT_SKR_MINI_E3_V1_2, MKS_ROBIN_LITE) #if MB(BTT_SKR_MINI_E3_V1_0, BTT_SKR_E3_DIP, BTT_SKR_MINI_E3_V1_2, MKS_ROBIN_LITE, MKS_ROBIN_E3D, MKS_ROBIN_E3)
// SKR Mini E3 boards use PA8 as FAN_PIN, so TIMER 1 is used for Fan PWM. // SKR Mini E3 boards use PA8 as FAN_PIN, so TIMER 1 is used for Fan PWM.
#ifdef STM32_HIGH_DENSITY #ifdef STM32_HIGH_DENSITY
#define SERVO0_TIMER_NUM 8 // tone.cpp uses Timer 4 #define SERVO0_TIMER_NUM 8 // tone.cpp uses Timer 4

View File

@@ -64,4 +64,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN)); TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
} }

View File

@@ -63,4 +63,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN)); TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
} }

View File

@@ -63,4 +63,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN)); TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
} }

View File

@@ -61,11 +61,24 @@ static constexpr uint8_t eeprom_device_address = I2C_ADDRESS(EEPROM_DEVICE_ADDRE
// Public functions // Public functions
// ------------------------ // ------------------------
#define SMALL_EEPROM (MARLIN_EEPROM_SIZE <= 2048)
// Combine Address high bits into the device address on <=16Kbit (2K) and >512Kbit (64K) EEPROMs.
// Note: MARLIN_EEPROM_SIZE is specified in bytes, whereas EEPROM model numbers refer to bits.
// e.g., The "16" in BL24C16 indicates a 16Kbit (2KB) size.
static uint8_t _eeprom_calc_device_address(uint8_t * const pos) {
const unsigned eeprom_address = (unsigned)pos;
return (SMALL_EEPROM || MARLIN_EEPROM_SIZE > 65536)
? uint8_t(eeprom_device_address | ((eeprom_address >> (SMALL_EEPROM ? 8 : 16)) & 0x07))
: eeprom_device_address;
}
static void _eeprom_begin(uint8_t * const pos) { static void _eeprom_begin(uint8_t * const pos) {
const unsigned eeprom_address = (unsigned)pos; const unsigned eeprom_address = (unsigned)pos;
Wire.beginTransmission(eeprom_device_address); Wire.beginTransmission(_eeprom_calc_device_address(pos));
Wire.write(int(eeprom_address >> 8)); // Address High if (!SMALL_EEPROM)
Wire.write(int(eeprom_address & 0xFF)); // Address Low Wire.write(uint8_t((eeprom_address >> 8) & 0xFF)); // Address High, if needed
Wire.write(uint8_t(eeprom_address & 0xFF)); // Address Low
} }
void eeprom_write_byte(uint8_t *pos, uint8_t value) { void eeprom_write_byte(uint8_t *pos, uint8_t value) {
@@ -81,7 +94,7 @@ void eeprom_write_byte(uint8_t *pos, uint8_t value) {
uint8_t eeprom_read_byte(uint8_t *pos) { uint8_t eeprom_read_byte(uint8_t *pos) {
_eeprom_begin(pos); _eeprom_begin(pos);
Wire.endTransmission(); Wire.endTransmission();
Wire.requestFrom(eeprom_device_address, (byte)1); Wire.requestFrom(_eeprom_calc_device_address(pos), (byte)1);
return Wire.available() ? Wire.read() : 0xFF; return Wire.available() ? Wire.read() : 0xFF;
} }

View File

@@ -282,12 +282,22 @@ bool wait_for_heatup = true;
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing" #pragma GCC diagnostic ignored "-Wnarrowing"
#ifndef RUNTIME_ONLY_ANALOG_TO_DIGITAL
template <pin_t ...D>
constexpr pin_t OnlyPins<_SP_END, D...>::table[sizeof...(D)];
#endif
bool pin_is_protected(const pin_t pin) { bool pin_is_protected(const pin_t pin) {
static const pin_t sensitive_pins[] PROGMEM = SENSITIVE_PINS; #ifdef RUNTIME_ONLY_ANALOG_TO_DIGITAL
LOOP_L_N(i, COUNT(sensitive_pins)) { static const pin_t sensitive_pins[] PROGMEM = { SENSITIVE_PINS };
pin_t sensitive_pin; const size_t pincount = COUNT(sensitive_pins);
memcpy_P(&sensitive_pin, &sensitive_pins[i], sizeof(pin_t)); #else
if (pin == sensitive_pin) return true; static constexpr size_t pincount = OnlyPins<SENSITIVE_PINS>::size;
static const pin_t (&sensitive_pins)[pincount] PROGMEM = OnlyPins<SENSITIVE_PINS>::table;
#endif
LOOP_L_N(i, pincount) {
const pin_t * const pptr = &sensitive_pins[i];
if (pin == (sizeof(pin_t) == 2 ? (pin_t)pgm_read_word(pptr) : (pin_t)pgm_read_byte(pptr))) return true;
} }
return false; return false;
} }
@@ -304,6 +314,9 @@ void enable_all_steppers() {
ENABLE_AXIS_X(); ENABLE_AXIS_X();
ENABLE_AXIS_Y(); ENABLE_AXIS_Y();
ENABLE_AXIS_Z(); ENABLE_AXIS_Z();
ENABLE_AXIS_I(); // Marlin 6-axis support by DerAndere (https://github.com/DerAndere1/Marlin/wiki)
ENABLE_AXIS_J();
ENABLE_AXIS_K();
enable_e_steppers(); enable_e_steppers();
TERN_(EXTENSIBLE_UI, ExtUI::onSteppersEnabled()); TERN_(EXTENSIBLE_UI, ExtUI::onSteppersEnabled());
@@ -317,7 +330,7 @@ void disable_e_steppers() {
void disable_e_stepper(const uint8_t e) { void disable_e_stepper(const uint8_t e) {
#define _CASE_DIS_E(N) case N: DISABLE_AXIS_E##N(); break; #define _CASE_DIS_E(N) case N: DISABLE_AXIS_E##N(); break;
switch (e) { switch (e) {
REPEAT(EXTRUDERS, _CASE_DIS_E) REPEAT(E_STEPPERS, _CASE_DIS_E)
} }
} }
@@ -325,6 +338,9 @@ void disable_all_steppers() {
DISABLE_AXIS_X(); DISABLE_AXIS_X();
DISABLE_AXIS_Y(); DISABLE_AXIS_Y();
DISABLE_AXIS_Z(); DISABLE_AXIS_Z();
DISABLE_AXIS_I();
DISABLE_AXIS_J();
DISABLE_AXIS_K();
disable_e_steppers(); disable_e_steppers();
TERN_(EXTENSIBLE_UI, ExtUI::onSteppersDisabled()); TERN_(EXTENSIBLE_UI, ExtUI::onSteppersDisabled());
@@ -408,19 +424,18 @@ void startOrResumeJob() {
* - Check if an idle but hot extruder needs filament extruded (EXTRUDER_RUNOUT_PREVENT) * - Check if an idle but hot extruder needs filament extruded (EXTRUDER_RUNOUT_PREVENT)
* - Pulse FET_SAFETY_PIN if it exists * - Pulse FET_SAFETY_PIN if it exists
*/ */
inline void manage_inactivity(const bool ignore_stepper_queue=false) { inline void manage_inactivity(const bool no_stepper_sleep=false) {
queue.get_available_commands(); queue.get_available_commands();
const millis_t ms = millis(); const millis_t ms = millis();
// Prevent steppers timing-out in the middle of M600 // Prevent steppers timing-out
// unless PAUSE_PARK_NO_STEPPER_TIMEOUT is disabled const bool do_reset_timeout = no_stepper_sleep
const bool parked_or_ignoring = ignore_stepper_queue
|| TERN0(PAUSE_PARK_NO_STEPPER_TIMEOUT, did_pause_print); || TERN0(PAUSE_PARK_NO_STEPPER_TIMEOUT, did_pause_print);
// Reset both the M18/M84 activity timeout and the M85 max 'kill' timeout // Reset both the M18/M84 activity timeout and the M85 max 'kill' timeout
if (parked_or_ignoring) gcode.reset_stepper_timeout(ms); if (do_reset_timeout) gcode.reset_stepper_timeout(ms);
if (gcode.stepper_max_timed_out(ms)) { if (gcode.stepper_max_timed_out(ms)) {
SERIAL_ERROR_MSG(STR_KILL_INACTIVE_TIME, parser.command_ptr); SERIAL_ERROR_MSG(STR_KILL_INACTIVE_TIME, parser.command_ptr);
@@ -436,7 +451,7 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
// activity timeout and the M85 max 'kill' timeout // activity timeout and the M85 max 'kill' timeout
if (planner.has_blocks_queued()) if (planner.has_blocks_queued())
gcode.reset_stepper_timeout(ms); gcode.reset_stepper_timeout(ms);
else if (!parked_or_ignoring && gcode.stepper_inactive_timeout()) { else if (!do_reset_timeout && gcode.stepper_inactive_timeout()) {
if (!already_shutdown_steppers) { if (!already_shutdown_steppers) {
already_shutdown_steppers = true; // L6470 SPI will consume 99% of free time without this already_shutdown_steppers = true; // L6470 SPI will consume 99% of free time without this
@@ -444,6 +459,9 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
if (ENABLED(DISABLE_INACTIVE_X)) DISABLE_AXIS_X(); if (ENABLED(DISABLE_INACTIVE_X)) DISABLE_AXIS_X();
if (ENABLED(DISABLE_INACTIVE_Y)) DISABLE_AXIS_Y(); if (ENABLED(DISABLE_INACTIVE_Y)) DISABLE_AXIS_Y();
if (ENABLED(DISABLE_INACTIVE_Z)) DISABLE_AXIS_Z(); if (ENABLED(DISABLE_INACTIVE_Z)) DISABLE_AXIS_Z();
if (ENABLED(DISABLE_INACTIVE_I)) DISABLE_AXIS_I();
if (ENABLED(DISABLE_INACTIVE_J)) DISABLE_AXIS_J();
if (ENABLED(DISABLE_INACTIVE_K)) DISABLE_AXIS_K();
if (ENABLED(DISABLE_INACTIVE_E)) disable_e_steppers(); if (ENABLED(DISABLE_INACTIVE_E)) disable_e_steppers();
TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled()); TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled());
@@ -716,14 +734,14 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
* - Update the Průša MMU2 * - Update the Průša MMU2
* - Handle Joystick jogging * - Handle Joystick jogging
*/ */
void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { void idle(bool no_stepper_sleep/*=false*/) {
#if ENABLED(MARLIN_DEV_MODE) #if ENABLED(MARLIN_DEV_MODE)
static uint16_t idle_depth = 0; static uint16_t idle_depth = 0;
if (++idle_depth > 5) SERIAL_ECHOLNPAIR("idle() call depth: ", idle_depth); if (++idle_depth > 5) SERIAL_ECHOLNPAIR("idle() call depth: ", idle_depth);
#endif #endif
// Core Marlin activities // Core Marlin activities
manage_inactivity(TERN_(ADVANCED_PAUSE_FEATURE, no_stepper_sleep)); manage_inactivity(no_stepper_sleep);
// Manage Heaters (and Watchdog) // Manage Heaters (and Watchdog)
thermalManager.manage_heater(); thermalManager.manage_heater();
@@ -935,6 +953,15 @@ inline void tmc_standby_setup() {
#if PIN_EXISTS(Z4_STDBY) #if PIN_EXISTS(Z4_STDBY)
SET_INPUT_PULLDOWN(Z4_STDBY_PIN); SET_INPUT_PULLDOWN(Z4_STDBY_PIN);
#endif #endif
#if PIN_EXISTS(I_STDBY)
SET_INPUT_PULLDOWN(I_STDBY_PIN);
#endif
#if PIN_EXISTS(J_STDBY)
SET_INPUT_PULLDOWN(J_STDBY_PIN);
#endif
#if PIN_EXISTS(K_STDBY)
SET_INPUT_PULLDOWN(K_STDBY_PIN);
#endif
#if PIN_EXISTS(E0_STDBY) #if PIN_EXISTS(E0_STDBY)
SET_INPUT_PULLDOWN(E0_STDBY_PIN); SET_INPUT_PULLDOWN(E0_STDBY_PIN);
#endif #endif
@@ -1073,11 +1100,17 @@ void setup() {
while (!MYSERIAL1.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ } while (!MYSERIAL1.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#if HAS_MULTI_SERIAL && !HAS_ETHERNET #if HAS_MULTI_SERIAL && !HAS_ETHERNET
MYSERIAL2.begin(BAUDRATE); #ifndef BAUDRATE_2
#define BAUDRATE_2 BAUDRATE
#endif
MYSERIAL2.begin(BAUDRATE_2);
serial_connect_timeout = millis() + 1000UL; serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL2.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ } while (!MYSERIAL2.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#ifdef SERIAL_PORT_3 #ifdef SERIAL_PORT_3
MYSERIAL3.begin(BAUDRATE); #ifndef BAUDRATE_3
#define BAUDRATE_3 BAUDRATE
#endif
MYSERIAL3.begin(BAUDRATE_3);
serial_connect_timeout = millis() + 1000UL; serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL3.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ } while (!MYSERIAL3.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#endif #endif
@@ -1095,6 +1128,7 @@ void setup() {
#endif #endif
#if HAS_FREEZE_PIN #if HAS_FREEZE_PIN
SETUP_LOG("FREEZE_PIN");
SET_INPUT_PULLUP(FREEZE_PIN); SET_INPUT_PULLUP(FREEZE_PIN);
#endif #endif
@@ -1103,11 +1137,19 @@ void setup() {
OUT_WRITE(SUICIDE_PIN, !SUICIDE_PIN_INVERTING); OUT_WRITE(SUICIDE_PIN, !SUICIDE_PIN_INVERTING);
#endif #endif
#ifdef JTAGSWD_RESET
SETUP_LOG("JTAGSWD_RESET");
JTAGSWD_RESET();
#endif
#if EITHER(DISABLE_DEBUG, DISABLE_JTAG) #if EITHER(DISABLE_DEBUG, DISABLE_JTAG)
delay(10);
// Disable any hardware debug to free up pins for IO // Disable any hardware debug to free up pins for IO
#if ENABLED(DISABLE_DEBUG) && defined(JTAGSWD_DISABLE) #if ENABLED(DISABLE_DEBUG) && defined(JTAGSWD_DISABLE)
SETUP_LOG("JTAGSWD_DISABLE");
JTAGSWD_DISABLE(); JTAGSWD_DISABLE();
#elif defined(JTAG_DISABLE) #elif defined(JTAG_DISABLE)
SETUP_LOG("JTAG_DISABLE");
JTAG_DISABLE(); JTAG_DISABLE();
#else #else
#error "DISABLE_(DEBUG|JTAG) is not supported for the selected MCU/Board." #error "DISABLE_(DEBUG|JTAG) is not supported for the selected MCU/Board."
@@ -1126,10 +1168,10 @@ void setup() {
SETUP_RUN(HAL_init()); SETUP_RUN(HAL_init());
// Init and disable SPI thermocouples; this is still needed // Init and disable SPI thermocouples; this is still needed
#if TEMP_SENSOR_0_IS_MAX_TC #if TEMP_SENSOR_0_IS_MAX_TC || (TEMP_SENSOR_REDUNDANT_IS_MAX_TC && TEMP_SENSOR_REDUNDANT_SOURCE == 0)
OUT_WRITE(MAX6675_SS_PIN, HIGH); // Disable OUT_WRITE(MAX6675_SS_PIN, HIGH); // Disable
#endif #endif
#if TEMP_SENSOR_1_IS_MAX_TC #if TEMP_SENSOR_1_IS_MAX_TC || (TEMP_SENSOR_REDUNDANT_IS_MAX_TC && TEMP_SENSOR_REDUNDANT_SOURCE == 1)
OUT_WRITE(MAX6675_SS2_PIN, HIGH); // Disable OUT_WRITE(MAX6675_SS2_PIN, HIGH); // Disable
#endif #endif
@@ -1417,10 +1459,7 @@ void setup() {
#endif #endif
#if HAS_PRUSA_MMU1 #if HAS_PRUSA_MMU1
SETUP_LOG("Prusa MMU1"); SETUP_RUN(mmu_init());
SET_OUTPUT(E_MUX0_PIN);
SET_OUTPUT(E_MUX1_PIN);
SET_OUTPUT(E_MUX2_PIN);
#endif #endif
#if HAS_FANMUX #if HAS_FANMUX
@@ -1488,7 +1527,7 @@ void setup() {
#endif #endif
#if HAS_TRINAMIC_CONFIG && DISABLED(PSU_DEFAULT_OFF) #if HAS_TRINAMIC_CONFIG && DISABLED(PSU_DEFAULT_OFF)
SETUP_RUN(test_tmc_connection(true, true, true, true)); SETUP_RUN(test_tmc_connection());
#endif #endif
#if HAS_DRIVER_SAFE_POWER_PROTECT #if HAS_DRIVER_SAFE_POWER_PROTECT

View File

@@ -34,8 +34,8 @@
void stop(); void stop();
// Pass true to keep steppers from timing out // Pass true to keep steppers from timing out
void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep=false)); void idle(bool no_stepper_sleep=false);
inline void idle_no_sleep() { idle(TERN_(ADVANCED_PAUSE_FEATURE, true)); } inline void idle_no_sleep() { idle(true); }
#if ENABLED(G38_PROBE_TARGET) #if ENABLED(G38_PROBE_TARGET)
extern uint8_t G38_move; // Flag to tell the ISR that G38 is in progress, and the type extern uint8_t G38_move; // Flag to tell the ISR that G38 is in progress, and the type

View File

@@ -159,6 +159,7 @@
#define BOARD_PICA_REVB 1324 // PICA Shield (original version) #define BOARD_PICA_REVB 1324 // PICA Shield (original version)
#define BOARD_PICA 1325 // PICA Shield (rev C or later) #define BOARD_PICA 1325 // PICA Shield (rev C or later)
#define BOARD_INTAMSYS40 1326 // Intamsys 4.0 (Funmat HT) #define BOARD_INTAMSYS40 1326 // Intamsys 4.0 (Funmat HT)
#define BOARD_MALYAN_M180 1327 // Malyan M180 Mainboard Version 2 (no display function, direct gcode only)
// //
// ATmega1281, ATmega2561 // ATmega1281, ATmega2561
@@ -320,7 +321,7 @@
#define BOARD_BTT_SKR_MINI_V1_1 4023 // BigTreeTech SKR Mini v1.1 (STM32F103RC) #define BOARD_BTT_SKR_MINI_V1_1 4023 // BigTreeTech SKR Mini v1.1 (STM32F103RC)
#define BOARD_BTT_SKR_MINI_E3_V1_0 4024 // BigTreeTech SKR Mini E3 (STM32F103RC) #define BOARD_BTT_SKR_MINI_E3_V1_0 4024 // BigTreeTech SKR Mini E3 (STM32F103RC)
#define BOARD_BTT_SKR_MINI_E3_V1_2 4025 // BigTreeTech SKR Mini E3 V1.2 (STM32F103RC) #define BOARD_BTT_SKR_MINI_E3_V1_2 4025 // BigTreeTech SKR Mini E3 V1.2 (STM32F103RC)
#define BOARD_BTT_SKR_MINI_E3_V2_0 4026 // BigTreeTech SKR Mini E3 V2.0 (STM32F103RC) #define BOARD_BTT_SKR_MINI_E3_V2_0 4026 // BigTreeTech SKR Mini E3 V2.0 (STM32F103RC / STM32F103RE)
#define BOARD_BTT_SKR_MINI_MZ_V1_0 4027 // BigTreeTech SKR Mini MZ V1.0 (STM32F103RC) #define BOARD_BTT_SKR_MINI_MZ_V1_0 4027 // BigTreeTech SKR Mini MZ V1.0 (STM32F103RC)
#define BOARD_BTT_SKR_E3_DIP 4028 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / STM32F103RE) #define BOARD_BTT_SKR_E3_DIP 4028 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / STM32F103RE)
#define BOARD_BTT_SKR_CR6 4029 // BigTreeTech SKR CR6 v1.0 (STM32F103RE) #define BOARD_BTT_SKR_CR6 4029 // BigTreeTech SKR CR6 v1.0 (STM32F103RE)
@@ -371,20 +372,21 @@
#define BOARD_BTT_SKR_V2_0_REV_B 4212 // BigTreeTech SKR v2.0 Rev B (STM32F407VGT6) #define BOARD_BTT_SKR_V2_0_REV_B 4212 // BigTreeTech SKR v2.0 Rev B (STM32F407VGT6)
#define BOARD_BTT_GTR_V1_0 4213 // BigTreeTech GTR v1.0 (STM32F407IGT) #define BOARD_BTT_GTR_V1_0 4213 // BigTreeTech GTR v1.0 (STM32F407IGT)
#define BOARD_BTT_OCTOPUS_V1_0 4214 // BigTreeTech Octopus v1.0 (STM32F446ZET6) #define BOARD_BTT_OCTOPUS_V1_0 4214 // BigTreeTech Octopus v1.0 (STM32F446ZET6)
#define BOARD_LERDGE_K 4215 // Lerdge K (STM32F407ZG) #define BOARD_BTT_OCTOPUS_V1_1 4215 // BigTreeTech Octopus v1.1 (STM32F446ZET6)
#define BOARD_LERDGE_S 4216 // Lerdge S (STM32F407VE) #define BOARD_LERDGE_K 4216 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_X 4217 // Lerdge X (STM32F407VE) #define BOARD_LERDGE_S 4217 // Lerdge S (STM32F407VE)
#define BOARD_VAKE403D 4218 // VAkE 403D (STM32F446VET6) #define BOARD_LERDGE_X 4218 // Lerdge X (STM32F407VE)
#define BOARD_FYSETC_S6 4219 // FYSETC S6 (STM32F446VET6) #define BOARD_VAKE403D 4219 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6_V2_0 4220 // FYSETC S6 v2.0 (STM32F446VET6) #define BOARD_FYSETC_S6 4220 // FYSETC S6 (STM32F446VET6)
#define BOARD_FYSETC_SPIDER 4221 // FYSETC Spider (STM32F446VET6) #define BOARD_FYSETC_S6_V2_0 4221 // FYSETC S6 v2.0 (STM32F446VET6)
#define BOARD_FLYF407ZG 4222 // FLYF407ZG (STM32F407ZG) #define BOARD_FYSETC_SPIDER 4222 // FYSETC Spider (STM32F446VET6)
#define BOARD_MKS_ROBIN2 4223 // MKS_ROBIN2 (STM32F407ZE) #define BOARD_FLYF407ZG 4223 // FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN_PRO_V2 4224 // MKS Robin Pro V2 (STM32F407VE) #define BOARD_MKS_ROBIN2 4224 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_NANO_V3 4225 // MKS Robin Nano V3 (STM32F407VG) #define BOARD_MKS_ROBIN_PRO_V2 4225 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_ANET_ET4 4226 // ANET ET4 V1.x (STM32F407VGT6) #define BOARD_MKS_ROBIN_NANO_V3 4226 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_ANET_ET4P 4227 // ANET ET4P V1.x (STM32F407VGT6) #define BOARD_ANET_ET4 4227 // ANET ET4 V1.x (STM32F407VGT6)
#define BOARD_FYSETC_CHEETAH_V20 4228 // FYSETC Cheetah V2.0 #define BOARD_ANET_ET4P 4228 // ANET ET4P V1.x (STM32F407VGT6)
#define BOARD_FYSETC_CHEETAH_V20 4229 // FYSETC Cheetah V2.0
// //

View File

@@ -44,6 +44,6 @@ private:
SERIAL_ECHOPGM_P(the_msg); SERIAL_ECHOPGM_P(the_msg);
} }
SERIAL_CHAR(' '); SERIAL_CHAR(' ');
print_xyz(current_position); print_pos(current_position);
} }
}; };

View File

@@ -60,6 +60,9 @@
#define AXIS_DRIVER_TYPE_X(T) _AXIS_DRIVER_TYPE(X,T) #define AXIS_DRIVER_TYPE_X(T) _AXIS_DRIVER_TYPE(X,T)
#define AXIS_DRIVER_TYPE_Y(T) _AXIS_DRIVER_TYPE(Y,T) #define AXIS_DRIVER_TYPE_Y(T) _AXIS_DRIVER_TYPE(Y,T)
#define AXIS_DRIVER_TYPE_Z(T) _AXIS_DRIVER_TYPE(Z,T) #define AXIS_DRIVER_TYPE_Z(T) _AXIS_DRIVER_TYPE(Z,T)
#define AXIS_DRIVER_TYPE_I(T) _AXIS_DRIVER_TYPE(I,T)
#define AXIS_DRIVER_TYPE_J(T) _AXIS_DRIVER_TYPE(J,T)
#define AXIS_DRIVER_TYPE_K(T) _AXIS_DRIVER_TYPE(K,T)
#define AXIS_DRIVER_TYPE_X2(T) (EITHER(X_DUAL_STEPPER_DRIVERS, DUAL_X_CARRIAGE) && _AXIS_DRIVER_TYPE(X2,T)) #define AXIS_DRIVER_TYPE_X2(T) (EITHER(X_DUAL_STEPPER_DRIVERS, DUAL_X_CARRIAGE) && _AXIS_DRIVER_TYPE(X2,T))
#define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T)) #define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T))
@@ -83,6 +86,7 @@
#define HAS_E_DRIVER(T) (0 RREPEAT2(E_STEPPERS, _OR_ADTE, T)) #define HAS_E_DRIVER(T) (0 RREPEAT2(E_STEPPERS, _OR_ADTE, T))
#define HAS_DRIVER(T) ( AXIS_DRIVER_TYPE_X(T) || AXIS_DRIVER_TYPE_Y(T) || AXIS_DRIVER_TYPE_Z(T) \ #define HAS_DRIVER(T) ( AXIS_DRIVER_TYPE_X(T) || AXIS_DRIVER_TYPE_Y(T) || AXIS_DRIVER_TYPE_Z(T) \
|| AXIS_DRIVER_TYPE_I(T) || AXIS_DRIVER_TYPE_J(T) || AXIS_DRIVER_TYPE_K(T) \
|| AXIS_DRIVER_TYPE_X2(T) || AXIS_DRIVER_TYPE_Y2(T) || AXIS_DRIVER_TYPE_Z2(T) \ || AXIS_DRIVER_TYPE_X2(T) || AXIS_DRIVER_TYPE_Y2(T) || AXIS_DRIVER_TYPE_Z2(T) \
|| AXIS_DRIVER_TYPE_Z3(T) || AXIS_DRIVER_TYPE_Z4(T) || HAS_E_DRIVER(T) ) || AXIS_DRIVER_TYPE_Z3(T) || AXIS_DRIVER_TYPE_Z4(T) || HAS_E_DRIVER(T) )
@@ -153,9 +157,11 @@
#define _OR_EAH(N,T) || AXIS_HAS_##T(E##N) #define _OR_EAH(N,T) || AXIS_HAS_##T(E##N)
#define E_AXIS_HAS(T) (0 _OR_EAH(0,T) _OR_EAH(1,T) _OR_EAH(2,T) _OR_EAH(3,T) _OR_EAH(4,T) _OR_EAH(5,T) _OR_EAH(6,T) _OR_EAH(7,T)) #define E_AXIS_HAS(T) (0 _OR_EAH(0,T) _OR_EAH(1,T) _OR_EAH(2,T) _OR_EAH(3,T) _OR_EAH(4,T) _OR_EAH(5,T) _OR_EAH(6,T) _OR_EAH(7,T))
#define ANY_AXIS_HAS(T) ( AXIS_HAS_##T(X) || AXIS_HAS_##T(Y) || AXIS_HAS_##T(Z) \ #define ANY_AXIS_HAS(T) ( AXIS_HAS_##T(X) || AXIS_HAS_##T(X2) \
|| AXIS_HAS_##T(X2) || AXIS_HAS_##T(Y2) || AXIS_HAS_##T(Z2) \ || AXIS_HAS_##T(Y) || AXIS_HAS_##T(Y2) \
|| AXIS_HAS_##T(Z3) || AXIS_HAS_##T(Z4) || E_AXIS_HAS(T) ) || AXIS_HAS_##T(Z) || AXIS_HAS_##T(Z2) || AXIS_HAS_##T(Z3) || AXIS_HAS_##T(Z4) \
|| AXIS_HAS_##T(I) || AXIS_HAS_##T(J) || AXIS_HAS_##T(K) \
|| E_AXIS_HAS(T) )
#if ANY_AXIS_HAS(STEALTHCHOP) #if ANY_AXIS_HAS(STEALTHCHOP)
#define HAS_STEALTHCHOP 1 #define HAS_STEALTHCHOP 1

View File

@@ -140,25 +140,7 @@
#define STR_RESEND "Resend: " #define STR_RESEND "Resend: "
#define STR_UNKNOWN_COMMAND "Unknown command: \"" #define STR_UNKNOWN_COMMAND "Unknown command: \""
#define STR_ACTIVE_EXTRUDER "Active Extruder: " #define STR_ACTIVE_EXTRUDER "Active Extruder: "
#define STR_X_MIN "x_min"
#define STR_X_MAX "x_max"
#define STR_X2_MIN "x2_min"
#define STR_X2_MAX "x2_max"
#define STR_Y_MIN "y_min"
#define STR_Y_MAX "y_max"
#define STR_Y2_MIN "y2_min"
#define STR_Y2_MAX "y2_max"
#define STR_Z_MIN "z_min"
#define STR_Z_MAX "z_max"
#define STR_Z2_MIN "z2_min"
#define STR_Z2_MAX "z2_max"
#define STR_Z3_MIN "z3_min"
#define STR_Z3_MAX "z3_max"
#define STR_Z4_MIN "z4_min"
#define STR_Z4_MAX "z4_max"
#define STR_Z_PROBE "z_probe"
#define STR_PROBE_EN "probe_en"
#define STR_FILAMENT_RUNOUT_SENSOR "filament"
#define STR_PROBE_OFFSET "Probe Offset" #define STR_PROBE_OFFSET "Probe Offset"
#define STR_SKEW_MIN "min_skew_factor: " #define STR_SKEW_MIN "min_skew_factor: "
#define STR_SKEW_MAX "max_skew_factor: " #define STR_SKEW_MAX "max_skew_factor: "
@@ -277,17 +259,43 @@
#define STR_REMINDER_SAVE_SETTINGS "Remember to save!" #define STR_REMINDER_SAVE_SETTINGS "Remember to save!"
#define STR_PASSWORD_SET "Password is " #define STR_PASSWORD_SET "Password is "
// LCD Menu Messages //
// Endstop Names used by Endstops::report_states
//
#define STR_X_MIN "x_min"
#define STR_X_MAX "x_max"
#define STR_X2_MIN "x2_min"
#define STR_X2_MAX "x2_max"
#define LANGUAGE_DATA_INCL_(M) STRINGIFY_(fontdata/langdata_##M.h) #if HAS_Y_AXIS
#define LANGUAGE_DATA_INCL(M) LANGUAGE_DATA_INCL_(M) #define STR_Y_MIN "y_min"
#define STR_Y_MAX "y_max"
#define STR_Y2_MIN "y2_min"
#define STR_Y2_MAX "y2_max"
#endif
#define LANGUAGE_INCL_(M) STRINGIFY_(../lcd/language/language_##M.h) #if HAS_Z_AXIS
#define LANGUAGE_INCL(M) LANGUAGE_INCL_(M) #define STR_Z_MIN "z_min"
#define STR_Z_MAX "z_max"
#define STR_Z2_MIN "z2_min"
#define STR_Z2_MAX "z2_max"
#define STR_Z3_MIN "z3_min"
#define STR_Z3_MAX "z3_max"
#define STR_Z4_MIN "z4_min"
#define STR_Z4_MAX "z4_max"
#endif
#define STR_Z_PROBE "z_probe"
#define STR_PROBE_EN "probe_en"
#define STR_FILAMENT_RUNOUT_SENSOR "filament"
// General axis names
#define STR_X "X" #define STR_X "X"
#define STR_Y "Y" #define STR_Y "Y"
#define STR_Z "Z" #define STR_Z "Z"
#define STR_I AXIS4_STR
#define STR_J AXIS5_STR
#define STR_K AXIS6_STR
#define STR_E "E" #define STR_E "E"
#if IS_KINEMATIC #if IS_KINEMATIC
#define STR_A "A" #define STR_A "A"
@@ -307,8 +315,114 @@
#define LCD_STR_A STR_A #define LCD_STR_A STR_A
#define LCD_STR_B STR_B #define LCD_STR_B STR_B
#define LCD_STR_C STR_C #define LCD_STR_C STR_C
#define LCD_STR_I STR_I
#define LCD_STR_J STR_J
#define LCD_STR_K STR_K
#define LCD_STR_E STR_E #define LCD_STR_E STR_E
// Extra Axis and Endstop Names
#if LINEAR_AXES >= 4
#if AXIS4_NAME == 'A'
#define AXIS4_STR "A"
#define STR_I_MIN "a_min"
#define STR_I_MAX "a_max"
#elif AXIS4_NAME == 'B'
#define AXIS4_STR "B"
#define STR_I_MIN "b_min"
#define STR_I_MAX "b_max"
#elif AXIS4_NAME == 'C'
#define AXIS4_STR "C"
#define STR_I_MIN "c_min"
#define STR_I_MAX "c_max"
#elif AXIS4_NAME == 'U'
#define AXIS4_STR "U"
#define STR_I_MIN "u_min"
#define STR_I_MAX "u_max"
#elif AXIS4_NAME == 'V'
#define AXIS4_STR "V"
#define STR_I_MIN "v_min"
#define STR_I_MAX "v_max"
#elif AXIS4_NAME == 'W'
#define AXIS4_STR "W"
#define STR_I_MIN "w_min"
#define STR_I_MAX "w_max"
#else
#define AXIS4_STR "A"
#define STR_I_MIN "a_min"
#define STR_I_MAX "a_max"
#endif
#else
#define AXIS4_STR ""
#endif
#if LINEAR_AXES >= 5
#if AXIS5_NAME == 'A'
#define AXIS5_STR "A"
#define STR_J_MIN "a_min"
#define STR_J_MAX "a_max"
#elif AXIS5_NAME == 'B'
#define AXIS5_STR "B"
#define STR_J_MIN "b_min"
#define STR_J_MAX "b_max"
#elif AXIS5_NAME == 'C'
#define AXIS5_STR "C"
#define STR_J_MIN "c_min"
#define STR_J_MAX "c_max"
#elif AXIS5_NAME == 'U'
#define AXIS5_STR "U"
#define STR_J_MIN "u_min"
#define STR_J_MAX "u_max"
#elif AXIS5_NAME == 'V'
#define AXIS5_STR "V"
#define STR_J_MIN "v_min"
#define STR_J_MAX "v_max"
#elif AXIS5_NAME == 'W'
#define AXIS5_STR "W"
#define STR_J_MIN "w_min"
#define STR_J_MAX "w_max"
#else
#define AXIS5_STR "B"
#define STR_J_MIN "b_min"
#define STR_J_MAX "b_max"
#endif
#else
#define AXIS5_STR ""
#endif
#if LINEAR_AXES >= 6
#if AXIS6_NAME == 'A'
#define AXIS6_STR "A"
#define STR_K_MIN "a_min"
#define STR_K_MAX "a_max"
#elif AXIS6_NAME == 'B'
#define AXIS6_STR "B"
#define STR_K_MIN "b_min"
#define STR_K_MAX "b_max"
#elif AXIS6_NAME == 'C'
#define AXIS6_STR "C"
#define STR_K_MIN "c_min"
#define STR_K_MAX "c_max"
#elif AXIS6_NAME == 'U'
#define AXIS6_STR "U"
#define STR_K_MIN "u_min"
#define STR_K_MAX "u_max"
#elif AXIS6_NAME == 'V'
#define AXIS6_STR "V"
#define STR_K_MIN "v_min"
#define STR_K_MAX "v_max"
#elif AXIS6_NAME == 'W'
#define AXIS6_STR "W"
#define STR_K_MIN "w_min"
#define STR_K_MAX "w_max"
#else
#define AXIS6_STR "C"
#define STR_K_MIN "c_min"
#define STR_K_MAX "c_max"
#endif
#else
#define AXIS6_STR ""
#endif
#if EITHER(HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL) #if EITHER(HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL)
// Custom characters defined in the first 8 characters of the LCD // Custom characters defined in the first 8 characters of the LCD
@@ -386,6 +500,14 @@
#define LCD_STR_E6 "E" LCD_STR_N6 #define LCD_STR_E6 "E" LCD_STR_N6
#define LCD_STR_E7 "E" LCD_STR_N7 #define LCD_STR_E7 "E" LCD_STR_N7
// Include localized LCD Menu Messages
#define LANGUAGE_DATA_INCL_(M) STRINGIFY_(fontdata/langdata_##M.h)
#define LANGUAGE_DATA_INCL(M) LANGUAGE_DATA_INCL_(M)
#define LANGUAGE_INCL_(M) STRINGIFY_(../lcd/language/language_##M.h)
#define LANGUAGE_INCL(M) LANGUAGE_INCL_(M)
// Use superscripts, if possible. Evaluated at point of use. // Use superscripts, if possible. Evaluated at point of use.
#define SUPERSCRIPT_TWO TERN(NOT_EXTENDED_ISO10646_1_5X7, "^2", "²") #define SUPERSCRIPT_TWO TERN(NOT_EXTENDED_ISO10646_1_5X7, "^2", "²")
#define SUPERSCRIPT_THREE TERN(NOT_EXTENDED_ISO10646_1_5X7, "^3", "³") #define SUPERSCRIPT_THREE TERN(NOT_EXTENDED_ISO10646_1_5X7, "^3", "³")

View File

@@ -36,12 +36,21 @@
#define _XMIN_ 100 #define _XMIN_ 100
#define _YMIN_ 200 #define _YMIN_ 200
#define _ZMIN_ 300 #define _ZMIN_ 300
#define _IMIN_ 500
#define _JMIN_ 600
#define _KMIN_ 700
#define _XMAX_ 101 #define _XMAX_ 101
#define _YMAX_ 201 #define _YMAX_ 201
#define _ZMAX_ 301 #define _ZMAX_ 301
#define _IMAX_ 501
#define _JMAX_ 601
#define _KMAX_ 701
#define _XDIAG_ 102 #define _XDIAG_ 102
#define _YDIAG_ 202 #define _YDIAG_ 202
#define _ZDIAG_ 302 #define _ZDIAG_ 302
#define _IDIAG_ 502
#define _JDIAG_ 602
#define _KDIAG_ 702
#define _E0DIAG_ 400 #define _E0DIAG_ 400
#define _E1DIAG_ 401 #define _E1DIAG_ 401
#define _E2DIAG_ 402 #define _E2DIAG_ 402
@@ -195,6 +204,11 @@
#define __TERN(T,V...) ___TERN(_CAT(_NO,T),V) // Prepend '_NO' to get '_NOT_0' or '_NOT_1' #define __TERN(T,V...) ___TERN(_CAT(_NO,T),V) // Prepend '_NO' to get '_NOT_0' or '_NOT_1'
#define ___TERN(P,V...) THIRD(P,V) // If first argument has a comma, A. Else B. #define ___TERN(P,V...) THIRD(P,V) // If first argument has a comma, A. Else B.
#define _OPTARG(A) , A
#define OPTARG(O,A) TERN_(O,DEFER4(_OPTARG)(A))
#define _OPTCODE(A) A;
#define OPTCODE(O,A) TERN_(O,DEFER4(_OPTCODE)(A))
// Macros to avoid 'f + 0.0' which is not always optimized away. Minus included for symmetry. // Macros to avoid 'f + 0.0' which is not always optimized away. Minus included for symmetry.
// Compiler flags -fno-signed-zeros -ffinite-math-only also cover 'f * 1.0', 'f - f', etc. // Compiler flags -fno-signed-zeros -ffinite-math-only also cover 'f * 1.0', 'f - f', etc.
#define PLUS_TERN0(O,A) _TERN(_ENA_1(O),,+ (A)) // OPTION ? '+ (A)' : '<nul>' #define PLUS_TERN0(O,A) _TERN(_ENA_1(O),,+ (A)) // OPTION ? '+ (A)' : '<nul>'

View File

@@ -36,6 +36,10 @@ PGMSTR(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMST
PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C"); PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C");
PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E"); PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E");
PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:"); PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:");
PGMSTR(I_STR, AXIS4_STR); PGMSTR(J_STR, AXIS5_STR); PGMSTR(K_STR, AXIS6_STR);
PGMSTR(I_LBL, AXIS4_STR ":"); PGMSTR(J_LBL, AXIS5_STR ":"); PGMSTR(K_LBL, AXIS6_STR ":");
PGMSTR(SP_I_STR, " " AXIS4_STR); PGMSTR(SP_J_STR, " " AXIS5_STR); PGMSTR(SP_K_STR, " " AXIS6_STR);
PGMSTR(SP_I_LBL, " " AXIS4_STR ":"); PGMSTR(SP_J_LBL, " " AXIS5_STR ":"); PGMSTR(SP_K_LBL, " " AXIS6_STR ":");
// Hook Meatpack if it's enabled on the first leaf // Hook Meatpack if it's enabled on the first leaf
#if ENABLED(MEATPACK_ON_SERIAL_PORT_1) #if ENABLED(MEATPACK_ON_SERIAL_PORT_1)
@@ -101,8 +105,10 @@ void print_bin(uint16_t val) {
} }
} }
void print_xyz(const_float_t x, const_float_t y, const_float_t z, PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/) { void print_pos(LINEAR_AXIS_ARGS(const_float_t), PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/) {
if (prefix) serialprintPGM(prefix); if (prefix) serialprintPGM(prefix);
SERIAL_ECHOPAIR_P(SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z); SERIAL_ECHOPAIR_P(
LIST_N(DOUBLE(LINEAR_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k)
);
if (suffix) serialprintPGM(suffix); else SERIAL_EOL(); if (suffix) serialprintPGM(suffix); else SERIAL_EOL();
} }

View File

@@ -29,12 +29,16 @@
#endif #endif
// Commonly-used strings in serial output // Commonly-used strings in serial output
extern const char NUL_STR[], SP_P_STR[], SP_T_STR[], extern const char NUL_STR[],
SP_X_STR[], SP_Y_STR[], SP_Z_STR[],
SP_A_STR[], SP_B_STR[], SP_C_STR[], SP_E_STR[],
SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_E_LBL[],
SP_I_STR[], SP_J_STR[], SP_K_STR[],
SP_I_LBL[], SP_J_LBL[], SP_K_LBL[],
SP_P_STR[], SP_T_STR[],
X_STR[], Y_STR[], Z_STR[], E_STR[], X_STR[], Y_STR[], Z_STR[], E_STR[],
X_LBL[], Y_LBL[], Z_LBL[], E_LBL[], X_LBL[], Y_LBL[], Z_LBL[], E_LBL[],
SP_A_STR[], SP_B_STR[], SP_C_STR[], I_LBL[], J_LBL[], K_LBL[];
SP_X_STR[], SP_Y_STR[], SP_Z_STR[], SP_E_STR[],
SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_E_LBL[];
// //
// Debugging flags for use by M111 // Debugging flags for use by M111
@@ -310,11 +314,11 @@ void serialprint_truefalse(const bool tf);
void serial_spaces(uint8_t count); void serial_spaces(uint8_t count);
void print_bin(const uint16_t val); void print_bin(const uint16_t val);
void print_xyz(const_float_t x, const_float_t y, const_float_t z, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr); void print_pos(LINEAR_AXIS_ARGS(const_float_t), PGM_P const prefix=nullptr, PGM_P const suffix=nullptr);
inline void print_xyz(const xyz_pos_t &xyz, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr) { inline void print_pos(const xyz_pos_t &xyz, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr) {
print_xyz(xyz.x, xyz.y, xyz.z, prefix, suffix); print_pos(LINEAR_AXIS_ELEM(xyz), prefix, suffix);
} }
#define SERIAL_POS(SUFFIX,VAR) do { print_xyz(VAR, PSTR(" " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n")); }while(0) #define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, PSTR(" " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n")); }while(0)
#define SERIAL_XYZ(PREFIX,V...) do { print_xyz(V, PSTR(PREFIX), nullptr); }while(0) #define SERIAL_XYZ(PREFIX,V...) do { print_pos(V, PSTR(PREFIX), nullptr); }while(0)

View File

@@ -29,34 +29,6 @@
class __FlashStringHelper; class __FlashStringHelper;
typedef const __FlashStringHelper *progmem_str; typedef const __FlashStringHelper *progmem_str;
//
// 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 Steppers on Core kinematics
//
enum AxisEnum : uint8_t {
X_AXIS = 0, A_AXIS = 0,
Y_AXIS = 1, B_AXIS = 1,
Z_AXIS = 2, C_AXIS = 2,
E_AXIS = 3,
X_HEAD = 4, Y_HEAD = 5, Z_HEAD = 6,
E0_AXIS = 3,
E1_AXIS, E2_AXIS, E3_AXIS, E4_AXIS, E5_AXIS, E6_AXIS, E7_AXIS,
ALL_AXES = 0xFE, NO_AXIS = 0xFF
};
//
// Loop over XYZE axes
//
#define LOOP_XYZ(VAR) LOOP_S_LE_N(VAR, X_AXIS, Z_AXIS)
#define LOOP_XYZE(VAR) LOOP_S_LE_N(VAR, X_AXIS, E_AXIS)
#define LOOP_XYZE_N(VAR) LOOP_S_L_N(VAR, X_AXIS, XYZE_N)
#define LOOP_ABC(VAR) LOOP_S_LE_N(VAR, A_AXIS, C_AXIS)
#define LOOP_ABCE(VAR) LOOP_S_LE_N(VAR, A_AXIS, E_AXIS)
#define LOOP_ABCE_N(VAR) LOOP_S_L_N(VAR, A_AXIS, XYZE_N)
// //
// Conditional type assignment magic. For example... // Conditional type assignment magic. For example...
// //
@@ -67,6 +39,85 @@ struct IF { typedef R type; };
template <class L, class R> template <class L, class R>
struct IF<true, L, R> { typedef L type; }; struct IF<true, L, R> { typedef L type; };
#define LINEAR_AXIS_GANG(V...) GANG_N(LINEAR_AXES, V)
#define LINEAR_AXIS_CODE(V...) CODE_N(LINEAR_AXES, V)
#define LINEAR_AXIS_LIST(V...) LIST_N(LINEAR_AXES, V)
#define LINEAR_AXIS_ARRAY(V...) { LINEAR_AXIS_LIST(V) }
#define LINEAR_AXIS_ARGS(T...) LINEAR_AXIS_LIST(T x, T y, T z, T i, T j, T k)
#define LINEAR_AXIS_ELEM(O) LINEAR_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k)
#define LINEAR_AXIS_DEFS(T,V) LINEAR_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V)
#define LOGICAL_AXIS_GANG(E,V...) LINEAR_AXIS_GANG(V) GANG_ITEM_E(E)
#define LOGICAL_AXIS_CODE(E,V...) LINEAR_AXIS_CODE(V) CODE_ITEM_E(E)
#define LOGICAL_AXIS_LIST(E,V...) LINEAR_AXIS_LIST(V) LIST_ITEM_E(E)
#define LOGICAL_AXIS_ARRAY(E,V...) { LOGICAL_AXIS_LIST(E,V) }
#define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k)
#define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k)
#define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V)
#if HAS_EXTRUDERS
#define LIST_ITEM_E(N) , N
#define CODE_ITEM_E(N) ; N
#define GANG_ITEM_E(N) N
#else
#define LIST_ITEM_E(N)
#define CODE_ITEM_E(N)
#define GANG_ITEM_E(N)
#endif
//
// 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 Steppers on Core kinematics
//
enum AxisEnum : uint8_t {
// Linear axes may be controlled directly or indirectly
LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS)
// Extruder axes may be considered distinctly
#define _EN_ITEM(N) , E##N##_AXIS
REPEAT(EXTRUDERS, _EN_ITEM)
#undef _EN_ITEM
// Core also keeps toolhead directions
#if EITHER(IS_CORE, MARKFORGED_XY)
, X_HEAD, Y_HEAD, Z_HEAD
#endif
// Distinct axes, including all E and Core
, NUM_AXIS_ENUMS
// Most of the time we refer only to the single E_AXIS
#if HAS_EXTRUDERS
, E_AXIS = E0_AXIS
#endif
// A, B, and C are for DELTA, SCARA, etc.
, A_AXIS = X_AXIS
#if LINEAR_AXES >= 2
, B_AXIS = Y_AXIS
#endif
#if LINEAR_AXES >= 3
, C_AXIS = Z_AXIS
#endif
// To refer to all or none
, ALL_AXES_ENUM = 0xFE, NO_AXIS_ENUM = 0xFF
};
typedef IF<(NUM_AXIS_ENUMS > 8), uint16_t, uint8_t>::type axis_bits_t;
//
// Loop over axes
//
#define LOOP_ABC(VAR) LOOP_S_LE_N(VAR, A_AXIS, C_AXIS)
#define LOOP_LINEAR_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LINEAR_AXES)
#define LOOP_LOGICAL_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LOGICAL_AXES)
#define LOOP_DISTINCT_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, DISTINCT_AXES)
// //
// feedRate_t is just a humble float // feedRate_t is just a humble float
// //
@@ -187,7 +238,7 @@ void toNative(xyz_pos_t &raw);
void toNative(xyze_pos_t &raw); void toNative(xyze_pos_t &raw);
// //
// XY coordinates, counters, etc. // Paired XY coordinates, counters, flags, etc.
// //
template<typename T> template<typename T>
struct XYval { struct XYval {
@@ -196,18 +247,34 @@ struct XYval {
struct { T a, b; }; struct { T a, b; };
T pos[2]; T pos[2];
}; };
FI void set(const T px) { x = px; }
FI void set(const T px, const T py) { x = px; y = py; } // Set all to 0
FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
FI void set(const T (&arr)[XYZ]) { x = arr[0]; y = arr[1]; }
FI void set(const T (&arr)[XYZE]) { x = arr[0]; y = arr[1]; }
#if XYZE_N > XYZE
FI void set(const T (&arr)[XYZE_N]) { x = arr[0]; y = arr[1]; }
#endif
FI void reset() { x = y = 0; } FI void reset() { x = y = 0; }
// Setters taking struct types and arrays
FI void set(const T px) { x = px; }
#if HAS_Y_AXIS
FI void set(const T px, const T py) { x = px; y = py; }
FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
#endif
#if LINEAR_AXES > XY
FI void set(const T (&arr)[LINEAR_AXES]) { x = arr[0]; y = arr[1]; }
#endif
#if LOGICAL_AXES > LINEAR_AXES
FI void set(const T (&arr)[LOGICAL_AXES]) { x = arr[0]; y = arr[1]; }
#if DISTINCT_AXES > LOGICAL_AXES
FI void set(const T (&arr)[DISTINCT_AXES]) { x = arr[0]; y = arr[1]; }
#endif
#endif
// Length reduced to one dimension
FI T magnitude() const { return (T)sqrtf(x*x + y*y); } FI T magnitude() const { return (T)sqrtf(x*x + y*y); }
// Pointer to the data as a simple array
FI operator T* () { return pos; } FI operator T* () { return pos; }
// If any element is true then it's true
FI operator bool() { return x || y; } FI operator bool() { return x || y; }
// Explicit copy and copies with conversion
FI XYval<T> copy() const { return *this; } FI XYval<T> copy() const { return *this; }
FI XYval<T> ABS() const { return { T(_ABS(x)), T(_ABS(y)) }; } FI XYval<T> ABS() const { return { T(_ABS(x)), T(_ABS(y)) }; }
FI XYval<int16_t> asInt() { return { int16_t(x), int16_t(y) }; } FI XYval<int16_t> asInt() { return { int16_t(x), int16_t(y) }; }
@@ -219,17 +286,27 @@ struct XYval {
FI XYval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y) }; } FI XYval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y) }; }
FI XYval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y) }; } FI XYval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y) }; }
FI XYval<float> reciprocal() const { return { _RECIP(x), _RECIP(y) }; } FI XYval<float> reciprocal() const { return { _RECIP(x), _RECIP(y) }; }
// Marlin workspace shifting is done with G92 and M206
FI XYval<float> asLogical() const { XYval<float> o = asFloat(); toLogical(o); return o; } FI XYval<float> asLogical() const { XYval<float> o = asFloat(); toLogical(o); return o; }
FI XYval<float> asNative() const { XYval<float> o = asFloat(); toNative(o); return o; } FI XYval<float> asNative() const { XYval<float> o = asFloat(); toNative(o); return o; }
// Cast to a type with more fields by making a new object
FI operator XYZval<T>() { return { x, y }; } FI operator XYZval<T>() { return { x, y }; }
FI operator XYZval<T>() const { return { x, y }; } FI operator XYZval<T>() const { return { x, y }; }
FI operator XYZEval<T>() { return { x, y }; } FI operator XYZEval<T>() { return { x, y }; }
FI operator XYZEval<T>() const { return { x, y }; } FI operator XYZEval<T>() const { return { x, y }; }
FI T& operator[](const int i) { return pos[i]; }
FI const T& operator[](const int i) const { return pos[i]; } // Accessor via an AxisEnum (or any integer) [index]
FI T& operator[](const int n) { return pos[n]; }
FI const T& operator[](const int n) const { return pos[n]; }
// Assignment operator overrides do the expected thing
FI XYval<T>& operator= (const T v) { set(v, v ); return *this; } FI XYval<T>& operator= (const T v) { set(v, v ); return *this; }
FI XYval<T>& operator= (const XYZval<T> &rs) { set(rs.x, rs.y); return *this; } FI XYval<T>& operator= (const XYZval<T> &rs) { set(rs.x, rs.y); return *this; }
FI XYval<T>& operator= (const XYZEval<T> &rs) { set(rs.x, rs.y); return *this; } FI XYval<T>& operator= (const XYZEval<T> &rs) { set(rs.x, rs.y); return *this; }
// Override other operators to get intuitive behaviors
FI XYval<T> operator+ (const XYval<T> &rs) const { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; } FI XYval<T> operator+ (const XYval<T> &rs) const { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
FI XYval<T> operator+ (const XYval<T> &rs) { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; } FI XYval<T> operator+ (const XYval<T> &rs) { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
FI XYval<T> operator- (const XYval<T> &rs) const { XYval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; } FI XYval<T> operator- (const XYval<T> &rs) const { XYval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
@@ -266,6 +343,10 @@ struct XYval {
FI XYval<T> operator>>(const int &v) { XYval<T> ls = *this; _RS(ls.x); _RS(ls.y); return ls; } FI XYval<T> operator>>(const int &v) { XYval<T> ls = *this; _RS(ls.x); _RS(ls.y); return ls; }
FI XYval<T> operator<<(const int &v) const { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; } FI XYval<T> operator<<(const int &v) const { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; }
FI XYval<T> operator<<(const int &v) { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; } FI XYval<T> operator<<(const int &v) { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; }
FI const XYval<T> operator-() const { XYval<T> o = *this; o.x = -x; o.y = -y; return o; }
FI XYval<T> operator-() { XYval<T> o = *this; o.x = -x; o.y = -y; return o; }
// Modifier operators
FI XYval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; } FI XYval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; }
FI XYval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; } FI XYval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
FI XYval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; } FI XYval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
@@ -279,6 +360,8 @@ struct XYval {
FI XYval<T>& operator*=(const int &v) { x *= v; y *= v; return *this; } FI XYval<T>& operator*=(const int &v) { x *= v; y *= v; return *this; }
FI XYval<T>& operator>>=(const int &v) { _RS(x); _RS(y); return *this; } FI XYval<T>& operator>>=(const int &v) { _RS(x); _RS(y); return *this; }
FI XYval<T>& operator<<=(const int &v) { _LS(x); _LS(y); return *this; } FI XYval<T>& operator<<=(const int &v) { _LS(x); _LS(y); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYval<T> &rs) { return x == rs.x && y == rs.y; } FI bool operator==(const XYval<T> &rs) { return x == rs.x && y == rs.y; }
FI bool operator==(const XYZval<T> &rs) { return x == rs.x && y == rs.y; } FI bool operator==(const XYZval<T> &rs) { return x == rs.x && y == rs.y; }
FI bool operator==(const XYZEval<T> &rs) { return x == rs.x && y == rs.y; } FI bool operator==(const XYZEval<T> &rs) { return x == rs.x && y == rs.y; }
@@ -291,224 +374,291 @@ struct XYval {
FI bool operator!=(const XYval<T> &rs) const { return !operator==(rs); } 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 XYZval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); } FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
FI XYval<T> operator-() { XYval<T> o = *this; o.x = -x; o.y = -y; return o; }
FI const XYval<T> operator-() const { XYval<T> o = *this; o.x = -x; o.y = -y; return o; }
}; };
// //
// XYZ coordinates, counters, etc. // Linear Axes coordinates, counters, flags, etc.
// //
template<typename T> template<typename T>
struct XYZval { struct XYZval {
union { union {
struct { T x, y, z; }; struct { T LINEAR_AXIS_ARGS(); };
struct { T a, b, c; }; struct { T LINEAR_AXIS_LIST(a, b, c, u, v, w); };
T pos[3]; T pos[LINEAR_AXES];
}; };
// Set all to 0
FI void reset() { LINEAR_AXIS_GANG(x =, y =, z =, i =, j =, k =) 0; }
// Setters taking struct types and arrays
FI void set(const T px) { x = px; } FI void set(const T px) { x = px; }
FI void set(const T px, const T py) { x = px; y = py; } FI void set(const T px, const T py) { x = px; y = py; }
FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
FI void set(const XYval<T> pxy, const T pz) { x = pxy.x; y = pxy.y; z = pz; } FI void set(const XYval<T> pxy, const T pz) { LINEAR_AXIS_CODE(x = pxy.x, y = pxy.y, z = pz, NOOP, NOOP, NOOP); }
FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; } FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
FI void set(const T (&arr)[XYZ]) { x = arr[0]; y = arr[1]; z = arr[2]; } #if HAS_Z_AXIS
FI void set(const T (&arr)[XYZE]) { x = arr[0]; y = arr[1]; z = arr[2]; } FI void set(const T (&arr)[LINEAR_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); }
#if XYZE_N > XYZE FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k ); }
FI void set(const T (&arr)[XYZE_N]) { x = arr[0]; y = arr[1]; z = arr[2]; }
#endif #endif
FI void reset() { x = y = z = 0; } #if LOGICAL_AXES > LINEAR_AXES
FI T magnitude() const { return (T)sqrtf(x*x + y*y + z*z); } FI void set(const T (&arr)[LOGICAL_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); }
FI void set(LOGICAL_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k ); }
#if DISTINCT_AXES > LOGICAL_AXES
FI void set(const T (&arr)[DISTINCT_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); }
#endif
#endif
#if LINEAR_AXES >= 4
FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; }
#endif
#if LINEAR_AXES >= 5
FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; }
#endif
#if LINEAR_AXES >= 6
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; }
#endif
// Length reduced to one dimension
FI T magnitude() const { return (T)sqrtf(LINEAR_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k)); }
// Pointer to the data as a simple array
FI operator T* () { return pos; } FI operator T* () { return pos; }
FI operator bool() { return z || x || y; } // If any element is true then it's true
FI operator bool() { return LINEAR_AXIS_GANG(x, || y, || z, || i, || j, || k); }
// Explicit copy and copies with conversion
FI XYZval<T> copy() const { XYZval<T> o = *this; return o; } FI XYZval<T> copy() const { XYZval<T> o = *this; return o; }
FI XYZval<T> ABS() const { return { T(_ABS(x)), T(_ABS(y)), T(_ABS(z)) }; } FI XYZval<T> ABS() const { return LINEAR_AXIS_ARRAY(T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k))); }
FI XYZval<int16_t> asInt() { return { int16_t(x), int16_t(y), int16_t(z) }; } FI XYZval<int16_t> asInt() { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); }
FI XYZval<int16_t> asInt() const { return { int16_t(x), int16_t(y), int16_t(z) }; } FI XYZval<int16_t> asInt() const { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); }
FI XYZval<int32_t> asLong() { return { int32_t(x), int32_t(y), int32_t(z) }; } FI XYZval<int32_t> asLong() { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); }
FI XYZval<int32_t> asLong() const { return { int32_t(x), int32_t(y), int32_t(z) }; } FI XYZval<int32_t> asLong() const { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); }
FI XYZval<int32_t> ROUNDL() { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)) }; } FI XYZval<int32_t> ROUNDL() { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); }
FI XYZval<int32_t> ROUNDL() const { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)) }; } FI XYZval<int32_t> ROUNDL() const { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); }
FI XYZval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) }; } FI XYZval<float> asFloat() { return LINEAR_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)); }
FI XYZval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) }; } FI XYZval<float> asFloat() const { return LINEAR_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)); }
FI XYZval<float> reciprocal() const { return { _RECIP(x), _RECIP(y), _RECIP(z) }; } FI XYZval<float> reciprocal() const { return LINEAR_AXIS_ARRAY(_RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); }
// 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> asLogical() const { XYZval<float> o = asFloat(); toLogical(o); return o; }
FI XYZval<float> asNative() const { XYZval<float> o = asFloat(); toNative(o); return o; } FI XYZval<float> asNative() const { XYZval<float> o = asFloat(); toNative(o); return o; }
// In-place cast to types having fewer fields
FI operator XYval<T>&() { return *(XYval<T>*)this; } FI operator XYval<T>&() { return *(XYval<T>*)this; }
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; } FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
FI operator XYZEval<T>() const { return { x, y, z }; }
FI T& operator[](const int i) { return pos[i]; } // Cast to a type with more fields by making a new object
FI const T& operator[](const int i) const { return pos[i]; } FI operator XYZEval<T>() const { return LINEAR_AXIS_ARRAY(x, y, z, i, j, k); }
FI XYZval<T>& operator= (const T v) { set(v, v, v ); return *this; }
// Accessor via an AxisEnum (or any integer) [index]
FI T& operator[](const int n) { return pos[n]; }
FI const T& operator[](const int n) const { return pos[n]; }
// Assignment operator overrides do the expected thing
FI XYZval<T>& operator= (const T v) { set(ARRAY_N_1(LINEAR_AXES, v)); return *this; }
FI XYZval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y ); return *this; } FI XYZval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y ); return *this; }
FI XYZval<T>& operator= (const XYZEval<T> &rs) { set(rs.x, rs.y, rs.z); return *this; } FI XYZval<T>& operator= (const XYZEval<T> &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; }
FI XYZval<T> operator+ (const XYval<T> &rs) const { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
FI XYZval<T> operator+ (const XYval<T> &rs) { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; } // Override other operators to get intuitive behaviors
FI XYZval<T> operator- (const XYval<T> &rs) const { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; } FI XYZval<T> operator+ (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator- (const XYval<T> &rs) { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; } FI XYZval<T> operator+ (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator* (const XYval<T> &rs) const { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; } FI XYZval<T> operator- (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator* (const XYval<T> &rs) { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; } FI XYZval<T> operator- (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator/ (const XYval<T> &rs) const { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; } FI XYZval<T> operator* (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator/ (const XYval<T> &rs) { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; } FI XYZval<T> operator* (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; } FI XYZval<T> operator/ (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator+ (const XYZval<T> &rs) { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; } FI XYZval<T> operator/ (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator- (const XYZval<T> &rs) const { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; } FI XYZval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; }
FI XYZval<T> operator- (const XYZval<T> &rs) { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; } FI XYZval<T> operator+ (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; }
FI XYZval<T> operator* (const XYZval<T> &rs) const { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; } FI XYZval<T> operator- (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; }
FI XYZval<T> operator* (const XYZval<T> &rs) { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; } FI XYZval<T> operator- (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; }
FI XYZval<T> operator/ (const XYZval<T> &rs) const { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; } FI XYZval<T> operator* (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; }
FI XYZval<T> operator/ (const XYZval<T> &rs) { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; } FI XYZval<T> operator* (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; }
FI XYZval<T> operator+ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; } FI XYZval<T> operator/ (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; }
FI XYZval<T> operator+ (const XYZEval<T> &rs) { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; } FI XYZval<T> operator/ (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; }
FI XYZval<T> operator- (const XYZEval<T> &rs) const { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; } FI XYZval<T> operator+ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; }
FI XYZval<T> operator- (const XYZEval<T> &rs) { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; } FI XYZval<T> operator+ (const XYZEval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; }
FI XYZval<T> operator* (const XYZEval<T> &rs) const { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; } FI XYZval<T> operator- (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; }
FI XYZval<T> operator* (const XYZEval<T> &rs) { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; } FI XYZval<T> operator- (const XYZEval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; }
FI XYZval<T> operator/ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; } FI XYZval<T> operator* (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; }
FI XYZval<T> operator/ (const XYZEval<T> &rs) { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; } FI XYZval<T> operator* (const XYZEval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; }
FI XYZval<T> operator* (const float &v) const { XYZval<T> ls = *this; ls.x *= v; ls.y *= v; ls.z *= v; return ls; } FI XYZval<T> operator/ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; }
FI XYZval<T> operator* (const float &v) { XYZval<T> ls = *this; ls.x *= v; ls.y *= v; ls.z *= v; return ls; } FI XYZval<T> operator/ (const XYZEval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; }
FI XYZval<T> operator* (const int &v) const { XYZval<T> ls = *this; ls.x *= v; ls.y *= v; ls.z *= v; return ls; } FI XYZval<T> operator* (const float &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; }
FI XYZval<T> operator* (const int &v) { XYZval<T> ls = *this; ls.x *= v; ls.y *= v; ls.z *= v; return ls; } FI XYZval<T> operator* (const float &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; }
FI XYZval<T> operator/ (const float &v) const { XYZval<T> ls = *this; ls.x /= v; ls.y /= v; ls.z /= v; return ls; } FI XYZval<T> operator* (const int &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; }
FI XYZval<T> operator/ (const float &v) { XYZval<T> ls = *this; ls.x /= v; ls.y /= v; ls.z /= v; return ls; } FI XYZval<T> operator* (const int &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; }
FI XYZval<T> operator/ (const int &v) const { XYZval<T> ls = *this; ls.x /= v; ls.y /= v; ls.z /= v; return ls; } FI XYZval<T> operator/ (const float &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; }
FI XYZval<T> operator/ (const int &v) { XYZval<T> ls = *this; ls.x /= v; ls.y /= v; ls.z /= v; return ls; } FI XYZval<T> operator/ (const float &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; }
FI XYZval<T> operator>>(const int &v) const { XYZval<T> ls = *this; _RS(ls.x); _RS(ls.y); _RS(ls.z); return ls; } FI XYZval<T> operator/ (const int &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; }
FI XYZval<T> operator>>(const int &v) { XYZval<T> ls = *this; _RS(ls.x); _RS(ls.y); _RS(ls.z); return ls; } FI XYZval<T> operator/ (const int &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; }
FI XYZval<T> operator<<(const int &v) const { XYZval<T> ls = *this; _LS(ls.x); _LS(ls.y); _LS(ls.z); return ls; } FI XYZval<T> operator>>(const int &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; }
FI XYZval<T> operator<<(const int &v) { XYZval<T> ls = *this; _LS(ls.x); _LS(ls.y); _LS(ls.z); return ls; } FI XYZval<T> operator>>(const int &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; }
FI XYZval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; } FI XYZval<T> operator<<(const int &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; }
FI XYZval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; } FI XYZval<T> operator<<(const int &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; }
FI XYZval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; } FI const XYZval<T> operator-() const { XYZval<T> o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k); return o; }
FI XYZval<T>& operator/=(const XYval<T> &rs) { x /= rs.x; y /= rs.y; return *this; } FI XYZval<T> operator-() { XYZval<T> o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k); return o; }
FI XYZval<T>& operator+=(const XYZval<T> &rs) { x += rs.x; y += rs.y; z += rs.z; return *this; }
FI XYZval<T>& operator-=(const XYZval<T> &rs) { x -= rs.x; y -= rs.y; z -= rs.z; return *this; } // Modifier operators
FI XYZval<T>& operator*=(const XYZval<T> &rs) { x *= rs.x; y *= rs.y; z *= rs.z; return *this; } FI XYZval<T>& operator+=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator/=(const XYZval<T> &rs) { x /= rs.x; y /= rs.y; z /= rs.z; return *this; } FI XYZval<T>& operator-=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator+=(const XYZEval<T> &rs) { x += rs.x; y += rs.y; z += rs.z; return *this; } FI XYZval<T>& operator*=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator-=(const XYZEval<T> &rs) { x -= rs.x; y -= rs.y; z -= rs.z; return *this; } FI XYZval<T>& operator/=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator*=(const XYZEval<T> &rs) { x *= rs.x; y *= rs.y; z *= rs.z; return *this; } FI XYZval<T>& operator+=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; }
FI XYZval<T>& operator/=(const XYZEval<T> &rs) { x /= rs.x; y /= rs.y; z /= rs.z; return *this; } FI XYZval<T>& operator-=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; }
FI XYZval<T>& operator*=(const float &v) { x *= v; y *= v; z *= v; return *this; } FI XYZval<T>& operator*=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; }
FI XYZval<T>& operator*=(const int &v) { x *= v; y *= v; z *= v; return *this; } FI XYZval<T>& operator/=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; }
FI XYZval<T>& operator>>=(const int &v) { _RS(x); _RS(y); _RS(z); return *this; } FI XYZval<T>& operator+=(const XYZEval<T> &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; }
FI XYZval<T>& operator<<=(const int &v) { _LS(x); _LS(y); _LS(z); return *this; } FI XYZval<T>& operator-=(const XYZEval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; }
FI bool operator==(const XYZEval<T> &rs) { return x == rs.x && y == rs.y && z == rs.z; } FI XYZval<T>& operator*=(const XYZEval<T> &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; }
FI XYZval<T>& operator/=(const XYZEval<T> &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; }
FI XYZval<T>& operator*=(const float &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; }
FI XYZval<T>& operator*=(const int &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; }
FI XYZval<T>& operator>>=(const int &v) { LINEAR_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k)); return *this; }
FI XYZval<T>& operator<<=(const int &v) { LINEAR_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYZEval<T> &rs) { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); }
FI bool operator==(const XYZEval<T> &rs) const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); }
FI bool operator!=(const XYZEval<T> &rs) { return !operator==(rs); } FI bool operator!=(const XYZEval<T> &rs) { return !operator==(rs); }
FI bool operator==(const XYZEval<T> &rs) const { return x == rs.x && y == rs.y && z == rs.z; }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); } FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
FI XYZval<T> operator-() { XYZval<T> o = *this; o.x = -x; o.y = -y; o.z = -z; return o; }
FI const XYZval<T> operator-() const { XYZval<T> o = *this; o.x = -x; o.y = -y; o.z = -z; return o; }
}; };
// //
// XYZE coordinates, counters, etc. // Logical Axes coordinates, counters, etc.
// //
template<typename T> template<typename T>
struct XYZEval { struct XYZEval {
union { union {
struct{ T x, y, z, e; }; struct { T LOGICAL_AXIS_ARGS(); };
struct{ T a, b, c; }; struct { T LOGICAL_AXIS_LIST(_e, a, b, c, u, v, w); };
T pos[4]; T pos[LOGICAL_AXES];
}; };
FI void reset() { x = y = z = e = 0; } // Reset all to 0
FI T magnitude() const { return (T)sqrtf(x*x + y*y + z*z + e*e); } FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =) 0; }
FI operator T* () { return pos; }
FI operator bool() { return e || z || x || y; } // Setters taking struct types and arrays
FI void set(const T px) { x = px; } FI void set(const T px) { x = px; }
FI void set(const T px, const T py) { x = px; y = py; } FI void set(const T px, const T py) { x = px; y = py; }
FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
FI void set(const T px, const T py, const T pz, const T pe) { x = px; y = py; z = pz; e = pe; } FI void set(const XYZval<T> pxyz) { set(LINEAR_AXIS_ELEM(pxyz)); }
FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; } #if HAS_Z_AXIS
FI void set(const XYval<T> pxy, const T pz) { x = pxy.x; y = pxy.y; z = pz; } FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k); }
FI void set(const XYZval<T> pxyz) { x = pxyz.x; y = pxyz.y; z = pxyz.z; }
FI void set(const XYval<T> pxy, const T pz, const T pe) { x = pxy.x; y = pxy.y; z = pz; e = pe; }
FI void set(const XYval<T> pxy, const XYval<T> pze) { x = pxy.x; y = pxy.y; z = pze.z; e = pze.e; }
FI void set(const XYZval<T> pxyz, const T pe) { x = pxyz.x; y = pxyz.y; z = pxyz.z; e = pe; }
FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
FI void set(const T (&arr)[XYZ]) { x = arr[0]; y = arr[1]; z = arr[2]; }
FI void set(const T (&arr)[XYZE]) { x = arr[0]; y = arr[1]; z = arr[2]; e = arr[3]; }
#if XYZE_N > XYZE
FI void set(const T (&arr)[XYZE_N]) { x = arr[0]; y = arr[1]; z = arr[2]; e = arr[3]; }
#endif #endif
FI XYZEval<T> copy() const { return *this; } #if LOGICAL_AXES > LINEAR_AXES
FI XYZEval<T> ABS() const { return { T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(e)) }; } FI void set(const XYval<T> pxy, const T pe) { set(pxy); e = pe; }
FI XYZEval<int16_t> asInt() { return { int16_t(x), int16_t(y), int16_t(z), int16_t(e) }; } FI void set(const XYZval<T> pxyz, const T pe) { set(pxyz); e = pe; }
FI XYZEval<int16_t> asInt() const { return { int16_t(x), int16_t(y), int16_t(z), int16_t(e) }; } FI void set(LOGICAL_AXIS_ARGS(const T)) { LOGICAL_AXIS_CODE(_e = e, a = x, b = y, c = z, u = i, v = j, w = k); }
FI XYZEval<int32_t> asLong() { return { int32_t(x), int32_t(y), int32_t(z), int32_t(e) }; } #endif
FI XYZEval<int32_t> asLong() const { return { int32_t(x), int32_t(y), int32_t(z), int32_t(e) }; } #if LINEAR_AXES >= 4
FI XYZEval<int32_t> ROUNDL() { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(e)) }; } FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; }
FI XYZEval<int32_t> ROUNDL() const { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(e)) }; } #endif
FI XYZEval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(e) }; } #if LINEAR_AXES >= 5
FI XYZEval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(e) }; } FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; }
FI XYZEval<float> reciprocal() const { return { _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(e) }; } #endif
FI XYZEval<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; } #if LINEAR_AXES >= 6
FI XYZEval<float> asNative() const { XYZEval<float> o = asFloat(); toNative(o); return o; } 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 operator XYval<T>&() { return *(XYval<T>*)this; } #endif
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
FI operator XYZval<T>&() { return *(XYZval<T>*)this; } // Length reduced to one dimension
FI operator const XYZval<T>&() const { return *(const XYZval<T>*)this; } FI T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k)); }
FI T& operator[](const int i) { return pos[i]; } // Pointer to the data as a simple array
FI const T& operator[](const int i) const { return pos[i]; } FI operator T* () { return pos; }
FI XYZEval<T>& operator= (const T v) { set(v, v, v, v); return *this; } // If any element is true then it's true
FI XYZEval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y); return *this; } FI operator bool() { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k); }
FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(rs.x, rs.y, rs.z); return *this; }
FI XYZEval<T> operator+ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; } // Explicit copy and copies with conversion
FI XYZEval<T> operator+ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; } FI XYZEval<T> copy() const { XYZEval<T> o = *this; return o; }
FI XYZEval<T> operator- (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; } FI XYZEval<T> ABS() const { return LOGICAL_AXIS_ARRAY(T(_ABS(e)), T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k))); }
FI XYZEval<T> operator- (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; } FI XYZEval<int16_t> asInt() { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); }
FI XYZEval<T> operator* (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; } FI XYZEval<int16_t> asInt() const { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); }
FI XYZEval<T> operator* (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; } FI XYZEval<int32_t> asLong() { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); }
FI XYZEval<T> operator/ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; } FI XYZEval<int32_t> asLong() const { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); }
FI XYZEval<T> operator/ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; } FI XYZEval<int32_t> ROUNDL() { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); }
FI XYZEval<T> operator+ (const XYZval<T> &rs) const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; } FI XYZEval<int32_t> ROUNDL() const { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); }
FI XYZEval<T> operator+ (const XYZval<T> &rs) { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; } FI XYZEval<float> asFloat() { 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)); }
FI XYZEval<T> operator- (const XYZval<T> &rs) const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; } FI 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)); }
FI XYZEval<T> operator- (const XYZval<T> &rs) { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; } FI XYZEval<float> reciprocal() const { return LOGICAL_AXIS_ARRAY(_RECIP(e), _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); }
FI XYZEval<T> operator* (const XYZval<T> &rs) const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; }
FI XYZEval<T> operator* (const XYZval<T> &rs) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; } // Marlin workspace shifting is done with G92 and M206
FI XYZEval<T> operator/ (const XYZval<T> &rs) const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; } FI XYZEval<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
FI XYZEval<T> operator/ (const XYZval<T> &rs) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; } FI XYZEval<float> asNative() const { XYZEval<float> o = asFloat(); toNative(o); return o; }
FI XYZEval<T> operator+ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; ls.e += rs.e; return ls; }
FI XYZEval<T> operator+ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; ls.e += rs.e; return ls; } // In-place cast to types having fewer fields
FI XYZEval<T> operator- (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; ls.e -= rs.e; return ls; } FI operator XYval<T>&() { return *(XYval<T>*)this; }
FI XYZEval<T> operator- (const XYZEval<T> &rs) { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; ls.e -= rs.e; return ls; } FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
FI XYZEval<T> operator* (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; ls.e *= rs.e; return ls; } FI operator XYZval<T>&() { return *(XYZval<T>*)this; }
FI XYZEval<T> operator* (const XYZEval<T> &rs) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; ls.e *= rs.e; return ls; } FI operator const XYZval<T>&() const { return *(const XYZval<T>*)this; }
FI XYZEval<T> operator/ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; ls.e /= rs.e; return ls; }
FI XYZEval<T> operator/ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; ls.e /= rs.e; return ls; } // Accessor via an AxisEnum (or any integer) [index]
FI XYZEval<T> operator* (const float &v) const { XYZEval<T> ls = *this; ls.x *= v; ls.y *= v; ls.z *= v; ls.e *= v; return ls; } FI T& operator[](const int n) { return pos[n]; }
FI XYZEval<T> operator* (const float &v) { XYZEval<T> ls = *this; ls.x *= v; ls.y *= v; ls.z *= v; ls.e *= v; return ls; } FI const T& operator[](const int n) const { return pos[n]; }
FI XYZEval<T> operator* (const int &v) const { XYZEval<T> ls = *this; ls.x *= v; ls.y *= v; ls.z *= v; ls.e *= v; return ls; }
FI XYZEval<T> operator* (const int &v) { XYZEval<T> ls = *this; ls.x *= v; ls.y *= v; ls.z *= v; ls.e *= v; return ls; } // Assignment operator overrides do the expected thing
FI XYZEval<T> operator/ (const float &v) const { XYZEval<T> ls = *this; ls.x /= v; ls.y /= v; ls.z /= v; ls.e /= v; return ls; } FI XYZEval<T>& operator= (const T v) { set(LIST_N_1(LINEAR_AXES, v)); return *this; }
FI XYZEval<T> operator/ (const float &v) { XYZEval<T> ls = *this; ls.x /= v; ls.y /= v; ls.z /= v; ls.e /= v; return ls; } FI XYZEval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y); return *this; }
FI XYZEval<T> operator/ (const int &v) const { XYZEval<T> ls = *this; ls.x /= v; ls.y /= v; ls.z /= v; ls.e /= v; return ls; } FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; }
FI XYZEval<T> operator/ (const int &v) { XYZEval<T> ls = *this; ls.x /= v; ls.y /= v; ls.z /= v; ls.e /= v; return ls; }
FI XYZEval<T> operator>>(const int &v) const { XYZEval<T> ls = *this; _RS(ls.x); _RS(ls.y); _RS(ls.z); _RS(ls.e); return ls; } // Override other operators to get intuitive behaviors
FI XYZEval<T> operator>>(const int &v) { XYZEval<T> ls = *this; _RS(ls.x); _RS(ls.y); _RS(ls.z); _RS(ls.e); return ls; } FI XYZEval<T> operator+ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
FI XYZEval<T> operator<<(const int &v) const { XYZEval<T> ls = *this; _LS(ls.x); _LS(ls.y); _LS(ls.z); _LS(ls.e); return ls; } FI XYZEval<T> operator+ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
FI XYZEval<T> operator<<(const int &v) { XYZEval<T> ls = *this; _LS(ls.x); _LS(ls.y); _LS(ls.z); _LS(ls.e); return ls; } FI XYZEval<T> operator- (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
FI XYZEval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; } FI XYZEval<T> operator- (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
FI XYZEval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; } FI XYZEval<T> operator* (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
FI XYZEval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; } FI XYZEval<T> operator* (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
FI XYZEval<T>& operator/=(const XYval<T> &rs) { x /= rs.x; y /= rs.y; return *this; } FI XYZEval<T> operator/ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYZEval<T>& operator+=(const XYZval<T> &rs) { x += rs.x; y += rs.y; z += rs.z; return *this; } FI XYZEval<T> operator/ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYZEval<T>& operator-=(const XYZval<T> &rs) { x -= rs.x; y -= rs.y; z -= rs.z; return *this; } FI XYZEval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; }
FI XYZEval<T>& operator*=(const XYZval<T> &rs) { x *= rs.x; y *= rs.y; z *= rs.z; return *this; } FI XYZEval<T> operator+ (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; }
FI XYZEval<T>& operator/=(const XYZval<T> &rs) { x /= rs.x; y /= rs.y; z /= rs.z; return *this; } FI XYZEval<T> operator- (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; }
FI XYZEval<T>& operator+=(const XYZEval<T> &rs) { x += rs.x; y += rs.y; z += rs.z; e += rs.e; return *this; } FI XYZEval<T> operator- (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; }
FI XYZEval<T>& operator-=(const XYZEval<T> &rs) { x -= rs.x; y -= rs.y; z -= rs.z; e -= rs.e; return *this; } FI XYZEval<T> operator* (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; }
FI XYZEval<T>& operator*=(const XYZEval<T> &rs) { x *= rs.x; y *= rs.y; z *= rs.z; e *= rs.e; return *this; } FI XYZEval<T> operator* (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; }
FI XYZEval<T>& operator/=(const XYZEval<T> &rs) { x /= rs.x; y /= rs.y; z /= rs.z; e /= rs.e; return *this; } FI XYZEval<T> operator/ (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; }
FI XYZEval<T>& operator*=(const T &v) { x *= v; y *= v; z *= v; e *= v; return *this; } FI XYZEval<T> operator/ (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; }
FI XYZEval<T>& operator>>=(const int &v) { _RS(x); _RS(y); _RS(z); _RS(e); return *this; } FI XYZEval<T> operator+ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; }
FI XYZEval<T>& operator<<=(const int &v) { _LS(x); _LS(y); _LS(z); _LS(e); return *this; } FI XYZEval<T> operator+ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; }
FI bool operator==(const XYZval<T> &rs) { return x == rs.x && y == rs.y && z == rs.z; } FI XYZEval<T> operator- (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; }
FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); } FI XYZEval<T> operator- (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; }
FI bool operator==(const XYZval<T> &rs) const { return x == rs.x && y == rs.y && z == rs.z; } FI XYZEval<T> operator* (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); } FI XYZEval<T> operator* (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; }
FI XYZEval<T> operator-() { return { -x, -y, -z, -e }; } FI XYZEval<T> operator/ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; }
FI const XYZEval<T> operator-() const { return { -x, -y, -z, -e }; } FI XYZEval<T> operator/ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; }
FI XYZEval<T> operator* (const float &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; }
FI XYZEval<T> operator* (const float &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; }
FI XYZEval<T> operator* (const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; }
FI XYZEval<T> operator* (const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; }
FI XYZEval<T> operator/ (const float &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; }
FI XYZEval<T> operator/ (const float &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; }
FI XYZEval<T> operator/ (const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; }
FI XYZEval<T> operator/ (const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; }
FI XYZEval<T> operator>>(const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; }
FI XYZEval<T> operator>>(const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; }
FI XYZEval<T> operator<<(const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; }
FI XYZEval<T> operator<<(const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; }
FI const XYZEval<T> operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k); }
FI XYZEval<T> operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k); }
// Modifier operators
FI XYZEval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; }
FI XYZEval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
FI XYZEval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
FI XYZEval<T>& operator/=(const XYval<T> &rs) { x /= rs.x; y /= rs.y; return *this; }
FI XYZEval<T>& operator+=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; }
FI XYZEval<T>& operator-=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; }
FI XYZEval<T>& operator*=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; }
FI XYZEval<T>& operator/=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; }
FI XYZEval<T>& operator+=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e += rs.e, x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; }
FI XYZEval<T>& operator-=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e -= rs.e, x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; }
FI XYZEval<T>& operator*=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e *= rs.e, x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; }
FI XYZEval<T>& operator/=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e /= rs.e, x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; }
FI XYZEval<T>& operator*=(const T &v) { LOGICAL_AXIS_CODE(e *= v, x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; }
FI XYZEval<T>& operator>>=(const int &v) { LOGICAL_AXIS_CODE(_RS(e), _RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k)); return *this; }
FI XYZEval<T>& operator<<=(const int &v) { LOGICAL_AXIS_CODE(_LS(e), _LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYZval<T> &rs) { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); }
FI bool operator==(const XYZval<T> &rs) const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); }
FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
}; };
#undef _RECIP #undef _RECIP
@@ -516,6 +666,3 @@ struct XYZEval {
#undef _LS #undef _LS
#undef _RS #undef _RS
#undef FI #undef FI
const xyze_char_t axis_codes { 'X', 'Y', 'Z', 'E' };
#define XYZ_CHAR(A) ((char)('X' + A))

View File

@@ -122,10 +122,10 @@ void safe_delay(millis_t ms) {
SERIAL_ECHOLNPAIR("Z Fade: ", planner.z_fade_height); SERIAL_ECHOLNPAIR("Z Fade: ", planner.z_fade_height);
#endif #endif
#if ABL_PLANAR #if ABL_PLANAR
SERIAL_ECHOPGM("ABL Adjustment X"); SERIAL_ECHOPGM("ABL Adjustment");
LOOP_XYZ(a) { LOOP_LINEAR_AXES(a) {
const float v = planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]; const float v = planner.get_axis_position_mm(AxisEnum(a)) - current_position[a];
SERIAL_CHAR(' ', XYZ_CHAR(a)); SERIAL_CHAR(' ', AXIS_CHAR(a));
if (v > 0) SERIAL_CHAR('+'); if (v > 0) SERIAL_CHAR('+');
SERIAL_DECIMAL(v); SERIAL_DECIMAL(v);
} }

View File

@@ -76,3 +76,11 @@ public:
// Converts from an uint8_t in the range of 0-255 to an uint8_t // Converts from an uint8_t in the range of 0-255 to an uint8_t
// in the range 0-100 while avoiding rounding artifacts // in the range 0-100 while avoiding rounding artifacts
constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; } constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; }
const xyze_char_t axis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', AXIS4_NAME, AXIS5_NAME, AXIS6_NAME);
#if LINEAR_AXES <= XYZ
#define AXIS_CHAR(A) ((char)('X' + A))
#else
#define AXIS_CHAR(A) axis_codes[A]
#endif

View File

@@ -0,0 +1,54 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../inc/MarlinConfig.h"
#if ENABLED(I2C_AMMETER)
#include "ammeter.h"
#ifndef I2C_AMMETER_IMAX
#define I2C_AMMETER_IMAX 0.500 // Calibration range 500 Milliamps
#endif
INA226 ina;
Ammeter ammeter;
float Ammeter::scale;
float Ammeter::current;
void Ammeter::init() {
ina.begin();
ina.configure(INA226_AVERAGES_16, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
ina.calibrate(I2C_AMMETER_SHUNT_RESISTOR, I2C_AMMETER_IMAX);
}
float Ammeter::read() {
scale = 1;
current = ina.readShuntCurrent();
if (current <= 0.0001f) current = 0; // Clean up least-significant-bit amplification errors
if (current < 0.1f) scale = 1000;
return current * scale;
}
#endif // I2C_AMMETER

View File

@@ -0,0 +1,39 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../inc/MarlinConfigPre.h"
#include <Wire.h>
#include <INA226.h>
class Ammeter {
private:
static float scale;
public:
static float current;
static void init();
static float read();
};
extern Ammeter ammeter;

View File

@@ -104,7 +104,7 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
const float f_corr = float(correction) / 255.0f; const float f_corr = float(correction) / 255.0f;
LOOP_XYZ(axis) { LOOP_LINEAR_AXES(axis) {
if (distance_mm[axis]) { if (distance_mm[axis]) {
const bool reversing = TEST(dm,axis); const bool reversing = TEST(dm,axis);

View File

@@ -24,7 +24,7 @@
#include "../../inc/MarlinConfigPre.h" #include "../../inc/MarlinConfigPre.h"
#if EITHER(RESTORE_LEVELING_AFTER_G28, ENABLE_LEVELING_AFTER_G28) #if EITHER(RESTORE_LEVELING_AFTER_G28, ENABLE_LEVELING_AFTER_G28)
#define G28_L0_ENSURES_LEVELING_OFF 1 #define CAN_SET_LEVELING_AFTER_G28 1
#endif #endif
#if ENABLED(PROBE_MANUALLY) #if ENABLED(PROBE_MANUALLY)

View File

@@ -103,9 +103,7 @@ public:
} }
static float get_z(const xy_pos_t &pos static float get_z(const xy_pos_t &pos
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) OPTARG(ENABLE_LEVELING_FADE_HEIGHT, const_float_t factor=1.0f)
, const_float_t factor=1.0f
#endif
) { ) {
#if DISABLED(ENABLE_LEVELING_FADE_HEIGHT) #if DISABLED(ENABLE_LEVELING_FADE_HEIGHT)
constexpr float factor = 1.0f; constexpr float factor = 1.0f;

View File

@@ -164,7 +164,7 @@ static void serial_echo_column_labels(const uint8_t sp) {
* 2: TODO: Display on Graphical LCD * 2: TODO: Display on Graphical LCD
* 4: Compact Human-Readable * 4: Compact Human-Readable
*/ */
void unified_bed_leveling::display_map(const int map_type) { void unified_bed_leveling::display_map(const uint8_t map_type) {
const bool was = gcode.set_autoreport_paused(true); const bool was = gcode.set_autoreport_paused(true);
constexpr uint8_t eachsp = 1 + 6 + 1, // [-3.567] constexpr uint8_t eachsp = 1 + 6 + 1, // [-3.567]
@@ -263,7 +263,7 @@ bool unified_bed_leveling::sanity_check() {
void GcodeSuite::M1004() { void GcodeSuite::M1004() {
#define ALIGN_GCODE TERN(Z_STEPPER_AUTO_ALIGN, "G34", "") #define ALIGN_GCODE TERN(Z_STEPPER_AUTO_ALIGN, "G34", "")
#define PROBE_GCODE TERN(HAS_BED_PROBE, "G29P1\nG29P3", "G29P4R255") #define PROBE_GCODE TERN(HAS_BED_PROBE, "G29P1\nG29P3", "G29P4R")
#if HAS_HOTEND #if HAS_HOTEND
if (parser.seenval('H')) { // Handle H# parameter to set Hotend temp if (parser.seenval('H')) { // Handle H# parameter to set Hotend temp

View File

@@ -47,10 +47,10 @@ struct mesh_index_pair;
typedef struct { typedef struct {
bool C_seen; bool C_seen;
int8_t V_verbosity, int8_t KLS_storage_slot;
uint8_t R_repetition,
V_verbosity,
P_phase, P_phase,
R_repetition,
KLS_storage_slot,
T_map_type; T_map_type;
float B_shim_thickness, float B_shim_thickness,
C_constant; C_constant;
@@ -98,7 +98,7 @@ public:
static void report_state(); static void report_state();
static void save_ubl_active_state_and_disable(); static void save_ubl_active_state_and_disable();
static void restore_ubl_active_state_and_leave(); static void restore_ubl_active_state_and_leave();
static void display_map(const int) _O0; static void display_map(const uint8_t) _O0;
static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const xy_pos_t&, const bool=false, MeshFlags *done_flags=nullptr) _O0; static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const xy_pos_t&, const bool=false, MeshFlags *done_flags=nullptr) _O0;
static mesh_index_pair find_furthest_invalid_mesh_point() _O0; static mesh_index_pair find_furthest_invalid_mesh_point() _O0;
static void reset(); static void reset();

View File

@@ -305,7 +305,7 @@ void unified_bed_leveling::G29() {
bool probe_deployed = false; bool probe_deployed = false;
if (G29_parse_parameters()) return; // Abort on parameter error if (G29_parse_parameters()) return; // Abort on parameter error
const int8_t p_val = parser.intval('P', -1); const uint8_t p_val = parser.byteval('P');
const bool may_move = p_val == 1 || p_val == 2 || p_val == 4 || parser.seen_test('J'); const bool may_move = p_val == 1 || p_val == 2 || p_val == 4 || parser.seen_test('J');
#if ENABLED(HAS_MULTI_HOTEND) #if ENABLED(HAS_MULTI_HOTEND)
const uint8_t old_tool_index = active_extruder; const uint8_t old_tool_index = active_extruder;
@@ -321,7 +321,7 @@ void unified_bed_leveling::G29() {
// Invalidate one or more nearby mesh points, possibly all. // Invalidate one or more nearby mesh points, possibly all.
if (parser.seen('I')) { if (parser.seen('I')) {
int16_t count = parser.has_value() ? parser.value_int() : 1; uint8_t count = parser.has_value() ? parser.value_byte() : 1;
bool invalidate_all = count >= GRID_MAX_POINTS; bool invalidate_all = count >= GRID_MAX_POINTS;
if (!invalidate_all) { if (!invalidate_all) {
while (count--) { while (count--) {
@@ -345,7 +345,7 @@ void unified_bed_leveling::G29() {
} }
if (parser.seen('Q')) { if (parser.seen('Q')) {
const int test_pattern = parser.has_value() ? parser.value_int() : -99; const int16_t test_pattern = parser.has_value() ? parser.value_int() : -99;
if (!WITHIN(test_pattern, -1, 2)) { if (!WITHIN(test_pattern, -1, 2)) {
SERIAL_ECHOLNPGM("Invalid test_pattern value. (-1 to 2)\n"); SERIAL_ECHOLNPGM("Invalid test_pattern value. (-1 to 2)\n");
return; return;
@@ -581,7 +581,7 @@ void unified_bed_leveling::G29() {
// use cases for the users. So we can wait and see what to do with it. // use cases for the users. So we can wait and see what to do with it.
// //
if (parser.seen_test('K')) // Kompare Current Mesh Data to Specified Stored Mesh if (parser.seen('K')) // Kompare Current Mesh Data to Specified Stored Mesh
g29_compare_current_mesh_to_stored_mesh(); g29_compare_current_mesh_to_stored_mesh();
#endif // UBL_DEVEL_DEBUGGING #endif // UBL_DEVEL_DEBUGGING
@@ -592,7 +592,7 @@ void unified_bed_leveling::G29() {
// //
if (parser.seen('L')) { // Load Current Mesh Data if (parser.seen('L')) { // Load Current Mesh Data
param.KLS_storage_slot = parser.has_value() ? parser.value_int() : storage_slot; param.KLS_storage_slot = parser.has_value() ? (int8_t)parser.value_int() : storage_slot;
int16_t a = settings.calc_num_meshes(); int16_t a = settings.calc_num_meshes();
@@ -617,10 +617,10 @@ void unified_bed_leveling::G29() {
// //
if (parser.seen('S')) { // Store (or Save) Current Mesh Data if (parser.seen('S')) { // Store (or Save) Current Mesh Data
param.KLS_storage_slot = parser.has_value() ? parser.value_int() : storage_slot; param.KLS_storage_slot = parser.has_value() ? (int8_t)parser.value_int() : storage_slot;
if (param.KLS_storage_slot == -1) // Special case, the user wants to 'Export' the mesh to the if (param.KLS_storage_slot == -1) // Special case: 'Export' the mesh to the
return report_current_mesh(); // host program to be saved on the user's computer return report_current_mesh(); // host so it can be saved in a file.
int16_t a = settings.calc_num_meshes(); int16_t a = settings.calc_num_meshes();
@@ -673,7 +673,7 @@ void unified_bed_leveling::G29() {
*/ */
void unified_bed_leveling::adjust_mesh_to_mean(const bool cflag, const_float_t offset) { void unified_bed_leveling::adjust_mesh_to_mean(const bool cflag, const_float_t offset) {
float sum = 0; float sum = 0;
int n = 0; uint8_t n = 0;
GRID_LOOP(x, y) GRID_LOOP(x, y)
if (!isnan(z_values[x][y])) { if (!isnan(z_values[x][y])) {
sum += z_values[x][y]; sum += z_values[x][y];
@@ -734,7 +734,7 @@ void unified_bed_leveling::shift_mesh_height() {
do { do {
if (do_ubl_mesh_map) display_map(param.T_map_type); if (do_ubl_mesh_map) display_map(param.T_map_type);
const int point_num = (GRID_MAX_POINTS) - count + 1; const uint8_t point_num = (GRID_MAX_POINTS - count) + 1;
SERIAL_ECHOLNPAIR("Probing mesh point ", point_num, "/", GRID_MAX_POINTS, "."); SERIAL_ECHOLNPAIR("Probing mesh point ", point_num, "/", GRID_MAX_POINTS, ".");
TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_MESH), point_num, int(GRID_MAX_POINTS))); TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_MESH), point_num, int(GRID_MAX_POINTS)));
@@ -1025,7 +1025,7 @@ void set_message_with_feedback(PGM_P const msg_P) {
SET_SOFT_ENDSTOP_LOOSE(true); SET_SOFT_ENDSTOP_LOOSE(true);
do { do {
idle(); idle_no_sleep();
new_z = ui.ubl_mesh_value(); 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, do_blocking_move_to_z(h_offset + new_z)); // Move the nozzle as the point is edited
SERIAL_FLUSH(); // Prevent host M105 buffer overrun. SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
@@ -1083,7 +1083,7 @@ bool unified_bed_leveling::G29_parse_parameters() {
param.R_repetition = 0; param.R_repetition = 0;
if (parser.seen('R')) { if (parser.seen('R')) {
param.R_repetition = parser.has_value() ? parser.value_int() : GRID_MAX_POINTS; param.R_repetition = parser.has_value() ? parser.value_byte() : GRID_MAX_POINTS;
NOMORE(param.R_repetition, GRID_MAX_POINTS); NOMORE(param.R_repetition, GRID_MAX_POINTS);
if (param.R_repetition < 1) { if (param.R_repetition < 1) {
SERIAL_ECHOLNPGM("?(R)epetition count invalid (1+).\n"); SERIAL_ECHOLNPGM("?(R)epetition count invalid (1+).\n");
@@ -1091,14 +1091,14 @@ bool unified_bed_leveling::G29_parse_parameters() {
} }
} }
param.V_verbosity = parser.intval('V'); param.V_verbosity = parser.byteval('V');
if (!WITHIN(param.V_verbosity, 0, 4)) { if (!WITHIN(param.V_verbosity, 0, 4)) {
SERIAL_ECHOLNPGM("?(V)erbose level implausible (0-4).\n"); SERIAL_ECHOLNPGM("?(V)erbose level implausible (0-4).\n");
err_flag = true; err_flag = true;
} }
if (parser.seen('P')) { if (parser.seen('P')) {
const int pv = parser.value_int(); const uint8_t pv = parser.value_byte();
#if !HAS_BED_PROBE #if !HAS_BED_PROBE
if (pv == 1) { if (pv == 1) {
SERIAL_ECHOLNPGM("G29 P1 requires a probe.\n"); SERIAL_ECHOLNPGM("G29 P1 requires a probe.\n");
@@ -1181,7 +1181,7 @@ bool unified_bed_leveling::G29_parse_parameters() {
} }
#endif #endif
param.T_map_type = parser.intval('T'); param.T_map_type = parser.byteval('T');
if (!WITHIN(param.T_map_type, 0, 2)) { if (!WITHIN(param.T_map_type, 0, 2)) {
SERIAL_ECHOLNPGM("Invalid map type.\n"); SERIAL_ECHOLNPGM("Invalid map type.\n");
return UBL_ERR; return UBL_ERR;
@@ -1833,7 +1833,7 @@ void unified_bed_leveling::smart_fill_mesh() {
return; return;
} }
param.KLS_storage_slot = parser.value_int(); param.KLS_storage_slot = (int8_t)parser.value_int();
float tmp_z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; float tmp_z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
settings.load_mesh(param.KLS_storage_slot, &tmp_z_values); settings.load_mesh(param.KLS_storage_slot, &tmp_z_values);

View File

@@ -113,20 +113,22 @@
const xy_float_t ad = sign * dist; const xy_float_t ad = sign * dist;
const bool use_x_dist = ad.x > ad.y; const bool use_x_dist = ad.x > ad.y;
float on_axis_distance = use_x_dist ? dist.x : dist.y, float on_axis_distance = use_x_dist ? dist.x : dist.y;
e_position = end.e - start.e,
z_position = end.z - start.z;
const float e_normalized_dist = e_position / on_axis_distance, // Allow divide by zero const float z_normalized_dist = (end.z - start.z) / on_axis_distance; // Allow divide by zero
z_normalized_dist = z_position / on_axis_distance; #if HAS_EXTRUDERS
const float e_normalized_dist = (end.e - start.e) / on_axis_distance;
const bool inf_normalized_flag = isinf(e_normalized_dist);
#endif
xy_int8_t icell = istart; xy_int8_t icell = istart;
const float ratio = dist.y / dist.x, // Allow divide by zero const float ratio = dist.y / dist.x, // Allow divide by zero
c = start.y - ratio * start.x; c = start.y - ratio * start.x;
const bool inf_normalized_flag = isinf(e_normalized_dist), const bool inf_ratio_flag = isinf(ratio);
inf_ratio_flag = isinf(ratio);
xyze_pos_t dest; // Stores XYZE for segmented moves
/** /**
* Handle vertical lines that stay within one column. * Handle vertical lines that stay within one column.
@@ -143,34 +145,36 @@
* For others the next X is the same so this can continue. * For others the next X is the same so this can continue.
* Calculate X at the next Y mesh line. * Calculate X at the next Y mesh line.
*/ */
const float rx = inf_ratio_flag ? start.x : (next_mesh_line_y - c) / ratio; dest.x = inf_ratio_flag ? start.x : (next_mesh_line_y - c) / ratio;
float z0 = z_correction_for_x_on_horizontal_mesh_line(rx, icell.x, icell.y) float z0 = z_correction_for_x_on_horizontal_mesh_line(dest.x, icell.x, icell.y)
* planner.fade_scaling_factor_for_z(end.z); * planner.fade_scaling_factor_for_z(end.z);
// Undefined parts of the Mesh in z_values[][] are NAN. // Undefined parts of the Mesh in z_values[][] are NAN.
// Replace NAN corrections with 0.0 to prevent NAN propagation. // Replace NAN corrections with 0.0 to prevent NAN propagation.
if (isnan(z0)) z0 = 0.0; if (isnan(z0)) z0 = 0.0;
const float ry = mesh_index_to_ypos(icell.y); dest.y = mesh_index_to_ypos(icell.y);
/** /**
* Without this check, it's possible to generate a zero length move, as in the case where * Without this check, it's possible to generate a zero length move, as in the case where
* the line is heading down, starting exactly on a mesh line boundary. Since this is rare * the line is heading down, starting exactly on a mesh line boundary. Since this is rare
* it might be fine to remove this check and let planner.buffer_segment() filter it out. * it might be fine to remove this check and let planner.buffer_segment() filter it out.
*/ */
if (ry != start.y) { if (dest.y != start.y) {
if (!inf_normalized_flag) { // fall-through faster than branch if (!inf_normalized_flag) { // fall-through faster than branch
on_axis_distance = use_x_dist ? rx - start.x : ry - start.y; on_axis_distance = use_x_dist ? dest.x - start.x : dest.y - start.y;
e_position = start.e + on_axis_distance * e_normalized_dist; TERN_(HAS_EXTRUDERS, dest.e = start.e + on_axis_distance * e_normalized_dist);
z_position = start.z + on_axis_distance * z_normalized_dist; dest.z = start.z + on_axis_distance * z_normalized_dist;
} }
else { else {
e_position = end.e; TERN_(HAS_EXTRUDERS, dest.e = end.e);
z_position = end.z; dest.z = end.z;
} }
planner.buffer_segment(rx, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder); dest.z += z0;
planner.buffer_segment(dest, scaled_fr_mm_s, extruder);
} //else printf("FIRST MOVE PRUNED "); } //else printf("FIRST MOVE PRUNED ");
} }
@@ -188,12 +192,13 @@
*/ */
if (iadd.y == 0) { // Horizontal line? if (iadd.y == 0) { // Horizontal line?
icell.x += ineg.x; // Heading left? Just go to the left edge of the cell for the first move. icell.x += ineg.x; // Heading left? Just go to the left edge of the cell for the first move.
while (icell.x != iend.x + ineg.x) { while (icell.x != iend.x + ineg.x) {
icell.x += iadd.x; icell.x += iadd.x;
const float rx = mesh_index_to_xpos(icell.x); dest.x = mesh_index_to_xpos(icell.x);
const float ry = ratio * rx + c; // Calculate Y at the next X mesh line dest.y = ratio * dest.x + c; // Calculate Y at the next X mesh line
float z0 = z_correction_for_y_on_vertical_mesh_line(ry, icell.x, icell.y) float z0 = z_correction_for_y_on_vertical_mesh_line(dest.y, icell.x, icell.y)
* planner.fade_scaling_factor_for_z(end.z); * planner.fade_scaling_factor_for_z(end.z);
// Undefined parts of the Mesh in z_values[][] are NAN. // Undefined parts of the Mesh in z_values[][] are NAN.
@@ -205,19 +210,20 @@
* the line is heading left, starting exactly on a mesh line boundary. Since this is rare * the line is heading left, starting exactly on a mesh line boundary. Since this is rare
* it might be fine to remove this check and let planner.buffer_segment() filter it out. * it might be fine to remove this check and let planner.buffer_segment() filter it out.
*/ */
if (rx != start.x) { if (dest.x != start.x) {
if (!inf_normalized_flag) { if (!inf_normalized_flag) {
on_axis_distance = use_x_dist ? rx - start.x : ry - start.y; on_axis_distance = use_x_dist ? dest.x - start.x : dest.y - start.y;
e_position = start.e + on_axis_distance * e_normalized_dist; // is based on X or Y because this is a horizontal move TERN_(HAS_EXTRUDERS, dest.e = start.e + on_axis_distance * e_normalized_dist); // Based on X or Y because the move is horizontal
z_position = start.z + on_axis_distance * z_normalized_dist; dest.z = start.z + on_axis_distance * z_normalized_dist;
} }
else { else {
e_position = end.e; TERN_(HAS_EXTRUDERS, dest.e = end.e);
z_position = end.z; dest.z = end.z;
} }
if (!planner.buffer_segment(rx, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder)) dest.z += z0;
break; if (!planner.buffer_segment(dest, scaled_fr_mm_s, extruder)) break;
} //else printf("FIRST MOVE PRUNED "); } //else printf("FIRST MOVE PRUNED ");
} }
@@ -239,57 +245,65 @@
while (cnt) { while (cnt) {
const float next_mesh_line_x = mesh_index_to_xpos(icell.x + iadd.x), const float next_mesh_line_x = mesh_index_to_xpos(icell.x + iadd.x),
next_mesh_line_y = mesh_index_to_ypos(icell.y + iadd.y), next_mesh_line_y = mesh_index_to_ypos(icell.y + iadd.y);
ry = ratio * next_mesh_line_x + c, // Calculate Y at the next X mesh line
rx = (next_mesh_line_y - c) / ratio; // Calculate X at the next Y mesh line
// (No need to worry about ratio == 0.
// In that case, it was already detected
// as a vertical line move above.)
if (neg.x == (rx > next_mesh_line_x)) { // Check if we hit the Y line first dest.y = ratio * next_mesh_line_x + c; // Calculate Y at the next X mesh line
dest.x = (next_mesh_line_y - c) / ratio; // Calculate X at the next Y mesh line
// (No need to worry about ratio == 0.
// In that case, it was already detected
// as a vertical line move above.)
if (neg.x == (dest.x > next_mesh_line_x)) { // Check if we hit the Y line first
// Yes! Crossing a Y Mesh Line next // Yes! Crossing a Y Mesh Line next
float z0 = z_correction_for_x_on_horizontal_mesh_line(rx, icell.x - ineg.x, icell.y + iadd.y) float z0 = z_correction_for_x_on_horizontal_mesh_line(dest.x, icell.x - ineg.x, icell.y + iadd.y)
* planner.fade_scaling_factor_for_z(end.z); * planner.fade_scaling_factor_for_z(end.z);
// Undefined parts of the Mesh in z_values[][] are NAN. // Undefined parts of the Mesh in z_values[][] are NAN.
// Replace NAN corrections with 0.0 to prevent NAN propagation. // Replace NAN corrections with 0.0 to prevent NAN propagation.
if (isnan(z0)) z0 = 0.0; if (isnan(z0)) z0 = 0.0;
dest.y = next_mesh_line_y;
if (!inf_normalized_flag) { if (!inf_normalized_flag) {
on_axis_distance = use_x_dist ? rx - start.x : next_mesh_line_y - start.y; on_axis_distance = use_x_dist ? dest.x - start.x : dest.y - start.y;
e_position = start.e + on_axis_distance * e_normalized_dist; TERN_(HAS_EXTRUDERS, dest.e = start.e + on_axis_distance * e_normalized_dist);
z_position = start.z + on_axis_distance * z_normalized_dist; dest.z = start.z + on_axis_distance * z_normalized_dist;
} }
else { else {
e_position = end.e; TERN_(HAS_EXTRUDERS, dest.e = end.e);
z_position = end.z; dest.z = end.z;
} }
if (!planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, scaled_fr_mm_s, extruder))
break; dest.z += z0;
if (!planner.buffer_segment(dest, scaled_fr_mm_s, extruder)) break;
icell.y += iadd.y; icell.y += iadd.y;
cnt.y--; cnt.y--;
} }
else { else {
// Yes! Crossing a X Mesh Line next // Yes! Crossing a X Mesh Line next
float z0 = z_correction_for_y_on_vertical_mesh_line(ry, icell.x + iadd.x, icell.y - ineg.y) float z0 = z_correction_for_y_on_vertical_mesh_line(dest.y, icell.x + iadd.x, icell.y - ineg.y)
* planner.fade_scaling_factor_for_z(end.z); * planner.fade_scaling_factor_for_z(end.z);
// Undefined parts of the Mesh in z_values[][] are NAN. // Undefined parts of the Mesh in z_values[][] are NAN.
// Replace NAN corrections with 0.0 to prevent NAN propagation. // Replace NAN corrections with 0.0 to prevent NAN propagation.
if (isnan(z0)) z0 = 0.0; if (isnan(z0)) z0 = 0.0;
dest.x = next_mesh_line_x;
if (!inf_normalized_flag) { if (!inf_normalized_flag) {
on_axis_distance = use_x_dist ? next_mesh_line_x - start.x : ry - start.y; on_axis_distance = use_x_dist ? dest.x - start.x : dest.y - start.y;
e_position = start.e + on_axis_distance * e_normalized_dist; TERN_(HAS_EXTRUDERS, dest.e = start.e + on_axis_distance * e_normalized_dist);
z_position = start.z + on_axis_distance * z_normalized_dist; dest.z = start.z + on_axis_distance * z_normalized_dist;
} }
else { else {
e_position = end.e; TERN_(HAS_EXTRUDERS, dest.e = end.e);
z_position = end.z; dest.z = end.z;
} }
if (!planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, scaled_fr_mm_s, extruder)) dest.z += z0;
break; if (!planner.buffer_segment(dest, scaled_fr_mm_s, extruder)) break;
icell.x += iadd.x; icell.x += iadd.x;
cnt.x--; cnt.x--;
} }
@@ -362,15 +376,11 @@
while (--segments) { while (--segments) {
raw += diff; raw += diff;
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
#if ENABLED(SCARA_FEEDRATE_SCALING) OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
, inv_duration
#endif
); );
} }
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, segment_xyz_mm planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, segment_xyz_mm
#if ENABLED(SCARA_FEEDRATE_SCALING) OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
, inv_duration
#endif
); );
return false; // Did not set current from destination return false; // Did not set current from destination
} }
@@ -442,11 +452,9 @@
#endif #endif
; ;
planner.buffer_line(raw.x, raw.y, raw.z + z_cxcy, raw.e, scaled_fr_mm_s, active_extruder, segment_xyz_mm const float oldz = raw.z; raw.z += z_cxcy;
#if ENABLED(SCARA_FEEDRATE_SCALING) planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration) );
, inv_duration raw.z = oldz;
#endif
);
if (segments == 0) // done with last segment if (segments == 0) // done with last segment
return false; // didn't set current from destination return false; // didn't set current from destination

View File

@@ -24,9 +24,11 @@
#include "../inc/MarlinConfig.h" #include "../inc/MarlinConfig.h"
#define BINARY_STREAM_COMPRESSION #define BINARY_STREAM_COMPRESSION
#if ENABLED(BINARY_STREAM_COMPRESSION) #if ENABLED(BINARY_STREAM_COMPRESSION)
#include "../libs/heatshrink/heatshrink_decoder.h" #include "../libs/heatshrink/heatshrink_decoder.h"
// STM32 (and others?) require a word-aligned buffer for SD card transfers via DMA
static __attribute__((aligned(sizeof(size_t)))) uint8_t decode_buffer[512] = {};
static heatshrink_decoder hsd;
#endif #endif
inline bool bs_serial_data_available(const serial_index_t index) { inline bool bs_serial_data_available(const serial_index_t index) {
@@ -37,16 +39,6 @@ inline int bs_read_serial(const serial_index_t index) {
return SERIAL_IMPL.read(index); return SERIAL_IMPL.read(index);
} }
#if ENABLED(BINARY_STREAM_COMPRESSION)
static heatshrink_decoder hsd;
#if BOTH(ARDUINO_ARCH_STM32F1, SDIO_SUPPORT)
// STM32 requires a word-aligned buffer for SD card transfers via DMA
static __attribute__((aligned(sizeof(size_t)))) uint8_t decode_buffer[512] = {};
#else
static uint8_t decode_buffer[512] = {};
#endif
#endif
class SDFileTransferProtocol { class SDFileTransferProtocol {
private: private:
struct Packet { struct Packet {

View File

@@ -41,11 +41,7 @@ bool CaseLight::on = CASE_LIGHT_DEFAULT_ON;
#if CASE_LIGHT_IS_COLOR_LED #if CASE_LIGHT_IS_COLOR_LED
#include "leds/leds.h" #include "leds/leds.h"
constexpr uint8_t init_case_light[] = CASE_LIGHT_DEFAULT_COLOR; constexpr uint8_t init_case_light[] = CASE_LIGHT_DEFAULT_COLOR;
LEDColor CaseLight::color = { init_case_light[0], init_case_light[1], init_case_light[2], TERN_(HAS_WHITE_LED, init_case_light[3]) }; LEDColor CaseLight::color = { init_case_light[0], init_case_light[1], init_case_light[2] OPTARG(HAS_WHITE_LED, init_case_light[3]) };
#endif
#ifndef INVERT_CASE_LIGHT
#define INVERT_CASE_LIGHT false
#endif #endif
void CaseLight::update(const bool sflag) { void CaseLight::update(const bool sflag) {
@@ -64,14 +60,12 @@ void CaseLight::update(const bool sflag) {
if (sflag && on) if (sflag && on)
brightness = brightness_sav; // Restore last brightness for M355 S1 brightness = brightness_sav; // Restore last brightness for M355 S1
const uint8_t i = on ? brightness : 0, n10ct = INVERT_CASE_LIGHT ? 255 - i : i; const uint8_t i = on ? brightness : 0, n10ct = ENABLED(INVERT_CASE_LIGHT) ? 255 - i : i;
UNUSED(n10ct); UNUSED(n10ct);
#endif #endif
#if CASE_LIGHT_IS_COLOR_LED #if CASE_LIGHT_IS_COLOR_LED
leds.set_color(LEDColor(color.r, color.g, color.b OPTARG(HAS_WHITE_LED, color.w), n10ct));
leds.set_color(MakeLEDColor(color.r, color.g, color.b, color.w, n10ct));
#else // !CASE_LIGHT_IS_COLOR_LED #else // !CASE_LIGHT_IS_COLOR_LED
#if CASELIGHT_USES_BRIGHTNESS #if CASELIGHT_USES_BRIGHTNESS
@@ -86,7 +80,7 @@ void CaseLight::update(const bool sflag) {
else else
#endif #endif
{ {
const bool s = on ? !INVERT_CASE_LIGHT : INVERT_CASE_LIGHT; const bool s = on ? TERN(INVERT_CASE_LIGHT, LOW, HIGH) : TERN(INVERT_CASE_LIGHT, HIGH, LOW);
WRITE(CASE_LIGHT_PIN, s ? HIGH : LOW); WRITE(CASE_LIGHT_PIN, s ? HIGH : LOW);
} }

View File

@@ -78,10 +78,8 @@ public:
// Get the total flow (in liters per minute) since the last reading // Get the total flow (in liters per minute) since the last reading
static void calc_flowrate() { static void calc_flowrate() {
//flowmeter_interrupt_disable(); // flowrate = (litres) * (seconds) = litres per minute
// const uint16_t pulses = flowpulses; flowrate = (flowpulses / (float)FLOWMETER_PPL) * ((1000.0f / (float)FLOWMETER_INTERVAL) * 60.0f);
//flowmeter_interrupt_enable();
flowrate = flowpulses * 60.0f * (1000.0f / (FLOWMETER_INTERVAL)) * (1000.0f / (FLOWMETER_PPL));
flowpulses = 0; flowpulses = 0;
} }

View File

@@ -73,7 +73,7 @@ uint8_t MCP4728::analogWrite(const uint8_t channel, const uint16_t value) {
uint8_t MCP4728::eepromWrite() { uint8_t MCP4728::eepromWrite() {
Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS)); Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS));
Wire.write(SEQWRITE); Wire.write(SEQWRITE);
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
Wire.write(DAC_STEPPER_VREF << 7 | DAC_STEPPER_GAIN << 4 | highByte(dac_values[i])); Wire.write(DAC_STEPPER_VREF << 7 | DAC_STEPPER_GAIN << 4 | highByte(dac_values[i]));
Wire.write(lowByte(dac_values[i])); Wire.write(lowByte(dac_values[i]));
} }
@@ -135,7 +135,7 @@ void MCP4728::setDrvPct(xyze_uint_t &pct) {
*/ */
uint8_t MCP4728::fastWrite() { uint8_t MCP4728::fastWrite() {
Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS)); Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS));
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
Wire.write(highByte(dac_values[i])); Wire.write(highByte(dac_values[i]));
Wire.write(lowByte(dac_values[i])); Wire.write(lowByte(dac_values[i]));
} }

View File

@@ -51,7 +51,7 @@ int StepperDAC::init() {
mcp4728.setVref_all(DAC_STEPPER_VREF); mcp4728.setVref_all(DAC_STEPPER_VREF);
mcp4728.setGain_all(DAC_STEPPER_GAIN); mcp4728.setGain_all(DAC_STEPPER_GAIN);
if (mcp4728.getDrvPct(0) < 1 || mcp4728.getDrvPct(1) < 1 || mcp4728.getDrvPct(2) < 1 || mcp4728.getDrvPct(3) < 1 ) { if (mcp4728.getDrvPct(0) < 1 || mcp4728.getDrvPct(1) < 1 || mcp4728.getDrvPct(2) < 1 || mcp4728.getDrvPct(3) < 1) {
mcp4728.setDrvPct(dac_channel_pct); mcp4728.setDrvPct(dac_channel_pct);
mcp4728.eepromWrite(); mcp4728.eepromWrite();
} }
@@ -77,7 +77,7 @@ static float dac_amps(int8_t n) { return mcp4728.getValue(dac_order[n]) * 0.125
uint8_t StepperDAC::get_current_percent(const AxisEnum axis) { return mcp4728.getDrvPct(dac_order[axis]); } uint8_t StepperDAC::get_current_percent(const AxisEnum axis) { return mcp4728.getDrvPct(dac_order[axis]); }
void StepperDAC::set_current_percents(xyze_uint8_t &pct) { void StepperDAC::set_current_percents(xyze_uint8_t &pct) {
LOOP_XYZE(i) dac_channel_pct[i] = pct[dac_order[i]]; LOOP_LOGICAL_AXES(i) dac_channel_pct[i] = pct[dac_order[i]];
mcp4728.setDrvPct(dac_channel_pct); mcp4728.setDrvPct(dac_channel_pct);
} }
@@ -85,10 +85,16 @@ void StepperDAC::print_values() {
if (!dac_present) return; if (!dac_present) return;
SERIAL_ECHO_MSG("Stepper current values in % (Amps):"); SERIAL_ECHO_MSG("Stepper current values in % (Amps):");
SERIAL_ECHO_START(); SERIAL_ECHO_START();
SERIAL_ECHOPAIR_P( SP_X_LBL, dac_perc(X_AXIS), PSTR(" ("), dac_amps(X_AXIS), PSTR(")")); SERIAL_ECHOPAIR_P(SP_X_LBL, dac_perc(X_AXIS), PSTR(" ("), dac_amps(X_AXIS), PSTR(")"));
SERIAL_ECHOPAIR_P( SP_Y_LBL, dac_perc(Y_AXIS), PSTR(" ("), dac_amps(Y_AXIS), PSTR(")")); #if HAS_Y_AXIS
SERIAL_ECHOPAIR_P( SP_Z_LBL, dac_perc(Z_AXIS), PSTR(" ("), dac_amps(Z_AXIS), PSTR(")")); SERIAL_ECHOPAIR_P(SP_Y_LBL, dac_perc(Y_AXIS), PSTR(" ("), dac_amps(Y_AXIS), PSTR(")"));
SERIAL_ECHOLNPAIR_P(SP_E_LBL, dac_perc(E_AXIS), PSTR(" ("), dac_amps(E_AXIS), PSTR(")")); #endif
#if HAS_Z_AXIS
SERIAL_ECHOPAIR_P(SP_Z_LBL, dac_perc(Z_AXIS), PSTR(" ("), dac_amps(Z_AXIS), PSTR(")"));
#endif
#if HAS_EXTRUDERS
SERIAL_ECHOLNPAIR_P(SP_E_LBL, dac_perc(E_AXIS), PSTR(" ("), dac_amps(E_AXIS), PSTR(")"));
#endif
} }
void StepperDAC::commit_eeprom() { void StepperDAC::commit_eeprom() {

View File

@@ -327,7 +327,7 @@ int32_t I2CPositionEncoder::get_raw_count() {
} }
bool I2CPositionEncoder::test_axis() { bool I2CPositionEncoder::test_axis() {
//only works on XYZ cartesian machines for the time being // Only works on XYZ Cartesian machines for the time being
if (!(encoderAxis == X_AXIS || encoderAxis == Y_AXIS || encoderAxis == Z_AXIS)) return false; if (!(encoderAxis == X_AXIS || encoderAxis == Y_AXIS || encoderAxis == Z_AXIS)) return false;
const float startPosition = soft_endstop.min[encoderAxis] + 10, const float startPosition = soft_endstop.min[encoderAxis] + 10,
@@ -337,7 +337,7 @@ bool I2CPositionEncoder::test_axis() {
ec = false; ec = false;
xyze_pos_t startCoord, endCoord; xyze_pos_t startCoord, endCoord;
LOOP_XYZ(a) { LOOP_LINEAR_AXES(a) {
startCoord[a] = planner.get_axis_position_mm((AxisEnum)a); startCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
endCoord[a] = planner.get_axis_position_mm((AxisEnum)a); endCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
} }
@@ -345,9 +345,12 @@ bool I2CPositionEncoder::test_axis() {
endCoord[encoderAxis] = endPosition; endCoord[encoderAxis] = endPosition;
planner.synchronize(); planner.synchronize();
startCoord.e = planner.get_axis_position_mm(E_AXIS);
planner.buffer_line(startCoord, fr_mm_s, 0); #if HAS_EXTRUDERS
planner.synchronize(); startCoord.e = planner.get_axis_position_mm(E_AXIS);
planner.buffer_line(startCoord, fr_mm_s, 0);
planner.synchronize();
#endif
// if the module isn't currently trusted, wait until it is (or until it should be if things are working) // if the module isn't currently trusted, wait until it is (or until it should be if things are working)
if (!trusted) { if (!trusted) {
@@ -357,7 +360,7 @@ bool I2CPositionEncoder::test_axis() {
} }
if (trusted) { // if trusted, commence test if (trusted) { // if trusted, commence test
endCoord.e = planner.get_axis_position_mm(E_AXIS); TERN_(HAS_EXTRUDERS, endCoord.e = planner.get_axis_position_mm(E_AXIS));
planner.buffer_line(endCoord, fr_mm_s, 0); planner.buffer_line(endCoord, fr_mm_s, 0);
planner.synchronize(); planner.synchronize();
} }
@@ -392,7 +395,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
travelDistance = endDistance - startDistance; travelDistance = endDistance - startDistance;
xyze_pos_t startCoord, endCoord; xyze_pos_t startCoord, endCoord;
LOOP_XYZ(a) { LOOP_LINEAR_AXES(a) {
startCoord[a] = planner.get_axis_position_mm((AxisEnum)a); startCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
endCoord[a] = planner.get_axis_position_mm((AxisEnum)a); endCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
} }
@@ -402,7 +405,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
planner.synchronize(); planner.synchronize();
LOOP_L_N(i, iter) { LOOP_L_N(i, iter) {
startCoord.e = planner.get_axis_position_mm(E_AXIS); TERN_(HAS_EXTRUDERS, startCoord.e = planner.get_axis_position_mm(E_AXIS));
planner.buffer_line(startCoord, fr_mm_s, 0); planner.buffer_line(startCoord, fr_mm_s, 0);
planner.synchronize(); planner.synchronize();
@@ -411,7 +414,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
//do_blocking_move_to(endCoord); //do_blocking_move_to(endCoord);
endCoord.e = planner.get_axis_position_mm(E_AXIS); TERN_(HAS_EXTRUDERS, endCoord.e = planner.get_axis_position_mm(E_AXIS));
planner.buffer_line(endCoord, fr_mm_s, 0); planner.buffer_line(endCoord, fr_mm_s, 0);
planner.synchronize(); planner.synchronize();
@@ -497,9 +500,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true)); encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_1_AXIS == E_AXIS TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_1_AXIS == E_AXIS) encoders[i].set_homed());
encoders[i].set_homed();
#endif
#endif #endif
#if I2CPE_ENCODER_CNT > 1 #if I2CPE_ENCODER_CNT > 1
@@ -528,9 +529,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true)); encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_2_AXIS == E_AXIS TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_2_AXIS == E_AXIS) encoders[i].set_homed());
encoders[i].set_homed();
#endif
#endif #endif
#if I2CPE_ENCODER_CNT > 2 #if I2CPE_ENCODER_CNT > 2
@@ -557,11 +556,9 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_ec_threshold(I2CPE_ENC_3_EC_THRESH); encoders[i].set_ec_threshold(I2CPE_ENC_3_EC_THRESH);
#endif #endif
encoders[i].set_active(encoders[i].passes_test(true)); encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_3_AXIS == E_AXIS TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_3_AXIS == E_AXIS) encoders[i].set_homed());
encoders[i].set_homed();
#endif
#endif #endif
#if I2CPE_ENCODER_CNT > 3 #if I2CPE_ENCODER_CNT > 3
@@ -590,9 +587,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true)); encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_4_AXIS == E_AXIS TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_4_AXIS == E_AXIS) encoders[i].set_homed());
encoders[i].set_homed();
#endif
#endif #endif
#if I2CPE_ENCODER_CNT > 4 #if I2CPE_ENCODER_CNT > 4
@@ -621,9 +616,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true)); encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_5_AXIS == E_AXIS TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_5_AXIS == E_AXIS) encoders[i].set_homed());
encoders[i].set_homed();
#endif
#endif #endif
#if I2CPE_ENCODER_CNT > 5 #if I2CPE_ENCODER_CNT > 5
@@ -652,9 +645,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true)); encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_6_AXIS == E_AXIS TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_6_AXIS == E_AXIS) encoders[i].set_homed());
encoders[i].set_homed();
#endif
#endif #endif
} }
@@ -822,7 +813,7 @@ void I2CPositionEncodersMgr::M860() {
const bool hasU = parser.seen_test('U'), hasO = parser.seen_test('O'); const bool hasU = parser.seen_test('U'), hasO = parser.seen_test('O');
if (I2CPE_idx == 0xFF) { if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen_test(axis_codes[i])) { if (!I2CPE_anyaxis || parser.seen_test(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i)); const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_position(idx, hasU, hasO); if ((int8_t)idx >= 0) report_position(idx, hasU, hasO);
@@ -849,7 +840,7 @@ void I2CPositionEncodersMgr::M861() {
if (parse()) return; if (parse()) return;
if (I2CPE_idx == 0xFF) { if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i)); const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_status(idx); if ((int8_t)idx >= 0) report_status(idx);
@@ -877,7 +868,7 @@ void I2CPositionEncodersMgr::M862() {
if (parse()) return; if (parse()) return;
if (I2CPE_idx == 0xFF) { if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i)); const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) test_axis(idx); if ((int8_t)idx >= 0) test_axis(idx);
@@ -908,7 +899,7 @@ void I2CPositionEncodersMgr::M863() {
const uint8_t iterations = constrain(parser.byteval('P', 1), 1, 10); const uint8_t iterations = constrain(parser.byteval('P', 1), 1, 10);
if (I2CPE_idx == 0xFF) { if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i)); const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) calibrate_steps_mm(idx, iterations); if ((int8_t)idx >= 0) calibrate_steps_mm(idx, iterations);
@@ -984,7 +975,7 @@ void I2CPositionEncodersMgr::M865() {
if (parse()) return; if (parse()) return;
if (!I2CPE_addr) { if (!I2CPE_addr) {
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i)); const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_module_firmware(encoders[idx].get_address()); if ((int8_t)idx >= 0) report_module_firmware(encoders[idx].get_address());
@@ -1015,7 +1006,7 @@ void I2CPositionEncodersMgr::M866() {
const bool hasR = parser.seen_test('R'); const bool hasR = parser.seen_test('R');
if (I2CPE_idx == 0xFF) { if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i)); const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) { if ((int8_t)idx >= 0) {
@@ -1053,7 +1044,7 @@ void I2CPositionEncodersMgr::M867() {
const int8_t onoff = parser.seenval('S') ? parser.value_int() : -1; const int8_t onoff = parser.seenval('S') ? parser.value_int() : -1;
if (I2CPE_idx == 0xFF) { if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i)); const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) { if ((int8_t)idx >= 0) {
@@ -1089,7 +1080,7 @@ void I2CPositionEncodersMgr::M868() {
const float newThreshold = parser.seenval('T') ? parser.value_float() : -9999; const float newThreshold = parser.seenval('T') ? parser.value_float() : -9999;
if (I2CPE_idx == 0xFF) { if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i)); const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) { if ((int8_t)idx >= 0) {
@@ -1123,7 +1114,7 @@ void I2CPositionEncodersMgr::M869() {
if (parse()) return; if (parse()) return;
if (I2CPE_idx == 0xFF) { if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i)); const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_error(idx); if ((int8_t)idx >= 0) report_error(idx);

View File

@@ -91,11 +91,7 @@ void FWRetract::reset() {
* Note: Auto-retract will apply the set Z hop in addition to any Z hop * Note: Auto-retract will apply the set Z hop in addition to any Z hop
* included in the G-code. Use M207 Z0 to to prevent double hop. * included in the G-code. Use M207 Z0 to to prevent double hop.
*/ */
void FWRetract::retract(const bool retracting void FWRetract::retract(const bool retracting OPTARG(HAS_MULTI_EXTRUDER, bool swapping/*=false*/)) {
#if HAS_MULTI_EXTRUDER
, bool swapping/*=false*/
#endif
) {
// Prevent two retracts or recovers in a row // Prevent two retracts or recovers in a row
if (retracted[active_extruder] == retracting) return; if (retracted[active_extruder] == retracting) return;

View File

@@ -74,11 +74,7 @@ public:
#endif #endif
} }
static void retract(const bool retracting static void retract(const bool retracting OPTARG(HAS_MULTI_EXTRUDER, bool swapping = false));
#if HAS_MULTI_EXTRUDER
, bool swapping = false
#endif
);
static void M207(); static void M207();
static void M207_report(const bool forReplay=false); static void M207_report(const bool forReplay=false);

View File

@@ -163,7 +163,7 @@ Joystick joystick;
// norm_jog values of [-1 .. 1] maps linearly to [-feedrate .. feedrate] // norm_jog values of [-1 .. 1] maps linearly to [-feedrate .. feedrate]
xyz_float_t move_dist{0}; xyz_float_t move_dist{0};
float hypot2 = 0; float hypot2 = 0;
LOOP_XYZ(i) if (norm_jog[i]) { LOOP_LINEAR_AXES(i) if (norm_jog[i]) {
move_dist[i] = seg_time * norm_jog[i] * TERN(EXTENSIBLE_UI, manual_feedrate_mm_s, planner.settings.max_feedrate_mm_s)[i]; move_dist[i] = seg_time * norm_jog[i] * TERN(EXTENSIBLE_UI, manual_feedrate_mm_s, planner.settings.max_feedrate_mm_s)[i];
hypot2 += sq(move_dist[i]); hypot2 += sq(move_dist[i]);
} }

View File

@@ -47,9 +47,10 @@
#endif #endif
#if ENABLED(LED_COLOR_PRESETS) #if ENABLED(LED_COLOR_PRESETS)
const LEDColor LEDLights::defaultLEDColor = MakeLEDColor( const LEDColor LEDLights::defaultLEDColor = LEDColor(
LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE, LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE
LED_USER_PRESET_WHITE, LED_USER_PRESET_BRIGHTNESS OPTARG(HAS_WHITE_LED, LED_USER_PRESET_WHITE)
OPTARG(NEOPIXEL_LED, LED_USER_PRESET_BRIGHTNESS)
); );
#endif #endif
@@ -75,36 +76,35 @@ void LEDLights::setup() {
} }
void LEDLights::set_color(const LEDColor &incol void LEDLights::set_color(const LEDColor &incol
#if ENABLED(NEOPIXEL_LED) OPTARG(NEOPIXEL_IS_SEQUENTIAL, bool isSequence/*=false*/)
, bool isSequence/*=false*/
#endif
) { ) {
#if ENABLED(NEOPIXEL_LED) #if ENABLED(NEOPIXEL_LED)
const uint32_t neocolor = LEDColorWhite() == incol const uint32_t neocolor = LEDColorWhite() == incol
? neo.Color(NEO_WHITE) ? neo.Color(NEO_WHITE)
: neo.Color(incol.r, incol.g, incol.b, incol.w); : neo.Color(incol.r, incol.g, incol.b OPTARG(HAS_WHITE_LED, incol.w));
static uint16_t nextLed = 0;
#ifdef NEOPIXEL_BKGD_LED_INDEX #if ENABLED(NEOPIXEL_IS_SEQUENTIAL)
if (NEOPIXEL_BKGD_LED_INDEX == nextLed) { static uint16_t nextLed = 0;
neo.set_color_background(); #ifdef NEOPIXEL_BKGD_INDEX_FIRST
if (++nextLed >= neo.pixels()) { while (WITHIN(nextLed, NEOPIXEL_BKGD_INDEX_FIRST, NEOPIXEL_BKGD_INDEX_LAST)) {
nextLed = 0; neo.reset_background_color();
return; if (++nextLed >= neo.pixels()) { nextLed = 0; return; }
} }
} #endif
#endif #endif
neo.set_brightness(incol.i); neo.set_brightness(incol.i);
if (isSequence) { #if ENABLED(NEOPIXEL_IS_SEQUENTIAL)
neo.set_pixel_color(nextLed, neocolor); if (isSequence) {
neo.show(); neo.set_pixel_color(nextLed, neocolor);
if (++nextLed >= neo.pixels()) nextLed = 0; neo.show();
return; if (++nextLed >= neo.pixels()) nextLed = 0;
} return;
}
#endif
neo.set_color(neocolor); neo.set_color(neocolor);
@@ -169,9 +169,10 @@ void LEDLights::set_color(const LEDColor &incol
#if ENABLED(NEOPIXEL2_SEPARATE) #if ENABLED(NEOPIXEL2_SEPARATE)
#if ENABLED(NEO2_COLOR_PRESETS) #if ENABLED(NEO2_COLOR_PRESETS)
const LEDColor LEDLights2::defaultLEDColor = MakeLEDColor( const LEDColor LEDLights2::defaultLEDColor = LEDColor(
NEO2_USER_PRESET_RED, NEO2_USER_PRESET_GREEN, NEO2_USER_PRESET_BLUE, LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE
NEO2_USER_PRESET_WHITE, NEO2_USER_PRESET_BRIGHTNESS OPTARG(HAS_WHITE_LED2, LED_USER_PRESET_WHITE)
OPTARG(NEOPIXEL_LED, LED_USER_PRESET_BRIGHTNESS)
); );
#endif #endif
@@ -190,7 +191,7 @@ void LEDLights::set_color(const LEDColor &incol
void LEDLights2::set_color(const LEDColor &incol) { void LEDLights2::set_color(const LEDColor &incol) {
const uint32_t neocolor = LEDColorWhite() == incol const uint32_t neocolor = LEDColorWhite() == incol
? neo2.Color(NEO2_WHITE) ? neo2.Color(NEO2_WHITE)
: neo2.Color(incol.r, incol.g, incol.b, incol.w); : neo2.Color(incol.r, incol.g, incol.b OPTARG(HAS_WHITE_LED2, incol.w));
neo2.set_brightness(incol.i); neo2.set_brightness(incol.i);
neo2.set_color(neocolor); neo2.set_color(neocolor);

View File

@@ -29,13 +29,15 @@
#include <string.h> #include <string.h>
#if ENABLED(NEOPIXEL_LED) // A white component can be passed
#include "neopixel.h" #if EITHER(RGBW_LED, PCA9632_RGBW)
#define HAS_WHITE_LED 1
#endif #endif
// A white component can be passed #if ENABLED(NEOPIXEL_LED)
#if ANY(RGBW_LED, NEOPIXEL_LED, PCA9632_RGBW) #define _NEOPIXEL_INCLUDE_
#define HAS_WHITE_LED 1 #include "neopixel.h"
#undef _NEOPIXEL_INCLUDE_
#endif #endif
/** /**
@@ -43,46 +45,21 @@
*/ */
typedef struct LEDColor { typedef struct LEDColor {
uint8_t r, g, b uint8_t r, g, b
#if HAS_WHITE_LED OPTARG(HAS_WHITE_LED, w)
, w OPTARG(NEOPIXEL_LED, i)
#if ENABLED(NEOPIXEL_LED)
, i
#endif
#endif
; ;
LEDColor() : r(255), g(255), b(255) LEDColor() : r(255), g(255), b(255)
#if HAS_WHITE_LED OPTARG(HAS_WHITE_LED, w(255))
, w(255) OPTARG(NEOPIXEL_LED, i(NEOPIXEL_BRIGHTNESS))
#if ENABLED(NEOPIXEL_LED)
, i(NEOPIXEL_BRIGHTNESS)
#endif
#endif
{} {}
LEDColor(uint8_t r, uint8_t g, uint8_t b LEDColor(uint8_t r, uint8_t g, uint8_t b OPTARG(HAS_WHITE_LED, uint8_t w=0) OPTARG(NEOPIXEL_LED, uint8_t i=NEOPIXEL_BRIGHTNESS))
#if HAS_WHITE_LED : r(r), g(g), b(b) OPTARG(HAS_WHITE_LED, w(w)) OPTARG(NEOPIXEL_LED, i(i)) {}
, uint8_t w=0
#if ENABLED(NEOPIXEL_LED)
, uint8_t i=NEOPIXEL_BRIGHTNESS
#endif
#endif
) : r(r), g(g), b(b)
#if HAS_WHITE_LED
, w(w)
#if ENABLED(NEOPIXEL_LED)
, i(i)
#endif
#endif
{}
LEDColor(const uint8_t (&rgbw)[4]) : r(rgbw[0]), g(rgbw[1]), b(rgbw[2]) LEDColor(const uint8_t (&rgbw)[4]) : r(rgbw[0]), g(rgbw[1]), b(rgbw[2])
#if HAS_WHITE_LED OPTARG(HAS_WHITE_LED, w(rgbw[3]))
, w(rgbw[3]) OPTARG(NEOPIXEL_LED, i(NEOPIXEL_BRIGHTNESS))
#if ENABLED(NEOPIXEL_LED)
, i(NEOPIXEL_BRIGHTNESS)
#endif
#endif
{} {}
LEDColor& operator=(const uint8_t (&rgbw)[4]) { LEDColor& operator=(const uint8_t (&rgbw)[4]) {
@@ -109,17 +86,8 @@ typedef struct LEDColor {
} LEDColor; } LEDColor;
/** /**
* Color helpers and presets * Color presets
*/ */
#if HAS_WHITE_LED
#if ENABLED(NEOPIXEL_LED)
#define MakeLEDColor(R,G,B,W,I) LEDColor(R, G, B, W, I)
#else
#define MakeLEDColor(R,G,B,W,I) LEDColor(R, G, B, W)
#endif
#else
#define MakeLEDColor(R,G,B,W,I) LEDColor(R, G, B)
#endif
#define LEDColorOff() LEDColor( 0, 0, 0) #define LEDColorOff() LEDColor( 0, 0, 0)
#define LEDColorRed() LEDColor(255, 0, 0) #define LEDColorRed() LEDColor(255, 0, 0)
@@ -147,25 +115,15 @@ public:
static void setup(); // init() static void setup(); // init()
static void set_color(const LEDColor &color static void set_color(const LEDColor &color
#if ENABLED(NEOPIXEL_LED) OPTARG(NEOPIXEL_IS_SEQUENTIAL, bool isSequence=false)
, bool isSequence=false
#endif
); );
static inline void set_color(uint8_t r, uint8_t g, uint8_t b static inline void set_color(uint8_t r, uint8_t g, uint8_t b
#if HAS_WHITE_LED OPTARG(HAS_WHITE_LED, uint8_t w=0)
, uint8_t w=0 OPTARG(NEOPIXEL_LED, uint8_t i=NEOPIXEL_BRIGHTNESS)
#endif OPTARG(NEOPIXEL_IS_SEQUENTIAL, bool isSequence=false)
#if ENABLED(NEOPIXEL_LED)
, uint8_t i=NEOPIXEL_BRIGHTNESS
, bool isSequence=false
#endif
) { ) {
set_color(MakeLEDColor(r, g, b, w, i) set_color(LEDColor(r, g, b OPTARG(HAS_WHITE_LED, w) OPTARG(NEOPIXEL_LED, i)) OPTARG(NEOPIXEL_IS_SEQUENTIAL, isSequence));
#if ENABLED(NEOPIXEL_LED)
, isSequence
#endif
);
} }
static inline void set_off() { set_color(LEDColorOff()); } static inline void set_off() { set_color(LEDColorOff()); }
@@ -223,8 +181,14 @@ extern LEDLights leds;
static void set_color(const LEDColor &color); static void set_color(const LEDColor &color);
inline void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0, uint8_t i=NEOPIXEL2_BRIGHTNESS) { static inline void set_color(uint8_t r, uint8_t g, uint8_t b
set_color(MakeLEDColor(r, g, b, w, i)); OPTARG(HAS_WHITE_LED, uint8_t w=0)
OPTARG(NEOPIXEL_LED, uint8_t i=NEOPIXEL_BRIGHTNESS)
) {
set_color(LEDColor(r, g, b
OPTARG(HAS_WHITE_LED, w)
OPTARG(NEOPIXEL_LED, i)
));
} }
static inline void set_off() { set_color(LEDColorOff()); } static inline void set_off() { set_color(LEDColorOff()); }

View File

@@ -28,7 +28,7 @@
#if ENABLED(NEOPIXEL_LED) #if ENABLED(NEOPIXEL_LED)
#include "neopixel.h" #include "leds.h"
#if EITHER(NEOPIXEL_STARTUP_TEST, NEOPIXEL2_STARTUP_TEST) #if EITHER(NEOPIXEL_STARTUP_TEST, NEOPIXEL2_STARTUP_TEST)
#include "../../core/utility.h" #include "../../core/utility.h"
@@ -37,17 +37,21 @@
Marlin_NeoPixel neo; Marlin_NeoPixel neo;
int8_t Marlin_NeoPixel::neoindex; int8_t Marlin_NeoPixel::neoindex;
Adafruit_NeoPixel Marlin_NeoPixel::adaneo1(NEOPIXEL_PIXELS, NEOPIXEL_PIN, NEOPIXEL_TYPE + NEO_KHZ800) Adafruit_NeoPixel Marlin_NeoPixel::adaneo1(NEOPIXEL_PIXELS, NEOPIXEL_PIN, NEOPIXEL_TYPE + NEO_KHZ800);
#if CONJOINED_NEOPIXEL #if CONJOINED_NEOPIXEL
, Marlin_NeoPixel::adaneo2(NEOPIXEL_PIXELS, NEOPIXEL2_PIN, NEOPIXEL2_TYPE + NEO_KHZ800) Adafruit_NeoPixel Marlin_NeoPixel::adaneo2(NEOPIXEL_PIXELS, NEOPIXEL2_PIN, NEOPIXEL2_TYPE + NEO_KHZ800);
#endif #endif
;
#ifdef NEOPIXEL_BKGD_LED_INDEX #ifdef NEOPIXEL_BKGD_INDEX_FIRST
void Marlin_NeoPixel::set_color_background() { void Marlin_NeoPixel::set_background_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
uint8_t background_color[4] = NEOPIXEL_BKGD_COLOR; for (int background_led = NEOPIXEL_BKGD_INDEX_FIRST; background_led <= NEOPIXEL_BKGD_INDEX_LAST; background_led++)
set_pixel_color(NEOPIXEL_BKGD_LED_INDEX, adaneo1.Color(background_color[0], background_color[1], background_color[2], background_color[3])); set_pixel_color(background_led, adaneo1.Color(r, g, b, w));
}
void Marlin_NeoPixel::reset_background_color() {
constexpr uint8_t background_color[4] = NEOPIXEL_BKGD_COLOR;
set_background_color(background_color[0], background_color[1], background_color[2], background_color[3]);
} }
#endif #endif
@@ -59,9 +63,10 @@ void Marlin_NeoPixel::set_color(const uint32_t color) {
} }
else { else {
for (uint16_t i = 0; i < pixels(); ++i) { for (uint16_t i = 0; i < pixels(); ++i) {
#ifdef NEOPIXEL_BKGD_LED_INDEX #ifdef NEOPIXEL_BKGD_INDEX_FIRST
if (i == NEOPIXEL_BKGD_LED_INDEX && TERN(NEOPIXEL_BKGD_ALWAYS_ON, true, color != 0x000000)) { if (i == NEOPIXEL_BKGD_INDEX_FIRST && TERN(NEOPIXEL_BKGD_ALWAYS_ON, true, color != 0x000000)) {
set_color_background(); reset_background_color();
i += NEOPIXEL_BKGD_INDEX_LAST - (NEOPIXEL_BKGD_INDEX_FIRST);
continue; continue;
} }
#endif #endif
@@ -90,36 +95,23 @@ void Marlin_NeoPixel::init() {
safe_delay(500); safe_delay(500);
set_color_startup(adaneo1.Color(0, 0, 255, 0)); // blue set_color_startup(adaneo1.Color(0, 0, 255, 0)); // blue
safe_delay(500); safe_delay(500);
#if HAS_WHITE_LED
set_color_startup(adaneo1.Color(0, 0, 0, 255)); // white
safe_delay(500);
#endif
#endif #endif
#ifdef NEOPIXEL_BKGD_LED_INDEX #ifdef NEOPIXEL_BKGD_INDEX_FIRST
set_color_background(); reset_background_color();
#endif #endif
#if ENABLED(LED_USER_PRESET_STARTUP) set_color(adaneo1.Color
set_color(adaneo1.Color(LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE, LED_USER_PRESET_WHITE)); TERN(LED_USER_PRESET_STARTUP,
#else (LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE, LED_USER_PRESET_WHITE),
set_color(adaneo1.Color(0, 0, 0, 0)); (0, 0, 0, 0))
#endif );
} }
#if 0
bool Marlin_NeoPixel::set_led_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t w, const uint8_t p) {
const uint32_t color = adaneo1.Color(r, g, b, w);
set_brightness(p);
#if DISABLED(NEOPIXEL_IS_SEQUENTIAL)
set_color(color);
return false;
#else
static uint16_t nextLed = 0;
set_pixel_color(nextLed, color);
show();
if (++nextLed >= pixels()) nextLed = 0;
return true;
#endif
}
#endif
#if ENABLED(NEOPIXEL2_SEPARATE) #if ENABLED(NEOPIXEL2_SEPARATE)
Marlin_NeoPixel2 neo2; Marlin_NeoPixel2 neo2;
@@ -158,13 +150,17 @@ bool Marlin_NeoPixel::set_led_color(const uint8_t r, const uint8_t g, const uint
safe_delay(500); safe_delay(500);
set_color_startup(adaneo.Color(0, 0, 255, 0)); // blue set_color_startup(adaneo.Color(0, 0, 255, 0)); // blue
safe_delay(500); safe_delay(500);
#if HAS_WHITE_LED2
set_color_startup(adaneo.Color(0, 0, 0, 255)); // white
safe_delay(500);
#endif
#endif #endif
#if ENABLED(NEO2_USER_PRESET_STARTUP) set_color(adaneo.Color
set_color(adaneo.Color(NEO2_USER_PRESET_RED, NEO2_USER_PRESET_GREEN, NEO2_USER_PRESET_BLUE, NEO2_USER_PRESET_WHITE)); TERN(NEO2_USER_PRESET_STARTUP,
#else (NEO2_USER_PRESET_RED, NEO2_USER_PRESET_GREEN, NEO2_USER_PRESET_BLUE, NEO2_USER_PRESET_WHITE),
set_color(adaneo.Color(0, 0, 0, 0)); (0, 0, 0, 0))
#endif );
} }
#endif // NEOPIXEL2_SEPARATE #endif // NEOPIXEL2_SEPARATE

View File

@@ -25,6 +25,10 @@
* NeoPixel support * NeoPixel support
*/ */
#ifndef _NEOPIXEL_INCLUDE_
#error "Always include 'leds.h' and not 'neopixel.h' directly."
#endif
// ------------------------ // ------------------------
// Includes // Includes
// ------------------------ // ------------------------
@@ -38,6 +42,18 @@
// Defines // Defines
// ------------------------ // ------------------------
#define _NEO_IS_RGB(N) (N == NEO_RGB || N == NEO_RBG || N == NEO_GRB || N == NEO_GBR || N == NEO_BRG || N == NEO_BGR)
#if !_NEO_IS_RGB(NEOPIXEL_TYPE)
#define HAS_WHITE_LED 1
#endif
#if HAS_WHITE_LED
#define NEO_WHITE 0, 0, 0, 255
#else
#define NEO_WHITE 255, 255, 255
#endif
#if defined(NEOPIXEL2_TYPE) && NEOPIXEL2_TYPE != NEOPIXEL_TYPE && DISABLED(NEOPIXEL2_SEPARATE) #if defined(NEOPIXEL2_TYPE) && NEOPIXEL2_TYPE != NEOPIXEL_TYPE && DISABLED(NEOPIXEL2_SEPARATE)
#define MULTIPLE_NEOPIXEL_TYPES 1 #define MULTIPLE_NEOPIXEL_TYPES 1
#endif #endif
@@ -46,29 +62,16 @@
#define CONJOINED_NEOPIXEL 1 #define CONJOINED_NEOPIXEL 1
#endif #endif
#if NEOPIXEL_TYPE == NEO_RGB || NEOPIXEL_TYPE == NEO_RBG || NEOPIXEL_TYPE == NEO_GRB || NEOPIXEL_TYPE == NEO_GBR || NEOPIXEL_TYPE == NEO_BRG || NEOPIXEL_TYPE == NEO_BGR
#define NEOPIXEL_IS_RGB 1
#else
#define NEOPIXEL_IS_RGBW 1
#endif
#if NEOPIXEL_IS_RGB
#define NEO_WHITE 255, 255, 255, 0
#else
#define NEO_WHITE 0, 0, 0, 255
#endif
// ------------------------ // ------------------------
// Function prototypes // Function prototypes
// ------------------------ // ------------------------
class Marlin_NeoPixel { class Marlin_NeoPixel {
private: private:
static Adafruit_NeoPixel adaneo1 static Adafruit_NeoPixel adaneo1;
#if CONJOINED_NEOPIXEL #if CONJOINED_NEOPIXEL
, adaneo2 static Adafruit_NeoPixel adaneo2;
#endif #endif
;
public: public:
static int8_t neoindex; static int8_t neoindex;
@@ -78,8 +81,9 @@ public:
static void set_color(const uint32_t c); static void set_color(const uint32_t c);
#ifdef NEOPIXEL_BKGD_LED_INDEX #ifdef NEOPIXEL_BKGD_INDEX_FIRST
static void set_color_background(); static void set_background_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
static void reset_background_color();
#endif #endif
static inline void begin() { static inline void begin() {
@@ -93,9 +97,7 @@ public:
else adaneo1.setPixelColor(n, c); else adaneo1.setPixelColor(n, c);
#else #else
adaneo1.setPixelColor(n, c); adaneo1.setPixelColor(n, c);
#if MULTIPLE_NEOPIXEL_TYPES TERN_(MULTIPLE_NEOPIXEL_TYPES, adaneo2.setPixelColor(n, c));
adaneo2.setPixelColor(n, c);
#endif
#endif #endif
} }
@@ -112,7 +114,6 @@ public:
#if CONJOINED_NEOPIXEL #if CONJOINED_NEOPIXEL
adaneo2.show(); adaneo2.show();
#else #else
IF_DISABLED(NEOPIXEL2_SEPARATE, adaneo1.setPin(NEOPIXEL2_PIN));
adaneo1.show(); adaneo1.show();
adaneo1.setPin(NEOPIXEL_PIN); adaneo1.setPin(NEOPIXEL_PIN);
#endif #endif
@@ -120,15 +121,13 @@ public:
TERN_(HAS_PAUSE_SERVO_OUTPUT, RESUME_SERVO_OUTPUT()); TERN_(HAS_PAUSE_SERVO_OUTPUT, RESUME_SERVO_OUTPUT());
} }
#if 0
bool set_led_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t w, const uint8_t p);
#endif
// Accessors // Accessors
static inline uint16_t pixels() { TERN(NEOPIXEL2_INSERIES, return adaneo1.numPixels() * 2, return adaneo1.numPixels()); } static inline uint16_t pixels() { return adaneo1.numPixels() * TERN1(NEOPIXEL2_INSERIES, 2); }
static inline uint8_t brightness() { return adaneo1.getBrightness(); } static inline uint8_t brightness() { return adaneo1.getBrightness(); }
static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
return adaneo1.Color(r, g, b, w); static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b OPTARG(HAS_WHITE_LED, uint8_t w)) {
return adaneo1.Color(r, g, b OPTARG(HAS_WHITE_LED, w));
} }
}; };
@@ -137,15 +136,12 @@ extern Marlin_NeoPixel neo;
// Neo pixel channel 2 // Neo pixel channel 2
#if ENABLED(NEOPIXEL2_SEPARATE) #if ENABLED(NEOPIXEL2_SEPARATE)
#if NEOPIXEL2_TYPE == NEO_RGB || NEOPIXEL2_TYPE == NEO_RBG || NEOPIXEL2_TYPE == NEO_GRB || NEOPIXEL2_TYPE == NEO_GBR || NEOPIXEL2_TYPE == NEO_BRG || NEOPIXEL2_TYPE == NEO_BGR #if _NEO_IS_RGB(NEOPIXEL2_TYPE)
#define NEOPIXEL2_IS_RGB 1 #define NEOPIXEL2_IS_RGB 1
#define NEO2_WHITE 255, 255, 255
#else #else
#define NEOPIXEL2_IS_RGBW 1 #define NEOPIXEL2_IS_RGBW 1
#endif #define HAS_WHITE_LED2 1 // A white component can be passed for NEOPIXEL2
#if NEOPIXEL2_IS_RGB
#define NEO2_WHITE 255, 255, 255, 0
#else
#define NEO2_WHITE 0, 0, 0, 255 #define NEO2_WHITE 0, 0, 0, 255
#endif #endif
@@ -172,11 +168,13 @@ extern Marlin_NeoPixel neo;
// Accessors // Accessors
static inline uint16_t pixels() { return adaneo.numPixels();} static inline uint16_t pixels() { return adaneo.numPixels();}
static inline uint8_t brightness() { return adaneo.getBrightness(); } static inline uint8_t brightness() { return adaneo.getBrightness(); }
static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b OPTARG(HAS_WHITE_LED2, uint8_t w)) {
return adaneo.Color(r, g, b, w); return adaneo.Color(r, g, b OPTARG(HAS_WHITE_LED2, w));
} }
}; };
extern Marlin_NeoPixel2 neo2; extern Marlin_NeoPixel2 neo2;
#endif // NEOPIXEL2_SEPARATE #endif // NEOPIXEL2_SEPARATE
#undef _NEO_IS_RGB

View File

@@ -93,9 +93,7 @@ static void PCA9632_WriteRegister(const byte addr, const byte regadd, const byte
} }
static void PCA9632_WriteAllRegisters(const byte addr, const byte regadd, const byte vr, const byte vg, const byte vb static void PCA9632_WriteAllRegisters(const byte addr, const byte regadd, const byte vr, const byte vg, const byte vb
#if ENABLED(PCA9632_RGBW) OPTARG(PCA9632_RGBW, const byte vw)
, const byte vw
#endif
) { ) {
#if DISABLED(PCA9632_NO_AUTO_INC) #if DISABLED(PCA9632_NO_AUTO_INC)
uint8_t data[4]; uint8_t data[4];
@@ -143,9 +141,7 @@ void PCA9632_set_led_color(const LEDColor &color) {
; ;
PCA9632_WriteAllRegisters(PCA9632_ADDRESS,PCA9632_PWM0, color.r, color.g, color.b PCA9632_WriteAllRegisters(PCA9632_ADDRESS,PCA9632_PWM0, color.r, color.g, color.b
#if ENABLED(PCA9632_RGBW) OPTARG(PCA9632_RGBW, color.w)
, color.w
#endif
); );
PCA9632_WriteRegister(PCA9632_ADDRESS,PCA9632_LEDOUT, LEDOUT); PCA9632_WriteRegister(PCA9632_ADDRESS,PCA9632_LEDOUT, LEDOUT);
} }

View File

@@ -45,12 +45,10 @@ PrinterEventLEDs printerEventLEDs;
return (uint8_t)map(constrain(current, start, target), start, target, 0, 255); return (uint8_t)map(constrain(current, start, target), start, target, 0, 255);
} }
inline void pel_set_rgb(const uint8_t r, const uint8_t g, const uint8_t b) { inline void pel_set_rgb(const uint8_t r, const uint8_t g, const uint8_t b OPTARG(HAS_WHITE_LED, const uint8_t w=0)) {
leds.set_color( leds.set_color(
MakeLEDColor(r, g, b, 0, neo.brightness()) LEDColor(r, g, b OPTARG(HAS_WHITE_LED, w) OPTARG(NEOPIXEL_LED, neo.brightness()))
#if ENABLED(NEOPIXEL_IS_SEQUENTIAL) OPTARG(NEOPIXEL_IS_SEQUENTIAL, true)
, true
#endif
); );
} }

View File

@@ -24,7 +24,14 @@
#if HAS_PRUSA_MMU1 #if HAS_PRUSA_MMU1
#include "../module/stepper.h" #include "../MarlinCore.h"
#include "../module/planner.h"
void mmu_init() {
SET_OUTPUT(E_MUX0_PIN);
SET_OUTPUT(E_MUX1_PIN);
SET_OUTPUT(E_MUX2_PIN);
}
void select_multiplexed_stepper(const uint8_t e) { void select_multiplexed_stepper(const uint8_t e) {
planner.synchronize(); planner.synchronize();

View File

@@ -21,4 +21,5 @@
*/ */
#pragma once #pragma once
void mmu_init();
void select_multiplexed_stepper(const uint8_t e); void select_multiplexed_stepper(const uint8_t e);

View File

@@ -81,7 +81,10 @@ bool Power::is_power_needed() {
#endif #endif
) return true; ) return true;
HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0 || thermalManager.temp_hotend[e].soft_pwm_amount > 0) return true; #if HAS_HOTEND
HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0 || thermalManager.temp_hotend[e].soft_pwm_amount > 0) return true;
#endif
if (TERN0(HAS_HEATED_BED, thermalManager.degTargetBed() > 0 || thermalManager.temp_bed.soft_pwm_amount > 0)) return true; if (TERN0(HAS_HEATED_BED, thermalManager.degTargetBed() > 0 || thermalManager.temp_bed.soft_pwm_amount > 0)) return true;
#if HAS_HOTEND && AUTO_POWER_E_TEMP #if HAS_HOTEND && AUTO_POWER_E_TEMP
@@ -105,12 +108,12 @@ bool Power::is_power_needed() {
void Power::check() { void Power::check() {
static millis_t nextPowerCheck = 0; static millis_t nextPowerCheck = 0;
millis_t ms = millis(); millis_t now = millis();
if (ELAPSED(ms, nextPowerCheck)) { if (ELAPSED(now, nextPowerCheck)) {
nextPowerCheck = ms + 2500UL; nextPowerCheck = now + 2500UL;
if (is_power_needed()) if (is_power_needed())
power_on(); power_on();
else if (!lastPowerOn || (POWER_TIMEOUT > 0 && ELAPSED(ms, lastPowerOn + SEC_TO_MS(POWER_TIMEOUT)))) else if (!lastPowerOn || (POWER_TIMEOUT > 0 && ELAPSED(now, lastPowerOn + SEC_TO_MS(POWER_TIMEOUT))))
power_off(); power_off();
} }
} }

View File

@@ -197,7 +197,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
#endif #endif
#endif #endif
#if EXTRUDERS #if HAS_EXTRUDERS
HOTEND_LOOP() info.target_temperature[e] = thermalManager.degTargetHotend(e); HOTEND_LOOP() info.target_temperature[e] = thermalManager.degTargetHotend(e);
#endif #endif
@@ -375,7 +375,7 @@ void PrintJobRecovery::resume() {
gcode.process_subcommands_now_P(PSTR("G92.9E0")); // Reset E to 0 gcode.process_subcommands_now_P(PSTR("G92.9E0")); // Reset E to 0
#if Z_HOME_DIR > 0 #if Z_HOME_TO_MAX
float z_now = z_raised; float z_now = z_raised;
@@ -549,7 +549,7 @@ void PrintJobRecovery::resume() {
TERN_(HAS_HOME_OFFSET, home_offset = info.home_offset); TERN_(HAS_HOME_OFFSET, home_offset = info.home_offset);
TERN_(HAS_POSITION_SHIFT, position_shift = info.position_shift); TERN_(HAS_POSITION_SHIFT, position_shift = info.position_shift);
#if HAS_HOME_OFFSET || HAS_POSITION_SHIFT #if HAS_HOME_OFFSET || HAS_POSITION_SHIFT
LOOP_XYZ(i) update_workspace_offset((AxisEnum)i); LOOP_LINEAR_AXES(i) update_workspace_offset((AxisEnum)i);
#endif #endif
// Relative axis modes // Relative axis modes
@@ -581,7 +581,7 @@ void PrintJobRecovery::resume() {
if (info.valid_head) { if (info.valid_head) {
if (info.valid_head == info.valid_foot) { if (info.valid_head == info.valid_foot) {
DEBUG_ECHOPGM("current_position: "); DEBUG_ECHOPGM("current_position: ");
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (i) DEBUG_CHAR(','); if (i) DEBUG_CHAR(',');
DEBUG_DECIMAL(info.current_position[i]); DEBUG_DECIMAL(info.current_position[i]);
} }
@@ -599,7 +599,7 @@ void PrintJobRecovery::resume() {
#if HAS_HOME_OFFSET #if HAS_HOME_OFFSET
DEBUG_ECHOPGM("home_offset: "); DEBUG_ECHOPGM("home_offset: ");
LOOP_XYZ(i) { LOOP_LINEAR_AXES(i) {
if (i) DEBUG_CHAR(','); if (i) DEBUG_CHAR(',');
DEBUG_DECIMAL(info.home_offset[i]); DEBUG_DECIMAL(info.home_offset[i]);
} }
@@ -608,7 +608,7 @@ void PrintJobRecovery::resume() {
#if HAS_POSITION_SHIFT #if HAS_POSITION_SHIFT
DEBUG_ECHOPGM("position_shift: "); DEBUG_ECHOPGM("position_shift: ");
LOOP_XYZ(i) { LOOP_LINEAR_AXES(i) {
if (i) DEBUG_CHAR(','); if (i) DEBUG_CHAR(',');
DEBUG_DECIMAL(info.position_shift[i]); DEBUG_DECIMAL(info.position_shift[i]);
} }

View File

@@ -88,7 +88,7 @@ typedef struct {
uint8_t fan_speed[FAN_COUNT]; uint8_t fan_speed[FAN_COUNT];
#endif #endif
#if ENABLED(HAS_LEVELING) #if HAS_LEVELING
float fade; float fade;
#endif #endif
@@ -120,7 +120,7 @@ typedef struct {
bool raised:1; // Raised before saved bool raised:1; // Raised before saved
bool dryrun:1; // M111 S8 bool dryrun:1; // M111 S8
bool allow_cold_extrusion:1; // M302 P1 bool allow_cold_extrusion:1; // M302 P1
#if ENABLED(HAS_LEVELING) #if HAS_LEVELING
bool leveling:1; // M420 S bool leveling:1; // M420 S
#endif #endif
#if DISABLED(NO_VOLUMETRICS) #if DISABLED(NO_VOLUMETRICS)

View File

@@ -47,7 +47,7 @@ typedef struct {
// Probe temperature calibration constants // Probe temperature calibration constants
#ifndef PTC_SAMPLE_COUNT #ifndef PTC_SAMPLE_COUNT
#define PTC_SAMPLE_COUNT 10U #define PTC_SAMPLE_COUNT 10
#endif #endif
#ifndef PTC_SAMPLE_RES #ifndef PTC_SAMPLE_RES
#define PTC_SAMPLE_RES 5 #define PTC_SAMPLE_RES 5
@@ -55,22 +55,22 @@ typedef struct {
#ifndef PTC_SAMPLE_START #ifndef PTC_SAMPLE_START
#define PTC_SAMPLE_START 30 #define PTC_SAMPLE_START 30
#endif #endif
#define PTC_SAMPLE_END ((PTC_SAMPLE_START) + (PTC_SAMPLE_COUNT) * (PTC_SAMPLE_RES)) #define PTC_SAMPLE_END (PTC_SAMPLE_START + (PTC_SAMPLE_COUNT) * PTC_SAMPLE_RES)
// Bed temperature calibration constants // Bed temperature calibration constants
#ifndef BTC_PROBE_TEMP #ifndef BTC_PROBE_TEMP
#define BTC_PROBE_TEMP 30 #define BTC_PROBE_TEMP 30
#endif #endif
#ifndef BTC_SAMPLE_COUNT #ifndef BTC_SAMPLE_COUNT
#define BTC_SAMPLE_COUNT 10U #define BTC_SAMPLE_COUNT 10
#endif #endif
#ifndef BTC_SAMPLE_STEP #ifndef BTC_SAMPLE_RES
#define BTC_SAMPLE_RES 5 #define BTC_SAMPLE_RES 5
#endif #endif
#ifndef BTC_SAMPLE_START #ifndef BTC_SAMPLE_START
#define BTC_SAMPLE_START 60 #define BTC_SAMPLE_START 60
#endif #endif
#define BTC_SAMPLE_END ((BTC_SAMPLE_START) + (BTC_SAMPLE_COUNT) * (BTC_SAMPLE_RES)) #define BTC_SAMPLE_END (BTC_SAMPLE_START + (BTC_SAMPLE_COUNT) * BTC_SAMPLE_RES)
#ifndef PTC_PROBE_HEATING_OFFSET #ifndef PTC_PROBE_HEATING_OFFSET
#define PTC_PROBE_HEATING_OFFSET 0.5f #define PTC_PROBE_HEATING_OFFSET 0.5f

View File

@@ -34,6 +34,10 @@
#include "../module/servo.h" #include "../module/servo.h"
#endif #endif
#if ENABLED(I2C_AMMETER)
#include "../feature/ammeter.h"
#endif
SpindleLaser cutter; SpindleLaser cutter;
uint8_t SpindleLaser::power; uint8_t SpindleLaser::power;
#if ENABLED(LASER_FEATURE) #if ENABLED(LASER_FEATURE)
@@ -74,6 +78,9 @@ void SpindleLaser::init() {
#if ENABLED(AIR_ASSIST) #if ENABLED(AIR_ASSIST)
OUT_WRITE(AIR_ASSIST_PIN, !AIR_ASSIST_ACTIVE); // Init Air Assist OFF OUT_WRITE(AIR_ASSIST_PIN, !AIR_ASSIST_ACTIVE); // Init Air Assist OFF
#endif #endif
#if ENABLED(I2C_AMMETER)
ammeter.init(); // Init I2C Ammeter
#endif
} }
#if ENABLED(SPINDLE_LASER_PWM) #if ENABLED(SPINDLE_LASER_PWM)

View File

@@ -211,7 +211,7 @@
SERIAL_PRINTLN(data.drv_status, HEX); SERIAL_PRINTLN(data.drv_status, HEX);
if (data.is_ot) SERIAL_ECHOLNPGM("overtemperature"); if (data.is_ot) SERIAL_ECHOLNPGM("overtemperature");
if (data.is_s2g) SERIAL_ECHOLNPGM("coil short circuit"); if (data.is_s2g) SERIAL_ECHOLNPGM("coil short circuit");
TERN_(TMC_DEBUG, tmc_report_all(true, true, true, true)); TERN_(TMC_DEBUG, tmc_report_all());
kill(PSTR("Driver error")); kill(PSTR("Driver error"));
} }
#endif #endif
@@ -417,6 +417,21 @@
} }
#endif #endif
#if AXIS_IS_TMC(I)
if (monitor_tmc_driver(stepperI, need_update_error_counters, need_debug_reporting))
step_current_down(stepperI);
#endif
#if AXIS_IS_TMC(J)
if (monitor_tmc_driver(stepperJ, need_update_error_counters, need_debug_reporting))
step_current_down(stepperJ);
#endif
#if AXIS_IS_TMC(K)
if (monitor_tmc_driver(stepperK, need_update_error_counters, need_debug_reporting))
step_current_down(stepperK);
#endif
#if AXIS_IS_TMC(E0) #if AXIS_IS_TMC(E0)
(void)monitor_tmc_driver(stepperE0, need_update_error_counters, need_debug_reporting); (void)monitor_tmc_driver(stepperE0, need_update_error_counters, need_debug_reporting);
#endif #endif
@@ -757,128 +772,148 @@
} }
} }
static void tmc_debug_loop(const TMC_debug_enum i, const bool print_x, const bool print_y, const bool print_z, const bool print_e) { static void tmc_debug_loop(const TMC_debug_enum n, LOGICAL_AXIS_ARGS(const bool)) {
if (print_x) { if (x) {
#if AXIS_IS_TMC(X) #if AXIS_IS_TMC(X)
tmc_status(stepperX, i); tmc_status(stepperX, n);
#endif #endif
#if AXIS_IS_TMC(X2) #if AXIS_IS_TMC(X2)
tmc_status(stepperX2, i); tmc_status(stepperX2, n);
#endif #endif
} }
if (print_y) { if (TERN0(HAS_Y_AXIS, y)) {
#if AXIS_IS_TMC(Y) #if AXIS_IS_TMC(Y)
tmc_status(stepperY, i); tmc_status(stepperY, n);
#endif #endif
#if AXIS_IS_TMC(Y2) #if AXIS_IS_TMC(Y2)
tmc_status(stepperY2, i); tmc_status(stepperY2, n);
#endif #endif
} }
if (print_z) { if (TERN0(HAS_Z_AXIS, z)) {
#if AXIS_IS_TMC(Z) #if AXIS_IS_TMC(Z)
tmc_status(stepperZ, i); tmc_status(stepperZ, n);
#endif #endif
#if AXIS_IS_TMC(Z2) #if AXIS_IS_TMC(Z2)
tmc_status(stepperZ2, i); tmc_status(stepperZ2, n);
#endif #endif
#if AXIS_IS_TMC(Z3) #if AXIS_IS_TMC(Z3)
tmc_status(stepperZ3, i); tmc_status(stepperZ3, n);
#endif #endif
#if AXIS_IS_TMC(Z4) #if AXIS_IS_TMC(Z4)
tmc_status(stepperZ4, i); tmc_status(stepperZ4, n);
#endif #endif
} }
if (print_e) { #if AXIS_IS_TMC(I)
if (i) tmc_status(stepperI, n);
#endif
#if AXIS_IS_TMC(J)
if (j) tmc_status(stepperJ, n);
#endif
#if AXIS_IS_TMC(K)
if (k) tmc_status(stepperK, n);
#endif
if (TERN0(HAS_EXTRUDERS, e)) {
#if AXIS_IS_TMC(E0) #if AXIS_IS_TMC(E0)
tmc_status(stepperE0, i); tmc_status(stepperE0, n);
#endif #endif
#if AXIS_IS_TMC(E1) #if AXIS_IS_TMC(E1)
tmc_status(stepperE1, i); tmc_status(stepperE1, n);
#endif #endif
#if AXIS_IS_TMC(E2) #if AXIS_IS_TMC(E2)
tmc_status(stepperE2, i); tmc_status(stepperE2, n);
#endif #endif
#if AXIS_IS_TMC(E3) #if AXIS_IS_TMC(E3)
tmc_status(stepperE3, i); tmc_status(stepperE3, n);
#endif #endif
#if AXIS_IS_TMC(E4) #if AXIS_IS_TMC(E4)
tmc_status(stepperE4, i); tmc_status(stepperE4, n);
#endif #endif
#if AXIS_IS_TMC(E5) #if AXIS_IS_TMC(E5)
tmc_status(stepperE5, i); tmc_status(stepperE5, n);
#endif #endif
#if AXIS_IS_TMC(E6) #if AXIS_IS_TMC(E6)
tmc_status(stepperE6, i); tmc_status(stepperE6, n);
#endif #endif
#if AXIS_IS_TMC(E7) #if AXIS_IS_TMC(E7)
tmc_status(stepperE7, i); tmc_status(stepperE7, n);
#endif #endif
} }
SERIAL_EOL(); SERIAL_EOL();
} }
static void drv_status_loop(const TMC_drv_status_enum i, const bool print_x, const bool print_y, const bool print_z, const bool print_e) { static void drv_status_loop(const TMC_drv_status_enum n, LOGICAL_AXIS_ARGS(const bool)) {
if (print_x) { if (x) {
#if AXIS_IS_TMC(X) #if AXIS_IS_TMC(X)
tmc_parse_drv_status(stepperX, i); tmc_parse_drv_status(stepperX, n);
#endif #endif
#if AXIS_IS_TMC(X2) #if AXIS_IS_TMC(X2)
tmc_parse_drv_status(stepperX2, i); tmc_parse_drv_status(stepperX2, n);
#endif #endif
} }
if (print_y) { if (TERN0(HAS_Y_AXIS, y)) {
#if AXIS_IS_TMC(Y) #if AXIS_IS_TMC(Y)
tmc_parse_drv_status(stepperY, i); tmc_parse_drv_status(stepperY, n);
#endif #endif
#if AXIS_IS_TMC(Y2) #if AXIS_IS_TMC(Y2)
tmc_parse_drv_status(stepperY2, i); tmc_parse_drv_status(stepperY2, n);
#endif #endif
} }
if (print_z) { if (TERN0(HAS_Z_AXIS, z)) {
#if AXIS_IS_TMC(Z) #if AXIS_IS_TMC(Z)
tmc_parse_drv_status(stepperZ, i); tmc_parse_drv_status(stepperZ, n);
#endif #endif
#if AXIS_IS_TMC(Z2) #if AXIS_IS_TMC(Z2)
tmc_parse_drv_status(stepperZ2, i); tmc_parse_drv_status(stepperZ2, n);
#endif #endif
#if AXIS_IS_TMC(Z3) #if AXIS_IS_TMC(Z3)
tmc_parse_drv_status(stepperZ3, i); tmc_parse_drv_status(stepperZ3, n);
#endif #endif
#if AXIS_IS_TMC(Z4) #if AXIS_IS_TMC(Z4)
tmc_parse_drv_status(stepperZ4, i); tmc_parse_drv_status(stepperZ4, n);
#endif #endif
} }
if (print_e) { #if AXIS_IS_TMC(I)
if (i) tmc_parse_drv_status(stepperI, n);
#endif
#if AXIS_IS_TMC(J)
if (j) tmc_parse_drv_status(stepperJ, n);
#endif
#if AXIS_IS_TMC(K)
if (k) tmc_parse_drv_status(stepperK, n);
#endif
if (TERN0(HAS_EXTRUDERS, e)) {
#if AXIS_IS_TMC(E0) #if AXIS_IS_TMC(E0)
tmc_parse_drv_status(stepperE0, i); tmc_parse_drv_status(stepperE0, n);
#endif #endif
#if AXIS_IS_TMC(E1) #if AXIS_IS_TMC(E1)
tmc_parse_drv_status(stepperE1, i); tmc_parse_drv_status(stepperE1, n);
#endif #endif
#if AXIS_IS_TMC(E2) #if AXIS_IS_TMC(E2)
tmc_parse_drv_status(stepperE2, i); tmc_parse_drv_status(stepperE2, n);
#endif #endif
#if AXIS_IS_TMC(E3) #if AXIS_IS_TMC(E3)
tmc_parse_drv_status(stepperE3, i); tmc_parse_drv_status(stepperE3, n);
#endif #endif
#if AXIS_IS_TMC(E4) #if AXIS_IS_TMC(E4)
tmc_parse_drv_status(stepperE4, i); tmc_parse_drv_status(stepperE4, n);
#endif #endif
#if AXIS_IS_TMC(E5) #if AXIS_IS_TMC(E5)
tmc_parse_drv_status(stepperE5, i); tmc_parse_drv_status(stepperE5, n);
#endif #endif
#if AXIS_IS_TMC(E6) #if AXIS_IS_TMC(E6)
tmc_parse_drv_status(stepperE6, i); tmc_parse_drv_status(stepperE6, n);
#endif #endif
#if AXIS_IS_TMC(E7) #if AXIS_IS_TMC(E7)
tmc_parse_drv_status(stepperE7, i); tmc_parse_drv_status(stepperE7, n);
#endif #endif
} }
@@ -889,9 +924,10 @@
* M122 report functions * M122 report functions
*/ */
void tmc_report_all(bool print_x, const bool print_y, const bool print_z, const bool print_e) { void tmc_report_all(LOGICAL_AXIS_ARGS(const bool)) {
#define TMC_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_debug_loop(ITEM, print_x, print_y, print_z, print_e); }while(0) #define TMC_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_debug_loop(ITEM, LOGICAL_AXIS_ARGS()); }while(0)
#define DRV_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); drv_status_loop(ITEM, print_x, print_y, print_z, print_e); }while(0) #define DRV_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); drv_status_loop(ITEM, LOGICAL_AXIS_ARGS()); }while(0)
TMC_REPORT("\t", TMC_CODES); TMC_REPORT("\t", TMC_CODES);
#if HAS_DRIVER(TMC2209) #if HAS_DRIVER(TMC2209)
TMC_REPORT("Address\t", TMC_UART_ADDR); TMC_REPORT("Address\t", TMC_UART_ADDR);
@@ -1015,72 +1051,82 @@
} }
#endif #endif
static void tmc_get_registers(TMC_get_registers_enum i, const bool print_x, const bool print_y, const bool print_z, const bool print_e) { static void tmc_get_registers(TMC_get_registers_enum n, LOGICAL_AXIS_ARGS(const bool)) {
if (print_x) { if (x) {
#if AXIS_IS_TMC(X) #if AXIS_IS_TMC(X)
tmc_get_registers(stepperX, i); tmc_get_registers(stepperX, n);
#endif #endif
#if AXIS_IS_TMC(X2) #if AXIS_IS_TMC(X2)
tmc_get_registers(stepperX2, i); tmc_get_registers(stepperX2, n);
#endif #endif
} }
if (print_y) { if (TERN0(HAS_Y_AXIS, y)) {
#if AXIS_IS_TMC(Y) #if AXIS_IS_TMC(Y)
tmc_get_registers(stepperY, i); tmc_get_registers(stepperY, n);
#endif #endif
#if AXIS_IS_TMC(Y2) #if AXIS_IS_TMC(Y2)
tmc_get_registers(stepperY2, i); tmc_get_registers(stepperY2, n);
#endif #endif
} }
if (print_z) { if (TERN0(HAS_Z_AXIS, z)) {
#if AXIS_IS_TMC(Z) #if AXIS_IS_TMC(Z)
tmc_get_registers(stepperZ, i); tmc_get_registers(stepperZ, n);
#endif #endif
#if AXIS_IS_TMC(Z2) #if AXIS_IS_TMC(Z2)
tmc_get_registers(stepperZ2, i); tmc_get_registers(stepperZ2, n);
#endif #endif
#if AXIS_IS_TMC(Z3) #if AXIS_IS_TMC(Z3)
tmc_get_registers(stepperZ3, i); tmc_get_registers(stepperZ3, n);
#endif #endif
#if AXIS_IS_TMC(Z4) #if AXIS_IS_TMC(Z4)
tmc_get_registers(stepperZ4, i); tmc_get_registers(stepperZ4, n);
#endif #endif
} }
if (print_e) { #if AXIS_IS_TMC(I)
if (i) tmc_get_registers(stepperI, n);
#endif
#if AXIS_IS_TMC(J)
if (j) tmc_get_registers(stepperJ, n);
#endif
#if AXIS_IS_TMC(K)
if (k) tmc_get_registers(stepperK, n);
#endif
if (TERN0(HAS_EXTRUDERS, e)) {
#if AXIS_IS_TMC(E0) #if AXIS_IS_TMC(E0)
tmc_get_registers(stepperE0, i); tmc_get_registers(stepperE0, n);
#endif #endif
#if AXIS_IS_TMC(E1) #if AXIS_IS_TMC(E1)
tmc_get_registers(stepperE1, i); tmc_get_registers(stepperE1, n);
#endif #endif
#if AXIS_IS_TMC(E2) #if AXIS_IS_TMC(E2)
tmc_get_registers(stepperE2, i); tmc_get_registers(stepperE2, n);
#endif #endif
#if AXIS_IS_TMC(E3) #if AXIS_IS_TMC(E3)
tmc_get_registers(stepperE3, i); tmc_get_registers(stepperE3, n);
#endif #endif
#if AXIS_IS_TMC(E4) #if AXIS_IS_TMC(E4)
tmc_get_registers(stepperE4, i); tmc_get_registers(stepperE4, n);
#endif #endif
#if AXIS_IS_TMC(E5) #if AXIS_IS_TMC(E5)
tmc_get_registers(stepperE5, i); tmc_get_registers(stepperE5, n);
#endif #endif
#if AXIS_IS_TMC(E6) #if AXIS_IS_TMC(E6)
tmc_get_registers(stepperE6, i); tmc_get_registers(stepperE6, n);
#endif #endif
#if AXIS_IS_TMC(E7) #if AXIS_IS_TMC(E7)
tmc_get_registers(stepperE7, i); tmc_get_registers(stepperE7, n);
#endif #endif
} }
SERIAL_EOL(); SERIAL_EOL();
} }
void tmc_get_registers(bool print_x, bool print_y, bool print_z, bool print_e) { void tmc_get_registers(LOGICAL_AXIS_ARGS(bool)) {
#define _TMC_GET_REG(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_get_registers(ITEM, print_x, print_y, print_z, print_e); }while(0) #define _TMC_GET_REG(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_get_registers(ITEM, LOGICAL_AXIS_ARGS()); }while(0)
#define TMC_GET_REG(NAME, TABS) _TMC_GET_REG(STRINGIFY(NAME) TABS, TMC_GET_##NAME) #define TMC_GET_REG(NAME, TABS) _TMC_GET_REG(STRINGIFY(NAME) TABS, TMC_GET_##NAME)
_TMC_GET_REG("\t", TMC_AXIS_CODES); _TMC_GET_REG("\t", TMC_AXIS_CODES);
TMC_GET_REG(GCONF, "\t\t"); TMC_GET_REG(GCONF, "\t\t");
@@ -1165,6 +1211,15 @@
#if AXIS_HAS_SPI(Z4) #if AXIS_HAS_SPI(Z4)
SET_CS_PIN(Z4); SET_CS_PIN(Z4);
#endif #endif
#if AXIS_HAS_SPI(I)
SET_CS_PIN(I);
#endif
#if AXIS_HAS_SPI(J)
SET_CS_PIN(J);
#endif
#if AXIS_HAS_SPI(K)
SET_CS_PIN(K);
#endif
#if AXIS_HAS_SPI(E0) #if AXIS_HAS_SPI(E0)
SET_CS_PIN(E0); SET_CS_PIN(E0);
#endif #endif
@@ -1214,10 +1269,10 @@ static bool test_connection(TMC &st) {
return test_result; return test_result;
} }
void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z, const bool test_e) { void test_tmc_connection(LOGICAL_AXIS_ARGS(const bool)) {
uint8_t axis_connection = 0; uint8_t axis_connection = 0;
if (test_x) { if (x) {
#if AXIS_IS_TMC(X) #if AXIS_IS_TMC(X)
axis_connection += test_connection(stepperX); axis_connection += test_connection(stepperX);
#endif #endif
@@ -1226,7 +1281,7 @@ void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z
#endif #endif
} }
if (test_y) { if (TERN0(HAS_Y_AXIS, y)) {
#if AXIS_IS_TMC(Y) #if AXIS_IS_TMC(Y)
axis_connection += test_connection(stepperY); axis_connection += test_connection(stepperY);
#endif #endif
@@ -1235,7 +1290,7 @@ void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z
#endif #endif
} }
if (test_z) { if (TERN0(HAS_Z_AXIS, z)) {
#if AXIS_IS_TMC(Z) #if AXIS_IS_TMC(Z)
axis_connection += test_connection(stepperZ); axis_connection += test_connection(stepperZ);
#endif #endif
@@ -1250,7 +1305,17 @@ void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z
#endif #endif
} }
if (test_e) { #if AXIS_IS_TMC(I)
if (i) axis_connection += test_connection(stepperI);
#endif
#if AXIS_IS_TMC(J)
if (j) axis_connection += test_connection(stepperJ);
#endif
#if AXIS_IS_TMC(K)
if (k) axis_connection += test_connection(stepperK);
#endif
if (TERN0(HAS_EXTRUDERS, e)) {
#if AXIS_IS_TMC(E0) #if AXIS_IS_TMC(E0)
axis_connection += test_connection(stepperE0); axis_connection += test_connection(stepperE0);
#endif #endif

View File

@@ -70,15 +70,9 @@ class TMCStorage {
} }
struct { struct {
#if ENABLED(HAS_STEALTHCHOP) OPTCODE(HAS_STEALTHCHOP, bool stealthChop_enabled = false)
bool stealthChop_enabled = false; OPTCODE(HYBRID_THRESHOLD, uint8_t hybrid_thrs = 0)
#endif OPTCODE(USE_SENSORLESS, int16_t homing_thrs = 0)
#if ENABLED(HYBRID_THRESHOLD)
uint8_t hybrid_thrs = 0;
#endif
#if ENABLED(USE_SENSORLESS)
int16_t homing_thrs = 0;
#endif
} stored; } stored;
}; };
@@ -341,14 +335,14 @@ void tmc_print_current(TMC &st) {
#endif #endif
void monitor_tmc_drivers(); void monitor_tmc_drivers();
void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z, const bool test_e); void test_tmc_connection(LOGICAL_AXIS_DECL(const bool, true));
#if ENABLED(TMC_DEBUG) #if ENABLED(TMC_DEBUG)
#if ENABLED(MONITOR_DRIVER_STATUS) #if ENABLED(MONITOR_DRIVER_STATUS)
void tmc_set_report_interval(const uint16_t update_interval); void tmc_set_report_interval(const uint16_t update_interval);
#endif #endif
void tmc_report_all(const bool print_x, const bool print_y, const bool print_z, const bool print_e); void tmc_report_all(LOGICAL_AXIS_DECL(const bool, true));
void tmc_get_registers(const bool print_x, const bool print_y, const bool print_z, const bool print_e); void tmc_get_registers(LOGICAL_AXIS_ARGS(const bool));
#endif #endif
/** /**
@@ -361,16 +355,16 @@ void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z
#if USE_SENSORLESS #if USE_SENSORLESS
// Track enabled status of stealthChop and only re-enable where applicable // Track enabled status of stealthChop and only re-enable where applicable
struct sensorless_t { bool x, y, z, x2, y2, z2, z3, z4; }; struct sensorless_t { bool LINEAR_AXIS_ARGS(), x2, y2, z2, z3, z4; };
#if ENABLED(IMPROVE_HOMING_RELIABILITY) #if ENABLED(IMPROVE_HOMING_RELIABILITY)
extern millis_t sg_guard_period; extern millis_t sg_guard_period;
constexpr uint16_t default_sg_guard_duration = 400; constexpr uint16_t default_sg_guard_duration = 400;
struct slow_homing_t { struct motion_state_t {
xy_ulong_t acceleration; xy_ulong_t acceleration;
#if ENABLED(HAS_CLASSIC_JERK) #if ENABLED(HAS_CLASSIC_JERK)
xy_float_t jerk_xy; xy_float_t jerk_state;
#endif #endif
}; };
#endif #endif

View File

@@ -291,7 +291,7 @@ typedef struct {
if (p2.x < 0 || p2.x >= (GRID_MAX_POINTS_X)) return; if (p2.x < 0 || p2.x >= (GRID_MAX_POINTS_X)) return;
if (p2.y < 0 || p2.y >= (GRID_MAX_POINTS_Y)) return; if (p2.y < 0 || p2.y >= (GRID_MAX_POINTS_Y)) return;
if(circle_flags.marked(p1.x, p1.y) && circle_flags.marked(p2.x, p2.y)) { if (circle_flags.marked(p1.x, p1.y) && circle_flags.marked(p2.x, p2.y)) {
xyz_pos_t s, e; xyz_pos_t s, e;
s.x = _GET_MESH_X(p1.x) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx; s.x = _GET_MESH_X(p1.x) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx;
e.x = _GET_MESH_X(p2.x) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx; e.x = _GET_MESH_X(p2.x) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx;
@@ -330,12 +330,8 @@ typedef struct {
thermalManager.setTargetBed(bed_temp); thermalManager.setTargetBed(bed_temp);
// Wait for the temperature to stabilize // Wait for the temperature to stabilize
if (!thermalManager.wait_for_bed(true if (!thermalManager.wait_for_bed(true OPTARG(G26_CLICK_CAN_CANCEL, true)))
#if G26_CLICK_CAN_CANCEL return G26_ERR;
, true
#endif
)
) return G26_ERR;
} }
#else #else
@@ -352,11 +348,8 @@ typedef struct {
thermalManager.setTargetHotend(hotend_temp, active_extruder); thermalManager.setTargetHotend(hotend_temp, active_extruder);
// Wait for the temperature to stabilize // Wait for the temperature to stabilize
if (!thermalManager.wait_for_hotend(active_extruder, true if (!thermalManager.wait_for_hotend(active_extruder, true OPTARG(G26_CLICK_CAN_CANCEL, true)))
#if G26_CLICK_CAN_CANCEL return G26_ERR;
, true
#endif
)) return G26_ERR;
#if HAS_WIRED_LCD #if HAS_WIRED_LCD
ui.reset_status(); ui.reset_status();

View File

@@ -91,8 +91,8 @@ void GcodeSuite::G35() {
// Disable duplication mode on homing // Disable duplication mode on homing
TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false)); TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false));
// Home all before this procedure // Home only Z axis when X and Y is trusted, otherwise all axes, if needed before this procedure
home_all_axes(); if (!all_axes_trusted()) process_subcommands_now_P(PSTR("G28Z"));
bool err_break = false; bool err_break = false;

View File

@@ -246,7 +246,7 @@ G29_TYPE GcodeSuite::G29() {
// Send 'N' to force homing before G29 (internal only) // Send 'N' to force homing before G29 (internal only)
if (parser.seen_test('N')) if (parser.seen_test('N'))
process_subcommands_now_P(TERN(G28_L0_ENSURES_LEVELING_OFF, PSTR("G28L0"), G28_STR)); process_subcommands_now_P(TERN(CAN_SET_LEVELING_AFTER_G28, PSTR("G28L0"), G28_STR));
// Don't allow auto-leveling without homing first // Don't allow auto-leveling without homing first
if (homing_needed_error()) G29_RETURN(false); if (homing_needed_error()) G29_RETURN(false);
@@ -689,7 +689,7 @@ G29_TYPE GcodeSuite::G29() {
TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/3"), GET_TEXT(MSG_PROBING_MESH), int(i + 1))); TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/3"), GET_TEXT(MSG_PROBING_MESH), int(i + 1)));
// Retain the last probe position // Retain the last probe position
abl.probePos = points[i]; abl.probePos = xy_pos_t(points[i]);
abl.measured_z = faux ? 0.001 * random(-100, 101) : probe.probe_at_point(abl.probePos, raise_after, abl.verbose_level); abl.measured_z = faux ? 0.001 * random(-100, 101) : probe.probe_at_point(abl.probePos, raise_after, abl.verbose_level);
if (isnan(abl.measured_z)) { if (isnan(abl.measured_z)) {
set_bed_leveling_enabled(abl.reenable); set_bed_leveling_enabled(abl.reenable);
@@ -795,7 +795,7 @@ G29_TYPE GcodeSuite::G29() {
const int ind = abl.indexIntoAB[xx][yy]; const int ind = abl.indexIntoAB[xx][yy];
xyz_float_t tmp = { abl.eqnAMatrix[ind + 0 * abl.abl_points], xyz_float_t tmp = { abl.eqnAMatrix[ind + 0 * abl.abl_points],
abl.eqnAMatrix[ind + 1 * abl.abl_points], 0 }; abl.eqnAMatrix[ind + 1 * abl.abl_points], 0 };
planner.bed_level_matrix.apply_rotation_xyz(tmp); planner.bed_level_matrix.apply_rotation_xyz(tmp.x, tmp.y, tmp.z);
if (get_min) NOMORE(min_diff, abl.eqnBVector[ind] - tmp.z); if (get_min) NOMORE(min_diff, abl.eqnBVector[ind] - tmp.z);
const float subval = get_min ? abl.mean : tmp.z + min_diff, const float subval = get_min ? abl.mean : tmp.z + min_diff,
diff = abl.eqnBVector[ind] - subval; diff = abl.eqnBVector[ind] - subval;

View File

@@ -70,7 +70,7 @@ void GcodeSuite::G29() {
return; return;
} }
int8_t ix, iy; int8_t ix, iy = 0;
switch (state) { switch (state) {
case MeshReport: case MeshReport:
@@ -87,7 +87,8 @@ void GcodeSuite::G29() {
mbl.reset(); mbl.reset();
mbl_probe_index = 0; mbl_probe_index = 0;
if (!ui.wait_for_move) { if (!ui.wait_for_move) {
queue.inject_P(parser.seen_test('N') ? PSTR("G28" TERN(G28_L0_ENSURES_LEVELING_OFF, "L0", "") "\nG29S2") : PSTR("G29S2")); queue.inject_P(parser.seen_test('N') ? PSTR("G28" TERN(CAN_SET_LEVELING_AFTER_G28, "L0", "") "\nG29S2") : PSTR("G29S2"));
TERN_(EXTENSIBLE_UI, ExtUI::onMeshLevelingStart());
return; return;
} }
state = MeshNext; state = MeshNext;
@@ -109,6 +110,7 @@ void GcodeSuite::G29() {
else { else {
// Save Z for the previous mesh position // Save Z for the previous mesh position
mbl.set_zigzag_z(mbl_probe_index - 1, current_position.z); mbl.set_zigzag_z(mbl_probe_index - 1, current_position.z);
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, current_position.z));
SET_SOFT_ENDSTOP_LOOSE(false); SET_SOFT_ENDSTOP_LOOSE(false);
} }
// If there's another point to sample, move there with optional lift. // If there's another point to sample, move there with optional lift.

View File

@@ -73,7 +73,7 @@
current_position.set(0.0, 0.0); current_position.set(0.0, 0.0);
sync_plan_position(); sync_plan_position();
const int x_axis_home_dir = x_home_dir(active_extruder); const int x_axis_home_dir = TOOL_X_HOME_DIR(active_extruder);
const float mlx = max_length(X_AXIS), const float mlx = max_length(X_AXIS),
mly = max_length(Y_AXIS), mly = max_length(Y_AXIS),
@@ -164,24 +164,24 @@
#if ENABLED(IMPROVE_HOMING_RELIABILITY) #if ENABLED(IMPROVE_HOMING_RELIABILITY)
slow_homing_t begin_slow_homing() { motion_state_t begin_slow_homing() {
slow_homing_t slow_homing{0}; motion_state_t motion_state{0};
slow_homing.acceleration.set(planner.settings.max_acceleration_mm_per_s2[X_AXIS], motion_state.acceleration.set(planner.settings.max_acceleration_mm_per_s2[X_AXIS],
planner.settings.max_acceleration_mm_per_s2[Y_AXIS]); planner.settings.max_acceleration_mm_per_s2[Y_AXIS]);
planner.settings.max_acceleration_mm_per_s2[X_AXIS] = 100; planner.settings.max_acceleration_mm_per_s2[X_AXIS] = 100;
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = 100; planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = 100;
#if HAS_CLASSIC_JERK #if HAS_CLASSIC_JERK
slow_homing.jerk_xy = planner.max_jerk; motion_state.jerk_state = planner.max_jerk;
planner.max_jerk.set(0, 0); planner.max_jerk.set(0, 0);
#endif #endif
planner.reset_acceleration_rates(); planner.reset_acceleration_rates();
return slow_homing; return motion_state;
} }
void end_slow_homing(const slow_homing_t &slow_homing) { void end_slow_homing(const motion_state_t &motion_state) {
planner.settings.max_acceleration_mm_per_s2[X_AXIS] = slow_homing.acceleration.x; planner.settings.max_acceleration_mm_per_s2[X_AXIS] = motion_state.acceleration.x;
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = slow_homing.acceleration.y; planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = motion_state.acceleration.y;
TERN_(HAS_CLASSIC_JERK, planner.max_jerk = slow_homing.jerk_xy); TERN_(HAS_CLASSIC_JERK, planner.max_jerk = motion_state.jerk_state);
planner.reset_acceleration_rates(); planner.reset_acceleration_rates();
} }
@@ -195,9 +195,9 @@
* None Home to all axes with no parameters. * None Home to all axes with no parameters.
* With QUICK_HOME enabled XY will home together, then Z. * With QUICK_HOME enabled XY will home together, then Z.
* *
* O Home only if position is unknown * L<bool> Force leveling state ON (if possible) or OFF after homing (Requires RESTORE_LEVELING_AFTER_G28 or ENABLE_LEVELING_AFTER_G28)
* * O Home only if the position is not known and trusted
* Rn Raise by n mm/inches before homing * R<linear> Raise by n mm/inches before homing
* *
* Cartesian/SCARA parameters * Cartesian/SCARA parameters
* *
@@ -220,7 +220,7 @@ void GcodeSuite::G28() {
#if ENABLED(MARLIN_DEV_MODE) #if ENABLED(MARLIN_DEV_MODE)
if (parser.seen_test('S')) { if (parser.seen_test('S')) {
LOOP_XYZ(a) set_axis_is_at_home((AxisEnum)a); LOOP_LINEAR_AXES(a) set_axis_is_at_home((AxisEnum)a);
sync_plan_position(); sync_plan_position();
SERIAL_ECHOLNPGM("Simulated Homing"); SERIAL_ECHOLNPGM("Simulated Homing");
report_current_position(); report_current_position();
@@ -229,7 +229,7 @@ void GcodeSuite::G28() {
#endif #endif
// Home (O)nly if position is unknown // Home (O)nly if position is unknown
if (!axes_should_home() && parser.boolval('O')) { if (!axes_should_home() && parser.seen_test('O')) {
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> homing not needed, skip"); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> homing not needed, skip");
return; return;
} }
@@ -242,12 +242,16 @@ void GcodeSuite::G28() {
SET_SOFT_ENDSTOP_LOOSE(false); // Reset a leftover 'loose' motion state SET_SOFT_ENDSTOP_LOOSE(false); // Reset a leftover 'loose' motion state
// Disable the leveling matrix before homing // Disable the leveling matrix before homing
#if HAS_LEVELING #if CAN_SET_LEVELING_AFTER_G28
const bool leveling_restore_state = parser.boolval('L', TERN(RESTORE_LEVELING_AFTER_G28, planner.leveling_active, ENABLED(ENABLE_LEVELING_AFTER_G28))); const bool leveling_restore_state = parser.boolval('L', TERN1(RESTORE_LEVELING_AFTER_G28, planner.leveling_active));
IF_ENABLED(PROBE_MANUALLY, g29_in_progress = false); // Cancel the active G29 session
set_bed_leveling_enabled(false);
#endif #endif
// Cancel any prior G29 session
TERN_(PROBE_MANUALLY, g29_in_progress = false);
// Disable leveling before homing
TERN_(HAS_LEVELING, set_bed_leveling_enabled(false));
// Reset to the XY plane // Reset to the XY plane
TERN_(CNC_WORKSPACE_PLANES, workspace_plane = PLANE_XY); TERN_(CNC_WORKSPACE_PLANES, workspace_plane = PLANE_XY);
@@ -285,7 +289,9 @@ void GcodeSuite::G28() {
#endif #endif
#endif #endif
TERN_(IMPROVE_HOMING_RELIABILITY, slow_homing_t slow_homing = begin_slow_homing()); #if ENABLED(IMPROVE_HOMING_RELIABILITY)
motion_state_t saved_motion_state = begin_slow_homing();
#endif
// Always home with tool 0 active // Always home with tool 0 active
#if HAS_MULTI_HOTEND #if HAS_MULTI_HOTEND
@@ -311,7 +317,7 @@ void GcodeSuite::G28() {
home_delta(); home_delta();
TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(slow_homing)); TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(saved_motion_state));
#elif ENABLED(AXEL_TPARA) #elif ENABLED(AXEL_TPARA)
@@ -321,33 +327,47 @@ void GcodeSuite::G28() {
#else #else
const bool homeZ = parser.seen_test('Z'), #define _UNSAFE(A) (homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(A##_AXIS))))
needX = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(X_AXIS))),
needY = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(Y_AXIS))),
homeX = needX || parser.seen_test('X'), homeY = needY || parser.seen_test('Y'),
home_all = homeX == homeY && homeX == homeZ, // All or None
doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ;
#if ENABLED(HOME_Z_FIRST) const bool homeZ = TERN0(HAS_Z_AXIS, parser.seen_test('Z')),
LINEAR_AXIS_LIST( // Other axes should be homed before Z safe-homing
if (doZ) homeaxis(Z_AXIS); needX = _UNSAFE(X), needY = _UNSAFE(Y), needZ = false, // UNUSED
needI = _UNSAFE(I), needJ = _UNSAFE(J), needK = _UNSAFE(K)
),
LINEAR_AXIS_LIST( // Home each axis if needed or flagged
homeX = needX || parser.seen_test('X'),
homeY = needY || parser.seen_test('Y'),
homeZZ = homeZ,
homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), homeK = needK || parser.seen_test(AXIS6_NAME),
),
home_all = LINEAR_AXIS_GANG( // Home-all if all or none are flagged
homeX == homeX, && homeY == homeX, && homeZ == homeX,
&& homeI == homeX, && homeJ == homeX, && homeK == homeX
),
LINEAR_AXIS_LIST(
doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ,
doI = home_all || homeI, doJ = home_all || homeJ, doK = home_all || homeK
);
#if HAS_Z_AXIS
UNUSED(needZ); UNUSED(homeZZ);
#else
constexpr bool doZ = false;
#endif #endif
TERN_(HOME_Z_FIRST, if (doZ) homeaxis(Z_AXIS));
const float z_homing_height = parser.seenval('R') ? parser.value_linear_units() : Z_HOMING_HEIGHT; const float z_homing_height = parser.seenval('R') ? parser.value_linear_units() : Z_HOMING_HEIGHT;
if (z_homing_height && (doX || doY || TERN0(Z_SAFE_HOMING, doZ))) { if (z_homing_height && (LINEAR_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK))) {
// Raise Z before homing any other axes and z is not already high enough (never lower z) // Raise Z before homing any other axes and z is not already high enough (never lower z)
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Raise Z (before homing) by ", z_homing_height); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Raise Z (before homing) by ", z_homing_height);
do_z_clearance(z_homing_height); do_z_clearance(z_homing_height);
TERN_(BLTOUCH, bltouch.init()); TERN_(BLTOUCH, bltouch.init());
} }
#if ENABLED(QUICK_HOME) // Diagonal move first if both are homing
TERN_(QUICK_HOME, if (doX && doY) quick_home_xy());
if (doX && doY) quick_home_xy();
#endif
// Home Y (before X) // Home Y (before X)
if (ENABLED(HOME_Y_BEFORE_X) && (doY || TERN0(CODEPENDENT_XY_HOMING, doX))) if (ENABLED(HOME_Y_BEFORE_X) && (doY || TERN0(CODEPENDENT_XY_HOMING, doX)))
@@ -383,10 +403,10 @@ void GcodeSuite::G28() {
if (DISABLED(HOME_Y_BEFORE_X) && doY) if (DISABLED(HOME_Y_BEFORE_X) && doY)
homeaxis(Y_AXIS); homeaxis(Y_AXIS);
TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(slow_homing)); TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(saved_motion_state));
// Home Z last if homing towards the bed // Home Z last if homing towards the bed
#if DISABLED(HOME_Z_FIRST) #if HAS_Z_AXIS && DISABLED(HOME_Z_FIRST)
if (doZ) { if (doZ) {
#if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN) #if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
stepper.set_all_z_lock(false); stepper.set_all_z_lock(false);
@@ -398,6 +418,16 @@ void GcodeSuite::G28() {
} }
#endif #endif
#if LINEAR_AXES >= 4
if (doI) homeaxis(I_AXIS);
#endif
#if LINEAR_AXES >= 5
if (doJ) homeaxis(J_AXIS);
#endif
#if LINEAR_AXES >= 6
if (doK) homeaxis(K_AXIS);
#endif
sync_plan_position(); sync_plan_position();
#endif #endif
@@ -412,7 +442,7 @@ void GcodeSuite::G28() {
if (idex_is_duplicating()) { if (idex_is_duplicating()) {
TERN_(IMPROVE_HOMING_RELIABILITY, slow_homing = begin_slow_homing()); TERN_(IMPROVE_HOMING_RELIABILITY, saved_motion_state = begin_slow_homing());
// Always home the 2nd (right) extruder first // Always home the 2nd (right) extruder first
active_extruder = 1; active_extruder = 1;
@@ -431,7 +461,7 @@ void GcodeSuite::G28() {
dual_x_carriage_mode = IDEX_saved_mode; dual_x_carriage_mode = IDEX_saved_mode;
set_duplication_enabled(IDEX_saved_duplication_state); set_duplication_enabled(IDEX_saved_duplication_state);
TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(slow_homing)); TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(saved_motion_state));
} }
#endif // DUAL_X_CARRIAGE #endif // DUAL_X_CARRIAGE
@@ -441,12 +471,10 @@ void GcodeSuite::G28() {
// Clear endstop state for polled stallGuard endstops // Clear endstop state for polled stallGuard endstops
TERN_(SPI_ENDSTOPS, endstops.clear_endstop_state()); TERN_(SPI_ENDSTOPS, endstops.clear_endstop_state());
#if BOTH(DELTA, DELTA_HOME_TO_SAFE_ZONE) // Move to a height where we can use the full xy-area
// move to a height where we can use the full xy-area TERN_(DELTA_HOME_TO_SAFE_ZONE, do_blocking_move_to_z(delta_clip_start_height));
do_blocking_move_to_z(delta_clip_start_height);
#endif
TERN_(HAS_LEVELING, set_bed_leveling_enabled(leveling_restore_state)); TERN_(CAN_SET_LEVELING_AFTER_G28, if (leveling_restore_state) set_bed_leveling_enabled());
restore_feedrate_and_scaling(); restore_feedrate_and_scaling();
@@ -469,7 +497,16 @@ void GcodeSuite::G28() {
#if HAS_CURRENT_HOME(Y2) #if HAS_CURRENT_HOME(Y2)
stepperY2.rms_current(tmc_save_current_Y2); stepperY2.rms_current(tmc_save_current_Y2);
#endif #endif
#endif #if HAS_CURRENT_HOME(I)
stepperI.rms_current(tmc_save_current_I);
#endif
#if HAS_CURRENT_HOME(J)
stepperJ.rms_current(tmc_save_current_J);
#endif
#if HAS_CURRENT_HOME(K)
stepperK.rms_current(tmc_save_current_K);
#endif
#endif // HAS_HOMING_CURRENT
ui.refresh(); ui.refresh();
@@ -487,11 +524,13 @@ void GcodeSuite::G28() {
// Set L6470 absolute position registers to counts // Set L6470 absolute position registers to counts
// constexpr *might* move this to PROGMEM. // constexpr *might* move this to PROGMEM.
// If not, this will need a PROGMEM directive and an accessor. // If not, this will need a PROGMEM directive and an accessor.
#define _EN_ITEM(N) , E_AXIS
static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = { static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = {
X_AXIS, Y_AXIS, Z_AXIS, LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS),
X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS, X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS, Z_AXIS
E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS REPEAT(E_STEPPERS, _EN_ITEM)
}; };
#undef _EN_ITEM
for (uint8_t j = 1; j <= L64XX::chain[0]; j++) { for (uint8_t j = 1; j <= L64XX::chain[0]; j++) {
const uint8_t cv = L64XX::chain[j]; const uint8_t cv = L64XX::chain[j];
L64xxManager.set_param((L64XX_axis_t)cv, L6470_ABS_POS, stepper.position(L64XX_axis_xref[cv])); L64xxManager.set_param((L64XX_axis_t)cv, L6470_ABS_POS, stepper.position(L64XX_axis_xref[cv]));

View File

@@ -347,7 +347,7 @@ static float auto_tune_a() {
abc_float_t delta_e = { 0.0f }, delta_t = { 0.0f }; abc_float_t delta_e = { 0.0f }, delta_t = { 0.0f };
delta_t.reset(); delta_t.reset();
LOOP_XYZ(axis) { LOOP_LINEAR_AXES(axis) {
delta_t[axis] = diff; delta_t[axis] = diff;
calc_kinematics_diff_probe_points(z_pt, delta_e, delta_r, delta_t); calc_kinematics_diff_probe_points(z_pt, delta_e, delta_r, delta_t);
delta_t[axis] = 0; delta_t[axis] = 0;
@@ -525,7 +525,7 @@ void GcodeSuite::G33() {
case 1: case 1:
test_precision = 0.0f; // forced end test_precision = 0.0f; // forced end
LOOP_XYZ(axis) e_delta[axis] = +Z4(CEN); LOOP_LINEAR_AXES(axis) e_delta[axis] = +Z4(CEN);
break; break;
case 2: case 2:
@@ -573,14 +573,14 @@ void GcodeSuite::G33() {
// Normalize angles to least-squares // Normalize angles to least-squares
if (_angle_results) { if (_angle_results) {
float a_sum = 0.0f; float a_sum = 0.0f;
LOOP_XYZ(axis) a_sum += delta_tower_angle_trim[axis]; LOOP_LINEAR_AXES(axis) a_sum += delta_tower_angle_trim[axis];
LOOP_XYZ(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f; LOOP_LINEAR_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f;
} }
// adjust delta_height and endstops by the max amount // adjust delta_height and endstops by the max amount
const float z_temp = _MAX(delta_endstop_adj.a, delta_endstop_adj.b, delta_endstop_adj.c); const float z_temp = _MAX(delta_endstop_adj.a, delta_endstop_adj.b, delta_endstop_adj.c);
delta_height -= z_temp; delta_height -= z_temp;
LOOP_XYZ(axis) delta_endstop_adj[axis] -= z_temp; LOOP_LINEAR_AXES(axis) delta_endstop_adj[axis] -= z_temp;
} }
recalc_delta_settings(); recalc_delta_settings();
NOMORE(zero_std_dev_min, zero_std_dev); NOMORE(zero_std_dev_min, zero_std_dev);

View File

@@ -39,7 +39,7 @@
void GcodeSuite::G34() { void GcodeSuite::G34() {
// Home before the alignment procedure // Home before the alignment procedure
if (!all_axes_trusted()) home_all_axes(); home_if_needed();
TERN_(HAS_LEVELING, TEMPORARY_BED_LEVELING_STATE(false)); TERN_(HAS_LEVELING, TEMPORARY_BED_LEVELING_STATE(false));

View File

@@ -48,6 +48,13 @@
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) #define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
#include "../../core/debug_out.h" #include "../../core/debug_out.h"
#if NUM_Z_STEPPER_DRIVERS >= 3
#define TRIPLE_Z 1
#if NUM_Z_STEPPER_DRIVERS >= 4
#define QUAD_Z 1
#endif
#endif
/** /**
* G34: Z-Stepper automatic alignment * G34: Z-Stepper automatic alignment
* *
@@ -82,9 +89,9 @@ void GcodeSuite::G34() {
switch (parser.intval('Z')) { switch (parser.intval('Z')) {
case 1: stepper.set_z1_lock(state); break; case 1: stepper.set_z1_lock(state); break;
case 2: stepper.set_z2_lock(state); break; case 2: stepper.set_z2_lock(state); break;
#if NUM_Z_STEPPER_DRIVERS >= 3 #if TRIPLE_Z
case 3: stepper.set_z3_lock(state); break; case 3: stepper.set_z3_lock(state); break;
#if NUM_Z_STEPPER_DRIVERS >= 4 #if QUAD_Z
case 4: stepper.set_z4_lock(state); break; case 4: stepper.set_z4_lock(state); break;
#endif #endif
#endif #endif
@@ -99,13 +106,6 @@ void GcodeSuite::G34() {
#if ENABLED(Z_STEPPER_AUTO_ALIGN) #if ENABLED(Z_STEPPER_AUTO_ALIGN)
do { // break out on error do { // break out on error
#if NUM_Z_STEPPER_DRIVERS == 4
SERIAL_ECHOLNPGM("Alignment for 4 steppers is Experimental!");
#elif NUM_Z_STEPPER_DRIVERS > 4
SERIAL_ECHOLNPGM("Alignment not supported for over 4 steppers");
break;
#endif
const int8_t z_auto_align_iterations = parser.intval('I', Z_STEPPER_ALIGN_ITERATIONS); const int8_t z_auto_align_iterations = parser.intval('I', Z_STEPPER_ALIGN_ITERATIONS);
if (!WITHIN(z_auto_align_iterations, 1, 30)) { if (!WITHIN(z_auto_align_iterations, 1, 30)) {
SERIAL_ECHOLNPGM("?(I)teration out of bounds (1-30)."); SERIAL_ECHOLNPGM("?(I)teration out of bounds (1-30).");
@@ -157,19 +157,17 @@ void GcodeSuite::G34() {
const xy_pos_t diff = z_stepper_align.xy[i] - z_stepper_align.xy[j]; const xy_pos_t diff = z_stepper_align.xy[i] - z_stepper_align.xy[j];
return HYPOT2(diff.x, diff.y); return HYPOT2(diff.x, diff.y);
}; };
float z_probe = Z_BASIC_CLEARANCE + (G34_MAX_GRADE) * 0.01f * SQRT( float z_probe = Z_BASIC_CLEARANCE + (G34_MAX_GRADE) * 0.01f * SQRT(_MAX(0, magnitude2(0, 1)
#if NUM_Z_STEPPER_DRIVERS == 3 #if TRIPLE_Z
_MAX(magnitude2(0, 1), magnitude2(1, 2), magnitude2(2, 0)) , magnitude2(2, 1), magnitude2(2, 0)
#elif NUM_Z_STEPPER_DRIVERS == 4 #if QUAD_Z
_MAX(magnitude2(0, 1), magnitude2(1, 2), magnitude2(2, 3), , magnitude2(3, 2), magnitude2(3, 1), magnitude2(3, 0)
magnitude2(3, 0), magnitude2(0, 2), magnitude2(1, 3)) #endif
#else
magnitude2(0, 1)
#endif #endif
); ));
// Home before the alignment procedure // Home before the alignment procedure
if (!all_axes_trusted()) home_all_axes(); home_if_needed();
// Move the Z coordinate realm towards the positive - dirty trick // Move the Z coordinate realm towards the positive - dirty trick
current_position.z += z_probe * 0.5f; current_position.z += z_probe * 0.5f;
@@ -178,7 +176,7 @@ void GcodeSuite::G34() {
// This hack is un-done at the end of G34 - either by re-homing, or by using the probed heights of the last iteration. // This hack is un-done at the end of G34 - either by re-homing, or by using the probed heights of the last iteration.
#if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS) #if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
float last_z_align_move[NUM_Z_STEPPER_DRIVERS] = ARRAY_N(NUM_Z_STEPPER_DRIVERS, 10000.0f, 10000.0f, 10000.0f, 10000.0f); float last_z_align_move[NUM_Z_STEPPER_DRIVERS] = ARRAY_N_1(NUM_Z_STEPPER_DRIVERS, 10000.0f);
#else #else
float last_z_align_level_indicator = 10000.0f; float last_z_align_level_indicator = 10000.0f;
#endif #endif
@@ -280,39 +278,52 @@ void GcodeSuite::G34() {
z_measured_min = _MIN(z_measured_min, z_measured[i]); z_measured_min = _MIN(z_measured_min, z_measured[i]);
} }
SERIAL_ECHOLNPAIR("CALCULATED STEPPER POSITIONS: Z1=", z_measured[0], " Z2=", z_measured[1], " Z3=", z_measured[2]); SERIAL_ECHOLNPAIR(
LIST_N(DOUBLE(NUM_Z_STEPPER_DRIVERS),
"Calculated Z1=", z_measured[0],
" Z2=", z_measured[1],
" Z3=", z_measured[2],
" Z4=", z_measured[3]
)
);
#endif #endif
SERIAL_ECHOLNPAIR("\n" SERIAL_ECHOLNPAIR("\n"
"DIFFERENCE Z1-Z2=", ABS(z_measured[0] - z_measured[1]) "Z2-Z1=", ABS(z_measured[1] - z_measured[0])
#if NUM_Z_STEPPER_DRIVERS == 3 #if TRIPLE_Z
, " Z2-Z3=", ABS(z_measured[1] - z_measured[2]) , " Z3-Z2=", ABS(z_measured[2] - z_measured[1])
, " Z3-Z1=", ABS(z_measured[2] - z_measured[0]) , " Z3-Z1=", ABS(z_measured[2] - z_measured[0])
#if QUAD_Z
, " Z4-Z3=", ABS(z_measured[3] - z_measured[2])
, " Z4-Z2=", ABS(z_measured[3] - z_measured[1])
, " Z4-Z1=", ABS(z_measured[3] - z_measured[0])
#endif
#endif #endif
); );
#if HAS_STATUS_MESSAGE #if HAS_STATUS_MESSAGE
char fstr1[10]; char fstr1[10];
#if NUM_Z_STEPPER_DRIVERS == 2 char msg[6 + (6 + 5) * NUM_Z_STEPPER_DRIVERS + 1]
char msg[6 + (6 + 5) * 1 + 1]; #if TRIPLE_Z
#else , fstr2[10], fstr3[10]
char msg[6 + (6 + 5) * 3 + 1], fstr2[10], fstr3[10]; #if QUAD_Z
#endif , fstr4[10], fstr5[10], fstr6[10]
sprintf_P(msg,
PSTR("Diffs Z1-Z2=%s"
#if NUM_Z_STEPPER_DRIVERS == 3
" Z2-Z3=%s"
" Z3-Z1=%s"
#endif #endif
), dtostrf(ABS(z_measured[0] - z_measured[1]), 1, 3, fstr1)
#if NUM_Z_STEPPER_DRIVERS == 3
, dtostrf(ABS(z_measured[1] - z_measured[2]), 1, 3, fstr2)
, dtostrf(ABS(z_measured[2] - z_measured[0]), 1, 3, fstr3)
#endif #endif
;
sprintf_P(msg,
PSTR("1:2=%s" TERN_(TRIPLE_Z, " 3-2=%s 3-1=%s") TERN_(QUAD_Z, " 4-3=%s 4-2=%s 4-1=%s")),
dtostrf(ABS(z_measured[1] - z_measured[0]), 1, 3, fstr1)
OPTARG(TRIPLE_Z, dtostrf(ABS(z_measured[2] - z_measured[1]), 1, 3, fstr2))
OPTARG(TRIPLE_Z, dtostrf(ABS(z_measured[2] - z_measured[0]), 1, 3, fstr3))
OPTARG(QUAD_Z, dtostrf(ABS(z_measured[3] - z_measured[2]), 1, 3, fstr4))
OPTARG(QUAD_Z, dtostrf(ABS(z_measured[3] - z_measured[1]), 1, 3, fstr5))
OPTARG(QUAD_Z, dtostrf(ABS(z_measured[3] - z_measured[0]), 1, 3, fstr6))
); );
ui.set_status(msg); ui.set_status(msg);
#endif #endif
auto decreasing_accuracy = [](const_float_t v1, const_float_t v2){ auto decreasing_accuracy = [](const_float_t v1, const_float_t v2) {
if (v1 < v2 * 0.7f) { if (v1 < v2 * 0.7f) {
SERIAL_ECHOLNPGM("Decreasing Accuracy Detected."); SERIAL_ECHOLNPGM("Decreasing Accuracy Detected.");
LCD_MESSAGEPGM(MSG_DECREASING_ACCURACY); LCD_MESSAGEPGM(MSG_DECREASING_ACCURACY);
@@ -437,7 +448,7 @@ void GcodeSuite::G34() {
#endif #endif
}while(0); }while(0);
#endif #endif // Z_STEPPER_AUTO_ALIGN
} }
#endif // Z_MULTI_ENDSTOPS || Z_STEPPER_AUTO_ALIGN #endif // Z_MULTI_ENDSTOPS || Z_STEPPER_AUTO_ALIGN

View File

@@ -73,11 +73,23 @@
#if BOTH(CALIBRATION_MEASURE_LEFT, CALIBRATION_MEASURE_RIGHT) #if BOTH(CALIBRATION_MEASURE_LEFT, CALIBRATION_MEASURE_RIGHT)
#define HAS_X_CENTER 1 #define HAS_X_CENTER 1
#endif #endif
#if BOTH(CALIBRATION_MEASURE_FRONT, CALIBRATION_MEASURE_BACK) #if HAS_Y_AXIS && BOTH(CALIBRATION_MEASURE_FRONT, CALIBRATION_MEASURE_BACK)
#define HAS_Y_CENTER 1 #define HAS_Y_CENTER 1
#endif #endif
#if LINEAR_AXES >= 4 && BOTH(CALIBRATION_MEASURE_IMIN, CALIBRATION_MEASURE_IMAX)
#define HAS_I_CENTER 1
#endif
#if LINEAR_AXES >= 5 && BOTH(CALIBRATION_MEASURE_JMIN, CALIBRATION_MEASURE_JMAX)
#define HAS_J_CENTER 1
#endif
#if LINEAR_AXES >= 6 && BOTH(CALIBRATION_MEASURE_KMIN, CALIBRATION_MEASURE_KMAX)
#define HAS_K_CENTER 1
#endif
enum side_t : uint8_t { TOP, RIGHT, FRONT, LEFT, BACK, NUM_SIDES }; enum side_t : uint8_t {
TOP, RIGHT, FRONT, LEFT, BACK, NUM_SIDES,
LIST_N(DOUBLE(SUB3(LINEAR_AXES)), IMINIMUM, IMAXIMUM, JMINIMUM, JMAXIMUM, KMINIMUM, KMAXIMUM)
};
static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER; static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER;
static constexpr xyz_float_t dimensions CALIBRATION_OBJECT_DIMENSIONS; static constexpr xyz_float_t dimensions CALIBRATION_OBJECT_DIMENSIONS;
@@ -105,7 +117,7 @@ struct measurements_t {
#endif #endif
inline void calibration_move() { inline void calibration_move() {
do_blocking_move_to(current_position, MMM_TO_MMS(CALIBRATION_FEEDRATE_TRAVEL)); do_blocking_move_to((xyz_pos_t)current_position, MMM_TO_MMS(CALIBRATION_FEEDRATE_TRAVEL));
} }
/** /**
@@ -174,7 +186,7 @@ float measuring_movement(const AxisEnum axis, const int dir, const bool stop_sta
destination = current_position; destination = current_position;
for (float travel = 0; travel < limit; travel += step) { for (float travel = 0; travel < limit; travel += step) {
destination[axis] += dir * step; destination[axis] += dir * step;
do_blocking_move_to(destination, mms); do_blocking_move_to((xyz_pos_t)destination, mms);
planner.synchronize(); planner.synchronize();
if (read_calibration_pin() == stop_state) break; if (read_calibration_pin() == stop_state) break;
} }
@@ -194,18 +206,22 @@ float measuring_movement(const AxisEnum axis, const int dir, const bool stop_sta
inline float measure(const AxisEnum axis, const int dir, const bool stop_state, float * const backlash_ptr, const float uncertainty) { inline float measure(const AxisEnum axis, const int dir, const bool stop_state, float * const backlash_ptr, const float uncertainty) {
const bool fast = uncertainty == CALIBRATION_MEASUREMENT_UNKNOWN; const bool fast = uncertainty == CALIBRATION_MEASUREMENT_UNKNOWN;
// Save position // Save the current position of the specified axis
destination = current_position; const float start_pos = current_position[axis];
const float start_pos = destination[axis];
// Take a measurement. Only the specified axis will be affected.
const float measured_pos = measuring_movement(axis, dir, stop_state, fast); const float measured_pos = measuring_movement(axis, dir, stop_state, fast);
// Measure backlash // Measure backlash
if (backlash_ptr && !fast) { if (backlash_ptr && !fast) {
const float release_pos = measuring_movement(axis, -dir, !stop_state, fast); const float release_pos = measuring_movement(axis, -dir, !stop_state, fast);
*backlash_ptr = ABS(release_pos - measured_pos); *backlash_ptr = ABS(release_pos - measured_pos);
} }
// Return to starting position
// Move back to the starting position
destination = current_position;
destination[axis] = start_pos; destination[axis] = start_pos;
do_blocking_move_to(destination, MMM_TO_MMS(CALIBRATION_FEEDRATE_TRAVEL)); do_blocking_move_to((xyz_pos_t)destination, MMM_TO_MMS(CALIBRATION_FEEDRATE_TRAVEL));
return measured_pos; return measured_pos;
} }
@@ -226,7 +242,15 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t
park_above_object(m, uncertainty); park_above_object(m, uncertainty);
switch (side) { switch (side) {
#if AXIS_CAN_CALIBRATE(Z) #if AXIS_CAN_CALIBRATE(X)
case RIGHT: dir = -1;
case LEFT: axis = X_AXIS; break;
#endif
#if LINEAR_AXES >= 2 && AXIS_CAN_CALIBRATE(Y)
case BACK: dir = -1;
case FRONT: axis = Y_AXIS; break;
#endif
#if HAS_Z_AXIS && AXIS_CAN_CALIBRATE(Z)
case TOP: { case TOP: {
const float measurement = measure(Z_AXIS, -1, true, &m.backlash[TOP], uncertainty); const float measurement = measure(Z_AXIS, -1, true, &m.backlash[TOP], uncertainty);
m.obj_center.z = measurement - dimensions.z / 2; m.obj_center.z = measurement - dimensions.z / 2;
@@ -234,13 +258,17 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t
return; return;
} }
#endif #endif
#if AXIS_CAN_CALIBRATE(X) #if LINEAR_AXES >= 4 && AXIS_CAN_CALIBRATE(I)
case LEFT: axis = X_AXIS; break; case IMINIMUM: dir = -1;
case RIGHT: axis = X_AXIS; dir = -1; break; case IMAXIMUM: axis = I_AXIS; break;
#endif #endif
#if AXIS_CAN_CALIBRATE(Y) #if LINEAR_AXES >= 5 && AXIS_CAN_CALIBRATE(J)
case FRONT: axis = Y_AXIS; break; case JMINIMUM: dir = -1;
case BACK: axis = Y_AXIS; dir = -1; break; case JMAXIMUM: axis = J_AXIS; break;
#endif
#if LINEAR_AXES >= 6 && AXIS_CAN_CALIBRATE(K)
case KMINIMUM: dir = -1;
case KMAXIMUM: axis = K_AXIS; break;
#endif #endif
default: return; default: return;
} }
@@ -285,14 +313,23 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
probe_side(m, uncertainty, TOP); probe_side(m, uncertainty, TOP);
#endif #endif
TERN_(CALIBRATION_MEASURE_RIGHT, probe_side(m, uncertainty, RIGHT, probe_top_at_edge)); TERN_(CALIBRATION_MEASURE_RIGHT, probe_side(m, uncertainty, RIGHT, probe_top_at_edge));
TERN_(CALIBRATION_MEASURE_FRONT, probe_side(m, uncertainty, FRONT, probe_top_at_edge)); TERN_(CALIBRATION_MEASURE_FRONT, probe_side(m, uncertainty, FRONT, probe_top_at_edge));
TERN_(CALIBRATION_MEASURE_LEFT, probe_side(m, uncertainty, LEFT, probe_top_at_edge)); TERN_(CALIBRATION_MEASURE_LEFT, probe_side(m, uncertainty, LEFT, probe_top_at_edge));
TERN_(CALIBRATION_MEASURE_BACK, probe_side(m, uncertainty, BACK, probe_top_at_edge)); TERN_(CALIBRATION_MEASURE_BACK, probe_side(m, uncertainty, BACK, probe_top_at_edge));
TERN_(CALIBRATION_MEASURE_IMIN, probe_side(m, uncertainty, IMINIMUM, probe_top_at_edge));
TERN_(CALIBRATION_MEASURE_IMAX, probe_side(m, uncertainty, IMAXIMUM, probe_top_at_edge));
TERN_(CALIBRATION_MEASURE_JMIN, probe_side(m, uncertainty, JMINIMUM, probe_top_at_edge));
TERN_(CALIBRATION_MEASURE_JMAX, probe_side(m, uncertainty, JMAXIMUM, probe_top_at_edge));
TERN_(CALIBRATION_MEASURE_KMIN, probe_side(m, uncertainty, KMINIMUM, probe_top_at_edge));
TERN_(CALIBRATION_MEASURE_KMAX, probe_side(m, uncertainty, KMAXIMUM, probe_top_at_edge));
// Compute the measured center of the calibration object. // Compute the measured center of the calibration object.
TERN_(HAS_X_CENTER, m.obj_center.x = (m.obj_side[LEFT] + m.obj_side[RIGHT]) / 2); TERN_(HAS_X_CENTER, m.obj_center.x = (m.obj_side[LEFT] + m.obj_side[RIGHT]) / 2);
TERN_(HAS_Y_CENTER, m.obj_center.y = (m.obj_side[FRONT] + m.obj_side[BACK]) / 2); TERN_(HAS_Y_CENTER, m.obj_center.y = (m.obj_side[FRONT] + m.obj_side[BACK]) / 2);
TERN_(HAS_I_CENTER, m.obj_center.i = (m.obj_side[IMINIMUM] + m.obj_side[IMAXIMUM]) / 2);
TERN_(HAS_J_CENTER, m.obj_center.j = (m.obj_side[JMINIMUM] + m.obj_side[JMAXIMUM]) / 2);
TERN_(HAS_K_CENTER, m.obj_center.k = (m.obj_side[KMINIMUM] + m.obj_side[KMAXIMUM]) / 2);
// Compute the outside diameter of the nozzle at the height // Compute the outside diameter of the nozzle at the height
// at which it makes contact with the calibration object // at which it makes contact with the calibration object
@@ -303,23 +340,20 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
// The difference between the known and the measured location // The difference between the known and the measured location
// of the calibration object is the positional error // of the calibration object is the positional error
m.pos_error.x = (0 LINEAR_AXIS_CODE(
#if HAS_X_CENTER m.pos_error.x = TERN0(HAS_X_CENTER, true_center.x - m.obj_center.x),
+ true_center.x - m.obj_center.x m.pos_error.y = TERN0(HAS_Y_CENTER, true_center.y - m.obj_center.y),
#endif m.pos_error.z = true_center.z - m.obj_center.z,
m.pos_error.i = TERN0(HAS_I_CENTER, true_center.i - m.obj_center.i),
m.pos_error.j = TERN0(HAS_J_CENTER, true_center.j - m.obj_center.j),
m.pos_error.k = TERN0(HAS_K_CENTER, true_center.k - m.obj_center.k)
); );
m.pos_error.y = (0
#if HAS_Y_CENTER
+ true_center.y - m.obj_center.y
#endif
);
m.pos_error.z = true_center.z - m.obj_center.z;
} }
#if ENABLED(CALIBRATION_REPORTING) #if ENABLED(CALIBRATION_REPORTING)
inline void report_measured_faces(const measurements_t &m) { inline void report_measured_faces(const measurements_t &m) {
SERIAL_ECHOLNPGM("Sides:"); SERIAL_ECHOLNPGM("Sides:");
#if AXIS_CAN_CALIBRATE(Z) #if HAS_Z_AXIS && AXIS_CAN_CALIBRATE(Z)
SERIAL_ECHOLNPAIR(" Top: ", m.obj_side[TOP]); SERIAL_ECHOLNPAIR(" Top: ", m.obj_side[TOP]);
#endif #endif
#if ENABLED(CALIBRATION_MEASURE_LEFT) #if ENABLED(CALIBRATION_MEASURE_LEFT)
@@ -328,11 +362,37 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
#if ENABLED(CALIBRATION_MEASURE_RIGHT) #if ENABLED(CALIBRATION_MEASURE_RIGHT)
SERIAL_ECHOLNPAIR(" Right: ", m.obj_side[RIGHT]); SERIAL_ECHOLNPAIR(" Right: ", m.obj_side[RIGHT]);
#endif #endif
#if ENABLED(CALIBRATION_MEASURE_FRONT) #if HAS_Y_AXIS
SERIAL_ECHOLNPAIR(" Front: ", m.obj_side[FRONT]); #if ENABLED(CALIBRATION_MEASURE_FRONT)
SERIAL_ECHOLNPAIR(" Front: ", m.obj_side[FRONT]);
#endif
#if ENABLED(CALIBRATION_MEASURE_BACK)
SERIAL_ECHOLNPAIR(" Back: ", m.obj_side[BACK]);
#endif
#endif #endif
#if ENABLED(CALIBRATION_MEASURE_BACK) #if LINEAR_AXES >= 4
SERIAL_ECHOLNPAIR(" Back: ", m.obj_side[BACK]); #if ENABLED(CALIBRATION_MEASURE_IMIN)
SERIAL_ECHOLNPAIR(" " STR_I_MIN ": ", m.obj_side[IMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_IMAX)
SERIAL_ECHOLNPAIR(" " STR_I_MAX ": ", m.obj_side[IMAXIMUM]);
#endif
#endif
#if LINEAR_AXES >= 5
#if ENABLED(CALIBRATION_MEASURE_JMIN)
SERIAL_ECHOLNPAIR(" " STR_J_MIN ": ", m.obj_side[JMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_JMAX)
SERIAL_ECHOLNPAIR(" " STR_J_MAX ": ", m.obj_side[JMAXIMUM]);
#endif
#endif
#if LINEAR_AXES >= 6
#if ENABLED(CALIBRATION_MEASURE_KMIN)
SERIAL_ECHOLNPAIR(" " STR_K_MIN ": ", m.obj_side[KMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_KMAX)
SERIAL_ECHOLNPAIR(" " STR_K_MAX ": ", m.obj_side[KMAXIMUM]);
#endif
#endif #endif
SERIAL_EOL(); SERIAL_EOL();
} }
@@ -346,6 +406,15 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
SERIAL_ECHOLNPAIR_P(SP_Y_STR, m.obj_center.y); SERIAL_ECHOLNPAIR_P(SP_Y_STR, m.obj_center.y);
#endif #endif
SERIAL_ECHOLNPAIR_P(SP_Z_STR, m.obj_center.z); SERIAL_ECHOLNPAIR_P(SP_Z_STR, m.obj_center.z);
#if HAS_I_CENTER
SERIAL_ECHOLNPAIR_P(SP_I_STR, m.obj_center.i);
#endif
#if HAS_J_CENTER
SERIAL_ECHOLNPAIR_P(SP_J_STR, m.obj_center.j);
#endif
#if HAS_K_CENTER
SERIAL_ECHOLNPAIR_P(SP_K_STR, m.obj_center.k);
#endif
SERIAL_EOL(); SERIAL_EOL();
} }
@@ -359,7 +428,7 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
SERIAL_ECHOLNPAIR(" Right: ", m.backlash[RIGHT]); SERIAL_ECHOLNPAIR(" Right: ", m.backlash[RIGHT]);
#endif #endif
#endif #endif
#if AXIS_CAN_CALIBRATE(Y) #if HAS_Y_AXIS && AXIS_CAN_CALIBRATE(Y)
#if ENABLED(CALIBRATION_MEASURE_FRONT) #if ENABLED(CALIBRATION_MEASURE_FRONT)
SERIAL_ECHOLNPAIR(" Front: ", m.backlash[FRONT]); SERIAL_ECHOLNPAIR(" Front: ", m.backlash[FRONT]);
#endif #endif
@@ -367,9 +436,33 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
SERIAL_ECHOLNPAIR(" Back: ", m.backlash[BACK]); SERIAL_ECHOLNPAIR(" Back: ", m.backlash[BACK]);
#endif #endif
#endif #endif
#if AXIS_CAN_CALIBRATE(Z) #if HAS_Z_AXIS && AXIS_CAN_CALIBRATE(Z)
SERIAL_ECHOLNPAIR(" Top: ", m.backlash[TOP]); SERIAL_ECHOLNPAIR(" Top: ", m.backlash[TOP]);
#endif #endif
#if LINEAR_AXES >= 4 && AXIS_CAN_CALIBRATE(I)
#if ENABLED(CALIBRATION_MEASURE_IMIN)
SERIAL_ECHOLNPAIR(" " STR_I_MIN ": ", m.backlash[IMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_IMAX)
SERIAL_ECHOLNPAIR(" " STR_I_MAX ": ", m.backlash[IMAXIMUM]);
#endif
#endif
#if LINEAR_AXES >= 5 && AXIS_CAN_CALIBRATE(J)
#if ENABLED(CALIBRATION_MEASURE_JMIN)
SERIAL_ECHOLNPAIR(" " STR_J_MIN ": ", m.backlash[JMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_JMAX)
SERIAL_ECHOLNPAIR(" " STR_J_MAX ": ", m.backlash[JMAXIMUM]);
#endif
#endif
#if LINEAR_AXES >= 6 && AXIS_CAN_CALIBRATE(K)
#if ENABLED(CALIBRATION_MEASURE_KMIN)
SERIAL_ECHOLNPAIR(" " STR_K_MIN ": ", m.backlash[KMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_KMAX)
SERIAL_ECHOLNPAIR(" " STR_K_MAX ": ", m.backlash[KMAXIMUM]);
#endif
#endif
SERIAL_EOL(); SERIAL_EOL();
} }
@@ -377,29 +470,37 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
SERIAL_CHAR('T'); SERIAL_CHAR('T');
SERIAL_ECHO(active_extruder); SERIAL_ECHO(active_extruder);
SERIAL_ECHOLNPGM(" Positional Error:"); SERIAL_ECHOLNPGM(" Positional Error:");
#if HAS_X_CENTER #if HAS_X_CENTER && AXIS_CAN_CALIBRATE(X)
SERIAL_ECHOLNPAIR_P(SP_X_STR, m.pos_error.x); SERIAL_ECHOLNPAIR_P(SP_X_STR, m.pos_error.x);
#endif #endif
#if HAS_Y_CENTER #if HAS_Y_CENTER && AXIS_CAN_CALIBRATE(Y)
SERIAL_ECHOLNPAIR_P(SP_Y_STR, m.pos_error.y); SERIAL_ECHOLNPAIR_P(SP_Y_STR, m.pos_error.y);
#endif #endif
if (AXIS_CAN_CALIBRATE(Z)) SERIAL_ECHOLNPAIR_P(SP_Z_STR, m.pos_error.z); #if HAS_Z_AXIS && AXIS_CAN_CALIBRATE(Z)
SERIAL_ECHOLNPAIR_P(SP_Z_STR, m.pos_error.z);
#endif
#if HAS_I_CENTER && AXIS_CAN_CALIBRATE(I)
SERIAL_ECHOLNPAIR_P(SP_I_STR, m.pos_error.i);
#endif
#if HAS_J_CENTER && AXIS_CAN_CALIBRATE(J)
SERIAL_ECHOLNPAIR_P(SP_J_STR, m.pos_error.j);
#endif
#if HAS_K_CENTER && AXIS_CAN_CALIBRATE(K)
SERIAL_ECHOLNPAIR_P(SP_Z_STR, m.pos_error.z);
#endif
SERIAL_EOL(); SERIAL_EOL();
} }
inline void report_measured_nozzle_dimensions(const measurements_t &m) { inline void report_measured_nozzle_dimensions(const measurements_t &m) {
SERIAL_ECHOLNPGM("Nozzle Tip Outer Dimensions:"); SERIAL_ECHOLNPGM("Nozzle Tip Outer Dimensions:");
#if HAS_X_CENTER || HAS_Y_CENTER #if HAS_X_CENTER
#if HAS_X_CENTER SERIAL_ECHOLNPAIR_P(SP_X_STR, m.nozzle_outer_dimension.x);
SERIAL_ECHOLNPAIR_P(SP_X_STR, m.nozzle_outer_dimension.x); #endif
#endif #if HAS_Y_CENTER
#if HAS_Y_CENTER SERIAL_ECHOLNPAIR_P(SP_Y_STR, m.nozzle_outer_dimension.y);
SERIAL_ECHOLNPAIR_P(SP_Y_STR, m.nozzle_outer_dimension.y);
#endif
#else
UNUSED(m);
#endif #endif
SERIAL_EOL(); SERIAL_EOL();
UNUSED(m);
} }
#if HAS_HOTEND_OFFSET #if HAS_HOTEND_OFFSET
@@ -448,8 +549,33 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) {
backlash.distance_mm.y = m.backlash[BACK]; backlash.distance_mm.y = m.backlash[BACK];
#endif #endif
if (AXIS_CAN_CALIBRATE(Z)) backlash.distance_mm.z = m.backlash[TOP]; TERN_(HAS_Z_AXIS, if (AXIS_CAN_CALIBRATE(Z)) backlash.distance_mm.z = m.backlash[TOP]);
#endif
#if HAS_I_CENTER
backlash.distance_mm.i = (m.backlash[IMINIMUM] + m.backlash[IMAXIMUM]) / 2;
#elif ENABLED(CALIBRATION_MEASURE_IMIN)
backlash.distance_mm.i = m.backlash[IMINIMUM];
#elif ENABLED(CALIBRATION_MEASURE_IMAX)
backlash.distance_mm.i = m.backlash[IMAXIMUM];
#endif
#if HAS_J_CENTER
backlash.distance_mm.j = (m.backlash[JMINIMUM] + m.backlash[JMAXIMUM]) / 2;
#elif ENABLED(CALIBRATION_MEASURE_JMIN)
backlash.distance_mm.j = m.backlash[JMINIMUM];
#elif ENABLED(CALIBRATION_MEASURE_JMAX)
backlash.distance_mm.j = m.backlash[JMAXIMUM];
#endif
#if HAS_K_CENTER
backlash.distance_mm.k = (m.backlash[KMINIMUM] + m.backlash[KMAXIMUM]) / 2;
#elif ENABLED(CALIBRATION_MEASURE_KMIN)
backlash.distance_mm.k = m.backlash[KMINIMUM];
#elif ENABLED(CALIBRATION_MEASURE_KMAX)
backlash.distance_mm.k = m.backlash[KMAXIMUM];
#endif
#endif // BACKLASH_GCODE
} }
#if ENABLED(BACKLASH_GCODE) #if ENABLED(BACKLASH_GCODE)
@@ -459,7 +585,10 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) {
// New scope for TEMPORARY_BACKLASH_CORRECTION // New scope for TEMPORARY_BACKLASH_CORRECTION
TEMPORARY_BACKLASH_CORRECTION(all_on); TEMPORARY_BACKLASH_CORRECTION(all_on);
TEMPORARY_BACKLASH_SMOOTHING(0.0f); TEMPORARY_BACKLASH_SMOOTHING(0.0f);
const xyz_float_t move = { AXIS_CAN_CALIBRATE(X) * 3, AXIS_CAN_CALIBRATE(Y) * 3, AXIS_CAN_CALIBRATE(Z) * 3 }; const xyz_float_t move = LINEAR_AXIS_ARRAY(
AXIS_CAN_CALIBRATE(X) * 3, AXIS_CAN_CALIBRATE(Y) * 3, AXIS_CAN_CALIBRATE(Z) * 3,
AXIS_CAN_CALIBRATE(I) * 3, AXIS_CAN_CALIBRATE(J) * 3, AXIS_CAN_CALIBRATE(K) * 3
);
current_position += move; calibration_move(); current_position += move; calibration_move();
current_position -= move; calibration_move(); current_position -= move; calibration_move();
} }
@@ -487,11 +616,7 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const
TEMPORARY_BACKLASH_CORRECTION(all_on); TEMPORARY_BACKLASH_CORRECTION(all_on);
TEMPORARY_BACKLASH_SMOOTHING(0.0f); TEMPORARY_BACKLASH_SMOOTHING(0.0f);
#if HAS_MULTI_HOTEND TERN(HAS_MULTI_HOTEND, set_nozzle(m, extruder), UNUSED(extruder));
set_nozzle(m, extruder);
#else
UNUSED(extruder);
#endif
probe_sides(m, uncertainty); probe_sides(m, uncertainty);
@@ -510,6 +635,10 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const
if (ENABLED(HAS_Y_CENTER) && AXIS_CAN_CALIBRATE(Y)) update_measurements(m, Y_AXIS); if (ENABLED(HAS_Y_CENTER) && AXIS_CAN_CALIBRATE(Y)) update_measurements(m, Y_AXIS);
if (AXIS_CAN_CALIBRATE(Z)) update_measurements(m, Z_AXIS); if (AXIS_CAN_CALIBRATE(Z)) update_measurements(m, Z_AXIS);
TERN_(HAS_I_CENTER, update_measurements(m, I_AXIS));
TERN_(HAS_J_CENTER, update_measurements(m, J_AXIS));
TERN_(HAS_K_CENTER, update_measurements(m, K_AXIS));
sync_plan_position(); sync_plan_position();
} }
@@ -589,12 +718,12 @@ void GcodeSuite::G425() {
SET_SOFT_ENDSTOP_LOOSE(true); SET_SOFT_ENDSTOP_LOOSE(true);
measurements_t m; measurements_t m;
float uncertainty = parser.seenval('U') ? parser.value_float() : CALIBRATION_MEASUREMENT_UNCERTAIN; const float uncertainty = parser.floatval('U', CALIBRATION_MEASUREMENT_UNCERTAIN);
if (parser.seen('B')) if (parser.seen_test('B'))
calibrate_backlash(m, uncertainty); calibrate_backlash(m, uncertainty);
else if (parser.seen('T')) else if (parser.seen_test('T'))
calibrate_toolhead(m, uncertainty, parser.has_value() ? parser.value_int() : active_extruder); calibrate_toolhead(m, uncertainty, parser.intval('T', active_extruder));
#if ENABLED(CALIBRATION_REPORTING) #if ENABLED(CALIBRATION_REPORTING)
else if (parser.seen('V')) { else if (parser.seen('V')) {
probe_sides(m, uncertainty); probe_sides(m, uncertainty);

View File

@@ -48,15 +48,20 @@ void GcodeSuite::M425() {
auto axis_can_calibrate = [](const uint8_t a) { auto axis_can_calibrate = [](const uint8_t a) {
switch (a) { switch (a) {
default: default: return false;
case X_AXIS: return AXIS_CAN_CALIBRATE(X); LINEAR_AXIS_CODE(
case Y_AXIS: return AXIS_CAN_CALIBRATE(Y); case X_AXIS: return AXIS_CAN_CALIBRATE(X),
case Z_AXIS: return AXIS_CAN_CALIBRATE(Z); case Y_AXIS: return AXIS_CAN_CALIBRATE(Y),
case Z_AXIS: return AXIS_CAN_CALIBRATE(Z),
case I_AXIS: return AXIS_CAN_CALIBRATE(I),
case J_AXIS: return AXIS_CAN_CALIBRATE(J),
case K_AXIS: return AXIS_CAN_CALIBRATE(K),
);
} }
}; };
LOOP_XYZ(a) { LOOP_LINEAR_AXES(a) {
if (axis_can_calibrate(a) && parser.seen(XYZ_CHAR(a))) { if (axis_can_calibrate(a) && parser.seen(AXIS_CHAR(a))) {
planner.synchronize(); planner.synchronize();
backlash.distance_mm[a] = parser.has_value() ? parser.value_linear_units() : backlash.get_measurement(AxisEnum(a)); backlash.distance_mm[a] = parser.has_value() ? parser.value_linear_units() : backlash.get_measurement(AxisEnum(a));
noArgs = false; noArgs = false;
@@ -83,8 +88,8 @@ void GcodeSuite::M425() {
SERIAL_ECHOLNPGM("active:"); SERIAL_ECHOLNPGM("active:");
SERIAL_ECHOLNPAIR(" Correction Amount/Fade-out: F", backlash.get_correction(), " (F1.0 = full, F0.0 = none)"); SERIAL_ECHOLNPAIR(" Correction Amount/Fade-out: F", backlash.get_correction(), " (F1.0 = full, F0.0 = none)");
SERIAL_ECHOPGM(" Backlash Distance (mm): "); SERIAL_ECHOPGM(" Backlash Distance (mm): ");
LOOP_XYZ(a) if (axis_can_calibrate(a)) { LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a)) {
SERIAL_CHAR(' ', XYZ_CHAR(a)); SERIAL_CHAR(' ', AXIS_CHAR(a));
SERIAL_ECHO(backlash.distance_mm[a]); SERIAL_ECHO(backlash.distance_mm[a]);
SERIAL_EOL(); SERIAL_EOL();
} }
@@ -96,8 +101,8 @@ void GcodeSuite::M425() {
#if ENABLED(MEASURE_BACKLASH_WHEN_PROBING) #if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
SERIAL_ECHOPGM(" Average measured backlash (mm):"); SERIAL_ECHOPGM(" Average measured backlash (mm):");
if (backlash.has_any_measurement()) { if (backlash.has_any_measurement()) {
LOOP_XYZ(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) { LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) {
SERIAL_CHAR(' ', XYZ_CHAR(a)); SERIAL_CHAR(' ', AXIS_CHAR(a));
SERIAL_ECHO(backlash.get_measurement(AxisEnum(a))); SERIAL_ECHO(backlash.get_measurement(AxisEnum(a)));
} }
} }

View File

@@ -39,11 +39,11 @@
*/ */
void GcodeSuite::M666() { void GcodeSuite::M666() {
DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING)); DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING));
LOOP_XYZ(i) { LOOP_LINEAR_AXES(i) {
if (parser.seen(XYZ_CHAR(i))) { if (parser.seen(AXIS_CHAR(i))) {
const float v = parser.value_linear_units(); const float v = parser.value_linear_units();
if (v * Z_HOME_DIR <= 0) delta_endstop_adj[i] = v; if (v * Z_HOME_DIR <= 0) delta_endstop_adj[i] = v;
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("delta_endstop_adj[", AS_CHAR(XYZ_CHAR(i)), "] = ", delta_endstop_adj[i]); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("delta_endstop_adj[", AS_CHAR(AXIS_CHAR(i)), "] = ", delta_endstop_adj[i]);
} }
} }
} }
@@ -71,29 +71,27 @@
#endif #endif
#if ENABLED(Z_MULTI_ENDSTOPS) #if ENABLED(Z_MULTI_ENDSTOPS)
if (parser.seenval('Z')) { if (parser.seenval('Z')) {
#if NUM_Z_STEPPER_DRIVERS >= 3 const float z_adj = parser.value_linear_units();
const float z_adj = parser.value_linear_units(); #if NUM_Z_STEPPER_DRIVERS == 2
const int ind = parser.intval('S'); endstops.z2_endstop_adj = z_adj;
if (!ind || ind == 2) endstops.z2_endstop_adj = z_adj;
if (!ind || ind == 3) endstops.z3_endstop_adj = z_adj;
#if NUM_Z_STEPPER_DRIVERS >= 4
if (!ind || ind == 4) endstops.z4_endstop_adj = z_adj;
#endif
#else #else
endstops.z2_endstop_adj = parser.value_linear_units(); const int ind = parser.intval('S');
#define _SET_ZADJ(N) if (!ind || ind == N) endstops.z##N##_endstop_adj = z_adj;
REPEAT_S(2, INCREMENT(NUM_Z_STEPPER_DRIVERS), _SET_ZADJ)
#endif #endif
} }
#endif #endif
if (!parser.seen("XYZ")) { if (!parser.seen("XYZ")) {
auto echo_adj = [](PGM_P const label, const_float_t value) { SERIAL_ECHOPAIR_P(label, value); };
SERIAL_ECHOPGM("Dual Endstop Adjustment (mm): "); SERIAL_ECHOPGM("Dual Endstop Adjustment (mm): ");
#if ENABLED(X_DUAL_ENDSTOPS) #if ENABLED(X_DUAL_ENDSTOPS)
SERIAL_ECHOPAIR(" X2:", endstops.x2_endstop_adj); echo_adj(PSTR(" X2:"), endstops.x2_endstop_adj);
#endif #endif
#if ENABLED(Y_DUAL_ENDSTOPS) #if ENABLED(Y_DUAL_ENDSTOPS)
SERIAL_ECHOPAIR(" Y2:", endstops.y2_endstop_adj); echo_adj(PSTR(" Y2:"), endstops.y2_endstop_adj);
#endif #endif
#if ENABLED(Z_MULTI_ENDSTOPS) #if ENABLED(Z_MULTI_ENDSTOPS)
#define _ECHO_ZADJ(N) SERIAL_ECHOPAIR(" Z" STRINGIFY(N) ":", endstops.z##N##_endstop_adj); #define _ECHO_ZADJ(N) echo_adj(PSTR(" Z" STRINGIFY(N) ":"), endstops.z##N##_endstop_adj);
REPEAT_S(2, INCREMENT(NUM_Z_STEPPER_DRIVERS), _ECHO_ZADJ) REPEAT_S(2, INCREMENT(NUM_Z_STEPPER_DRIVERS), _ECHO_ZADJ)
#endif #endif
SERIAL_EOL(); SERIAL_EOL();

View File

@@ -86,7 +86,7 @@ void GcodeSuite::M852() {
// When skew is changed the current position changes // When skew is changed the current position changes
if (setval) { if (setval) {
set_current_from_steppers_for_axis(ALL_AXES); set_current_from_steppers_for_axis(ALL_AXES_ENUM);
sync_plan_position(); sync_plan_position();
report_current_position(); report_current_position();
} }

View File

@@ -86,9 +86,9 @@ void GcodeSuite::M201() {
if (parser.seenval('G')) planner.xy_freq_min_speed_factor = constrain(parser.value_float(), 1, 100) / 100; if (parser.seenval('G')) planner.xy_freq_min_speed_factor = constrain(parser.value_float(), 1, 100) / 100;
#endif #endif
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (parser.seen(axis_codes[i])) { if (parser.seenval(axis_codes[i])) {
const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i); const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i);
planner.set_max_acceleration(a, parser.value_axis_units((AxisEnum)a)); planner.set_max_acceleration(a, parser.value_axis_units((AxisEnum)a));
} }
} }
@@ -104,9 +104,9 @@ void GcodeSuite::M203() {
const int8_t target_extruder = get_target_extruder_from_command(); const int8_t target_extruder = get_target_extruder_from_command();
if (target_extruder < 0) return; if (target_extruder < 0) return;
LOOP_XYZE(i) LOOP_LOGICAL_AXES(i)
if (parser.seen(axis_codes[i])) { if (parser.seenval(axis_codes[i])) {
const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i); const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i);
planner.set_max_feedrate(a, parser.value_axis_units((AxisEnum)a)); planner.set_max_feedrate(a, parser.value_axis_units((AxisEnum)a));
} }
} }
@@ -147,24 +147,17 @@ void GcodeSuite::M204() {
* J = Junction Deviation (mm) (If not using CLASSIC_JERK) * J = Junction Deviation (mm) (If not using CLASSIC_JERK)
*/ */
void GcodeSuite::M205() { void GcodeSuite::M205() {
#if HAS_JUNCTION_DEVIATION if (!parser.seen("BST" TERN_(HAS_JUNCTION_DEVIATION, "J") TERN_(HAS_CLASSIC_JERK, "XYZE"))) return;
#define J_PARAM "J"
#else
#define J_PARAM
#endif
#if HAS_CLASSIC_JERK
#define XYZE_PARAM "XYZE"
#else
#define XYZE_PARAM
#endif
if (!parser.seen("BST" J_PARAM XYZE_PARAM)) return;
//planner.synchronize(); //planner.synchronize();
if (parser.seen('B')) planner.settings.min_segment_time_us = parser.value_ulong(); if (parser.seenval('B')) planner.settings.min_segment_time_us = parser.value_ulong();
if (parser.seen('S')) planner.settings.min_feedrate_mm_s = parser.value_linear_units(); if (parser.seenval('S')) planner.settings.min_feedrate_mm_s = parser.value_linear_units();
if (parser.seen('T')) planner.settings.min_travel_feedrate_mm_s = parser.value_linear_units(); if (parser.seenval('T')) planner.settings.min_travel_feedrate_mm_s = parser.value_linear_units();
#if HAS_JUNCTION_DEVIATION #if HAS_JUNCTION_DEVIATION
if (parser.seen('J')) { #if HAS_CLASSIC_JERK && (AXIS4_NAME == 'J' || AXIS5_NAME == 'J' || AXIS6_NAME == 'J')
#error "Can't set_max_jerk for 'J' axis because 'J' is used for Junction Deviation."
#endif
if (parser.seenval('J')) {
const float junc_dev = parser.value_linear_units(); const float junc_dev = parser.value_linear_units();
if (WITHIN(junc_dev, 0.01f, 0.3f)) { if (WITHIN(junc_dev, 0.01f, 0.3f)) {
planner.junction_deviation_mm = junc_dev; planner.junction_deviation_mm = junc_dev;
@@ -175,17 +168,19 @@ void GcodeSuite::M205() {
} }
#endif #endif
#if HAS_CLASSIC_JERK #if HAS_CLASSIC_JERK
if (parser.seen('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units()); bool seenZ = false;
if (parser.seen('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units()); LOGICAL_AXIS_CODE(
if (parser.seen('Z')) { if (parser.seenval('E')) planner.set_max_jerk(E_AXIS, parser.value_linear_units()),
planner.set_max_jerk(Z_AXIS, parser.value_linear_units()); if (parser.seenval('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units()),
#if HAS_MESH && DISABLED(LIMITED_JERK_EDITING) if (parser.seenval('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units()),
if (planner.max_jerk.z <= 0.1f) if ((seenZ = parser.seenval('Z'))) planner.set_max_jerk(Z_AXIS, parser.value_linear_units()),
SERIAL_ECHOLNPGM("WARNING! Low Z Jerk may lead to unwanted pauses."); if (parser.seenval(AXIS4_NAME)) planner.set_max_jerk(I_AXIS, parser.value_linear_units()),
#endif if (parser.seenval(AXIS5_NAME)) planner.set_max_jerk(J_AXIS, parser.value_linear_units()),
} if (parser.seenval(AXIS6_NAME)) planner.set_max_jerk(K_AXIS, parser.value_linear_units())
#if HAS_CLASSIC_E_JERK );
if (parser.seen('E')) planner.set_max_jerk(E_AXIS, parser.value_linear_units()); #if HAS_MESH && DISABLED(LIMITED_JERK_EDITING)
if (seenZ && planner.max_jerk.z <= 0.1f)
SERIAL_ECHOLNPGM("WARNING! Low Z Jerk may lead to unwanted pauses.");
#endif #endif
#endif #endif // HAS_CLASSIC_JERK
} }

View File

@@ -23,7 +23,7 @@
#include "../gcode.h" #include "../gcode.h"
#include "../../module/planner.h" #include "../../module/planner.h"
#if EXTRUDERS #if HAS_EXTRUDERS
/** /**
* M221: Set extrusion percentage (M221 T0 S95) * M221: Set extrusion percentage (M221 T0 S95)

View File

@@ -25,10 +25,15 @@
void report_M92(const bool echo=true, const int8_t e=-1) { void report_M92(const bool echo=true, const int8_t e=-1) {
if (echo) SERIAL_ECHO_START(); else SERIAL_CHAR(' '); if (echo) SERIAL_ECHO_START(); else SERIAL_CHAR(' ');
SERIAL_ECHOPAIR_P(PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]), SERIAL_ECHOPAIR_P(LIST_N(DOUBLE(LINEAR_AXES),
SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]), PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]),
SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS])); SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]),
#if DISABLED(DISTINCT_E_FACTORS) SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS]),
SP_I_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[I_AXIS]),
SP_J_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[J_AXIS]),
SP_K_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[K_AXIS]))
);
#if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS)
SERIAL_ECHOPAIR_P(SP_E_STR, VOLUMETRIC_UNIT(planner.settings.axis_steps_per_mm[E_AXIS])); SERIAL_ECHOPAIR_P(SP_E_STR, VOLUMETRIC_UNIT(planner.settings.axis_steps_per_mm[E_AXIS]));
#endif #endif
SERIAL_EOL(); SERIAL_EOL();
@@ -42,7 +47,7 @@ void report_M92(const bool echo=true, const int8_t e=-1) {
} }
#endif #endif
UNUSED_E(e); UNUSED(e);
} }
/** /**
@@ -64,28 +69,28 @@ void GcodeSuite::M92() {
if (target_extruder < 0) return; if (target_extruder < 0) return;
// No arguments? Show M92 report. // No arguments? Show M92 report.
if (!parser.seen("XYZE" if (!parser.seen(
#if ENABLED(MAGIC_NUMBERS_GCODE) LOGICAL_AXIS_GANG("E", "X", "Y", "Z", AXIS4_STR, AXIS5_STR, AXIS6_STR)
"HL" TERN_(MAGIC_NUMBERS_GCODE, "HL")
#endif
)) return report_M92(true, target_extruder); )) return report_M92(true, target_extruder);
LOOP_XYZE(i) { LOOP_LOGICAL_AXES(i) {
if (parser.seenval(axis_codes[i])) { if (parser.seenval(axis_codes[i])) {
if (i == E_AXIS) { if (TERN1(HAS_EXTRUDERS, i != E_AXIS))
const float value = parser.value_per_axis_units((AxisEnum)(E_AXIS_N(target_extruder)));
if (value < 20) {
float factor = planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] / value; // increase e constants if M92 E14 is given for netfab.
#if HAS_CLASSIC_JERK && HAS_CLASSIC_E_JERK
planner.max_jerk.e *= factor;
#endif
planner.settings.max_feedrate_mm_s[E_AXIS_N(target_extruder)] *= factor;
planner.max_acceleration_steps_per_s2[E_AXIS_N(target_extruder)] *= factor;
}
planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] = value;
}
else {
planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i); planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i);
else {
#if HAS_EXTRUDERS
const float value = parser.value_per_axis_units((AxisEnum)(E_AXIS_N(target_extruder)));
if (value < 20) {
float factor = planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] / value; // increase e constants if M92 E14 is given for netfab.
#if HAS_CLASSIC_JERK && HAS_CLASSIC_E_JERK
planner.max_jerk.e *= factor;
#endif
planner.settings.max_feedrate_mm_s[E_AXIS_N(target_extruder)] *= factor;
planner.max_acceleration_steps_per_s2[E_AXIS_N(target_extruder)] *= factor;
}
planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] = value;
#endif
} }
} }
} }

View File

@@ -33,11 +33,16 @@
* M17: Enable stepper motors * M17: Enable stepper motors
*/ */
void GcodeSuite::M17() { void GcodeSuite::M17() {
if (parser.seen("XYZE")) { if (parser.seen(LOGICAL_AXIS_GANG("E", "X", "Y", "Z", AXIS4_STR, AXIS5_STR, AXIS6_STR))) {
if (parser.seen('X')) ENABLE_AXIS_X(); LOGICAL_AXIS_CODE(
if (parser.seen('Y')) ENABLE_AXIS_Y(); if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen_test('E'))) enable_e_steppers(),
if (parser.seen('Z')) ENABLE_AXIS_Z(); if (parser.seen_test('X')) ENABLE_AXIS_X(),
if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen('E'))) enable_e_steppers(); if (parser.seen_test('Y')) ENABLE_AXIS_Y(),
if (parser.seen_test('Z')) ENABLE_AXIS_Z(),
if (parser.seen_test(AXIS4_NAME)) ENABLE_AXIS_I(),
if (parser.seen_test(AXIS5_NAME)) ENABLE_AXIS_J(),
if (parser.seen_test(AXIS6_NAME)) ENABLE_AXIS_K()
);
} }
else { else {
LCD_MESSAGEPGM(MSG_NO_MOVE); LCD_MESSAGEPGM(MSG_NO_MOVE);
@@ -54,12 +59,17 @@ void GcodeSuite::M18_M84() {
stepper_inactive_time = parser.value_millis_from_seconds(); stepper_inactive_time = parser.value_millis_from_seconds();
} }
else { else {
if (parser.seen("XYZE")) { if (parser.seen(LOGICAL_AXIS_GANG("E", "X", "Y", "Z", AXIS4_STR, AXIS5_STR, AXIS6_STR))) {
planner.synchronize(); planner.synchronize();
if (parser.seen('X')) DISABLE_AXIS_X(); LOGICAL_AXIS_CODE(
if (parser.seen('Y')) DISABLE_AXIS_Y(); if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen_test('E'))) disable_e_steppers(),
if (parser.seen('Z')) DISABLE_AXIS_Z(); if (parser.seen_test('X')) DISABLE_AXIS_X(),
if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen('E'))) disable_e_steppers(); if (parser.seen_test('Y')) DISABLE_AXIS_Y(),
if (parser.seen_test('Z')) DISABLE_AXIS_Z(),
if (parser.seen_test(AXIS4_NAME)) DISABLE_AXIS_I(),
if (parser.seen_test(AXIS5_NAME)) DISABLE_AXIS_J(),
if (parser.seen_test(AXIS6_NAME)) DISABLE_AXIS_K()
);
} }
else else
planner.finish_and_disable(); planner.finish_and_disable();

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