Browse Source

🔧 Config INI, dump options (#24528)

Scott Lahteine 1 year ago
parent
commit
1bed10c380
No account linked to committer's email address

+ 72
- 29
Marlin/Configuration.h View File

@@ -112,6 +112,7 @@
112 112
  * :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000]
113 113
  */
114 114
 #define BAUDRATE 250000
115
+
115 116
 //#define BAUD_RATE_GCODE     // Enable G-code M575 to set the baud rate
116 117
 
117 118
 /**
@@ -120,7 +121,7 @@
120 121
  * :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
121 122
  */
122 123
 //#define SERIAL_PORT_2 -1
123
-//#define BAUDRATE_2 250000   // Enable to override BAUDRATE
124
+//#define BAUDRATE_2 250000   // :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000] Enable to override BAUDRATE
124 125
 
125 126
 /**
126 127
  * Select a third serial port on the board to use for communication with the host.
@@ -128,7 +129,7 @@
128 129
  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
129 130
  */
130 131
 //#define SERIAL_PORT_3 1
131
-//#define BAUDRATE_3 250000   // Enable to override BAUDRATE
132
+//#define BAUDRATE_3 250000   // :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000] Enable to override BAUDRATE
132 133
 
133 134
 // Enable the Bluetooth serial interface on AT90USB devices
134 135
 //#define BLUETOOTH
@@ -387,7 +388,7 @@
387 388
 //#define HOTEND_OFFSET_Y { 0.0, 5.00 }  // (mm) relative Y-offset for each nozzle
388 389
 //#define HOTEND_OFFSET_Z { 0.0, 0.00 }  // (mm) relative Z-offset for each nozzle
389 390
 
390
-// @section machine
391
+// @section psu control
391 392
 
392 393
 /**
393 394
  * Power Supply Control
@@ -549,22 +550,32 @@
549 550
 #define DUMMY_THERMISTOR_999_VALUE 100
550 551
 
551 552
 // Resistor values when using MAX31865 sensors (-5) on TEMP_SENSOR_0 / 1
552
-//#define MAX31865_SENSOR_OHMS_0      100   // (Ω) Typically 100 or 1000 (PT100 or PT1000)
553
-//#define MAX31865_CALIBRATION_OHMS_0 430   // (Ω) Typically 430 for Adafruit PT100; 4300 for Adafruit PT1000
554
-//#define MAX31865_SENSOR_OHMS_1      100
555
-//#define MAX31865_CALIBRATION_OHMS_1 430
553
+#if TEMP_SENSOR_IS_MAX_TC(0)
554
+  #define MAX31865_SENSOR_OHMS_0      100   // (Ω) Typically 100 or 1000 (PT100 or PT1000)
555
+  #define MAX31865_CALIBRATION_OHMS_0 430   // (Ω) Typically 430 for Adafruit PT100; 4300 for Adafruit PT1000
556
+#endif
557
+#if TEMP_SENSOR_IS_MAX_TC(1)
558
+  #define MAX31865_SENSOR_OHMS_1      100
559
+  #define MAX31865_CALIBRATION_OHMS_1 430
560
+#endif
556 561
 
557
-#define TEMP_RESIDENCY_TIME         10  // (seconds) Time to wait for hotend to "settle" in M109
558
-#define TEMP_WINDOW                  1  // (°C) Temperature proximity for the "temperature reached" timer
559
-#define TEMP_HYSTERESIS              3  // (°C) Temperature proximity considered "close enough" to the target
562
+#if HAS_E_TEMP_SENSOR
563
+  #define TEMP_RESIDENCY_TIME         10  // (seconds) Time to wait for hotend to "settle" in M109
564
+  #define TEMP_WINDOW                  1  // (°C) Temperature proximity for the "temperature reached" timer
565
+  #define TEMP_HYSTERESIS              3  // (°C) Temperature proximity considered "close enough" to the target
566
+#endif
560 567
 
561
-#define TEMP_BED_RESIDENCY_TIME     10  // (seconds) Time to wait for bed to "settle" in M190
562
-#define TEMP_BED_WINDOW              1  // (°C) Temperature proximity for the "temperature reached" timer
563
-#define TEMP_BED_HYSTERESIS          3  // (°C) Temperature proximity considered "close enough" to the target
568
+#if TEMP_SENSOR_BED
569
+  #define TEMP_BED_RESIDENCY_TIME     10  // (seconds) Time to wait for bed to "settle" in M190
570
+  #define TEMP_BED_WINDOW              1  // (°C) Temperature proximity for the "temperature reached" timer
571
+  #define TEMP_BED_HYSTERESIS          3  // (°C) Temperature proximity considered "close enough" to the target
572
+#endif
564 573
 
565
-#define TEMP_CHAMBER_RESIDENCY_TIME 10  // (seconds) Time to wait for chamber to "settle" in M191
566
-#define TEMP_CHAMBER_WINDOW          1  // (°C) Temperature proximity for the "temperature reached" timer
567
-#define TEMP_CHAMBER_HYSTERESIS      3  // (°C) Temperature proximity considered "close enough" to the target
574
+#if TEMP_SENSOR_CHAMBER
575
+  #define TEMP_CHAMBER_RESIDENCY_TIME 10  // (seconds) Time to wait for chamber to "settle" in M191
576
+  #define TEMP_CHAMBER_WINDOW          1  // (°C) Temperature proximity for the "temperature reached" timer
577
+  #define TEMP_CHAMBER_HYSTERESIS      3  // (°C) Temperature proximity considered "close enough" to the target
578
+#endif
568 579
 
569 580
 /**
570 581
  * Redundant Temperature Sensor (TEMP_SENSOR_REDUNDANT)
@@ -623,6 +634,8 @@
623 634
 //============================= PID Settings ================================
624 635
 //===========================================================================
625 636
 
637
+// @section hotend temp
638
+
626 639
 // Enable PIDTEMP for PID control or MPCTEMP for Predictive Model.
627 640
 // temperature control. Disable both for bang-bang heating.
628 641
 #define PIDTEMP          // See the PID Tuning Guide at https://reprap.org/wiki/PID_Tuning
@@ -633,7 +646,8 @@
633 646
 #define PID_K1 0.95      // Smoothing factor within any PID loop
634 647
 
635 648
 #if ENABLED(PIDTEMP)
636
-  //#define PID_PARAMS_PER_HOTEND // Uses separate PID parameters for each extruder (useful for mismatched extruders)
649
+  //#define PID_DEBUG             // Print PID debug data to the serial port. Use 'M303 D' to toggle activation.
650
+  //#define PID_PARAMS_PER_HOTEND // Use separate PID parameters for each extruder (useful for mismatched extruders)
637 651
                                   // Set/get with G-code: M301 E[extruder number, 0-2]
638 652
 
639 653
   #if ENABLED(PID_PARAMS_PER_HOTEND)
@@ -655,6 +669,7 @@
655 669
  * Use a physical model of the hotend to control temperature. When configured correctly
656 670
  * this gives better responsiveness and stability than PID and it also removes the need
657 671
  * for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 T to autotune the model.
672
+ * @section mpctemp
658 673
  */
659 674
 #if ENABLED(MPCTEMP)
660 675
   //#define MPC_EDIT_MENU                             // Add MPC editing to the "Advanced Settings" menu. (~1300 bytes of flash)
@@ -707,6 +722,7 @@
707 722
  * impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W
708 723
  * heater. If your configuration is significantly different than this and you don't understand
709 724
  * the issues involved, don't use bed PID until someone else verifies that your hardware works.
725
+ * @section bed temp
710 726
  */
711 727
 //#define PIDTEMPBED
712 728
 
@@ -722,7 +738,7 @@
722 738
 
723 739
 #if ENABLED(PIDTEMPBED)
724 740
   //#define MIN_BED_POWER 0
725
-  //#define PID_BED_DEBUG // Sends debug data to the serial port.
741
+  //#define PID_BED_DEBUG // Print Bed PID debug data to the serial port.
726 742
 
727 743
   // 120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
728 744
   // from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@@ -750,6 +766,7 @@
750 766
  * impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 200W
751 767
  * heater. If your configuration is significantly different than this and you don't understand
752 768
  * the issues involved, don't use chamber PID until someone else verifies that your hardware works.
769
+ * @section chamber temp
753 770
  */
754 771
 //#define PIDTEMPCHAMBER
755 772
 //#define CHAMBER_LIMIT_SWITCHING
@@ -764,7 +781,7 @@
764 781
 
765 782
 #if ENABLED(PIDTEMPCHAMBER)
766 783
   #define MIN_CHAMBER_POWER 0
767
-  //#define PID_CHAMBER_DEBUG // Sends debug data to the serial port.
784
+  //#define PID_CHAMBER_DEBUG // Print Chamber PID debug data to the serial port.
768 785
 
769 786
   // Lasko "MyHeat Personal Heater" (200w) modified with a Fotek SSR-10DA to control only the heating element
770 787
   // and placed inside the small Creality printer enclosure tent.
@@ -778,7 +795,6 @@
778 795
 #endif // PIDTEMPCHAMBER
779 796
 
780 797
 #if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER)
781
-  //#define PID_DEBUG             // Sends debug data to the serial port. Use 'M303 D' to toggle activation.
782 798
   //#define PID_OPENLOOP          // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
783 799
   //#define SLOW_PWM_HEATERS      // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay
784 800
   #define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
@@ -788,7 +804,7 @@
788 804
   //#define PID_AUTOTUNE_MENU     // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of flash)
789 805
 #endif
790 806
 
791
-// @section extruder
807
+// @section safety
792 808
 
793 809
 /**
794 810
  * Prevent extrusion if the temperature is below EXTRUDE_MINTEMP.
@@ -856,6 +872,8 @@
856 872
   #define POLAR_SEGMENTS_PER_SECOND 5
857 873
 #endif
858 874
 
875
+// @section delta
876
+
859 877
 // Enable for DELTA kinematics and configure below
860 878
 //#define DELTA
861 879
 #if ENABLED(DELTA)
@@ -915,6 +933,8 @@
915 933
   //#define DELTA_DIAGONAL_ROD_TRIM_TOWER { 0.0, 0.0, 0.0 }
916 934
 #endif
917 935
 
936
+// @section scara
937
+
918 938
 /**
919 939
  * MORGAN_SCARA was developed by QHARLEY in South Africa in 2012-2013.
920 940
  * Implemented and slightly reworked by JCERNY in June, 2014.
@@ -958,6 +978,8 @@
958 978
 
959 979
 #endif
960 980
 
981
+// @section tpara
982
+
961 983
 // Enable for TPARA kinematics and configure below
962 984
 //#define AXEL_TPARA
963 985
 #if ENABLED(AXEL_TPARA)
@@ -984,6 +1006,8 @@
984 1006
   #define PSI_HOMING_OFFSET    0
985 1007
 #endif
986 1008
 
1009
+// @section machine
1010
+
987 1011
 // Articulated robot (arm). Joints are directly mapped to axes with no kinematics.
988 1012
 //#define ARTICULATED_ROBOT_ARM
989 1013
 
@@ -995,7 +1019,7 @@
995 1019
 //============================== Endstop Settings ===========================
996 1020
 //===========================================================================
997 1021
 
998
-// @section homing
1022
+// @section endstops
999 1023
 
1000 1024
 // Specify here all the endstop connectors that are connected to any endstop or probe.
1001 1025
 // Almost all printers will be using one per axis. Probes will use one or more of the
@@ -1659,7 +1683,7 @@
1659 1683
 //#define V_HOME_DIR -1
1660 1684
 //#define W_HOME_DIR -1
1661 1685
 
1662
-// @section machine
1686
+// @section geometry
1663 1687
 
1664 1688
 // The size of the printable area
1665 1689
 #define X_BED_SIZE 200
@@ -2119,7 +2143,7 @@
2119 2143
 //============================= Additional Features ===========================
2120 2144
 //=============================================================================
2121 2145
 
2122
-// @section extras
2146
+// @section eeprom
2123 2147
 
2124 2148
 /**
2125 2149
  * EEPROM
@@ -2139,6 +2163,8 @@
2139 2163
   //#define EEPROM_INIT_NOW   // Init EEPROM on first boot after a new build.
2140 2164
 #endif
2141 2165
 
2166
+// @section host
2167
+
2142 2168
 //
2143 2169
 // Host Keepalive
2144 2170
 //
@@ -2149,6 +2175,8 @@
2149 2175
 #define DEFAULT_KEEPALIVE_INTERVAL 2  // Number of seconds between "busy" messages. Set with M113.
2150 2176
 #define BUSY_WHILE_HEATING            // Some hosts require "busy" messages even during heating
2151 2177
 
2178
+// @section units
2179
+
2152 2180
 //
2153 2181
 // G20/G21 Inch mode support
2154 2182
 //
@@ -2176,6 +2204,8 @@
2176 2204
 #define PREHEAT_2_TEMP_CHAMBER 35
2177 2205
 #define PREHEAT_2_FAN_SPEED     0 // Value from 0 to 255
2178 2206
 
2207
+// @section motion
2208
+
2179 2209
 /**
2180 2210
  * Nozzle Park
2181 2211
  *
@@ -2274,6 +2304,8 @@
2274 2304
 
2275 2305
 #endif
2276 2306
 
2307
+// @section host
2308
+
2277 2309
 /**
2278 2310
  * Print Job Timer
2279 2311
  *
@@ -2300,6 +2332,8 @@
2300 2332
  */
2301 2333
 #define PRINTJOB_TIMER_AUTOSTART
2302 2334
 
