Compare commits
199 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 988140a467 | |||
| c320503d78 | |||
| d90d15817c | |||
| 4479f438fd | |||
| 5573d98ecc | |||
| 38b44e3fc9 | |||
| d4ab2024f5 | |||
| 790bba1556 | |||
| b51aed8aa5 | |||
| 1f52112d72 | |||
| ad907a51e2 | |||
| 6673359d89 | |||
| 560448afed | |||
| deaefbf1dc | |||
| 9823a37362 | |||
| 15bda88d04 | |||
| de73b9b934 | |||
| 2fc854eda0 | |||
| 60607ed18d | |||
| 546e56ef3d | |||
| dc78e0a250 | |||
| 5ffa6f3331 | |||
| 1a23ffd776 | |||
| c07f99d5e4 | |||
| ae8be31247 | |||
| 4f6910c131 | |||
| d787cd3076 | |||
| cc3e878f90 | |||
| b9b9a3115a | |||
| 36d3b6aa95 | |||
| 911cd1a6d3 | |||
| da84b59ee4 | |||
| 11343bb0ea | |||
| e05616ada1 | |||
| 3107d8a0f4 | |||
| 7f1fa0d1ff | |||
| 604c5dedf4 | |||
| 71f2617263 | |||
| 8532c2b9b6 | |||
| 1affbe2100 | |||
| 9dc2712c47 | |||
| 6e1024737d | |||
| 03a41021de | |||
| a73cff8e4f | |||
| 8857fc6c4b | |||
| f671e6d138 | |||
| 4d6ebf95fc | |||
| 8c512191b2 | |||
| f147a8990a | |||
| 048f6b4731 | |||
| 9cba3c87ef | |||
| dbd28eecc9 | |||
| 2c62886c71 | |||
| fe0b770033 | |||
| b75e682c50 | |||
| bb6d718e19 | |||
| 28a136d7f4 | |||
| 10ec5c7f34 | |||
| 55c31fbe9a | |||
| 2f1fd4bbaa | |||
| 18a10c0db1 | |||
| aad0f517b4 | |||
| 1b9ff68f8c | |||
| aa054471f2 | |||
| f2ff75f3a2 | |||
| 5dc8f5cfab | |||
| ced1bb9404 | |||
| 9f14127fd6 | |||
| b95e548ddb | |||
| b4402a789a | |||
| 87bef13a4c | |||
| 72cc5a49e6 | |||
| a94fa7b476 | |||
| 43b712d42b | |||
| 2c5967925f | |||
| 4182cf3e9e | |||
| a1796ecace | |||
| 3eb8e26174 | |||
| d05bf563a2 | |||
| 3ea56ba4c7 | |||
| f56929d0df | |||
| 101f09aabd | |||
| a0d312396a | |||
| 6903a2ffc5 | |||
| 8dee12ff05 | |||
| 9299f4e98a | |||
| 6225870aa9 | |||
| dad486c01b | |||
| 0b7e857614 | |||
| 431f6bf3a5 | |||
| 9372aa99af | |||
| 81c29ecc7e | |||
| dd388aedfd | |||
| a46e025725 | |||
| fd270ddc6c | |||
| 369ffe518d | |||
| 0afa4cc957 | |||
| 872f031405 | |||
| 35791c6371 | |||
| 137f70b122 | |||
| dfa33082bb | |||
| b2bc85f6f6 | |||
| 21372c3d4e | |||
| 7ee9aefed7 | |||
| 8c9a59c29e | |||
| 28404f9e87 | |||
| e66e51fa6d | |||
| 2b9842e094 | |||
| f52cba6aff | |||
| 713de872ce | |||
| 1aa421efe5 | |||
| dd42831cba | |||
| f0b662ff58 | |||
| e8ca077f30 | |||
| 2328f8b9b8 | |||
| 680172a084 | |||
| 254b25296b | |||
| 903d0b91fc | |||
| 54ccfcc705 | |||
| dfacd260bb | |||
| 04b83d50a2 | |||
| 1236585693 | |||
| c76008bd6a | |||
| e0aa9ce372 | |||
| ee7701c15b | |||
| 6e1c133e33 | |||
| 969268166e | |||
| 83a156ef47 | |||
| 6136959a6a | |||
| 4f840c211c | |||
| db5967472b | |||
| e65a84f6ea | |||
| b385758e22 | |||
| 526924559f | |||
| 24623d398c | |||
| 56462cf082 | |||
| f384f81253 | |||
| 427b5d61f4 | |||
| e27fba0c06 | |||
| 7a1ec78563 | |||
| ec42be346d | |||
| ccf990a0d7 | |||
| fd77251fdd | |||
| f7d9305786 | |||
| bcda46e3f3 | |||
| 7fc75fc482 | |||
| 45fff07a4c | |||
| 08d54b3d78 | |||
| 735c1b6183 | |||
| bb1039d4c9 | |||
| a21d4c06ae | |||
| 12468f5e9f | |||
| 468e437390 | |||
| d167af4c38 | |||
| 3061a31c92 | |||
| 73e354b7a0 | |||
| 0cc03f912c | |||
| f003e52009 | |||
| 13c4eef637 | |||
| d5b06624fb | |||
| a3a10b62f2 | |||
| 03160719eb | |||
| b276a7fd17 | |||
| 37e2250992 | |||
| bdb8c07bb2 | |||
| 27f9437d31 | |||
| ba301fd800 | |||
| 34cda524c4 | |||
| 53d7ae4e9b | |||
| 7a027be255 | |||
| ece06c26a9 | |||
| 8d28853774 | |||
| fb8b421aac | |||
| b3ecede429 | |||
| b8d7925d0d | |||
| 95e0ed2826 | |||
| 900047298e | |||
| c86c85437f | |||
| 18d0e1b365 | |||
| a34b4471b5 | |||
| ae9372bc16 | |||
| 848e9ea241 | |||
| d21d6f6c9e | |||
| b35d0c61b9 | |||
| 5c1c99da0c | |||
| 261778e540 | |||
| 6ee6205e18 | |||
| d47ceb2e8b | |||
| 75beeb7b25 | |||
| 522735b858 | |||
| 4f7d610c96 | |||
| d2cee0be7a | |||
| 20c60fe8f1 | |||
| 877b3c65f9 | |||
| aa9b6280ff | |||
| 2a9ecf46a5 | |||
| cf9a8e184e | |||
| b12fe74d75 | |||
| 8b927a283e |
+178
-89
@@ -1,5 +1,4 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
/** Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
@@ -58,23 +57,18 @@
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
//============================= DELTA Printer ===============================
|
||||
//========================== DELTA / SCARA / TPARA ==========================
|
||||
//===========================================================================
|
||||
// For a Delta printer, start with one of the configuration files in the config/examples/delta directory
|
||||
// from https://github.com/MarlinFirmware/Configurations/branches/all and customize for your machine.
|
||||
//
|
||||
|
||||
//===========================================================================
|
||||
//============================= SCARA Printer ===============================
|
||||
//===========================================================================
|
||||
// For a SCARA printer, start with one of the configuration files in the config/examples/SCARA directory
|
||||
// from https://github.com/MarlinFirmware/Configurations/branches/all and customize for your machine.
|
||||
// Download configurations from the link above and customize for your machine.
|
||||
// Examples are located in config/examples/delta, .../SCARA, and .../TPARA.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
// @section info
|
||||
|
||||
// Author info of this build printed to the host during boot and M115
|
||||
#define STRING_CONFIG_H_AUTHOR "(none, default config)" // Who made the changes.
|
||||
#define STRING_CONFIG_H_AUTHOR "3DXtech / Insanity Automation" // Who made the changes.
|
||||
//#define CUSTOM_VERSION_FILE Version.h // Path from the root directory (no quotes)
|
||||
|
||||
/**
|
||||
@@ -132,7 +126,7 @@
|
||||
|
||||
// Choose the name from boards.h that matches your setup
|
||||
#ifndef MOTHERBOARD
|
||||
#define MOTHERBOARD BOARD_RAMPS_14_EFB
|
||||
#define MOTHERBOARD BOARD_INTAMSYS40
|
||||
#endif
|
||||
|
||||
// Name displayed in the LCD "Ready" message and Info menu
|
||||
@@ -168,8 +162,8 @@
|
||||
* PRUSA_MMU1 : Průša MMU1 (The "multiplexer" version)
|
||||
* PRUSA_MMU2 : Průša MMU2
|
||||
* PRUSA_MMU2S : Průša MMU2S (Requires MK3S extruder with motion sensor, EXTRUDERS = 5)
|
||||
* SMUFF_EMU_MMU2 : Technik Gegg SMUFF (Průša MMU2 emulation mode)
|
||||
* SMUFF_EMU_MMU2S : Technik Gegg SMUFF (Průša MMU2S emulation mode)
|
||||
* SMUFF_EMU_MMU2 : Technik Gegg SMuFF (Průša MMU2 emulation mode)
|
||||
* SMUFF_EMU_MMU2S : Technik Gegg SMuFF (Průša MMU2S emulation mode)
|
||||
*
|
||||
* Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
|
||||
* See additional options in Configuration_adv.h.
|
||||
@@ -316,27 +310,29 @@
|
||||
* Enable and connect the power supply to the PS_ON_PIN.
|
||||
* Specify whether the power supply is active HIGH or active LOW.
|
||||
*/
|
||||
//#define PSU_CONTROL
|
||||
#define PSU_CONTROL
|
||||
//#define PSU_NAME "Power Supply"
|
||||
|
||||
#if ENABLED(PSU_CONTROL)
|
||||
#define PSU_ACTIVE_STATE LOW // Set 'LOW' for ATX, 'HIGH' for X-Box
|
||||
#define PSU_ACTIVE_STATE HIGH // Set 'LOW' for ATX, 'HIGH' for X-Box
|
||||
|
||||
//#define PSU_DEFAULT_OFF // Keep power off until enabled directly with M80
|
||||
//#define PSU_POWERUP_DELAY 250 // (ms) Delay for the PSU to warm up to full power
|
||||
#define PSU_POWERUP_DELAY 250 // (ms) Delay for the PSU to warm up to full power
|
||||
|
||||
//#define PSU_POWERUP_GCODE "M355 S1" // G-code to run after power-on (e.g., case light on)
|
||||
//#define PSU_POWEROFF_GCODE "M355 S0" // G-code to run before power-off (e.g., case light off)
|
||||
|
||||
//#define AUTO_POWER_CONTROL // Enable automatic control of the PS_ON pin
|
||||
#define AUTO_POWER_CONTROL // Enable automatic control of the PS_ON pin
|
||||
#if ENABLED(AUTO_POWER_CONTROL)
|
||||
#define AUTO_POWER_FANS // Turn on PSU if fans need power
|
||||
#define AUTO_POWER_E_FANS
|
||||
#define AUTO_POWER_CONTROLLERFAN
|
||||
#define AUTO_POWER_CHAMBER_FAN
|
||||
//#define AUTO_POWER_E_TEMP 50 // (°C) Turn on PSU if any extruder is over this temperature
|
||||
//#define AUTO_POWER_CHAMBER_TEMP 30 // (°C) Turn on PSU if the chamber is over this temperature
|
||||
#define POWER_TIMEOUT 30 // (s) Turn off power if the machine is idle for this duration
|
||||
#define AUTO_POWER_COOLER_FAN
|
||||
#define AUTO_POWER_E_TEMP 50 // (°C) Turn on PSU if any extruder is over this temperature
|
||||
#define AUTO_POWER_CHAMBER_TEMP 30 // (°C) Turn on PSU if the chamber is over this temperature
|
||||
//#define AUTO_POWER_COOLER_TEMP 26 // (°C) Turn on PSU if the cooler is over this temperature
|
||||
#define POWER_TIMEOUT 120 // (s) Turn off power if the machine is idle for this duration
|
||||
//#define POWER_OFF_DELAY 60 // (s) Delay of poweroff after M81 command. Useful to let fans run for extra time.
|
||||
#endif
|
||||
#endif
|
||||
@@ -412,7 +408,7 @@
|
||||
* 998 : Dummy Table that ALWAYS reads 25°C or the temperature defined below.
|
||||
* 999 : Dummy Table that ALWAYS reads 100°C or the temperature defined below.
|
||||
*/
|
||||
#define TEMP_SENSOR_0 1
|
||||
#define TEMP_SENSOR_0 20
|
||||
#define TEMP_SENSOR_1 0
|
||||
#define TEMP_SENSOR_2 0
|
||||
#define TEMP_SENSOR_3 0
|
||||
@@ -420,9 +416,10 @@
|
||||
#define TEMP_SENSOR_5 0
|
||||
#define TEMP_SENSOR_6 0
|
||||
#define TEMP_SENSOR_7 0
|
||||
#define TEMP_SENSOR_BED 0
|
||||
#define TEMP_SENSOR_BED 1
|
||||
#define TEMP_SENSOR_PROBE 0
|
||||
#define TEMP_SENSOR_CHAMBER 0
|
||||
#define TEMP_SENSOR_CHAMBER 1
|
||||
#define TEMP_SENSOR_COOLER 0
|
||||
|
||||
// Dummy thermistor constant temperature readings, for use with 998 and 999
|
||||
#define DUMMY_THERMISTOR_998_VALUE 25
|
||||
@@ -439,14 +436,18 @@
|
||||
//#define TEMP_SENSOR_1_AS_REDUNDANT
|
||||
#define MAX_REDUNDANT_TEMP_SENSOR_DIFF 10
|
||||
|
||||
#define TEMP_RESIDENCY_TIME 10 // (seconds) Time to wait for hotend to "settle" in M109
|
||||
#define TEMP_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
|
||||
#define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
|
||||
#define TEMP_RESIDENCY_TIME 3 // (seconds) Time to wait for hotend to "settle" in M109
|
||||
#define TEMP_WINDOW 3 // (°C) Temperature proximity for the "temperature reached" timer
|
||||
#define TEMP_HYSTERESIS 5 // (°C) Temperature proximity considered "close enough" to the target
|
||||
|
||||
#define TEMP_BED_RESIDENCY_TIME 10 // (seconds) Time to wait for bed to "settle" in M190
|
||||
#define TEMP_BED_RESIDENCY_TIME 5 // (seconds) Time to wait for bed to "settle" in M190
|
||||
#define TEMP_BED_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
|
||||
#define TEMP_BED_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
|
||||
|
||||
#define TEMP_CHAMBER_RESIDENCY_TIME 10 // (seconds) Time to wait for chamber to "settle" in M191
|
||||
#define TEMP_CHAMBER_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
|
||||
#define TEMP_CHAMBER_HYSTERESIS 5 // (°C) Temperature proximity considered "close enough" to the target
|
||||
|
||||
// Below this temperature the heater will be switched off
|
||||
// because it probably indicates a broken thermistor wire.
|
||||
#define HEATER_0_MINTEMP 5
|
||||
@@ -458,11 +459,12 @@
|
||||
#define HEATER_6_MINTEMP 5
|
||||
#define HEATER_7_MINTEMP 5
|
||||
#define BED_MINTEMP 5
|
||||
#define CHAMBER_MINTEMP 5
|
||||
|
||||
// Above this temperature the heater will be switched off.
|
||||
// This can protect components from overheating, but NOT from shorts and failures.
|
||||
// (Use MINTEMP for thermistor short/failure protection.)
|
||||
#define HEATER_0_MAXTEMP 275
|
||||
#define HEATER_0_MAXTEMP 415
|
||||
#define HEATER_1_MAXTEMP 275
|
||||
#define HEATER_2_MAXTEMP 275
|
||||
#define HEATER_3_MAXTEMP 275
|
||||
@@ -471,6 +473,16 @@
|
||||
#define HEATER_6_MAXTEMP 275
|
||||
#define HEATER_7_MAXTEMP 275
|
||||
#define BED_MAXTEMP 150
|
||||
#define CHAMBER_MAXTEMP 80
|
||||
|
||||
/**
|
||||
* Thermal Overshoot
|
||||
* During heatup (and printing) the temperature can often "overshoot" the target by many degrees
|
||||
* (especially before PID tuning). Setting the target temperature too close to MAXTEMP guarantees
|
||||
* a MAXTEMP shutdown! Use these values to forbid temperatures being set too close to MAXTEMP.
|
||||
*/
|
||||
#define HOTEND_OVERSHOOT 15 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
|
||||
#define BED_OVERSHOOT 10 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
|
||||
|
||||
//===========================================================================
|
||||
//============================= PID Settings ================================
|
||||
@@ -484,8 +496,8 @@
|
||||
#define PID_K1 0.95 // Smoothing factor within any PID loop
|
||||
|
||||
#if ENABLED(PIDTEMP)
|
||||
//#define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of PROGMEM)
|
||||
//#define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of PROGMEM)
|
||||
#define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of PROGMEM)
|
||||
#define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of PROGMEM)
|
||||
//#define PID_PARAMS_PER_HOTEND // Uses separate PID parameters for each extruder (useful for mismatched extruders)
|
||||
// Set/get with gcode: M301 E[extruder number, 0-2]
|
||||
|
||||
@@ -496,9 +508,9 @@
|
||||
#define DEFAULT_Ki_LIST { 1.08, 1.08 }
|
||||
#define DEFAULT_Kd_LIST { 114.00, 114.00 }
|
||||
#else
|
||||
#define DEFAULT_Kp 22.20
|
||||
#define DEFAULT_Ki 1.08
|
||||
#define DEFAULT_Kd 114.00
|
||||
#define DEFAULT_Kp 10.5
|
||||
#define DEFAULT_Ki 0.45
|
||||
#define DEFAULT_Kd 70
|
||||
#endif
|
||||
#endif // PIDTEMP
|
||||
|
||||
@@ -519,7 +531,7 @@
|
||||
* heater. If your configuration is significantly different than this and you don't understand
|
||||
* the issues involved, don't use bed PID until someone else verifies that your hardware works.
|
||||
*/
|
||||
//#define PIDTEMPBED
|
||||
#define PIDTEMPBED
|
||||
|
||||
//#define BED_LIMIT_SWITCHING
|
||||
|
||||
@@ -535,16 +547,60 @@
|
||||
//#define MIN_BED_POWER 0
|
||||
//#define PID_BED_DEBUG // Sends debug data to the serial port.
|
||||
|
||||
// 120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
|
||||
// from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
|
||||
#define DEFAULT_bedKp 10.00
|
||||
#define DEFAULT_bedKi .023
|
||||
#define DEFAULT_bedKd 305.4
|
||||
//120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
|
||||
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
|
||||
#define DEFAULT_bedKp 104.28
|
||||
#define DEFAULT_bedKi 20.53
|
||||
#define DEFAULT_bedKd 353.10
|
||||
|
||||
// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
|
||||
#endif // PIDTEMPBED
|
||||
|
||||
#if EITHER(PIDTEMP, PIDTEMPBED)
|
||||
//===========================================================================
|
||||
//==================== PID > Chamber Temperature Control ====================
|
||||
//===========================================================================
|
||||
|
||||
/**
|
||||
* PID Chamber Heating
|
||||
*
|
||||
* If this option is enabled set PID constants below.
|
||||
* If this option is disabled, bang-bang will be used and CHAMBER_LIMIT_SWITCHING will enable
|
||||
* hysteresis.
|
||||
*
|
||||
* The PID frequency will be the same as the extruder PWM.
|
||||
* If PID_dT is the default, and correct for the hardware/configuration, that means 7.689Hz,
|
||||
* which is fine for driving a square wave into a resistive load and does not significantly
|
||||
* impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 200W
|
||||
* heater. If your configuration is significantly different than this and you don't understand
|
||||
* the issues involved, don't use chamber PID until someone else verifies that your hardware works.
|
||||
*/
|
||||
//#define PIDTEMPCHAMBER
|
||||
//#define CHAMBER_LIMIT_SWITCHING
|
||||
|
||||
/**
|
||||
* Max Chamber Power
|
||||
* Applies to all forms of chamber control (PID, bang-bang, and bang-bang with hysteresis).
|
||||
* When set to any value below 255, enables a form of PWM to the chamber heater that acts like a divider
|
||||
* so don't use it unless you are OK with PWM on your heater. (See the comment on enabling PIDTEMPCHAMBER)
|
||||
*/
|
||||
#define MAX_CHAMBER_POWER 255 // limits duty cycle to chamber heater; 255=full current
|
||||
|
||||
#if ENABLED(PIDTEMPCHAMBER)
|
||||
#define MIN_CHAMBER_POWER 0
|
||||
//#define PID_CHAMBER_DEBUG // Sends debug data to the serial port.
|
||||
|
||||
// Lasko "MyHeat Personal Heater" (200w) modified with a Fotek SSR-10DA to control only the heating element
|
||||
// and placed inside the small Creality printer enclosure tent.
|
||||
//
|
||||
#define DEFAULT_chamberKp 37.04
|
||||
#define DEFAULT_chamberKi 1.40
|
||||
#define DEFAULT_chamberKd 655.17
|
||||
// M309 P37.04 I1.04 D655.17
|
||||
|
||||
// FIND YOUR OWN: "M303 E-2 C8 S50" to run autotune on the chamber at 50 degreesC for 8 cycles.
|
||||
#endif // PIDTEMPCHAMBER
|
||||
|
||||
#if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER)
|
||||
//#define PID_DEBUG // Sends debug data to the serial port. Use 'M303 D' to toggle activation.
|
||||
//#define PID_OPENLOOP // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
|
||||
//#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
|
||||
@@ -591,6 +647,7 @@
|
||||
#define THERMAL_PROTECTION_HOTENDS // Enable thermal protection for all extruders
|
||||
#define THERMAL_PROTECTION_BED // Enable thermal protection for the heated bed
|
||||
#define THERMAL_PROTECTION_CHAMBER // Enable thermal protection for the heated chamber
|
||||
#define THERMAL_PROTECTION_COOLER // Enable thermal protection for the laser cooling
|
||||
|
||||
//===========================================================================
|
||||
//============================= Mechanical Settings =========================
|
||||
@@ -651,13 +708,13 @@
|
||||
#endif
|
||||
|
||||
// Mechanical endstop with COM to ground and NC to Signal uses "false" here (most common setup).
|
||||
#define X_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
|
||||
#define Y_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
|
||||
#define Z_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
|
||||
#define X_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
|
||||
#define Y_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
|
||||
#define Z_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
|
||||
#define Z_MIN_PROBE_ENDSTOP_INVERTING false // Set to true to invert the logic of the probe.
|
||||
#define X_MIN_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
|
||||
#define Y_MIN_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
|
||||
#define Z_MIN_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
|
||||
#define X_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
|
||||
#define Y_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
|
||||
#define Z_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
|
||||
#define Z_MIN_PROBE_ENDSTOP_INVERTING true // Set to true to invert the logic of the probe.
|
||||
|
||||
/**
|
||||
* Stepper Drivers
|
||||
@@ -740,14 +797,14 @@
|
||||
* Override with M92
|
||||
* X, Y, Z, E0 [, E1[, E2...]]
|
||||
*/
|
||||
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 500 }
|
||||
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 800, 92.6 }
|
||||
|
||||
/**
|
||||
* Default Max Feed Rate (mm/s)
|
||||
* Override with M203
|
||||
* X, Y, Z, E0 [, E1[, E2...]]
|
||||
*/
|
||||
#define DEFAULT_MAX_FEEDRATE { 300, 300, 5, 25 }
|
||||
#define DEFAULT_MAX_FEEDRATE { 300, 300, 20, 70 }
|
||||
|
||||
//#define LIMITED_MAX_FR_EDITING // Limit edit via M203 or LCD to DEFAULT_MAX_FEEDRATE * 2
|
||||
#if ENABLED(LIMITED_MAX_FR_EDITING)
|
||||
@@ -760,7 +817,7 @@
|
||||
* Override with M201
|
||||
* X, Y, Z, E0 [, E1[, E2...]]
|
||||
*/
|
||||
#define DEFAULT_MAX_ACCELERATION { 3000, 3000, 100, 10000 }
|
||||
#define DEFAULT_MAX_ACCELERATION { 9000, 9000, 100, 10000 }
|
||||
|
||||
//#define LIMITED_MAX_ACCEL_EDITING // Limit edit via M201 or LCD to DEFAULT_MAX_ACCELERATION * 2
|
||||
#if ENABLED(LIMITED_MAX_ACCEL_EDITING)
|
||||
@@ -787,7 +844,7 @@
|
||||
* When changing speed and direction, if the difference is less than the
|
||||
* value set here, it may happen instantaneously.
|
||||
*/
|
||||
//#define CLASSIC_JERK
|
||||
#define CLASSIC_JERK
|
||||
#if ENABLED(CLASSIC_JERK)
|
||||
#define DEFAULT_XJERK 10.0
|
||||
#define DEFAULT_YJERK 10.0
|
||||
@@ -824,7 +881,7 @@
|
||||
*
|
||||
* See https://github.com/synthetos/TinyG/wiki/Jerk-Controlled-Motion-Explained
|
||||
*/
|
||||
//#define S_CURVE_ACCELERATION
|
||||
#define S_CURVE_ACCELERATION
|
||||
|
||||
//===========================================================================
|
||||
//============================= Z Probe Options =============================
|
||||
@@ -997,13 +1054,13 @@
|
||||
#define PROBING_MARGIN 10
|
||||
|
||||
// X and Y axis travel speed (mm/min) between probes
|
||||
#define XY_PROBE_SPEED (133*60)
|
||||
#define XY_PROBE_FEEDRATE (133*60)
|
||||
|
||||
// Feedrate (mm/min) for the first approach when double-probing (MULTIPLE_PROBING == 2)
|
||||
#define Z_PROBE_SPEED_FAST (4*60)
|
||||
#define Z_PROBE_FEEDRATE_FAST (4*60)
|
||||
|
||||
// Feedrate (mm/min) for the "accurate" probe of each point
|
||||
#define Z_PROBE_SPEED_SLOW (Z_PROBE_SPEED_FAST / 2)
|
||||
#define Z_PROBE_FEEDRATE_SLOW (Z_PROBE_FEEDRATE_FAST / 2)
|
||||
|
||||
/**
|
||||
* Probe Activation Switch
|
||||
@@ -1066,8 +1123,8 @@
|
||||
#define Z_PROBE_LOW_POINT -2 // Farthest distance below the trigger-point to go before stopping
|
||||
|
||||
// For M851 give a range for adjusting the Z probe offset
|
||||
#define Z_PROBE_OFFSET_RANGE_MIN -20
|
||||
#define Z_PROBE_OFFSET_RANGE_MAX 20
|
||||
#define Z_PROBE_OFFSET_RANGE_MIN -9
|
||||
#define Z_PROBE_OFFSET_RANGE_MAX 9
|
||||
|
||||
// Enable the M48 repeatability test to test probe accuracy
|
||||
//#define Z_MIN_PROBE_REPEATABILITY_TEST
|
||||
@@ -1088,6 +1145,7 @@
|
||||
//#define PROBING_HEATERS_OFF // Turn heaters off when probing
|
||||
#if ENABLED(PROBING_HEATERS_OFF)
|
||||
//#define WAIT_FOR_BED_HEATER // Wait for bed to heat back up between probes (to improve accuracy)
|
||||
//#define WAIT_FOR_HOTEND // Wait for hotend to heat back up between probes (to improve accuracy & prevent cold extrude)
|
||||
#endif
|
||||
//#define PROBING_FANS_OFF // Turn fans off when probing
|
||||
//#define PROBING_STEPPERS_OFF // Turn steppers off (unless needed to hold position) when probing
|
||||
@@ -1124,9 +1182,9 @@
|
||||
// @section machine
|
||||
|
||||
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
|
||||
#define INVERT_X_DIR false
|
||||
#define INVERT_Y_DIR true
|
||||
#define INVERT_Z_DIR false
|
||||
#define INVERT_X_DIR true
|
||||
#define INVERT_Y_DIR false
|
||||
#define INVERT_Z_DIR true
|
||||
|
||||
// @section extruder
|
||||
|
||||
@@ -1144,7 +1202,13 @@
|
||||
|
||||
//#define NO_MOTION_BEFORE_HOMING // Inhibit movement until all axes have been homed. Also enable HOME_AFTER_DEACTIVATE for extra safety.
|
||||
//#define HOME_AFTER_DEACTIVATE // Require rehoming after steppers are deactivated. Also enable NO_MOTION_BEFORE_HOMING for extra safety.
|
||||
//#define UNKNOWN_Z_NO_RAISE // Don't raise Z (lower the bed) if Z is "unknown." For beds that fall when Z is powered off.
|
||||
|
||||
/**
|
||||
* Set Z_IDLE_HEIGHT if the Z-Axis moves on its own when steppers are disabled.
|
||||
* - Use a low value (i.e., Z_MIN_POS) if the nozzle falls down to the bed.
|
||||
* - Use a large value (i.e., Z_MAX_POS) if the bed falls down, away from the nozzle.
|
||||
*/
|
||||
//#define Z_IDLE_HEIGHT Z_HOME_POS
|
||||
|
||||
//#define Z_HOMING_HEIGHT 4 // (mm) Minimal Z height before homing (G28) for Z clearance above the bed, clamps, ...
|
||||
// Be sure to have this much clearance over your Z_MAX_POS to prevent grinding.
|
||||
@@ -1160,8 +1224,8 @@
|
||||
// @section machine
|
||||
|
||||
// The size of the print bed
|
||||
#define X_BED_SIZE 200
|
||||
#define Y_BED_SIZE 200
|
||||
#define X_BED_SIZE 260
|
||||
#define Y_BED_SIZE 260
|
||||
|
||||
// Travel limits (mm) after homing, corresponding to endstop positions.
|
||||
#define X_MIN_POS 0
|
||||
@@ -1169,7 +1233,7 @@
|
||||
#define Z_MIN_POS 0
|
||||
#define X_MAX_POS X_BED_SIZE
|
||||
#define Y_MAX_POS Y_BED_SIZE
|
||||
#define Z_MAX_POS 200
|
||||
#define Z_MAX_POS 260
|
||||
|
||||
/**
|
||||
* Software Endstops
|
||||
@@ -1197,7 +1261,7 @@
|
||||
#endif
|
||||
|
||||
#if EITHER(MIN_SOFTWARE_ENDSTOPS, MAX_SOFTWARE_ENDSTOPS)
|
||||
//#define SOFT_ENDSTOPS_MENU_ITEM // Enable/Disable software endstops from the LCD
|
||||
#define SOFT_ENDSTOPS_MENU_ITEM // Enable/Disable software endstops from the LCD
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -1213,7 +1277,7 @@
|
||||
* RAMPS-based boards use SERVO3_PIN for the first runout sensor.
|
||||
* For other boards you may need to define FIL_RUNOUT_PIN, FIL_RUNOUT2_PIN, etc.
|
||||
*/
|
||||
//#define FILAMENT_RUNOUT_SENSOR
|
||||
#define FILAMENT_RUNOUT_SENSOR
|
||||
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
|
||||
#define FIL_RUNOUT_ENABLED_DEFAULT true // Enable the sensor on startup. Override with M412 followed by M500.
|
||||
#define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each.
|
||||
@@ -1221,6 +1285,8 @@
|
||||
#define FIL_RUNOUT_STATE LOW // Pin state indicating that filament is NOT present.
|
||||
#define FIL_RUNOUT_PULLUP // Use internal pullup for filament runout pins.
|
||||
//#define FIL_RUNOUT_PULLDOWN // Use internal pulldown for filament runout pins.
|
||||
//#define WATCH_ALL_RUNOUT_SENSORS // Execute runout script on any triggering sensor, not only for the active extruder.
|
||||
// This is automatically enabled for MIXING_EXTRUDERs.
|
||||
|
||||
// Override individually if the runout sensors vary
|
||||
//#define FIL_RUNOUT1_STATE LOW
|
||||
@@ -1255,14 +1321,15 @@
|
||||
//#define FIL_RUNOUT8_PULLUP
|
||||
//#define FIL_RUNOUT8_PULLDOWN
|
||||
|
||||
// Set one or more commands to execute on filament runout.
|
||||
// (After 'M412 H' Marlin will ask the host to handle the process.)
|
||||
// Commands to execute on filament runout.
|
||||
// With multiple runout sensors use the %c placeholder for the current tool in commands (e.g., "M600 T%c")
|
||||
// NOTE: After 'M412 H1' the host handles filament runout and this script does not apply.
|
||||
#define FILAMENT_RUNOUT_SCRIPT "M600"
|
||||
|
||||
// After a runout is detected, continue printing this length of filament
|
||||
// before executing the runout script. Useful for a sensor at the end of
|
||||
// a feed tube. Requires 4 bytes SRAM per sensor, plus 4 bytes overhead.
|
||||
//#define FILAMENT_RUNOUT_DISTANCE_MM 25
|
||||
#define FILAMENT_RUNOUT_DISTANCE_MM 5
|
||||
|
||||
#ifdef FILAMENT_RUNOUT_DISTANCE_MM
|
||||
// Enable this option to use an encoder disc that toggles the runout pin
|
||||
@@ -1314,14 +1381,14 @@
|
||||
//#define AUTO_BED_LEVELING_LINEAR
|
||||
//#define AUTO_BED_LEVELING_BILINEAR
|
||||
//#define AUTO_BED_LEVELING_UBL
|
||||
//#define MESH_BED_LEVELING
|
||||
#define MESH_BED_LEVELING
|
||||
|
||||
/**
|
||||
* Normally G28 leaves leveling disabled on completion. Enable one of
|
||||
* these options to restore the prior leveling state or to always enable
|
||||
* leveling immediately after G28.
|
||||
*/
|
||||
//#define RESTORE_LEVELING_AFTER_G28
|
||||
#define RESTORE_LEVELING_AFTER_G28
|
||||
//#define ENABLE_LEVELING_AFTER_G28
|
||||
|
||||
/**
|
||||
@@ -1358,7 +1425,7 @@
|
||||
/**
|
||||
* Enable the G26 Mesh Validation Pattern tool.
|
||||
*/
|
||||
//#define G26_MESH_VALIDATION
|
||||
#define G26_MESH_VALIDATION
|
||||
#if ENABLED(G26_MESH_VALIDATION)
|
||||
#define MESH_TEST_NOZZLE_SIZE 0.4 // (mm) Diameter of primary nozzle.
|
||||
#define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for G26.
|
||||
@@ -1423,7 +1490,7 @@
|
||||
//===========================================================================
|
||||
|
||||
#define MESH_INSET 10 // Set Mesh bounds as an inset region of the bed
|
||||
#define GRID_MAX_POINTS_X 3 // Don't use more than 7 points per axis, implementation limited.
|
||||
#define GRID_MAX_POINTS_X 5 // Don't use more than 7 points per axis, implementation limited.
|
||||
#define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
|
||||
|
||||
//#define MESH_G28_REST_ORIGIN // After homing all axes ('G28' or 'G28 XYZ') rest Z at Z_MIN_POS
|
||||
@@ -1434,16 +1501,16 @@
|
||||
* Add a bed leveling sub-menu for ABL or MBL.
|
||||
* Include a guided procedure if manual probing is enabled.
|
||||
*/
|
||||
//#define LCD_BED_LEVELING
|
||||
#define LCD_BED_LEVELING
|
||||
|
||||
#if ENABLED(LCD_BED_LEVELING)
|
||||
#define MESH_EDIT_Z_STEP 0.025 // (mm) Step size while manually probing Z axis.
|
||||
#define LCD_PROBE_Z_RANGE 4 // (mm) Z Range centered on Z_MIN_POS for LCD Z adjustment
|
||||
//#define MESH_EDIT_MENU // Add a menu to edit mesh points
|
||||
#define MESH_EDIT_MENU // Add a menu to edit mesh points
|
||||
#endif
|
||||
|
||||
// Add a menu item to move between bed corners for manual bed adjustment
|
||||
//#define LEVEL_BED_CORNERS
|
||||
#define LEVEL_BED_CORNERS
|
||||
|
||||
#if ENABLED(LEVEL_BED_CORNERS)
|
||||
#define LEVEL_CORNERS_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
|
||||
@@ -1588,12 +1655,12 @@
|
||||
* M501 - Read settings from EEPROM. (i.e., Throw away unsaved changes)
|
||||
* M502 - Revert settings to "factory" defaults. (Follow with M500 to init the EEPROM.)
|
||||
*/
|
||||
//#define EEPROM_SETTINGS // Persistent storage with M500 and M501
|
||||
#define EEPROM_SETTINGS // Persistent storage with M500 and M501
|
||||
//#define DISABLE_M503 // Saves ~2700 bytes of PROGMEM. Disable for release!
|
||||
#define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save PROGMEM.
|
||||
#define EEPROM_BOOT_SILENT // Keep M503 quiet and only give errors during first load
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
//#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors.
|
||||
#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors.
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -1624,11 +1691,13 @@
|
||||
#define PREHEAT_1_LABEL "PLA"
|
||||
#define PREHEAT_1_TEMP_HOTEND 180
|
||||
#define PREHEAT_1_TEMP_BED 70
|
||||
#define PREHEAT_1_TEMP_CHAMBER 35
|
||||
#define PREHEAT_1_FAN_SPEED 0 // Value from 0 to 255
|
||||
|
||||
#define PREHEAT_2_LABEL "ABS"
|
||||
#define PREHEAT_2_TEMP_HOTEND 240
|
||||
#define PREHEAT_2_TEMP_BED 110
|
||||
#define PREHEAT_2_TEMP_CHAMBER 45
|
||||
#define PREHEAT_2_FAN_SPEED 0 // Value from 0 to 255
|
||||
|
||||
/**
|
||||
@@ -1642,11 +1711,11 @@
|
||||
* P1 Raise the nozzle always to Z-park height.
|
||||
* P2 Raise the nozzle by Z-park amount, limited to Z_MAX_POS.
|
||||
*/
|
||||
//#define NOZZLE_PARK_FEATURE
|
||||
#define NOZZLE_PARK_FEATURE
|
||||
|
||||
#if ENABLED(NOZZLE_PARK_FEATURE)
|
||||
// Specify a park position as { X, Y, Z_raise }
|
||||
#define NOZZLE_PARK_POINT { (X_MIN_POS + 10), (Y_MAX_POS - 10), 20 }
|
||||
#define NOZZLE_PARK_POINT { (X_CENTER), (Y_CENTER), 20 }
|
||||
//#define NOZZLE_PARK_X_ONLY // X move only is required to park
|
||||
//#define NOZZLE_PARK_Y_ONLY // Y move only is required to park
|
||||
#define NOZZLE_PARK_Z_RAISE_MIN 2 // (mm) Always raise Z by at least this distance
|
||||
@@ -1850,7 +1919,7 @@
|
||||
* SD Card support is disabled by default. If your controller has an SD slot,
|
||||
* you must uncomment the following option or it won't work.
|
||||
*/
|
||||
//#define SDSUPPORT
|
||||
#define SDSUPPORT
|
||||
|
||||
/**
|
||||
* SD CARD: ENABLE CRC
|
||||
@@ -1920,7 +1989,7 @@
|
||||
//
|
||||
// Add individual axis homing items (Home X, Home Y, and Home Z) to the LCD menu.
|
||||
//
|
||||
//#define INDIVIDUAL_AXIS_HOMING_MENU
|
||||
#define INDIVIDUAL_AXIS_HOMING_MENU
|
||||
|
||||
//
|
||||
// SPEAKER/BUZZER
|
||||
@@ -1928,7 +1997,7 @@
|
||||
// If you have a speaker that can produce tones, enable it here.
|
||||
// By default Marlin assumes you have a buzzer with a fixed frequency.
|
||||
//
|
||||
//#define SPEAKER
|
||||
#define SPEAKER
|
||||
|
||||
//
|
||||
// The duration and frequency for the UI feedback sound.
|
||||
@@ -2109,7 +2178,12 @@
|
||||
// RepRapDiscount FULL GRAPHIC Smart Controller
|
||||
// https://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller
|
||||
//
|
||||
//#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
|
||||
//
|
||||
// K.3D Full Graphic Smart Controller
|
||||
//
|
||||
//#define K3D_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
|
||||
//
|
||||
// ReprapWorld Graphical LCD
|
||||
@@ -2248,7 +2322,7 @@
|
||||
//#define OLED_PANEL_TINYBOY2
|
||||
|
||||
//
|
||||
// MKS OLED 1.3" 128×64 FULL GRAPHICS CONTROLLER
|
||||
// MKS OLED 1.3" 128×64 Full Graphics Controller
|
||||
// https://reprap.org/wiki/MKS_12864OLED
|
||||
//
|
||||
// Tiny, but very sharp OLED display
|
||||
@@ -2257,7 +2331,7 @@
|
||||
//#define MKS_12864OLED_SSD1306 // Uses the SSD1306 controller
|
||||
|
||||
//
|
||||
// Zonestar OLED 128×64 FULL GRAPHICS CONTROLLER
|
||||
// Zonestar OLED 128×64 Full Graphics Controller
|
||||
//
|
||||
//#define ZONESTAR_12864LCD // Graphical (DOGM) with ST7920 controller
|
||||
//#define ZONESTAR_12864OLED // 1.3" OLED with SH1106 controller (default)
|
||||
@@ -2274,10 +2348,15 @@
|
||||
//#define OVERLORD_OLED
|
||||
|
||||
//
|
||||
// FYSETC OLED 2.42" 128×64 FULL GRAPHICS CONTROLLER with WS2812 RGB
|
||||
// FYSETC OLED 2.42" 128×64 Full Graphics Controller with WS2812 RGB
|
||||
// Where to find : https://www.aliexpress.com/item/4000345255731.html
|
||||
//#define FYSETC_242_OLED_12864 // Uses the SSD1309 controller
|
||||
|
||||
//
|
||||
// K.3D SSD1309 OLED 2.42" 128×64 Full Graphics Controller
|
||||
//
|
||||
//#define K3D_242_OLED_CONTROLLER // Software SPI
|
||||
|
||||
//=============================================================================
|
||||
//========================== Extensible UI Displays ===========================
|
||||
//=============================================================================
|
||||
@@ -2290,6 +2369,7 @@
|
||||
//#define DGUS_LCD_UI_ORIGIN
|
||||
//#define DGUS_LCD_UI_FYSETC
|
||||
//#define DGUS_LCD_UI_HIPRECY
|
||||
//#define DGUS_LCD_UI_MKS
|
||||
|
||||
//
|
||||
// Touch-screen LCD for Malyan M200/M300 printers
|
||||
@@ -2315,6 +2395,14 @@
|
||||
//#define ANYCUBIC_LCD_DEBUG
|
||||
#endif
|
||||
|
||||
//
|
||||
// 320x240 Nextion 2.8" serial TFT Resistive Touch Screen NX3224T028
|
||||
//
|
||||
//#define NEXTION_TFT
|
||||
#if ENABLED(NEXTION_TFT)
|
||||
#define LCD_SERIAL_PORT 1 // Default is 1 for Nextion
|
||||
#endif
|
||||
|
||||
//
|
||||
// Third-party or vendor-customized controller interfaces.
|
||||
// Sources should be installed in 'src/lcd/extui'.
|
||||
@@ -2591,6 +2679,7 @@
|
||||
// Use a single NeoPixel LED for static (background) lighting
|
||||
//#define NEOPIXEL_BKGD_LED_INDEX 0 // Index of the LED to use
|
||||
//#define NEOPIXEL_BKGD_COLOR { 255, 255, 255, 0 } // R, G, B, W
|
||||
//#define NEOPIXEL_BKGD_ALWAYS_ON // Keep the backlight on when other NeoPixels are off
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
+294
-180
@@ -113,6 +113,12 @@
|
||||
#define CHAMBER_BETA 3950 // Beta value
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_COOLER == 1000
|
||||
#define COOLER_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
|
||||
#define COOLER_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
|
||||
#define COOLER_BETA 3950 // Beta value
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_PROBE == 1000
|
||||
#define PROBE_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
|
||||
#define PROBE_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
|
||||
@@ -143,13 +149,17 @@
|
||||
//
|
||||
// Heated Chamber options
|
||||
//
|
||||
#if DISABLED(PIDTEMPCHAMBER)
|
||||
#define CHAMBER_CHECK_INTERVAL 5000 // (ms) Interval between checks in bang-bang control
|
||||
#if ENABLED(CHAMBER_LIMIT_SWITCHING)
|
||||
#define CHAMBER_HYSTERESIS 5 // (°C) Only set the relevant heater state when ABS(T-target) > CHAMBER_HYSTERESIS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TEMP_SENSOR_CHAMBER
|
||||
#define CHAMBER_MINTEMP 5
|
||||
#define CHAMBER_MAXTEMP 60
|
||||
#define TEMP_CHAMBER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
|
||||
//#define CHAMBER_LIMIT_SWITCHING
|
||||
//#define HEATER_CHAMBER_PIN 44 // Chamber heater on/off pin
|
||||
//#define HEATER_CHAMBER_PIN P2_04 // Required heater on/off pin (example: SKR 1.4 Turbo HE1 plug)
|
||||
//#define HEATER_CHAMBER_INVERTING false
|
||||
//#define FAN1_PIN -1 // Remove the fan signal on pin P2_04 (example: SKR 1.4 Turbo HE1 plug)
|
||||
|
||||
//#define CHAMBER_FAN // Enable a fan on the chamber
|
||||
#if ENABLED(CHAMBER_FAN)
|
||||
@@ -175,6 +185,25 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Laser Cooler options
|
||||
//
|
||||
#if TEMP_SENSOR_COOLER
|
||||
#define COOLER_MINTEMP 8 // (°C)
|
||||
#define COOLER_MAXTEMP 26 // (°C)
|
||||
#define COOLER_DEFAULT_TEMP 16 // (°C)
|
||||
#define TEMP_COOLER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
|
||||
#define COOLER_PIN 8 // Laser cooler on/off pin used to control power to the cooling element e.g. TEC, External chiller via relay
|
||||
#define COOLER_INVERTING false
|
||||
#define TEMP_COOLER_PIN 15 // Laser/Cooler temperature sensor pin. ADC is required.
|
||||
#define COOLER_FAN // Enable a fan on the cooler, Fan# 0,1,2,3 etc.
|
||||
#define COOLER_FAN_INDEX 0 // FAN number 0, 1, 2 etc. e.g.
|
||||
#if ENABLED(COOLER_FAN)
|
||||
#define COOLER_FAN_BASE 100 // Base Cooler fan PWM (0-255); turns on when Cooler temperature is above the target
|
||||
#define COOLER_FAN_FACTOR 25 // PWM increase per °C above target
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Thermal Protection provides additional protection to your printer from damage
|
||||
* and fire. Marlin always includes safe min and max temperature ranges which
|
||||
@@ -192,12 +221,12 @@
|
||||
* THERMAL_PROTECTION_HYSTERESIS and/or THERMAL_PROTECTION_PERIOD
|
||||
*/
|
||||
#if ENABLED(THERMAL_PROTECTION_HOTENDS)
|
||||
#define THERMAL_PROTECTION_PERIOD 40 // Seconds
|
||||
#define THERMAL_PROTECTION_HYSTERESIS 4 // Degrees Celsius
|
||||
#define THERMAL_PROTECTION_PERIOD 70 // Seconds
|
||||
#define THERMAL_PROTECTION_HYSTERESIS 10 // Degrees Celsius
|
||||
|
||||
//#define ADAPTIVE_FAN_SLOWING // Slow part cooling fan if temperature drops
|
||||
#define ADAPTIVE_FAN_SLOWING // Slow part cooling fan if temperature drops
|
||||
#if BOTH(ADAPTIVE_FAN_SLOWING, PIDTEMP)
|
||||
//#define NO_FAN_SLOWING_IN_PID_TUNING // Don't slow fan speed during M303
|
||||
#define NO_FAN_SLOWING_IN_PID_TUNING // Don't slow fan speed during M303
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -212,7 +241,7 @@
|
||||
* and/or decrease WATCH_TEMP_INCREASE. WATCH_TEMP_INCREASE should not be set
|
||||
* below 2.
|
||||
*/
|
||||
#define WATCH_TEMP_PERIOD 20 // Seconds
|
||||
#define WATCH_TEMP_PERIOD 40 // Seconds
|
||||
#define WATCH_TEMP_INCREASE 2 // Degrees Celsius
|
||||
#endif
|
||||
|
||||
@@ -220,30 +249,44 @@
|
||||
* Thermal Protection parameters for the bed are just as above for hotends.
|
||||
*/
|
||||
#if ENABLED(THERMAL_PROTECTION_BED)
|
||||
#define THERMAL_PROTECTION_BED_PERIOD 20 // Seconds
|
||||
#define THERMAL_PROTECTION_BED_PERIOD 30 // Seconds
|
||||
#define THERMAL_PROTECTION_BED_HYSTERESIS 2 // Degrees Celsius
|
||||
|
||||
/**
|
||||
* As described above, except for the bed (M140/M190/M303).
|
||||
*/
|
||||
#define WATCH_BED_TEMP_PERIOD 60 // Seconds
|
||||
#define WATCH_BED_TEMP_INCREASE 2 // Degrees Celsius
|
||||
#define WATCH_BED_TEMP_INCREASE 1 // Degrees Celsius
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Thermal Protection parameters for the heated chamber.
|
||||
*/
|
||||
#if ENABLED(THERMAL_PROTECTION_CHAMBER)
|
||||
#define THERMAL_PROTECTION_CHAMBER_PERIOD 20 // Seconds
|
||||
#define THERMAL_PROTECTION_CHAMBER_PERIOD 60 // Seconds
|
||||
#define THERMAL_PROTECTION_CHAMBER_HYSTERESIS 2 // Degrees Celsius
|
||||
|
||||
/**
|
||||
* Heated chamber watch settings (M141/M191).
|
||||
*/
|
||||
#define WATCH_CHAMBER_TEMP_PERIOD 60 // Seconds
|
||||
#define WATCH_CHAMBER_TEMP_PERIOD 360 // Seconds
|
||||
#define WATCH_CHAMBER_TEMP_INCREASE 2 // Degrees Celsius
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Thermal Protection parameters for the laser cooler.
|
||||
*/
|
||||
#if ENABLED(THERMAL_PROTECTION_COOLER)
|
||||
#define THERMAL_PROTECTION_COOLER_PERIOD 10 // Seconds
|
||||
#define THERMAL_PROTECTION_COOLER_HYSTERESIS 3 // Degrees Celsius
|
||||
|
||||
/**
|
||||
* Laser cooling watch settings (M143/M193).
|
||||
*/
|
||||
#define WATCH_COOLER_TEMP_PERIOD 60 // Seconds
|
||||
#define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius
|
||||
#endif
|
||||
|
||||
#if ENABLED(PIDTEMP)
|
||||
// Add an experimental additional term to the heater power, proportional to the extrusion speed.
|
||||
// A well-chosen Kc value should add just enough power to melt the increased material volume.
|
||||
@@ -489,11 +532,15 @@
|
||||
#define E6_AUTO_FAN_PIN -1
|
||||
#define E7_AUTO_FAN_PIN -1
|
||||
#define CHAMBER_AUTO_FAN_PIN -1
|
||||
#define COOLER_AUTO_FAN_PIN -1
|
||||
#define COOLER_FAN_PIN -1
|
||||
|
||||
#define EXTRUDER_AUTO_FAN_TEMPERATURE 50
|
||||
#define EXTRUDER_AUTO_FAN_SPEED 255 // 255 == full speed
|
||||
#define CHAMBER_AUTO_FAN_TEMPERATURE 30
|
||||
#define CHAMBER_AUTO_FAN_SPEED 255
|
||||
#define COOLER_AUTO_FAN_TEMPERATURE 18
|
||||
#define COOLER_AUTO_FAN_SPEED 255
|
||||
|
||||
/**
|
||||
* Part-Cooling Fan Multiplexer
|
||||
@@ -509,18 +556,23 @@
|
||||
/**
|
||||
* M355 Case Light on-off / brightness
|
||||
*/
|
||||
//#define CASE_LIGHT_ENABLE
|
||||
#define CASE_LIGHT_ENABLE
|
||||
#if ENABLED(CASE_LIGHT_ENABLE)
|
||||
//#define CASE_LIGHT_PIN 4 // Override the default pin if needed
|
||||
#define INVERT_CASE_LIGHT false // Set true if Case Light is ON when pin is LOW
|
||||
#define CASE_LIGHT_DEFAULT_ON true // Set default power-up state on
|
||||
#define CASE_LIGHT_DEFAULT_BRIGHTNESS 105 // Set default power-up brightness (0-255, requires PWM pin)
|
||||
//#define CASE_LIGHT_MAX_PWM 128 // Limit pwm
|
||||
#define CASE_LIGHT_DEFAULT_BRIGHTNESS 255 // Set default power-up brightness (0-255, requires PWM pin)
|
||||
#define CASE_LIGHT_NO_BRIGHTNESS // Disable brightness control. Enable for non-PWM lighting.
|
||||
//#define CASE_LIGHT_MAX_PWM 128 // Limit PWM duty cycle (0-255)
|
||||
//#define CASE_LIGHT_MENU // Add Case Light options to the LCD menu
|
||||
//#define CASE_LIGHT_NO_BRIGHTNESS // Disable brightness control. Enable for non-PWM lighting.
|
||||
//#define CASE_LIGHT_USE_NEOPIXEL // Use NeoPixel LED as case light, requires NEOPIXEL_LED.
|
||||
#if ENABLED(CASE_LIGHT_USE_NEOPIXEL)
|
||||
#define CASE_LIGHT_NEOPIXEL_COLOR { 255, 255, 255, 255 } // { Red, Green, Blue, White }
|
||||
#if ENABLED(NEOPIXEL_LED)
|
||||
//#define CASE_LIGHT_USE_NEOPIXEL // Use NeoPixel LED as case light
|
||||
#endif
|
||||
#if EITHER(RGB_LED, RGBW_LED)
|
||||
//#define CASE_LIGHT_USE_RGB_LED // Use RGB / RGBW LED as case light
|
||||
#endif
|
||||
#if EITHER(CASE_LIGHT_USE_NEOPIXEL, CASE_LIGHT_USE_RGB_LED)
|
||||
#define CASE_LIGHT_DEFAULT_COLOR { 255, 255, 255, 255 } // { Red, Green, Blue, White }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -672,7 +724,7 @@
|
||||
|
||||
//#define HOMING_BACKOFF_POST_MM { 2, 2, 2 } // (mm) Backoff from endstops after homing
|
||||
|
||||
//#define QUICK_HOME // If G28 contains XY do a diagonal move first
|
||||
#define QUICK_HOME // If G28 contains XY do a diagonal move first
|
||||
//#define HOME_Y_BEFORE_X // If G28 contains XY home Y before X
|
||||
//#define HOME_Z_FIRST // Home Z first. Requires a Z-MIN endstop (not a probe).
|
||||
//#define CODEPENDENT_XY_HOMING // If X/Y can't home without homing Y/X first
|
||||
@@ -736,8 +788,8 @@
|
||||
/**
|
||||
* Use "HIGH SPEED" mode for probing.
|
||||
* Danger: Disable if your probe sometimes fails. Only suitable for stable well-adjusted systems.
|
||||
* This feature was designed for Delta's with very fast Z moves however higher speed cartesians may function
|
||||
* If the machine cannot raise the probe fast enough after a trigger, it may enter a fault state.
|
||||
* This feature was designed for Deltabots with very fast Z moves; however, higher speed Cartesians
|
||||
* might be able to use it. If the machine can't raise Z fast enough the BLTouch may go into ALARM.
|
||||
*/
|
||||
//#define BLTOUCH_HS_MODE
|
||||
|
||||
@@ -846,10 +898,10 @@
|
||||
//#define MULTI_NOZZLE_DUPLICATION
|
||||
|
||||
// By default pololu step drivers require an active high signal. However, some high power drivers require an active low signal as step.
|
||||
#define INVERT_X_STEP_PIN false
|
||||
#define INVERT_Y_STEP_PIN false
|
||||
#define INVERT_Z_STEP_PIN false
|
||||
#define INVERT_E_STEP_PIN false
|
||||
#define INVERT_X_STEP_PIN true
|
||||
#define INVERT_Y_STEP_PIN true
|
||||
#define INVERT_Z_STEP_PIN true
|
||||
#define INVERT_E_STEP_PIN true
|
||||
|
||||
/**
|
||||
* Idle Stepper Shutdown
|
||||
@@ -862,9 +914,6 @@
|
||||
#define DISABLE_INACTIVE_Z true // Set 'false' if the nozzle could fall onto your printed part!
|
||||
#define DISABLE_INACTIVE_E true
|
||||
|
||||
// If the Nozzle or Bed falls when the Z stepper is disabled, set its resting position here.
|
||||
//#define Z_AFTER_DEACTIVATE Z_HOME_POS
|
||||
|
||||
// Default Minimum Feedrates for printing and travel moves
|
||||
#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s) Minimum feedrate. Set with M205 S.
|
||||
#define DEFAULT_MINTRAVELFEEDRATE 0.0 // (mm/s) Minimum travel feedrate. Set with M205 T.
|
||||
@@ -923,7 +972,7 @@
|
||||
// increments while checking for the contact to be broken.
|
||||
#define BACKLASH_MEASUREMENT_LIMIT 0.5 // (mm)
|
||||
#define BACKLASH_MEASUREMENT_RESOLUTION 0.005 // (mm)
|
||||
#define BACKLASH_MEASUREMENT_FEEDRATE Z_PROBE_SPEED_SLOW // (mm/min)
|
||||
#define BACKLASH_MEASUREMENT_FEEDRATE Z_PROBE_FEEDRATE_SLOW // (mm/min)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -1026,7 +1075,7 @@
|
||||
* M908 - BQ_ZUM_MEGA_3D, RAMBO, PRINTRBOARD_REVF, RIGIDBOARD_V2 & SCOOVO_X9H
|
||||
* M909, M910 & LCD - only PRINTRBOARD_REVF & RIGIDBOARD_V2
|
||||
*/
|
||||
//#define PWM_MOTOR_CURRENT { 1300, 1300, 1250 } // Values in milliamps
|
||||
#define PWM_MOTOR_CURRENT { 1300, 1300, 1250 } // Values in milliamps
|
||||
//#define DIGIPOT_MOTOR_CURRENT { 135,135,135,135,135 } // Values 0-255 (RAMBO 135 = ~0.75A, 185 = ~1A)
|
||||
//#define DAC_MOTOR_CURRENT_DEFAULT { 70, 80, 90, 80 } // Default drive percent - X, Y, Z, E axis
|
||||
|
||||
@@ -1143,11 +1192,14 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Insert a menu for preheating at the top level to allow for quick access
|
||||
//#define PREHEAT_SHORTCUT_MENU_ITEM
|
||||
|
||||
#endif // HAS_LCD_MENU
|
||||
|
||||
#if HAS_DISPLAY
|
||||
// The timeout (in ms) to return to the status screen from sub-menus
|
||||
//#define LCD_TIMEOUT_TO_STATUS 15000
|
||||
#define LCD_TIMEOUT_TO_STATUS 15000
|
||||
|
||||
#if ENABLED(SHOW_BOOTSCREEN)
|
||||
#define BOOTSCREEN_TIMEOUT 4000 // (ms) Total Duration to display the boot screen(s)
|
||||
@@ -1157,13 +1209,13 @@
|
||||
#endif
|
||||
|
||||
// Scroll a longer status message into view
|
||||
//#define STATUS_MESSAGE_SCROLLING
|
||||
#define STATUS_MESSAGE_SCROLLING
|
||||
|
||||
// On the Info Screen, display XY with one decimal place when possible
|
||||
//#define LCD_DECIMAL_SMALL_XY
|
||||
|
||||
// Add an 'M73' G-code to set the current percentage
|
||||
//#define LCD_SET_PROGRESS_MANUALLY
|
||||
#define LCD_SET_PROGRESS_MANUALLY
|
||||
|
||||
// Show the E position (filament used) during printing
|
||||
//#define LCD_SHOW_E_TOTAL
|
||||
@@ -1247,7 +1299,6 @@
|
||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||
#define PLR_ENABLED_DEFAULT false // Power Loss Recovery enabled by default. (Set with 'M413 Sn' & M500)
|
||||
//#define BACKUP_POWER_SUPPLY // Backup power / UPS to move the steppers on power loss
|
||||
//#define POWER_LOSS_RECOVER_ZHOME // Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
|
||||
//#define POWER_LOSS_ZRAISE 2 // (mm) Z axis raise on resume (on power loss with UPS)
|
||||
//#define POWER_LOSS_PIN 44 // Pin to detect power loss. Set to -1 to disable default pin on boards without module.
|
||||
//#define POWER_LOSS_STATE HIGH // State of pin indicating power loss
|
||||
@@ -1259,6 +1310,12 @@
|
||||
// Without a POWER_LOSS_PIN the following option helps reduce wear on the SD card,
|
||||
// especially with "vase mode" printing. Set too high and vases cannot be continued.
|
||||
#define POWER_LOSS_MIN_Z_CHANGE 0.05 // (mm) Minimum Z change before saving power-loss data
|
||||
|
||||
// Enable if Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
|
||||
//#define POWER_LOSS_RECOVER_ZHOME
|
||||
#if ENABLED(POWER_LOSS_RECOVER_ZHOME)
|
||||
//#define POWER_LOSS_ZHOME_POS { 0, 0 } // Safe XY position to home Z while avoiding objects on the bed
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -1304,10 +1361,10 @@
|
||||
//#define UTF_FILENAME_SUPPORT
|
||||
|
||||
// This allows hosts to request long names for files and folders with M33
|
||||
//#define LONG_FILENAME_HOST_SUPPORT
|
||||
#define LONG_FILENAME_HOST_SUPPORT
|
||||
|
||||
// Enable this option to scroll long filenames in the SD card menu
|
||||
//#define SCROLL_LONG_FILENAMES
|
||||
#define SCROLL_LONG_FILENAMES
|
||||
|
||||
// Leave the heaters on after Stop Print (not recommended!)
|
||||
//#define SD_ABORT_NO_COOLDOWN
|
||||
@@ -1329,7 +1386,7 @@
|
||||
/**
|
||||
* Auto-report SdCard status with M27 S<seconds>
|
||||
*/
|
||||
//#define AUTO_REPORT_SD_STATUS
|
||||
#define AUTO_REPORT_SD_STATUS
|
||||
|
||||
/**
|
||||
* Support for USB thumb drives using an Arduino USB Host Shield or
|
||||
@@ -1481,10 +1538,12 @@
|
||||
#define STATUS_BED_ANIM // Use a second bitmap to indicate bed heating
|
||||
#define STATUS_CHAMBER_ANIM // Use a second bitmap to indicate chamber heating
|
||||
//#define STATUS_CUTTER_ANIM // Use a second bitmap to indicate spindle / laser active
|
||||
//#define STATUS_COOLER_ANIM // Use a second bitmap to indicate laser cooling
|
||||
//#define STATUS_ALT_BED_BITMAP // Use the alternative bed bitmap
|
||||
//#define STATUS_ALT_FAN_BITMAP // Use the alternative fan bitmap
|
||||
//#define STATUS_FAN_FRAMES 3 // :[0,1,2,3,4] Number of fan animation frames
|
||||
//#define STATUS_HEAT_PERCENT // Show heating in a progress bar
|
||||
#define BOOT_MARLIN_LOGO_SMALL // Show a smaller Marlin logo on the Boot Screen (saving 399 bytes of flash)
|
||||
//#define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~3260 (or ~940) bytes of PROGMEM.
|
||||
|
||||
// Frivolous Game Options
|
||||
@@ -1508,12 +1567,12 @@
|
||||
|
||||
#define DGUS_UPDATE_INTERVAL_MS 500 // (ms) Interval between automatic screen updates
|
||||
|
||||
#if EITHER(DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_HIPRECY)
|
||||
#if ANY(DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_MKS, DGUS_LCD_UI_HIPRECY)
|
||||
#define DGUS_PRINT_FILENAME // Display the filename during printing
|
||||
#define DGUS_PREHEAT_UI // Display a preheat screen during heatup
|
||||
|
||||
#if ENABLED(DGUS_LCD_UI_FYSETC)
|
||||
//#define DGUS_UI_MOVE_DIS_OPTION // Disabled by default for UI_FYSETC
|
||||
#if EITHER(DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_MKS)
|
||||
//#define DGUS_UI_MOVE_DIS_OPTION // Disabled by default for FYSETC and MKS
|
||||
#else
|
||||
#define DGUS_UI_MOVE_DIS_OPTION // Enabled by default for UI_HIPRECY
|
||||
#endif
|
||||
@@ -1556,6 +1615,8 @@
|
||||
//#define LCD_HAOYU_FT810CB // Haoyu with 5" (800x480)
|
||||
//#define LCD_ALEPHOBJECTS_CLCD_UI // Aleph Objects Color LCD UI
|
||||
//#define LCD_FYSETC_TFT81050 // FYSETC with 5" (800x480)
|
||||
//#define LCD_EVE3_50G // Matrix Orbital 5.0", 800x480, BT815
|
||||
//#define LCD_EVE2_50G // Matrix Orbital 5.0", 800x480, FT813
|
||||
|
||||
// Correct the resolution if not using the stock TFT panel.
|
||||
//#define TOUCH_UI_320x240
|
||||
@@ -1675,33 +1736,34 @@
|
||||
*
|
||||
* Warning: Does not respect endstops!
|
||||
*/
|
||||
//#define BABYSTEPPING
|
||||
#define BABYSTEPPING
|
||||
#if ENABLED(BABYSTEPPING)
|
||||
//#define INTEGRATED_BABYSTEPPING // EXPERIMENTAL integration of babystepping into the Stepper ISR
|
||||
#define INTEGRATED_BABYSTEPPING // EXPERIMENTAL integration of babystepping into the Stepper ISR
|
||||
//#define BABYSTEP_WITHOUT_HOMING
|
||||
//#define BABYSTEP_ALWAYS_AVAILABLE // Allow babystepping at all times (not just during movement).
|
||||
#define BABYSTEP_ALWAYS_AVAILABLE // Allow babystepping at all times (not just during movement).
|
||||
//#define BABYSTEP_XY // Also enable X/Y Babystepping. Not supported on DELTA!
|
||||
#define BABYSTEP_INVERT_Z false // Change if Z babysteps should go the other way
|
||||
//#define BABYSTEP_MILLIMETER_UNITS // Specify BABYSTEP_MULTIPLICATOR_(XY|Z) in mm instead of micro-steps
|
||||
#define BABYSTEP_MULTIPLICATOR_Z 1 // (steps or mm) Steps or millimeter distance for each Z babystep
|
||||
#define BABYSTEP_MULTIPLICATOR_Z 20 // (steps or mm) Steps or millimeter distance for each Z babystep
|
||||
#define BABYSTEP_MULTIPLICATOR_XY 1 // (steps or mm) Steps or millimeter distance for each XY babystep
|
||||
|
||||
//#define DOUBLECLICK_FOR_Z_BABYSTEPPING // Double-click on the Status Screen for Z Babystepping.
|
||||
#define DOUBLECLICK_FOR_Z_BABYSTEPPING // Double-click on the Status Screen for Z Babystepping.
|
||||
#if ENABLED(DOUBLECLICK_FOR_Z_BABYSTEPPING)
|
||||
#define DOUBLECLICK_MAX_INTERVAL 1250 // Maximum interval between clicks, in milliseconds.
|
||||
// Note: Extra time may be added to mitigate controller latency.
|
||||
#define BABYSTEP_ALWAYS_AVAILABLE // Allow babystepping at all times (not just during movement).
|
||||
//#define MOVE_Z_WHEN_IDLE // Jump to the move Z menu on doubleclick when printer is idle.
|
||||
#if ENABLED(MOVE_Z_WHEN_IDLE)
|
||||
#define MOVE_Z_IDLE_MULTIPLICATOR 1 // Multiply 1mm by this factor for the move step size.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//#define BABYSTEP_DISPLAY_TOTAL // Display total babysteps since last G28
|
||||
#define BABYSTEP_DISPLAY_TOTAL // Display total babysteps since last G28
|
||||
|
||||
//#define BABYSTEP_ZPROBE_OFFSET // Combine M851 Z and Babystepping
|
||||
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)
|
||||
//#define BABYSTEP_HOTEND_Z_OFFSET // For multiple hotends, babystep relative Z offsets
|
||||
//#define BABYSTEP_ZPROBE_GFX_OVERLAY // Enable graphical overlay on Z-offset editor
|
||||
#define BABYSTEP_ZPROBE_GFX_OVERLAY // Enable graphical overlay on Z-offset editor
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -2012,6 +2074,12 @@
|
||||
//#define SERIAL_STATS_DROPPED_RX
|
||||
#endif
|
||||
|
||||
// Monitor RX buffer usage
|
||||
// Dump an error to the serial port if the serial receive buffer overflows.
|
||||
// If you see these errors, increase the RX_BUFFER_SIZE value.
|
||||
// Not supported on all platforms.
|
||||
//#define RX_BUFFER_MONITOR
|
||||
|
||||
/**
|
||||
* Emergency Command Parser
|
||||
*
|
||||
@@ -2020,16 +2088,16 @@
|
||||
* Currently handles M108, M112, M410, M876
|
||||
* NOTE: Not yet implemented for all platforms.
|
||||
*/
|
||||
//#define EMERGENCY_PARSER
|
||||
#define EMERGENCY_PARSER
|
||||
|
||||
// Bad Serial-connections can miss a received command by sending an 'ok'
|
||||
// Therefore some clients abort after 30 seconds in a timeout.
|
||||
// Some other clients start sending commands while receiving a 'wait'.
|
||||
// This "wait" is only sent when the buffer is empty. 1 second is a good value here.
|
||||
//#define NO_TIMEOUTS 1000 // Milliseconds
|
||||
#define NO_TIMEOUTS 1000 // Milliseconds
|
||||
|
||||
// Some clients will have this feature soon. This could make the NO_TIMEOUTS unnecessary.
|
||||
//#define ADVANCED_OK
|
||||
#define ADVANCED_OK
|
||||
|
||||
// Printrun may have trouble receiving long strings all at once.
|
||||
// This option inserts short delays between lines of serial output.
|
||||
@@ -2163,7 +2231,7 @@
|
||||
* Requires NOZZLE_PARK_FEATURE.
|
||||
* This feature is required for the default FILAMENT_RUNOUT_SCRIPT.
|
||||
*/
|
||||
//#define ADVANCED_PAUSE_FEATURE
|
||||
#define ADVANCED_PAUSE_FEATURE
|
||||
#if ENABLED(ADVANCED_PAUSE_FEATURE)
|
||||
#define PAUSE_PARK_RETRACT_FEEDRATE 60 // (mm/s) Initial retract feedrate.
|
||||
#define PAUSE_PARK_RETRACT_LENGTH 2 // (mm) Initial retract.
|
||||
@@ -2189,7 +2257,7 @@
|
||||
// Filament can be extruded repeatedly from the Filament Change menu
|
||||
// until extrusion is consistent, and to purge old filament.
|
||||
#define ADVANCED_PAUSE_RESUME_PRIME 0 // (mm) Extra distance to prime nozzle after returning from park.
|
||||
//#define ADVANCED_PAUSE_FANS_PAUSE // Turn off print-cooling fans while the machine is paused.
|
||||
#define ADVANCED_PAUSE_FANS_PAUSE // Turn off print-cooling fans while the machine is paused.
|
||||
|
||||
// Filament Unload does a Retract, Delay, and Purge first:
|
||||
#define FILAMENT_UNLOAD_PURGE_RETRACT 13 // (mm) Unload initial retract length.
|
||||
@@ -2198,14 +2266,14 @@
|
||||
#define FILAMENT_UNLOAD_PURGE_FEEDRATE 25 // (mm/s) feedrate to purge before unload
|
||||
|
||||
#define PAUSE_PARK_NOZZLE_TIMEOUT 45 // (seconds) Time limit before the nozzle is turned off for safety.
|
||||
#define FILAMENT_CHANGE_ALERT_BEEPS 10 // Number of alert beeps to play when a response is needed.
|
||||
#define FILAMENT_CHANGE_ALERT_BEEPS 2 // Number of alert beeps to play when a response is needed.
|
||||
#define PAUSE_PARK_NO_STEPPER_TIMEOUT // Enable for XYZ steppers to stay powered on during filament change.
|
||||
|
||||
//#define PARK_HEAD_ON_PAUSE // Park the nozzle during pause and filament change.
|
||||
//#define HOME_BEFORE_FILAMENT_CHANGE // If needed, home before parking for filament change
|
||||
#define PARK_HEAD_ON_PAUSE // Park the nozzle during pause and filament change.
|
||||
#define HOME_BEFORE_FILAMENT_CHANGE // If needed, home before parking for filament change
|
||||
|
||||
//#define FILAMENT_LOAD_UNLOAD_GCODES // Add M701/M702 Load/Unload G-codes, plus Load/Unload in the LCD Prepare menu.
|
||||
//#define FILAMENT_UNLOAD_ALL_EXTRUDERS // Allow M702 to unload all extruders above a minimum target temp (as set by M302)
|
||||
#define FILAMENT_LOAD_UNLOAD_GCODES // Add M701/M702 Load/Unload G-codes, plus Load/Unload in the LCD Prepare menu.
|
||||
#define FILAMENT_UNLOAD_ALL_EXTRUDERS // Allow M702 to unload all extruders above a minimum target temp (as set by M302)
|
||||
#endif
|
||||
|
||||
// @section tmc
|
||||
@@ -2227,7 +2295,7 @@
|
||||
#if AXIS_DRIVER_TYPE_X2(TMC26X)
|
||||
#define X2_MAX_CURRENT 1000
|
||||
#define X2_SENSE_RESISTOR 91
|
||||
#define X2_MICROSTEPS 16
|
||||
#define X2_MICROSTEPS X_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Y(TMC26X)
|
||||
@@ -2239,7 +2307,7 @@
|
||||
#if AXIS_DRIVER_TYPE_Y2(TMC26X)
|
||||
#define Y2_MAX_CURRENT 1000
|
||||
#define Y2_SENSE_RESISTOR 91
|
||||
#define Y2_MICROSTEPS 16
|
||||
#define Y2_MICROSTEPS Y_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Z(TMC26X)
|
||||
@@ -2251,19 +2319,19 @@
|
||||
#if AXIS_DRIVER_TYPE_Z2(TMC26X)
|
||||
#define Z2_MAX_CURRENT 1000
|
||||
#define Z2_SENSE_RESISTOR 91
|
||||
#define Z2_MICROSTEPS 16
|
||||
#define Z2_MICROSTEPS Z_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Z3(TMC26X)
|
||||
#define Z3_MAX_CURRENT 1000
|
||||
#define Z3_SENSE_RESISTOR 91
|
||||
#define Z3_MICROSTEPS 16
|
||||
#define Z3_MICROSTEPS Z_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Z4(TMC26X)
|
||||
#define Z4_MAX_CURRENT 1000
|
||||
#define Z4_SENSE_RESISTOR 91
|
||||
#define Z4_MICROSTEPS 16
|
||||
#define Z4_MICROSTEPS Z_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_E0(TMC26X)
|
||||
@@ -2275,43 +2343,43 @@
|
||||
#if AXIS_DRIVER_TYPE_E1(TMC26X)
|
||||
#define E1_MAX_CURRENT 1000
|
||||
#define E1_SENSE_RESISTOR 91
|
||||
#define E1_MICROSTEPS 16
|
||||
#define E1_MICROSTEPS E0_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_E2(TMC26X)
|
||||
#define E2_MAX_CURRENT 1000
|
||||
#define E2_SENSE_RESISTOR 91
|
||||
#define E2_MICROSTEPS 16
|
||||
#define E2_MICROSTEPS E0_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_E3(TMC26X)
|
||||
#define E3_MAX_CURRENT 1000
|
||||
#define E3_SENSE_RESISTOR 91
|
||||
#define E3_MICROSTEPS 16
|
||||
#define E3_MICROSTEPS E0_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_E4(TMC26X)
|
||||
#define E4_MAX_CURRENT 1000
|
||||
#define E4_SENSE_RESISTOR 91
|
||||
#define E4_MICROSTEPS 16
|
||||
#define E4_MICROSTEPS E0_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_E5(TMC26X)
|
||||
#define E5_MAX_CURRENT 1000
|
||||
#define E5_SENSE_RESISTOR 91
|
||||
#define E5_MICROSTEPS 16
|
||||
#define E5_MICROSTEPS E0_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_E6(TMC26X)
|
||||
#define E6_MAX_CURRENT 1000
|
||||
#define E6_SENSE_RESISTOR 91
|
||||
#define E6_MICROSTEPS 16
|
||||
#define E6_MICROSTEPS E0_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_E7(TMC26X)
|
||||
#define E7_MAX_CURRENT 1000
|
||||
#define E7_SENSE_RESISTOR 91
|
||||
#define E7_MICROSTEPS 16
|
||||
#define E7_MICROSTEPS E0_MICROSTEPS
|
||||
#endif
|
||||
|
||||
#endif // TMC26X
|
||||
@@ -2356,7 +2424,7 @@
|
||||
#if AXIS_IS_TMC(X2)
|
||||
#define X2_CURRENT 800
|
||||
#define X2_CURRENT_HOME X2_CURRENT
|
||||
#define X2_MICROSTEPS 16
|
||||
#define X2_MICROSTEPS X_MICROSTEPS
|
||||
#define X2_RSENSE 0.11
|
||||
#define X2_CHAIN_POS -1
|
||||
//#define X2_INTERPOLATE true
|
||||
@@ -2374,7 +2442,7 @@
|
||||
#if AXIS_IS_TMC(Y2)
|
||||
#define Y2_CURRENT 800
|
||||
#define Y2_CURRENT_HOME Y2_CURRENT
|
||||
#define Y2_MICROSTEPS 16
|
||||
#define Y2_MICROSTEPS Y_MICROSTEPS
|
||||
#define Y2_RSENSE 0.11
|
||||
#define Y2_CHAIN_POS -1
|
||||
//#define Y2_INTERPOLATE true
|
||||
@@ -2392,7 +2460,7 @@
|
||||
#if AXIS_IS_TMC(Z2)
|
||||
#define Z2_CURRENT 800
|
||||
#define Z2_CURRENT_HOME Z2_CURRENT
|
||||
#define Z2_MICROSTEPS 16
|
||||
#define Z2_MICROSTEPS Z_MICROSTEPS
|
||||
#define Z2_RSENSE 0.11
|
||||
#define Z2_CHAIN_POS -1
|
||||
//#define Z2_INTERPOLATE true
|
||||
@@ -2401,7 +2469,7 @@
|
||||
#if AXIS_IS_TMC(Z3)
|
||||
#define Z3_CURRENT 800
|
||||
#define Z3_CURRENT_HOME Z3_CURRENT
|
||||
#define Z3_MICROSTEPS 16
|
||||
#define Z3_MICROSTEPS Z_MICROSTEPS
|
||||
#define Z3_RSENSE 0.11
|
||||
#define Z3_CHAIN_POS -1
|
||||
//#define Z3_INTERPOLATE true
|
||||
@@ -2410,7 +2478,7 @@
|
||||
#if AXIS_IS_TMC(Z4)
|
||||
#define Z4_CURRENT 800
|
||||
#define Z4_CURRENT_HOME Z4_CURRENT
|
||||
#define Z4_MICROSTEPS 16
|
||||
#define Z4_MICROSTEPS Z_MICROSTEPS
|
||||
#define Z4_RSENSE 0.11
|
||||
#define Z4_CHAIN_POS -1
|
||||
//#define Z4_INTERPOLATE true
|
||||
@@ -2426,7 +2494,7 @@
|
||||
|
||||
#if AXIS_IS_TMC(E1)
|
||||
#define E1_CURRENT 800
|
||||
#define E1_MICROSTEPS 16
|
||||
#define E1_MICROSTEPS E0_MICROSTEPS
|
||||
#define E1_RSENSE 0.11
|
||||
#define E1_CHAIN_POS -1
|
||||
//#define E1_INTERPOLATE true
|
||||
@@ -2434,7 +2502,7 @@
|
||||
|
||||
#if AXIS_IS_TMC(E2)
|
||||
#define E2_CURRENT 800
|
||||
#define E2_MICROSTEPS 16
|
||||
#define E2_MICROSTEPS E0_MICROSTEPS
|
||||
#define E2_RSENSE 0.11
|
||||
#define E2_CHAIN_POS -1
|
||||
//#define E2_INTERPOLATE true
|
||||
@@ -2442,7 +2510,7 @@
|
||||
|
||||
#if AXIS_IS_TMC(E3)
|
||||
#define E3_CURRENT 800
|
||||
#define E3_MICROSTEPS 16
|
||||
#define E3_MICROSTEPS E0_MICROSTEPS
|
||||
#define E3_RSENSE 0.11
|
||||
#define E3_CHAIN_POS -1
|
||||
//#define E3_INTERPOLATE true
|
||||
@@ -2450,7 +2518,7 @@
|
||||
|
||||
#if AXIS_IS_TMC(E4)
|
||||
#define E4_CURRENT 800
|
||||
#define E4_MICROSTEPS 16
|
||||
#define E4_MICROSTEPS E0_MICROSTEPS
|
||||
#define E4_RSENSE 0.11
|
||||
#define E4_CHAIN_POS -1
|
||||
//#define E4_INTERPOLATE true
|
||||
@@ -2458,7 +2526,7 @@
|
||||
|
||||
#if AXIS_IS_TMC(E5)
|
||||
#define E5_CURRENT 800
|
||||
#define E5_MICROSTEPS 16
|
||||
#define E5_MICROSTEPS E0_MICROSTEPS
|
||||
#define E5_RSENSE 0.11
|
||||
#define E5_CHAIN_POS -1
|
||||
//#define E5_INTERPOLATE true
|
||||
@@ -2466,7 +2534,7 @@
|
||||
|
||||
#if AXIS_IS_TMC(E6)
|
||||
#define E6_CURRENT 800
|
||||
#define E6_MICROSTEPS 16
|
||||
#define E6_MICROSTEPS E0_MICROSTEPS
|
||||
#define E6_RSENSE 0.11
|
||||
#define E6_CHAIN_POS -1
|
||||
//#define E6_INTERPOLATE true
|
||||
@@ -2474,7 +2542,7 @@
|
||||
|
||||
#if AXIS_IS_TMC(E7)
|
||||
#define E7_CURRENT 800
|
||||
#define E7_MICROSTEPS 16
|
||||
#define E7_MICROSTEPS E0_MICROSTEPS
|
||||
#define E7_RSENSE 0.11
|
||||
#define E7_CHAIN_POS -1
|
||||
//#define E7_INTERPOLATE true
|
||||
@@ -2749,138 +2817,138 @@
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
#define X2_MICROSTEPS 128
|
||||
#define X2_OVERCURRENT 2000
|
||||
#define X2_STALLCURRENT 1500
|
||||
#define X2_MAX_VOLTAGE 127
|
||||
#define X2_CHAIN_POS -1
|
||||
#define X2_SLEW_RATE 1
|
||||
#define X2_MICROSTEPS X_MICROSTEPS
|
||||
#define X2_OVERCURRENT 2000
|
||||
#define X2_STALLCURRENT 1500
|
||||
#define X2_MAX_VOLTAGE 127
|
||||
#define X2_CHAIN_POS -1
|
||||
#define X2_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
#define Y_MICROSTEPS 128
|
||||
#define Y_OVERCURRENT 2000
|
||||
#define Y_STALLCURRENT 1500
|
||||
#define Y_MAX_VOLTAGE 127
|
||||
#define Y_CHAIN_POS -1
|
||||
#define Y_SLEW_RATE 1
|
||||
#define Y_MICROSTEPS 128
|
||||
#define Y_OVERCURRENT 2000
|
||||
#define Y_STALLCURRENT 1500
|
||||
#define Y_MAX_VOLTAGE 127
|
||||
#define Y_CHAIN_POS -1
|
||||
#define Y_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(Y2)
|
||||
#define Y2_MICROSTEPS 128
|
||||
#define Y2_OVERCURRENT 2000
|
||||
#define Y2_STALLCURRENT 1500
|
||||
#define Y2_MAX_VOLTAGE 127
|
||||
#define Y2_CHAIN_POS -1
|
||||
#define Y2_SLEW_RATE 1
|
||||
#define Y2_MICROSTEPS Y_MICROSTEPS
|
||||
#define Y2_OVERCURRENT 2000
|
||||
#define Y2_STALLCURRENT 1500
|
||||
#define Y2_MAX_VOLTAGE 127
|
||||
#define Y2_CHAIN_POS -1
|
||||
#define Y2_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
#define Z_MICROSTEPS 128
|
||||
#define Z_OVERCURRENT 2000
|
||||
#define Z_STALLCURRENT 1500
|
||||
#define Z_MAX_VOLTAGE 127
|
||||
#define Z_CHAIN_POS -1
|
||||
#define Z_SLEW_RATE 1
|
||||
#define Z_MICROSTEPS 128
|
||||
#define Z_OVERCURRENT 2000
|
||||
#define Z_STALLCURRENT 1500
|
||||
#define Z_MAX_VOLTAGE 127
|
||||
#define Z_CHAIN_POS -1
|
||||
#define Z_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(Z2)
|
||||
#define Z2_MICROSTEPS 128
|
||||
#define Z2_OVERCURRENT 2000
|
||||
#define Z2_STALLCURRENT 1500
|
||||
#define Z2_MAX_VOLTAGE 127
|
||||
#define Z2_CHAIN_POS -1
|
||||
#define Z2_SLEW_RATE 1
|
||||
#define Z2_MICROSTEPS Z_MICROSTEPS
|
||||
#define Z2_OVERCURRENT 2000
|
||||
#define Z2_STALLCURRENT 1500
|
||||
#define Z2_MAX_VOLTAGE 127
|
||||
#define Z2_CHAIN_POS -1
|
||||
#define Z2_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(Z3)
|
||||
#define Z3_MICROSTEPS 128
|
||||
#define Z3_OVERCURRENT 2000
|
||||
#define Z3_STALLCURRENT 1500
|
||||
#define Z3_MAX_VOLTAGE 127
|
||||
#define Z3_CHAIN_POS -1
|
||||
#define Z3_SLEW_RATE 1
|
||||
#define Z3_MICROSTEPS Z_MICROSTEPS
|
||||
#define Z3_OVERCURRENT 2000
|
||||
#define Z3_STALLCURRENT 1500
|
||||
#define Z3_MAX_VOLTAGE 127
|
||||
#define Z3_CHAIN_POS -1
|
||||
#define Z3_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(Z4)
|
||||
#define Z4_MICROSTEPS 128
|
||||
#define Z4_OVERCURRENT 2000
|
||||
#define Z4_STALLCURRENT 1500
|
||||
#define Z4_MAX_VOLTAGE 127
|
||||
#define Z4_CHAIN_POS -1
|
||||
#define Z4_SLEW_RATE 1
|
||||
#define Z4_MICROSTEPS Z_MICROSTEPS
|
||||
#define Z4_OVERCURRENT 2000
|
||||
#define Z4_STALLCURRENT 1500
|
||||
#define Z4_MAX_VOLTAGE 127
|
||||
#define Z4_CHAIN_POS -1
|
||||
#define Z4_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
#define E0_MICROSTEPS 128
|
||||
#define E0_OVERCURRENT 2000
|
||||
#define E0_STALLCURRENT 1500
|
||||
#define E0_MAX_VOLTAGE 127
|
||||
#define E0_CHAIN_POS -1
|
||||
#define E0_SLEW_RATE 1
|
||||
#define E0_MICROSTEPS 128
|
||||
#define E0_OVERCURRENT 2000
|
||||
#define E0_STALLCURRENT 1500
|
||||
#define E0_MAX_VOLTAGE 127
|
||||
#define E0_CHAIN_POS -1
|
||||
#define E0_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
#define E1_MICROSTEPS 128
|
||||
#define E1_OVERCURRENT 2000
|
||||
#define E1_STALLCURRENT 1500
|
||||
#define E1_MAX_VOLTAGE 127
|
||||
#define E1_CHAIN_POS -1
|
||||
#define E1_SLEW_RATE 1
|
||||
#define E1_MICROSTEPS E0_MICROSTEPS
|
||||
#define E1_OVERCURRENT 2000
|
||||
#define E1_STALLCURRENT 1500
|
||||
#define E1_MAX_VOLTAGE 127
|
||||
#define E1_CHAIN_POS -1
|
||||
#define E1_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
#define E2_MICROSTEPS 128
|
||||
#define E2_OVERCURRENT 2000
|
||||
#define E2_STALLCURRENT 1500
|
||||
#define E2_MAX_VOLTAGE 127
|
||||
#define E2_CHAIN_POS -1
|
||||
#define E2_SLEW_RATE 1
|
||||
#define E2_MICROSTEPS E0_MICROSTEPS
|
||||
#define E2_OVERCURRENT 2000
|
||||
#define E2_STALLCURRENT 1500
|
||||
#define E2_MAX_VOLTAGE 127
|
||||
#define E2_CHAIN_POS -1
|
||||
#define E2_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
#define E3_MICROSTEPS 128
|
||||
#define E3_OVERCURRENT 2000
|
||||
#define E3_STALLCURRENT 1500
|
||||
#define E3_MAX_VOLTAGE 127
|
||||
#define E3_CHAIN_POS -1
|
||||
#define E3_SLEW_RATE 1
|
||||
#define E3_MICROSTEPS E0_MICROSTEPS
|
||||
#define E3_OVERCURRENT 2000
|
||||
#define E3_STALLCURRENT 1500
|
||||
#define E3_MAX_VOLTAGE 127
|
||||
#define E3_CHAIN_POS -1
|
||||
#define E3_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
#define E4_MICROSTEPS 128
|
||||
#define E4_OVERCURRENT 2000
|
||||
#define E4_STALLCURRENT 1500
|
||||
#define E4_MAX_VOLTAGE 127
|
||||
#define E4_CHAIN_POS -1
|
||||
#define E4_SLEW_RATE 1
|
||||
#define E4_MICROSTEPS E0_MICROSTEPS
|
||||
#define E4_OVERCURRENT 2000
|
||||
#define E4_STALLCURRENT 1500
|
||||
#define E4_MAX_VOLTAGE 127
|
||||
#define E4_CHAIN_POS -1
|
||||
#define E4_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
#define E5_MICROSTEPS 128
|
||||
#define E5_OVERCURRENT 2000
|
||||
#define E5_STALLCURRENT 1500
|
||||
#define E5_MAX_VOLTAGE 127
|
||||
#define E5_CHAIN_POS -1
|
||||
#define E5_SLEW_RATE 1
|
||||
#define E5_MICROSTEPS E0_MICROSTEPS
|
||||
#define E5_OVERCURRENT 2000
|
||||
#define E5_STALLCURRENT 1500
|
||||
#define E5_MAX_VOLTAGE 127
|
||||
#define E5_CHAIN_POS -1
|
||||
#define E5_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(E6)
|
||||
#define E6_MICROSTEPS 128
|
||||
#define E6_OVERCURRENT 2000
|
||||
#define E6_STALLCURRENT 1500
|
||||
#define E6_MAX_VOLTAGE 127
|
||||
#define E6_CHAIN_POS -1
|
||||
#define E6_SLEW_RATE 1
|
||||
#define E6_MICROSTEPS E0_MICROSTEPS
|
||||
#define E6_OVERCURRENT 2000
|
||||
#define E6_STALLCURRENT 1500
|
||||
#define E6_MAX_VOLTAGE 127
|
||||
#define E6_CHAIN_POS -1
|
||||
#define E6_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
#if AXIS_IS_L64XX(E7)
|
||||
#define E7_MICROSTEPS 128
|
||||
#define E7_OVERCURRENT 2000
|
||||
#define E7_STALLCURRENT 1500
|
||||
#define E7_MAX_VOLTAGE 127
|
||||
#define E7_CHAIN_POS -1
|
||||
#define E7_SLEW_RATE 1
|
||||
#define E7_MICROSTEPS E0_MICROSTEPS
|
||||
#define E7_OVERCURRENT 2000
|
||||
#define E7_STALLCURRENT 1500
|
||||
#define E7_MAX_VOLTAGE 127
|
||||
#define E7_CHAIN_POS -1
|
||||
#define E7_SLEW_RATE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -3307,7 +3375,9 @@
|
||||
//#define GCODE_QUOTED_STRINGS // Support for quoted string parameters
|
||||
#endif
|
||||
|
||||
//#define MEATPACK // Support for MeatPack G-code compression (https://github.com/scottmudge/OctoPrint-MeatPack)
|
||||
// Support for MeatPack G-code compression (https://github.com/scottmudge/OctoPrint-MeatPack)
|
||||
//#define MEATPACK_ON_SERIAL_PORT_1
|
||||
//#define MEATPACK_ON_SERIAL_PORT_2
|
||||
|
||||
//#define GCODE_CASE_INSENSITIVE // Accept G-code sent to the firmware in lowercase
|
||||
|
||||
@@ -3347,6 +3417,37 @@
|
||||
#define GCODE_MACROS_SLOT_SIZE 50 // Maximum length of a single macro
|
||||
#endif
|
||||
|
||||
/**
|
||||
* User-defined buttons to run custom G-code.
|
||||
* Up to 25 may be defined.
|
||||
*/
|
||||
//#define CUSTOM_USER_BUTTONS
|
||||
#if ENABLED(CUSTOM_USER_BUTTONS)
|
||||
//#define BUTTON1_PIN -1
|
||||
#if PIN_EXISTS(BUTTON1)
|
||||
#define BUTTON1_HIT_STATE LOW // State of the triggered button. NC=LOW. NO=HIGH.
|
||||
#define BUTTON1_WHEN_PRINTING false // Button allowed to trigger during printing?
|
||||
#define BUTTON1_GCODE "G28"
|
||||
#define BUTTON1_DESC "Homing" // Optional string to set the LCD status
|
||||
#endif
|
||||
|
||||
//#define BUTTON2_PIN -1
|
||||
#if PIN_EXISTS(BUTTON2)
|
||||
#define BUTTON2_HIT_STATE LOW
|
||||
#define BUTTON2_WHEN_PRINTING false
|
||||
#define BUTTON2_GCODE "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
|
||||
#define BUTTON2_DESC "Preheat for " PREHEAT_1_LABEL
|
||||
#endif
|
||||
|
||||
//#define BUTTON3_PIN -1
|
||||
#if PIN_EXISTS(BUTTON3)
|
||||
#define BUTTON3_HIT_STATE LOW
|
||||
#define BUTTON3_WHEN_PRINTING false
|
||||
#define BUTTON3_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
|
||||
#define BUTTON3_DESC "Preheat for " PREHEAT_2_LABEL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* User-defined menu items to run custom G-code.
|
||||
* Up to 25 may be defined, but the actual number is LCD-dependent.
|
||||
@@ -3356,22 +3457,28 @@
|
||||
//#define CUSTOM_USER_MENU_TITLE "Custom Commands"
|
||||
#define USER_SCRIPT_DONE "M117 User Script Done"
|
||||
#define USER_SCRIPT_AUDIBLE_FEEDBACK
|
||||
//#define USER_SCRIPT_RETURN // Return to status screen after a script
|
||||
//#define USER_SCRIPT_RETURN // Return to status screen after a script
|
||||
#define CUSTOM_MENU_ONLY_IDLE // Only show custom menu when the machine is idle
|
||||
|
||||
#define USER_DESC_1 "Home & UBL Info"
|
||||
#define USER_GCODE_1 "G28\nG29W"
|
||||
//#define USER_CONFIRM_1 // Show a confirmation dialog before this action
|
||||
|
||||
#define USER_DESC_2 "Preheat for " PREHEAT_1_LABEL
|
||||
#define USER_GCODE_2 "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
|
||||
//#define USER_CONFIRM_2
|
||||
|
||||
#define USER_DESC_3 "Preheat for " PREHEAT_2_LABEL
|
||||
#define USER_GCODE_3 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
|
||||
//#define USER_CONFIRM_3
|
||||
|
||||
#define USER_DESC_4 "Heat Bed/Home/Level"
|
||||
#define USER_GCODE_4 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29"
|
||||
//#define USER_CONFIRM_4
|
||||
|
||||
#define USER_DESC_5 "Home & Info"
|
||||
#define USER_GCODE_5 "G28\nM503"
|
||||
//#define USER_CONFIRM_5
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -3388,10 +3495,10 @@
|
||||
* Host Prompt Support enables Marlin to use the host for user prompts so
|
||||
* filament runout and other processes can be managed from the host side.
|
||||
*/
|
||||
//#define HOST_ACTION_COMMANDS
|
||||
#define HOST_ACTION_COMMANDS
|
||||
#if ENABLED(HOST_ACTION_COMMANDS)
|
||||
//#define HOST_PROMPT_SUPPORT
|
||||
//#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start
|
||||
#define HOST_PROMPT_SUPPORT
|
||||
#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -3728,7 +3835,14 @@
|
||||
//
|
||||
// M43 - display pin status, toggle pins, watch pins, watch endstops & toggle LED, test servo probe
|
||||
//
|
||||
//#define PINS_DEBUGGING
|
||||
#define PINS_DEBUGGING
|
||||
|
||||
// Enable Marlin dev mode which adds some special commands
|
||||
//#define MARLIN_DEV_MODE
|
||||
|
||||
/**
|
||||
* Postmortem Debugging captures misbehavior and outputs the CPU status and backtrace to serial.
|
||||
* When running in the debugger it will break for debugging. This is useful to help understand
|
||||
* a crash from a remote location. Requires ~400 bytes of SRAM and 5Kb of flash.
|
||||
*/
|
||||
//#define POSTMORTEM_DEBUGGING
|
||||
|
||||
@@ -323,6 +323,8 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1203)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1204)
|
||||
# abee Scoovo X9H
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1205)
|
||||
# Rambo ThinkerV2
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1206)
|
||||
|
||||
#
|
||||
# Other ATmega1280, ATmega2560
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Custom Bitmap for splashscreen
|
||||
*
|
||||
* You may use one of the following tools to generate the C++ bitmap array from
|
||||
* a black and white image:
|
||||
*
|
||||
* - http://www.marlinfw.org/tools/u8glib/converter.html
|
||||
* - http://www.digole.com/tools/PicturetoC_Hex_converter.php
|
||||
*/
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define CUSTOM_BOOTSCREEN_TIMEOUT 2500
|
||||
#define CUSTOM_BOOTSCREEN_BMPWIDTH 125
|
||||
//#define CUSTOM_BOOTSCREEN_INVERTED
|
||||
|
||||
const unsigned char custom_start_bmp[] PROGMEM = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ..............................................................##................................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ..............................................................##.##.............................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ................................................................#...#...........................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ................................................................###..###........................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x71,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // .................................................................###...##.......................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x40,0x00,0x00,0x00,0x00,0x00,0x00, // ..................................................................##.....#......................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x20,0x00,0x00,0x00,0x00,0x00,0x00, // ..................................................................####....#.....................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x20,0x00,0x00,0x00,0x00,0x00,0x00, // ................................................................########..#.....................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x01,0xF8,0x00,0x87,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, // ...............................................######...........#....########...................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x00,0x83,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, // ..............................................##....##..........#.....#####.....................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x06,0x0C,0x00,0x81,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // .............................................##.....##..........#......###......................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x0C,0x06,0x00,0x80,0xE3,0x00,0x00,0x00,0x00,0x00,0x00, // ............................................##.......##.........#.......###...##................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x18,0x06,0x00,0x80,0x6F,0x80,0x00,0x00,0x00,0x00,0x00, // ...........................................##........##.........#........##.#####...............................................
|
||||
0x00,0x00,0x00,0x00,0x1C,0x38,0x02,0x00,0x80,0x3C,0xC0,0x00,0x00,0x00,0x00,0x00, // ...................................###....###.........#.........#.........####..##..............................................
|
||||
0x00,0x00,0x00,0x00,0x1F,0x30,0x03,0x00,0xC0,0x3C,0x60,0x00,0x00,0x00,0x00,0x00, // ...................................#####..##..........##........##........####...##.............................................
|
||||
0x00,0x00,0x00,0x00,0x77,0xB0,0x02,0xFF,0x60,0x3C,0x30,0x00,0x00,0x00,0x00,0x00, // .................................###.####.##..........#.########.##.......####....##............................................
|
||||
0x00,0x00,0x00,0x00,0xE0,0xF8,0x06,0xFF,0xB0,0x3C,0x18,0x00,0x00,0x00,0x00,0x00, // ................................###.....#####........##.#########.##......####.....##...........................................
|
||||
0x00,0x00,0x00,0x00,0xC0,0xD8,0x0D,0x81,0x98,0x1C,0x08,0x00,0x00,0x00,0x00,0x00, // ................................##......##.##.......##.##......##..##......###......#...........................................
|
||||
0x00,0x00,0x00,0x03,0x80,0xD8,0x09,0x80,0xDC,0xFC,0x08,0x00,0x00,0x00,0x00,0x00, // ..............................###.......##.##.......#..##.......##.###..######......#...........................................
|
||||
0x00,0x00,0x00,0x02,0x00,0xD8,0x1B,0x00,0x6F,0xE4,0x0C,0x00,0x00,0x00,0x00,0x00, // ..............................#.........##.##......##.##.........##.#######..#......##..........................................
|
||||
0x00,0x00,0x00,0x02,0x00,0xDF,0xFB,0x00,0x37,0x06,0x0C,0x00,0x00,0x00,0x00,0x00, // ..............................#.........##.##########.##..........##.###.....##.....##..........................................
|
||||
0x00,0x00,0x00,0x06,0x00,0xE7,0xF6,0x00,0x18,0x03,0x04,0x00,0x00,0x00,0x00,0x00, // .............................##.........###..#######.##............##.........##.....#..........................................
|
||||
0x00,0x00,0x00,0x06,0x00,0xE0,0x0E,0x00,0x18,0x0F,0x04,0x00,0x00,0x00,0x00,0x00, // .............................##.........###.........###............##.......####.....#..........................................
|
||||
0x00,0x00,0x00,0x06,0x00,0xC0,0x2E,0x00,0x1B,0xFF,0xC6,0x00,0x00,0x00,0x00,0x00, // .............................##.........##........#.###............##.############...##.........................................
|
||||
0x3F,0xFC,0x1F,0xF6,0x7D,0x81,0xE6,0x00,0x1B,0xC7,0xC6,0x00,0x00,0x00,0x00,0x00, // ..############.....#########.##..#####.##......####..##............##.####...#####...##.........................................
|
||||
0x7F,0xFE,0x3F,0xFF,0x1F,0x8F,0xC3,0xFF,0xFF,0xFF,0xFC,0x1F,0xFF,0x38,0x03,0xC0, // .##############...##############...######...######....################################.....#############..###.........####......
|
||||
0xFF,0xFF,0xFF,0xFF,0x8F,0x1F,0xC7,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0x3C,0x03,0xE0, // #################################...####...#######...################################...################..####........#####.....
|
||||
0x10,0x0F,0xF0,0x0F,0x8F,0xFF,0x83,0xFF,0xF7,0xFF,0xF8,0xFF,0xFC,0x3C,0x03,0xE0, // ...#........########........#####...#############.....##############.################...##############....####........#####.....
|
||||
0x00,0x0F,0xF0,0x07,0xFF,0xFF,0x01,0x9E,0x27,0xFC,0xC2,0xF8,0x00,0x3E,0x03,0xE0, // ............########.........###################.......##..####...#..#########..##....#.#####.............#####.......#####.....
|
||||
0x0F,0xFF,0xF0,0x03,0xDF,0xFE,0x01,0xCE,0x6C,0xFC,0x47,0xF8,0x00,0x3F,0xFF,0xE0, // ....################..........####.############........###..###..##.##..######...#...########.............#################.....
|
||||
0x1F,0xFF,0xF0,0x03,0xC3,0xFC,0x00,0xFF,0xCC,0xFF,0xFF,0xF0,0x00,0x3F,0xFF,0xE0, // ...#################..........####....########..........##########..##..####################..............#################.....
|
||||
0x1F,0xFF,0xF0,0x03,0xC3,0xFC,0x00,0x0E,0x1C,0xFF,0xF9,0xE0,0x00,0x3F,0xFF,0xE0, // ...#################..........####....########..............###....###..#############..####...............#################.....
|
||||
0x00,0x0F,0xF0,0x0F,0xC7,0xFC,0x00,0x0E,0x1C,0xFF,0xF1,0xE0,0x00,0x3F,0xFF,0xE0, // ............########........######...#########..............###....###..############...####...............#################.....
|
||||
0x00,0x0F,0xF8,0x0F,0x87,0xFE,0x00,0x0E,0x0C,0xF8,0xF0,0xF0,0x00,0x3C,0x03,0xE0, // ............#########.......#####....##########.............###.....##..#####...####....####..............####........#####.....
|
||||
0x7F,0xFF,0xFF,0xFF,0xBF,0x8F,0x00,0x3F,0xE6,0xF8,0xE0,0xFC,0x00,0x3C,0x03,0xE0, // .################################.#######...####..........#########..##.#####...###.....######............####........#####.....
|
||||
0x7F,0xFF,0xFF,0xFF,0xFF,0x07,0xC0,0xFF,0xE7,0xFF,0xFC,0xFF,0xFF,0x3C,0x03,0xE0, // .#######################################.....#####......###########..#################..################..####........#####.....
|
||||
0xFF,0xFF,0xFF,0xFF,0xFE,0x03,0xE0,0x8E,0x33,0xFF,0xFC,0x1F,0xFF,0x3C,0x03,0xE0, // #######################################.......#####.....#...###...##..################.....#############..####........#####.....
|
||||
0x7F,0xFC,0x3F,0xF0,0x3C,0x01,0xF1,0x9E,0x31,0xFF,0xF9,0x0F,0xFE,0x3C,0x03,0xC0, // .#############....##########......####.........#####...##..####...##...##############..#....###########...####........####......
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x19,0xFF,0xC1,0x00,0x00,0x00,0x00,0x00, // ......................................................##...........##..###########.....#........................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0xE0,0xC1,0x00,0x00,0x00,0x00,0x00, // ......................................................##............##..###.....##.....#........................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x42,0x00,0x00,0x00,0x00,0x00, // .....................................................##.............##...........#....#.........................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x01,0x62,0x00,0x00,0x00,0x00,0x00, // .....................................................##..............##........#.##...#.........................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x06,0x3F,0x62,0x00,0x00,0x00,0x00,0x00, // ....................................................##...............##...######.##...#.........................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x38,0x0E,0x00,0x0D,0xFD,0xEE,0x00,0x00,0x00,0x00,0x00, // ..........................................###.......###.............##.#######.####.###.........................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x7F,0xE6,0x00,0x19,0x81,0xFC,0x00,0x00,0x00,0x00,0x00, // .........................................##########..##............##..##......#######..........................................
|
||||
0x00,0x00,0x00,0x00,0x00,0xEF,0xF7,0x00,0x1B,0x01,0xF0,0x00,0x00,0x00,0x00,0x00, // ........................................###.########.###...........##.##.......#####............................................
|
||||
0x00,0x00,0x00,0x00,0x00,0xC0,0x33,0x00,0x33,0x01,0xC8,0x00,0x00,0x00,0x00,0x00, // ........................................##........##..##..........##..##.......###..#...........................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x80,0x1B,0x00,0x36,0x01,0x98,0x00,0x00,0x00,0x00,0x00, // ........................................#..........##.##..........##.##........##..##...........................................
|
||||
0x00,0x00,0x00,0x00,0x01,0x80,0x0D,0xFF,0xEC,0x01,0xF0,0x00,0x00,0x00,0x00,0x00, // .......................................##...........##.############.##.........#####............................................
|
||||
0x00,0x00,0x00,0x00,0x01,0x00,0x0E,0xFF,0xD8,0x01,0xE0,0x00,0x00,0x00,0x00,0x00, // .......................................#............###.##########.##..........####.............................................
|
||||
0x00,0x00,0x00,0x01,0xF1,0x80,0x06,0x60,0x38,0x07,0xA0,0x00,0x00,0x00,0x00,0x00, // ...............................#####...##............##..##.......###........####.#.............................................
|
||||
0x00,0x00,0x00,0x01,0xFD,0x80,0x03,0x00,0x18,0x05,0x40,0x00,0x00,0x00,0x00,0x00, // ...............................#######.##.............##...........##........#.#.#..............................................
|
||||
0x00,0x00,0x00,0x01,0x8F,0xC0,0x06,0xFF,0xDC,0x0A,0x80,0x00,0x00,0x00,0x00,0x00, // ...............................##...######...........##.##########.###......#.#.#...............................................
|
||||
0x00,0x00,0x00,0x00,0x81,0xE0,0x0C,0xFF,0xCC,0x1F,0x00,0x00,0x00,0x00,0x00,0x00, // ................................#......####.........##..##########..##.....#####................................................
|
||||
0x00,0x00,0x00,0x00,0x81,0xF0,0x0D,0x80,0x6C,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, // ................................#......#####........##.##........##.##..#######.................................................
|
||||
0x00,0x00,0x00,0x00,0x40,0xFE,0x1B,0x00,0x67,0x8C,0x00,0x00,0x00,0x00,0x00,0x00, // .................................#......#######....##.##.........##..####...##..................................................
|
||||
0x00,0x00,0x00,0x00,0x20,0x7F,0xF6,0x00,0x20,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // ..................................#......###########.##...........#........##...................................................
|
||||
0x00,0x00,0x00,0x00,0x10,0x30,0x6E,0x00,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, // ...................................#......##.....##.###...........##########....................................................
|
||||
0x00,0x00,0x00,0x00,0x04,0x30,0x0E,0x00,0xFF,0xA0,0x00,0x00,0x00,0x00,0x00,0x00, // .....................................#....##........###.........#########.#.....................................................
|
||||
0x00,0x00,0x00,0x00,0x03,0x30,0x06,0x00,0xE1,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ......................................##..##.........##.........###....#........................................................
|
||||
0x00,0x00,0x00,0x00,0x01,0xF0,0x03,0x03,0xE2,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // .......................................#####..........##......#####...#.........................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // .......................................................##########...#...........................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ..............................................................#...##............................................................
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // .............................................................###................................................................
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Custom Status Screen bitmap
|
||||
*
|
||||
* Place this file in the root with your configuration files
|
||||
* and enable CUSTOM_STATUS_SCREEN_IMAGE in Configuration.h.
|
||||
*
|
||||
* Use the Marlin Bitmap Converter to make your own:
|
||||
* http://marlinfw.org/tools/u8glib/converter.html
|
||||
*/
|
||||
|
||||
//
|
||||
// Status Screen Logo bitmap
|
||||
//
|
||||
#define STATUS_LOGO_Y 1
|
||||
#define STATUS_LOGO_WIDTH 32
|
||||
|
||||
const unsigned char status_logo_bmp[] PROGMEM = {
|
||||
0x00,0x00,0x00,0x00, // ................................
|
||||
0x00,0x00,0x00,0x00, // ................................
|
||||
0x00,0x00,0x00,0x00, // ................................
|
||||
0x00,0x00,0x10,0x00, // ...................#............
|
||||
0x00,0x00,0x06,0x00, // .....................##.........
|
||||
0x00,0x00,0x00,0x00, // ................................
|
||||
0x01,0x00,0x00,0x00, // .......#........................
|
||||
0x08,0x00,0x01,0x00, // ....#..................#........
|
||||
0x01,0x00,0x41,0x00, // .......#.........#.....#........
|
||||
0x01,0x00,0x02,0x00, // .......#..............#.........
|
||||
0x00,0xE0,0x00,0x00, // ........###.....................
|
||||
0x80,0x08,0x10,0x80, // #...........#......#....#.......
|
||||
0x04,0x00,0x00,0x40, // .....#...................#......
|
||||
0x08,0x00,0x08,0x00, // ....#...............#...........
|
||||
0x10,0x04,0x00,0x00, // ...#.........#..................
|
||||
0x00,0x00,0x00,0x30, // ..........................##....
|
||||
0x00,0x00,0x00,0x20, // ..........................#.....
|
||||
0x00,0x01,0xE8,0x20, // ...............####.#.....#.....
|
||||
0x00,0x00,0x00,0x60, // .........................##.....
|
||||
0x00,0x00,0x02,0x00, // ......................#.........
|
||||
0x00,0x08,0x00,0x00, // ............#...................
|
||||
0x00,0x00,0x01,0x20, // .......................#..#.....
|
||||
0x02,0xE8,0x10,0x60, // ......#.###.#......#.....##.....
|
||||
0x00,0x00,0x00,0x40, // .........................#......
|
||||
0x00,0x03,0xC0,0x60, // ..............####.......##.....
|
||||
0x64,0x00,0x10,0x00, // .##..#.............#............
|
||||
0x04,0x03,0xC0,0x00, // .....#........####..............
|
||||
0x02,0x00,0x20,0x00, // ......#...........#.............
|
||||
0x00,0x28,0x00,0x00, // ..........#.#...................
|
||||
0x00,0x08,0x20,0x00, // ............#.....#.............
|
||||
0x00,0x00,0x40,0x00, // .................#..............
|
||||
0x00,0x00,0x00,0x00 // ................................
|
||||
};
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "HAL.h"
|
||||
|
||||
#ifdef USBCON
|
||||
DefaultSerial MSerial(false, Serial);
|
||||
DefaultSerial1 MSerial0(false, Serial);
|
||||
#ifdef BLUETOOTH
|
||||
BTSerial btSerial(false, bluetoothSerial);
|
||||
#endif
|
||||
|
||||
@@ -83,25 +83,25 @@ typedef int8_t pin_t;
|
||||
// Serial ports
|
||||
#ifdef USBCON
|
||||
#include "../../core/serial_hook.h"
|
||||
typedef ForwardSerial0Type< decltype(Serial) > DefaultSerial;
|
||||
extern DefaultSerial MSerial;
|
||||
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
|
||||
extern DefaultSerial1 MSerial0;
|
||||
#ifdef BLUETOOTH
|
||||
typedef ForwardSerial0Type< decltype(bluetoothSerial) > BTSerial;
|
||||
typedef ForwardSerial1Class< decltype(bluetoothSerial) > BTSerial;
|
||||
extern BTSerial btSerial;
|
||||
#endif
|
||||
|
||||
#define MYSERIAL0 TERN(BLUETOOTH, btSerial, MSerial)
|
||||
#define MYSERIAL1 TERN(BLUETOOTH, btSerial, MSerial0)
|
||||
#else
|
||||
#if !WITHIN(SERIAL_PORT, -1, 3)
|
||||
#error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
|
||||
#endif
|
||||
#define MYSERIAL0 customizedSerial1
|
||||
#define MYSERIAL1 customizedSerial1
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if !WITHIN(SERIAL_PORT_2, -1, 3)
|
||||
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
|
||||
#endif
|
||||
#define MYSERIAL1 customizedSerial2
|
||||
#define MYSERIAL2 customizedSerial2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -238,11 +238,11 @@
|
||||
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
|
||||
};
|
||||
|
||||
typedef Serial0Type< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
|
||||
extern MSerialT customizedSerial1;
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
typedef Serial0Type< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
|
||||
extern MSerialT2 customizedSerial2;
|
||||
#endif
|
||||
|
||||
@@ -252,17 +252,17 @@
|
||||
template <uint8_t serial>
|
||||
struct MMU2SerialCfg {
|
||||
static constexpr int PORT = serial;
|
||||
static constexpr unsigned int RX_SIZE = 32;
|
||||
static constexpr unsigned int TX_SIZE = 32;
|
||||
static constexpr bool XONOFF = false;
|
||||
static constexpr bool EMERGENCYPARSER = false;
|
||||
static constexpr bool DROPPED_RX = false;
|
||||
static constexpr bool RX_FRAMING_ERRORS = false;
|
||||
static constexpr bool MAX_RX_QUEUED = false;
|
||||
static constexpr unsigned int RX_SIZE = 32;
|
||||
static constexpr unsigned int TX_SIZE = 32;
|
||||
static constexpr bool RX_OVERRUNS = false;
|
||||
};
|
||||
|
||||
typedef Serial0Type< MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> > > MSerialT3;
|
||||
typedef Serial1Class< MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> > > MSerialT3;
|
||||
extern MSerialT3 mmuSerial;
|
||||
#endif
|
||||
|
||||
@@ -270,34 +270,23 @@
|
||||
|
||||
template <uint8_t serial>
|
||||
struct LCDSerialCfg {
|
||||
static constexpr int PORT = serial;
|
||||
static constexpr bool XONOFF = false;
|
||||
static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
|
||||
static constexpr bool DROPPED_RX = false;
|
||||
static constexpr bool RX_FRAMING_ERRORS = false;
|
||||
static constexpr bool MAX_RX_QUEUED = false;
|
||||
#if HAS_DGUS_LCD
|
||||
static constexpr unsigned int RX_SIZE = DGUS_RX_BUFFER_SIZE;
|
||||
static constexpr unsigned int TX_SIZE = DGUS_TX_BUFFER_SIZE;
|
||||
static constexpr bool RX_OVERRUNS = ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS);
|
||||
#elif EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
|
||||
static constexpr unsigned int RX_SIZE = 64;
|
||||
static constexpr unsigned int TX_SIZE = 128;
|
||||
static constexpr bool RX_OVERRUNS = false;
|
||||
#else
|
||||
static constexpr unsigned int RX_SIZE = 64;
|
||||
static constexpr unsigned int TX_SIZE = 128;
|
||||
static constexpr bool RX_OVERRUNS = false
|
||||
#endif
|
||||
static constexpr int PORT = serial;
|
||||
static constexpr unsigned int RX_SIZE = TERN(HAS_DGUS_LCD, DGUS_RX_BUFFER_SIZE, 64);
|
||||
static constexpr unsigned int TX_SIZE = TERN(HAS_DGUS_LCD, DGUS_TX_BUFFER_SIZE, 128);
|
||||
static constexpr bool XONOFF = false;
|
||||
static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
|
||||
static constexpr bool DROPPED_RX = false;
|
||||
static constexpr bool RX_FRAMING_ERRORS = false;
|
||||
static constexpr bool MAX_RX_QUEUED = false;
|
||||
static constexpr bool RX_OVERRUNS = BOTH(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS);
|
||||
};
|
||||
|
||||
|
||||
typedef Serial0Type< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialT4;
|
||||
typedef Serial1Class< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialT4;
|
||||
extern MSerialT4 lcdSerial;
|
||||
#endif
|
||||
|
||||
// Use the UART for Bluetooth in AT90USB configurations
|
||||
#if defined(USBCON) && ENABLED(BLUETOOTH)
|
||||
typedef Serial0Type<HardwareSerial> MSerialT5;
|
||||
typedef Serial1Class<HardwareSerial> MSerialT5;
|
||||
extern MSerialT5 bluetoothSerial;
|
||||
#endif
|
||||
|
||||
@@ -285,7 +285,7 @@ enum ClockSource2 : char {
|
||||
*/
|
||||
|
||||
// Determine which harware PWMs are already in use
|
||||
#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN)
|
||||
#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN || P == COOLER_AUTO_FAN_PIN)
|
||||
#if PIN_EXISTS(CONTROLLER_FAN)
|
||||
#define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN)
|
||||
#else
|
||||
|
||||
@@ -56,3 +56,10 @@
|
||||
#if BOTH(HAS_TMC_SW_SERIAL, MONITOR_DRIVER_STATUS)
|
||||
#error "MONITOR_DRIVER_STATUS causes performance issues when used with SoftwareSerial-connected drivers. Disable MONITOR_DRIVER_STATUS or use hardware serial to continue."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Postmortem debugging
|
||||
*/
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not supported on AVR boards."
|
||||
#endif
|
||||
|
||||
@@ -1,342 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../core/macros.h"
|
||||
#include "../../core/serial.h"
|
||||
|
||||
#include "../shared/backtrace/unwinder.h"
|
||||
#include "../shared/backtrace/unwmemaccess.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
// Debug monitor that dumps to the Programming port all status when
|
||||
// an exception or WDT timeout happens - And then resets the board
|
||||
|
||||
// All the Monitor routines must run with interrupts disabled and
|
||||
// under an ISR execution context. That is why we cannot reuse the
|
||||
// Serial interrupt routines or any C runtime, as we don't know the
|
||||
// state we are when running them
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() __asm__ volatile("": : :"memory");
|
||||
|
||||
// (re)initialize UART0 as a monitor output to 250000,n,8,1
|
||||
static void TXBegin() {
|
||||
|
||||
// Disable UART interrupt in NVIC
|
||||
NVIC_DisableIRQ( UART_IRQn );
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
// Disable clock
|
||||
pmc_disable_periph_clk( ID_UART );
|
||||
|
||||
// Configure PMC
|
||||
pmc_enable_periph_clk( ID_UART );
|
||||
|
||||
// Disable PDC channel
|
||||
UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
|
||||
|
||||
// Reset and disable receiver and transmitter
|
||||
UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
|
||||
|
||||
// Configure mode: 8bit, No parity, 1 bit stop
|
||||
UART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
|
||||
|
||||
// Configure baudrate (asynchronous, no oversampling) to BAUDRATE bauds
|
||||
UART->UART_BRGR = (SystemCoreClock / (BAUDRATE << 4));
|
||||
|
||||
// Enable receiver and transmitter
|
||||
UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
|
||||
}
|
||||
|
||||
// Send character through UART with no interrupts
|
||||
static void TX(char c) {
|
||||
while (!(UART->UART_SR & UART_SR_TXRDY)) { WDT_Restart(WDT); sw_barrier(); };
|
||||
UART->UART_THR = c;
|
||||
}
|
||||
|
||||
// Send String through UART
|
||||
static void TX(const char* s) {
|
||||
while (*s) TX(*s++);
|
||||
}
|
||||
|
||||
static void TXDigit(uint32_t d) {
|
||||
if (d < 10) TX((char)(d+'0'));
|
||||
else if (d < 16) TX((char)(d+'A'-10));
|
||||
else TX('?');
|
||||
}
|
||||
|
||||
// Send Hex number thru UART
|
||||
static void TXHex(uint32_t v) {
|
||||
TX("0x");
|
||||
for (uint8_t i = 0; i < 8; i++, v <<= 4)
|
||||
TXDigit((v >> 28) & 0xF);
|
||||
}
|
||||
|
||||
// Send Decimal number thru UART
|
||||
static void TXDec(uint32_t v) {
|
||||
if (!v) {
|
||||
TX('0');
|
||||
return;
|
||||
}
|
||||
|
||||
char nbrs[14];
|
||||
char *p = &nbrs[0];
|
||||
while (v != 0) {
|
||||
*p++ = '0' + (v % 10);
|
||||
v /= 10;
|
||||
}
|
||||
do {
|
||||
p--;
|
||||
TX(*p);
|
||||
} while (p != &nbrs[0]);
|
||||
}
|
||||
|
||||
// Dump a backtrace entry
|
||||
static bool UnwReportOut(void* ctx, const UnwReport* bte) {
|
||||
int* p = (int*)ctx;
|
||||
|
||||
(*p)++;
|
||||
TX('#'); TXDec(*p); TX(" : ");
|
||||
TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
|
||||
TX('+'); TXDec(bte->address - bte->function);
|
||||
TX(" PC:");TXHex(bte->address); TX('\n');
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef UNW_DEBUG
|
||||
void UnwPrintf(const char* format, ...) {
|
||||
char dest[256];
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vsprintf(dest, format, argptr);
|
||||
va_end(argptr);
|
||||
TX(&dest[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Table of function pointers for passing to the unwinder */
|
||||
static const UnwindCallbacks UnwCallbacks = {
|
||||
UnwReportOut,
|
||||
UnwReadW,
|
||||
UnwReadH,
|
||||
UnwReadB
|
||||
#ifdef UNW_DEBUG
|
||||
, UnwPrintf
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* HardFaultHandler_C:
|
||||
* This is called from the HardFault_HandlerAsm with a pointer the Fault stack
|
||||
* as the parameter. We can then read the values from the stack and place them
|
||||
* into local variables for ease of reading.
|
||||
* We then read the various Fault Status and Address Registers to help decode
|
||||
* cause of the fault.
|
||||
* The function ends with a BKPT instruction to force control back into the debugger
|
||||
*/
|
||||
extern "C"
|
||||
void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
|
||||
|
||||
static const char* causestr[] = {
|
||||
"NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
|
||||
};
|
||||
|
||||
UnwindFrame btf;
|
||||
|
||||
// Dump report to the Programming port (interrupts are DISABLED)
|
||||
TXBegin();
|
||||
TX("\n\n## Software Fault detected ##\n");
|
||||
TX("Cause: "); TX(causestr[cause]); TX('\n');
|
||||
|
||||
TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
|
||||
TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
|
||||
TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
|
||||
TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
|
||||
TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
|
||||
TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
|
||||
TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
|
||||
TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
|
||||
|
||||
// Configurable Fault Status Register
|
||||
// Consists of MMSR, BFSR and UFSR
|
||||
TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
|
||||
|
||||
// Hard Fault Status Register
|
||||
TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
|
||||
|
||||
// Debug Fault Status Register
|
||||
TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
|
||||
|
||||
// Auxiliary Fault Status Register
|
||||
TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
|
||||
|
||||
// Read the Fault Address Registers. These may not contain valid values.
|
||||
// Check BFARVALID/MMARVALID to see if they are valid values
|
||||
// MemManage Fault Address Register
|
||||
TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
|
||||
|
||||
// Bus Fault Address Register
|
||||
TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
|
||||
|
||||
TX("ExcLR: "); TXHex(lr); TX('\n');
|
||||
TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
|
||||
|
||||
btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
|
||||
btf.fp = btf.sp;
|
||||
btf.lr = ((unsigned long)sp[5]);
|
||||
btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
|
||||
|
||||
// Perform a backtrace
|
||||
TX("\nBacktrace:\n\n");
|
||||
int ctr = 0;
|
||||
UnwindStart(&btf, &UnwCallbacks, &ctr);
|
||||
|
||||
// Disable all NVIC interrupts
|
||||
NVIC->ICER[0] = 0xFFFFFFFF;
|
||||
NVIC->ICER[1] = 0xFFFFFFFF;
|
||||
|
||||
// Relocate VTOR table to default position
|
||||
SCB->VTOR = 0;
|
||||
|
||||
// Disable USB
|
||||
otg_disable();
|
||||
|
||||
// Restart watchdog
|
||||
WDT_Restart(WDT);
|
||||
|
||||
// Reset controller
|
||||
NVIC_SystemReset();
|
||||
for (;;) WDT_Restart(WDT);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void NMI_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#0")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void HardFault_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#1")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void MemManage_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#2")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void BusFault_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#3")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void UsageFault_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#4")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void DebugMon_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#5")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
|
||||
__attribute__((naked)) void WDT_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#6")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void RSTC_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#7")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
||||
@@ -40,6 +40,8 @@ uint16_t HAL_adc_result;
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
|
||||
|
||||
// HAL initialization task
|
||||
void HAL_init() {
|
||||
// Initialize the USB stack
|
||||
@@ -47,6 +49,7 @@ void HAL_init() {
|
||||
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
|
||||
#endif
|
||||
usb_task_init();
|
||||
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
|
||||
}
|
||||
|
||||
// HAL idle task
|
||||
@@ -104,16 +107,16 @@ uint16_t HAL_adc_get_result() {
|
||||
|
||||
// Forward the default serial ports
|
||||
#if ANY_SERIAL_IS(0)
|
||||
DefaultSerial MSerial(false, Serial);
|
||||
DefaultSerial1 MSerial0(false, Serial);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(1)
|
||||
DefaultSerial1 MSerial1(false, Serial1);
|
||||
DefaultSerial2 MSerial1(false, Serial1);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(2)
|
||||
DefaultSerial2 MSerial2(false, Serial2);
|
||||
DefaultSerial3 MSerial2(false, Serial2);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(3)
|
||||
DefaultSerial3 MSerial3(false, Serial3);
|
||||
DefaultSerial4 MSerial3(false, Serial3);
|
||||
#endif
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
||||
|
||||
+13
-14
@@ -38,33 +38,32 @@
|
||||
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
typedef ForwardSerial0Type< decltype(Serial) > DefaultSerial;
|
||||
typedef ForwardSerial0Type< decltype(Serial1) > DefaultSerial1;
|
||||
typedef ForwardSerial0Type< decltype(Serial2) > DefaultSerial2;
|
||||
typedef ForwardSerial0Type< decltype(Serial3) > DefaultSerial3;
|
||||
extern DefaultSerial MSerial;
|
||||
extern DefaultSerial1 MSerial1;
|
||||
extern DefaultSerial2 MSerial2;
|
||||
extern DefaultSerial3 MSerial3;
|
||||
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
|
||||
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
|
||||
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
|
||||
typedef ForwardSerial1Class< decltype(Serial3) > DefaultSerial4;
|
||||
extern DefaultSerial1 MSerial0;
|
||||
extern DefaultSerial2 MSerial1;
|
||||
extern DefaultSerial3 MSerial2;
|
||||
extern DefaultSerial4 MSerial3;
|
||||
|
||||
#define _MSERIAL(X) MSerial##X
|
||||
#define MSERIAL(X) _MSERIAL(X)
|
||||
#define MSerial0 MSerial
|
||||
|
||||
// Define MYSERIAL0/1 before MarlinSerial includes!
|
||||
// Define MYSERIAL1/2 before MarlinSerial includes!
|
||||
#if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER)
|
||||
#define MYSERIAL0 customizedSerial1
|
||||
#define MYSERIAL1 customizedSerial1
|
||||
#elif WITHIN(SERIAL_PORT, 0, 3)
|
||||
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#else
|
||||
#error "The required SERIAL_PORT must be from -1 to 3. Please update your configuration."
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if SERIAL_PORT_2 == -1 || ENABLED(EMERGENCY_PARSER)
|
||||
#define MYSERIAL1 customizedSerial2
|
||||
#define MYSERIAL2 customizedSerial2
|
||||
#elif WITHIN(SERIAL_PORT_2, 0, 3)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
|
||||
#else
|
||||
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
|
||||
#include "../shared/HAL_MinSerial.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static void TXBegin() {
|
||||
// Disable UART interrupt in NVIC
|
||||
NVIC_DisableIRQ( UART_IRQn );
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
// Disable clock
|
||||
pmc_disable_periph_clk( ID_UART );
|
||||
|
||||
// Configure PMC
|
||||
pmc_enable_periph_clk( ID_UART );
|
||||
|
||||
// Disable PDC channel
|
||||
UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
|
||||
|
||||
// Reset and disable receiver and transmitter
|
||||
UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
|
||||
|
||||
// Configure mode: 8bit, No parity, 1 bit stop
|
||||
UART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
|
||||
|
||||
// Configure baudrate (asynchronous, no oversampling) to BAUDRATE bauds
|
||||
UART->UART_BRGR = (SystemCoreClock / (BAUDRATE << 4));
|
||||
|
||||
// Enable receiver and transmitter
|
||||
UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
|
||||
}
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() __asm__ volatile("": : :"memory");
|
||||
static void TX(char c) {
|
||||
while (!(UART->UART_SR & UART_SR_TXRDY)) { WDT_Restart(WDT); sw_barrier(); };
|
||||
UART->UART_THR = c;
|
||||
}
|
||||
|
||||
void install_min_serial() {
|
||||
HAL_min_serial_init = &TXBegin;
|
||||
HAL_min_serial_out = &TX;
|
||||
}
|
||||
|
||||
#if DISABLED(DYNAMIC_VECTORTABLE)
|
||||
extern "C" {
|
||||
__attribute__((naked)) void JumpHandler_ASM() {
|
||||
__asm__ __volatile__ (
|
||||
"b CommonHandler_ASM\n"
|
||||
);
|
||||
}
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) HardFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) BusFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) UsageFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) MemManage_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) NMI_Handler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // POSTMORTEM_DEBUGGING
|
||||
#endif // ARDUINO_ARCH_SAM
|
||||
@@ -141,11 +141,11 @@ struct MarlinSerialCfg {
|
||||
};
|
||||
|
||||
#if SERIAL_PORT >= 0
|
||||
typedef Serial0Type< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
|
||||
extern MSerialT customizedSerial1;
|
||||
#endif
|
||||
|
||||
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
|
||||
typedef Serial0Type< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
|
||||
extern MSerialT2 customizedSerial2;
|
||||
#endif
|
||||
|
||||
@@ -92,12 +92,11 @@ int MarlinSerialUSB::read() {
|
||||
return c;
|
||||
}
|
||||
|
||||
bool MarlinSerialUSB::available() {
|
||||
/* If Pending chars */
|
||||
return pending_char >= 0 ||
|
||||
/* or USB CDC enumerated and configured on the PC side and some
|
||||
bytes where sent to us */
|
||||
(usb_task_cdc_isenabled() && udi_cdc_is_rx_ready());
|
||||
int MarlinSerialUSB::available() {
|
||||
if (pending_char > 0) return pending_char;
|
||||
return pending_char == 0 ||
|
||||
// or USB CDC enumerated and configured on the PC side and some bytes where sent to us */
|
||||
(usb_task_cdc_isenabled() && udi_cdc_is_rx_ready());
|
||||
}
|
||||
|
||||
void MarlinSerialUSB::flush() { }
|
||||
|
||||
@@ -39,7 +39,7 @@ struct MarlinSerialUSB {
|
||||
int peek();
|
||||
int read();
|
||||
void flush();
|
||||
bool available();
|
||||
int available();
|
||||
size_t write(const uint8_t c);
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
@@ -50,7 +50,7 @@ struct MarlinSerialUSB {
|
||||
FORCE_INLINE int rxMaxEnqueued() { return 0; }
|
||||
#endif
|
||||
};
|
||||
typedef Serial0Type<MarlinSerialUSB> MSerialT;
|
||||
typedef Serial1Class<MarlinSerialUSB> MSerialT;
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
extern MSerialT customizedSerial1;
|
||||
|
||||
@@ -57,5 +57,5 @@
|
||||
#endif
|
||||
|
||||
#if HAS_TMC_SW_SERIAL
|
||||
#error "TMC220x Software Serial is not supported on this platform."
|
||||
#error "TMC220x Software Serial is not supported on the DUE platform."
|
||||
#endif
|
||||
|
||||
@@ -20,11 +20,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "FlushableHardwareSerial.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
#include "FlushableHardwareSerial.h"
|
||||
|
||||
Serial0Type<FlushableHardwareSerial> flushableSerial(false, 0);
|
||||
Serial1Class<FlushableHardwareSerial> flushableSerial(false, 0);
|
||||
|
||||
#endif // ARDUINO_ARCH_ESP32
|
||||
#endif
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
class FlushableHardwareSerial : public HardwareSerial {
|
||||
@@ -31,6 +31,4 @@ public:
|
||||
FlushableHardwareSerial(int uart_nr) : HardwareSerial(uart_nr) {}
|
||||
};
|
||||
|
||||
extern Serial0Type<FlushableHardwareSerial> flushableSerial;
|
||||
|
||||
#endif // ARDUINO_ARCH_ESP32
|
||||
extern Serial1Class<FlushableHardwareSerial> flushableSerial;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#endif
|
||||
|
||||
#if ENABLED(ESP3D_WIFISUPPORT)
|
||||
DefaultSerial MSerial(false, Serial2Socket);
|
||||
DefaultSerial1 MSerial0(false, Serial2Socket);
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
@@ -185,6 +185,7 @@ void HAL_adc_init() {
|
||||
TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
|
||||
TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
|
||||
TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
|
||||
TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
|
||||
TERN_(FILAMENT_WIDTH_SENSOR, adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db));
|
||||
|
||||
// Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail.
|
||||
|
||||
@@ -51,15 +51,15 @@
|
||||
|
||||
extern portMUX_TYPE spinlock;
|
||||
|
||||
#define MYSERIAL0 flushableSerial
|
||||
#define MYSERIAL1 flushableSerial
|
||||
|
||||
#if EITHER(WIFISUPPORT, ESP3D_WIFISUPPORT)
|
||||
#if ENABLED(ESP3D_WIFISUPPORT)
|
||||
typedef ForwardSerial0Type< decltype(Serial2Socket) > DefaultSerial;
|
||||
extern DefaultSerial MSerial;
|
||||
#define MYSERIAL1 MSerial
|
||||
typedef ForwardSerial1Class< decltype(Serial2Socket) > DefaultSerial1;
|
||||
extern DefaultSerial1 MSerial0;
|
||||
#define MYSERIAL2 MSerial0
|
||||
#else
|
||||
#define MYSERIAL1 webSocketSerial
|
||||
#define MYSERIAL2 webSocketSerial
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -81,5 +81,5 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef Serial0Type<WebSocketSerial> MSerialT;
|
||||
typedef Serial1Class<WebSocketSerial> MSerialT;
|
||||
extern MSerialT webSocketSerial;
|
||||
|
||||
@@ -30,9 +30,13 @@
|
||||
#endif
|
||||
|
||||
#if HAS_TMC_SW_SERIAL
|
||||
#error "TMC220x Software Serial is not supported on this platform."
|
||||
#error "TMC220x Software Serial is not supported on ESP32."
|
||||
#endif
|
||||
|
||||
#if BOTH(WIFISUPPORT, ESP3D_WIFISUPPORT)
|
||||
#error "Only enable one WiFi option, either WIFISUPPORT or ESP3D_WIFISUPPORT."
|
||||
#endif
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not yet supported on ESP32."
|
||||
#endif
|
||||
|
||||
@@ -29,12 +29,6 @@
|
||||
|
||||
#include HAL_PATH(.,HAL.h)
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#define NUM_SERIAL 2
|
||||
#else
|
||||
#define NUM_SERIAL 1
|
||||
#endif
|
||||
|
||||
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
|
||||
|
||||
#ifndef I2C_ADDRESS
|
||||
|
||||
@@ -61,7 +61,7 @@ uint8_t _getc();
|
||||
#define SHARED_SERVOS HAS_SERVOS
|
||||
|
||||
extern MSerialT usb_serial;
|
||||
#define MYSERIAL0 usb_serial
|
||||
#define MYSERIAL1 usb_serial
|
||||
|
||||
#define ST7920_DELAY_1 DELAY_NS(600)
|
||||
#define ST7920_DELAY_2 DELAY_NS(750)
|
||||
|
||||
@@ -35,5 +35,9 @@
|
||||
#endif
|
||||
|
||||
#if HAS_TMC_SW_SERIAL
|
||||
#error "TMC220x Software Serial is not supported on this platform."
|
||||
#error "TMC220x Software Serial is not supported on LINUX."
|
||||
#endif
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not yet supported on LINUX."
|
||||
#endif
|
||||
|
||||
@@ -115,4 +115,4 @@ struct HalSerial {
|
||||
volatile bool host_connected;
|
||||
};
|
||||
|
||||
typedef Serial0Type<HalSerial> MSerialT;
|
||||
typedef Serial1Class<HalSerial> MSerialT;
|
||||
|
||||
@@ -105,8 +105,8 @@ int main() {
|
||||
std::thread write_serial (write_serial_thread);
|
||||
std::thread read_serial (read_serial_thread);
|
||||
|
||||
#ifdef MYSERIAL0
|
||||
MYSERIAL0.begin(BAUDRATE);
|
||||
#ifdef MYSERIAL1
|
||||
MYSERIAL1.begin(BAUDRATE);
|
||||
SERIAL_ECHOLNPGM("x86_64 Initialized");
|
||||
SERIAL_FLUSHTX();
|
||||
#endif
|
||||
|
||||
@@ -1,322 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../core/macros.h"
|
||||
#include "../../core/serial.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "../shared/backtrace/unwinder.h"
|
||||
#include "../shared/backtrace/unwmemaccess.h"
|
||||
#include "watchdog.h"
|
||||
#include <debug_frmwrk.h>
|
||||
|
||||
|
||||
// Debug monitor that dumps to the Programming port all status when
|
||||
// an exception or WDT timeout happens - And then resets the board
|
||||
|
||||
// All the Monitor routines must run with interrupts disabled and
|
||||
// under an ISR execution context. That is why we cannot reuse the
|
||||
// Serial interrupt routines or any C runtime, as we don't know the
|
||||
// state we are when running them
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() __asm__ volatile("": : :"memory");
|
||||
|
||||
// (re)initialize UART0 as a monitor output to 250000,n,8,1
|
||||
static void TXBegin() {
|
||||
}
|
||||
|
||||
// Send character through UART with no interrupts
|
||||
static void TX(char c) {
|
||||
_DBC(c);
|
||||
}
|
||||
|
||||
// Send String through UART
|
||||
static void TX(const char* s) {
|
||||
while (*s) TX(*s++);
|
||||
}
|
||||
|
||||
static void TXDigit(uint32_t d) {
|
||||
if (d < 10) TX((char)(d+'0'));
|
||||
else if (d < 16) TX((char)(d+'A'-10));
|
||||
else TX('?');
|
||||
}
|
||||
|
||||
// Send Hex number thru UART
|
||||
static void TXHex(uint32_t v) {
|
||||
TX("0x");
|
||||
for (uint8_t i = 0; i < 8; i++, v <<= 4)
|
||||
TXDigit((v >> 28) & 0xF);
|
||||
}
|
||||
|
||||
// Send Decimal number thru UART
|
||||
static void TXDec(uint32_t v) {
|
||||
if (!v) {
|
||||
TX('0');
|
||||
return;
|
||||
}
|
||||
|
||||
char nbrs[14];
|
||||
char *p = &nbrs[0];
|
||||
while (v != 0) {
|
||||
*p++ = '0' + (v % 10);
|
||||
v /= 10;
|
||||
}
|
||||
do {
|
||||
p--;
|
||||
TX(*p);
|
||||
} while (p != &nbrs[0]);
|
||||
}
|
||||
|
||||
// Dump a backtrace entry
|
||||
static bool UnwReportOut(void* ctx, const UnwReport* bte) {
|
||||
int* p = (int*)ctx;
|
||||
|
||||
(*p)++;
|
||||
TX('#'); TXDec(*p); TX(" : ");
|
||||
TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
|
||||
TX('+'); TXDec(bte->address - bte->function);
|
||||
TX(" PC:");TXHex(bte->address); TX('\n');
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef UNW_DEBUG
|
||||
void UnwPrintf(const char* format, ...) {
|
||||
char dest[256];
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vsprintf(dest, format, argptr);
|
||||
va_end(argptr);
|
||||
TX(&dest[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Table of function pointers for passing to the unwinder */
|
||||
static const UnwindCallbacks UnwCallbacks = {
|
||||
UnwReportOut,
|
||||
UnwReadW,
|
||||
UnwReadH,
|
||||
UnwReadB
|
||||
#ifdef UNW_DEBUG
|
||||
,UnwPrintf
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HardFaultHandler_C:
|
||||
* This is called from the HardFault_HandlerAsm with a pointer the Fault stack
|
||||
* as the parameter. We can then read the values from the stack and place them
|
||||
* into local variables for ease of reading.
|
||||
* We then read the various Fault Status and Address Registers to help decode
|
||||
* cause of the fault.
|
||||
* The function ends with a BKPT instruction to force control back into the debugger
|
||||
*/
|
||||
extern "C"
|
||||
void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
|
||||
|
||||
static const char* causestr[] = {
|
||||
"NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
|
||||
};
|
||||
|
||||
UnwindFrame btf;
|
||||
|
||||
// Dump report to the Programming port (interrupts are DISABLED)
|
||||
TXBegin();
|
||||
TX("\n\n## Software Fault detected ##\n");
|
||||
TX("Cause: "); TX(causestr[cause]); TX('\n');
|
||||
|
||||
TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
|
||||
TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
|
||||
TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
|
||||
TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
|
||||
TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
|
||||
TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
|
||||
TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
|
||||
TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
|
||||
|
||||
// Configurable Fault Status Register
|
||||
// Consists of MMSR, BFSR and UFSR
|
||||
TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
|
||||
|
||||
// Hard Fault Status Register
|
||||
TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
|
||||
|
||||
// Debug Fault Status Register
|
||||
TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
|
||||
|
||||
// Auxiliary Fault Status Register
|
||||
TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
|
||||
|
||||
// Read the Fault Address Registers. These may not contain valid values.
|
||||
// Check BFARVALID/MMARVALID to see if they are valid values
|
||||
// MemManage Fault Address Register
|
||||
TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
|
||||
|
||||
// Bus Fault Address Register
|
||||
TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
|
||||
|
||||
TX("ExcLR: "); TXHex(lr); TX('\n');
|
||||
TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
|
||||
|
||||
btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
|
||||
btf.fp = btf.sp;
|
||||
btf.lr = ((unsigned long)sp[5]);
|
||||
btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
|
||||
|
||||
// Perform a backtrace
|
||||
TX("\nBacktrace:\n\n");
|
||||
int ctr = 0;
|
||||
UnwindStart(&btf, &UnwCallbacks, &ctr);
|
||||
|
||||
// Disable all NVIC interrupts
|
||||
NVIC->ICER[0] = 0xFFFFFFFF;
|
||||
NVIC->ICER[1] = 0xFFFFFFFF;
|
||||
|
||||
// Relocate VTOR table to default position
|
||||
SCB->VTOR = 0;
|
||||
|
||||
// Clear cause of reset to prevent entering smoothie bootstrap
|
||||
HAL_clear_reset_source();
|
||||
|
||||
// Restart watchdog
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
//WDT_Restart(WDT);
|
||||
watchdog_init();
|
||||
#endif
|
||||
|
||||
// Reset controller
|
||||
NVIC_SystemReset();
|
||||
|
||||
// Nothing below here is compiled because NVIC_SystemReset loops forever
|
||||
|
||||
for (;;) { TERN_(USE_WATCHDOG, watchdog_init()); }
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
__attribute__((naked)) void NMI_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#0")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void HardFault_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#1")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void MemManage_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#2")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void BusFault_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#3")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void UsageFault_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#4")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void DebugMon_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#5")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
|
||||
__attribute__((naked)) void WDT_IRQHandler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#6")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void RSTC_Handler() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified" "\n\t"
|
||||
A("tst lr, #4")
|
||||
A("ite eq")
|
||||
A("mrseq r0, msp")
|
||||
A("mrsne r0, psp")
|
||||
A("mov r1,lr")
|
||||
A("mov r2,#7")
|
||||
A("b HardFault_HandlerC")
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "watchdog.h"
|
||||
#endif
|
||||
|
||||
DefaultSerial USBSerial(false, UsbSerial);
|
||||
DefaultSerial1 USBSerial(false, UsbSerial);
|
||||
|
||||
uint32_t HAL_adc_reading = 0;
|
||||
|
||||
|
||||
@@ -60,26 +60,25 @@ extern "C" volatile uint32_t _millis;
|
||||
#define ST7920_DELAY_3 DELAY_NS(750)
|
||||
#endif
|
||||
|
||||
typedef ForwardSerial0Type< decltype(UsbSerial) > DefaultSerial;
|
||||
extern DefaultSerial USBSerial;
|
||||
typedef ForwardSerial1Class< decltype(UsbSerial) > DefaultSerial1;
|
||||
extern DefaultSerial1 USBSerial;
|
||||
|
||||
#define _MSERIAL(X) MSerial##X
|
||||
#define MSERIAL(X) _MSERIAL(X)
|
||||
#define MSerial0 MSerial
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
#define MYSERIAL0 USBSerial
|
||||
#define MYSERIAL1 USBSerial
|
||||
#elif WITHIN(SERIAL_PORT, 0, 3)
|
||||
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#else
|
||||
#error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if SERIAL_PORT_2 == -1
|
||||
#define MYSERIAL1 USBSerial
|
||||
#define MYSERIAL2 USBSerial
|
||||
#elif WITHIN(SERIAL_PORT_2, 0, 3)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
|
||||
#else
|
||||
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "HAL.h"
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
|
||||
#include "../shared/HAL_MinSerial.h"
|
||||
#include <debug_frmwrk.h>
|
||||
|
||||
static void TX(char c) { _DBC(c); }
|
||||
void install_min_serial() { HAL_min_serial_out = &TX; }
|
||||
|
||||
#if DISABLED(DYNAMIC_VECTORTABLE)
|
||||
extern "C" {
|
||||
__attribute__((naked)) void JumpHandler_ASM() {
|
||||
__asm__ __volatile__ (
|
||||
"b CommonHandler_ASM\n"
|
||||
);
|
||||
}
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) HardFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) BusFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) UsageFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) MemManage_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) NMI_Handler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // POSTMORTEM_DEBUGGING
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -25,20 +25,46 @@
|
||||
#include "MarlinSerial.h"
|
||||
|
||||
#if ANY_SERIAL_IS(0)
|
||||
MSerialT MSerial(true, LPC_UART0);
|
||||
extern "C" void UART0_IRQHandler() { MSerial.IRQHandler(); }
|
||||
MarlinSerial _MSerial(LPC_UART0);
|
||||
MSerialT MSerial0(true, _MSerial);
|
||||
extern "C" void UART0_IRQHandler() { _MSerial.IRQHandler(); }
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(1)
|
||||
MSerialT MSerial1(true, (LPC_UART_TypeDef *) LPC_UART1);
|
||||
extern "C" void UART1_IRQHandler() { MSerial1.IRQHandler(); }
|
||||
MarlinSerial _MSerial1((LPC_UART_TypeDef *) LPC_UART1);
|
||||
MSerialT MSerial1(true, _MSerial1);
|
||||
extern "C" void UART1_IRQHandler() { _MSerial1.IRQHandler(); }
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(2)
|
||||
MSerialT MSerial2(true, LPC_UART2);
|
||||
extern "C" void UART2_IRQHandler() { MSerial2.IRQHandler(); }
|
||||
MarlinSerial _MSerial2(LPC_UART2);
|
||||
MSerialT MSerial2(true, _MSerial2);
|
||||
extern "C" void UART2_IRQHandler() { _MSerial2.IRQHandler(); }
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(3)
|
||||
MSerialT MSerial3(true, LPC_UART3);
|
||||
extern "C" void UART3_IRQHandler() { MSerial3.IRQHandler(); }
|
||||
MarlinSerial _MSerial3(LPC_UART3);
|
||||
MSerialT MSerial3(true, _MSerial3);
|
||||
extern "C" void UART3_IRQHandler() { _MSerial3.IRQHandler(); }
|
||||
#endif
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
|
||||
bool MarlinSerial::recv_callback(const char c) {
|
||||
// Need to figure out which serial port we are and react in consequence (Marlin does not have CONTAINER_OF macro)
|
||||
if (false) {}
|
||||
#if ANY_SERIAL_IS(0)
|
||||
else if (this == &_MSerial) emergency_parser.update(MSerial0.emergency_state, c);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(1)
|
||||
else if (this == &_MSerial1) emergency_parser.update(MSerial1.emergency_state, c);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(2)
|
||||
else if (this == &_MSerial2) emergency_parser.update(MSerial2.emergency_state, c);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(3)
|
||||
else if (this == &_MSerial3) emergency_parser.update(MSerial3.emergency_state, c);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // TARGET_LPC1768
|
||||
|
||||
@@ -47,15 +47,21 @@ public:
|
||||
void end() {}
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
bool recv_callback(const char c) override {
|
||||
emergency_parser.update(static_cast<Serial0Type<MarlinSerial> *>(this)->emergency_state, c);
|
||||
return true; // do not discard character
|
||||
}
|
||||
bool recv_callback(const char c) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef Serial0Type<MarlinSerial> MSerialT;
|
||||
extern MSerialT MSerial;
|
||||
// On LPC176x framework, HardwareSerial does not implement the same interface as Arduino's Serial, so overloads
|
||||
// of 'available' and 'read' method are not used in this multiple inheritance scenario.
|
||||
// Instead, use a ForwardSerial here that adapts the interface.
|
||||
typedef ForwardSerial1Class<MarlinSerial> MSerialT;
|
||||
extern MSerialT MSerial0;
|
||||
extern MSerialT MSerial1;
|
||||
extern MSerialT MSerial2;
|
||||
extern MSerialT MSerial3;
|
||||
|
||||
// Consequently, we can't use a RuntimeSerial either. The workaround would be to use a RuntimeSerial<ForwardSerial<MarlinSerial>> type here
|
||||
// Right now, let's ignore this until it's actually required.
|
||||
#if ENABLED(SERIAL_RUNTIME_HOOK)
|
||||
#error "SERIAL_RUNTIME_HOOK is not yet supported for LPC176x."
|
||||
#endif
|
||||
|
||||
@@ -83,14 +83,13 @@ bool PersistentStore::access_finish() {
|
||||
static void debug_rw(const bool write, int &pos, const uint8_t *value, const size_t size, const FRESULT s, const size_t total=0) {
|
||||
PGM_P const rw_str = write ? PSTR("write") : PSTR("read");
|
||||
SERIAL_CHAR(' ');
|
||||
serialprintPGM(rw_str);
|
||||
SERIAL_ECHOPGM_P(rw_str);
|
||||
SERIAL_ECHOLNPAIR("_data(", pos, ",", value, ",", size, ", ...)");
|
||||
if (total) {
|
||||
SERIAL_ECHOPGM(" f_");
|
||||
serialprintPGM(rw_str);
|
||||
SERIAL_ECHOPGM_P(rw_str);
|
||||
SERIAL_ECHOPAIR("()=", s, "\n size=", size, "\n bytes_");
|
||||
serialprintPGM(write ? PSTR("written=") : PSTR("read="));
|
||||
SERIAL_ECHOLN(total);
|
||||
SERIAL_ECHOLNPAIR_P(write ? PSTR("written=") : PSTR("read="), total);
|
||||
}
|
||||
else
|
||||
SERIAL_ECHOLNPAIR(" f_lseek()=", s);
|
||||
|
||||
@@ -30,6 +30,5 @@
|
||||
// LPC1768 boards seem to lose steps when saving to EEPROM during print (issue #20785)
|
||||
// TODO: Which other boards are incompatible?
|
||||
#if defined(MCU_LPC1768) && PRINTCOUNTER_SAVE_INTERVAL > 0
|
||||
#warning "To prevent step loss, motion will pause for PRINTCOUNTER auto-save."
|
||||
#define PRINTCOUNTER_SYNC 1
|
||||
#endif
|
||||
|
||||
@@ -270,7 +270,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
#error "SERIAL_STATS_MAX_RX_QUEUED is not supported on this platform."
|
||||
#error "SERIAL_STATS_MAX_RX_QUEUED is not supported on LPC176x."
|
||||
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
#error "SERIAL_STATS_DROPPED_RX is not supported on this platform."
|
||||
#error "SERIAL_STATS_DROPPED_RX is not supported on LPX176x."
|
||||
#endif
|
||||
|
||||
@@ -46,6 +46,8 @@ extern "C" {
|
||||
|
||||
void SysTick_Callback() { disk_timerproc(); }
|
||||
|
||||
TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
|
||||
|
||||
void HAL_init() {
|
||||
|
||||
// Init LEDs
|
||||
@@ -123,9 +125,7 @@ void HAL_init() {
|
||||
delay(1000); // Give OS time to notice
|
||||
USB_Connect(true);
|
||||
|
||||
#if HAS_SD_HOST_DRIVE
|
||||
MSC_SD_Init(0); // Enable USB SD card access
|
||||
#endif
|
||||
TERN_(HAS_SD_HOST_DRIVE, MSC_SD_Init(0)); // Enable USB SD card access
|
||||
|
||||
const millis_t usb_timeout = millis() + 2000;
|
||||
while (!USB_Configuration && PENDING(millis(), usb_timeout)) {
|
||||
@@ -137,6 +137,8 @@ void HAL_init() {
|
||||
}
|
||||
|
||||
HAL_timer_init();
|
||||
|
||||
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
|
||||
}
|
||||
|
||||
// HAL idle task
|
||||
|
||||
@@ -8,9 +8,7 @@ from __future__ import print_function
|
||||
target_filename = "FIRMWARE.CUR"
|
||||
target_drive = "REARM"
|
||||
|
||||
import os
|
||||
import getpass
|
||||
import platform
|
||||
import os,getpass,platform
|
||||
|
||||
current_OS = platform.system()
|
||||
Import("env")
|
||||
@@ -33,9 +31,8 @@ try:
|
||||
#
|
||||
# platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:'
|
||||
# Windows - doesn't care about the disk's name, only cares about the drive letter
|
||||
import subprocess
|
||||
import subprocess,string
|
||||
from ctypes import windll
|
||||
import string
|
||||
|
||||
# getting list of drives
|
||||
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
EmergencyParser::State emergency_state;
|
||||
|
||||
bool CDC_RecvCallback(const char buffer) {
|
||||
emergency_parser.update(emergency_state, buffer);
|
||||
bool CDC_RecvCallback(const char c) {
|
||||
emergency_parser.update(emergency_state, c);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,19 +26,19 @@
|
||||
|
||||
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
|
||||
#if ANY_SERIAL_IS(-1)
|
||||
DefaultSerial MSerial(false, Serial);
|
||||
DefaultSerial1 MSerial0(false, Serial);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(0)
|
||||
DefaultSerial1 MSerial1(false, Serial1);
|
||||
DefaultSerial2 MSerial1(false, Serial1);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(1)
|
||||
DefaultSerial2 MSerial2(false, Serial2);
|
||||
DefaultSerial3 MSerial2(false, Serial2);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(2)
|
||||
DefaultSerial3 MSerial3(false, Serial3);
|
||||
DefaultSerial4 MSerial3(false, Serial3);
|
||||
#endif
|
||||
#if ANY_SERIAL_IS(3)
|
||||
DefaultSerial4 MSerial4(false, Serial4);
|
||||
DefaultSerial5 MSerial4(false, Serial4);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#define GET_PROBE_ADC() TERN(HAS_TEMP_PROBE, PIN_TO_ADC(TEMP_PROBE_PIN), -1)
|
||||
#define GET_BED_ADC() TERN(HAS_TEMP_ADC_BED, PIN_TO_ADC(TEMP_BED_PIN), -1)
|
||||
#define GET_CHAMBER_ADC() TERN(HAS_TEMP_ADC_CHAMBER, PIN_TO_ADC(TEMP_CHAMBER_PIN), -1)
|
||||
#define GET_COOLER_ADC() TERN(HAS_TEMP_ADC_COOLER, PIN_TO_ADC(TEMP_COOLER_PIN), -1)
|
||||
#define GET_FILAMENT_WIDTH_ADC() TERN(FILAMENT_WIDTH_SENSOR, PIN_TO_ADC(FILWIDTH_PIN), -1)
|
||||
#define GET_BUTTONS_ADC() TERN(HAS_ADC_BUTTONS, PIN_TO_ADC(ADC_KEYPAD_PIN), -1)
|
||||
|
||||
@@ -66,6 +67,7 @@
|
||||
|| GET_PROBE_ADC() == n \
|
||||
|| GET_BED_ADC() == n \
|
||||
|| GET_CHAMBER_ADC() == n \
|
||||
|| GET_COOLER_ADC() == n \
|
||||
|| GET_FILAMENT_WIDTH_ADC() == n \
|
||||
|| GET_BUTTONS_ADC() == n \
|
||||
)
|
||||
@@ -144,6 +146,9 @@ uint16_t HAL_adc_result;
|
||||
#if GET_CHAMBER_ADC() == 0
|
||||
TEMP_CHAMBER_PIN,
|
||||
#endif
|
||||
#if GET_COOLER_ADC() == 0
|
||||
TEMP_COOLER_PIN,
|
||||
#endif
|
||||
#if GET_FILAMENT_WIDTH_ADC() == 0
|
||||
FILWIDTH_PIN,
|
||||
#endif
|
||||
@@ -184,6 +189,9 @@ uint16_t HAL_adc_result;
|
||||
#if GET_CHAMBER_ADC() == 1
|
||||
TEMP_CHAMBER_PIN,
|
||||
#endif
|
||||
#if GET_COOLER_ADC() == 1
|
||||
TEMP_COOLER_PIN,
|
||||
#endif
|
||||
#if GET_FILAMENT_WIDTH_ADC() == 1
|
||||
FILWIDTH_PIN,
|
||||
#endif
|
||||
@@ -232,6 +240,9 @@ uint16_t HAL_adc_result;
|
||||
#if GET_CHAMBER_ADC() == 0
|
||||
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
|
||||
#endif
|
||||
#if GET_COOLER_ADC() == 0
|
||||
{ PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
|
||||
#endif
|
||||
#if GET_FILAMENT_WIDTH_ADC() == 0
|
||||
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
|
||||
#endif
|
||||
@@ -281,6 +292,9 @@ uint16_t HAL_adc_result;
|
||||
#if GET_CHAMBER_ADC() == 1
|
||||
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
|
||||
#endif
|
||||
#if GET_COOLER_ADC() == 1
|
||||
{ PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
|
||||
#endif
|
||||
#if GET_FILAMENT_WIDTH_ADC() == 1
|
||||
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
|
||||
#endif
|
||||
|
||||
+17
-17
@@ -32,36 +32,36 @@
|
||||
#include "MarlinSerial_AGCM4.h"
|
||||
|
||||
// Serial ports
|
||||
typedef ForwardSerial0Type< decltype(Serial) > DefaultSerial;
|
||||
typedef ForwardSerial0Type< decltype(Serial1) > DefaultSerial1;
|
||||
typedef ForwardSerial0Type< decltype(Serial2) > DefaultSerial2;
|
||||
typedef ForwardSerial0Type< decltype(Serial3) > DefaultSerial3;
|
||||
typedef ForwardSerial0Type< decltype(Serial4) > DefaultSerial4;
|
||||
extern DefaultSerial MSerial;
|
||||
extern DefaultSerial1 MSerial1;
|
||||
extern DefaultSerial2 MSerial2;
|
||||
extern DefaultSerial3 MSerial3;
|
||||
extern DefaultSerial4 MSerial4;
|
||||
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
|
||||
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
|
||||
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
|
||||
typedef ForwardSerial1Class< decltype(Serial3) > DefaultSerial4;
|
||||
typedef ForwardSerial1Class< decltype(Serial4) > DefaultSerial5;
|
||||
extern DefaultSerial1 MSerial0;
|
||||
extern DefaultSerial2 MSerial1;
|
||||
extern DefaultSerial3 MSerial2;
|
||||
extern DefaultSerial4 MSerial3;
|
||||
extern DefaultSerial5 MSerial4;
|
||||
|
||||
// MYSERIAL0 required before MarlinSerial includes!
|
||||
// MYSERIAL1 required before MarlinSerial includes!
|
||||
|
||||
#define __MSERIAL(X) MSerial##X
|
||||
#define _MSERIAL(X) __MSERIAL(X)
|
||||
#define MSERIAL(X) _MSERIAL(INCREMENT(X))
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
#define MYSERIAL0 MSerial
|
||||
#define MYSERIAL1 MSerial0
|
||||
#elif WITHIN(SERIAL_PORT, 0, 3)
|
||||
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#else
|
||||
#error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if SERIAL_PORT_2 == -1
|
||||
#define MYSERIAL1 MSerial
|
||||
#define MYSERIAL2 MSerial0
|
||||
#elif WITHIN(SERIAL_PORT_2, 0, 3)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
|
||||
#else
|
||||
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
|
||||
#endif
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
#ifdef MMU2_SERIAL_PORT
|
||||
#if MMU2_SERIAL_PORT == -1
|
||||
#define MMU2_SERIAL MSerial
|
||||
#define MMU2_SERIAL MSerial0
|
||||
#elif WITHIN(MMU2_SERIAL_PORT, 0, 3)
|
||||
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
|
||||
#else
|
||||
@@ -79,7 +79,7 @@
|
||||
|
||||
#ifdef LCD_SERIAL_PORT
|
||||
#if LCD_SERIAL_PORT == -1
|
||||
#define LCD_SERIAL MSerial
|
||||
#define LCD_SERIAL MSerial0
|
||||
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
|
||||
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
|
||||
#else
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
typedef Serial0Type<Uart> UartT;
|
||||
typedef Serial1Class<Uart> UartT;
|
||||
|
||||
extern UartT Serial2;
|
||||
extern UartT Serial3;
|
||||
|
||||
@@ -50,3 +50,7 @@
|
||||
#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
|
||||
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on SAMD51."
|
||||
#endif
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not yet supported on AGCM4."
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "../shared/Delay.h"
|
||||
|
||||
#ifdef USBCON
|
||||
DefaultSerial MSerial(false, SerialUSB);
|
||||
DefaultSerial1 MSerial0(false, SerialUSB);
|
||||
#endif
|
||||
|
||||
#if ENABLED(SRAM_EEPROM_EMULATION)
|
||||
@@ -57,10 +57,18 @@ uint16_t HAL_adc_result;
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
|
||||
|
||||
// HAL initialization task
|
||||
void HAL_init() {
|
||||
FastIO_init();
|
||||
|
||||
// Ensure F_CPU is a constant expression.
|
||||
// If the compiler breaks here, it means that delay code that should compute at compile time will not work.
|
||||
// So better safe than sorry here.
|
||||
constexpr int cpuFreq = F_CPU;
|
||||
UNUSED(cpuFreq);
|
||||
|
||||
#if ENABLED(SDSUPPORT) && DISABLED(SDIO_SUPPORT) && (defined(SDSS) && SDSS != -1)
|
||||
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
|
||||
#endif
|
||||
@@ -83,6 +91,8 @@ void HAL_init() {
|
||||
USB_Hook_init();
|
||||
#endif
|
||||
|
||||
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
|
||||
|
||||
#if HAS_SD_HOST_DRIVE
|
||||
MSC_SD_init(); // Enable USB SD card access
|
||||
#endif
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
#ifdef USBCON
|
||||
#include <USBSerial.h>
|
||||
#include "../../core/serial_hook.h"
|
||||
typedef ForwardSerial0Type< decltype(SerialUSB) > DefaultSerial;
|
||||
extern DefaultSerial MSerial;
|
||||
typedef ForwardSerial1Class< decltype(SerialUSB) > DefaultSerial1;
|
||||
extern DefaultSerial1 MSerial0;
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
@@ -51,18 +51,18 @@
|
||||
#define MSERIAL(X) _MSERIAL(X)
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
#define MYSERIAL0 MSerial
|
||||
#define MYSERIAL1 MSerial0
|
||||
#elif WITHIN(SERIAL_PORT, 1, 6)
|
||||
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#else
|
||||
#error "SERIAL_PORT must be -1 or from 1 to 6. Please update your configuration."
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if SERIAL_PORT_2 == -1
|
||||
#define MYSERIAL1 MSerial
|
||||
#define MYSERIAL2 MSerial0
|
||||
#elif WITHIN(SERIAL_PORT_2, 1, 6)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
|
||||
#else
|
||||
#error "SERIAL_PORT_2 must be -1 or from 1 to 6. Please update your configuration."
|
||||
#endif
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
#ifdef MMU2_SERIAL_PORT
|
||||
#if MMU2_SERIAL_PORT == -1
|
||||
#define MMU2_SERIAL MSerial
|
||||
#define MMU2_SERIAL MSerial0
|
||||
#elif WITHIN(MMU2_SERIAL_PORT, 1, 6)
|
||||
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
|
||||
#else
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
#ifdef LCD_SERIAL_PORT
|
||||
#if LCD_SERIAL_PORT == -1
|
||||
#define LCD_SERIAL MSerial
|
||||
#define LCD_SERIAL MSerial0
|
||||
#elif WITHIN(LCD_SERIAL_PORT, 1, 6)
|
||||
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
|
||||
#include "../shared/HAL_MinSerial.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
/* Instruction Synchronization Barrier */
|
||||
#define isb() __asm__ __volatile__ ("isb" : : : "memory")
|
||||
|
||||
/* Data Synchronization Barrier */
|
||||
#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
|
||||
|
||||
// Dumb mapping over the registers of a USART device on STM32
|
||||
struct USARTMin {
|
||||
volatile uint32_t SR;
|
||||
volatile uint32_t DR;
|
||||
volatile uint32_t BRR;
|
||||
volatile uint32_t CR1;
|
||||
volatile uint32_t CR2;
|
||||
};
|
||||
|
||||
#if WITHIN(SERIAL_PORT, 1, 6)
|
||||
// Depending on the CPU, the serial port is different for USART1
|
||||
static const uintptr_t regsAddr[] = {
|
||||
TERN(STM32F1xx, 0x40013800, 0x40011000), // USART1
|
||||
0x40004400, // USART2
|
||||
0x40004800, // USART3
|
||||
0x40004C00, // UART4_BASE
|
||||
0x40005000, // UART5_BASE
|
||||
0x40011400 // USART6
|
||||
};
|
||||
static USARTMin * regs = (USARTMin*)regsAddr[SERIAL_PORT - 1];
|
||||
#endif
|
||||
|
||||
static void TXBegin() {
|
||||
#if !WITHIN(SERIAL_PORT, 1, 6)
|
||||
#warning "Using POSTMORTEM_DEBUGGING requires a physical U(S)ART hardware in case of severe error."
|
||||
#warning "Disabling the severe error reporting feature currently because the used serial port is not a HW port."
|
||||
#else
|
||||
// This is common between STM32F1/STM32F2 and STM32F4
|
||||
const int nvicUART[] = { /* NVIC_USART1 */ 37, /* NVIC_USART2 */ 38, /* NVIC_USART3 */ 39, /* NVIC_UART4 */ 52, /* NVIC_UART5 */ 53, /* NVIC_USART6 */ 71 };
|
||||
int nvicIndex = nvicUART[SERIAL_PORT - 1];
|
||||
|
||||
struct NVICMin {
|
||||
volatile uint32_t ISER[32];
|
||||
volatile uint32_t ICER[32];
|
||||
};
|
||||
|
||||
NVICMin * nvicBase = (NVICMin*)0xE000E100;
|
||||
nvicBase->ICER[nvicIndex / 32] |= _BV32(nvicIndex % 32);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
dsb();
|
||||
isb();
|
||||
|
||||
// Example for USART1 disable: (RCC->APB2ENR &= ~(RCC_APB2ENR_USART1EN))
|
||||
// Too difficult to reimplement here, let's query the STM32duino macro here
|
||||
#if SERIAL_PORT == 1
|
||||
__HAL_RCC_USART1_CLK_DISABLE();
|
||||
__HAL_RCC_USART1_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 2
|
||||
__HAL_RCC_USART2_CLK_DISABLE();
|
||||
__HAL_RCC_USART2_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 3
|
||||
__HAL_RCC_USART3_CLK_DISABLE();
|
||||
__HAL_RCC_USART3_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 4
|
||||
__HAL_RCC_UART4_CLK_DISABLE(); // BEWARE: UART4 and not USART4 here
|
||||
__HAL_RCC_UART4_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 5
|
||||
__HAL_RCC_UART5_CLK_DISABLE(); // BEWARE: UART5 and not USART5 here
|
||||
__HAL_RCC_UART5_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 6
|
||||
__HAL_RCC_USART6_CLK_DISABLE();
|
||||
__HAL_RCC_USART6_CLK_ENABLE();
|
||||
#endif
|
||||
|
||||
uint32_t brr = regs->BRR;
|
||||
regs->CR1 = 0; // Reset the USART
|
||||
regs->CR2 = 0; // 1 stop bit
|
||||
|
||||
// If we don't touch the BRR (baudrate register), we don't need to recompute.
|
||||
regs->BRR = brr;
|
||||
|
||||
regs->CR1 = _BV(3) | _BV(13); // 8 bits, no parity, 1 stop bit (TE | UE)
|
||||
#endif
|
||||
}
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() __asm__ volatile("": : :"memory");
|
||||
static void TX(char c) {
|
||||
#if WITHIN(SERIAL_PORT, 1, 6)
|
||||
constexpr uint32_t usart_sr_txe = _BV(7);
|
||||
while (!(regs->SR & usart_sr_txe)) {
|
||||
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
|
||||
sw_barrier();
|
||||
}
|
||||
regs->DR = c;
|
||||
#else
|
||||
// Let's hope a mystical guru will fix this, one day by writting interrupt-free USB CDC ACM code (or, at least, by polling the registers since interrupt will be queued but will never trigger)
|
||||
// For now, it's completely lost to oblivion.
|
||||
#endif
|
||||
}
|
||||
|
||||
void install_min_serial() {
|
||||
HAL_min_serial_init = &TXBegin;
|
||||
HAL_min_serial_out = &TX;
|
||||
}
|
||||
|
||||
#if DISABLED(DYNAMIC_VECTORTABLE) && DISABLED(STM32F0xx) // Cortex M0 can't jump to a symbol that's too far from the current function, so we work around this in exception_arm.cpp
|
||||
extern "C" {
|
||||
__attribute__((naked)) void JumpHandler_ASM() {
|
||||
__asm__ __volatile__ (
|
||||
"b CommonHandler_ASM\n"
|
||||
);
|
||||
}
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) HardFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) BusFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) UsageFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) MemManage_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) NMI_Handler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // POSTMORTEM_DEBUGGING
|
||||
#endif // ARDUINO_ARCH_STM32
|
||||
@@ -42,7 +42,7 @@ protected:
|
||||
usart_rx_callback_t _rx_callback;
|
||||
};
|
||||
|
||||
typedef Serial0Type<MarlinSerial> MSerialT;
|
||||
typedef Serial1Class<MarlinSerial> MSerialT;
|
||||
extern MSerialT MSerial1;
|
||||
extern MSerialT MSerial2;
|
||||
extern MSerialT MSerial3;
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#include "stm32_def.h"
|
||||
|
||||
#define DEBUG_OUT ENABLED(EEPROM_CHITCHAT)
|
||||
#include "src/core/debug_out.h"
|
||||
#include "../../core/debug_out.h"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
|
||||
|
||||
@@ -24,3 +24,9 @@
|
||||
#if defined(USBD_USE_CDC_MSC) && DISABLED(NO_SD_HOST_DRIVE)
|
||||
#define HAS_SD_HOST_DRIVE 1
|
||||
#endif
|
||||
|
||||
// Fix F_CPU not being a compile-time constant in STSTM32 framework
|
||||
#ifdef BOARD_F_CPU
|
||||
#undef F_CPU
|
||||
#define F_CPU BOARD_F_CPU
|
||||
#endif
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
#error "SERIAL_STATS_MAX_RX_QUEUED is not supported on this platform."
|
||||
#error "SERIAL_STATS_MAX_RX_QUEUED is not supported on STM32."
|
||||
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
#error "SERIAL_STATS_DROPPED_RX is not supported on this platform."
|
||||
#error "SERIAL_STATS_DROPPED_RX is not supported on STM32."
|
||||
#endif
|
||||
|
||||
#if ANY(TFT_COLOR_UI, TFT_LVGL_UI, TFT_CLASSIC_UI) && NOT_TARGET(STM32F4xx, STM32F1xx)
|
||||
|
||||
@@ -207,12 +207,12 @@ void TFT_SPI::Transmit(uint16_t Data) {
|
||||
while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {}
|
||||
|
||||
if (TFT_MISO_PIN != TFT_MOSI_PIN)
|
||||
__HAL_SPI_CLEAR_OVRFLAG(&SPIx); /* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(&SPIx); // Clear overrun flag in 2 Lines communication mode because received is not read
|
||||
}
|
||||
|
||||
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
|
||||
// Wait last dma finish, to start another
|
||||
while(isBusy()) { }
|
||||
while (isBusy()) { /* nada */ }
|
||||
|
||||
DMAtx.Init.MemInc = MemoryIncrease;
|
||||
HAL_DMA_Init(&DMAtx);
|
||||
@@ -225,7 +225,7 @@ void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Coun
|
||||
HAL_DMA_Start(&DMAtx, (uint32_t)Data, (uint32_t)&(SPIx.Instance->DR), Count);
|
||||
__HAL_SPI_ENABLE(&SPIx);
|
||||
|
||||
SET_BIT(SPIx.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */
|
||||
SET_BIT(SPIx.Instance->CR2, SPI_CR2_TXDMAEN); // Enable Tx DMA Request
|
||||
|
||||
HAL_DMA_PollForTransfer(&DMAtx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
|
||||
Abort();
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
#if defined(SERIAL_USB) && !HAS_SD_HOST_DRIVE
|
||||
USBSerial SerialUSB;
|
||||
DefaultSerial MSerial(true, SerialUSB);
|
||||
DefaultSerial1 MSerial0(true, SerialUSB);
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#include "../libmaple/usb/stm32f1/usb_reg_map.h"
|
||||
@@ -107,7 +107,7 @@
|
||||
len = usb_cdcacm_peek(buf, total);
|
||||
|
||||
for (uint32 i = 0; i < len; i++)
|
||||
emergency_parser.update(MSerial.emergency_state, buf[i + total - len]);
|
||||
emergency_parser.update(MSerial0.emergency_state, buf[i + total - len]);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -132,6 +132,9 @@ const uint8_t adc_pins[] = {
|
||||
#if HAS_TEMP_CHAMBER
|
||||
TEMP_CHAMBER_PIN,
|
||||
#endif
|
||||
#if HAS_TEMP_COOLER
|
||||
TEMP_COOLER_PIN,
|
||||
#endif
|
||||
#if HAS_TEMP_ADC_1
|
||||
TEMP_1_PIN,
|
||||
#endif
|
||||
@@ -189,6 +192,9 @@ enum TempPinIndex : char {
|
||||
#if HAS_TEMP_CHAMBER
|
||||
TEMP_CHAMBER,
|
||||
#endif
|
||||
#if HAS_TEMP_COOLER
|
||||
TEMP_COOLER_PIN,
|
||||
#endif
|
||||
#if HAS_TEMP_ADC_1
|
||||
TEMP_1,
|
||||
#endif
|
||||
@@ -272,6 +278,8 @@ static void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) {
|
||||
} }
|
||||
#endif
|
||||
|
||||
TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
|
||||
|
||||
void HAL_init() {
|
||||
NVIC_SetPriorityGrouping(0x3);
|
||||
#if PIN_EXISTS(LED)
|
||||
@@ -287,6 +295,7 @@ void HAL_init() {
|
||||
delay(1000); // Give OS time to notice
|
||||
OUT_WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING);
|
||||
#endif
|
||||
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the minimal serial handler
|
||||
}
|
||||
|
||||
// HAL idle task
|
||||
@@ -382,6 +391,9 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
|
||||
#if HAS_TEMP_CHAMBER
|
||||
case TEMP_CHAMBER_PIN: pin_index = TEMP_CHAMBER; break;
|
||||
#endif
|
||||
#if HAS_TEMP_COOLER
|
||||
case TEMP_COOLER_PIN: pin_index = TEMP_COOLER; break;
|
||||
#endif
|
||||
#if HAS_TEMP_ADC_1
|
||||
case TEMP_1_PIN: pin_index = TEMP_1; break;
|
||||
#endif
|
||||
|
||||
@@ -61,11 +61,11 @@
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
typedef ForwardSerial0Type< USBSerial > DefaultSerial;
|
||||
extern DefaultSerial MSerial;
|
||||
typedef ForwardSerial1Class< USBSerial > DefaultSerial1;
|
||||
extern DefaultSerial1 MSerial0;
|
||||
|
||||
#if !HAS_SD_HOST_DRIVE
|
||||
#define UsbSerial MSerial
|
||||
#define UsbSerial MSerial0
|
||||
#else
|
||||
#define UsbSerial MarlinCompositeSerial
|
||||
#endif
|
||||
@@ -81,9 +81,9 @@
|
||||
#endif
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
#define MYSERIAL0 UsbSerial
|
||||
#define MYSERIAL1 UsbSerial
|
||||
#elif WITHIN(SERIAL_PORT, 1, NUM_UARTS)
|
||||
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#elif NUM_UARTS == 5
|
||||
#error "SERIAL_PORT must be -1 or from 1 to 5. Please update your configuration."
|
||||
#else
|
||||
@@ -92,9 +92,9 @@
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if SERIAL_PORT_2 == -1
|
||||
#define MYSERIAL1 UsbSerial
|
||||
#define MYSERIAL2 UsbSerial
|
||||
#elif WITHIN(SERIAL_PORT_2, 1, NUM_UARTS)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
|
||||
#elif NUM_UARTS == 5
|
||||
#error "SERIAL_PORT_2 must be -1 or from 1 to 5. Please update your configuration."
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifdef __STM32F1__
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
|
||||
#include "../shared/HAL_MinSerial.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
#include <libmaple/usart.h>
|
||||
#include <libmaple/rcc.h>
|
||||
#include <libmaple/nvic.h>
|
||||
|
||||
/* Instruction Synchronization Barrier */
|
||||
#define isb() __asm__ __volatile__ ("isb" : : : "memory")
|
||||
|
||||
/* Data Synchronization Barrier */
|
||||
#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
|
||||
|
||||
static void TXBegin() {
|
||||
#if !WITHIN(SERIAL_PORT, 1, 6)
|
||||
#warning "Using POSTMORTEM_DEBUGGING requires a physical U(S)ART hardware in case of severe error."
|
||||
#warning "Disabling the severe error reporting feature currently because the used serial port is not a HW port."
|
||||
#else
|
||||
// We use MYSERIAL1 here, so we need to figure out how to get the linked register
|
||||
struct usart_dev* dev = MYSERIAL1.c_dev();
|
||||
|
||||
// Or use this if removing libmaple
|
||||
// int irq = dev->irq_num;
|
||||
// int nvicUART[] = { NVIC_USART1 /* = 37 */, NVIC_USART2 /* = 38 */, NVIC_USART3 /* = 39 */, NVIC_UART4 /* = 52 */, NVIC_UART5 /* = 53 */ };
|
||||
// Disabling irq means setting the bit in the NVIC ICER register located at
|
||||
// Disable UART interrupt in NVIC
|
||||
nvic_irq_disable(dev->irq_num);
|
||||
|
||||
// Use this if removing libmaple
|
||||
//NVIC_BASE->ICER[1] |= _BV(irq - 32);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
dsb();
|
||||
isb();
|
||||
|
||||
rcc_clk_disable(dev->clk_id);
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
|
||||
usart_reg_map *regs = dev->regs;
|
||||
regs->CR1 = 0; // Reset the USART
|
||||
regs->CR2 = 0; // 1 stop bit
|
||||
|
||||
// If we don't touch the BRR (baudrate register), we don't need to recompute. Else we would need to call
|
||||
usart_set_baud_rate(dev, 0, BAUDRATE);
|
||||
|
||||
regs->CR1 = (USART_CR1_TE | USART_CR1_UE); // 8 bits, no parity, 1 stop bit
|
||||
#endif
|
||||
}
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() __asm__ volatile("": : :"memory");
|
||||
static void TX(char c) {
|
||||
#if WITHIN(SERIAL_PORT, 1, 6)
|
||||
struct usart_dev* dev = MYSERIAL1.c_dev();
|
||||
while (!(dev->regs->SR & USART_SR_TXE)) {
|
||||
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
|
||||
sw_barrier();
|
||||
}
|
||||
dev->regs->DR = c;
|
||||
#endif
|
||||
}
|
||||
|
||||
void install_min_serial() {
|
||||
HAL_min_serial_init = &TXBegin;
|
||||
HAL_min_serial_out = &TX;
|
||||
}
|
||||
|
||||
#if DISABLED(DYNAMIC_VECTORTABLE) && DISABLED(STM32F0xx) // Cortex M0 can't branch to a symbol that's too far, so we have a specific hack for them
|
||||
extern "C" {
|
||||
__attribute__((naked)) void JumpHandler_ASM() {
|
||||
__asm__ __volatile__ (
|
||||
"b CommonHandler_ASM\n"
|
||||
);
|
||||
}
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_hardfault();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_busfault();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_usagefault();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_memmanage();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_nmi();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception7();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception8();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception9();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception10();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception13();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // POSTMORTEM_DEBUGGING
|
||||
#endif // __STM32F1__
|
||||
@@ -134,12 +134,12 @@ constexpr bool IsSerialClassAllowed(const HardwareSerial&) { return false; }
|
||||
// If you encounter this error, replace SerialX with MSerialX, for example MSerial3.
|
||||
|
||||
// Non-TMC ports were already validated in HAL.h, so do not require verbose error messages.
|
||||
#ifdef MYSERIAL0
|
||||
CHECK_CFG_SERIAL(MYSERIAL0);
|
||||
#endif
|
||||
#ifdef MYSERIAL1
|
||||
CHECK_CFG_SERIAL(MYSERIAL1);
|
||||
#endif
|
||||
#ifdef MYSERIAL2
|
||||
CHECK_CFG_SERIAL(MYSERIAL2);
|
||||
#endif
|
||||
#ifdef LCD_SERIAL
|
||||
CHECK_CFG_SERIAL(LCD_SERIAL);
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,7 @@ struct MarlinSerial : public HardwareSerial {
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef Serial0Type<MarlinSerial> MSerialT;
|
||||
typedef Serial1Class<MarlinSerial> MSerialT;
|
||||
|
||||
extern MSerialT MSerial1;
|
||||
extern MSerialT MSerial2;
|
||||
|
||||
@@ -40,7 +40,7 @@ void eeprom_init() { BL24CXX::init(); }
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
void eeprom_write_byte(uint8_t *pos, unsigned char value) {
|
||||
void eeprom_write_byte(uint8_t *pos, uint8_t value) {
|
||||
const unsigned eeprom_address = (unsigned)pos;
|
||||
return BL24CXX::writeOneByte(eeprom_address, value);
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
#error "SERIAL_STATS_MAX_RX_QUEUED is not supported on this platform."
|
||||
#error "SERIAL_STATS_MAX_RX_QUEUED is not supported on the STM32F1 platform."
|
||||
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
#error "SERIAL_STATS_DROPPED_RX is not supported on this platform."
|
||||
#error "SERIAL_STATS_DROPPED_RX is not supported on the STM32F1 platform."
|
||||
#endif
|
||||
|
||||
#if ENABLED(NEOPIXEL_LED)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define PRODUCT_ID 0x29
|
||||
|
||||
USBMassStorage MarlinMSC;
|
||||
Serial0Type<USBCompositeSerial> MarlinCompositeSerial(true);
|
||||
Serial1Class<USBCompositeSerial> MarlinCompositeSerial(true);
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
@@ -43,26 +43,27 @@ Serial0Type<USBCompositeSerial> MarlinCompositeSerial(true);
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
|
||||
// The original callback is not called (no way to retrieve address).
|
||||
// That callback detects a special STM32 reset sequence: this functionality is not essential
|
||||
// as M997 achieves the same.
|
||||
void my_rx_callback(unsigned int, void*) {
|
||||
// max length of 16 is enough to contain all emergency commands
|
||||
uint8 buf[16];
|
||||
// The original callback is not called (no way to retrieve address).
|
||||
// That callback detects a special STM32 reset sequence: this functionality is not essential
|
||||
// as M997 achieves the same.
|
||||
void my_rx_callback(unsigned int, void*) {
|
||||
// max length of 16 is enough to contain all emergency commands
|
||||
uint8 buf[16];
|
||||
|
||||
//rx is usbSerialPart.endpoints[2]
|
||||
uint16 len = usb_get_ep_rx_count(usbSerialPart.endpoints[2].address);
|
||||
uint32 total = composite_cdcacm_data_available();
|
||||
//rx is usbSerialPart.endpoints[2]
|
||||
uint16 len = usb_get_ep_rx_count(usbSerialPart.endpoints[2].address);
|
||||
uint32 total = composite_cdcacm_data_available();
|
||||
|
||||
if (len == 0 || total == 0 || !WITHIN(total, len, COUNT(buf)))
|
||||
return;
|
||||
if (len == 0 || total == 0 || !WITHIN(total, len, COUNT(buf)))
|
||||
return;
|
||||
|
||||
// cannot get character by character due to bug in composite_cdcacm_peek_ex
|
||||
len = composite_cdcacm_peek(buf, total);
|
||||
// cannot get character by character due to bug in composite_cdcacm_peek_ex
|
||||
len = composite_cdcacm_peek(buf, total);
|
||||
|
||||
for (uint32 i = 0; i < len; i++)
|
||||
emergency_parser.update(MarlinCompositeSerial.emergency_state, buf[i+total-len]);
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < len; i++)
|
||||
emergency_parser.update(MarlinCompositeSerial.emergency_state, buf[i+total-len]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MSC_SD_init() {
|
||||
@@ -87,7 +88,7 @@ void MSC_SD_init() {
|
||||
MarlinCompositeSerial.registerComponent();
|
||||
USBComposite.begin();
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
composite_cdcacm_set_hooks(USBHID_CDCACM_HOOK_RX, my_rx_callback);
|
||||
composite_cdcacm_set_hooks(USBHID_CDCACM_HOOK_RX, my_rx_callback);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
extern USBMassStorage MarlinMSC;
|
||||
extern Serial0Type<USBCompositeSerial> MarlinCompositeSerial;
|
||||
extern Serial1Class<USBCompositeSerial> MarlinCompositeSerial;
|
||||
|
||||
void MSC_SD_init();
|
||||
|
||||
@@ -31,7 +31,11 @@
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
DefaultSerial MSerial(false);
|
||||
#define _IMPLEMENT_SERIAL(X) DefaultSerial##X MSerial##X(false, Serial##X)
|
||||
#define IMPLEMENT_SERIAL(X) _IMPLEMENT_SERIAL(X)
|
||||
#if WITHIN(SERIAL_PORT, 0, 3)
|
||||
IMPLEMENT_SERIAL(SERIAL_PORT);
|
||||
#endif
|
||||
USBSerialType USBSerial(false, SerialUSB);
|
||||
|
||||
uint16_t HAL_adc_result;
|
||||
|
||||
@@ -51,19 +51,24 @@
|
||||
#endif
|
||||
|
||||
#include "../../core/serial_hook.h"
|
||||
typedef Serial0Type<decltype(Serial)> DefaultSerial;
|
||||
extern DefaultSerial MSerial;
|
||||
typedef ForwardSerial0Type<decltype(SerialUSB)> USBSerialType;
|
||||
|
||||
#define Serial0 Serial
|
||||
#define _DECLARE_SERIAL(X) \
|
||||
typedef ForwardSerial1Class<decltype(Serial##X)> DefaultSerial##X; \
|
||||
extern DefaultSerial##X MSerial##X
|
||||
#define DECLARE_SERIAL(X) _DECLARE_SERIAL(X)
|
||||
|
||||
typedef ForwardSerial1Class<decltype(SerialUSB)> USBSerialType;
|
||||
extern USBSerialType USBSerial;
|
||||
|
||||
#define _MSERIAL(X) MSerial##X
|
||||
#define MSERIAL(X) _MSERIAL(X)
|
||||
#define MSerial0 MSerial
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
#define MYSERIAL0 USBSerial
|
||||
#define MYSERIAL1 USBSerial
|
||||
#elif WITHIN(SERIAL_PORT, 0, 3)
|
||||
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
|
||||
DECLARE_SERIAL(SERIAL_PORT);
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#endif
|
||||
|
||||
#define HAL_SERVO_LIB libServo
|
||||
|
||||
@@ -34,5 +34,9 @@
|
||||
#endif
|
||||
|
||||
#if HAS_TMC_SW_SERIAL
|
||||
#error "TMC220x Software Serial is not supported on this platform."
|
||||
#error "TMC220x Software Serial is not supported on Teensy 3.1/3.2."
|
||||
#endif
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not yet supported on Teensy 3.1/3.2."
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,12 @@
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
DefaultSerial MSerial(false);
|
||||
#define _IMPLEMENT_SERIAL(X) DefaultSerial##X MSerial##X(false, Serial##X)
|
||||
#define IMPLEMENT_SERIAL(X) _IMPLEMENT_SERIAL(X)
|
||||
#if WITHIN(SERIAL_PORT, 0, 3)
|
||||
IMPLEMENT_SERIAL(SERIAL_PORT);
|
||||
#endif
|
||||
|
||||
USBSerialType USBSerial(false, SerialUSB);
|
||||
|
||||
uint16_t HAL_adc_result, HAL_adc_select;
|
||||
|
||||
@@ -54,19 +54,24 @@
|
||||
#endif
|
||||
|
||||
#include "../../core/serial_hook.h"
|
||||
typedef Serial0Type<decltype(Serial)> DefaultSerial;
|
||||
extern DefaultSerial MSerial;
|
||||
typedef ForwardSerial0Type<decltype(SerialUSB)> USBSerialType;
|
||||
|
||||
#define Serial0 Serial
|
||||
#define _DECLARE_SERIAL(X) \
|
||||
typedef ForwardSerial1Class<decltype(Serial##X)> DefaultSerial##X; \
|
||||
extern DefaultSerial##X MSerial##X
|
||||
#define DECLARE_SERIAL(X) _DECLARE_SERIAL(X)
|
||||
|
||||
typedef ForwardSerial1Class<decltype(SerialUSB)> USBSerialType;
|
||||
extern USBSerialType USBSerial;
|
||||
|
||||
#define _MSERIAL(X) MSerial##X
|
||||
#define MSERIAL(X) _MSERIAL(X)
|
||||
#define MSerial0 MSerial
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
#define MYSERIAL0 USBSerial
|
||||
#define MYSERIAL1 USBSerial
|
||||
#elif WITHIN(SERIAL_PORT, 0, 3)
|
||||
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
DECLARE_SERIAL(SERIAL_PORT);
|
||||
#endif
|
||||
|
||||
#define HAL_SERVO_LIB libServo
|
||||
|
||||
@@ -34,5 +34,9 @@
|
||||
#endif
|
||||
|
||||
#if HAS_TMC_SW_SERIAL
|
||||
#error "TMC220x Software Serial is not supported on this platform."
|
||||
#error "TMC220x Software Serial is not supported on Teensy 3.5/3.6."
|
||||
#endif
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not yet supported on Teensy 3.5/3.6."
|
||||
#endif
|
||||
|
||||
@@ -32,7 +32,11 @@
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
DefaultSerial MSerial(false);
|
||||
#define _IMPLEMENT_SERIAL(X) DefaultSerial##X MSerial##X(false, Serial##X)
|
||||
#define IMPLEMENT_SERIAL(X) _IMPLEMENT_SERIAL(X)
|
||||
#if WITHIN(SERIAL_PORT, 0, 3)
|
||||
IMPLEMENT_SERIAL(SERIAL_PORT);
|
||||
#endif
|
||||
USBSerialType USBSerial(false, SerialUSB);
|
||||
|
||||
uint16_t HAL_adc_result, HAL_adc_select;
|
||||
|
||||
@@ -56,30 +56,34 @@
|
||||
#endif
|
||||
|
||||
#include "../../core/serial_hook.h"
|
||||
typedef Serial0Type<decltype(Serial)> DefaultSerial;
|
||||
extern DefaultSerial MSerial;
|
||||
typedef ForwardSerial0Type<decltype(SerialUSB)> USBSerialType;
|
||||
#define Serial0 Serial
|
||||
#define _DECLARE_SERIAL(X) \
|
||||
typedef ForwardSerial1Class<decltype(Serial##X)> DefaultSerial##X; \
|
||||
extern DefaultSerial##X MSerial##X
|
||||
#define DECLARE_SERIAL(X) _DECLARE_SERIAL(X)
|
||||
|
||||
typedef ForwardSerial1Class<decltype(SerialUSB)> USBSerialType;
|
||||
extern USBSerialType USBSerial;
|
||||
|
||||
#define _MSERIAL(X) MSerial##X
|
||||
#define MSERIAL(X) _MSERIAL(X)
|
||||
#define MSerial0 MSerial
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
#define MYSERIAL0 SerialUSB
|
||||
#define MYSERIAL1 SerialUSB
|
||||
#elif WITHIN(SERIAL_PORT, 0, 8)
|
||||
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
|
||||
DECLARE_SERIAL(SERIAL_PORT);
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#else
|
||||
#error "The required SERIAL_PORT must be from -1 to 8. Please update your configuration."
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if SERIAL_PORT_2 == -1
|
||||
#define MYSERIAL1 usbSerial
|
||||
#define MYSERIAL2 usbSerial
|
||||
#elif SERIAL_PORT_2 == -2
|
||||
#define MYSERIAL1 ethernet.telnetClient
|
||||
#define MYSERIAL2 ethernet.telnetClient
|
||||
#elif WITHIN(SERIAL_PORT_2, 0, 8)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
|
||||
#else
|
||||
#error "SERIAL_PORT_2 must be from -2 to 8. Please update your configuration."
|
||||
#endif
|
||||
|
||||
@@ -34,5 +34,9 @@
|
||||
#endif
|
||||
|
||||
#if HAS_TMC_SW_SERIAL
|
||||
#error "TMC220x Software Serial is not supported on this platform."
|
||||
#error "TMC220x Software Serial is not supported on Teensy 4.0/4.1."
|
||||
#endif
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not yet supported on Teensy 4.0/4.1."
|
||||
#endif
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
// Use hardware cycle counter instead, it's much safer
|
||||
void delay_dwt(uint32_t count) {
|
||||
// Reuse the ASM_CYCLES_PER_ITERATION variable to avoid wasting another useless variable
|
||||
register uint32_t start = HW_REG(_DWT_CYCCNT) - ASM_CYCLES_PER_ITERATION, elapsed;
|
||||
uint32_t start = HW_REG(_DWT_CYCCNT) - ASM_CYCLES_PER_ITERATION, elapsed;
|
||||
do {
|
||||
elapsed = HW_REG(_DWT_CYCCNT) - start;
|
||||
} while (elapsed < count);
|
||||
@@ -109,12 +109,12 @@
|
||||
void dump_delay_accuracy_check() {
|
||||
auto report_call_time = [](PGM_P const name, PGM_P const unit, const uint32_t cycles, const uint32_t total, const bool do_flush=true) {
|
||||
SERIAL_ECHOPGM("Calling ");
|
||||
serialprintPGM(name);
|
||||
SERIAL_ECHOPGM_P(name);
|
||||
SERIAL_ECHOLNPAIR(" for ", cycles);
|
||||
serialprintPGM(unit);
|
||||
SERIAL_ECHOPGM_P(unit);
|
||||
SERIAL_ECHOLNPAIR(" took: ", total);
|
||||
serialprintPGM(unit);
|
||||
if (do_flush) SERIAL_FLUSH();
|
||||
SERIAL_ECHOPGM_P(unit);
|
||||
if (do_flush) SERIAL_FLUSHTX();
|
||||
};
|
||||
|
||||
uint32_t s, e;
|
||||
@@ -169,10 +169,7 @@
|
||||
|
||||
void calibrate_delay_loop() {}
|
||||
#if ENABLED(MARLIN_DEV_MODE)
|
||||
void dump_delay_accuracy_check() {
|
||||
static PGMSTR(none, "N/A on this platform");
|
||||
serialprintPGM(none);
|
||||
}
|
||||
void dump_delay_accuracy_check() { SERIAL_ECHOPGM_P(PSTR("N/A on this platform")); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "HAL_MinSerial.h"
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
|
||||
void HAL_min_serial_init_default() {}
|
||||
void HAL_min_serial_out_default(char ch) { SERIAL_CHAR(ch); }
|
||||
void (*HAL_min_serial_init)() = &HAL_min_serial_init_default;
|
||||
void (*HAL_min_serial_out)(char) = &HAL_min_serial_out_default;
|
||||
|
||||
bool MinSerial::force_using_default_output = false;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../core/serial.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// Serial stuff here
|
||||
// Inside an exception handler, the CPU state is not safe, we can't expect the handler to resume
|
||||
// and the software to continue. UART communication can't rely on later callback/interrupt as it might never happen.
|
||||
// So, you need to provide some method to send one byte to the usual UART with the interrupts disabled
|
||||
// By default, the method uses SERIAL_CHAR but it's 100% guaranteed to break (couldn't be worse than nothing...)7
|
||||
extern void (*HAL_min_serial_init)();
|
||||
extern void (*HAL_min_serial_out)(char ch);
|
||||
|
||||
struct MinSerial {
|
||||
static bool force_using_default_output;
|
||||
// Serial output
|
||||
static void TX(char ch) {
|
||||
if (force_using_default_output)
|
||||
SERIAL_CHAR(ch);
|
||||
else
|
||||
HAL_min_serial_out(ch);
|
||||
}
|
||||
// Send String through UART
|
||||
static void TX(const char* s) { while (*s) TX(*s++); }
|
||||
// Send a digit through UART
|
||||
static void TXDigit(uint32_t d) {
|
||||
if (d < 10) TX((char)(d+'0'));
|
||||
else if (d < 16) TX((char)(d+'A'-10));
|
||||
else TX('?');
|
||||
}
|
||||
|
||||
// Send Hex number through UART
|
||||
static void TXHex(uint32_t v) {
|
||||
TX("0x");
|
||||
for (uint8_t i = 0; i < 8; i++, v <<= 4)
|
||||
TXDigit((v >> 28) & 0xF);
|
||||
}
|
||||
|
||||
// Send Decimal number through UART
|
||||
static void TXDec(uint32_t v) {
|
||||
if (!v) {
|
||||
TX('0');
|
||||
return;
|
||||
}
|
||||
|
||||
char nbrs[14];
|
||||
char *p = &nbrs[0];
|
||||
while (v != 0) {
|
||||
*p++ = '0' + (v % 10);
|
||||
v /= 10;
|
||||
}
|
||||
do {
|
||||
p--;
|
||||
TX(*p);
|
||||
} while (p != &nbrs[0]);
|
||||
}
|
||||
static void init() { if (!force_using_default_output) HAL_min_serial_init(); }
|
||||
};
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "unwinder.h"
|
||||
#include "unwmemaccess.h"
|
||||
|
||||
#include "../../../core/serial.h"
|
||||
#include "../HAL_MinSerial.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
// Dump a backtrace entry
|
||||
@@ -34,10 +34,12 @@ static bool UnwReportOut(void* ctx, const UnwReport* bte) {
|
||||
|
||||
(*p)++;
|
||||
|
||||
SERIAL_CHAR('#'); SERIAL_ECHO(*p); SERIAL_ECHOPGM(" : ");
|
||||
SERIAL_ECHOPGM(bte->name ? bte->name : "unknown"); SERIAL_ECHOPGM("@0x"); SERIAL_PRINT(bte->function, PrintBase::Hex);
|
||||
SERIAL_CHAR('+'); SERIAL_ECHO(bte->address - bte->function);
|
||||
SERIAL_ECHOPGM(" PC:"); SERIAL_PRINT(bte->address, PrintBase::Hex); SERIAL_CHAR('\n');
|
||||
const uint32_t a = bte->address, f = bte->function;
|
||||
MinSerial::TX('#'); MinSerial::TXDec(*p); MinSerial::TX(" : ");
|
||||
MinSerial::TX(bte->name?:"unknown"); MinSerial::TX('@'); MinSerial::TXHex(f);
|
||||
MinSerial::TX('+'); MinSerial::TXDec(a - f);
|
||||
MinSerial::TX(" PC:"); MinSerial::TXHex(a);
|
||||
MinSerial::TX('\n');
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,7 +50,7 @@ static bool UnwReportOut(void* ctx, const UnwReport* bte) {
|
||||
va_start(argptr, format);
|
||||
vsprintf(dest, format, argptr);
|
||||
va_end(argptr);
|
||||
TX(&dest[0]);
|
||||
MinSerial::TX(&dest[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -63,10 +65,10 @@ static const UnwindCallbacks UnwCallbacks = {
|
||||
#endif
|
||||
};
|
||||
|
||||
// Perform a backtrace to the serial port
|
||||
void backtrace() {
|
||||
|
||||
UnwindFrame btf;
|
||||
uint32_t sp = 0, lr = 0, pc = 0;
|
||||
unsigned long sp = 0, lr = 0, pc = 0;
|
||||
|
||||
// Capture the values of the registers to perform the traceback
|
||||
__asm__ __volatile__ (
|
||||
@@ -79,6 +81,12 @@ void backtrace() {
|
||||
::
|
||||
);
|
||||
|
||||
backtrace_ex(sp, lr, pc);
|
||||
}
|
||||
|
||||
void backtrace_ex(unsigned long sp, unsigned long lr, unsigned long pc) {
|
||||
UnwindFrame btf;
|
||||
|
||||
// Fill the traceback structure
|
||||
btf.sp = sp;
|
||||
btf.fp = btf.sp;
|
||||
@@ -86,7 +94,7 @@ void backtrace() {
|
||||
btf.pc = pc | 1; // Force Thumb, as CORTEX only support it
|
||||
|
||||
// Perform a backtrace
|
||||
SERIAL_ERROR_MSG("Backtrace:");
|
||||
MinSerial::TX("Backtrace:");
|
||||
int ctr = 0;
|
||||
UnwindStart(&btf, &UnwCallbacks, &ctr);
|
||||
}
|
||||
@@ -95,4 +103,4 @@ void backtrace() {
|
||||
|
||||
void backtrace() {}
|
||||
|
||||
#endif
|
||||
#endif // __arm__ || __thumb__
|
||||
|
||||
@@ -23,3 +23,6 @@
|
||||
|
||||
// Perform a backtrace to the serial port
|
||||
void backtrace();
|
||||
|
||||
// Perform a backtrace to the serial port
|
||||
void backtrace_ex(unsigned long sp, unsigned long lr, unsigned long pc);
|
||||
|
||||
@@ -41,27 +41,16 @@
|
||||
#define START_FLASH_ADDR 0x00000000
|
||||
#define END_FLASH_ADDR 0x00080000
|
||||
|
||||
#elif 0
|
||||
|
||||
// For STM32F103CBT6
|
||||
// SRAM (0x20000000 - 0x20005000) (20kb)
|
||||
// FLASH (0x00000000 - 0x00020000) (128kb)
|
||||
//
|
||||
#define START_SRAM_ADDR 0x20000000
|
||||
#define END_SRAM_ADDR 0x20005000
|
||||
#define START_FLASH_ADDR 0x00000000
|
||||
#define END_FLASH_ADDR 0x00020000
|
||||
|
||||
#elif defined(__STM32F1__) || defined(STM32F1xx) || defined(STM32F0xx)
|
||||
|
||||
// For STM32F103ZET6/STM32F103VET6/STM32F0xx
|
||||
// SRAM (0x20000000 - 0x20010000) (64kb)
|
||||
// FLASH (0x00000000 - 0x00080000) (512kb)
|
||||
// FLASH (0x08000000 - 0x08080000) (512kb)
|
||||
//
|
||||
#define START_SRAM_ADDR 0x20000000
|
||||
#define END_SRAM_ADDR 0x20010000
|
||||
#define START_FLASH_ADDR 0x00000000
|
||||
#define END_FLASH_ADDR 0x00080000
|
||||
#define START_FLASH_ADDR 0x08000000
|
||||
#define END_FLASH_ADDR 0x08080000
|
||||
|
||||
#elif defined(STM32F4) || defined(STM32F4xx)
|
||||
|
||||
@@ -142,20 +131,57 @@
|
||||
#define START_FLASH_ADDR 0x00000000
|
||||
#define END_FLASH_ADDR 0x00100000
|
||||
|
||||
#else
|
||||
// Generic ARM code, that's testing if an access to the given address would cause a fault or not
|
||||
// It can't guarantee an address is in RAM or Flash only, but we usually don't care
|
||||
|
||||
#define NVIC_FAULT_STAT 0xE000ED28 // Configurable Fault Status Reg.
|
||||
#define NVIC_CFG_CTRL 0xE000ED14 // Configuration Control Register
|
||||
#define NVIC_FAULT_STAT_BFARV 0x00008000 // BFAR is valid
|
||||
#define NVIC_CFG_CTRL_BFHFNMIGN 0x00000100 // Ignore bus fault in NMI/fault
|
||||
#define HW_REG(X) (*((volatile unsigned long *)(X)))
|
||||
|
||||
static bool validate_addr(uint32_t read_address) {
|
||||
bool works = true;
|
||||
uint32_t intDisabled = 0;
|
||||
// Read current interrupt state
|
||||
__asm__ __volatile__ ("MRS %[result], PRIMASK\n\t" : [result]"=r"(intDisabled) :: ); // 0 is int enabled, 1 for disabled
|
||||
|
||||
// Clear bus fault indicator first (write 1 to clear)
|
||||
HW_REG(NVIC_FAULT_STAT) |= NVIC_FAULT_STAT_BFARV;
|
||||
// Ignore bus fault interrupt
|
||||
HW_REG(NVIC_CFG_CTRL) |= NVIC_CFG_CTRL_BFHFNMIGN;
|
||||
// Disable interrupts if not disabled previously
|
||||
if (!intDisabled) __asm__ __volatile__ ("CPSID f");
|
||||
// Probe address
|
||||
*(volatile uint32_t*)read_address;
|
||||
// Check if a fault happened
|
||||
if ((HW_REG(NVIC_FAULT_STAT) & NVIC_FAULT_STAT_BFARV) != 0)
|
||||
works = false;
|
||||
// Enable interrupts again if previously disabled
|
||||
if (!intDisabled) __asm__ __volatile__ ("CPSIE f");
|
||||
// Enable fault interrupt flag
|
||||
HW_REG(NVIC_CFG_CTRL) &= ~NVIC_CFG_CTRL_BFHFNMIGN;
|
||||
|
||||
return works;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static bool validate_addr(uint32_t addr) {
|
||||
#ifdef START_SRAM_ADDR
|
||||
static bool validate_addr(uint32_t addr) {
|
||||
|
||||
// Address must be in SRAM range
|
||||
if (addr >= START_SRAM_ADDR && addr < END_SRAM_ADDR)
|
||||
return true;
|
||||
// Address must be in SRAM range
|
||||
if (addr >= START_SRAM_ADDR && addr < END_SRAM_ADDR)
|
||||
return true;
|
||||
|
||||
// Or in FLASH range
|
||||
if (addr >= START_FLASH_ADDR && addr < END_FLASH_ADDR)
|
||||
return true;
|
||||
// Or in FLASH range
|
||||
if (addr >= START_FLASH_ADDR && addr < END_FLASH_ADDR)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool UnwReadW(const uint32_t a, uint32_t *v) {
|
||||
if (!validate_addr(a))
|
||||
|
||||
@@ -0,0 +1,379 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
* Copyright (c) 2020 Cyril Russo
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
* ARM CPU Exception handler
|
||||
***************************************************************************/
|
||||
|
||||
#if defined(__arm__) || defined(__thumb__)
|
||||
|
||||
|
||||
/*
|
||||
On ARM CPUs exception handling is quite powerful.
|
||||
|
||||
By default, upon a crash, the CPU enters the handlers that have a higher priority than any other interrupts,
|
||||
so, in effect, no (real) interrupt can "interrupt" the handler (it's acting like if interrupts were disabled).
|
||||
|
||||
If the handler is not called as re-entrant (that is, if the crash is not happening inside an interrupt or an handler),
|
||||
then it'll patch the return address to a dumping function (resume_from_fault) and save the crash state.
|
||||
The CPU will exit the handler and, as such, re-allow the other interrupts, and jump to the dumping function.
|
||||
In this function, the usual serial port (USB / HW) will be used to dump the crash (no special configuration required).
|
||||
|
||||
The only case where it requires hardware UART is when it's crashing in an interrupt or a crash handler.
|
||||
In that case, instead of returning to the resume_from_fault function (and thus, re-enabling interrupts),
|
||||
it jumps to this function directly (so with interrupts disabled), after changing the behavior of the serial output
|
||||
wrapper to use the HW uart (and in effect, calling MinSerial::init which triggers a warning if you are using
|
||||
a USB serial port).
|
||||
|
||||
In the case you have a USB serial port, this part will be disabled, and only that part (so that's the reason for
|
||||
the warning).
|
||||
This means that you can't have a crash report if the crash happens in an interrupt or an handler if you are using
|
||||
a USB serial port since it's physically impossible.
|
||||
You will get a crash report in all other cases.
|
||||
*/
|
||||
|
||||
#include "exception_hook.h"
|
||||
#include "../backtrace/backtrace.h"
|
||||
#include "../HAL_MinSerial.h"
|
||||
|
||||
#define HW_REG(X) (*((volatile unsigned long *)(X)))
|
||||
|
||||
// Default function use the CPU VTOR register to get the vector table.
|
||||
// Accessing the CPU VTOR register is done in assembly since it's the only way that's common to all current tool
|
||||
unsigned long get_vtor() { return HW_REG(0xE000ED08); } // Even if it looks like an error, it is not an error
|
||||
void * hook_get_hardfault_vector_address(unsigned vtor) { return (void*)(vtor + 0x03); }
|
||||
void * hook_get_memfault_vector_address(unsigned vtor) { return (void*)(vtor + 0x04); }
|
||||
void * hook_get_busfault_vector_address(unsigned vtor) { return (void*)(vtor + 0x05); }
|
||||
void * hook_get_usagefault_vector_address(unsigned vtor) { return (void*)(vtor + 0x06); }
|
||||
void * hook_get_reserved_vector_address(unsigned vtor) { return (void*)(vtor + 0x07); }
|
||||
|
||||
// Common exception frame for ARM, should work for all ARM CPU
|
||||
// Described here (modified for convenience): https://interrupt.memfault.com/blog/cortex-m-fault-debug
|
||||
struct __attribute__((packed)) ContextStateFrame {
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r12;
|
||||
uint32_t lr;
|
||||
uint32_t pc;
|
||||
uint32_t xpsr;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) ContextSavedFrame {
|
||||
uint32_t R0;
|
||||
uint32_t R1;
|
||||
uint32_t R2;
|
||||
uint32_t R3;
|
||||
uint32_t R12;
|
||||
uint32_t LR;
|
||||
uint32_t PC;
|
||||
uint32_t XPSR;
|
||||
|
||||
uint32_t CFSR;
|
||||
uint32_t HFSR;
|
||||
uint32_t DFSR;
|
||||
uint32_t AFSR;
|
||||
uint32_t MMAR;
|
||||
uint32_t BFAR;
|
||||
|
||||
uint32_t ESP;
|
||||
uint32_t ELR;
|
||||
};
|
||||
|
||||
#if DISABLED(STM32F0xx)
|
||||
extern "C"
|
||||
__attribute__((naked)) void CommonHandler_ASM() {
|
||||
__asm__ __volatile__ (
|
||||
// Bit 2 of LR tells which stack pointer to use (either main or process, only main should be used anyway)
|
||||
"tst lr, #4\n"
|
||||
"ite eq\n"
|
||||
"mrseq r0, msp\n"
|
||||
"mrsne r0, psp\n"
|
||||
// Save the LR in use when being interrupted
|
||||
"mov r1, lr\n"
|
||||
// Get the exception number from the ICSR register
|
||||
"ldr r2, =0xE000ED00\n"
|
||||
"ldr r2, [r2, #4]\n"
|
||||
"b CommonHandler_C\n"
|
||||
);
|
||||
}
|
||||
#else // Cortex M0 does not support conditional mov and testing with a constant, so let's have a specific handler for it
|
||||
extern "C"
|
||||
__attribute__((naked)) void CommonHandler_ASM() {
|
||||
__asm__ __volatile__ (
|
||||
".syntax unified\n"
|
||||
// Save the LR in use when being interrupted
|
||||
"mov r1, lr\n"
|
||||
// Get the exception number from the ICSR register
|
||||
"ldr r2, =0xE000ED00\n"
|
||||
"ldr r2, [r2, #4]\n"
|
||||
"movs r0, #4\n"
|
||||
"tst r1, r0\n"
|
||||
"beq _MSP\n"
|
||||
"mrs r0, psp\n"
|
||||
"b CommonHandler_C\n"
|
||||
"_MSP:\n"
|
||||
"mrs r0, msp\n"
|
||||
"b CommonHandler_C\n"
|
||||
);
|
||||
}
|
||||
|
||||
#if DISABLED(DYNAMIC_VECTORTABLE) // Cortex M0 requires the handler's address to be within 32kB to the actual function to be able to branch to it
|
||||
extern "C" {
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __exc_hardfault();
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __exc_busfault();
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __exc_usagefault();
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __exc_memmanage();
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __exc_nmi();
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __stm32reservedexception7();
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __stm32reservedexception8();
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __stm32reservedexception9();
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __stm32reservedexception10();
|
||||
void __attribute__((naked, alias("CommonHandler_ASM"), nothrow)) __stm32reservedexception13();
|
||||
}
|
||||
//TODO When going off from libmaple, you'll need to replace those by the one from STM32/HAL_MinSerial.cpp
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Must be a macro to avoid creating a function frame
|
||||
#define HALT_IF_DEBUGGING() \
|
||||
do { \
|
||||
if (HW_REG(0xE000EDF0) & _BV(0)) { \
|
||||
__asm("bkpt 1"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Resume from a fault (if possible) so we can still use interrupt based code for serial output
|
||||
// In that case, we will not jump back to the faulty code, but instead to a dumping code and then a
|
||||
// basic loop with watchdog calling or manual resetting
|
||||
static ContextSavedFrame savedFrame;
|
||||
static uint8_t lastCause;
|
||||
bool resume_from_fault() {
|
||||
static const char* causestr[] = { "Thread", "Rsvd", "NMI", "Hard", "Mem", "Bus", "Usage", "7", "8", "9", "10", "SVC", "Dbg", "13", "PendSV", "SysTk", "IRQ" };
|
||||
// Reinit the serial link (might only work if implemented in each of your boards)
|
||||
MinSerial::init();
|
||||
|
||||
MinSerial::TX("\n\n## Software Fault detected ##\n");
|
||||
MinSerial::TX("Cause: "); MinSerial::TX(causestr[min(lastCause, (uint8_t)16)]); MinSerial::TX('\n');
|
||||
|
||||
MinSerial::TX("R0 : "); MinSerial::TXHex(savedFrame.R0); MinSerial::TX('\n');
|
||||
MinSerial::TX("R1 : "); MinSerial::TXHex(savedFrame.R1); MinSerial::TX('\n');
|
||||
MinSerial::TX("R2 : "); MinSerial::TXHex(savedFrame.R2); MinSerial::TX('\n');
|
||||
MinSerial::TX("R3 : "); MinSerial::TXHex(savedFrame.R3); MinSerial::TX('\n');
|
||||
MinSerial::TX("R12 : "); MinSerial::TXHex(savedFrame.R12); MinSerial::TX('\n');
|
||||
MinSerial::TX("LR : "); MinSerial::TXHex(savedFrame.LR); MinSerial::TX('\n');
|
||||
MinSerial::TX("PC : "); MinSerial::TXHex(savedFrame.PC); MinSerial::TX('\n');
|
||||
MinSerial::TX("PSR : "); MinSerial::TXHex(savedFrame.XPSR); MinSerial::TX('\n');
|
||||
|
||||
// Configurable Fault Status Register
|
||||
// Consists of MMSR, BFSR and UFSR
|
||||
MinSerial::TX("CFSR : "); MinSerial::TXHex(savedFrame.CFSR); MinSerial::TX('\n');
|
||||
|
||||
// Hard Fault Status Register
|
||||
MinSerial::TX("HFSR : "); MinSerial::TXHex(savedFrame.HFSR); MinSerial::TX('\n');
|
||||
|
||||
// Debug Fault Status Register
|
||||
MinSerial::TX("DFSR : "); MinSerial::TXHex(savedFrame.DFSR); MinSerial::TX('\n');
|
||||
|
||||
// Auxiliary Fault Status Register
|
||||
MinSerial::TX("AFSR : "); MinSerial::TXHex(savedFrame.AFSR); MinSerial::TX('\n');
|
||||
|
||||
// Read the Fault Address Registers. These may not contain valid values.
|
||||
// Check BFARVALID/MMARVALID to see if they are valid values
|
||||
// MemManage Fault Address Register
|
||||
MinSerial::TX("MMAR : "); MinSerial::TXHex(savedFrame.MMAR); MinSerial::TX('\n');
|
||||
|
||||
// Bus Fault Address Register
|
||||
MinSerial::TX("BFAR : "); MinSerial::TXHex(savedFrame.BFAR); MinSerial::TX('\n');
|
||||
|
||||
MinSerial::TX("ExcLR: "); MinSerial::TXHex(savedFrame.ELR); MinSerial::TX('\n');
|
||||
MinSerial::TX("ExcSP: "); MinSerial::TXHex(savedFrame.ESP); MinSerial::TX('\n');
|
||||
|
||||
// The stack pointer is pushed by 8 words upon entering an exception, so we need to revert this
|
||||
backtrace_ex(savedFrame.ESP + 8*4, savedFrame.LR, savedFrame.PC);
|
||||
|
||||
// Call the last resort function here
|
||||
hook_last_resort_func();
|
||||
|
||||
const uint32_t start = millis(), end = start + 100; // 100ms should be enough
|
||||
// We need to wait for the serial buffers to be output but we don't know for how long
|
||||
// So we'll just need to refresh the watchdog for a while and then stop for the system to reboot
|
||||
uint32_t last = start;
|
||||
while (PENDING(last, end)) {
|
||||
watchdog_refresh();
|
||||
while (millis() == last) { /* nada */ }
|
||||
last = millis();
|
||||
MinSerial::TX('.');
|
||||
}
|
||||
|
||||
// Reset now by reinstantiating the bootloader's vector table
|
||||
HW_REG(0xE000ED08) = 0;
|
||||
// Restart watchdog
|
||||
#if DISABLED(USE_WATCHDOG)
|
||||
// No watchdog, let's perform ARMv7 reset instead by writing to AIRCR register with VECTKEY set to SYSRESETREQ
|
||||
HW_REG(0xE000ED0C) = (HW_REG(0xE000ED0C) & 0x0000FFFF) | 0x05FA0004;
|
||||
#endif
|
||||
|
||||
while(1) {} // Bad luck, nothing worked
|
||||
}
|
||||
|
||||
// Make sure the compiler does not optimize the frame argument away
|
||||
extern "C"
|
||||
__attribute__((optimize("O0")))
|
||||
void CommonHandler_C(ContextStateFrame * frame, unsigned long lr, unsigned long cause) {
|
||||
|
||||
// If you are using it'll stop here
|
||||
HALT_IF_DEBUGGING();
|
||||
|
||||
// Save the state to backtrace later on (don't call memcpy here since the stack can be corrupted)
|
||||
savedFrame.R0 = frame->r0;
|
||||
savedFrame.R1 = frame->r1;
|
||||
savedFrame.R2 = frame->r2;
|
||||
savedFrame.R3 = frame->r3;
|
||||
savedFrame.R12 = frame->r12;
|
||||
savedFrame.LR = frame->lr;
|
||||
savedFrame.PC = frame->pc;
|
||||
savedFrame.XPSR= frame->xpsr;
|
||||
lastCause = cause & 0x1FF;
|
||||
|
||||
volatile uint32_t &CFSR = HW_REG(0xE000ED28);
|
||||
savedFrame.CFSR = CFSR;
|
||||
savedFrame.HFSR = HW_REG(0xE000ED2C);
|
||||
savedFrame.DFSR = HW_REG(0xE000ED30);
|
||||
savedFrame.AFSR = HW_REG(0xE000ED3C);
|
||||
savedFrame.MMAR = HW_REG(0xE000ED34);
|
||||
savedFrame.BFAR = HW_REG(0xE000ED38);
|
||||
savedFrame.ESP = (unsigned long)frame; // Even on return, this should not be overwritten by the CPU
|
||||
savedFrame.ELR = lr;
|
||||
|
||||
// First check if we can resume from this exception to our own handler safely
|
||||
// If we can, then we don't need to disable interrupts and the usual serial code
|
||||
// can be used
|
||||
|
||||
//const uint32_t non_usage_fault_mask = 0x0000FFFF;
|
||||
//const bool non_usage_fault_occurred = (CFSR & non_usage_fault_mask) != 0;
|
||||
// the bottom 8 bits of the xpsr hold the exception number of the
|
||||
// executing exception or 0 if the processor is in Thread mode
|
||||
const bool faulted_from_exception = ((frame->xpsr & 0xFF) != 0);
|
||||
if (!faulted_from_exception) { // Not sure about the non_usage_fault, we want to try anyway, don't we ? && !non_usage_fault_occurred)
|
||||
// Try to resume to our handler here
|
||||
CFSR |= CFSR; // The ARM programmer manual says you must write to 1 all fault bits to clear them so this instruction is correct
|
||||
// The frame will not be valid when returning anymore, let's clean it
|
||||
savedFrame.CFSR = 0;
|
||||
|
||||
frame->pc = (uint32_t)resume_from_fault; // Patch where to return to
|
||||
frame->lr = 0xDEADBEEF; // If our handler returns (it shouldn't), let's make it trigger an exception immediately
|
||||
frame->xpsr = _BV(24); // Need to clean the PSR register to thumb II only
|
||||
MinSerial::force_using_default_output = true;
|
||||
return; // The CPU will resume in our handler hopefully, and we'll try to use default serial output
|
||||
}
|
||||
|
||||
// Sorry, we need to emergency code here since the fault is too dangerous to recover from
|
||||
MinSerial::force_using_default_output = false;
|
||||
resume_from_fault();
|
||||
}
|
||||
|
||||
void hook_cpu_exceptions() {
|
||||
#if ENABLED(DYNAMIC_VECTORTABLE)
|
||||
// On ARM 32bits CPU, the vector table is like this:
|
||||
// 0x0C => Hardfault
|
||||
// 0x10 => MemFault
|
||||
// 0x14 => BusFault
|
||||
// 0x18 => UsageFault
|
||||
|
||||
// Unfortunately, it's usually run from flash, and we can't write to flash here directly to hook our instruction
|
||||
// We could set an hardware breakpoint, and hook on the fly when it's being called, but this
|
||||
// is hard to get right and would probably break debugger when attached
|
||||
|
||||
// So instead, we'll allocate a new vector table filled with the previous value except
|
||||
// for the fault we are interested in.
|
||||
// Now, comes the issue to figure out what is the current vector table size
|
||||
// There is nothing telling us what is the vector table as it's per-cpu vendor specific.
|
||||
// BUT: we are being called at the end of the setup, so we assume the setup is done
|
||||
// Thus, we can read the current vector table until we find an address that's not in flash, and it would mark the
|
||||
// end of the vector table (skipping the fist entry obviously)
|
||||
// The position of the program in flash is expected to be at 0x08xxx xxxx on all known platform for ARM and the
|
||||
// flash size is available via register 0x1FFFF7E0 on STM32 family, but it's not the case for all ARM boards
|
||||
// (accessing this register might trigger a fault if it's not implemented).
|
||||
|
||||
// So we'll simply mask the top 8 bits of the first handler as an hint of being in the flash or not -that's poor and will
|
||||
// probably break if the flash happens to be more than 128MB, but in this case, we are not magician, we need help from outside.
|
||||
|
||||
unsigned long * vecAddr = (unsigned long*)get_vtor();
|
||||
SERIAL_ECHO("Vector table addr: ");
|
||||
SERIAL_PRINTLN(get_vtor(), HEX);
|
||||
|
||||
#ifdef VECTOR_TABLE_SIZE
|
||||
uint32_t vec_size = VECTOR_TABLE_SIZE;
|
||||
alignas(128) static unsigned long vectable[VECTOR_TABLE_SIZE] ;
|
||||
#else
|
||||
#ifndef IS_IN_FLASH
|
||||
#define IS_IN_FLASH(X) (((unsigned long)X & 0xFF000000) == 0x08000000)
|
||||
#endif
|
||||
|
||||
// When searching for the end of the vector table, this acts as a limit not to overcome
|
||||
#ifndef VECTOR_TABLE_SENTINEL
|
||||
#define VECTOR_TABLE_SENTINEL 80
|
||||
#endif
|
||||
|
||||
// Find the vector table size
|
||||
uint32_t vec_size = 1;
|
||||
while (IS_IN_FLASH(vecAddr[vec_size]) && vec_size < VECTOR_TABLE_SENTINEL)
|
||||
vec_size++;
|
||||
|
||||
// We failed to find a valid vector table size, let's abort hooking up
|
||||
if (vec_size == VECTOR_TABLE_SENTINEL) return;
|
||||
// Poor method that's wasting RAM here, but allocating with malloc and alignment would be worst
|
||||
// 128 bytes alignement is required for writing the VTOR register
|
||||
alignas(128) static unsigned long vectable[VECTOR_TABLE_SENTINEL];
|
||||
|
||||
SERIAL_ECHO("Detected vector table size: ");
|
||||
SERIAL_PRINTLN(vec_size, HEX);
|
||||
#endif
|
||||
|
||||
uint32_t defaultFaultHandler = vecAddr[(unsigned)7];
|
||||
// Copy the current vector table into the new table
|
||||
for (uint32_t i = 0; i < vec_size; i++) {
|
||||
vectable[i] = vecAddr[i];
|
||||
// Replace all default handler by our own handler
|
||||
if (vectable[i] == defaultFaultHandler)
|
||||
vectable[i] = (unsigned long)&CommonHandler_ASM;
|
||||
}
|
||||
|
||||
// Let's hook now with our functions
|
||||
vectable[(unsigned long)hook_get_hardfault_vector_address(0)] = (unsigned long)&CommonHandler_ASM;
|
||||
vectable[(unsigned long)hook_get_memfault_vector_address(0)] = (unsigned long)&CommonHandler_ASM;
|
||||
vectable[(unsigned long)hook_get_busfault_vector_address(0)] = (unsigned long)&CommonHandler_ASM;
|
||||
vectable[(unsigned long)hook_get_usagefault_vector_address(0)] = (unsigned long)&CommonHandler_ASM;
|
||||
|
||||
// Finally swap with our own vector table
|
||||
// This is supposed to be atomic, but let's do that with interrupt disabled
|
||||
|
||||
HW_REG(0xE000ED08) = (unsigned long)vectable | _BV32(29); // 29th bit is for telling the CPU the table is now in SRAM (should be present already)
|
||||
|
||||
SERIAL_ECHOLN("Installed fault handlers");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // __arm__ || __thumb__
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "exception_hook.h"
|
||||
|
||||
void * __attribute__((weak)) hook_get_hardfault_vector_address(unsigned) { return 0; }
|
||||
void * __attribute__((weak)) hook_get_memfault_vector_address(unsigned) { return 0; }
|
||||
void * __attribute__((weak)) hook_get_busfault_vector_address(unsigned) { return 0; }
|
||||
void * __attribute__((weak)) hook_get_usagefault_vector_address(unsigned) { return 0; }
|
||||
void __attribute__((weak)) hook_last_resort_func() {}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* Here is the expected behavior of a system producing a CPU exception with this hook installed:
|
||||
1. Before the system is crashed
|
||||
1.1 Upon validation (not done yet in this code, but we could be using DEBUG flags here to allow/disallow hooking)
|
||||
1.2 Install the hook by overwriting the vector table exception handler with the hooked function
|
||||
2. Upon system crash (for example, by a dereference of a NULL pointer or anything else)
|
||||
2.1 The CPU triggers its exception and jump into the vector table for the exception type
|
||||
2.2 Instead of finding the default handler, it finds the updated pointer to our hook
|
||||
2.3 The CPU jumps into our hook function (likely a naked function to keep all information about crash point intact)
|
||||
2.4 The hook (naked) function saves the important registers (stack pointer, program counter, current mode) and jumps to a common exception handler (in C)
|
||||
2.5 The common exception handler dumps the registers on the serial link and perform a backtrace around the crashing point
|
||||
2.6 Once the backtrace is performed the last resort function is called (platform specific).
|
||||
On some platform with a LCD screen, this might display the crash information as a QR code or as text for the
|
||||
user to capture by taking a picture
|
||||
2.7 The CPU is reset and/or halted by triggering a debug breakpoint if a debugger is attached */
|
||||
|
||||
// Hook into CPU exception interrupt table to call the backtracing code upon an exception
|
||||
// Most platform will simply do nothing here, but those who can will install/overwrite the default exception handler
|
||||
// with a more performant exception handler
|
||||
void hook_cpu_exceptions();
|
||||
|
||||
// Some platform might deal without a hard fault handler, in that case, return 0 in your platform here or skip implementing it
|
||||
void * __attribute__((weak)) hook_get_hardfault_vector_address(unsigned base_address);
|
||||
// Some platform might deal without a memory management fault handler, in that case, return 0 in your platform here or skip implementing it
|
||||
void * __attribute__((weak)) hook_get_memfault_vector_address(unsigned base_address);
|
||||
// Some platform might deal without a bus fault handler, in that case, return 0 in your platform here or skip implementing it
|
||||
void * __attribute__((weak)) hook_get_busfault_vector_address(unsigned base_address);
|
||||
// Some platform might deal without a usage fault handler, in that case, return 0 in your platform here or skip implementing it
|
||||
void * __attribute__((weak)) hook_get_usagefault_vector_address(unsigned base_address);
|
||||
|
||||
// Last resort function that can be called after the exception handler was called.
|
||||
void __attribute__((weak)) hook_last_resort_func();
|
||||
@@ -25,5 +25,5 @@
|
||||
// EEPROM
|
||||
//
|
||||
void eeprom_init();
|
||||
void eeprom_write_byte(uint8_t *pos, unsigned char value);
|
||||
void eeprom_write_byte(uint8_t *pos, uint8_t value);
|
||||
uint8_t eeprom_read_byte(uint8_t *pos);
|
||||
|
||||
@@ -32,7 +32,13 @@
|
||||
#include "eeprom_if.h"
|
||||
#include <Wire.h>
|
||||
|
||||
void eeprom_init() { Wire.begin(); }
|
||||
void eeprom_init() {
|
||||
Wire.begin(
|
||||
#if PINS_EXIST(I2C_SCL, I2C_SDA)
|
||||
uint8_t(I2C_SDA_PIN), uint8_t(I2C_SCL_PIN)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
#if ENABLED(USE_SHARED_EEPROM)
|
||||
|
||||
@@ -49,12 +55,15 @@ static constexpr uint8_t eeprom_device_address = I2C_ADDRESS(EEPROM_DEVICE_ADDRE
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
void eeprom_write_byte(uint8_t *pos, unsigned char value) {
|
||||
static void _eeprom_begin(uint8_t * const pos) {
|
||||
const unsigned eeprom_address = (unsigned)pos;
|
||||
|
||||
Wire.beginTransmission(eeprom_device_address);
|
||||
Wire.write(int(eeprom_address >> 8)); // MSB
|
||||
Wire.write(int(eeprom_address & 0xFF)); // LSB
|
||||
Wire.write(int(eeprom_address >> 8)); // Address High
|
||||
Wire.write(int(eeprom_address & 0xFF)); // Address Low
|
||||
}
|
||||
|
||||
void eeprom_write_byte(uint8_t *pos, uint8_t value) {
|
||||
_eeprom_begin(pos);
|
||||
Wire.write(value);
|
||||
Wire.endTransmission();
|
||||
|
||||
@@ -64,11 +73,7 @@ void eeprom_write_byte(uint8_t *pos, unsigned char value) {
|
||||
}
|
||||
|
||||
uint8_t eeprom_read_byte(uint8_t *pos) {
|
||||
const unsigned eeprom_address = (unsigned)pos;
|
||||
|
||||
Wire.beginTransmission(eeprom_device_address);
|
||||
Wire.write(int(eeprom_address >> 8)); // MSB
|
||||
Wire.write(int(eeprom_address & 0xFF)); // LSB
|
||||
_eeprom_begin(pos);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(eeprom_device_address, (byte)1);
|
||||
return Wire.available() ? Wire.read() : 0xFF;
|
||||
|
||||
@@ -43,44 +43,41 @@ void eeprom_init() {}
|
||||
#define EEPROM_WRITE_DELAY 7
|
||||
#endif
|
||||
|
||||
uint8_t eeprom_read_byte(uint8_t* pos) {
|
||||
uint8_t v;
|
||||
uint8_t eeprom_temp[3];
|
||||
|
||||
// set read location
|
||||
// begin transmission from device
|
||||
eeprom_temp[0] = CMD_READ;
|
||||
eeprom_temp[1] = ((unsigned)pos>>8) & 0xFF; // addr High
|
||||
eeprom_temp[2] = (unsigned)pos& 0xFF; // addr Low
|
||||
WRITE(SPI_EEPROM1_CS, HIGH);
|
||||
WRITE(SPI_EEPROM1_CS, LOW);
|
||||
static void _eeprom_begin(uint8_t * const pos, const uint8_t cmd) {
|
||||
const uint8_t eeprom_temp[3] = {
|
||||
cmd,
|
||||
(unsigned(pos) >> 8) & 0xFF, // Address High
|
||||
unsigned(pos) & 0xFF // Address Low
|
||||
};
|
||||
WRITE(SPI_EEPROM1_CS, HIGH); // Usually free already
|
||||
WRITE(SPI_EEPROM1_CS, LOW); // Activate the Bus
|
||||
spiSend(SPI_CHAN_EEPROM1, eeprom_temp, 3);
|
||||
// Leave the Bus in-use
|
||||
}
|
||||
|
||||
uint8_t eeprom_read_byte(uint8_t* pos) {
|
||||
_eeprom_begin(pos, CMD_READ); // Set read location and begin transmission
|
||||
|
||||
const uint8_t v = spiRec(SPI_CHAN_EEPROM1); // After READ a value sits on the Bus
|
||||
|
||||
WRITE(SPI_EEPROM1_CS, HIGH); // Done with device
|
||||
|
||||
v = spiRec(SPI_CHAN_EEPROM1);
|
||||
WRITE(SPI_EEPROM1_CS, HIGH);
|
||||
return v;
|
||||
}
|
||||
|
||||
void eeprom_write_byte(uint8_t* pos, uint8_t value) {
|
||||
uint8_t eeprom_temp[3];
|
||||
|
||||
/*write enable*/
|
||||
eeprom_temp[0] = CMD_WREN;
|
||||
void eeprom_write_byte(uint8_t *pos, uint8_t value) {
|
||||
const uint8_t eeprom_temp = CMD_WREN;
|
||||
WRITE(SPI_EEPROM1_CS, LOW);
|
||||
spiSend(SPI_CHAN_EEPROM1, eeprom_temp, 1);
|
||||
WRITE(SPI_EEPROM1_CS, HIGH);
|
||||
delay(1);
|
||||
spiSend(SPI_CHAN_EEPROM1, &eeprom_temp, 1); // Write Enable
|
||||
|
||||
/*write addr*/
|
||||
eeprom_temp[0] = CMD_WRITE;
|
||||
eeprom_temp[1] = ((unsigned)pos>>8) & 0xFF; //addr High
|
||||
eeprom_temp[2] = (unsigned)pos & 0xFF; //addr Low
|
||||
WRITE(SPI_EEPROM1_CS, LOW);
|
||||
spiSend(SPI_CHAN_EEPROM1, eeprom_temp, 3);
|
||||
WRITE(SPI_EEPROM1_CS, HIGH); // Done with the Bus
|
||||
delay(1); // For a small amount of time
|
||||
|
||||
spiSend(SPI_CHAN_EEPROM1, value);
|
||||
WRITE(SPI_EEPROM1_CS, HIGH);
|
||||
delay(EEPROM_WRITE_DELAY); // wait for page write to complete
|
||||
_eeprom_begin(pos, CMD_WRITE); // Set write address and begin transmission
|
||||
|
||||
spiSend(SPI_CHAN_EEPROM1, value); // Send the value to be written
|
||||
WRITE(SPI_EEPROM1_CS, HIGH); // Done with the Bus
|
||||
delay(EEPROM_WRITE_DELAY); // Give page write time to complete
|
||||
}
|
||||
|
||||
#endif // USE_SHARED_EEPROM
|
||||
|
||||
+299
-53
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "HAL/shared/Delay.h"
|
||||
#include "HAL/shared/esp_wifi.h"
|
||||
#include "HAL/shared/cpu_exception/exception_hook.h"
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <pins_arduino.h>
|
||||
@@ -230,6 +231,10 @@
|
||||
#include "feature/password/password.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(DGUS_LCD_UI_MKS)
|
||||
#include "lcd/extui/lib/dgus/DGUSScreenHandler.h"
|
||||
#endif
|
||||
|
||||
PGMSTR(M112_KILL_STR, "M112 Shutdown");
|
||||
|
||||
MarlinState marlin_state = MF_INITIALIZING;
|
||||
@@ -387,6 +392,7 @@ void startOrResumeJob() {
|
||||
if (queue.enqueue_one_P(PSTR("M1001"))) {
|
||||
marlin_state = MF_RUNNING;
|
||||
TERN_(PASSWORD_AFTER_SD_PRINT_END, password.lock_machine());
|
||||
TERN_(DGUS_LCD_UI_MKS, ScreenHandler.SDPrintingFinished());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,13 +406,14 @@ void startOrResumeJob() {
|
||||
* - Check if CHDK_PIN needs to go LOW
|
||||
* - Check for KILL button held down
|
||||
* - Check for HOME button held down
|
||||
* - Check for CUSTOM USER button held down
|
||||
* - Check if cooling fan needs to be switched on
|
||||
* - Check if an idle but hot extruder needs filament extruded (EXTRUDER_RUNOUT_PREVENT)
|
||||
* - Pulse FET_SAFETY_PIN if it exists
|
||||
*/
|
||||
inline void manage_inactivity(const bool ignore_stepper_queue=false) {
|
||||
|
||||
if (queue.length < BUFSIZE) queue.get_available_commands();
|
||||
queue.get_available_commands();
|
||||
|
||||
const millis_t ms = millis();
|
||||
|
||||
@@ -492,6 +499,102 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLED(CUSTOM_USER_BUTTONS)
|
||||
// Handle a custom user button if defined
|
||||
const bool printer_not_busy = !printingIsActive();
|
||||
#define HAS_CUSTOM_USER_BUTTON(N) (PIN_EXISTS(BUTTON##N) && defined(BUTTON##N##_HIT_STATE) && defined(BUTTON##N##_GCODE) && defined(BUTTON##N##_DESC))
|
||||
#define CHECK_CUSTOM_USER_BUTTON(N) do{ \
|
||||
constexpr millis_t CUB_DEBOUNCE_DELAY_##N = 250UL; \
|
||||
static millis_t next_cub_ms_##N; \
|
||||
if (BUTTON##N##_HIT_STATE == READ(BUTTON##N##_PIN) \
|
||||
&& (ENABLED(BUTTON##N##_WHEN_PRINTING) || printer_not_busy)) { \
|
||||
const millis_t ms = millis(); \
|
||||
if (ELAPSED(ms, next_cub_ms_##N)) { \
|
||||
next_cub_ms_##N = ms + CUB_DEBOUNCE_DELAY_##N; \
|
||||
if (strlen(BUTTON##N##_DESC)) \
|
||||
LCD_MESSAGEPGM_P(PSTR(BUTTON##N##_DESC)); \
|
||||
queue.inject_P(PSTR(BUTTON##N##_GCODE)); \
|
||||
} \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
#if HAS_CUSTOM_USER_BUTTON(1)
|
||||
CHECK_CUSTOM_USER_BUTTON(1);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(2)
|
||||
CHECK_CUSTOM_USER_BUTTON(2);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(3)
|
||||
CHECK_CUSTOM_USER_BUTTON(3);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(4)
|
||||
CHECK_CUSTOM_USER_BUTTON(4);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(5)
|
||||
CHECK_CUSTOM_USER_BUTTON(5);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(6)
|
||||
CHECK_CUSTOM_USER_BUTTON(6);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(7)
|
||||
CHECK_CUSTOM_USER_BUTTON(7);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(8)
|
||||
CHECK_CUSTOM_USER_BUTTON(8);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(9)
|
||||
CHECK_CUSTOM_USER_BUTTON(9);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(10)
|
||||
CHECK_CUSTOM_USER_BUTTON(10);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(11)
|
||||
CHECK_CUSTOM_USER_BUTTON(11);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(12)
|
||||
CHECK_CUSTOM_USER_BUTTON(12);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(13)
|
||||
CHECK_CUSTOM_USER_BUTTON(13);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(14)
|
||||
CHECK_CUSTOM_USER_BUTTON(14);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(15)
|
||||
CHECK_CUSTOM_USER_BUTTON(15);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(16)
|
||||
CHECK_CUSTOM_USER_BUTTON(16);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(17)
|
||||
CHECK_CUSTOM_USER_BUTTON(17);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(18)
|
||||
CHECK_CUSTOM_USER_BUTTON(18);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(19)
|
||||
CHECK_CUSTOM_USER_BUTTON(19);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(20)
|
||||
CHECK_CUSTOM_USER_BUTTON(20);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(21)
|
||||
CHECK_CUSTOM_USER_BUTTON(21);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(22)
|
||||
CHECK_CUSTOM_USER_BUTTON(22);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(23)
|
||||
CHECK_CUSTOM_USER_BUTTON(23);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(24)
|
||||
CHECK_CUSTOM_USER_BUTTON(24);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(25)
|
||||
CHECK_CUSTOM_USER_BUTTON(25);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TERN_(USE_CONTROLLER_FAN, controllerFan.update()); // Check if fan should be turned on to cool stepper drivers down
|
||||
|
||||
TERN_(AUTO_POWER_CONTROL, powerManager.check());
|
||||
@@ -786,8 +889,8 @@ void stop() {
|
||||
|
||||
print_job_timer.stop();
|
||||
|
||||
#if ENABLED(PROBING_FANS_OFF)
|
||||
if (thermalManager.fans_paused) thermalManager.set_fans_paused(false); // put things back the way they were
|
||||
#if EITHER(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE)
|
||||
thermalManager.set_fans_paused(false); // Un-pause fans for safety
|
||||
#endif
|
||||
|
||||
if (IsRunning()) {
|
||||
@@ -850,25 +953,97 @@ inline void tmc_standby_setup() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Marlin entry-point: Set up before the program loop
|
||||
* - Set up the kill pin, filament runout, power hold
|
||||
* - Start the serial port
|
||||
* Marlin Firmware entry-point. Abandon Hope All Ye Who Enter Here.
|
||||
* Setup before the program loop:
|
||||
*
|
||||
* - Call any special pre-init set for the board
|
||||
* - Put TMC drivers into Low Power Standby mode
|
||||
* - Init the serial ports (so setup can be debugged)
|
||||
* - Set up the kill and suicide pins
|
||||
* - Prepare (disable) board JTAG and Debug ports
|
||||
* - Init serial for a connected MKS TFT with WiFi
|
||||
* - Install Marlin custom Exception Handlers, if set.
|
||||
* - Init Marlin's HAL interfaces (for SPI, i2c, etc.)
|
||||
* - Init some optional hardware and features:
|
||||
* • MAX Thermocouple pins
|
||||
* • Duet Smart Effector
|
||||
* • Filament Runout Sensor
|
||||
* • TMC220x Stepper Drivers (Serial)
|
||||
* • PSU control
|
||||
* • Power-loss Recovery
|
||||
* • L64XX Stepper Drivers (SPI)
|
||||
* • Stepper Driver Reset: DISABLE
|
||||
* • TMC Stepper Drivers (SPI)
|
||||
* • Run BOARD_INIT if defined
|
||||
* • ESP WiFi
|
||||
* - Get the Reset Reason and report it
|
||||
* - Print startup messages and diagnostics
|
||||
* - Get EEPROM or default settings
|
||||
* - Initialize managers for:
|
||||
* • temperature
|
||||
* • planner
|
||||
* • watchdog
|
||||
* • stepper
|
||||
* • photo pin
|
||||
* • servos
|
||||
* • LCD controller
|
||||
* • Digipot I2C
|
||||
* • Z probe sled
|
||||
* • status LEDs
|
||||
* • Max7219
|
||||
* - Calibrate the HAL DELAY for precise timing
|
||||
* - Init the buzzer, possibly a custom timer
|
||||
* - Init more optional hardware:
|
||||
* • Color LED illumination
|
||||
* • Neopixel illumination
|
||||
* • Controller Fan
|
||||
* • Creality DWIN LCD (show boot image)
|
||||
* • Tare the Probe if possible
|
||||
* - Mount the (most likely external) SD Card
|
||||
* - Load settings from EEPROM (or use defaults)
|
||||
* - Init the Ethernet Port
|
||||
* - Init Touch Buttons (for emulated DOGLCD)
|
||||
* - Adjust the (certainly wrong) current position by the home offset
|
||||
* - Init the Planner::position (steps) based on current (native) position
|
||||
* - Initialize more managers and peripherals:
|
||||
* • Temperatures
|
||||
* • Print Job Timer
|
||||
* • Endstops and Endstop Interrupts
|
||||
* • Stepper ISR - Kind of Important!
|
||||
* • Servos
|
||||
* • Servo-based Probe
|
||||
* • Photograph Pin
|
||||
* • Laser/Spindle tool Power / PWM
|
||||
* • Coolant Control
|
||||
* • Bed Probe
|
||||
* • Stepper Driver Reset: ENABLE
|
||||
* • Digipot I2C - Stepper driver current control
|
||||
* • Stepper DAC - Stepper driver current control
|
||||
* • Solenoid (probe, or for other use)
|
||||
* • Home Pin
|
||||
* • Custom User Buttons
|
||||
* • Red/Blue Status LEDs
|
||||
* • Case Light
|
||||
* • Prusa MMU filament changer
|
||||
* • Fan Multiplexer
|
||||
* • Mixing Extruder
|
||||
* • BLTouch Probe
|
||||
* • I2C Position Encoders
|
||||
* • Custom I2C Bus handlers
|
||||
* • Enhanced tools or extruders:
|
||||
* • Switching Extruder
|
||||
* • Switching Nozzle
|
||||
* • Parking Extruder
|
||||
* • Magnetic Parking Extruder
|
||||
* • Switching Toolhead
|
||||
* • Electromagnetic Switching Toolhead
|
||||
* • Watchdog Timer - Also Kind of Important!
|
||||
* • Closed Loop Controller
|
||||
* - Run Startup Commands, if defined
|
||||
* - Tell host to close Host Prompts
|
||||
* - Test Trinamic driver connections
|
||||
* - Init Prusa MMU2 filament changer
|
||||
* - Init and test BL24Cxx EEPROM
|
||||
* - Init Creality DWIN encoder, show faux progress bar
|
||||
* - Reset Status Message / Show Service Messages
|
||||
* - Init MAX7219 LED Matrix
|
||||
* - Init Direct Stepping (Klipper-style motion control)
|
||||
* - Init TFT LVGL UI (with 3D Graphics)
|
||||
* - Apply Password Lock - Hold for Authentication
|
||||
* - Open Touch Screen Calibration screen, if not calibrated
|
||||
* - Set Marlin to RUNNING State
|
||||
*/
|
||||
void setup() {
|
||||
#ifdef BOARD_PREINIT
|
||||
BOARD_PREINIT(); // Low-level init (before serial init)
|
||||
#endif
|
||||
|
||||
tmc_standby_setup(); // TMC Low Power Standby pins must be set early or they're not usable
|
||||
|
||||
@@ -876,8 +1051,7 @@ void setup() {
|
||||
auto log_current_ms = [&](PGM_P const msg) {
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_CHAR('['); SERIAL_ECHO(millis()); SERIAL_ECHOPGM("] ");
|
||||
serialprintPGM(msg);
|
||||
SERIAL_EOL();
|
||||
SERIAL_ECHOLNPGM_P(msg);
|
||||
};
|
||||
#define SETUP_LOG(M) log_current_ms(PSTR(M))
|
||||
#else
|
||||
@@ -885,14 +1059,14 @@ void setup() {
|
||||
#endif
|
||||
#define SETUP_RUN(C) do{ SETUP_LOG(STRINGIFY(C)); C; }while(0)
|
||||
|
||||
MYSERIAL0.begin(BAUDRATE);
|
||||
MYSERIAL1.begin(BAUDRATE);
|
||||
millis_t serial_connect_timeout = millis() + 1000UL;
|
||||
while (!MYSERIAL0.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
|
||||
while (!MYSERIAL1.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
|
||||
|
||||
#if HAS_MULTI_SERIAL && !HAS_ETHERNET
|
||||
MYSERIAL1.begin(BAUDRATE);
|
||||
MYSERIAL2.begin(BAUDRATE);
|
||||
serial_connect_timeout = millis() + 1000UL;
|
||||
while (!MYSERIAL1.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
|
||||
while (!MYSERIAL2.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
|
||||
#endif
|
||||
SERIAL_ECHOLNPGM("start");
|
||||
|
||||
@@ -911,12 +1085,6 @@ void setup() {
|
||||
OUT_WRITE(SUICIDE_PIN, !SUICIDE_PIN_INVERTING);
|
||||
#endif
|
||||
|
||||
#if ENABLED(PSU_CONTROL)
|
||||
SETUP_LOG("PSU_CONTROL");
|
||||
powersupply_on = ENABLED(PSU_DEFAULT_OFF);
|
||||
if (ENABLED(PSU_DEFAULT_OFF)) PSU_OFF(); else PSU_ON();
|
||||
#endif
|
||||
|
||||
#if EITHER(DISABLE_DEBUG, DISABLE_JTAG)
|
||||
// Disable any hardware debug to free up pins for IO
|
||||
#if ENABLED(DISABLE_DEBUG) && defined(JTAGSWD_DISABLE)
|
||||
@@ -935,6 +1103,8 @@ void setup() {
|
||||
while (/*!WIFISERIAL && */PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
|
||||
#endif
|
||||
|
||||
TERN_(DYNAMIC_VECTORTABLE, hook_cpu_exceptions()); // If supported, install Marlin exception handlers at runtime
|
||||
|
||||
SETUP_RUN(HAL_init());
|
||||
|
||||
// Init and disable SPI thermocouples; this is still needed
|
||||
@@ -945,10 +1115,6 @@ void setup() {
|
||||
OUT_WRITE(MAX6675_SS2_PIN, HIGH); // Disable
|
||||
#endif
|
||||
|
||||
#if HAS_L64XX
|
||||
SETUP_RUN(L64xxManager.init()); // Set up SPI, init drivers
|
||||
#endif
|
||||
|
||||
#if ENABLED(DUET_SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
|
||||
OUT_WRITE(SMART_EFFECTOR_MOD_PIN, LOW); // Put Smart Effector into NORMAL mode
|
||||
#endif
|
||||
@@ -957,12 +1123,22 @@ void setup() {
|
||||
SETUP_RUN(runout.setup());
|
||||
#endif
|
||||
|
||||
#if HAS_TMC220x
|
||||
SETUP_RUN(tmc_serial_begin());
|
||||
#endif
|
||||
|
||||
#if ENABLED(PSU_CONTROL)
|
||||
SETUP_LOG("PSU_CONTROL");
|
||||
powersupply_on = ENABLED(PSU_DEFAULT_OFF);
|
||||
if (ENABLED(PSU_DEFAULT_OFF)) PSU_OFF(); else PSU_ON();
|
||||
#endif
|
||||
|
||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||
SETUP_RUN(recovery.setup());
|
||||
#endif
|
||||
|
||||
#if HAS_TMC220x
|
||||
SETUP_RUN(tmc_serial_begin());
|
||||
#if HAS_L64XX
|
||||
SETUP_RUN(L64xxManager.init()); // Set up SPI, init drivers
|
||||
#endif
|
||||
|
||||
#if HAS_STEPPER_RESET
|
||||
@@ -992,7 +1168,7 @@ void setup() {
|
||||
if (mcu & RST_SOFTWARE) SERIAL_ECHOLNPGM(STR_SOFTWARE_RESET);
|
||||
HAL_clear_reset_source();
|
||||
|
||||
serialprintPGM(GET_TEXT(MSG_MARLIN));
|
||||
SERIAL_ECHOPGM_P(GET_TEXT(MSG_MARLIN));
|
||||
SERIAL_CHAR(' ');
|
||||
SERIAL_ECHOLNPGM(SHORT_BUILD_VERSION);
|
||||
SERIAL_EOL();
|
||||
@@ -1121,19 +1297,95 @@ void setup() {
|
||||
SET_INPUT_PULLUP(HOME_PIN);
|
||||
#endif
|
||||
|
||||
#if ENABLED(CUSTOM_USER_BUTTONS)
|
||||
#define INIT_CUSTOM_USER_BUTTON_PIN(N) do{ SET_INPUT(BUTTON##N##_PIN); WRITE(BUTTON##N##_PIN, !BUTTON##N##_HIT_STATE); }while(0)
|
||||
|
||||
#if HAS_CUSTOM_USER_BUTTON(1)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(1);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(2)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(2);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(3)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(3);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(4)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(4);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(5)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(5);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(6)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(6);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(7)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(7);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(8)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(8);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(9)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(9);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(10)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(10);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(11)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(11);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(12)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(12);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(13)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(13);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(14)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(14);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(15)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(15);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(16)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(16);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(17)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(17);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(18)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(18);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(19)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(19);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(20)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(20);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(21)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(21);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(22)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(22);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(23)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(23);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(24)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(24);
|
||||
#endif
|
||||
#if HAS_CUSTOM_USER_BUTTON(25)
|
||||
INIT_CUSTOM_USER_BUTTON_PIN(25);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PIN_EXISTS(STAT_LED_RED)
|
||||
OUT_WRITE(STAT_LED_RED_PIN, LOW); // OFF
|
||||
#endif
|
||||
|
||||
#if PIN_EXISTS(STAT_LED_BLUE)
|
||||
OUT_WRITE(STAT_LED_BLUE_PIN, LOW); // OFF
|
||||
#endif
|
||||
|
||||
#if ENABLED(CASE_LIGHT_ENABLE)
|
||||
#if DISABLED(CASE_LIGHT_USE_NEOPIXEL)
|
||||
if (PWM_PIN(CASE_LIGHT_PIN)) SET_PWM(CASE_LIGHT_PIN); else SET_OUTPUT(CASE_LIGHT_PIN);
|
||||
#endif
|
||||
SETUP_RUN(caselight.update_brightness());
|
||||
SETUP_RUN(caselight.init());
|
||||
#endif
|
||||
|
||||
#if HAS_PRUSA_MMU1
|
||||
@@ -1180,19 +1432,13 @@ void setup() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(MAGNETIC_PARKING_EXTRUDER)
|
||||
SETUP_RUN(mpe_settings_init());
|
||||
#endif
|
||||
|
||||
#if ENABLED(PARKING_EXTRUDER)
|
||||
SETUP_RUN(pe_solenoid_init());
|
||||
#endif
|
||||
|
||||
#if ENABLED(SWITCHING_TOOLHEAD)
|
||||
#elif ENABLED(MAGNETIC_PARKING_EXTRUDER)
|
||||
SETUP_RUN(mpe_settings_init());
|
||||
#elif ENABLED(SWITCHING_TOOLHEAD)
|
||||
SETUP_RUN(swt_init());
|
||||
#endif
|
||||
|
||||
#if ENABLED(ELECTROMAGNETIC_SWITCHING_TOOLHEAD)
|
||||
#elif ENABLED(ELECTROMAGNETIC_SWITCHING_TOOLHEAD)
|
||||
SETUP_RUN(est_init());
|
||||
#endif
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
#define BOARD_EINSY_RAMBO 1203 // Einsy Rambo
|
||||
#define BOARD_EINSY_RETRO 1204 // Einsy Retro
|
||||
#define BOARD_SCOOVO_X9H 1205 // abee Scoovo X9H
|
||||
#define BOARD_RAMBO_THINKERV2 1206 // ThinkerV2
|
||||
|
||||
//
|
||||
// Other ATmega1280, ATmega2560
|
||||
@@ -278,6 +279,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
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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_ECHOPAIR 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_ECHOPAIR, that is: a key-value call of the local variables you want
|
||||
// to dump to the serial port before stopping the CPU.
|
||||
#define BUG_ON(V...) do { SERIAL_ECHOPAIR(ONLY_FILENAME, __LINE__, ": "); SERIAL_ECHOLNPAIR(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
|
||||
#define BUG_ON(V...) do { SERIAL_ECHOPAIR(ONLY_FILENAME, __LINE__, ": BUG!\n"); SERIAL_ECHOLNPAIR(V); SERIAL_FLUSHTX(); } while(0)
|
||||
#else
|
||||
// Release mode, let's ignore the bug
|
||||
#define BUG_ON(V...) NOOP
|
||||
#endif
|
||||
@@ -27,7 +27,7 @@
|
||||
//
|
||||
|
||||
#undef DEBUG_SECTION
|
||||
#undef DEBUG_PRINT_P
|
||||
#undef DEBUG_ECHOPGM_P
|
||||
#undef DEBUG_ECHO_START
|
||||
#undef DEBUG_ERROR_START
|
||||
#undef DEBUG_CHAR
|
||||
@@ -59,7 +59,7 @@
|
||||
#include "debug_section.h"
|
||||
#define DEBUG_SECTION(N,S,D) SectionLog N(PSTR(S),D)
|
||||
|
||||
#define DEBUG_PRINT_P(P) serialprintPGM(P)
|
||||
#define DEBUG_ECHOPGM_P(P) SERIAL_ECHOPGM_P(P)
|
||||
#define DEBUG_ECHO_START SERIAL_ECHO_START
|
||||
#define DEBUG_ERROR_START SERIAL_ERROR_START
|
||||
#define DEBUG_CHAR SERIAL_CHAR
|
||||
@@ -89,7 +89,7 @@
|
||||
#else
|
||||
|
||||
#define DEBUG_SECTION(...) NOOP
|
||||
#define DEBUG_PRINT_P(P) NOOP
|
||||
#define DEBUG_ECHOPGM_P(P) NOOP
|
||||
#define DEBUG_ECHO_START() NOOP
|
||||
#define DEBUG_ERROR_START() NOOP
|
||||
#define DEBUG_CHAR(...) NOOP
|
||||
|
||||
@@ -38,10 +38,10 @@ private:
|
||||
bool debug;
|
||||
|
||||
void echo_msg(PGM_P const pre) {
|
||||
serialprintPGM(pre);
|
||||
SERIAL_ECHOPGM_P(pre);
|
||||
if (the_msg) {
|
||||
SERIAL_CHAR(' ');
|
||||
serialprintPGM(the_msg);
|
||||
SERIAL_ECHOPGM_P(the_msg);
|
||||
}
|
||||
SERIAL_CHAR(' ');
|
||||
print_xyz(current_position);
|
||||
|
||||
@@ -131,6 +131,7 @@
|
||||
#define STR_WATCHDOG_FIRED "Watchdog timeout. Reset required."
|
||||
#define STR_ERR_KILLED "Printer halted. kill() called!"
|
||||
#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"
|
||||
@@ -221,7 +222,7 @@
|
||||
|
||||
// temperature.cpp strings
|
||||
#define STR_PID_AUTOTUNE_START "PID Autotune start"
|
||||
#define STR_PID_BAD_EXTRUDER_NUM "PID Autotune failed! Bad extruder number"
|
||||
#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: "
|
||||
@@ -246,6 +247,8 @@
|
||||
|
||||
#define STR_HEATER_BED "bed"
|
||||
#define STR_HEATER_CHAMBER "chamber"
|
||||
#define STR_COOLER "cooler"
|
||||
#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 !"
|
||||
|
||||
@@ -104,6 +104,7 @@
|
||||
#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))
|
||||
@@ -349,6 +350,31 @@
|
||||
#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 slash
|
||||
constexpr bool containsSlash(const char *str) {
|
||||
return *str == '/' ? true : (*str ? containsSlash(str + 1) : false);
|
||||
}
|
||||
// Find the last position of the slash
|
||||
constexpr const char* findLastSlashPos(const char* str) {
|
||||
return *str == '/' ? (str + 1) : findLastSlashPos(str - 1);
|
||||
}
|
||||
// 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 containsSlash(str) ? findLastSlashPos(findStringEnd(str)) : str;
|
||||
}
|
||||
}
|
||||
|
||||
#define ONLY_FILENAME CompileTimeString::baseName(__FILE__)
|
||||
|
||||
#else
|
||||
|
||||
#define MIN_2(a,b) ((a)<(b)?(a):(b))
|
||||
|
||||
+14
-11
@@ -37,19 +37,22 @@ 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:");
|
||||
|
||||
// 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
|
||||
|
||||
// Step 2: For multiserial, handle the second serial port as well
|
||||
#if HAS_MULTI_SERIAL
|
||||
#ifdef SERIAL_CATCHALL
|
||||
SerialOutputT multiSerial(MYSERIAL, SERIAL_CATCHALL);
|
||||
#else
|
||||
#if HAS_ETHERNET
|
||||
// Runtime checking of the condition variable
|
||||
ConditionalSerial<decltype(MYSERIAL1)> serialOut1(ethernet.have_telnet_client, MYSERIAL1, false); // Takes reference here
|
||||
#else
|
||||
// Don't pay for runtime checking a true variable, instead use the output directly
|
||||
#define serialOut1 MYSERIAL1
|
||||
#endif
|
||||
SerialOutputT multiSerial(MYSERIAL0, serialOut1);
|
||||
#if HAS_ETHERNET
|
||||
// We need a definition here
|
||||
SerialLeafT2 msSerial2(ethernet.have_telnet_client, MYSERIAL2, false);
|
||||
#endif
|
||||
|
||||
SerialOutputT multiSerial(SERIAL_LEAF_1, SERIAL_LEAF_2);
|
||||
#endif
|
||||
|
||||
void serialprintPGM(PGM_P str) {
|
||||
|
||||
+60
-21
@@ -24,6 +24,10 @@
|
||||
#include "../inc/MarlinConfig.h"
|
||||
#include "serial_hook.h"
|
||||
|
||||
#if HAS_MEATPACK
|
||||
#include "../feature/meatpack.h"
|
||||
#endif
|
||||
|
||||
// Commonly-used strings in serial output
|
||||
extern const char NUL_STR[], SP_P_STR[], SP_T_STR[],
|
||||
X_STR[], Y_STR[], Z_STR[], E_STR[],
|
||||
@@ -58,31 +62,66 @@ extern uint8_t marlin_debug_flags;
|
||||
//
|
||||
// Serial redirection
|
||||
//
|
||||
typedef int8_t serial_index_t;
|
||||
#define SERIAL_ALL 0x7F
|
||||
#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(); }
|
||||
#ifdef SERIAL_CATCHALL
|
||||
typedef MultiSerial<decltype(MYSERIAL), decltype(SERIAL_CATCHALL), 0> SerialOutputT;
|
||||
#else
|
||||
typedef MultiSerial<decltype(MYSERIAL0), TERN(HAS_ETHERNET, ConditionalSerial<decltype(MYSERIAL1)>, decltype(MYSERIAL1)), 0> SerialOutputT;
|
||||
#endif
|
||||
extern SerialOutputT multiSerial;
|
||||
#define SERIAL_IMPL multiSerial
|
||||
// Step 1: Find what's the first serial leaf
|
||||
#if BOTH(HAS_MULTI_SERIAL, SERIAL_CATCHALL)
|
||||
#define _SERIAL_LEAF_1 MYSERIAL
|
||||
#else
|
||||
#define _PORT_REDIRECT(n,p) NOOP
|
||||
#define _PORT_RESTORE(n) NOOP
|
||||
#define SERIAL_ASSERT(P) NOOP
|
||||
#define SERIAL_IMPL MYSERIAL0
|
||||
#define _SERIAL_LEAF_1 MYSERIAL1
|
||||
#endif
|
||||
|
||||
// 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_LEAF_1 _SERIAL_LEAF_1
|
||||
#endif
|
||||
|
||||
// Step 2: For multiserial, handle the second serial port as well
|
||||
#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
|
||||
#else
|
||||
#if HAS_ETHERNET
|
||||
// We need to create an instance here
|
||||
typedef ConditionalSerial<decltype(MYSERIAL2)> SerialLeafT2;
|
||||
extern SerialLeafT2 msSerial2;
|
||||
#define _SERIAL_LEAF_2 msSerial2
|
||||
#else
|
||||
// Don't create a useless instance here, directly use the existing instance
|
||||
#define _SERIAL_LEAF_2 MYSERIAL2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
||||
typedef MultiSerial<decltype(SERIAL_LEAF_1), decltype(SERIAL_LEAF_2), 0> SerialOutputT;
|
||||
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
|
||||
|
||||
#define SERIAL_OUT(WHAT, V...) (void)SERIAL_IMPL.WHAT(V)
|
||||
|
||||
#define PORT_REDIRECT(p) _PORT_REDIRECT(1,p)
|
||||
#define PORT_RESTORE() _PORT_RESTORE(1)
|
||||
#define SERIAL_PORTMASK(P) _BV(P)
|
||||
#define PORT_REDIRECT(p) _PORT_REDIRECT(1,p)
|
||||
#define PORT_RESTORE() _PORT_RESTORE(1)
|
||||
#define SERIAL_PORTMASK(P) SerialMask::from(P)
|
||||
|
||||
//
|
||||
// SERIAL_CHAR - Print one or more individual chars
|
||||
@@ -295,7 +334,7 @@ void serialprintPGM(PGM_P str);
|
||||
#endif
|
||||
|
||||
#define SERIAL_ECHOPGM_P(P) (serialprintPGM(P))
|
||||
#define SERIAL_ECHOLNPGM_P(P) (serialprintPGM(P "\n"))
|
||||
#define SERIAL_ECHOLNPGM_P(P) do{ serialprintPGM(P); SERIAL_EOL(); }while(0)
|
||||
|
||||
#define SERIAL_ECHOPGM(S) (serialprintPGM(PSTR(S)))
|
||||
#define SERIAL_ECHOLNPGM(S) (serialprintPGM(PSTR(S "\n")))
|
||||
|
||||
@@ -22,12 +22,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "../inc/MarlinConfigPre.h"
|
||||
#include "macros.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) {}
|
||||
};
|
||||
|
||||
// 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);
|
||||
@@ -79,10 +96,10 @@ struct SerialBase {
|
||||
void end() { static_cast<Child*>(this)->end(); }
|
||||
/** Check for available data from the port
|
||||
@param index The port index, usually 0 */
|
||||
bool available(uint8_t index = 0) { return static_cast<Child*>(this)->available(index); }
|
||||
int available(serial_index_t index = 0) { return static_cast<Child*>(this)->available(index); }
|
||||
/** Read a value from the port
|
||||
@param index The port index, usually 0 */
|
||||
int read(uint8_t index = 0) { return static_cast<Child*>(this)->read(index); }
|
||||
int read(serial_index_t index = 0) { return static_cast<Child*>(this)->read(index); }
|
||||
// Check if the serial port is connected (usually bypassed)
|
||||
bool connected() { return static_cast<Child*>(this)->connected(); }
|
||||
// Redirect flush
|
||||
|
||||
@@ -21,9 +21,33 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "macros.h"
|
||||
#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 {
|
||||
@@ -35,8 +59,9 @@ struct BaseSerial : public SerialBase< BaseSerial<SerialT> >, public SerialT {
|
||||
|
||||
void msgDone() {}
|
||||
|
||||
bool available(uint8_t index) { return index == 0 && SerialT::available(); }
|
||||
int read(uint8_t index) { return index == 0 ? SerialT::read() : -1; }
|
||||
// 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); }
|
||||
|
||||
@@ -65,18 +90,18 @@ struct ConditionalSerial : public SerialBase< ConditionalSerial<SerialT> > {
|
||||
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 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); }
|
||||
bool connected() { return CALL_IF_EXISTS(bool, &out, connected); }
|
||||
void flushTX() { CALL_IF_EXISTS(void, &out, flushTX); }
|
||||
|
||||
bool available(uint8_t index) { return index == 0 && out.available(); }
|
||||
int read(uint8_t index) { return index == 0 ? out.read() : -1; }
|
||||
using BaseClassT::available;
|
||||
using BaseClassT::read;
|
||||
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(); }
|
||||
|
||||
ConditionalSerial(bool & conditionVariable, SerialT & out, const bool e) : BaseClassT(e), condition(conditionVariable), out(out) {}
|
||||
};
|
||||
@@ -97,10 +122,10 @@ struct ForwardSerial : public SerialBase< ForwardSerial<SerialT> > {
|
||||
bool connected() { return Private::HasMember_connected<SerialT>::value ? CALL_IF_EXISTS(bool, &out, connected) : (bool)out; }
|
||||
void flushTX() { CALL_IF_EXISTS(void, &out, flushTX); }
|
||||
|
||||
bool available(uint8_t index) { return index == 0 && out.available(); }
|
||||
int read(uint8_t index) { return index == 0 ? out.read() : -1; }
|
||||
bool available() { return out.available(); }
|
||||
int read() { return out.read(); }
|
||||
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(); }
|
||||
|
||||
ForwardSerial(const bool e, SerialT & out) : BaseClassT(e), out(out) {}
|
||||
};
|
||||
@@ -125,8 +150,8 @@ struct RuntimeSerial : public SerialBase< RuntimeSerial<SerialT> >, public Seria
|
||||
if (eofHook) eofHook(userPointer);
|
||||
}
|
||||
|
||||
bool available(uint8_t index) { return index == 0 && SerialT::available(); }
|
||||
int read(uint8_t index) { return index == 0 ? SerialT::read() : -1; }
|
||||
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;
|
||||
@@ -157,60 +182,59 @@ struct RuntimeSerial : public SerialBase< RuntimeSerial<SerialT> >, public Seria
|
||||
|
||||
// Forward constructor
|
||||
template <typename... Args>
|
||||
RuntimeSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...) {}
|
||||
RuntimeSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...), writeHook(0), eofHook(0), userPointer(0) {}
|
||||
};
|
||||
|
||||
// A class that's duplicating its output conditionally to 2 serial interface
|
||||
template <class Serial0T, class Serial1T, const uint8_t offset = 0>
|
||||
struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset> > {
|
||||
typedef SerialBase< MultiSerial<Serial0T, Serial1T, offset> > BaseClassT;
|
||||
// A class that duplicates its output conditionally to 2 serial interfaces
|
||||
template <class Serial0T, class Serial1T, const uint8_t offset = 0, const uint8_t step = 1>
|
||||
struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset, step> > {
|
||||
typedef SerialBase< MultiSerial<Serial0T, Serial1T, offset, step> > BaseClassT;
|
||||
|
||||
uint8_t portMask;
|
||||
SerialMask portMask;
|
||||
Serial0T & serial0;
|
||||
Serial1T & serial1;
|
||||
|
||||
enum Masks {
|
||||
FirstOutputMask = (1 << offset),
|
||||
SecondOutputMask = (1 << (offset + 1)),
|
||||
AllMask = FirstOutputMask | SecondOutputMask,
|
||||
};
|
||||
static constexpr uint8_t Usage = ((1 << step) - 1); // A bit mask containing as many bits as step
|
||||
static constexpr uint8_t FirstOutput = (Usage << offset);
|
||||
static constexpr uint8_t SecondOutput = (Usage << (offset + step));
|
||||
static constexpr uint8_t Both = FirstOutput | SecondOutput;
|
||||
|
||||
NO_INLINE size_t write(uint8_t c) {
|
||||
size_t ret = 0;
|
||||
if (portMask & FirstOutputMask) ret = serial0.write(c);
|
||||
if (portMask & SecondOutputMask) ret = serial1.write(c) | ret;
|
||||
if (portMask.enabled(FirstOutput)) ret = serial0.write(c);
|
||||
if (portMask.enabled(SecondOutput)) ret = serial1.write(c) | ret;
|
||||
return ret;
|
||||
}
|
||||
NO_INLINE void msgDone() {
|
||||
if (portMask & FirstOutputMask) serial0.msgDone();
|
||||
if (portMask & SecondOutputMask) serial1.msgDone();
|
||||
if (portMask.enabled(FirstOutput)) serial0.msgDone();
|
||||
if (portMask.enabled(SecondOutput)) serial1.msgDone();
|
||||
}
|
||||
bool available(uint8_t index) {
|
||||
switch(index) {
|
||||
case 0 + offset: return serial0.available();
|
||||
case 1 + offset: return serial1.available();
|
||||
default: return false;
|
||||
}
|
||||
int available(serial_index_t index) {
|
||||
if (index.within(0 + offset, step + offset - 1))
|
||||
return serial0.available(index);
|
||||
else if (index.within(step + offset, 2 * step + offset - 1))
|
||||
return serial1.available(index);
|
||||
return false;
|
||||
}
|
||||
NO_INLINE int read(uint8_t index) {
|
||||
switch(index) {
|
||||
case 0 + offset: return serial0.read();
|
||||
case 1 + offset: return serial1.read();
|
||||
default: return -1;
|
||||
}
|
||||
int read(serial_index_t index) {
|
||||
if (index.within(0 + offset, step + offset - 1))
|
||||
return serial0.read(index);
|
||||
else if (index.within(step + offset, 2 * step + offset - 1))
|
||||
return serial1.read(index);
|
||||
return -1;
|
||||
}
|
||||
void begin(const long br) {
|
||||
if (portMask & FirstOutputMask) serial0.begin(br);
|
||||
if (portMask & SecondOutputMask) serial1.begin(br);
|
||||
if (portMask.enabled(FirstOutput)) serial0.begin(br);
|
||||
if (portMask.enabled(SecondOutput)) serial1.begin(br);
|
||||
}
|
||||
void end() {
|
||||
if (portMask & FirstOutputMask) serial0.end();
|
||||
if (portMask & SecondOutputMask) serial1.end();
|
||||
if (portMask.enabled(FirstOutput)) serial0.end();
|
||||
if (portMask.enabled(SecondOutput)) serial1.end();
|
||||
}
|
||||
bool connected() {
|
||||
bool ret = true;
|
||||
if (portMask & FirstOutputMask) ret = CALL_IF_EXISTS(bool, &serial0, connected);
|
||||
if (portMask & SecondOutputMask) ret = ret && CALL_IF_EXISTS(bool, &serial1, connected);
|
||||
if (portMask.enabled(FirstOutput)) ret = CALL_IF_EXISTS(bool, &serial0, connected);
|
||||
if (portMask.enabled(SecondOutput)) ret = ret && CALL_IF_EXISTS(bool, &serial1, connected);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -219,22 +243,22 @@ struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset>
|
||||
|
||||
// Redirect flush
|
||||
NO_INLINE void flush() {
|
||||
if (portMask & FirstOutputMask) serial0.flush();
|
||||
if (portMask & SecondOutputMask) serial1.flush();
|
||||
if (portMask.enabled(FirstOutput)) serial0.flush();
|
||||
if (portMask.enabled(SecondOutput)) serial1.flush();
|
||||
}
|
||||
NO_INLINE void flushTX() {
|
||||
if (portMask & FirstOutputMask) CALL_IF_EXISTS(void, &serial0, flushTX);
|
||||
if (portMask & SecondOutputMask) CALL_IF_EXISTS(void, &serial1, flushTX);
|
||||
if (portMask.enabled(FirstOutput)) CALL_IF_EXISTS(void, &serial0, flushTX);
|
||||
if (portMask.enabled(SecondOutput)) CALL_IF_EXISTS(void, &serial1, flushTX);
|
||||
}
|
||||
|
||||
MultiSerial(Serial0T & serial0, Serial1T & serial1, int8_t mask = AllMask, const bool e = false) :
|
||||
MultiSerial(Serial0T & serial0, Serial1T & serial1, const SerialMask mask = Both, const bool e = false) :
|
||||
BaseClassT(e),
|
||||
portMask(mask), serial0(serial0), serial1(serial1) {}
|
||||
};
|
||||
|
||||
// Build the actual serial object depending on current configuration
|
||||
#define Serial0Type TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, BaseSerial)
|
||||
#define ForwardSerial0Type TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial)
|
||||
#define Serial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, BaseSerial)
|
||||
#define ForwardSerial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial)
|
||||
#ifdef HAS_MULTI_SERIAL
|
||||
#define Serial1Type ConditionalSerial
|
||||
#define Serial2Class ConditionalSerial
|
||||
#endif
|
||||
|
||||
@@ -92,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");
|
||||
|
||||
@@ -102,7 +102,7 @@ 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
|
||||
|
||||
@@ -98,7 +98,7 @@ TemporaryBedLevelingState::TemporaryBedLevelingState(const bool enable) : saved(
|
||||
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
|
||||
void set_z_fade_height(const float zfh, const bool do_report/*=true*/) {
|
||||
void set_z_fade_height(const float &zfh, const bool do_report/*=true*/) {
|
||||
|
||||
if (planner.z_fade_height == zfh) return;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ void set_bed_leveling_enabled(const bool enable=true);
|
||||
void reset_bed_level();
|
||||
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
void set_z_fade_height(const float zfh, const bool do_report=true);
|
||||
void set_z_fade_height(const float &zfh, const bool do_report=true);
|
||||
#endif
|
||||
|
||||
#if EITHER(MESH_BED_LEVELING, PROBE_MANUALLY)
|
||||
|
||||
@@ -24,234 +24,234 @@
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
|
||||
#include "../bedlevel.h"
|
||||
#include "../bedlevel.h"
|
||||
|
||||
unified_bed_leveling ubl;
|
||||
unified_bed_leveling ubl;
|
||||
|
||||
#include "../../../MarlinCore.h"
|
||||
#include "../../../gcode/gcode.h"
|
||||
#include "../../../MarlinCore.h"
|
||||
#include "../../../gcode/gcode.h"
|
||||
|
||||
#include "../../../module/settings.h"
|
||||
#include "../../../module/planner.h"
|
||||
#include "../../../module/motion.h"
|
||||
#include "../../../module/probe.h"
|
||||
#include "../../../module/settings.h"
|
||||
#include "../../../module/planner.h"
|
||||
#include "../../../module/motion.h"
|
||||
#include "../../../module/probe.h"
|
||||
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
#include "../../../lcd/extui/ui_api.h"
|
||||
#endif
|
||||
|
||||
#include "math.h"
|
||||
|
||||
void unified_bed_leveling::echo_name() { SERIAL_ECHOPGM("Unified Bed Leveling"); }
|
||||
|
||||
void unified_bed_leveling::report_current_mesh() {
|
||||
if (!leveling_is_valid()) return;
|
||||
SERIAL_ECHO_MSG(" G29 I999");
|
||||
GRID_LOOP(x, y)
|
||||
if (!isnan(z_values[x][y])) {
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPAIR(" M421 I", x, " J", y);
|
||||
SERIAL_ECHOLNPAIR_F_P(SP_Z_STR, z_values[x][y], 4);
|
||||
serial_delay(75); // Prevent Printrun from exploding
|
||||
}
|
||||
}
|
||||
|
||||
void unified_bed_leveling::report_state() {
|
||||
echo_name();
|
||||
SERIAL_ECHO_TERNARY(planner.leveling_active, " System v" UBL_VERSION " ", "", "in", "active\n");
|
||||
serial_delay(50);
|
||||
}
|
||||
|
||||
int8_t unified_bed_leveling::storage_slot;
|
||||
|
||||
float unified_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
|
||||
|
||||
#define _GRIDPOS(A,N) (MESH_MIN_##A + N * (MESH_##A##_DIST))
|
||||
|
||||
const float
|
||||
unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X,
|
||||
_GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3),
|
||||
_GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7),
|
||||
_GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11),
|
||||
_GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15)
|
||||
),
|
||||
unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y,
|
||||
_GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3),
|
||||
_GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7),
|
||||
_GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11),
|
||||
_GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15)
|
||||
);
|
||||
|
||||
volatile int16_t unified_bed_leveling::encoder_diff;
|
||||
|
||||
unified_bed_leveling::unified_bed_leveling() { reset(); }
|
||||
|
||||
void unified_bed_leveling::reset() {
|
||||
const bool was_enabled = planner.leveling_active;
|
||||
set_bed_leveling_enabled(false);
|
||||
storage_slot = -1;
|
||||
ZERO(z_values);
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
#include "../../../lcd/extui/ui_api.h"
|
||||
GRID_LOOP(x, y) ExtUI::onMeshUpdate(x, y, 0);
|
||||
#endif
|
||||
if (was_enabled) report_current_position();
|
||||
}
|
||||
|
||||
#include "math.h"
|
||||
void unified_bed_leveling::invalidate() {
|
||||
set_bed_leveling_enabled(false);
|
||||
set_all_mesh_points_to_value(NAN);
|
||||
}
|
||||
|
||||
void unified_bed_leveling::echo_name() { SERIAL_ECHOPGM("Unified Bed Leveling"); }
|
||||
void unified_bed_leveling::set_all_mesh_points_to_value(const float value) {
|
||||
GRID_LOOP(x, y) {
|
||||
z_values[x][y] = value;
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, value));
|
||||
}
|
||||
}
|
||||
|
||||
void unified_bed_leveling::report_current_mesh() {
|
||||
if (!leveling_is_valid()) return;
|
||||
SERIAL_ECHO_MSG(" G29 I999");
|
||||
GRID_LOOP(x, y)
|
||||
if (!isnan(z_values[x][y])) {
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPAIR(" M421 I", x, " J", y);
|
||||
SERIAL_ECHOLNPAIR_F_P(SP_Z_STR, z_values[x][y], 4);
|
||||
serial_delay(75); // Prevent Printrun from exploding
|
||||
}
|
||||
#if ENABLED(OPTIMIZED_MESH_STORAGE)
|
||||
|
||||
constexpr float mesh_store_scaling = 1000;
|
||||
constexpr int16_t Z_STEPS_NAN = INT16_MAX;
|
||||
|
||||
void unified_bed_leveling::set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values) {
|
||||
auto z_to_store = [](const float &z) {
|
||||
if (isnan(z)) return Z_STEPS_NAN;
|
||||
const int32_t z_scaled = TRUNC(z * mesh_store_scaling);
|
||||
if (z_scaled == Z_STEPS_NAN || !WITHIN(z_scaled, INT16_MIN, INT16_MAX))
|
||||
return Z_STEPS_NAN; // If Z is out of range, return our custom 'NaN'
|
||||
return int16_t(z_scaled);
|
||||
};
|
||||
GRID_LOOP(x, y) stored_values[x][y] = z_to_store(in_values[x][y]);
|
||||
}
|
||||
|
||||
void unified_bed_leveling::report_state() {
|
||||
echo_name();
|
||||
SERIAL_ECHO_TERNARY(planner.leveling_active, " System v" UBL_VERSION " ", "", "in", "active\n");
|
||||
serial_delay(50);
|
||||
void unified_bed_leveling::set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values) {
|
||||
auto store_to_z = [](const int16_t z_scaled) {
|
||||
return z_scaled == Z_STEPS_NAN ? NAN : z_scaled / mesh_store_scaling;
|
||||
};
|
||||
GRID_LOOP(x, y) out_values[x][y] = store_to_z(stored_values[x][y]);
|
||||
}
|
||||
|
||||
int8_t unified_bed_leveling::storage_slot;
|
||||
#endif // OPTIMIZED_MESH_STORAGE
|
||||
|
||||
float unified_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
|
||||
static void serial_echo_xy(const uint8_t sp, const int16_t x, const int16_t y) {
|
||||
SERIAL_ECHO_SP(sp);
|
||||
SERIAL_CHAR('(');
|
||||
if (x < 100) { SERIAL_CHAR(' '); if (x < 10) SERIAL_CHAR(' '); }
|
||||
SERIAL_ECHO(x);
|
||||
SERIAL_CHAR(',');
|
||||
if (y < 100) { SERIAL_CHAR(' '); if (y < 10) SERIAL_CHAR(' '); }
|
||||
SERIAL_ECHO(y);
|
||||
SERIAL_CHAR(')');
|
||||
serial_delay(5);
|
||||
}
|
||||
|
||||
#define _GRIDPOS(A,N) (MESH_MIN_##A + N * (MESH_##A##_DIST))
|
||||
|
||||
const float
|
||||
unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X,
|
||||
_GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3),
|
||||
_GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7),
|
||||
_GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11),
|
||||
_GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15)
|
||||
),
|
||||
unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y,
|
||||
_GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3),
|
||||
_GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7),
|
||||
_GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11),
|
||||
_GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15)
|
||||
);
|
||||
|
||||
volatile int16_t unified_bed_leveling::encoder_diff;
|
||||
|
||||
unified_bed_leveling::unified_bed_leveling() { reset(); }
|
||||
|
||||
void unified_bed_leveling::reset() {
|
||||
const bool was_enabled = planner.leveling_active;
|
||||
set_bed_leveling_enabled(false);
|
||||
storage_slot = -1;
|
||||
ZERO(z_values);
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
GRID_LOOP(x, y) ExtUI::onMeshUpdate(x, y, 0);
|
||||
#endif
|
||||
if (was_enabled) report_current_position();
|
||||
}
|
||||
|
||||
void unified_bed_leveling::invalidate() {
|
||||
set_bed_leveling_enabled(false);
|
||||
set_all_mesh_points_to_value(NAN);
|
||||
}
|
||||
|
||||
void unified_bed_leveling::set_all_mesh_points_to_value(const float value) {
|
||||
GRID_LOOP(x, y) {
|
||||
z_values[x][y] = value;
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, value));
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLED(OPTIMIZED_MESH_STORAGE)
|
||||
|
||||
constexpr float mesh_store_scaling = 1000;
|
||||
constexpr int16_t Z_STEPS_NAN = INT16_MAX;
|
||||
|
||||
void unified_bed_leveling::set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values) {
|
||||
auto z_to_store = [](const float &z) {
|
||||
if (isnan(z)) return Z_STEPS_NAN;
|
||||
const int32_t z_scaled = TRUNC(z * mesh_store_scaling);
|
||||
if (z_scaled == Z_STEPS_NAN || !WITHIN(z_scaled, INT16_MIN, INT16_MAX))
|
||||
return Z_STEPS_NAN; // If Z is out of range, return our custom 'NaN'
|
||||
return int16_t(z_scaled);
|
||||
};
|
||||
GRID_LOOP(x, y) stored_values[x][y] = z_to_store(in_values[x][y]);
|
||||
}
|
||||
|
||||
void unified_bed_leveling::set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values) {
|
||||
auto store_to_z = [](const int16_t z_scaled) {
|
||||
return z_scaled == Z_STEPS_NAN ? NAN : z_scaled / mesh_store_scaling;
|
||||
};
|
||||
GRID_LOOP(x, y) out_values[x][y] = store_to_z(stored_values[x][y]);
|
||||
}
|
||||
|
||||
#endif // OPTIMIZED_MESH_STORAGE
|
||||
|
||||
static void serial_echo_xy(const uint8_t sp, const int16_t x, const int16_t y) {
|
||||
static void serial_echo_column_labels(const uint8_t sp) {
|
||||
SERIAL_ECHO_SP(7);
|
||||
LOOP_L_N(i, GRID_MAX_POINTS_X) {
|
||||
if (i < 10) SERIAL_CHAR(' ');
|
||||
SERIAL_ECHO(i);
|
||||
SERIAL_ECHO_SP(sp);
|
||||
SERIAL_CHAR('(');
|
||||
if (x < 100) { SERIAL_CHAR(' '); if (x < 10) SERIAL_CHAR(' '); }
|
||||
SERIAL_ECHO(x);
|
||||
SERIAL_CHAR(',');
|
||||
if (y < 100) { SERIAL_CHAR(' '); if (y < 10) SERIAL_CHAR(' '); }
|
||||
SERIAL_ECHO(y);
|
||||
SERIAL_CHAR(')');
|
||||
serial_delay(5);
|
||||
}
|
||||
serial_delay(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce one of these mesh maps:
|
||||
* 0: Human-readable
|
||||
* 1: CSV format for spreadsheet import
|
||||
* 2: TODO: Display on Graphical LCD
|
||||
* 4: Compact Human-Readable
|
||||
*/
|
||||
void unified_bed_leveling::display_map(const int map_type) {
|
||||
const bool was = gcode.set_autoreport_paused(true);
|
||||
|
||||
constexpr uint8_t eachsp = 1 + 6 + 1, // [-3.567]
|
||||
twixt = eachsp * (GRID_MAX_POINTS_X) - 9 * 2; // Leading 4sp, Coordinates 9sp each
|
||||
|
||||
const bool human = !(map_type & 0x3), csv = map_type == 1, lcd = map_type == 2, comp = map_type & 0x4;
|
||||
|
||||
SERIAL_ECHOPGM("\nBed Topography Report");
|
||||
if (human) {
|
||||
SERIAL_ECHOLNPGM(":\n");
|
||||
serial_echo_xy(4, MESH_MIN_X, MESH_MAX_Y);
|
||||
serial_echo_xy(twixt, MESH_MAX_X, MESH_MAX_Y);
|
||||
SERIAL_EOL();
|
||||
serial_echo_column_labels(eachsp - 2);
|
||||
}
|
||||
else {
|
||||
SERIAL_ECHOPGM(" for ");
|
||||
SERIAL_ECHOPGM_P(csv ? PSTR("CSV:\n") : PSTR("LCD:\n"));
|
||||
}
|
||||
|
||||
static void serial_echo_column_labels(const uint8_t sp) {
|
||||
SERIAL_ECHO_SP(7);
|
||||
// Add XY probe offset from extruder because probe.probe_at_point() subtracts them when
|
||||
// moving to the XY position to be measured. This ensures better agreement between
|
||||
// the current Z position after G28 and the mesh values.
|
||||
const xy_int8_t curr = closest_indexes(xy_pos_t(current_position) + probe.offset_xy);
|
||||
|
||||
if (!lcd) SERIAL_EOL();
|
||||
for (int8_t j = GRID_MAX_POINTS_Y - 1; j >= 0; j--) {
|
||||
|
||||
// Row Label (J index)
|
||||
if (human) {
|
||||
if (j < 10) SERIAL_CHAR(' ');
|
||||
SERIAL_ECHO(j);
|
||||
SERIAL_ECHOPGM(" |");
|
||||
}
|
||||
|
||||
// Row Values (I indexes)
|
||||
LOOP_L_N(i, GRID_MAX_POINTS_X) {
|
||||
if (i < 10) SERIAL_CHAR(' ');
|
||||
SERIAL_ECHO(i);
|
||||
SERIAL_ECHO_SP(sp);
|
||||
|
||||
// Opening Brace or Space
|
||||
const bool is_current = i == curr.x && j == curr.y;
|
||||
if (human) SERIAL_CHAR(is_current ? '[' : ' ');
|
||||
|
||||
// Z Value at current I, J
|
||||
const float f = z_values[i][j];
|
||||
if (lcd) {
|
||||
// TODO: Display on Graphical LCD
|
||||
}
|
||||
else if (isnan(f))
|
||||
SERIAL_ECHOPGM_P(human ? PSTR(" . ") : PSTR("NAN"));
|
||||
else if (human || csv) {
|
||||
if (human && f >= 0.0) SERIAL_CHAR(f > 0 ? '+' : ' '); // Display sign also for positive numbers (' ' for 0)
|
||||
SERIAL_ECHO_F(f, 3); // Positive: 5 digits, Negative: 6 digits
|
||||
}
|
||||
if (csv && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR('\t');
|
||||
|
||||
// Closing Brace or Space
|
||||
if (human) SERIAL_CHAR(is_current ? ']' : ' ');
|
||||
|
||||
SERIAL_FLUSHTX();
|
||||
idle_no_sleep();
|
||||
}
|
||||
serial_delay(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce one of these mesh maps:
|
||||
* 0: Human-readable
|
||||
* 1: CSV format for spreadsheet import
|
||||
* 2: TODO: Display on Graphical LCD
|
||||
* 4: Compact Human-Readable
|
||||
*/
|
||||
void unified_bed_leveling::display_map(const int map_type) {
|
||||
const bool was = gcode.set_autoreport_paused(true);
|
||||
|
||||
constexpr uint8_t eachsp = 1 + 6 + 1, // [-3.567]
|
||||
twixt = eachsp * (GRID_MAX_POINTS_X) - 9 * 2; // Leading 4sp, Coordinates 9sp each
|
||||
|
||||
const bool human = !(map_type & 0x3), csv = map_type == 1, lcd = map_type == 2, comp = map_type & 0x4;
|
||||
|
||||
SERIAL_ECHOPGM("\nBed Topography Report");
|
||||
if (human) {
|
||||
SERIAL_ECHOLNPGM(":\n");
|
||||
serial_echo_xy(4, MESH_MIN_X, MESH_MAX_Y);
|
||||
serial_echo_xy(twixt, MESH_MAX_X, MESH_MAX_Y);
|
||||
SERIAL_EOL();
|
||||
serial_echo_column_labels(eachsp - 2);
|
||||
}
|
||||
else {
|
||||
SERIAL_ECHOPGM(" for ");
|
||||
serialprintPGM(csv ? PSTR("CSV:\n") : PSTR("LCD:\n"));
|
||||
}
|
||||
|
||||
// Add XY probe offset from extruder because probe.probe_at_point() subtracts them when
|
||||
// moving to the XY position to be measured. This ensures better agreement between
|
||||
// the current Z position after G28 and the mesh values.
|
||||
const xy_int8_t curr = closest_indexes(xy_pos_t(current_position) + probe.offset_xy);
|
||||
|
||||
if (!lcd) SERIAL_EOL();
|
||||
for (int8_t j = GRID_MAX_POINTS_Y - 1; j >= 0; j--) {
|
||||
|
||||
// Row Label (J index)
|
||||
if (human) {
|
||||
if (j < 10) SERIAL_CHAR(' ');
|
||||
SERIAL_ECHO(j);
|
||||
SERIAL_ECHOPGM(" |");
|
||||
}
|
||||
|
||||
// Row Values (I indexes)
|
||||
LOOP_L_N(i, GRID_MAX_POINTS_X) {
|
||||
|
||||
// Opening Brace or Space
|
||||
const bool is_current = i == curr.x && j == curr.y;
|
||||
if (human) SERIAL_CHAR(is_current ? '[' : ' ');
|
||||
|
||||
// Z Value at current I, J
|
||||
const float f = z_values[i][j];
|
||||
if (lcd) {
|
||||
// TODO: Display on Graphical LCD
|
||||
}
|
||||
else if (isnan(f))
|
||||
serialprintPGM(human ? PSTR(" . ") : PSTR("NAN"));
|
||||
else if (human || csv) {
|
||||
if (human && f >= 0.0) SERIAL_CHAR(f > 0 ? '+' : ' '); // Display sign also for positive numbers (' ' for 0)
|
||||
SERIAL_ECHO_F(f, 3); // Positive: 5 digits, Negative: 6 digits
|
||||
}
|
||||
if (csv && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR('\t');
|
||||
|
||||
// Closing Brace or Space
|
||||
if (human) SERIAL_CHAR(is_current ? ']' : ' ');
|
||||
|
||||
SERIAL_FLUSHTX();
|
||||
idle_no_sleep();
|
||||
}
|
||||
if (!lcd) SERIAL_EOL();
|
||||
|
||||
// A blank line between rows (unless compact)
|
||||
if (j && human && !comp) SERIAL_ECHOLNPGM(" |");
|
||||
}
|
||||
|
||||
if (human) {
|
||||
serial_echo_column_labels(eachsp - 2);
|
||||
SERIAL_EOL();
|
||||
serial_echo_xy(4, MESH_MIN_X, MESH_MIN_Y);
|
||||
serial_echo_xy(twixt, MESH_MAX_X, MESH_MIN_Y);
|
||||
SERIAL_EOL();
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
gcode.set_autoreport_paused(was);
|
||||
// A blank line between rows (unless compact)
|
||||
if (j && human && !comp) SERIAL_ECHOLNPGM(" |");
|
||||
}
|
||||
|
||||
bool unified_bed_leveling::sanity_check() {
|
||||
uint8_t error_flag = 0;
|
||||
|
||||
if (settings.calc_num_meshes() < 1) {
|
||||
SERIAL_ECHOLNPGM("?Mesh too big for EEPROM.");
|
||||
error_flag++;
|
||||
}
|
||||
|
||||
return !!error_flag;
|
||||
if (human) {
|
||||
serial_echo_column_labels(eachsp - 2);
|
||||
SERIAL_EOL();
|
||||
serial_echo_xy(4, MESH_MIN_X, MESH_MIN_Y);
|
||||
serial_echo_xy(twixt, MESH_MAX_X, MESH_MIN_Y);
|
||||
SERIAL_EOL();
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
gcode.set_autoreport_paused(was);
|
||||
}
|
||||
|
||||
bool unified_bed_leveling::sanity_check() {
|
||||
uint8_t error_flag = 0;
|
||||
|
||||
if (settings.calc_num_meshes() < 1) {
|
||||
SERIAL_ECHOLNPGM("?Mesh too big for EEPROM.");
|
||||
error_flag++;
|
||||
}
|
||||
|
||||
return !!error_flag;
|
||||
}
|
||||
|
||||
#endif // AUTO_BED_LEVELING_UBL
|
||||
|
||||
@@ -46,275 +46,275 @@ struct mesh_index_pair;
|
||||
#endif
|
||||
|
||||
class unified_bed_leveling {
|
||||
private:
|
||||
private:
|
||||
|
||||
static int g29_verbose_level,
|
||||
g29_phase_value,
|
||||
g29_repetition_cnt,
|
||||
g29_storage_slot,
|
||||
g29_map_type;
|
||||
static bool g29_c_flag;
|
||||
static float g29_card_thickness,
|
||||
g29_constant;
|
||||
static xy_pos_t g29_pos;
|
||||
static xy_bool_t xy_seen;
|
||||
static int g29_verbose_level,
|
||||
g29_phase_value,
|
||||
g29_repetition_cnt,
|
||||
g29_storage_slot,
|
||||
g29_map_type;
|
||||
static bool g29_c_flag;
|
||||
static float g29_card_thickness,
|
||||
g29_constant;
|
||||
static xy_pos_t g29_pos;
|
||||
static xy_bool_t xy_seen;
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
static int g29_grid_size;
|
||||
#endif
|
||||
#if HAS_BED_PROBE
|
||||
static int g29_grid_size;
|
||||
#endif
|
||||
|
||||
#if IS_NEWPANEL
|
||||
static void move_z_with_encoder(const float &multiplier);
|
||||
static float measure_point_with_encoder();
|
||||
static float measure_business_card_thickness();
|
||||
static void manually_probe_remaining_mesh(const xy_pos_t&, const float&, const float&, const bool) _O0;
|
||||
static void fine_tune_mesh(const xy_pos_t &pos, const bool do_ubl_mesh_map) _O0;
|
||||
#endif
|
||||
#if IS_NEWPANEL
|
||||
static void move_z_with_encoder(const float &multiplier);
|
||||
static float measure_point_with_encoder();
|
||||
static float measure_business_card_thickness();
|
||||
static void manually_probe_remaining_mesh(const xy_pos_t&, const float&, const float&, const bool) _O0;
|
||||
static void fine_tune_mesh(const xy_pos_t &pos, const bool do_ubl_mesh_map) _O0;
|
||||
#endif
|
||||
|
||||
static bool g29_parameter_parsing() _O0;
|
||||
static void shift_mesh_height();
|
||||
static void probe_entire_mesh(const xy_pos_t &near, const bool do_ubl_mesh_map, const bool stow_probe, const bool do_furthest) _O0;
|
||||
static void tilt_mesh_based_on_3pts(const float &z1, const float &z2, const float &z3);
|
||||
static void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map);
|
||||
static bool smart_fill_one(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir);
|
||||
static inline bool smart_fill_one(const xy_uint8_t &pos, const xy_uint8_t &dir) {
|
||||
return smart_fill_one(pos.x, pos.y, dir.x, dir.y);
|
||||
}
|
||||
static void smart_fill_mesh();
|
||||
static bool g29_parameter_parsing() _O0;
|
||||
static void shift_mesh_height();
|
||||
static void probe_entire_mesh(const xy_pos_t &near, const bool do_ubl_mesh_map, const bool stow_probe, const bool do_furthest) _O0;
|
||||
static void tilt_mesh_based_on_3pts(const float &z1, const float &z2, const float &z3);
|
||||
static void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map);
|
||||
static bool smart_fill_one(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir);
|
||||
static inline bool smart_fill_one(const xy_uint8_t &pos, const xy_uint8_t &dir) {
|
||||
return smart_fill_one(pos.x, pos.y, dir.x, dir.y);
|
||||
}
|
||||
static void smart_fill_mesh();
|
||||
|
||||
#if ENABLED(UBL_DEVEL_DEBUGGING)
|
||||
static void g29_what_command();
|
||||
static void g29_eeprom_dump();
|
||||
static void g29_compare_current_mesh_to_stored_mesh();
|
||||
#endif
|
||||
#if ENABLED(UBL_DEVEL_DEBUGGING)
|
||||
static void g29_what_command();
|
||||
static void g29_eeprom_dump();
|
||||
static void g29_compare_current_mesh_to_stored_mesh();
|
||||
#endif
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
static void echo_name();
|
||||
static void report_current_mesh();
|
||||
static void report_state();
|
||||
static void save_ubl_active_state_and_disable();
|
||||
static void restore_ubl_active_state_and_leave();
|
||||
static void display_map(const int) _O0;
|
||||
static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const xy_pos_t&, const bool=false, MeshFlags *done_flags=nullptr) _O0;
|
||||
static mesh_index_pair find_furthest_invalid_mesh_point() _O0;
|
||||
static void reset();
|
||||
static void invalidate();
|
||||
static void set_all_mesh_points_to_value(const float value);
|
||||
static void adjust_mesh_to_mean(const bool cflag, const float value);
|
||||
static bool sanity_check();
|
||||
static void echo_name();
|
||||
static void report_current_mesh();
|
||||
static void report_state();
|
||||
static void save_ubl_active_state_and_disable();
|
||||
static void restore_ubl_active_state_and_leave();
|
||||
static void display_map(const int) _O0;
|
||||
static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const xy_pos_t&, const bool=false, MeshFlags *done_flags=nullptr) _O0;
|
||||
static mesh_index_pair find_furthest_invalid_mesh_point() _O0;
|
||||
static void reset();
|
||||
static void invalidate();
|
||||
static void set_all_mesh_points_to_value(const float value);
|
||||
static void adjust_mesh_to_mean(const bool cflag, const float value);
|
||||
static bool sanity_check();
|
||||
|
||||
static void G29() _O0; // O0 for no optimization
|
||||
static void smart_fill_wlsf(const float &) _O2; // O2 gives smaller code than Os on A2560
|
||||
static void G29() _O0; // O0 for no optimization
|
||||
static void smart_fill_wlsf(const float &) _O2; // O2 gives smaller code than Os on A2560
|
||||
|
||||
static int8_t storage_slot;
|
||||
static int8_t storage_slot;
|
||||
|
||||
static bed_mesh_t z_values;
|
||||
#if ENABLED(OPTIMIZED_MESH_STORAGE)
|
||||
static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values);
|
||||
static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values);
|
||||
#endif
|
||||
static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X],
|
||||
_mesh_index_to_ypos[GRID_MAX_POINTS_Y];
|
||||
static bed_mesh_t z_values;
|
||||
#if ENABLED(OPTIMIZED_MESH_STORAGE)
|
||||
static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values);
|
||||
static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values);
|
||||
#endif
|
||||
static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X],
|
||||
_mesh_index_to_ypos[GRID_MAX_POINTS_Y];
|
||||
|
||||
#if HAS_LCD_MENU
|
||||
static bool lcd_map_control;
|
||||
static void steppers_were_disabled();
|
||||
#else
|
||||
static inline void steppers_were_disabled() {}
|
||||
#endif
|
||||
#if HAS_LCD_MENU
|
||||
static bool lcd_map_control;
|
||||
static void steppers_were_disabled();
|
||||
#else
|
||||
static inline void steppers_were_disabled() {}
|
||||
#endif
|
||||
|
||||
static volatile int16_t encoder_diff; // Volatile because buttons may changed it at interrupt time
|
||||
static volatile int16_t encoder_diff; // Volatile because buttons may changed it at interrupt time
|
||||
|
||||
unified_bed_leveling();
|
||||
unified_bed_leveling();
|
||||
|
||||
FORCE_INLINE static void set_z(const int8_t px, const int8_t py, const float &z) { z_values[px][py] = z; }
|
||||
FORCE_INLINE static void set_z(const int8_t px, const int8_t py, const float &z) { z_values[px][py] = z; }
|
||||
|
||||
static int8_t cell_index_x_raw(const float &x) {
|
||||
return FLOOR((x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST));
|
||||
static int8_t cell_index_x_raw(const float &x) {
|
||||
return FLOOR((x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST));
|
||||
}
|
||||
|
||||
static int8_t cell_index_y_raw(const float &y) {
|
||||
return FLOOR((y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST));
|
||||
}
|
||||
|
||||
static int8_t cell_index_x_valid(const float &x) {
|
||||
return WITHIN(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X - 2));
|
||||
}
|
||||
|
||||
static int8_t cell_index_y_valid(const float &y) {
|
||||
return WITHIN(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y - 2));
|
||||
}
|
||||
|
||||
static int8_t cell_index_x(const float &x) {
|
||||
return constrain(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X) - 2);
|
||||
}
|
||||
|
||||
static int8_t cell_index_y(const float &y) {
|
||||
return constrain(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y) - 2);
|
||||
}
|
||||
|
||||
static inline xy_int8_t cell_indexes(const float &x, const float &y) {
|
||||
return { cell_index_x(x), cell_index_y(y) };
|
||||
}
|
||||
static inline xy_int8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); }
|
||||
|
||||
static int8_t closest_x_index(const float &x) {
|
||||
const int8_t px = (x - (MESH_MIN_X) + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST);
|
||||
return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1;
|
||||
}
|
||||
static int8_t closest_y_index(const float &y) {
|
||||
const int8_t py = (y - (MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST);
|
||||
return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1;
|
||||
}
|
||||
static inline xy_int8_t closest_indexes(const xy_pos_t &xy) {
|
||||
return { closest_x_index(xy.x), closest_y_index(xy.y) };
|
||||
}
|
||||
|
||||
/**
|
||||
* z2 --|
|
||||
* z0 | |
|
||||
* | | + (z2-z1)
|
||||
* z1 | | |
|
||||
* ---+-------------+--------+-- --|
|
||||
* a1 a0 a2
|
||||
* |<---delta_a---------->|
|
||||
*
|
||||
* calc_z0 is the basis for all the Mesh Based correction. It is used to
|
||||
* find the expected Z Height at a position between two known Z-Height locations.
|
||||
*
|
||||
* It is fairly expensive with its 4 floating point additions and 2 floating point
|
||||
* multiplications.
|
||||
*/
|
||||
FORCE_INLINE static float calc_z0(const float &a0, const float &a1, const float &z1, const float &a2, const float &z2) {
|
||||
return z1 + (z2 - z1) * (a0 - a1) / (a2 - a1);
|
||||
}
|
||||
|
||||
#ifdef UBL_Z_RAISE_WHEN_OFF_MESH
|
||||
#define _UBL_OUTER_Z_RAISE UBL_Z_RAISE_WHEN_OFF_MESH
|
||||
#else
|
||||
#define _UBL_OUTER_Z_RAISE NAN
|
||||
#endif
|
||||
|
||||
/**
|
||||
* z_correction_for_x_on_horizontal_mesh_line is an optimization for
|
||||
* the case where the printer is making a vertical line that only crosses horizontal mesh lines.
|
||||
*/
|
||||
static inline float z_correction_for_x_on_horizontal_mesh_line(const float &rx0, const int x1_i, const int yi) {
|
||||
if (!WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(yi, 0, GRID_MAX_POINTS_Y - 1)) {
|
||||
|
||||
if (DEBUGGING(LEVELING)) {
|
||||
if (WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("yi"); else DEBUG_ECHOPGM("x1_i");
|
||||
DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_x_on_horizontal_mesh_line(rx0=", rx0, ",x1_i=", x1_i, ",yi=", yi, ")");
|
||||
}
|
||||
|
||||
// The requested location is off the mesh. Return UBL_Z_RAISE_WHEN_OFF_MESH or NAN.
|
||||
return _UBL_OUTER_Z_RAISE;
|
||||
}
|
||||
|
||||
static int8_t cell_index_y_raw(const float &y) {
|
||||
return FLOOR((y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST));
|
||||
const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * RECIPROCAL(MESH_X_DIST),
|
||||
z1 = z_values[x1_i][yi];
|
||||
|
||||
return z1 + xratio * (z_values[_MIN(x1_i, GRID_MAX_POINTS_X - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
|
||||
// If it is, it is clamped to the last element of the
|
||||
// z_values[][] array and no correction is applied.
|
||||
}
|
||||
|
||||
//
|
||||
// See comments above for z_correction_for_x_on_horizontal_mesh_line
|
||||
//
|
||||
static inline float z_correction_for_y_on_vertical_mesh_line(const float &ry0, const int xi, const int y1_i) {
|
||||
if (!WITHIN(xi, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(y1_i, 0, GRID_MAX_POINTS_Y - 1)) {
|
||||
|
||||
if (DEBUGGING(LEVELING)) {
|
||||
if (WITHIN(xi, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("y1_i"); else DEBUG_ECHOPGM("xi");
|
||||
DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_y_on_vertical_mesh_line(ry0=", ry0, ", xi=", xi, ", y1_i=", y1_i, ")");
|
||||
}
|
||||
|
||||
// The requested location is off the mesh. Return UBL_Z_RAISE_WHEN_OFF_MESH or NAN.
|
||||
return _UBL_OUTER_Z_RAISE;
|
||||
}
|
||||
|
||||
static int8_t cell_index_x_valid(const float &x) {
|
||||
return WITHIN(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X - 2));
|
||||
}
|
||||
const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * RECIPROCAL(MESH_Y_DIST),
|
||||
z1 = z_values[xi][y1_i];
|
||||
|
||||
static int8_t cell_index_y_valid(const float &y) {
|
||||
return WITHIN(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y - 2));
|
||||
}
|
||||
return z1 + yratio * (z_values[xi][_MIN(y1_i, GRID_MAX_POINTS_Y - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
|
||||
// If it is, it is clamped to the last element of the
|
||||
// z_values[][] array and no correction is applied.
|
||||
}
|
||||
|
||||
static int8_t cell_index_x(const float &x) {
|
||||
return constrain(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X) - 2);
|
||||
}
|
||||
|
||||
static int8_t cell_index_y(const float &y) {
|
||||
return constrain(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y) - 2);
|
||||
}
|
||||
|
||||
static inline xy_int8_t cell_indexes(const float &x, const float &y) {
|
||||
return { cell_index_x(x), cell_index_y(y) };
|
||||
}
|
||||
static inline xy_int8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); }
|
||||
|
||||
static int8_t closest_x_index(const float &x) {
|
||||
const int8_t px = (x - (MESH_MIN_X) + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST);
|
||||
return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1;
|
||||
}
|
||||
static int8_t closest_y_index(const float &y) {
|
||||
const int8_t py = (y - (MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST);
|
||||
return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1;
|
||||
}
|
||||
static inline xy_int8_t closest_indexes(const xy_pos_t &xy) {
|
||||
return { closest_x_index(xy.x), closest_y_index(xy.y) };
|
||||
}
|
||||
/**
|
||||
* This is the generic Z-Correction. It works anywhere within a Mesh Cell. It first
|
||||
* does a linear interpolation along both of the bounding X-Mesh-Lines to find the
|
||||
* Z-Height at both ends. Then it does a linear interpolation of these heights based
|
||||
* on the Y position within the cell.
|
||||
*/
|
||||
static float get_z_correction(const float &rx0, const float &ry0) {
|
||||
const int8_t cx = cell_index_x(rx0), cy = cell_index_y(ry0); // return values are clamped
|
||||
|
||||
/**
|
||||
* z2 --|
|
||||
* z0 | |
|
||||
* | | + (z2-z1)
|
||||
* z1 | | |
|
||||
* ---+-------------+--------+-- --|
|
||||
* a1 a0 a2
|
||||
* |<---delta_a---------->|
|
||||
*
|
||||
* calc_z0 is the basis for all the Mesh Based correction. It is used to
|
||||
* find the expected Z Height at a position between two known Z-Height locations.
|
||||
*
|
||||
* It is fairly expensive with its 4 floating point additions and 2 floating point
|
||||
* multiplications.
|
||||
* Check if the requested location is off the mesh. If so, and
|
||||
* UBL_Z_RAISE_WHEN_OFF_MESH is specified, that value is returned.
|
||||
*/
|
||||
FORCE_INLINE static float calc_z0(const float &a0, const float &a1, const float &z1, const float &a2, const float &z2) {
|
||||
return z1 + (z2 - z1) * (a0 - a1) / (a2 - a1);
|
||||
}
|
||||
|
||||
#ifdef UBL_Z_RAISE_WHEN_OFF_MESH
|
||||
#define _UBL_OUTER_Z_RAISE UBL_Z_RAISE_WHEN_OFF_MESH
|
||||
#else
|
||||
#define _UBL_OUTER_Z_RAISE NAN
|
||||
if (!WITHIN(rx0, MESH_MIN_X, MESH_MAX_X) || !WITHIN(ry0, MESH_MIN_Y, MESH_MAX_Y))
|
||||
return UBL_Z_RAISE_WHEN_OFF_MESH;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* z_correction_for_x_on_horizontal_mesh_line is an optimization for
|
||||
* the case where the printer is making a vertical line that only crosses horizontal mesh lines.
|
||||
*/
|
||||
static inline float z_correction_for_x_on_horizontal_mesh_line(const float &rx0, const int x1_i, const int yi) {
|
||||
if (!WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(yi, 0, GRID_MAX_POINTS_Y - 1)) {
|
||||
const float z1 = calc_z0(rx0,
|
||||
mesh_index_to_xpos(cx), z_values[cx][cy],
|
||||
mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][cy]);
|
||||
|
||||
if (DEBUGGING(LEVELING)) {
|
||||
if (WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("yi"); else DEBUG_ECHOPGM("x1_i");
|
||||
DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_x_on_horizontal_mesh_line(rx0=", rx0, ",x1_i=", x1_i, ",yi=", yi, ")");
|
||||
}
|
||||
const float z2 = calc_z0(rx0,
|
||||
mesh_index_to_xpos(cx), z_values[cx][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1],
|
||||
mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1]);
|
||||
|
||||
// The requested location is off the mesh. Return UBL_Z_RAISE_WHEN_OFF_MESH or NAN.
|
||||
return _UBL_OUTER_Z_RAISE;
|
||||
}
|
||||
float z0 = calc_z0(ry0,
|
||||
mesh_index_to_ypos(cy), z1,
|
||||
mesh_index_to_ypos(cy + 1), z2);
|
||||
|
||||
const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * RECIPROCAL(MESH_X_DIST),
|
||||
z1 = z_values[x1_i][yi];
|
||||
|
||||
return z1 + xratio * (z_values[_MIN(x1_i, GRID_MAX_POINTS_X - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
|
||||
// If it is, it is clamped to the last element of the
|
||||
// z_values[][] array and no correction is applied.
|
||||
if (DEBUGGING(MESH_ADJUST)) {
|
||||
DEBUG_ECHOPAIR(" raw get_z_correction(", rx0);
|
||||
DEBUG_CHAR(','); DEBUG_ECHO(ry0);
|
||||
DEBUG_ECHOPAIR_F(") = ", z0, 6);
|
||||
DEBUG_ECHOLNPAIR_F(" >>>---> ", z0, 6);
|
||||
}
|
||||
|
||||
//
|
||||
// See comments above for z_correction_for_x_on_horizontal_mesh_line
|
||||
//
|
||||
static inline float z_correction_for_y_on_vertical_mesh_line(const float &ry0, const int xi, const int y1_i) {
|
||||
if (!WITHIN(xi, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(y1_i, 0, GRID_MAX_POINTS_Y - 1)) {
|
||||
|
||||
if (DEBUGGING(LEVELING)) {
|
||||
if (WITHIN(xi, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("y1_i"); else DEBUG_ECHOPGM("xi");
|
||||
DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_y_on_vertical_mesh_line(ry0=", ry0, ", xi=", xi, ", y1_i=", y1_i, ")");
|
||||
}
|
||||
|
||||
// The requested location is off the mesh. Return UBL_Z_RAISE_WHEN_OFF_MESH or NAN.
|
||||
return _UBL_OUTER_Z_RAISE;
|
||||
}
|
||||
|
||||
const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * RECIPROCAL(MESH_Y_DIST),
|
||||
z1 = z_values[xi][y1_i];
|
||||
|
||||
return z1 + yratio * (z_values[xi][_MIN(y1_i, GRID_MAX_POINTS_Y - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
|
||||
// If it is, it is clamped to the last element of the
|
||||
// z_values[][] array and no correction is applied.
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the generic Z-Correction. It works anywhere within a Mesh Cell. It first
|
||||
* does a linear interpolation along both of the bounding X-Mesh-Lines to find the
|
||||
* Z-Height at both ends. Then it does a linear interpolation of these heights based
|
||||
* on the Y position within the cell.
|
||||
*/
|
||||
static float get_z_correction(const float &rx0, const float &ry0) {
|
||||
const int8_t cx = cell_index_x(rx0), cy = cell_index_y(ry0); // return values are clamped
|
||||
|
||||
/**
|
||||
* Check if the requested location is off the mesh. If so, and
|
||||
* UBL_Z_RAISE_WHEN_OFF_MESH is specified, that value is returned.
|
||||
*/
|
||||
#ifdef UBL_Z_RAISE_WHEN_OFF_MESH
|
||||
if (!WITHIN(rx0, MESH_MIN_X, MESH_MAX_X) || !WITHIN(ry0, MESH_MIN_Y, MESH_MAX_Y))
|
||||
return UBL_Z_RAISE_WHEN_OFF_MESH;
|
||||
#endif
|
||||
|
||||
const float z1 = calc_z0(rx0,
|
||||
mesh_index_to_xpos(cx), z_values[cx][cy],
|
||||
mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][cy]);
|
||||
|
||||
const float z2 = calc_z0(rx0,
|
||||
mesh_index_to_xpos(cx), z_values[cx][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1],
|
||||
mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1]);
|
||||
|
||||
float z0 = calc_z0(ry0,
|
||||
mesh_index_to_ypos(cy), z1,
|
||||
mesh_index_to_ypos(cy + 1), z2);
|
||||
if (isnan(z0)) { // if part of the Mesh is undefined, it will show up as NAN
|
||||
z0 = 0.0; // in ubl.z_values[][] and propagate through the
|
||||
// calculations. If our correction is NAN, we throw it out
|
||||
// because part of the Mesh is undefined and we don't have the
|
||||
// information we need to complete the height correction.
|
||||
|
||||
if (DEBUGGING(MESH_ADJUST)) {
|
||||
DEBUG_ECHOPAIR(" raw get_z_correction(", rx0);
|
||||
DEBUG_CHAR(','); DEBUG_ECHO(ry0);
|
||||
DEBUG_ECHOPAIR_F(") = ", z0, 6);
|
||||
DEBUG_ECHOLNPAIR_F(" >>>---> ", z0, 6);
|
||||
DEBUG_ECHOPAIR("??? Yikes! NAN in get_z_correction(", rx0);
|
||||
DEBUG_CHAR(',');
|
||||
DEBUG_ECHO(ry0);
|
||||
DEBUG_CHAR(')');
|
||||
DEBUG_EOL();
|
||||
}
|
||||
|
||||
if (isnan(z0)) { // if part of the Mesh is undefined, it will show up as NAN
|
||||
z0 = 0.0; // in ubl.z_values[][] and propagate through the
|
||||
// calculations. If our correction is NAN, we throw it out
|
||||
// because part of the Mesh is undefined and we don't have the
|
||||
// information we need to complete the height correction.
|
||||
|
||||
if (DEBUGGING(MESH_ADJUST)) {
|
||||
DEBUG_ECHOPAIR("??? Yikes! NAN in get_z_correction(", rx0);
|
||||
DEBUG_CHAR(',');
|
||||
DEBUG_ECHO(ry0);
|
||||
DEBUG_CHAR(')');
|
||||
DEBUG_EOL();
|
||||
}
|
||||
}
|
||||
return z0;
|
||||
}
|
||||
static inline float get_z_correction(const xy_pos_t &pos) { return get_z_correction(pos.x, pos.y); }
|
||||
return z0;
|
||||
}
|
||||
static inline float get_z_correction(const xy_pos_t &pos) { return get_z_correction(pos.x, pos.y); }
|
||||
|
||||
static inline float mesh_index_to_xpos(const uint8_t i) {
|
||||
return i < GRID_MAX_POINTS_X ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
|
||||
}
|
||||
static inline float mesh_index_to_ypos(const uint8_t i) {
|
||||
return i < GRID_MAX_POINTS_Y ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
|
||||
}
|
||||
static inline float mesh_index_to_xpos(const uint8_t i) {
|
||||
return i < GRID_MAX_POINTS_X ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
|
||||
}
|
||||
static inline float mesh_index_to_ypos(const uint8_t i) {
|
||||
return i < GRID_MAX_POINTS_Y ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
|
||||
}
|
||||
|
||||
#if UBL_SEGMENTED
|
||||
static bool line_to_destination_segmented(const feedRate_t &scaled_fr_mm_s);
|
||||
#else
|
||||
static void line_to_destination_cartesian(const feedRate_t &scaled_fr_mm_s, const uint8_t e);
|
||||
#endif
|
||||
#if UBL_SEGMENTED
|
||||
static bool line_to_destination_segmented(const feedRate_t &scaled_fr_mm_s);
|
||||
#else
|
||||
static void line_to_destination_cartesian(const feedRate_t &scaled_fr_mm_s, const uint8_t e);
|
||||
#endif
|
||||
|
||||
static inline bool mesh_is_valid() {
|
||||
GRID_LOOP(x, y) if (isnan(z_values[x][y])) return false;
|
||||
return true;
|
||||
}
|
||||
static inline bool mesh_is_valid() {
|
||||
GRID_LOOP(x, y) if (isnan(z_values[x][y])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // class unified_bed_leveling
|
||||
|
||||
|
||||
+1617
-1610
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user