Merge branch 'bugfix-2.0.x' into CrealityDwin2.0_Bleeding

This commit is contained in:
InsanityAutomation
2021-11-11 21:23:58 -05:00
417 changed files with 7832 additions and 3960 deletions
+1 -5
View File
@@ -27,7 +27,7 @@ bdf2u8g
# OS
#
applet/
*.DS_Store
.DS_Store
#
# Misc
@@ -167,7 +167,3 @@ __pycache__
# IOLogger logs
*_log.csv
# Simulation / Native
eeprom.dat
imgui.ini
+28 -27
View File
@@ -291,7 +291,7 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
#define CONFIGURATION_H_VERSION 02000902
#define CONFIGURATION_H_VERSION 02000903
//===========================================================================
//============================= Getting Started =============================
@@ -888,7 +888,6 @@
#define PARKING_EXTRUDER_PARKING_X { -78, 184 } // X positions for parking the extruders
#define PARKING_EXTRUDER_GRAB_DISTANCE 1 // (mm) Distance to move beyond the parking point to grab the extruder
//#define MANUAL_SOLENOID_CONTROL // Manual control of docking solenoids with M380 S / M381
#if ENABLED(PARKING_EXTRUDER)
@@ -2257,6 +2256,15 @@
#endif
#endif
/**
* Probe Enable / Disable
* The probe only provides a triggered signal when enabled.
*/
//#define PROBE_ENABLE_DISABLE
#if ENABLED(PROBE_ENABLE_DISABLE)
//#define PROBE_ENABLE_PIN -1 // Override the default pin here
#endif
/**
* Multiple Probing
*
@@ -4100,32 +4108,32 @@
*/
//
// 480x320, 3.5", SPI Display From MKS
// Normally used in MKS Robin Nano V2
// 480x320, 3.5", SPI Display with Rotary Encoder from MKS
// Usually paired with MKS Robin Nano V2 & V3
//
//#define MKS_TS35_V2_0
//
// 320x240, 2.4", FSMC Display From MKS
// Normally used in MKS Robin Nano V1.2
// Usually paired with MKS Robin Nano V1.2
//
//#define MKS_ROBIN_TFT24
//
// 320x240, 2.8", FSMC Display From MKS
// Normally used in MKS Robin Nano V1.2
// Usually paired with MKS Robin Nano V1.2
//
//#define MKS_ROBIN_TFT28
//
// 320x240, 3.2", FSMC Display From MKS
// Normally used in MKS Robin Nano V1.2
// Usually paired with MKS Robin Nano V1.2
//
//#define MKS_ROBIN_TFT32
//
// 480x320, 3.5", FSMC Display From MKS
// Normally used in MKS Robin Nano V1.2
// Usually paired with MKS Robin Nano V1.2
//
//#define MKS_ROBIN_TFT35
@@ -4136,7 +4144,7 @@
//
// 320x240, 3.2", FSMC Display From MKS
// Normally used in MKS Robin
// Usually paired with MKS Robin
//
//#define MKS_ROBIN_TFT_V1_1R
@@ -4166,10 +4174,15 @@
//#define ANET_ET5_TFT35
//
// 1024x600, 7", RGB Stock Display from BIQU-BX
// 1024x600, 7", RGB Stock Display with Rotary Encoder from BIQU-BX
//
//#define BIQU_BX_TFT70
//
// 480x320, 3.5", SPI Stock Display with Rotary Encoder from BIQU B1 SE Series
//
//#define BTT_TFT35_SPI_V1_0
//
// Generic TFT with detailed options
//
@@ -4224,23 +4237,11 @@
//
// Ender-3 v2 OEM display. A DWIN display with Rotary Encoder.
//
//#define DWIN_CREALITY_LCD
//
// Ender-3 v2 OEM display, enhanced.
//
//#define DWIN_CREALITY_LCD_ENHANCED
//
// Ender-3 v2 OEM display with enhancements by Jacob Myers
//
//#define DWIN_CREALITY_LCD_JYERSUI
//
// MarlinUI for Creality's DWIN display (and others)
//
//#define DWIN_MARLINUI_PORTRAIT
//#define DWIN_MARLINUI_LANDSCAPE
//#define DWIN_CREALITY_LCD // Creality UI
//#define DWIN_CREALITY_LCD_ENHANCED // Enhanced UI
//#define DWIN_CREALITY_LCD_JYERSUI // Jyers UI by Jacob Myers
//#define DWIN_MARLINUI_PORTRAIT // MarlinUI (portrait orientation)
//#define DWIN_MARLINUI_LANDSCAPE // MarlinUI (landscape orientation)
//
// Touch Screen Settings
+63 -47
View File
@@ -30,7 +30,7 @@
*
* Basic settings can be found in Configuration.h
*/
#define CONFIGURATION_ADV_H_VERSION 02000902
#define CONFIGURATION_ADV_H_VERSION 02000903
//===========================================================================
//============================= Thermal Settings ============================
@@ -437,7 +437,7 @@
#define AUTOTEMP
#endif
#if ENABLED(AUTOTEMP)
#define AUTOTEMP_OLDWEIGHT 0.98
#define AUTOTEMP_OLDWEIGHT 0.98 // Factor used to weight previous readings (0.0 < value < 1.0)
// Turn on AUTOTEMP on M104/M109 by default using proportions set here
//#define AUTOTEMP_PROPORTIONAL
#if ENABLED(AUTOTEMP_PROPORTIONAL)
@@ -1340,7 +1340,7 @@
#endif // HAS_LCD_MENU
#if HAS_DISPLAY
#if EITHER(HAS_DISPLAY, DWIN_CREALITY_LCD_ENHANCED)
// The timeout (in ms) to return to the status screen from sub-menus
#define LCD_TIMEOUT_TO_STATUS 15000
@@ -2012,6 +2012,7 @@
#define LIN_ADVANCE_K 0.0 // Unit: mm compression per 1mm/s extruder speed
//#define LA_DEBUG // If enabled, this will generate debug information output over USB.
#define EXPERIMENTAL_SCURVE // Enable this option to permit S-Curve Acceleration
#define ALLOW_LOW_EJERK // Allow a DEFAULT_EJERK value of <10. Recommended for direct drive hotends.
#endif
// @section leveling
@@ -2089,59 +2090,69 @@
/**
* Thermal Probe Compensation
* Probe measurements are adjusted to compensate for temperature distortion.
* Use G76 to calibrate this feature. Use M871 to set values manually.
* For a more detailed explanation of the process see G76_M871.cpp.
*
* Adjust probe measurements to compensate for distortion associated with the temperature
* of the probe, bed, and/or hotend.
* Use G76 to automatically calibrate this feature for probe and bed temperatures.
* (Extruder temperature/offset values must be calibrated manually.)
* Use M871 to set temperature/offset values manually.
* For more details see https://marlinfw.org/docs/features/probe_temp_compensation.html
*/
#if HAS_BED_PROBE && TEMP_SENSOR_PROBE && TEMP_SENSOR_BED
// Enable thermal first layer compensation using bed and probe temperatures
#define PROBE_TEMP_COMPENSATION
//#define PTC_PROBE // Compensate based on probe temperature
//#define PTC_BED // Compensate based on bed temperature
//#define PTC_HOTEND // Compensate based on hotend temperature
// Add additional compensation depending on hotend temperature
// Note: this values cannot be calibrated and have to be set manually
#if ENABLED(PROBE_TEMP_COMPENSATION)
#if ANY(PTC_PROBE, PTC_BED, PTC_HOTEND)
/**
* If the probe is outside the defined range, use linear extrapolation with the closest
* point and the point with index PTC_LINEAR_EXTRAPOLATION. e.g., If set to 4 it will use the
* linear extrapolation between data[0] and data[4] for values below PTC_PROBE_START.
*/
//#define PTC_LINEAR_EXTRAPOLATION 4
#if ENABLED(PTC_PROBE)
// Probe temperature calibration generates a table of values starting at PTC_PROBE_START
// (e.g., 30), in steps of PTC_PROBE_RES (e.g., 5) with PTC_PROBE_COUNT (e.g., 10) samples.
#define PTC_PROBE_START 30 // (°C)
#define PTC_PROBE_RES 5 // (°C)
#define PTC_PROBE_COUNT 10
#define PTC_PROBE_ZOFFS { 0 } // (µm) Z adjustments per sample
#endif
#if ENABLED(PTC_BED)
// Bed temperature calibration builds a similar table.
#define PTC_BED_START 60 // (°C)
#define PTC_BED_RES 5 // (°C)
#define PTC_BED_COUNT 10
#define PTC_BED_ZOFFS { 0 } // (µm) Z adjustments per sample
#endif
#if ENABLED(PTC_HOTEND)
// Note: There is no automatic calibration for the hotend. Use M871.
#define PTC_HOTEND_START 180 // (°C)
#define PTC_HOTEND_RES 5 // (°C)
#define PTC_HOTEND_COUNT 20
#define PTC_HOTEND_ZOFFS { 0 } // (µm) Z adjustments per sample
#endif
// G76 options
#if BOTH(PTC_PROBE, PTC_BED)
// Park position to wait for probe cooldown
#define PTC_PARK_POS { 0, 0, 100 }
// Probe position to probe and wait for probe to reach target temperature
//#define PTC_PROBE_POS { 12.0f, 7.3f } // Example: MK52 magnetic heatbed
#define PTC_PROBE_POS { 90, 100 }
// Enable additional compensation using hotend temperature
// Note: this values cannot be calibrated automatically but have to be set manually
//#define USE_TEMP_EXT_COMPENSATION
// Probe temperature calibration generates a table of values starting at PTC_SAMPLE_START
// (e.g., 30), in steps of PTC_SAMPLE_RES (e.g., 5) with PTC_SAMPLE_COUNT (e.g., 10) samples.
//#define PTC_SAMPLE_START 30 // (°C)
//#define PTC_SAMPLE_RES 5 // (°C)
//#define PTC_SAMPLE_COUNT 10
// Bed temperature calibration builds a similar table.
//#define BTC_SAMPLE_START 60 // (°C)
//#define BTC_SAMPLE_RES 5 // (°C)
//#define BTC_SAMPLE_COUNT 10
// The temperature the probe should be at while taking measurements during bed temperature
// calibration.
//#define BTC_PROBE_TEMP 30 // (°C)
// The temperature the probe should be at while taking measurements during
// bed temperature calibration.
#define PTC_PROBE_TEMP 30 // (°C)
// Height above Z=0.0 to raise the nozzle. Lowering this can help the probe to heat faster.
// Note: the Z=0.0 offset is determined by the probe offset which can be set using M851.
//#define PTC_PROBE_HEATING_OFFSET 0.5
// Height to raise the Z-probe between heating and taking the next measurement. Some probes
// may fail to untrigger if they have been triggered for a long time, which can be solved by
// increasing the height the probe is raised to.
//#define PTC_PROBE_RAISE 15
// If the probe is outside of the defined range, use linear extrapolation using the closest
// point and the PTC_LINEAR_EXTRAPOLATION'th next point. E.g. if set to 4 it will use data[0]
// and data[4] to perform linear extrapolation for values below PTC_SAMPLE_START.
//#define PTC_LINEAR_EXTRAPOLATION 4
// Note: The Z=0.0 offset is determined by the probe Z offset (e.g., as set with M851 Z).
#define PTC_PROBE_HEATING_OFFSET 0.5
#endif
#endif
#endif // PTC_PROBE || PTC_BED || PTC_HOTEND
// @section extras
@@ -2436,6 +2447,7 @@
*/
//#define EVENT_GCODE_TOOLCHANGE_T0 "G28 A\nG1 A0" // Extra G-code to run while executing tool-change command T0
//#define EVENT_GCODE_TOOLCHANGE_T1 "G1 A10" // Extra G-code to run while executing tool-change command T1
//#define EVENT_GCODE_TOOLCHANGE_ALWAYS_RUN // Always execute above G-code sequences. Use with caution!
/**
* Tool Sensors detect when tools have been picked up or dropped.
@@ -4013,11 +4025,12 @@
*/
#define HOST_ACTION_COMMANDS
#if ENABLED(HOST_ACTION_COMMANDS)
//#define HOST_PAUSE_M76
#if DISABLED(MachineCR10Orig) || ENABLED(MelziHostOnly)
//#define HOST_PAUSE_M76
#define HOST_PROMPT_SUPPORT
#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start
#endif
#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start
//#define HOST_SHUTDOWN_MENU_ITEM // Add a menu item that tells the host to shut down
#endif
/**
@@ -4394,3 +4407,6 @@
*/
//#define SOFT_RESET_VIA_SERIAL // 'KILL' and '^X' commands will soft-reset the controller
//#define SOFT_RESET_ON_KILL // Use a digital button to soft-reset the controller after KILL
// Report uncleaned reset reason from register r2 instead of MCUSR. Supported by Optiboot on AVR.
//#define OPTIBOOT_RESET_REASON
+1 -1
View File
@@ -125,7 +125,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
#define STRING_DISTRIBUTION_DATE "2021-10-15"
#define STRING_DISTRIBUTION_DATE "2021-11-12"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.
+20 -1
View File
@@ -35,12 +35,31 @@
// Public Variables
// ------------------------
//uint8_t MCUSR;
// Don't initialize/override variable (which would happen in .init4)
uint8_t reset_reason __attribute__((section(".noinit")));
// ------------------------
// Public functions
// ------------------------
__attribute__((naked)) // Don't output function pro- and epilogue
__attribute__((used)) // Output the function, even if "not used"
__attribute__((section(".init3"))) // Put in an early user definable section
void HAL_save_reset_reason() {
#if ENABLED(OPTIBOOT_RESET_REASON)
__asm__ __volatile__(
A("STS %0, r2")
: "=m"(reset_reason)
);
#else
reset_reason = MCUSR;
#endif
// Clear within 16ms since WDRF bit enables a 16ms watchdog timer -> Boot loop
MCUSR = 0;
wdt_disable();
}
void HAL_init() {
// Init Servo Pins
#define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW)
+6 -8
View File
@@ -91,7 +91,7 @@ typedef int8_t pin_t;
// Public Variables
// ------------------------
//extern uint8_t MCUSR;
extern uint8_t reset_reason;
// Serial ports
#ifdef USBCON
@@ -152,21 +152,19 @@ void HAL_init();
//void _delay_ms(const int delay);
inline void HAL_clear_reset_source() { MCUSR = 0; }
inline uint8_t HAL_get_reset_source() { return MCUSR; }
inline void HAL_clear_reset_source() { }
inline uint8_t HAL_get_reset_source() { return reset_reason; }
void HAL_reboot();
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
extern "C" int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
// ADC
#ifdef DIDR2
@@ -223,7 +221,7 @@ void set_pwm_frequency(const pin_t pin, int f_desired);
/**
* set_pwm_duty
* Sets the PWM duty cycle of the provided pin to the provided value
* Set the PWM duty cycle of the provided pin to the provided value
* Optionally allows inverting the duty cycle [default = false]
* Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
*/
+31 -33
View File
@@ -22,11 +22,10 @@
#ifdef __AVR__
#include "../../inc/MarlinConfigPre.h"
#include "HAL.h"
#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM
#include "HAL.h"
struct Timer {
volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer
volatile uint16_t* OCRnQ[3]; // max 3 OCR registers per timer
@@ -153,7 +152,7 @@ Timer get_pwm_timer(const pin_t pin) {
void set_pwm_frequency(const pin_t pin, int f_desired) {
Timer timer = get_pwm_timer(pin);
if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
if (timer.n == 0) return; // Don't proceed if protected timer or not recognized
uint16_t size;
if (timer.n == 2) size = 255; else size = 65535;
@@ -243,40 +242,39 @@ void set_pwm_frequency(const pin_t pin, int f_desired) {
_SET_ICRn(timer.ICRn, res); // Set ICRn value (TOP) = res
}
#endif // NEEDS_HARDWARE_PWM
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
// If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
// Note that digitalWrite also disables pwm output for us (sets COM bit to 0)
if (v == 0)
digitalWrite(pin, invert);
else if (v == v_size)
digitalWrite(pin, !invert);
else {
Timer timer = get_pwm_timer(pin);
if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
// Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted)
_SET_COMnQ(timer.TCCRnQ, (timer.q
#ifdef TCCR2
+ (timer.q == 2) // COM20 is on bit 4 of TCCR2, thus requires q + 1 in the macro
#endif
), COM_CLEAR_SET + invert
);
#if NEEDS_HARDWARE_PWM
uint16_t top;
if (timer.n == 2) { // if TIMER2
top = (
#if ENABLED(USE_OCR2A_AS_TOP)
*timer.OCRnQ[0] // top = OCR2A
#else
255 // top = 0xFF (max)
#endif
// If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
// Note that digitalWrite also disables pwm output for us (sets COM bit to 0)
if (v == 0)
digitalWrite(pin, invert);
else if (v == v_size)
digitalWrite(pin, !invert);
else {
Timer timer = get_pwm_timer(pin);
if (timer.n == 0) return; // Don't proceed if protected timer or not recognized
// Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted)
_SET_COMnQ(timer.TCCRnQ, (timer.q
#ifdef TCCR2
+ (timer.q == 2) // COM20 is on bit 4 of TCCR2, thus requires q + 1 in the macro
#endif
), COM_CLEAR_SET + invert
);
}
else
top = *timer.ICRn; // top = ICRn
_SET_OCRnQ(timer.OCRnQ, timer.q, v * float(top) / float(v_size)); // Scale 8/16-bit v to top value
}
uint16_t top = (timer.n == 2) ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn;
_SET_OCRnQ(timer.OCRnQ, timer.q, (v * top + v_size / 2) / v_size); // Scale 8/16-bit v to top value
}
#else
analogWrite(pin, v);
UNUSED(v_size);
UNUSED(invert);
#endif
}
#endif // NEEDS_HARDWARE_PWM
#endif // __AVR__
+7 -4
View File
@@ -144,6 +144,11 @@ inline void HAL_adc_init() {}//todo
void HAL_adc_start_conversion(const uint8_t ch);
uint16_t HAL_adc_get_result();
//
// PWM
//
inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); }
//
// Pin Map
//
@@ -168,16 +173,14 @@ void HAL_init();
//
void _delay_ms(const int delay);
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
#ifdef __cplusplus
extern "C" {
+10 -9
View File
@@ -4,15 +4,16 @@
# Windows: bossac.exe
# Other: leave unchanged
#
import pioutil
if pioutil.is_pio_build():
import platform
current_OS = platform.system()
import platform
current_OS = platform.system()
if current_OS == 'Windows':
if current_OS == 'Windows':
Import("env")
Import("env")
# Use bossac.exe on Windows
env.Replace(
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
)
# Use bossac.exe on Windows
env.Replace(
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
)
+6 -4
View File
@@ -105,16 +105,14 @@ void HAL_reboot();
void _delay_ms(int delay);
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
void analogWrite(pin_t pin, int value);
@@ -131,6 +129,10 @@ void HAL_adc_init();
void HAL_adc_start_conversion(const uint8_t adc_pin);
// PWM
inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); }
// Pin Map
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
+14 -16
View File
@@ -64,12 +64,9 @@ uint32_t i2s_port_data = 0;
#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
static inline void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) {
//if pin = -1, do not need to configure
if (gpio != -1) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv);
}
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv);
}
static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num) {
@@ -256,13 +253,7 @@ int i2s_init() {
I2S0.fifo_conf.dscr_en = 0;
I2S0.conf_chan.tx_chan_mod = (
#if ENABLED(I2S_STEPPER_SPLIT_STREAM)
4
#else
0
#endif
);
I2S0.conf_chan.tx_chan_mod = TERN(I2S_STEPPER_SPLIT_STREAM, 4, 0);
I2S0.fifo_conf.tx_fifo_mod = 0;
I2S0.conf.tx_mono = 0;
@@ -313,9 +304,16 @@ int i2s_init() {
xTaskCreatePinnedToCore(stepperTask, "StepperTask", 10000, nullptr, 1, nullptr, CONFIG_ARDUINO_RUNNING_CORE); // run I2S stepper task on same core as rest of Marlin
// Route the i2s pins to the appropriate GPIO
gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0);
gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0);
gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0);
// If a pin is not defined, no need to configure
#if defined(I2S_DATA) && I2S_DATA >= 0
gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0);
#endif
#if defined(I2S_BCK) && I2S_BCK >= 0
gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0);
#endif
#if defined(I2S_WS) && I2S_WS >= 0
gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0);
#endif
// Start the I2S peripheral
return i2s_start(I2S_NUM_0);
+5 -4
View File
@@ -79,16 +79,14 @@ extern MSerialT usb_serial;
inline void HAL_init() {}
// Utility functions
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
// ADC
#define HAL_ADC_VREF 5.0
@@ -103,6 +101,9 @@ void HAL_adc_enable_channel(const uint8_t ch);
void HAL_adc_start_conversion(const uint8_t ch);
uint16_t HAL_adc_get_result();
// PWM
inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); }
// Reset source
inline void HAL_clear_reset_source(void) {}
inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; }
+2 -4
View File
@@ -123,16 +123,14 @@ extern DefaultSerial1 USBSerial;
//
// Utility functions
//
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
//
// ADC API
+8 -8
View File
@@ -22,18 +22,18 @@
#ifdef TARGET_LPC1768
#include "../../inc/MarlinConfigPre.h"
#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM
#include <pwm.h>
void set_pwm_frequency(const pin_t pin, int f_desired) {
LPC176x::pwm_set_frequency(pin, f_desired);
}
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
LPC176x::pwm_write_ratio(pin, invert ? 1.0f - (float)v / v_size : (float)v / v_size);
}
#endif // NEEDS_HARDWARE_PWM
#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM
void set_pwm_frequency(const pin_t pin, int f_desired) {
LPC176x::pwm_set_frequency(pin, f_desired);
}
#endif
#endif // TARGET_LPC1768
+102 -98
View File
@@ -1,123 +1,127 @@
#
# sets output_port
# upload_extra_script.py
# set the output_port
# if target_filename is found then that drive is used
# else if target_drive is found then that drive is used
#
from __future__ import print_function
target_filename = "FIRMWARE.CUR"
target_drive = "REARM"
import pioutil
if pioutil.is_pio_build():
import os,getpass,platform
target_filename = "FIRMWARE.CUR"
target_drive = "REARM"
current_OS = platform.system()
Import("env")
import os,getpass,platform
def print_error(e):
print('\nUnable to find destination disk (%s)\n' \
'Please select it in platformio.ini using the upload_port keyword ' \
'(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \
'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \
%(e, env.get('PIOENV')))
current_OS = platform.system()
Import("env")
def before_upload(source, target, env):
try:
#
# Find a disk for upload
#
upload_disk = 'Disk not found'
target_file_found = False
target_drive_found = False
if current_OS == 'Windows':
def print_error(e):
print('\nUnable to find destination disk (%s)\n' \
'Please select it in platformio.ini using the upload_port keyword ' \
'(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \
'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \
%(e, env.get('PIOENV')))
def before_upload(source, target, env):
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,string
from ctypes import windll
# Find a disk for upload
#
upload_disk = 'Disk not found'
target_file_found = False
target_drive_found = False
if current_OS == 'Windows':
#
# 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,string
from ctypes import windll
# getting list of drives
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
drives = []
bitmask = windll.kernel32.GetLogicalDrives()
for letter in string.ascii_uppercase:
if bitmask & 1:
drives.append(letter)
bitmask >>= 1
# getting list of drives
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
drives = []
bitmask = windll.kernel32.GetLogicalDrives()
for letter in string.ascii_uppercase:
if bitmask & 1:
drives.append(letter)
bitmask >>= 1
for drive in drives:
final_drive_name = drive + ':\\'
# print ('disc check: {}'.format(final_drive_name))
try:
volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
except Exception as e:
print ('error:{}'.format(e))
continue
else:
if target_drive in volume_info and not target_file_found: # set upload if not found target file yet
target_drive_found = True
upload_disk = final_drive_name
if target_filename in volume_info:
if not target_file_found:
for drive in drives:
final_drive_name = drive + ':\\'
# print ('disc check: {}'.format(final_drive_name))
try:
volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
except Exception as e:
print ('error:{}'.format(e))
continue
else:
if target_drive in volume_info and not target_file_found: # set upload if not found target file yet
target_drive_found = True
upload_disk = final_drive_name
target_file_found = True
if target_filename in volume_info:
if not target_file_found:
upload_disk = final_drive_name
target_file_found = True
elif current_OS == 'Linux':
#
# platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive'
#
drives = os.listdir(os.path.join(os.sep, 'media', getpass.getuser()))
if target_drive in drives: # If target drive is found, use it.
target_drive_found = True
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), target_drive) + os.sep
else:
elif current_OS == 'Linux':
#
# platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive'
#
drives = os.listdir(os.path.join(os.sep, 'media', getpass.getuser()))
if target_drive in drives: # If target drive is found, use it.
target_drive_found = True
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), target_drive) + os.sep
else:
for drive in drives:
try:
files = os.listdir(os.path.join(os.sep, 'media', getpass.getuser(), drive))
except:
continue
else:
if target_filename in files:
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), drive) + os.sep
target_file_found = True
break
#
# set upload_port to drive if found
#
if target_file_found or target_drive_found:
env.Replace(
UPLOAD_FLAGS="-P$UPLOAD_PORT"
)
elif current_OS == 'Darwin': # MAC
#
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
#
drives = os.listdir('/Volumes') # human readable names
if target_drive in drives and not target_file_found: # set upload if not found target file yet
target_drive_found = True
upload_disk = '/Volumes/' + target_drive + '/'
for drive in drives:
try:
files = os.listdir(os.path.join(os.sep, 'media', getpass.getuser(), drive))
filenames = os.listdir('/Volumes/' + drive + '/') # will get an error if the drive is protected
except:
continue
else:
if target_filename in files:
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), drive) + os.sep
if target_filename in filenames:
if not target_file_found:
upload_disk = '/Volumes/' + drive + '/'
target_file_found = True
break
#
# set upload_port to drive if found
#
#
# Set upload_port to drive if found
#
if target_file_found or target_drive_found:
env.Replace(
UPLOAD_FLAGS="-P$UPLOAD_PORT"
)
env.Replace(UPLOAD_PORT=upload_disk)
print('\nUpload disk: ', upload_disk, '\n')
else:
print_error('Autodetect Error')
elif current_OS == 'Darwin': # MAC
#
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
#
drives = os.listdir('/Volumes') # human readable names
if target_drive in drives and not target_file_found: # set upload if not found target file yet
target_drive_found = True
upload_disk = '/Volumes/' + target_drive + '/'
for drive in drives:
try:
filenames = os.listdir('/Volumes/' + drive + '/') # will get an error if the drive is protected
except:
continue
else:
if target_filename in filenames:
if not target_file_found:
upload_disk = '/Volumes/' + drive + '/'
target_file_found = True
except Exception as e:
print_error(str(e))
#
# Set upload_port to drive if found
#
if target_file_found or target_drive_found:
env.Replace(UPLOAD_PORT=upload_disk)
print('\nUpload disk: ', upload_disk, '\n')
else:
print_error('Autodetect Error')
except Exception as e:
print_error(str(e))
env.AddPreAction("upload", before_upload)
env.AddPreAction("upload", before_upload)
+3
View File
@@ -133,6 +133,9 @@ void HAL_adc_enable_channel(const uint8_t ch);
void HAL_adc_start_conversion(const uint8_t ch);
uint16_t HAL_adc_get_result();
// PWM
inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); }
// Reset source
inline void HAL_clear_reset_source(void) {}
inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; }
+7 -4
View File
@@ -127,6 +127,11 @@ void HAL_adc_init();
void HAL_adc_start_conversion(const uint8_t adc_pin);
//
// PWM
//
inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); }
//
// Pin Map
//
@@ -153,16 +158,14 @@ void HAL_idletask();
//
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
#ifdef __cplusplus
extern "C" {
+1 -1
View File
@@ -154,7 +154,7 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) { HAL_adc_result = analogRe
uint16_t HAL_adc_get_result() { return HAL_adc_result; }
// Reset the system to initiate a firmware flash
void flashFirmware(const int16_t) { HAL_reboot(); }
WEAK void flashFirmware(const int16_t) { HAL_reboot(); }
// Maple Compatibility
volatile uint32_t systick_uptime_millis = 0;
+20 -19
View File
@@ -24,32 +24,17 @@
#ifdef HAL_STM32
#include "../../inc/MarlinConfigPre.h"
#if NEEDS_HARDWARE_PWM
#include "HAL.h"
#include "../../inc/MarlinConfig.h"
#include "timers.h"
void set_pwm_frequency(const pin_t pin, int f_desired) {
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
PinName pin_name = digitalPinToPinName(pin);
TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance
LOOP_S_L_N(i, 0, NUM_HARDWARE_TIMERS) // Protect used timers
if (timer_instance[i] && timer_instance[i]->getHandle()->Instance == Instance)
return;
pwm_start(pin_name, f_desired, 0, RESOLUTION_8B_COMPARE_FORMAT);
}
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
PinName pin_name = digitalPinToPinName(pin);
TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM);
uint16_t adj_val = Instance->ARR * v / v_size;
if (invert) adj_val = Instance->ARR - adj_val;
switch (get_pwm_channel(pin_name)) {
case TIM_CHANNEL_1: LL_TIM_OC_SetCompareCH1(Instance, adj_val); break;
case TIM_CHANNEL_2: LL_TIM_OC_SetCompareCH2(Instance, adj_val); break;
@@ -58,5 +43,21 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255
}
}
#endif // NEEDS_HARDWARE_PWM
#if NEEDS_HARDWARE_PWM
void set_pwm_frequency(const pin_t pin, int f_desired) {
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
PinName pin_name = digitalPinToPinName(pin);
TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance
LOOP_S_L_N(i, 0, NUM_HARDWARE_TIMERS) // Protect used timers
if (timer_instance[i] && timer_instance[i]->getHandle()->Instance == Instance)
return;
pwm_start(pin_name, f_desired, 0, RESOLUTION_8B_COMPARE_FORMAT);
}
#endif
#endif // HAL_STM32
+1 -2
View File
@@ -449,8 +449,7 @@ uint16_t analogRead(pin_t pin) {
// Wrapper to maple unprotected analogWrite
void analogWrite(pin_t pin, int pwm_val8) {
if (PWM_PIN(pin))
analogWrite(uint8_t(pin), pwm_val8);
if (PWM_PIN(pin)) analogWrite(uint8_t(pin), pwm_val8);
}
void HAL_reboot() { nvic_sys_reset(); }
+16 -14
View File
@@ -30,25 +30,27 @@ if __name__ == "__main__":
# extra script for linker options
else:
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
env.Append(
import pioutil
if pioutil.is_pio_build():
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
env.Append(
ARFLAGS=["rcs"],
ASFLAGS=["-x", "assembler-with-cpp"],
CXXFLAGS=[
"-fabi-version=0",
"-fno-use-cxa-atexit",
"-fno-threadsafe-statics"
"-fabi-version=0",
"-fno-use-cxa-atexit",
"-fno-threadsafe-statics"
],
LINKFLAGS=[
"-Os",
"-mcpu=cortex-m3",
"-ffreestanding",
"-mthumb",
"--specs=nano.specs",
"--specs=nosys.specs",
"-u_printf_float",
"-Os",
"-mcpu=cortex-m3",
"-ffreestanding",
"-mthumb",
"--specs=nano.specs",
"--specs=nosys.specs",
"-u_printf_float",
],
)
)
+31 -30
View File
@@ -23,46 +23,47 @@
#include "../../inc/MarlinConfigPre.h"
#if NEEDS_HARDWARE_PWM
#include <pwm.h>
#include "HAL.h"
#include "timers.h"
void set_pwm_frequency(const pin_t pin, int f_desired) {
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
timer_dev *timer = PIN_MAP[pin].timer_device;
uint8_t channel = PIN_MAP[pin].timer_channel;
// Protect used timers
if (timer == get_timer_dev(TEMP_TIMER_NUM)) return;
if (timer == get_timer_dev(STEP_TIMER_NUM)) return;
#if PULSE_TIMER_NUM != STEP_TIMER_NUM
if (timer == get_timer_dev(PULSE_TIMER_NUM)) return;
#endif
if (!(timer->regs.bas->SR & TIMER_CR1_CEN)) // Ensure the timer is enabled
timer_init(timer);
timer_set_mode(timer, channel, TIMER_PWM);
uint16_t preload = 255; // Lock 255 PWM resolution for high frequencies
int32_t prescaler = (HAL_TIMER_RATE) / (preload + 1) / f_desired - 1;
if (prescaler > 65535) { // For low frequencies increase prescaler
prescaler = 65535;
preload = (HAL_TIMER_RATE) / (prescaler + 1) / f_desired - 1;
}
if (prescaler < 0) return; // Too high frequency
timer_set_reload(timer, preload);
timer_set_prescaler(timer, prescaler);
}
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
if (!PWM_PIN(pin)) return;
timer_dev *timer = PIN_MAP[pin].timer_device;
uint16_t max_val = timer->regs.bas->ARR * v / v_size;
if (invert) max_val = v_size - max_val;
pwmWrite(pin, max_val);
}
#if NEEDS_HARDWARE_PWM
void set_pwm_frequency(const pin_t pin, int f_desired) {
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
timer_dev *timer = PIN_MAP[pin].timer_device;
uint8_t channel = PIN_MAP[pin].timer_channel;
// Protect used timers
if (timer == get_timer_dev(TEMP_TIMER_NUM)) return;
if (timer == get_timer_dev(STEP_TIMER_NUM)) return;
#if PULSE_TIMER_NUM != STEP_TIMER_NUM
if (timer == get_timer_dev(PULSE_TIMER_NUM)) return;
#endif
if (!(timer->regs.bas->SR & TIMER_CR1_CEN)) // Ensure the timer is enabled
timer_init(timer);
timer_set_mode(timer, channel, TIMER_PWM);
uint16_t preload = 255; // Lock 255 PWM resolution for high frequencies
int32_t prescaler = (HAL_TIMER_RATE) / (preload + 1) / f_desired - 1;
if (prescaler > 65535) { // For low frequencies increase prescaler
prescaler = 65535;
preload = (HAL_TIMER_RATE) / (prescaler + 1) / f_desired - 1;
}
if (prescaler < 0) return; // Too high frequency
timer_set_reload(timer, preload);
timer_set_prescaler(timer, prescaler);
}
#endif // NEEDS_HARDWARE_PWM
#endif // __STM32F1__
+8 -4
View File
@@ -98,16 +98,14 @@ void HAL_reboot();
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
extern "C" int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
// ADC
@@ -124,6 +122,12 @@ void HAL_adc_init();
void HAL_adc_start_conversion(const uint8_t adc_pin);
uint16_t HAL_adc_get_result();
// PWM
inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); }
// Pin Map
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
+8 -4
View File
@@ -105,16 +105,14 @@ void HAL_reboot();
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
extern "C" int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
// ADC
@@ -131,6 +129,12 @@ void HAL_adc_init();
void HAL_adc_start_conversion(const uint8_t adc_pin);
uint16_t HAL_adc_get_result();
// PWM
inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); }
// Pin Map
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
+5 -5
View File
@@ -106,17 +106,17 @@ void HAL_adc_init() {
void HAL_clear_reset_source() {
uint32_t reset_source = SRC_SRSR;
SRC_SRSR = reset_source;
}
}
uint8_t HAL_get_reset_source() {
switch (SRC_SRSR & 0xFF) {
case 1: return RST_POWER_ON; break;
case 2: return RST_SOFTWARE; break;
case 4: return RST_EXTERNAL; break;
// case 8: return RST_BROWN_OUT; break;
//case 8: return RST_BROWN_OUT; break;
case 16: return RST_WATCHDOG; break;
case 64: return RST_JTAG; break;
// case 128: return RST_OVERTEMP; break;
case 64: return RST_JTAG; break;
//case 128: return RST_OVERTEMP; break;
}
return 0;
}
@@ -168,7 +168,7 @@ uint16_t HAL_adc_get_result() {
return 0;
}
bool is_output(uint8_t pin) {
bool is_output(pin_t pin) {
const struct digital_pin_bitband_and_config_table_struct *p;
p = digital_pin_to_info_PGM + pin;
return (*(p->reg + 1) & p->mask);
+9 -5
View File
@@ -125,16 +125,14 @@ void HAL_reboot();
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
extern "C" uint32_t freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
// ADC
@@ -152,8 +150,14 @@ void HAL_adc_init();
void HAL_adc_start_conversion(const uint8_t adc_pin);
uint16_t HAL_adc_get_result();
// PWM
inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); }
// Pin Map
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
bool is_output(uint8_t pin);
bool is_output(pin_t pin);
+12 -3
View File
@@ -92,6 +92,12 @@ void calibrate_delay_loop();
#define DELAY_CYCLES(X) do { SmartDelay<IS_CONSTEXPR(X), IS_CONSTEXPR(X) ? X : 0> _smrtdly_X(X); } while(0)
#if GCC_VERSION <= 70000
#define DELAY_CYCLES_VAR(X) DelayCycleFnc(X)
#else
#define DELAY_CYCLES_VAR DELAY_CYCLES
#endif
// For delay in microseconds, no smart delay selection is required, directly call the delay function
// Teensy compiler is too old and does not accept smart delay compile-time / run-time selection correctly
#define DELAY_US(x) DelayCycleFnc((x) * ((F_CPU) / 1000000UL))
@@ -200,9 +206,12 @@ void calibrate_delay_loop();
#endif
#if ENABLED(DELAY_NS_ROUND_DOWN)
#define DELAY_NS(x) DELAY_CYCLES((x) * ((F_CPU) / 1000000UL) / 1000UL) // floor
#define _NS_TO_CYCLES(x) ( (x) * ((F_CPU) / 1000000UL) / 1000UL) // floor
#elif ENABLED(DELAY_NS_ROUND_CLOSEST)
#define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 500) / 1000UL) // round
#define _NS_TO_CYCLES(x) (((x) * ((F_CPU) / 1000000UL) + 500) / 1000UL) // round
#else
#define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 999) / 1000UL) // "ceil"
#define _NS_TO_CYCLES(x) (((x) * ((F_CPU) / 1000000UL) + 999) / 1000UL) // "ceil"
#endif
#define DELAY_NS(x) DELAY_CYCLES(_NS_TO_CYCLES(x))
#define DELAY_NS_VAR(x) DELAY_CYCLES_VAR(_NS_TO_CYCLES(x))
+1 -1
View File
@@ -39,7 +39,7 @@
#define DISABLED(V...) DO(DIS,&&,V)
#undef _BV
#define _BV(b) (1UL << (b))
#define _BV(b) (1 << (b))
#ifndef SBI
#define SBI(A,B) (A |= _BV(B))
#endif
+15 -8
View File
@@ -216,6 +216,10 @@
#include "feature/controllerfan.h"
#endif
#if HAS_PRUSA_MMU1
#include "feature/mmu/mmu.h"
#endif
#if HAS_PRUSA_MMU2
#include "feature/mmu/mmu2.h"
#endif
@@ -872,7 +876,7 @@ void kill(FSTR_P const lcd_error/*=nullptr*/, FSTR_P const lcd_component/*=nullp
SERIAL_ERROR_MSG(STR_ERR_KILLED);
#ifdef ACTION_ON_KILL
host_action_kill();
hostui.kill();
#endif
minkill(steppers_off);
@@ -1100,6 +1104,10 @@ void setup() {
tmc_standby_setup(); // TMC Low Power Standby pins must be set early or they're not usable
// Check startup - does nothing if bootloader sets MCUSR to 0
const byte mcu = HAL_get_reset_source();
HAL_clear_reset_source();
#if ENABLED(MARLIN_DEV_MODE)
auto log_current_ms = [&](PGM_P const msg) {
SERIAL_ECHO_START();
@@ -1228,15 +1236,14 @@ void setup() {
SETUP_RUN(esp_wifi_init());
// Check startup - does nothing if bootloader sets MCUSR to 0
const byte mcu = HAL_get_reset_source();
// Report Reset Reason
if (mcu & RST_POWER_ON) SERIAL_ECHOLNPGM(STR_POWERUP);
if (mcu & RST_EXTERNAL) SERIAL_ECHOLNPGM(STR_EXTERNAL_RESET);
if (mcu & RST_BROWN_OUT) SERIAL_ECHOLNPGM(STR_BROWNOUT_RESET);
if (mcu & RST_WATCHDOG) SERIAL_ECHOLNPGM(STR_WATCHDOG_RESET);
if (mcu & RST_SOFTWARE) SERIAL_ECHOLNPGM(STR_SOFTWARE_RESET);
HAL_clear_reset_source();
// Identify myself as Marlin x.x.x
SERIAL_ECHOLNPGM("Marlin " SHORT_BUILD_VERSION);
#if defined(STRING_DISTRIBUTION_DATE) && defined(STRING_CONFIG_H_AUTHOR)
SERIAL_ECHO_MSG(
@@ -1525,7 +1532,7 @@ void setup() {
#endif
#if ENABLED(HOST_PROMPT_SUPPORT)
SETUP_RUN(host_action_prompt_end());
SETUP_RUN(hostui.prompt_end());
#endif
#if HAS_TRINAMIC_CONFIG && DISABLED(PSU_DEFAULT_OFF)
@@ -1547,15 +1554,15 @@ void setup() {
#endif
#if HAS_DWIN_E3V2_BASIC
SETUP_LOG("E3V2 Init");
Encoder_Configuration();
HMI_Init();
HMI_SetLanguageCache();
HMI_StartFrame(true);
DWIN_StatusChanged(GET_TEXT_F(WELCOME_MSG));
#endif
#if HAS_SERVICE_INTERVALS && !HAS_DWIN_E3V2_BASIC
ui.reset_status(true); // Show service messages or keep current status
SETUP_RUN(ui.reset_status(true)); // Show service messages or keep current status
#endif
#if ENABLED(MAX7219_DEBUG)
@@ -1586,7 +1593,7 @@ void setup() {
#endif
#if BOTH(HAS_LCD_MENU, TOUCH_SCREEN_CALIBRATION) && EITHER(TFT_CLASSIC_UI, TFT_COLOR_UI)
ui.check_touch_calibration();
SETUP_RUN(ui.check_touch_calibration());
#endif
marlin_state = MF_RUNNING;
+26 -22
View File
@@ -356,6 +356,7 @@
#define BOARD_ZONESTAR_ZM3E2 4056 // Zonestar ZM3E2 (STM32F103RCT6)
#define BOARD_ZONESTAR_ZM3E4 4057 // Zonestar ZM3E4 V1 (STM32F103VCT6)
#define BOARD_ZONESTAR_ZM3E4V2 4058 // Zonestar ZM3E4 V2 (STM32F103VCT6)
#define BOARD_ERYONE_ERY32_MINI 4059 // Eryone Ery32 mini (STM32F103VET6)
//
// ARM Cortex-M4F
@@ -385,25 +386,27 @@
#define BOARD_BTT_GTR_V1_0 4214 // BigTreeTech GTR v1.0 (STM32F407IGT)
#define BOARD_BTT_OCTOPUS_V1_0 4215 // BigTreeTech Octopus v1.0 (STM32F446ZET6)
#define BOARD_BTT_OCTOPUS_V1_1 4216 // BigTreeTech Octopus v1.1 (STM32F446ZET6)
#define BOARD_LERDGE_K 4217 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4218 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4219 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4220 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4221 // FYSETC S6 (STM32F446VET6)
#define BOARD_FYSETC_S6_V2_0 4222 // FYSETC S6 v2.0 (STM32F446VET6)
#define BOARD_FYSETC_SPIDER 4223 // FYSETC Spider (STM32F446VET6)
#define BOARD_FLYF407ZG 4224 // FLYmaker FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4225 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4226 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4227 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_MKS_MONSTER8 4228 // MKS Monster8 (STM32F407VGT6)
#define BOARD_ANET_ET4 4229 // ANET ET4 V1.x (STM32F407VGT6)
#define BOARD_ANET_ET4P 4230 // ANET ET4P V1.x (STM32F407VGT6)
#define BOARD_FYSETC_CHEETAH_V20 4231 // FYSETC Cheetah V2.0
#define BOARD_TH3D_EZBOARD_LITE_V2 4232 // TH3D EZBoard Lite v2.0
#define BOARD_INDEX_REV03 4233 // Index PnP Controller REV03 (STM32F407VET6/VGT6)
#define BOARD_MKS_ROBIN_NANO_V1_3_F4 4234 // MKS Robin Nano V1.3 and MKS Robin Nano-S V1.3 (STM32F407VET6)
#define BOARD_MKS_EAGLE 4235 // MKS Eagle (STM32F407VET6)
#define BOARD_BTT_OCTOPUS_PRO_V1_0 4217 // BigTreeTech Octopus Pro v1.0 (STM32F446ZET6/STM32F429ZGT6)
#define BOARD_LERDGE_K 4218 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4219 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4220 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4221 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4222 // FYSETC S6 (STM32F446VET6)
#define BOARD_FYSETC_S6_V2_0 4223 // FYSETC S6 v2.0 (STM32F446VET6)
#define BOARD_FYSETC_SPIDER 4224 // FYSETC Spider (STM32F446VET6)
#define BOARD_FLYF407ZG 4225 // FLYmaker FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4226 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4227 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4228 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_MKS_MONSTER8 4229 // MKS Monster8 (STM32F407VGT6)
#define BOARD_ANET_ET4 4230 // ANET ET4 V1.x (STM32F407VGT6)
#define BOARD_ANET_ET4P 4231 // ANET ET4P V1.x (STM32F407VGT6)
#define BOARD_FYSETC_CHEETAH_V20 4232 // FYSETC Cheetah V2.0
#define BOARD_TH3D_EZBOARD_V2 4233 // TH3D EZBoard v2.0
#define BOARD_INDEX_REV03 4234 // Index PnP Controller REV03 (STM32F407VET6/VGT6)
#define BOARD_MKS_ROBIN_NANO_V1_3_F4 4235 // MKS Robin Nano V1.3 and MKS Robin Nano-S V1.3 (STM32F407VET6)
#define BOARD_MKS_EAGLE 4236 // MKS Eagle (STM32F407VET6)
#define BOARD_ARTILLERY_RUBY 4237 // Artillery Ruby (STM32F401RCT6)
//
// ARM Cortex M7
@@ -423,9 +426,10 @@
#define BOARD_MRR_ESPA 6001 // MRR ESPA based on ESP32 (native pins only)
#define BOARD_MRR_ESPE 6002 // MRR ESPE based on ESP32 (with I2S stepper stream)
#define BOARD_E4D_BOX 6003 // E4d@BOX
#define BOARD_FYSETC_E4 6004 // FYSETC E4
#define BOARD_PANDA_ZHU 6005 // Panda_ZHU
#define BOARD_PANDA_M4 6006 // Panda_M4
#define BOARD_RESP32_CUSTOM 6004 // Rutilea ESP32 custom board
#define BOARD_FYSETC_E4 6005 // FYSETC E4
#define BOARD_PANDA_ZHU 6006 // Panda_ZHU
#define BOARD_PANDA_M4 6007 // Panda_M4
//
// SAMD51 ARM Cortex M4
+37 -1
View File
@@ -33,6 +33,12 @@
#define _AXIS(A) (A##_AXIS)
#define _XSTOP_ 0x01
#define _YSTOP_ 0x02
#define _ZSTOP_ 0x03
#define _ISTOP_ 0x04
#define _JSTOP_ 0x05
#define _KSTOP_ 0x06
#define _XMIN_ 0x11
#define _YMIN_ 0x12
#define _ZMIN_ 0x13
@@ -160,7 +166,7 @@
#endif
// Macros to chain up to 14 conditions
// Macros to chain up to 40 conditions
#define _DO_1(W,C,A) (_##W##_1(A))
#define _DO_2(W,C,A,B) (_##W##_1(A) C _##W##_1(B))
#define _DO_3(W,C,A,V...) (_##W##_1(A) C _DO_2(W,C,V))
@@ -176,6 +182,31 @@
#define _DO_13(W,C,A,V...) (_##W##_1(A) C _DO_12(W,C,V))
#define _DO_14(W,C,A,V...) (_##W##_1(A) C _DO_13(W,C,V))
#define _DO_15(W,C,A,V...) (_##W##_1(A) C _DO_14(W,C,V))
#define _DO_16(W,C,A,V...) (_##W##_1(A) C _DO_15(W,C,V))
#define _DO_17(W,C,A,V...) (_##W##_1(A) C _DO_16(W,C,V))
#define _DO_18(W,C,A,V...) (_##W##_1(A) C _DO_17(W,C,V))
#define _DO_19(W,C,A,V...) (_##W##_1(A) C _DO_18(W,C,V))
#define _DO_20(W,C,A,V...) (_##W##_1(A) C _DO_19(W,C,V))
#define _DO_21(W,C,A,V...) (_##W##_1(A) C _DO_20(W,C,V))
#define _DO_22(W,C,A,V...) (_##W##_1(A) C _DO_21(W,C,V))
#define _DO_23(W,C,A,V...) (_##W##_1(A) C _DO_22(W,C,V))
#define _DO_24(W,C,A,V...) (_##W##_1(A) C _DO_23(W,C,V))
#define _DO_25(W,C,A,V...) (_##W##_1(A) C _DO_24(W,C,V))
#define _DO_26(W,C,A,V...) (_##W##_1(A) C _DO_25(W,C,V))
#define _DO_27(W,C,A,V...) (_##W##_1(A) C _DO_26(W,C,V))
#define _DO_28(W,C,A,V...) (_##W##_1(A) C _DO_27(W,C,V))
#define _DO_29(W,C,A,V...) (_##W##_1(A) C _DO_28(W,C,V))
#define _DO_30(W,C,A,V...) (_##W##_1(A) C _DO_29(W,C,V))
#define _DO_31(W,C,A,V...) (_##W##_1(A) C _DO_30(W,C,V))
#define _DO_32(W,C,A,V...) (_##W##_1(A) C _DO_31(W,C,V))
#define _DO_33(W,C,A,V...) (_##W##_1(A) C _DO_32(W,C,V))
#define _DO_34(W,C,A,V...) (_##W##_1(A) C _DO_33(W,C,V))
#define _DO_35(W,C,A,V...) (_##W##_1(A) C _DO_34(W,C,V))
#define _DO_36(W,C,A,V...) (_##W##_1(A) C _DO_35(W,C,V))
#define _DO_37(W,C,A,V...) (_##W##_1(A) C _DO_36(W,C,V))
#define _DO_38(W,C,A,V...) (_##W##_1(A) C _DO_37(W,C,V))
#define _DO_39(W,C,A,V...) (_##W##_1(A) C _DO_38(W,C,V))
#define _DO_40(W,C,A,V...) (_##W##_1(A) C _DO_39(W,C,V))
#define __DO_N(W,C,N,V...) _DO_##N(W,C,V)
#define _DO_N(W,C,N,V...) __DO_N(W,C,N,V)
#define DO(W,C,V...) (_DO_N(W,C,NUM_ARGS(V),V))
@@ -251,6 +282,11 @@
memcpy(&a[0],&b[0],_MIN(sizeof(a),sizeof(b))); \
}while(0)
#define CODE_16( A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,...) A; B; C; D; E; F; G; H; I; J; K; L; M; N; O; P
#define CODE_15( A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,...) A; B; C; D; E; F; G; H; I; J; K; L; M; N; O
#define CODE_14( A,B,C,D,E,F,G,H,I,J,K,L,M,N,...) A; B; C; D; E; F; G; H; I; J; K; L; M; N
#define CODE_13( A,B,C,D,E,F,G,H,I,J,K,L,M,...) A; B; C; D; E; F; G; H; I; J; K; L; M
#define CODE_12( A,B,C,D,E,F,G,H,I,J,K,L,...) A; B; C; D; E; F; G; H; I; J; K; L
#define CODE_11( A,B,C,D,E,F,G,H,I,J,K,...) A; B; C; D; E; F; G; H; I; J; K
#define CODE_10( A,B,C,D,E,F,G,H,I,J,...) A; B; C; D; E; F; G; H; I; J
#define CODE_9( A,B,C,D,E,F,G,H,I,...) A; B; C; D; E; F; G; H; I
+1 -1
View File
@@ -87,7 +87,7 @@ extern uint8_t marlin_debug_flags;
// interface with the ability to output to multiple serial ports.
#if HAS_MULTI_SERIAL
#define _PORT_REDIRECT(n,p) REMEMBER(n,multiSerial.portMask,p)
#define _PORT_RESTORE(n,p) RESTORE(n)
#define _PORT_RESTORE(n) RESTORE(n)
#define SERIAL_ASSERT(P) if (multiSerial.portMask!=(P)) { debugger(); }
// If we have a catchall, use that directly
#ifdef SERIAL_CATCHALL
+4 -3
View File
@@ -346,13 +346,14 @@ void unified_bed_leveling::G29() {
if (parser.seen('Q')) {
const int16_t test_pattern = parser.has_value() ? parser.value_int() : -99;
if (!WITHIN(test_pattern, -1, 2)) {
SERIAL_ECHOLNPGM("Invalid test_pattern value. (-1 to 2)\n");
if (!WITHIN(test_pattern, TERN0(UBL_DEVEL_DEBUGGING, -1), 2)) {
SERIAL_ECHOLNPGM("?Invalid (Q) test pattern. (" TERN(UBL_DEVEL_DEBUGGING, "-1", "0") " to 2)\n");
return;
}
SERIAL_ECHOLNPGM("Loading test_pattern values.\n");
SERIAL_ECHOLNPGM("Applying test pattern.\n");
switch (test_pattern) {
default:
case -1: TERN_(UBL_DEVEL_DEBUGGING, g29_eeprom_dump()); break;
case 0:
+1 -1
View File
@@ -70,7 +70,7 @@ void CaseLight::update(const bool sflag) {
#if CASELIGHT_USES_BRIGHTNESS
if (pin_is_pwm())
analogWrite(pin_t(CASE_LIGHT_PIN), (
set_pwm_duty(pin_t(CASE_LIGHT_PIN), (
#if CASE_LIGHT_MAX_PWM == 255
n10ct
#else
+5 -4
View File
@@ -58,7 +58,7 @@ void ControllerFan::update() {
// - At least one stepper driver is enabled
// - The heated bed is enabled
// - TEMP_SENSOR_BOARD is reporting >= CONTROLLER_FAN_MIN_BOARD_TEMP
const ena_mask_t axis_mask = TERN(CONTROLLER_FAN_USE_Z_ONLY, _BV(Z_AXIS), ~TERN0(CONTROLLER_FAN_IGNORE_Z, _BV(Z_AXIS)));
const ena_mask_t axis_mask = TERN(CONTROLLER_FAN_USE_Z_ONLY, _BV(Z_AXIS), (ena_mask_t)~TERN0(CONTROLLER_FAN_IGNORE_Z, _BV(Z_AXIS)));
if ( (stepper.axis_enabled.bits & axis_mask)
|| TERN0(HAS_HEATED_BED, thermalManager.temp_bed.soft_pwm_amount > 0)
|| TERN0(HAS_CONTROLLER_FAN_MIN_BOARD_TEMP, thermalManager.wholeDegBoard() >= CONTROLLER_FAN_MIN_BOARD_TEMP)
@@ -72,9 +72,10 @@ void ControllerFan::update() {
? settings.active_speed : settings.idle_speed
);
// Allow digital or PWM fan output (see M42 handling)
WRITE(CONTROLLER_FAN_PIN, speed);
analogWrite(pin_t(CONTROLLER_FAN_PIN), speed);
if (PWM_PIN(CONTROLLER_FAN_PIN))
set_pwm_duty(pin_t(CONTROLLER_FAN_PIN), speed);
else
WRITE(CONTROLLER_FAN_PIN, speed);
}
}
+1 -1
View File
@@ -199,7 +199,7 @@ public:
case EP_M112: killed_by_M112 = true; break;
case EP_M410: quickstop_by_M410 = true; break;
#if ENABLED(HOST_PROMPT_SUPPORT)
case EP_M876SN: host_response_handler(M876_reason); break;
case EP_M876SN: hostui.handle_response(M876_reason); break;
#endif
#if ENABLED(REALTIME_REPORTING_COMMANDS)
case EP_GRBL_STATUS: report_current_position_moving(); break;
+69 -44
View File
@@ -24,10 +24,10 @@
#if ENABLED(HOST_ACTION_COMMANDS)
#include "host_actions.h"
//#define DEBUG_HOST_ACTIONS
#include "host_actions.h"
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#include "pause.h"
#include "../gcode/queue.h"
@@ -37,7 +37,12 @@
#include "runout.h"
#endif
void host_action(FSTR_P const fstr, const bool eol) {
HostUI hostui;
flag_t HostUI::flag;
void HostUI::action(FSTR_P const fstr, const bool eol) {
if (!flag.bits) return;
PORT_REDIRECT(SerialMask::All);
SERIAL_ECHOPGM("//action:");
SERIAL_ECHOF(fstr);
@@ -45,29 +50,44 @@ void host_action(FSTR_P const fstr, const bool eol) {
}
#ifdef ACTION_ON_KILL
void host_action_kill() { host_action(F(ACTION_ON_KILL)); }
void HostUI::kill() { action(F(ACTION_ON_KILL)); }
#endif
#ifdef ACTION_ON_PAUSE
void host_action_pause(const bool eol/*=true*/) { host_action(F(ACTION_ON_PAUSE), eol); }
void HostUI::pause(const bool eol/*=true*/) { action(F(ACTION_ON_PAUSE), eol); }
#endif
#ifdef ACTION_ON_PAUSED
void host_action_paused(const bool eol/*=true*/) { host_action(F(ACTION_ON_PAUSED), eol); }
void HostUI::paused(const bool eol/*=true*/) { action(F(ACTION_ON_PAUSED), eol); }
#endif
#ifdef ACTION_ON_RESUME
void host_action_resume() { host_action(F(ACTION_ON_RESUME)); }
void HostUI::resume() { action(F(ACTION_ON_RESUME)); }
#endif
#ifdef ACTION_ON_RESUMED
void host_action_resumed() { host_action(F(ACTION_ON_RESUMED)); }
void HostUI::resumed() { action(F(ACTION_ON_RESUMED)); }
#endif
#ifdef ACTION_ON_CANCEL
void host_action_cancel() { host_action(F(ACTION_ON_CANCEL)); }
void HostUI::cancel() { action(F(ACTION_ON_CANCEL)); }
#endif
#ifdef ACTION_ON_START
void host_action_start() { host_action(F(ACTION_ON_START)); }
void HostUI::start() { action(F(ACTION_ON_START)); }
#endif
#if ENABLED(G29_RETRY_AND_RECOVER)
#ifdef ACTION_ON_G29_RECOVER
void HostUI::g29_recover() { action(F(ACTION_ON_G29_RECOVER)); }
#endif
#ifdef ACTION_ON_G29_FAILURE
void HostUI::g29_failure() { action(F(ACTION_ON_G29_FAILURE)); }
#endif
#endif
#ifdef SHUTDOWN_ACTION
void HostUI::shutdown() { action(F(SHUTDOWN_ACTION)); }
#endif
#if ENABLED(HOST_PROMPT_SUPPORT)
PromptReason HostUI::host_prompt_reason = PROMPT_NOT_DEFINED;
PGMSTR(CONTINUE_STR, "Continue");
PGMSTR(DISMISS_STR, "Dismiss");
@@ -75,64 +95,69 @@ void host_action(FSTR_P const fstr, const bool eol) {
extern bool wait_for_user;
#endif
PromptReason host_prompt_reason = PROMPT_NOT_DEFINED;
void host_action_notify(const char * const cstr) {
void HostUI::notify(const char * const cstr) {
if (!flag.bits) return;
PORT_REDIRECT(SerialMask::All);
host_action(F("notification "), false);
action(F("notification "), false);
SERIAL_ECHOLN(cstr);
}
void host_action_notify(FSTR_P const fstr) {
void HostUI::notify_P(PGM_P const pstr) {
if (!flag.bits) return;
PORT_REDIRECT(SerialMask::All);
host_action(F("notification "), false);
SERIAL_ECHOLNF(fstr);
action(F("notification "), false);
SERIAL_ECHOLNPGM_P(pstr);
}
void host_action_prompt(FSTR_P const ptype, const bool eol=true) {
void HostUI::prompt(FSTR_P const ptype, const bool eol/*=true*/) {
if (!flag.bits) return;
PORT_REDIRECT(SerialMask::All);
host_action(F("prompt_"), false);
action(F("prompt_"), false);
SERIAL_ECHOF(ptype);
if (eol) SERIAL_EOL();
}
void host_action_prompt_plus(FSTR_P const ptype, FSTR_P const fstr, const char extra_char='\0') {
host_action_prompt(ptype, false);
void HostUI::prompt_plus(FSTR_P const ptype, FSTR_P const fstr, const char extra_char/*='\0'*/) {
if (!flag.bits) return;
prompt(ptype, false);
PORT_REDIRECT(SerialMask::All);
SERIAL_CHAR(' ');
SERIAL_ECHOF(fstr);
if (extra_char != '\0') SERIAL_CHAR(extra_char);
SERIAL_EOL();
}
void host_action_prompt_begin(const PromptReason reason, FSTR_P const fstr, const char extra_char/*='\0'*/) {
host_action_prompt_end();
void HostUI::prompt_begin(const PromptReason reason, FSTR_P const fstr, const char extra_char/*='\0'*/) {
if (!flag.bits) return;
prompt_end();
host_prompt_reason = reason;
host_action_prompt_plus(F("begin"), fstr, extra_char);
prompt_plus(F("begin"), fstr, extra_char);
}
void host_action_prompt_button(FSTR_P const fstr) { host_action_prompt_plus(F("button"), fstr); }
void host_action_prompt_end() { host_action_prompt(F("end")); }
void host_action_prompt_show() { host_action_prompt(F("show")); }
void HostUI::prompt_button(FSTR_P const fstr) { prompt_plus(F("button"), fstr); }
void HostUI::prompt_end() { prompt(F("end")); }
void HostUI::prompt_show() { prompt(F("show")); }
void _host_prompt_show(FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) {
if (btn1) host_action_prompt_button(btn1);
if (btn2) host_action_prompt_button(btn2);
host_action_prompt_show();
void HostUI::_prompt_show(FSTR_P const btn1, FSTR_P const btn2) {
if (btn1) prompt_button(btn1);
if (btn2) prompt_button(btn2);
prompt_show();
}
void host_prompt_do(const PromptReason reason, FSTR_P const fstr, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) {
host_action_prompt_begin(reason, fstr);
_host_prompt_show(btn1, btn2);
void HostUI::prompt_do(const PromptReason reason, FSTR_P const fstr, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) {
prompt_begin(reason, fstr);
_prompt_show(btn1, btn2);
}
void host_prompt_do(const PromptReason reason, FSTR_P const fstr, const char extra_char, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) {
host_action_prompt_begin(reason, fstr, extra_char);
_host_prompt_show(btn1, btn2);
void HostUI::prompt_do(const PromptReason reason, FSTR_P const fstr, const char extra_char, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) {
prompt_begin(reason, fstr, extra_char);
_prompt_show(btn1, btn2);
}
void filament_load_host_prompt() {
const bool disable_to_continue = TERN0(HAS_FILAMENT_SENSOR, runout.filament_ran_out);
host_prompt_do(PROMPT_FILAMENT_RUNOUT, F("Paused"), F("PurgeMore"),
disable_to_continue ? F("DisableRunout") : FPSTR(CONTINUE_STR)
);
}
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void HostUI::filament_load_prompt() {
const bool disable_to_continue = TERN0(HAS_FILAMENT_SENSOR, runout.filament_ran_out);
prompt_do(PROMPT_FILAMENT_RUNOUT, F("Paused"), F("PurgeMore"),
disable_to_continue ? F("DisableRunout") : FPSTR(CONTINUE_STR)
);
}
#endif
//
// Handle responses from the host, such as:
@@ -141,7 +166,7 @@ void host_action(FSTR_P const fstr, const bool eol) {
// - Resume Print response
// - Dismissal of info
//
void host_response_handler(const uint8_t response) {
void HostUI::handle_response(const uint8_t response) {
const PromptReason hpr = host_prompt_reason;
host_prompt_reason = PROMPT_NOT_DEFINED; // Reset now ahead of logic
switch (hpr) {
+83 -42
View File
@@ -24,34 +24,13 @@
#include "../inc/MarlinConfigPre.h"
#include "../HAL/shared/Marduino.h"
void host_action(FSTR_P const fstr, const bool eol=true);
#ifdef ACTION_ON_KILL
void host_action_kill();
#endif
#ifdef ACTION_ON_PAUSE
void host_action_pause(const bool eol=true);
#endif
#ifdef ACTION_ON_PAUSED
void host_action_paused(const bool eol=true);
#endif
#ifdef ACTION_ON_RESUME
void host_action_resume();
#endif
#ifdef ACTION_ON_RESUMED
void host_action_resumed();
#endif
#ifdef ACTION_ON_CANCEL
void host_action_cancel();
#endif
#ifdef ACTION_ON_START
void host_action_start();
#endif
typedef union {
uint8_t bits;
struct { bool info:1, errors:1, debug:1; };
} flag_t;
#if ENABLED(HOST_PROMPT_SUPPORT)
extern const char CONTINUE_STR[], DISMISS_STR[];
enum PromptReason : uint8_t {
PROMPT_NOT_DEFINED,
PROMPT_FILAMENT_RUNOUT,
@@ -61,21 +40,83 @@ void host_action(FSTR_P const fstr, const bool eol=true);
PROMPT_INFO
};
extern PromptReason host_prompt_reason;
void host_response_handler(const uint8_t response);
void host_action_notify(const char * const cstr);
void host_action_notify(FSTR_P const fstr);
void host_action_prompt_begin(const PromptReason reason, FSTR_P const fstr, const char extra_char='\0');
void host_action_prompt_button(FSTR_P const fstr);
void host_action_prompt_end();
void host_action_prompt_show();
void host_prompt_do(const PromptReason reason, FSTR_P const fstr, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr);
void host_prompt_do(const PromptReason reason, FSTR_P const fstr, const char extra_char, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr);
inline void host_prompt_open(const PromptReason reason, FSTR_P const fstr, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr) {
if (host_prompt_reason == PROMPT_NOT_DEFINED) host_prompt_do(reason, fstr, btn1, btn2);
}
void filament_load_host_prompt();
#endif
class HostUI {
public:
static flag_t flag;
HostUI() { flag.bits = 0xFF; }
static void action(FSTR_P const fstr, const bool eol=true);
#ifdef ACTION_ON_KILL
static void kill();
#endif
#ifdef ACTION_ON_PAUSE
static void pause(const bool eol=true);
#endif
#ifdef ACTION_ON_PAUSED
static void paused(const bool eol=true);
#endif
#ifdef ACTION_ON_RESUME
static void resume();
#endif
#ifdef ACTION_ON_RESUMED
static void resumed();
#endif
#ifdef ACTION_ON_CANCEL
static void cancel();
#endif
#ifdef ACTION_ON_START
static void start();
#endif
#ifdef SHUTDOWN_ACTION
static void shutdown();
#endif
#if ENABLED(G29_RETRY_AND_RECOVER)
#ifdef ACTION_ON_G29_RECOVER
static void g29_recover();
#endif
#ifdef ACTION_ON_G29_FAILURE
static void g29_failure();
#endif
#endif
#if ENABLED(HOST_PROMPT_SUPPORT)
private:
static void prompt(FSTR_P const ptype, const bool eol=true);
static void prompt_plus(FSTR_P const ptype, FSTR_P const fstr, const char extra_char='\0');
static void prompt_show();
static void _prompt_show(FSTR_P const btn1, FSTR_P const btn2);
public:
static PromptReason host_prompt_reason;
static void handle_response(const uint8_t response);
static void notify_P(PGM_P const message);
static inline void notify(FSTR_P const fmsg) { notify_P(FTOP(fmsg)); }
static void notify(const char * const message);
static void prompt_begin(const PromptReason reason, FSTR_P const fstr, const char extra_char='\0');
static void prompt_button(FSTR_P const fstr);
static void prompt_end();
static void prompt_do(const PromptReason reason, FSTR_P const pstr, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr);
static void prompt_do(const PromptReason reason, FSTR_P const pstr, const char extra_char, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr);
static inline void prompt_open(const PromptReason reason, FSTR_P const pstr, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr) {
if (host_prompt_reason == PROMPT_NOT_DEFINED) prompt_do(reason, pstr, btn1, btn2);
}
#if ENABLED(ADVANCED_PAUSE_FEATURE)
static void filament_load_prompt();
#endif
#endif
};
extern HostUI hostui;
extern const char CONTINUE_STR[], DISMISS_STR[];
+8 -8
View File
@@ -121,11 +121,11 @@ void LEDLights::set_color(const LEDColor &incol
// This variant uses 3-4 separate pins for the RGB(W) components.
// If the pins can do PWM then their intensity will be set.
#define _UPDATE_RGBW(C,c) do { \
if (PWM_PIN(RGB_LED_##C##_PIN)) \
analogWrite(pin_t(RGB_LED_##C##_PIN), c); \
else \
WRITE(RGB_LED_##C##_PIN, c ? HIGH : LOW); \
#define _UPDATE_RGBW(C,c) do { \
if (PWM_PIN(RGB_LED_##C##_PIN)) \
set_pwm_duty(pin_t(RGB_LED_##C##_PIN), c); \
else \
WRITE(RGB_LED_##C##_PIN, c ? HIGH : LOW); \
}while(0)
#define UPDATE_RGBW(C,c) _UPDATE_RGBW(C, TERN1(CASE_LIGHT_USE_RGB_LED, caselight.on) ? incol.c : 0)
UPDATE_RGBW(R,r); UPDATE_RGBW(G,g); UPDATE_RGBW(B,b);
@@ -170,9 +170,9 @@ void LEDLights::set_color(const LEDColor &incol
#if ENABLED(NEO2_COLOR_PRESETS)
const LEDColor LEDLights2::defaultLEDColor = LEDColor(
LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE
OPTARG(HAS_WHITE_LED2, LED_USER_PRESET_WHITE)
OPTARG(NEOPIXEL_LED, LED_USER_PRESET_BRIGHTNESS)
NEO2_USER_PRESET_RED, NEO2_USER_PRESET_GREEN, NEO2_USER_PRESET_BLUE
OPTARG(HAS_WHITE_LED2, NEO2_USER_PRESET_WHITE)
OPTARG(NEOPIXEL_LED, NEO2_USER_PRESET_BRIGHTNESS)
);
#endif
+3 -3
View File
@@ -24,9 +24,9 @@
#if HAS_PRUSA_MMU1
#include "../MarlinCore.h"
#include "../module/planner.h"
#include "../module/stepper.h"
#include "../../MarlinCore.h"
#include "../../module/planner.h"
#include "../../module/stepper.h"
void mmu_init() {
SET_OUTPUT(E_MUX0_PIN);
+1 -1
View File
@@ -962,7 +962,7 @@ bool MMU2::eject_filament(const uint8_t index, const bool recover) {
if (recover) {
LCD_MESSAGE(MSG_MMU2_EJECT_RECOVER);
BUZZ(200, 404);
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, F("MMU2 Eject Recover"), FPSTR(CONTINUE_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, F("MMU2 Eject Recover"), FPSTR(CONTINUE_STR)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(F("MMU2 Eject Recover")));
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response());
BUZZ(200, 404);
+14 -15
View File
@@ -198,7 +198,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
#if ENABLED(HOST_PROMPT_SUPPORT)
const char tool = '0' + TERN0(MULTI_FILAMENT_SENSOR, active_extruder);
host_prompt_do(PROMPT_USER_CONTINUE, F("Load Filament T"), tool, FPSTR(CONTINUE_STR));
hostui.prompt_do(PROMPT_USER_CONTINUE, F("Load Filament T"), tool, FPSTR(CONTINUE_STR));
#endif
while (wait_for_user) {
@@ -253,8 +253,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_PURGE);
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE)));
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE), FPSTR(CONTINUE_STR)));
TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_Popup_Confirm(ICON_BLTouch, GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE), FPSTR(CONTINUE_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE), FPSTR(CONTINUE_STR)));
wait_for_user = true; // A click or M108 breaks the purge_length loop
for (float purge_count = purge_length; purge_count > 0 && wait_for_user; --purge_count)
unscaled_e_move(1, ADVANCED_PAUSE_PURGE_FEEDRATE);
@@ -271,7 +270,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
unscaled_e_move(purge_length, ADVANCED_PAUSE_PURGE_FEEDRATE);
}
TERN_(HOST_PROMPT_SUPPORT, filament_load_host_prompt()); // Initiate another host prompt.
TERN_(HOST_PROMPT_SUPPORT, hostui.filament_load_prompt()); // Initiate another host prompt.
#if M600_PURGE_MORE_RESUMABLE
if (show_lcd) {
@@ -291,7 +290,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
} while (TERN0(M600_PURGE_MORE_RESUMABLE, pause_menu_response == PAUSE_RESPONSE_EXTRUDE_MORE));
#endif
TERN_(HOST_PROMPT_SUPPORT, host_action_prompt_end());
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_end());
return true;
}
@@ -397,13 +396,13 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool
#if ENABLED(HOST_ACTION_COMMANDS)
#ifdef ACTION_ON_PAUSED
host_action_paused();
hostui.paused();
#elif defined(ACTION_ON_PAUSE)
host_action_pause();
hostui.pause();
#endif
#endif
TERN_(HOST_PROMPT_SUPPORT, host_prompt_open(PROMPT_INFO, F("Pause"), FPSTR(DISMISS_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_open(PROMPT_INFO, F("Pause"), FPSTR(DISMISS_STR)));
// Indicate that the printer is paused
++did_pause_print;
@@ -512,7 +511,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
// Wait for filament insert by user and press button
KEEPALIVE_STATE(PAUSED_FOR_USER);
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_NOZZLE_PARKED), FPSTR(CONTINUE_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_NOZZLE_PARKED), FPSTR(CONTINUE_STR)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_NOZZLE_PARKED)));
wait_for_user = true; // LCD click or M108 will clear this
while (wait_for_user) {
@@ -528,13 +527,13 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
ui.pause_show_message(PAUSE_MESSAGE_HEAT);
SERIAL_ECHO_MSG(_PMSG(STR_FILAMENT_CHANGE_HEAT));
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_HEATER_TIMEOUT), GET_TEXT_F(MSG_REHEAT)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_HEATER_TIMEOUT), GET_TEXT_F(MSG_REHEAT)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_HEATER_TIMEOUT)));
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response(0, true)); // Wait for LCD click or M108
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_INFO, GET_TEXT_F(MSG_REHEATING)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_INFO, GET_TEXT_F(MSG_REHEATING)));
TERN_(EXTENSIBLE_UI, ExtUI::onStatusChanged(GET_TEXT_F(MSG_REHEATING)));
@@ -554,7 +553,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
HOTEND_LOOP() thermalManager.heater_idle[e].start(nozzle_timeout);
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_REHEATDONE), FPSTR(CONTINUE_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_REHEATDONE), FPSTR(CONTINUE_STR)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_REHEATDONE)));
TERN_(DWIN_CREALITY_LCD_ENHANCED, LCD_MESSAGE(MSG_REHEATDONE));
@@ -664,14 +663,14 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_
ui.pause_show_message(PAUSE_MESSAGE_STATUS);
#ifdef ACTION_ON_RESUMED
host_action_resumed();
hostui.resumed();
#elif defined(ACTION_ON_RESUME)
host_action_resume();
hostui.resume();
#endif
--did_pause_print;
TERN_(HOST_PROMPT_SUPPORT, host_prompt_open(PROMPT_INFO, F("Resuming"), FPSTR(DISMISS_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_open(PROMPT_INFO, F("Resuming"), FPSTR(DISMISS_STR)));
// Resume the print job timer if it was running
if (print_job_timer.isPaused()) print_job_timer.start();
+79 -68
View File
@@ -22,37 +22,53 @@
#include "../inc/MarlinConfigPre.h"
#if ENABLED(PROBE_TEMP_COMPENSATION)
#if HAS_PTC
//#define DEBUG_PTC // Print extra debug output with 'M871'
#include "probe_temp_comp.h"
#include <math.h>
ProbeTempComp temp_comp;
ProbeTempComp ptc;
int16_t ProbeTempComp::z_offsets_probe[cali_info_init[TSI_PROBE].measurements], // = {0}
ProbeTempComp::z_offsets_bed[cali_info_init[TSI_BED].measurements]; // = {0}
#if ENABLED(PTC_PROBE)
constexpr int16_t z_offsets_probe_default[PTC_PROBE_COUNT] = PTC_PROBE_ZOFFS;
int16_t ProbeTempComp::z_offsets_probe[PTC_PROBE_COUNT] = PTC_PROBE_ZOFFS;
#endif
#if ENABLED(USE_TEMP_EXT_COMPENSATION)
int16_t ProbeTempComp::z_offsets_ext[cali_info_init[TSI_EXT].measurements]; // = {0}
#if ENABLED(PTC_BED)
constexpr int16_t z_offsets_bed_default[PTC_BED_COUNT] = PTC_BED_ZOFFS;
int16_t ProbeTempComp::z_offsets_bed[PTC_BED_COUNT] = PTC_BED_ZOFFS;
#endif
#if ENABLED(PTC_HOTEND)
constexpr int16_t z_offsets_hotend_default[PTC_HOTEND_COUNT] = PTC_HOTEND_ZOFFS;
int16_t ProbeTempComp::z_offsets_hotend[PTC_HOTEND_COUNT] = PTC_HOTEND_ZOFFS;
#endif
int16_t *ProbeTempComp::sensor_z_offsets[TSI_COUNT] = {
ProbeTempComp::z_offsets_probe, ProbeTempComp::z_offsets_bed
OPTARG(USE_TEMP_EXT_COMPENSATION, ProbeTempComp::z_offsets_ext)
#if ENABLED(PTC_PROBE)
ProbeTempComp::z_offsets_probe,
#endif
#if ENABLED(PTC_BED)
ProbeTempComp::z_offsets_bed,
#endif
#if ENABLED(PTC_HOTEND)
ProbeTempComp::z_offsets_hotend,
#endif
};
const temp_calib_t ProbeTempComp::cali_info[TSI_COUNT] = {
cali_info_init[TSI_PROBE], cali_info_init[TSI_BED]
OPTARG(USE_TEMP_EXT_COMPENSATION, cali_info_init[TSI_EXT])
};
constexpr xyz_pos_t ProbeTempComp::park_point;
constexpr xy_pos_t ProbeTempComp::measure_point;
constexpr celsius_t ProbeTempComp::probe_calib_bed_temp;
constexpr temp_calib_t ProbeTempComp::cali_info[TSI_COUNT];
uint8_t ProbeTempComp::calib_idx; // = 0
float ProbeTempComp::init_measurement; // = 0.0
void ProbeTempComp::reset() {
TERN_(PTC_PROBE, LOOP_L_N(i, PTC_PROBE_COUNT) z_offsets_probe[i] = z_offsets_probe_default[i]);
TERN_(PTC_BED, LOOP_L_N(i, PTC_BED_COUNT) z_offsets_bed[i] = z_offsets_bed_default[i]);
TERN_(PTC_HOTEND, LOOP_L_N(i, PTC_HOTEND_COUNT) z_offsets_hotend[i] = z_offsets_hotend_default[i]);
}
void ProbeTempComp::clear_offsets(const TempSensorID tsi) {
LOOP_L_N(i, cali_info[tsi].measurements)
sensor_z_offsets[tsi][i] = 0;
@@ -69,19 +85,26 @@ void ProbeTempComp::print_offsets() {
LOOP_L_N(s, TSI_COUNT) {
celsius_t temp = cali_info[s].start_temp;
for (int16_t i = -1; i < cali_info[s].measurements; ++i) {
SERIAL_ECHOF(s == TSI_BED ? F("Bed") :
#if ENABLED(USE_TEMP_EXT_COMPENSATION)
s == TSI_EXT ? F("Extruder") :
#endif
SERIAL_ECHOF(
TERN_(PTC_BED, s == TSI_BED ? F("Bed") :)
TERN_(PTC_HOTEND, s == TSI_EXT ? F("Extruder") :)
F("Probe")
);
SERIAL_ECHOLNPGM(
" temp: ", temp,
"C; Offset: ", i < 0 ? 0.0f : sensor_z_offsets[s][i], " um"
);
temp += cali_info[s].temp_res;
temp += cali_info[s].temp_resolution;
}
}
#if ENABLED(DEBUG_PTC)
float meas[4] = { 0, 0, 0, 0 };
compensate_measurement(TSI_PROBE, 27.5, meas[0]);
compensate_measurement(TSI_PROBE, 32.5, meas[1]);
compensate_measurement(TSI_PROBE, 77.5, meas[2]);
compensate_measurement(TSI_PROBE, 82.5, meas[3]);
SERIAL_ECHOLNPGM("DEBUG_PTC 27.5:", meas[0], " 32.5:", meas[1], " 77.5:", meas[2], " 82.5:", meas[3]);
#endif
}
void ProbeTempComp::prepare_new_calibration(const_float_t init_meas_z) {
@@ -90,28 +113,20 @@ void ProbeTempComp::prepare_new_calibration(const_float_t init_meas_z) {
}
void ProbeTempComp::push_back_new_measurement(const TempSensorID tsi, const_float_t meas_z) {
switch (tsi) {
case TSI_PROBE:
case TSI_BED:
//case TSI_EXT:
if (calib_idx >= cali_info[tsi].measurements) return;
sensor_z_offsets[tsi][calib_idx++] = static_cast<int16_t>(meas_z * 1000.0f - init_measurement * 1000.0f);
default: break;
}
if (calib_idx >= cali_info[tsi].measurements) return;
sensor_z_offsets[tsi][calib_idx++] = static_cast<int16_t>((meas_z - init_measurement) * 1000.0f);
}
bool ProbeTempComp::finish_calibration(const TempSensorID tsi) {
if (tsi != TSI_PROBE && tsi != TSI_BED) return false;
if (calib_idx < 3) {
SERIAL_ECHOLNPGM("!Insufficient measurements (min. 3).");
if (!calib_idx) {
SERIAL_ECHOLNPGM("!No measurements.");
clear_offsets(tsi);
return false;
}
const uint8_t measurements = cali_info[tsi].measurements;
const celsius_t start_temp = cali_info[tsi].start_temp,
res_temp = cali_info[tsi].temp_res;
res_temp = cali_info[tsi].temp_resolution;
int16_t * const data = sensor_z_offsets[tsi];
// Extrapolate
@@ -120,16 +135,15 @@ bool ProbeTempComp::finish_calibration(const TempSensorID tsi) {
SERIAL_ECHOLNPGM("Got ", calib_idx, " measurements. ");
if (linear_regression(tsi, k, d)) {
SERIAL_ECHOPGM("Applying linear extrapolation");
calib_idx--;
for (; calib_idx < measurements; ++calib_idx) {
const celsius_float_t temp = start_temp + float(calib_idx) * res_temp;
const celsius_float_t temp = start_temp + float(calib_idx + 1) * res_temp;
data[calib_idx] = static_cast<int16_t>(k * temp + d);
}
}
else {
// Simply use the last measured value for higher temperatures
SERIAL_ECHOPGM("Failed to extrapolate");
const int16_t last_val = data[calib_idx];
const int16_t last_val = data[calib_idx-1];
for (; calib_idx < measurements; ++calib_idx)
data[calib_idx] = last_val;
}
@@ -147,7 +161,7 @@ bool ProbeTempComp::finish_calibration(const TempSensorID tsi) {
// Restrict the max. offset difference between two probings
if (calib_idx > 0 && ABS(data[calib_idx - 1] - data[calib_idx]) > 800) {
SERIAL_ECHOLNPGM("!Invalid Z-offset between two probings detected (0-0.8).");
clear_offsets(TSI_PROBE);
clear_offsets(tsi);
return false;
}
}
@@ -156,55 +170,52 @@ bool ProbeTempComp::finish_calibration(const TempSensorID tsi) {
}
void ProbeTempComp::compensate_measurement(const TempSensorID tsi, const celsius_t temp, float &meas_z) {
if (WITHIN(temp, cali_info[tsi].start_temp, cali_info[tsi].end_temp))
meas_z -= get_offset_for_temperature(tsi, temp);
}
float ProbeTempComp::get_offset_for_temperature(const TempSensorID tsi, const celsius_t temp) {
const uint8_t measurements = cali_info[tsi].measurements;
const celsius_t start_temp = cali_info[tsi].start_temp,
res_temp = cali_info[tsi].temp_res;
res_temp = cali_info[tsi].temp_resolution,
end_temp = start_temp + measurements * res_temp;
const int16_t * const data = sensor_z_offsets[tsi];
auto point = [&](uint8_t i) -> xy_float_t {
return xy_float_t({ static_cast<float>(start_temp) + i * res_temp, static_cast<float>(data[i]) });
// Given a data index, return { celsius, zoffset } in the form { x, y }
auto tpoint = [&](uint8_t i) -> xy_float_t {
return xy_float_t({ static_cast<float>(start_temp) + i * res_temp, i ? static_cast<float>(data[i - 1]) : 0.0f });
};
// Interpolate Z based on a temperature being within a given range
auto linear_interp = [](const_float_t x, xy_float_t p1, xy_float_t p2) {
return (p2.y - p1.y) / (p2.x - p2.y) * (x - p1.x) + p1.y;
// zoffs1 + zoffset_per_toffset * toffset
return p1.y + (p2.y - p1.y) / (p2.x - p1.x) * (x - p1.x);
};
// Linear interpolation
uint8_t idx = static_cast<uint8_t>((temp - start_temp) / res_temp);
// offset in µm
float offset = 0.0f;
#if !defined(PTC_LINEAR_EXTRAPOLATION) || PTC_LINEAR_EXTRAPOLATION <= 0
if (idx < 0)
offset = 0.0f;
else if (idx > measurements - 2)
offset = static_cast<float>(data[measurements - 1]);
#if PTC_LINEAR_EXTRAPOLATION
if (temp < start_temp)
offset = linear_interp(temp, tpoint(0), tpoint(PTC_LINEAR_EXTRAPOLATION));
else if (temp >= end_temp)
offset = linear_interp(temp, tpoint(measurements - PTC_LINEAR_EXTRAPOLATION), tpoint(measurements));
#else
if (idx < 0)
offset = linear_interp(temp, point(0), point(PTC_LINEAR_EXTRAPOLATION));
else if (idx > measurements - 2)
offset = linear_interp(temp, point(measurements - PTC_LINEAR_EXTRAPOLATION - 1), point(measurements - 1));
if (temp < start_temp)
offset = 0.0f;
else if (temp >= end_temp)
offset = static_cast<float>(data[measurements - 1]);
#endif
else
offset = linear_interp(temp, point(idx), point(idx + 1));
else {
// Linear interpolation
const int8_t idx = static_cast<int8_t>((temp - start_temp) / res_temp);
offset = linear_interp(temp, tpoint(idx), tpoint(idx + 1));
}
// return offset in mm
return offset / 1000.0f;
// convert offset to mm and apply it
meas_z -= offset / 1000.0f;
}
bool ProbeTempComp::linear_regression(const TempSensorID tsi, float &k, float &d) {
if (tsi != TSI_PROBE && tsi != TSI_BED) return false;
if (!WITHIN(calib_idx, 2, cali_info[tsi].measurements)) return false;
if (!WITHIN(calib_idx, 1, cali_info[tsi].measurements)) return false;
const celsius_t start_temp = cali_info[tsi].start_temp,
res_temp = cali_info[tsi].temp_res;
res_temp = cali_info[tsi].temp_resolution;
const int16_t * const data = sensor_z_offsets[tsi];
float sum_x = start_temp,
@@ -234,4 +245,4 @@ bool ProbeTempComp::linear_regression(const TempSensorID tsi, float &k, float &d
return true;
}
#endif // PROBE_TEMP_COMPENSATION
#endif // HAS_PTC
+35 -73
View File
@@ -24,19 +24,22 @@
#include "../inc/MarlinConfig.h"
enum TempSensorID : uint8_t {
TSI_PROBE,
TSI_BED,
#if ENABLED(USE_TEMP_EXT_COMPENSATION)
#if ENABLED(PTC_PROBE)
TSI_PROBE,
#endif
#if ENABLED(PTC_BED)
TSI_BED,
#endif
#if ENABLED(PTC_HOTEND)
TSI_EXT,
#endif
TSI_COUNT
};
typedef struct {
uint8_t measurements; // Max. number of measurements to be stored (35 - 80°C)
celsius_t temp_res, // Resolution in °C between measurements
start_temp, // Base measurement; z-offset == 0
end_temp;
uint8_t measurements; // Max. number of measurements to be stored (35 - 80°C)
celsius_t temp_resolution, // Resolution in °C between measurements
start_temp; // Base measurement; z-offset == 0
} temp_calib_t;
/**
@@ -45,79 +48,40 @@ typedef struct {
* measurement errors/shifts due to changed temperature.
*/
// Probe temperature calibration constants
#ifndef PTC_SAMPLE_COUNT
#define PTC_SAMPLE_COUNT 10
#endif
#ifndef PTC_SAMPLE_RES
#define PTC_SAMPLE_RES 5
#endif
#ifndef PTC_SAMPLE_START
#define PTC_SAMPLE_START 30
#endif
#define PTC_SAMPLE_END (PTC_SAMPLE_START + (PTC_SAMPLE_COUNT) * PTC_SAMPLE_RES)
// Bed temperature calibration constants
#ifndef BTC_PROBE_TEMP
#define BTC_PROBE_TEMP 30
#endif
#ifndef BTC_SAMPLE_COUNT
#define BTC_SAMPLE_COUNT 10
#endif
#ifndef BTC_SAMPLE_RES
#define BTC_SAMPLE_RES 5
#endif
#ifndef BTC_SAMPLE_START
#define BTC_SAMPLE_START 60
#endif
#define BTC_SAMPLE_END (BTC_SAMPLE_START + (BTC_SAMPLE_COUNT) * BTC_SAMPLE_RES)
#ifndef PTC_PROBE_HEATING_OFFSET
#define PTC_PROBE_HEATING_OFFSET 0.5f
#endif
#ifndef PTC_PROBE_RAISE
#define PTC_PROBE_RAISE 10
#endif
static constexpr temp_calib_t cali_info_init[TSI_COUNT] = {
{ PTC_SAMPLE_COUNT, PTC_SAMPLE_RES, PTC_SAMPLE_START, PTC_SAMPLE_END }, // Probe
{ BTC_SAMPLE_COUNT, BTC_SAMPLE_RES, BTC_SAMPLE_START, BTC_SAMPLE_END }, // Bed
#if ENABLED(USE_TEMP_EXT_COMPENSATION)
{ 20, 5, 180, 180 + 5 * 20 } // Extruder
#endif
};
class ProbeTempComp {
public:
static const temp_calib_t cali_info[TSI_COUNT];
static constexpr temp_calib_t cali_info[TSI_COUNT] = {
#if ENABLED(PTC_PROBE)
{ PTC_PROBE_COUNT, PTC_PROBE_RES, PTC_PROBE_START }, // Probe
#endif
#if ENABLED(PTC_BED)
{ PTC_BED_COUNT, PTC_BED_RES, PTC_BED_START }, // Bed
#endif
#if ENABLED(PTC_HOTEND)
{ PTC_HOTEND_COUNT, PTC_HOTEND_RES, PTC_HOTEND_START }, // Extruder
#endif
};
// Where to park nozzle to wait for probe cooldown
static constexpr xyz_pos_t park_point = PTC_PARK_POS;
// XY coordinates of nozzle for probing the bed
static constexpr xy_pos_t measure_point = PTC_PROBE_POS; // Coordinates to probe
//measure_point = { 12.0f, 7.3f }; // Coordinates for the MK52 magnetic heatbed
static constexpr celsius_t probe_calib_bed_temp = BED_MAX_TARGET, // Bed temperature while calibrating probe
bed_calib_probe_temp = BTC_PROBE_TEMP; // Probe temperature while calibrating bed
static int16_t *sensor_z_offsets[TSI_COUNT],
z_offsets_probe[cali_info_init[TSI_PROBE].measurements], // (µm)
z_offsets_bed[cali_info_init[TSI_BED].measurements]; // (µm)
#if ENABLED(USE_TEMP_EXT_COMPENSATION)
static int16_t z_offsets_ext[cali_info_init[TSI_EXT].measurements]; // (µm)
static int16_t *sensor_z_offsets[TSI_COUNT];
#if ENABLED(PTC_PROBE)
static int16_t z_offsets_probe[PTC_PROBE_COUNT]; // (µm)
#endif
#if ENABLED(PTC_BED)
static int16_t z_offsets_bed[PTC_BED_COUNT]; // (µm)
#endif
#if ENABLED(PTC_HOTEND)
static int16_t z_offsets_hotend[PTC_HOTEND_COUNT]; // (µm)
#endif
static inline void reset_index() { calib_idx = 0; };
static inline uint8_t get_index() { return calib_idx; }
static void reset();
static void clear_offsets(const TempSensorID tsi);
static inline void clear_all_offsets() {
clear_offsets(TSI_BED);
clear_offsets(TSI_PROBE);
TERN_(USE_TEMP_EXT_COMPENSATION, clear_offsets(TSI_EXT));
TERN_(PTC_PROBE, clear_offsets(TSI_PROBE));
TERN_(PTC_BED, clear_offsets(TSI_BED));
TERN_(PTC_HOTEND, clear_offsets(TSI_EXT));
}
static bool set_offset(const TempSensorID tsi, const uint8_t idx, const int16_t offset);
static void print_offsets();
@@ -135,8 +99,6 @@ class ProbeTempComp {
*/
static float init_measurement;
static float get_offset_for_temperature(const TempSensorID tsi, const celsius_t temp);
/**
* Fit a linear function in measured temperature offsets
* to allow generating values of higher temperatures.
@@ -144,4 +106,4 @@ class ProbeTempComp {
static bool linear_regression(const TempSensorID tsi, float &k, float &d);
};
extern ProbeTempComp temp_comp;
extern ProbeTempComp ptc;
+4 -5
View File
@@ -96,8 +96,7 @@ void event_filament_runout(const uint8_t extruder) {
//action:out_of_filament
#if ENABLED(HOST_PROMPT_SUPPORT)
host_action_prompt_begin(PROMPT_FILAMENT_RUNOUT, F("FilamentRunout T"), tool);
host_action_prompt_show();
hostui.prompt_do(PROMPT_FILAMENT_RUNOUT, F("FilamentRunout T"), tool); //action:out_of_filament
#endif
const bool run_runout_script = !runout.host_handling;
@@ -109,18 +108,18 @@ void event_filament_runout(const uint8_t extruder) {
|| TERN0(ADVANCED_PAUSE_FEATURE, strstr(FILAMENT_RUNOUT_SCRIPT, "M25"))
)
) {
host_action_paused(false);
hostui.paused(false);
}
else {
// Legacy Repetier command for use until newer version supports standard dialog
// To be removed later when pause command also triggers dialog
#ifdef ACTION_ON_FILAMENT_RUNOUT
host_action(F(ACTION_ON_FILAMENT_RUNOUT " T"), false);
hostui.action(F(ACTION_ON_FILAMENT_RUNOUT " T"), false);
SERIAL_CHAR(tool);
SERIAL_EOL();
#endif
host_action_pause(false);
hostui.pause(false);
}
SERIAL_ECHOPGM(" " ACTION_REASON_ON_FILAMENT_RUNOUT " ");
SERIAL_CHAR(tool);
+5 -35
View File
@@ -34,28 +34,12 @@
#include "../module/tool_change.h"
#endif
#define HAS_SOLENOID(N) (HAS_SOLENOID_##N && (ENABLED(MANUAL_SOLENOID_CONTROL) || N < EXTRUDERS))
// Used primarily with MANUAL_SOLENOID_CONTROL
static void set_solenoid(const uint8_t num, const bool active) {
const uint8_t value = active ? PE_MAGNET_ON_STATE : !PE_MAGNET_ON_STATE;
#define _SOL_CASE(N) case N: TERN_(HAS_SOLENOID_##N, OUT_WRITE(SOL##N##_PIN, value)); break;
switch (num) {
case 0: OUT_WRITE(SOL0_PIN, value); break;
#if HAS_SOLENOID(1)
case 1: OUT_WRITE(SOL1_PIN, value); break;
#endif
#if HAS_SOLENOID(2)
case 2: OUT_WRITE(SOL2_PIN, value); break;
#endif
#if HAS_SOLENOID(3)
case 3: OUT_WRITE(SOL3_PIN, value); break;
#endif
#if HAS_SOLENOID(4)
case 4: OUT_WRITE(SOL4_PIN, value); break;
#endif
#if HAS_SOLENOID(5)
case 5: OUT_WRITE(SOL5_PIN, value); break;
#endif
REPEAT(8, _SOL_CASE)
default: SERIAL_ECHO_MSG(STR_INVALID_SOLENOID); break;
}
@@ -67,25 +51,11 @@ static void set_solenoid(const uint8_t num, const bool active) {
void enable_solenoid(const uint8_t num) { set_solenoid(num, true); }
void disable_solenoid(const uint8_t num) { set_solenoid(num, false); }
void enable_solenoid_on_active_extruder() { enable_solenoid(active_extruder); }
void enable_solenoid_on_active_extruder() { }
void disable_all_solenoids() {
disable_solenoid(0);
#if HAS_SOLENOID(1)
disable_solenoid(1);
#endif
#if HAS_SOLENOID(2)
disable_solenoid(2);
#endif
#if HAS_SOLENOID(3)
disable_solenoid(3);
#endif
#if HAS_SOLENOID(4)
disable_solenoid(4);
#endif
#if HAS_SOLENOID(5)
disable_solenoid(5);
#endif
#define _SOL_DISABLE(N) TERN_(HAS_SOLENOID_##N, disable_solenoid(N));
REPEAT(8, _SOL_DISABLE)
}
#endif // EXT_SOLENOID || MANUAL_SOLENOID_CONTROL
+2 -4
View File
@@ -66,7 +66,7 @@ void SpindleLaser::init() {
#endif
#if ENABLED(SPINDLE_LASER_USE_PWM)
SET_PWM(SPINDLE_LASER_PWM_PIN);
analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed
set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed
#endif
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && defined(SPINDLE_LASER_FREQUENCY)
set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY);
@@ -92,10 +92,8 @@ void SpindleLaser::init() {
void SpindleLaser::_set_ocr(const uint8_t ocr) {
#if NEEDS_HARDWARE_PWM && SPINDLE_LASER_FREQUENCY
set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), TERN(MARLIN_DEV_MODE, frequency, SPINDLE_LASER_FREQUENCY));
set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
#else
analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
#endif
set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
}
void SpindleLaser::set_ocr(const uint8_t ocr) {
+1 -1
View File
@@ -98,7 +98,7 @@ void TWIBus::echodata(uint8_t bytes, FSTR_P const pref, uint8_t adr, const uint8
union TwoBytesToInt16 { uint8_t bytes[2]; int16_t integervalue; };
TwoBytesToInt16 ConversionUnion;
echoprefix(bytes, pref, adr);
echoprefix(bytes, pref, adr);
while (bytes-- && Wire.available()) {
int value = Wire.read();
+3 -3
View File
@@ -520,7 +520,7 @@ void GcodeSuite::G26() {
g26.keep_heaters_on = parser.boolval('K');
// Accept 'I' if temperature presets are defined
#if PREHEAT_COUNT
#if HAS_PREHEAT
const uint8_t preset_index = parser.seenval('I') ? _MIN(parser.value_byte(), PREHEAT_COUNT - 1) + 1 : 0;
#endif
@@ -530,7 +530,7 @@ void GcodeSuite::G26() {
celsius_t bedtemp = 0;
// Use the 'I' index if temperature presets are defined
#if PREHEAT_COUNT
#if HAS_PREHEAT
if (preset_index) bedtemp = ui.material_preset[preset_index - 1].bed_temp;
#endif
@@ -613,7 +613,7 @@ void GcodeSuite::G26() {
celsius_t noztemp = 0;
// Accept 'I' if temperature presets are defined
#if PREHEAT_COUNT
#if HAS_PREHEAT
if (preset_index) noztemp = ui.material_preset[preset_index - 1].hotend_temp;
#endif
+4 -6
View File
@@ -36,7 +36,7 @@
#include "../../../module/probe.h"
#include "../../queue.h"
#if ENABLED(PROBE_TEMP_COMPENSATION)
#if HAS_PTC
#include "../../../feature/probe_temp_comp.h"
#include "../../../module/temperature.h"
#endif
@@ -645,11 +645,9 @@ G29_TYPE GcodeSuite::G29() {
break; // Breaks out of both loops
}
#if ENABLED(PROBE_TEMP_COMPENSATION)
temp_comp.compensate_measurement(TSI_BED, thermalManager.degBed(), abl.measured_z);
temp_comp.compensate_measurement(TSI_PROBE, thermalManager.degProbe(), abl.measured_z);
TERN_(USE_TEMP_EXT_COMPENSATION, temp_comp.compensate_measurement(TSI_EXT, thermalManager.degHotend(), abl.measured_z));
#endif
TERN_(PTC_BED, ptc.compensate_measurement(TSI_BED, thermalManager.degBed(), abl.measured_z));
TERN_(PTC_PROBE, ptc.compensate_measurement(TSI_PROBE, thermalManager.degProbe(), abl.measured_z));
TERN_(PTC_HOTEND, ptc.compensate_measurement(TSI_EXT, thermalManager.degHotend(0), abl.measured_z));
#if ENABLED(AUTO_BED_LEVELING_LINEAR)
@@ -1,358 +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/>.
*
*/
/**
* G76_M871.cpp - Temperature calibration/compensation for z-probing
*/
#include "../../inc/MarlinConfig.h"
#if ENABLED(PROBE_TEMP_COMPENSATION)
#include "../gcode.h"
#include "../../module/motion.h"
#include "../../module/planner.h"
#include "../../module/probe.h"
#include "../../feature/bedlevel/bedlevel.h"
#include "../../module/temperature.h"
#include "../../module/probe.h"
#include "../../feature/probe_temp_comp.h"
#include "../../lcd/marlinui.h"
/**
* G76: calibrate probe and/or bed temperature offsets
* Notes:
* - When calibrating probe, bed temperature is held constant.
* Compensation values are deltas to first probe measurement at probe temp. = 30°C.
* - When calibrating bed, probe temperature is held constant.
* Compensation values are deltas to first probe measurement at bed temp. = 60°C.
* - The hotend will not be heated at any time.
* - On my Průša MK3S clone I put a piece of paper between the probe and the hotend
* so the hotend fan would not cool my probe constantly. Alternatively you could just
* make sure the fan is not running while running the calibration process.
*
* Probe calibration:
* - Moves probe to cooldown point.
* - Heats up bed to 100°C.
* - Moves probe to probing point (1mm above heatbed).
* - Waits until probe reaches target temperature (30°C).
* - Does a z-probing (=base value) and increases target temperature by 5°C.
* - Waits until probe reaches increased target temperature.
* - Does a z-probing (delta to base value will be a compensation value) and increases target temperature by 5°C.
* - Repeats last two steps until max. temperature reached or timeout (i.e. probe does not heat up any further).
* - Compensation values of higher temperatures will be extrapolated (using linear regression first).
* While this is not exact by any means it is still better than simply using the last compensation value.
*
* Bed calibration:
* - Moves probe to cooldown point.
* - Heats up bed to 60°C.
* - Moves probe to probing point (1mm above heatbed).
* - Waits until probe reaches target temperature (30°C).
* - Does a z-probing (=base value) and increases bed temperature by 5°C.
* - Moves probe to cooldown point.
* - Waits until probe is below 30°C and bed has reached target temperature.
* - Moves probe to probing point and waits until it reaches target temperature (30°C).
* - Does a z-probing (delta to base value will be a compensation value) and increases bed temperature by 5°C.
* - Repeats last four points until max. bed temperature reached (110°C) or timeout.
* - Compensation values of higher temperatures will be extrapolated (using linear regression first).
* While this is not exact by any means it is still better than simply using the last compensation value.
*
* G76 [B | P]
* - no flag - Both calibration procedures will be run.
* - `B` - Run bed temperature calibration.
* - `P` - Run probe temperature calibration.
*/
static void say_waiting_for() { SERIAL_ECHOPGM("Waiting for "); }
static void say_waiting_for_probe_heating() { say_waiting_for(); SERIAL_ECHOLNPGM("probe heating."); }
static void say_successfully_calibrated() { SERIAL_ECHOPGM("Successfully calibrated"); }
static void say_failed_to_calibrate() { SERIAL_ECHOPGM("!Failed to calibrate"); }
void GcodeSuite::G76() {
// Check if heated bed is available and z-homing is done with probe
#if TEMP_SENSOR_BED == 0 || !(HOMING_Z_WITH_PROBE)
return;
#endif
auto report_temps = [](millis_t &ntr, millis_t timeout=0) {
idle_no_sleep();
const millis_t ms = millis();
if (ELAPSED(ms, ntr)) {
ntr = ms + 1000;
thermalManager.print_heater_states(active_extruder);
}
return (timeout && ELAPSED(ms, timeout));
};
auto wait_for_temps = [&](const celsius_t tb, const celsius_t tp, millis_t &ntr, const millis_t timeout=0) {
say_waiting_for(); SERIAL_ECHOLNPGM("bed and probe temperature.");
while (thermalManager.wholeDegBed() != tb || thermalManager.wholeDegProbe() > tp)
if (report_temps(ntr, timeout)) return true;
return false;
};
auto g76_probe = [](const TempSensorID sid, celsius_t &targ, const xy_pos_t &nozpos) {
do_z_clearance(5.0); // Raise nozzle before probing
const float measured_z = probe.probe_at_point(nozpos, PROBE_PT_STOW, 0, false); // verbose=0, probe_relative=false
if (isnan(measured_z))
SERIAL_ECHOLNPGM("!Received NAN. Aborting.");
else {
SERIAL_ECHOLNPAIR_F("Measured: ", measured_z);
if (targ == cali_info_init[sid].start_temp)
temp_comp.prepare_new_calibration(measured_z);
else
temp_comp.push_back_new_measurement(sid, measured_z);
targ += cali_info_init[sid].temp_res;
}
return measured_z;
};
#if ENABLED(BLTOUCH)
// Make sure any BLTouch error condition is cleared
bltouch_command(BLTOUCH_RESET, BLTOUCH_RESET_DELAY);
set_bltouch_deployed(false);
#endif
bool do_bed_cal = parser.boolval('B'), do_probe_cal = parser.boolval('P');
if (!do_bed_cal && !do_probe_cal) do_bed_cal = do_probe_cal = true;
// Synchronize with planner
planner.synchronize();
const xyz_pos_t parkpos = temp_comp.park_point,
probe_pos_xyz = xyz_pos_t(temp_comp.measure_point) + xyz_pos_t({ 0.0f, 0.0f, PTC_PROBE_HEATING_OFFSET }),
noz_pos_xyz = probe_pos_xyz - probe.offset_xy; // Nozzle position based on probe position
if (do_bed_cal || do_probe_cal) {
// Ensure park position is reachable
bool reachable = position_is_reachable(parkpos) || WITHIN(parkpos.z, Z_MIN_POS - fslop, Z_MAX_POS + fslop);
if (!reachable)
SERIAL_ECHOLNPGM("!Park");
else {
// Ensure probe position is reachable
reachable = probe.can_reach(probe_pos_xyz);
if (!reachable) SERIAL_ECHOLNPGM("!Probe");
}
if (!reachable) {
SERIAL_ECHOLNPGM(" position unreachable - aborting.");
return;
}
process_subcommands_now(FPSTR(G28_STR));
}
remember_feedrate_scaling_off();
/******************************************
* Calibrate bed temperature offsets
******************************************/
// Report temperatures every second and handle heating timeouts
millis_t next_temp_report = millis() + 1000;
auto report_targets = [&](const celsius_t tb, const celsius_t tp) {
SERIAL_ECHOLNPGM("Target Bed:", tb, " Probe:", tp);
};
if (do_bed_cal) {
celsius_t target_bed = cali_info_init[TSI_BED].start_temp,
target_probe = temp_comp.bed_calib_probe_temp;
say_waiting_for(); SERIAL_ECHOLNPGM(" cooling.");
while (thermalManager.wholeDegBed() > target_bed || thermalManager.wholeDegProbe() > target_probe)
report_temps(next_temp_report);
// Disable leveling so it won't mess with us
TERN_(HAS_LEVELING, set_bed_leveling_enabled(false));
for (;;) {
thermalManager.setTargetBed(target_bed);
report_targets(target_bed, target_probe);
// Park nozzle
do_blocking_move_to(parkpos);
// Wait for heatbed to reach target temp and probe to cool below target temp
if (wait_for_temps(target_bed, target_probe, next_temp_report, millis() + MIN_TO_MS(15))) {
SERIAL_ECHOLNPGM("!Bed heating timeout.");
break;
}
// Move the nozzle to the probing point and wait for the probe to reach target temp
do_blocking_move_to(noz_pos_xyz);
say_waiting_for_probe_heating();
SERIAL_EOL();
while (thermalManager.wholeDegProbe() < target_probe)
report_temps(next_temp_report);
const float measured_z = g76_probe(TSI_BED, target_bed, noz_pos_xyz);
if (isnan(measured_z) || target_bed > (BED_MAX_TARGET)) break;
}
SERIAL_ECHOLNPGM("Retrieved measurements: ", temp_comp.get_index());
if (temp_comp.finish_calibration(TSI_BED)) {
say_successfully_calibrated();
SERIAL_ECHOLNPGM(" bed.");
}
else {
say_failed_to_calibrate();
SERIAL_ECHOLNPGM(" bed. Values reset.");
}
// Cleanup
thermalManager.setTargetBed(0);
TERN_(HAS_LEVELING, set_bed_leveling_enabled(true));
} // do_bed_cal
/********************************************
* Calibrate probe temperature offsets
********************************************/
if (do_probe_cal) {
// Park nozzle
do_blocking_move_to(parkpos);
// Initialize temperatures
const celsius_t target_bed = temp_comp.probe_calib_bed_temp;
thermalManager.setTargetBed(target_bed);
celsius_t target_probe = cali_info_init[TSI_PROBE].start_temp;
report_targets(target_bed, target_probe);
// Wait for heatbed to reach target temp and probe to cool below target temp
wait_for_temps(target_bed, target_probe, next_temp_report);
// Disable leveling so it won't mess with us
TERN_(HAS_LEVELING, set_bed_leveling_enabled(false));
bool timeout = false;
for (;;) {
// Move probe to probing point and wait for it to reach target temperature
do_blocking_move_to(noz_pos_xyz);
say_waiting_for_probe_heating();
SERIAL_ECHOLNPGM(" Bed:", target_bed, " Probe:", target_probe);
const millis_t probe_timeout_ms = millis() + SEC_TO_MS(900UL);
while (thermalManager.degProbe() < target_probe) {
if (report_temps(next_temp_report, probe_timeout_ms)) {
SERIAL_ECHOLNPGM("!Probe heating timed out.");
timeout = true;
break;
}
}
if (timeout) break;
const float measured_z = g76_probe(TSI_PROBE, target_probe, noz_pos_xyz);
if (isnan(measured_z) || target_probe > cali_info_init[TSI_PROBE].end_temp) break;
}
SERIAL_ECHOLNPGM("Retrieved measurements: ", temp_comp.get_index());
if (temp_comp.finish_calibration(TSI_PROBE))
say_successfully_calibrated();
else
say_failed_to_calibrate();
SERIAL_ECHOLNPGM(" probe.");
// Cleanup
thermalManager.setTargetBed(0);
TERN_(HAS_LEVELING, set_bed_leveling_enabled(true));
SERIAL_ECHOLNPGM("Final compensation values:");
temp_comp.print_offsets();
} // do_probe_cal
restore_feedrate_and_scaling();
}
/**
* M871: Report / reset temperature compensation offsets.
* Note: This does not affect values in EEPROM until M500.
*
* M871 [ R | B | P | E ]
*
* No Parameters - Print current offset values.
*
* Select only one of these flags:
* R - Reset all offsets to zero (i.e., disable compensation).
* B - Manually set offset for bed
* P - Manually set offset for probe
* E - Manually set offset for extruder
*
* With B, P, or E:
* I[index] - Index in the array
* V[value] - Adjustment in µm
*/
void GcodeSuite::M871() {
if (parser.seen('R')) {
// Reset z-probe offsets to factory defaults
temp_comp.clear_all_offsets();
SERIAL_ECHOLNPGM("Offsets reset to default.");
}
else if (parser.seen("BPE")) {
if (!parser.seenval('V')) return;
const int16_t offset_val = parser.value_int();
if (!parser.seenval('I')) return;
const int16_t idx = parser.value_int();
const TempSensorID mod = (parser.seen('B') ? TSI_BED :
#if ENABLED(USE_TEMP_EXT_COMPENSATION)
parser.seen('E') ? TSI_EXT :
#endif
TSI_PROBE
);
if (idx > 0 && temp_comp.set_offset(mod, idx - 1, offset_val))
SERIAL_ECHOLNPGM("Set value: ", offset_val);
else
SERIAL_ECHOLNPGM("!Invalid index. Failed to set value (note: value at index 0 is constant).");
}
else // Print current Z-probe adjustments. Note: Values in EEPROM might differ.
temp_comp.print_offsets();
}
/**
* M192: Wait for probe temperature sensor to reach a target
*
* Select only one of these flags:
* R - Wait for heating or cooling
* S - Wait only for heating
*/
void GcodeSuite::M192() {
if (DEBUGGING(DRYRUN)) return;
const bool no_wait_for_cooling = parser.seenval('S');
if (!no_wait_for_cooling && ! parser.seenval('R')) {
SERIAL_ERROR_MSG("No target temperature set.");
return;
}
const celsius_t target_temp = parser.value_celsius();
ui.set_status(thermalManager.isProbeBelowTemp(target_temp) ? GET_TEXT_F(MSG_PROBE_HEATING) : GET_TEXT_F(MSG_PROBE_COOLING));
thermalManager.wait_for_probe(target_temp, no_wait_for_cooling);
}
#endif // PROBE_TEMP_COMPENSATION
+337
View File
@@ -0,0 +1,337 @@
/**
* 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/>.
*
*/
/**
* G76_M871.cpp - Temperature calibration/compensation for z-probing
*/
#include "../../inc/MarlinConfig.h"
#if HAS_PTC
#include "../gcode.h"
#include "../../module/motion.h"
#include "../../module/planner.h"
#include "../../module/probe.h"
#include "../../feature/bedlevel/bedlevel.h"
#include "../../module/temperature.h"
#include "../../module/probe.h"
#include "../../feature/probe_temp_comp.h"
#include "../../lcd/marlinui.h"
/**
* G76: calibrate probe and/or bed temperature offsets
* Notes:
* - When calibrating probe, bed temperature is held constant.
* Compensation values are deltas to first probe measurement at probe temp. = 30°C.
* - When calibrating bed, probe temperature is held constant.
* Compensation values are deltas to first probe measurement at bed temp. = 60°C.
* - The hotend will not be heated at any time.
* - On my Průša MK3S clone I put a piece of paper between the probe and the hotend
* so the hotend fan would not cool my probe constantly. Alternatively you could just
* make sure the fan is not running while running the calibration process.
*
* Probe calibration:
* - Moves probe to cooldown point.
* - Heats up bed to 100°C.
* - Moves probe to probing point (1mm above heatbed).
* - Waits until probe reaches target temperature (30°C).
* - Does a z-probing (=base value) and increases target temperature by 5°C.
* - Waits until probe reaches increased target temperature.
* - Does a z-probing (delta to base value will be a compensation value) and increases target temperature by 5°C.
* - Repeats last two steps until max. temperature reached or timeout (i.e. probe does not heat up any further).
* - Compensation values of higher temperatures will be extrapolated (using linear regression first).
* While this is not exact by any means it is still better than simply using the last compensation value.
*
* Bed calibration:
* - Moves probe to cooldown point.
* - Heats up bed to 60°C.
* - Moves probe to probing point (1mm above heatbed).
* - Waits until probe reaches target temperature (30°C).
* - Does a z-probing (=base value) and increases bed temperature by 5°C.
* - Moves probe to cooldown point.
* - Waits until probe is below 30°C and bed has reached target temperature.
* - Moves probe to probing point and waits until it reaches target temperature (30°C).
* - Does a z-probing (delta to base value will be a compensation value) and increases bed temperature by 5°C.
* - Repeats last four points until max. bed temperature reached (110°C) or timeout.
* - Compensation values of higher temperatures will be extrapolated (using linear regression first).
* While this is not exact by any means it is still better than simply using the last compensation value.
*
* G76 [B | P]
* - no flag - Both calibration procedures will be run.
* - `B` - Run bed temperature calibration.
* - `P` - Run probe temperature calibration.
*/
static void say_waiting_for() { SERIAL_ECHOPGM("Waiting for "); }
static void say_waiting_for_probe_heating() { say_waiting_for(); SERIAL_ECHOLNPGM("probe heating."); }
static void say_successfully_calibrated() { SERIAL_ECHOPGM("Successfully calibrated"); }
static void say_failed_to_calibrate() { SERIAL_ECHOPGM("!Failed to calibrate"); }
#if BOTH(PTC_PROBE, PTC_BED)
void GcodeSuite::G76() {
auto report_temps = [](millis_t &ntr, millis_t timeout=0) {
idle_no_sleep();
const millis_t ms = millis();
if (ELAPSED(ms, ntr)) {
ntr = ms + 1000;
thermalManager.print_heater_states(active_extruder);
}
return (timeout && ELAPSED(ms, timeout));
};
auto wait_for_temps = [&](const celsius_t tb, const celsius_t tp, millis_t &ntr, const millis_t timeout=0) {
say_waiting_for(); SERIAL_ECHOLNPGM("bed and probe temperature.");
while (thermalManager.wholeDegBed() != tb || thermalManager.wholeDegProbe() > tp)
if (report_temps(ntr, timeout)) return true;
return false;
};
auto g76_probe = [](const TempSensorID sid, celsius_t &targ, const xy_pos_t &nozpos) {
do_z_clearance(5.0); // Raise nozzle before probing
const float measured_z = probe.probe_at_point(nozpos, PROBE_PT_STOW, 0, false); // verbose=0, probe_relative=false
if (isnan(measured_z))
SERIAL_ECHOLNPGM("!Received NAN. Aborting.");
else {
SERIAL_ECHOLNPAIR_F("Measured: ", measured_z);
if (targ == ProbeTempComp::cali_info[sid].start_temp)
ptc.prepare_new_calibration(measured_z);
else
ptc.push_back_new_measurement(sid, measured_z);
targ += ProbeTempComp::cali_info[sid].temp_resolution;
}
return measured_z;
};
#if ENABLED(BLTOUCH)
// Make sure any BLTouch error condition is cleared
bltouch_command(BLTOUCH_RESET, BLTOUCH_RESET_DELAY);
set_bltouch_deployed(false);
#endif
bool do_bed_cal = parser.boolval('B'), do_probe_cal = parser.boolval('P');
if (!do_bed_cal && !do_probe_cal) do_bed_cal = do_probe_cal = true;
// Synchronize with planner
planner.synchronize();
#ifndef PTC_PROBE_HEATING_OFFSET
#define PTC_PROBE_HEATING_OFFSET 0
#endif
const xyz_pos_t parkpos = PTC_PARK_POS,
probe_pos_xyz = xyz_pos_t(PTC_PROBE_POS) + xyz_pos_t({ 0.0f, 0.0f, PTC_PROBE_HEATING_OFFSET }),
noz_pos_xyz = probe_pos_xyz - probe.offset_xy; // Nozzle position based on probe position
if (do_bed_cal || do_probe_cal) {
// Ensure park position is reachable
bool reachable = position_is_reachable(parkpos) || WITHIN(parkpos.z, Z_MIN_POS - fslop, Z_MAX_POS + fslop);
if (!reachable)
SERIAL_ECHOLNPGM("!Park");
else {
// Ensure probe position is reachable
reachable = probe.can_reach(probe_pos_xyz);
if (!reachable) SERIAL_ECHOLNPGM("!Probe");
}
if (!reachable) {
SERIAL_ECHOLNPGM(" position unreachable - aborting.");
return;
}
process_subcommands_now(FPSTR(G28_STR));
}
remember_feedrate_scaling_off();
/******************************************
* Calibrate bed temperature offsets
******************************************/
// Report temperatures every second and handle heating timeouts
millis_t next_temp_report = millis() + 1000;
auto report_targets = [&](const celsius_t tb, const celsius_t tp) {
SERIAL_ECHOLNPGM("Target Bed:", tb, " Probe:", tp);
};
if (do_bed_cal) {
celsius_t target_bed = PTC_BED_START,
target_probe = PTC_PROBE_TEMP;
say_waiting_for(); SERIAL_ECHOLNPGM(" cooling.");
while (thermalManager.wholeDegBed() > target_bed || thermalManager.wholeDegProbe() > target_probe)
report_temps(next_temp_report);
// Disable leveling so it won't mess with us
TERN_(HAS_LEVELING, set_bed_leveling_enabled(false));
for (uint8_t idx = 0; idx <= PTC_BED_COUNT; idx++) {
thermalManager.setTargetBed(target_bed);
report_targets(target_bed, target_probe);
// Park nozzle
do_blocking_move_to(parkpos);
// Wait for heatbed to reach target temp and probe to cool below target temp
if (wait_for_temps(target_bed, target_probe, next_temp_report, millis() + MIN_TO_MS(15))) {
SERIAL_ECHOLNPGM("!Bed heating timeout.");
break;
}
// Move the nozzle to the probing point and wait for the probe to reach target temp
do_blocking_move_to(noz_pos_xyz);
say_waiting_for_probe_heating();
SERIAL_EOL();
while (thermalManager.wholeDegProbe() < target_probe)
report_temps(next_temp_report);
const float measured_z = g76_probe(TSI_BED, target_bed, noz_pos_xyz);
if (isnan(measured_z) || target_bed > (BED_MAX_TARGET)) break;
}
SERIAL_ECHOLNPGM("Retrieved measurements: ", ptc.get_index());
if (ptc.finish_calibration(TSI_BED)) {
say_successfully_calibrated();
SERIAL_ECHOLNPGM(" bed.");
}
else {
say_failed_to_calibrate();
SERIAL_ECHOLNPGM(" bed. Values reset.");
}
// Cleanup
thermalManager.setTargetBed(0);
TERN_(HAS_LEVELING, set_bed_leveling_enabled(true));
} // do_bed_cal
/********************************************
* Calibrate probe temperature offsets
********************************************/
if (do_probe_cal) {
// Park nozzle
do_blocking_move_to(parkpos);
// Initialize temperatures
const celsius_t target_bed = BED_MAX_TARGET;
thermalManager.setTargetBed(target_bed);
celsius_t target_probe = PTC_PROBE_START;
report_targets(target_bed, target_probe);
// Wait for heatbed to reach target temp and probe to cool below target temp
wait_for_temps(target_bed, target_probe, next_temp_report);
// Disable leveling so it won't mess with us
TERN_(HAS_LEVELING, set_bed_leveling_enabled(false));
bool timeout = false;
for (uint8_t idx = 0; idx <= PTC_PROBE_COUNT; idx++) {
// Move probe to probing point and wait for it to reach target temperature
do_blocking_move_to(noz_pos_xyz);
say_waiting_for_probe_heating();
SERIAL_ECHOLNPGM(" Bed:", target_bed, " Probe:", target_probe);
const millis_t probe_timeout_ms = millis() + SEC_TO_MS(900UL);
while (thermalManager.degProbe() < target_probe) {
if (report_temps(next_temp_report, probe_timeout_ms)) {
SERIAL_ECHOLNPGM("!Probe heating timed out.");
timeout = true;
break;
}
}
if (timeout) break;
const float measured_z = g76_probe(TSI_PROBE, target_probe, noz_pos_xyz);
if (isnan(measured_z)) break;
}
SERIAL_ECHOLNPGM("Retrieved measurements: ", ptc.get_index());
if (ptc.finish_calibration(TSI_PROBE))
say_successfully_calibrated();
else
say_failed_to_calibrate();
SERIAL_ECHOLNPGM(" probe.");
// Cleanup
thermalManager.setTargetBed(0);
TERN_(HAS_LEVELING, set_bed_leveling_enabled(true));
SERIAL_ECHOLNPGM("Final compensation values:");
ptc.print_offsets();
} // do_probe_cal
restore_feedrate_and_scaling();
}
#endif // PTC_PROBE && PTC_BED
/**
* M871: Report / reset temperature compensation offsets.
* Note: This does not affect values in EEPROM until M500.
*
* M871 [ R | B | P | E ]
*
* No Parameters - Print current offset values.
*
* Select only one of these flags:
* R - Reset all offsets to zero (i.e., disable compensation).
* B - Manually set offset for bed
* P - Manually set offset for probe
* E - Manually set offset for extruder
*
* With B, P, or E:
* I[index] - Index in the array
* V[value] - Adjustment in µm
*/
void GcodeSuite::M871() {
if (parser.seen('R')) {
// Reset z-probe offsets to factory defaults
ptc.clear_all_offsets();
SERIAL_ECHOLNPGM("Offsets reset to default.");
}
else if (parser.seen("BPE")) {
if (!parser.seenval('V')) return;
const int16_t offset_val = parser.value_int();
if (!parser.seenval('I')) return;
const int16_t idx = parser.value_int();
const TempSensorID mod = TERN_(PTC_BED, parser.seen_test('B') ? TSI_BED :)
TERN_(PTC_HOTEND, parser.seen_test('E') ? TSI_EXT :)
TERN_(PTC_PROBE, parser.seen_test('P') ? TSI_PROBE :) TSI_COUNT;
if (mod == TSI_COUNT)
SERIAL_ECHOLNPGM("!Invalid sensor.");
else if (idx > 0 && ptc.set_offset(mod, idx - 1, offset_val))
SERIAL_ECHOLNPGM("Set value: ", offset_val);
else
SERIAL_ECHOLNPGM("!Invalid index. Failed to set value (note: value at index 0 is constant).");
}
else // Print current Z-probe adjustments. Note: Values in EEPROM might differ.
ptc.print_offsets();
}
#endif // HAS_PTC
+1 -1
View File
@@ -43,7 +43,7 @@ void GcodeSuite::M304() {
void GcodeSuite::M304_report(const bool forReplay/*=true*/) {
report_heading_etc(forReplay, F(STR_BED_PID));
SERIAL_ECHO_MSG(
SERIAL_ECHOLNPGM(
" M304 P", thermalManager.temp_bed.pid.Kp
, " I", unscalePID_i(thermalManager.temp_bed.pid.Ki)
, " D", unscalePID_d(thermalManager.temp_bed.pid.Kd)
+1 -1
View File
@@ -344,7 +344,7 @@ void GcodeSuite::M43() {
#if HAS_RESUME_CONTINUE
KEEPALIVE_STATE(PAUSED_FOR_USER);
wait_for_user = true;
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, F("M43 Wait Called"), FPSTR(CONTINUE_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, F("M43 Wait Called"), FPSTR(CONTINUE_STR)));
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(F("M43 Wait Called")));
#endif
+1 -1
View File
@@ -26,7 +26,7 @@
* M111: Set the debug level
*/
void GcodeSuite::M111() {
if (parser.seen('S')) marlin_debug_flags = parser.byteval('S');
if (parser.seenval('S')) marlin_debug_flags = parser.value_byte();
static PGMSTR(str_debug_1, STR_DEBUG_ECHO);
static PGMSTR(str_debug_2, STR_DEBUG_INFO);
+2 -2
View File
@@ -126,10 +126,10 @@ void GcodeSuite::M42() {
extDigitalWrite(pin, pin_status);
#ifdef ARDUINO_ARCH_STM32
// A simple I/O will be set to 0 by analogWrite()
// A simple I/O will be set to 0 by set_pwm_duty()
if (pin_status <= 1 && !PWM_PIN(pin)) return;
#endif
analogWrite(pin, pin_status);
set_pwm_duty(pin, pin_status);
}
#endif // DIRECT_PIN_CONTROL
+1 -2
View File
@@ -74,13 +74,12 @@
* This code should ALWAYS be available for FULL SHUTDOWN!
*/
void GcodeSuite::M81() {
thermalManager.disable_all_heaters();
planner.finish_and_disable();
thermalManager.cooldown();
print_job_timer.stop();
#if HAS_FAN
thermalManager.zero_fan_speeds();
#if ENABLED(PROBING_FANS_OFF)
thermalManager.fans_paused = false;
ZERO(thermalManager.saved_fan_speed);
+1 -1
View File
@@ -280,7 +280,7 @@ void GcodeSuite::M906() {
#if E_STEPPERS
case E_AXIS: {
const int8_t target_e_stepper = get_target_e_stepper_from_command();
const int8_t target_e_stepper = get_target_e_stepper_from_command(0);
if (target_e_stepper < 0) return;
switch (target_e_stepper) {
#if AXIS_IS_L64XX(E0)
+1 -1
View File
@@ -133,7 +133,7 @@ static void say_stealth_status() {
*/
void GcodeSuite::M569() {
if (parser.seen('S'))
set_stealth_status(parser.value_bool(), get_target_e_stepper_from_command());
set_stealth_status(parser.value_bool(), get_target_e_stepper_from_command(0));
else
say_stealth_status();
}
+1 -1
View File
@@ -104,7 +104,7 @@ void GcodeSuite::M906() {
#if E_STEPPERS
case E_AXIS: {
const int8_t target_e_stepper = get_target_e_stepper_from_command();
const int8_t target_e_stepper = get_target_e_stepper_from_command(0);
if (target_e_stepper < 0) return;
switch (target_e_stepper) {
#if AXIS_IS_TMC(E0)
@@ -268,7 +268,7 @@
break;
#if E_STEPPERS
case E_AXIS: {
const int8_t target_e_stepper = get_target_e_stepper_from_command();
const int8_t target_e_stepper = get_target_e_stepper_from_command(0);
if (target_e_stepper < 0) return;
switch (target_e_stepper) {
TERN_(E0_HAS_STEALTHCHOP, case 0: TMC_SET_PWMTHRS_E(0); break;)
+22 -17
View File
@@ -137,11 +137,12 @@ int8_t GcodeSuite::get_target_extruder_from_command() {
}
/**
* Get the target e stepper from the T parameter
* Return -1 if the T parameter is out of range or unspecified
* Get the target E stepper from the 'T' parameter.
* If there is no 'T' parameter then dval will be substituted.
* Returns -1 if the resulting E stepper index is out of range.
*/
int8_t GcodeSuite::get_target_e_stepper_from_command() {
const int8_t e = parser.intval('T', -1);
int8_t GcodeSuite::get_target_e_stepper_from_command(const int8_t dval/*=-1*/) {
const int8_t e = parser.intval('T', dval);
if (WITHIN(e, 0, E_STEPPERS - 1)) return e;
SERIAL_ECHO_START();
@@ -237,9 +238,9 @@ void GcodeSuite::dwell(millis_t time) {
#if ENABLED(G29_RETRY_AND_RECOVER)
void GcodeSuite::event_probe_recover() {
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_INFO, F("G29 Retrying"), FPSTR(DISMISS_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_INFO, F("G29 Retrying"), FPSTR(DISMISS_STR)));
#ifdef ACTION_ON_G29_RECOVER
host_action(F(ACTION_ON_G29_RECOVER));
hostui.g29_recover();
#endif
#ifdef G29_RECOVER_COMMANDS
process_subcommands_now(F(G29_RECOVER_COMMANDS));
@@ -252,14 +253,14 @@ void GcodeSuite::dwell(millis_t time) {
void GcodeSuite::event_probe_failure() {
#ifdef ACTION_ON_G29_FAILURE
host_action(F(ACTION_ON_G29_FAILURE));
hostui.g29_failure();
#endif
#ifdef G29_FAILURE_COMMANDS
process_subcommands_now(F(G29_FAILURE_COMMANDS));
#endif
#if ENABLED(G29_HALT_ON_FAILURE)
#ifdef ACTION_ON_CANCEL
host_action_cancel();
hostui.cancel();
#endif
kill(GET_TEXT_F(MSG_LCD_PROBING_FAILED));
#endif
@@ -282,7 +283,7 @@ void GcodeSuite::dwell(millis_t time) {
}
}
TERN_(HOST_PROMPT_SUPPORT, host_action_prompt_end());
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_end());
#ifdef G29_SUCCESS_COMMANDS
process_subcommands_now(F(G29_SUCCESS_COMMANDS));
@@ -423,7 +424,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 61: G61(); break; // G61: Apply/restore saved coordinates.
#endif
#if ENABLED(PROBE_TEMP_COMPENSATION)
#if BOTH(PTC_PROBE, PTC_BED)
case 76: G76(); break; // G76: Calibrate first layer compensation values
#endif
@@ -586,6 +587,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 191: M191(); break; // M191: Wait for chamber temperature to reach target
#endif
#if HAS_TEMP_PROBE
case 192: M192(); break; // M192: Wait for probe temp
#endif
#if HAS_COOLER
case 143: M143(); break; // M143: Set cooler temperature
case 193: M193(); break; // M193: Wait for cooler temperature to reach target
@@ -639,7 +644,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 120: M120(); break; // M120: Enable endstops
case 121: M121(); break; // M121: Disable endstops
#if PREHEAT_COUNT
#if HAS_PREHEAT
case 145: M145(); break; // M145: Set material heatup parameters
#endif
@@ -920,8 +925,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 852: M852(); break; // M852: Set Skew factors
#endif
#if ENABLED(PROBE_TEMP_COMPENSATION)
case 192: M192(); break; // M192: Wait for probe temp
#if HAS_PTC
case 871: M871(); break; // M871: Print/reset/clear first layer temperature offset values
#endif
@@ -1095,14 +1099,15 @@ void GcodeSuite::process_next_command() {
process_parsed_command();
}
#pragma GCC diagnostic push
#if GCC_VERSION >= 80000
#pragma GCC diagnostic ignored "-Wstringop-truncation"
#endif
/**
* Run a series of commands, bypassing the command queue to allow
* G-code "macros" to be called from within other G-code handlers.
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
void GcodeSuite::process_subcommands_now(FSTR_P fgcode) {
PGM_P pgcode = FTOP(fgcode);
char * const saved_cmd = parser.command_ptr; // Save the parser state
+42 -21
View File
@@ -66,7 +66,7 @@
* G42 - Coordinated move to a mesh point (Requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BLINEAR, or AUTO_BED_LEVELING_UBL)
* G60 - Save current position. (Requires SAVED_POSITIONS)
* G61 - Apply/restore saved coordinates. (Requires SAVED_POSITIONS)
* G76 - Calibrate first layer temperature offsets. (Requires PROBE_TEMP_COMPENSATION)
* G76 - Calibrate first layer temperature offsets. (Requires PTC_PROBE and PTC_BED)
* G80 - Cancel current motion mode (Requires GCODE_MOTION_MODES)
* G90 - Use Absolute Coordinates
* G91 - Use Relative Coordinates
@@ -88,6 +88,8 @@
* M16 - Expected printer check. (Requires EXPECTED_PRINTER_CHECK)
* M17 - Enable/Power all stepper motors
* M18 - Disable all stepper motors; same as M84
*
*** Print from Media (SDSUPPORT) ***
* M20 - List SD card. (Requires SDSUPPORT)
* M21 - Init SD card. (Requires SDSUPPORT)
* M22 - Release SD card. (Requires SDSUPPORT)
@@ -100,30 +102,36 @@
* OR, with 'C' get the current filename.
* M28 - Start SD write: "M28 /path/file.gco". (Requires SDSUPPORT)
* M29 - Stop SD write. (Requires SDSUPPORT)
* M30 - Delete file from SD: "M30 /path/file.gco"
* M30 - Delete file from SD: "M30 /path/file.gco" (Requires SDSUPPORT)
* M31 - Report time since last M109 or SD card start to serial.
* M32 - Select file and start SD print: "M32 [S<bytepos>] !/path/file.gco#". (Requires SDSUPPORT)
* Use P to run other files as sub-programs: "M32 P !filename#"
* The '#' is necessary when calling from within sd files, as it stops buffer prereading
* M33 - Get the longname version of a path. (Requires LONG_FILENAME_HOST_SUPPORT)
* M34 - Set SD Card sorting options. (Requires SDCARD_SORT_ALPHA)
*
* M42 - Change pin status via gcode: M42 P<pin> S<value>. LED pin assumed if P is omitted. (Requires DIRECT_PIN_CONTROL)
* M43 - Display pin status, watch pins for changes, watch endstops & toggle LED, Z servo probe test, toggle pins
* M43 - Display pin status, watch pins for changes, watch endstops & toggle LED, Z servo probe test, toggle pins (Requires PINS_DEBUGGING)
* M48 - Measure Z Probe repeatability: M48 P<points> X<pos> Y<pos> V<level> E<engage> L<legs> S<chizoid>. (Requires Z_MIN_PROBE_REPEATABILITY_TEST)
*
* M73 - Set the progress percentage. (Requires LCD_SET_PROGRESS_MANUALLY)
* M75 - Start the print job timer.
* M76 - Pause the print job timer.
* M77 - Stop the print job timer.
* M78 - Show statistical information about the print jobs. (Requires PRINTCOUNTER)
*
* M80 - Turn on Power Supply. (Requires PSU_CONTROL)
* M81 - Turn off Power Supply. (Requires PSU_CONTROL)
*
* M82 - Set E codes absolute (default).
* M83 - Set E codes relative while in Absolute (G90) mode.
* M84 - Disable steppers until next move, or use S<seconds> to specify an idle
* duration after which steppers should turn off. S0 disables the timeout.
* M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
* M92 - Set planner.settings.axis_steps_per_mm for one or more axes.
*
* M100 - Watch Free Memory (for debugging) (Requires M100_FREE_MEMORY_WATCHER)
*
* M104 - Set extruder target temp.
* M105 - Report current temperatures.
* M106 - Set print fan speed.
@@ -132,23 +140,29 @@
* M109 - S<temp> Wait for extruder current temp to reach target temp. ** Wait only when heating! **
* R<temp> Wait for extruder current temp to reach target temp. ** Wait for heating or cooling. **
* If AUTOTEMP is enabled, S<mintemp> B<maxtemp> F<factor>. Exit autotemp by any M109 without F
*
* M110 - Set the current line number. (Used by host printing)
* M111 - Set debug flags: "M111 S<flagbits>". See flag bits defined in enum.h.
* M112 - Full Shutdown.
*
* M113 - Get or set the timeout interval for Host Keepalive "busy" messages. (Requires HOST_KEEPALIVE_FEATURE)
* M114 - Report current position.
* M115 - Report capabilities. (Extended capabilities requires EXTENDED_CAPABILITIES_REPORT)
* M117 - Display a message on the controller screen. (Requires an LCD)
* M118 - Display a message in the host console.
*
* M119 - Report endstops status.
* M120 - Enable endstops detection.
* M121 - Disable endstops detection.
*
* M122 - Debug stepper (Requires at least one _DRIVER_TYPE defined as TMC2130/2160/5130/5160/2208/2209/2660 or L6470)
* M125 - Save current position and move to filament change position. (Requires PARK_HEAD_ON_PAUSE)
*
* M126 - Solenoid Air Valve Open. (Requires BARICUDA)
* M127 - Solenoid Air Valve Closed. (Requires BARICUDA)
* M128 - EtoP Open. (Requires BARICUDA)
* M129 - EtoP Closed. (Requires BARICUDA)
*
* M140 - Set bed target temp. S<temp>
* M141 - Set heated chamber target temp. S<temp> (Requires a chamber heater)
* M143 - Set cooler target temp. S<temp> (Requires a laser cooling device)
@@ -161,9 +175,9 @@
* M164 - Commit the mix and save to a virtual tool (current, or as specified by 'S'). (Requires MIXING_EXTRUDER)
* M165 - Set the mix for the mixing extruder (and current virtual tool) with parameters ABCDHI. (Requires MIXING_EXTRUDER and DIRECT_MIXING_IN_G1)
* M166 - Set the Gradient Mix for the mixing extruder. (Requires GRADIENT_MIX)
* M190 - S<temp> Wait for bed current temp to reach target temp. ** Wait only when heating! **
* R<temp> Wait for bed current temp to reach target temp. ** Wait for heating or cooling. **
* M193 - R<temp> Wait for cooler temp to reach target temp. ** Wait for cooling. **
* M190 - Set bed target temperature and wait. R<temp> Set target temperature and wait. S<temp> Set, but only wait when heating. (Requires TEMP_SENSOR_BED)
* M192 - Wait for probe to reach target temperature. (Requires TEMP_SENSOR_PROBE)
* M193 - R<temp> Wait for cooler to reach target temp. ** Wait for cooling. **
* M200 - Set filament diameter, D<diameter>, setting E axis units to cubic. (Use S0 to revert to linear units.)
* M201 - Set max acceleration in units/s^2 for print moves: "M201 X<accel> Y<accel> Z<accel> E<accel>"
* M202 - Set max acceleration in units/s^2 for travel moves: "M202 X<accel> Y<accel> Z<accel> E<accel>" ** UNUSED IN MARLIN! **
@@ -183,7 +197,7 @@
* M218 - Set/get a tool offset: "M218 T<index> X<offset> Y<offset>". (Requires 2 or more extruders)
* M220 - Set Feedrate Percentage: "M220 S<percent>" (i.e., "FR" on the LCD)
* Use "M220 B" to back up the Feedrate Percentage and "M220 R" to restore it. (Requires an MMU_MODEL version 2 or 2S)
* M221 - Set Flow Percentage: "M221 S<percent>"
* M221 - Set Flow Percentage: "M221 S<percent>" (Requires an extruder)
* M226 - Wait until a pin is in a given state: "M226 P<pin> S<state>" (Requires DIRECT_PIN_CONTROL)
* M240 - Trigger a camera to take a photograph. (Requires PHOTO_GCODE)
* M250 - Set LCD contrast: "M250 C<contrast>" (0-63). (Requires LCD support)
@@ -230,9 +244,9 @@
* M502 - Revert to the default "factory settings". ** Does not write them to EEPROM! **
* M503 - Print the current settings (in memory): "M503 S<verbose>". S0 specifies compact output.
* M504 - Validate EEPROM contents. (Requires EEPROM_SETTINGS)
* M510 - Lock Printer
* M511 - Unlock Printer
* M512 - Set/Change/Remove Password
* M510 - Lock Printer (Requires PASSWORD_FEATURE)
* M511 - Unlock Printer (Requires PASSWORD_UNLOCK_GCODE)
* M512 - Set/Change/Remove Password (Requires PASSWORD_CHANGE_GCODE)
* M524 - Abort the current SD print job started with M24. (Requires SDSUPPORT)
* M540 - Enable/disable SD card abort on endstop hit: "M540 S<state>". (Requires SD_ABORT_ON_ENDSTOP_HIT)
* M552 - Get or set IP address. Enable/disable network interface. (Requires enabled Ethernet port)
@@ -252,7 +266,9 @@
* M808 - Set or Goto a Repeat Marker (Requires GCODE_REPEAT_MARKERS)
* M810-M819 - Define/execute a G-code macro (Requires GCODE_MACROS)
* M851 - Set Z probe's XYZ offsets in current units. (Negative values: X=left, Y=front, Z=below)
* M852 - Set skew factors: "M852 [I<xy>] [J<xz>] [K<yz>]". (Requires SKEW_CORRECTION_GCODE, and SKEW_CORRECTION_FOR_Z for IJ)
* M852 - Set skew factors: "M852 [I<xy>] [J<xz>] [K<yz>]". (Requires SKEW_CORRECTION_GCODE, plus SKEW_CORRECTION_FOR_Z for IJ)
*
*** I2C_POSITION_ENCODERS ***
* M860 - Report the position of position encoder modules.
* M861 - Report the status of position encoder modules.
* M862 - Perform an axis continuity test for position encoder modules.
@@ -263,8 +279,8 @@
* M867 - Enable/disable or toggle error correction for position encoder modules.
* M868 - Report or set position encoder module error correction threshold.
* M869 - Report position encoder module error.
* M871 - Print/reset/clear first layer temperature offset values. (Requires PROBE_TEMP_COMPENSATION)
* M192 - Wait for probe temp (Requires PROBE_TEMP_COMPENSATION)
*
* M871 - Print/reset/clear first layer temperature offset values. (Requires PTC_PROBE, PTC_BED, or PTC_HOTEND)
* M876 - Handle Prompt Response. (Requires HOST_PROMPT_SUPPORT and not EMERGENCY_PARSER)
* M900 - Get or Set Linear Advance K-factor. (Requires LIN_ADVANCE)
* M906 - Set or get motor current in milliamps using axis codes X, Y, Z, E. Report values if no axis codes given. (Requires at least one _DRIVER_TYPE defined as TMC2130/2160/5130/5160/2208/2209/2660 or L6470)
@@ -282,13 +298,14 @@
* M951 - Set Magnetic Parking Extruder parameters. (Requires MAGNETIC_PARKING_EXTRUDER)
* M7219 - Control Max7219 Matrix LEDs. (Requires MAX7219_GCODE)
*
*** SCARA ***
* M360 - SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
* M361 - SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
* M362 - SCARA calibration: Move to cal-position PsiA (0 deg calibration)
* M363 - SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree)
* M364 - SCARA calibration: Move to cal-position PSIC (90 deg to Theta calibration position)
*
* ************ Custom codes - This can change to suit future G-code regulations
*** Custom codes (can be changed to suit future G-code standards) ***
* G425 - Calibrate using a conductive object. (Requires CALIBRATION_GCODE)
* M928 - Start SD logging: "M928 filename.gco". Stop with M29. (Requires SDSUPPORT)
* M993 - Backup SPI Flash to SD
@@ -296,10 +313,11 @@
* M995 - Touch screen calibration for TFT display
* M997 - Perform in-application firmware update
* M999 - Restart after being stopped by error
*
* D... - Custom Development G-code. Add hooks to 'gcode_D.cpp' for developers to test features. (Requires MARLIN_DEV_MODE)
* D576 - Set buffer monitoring options. (Requires BUFFER_MONITORING)
*
* "T" Codes
*** "T" Codes ***
*
* T0-T3 - Select an extruder (tool) by index: "T<n> F<units/min>"
*/
@@ -390,7 +408,7 @@ public:
static void say_units();
static int8_t get_target_extruder_from_command();
static int8_t get_target_e_stepper_from_command();
static int8_t get_target_e_stepper_from_command(const int8_t dval=-1);
static void get_destination_from_command();
static void process_parsed_command(const bool no_ok=false);
@@ -551,7 +569,7 @@ private:
static void G59();
#endif
#if ENABLED(PROBE_TEMP_COMPENSATION)
#if BOTH(PTC_PROBE, PTC_BED)
static void G76();
#endif
@@ -744,12 +762,16 @@ private:
static void M191();
#endif
#if HAS_TEMP_PROBE
static void M192();
#endif
#if HAS_COOLER
static void M143();
static void M193();
#endif
#if PREHEAT_COUNT
#if HAS_PREHEAT
static void M145();
static void M145_report(const bool forReplay=true);
#endif
@@ -1087,8 +1109,7 @@ private:
FORCE_INLINE static void M869() { I2CPEM.M869(); }
#endif
#if ENABLED(PROBE_TEMP_COMPENSATION)
static void M192();
#if HAS_PTC
static void M871();
#endif
@@ -1109,7 +1130,7 @@ private:
static void M913();
static void M913_report(const bool forReplay=true);
#endif
#if ENABLED(USE_SENSORLESS)
#if USE_SENSORLESS
static void M914();
static void M914_report(const bool forReplay=true);
#endif
+1 -1
View File
@@ -33,7 +33,7 @@
*/
void GcodeSuite::M876() {
if (parser.seenval('S')) host_response_handler((uint8_t)parser.value_int());
if (parser.seenval('S')) hostui.handle_response((uint8_t)parser.value_int());
}
+1 -1
View File
@@ -84,7 +84,7 @@ void GcodeSuite::M0_M1() {
#endif
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, parser.codenum ? F("M1 Stop") : F("M0 Stop"), FPSTR(CONTINUE_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, parser.codenum ? F("M1 Stop") : F("M0 Stop"), FPSTR(CONTINUE_STR)));
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response(ms));
+2 -2
View File
@@ -22,7 +22,7 @@
#include "../../inc/MarlinConfig.h"
#if PREHEAT_COUNT
#if HAS_PREHEAT
#include "../gcode.h"
#include "../../lcd/marlinui.h"
@@ -79,4 +79,4 @@ void GcodeSuite::M145_report(const bool forReplay/*=true*/) {
}
}
#endif // PREHEAT_COUNT
#endif // HAS_PREHEAT
+1 -1
View File
@@ -719,7 +719,7 @@ void GCodeQueue::advance() {
if (auto_buffer_report_interval && ELAPSED(ms, next_buffer_report_ms)) {
next_buffer_report_ms = ms + 1000UL * auto_buffer_report_interval;
PORT_REDIRECT(SERIAL_BOTH);
PORT_REDIRECT(SerialMask::All);
report_buffer_statistics();
PORT_RESTORE();
}
+1 -1
View File
@@ -133,7 +133,7 @@ public:
* Enqueue command(s) to run from SRAM. Drained by process_injected_command().
* Aborts the current SRAM queue so only use for one or two commands.
*/
static inline void inject(char * const gcode) {
static inline void inject(const char * const gcode) {
strncpy(injected_commands, gcode, sizeof(injected_commands) - 1);
}
+1 -1
View File
@@ -97,7 +97,7 @@ void GcodeSuite::M1001() {
if (long_print) {
printerEventLEDs.onPrintCompleted();
TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_PRINT_DONE)));
TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_PRINT_DONE), FPSTR(CONTINUE_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_PRINT_DONE), FPSTR(CONTINUE_STR)));
TERN_(HAS_RESUME_CONTINUE, wait_for_user_response(SEC_TO_MS(TERN(HAS_LCD_MENU, PE_LEDS_COMPLETED_TIME, 30))));
printerEventLEDs.onResumeAfterWait();
}
+4 -4
View File
@@ -77,9 +77,9 @@ void GcodeSuite::M24() {
#if ENABLED(HOST_ACTION_COMMANDS)
#ifdef ACTION_ON_RESUME
host_action_resume();
hostui.resume();
#endif
TERN_(HOST_PROMPT_SUPPORT, host_prompt_open(PROMPT_INFO, F("Resuming SD"), FPSTR(DISMISS_STR)));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_open(PROMPT_INFO, F("Resuming SD"), FPSTR(DISMISS_STR)));
#endif
ui.reset_status();
@@ -116,9 +116,9 @@ void GcodeSuite::M25() {
IF_DISABLED(DWIN_CREALITY_LCD, ui.reset_status());
#if ENABLED(HOST_ACTION_COMMANDS)
TERN_(HOST_PROMPT_SUPPORT, host_prompt_open(PROMPT_PAUSE_RESUME, F("Pause SD"), F("Resume")));
TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_open(PROMPT_PAUSE_RESUME, F("Pause SD"), F("Resume")));
#ifdef ACTION_ON_PAUSE
host_action_pause();
hostui.pause();
#endif
#endif
+1 -1
View File
@@ -49,7 +49,7 @@ void GcodeSuite::M75() {
*/
void GcodeSuite::M76() {
print_job_timer.pause();
TERN_(HOST_PAUSE_M76, host_action_pause());
TERN_(HOST_PAUSE_M76, hostui.pause());
}
/**
+1 -1
View File
@@ -88,7 +88,7 @@ void GcodeSuite::M104_M109(const bool isM109) {
celsius_t temp = 0;
// Accept 'I' if temperature presets are defined
#if PREHEAT_COUNT
#if HAS_PREHEAT
got_temp = parser.seenval('I');
if (got_temp) {
const uint8_t index = parser.value_byte();
+2 -2
View File
@@ -32,7 +32,7 @@
#include "../../module/planner.h"
#endif
#if PREHEAT_COUNT
#if HAS_PREHEAT
#include "../../lcd/marlinui.h"
#endif
@@ -75,7 +75,7 @@ void GcodeSuite::M106() {
uint16_t speed = dspeed;
// Accept 'I' if temperature presets are defined
#if PREHEAT_COUNT
#if HAS_PREHEAT
const bool got_preset = parser.seenval('I');
if (got_preset) speed = ui.material_preset[_MIN(parser.value_byte(), PREHEAT_COUNT - 1)].fan_speed;
#else
+1 -1
View File
@@ -63,7 +63,7 @@ void GcodeSuite::M140_M190(const bool isM190) {
celsius_t temp = 0;
// Accept 'I' if temperature presets are defined
#if PREHEAT_COUNT
#if HAS_PREHEAT
got_temp = parser.seenval('I');
if (got_temp) {
const uint8_t index = parser.value_byte();
+56
View File
@@ -0,0 +1,56 @@
/**
* 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/>.
*
*/
/**
* M192.cpp - Wait for probe to reach temperature
*/
#include "../../inc/MarlinConfig.h"
#if HAS_TEMP_PROBE
#include "../gcode.h"
#include "../../module/temperature.h"
#include "../../lcd/marlinui.h"
/**
* M192: Wait for probe temperature sensor to reach a target
*
* Select only one of these flags:
* R - Wait for heating or cooling
* S - Wait only for heating
*/
void GcodeSuite::M192() {
if (DEBUGGING(DRYRUN)) return;
const bool no_wait_for_cooling = parser.seenval('S');
if (!no_wait_for_cooling && !parser.seenval('R')) {
SERIAL_ERROR_MSG("No target temperature set.");
return;
}
const celsius_t target_temp = parser.value_celsius();
ui.set_status(thermalManager.isProbeBelowTemp(target_temp) ? GET_TEXT_F(MSG_PROBE_HEATING) : GET_TEXT_F(MSG_PROBE_COOLING));
thermalManager.wait_for_probe(target_temp, no_wait_for_cooling);
}
#endif // HAS_TEMP_PROBE
+6 -7
View File
@@ -332,7 +332,6 @@
#if ANY(FSMC_GRAPHICAL_TFT, SPI_GRAPHICAL_TFT, TFT_320x240, TFT_480x320, TFT_320x240_SPI, TFT_480x320_SPI, TFT_LVGL_UI_FSMC, TFT_LVGL_UI_SPI)
#define IS_LEGACY_TFT 1
#define TFT_GENERIC
#warning "Don't forget to update your TFT settings in Configuration.h."
#endif
#if ANY(FSMC_GRAPHICAL_TFT, TFT_320x240, TFT_480x320, TFT_LVGL_UI_FSMC)
@@ -1251,20 +1250,20 @@
* - TFT_COLOR
* - GRAPHICAL_TFT_UPSCALE
*/
#if ENABLED(MKS_TS35_V2_0) // ST7796
#if EITHER(MKS_TS35_V2_0, BTT_TFT35_SPI_V1_0) // ST7796
#define TFT_DEFAULT_DRIVER ST7796
#define TFT_DEFAULT_ORIENTATION TFT_EXCHANGE_XY
#define TFT_RES_480x320
#define TFT_INTERFACE_SPI
#elif EITHER(LERDGE_TFT35, ANET_ET5_TFT35) // ST7796
#elif EITHER(LERDGE_TFT35, ANET_ET5_TFT35) // ST7796
#define TFT_DEFAULT_ORIENTATION TFT_EXCHANGE_XY
#define TFT_RES_480x320
#define TFT_INTERFACE_FSMC
#elif ANY(ANET_ET4_TFT28, MKS_ROBIN_TFT24, MKS_ROBIN_TFT28, MKS_ROBIN_TFT32) // ST7789
#elif ANY(ANET_ET4_TFT28, MKS_ROBIN_TFT24, MKS_ROBIN_TFT28, MKS_ROBIN_TFT32) // ST7789
#define TFT_DEFAULT_ORIENTATION (TFT_EXCHANGE_XY | TFT_INVERT_Y)
#define TFT_RES_320x240
#define TFT_INTERFACE_FSMC
#elif ANY(MKS_ROBIN_TFT35, TFT_TRONXY_X5SA, ANYCUBIC_TFT35) // ILI9488
#elif ANY(MKS_ROBIN_TFT35, TFT_TRONXY_X5SA, ANYCUBIC_TFT35) // ILI9488
#define TFT_DRIVER ILI9488
#define TFT_DEFAULT_ORIENTATION (TFT_EXCHANGE_XY | TFT_INVERT_X | TFT_INVERT_Y)
#define TFT_RES_480x320
@@ -1274,11 +1273,11 @@
#define TFT_DEFAULT_ORIENTATION 0
#define TFT_RES_480x272
#define TFT_INTERFACE_FSMC
#elif ANY(MKS_ROBIN_TFT_V1_1R, LONGER_LK_TFT28) // ILI9328 or R61505
#elif ANY(MKS_ROBIN_TFT_V1_1R, LONGER_LK_TFT28) // ILI9328 or R61505
#define TFT_DEFAULT_ORIENTATION (TFT_EXCHANGE_XY | TFT_INVERT_X | TFT_INVERT_Y)
#define TFT_RES_320x240
#define TFT_INTERFACE_FSMC
#elif ENABLED(BIQU_BX_TFT70) // RGB
#elif ENABLED(BIQU_BX_TFT70) // RGB
#define TFT_DEFAULT_ORIENTATION TFT_EXCHANGE_XY
#define TFT_RES_1024x600
#define TFT_INTERFACE_LTDC
+24 -9
View File
@@ -132,17 +132,15 @@
#define HID_E6 6
#define HID_E7 7
#define ANY_TEMP_SENSOR_IS(n) (n == TEMP_SENSOR_0 || n == TEMP_SENSOR_1 || n == TEMP_SENSOR_2 || n == TEMP_SENSOR_3 \
|| n == TEMP_SENSOR_4 || n == TEMP_SENSOR_5 || n == TEMP_SENSOR_6 || n == TEMP_SENSOR_7 \
|| n == TEMP_SENSOR_BED \
|| n == TEMP_SENSOR_PROBE \
|| n == TEMP_SENSOR_CHAMBER \
|| n == TEMP_SENSOR_COOLER \
|| n == TEMP_SENSOR_REDUNDANT )
#if ANY_TEMP_SENSOR_IS(1000)
#define _SENSOR_IS(I,N) || (TEMP_SENSOR_##N == I)
#define _E_SENSOR_IS(I,N) _SENSOR_IS(N,I)
#define ANY_THERMISTOR_IS(N) (0 REPEAT2(HOTENDS, _E_SENSOR_IS, N) \
_SENSOR_IS(N,BED) _SENSOR_IS(N,PROBE) _SENSOR_IS(N,CHAMBER) \
_SENSOR_IS(N,COOLER) _SENSOR_IS(N,BOARD) _SENSOR_IS(N,REDUNDANT) )
#if ANY_THERMISTOR_IS(1000)
#define HAS_USER_THERMISTORS 1
#endif
#undef ANY_TEMP_SENSOR_IS
#if TEMP_SENSOR_REDUNDANT
#define _HEATER_ID(M) HID_##M
@@ -552,6 +550,20 @@
#endif
#endif
// Probe Temperature Compensation
#if !TEMP_SENSOR_PROBE
#undef PTC_PROBE
#endif
#if !TEMP_SENSOR_BED
#undef PTC_BED
#endif
#if !HAS_EXTRUDERS
#undef PTC_HOTEND
#endif
#if ANY(PTC_PROBE, PTC_BED, PTC_HOTEND)
#define HAS_PTC 1
#endif
// Let SD_FINISHED_RELEASECOMMAND stand in for SD_FINISHED_STEPPERRELEASE
#if ENABLED(SD_FINISHED_STEPPERRELEASE)
#ifndef SD_FINISHED_RELEASECOMMAND
@@ -703,6 +715,9 @@
#ifndef ACTION_ON_KILL
#define ACTION_ON_KILL "poweroff"
#endif
#ifndef SHUTDOWN_ACTION
#define SHUTDOWN_ACTION "shutdown"
#endif
#if HAS_FILAMENT_SENSOR
#ifndef ACTION_ON_FILAMENT_RUNOUT
#define ACTION_ON_FILAMENT_RUNOUT "filament_runout"
+106 -31
View File
@@ -769,19 +769,25 @@
#define X2_MAX_ENDSTOP_INVERTING false
#endif
#endif
#ifndef X2_MAX_PIN
#if !defined(X2_MAX_PIN) && !defined(X2_STOP_PIN)
#if X2_USE_ENDSTOP == _XMIN_
#define X2_MAX_PIN X_MIN_PIN
#elif X2_USE_ENDSTOP == _XMAX_
#define X2_MAX_PIN X_MAX_PIN
#elif X2_USE_ENDSTOP == _XSTOP_
#define X2_MAX_PIN X_STOP_PIN
#elif X2_USE_ENDSTOP == _YMIN_
#define X2_MAX_PIN Y_MIN_PIN
#elif X2_USE_ENDSTOP == _YMAX_
#define X2_MAX_PIN Y_MAX_PIN
#elif X2_USE_ENDSTOP == _YSTOP_
#define X2_MAX_PIN Y_STOP_PIN
#elif X2_USE_ENDSTOP == _ZMIN_
#define X2_MAX_PIN Z_MIN_PIN
#elif X2_USE_ENDSTOP == _ZMAX_
#define X2_MAX_PIN Z_MAX_PIN
#elif X2_USE_ENDSTOP == _ZSTOP_
#define X2_MAX_PIN Z_STOP_PIN
#elif X2_USE_ENDSTOP == _XDIAG_
#define X2_MAX_PIN X_DIAG_PIN
#elif X2_USE_ENDSTOP == _YDIAG_
@@ -827,19 +833,25 @@
#define X2_MIN_ENDSTOP_INVERTING false
#endif
#endif
#ifndef X2_MIN_PIN
#if !defined(X2_MIN_PIN) && !defined(X2_STOP_PIN)
#if X2_USE_ENDSTOP == _XMIN_
#define X2_MIN_PIN X_MIN_PIN
#elif X2_USE_ENDSTOP == _XMAX_
#define X2_MIN_PIN X_MAX_PIN
#elif X2_USE_ENDSTOP == _XSTOP_
#define X2_MIN_PIN X_STOP_PIN
#elif X2_USE_ENDSTOP == _YMIN_
#define X2_MIN_PIN Y_MIN_PIN
#elif X2_USE_ENDSTOP == _YMAX_
#define X2_MIN_PIN Y_MAX_PIN
#elif X2_USE_ENDSTOP == _YSTOP_
#define X2_MIN_PIN Y_STOP_PIN
#elif X2_USE_ENDSTOP == _ZMIN_
#define X2_MIN_PIN Z_MIN_PIN
#elif X2_USE_ENDSTOP == _ZMAX_
#define X2_MIN_PIN Z_MAX_PIN
#elif X2_USE_ENDSTOP == _ZSTOP_
#define X2_MIN_PIN Z_STOP_PIN
#elif X2_USE_ENDSTOP == _XDIAG_
#define X2_MIN_PIN X_DIAG_PIN
#elif X2_USE_ENDSTOP == _YDIAG_
@@ -892,19 +904,25 @@
#define Y2_MAX_ENDSTOP_INVERTING false
#endif
#endif
#ifndef Y2_MAX_PIN
#if !defined(Y2_MAX_PIN) && !defined(Y2_STOP_PIN)
#if Y2_USE_ENDSTOP == _XMIN_
#define Y2_MAX_PIN X_MIN_PIN
#elif Y2_USE_ENDSTOP == _XMAX_
#define Y2_MAX_PIN X_MAX_PIN
#elif Y2_USE_ENDSTOP == _XSTOP_
#define Y2_MAX_PIN X_STOP_PIN
#elif Y2_USE_ENDSTOP == _YMIN_
#define Y2_MAX_PIN Y_MIN_PIN
#elif Y2_USE_ENDSTOP == _YMAX_
#define Y2_MAX_PIN Y_MAX_PIN
#elif Y2_USE_ENDSTOP == _YSTOP_
#define Y2_MAX_PIN Y_STOP_PIN
#elif Y2_USE_ENDSTOP == _ZMIN_
#define Y2_MAX_PIN Z_MIN_PIN
#elif Y2_USE_ENDSTOP == _ZMAX_
#define Y2_MAX_PIN Z_MAX_PIN
#elif Y2_USE_ENDSTOP == _ZSTOP_
#define Y2_MAX_PIN Z_STOP_PIN
#elif Y2_USE_ENDSTOP == _XDIAG_
#define Y2_MAX_PIN X_DIAG_PIN
#elif Y2_USE_ENDSTOP == _YDIAG_
@@ -950,19 +968,25 @@
#define Y2_MIN_ENDSTOP_INVERTING false
#endif
#endif
#ifndef Y2_MIN_PIN
#if !defined(Y2_MIN_PIN) && !defined(Y2_STOP_PIN)
#if Y2_USE_ENDSTOP == _XMIN_
#define Y2_MIN_PIN X_MIN_PIN
#elif Y2_USE_ENDSTOP == _XMAX_
#define Y2_MIN_PIN X_MAX_PIN
#elif Y2_USE_ENDSTOP == _XSTOP_
#define Y2_MIN_PIN X_STOP_PIN
#elif Y2_USE_ENDSTOP == _YMIN_
#define Y2_MIN_PIN Y_MIN_PIN
#elif Y2_USE_ENDSTOP == _YMAX_
#define Y2_MIN_PIN Y_MAX_PIN
#elif Y2_USE_ENDSTOP == _YSTOP_
#define Y2_MIN_PIN Y_STOP_PIN
#elif Y2_USE_ENDSTOP == _ZMIN_
#define Y2_MIN_PIN Z_MIN_PIN
#elif Y2_USE_ENDSTOP == _ZMAX_
#define Y2_MIN_PIN Z_MAX_PIN
#elif Y2_USE_ENDSTOP == _ZSTOP_
#define Y2_MIN_PIN Z_STOP_PIN
#elif Y2_USE_ENDSTOP == _XDIAG_
#define Y2_MIN_PIN X_DIAG_PIN
#elif Y2_USE_ENDSTOP == _YDIAG_
@@ -1016,19 +1040,25 @@
#define Z2_MAX_ENDSTOP_INVERTING false
#endif
#endif
#ifndef Z2_MAX_PIN
#if !defined(Z2_MAX_PIN) && !defined(Z2_STOP_PIN)
#if Z2_USE_ENDSTOP == _XMIN_
#define Z2_MAX_PIN X_MIN_PIN
#elif Z2_USE_ENDSTOP == _XMAX_
#define Z2_MAX_PIN X_MAX_PIN
#elif Z2_USE_ENDSTOP == _XSTOP_
#define Z2_MAX_PIN X_STOP_PIN
#elif Z2_USE_ENDSTOP == _YMIN_
#define Z2_MAX_PIN Y_MIN_PIN
#elif Z2_USE_ENDSTOP == _YMAX_
#define Z2_MAX_PIN Y_MAX_PIN
#elif Z2_USE_ENDSTOP == _YSTOP_
#define Z2_MAX_PIN Y_STOP_PIN
#elif Z2_USE_ENDSTOP == _ZMIN_
#define Z2_MAX_PIN Z_MIN_PIN
#elif Z2_USE_ENDSTOP == _ZMAX_
#define Z2_MAX_PIN Z_MAX_PIN
#elif Z2_USE_ENDSTOP == _ZSTOP_
#define Z2_MAX_PIN Z_STOP_PIN
#elif Z2_USE_ENDSTOP == _XDIAG_
#define Z2_MAX_PIN X_DIAG_PIN
#elif Z2_USE_ENDSTOP == _YDIAG_
@@ -1079,14 +1109,20 @@
#define Z2_MIN_PIN X_MIN_PIN
#elif Z2_USE_ENDSTOP == _XMAX_
#define Z2_MIN_PIN X_MAX_PIN
#elif Z2_USE_ENDSTOP == _XSTOP_
#define Z2_MIN_PIN X_STOP_PIN
#elif Z2_USE_ENDSTOP == _YMIN_
#define Z2_MIN_PIN Y_MIN_PIN
#elif Z2_USE_ENDSTOP == _YMAX_
#define Z2_MIN_PIN Y_MAX_PIN
#elif Z2_USE_ENDSTOP == _YSTOP_
#define Z2_MIN_PIN Y_STOP_PIN
#elif Z2_USE_ENDSTOP == _ZMIN_
#define Z2_MIN_PIN Z_MIN_PIN
#elif Z2_USE_ENDSTOP == _ZMAX_
#define Z2_MIN_PIN Z_MAX_PIN
#elif Z2_USE_ENDSTOP == _ZSTOP_
#define Z2_MIN_PIN Z_STOP_PIN
#elif Z2_USE_ENDSTOP == _XDIAG_
#define Z2_MIN_PIN X_DIAG_PIN
#elif Z2_USE_ENDSTOP == _YDIAG_
@@ -1140,14 +1176,20 @@
#define Z3_MAX_PIN X_MIN_PIN
#elif Z3_USE_ENDSTOP == _XMAX_
#define Z3_MAX_PIN X_MAX_PIN
#elif Z3_USE_ENDSTOP == _XSTOP_
#define Z3_MAX_PIN X_STOP_PIN
#elif Z3_USE_ENDSTOP == _YMIN_
#define Z3_MAX_PIN Y_MIN_PIN
#elif Z3_USE_ENDSTOP == _YMAX_
#define Z3_MAX_PIN Y_MAX_PIN
#elif Z3_USE_ENDSTOP == _YSTOP_
#define Z3_MAX_PIN Y_STOP_PIN
#elif Z3_USE_ENDSTOP == _ZMIN_
#define Z3_MAX_PIN Z_MIN_PIN
#elif Z3_USE_ENDSTOP == _ZMAX_
#define Z3_MAX_PIN Z_MAX_PIN
#elif Z3_USE_ENDSTOP == _ZSTOP_
#define Z3_MAX_PIN Z_STOP_PIN
#elif Z3_USE_ENDSTOP == _XDIAG_
#define Z3_MAX_PIN X_DIAG_PIN
#elif Z3_USE_ENDSTOP == _YDIAG_
@@ -1198,14 +1240,20 @@
#define Z3_MIN_PIN X_MIN_PIN
#elif Z3_USE_ENDSTOP == _XMAX_
#define Z3_MIN_PIN X_MAX_PIN
#elif Z3_USE_ENDSTOP == _XSTOP_
#define Z3_MIN_PIN X_STOP_PIN
#elif Z3_USE_ENDSTOP == _YMIN_
#define Z3_MIN_PIN Y_MIN_PIN
#elif Z3_USE_ENDSTOP == _YMAX_
#define Z3_MIN_PIN Y_MAX_PIN
#elif Z3_USE_ENDSTOP == _YSTOP_
#define Z3_MIN_PIN Y_STOP_PIN
#elif Z3_USE_ENDSTOP == _ZMIN_
#define Z3_MIN_PIN Z_MIN_PIN
#elif Z3_USE_ENDSTOP == _ZMAX_
#define Z3_MIN_PIN Z_MAX_PIN
#elif Z3_USE_ENDSTOP == _ZSTOP_
#define Z3_MIN_PIN Z_STOP_PIN
#elif Z3_USE_ENDSTOP == _XDIAG_
#define Z3_MIN_PIN X_DIAG_PIN
#elif Z3_USE_ENDSTOP == _YDIAG_
@@ -1260,14 +1308,20 @@
#define Z4_MAX_PIN X_MIN_PIN
#elif Z4_USE_ENDSTOP == _XMAX_
#define Z4_MAX_PIN X_MAX_PIN
#elif Z4_USE_ENDSTOP == _XSTOP_
#define Z4_MAX_PIN X_STOP_PIN
#elif Z4_USE_ENDSTOP == _YMIN_
#define Z4_MAX_PIN Y_MIN_PIN
#elif Z4_USE_ENDSTOP == _YMAX_
#define Z4_MAX_PIN Y_MAX_PIN
#elif Z4_USE_ENDSTOP == _YSTOP_
#define Z4_MAX_PIN Y_STOP_PIN
#elif Z4_USE_ENDSTOP == _ZMIN_
#define Z4_MAX_PIN Z_MIN_PIN
#elif Z4_USE_ENDSTOP == _ZMAX_
#define Z4_MAX_PIN Z_MAX_PIN
#elif Z4_USE_ENDSTOP == _ZSTOP_
#define Z4_MAX_PIN Z_STOP_PIN
#elif Z4_USE_ENDSTOP == _XDIAG_
#define Z4_MAX_PIN X_DIAG_PIN
#elif Z4_USE_ENDSTOP == _YDIAG_
@@ -1318,14 +1372,20 @@
#define Z4_MIN_PIN X_MIN_PIN
#elif Z4_USE_ENDSTOP == _XMAX_
#define Z4_MIN_PIN X_MAX_PIN
#elif Z4_USE_ENDSTOP == _XSTOP_
#define Z4_MIN_PIN X_STOP_PIN
#elif Z4_USE_ENDSTOP == _YMIN_
#define Z4_MIN_PIN Y_MIN_PIN
#elif Z4_USE_ENDSTOP == _YMAX_
#define Z4_MIN_PIN Y_MAX_PIN
#elif Z4_USE_ENDSTOP == _YSTOP_
#define Z4_MIN_PIN Y_STOP_PIN
#elif Z4_USE_ENDSTOP == _ZMIN_
#define Z4_MIN_PIN Z_MIN_PIN
#elif Z4_USE_ENDSTOP == _ZMAX_
#define Z4_MIN_PIN Z_MAX_PIN
#elif Z4_USE_ENDSTOP == _ZSTOP_
#define Z4_MIN_PIN Z_STOP_PIN
#elif Z4_USE_ENDSTOP == _XDIAG_
#define Z4_MIN_PIN X_DIAG_PIN
#elif Z4_USE_ENDSTOP == _YDIAG_
@@ -1635,11 +1695,8 @@
#if PIN_EXISTS(E0_MS1)
#define HAS_E0_MS_PINS 1
#endif
#if PIN_EXISTS(SOL0)
#define HAS_SOLENOID_0 1
#endif
#if E_STEPPERS > 1
#if E_STEPPERS > 1 || ENABLED(E_DUAL_STEPPER_DRIVERS)
#if PIN_EXISTS(E1_ENABLE) || AXIS_IS_L64XX(E1) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E1))
#define HAS_E1_ENABLE 1
#endif
@@ -1652,9 +1709,6 @@
#if PIN_EXISTS(E1_MS1)
#define HAS_E1_MS_PINS 1
#endif
#if PIN_EXISTS(SOL1)
#define HAS_SOLENOID_1 1
#endif
#endif
#if E_STEPPERS > 2
@@ -1670,9 +1724,6 @@
#if PIN_EXISTS(E2_MS1)
#define HAS_E2_MS_PINS 1
#endif
#if PIN_EXISTS(SOL2)
#define HAS_SOLENOID_2 1
#endif
#endif
#if E_STEPPERS > 3
@@ -1688,9 +1739,6 @@
#if PIN_EXISTS(E3_MS1)
#define HAS_E3_MS_PINS 1
#endif
#if PIN_EXISTS(SOL3)
#define HAS_SOLENOID_3 1
#endif
#endif
#if E_STEPPERS > 4
@@ -1706,9 +1754,6 @@
#if PIN_EXISTS(E4_MS1)
#define HAS_E4_MS_PINS 1
#endif
#if PIN_EXISTS(SOL4)
#define HAS_SOLENOID_4 1
#endif
#endif
#if E_STEPPERS > 5
@@ -1724,9 +1769,6 @@
#if PIN_EXISTS(E5_MS1)
#define HAS_E5_MS_PINS 1
#endif
#if PIN_EXISTS(SOL5)
#define HAS_SOLENOID_5 1
#endif
#endif
#if E_STEPPERS > 6
@@ -1742,9 +1784,6 @@
#if PIN_EXISTS(E6_MS1)
#define HAS_E6_MS_PINS 1
#endif
#if PIN_EXISTS(SOL6)
#define HAS_SOLENOID_6 1
#endif
#endif
#if E_STEPPERS > 7
@@ -1760,9 +1799,6 @@
#if PIN_EXISTS(E7_MS1)
#define HAS_E7_MS_PINS 1
#endif
#if PIN_EXISTS(SOL7)
#define HAS_SOLENOID_7 1
#endif
#endif
#if !defined(DISABLE_INACTIVE_E) && ENABLED(DISABLE_E)
@@ -1772,6 +1808,41 @@
#undef DISABLE_INACTIVE_E
#endif // HAS_EXTRUDERS
/**
* Set solenoid flags if any features use solenoids
* - EXT_SOLENOID (M380, M381) to enable/disable the extruder solenoid
* - MANUAL_SOLENOID_CONTROL (M380, M381) to enable/disable solenoids by index
* - PARKING_EXTRUDER uses SOL0_PIN and SOL1_PIN
* - SOLENOID_PROBE uses SOL1_PIN
* - Z_PROBE_SLED uses SOL1_PIN, when defined (unless EXT_SOLENOID is enabled)
*/
#if ANY(EXT_SOLENOID, MANUAL_SOLENOID_CONTROL, PARKING_EXTRUDER, SOLENOID_PROBE, Z_PROBE_SLED)
#if PIN_EXISTS(SOL0) && (EITHER(MANUAL_SOLENOID_CONTROL, PARKING_EXTRUDER) || BOTH(EXT_SOLENOID, HAS_EXTRUDERS))
#define HAS_SOLENOID_0 1
#endif
#if PIN_EXISTS(SOL1) && (ANY(MANUAL_SOLENOID_CONTROL, PARKING_EXTRUDER, SOLENOID_PROBE, Z_PROBE_SLED) || TERN0(EXT_SOLENOID, E_STEPPERS > 1))
#define HAS_SOLENOID_1 1
#endif
#if PIN_EXISTS(SOL2) && (ENABLED(MANUAL_SOLENOID_CONTROL) || TERN0(EXT_SOLENOID, E_STEPPERS > 2))
#define HAS_SOLENOID_2 2
#endif
#if PIN_EXISTS(SOL3) && (ENABLED(MANUAL_SOLENOID_CONTROL) || TERN0(EXT_SOLENOID, E_STEPPERS > 3))
#define HAS_SOLENOID_3 3
#endif
#if PIN_EXISTS(SOL4) && (ENABLED(MANUAL_SOLENOID_CONTROL) || TERN0(EXT_SOLENOID, E_STEPPERS > 4))
#define HAS_SOLENOID_4 4
#endif
#if PIN_EXISTS(SOL5) && (ENABLED(MANUAL_SOLENOID_CONTROL) || TERN0(EXT_SOLENOID, E_STEPPERS > 5))
#define HAS_SOLENOID_5 5
#endif
#if PIN_EXISTS(SOL6) && (ENABLED(MANUAL_SOLENOID_CONTROL) || TERN0(EXT_SOLENOID, E_STEPPERS > 6))
#define HAS_SOLENOID_6 6
#endif
#if PIN_EXISTS(SOL7) && (ENABLED(MANUAL_SOLENOID_CONTROL) || TERN0(EXT_SOLENOID, E_STEPPERS > 7))
#define HAS_SOLENOID_7 7
#endif
#endif
//
// Trinamic Stepper Drivers
//
@@ -2865,10 +2936,14 @@
#elif defined(PREHEAT_1_LABEL)
#define PREHEAT_COUNT 1
#endif
#if PREHEAT_COUNT && ANY(HAS_HOTEND, HAS_HEATED_BED, HAS_FAN)
#define HAS_PREHEAT 1
#endif
#endif
#if !PREHEAT_COUNT
#if !HAS_PREHEAT
#undef PREHEAT_SHORTCUT_MENU_ITEM
#undef DGUS_PREHEAT_UI
#endif
/**
+76 -102
View File
@@ -595,6 +595,12 @@
#error "ARC_SUPPORT now requires MIN_ARC_SEGMENT_MM and MAX_ARC_SEGMENT_MM."
#elif defined(SPINDLE_LASER_PWM)
#error "SPINDLE_LASER_PWM (true) is now set with SPINDLE_LASER_USE_PWM (enabled)."
#elif ANY(IS_RAMPS_EEB, IS_RAMPS_EEF, IS_RAMPS_EFB, IS_RAMPS_EFF, IS_RAMPS_SF)
#error "The IS_RAMPS_* conditionals (for heater/fan/bed pins) are now called FET_ORDER_*."
#elif defined(PROBE_TEMP_COMPENSATION)
#error "PROBE_TEMP_COMPENSATION is now set using the PTC_PROBE, PTC_BED, PTC_HOTEND options."
#elif defined(BTC_PROBE_TEMP)
#error "BTC_PROBE_TEMP is now PTC_PROBE_TEMP."
#endif
#if MB(DUE3DOM_MINI) && PIN_EXISTS(TEMP_2) && DISABLED(TEMP_SENSOR_BOARD)
@@ -609,44 +615,60 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
/**
* Probe temp compensation requirements
*/
#if ENABLED(PROBE_TEMP_COMPENSATION)
#if defined(PTC_PARK_POS_X) || defined(PTC_PARK_POS_Y) || defined(PTC_PARK_POS_Z)
#error "PTC_PARK_POS_[XYZ] is now PTC_PARK_POS (array)."
#elif !defined(PTC_PARK_POS)
#error "PROBE_TEMP_COMPENSATION requires PTC_PARK_POS."
#elif defined(PTC_PROBE_POS_X) || defined(PTC_PROBE_POS_Y)
#error "PTC_PROBE_POS_[XY] is now PTC_PROBE_POS (array)."
#elif !defined(PTC_PROBE_POS)
#error "PROBE_TEMP_COMPENSATION requires PTC_PROBE_POS."
#if HAS_PTC
#if TEMP_SENSOR_PROBE && TEMP_SENSOR_BED
#if defined(PTC_PARK_POS_X) || defined(PTC_PARK_POS_Y) || defined(PTC_PARK_POS_Z)
#error "PTC_PARK_POS_[XYZ] is now PTC_PARK_POS (array)."
#elif !defined(PTC_PARK_POS)
#error "PTC_PARK_POS is required for Probe Temperature Compensation."
#elif defined(PTC_PROBE_POS_X) || defined(PTC_PROBE_POS_Y)
#error "PTC_PROBE_POS_[XY] is now PTC_PROBE_POS (array)."
#elif !defined(PTC_PROBE_POS)
#error "PTC_PROBE_POS is required for Probe Temperature Compensation."
#endif
#endif
#ifdef PTC_SAMPLE_START
constexpr auto _ptc_sample_start = PTC_SAMPLE_START;
#ifdef PTC_PROBE_START
constexpr auto _ptc_sample_start = PTC_PROBE_START;
constexpr decltype(_ptc_sample_start) _test_ptc_sample_start = 12.3f;
static_assert(_test_ptc_sample_start != 12.3f, "PTC_SAMPLE_START must be a whole number.");
static_assert(_test_ptc_sample_start != 12.3f, "PTC_PROBE_START must be a whole number.");
#endif
#ifdef PTC_SAMPLE_RES
constexpr auto _ptc_sample_res = PTC_SAMPLE_RES;
#ifdef PTC_PROBE_RES
constexpr auto _ptc_sample_res = PTC_PROBE_RES;
constexpr decltype(_ptc_sample_res) _test_ptc_sample_res = 12.3f;
static_assert(_test_ptc_sample_res != 12.3f, "PTC_SAMPLE_RES must be a whole number.");
static_assert(_test_ptc_sample_res != 12.3f, "PTC_PROBE_RES must be a whole number.");
#endif
#ifdef BTC_SAMPLE_START
constexpr auto _btc_sample_start = BTC_SAMPLE_START;
#ifdef PTC_BED_START
constexpr auto _btc_sample_start = PTC_BED_START;
constexpr decltype(_btc_sample_start) _test_btc_sample_start = 12.3f;
static_assert(_test_btc_sample_start != 12.3f, "BTC_SAMPLE_START must be a whole number.");
static_assert(_test_btc_sample_start != 12.3f, "PTC_BED_START must be a whole number.");
#endif
#ifdef BTC_SAMPLE_RES
constexpr auto _btc_sample_res = BTC_SAMPLE_RES;
#ifdef PTC_BED_RES
constexpr auto _btc_sample_res = PTC_BED_RES;
constexpr decltype(_btc_sample_res) _test_btc_sample_res = 12.3f;
static_assert(_test_btc_sample_res != 12.3f, "BTC_SAMPLE_RES must be a whole number.");
static_assert(_test_btc_sample_res != 12.3f, "PTC_BED_RES must be a whole number.");
#endif
#ifdef BTC_PROBE_TEMP
constexpr auto _btc_probe_temp = BTC_PROBE_TEMP;
#ifdef PTC_PROBE_TEMP
constexpr auto _btc_probe_temp = PTC_PROBE_TEMP;
constexpr decltype(_btc_probe_temp) _test_btc_probe_temp = 12.3f;
static_assert(_test_btc_probe_temp != 12.3f, "BTC_PROBE_TEMP must be a whole number.");
static_assert(_test_btc_probe_temp != 12.3f, "PTC_PROBE_TEMP must be a whole number.");
#endif
#endif
#if ENABLED(PTC_HOTEND)
#if EXTRUDERS != 1
#error "PTC_HOTEND only works with a single extruder."
#endif
#ifdef PTC_HOTEND_START
constexpr auto _etc_sample_start = PTC_HOTEND_START;
constexpr decltype(_etc_sample_start) _test_etc_sample_start = 12.3f;
static_assert(_test_etc_sample_start != 12.3f, "PTC_HOTEND_START must be a whole number.");
#endif
#ifdef PTC_HOTEND_RES
constexpr auto _etc_sample_res = PTC_HOTEND_RES;
constexpr decltype(_etc_sample_res) _test_etc_sample_res = 12.3f;
static_assert(_test_etc_sample_res != 12.3f, "PTC_HOTEND_RES must be a whole number.");
#endif
#endif
#endif // HAS_PTC
/**
* Marlin release, version and default string
@@ -1224,8 +1246,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "LIN_ADVANCE and S_CURVE_ACCELERATION may not play well together! Enable EXPERIMENTAL_SCURVE to continue."
#elif ENABLED(DIRECT_STEPPING)
#error "DIRECT_STEPPING is incompatible with LIN_ADVANCE. Enable in external planner if possible."
#elif !HAS_JUNCTION_DEVIATION && defined(DEFAULT_EJERK)
//static_assert(DEFAULT_EJERK >= 10, "It is strongly recommended to set DEFAULT_EJERK >= 10 when using LIN_ADVANCE.");
#elif NONE(HAS_JUNCTION_DEVIATION, ALLOW_LOW_EJERK) && defined(DEFAULT_EJERK)
static_assert(DEFAULT_EJERK >= 10, "It is strongly recommended to set DEFAULT_EJERK >= 10 when using LIN_ADVANCE. Enable ALLOW_LOW_EJERK to bypass this alert (e.g., for direct drive).");
#endif
#endif
@@ -1239,7 +1261,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
/**
* (Magnetic) Parking Extruder requirements
*/
#if ANY(PARKING_EXTRUDER, MAGNETIC_PARKING_EXTRUDER)
#if EITHER(PARKING_EXTRUDER, MAGNETIC_PARKING_EXTRUDER)
#if ENABLED(EXT_SOLENOID)
#error "(MAGNETIC_)PARKING_EXTRUDER and EXT_SOLENOID are incompatible. (Pins are used twice.)"
#elif EXTRUDERS != 2
@@ -1658,10 +1680,6 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "Z_PROBE_LOW_POINT must be less than or equal to 0."
#endif
#if HOMING_Z_WITH_PROBE && IS_CARTESIAN && DISABLED(Z_SAFE_HOMING)
#error "Z_SAFE_HOMING is recommended when homing with a probe. Enable it or comment out this line to continue."
#endif
#if ENABLED(PROBE_ACTIVATION_SWITCH)
#ifndef PROBE_ACTIVATION_SWITCH_STATE
#error "PROBE_ACTIVATION_SWITCH_STATE is required for PROBE_ACTIVATION_SWITCH."
@@ -2193,68 +2211,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#elif !PIN_EXISTS(TEMP_7) && !TEMP_SENSOR_7_IS_DUMMY
#error "TEMP_7_PIN not defined for this board."
#endif
#elif TEMP_SENSOR_7 != 0
#error "TEMP_SENSOR_7 shouldn't be set with only 7 HOTENDS."
#endif
#elif TEMP_SENSOR_6 != 0
#error "TEMP_SENSOR_6 shouldn't be set with only 6 HOTENDS."
#elif TEMP_SENSOR_7 != 0
#error "TEMP_SENSOR_7 shouldn't be set with only 6 HOTENDS."
#endif
#elif TEMP_SENSOR_5 != 0
#error "TEMP_SENSOR_5 shouldn't be set with only 5 HOTENDS."
#elif TEMP_SENSOR_6 != 0
#error "TEMP_SENSOR_6 shouldn't be set with only 5 HOTENDS."
#elif TEMP_SENSOR_7 != 0
#error "TEMP_SENSOR_7 shouldn't be set with only 5 HOTENDS."
#endif
#elif TEMP_SENSOR_4 != 0
#error "TEMP_SENSOR_4 shouldn't be set with only 4 HOTENDS."
#elif TEMP_SENSOR_5 != 0
#error "TEMP_SENSOR_5 shouldn't be set with only 4 HOTENDS."
#elif TEMP_SENSOR_6 != 0
#error "TEMP_SENSOR_6 shouldn't be set with only 4 HOTENDS."
#elif TEMP_SENSOR_7 != 0
#error "TEMP_SENSOR_7 shouldn't be set with only 4 HOTENDS."
#endif
#elif TEMP_SENSOR_3 != 0
#error "TEMP_SENSOR_3 shouldn't be set with only 3 HOTENDS."
#elif TEMP_SENSOR_4 != 0
#error "TEMP_SENSOR_4 shouldn't be set with only 3 HOTENDS."
#elif TEMP_SENSOR_5 != 0
#error "TEMP_SENSOR_5 shouldn't be set with only 3 HOTENDS."
#elif TEMP_SENSOR_6 != 0
#error "TEMP_SENSOR_6 shouldn't be set with only 3 HOTENDS."
#elif TEMP_SENSOR_7 != 0
#error "TEMP_SENSOR_7 shouldn't be set with only 3 HOTENDS."
#endif
#elif TEMP_SENSOR_2 != 0
#error "TEMP_SENSOR_2 shouldn't be set with only 2 HOTENDS."
#elif TEMP_SENSOR_3 != 0
#error "TEMP_SENSOR_3 shouldn't be set with only 2 HOTENDS."
#elif TEMP_SENSOR_4 != 0
#error "TEMP_SENSOR_4 shouldn't be set with only 2 HOTENDS."
#elif TEMP_SENSOR_5 != 0
#error "TEMP_SENSOR_5 shouldn't be set with only 2 HOTENDS."
#elif TEMP_SENSOR_6 != 0
#error "TEMP_SENSOR_6 shouldn't be set with only 2 HOTENDS."
#elif TEMP_SENSOR_7 != 0
#error "TEMP_SENSOR_7 shouldn't be set with only 2 HOTENDS."
#endif
#elif TEMP_SENSOR_1 != 0
#error "TEMP_SENSOR_1 shouldn't be set with only 1 HOTEND."
#elif TEMP_SENSOR_2 != 0
#error "TEMP_SENSOR_2 shouldn't be set with only 1 HOTEND."
#elif TEMP_SENSOR_3 != 0
#error "TEMP_SENSOR_3 shouldn't be set with only 1 HOTEND."
#elif TEMP_SENSOR_4 != 0
#error "TEMP_SENSOR_4 shouldn't be set with only 1 HOTEND."
#elif TEMP_SENSOR_5 != 0
#error "TEMP_SENSOR_5 shouldn't be set with only 1 HOTEND."
#elif TEMP_SENSOR_6 != 0
#error "TEMP_SENSOR_6 shouldn't be set with only 1 HOTEND."
#elif TEMP_SENSOR_7 != 0
#error "TEMP_SENSOR_7 shouldn't be set with only 1 HOTEND."
#endif // HOTENDS > 7
#endif // HOTENDS > 6
#endif // HOTENDS > 5
#endif // HOTENDS > 4
#endif // HOTENDS > 3
#endif // HOTENDS > 2
#endif // HAS_MULTI_HOTEND
/**
@@ -2527,6 +2489,11 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "An encoder button is required or SOFT_RESET_ON_KILL will reset the printer without notice!"
#endif
// Reset reason for AVR
#if ENABLED(OPTIBOOT_RESET_REASON) && !defined(__AVR__)
#error "OPTIBOOT_RESET_REASON only applies to AVR."
#endif
/**
* I2C bus
*/
@@ -2673,7 +2640,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
+ COUNT_ENABLED(FYSETC_MINI_12864_X_X, FYSETC_MINI_12864_1_2, FYSETC_MINI_12864_2_0, FYSETC_MINI_12864_2_1, FYSETC_GENERIC_12864_1_1) \
+ COUNT_ENABLED(LCD_SAINSMART_I2C_1602, LCD_SAINSMART_I2C_2004) \
+ COUNT_ENABLED(MKS_12864OLED, MKS_12864OLED_SSD1306) \
+ COUNT_ENABLED(MKS_TS35_V2_0, MKS_ROBIN_TFT24, MKS_ROBIN_TFT28, MKS_ROBIN_TFT32, MKS_ROBIN_TFT35, MKS_ROBIN_TFT43, MKS_ROBIN_TFT_V1_1R, ANET_ET4_TFT28, ANET_ET5_TFT35) \
+ COUNT_ENABLED(MKS_TS35_V2_0, MKS_ROBIN_TFT24, MKS_ROBIN_TFT28, MKS_ROBIN_TFT32, MKS_ROBIN_TFT35, MKS_ROBIN_TFT43, MKS_ROBIN_TFT_V1_1R, ANET_ET4_TFT28, ANET_ET5_TFT35, BIQU_BX_TFT70, BTT_TFT35_SPI_V1_0) \
+ COUNT_ENABLED(TFTGLCD_PANEL_SPI, TFTGLCD_PANEL_I2C) \
+ COUNT_ENABLED(VIKI2, miniVIKI) \
+ ENABLED(WYH_L12864) \
@@ -2723,12 +2690,11 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#undef IS_U8GLIB_SSD1306
#undef IS_EXTUI
#undef IS_LEGACY_TFT
#if ANY(TFT_GENERIC, MKS_TS35_V2_0, MKS_ROBIN_TFT24, MKS_ROBIN_TFT28, MKS_ROBIN_TFT32, MKS_ROBIN_TFT35, MKS_ROBIN_TFT43, MKS_ROBIN_TFT_V1_1R, TFT_TRONXY_X5SA, ANYCUBIC_TFT35, ANYCUBIC_TFT35, LONGER_LK_TFT28, ANET_ET4_TFT28, ANET_ET5_TFT35, BIQU_BX_TFT70)
#if ANY(TFT_GENERIC, MKS_TS35_V2_0, MKS_ROBIN_TFT24, MKS_ROBIN_TFT28, MKS_ROBIN_TFT32, MKS_ROBIN_TFT35, MKS_ROBIN_TFT43, MKS_ROBIN_TFT_V1_1R, TFT_TRONXY_X5SA, ANYCUBIC_TFT35, ANYCUBIC_TFT35, LONGER_LK_TFT28, ANET_ET4_TFT28, ANET_ET5_TFT35, BIQU_BX_TFT70, BTT_TFT35_SPI_V1_0)
#if NONE(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI)
#error "TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI is required for your TFT. Please enable one."
#elif 1 < ENABLED(TFT_COLOR_UI) + ENABLED(TFT_CLASSIC_UI) + ENABLED(TFT_LVGL_UI)
#elif MANY(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI)
#error "Please select only one of TFT_COLOR_UI, TFT_CLASSIC_UI, or TFT_LVGL_UI."
#endif
#elif ANY(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI)
@@ -2751,8 +2717,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "Please select only one of TFT_RES_320x240, TFT_RES_480x272, TFT_RES_480x320, or TFT_RES_1024x600."
#endif
#if HAS_TFT_LVGL_UI && DISABLED(TFT_RES_480x320)
#error "(FMSC|SPI)TFT_LVGL_UI requires TFT_RES_480x320."
#if ENABLED(TFT_LVGL_UI)
#if DISABLED(TFT_RES_480x320)
#error "TFT_LVGL_UI requires TFT_RES_480x320."
#elif DISABLED(SDSUPPORT)
#error "TFT_LVGL_UI requires SDSUPPORT."
#endif
#endif
#if defined(GRAPHICAL_TFT_UPSCALE) && !WITHIN(GRAPHICAL_TFT_UPSCALE, 2, 4)
@@ -2763,6 +2733,10 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "Please select only one of CHIRON_TFT_STANDARD or CHIRON_TFT_NEW."
#endif
#if EITHER(MKS_TS35_V2_0, BTT_TFT35_SPI_V1_0) && SD_CONNECTION_IS(LCD)
#error "SDCARD_CONNECTION cannot be set to LCD for the enabled TFT. No available SD card reader."
#endif
/**
* Ender 3 V2 controller has some limitations
*/
@@ -3289,7 +3263,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#if HAS_MOTOR_CURRENT_I2C
#if BOTH(DIGIPOT_MCP4018, DIGIPOT_MCP4451)
#error "Enable only one of DIGIPOT_MCP4018 or DIGIPOT_MCP4451."
#elif !MB(MKS_SBASE, AZTEEG_X5_GT, AZTEEG_X5_MINI, AZTEEG_X5_MINI_WIFI) \
#elif !MB(MKS_SBASE, AZTEEG_X5_GT, AZTEEG_X5_MINI, AZTEEG_X5_MINI_WIFI) \
&& (!defined(DIGIPOTS_I2C_SDA_X) || !defined(DIGIPOTS_I2C_SDA_Y) || !defined(DIGIPOTS_I2C_SDA_Z) || !defined(DIGIPOTS_I2C_SDA_E0) || !defined(DIGIPOTS_I2C_SDA_E1))
#error "DIGIPOT_MCP4018/4451 requires DIGIPOTS_I2C_SDA_* pins to be defined."
#endif
+2 -2
View File
@@ -42,7 +42,7 @@
* version was tagged.
*/
#ifndef STRING_DISTRIBUTION_DATE
#define STRING_DISTRIBUTION_DATE "2021-10-13"
#define STRING_DISTRIBUTION_DATE "2021-11-12"
#endif
/**
@@ -52,7 +52,7 @@
* to alert users to major changes.
*/
#define MARLIN_HEX_VERSION 02000902
#define MARLIN_HEX_VERSION 02000903
#ifndef REQUIRED_CONFIGURATION_H_VERSION
#define REQUIRED_CONFIGURATION_H_VERSION MARLIN_HEX_VERSION
#endif
+85
View File
@@ -35,6 +35,26 @@
#warning "WARNING! Disable MARLIN_DEV_MODE for the final build!"
#endif
// Safety Features
#if DISABLED(USE_WATCHDOG)
#warning "Safety Alert! Enable USE_WATCHDOG for the final build!"
#endif
#if HAS_HOTEND && DISABLED(THERMAL_PROTECTION_HOTENDS)
#warning "Safety Alert! Enable THERMAL_PROTECTION_HOTENDS for the final build!"
#endif
#if HAS_HEATED_BED && DISABLED(THERMAL_PROTECTION_BED)
#warning "Safety Alert! Enable THERMAL_PROTECTION_BED for the final build!"
#endif
#if HAS_HEATED_CHAMBER && DISABLED(THERMAL_PROTECTION_CHAMBER)
#warning "Safety Alert! Enable THERMAL_PROTECTION_CHAMBER for the final build!"
#endif
#if HAS_COOLER && DISABLED(THERMAL_PROTECTION_COOLER)
#warning "Safety Alert! Enable THERMAL_PROTECTION_COOLER for the final build!"
#endif
#if ANY_THERMISTOR_IS(998) || ANY_THERMISTOR_IS(999)
#warning "Warning! Don't use dummy thermistors (998/999) for final build!"
#endif
#if NONE(HAS_RESUME_CONTINUE, HOST_PROMPT_SUPPORT)
#warning "Your Configuration provides no method to acquire user feedback!"
#endif
@@ -59,14 +79,20 @@
#warning "Auto-assigned X2_DIAG_PIN to X_MIN_PIN."
#elif X2_USE_ENDSTOP == _XMAX_
#warning "Auto-assigned X2_DIAG_PIN to X_MAX_PIN."
#elif X2_USE_ENDSTOP == _XSTOP_
#warning "Auto-assigned X2_DIAG_PIN to X_STOP_PIN."
#elif X2_USE_ENDSTOP == _YMIN_
#warning "Auto-assigned X2_DIAG_PIN to Y_MIN_PIN."
#elif X2_USE_ENDSTOP == _YMAX_
#warning "Auto-assigned X2_DIAG_PIN to Y_MAX_PIN."
#elif X2_USE_ENDSTOP == _YSTOP_
#warning "Auto-assigned X2_DIAG_PIN to Y_STOP_PIN."
#elif X2_USE_ENDSTOP == _ZMIN_
#warning "Auto-assigned X2_DIAG_PIN to Z_MIN_PIN."
#elif X2_USE_ENDSTOP == _ZMAX_
#warning "Auto-assigned X2_DIAG_PIN to Z_MAX_PIN."
#elif X2_USE_ENDSTOP == _ZSTOP_
#warning "Auto-assigned X2_DIAG_PIN to Z_STOP_PIN."
#elif X2_USE_ENDSTOP == _XDIAG_
#warning "Auto-assigned X2_DIAG_PIN to X_DIAG_PIN."
#elif X2_USE_ENDSTOP == _YDIAG_
@@ -111,14 +137,20 @@
#warning "Auto-assigned Y2_DIAG_PIN to X_MIN_PIN."
#elif Y2_USE_ENDSTOP == _XMAX_
#warning "Auto-assigned Y2_DIAG_PIN to X_MAX_PIN."
#elif Y2_USE_ENDSTOP == _XSTOP_
#warning "Auto-assigned Y2_DIAG_PIN to X_STOP_PIN."
#elif Y2_USE_ENDSTOP == _YMIN_
#warning "Auto-assigned Y2_DIAG_PIN to Y_MIN_PIN."
#elif Y2_USE_ENDSTOP == _YMAX_
#warning "Auto-assigned Y2_DIAG_PIN to Y_MAX_PIN."
#elif Y2_USE_ENDSTOP == _YSTOP_
#warning "Auto-assigned Y2_DIAG_PIN to Y_STOP_PIN."
#elif Y2_USE_ENDSTOP == _ZMIN_
#warning "Auto-assigned Y2_DIAG_PIN to Z_MIN_PIN."
#elif Y2_USE_ENDSTOP == _ZMAX_
#warning "Auto-assigned Y2_DIAG_PIN to Z_MAX_PIN."
#elif Y2_USE_ENDSTOP == _ZSTOP_
#warning "Auto-assigned Y2_DIAG_PIN to Z_STOP_PIN."
#elif Y2_USE_ENDSTOP == _XDIAG_
#warning "Auto-assigned Y2_DIAG_PIN to X_DIAG_PIN."
#elif Y2_USE_ENDSTOP == _YDIAG_
@@ -163,14 +195,20 @@
#warning "Auto-assigned Z2_DIAG_PIN to X_MIN_PIN."
#elif Z2_USE_ENDSTOP == _XMAX_
#warning "Auto-assigned Z2_DIAG_PIN to X_MAX_PIN."
#elif Z2_USE_ENDSTOP == _XSTOP_
#warning "Auto-assigned Z2_DIAG_PIN to X_STOP_PIN."
#elif Z2_USE_ENDSTOP == _YMIN_
#warning "Auto-assigned Z2_DIAG_PIN to Y_MIN_PIN."
#elif Z2_USE_ENDSTOP == _YMAX_
#warning "Auto-assigned Z2_DIAG_PIN to Y_MAX_PIN."
#elif Z2_USE_ENDSTOP == _YSTOP_
#warning "Auto-assigned Z2_DIAG_PIN to Y_STOP_PIN."
#elif Z2_USE_ENDSTOP == _ZMIN_
#warning "Auto-assigned Z2_DIAG_PIN to Z_MIN_PIN."
#elif Z2_USE_ENDSTOP == _ZMAX_
#warning "Auto-assigned Z2_DIAG_PIN to Z_MAX_PIN."
#elif Z2_USE_ENDSTOP == _ZSTOP_
#warning "Auto-assigned Z2_DIAG_PIN to Z_STOP_PIN."
#elif Z2_USE_ENDSTOP == _XDIAG_
#warning "Auto-assigned Z2_DIAG_PIN to X_DIAG_PIN."
#elif Z2_USE_ENDSTOP == _YDIAG_
@@ -215,14 +253,20 @@
#warning "Auto-assigned Z3_DIAG_PIN to X_MIN_PIN."
#elif Z3_USE_ENDSTOP == _XMAX_
#warning "Auto-assigned Z3_DIAG_PIN to X_MAX_PIN."
#elif Z3_USE_ENDSTOP == _XSTOP_
#warning "Auto-assigned Z3_DIAG_PIN to X_STOP_PIN."
#elif Z3_USE_ENDSTOP == _YMIN_
#warning "Auto-assigned Z3_DIAG_PIN to Y_MIN_PIN."
#elif Z3_USE_ENDSTOP == _YMAX_
#warning "Auto-assigned Z3_DIAG_PIN to Y_MAX_PIN."
#elif Z3_USE_ENDSTOP == _YSTOP_
#warning "Auto-assigned Z3_DIAG_PIN to Y_STOP_PIN."
#elif Z3_USE_ENDSTOP == _ZMIN_
#warning "Auto-assigned Z3_DIAG_PIN to Z_MIN_PIN."
#elif Z3_USE_ENDSTOP == _ZMAX_
#warning "Auto-assigned Z3_DIAG_PIN to Z_MAX_PIN."
#elif Z3_USE_ENDSTOP == _ZSTOP_
#warning "Auto-assigned Z3_DIAG_PIN to Z_STOP_PIN."
#elif Z3_USE_ENDSTOP == _XDIAG_
#warning "Auto-assigned Z3_DIAG_PIN to X_DIAG_PIN."
#elif Z3_USE_ENDSTOP == _YDIAG_
@@ -267,14 +311,20 @@
#warning "Auto-assigned Z4_DIAG_PIN to X_MIN_PIN."
#elif Z4_USE_ENDSTOP == _XMAX_
#warning "Auto-assigned Z4_DIAG_PIN to X_MAX_PIN."
#elif Z4_USE_ENDSTOP == _XSTOP_
#warning "Auto-assigned Z4_DIAG_PIN to X_STOP_PIN."
#elif Z4_USE_ENDSTOP == _YMIN_
#warning "Auto-assigned Z4_DIAG_PIN to Y_MIN_PIN."
#elif Z4_USE_ENDSTOP == _YMAX_
#warning "Auto-assigned Z4_DIAG_PIN to Y_MAX_PIN."
#elif Z4_USE_ENDSTOP == _YSTOP_
#warning "Auto-assigned Z4_DIAG_PIN to Y_STOP_PIN."
#elif Z4_USE_ENDSTOP == _ZMIN_
#warning "Auto-assigned Z4_DIAG_PIN to Z_MIN_PIN."
#elif Z4_USE_ENDSTOP == _ZMAX_
#warning "Auto-assigned Z4_DIAG_PIN to Z_MAX_PIN."
#elif Z4_USE_ENDSTOP == _ZSTOP_
#warning "Auto-assigned Z4_DIAG_PIN to Z_STOP_PIN."
#elif Z4_USE_ENDSTOP == _XDIAG_
#warning "Auto-assigned Z4_DIAG_PIN to X_DIAG_PIN."
#elif Z4_USE_ENDSTOP == _YDIAG_
@@ -319,14 +369,20 @@
#warning "Auto-assigned I_DIAG_PIN to X_MIN_PIN."
#elif I_USE_ENDSTOP == _XMAX_
#warning "Auto-assigned I_DIAG_PIN to X_MAX_PIN."
#elif I_USE_ENDSTOP == _XSTOP_
#warning "Auto-assigned I_DIAG_PIN to X_STOP_PIN."
#elif I_USE_ENDSTOP == _YMIN_
#warning "Auto-assigned I_DIAG_PIN to Y_MIN_PIN."
#elif I_USE_ENDSTOP == _YMAX_
#warning "Auto-assigned I_DIAG_PIN to Y_MAX_PIN."
#elif I_USE_ENDSTOP == _YSTOP_
#warning "Auto-assigned I_DIAG_PIN to Y_STOP_PIN."
#elif I_USE_ENDSTOP == _ZMIN_
#warning "Auto-assigned I_DIAG_PIN to Z_MIN_PIN."
#elif I_USE_ENDSTOP == _ZMAX_
#warning "Auto-assigned I_DIAG_PIN to Z_MAX_PIN."
#elif I_USE_ENDSTOP == _ZSTOP_
#warning "Auto-assigned I_DIAG_PIN to Z_STOP_PIN."
#elif I_USE_ENDSTOP == _XDIAG_
#warning "Auto-assigned I_DIAG_PIN to X_DIAG_PIN."
#elif I_USE_ENDSTOP == _YDIAG_
@@ -371,14 +427,20 @@
#warning "Auto-assigned J_DIAG_PIN to X_MIN_PIN."
#elif J_USE_ENDSTOP == _XMAX_
#warning "Auto-assigned J_DIAG_PIN to X_MAX_PIN."
#elif J_USE_ENDSTOP == _XSTOP_
#warning "Auto-assigned J_DIAG_PIN to X_STOP_PIN."
#elif J_USE_ENDSTOP == _YMIN_
#warning "Auto-assigned J_DIAG_PIN to Y_MIN_PIN."
#elif J_USE_ENDSTOP == _YMAX_
#warning "Auto-assigned J_DIAG_PIN to Y_MAX_PIN."
#elif J_USE_ENDSTOP == _YSTOP_
#warning "Auto-assigned J_DIAG_PIN to Y_STOP_PIN."
#elif J_USE_ENDSTOP == _ZMIN_
#warning "Auto-assigned J_DIAG_PIN to Z_MIN_PIN."
#elif J_USE_ENDSTOP == _ZMAX_
#warning "Auto-assigned J_DIAG_PIN to Z_MAX_PIN."
#elif J_USE_ENDSTOP == _ZSTOP_
#warning "Auto-assigned J_DIAG_PIN to Z_STOP_PIN."
#elif J_USE_ENDSTOP == _XDIAG_
#warning "Auto-assigned J_DIAG_PIN to X_DIAG_PIN."
#elif J_USE_ENDSTOP == _YDIAG_
@@ -423,14 +485,20 @@
#warning "Auto-assigned K_DIAG_PIN to X_MIN_PIN."
#elif K_USE_ENDSTOP == _XMAX_
#warning "Auto-assigned K_DIAG_PIN to X_MAX_PIN."
#elif K_USE_ENDSTOP == _XSTOP_
#warning "Auto-assigned K_DIAG_PIN to X_STOP_PIN."
#elif K_USE_ENDSTOP == _YMIN_
#warning "Auto-assigned K_DIAG_PIN to Y_MIN_PIN."
#elif K_USE_ENDSTOP == _YMAX_
#warning "Auto-assigned K_DIAG_PIN to Y_MAX_PIN."
#elif K_USE_ENDSTOP == _YSTOP_
#warning "Auto-assigned K_DIAG_PIN to Y_STOP_PIN."
#elif K_USE_ENDSTOP == _ZMIN_
#warning "Auto-assigned K_DIAG_PIN to Z_MIN_PIN."
#elif K_USE_ENDSTOP == _ZMAX_
#warning "Auto-assigned K_DIAG_PIN to Z_MAX_PIN."
#elif K_USE_ENDSTOP == _ZSTOP_
#warning "Auto-assigned K_DIAG_PIN to Z_STOP_PIN."
#elif K_USE_ENDSTOP == _XDIAG_
#warning "Auto-assigned K_DIAG_PIN to X_DIAG_PIN."
#elif K_USE_ENDSTOP == _YDIAG_
@@ -456,7 +524,24 @@
#endif
#endif
#if IS_LEGACY_TFT
#warning "Don't forget to update your TFT settings in Configuration.h."
#endif
// Ender 3 Pro (but, apparently all Creality 4.2.2 boards)
#if ENABLED(EMIT_CREALITY_422_WARNING) || MB(CREALITY_V4)
#warning "Creality 4.2.2 boards may have A4988 or TMC2208_STANDALONE drivers. Check your board and make sure to select the correct DRIVER_TYPE!"
#endif
#if HOMING_Z_WITH_PROBE && IS_CARTESIAN && DISABLED(Z_SAFE_HOMING)
#error "Z_SAFE_HOMING is recommended when homing with a probe. Enable Z_SAFE_HOMING or comment out this line to continue."
#endif
//
// Warn users of potential endstop/DIAG pin conflicts to prevent homing issues when not using sensorless homing
//
#if !USE_SENSORLESS && ENABLED(USES_DIAG_JUMPERS)
#warning "Motherboard DIAG jumpers must be removed when SENSORLESS_HOMING is disabled."
#elif !USE_SENSORLESS && ENABLED(USES_DIAG_PINS)
#warning "Driver DIAG pins must be physically removed unless SENSORLESS_HOMING is enabled. (See https://bit.ly/2ZPRlt0)"
#endif
+3 -1
View File
@@ -339,12 +339,14 @@ void MarlinUI::draw_kill_screen() {
void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
#if HAS_LCD_BRIGHTNESS
void MarlinUI::_set_brightness() {
#if PIN_EXISTS(TFT_BACKLIGHT)
if (PWM_PIN(TFT_BACKLIGHT_PIN))
analogWrite(pin_t(TFT_BACKLIGHT_PIN), brightness);
analogWrite(pin_t(TFT_BACKLIGHT_PIN), backlight ? brightness : 0);
#endif
}
#endif
#if HAS_LCD_MENU
+2 -4
View File
@@ -862,17 +862,15 @@ void MarlinUI::draw_status_screen() {
mix_label = PSTR("Mx");
}
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-overflow"
#endif
sprintf_P(mixer_messages, PSTR(S_FMT " %d;%d%% "), mix_label, int(mixer.mix[0]), int(mixer.mix[1]));
lcd_put_u8str(X_LABEL_POS, XYZ_BASELINE, mixer_messages);
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#pragma GCC diagnostic pop
#else
@@ -78,13 +78,13 @@ TFT_IO tftio;
#include "../marlinui.h"
#endif
#if HAS_TOUCH_BUTTONS
#include "../touch/touch_buttons.h"
#if HAS_TOUCH_SLEEP
#define HAS_TOUCH_BUTTONS_SLEEP 1
#endif
#if HAS_TOUCH_BUTTONS && HAS_TOUCH_SLEEP
#define HAS_TOUCH_BUTTONS_SLEEP 1
#endif
#include "../touch/touch_buttons.h"
#include "../scaled_tft.h"
#define X_HI (UPSCALE(TFT_PIXEL_OFFSET_X, WIDTH) - 1)
#define Y_HI (UPSCALE(TFT_PIXEL_OFFSET_Y, HEIGHT) - 1)
@@ -325,6 +325,7 @@ static bool preinit = true;
static uint8_t page;
#if HAS_TOUCH_BUTTONS
static bool redrawTouchButtons = true;
static void drawTouchButtons(u8g_t *u8g, u8g_dev_t *dev) {
if (!redrawTouchButtons) return;
@@ -343,6 +344,7 @@ static uint8_t page;
setWindow(u8g, dev, BUTTONC_X_LO, BUTTON_Y_LO, BUTTONC_X_HI, BUTTON_Y_HI);
drawImage(buttonC, u8g, dev, BUTTON_DRAW_WIDTH, BUTTON_DRAW_HEIGHT, TFT_BTOKMENU_COLOR);
}
#endif // HAS_TOUCH_BUTTONS
static void u8g_upscale_clear_lcd(u8g_t *u8g, u8g_dev_t *dev, uint16_t *buffer) {
@@ -395,7 +397,7 @@ uint8_t u8g_dev_tft_320x240_upscale_from_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, u
if (!sleepCleared) {
sleepCleared = true;
u8g_upscale_clear_lcd(u8g, dev, buffer);
IF_ENABLED(HAS_TOUCH_BUTTONS, redrawTouchButtons = true);
TERN_(HAS_TOUCH_BUTTONS, redrawTouchButtons = true);
}
break;
}
+199 -177
View File
@@ -165,14 +165,15 @@ typedef struct {
} select_t;
select_t select_page{0}, select_file{0}, select_print{0}, select_prepare{0}
, select_control{0}, select_axis{0}, select_temp{0}, select_motion{0}, select_tune{0}
, select_advset{0}, select_PLA{0}, select_ABS{0}
, select_speed{0}
, select_acc{0}
, select_jerk{0}
, select_step{0}
, select_item{0}
;
, select_control{0}, select_axis{0}, select_temp{0}, select_motion{0}, select_tune{0}
, select_advset{0}, select_speed{0}, select_acc{0}, select_jerk{0}, select_step{0}, select_item{0};
#if HAS_PREHEAT
select_t select_PLA{0};
#if PREHEAT_COUNT > 1
select_t select_ABS{0};
#endif
#endif
uint8_t index_file = MROWS,
index_prepare = MROWS,
@@ -497,8 +498,8 @@ inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) {
#define PREPARE_CASE_DISA 2
#define PREPARE_CASE_HOME 3
#define PREPARE_CASE_ZOFF (PREPARE_CASE_HOME + ENABLED(HAS_ZOFFSET_ITEM))
#define PREPARE_CASE_PLA (PREPARE_CASE_ZOFF + ENABLED(HAS_HOTEND))
#define PREPARE_CASE_ABS (PREPARE_CASE_PLA + ENABLED(HAS_HOTEND))
#define PREPARE_CASE_PLA (PREPARE_CASE_ZOFF + ENABLED(HAS_PREHEAT))
#define PREPARE_CASE_ABS (PREPARE_CASE_PLA + (TERN0(HAS_PREHEAT, PREHEAT_COUNT > 1)))
#define PREPARE_CASE_COOL (PREPARE_CASE_ABS + EITHER(HAS_HOTEND, HAS_HEATED_BED))
#define PREPARE_CASE_LANG (PREPARE_CASE_COOL + 1)
#define PREPARE_CASE_TOTAL PREPARE_CASE_LANG
@@ -522,8 +523,8 @@ inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) {
#define TEMP_CASE_TEMP (0 + ENABLED(HAS_HOTEND))
#define TEMP_CASE_BED (TEMP_CASE_TEMP + ENABLED(HAS_HEATED_BED))
#define TEMP_CASE_FAN (TEMP_CASE_BED + ENABLED(HAS_FAN))
#define TEMP_CASE_PLA (TEMP_CASE_FAN + ENABLED(HAS_HOTEND))
#define TEMP_CASE_ABS (TEMP_CASE_PLA + ENABLED(HAS_HOTEND))
#define TEMP_CASE_PLA (TEMP_CASE_FAN + ENABLED(HAS_PREHEAT))
#define TEMP_CASE_ABS (TEMP_CASE_PLA + (TERN0(HAS_PREHEAT, PREHEAT_COUNT > 1)))
#define TEMP_CASE_TOTAL TEMP_CASE_ABS
#define PREHEAT_CASE_TEMP (0 + ENABLED(HAS_HOTEND))
@@ -615,7 +616,7 @@ void Draw_Edit_Float3(const uint8_t row, const uint16_t value, const bool active
}
void Draw_Edit_Signed_Float2(const uint8_t row, const float value, const bool active=false) {
DWIN_Draw_Signed_Float(font8x16, active ? Select_Color : Color_Bg_Black, 2, UNITFDIGITS, 220 + 8 - UNITFDIGITS * 8, EBASE(row), value);
DWIN_Draw_Signed_Float(font8x16, active ? Select_Color : Color_Bg_Black, 2, UNITFDIGITS + 1, 220 + 8 - UNITFDIGITS * 8, EBASE(row), value);
}
void Draw_Edit_Signed_Float3(const uint8_t row, const float value, const bool active=false) {
@@ -700,7 +701,7 @@ void Item_Prepare_Home(const uint8_t row) {
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
void Item_Prepare_PLA(const uint8_t row) {
if (HMI_IsChinese())
Item_AreaCopy(100, 89, 151, 101, row);
@@ -715,22 +716,22 @@ void Item_Prepare_Home(const uint8_t row) {
Draw_Menu_Line(row, ICON_PLAPreheat);
}
void Item_Prepare_ABS(const uint8_t row) {
if (HMI_IsChinese())
Item_AreaCopy(180, 89, 233, 100, row);
else {
#ifdef USE_STRING_TITLES
DWIN_Draw_Label(row, F("Preheat " PREHEAT_2_LABEL));
#else
Item_AreaCopy(108, 76, 155, 87, row); // "Preheat"
say_abs_en(52, row); // "ABS"
#endif
#if PREHEAT_COUNT > 1
void Item_Prepare_ABS(const uint8_t row) {
if (HMI_IsChinese())
Item_AreaCopy(180, 89, 233, 100, row);
else {
#ifdef USE_STRING_TITLES
DWIN_Draw_Label(row, F("Preheat " PREHEAT_2_LABEL));
#else
Item_AreaCopy(108, 76, 155, 87, row); // "Preheat"
say_abs_en(52, row); // "ABS"
#endif
}
Draw_Menu_Line(row, ICON_ABSPreheat);
}
Draw_Menu_Line(row, ICON_ABSPreheat);
}
#endif
#endif
#if HAS_PREHEAT
void Item_Prepare_Cool(const uint8_t row) {
if (HMI_IsChinese())
Item_AreaCopy(1, 104, 56, 117, row);
@@ -785,11 +786,13 @@ void Draw_Prepare_Menu() {
#if HAS_ZOFFSET_ITEM
if (PVISI(PREPARE_CASE_ZOFF)) Item_Prepare_Offset(PSCROL(PREPARE_CASE_ZOFF)); // Edit Z-Offset / Babystep / Set Home Offset
#endif
#if HAS_HOTEND
if (PVISI(PREPARE_CASE_PLA)) Item_Prepare_PLA(PSCROL(PREPARE_CASE_PLA)); // Preheat PLA
if (PVISI(PREPARE_CASE_ABS)) Item_Prepare_ABS(PSCROL(PREPARE_CASE_ABS)); // Preheat ABS
#endif
#if HAS_PREHEAT
if (PVISI(PREPARE_CASE_PLA)) Item_Prepare_PLA(PSCROL(PREPARE_CASE_PLA)); // Preheat PLA
#if PREHEAT_COUNT > 1
if (PVISI(PREPARE_CASE_ABS)) Item_Prepare_ABS(PSCROL(PREPARE_CASE_ABS)); // Preheat ABS
#endif
#endif
#if HAS_HOTEND || HAS_HEATED_BED
if (PVISI(PREPARE_CASE_COOL)) Item_Prepare_Cool(PSCROL(PREPARE_CASE_COOL)); // Cooldown
#endif
if (PVISI(PREPARE_CASE_LANG)) Item_Prepare_Lang(PSCROL(PREPARE_CASE_LANG)); // Language CN/EN
@@ -1425,25 +1428,34 @@ void HMI_Move_Z() {
uint8_t temp_line;
switch (HMI_ValueStruct.show_mode) {
case -1: temp_line = TEMP_CASE_TEMP; break;
case -2: temp_line = PREHEAT_CASE_TEMP; break;
case -3: temp_line = PREHEAT_CASE_TEMP; break;
#if HAS_PREHEAT
case -2: temp_line = PREHEAT_CASE_TEMP; break;
#if PREHEAT_COUNT > 1
case -3: temp_line = PREHEAT_CASE_TEMP; break;
#endif
#endif
default: temp_line = TUNE_CASE_TEMP + MROWS - index_tune;
}
if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.E_Temp)) {
EncoderRate.enabled = false;
if (HMI_ValueStruct.show_mode == -2) {
checkkey = PLAPreheat;
ui.material_preset[0].hotend_temp = HMI_ValueStruct.E_Temp;
Draw_Edit_Integer3(temp_line, ui.material_preset[0].hotend_temp);
return;
}
else if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].hotend_temp = HMI_ValueStruct.E_Temp;
Draw_Edit_Integer3(temp_line, ui.material_preset[1].hotend_temp);
return;
}
else if (HMI_ValueStruct.show_mode == -1) // Temperature
#if HAS_PREHEAT
if (HMI_ValueStruct.show_mode == -2) {
checkkey = PLAPreheat;
ui.material_preset[0].hotend_temp = HMI_ValueStruct.E_Temp;
Draw_Edit_Integer3(temp_line, ui.material_preset[0].hotend_temp);
return;
}
#if PREHEAT_COUNT > 1
if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].hotend_temp = HMI_ValueStruct.E_Temp;
Draw_Edit_Integer3(temp_line, ui.material_preset[1].hotend_temp);
return;
}
#endif
#endif
if (HMI_ValueStruct.show_mode == -1) // Temperature
checkkey = TemperatureID;
else
checkkey = Tune;
@@ -1467,28 +1479,33 @@ void HMI_Move_Z() {
uint8_t bed_line;
switch (HMI_ValueStruct.show_mode) {
case -1: bed_line = TEMP_CASE_BED; break;
case -2: bed_line = PREHEAT_CASE_BED; break;
case -3: bed_line = PREHEAT_CASE_BED; break;
#if HAS_PREHEAT
case -2: bed_line = PREHEAT_CASE_BED; break;
#if PREHEAT_COUNT > 1
case -3: bed_line = PREHEAT_CASE_BED; break;
#endif
#endif
default: bed_line = TUNE_CASE_BED + MROWS - index_tune;
}
if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Bed_Temp)) {
EncoderRate.enabled = false;
if (HMI_ValueStruct.show_mode == -2) {
checkkey = PLAPreheat;
ui.material_preset[0].bed_temp = HMI_ValueStruct.Bed_Temp;
Draw_Edit_Integer3(bed_line, ui.material_preset[0].bed_temp);
return;
}
else if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].bed_temp = HMI_ValueStruct.Bed_Temp;
Draw_Edit_Integer3(bed_line, ui.material_preset[1].bed_temp);
return;
}
else if (HMI_ValueStruct.show_mode == -1)
checkkey = TemperatureID;
else
checkkey = Tune;
#if HAS_PREHEAT
if (HMI_ValueStruct.show_mode == -2) {
checkkey = PLAPreheat;
ui.material_preset[0].bed_temp = HMI_ValueStruct.Bed_Temp;
Draw_Edit_Integer3(bed_line, ui.material_preset[0].bed_temp);
return;
}
#if PREHEAT_COUNT > 1
if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].bed_temp = HMI_ValueStruct.Bed_Temp;
Draw_Edit_Integer3(bed_line, ui.material_preset[1].bed_temp);
return;
}
#endif
#endif
checkkey = HMI_ValueStruct.show_mode == -1 ? TemperatureID : Tune;
Draw_Edit_Integer3(bed_line, HMI_ValueStruct.Bed_Temp);
thermalManager.setTargetBed(HMI_ValueStruct.Bed_Temp);
return;
@@ -1522,16 +1539,15 @@ void HMI_Move_Z() {
Draw_Edit_Integer3(fan_line, ui.material_preset[0].fan_speed);
return;
}
else if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].fan_speed = HMI_ValueStruct.Fan_speed;
Draw_Edit_Integer3(fan_line, ui.material_preset[1].fan_speed);
return;
}
else if (HMI_ValueStruct.show_mode == -1)
checkkey = TemperatureID;
else
checkkey = Tune;
#if PREHEAT_COUNT > 1
if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].fan_speed = HMI_ValueStruct.Fan_speed;
Draw_Edit_Integer3(fan_line, ui.material_preset[1].fan_speed);
return;
}
#endif
checkkey = HMI_ValueStruct.show_mode == -1 ? TemperatureID : Tune;
Draw_Edit_Integer3(fan_line, HMI_ValueStruct.Fan_speed);
thermalManager.set_fan_speed(0, HMI_ValueStruct.Fan_speed);
return;
@@ -1659,7 +1675,7 @@ void _update_axis_value(const AxisEnum axis, const uint16_t x, const uint16_t y,
else if (blink && draw_empty)
DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, x, y, F(" "));
else
DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, x, y, p * 10);
DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, x, y, p);
}
}
@@ -1769,11 +1785,11 @@ void update_variable() {
if (BABY_Z_VAR != _offset) {
_offset = BABY_Z_VAR;
if (BABY_Z_VAR < 0) {
Draw_Stat_Float(207, 417, -_offset * 100);
Draw_Stat_Float(207, 417, -_offset);
DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, 205, 419, F("-"));
}
else {
Draw_Stat_Float(207, 417, _offset * 100);
Draw_Stat_Float(207, 417, _offset);
DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, 205, 419, F(" "));
}
}
@@ -2363,7 +2379,7 @@ void HMI_PauseOrStop() {
card.abortFilePrintSoon(); // Let the main loop handle SD abort
dwin_abort_flag = true; // Reset feedrate, return to Home
#ifdef ACTION_ON_CANCEL
host_action_cancel();
hostui.cancel();
#endif
Popup_Window_Home(true);
if (HMI_flag.home_flag) planner.synchronize(); // Wait for planner moves to finish!
@@ -2656,10 +2672,10 @@ void HMI_Prepare() {
// Draw "More" icon for sub-menus
if (index_prepare < 7) Draw_More_Icon(MROWS - index_prepare + 1);
#if HAS_HOTEND
#if PREHEAT_COUNT > 1
if (index_prepare == PREPARE_CASE_ABS) Item_Prepare_ABS(MROWS);
#endif
#if HAS_PREHEAT
#if HAS_HOTEND || HAS_HEATED_BED
if (index_prepare == PREPARE_CASE_COOL) Item_Prepare_Cool(MROWS);
#endif
if (index_prepare == PREPARE_CASE_LANG) Item_Prepare_Lang(MROWS);
@@ -2719,6 +2735,7 @@ void HMI_Prepare() {
queue.inject_P(G28_STR); // G28 will set home_flag
Popup_Window_Home();
break;
#if HAS_ZOFFSET_ITEM
case PREPARE_CASE_ZOFF:
#if EITHER(HAS_BED_PROBE, BABYSTEPPING)
@@ -2734,28 +2751,23 @@ void HMI_Prepare() {
#endif
break;
#endif
#if HAS_PREHEAT
case PREPARE_CASE_PLA:
TERN_(HAS_HOTEND, thermalManager.setTargetHotend(ui.material_preset[0].hotend_temp, 0));
TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(ui.material_preset[0].bed_temp));
TERN_(HAS_FAN, thermalManager.set_fan_speed(0, ui.material_preset[0].fan_speed));
break;
case PREPARE_CASE_ABS:
TERN_(HAS_HOTEND, thermalManager.setTargetHotend(ui.material_preset[1].hotend_temp, 0));
TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(ui.material_preset[1].bed_temp));
TERN_(HAS_FAN, thermalManager.set_fan_speed(0, ui.material_preset[1].fan_speed));
break;
case PREPARE_CASE_COOL:
TERN_(HAS_FAN, thermalManager.zero_fan_speeds());
#if HAS_HOTEND || HAS_HEATED_BED
thermalManager.disable_all_heaters();
#endif
break;
case PREPARE_CASE_PLA: ui.preheat_all(0); break;
#if PREHEAT_COUNT > 1
case PREPARE_CASE_ABS: ui.preheat_all(1); break;
#endif
#endif
#if HAS_HOTEND || HAS_HEATED_BED
case PREPARE_CASE_COOL: thermalManager.cooldown(); break;
#endif
case PREPARE_CASE_LANG:
HMI_ToggleLanguage();
Draw_Prepare_Menu();
break;
default: break;
}
}
@@ -2776,9 +2788,11 @@ void Draw_Temperature_Menu() {
#if HAS_FAN
Item_AreaCopy(115, 134, 170, 146, TEMP_CASE_FAN);
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
Item_AreaCopy(100, 89, 178, 101, TEMP_CASE_PLA);
Item_AreaCopy(180, 89, 260, 100, TEMP_CASE_ABS);
#if PREHEAT_COUNT > 1
Item_AreaCopy(180, 89, 260, 100, TEMP_CASE_ABS);
#endif
#endif
}
else {
@@ -2797,30 +2811,33 @@ void Draw_Temperature_Menu() {
#if HAS_FAN
DWIN_Draw_Label(TEMP_CASE_FAN, GET_TEXT_F(MSG_FAN_SPEED));
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
DWIN_Draw_Label(TEMP_CASE_PLA, F(PREHEAT_1_LABEL " Preheat Settings"));
DWIN_Draw_Label(TEMP_CASE_ABS, F(PREHEAT_2_LABEL " Preheat Settings"));
#if PREHEAT_COUNT > 1
DWIN_Draw_Label(TEMP_CASE_ABS, F(PREHEAT_2_LABEL " Preheat Settings"));
#endif
#endif
#else
#if HAS_HOTEND
Item_AreaCopy(197, 104, 238, 114, TEMP_CASE_TEMP); // "Nozzle"
Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_TEMP, 44); // "Temperature"
Item_AreaCopy(197, 104, 238, 114, TEMP_CASE_TEMP); // "Nozzle"
Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_TEMP, 44); // "Temperature"
#endif
#if HAS_HEATED_BED
Item_AreaCopy(240, 104, 264, 114, TEMP_CASE_BED); // "Bed"
Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_BED, 27); // "Temperature"
Item_AreaCopy(240, 104, 264, 114, TEMP_CASE_BED); // "Bed"
Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_BED, 27); // "Temperature"
#endif
#if HAS_FAN
Item_AreaCopy( 1, 119, 61, 132, TEMP_CASE_FAN); // "Fan speed"
Item_AreaCopy( 1, 119, 61, 132, TEMP_CASE_FAN); // "Fan speed"
#endif
#if HAS_HOTEND
Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_PLA); // "Preheat"
say_pla_en(52, TEMP_CASE_PLA); // "PLA"
Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_PLA, 79); // "Settings"
Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_ABS); // "Preheat"
say_abs_en(52, TEMP_CASE_ABS); // "ABS"
Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_ABS, 81); // "Settings"
#if HAS_PREHEAT
Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_PLA); // "Preheat"
say_pla_en(52, TEMP_CASE_PLA); // "PLA"
Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_PLA, 79); // "Settings"
#if PREHEAT_COUNT > 1
Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_ABS); // "Preheat"
say_abs_en(52, TEMP_CASE_ABS); // "ABS"
Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_ABS, 81); // "Settings"
#endif
#endif
#endif
}
@@ -2843,12 +2860,12 @@ void Draw_Temperature_Menu() {
_TMENU_ICON(TEMP_CASE_FAN);
Draw_Edit_Integer3(i, thermalManager.fan_speed[0]);
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
// PLA/ABS items have submenus
_TMENU_ICON(TEMP_CASE_PLA);
Draw_More_Icon(i);
_TMENU_ICON(TEMP_CASE_ABS);
Draw_More_Icon(i);
_TMENU_ICON(TEMP_CASE_PLA); Draw_More_Icon(i);
#if PREHEAT_COUNT > 1
_TMENU_ICON(TEMP_CASE_ABS); Draw_More_Icon(i);
#endif
#endif
}
@@ -3072,7 +3089,8 @@ void HMI_Temperature() {
EncoderRate.enabled = true;
break;
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
case TEMP_CASE_PLA: {
checkkey = PLAPreheat;
select_PLA.reset();
@@ -3149,7 +3167,9 @@ void HMI_Temperature() {
Draw_Menu_Line(++i, ICON_WriteEEPROM);
#endif
} break;
#endif // HAS_PREHEAT
#if PREHEAT_COUNT > 1
case TEMP_CASE_ABS: { // ABS preheat setting
checkkey = ABSPreheat;
select_ABS.reset();
@@ -3231,7 +3251,7 @@ void HMI_Temperature() {
} break;
#endif // HAS_HOTEND
#endif // PREHEAT_COUNT > 1
}
}
DWIN_UpdateLCD();
@@ -3574,14 +3594,12 @@ void HMI_AdvSet() {
#if HAS_HOTEND
case ADVSET_CASE_HEPID:
thermalManager.setTargetHotend(ui.material_preset[0].hotend_temp, 0);
thermalManager.PID_autotune(ui.material_preset[0].hotend_temp, H_E0, 10, true);
break;
#endif
#if HAS_HEATED_BED
case ADVSET_CASE_BEDPID:
thermalManager.setTargetBed(ui.material_preset[0].bed_temp);
thermalManager.PID_autotune(ui.material_preset[0].bed_temp, H_BED, 10, true);
break;
#endif
@@ -3876,63 +3894,65 @@ void HMI_Tune() {
DWIN_UpdateLCD();
}
// ABS Preheat
void HMI_ABSPreheatSetting() {
EncoderState encoder_diffState = get_encoder_state();
if (encoder_diffState == ENCODER_DIFF_NO) return;
#if PREHEAT_COUNT > 1
// ABS Preheat
void HMI_ABSPreheatSetting() {
EncoderState encoder_diffState = get_encoder_state();
if (encoder_diffState == ENCODER_DIFF_NO) return;
// Avoid flicker by updating only the previous menu
if (encoder_diffState == ENCODER_DIFF_CW) {
if (select_ABS.inc(1 + PREHEAT_CASE_TOTAL)) Move_Highlight(1, select_ABS.now);
}
else if (encoder_diffState == ENCODER_DIFF_CCW) {
if (select_ABS.dec()) Move_Highlight(-1, select_ABS.now);
}
else if (encoder_diffState == ENCODER_DIFF_ENTER) {
switch (select_ABS.now) {
case CASE_BACK:
checkkey = TemperatureID;
select_temp.now = TEMP_CASE_ABS;
HMI_ValueStruct.show_mode = -1;
Draw_Temperature_Menu();
break;
#if HAS_HOTEND
case PREHEAT_CASE_TEMP:
checkkey = ETemp;
HMI_ValueStruct.E_Temp = ui.material_preset[1].hotend_temp;
Draw_Edit_Integer3(PREHEAT_CASE_TEMP, ui.material_preset[1].hotend_temp, true);
EncoderRate.enabled = true;
break;
#endif
#if HAS_HEATED_BED
case PREHEAT_CASE_BED:
checkkey = BedTemp;
HMI_ValueStruct.Bed_Temp = ui.material_preset[1].bed_temp;
Draw_Edit_Integer3(PREHEAT_CASE_BED, ui.material_preset[1].bed_temp, true);
EncoderRate.enabled = true;
break;
#endif
#if HAS_FAN
case PREHEAT_CASE_FAN:
checkkey = FanSpeed;
HMI_ValueStruct.Fan_speed = ui.material_preset[1].fan_speed;
Draw_Edit_Integer3(PREHEAT_CASE_FAN, ui.material_preset[1].fan_speed, true);
EncoderRate.enabled = true;
break;
#endif
#if ENABLED(EEPROM_SETTINGS)
case PREHEAT_CASE_SAVE: {
const bool success = settings.save();
HMI_AudioFeedback(success);
} break;
#endif
default: break;
// Avoid flicker by updating only the previous menu
if (encoder_diffState == ENCODER_DIFF_CW) {
if (select_ABS.inc(1 + PREHEAT_CASE_TOTAL)) Move_Highlight(1, select_ABS.now);
}
else if (encoder_diffState == ENCODER_DIFF_CCW) {
if (select_ABS.dec()) Move_Highlight(-1, select_ABS.now);
}
else if (encoder_diffState == ENCODER_DIFF_ENTER) {
switch (select_ABS.now) {
case CASE_BACK:
checkkey = TemperatureID;
select_temp.now = TEMP_CASE_ABS;
HMI_ValueStruct.show_mode = -1;
Draw_Temperature_Menu();
break;
#if HAS_HOTEND
case PREHEAT_CASE_TEMP:
checkkey = ETemp;
HMI_ValueStruct.E_Temp = ui.material_preset[1].hotend_temp;
Draw_Edit_Integer3(PREHEAT_CASE_TEMP, ui.material_preset[1].hotend_temp, true);
EncoderRate.enabled = true;
break;
#endif
#if HAS_HEATED_BED
case PREHEAT_CASE_BED:
checkkey = BedTemp;
HMI_ValueStruct.Bed_Temp = ui.material_preset[1].bed_temp;
Draw_Edit_Integer3(PREHEAT_CASE_BED, ui.material_preset[1].bed_temp, true);
EncoderRate.enabled = true;
break;
#endif
#if HAS_FAN
case PREHEAT_CASE_FAN:
checkkey = FanSpeed;
HMI_ValueStruct.Fan_speed = ui.material_preset[1].fan_speed;
Draw_Edit_Integer3(PREHEAT_CASE_FAN, ui.material_preset[1].fan_speed, true);
EncoderRate.enabled = true;
break;
#endif
#if ENABLED(EEPROM_SETTINGS)
case PREHEAT_CASE_SAVE: {
const bool success = settings.save();
HMI_AudioFeedback(success);
} break;
#endif
default: break;
}
}
DWIN_UpdateLCD();
}
DWIN_UpdateLCD();
}
#endif // PREHEAT_COUNT > 1
#endif
#endif // HAS_PREHEAT
// Max Speed
void HMI_MaxSpeed() {
@@ -4236,7 +4256,9 @@ void DWIN_HandleScreen() {
case Tune: HMI_Tune(); break;
#if HAS_PREHEAT
case PLAPreheat: HMI_PLAPreheatSetting(); break;
case ABSPreheat: HMI_ABSPreheatSetting(); break;
#if PREHEAT_COUNT > 1
case ABSPreheat: HMI_ABSPreheatSetting(); break;
#endif
#endif
case MaxSpeed: HMI_MaxSpeed(); break;
case MaxAcceleration: HMI_MaxAcceleration(); break;
+3 -8
View File
@@ -31,13 +31,6 @@
#include "../../../inc/MarlinConfigPre.h"
#if ANY(HAS_HOTEND, HAS_HEATED_BED, HAS_FAN) && PREHEAT_COUNT
#define HAS_PREHEAT 1
#if PREHEAT_COUNT < 2
#error "Creality DWIN requires two material preheat presets."
#endif
#endif
enum processID : uint8_t {
// Process ID
MainMenu,
@@ -53,7 +46,9 @@ enum processID : uint8_t {
Tune,
#if HAS_PREHEAT
PLAPreheat,
ABSPreheat,
#if PREHEAT_COUNT > 1
ABSPreheat,
#endif
#endif
MaxSpeed,
MaxSpeed_value,
+163 -100
View File
@@ -23,8 +23,8 @@
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/10
* Version: 3.7.1
* Date: 2021/11/09
*/
#include "../../../inc/MarlinConfigPre.h"
@@ -142,7 +142,7 @@ HMI_data_t HMI_data;
millis_t dwin_heat_time = 0;
uint8_t checkkey = MainMenu, last_checkkey = MainMenu;
uint8_t checkkey = 255, last_checkkey = MainMenu;
enum SelectItem : uint8_t {
PAGE_PRINT = 0,
@@ -170,6 +170,7 @@ select_t select_page{0}, select_file{0}, select_print{0};
uint8_t index_file = MROWS;
bool dwin_abort_flag = false; // Flag to reset feedrate, return to Home
bool hash_changed = true; // Flag to know if message status was changed
constexpr float default_max_feedrate[] = DEFAULT_MAX_FEEDRATE;
constexpr float default_max_acceleration[] = DEFAULT_MAX_ACCELERATION;
@@ -386,15 +387,15 @@ void ICON_Stop() {
ICON_Button(select_print.now == PRINT_STOP, ICON_Stop_0, ico, txt);
}
void Draw_Menu_Cursor(const uint8_t line) {
void Draw_Menu_Cursor(const int8_t line) {
DWIN_Draw_Rectangle(1, HMI_data.Cursor_color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20);
}
void Erase_Menu_Cursor(const uint8_t line) {
void Erase_Menu_Cursor(const int8_t line) {
DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20);
}
void Move_Highlight(const int16_t from, const uint16_t newline) {
void Move_Highlight(const int8_t from, const int8_t newline) {
Erase_Menu_Cursor(newline - from);
Draw_Menu_Cursor(newline);
}
@@ -577,6 +578,7 @@ void Popup_window_PauseOrStop() {
DWINUI::Draw_Icon(ICON_Cancel_E, 146, 280);
}
Draw_Select_Highlight(true);
DWIN_UpdateLCD();
}
#if HAS_HOTEND || HAS_HEATED_BED
@@ -607,9 +609,88 @@ void Popup_window_PauseOrStop() {
}
}
}
#endif
// Draw status line
void DWIN_DrawStatusLine(const uint16_t color, const uint16_t bgcolor, const char *text, const bool center = true) {
DWIN_Draw_Rectangle(1, bgcolor, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 20);
if (text) {
if (center) DWINUI::Draw_CenteredString(color, STATUS_Y + 2, text);
else DWINUI::Draw_String(color, 0, STATUS_Y + 2, text);
}
DWIN_UpdateLCD();
}
void DWIN_DrawStatusLine(const char *text, const bool center = true) {
DWIN_DrawStatusLine(HMI_data.StatusTxt_Color, HMI_data.StatusBg_Color, text, center);
}
// Clear & reset status line
void DWIN_ResetStatusLine() {
ui.status_message[0] = 0;
DWIN_CheckStatusMessage();
}
// Djb2 hash algorithm
void DWIN_CheckStatusMessage() {
static uint32_t old_hash = 0;
char * str = &ui.status_message[0];
uint32_t hash = 5381;
char c;
while ((c = *str++)) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
hash_changed = hash != old_hash;
old_hash = hash;
};
void DWIN_DrawStatusMessage() {
const uint8_t max_status_chars = DWIN_WIDTH / DWINUI::fontWidth(DWINUI::font);
#if ENABLED(STATUS_MESSAGE_SCROLLING)
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(ui.status_message);
// If the string fits the status line do not scroll it
if (slen <= max_status_chars) {
if (hash_changed) {
DWIN_DrawStatusLine(HMI_data.StatusTxt_Color, HMI_data.StatusBg_Color, ui.status_message);
hash_changed = false;
}
}
else {
// String is larger than the available line space
// Get a pointer to the next valid UTF8 character
// and the string remaining length
uint8_t rlen;
const char *stat = MarlinUI::status_and_len(rlen);
DWIN_Draw_Rectangle(1, HMI_data.StatusBg_Color, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 20);
DWINUI::MoveTo(0, STATUS_Y + 2);
DWINUI::Draw_String(stat, max_status_chars);
// If the string doesn't completely fill the line...
if (rlen < max_status_chars) {
DWINUI::Draw_Char('.'); // Always at 1+ spaces left, draw a dot
uint8_t chars = max_status_chars - rlen; // Amount of space left in characters
if (--chars) { // Draw a second dot if there's space
DWINUI::Draw_Char('.');
if (--chars)
DWINUI::Draw_String(ui.status_message, chars); // Print a second copy of the message
}
}
MarlinUI::advance_status_scroll();
}
#else
if (hash_changed) {
ui.status_message[max_status_chars] = 0;
DWIN_DrawStatusLine(HMI_data.StatusTxt_Color, HMI_data.StatusBg_Color, ui.status_message);
hash_changed = false;
}
#endif
}
void Draw_Print_Labels() {
if (HMI_IsChinese()) {
Title.FrameCopy(30, 1, 42, 14); // "Printing"
@@ -671,6 +752,7 @@ void Draw_PrintProcess() {
}
void Goto_PrintProcess() {
if (checkkey == PrintProcess) return;
checkkey = PrintProcess;
Draw_PrintProcess();
}
@@ -712,8 +794,9 @@ void Draw_Main_Menu() {
}
void Goto_Main_Menu() {
if (checkkey == MainMenu) return;
checkkey = MainMenu;
DWIN_StatusChanged();
ui.reset_status(true);
Draw_Main_Menu();
}
@@ -1077,6 +1160,7 @@ void Draw_Status_Area(const bool with_update) {
void HMI_StartFrame(const bool with_update) {
Goto_Main_Menu();
DWIN_DrawStatusLine(nullptr);
Draw_Status_Area(with_update);
}
@@ -1105,7 +1189,7 @@ void Draw_Info_Menu() {
LOOP_L_N(i, 3) {
DWINUI::Draw_Icon(ICON_PrintSize + i, 26, 99 + i * 73);
DWIN_Draw_Line(HMI_data.SplitLine_Color, 16, MBASE(2) + i * 73, 256, 156 + i * 73);
DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MBASE(2) + i * 73, 240);
}
DWIN_UpdateLCD();
@@ -1157,10 +1241,10 @@ void HMI_MainMenu() {
case PAGE_INFO_LEVELING:
#if HAS_ONESTEP_LEVELING
queue.inject(F("G28XYO\nG28Z\nG29")); // TODO: 'G29' should be homing when needed. Does it make sense for every LCD to do this differently?
queue.inject(F("G28Z\nG29")); // Force to get the current Z home position
#else
checkkey = Info;
Draw_Info_Menu();
last_checkkey = MainMenu;
Goto_InfoMenu();
#endif
break;
}
@@ -1245,7 +1329,7 @@ void HMI_SelectFile() {
}
}
else if (encoder_diffState == ENCODER_DIFF_ENTER) {
if (select_file.now == 0) {
if (select_file.now == 0) { // Back
select_page.set(PAGE_PRINT);
Goto_Main_Menu();
}
@@ -1391,7 +1475,7 @@ void HMI_PauseOrStop() {
card.abortFilePrintSoon(); // Let the main loop handle SD abort
dwin_abort_flag = true; // Reset feedrate, return to Home
#ifdef ACTION_ON_CANCEL
host_action_cancel();
hostui.cancel();
#endif
DWIN_Draw_Popup(ICON_BLTouch, F("Stopping...") , F("Please wait until done."));
}
@@ -1441,7 +1525,6 @@ void Draw_Main_Area() {
void HMI_ReturnScreen() {
checkkey = last_checkkey;
Draw_Main_Area();
DWIN_UpdateLCD();
return;
}
@@ -1474,7 +1557,7 @@ void DWIN_Update() {
}
void EachMomentUpdate() {
static millis_t next_var_update_ms = 0, next_rts_update_ms = 0;
static millis_t next_var_update_ms = 0, next_rts_update_ms = 0, next_status_update_ms = 0;
const millis_t ms = millis();
if (ELAPSED(ms, next_var_update_ms)) {
@@ -1482,6 +1565,11 @@ void EachMomentUpdate() {
update_variable();
}
if (ELAPSED(ms, next_status_update_ms)) {
next_status_update_ms = ms + 500;
DWIN_DrawStatusMessage();
}
if (PENDING(ms, next_rts_update_ms)) return;
next_rts_update_ms = ms + DWIN_SCROLL_UPDATE_INTERVAL;
@@ -1651,6 +1739,7 @@ void HMI_SaveProcessID(const uint8_t id) {
void DWIN_StartHoming() {
HMI_flag.home_flag = true;
HMI_SaveProcessID(Homing);
Title.ShowCaption(F("Axis Homing"));
DWIN_Draw_Popup(ICON_BLTouch, F("Axis Homing"), F("Please wait until done."));
}
@@ -1666,6 +1755,7 @@ void DWIN_CompletedHoming() {
void DWIN_MeshLevelingStart() {
#if HAS_ONESTEP_LEVELING
HMI_SaveProcessID(Leveling);
Title.ShowCaption(F("Bed Leveling"));
DWIN_Draw_Popup(ICON_AutoLeveling, GET_TEXT_F(MSG_BED_LEVELING), F("Please wait until done."));
#elif ENABLED(MESH_BED_LEVELING)
Draw_ManualMesh_Menu();
@@ -1743,7 +1833,7 @@ void Draw_Title(TitleClass* title) {
void Draw_Menu(MenuClass* menu) {
DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color);
DWIN_Draw_Rectangle(1, DWINUI::backcolor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1);
ui.set_status("");
DWIN_ResetStatusLine();
}
// Startup routines
@@ -1756,23 +1846,6 @@ void DWIN_Startup() {
HMI_SetLanguage();
}
void DWIN_DrawStatusLine(const uint16_t color, const uint16_t bgcolor, const char * const text/*=nullptr*/) {
DWIN_Draw_Rectangle(1, bgcolor, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 20);
if (text) DWINUI::Draw_CenteredString(color, STATUS_Y + 2, text);
DWIN_UpdateLCD();
}
// Update Status line
void DWIN_StatusChanged(const char * const cstr/*=nullptr*/) {
DWIN_DrawStatusLine(HMI_data.StatusTxt_Color, HMI_data.StatusBg_Color, cstr);
}
void DWIN_StatusChanged(FSTR_P const fstr) {
char str[strlen_P(FTOP(fstr)) + 1];
strcpy_P(str, FTOP(fstr));
DWIN_StatusChanged(str);
}
// Started a Print Job
void DWIN_Print_Started(const bool sd) {
sdprint = card.isPrinting() || sd;
@@ -1785,8 +1858,7 @@ void DWIN_Print_Started(const bool sd) {
// Ended print job
void DWIN_Print_Finished() {
if (checkkey == PrintProcess || printingIsActive()) {
thermalManager.disable_all_heaters();
thermalManager.zero_fan_speeds();
thermalManager.cooldown();
HMI_flag.print_finish = true;
}
}
@@ -1865,7 +1937,6 @@ void DWIN_RebootScreen() {
void DWIN_Redraw_screen() {
Draw_Main_Area();
DWIN_StatusChanged(ui.status_message);
Draw_Status_Area(false);
}
@@ -2114,23 +2185,13 @@ void SetHome() {
#endif
#if HAS_PREHEAT
void SetPreheat(const uint8_t i) {
TERN_(HAS_HOTEND, thermalManager.setTargetHotend(ui.material_preset[i].hotend_temp, 0));
TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(ui.material_preset[i].bed_temp));
TERN_(HAS_FAN, thermalManager.set_fan_speed(0, ui.material_preset[i].fan_speed));
}
void SetPreheat0() { SetPreheat(0); }
void SetPreheat1() { SetPreheat(1); }
void SetPreheat2() { SetPreheat(2); }
void SetCoolDown() {
TERN_(HAS_FAN, thermalManager.zero_fan_speeds());
#if HAS_HOTEND || HAS_HEATED_BED
thermalManager.disable_all_heaters();
#endif
}
void DoPreheat0() { ui.preheat_all(0); }
void DoPreheat1() { ui.preheat_all(1); }
void DoPreheat2() { ui.preheat_all(2); }
#endif
void DoCoolDown() { thermalManager.cooldown(); }
void SetLanguage() {
HMI_ToggleLanguage();
CurrentMenu = nullptr; // Invalidate menu to full redraw
@@ -2170,7 +2231,7 @@ void SetMoveZ() { HMI_value.axis = Z_AXIS; SetPFloatOnClick(Z_MIN_POS, Z_MAX_POS
void SetMoveZto0() {
char cmd[48] = "";
char str_1[5] = "", str_2[5] = "";
sprintf_P(cmd, PSTR("G28OXY\nG28Z\nG0X%sY%sF5000\nG0Z0F300"),
sprintf_P(cmd, PSTR("G28Z\nG0X%sY%sF5000\nM420S0\nG0Z0F300"),
#if ENABLED(MESH_BED_LEVELING)
dtostrf(0, 1, 1, str_1),
dtostrf(0, 1, 1, str_2)
@@ -2341,7 +2402,8 @@ void SetSpeed() { SetPIntOnClick(MIN_PRINT_SPEED, MAX_PRINT_SPEED); }
#endif // ADVANCED_PAUSE_FEATURE
void SetFlow() { SetPIntOnClick(MIN_PRINT_FLOW, MAX_PRINT_FLOW); }
void ApplyFlow() { planner.refresh_e_factor(0); }
void SetFlow() { SetPIntOnClick(MIN_PRINT_FLOW, MAX_PRINT_FLOW, ApplyFlow); }
// Leveling Bed Corners
void LevBed(uint8_t point) {
@@ -2352,7 +2414,7 @@ void LevBed(uint8_t point) {
float xpos = 0, ypos = 0, zval = 0;
float margin = PROBING_MARGIN;
#else
#define fmt "M420 S0\nG28O\nG90\nG0 Z5 F300\nG0 X%i Y%i F5000\nG0 Z0 F300"
#define fmt "M420S0\nG28O\nG90\nG0Z5F300\nG0X%iY%iF5000\nG0Z0F300"
int16_t xpos = 0, ypos = 0;
int16_t margin = 30;
#endif
@@ -2408,7 +2470,7 @@ void LevBedC () { LevBed(4); }
void ManualMeshStart(){
LCD_MESSAGE(MSG_UBL_BUILD_MESH_MENU);
gcode.process_subcommands_now(F("G28 XYO\nG28 Z\nM211 S0\nG29S1"));
gcode.process_subcommands_now(F("G28Z\nM211S0\nG29S1"));
planner.synchronize();
#ifdef MANUAL_PROBE_START_Z
const uint8_t line = CurrentMenu->line(MMeshMoveZItem->pos);
@@ -2433,7 +2495,7 @@ void LevBedC () { LevBed(4); }
void ManualMeshSave(){
LCD_MESSAGE(MSG_UBL_STORAGE_MESH_MENU);
queue.inject(F("M211 S1\nM500"));
queue.inject(F("M211S1\nM500"));
}
#endif // MESH_BED_LEVELING
@@ -2749,7 +2811,7 @@ void onDrawSteps(MenuItemClass* menuitem, int8_t line) {
#if ENABLED(MESH_BED_LEVELING)
void onDrawMMeshMoveZ(MenuItemClass* menuitem, int8_t line) {
if (HMI_IsChinese()) menuitem->SetFrame(1, 160, 118, 209, 132);
onDrawPFloatMenu(menuitem, line);
onDrawPFloat2Menu(menuitem, line);
}
#endif
@@ -3035,11 +3097,11 @@ void HMI_SetIntNoDraw() {
// Set an integer pointer variable using the encoder
void HMI_SetPInt() {
int8_t val = HMI_GetInt(HMI_value.MinValue, HMI_value.MaxValue);
if (!val) return;
else if (val == 2) { // Apply
*HMI_value.P_Int = HMI_value.Value;
if (HMI_value.Apply != nullptr) HMI_value.Apply();
} else if (HMI_value.LiveUpdate != nullptr) HMI_value.LiveUpdate();
switch (val) {
case 0: return;
case 1: if (HMI_value.LiveUpdate != nullptr) HMI_value.LiveUpdate(); break;
case 2: *HMI_value.P_Int = HMI_value.Value; if (HMI_value.Apply != nullptr) HMI_value.Apply(); break;
}
}
// Get a scaled float value using the encoder
@@ -3079,17 +3141,16 @@ void HMI_SetFloat() {
// Set a scaled float pointer variable using the encoder
void HMI_SetPFloat() {
const int8_t val = HMI_GetFloat(HMI_value.dp, HMI_value.MinValue, HMI_value.MaxValue);
if (!val) return;
if (val == 2) { // Apply
*HMI_value.P_Float = HMI_value.Value / POW(10, HMI_value.dp);
if (HMI_value.Apply != nullptr) HMI_value.Apply();
switch (val) {
case 0: return;
case 1: if (HMI_value.LiveUpdate != nullptr) HMI_value.LiveUpdate(); break;
case 2: *HMI_value.P_Float = HMI_value.Value / POW(10, HMI_value.dp); if (HMI_value.Apply != nullptr) HMI_value.Apply(); break;
}
else if (HMI_value.LiveUpdate != nullptr) HMI_value.LiveUpdate();
}
// Menu Creation and Drawing functions ======================================================
void SetMenuTitle(frame_rect_t cn, frame_rect_t en, const __FlashStringHelper* fstr) {
void SetMenuTitle(frame_rect_t cn, const __FlashStringHelper* fstr) {
if (HMI_IsChinese() && (cn.w != 0))
CurrentMenu->MenuTitle.SetFrame(cn.x, cn.y, cn.w, cn.h);
else
@@ -3101,7 +3162,7 @@ void Draw_Prepare_Menu() {
if (PrepareMenu == nullptr) PrepareMenu = new MenuClass();
if (CurrentMenu != PrepareMenu) {
CurrentMenu = PrepareMenu;
SetMenuTitle({133, 1, 28, 13}, {179, 0, 48, 14}, GET_TEXT_F(MSG_PREPARE));
SetMenuTitle({133, 1, 28, 13}, GET_TEXT_F(MSG_PREPARE));
DWINUI::MenuItemsPrepare(13);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Goto_Main_Menu);
#if ENABLED(ADVANCED_PAUSE_FEATURE)
@@ -3121,14 +3182,16 @@ void Draw_Prepare_Menu() {
ADDMENUITEM(ICON_SetHome, GET_TEXT_F(MSG_SET_HOME_OFFSETS), onDrawHomeOffset, SetHome);
#endif
#endif
#if HAS_HOTEND
ADDMENUITEM(ICON_PLAPreheat, GET_TEXT_F(MSG_PREHEAT_1), onDrawPreheat1, SetPreheat0);
ADDMENUITEM(ICON_ABSPreheat, PSTR("Preheat " PREHEAT_2_LABEL), onDrawPreheat2, SetPreheat1);
ADDMENUITEM(ICON_CustomPreheat, GET_TEXT_F(MSG_PREHEAT_CUSTOM), onDrawMenuItem, SetPreheat2);
#endif
#if HAS_PREHEAT
ADDMENUITEM(ICON_Cool, GET_TEXT_F(MSG_COOLDOWN), onDrawCooldown, SetCoolDown);
ADDMENUITEM(ICON_PLAPreheat, GET_TEXT_F(MSG_PREHEAT_1), onDrawPreheat1, DoPreheat0);
#if PREHEAT_COUNT > 1
ADDMENUITEM(ICON_ABSPreheat, PSTR("Preheat " PREHEAT_2_LABEL), onDrawPreheat2, DoPreheat1);
#endif
#if PREHEAT_COUNT > 2
ADDMENUITEM(ICON_CustomPreheat, GET_TEXT_F(MSG_PREHEAT_CUSTOM), onDrawMenuItem, DoPreheat2);
#endif
#endif
ADDMENUITEM(ICON_Cool, GET_TEXT_F(MSG_COOLDOWN), onDrawCooldown, DoCoolDown);
ADDMENUITEM(ICON_Language, PSTR("UI Language"), onDrawLanguage, SetLanguage);
}
CurrentMenu->draw();
@@ -3140,7 +3203,7 @@ void Draw_LevBedCorners_Menu() {
if (LevBedMenu == nullptr) LevBedMenu = new MenuClass();
if (CurrentMenu != LevBedMenu) {
CurrentMenu = LevBedMenu;
SetMenuTitle({0}, {0}, GET_TEXT_F(MSG_BED_TRAMMING)); // TODO: Chinese, English "Bed Tramming" JPG
SetMenuTitle({0}, GET_TEXT_F(MSG_BED_TRAMMING)); // TODO: Chinese, English "Bed Tramming" JPG
DWINUI::MenuItemsPrepare(6);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Prepare_Menu);
ADDMENUITEM(ICON_Axis, GET_TEXT_F(MSG_LEVBED_FL), onDrawMenuItem, LevBedFL);
@@ -3157,7 +3220,7 @@ void Draw_Control_Menu() {
if (ControlMenu == nullptr) ControlMenu = new MenuClass();
if (CurrentMenu != ControlMenu) {
CurrentMenu = ControlMenu;
SetMenuTitle({103, 1, 28, 14}, {128, 2, 49, 11}, GET_TEXT_F(MSG_CONTROL));
SetMenuTitle({103, 1, 28, 14}, GET_TEXT_F(MSG_CONTROL));
DWINUI::MenuItemsPrepare(9);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Goto_Main_Menu);
ADDMENUITEM(ICON_Temperature, GET_TEXT_F(MSG_TEMPERATURE), onDrawTempSubMenu, Draw_Temperature_Menu);
@@ -3179,8 +3242,8 @@ void Draw_AdvancedSettings_Menu() {
if (AdvancedSettings == nullptr) AdvancedSettings = new MenuClass();
if (CurrentMenu != AdvancedSettings) {
CurrentMenu = AdvancedSettings;
SetMenuTitle({0}, {0}, GET_TEXT_F(MSG_ADVANCED_SETTINGS)); // TODO: Chinese, English "Advanced Settings" JPG
DWINUI::MenuItemsPrepare(11);
SetMenuTitle({0}, GET_TEXT_F(MSG_ADVANCED_SETTINGS)); // TODO: Chinese, English "Advanced Settings" JPG
DWINUI::MenuItemsPrepare(12);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Control_Menu);
#if HAS_HOME_OFFSET
ADDMENUITEM(ICON_HomeOffset, GET_TEXT_F(MSG_SET_HOME_OFFSETS), onDrawSubMenu, Draw_HomeOffset_Menu);
@@ -3220,7 +3283,7 @@ void Draw_Move_Menu() {
if (MoveMenu == nullptr) MoveMenu = new MenuClass();
if (CurrentMenu != MoveMenu) {
CurrentMenu = MoveMenu;
SetMenuTitle({192, 1, 42, 14}, {231, 2, 35, 11}, GET_TEXT_F(MSG_MOVE_AXIS));
SetMenuTitle({192, 1, 42, 14}, GET_TEXT_F(MSG_MOVE_AXIS));
DWINUI::MenuItemsPrepare(5);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Prepare_Menu);
ADDMENUITEM_P(ICON_MoveX, GET_TEXT_F(MSG_MOVE_X), onDrawMoveX, SetMoveX, &current_position.x);
@@ -3240,7 +3303,7 @@ void Draw_Move_Menu() {
if (HomeOffMenu == nullptr) HomeOffMenu = new MenuClass();
if (CurrentMenu != HomeOffMenu) {
CurrentMenu = HomeOffMenu;
SetMenuTitle({0}, {0}, GET_TEXT_F(MSG_SET_HOME_OFFSETS)); // TODO: Chinese, English "Set Home Offsets" JPG
SetMenuTitle({0}, GET_TEXT_F(MSG_SET_HOME_OFFSETS)); // TODO: Chinese, English "Set Home Offsets" JPG
DWINUI::MenuItemsPrepare(4);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_AdvancedSettings_Menu);
ADDMENUITEM_P(ICON_HomeOffsetX, GET_TEXT_F(MSG_HOME_OFFSET_X), onDrawPFloatMenu, SetHomeOffsetX, &home_offset[X_AXIS]);
@@ -3257,7 +3320,7 @@ void Draw_Move_Menu() {
if (ProbeSetMenu == nullptr) ProbeSetMenu = new MenuClass();
if (CurrentMenu != ProbeSetMenu) {
CurrentMenu = ProbeSetMenu;
SetMenuTitle({0}, {0}, GET_TEXT_F(MSG_ZPROBE_SETTINGS)); // TODO: Chinese, English "Probe Settings" JPG
SetMenuTitle({0}, GET_TEXT_F(MSG_ZPROBE_SETTINGS)); // TODO: Chinese, English "Probe Settings" JPG
DWINUI::MenuItemsPrepare(5);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_AdvancedSettings_Menu);
ADDMENUITEM_P(ICON_ProbeOffsetX, GET_TEXT_F(MSG_ZPROBE_XOFFSET), onDrawPFloatMenu, SetProbeOffsetX, &probe.offset.x);
@@ -3301,7 +3364,7 @@ void Draw_SelectColors_Menu() {
if (SelectColorMenu == nullptr) SelectColorMenu = new MenuClass();
if (CurrentMenu != SelectColorMenu) {
CurrentMenu = SelectColorMenu;
SetMenuTitle({0}, {0}, F("Select Colors")); // TODO: Chinese, English "Select Color" JPG
SetMenuTitle({0}, F("Select Colors")); // TODO: Chinese, English "Select Color" JPG
DWINUI::MenuItemsPrepare(20);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_AdvancedSettings_Menu);
ADDMENUITEM(ICON_StockConfiguration, GET_TEXT_F(MSG_RESTORE_DEFAULTS), onDrawMenuItem, RestoreDefaultsColors);
@@ -3332,7 +3395,7 @@ void Draw_GetColor_Menu() {
if (GetColorMenu == nullptr) GetColorMenu = new MenuClass();
if (CurrentMenu != GetColorMenu) {
CurrentMenu = GetColorMenu;
SetMenuTitle({0}, {0}, F("Get Color")); // TODO: Chinese, English "Get Color" JPG
SetMenuTitle({0}, F("Get Color")); // TODO: Chinese, English "Get Color" JPG
DWINUI::MenuItemsPrepare(5);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, DWIN_ApplyColor);
ADDMENUITEM(ICON_Cancel, GET_TEXT_F(MSG_BUTTON_CANCEL), onDrawMenuItem, Draw_SelectColors_Menu);
@@ -3349,7 +3412,7 @@ void Draw_Tune_Menu() {
if (TuneMenu == nullptr) TuneMenu = new MenuClass();
if (CurrentMenu != TuneMenu) {
CurrentMenu = TuneMenu;
SetMenuTitle({73, 2, 28, 12}, {94, 2, 33, 11}, GET_TEXT_F(MSG_TUNE)); // TODO: Chinese, English "Tune" JPG
SetMenuTitle({73, 2, 28, 12}, GET_TEXT_F(MSG_TUNE)); // TODO: Chinese, English "Tune" JPG
DWINUI::MenuItemsPrepare(10);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Goto_PrintProcess);
ADDMENUITEM_P(ICON_Speed, GET_TEXT_F(MSG_SPEED), onDrawSpeedItem, SetSpeed, &feedrate_percentage);
@@ -3382,7 +3445,7 @@ void Draw_Motion_Menu() {
if (MotionMenu == nullptr) MotionMenu = new MenuClass();
if (CurrentMenu != MotionMenu) {
CurrentMenu = MotionMenu;
SetMenuTitle({1, 16, 28, 13}, {144, 16, 46, 11}, GET_TEXT_F(MSG_MOTION)); // TODO: Chinese, English "Motion" JPG
SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_MOTION)); // TODO: Chinese, English "Motion" JPG
DWINUI::MenuItemsPrepare(6);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Control_Menu);
ADDMENUITEM(ICON_MaxSpeed, GET_TEXT_F(MSG_SPEED), onDrawSpeed, Draw_MaxSpeed_Menu);
@@ -3402,7 +3465,7 @@ void Draw_Motion_Menu() {
if (FilamentMenu == nullptr) FilamentMenu = new MenuClass();
if (CurrentMenu != FilamentMenu) {
CurrentMenu = FilamentMenu;
SetMenuTitle({0}, {0}, GET_TEXT_F(MSG_FILAMENT_MAN)); // TODO: Chinese, English "Filament Management" JPG
SetMenuTitle({0}, GET_TEXT_F(MSG_FILAMENT_MAN)); // TODO: Chinese, English "Filament Management" JPG
DWINUI::MenuItemsPrepare(5);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Prepare_Menu);
ADDMENUITEM(ICON_Park, GET_TEXT_F(MSG_FILAMENT_PARK_ENABLED), onDrawMenuItem, ParkHead);
@@ -3422,8 +3485,8 @@ void Draw_Motion_Menu() {
if (ManualMesh == nullptr) ManualMesh = new MenuClass();
if (CurrentMenu != ManualMesh) {
CurrentMenu = ManualMesh;
SetMenuTitle({0}, {0}, GET_TEXT_F(MSG_MANUAL_MESH)); // TODO: Chinese, English "Manual Mesh Leveling" JPG
DWINUI::MenuItemsPrepare(5);
SetMenuTitle({0}, GET_TEXT_F(MSG_MANUAL_MESH)); // TODO: Chinese, English "Manual Mesh Leveling" JPG
DWINUI::MenuItemsPrepare(6);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Prepare_Menu);
ADDMENUITEM(ICON_ManualMesh, GET_TEXT_F(MSG_LEVEL_BED), onDrawMenuItem, ManualMeshStart);
MMeshMoveZItem = ADDMENUITEM_P(ICON_Zoffset, GET_TEXT_F(MSG_MOVE_Z), onDrawMMeshMoveZ, SetMMeshMoveZ, &current_position.z);
@@ -3437,11 +3500,11 @@ void Draw_Motion_Menu() {
#if HAS_PREHEAT
void Draw_Preheat_Menu(frame_rect_t cn, frame_rect_t en, const __FlashStringHelper* fstr) {
void Draw_Preheat_Menu(frame_rect_t cn, const __FlashStringHelper* fstr) {
checkkey = Menu;
if (CurrentMenu != PreheatMenu) {
CurrentMenu = PreheatMenu;
SetMenuTitle(cn, en, fstr);
SetMenuTitle(cn, fstr);
DWINUI::MenuItemsPrepare(5);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Temperature_Menu);
#if HAS_HOTEND
@@ -3463,13 +3526,13 @@ void Draw_Motion_Menu() {
void Draw_Preheat1_Menu() {
HMI_value.Preheat = 0;
if (PreheatMenu == nullptr) PreheatMenu = new MenuClass();
Draw_Preheat_Menu({59, 16, 81, 14}, {56, 15, 85, 14}, F(PREHEAT_1_LABEL " Preheat Settings")); // TODO: English "PLA Settings" JPG
Draw_Preheat_Menu({59, 16, 81, 14}, F(PREHEAT_1_LABEL " Preheat Settings")); // TODO: English "PLA Settings" JPG
}
void Draw_Preheat2_Menu() {
HMI_value.Preheat = 1;
if (PreheatMenu == nullptr) PreheatMenu = new MenuClass();
Draw_Preheat_Menu({142, 16, 82, 14}, {56, 15, 85, 14}, F(PREHEAT_2_LABEL " Preheat Settings")); // TODO: English "ABS Settings" JPG
Draw_Preheat_Menu({142, 16, 82, 14}, F(PREHEAT_2_LABEL " Preheat Settings")); // TODO: English "ABS Settings" JPG
}
#ifdef PREHEAT_3_LABEL
@@ -3477,7 +3540,7 @@ void Draw_Motion_Menu() {
HMI_value.Preheat = 2;
if (PreheatMenu == nullptr) PreheatMenu = new MenuClass();
#define PREHEAT_3_TITLE PREHEAT_3_LABEL " Preheat Set."
Draw_Preheat_Menu({0}, {0}, F(PREHEAT_3_TITLE)); // TODO: Chinese, English "Custom Preheat Settings" JPG
Draw_Preheat_Menu({0}, F(PREHEAT_3_TITLE)); // TODO: Chinese, English "Custom Preheat Settings" JPG
}
#endif
@@ -3488,7 +3551,7 @@ void Draw_Temperature_Menu() {
if (TemperatureMenu == nullptr) TemperatureMenu = new MenuClass();
if (CurrentMenu != TemperatureMenu) {
CurrentMenu = TemperatureMenu;
SetMenuTitle({236, 2, 28, 12}, {56, 15, 85, 14}, GET_TEXT_F(MSG_TEMPERATURE));
SetMenuTitle({236, 2, 28, 12}, GET_TEXT_F(MSG_TEMPERATURE));
DWINUI::MenuItemsPrepare(7);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Control_Menu);
#if HAS_HOTEND
@@ -3516,7 +3579,7 @@ void Draw_MaxSpeed_Menu() {
if (MaxSpeedMenu == nullptr) MaxSpeedMenu = new MenuClass();
if (CurrentMenu != MaxSpeedMenu) {
CurrentMenu = MaxSpeedMenu;
SetMenuTitle({1, 16, 28, 13}, {144, 16, 46, 11}, GET_TEXT_F(MSG_MAXSPEED));
SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_MAXSPEED));
DWINUI::MenuItemsPrepare(5);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Motion_Menu);
ADDMENUITEM_P(ICON_MaxSpeedX, GET_TEXT_F(MSG_MAXSPEED_X), onDrawMaxSpeedX, SetMaxSpeedX, &planner.settings.max_feedrate_mm_s[X_AXIS]);
@@ -3534,7 +3597,7 @@ void Draw_MaxAccel_Menu() {
if (MaxAccelMenu == nullptr) MaxAccelMenu = new MenuClass();
if (CurrentMenu != MaxAccelMenu) {
CurrentMenu = MaxAccelMenu;
SetMenuTitle({1, 16, 28, 13}, {144, 16, 46, 11}, GET_TEXT_F(MSG_ACCELERATION));
SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_ACCELERATION));
DWINUI::MenuItemsPrepare(5);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Motion_Menu);
ADDMENUITEM_P(ICON_MaxAccX, GET_TEXT_F(MSG_AMAX_A), onDrawMaxAccelX, SetMaxAccelX, &planner.settings.max_acceleration_mm_per_s2[X_AXIS]);
@@ -3553,7 +3616,7 @@ void Draw_MaxAccel_Menu() {
if (MaxJerkMenu == nullptr) MaxJerkMenu = new MenuClass();
if (CurrentMenu != MaxJerkMenu) {
CurrentMenu = MaxJerkMenu;
SetMenuTitle({1, 16, 28, 13}, {144, 16, 46, 11}, GET_TEXT_F(MSG_JERK));
SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_JERK));
DWINUI::MenuItemsPrepare(5);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Motion_Menu);
ADDMENUITEM_P(ICON_MaxSpeedJerkX, GET_TEXT_F(MSG_VA_JERK), onDrawMaxJerkX, SetMaxJerkX, &planner.max_jerk[X_AXIS]);
@@ -3572,7 +3635,7 @@ void Draw_Steps_Menu() {
if (StepsMenu == nullptr) StepsMenu = new MenuClass();
if (CurrentMenu != StepsMenu) {
CurrentMenu = StepsMenu;
SetMenuTitle({1, 16, 28, 13}, {144, 16, 46, 11}, GET_TEXT_F(MSG_STEPS_PER_MM));
SetMenuTitle({1, 16, 28, 13}, GET_TEXT_F(MSG_STEPS_PER_MM));
DWINUI::MenuItemsPrepare(5);
ADDMENUITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Motion_Menu);
ADDMENUITEM_P(ICON_StepX, GET_TEXT_F(MSG_A_STEPS), onDrawStepsX, SetStepsX, &planner.settings.axis_steps_per_mm[X_AXIS]);
+12 -18
View File
@@ -24,8 +24,8 @@
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* Version: 3.7.1
* Date: 2021/11/09
*/
#include "../../../inc/MarlinConfigPre.h"
@@ -33,13 +33,6 @@
#include "../common/encoder.h"
#include "../../../libs/BL24CXX.h"
#if ANY(HAS_HOTEND, HAS_HEATED_BED, HAS_FAN) && PREHEAT_COUNT
#define HAS_PREHEAT 1
#if PREHEAT_COUNT < 2
#error "Creality DWIN requires two material preheat presets."
#endif
#endif
#if ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT) && DISABLED(PROBE_MANUALLY)
#define HAS_ONESTEP_LEVELING 1
#endif
@@ -123,12 +116,14 @@ typedef struct {
uint16_t Barfill_Color = Def_Barfill_Color;
uint16_t Indicator_Color = Def_Indicator_Color;
uint16_t Coordinate_Color = Def_Coordinate_Color;
#if HAS_HOTEND
int16_t HotendPidT = PREHEAT_1_TEMP_HOTEND;
int16_t PidCycles = 10;
#endif
#ifdef PREHEAT_1_TEMP_BED
int16_t BedPidT = PREHEAT_1_TEMP_BED;
#if HAS_PREHEAT
#ifdef PREHEAT_1_TEMP_HOTEND
int16_t HotendPidT = PREHEAT_1_TEMP_HOTEND;
int16_t PidCycles = 10;
#endif
#ifdef PREHEAT_1_TEMP_BED
int16_t BedPidT = PREHEAT_1_TEMP_BED;
#endif
#endif
#if ENABLED(PREVENT_COLD_EXTRUSION)
int16_t ExtMinT = EXTRUDE_MINTEMP;
@@ -159,6 +154,7 @@ void HMI_SDCardUpdate();
// Other
void Goto_PrintProcess();
void Goto_Main_Menu();
void Goto_InfoMenu();
void Draw_Select_Highlight(const bool sel);
void Draw_Status_Area(const bool with_update); // Status Area
void Draw_Main_Area(); // Redraw main area;
@@ -179,9 +175,7 @@ void EachMomentUpdate();
void update_variable();
void DWIN_HandleScreen();
void DWIN_Update();
void DWIN_DrawStatusLine(const uint16_t color, const uint16_t bgcolor, const char *text=nullptr);
void DWIN_StatusChanged(const char * const cstr=nullptr);
void DWIN_StatusChanged(FSTR_P const fstr);
void DWIN_CheckStatusMessage();
void DWIN_StartHoming();
void DWIN_CompletedHoming();
#if HAS_MESH
+2 -2
View File
@@ -23,8 +23,8 @@
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* Version: 3.7.1
* Date: 2021/11/09
*/
#include "../../../inc/MarlinConfigPre.h"
+2 -9
View File
@@ -24,8 +24,8 @@
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* Version: 3.7.1
* Date: 2021/11/09
*/
#include "../common/dwin_api.h"
@@ -48,13 +48,6 @@ inline void DWIN_Draw_QR(uint8_t QR_Pixel, uint16_t x, uint16_t y, FSTR_P title)
// x/y: Screen paste point
void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y);
// Copy area from virtual display area to current screen
// cacheID: virtual area number
// xStart/yStart: Upper-left of virtual area
// xEnd/yEnd: Lower-right of virtual area
// x/y: Screen paste point
void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y);
// Copy area from current virtual display area to current screen
// xStart/yStart: Upper-left of virtual area
// xEnd/yEnd: Lower-right of virtual area
+9 -9
View File
@@ -23,8 +23,8 @@
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* Version: 3.7.1
* Date: 2021/11/09
*/
#include "../../../inc/MarlinConfigPre.h"
@@ -38,8 +38,8 @@
//#define DEBUG_OUT 1
#include "../../../core/debug_out.h"
uint8_t MenuItemTotal = 0;
uint8_t MenuItemCount = 0;
int8_t MenuItemTotal = 0;
int8_t MenuItemCount = 0;
MenuItemClass** MenuItems = nullptr;
MenuClass *CurrentMenu = nullptr;
MenuClass *PreviousMenu = nullptr;
@@ -50,8 +50,8 @@ uint16_t DWINUI::textcolor = Def_Text_Color;
uint16_t DWINUI::backcolor = Def_Background_Color;
uint8_t DWINUI::font = font8x16;
void (*DWINUI::onCursorErase)(uint8_t line)=nullptr;
void (*DWINUI::onCursorDraw)(uint8_t line)=nullptr;
void (*DWINUI::onCursorErase)(const int8_t line)=nullptr;
void (*DWINUI::onCursorDraw)(const int8_t line)=nullptr;
void (*DWINUI::onTitleDraw)(TitleClass* title)=nullptr;
void (*DWINUI::onMenuDraw)(MenuClass* menu)=nullptr;
@@ -304,14 +304,14 @@ void DWINUI::ClearMenuArea() {
void DWINUI::MenuItemsClear() {
if (MenuItems == nullptr) return;
for (uint8_t i = 0; i < MenuItemCount; i++) delete MenuItems[i];
for (int8_t i = 0; i < MenuItemCount; i++) delete MenuItems[i];
delete[] MenuItems;
MenuItems = nullptr;
MenuItemCount = 0;
MenuItemTotal = 0;
}
void DWINUI::MenuItemsPrepare(uint8_t totalitems) {
void DWINUI::MenuItemsPrepare(int8_t totalitems) {
MenuItemsClear();
MenuItemTotal = totalitems;
MenuItems = new MenuItemClass*[totalitems];
@@ -379,7 +379,7 @@ MenuClass::MenuClass() {
void MenuClass::draw() {
MenuTitle.draw();
if (DWINUI::onMenuDraw != nullptr) (*DWINUI::onMenuDraw)(this);
for (uint8_t i = 0; i < MenuItemCount; i++)
for (int8_t i = 0; i < MenuItemCount; i++)
MenuItems[i]->draw(i - topline);
if (DWINUI::onCursorDraw != nullptr) DWINUI::onCursorDraw(line());
DWIN_UpdateLCD();
+21 -16
View File
@@ -24,11 +24,10 @@
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* Version: 3.7.1
* Date: 2021/11/09
*/
#include "../../../core/types.h"
#include "dwin_lcd.h"
#include "../common/dwin_set.h"
#include "../common/dwin_font.h"
@@ -138,7 +137,7 @@ extern TitleClass Title;
class MenuItemClass {
protected:
public:
uint8_t pos = 0;
int8_t pos = 0;
uint8_t icon = 0;
char caption[32] = "";
uint8_t frameid = 0;
@@ -185,8 +184,8 @@ namespace DWINUI {
extern uint16_t backcolor;
extern uint8_t font;
extern void (*onCursorErase)(uint8_t line);
extern void (*onCursorDraw)(uint8_t line);
extern void (*onCursorErase)(const int8_t line);
extern void (*onCursorDraw)(const int8_t line);
extern void (*onTitleDraw)(TitleClass* title);
extern void (*onMenuDraw)(MenuClass* menu);
@@ -342,6 +341,12 @@ namespace DWINUI {
// rlimit: For draw less chars than string length use rlimit
void Draw_String(const char * const string, uint16_t rlimit = 0xFFFF);
void Draw_String(uint16_t color, const char * const string, uint16_t rlimit = 0xFFFF);
inline void Draw_String(FSTR_P string, uint16_t rlimit = 0xFFFF) {
Draw_String(FTOP(string), rlimit);
}
inline void Draw_String(uint16_t color, FSTR_P string, uint16_t rlimit = 0xFFFF) {
Draw_String(color, FTOP(string), rlimit);
}
// Draw a string
// size: Font size
@@ -353,25 +358,25 @@ namespace DWINUI {
DWIN_Draw_String(false, font, textcolor, backcolor, x, y, string);
}
inline void Draw_String(uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(false, font, textcolor, backcolor, x, y, (char *)title);
DWIN_Draw_String(false, font, textcolor, backcolor, x, y, FTOP(title));
}
inline void Draw_String(uint16_t color, uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(false, font, color, backcolor, x, y, string);
}
inline void Draw_String(uint16_t color, uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(false, font, color, backcolor, x, y, (char *)title);
DWIN_Draw_String(false, font, color, backcolor, x, y, title);
}
inline void Draw_String(uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(true, font, color, bgcolor, x, y, string);
}
inline void Draw_String(uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(true, font, color, bgcolor, x, y, (char *)title);
DWIN_Draw_String(true, font, color, bgcolor, x, y, title);
}
inline void Draw_String(uint8_t size, uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(true, size, color, bgcolor, x, y, string);
}
inline void Draw_String(uint8_t size, uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(true, size, color, bgcolor, x, y, (char *)title);
DWIN_Draw_String(true, size, color, bgcolor, x, y, title);
}
// Draw a centered string using DWIN_WIDTH
@@ -382,8 +387,8 @@ namespace DWINUI {
// y: Upper coordinate of the string
// *string: The string
void Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, const char * const string);
inline void Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, FSTR_P title) {
Draw_CenteredString(bShow, size, color, bColor, y, (char *)title);
inline void Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, FSTR_P string) {
Draw_CenteredString(bShow, size, color, bColor, y, FTOP(string));
}
inline void Draw_CenteredString(uint16_t color, uint16_t bcolor, uint16_t y, const char * const string) {
Draw_CenteredString(true, font, color, bcolor, y, string);
@@ -392,19 +397,19 @@ namespace DWINUI {
Draw_CenteredString(false, size, color, backcolor, y, string);
}
inline void Draw_CenteredString(uint8_t size, uint16_t color, uint16_t y, FSTR_P title) {
Draw_CenteredString(false, size, color, backcolor, y, (char *)title);
Draw_CenteredString(false, size, color, backcolor, y, title);
}
inline void Draw_CenteredString(uint16_t color, uint16_t y, const char * const string) {
Draw_CenteredString(false, font, color, backcolor, y, string);
}
inline void Draw_CenteredString(uint16_t color, uint16_t y, FSTR_P title) {
Draw_CenteredString(false, font, color, backcolor, y, (char *)title);
Draw_CenteredString(false, font, color, backcolor, y, title);
}
inline void Draw_CenteredString(uint16_t y, const char * const string) {
Draw_CenteredString(false, font, textcolor, backcolor, y, string);
}
inline void Draw_CenteredString(uint16_t y, FSTR_P title) {
Draw_CenteredString(false, font, textcolor, backcolor, y, (char *)title);
Draw_CenteredString(false, font, textcolor, backcolor, y, title);
}
// Draw a circle
@@ -477,7 +482,7 @@ namespace DWINUI {
void MenuItemsClear();
// Prepare MenuItems array
void MenuItemsPrepare(uint8_t totalitems);
void MenuItemsPrepare(int8_t totalitems);
// Add elements to the MenuItems array
MenuItemClass* MenuItemsAdd(MenuItemClass* menuitem);
+35 -8
View File
@@ -1,8 +1,8 @@
/**
* DWIN Mesh Viewer
* Author: Miguel A. Risco-Castillo
* version: 2.5
* Date: 2021/09/27
* version: 3.8.1
* Date: 2021/11/06
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
@@ -35,13 +35,15 @@
MeshViewerClass MeshViewer;
void MeshViewerClass::Draw() {
const int8_t mx = 30, my = 30; // Margins
const int8_t mx = 25, my = 25; // Margins
const int16_t stx = (DWIN_WIDTH - 2 * mx) / (GRID_MAX_POINTS_X - 1), // Steps
sty = (DWIN_WIDTH - 2 * my) / (GRID_MAX_POINTS_Y - 1);
int8_t zmesh[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y], maxz =-127, minz = 127;
const int8_t rmax = _MIN(mx - 2, stx / 2);
const int8_t rmin = 7;
int16_t zmesh[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y], maxz =-32000, minz = 32000;
#define px(xp) (mx + (xp) * stx)
#define py(yp) (30 + DWIN_WIDTH - my - (yp) * sty)
#define rm(z) ((((z) - minz) * 10 / _MAX(1, (maxz - minz))) + 10)
#define rm(z) ((z - minz) * (rmax - rmin) / _MAX(1, (maxz - minz)) + rmin)
#define DrawMeshValue(xp, yp, zv) DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(xp) - 12, py(yp) - 6, zv)
#define DrawMeshHLine(yp) DWIN_Draw_HLine(HMI_data.SplitLine_Color, px(0), py(yp), DWIN_WIDTH - 2 * mx)
#define DrawMeshVLine(xp) DWIN_Draw_VLine(HMI_data.SplitLine_Color, px(xp), py(GRID_MAX_POINTS_Y - 1), DWIN_WIDTH - 2 * my)
@@ -51,7 +53,7 @@ void MeshViewerClass::Draw() {
NOLESS(maxz, v);
NOMORE(minz, v);
}
Title.ShowCaption(F("Mesh viewer"));
Title.ShowCaption(F("Mesh Viewer"));
DWINUI::ClearMenuArea();
DWINUI::Draw_Icon(ICON_Continue_E, 86, 305);
DWIN_Draw_Rectangle(0, HMI_data.SplitLine_Color, px(0), py(0), px(GRID_MAX_POINTS_X - 1), py(GRID_MAX_POINTS_Y - 1));
@@ -61,8 +63,33 @@ void MeshViewerClass::Draw() {
watchdog_refresh();
LOOP_L_N(x, GRID_MAX_POINTS_X) {
uint16_t color = DWINUI::RainbowInt(zmesh[x][y], _MIN(-5, minz), _MAX(5, maxz));
DWINUI::Draw_FillCircle(color, px(x), py(y), rm(zmesh[x][y]));
DrawMeshValue(x, y, Z_VALUES(x,y));
uint8_t radius = rm(zmesh[x][y]);
DWINUI::Draw_FillCircle(color, px(x), py(y), radius);
if (GRID_MAX_POINTS_X < 9)
DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(x) - 12, py(y) - 6, Z_VALUES(x,y));
else {
char str_1[9];
str_1[0] = 0;
switch (zmesh[x][y]) {
case -999 ... -100:
DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 12, py(y) - 6, Z_VALUES(x,y));
break;
case -99 ... -1:
sprintf_P(str_1, PSTR("-.%02i"), -zmesh[x][y]);
break;
case 0:
DWIN_Draw_String(false, font6x12, DWINUI::textcolor, DWINUI::backcolor, px(x) - 4, py(y) - 6, "0");;
break;
case 1 ... 99:
sprintf_P(str_1, PSTR(".%02i"), zmesh[x][y]);
break;
case 100 ... 999:
DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 12, py(y) - 6, Z_VALUES(x,y));
break;
}
if (str_1[0])
DWIN_Draw_String(false, font6x12, DWINUI::textcolor, DWINUI::backcolor, px(x) - 12, py(y) - 6, str_1);
}
}
}
char str_1[6], str_2[6] = "";
+2 -2
View File
@@ -1,8 +1,8 @@
/**
* DWIN Mesh Viewer
* Author: Miguel A. Risco-Castillo
* version: 2.5
* Date: 2021/09/27
* Version: 3.8.1
* Date: 2021/11/06
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
+1 -1
View File
@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
+1 -1
View File
@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@@ -132,20 +132,19 @@ FORCE_INLINE void _draw_fan_status(const uint16_t x, const uint16_t y) {
}
}
#if HOTENDS > 2
#define HOTEND_STATS 3
#elif HOTENDS > 1
#define HOTEND_STATS 2
#elif HAS_HOTEND
#define HOTEND_STATS 1
#endif
/**
* Draw a single heater icon with current and target temperature, at the given XY
*/
FORCE_INLINE void _draw_heater_status(const heater_id_t heater, const uint16_t x, const uint16_t y) {
#if HAS_HOTEND
#if HOTENDS > 2
#define HOTEND_STATS 3
#elif HOTENDS > 1
#define HOTEND_STATS 2
#elif HAS_HOTEND
#define HOTEND_STATS 1
#endif
static celsius_t old_temp[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500),
old_target[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500);
static bool old_on[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, false);
+10 -49
View File
@@ -185,7 +185,7 @@ void DGUSScreenHandler::DGUSLCD_SendStringToDisplayPGM(DGUS_VP_Variable &var) {
case VP_E0_PID_I: valuesend = unscalePID_i(value); break;
case VP_E0_PID_D: valuesend = unscalePID_d(value); break;
#endif
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
case VP_E1_PID_P: valuesend = value; break;
case VP_E1_PID_I: valuesend = unscalePID_i(value); break;
case VP_E1_PID_D: valuesend = unscalePID_d(value); break;
@@ -400,7 +400,7 @@ void DGUSScreenHandler::HandleTemperatureChanged(DGUS_VP_Variable &var, void *va
acceptedvalue = thermalManager.degTargetHotend(0);
break;
#endif
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
case VP_T_E1_Set:
NOMORE(newvalue, HEATER_1_MAXTEMP);
thermalManager.setTargetHotend(newvalue, 1);
@@ -551,7 +551,7 @@ void DGUSScreenHandler::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, vo
sprintf_P(buf, PSTR("M303 E%d C5 S210 U1"), ExtUI::extruder_t::E0);
break;
#endif
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
case VP_PID_AUTOTUNE_E1:
sprintf_P(buf, PSTR("M303 E%d C5 S210 U1"), ExtUI::extruder_t::E1);
break;
@@ -598,7 +598,7 @@ void DGUSScreenHandler::HandleHeaterControl(DGUS_VP_Variable &var, void *val_ptr
switch (var.VP) {
#if HAS_HOTEND
case VP_E0_CONTROL:
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
case VP_E1_CONTROL:
#if HOTENDS >= 3
case VP_E2_CONTROL:
@@ -621,55 +621,16 @@ void DGUSScreenHandler::HandleHeaterControl(DGUS_VP_Variable &var, void *val_ptr
void DGUSScreenHandler::HandlePreheat(DGUS_VP_Variable &var, void *val_ptr) {
DEBUG_ECHOLNPGM("HandlePreheat");
uint8_t e_temp = 0;
#if HAS_HEATED_BED
uint8_t bed_temp = 0;
#endif
const uint16_t preheat_option = swap16(*(uint16_t*)val_ptr);
switch (preheat_option) {
default:
case 0: // Preheat PLA
#if defined(PREHEAT_1_TEMP_HOTEND) && defined(PREHEAT_1_TEMP_BED)
e_temp = PREHEAT_1_TEMP_HOTEND;
TERN_(HAS_HEATED_BED, bed_temp = PREHEAT_1_TEMP_BED);
#endif
break;
case 1: // Preheat ABS
#if defined(PREHEAT_2_TEMP_HOTEND) && defined(PREHEAT_2_TEMP_BED)
e_temp = PREHEAT_2_TEMP_HOTEND;
TERN_(HAS_HEATED_BED, bed_temp = PREHEAT_2_TEMP_BED);
#endif
break;
case 2: // Preheat PET
#if defined(PREHEAT_3_TEMP_HOTEND) && defined(PREHEAT_3_TEMP_BED)
e_temp = PREHEAT_3_TEMP_HOTEND;
TERN_(HAS_HEATED_BED, bed_temp = PREHEAT_3_TEMP_BED);
#endif
break;
case 3: // Preheat FLEX
#if defined(PREHEAT_4_TEMP_HOTEND) && defined(PREHEAT_4_TEMP_BED)
e_temp = PREHEAT_4_TEMP_HOTEND;
TERN_(HAS_HEATED_BED, bed_temp = PREHEAT_4_TEMP_BED);
#endif
break;
switch (var.VP) {
default: return;
case VP_E0_BED_PREHEAT: TERN_(HAS_HOTEND, ui.preheat_all(0)); break;
case VP_E1_BED_PREHEAT: TERN_(HAS_MULTI_HOTEND, ui.preheat_all(1)); break;
}
case 7: break; // Custom preheat
case 9: break; // Cool down
}
switch (var.VP) {
default: return;
#if HAS_HOTEND
case VP_E0_BED_PREHEAT:
thermalManager.setTargetHotend(e_temp, 0);
TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(bed_temp));
break;
#endif
#if HOTENDS >= 2
case VP_E1_BED_PREHEAT:
thermalManager.setTargetHotend(e_temp, 1);
TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(bed_temp));
break;
#endif
case 9: thermalManager.cooldown(); break; // Cool down
}
// Go to the preheat screen to show the heating progress
@@ -51,7 +51,7 @@ const uint16_t VPList_Main[] PROGMEM = {
#if HAS_HOTEND
VP_T_E0_Is, VP_T_E0_Set, VP_E0_STATUS,
#endif
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
VP_T_E1_Is, VP_T_E1_Set,
#endif
#if HAS_HEATED_BED
@@ -73,7 +73,7 @@ const uint16_t VPList_Temp[] PROGMEM = {
#if HAS_HOTEND
VP_T_E0_Is, VP_T_E0_Set,
#endif
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
VP_T_E1_Is, VP_T_E1_Set,
#endif
#if HAS_HEATED_BED
@@ -87,7 +87,7 @@ const uint16_t VPList_Status[] PROGMEM = {
#if HAS_HOTEND
VP_T_E0_Is, VP_T_E0_Set,
#endif
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
VP_T_E1_Is, VP_T_E1_Set,
#endif
#if HAS_HEATED_BED
@@ -120,7 +120,7 @@ const uint16_t VPList_Preheat[] PROGMEM = {
#if HAS_HOTEND
VP_T_E0_Is, VP_T_E0_Set,
#endif
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
VP_T_E1_Is, VP_T_E1_Set,
#endif
#if HAS_HEATED_BED
@@ -187,7 +187,7 @@ const uint16_t VPList_SD_PrintManipulation[] PROGMEM = {
#if HAS_HOTEND
VP_T_E0_Is, VP_T_E0_Set,
#endif
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
VP_T_E1_Is, VP_T_E1_Set,
#endif
#if HAS_HEATED_BED
@@ -379,7 +379,7 @@ const struct DGUS_VP_Variable ListOfVP[] PROGMEM = {
VPHELPER(VP_E0_FILAMENT_LOAD_UNLOAD, nullptr, ScreenHandler.HandleFilamentOption, ScreenHandler.HandleFilamentLoadUnload),
#endif
#endif
#if HOTENDS >= 2
#if HAS_MULTI_HOTEND
VPHELPER(VP_T_E1_Is, &thermalManager.temp_hotend[1].celsius, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<0>),
VPHELPER(VP_T_E1_Set, &thermalManager.temp_hotend[1].target, ScreenHandler.HandleTemperatureChanged, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
VPHELPER(VP_Flowrate_E1, &planner.flow_percentage[ExtUI::extruder_t::E1], ScreenHandler.HandleFlowRateChanged, ScreenHandler.DGUSLCD_SendWordValueToDisplay), // ERROR: Flow is per-extruder, not per-hotend

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