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
steps:
- uses: peter-evans/close-pull@v1
- uses: superbrothers/close-pull-request@v3
with:
token: ${{ github.token }}
delete-branch: false
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.

View File

@@ -56,29 +56,31 @@ jobs:
# STM32F1 (Maple) Environments
- STM32F103RC_btt
- STM32F103RC_btt_USB
- STM32F103RE_btt
- STM32F103RE_btt_USB
#- STM32F103RC_btt_maple
- STM32F103RC_btt_USB_maple
- STM32F103RC_fysetc
- STM32F103RC_meeb
- jgaurora_a5s_a1
- STM32F103VE_longer
- mks_robin
#- mks_robin_maple
- mks_robin_lite
- mks_robin_pro
- STM32F103RET6_creality
- mks_robin_nano35
#- mks_robin_nano35_maple
#- STM32F103RET6_creality_maple
# STM32 (ST) Environments
- STM32F103RC_btt_stm32
- STM32F103RC_btt
#- STM32F103RC_btt_USB
- STM32F103RE_btt
- STM32F103RE_btt_USB
- STM32F103RET6_creality
- STM32F407VE_black
- STM32F401VE_STEVAL
- BIGTREE_BTT002
- BIGTREE_SKR_PRO
- BIGTREE_GTR_V1_0
- mks_robin_stm32
- mks_robin
- ARMED
- FYSETC_S6
- STM32F070CB_malyan
@@ -88,7 +90,7 @@ jobs:
- rumba32
- LERDGEX
- LERDGEK
- mks_robin_nano35_stm32
- mks_robin_nano35
- NUCLEO_F767ZI
- REMRAM_V1
- BTT_SKR_SE_BX
@@ -107,8 +109,25 @@ jobs:
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
uses: actions/setup-python@v1
uses: actions/setup-python@v2
with:
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
@@ -118,9 +137,6 @@ jobs:
pip install -U https://github.com/platformio/platformio-core/archive/develop.zip
platformio update
- name: Check out the PR
uses: actions/checkout@v2
- name: Run ${{ matrix.test-platform }} Tests
run: |
make tests-single-ci TEST_TARGET=${{ matrix.test-platform }}

View File