2335
+// @section stats
2336
+
2303 2337
 /**
2304 2338
  * Print Counter
2305 2339
  *
@@ -2317,6 +2351,8 @@
2317 2351
   #define PRINTCOUNTER_SAVE_INTERVAL 60 // (minutes) EEPROM save interval during print
2318 2352
 #endif
2319 2353
 
2354
+// @section security
2355
+
2320 2356
 /**
2321 2357
  * Password
2322 2358
  *
@@ -2352,7 +2388,7 @@
2352 2388
 //============================= LCD and SD support ============================
2353 2389
 //=============================================================================
2354 2390
 
2355
-// @section lcd
2391
+// @section interface
2356 2392
 
2357 2393
 /**
2358 2394
  * LCD LANGUAGE
@@ -2508,6 +2544,7 @@
2508 2544
 //======================== LCD / Controller Selection =========================
2509 2545
 //========================   (Character-based LCDs)   =========================
2510 2546
 //=============================================================================
2547
+// @section lcd
2511 2548
 
2512 2549
 //
2513 2550
 // RepRapDiscount Smart Controller.
@@ -3142,7 +3179,7 @@
3142 3179
 //=============================== Extra Features ==============================
3143 3180
 //=============================================================================
3144 3181
 
3145
-// @section extras
3182
+// @section fans
3146 3183
 
3147 3184
 // Set number of user-controlled fans. Disable to use all board-defined fans.
3148 3185
 // :[1,2,3,4,5,6,7,8]
@@ -3166,14 +3203,18 @@
3166 3203
 // duty cycle is attained.
3167 3204
 //#define SOFT_PWM_DITHER
3168 3205
 
3206
+// @section extras
3207
+
3208
+// Support for the BariCUDA Paste Extruder
3209
+//#define BARICUDA
3210
+
3211
+// @section lights
3212
+
3169 3213
 // Temperature status LEDs that display the hotend and bed temperature.
3170 3214
 // If all hotends, bed temperature, and target temperature are under 54C
3171 3215
 // then the BLUE led is on. Otherwise the RED led is on. (1C hysteresis)
3172 3216
 //#define TEMP_STAT_LEDS
3173 3217
 
3174
-// Support for the BariCUDA Paste Extruder
3175
-//#define BARICUDA
3176
-
3177 3218
 // Support for BlinkM/CyzRgb
3178 3219
 //#define BLINKM
3179 3220
 
@@ -3259,6 +3300,8 @@
3259 3300
   #define PRINTER_EVENT_LEDS
3260 3301
 #endif
3261 3302
 
3303
+// @section servos
3304
+
3262 3305
 /**
3263 3306
  * Number of servos
3264 3307
  *

+ 88
- 14
Marlin/Configuration_adv.h View File

@@ -32,6 +32,24 @@
32 32
  */
33 33
 #define CONFIGURATION_ADV_H_VERSION 02010100
34 34
 
35
+// @section develop
36
+
37
+/**
38
+ * Configuration Dump
39
+ *
40
+ * Dump the configuration as part of the build. (See signature.py)
41
+ * Output files are saved with the build (e.g., .pio/build/mega2560).
42
+ *
43
+ * See `build_all_examples --ini` as an example of config.ini archiving.
44
+ *
45
+ *  1 = marlin_config.json - Dictionary containing the configuration.
46
+ *      This file is also generated for CONFIGURATION_EMBEDDING.
47
+ *  2 = config.ini - File format for PlatformIO preprocessing.
48
+ *  3 = schema.json - The entire configuration schema. (13 = pattern groups)
49
+ *  4 = schema.yml - The entire configuration schema.
50
+ */
51
+//#define CONFIG_DUMP   // :[1:'JSON', 2:'config.ini', 3:'schema.json', 4:'schema.yml']
52
+
35 53
 //===========================================================================
36 54
 //============================= Thermal Settings ============================
37 55
 //===========================================================================
@@ -2545,6 +2563,8 @@
2545 2563
   #endif
2546 2564
 #endif // HAS_MULTI_EXTRUDER
2547 2565
 
2566
+// @section advanced pause
2567
+
2548 2568
 /**
2549 2569
  * Advanced Pause for Filament Change
2550 2570
  *  - Adds the G-code M600 Filament Change to initiate a filament change.
@@ -2603,13 +2623,12 @@
2603 2623
   //#define FILAMENT_UNLOAD_ALL_EXTRUDERS         // Allow M702 to unload all extruders above a minimum target temp (as set by M302)
2604 2624
 #endif
2605 2625
 
2606
-// @section tmc
2607
-
2608 2626
 /**
2609 2627
  * TMC26X Stepper Driver options
2610 2628
  *
2611 2629
  * The TMC26XStepper library is required for this stepper driver.
2612 2630
  * https://github.com/trinamic/TMC26XStepper
2631
+ * @section tmc/tmc26x
2613 2632
  */
2614 2633
 #if HAS_DRIVER(TMC26X)
2615 2634
 
@@ -2747,8 +2766,6 @@
2747 2766
 
2748 2767
 #endif // TMC26X
2749 2768
 
2750
-// @section tmc_smart
2751
-
2752 2769
 /**
2753 2770
  * To use TMC2130, TMC2160, TMC2660, TMC5130, TMC5160 stepper drivers in SPI mode
2754 2771
  * connect your SPI pins to the hardware SPI interface on your board and define
@@ -2764,6 +2781,7 @@
2764 2781
  *
2765 2782
  * TMCStepper library is required to use TMC stepper drivers.
2766 2783
  * https://github.com/teemuatlut/TMCStepper
2784
+ * @section tmc/config
2767 2785
  */
2768 2786
 #if HAS_TRINAMIC_CONFIG
2769 2787
 
@@ -2987,6 +3005,8 @@
2987 3005
     //#define E7_HOLD_MULTIPLIER 0.5
2988 3006
   #endif
2989 3007
 
3008
+  // @section tmc/spi
3009
+
2990 3010
   /**
2991 3011
    * Override default SPI pins for TMC2130, TMC2160, TMC2660, TMC5130 and TMC5160 drivers here.
2992 3012
    * The default pins can be found in your board's pins file.
@@ -3024,6 +3044,8 @@
3024 3044
   //#define TMC_SW_MISO       -1
3025 3045
   //#define TMC_SW_SCK        -1
3026 3046
 
3047
+  // @section tmc/serial
3048
+
3027 3049
   /**
3028 3050
    * Four TMC2209 drivers can use the same HW/SW serial port with hardware configured addresses.
3029 3051
    * Set the address using jumpers on pins MS1 and MS2.
@@ -3059,6 +3081,8 @@
3059 3081
   //#define E6_SLAVE_ADDRESS 0
3060 3082
   //#define E7_SLAVE_ADDRESS 0
3061 3083
 
3084
+  // @section tmc/smart
3085
+
3062 3086
   /**
3063 3087
    * Software enable
3064 3088
    *
@@ -3067,6 +3091,8 @@
3067 3091
    */
3068 3092
   //#define SOFTWARE_DRIVER_ENABLE
3069 3093
 
3094
+  // @section tmc/stealthchop
3095
+
3070 3096
   /**
3071 3097
    * TMC2130, TMC2160, TMC2208, TMC2209, TMC5130 and TMC5160 only
3072 3098
    * Use Trinamic's ultra quiet stepping mode.
@@ -3121,6 +3147,8 @@
3121 3147
   //#define CHOPPER_TIMING_E6 CHOPPER_TIMING_E
3122 3148
   //#define CHOPPER_TIMING_E7 CHOPPER_TIMING_E
3123 3149
 
3150
+  // @section tmc/status
3151
+
3124 3152
   /**
3125 3153
    * Monitor Trinamic drivers
3126 3154
    * for error conditions like overtemperature and short to ground.
@@ -3140,6 +3168,8 @@
3140 3168
     #define STOP_ON_ERROR
3141 3169
   #endif
3142 3170
 
3171
+  // @section tmc/hybrid
3172
+
3143 3173
   /**
3144 3174
    * TMC2130, TMC2160, TMC2208, TMC2209, TMC5130 and TMC5160 only
3145 3175
    * The driver will switch to spreadCycle when stepper speed is over HYBRID_THRESHOLD.
@@ -3196,6 +3226,7 @@
3196 3226
    * homing and adds a guard period for endstop triggering.
3197 3227
    *
3198 3228
    * Comment *_STALL_SENSITIVITY to disable sensorless homing for that axis.
3229
+   * @section tmc/stallguard
3199 3230
    */
3200 3231
   //#define SENSORLESS_HOMING // StallGuard capable drivers only
3201 3232
 
@@ -3219,6 +3250,8 @@
3219 3250
     //#define IMPROVE_HOMING_RELIABILITY
3220 3251
   #endif
3221 3252
 
3253
+  // @section tmc/config
3254
+
3222 3255
   /**
3223 3256
    * TMC Homing stepper phase.
3224 3257
    *
@@ -3258,7 +3291,6 @@
3258 3291
 
3259 3292
 #endif // HAS_TRINAMIC_CONFIG
3260 3293
 
3261
-
3262 3294
 // @section i2cbus
3263 3295
 
3264 3296
 //
@@ -3300,7 +3332,7 @@
3300 3332
   #define I2C_SLAVE_ADDRESS  0  // Set a value from 8 to 127 to act as a slave
3301 3333
 #endif
3302 3334
 
3303
-// @section extras
3335
+// @section photo
3304 3336
 
3305 3337
 /**
3306 3338
  * Photo G-code
@@ -3343,6 +3375,8 @@
3343 3375
   #endif
3344 3376
 #endif
3345 3377
 
3378
+// @section cnc
3379
+
3346 3380
 /**
3347 3381
  * Spindle & Laser control
3348 3382
  *
@@ -3546,6 +3580,8 @@
3546 3580
   #define COOLANT_FLOOD_INVERT false  // Set "true" if the on/off function is reversed
3547 3581
 #endif
3548 3582
 
3583
+// @section filament width
3584
+
3549 3585
 /**
3550 3586
  * Filament Width Sensor
3551 3587
  *
@@ -3579,6 +3615,8 @@
3579 3615
   //#define FILAMENT_LCD_DISPLAY
3580 3616
 #endif
3581 3617
 
3618
+// @section power
3619
+
3582 3620
 /**
3583 3621
  * Power Monitor
3584 3622
  * Monitor voltage (V) and/or current (A), and -when possible- power (W)
@@ -3602,6 +3640,8 @@
3602 3640
   #define POWER_MONITOR_VOLTAGE_OFFSET  0         // Offset (in volts) applied to the calculated voltage
3603 3641
 #endif
3604 3642
 
3643
+// @section safety
3644
+
3605 3645
 /**
3606 3646
  * Stepper Driver Anti-SNAFU Protection
3607 3647
  *
@@ -3611,6 +3651,8 @@
3611 3651
  */
3612 3652
 //#define DISABLE_DRIVER_SAFE_POWER_PROTECT
3613 3653
 
3654
+// @section cnc
3655
+
3614 3656
 /**
3615 3657
  * CNC Coordinate Systems
3616 3658
  *
@@ -3619,6 +3661,8 @@
3619 3661
  */
3620 3662
 //#define CNC_COORDINATE_SYSTEMS
3621 3663
 
3664
+// @section reporting
3665
+
3622 3666
 /**
3623 3667
  * Auto-report fan speed with M123 S<seconds>
3624 3668
  * Requires fans with tachometer pins
@@ -3646,6 +3690,8 @@
3646 3690
   //#define M115_GEOMETRY_REPORT
3647 3691
 #endif
3648 3692
 
3693
+// @section security
3694
+
3649 3695
 /**
3650 3696
  * Expected Printer Check
3651 3697
  * Add the M16 G-code to compare a string to the MACHINE_NAME.
@@ -3653,6 +3699,8 @@
3653 3699
  */
3654 3700
 //#define EXPECTED_PRINTER_CHECK
3655 3701
 
3702
+// @section volumetrics
3703
+
3656 3704
 /**
3657 3705
  * Disable all Volumetric extrusion options
3658 3706
  */
@@ -3681,14 +3729,7 @@
3681 3729
   #endif
3682 3730
 #endif
3683 3731
 
3684
-/**
3685
- * Enable this option for a leaner build of Marlin that removes all
3686
- * workspace offsets, simplifying coordinate transformations, leveling, etc.
3687
- *
3688
- *  - M206 and M428 are disabled.
3689
- *  - G92 will revert to its behavior from Marlin 1.0.
3690
- */
3691
-//#define NO_WORKSPACE_OFFSETS
3732
+// @section reporting
3692 3733
 
3693 3734
 // Extra options for the M114 "Current Position" report
3694 3735
 //#define M114_DETAIL         // Use 'M114` for details to check planner calculations
@@ -3697,6 +3738,8 @@
3697 3738
 
3698 3739
 //#define REPORT_FAN_CHANGE   // Report the new fan speed when changed by M106 (and others)
3699 3740
 
3741
+// @section gcode
3742
+
3700 3743
 /**
3701 3744
  * Spend 28 bytes of SRAM to optimize the G-code parser
3702 3745
  */
@@ -3715,6 +3758,15 @@
3715 3758
 //#define REPETIER_GCODE_M360     // Add commands originally from Repetier FW
3716 3759
 
