update code base to Marlin 2.0.9.2
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -56,55 +56,68 @@
|
||||
#define BOARD_3DRAG 1100 // 3Drag Controller
|
||||
#define BOARD_K8200 1101 // Velleman K8200 Controller (derived from 3Drag Controller)
|
||||
#define BOARD_K8400 1102 // Velleman K8400 Controller (derived from 3Drag Controller)
|
||||
#define BOARD_BAM_DICE 1103 // 2PrintBeta BAM&DICE with STK drivers
|
||||
#define BOARD_BAM_DICE_DUE 1104 // 2PrintBeta BAM&DICE Due with STK drivers
|
||||
#define BOARD_MKS_BASE 1105 // MKS BASE v1.0
|
||||
#define BOARD_MKS_BASE_14 1106 // MKS BASE v1.4 with Allegro A4982 stepper drivers
|
||||
#define BOARD_MKS_BASE_15 1107 // MKS BASE v1.5 with Allegro A4982 stepper drivers
|
||||
#define BOARD_MKS_BASE_16 1108 // MKS BASE v1.6 with Allegro A4982 stepper drivers
|
||||
#define BOARD_MKS_BASE_HEROIC 1109 // MKS BASE 1.0 with Heroic HR4982 stepper drivers
|
||||
#define BOARD_MKS_GEN_13 1110 // MKS GEN v1.3 or 1.4
|
||||
#define BOARD_MKS_GEN_L 1111 // MKS GEN L
|
||||
#define BOARD_KFB_2 1112 // BigTreeTech or BIQU KFB2.0
|
||||
#define BOARD_ZRIB_V20 1113 // zrib V2.0 control board (Chinese knock off RAMPS replica)
|
||||
#define BOARD_FELIX2 1114 // Felix 2.0+ Electronics Board (RAMPS like)
|
||||
#define BOARD_RIGIDBOARD 1115 // Invent-A-Part RigidBoard
|
||||
#define BOARD_RIGIDBOARD_V2 1116 // Invent-A-Part RigidBoard V2
|
||||
#define BOARD_SAINSMART_2IN1 1117 // Sainsmart 2-in-1 board
|
||||
#define BOARD_ULTIMAKER 1118 // Ultimaker
|
||||
#define BOARD_ULTIMAKER_OLD 1119 // Ultimaker (Older electronics. Pre 1.5.4. This is rare)
|
||||
#define BOARD_AZTEEG_X3 1120 // Azteeg X3
|
||||
#define BOARD_AZTEEG_X3_PRO 1121 // Azteeg X3 Pro
|
||||
#define BOARD_ULTIMAIN_2 1122 // Ultimainboard 2.x (Uses TEMP_SENSOR 20)
|
||||
#define BOARD_RUMBA 1123 // Rumba
|
||||
#define BOARD_RUMBA_RAISE3D 1124 // Raise3D N series Rumba derivative
|
||||
#define BOARD_RL200 1125 // Rapide Lite 200 (v1, low-cost RUMBA clone with drv)
|
||||
#define BOARD_FORMBOT_TREX2PLUS 1126 // Formbot T-Rex 2 Plus
|
||||
#define BOARD_FORMBOT_TREX3 1127 // Formbot T-Rex 3
|
||||
#define BOARD_FORMBOT_RAPTOR 1128 // Formbot Raptor
|
||||
#define BOARD_FORMBOT_RAPTOR2 1129 // Formbot Raptor 2
|
||||
#define BOARD_BQ_ZUM_MEGA_3D 1130 // bq ZUM Mega 3D
|
||||
#define BOARD_MAKEBOARD_MINI 1131 // MakeBoard Mini v2.1.2 is a control board sold by MicroMake
|
||||
#define BOARD_TRIGORILLA_13 1132 // TriGorilla Anycubic version 1.3-based on RAMPS EFB
|
||||
#define BOARD_TRIGORILLA_14 1133 // ... Ver 1.4
|
||||
#define BOARD_TRIGORILLA_14_11 1134 // ... Rev 1.1 (new servo pin order)
|
||||
#define BOARD_RAMPS_ENDER_4 1135 // Creality: Ender-4, CR-8
|
||||
#define BOARD_RAMPS_CREALITY 1136 // Creality: CR10S, CR20, CR-X
|
||||
#define BOARD_RAMPS_DAGOMA 1137 // Dagoma F5
|
||||
#define BOARD_FYSETC_F6_13 1138 // FYSETC F6 1.3
|
||||
#define BOARD_FYSETC_F6_14 1139 // FYSETC F6 1.4
|
||||
#define BOARD_DUPLICATOR_I3_PLUS 1140 // Wanhao Duplicator i3 Plus
|
||||
#define BOARD_VORON 1141 // VORON Design
|
||||
#define BOARD_TRONXY_V3_1_0 1142 // Tronxy TRONXY-V3-1.0
|
||||
#define BOARD_Z_BOLT_X_SERIES 1143 // Z-Bolt X Series
|
||||
#define BOARD_TT_OSCAR 1144 // TT OSCAR
|
||||
#define BOARD_OVERLORD 1145 // Overlord/Overlord Pro
|
||||
#define BOARD_HJC2560C_REV1 1146 // ADIMLab Gantry v1
|
||||
#define BOARD_HJC2560C_REV2 1147 // ADIMLab Gantry v2
|
||||
#define BOARD_TANGO 1148 // BIQU Tango V1
|
||||
#define BOARD_MKS_GEN_L_V2 1149 // MKS GEN L V2
|
||||
#define BOARD_COPYMASTER_3D 1150 // Copymaster 3D
|
||||
#define BOARD_TRIGORILLA_CHIRON 1151 // TriGorilla Anycubic version 1.4 based on RAMPS EFB for Chiron
|
||||
#define BOARD_K8600 1103 // Velleman K8600 Controller (Vertex Nano)
|
||||
#define BOARD_K8800 1104 // Velleman K8800 Controller (Vertex Delta)
|
||||
#define BOARD_BAM_DICE 1105 // 2PrintBeta BAM&DICE with STK drivers
|
||||
#define BOARD_BAM_DICE_DUE 1106 // 2PrintBeta BAM&DICE Due with STK drivers
|
||||
#define BOARD_MKS_BASE 1107 // MKS BASE v1.0
|
||||
#define BOARD_MKS_BASE_14 1108 // MKS BASE v1.4 with Allegro A4982 stepper drivers
|
||||
#define BOARD_MKS_BASE_15 1109 // MKS BASE v1.5 with Allegro A4982 stepper drivers
|
||||
#define BOARD_MKS_BASE_16 1110 // MKS BASE v1.6 with Allegro A4982 stepper drivers
|
||||
#define BOARD_MKS_BASE_HEROIC 1111 // MKS BASE 1.0 with Heroic HR4982 stepper drivers
|
||||
#define BOARD_MKS_GEN_13 1112 // MKS GEN v1.3 or 1.4
|
||||
#define BOARD_MKS_GEN_L 1113 // MKS GEN L
|
||||
#define BOARD_KFB_2 1114 // BigTreeTech or BIQU KFB2.0
|
||||
#define BOARD_ZRIB_V20 1115 // zrib V2.0 (Chinese RAMPS replica)
|
||||
#define BOARD_ZRIB_V52 1116 // zrib V5.2 (Chinese RAMPS replica)
|
||||
#define BOARD_FELIX2 1117 // Felix 2.0+ Electronics Board (RAMPS like)
|
||||
#define BOARD_RIGIDBOARD 1118 // Invent-A-Part RigidBoard
|
||||
#define BOARD_RIGIDBOARD_V2 1119 // Invent-A-Part RigidBoard V2
|
||||
#define BOARD_SAINSMART_2IN1 1120 // Sainsmart 2-in-1 board
|
||||
#define BOARD_ULTIMAKER 1121 // Ultimaker
|
||||
#define BOARD_ULTIMAKER_OLD 1122 // Ultimaker (Older electronics. Pre 1.5.4. This is rare)
|
||||
#define BOARD_AZTEEG_X3 1123 // Azteeg X3
|
||||
#define BOARD_AZTEEG_X3_PRO 1124 // Azteeg X3 Pro
|
||||
#define BOARD_ULTIMAIN_2 1125 // Ultimainboard 2.x (Uses TEMP_SENSOR 20)
|
||||
#define BOARD_RUMBA 1126 // Rumba
|
||||
#define BOARD_RUMBA_RAISE3D 1127 // Raise3D N series Rumba derivative
|
||||
#define BOARD_RL200 1128 // Rapide Lite 200 (v1, low-cost RUMBA clone with drv)
|
||||
#define BOARD_FORMBOT_TREX2PLUS 1129 // Formbot T-Rex 2 Plus
|
||||
#define BOARD_FORMBOT_TREX3 1130 // Formbot T-Rex 3
|
||||
#define BOARD_FORMBOT_RAPTOR 1131 // Formbot Raptor
|
||||
#define BOARD_FORMBOT_RAPTOR2 1132 // Formbot Raptor 2
|
||||
#define BOARD_BQ_ZUM_MEGA_3D 1133 // bq ZUM Mega 3D
|
||||
#define BOARD_MAKEBOARD_MINI 1134 // MakeBoard Mini v2.1.2 by MicroMake
|
||||
#define BOARD_TRIGORILLA_13 1135 // TriGorilla Anycubic version 1.3-based on RAMPS EFB
|
||||
#define BOARD_TRIGORILLA_14 1136 // ... Ver 1.4
|
||||
#define BOARD_TRIGORILLA_14_11 1137 // ... Rev 1.1 (new servo pin order)
|
||||
#define BOARD_RAMPS_ENDER_4 1138 // Creality: Ender-4, CR-8
|
||||
#define BOARD_RAMPS_CREALITY 1139 // Creality: CR10S, CR20, CR-X
|
||||
#define BOARD_DAGOMA_F5 1140 // Dagoma F5
|
||||
#define BOARD_FYSETC_F6_13 1141 // FYSETC F6 1.3
|
||||
#define BOARD_FYSETC_F6_14 1142 // FYSETC F6 1.4
|
||||
#define BOARD_DUPLICATOR_I3_PLUS 1143 // Wanhao Duplicator i3 Plus
|
||||
#define BOARD_VORON 1144 // VORON Design
|
||||
#define BOARD_TRONXY_V3_1_0 1145 // Tronxy TRONXY-V3-1.0
|
||||
#define BOARD_Z_BOLT_X_SERIES 1146 // Z-Bolt X Series
|
||||
#define BOARD_TT_OSCAR 1147 // TT OSCAR
|
||||
#define BOARD_OVERLORD 1148 // Overlord/Overlord Pro
|
||||
#define BOARD_HJC2560C_REV1 1149 // ADIMLab Gantry v1
|
||||
#define BOARD_HJC2560C_REV2 1150 // ADIMLab Gantry v2
|
||||
#define BOARD_TANGO 1151 // BIQU Tango V1
|
||||
#define BOARD_MKS_GEN_L_V2 1152 // MKS GEN L V2
|
||||
#define BOARD_MKS_GEN_L_V21 1153 // MKS GEN L V2.1
|
||||
#define BOARD_COPYMASTER_3D 1154 // Copymaster 3D
|
||||
#define BOARD_ORTUR_4 1155 // Ortur 4
|
||||
#define BOARD_TENLOG_D3_HERO 1156 // Tenlog D3 Hero IDEX printer
|
||||
#define BOARD_RAMPS_S_12_EEFB 1157 // Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Fan, Bed)
|
||||
#define BOARD_RAMPS_S_12_EEEB 1158 // Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Hotend2, Bed)
|
||||
#define BOARD_RAMPS_S_12_EFFB 1159 // Ramps S 1.2 by Sakul.cz (Power outputs: Hotend, Fan0, Fan1, Bed)
|
||||
#define BOARD_LONGER3D_LK1_PRO 1160 // Longer LK1 PRO / Alfawise U20 Pro (PRO version)
|
||||
#define BOARD_LONGER3D_LKx_PRO 1161 // Longer LKx PRO / Alfawise Uxx Pro (PRO version)
|
||||
// PATCH START: Knutwurst
|
||||
#define BOARD_TRIGORILLA_CHIRON 1162 // TriGorilla Anycubic version 1.4 based on RAMPS EFB for Chiron
|
||||
// PATCH END: Knutwurst
|
||||
|
||||
//
|
||||
// RAMBo and derivatives
|
||||
@@ -135,17 +148,22 @@
|
||||
#define BOARD_ELEFU_3 1311 // Elefu Ra Board (v3)
|
||||
#define BOARD_LEAPFROG 1312 // Leapfrog
|
||||
#define BOARD_MEGACONTROLLER 1313 // Mega controller
|
||||
#define BOARD_GT2560_REV_A 1314 // Geeetech GT2560 Rev. A
|
||||
#define BOARD_GT2560_REV_A_PLUS 1315 // Geeetech GT2560 Rev. A+ (with auto level probe)
|
||||
#define BOARD_GT2560_V3 1316 // Geeetech GT2560 Rev B for A10(M/D)
|
||||
#define BOARD_GT2560_V3_MC2 1317 // Geeetech GT2560 Rev B for Mecreator2
|
||||
#define BOARD_GT2560_V3_A20 1318 // Geeetech GT2560 Rev B for A20(M/D)
|
||||
#define BOARD_EINSTART_S 1319 // Einstart retrofit
|
||||
#define BOARD_WANHAO_ONEPLUS 1320 // Wanhao 0ne+ i3 Mini
|
||||
#define BOARD_LEAPFROG_XEED2015 1321 // Leapfrog Xeed 2015
|
||||
#define BOARD_PICA_REVB 1322 // PICA Shield (original version)
|
||||
#define BOARD_PICA 1323 // PICA Shield (rev C or later)
|
||||
#define BOARD_INTAMSYS40 1324 // Intamsys 4.0 (Funmat HT)
|
||||
#define BOARD_GT2560_REV_A 1314 // Geeetech GT2560 Rev A
|
||||
#define BOARD_GT2560_REV_A_PLUS 1315 // Geeetech GT2560 Rev A+ (with auto level probe)
|
||||
#define BOARD_GT2560_REV_B 1316 // Geeetech GT2560 Rev B
|
||||
#define BOARD_GT2560_V3 1317 // Geeetech GT2560 Rev B for A10(M/T/D)
|
||||
#define BOARD_GT2560_V4 1318 // Geeetech GT2560 Rev B for A10(M/T/D)
|
||||
#define BOARD_GT2560_V3_MC2 1319 // Geeetech GT2560 Rev B for Mecreator2
|
||||
#define BOARD_GT2560_V3_A20 1320 // Geeetech GT2560 Rev B for A20(M/T/D)
|
||||
#define BOARD_EINSTART_S 1321 // Einstart retrofit
|
||||
#define BOARD_WANHAO_ONEPLUS 1322 // Wanhao 0ne+ i3 Mini
|
||||
#define BOARD_LEAPFROG_XEED2015 1323 // Leapfrog Xeed 2015
|
||||
#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)
|
||||
#define BOARD_GT2560_V4_A20 1328 // Geeetech GT2560 Rev B for A20(M/T/D)
|
||||
#define BOARD_PROTONEER_CNC_SHIELD_V3 1329 // Mega controller & Protoneer CNC Shield V3.00
|
||||
|
||||
//
|
||||
// ATmega1281, ATmega2561
|
||||
@@ -161,13 +179,15 @@
|
||||
#define BOARD_SANGUINOLOLU_11 1500 // Sanguinololu < 1.2
|
||||
#define BOARD_SANGUINOLOLU_12 1501 // Sanguinololu 1.2 and above
|
||||
#define BOARD_MELZI 1502 // Melzi
|
||||
#define BOARD_MELZI_MAKR3D 1503 // Melzi with ATmega1284 (MaKr3d version)
|
||||
#define BOARD_MELZI_CREALITY 1504 // Melzi Creality3D board (for CR-10 etc)
|
||||
#define BOARD_MELZI_MALYAN 1505 // Melzi Malyan M150 board
|
||||
#define BOARD_MELZI_TRONXY 1506 // Tronxy X5S
|
||||
#define BOARD_STB_11 1507 // STB V1.1
|
||||
#define BOARD_AZTEEG_X1 1508 // Azteeg X1
|
||||
#define BOARD_ANET_10 1509 // Anet 1.0 (Melzi clone)
|
||||
#define BOARD_MELZI_V2 1503 // Melzi V2
|
||||
#define BOARD_MELZI_MAKR3D 1504 // Melzi with ATmega1284 (MaKr3d version)
|
||||
#define BOARD_MELZI_CREALITY 1505 // Melzi Creality3D (for CR-10 etc)
|
||||
#define BOARD_MELZI_MALYAN 1506 // Melzi Malyan M150
|
||||
#define BOARD_MELZI_TRONXY 1507 // Tronxy X5S
|
||||
#define BOARD_STB_11 1508 // STB V1.1
|
||||
#define BOARD_AZTEEG_X1 1509 // Azteeg X1
|
||||
#define BOARD_ANET_10 1510 // Anet 1.0 (Melzi clone)
|
||||
#define BOARD_ZMIB_V2 1511 // ZoneStar ZMIB V2
|
||||
|
||||
//
|
||||
// Other ATmega644P, ATmega644, ATmega1284P
|
||||
@@ -177,12 +197,12 @@
|
||||
#define BOARD_GEN3_PLUS 1601 // Gen3+
|
||||
#define BOARD_GEN6 1602 // Gen6
|
||||
#define BOARD_GEN6_DELUXE 1603 // Gen6 deluxe
|
||||
#define BOARD_GEN7_CUSTOM 1604 // Gen7 custom (Alfons3 Version) "https://github.com/Alfons3/Generation_7_Electronics"
|
||||
#define BOARD_GEN7_CUSTOM 1604 // Gen7 custom (Alfons3 Version) https://github.com/Alfons3/Generation_7_Electronics
|
||||
#define BOARD_GEN7_12 1605 // Gen7 v1.1, v1.2
|
||||
#define BOARD_GEN7_13 1606 // Gen7 v1.3
|
||||
#define BOARD_GEN7_14 1607 // Gen7 v1.4
|
||||
#define BOARD_OMCA_A 1608 // Alpha OMCA board
|
||||
#define BOARD_OMCA 1609 // Final OMCA board
|
||||
#define BOARD_OMCA_A 1608 // Alpha OMCA
|
||||
#define BOARD_OMCA 1609 // Final OMCA
|
||||
#define BOARD_SETHI 1610 // Sethi 3D_1
|
||||
|
||||
//
|
||||
@@ -213,7 +233,7 @@
|
||||
#define BOARD_SELENA_COMPACT 2008 // Selena Compact (Power outputs: Hotend0, Hotend1, Bed0, Bed1, Fan0, Fan1)
|
||||
#define BOARD_BIQU_B300_V1_0 2009 // BIQU B300_V1.0 (Power outputs: Hotend0, Fan, Bed, SPI Driver)
|
||||
#define BOARD_MKS_SGEN_L 2010 // MKS-SGen-L (Power outputs: Hotend0, Hotend1, Bed, Fan)
|
||||
#define BOARD_GMARSH_X6_REV1 2011 // GMARSH X6 board, revision 1 prototype
|
||||
#define BOARD_GMARSH_X6_REV1 2011 // GMARSH X6, revision 1 prototype
|
||||
#define BOARD_BTT_SKR_V1_1 2012 // BigTreeTech SKR v1.1 (Power outputs: Hotend0, Hotend1, Fan, Bed)
|
||||
#define BOARD_BTT_SKR_V1_3 2013 // BigTreeTech SKR v1.3 (Power outputs: Hotend0, Hotend1, Fan, Bed)
|
||||
#define BOARD_BTT_SKR_V1_4 2014 // BigTreeTech SKR v1.4 (Power outputs: Hotend0, Hotend1, Fan, Bed)
|
||||
@@ -231,6 +251,9 @@
|
||||
#define BOARD_SMOOTHIEBOARD 2506 // Smoothieboard
|
||||
#define BOARD_TH3D_EZBOARD 2507 // TH3D EZBoard v1.0
|
||||
#define BOARD_BTT_SKR_V1_4_TURBO 2508 // BigTreeTech SKR v1.4 TURBO (Power outputs: Hotend0, Hotend1, Fan, Bed)
|
||||
#define BOARD_MKS_SGEN_L_V2 2509 // MKS SGEN_L V2 (Power outputs: Hotend0, Hotend1, Bed, Fan)
|
||||
#define BOARD_BTT_SKR_E3_TURBO 2510 // BigTreeTech SKR E3 Turbo (Power outputs: Hotend0, Hotend1, Bed, Fan0, Fan1)
|
||||
#define BOARD_FLY_CDY 2511 // FLYmaker FLY CDY (Power outputs: Hotend0, Hotend1, Hotend2, Bed, Fan0, Fan1, Fan2)
|
||||
|
||||
//
|
||||
// SAM3X8E ARM Cortex M3
|
||||
@@ -263,6 +286,7 @@
|
||||
#define BOARD_ARCHIM2 3024 // UltiMachine Archim2 (with TMC2130 drivers)
|
||||
#define BOARD_ALLIGATOR 3025 // Alligator Board R2
|
||||
#define BOARD_CNCONTROLS_15D 3026 // Cartesio CN Controls V15 on DUE
|
||||
#define BOARD_KRATOS32 3027 // K.3D Kratos32 (Arduino Due Shield)
|
||||
|
||||
//
|
||||
// SAM3X8C ARM Cortex M3
|
||||
@@ -275,30 +299,64 @@
|
||||
// STM32 ARM Cortex-M3
|
||||
//
|
||||
|
||||
#define BOARD_STM32F103RE 4000 // STM32F103RE Libmaple-based STM32F1 controller
|
||||
#define BOARD_MALYAN_M200 4001 // STM32C8T6 Libmaple-based STM32F1 controller
|
||||
#define BOARD_STM3R_MINI 4002 // STM32F103RE Libmaple-based STM32F1 controller
|
||||
#define BOARD_GTM32_PRO_VB 4003 // STM32F103VET6 controller
|
||||
#define BOARD_MORPHEUS 4004 // STM32F103C8 / STM32F103CB Libmaple-based STM32F1 controller
|
||||
#define BOARD_CHITU3D 4005 // Chitu3D (STM32F103RET6)
|
||||
#define BOARD_MKS_ROBIN 4006 // MKS Robin (STM32F103ZET6)
|
||||
#define BOARD_MKS_ROBIN_MINI 4007 // MKS Robin Mini (STM32F103VET6)
|
||||
#define BOARD_MKS_ROBIN_NANO 4008 // MKS Robin Nano (STM32F103VET6)
|
||||
#define BOARD_MKS_ROBIN_LITE 4009 // MKS Robin Lite/Lite2 (STM32F103RCT6)
|
||||
#define BOARD_MKS_ROBIN_LITE3 4010 // MKS Robin Lite3 (STM32F103RCT6)
|
||||
#define BOARD_MKS_ROBIN_PRO 4011 // MKS Robin Pro (STM32F103ZET6)
|
||||
#define BOARD_BTT_SKR_MINI_V1_1 4012 // BigTreeTech SKR Mini v1.1 (STM32F103RC)
|
||||
#define BOARD_BTT_SKR_MINI_E3_V1_0 4013 // BigTreeTech SKR Mini E3 (STM32F103RC)
|
||||
#define BOARD_BTT_SKR_MINI_E3_V1_2 4014 // BigTreeTech SKR Mini E3 V1.2 (STM32F103RC)
|
||||
#define BOARD_BTT_SKR_E3_DIP 4015 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / STM32F103RE)
|
||||
#define BOARD_JGAURORA_A5S_A1 4016 // JGAurora A5S A1 (STM32F103ZET6)
|
||||
#define BOARD_FYSETC_AIO_II 4017 // FYSETC AIO_II
|
||||
#define BOARD_FYSETC_CHEETAH 4018 // FYSETC Cheetah
|
||||
#define BOARD_FYSETC_CHEETAH_V12 4019 // FYSETC Cheetah V1.2
|
||||
#define BOARD_LONGER3D_LK 4020 // Alfawise U20/U20+/U30 (Longer3D LK1/2) / STM32F103VET6
|
||||
#define BOARD_GTM32_MINI 4021 // STM32F103VET6 controller
|
||||
#define BOARD_GTM32_MINI_A30 4022 // STM32F103VET6 controller
|
||||
#define BOARD_GTM32_REV_B 4023 // STM32F103VET6 controller
|
||||
#define BOARD_MALYAN_M200_V2 4000 // STM32F070CB controller
|
||||
#define BOARD_MALYAN_M300 4001 // STM32F070-based delta
|
||||
#define BOARD_STM32F103RE 4002 // STM32F103RE Libmaple-based STM32F1 controller
|
||||
#define BOARD_MALYAN_M200 4003 // STM32C8T6 Libmaple-based STM32F1 controller
|
||||
#define BOARD_STM3R_MINI 4004 // STM32F103RE Libmaple-based STM32F1 controller
|
||||
#define BOARD_GTM32_PRO_VB 4005 // STM32F103VET6 controller
|
||||
#define BOARD_GTM32_MINI 4006 // STM32F103VET6 controller
|
||||
#define BOARD_GTM32_MINI_A30 4007 // STM32F103VET6 controller
|
||||
#define BOARD_GTM32_REV_B 4008 // STM32F103VET6 controller
|
||||
#define BOARD_MORPHEUS 4009 // STM32F103C8 / STM32F103CB Libmaple-based STM32F1 controller
|
||||
#define BOARD_CHITU3D 4010 // Chitu3D (STM32F103RET6)
|
||||
#define BOARD_MKS_ROBIN 4011 // MKS Robin (STM32F103ZET6)
|
||||
#define BOARD_MKS_ROBIN_MINI 4012 // MKS Robin Mini (STM32F103VET6)
|
||||
#define BOARD_MKS_ROBIN_NANO 4013 // MKS Robin Nano (STM32F103VET6)
|
||||
#define BOARD_MKS_ROBIN_NANO_V2 4014 // MKS Robin Nano V2 (STM32F103VET6)
|
||||
#define BOARD_MKS_ROBIN_LITE 4015 // MKS Robin Lite/Lite2 (STM32F103RCT6)
|
||||
#define BOARD_MKS_ROBIN_LITE3 4016 // MKS Robin Lite3 (STM32F103RCT6)
|
||||
#define BOARD_MKS_ROBIN_PRO 4017 // MKS Robin Pro (STM32F103ZET6)
|
||||
#define BOARD_MKS_ROBIN_E3 4018 // MKS Robin E3 (STM32F103RCT6)
|
||||
#define BOARD_MKS_ROBIN_E3_V1_1 4019 // MKS Robin E3 V1.1 (STM32F103RCT6)
|
||||
#define BOARD_MKS_ROBIN_E3D 4020 // MKS Robin E3D (STM32F103RCT6)
|
||||
#define BOARD_MKS_ROBIN_E3D_V1_1 4021 // MKS Robin E3D V1.1 (STM32F103RCT6)
|
||||
#define BOARD_MKS_ROBIN_E3P 4022 // MKS Robin E3p (STM32F103VET6)
|
||||
#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 / 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)
|
||||
#define BOARD_JGAURORA_A5S_A1 4030 // JGAurora A5S A1 (STM32F103ZET6)
|
||||
#define BOARD_FYSETC_AIO_II 4031 // FYSETC AIO_II
|
||||
#define BOARD_FYSETC_CHEETAH 4032 // FYSETC Cheetah
|
||||
#define BOARD_FYSETC_CHEETAH_V12 4033 // FYSETC Cheetah V1.2
|
||||
#define BOARD_LONGER3D_LK 4034 // Alfawise U20/U20+/U30 (Longer3D LK1/2) / STM32F103VET6
|
||||
#define BOARD_CCROBOT_MEEB_3DP 4035 // ccrobot-online.com MEEB_3DP (STM32F103RC)
|
||||
#define BOARD_CHITU3D_V5 4036 // Chitu3D TronXY X5SA V5 Board
|
||||
#define BOARD_CHITU3D_V6 4037 // Chitu3D TronXY X5SA V6 Board
|
||||
#define BOARD_CHITU3D_V9 4038 // Chitu3D TronXY X5SA V9 Board
|
||||
#define BOARD_CREALITY_V4 4039 // Creality v4.x (STM32F103RE)
|
||||
#define BOARD_CREALITY_V427 4040 // Creality v4.2.7 (STM32F103RE)
|
||||
#define BOARD_CREALITY_V4210 4041 // Creality v4.2.10 (STM32F103RE) as found in the CR-30
|
||||
#define BOARD_CREALITY_V431 4042 // Creality v4.3.1 (STM32F103RE)
|
||||
#define BOARD_CREALITY_V431_A 4043 // Creality v4.3.1a (STM32F103RE)
|
||||
#define BOARD_CREALITY_V431_B 4044 // Creality v4.3.1b (STM32F103RE)
|
||||
#define BOARD_CREALITY_V431_C 4045 // Creality v4.3.1c (STM32F103RE)
|
||||
#define BOARD_CREALITY_V431_D 4046 // Creality v4.3.1d (STM32F103RE)
|
||||
#define BOARD_CREALITY_V452 4047 // Creality v4.5.2 (STM32F103RE)
|
||||
#define BOARD_CREALITY_V453 4048 // Creality v4.5.3 (STM32F103RE)
|
||||
#define BOARD_TRIGORILLA_PRO 4049 // Trigorilla Pro (STM32F103ZET6)
|
||||
#define BOARD_FLY_MINI 4050 // FLYmaker FLY MINI (STM32F103RCT6)
|
||||
#define BOARD_FLSUN_HISPEED 4051 // FLSUN HiSpeedV1 (STM32F103VET6)
|
||||
#define BOARD_BEAST 4052 // STM32F103RET6 Libmaple-based controller
|
||||
#define BOARD_MINGDA_MPX_ARM_MINI 4053 // STM32F103ZET6 Mingda MD-16
|
||||
#define BOARD_GTM32_PRO_VD 4054 // STM32F103VET6 controller
|
||||
#define BOARD_ZONESTAR_ZM3E2 4055 // Zonestar ZM3E2 (STM32F103RCT6)
|
||||
#define BOARD_ZONESTAR_ZM3E4 4056 // Zonestar ZM3E4 V1 (STM32F103VCT6)
|
||||
#define BOARD_ZONESTAR_ZM3E4V2 4057 // Zonestar ZM3E4 V2 (STM32F103VCT6)
|
||||
|
||||
//
|
||||
// ARM Cortex-M4F
|
||||
@@ -311,44 +369,74 @@
|
||||
// STM32 ARM Cortex-M4F
|
||||
//
|
||||
|
||||
#define BOARD_BEAST 4200 // STM32F4xxVxT6 Libmaple-based STM32F4 controller
|
||||
#define BOARD_GENERIC_STM32F4 4201 // STM32 STM32GENERIC-based STM32F4 controller
|
||||
#define BOARD_ARMED 4202 // Arm'ed STM32F4-based controller
|
||||
#define BOARD_RUMBA32_AUS3D 4203 // RUMBA32 STM32F446VET6 based controller from Aus3D
|
||||
#define BOARD_RUMBA32_MKS 4204 // RUMBA32 STM32F446VET6 based controller from Makerbase
|
||||
#define BOARD_ARMED 4200 // Arm'ed STM32F4-based controller
|
||||
#define BOARD_RUMBA32_V1_0 4201 // RUMBA32 STM32F446VET6 based controller from Aus3D
|
||||
#define BOARD_RUMBA32_V1_1 4202 // RUMBA32 STM32F446VET6 based controller from Aus3D
|
||||
#define BOARD_RUMBA32_MKS 4203 // RUMBA32 STM32F446VET6 based controller from Makerbase
|
||||
#define BOARD_RUMBA32_BTT 4204 // RUMBA32 STM32F446VET6 based controller from BIGTREETECH
|
||||
#define BOARD_BLACK_STM32F407VE 4205 // BLACK_STM32F407VE
|
||||
#define BOARD_BLACK_STM32F407ZE 4206 // BLACK_STM32F407ZE
|
||||
#define BOARD_STEVAL_3DP001V1 4207 // STEVAL-3DP001V1 3D PRINTER BOARD
|
||||
#define BOARD_BTT_SKR_PRO_V1_1 4208 // BigTreeTech SKR Pro v1.1 (STM32F407ZG)
|
||||
#define BOARD_BTT_BTT002_V1_0 4209 // BigTreeTech BTT002 v1.0 (STM32F407VE)
|
||||
#define BOARD_BTT_GTR_V1_0 4210 // BigTreeTech GTR v1.0 (STM32F407IGT)
|
||||
#define BOARD_LERDGE_K 4211 // Lerdge K (STM32F407ZG)
|
||||
#define BOARD_LERDGE_X 4212 // Lerdge X (STM32F407VE)
|
||||
#define BOARD_VAKE403D 4213 // VAkE 403D (STM32F446VET6)
|
||||
#define BOARD_FYSETC_S6 4214 // FYSETC S6 board
|
||||
#define BOARD_FLYF407ZG 4215 // FLYF407ZG board (STM32F407ZG)
|
||||
#define BOARD_MKS_ROBIN2 4216 // MKS_ROBIN2 (STM32F407ZE)
|
||||
#define BOARD_BTT_SKR_PRO_V1_1 4208 // BigTreeTech SKR Pro v1.1 (STM32F407ZGT6)
|
||||
#define BOARD_BTT_SKR_PRO_V1_2 4209 // BigTreeTech SKR Pro v1.2 (STM32F407ZGT6)
|
||||
#define BOARD_BTT_BTT002_V1_0 4210 // BigTreeTech BTT002 v1.0 (STM32F407VGT6)
|
||||
#define BOARD_BTT_E3_RRF 4211 // BigTreeTech E3 RRF (STM32F407VGT6)
|
||||
#define BOARD_BTT_SKR_V2_0_REV_A 4212 // BigTreeTech SKR v2.0 Rev A (STM32F407VGT6)
|
||||
#define BOARD_BTT_SKR_V2_0_REV_B 4213 // BigTreeTech SKR v2.0 Rev B (STM32F407VGT6)
|
||||
#define BOARD_BTT_GTR_V1_0 4214 // BigTreeTech GTR v1.0 (STM32F407IGT)
|
||||
#define BOARD_BTT_OCTOPUS_V1_0 4215 // BigTreeTech Octopus v1.0 (STM32F446ZET6)
|
||||
#define BOARD_BTT_OCTOPUS_V1_1 4216 // BigTreeTech Octopus v1.1 (STM32F446ZET6)
|
||||
#define BOARD_LERDGE_K 4217 // Lerdge K (STM32F407ZG)
|
||||
#define BOARD_LERDGE_S 4218 // Lerdge S (STM32F407VE)
|
||||
#define BOARD_LERDGE_X 4219 // Lerdge X (STM32F407VE)
|
||||
#define BOARD_VAKE403D 4220 // VAkE 403D (STM32F446VET6)
|
||||
#define BOARD_FYSETC_S6 4221 // FYSETC S6 (STM32F446VET6)
|
||||
#define BOARD_FYSETC_S6_V2_0 4222 // FYSETC S6 v2.0 (STM32F446VET6)
|
||||
#define BOARD_FYSETC_SPIDER 4223 // FYSETC Spider (STM32F446VET6)
|
||||
#define BOARD_FLYF407ZG 4224 // FLYmaker FLYF407ZG (STM32F407ZG)
|
||||
#define BOARD_MKS_ROBIN2 4225 // MKS_ROBIN2 (STM32F407ZE)
|
||||
#define BOARD_MKS_ROBIN_PRO_V2 4226 // MKS Robin Pro V2 (STM32F407VE)
|
||||
#define BOARD_MKS_ROBIN_NANO_V3 4227 // MKS Robin Nano V3 (STM32F407VG)
|
||||
#define BOARD_MKS_MONSTER8 4228 // MKS Monster8 (STM32F407VGT6)
|
||||
#define BOARD_ANET_ET4 4229 // ANET ET4 V1.x (STM32F407VGT6)
|
||||
#define BOARD_ANET_ET4P 4230 // ANET ET4P V1.x (STM32F407VGT6)
|
||||
#define BOARD_FYSETC_CHEETAH_V20 4231 // FYSETC Cheetah V2.0
|
||||
#define BOARD_TH3D_EZBOARD_LITE_V2 4232 // TH3D EZBoard Lite v2.0
|
||||
#define BOARD_INDEX_REV03 4233 // Index PnP Controller REV03 (STM32F407VET6/VGT6)
|
||||
#define BOARD_MKS_ROBIN_NANO_V1_3_F4 4234 // MKS Robin Nano V1.3 and MKS Robin Nano-S V1.3 (STM32F407VET6)
|
||||
|
||||
//
|
||||
// ARM Cortex M7
|
||||
//
|
||||
|
||||
#define BOARD_THE_BORG 5000 // THE-BORG (Power outputs: Hotend0, Hotend1, Bed, Fan)
|
||||
#define BOARD_REMRAM_V1 5001 // RemRam v1
|
||||
#define BOARD_REMRAM_V1 5000 // RemRam v1
|
||||
#define BOARD_TEENSY41 5001 // Teensy 4.1
|
||||
#define BOARD_T41U5XBB 5002 // T41U5XBB Teensy 4.1 breakout board
|
||||
#define BOARD_NUCLEO_F767ZI 5003 // ST NUCLEO-F767ZI Dev Board
|
||||
#define BOARD_BTT_SKR_SE_BX 5004 // BigTreeTech SKR SE BX (STM32H743II)
|
||||
|
||||
//
|
||||
// Espressif ESP32 WiFi
|
||||
//
|
||||
|
||||
#define BOARD_ESPRESSIF_ESP32 6000 // Generic ESP32
|
||||
#define BOARD_MRR_ESPA 6001 // MRR ESPA board based on ESP32 (native pins only)
|
||||
#define BOARD_MRR_ESPE 6002 // MRR ESPE board based on ESP32 (with I2S stepper stream)
|
||||
#define BOARD_MRR_ESPA 6001 // MRR ESPA based on ESP32 (native pins only)
|
||||
#define BOARD_MRR_ESPE 6002 // MRR ESPE based on ESP32 (with I2S stepper stream)
|
||||
#define BOARD_E4D_BOX 6003 // E4d@BOX
|
||||
#define BOARD_FYSETC_E4 6004 // FYSETC E4
|
||||
|
||||
//
|
||||
// SAMD51 ARM Cortex M4
|
||||
//
|
||||
|
||||
#define BOARD_AGCM4_RAMPS_144 6100 // RAMPS 1.4.4
|
||||
|
||||
//
|
||||
// Custom board
|
||||
//
|
||||
|
||||
#define BOARD_CUSTOM 9998 // Custom pins definition for development and/or rare boards
|
||||
|
||||
//
|
||||
// Simulations
|
||||
//
|
||||
@@ -357,5 +445,3 @@
|
||||
|
||||
#define _MB_1(B) (defined(BOARD_##B) && MOTHERBOARD==BOARD_##B)
|
||||
#define MB(V...) DO(MB,||,V)
|
||||
|
||||
#define IS_MELZI MB(MELZI, MELZI_CREALITY, MELZI_MAKR3D, MELZI_MALYAN, MELZI_TRONXY)
|
||||
|
39
Marlin/src/core/bug_on.h
Normal file
39
Marlin/src/core/bug_on.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Copyright (c) 2021 X-Ryl669 [https://blog.cyril.by]
|
||||
*
|
||||
* 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
|
||||
|
||||
// We need SERIAL_ECHOPGM and macros.h
|
||||
#include "serial.h"
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
// Useful macro for stopping the CPU on an unexpected condition
|
||||
// This is used like SERIAL_ECHOPGM, that is: a key-value call of the local variables you want
|
||||
// to dump to the serial port before stopping the CPU.
|
||||
// \/ Don't replace by SERIAL_ECHOPGM since ONLY_FILENAME cannot be transformed to a PGM string on Arduino and it breaks building
|
||||
#define BUG_ON(V...) do { SERIAL_ECHO(ONLY_FILENAME); SERIAL_ECHO(__LINE__); SERIAL_ECHOLNPGM(": "); SERIAL_ECHOLNPGM(V); SERIAL_FLUSHTX(); *(char*)0 = 42; } while(0)
|
||||
#elif ENABLED(MARLIN_DEV_MODE)
|
||||
// Don't stop the CPU here, but at least dump the bug on the serial port
|
||||
// \/ Don't replace by SERIAL_ECHOPGM since ONLY_FILENAME cannot be transformed to a PGM string on Arduino and it breaks building
|
||||
#define BUG_ON(V...) do { SERIAL_ECHO(ONLY_FILENAME); SERIAL_ECHO(__LINE__); SERIAL_ECHOLNPGM(": BUG!"); SERIAL_ECHOLNPGM(V); SERIAL_FLUSHTX(); } while(0)
|
||||
#else
|
||||
// Release mode, let's ignore the bug
|
||||
#define BUG_ON(V...) NOOP
|
||||
#endif
|
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -26,78 +26,89 @@
|
||||
// (or not) in a given .cpp file
|
||||
//
|
||||
|
||||
#undef DEBUG_PRINT_P
|
||||
#undef DEBUG_SECTION
|
||||
#undef DEBUG_ECHO_START
|
||||
#undef DEBUG_ERROR_START
|
||||
#undef DEBUG_CHAR
|
||||
#undef DEBUG_ECHO
|
||||
#undef DEBUG_DECIMAL
|
||||
#undef DEBUG_ECHO_F
|
||||
#undef DEBUG_ECHOLN
|
||||
#undef DEBUG_ECHOPGM
|
||||
#undef DEBUG_ECHOLNPGM
|
||||
#undef DEBUG_ECHOPAIR
|
||||
#undef DEBUG_ECHOPAIR_P
|
||||
#undef DEBUG_ECHOPGM_P
|
||||
#undef DEBUG_ECHOLNPGM_P
|
||||
#undef DEBUG_ECHOPAIR_F
|
||||
#undef DEBUG_ECHOPAIR_F_P
|
||||
#undef DEBUG_ECHOLNPAIR
|
||||
#undef DEBUG_ECHOLNPAIR_P
|
||||
#undef DEBUG_ECHOLNPAIR_F
|
||||
#undef DEBUG_ECHOLNPAIR_F_P
|
||||
#undef DEBUG_ECHO_MSG
|
||||
#undef DEBUG_ERROR_MSG
|
||||
#undef DEBUG_EOL
|
||||
#undef DEBUG_FLUSH
|
||||
#undef DEBUG_POS
|
||||
#undef DEBUG_XYZ
|
||||
#undef DEBUG_DELAY
|
||||
#undef DEBUG_SYNCHRONIZE
|
||||
|
||||
#if DEBUG_OUT
|
||||
#define DEBUG_PRINT_P(P) serialprintPGM(P)
|
||||
|
||||
#include "debug_section.h"
|
||||
#define DEBUG_SECTION(N,S,D) SectionLog N(PSTR(S),D)
|
||||
|
||||
#define DEBUG_ECHO_START SERIAL_ECHO_START
|
||||
#define DEBUG_ERROR_START SERIAL_ERROR_START
|
||||
#define DEBUG_CHAR SERIAL_CHAR
|
||||
#define DEBUG_ECHO SERIAL_ECHO
|
||||
#define DEBUG_DECIMAL SERIAL_DECIMAL
|
||||
#define DEBUG_ECHO_F SERIAL_ECHO_F
|
||||
#define DEBUG_ECHOLN SERIAL_ECHOLN
|
||||
#define DEBUG_ECHOPGM SERIAL_ECHOPGM
|
||||
#define DEBUG_ECHOLNPGM SERIAL_ECHOLNPGM
|
||||
#define DEBUG_ECHOPAIR SERIAL_ECHOPAIR
|
||||
#define DEBUG_ECHOPAIR_P SERIAL_ECHOPAIR_P
|
||||
#define DEBUG_ECHOPGM SERIAL_ECHOPGM
|
||||
#define DEBUG_ECHOPGM_P SERIAL_ECHOPGM_P
|
||||
#define DEBUG_ECHOPAIR_F SERIAL_ECHOPAIR_F
|
||||
#define DEBUG_ECHOPAIR_F_P SERIAL_ECHOPAIR_F_P
|
||||
#define DEBUG_ECHOLNPAIR SERIAL_ECHOLNPAIR
|
||||
#define DEBUG_ECHOLNPAIR_P SERIAL_ECHOLNPAIR_P
|
||||
#define DEBUG_ECHOLNPGM SERIAL_ECHOLNPGM
|
||||
#define DEBUG_ECHOLNPGM_P SERIAL_ECHOLNPGM_P
|
||||
#define DEBUG_ECHOLNPAIR_F SERIAL_ECHOLNPAIR_F
|
||||
#define DEBUG_ECHOLNPAIR_F_P SERIAL_ECHOLNPAIR_F_P
|
||||
#define DEBUG_ECHO_MSG SERIAL_ECHO_MSG
|
||||
#define DEBUG_ERROR_MSG SERIAL_ERROR_MSG
|
||||
#define DEBUG_EOL SERIAL_EOL
|
||||
#define DEBUG_FLUSH SERIAL_FLUSH
|
||||
#define DEBUG_POS SERIAL_POS
|
||||
#define DEBUG_XYZ SERIAL_XYZ
|
||||
#define DEBUG_DELAY(ms) serial_delay(ms)
|
||||
#define DEBUG_SYNCHRONIZE() planner.synchronize()
|
||||
|
||||
#else
|
||||
#define DEBUG_PRINT_P(P) NOOP
|
||||
|
||||
#define DEBUG_SECTION(...) NOOP
|
||||
#define DEBUG_ECHO_START() NOOP
|
||||
#define DEBUG_ERROR_START() NOOP
|
||||
#define DEBUG_CHAR(...) NOOP
|
||||
#define DEBUG_ECHO(...) NOOP
|
||||
#define DEBUG_DECIMAL(...) NOOP
|
||||
#define DEBUG_ECHO_F(...) NOOP
|
||||
#define DEBUG_ECHOLN(...) NOOP
|
||||
#define DEBUG_ECHOPGM(...) NOOP
|
||||
#define DEBUG_ECHOLNPGM(...) NOOP
|
||||
#define DEBUG_ECHOPAIR(...) NOOP
|
||||
#define DEBUG_ECHOPAIR_P(...) NOOP
|
||||
#define DEBUG_ECHOPGM_P(...) NOOP
|
||||
#define DEBUG_ECHOLNPGM_P(...) NOOP
|
||||
#define DEBUG_ECHOPAIR_F(...) NOOP
|
||||
#define DEBUG_ECHOPAIR_F_P(...) NOOP
|
||||
#define DEBUG_ECHOLNPAIR(...) NOOP
|
||||
#define DEBUG_ECHOLNPAIR_P(...) NOOP
|
||||
#define DEBUG_ECHOLNPAIR_F(...) NOOP
|
||||
#define DEBUG_ECHOLNPAIR_F_P(...) NOOP
|
||||
#define DEBUG_ECHO_MSG(...) NOOP
|
||||
#define DEBUG_ERROR_MSG(...) NOOP
|
||||
#define DEBUG_EOL() NOOP
|
||||
#define DEBUG_FLUSH() NOOP
|
||||
#define DEBUG_POS(...) NOOP
|
||||
#define DEBUG_XYZ(...) NOOP
|
||||
#define DEBUG_DELAY(...) NOOP
|
||||
#define DEBUG_SYNCHRONIZE() NOOP
|
||||
|
||||
#endif
|
||||
|
||||
#undef DEBUG_OUT
|
||||
|
49
Marlin/src/core/debug_section.h
Normal file
49
Marlin/src/core/debug_section.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "serial.h"
|
||||
#include "../module/motion.h"
|
||||
|
||||
class SectionLog {
|
||||
public:
|
||||
SectionLog(PGM_P const msg=nullptr, bool inbug=true) {
|
||||
the_msg = msg;
|
||||
if ((debug = inbug)) echo_msg(PSTR(">>>"));
|
||||
}
|
||||
|
||||
~SectionLog() { if (debug) echo_msg(PSTR("<<<")); }
|
||||
|
||||
private:
|
||||
PGM_P the_msg;
|
||||
bool debug;
|
||||
|
||||
void echo_msg(PGM_P const pre) {
|
||||
SERIAL_ECHOPGM_P(pre);
|
||||
if (the_msg) {
|
||||
SERIAL_CHAR(' ');
|
||||
SERIAL_ECHOPGM_P(the_msg);
|
||||
}
|
||||
SERIAL_CHAR(' ');
|
||||
print_pos(current_position);
|
||||
}
|
||||
};
|
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -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,9 +86,14 @@
|
||||
#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) )
|
||||
|
||||
//
|
||||
// Trinamic Stepper Drivers
|
||||
//
|
||||
|
||||
// Test for supported TMC drivers that require advanced configuration
|
||||
// Does not match standalone configurations
|
||||
#if ( HAS_DRIVER(TMC2130) || HAS_DRIVER(TMC2160) \
|
||||
@@ -127,6 +135,7 @@
|
||||
|
||||
#define AXIS_HAS_RXTX AXIS_HAS_UART
|
||||
|
||||
#define AXIS_HAS_HW_SERIAL(A) ( AXIS_HAS_UART(A) && defined(A##_HARDWARE_SERIAL) )
|
||||
#define AXIS_HAS_SW_SERIAL(A) ( AXIS_HAS_UART(A) && !defined(A##_HARDWARE_SERIAL) )
|
||||
|
||||
#define AXIS_HAS_STALLGUARD(A) ( AXIS_DRIVER_TYPE(A,TMC2130) || AXIS_DRIVER_TYPE(A,TMC2160) \
|
||||
@@ -148,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
|
||||
@@ -171,17 +182,16 @@
|
||||
#define HAS_TMC_SPI 1
|
||||
#endif
|
||||
|
||||
// Defines that can't be evaluated now
|
||||
#define HAS_TMC_SW_SERIAL ANY_AXIS_HAS(SW_SERIAL)
|
||||
//
|
||||
// TMC26XX Stepper Drivers
|
||||
//
|
||||
#if HAS_DRIVER(TMC26X)
|
||||
#define HAS_TMC26X 1
|
||||
#endif
|
||||
|
||||
//
|
||||
// Stretching 'drivers.h' to include LPC/SAMD51 SD options
|
||||
// L64XX Stepper Drivers
|
||||
//
|
||||
#define _SDCARD_LCD 1
|
||||
#define _SDCARD_ONBOARD 2
|
||||
#define _SDCARD_CUSTOM_CABLE 3
|
||||
#define _SDCARD_ID(V) _CAT(_SDCARD_, V)
|
||||
#define SD_CONNECTION_IS(V) (_SDCARD_ID(SDCARD_CONNECTION) == _SDCARD_ID(V))
|
||||
|
||||
#if HAS_DRIVER(L6470) || HAS_DRIVER(L6474) || HAS_DRIVER(L6480) || HAS_DRIVER(POWERSTEP01)
|
||||
#define HAS_L64XX 1
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -39,7 +39,7 @@
|
||||
//
|
||||
// ==> ALWAYS TRY TO COMPILE MARLIN WITH/WITHOUT "ULTIPANEL" / "ULTRA_LCD" / "SDSUPPORT" #define IN "Configuration.h"
|
||||
// ==> ALSO TRY ALL AVAILABLE LANGUAGE OPTIONS
|
||||
// See also http://marlinfw.org/docs/development/lcd_language.html
|
||||
// See also https://marlinfw.org/docs/development/lcd_language.html
|
||||
|
||||
// Languages
|
||||
// an Aragonese
|
||||
@@ -48,8 +48,8 @@
|
||||
// cz Czech
|
||||
// da Danish
|
||||
// de German
|
||||
// el Greek
|
||||
// el_gr Greek (Greece)
|
||||
// el Greek (Greece)
|
||||
// el_CY Greek (Cyprus)
|
||||
// en English
|
||||
// es Spanish
|
||||
// eu Basque-Euskera
|
||||
@@ -57,6 +57,7 @@
|
||||
// fr French
|
||||
// gl Galician
|
||||
// hr Croatian
|
||||
// hu Hungarian
|
||||
// it Italian
|
||||
// jp_kana Japanese
|
||||
// ko_KR Korean (South Korea)
|
||||
@@ -64,8 +65,10 @@
|
||||
// pl Polish
|
||||
// pt Portuguese
|
||||
// pt_br Portuguese (Brazilian)
|
||||
// ro Romanian
|
||||
// ru Russian
|
||||
// sk Slovak
|
||||
// sv Swedish
|
||||
// tr Turkish
|
||||
// uk Ukrainian
|
||||
// vi Vietnamese
|
||||
@@ -80,18 +83,16 @@
|
||||
#ifdef CUSTOM_MACHINE_NAME
|
||||
#undef MACHINE_NAME
|
||||
#define MACHINE_NAME CUSTOM_MACHINE_NAME
|
||||
#else
|
||||
#ifdef DEFAULT_MACHINE_NAME
|
||||
#undef MACHINE_NAME
|
||||
#define MACHINE_NAME DEFAULT_MACHINE_NAME
|
||||
#endif
|
||||
#elif defined(DEFAULT_MACHINE_NAME)
|
||||
#undef MACHINE_NAME
|
||||
#define MACHINE_NAME DEFAULT_MACHINE_NAME
|
||||
#endif
|
||||
|
||||
#ifndef MACHINE_UUID
|
||||
#define MACHINE_UUID DEFAULT_MACHINE_UUID
|
||||
#endif
|
||||
|
||||
#define MARLIN_WEBSITE_URL "http://marlinfw.org"
|
||||
#define MARLIN_WEBSITE_URL "marlinfw.org"
|
||||
|
||||
//#if !defined(STRING_SPLASH_LINE3) && defined(WEBSITE_URL)
|
||||
// #define STRING_SPLASH_LINE3 WEBSITE_URL
|
||||
@@ -108,8 +109,6 @@
|
||||
#define STR_BROWNOUT_RESET " Brown out Reset"
|
||||
#define STR_WATCHDOG_RESET " Watchdog Reset"
|
||||
#define STR_SOFTWARE_RESET " Software Reset"
|
||||
#define STR_AUTHOR " | Author: "
|
||||
#define STR_CONFIGURATION_VER " Last Updated: "
|
||||
#define STR_FREE_MEMORY " Free Memory: "
|
||||
#define STR_PLANNER_BUFFER_BYTES " PlannerBufferBytes: "
|
||||
#define STR_OK "ok"
|
||||
@@ -120,19 +119,20 @@
|
||||
#define STR_ERR_CHECKSUM_MISMATCH "checksum mismatch, Last Line: "
|
||||
#define STR_ERR_NO_CHECKSUM "No Checksum with line number, Last Line: "
|
||||
#define STR_FILE_PRINTED "Done printing file"
|
||||
#define STR_NO_MEDIA "No media"
|
||||
#define STR_BEGIN_FILE_LIST "Begin file list"
|
||||
#define STR_END_FILE_LIST "End file list"
|
||||
#define STR_INVALID_EXTRUDER "Invalid extruder"
|
||||
#define STR_INVALID_E_STEPPER "Invalid E stepper"
|
||||
#define STR_E_STEPPER_NOT_SPECIFIED "E stepper not specified"
|
||||
#define STR_INVALID_SOLENOID "Invalid solenoid"
|
||||
#define STR_M115_REPORT "FIRMWARE_NAME:Marlin " DETAILED_BUILD_VERSION " KNUTWURST_AI3M_VERSION:" CUSTOM_BUILD_VERSION " DISTRIBUTION_DATE:" STRING_DISTRIBUTION_DATE " SOURCE_CODE_URL:" SOURCE_CODE_URL " PROTOCOL_VERSION:" PROTOCOL_VERSION " MACHINE_TYPE:" MACHINE_NAME " EXTRUDER_COUNT:" STRINGIFY(EXTRUDERS) " UUID:" MACHINE_UUID
|
||||
#define STR_MARLIN_AI3M "Marlin-AI3M"
|
||||
#define STR_COUNT_X " Count X:"
|
||||
#define STR_COUNT_A " Count A:"
|
||||
#define STR_WATCHDOG_FIRED "Watchdog timeout. Reset required."
|
||||
#define STR_ERR_KILLED "Printer halted. kill() called!"
|
||||
#define STR_FLOWMETER_FAULT "Coolant flow fault. Flowmeter safety is active. Attention required."
|
||||
#define STR_ERR_STOPPED "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)"
|
||||
#define STR_ERR_SERIAL_MISMATCH "Serial status mismatch"
|
||||
#define STR_BUSY_PROCESSING "busy: processing"
|
||||
#define STR_BUSY_PAUSED_FOR_USER "busy: paused for user"
|
||||
#define STR_BUSY_PAUSED_FOR_INPUT "busy: paused for input"
|
||||
@@ -140,31 +140,14 @@
|
||||
#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_FILAMENT_RUNOUT_SENSOR "filament"
|
||||
|
||||
#define STR_PROBE_OFFSET "Probe Offset"
|
||||
#define STR_SKEW_MIN "min_skew_factor: "
|
||||
#define STR_SKEW_MAX "max_skew_factor: "
|
||||
#define STR_ERR_MATERIAL_INDEX "M145 S<index> out of range (0-1)"
|
||||
#define STR_ERR_M421_PARAMETERS "M421 incorrect parameter usage"
|
||||
#define STR_ERR_BAD_PLANE_MODE "G5 requires XY plane mode"
|
||||
#define STR_ERR_MESH_XY "Mesh point cannot be resolved"
|
||||
#define STR_ERR_MESH_XY "Mesh point out of range"
|
||||
#define STR_ERR_ARC_ARGS "G2/G3 bad parameters"
|
||||
#define STR_ERR_PROTECTED_PIN "Protected Pin"
|
||||
#define STR_ERR_M420_FAILED "Failed to enable Bed Leveling"
|
||||
@@ -175,18 +158,17 @@
|
||||
#define STR_OFF "OFF"
|
||||
#define STR_ENDSTOP_HIT "TRIGGERED"
|
||||
#define STR_ENDSTOP_OPEN "open"
|
||||
#define STR_HOTEND_OFFSET "Hotend offsets:"
|
||||
#define STR_DUPLICATION_MODE "Duplication mode: "
|
||||
#define STR_SOFT_ENDSTOPS "Soft endstops: "
|
||||
#define STR_SOFT_MIN " Min: "
|
||||
#define STR_SOFT_MAX " Max: "
|
||||
|
||||
#define STR_SAVED_POS "Position saved"
|
||||
#define STR_RESTORING_POS "Restoring position"
|
||||
#define STR_INVALID_POS_SLOT "Invalid slot. Total: "
|
||||
#define STR_DONE "Done."
|
||||
|
||||
#define STR_SD_CANT_OPEN_SUBDIR "Cannot open subdir "
|
||||
#define STR_SD_INIT_FAIL "SD init fail"
|
||||
#define STR_SD_INIT_FAIL "No SD card"
|
||||
#define STR_SD_VOL_INIT_FAIL "volume.init failed"
|
||||
#define STR_SD_OPENROOT_FAIL "openRoot failed"
|
||||
#define STR_SD_CARD_OK "SD card ok"
|
||||
@@ -206,7 +188,6 @@
|
||||
#define STR_ERR_COLD_EXTRUDE_STOP " cold extrusion prevented"
|
||||
#define STR_ERR_LONG_EXTRUDE_STOP " too long extrusion prevented"
|
||||
#define STR_ERR_HOTEND_TOO_COLD "Hotend too cold"
|
||||
#define STR_ERR_Z_HOMING_SER "Home XY first"
|
||||
#define STR_ERR_EEPROM_WRITE "Error writing to EEPROM!"
|
||||
|
||||
#define STR_FILAMENT_CHANGE_HEAT_LCD "Press button to heat nozzle"
|
||||
@@ -222,12 +203,10 @@
|
||||
#define STR_KILL_BUTTON "!! KILL caused by KILL button/pin"
|
||||
|
||||
// temperature.cpp strings
|
||||
#define STR_PID_AUTOTUNE_PREFIX "PID Autotune"
|
||||
#define STR_PID_AUTOTUNE_START STR_PID_AUTOTUNE_PREFIX " start"
|
||||
#define STR_PID_AUTOTUNE_FAILED STR_PID_AUTOTUNE_PREFIX " failed!"
|
||||
#define STR_PID_BAD_EXTRUDER_NUM STR_PID_AUTOTUNE_FAILED " Bad extruder number"
|
||||
#define STR_PID_TEMP_TOO_HIGH STR_PID_AUTOTUNE_FAILED " Temperature too high"
|
||||
#define STR_PID_TIMEOUT STR_PID_AUTOTUNE_FAILED " timeout"
|
||||
#define STR_PID_AUTOTUNE_START "PID Autotune start"
|
||||
#define STR_PID_BAD_HEATER_ID "PID Autotune failed! Bad heater id"
|
||||
#define STR_PID_TEMP_TOO_HIGH "PID Autotune failed! Temperature too high"
|
||||
#define STR_PID_TIMEOUT "PID Autotune failed! timeout"
|
||||
#define STR_BIAS " bias: "
|
||||
#define STR_D_COLON " d: "
|
||||
#define STR_T_MIN " min: "
|
||||
@@ -238,7 +217,7 @@
|
||||
#define STR_KP " Kp: "
|
||||
#define STR_KI " Ki: "
|
||||
#define STR_KD " Kd: "
|
||||
#define STR_PID_AUTOTUNE_FINISHED STR_PID_AUTOTUNE_PREFIX " finished! Put the last Kp, Ki and Kd constants from below into Configuration.h"
|
||||
#define STR_PID_AUTOTUNE_FINISHED "PID Autotune finished! Put the last Kp, Ki and Kd constants from below into Configuration.h"
|
||||
#define STR_PID_DEBUG " PID_DEBUG "
|
||||
#define STR_PID_DEBUG_INPUT ": Input "
|
||||
#define STR_PID_DEBUG_OUTPUT " Output "
|
||||
@@ -250,6 +229,11 @@
|
||||
|
||||
#define STR_HEATER_BED "bed"
|
||||
#define STR_HEATER_CHAMBER "chamber"
|
||||
#define STR_COOLER "cooler"
|
||||
#define STR_MOTHERBOARD "motherboard"
|
||||
#define STR_PROBE "probe"
|
||||
#define STR_REDUNDANT "redundant "
|
||||
#define STR_LASER_TEMP "laser temperature"
|
||||
|
||||
#define STR_STOPPED_HEATER ", system stopped! Heater_ID: "
|
||||
#define STR_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !"
|
||||
@@ -270,17 +254,94 @@
|
||||
#define STR_DEBUG_COMMUNICATION "COMMUNICATION"
|
||||
#define STR_DEBUG_LEVELING "LEVELING"
|
||||
|
||||
// LCD Menu Messages
|
||||
#define STR_PRINTER_LOCKED "Printer locked! (Unlock with M511 or LCD)"
|
||||
#define STR_WRONG_PASSWORD "Incorrect Password"
|
||||
#define STR_PASSWORD_TOO_LONG "Password too long"
|
||||
#define STR_PASSWORD_REMOVED "Password removed"
|
||||
#define STR_REMINDER_SAVE_SETTINGS "Remember to save!"
|
||||
#define STR_PASSWORD_SET "Password is "
|
||||
|
||||
#define LANGUAGE_DATA_INCL_(M) STRINGIFY_(fontdata/langdata_##M.h)
|
||||
#define LANGUAGE_DATA_INCL(M) LANGUAGE_DATA_INCL_(M)
|
||||
// Settings Report Strings
|
||||
#define STR_Z_AUTO_ALIGN "Z Auto-Align"
|
||||
#define STR_BACKLASH_COMPENSATION "Backlash compensation"
|
||||
#define STR_S_SEG_PER_SEC "S<seg-per-sec>"
|
||||
#define STR_DELTA_SETTINGS "Delta (L<diagonal-rod> R<radius> H<height> S<seg-per-sec> XYZ<tower-angle-trim> ABC<rod-trim>)"
|
||||
#define STR_SCARA_SETTINGS "SCARA"
|
||||
#define STR_POLARGRAPH_SETTINGS "Polargraph"
|
||||
#define STR_SCARA_P_T_Z "P<theta-psi-offset> T<theta-offset> Z<home-offset>"
|
||||
#define STR_ENDSTOP_ADJUSTMENT "Endstop adjustment"
|
||||
#define STR_SKEW_FACTOR "Skew Factor"
|
||||
#define STR_FILAMENT_SETTINGS "Filament settings"
|
||||
#define STR_MAX_ACCELERATION "Max Acceleration (units/s2)"
|
||||
#define STR_MAX_FEEDRATES "Max feedrates (units/s)"
|
||||
#define STR_ACCELERATION_P_R_T "Acceleration (units/s2) (P<print-accel> R<retract-accel> T<travel-accel>)"
|
||||
#define STR_TOOL_CHANGING "Tool-changing"
|
||||
#define STR_HOTEND_OFFSETS "Hotend offsets"
|
||||
#define STR_SERVO_ANGLES "Servo Angles"
|
||||
#define STR_HOTEND_PID "Hotend PID"
|
||||
#define STR_BED_PID "Bed PID"
|
||||
#define STR_CHAMBER_PID "Chamber PID"
|
||||
#define STR_STEPS_PER_UNIT "Steps per unit"
|
||||
#define STR_LINEAR_ADVANCE "Linear Advance"
|
||||
#define STR_CONTROLLER_FAN "Controller Fan"
|
||||
#define STR_STEPPER_MOTOR_CURRENTS "Stepper motor currents"
|
||||
#define STR_RETRACT_S_F_Z "Retract (S<length> F<feedrate> Z<lift>)"
|
||||
#define STR_RECOVER_S_F "Recover (S<length> F<feedrate>)"
|
||||
#define STR_AUTO_RETRACT_S "Auto-Retract (S<enable>)"
|
||||
#define STR_FILAMENT_LOAD_UNLOAD "Filament load/unload"
|
||||
#define STR_POWER_LOSS_RECOVERY "Power-loss recovery"
|
||||
#define STR_FILAMENT_RUNOUT_SENSOR "Filament runout sensor"
|
||||
#define STR_DRIVER_STEPPING_MODE "Driver stepping mode"
|
||||
#define STR_STEPPER_DRIVER_CURRENT "Stepper driver current"
|
||||
#define STR_HYBRID_THRESHOLD "Hybrid Threshold"
|
||||
#define STR_STALLGUARD_THRESHOLD "StallGuard threshold"
|
||||
#define STR_HOME_OFFSET "Home offset"
|
||||
#define STR_SOFT_ENDSTOPS "Soft endstops"
|
||||
#define STR_MATERIAL_HEATUP "Material heatup parameters"
|
||||
#define STR_LCD_CONTRAST "LCD Contrast"
|
||||
#define STR_LCD_BRIGHTNESS "LCD Brightness"
|
||||
#define STR_UI_LANGUAGE "UI Language"
|
||||
#define STR_Z_PROBE_OFFSET "Z-Probe Offset"
|
||||
#define STR_TEMPERATURE_UNITS "Temperature Units"
|
||||
#define STR_USER_THERMISTORS "User thermistors"
|
||||
|
||||
#define LANGUAGE_INCL_(M) STRINGIFY_(../lcd/language/language_##M.h)
|
||||
#define LANGUAGE_INCL(M) LANGUAGE_INCL_(M)
|
||||
//
|
||||
// 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"
|
||||
|
||||
#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
|
||||
|
||||
#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 "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"
|
||||
@@ -300,9 +361,115 @@
|
||||
#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
|
||||
|
||||
#if HAS_CHARACTER_LCD
|
||||
// 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
|
||||
#define LCD_STR_BEDTEMP "\x00" // Print only as a char. This will have 'unexpected' results when used in a string!
|
||||
@@ -347,10 +514,9 @@
|
||||
* However, internal to Marlin E0/T0 is the first tool, and
|
||||
* most board silkscreens say "E0." Zero-based labels will
|
||||
* make these indexes consistent but this defies expectation.
|
||||
*
|
||||
*/
|
||||
#if ENABLED(NUMBER_TOOLS_FROM_0)
|
||||
#define LCD_FIRST_TOOL '0'
|
||||
#define LCD_FIRST_TOOL 0
|
||||
#define LCD_STR_N0 "0"
|
||||
#define LCD_STR_N1 "1"
|
||||
#define LCD_STR_N2 "2"
|
||||
@@ -360,7 +526,7 @@
|
||||
#define LCD_STR_N6 "6"
|
||||
#define LCD_STR_N7 "7"
|
||||
#else
|
||||
#define LCD_FIRST_TOOL '1'
|
||||
#define LCD_FIRST_TOOL 1
|
||||
#define LCD_STR_N0 "1"
|
||||
#define LCD_STR_N1 "2"
|
||||
#define LCD_STR_N2 "3"
|
||||
@@ -380,6 +546,18 @@
|
||||
#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", "³")
|
||||
|
||||
#include "multi_language.h" // Allow multiple languages
|
||||
|
||||
#include "../lcd/language/language_en.h"
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -33,26 +33,36 @@
|
||||
|
||||
#define _AXIS(A) (A##_AXIS)
|
||||
|
||||
#define _XMIN_ 100
|
||||
#define _YMIN_ 200
|
||||
#define _ZMIN_ 300
|
||||
#define _XMAX_ 101
|
||||
#define _YMAX_ 201
|
||||
#define _ZMAX_ 301
|
||||
#define _XDIAG_ 102
|
||||
#define _YDIAG_ 202
|
||||
#define _ZDIAG_ 302
|
||||
#define _E0DIAG_ 400
|
||||
#define _E1DIAG_ 401
|
||||
#define _E2DIAG_ 402
|
||||
#define _E3DIAG_ 403
|
||||
#define _E4DIAG_ 404
|
||||
#define _E5DIAG_ 405
|
||||
#define _E6DIAG_ 406
|
||||
#define _E7DIAG_ 407
|
||||
#define _XMIN_ 0x11
|
||||
#define _YMIN_ 0x12
|
||||
#define _ZMIN_ 0x13
|
||||
#define _IMIN_ 0x14
|
||||
#define _JMIN_ 0x15
|
||||
#define _KMIN_ 0x16
|
||||
#define _XMAX_ 0x21
|
||||
#define _YMAX_ 0x22
|
||||
#define _ZMAX_ 0x23
|
||||
#define _IMAX_ 0x24
|
||||
#define _JMAX_ 0x25
|
||||
#define _KMAX_ 0x26
|
||||
#define _XDIAG_ 0x31
|
||||
#define _YDIAG_ 0x32
|
||||
#define _ZDIAG_ 0x33
|
||||
#define _IDIAG_ 0x34
|
||||
#define _JDIAG_ 0x35
|
||||
#define _KDIAG_ 0x36
|
||||
#define _E0DIAG_ 0xE0
|
||||
#define _E1DIAG_ 0xE1
|
||||
#define _E2DIAG_ 0xE2
|
||||
#define _E3DIAG_ 0xE3
|
||||
#define _E4DIAG_ 0xE4
|
||||
#define _E5DIAG_ 0xE5
|
||||
#define _E6DIAG_ 0xE6
|
||||
#define _E7DIAG_ 0xE7
|
||||
|
||||
#define _FORCE_INLINE_ __attribute__((__always_inline__)) __inline__
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#define NO_INLINE __attribute__((noinline))
|
||||
#define _UNUSED __attribute__((unused))
|
||||
#define _O0 __attribute__((optimize("O0")))
|
||||
#define _Os __attribute__((optimize("Os")))
|
||||
@@ -60,12 +70,10 @@
|
||||
#define _O2 __attribute__((optimize("O2")))
|
||||
#define _O3 __attribute__((optimize("O3")))
|
||||
|
||||
#define IS_CONSTEXPR(...) __builtin_constant_p(__VA_ARGS__) // Only valid solution with C++14. Should use std::is_constant_evaluated() in C++20 instead
|
||||
|
||||
#ifndef UNUSED
|
||||
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
|
||||
#define UNUSED(X) (void)X
|
||||
#else
|
||||
#define UNUSED(x) ((void)(x))
|
||||
#endif
|
||||
#define UNUSED(x) ((void)(x))
|
||||
#endif
|
||||
|
||||
// Clock speed factors
|
||||
@@ -76,13 +84,6 @@
|
||||
// Nanoseconds per cycle
|
||||
#define NANOSECONDS_PER_CYCLE (1000000000.0 / F_CPU)
|
||||
|
||||
// Macros to make sprintf_P read from PROGMEM (AVR extension)
|
||||
#ifdef __AVR__
|
||||
#define S_FMT "%S"
|
||||
#else
|
||||
#define S_FMT "%s"
|
||||
#endif
|
||||
|
||||
// Macros to make a string from a macro
|
||||
#define STRINGIFY_(M) #M
|
||||
#define STRINGIFY(M) STRINGIFY_(M)
|
||||
@@ -95,29 +96,29 @@
|
||||
#define _BV(n) (1<<(n))
|
||||
#define TEST(n,b) (!!((n)&_BV(b)))
|
||||
#define SET_BIT_TO(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)
|
||||
|
||||
#ifndef SBI
|
||||
#define SBI(A,B) (A |= (1 << (B)))
|
||||
#define SBI(A,B) (A |= _BV(B))
|
||||
#endif
|
||||
|
||||
#ifndef CBI
|
||||
#define CBI(A,B) (A &= ~(1 << (B)))
|
||||
#define CBI(A,B) (A &= ~_BV(B))
|
||||
#endif
|
||||
|
||||
#define TBI(N,B) (N ^= _BV(B))
|
||||
#define _BV32(b) (1UL << (b))
|
||||
#define TEST32(n,b) !!((n)&_BV32(b))
|
||||
#define SBI32(n,b) (n |= _BV32(b))
|
||||
#define CBI32(n,b) (n &= ~_BV32(b))
|
||||
#define TBI32(N,B) (N ^= _BV32(B))
|
||||
|
||||
#define cu(x) ((x)*(x)*(x))
|
||||
#define cu(x) ({__typeof__(x) _x = (x); (_x)*(_x)*(_x);})
|
||||
#define RADIANS(d) ((d)*float(M_PI)/180.0f)
|
||||
#define DEGREES(r) ((r)*180.0f/float(M_PI))
|
||||
#define HYPOT2(x,y) (sq(x)+sq(y))
|
||||
#define NORMSQ(x,y,z) (sq(x)+sq(y)+sq(z))
|
||||
|
||||
#define CIRCLE_AREA(R) (float(M_PI) * sq(float(R)))
|
||||
#define CIRCLE_CIRC(R) (2 * float(M_PI) * float(R))
|
||||
|
||||
#define SIGN(a) ((a>0)-(a<0))
|
||||
#define SIGN(a) ({__typeof__(a) _a = (a); (_a>0)-(_a<0);})
|
||||
#define IS_POWER_OF_2(x) ((x) && !((x) & ((x) - 1)))
|
||||
|
||||
// Macros to constrain values
|
||||
@@ -137,31 +138,29 @@
|
||||
|
||||
#else
|
||||
|
||||
// Using GCC extensions, but Travis GCC version does not like it and gives
|
||||
// "error: statement-expressions are not allowed outside functions nor in template-argument lists"
|
||||
#define NOLESS(v, n) \
|
||||
do{ \
|
||||
__typeof__(n) _n = (n); \
|
||||
__typeof__(v) _n = (n); \
|
||||
if (_n > v) v = _n; \
|
||||
}while(0)
|
||||
|
||||
#define NOMORE(v, n) \
|
||||
do{ \
|
||||
__typeof__(n) _n = (n); \
|
||||
__typeof__(v) _n = (n); \
|
||||
if (_n < v) v = _n; \
|
||||
}while(0)
|
||||
|
||||
#define LIMIT(v, n1, n2) \
|
||||
do{ \
|
||||
__typeof__(n1) _n1 = (n1); \
|
||||
__typeof__(n2) _n2 = (n2); \
|
||||
__typeof__(v) _n1 = (n1); \
|
||||
__typeof__(v) _n2 = (n2); \
|
||||
if (_n1 > v) v = _n1; \
|
||||
else if (_n2 < v) v = _n2; \
|
||||
}while(0)
|
||||
|
||||
#endif
|
||||
|
||||
// Macros to chain up to 12 conditions
|
||||
// Macros to chain up to 14 conditions
|
||||
#define _DO_1(W,C,A) (_##W##_1(A))
|
||||
#define _DO_2(W,C,A,B) (_##W##_1(A) C _##W##_1(B))
|
||||
#define _DO_3(W,C,A,V...) (_##W##_1(A) C _DO_2(W,C,V))
|
||||
@@ -174,9 +173,12 @@
|
||||
#define _DO_10(W,C,A,V...) (_##W##_1(A) C _DO_9(W,C,V))
|
||||
#define _DO_11(W,C,A,V...) (_##W##_1(A) C _DO_10(W,C,V))
|
||||
#define _DO_12(W,C,A,V...) (_##W##_1(A) C _DO_11(W,C,V))
|
||||
#define _DO_13(W,C,A,V...) (_##W##_1(A) C _DO_12(W,C,V))
|
||||
#define _DO_14(W,C,A,V...) (_##W##_1(A) C _DO_13(W,C,V))
|
||||
#define _DO_15(W,C,A,V...) (_##W##_1(A) C _DO_14(W,C,V))
|
||||
#define __DO_N(W,C,N,V...) _DO_##N(W,C,V)
|
||||
#define _DO_N(W,C,N,V...) __DO_N(W,C,N,V)
|
||||
#define DO(W,C,V...) _DO_N(W,C,NUM_ARGS(V),V)
|
||||
#define DO(W,C,V...) (_DO_N(W,C,NUM_ARGS(V),V))
|
||||
|
||||
// Macros to support option testing
|
||||
#define _CAT(a,V...) a##V
|
||||
@@ -192,20 +194,37 @@
|
||||
#define _DIS_1(O) NOT(_ENA_1(O))
|
||||
#define ENABLED(V...) DO(ENA,&&,V)
|
||||
#define DISABLED(V...) DO(DIS,&&,V)
|
||||
#define COUNT_ENABLED(V...) DO(ENA,+,V)
|
||||
|
||||
#define TERN(O,A,B) _TERN(_ENA_1(O),B,A) // OPTION converted to '0' or '1'
|
||||
#define TERN0(O,A) _TERN(_ENA_1(O),0,A) // OPTION converted to A or '0'
|
||||
#define TERN1(O,A) _TERN(_ENA_1(O),1,A) // OPTION converted to A or '1'
|
||||
#define TERN_(O,A) _TERN(_ENA_1(O),,A) // OPTION converted to A or '<nul>'
|
||||
#define TERN(O,A,B) _TERN(_ENA_1(O),B,A) // OPTION ? 'A' : 'B'
|
||||
#define TERN0(O,A) _TERN(_ENA_1(O),0,A) // OPTION ? 'A' : '0'
|
||||
#define TERN1(O,A) _TERN(_ENA_1(O),1,A) // OPTION ? 'A' : '1'
|
||||
#define TERN_(O,A) _TERN(_ENA_1(O),,A) // OPTION ? 'A' : '<nul>'
|
||||
#define _TERN(E,V...) __TERN(_CAT(T_,E),V) // Prepend 'T_' to get 'T_0' or 'T_1'
|
||||
#define __TERN(T,V...) ___TERN(_CAT(_NO,T),V) // Prepend '_NO' to get '_NOT_0' or '_NOT_1'
|
||||
#define ___TERN(P,V...) THIRD(P,V) // If first argument has a comma, A. Else B.
|
||||
|
||||
#define _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>'
|
||||
#define MINUS_TERN0(O,A) _TERN(_ENA_1(O),,- (A)) // OPTION ? '- (A)' : '<nul>'
|
||||
#define SUM_TERN(O,B,A) ((B) PLUS_TERN0(O,A)) // ((B) (OPTION ? '+ (A)' : '<nul>'))
|
||||
#define DIFF_TERN(O,B,A) ((B) MINUS_TERN0(O,A)) // ((B) (OPTION ? '- (A)' : '<nul>'))
|
||||
|
||||
#define IF_ENABLED TERN_
|
||||
#define IF_DISABLED(O,A) TERN(O,,A)
|
||||
|
||||
#define ANY(V...) !DISABLED(V)
|
||||
#define NONE(V...) DISABLED(V)
|
||||
#define ALL(V...) ENABLED(V)
|
||||
#define BOTH(V1,V2) ALL(V1,V2)
|
||||
#define EITHER(V1,V2) ANY(V1,V2)
|
||||
#define MANY(V...) (COUNT_ENABLED(V) > 1)
|
||||
|
||||
// Macros to support pins/buttons exist testing
|
||||
#define PIN_EXISTS(PN) (defined(PN##_PIN) && PN##_PIN >= 0)
|
||||
@@ -219,8 +238,10 @@
|
||||
#define ANY_BUTTON(V...) DO(BTNEX,||,V)
|
||||
|
||||
#define WITHIN(N,L,H) ((N) >= (L) && (N) <= (H))
|
||||
#define ISEOL(C) ((C) == '\n' || (C) == '\r')
|
||||
#define NUMERIC(a) WITHIN(a, '0', '9')
|
||||
#define DECIMAL(a) (NUMERIC(a) || a == '.')
|
||||
#define HEXCHR(a) (NUMERIC(a) ? (a) - '0' : WITHIN(a, 'a', 'f') ? ((a) - 'a' + 10) : WITHIN(a, 'A', 'F') ? ((a) - 'A' + 10) : -1)
|
||||
#define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-' || (a) == '+')
|
||||
#define DECIMAL_SIGNED(a) (DECIMAL(a) || (a) == '-' || (a) == '+')
|
||||
#define COUNT(a) (sizeof(a)/sizeof(*a))
|
||||
@@ -230,7 +251,47 @@
|
||||
memcpy(&a[0],&b[0],_MIN(sizeof(a),sizeof(b))); \
|
||||
}while(0)
|
||||
|
||||
#define CODE_11( A,B,C,D,E,F,G,H,I,J,K,...) A; B; C; D; E; F; G; H; I; J; K
|
||||
#define CODE_10( A,B,C,D,E,F,G,H,I,J,...) A; B; C; D; E; F; G; H; I; J
|
||||
#define CODE_9( A,B,C,D,E,F,G,H,I,...) A; B; C; D; E; F; G; H; I
|
||||
#define CODE_8( A,B,C,D,E,F,G,H,...) A; B; C; D; E; F; G; H
|
||||
#define CODE_7( A,B,C,D,E,F,G,...) A; B; C; D; E; F; G
|
||||
#define CODE_6( A,B,C,D,E,F,...) A; B; C; D; E; F
|
||||
#define CODE_5( A,B,C,D,E,...) A; B; C; D; E
|
||||
#define CODE_4( A,B,C,D,...) A; B; C; D
|
||||
#define CODE_3( A,B,C,...) A; B; C
|
||||
#define CODE_2( A,B,...) A; B
|
||||
#define CODE_1( A,...) A
|
||||
#define CODE_0(...)
|
||||
#define _CODE_N(N,V...) CODE_##N(V)
|
||||
#define CODE_N(N,V...) _CODE_N(N,V)
|
||||
|
||||
#define GANG_16(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,...) A B C D E F G H I J K L M N O P
|
||||
#define GANG_15(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,...) A B C D E F G H I J K L M N O
|
||||
#define GANG_14(A,B,C,D,E,F,G,H,I,J,K,L,M,N,...) A B C D E F G H I J K L M N
|
||||
#define GANG_13(A,B,C,D,E,F,G,H,I,J,K,L,M...) A B C D E F G H I J K L M
|
||||
#define GANG_12(A,B,C,D,E,F,G,H,I,J,K,L...) A B C D E F G H I J K L
|
||||
#define GANG_11(A,B,C,D,E,F,G,H,I,J,K,...) A B C D E F G H I J K
|
||||
#define GANG_10(A,B,C,D,E,F,G,H,I,J,...) A B C D E F G H I J
|
||||
#define GANG_9( A,B,C,D,E,F,G,H,I,...) A B C D E F G H I
|
||||
#define GANG_8( A,B,C,D,E,F,G,H,...) A B C D E F G H
|
||||
#define GANG_7( A,B,C,D,E,F,G,...) A B C D E F G
|
||||
#define GANG_6( A,B,C,D,E,F,...) A B C D E F
|
||||
#define GANG_5( A,B,C,D,E,...) A B C D E
|
||||
#define GANG_4( A,B,C,D,...) A B C D
|
||||
#define GANG_3( A,B,C,...) A B C
|
||||
#define GANG_2( A,B,...) A B
|
||||
#define GANG_1( A,...) A
|
||||
#define GANG_0(...)
|
||||
#define _GANG_N(N,V...) GANG_##N(V)
|
||||
#define GANG_N(N,V...) _GANG_N(N,V)
|
||||
#define GANG_N_1(N,K) _GANG_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K)
|
||||
|
||||
// Macros for initializing arrays
|
||||
#define LIST_20(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T
|
||||
#define LIST_19(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S
|
||||
#define LIST_18(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R
|
||||
#define LIST_17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q
|
||||
#define LIST_16(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
|
||||
#define LIST_15(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O
|
||||
#define LIST_14(A,B,C,D,E,F,G,H,I,J,K,L,M,N,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N
|
||||
@@ -247,10 +308,13 @@
|
||||
#define LIST_3( A,B,C,...) A,B,C
|
||||
#define LIST_2( A,B,...) A,B
|
||||
#define LIST_1( A,...) A
|
||||
#define LIST_0(...)
|
||||
|
||||
#define _LIST_N(N,V...) LIST_##N(V)
|
||||
#define LIST_N(N,V...) _LIST_N(N,V)
|
||||
#define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K)
|
||||
#define ARRAY_N(N,V...) { _LIST_N(N,V) }
|
||||
#define ARRAY_N_1(N,K) { LIST_N_1(N,K) }
|
||||
|
||||
#define _JOIN_1(O) (O)
|
||||
#define JOIN_N(N,C,V...) (DO(JOIN,C,LIST_N(N,V)))
|
||||
@@ -276,7 +340,7 @@
|
||||
#define NEAR(x,y) NEAR_ZERO((x)-(y))
|
||||
|
||||
#define RECIPROCAL(x) (NEAR_ZERO(x) ? 0 : (1 / float(x)))
|
||||
#define FIXFLOAT(f) (f + (f < 0 ? -0.00005f : 0.00005f))
|
||||
#define FIXFLOAT(f) ({__typeof__(f) _f = (f); _f + (_f < 0 ? -0.0000005f : 0.0000005f);})
|
||||
|
||||
//
|
||||
// Maths macros that can be overridden by HAL
|
||||
@@ -288,19 +352,18 @@
|
||||
#define RSQRT(x) (1.0f / sqrtf(x))
|
||||
#define CEIL(x) ceilf(x)
|
||||
#define FLOOR(x) floorf(x)
|
||||
#define TRUNC(x) truncf(x)
|
||||
#define LROUND(x) lroundf(x)
|
||||
#define FMOD(x, y) fmodf(x, y)
|
||||
#define HYPOT(x,y) SQRT(HYPOT2(x,y))
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
#define I2C_ADDRESS(A) ((A) << 1)
|
||||
#else
|
||||
#define I2C_ADDRESS(A) A
|
||||
#endif
|
||||
|
||||
// Use NUM_ARGS(__VA_ARGS__) to get the number of variadic arguments
|
||||
#define _NUM_ARGS(_,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
|
||||
#define NUM_ARGS(V...) _NUM_ARGS(0,V,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
|
||||
#define _NUM_ARGS(_,n,m,l,k,j,i,h,g,f,e,d,c,b,a,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
|
||||
#define NUM_ARGS(V...) _NUM_ARGS(0,V,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
|
||||
|
||||
// Use TWO_ARGS(__VA_ARGS__) to get whether there are 1, 2, or >2 arguments
|
||||
#define _TWO_ARGS(_,n,m,l,k,j,i,h,g,f,e,d,c,b,a,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
|
||||
#define TWO_ARGS(V...) _TWO_ARGS(0,V,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -323,46 +386,133 @@
|
||||
|
||||
#endif
|
||||
|
||||
// Allow manipulating enumeration value like flags without ugly cast everywhere
|
||||
#define ENUM_FLAGS(T) \
|
||||
FORCE_INLINE constexpr T operator&(T x, T y) { return static_cast<T>(static_cast<int>(x) & static_cast<int>(y)); } \
|
||||
FORCE_INLINE constexpr T operator|(T x, T y) { return static_cast<T>(static_cast<int>(x) | static_cast<int>(y)); } \
|
||||
FORCE_INLINE constexpr T operator^(T x, T y) { return static_cast<T>(static_cast<int>(x) ^ static_cast<int>(y)); } \
|
||||
FORCE_INLINE constexpr T operator~(T x) { return static_cast<T>(~static_cast<int>(x)); } \
|
||||
FORCE_INLINE T & operator&=(T &x, T y) { return x &= y; } \
|
||||
FORCE_INLINE T & operator|=(T &x, T y) { return x |= y; } \
|
||||
FORCE_INLINE T & operator^=(T &x, T y) { return x ^= y; }
|
||||
|
||||
// C++11 solution that is standard compliant. <type_traits> is not available on all platform
|
||||
namespace Private {
|
||||
template<bool, typename _Tp = void> struct enable_if { };
|
||||
template<typename _Tp> struct enable_if<true, _Tp> { typedef _Tp type; };
|
||||
|
||||
template<typename T, typename U> struct is_same { enum { value = false }; };
|
||||
template<typename T> struct is_same<T, T> { enum { value = true }; };
|
||||
|
||||
template <typename T, typename ... Args> struct first_type_of { typedef T type; };
|
||||
template <typename T> struct first_type_of<T> { typedef T type; };
|
||||
}
|
||||
// C++11 solution using SFINAE to detect the existence of a member in a class at compile time.
|
||||
// It creates a HasMember<Type> structure containing 'value' set to true if the member exists
|
||||
#define HAS_MEMBER_IMPL(Member) \
|
||||
namespace Private { \
|
||||
template <typename Type, typename Yes=char, typename No=long> struct HasMember_ ## Member { \
|
||||
template <typename C> static Yes& test( decltype(&C::Member) ) ; \
|
||||
template <typename C> static No& test(...); \
|
||||
enum { value = sizeof(test<Type>(0)) == sizeof(Yes) }; }; \
|
||||
}
|
||||
|
||||
// Call the method if it exists, but do nothing if it does not. The method is detected at compile time.
|
||||
// If the method exists, this is inlined and does not cost anything. Else, an "empty" wrapper is created, returning a default value
|
||||
#define CALL_IF_EXISTS_IMPL(Return, Method, ...) \
|
||||
HAS_MEMBER_IMPL(Method) \
|
||||
namespace Private { \
|
||||
template <typename T, typename ... Args> FORCE_INLINE typename enable_if<HasMember_ ## Method <T>::value, Return>::type Call_ ## Method(T * t, Args... a) { return static_cast<Return>(t->Method(a...)); } \
|
||||
_UNUSED static Return Call_ ## Method(...) { return __VA_ARGS__; } \
|
||||
}
|
||||
#define CALL_IF_EXISTS(Return, That, Method, ...) \
|
||||
static_cast<Return>(Private::Call_ ## Method(That, ##__VA_ARGS__))
|
||||
|
||||
// Compile-time string manipulation
|
||||
namespace CompileTimeString {
|
||||
// Simple compile-time parser to find the position of the end of a string
|
||||
constexpr const char* findStringEnd(const char *str) {
|
||||
return *str ? findStringEnd(str + 1) : str;
|
||||
}
|
||||
|
||||
// Check whether a string contains a specific character
|
||||
constexpr bool contains(const char *str, const char ch) {
|
||||
return *str == ch ? true : (*str ? contains(str + 1, ch) : false);
|
||||
}
|
||||
// Find the last position of the specific character (should be called with findStringEnd)
|
||||
constexpr const char* findLastPos(const char *str, const char ch) {
|
||||
return *str == ch ? (str + 1) : findLastPos(str - 1, ch);
|
||||
}
|
||||
// Compile-time evaluation of the last part of a file path
|
||||
// Typically used to shorten the path to file in compiled strings
|
||||
// CompileTimeString::baseName(__FILE__) returns "macros.h" and not /path/to/Marlin/src/core/macros.h
|
||||
constexpr const char* baseName(const char *str) {
|
||||
return contains(str, '/') ? findLastPos(findStringEnd(str), '/') : str;
|
||||
}
|
||||
|
||||
// Find the first occurrence of a character in a string (or return the last position in the string)
|
||||
constexpr const char* findFirst(const char *str, const char ch) {
|
||||
return *str == ch || *str == 0 ? (str + 1) : findFirst(str + 1, ch);
|
||||
}
|
||||
// Compute the string length at compile time
|
||||
constexpr unsigned stringLen(const char *str) {
|
||||
return *str == 0 ? 0 : 1 + stringLen(str + 1);
|
||||
}
|
||||
}
|
||||
|
||||
#define ONLY_FILENAME CompileTimeString::baseName(__FILE__)
|
||||
/** Get the templated type name. This does not depends on RTTI, but on the preprocessor, so it should be quite safe to use even on old compilers.
|
||||
WARNING: DO NOT RENAME THIS FUNCTION (or change the text inside the function to match what the preprocessor will generate)
|
||||
The name is chosen very short since the binary will store "const char* gtn(T*) [with T = YourTypeHere]" so avoid long function name here */
|
||||
template <typename T>
|
||||
inline const char* gtn(T*) {
|
||||
// It works on GCC by instantiating __PRETTY_FUNCTION__ and parsing the result. So the syntax here is very limited to GCC output
|
||||
constexpr unsigned verboseChatLen = sizeof("const char* gtn(T*) [with T = ") - 1;
|
||||
static char templateType[sizeof(__PRETTY_FUNCTION__) - verboseChatLen] = {};
|
||||
__builtin_memcpy(templateType, __PRETTY_FUNCTION__ + verboseChatLen, sizeof(__PRETTY_FUNCTION__) - verboseChatLen - 2);
|
||||
return templateType;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define MIN_2(a,b) ((a)<(b)?(a):(b))
|
||||
#define MIN_3(a,V...) MIN_2(a,MIN_2(V))
|
||||
#define MIN_4(a,V...) MIN_2(a,MIN_3(V))
|
||||
#define MIN_5(a,V...) MIN_2(a,MIN_4(V))
|
||||
#define MIN_6(a,V...) MIN_2(a,MIN_5(V))
|
||||
#define MIN_7(a,V...) MIN_2(a,MIN_6(V))
|
||||
#define MIN_8(a,V...) MIN_2(a,MIN_7(V))
|
||||
#define MIN_9(a,V...) MIN_2(a,MIN_8(V))
|
||||
#define MIN_10(a,V...) MIN_2(a,MIN_9(V))
|
||||
#define __MIN_N(N,V...) MIN_##N(V)
|
||||
#define _MIN_N(N,V...) __MIN_N(N,V)
|
||||
#define _MIN(V...) _MIN_N(NUM_ARGS(V), V)
|
||||
#define _MIN_N_REF() _MIN_N
|
||||
#define _MIN(V...) EVAL(_MIN_N(TWO_ARGS(V),V))
|
||||
#define MIN_2(a,b) ((a)<(b)?(a):(b))
|
||||
#define MIN_3(a,V...) MIN_2(a,DEFER2(_MIN_N_REF)()(TWO_ARGS(V),V))
|
||||
|
||||
#define MAX_2(a,b) ((a)>(b)?(a):(b))
|
||||
#define MAX_3(a,V...) MAX_2(a,MAX_2(V))
|
||||
#define MAX_4(a,V...) MAX_2(a,MAX_3(V))
|
||||
#define MAX_5(a,V...) MAX_2(a,MAX_4(V))
|
||||
#define MAX_6(a,V...) MAX_2(a,MAX_5(V))
|
||||
#define MAX_7(a,V...) MAX_2(a,MAX_6(V))
|
||||
#define MAX_8(a,V...) MAX_2(a,MAX_7(V))
|
||||
#define MAX_9(a,V...) MAX_2(a,MAX_8(V))
|
||||
#define MAX_10(a,V...) MAX_2(a,MAX_9(V))
|
||||
#define __MAX_N(N,V...) MAX_##N(V)
|
||||
#define _MAX_N(N,V...) __MAX_N(N,V)
|
||||
#define _MAX(V...) _MAX_N(NUM_ARGS(V), V)
|
||||
#define _MAX_N_REF() _MAX_N
|
||||
#define _MAX(V...) EVAL(_MAX_N(TWO_ARGS(V),V))
|
||||
#define MAX_2(a,b) ((a)>(b)?(a):(b))
|
||||
#define MAX_3(a,V...) MAX_2(a,DEFER2(_MAX_N_REF)()(TWO_ARGS(V),V))
|
||||
|
||||
#endif
|
||||
|
||||
// Macros for adding
|
||||
#define INC_0 1
|
||||
#define INC_1 2
|
||||
#define INC_2 3
|
||||
#define INC_3 4
|
||||
#define INC_4 5
|
||||
#define INC_5 6
|
||||
#define INC_6 7
|
||||
#define INC_7 8
|
||||
#define INC_8 9
|
||||
#define INC_0 1
|
||||
#define INC_1 2
|
||||
#define INC_2 3
|
||||
#define INC_3 4
|
||||
#define INC_4 5
|
||||
#define INC_5 6
|
||||
#define INC_6 7
|
||||
#define INC_7 8
|
||||
#define INC_8 9
|
||||
#define INC_9 10
|
||||
#define INC_10 11
|
||||
#define INC_11 12
|
||||
#define INC_12 13
|
||||
#define INC_13 14
|
||||
#define INC_14 15
|
||||
#define INC_15 16
|
||||
#define INC_16 17
|
||||
#define INC_17 18
|
||||
#define INC_18 19
|
||||
#define INC_19 20
|
||||
#define INC_20 21
|
||||
#define INCREMENT_(n) INC_##n
|
||||
#define INCREMENT(n) INCREMENT_(n)
|
||||
|
||||
@@ -377,18 +527,27 @@
|
||||
#define ADD8(N) ADD4(ADD4(N))
|
||||
#define ADD9(N) ADD4(ADD5(N))
|
||||
#define ADD10(N) ADD5(ADD5(N))
|
||||
#define SUM(A,B) _CAT(ADD,A)(B)
|
||||
#define DOUBLE_(n) ADD##n(n)
|
||||
#define DOUBLE(n) DOUBLE_(n)
|
||||
|
||||
// Macros for subtracting
|
||||
#define DEC_0 0
|
||||
#define DEC_1 0
|
||||
#define DEC_2 1
|
||||
#define DEC_3 2
|
||||
#define DEC_4 3
|
||||
#define DEC_5 4
|
||||
#define DEC_6 5
|
||||
#define DEC_7 6
|
||||
#define DEC_8 7
|
||||
#define DEC_9 8
|
||||
#define DEC_0 0
|
||||
#define DEC_1 0
|
||||
#define DEC_2 1
|
||||
#define DEC_3 2
|
||||
#define DEC_4 3
|
||||
#define DEC_5 4
|
||||
#define DEC_6 5
|
||||
#define DEC_7 6
|
||||
#define DEC_8 7
|
||||
#define DEC_9 8
|
||||
#define DEC_10 9
|
||||
#define DEC_11 10
|
||||
#define DEC_12 11
|
||||
#define DEC_13 12
|
||||
#define DEC_14 13
|
||||
#define DEC_15 14
|
||||
#define DECREMENT_(n) DEC_##n
|
||||
#define DECREMENT(n) DECREMENT_(n)
|
||||
|
||||
@@ -450,6 +609,12 @@
|
||||
#define HAS_ARGS(V...) _BOOL(FIRST(_END_OF_ARGUMENTS_ V)())
|
||||
#define _END_OF_ARGUMENTS_() 0
|
||||
|
||||
|
||||
// Simple Inline IF Macros, friendly to use in other macro definitions
|
||||
#define IF(O, A, B) ((O) ? (A) : (B))
|
||||
#define IF_0(O, A) IF(O, A, 0)
|
||||
#define IF_1(O, A) IF(O, A, 1)
|
||||
|
||||
//
|
||||
// REPEAT core macros. Recurse N times with ascending I.
|
||||
//
|
||||
@@ -473,6 +638,7 @@
|
||||
// Repeat a macro passing S...N-1.
|
||||
#define REPEAT_S(S,N,OP) EVAL(_REPEAT(S,SUB##S(N),OP))
|
||||
#define REPEAT(N,OP) REPEAT_S(0,N,OP)
|
||||
#define REPEAT_1(N,OP) REPEAT_S(1,INCREMENT(N),OP)
|
||||
|
||||
// Repeat a macro passing 0...N-1 plus additional arguments.
|
||||
#define REPEAT2_S(S,N,OP,V...) EVAL(_REPEAT2(S,SUB##S(N),OP,V))
|
||||
@@ -495,3 +661,14 @@
|
||||
#define RREPEAT(N,OP) RREPEAT_S(0,N,OP)
|
||||
#define RREPEAT2_S(S,N,OP,V...) EVAL1024(_RREPEAT2(S,SUB##S(N),OP,V))
|
||||
#define RREPEAT2(N,OP,V...) RREPEAT2_S(0,N,OP,V)
|
||||
|
||||
// See https://github.com/swansontec/map-macro
|
||||
#define MAP_OUT
|
||||
#define MAP_END(...)
|
||||
#define MAP_GET_END() 0, MAP_END
|
||||
#define MAP_NEXT0(test, next, ...) next MAP_OUT
|
||||
#define MAP_NEXT1(test, next) MAP_NEXT0 (test, next, 0)
|
||||
#define MAP_NEXT(test, next) MAP_NEXT1 (MAP_GET_END test, next)
|
||||
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__)
|
||||
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)
|
||||
#define MAP(f, ...) EVAL512 (MAP1 (f, __VA_ARGS__, (), 0))
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -25,5 +25,9 @@
|
||||
|
||||
typedef uint32_t millis_t;
|
||||
|
||||
#define SEC_TO_MS(N) millis_t((N)*1000UL)
|
||||
#define MIN_TO_MS(N) SEC_TO_MS((N)*60UL)
|
||||
#define MS_TO_SEC(N) millis_t((N)/1000UL)
|
||||
|
||||
#define PENDING(NOW,SOON) ((int32_t)(NOW-(SOON))<0)
|
||||
#define ELAPSED(NOW,SOON) (!PENDING(NOW,SOON))
|
||||
|
@@ -1,28 +1,37 @@
|
||||
/********************
|
||||
* multi_language.h *
|
||||
********************/
|
||||
|
||||
/****************************************************************************
|
||||
* Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* To view a copy of the GNU General Public License, go to the following *
|
||||
* location: <http://www.gnu.org/licenses/>. *
|
||||
****************************************************************************/
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
typedef const char Language_Str[];
|
||||
/*******************************************************
|
||||
* multi_language.h *
|
||||
* By Marcio Teixeira 2019 for Aleph Objects *
|
||||
*******************************************************/
|
||||
|
||||
#if defined(LCD_LANGUAGE_5)
|
||||
#include "../inc/MarlinConfigPre.h"
|
||||
|
||||
typedef const char Language_Str[];
|
||||
#define LSTR PROGMEM Language_Str
|
||||
|
||||
#ifdef LCD_LANGUAGE_5
|
||||
#define NUM_LANGUAGES 5
|
||||
#elif defined(LCD_LANGUAGE_4)
|
||||
#define NUM_LANGUAGES 4
|
||||
@@ -34,21 +43,17 @@ typedef const char Language_Str[];
|
||||
#define NUM_LANGUAGES 1
|
||||
#endif
|
||||
|
||||
// Setting the unused languages equal to each other allows
|
||||
// the compiler to optimize away the conditionals
|
||||
|
||||
// Set unused languages equal to each other so the
|
||||
// compiler can optimize away the conditionals.
|
||||
#ifndef LCD_LANGUAGE_2
|
||||
#define LCD_LANGUAGE_2 LCD_LANGUAGE
|
||||
#endif
|
||||
|
||||
#ifndef LCD_LANGUAGE_3
|
||||
#define LCD_LANGUAGE_3 LCD_LANGUAGE_2
|
||||
#endif
|
||||
|
||||
#ifndef LCD_LANGUAGE_4
|
||||
#define LCD_LANGUAGE_4 LCD_LANGUAGE_3
|
||||
#endif
|
||||
|
||||
#ifndef LCD_LANGUAGE_5
|
||||
#define LCD_LANGUAGE_5 LCD_LANGUAGE_4
|
||||
#endif
|
||||
@@ -57,23 +62,28 @@ typedef const char Language_Str[];
|
||||
#define GET_LANG(LANG) _GET_LANG(LANG)
|
||||
|
||||
#if NUM_LANGUAGES > 1
|
||||
extern uint8_t lang;
|
||||
#define HAS_MULTI_LANGUAGE 1
|
||||
#define GET_TEXT(MSG) ( \
|
||||
lang == 0 ? GET_LANG(LCD_LANGUAGE)::MSG : \
|
||||
lang == 1 ? GET_LANG(LCD_LANGUAGE_2)::MSG : \
|
||||
lang == 2 ? GET_LANG(LCD_LANGUAGE_3)::MSG : \
|
||||
lang == 3 ? GET_LANG(LCD_LANGUAGE_4)::MSG : \
|
||||
GET_LANG(LCD_LANGUAGE_5)::MSG \
|
||||
)
|
||||
#define MAX_LANG_CHARSIZE _MAX(GET_LANG(LCD_LANGUAGE)::CHARSIZE, \
|
||||
GET_LANG(LCD_LANGUAGE_2)::CHARSIZE, \
|
||||
GET_LANG(LCD_LANGUAGE_3)::CHARSIZE, \
|
||||
GET_LANG(LCD_LANGUAGE_4)::CHARSIZE, \
|
||||
GET_LANG(LCD_LANGUAGE_5)::CHARSIZE)
|
||||
ui.language == 4 ? GET_LANG(LCD_LANGUAGE_5)::MSG : \
|
||||
ui.language == 3 ? GET_LANG(LCD_LANGUAGE_4)::MSG : \
|
||||
ui.language == 2 ? GET_LANG(LCD_LANGUAGE_3)::MSG : \
|
||||
ui.language == 1 ? GET_LANG(LCD_LANGUAGE_2)::MSG : \
|
||||
GET_LANG(LCD_LANGUAGE )::MSG )
|
||||
#define MAX_LANG_CHARSIZE _MAX(GET_LANG(LCD_LANGUAGE )::CHARSIZE, \
|
||||
GET_LANG(LCD_LANGUAGE_2)::CHARSIZE, \
|
||||
GET_LANG(LCD_LANGUAGE_3)::CHARSIZE, \
|
||||
GET_LANG(LCD_LANGUAGE_4)::CHARSIZE, \
|
||||
GET_LANG(LCD_LANGUAGE_5)::CHARSIZE )
|
||||
#else
|
||||
#define GET_TEXT(MSG) GET_LANG(LCD_LANGUAGE)::MSG
|
||||
#define MAX_LANG_CHARSIZE GET_LANG(LCD_LANGUAGE)::CHARSIZE
|
||||
#define MAX_LANG_CHARSIZE LANG_CHARSIZE
|
||||
#endif
|
||||
#define GET_TEXT_F(MSG) (const __FlashStringHelper*)GET_TEXT(MSG)
|
||||
#define GET_TEXT_F(MSG) FPSTR(GET_TEXT(MSG))
|
||||
|
||||
#define MSG_CONCAT(A,B) pgm_p_pair_t(GET_TEXT(A),GET_TEXT(B))
|
||||
#define GET_LANGUAGE_NAME(INDEX) GET_LANG(LCD_LANGUAGE_##INDEX)::LANGUAGE
|
||||
#define LANG_CHARSIZE GET_TEXT(CHARSIZE)
|
||||
#define USE_WIDE_GLYPH (LANG_CHARSIZE > 2)
|
||||
|
||||
#define MSG_1_LINE(A) A "\0" "\0"
|
||||
#define MSG_2_LINE(A,B) A "\0" B "\0"
|
||||
#define MSG_3_LINE(A,B,C) A "\0" B "\0" C
|
||||
|
@@ -16,36 +16,65 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "serial.h"
|
||||
#include "language.h"
|
||||
#include "../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_ETHERNET
|
||||
#include "../feature/ethernet.h"
|
||||
#endif
|
||||
|
||||
uint8_t marlin_debug_flags = MARLIN_DEBUG_NONE;
|
||||
|
||||
static const char errormagic[] PROGMEM = "Error:";
|
||||
static const char echomagic[] PROGMEM = "echo:";
|
||||
// Commonly-used strings in serial output
|
||||
PGMSTR(NUL_STR, ""); PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T");
|
||||
PGMSTR(X_STR, "X"); PGMSTR(Y_STR, "Y"); PGMSTR(Z_STR, "Z"); PGMSTR(E_STR, "E");
|
||||
PGMSTR(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMSTR(E_LBL, "E:");
|
||||
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)
|
||||
SerialLeafT1 mpSerial1(false, _SERIAL_LEAF_1);
|
||||
#endif
|
||||
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
|
||||
SerialLeafT2 mpSerial2(false, _SERIAL_LEAF_2);
|
||||
#endif
|
||||
#if ENABLED(MEATPACK_ON_SERIAL_PORT_3)
|
||||
SerialLeafT3 mpSerial3(false, _SERIAL_LEAF_3);
|
||||
#endif
|
||||
|
||||
// Step 2: For multiserial, handle the second serial port as well
|
||||
#if HAS_MULTI_SERIAL
|
||||
#if HAS_ETHERNET
|
||||
// We need a definition here
|
||||
SerialLeafT2 msSerial2(ethernet.have_telnet_client, MYSERIAL2, false);
|
||||
#endif
|
||||
|
||||
#define __S_LEAF(N) ,SERIAL_LEAF_##N
|
||||
#define _S_LEAF(N) __S_LEAF(N)
|
||||
|
||||
SerialOutputT multiSerial( SERIAL_LEAF_1 REPEAT_S(2, INCREMENT(NUM_SERIAL), _S_LEAF) );
|
||||
|
||||
#undef __S_LEAF
|
||||
#undef _S_LEAF
|
||||
|
||||
#if NUM_SERIAL > 1
|
||||
serial_index_t serial_port_index = 0;
|
||||
#endif
|
||||
|
||||
void serialprintPGM(PGM_P str) {
|
||||
while (const char c = pgm_read_byte(str++)) SERIAL_CHAR(c);
|
||||
}
|
||||
void serial_echo_start() { serialprintPGM(echomagic); }
|
||||
void serial_error_start() { serialprintPGM(errormagic); }
|
||||
|
||||
void serial_echopair_PGM(PGM_P const s_P, const char *v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
|
||||
void serial_echopair_PGM(PGM_P const s_P, char v) { serialprintPGM(s_P); SERIAL_CHAR(v); }
|
||||
void serial_echopair_PGM(PGM_P const s_P, int v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
|
||||
void serial_echopair_PGM(PGM_P const s_P, long v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
|
||||
void serial_echopair_PGM(PGM_P const s_P, float v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
|
||||
void serial_echopair_PGM(PGM_P const s_P, double v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
|
||||
void serial_echopair_PGM(PGM_P const s_P, unsigned int v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
|
||||
void serial_echopair_PGM(PGM_P const s_P, unsigned long v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
|
||||
void serial_echo_start() { static PGMSTR(echomagic, "echo:"); serialprintPGM(echomagic); }
|
||||
void serial_error_start() { static PGMSTR(errormagic, "Error:"); serialprintPGM(errormagic); }
|
||||
|
||||
void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); }
|
||||
|
||||
@@ -65,10 +94,10 @@ void print_bin(uint16_t val) {
|
||||
}
|
||||
}
|
||||
|
||||
extern const char SP_X_STR[], SP_Y_STR[], SP_Z_STR[];
|
||||
|
||||
void print_xyz(const float &x, const float &y, const float &z, PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/) {
|
||||
serialprintPGM(prefix);
|
||||
SERIAL_ECHOPAIR_P(SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z);
|
||||
void print_pos(LINEAR_AXIS_ARGS(const_float_t), PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/) {
|
||||
if (prefix) serialprintPGM(prefix);
|
||||
SERIAL_ECHOPGM_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();
|
||||
}
|
||||
|
@@ -16,16 +16,34 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
#include "serial_hook.h"
|
||||
|
||||
/**
|
||||
* Define debug bit-masks
|
||||
*/
|
||||
#if HAS_MEATPACK
|
||||
#include "../feature/meatpack.h"
|
||||
#endif
|
||||
|
||||
// Commonly-used strings in serial output
|
||||
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[],
|
||||
I_STR[], J_STR[], K_STR[],
|
||||
X_LBL[], Y_LBL[], Z_LBL[], E_LBL[],
|
||||
I_LBL[], J_LBL[], K_LBL[];
|
||||
|
||||
//
|
||||
// Debugging flags for use by M111
|
||||
//
|
||||
enum MarlinDebugFlags : uint8_t {
|
||||
MARLIN_DEBUG_NONE = 0,
|
||||
MARLIN_DEBUG_ECHO = _BV(0), ///< Echo commands in order as they are processed
|
||||
@@ -45,210 +63,203 @@ enum MarlinDebugFlags : uint8_t {
|
||||
|
||||
extern uint8_t marlin_debug_flags;
|
||||
#define DEBUGGING(F) (marlin_debug_flags & (MARLIN_DEBUG_## F))
|
||||
typedef int8_t serial_index_t;
|
||||
#define SERIAL_BOTH 0x7F
|
||||
#if NUM_SERIAL > 1
|
||||
extern serial_index_t serial_port_index;
|
||||
#define _PORT_REDIRECT(n,p) REMEMBER(n,serial_port_index,p)
|
||||
#define _PORT_RESTORE(n) RESTORE(n)
|
||||
#define SERIAL_OUT(WHAT, V...) do{ \
|
||||
if (!serial_port_index || serial_port_index == SERIAL_BOTH) (void)MYSERIAL0.WHAT(V); \
|
||||
if ( serial_port_index) (void)MYSERIAL1.WHAT(V); \
|
||||
}while(0)
|
||||
#define SERIAL_ASSERT(P) if(serial_port_index!=(P)){ debugger(); }
|
||||
|
||||
//
|
||||
// Serial redirection
|
||||
//
|
||||
// Step 1: Find out what the first serial leaf is
|
||||
#if HAS_MULTI_SERIAL && defined(SERIAL_CATCHALL)
|
||||
#define _SERIAL_LEAF_1 MYSERIAL
|
||||
#else
|
||||
#define _PORT_REDIRECT(n,p) NOOP
|
||||
#define _PORT_RESTORE(n) NOOP
|
||||
#define SERIAL_OUT(WHAT, V...) (void)MYSERIAL0.WHAT(V)
|
||||
#define SERIAL_ASSERT(P) NOOP
|
||||
#define _SERIAL_LEAF_1 MYSERIAL1
|
||||
#endif
|
||||
|
||||
#define PORT_REDIRECT(p) _PORT_REDIRECT(1,p)
|
||||
#define PORT_RESTORE() _PORT_RESTORE(1)
|
||||
|
||||
#define SERIAL_ECHO(x) SERIAL_OUT(print, x)
|
||||
#define SERIAL_ECHO_F(V...) SERIAL_OUT(print, V)
|
||||
#define SERIAL_ECHOLN(x) SERIAL_OUT(println, x)
|
||||
#define SERIAL_PRINT(x,b) SERIAL_OUT(print, x, b)
|
||||
#define SERIAL_PRINTLN(x,b) SERIAL_OUT(println, x, b)
|
||||
#define SERIAL_PRINTF(V...) SERIAL_OUT(printf, V)
|
||||
#define SERIAL_FLUSH() SERIAL_OUT(flush)
|
||||
|
||||
#ifdef ARDUINO_ARCH_STM32
|
||||
#define SERIAL_FLUSHTX() SERIAL_OUT(flush)
|
||||
#elif TX_BUFFER_SIZE > 0
|
||||
#define SERIAL_FLUSHTX() SERIAL_OUT(flushTX)
|
||||
// Hook Meatpack if it's enabled on the first leaf
|
||||
#if ENABLED(MEATPACK_ON_SERIAL_PORT_1)
|
||||
typedef MeatpackSerial<decltype(_SERIAL_LEAF_1)> SerialLeafT1;
|
||||
extern SerialLeafT1 mpSerial1;
|
||||
#define SERIAL_LEAF_1 mpSerial1
|
||||
#else
|
||||
#define SERIAL_FLUSHTX()
|
||||
#define SERIAL_LEAF_1 _SERIAL_LEAF_1
|
||||
#endif
|
||||
|
||||
// Print up to 10 chars from a list
|
||||
#define __CHAR_N(N,V...) _CHAR_##N(V)
|
||||
#define _CHAR_N(N,V...) __CHAR_N(N,V)
|
||||
#define _CHAR_1(c) SERIAL_OUT(write, c)
|
||||
#define _CHAR_2(a,b) do{ _CHAR_1(a); _CHAR_1(b); }while(0)
|
||||
#define _CHAR_3(a,V...) do{ _CHAR_1(a); _CHAR_2(V); }while(0)
|
||||
#define _CHAR_4(a,V...) do{ _CHAR_1(a); _CHAR_3(V); }while(0)
|
||||
#define _CHAR_5(a,V...) do{ _CHAR_1(a); _CHAR_4(V); }while(0)
|
||||
#define _CHAR_6(a,V...) do{ _CHAR_1(a); _CHAR_5(V); }while(0)
|
||||
#define _CHAR_7(a,V...) do{ _CHAR_1(a); _CHAR_6(V); }while(0)
|
||||
#define _CHAR_8(a,V...) do{ _CHAR_1(a); _CHAR_7(V); }while(0)
|
||||
#define _CHAR_9(a,V...) do{ _CHAR_1(a); _CHAR_8(V); }while(0)
|
||||
#define _CHAR_10(a,V...) do{ _CHAR_1(a); _CHAR_9(V); }while(0)
|
||||
// Step 2: For multiserial wrap all serial ports in a single
|
||||
// interface with the ability to output to multiple serial ports.
|
||||
#if HAS_MULTI_SERIAL
|
||||
#define _PORT_REDIRECT(n,p) REMEMBER(n,multiSerial.portMask,p)
|
||||
#define _PORT_RESTORE(n,p) RESTORE(n)
|
||||
#define SERIAL_ASSERT(P) if (multiSerial.portMask!=(P)) { debugger(); }
|
||||
// If we have a catchall, use that directly
|
||||
#ifdef SERIAL_CATCHALL
|
||||
#define _SERIAL_LEAF_2 SERIAL_CATCHALL
|
||||
#elif HAS_ETHERNET
|
||||
typedef ConditionalSerial<decltype(MYSERIAL2)> SerialLeafT2; // We need to create an instance here
|
||||
extern SerialLeafT2 msSerial2;
|
||||
#define _SERIAL_LEAF_2 msSerial2
|
||||
#else
|
||||
#define _SERIAL_LEAF_2 MYSERIAL2 // Don't create a useless instance here, directly use the existing instance
|
||||
#endif
|
||||
|
||||
#define SERIAL_CHAR(V...) _CHAR_N(NUM_ARGS(V),V)
|
||||
// Nothing complicated here
|
||||
#define _SERIAL_LEAF_3 MYSERIAL3
|
||||
|
||||
// Print up to 12 pairs of values. Odd elements auto-wrapped in PSTR().
|
||||
#define __SEP_N(N,V...) _SEP_##N(V)
|
||||
#define _SEP_N(N,V...) __SEP_N(N,V)
|
||||
#define _SEP_1(PRE) SERIAL_ECHOPGM(PRE)
|
||||
#define _SEP_2(PRE,V) serial_echopair_PGM(PSTR(PRE),V)
|
||||
#define _SEP_3(a,b,c) do{ _SEP_2(a,b); SERIAL_ECHOPGM(c); }while(0)
|
||||
#define _SEP_4(a,b,V...) do{ _SEP_2(a,b); _SEP_2(V); }while(0)
|
||||
#define _SEP_5(a,b,V...) do{ _SEP_2(a,b); _SEP_3(V); }while(0)
|
||||
#define _SEP_6(a,b,V...) do{ _SEP_2(a,b); _SEP_4(V); }while(0)
|
||||
#define _SEP_7(a,b,V...) do{ _SEP_2(a,b); _SEP_5(V); }while(0)
|
||||
#define _SEP_8(a,b,V...) do{ _SEP_2(a,b); _SEP_6(V); }while(0)
|
||||
#define _SEP_9(a,b,V...) do{ _SEP_2(a,b); _SEP_7(V); }while(0)
|
||||
#define _SEP_10(a,b,V...) do{ _SEP_2(a,b); _SEP_8(V); }while(0)
|
||||
#define _SEP_11(a,b,V...) do{ _SEP_2(a,b); _SEP_9(V); }while(0)
|
||||
#define _SEP_12(a,b,V...) do{ _SEP_2(a,b); _SEP_10(V); }while(0)
|
||||
#define _SEP_13(a,b,V...) do{ _SEP_2(a,b); _SEP_11(V); }while(0)
|
||||
#define _SEP_14(a,b,V...) do{ _SEP_2(a,b); _SEP_12(V); }while(0)
|
||||
#define _SEP_15(a,b,V...) do{ _SEP_2(a,b); _SEP_13(V); }while(0)
|
||||
#define _SEP_16(a,b,V...) do{ _SEP_2(a,b); _SEP_14(V); }while(0)
|
||||
#define _SEP_17(a,b,V...) do{ _SEP_2(a,b); _SEP_15(V); }while(0)
|
||||
#define _SEP_18(a,b,V...) do{ _SEP_2(a,b); _SEP_16(V); }while(0)
|
||||
#define _SEP_19(a,b,V...) do{ _SEP_2(a,b); _SEP_17(V); }while(0)
|
||||
#define _SEP_20(a,b,V...) do{ _SEP_2(a,b); _SEP_18(V); }while(0)
|
||||
#define _SEP_21(a,b,V...) do{ _SEP_2(a,b); _SEP_19(V); }while(0)
|
||||
#define _SEP_22(a,b,V...) do{ _SEP_2(a,b); _SEP_20(V); }while(0)
|
||||
#define _SEP_23(a,b,V...) do{ _SEP_2(a,b); _SEP_21(V); }while(0)
|
||||
#define _SEP_24(a,b,V...) do{ _SEP_2(a,b); _SEP_22(V); }while(0)
|
||||
// Hook Meatpack if it's enabled on the second leaf
|
||||
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
|
||||
typedef MeatpackSerial<decltype(_SERIAL_LEAF_2)> SerialLeafT2;
|
||||
extern SerialLeafT2 mpSerial2;
|
||||
#define SERIAL_LEAF_2 mpSerial2
|
||||
#else
|
||||
#define SERIAL_LEAF_2 _SERIAL_LEAF_2
|
||||
#endif
|
||||
|
||||
#define SERIAL_ECHOPAIR(V...) _SEP_N(NUM_ARGS(V),V)
|
||||
// Hook Meatpack if it's enabled on the third leaf
|
||||
#if ENABLED(MEATPACK_ON_SERIAL_PORT_3)
|
||||
typedef MeatpackSerial<decltype(_SERIAL_LEAF_3)> SerialLeafT3;
|
||||
extern SerialLeafT3 mpSerial3;
|
||||
#define SERIAL_LEAF_3 mpSerial3
|
||||
#else
|
||||
#define SERIAL_LEAF_3 _SERIAL_LEAF_3
|
||||
#endif
|
||||
|
||||
// Print up to 12 pairs of values. Odd elements must be PSTR pointers.
|
||||
#define __SEP_N_P(N,V...) _SEP_##N##_P(V)
|
||||
#define _SEP_N_P(N,V...) __SEP_N_P(N,V)
|
||||
#define _SEP_1_P(PRE) serialprintPGM(PRE)
|
||||
#define _SEP_2_P(PRE,V) serial_echopair_PGM(PRE,V)
|
||||
#define _SEP_3_P(a,b,c) do{ _SEP_2_P(a,b); serialprintPGM(c); }while(0)
|
||||
#define _SEP_4_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_2_P(V); }while(0)
|
||||
#define _SEP_5_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_3_P(V); }while(0)
|
||||
#define _SEP_6_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_4_P(V); }while(0)
|
||||
#define _SEP_7_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_5_P(V); }while(0)
|
||||
#define _SEP_8_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_6_P(V); }while(0)
|
||||
#define _SEP_9_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_7_P(V); }while(0)
|
||||
#define _SEP_10_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_8_P(V); }while(0)
|
||||
#define _SEP_11_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_9_P(V); }while(0)
|
||||
#define _SEP_12_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_10_P(V); }while(0)
|
||||
#define _SEP_13_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_11_P(V); }while(0)
|
||||
#define _SEP_14_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_12_P(V); }while(0)
|
||||
#define _SEP_15_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_13_P(V); }while(0)
|
||||
#define _SEP_16_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_14_P(V); }while(0)
|
||||
#define _SEP_17_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_15_P(V); }while(0)
|
||||
#define _SEP_18_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_16_P(V); }while(0)
|
||||
#define _SEP_19_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_17_P(V); }while(0)
|
||||
#define _SEP_20_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_18_P(V); }while(0)
|
||||
#define _SEP_21_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_19_P(V); }while(0)
|
||||
#define _SEP_22_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_20_P(V); }while(0)
|
||||
#define _SEP_23_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_21_P(V); }while(0)
|
||||
#define _SEP_24_P(a,b,V...) do{ _SEP_2_P(a,b); _SEP_22_P(V); }while(0)
|
||||
#define __S_MULTI(N) decltype(SERIAL_LEAF_##N),
|
||||
#define _S_MULTI(N) __S_MULTI(N)
|
||||
|
||||
#define SERIAL_ECHOPAIR_P(V...) _SEP_N_P(NUM_ARGS(V),V)
|
||||
typedef MultiSerial< REPEAT_1(NUM_SERIAL, _S_MULTI) 0> SerialOutputT;
|
||||
|
||||
// Print up to 12 pairs of values followed by newline
|
||||
#define __SELP_N(N,V...) _SELP_##N(V)
|
||||
#define _SELP_N(N,V...) __SELP_N(N,V)
|
||||
#define _SELP_1(PRE) SERIAL_ECHOLNPGM(PRE)
|
||||
#define _SELP_2(PRE,V) do{ serial_echopair_PGM(PSTR(PRE),V); SERIAL_EOL(); }while(0)
|
||||
#define _SELP_3(a,b,c) do{ _SEP_2(a,b); SERIAL_ECHOLNPGM(c); }while(0)
|
||||
#define _SELP_4(a,b,V...) do{ _SEP_2(a,b); _SELP_2(V); }while(0)
|
||||
#define _SELP_5(a,b,V...) do{ _SEP_2(a,b); _SELP_3(V); }while(0)
|
||||
#define _SELP_6(a,b,V...) do{ _SEP_2(a,b); _SELP_4(V); }while(0)
|
||||
#define _SELP_7(a,b,V...) do{ _SEP_2(a,b); _SELP_5(V); }while(0)
|
||||
#define _SELP_8(a,b,V...) do{ _SEP_2(a,b); _SELP_6(V); }while(0)
|
||||
#define _SELP_9(a,b,V...) do{ _SEP_2(a,b); _SELP_7(V); }while(0)
|
||||
#define _SELP_10(a,b,V...) do{ _SEP_2(a,b); _SELP_8(V); }while(0)
|
||||
#define _SELP_11(a,b,V...) do{ _SEP_2(a,b); _SELP_9(V); }while(0)
|
||||
#define _SELP_12(a,b,V...) do{ _SEP_2(a,b); _SELP_10(V); }while(0)
|
||||
#define _SELP_13(a,b,V...) do{ _SEP_2(a,b); _SELP_11(V); }while(0)
|
||||
#define _SELP_14(a,b,V...) do{ _SEP_2(a,b); _SELP_12(V); }while(0)
|
||||
#define _SELP_15(a,b,V...) do{ _SEP_2(a,b); _SELP_13(V); }while(0)
|
||||
#define _SELP_16(a,b,V...) do{ _SEP_2(a,b); _SELP_14(V); }while(0)
|
||||
#define _SELP_17(a,b,V...) do{ _SEP_2(a,b); _SELP_15(V); }while(0)
|
||||
#define _SELP_18(a,b,V...) do{ _SEP_2(a,b); _SELP_16(V); }while(0)
|
||||
#define _SELP_19(a,b,V...) do{ _SEP_2(a,b); _SELP_17(V); }while(0)
|
||||
#define _SELP_20(a,b,V...) do{ _SEP_2(a,b); _SELP_18(V); }while(0)
|
||||
#define _SELP_21(a,b,V...) do{ _SEP_2(a,b); _SELP_19(V); }while(0)
|
||||
#define _SELP_22(a,b,V...) do{ _SEP_2(a,b); _SELP_20(V); }while(0)
|
||||
#define _SELP_23(a,b,V...) do{ _SEP_2(a,b); _SELP_21(V); }while(0)
|
||||
#define _SELP_24(a,b,V...) do{ _SEP_2(a,b); _SELP_22(V); }while(0) // Eat two args, pass the rest up
|
||||
#undef __S_MULTI
|
||||
#undef _S_MULTI
|
||||
|
||||
#define SERIAL_ECHOLNPAIR(V...) _SELP_N(NUM_ARGS(V),V)
|
||||
extern SerialOutputT multiSerial;
|
||||
#define SERIAL_IMPL multiSerial
|
||||
#else
|
||||
#define _PORT_REDIRECT(n,p) NOOP
|
||||
#define _PORT_RESTORE(n) NOOP
|
||||
#define SERIAL_ASSERT(P) NOOP
|
||||
#define SERIAL_IMPL SERIAL_LEAF_1
|
||||
#endif
|
||||
|
||||
// Print up to 12 pairs of values followed by newline
|
||||
#define __SELP_N_P(N,V...) _SELP_##N##_P(V)
|
||||
#define _SELP_N_P(N,V...) __SELP_N_P(N,V)
|
||||
#define _SELP_1_P(PRE) serialprintPGM(PRE)
|
||||
#define _SELP_2_P(PRE,V) do{ serial_echopair_PGM(PRE,V); SERIAL_EOL(); }while(0)
|
||||
#define _SELP_3_P(a,b,c) do{ _SEP_2_P(a,b); serialprintPGM(c); }while(0)
|
||||
#define _SELP_4_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_2_P(V); }while(0)
|
||||
#define _SELP_5_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_3_P(V); }while(0)
|
||||
#define _SELP_6_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_4_P(V); }while(0)
|
||||
#define _SELP_7_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_5_P(V); }while(0)
|
||||
#define _SELP_8_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_6_P(V); }while(0)
|
||||
#define _SELP_9_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_7_P(V); }while(0)
|
||||
#define _SELP_10_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_8_P(V); }while(0)
|
||||
#define _SELP_11_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_9_P(V); }while(0)
|
||||
#define _SELP_12_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_10_P(V); }while(0)
|
||||
#define _SELP_13_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_11_P(V); }while(0)
|
||||
#define _SELP_14_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_12_P(V); }while(0)
|
||||
#define _SELP_15_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_13_P(V); }while(0)
|
||||
#define _SELP_16_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_14_P(V); }while(0)
|
||||
#define _SELP_17_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_15_P(V); }while(0)
|
||||
#define _SELP_18_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_16_P(V); }while(0)
|
||||
#define _SELP_19_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_17_P(V); }while(0)
|
||||
#define _SELP_20_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_18_P(V); }while(0)
|
||||
#define _SELP_21_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_19_P(V); }while(0)
|
||||
#define _SELP_22_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_20_P(V); }while(0)
|
||||
#define _SELP_23_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_21_P(V); }while(0)
|
||||
#define _SELP_24_P(a,b,V...) do{ _SEP_2_P(a,b); _SELP_22_P(V); }while(0) // Eat two args, pass the rest up
|
||||
#define SERIAL_OUT(WHAT, V...) (void)SERIAL_IMPL.WHAT(V)
|
||||
|
||||
#define SERIAL_ECHOLNPAIR_P(V...) _SELP_N_P(NUM_ARGS(V),V)
|
||||
#define PORT_REDIRECT(p) _PORT_REDIRECT(1,p)
|
||||
#define PORT_RESTORE() _PORT_RESTORE(1)
|
||||
#define SERIAL_PORTMASK(P) SerialMask::from(P)
|
||||
|
||||
// Print up to 20 comma-separated pairs of values
|
||||
#define __SLST_N(N,V...) _SLST_##N(V)
|
||||
#define _SLST_N(N,V...) __SLST_N(N,V)
|
||||
#define _SLST_1(a) SERIAL_ECHO(a)
|
||||
#define _SLST_2(a,b) do{ SERIAL_ECHO(a); SERIAL_ECHOPAIR(", ",b); }while(0)
|
||||
#define _SLST_3(a,b,c) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_1(c); }while(0)
|
||||
#define _SLST_4(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_2(V); }while(0)
|
||||
#define _SLST_5(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_3(V); }while(0)
|
||||
#define _SLST_6(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_4(V); }while(0)
|
||||
#define _SLST_7(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_5(V); }while(0)
|
||||
#define _SLST_8(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_6(V); }while(0)
|
||||
#define _SLST_9(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_7(V); }while(0)
|
||||
#define _SLST_10(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_8(V); }while(0)
|
||||
#define _SLST_11(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_9(V); }while(0)
|
||||
#define _SLST_12(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_10(V); }while(0)
|
||||
#define _SLST_13(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_11(V); }while(0)
|
||||
#define _SLST_14(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_12(V); }while(0)
|
||||
#define _SLST_15(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_13(V); }while(0)
|
||||
#define _SLST_16(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_14(V); }while(0)
|
||||
#define _SLST_17(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_15(V); }while(0)
|
||||
#define _SLST_18(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_16(V); }while(0)
|
||||
#define _SLST_19(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_17(V); }while(0)
|
||||
#define _SLST_20(a,b,V...) do{ SERIAL_ECHO(a); _SEP_2(", ",b); _SLST_18(V); }while(0) // Eat two args, pass the rest up
|
||||
//
|
||||
// SERIAL_CHAR - Print one or more individual chars
|
||||
//
|
||||
inline void SERIAL_CHAR(char a) { SERIAL_IMPL.write(a); }
|
||||
template <typename ... Args>
|
||||
void SERIAL_CHAR(char a, Args ... args) { SERIAL_IMPL.write(a); SERIAL_CHAR(args ...); }
|
||||
|
||||
#define SERIAL_ECHOLIST(pre,V...) do{ SERIAL_ECHOPGM(pre); _SLST_N(NUM_ARGS(V),V); }while(0)
|
||||
#define SERIAL_ECHOLIST_N(N,V...) _SLST_N(N,LIST_N(N,V))
|
||||
/**
|
||||
* SERIAL_ECHO - Print a single string or value.
|
||||
* Any numeric parameter (including char) is printed as a base-10 number.
|
||||
* A string pointer or literal will be output as a string.
|
||||
*
|
||||
* NOTE: Use SERIAL_CHAR to print char as a single character.
|
||||
*/
|
||||
template <typename T>
|
||||
void SERIAL_ECHO(T x) { SERIAL_IMPL.print(x); }
|
||||
|
||||
#define SERIAL_ECHO_P(P) (serialprintPGM(P))
|
||||
// Wrapper for ECHO commands to interpret a char
|
||||
typedef struct SerialChar { char c; SerialChar(char n) : c(n) { } } serial_char_t;
|
||||
inline void SERIAL_ECHO(serial_char_t x) { SERIAL_IMPL.write(x.c); }
|
||||
#define AS_CHAR(C) serial_char_t(C)
|
||||
#define AS_DIGIT(C) AS_CHAR('0' + (C))
|
||||
|
||||
#define SERIAL_ECHOPGM(S) (SERIAL_ECHO_P(PSTR(S)))
|
||||
#define SERIAL_ECHOLNPGM(S) (SERIAL_ECHO_P(PSTR(S "\n")))
|
||||
// SERIAL_ECHO_F prints a floating point value with optional precision
|
||||
inline void SERIAL_ECHO_F(EnsureDouble x, int digit=2) { SERIAL_IMPL.print(x, digit); }
|
||||
|
||||
template <typename T>
|
||||
void SERIAL_ECHOLN(T x) { SERIAL_IMPL.println(x); }
|
||||
|
||||
// SERIAL_PRINT works like SERIAL_ECHO but allow to specify the encoding base of the number printed
|
||||
template <typename T, typename U>
|
||||
void SERIAL_PRINT(T x, U y) { SERIAL_IMPL.print(x, y); }
|
||||
|
||||
template <typename T>
|
||||
void SERIAL_PRINTLN(T x, PrintBase y) { SERIAL_IMPL.println(x, y); }
|
||||
|
||||
// Flush the serial port
|
||||
inline void SERIAL_FLUSH() { SERIAL_IMPL.flush(); }
|
||||
inline void SERIAL_FLUSHTX() { SERIAL_IMPL.flushTX(); }
|
||||
|
||||
// Print a single PROGMEM string to serial
|
||||
void serialprintPGM(PGM_P str);
|
||||
|
||||
//
|
||||
// SERIAL_ECHOPGM... macros are used to output string-value pairs.
|
||||
//
|
||||
|
||||
// Print up to 20 pairs of values. Odd elements must be literal strings.
|
||||
#define __SEP_N(N,V...) _SEP_##N(V)
|
||||
#define _SEP_N(N,V...) __SEP_N(N,V)
|
||||
#define _SEP_N_REF() _SEP_N
|
||||
#define _SEP_1(s) serialprintPGM(PSTR(s));
|
||||
#define _SEP_2(s,v) serial_echopair_PGM(PSTR(s),v);
|
||||
#define _SEP_3(s,v,V...) _SEP_2(s,v); DEFER2(_SEP_N_REF)()(TWO_ARGS(V),V);
|
||||
#define SERIAL_ECHOPGM(V...) do{ EVAL(_SEP_N(TWO_ARGS(V),V)); }while(0)
|
||||
|
||||
// Print up to 20 pairs of values followed by newline. Odd elements must be literal strings.
|
||||
#define __SELP_N(N,V...) _SELP_##N(V)
|
||||
#define _SELP_N(N,V...) __SELP_N(N,V)
|
||||
#define _SELP_N_REF() _SELP_N
|
||||
#define _SELP_1(s) serialprintPGM(PSTR(s "\n"));
|
||||
#define _SELP_2(s,v) serial_echopair_PGM(PSTR(s),v); SERIAL_EOL();
|
||||
#define _SELP_3(s,v,V...) _SEP_2(s,v); DEFER2(_SELP_N_REF)()(TWO_ARGS(V),V);
|
||||
#define SERIAL_ECHOLNPGM(V...) do{ EVAL(_SELP_N(TWO_ARGS(V),V)); }while(0)
|
||||
|
||||
// Print up to 20 pairs of values. Odd elements must be PSTR pointers.
|
||||
#define __SEP_N_P(N,V...) _SEP_##N##_P(V)
|
||||
#define _SEP_N_P(N,V...) __SEP_N_P(N,V)
|
||||
#define _SEP_N_P_REF() _SEP_N_P
|
||||
#define _SEP_1_P(p) serialprintPGM(p);
|
||||
#define _SEP_2_P(p,v) serial_echopair_PGM(p,v);
|
||||
#define _SEP_3_P(p,v,V...) _SEP_2_P(p,v); DEFER2(_SEP_N_P_REF)()(TWO_ARGS(V),V);
|
||||
#define SERIAL_ECHOPGM_P(V...) do{ EVAL(_SEP_N_P(TWO_ARGS(V),V)); }while(0)
|
||||
|
||||
// Print up to 20 pairs of values followed by newline. Odd elements must be PSTR pointers.
|
||||
#define __SELP_N_P(N,V...) _SELP_##N##_P(V)
|
||||
#define _SELP_N_P(N,V...) __SELP_N_P(N,V)
|
||||
#define _SELP_N_P_REF() _SELP_N_P
|
||||
#define _SELP_1_P(p) { serialprintPGM(p); SERIAL_EOL(); }
|
||||
#define _SELP_2_P(p,v) { serial_echopair_PGM(p,v); SERIAL_EOL(); }
|
||||
#define _SELP_3_P(p,v,V...) { _SEP_2_P(p,v); DEFER2(_SELP_N_P_REF)()(TWO_ARGS(V),V); }
|
||||
#define SERIAL_ECHOLNPGM_P(V...) do{ EVAL(_SELP_N_P(TWO_ARGS(V),V)); }while(0)
|
||||
|
||||
#ifdef AllowDifferentTypeInList
|
||||
|
||||
inline void SERIAL_ECHOLIST_IMPL() {}
|
||||
template <typename T>
|
||||
void SERIAL_ECHOLIST_IMPL(T && t) { SERIAL_IMPL.print(t); }
|
||||
|
||||
template <typename T, typename ... Args>
|
||||
void SERIAL_ECHOLIST_IMPL(T && t, Args && ... args) {
|
||||
SERIAL_IMPL.print(t);
|
||||
serialprintPGM(PSTR(", "));
|
||||
SERIAL_ECHOLIST_IMPL(args...);
|
||||
}
|
||||
|
||||
template <typename ... Args>
|
||||
void SERIAL_ECHOLIST(PGM_P const str, Args && ... args) {
|
||||
SERIAL_IMPL.print(str);
|
||||
SERIAL_ECHOLIST_IMPL(args...);
|
||||
}
|
||||
|
||||
#else // Optimization if the listed type are all the same (seems to be the case in the codebase so use that instead)
|
||||
|
||||
template <typename ... Args>
|
||||
void SERIAL_ECHOLIST(PGM_P const str, Args && ... args) {
|
||||
serialprintPGM(str);
|
||||
typename Private::first_type_of<Args...>::type values[] = { args... };
|
||||
constexpr size_t argsSize = sizeof...(args);
|
||||
for (size_t i = 0; i < argsSize; i++) {
|
||||
if (i) serialprintPGM(PSTR(", "));
|
||||
SERIAL_IMPL.print(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define SERIAL_ECHOPAIR_F_P(P,V...) do{ serialprintPGM(P); SERIAL_ECHO_F(V); }while(0)
|
||||
#define SERIAL_ECHOLNPAIR_F_P(V...) do{ SERIAL_ECHOPAIR_F_P(V); SERIAL_EOL(); }while(0)
|
||||
@@ -260,29 +271,35 @@ typedef int8_t serial_index_t;
|
||||
#define SERIAL_ERROR_START() serial_error_start()
|
||||
#define SERIAL_EOL() SERIAL_CHAR('\n')
|
||||
|
||||
#define SERIAL_ECHO_MSG(V...) do{ SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR(V); }while(0)
|
||||
#define SERIAL_ERROR_MSG(V...) do{ SERIAL_ERROR_START(); SERIAL_ECHOLNPAIR(V); }while(0)
|
||||
#define SERIAL_ECHO_MSG(V...) do{ SERIAL_ECHO_START(); SERIAL_ECHOLNPGM(V); }while(0)
|
||||
#define SERIAL_ERROR_MSG(V...) do{ SERIAL_ERROR_START(); SERIAL_ECHOLNPGM(V); }while(0)
|
||||
|
||||
#define SERIAL_ECHO_SP(C) serial_spaces(C)
|
||||
|
||||
#define SERIAL_ECHO_TERNARY(TF, PRE, ON, OFF, POST) serial_ternary(TF, PSTR(PRE), PSTR(ON), PSTR(OFF), PSTR(POST))
|
||||
|
||||
#if SERIAL_FLOAT_PRECISION
|
||||
#define SERIAL_DECIMAL(V) SERIAL_PRINT(V, SERIAL_FLOAT_PRECISION)
|
||||
#else
|
||||
#define SERIAL_DECIMAL(V) SERIAL_ECHO(V)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Functions for serial printing from PROGMEM. (Saves loads of SRAM.)
|
||||
//
|
||||
void serial_echopair_PGM(PGM_P const s_P, const char *v);
|
||||
void serial_echopair_PGM(PGM_P const s_P, char v);
|
||||
void serial_echopair_PGM(PGM_P const s_P, int v);
|
||||
void serial_echopair_PGM(PGM_P const s_P, long v);
|
||||
void serial_echopair_PGM(PGM_P const s_P, float v);
|
||||
void serial_echopair_PGM(PGM_P const s_P, double v);
|
||||
void serial_echopair_PGM(PGM_P const s_P, unsigned int v);
|
||||
void serial_echopair_PGM(PGM_P const s_P, unsigned long v);
|
||||
inline void serial_echopair_PGM(PGM_P const s_P, uint8_t v) { serial_echopair_PGM(s_P, (int)v); }
|
||||
inline void serial_echopair_PGM(PGM_P const s_P, bool v) { serial_echopair_PGM(s_P, (int)v); }
|
||||
inline void serial_echopair_PGM(PGM_P const s_P, void *v) { serial_echopair_PGM(s_P, (unsigned long)v); }
|
||||
inline void serial_echopair_PGM(PGM_P const s_P, serial_char_t v) { serialprintPGM(s_P); SERIAL_CHAR(v.c); }
|
||||
|
||||
inline void serial_echopair_PGM(PGM_P const s_P, float v) { serialprintPGM(s_P); SERIAL_DECIMAL(v); }
|
||||
inline void serial_echopair_PGM(PGM_P const s_P, double v) { serialprintPGM(s_P); SERIAL_DECIMAL(v); }
|
||||
inline void serial_echopair_PGM(PGM_P const s_P, const char *v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
|
||||
|
||||
// Default implementation for types without a specialization. Handles integers.
|
||||
template <typename T>
|
||||
void serial_echopair_PGM(PGM_P const s_P, T v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
|
||||
|
||||
inline void serial_echopair_PGM(PGM_P const s_P, bool v) { serial_echopair_PGM(s_P, (int)v); }
|
||||
inline void serial_echopair_PGM(PGM_P const s_P, void *v) { serial_echopair_PGM(s_P, (uintptr_t)v); }
|
||||
|
||||
void serialprintPGM(PGM_P str);
|
||||
void serial_echo_start();
|
||||
void serial_error_start();
|
||||
void serial_ternary(const bool onoff, PGM_P const pre, PGM_P const on, PGM_P const off, PGM_P const post=nullptr);
|
||||
@@ -292,11 +309,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 &x, const float &y, const float &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)
|
||||
|
258
Marlin/src/core/serial_base.h
Normal file
258
Marlin/src/core/serial_base.h
Normal file
@@ -0,0 +1,258 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#include "../feature/e_parser.h"
|
||||
#endif
|
||||
|
||||
// Used in multiple places
|
||||
// You can build it but not manipulate it.
|
||||
// There are only few places where it's required to access the underlying member: GCodeQueue, SerialMask and MultiSerial
|
||||
struct serial_index_t {
|
||||
// A signed index, where -1 is a special case meaning no action (neither output or input)
|
||||
int8_t index;
|
||||
|
||||
// Check if the index is within the range [a ... b]
|
||||
constexpr inline bool within(const int8_t a, const int8_t b) const { return WITHIN(index, a, b); }
|
||||
constexpr inline bool valid() const { return WITHIN(index, 0, 7); } // At most, 8 bits
|
||||
|
||||
// Construction is either from an index
|
||||
constexpr serial_index_t(const int8_t index) : index(index) {}
|
||||
|
||||
// Default to "no index"
|
||||
constexpr serial_index_t() : index(-1) {}
|
||||
};
|
||||
|
||||
// In order to catch usage errors in code, we make the base to encode number explicit
|
||||
// If given a number (and not this enum), the compiler will reject the overload, falling back to the (double, digit) version
|
||||
// We don't want hidden conversion of the first parameter to double, so it has to be as hard to do for the compiler as creating this enum
|
||||
enum class PrintBase {
|
||||
Dec = 10,
|
||||
Hex = 16,
|
||||
Oct = 8,
|
||||
Bin = 2
|
||||
};
|
||||
|
||||
// A simple feature list enumeration
|
||||
enum class SerialFeature {
|
||||
None = 0x00,
|
||||
MeatPack = 0x01, //!< Enabled when Meatpack is present
|
||||
BinaryFileTransfer = 0x02, //!< Enabled for BinaryFile transfer support (in the future)
|
||||
Virtual = 0x04, //!< Enabled for virtual serial port (like Telnet / Websocket / ...)
|
||||
Hookable = 0x08, //!< Enabled if the serial class supports a setHook method
|
||||
};
|
||||
ENUM_FLAGS(SerialFeature);
|
||||
|
||||
// flushTX is not implemented in all HAL, so use SFINAE to call the method where it is.
|
||||
CALL_IF_EXISTS_IMPL(void, flushTX);
|
||||
CALL_IF_EXISTS_IMPL(bool, connected, true);
|
||||
CALL_IF_EXISTS_IMPL(SerialFeature, features, SerialFeature::None);
|
||||
|
||||
// A simple forward struct to prevent the compiler from selecting print(double, int) as a default overload
|
||||
// for any type other than double/float. For double/float, a conversion exists so the call will be invisible.
|
||||
struct EnsureDouble {
|
||||
double a;
|
||||
operator double() { return a; }
|
||||
// If the compiler breaks on ambiguity here, it's likely because print(X, base) is called with X not a double/float, and
|
||||
// a base that's not a PrintBase value. This code is made to detect the error. You MUST set a base explicitly like this:
|
||||
// SERIAL_PRINT(v, PrintBase::Hex)
|
||||
EnsureDouble(double a) : a(a) {}
|
||||
EnsureDouble(float a) : a(a) {}
|
||||
};
|
||||
|
||||
// Using Curiously-Recurring Template Pattern here to avoid virtual table cost when compiling.
|
||||
// Since the real serial class is known at compile time, this results in the compiler writing
|
||||
// a completely efficient code.
|
||||
template <class Child>
|
||||
struct SerialBase {
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
const bool ep_enabled;
|
||||
EmergencyParser::State emergency_state;
|
||||
inline bool emergency_parser_enabled() { return ep_enabled; }
|
||||
SerialBase(bool ep_capable) : ep_enabled(ep_capable), emergency_state(EmergencyParser::State::EP_RESET) {}
|
||||
#else
|
||||
SerialBase(const bool) {}
|
||||
#endif
|
||||
|
||||
#define SerialChild static_cast<Child*>(this)
|
||||
|
||||
// Static dispatch methods below:
|
||||
// The most important method here is where it all ends to:
|
||||
void write(uint8_t c) { SerialChild->write(c); }
|
||||
|
||||
// Called when the parser finished processing an instruction, usually build to nothing
|
||||
void msgDone() const { SerialChild->msgDone(); }
|
||||
|
||||
// Called on initialization
|
||||
void begin(const long baudRate) { SerialChild->begin(baudRate); }
|
||||
|
||||
// Called on destruction
|
||||
void end() { SerialChild->end(); }
|
||||
|
||||
/** Check for available data from the port
|
||||
@param index The port index, usually 0 */
|
||||
int available(serial_index_t index=0) const { return SerialChild->available(index); }
|
||||
|
||||
/** Read a value from the port
|
||||
@param index The port index, usually 0 */
|
||||
int read(serial_index_t index=0) { return SerialChild->read(index); }
|
||||
|
||||
/** Combine the features of this serial instance and return it
|
||||
@param index The port index, usually 0 */
|
||||
SerialFeature features(serial_index_t index=0) const { return static_cast<const Child*>(this)->features(index); }
|
||||
|
||||
// Check if the serial port has a feature
|
||||
bool has_feature(serial_index_t index, SerialFeature flag) const { return (features(index) & flag) != SerialFeature::None; }
|
||||
|
||||
// Check if the serial port is connected (usually bypassed)
|
||||
bool connected() const { return SerialChild->connected(); }
|
||||
|
||||
// Redirect flush
|
||||
void flush() { SerialChild->flush(); }
|
||||
|
||||
// Not all implementation have a flushTX, so let's call them only if the child has the implementation
|
||||
void flushTX() { CALL_IF_EXISTS(void, SerialChild, flushTX); }
|
||||
|
||||
// Glue code here
|
||||
void write(const char *str) { while (*str) write(*str++); }
|
||||
void write(const uint8_t *buffer, size_t size) { while (size--) write(*buffer++); }
|
||||
void print(char *str) { write(str); }
|
||||
void print(const char *str) { write(str); }
|
||||
// No default argument to avoid ambiguity
|
||||
|
||||
// Define print for every fundamental integer type, to ensure that all redirect properly
|
||||
// to the correct underlying implementation.
|
||||
|
||||
// Prints are performed with a single size, to avoid needing multiple print functions.
|
||||
// The fixed integer size used for prints will be the larger of long or a pointer.
|
||||
#if __LONG_WIDTH__ >= __INTPTR_WIDTH__
|
||||
typedef long int_fixed_print_t;
|
||||
typedef unsigned long uint_fixed_print_t;
|
||||
#else
|
||||
typedef intptr_t int_fixed_print_t;
|
||||
typedef uintptr_t uint_fixed_print_t;
|
||||
|
||||
FORCE_INLINE void print(intptr_t c, PrintBase base) { printNumber_signed(c, base); }
|
||||
FORCE_INLINE void print(uintptr_t c, PrintBase base) { printNumber_unsigned(c, base); }
|
||||
#endif
|
||||
|
||||
FORCE_INLINE void print(char c, PrintBase base) { printNumber_signed(c, base); }
|
||||
FORCE_INLINE void print(short c, PrintBase base) { printNumber_signed(c, base); }
|
||||
FORCE_INLINE void print(int c, PrintBase base) { printNumber_signed(c, base); }
|
||||
FORCE_INLINE void print(long c, PrintBase base) { printNumber_signed(c, base); }
|
||||
FORCE_INLINE void print(unsigned char c, PrintBase base) { printNumber_unsigned(c, base); }
|
||||
FORCE_INLINE void print(unsigned short c, PrintBase base) { printNumber_unsigned(c, base); }
|
||||
FORCE_INLINE void print(unsigned int c, PrintBase base) { printNumber_unsigned(c, base); }
|
||||
FORCE_INLINE void print(unsigned long c, PrintBase base) { printNumber_unsigned(c, base); }
|
||||
|
||||
|
||||
void print(EnsureDouble c, int digits) { printFloat(c, digits); }
|
||||
|
||||
// Forward the call to the former's method
|
||||
|
||||
// Default implementation for anything without a specialization
|
||||
// This handles integers since they are the most common
|
||||
template <typename T>
|
||||
void print(T c) { print(c, PrintBase::Dec); }
|
||||
|
||||
void print(float c) { print(c, 2); }
|
||||
void print(double c) { print(c, 2); }
|
||||
|
||||
void println(char *s) { print(s); println(); }
|
||||
void println(const char *s) { print(s); println(); }
|
||||
void println(float c, int digits) { print(c, digits); println(); }
|
||||
void println(double c, int digits) { print(c, digits); println(); }
|
||||
void println() { write('\r'); write('\n'); }
|
||||
|
||||
// Default implementations for types without a specialization. Handles integers.
|
||||
template <typename T>
|
||||
void println(T c, PrintBase base) { print(c, base); println(); }
|
||||
|
||||
template <typename T>
|
||||
void println(T c) { println(c, PrintBase::Dec); }
|
||||
|
||||
// Forward the call to the former's method
|
||||
void println(float c) { println(c, 2); }
|
||||
void println(double c) { println(c, 2); }
|
||||
|
||||
// Print a number with the given base
|
||||
NO_INLINE void printNumber_unsigned(uint_fixed_print_t n, PrintBase base) {
|
||||
if (n) {
|
||||
unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
|
||||
int8_t i = 0;
|
||||
while (n) {
|
||||
buf[i++] = n % (uint_fixed_print_t)base;
|
||||
n /= (uint_fixed_print_t)base;
|
||||
}
|
||||
while (i--) write((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
|
||||
}
|
||||
else write('0');
|
||||
}
|
||||
|
||||
NO_INLINE void printNumber_signed(int_fixed_print_t n, PrintBase base) {
|
||||
if (base == PrintBase::Dec && n < 0) {
|
||||
n = -n; // This works because all platforms Marlin's builds on are using 2-complement encoding for negative number
|
||||
// On such CPU, changing the sign of a number is done by inverting the bits and adding one, so if n = 0x80000000 = -2147483648 then
|
||||
// -n = 0x7FFFFFFF + 1 => 0x80000000 = 2147483648 (if interpreted as unsigned) or -2147483648 if interpreted as signed.
|
||||
// On non 2-complement CPU, there would be no possible representation for 2147483648.
|
||||
write('-');
|
||||
}
|
||||
printNumber_unsigned((uint_fixed_print_t)n , base);
|
||||
}
|
||||
|
||||
// Print a decimal number
|
||||
NO_INLINE void printFloat(double number, uint8_t digits) {
|
||||
// Handle negative numbers
|
||||
if (number < 0.0) {
|
||||
write('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
LOOP_L_N(i, digits) rounding *= 0.1;
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
unsigned long int_part = (unsigned long)number;
|
||||
double remainder = number - (double)int_part;
|
||||
printNumber_unsigned(int_part, PrintBase::Dec);
|
||||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if (digits) {
|
||||
write('.');
|
||||
// Extract digits from the remainder one at a time
|
||||
while (digits--) {
|
||||
remainder *= 10.0;
|
||||
unsigned long toPrint = (unsigned long)remainder;
|
||||
printNumber_unsigned(toPrint, PrintBase::Dec);
|
||||
remainder -= toPrint;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// All serial instances will be built by chaining the features required
|
||||
// for the function in the form of a template type definition.
|
306
Marlin/src/core/serial_hook.h
Normal file
306
Marlin/src/core/serial_hook.h
Normal file
@@ -0,0 +1,306 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "serial_base.h"
|
||||
|
||||
// A mask containing a bitmap of the serial port to act upon
|
||||
// This is written to ensure a serial index is never used as a serial mask
|
||||
class SerialMask {
|
||||
uint8_t mask;
|
||||
|
||||
// This constructor is private to ensure you can't convert an index to a mask
|
||||
// The compiler will stop here if you are mixing index and mask in your code.
|
||||
// If you need to, you'll have to use the explicit static "from" method here
|
||||
SerialMask(const serial_index_t);
|
||||
|
||||
public:
|
||||
inline constexpr bool enabled(const SerialMask PortMask) const { return mask & PortMask.mask; }
|
||||
inline constexpr SerialMask combine(const SerialMask other) const { return SerialMask(mask | other.mask); }
|
||||
inline constexpr SerialMask operator<< (const int offset) const { return SerialMask(mask << offset); }
|
||||
static inline SerialMask from(const serial_index_t index) {
|
||||
if (index.valid()) return SerialMask(_BV(index.index));
|
||||
return SerialMask(0); // A invalid index mean no output
|
||||
}
|
||||
|
||||
constexpr SerialMask(const uint8_t mask) : mask(mask) {}
|
||||
constexpr SerialMask(const SerialMask & other) : mask(other.mask) {} // Can't use = default here since not all framework support this
|
||||
|
||||
static constexpr uint8_t All = 0xFF;
|
||||
};
|
||||
|
||||
// The most basic serial class: it dispatch to the base serial class with no hook whatsoever. This will compile to nothing but the base serial class
|
||||
template <class SerialT>
|
||||
struct BaseSerial : public SerialBase< BaseSerial<SerialT> >, public SerialT {
|
||||
typedef SerialBase< BaseSerial<SerialT> > BaseClassT;
|
||||
|
||||
// It's required to implement a write method here to help compiler disambiguate what method to call
|
||||
using SerialT::write;
|
||||
using SerialT::flush;
|
||||
|
||||
void msgDone() {}
|
||||
|
||||
// We don't care about indices here, since if one can call us, it's the right index anyway
|
||||
int available(serial_index_t) { return (int)SerialT::available(); }
|
||||
int read(serial_index_t) { return (int)SerialT::read(); }
|
||||
bool connected() { return CALL_IF_EXISTS(bool, static_cast<SerialT*>(this), connected);; }
|
||||
void flushTX() { CALL_IF_EXISTS(void, static_cast<SerialT*>(this), flushTX); }
|
||||
|
||||
SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, static_cast<const SerialT*>(this), features, index); }
|
||||
|
||||
// Two implementations of the same method exist in both base classes so indicate the right one
|
||||
using SerialT::available;
|
||||
using SerialT::read;
|
||||
using SerialT::begin;
|
||||
using SerialT::end;
|
||||
|
||||
using BaseClassT::print;
|
||||
using BaseClassT::println;
|
||||
|
||||
BaseSerial(const bool e) : BaseClassT(e) {}
|
||||
|
||||
// Forward constructor
|
||||
template <typename... Args>
|
||||
BaseSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...) {}
|
||||
};
|
||||
|
||||
// A serial with a condition checked at runtime for its output
|
||||
// A bit less efficient than static dispatching but since it's only used for ethernet's serial output right now, it's ok.
|
||||
template <class SerialT>
|
||||
struct ConditionalSerial : public SerialBase< ConditionalSerial<SerialT> > {
|
||||
typedef SerialBase< ConditionalSerial<SerialT> > BaseClassT;
|
||||
|
||||
bool & condition;
|
||||
SerialT & out;
|
||||
NO_INLINE size_t write(uint8_t c) { if (condition) return out.write(c); return 0; }
|
||||
void flush() { if (condition) out.flush(); }
|
||||
void begin(long br) { out.begin(br); }
|
||||
void end() { out.end(); }
|
||||
|
||||
void msgDone() {}
|
||||
bool connected() { return CALL_IF_EXISTS(bool, &out, connected); }
|
||||
void flushTX() { CALL_IF_EXISTS(void, &out, flushTX); }
|
||||
|
||||
int available(serial_index_t) { return (int)out.available(); }
|
||||
int read(serial_index_t) { return (int)out.read(); }
|
||||
int available() { return (int)out.available(); }
|
||||
int read() { return (int)out.read(); }
|
||||
SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, &out, features, index); }
|
||||
|
||||
ConditionalSerial(bool & conditionVariable, SerialT & out, const bool e) : BaseClassT(e), condition(conditionVariable), out(out) {}
|
||||
};
|
||||
|
||||
// A simple forward class that taking a reference to an existing serial instance (likely created in their respective framework)
|
||||
template <class SerialT>
|
||||
struct ForwardSerial : public SerialBase< ForwardSerial<SerialT> > {
|
||||
typedef SerialBase< ForwardSerial<SerialT> > BaseClassT;
|
||||
|
||||
SerialT & out;
|
||||
NO_INLINE size_t write(uint8_t c) { return out.write(c); }
|
||||
void flush() { out.flush(); }
|
||||
void begin(long br) { out.begin(br); }
|
||||
void end() { out.end(); }
|
||||
|
||||
void msgDone() {}
|
||||
// Existing instances implement Arduino's operator bool, so use that if it's available
|
||||
bool connected() { return Private::HasMember_connected<SerialT>::value ? CALL_IF_EXISTS(bool, &out, connected) : (bool)out; }
|
||||
void flushTX() { CALL_IF_EXISTS(void, &out, flushTX); }
|
||||
|
||||
int available(serial_index_t) { return (int)out.available(); }
|
||||
int read(serial_index_t) { return (int)out.read(); }
|
||||
int available() { return (int)out.available(); }
|
||||
int read() { return (int)out.read(); }
|
||||
SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, &out, features, index); }
|
||||
|
||||
ForwardSerial(const bool e, SerialT & out) : BaseClassT(e), out(out) {}
|
||||
};
|
||||
|
||||
// A class that can be hooked and unhooked at runtime, useful to capture the output of the serial interface
|
||||
template <class SerialT>
|
||||
struct RuntimeSerial : public SerialBase< RuntimeSerial<SerialT> >, public SerialT {
|
||||
typedef SerialBase< RuntimeSerial<SerialT> > BaseClassT;
|
||||
typedef void (*WriteHook)(void * userPointer, uint8_t c);
|
||||
typedef void (*EndOfMessageHook)(void * userPointer);
|
||||
|
||||
WriteHook writeHook;
|
||||
EndOfMessageHook eofHook;
|
||||
void * userPointer;
|
||||
|
||||
NO_INLINE size_t write(uint8_t c) {
|
||||
if (writeHook) writeHook(userPointer, c);
|
||||
return SerialT::write(c);
|
||||
}
|
||||
|
||||
NO_INLINE void msgDone() {
|
||||
if (eofHook) eofHook(userPointer);
|
||||
}
|
||||
|
||||
int available(serial_index_t) { return (int)SerialT::available(); }
|
||||
int read(serial_index_t) { return (int)SerialT::read(); }
|
||||
using SerialT::available;
|
||||
using SerialT::read;
|
||||
using SerialT::flush;
|
||||
using SerialT::begin;
|
||||
using SerialT::end;
|
||||
|
||||
using BaseClassT::print;
|
||||
using BaseClassT::println;
|
||||
|
||||
// Underlying implementation might use Arduino's bool operator
|
||||
bool connected() {
|
||||
return Private::HasMember_connected<SerialT>::value
|
||||
? CALL_IF_EXISTS(bool, static_cast<SerialT*>(this), connected)
|
||||
: static_cast<SerialT*>(this)->operator bool();
|
||||
}
|
||||
|
||||
void flushTX() { CALL_IF_EXISTS(void, static_cast<SerialT*>(this), flushTX); }
|
||||
|
||||
// Append Hookable for this class
|
||||
SerialFeature features(serial_index_t index) const { return SerialFeature::Hookable | CALL_IF_EXISTS(SerialFeature, static_cast<const SerialT*>(this), features, index); }
|
||||
|
||||
void setHook(WriteHook writeHook = 0, EndOfMessageHook eofHook = 0, void * userPointer = 0) {
|
||||
// Order is important here as serial code can be called inside interrupts
|
||||
// When setting a hook, the user pointer must be set first so if writeHook is called as soon as it's set, it'll be valid
|
||||
if (userPointer) this->userPointer = userPointer;
|
||||
this->writeHook = writeHook;
|
||||
this->eofHook = eofHook;
|
||||
// Order is important here because of asynchronous access here
|
||||
// When unsetting a hook, the user pointer must be unset last so that any pending writeHook is still using the old pointer
|
||||
if (!userPointer) this->userPointer = 0;
|
||||
}
|
||||
|
||||
RuntimeSerial(const bool e) : BaseClassT(e), writeHook(0), eofHook(0), userPointer(0) {}
|
||||
|
||||
// Forward constructor
|
||||
template <typename... Args>
|
||||
RuntimeSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...), writeHook(0), eofHook(0), userPointer(0) {}
|
||||
};
|
||||
|
||||
#define _S_CLASS(N) class Serial##N##T,
|
||||
#define _S_NAME(N) Serial##N##T,
|
||||
|
||||
template < REPEAT(NUM_SERIAL, _S_CLASS) const uint8_t offset=0, const uint8_t step=1 >
|
||||
struct MultiSerial : public SerialBase< MultiSerial< REPEAT(NUM_SERIAL, _S_NAME) offset, step > > {
|
||||
typedef SerialBase< MultiSerial< REPEAT(NUM_SERIAL, _S_NAME) offset, step > > BaseClassT;
|
||||
|
||||
#undef _S_CLASS
|
||||
#undef _S_NAME
|
||||
|
||||
SerialMask portMask;
|
||||
|
||||
#define _S_DECLARE(N) Serial##N##T & serial##N;
|
||||
REPEAT(NUM_SERIAL, _S_DECLARE);
|
||||
#undef _S_DECLARE
|
||||
|
||||
static constexpr uint8_t Usage = _BV(step) - 1; // A bit mask containing 'step' bits
|
||||
|
||||
#define _OUT_PORT(N) (Usage << (offset + (step * N))),
|
||||
static constexpr uint8_t output[] = { REPEAT(NUM_SERIAL, _OUT_PORT) };
|
||||
#undef _OUT_PORT
|
||||
|
||||
#define _OUT_MASK(N) | output[N]
|
||||
static constexpr uint8_t ALL = 0 REPEAT(NUM_SERIAL, _OUT_MASK);
|
||||
#undef _OUT_MASK
|
||||
|
||||
NO_INLINE void write(uint8_t c) {
|
||||
#define _S_WRITE(N) if (portMask.enabled(output[N])) serial##N.write(c);
|
||||
REPEAT(NUM_SERIAL, _S_WRITE);
|
||||
#undef _S_WRITE
|
||||
}
|
||||
NO_INLINE void msgDone() {
|
||||
#define _S_DONE(N) if (portMask.enabled(output[N])) serial##N.msgDone();
|
||||
REPEAT(NUM_SERIAL, _S_DONE);
|
||||
#undef _S_DONE
|
||||
}
|
||||
int available(serial_index_t index) {
|
||||
uint8_t pos = offset;
|
||||
#define _S_AVAILABLE(N) if (index.within(pos, pos + step - 1)) return serial##N.available(index); else pos += step;
|
||||
REPEAT(NUM_SERIAL, _S_AVAILABLE);
|
||||
#undef _S_AVAILABLE
|
||||
return false;
|
||||
}
|
||||
int read(serial_index_t index) {
|
||||
uint8_t pos = offset;
|
||||
#define _S_READ(N) if (index.within(pos, pos + step - 1)) return serial##N.read(index); else pos += step;
|
||||
REPEAT(NUM_SERIAL, _S_READ);
|
||||
#undef _S_READ
|
||||
return -1;
|
||||
}
|
||||
void begin(const long br) {
|
||||
#define _S_BEGIN(N) if (portMask.enabled(output[N])) serial##N.begin(br);
|
||||
REPEAT(NUM_SERIAL, _S_BEGIN);
|
||||
#undef _S_BEGIN
|
||||
}
|
||||
void end() {
|
||||
#define _S_END(N) if (portMask.enabled(output[N])) serial##N.end();
|
||||
REPEAT(NUM_SERIAL, _S_END);
|
||||
#undef _S_END
|
||||
}
|
||||
bool connected() {
|
||||
bool ret = true;
|
||||
#define _S_CONNECTED(N) if (portMask.enabled(output[N]) && !CALL_IF_EXISTS(bool, &serial##N, connected)) ret = false;
|
||||
REPEAT(NUM_SERIAL, _S_CONNECTED);
|
||||
#undef _S_CONNECTED
|
||||
return ret;
|
||||
}
|
||||
|
||||
using BaseClassT::available;
|
||||
using BaseClassT::read;
|
||||
|
||||
// Redirect flush
|
||||
NO_INLINE void flush() {
|
||||
#define _S_FLUSH(N) if (portMask.enabled(output[N])) serial##N.flush();
|
||||
REPEAT(NUM_SERIAL, _S_FLUSH);
|
||||
#undef _S_FLUSH
|
||||
}
|
||||
NO_INLINE void flushTX() {
|
||||
#define _S_FLUSHTX(N) if (portMask.enabled(output[N])) CALL_IF_EXISTS(void, &serial0, flushTX);
|
||||
REPEAT(NUM_SERIAL, _S_FLUSHTX);
|
||||
#undef _S_FLUSHTX
|
||||
}
|
||||
|
||||
// Forward feature queries
|
||||
SerialFeature features(serial_index_t index) const {
|
||||
uint8_t pos = offset;
|
||||
#define _S_FEATURES(N) if (index.within(pos, pos + step - 1)) return serial##N.features(index); else pos += step;
|
||||
REPEAT(NUM_SERIAL, _S_FEATURES);
|
||||
#undef _S_FEATURES
|
||||
return SerialFeature::None;
|
||||
}
|
||||
|
||||
#define _S_REFS(N) Serial##N##T & serial##N,
|
||||
#define _S_INIT(N) ,serial##N (serial##N)
|
||||
|
||||
MultiSerial(REPEAT(NUM_SERIAL, _S_REFS) const SerialMask mask = ALL, const bool e = false)
|
||||
: BaseClassT(e), portMask(mask) REPEAT(NUM_SERIAL, _S_INIT) {}
|
||||
|
||||
};
|
||||
|
||||
// Build the actual serial object depending on current configuration
|
||||
#define Serial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, BaseSerial)
|
||||
#define ForwardSerial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial)
|
||||
#ifdef HAS_MULTI_SERIAL
|
||||
#define Serial2Class ConditionalSerial
|
||||
#if NUM_SERIAL >= 3
|
||||
#define Serial3Class ConditionalSerial
|
||||
#endif
|
||||
#endif
|
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -27,35 +27,11 @@
|
||||
#include "../inc/MarlinConfigPre.h"
|
||||
|
||||
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)
|
||||
typedef const __FlashStringHelper* FSTR_P;
|
||||
#ifndef FPSTR
|
||||
#define FPSTR(S) (reinterpret_cast<FSTR_P>(S))
|
||||
#endif
|
||||
#define FTOP(S) (reinterpret_cast<const char*>(S))
|
||||
|
||||
//
|
||||
// Conditional type assignment magic. For example...
|
||||
@@ -67,22 +43,120 @@ 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)
|
||||
|
||||
#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", AXIS4_STR, AXIS5_STR, AXIS6_STR)
|
||||
|
||||
#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
|
||||
//
|
||||
typedef float feedRate_t;
|
||||
|
||||
//
|
||||
// celsius_t is the native unit of temperature. Signed to handle a disconnected thermistor value (-14).
|
||||
// For more resolition (e.g., for a chocolate printer) this may later be changed to Celsius x 100
|
||||
//
|
||||
typedef int16_t celsius_t;
|
||||
typedef float celsius_float_t;
|
||||
|
||||
//
|
||||
// On AVR pointers are only 2 bytes so use 'const float &' for 'const float'
|
||||
//
|
||||
#ifdef __AVR__
|
||||
typedef const float & const_float_t;
|
||||
#else
|
||||
typedef const float const_float_t;
|
||||
#endif
|
||||
typedef const_float_t const_feedRate_t;
|
||||
typedef const_float_t const_celsius_float_t;
|
||||
|
||||
// Conversion macros
|
||||
#define MMM_TO_MMS(MM_M) feedRate_t(float(MM_M) / 60.0f)
|
||||
#define MMS_TO_MMM(MM_S) (float(MM_S) * 60.0f)
|
||||
#define MMS_SCALED(V) ((V) * 0.01f * feedrate_percentage)
|
||||
#define MMM_TO_MMS(MM_M) feedRate_t(static_cast<float>(MM_M) / 60.0f)
|
||||
#define MMS_TO_MMM(MM_S) (static_cast<float>(MM_S) * 60.0f)
|
||||
|
||||
//
|
||||
// Coordinates structures for XY, XYZ, XYZE...
|
||||
//
|
||||
|
||||
// Helpers
|
||||
#define _RECIP(N) ((N) ? 1.0f / float(N) : 0.0f)
|
||||
#define _RECIP(N) ((N) ? 1.0f / static_cast<float>(N) : 0.0f)
|
||||
#define _ABS(N) ((N) < 0 ? -(N) : (N))
|
||||
#define _LS(N) (N = (T)(uint32_t(N) << v))
|
||||
#define _RS(N) (N = (T)(uint32_t(N) >> v))
|
||||
@@ -170,7 +244,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 {
|
||||
@@ -179,18 +253,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) }; }
|
||||
@@ -199,20 +289,30 @@ struct XYval {
|
||||
FI XYval<int32_t> asLong() const { return { int32_t(x), int32_t(y) }; }
|
||||
FI XYval<int32_t> ROUNDL() { return { int32_t(LROUND(x)), int32_t(LROUND(y)) }; }
|
||||
FI XYval<int32_t> ROUNDL() const { return { int32_t(LROUND(x)), int32_t(LROUND(y)) }; }
|
||||
FI XYval<float> asFloat() { return { float(x), float(y) }; }
|
||||
FI XYval<float> asFloat() const { return { float(x), float(y) }; }
|
||||
FI XYval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y) }; }
|
||||
FI XYval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y) }; }
|
||||
FI XYval<float> 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; }
|
||||
@@ -249,6 +349,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; }
|
||||
@@ -262,6 +366,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; }
|
||||
@@ -274,224 +380,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 { float(x), float(y), float(z) }; }
|
||||
FI XYZval<float> asFloat() const { return { float(x), float(y), 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 { float(x), float(y), float(z), float(e) }; }
|
||||
FI XYZEval<float> asFloat() const { return { float(x), float(y), float(z), 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
|
||||
@@ -499,6 +672,3 @@ struct XYZEval {
|
||||
#undef _LS
|
||||
#undef _RS
|
||||
#undef FI
|
||||
|
||||
const xyze_char_t axis_codes { 'X', 'Y', 'Z', 'E' };
|
||||
#define XYZ_CHAR(A) ('X' + char(A))
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -57,30 +57,31 @@ void safe_delay(millis_t ms) {
|
||||
|
||||
void log_machine_info() {
|
||||
SERIAL_ECHOLNPGM("Machine Type: "
|
||||
TERN(DELTA, "Delta", "")
|
||||
TERN(IS_SCARA, "SCARA", "")
|
||||
TERN(IS_CORE, "Core", "")
|
||||
TERN(IS_CARTESIAN, "Cartesian", "")
|
||||
TERN_(DELTA, "Delta")
|
||||
TERN_(IS_SCARA, "SCARA")
|
||||
TERN_(IS_CORE, "Core")
|
||||
TERN_(MARKFORGED_XY, "MarkForged")
|
||||
TERN_(IS_CARTESIAN, "Cartesian")
|
||||
);
|
||||
|
||||
SERIAL_ECHOLNPGM("Probe: "
|
||||
TERN(PROBE_MANUALLY, "PROBE_MANUALLY", "")
|
||||
TERN(NOZZLE_AS_PROBE, "NOZZLE_AS_PROBE", "")
|
||||
TERN(FIX_MOUNTED_PROBE, "FIX_MOUNTED_PROBE", "")
|
||||
TERN(HAS_Z_SERVO_PROBE, TERN(BLTOUCH, "BLTOUCH", "SERVO PROBE"), "")
|
||||
TERN(TOUCH_MI_PROBE, "TOUCH_MI_PROBE", "")
|
||||
TERN(Z_PROBE_SLED, "Z_PROBE_SLED", "")
|
||||
TERN(Z_PROBE_ALLEN_KEY, "Z_PROBE_ALLEN_KEY", "")
|
||||
TERN(SOLENOID_PROBE, "SOLENOID_PROBE", "")
|
||||
TERN_(PROBE_MANUALLY, "PROBE_MANUALLY")
|
||||
TERN_(NOZZLE_AS_PROBE, "NOZZLE_AS_PROBE")
|
||||
TERN_(FIX_MOUNTED_PROBE, "FIX_MOUNTED_PROBE")
|
||||
TERN_(HAS_Z_SERVO_PROBE, TERN(BLTOUCH, "BLTOUCH", "SERVO PROBE"))
|
||||
TERN_(TOUCH_MI_PROBE, "TOUCH_MI_PROBE")
|
||||
TERN_(Z_PROBE_SLED, "Z_PROBE_SLED")
|
||||
TERN_(Z_PROBE_ALLEN_KEY, "Z_PROBE_ALLEN_KEY")
|
||||
TERN_(SOLENOID_PROBE, "SOLENOID_PROBE")
|
||||
TERN(PROBE_SELECTED, "", "NONE")
|
||||
);
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
|
||||
#if !HAS_PROBE_XY_OFFSET
|
||||
SERIAL_ECHOPAIR("Probe Offset X0 Y0 Z", probe.offset.z, " (");
|
||||
SERIAL_ECHOPGM("Probe Offset X0 Y0 Z", probe.offset.z, " (");
|
||||
#else
|
||||
SERIAL_ECHOPAIR_P(PSTR("Probe Offset X"), probe.offset_xy.x, SP_Y_STR, probe.offset_xy.y, SP_Z_STR, probe.offset.z);
|
||||
SERIAL_ECHOPGM_P(PSTR("Probe Offset X"), probe.offset_xy.x, SP_Y_STR, probe.offset_xy.y, SP_Z_STR, probe.offset.z);
|
||||
if (probe.offset_xy.x > 0)
|
||||
SERIAL_ECHOPGM(" (Right");
|
||||
else if (probe.offset_xy.x < 0)
|
||||
@@ -91,9 +92,9 @@ void safe_delay(millis_t ms) {
|
||||
SERIAL_ECHOPGM(" (Aligned With");
|
||||
|
||||
if (probe.offset_xy.y > 0)
|
||||
serialprintPGM(ENABLED(IS_SCARA) ? PSTR("-Distal") : PSTR("-Back"));
|
||||
SERIAL_ECHOPGM_P(ENABLED(IS_SCARA) ? PSTR("-Distal") : PSTR("-Back"));
|
||||
else if (probe.offset_xy.y < 0)
|
||||
serialprintPGM(ENABLED(IS_SCARA) ? PSTR("-Proximal") : PSTR("-Front"));
|
||||
SERIAL_ECHOPGM_P(ENABLED(IS_SCARA) ? PSTR("-Proximal") : PSTR("-Front"));
|
||||
else if (probe.offset_xy.x != 0)
|
||||
SERIAL_ECHOPGM("-Center");
|
||||
|
||||
@@ -101,32 +102,32 @@ void safe_delay(millis_t ms) {
|
||||
|
||||
#endif
|
||||
|
||||
serialprintPGM(probe.offset.z < 0 ? PSTR("Below") : probe.offset.z > 0 ? PSTR("Above") : PSTR("Same Z as"));
|
||||
SERIAL_ECHOPGM_P(probe.offset.z < 0 ? PSTR("Below") : probe.offset.z > 0 ? PSTR("Above") : PSTR("Same Z as"));
|
||||
SERIAL_ECHOLNPGM(" Nozzle)");
|
||||
|
||||
#endif
|
||||
|
||||
#if HAS_ABL_OR_UBL
|
||||
SERIAL_ECHOPGM("Auto Bed Leveling: "
|
||||
TERN(AUTO_BED_LEVELING_LINEAR, "LINEAR", "")
|
||||
TERN(AUTO_BED_LEVELING_BILINEAR, "BILINEAR", "")
|
||||
TERN(AUTO_BED_LEVELING_3POINT, "3POINT", "")
|
||||
TERN(AUTO_BED_LEVELING_UBL, "UBL", "")
|
||||
TERN_(AUTO_BED_LEVELING_LINEAR, "LINEAR")
|
||||
TERN_(AUTO_BED_LEVELING_BILINEAR, "BILINEAR")
|
||||
TERN_(AUTO_BED_LEVELING_3POINT, "3POINT")
|
||||
TERN_(AUTO_BED_LEVELING_UBL, "UBL")
|
||||
);
|
||||
|
||||
if (planner.leveling_active) {
|
||||
SERIAL_ECHOLNPGM(" (enabled)");
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
if (planner.z_fade_height)
|
||||
SERIAL_ECHOLNPAIR("Z Fade: ", planner.z_fade_height);
|
||||
SERIAL_ECHOLNPGM("Z Fade: ", planner.z_fade_height);
|
||||
#endif
|
||||
#if ABL_PLANAR
|
||||
SERIAL_ECHOPGM("ABL Adjustment X");
|
||||
LOOP_XYZ(a) {
|
||||
float v = planner.get_axis_position_mm(AxisEnum(a)) - current_position[a];
|
||||
SERIAL_CHAR(' ', XYZ_CHAR(a));
|
||||
SERIAL_ECHOPGM("ABL Adjustment");
|
||||
LOOP_LINEAR_AXES(a) {
|
||||
const float v = planner.get_axis_position_mm(AxisEnum(a)) - current_position[a];
|
||||
SERIAL_CHAR(' ', AXIS_CHAR(a));
|
||||
if (v > 0) SERIAL_CHAR('+');
|
||||
SERIAL_ECHO(v);
|
||||
SERIAL_DECIMAL(v);
|
||||
}
|
||||
#else
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
@@ -139,7 +140,7 @@ void safe_delay(millis_t ms) {
|
||||
SERIAL_ECHO(ftostr43sign(rz, '+'));
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
if (planner.z_fade_height) {
|
||||
SERIAL_ECHOPAIR(" (", ftostr43sign(rz * planner.fade_scaling_factor_for_z(current_position.z), '+'));
|
||||
SERIAL_ECHOPGM(" (", ftostr43sign(rz * planner.fade_scaling_factor_for_z(current_position.z), '+'));
|
||||
SERIAL_CHAR(')');
|
||||
}
|
||||
#endif
|
||||
@@ -155,10 +156,10 @@ void safe_delay(millis_t ms) {
|
||||
SERIAL_ECHOPGM("Mesh Bed Leveling");
|
||||
if (planner.leveling_active) {
|
||||
SERIAL_ECHOLNPGM(" (enabled)");
|
||||
SERIAL_ECHOPAIR("MBL Adjustment Z", ftostr43sign(mbl.get_z(current_position), '+'));
|
||||
SERIAL_ECHOPGM("MBL Adjustment Z", ftostr43sign(mbl.get_z(current_position), '+'));
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
if (planner.z_fade_height) {
|
||||
SERIAL_ECHOPAIR(" (", ftostr43sign(
|
||||
SERIAL_ECHOPGM(" (", ftostr43sign(
|
||||
mbl.get_z(current_position, planner.fade_scaling_factor_for_z(current_position.z)), '+'
|
||||
));
|
||||
SERIAL_CHAR(')');
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -25,8 +25,7 @@
|
||||
#include "../core/types.h"
|
||||
#include "../core/millis_t.h"
|
||||
|
||||
// Delay that ensures heaters and watchdog are kept alive
|
||||
void safe_delay(millis_t ms);
|
||||
void safe_delay(millis_t ms); // Delay ensuring that temperatures are updated and the watchdog is kept alive.
|
||||
|
||||
#if ENABLED(SERIAL_OVERRUN_PROTECTION)
|
||||
void serial_delay(const millis_t ms);
|
||||
@@ -34,7 +33,7 @@ void safe_delay(millis_t ms);
|
||||
inline void serial_delay(const millis_t) {}
|
||||
#endif
|
||||
|
||||
#if GRID_MAX_POINTS_X && GRID_MAX_POINTS_Y
|
||||
#if (GRID_MAX_POINTS_X) && (GRID_MAX_POINTS_Y)
|
||||
|
||||
// 16x16 bit arrays
|
||||
template <int W, int H>
|
||||
@@ -71,9 +70,17 @@ public:
|
||||
inline void restore() { ref_ = val_; }
|
||||
};
|
||||
|
||||
#define REMEMBER(N,X,V...) restorer<typeof(X)> restorer_##N(X, ##V)
|
||||
#define REMEMBER(N,X,V...) restorer<__typeof__(X)> restorer_##N(X, ##V)
|
||||
#define RESTORE(N) restorer_##N.restore()
|
||||
|
||||
// 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
|
||||
|
Reference in New Issue
Block a user