@@ -35,7 +35,7 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
#define CONFIGURATION_H_VERSION 02000801
#define CONFIGURATION_H_VERSION 02000901
//===========================================================================
//============================= Getting Started =============================
@@ -105,21 +105,9 @@
#define SERIAL_PORT 0
/**
* 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
/**
* 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.
* Serial Port Baud Rate
* This is the default communication speed for all serial ports.
* Set the baud rate defaults for additional serial ports below.
*
* 250000 works in most cases, but you might try a lower speed if
* you commonly experience drop-outs during host printing.
@@ -128,6 +116,23 @@
* :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000]
*/
#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
//#define BLUETOOTH
@@ -144,6 +149,45 @@
// Choose your own or use a service like https://www.uuidgenerator.net/version4
//#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
// This defines the number of extruders
@@ -428,6 +472,7 @@
#define TEMP_SENSOR_PROBE 0
#define TEMP_SENSOR_CHAMBER 0
#define TEMP_SENSOR_COOLER 0
#define TEMP_SENSOR_REDUNDANT 0
// Dummy thermistor constant temperature readings, for use with 998 and 999
#define DUMMY_THERMISTOR_998_VALUE 25
@@ -439,11 +484,6 @@
//#define MAX31865_SENSOR_OHMS_1 100
//#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_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#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_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
// because it probably indicates a broken thermistor wire.
#define HEATER_0_MINTEMP 5
@@ -686,9 +748,15 @@
#define USE_XMIN_PLUG
#define USE_YMIN_PLUG
#define USE_ZMIN_PLUG
//#define USE_IMIN_PLUG
//#define USE_JMIN_PLUG
//#define USE_KMIN_PLUG
//#define USE_XMAX_PLUG
//#define USE_YMAX_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
#define ENDSTOPPULLUPS
@@ -697,9 +765,15 @@
//#define ENDSTOPPULLUP_XMAX
//#define ENDSTOPPULLUP_YMAX
//#define ENDSTOPPULLUP_ZMAX
//#define ENDSTOPPULLUP_IMAX
//#define ENDSTOPPULLUP_JMAX
//#define ENDSTOPPULLUP_KMAX
//#define ENDSTOPPULLUP_XMIN
//#define ENDSTOPPULLUP_YMIN
//#define ENDSTOPPULLUP_ZMIN
//#define ENDSTOPPULLUP_IMIN
//#define ENDSTOPPULLUP_JMIN
//#define ENDSTOPPULLUP_KMIN
//#define ENDSTOPPULLUP_ZMIN_PROBE
#endif
@@ -710,9 +784,15 @@
//#define ENDSTOPPULLDOWN_XMAX
//#define ENDSTOPPULLDOWN_YMAX
//#define ENDSTOPPULLDOWN_ZMAX
//#define ENDSTOPPULLDOWN_IMAX
//#define ENDSTOPPULLDOWN_JMAX
//#define ENDSTOPPULLDOWN_KMAX
//#define ENDSTOPPULLDOWN_XMIN
//#define ENDSTOPPULLDOWN_YMIN
//#define ENDSTOPPULLDOWN_ZMIN
//#define ENDSTOPPULLDOWN_IMIN
//#define ENDSTOPPULLDOWN_JMIN
//#define ENDSTOPPULLDOWN_KMIN
//#define ENDSTOPPULLDOWN_ZMIN_PROBE
#endif
@@ -720,9 +800,15 @@
#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 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 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 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.
/**
@@ -751,6 +837,9 @@
//#define Z2_DRIVER_TYPE A4988
//#define Z3_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 E1_DRIVER_TYPE A4988
//#define E2_DRIVER_TYPE A4988
@@ -804,14 +893,14 @@
/**
* Default Axis Steps Per Unit (steps/mm)
* 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 }
/**
* Default Max Feed Rate (mm/s)
* 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 }
@@ -824,7 +913,7 @@
* Default Max Acceleration (change/s) change = mm/s
* (Maximum start speed for accelerated moves)
* 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 }
@@ -858,6 +947,9 @@
#define DEFAULT_XJERK 10.0
#define DEFAULT_YJERK 10.0
#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
@@ -1156,7 +1248,8 @@
//#define WAIT_FOR_HOTEND // Wait for hotend to heat back up between probes (to improve accuracy & prevent cold extrude)
#endif
//#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
// Require minimum nozzle and/or bed temperature for probing
@@ -1172,12 +1265,18 @@
#define Y_ENABLE_ON 0
#define Z_ENABLE_ON 0
#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.
// WARNING: When motors turn off there is a chance of losing position accuracy!
#define DISABLE_X false
#define DISABLE_Y 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
//#define DISABLE_REDUCED_ACCURACY_WARNING
@@ -1193,6 +1292,9 @@
#define INVERT_X_DIR false
#define INVERT_Y_DIR true
#define INVERT_Z_DIR false
//#define INVERT_I_DIR false
//#define INVERT_J_DIR false
//#define INVERT_K_DIR false
// @section extruder
@@ -1228,6 +1330,9 @@
#define X_HOME_DIR -1
#define Y_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
@@ -1242,6 +1347,12 @@
#define X_MAX_POS X_BED_SIZE
#define Y_MAX_POS Y_BED_SIZE
#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
@@ -1258,6 +1369,9 @@
#define MIN_SOFTWARE_ENDSTOP_X
#define MIN_SOFTWARE_ENDSTOP_Y
#define MIN_SOFTWARE_ENDSTOP_Z
#define MIN_SOFTWARE_ENDSTOP_I
#define MIN_SOFTWARE_ENDSTOP_J
#define MIN_SOFTWARE_ENDSTOP_K
#endif
// Max software endstops constrain movement within maximum coordinate bounds
@@ -1266,6 +1380,9 @@
#define MAX_SOFTWARE_ENDSTOP_X
#define MAX_SOFTWARE_ENDSTOP_Y
#define MAX_SOFTWARE_ENDSTOP_Z
#define MAX_SOFTWARE_ENDSTOP_I
#define MAX_SOFTWARE_ENDSTOP_J
#define MAX_SOFTWARE_ENDSTOP_K
#endif
#if EITHER(MIN_SOFTWARE_ENDSTOPS, MAX_SOFTWARE_ENDSTOPS)
@@ -1577,6 +1694,9 @@
//#define MANUAL_X_HOME_POS 0
//#define MANUAL_Y_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.
//
@@ -1819,11 +1939,20 @@
/**
* 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
* M109 (hotend, wait) - high temp = start timer, low temp = stop timer
* M190 (bed, wait) - high temp = start timer, low temp = none
* M104 (hotend, no wait) - high temp = none, low temp = stop timer
* M109 (hotend, wait) - high temp = start timer, low temp = stop timer
* 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:
*
@@ -2685,7 +2814,7 @@
//#define 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_PIN 4 // LED driving pin
//#define NEOPIXEL_PIN 4 // LED driving pin
//#define NEOPIXEL2_TYPE NEOPIXEL_TYPE
//#define NEOPIXEL2_PIN 5
#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
#endif
// Use a single NeoPixel LED for static (background) lighting
//#define NEOPIXEL_BKGD_LED_INDEX 0 // Index of the LED to use
//#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
// Use some of the NeoPixel LEDs for static (background) lighting
//#define NEOPIXEL_BKGD_INDEX_FIRST 0 // Index of the first background LED
//#define NEOPIXEL_BKGD_INDEX_LAST 5 // Index of the last background LED
//#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
/**

View File

@@ -30,7 +30,7 @@
*
* Basic settings can be found in Configuration.h
*/
#define CONFIGURATION_ADV_H_VERSION 02000801
#define CONFIGURATION_ADV_H_VERSION 02000901
//===========================================================================
//============================= Thermal Settings ============================
@@ -125,6 +125,12 @@
#define PROBE_BETA 3950 // Beta value
#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.
// https://store.bq.com/en/heated-bed-kit-hephestos2
@@ -196,7 +202,7 @@
#define COOLER_MAXTEMP 26 // (°C)
#define COOLER_DEFAULT_TEMP 16 // (°C)
#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 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.
@@ -526,6 +532,11 @@
//#define USE_OCR2A_AS_TOP
#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
/**
@@ -671,6 +682,12 @@
#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
*
@@ -734,7 +751,7 @@
* 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_DIVISOR { 2, 2, 4 } // Re-Bump Speed Divisor (Divides the Homing Feedrate)
@@ -918,6 +935,9 @@
#define INVERT_X_STEP_PIN false
#define INVERT_Y_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
/**
@@ -929,6 +949,9 @@
#define DISABLE_INACTIVE_X 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_I true
#define DISABLE_INACTIVE_J true
#define DISABLE_INACTIVE_K true
#define DISABLE_INACTIVE_E true
// Default Minimum Feedrates for printing and travel moves
@@ -969,7 +992,7 @@
#if ENABLED(BACKLASH_COMPENSATION)
// Define values for backlash distance and correction.
// 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
// Add steps for motor direction changes on CORE kinematics
@@ -1040,6 +1063,13 @@
#define CALIBRATION_MEASURE_LEFT
#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 on a screwhead or hollow washer, probe near the 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 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")
#if ENABLED(PRINTER_EVENT_LEDS)
@@ -1562,7 +1594,7 @@
*/
//#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_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_BED_ANIM // Use a second bitmap to indicate bed heating
#define STATUS_CHAMBER_ANIM // Use a second bitmap to indicate chamber heating
@@ -1940,30 +1972,30 @@
//#define USE_TEMP_EXT_COMPENSATION
// 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_RES 5.0f
//#define PTC_SAMPLE_COUNT 10U
//#define PTC_SAMPLE_START 30 // (°C)
//#define PTC_SAMPLE_RES 5 // (°C)
//#define PTC_SAMPLE_COUNT 10
// Bed temperature calibration builds a similar table.
//#define BTC_SAMPLE_START 60.0f
//#define BTC_SAMPLE_RES 5.0f
//#define BTC_SAMPLE_COUNT 10U
//#define BTC_SAMPLE_START 60 // (°C)
//#define BTC_SAMPLE_RES 5 // (°C)
//#define BTC_SAMPLE_COUNT 10
// The temperature the probe should be at while taking measurements during bed temperature
// 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.
// Note: the Z=0.0f offset is determined by the probe offset which can be set using M851.
//#define PTC_PROBE_HEATING_OFFSET 0.5f
// Height above Z=0.0 to raise the nozzle. Lowering this can help the probe to heat faster.
// Note: the Z=0.0 offset is determined by the probe offset which can be set using M851.
//#define PTC_PROBE_HEATING_OFFSET 0.5
// 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
// 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
// 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
// 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)
#define BLOCK_BUFFER_SIZE 8
#elif ENABLED(SDSUPPORT)
@@ -2114,9 +2146,6 @@
//#define SERIAL_XON_XOFF
#endif
// Add M575 G-code to change the baud rate
//#define BAUD_RATE_GCODE
#if ENABLED(SDSUPPORT)
// Enable this option to collect and display the maximum
// 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
#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.
* Requires the pins TOOL_SENSOR1_PIN, TOOL_SENSOR2_PIN, etc.
@@ -2414,6 +2450,24 @@
#define Z4_MICROSTEPS Z_MICROSTEPS
#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)
#define E0_MAX_CURRENT 1000
#define E0_SENSE_RESISTOR 91
@@ -2564,6 +2618,33 @@
//#define Z4_INTERPOLATE true
#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)
#define E0_CURRENT 800
#define E0_MICROSTEPS 16
@@ -2639,6 +2720,10 @@
//#define Y2_CS_PIN -1
//#define Z2_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 E1_CS_PIN -1
//#define E2_CS_PIN -1
@@ -2678,6 +2763,9 @@
//#define Z2_SLAVE_ADDRESS 0
//#define Z3_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 E1_SLAVE_ADDRESS 0
//#define E2_SLAVE_ADDRESS 0
@@ -2702,6 +2790,9 @@
*/
#define STEALTHCHOP_XY
#define STEALTHCHOP_Z
#define STEALTHCHOP_I
#define STEALTHCHOP_J
#define STEALTHCHOP_K
#define STEALTHCHOP_E
/**
@@ -2773,6 +2864,9 @@
#define Z2_HYBRID_THRESHOLD 3
#define Z3_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 E1_HYBRID_THRESHOLD 30
#define E2_HYBRID_THRESHOLD 30
@@ -2798,7 +2892,7 @@
*
* 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.
* Removes the need for a wire from DIAG1 to an endstop pin.
*
@@ -2819,6 +2913,9 @@
//#define Z2_STALL_SENSITIVITY Z_STALL_SENSITIVITY
//#define Z3_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 IMPROVE_HOMING_RELIABILITY
#endif
@@ -2959,6 +3056,33 @@
#define Z4_SLEW_RATE 1
#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)
#define E0_MICROSTEPS 128
#define E0_OVERCURRENT 2000
@@ -3308,8 +3432,18 @@
#define SPINDLE_LASER_POWERDOWN_DELAY 50 // (ms) Delay to allow the spindle to stop
#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 // SPINDLE_FEATURE || LASER_FEATURE
/**
* Synchronous Laser Control with M106/M107

View File

@@ -28,7 +28,7 @@
/**
* 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
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* 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.

View File

@@ -186,7 +186,7 @@ inline void HAL_adc_init() {
#define GET_PIN_MAP_INDEX(pin) pin
#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__
#define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)

View File

@@ -168,6 +168,51 @@ void setup_endstop_interrupts() {
pciSetup(Z_MIN_PIN);
#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 (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MAX_PIN);
@@ -256,6 +301,5 @@ void setup_endstop_interrupts() {
pciSetup(Z_MIN_PROBE_PIN);
#endif
#endif
// 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
#define digitalPinToTimer_DEBUG(p) digitalPinToTimer(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))
#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_MIN, _ATTACH(Z4_MIN_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_MIN, _ATTACH(Z4_MIN_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"
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) {
return parser.intval(code, dval);
}

View File

@@ -34,26 +34,32 @@ constexpr uint8_t NUM_ANALOG_INPUTS = 16;
#define HAL_SENSITIVE_PINS
constexpr 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 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);
constexpr pin_t analogInputToDigitalPin(const int8_t p) {
return (WITHIN(p, 0, NUM_ANALOG_INPUTS) ? analog_offset + p : P_NC);
}
// 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
bool PWM_PIN(const pin_t p);
constexpr bool PWM_PIN(const pin_t p) { return false; }
// 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
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
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
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
// 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
void HAL_idletask();

View File

@@ -66,11 +66,7 @@
#include <SoftwareSPI.h>
#ifndef HAL_SPI_SPEED
#define HAL_SPI_SPEED SPI_FULL_SPEED
#endif
static uint8_t SPI_speed = HAL_SPI_SPEED;
static uint8_t SPI_speed = SPI_FULL_SPEED;
static uint8_t spiTransfer(uint8_t b) {
return swSpiTransfer(b, SPI_speed, SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
@@ -106,15 +102,13 @@
#else
#ifndef HAL_SPI_SPEED
#ifdef SD_SPI_SPEED
#define HAL_SPI_SPEED SD_SPI_SPEED
#else
#define HAL_SPI_SPEED SPI_FULL_SPEED
#endif
#ifdef SD_SPI_SPEED
#define INIT_SPI_SPEED SD_SPI_SPEED
#else
#define INIT_SPI_SPEED SPI_FULL_SPEED
#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) {
#if SD_MISO_PIN == BOARD_SPI1_MISO_PIN

View File

@@ -122,4 +122,37 @@ void setup_endstop_interrupts() {
#endif
_ATTACH(Z_MIN_PROBE_PIN);
#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!"
#elif ANY_RX(2, X_DIR_PIN, Y_DIR_PIN)
#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!"
#elif HAS_CUSTOM_PROBE_PIN && IS_TX2(Z_MIN_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,
};
#if !defined(XPT2046_Z1_THRESHOLD)
#ifndef XPT2046_Z1_THRESHOLD
#define XPT2046_Z1_THRESHOLD 10
#endif

View File

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

View File

@@ -195,6 +195,7 @@ uint16_t HAL_adc_get_result();
#ifdef STM32F1xx
#define JTAG_DISABLE() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_JTAGDISABLE)
#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
#define PLATFORM_M997_SUPPORT

View File

@@ -163,11 +163,9 @@ static SPISettings spiConfig;
}
spiConfig = SPISettings(clock, MSBFIRST, SPI_MODE0);
#if ENABLED(CUSTOM_SPI_PINS)
SPI.setMISO(SD_MISO_PIN);
SPI.setMOSI(SD_MOSI_PIN);
SPI.setSCLK(SD_SCK_PIN);
#endif
SPI.setMISO(SD_MISO_PIN);
SPI.setMOSI(SD_MOSI_PIN);
SPI.setSCLK(SD_SCK_PIN);
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"
// 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
* 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_MIN, _ATTACH(Z4_MIN_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
#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
#endif
@@ -30,3 +30,6 @@
#undef F_CPU
#define F_CPU BOARD_F_CPU
#endif
// The Sensitive Pins array is not optimizable
#define RUNTIME_ONLY_ANALOG_TO_DIGITAL

View File

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

View File

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

View File

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

View File

@@ -167,6 +167,15 @@ constexpr bool IsSerialClassAllowed(const HardwareSerial&) { return false; }
#if AXIS_HAS_HW_SERIAL(Z4)
CHECK_AXIS_SERIAL(Z4);
#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)
CHECK_AXIS_SERIAL(E0);
#endif

View File

@@ -11,6 +11,7 @@ if __name__ == "__main__":
"-fsigned-char",
"-fno-move-loop-invariants",
"-fno-strict-aliasing",
"-fsingle-precision-constant",
"--specs=nano.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_MIN, _ATTACH(Z4_MIN_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
#endif
#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_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 FCLK_FAST() ONBOARD_SD_SPI.setClockDivider(SPI_CLOCK_MAX)
#define FCLK_SLOW() ONBOARD_SD_SPI.setClockDivider(SPI_BAUD_PCLK_DIV_256)
@@ -49,32 +49,32 @@
---------------------------------------------------------------------------*/
/* MMC/SD command */
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD12 (12) /* STOP_TRANSMISSION */
#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (24) /* WRITE_BLOCK */
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
#define CMD32 (32) /* ERASE_ER_BLK_START */
#define CMD33 (33) /* ERASE_ER_BLK_END */
#define CMD38 (38) /* ERASE */
#define CMD48 (48) /* READ_EXTR_SINGLE */
#define CMD49 (49) /* WRITE_EXTR_SINGLE */
#define CMD55 (55) /* APP_CMD */
#define CMD58 (58) /* READ_OCR */
#define CMD0 (0) // GO_IDLE_STATE
#define CMD1 (1) // SEND_OP_COND (MMC)
#define ACMD41 (0x80+41) // SEND_OP_COND (SDC)
#define CMD8 (8) // SEND_IF_COND
#define CMD9 (9) // SEND_CSD
#define CMD10 (10) // SEND_CID
#define CMD12 (12) // STOP_TRANSMISSION
#define ACMD13 (0x80+13) // SD_STATUS (SDC)
#define CMD16 (16) // SET_BLOCKLEN
#define CMD17 (17) // READ_SINGLE_BLOCK
#define CMD18 (18) // READ_MULTIPLE_BLOCK
#define CMD23 (23) // SET_BLOCK_COUNT (MMC)
#define ACMD23 (0x80+23) // SET_WR_BLK_ERASE_COUNT (SDC)
#define CMD24 (24) // WRITE_BLOCK
#define CMD25 (25) // WRITE_MULTIPLE_BLOCK
#define CMD32 (32) // ERASE_ER_BLK_START
#define CMD33 (33) // ERASE_ER_BLK_END
#define CMD38 (38) // ERASE
#define CMD48 (48) // READ_EXTR_SINGLE
#define CMD49 (49) // WRITE_EXTR_SINGLE
#define CMD55 (55) // APP_CMD
#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 BYTE CardType; /* Card type flags */
static BYTE CardType; // Card type flags
/*-----------------------------------------------------------------------*/
/* Send/Receive data to the MMC (Platform dependent) */
@@ -82,7 +82,7 @@ static BYTE CardType; /* Card type flags */
/* Exchange a byte */
static BYTE xchg_spi (
BYTE dat /* Data to send */
BYTE dat // Data to send
) {
BYTE returnByte = ONBOARD_SD_SPI.transfer(dat);
return returnByte;
@@ -90,18 +90,18 @@ static BYTE xchg_spi (
/* Receive multiple byte */
static void rcvr_spi_multi (
BYTE *buff, /* Pointer to data buffer */
UINT btr /* Number of bytes to receive (16, 64 or 512) */
BYTE *buff, // Pointer to data buffer
UINT btr // Number of bytes to receive (16, 64 or 512)
) {
ONBOARD_SD_SPI.dmaTransfer(0, const_cast<uint8_t*>(buff), btr);
}
#if _DISKIO_WRITE
/* Send multiple bytes */
// Send multiple bytes
static void xmit_spi_multi (
const BYTE *buff, /* Pointer to the data */
UINT btx /* Number of bytes to send (multiple of 16) */
const BYTE *buff, // Pointer to the data
UINT btx // Number of bytes to send (multiple of 16)
) {
ONBOARD_SD_SPI.dmaSend(const_cast<uint8_t*>(buff), btx);
}
@@ -112,16 +112,15 @@ static void rcvr_spi_multi (
/* Wait for card ready */
/*-----------------------------------------------------------------------*/
static int wait_ready ( /* 1:Ready, 0:Timeout */
UINT wt /* Timeout [ms] */
static int wait_ready ( // 1:Ready, 0:Timeout
UINT wt // Timeout [ms]
) {
BYTE d;
timeout = millis() + wt;
do {
d = xchg_spi(0xFF);
/* This loop takes a while. Insert rot_rdq() here for multitask environment. */
} while (d != 0xFF && (timeout > millis())); /* Wait for card goes ready or timeout */
// This loop takes a while. Insert rot_rdq() here for multitask environment.
} while (d != 0xFF && (timeout > millis())); // Wait for card goes ready or timeout
return (d == 0xFF) ? 1 : 0;
}
@@ -131,21 +130,21 @@ static int wait_ready ( /* 1:Ready, 0:Timeout */
/*-----------------------------------------------------------------------*/
static void deselect() {
CS_HIGH(); /* CS = H */
xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
CS_HIGH(); // CS = H
xchg_spi(0xFF); // Dummy clock (force DO hi-z for multiple slave SPI)
}
/*-----------------------------------------------------------------------*/
/* Select card and wait for ready */
/*-----------------------------------------------------------------------*/
static int select() { /* 1:OK, 0:Timeout */
CS_LOW(); /* CS = L */
xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
static int select() { // 1:OK, 0:Timeout
CS_LOW(); // CS = L
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;
}
@@ -153,16 +152,18 @@ static int select() { /* 1:OK, 0:Timeout */
/* 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.begin();
ONBOARD_SD_SPI.setBitOrder(MSBFIRST);
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 */
select(); /* Wait for card ready */
// Disable SPI function
static void sd_power_off() {
select(); // Wait for card ready
deselect();
}
@@ -170,23 +171,23 @@ static void power_off() { /* Disable SPI function */
/* Receive a data packet from the MMC */
/*-----------------------------------------------------------------------*/
static int rcvr_datablock ( /* 1:OK, 0:Error */
BYTE *buff, /* Data buffer */
UINT btr /* Data block length (byte) */
static int rcvr_datablock ( // 1:OK, 0:Error
BYTE *buff, // Data buffer
UINT btr // Data block length (byte)
) {
BYTE token;
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);
/* 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()));
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 */
xchg_spi(0xFF); xchg_spi(0xFF); /* Discard CRC */
rcvr_spi_multi(buff, btr); // Store trailing data to the buffer
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
static int xmit_datablock ( /* 1:OK, 0:Failed */
const BYTE *buff, /* Ponter to 512 byte data to be sent */
BYTE token /* Token */
static int xmit_datablock( // 1:OK, 0:Failed
const BYTE *buff, // Pointer to 512 byte data to be sent
BYTE token // Token
) {
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 */
if (token == 0xFD) return 1; /* Do not send data if token is StopTran */
xchg_spi(token); // Send token
if (token == 0xFD) return 1; // Do not send data if token is StopTran
xmit_spi_multi(buff, 512); /* Data */
xchg_spi(0xFF); xchg_spi(0xFF); /* Dummy CRC */
xmit_spi_multi(buff, 512); // Data
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
@@ -222,43 +223,43 @@ static int rcvr_datablock ( /* 1:OK, 0:Error */
/* Send a command packet to the MMC */
/*-----------------------------------------------------------------------*/
static BYTE send_cmd ( /* Return value: R1 resp (bit7==1:Failed to send) */
BYTE cmd, /* Command index */
DWORD arg /* Argument */
static BYTE send_cmd( // Return value: R1 resp (bit7==1:Failed to send)
BYTE cmd, // Command index
DWORD arg // Argument
) {
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;
res = send_cmd(CMD55, 0);
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) {
deselect();
if (!select()) return 0xFF;
}
/* Send command packet */
xchg_spi(0x40 | cmd); /* Start + command index */
xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
xchg_spi((BYTE)arg); /* Argument[7..0] */
n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
// Send command packet
xchg_spi(0x40 | cmd); // Start + command index
xchg_spi((BYTE)(arg >> 24)); // Argument[31..24]
xchg_spi((BYTE)(arg >> 16)); // Argument[23..16]
xchg_spi((BYTE)(arg >> 8)); // Argument[15..8]
xchg_spi((BYTE)arg); // Argument[7..0]
n = 0x01; // Dummy CRC + Stop
if (cmd == CMD0) n = 0x95; // Valid CRC for CMD0(0)
if (cmd == CMD8) n = 0x87; // Valid CRC for CMD8(0x1AA)
xchg_spi(n);
/* Receive command resp */
if (cmd == CMD12) xchg_spi(0xFF); /* Diacard following one byte when CMD12 */
n = 10; /* Wait for response (10 bytes max) */
// Receive command response
if (cmd == CMD12) xchg_spi(0xFF); // Discard the following byte when CMD12
n = 10; // Wait for response (10 bytes max)
do
res = xchg_spi(0xFF);
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 (
BYTE drv /* Physical drive number (0) */
BYTE drv // Physical drive number (0)
) {
BYTE n, cmd, ty, ocr[4];
if (drv) return STA_NOINIT; /* Supports only drive 0 */
power_on(); /* Initialize SPI */
if (drv) return STA_NOINIT; // Supports only drive 0
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();
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;
if (send_cmd(CMD0, 0) == 1) { /* Put the card SPI state */
timeout = millis() + 1000; /* Initialization timeout = 1 sec */
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 */
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) */
if ((timeout > millis()) && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
if (send_cmd(CMD0, 0) == 1) { // Put the card SPI state
timeout = millis() + 1000; // Initialization timeout = 1 sec
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
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)
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);
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? */
ty = CT_SD1; cmd = ACMD41; /* SDv1 (ACMD41(0)) */
} else {
ty = CT_MMC; cmd = CMD1; /* MMCv3 (CMD1(0)) */
}
else { // Not an SDv2 card
if (send_cmd(ACMD41, 0) <= 1) { // SDv1 or MMCv3?
ty = CT_SD1; cmd = ACMD41; // SDv1 (ACMD41(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 */
else {
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;
}
}
CardType = ty; /* Card type */
CardType = ty; // Card type
deselect();
if (ty) { /* OK */
FCLK_FAST(); /* Set fast clock */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */
} else { /* Failed */
power_off();
if (ty) { // OK
FCLK_FAST(); // Set fast clock
Stat &= ~STA_NOINIT; // Clear STA_NOINIT flag
}
else { // Failed
sd_power_off();
Stat = STA_NOINIT;
}
@@ -324,10 +328,10 @@ DSTATUS disk_initialize (
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE drv /* Physical drive number (0) */
BYTE drv // Physical drive number (0)
) {
if (drv) return STA_NOINIT; /* Supports only drive 0 */
return Stat; /* Return disk status */
if (drv) return STA_NOINIT; // Supports only drive 0
return Stat; // Return disk status
}
/*-----------------------------------------------------------------------*/
@@ -335,28 +339,28 @@ DSTATUS disk_status (
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE drv, /* Physical drive number (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
UINT count /* Number of sectors to read (1..128) */
BYTE drv, // Physical drive number (0)
BYTE *buff, // Pointer to the data buffer to store read data
DWORD sector, // Start sector number (LBA)
UINT count // Number of sectors to read (1..128)
) {
BYTE cmd;
if (drv || !count) return RES_PARERR; /* Check parameter */
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 (drv || !count) return RES_PARERR; // Check parameter
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)
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) {
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
if (cmd == CMD18) send_cmd(CMD12, 0); // STOP_TRANSMISSION
}
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
DRESULT disk_write(
BYTE drv, /* Physical drive number (0) */
const BYTE *buff, /* Ponter to the data to write */
DWORD sector, /* Start sector number (LBA) */
UINT count /* Number of sectors to write (1..128) */
BYTE drv, // Physical drive number (0)
const BYTE *buff, // Pointer to the data to write
DWORD sector, // Start sector number (LBA)
UINT count // Number of sectors to write (1..128)
) {
if (drv || !count) return RES_PARERR; /* Check parameter */
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check drive status */
if (Stat & STA_PROTECT) return RES_WRPRT; /* Check write protect */
if (drv || !count) return RES_PARERR; // Check parameter
if (Stat & STA_NOINIT) return RES_NOTRDY; // Check drive status
if (Stat & STA_PROTECT) return RES_WRPRT; // Check write protect
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 ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
if (count == 1) { // Single sector write
if ((send_cmd(CMD24, sector) == 0) // WRITE_BLOCK
&& xmit_datablock(buff, 0xFE)) {
count = 0;
}
}
else { /* Multiple sector write */
if (CardType & CT_SDC) send_cmd(ACMD23, count); /* Predefine number of sectors */
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
else { // Multiple sector write
if (CardType & CT_SDC) send_cmd(ACMD23, count); // Predefine number of sectors
if (send_cmd(CMD25, sector) == 0) { // WRITE_MULTIPLE_BLOCK
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) count = 1; /* STOP_TRAN token */
if (!xmit_datablock(0, 0xFD)) count = 1; // STOP_TRAN token
}
}
deselect();
return count ? RES_ERROR : RES_OK; /* Return result */
return count ? RES_ERROR : RES_OK; // Return result
}
#endif // _DISKIO_WRITE
@@ -407,9 +411,9 @@ DRESULT disk_read (
#if _DISKIO_IOCTL
DRESULT disk_ioctl (
BYTE drv, /* Physical drive number (0) */
BYTE cmd, /* Control command code */
void *buff /* Pointer to the conrtol data */
BYTE drv, // Physical drive number (0)
BYTE cmd, // Control command code
void *buff // Pointer to the conrtol data
) {
DRESULT res;
BYTE n, csd[16], *ptr = (BYTE *)buff;
@@ -420,22 +424,23 @@ DRESULT disk_read (
UINT dc;
#endif
if (drv) return RES_PARERR; /* Check parameter */
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
if (drv) return RES_PARERR; // Check parameter
if (Stat & STA_NOINIT) return RES_NOTRDY; // Check if drive is ready
res = RES_ERROR;
FCLK_FAST();
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;
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 ((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;
*(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;
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(DWORD*)buff = csize << (n - 9);
@@ -444,21 +449,23 @@ DRESULT disk_read (
}
break;
case GET_BLOCK_SIZE: /* Get erase block size in unit of sector (DWORD) */
if (CardType & CT_SD2) { /* SDC ver 2.00 */
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
case GET_BLOCK_SIZE: // Get erase block size in unit of sector (DWORD)
if (CardType & CT_SD2) { // SDC ver 2.00
if (send_cmd(ACMD13, 0) == 0) { // Read SD status
xchg_spi(0xFF);
if (rcvr_datablock(csd, 16)) { /* Read partial block */
for (n = 64 - 16; n; n--) xchg_spi(0xFF); /* Purge trailing data */
if (rcvr_datablock(csd, 16)) { // Read partial block
for (n = 64 - 16; n; n--) xchg_spi(0xFF); // Purge trailing data
*(DWORD*)buff = 16UL << (csd[10] >> 4);
res = RES_OK;
}
}
} else { /* SDC ver 1.XX or MMC */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
if (CardType & CT_SD1) { /* SDC ver 1.XX */
}
else { // SDC ver 1.XX or MMC
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);
} else { /* MMC */
}
else { // MMC
*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
}
res = RES_OK;
@@ -466,47 +473,47 @@ DRESULT disk_read (
}
break;
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 (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 */
dp = (DWORD *)buff; st = dp[0]; ed = dp[1]; /* Load sector block */
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 (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
dp = (DWORD *)buff; st = dp[0]; ed = dp[1]; // Load sector block
if (!(CardType & CT_BLOCK)) {
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 */
res = RES_OK; /* FatFs does not check result of this command */
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
}
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;
res = RES_OK;
break;
case MMC_GET_CSD: /* Read CSD (16 bytes) */
if (send_cmd(CMD9, 0) == 0 && rcvr_datablock(ptr, 16)) { /* READ_CSD */
case MMC_GET_CSD: // Read CSD (16 bytes)
if (send_cmd(CMD9, 0) == 0 && rcvr_datablock(ptr, 16)) {
res = RES_OK;
}
break;
case MMC_GET_CID: /* Read CID (16 bytes) */
if (send_cmd(CMD10, 0) == 0 && rcvr_datablock(ptr, 16)) { /* READ_CID */
case MMC_GET_CID: // Read CID (16 bytes)
if (send_cmd(CMD10, 0) == 0 && rcvr_datablock(ptr, 16)) {
res = RES_OK;
}
break;
case MMC_GET_OCR: /* Read OCR (4 bytes) */
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
case MMC_GET_OCR: // Read OCR (4 bytes)
if (send_cmd(CMD58, 0) == 0) {
for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF);
res = RES_OK;
}
break;
case MMC_GET_SDSTAT: /* Read SD status (64 bytes) */
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
case MMC_GET_SDSTAT: // Read SD status (64 bytes)
if (send_cmd(ACMD13, 0) == 0) {
xchg_spi(0xFF);
if (rcvr_datablock(ptr, 64)) res = RES_OK;
}

View File

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

View File

@@ -54,7 +54,7 @@ enum XPTCoordinate : uint8_t {
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
};
#if !defined(XPT2046_Z1_THRESHOLD)
#ifndef XPT2046_Z1_THRESHOLD
#define XPT2046_Z1_THRESHOLD 10
#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
#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.
#ifdef STM32_HIGH_DENSITY
#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_MIN, _ATTACH(Z4_MIN_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_MIN, _ATTACH(Z4_MIN_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_MIN, _ATTACH(Z4_MIN_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
// ------------------------
#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) {
const unsigned eeprom_address = (unsigned)pos;
Wire.beginTransmission(eeprom_device_address);
Wire.write(int(eeprom_address >> 8)); // Address High
Wire.write(int(eeprom_address & 0xFF)); // Address Low
Wire.beginTransmission(_eeprom_calc_device_address(pos));
if (!SMALL_EEPROM)
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) {
@@ -81,7 +94,7 @@ void eeprom_write_byte(uint8_t *pos, uint8_t value) {
uint8_t eeprom_read_byte(uint8_t *pos) {
_eeprom_begin(pos);
Wire.endTransmission();
Wire.requestFrom(eeprom_device_address, (byte)1);
Wire.requestFrom(_eeprom_calc_device_address(pos), (byte)1);
return Wire.available() ? Wire.read() : 0xFF;
}

View File

@@ -282,12 +282,22 @@ bool wait_for_heatup = true;
#pragma GCC diagnostic push
#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) {
static const pin_t sensitive_pins[] PROGMEM = SENSITIVE_PINS;
LOOP_L_N(i, COUNT(sensitive_pins)) {
pin_t sensitive_pin;
memcpy_P(&sensitive_pin, &sensitive_pins[i], sizeof(pin_t));
if (pin == sensitive_pin) return true;
#ifdef RUNTIME_ONLY_ANALOG_TO_DIGITAL
static const pin_t sensitive_pins[] PROGMEM = { SENSITIVE_PINS };
const size_t pincount = COUNT(sensitive_pins);
#else
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;
}
@@ -304,6 +314,9 @@ void enable_all_steppers() {
ENABLE_AXIS_X();
ENABLE_AXIS_Y();
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();
TERN_(EXTENSIBLE_UI, ExtUI::onSteppersEnabled());
@@ -317,7 +330,7 @@ void disable_e_steppers() {
void disable_e_stepper(const uint8_t e) {
#define _CASE_DIS_E(N) case N: DISABLE_AXIS_E##N(); break;
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_Y();
DISABLE_AXIS_Z();
DISABLE_AXIS_I();
DISABLE_AXIS_J();
DISABLE_AXIS_K();
disable_e_steppers();
TERN_(EXTENSIBLE_UI, ExtUI::onSteppersDisabled());
@@ -408,19 +424,18 @@ void startOrResumeJob() {
* - Check if an idle but hot extruder needs filament extruded (EXTRUDER_RUNOUT_PREVENT)
* - 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();
const millis_t ms = millis();
// Prevent steppers timing-out in the middle of M600
// unless PAUSE_PARK_NO_STEPPER_TIMEOUT is disabled
const bool parked_or_ignoring = ignore_stepper_queue
// Prevent steppers timing-out
const bool do_reset_timeout = no_stepper_sleep
|| TERN0(PAUSE_PARK_NO_STEPPER_TIMEOUT, did_pause_print);
// 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)) {
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
if (planner.has_blocks_queued())
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) {
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_Y)) DISABLE_AXIS_Y();
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();
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
* - 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)
static uint16_t idle_depth = 0;
if (++idle_depth > 5) SERIAL_ECHOLNPAIR("idle() call depth: ", idle_depth);
#endif
// Core Marlin activities
manage_inactivity(TERN_(ADVANCED_PAUSE_FEATURE, no_stepper_sleep));
manage_inactivity(no_stepper_sleep);
// Manage Heaters (and Watchdog)
thermalManager.manage_heater();
@@ -935,6 +953,15 @@ inline void tmc_standby_setup() {
#if PIN_EXISTS(Z4_STDBY)
SET_INPUT_PULLDOWN(Z4_STDBY_PIN);
#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)
SET_INPUT_PULLDOWN(E0_STDBY_PIN);
#endif
@@ -1073,11 +1100,17 @@ void setup() {
while (!MYSERIAL1.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#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;
while (!MYSERIAL2.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#ifdef SERIAL_PORT_3
MYSERIAL3.begin(BAUDRATE);
#ifndef BAUDRATE_3
#define BAUDRATE_3 BAUDRATE
#endif
MYSERIAL3.begin(BAUDRATE_3);
serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL3.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#endif
@@ -1095,6 +1128,7 @@ void setup() {
#endif
#if HAS_FREEZE_PIN
SETUP_LOG("FREEZE_PIN");
SET_INPUT_PULLUP(FREEZE_PIN);
#endif
@@ -1103,11 +1137,19 @@ void setup() {
OUT_WRITE(SUICIDE_PIN, !SUICIDE_PIN_INVERTING);
#endif
#ifdef JTAGSWD_RESET
SETUP_LOG("JTAGSWD_RESET");
JTAGSWD_RESET();
#endif
#if EITHER(DISABLE_DEBUG, DISABLE_JTAG)
delay(10);
// Disable any hardware debug to free up pins for IO
#if ENABLED(DISABLE_DEBUG) && defined(JTAGSWD_DISABLE)
SETUP_LOG("JTAGSWD_DISABLE");
JTAGSWD_DISABLE();
#elif defined(JTAG_DISABLE)
SETUP_LOG("JTAG_DISABLE");
JTAG_DISABLE();
#else
#error "DISABLE_(DEBUG|JTAG) is not supported for the selected MCU/Board."
@@ -1126,10 +1168,10 @@ void setup() {
SETUP_RUN(HAL_init());
// 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
#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
#endif
@@ -1417,10 +1459,7 @@ void setup() {
#endif
#if HAS_PRUSA_MMU1
SETUP_LOG("Prusa MMU1");
SET_OUTPUT(E_MUX0_PIN);
SET_OUTPUT(E_MUX1_PIN);
SET_OUTPUT(E_MUX2_PIN);
SETUP_RUN(mmu_init());
#endif
#if HAS_FANMUX
@@ -1488,7 +1527,7 @@ void setup() {
#endif
#if HAS_TRINAMIC_CONFIG && DISABLED(PSU_DEFAULT_OFF)
SETUP_RUN(test_tmc_connection(true, true, true, true));
SETUP_RUN(test_tmc_connection());
#endif
#if HAS_DRIVER_SAFE_POWER_PROTECT

View File

@@ -34,8 +34,8 @@
void stop();
// Pass true to keep steppers from timing out
void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep=false));
inline void idle_no_sleep() { idle(TERN_(ADVANCED_PAUSE_FEATURE, true)); }
void idle(bool no_stepper_sleep=false);
inline void idle_no_sleep() { idle(true); }
#if ENABLED(G38_PROBE_TARGET)
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 1325 // PICA Shield (rev C or later)
#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
@@ -320,7 +321,7 @@
#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_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_E3_DIP 4028 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / 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_GTR_V1_0 4213 // BigTreeTech GTR v1.0 (STM32F407IGT)
#define BOARD_BTT_OCTOPUS_V1_0 4214 // BigTreeTech Octopus v1.0 (STM32F446ZET6)
#define BOARD_LERDGE_K 4215 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4216 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4217 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4218 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4219 // FYSETC S6 (STM32F446VET6)
#define BOARD_FYSETC_S6_V2_0 4220 // FYSETC S6 v2.0 (STM32F446VET6)
#define BOARD_FYSETC_SPIDER 4221 // FYSETC Spider (STM32F446VET6)
#define BOARD_FLYF407ZG 4222 // FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4223 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4224 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4225 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_ANET_ET4 4226 // ANET ET4 V1.x (STM32F407VGT6)
#define BOARD_ANET_ET4P 4227 // ANET ET4P V1.x (STM32F407VGT6)
#define BOARD_FYSETC_CHEETAH_V20 4228 // FYSETC Cheetah V2.0
#define BOARD_BTT_OCTOPUS_V1_1 4215 // BigTreeTech Octopus v1.1 (STM32F446ZET6)
#define BOARD_LERDGE_K 4216 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4217 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4218 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4219 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4220 // FYSETC S6 (STM32F446VET6)
#define BOARD_FYSETC_S6_V2_0 4221 // FYSETC S6 v2.0 (STM32F446VET6)
#define BOARD_FYSETC_SPIDER 4222 // FYSETC Spider (STM32F446VET6)
#define BOARD_FLYF407ZG 4223 // FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4224 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4225 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4226 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_ANET_ET4 4227 // ANET ET4 V1.x (STM32F407VGT6)
#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_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_Y(T) _AXIS_DRIVER_TYPE(Y,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_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_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_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 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) \
|| AXIS_HAS_##T(X2) || AXIS_HAS_##T(Y2) || AXIS_HAS_##T(Z2) \
|| AXIS_HAS_##T(Z3) || AXIS_HAS_##T(Z4) || E_AXIS_HAS(T) )
#define ANY_AXIS_HAS(T) ( AXIS_HAS_##T(X) || AXIS_HAS_##T(X2) \
|| AXIS_HAS_##T(Y) || AXIS_HAS_##T(Y2) \
|| 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)
#define HAS_STEALTHCHOP 1

View File

@@ -140,25 +140,7 @@
#define STR_RESEND "Resend: "
#define STR_UNKNOWN_COMMAND "Unknown command: \""
#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_SKEW_MIN "min_skew_factor: "
#define STR_SKEW_MAX "max_skew_factor: "
@@ -277,17 +259,43 @@
#define STR_REMINDER_SAVE_SETTINGS "Remember to save!"
#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)
#define LANGUAGE_DATA_INCL(M) LANGUAGE_DATA_INCL_(M)
#if HAS_Y_AXIS
#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)
#define LANGUAGE_INCL(M) LANGUAGE_INCL_(M)
#if HAS_Z_AXIS
#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_Y "Y"
#define STR_Z "Z"
#define STR_I AXIS4_STR
#define STR_J AXIS5_STR
#define STR_K AXIS6_STR
#define STR_E "E"
#if IS_KINEMATIC
#define STR_A "A"
@@ -307,8 +315,114 @@
#define LCD_STR_A STR_A
#define LCD_STR_B STR_B
#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
// 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)
// 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_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.
#define SUPERSCRIPT_TWO TERN(NOT_EXTENDED_ISO10646_1_5X7, "^2", "²")
#define SUPERSCRIPT_THREE TERN(NOT_EXTENDED_ISO10646_1_5X7, "^3", "³")

View File

@@ -36,12 +36,21 @@
#define _XMIN_ 100
#define _YMIN_ 200
#define _ZMIN_ 300
#define _IMIN_ 500
#define _JMIN_ 600
#define _KMIN_ 700
#define _XMAX_ 101
#define _YMAX_ 201
#define _ZMAX_ 301
#define _IMAX_ 501
#define _JMAX_ 601
#define _KMAX_ 701
#define _XDIAG_ 102
#define _YDIAG_ 202
#define _ZDIAG_ 302
#define _IDIAG_ 502
#define _JDIAG_ 602
#define _KDIAG_ 702
#define _E0DIAG_ 400
#define _E1DIAG_ 401
#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(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.
// 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>'

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_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(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
#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);
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();
}

View File

@@ -29,12 +29,16 @@
#endif
// 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_LBL[], Y_LBL[], Z_LBL[], E_LBL[],
SP_A_STR[], SP_B_STR[], SP_C_STR[],
SP_X_STR[], SP_Y_STR[], SP_Z_STR[], SP_E_STR[],
SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_E_LBL[];
I_LBL[], J_LBL[], K_LBL[];
//
// Debugging flags for use by M111
@@ -310,11 +314,11 @@ void serialprint_truefalse(const bool tf);
void serial_spaces(uint8_t count);
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) {
print_xyz(xyz.x, xyz.y, xyz.z, prefix, suffix);
inline void print_pos(const xyz_pos_t &xyz, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr) {
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_XYZ(PREFIX,V...) do { print_xyz(V, PSTR(PREFIX), nullptr); }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_pos(V, PSTR(PREFIX), nullptr); }while(0)

View File

@@ -29,34 +29,6 @@
class __FlashStringHelper;
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...
//
@@ -67,6 +39,85 @@ struct IF { typedef R type; };
template <class L, class R>
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
//
@@ -187,7 +238,7 @@ void toNative(xyz_pos_t &raw);
void toNative(xyze_pos_t &raw);
//
// XY coordinates, counters, etc.
// Paired XY coordinates, counters, flags, etc.
//
template<typename T>
struct XYval {
@@ -196,18 +247,34 @@ struct XYval {
struct { T a, b; };
T pos[2];
};
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 (&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
// Set all to 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); }
// Pointer to the data as a simple array
FI operator T* () { return pos; }
// If any element is true then it's true
FI operator bool() { return x || y; }
// Explicit copy and copies with conversion
FI XYval<T> copy() const { return *this; }
FI XYval<T> ABS() const { return { T(_ABS(x)), T(_ABS(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() const { return { static_cast<float>(x), static_cast<float>(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> 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>() const { return { x, y }; }
FI operator XYZEval<T>() { 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 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; }
// 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) { 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) 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 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; }
@@ -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) { _RS(x); _RS(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 XYZval<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 XYZval<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>
struct XYZval {
union {
struct { T x, y, z; };
struct { T a, b, c; };
T pos[3];
struct { T LINEAR_AXIS_ARGS(); };
struct { T LINEAR_AXIS_LIST(a, b, c, u, v, w); };
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, 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, const T pz) { x = pxy.x; y = pxy.y; 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) { 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)[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]; }
#if XYZE_N > XYZE
FI void set(const T (&arr)[XYZE_N]) { x = arr[0]; y = arr[1]; z = arr[2]; }
#if HAS_Z_AXIS
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]); }
FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k ); }
#endif
FI void reset() { x = y = z = 0; }
FI T magnitude() const { return (T)sqrtf(x*x + y*y + z*z); }
#if LOGICAL_AXES > LINEAR_AXES
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 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> ABS() const { return { T(_ABS(x)), T(_ABS(y)), T(_ABS(z)) }; }
FI XYZval<int16_t> asInt() { return { int16_t(x), int16_t(y), int16_t(z) }; }
FI XYZval<int16_t> asInt() const { return { int16_t(x), int16_t(y), int16_t(z) }; }
FI XYZval<int32_t> asLong() { return { int32_t(x), int32_t(y), int32_t(z) }; }
FI XYZval<int32_t> asLong() const { return { int32_t(x), int32_t(y), int32_t(z) }; }
FI XYZval<int32_t> ROUNDL() { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)) }; }
FI XYZval<int32_t> ROUNDL() const { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)) }; }
FI XYZval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) }; }
FI XYZval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) }; }
FI XYZval<float> reciprocal() const { return { _RECIP(x), _RECIP(y), _RECIP(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 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 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 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 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 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 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 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 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 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> 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 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]; }
FI const T& operator[](const int i) const { return pos[i]; }
FI XYZval<T>& operator= (const T v) { set(v, v, v ); return *this; }
// Cast to a type with more fields by making a new object
FI operator XYZEval<T>() const { return LINEAR_AXIS_ARRAY(x, y, z, i, j, k); }
// 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 XYZEval<T> &rs) { set(rs.x, rs.y, rs.z); 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; }
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; }
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; }
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; }
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) { 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; 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 float &v) { 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; ls.x *= v; ls.y *= v; ls.z *= 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) const { 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; ls.x /= v; ls.y /= v; ls.z /= 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 int &v) { 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; _RS(ls.x); _RS(ls.y); _RS(ls.z); 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) const { 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; _LS(ls.x); _LS(ls.y); _LS(ls.z); return ls; }
FI XYZval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; }
FI XYZval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
FI XYZval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
FI XYZval<T>& operator/=(const XYval<T> &rs) { x /= rs.x; y /= rs.y; 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 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; }
FI XYZval<T>& operator/=(const XYZval<T> &rs) { x /= rs.x; y /= rs.y; z /= rs.z; 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 XYZEval<T> &rs) { x -= rs.x; y -= rs.y; z -= rs.z; 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 XYZEval<T> &rs) { x /= rs.x; y /= rs.y; z /= rs.z; return *this; }
FI XYZval<T>& operator*=(const float &v) { x *= v; y *= v; z *= v; return *this; }
FI XYZval<T>& operator*=(const int &v) { x *= v; y *= v; z *= v; return *this; }
FI XYZval<T>& operator>>=(const int &v) { _RS(x); _RS(y); _RS(z); return *this; }
FI XYZval<T>& operator<<=(const int &v) { _LS(x); _LS(y); _LS(z); 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) { set(LINEAR_AXIS_ELEM(rs)); return *this; }
// Override other operators to get intuitive behaviors
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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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) 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 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 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-() { 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; }
// Modifier operators
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 XYval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP ); 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 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) { 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 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 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 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) { 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 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) const { return x == rs.x && y == rs.y && z == rs.z; }
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>
struct XYZEval {
union {
struct{ T x, y, z, e; };
struct{ T a, b, c; };
T pos[4];
struct { T LOGICAL_AXIS_ARGS(); };
struct { T LOGICAL_AXIS_LIST(_e, a, b, c, u, v, w); };
T pos[LOGICAL_AXES];
};
FI void reset() { x = y = z = e = 0; }
FI T magnitude() const { return (T)sqrtf(x*x + y*y + z*z + e*e); }
FI operator T* () { return pos; }
FI operator bool() { return e || z || x || y; }
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, const T pz) { x = px; y = py; z = pz; }
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 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 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]; }
// Reset all to 0
FI void reset() { LOGICAL_AXIS_GANG(e =, 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, const T py) { x = px; y = py; }
FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
FI void set(const XYZval<T> pxyz) { set(LINEAR_AXIS_ELEM(pxyz)); }
#if HAS_Z_AXIS
FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k); }
#endif
FI XYZEval<T> copy() const { return *this; }
FI XYZEval<T> ABS() const { return { T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(e)) }; }
FI XYZEval<int16_t> asInt() { return { int16_t(x), int16_t(y), int16_t(z), int16_t(e) }; }
FI XYZEval<int16_t> asInt() const { return { int16_t(x), int16_t(y), int16_t(z), int16_t(e) }; }
FI XYZEval<int32_t> asLong() { return { int32_t(x), int32_t(y), int32_t(z), int32_t(e) }; }
FI XYZEval<int32_t> asLong() const { return { int32_t(x), int32_t(y), int32_t(z), int32_t(e) }; }
FI XYZEval<int32_t> ROUNDL() { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(e)) }; }
FI XYZEval<int32_t> ROUNDL() const { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(e)) }; }
FI XYZEval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(e) }; }
FI XYZEval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(e) }; }
FI XYZEval<float> reciprocal() const { return { _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(e) }; }
FI XYZEval<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
FI XYZEval<float> asNative() const { XYZEval<float> o = asFloat(); toNative(o); return o; }
FI operator XYval<T>&() { return *(XYval<T>*)this; }
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
FI operator XYZval<T>&() { return *(XYZval<T>*)this; }
FI operator const XYZval<T>&() const { return *(const XYZval<T>*)this; }
FI T& operator[](const int i) { return pos[i]; }
FI const T& operator[](const int i) const { return pos[i]; }
FI XYZEval<T>& operator= (const T v) { set(v, v, v, v); return *this; }
FI XYZEval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y); return *this; }
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; }
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) const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; 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 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) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; 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) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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 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 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; }
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 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 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; }
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; }
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 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 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) { 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) { x += rs.x; y += rs.y; z += rs.z; return *this; }
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) { x *= rs.x; y *= rs.y; z *= rs.z; return *this; }
FI XYZEval<T>& operator/=(const XYZval<T> &rs) { x /= rs.x; y /= rs.y; z /= rs.z; return *this; }
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 XYZEval<T> &rs) { x -= rs.x; y -= rs.y; z -= rs.z; e -= rs.e; return *this; }
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 XYZEval<T> &rs) { x /= rs.x; y /= rs.y; z /= rs.z; e /= rs.e; return *this; }
FI XYZEval<T>& operator*=(const T &v) { x *= v; y *= v; z *= v; e *= v; return *this; }
FI XYZEval<T>& operator>>=(const int &v) { _RS(x); _RS(y); _RS(z); _RS(e); return *this; }
FI XYZEval<T>& operator<<=(const int &v) { _LS(x); _LS(y); _LS(z); _LS(e); return *this; }
FI bool operator==(const XYZval<T> &rs) { return x == rs.x && y == rs.y && z == rs.z; }
FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); }
FI bool operator==(const XYZval<T> &rs) const { return x == rs.x && y == rs.y && z == rs.z; }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
FI XYZEval<T> operator-() { return { -x, -y, -z, -e }; }
FI const XYZEval<T> operator-() const { return { -x, -y, -z, -e }; }
#if LOGICAL_AXES > LINEAR_AXES
FI void set(const XYval<T> pxy, const T pe) { set(pxy); e = pe; }
FI void set(const XYZval<T> pxyz, const T pe) { set(pxyz); e = pe; }
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); }
#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(LOGICAL_AXIS_GANG(+ e*e, + 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; }
// If any element is true then it's true
FI operator bool() { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k); }
// Explicit copy and copies with conversion
FI XYZEval<T> copy() const { XYZEval<T> o = *this; return o; }
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<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<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<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<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<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<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<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<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<float> reciprocal() const { return LOGICAL_AXIS_ARRAY(_RECIP(e), _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); }
// Marlin workspace shifting is done with G92 and M206
FI XYZEval<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
FI XYZEval<float> asNative() const { XYZEval<float> o = asFloat(); toNative(o); return o; }
// In-place cast to types having fewer fields
FI operator XYval<T>&() { return *(XYval<T>*)this; }
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
FI operator XYZval<T>&() { return *(XYZval<T>*)this; }
FI operator const XYZval<T>&() const { return *(const XYZval<T>*)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 XYZEval<T>& operator= (const T v) { set(LIST_N_1(LINEAR_AXES, v)); return *this; }
FI XYZEval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y); return *this; }
FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; }
// Override other operators to get intuitive behaviors
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) { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; 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) { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; 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) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; 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) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
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) { 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) 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) { 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) 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) { 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) 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) { 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) 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 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 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 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 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 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 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 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
@@ -516,6 +666,3 @@ struct XYZEval {
#undef _LS
#undef _RS
#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);
#endif
#if ABL_PLANAR
SERIAL_ECHOPGM("ABL Adjustment X");
LOOP_XYZ(a) {
SERIAL_ECHOPGM("ABL Adjustment");
LOOP_LINEAR_AXES(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('+');
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
// 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; }
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;
LOOP_XYZ(axis) {
LOOP_LINEAR_AXES(axis) {
if (distance_mm[axis]) {
const bool reversing = TEST(dm,axis);

View File

@@ -24,7 +24,7 @@
#include "../../inc/MarlinConfigPre.h"
#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
#if ENABLED(PROBE_MANUALLY)

View File

@@ -103,9 +103,7 @@ public:
}
static float get_z(const xy_pos_t &pos
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
, const_float_t factor=1.0f
#endif
OPTARG(ENABLE_LEVELING_FADE_HEIGHT, const_float_t factor=1.0f)
) {
#if DISABLED(ENABLE_LEVELING_FADE_HEIGHT)
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
* 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);
constexpr uint8_t eachsp = 1 + 6 + 1, // [-3.567]
@@ -263,7 +263,7 @@ bool unified_bed_leveling::sanity_check() {
void GcodeSuite::M1004() {
#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 (parser.seenval('H')) { // Handle H# parameter to set Hotend temp

View File

@@ -47,10 +47,10 @@ struct mesh_index_pair;
typedef struct {
bool C_seen;
int8_t V_verbosity,
int8_t KLS_storage_slot;
uint8_t R_repetition,
V_verbosity,
P_phase,
R_repetition,
KLS_storage_slot,
T_map_type;
float B_shim_thickness,
C_constant;
@@ -98,7 +98,7 @@ public:
static void report_state();
static void save_ubl_active_state_and_disable();
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_furthest_invalid_mesh_point() _O0;
static void reset();

View File

@@ -305,7 +305,7 @@ void unified_bed_leveling::G29() {
bool probe_deployed = false;
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');
#if ENABLED(HAS_MULTI_HOTEND)
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.
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;
if (!invalidate_all) {
while (count--) {
@@ -345,7 +345,7 @@ void unified_bed_leveling::G29() {
}
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)) {
SERIAL_ECHOLNPGM("Invalid test_pattern value. (-1 to 2)\n");
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.
//
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();
#endif // UBL_DEVEL_DEBUGGING
@@ -592,7 +592,7 @@ void unified_bed_leveling::G29() {
//
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();
@@ -617,10 +617,10 @@ void unified_bed_leveling::G29() {
//
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
return report_current_mesh(); // host program to be saved on the user's computer
if (param.KLS_storage_slot == -1) // Special case: 'Export' the mesh to the
return report_current_mesh(); // host so it can be saved in a file.
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) {
float sum = 0;
int n = 0;
uint8_t n = 0;
GRID_LOOP(x, y)
if (!isnan(z_values[x][y])) {
sum += z_values[x][y];
@@ -734,7 +734,7 @@ void unified_bed_leveling::shift_mesh_height() {
do {
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, ".");
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);
do {
idle();
idle_no_sleep();
new_z = ui.ubl_mesh_value();
TERN_(UBL_MESH_EDIT_MOVES_Z, do_blocking_move_to_z(h_offset + new_z)); // Move the nozzle as the point is edited
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
@@ -1083,7 +1083,7 @@ bool unified_bed_leveling::G29_parse_parameters() {
param.R_repetition = 0;
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);
if (param.R_repetition < 1) {
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)) {
SERIAL_ECHOLNPGM("?(V)erbose level implausible (0-4).\n");
err_flag = true;
}
if (parser.seen('P')) {
const int pv = parser.value_int();
const uint8_t pv = parser.value_byte();
#if !HAS_BED_PROBE
if (pv == 1) {
SERIAL_ECHOLNPGM("G29 P1 requires a probe.\n");
@@ -1181,7 +1181,7 @@ bool unified_bed_leveling::G29_parse_parameters() {
}
#endif
param.T_map_type = parser.intval('T');
param.T_map_type = parser.byteval('T');
if (!WITHIN(param.T_map_type, 0, 2)) {
SERIAL_ECHOLNPGM("Invalid map type.\n");
return UBL_ERR;
@@ -1833,7 +1833,7 @@ void unified_bed_leveling::smart_fill_mesh() {
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];
settings.load_mesh(param.KLS_storage_slot, &tmp_z_values);

View File

@@ -113,20 +113,22 @@
const xy_float_t ad = sign * dist;
const bool use_x_dist = ad.x > ad.y;
float on_axis_distance = use_x_dist ? dist.x : dist.y,
e_position = end.e - start.e,
z_position = end.z - start.z;
float on_axis_distance = use_x_dist ? dist.x : dist.y;
const float e_normalized_dist = e_position / on_axis_distance, // Allow divide by zero
z_normalized_dist = z_position / on_axis_distance;
const float z_normalized_dist = (end.z - start.z) / on_axis_distance; // Allow divide by zero
#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;
const float ratio = dist.y / dist.x, // Allow divide by zero
c = start.y - ratio * start.x;
const bool inf_normalized_flag = isinf(e_normalized_dist),
inf_ratio_flag = isinf(ratio);
const bool inf_ratio_flag = isinf(ratio);
xyze_pos_t dest; // Stores XYZE for segmented moves
/**
* Handle vertical lines that stay within one column.
@@ -143,34 +145,36 @@
* For others the next X is the same so this can continue.
* 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);
// Undefined parts of the Mesh in z_values[][] are NAN.
// Replace NAN corrections with 0.0 to prevent NAN propagation.
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
* 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.
*/
if (ry != start.y) {
if (dest.y != start.y) {
if (!inf_normalized_flag) { // fall-through faster than branch
on_axis_distance = use_x_dist ? rx - start.x : ry - start.y;
e_position = start.e + on_axis_distance * e_normalized_dist;
z_position = start.z + on_axis_distance * z_normalized_dist;
on_axis_distance = use_x_dist ? dest.x - start.x : dest.y - start.y;
TERN_(HAS_EXTRUDERS, dest.e = start.e + on_axis_distance * e_normalized_dist);
dest.z = start.z + on_axis_distance * z_normalized_dist;
}
else {
e_position = end.e;
z_position = end.z;
TERN_(HAS_EXTRUDERS, dest.e = end.e);
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 ");
}
@@ -188,12 +192,13 @@
*/
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.
while (icell.x != iend.x + ineg.x) {
icell.x += iadd.x;
const float rx = mesh_index_to_xpos(icell.x);
const float ry = ratio * rx + c; // Calculate Y at the next X mesh line
dest.x = mesh_index_to_xpos(icell.x);
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);
// 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
* 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) {
on_axis_distance = use_x_dist ? rx - start.x : ry - start.y;
e_position = start.e + on_axis_distance * e_normalized_dist; // is based on X or Y because this is a horizontal move
z_position = start.z + on_axis_distance * z_normalized_dist;
on_axis_distance = use_x_dist ? dest.x - start.x : dest.y - start.y;
TERN_(HAS_EXTRUDERS, dest.e = start.e + on_axis_distance * e_normalized_dist); // Based on X or Y because the move is horizontal
dest.z = start.z + on_axis_distance * z_normalized_dist;
}
else {
e_position = end.e;
z_position = end.z;
TERN_(HAS_EXTRUDERS, dest.e = end.e);
dest.z = end.z;
}
if (!planner.buffer_segment(rx, ry, 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;
} //else printf("FIRST MOVE PRUNED ");
}
@@ -239,57 +245,65 @@
while (cnt) {
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),
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.)
next_mesh_line_y = mesh_index_to_ypos(icell.y + iadd.y);
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
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);
// Undefined parts of the Mesh in z_values[][] are NAN.
// Replace NAN corrections with 0.0 to prevent NAN propagation.
if (isnan(z0)) z0 = 0.0;
dest.y = next_mesh_line_y;
if (!inf_normalized_flag) {
on_axis_distance = use_x_dist ? rx - start.x : next_mesh_line_y - start.y;
e_position = start.e + on_axis_distance * e_normalized_dist;
z_position = start.z + on_axis_distance * z_normalized_dist;
on_axis_distance = use_x_dist ? dest.x - start.x : dest.y - start.y;
TERN_(HAS_EXTRUDERS, dest.e = start.e + on_axis_distance * e_normalized_dist);
dest.z = start.z + on_axis_distance * z_normalized_dist;
}
else {
e_position = end.e;
z_position = end.z;
TERN_(HAS_EXTRUDERS, dest.e = end.e);
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;
cnt.y--;
}
else {
// 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);
// Undefined parts of the Mesh in z_values[][] are NAN.
// Replace NAN corrections with 0.0 to prevent NAN propagation.
if (isnan(z0)) z0 = 0.0;
dest.x = next_mesh_line_x;
if (!inf_normalized_flag) {
on_axis_distance = use_x_dist ? next_mesh_line_x - start.x : ry - start.y;
e_position = start.e + on_axis_distance * e_normalized_dist;
z_position = start.z + on_axis_distance * z_normalized_dist;
on_axis_distance = use_x_dist ? dest.x - start.x : dest.y - start.y;
TERN_(HAS_EXTRUDERS, dest.e = start.e + on_axis_distance * e_normalized_dist);
dest.z = start.z + on_axis_distance * z_normalized_dist;
}
else {
e_position = end.e;
z_position = end.z;
TERN_(HAS_EXTRUDERS, dest.e = end.e);
dest.z = end.z;
}
if (!planner.buffer_segment(next_mesh_line_x, ry, 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.x += iadd.x;
cnt.x--;
}
@@ -362,15 +376,11 @@
while (--segments) {
raw += diff;
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
#if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration
#endif
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
);
}
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, segment_xyz_mm
#if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration
#endif
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
);
return false; // Did not set current from destination
}
@@ -442,11 +452,9 @@
#endif
;
planner.buffer_line(raw.x, raw.y, raw.z + z_cxcy, raw.e, scaled_fr_mm_s, active_extruder, segment_xyz_mm
#if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration
#endif
);
const float oldz = raw.z; raw.z += z_cxcy;
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration) );
raw.z = oldz;
if (segments == 0) // done with last segment
return false; // didn't set current from destination

View File

@@ -24,9 +24,11 @@
#include "../inc/MarlinConfig.h"
#define BINARY_STREAM_COMPRESSION
#if ENABLED(BINARY_STREAM_COMPRESSION)
#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
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);
}
#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 {
private:
struct Packet {

View File

@@ -41,11 +41,7 @@ bool CaseLight::on = CASE_LIGHT_DEFAULT_ON;
#if CASE_LIGHT_IS_COLOR_LED
#include "leds/leds.h"
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]) };
#endif
#ifndef INVERT_CASE_LIGHT
#define INVERT_CASE_LIGHT false
LEDColor CaseLight::color = { init_case_light[0], init_case_light[1], init_case_light[2] OPTARG(HAS_WHITE_LED, init_case_light[3]) };
#endif
void CaseLight::update(const bool sflag) {
@@ -64,14 +60,12 @@ void CaseLight::update(const bool sflag) {
if (sflag && on)
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);
#endif
#if CASE_LIGHT_IS_COLOR_LED
leds.set_color(MakeLEDColor(color.r, color.g, color.b, color.w, n10ct));
leds.set_color(LEDColor(color.r, color.g, color.b OPTARG(HAS_WHITE_LED, color.w), n10ct));
#else // !CASE_LIGHT_IS_COLOR_LED
#if CASELIGHT_USES_BRIGHTNESS
@@ -86,7 +80,7 @@ void CaseLight::update(const bool sflag) {
else
#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);
}

View File

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

View File

@@ -73,7 +73,7 @@ uint8_t MCP4728::analogWrite(const uint8_t channel, const uint16_t value) {
uint8_t MCP4728::eepromWrite() {
Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS));
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(lowByte(dac_values[i]));
}
@@ -135,7 +135,7 @@ void MCP4728::setDrvPct(xyze_uint_t &pct) {
*/
uint8_t MCP4728::fastWrite() {
Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS));
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
Wire.write(highByte(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.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.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]); }
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);
}
@@ -85,10 +85,16 @@ void StepperDAC::print_values() {
if (!dac_present) return;
SERIAL_ECHO_MSG("Stepper current values in % (Amps):");
SERIAL_ECHO_START();
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(")"));
SERIAL_ECHOPAIR_P( SP_Z_LBL, dac_perc(Z_AXIS), PSTR(" ("), dac_amps(Z_AXIS), PSTR(")"));
SERIAL_ECHOLNPAIR_P(SP_E_LBL, dac_perc(E_AXIS), PSTR(" ("), dac_amps(E_AXIS), PSTR(")"));
SERIAL_ECHOPAIR_P(SP_X_LBL, dac_perc(X_AXIS), PSTR(" ("), dac_amps(X_AXIS), PSTR(")"));
#if HAS_Y_AXIS
SERIAL_ECHOPAIR_P(SP_Y_LBL, dac_perc(Y_AXIS), PSTR(" ("), dac_amps(Y_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() {

View File

@@ -327,7 +327,7 @@ int32_t I2CPositionEncoder::get_raw_count() {
}
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;
const float startPosition = soft_endstop.min[encoderAxis] + 10,
@@ -337,7 +337,7 @@ bool I2CPositionEncoder::test_axis() {
ec = false;
xyze_pos_t startCoord, endCoord;
LOOP_XYZ(a) {
LOOP_LINEAR_AXES(a) {
startCoord[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;
planner.synchronize();
startCoord.e = planner.get_axis_position_mm(E_AXIS);
planner.buffer_line(startCoord, fr_mm_s, 0);
planner.synchronize();
#if HAS_EXTRUDERS
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 (!trusted) {
@@ -357,7 +360,7 @@ bool I2CPositionEncoder::test_axis() {
}
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.synchronize();
}
@@ -392,7 +395,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
travelDistance = endDistance - startDistance;
xyze_pos_t startCoord, endCoord;
LOOP_XYZ(a) {
LOOP_LINEAR_AXES(a) {
startCoord[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();
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.synchronize();
@@ -411,7 +414,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
//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.synchronize();
@@ -497,9 +500,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_1_AXIS == E_AXIS
encoders[i].set_homed();
#endif
TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_1_AXIS == E_AXIS) encoders[i].set_homed());
#endif
#if I2CPE_ENCODER_CNT > 1
@@ -528,9 +529,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_2_AXIS == E_AXIS
encoders[i].set_homed();
#endif
TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_2_AXIS == E_AXIS) encoders[i].set_homed());
#endif
#if I2CPE_ENCODER_CNT > 2
@@ -557,11 +556,9 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_ec_threshold(I2CPE_ENC_3_EC_THRESH);
#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
encoders[i].set_homed();
#endif
TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_3_AXIS == E_AXIS) encoders[i].set_homed());
#endif
#if I2CPE_ENCODER_CNT > 3
@@ -590,9 +587,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_4_AXIS == E_AXIS
encoders[i].set_homed();
#endif
TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_4_AXIS == E_AXIS) encoders[i].set_homed());
#endif
#if I2CPE_ENCODER_CNT > 4
@@ -621,9 +616,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_5_AXIS == E_AXIS
encoders[i].set_homed();
#endif
TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_5_AXIS == E_AXIS) encoders[i].set_homed());
#endif
#if I2CPE_ENCODER_CNT > 5
@@ -652,9 +645,7 @@ void I2CPositionEncodersMgr::init() {
encoders[i].set_active(encoders[i].passes_test(true));
#if I2CPE_ENC_6_AXIS == E_AXIS
encoders[i].set_homed();
#endif
TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_6_AXIS == E_AXIS) encoders[i].set_homed());
#endif
}
@@ -822,7 +813,7 @@ void I2CPositionEncodersMgr::M860() {
const bool hasU = parser.seen_test('U'), hasO = parser.seen_test('O');
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen_test(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_position(idx, hasU, hasO);
@@ -849,7 +840,7 @@ void I2CPositionEncodersMgr::M861() {
if (parse()) return;
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_status(idx);
@@ -877,7 +868,7 @@ void I2CPositionEncodersMgr::M862() {
if (parse()) return;
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
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);
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) calibrate_steps_mm(idx, iterations);
@@ -984,7 +975,7 @@ void I2CPositionEncodersMgr::M865() {
if (parse()) return;
if (!I2CPE_addr) {
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
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');
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) {
@@ -1053,7 +1044,7 @@ void I2CPositionEncodersMgr::M867() {
const int8_t onoff = parser.seenval('S') ? parser.value_int() : -1;
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) {
@@ -1089,7 +1080,7 @@ void I2CPositionEncodersMgr::M868() {
const float newThreshold = parser.seenval('T') ? parser.value_float() : -9999;
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) {
@@ -1123,7 +1114,7 @@ void I2CPositionEncodersMgr::M869() {
if (parse()) return;
if (I2CPE_idx == 0xFF) {
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
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
* included in the G-code. Use M207 Z0 to to prevent double hop.
*/
void FWRetract::retract(const bool retracting
#if HAS_MULTI_EXTRUDER
, bool swapping/*=false*/
#endif
) {
void FWRetract::retract(const bool retracting OPTARG(HAS_MULTI_EXTRUDER, bool swapping/*=false*/)) {
// Prevent two retracts or recovers in a row
if (retracted[active_extruder] == retracting) return;

View File

@@ -74,11 +74,7 @@ public:
#endif
}
static void retract(const bool retracting
#if HAS_MULTI_EXTRUDER
, bool swapping = false
#endif
);
static void retract(const bool retracting OPTARG(HAS_MULTI_EXTRUDER, bool swapping = false));
static void M207();
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]
xyz_float_t move_dist{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];
hypot2 += sq(move_dist[i]);
}

View File

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

View File

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

View File

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

View File

@@ -25,6 +25,10 @@
* NeoPixel support
*/
#ifndef _NEOPIXEL_INCLUDE_
#error "Always include 'leds.h' and not 'neopixel.h' directly."
#endif
// ------------------------
// Includes
// ------------------------
@@ -38,6 +42,18 @@
// 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)
#define MULTIPLE_NEOPIXEL_TYPES 1
#endif
@@ -46,29 +62,16 @@
#define CONJOINED_NEOPIXEL 1
#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
// ------------------------
class Marlin_NeoPixel {
private:
static Adafruit_NeoPixel adaneo1
#if CONJOINED_NEOPIXEL
, adaneo2
#endif
;
static Adafruit_NeoPixel adaneo1;
#if CONJOINED_NEOPIXEL
static Adafruit_NeoPixel adaneo2;
#endif
public:
static int8_t neoindex;
@@ -78,8 +81,9 @@ public:
static void set_color(const uint32_t c);
#ifdef NEOPIXEL_BKGD_LED_INDEX
static void set_color_background();
#ifdef NEOPIXEL_BKGD_INDEX_FIRST
static void set_background_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
static void reset_background_color();
#endif
static inline void begin() {
@@ -93,9 +97,7 @@ public:
else adaneo1.setPixelColor(n, c);
#else
adaneo1.setPixelColor(n, c);
#if MULTIPLE_NEOPIXEL_TYPES
adaneo2.setPixelColor(n, c);
#endif
TERN_(MULTIPLE_NEOPIXEL_TYPES, adaneo2.setPixelColor(n, c));
#endif
}
@@ -112,7 +114,6 @@ public:
#if CONJOINED_NEOPIXEL
adaneo2.show();
#else
IF_DISABLED(NEOPIXEL2_SEPARATE, adaneo1.setPin(NEOPIXEL2_PIN));
adaneo1.show();
adaneo1.setPin(NEOPIXEL_PIN);
#endif
@@ -120,15 +121,13 @@ public:
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
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 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
#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 NEO2_WHITE 255, 255, 255
#else
#define NEOPIXEL2_IS_RGBW 1
#endif
#if NEOPIXEL2_IS_RGB
#define NEO2_WHITE 255, 255, 255, 0
#else
#define HAS_WHITE_LED2 1 // A white component can be passed for NEOPIXEL2
#define NEO2_WHITE 0, 0, 0, 255
#endif
@@ -172,11 +168,13 @@ extern Marlin_NeoPixel neo;
// Accessors
static inline uint16_t pixels() { return adaneo.numPixels();}
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) {
return adaneo.Color(r, g, b, 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 OPTARG(HAS_WHITE_LED2, w));
}
};
extern Marlin_NeoPixel2 neo2;
#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
#if ENABLED(PCA9632_RGBW)
, const byte vw
#endif
OPTARG(PCA9632_RGBW, const byte vw)
) {
#if DISABLED(PCA9632_NO_AUTO_INC)
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
#if ENABLED(PCA9632_RGBW)
, color.w
#endif
OPTARG(PCA9632_RGBW, color.w)
);
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);
}
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(
MakeLEDColor(r, g, b, 0, neo.brightness())
#if ENABLED(NEOPIXEL_IS_SEQUENTIAL)
, true
#endif
LEDColor(r, g, b OPTARG(HAS_WHITE_LED, w) OPTARG(NEOPIXEL_LED, neo.brightness()))
OPTARG(NEOPIXEL_IS_SEQUENTIAL, true)
);
}

View File

@@ -24,7 +24,14 @@
#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) {
planner.synchronize();

View File

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

View File

@@ -81,7 +81,10 @@ bool Power::is_power_needed() {
#endif
) 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 HAS_HOTEND && AUTO_POWER_E_TEMP
@@ -105,12 +108,12 @@ bool Power::is_power_needed() {
void Power::check() {
static millis_t nextPowerCheck = 0;
millis_t ms = millis();
if (ELAPSED(ms, nextPowerCheck)) {
nextPowerCheck = ms + 2500UL;
millis_t now = millis();
if (ELAPSED(now, nextPowerCheck)) {
nextPowerCheck = now + 2500UL;
if (is_power_needed())
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();
}
}

View File

@@ -197,7 +197,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
#endif
#endif
#if EXTRUDERS
#if HAS_EXTRUDERS
HOTEND_LOOP() info.target_temperature[e] = thermalManager.degTargetHotend(e);
#endif
@@ -375,7 +375,7 @@ void PrintJobRecovery::resume() {
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;
@@ -549,7 +549,7 @@ void PrintJobRecovery::resume() {
TERN_(HAS_HOME_OFFSET, home_offset = info.home_offset);
TERN_(HAS_POSITION_SHIFT, position_shift = info.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
// Relative axis modes
@@ -581,7 +581,7 @@ void PrintJobRecovery::resume() {
if (info.valid_head) {
if (info.valid_head == info.valid_foot) {
DEBUG_ECHOPGM("current_position: ");
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (i) DEBUG_CHAR(',');
DEBUG_DECIMAL(info.current_position[i]);
}
@@ -599,7 +599,7 @@ void PrintJobRecovery::resume() {
#if HAS_HOME_OFFSET
DEBUG_ECHOPGM("home_offset: ");
LOOP_XYZ(i) {
LOOP_LINEAR_AXES(i) {
if (i) DEBUG_CHAR(',');
DEBUG_DECIMAL(info.home_offset[i]);
}
@@ -608,7 +608,7 @@ void PrintJobRecovery::resume() {
#if HAS_POSITION_SHIFT
DEBUG_ECHOPGM("position_shift: ");
LOOP_XYZ(i) {
LOOP_LINEAR_AXES(i) {
if (i) DEBUG_CHAR(',');
DEBUG_DECIMAL(info.position_shift[i]);
}

View File

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

View File

@@ -47,7 +47,7 @@ typedef struct {
// Probe temperature calibration constants
#ifndef PTC_SAMPLE_COUNT
#define PTC_SAMPLE_COUNT 10U
#define PTC_SAMPLE_COUNT 10
#endif
#ifndef PTC_SAMPLE_RES
#define PTC_SAMPLE_RES 5
@@ -55,22 +55,22 @@ typedef struct {
#ifndef PTC_SAMPLE_START
#define PTC_SAMPLE_START 30
#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
#ifndef BTC_PROBE_TEMP
#define BTC_PROBE_TEMP 30
#endif
#ifndef BTC_SAMPLE_COUNT
#define BTC_SAMPLE_COUNT 10U
#define BTC_SAMPLE_COUNT 10
#endif
#ifndef BTC_SAMPLE_STEP
#ifndef BTC_SAMPLE_RES
#define BTC_SAMPLE_RES 5
#endif
#ifndef BTC_SAMPLE_START
#define BTC_SAMPLE_START 60
#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
#define PTC_PROBE_HEATING_OFFSET 0.5f

View File

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

View File

@@ -211,7 +211,7 @@
SERIAL_PRINTLN(data.drv_status, HEX);
if (data.is_ot) SERIAL_ECHOLNPGM("overtemperature");
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"));
}
#endif
@@ -417,6 +417,21 @@
}
#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)
(void)monitor_tmc_driver(stepperE0, need_update_error_counters, need_debug_reporting);
#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) {
if (print_x) {
static void tmc_debug_loop(const TMC_debug_enum n, LOGICAL_AXIS_ARGS(const bool)) {
if (x) {
#if AXIS_IS_TMC(X)
tmc_status(stepperX, i);
tmc_status(stepperX, n);
#endif
#if AXIS_IS_TMC(X2)
tmc_status(stepperX2, i);
tmc_status(stepperX2, n);
#endif
}
if (print_y) {
if (TERN0(HAS_Y_AXIS, y)) {
#if AXIS_IS_TMC(Y)
tmc_status(stepperY, i);
tmc_status(stepperY, n);
#endif
#if AXIS_IS_TMC(Y2)
tmc_status(stepperY2, i);
tmc_status(stepperY2, n);
#endif
}
if (print_z) {
if (TERN0(HAS_Z_AXIS, z)) {
#if AXIS_IS_TMC(Z)
tmc_status(stepperZ, i);
tmc_status(stepperZ, n);
#endif
#if AXIS_IS_TMC(Z2)
tmc_status(stepperZ2, i);
tmc_status(stepperZ2, n);
#endif
#if AXIS_IS_TMC(Z3)
tmc_status(stepperZ3, i);
tmc_status(stepperZ3, n);
#endif
#if AXIS_IS_TMC(Z4)
tmc_status(stepperZ4, i);
tmc_status(stepperZ4, n);
#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)
tmc_status(stepperE0, i);
tmc_status(stepperE0, n);
#endif
#if AXIS_IS_TMC(E1)
tmc_status(stepperE1, i);
tmc_status(stepperE1, n);
#endif
#if AXIS_IS_TMC(E2)
tmc_status(stepperE2, i);
tmc_status(stepperE2, n);
#endif
#if AXIS_IS_TMC(E3)
tmc_status(stepperE3, i);
tmc_status(stepperE3, n);
#endif
#if AXIS_IS_TMC(E4)
tmc_status(stepperE4, i);
tmc_status(stepperE4, n);
#endif
#if AXIS_IS_TMC(E5)
tmc_status(stepperE5, i);
tmc_status(stepperE5, n);
#endif
#if AXIS_IS_TMC(E6)
tmc_status(stepperE6, i);
tmc_status(stepperE6, n);
#endif
#if AXIS_IS_TMC(E7)
tmc_status(stepperE7, i);
tmc_status(stepperE7, n);
#endif
}
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) {
if (print_x) {
static void drv_status_loop(const TMC_drv_status_enum n, LOGICAL_AXIS_ARGS(const bool)) {
if (x) {
#if AXIS_IS_TMC(X)
tmc_parse_drv_status(stepperX, i);
tmc_parse_drv_status(stepperX, n);
#endif
#if AXIS_IS_TMC(X2)
tmc_parse_drv_status(stepperX2, i);
tmc_parse_drv_status(stepperX2, n);
#endif
}
if (print_y) {
if (TERN0(HAS_Y_AXIS, y)) {
#if AXIS_IS_TMC(Y)
tmc_parse_drv_status(stepperY, i);
tmc_parse_drv_status(stepperY, n);
#endif
#if AXIS_IS_TMC(Y2)
tmc_parse_drv_status(stepperY2, i);
tmc_parse_drv_status(stepperY2, n);
#endif
}
if (print_z) {
if (TERN0(HAS_Z_AXIS, z)) {
#if AXIS_IS_TMC(Z)
tmc_parse_drv_status(stepperZ, i);
tmc_parse_drv_status(stepperZ, n);
#endif
#if AXIS_IS_TMC(Z2)
tmc_parse_drv_status(stepperZ2, i);
tmc_parse_drv_status(stepperZ2, n);
#endif
#if AXIS_IS_TMC(Z3)
tmc_parse_drv_status(stepperZ3, i);
tmc_parse_drv_status(stepperZ3, n);
#endif
#if AXIS_IS_TMC(Z4)
tmc_parse_drv_status(stepperZ4, i);
tmc_parse_drv_status(stepperZ4, n);
#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)
tmc_parse_drv_status(stepperE0, i);
tmc_parse_drv_status(stepperE0, n);
#endif
#if AXIS_IS_TMC(E1)
tmc_parse_drv_status(stepperE1, i);
tmc_parse_drv_status(stepperE1, n);
#endif
#if AXIS_IS_TMC(E2)
tmc_parse_drv_status(stepperE2, i);
tmc_parse_drv_status(stepperE2, n);
#endif
#if AXIS_IS_TMC(E3)
tmc_parse_drv_status(stepperE3, i);
tmc_parse_drv_status(stepperE3, n);
#endif
#if AXIS_IS_TMC(E4)
tmc_parse_drv_status(stepperE4, i);
tmc_parse_drv_status(stepperE4, n);
#endif
#if AXIS_IS_TMC(E5)
tmc_parse_drv_status(stepperE5, i);
tmc_parse_drv_status(stepperE5, n);
#endif
#if AXIS_IS_TMC(E6)
tmc_parse_drv_status(stepperE6, i);
tmc_parse_drv_status(stepperE6, n);
#endif
#if AXIS_IS_TMC(E7)
tmc_parse_drv_status(stepperE7, i);
tmc_parse_drv_status(stepperE7, n);
#endif
}
@@ -889,9 +924,10 @@
* M122 report functions
*/
void tmc_report_all(bool print_x, const bool print_y, const bool print_z, const bool print_e) {
#define TMC_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_debug_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, print_x, print_y, print_z, print_e); }while(0)
void tmc_report_all(LOGICAL_AXIS_ARGS(const bool)) {
#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, LOGICAL_AXIS_ARGS()); }while(0)
TMC_REPORT("\t", TMC_CODES);
#if HAS_DRIVER(TMC2209)
TMC_REPORT("Address\t", TMC_UART_ADDR);
@@ -1015,72 +1051,82 @@
}
#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) {
if (print_x) {
static void tmc_get_registers(TMC_get_registers_enum n, LOGICAL_AXIS_ARGS(const bool)) {
if (x) {
#if AXIS_IS_TMC(X)
tmc_get_registers(stepperX, i);
tmc_get_registers(stepperX, n);
#endif
#if AXIS_IS_TMC(X2)
tmc_get_registers(stepperX2, i);
tmc_get_registers(stepperX2, n);
#endif
}
if (print_y) {
if (TERN0(HAS_Y_AXIS, y)) {
#if AXIS_IS_TMC(Y)
tmc_get_registers(stepperY, i);
tmc_get_registers(stepperY, n);
#endif
#if AXIS_IS_TMC(Y2)
tmc_get_registers(stepperY2, i);
tmc_get_registers(stepperY2, n);
#endif
}
if (print_z) {
if (TERN0(HAS_Z_AXIS, z)) {
#if AXIS_IS_TMC(Z)
tmc_get_registers(stepperZ, i);
tmc_get_registers(stepperZ, n);
#endif
#if AXIS_IS_TMC(Z2)
tmc_get_registers(stepperZ2, i);
tmc_get_registers(stepperZ2, n);
#endif
#if AXIS_IS_TMC(Z3)
tmc_get_registers(stepperZ3, i);
tmc_get_registers(stepperZ3, n);
#endif
#if AXIS_IS_TMC(Z4)
tmc_get_registers(stepperZ4, i);
tmc_get_registers(stepperZ4, n);
#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)
tmc_get_registers(stepperE0, i);
tmc_get_registers(stepperE0, n);
#endif
#if AXIS_IS_TMC(E1)
tmc_get_registers(stepperE1, i);
tmc_get_registers(stepperE1, n);
#endif
#if AXIS_IS_TMC(E2)
tmc_get_registers(stepperE2, i);
tmc_get_registers(stepperE2, n);
#endif
#if AXIS_IS_TMC(E3)
tmc_get_registers(stepperE3, i);
tmc_get_registers(stepperE3, n);
#endif
#if AXIS_IS_TMC(E4)
tmc_get_registers(stepperE4, i);
tmc_get_registers(stepperE4, n);
#endif
#if AXIS_IS_TMC(E5)
tmc_get_registers(stepperE5, i);
tmc_get_registers(stepperE5, n);
#endif
#if AXIS_IS_TMC(E6)
tmc_get_registers(stepperE6, i);
tmc_get_registers(stepperE6, n);
#endif
#if AXIS_IS_TMC(E7)
tmc_get_registers(stepperE7, i);
tmc_get_registers(stepperE7, n);
#endif
}
SERIAL_EOL();
}
void tmc_get_registers(bool print_x, bool print_y, bool print_z, bool print_e) {
#define _TMC_GET_REG(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_get_registers(ITEM, print_x, print_y, print_z, print_e); }while(0)
void tmc_get_registers(LOGICAL_AXIS_ARGS(bool)) {
#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)
_TMC_GET_REG("\t", TMC_AXIS_CODES);
TMC_GET_REG(GCONF, "\t\t");
@@ -1165,6 +1211,15 @@
#if AXIS_HAS_SPI(Z4)
SET_CS_PIN(Z4);
#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)
SET_CS_PIN(E0);
#endif
@@ -1214,10 +1269,10 @@ static bool test_connection(TMC &st) {
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;
if (test_x) {
if (x) {
#if AXIS_IS_TMC(X)
axis_connection += test_connection(stepperX);
#endif
@@ -1226,7 +1281,7 @@ void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z
#endif
}
if (test_y) {
if (TERN0(HAS_Y_AXIS, y)) {
#if AXIS_IS_TMC(Y)
axis_connection += test_connection(stepperY);
#endif
@@ -1235,7 +1290,7 @@ void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z
#endif
}
if (test_z) {
if (TERN0(HAS_Z_AXIS, z)) {
#if AXIS_IS_TMC(Z)
axis_connection += test_connection(stepperZ);
#endif
@@ -1250,7 +1305,17 @@ void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z
#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)
axis_connection += test_connection(stepperE0);
#endif

View File

@@ -70,15 +70,9 @@ class TMCStorage {
}
struct {
#if ENABLED(HAS_STEALTHCHOP)
bool stealthChop_enabled = false;
#endif
#if ENABLED(HYBRID_THRESHOLD)
uint8_t hybrid_thrs = 0;
#endif
#if ENABLED(USE_SENSORLESS)
int16_t homing_thrs = 0;
#endif
OPTCODE(HAS_STEALTHCHOP, bool stealthChop_enabled = false)
OPTCODE(HYBRID_THRESHOLD, uint8_t hybrid_thrs = 0)
OPTCODE(USE_SENSORLESS, int16_t homing_thrs = 0)
} stored;
};
@@ -341,14 +335,14 @@ void tmc_print_current(TMC &st) {
#endif
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(MONITOR_DRIVER_STATUS)
void tmc_set_report_interval(const uint16_t update_interval);
#endif
void tmc_report_all(const bool print_x, const bool print_y, const bool print_z, const bool print_e);
void tmc_get_registers(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(LOGICAL_AXIS_ARGS(const bool));
#endif
/**
@@ -361,16 +355,16 @@ void test_tmc_connection(const bool test_x, const bool test_y, const bool test_z
#if USE_SENSORLESS
// 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)
extern millis_t sg_guard_period;
constexpr uint16_t default_sg_guard_duration = 400;
struct slow_homing_t {
struct motion_state_t {
xy_ulong_t acceleration;
#if ENABLED(HAS_CLASSIC_JERK)
xy_float_t jerk_xy;
xy_float_t jerk_state;
#endif
};
#endif

View File

@@ -291,7 +291,7 @@ typedef struct {
if (p2.x < 0 || p2.x >= (GRID_MAX_POINTS_X)) 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;
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;
@@ -330,12 +330,8 @@ typedef struct {
thermalManager.setTargetBed(bed_temp);
// Wait for the temperature to stabilize
if (!thermalManager.wait_for_bed(true
#if G26_CLICK_CAN_CANCEL
, true
#endif
)
) return G26_ERR;
if (!thermalManager.wait_for_bed(true OPTARG(G26_CLICK_CAN_CANCEL, true)))
return G26_ERR;
}
#else
@@ -352,11 +348,8 @@ typedef struct {
thermalManager.setTargetHotend(hotend_temp, active_extruder);
// Wait for the temperature to stabilize
if (!thermalManager.wait_for_hotend(active_extruder, true
#if G26_CLICK_CAN_CANCEL
, true
#endif
)) return G26_ERR;
if (!thermalManager.wait_for_hotend(active_extruder, true OPTARG(G26_CLICK_CAN_CANCEL, true)))
return G26_ERR;
#if HAS_WIRED_LCD
ui.reset_status();

View File

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

View File

@@ -246,7 +246,7 @@ G29_TYPE GcodeSuite::G29() {
// Send 'N' to force homing before G29 (internal only)
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
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)));
// 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);
if (isnan(abl.measured_z)) {
set_bed_leveling_enabled(abl.reenable);
@@ -795,7 +795,7 @@ G29_TYPE GcodeSuite::G29() {
const int ind = abl.indexIntoAB[xx][yy];
xyz_float_t tmp = { abl.eqnAMatrix[ind + 0 * abl.abl_points],
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);
const float subval = get_min ? abl.mean : tmp.z + min_diff,
diff = abl.eqnBVector[ind] - subval;

View File

@@ -70,7 +70,7 @@ void GcodeSuite::G29() {
return;
}
int8_t ix, iy;
int8_t ix, iy = 0;
switch (state) {
case MeshReport:
@@ -87,7 +87,8 @@ void GcodeSuite::G29() {
mbl.reset();
mbl_probe_index = 0;
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;
}
state = MeshNext;
@@ -109,6 +110,7 @@ void GcodeSuite::G29() {
else {
// Save Z for the previous mesh position
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);
}
// 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);
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),
mly = max_length(Y_AXIS),
@@ -164,24 +164,24 @@
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
slow_homing_t begin_slow_homing() {
slow_homing_t slow_homing{0};
slow_homing.acceleration.set(planner.settings.max_acceleration_mm_per_s2[X_AXIS],
motion_state_t begin_slow_homing() {
motion_state_t motion_state{0};
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[X_AXIS] = 100;
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = 100;
#if HAS_CLASSIC_JERK
slow_homing.jerk_xy = planner.max_jerk;
motion_state.jerk_state = planner.max_jerk;
planner.max_jerk.set(0, 0);
#endif
planner.reset_acceleration_rates();
return slow_homing;
return motion_state;
}
void end_slow_homing(const slow_homing_t &slow_homing) {
planner.settings.max_acceleration_mm_per_s2[X_AXIS] = slow_homing.acceleration.x;
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = slow_homing.acceleration.y;
TERN_(HAS_CLASSIC_JERK, planner.max_jerk = slow_homing.jerk_xy);
void end_slow_homing(const motion_state_t &motion_state) {
planner.settings.max_acceleration_mm_per_s2[X_AXIS] = motion_state.acceleration.x;
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = motion_state.acceleration.y;
TERN_(HAS_CLASSIC_JERK, planner.max_jerk = motion_state.jerk_state);
planner.reset_acceleration_rates();
}
@@ -195,9 +195,9 @@
* None Home to all axes with no parameters.
* With QUICK_HOME enabled XY will home together, then Z.
*
* O Home only if position is unknown
*
* Rn Raise by n mm/inches before homing
* 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
* R<linear> Raise by n mm/inches before homing
*
* Cartesian/SCARA parameters
*
@@ -220,7 +220,7 @@ void GcodeSuite::G28() {
#if ENABLED(MARLIN_DEV_MODE)
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();
SERIAL_ECHOLNPGM("Simulated Homing");
report_current_position();
@@ -229,7 +229,7 @@ void GcodeSuite::G28() {
#endif
// 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");
return;
}
@@ -242,12 +242,16 @@ void GcodeSuite::G28() {
SET_SOFT_ENDSTOP_LOOSE(false); // Reset a leftover 'loose' motion state
// Disable the leveling matrix before homing
#if HAS_LEVELING
const bool leveling_restore_state = parser.boolval('L', TERN(RESTORE_LEVELING_AFTER_G28, planner.leveling_active, ENABLED(ENABLE_LEVELING_AFTER_G28)));
IF_ENABLED(PROBE_MANUALLY, g29_in_progress = false); // Cancel the active G29 session
set_bed_leveling_enabled(false);
#if CAN_SET_LEVELING_AFTER_G28
const bool leveling_restore_state = parser.boolval('L', TERN1(RESTORE_LEVELING_AFTER_G28, planner.leveling_active));
#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
TERN_(CNC_WORKSPACE_PLANES, workspace_plane = PLANE_XY);
@@ -285,7 +289,9 @@ void GcodeSuite::G28() {
#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
#if HAS_MULTI_HOTEND
@@ -311,7 +317,7 @@ void GcodeSuite::G28() {
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)
@@ -321,33 +327,47 @@ void GcodeSuite::G28() {
#else
const bool homeZ = parser.seen_test('Z'),
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;
#define _UNSAFE(A) (homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(A##_AXIS))))
#if ENABLED(HOME_Z_FIRST)
if (doZ) homeaxis(Z_AXIS);
const bool homeZ = TERN0(HAS_Z_AXIS, parser.seen_test('Z')),
LINEAR_AXIS_LIST( // Other axes should be homed before Z safe-homing
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
TERN_(HOME_Z_FIRST, if (doZ) homeaxis(Z_AXIS));
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)
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Raise Z (before homing) by ", z_homing_height);
do_z_clearance(z_homing_height);
TERN_(BLTOUCH, bltouch.init());
}
#if ENABLED(QUICK_HOME)
if (doX && doY) quick_home_xy();
#endif
// Diagonal move first if both are homing
TERN_(QUICK_HOME, if (doX && doY) quick_home_xy());
// Home Y (before X)
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)
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
#if DISABLED(HOME_Z_FIRST)
#if HAS_Z_AXIS && DISABLED(HOME_Z_FIRST)
if (doZ) {
#if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
stepper.set_all_z_lock(false);
@@ -398,6 +418,16 @@ void GcodeSuite::G28() {
}
#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();
#endif
@@ -412,7 +442,7 @@ void GcodeSuite::G28() {
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
active_extruder = 1;
@@ -431,7 +461,7 @@ void GcodeSuite::G28() {
dual_x_carriage_mode = IDEX_saved_mode;
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
@@ -441,12 +471,10 @@ void GcodeSuite::G28() {
// Clear endstop state for polled stallGuard endstops
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
do_blocking_move_to_z(delta_clip_start_height);
#endif
// 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));
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();
@@ -469,7 +497,16 @@ void GcodeSuite::G28() {
#if HAS_CURRENT_HOME(Y2)
stepperY2.rms_current(tmc_save_current_Y2);
#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();
@@ -487,11 +524,13 @@ void GcodeSuite::G28() {
// Set L6470 absolute position registers to counts
// constexpr *might* move this to PROGMEM.
// 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] = {
X_AXIS, Y_AXIS, Z_AXIS,
X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS,
E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS
LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS),
X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS, Z_AXIS
REPEAT(E_STEPPERS, _EN_ITEM)
};
#undef _EN_ITEM
for (uint8_t j = 1; j <= L64XX::chain[0]; j++) {
const uint8_t cv = L64XX::chain[j];
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 };
delta_t.reset();
LOOP_XYZ(axis) {
LOOP_LINEAR_AXES(axis) {
delta_t[axis] = diff;
calc_kinematics_diff_probe_points(z_pt, delta_e, delta_r, delta_t);
delta_t[axis] = 0;
@@ -525,7 +525,7 @@ void GcodeSuite::G33() {
case 1:
test_precision = 0.0f; // forced end
LOOP_XYZ(axis) e_delta[axis] = +Z4(CEN);
LOOP_LINEAR_AXES(axis) e_delta[axis] = +Z4(CEN);
break;
case 2:
@@ -573,14 +573,14 @@ void GcodeSuite::G33() {
// Normalize angles to least-squares
if (_angle_results) {
float a_sum = 0.0f;
LOOP_XYZ(axis) a_sum += delta_tower_angle_trim[axis];
LOOP_XYZ(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f;
LOOP_LINEAR_AXES(axis) a_sum += delta_tower_angle_trim[axis];
LOOP_LINEAR_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f;
}
// 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);
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();
NOMORE(zero_std_dev_min, zero_std_dev);

View File

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

View File

@@ -48,6 +48,13 @@
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
#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
*
@@ -82,9 +89,9 @@ void GcodeSuite::G34() {
switch (parser.intval('Z')) {
case 1: stepper.set_z1_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;
#if NUM_Z_STEPPER_DRIVERS >= 4
#if QUAD_Z
case 4: stepper.set_z4_lock(state); break;
#endif
#endif
@@ -99,13 +106,6 @@ void GcodeSuite::G34() {
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
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);
if (!WITHIN(z_auto_align_iterations, 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];
return HYPOT2(diff.x, diff.y);
};
float z_probe = Z_BASIC_CLEARANCE + (G34_MAX_GRADE) * 0.01f * SQRT(
#if NUM_Z_STEPPER_DRIVERS == 3
_MAX(magnitude2(0, 1), magnitude2(1, 2), magnitude2(2, 0))
#elif NUM_Z_STEPPER_DRIVERS == 4
_MAX(magnitude2(0, 1), magnitude2(1, 2), magnitude2(2, 3),
magnitude2(3, 0), magnitude2(0, 2), magnitude2(1, 3))
#else
magnitude2(0, 1)
float z_probe = Z_BASIC_CLEARANCE + (G34_MAX_GRADE) * 0.01f * SQRT(_MAX(0, magnitude2(0, 1)
#if TRIPLE_Z
, magnitude2(2, 1), magnitude2(2, 0)
#if QUAD_Z
, magnitude2(3, 2), magnitude2(3, 1), magnitude2(3, 0)
#endif
#endif
);
));
// 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
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.
#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
float last_z_align_level_indicator = 10000.0f;
#endif
@@ -280,39 +278,52 @@ void GcodeSuite::G34() {
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
SERIAL_ECHOLNPAIR("\n"
"DIFFERENCE Z1-Z2=", ABS(z_measured[0] - z_measured[1])
#if NUM_Z_STEPPER_DRIVERS == 3
, " Z2-Z3=", ABS(z_measured[1] - z_measured[2])
"Z2-Z1=", ABS(z_measured[1] - z_measured[0])
#if TRIPLE_Z
, " Z3-Z2=", ABS(z_measured[2] - z_measured[1])
, " 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
);
#if HAS_STATUS_MESSAGE
char fstr1[10];
#if NUM_Z_STEPPER_DRIVERS == 2
char msg[6 + (6 + 5) * 1 + 1];
#else
char msg[6 + (6 + 5) * 3 + 1], fstr2[10], fstr3[10];
#endif
sprintf_P(msg,
PSTR("Diffs Z1-Z2=%s"
#if NUM_Z_STEPPER_DRIVERS == 3
" Z2-Z3=%s"
" Z3-Z1=%s"
char msg[6 + (6 + 5) * NUM_Z_STEPPER_DRIVERS + 1]
#if TRIPLE_Z
, fstr2[10], fstr3[10]
#if QUAD_Z
, fstr4[10], fstr5[10], fstr6[10]
#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
;
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);
#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) {
SERIAL_ECHOLNPGM("Decreasing Accuracy Detected.");
LCD_MESSAGEPGM(MSG_DECREASING_ACCURACY);
@@ -437,7 +448,7 @@ void GcodeSuite::G34() {
#endif
}while(0);
#endif
#endif // 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)
#define HAS_X_CENTER 1
#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
#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_float_t dimensions CALIBRATION_OBJECT_DIMENSIONS;
@@ -105,7 +117,7 @@ struct measurements_t {
#endif
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;
for (float travel = 0; travel < limit; travel += step) {
destination[axis] += dir * step;
do_blocking_move_to(destination, mms);
do_blocking_move_to((xyz_pos_t)destination, mms);
planner.synchronize();
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) {
const bool fast = uncertainty == CALIBRATION_MEASUREMENT_UNKNOWN;
// Save position
destination = current_position;
const float start_pos = destination[axis];
// Save the current position of the specified axis
const float start_pos = current_position[axis];
// Take a measurement. Only the specified axis will be affected.
const float measured_pos = measuring_movement(axis, dir, stop_state, fast);
// Measure backlash
if (backlash_ptr && !fast) {
const float release_pos = measuring_movement(axis, -dir, !stop_state, fast);
*backlash_ptr = ABS(release_pos - measured_pos);
}
// Return to starting position
// Move back to the starting position
destination = current_position;
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;
}
@@ -226,7 +242,15 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t
park_above_object(m, uncertainty);
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: {
const float measurement = measure(Z_AXIS, -1, true, &m.backlash[TOP], uncertainty);
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;
}
#endif
#if AXIS_CAN_CALIBRATE(X)
case LEFT: axis = X_AXIS; break;
case RIGHT: axis = X_AXIS; dir = -1; break;
#if LINEAR_AXES >= 4 && AXIS_CAN_CALIBRATE(I)
case IMINIMUM: dir = -1;
case IMAXIMUM: axis = I_AXIS; break;
#endif
#if AXIS_CAN_CALIBRATE(Y)
case FRONT: axis = Y_AXIS; break;
case BACK: axis = Y_AXIS; dir = -1; break;
#if LINEAR_AXES >= 5 && AXIS_CAN_CALIBRATE(J)
case JMINIMUM: dir = -1;
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
default: return;
}
@@ -285,14 +313,23 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
probe_side(m, uncertainty, TOP);
#endif
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_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_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_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_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.
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_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_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
// 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
// of the calibration object is the positional error
m.pos_error.x = (0
#if HAS_X_CENTER
+ true_center.x - m.obj_center.x
#endif
LINEAR_AXIS_CODE(
m.pos_error.x = TERN0(HAS_X_CENTER, true_center.x - m.obj_center.x),
m.pos_error.y = TERN0(HAS_Y_CENTER, true_center.y - m.obj_center.y),
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)
inline void report_measured_faces(const measurements_t &m) {
SERIAL_ECHOLNPGM("Sides:");
#if AXIS_CAN_CALIBRATE(Z)
#if HAS_Z_AXIS && AXIS_CAN_CALIBRATE(Z)
SERIAL_ECHOLNPAIR(" Top: ", m.obj_side[TOP]);
#endif
#if ENABLED(CALIBRATION_MEASURE_LEFT)
@@ -328,11 +362,37 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
#if ENABLED(CALIBRATION_MEASURE_RIGHT)
SERIAL_ECHOLNPAIR(" Right: ", m.obj_side[RIGHT]);
#endif
#if ENABLED(CALIBRATION_MEASURE_FRONT)
SERIAL_ECHOLNPAIR(" Front: ", m.obj_side[FRONT]);
#if HAS_Y_AXIS
#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
#if ENABLED(CALIBRATION_MEASURE_BACK)
SERIAL_ECHOLNPAIR(" Back: ", m.obj_side[BACK]);
#if LINEAR_AXES >= 4
#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
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);
#endif
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();
}
@@ -359,7 +428,7 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
SERIAL_ECHOLNPAIR(" Right: ", m.backlash[RIGHT]);
#endif
#endif
#if AXIS_CAN_CALIBRATE(Y)
#if HAS_Y_AXIS && AXIS_CAN_CALIBRATE(Y)
#if ENABLED(CALIBRATION_MEASURE_FRONT)
SERIAL_ECHOLNPAIR(" Front: ", m.backlash[FRONT]);
#endif
@@ -367,9 +436,33 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
SERIAL_ECHOLNPAIR(" Back: ", m.backlash[BACK]);
#endif
#endif
#if AXIS_CAN_CALIBRATE(Z)
#if HAS_Z_AXIS && AXIS_CAN_CALIBRATE(Z)
SERIAL_ECHOLNPAIR(" Top: ", m.backlash[TOP]);
#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();
}
@@ -377,29 +470,37 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
SERIAL_CHAR('T');
SERIAL_ECHO(active_extruder);
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);
#endif
#if HAS_Y_CENTER
#if HAS_Y_CENTER && AXIS_CAN_CALIBRATE(Y)
SERIAL_ECHOLNPAIR_P(SP_Y_STR, m.pos_error.y);
#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();
}
inline void report_measured_nozzle_dimensions(const measurements_t &m) {
SERIAL_ECHOLNPGM("Nozzle Tip Outer Dimensions:");
#if HAS_X_CENTER || HAS_Y_CENTER
#if HAS_X_CENTER
SERIAL_ECHOLNPAIR_P(SP_X_STR, m.nozzle_outer_dimension.x);
#endif
#if HAS_Y_CENTER
SERIAL_ECHOLNPAIR_P(SP_Y_STR, m.nozzle_outer_dimension.y);
#endif
#else
UNUSED(m);
#if HAS_X_CENTER
SERIAL_ECHOLNPAIR_P(SP_X_STR, m.nozzle_outer_dimension.x);
#endif
#if HAS_Y_CENTER
SERIAL_ECHOLNPAIR_P(SP_Y_STR, m.nozzle_outer_dimension.y);
#endif
SERIAL_EOL();
UNUSED(m);
}
#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];
#endif
if (AXIS_CAN_CALIBRATE(Z)) backlash.distance_mm.z = m.backlash[TOP];
#endif
TERN_(HAS_Z_AXIS, if (AXIS_CAN_CALIBRATE(Z)) backlash.distance_mm.z = m.backlash[TOP]);
#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)
@@ -459,7 +585,10 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) {
// New scope for TEMPORARY_BACKLASH_CORRECTION
TEMPORARY_BACKLASH_CORRECTION(all_on);
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();
}
@@ -487,11 +616,7 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const
TEMPORARY_BACKLASH_CORRECTION(all_on);
TEMPORARY_BACKLASH_SMOOTHING(0.0f);
#if HAS_MULTI_HOTEND
set_nozzle(m, extruder);
#else
UNUSED(extruder);
#endif
TERN(HAS_MULTI_HOTEND, set_nozzle(m, extruder), UNUSED(extruder));
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 (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();
}
@@ -589,12 +718,12 @@ void GcodeSuite::G425() {
SET_SOFT_ENDSTOP_LOOSE(true);
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);
else if (parser.seen('T'))
calibrate_toolhead(m, uncertainty, parser.has_value() ? parser.value_int() : active_extruder);
else if (parser.seen_test('T'))
calibrate_toolhead(m, uncertainty, parser.intval('T', active_extruder));
#if ENABLED(CALIBRATION_REPORTING)
else if (parser.seen('V')) {
probe_sides(m, uncertainty);

View File

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

View File

@@ -39,11 +39,11 @@
*/
void GcodeSuite::M666() {
DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING));
LOOP_XYZ(i) {
if (parser.seen(XYZ_CHAR(i))) {
LOOP_LINEAR_AXES(i) {
if (parser.seen(AXIS_CHAR(i))) {
const float v = parser.value_linear_units();
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
#if ENABLED(Z_MULTI_ENDSTOPS)
if (parser.seenval('Z')) {
#if NUM_Z_STEPPER_DRIVERS >= 3
const float z_adj = parser.value_linear_units();
const int ind = parser.intval('S');
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
const float z_adj = parser.value_linear_units();
#if NUM_Z_STEPPER_DRIVERS == 2
endstops.z2_endstop_adj = z_adj;
#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
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): ");
#if ENABLED(X_DUAL_ENDSTOPS)
SERIAL_ECHOPAIR(" X2:", endstops.x2_endstop_adj);
echo_adj(PSTR(" X2:"), endstops.x2_endstop_adj);
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
SERIAL_ECHOPAIR(" Y2:", endstops.y2_endstop_adj);
echo_adj(PSTR(" Y2:"), endstops.y2_endstop_adj);
#endif
#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)
#endif
SERIAL_EOL();

View File

@@ -86,7 +86,7 @@ void GcodeSuite::M852() {
// When skew is changed the current position changes
if (setval) {
set_current_from_steppers_for_axis(ALL_AXES);
set_current_from_steppers_for_axis(ALL_AXES_ENUM);
sync_plan_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;
#endif
LOOP_XYZE(i) {
if (parser.seen(axis_codes[i])) {
const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i);
LOOP_LOGICAL_AXES(i) {
if (parser.seenval(axis_codes[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));
}
}
@@ -104,9 +104,9 @@ void GcodeSuite::M203() {
const int8_t target_extruder = get_target_extruder_from_command();
if (target_extruder < 0) return;
LOOP_XYZE(i)
if (parser.seen(axis_codes[i])) {
const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i);
LOOP_LOGICAL_AXES(i)
if (parser.seenval(axis_codes[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));
}
}
@@ -147,24 +147,17 @@ void GcodeSuite::M204() {
* J = Junction Deviation (mm) (If not using CLASSIC_JERK)
*/
void GcodeSuite::M205() {
#if HAS_JUNCTION_DEVIATION
#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;
if (!parser.seen("BST" TERN_(HAS_JUNCTION_DEVIATION, "J") TERN_(HAS_CLASSIC_JERK, "XYZE"))) return;
//planner.synchronize();
if (parser.seen('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.seen('T')) planner.settings.min_travel_feedrate_mm_s = parser.value_linear_units();
if (parser.seenval('B')) planner.settings.min_segment_time_us = parser.value_ulong();
if (parser.seenval('S')) planner.settings.min_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 (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();
if (WITHIN(junc_dev, 0.01f, 0.3f)) {
planner.junction_deviation_mm = junc_dev;
@@ -175,17 +168,19 @@ void GcodeSuite::M205() {
}
#endif
#if HAS_CLASSIC_JERK
if (parser.seen('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units());
if (parser.seen('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units());
if (parser.seen('Z')) {
planner.set_max_jerk(Z_AXIS, parser.value_linear_units());
#if HAS_MESH && DISABLED(LIMITED_JERK_EDITING)
if (planner.max_jerk.z <= 0.1f)
SERIAL_ECHOLNPGM("WARNING! Low Z Jerk may lead to unwanted pauses.");
#endif
}
#if HAS_CLASSIC_E_JERK
if (parser.seen('E')) planner.set_max_jerk(E_AXIS, parser.value_linear_units());
bool seenZ = false;
LOGICAL_AXIS_CODE(
if (parser.seenval('E')) planner.set_max_jerk(E_AXIS, parser.value_linear_units()),
if (parser.seenval('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units()),
if (parser.seenval('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units()),
if ((seenZ = parser.seenval('Z'))) planner.set_max_jerk(Z_AXIS, parser.value_linear_units()),
if (parser.seenval(AXIS4_NAME)) planner.set_max_jerk(I_AXIS, parser.value_linear_units()),
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_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 // HAS_CLASSIC_JERK
}

View File

@@ -23,7 +23,7 @@
#include "../gcode.h"
#include "../../module/planner.h"
#if EXTRUDERS
#if HAS_EXTRUDERS
/**
* 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) {
if (echo) SERIAL_ECHO_START(); else SERIAL_CHAR(' ');
SERIAL_ECHOPAIR_P(PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]),
SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]),
SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS]));
#if DISABLED(DISTINCT_E_FACTORS)
SERIAL_ECHOPAIR_P(LIST_N(DOUBLE(LINEAR_AXES),
PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]),
SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]),
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]));
#endif
SERIAL_EOL();
@@ -42,7 +47,7 @@ void report_M92(const bool echo=true, const int8_t e=-1) {
}
#endif
UNUSED_E(e);
UNUSED(e);
}
/**
@@ -64,28 +69,28 @@ void GcodeSuite::M92() {
if (target_extruder < 0) return;
// No arguments? Show M92 report.
if (!parser.seen("XYZE"
#if ENABLED(MAGIC_NUMBERS_GCODE)
"HL"
#endif
if (!parser.seen(
LOGICAL_AXIS_GANG("E", "X", "Y", "Z", AXIS4_STR, AXIS5_STR, AXIS6_STR)
TERN_(MAGIC_NUMBERS_GCODE, "HL")
)) return report_M92(true, target_extruder);
LOOP_XYZE(i) {
LOOP_LOGICAL_AXES(i) {
if (parser.seenval(axis_codes[i])) {
if (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 {
if (TERN1(HAS_EXTRUDERS, i != E_AXIS))
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
*/
void GcodeSuite::M17() {
if (parser.seen("XYZE")) {
if (parser.seen('X')) ENABLE_AXIS_X();
if (parser.seen('Y')) ENABLE_AXIS_Y();
if (parser.seen('Z')) ENABLE_AXIS_Z();
if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen('E'))) enable_e_steppers();
if (parser.seen(LOGICAL_AXIS_GANG("E", "X", "Y", "Z", AXIS4_STR, AXIS5_STR, AXIS6_STR))) {
LOGICAL_AXIS_CODE(
if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen_test('E'))) enable_e_steppers(),
if (parser.seen_test('X')) ENABLE_AXIS_X(),
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 {
LCD_MESSAGEPGM(MSG_NO_MOVE);
@@ -54,12 +59,17 @@ void GcodeSuite::M18_M84() {
stepper_inactive_time = parser.value_millis_from_seconds();
}
else {
if (parser.seen("XYZE")) {
if (parser.seen(LOGICAL_AXIS_GANG("E", "X", "Y", "Z", AXIS4_STR, AXIS5_STR, AXIS6_STR))) {
planner.synchronize();
if (parser.seen('X')) DISABLE_AXIS_X();
if (parser.seen('Y')) DISABLE_AXIS_Y();
if (parser.seen('Z')) DISABLE_AXIS_Z();
if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen('E'))) disable_e_steppers();
LOGICAL_AXIS_CODE(
if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen_test('E'))) disable_e_steppers(),
if (parser.seen_test('X')) DISABLE_AXIS_X(),
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
planner.finish_and_disable();

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