3717 3760
 /**
3761
+ * Enable this option for a leaner build of Marlin that removes all
3762
+ * workspace offsets, simplifying coordinate transformations, leveling, etc.
3763
+ *
3764
+ *  - M206 and M428 are disabled.
3765
+ *  - G92 will revert to its behavior from Marlin 1.0.
3766
+ */
3767
+//#define NO_WORKSPACE_OFFSETS
3768
+
3769
+/**
3718 3770
  * CNC G-code options
3719 3771
  * Support CNC-style G-code dialects used by laser cutters, drawing machine cams, etc.
3720 3772
  * Note that G0 feedrates should be used with care for 3D printing (if used at all).
@@ -3729,6 +3781,8 @@
3729 3781
   //#define VARIABLE_G0_FEEDRATE // The G0 feedrate is set by F in G0 motion mode
3730 3782
 #endif
3731 3783
 
3784
+// @section gcode
3785
+
3732 3786
 /**
3733 3787
  * Startup commands
3734 3788
  *
@@ -3753,6 +3807,8 @@
3753 3807
  * Up to 25 may be defined, but the actual number is LCD-dependent.
3754 3808
  */
3755 3809
 
3810
+// @section custom main menu
3811
+
3756 3812
 // Custom Menu: Main Menu
3757 3813
 //#define CUSTOM_MENU_MAIN
3758 3814
 #if ENABLED(CUSTOM_MENU_MAIN)
@@ -3783,6 +3839,8 @@
3783 3839
   //#define MAIN_MENU_ITEM_5_CONFIRM
3784 3840
 #endif
3785 3841
 
3842
+// @section custom config menu
3843
+
3786 3844
 // Custom Menu: Configuration Menu
3787 3845
 //#define CUSTOM_MENU_CONFIG
3788 3846
 #if ENABLED(CUSTOM_MENU_CONFIG)
@@ -3813,6 +3871,8 @@
3813 3871
   //#define CONFIG_MENU_ITEM_5_CONFIRM
3814 3872
 #endif
3815 3873
 
3874
+// @section custom buttons
3875
+
3816 3876
 /**
3817 3877
  * User-defined buttons to run custom G-code.
3818 3878
  * Up to 25 may be defined.
@@ -3844,6 +3904,8 @@
3844 3904
   #endif
3845 3905
 #endif
3846 3906
 
3907
+// @section host
3908
+
3847 3909
 /**
3848 3910
  * Host Action Commands
3849 3911
  *
@@ -3869,6 +3931,8 @@
3869 3931
   //#define HOST_SHUTDOWN_MENU_ITEM       // Add a menu item that tells the host to shut down
3870 3932
 #endif
3871 3933
 
3934
+// @section extras
3935
+
3872 3936
 /**
3873 3937
  * Cancel Objects
3874 3938
  *
@@ -3890,6 +3954,7 @@
3890 3954
  * Alternative Supplier: https://reliabuild3d.com/
3891 3955
  *
3892 3956
  * Reliabuild encoders have been modified to improve reliability.
3957
+ * @section i2c encoders
3893 3958
  */
3894 3959
 
3895 3960
 //#define I2C_POSITION_ENCODERS
@@ -3961,6 +4026,7 @@
3961 4026
 
3962 4027
 /**
3963 4028
  * Analog Joystick(s)
4029
+ * @section joystick
3964 4030
  */
3965 4031
 //#define JOYSTICK
3966 4032
 #if ENABLED(JOYSTICK)
@@ -3985,6 +4051,7 @@
3985 4051
  * Modern replacement for the Prusa TMC_Z_CALIBRATION.
3986 4052
  * Adds capability to work with any adjustable current drivers.
3987 4053
  * Implemented as G34 because M915 is deprecated.
4054
+ * @section calibrate
3988 4055
  */
3989 4056
 //#define MECHANICAL_GANTRY_CALIBRATION
3990 4057
 #if ENABLED(MECHANICAL_GANTRY_CALIBRATION)
@@ -4002,6 +4069,7 @@
4002 4069
 /**
4003 4070
  * Instant freeze / unfreeze functionality
4004 4071
  * Potentially useful for emergency stop that allows being resumed.
4072
+ * @section interface
4005 4073
  */
4006 4074
 //#define FREEZE_FEATURE
4007 4075
 #if ENABLED(FREEZE_FEATURE)
@@ -4014,6 +4082,7 @@
4014 4082
  *
4015 4083
  * Add support for a low-cost 8x8 LED Matrix based on the Max7219 chip as a realtime status display.
4016 4084
  * Requires 3 signal wires. Some useful debug options are included to demonstrate its usage.
4085
+ * @section debug matrix
4017 4086
  */
4018 4087
 //#define MAX7219_DEBUG
4019 4088
 #if ENABLED(MAX7219_DEBUG)
@@ -4052,6 +4121,7 @@
4052 4121
  * Support for Synchronized Z moves when used with NanoDLP. G0/G1 axis moves will
4053 4122
  * output a "Z_move_comp" string to enable synchronization with DLP projector exposure.
4054 4123
  * This feature allows you to use [[WaitForDoneMessage]] instead of M400 commands.
4124
+ * @section nanodlp
4055 4125
  */
4056 4126
 //#define NANODLP_Z_SYNC
4057 4127
 #if ENABLED(NANODLP_Z_SYNC)
@@ -4060,6 +4130,7 @@
4060 4130
 
4061 4131
 /**
4062 4132
  * Ethernet. Use M552 to enable and set the IP address.
4133
+ * @section network
4063 4134
  */
4064 4135
 #if HAS_ETHERNET
4065 4136
   #define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D }  // A MAC address unique to your network
@@ -4087,6 +4158,8 @@
4087 4158
   //#include "Configuration_Secure.h" // External file with WiFi SSID / Password
4088 4159
 #endif
4089 4160
 
4161
+// @section multi-material
4162
+
4090 4163
 /**
4091 4164
  * Průša Multi-Material Unit (MMU)
4092 4165
  * Enable in Configuration.h
@@ -4192,6 +4265,7 @@
4192 4265
 
4193 4266
 /**
4194 4267
  * Advanced Print Counter settings
4268
+ * @section stats
4195 4269
  */
4196 4270
 #if ENABLED(PRINTCOUNTER)
4197 4271
   #define SERVICE_WARNING_BUZZES  3

+ 107
- 0
Marlin/base.ini View File

@@ -0,0 +1,107 @@
1
+#
2
+# Marlin Firmware
3
+# base.ini - A base ini to include for testing
4
+#
5
+[config:base]
6
+motherboard                              = BOARD_RAMPS_14_EFB
7
+serial_port                              = 0
8
+baudrate                                 = 250000
9
+
10
+use_watchdog                             = on
11
+thermal_protection_hotends               = on
12
+thermal_protection_hysteresis            = 4
13
+thermal_protection_period                = 40
14
+
15
+bufsize                                  = 4
16
+block_buffer_size                        = 16
17
+max_cmd_size                             = 96
18
+
19
+extruders                                = 1
20
+temp_sensor_0                            = 1
21
+
22
+temp_hysteresis                          = 3
23
+heater_0_mintemp                         = 5
24
+heater_0_maxtemp                         = 275
25
+preheat_1_temp_hotend                    = 180
26
+
27
+bang_max                                 = 255
28
+pidtemp                                  = on
29
+pid_k1                                   = 0.95
30
+pid_max                                  = BANG_MAX
31
+pid_functional_range                     = 10
32
+
33
+default_kp                               = 22.20
34
+default_ki                               = 1.08
35
+default_kd                               = 114.00
36
+
37
+x_driver_type                            = A4988
38
+y_driver_type                            = A4988
39
+z_driver_type                            = A4988
40
+e0_driver_type                           = A4988
41
+
42
+x_bed_size                               = 200
43
+x_min_pos                                = 0
44
+x_max_pos                                = X_BED_SIZE
45
+
46
+y_bed_size                               = 200
47
+y_min_pos                                = 0
48
+y_max_pos                                = Y_BED_SIZE
49
+
50
+z_min_pos                                = 0
51
+z_max_pos                                = 200
52
+
53
+x_home_dir                               = -1
54
+y_home_dir                               = -1
55
+z_home_dir                               = -1
56
+
57
+use_xmin_plug                            = on
58
+use_ymin_plug                            = on
59
+use_zmin_plug                            = on
60
+
61
+x_min_endstop_inverting                  = false
62
+y_min_endstop_inverting                  = false
63
+z_min_endstop_inverting                  = false
64
+
65
+default_axis_steps_per_unit              = { 80, 80, 400, 500 }
66
+axis_relative_modes                      = { false, false, false, false }
67
+default_max_feedrate                     = { 300, 300, 5, 25 }
68
+default_max_acceleration                 = { 3000, 3000, 100, 10000 }
69
+
70
+homing_feedrate_mm_m                     = { (50*60), (50*60), (4*60) }
71
+homing_bump_divisor                      = { 2, 2, 4 }
72
+
73
+x_enable_on                              = 0
74
+y_enable_on                              = 0
75
+z_enable_on                              = 0
76
+e_enable_on                              = 0
77
+
78
+invert_x_dir                             = false
79
+invert_y_dir                             = true
80
+invert_z_dir                             = false
81
+invert_e0_dir                            = false
82
+
83
+invert_e_step_pin                        = false
84
+invert_x_step_pin                        = false
85
+invert_y_step_pin                        = false
86
+invert_z_step_pin                        = false
87
+
88
+disable_x                                = false
89
+disable_y                                = false
90
+disable_z                                = false
91
+disable_e                                = false
92
+
93
+proportional_font_ratio                  = 1.0
94
+default_nominal_filament_dia             = 1.75
95
+
96
+junction_deviation_mm                    = 0.013
97
+
98
+default_acceleration                     = 3000
99
+default_travel_acceleration              = 3000
100
+default_retract_acceleration             = 3000
101
+
102
+default_minimumfeedrate                  = 0.0
103
+default_mintravelfeedrate                = 0.0
104
+
105
+minimum_planner_speed                    = 0.05
106
+min_steps_per_segment                    = 6
107
+default_minsegmenttime                   = 20000

+ 203
- 0
Marlin/config.ini View File

@@ -0,0 +1,203 @@
1
+#
2
+# Marlin Firmware
3
+# config.ini - Options to apply before the build
4
+#
5
+[config:base]
6
+ini_use_config                           = none
7
+#ini_use_config                          = base.ini, another.ini
8
+#ini_use_config                          = example/Creality/Ender-5 Plus
9
+#ini_use_config                          = https://me.myserver.com/path/to/configs
10
+#ini_use_config                          = base
11
+#config_dump                             = 2
12
+
13
+motherboard                              = BOARD_RAMPS_14_EFB
14
+serial_port                              = 0
15
+baudrate                                 = 250000
16
+
17
+use_watchdog                             = on
18
+thermal_protection_hotends               = on
19
+thermal_protection_hysteresis            = 4
20
+thermal_protection_period                = 40
21
+
22
+bufsize                                  = 4
23
+block_buffer_size                        = 16
24
+max_cmd_size                             = 96
25
+
26
+extruders                                = 1
27
+temp_sensor_0                            = 1
28
+
29
+temp_hysteresis                          = 3
30
+heater_0_mintemp                         = 5
31
+heater_0_maxtemp                         = 275
32
+preheat_1_temp_hotend                    = 180
33
+
34
+bang_max                                 = 255
35
+pidtemp                                  = on
36
+pid_k1                                   = 0.95
37
+pid_max                                  = BANG_MAX
38
+pid_functional_range                     = 10
39
+
40
+default_kp                               = 22.20
41
+default_ki                               = 1.08
42
+default_kd                               = 114.00
43
+
44
+x_driver_type                            = A4988
45
+y_driver_type                            = A4988
46
+z_driver_type                            = A4988
47
+e0_driver_type                           = A4988
48
+
49
+x_bed_size                               = 200
50
+x_min_pos                                = 0
51
+x_max_pos                                = X_BED_SIZE
52
+
53
+y_bed_size                               = 200
54
+y_min_pos                                = 0
55
+y_max_pos                                = Y_BED_SIZE
56
+
57
+z_min_pos                                = 0
58
+z_max_pos                                = 200
59
+
60
+x_home_dir                               = -1
61
+y_home_dir                               = -1
62
+z_home_dir                               = -1
63
+
64
+use_xmin_plug                            = on
65
+use_ymin_plug                            = on
66
+use_zmin_plug                            = on
67
+
68
+x_min_endstop_inverting                  = false
69
+y_min_endstop_inverting                  = false
70
+z_min_endstop_inverting                  = false
71
+
72
+default_axis_steps_per_unit              = { 80, 80, 400, 500 }
73
+axis_relative_modes                      = { false, false, false, false }
74
+default_max_feedrate                     = { 300, 300, 5, 25 }
75
+default_max_acceleration                 = { 3000, 3000, 100, 10000 }
76
+
77
+homing_feedrate_mm_m                     = { (50*60), (50*60), (4*60) }
78
+homing_bump_divisor                      = { 2, 2, 4 }
79
+
80
+x_enable_on                              = 0
81
+y_enable_on                              = 0
82
+z_enable_on                              = 0
83
+e_enable_on                              = 0
84
+
85
+invert_x_dir                             = false
86
+invert_y_dir                             = true
87
+invert_z_dir                             = false
88
+invert_e0_dir                            = false
89
+
90
+invert_e_step_pin                        = false
91
+invert_x_step_pin                        = false
92
+invert_y_step_pin                        = false
93
+invert_z_step_pin                        = false
94
+
95
+disable_x                                = false
96
+disable_y                                = false
97
+disable_z                                = false
98
+disable_e                                = false
99
+
100
+proportional_font_ratio                  = 1.0
101
+default_nominal_filament_dia             = 1.75
102
+
103
+junction_deviation_mm                    = 0.013
104
+
105
+default_acceleration                     = 3000
106
+default_travel_acceleration              = 3000
107
+default_retract_acceleration             = 3000
108
+
109
+default_minimumfeedrate                  = 0.0
110
+default_mintravelfeedrate                = 0.0
111
+
112
+minimum_planner_speed                    = 0.05
113
+min_steps_per_segment                    = 6
114
+default_minsegmenttime                   = 20000
115
+
116
+[config:basic]
117
+bed_overshoot                            = 10
118
+busy_while_heating                       = on
119
+default_ejerk                            = 5.0
120
+default_keepalive_interval               = 2
121
+default_leveling_fade_height             = 0.0
122
+disable_inactive_extruder                = on
123
+display_charset_hd44780                  = JAPANESE
124
+eeprom_boot_silent                       = on
125
+eeprom_chitchat                          = on
126
+endstoppullups                           = on
127
+extrude_maxlength                        = 200
128
+extrude_mintemp                          = 170
129
+host_keepalive_feature                   = on
130
+hotend_overshoot                         = 15
131
+jd_handle_small_segments                 = on
132
+lcd_info_screen_style                    = 0
133
+lcd_language                             = en
134
+max_bed_power                            = 255
135
+mesh_inset                               = 0
136
+min_software_endstops                    = on
137
+max_software_endstops                    = on
138
+min_software_endstop_x                   = on
139
+min_software_endstop_y                   = on
140
+min_software_endstop_z                   = on
141
+max_software_endstop_x                   = on
142
+max_software_endstop_y                   = on
143
+max_software_endstop_z                   = on
144
+preheat_1_fan_speed                      = 0
145
+preheat_1_label                          = "PLA"
146
+preheat_1_temp_bed                       = 70
147
+prevent_cold_extrusion                   = on
148
+prevent_lengthy_extrude                  = on
149
+printjob_timer_autostart                 = on
150
+probing_margin                           = 10
151
+show_bootscreen                          = on
152
+soft_pwm_scale                           = 0
153
+string_config_h_author                   = "(none, default config)"
154
+temp_bed_hysteresis                      = 3
155
+temp_bed_residency_time                  = 10
156
+temp_bed_window                          = 1
157
+temp_residency_time                      = 10
158
+temp_window                              = 1
159
+validate_homing_endstops                 = on
160
+xy_probe_feedrate                        = (133*60)
161
+z_clearance_between_probes               = 5
162
+z_clearance_deploy_probe                 = 10
163
+z_clearance_multi_probe                  = 5
164
+
165
+[config:advanced]
166
+arc_support                              = on
167
+auto_report_temperatures                 = on
168
+autotemp                                 = on
169
+autotemp_oldweight                       = 0.98
170
+bed_check_interval                       = 5000
171
+default_stepper_deactive_time            = 120
172
+default_volumetric_extruder_limit        = 0.00
173
+disable_inactive_e                       = true
174
+disable_inactive_x                       = true
175
+disable_inactive_y                       = true
176
+disable_inactive_z                       = true
177
+e0_auto_fan_pin                          = -1
178
+encoder_100x_steps_per_sec               = 80
179
+encoder_10x_steps_per_sec                = 30
180
+encoder_rate_multiplier                  = on
181
+extended_capabilities_report             = on
182
+extruder_auto_fan_speed                  = 255
183
+extruder_auto_fan_temperature            = 50
184
+fanmux0_pin                              = -1
185
+fanmux1_pin                              = -1
186
+fanmux2_pin                              = -1
187
+faster_gcode_parser                      = on
188
+homing_bump_mm                           = { 5, 5, 2 }
189
+max_arc_segment_mm                       = 1.0
190
+min_arc_segment_mm                       = 0.1
191
+min_circle_segments                      = 72
192
+n_arc_correction                         = 25
193
+serial_overrun_protection                = on
194
+slowdown                                 = on
195
+slowdown_divisor                         = 2
196
+temp_sensor_bed                          = 0
197
+thermal_protection_bed_hysteresis        = 2
198
+thermocouple_max_errors                  = 15
199
+tx_buffer_size                           = 0
200
+watch_bed_temp_increase                  = 2
201
+watch_bed_temp_period                    = 60
202
+watch_temp_increase                      = 2
203
+watch_temp_period                        = 20

+ 2
- 2
Marlin/src/MarlinCore.cpp View File

@@ -1220,10 +1220,10 @@ void setup() {
1220 1220
   SETUP_RUN(hal.init());
1221 1221
 
1222 1222
   // Init and disable SPI thermocouples; this is still needed
1223
-  #if TEMP_SENSOR_0_IS_MAX_TC || (TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E0))
1223
+  #if TEMP_SENSOR_IS_MAX_TC(0) || (TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E0))
1224 1224
     OUT_WRITE(TEMP_0_CS_PIN, HIGH);  // Disable
1225 1225
   #endif
1226
-  #if TEMP_SENSOR_1_IS_MAX_TC || (TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E1))
1226
+  #if TEMP_SENSOR_IS_MAX_TC(1) || (TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E1))
1227 1227
     OUT_WRITE(TEMP_1_CS_PIN, HIGH);
1228 1228
   #endif
1229 1229
 

+ 5
- 0
Marlin/src/core/macros.h View File

@@ -730,3 +730,8 @@
730 730
 #define __MAPLIST() _MAPLIST
731 731
 
732 732
 #define MAPLIST(OP,V...) EVAL(_MAPLIST(OP,V))
733
+
734
+// Temperature Sensor Config
735
+#define _HAS_E_TEMP(N) || (TEMP_SENSOR_##N != 0)
736
+#define HAS_E_TEMP_SENSOR (0 REPEAT(EXTRUDERS, _HAS_E_TEMP))
737
+#define TEMP_SENSOR_IS_MAX_TC(T) (TEMP_SENSOR_##T == -5 || TEMP_SENSOR_##T == -3 || TEMP_SENSOR_##T == -2)

+ 1
- 1
Marlin/src/gcode/temp/M303.cpp View File

@@ -48,7 +48,7 @@
48 48
 
49 49
 void GcodeSuite::M303() {
50 50
 
51
-  #if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
51
+  #if HAS_PID_DEBUG
52 52
     if (parser.seen_test('D')) {
53 53
       thermalManager.pid_debug_flag ^= true;
54 54
       SERIAL_ECHO_START();

+ 53
- 0
Marlin/src/inc/Conditionals_LCD.h View File

@@ -668,6 +668,31 @@
668 668
   #define E_MANUAL EXTRUDERS
669 669
 #endif
670 670
 
671
+#if E_STEPPERS <= 7
672
+  #undef INVERT_E7_DIR
673
+  #if E_STEPPERS <= 6
674
+    #undef INVERT_E6_DIR
675
+    #if E_STEPPERS <= 5
676
+      #undef INVERT_E5_DIR
677
+      #if E_STEPPERS <= 4
678
+        #undef INVERT_E4_DIR
679
+        #if E_STEPPERS <= 3
680
+          #undef INVERT_E3_DIR
681
+          #if E_STEPPERS <= 2
682
+            #undef INVERT_E2_DIR
683
+            #if E_STEPPERS <= 1
684
+              #undef INVERT_E1_DIR
685
+              #if E_STEPPERS == 0
686
+                #undef INVERT_E0_DIR
687
+              #endif
688
+            #endif
689
+          #endif
690
+        #endif
691
+      #endif
692
+    #endif
693
+  #endif
694
+#endif
695
+
671 696
 /**
672 697
  * Number of Linear Axes (e.g., XYZIJKUVW)
673 698
  * All the logical axes except for the tool (E) axis
@@ -768,6 +793,9 @@
768 793
   #undef Y_MIN_POS
769 794
   #undef Y_MAX_POS
770 795
   #undef MANUAL_Y_HOME_POS
796
+  #undef MIN_SOFTWARE_ENDSTOP_Y
797
+  #undef MAX_SOFTWARE_ENDSTOP_Y
798
+  #undef SAFE_BED_LEVELING_START_Y
771 799
 #endif
772 800
 
773 801
 #if !HAS_Z_AXIS
@@ -785,6 +813,9 @@
785 813
   #undef Z_MIN_POS
786 814
   #undef Z_MAX_POS
787 815
   #undef MANUAL_Z_HOME_POS
816
+  #undef MIN_SOFTWARE_ENDSTOP_Z
817
+  #undef MAX_SOFTWARE_ENDSTOP_Z
818
+  #undef SAFE_BED_LEVELING_START_Z
788 819
 #endif
789 820
 
790 821
 #if !HAS_I_AXIS
@@ -799,6 +830,9 @@
799 830
   #undef I_MIN_POS
800 831
   #undef I_MAX_POS
801 832
   #undef MANUAL_I_HOME_POS
833
+  #undef MIN_SOFTWARE_ENDSTOP_I
834
+  #undef MAX_SOFTWARE_ENDSTOP_I
835
+  #undef SAFE_BED_LEVELING_START_I
802 836
 #endif
803 837
 
804 838
 #if !HAS_J_AXIS
@@ -813,6 +847,9 @@
813 847
   #undef J_MIN_POS
814 848
   #undef J_MAX_POS
815 849
   #undef MANUAL_J_HOME_POS
850
+  #undef MIN_SOFTWARE_ENDSTOP_J
851
+  #undef MAX_SOFTWARE_ENDSTOP_J
852
+  #undef SAFE_BED_LEVELING_START_J
816 853
 #endif
817 854
 
818 855
 #if !HAS_K_AXIS
@@ -827,6 +864,9 @@
827 864
   #undef K_MIN_POS
828 865
   #undef K_MAX_POS
829 866
   #undef MANUAL_K_HOME_POS
867
+  #undef MIN_SOFTWARE_ENDSTOP_K
868
+  #undef MAX_SOFTWARE_ENDSTOP_K
869
+  #undef SAFE_BED_LEVELING_START_K
830 870
 #endif
831 871
 
832 872
 #if !HAS_U_AXIS
@@ -841,6 +881,9 @@
841 881
   #undef U_MIN_POS
842 882
   #undef U_MAX_POS
843 883
   #undef MANUAL_U_HOME_POS
884
+  #undef MIN_SOFTWARE_ENDSTOP_U
885
+  #undef MAX_SOFTWARE_ENDSTOP_U
886
+  #undef SAFE_BED_LEVELING_START_U
844 887
 #endif
845 888
 
846 889
 #if !HAS_V_AXIS
@@ -855,6 +898,9 @@
855 898
   #undef V_MIN_POS
856 899
   #undef V_MAX_POS
857 900
   #undef MANUAL_V_HOME_POS
901
+  #undef MIN_SOFTWARE_ENDSTOP_V
902
+  #undef MAX_SOFTWARE_ENDSTOP_V
903
+  #undef SAFE_BED_LEVELING_START_V
858 904
 #endif
859 905
 
860 906
 #if !HAS_W_AXIS
@@ -869,6 +915,9 @@
869 915
   #undef W_MIN_POS
870 916
   #undef W_MAX_POS
871 917
   #undef MANUAL_W_HOME_POS
918
+  #undef MIN_SOFTWARE_ENDSTOP_W
919
+  #undef MAX_SOFTWARE_ENDSTOP_W
920
+  #undef SAFE_BED_LEVELING_START_W
872 921
 #endif
873 922
 
874 923
 #ifdef X2_DRIVER_TYPE
@@ -1398,6 +1447,10 @@
1398 1447
   #define EXTRUDE_MINTEMP 170
1399 1448
 #endif
1400 1449
 
1450
+#if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
1451
+  #define HAS_PID_DEBUG 1
1452
+#endif
1453
+
1401 1454
 /**
1402 1455
  * TFT Displays
1403 1456
  *

+ 30
- 9
Marlin/src/inc/Conditionals_adv.h View File

@@ -116,6 +116,31 @@
116 116
   #undef STEALTHCHOP_E
117 117
 #endif
118 118
 
119
+#if HOTENDS <= 7
120
+  #undef E7_AUTO_FAN_PIN
121
+  #if HOTENDS <= 6
122
+    #undef E6_AUTO_FAN_PIN
123
+    #if HOTENDS <= 5
124
+      #undef E5_AUTO_FAN_PIN
125
+      #if HOTENDS <= 4
126
+        #undef E4_AUTO_FAN_PIN
127
+        #if HOTENDS <= 3
128
+          #undef E3_AUTO_FAN_PIN
129
+          #if HOTENDS <= 2
130
+            #undef E2_AUTO_FAN_PIN
131
+            #if HOTENDS <= 1
132
+              #undef E1_AUTO_FAN_PIN
133
+              #if HOTENDS == 0
134
+                #undef E0_AUTO_FAN_PIN
135
+              #endif
136
+            #endif
137
+          #endif
138
+        #endif
139
+      #endif
140
+    #endif
141
+  #endif
142
+#endif
143
+
119 144
 /**
120 145
  * Temperature Sensors; define what sensor(s) we have.
121 146
  */
@@ -154,8 +179,7 @@
154 179
   #define REDUNDANT_TEMP_MATCH(...) 0
155 180
 #endif
156 181
 
157
-#if TEMP_SENSOR_0 == -5 || TEMP_SENSOR_0 == -3 || TEMP_SENSOR_0 == -2
158
-  #define TEMP_SENSOR_0_IS_MAX_TC 1
182
+#if TEMP_SENSOR_IS_MAX_TC(0)
159 183
   #if TEMP_SENSOR_0 == -5
160 184
     #define TEMP_SENSOR_0_IS_MAX31865 1
161 185
     #define TEMP_SENSOR_0_MAX_TC_TMIN    0
@@ -191,8 +215,7 @@
191 215
   #undef HEATER_0_MAXTEMP
192 216
 #endif
193 217
 
194
-#if TEMP_SENSOR_1 == -5 || TEMP_SENSOR_1 == -3 || TEMP_SENSOR_1 == -2
195
-  #define TEMP_SENSOR_1_IS_MAX_TC 1
218
+#if TEMP_SENSOR_IS_MAX_TC(1)
196 219
   #if TEMP_SENSOR_1 == -5
197 220
     #define TEMP_SENSOR_1_IS_MAX31865 1
198 221
     #define TEMP_SENSOR_1_MAX_TC_TMIN    0
@@ -238,9 +261,7 @@
238 261
   #undef HEATER_1_MAXTEMP
239 262
 #endif
240 263
 
241
-#if TEMP_SENSOR_REDUNDANT == -5 || TEMP_SENSOR_REDUNDANT == -3 || TEMP_SENSOR_REDUNDANT == -2
242
-  #define TEMP_SENSOR_REDUNDANT_IS_MAX_TC 1
243
-
264
+#if TEMP_SENSOR_IS_MAX_TC(REDUNDANT)
244 265
   #if TEMP_SENSOR_REDUNDANT == -5
245 266
     #if !REDUNDANT_TEMP_MATCH(SOURCE, E0) && !REDUNDANT_TEMP_MATCH(SOURCE, E1)
246 267
       #error "MAX31865 Thermocouples (-5) not supported for TEMP_SENSOR_REDUNDANT_SOURCE other than TEMP_SENSOR_0/TEMP_SENSOR_1 (0/1)."
@@ -282,7 +303,7 @@
282 303
     #endif
283 304
   #endif
284 305
 
285
-  #if (TEMP_SENSOR_0_IS_MAX_TC && TEMP_SENSOR_REDUNDANT != TEMP_SENSOR_0) || (TEMP_SENSOR_1_IS_MAX_TC && TEMP_SENSOR_REDUNDANT != TEMP_SENSOR_1)
306
+  #if (TEMP_SENSOR_IS_MAX_TC(0) && TEMP_SENSOR_REDUNDANT != TEMP_SENSOR_0) || (TEMP_SENSOR_IS_MAX_TC(1) && TEMP_SENSOR_REDUNDANT != TEMP_SENSOR_1)
286 307
     #if   TEMP_SENSOR_REDUNDANT == -5
287 308
       #error "If MAX31865 Thermocouple (-5) is used for TEMP_SENSOR_0/TEMP_SENSOR_1 then TEMP_SENSOR_REDUNDANT must match."
288 309
     #elif TEMP_SENSOR_REDUNDANT == -3
@@ -304,7 +325,7 @@
304 325
   #endif
305 326
 #endif
306 327
 
307
-#if TEMP_SENSOR_0_IS_MAX_TC || TEMP_SENSOR_1_IS_MAX_TC || TEMP_SENSOR_REDUNDANT_IS_MAX_TC
328
+#if TEMP_SENSOR_IS_MAX_TC(0) || TEMP_SENSOR_IS_MAX_TC(1) || TEMP_SENSOR_IS_MAX_TC(REDUNDANT)
308 329
   #define HAS_MAX_TC 1
309 330
 #endif
310 331
 #if TEMP_SENSOR_0_IS_MAX6675 || TEMP_SENSOR_1_IS_MAX6675 || TEMP_SENSOR_REDUNDANT_IS_MAX6675

+ 6
- 6
Marlin/src/inc/Conditionals_post.h View File

@@ -681,7 +681,7 @@
681 681
 #if HAS_MAX_TC
682 682
 
683 683
   // Translate old _SS, _CS, _SCK, _DO, _DI, _MISO, and _MOSI PIN defines.
684
-  #if TEMP_SENSOR_0_IS_MAX_TC || (TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E1))
684
+  #if TEMP_SENSOR_IS_MAX_TC(0) || (TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E1))
685 685
 
686 686
     #if !PIN_EXISTS(TEMP_0_CS) // SS, CS
687 687
       #if PIN_EXISTS(MAX6675_SS)
@@ -748,9 +748,9 @@
748 748
       #endif
749 749
     #endif
750 750
 
751
-  #endif // TEMP_SENSOR_0_IS_MAX_TC
751
+  #endif // TEMP_SENSOR_IS_MAX_TC(0)
752 752
 
753
-  #if TEMP_SENSOR_1_IS_MAX_TC || (TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E1))
753
+  #if TEMP_SENSOR_IS_MAX_TC(1) || (TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E1))
754 754
 
755 755
     #if !PIN_EXISTS(TEMP_1_CS) // SS2, CS2
756 756
       #if PIN_EXISTS(MAX6675_SS2)
@@ -817,7 +817,7 @@
817 817
       #endif
818 818
     #endif
819 819
 
820
-  #endif // TEMP_SENSOR_1_IS_MAX_TC
820
+  #endif // TEMP_SENSOR_IS_MAX_TC(1)
821 821
 
822 822
   //
823 823
   // User-defined thermocouple libraries
@@ -2656,7 +2656,7 @@
2656 2656
 //
2657 2657
 // ADC Temp Sensors (Thermistor or Thermocouple with amplifier ADC interface)
2658 2658
 //
2659
-#define HAS_ADC_TEST(P) (PIN_EXISTS(TEMP_##P) && TEMP_SENSOR_##P != 0 && NONE(TEMP_SENSOR_##P##_IS_MAX_TC, TEMP_SENSOR_##P##_IS_DUMMY))
2659
+#define HAS_ADC_TEST(P) (PIN_EXISTS(TEMP_##P) && TEMP_SENSOR_##P != 0 && !TEMP_SENSOR_IS_MAX_TC(P) && !TEMP_SENSOR_##P##_IS_DUMMY)
2660 2660
 #if HOTENDS > 0 && HAS_ADC_TEST(0)
2661 2661
   #define HAS_TEMP_ADC_0 1
2662 2662
 #endif
@@ -2700,7 +2700,7 @@
2700 2700
   #define HAS_TEMP_ADC_REDUNDANT 1
2701 2701
 #endif
2702 2702
 
2703
-#define HAS_TEMP(N) ANY(HAS_TEMP_ADC_##N, TEMP_SENSOR_##N##_IS_MAX_TC, TEMP_SENSOR_##N##_IS_DUMMY)
2703
+#define HAS_TEMP(N) (TEMP_SENSOR_IS_MAX_TC(N) || EITHER(HAS_TEMP_ADC_##N, TEMP_SENSOR_##N##_IS_DUMMY))
2704 2704
 #if HAS_HOTEND && HAS_TEMP(0)
2705 2705
   #define HAS_TEMP_HOTEND 1
2706 2706
 #endif

+ 4
- 4
Marlin/src/inc/SanityCheck.h View File

@@ -2328,9 +2328,9 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
2328 2328
     #error "TEMP_SENSOR_REDUNDANT_TARGET can't be COOLER without TEMP_COOLER_PIN defined."
2329 2329
   #endif
2330 2330
 
2331
-  #if TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E0) && !PIN_EXISTS(TEMP_0_CS)
2331
+  #if TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E0) && !PIN_EXISTS(TEMP_0_CS)
2332 2332
     #error "TEMP_SENSOR_REDUNDANT MAX Thermocouple with TEMP_SENSOR_REDUNDANT_SOURCE E0 requires TEMP_0_CS_PIN."
2333
-  #elif TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E1) && !PIN_EXISTS(TEMP_1_CS)
2333
+  #elif TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E1) && !PIN_EXISTS(TEMP_1_CS)
2334 2334
     #error "TEMP_SENSOR_REDUNDANT MAX Thermocouple with TEMP_SENSOR_REDUNDANT_SOURCE E1 requires TEMP_1_CS_PIN."
2335 2335
   #endif
2336 2336
 #endif
@@ -2343,7 +2343,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
2343 2343
   #error "TEMP_0_PIN or TEMP_0_CS_PIN not defined for this board."
2344 2344
 #elif HAS_EXTRUDERS && !HAS_HEATER_0
2345 2345
   #error "HEATER_0_PIN not defined for this board."
2346
-#elif TEMP_SENSOR_0_IS_MAX_TC && !PIN_EXISTS(TEMP_0_CS)
2346
+#elif TEMP_SENSOR_IS_MAX_TC(0) && !PIN_EXISTS(TEMP_0_CS)
2347 2347
   #error "TEMP_SENSOR_0 MAX thermocouple requires TEMP_0_CS_PIN."
2348 2348
 #elif HAS_HOTEND && !HAS_TEMP_HOTEND && !TEMP_SENSOR_0_IS_DUMMY
2349 2349
   #error "TEMP_0_PIN (required for TEMP_SENSOR_0) not defined for this board."
@@ -2352,7 +2352,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
2352 2352
 #endif
2353 2353
 
2354 2354
 #if HAS_MULTI_HOTEND
2355
-  #if TEMP_SENSOR_1_IS_MAX_TC && !PIN_EXISTS(TEMP_1_CS)
2355
+  #if TEMP_SENSOR_IS_MAX_TC(1) && !PIN_EXISTS(TEMP_1_CS)
2356 2356
     #error "TEMP_SENSOR_1 MAX thermocouple requires TEMP_1_CS_PIN."
2357 2357
   #elif TEMP_SENSOR_1 == 0
2358 2358
     #error "TEMP_SENSOR_1 is required with 2 or more HOTENDS."

+ 21
- 16
Marlin/src/module/temperature.cpp View File

@@ -77,7 +77,7 @@
77 77
 
78 78
 // MAX TC related macros
79 79
 #define TEMP_SENSOR_IS_MAX(n, M) (ENABLED(TEMP_SENSOR_##n##_IS_MAX##M) || (ENABLED(TEMP_SENSOR_REDUNDANT_IS_MAX##M) && REDUNDANT_TEMP_MATCH(SOURCE, E##n)))
80
-#define TEMP_SENSOR_IS_ANY_MAX_TC(n) (ENABLED(TEMP_SENSOR_##n##_IS_MAX_TC) || (ENABLED(TEMP_SENSOR_REDUNDANT_IS_MAX_TC) && REDUNDANT_TEMP_MATCH(SOURCE, E##n)))
80
+#define TEMP_SENSOR_IS_ANY_MAX_TC(n) (TEMP_SENSOR_IS_MAX_TC(n) || (TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E##n)))
81 81
 
82 82
 // LIB_MAX6675 can be added to the build_flags in platformio.ini to use a user-defined library
83 83
 // If LIB_MAX6675 is not on the build_flags then raw SPI reads will be used.
@@ -1317,8 +1317,7 @@ void Temperature::min_temp_error(const heater_id_t heater_id) {
1317 1317
   _temp_error(heater_id, F(STR_T_MINTEMP), GET_TEXT_F(MSG_ERR_MINTEMP));
1318 1318
 }
1319 1319
 
1320
-#if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
1321
-  #define HAS_PID_DEBUG 1
1320
+#if HAS_PID_DEBUG
1322 1321
   bool Temperature::pid_debug_flag; // = false
1323 1322
 #endif
1324 1323
 
@@ -1856,15 +1855,15 @@ void Temperature::task() {
1856 1855
   if (!updateTemperaturesIfReady()) return; // Will also reset the watchdog if temperatures are ready
1857 1856
 
1858 1857
   #if DISABLED(IGNORE_THERMOCOUPLE_ERRORS)
1859
-    #if TEMP_SENSOR_0_IS_MAX_TC
1858
+    #if TEMP_SENSOR_IS_MAX_TC(0)
1860 1859
       if (degHotend(0) > _MIN(HEATER_0_MAXTEMP, TEMP_SENSOR_0_MAX_TC_TMAX - 1.0)) max_temp_error(H_E0);
1861 1860
       if (degHotend(0) < _MAX(HEATER_0_MINTEMP, TEMP_SENSOR_0_MAX_TC_TMIN + .01)) min_temp_error(H_E0);
1862 1861
     #endif
1863
-    #if TEMP_SENSOR_1_IS_MAX_TC
1862
+    #if TEMP_SENSOR_IS_MAX_TC(1)
1864 1863
       if (degHotend(1) > _MIN(HEATER_1_MAXTEMP, TEMP_SENSOR_1_MAX_TC_TMAX - 1.0)) max_temp_error(H_E1);
1865 1864
       if (degHotend(1) < _MAX(HEATER_1_MINTEMP, TEMP_SENSOR_1_MAX_TC_TMIN + .01)) min_temp_error(H_E1);
1866 1865
     #endif
1867
-    #if TEMP_SENSOR_REDUNDANT_IS_MAX_TC
1866
+    #if TEMP_SENSOR_IS_MAX_TC(REDUNDANT)
1868 1867
       if (degRedundant() > TEMP_SENSOR_REDUNDANT_MAX_TC_TMAX - 1.0) max_temp_error(H_REDUNDANT);
1869 1868
       if (degRedundant() < TEMP_SENSOR_REDUNDANT_MAX_TC_TMIN + .01) min_temp_error(H_REDUNDANT);
1870 1869
     #endif
@@ -2072,7 +2071,7 @@ void Temperature::task() {
2072 2071
       case 0:
2073 2072
         #if TEMP_SENSOR_0_IS_CUSTOM
2074 2073
           return user_thermistor_to_deg_c(CTI_HOTEND_0, raw);
2075
-        #elif TEMP_SENSOR_0_IS_MAX_TC
2074
+        #elif TEMP_SENSOR_IS_MAX_TC(0)
2076 2075
           #if TEMP_SENSOR_0_IS_MAX31865
2077 2076
             return TERN(LIB_INTERNAL_MAX31865,
2078 2077
               max31865_0.temperature(raw),
@@ -2091,7 +2090,7 @@ void Temperature::task() {
2091 2090
       case 1:
2092 2091
         #if TEMP_SENSOR_1_IS_CUSTOM
2093 2092
           return user_thermistor_to_deg_c(CTI_HOTEND_1, raw);
2094
-        #elif TEMP_SENSOR_1_IS_MAX_TC
2093
+        #elif TEMP_SENSOR_IS_MAX_TC(1)
2095 2094
           #if TEMP_SENSOR_0_IS_MAX31865
2096 2095
             return TERN(LIB_INTERNAL_MAX31865,
2097 2096
               max31865_1.temperature(raw),
@@ -2275,9 +2274,9 @@ void Temperature::task() {
2275 2274
   celsius_float_t Temperature::analog_to_celsius_redundant(const raw_adc_t raw) {
2276 2275
     #if TEMP_SENSOR_REDUNDANT_IS_CUSTOM
2277 2276
       return user_thermistor_to_deg_c(CTI_REDUNDANT, raw);
2278
-    #elif TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E0)
2277
+    #elif TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E0)
2279 2278
       return TERN(TEMP_SENSOR_REDUNDANT_IS_MAX31865, max31865_0.temperature(raw), (int16_t)raw * 0.25);
2280
-    #elif TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E1)
2279
+    #elif TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E1)
2281 2280
       return TERN(TEMP_SENSOR_REDUNDANT_IS_MAX31865, max31865_1.temperature(raw), (int16_t)raw * 0.25);
2282 2281
     #elif TEMP_SENSOR_REDUNDANT_IS_THERMISTOR
2283 2282
       SCAN_THERMISTOR_TABLE(TEMPTABLE_REDUNDANT, TEMPTABLE_REDUNDANT_LEN);
@@ -2308,9 +2307,15 @@ void Temperature::updateTemperaturesFromRawValues() {
2308 2307
 
2309 2308
   hal.watchdog_refresh(); // Reset because raw_temps_ready was set by the interrupt
2310 2309
 
2311
-  TERN_(TEMP_SENSOR_0_IS_MAX_TC, temp_hotend[0].setraw(READ_MAX_TC(0)));
2312
-  TERN_(TEMP_SENSOR_1_IS_MAX_TC, temp_hotend[1].setraw(READ_MAX_TC(1)));
2313
-  TERN_(TEMP_SENSOR_REDUNDANT_IS_MAX_TC, temp_redundant.setraw(READ_MAX_TC(HEATER_ID(TEMP_SENSOR_REDUNDANT_SOURCE))));
2310
+  #if TEMP_SENSOR_IS_MAX_TC(0)
2311
+    temp_hotend[0].setraw(READ_MAX_TC(0));
2312
+  #endif
2313
+  #if TEMP_SENSOR_IS_MAX_TC(1)
2314
+    temp_hotend[1].setraw(READ_MAX_TC(1));
2315
+  #endif
2316
+  #if TEMP_SENSOR_IS_MAX_TC(REDUNDANT)
2317
+    temp_redundant.setraw(READ_MAX_TC(HEATER_ID(TEMP_SENSOR_REDUNDANT_SOURCE)));
2318
+  #endif
2314 2319
 
2315 2320
   #if HAS_HOTEND
2316 2321
     HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].getraw(), e);
@@ -3139,15 +3144,15 @@ void Temperature::disable_all_heaters() {
3139 3144
 void Temperature::update_raw_temperatures() {
3140 3145
 
3141 3146
   // TODO: can this be collapsed into a HOTEND_LOOP()?
3142
-  #if HAS_TEMP_ADC_0 && !TEMP_SENSOR_0_IS_MAX_TC
3147
+  #if HAS_TEMP_ADC_0 && !TEMP_SENSOR_IS_MAX_TC(0)
3143 3148
     temp_hotend[0].update();
3144 3149
   #endif
3145 3150
 
3146
-  #if HAS_TEMP_ADC_1 && !TEMP_SENSOR_1_IS_MAX_TC
3151
+  #if HAS_TEMP_ADC_1 && !TEMP_SENSOR_IS_MAX_TC(1)
3147 3152
     temp_hotend[1].update();
3148 3153
   #endif
3149 3154
 
3150
-  #if HAS_TEMP_ADC_REDUNDANT && !TEMP_SENSOR_REDUNDANT_IS_MAX_TC
3155
+  #if HAS_TEMP_ADC_REDUNDANT && !TEMP_SENSOR_IS_MAX_TC(REDUNDANT)
3151 3156
     temp_redundant.update();
3152 3157
   #endif
3153 3158
 

+ 2
- 2
Marlin/src/module/temperature.h View File

@@ -953,7 +953,7 @@ class Temperature {
953 953
      */
954 954
     #if HAS_PID_HEATING
955 955
 
956
-      #if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
956
+      #if HAS_PID_DEBUG
957 957
         static bool pid_debug_flag;
958 958
       #endif
959 959
 
@@ -1035,7 +1035,7 @@ class Temperature {
1035 1035
 
1036 1036
     // MAX Thermocouples
1037 1037
     #if HAS_MAX_TC
1038
-      #define MAX_TC_COUNT COUNT_ENABLED(TEMP_SENSOR_0_IS_MAX_TC, TEMP_SENSOR_1_IS_MAX_TC, TEMP_SENSOR_REDUNDANT_IS_MAX_TC)
1038
+      #define MAX_TC_COUNT TEMP_SENSOR_IS_MAX_TC(0) + TEMP_SENSOR_IS_MAX_TC(1) + TEMP_SENSOR_IS_MAX_TC(REDUNDANT)
1039 1039
       #if MAX_TC_COUNT > 1
1040 1040
         #define HAS_MULTI_MAX_TC 1
1041 1041
         #define READ_MAX_TC(N) read_max_tc(N)

+ 236
- 0
buildroot/share/PlatformIO/scripts/configuration.py View File

@@ -0,0 +1,236 @@
1
+#
2
+# configuration.py
3
+# Apply options from config.ini to the existing Configuration headers
4
+#
5
+import re, shutil, configparser
6
+from pathlib import Path
7
+
8
+verbose = 0
9
+def blab(str,level=1):
10
+	if verbose >= level: print(f"[config] {str}")
11
+
12
+def config_path(cpath):
13
+	return Path("Marlin", cpath)
14
+
15
+# Apply a single name = on/off ; name = value ; etc.
16
+# TODO: Limit to the given (optional) configuration
17
+def apply_opt(name, val, conf=None):
18
+	if name == "lcd": name, val = val, "on"
19
+
20
+	# Create a regex to match the option and capture parts of the line
21
+	regex = re.compile(r'^(\s*)(//\s*)?(#define\s+)(' + name + r'\b)(\s*)(.*?)(\s*)(//.*)?$', re.IGNORECASE)
22
+
23
+	# Find and enable and/or update all matches
24
+	for file in ("Configuration.h", "Configuration_adv.h"):
25
+		fullpath = config_path(file)
26
+		lines = fullpath.read_text().split('\n')
27
+		found = False
28
+		for i in range(len(lines)):
29
+			line = lines[i]
30
+			match = regex.match(line)
31
+			if match and match[4].upper() == name.upper():
32
+				found = True
33
+				# For boolean options un/comment the define
34
+				if val in ("on", "", None):
35
+					newline = re.sub(r'^(\s*)//+\s*(#define)(\s{1,3})?(\s*)', r'\1\2 \4', line)
36
+				elif val == "off":
37
+					newline = re.sub(r'^(\s*)(#define)(\s{1,3})?(\s*)', r'\1//\2 \4', line)
38
+				else:
39
+					# For options with values, enable and set the value
40
+					newline = match[1] + match[3] + match[4] + match[5] + val
41
+					if match[8]:
42
+						sp = match[7] if match[7] else ' '
43
+						newline += sp + match[8]
44
+				lines[i] = newline
45
+				blab(f"Set {name} to {val}")
46
+
47
+		# If the option was found, write the modified lines
48
+		if found:
49
+			fullpath.write_text('\n'.join(lines))
50
+			break
51
+
52
+	# If the option didn't appear in either config file, add it
53
+	if not found:
54
+		# OFF options are added as disabled items so they appear
55
+		# in config dumps. Useful for custom settings.
56
+		prefix = ""
57
+		if val == "off":
58
+			prefix, val = "//", ""	# Item doesn't appear in config dump
59
+			#val = "false"			# Item appears in config dump
60
+
61
+		# Uppercase the option unless already mixed/uppercase
62
+		added = name.upper() if name.islower() else name
63
+
64
+		# Add the provided value after the name
65
+		if val != "on" and val != "" and val is not None:
66
+			added += " " + val
67
+
68
+		# Prepend the new option after the first set of #define lines
69
+		fullpath = config_path("Configuration.h")
70
+		with fullpath.open() as f:
71
+			lines = f.readlines()
72
+			linenum = 0
73
+			gotdef = False
74
+			for line in lines:
75
+				isdef = line.startswith("#define")
76
+				if not gotdef:
77
+					gotdef = isdef
78
+				elif not isdef:
79
+					break
80
+				linenum += 1
81
+			lines.insert(linenum, f"{prefix}#define {added} // Added by config.ini\n")
82
+			fullpath.write_text('\n'.join(lines))
83
+
84
+# Fetch configuration files from GitHub given the path.
85
+# Return True if any files were fetched.
86
+def fetch_example(path):
87
+	if path.endswith("/"):
88
+		path = path[:-1]
89
+
90
+	url = path.replace("%", "%25").replace(" ", "%20")
91
+	if not path.startswith('http'):
92
+		url = "https://raw.githubusercontent.com/MarlinFirmware/Configurations/bugfix-2.1.x/config/%s" % url
93
+
94
+	# Find a suitable fetch command
95
+	if shutil.which("curl") is not None:
96
+		fetch = "curl -L -s -S -f -o"
97
+	elif shutil.which("wget") is not None:
98
+		fetch = "wget -q -O"
99
+	else:
100
+		blab("Couldn't find curl or wget", -1)
101
+		return False
102
+
103
+	import os
104
+
105
+	# Reset configurations to default
106
+	os.system("git reset --hard HEAD")
107
+
108
+	gotfile = False
109
+
110
+	# Try to fetch the remote files
111
+	for fn in ("Configuration.h", "Configuration_adv.h", "_Bootscreen.h", "_Statusscreen.h"):
112
+		if os.system("%s wgot %s/%s >/dev/null 2>&1" % (fetch, url, fn)) == 0:
113
+			shutil.move('wgot', config_path(fn))
114
+			gotfile = True
115
+
116
+	if Path('wgot').exists():
117
+		shutil.rmtree('wgot')
118
+
119
+	return gotfile
120
+
121
+def section_items(cp, sectkey):
122
+	return cp.items(sectkey) if sectkey in cp.sections() else []
123
+
124
+# Apply all items from a config section
125
+def apply_ini_by_name(cp, sect):
126
+	iniok = True
127
+	if sect in ('config:base', 'config:root'):
128
+		iniok = False
129
+		items = section_items(cp, 'config:base') + section_items(cp, 'config:root')
130
+	else:
131
+		items = cp.items(sect)
132
+
133
+	for item in items:
134
+		if iniok or not item[0].startswith('ini_'):
135
+			apply_opt(item[0], item[1])
136
+
137
+# Apply all config sections from a parsed file
138
+def apply_all_sections(cp):
139
+	for sect in cp.sections():
140
+		if sect.startswith('config:'):
141
+			apply_ini_by_name(cp, sect)
142
+
143
+# Apply certain config sections from a parsed file
144
+def apply_sections(cp, ckey='all', addbase=False):
145
+	blab("[config] apply section key: %s" % ckey)
146
+	if ckey == 'all':
147
+		apply_all_sections(cp)
148
+	else:
149
+		# Apply the base/root config.ini settings after external files are done
150
+		if addbase or ckey in ('base', 'root'):
151
+			apply_ini_by_name(cp, 'config:base')
152
+
153
+		# Apply historically 'Configuration.h' settings everywhere
154
+		if ckey == 'basic':
155
+			apply_ini_by_name(cp, 'config:basic')
156
+
157
+		# Apply historically Configuration_adv.h settings everywhere
158
+		# (Some of which rely on defines in 'Conditionals_LCD.h')
159
+		elif ckey in ('adv', 'advanced'):
160
+			apply_ini_by_name(cp, 'config:advanced')
161
+
162
+		# Apply a specific config:<name> section directly
163
+		elif ckey.startswith('config:'):
164
+			apply_ini_by_name(cp, ckey)
165
+
166
+# Apply settings from a top level config.ini
167
+def apply_config_ini(cp):
168
+	blab("=" * 20 + " Gather 'config.ini' entries...")
169
+
170
+	# Pre-scan for ini_use_config to get config_keys
171
+	base_items = section_items(cp, 'config:base') + section_items(cp, 'config:root')
172
+	config_keys = ['base']
173
+	for ikey, ival in base_items:
174
+		if ikey == 'ini_use_config':
175
+			config_keys = [ x.strip() for x in ival.split(',') ]
176
+
177
+	# For each ini_use_config item perform an action
178
+	for ckey in config_keys:
179
+		addbase = False
180
+
181
+		# For a key ending in .ini load and parse another .ini file
182
+		if ckey.endswith('.ini'):
183
+			sect = 'base'
184
+			if '@' in ckey: sect, ckey = ckey.split('@')
185
+			other_ini = configparser.ConfigParser()
186
+			other_ini.read(config_path(ckey))
187
+			apply_sections(other_ini, sect)
188
+
189
+		# (Allow 'example/' as a shortcut for 'examples/')
190
+		elif ckey.startswith('example/'):
191
+			ckey = 'examples' + ckey[7:]
192
+
193
+		# For 'examples/<path>' fetch an example set from GitHub.
194
+		# For https?:// do a direct fetch of the URL.
195
+		elif ckey.startswith('examples/') or ckey.startswith('http'):
196
+			addbase = True
197
+			fetch_example(ckey)
198
+
199
+		# Apply keyed sections after external files are done
200
+		apply_sections(cp, 'config:' + ckey, addbase)
201
+
202
+if __name__ == "__main__":
203
+	#
204
+	# From command line use the given file name
205
+	#
206
+	import sys
207
+	args = sys.argv[1:]
208
+	if len(args) > 0:
209
+		if args[0].endswith('.ini'):
210
+			ini_file = args[0]
211
+		else:
212
+			print("Usage: %s <.ini file>" % sys.argv[0])
213
+	else:
214
+		ini_file = config_path('config.ini')
215
+
216
+	if ini_file:
217
+		user_ini = configparser.ConfigParser()
218
+		user_ini.read(ini_file)
219
+		apply_config_ini(user_ini)
220
+
221
+else:
222
+	#
223
+	# From within PlatformIO use the loaded INI file
224
+	#
225
+	import pioutil
226
+	if pioutil.is_pio_build():
227
+
228
+		Import("env")
229
+
230
+		try:
231
+			verbose = int(env.GetProjectOption('custom_verbose'))
232
+		except:
233
+			pass
234
+
235
+		from platformio.project.config import ProjectConfig
236
+		apply_config_ini(ProjectConfig())

+ 403
- 0
buildroot/share/PlatformIO/scripts/schema.py View File

@@ -0,0 +1,403 @@
1
+#!/usr/bin/env python3
2
+#
3
+# schema.py
4
+#
5
+# Used by signature.py via common-dependencies.py to generate a schema file during the PlatformIO build.
6
+# This script can also be run standalone from within the Marlin repo to generate all schema files.
7
+#
8
+import re,json
9
+from pathlib import Path
10
+
11
+def extend_dict(d:dict, k:tuple):
12
+	if len(k) >= 1 and k[0] not in d:
13
+		d[k[0]] = {}
14
+	if len(k) >= 2 and k[1] not in d[k[0]]:
15
+		d[k[0]][k[1]] = {}
16
+	if len(k) >= 3 and k[2] not in d[k[0]][k[1]]:
17
+		d[k[0]][k[1]][k[2]] = {}
18
+
19
+grouping_patterns = [
20
+	re.compile(r'^([XYZIJKUVW]|[XYZ]2|Z[34]|E[0-7])$'),
21
+	re.compile(r'^AXIS\d$'),
22
+	re.compile(r'^(MIN|MAX)$'),
23
+	re.compile(r'^[0-8]$'),
24
+	re.compile(r'^HOTEND[0-7]$'),
25
+	re.compile(r'^(HOTENDS|BED|PROBE|COOLER)$'),
26
+	re.compile(r'^[XYZIJKUVW]M(IN|AX)$')
27
+]
28
+# If the indexed part of the option name matches a pattern
29
+# then add it to the dictionary.
30
+def find_grouping(gdict, filekey, sectkey, optkey, pindex):
31
+	optparts = optkey.split('_')
32
+	if 1 < len(optparts) > pindex:
33
+		for patt in grouping_patterns:
34
+			if patt.match(optparts[pindex]):
35
+				subkey = optparts[pindex]
36
+				modkey = '_'.join(optparts)
37
+				optparts[pindex] = '*'
38
+				wildkey = '_'.join(optparts)
39
+				kkey = f'{filekey}|{sectkey}|{wildkey}'
40
+				if kkey not in gdict: gdict[kkey] = []
41
+				gdict[kkey].append((subkey, modkey))
42
+
43
+# Build a list of potential groups. Only those with multiple items will be grouped.
44
+def group_options(schema):
45
+	for pindex in range(10, -1, -1):
46
+		found_groups = {}
47
+		for filekey, f in schema.items():
48
+			for sectkey, s in f.items():
49
+				for optkey in s:
50
+					find_grouping(found_groups, filekey, sectkey, optkey, pindex)
51
+
52
+		fkeys = [ k for k in found_groups.keys() ]
53
+		for kkey in fkeys:
54
+			items = found_groups[kkey]
55
+			if len(items) > 1:
56
+				f, s, w = kkey.split('|')
57
+				extend_dict(schema, (f, s, w))						# Add wildcard group to schema
58
+				for subkey, optkey in items:						# Add all items to wildcard group
59
+					schema[f][s][w][subkey] = schema[f][s][optkey]	# Move non-wildcard item to wildcard group
60
+					del schema[f][s][optkey]
61
+			del found_groups[kkey]
62
+
63
+# Extract all board names from boards.h
64
+def load_boards():
65
+	bpath = Path("Marlin/src/core/boards.h")
66
+	if bpath.is_file():
67
+		with bpath.open() as bfile:
68
+			boards = []
69
+			for line in bfile:
70
+				if line.startswith("#define BOARD_"):
71
+					bname = line.split()[1]
72
+					if bname != "BOARD_UNKNOWN": boards.append(bname)
73
+			return "['" + "','".join(boards) + "']"
74
+	return ''
75
+
76
+#
77
+# Extract a schema from the current configuration files
78
+#
79
+def extract():
80
+	# Load board names from boards.h
81
+	boards = load_boards()
82
+
83
+	# Parsing states
84
+	class Parse:
85
+		NORMAL			= 0 # No condition yet
86
+		BLOCK_COMMENT	= 1 # Looking for the end of the block comment
87
+		EOL_COMMENT		= 2 # EOL comment started, maybe add the next comment?
88
+		GET_SENSORS		= 3 # Gathering temperature sensor options
89
+		ERROR			= 9 # Syntax error
90
+
91
+	# List of files to process, with shorthand
92
+	filekey = { 'Configuration.h':'basic', 'Configuration_adv.h':'advanced' }
93
+	# A JSON object to store the data
94
+	sch_out = { 'basic':{}, 'advanced':{} }
95
+	# Regex for #define NAME [VALUE] [COMMENT] with sanitized line
96
+	defgrep = re.compile(r'^(//)?\s*(#define)\s+([A-Za-z0-9_]+)\s*(.*?)\s*(//.+)?$')
97
+	# Defines to ignore
98
+	ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_DUMP')
99
+	# Start with unknown state
100
+	state = Parse.NORMAL
101
+	# Serial ID
102
+	sid = 0
103
+	# Loop through files and parse them line by line
104
+	for fn, fk in filekey.items():
105
+		with Path("Marlin", fn).open() as fileobj:
106
+			section = 'none'		# Current Settings section
107
+			line_number = 0			# Counter for the line number of the file
108
+			conditions = []			# Create a condition stack for the current file
109
+			comment_buff = []		# A temporary buffer for comments
110
+			options_json = ''		# A buffer for the most recent options JSON found
111
+			eol_options = False		# The options came from end of line, so only apply once
112
+			join_line = False		# A flag that the line should be joined with the previous one
113
+			line = ''				# A line buffer to handle \ continuation
114
+			last_added_ref = None	# Reference to the last added item
115
+			# Loop through the lines in the file
116
+			for the_line in fileobj.readlines():
117
+				line_number += 1
118
+
119
+				# Clean the line for easier parsing
120
+				the_line = the_line.strip()
121
+
122
+				if join_line:	# A previous line is being made longer
123
+					line += (' ' if line else '') + the_line
124
+				else:			# Otherwise, start the line anew
125
+					line, line_start = the_line, line_number
126
+
127
+				# If the resulting line ends with a \, don't process now.
128
+				# Strip the end off. The next line will be joined with it.
129
+				join_line = line.endswith("\\")
130
+				if join_line:
131
+					line = line[:-1].strip()
132
+					continue
133
+				else:
134
+					line_end = line_number
135
+
136
+				defmatch = defgrep.match(line)
137
+
138
+				# Special handling for EOL comments after a #define.
139
+				# At this point the #define is already digested and inserted,
140
+				# so we have to extend it
141
+				if state == Parse.EOL_COMMENT:
142
+					# If the line is not a comment, we're done with the EOL comment
143
+					if not defmatch and the_line.startswith('//'):
144
+						comment_buff.append(the_line[2:].strip())
145
+					else:
146
+						last_added_ref['comment'] = ' '.join(comment_buff)
147
+						comment_buff = []
148
+						state = Parse.NORMAL
149
+
150
+				def use_comment(c, opt, sec, bufref):
151
+					if c.startswith(':'):				# If the comment starts with : then it has magic JSON
152
+						d = c[1:].strip()				# Strip the leading :
153
+						cbr = c.rindex('}') if d.startswith('{') else c.rindex(']') if d.startswith('[') else 0
154
+						if cbr:
155
+							opt, cmt = c[1:cbr+1].strip(), c[cbr+1:].strip()
156
+							if cmt != '': bufref.append(cmt)
157
+						else:
158
+							opt = c[1:].strip()
159
+					elif c.startswith('@section'):		# Start a new section
160
+						sec = c[8:].strip()
161
+					elif not c.startswith('========'):
162
+						bufref.append(c)
163
+					return opt, sec
164
+
165
+				# In a block comment, capture lines up to the end of the comment.
166
+				# Assume nothing follows the comment closure.
167
+				if state in (Parse.BLOCK_COMMENT, Parse.GET_SENSORS):
168
+					endpos = line.find('*/')
169
+					if endpos < 0:
170
+						cline = line
171
+					else:
172
+						cline, line = line[:endpos].strip(), line[endpos+2:].strip()
173
+
174
+						# Temperature sensors are done
175
+						if state == Parse.GET_SENSORS:
176
+							options_json = f'[ {options_json[:-2]} ]'
177
+
178
+						state = Parse.NORMAL
179
+
180
+					# Strip the leading '*' from block comments
181
+					if cline.startswith('*'): cline = cline[1:].strip()
182
+
183
+					# Collect temperature sensors
184
+					if state == Parse.GET_SENSORS:
185
+						sens = re.match(r'^(-?\d+)\s*:\s*(.+)$', cline)
186
+						if sens:
187
+							s2 = sens[2].replace("'","''")
188
+							options_json += f"{sens[1]}:'{s2}', "
189
+
190
+					elif state == Parse.BLOCK_COMMENT:
191
+
192
+						# Look for temperature sensors
193
+						if cline == "Temperature sensors available:":
194
+							state, cline = Parse.GET_SENSORS, "Temperature Sensors"
195
+
196
+						options_json, section = use_comment(cline, options_json, section, comment_buff)
197
+
198
+				# For the normal state we're looking for any non-blank line
199
+				elif state == Parse.NORMAL:
200
+					# Skip a commented define when evaluating comment opening
201
+					st = 2 if re.match(r'^//\s*#define', line) else 0
202
+					cpos1 = line.find('/*')		# Start a block comment on the line?
203
+					cpos2 = line.find('//', st)	# Start an end of line comment on the line?
204
+
205
+					# Only the first comment starter gets evaluated
206
+					cpos = -1
207
+					if cpos1 != -1 and (cpos1 < cpos2 or cpos2 == -1):
208
+						cpos = cpos1
209
+						comment_buff = []
210
+						state = Parse.BLOCK_COMMENT
211
+						eol_options = False
212
+
213
+					elif cpos2 != -1 and (cpos2 < cpos1 or cpos1 == -1):
214
+						cpos = cpos2
215
+
216
+						# Expire end-of-line options after first use
217
+						if cline.startswith(':'): eol_options = True
218
+
219
+						# Comment after a define may be continued on the following lines
220
+						if state == Parse.NORMAL and defmatch != None and cpos > 10:
221
+							state = Parse.EOL_COMMENT
222
+							comment_buff = []
223
+
224
+					# Process the start of a new comment
225
+					if cpos != -1:
226
+						cline, line = line[cpos+2:].strip(), line[:cpos].strip()
227
+
228
+						# Strip leading '*' from block comments
229
+						if state == Parse.BLOCK_COMMENT:
230
+							if cline.startswith('*'): cline = cline[1:].strip()
231
+
232
+						# Buffer a non-empty comment start
233
+						if cline != '':
234
+							options_json, section = use_comment(cline, options_json, section, comment_buff)
235
+
236
+					# If the line has nothing before the comment, go to the next line
237
+					if line == '':
238
+						options_json = ''
239
+						continue
240
+
241
+					# Parenthesize the given expression if needed
242
+					def atomize(s):
243
+						if s == '' \
244
+						or re.match(r'^[A-Za-z0-9_]*(\([^)]+\))?$', s) \
245
+						or re.match(r'^[A-Za-z0-9_]+ == \d+?$', s):
246
+							return s
247
+						return f'({s})'
248
+
249
+					#
250
+					# The conditions stack is an array containing condition-arrays.
251
+					# Each condition-array lists the conditions for the current block.
252
+					# IF/N/DEF adds a new condition-array to the stack.
253
+					# ELSE/ELIF/ENDIF pop the condition-array.
254
+					# ELSE/ELIF negate the last item in the popped condition-array.
255
+					# ELIF adds a new condition to the end of the array.
256
+					# ELSE/ELIF re-push the condition-array.
257
+					#
258
+					cparts = line.split()
259
+					iselif, iselse = cparts[0] == '#elif', cparts[0] == '#else'
260
+					if iselif or iselse or cparts[0] == '#endif':
261
+						if len(conditions) == 0:
262
+							raise Exception(f'no #if block at line {line_number}')
263
+
264
+						# Pop the last condition-array from the stack
265
+						prev = conditions.pop()
266
+
267
+						if iselif or iselse:
268
+							prev[-1] = '!' + prev[-1] # Invert the last condition
269
+							if iselif: prev.append(atomize(line[5:].strip()))
270
+							conditions.append(prev)
271
+
272
+					elif cparts[0] == '#if':
273
+						conditions.append([ atomize(line[3:].strip()) ])
274
+					elif cparts[0] == '#ifdef':
275
+						conditions.append([ f'defined({line[6:].strip()})' ])
276
+					elif cparts[0] == '#ifndef':
277
+						conditions.append([ f'!defined({line[7:].strip()})' ])
278
+
279
+					# Handle a complete #define line
280
+					elif defmatch != None:
281
+
282
+						# Get the match groups into vars
283
+						enabled, define_name, val = defmatch[1] == None, defmatch[3], defmatch[4]
284
+
285
+						# Increment the serial ID
286
+						sid += 1
287
+
288
+						# Create a new dictionary for the current #define
289
+						define_info = {
290
+							'section': section,
291
+							'name': define_name,
292
+							'enabled': enabled,
293
+							'line': line_start,
294
+							'sid': sid
295
+						}
296
+
297
+						if val != '': define_info['value'] = val
298
+
299
+						# Type is based on the value
300
+						if val == '':
301
+							value_type = 'switch'
302
+						elif re.match(r'^(true|false)$', val):
303
+							value_type = 'bool'
304
+							val = val == 'true'
305
+						elif re.match(r'^[-+]?\s*\d+$', val):
306
+							value_type = 'int'
307
+							val = int(val)
308
+						elif re.match(r'[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?', val):
309
+							value_type = 'float'
310
+							val = float(val.replace('f',''))
311
+						else:
312
+							value_type = 'string'	if val[0] == '"' \
313
+									else 'char'		if val[0] == "'" \
314
+									else 'state'	if re.match(r'^(LOW|HIGH)$', val) \
315
+									else 'enum'		if re.match(r'^[A-Za-z0-9_]{3,}$', val) \
316
+									else 'int[]'	if re.match(r'^{(\s*[-+]?\s*\d+\s*(,\s*)?)+}$', val) \
317
+									else 'float[]'	if re.match(r'^{(\s*[-+]?\s*(\d+\.|\d*\.\d+)([eE][-+]?\d+)?[fF]?\s*(,\s*)?)+}$', val) \
318
+									else 'array'	if val[0] == '{' \
319
+									else ''
320
+
321
+						if value_type != '': define_info['type'] = value_type
322
+
323
+						# Join up accumulated conditions with &&
324
+						if conditions: define_info['requires'] = ' && '.join(sum(conditions, []))
325
+
326
+						# If the comment_buff is not empty, add the comment to the info
327
+						if comment_buff:
328
+							full_comment = '\n'.join(comment_buff)
329
+
330
+							# An EOL comment will be added later
331
+							# The handling could go here instead of above
332
+							if state == Parse.EOL_COMMENT:
333
+								define_info['comment'] = ''
334
+							else:
335
+								define_info['comment'] = full_comment
336
+								comment_buff = []
337
+
338
+							# If the comment specifies units, add that to the info
339
+							units = re.match(r'^\(([^)]+)\)', full_comment)
340
+							if units:
341
+								units = units[1]
342
+								if units == 's' or units == 'sec': units = 'seconds'
343
+								define_info['units'] = units
344
+
345
+						# Set the options for the current #define
346
+						if define_name == "MOTHERBOARD" and boards != '':
347
+							define_info['options'] = boards
348
+						elif options_json != '':
349
+							define_info['options'] = options_json
350
+							if eol_options: options_json = ''
351
+
352
+						# Create section dict if it doesn't exist yet
353
+						if section not in sch_out[fk]: sch_out[fk][section] = {}
354
+
355
+						# If define has already been seen...
356
+						if define_name in sch_out[fk][section]:
357
+							info = sch_out[fk][section][define_name]
358
+							if isinstance(info, dict): info = [ info ]	# Convert a single dict into a list
359
+							info.append(define_info)					# Add to the list
360
+						else:
361
+							# Add the define dict with name as key
362
+							sch_out[fk][section][define_name] = define_info
363
+
364
+						if state == Parse.EOL_COMMENT:
365
+							last_added_ref = define_info
366
+
367
+	return sch_out
368
+
369
+def dump_json(schema:dict, jpath:Path):
370
+	with jpath.open('w') as jfile:
371
+		json.dump(schema, jfile, ensure_ascii=False, indent=2)
372
+
373
+def dump_yaml(schema:dict, ypath:Path):
374
+	import yaml
375
+	with ypath.open('w') as yfile:
376
+		yaml.dump(schema, yfile, default_flow_style=False, width=120, indent=2)
377
+
378
+def main():
379
+	try:
380
+		schema = extract()
381
+	except Exception as exc:
382
+		print("Error: " + str(exc))
383
+		schema = None
384
+
385
+	if schema:
386
+		print("Generating JSON ...")
387
+		dump_json(schema, Path('schema.json'))
388
+		group_options(schema)
389
+		dump_json(schema, Path('schema_grouped.json'))
390
+
391
+		try:
392
+			import yaml
393
+		except ImportError:
394
+			print("Installing YAML module ...")
395
+			import subprocess
396
+			subprocess.run(['python3', '-m', 'pip', 'install', 'pyyaml'])
397
+			import yaml
398
+
399
+		print("Generating YML ...")
400
+		dump_yaml(schema, Path('schema.yml'))
401
+
402
+if __name__ == '__main__':
403
+	main()

+ 90
- 13
buildroot/share/PlatformIO/scripts/signature.py View File

@@ -1,7 +1,9 @@
1 1
 #
2 2
 # signature.py
3 3
 #
4
-import os,subprocess,re,json,hashlib
4
+import subprocess,re,json,hashlib
5
+import schema
6
+from pathlib import Path
5 7
 
6 8
 #
7 9
 # Return all macro names in a header as an array, so we can take
@@ -51,19 +53,19 @@ def compute_build_signature(env):
51 53
 	# Definitions from these files will be kept
52 54
 	files_to_keep = [ 'Marlin/Configuration.h', 'Marlin/Configuration_adv.h' ]
53 55
 
54
-	build_dir = os.path.join(env['PROJECT_BUILD_DIR'], env['PIOENV'])
56
+	build_path = Path(env['PROJECT_BUILD_DIR'], env['PIOENV'])
55 57
 
56 58
 	# Check if we can skip processing
57 59
 	hashes = ''
58 60
 	for header in files_to_keep:
59 61
 		hashes += get_file_sha256sum(header)[0:10]
60 62
 
61
-	marlin_json = os.path.join(build_dir, 'marlin_config.json')
62
-	marlin_zip = os.path.join(build_dir, 'mc')
63
+	marlin_json = build_path / 'marlin_config.json'
64
+	marlin_zip = build_path / 'mc'
63 65
 
64 66
 	# Read existing config file
65 67
 	try:
66
-		with open(marlin_json, 'r') as infile:
68
+		with marlin_json.open() as infile:
67 69
 			conf = json.load(infile)
68 70
 			if conf['__INITIAL_HASH'] == hashes:
69 71
 				# Same configuration, skip recomputing the building signature
@@ -109,7 +111,10 @@ def compute_build_signature(env):
109 111
 
110 112
 		defines[key] = value if len(value) else ""
111 113
 
112
-	if not 'CONFIGURATION_EMBEDDING' in defines:
114
+	#
115
+	# Continue to gather data for CONFIGURATION_EMBEDDING or CONFIG_DUMP
116
+	#
117
+	if not ('CONFIGURATION_EMBEDDING' in defines or 'CONFIG_DUMP' in defines):
113 118
 		return
114 119
 
115 120
 	# Second step is to filter useless macro
@@ -145,6 +150,71 @@ def compute_build_signature(env):
145 150
 			if key in conf_defines[header]:
146 151
 				data[header][key] = resolved_defines[key]
147 152
 
153
+	# Every python needs this toy
154
+	def tryint(key):
155
+		try:
156
+			return int(defines[key])
157
+		except:
158
+			return 0
159
+
160
+	config_dump = tryint('CONFIG_DUMP')
161
+
162
+	#
163
+	# Produce an INI file if CONFIG_DUMP == 2
164
+	#
165
+	if config_dump == 2:
166
+		print("Generating config.ini ...")
167
+		ignore = ('CONFIGURATION_H_VERSION', 'CONFIGURATION_ADV_H_VERSION', 'CONFIG_DUMP')
168
+		filegrp = { 'Configuration.h':'config:basic', 'Configuration_adv.h':'config:advanced' }
169
+		config_ini = build_path / 'config.ini'
170
+		with config_ini.open('w') as outfile:
171
+			outfile.write('#\n# Marlin Firmware\n# config.ini - Options to apply before the build\n#\n')
172
+			# Loop through the data array of arrays
173
+			for header in data:
174
+				if header.startswith('__'):
175
+					continue
176
+				outfile.write('\n[' + filegrp[header] + ']\n')
177
+				for key in sorted(data[header]):
178
+					if key not in ignore:
179
+						val = 'on' if data[header][key] == '' else data[header][key]
180
+						outfile.write('{0:40}{1}'.format(key.lower(), ' = ' + val) + '\n')
181
+
182
+	#
183
+	# Produce a schema.json file if CONFIG_DUMP == 3
184
+	#
185
+	if config_dump >= 3:
186
+		try:
187
+			conf_schema = schema.extract()
188
+		except Exception as exc:
189
+			print("Error: " + str(exc))
190
+			conf_schema = None
191
+
192
+		if conf_schema:
193
+			#
194
+			# Produce a schema.json file if CONFIG_DUMP == 3
195
+			#
196
+			if config_dump in (3, 13):
197
+				print("Generating schema.json ...")
198
+				schema.dump_json(conf_schema, build_path / 'schema.json')
199
+				if config_dump == 13:
200
+					schema.group_options(conf_schema)
201
+					schema.dump_json(conf_schema, build_path / 'schema_grouped.json')
202
+
203
+			#
204
+			# Produce a schema.yml file if CONFIG_DUMP == 4
205
+			#
206
+			elif config_dump == 4:
207
+				print("Generating schema.yml ...")
208
+				try:
209
+					import yaml
210
+				except ImportError:
211
+					env.Execute(env.VerboseAction(
212
+						'$PYTHONEXE -m pip install "pyyaml"',
213
+						"Installing YAML for schema.yml export",
214
+					))
215
+					import yaml
216
+				schema.dump_yaml(conf_schema, build_path / 'schema.yml')
217
+
148 218
 	# Append the source code version and date
149 219
 	data['VERSION'] = {}
150 220
 	data['VERSION']['DETAILED_BUILD_VERSION'] = resolved_defines['DETAILED_BUILD_VERSION']
@@ -156,10 +226,17 @@ def compute_build_signature(env):
156 226
 		pass
157 227
 
158 228
 	#
159
-	# Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_DUMP > 0
229
+	# Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_DUMP == 1
160 230
 	#
161
-	with open(marlin_json, 'w') as outfile:
162
-		json.dump(data, outfile, separators=(',', ':'))
231
+	if config_dump == 1 or 'CONFIGURATION_EMBEDDING' in defines:
232
+		with marlin_json.open('w') as outfile:
233
+			json.dump(data, outfile, separators=(',', ':'))
234
+
235
+	#
236
+	# The rest only applies to CONFIGURATION_EMBEDDING
237
+	#
238
+	if not 'CONFIGURATION_EMBEDDING' in defines:
239
+		return
163 240
 
164 241
 	# Compress the JSON file as much as we can
165 242
 	compress_file(marlin_json, marlin_zip)
@@ -173,11 +250,11 @@ def compute_build_signature(env):
173 250
 			+ b'const unsigned char mc_zip[] PROGMEM = {\n '
174 251
 		)
175 252
 		count = 0
176
-		for b in open(os.path.join(build_dir, 'mc.zip'), 'rb').read():
253
+		for b in (build_path / 'mc.zip').open('rb').read():
177 254
 			result_file.write(b' 0x%02X,' % b)
178 255
 			count += 1
179
-			if (count % 16 == 0):
180
-			 	result_file.write(b'\n ')
181
-		if (count % 16):
256
+			if count % 16 == 0:
257
+				result_file.write(b'\n ')
258
+		if count % 16:
182 259
 			result_file.write(b'\n')
183 260
 		result_file.write(b'};\n')

+ 3
- 1
platformio.ini View File

@@ -16,6 +16,7 @@ boards_dir   = buildroot/share/PlatformIO/boards
16 16
 default_envs = mega2560
17 17
 include_dir  = Marlin
18 18
 extra_configs =
19
+    Marlin/config.ini
19 20
     ini/avr.ini
20 21
     ini/due.ini
21 22
     ini/esp32.ini
@@ -44,12 +45,13 @@ extra_configs =
44 45
 build_flags        = -g3 -D__MARLIN_FIRMWARE__ -DNDEBUG
45 46
                      -fmax-errors=5
46 47
 extra_scripts      =
48
+  pre:buildroot/share/PlatformIO/scripts/configuration.py
47 49
   pre:buildroot/share/PlatformIO/scripts/common-dependencies.py
48 50
   pre:buildroot/share/PlatformIO/scripts/common-cxxflags.py
49 51
   pre:buildroot/share/PlatformIO/scripts/preflight-checks.py
50 52
   post:buildroot/share/PlatformIO/scripts/common-dependencies-post.py
51 53
 lib_deps           =
52
-default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
54
+default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared> -<Marlin/Marlin.ino>
53 55
   -<src/lcd/HD44780> -<src/lcd/TFTGLCD> -<src/lcd/dogm> -<src/lcd/tft> -<src/lcd/tft_io>
54 56
   -<src/HAL/STM32/tft> -<src/HAL/STM32F1/tft>
55 57
   -<src/lcd/e3v2/common> -<src/lcd/e3v2/creality> -<src/lcd/e3v2/proui> -<src/lcd/e3v2/jyersui> -<src/lcd/e3v2/marlinui>

Loading…
Cancel
Save