diff --git a/.github/workflows/ci-build-tests.yml b/.github/workflows/ci-build-tests.yml index 546faa5f38..edd69c1c15 100644 --- a/.github/workflows/ci-build-tests.yml +++ b/.github/workflows/ci-build-tests.yml @@ -37,6 +37,7 @@ jobs: runs-on: ubuntu-latest strategy: + fail-fast: true matrix: test-platform: diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 06fea21614..414ea24454 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -3424,7 +3424,9 @@ #define BUTTON_DELAY_EDIT 50 // (ms) Button repeat delay for edit screens #define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus - //#define DISABLE_ENCODER // Disable the click encoder, if any + #if ANY(TFT_CLASSIC_UI, TFT_COLOR_UI) + //#define NO_BACK_MENU_ITEM // Don't display a top menu item to go back to the parent menu + #endif #define TOUCH_SCREEN_CALIBRATION diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 853d597a92..74528ac635 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -603,7 +603,9 @@ * (Does not work on Sanguinololu with FAN_SOFT_PWM.) */ #define FAN_KICKSTART_TIME 100 // (ms) -#define FAN_KICKSTART_POWER 180 // 64-255 +#define FAN_KICKSTART_POWER 255 // 64-255 +//#define FAN_KICKSTART_LINEAR // Set kickstart time linearly based on the speed, e.g., for 20% (51) it will be FAN_KICKSTART_TIME * 0.2. + // Useful for quick speed up to low speed. Kickstart power must be set to 255. // Some coolers may require a non-zero "off" state. //#define FAN_OFF_PWM 1 @@ -1331,8 +1333,6 @@ //#define CALIBRATION_SCRIPT_PRE "M117 Starting Auto-Calibration\nT0\nG28\nG12\nM117 Calibrating..." //#define CALIBRATION_SCRIPT_POST "M500\nM117 Calibration data saved" - #define CALIBRATION_MEASUREMENT_RESOLUTION 0.01 // mm - #define CALIBRATION_FEEDRATE_SLOW 60 // mm/min #define CALIBRATION_FEEDRATE_FAST 1200 // mm/min #define CALIBRATION_FEEDRATE_TRAVEL 3000 // mm/min @@ -2329,6 +2329,7 @@ * * Control extrusion rate based on instantaneous extruder velocity. Can be used to correct for * underextrusion at high extruder speeds that are otherwise well-behaved (i.e., not skipping). + * For better results also enable ADAPTIVE_STEP_SMOOTHING. */ //#define NONLINEAR_EXTRUSION @@ -2556,27 +2557,28 @@ //#define MINIMUM_STEPPER_PRE_DIR_DELAY 650 /** - * Minimum stepper driver pulse width (in µs) - * 0 : Smallest possible width the MCU can produce, compatible with TMC2xxx drivers - * 0 : Minimum 500ns for LV8729, adjusted in stepper.h - * 1 : Minimum for A4988 and A5984 stepper drivers - * 2 : Minimum for DRV8825 stepper drivers - * 3 : Minimum for TB6600 stepper drivers - * 30 : Minimum for TB6560 stepper drivers + * Minimum stepper driver pulse width (in ns) + * If undefined, these defaults (from Conditionals_adv.h) apply: + * 100 : Minimum for TMC2xxx stepper drivers + * 500 : Minimum for LV8729 + * 1000 : Minimum for A4988 and A5984 stepper drivers + * 2000 : Minimum for DRV8825 stepper drivers + * 3000 : Minimum for TB6600 stepper drivers + * 30000 : Minimum for TB6560 stepper drivers * * Override the default value based on the driver type set in Configuration.h. */ -#define MINIMUM_STEPPER_PULSE 10 +#define MINIMUM_STEPPER_PULSE_NS 3500 /** * Maximum stepping rate (in Hz) the stepper driver allows - * If undefined, defaults to 1MHz / (2 * MINIMUM_STEPPER_PULSE) + * If undefined, these defaults (from Conditionals_adv.h) apply: * 5000000 : Maximum for TMC2xxx stepper drivers * 1000000 : Maximum for LV8729 stepper driver - * 500000 : Maximum for A4988 stepper driver - * 250000 : Maximum for DRV8825 stepper driver - * 150000 : Maximum for TB6600 stepper driver - * 15000 : Maximum for TB6560 stepper driver + * 500000 : Maximum for A4988 stepper driver + * 250000 : Maximum for DRV8825 stepper driver + * 150000 : Maximum for TB6600 stepper driver + * 15000 : Maximum for TB6560 stepper driver * * Override the default value based on the driver type set in Configuration.h. */ diff --git a/Marlin/Version.h b/Marlin/Version.h index e24e66077b..0cf58aea3e 100644 --- a/Marlin/Version.h +++ b/Marlin/Version.h @@ -41,7 +41,7 @@ * here we define this default string as the date where the latest release * version was tagged. */ -//#define STRING_DISTRIBUTION_DATE "2024-05-24" +//#define STRING_DISTRIBUTION_DATE "2024-07-07" /** * Defines a generic printer name to be output to the LCD after booting Marlin. diff --git a/Marlin/src/HAL/AVR/HAL.h b/Marlin/src/HAL/AVR/HAL.h index 3c883b645c..717bc7e3fe 100644 --- a/Marlin/src/HAL/AVR/HAL.h +++ b/Marlin/src/HAL/AVR/HAL.h @@ -141,7 +141,7 @@ typedef Servo hal_servo_t; #error "LCD_SERIAL_PORT must be from 0 to 3." #endif #define LCD_SERIAL lcdSerial - #if HAS_DGUS_LCD + #if ANY(HAS_DGUS_LCD, EXTENSIBLE_UI) #define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.get_tx_buffer_free() #endif #endif @@ -159,7 +159,7 @@ typedef Servo hal_servo_t; #define GET_PIN_MAP_INDEX(pin) pin #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) -#define HAL_SENSITIVE_PINS 0, 1, +#define HAL_SENSITIVE_PINS 0, 1 #ifdef __AVR_AT90USB1286__ #define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0) diff --git a/Marlin/src/HAL/AVR/MarlinSerial.cpp b/Marlin/src/HAL/AVR/MarlinSerial.cpp index 986462437c..dabcfb5239 100644 --- a/Marlin/src/HAL/AVR/MarlinSerial.cpp +++ b/Marlin/src/HAL/AVR/MarlinSerial.cpp @@ -629,7 +629,7 @@ MSerialT1 customizedSerial1(MSerialT1::HasEmergencyParser); template class MarlinSerial< LCDSerialCfg >; MSerialLCD lcdSerial(MSerialLCD::HasEmergencyParser); - #if HAS_DGUS_LCD + #if ANY(HAS_DGUS_LCD, EXTENSIBLE_UI) template typename MarlinSerial::ring_buffer_pos_t MarlinSerial::get_tx_buffer_free() { const ring_buffer_pos_t t = tx_buffer.tail, // next byte to send. diff --git a/Marlin/src/HAL/AVR/MarlinSerial.h b/Marlin/src/HAL/AVR/MarlinSerial.h index a40730e0a8..609aac5f4a 100644 --- a/Marlin/src/HAL/AVR/MarlinSerial.h +++ b/Marlin/src/HAL/AVR/MarlinSerial.h @@ -205,7 +205,7 @@ static ring_buffer_pos_t available(); static void write(const uint8_t c); static void flushTX(); - #if HAS_DGUS_LCD + #if ANY(HAS_DGUS_LCD, EXTENSIBLE_UI) static ring_buffer_pos_t get_tx_buffer_free(); #endif diff --git a/Marlin/src/HAL/AVR/endstop_interrupts.h b/Marlin/src/HAL/AVR/endstop_interrupts.h index 91cb336e24..a6813ff277 100644 --- a/Marlin/src/HAL/AVR/endstop_interrupts.h +++ b/Marlin/src/HAL/AVR/endstop_interrupts.h @@ -345,6 +345,14 @@ void setup_endstop_interrupts() { pciSetup(Z_MIN_PROBE_PIN); #endif #endif + #if USE_CALIBRATION + #if (digitalPinToInterrupt(CALIBRATION_PIN) != NOT_AN_INTERRUPT) + _ATTACH(CALIBRATION_PIN); + #else + static_assert(digitalPinHasPCICR(CALIBRATION_PIN), "CALIBRATION_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); + pciSetup(CALIBRATION_PIN); + #endif + #endif // If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI. } diff --git a/Marlin/src/HAL/AVR/fast_pwm.cpp b/Marlin/src/HAL/AVR/fast_pwm.cpp index 6da68e6245..936f9e5688 100644 --- a/Marlin/src/HAL/AVR/fast_pwm.cpp +++ b/Marlin/src/HAL/AVR/fast_pwm.cpp @@ -150,7 +150,7 @@ void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) { else { if (p == 32 || p == 128) continue; // Skip TIMER2 specific prescalers when not TIMER2 const uint16_t rft = (F_CPU) / (p * f_desired); - DEBUG_ECHOLNPGM("(Not Timer 2) F_CPU=" STRINGIFY(F_CPU), " prescaler=", p, " f_desired=", f_desired); + DEBUG_ECHOLNPGM("(Not Timer 2) F_CPU=", STRINGIFY(F_CPU), " prescaler=", p, " f_desired=", f_desired); res_fast_temp = rft - 1; res_pc_temp = rft / 2; } diff --git a/Marlin/src/HAL/AVR/fastio/fastio_1280.h b/Marlin/src/HAL/AVR/fastio/fastio_1280.h index 633774dda9..57d6181d2e 100644 --- a/Marlin/src/HAL/AVR/fastio/fastio_1280.h +++ b/Marlin/src/HAL/AVR/fastio/fastio_1280.h @@ -28,9 +28,6 @@ * Port : E0 E1 E4 E5 G5 E3 H3 H4 H5 H6 B4 B5 B6 B7 J1 J0 H1 H0 D3 D2 D1 D0 A0 A1 A2 A3 A4 A5 A6 A7 C7 C6 C5 C4 C3 C2 C1 C0 D7 G2 G1 G0 L7 L6 L5 L4 L3 L2 L1 L0 B3 B2 B1 B0 F0 F1 F2 F3 F4 F5 F6 F7 K0 K1 K2 K3 K4 K5 K6 K7 | E2 E6 E7 xx xx H2 H7 G3 G4 xx xx xx xx xx D4 D5 D6 xx xx J2 J3 J4 J5 J6 J7 xx xx xx xx xx * Logical Pin : 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 78 79 80 xx xx 84 85 71 70 xx xx xx xx xx 81 82 83 xx xx 72 73 75 76 77 74 xx xx xx xx xx * Analog Input : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - * - * Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA - * AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg */ #include "../fastio.h" diff --git a/Marlin/src/HAL/AVR/fastio/fastio_1281.h b/Marlin/src/HAL/AVR/fastio/fastio_1281.h index 6067248978..fdff219ec3 100644 --- a/Marlin/src/HAL/AVR/fastio/fastio_1281.h +++ b/Marlin/src/HAL/AVR/fastio/fastio_1281.h @@ -26,9 +26,6 @@ * * Logical Pin: 38 39 40 41 42 43 44 45 16 10 11 12 06 07 08 09 30 31 32 33 34 35 36 37 17 18 19 20 21 22 23 24 00 01 13 05 02 03 14 15 46 47 48 49 50 51 52 53 25 26 27 28 29 04 * Port: A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 E0 E1 E2 E3 E4 E5 E6 E7 F0 F1 F2 F3 F4 F5 F6 F7 G0 G1 G2 G3 G4 G5 - * - * Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA - * AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg */ #include "../fastio.h" diff --git a/Marlin/src/HAL/AVR/fastio/fastio_168.h b/Marlin/src/HAL/AVR/fastio/fastio_168.h index cc55979740..36dc552385 100644 --- a/Marlin/src/HAL/AVR/fastio/fastio_168.h +++ b/Marlin/src/HAL/AVR/fastio/fastio_168.h @@ -26,9 +26,6 @@ * * Logical Pin: 08 09 10 11 12 13 14 15 16 17 18 19 20 21 00 01 02 03 04 05 06 07 * Port: B0 B1 B2 B3 B4 B5 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 - * - * Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA - * AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg */ #include "../fastio.h" diff --git a/Marlin/src/HAL/AVR/fastio/fastio_644.h b/Marlin/src/HAL/AVR/fastio/fastio_644.h index 94b322a819..e20a3d345e 100644 --- a/Marlin/src/HAL/AVR/fastio/fastio_644.h +++ b/Marlin/src/HAL/AVR/fastio/fastio_644.h @@ -26,9 +26,6 @@ * * Logical Pin: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 * Port: B0 B1 B2 B3 B4 B5 B6 B7 D0 D1 D2 D3 D4 D5 D6 D7 C0 C1 C2 C3 C4 C5 C6 C7 A7 A6 A5 A4 A3 A2 A1 A0 - * - * Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA - * AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg */ /** ATMega644 diff --git a/Marlin/src/HAL/AVR/fastio/fastio_AT90USB.h b/Marlin/src/HAL/AVR/fastio/fastio_AT90USB.h index 51c5e09658..ee250b1786 100644 --- a/Marlin/src/HAL/AVR/fastio/fastio_AT90USB.h +++ b/Marlin/src/HAL/AVR/fastio/fastio_AT90USB.h @@ -27,9 +27,6 @@ * Logical Pin: 28 29 30 31 32 33 34 35 20 21 22 23 24 25 26 27 10 11 12 13 14 15 16 17 00 01 02 03 04 05 06 07 08 09(46*47)36 37 18 19 38 39 40 41 42 43 44 45 * Port: A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 E0 E1 E2 E3 E4 E5 E6 E7 F0 F1 F2 F3 F4 F5 F6 F7 * The logical pins 46 and 47 are not supported by Teensyduino, but are supported below as E2 and E3 - * - * Arduino Pin Layout video: https://youtu.be/rIqeVCX09FA - * AVR alternate pin function overview video: https://youtu.be/1yd8wuI5Plg */ #include "../fastio.h" diff --git a/Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp b/Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp index 131174b06c..9617c9544d 100644 --- a/Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp +++ b/Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp @@ -120,7 +120,7 @@ void u8g_spiSend_sw_AVR_mode_3(uint8_t val) { U8G_ATOMIC_END(); } -#if ENABLED(FYSETC_MINI_12864) +#if U8G_SPI_USE_MODE_3 #define SPISEND_SW_AVR u8g_spiSend_sw_AVR_mode_3 #else #define SPISEND_SW_AVR u8g_spiSend_sw_AVR_mode_0 @@ -143,9 +143,9 @@ uint8_t u8g_com_HAL_AVR_sw_sp_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void break; case U8G_COM_MSG_CHIP_SELECT: - #if ENABLED(FYSETC_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0 - if (arg_val) { // SCK idle state needs to be set to the proper idle state before - // the next chip select goes active + #if U8G_SPI_USE_MODE_3 // LCD SPI is running mode 3 while SD card is running mode 0 + if (arg_val) { // SCK idle state needs to be set to the proper idle state before + // the next chip select goes active u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW); } diff --git a/Marlin/src/HAL/DUE/endstop_interrupts.h b/Marlin/src/HAL/DUE/endstop_interrupts.h index 954eb625a5..798ca4f0cb 100644 --- a/Marlin/src/HAL/DUE/endstop_interrupts.h +++ b/Marlin/src/HAL/DUE/endstop_interrupts.h @@ -64,6 +64,7 @@ void setup_endstop_interrupts() { TERN_(USE_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(USE_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(USE_Z_MIN_PROBE, _ATTACH(Z_MIN_PROBE_PIN)); + TERN_(USE_CALIBRATION, _ATTACH(CALIBRATION_PIN)); TERN_(USE_I_MAX, _ATTACH(I_MAX_PIN)); TERN_(USE_I_MIN, _ATTACH(I_MIN_PIN)); TERN_(USE_J_MAX, _ATTACH(J_MAX_PIN)); diff --git a/Marlin/src/HAL/DUE/inc/SanityCheck.h b/Marlin/src/HAL/DUE/inc/SanityCheck.h index 1eaa2fbd8c..599e2aa464 100644 --- a/Marlin/src/HAL/DUE/inc/SanityCheck.h +++ b/Marlin/src/HAL/DUE/inc/SanityCheck.h @@ -68,16 +68,15 @@ * Usually the hardware SPI pins are only available to the LCD. This makes the DUE hard SPI used at the same time * as the TMC2130 soft SPI the most common setup. */ -#define _IS_HW_SPI(P) (defined(TMC_SPI_##P) && (TMC_SPI_##P == SD_MOSI_PIN || TMC_SPI_##P == SD_MISO_PIN || TMC_SPI_##P == SD_SCK_PIN)) - #if HAS_MEDIA && HAS_DRIVER(TMC2130) - #if ENABLED(TMC_USE_SW_SPI) - #if DISABLED(SOFTWARE_SPI) && (_IS_HW_SPI(MOSI) || _IS_HW_SPI(MISO) || _IS_HW_SPI(SCK)) - #error "DUE hardware SPI is required but is incompatible with TMC2130 software SPI. Either disable TMC_USE_SW_SPI or use separate pins for the two SPIs." - #endif - #elif ENABLED(SOFTWARE_SPI) + #define _IS_HW_SPI(P) (defined(TMC_SPI_##P) && (TMC_SPI_##P == SD_MOSI_PIN || TMC_SPI_##P == SD_MISO_PIN || TMC_SPI_##P == SD_SCK_PIN)) + #if DISABLED(SOFTWARE_SPI) && ENABLED(TMC_USE_SW_SPI) && (_IS_HW_SPI(MOSI) || _IS_HW_SPI(MISO) || _IS_HW_SPI(SCK)) + #error "DUE hardware SPI is required but is incompatible with TMC2130 software SPI. Either disable TMC_USE_SW_SPI or use separate pins for the two SPIs." + #endif + #if ENABLED(SOFTWARE_SPI) && DISABLED(TMC_USE_SW_SPI) #error "DUE software SPI is required but is incompatible with TMC2130 hardware SPI. Enable TMC_USE_SW_SPI to fix." #endif + #undef _IS_HW_SPI #endif #if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY diff --git a/Marlin/src/HAL/DUE/spi_pins.h b/Marlin/src/HAL/DUE/spi_pins.h index 41ac7a8b58..7f0b1290b1 100644 --- a/Marlin/src/HAL/DUE/spi_pins.h +++ b/Marlin/src/HAL/DUE/spi_pins.h @@ -24,7 +24,7 @@ /** * Define SPI Pins: SCK, MISO, MOSI, SS * - * Available chip select pins for HW SPI are 4 10 52 77 + * Available chip select pins for HW SPI are 4 10 52 77 87 */ #if SDSS == 4 || SDSS == 10 || SDSS == 52 || SDSS == 77 || SDSS == 87 #if SDSS == 4 diff --git a/Marlin/src/HAL/DUE/u8g/u8g_com_HAL_DUE_sw_spi.cpp b/Marlin/src/HAL/DUE/u8g/u8g_com_HAL_DUE_sw_spi.cpp index 68e3e74a45..a8f4dd2b03 100644 --- a/Marlin/src/HAL/DUE/u8g/u8g_com_HAL_DUE_sw_spi.cpp +++ b/Marlin/src/HAL/DUE/u8g/u8g_com_HAL_DUE_sw_spi.cpp @@ -66,7 +66,7 @@ #include -#if ENABLED(FYSETC_MINI_12864) +#if U8G_SPI_USE_MODE_3 #define SPISEND_SW_DUE u8g_spiSend_sw_DUE_mode_3 #else #define SPISEND_SW_DUE u8g_spiSend_sw_DUE_mode_0 @@ -96,15 +96,15 @@ uint8_t u8g_com_HAL_DUE_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void break; case U8G_COM_MSG_CHIP_SELECT: - #if ENABLED(FYSETC_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0 - if (arg_val) { // SCK idle state needs to be set to the proper idle state before - // the next chip select goes active - u8g_SetPILevel_DUE(u8g, U8G_PI_SCK, 1); //set SCK to mode 3 idle state before CS goes active + #if U8G_SPI_USE_MODE_3 // LCD SPI is running mode 3 while SD card is running mode 0 + if (arg_val) { // SCK idle state needs to be set to the proper idle state before + // the next chip select goes active + u8g_SetPILevel_DUE(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active u8g_SetPILevel_DUE(u8g, U8G_PI_CS, LOW); } else { u8g_SetPILevel_DUE(u8g, U8G_PI_CS, HIGH); - u8g_SetPILevel_DUE(u8g, U8G_PI_SCK, 0); //set SCK to mode 0 idle state after CS goes inactive + u8g_SetPILevel_DUE(u8g, U8G_PI_SCK, 0); // Set SCK to mode 0 idle state after CS goes inactive } #else u8g_SetPILevel_DUE(u8g, U8G_PI_CS, !arg_val); diff --git a/Marlin/src/HAL/DUE/upload_extra_script.py b/Marlin/src/HAL/DUE/upload_extra_script.py index ca12b3b54f..729b1d67de 100644 --- a/Marlin/src/HAL/DUE/upload_extra_script.py +++ b/Marlin/src/HAL/DUE/upload_extra_script.py @@ -11,7 +11,7 @@ if pioutil.is_pio_build(): if current_OS == 'Windows': - Import("env") + env = pioutil.env # Use bossac.exe on Windows env.Replace( diff --git a/Marlin/src/HAL/ESP32/endstop_interrupts.h b/Marlin/src/HAL/ESP32/endstop_interrupts.h index 1377345992..8b88f1f41f 100644 --- a/Marlin/src/HAL/ESP32/endstop_interrupts.h +++ b/Marlin/src/HAL/ESP32/endstop_interrupts.h @@ -59,6 +59,7 @@ void setup_endstop_interrupts() { TERN_(USE_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(USE_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(USE_Z_MIN_PROBE, _ATTACH(Z_MIN_PROBE_PIN)); + TERN_(USE_CALIBRATION, _ATTACH(CALIBRATION_PIN)); TERN_(USE_I_MAX, _ATTACH(I_MAX_PIN)); TERN_(USE_I_MIN, _ATTACH(I_MIN_PIN)); TERN_(USE_J_MAX, _ATTACH(J_MAX_PIN)); diff --git a/Marlin/src/HAL/HC32/endstop_interrupts.cpp b/Marlin/src/HAL/HC32/endstop_interrupts.cpp index 99987ec76f..06c4d0e186 100644 --- a/Marlin/src/HAL/HC32/endstop_interrupts.cpp +++ b/Marlin/src/HAL/HC32/endstop_interrupts.cpp @@ -101,12 +101,14 @@ void setup_endstop_interrupts() { SETUP(Z_MIN_PROBE); + SETUP(CALIBRATION); + #undef SETUP } // Ensure 1 - 10 IRQs are registered // Disable some endstops if you encounter this error -#define ENDSTOPS_INTERRUPTS_COUNT COUNT_ENABLED(USE_X_MAX, USE_X_MIN, USE_X2_MAX, USE_X2_MIN, USE_Y_MAX, USE_Y_MIN, USE_Y2_MAX, USE_Y2_MIN, USE_Z_MAX, USE_Z_MIN, USE_Z2_MAX, USE_Z2_MIN, USE_Z3_MAX, USE_Z3_MIN, USE_Z4_MAX, USE_Z4_MIN, USE_Z_MIN_PROBE) +#define ENDSTOPS_INTERRUPTS_COUNT COUNT_ENABLED(USE_X_MAX, USE_X_MIN, USE_X2_MAX, USE_X2_MIN, USE_Y_MAX, USE_Y_MIN, USE_Y2_MAX, USE_Y2_MIN, USE_Z_MAX, USE_Z_MIN, USE_Z2_MAX, USE_Z2_MIN, USE_Z3_MAX, USE_Z3_MIN, USE_Z4_MAX, USE_Z4_MIN, USE_Z_MIN_PROBE, USE_CALIBRATION) #if ENDSTOPS_INTERRUPTS_COUNT > 10 #error "Too many endstop interrupts! HC32F460 only supports 10 endstop interrupts." #elif ENDSTOPS_INTERRUPTS_COUNT == 0 diff --git a/Marlin/src/HAL/HC32/u8g/u8g_com_HAL_HC32_sw_spi.cpp b/Marlin/src/HAL/HC32/u8g/u8g_com_HAL_HC32_sw_spi.cpp index 9f36096194..97f4b85eaf 100644 --- a/Marlin/src/HAL/HC32/u8g/u8g_com_HAL_HC32_sw_spi.cpp +++ b/Marlin/src/HAL/HC32/u8g/u8g_com_HAL_HC32_sw_spi.cpp @@ -82,7 +82,7 @@ static inline uint8_t swSpiTransfer_mode_3(uint8_t b, const uint8_t spi_speed, c } static void u8g_sw_spi_shift_out(uint8_t val) { - #if ANY(FYSETC_MINI_12864, MKS_MINI_12864) + #if U8G_SPI_USE_MODE_3 swSpiTransfer_mode_3(val, SPI_speed); #else swSpiTransfer_mode_0(val, SPI_speed); @@ -116,15 +116,15 @@ uint8_t u8g_com_HAL_HC32_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, voi break; case U8G_COM_MSG_CHIP_SELECT: - #if ANY(FYSETC_MINI_12864, MKS_MINI_12864) // This LCD SPI is running mode 3 while SD card is running mode 0 - if (arg_val) { // SCK idle state needs to be set to the proper idle state before - // the next chip select goes active - WRITE(DOGLCD_SCK, HIGH); // Set SCK to mode 3 idle state before CS goes active + #if U8G_SPI_USE_MODE_3 // This LCD SPI is running mode 3 while SD card is running mode 0 + if (arg_val) { // SCK idle state needs to be set to the proper idle state before + // the next chip select goes active + WRITE(DOGLCD_SCK, HIGH); // Set SCK to mode 3 idle state before CS goes active WRITE(DOGLCD_CS, LOW); } else { WRITE(DOGLCD_CS, HIGH); - WRITE(DOGLCD_SCK, LOW); // Set SCK to mode 0 idle state after CS goes inactive + WRITE(DOGLCD_SCK, LOW); // Set SCK to mode 0 idle state after CS goes inactive } #else WRITE(DOGLCD_CS, !arg_val); diff --git a/Marlin/src/HAL/LINUX/spi_pins.h b/Marlin/src/HAL/LINUX/spi_pins.h index 607b964281..4139c8f898 100644 --- a/Marlin/src/HAL/LINUX/spi_pins.h +++ b/Marlin/src/HAL/LINUX/spi_pins.h @@ -28,12 +28,6 @@ // spiBeginTransaction. #endif -// Onboard SD -//#define SD_SCK_PIN P0_07 -//#define SD_MISO_PIN P0_08 -//#define SD_MOSI_PIN P0_09 -//#define SD_SS_PIN P0_06 - // External SD #ifndef SD_SCK_PIN #define SD_SCK_PIN 50 diff --git a/Marlin/src/HAL/LPC1768/HAL.h b/Marlin/src/HAL/LPC1768/HAL.h index ab28e06eb8..dfa090210f 100644 --- a/Marlin/src/HAL/LPC1768/HAL.h +++ b/Marlin/src/HAL/LPC1768/HAL.h @@ -100,7 +100,7 @@ extern DefaultSerial1 USBSerial; #else #error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB." #endif - #if HAS_DGUS_LCD + #if ANY(HAS_DGUS_LCD, EXTENSIBLE_UI) #define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.available() #endif #endif @@ -159,7 +159,7 @@ constexpr pin_t GET_PIN_MAP_PIN(const int16_t index) { // Parse a G-code word into a pin index int16_t PARSED_PIN_INDEX(const char code, const int16_t dval); // P0.6 thru P0.9 are for the onboard SD card -#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09, +#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09 // ------------------------ // Defines diff --git a/Marlin/src/HAL/LPC1768/endstop_interrupts.h b/Marlin/src/HAL/LPC1768/endstop_interrupts.h index 7a67b958b4..2c75fe6986 100644 --- a/Marlin/src/HAL/LPC1768/endstop_interrupts.h +++ b/Marlin/src/HAL/LPC1768/endstop_interrupts.h @@ -146,6 +146,12 @@ void setup_endstop_interrupts() { #endif _ATTACH(Z_MIN_PROBE_PIN); #endif + #if USE_CALIBRATION + #if !LPC1768_PIN_INTERRUPT_M(CALIBRATION_PIN) + #error "CALIBRATION_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." + #endif + _ATTACH(CALIBRATION_PIN); + #endif #if USE_I_MAX #if !LPC1768_PIN_INTERRUPT_M(I_MAX_PIN) #error "I_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." diff --git a/Marlin/src/HAL/LPC1768/fast_pwm.cpp b/Marlin/src/HAL/LPC1768/fast_pwm.cpp index 6d2b1a9002..7cb212f5f9 100644 --- a/Marlin/src/HAL/LPC1768/fast_pwm.cpp +++ b/Marlin/src/HAL/LPC1768/fast_pwm.cpp @@ -26,8 +26,10 @@ void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { if (!LPC176x::pin_is_valid(pin)) return; - if (LPC176x::pwm_attach_pin(pin)) - LPC176x::pwm_write_ratio(pin, invert ? 1.0f - (float)v / v_size : (float)v / v_size); // map 1-254 onto PWM range + if (LPC176x::pwm_attach_pin(pin)) { + const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, LPC176x::pwm_get_period(pin)); + LPC176x::pwm_write(pin, duty); + } } void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) { diff --git a/Marlin/src/HAL/LPC1768/fastio.h b/Marlin/src/HAL/LPC1768/fastio.h index c553ffb182..4858334080 100644 --- a/Marlin/src/HAL/LPC1768/fastio.h +++ b/Marlin/src/HAL/LPC1768/fastio.h @@ -66,7 +66,7 @@ #define _WRITE(IO,V) WRITE_PIN(IO,V) /// toggle a pin -#define _TOGGLE(IO) _WRITE(IO, !READ(IO)) +#define _TOGGLE(IO) LPC176x::gpio_toggle(IO) /// set pin as input #define _SET_INPUT(IO) SET_DIR_INPUT(IO) diff --git a/Marlin/src/HAL/LPC1768/spi_pins.h b/Marlin/src/HAL/LPC1768/spi_pins.h index 295d6462fd..e52f78a7cb 100644 --- a/Marlin/src/HAL/LPC1768/spi_pins.h +++ b/Marlin/src/HAL/LPC1768/spi_pins.h @@ -28,12 +28,13 @@ // spiBeginTransaction. #endif -/** onboard SD card */ -//#define SD_SCK_PIN P0_07 -//#define SD_MISO_PIN P0_08 -//#define SD_MOSI_PIN P0_09 -//#define SD_SS_PIN P0_06 -/** external */ +// Onboard SD +//#define SD_SCK_PIN P0_07 +//#define SD_MISO_PIN P0_08 +//#define SD_MOSI_PIN P0_09 +//#define SD_SS_PIN P0_06 + +// External SD #ifndef SD_SCK_PIN #define SD_SCK_PIN P0_15 #endif diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp index 4edd0d3886..77e5870de7 100644 --- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp +++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp @@ -132,7 +132,7 @@ uint8_t swSpiTransfer_mode_3(uint8_t b, const uint8_t spi_speed, const pin_t sck static uint8_t SPI_speed = 0; static void u8g_sw_spi_shift_out(uint8_t dataPin, uint8_t clockPin, uint8_t val) { - #if ANY(FYSETC_MINI_12864, MKS_MINI_12864) + #if U8G_SPI_USE_MODE_3 swSpiTransfer_mode_3(val, SPI_speed, clockPin, -1, dataPin); #else swSpiTransfer_mode_0(val, SPI_speed, clockPin, -1, dataPin); @@ -160,15 +160,15 @@ uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, break; case U8G_COM_MSG_CHIP_SELECT: - #if ANY(FYSETC_MINI_12864, MKS_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0 - if (arg_val) { // SCK idle state needs to be set to the proper idle state before - // the next chip select goes active - u8g_SetPILevel(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active + #if U8G_SPI_USE_MODE_3 // LCD SPI is running mode 3 while SD card is running mode 0 + if (arg_val) { // SCK idle state needs to be set to the proper idle state before + // the next chip select goes active + u8g_SetPILevel(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active u8g_SetPILevel(u8g, U8G_PI_CS, LOW); } else { u8g_SetPILevel(u8g, U8G_PI_CS, HIGH); - u8g_SetPILevel(u8g, U8G_PI_SCK, 0); // Set SCK to mode 0 idle state after CS goes inactive + u8g_SetPILevel(u8g, U8G_PI_SCK, 0); // Set SCK to mode 0 idle state after CS goes inactive } #else u8g_SetPILevel(u8g, U8G_PI_CS, !arg_val); diff --git a/Marlin/src/HAL/LPC1768/upload_extra_script.py b/Marlin/src/HAL/LPC1768/upload_extra_script.py index efd46fdd63..b788a2bd1d 100755 --- a/Marlin/src/HAL/LPC1768/upload_extra_script.py +++ b/Marlin/src/HAL/LPC1768/upload_extra_script.py @@ -13,9 +13,9 @@ if pioutil.is_pio_build(): target_drive = "REARM" import platform - current_OS = platform.system() - Import("env") + + env = pioutil.env def print_error(e): print('\nUnable to find destination disk (%s)\n' \ diff --git a/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_sw_spi.cpp b/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_sw_spi.cpp index 9184e2f618..f984983b40 100644 --- a/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_sw_spi.cpp +++ b/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_sw_spi.cpp @@ -131,7 +131,7 @@ static uint8_t swSpiInit(const uint8_t spi_speed, const uint8_t clk_pin, const u } static void u8g_sw_spi_shift_out(uint8_t dataPin, uint8_t clockPin, uint8_t val) { - #if ANY(FYSETC_MINI_12864, MKS_MINI_12864) + #if U8G_SPI_USE_MODE_3 swSpiTransfer_mode_3(val, SPI_speed, clockPin, -1, dataPin); #else swSpiTransfer_mode_0(val, SPI_speed, clockPin, -1, dataPin); @@ -159,15 +159,15 @@ uint8_t u8g_com_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_pt break; case U8G_COM_MSG_CHIP_SELECT: - #if ANY(FYSETC_MINI_12864, MKS_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0 - if (arg_val) { // SCK idle state needs to be set to the proper idle state before - // the next chip select goes active - u8g_SetPILevel(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active + #if U8G_SPI_USE_MODE_3 // LCD SPI is running mode 3 while SD card is running mode 0 + if (arg_val) { // SCK idle state needs to be set to the proper idle state before + // the next chip select goes active + u8g_SetPILevel(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active u8g_SetPILevel(u8g, U8G_PI_CS, LOW); } else { u8g_SetPILevel(u8g, U8G_PI_CS, HIGH); - u8g_SetPILevel(u8g, U8G_PI_SCK, 0); // Set SCK to mode 0 idle state after CS goes inactive + u8g_SetPILevel(u8g, U8G_PI_SCK, 0); // Set SCK to mode 0 idle state after CS goes inactive } #else u8g_SetPILevel(u8g, U8G_PI_CS, !arg_val); diff --git a/Marlin/src/HAL/SAMD21/endstop_interrupts.h b/Marlin/src/HAL/SAMD21/endstop_interrupts.h index 37fdb7504b..4ef075f8f9 100644 --- a/Marlin/src/HAL/SAMD21/endstop_interrupts.h +++ b/Marlin/src/HAL/SAMD21/endstop_interrupts.h @@ -83,6 +83,7 @@ #define MATCH_Z4_MAX_EILINE(P) TERN0(USE_Z4_MAX, DEFER4(MATCH_EILINE)(P, Z4_MAX_PIN)) #define MATCH_Z4_MIN_EILINE(P) TERN0(USE_Z4_MIN, DEFER4(MATCH_EILINE)(P, Z4_MIN_PIN)) #define MATCH_Z_MIN_PROBE_EILINE(P) TERN0(USE_Z_MIN_PROBE, DEFER4(MATCH_EILINE)(P, Z_MIN_PROBE_PIN)) +#define MATCH_CALIBRATION_EILINE(P) TERN0(USE_CALIBRATION, DEFER4(MATCH_EILINE)(P, CALIBRATION_PIN)) #define AVAILABLE_EILINE(P) ( PIN_TO_EILINE(P) != -1 \ && !MATCH_X_MAX_EILINE(P) && !MATCH_X_MIN_EILINE(P) \ @@ -99,7 +100,8 @@ && !MATCH_Z2_MAX_EILINE(P) && !MATCH_Z2_MIN_EILINE(P) \ && !MATCH_Z3_MAX_EILINE(P) && !MATCH_Z3_MIN_EILINE(P) \ && !MATCH_Z4_MAX_EILINE(P) && !MATCH_Z4_MIN_EILINE(P) \ - && !MATCH_Z_MIN_PROBE_EILINE(P) ) + && !MATCH_Z_MIN_PROBE_EILINE(P) \ + && !MATCH_CALIBRATION_EILINE(P) ) // One ISR for all EXT-Interrupts void endstop_ISR() { endstops.update(); } @@ -208,6 +210,12 @@ void setup_endstop_interrupts() { #endif _ATTACH(Z_MIN_PROBE_PIN); #endif + #if USE_CALIBRATION + #if !AVAILABLE_EILINE(CALIBRATION_PIN) + #error "CALIBRATION_PIN has no EXTINT line available. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." + #endif + _ATTACH(CALIBRATION_PIN); + #endif #if USE_I_MAX #if !AVAILABLE_EILINE(I_MAX_PIN) #error "I_MAX_PIN has no EXTINT line available. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." diff --git a/Marlin/src/HAL/SAMD51/endstop_interrupts.h b/Marlin/src/HAL/SAMD51/endstop_interrupts.h index 84b6c46da9..34c238ba5c 100644 --- a/Marlin/src/HAL/SAMD51/endstop_interrupts.h +++ b/Marlin/src/HAL/SAMD51/endstop_interrupts.h @@ -82,6 +82,7 @@ #define MATCH_Z4_MAX_EILINE(P) TERN0(USE_Z4_MAX, DEFER4(MATCH_EILINE)(P, Z4_MAX_PIN)) #define MATCH_Z4_MIN_EILINE(P) TERN0(USE_Z4_MIN, DEFER4(MATCH_EILINE)(P, Z4_MIN_PIN)) #define MATCH_Z_MIN_PROBE_EILINE(P) TERN0(USE_Z_MIN_PROBE, DEFER4(MATCH_EILINE)(P, Z_MIN_PROBE_PIN)) +#define MATCH_CALIBRATION_EILINE(P) TERN0(USE_CALIBRATION, DEFER4(MATCH_EILINE)(P, CALIBRATION_PIN)) #define AVAILABLE_EILINE(P) ( PIN_TO_EILINE(P) != -1 \ && !MATCH_X_MAX_EILINE(P) && !MATCH_X_MIN_EILINE(P) \ @@ -98,7 +99,8 @@ && !MATCH_Z2_MAX_EILINE(P) && !MATCH_Z2_MIN_EILINE(P) \ && !MATCH_Z3_MAX_EILINE(P) && !MATCH_Z3_MIN_EILINE(P) \ && !MATCH_Z4_MAX_EILINE(P) && !MATCH_Z4_MIN_EILINE(P) \ - && !MATCH_Z_MIN_PROBE_EILINE(P) ) + && !MATCH_Z_MIN_PROBE_EILINE(P) \ + && !MATCH_CALIBRATION_EILINE(P) ) // One ISR for all EXT-Interrupts void endstop_ISR() { endstops.update(); } @@ -183,6 +185,12 @@ void setup_endstop_interrupts() { #endif _ATTACH(Z_MIN_PROBE_PIN); #endif + #if USE_CALIBRATION + #if !AVAILABLE_EILINE(CALIBRATION_PIN) + #error "CALIBRATION_PIN has no EXTINT line available. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." + #endif + _ATTACH(CALIBRATION_PIN); + #endif #if USE_I_MAX #if !AVAILABLE_EILINE(I_MAX_PIN) #error "I_MAX_PIN has no EXTINT line available. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." diff --git a/Marlin/src/HAL/STM32/HAL.h b/Marlin/src/HAL/STM32/HAL.h index 276f031685..9c74a95ff0 100644 --- a/Marlin/src/HAL/STM32/HAL.h +++ b/Marlin/src/HAL/STM32/HAL.h @@ -112,7 +112,7 @@ #else #error "LCD_SERIAL_PORT must be from 1 to 9, or -1 for Native USB." #endif - #if HAS_DGUS_LCD + #if ANY(HAS_DGUS_LCD, EXTENSIBLE_UI) #define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite() #endif #endif diff --git a/Marlin/src/HAL/STM32/HAL_SPI.cpp b/Marlin/src/HAL/STM32/HAL_SPI.cpp index cc035ecffa..b220ae6a78 100644 --- a/Marlin/src/HAL/STM32/HAL_SPI.cpp +++ b/Marlin/src/HAL/STM32/HAL_SPI.cpp @@ -37,7 +37,7 @@ static SPISettings spiConfig; // Public functions // ------------------------ -#if ENABLED(SOFTWARE_SPI) +#if ANY(SOFTWARE_SPI, FORCE_SOFT_SPI) // ------------------------ // Software SPI diff --git a/Marlin/src/HAL/STM32/dogm/u8g_com_stm32duino_swspi.cpp b/Marlin/src/HAL/STM32/dogm/u8g_com_stm32duino_swspi.cpp new file mode 100644 index 0000000000..68c6430538 --- /dev/null +++ b/Marlin/src/HAL/STM32/dogm/u8g_com_stm32duino_swspi.cpp @@ -0,0 +1,136 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2024 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm / Ryan Power + * + * 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 . + * + */ + +#ifdef HAL_STM32 + +#include "../../../inc/MarlinConfig.h" + +#if ALL(HAS_MARLINUI_U8GLIB, FORCE_SOFT_SPI) + +#include +#include "../../shared/HAL_SPI.h" + +#define nop asm volatile ("\tnop\n") + +static inline uint8_t swSpiTransfer_mode_0(uint8_t b) { + for (uint8_t i = 0; i < 8; ++i) { + const uint8_t state = (b & 0x80) ? HIGH : LOW; + WRITE(DOGLCD_SCK, HIGH); + WRITE(DOGLCD_MOSI, state); + b <<= 1; + WRITE(DOGLCD_SCK, LOW); + } + return b; +} + +static inline uint8_t swSpiTransfer_mode_3(uint8_t b) { + for (uint8_t i = 0; i < 8; ++i) { + const uint8_t state = (b & 0x80) ? HIGH : LOW; + WRITE(DOGLCD_SCK, LOW); + WRITE(DOGLCD_MOSI, state); + b <<= 1; + WRITE(DOGLCD_SCK, HIGH); + } + return b; +} + +static void u8g_sw_spi_shift_out(uint8_t val) { + #if U8G_SPI_USE_MODE_3 + swSpiTransfer_mode_3(val); + #else + swSpiTransfer_mode_0(val); + #endif +} + +static void swSpiInit() { + #if PIN_EXISTS(LCD_RESET) + SET_OUTPUT(LCD_RESET_PIN); + #endif + SET_OUTPUT(DOGLCD_A0); + OUT_WRITE(DOGLCD_SCK, LOW); + OUT_WRITE(DOGLCD_MOSI, LOW); + OUT_WRITE(DOGLCD_CS, HIGH); +} + +uint8_t u8g_com_HAL_STM32_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { + switch (msg) { + case U8G_COM_MSG_INIT: + swSpiInit(); + break; + + case U8G_COM_MSG_STOP: + break; + + case U8G_COM_MSG_RESET: + #if PIN_EXISTS(LCD_RESET) + WRITE(LCD_RESET_PIN, arg_val); + #endif + break; + + case U8G_COM_MSG_CHIP_SELECT: + #if U8G_SPI_USE_MODE_3 // This LCD SPI is running mode 3 while SD card is running mode 0 + if (arg_val) { // SCK idle state needs to be set to the proper idle state before + // the next chip select goes active + WRITE(DOGLCD_SCK, HIGH); // Set SCK to mode 3 idle state before CS goes active + WRITE(DOGLCD_CS, LOW); + nop; // hold SCK high for a few ns + nop; + } + else { + WRITE(DOGLCD_CS, HIGH); + WRITE(DOGLCD_SCK, LOW); // Set SCK to mode 0 idle state after CS goes inactive + } + #else + WRITE(DOGLCD_CS, !arg_val); + #endif + break; + + case U8G_COM_MSG_WRITE_BYTE: + u8g_sw_spi_shift_out(arg_val); + break; + + case U8G_COM_MSG_WRITE_SEQ: { + uint8_t *ptr = (uint8_t *)arg_ptr; + while (arg_val > 0) { + u8g_sw_spi_shift_out(*ptr++); + arg_val--; + } + } break; + + case U8G_COM_MSG_WRITE_SEQ_P: { + uint8_t *ptr = (uint8_t *)arg_ptr; + while (arg_val > 0) { + u8g_sw_spi_shift_out(u8g_pgm_read(ptr)); + ptr++; + arg_val--; + } + } break; + + case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ + WRITE(DOGLCD_A0, arg_val); + break; + } + return 1; +} + +#endif // HAS_MARLINUI_U8GLIB && FORCE_SOFT_SPI +#endif // HAL_STM32 diff --git a/Marlin/src/HAL/STM32/endstop_interrupts.h b/Marlin/src/HAL/STM32/endstop_interrupts.h index ab86bf29c2..e17b8a4c8e 100644 --- a/Marlin/src/HAL/STM32/endstop_interrupts.h +++ b/Marlin/src/HAL/STM32/endstop_interrupts.h @@ -45,6 +45,7 @@ void setup_endstop_interrupts() { TERN_(USE_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(USE_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(USE_Z_MIN_PROBE, _ATTACH(Z_MIN_PROBE_PIN)); + TERN_(USE_CALIBRATION, _ATTACH(CALIBRATION_PIN)); TERN_(USE_I_MAX, _ATTACH(I_MAX_PIN)); TERN_(USE_I_MIN, _ATTACH(I_MIN_PIN)); TERN_(USE_J_MAX, _ATTACH(J_MAX_PIN)); diff --git a/Marlin/src/HAL/STM32/inc/Conditionals_adv.h b/Marlin/src/HAL/STM32/inc/Conditionals_adv.h index 032716a294..f345b925bb 100644 --- a/Marlin/src/HAL/STM32/inc/Conditionals_adv.h +++ b/Marlin/src/HAL/STM32/inc/Conditionals_adv.h @@ -30,6 +30,3 @@ #undef F_CPU #define F_CPU BOARD_F_CPU #endif - -// The Sensitive Pins array is not optimizable -#define RUNTIME_ONLY_ANALOG_TO_DIGITAL diff --git a/Marlin/src/HAL/STM32/u8g/LCD_defines.h b/Marlin/src/HAL/STM32/u8g/LCD_defines.h index 35f1674d69..59b2b8839a 100644 --- a/Marlin/src/HAL/STM32/u8g/LCD_defines.h +++ b/Marlin/src/HAL/STM32/u8g/LCD_defines.h @@ -25,8 +25,8 @@ * STM32 LCD-specific defines */ -uint8_t u8g_com_std_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); // See U8glib-HAL -uint8_t u8g_com_stm32duino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); // See U8glib-HAL +uint8_t u8g_com_HAL_STM32_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); // u8g_com_stm32duino_swspi.cpp +#define U8G_COM_HAL_SW_SPI_FN u8g_com_HAL_STM32_sw_spi_fn -#define U8G_COM_HAL_SW_SPI_FN u8g_com_std_sw_spi_fn +uint8_t u8g_com_stm32duino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); // See U8glib-HAL #define U8G_COM_HAL_HW_SPI_FN u8g_com_stm32duino_hw_spi_fn diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h index 41c91e200f..007bf83b09 100644 --- a/Marlin/src/HAL/STM32F1/HAL.h +++ b/Marlin/src/HAL/STM32F1/HAL.h @@ -138,7 +138,7 @@ #define LCD_SERIAL MSERIAL(1) // dummy port static_assert(false, "LCD_SERIAL_PORT must be from 1 to " STRINGIFY(NUM_UARTS) ". You can also use -1 if the board supports Native USB.") #endif - #if HAS_DGUS_LCD + #if ANY(HAS_DGUS_LCD, EXTENSIBLE_UI) #define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite() #endif #endif diff --git a/Marlin/src/HAL/STM32F1/build_flags.py b/Marlin/src/HAL/STM32F1/build_flags.py deleted file mode 100755 index 970ca8b767..0000000000 --- a/Marlin/src/HAL/STM32F1/build_flags.py +++ /dev/null @@ -1,56 +0,0 @@ -from __future__ import print_function -import sys - -#dynamic build flags for generic compile options -if __name__ == "__main__": - args = " ".join([ "-std=gnu++14", - "-Os", - "-mcpu=cortex-m3", - "-mthumb", - - "-fsigned-char", - "-fno-move-loop-invariants", - "-fno-strict-aliasing", - "-fsingle-precision-constant", - - "--specs=nano.specs", - "--specs=nosys.specs", - - "-IMarlin/src/HAL/STM32F1", - - "-MMD", - "-MP", - "-DTARGET_STM32F1" - ]) - - for i in range(1, len(sys.argv)): - args += " " + sys.argv[i] - - print(args) - -# extra script for linker options -else: - 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" - ], - LINKFLAGS=[ - "-Os", - "-mcpu=cortex-m3", - "-ffreestanding", - "-mthumb", - "--specs=nano.specs", - "--specs=nosys.specs", - "-u_printf_float", - ], - ) diff --git a/Marlin/src/HAL/STM32F1/dogm/u8g_com_stm32duino_swspi.cpp b/Marlin/src/HAL/STM32F1/dogm/u8g_com_stm32duino_swspi.cpp index fc421897c4..28302edaf5 100644 --- a/Marlin/src/HAL/STM32F1/dogm/u8g_com_stm32duino_swspi.cpp +++ b/Marlin/src/HAL/STM32F1/dogm/u8g_com_stm32duino_swspi.cpp @@ -89,7 +89,7 @@ static inline uint8_t swSpiTransfer_mode_3(uint8_t b, const uint8_t spi_speed, c } static void u8g_sw_spi_shift_out(uint8_t val) { - #if ENABLED(FYSETC_MINI_12864) + #if U8G_SPI_USE_MODE_3 swSpiTransfer_mode_3(val, SPI_speed); #else swSpiTransfer_mode_0(val, SPI_speed); @@ -123,15 +123,15 @@ uint8_t u8g_com_HAL_STM32F1_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, break; case U8G_COM_MSG_CHIP_SELECT: - #if ENABLED(FYSETC_MINI_12864) // This LCD SPI is running mode 3 while SD card is running mode 0 - if (arg_val) { // SCK idle state needs to be set to the proper idle state before - // the next chip select goes active - WRITE(DOGLCD_SCK, HIGH); // Set SCK to mode 3 idle state before CS goes active + #if U8G_SPI_USE_MODE_3 // This LCD SPI is running mode 3 while SD card is running mode 0 + if (arg_val) { // SCK idle state needs to be set to the proper idle state before + // the next chip select goes active + WRITE(DOGLCD_SCK, HIGH); // Set SCK to mode 3 idle state before CS goes active WRITE(DOGLCD_CS, LOW); } else { WRITE(DOGLCD_CS, HIGH); - WRITE(DOGLCD_SCK, LOW); // Set SCK to mode 0 idle state after CS goes inactive + WRITE(DOGLCD_SCK, LOW); // Set SCK to mode 0 idle state after CS goes inactive } #else WRITE(DOGLCD_CS, !arg_val); diff --git a/Marlin/src/HAL/STM32F1/endstop_interrupts.h b/Marlin/src/HAL/STM32F1/endstop_interrupts.h index d11b3bf505..6724bf3456 100644 --- a/Marlin/src/HAL/STM32F1/endstop_interrupts.h +++ b/Marlin/src/HAL/STM32F1/endstop_interrupts.h @@ -70,6 +70,7 @@ void setup_endstop_interrupts() { TERN_(USE_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(USE_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(USE_Z_MIN_PROBE, _ATTACH(Z_MIN_PROBE_PIN)); + TERN_(USE_CALIBRATION, _ATTACH(CALIBRATION_PIN)); TERN_(USE_I_MAX, _ATTACH(I_MAX_PIN)); TERN_(USE_I_MIN, _ATTACH(I_MIN_PIN)); TERN_(USE_J_MAX, _ATTACH(J_MAX_PIN)); diff --git a/Marlin/src/HAL/STM32F1/u8g/LCD_defines.h b/Marlin/src/HAL/STM32F1/u8g/LCD_defines.h index 4bd461cb39..9d0137ae6a 100644 --- a/Marlin/src/HAL/STM32F1/u8g/LCD_defines.h +++ b/Marlin/src/HAL/STM32F1/u8g/LCD_defines.h @@ -25,7 +25,7 @@ * STM32F1 (Maple) LCD-specific defines */ -uint8_t u8g_com_HAL_STM32F1_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); +uint8_t u8g_com_HAL_STM32F1_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); // u8g_com_stm32duino_swspi.cpp uint8_t u8g_com_stm32duino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); // See U8glib-HAL #define U8G_COM_HAL_SW_SPI_FN u8g_com_HAL_STM32F1_sw_spi_fn diff --git a/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h b/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h index 954eb625a5..798ca4f0cb 100644 --- a/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h @@ -64,6 +64,7 @@ void setup_endstop_interrupts() { TERN_(USE_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(USE_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(USE_Z_MIN_PROBE, _ATTACH(Z_MIN_PROBE_PIN)); + TERN_(USE_CALIBRATION, _ATTACH(CALIBRATION_PIN)); TERN_(USE_I_MAX, _ATTACH(I_MAX_PIN)); TERN_(USE_I_MIN, _ATTACH(I_MIN_PIN)); TERN_(USE_J_MAX, _ATTACH(J_MAX_PIN)); diff --git a/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h b/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h index bc8e177fb7..a938041b5a 100644 --- a/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h @@ -63,6 +63,7 @@ void setup_endstop_interrupts() { TERN_(USE_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(USE_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(USE_Z_MIN_PROBE, _ATTACH(Z_MIN_PROBE_PIN)); + TERN_(USE_CALIBRATION, _ATTACH(CALIBRATION_PIN)); TERN_(USE_I_MAX, _ATTACH(I_MAX_PIN)); TERN_(USE_I_MIN, _ATTACH(I_MIN_PIN)); TERN_(USE_J_MAX, _ATTACH(J_MAX_PIN)); diff --git a/Marlin/src/HAL/TEENSY40_41/endstop_interrupts.h b/Marlin/src/HAL/TEENSY40_41/endstop_interrupts.h index 722912c890..f59a9409c8 100644 --- a/Marlin/src/HAL/TEENSY40_41/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY40_41/endstop_interrupts.h @@ -63,6 +63,7 @@ void setup_endstop_interrupts() { TERN_(USE_Z4_MAX, _ATTACH(Z4_MAX_PIN)); TERN_(USE_Z4_MIN, _ATTACH(Z4_MIN_PIN)); TERN_(USE_Z_MIN_PROBE, _ATTACH(Z_MIN_PROBE_PIN)); + TERN_(USE_CALIBRATION, _ATTACH(CALIBRATION_PIN)); TERN_(USE_I_MAX, _ATTACH(I_MAX_PIN)); TERN_(USE_I_MIN, _ATTACH(I_MIN_PIN)); TERN_(USE_J_MAX, _ATTACH(J_MAX_PIN)); diff --git a/Marlin/src/HAL/TEENSY40_41/timers.h b/Marlin/src/HAL/TEENSY40_41/timers.h index 3c7cda0b4e..fc160ab8b8 100644 --- a/Marlin/src/HAL/TEENSY40_41/timers.h +++ b/Marlin/src/HAL/TEENSY40_41/timers.h @@ -36,13 +36,13 @@ typedef uint32_t hal_timer_t; #define HAL_TIMER_TYPE_MAX 0xFFFFFFFE -#define GPT_TIMER_RATE F_BUS_ACTUAL // 150MHz +#define GPT_TIMER_RATE (F_CPU / 4) // 150MHz (Can't use F_BUS_ACTUAL because it's extern volatile) #define GPT1_TIMER_PRESCALE 2 #define GPT2_TIMER_PRESCALE 10 -#define GPT1_TIMER_RATE (GPT_TIMER_RATE / GPT1_TIMER_PRESCALE) // 75MHz -#define GPT2_TIMER_RATE (GPT_TIMER_RATE / GPT2_TIMER_PRESCALE) // 15MHz +#define GPT1_TIMER_RATE (GPT_TIMER_RATE / GPT1_TIMER_PRESCALE) // 150MHz / 2 = 75MHz +#define GPT2_TIMER_RATE (GPT_TIMER_RATE / GPT2_TIMER_PRESCALE) // 150MHz / 10 = 15MHz #ifndef MF_TIMER_STEP #define MF_TIMER_STEP 0 // Timer Index for Stepper @@ -57,7 +57,8 @@ typedef uint32_t hal_timer_t; #define TEMP_TIMER_RATE 1000000 #define TEMP_TIMER_FREQUENCY 1000 -#define STEPPER_TIMER_RATE GPT1_TIMER_RATE +#define HAL_TIMER_RATE GPT1_TIMER_RATE +#define STEPPER_TIMER_RATE HAL_TIMER_RATE #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) #define STEPPER_TIMER_PRESCALE ((GPT_TIMER_RATE / 1000000) / STEPPER_TIMER_TICKS_PER_US) diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 2dba3944e5..dbfb822015 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -263,7 +263,7 @@ PGMSTR(M112_KILL_STR, "M112 Shutdown"); -MarlinState marlin_state = MF_INITIALIZING; +MarlinState marlin_state = MarlinState::MF_INITIALIZING; // For M109 and M190, this flag may be cleared (by M108) to exit the wait loop bool wait_for_heatup = false; @@ -308,23 +308,12 @@ bool wait_for_heatup = false; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnarrowing" -#ifndef RUNTIME_ONLY_ANALOG_TO_DIGITAL - template - constexpr pin_t OnlyPins<_SP_END, D...>::table[sizeof...(D)]; -#endif - bool pin_is_protected(const pin_t pin) { - #ifdef RUNTIME_ONLY_ANALOG_TO_DIGITAL - static const pin_t sensitive_pins[] PROGMEM = { SENSITIVE_PINS }; - const size_t pincount = COUNT(sensitive_pins); - #else - static constexpr size_t pincount = OnlyPins::size; - static const pin_t (&sensitive_pins)[pincount] PROGMEM = OnlyPins::table; - #endif - for (uint8_t i = 0; i < pincount; ++i) { - const pin_t * const pptr = &sensitive_pins[i]; - if (pin == (sizeof(pin_t) == 2 ? (pin_t)pgm_read_word(pptr) : (pin_t)pgm_read_byte(pptr))) return true; - } + #define pgm_read_pin(P) (sizeof(pin_t) == 2 ? (pin_t)pgm_read_word(P) : (pin_t)pgm_read_byte(P)) + for (uint8_t i = 0; i < COUNT(sensitive_dio); ++i) + if (pin == pgm_read_pin(&sensitive_dio[i])) return true; + for (uint8_t i = 0; i < COUNT(sensitive_aio); ++i) + if (pin == analogInputToDigitalPin(pgm_read_pin(&sensitive_dio[i]))) return true; return false; } @@ -388,8 +377,8 @@ void startOrResumeJob() { } inline void finishSDPrinting() { - if (queue.enqueue_one(F("M1001"))) { // Keep trying until it gets queued - marlin_state = MF_RUNNING; // Signal to stop trying + if (queue.enqueue_one(F("M1001"))) { // Keep trying until it gets queued + marlin_state = MarlinState::MF_RUNNING; // Signal to stop trying TERN_(PASSWORD_AFTER_SD_PRINT_END, password.lock_machine()); TERN_(DGUS_LCD_UI_MKS, screen.sdPrintingFinished()); } @@ -784,7 +773,7 @@ void idle(const bool no_stepper_sleep/*=false*/) { TERN_(MAX7219_DEBUG, max7219.idle_tasks()); // Return if setup() isn't completed - if (marlin_state == MF_INITIALIZING) goto IDLE_DONE; + if (marlin_state == MarlinState::MF_INITIALIZING) goto IDLE_DONE; // TODO: Still causing errors TERN_(TOOL_SENSOR, (void)check_tool_sensor_stats(active_extruder, true)); @@ -970,7 +959,7 @@ void stop() { SERIAL_ERROR_MSG(STR_ERR_STOPPED); LCD_MESSAGE(MSG_STOPPED); safe_delay(350); // allow enough time for messages to get out before stopping - marlin_state = MF_STOPPED; + marlin_state = MarlinState::MF_STOPPED; } } @@ -1330,18 +1319,23 @@ void setup() { #endif #endif - #if ALL(HAS_MEDIA, SDCARD_EEPROM_EMULATION) + #if HAS_MEDIA && ANY(SDCARD_EEPROM_EMULATION, POWER_LOSS_RECOVERY) SETUP_RUN(card.mount()); // Mount media with settings before first_load #endif - SETUP_RUN(settings.first_load()); // Load data from EEPROM if available (or use defaults) - // This also updates variables in the planner, elsewhere + // Prepare some LCDs to display early + #if HAS_EARLY_LCD_SETTINGS + SETUP_RUN(settings.load_lcd_state()); + #endif #if ALL(HAS_WIRED_LCD, SHOW_BOOTSCREEN) SETUP_RUN(ui.show_bootscreen()); const millis_t bootscreen_ms = millis(); #endif + SETUP_RUN(settings.first_load()); // Load data from EEPROM if available (or use defaults) + // This also updates variables in the planner, elsewhere + #if ENABLED(PROBE_TARE) SETUP_RUN(probe.tare_init()); #endif @@ -1652,7 +1646,7 @@ void setup() { SETUP_RUN(ftMotion.init()); #endif - marlin_state = MF_RUNNING; + marlin_state = MarlinState::MF_RUNNING; #ifdef STARTUP_TUNE // Play a short startup tune before continuing. @@ -1684,7 +1678,7 @@ void loop() { #if HAS_MEDIA if (card.flag.abort_sd_printing) abortSDPrinting(); - if (marlin_state == MF_SD_COMPLETE) finishSDPrinting(); + if (marlin_state == MarlinState::MF_SD_COMPLETE) finishSDPrinting(); #endif queue.advance(); diff --git a/Marlin/src/MarlinCore.h b/Marlin/src/MarlinCore.h index e9c63bb31f..9cf74de2c6 100644 --- a/Marlin/src/MarlinCore.h +++ b/Marlin/src/MarlinCore.h @@ -42,7 +42,7 @@ void kill(FSTR_P const lcd_error=nullptr, FSTR_P const lcd_component=nullptr, co void minkill(const bool steppers_off=false); // Global State of the firmware -enum MarlinState : uint8_t { +enum class MarlinState : uint8_t { MF_INITIALIZING = 0, MF_STOPPED, MF_KILLED, @@ -53,8 +53,8 @@ enum MarlinState : uint8_t { }; extern MarlinState marlin_state; -inline bool IsRunning() { return marlin_state >= MF_RUNNING; } -inline bool IsStopped() { return marlin_state == MF_STOPPED; } +inline bool IsRunning() { return marlin_state >= MarlinState::MF_RUNNING; } +inline bool IsStopped() { return marlin_state == MarlinState::MF_STOPPED; } bool printingIsActive(); bool printJobOngoing(); diff --git a/Marlin/src/core/drivers.h b/Marlin/src/core/drivers.h index e28fc1bba7..c4417aab75 100644 --- a/Marlin/src/core/drivers.h +++ b/Marlin/src/core/drivers.h @@ -103,7 +103,8 @@ #define HAS_TRINAMIC HAS_TRINAMIC_CONFIG -#if ( HAS_DRIVER(TMC2130_STANDALONE) || HAS_DRIVER(TMC2160_STANDALONE) \ +#if ( HAS_DRIVER(TMC2100) \ + || HAS_DRIVER(TMC2130_STANDALONE) || HAS_DRIVER(TMC2160_STANDALONE) \ || HAS_DRIVER(TMC2208_STANDALONE) || HAS_DRIVER(TMC2209_STANDALONE) \ || HAS_DRIVER(TMC2660_STANDALONE) || HAS_DRIVER(TMC5130_STANDALONE) \ || HAS_DRIVER(TMC5160_STANDALONE) ) diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index ad84966453..9d2cdca897 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -355,6 +355,8 @@ #define STR_PROBE_EN "probe_en" #define STR_FILAMENT "filament" +#define STR_CALIBRATION "calibration" + // General axis names #define STR_X "X" #define STR_Y "Y" diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index 4f1aba23c8..56250fb149 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -55,9 +55,6 @@ #define CYCLES_PER_MICROSECOND (F_CPU / 1000000UL) // 16 or 20 on AVR #endif -// Nanoseconds per cycle -#define NANOSECONDS_PER_CYCLE (1000000000.0 / F_CPU) - // Macros to make a string from a macro #define STRINGIFY_(M) #M #define STRINGIFY(M) STRINGIFY_(M) @@ -197,8 +194,8 @@ #define ENABLED(V...) DO(ENA,&&,V) #define DISABLED(V...) DO(DIS,&&,V) #define ANY(V...) !DISABLED(V) -#define ALL ENABLED -#define NONE DISABLED +#define ALL(V...) ENABLED(V) +#define NONE(V...) DISABLED(V) #define COUNT_ENABLED(V...) DO(ENA,+,V) #define MANY(V...) (COUNT_ENABLED(V) > 1) @@ -630,7 +627,7 @@ #define DEFER4(M) M EMPTY EMPTY EMPTY EMPTY()()()() // Force define expansion -#define EVAL EVAL16 +#define EVAL(V...) EVAL16(V) #define EVAL4096(V...) EVAL2048(EVAL2048(V)) #define EVAL2048(V...) EVAL1024(EVAL1024(V)) #define EVAL1024(V...) EVAL512(EVAL512(V)) diff --git a/Marlin/src/feature/backlash.cpp b/Marlin/src/feature/backlash.cpp index 07fa7725a0..3b9d78cb2e 100644 --- a/Marlin/src/feature/backlash.cpp +++ b/Marlin/src/feature/backlash.cpp @@ -171,13 +171,14 @@ int32_t Backlash::get_applied_steps(const AxisEnum axis) { const int32_t residual_error_axis = residual_error[axis]; - // At startup it is assumed the last move was forward. - // So the applied steps will always be negative. + // At startup, when no steps are applied, it is assumed the last move was backwards. + // So the applied steps will always be zero (when moving backwards) or a positive + // number (when moving forwards). - if (forward) return -residual_error_axis; + if (!forward) return -residual_error_axis; const float f_corr = float(correction) / all_on; - const int32_t full_error_axis = -f_corr * distance_mm[axis] * planner.settings.axis_steps_per_mm[axis]; + const int32_t full_error_axis = f_corr * distance_mm[axis] * planner.settings.axis_steps_per_mm[axis]; return full_error_axis - residual_error_axis; } diff --git a/Marlin/src/feature/leds/leds.cpp b/Marlin/src/feature/leds/leds.cpp index ac7f181516..8810c518cf 100644 --- a/Marlin/src/feature/leds/leds.cpp +++ b/Marlin/src/feature/leds/leds.cpp @@ -239,7 +239,7 @@ void LEDLights::set_color(const LEDColor &incol void LEDLights::toggle() { if (lights_on) set_off(); else update(); } #endif -#if LED_POWEROFF_TIMEOUT > 0 +#if HAS_LED_POWEROFF_TIMEOUT millis_t LEDLights::led_off_time; // = 0 diff --git a/Marlin/src/feature/leds/leds.h b/Marlin/src/feature/leds/leds.h index 7a31ca685d..da8ba42fba 100644 --- a/Marlin/src/feature/leds/leds.h +++ b/Marlin/src/feature/leds/leds.h @@ -164,11 +164,11 @@ public: #if ENABLED(LED_CONTROL_MENU) static void toggle(); // swap "off" with color #endif - #if ANY(LED_CONTROL_MENU, CASE_LIGHT_USE_RGB_LED) || LED_POWEROFF_TIMEOUT > 0 + #if ANY(LED_CONTROL_MENU, CASE_LIGHT_USE_RGB_LED, HAS_LED_POWEROFF_TIMEOUT) static void update() { set_color(color); } #endif - #if LED_POWEROFF_TIMEOUT > 0 + #if HAS_LED_POWEROFF_TIMEOUT private: static millis_t led_off_time; public: diff --git a/Marlin/src/feature/powerloss.cpp b/Marlin/src/feature/powerloss.cpp index 1867aba6ed..cd5fc13dda 100644 --- a/Marlin/src/feature/powerloss.cpp +++ b/Marlin/src/feature/powerloss.cpp @@ -205,6 +205,9 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW // info.sdpos and info.current_position are pre-filled from the Stepper ISR info.feedrate = uint16_t(MMS_TO_MMM(feedrate_mm_s)); + info.feedrate_percentage = feedrate_percentage; + COPY(info.flow_percentage, planner.flow_percentage); + info.zraise = zraise; info.flag.raised = raised; // Was Z raised before power-off? @@ -216,7 +219,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW #if DISABLED(NO_VOLUMETRICS) info.flag.volumetric_enabled = parser.volumetric_enabled; #if HAS_MULTI_EXTRUDER - EXTRUDER_LOOP() info.filament_size[e] = planner.filament_size[e]; + COPY(info.filament_size, planner.filament_size); #else if (parser.volumetric_enabled) info.filament_size[0] = planner.filament_size[active_extruder]; #endif @@ -269,7 +272,10 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW #if POWER_LOSS_RETRACT_LEN // Retract filament now - gcode.process_subcommands_now(F("G1 F3000 E-" STRINGIFY(POWER_LOSS_RETRACT_LEN))); + const uint16_t old_flow = planner.flow_percentage[active_extruder]; + planner.set_flow(active_extruder, 100); + gcode.process_subcommands_now(F("G1F3000E-" STRINGIFY(POWER_LOSS_RETRACT_LEN))); + planner.set_flow(active_extruder, old_flow); #endif #if POWER_LOSS_ZRAISE @@ -555,8 +561,12 @@ void PrintJobRecovery::resume() { // Move back down to the saved Z for printing PROCESS_SUBCOMMANDS_NOW(TS(F("G1F600Z"), p_float_t(z_print, 3))); - // Restore the feedrate + // Restore the feedrate and percentage PROCESS_SUBCOMMANDS_NOW(TS(F("G1F"), info.feedrate)); + feedrate_percentage = info.feedrate_percentage; + + // Flowrate percentage + EXTRUDER_LOOP() planner.set_flow(e, info.flow_percentage[e]); // Restore E position with G92.9 PROCESS_SUBCOMMANDS_NOW(TS(F("G92.9E"), p_float_t(resume_pos.e, 3))); @@ -589,7 +599,8 @@ void PrintJobRecovery::resume() { } DEBUG_EOL(); - DEBUG_ECHOLNPGM("feedrate: ", info.feedrate); + DEBUG_ECHOLN(F("feedrate: "), info.feedrate, F(" x "), info.feedrate_percentage, '%'); + EXTRUDER_LOOP() DEBUG_ECHOLN('E', e + 1, F(" flow %: "), info.flow_percentage[e]); DEBUG_ECHOLNPGM("zraise: ", info.zraise, " ", info.flag.raised ? "(before)" : ""); diff --git a/Marlin/src/feature/powerloss.h b/Marlin/src/feature/powerloss.h index 7de8450c91..238f276c1b 100644 --- a/Marlin/src/feature/powerloss.h +++ b/Marlin/src/feature/powerloss.h @@ -59,6 +59,8 @@ typedef struct { // Machine state xyze_pos_t current_position; uint16_t feedrate; + int16_t feedrate_percentage; + uint16_t flow_percentage[EXTRUDERS]; float zraise; diff --git a/Marlin/src/gcode/calibrate/G425.cpp b/Marlin/src/gcode/calibrate/G425.cpp index 992d7c38e6..ad17b2e106 100644 --- a/Marlin/src/gcode/calibrate/G425.cpp +++ b/Marlin/src/gcode/calibrate/G425.cpp @@ -181,20 +181,6 @@ inline void park_above_object(measurements_t &m, const float uncertainty) { #endif -#if !PIN_EXISTS(CALIBRATION) - #include "../../module/probe.h" -#endif - -inline bool read_calibration_pin() { - return ( - #if PIN_EXISTS(CALIBRATION) - READ(CALIBRATION_PIN) != CALIBRATION_PIN_INVERTING - #else - PROBE_TRIGGERED() - #endif - ); -} - /** * Move along axis in the specified dir until the probe value becomes stop_state, * then return the axis value. @@ -205,18 +191,18 @@ inline bool read_calibration_pin() { * fast in - Fast vs. precise measurement */ float measuring_movement(const AxisEnum axis, const int dir, const bool stop_state, const bool fast) { - const float step = fast ? 0.25 : CALIBRATION_MEASUREMENT_RESOLUTION; const feedRate_t mms = fast ? MMM_TO_MMS(CALIBRATION_FEEDRATE_FAST) : MMM_TO_MMS(CALIBRATION_FEEDRATE_SLOW); const float limit = fast ? 50 : 5; destination = current_position; - for (float travel = 0; travel < limit; travel += step) { - destination[axis] += dir * step; - do_blocking_move_to((xyz_pos_t)destination, mms); - planner.synchronize(); - if (read_calibration_pin() == stop_state) break; - } - return destination[axis]; + destination[axis] += dir * limit; + endstops.enable_calibration_probe(true, stop_state); + do_blocking_move_to((xyz_pos_t)destination, mms); + endstops.enable_calibration_probe(false); + endstops.hit_on_purpose(); + set_current_from_steppers_for_axis(axis); + sync_plan_position(); + return current_position[axis]; } /** diff --git a/Marlin/src/gcode/control/M80_M81.cpp b/Marlin/src/gcode/control/M80_M81.cpp index 2d3e407446..3f0264994e 100644 --- a/Marlin/src/gcode/control/M80_M81.cpp +++ b/Marlin/src/gcode/control/M80_M81.cpp @@ -112,9 +112,9 @@ void GcodeSuite::M81() { return; } - #if HAS_SUICIDE - suicide(); - #elif ENABLED(PSU_CONTROL) + #if ENABLED(PSU_CONTROL) powerManager.power_off_soon(); + #elif HAS_SUICIDE + suicide(); #endif } diff --git a/Marlin/src/gcode/control/M999.cpp b/Marlin/src/gcode/control/M999.cpp index b7d6db9f23..b4278fccad 100644 --- a/Marlin/src/gcode/control/M999.cpp +++ b/Marlin/src/gcode/control/M999.cpp @@ -36,7 +36,7 @@ * existing command buffer. */ void GcodeSuite::M999() { - marlin_state = MF_RUNNING; + marlin_state = MarlinState::MF_RUNNING; ui.reset_alert_level(); if (parser.boolval('S')) return; diff --git a/Marlin/src/gcode/feature/nonlinear/M592.cpp b/Marlin/src/gcode/feature/nonlinear/M592.cpp index b1c4ca4be7..2fc02133ec 100644 --- a/Marlin/src/gcode/feature/nonlinear/M592.cpp +++ b/Marlin/src/gcode/feature/nonlinear/M592.cpp @@ -35,12 +35,12 @@ void GcodeSuite::M592_report(const bool forReplay/*=true*/) { /** * M592: Get or set nonlinear extrusion parameters - * A Linear coefficient (default 0.0) - * B Quadratic coefficient (default 0.0) + * A Quadratic coefficient (default 0.0) + * B Linear coefficient (default 0.0) * C Constant coefficient (default 1.0) * * Adjusts the amount of extrusion based on the instantaneous velocity of extrusion, as a multiplier. - * The amount of extrusion is multiplied by max(C, C + A*v + B*v^2) where v is extruder velocity in mm/s. + * The amount of extrusion is multiplied by max(C, A*v^2 + B*v + C) where v is extruder velocity in mm/s. * Only adjusts forward extrusions, since those are the ones affected by backpressure. */ void GcodeSuite::M592() { diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index 1ff643dc21..9e81c7d4bc 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -1105,6 +1105,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { case 1002: M1002(); break; // M1002: [INTERNAL] Tool-change and Relative E Move #endif + #if ENABLED(ONE_CLICK_PRINT) + case 1003: M1003(); break; // M1003: [INTERNAL] Set the current dir to / + #endif + #if ENABLED(UBL_MESH_WIZARD) case 1004: M1004(); break; // M1004: UBL Mesh Wizard #endif diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index 1e3ec7c7f1..144d724cd9 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -1276,6 +1276,10 @@ private: static void M1002(); #endif + #if ENABLED(ONE_CLICK_PRINT) + static void M1003(); + #endif + #if ENABLED(UBL_MESH_WIZARD) static void M1004(); #endif diff --git a/Marlin/src/gcode/probe/G30.cpp b/Marlin/src/gcode/probe/G30.cpp index 3ce37bed05..e736a99ec8 100644 --- a/Marlin/src/gcode/probe/G30.cpp +++ b/Marlin/src/gcode/probe/G30.cpp @@ -34,7 +34,7 @@ #include "../../feature/probe_temp_comp.h" #endif -#if ANY(DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI) +#if ANY(DWIN_CREALITY_LCD_JYERSUI, EXTENSIBLE_UI) #define VERBOSE_SINGLE_PROBE #endif diff --git a/Marlin/src/gcode/sd/M1003.cpp b/Marlin/src/gcode/sd/M1003.cpp new file mode 100644 index 0000000000..bed9d2cb10 --- /dev/null +++ b/Marlin/src/gcode/sd/M1003.cpp @@ -0,0 +1,36 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2024 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 . + * + */ + +#include "../../inc/MarlinConfig.h" + +#if ENABLED(ONE_CLICK_PRINT) + +#include "../gcode.h" +#include "../../sd/cardreader.h" + +/** + * M1003: Set the current dir to /. Should come after 'M24'. + * Prevents the SD menu getting stuck in the newest file's workDir. + */ +void GcodeSuite::M1003() { card.cdroot(); } + +#endif // ONE_CLICK_PRINT diff --git a/Marlin/src/inc/Changes.h b/Marlin/src/inc/Changes.h index 1019638931..a5319e4654 100644 --- a/Marlin/src/inc/Changes.h +++ b/Marlin/src/inc/Changes.h @@ -497,6 +497,8 @@ #error "DIGIPOT_I2C is now DIGIPOT_MCP4451 (or DIGIPOT_MCP4018)." #elif defined(TOUCH_BUTTONS) #error "TOUCH_BUTTONS is now TOUCH_SCREEN." +#elif defined(DISABLE_ENCODER) + #error "DISABLE_ENCODER is now NO_BACK_MENU_ITEM." #elif defined(LCD_FULL_PIXEL_HEIGHT) || defined(LCD_FULL_PIXEL_WIDTH) #error "LCD_FULL_PIXEL_(WIDTH|HEIGHT) is deprecated and should be removed." #elif defined(FSMC_UPSCALE) @@ -641,6 +643,8 @@ #error "PROBE_PT_[123]_[XY] is now defined using PROBE_PT_[123] with an array { x, y }." #elif defined(SQUARE_WAVE_STEPPING) #error "SQUARE_WAVE_STEPPING is now EDGE_STEPPING." +#elif defined(MINIMUM_STEPPER_PULSE) + #error "MINIMUM_STEPPER_PULSE (in µs) is now MINIMUM_STEPPER_PULSE_NS. Multiply old MINIMUM_STEPPER_PULSE x 1000!" #elif defined(FAN_PIN) #error "FAN_PIN is now FAN0_PIN." #elif defined(X_MIN_ENDSTOP_INVERTING) || defined(Y_MIN_ENDSTOP_INVERTING) || defined(Z_MIN_ENDSTOP_INVERTING) \ @@ -693,6 +697,8 @@ #error "Z_PROBE_END_SCRIPT is now EVENT_GCODE_AFTER_G29." #elif defined(WIFI_SERIAL) #error "WIFI_SERIAL is now WIFI_SERIAL_PORT." +#elif defined(CALIBRATION_MEASUREMENT_RESOLUTION) + #error "CALIBRATION_MEASUREMENT_RESOLUTION is no longer needed and should be removed." #endif // Changes to Probe Temp Compensation (#17392) diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index efda2d493e..ab5fd9e55c 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -654,11 +654,11 @@ #elif ENABLED(ZONESTAR_12864OLED) #define IS_RRD_SC 1 - #define U8GLIB_SH1106 + #define U8GLIB_SH1106_SPI #elif ENABLED(ZONESTAR_12864OLED_SSD1306) #define IS_RRD_SC 1 - #define IS_U8GLIB_SSD1306 + #define U8GLIB_SSD1306_SPI #elif ENABLED(RADDS_DISPLAY) #define IS_ULTIPANEL 1 @@ -716,7 +716,7 @@ #elif ENABLED(SAV_3DGLCD) - #ifdef U8GLIB_SSD1306 + #if ENABLED(U8GLIB_SSD1306) #define IS_U8GLIB_SSD1306 // Allow for U8GLIB_SSD1306 + SAV_3DGLCD #endif #define IS_NEWPANEL 1 @@ -815,6 +815,10 @@ #endif +#if ANY(FYSETC_MINI_12864, MKS_MINI_12864) + #define U8G_SPI_USE_MODE_3 1 +#endif + // ST7920-based graphical displays #if ANY(IS_RRD_FG_SC, LCD_FOR_MELZI, SILVER_GATE_GLCD_CONTROLLER) #define DOGLCD @@ -853,9 +857,12 @@ #define STD_ENCODER_STEPS_PER_MENU_ITEM 1 #endif -// 128x64 I2C OLED LCDs - SSD1306/SSD1309/SH1106 +// 128x64 I2C OLED LCDs (SSD1306 / SSD1309 / SH1106) +// ...and 128x64 SPI OLED LCDs (SSD1306 / SH1106) #if ANY(U8GLIB_SSD1306, U8GLIB_SSD1309, U8GLIB_SH1106) #define HAS_U8GLIB_I2C_OLED 1 +#endif +#if ANY(HAS_U8GLIB_I2C_OLED, U8GLIB_SSD1306_SPI, U8GLIB_SH1106_SPI) #define HAS_WIRED_LCD 1 #define DOGLCD #endif @@ -1095,6 +1102,9 @@ * - poweroff (for PSU_CONTROL and HAS_MARLINUI_MENU) * * ...and implements these MarlinUI methods: + * - init_lcd + * - clear_lcd + * - clear_for_drawing * - zoffset_overlay (if BABYSTEP_GFX_OVERLAY or MESH_EDIT_GFX_OVERLAY are supported) * - draw_kill_screen * - kill_screen @@ -1888,6 +1898,10 @@ #define NEOPIXEL_BKGD_INDEX_LAST NEOPIXEL_BKGD_INDEX_FIRST #endif +#if LED_POWEROFF_TIMEOUT > 0 + #define HAS_LED_POWEROFF_TIMEOUT 1 +#endif + #if ALL(SPI_FLASH, HAS_MEDIA, MARLIN_DEV_MODE) #define SPI_FLASH_BACKUP 1 #endif diff --git a/Marlin/src/inc/Conditionals_adv.h b/Marlin/src/inc/Conditionals_adv.h index 8e5814f5f2..ef0b18e4b7 100644 --- a/Marlin/src/inc/Conditionals_adv.h +++ b/Marlin/src/inc/Conditionals_adv.h @@ -1198,21 +1198,21 @@ #define MINIMUM_STEPPER_PRE_DIR_DELAY MINIMUM_STEPPER_POST_DIR_DELAY #endif -#ifndef MINIMUM_STEPPER_PULSE +#ifndef MINIMUM_STEPPER_PULSE_NS #if HAS_DRIVER(TB6560) - #define MINIMUM_STEPPER_PULSE 30 + #define MINIMUM_STEPPER_PULSE_NS 30000 #elif HAS_DRIVER(TB6600) - #define MINIMUM_STEPPER_PULSE 3 + #define MINIMUM_STEPPER_PULSE_NS 3000 #elif HAS_DRIVER(DRV8825) - #define MINIMUM_STEPPER_PULSE 2 + #define MINIMUM_STEPPER_PULSE_NS 2000 #elif HAS_DRIVER(A4988) || HAS_DRIVER(A5984) - #define MINIMUM_STEPPER_PULSE 1 - #elif HAS_TRINAMIC_CONFIG || HAS_TRINAMIC_STANDALONE - #define MINIMUM_STEPPER_PULSE 0 + #define MINIMUM_STEPPER_PULSE_NS 1000 #elif HAS_DRIVER(LV8729) - #define MINIMUM_STEPPER_PULSE 0 + #define MINIMUM_STEPPER_PULSE_NS 500 + #elif HAS_TRINAMIC_CONFIG || HAS_TRINAMIC_STANDALONE + #define MINIMUM_STEPPER_PULSE_NS 100 #else - #define MINIMUM_STEPPER_PULSE 2 + // Expecting MAXIMUM_STEPPER_RATE to be defined #endif #endif @@ -1230,7 +1230,7 @@ #elif HAS_TRINAMIC_CONFIG || HAS_TRINAMIC_STANDALONE #define MAXIMUM_STEPPER_RATE 5000000 #else - #define MAXIMUM_STEPPER_RATE 250000 + // Expecting MINIMUM_STEPPER_PULSE_NS to be defined #endif #endif diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index 8446a1acf0..7af8536d90 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -557,7 +557,7 @@ #endif #endif - #if HAS_SD_DETECT && NONE(HAS_GRAPHICAL_TFT, LCD_USE_DMA_FSMC, HAS_FSMC_GRAPHICAL_TFT, HAS_SPI_GRAPHICAL_TFT, IS_DWIN_MARLINUI, EXTENSIBLE_UI, HAS_DWIN_E3V2) + #if HAS_SD_DETECT && NONE(HAS_GRAPHICAL_TFT, LCD_USE_DMA_FSMC, HAS_FSMC_GRAPHICAL_TFT, HAS_SPI_GRAPHICAL_TFT, IS_DWIN_MARLINUI, EXTENSIBLE_UI, HAS_DWIN_E3V2, HAS_U8GLIB_I2C_OLED) #define REINIT_NOISY_LCD 1 // Have the LCD re-init on SD insertion #endif @@ -2200,6 +2200,11 @@ #define HAS_Z_PROBE_STATE 1 #endif +#if PIN_EXISTS(CALIBRATION) + #define USE_CALIBRATION 1 + #define HAS_CALIBRATION_STATE 1 +#endif + #undef _ANY_STOP #undef _USE_STOP #undef _HAS_STATE @@ -2752,7 +2757,7 @@ // Fan Kickstart #if FAN_KICKSTART_TIME && !defined(FAN_KICKSTART_POWER) - #define FAN_KICKSTART_POWER 180 + #define FAN_KICKSTART_POWER TERN(FAN_KICKSTART_LINEAR, 255, 180) #endif // Servos @@ -3379,6 +3384,10 @@ #define LCD_HEIGHT TERN(IS_ULTIPANEL, 4, 2) #endif #endif + // Prepare the LCD to show the bootscreen early in setup + #if ENABLED(SHOW_BOOTSCREEN) && ANY(HAS_LCD_CONTRAST, HAS_LCD_BRIGHTNESS) + #define HAS_EARLY_LCD_SETTINGS 1 + #endif #endif #if BUTTONS_EXIST(EN1, EN2, ENC) diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 0383d29a69..7113e9946b 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -837,9 +837,7 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L * Nonlinear Extrusion requirements */ #if ENABLED(NONLINEAR_EXTRUSION) - #if DISABLED(ADAPTIVE_STEP_SMOOTHING) - #error "ADAPTIVE_STEP_SMOOTHING is required for NONLINEAR_EXTRUSION." - #elif HAS_MULTI_EXTRUDER + #if HAS_MULTI_EXTRUDER #error "NONLINEAR_EXTRUSION doesn't currently support multi-extruder setups." #elif DISABLED(CPU_32_BIT) #error "NONLINEAR_EXTRUSION requires a 32-bit CPU." @@ -1011,8 +1009,12 @@ static_assert(NUM_SERVOS <= NUM_SERVO_PLUGS, "NUM_SERVOS (or some servo index) i #endif // Fan Kickstart power -#if FAN_KICKSTART_TIME && !WITHIN(FAN_KICKSTART_POWER, 64, 255) - #error "FAN_KICKSTART_POWER must be an integer from 64 to 255." +#if FAN_KICKSTART_TIME + #if ENABLED(FAN_KICKSTART_LINEAR) && FAN_KICKSTART_POWER != 255 + #error "FAN_KICKSTART_LINEAR requires a FAN_KICKSTART_POWER of 255." + #elif !WITHIN(FAN_KICKSTART_POWER, 64, 255) + #error "FAN_KICKSTART_POWER must be an integer from 64 to 255." + #endif #endif /** @@ -2466,6 +2468,51 @@ static_assert(NUM_SERVOS <= NUM_SERVO_PLUGS, "NUM_SERVOS (or some servo index) i #elif Z_SPI_SENSORLESS && !(AXIS_HAS_SPI(Z2) && (NUM_Z_STEPPERS < 3 || AXIS_HAS_SPI(Z3)) && (NUM_Z_STEPPERS < 4 || AXIS_HAS_SPI(Z4))) #error "All Z Stepper Drivers must be SPI-capable to use SPI Endstops on Z." #endif + #if PIN_EXISTS(Z2_STOP) + #if X_HOME_TO_MIN && Z2_STOP_PIN == X_MIN_PIN + #error "Z2_STOP_PIN can't be the same as X_MIN_PIN when homing to X_MIN" + #elif X_HOME_TO_MAX && Z2_STOP_PIN == X_MAX_PIN + #error "Z2_STOP_PIN can't be the same as X_MAX_PIN when homing to X_MAX" + #elif Y_HOME_TO_MIN && Z2_STOP_PIN == Y_MIN_PIN + #error "Z2_STOP_PIN can't be the same as Y_MIN_PIN when homing to Y_MIN" + #elif Y_HOME_TO_MAX && Z2_STOP_PIN == Y_MAX_PIN + #error "Z2_STOP_PIN can't be the same as Y_MAX_PIN when homing to Y_MAX" + #elif Z_HOME_TO_MIN && Z2_STOP_PIN == Z_MIN_PIN + #error "Z2_STOP_PIN can't be the same as Z_MIN_PIN when homing to Z_MIN" + #elif Z_HOME_TO_MAX && Z2_STOP_PIN == Z_MAX_PIN + #error "Z2_STOP_PIN can't be the same as Z_MAX_PIN when homing to Z_MAX" + #endif + #endif + #if PIN_EXISTS(Z3_STOP) + #if X_HOME_TO_MIN && Z3_STOP_PIN == X_MIN_PIN + #error "Z3_STOP_PIN can't be the same as X_MIN_PIN when homing to X_MIN" + #elif X_HOME_TO_MAX && Z3_STOP_PIN == X_MAX_PIN + #error "Z3_STOP_PIN can't be the same as X_MAX_PIN when homing to X_MAX" + #elif Y_HOME_TO_MIN && Z3_STOP_PIN == Y_MIN_PIN + #error "Z3_STOP_PIN can't be the same as Y_MIN_PIN when homing to Y_MIN" + #elif Y_HOME_TO_MAX && Z3_STOP_PIN == Y_MAX_PIN + #error "Z3_STOP_PIN can't be the same as Y_MAX_PIN when homing to Y_MAX" + #elif Z_HOME_TO_MIN && Z3_STOP_PIN == Z_MIN_PIN + #error "Z3_STOP_PIN can't be the same as Z_MIN_PIN when homing to Z_MIN" + #elif Z_HOME_TO_MAX && Z3_STOP_PIN == Z_MAX_PIN + #error "Z3_STOP_PIN can't be the same as Z_MAX_PIN when homing to Z_MAX" + #endif + #endif + #if PIN_EXISTS(Z4_STOP) + #if X_HOME_TO_MIN && Z4_STOP_PIN == X_MIN_PIN + #error "Z4_STOP_PIN can't be the same as X_MIN_PIN when homing to X_MIN" + #elif X_HOME_TO_MAX && Z4_STOP_PIN == X_MAX_PIN + #error "Z4_STOP_PIN can't be the same as X_MAX_PIN when homing to X_MAX" + #elif Y_HOME_TO_MIN && Z4_STOP_PIN == Y_MIN_PIN + #error "Z4_STOP_PIN can't be the same as Y_MIN_PIN when homing to Y_MIN" + #elif Y_HOME_TO_MAX && Z4_STOP_PIN == Y_MAX_PIN + #error "Z4_STOP_PIN can't be the same as Y_MAX_PIN when homing to Y_MAX" + #elif Z_HOME_TO_MIN && Z4_STOP_PIN == Z_MIN_PIN + #error "Z4_STOP_PIN can't be the same as Z_MIN_PIN when homing to Z_MIN" + #elif Z_HOME_TO_MAX && Z4_STOP_PIN == Z_MAX_PIN + #error "Z4_STOP_PIN can't be the same as Z_MAX_PIN when homing to Z_MAX" + #endif + #endif #endif #if defined(ENDSTOP_NOISE_THRESHOLD) && !WITHIN(ENDSTOP_NOISE_THRESHOLD, 2, 7) diff --git a/Marlin/src/inc/Version.h b/Marlin/src/inc/Version.h index fe24634b83..e033a908c4 100644 --- a/Marlin/src/inc/Version.h +++ b/Marlin/src/inc/Version.h @@ -42,7 +42,7 @@ * version was tagged. */ #ifndef STRING_DISTRIBUTION_DATE - #define STRING_DISTRIBUTION_DATE "2024-05-24" + #define STRING_DISTRIBUTION_DATE "2024-07-07" #endif /** diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp index 8fc775d4c2..8f7a31ffb4 100644 --- a/Marlin/src/inc/Warnings.cpp +++ b/Marlin/src/inc/Warnings.cpp @@ -789,7 +789,7 @@ * Input Shaping */ #if HAS_ZV_SHAPING - #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) + #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) #warning "Input Shaping for CORE / MARKFORGED kinematic axes is still experimental." #endif #if ENABLED(I2S_STEPPER_STREAM) diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp index ea73243250..ae92d0a5f8 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp @@ -467,6 +467,7 @@ bool MarlinUI::detected() { #endif void MarlinUI::clear_lcd() { lcd.clear(); } +void MarlinUI::clear_for_drawing() { clear_lcd(); } #if ENABLED(SHOW_BOOTSCREEN) @@ -1515,7 +1516,7 @@ void MarlinUI::draw_status_screen() { lower_right.column = 0; lower_right.row = 0; - clear_lcd(); + clear_for_drawing(); x_map_pixels = (HD44780_CHAR_WIDTH) * (MESH_MAP_COLS) - 2; // Minus 2 because we are drawing a box around the map y_map_pixels = (HD44780_CHAR_HEIGHT) * (MESH_MAP_ROWS) - 2; diff --git a/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp b/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp index b29653f7b0..6dc5a41fdd 100644 --- a/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp +++ b/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp @@ -376,6 +376,8 @@ void MarlinUI::clear_lcd() { lcd.clear_buffer(); } +void MarlinUI::clear_for_drawing() { clear_lcd(); } + #if HAS_LCD_CONTRAST void MarlinUI::_set_contrast() { lcd.setContrast(contrast); } #endif diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp index 1bc55630af..5e5267c95a 100644 --- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp +++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp @@ -374,12 +374,25 @@ void MarlinUI::draw_kill_screen() { } while (u8g.nextPage()); } -void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop +// Erase the LCD contents by drawing an empty box. +void MarlinUI::clear_lcd() { + u8g.setColorIndex(0); + u8g.firstPage(); + do { + u8g.drawBox(0, 0, u8g.getWidth(), u8g.getHeight()); + } while (u8g.nextPage()); + u8g.setColorIndex(1); +} + +// U8G displays are drawn over multiple loops so must do their own clearing. +void MarlinUI::clear_for_drawing() { + // Automatically cleared by Picture Loop +} #if HAS_DISPLAY_SLEEP void MarlinUI::sleep_display(const bool sleep/*=true*/) { static bool asleep = false; - if (asleep != sleep){ + if (asleep != sleep) { sleep ? u8g.sleepOn() : u8g.sleepOff(); asleep = sleep; } diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.h b/Marlin/src/lcd/dogm/marlinui_DOGM.h index 9025395f56..d3f38cd619 100644 --- a/Marlin/src/lcd/dogm/marlinui_DOGM.h +++ b/Marlin/src/lcd/dogm/marlinui_DOGM.h @@ -155,7 +155,11 @@ #if ENABLED(ALTERNATIVE_LCD) #define U8G_CLASS U8GLIB_SH1306_128X64_2X // 4 stripes #else - #define U8G_CLASS U8GLIB_SH1306_128X64 // 8 stripes + #if ENABLED(U8GLIB_SSD1306_SPI) + #define U8G_CLASS U8GLIB_SSD1306_128X64_SW_SPI_HAL + #else + #define U8G_CLASS U8GLIB_SH1306_128X64 // 8 stripes + #endif #endif #elif ANY(MKS_12864OLED, ZONESTAR_12864OLED) @@ -168,7 +172,11 @@ #if ENABLED(ALTERNATIVE_LCD) #define U8G_CLASS U8GLIB_SH1106_128X64_2X // 4 stripes #else - #define U8G_CLASS U8GLIB_SH1106_128X64 // 8 stripes + #if ENABLED(U8GLIB_SH1106_SPI) + #define U8G_CLASS U8GLIB_SH1106_128X64_SW_SPI_HAL + #else + #define U8G_CLASS U8GLIB_SH1106_128X64 // 8 stripes + #endif #endif #elif ENABLED(U8GLIB_SH1106_EINSTART) diff --git a/Marlin/src/lcd/dogm/u8g/HAL_LCD_class_defines.h b/Marlin/src/lcd/dogm/u8g/HAL_LCD_class_defines.h index 907fa43c9b..33a9c21c41 100644 --- a/Marlin/src/lcd/dogm/u8g/HAL_LCD_class_defines.h +++ b/Marlin/src/lcd/dogm/u8g/HAL_LCD_class_defines.h @@ -23,7 +23,7 @@ #include "../../../inc/MarlinConfig.h" -// use this file to create the public interface for device drivers that are NOT in the U8G library +// Use this file to create the public interface for device drivers that are NOT in the U8G library extern u8g_dev_t u8g_dev_st7565_64128n_HAL_2x_sw_spi; extern u8g_dev_t u8g_dev_st7565_64128n_HAL_2x_hw_spi; @@ -90,6 +90,30 @@ public: void init(uint8_t options = U8G_I2C_OPT_NONE) { U8GLIB::init(&u8g_dev_ssd1306_128x64_2x_i2c_2_wire, options); } }; +#if ENABLED(U8GLIB_SH1106_SPI) + extern u8g_dev_t u8g_dev_sh1106_128x64_HAL_sw_spi; + class U8GLIB_SH1106_128X64_SW_SPI_HAL : public U8GLIB { + public: + U8GLIB_SH1106_128X64_SW_SPI_HAL() : U8GLIB() { } + U8GLIB_SH1106_128X64_SW_SPI_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) {init(sck, mosi, cs, reset); } + void init(pin_t sck, pin_t mosi, pin_t cs, pin_t reset=U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_sh1106_128x64_HAL_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, U8G_PIN_NONE, (uint8_t)reset); + } + }; +#endif + +#if ENABLED(U8GLIB_SSD1306_SPI) + extern u8g_dev_t u8g_dev_ssd1306_128x64_HAL_sw_spi; + class U8GLIB_SSD1306_128X64_SW_SPI_HAL : public U8GLIB { + public: + U8GLIB_SSD1306_128X64_SW_SPI_HAL() : U8GLIB() { } + U8GLIB_SSD1306_128X64_SW_SPI_HAL(pin_t sck, pin_t mosi, pin_t cs, pin_t reset = U8G_PIN_NONE) {init(sck, mosi, cs, reset); } + void init(pin_t sck, pin_t mosi, pin_t cs, pin_t reset=U8G_PIN_NONE) { + U8GLIB::init(&u8g_dev_ssd1306_128x64_HAL_sw_spi, (uint8_t)sck, (uint8_t)mosi, (uint8_t)cs, U8G_PIN_NONE, (uint8_t)reset); + } + }; +#endif + // // Very basic support for 320x240 TFT screen // Tested on MKS Robin TFT_V2.0 with ST7789V controller diff --git a/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1306_sh1106_128x64_I2C.cpp b/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1306_sh1106_128x64_I2C.cpp index 4cd9b8f3c0..4d4756c298 100644 --- a/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1306_sh1106_128x64_I2C.cpp +++ b/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1306_sh1106_128x64_I2C.cpp @@ -77,35 +77,34 @@ uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq); -// The sh1106 is compatible to the ssd1306, but is 132x64. 128x64 display area is centered within -// the 132x64. +// SH1106 (132x64) is compatible with SSD1306 (128x64) by adding a small margin to the larger display + +#define SH1106_PAGE_ADR(N) (0x20), (N) +#define SH1106_COL_ADR(N) (0x10 | ((N) >> 4)), ((N) & 0xFF) +#define SH1106_COLUMN_RANGE(N,O) (0x21), (N), (O) +#define SH1106_PAGE_RANGE(N,O) (0x22), (N), (O) +#define SH1106_SCROLL(N) ((N) ? 0x2F : 0x2E) +#define SH1106_START_LINE(N) (0x40 | (N)) +#define SH1106_CONTRAST(N) (0x81), (N) +#define SH1106_CHARGE_PUMP(N) (0x8D), ((N) ? 0x14 : 0x10) +#define SH1106_ADC_REVERSE(N) ((N) ? 0xA1 : 0xA0) +#define SH1106_ALL_PIX(N) ((N) ? 0xA5 : 0xA4) +#define SH1106_INVERTED(N) ((N) ? 0xA7 : 0xA6) +#define SH1106_MUX_RATIO(N) (0xA8), (N) +#define SH1106_ON(N) ((N) ? 0xAF : 0xAE) +#define SH1106_OUT_MODE(N) ((N) ? 0xC8 : 0xC0) +#define SH1106_DISP_OFFS(N) (0xD3), (N) +#define SH1106_OSC_FREQ(R,F) (0xD5), ((F) << 4 | (R)) +#define SH1106_CHARGE_PER(P,D) (0xD9), ((D) << 4 | (P)) +#define SH1106_COM_CONFIG(N) (0xDA), ((N) ? 0x12 : 0x02) +#define SH1106_VCOM_DESEL(N) (0xDB), (N) +#define SH1106_NOOP() (0xE3) static const uint8_t u8g_dev_sh1106_128x64_data_start_2_wire[] PROGMEM = { - 0x010, // set upper 4 bit of the col adr to 0 - 0x002, // set lower 4 bit of the col adr to 2 (centered display with ssd1306) - U8G_ESC_END // end of sequence + SH1106_COL_ADR(2), // Column 2 to center 128 pixels in 132 pixels + U8G_ESC_END // End of sequence }; -#define SH1106_PAGE_ADR(N) (0x20), (N) -#define SH1106_COLUMN_RANGE(N) (0x21), (((N) >> 8) & 0xFF), ((N) & 0xFF) -#define SH1106_PAGE_RANGE(N,O) (0x22), (N), (O) -#define SH1106_SCROLL(N) ((N) ? 0x2F : 0x2E) -#define SH1106_START_LINE(N) (0x40 | (N)) -#define SH1106_CONTRAST(N) (0x81), (N) -#define SH1106_CHARGE_PUMP(N) (0x8D), ((N) ? 0x14 : 0x10) -#define SH1106_ADC_REVERSE(N) ((N) ? 0xA1 : 0xA0) -#define SH1106_ALL_PIX(N) ((N) ? 0xA5 : 0xA4) -#define SH1106_INVERTED(N) ((N) ? 0xA7 : 0xA6) -#define SH1106_MUX_RATIO(N) (0xA8), (N) -#define SH1106_ON(N) ((N) ? 0xAF : 0xAE) -#define SH1106_OUT_MODE(N) ((N) ? 0xC8 : 0xC0) -#define SH1106_DISP_OFFS(N) (0xD3), (N) -#define SH1106_OSC_FREQ(R,F) (0xD5), ((F) << 4 | (R)) -#define SH1106_CHARGE_PER(P,D) (0xD9), ((D) << 4 | (P)) -#define SH1106_COM_CONFIG(N) (0xDA), ((N) ? 0x12 : 0x02) -#define SH1106_VCOM_DESEL(N) (0xDB), (N) -#define SH1106_NOOP() (0xE3) - static const uint8_t u8g_dev_sh1106_128x64_init_seq_2_wire[] PROGMEM = { U8G_ESC_ADR(0), // Initiate command mode SH1106_ON(0), // Display off, sleep mode @@ -113,19 +112,19 @@ static const uint8_t u8g_dev_sh1106_128x64_init_seq_2_wire[] PROGMEM = { SH1106_DISP_OFFS(0), // Display offset SH1106_START_LINE(0), // Start line SH1106_ADC_REVERSE(1), // Segment remap A0/A1 - SH1106_OUT_MODE(1), // C0: scan dir normal, C8: reverse - SH1106_COM_CONFIG(1), // Com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) - SH1106_CONTRAST(0xCF), // [2] set contrast control - SH1106_PAGE_ADR(0x02), // 2012-05-27: page addressing mode - SH1106_COLUMN_RANGE(0x281), // Set column range from 0 through 131 - SH1106_PAGE_RANGE(0, 7), // Set page range from 0 through 7 - SH1106_CHARGE_PER(0x1, 0xF), // [2] pre-charge period 0x22/F1 + SH1106_OUT_MODE(1), // 0: scan dir normal, 1: reverse + SH1106_COM_CONFIG(1), // COM pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) + SH1106_CONTRAST(0xCF), // Set contrast control + SH1106_PAGE_ADR(0x02), // page addressing mode + SH1106_COLUMN_RANGE(2, 129), // Set column range 2 .. 129 + SH1106_PAGE_RANGE(0, 7), // Set page range 0 .. 7 + SH1106_CHARGE_PER(0x1, 0xF), // Pre-charge period SH1106_VCOM_DESEL(0x40), // Vcomh deselect level - SH1106_ALL_PIX(0), // Output ram to display + SH1106_ALL_PIX(0), // Output RAM to display SH1106_INVERTED(0), // Normal display mode SH1106_OSC_FREQ(0, 8), // Clock divide ratio (0:1) and oscillator frequency (8) - SH1106_CHARGE_PUMP(1), // [2] charge pump setting (P62): 0x14 enable, 0x10 disable - SH1106_SCROLL(0), // 2012-05-27: Deactivate scroll + SH1106_CHARGE_PUMP(1), // Charge pump setting + SH1106_SCROLL(0), // Deactivate scroll SH1106_ON(1), // Display on U8G_ESC_END // End of sequence }; @@ -136,28 +135,24 @@ uint8_t u8g_dev_sh1106_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t m u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_init_seq_2_wire); break; - case U8G_DEV_MSG_STOP: - break; + case U8G_DEV_MSG_STOP: break; case U8G_DEV_MSG_PAGE_NEXT: { - u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); - u8g_SetAddress(u8g, dev, 0); // instruction mode - u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_data_start_2_wire); - u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2)); // select current page - u8g_SetAddress(u8g, dev, 1); // data mode - u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *) pb->buf); - u8g_SetChipSelect(u8g, dev, 0); - u8g_SetAddress(u8g, dev, 0); // instruction mode - u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_data_start_2_wire); - u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2+1)); // select current page - u8g_SetAddress(u8g, dev, 1); // data mode - u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width); - u8g_SetChipSelect(u8g, dev, 0); - } - break; - case U8G_DEV_MSG_SLEEP_ON: - return 1; - case U8G_DEV_MSG_SLEEP_OFF: - return 1; + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_SetAddress(u8g, dev, 0); // Instruction mode + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_data_start_2_wire); + u8g_WriteByte(u8g, dev, 0xB0 | (pb->p.page*2)); // Select current page + u8g_SetAddress(u8g, dev, 1); // Data mode + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *) pb->buf); + u8g_SetChipSelect(u8g, dev, 0); + u8g_SetAddress(u8g, dev, 0); // Instruction mode + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_data_start_2_wire); + u8g_WriteByte(u8g, dev, 0xB0 | (pb->p.page*2+1)); // Select current page + u8g_SetAddress(u8g, dev, 1); // Data mode + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width); + u8g_SetChipSelect(u8g, dev, 0); + } break; + case U8G_DEV_MSG_SLEEP_ON: return 1; + case U8G_DEV_MSG_SLEEP_OFF: return 1; } return u8g_dev_pb16v1_base_fn(u8g, dev, msg, arg); } @@ -169,33 +164,32 @@ u8g_dev_t u8g_dev_sh1106_128x64_2x_i2c_2_wire = { u8g_dev_sh1106_128x64_2x_2_wir ///////////////////////////////////////////////////////////////////////////////////////////// static const uint8_t u8g_dev_ssd1306_128x64_data_start_2_wire[] PROGMEM = { - 0x010, // set upper 4 bit of the col adr to 0 - 0x000, // set lower 4 bit of the col adr to 0 - U8G_ESC_END // end of sequence + SH1106_COL_ADR(0), // Column 0 + U8G_ESC_END // End of sequence }; static const uint8_t u8g_dev_ssd1306_128x64_init_seq_2_wire[] PROGMEM = { - U8G_ESC_ADR(0), // initiate command mode - 0x0AE, // display off, sleep mode - 0x0A8, 0x03F, // mux ratio - 0x0D3, 0x00, // display offset - 0x040, // start line - 0x0A1, // segment remap a0/a1 - 0x0C8, // c0: scan dir normal, c8: reverse - 0x0DA, 0x012, // com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) - 0x081, 0x0CF, // [2] set contrast control - 0x020, 0x002, // 2012-05-27: page addressing mode - 0x21, 0, 0x7F, // set column range from 0 through 127 - 0x22, 0, 7, // set page range from 0 through 7 - 0x0D9, 0x0F1, // [2] pre-charge period 0x022/f1 - 0x0DB, 0x040, // vcomh deselect level - 0x0A4, // output ram to display - 0x0A6, // none inverted normal display mode - 0x0D5, 0x080, // clock divide ratio (0x00=1) and oscillator frequency (0x8) - 0x08D, 0x014, // [2] charge pump setting (p62): 0x014 enable, 0x010 disable - 0x02E, // 2012-05-27: Deactivate scroll - 0x0AF, // display on - U8G_ESC_END // end of sequence + U8G_ESC_CS(0), // Disable chip + SH1106_ON(0), // Display off, sleep mode + SH1106_MUX_RATIO(0x3F), // Mux ratio + SH1106_DISP_OFFS(0), // Display offset + SH1106_START_LINE(0), // Start line + SH1106_ADC_REVERSE(1), // Segment remap A0/A1 + SH1106_OUT_MODE(1), // 0: scan dir normal, 1: reverse + SH1106_COM_CONFIG(1), // COM pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) + SH1106_CONTRAST(0xCF), // Set contrast control + SH1106_PAGE_ADR(0x02), // page addressing mode + SH1106_COLUMN_RANGE(0, 127), // Set column range 0 .. 127 + SH1106_PAGE_RANGE(0, 7), // Set page range from 0 .. 7 + SH1106_CHARGE_PER(0x1, 0xF), // Pre-charge period + SH1106_VCOM_DESEL(0x40), // Vcomh deselect level + SH1106_ALL_PIX(0), // Send RAM to display + SH1106_INVERTED(0), // Normal display mode + SH1106_OSC_FREQ(0, 8), // Clock divide ratio (0:1) and oscillator frequency (8) + SH1106_CHARGE_PUMP(1), // Charge pump setting + SH1106_SCROLL(0), // Deactivate scroll + SH1106_ON(1), // Display on + U8G_ESC_END // End of sequence }; uint8_t u8g_dev_ssd1306_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { @@ -204,28 +198,24 @@ uint8_t u8g_dev_ssd1306_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_init_seq_2_wire); break; - case U8G_DEV_MSG_STOP: - break; + case U8G_DEV_MSG_STOP: break; case U8G_DEV_MSG_PAGE_NEXT: { - u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); - u8g_SetAddress(u8g, dev, 0); // instruction mode - u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_data_start_2_wire); - u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2)); // select current page - u8g_SetAddress(u8g, dev, 1); // data mode - u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *) pb->buf); - u8g_SetChipSelect(u8g, dev, 0); - u8g_SetAddress(u8g, dev, 0); // instruction mode - u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_data_start_2_wire); - u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2+1)); // select current page - u8g_SetAddress(u8g, dev, 1); // data mode - u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width); - u8g_SetChipSelect(u8g, dev, 0); - } - break; - case U8G_DEV_MSG_SLEEP_ON: - return 1; - case U8G_DEV_MSG_SLEEP_OFF: - return 1; + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_SetAddress(u8g, dev, 0); // Instruction mode + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_data_start_2_wire); + u8g_WriteByte(u8g, dev, 0xB0 | (pb->p.page*2)); // Select current page + u8g_SetAddress(u8g, dev, 1); // Data mode + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *) pb->buf); + u8g_SetChipSelect(u8g, dev, 0); + u8g_SetAddress(u8g, dev, 0); // Instruction mode + u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_data_start_2_wire); + u8g_WriteByte(u8g, dev, 0xB0 | (pb->p.page*2+1)); // Select current page + u8g_SetAddress(u8g, dev, 1); // Data mode + u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width); + u8g_SetChipSelect(u8g, dev, 0); + } break; + case U8G_DEV_MSG_SLEEP_ON: return 1; + case U8G_DEV_MSG_SLEEP_OFF: return 1; } return u8g_dev_pb16v1_base_fn(u8g, dev, msg, arg); } @@ -236,10 +226,10 @@ u8g_dev_t u8g_dev_ssd1306_128x64_2x_i2c_2_wire = { u8g_dev_ssd1306_128x64_2x_2_w ///////////////////////////////////////////////////////////////////////////////////////////// -// This routine adds the instruction byte in between the command bytes. This makes the init -// sequences a lot easier to read. +// This routine adds the instruction byte in between the command bytes. +// This makes the init sequences a lot easier to read. -#define I2C_CMD_MODE 0x080 +#define I2C_CMD_MODE 0x80 uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq) { uint8_t is_escape = 0; @@ -247,10 +237,8 @@ uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_s uint8_t value = u8g_pgm_read(esc_seq); if (is_escape == 0) { if (value != 255) { - if (u8g_WriteByte(u8g, dev, value) == 0 ) - return 0; - if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0 ) - return 0; + if (u8g_WriteByte(u8g, dev, value) == 0) return 0; + if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0) return 0; } else { is_escape = 1; @@ -258,16 +246,14 @@ uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_s } else { if (value == 255) { - if (u8g_WriteByte(u8g, dev, value) == 0 ) - return 0; - if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0 ) - return 0; + if (u8g_WriteByte(u8g, dev, value) == 0) return 0; + if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0) return 0; } else if (value == 254) { break; } - else if (value >= 0x0F0) { - /* not yet used, do nothing */ + else if (value >= 0xF0) { + // not yet used, do nothing } else if (value >= 0xE0 ) { u8g_SetAddress(u8g, dev, value & 0x0F); @@ -279,13 +265,14 @@ uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_s u8g_SetResetLow(u8g, dev); value &= 0x0F; value <<= 4; - value+=2; + value += 2; u8g_Delay(value); u8g_SetResetHigh(u8g, dev); u8g_Delay(value); } - else if (value >= 0xBE) { /* not yet implemented */ - /* u8g_SetVCC(u8g, dev, value & 0x01); */ + else if (value >= 0xBE) { + // not yet implemented + //u8g_SetVCC(u8g, dev, value & 0x01); } else if (value <= 127) { u8g_Delay(value); diff --git a/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1306_sh1106_128x64_SWSPI.cpp b/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1306_sh1106_128x64_SWSPI.cpp new file mode 100644 index 0000000000..afb3c28a8c --- /dev/null +++ b/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1306_sh1106_128x64_SWSPI.cpp @@ -0,0 +1,246 @@ +/** + * 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 . + * + */ + +/** + * Based on u8g_dev_ssd1306_128x64.c + * + * Universal 8bit Graphics Library + * + * Copyright (c) 2015, olikraus@gmail.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "../../../inc/MarlinConfig.h" + +#if ALL(HAS_MARLINUI_U8GLIB, FORCE_SOFT_SPI) && ANY(U8GLIB_SH1106_SPI, U8GLIB_SSD1306_SPI) + +#include "HAL_LCD_com_defines.h" + +#define WIDTH 128 +#define HEIGHT 64 +#define PAGE_HEIGHT 8 + +#define SH1106_PAGE_ADR(N) (0x20), (N) +#define SH1106_COL_ADR(N) (0x10 | ((N) >> 4)), ((N) & 0xFF) +#define SH1106_COLUMN_RANGE(N,O) (0x21), (N), (O) +#define SH1106_PAGE_RANGE(N,O) (0x22), (N), (O) +#define SH1106_SCROLL(N) ((N) ? 0x2F : 0x2E) +#define SH1106_START_LINE(N) (0x40 | (N)) +#define SH1106_CONTRAST(N) (0x81), (N) +#define SH1106_CHARGE_PUMP(N) (0x8D), ((N) ? 0x14 : 0x10) +#define SH1106_ADC_REVERSE(N) ((N) ? 0xA1 : 0xA0) +#define SH1106_ALL_PIX(N) ((N) ? 0xA5 : 0xA4) +#define SH1106_INVERTED(N) ((N) ? 0xA7 : 0xA6) +#define SH1106_MUX_RATIO(N) (0xA8), (N) +#define SH1106_ON(N) ((N) ? 0xAF : 0xAE) +#define SH1106_OUT_MODE(N) ((N) ? 0xC8 : 0xC0) +#define SH1106_DISP_OFFS(N) (0xD3), (N) +#define SH1106_OSC_FREQ(R,F) (0xD5), ((F) << 4 | (R)) +#define SH1106_CHARGE_PER(P,D) (0xD9), ((D) << 4 | (P)) +#define SH1106_COM_CONFIG(N) (0xDA), ((N) ? 0x12 : 0x02) +#define SH1106_VCOM_DESEL(N) (0xDB), (N) +#define SH1106_NOOP() (0xE3) + +static const uint8_t u8g_dev_ssd13xx_HAL_sleep_on[] PROGMEM = { + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + SH1106_ON(0) // Display off + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence +}; + +static const uint8_t u8g_dev_ssd13xx_HAL_sleep_off[] PROGMEM = { + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + SH1106_ON(1), // Display on + U8G_ESC_DLY(50), // Delay 50 ms + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence +}; + +#if ENABLED(U8GLIB_SH1106_SPI) + +// Init sequence Adafruit 128x64 OLED (NOT TESTED). Like Adafruit3, but with page addressing mode. +static const uint8_t u8g_dev_sh1106_128x64_HAL_init_seq[] PROGMEM = { + U8G_ESC_CS(0), // Disable chip + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_RST(1), // Do reset low pulse with (1*16)+2 milliseconds + U8G_ESC_CS(1), // Enable chip + SH1106_ON(0), // Display off, sleep mode + SH1106_OSC_FREQ(0, 8), // Clock divide ratio (0:1) and oscillator frequency (8) + SH1106_MUX_RATIO(0x3F), // Mux ratio + SH1106_DISP_OFFS(0), // Display offset + SH1106_START_LINE(0), // Start line + SH1106_CHARGE_PUMP(1), // Charge pump setting + SH1106_PAGE_ADR(0x02), // page addressing mode + SH1106_ADC_REVERSE(1), // Segment remap A0/A1 + SH1106_OUT_MODE(1), // 0: scan dir normal, 1: reverse + SH1106_COM_CONFIG(1), // COM pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) + SH1106_CONTRAST(0x80), // Set contrast control + SH1106_CHARGE_PER(0x1, 0xF), // Pre-charge period + SH1106_VCOM_DESEL(0x40), // Vcomh deselect level + SH1106_SCROLL(0), // Deactivate scroll + SH1106_ALL_PIX(0), // Output RAM to display + SH1106_INVERTED(0), // Normal display mode + SH1106_ON(1), // Display on + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence +}; + +// SH1106 (132x64) is compatible with SSD1306 (128x64) by adding a small margin to the larger display +static const uint8_t u8g_dev_sh1106_128x64_HAL_data_start[] PROGMEM = { + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + SH1106_COL_ADR(2), // Column 2 to center 128 pixels in 132 pixels + U8G_ESC_END // End of sequence +}; + +uint8_t u8g_dev_sh1106_128x64_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + switch(msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_sh1106_128x64_HAL_init_seq); + break; + case U8G_DEV_MSG_STOP: + break; + case U8G_DEV_MSG_PAGE_NEXT: { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_sh1106_128x64_HAL_data_start); + u8g_WriteByte(u8g, dev, 0x0B0 | pb->p.page); // Select current page (SSD1306) + u8g_SetAddress(u8g, dev, 1); // Data mode + if (u8g_pb_WriteBuffer(pb, u8g, dev) == 0) return 0; + u8g_SetChipSelect(u8g, dev, 0); + } break; + case U8G_DEV_MSG_SLEEP_ON: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd13xx_HAL_sleep_on); + return 1; + case U8G_DEV_MSG_SLEEP_OFF: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd13xx_HAL_sleep_off); + return 1; + case U8G_DEV_MSG_CONTRAST: + u8g_SetChipSelect(u8g, dev, 1); + u8g_SetAddress(u8g, dev, 0); // Instruction mode + u8g_WriteByte(u8g, dev, 0x81); + u8g_WriteByte(u8g, dev, *(uint8_t *) arg); + u8g_SetChipSelect(u8g, dev, 0); + return 1; + } + return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg); +} + +U8G_PB_DEV(u8g_dev_sh1106_128x64_HAL_sw_spi, WIDTH, HEIGHT, PAGE_HEIGHT, u8g_dev_sh1106_128x64_HAL_fn, U8G_COM_HAL_SW_SPI_FN); + +#elif ENABLED(U8GLIB_SSD1306_SPI) + +static const uint8_t u8g_dev_ssd1306_128x64_HAL_init_seq[] PROGMEM = { + U8G_ESC_CS(0), // Disable chip + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_RST(1), // Do reset low pulse with (1*16)+2 milliseconds + U8G_ESC_CS(1), // Enable chip + SH1106_ON(0), // Display off, sleep mode + SH1106_OSC_FREQ(0, 8), // Clock divide ratio (0:1) and oscillator frequency (8) + SH1106_MUX_RATIO(0x3F), // Mux ratio + SH1106_DISP_OFFS(0), // Display offset + SH1106_START_LINE(0), // Start line + SH1106_CHARGE_PUMP(1), // Charge pump setting + SH1106_PAGE_ADR(0x02), // page addressing mode + SH1106_ADC_REVERSE(1), // Segment remap A0/A1 + SH1106_OUT_MODE(1), // 0: scan dir normal, 1: reverse + SH1106_COM_CONFIG(1), // COM pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) + SH1106_CONTRAST(0x80), // Set contrast control + SH1106_CHARGE_PER(0x1, 0xF), // Pre-charge period + SH1106_VCOM_DESEL(0x40), // Vcomh deselect level + SH1106_SCROLL(0), // Deactivate scroll + SH1106_ALL_PIX(0), // Output RAM to display + SH1106_INVERTED(0), // Normal display mode + SH1106_ON(1), // Display on + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence +}; + +static const uint8_t u8g_dev_ssd1306_128x64_HAL_data_start[] PROGMEM = { + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + SH1106_COL_ADR(0), // Column 0 + U8G_ESC_END // End of sequence +}; + +uint8_t u8g_dev_ssd1306_128x64_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { + switch(msg) { + case U8G_DEV_MSG_INIT: + u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd1306_128x64_HAL_init_seq); + break; + case U8G_DEV_MSG_STOP: break; + case U8G_DEV_MSG_PAGE_NEXT: { + u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd1306_128x64_HAL_data_start); + u8g_WriteByte(u8g, dev, 0x0b0 | pb->p.page); // Select current page (SSD1306) + u8g_SetAddress(u8g, dev, 1); // Data mode + if (u8g_pb_WriteBuffer(pb, u8g, dev) == 0) return 0; + u8g_SetChipSelect(u8g, dev, 0); + } break; + case U8G_DEV_MSG_SLEEP_ON: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd13xx_HAL_sleep_on); + return 1; + case U8G_DEV_MSG_SLEEP_OFF: + u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd13xx_HAL_sleep_off); + return 1; + case U8G_DEV_MSG_CONTRAST: + u8g_SetChipSelect(u8g, dev, 1); + u8g_SetAddress(u8g, dev, 0); // Instruction mode + u8g_WriteByte(u8g, dev, 0x81); + u8g_WriteByte(u8g, dev, *(uint8_t *) arg); + u8g_SetChipSelect(u8g, dev, 0); + return 1; + } + return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg); +} + +U8G_PB_DEV(u8g_dev_ssd1306_128x64_HAL_sw_spi, WIDTH, HEIGHT, PAGE_HEIGHT, u8g_dev_ssd1306_128x64_HAL_fn, U8G_COM_HAL_SW_SPI_FN); + +#endif // U8GLIB_SSD1306_SPI +#endif // HAS_MARLINUI_U8GLIB diff --git a/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1309_12864.cpp b/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1309_12864.cpp index 4aa90d5e8e..010231d056 100644 --- a/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1309_12864.cpp +++ b/Marlin/src/lcd/dogm/u8g/u8g_dev_ssd1309_12864.cpp @@ -31,61 +31,83 @@ #define HEIGHT 64 #define PAGE_HEIGHT 8 +#define SSD1309_PAGE_ADR(N) (0x20), (N) +#define SSD1309_COL_ADR(N) (0x10 | ((N) >> 4)), ((N) & 0xFF) +#define SSD1309_COLUMN_RANGE(N,O) (0x21), (N), (O) +#define SSD1309_PAGE_RANGE(N,O) (0x22), (N), (O) +#define SSD1309_SCROLL(N) ((N) ? 0x2F : 0x2E) +#define SSD1309_START_LINE(N) (0x40 | (N)) +#define SSD1309_CONTRAST(N) (0x81), (N) +#define SSD1309_CHARGE_PUMP(N) (0x8D), ((N) ? 0x14 : 0x10) +#define SSD1309_ADC_REVERSE(N) ((N) ? 0xA1 : 0xA0) +#define SSD1309_ALL_PIX(N) ((N) ? 0xA5 : 0xA4) +#define SSD1309_INVERTED(N) ((N) ? 0xA7 : 0xA6) +#define SSD1309_MUX_RATIO(N) (0xA8), (N) +#define SSD1309_ON(N) ((N) ? 0xAF : 0xAE) +#define SSD1309_OUT_MODE(N) ((N) ? 0xC8 : 0xC0) +#define SSD1309_DISP_OFFS(N) (0xD3), (N) +#define SSD1309_OSC_FREQ(R,F) (0xD5), ((F) << 4 | (R)) +#define SSD1309_CHARGE_PER(P,D) (0xD9), ((D) << 4 | (P)) +#define SSD1309_COM_CONFIG(N) (0xDA), ((N) ? 0x12 : 0x02) +#define SSD1309_VCOM_DESEL(N) (0xDB), (N) +#define SSD1309_NOOP() (0xE3) +#define SSD1309_COMMAND_LOCK(N) (0xFD), ((N) ? 0x16 : 0x12) + // SSD1309 init sequence static const uint8_t u8g_dev_ssd1309_128x64_init_seq[] PROGMEM = { - U8G_ESC_CS(0), // Disable chip - U8G_ESC_ADR(0), // Instruction mode - U8G_ESC_RST(1), // Do reset low pulse with (1*16)+2 milliseconds - U8G_ESC_CS(1), // Enable chip + U8G_ESC_CS(0), // Disable chip + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_RST(1), // Do reset low pulse with (1*16)+2 milliseconds + U8G_ESC_CS(1), // Enable chip - 0xFD,0x12, // Command Lock - 0xAE, // Set Display Off - 0xD5,0xA0, // Set Display Clock Divide Ratio/Oscillator Frequency - 0xA8,0x3F, // Set Multiplex Ratio - 0x3D,0x00, // Set Display Offset - 0x40, // Set Display Start Line - 0xA1, // Set Segment Re-Map - 0xC8, // Set COM Output Scan Direction - 0xDA,0x12, // Set COM Pins Hardware Configuration - 0x81,0xDF, // Set Current Control - 0xD9,0x82, // Set Pre-Charge Period - 0xDB,0x34, // Set VCOMH Deselect Level - 0xA4, // Set Entire Display On/Off - 0xA6, // Set Normal/Inverse Display - U8G_ESC_VCC(1), // Power up VCC & Stabilized + SSD1309_COMMAND_LOCK(0), // Unlock OLED driver IC MCU command interface + SSD1309_ON(0), + SSD1309_OSC_FREQ(0, 10), // Clock divide ratio (0:1) and oscillator frequency (8) + SSD1309_MUX_RATIO(0x3F), // Mux ratio + SSD1309_DISP_OFFS(0), // Display offset + SSD1309_START_LINE(0), // Start line + SSD1309_ADC_REVERSE(1), // Segment remap A0/A1 + SSD1309_OUT_MODE(1), // 0: scan dir normal, 1: reverse + SSD1309_COM_CONFIG(1), // COM pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) + SSD1309_CONTRAST(0xDF), // Set contrast control + SSD1309_CHARGE_PER(0x2, 0x8), // Pre-charge period + SSD1309_VCOM_DESEL(0x34), // Vcomh deselect level + SSD1309_ALL_PIX(0), // Output RAM to display + SSD1309_INVERTED(0), // Normal display mode + + U8G_ESC_VCC(1), // Power up VCC & stabilize U8G_ESC_DLY(50), - 0xAF, // Set Display On + SSD1309_ON(1), // Display on U8G_ESC_DLY(50), - U8G_ESC_CS(0), // Disable chip - U8G_ESC_END // End of sequence + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence }; // Select one init sequence here #define u8g_dev_ssd1309_128x64_init_seq u8g_dev_ssd1309_128x64_init_seq static const uint8_t u8g_dev_ssd1309_128x64_data_start[] PROGMEM = { - U8G_ESC_ADR(0), // Instruction mode - U8G_ESC_CS(1), // Enable chip - 0x010, // Set upper 4 bit of the col adr to 0 - 0x000, // Set lower 4 bit of the col adr to 4 - U8G_ESC_END // End of sequence + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + SSD1309_COL_ADR(0), // Column 0 + U8G_ESC_END // End of sequence }; static const uint8_t u8g_dev_ssd13xx_sleep_on[] PROGMEM = { - U8G_ESC_ADR(0), // Instruction mode - U8G_ESC_CS(1), // Enable chip - 0x0AE, // Display off - U8G_ESC_CS(0), // Disable chip - U8G_ESC_END // End of sequence + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + SSD1309_ON(0), // Display off + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence }; static const uint8_t u8g_dev_ssd13xx_sleep_off[] PROGMEM = { - U8G_ESC_ADR(0), // Instruction mode - U8G_ESC_CS(1), // Enable chip - 0x0AF, // Display on - U8G_ESC_DLY(50), // Delay 50 ms - U8G_ESC_CS(0), // Disable chip - U8G_ESC_END // End of sequence + U8G_ESC_ADR(0), // Instruction mode + U8G_ESC_CS(1), // Enable chip + SSD1309_ON(1), // Display on + U8G_ESC_DLY(50), // Delay 50 ms + U8G_ESC_CS(0), // Disable chip + U8G_ESC_END // End of sequence }; uint8_t u8g_dev_ssd1309_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { @@ -99,7 +121,7 @@ uint8_t u8g_dev_ssd1309_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void case U8G_DEV_MSG_PAGE_NEXT: { u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); u8g_WriteEscSeqP(u8g, dev, u8g_dev_ssd1309_128x64_data_start); - u8g_WriteByte(u8g, dev, 0x0B0 | pb->p.page); // Select current page (SSD1306) + u8g_WriteByte(u8g, dev, 0xB0 | pb->p.page); // Select current page (SSD1306) u8g_SetAddress(u8g, dev, 1); // Data mode if (u8g_pb_WriteBuffer(pb, u8g, dev) == 0) return 0; u8g_SetChipSelect(u8g, dev, 0); @@ -108,8 +130,8 @@ uint8_t u8g_dev_ssd1309_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void case U8G_DEV_MSG_CONTRAST: u8g_SetChipSelect(u8g, dev, 1); u8g_SetAddress(u8g, dev, 0); // Instruction mode - u8g_WriteByte(u8g, dev, 0x081); - u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) ); // 11 Jul 2015: fixed contrast calculation + u8g_WriteByte(u8g, dev, 0x81); + u8g_WriteByte(u8g, dev, (*(uint8_t *)arg)); u8g_SetChipSelect(u8g, dev, 0); return 1; case U8G_DEV_MSG_SLEEP_ON: diff --git a/Marlin/src/lcd/dogm/u8g/u8g_dev_uc1701_mini12864_HAL.cpp b/Marlin/src/lcd/dogm/u8g/u8g_dev_uc1701_mini12864_HAL.cpp index 95ae2810f2..f9c68c15fc 100644 --- a/Marlin/src/lcd/dogm/u8g/u8g_dev_uc1701_mini12864_HAL.cpp +++ b/Marlin/src/lcd/dogm/u8g/u8g_dev_uc1701_mini12864_HAL.cpp @@ -130,7 +130,7 @@ static const uint8_t u8g_dev_uc1701_mini12864_HAL_data_start[] PROGMEM = { UC1701_V5_RATIO(3), // set V0 voltage resistor ratio to large UC1701_INDICATOR(0), // indicator disable UC1701_ON(1), // display on - UC1701_COLUMN_HI(0), // set upper 4 bit of the col adr to 0 + UC1701_COLUMN_HI(0), // set upper 4 bits of the col adr to 0 U8G_ESC_END, // end of sequence U8G_ESC_DLY(5) // delay 5 ms #else diff --git a/Marlin/src/lcd/e3v2/creality/dwin.cpp b/Marlin/src/lcd/e3v2/creality/dwin.cpp index 7f057137d8..34bdd29694 100644 --- a/Marlin/src/lcd/e3v2/creality/dwin.cpp +++ b/Marlin/src/lcd/e3v2/creality/dwin.cpp @@ -1816,6 +1816,8 @@ void hmiSDCardInit() { card.cdroot(); } // Initialize or re-initialize the LCD void MarlinUI::init_lcd() { dwinStartup(); } +void MarlinUI::clear_lcd() {} + void MarlinUI::update() { eachMomentUpdate(); // Status update hmiSDCardUpdate(); // SD card update diff --git a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp index c9191dd31d..2edc03dfd6 100644 --- a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp @@ -828,7 +828,7 @@ void JyersDWIN::drawStatusArea(const bool icons/*=false*/) { } if (planner.flow_percentage[0] != flow) { flow = planner.flow_percentage[0]; - dwinDrawIntValue(true, true, 0, DWIN_FONT_STAT, getColor(eeprom_settings.status_area_text, COLOR_WHITE), COLOR_BG_BLACK, 3, 116 + 2 * STAT_CHR_W, 417, planner.flow_percentage[0]); + dwinDrawIntValue(true, true, 0, DWIN_FONT_STAT, getColor(eeprom_settings.status_area_text, COLOR_WHITE), COLOR_BG_BLACK, 3, 116 + 2 * STAT_CHR_W, 417, flow); } #endif @@ -5155,6 +5155,8 @@ void MarlinUI::init_lcd() { jyersDWIN.redrawScreen(); } +void MarlinUI::clear_lcd() {} + #if ENABLED(ADVANCED_PAUSE_FEATURE) void MarlinUI::pause_show_message(const PauseMessage message, const PauseMode mode/*=PAUSE_MODE_SAME*/, const uint8_t extruder/*=active_extruder*/) { if (mode != PAUSE_MODE_SAME) pause_mode = mode; diff --git a/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp b/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp index 4a60f77c9d..31cf269227 100644 --- a/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp +++ b/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp @@ -90,6 +90,8 @@ void MarlinUI::clear_lcd() { did_first_redraw = false; } +void MarlinUI::clear_for_drawing() { clear_lcd(); } + #if ENABLED(SHOW_BOOTSCREEN) void MarlinUI::show_bootscreen() { @@ -111,7 +113,7 @@ void MarlinUI::clear_lcd() { dwinDrawString(false, font10x20, COLOR_YELLOW, COLOR_BG_BLACK, INFO_CENTER - (dwin_string.length * 10) / 2, VERSION_Y, S(dwin_string.string())); TERN_(SHOW_CUSTOM_BOOTSCREEN, safe_delay(CUSTOM_BOOTSCREEN_TIMEOUT)); - clear_lcd(); + clear_for_drawing(); dwinIconShow(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2, 15); #if ENABLED(DWIN_MARLINUI_PORTRAIT) @@ -132,7 +134,7 @@ void MarlinUI::clear_lcd() { void MarlinUI::bootscreen_completion(const millis_t sofar) { if ((BOOTSCREEN_TIMEOUT) > sofar) safe_delay((BOOTSCREEN_TIMEOUT) - sofar); - clear_lcd(); + clear_for_drawing(); } #endif diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 56c7fec517..2b691326c0 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -1913,6 +1913,8 @@ void MarlinUI::init_lcd() { dwinJPGCacheTo1(Language_English); } +void MarlinUI::clear_lcd() {} + void dwinInitScreen() { dwinSetColorDefaults(); hmiInit(); // Draws boot screen diff --git a/Marlin/src/lcd/e3v2/proui/proui_extui.cpp b/Marlin/src/lcd/e3v2/proui/proui_extui.cpp index ae85a5a60c..2adca7cbe6 100644 --- a/Marlin/src/lcd/e3v2/proui/proui_extui.cpp +++ b/Marlin/src/lcd/e3v2/proui/proui_extui.cpp @@ -195,6 +195,7 @@ namespace ExtUI { void onPIDTuning(const pidresult_t rst) { // Called for temperature PID tuning result switch (rst) { + default: break; #if ENABLED(PIDTEMP) case PID_STARTED: dwinPIDTuning(PIDTEMP_START); break; #endif diff --git a/Marlin/src/lcd/extui/anycubic/common_defs.h b/Marlin/src/lcd/extui/anycubic/common_defs.h index 4257f1dabf..7ec336889f 100644 --- a/Marlin/src/lcd/extui/anycubic/common_defs.h +++ b/Marlin/src/lcd/extui/anycubic/common_defs.h @@ -27,20 +27,18 @@ #include "../../../inc/MarlinConfigPre.h" -#define ACDEBUGLEVEL 0 // 0: off, 255: all levels enabled +// Bit-masks for selective debug +#define AC_INFO 1 +#define AC_ACTION 2 +#define AC_FILE 4 +#define AC_PANEL 8 +#define AC_MARLIN 16 +#define AC_SOME 32 +#define AC_ALL 64 +//#define ACDEBUGLEVEL AC_MARLIN // 0: off, 255: all levels enabled #if ACDEBUGLEVEL - // Bit-masks for selective debug: - enum ACDebugMask : uint8_t { - AC_INFO = 1, - AC_ACTION = 2, - AC_FILE = 4, - AC_PANEL = 8, - AC_MARLIN = 16, - AC_SOME = 32, - AC_ALL = 64 - }; - #define ACDEBUG(mask) ( ((mask) & ACDEBUGLEVEL) == mask ) // Debug flag macro + #define ACDEBUG(mask) ((mask) & ACDEBUGLEVEL) #else #define ACDEBUG(mask) false #endif diff --git a/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.cpp b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.cpp index 9be00411cc..815d0783bf 100644 --- a/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.cpp +++ b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.cpp @@ -52,25 +52,6 @@ namespace Anycubic { - const char MESSAGE_charu[] = {0xB4, 0xE6, 0xB4, 0xA2, 0xBF, 0xA8, 0xD2, 0xD1, 0xB2, 0xE5, 0xC8, 0xEB, 0x00}; // '忙'垄驴篓脪脩虏氓脠毛 - const char MESSAGE_bachu[] = {0xB4, 0xE6, 0xB4, 0xA2, 0xBF, 0xA8, 0xD2, 0xD1, 0xB0, 0xCE, 0xB3, 0xF6, 0x00}; - const char MESSAGE_wuka[] = {0xCE, 0xDE, 0xB4, 0xE6, 0xB4, 0xA2, 0xBF, 0xA8, 0x00}; - const char MESSAGE_lianji[] = {0xC1, 0xAA, 0xBB, 0xFA, 0xD6, 0xD0, 0x00}; - const char MESSAGE_tuoji[] = {0xCD, 0xD1, 0xBB, 0xFA, 0xB4, 0xF2, 0xD3, 0xA1, 0xD6, 0xD0, 0x00}; - const char MESSAGE_zanting[] = {0xB4, 0xF2, 0xD3, 0xA1, 0xD4, 0xDD, 0xCD, 0xA3, 0xD6, 0xD0, 0x00}; - const char MESSAGE_tingzhi[] = {0xCD, 0xA3, 0xD6, 0xB9, 0xB4, 0xF2, 0xD3, 0xA1, 0x00}; - const char MESSAGE_wancheng[] = {0xCD, 0xEA, 0xB3, 0xC9, 0xB4, 0xF2, 0xD3, 0xA1, 0x00}; - const char MESSAGE_hotend_heating[] = {0xB4, 0xF2, 0xD3, 0xA1, 0xCD, 0xB7, 0xD5, 0xFD, 0xD4, 0xDA, 0xBC, 0xD3, 0xC8, 0xC8, 0x00}; - const char MESSAGE_hotend_over[] = {0xB4, 0xF2, 0xD3, 0xA1, 0xCD, 0xB7, 0xBC, 0xD3, 0xC8, 0xC8, 0xCD, 0xEA, 0xB3, 0xC9, 0x00}; - const char MESSAGE_bed_heating[] = {0xC8, 0xC8, 0xB4, 0xB2, 0xD5, 0xFD, 0xD4, 0xDA, 0xBC, 0xD3, 0xC8, 0xC8, 0x00}; - const char MESSAGE_bed_over[] = {0xC8, 0xC8, 0xB4, 0xB2, 0xBC, 0xD3, 0xC8, 0xC8, 0xCD, 0xEA, 0xB3, 0xC9, 0x00}; - const char MESSAGE_ready[] = {0xD7, 0xBC, 0xB1, 0xB8, 0xBE, 0xCD, 0xD0, 0xF7, 0x00}; - const char MESSAGE_cold[] = {0xB4, 0xF2, 0xD3, 0xA1, 0xCD, 0xB7, 0xCE, 0xC2, 0xB6, 0xC8, 0xB9, 0xFD, 0xB5, 0xCD, 0x00}; - - const char *p_mesage[] = { MESSAGE_charu, MESSAGE_bachu, MESSAGE_wuka, MESSAGE_lianji, MESSAGE_tuoji, MESSAGE_zanting, - MESSAGE_tingzhi, MESSAGE_wancheng, MESSAGE_hotend_heating, MESSAGE_hotend_over, MESSAGE_bed_heating, - MESSAGE_bed_over, MESSAGE_ready, MESSAGE_cold }; - DgusTFT::p_fun fun_array[] = { DgusTFT::page1, DgusTFT::page2, DgusTFT::page3, DgusTFT::page4, DgusTFT::page5, DgusTFT::page6, DgusTFT::page7, DgusTFT::page8, DgusTFT::page9, DgusTFT::page10, DgusTFT::page11, DgusTFT::page12, @@ -100,28 +81,30 @@ namespace Anycubic { uint8_t DgusTFT::data_buf[DATA_BUF_SIZE]; uint8_t DgusTFT::data_index; uint16_t DgusTFT::page_index_now, DgusTFT::page_index_last, DgusTFT::page_index_last_2; - uint8_t DgusTFT::message_index; uint8_t DgusTFT::pop_up_index; uint32_t DgusTFT::key_value; uint8_t DgusTFT::lcd_txtbox_index; uint8_t DgusTFT::lcd_txtbox_page; - int16_t DgusTFT::feedrate_back; + uint16_t DgusTFT::feedrate_back; lcd_info_t DgusTFT::lcd_info, DgusTFT::lcd_info_back; language_t DgusTFT::ui_language; - uint16_t page_index_saved; // flags to keep from bombing the host display - uint8_t pop_up_index_saved; - uint32_t key_value_saved; + + #if ACDEBUG(AC_MARLIN) + uint16_t page_index_saved; // flags to keep from bombing the host display + uint32_t key_value_saved; + #endif void DEBUG_PRINT_PAUSED_STATE(const paused_state_t state, FSTR_P const msg=nullptr); void DEBUG_PRINT_PRINTER_STATE(const printer_state_t state, FSTR_P const msg=nullptr); void DEBUG_PRINT_TIMER_EVENT(const timer_event_t event, FSTR_P const msg=nullptr); void DEBUG_PRINT_MEDIA_EVENT(const media_event_t event, FSTR_P const msg=nullptr); + void set_brightness(); + DgusTFT dgus; DgusTFT::DgusTFT() { data_buf[0] = '\0'; - message_index = 100; pop_up_index = 100; page_index_now = page_index_last = page_index_last_2 = 1; lcd_txtbox_index = 0; @@ -202,6 +185,14 @@ namespace Anycubic { } #endif + // Periodically update main page + if ((page_index_now == 121 || page_index_now == 1) && ((millis() % 500) == 0)) { + TERN_(HAS_HOTEND, send_temperature_hotend(TXT_MAIN_HOTEND)); + TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_MAIN_BED)); + set_brightness(); + delay(1); // wait for millis() to advance so this clause isn't repeated + } + switch (page_index_now) { case 115: page115(); break; case 117: page117(); break; @@ -435,12 +426,8 @@ namespace Anycubic { else { printer_state = AC_printer_stopping; - // Get Printing Time - uint32_t time = getProgress_seconds_elapsed() / 60; - char str_buf[20]; - sprintf(str_buf, "%s H ", utostr3(time / 60)); - sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60)); - sendTxtToTFT(str_buf, TXT_FINISH_TIME); + // Report Printing Time in minutes + sendTimeToTFT(getProgress_seconds_elapsed() / 60, TXT_FINISH_TIME); changePageOfTFT(PAGE_PRINT_FINISH); tftSendLn(AC_msg_print_complete); pop_up_index = 100; @@ -556,6 +543,9 @@ namespace Anycubic { static grid_count_t probe_cnt = 0; #endif + // Visible in main page + sendTxtToTFT_P(msg, TXT_MAIN_MESSAGE); + // The only way to get printer status is to parse messages // Use the state to minimise the work we do here. switch (printer_state) { @@ -672,13 +662,6 @@ namespace Anycubic { #if ENABLED(POWER_LOSS_RECOVERY) - void DgusTFT::powerLoss() { - // On: 5A A5 05 82 00 82 00 00 - // Off: 5A A5 05 82 00 82 00 64 - uint8_t data[] = { 0x5A, 0xA5, 0x05, 0x82, 0x00, 0x82, 0x00, uint8_t(recovery.enabled ? 0x00 : 0x64) }; - for (uint8_t i = 0; i < COUNT(data); ++i) TFTSer.write(data[i]); - } - void DgusTFT::powerLossRecovery() { printer_state = AC_printer_resuming_from_power_outage; // Play tune to notify user we can recover. } @@ -743,10 +726,15 @@ namespace Anycubic { } void DgusTFT::sendColorToTFT(const uint16_t color, const uint16_t address) { - uint8_t data[] = { 0x5A, 0xA5, 0x05, 0x82, uint8_t(address >> 8), uint8_t(address & 0xFF), uint8_t(color >> 8), uint8_t(color & 0xFF) }; + uint16_t color_address = address + 3; + uint8_t data[] = { 0x5A, 0xA5, 0x05, 0x82, uint8_t(color_address >> 8), uint8_t(color_address & 0xFF), uint8_t(color >> 8), uint8_t(color & 0xFF) }; for (uint8_t i = 0; i < COUNT(data); ++i) TFTSer.write(data[i]); } + void DgusTFT::sendTimeToTFT(const uint32_t minutes, const uint16_t address) { + sendTxtToTFT(MString<20>().setf(PSTR("%3d H %3d M"), minutes / 60, minutes % 60), TXT_PRINT_TIME); + } + void DgusTFT::sendReadNumOfTxtToTFT(const uint8_t number, const uint16_t address) { uint8_t data[] = { 0x5A, 0xA5, 0x04, 0x83, uint8_t(address >> 8), uint8_t(address & 0xFF), number }; for (uint8_t i = 0; i < COUNT(data); ++i) TFTSer.write(data[i]); @@ -801,6 +789,23 @@ namespace Anycubic { changePageOfTFT(page_index, true); } + void DgusTFT::debugPage(int page/*=0*/) { + #if ACDEBUG(AC_ALL) + if (page == 0) page = page_index_now; + if (page_index_saved != page_index_now || key_value_saved != key_value) { + DEBUG_ECHOLNPGM("page", page, " page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); + page_index_saved = page_index_now; + key_value_saved = key_value; + } + #endif + UNUSED(page); + } + + void DgusTFT::showAboutPage() { + sendTxtToTFT_P(getFirmwareName_str(), TXT_VERSION); + changePageOfTFT(PAGE_ABOUT); + } + void DgusTFT::lcdAudioSet(const bool audio_on) { // On: 5A A5 07 82 00 80 5A 00 00 1A // Off: 5A A5 07 82 00 80 5A 00 00 12 @@ -907,9 +912,10 @@ namespace Anycubic { } void DgusTFT::checkHeaters() { - static uint32_t time_last = 0; - if (PENDING(millis(), time_last)) return; - time_last = millis() + 500; + static uint32_t time_next = 0; + const millis_t ms = millis(); + if (PENDING(ms, time_next)) return; + time_next = ms + 500; float temp = 0; @@ -997,7 +1003,6 @@ namespace Anycubic { uint16_t control_index = 0; uint32_t control_value; uint16_t temp; - char str_buf[20]; if (data_received) { data_received = false; @@ -1014,8 +1019,6 @@ namespace Anycubic { control_value = (uint16_t(data_buf[4]) << 8) | uint16_t(data_buf[5]); temp = constrain(uint16_t(control_value), 0, thermalManager.hotend_max_target(0)); setTargetTemp_celsius(temp, E0); - //sprintf(str_buf,"%u/%u", (uint16_t)thermalManager.degHotend(0), uint16_t(control_value)); - //sendTxtToTFT(str_buf, TXT_PRINT_HOTEND); } #endif @@ -1024,8 +1027,6 @@ namespace Anycubic { control_value = (uint16_t(data_buf[4]) << 8) | uint16_t(data_buf[5]); temp = constrain(uint16_t(control_value), 0, BED_MAX_TARGET); setTargetTemp_celsius(temp, BED); - //sprintf(str_buf,"%u/%u", uint16_t(thermalManager.degBed()), uint16_t(control_value)); - //sendTxtToTFT(str_buf, TXT_PRINT_BED); } #endif @@ -1043,8 +1044,7 @@ namespace Anycubic { control_value = (uint16_t(data_buf[4]) << 8) | uint16_t(data_buf[5]); const uint16_t feedrate = constrain(uint16_t(control_value), 40, 999); //feedrate_percentage=constrain(control_value,40,999); - sprintf(str_buf, "%u", feedrate); - sendTxtToTFT(str_buf, TXT_PRINT_SPEED); + sendTxtToTFT(MString<6>(feedrate), TXT_PRINT_SPEED); sendValueToTFT(feedrate, TXT_PRINT_SPEED_NOW); sendValueToTFT(feedrate, TXT_PRINT_SPEED_TARGET); setFeedrate_percent(feedrate); @@ -1109,23 +1109,10 @@ namespace Anycubic { } } - #if 0 - { - // Break these up into logical blocks // as its easier to navigate than one huge switch case! - int8_t req = atoi(&panel_command[1]); - - // Information requests A0 - A8 and A33 - if (req <= 8 || req == 33) panelInfo(req); - - // Simple Actions A9 - A28 - else if (req <= 28) panelAction(req); - - // Process Initiation - else if (req <= 34) panelProcess(req); - - else tftSendLn(); - } - #endif + void set_brightness() { + uint8_t data[] = { 0x5A, 0xA5, 0x07, 0x82, 0x00, 0x82, 0x64, 0x32, 0x03, 0xE8 }; + for (uint8_t i = 0; i < COUNT(data); ++i) TFTSer.write(data[i]); + } void DgusTFT::set_language(language_t language) { lcd_info.language = ui_language = lcd_info_back.language = language; @@ -1156,29 +1143,19 @@ namespace Anycubic { } #if HAS_HOTEND - void DgusTFT::send_temperature_hotend(uint32_t addr) { - char str_buf[16]; - sprintf(str_buf, "%u/%u", uint16_t(getActualTemp_celsius(E0)), uint16_t(getTargetTemp_celsius(E0))); - sendTxtToTFT(str_buf, addr); + void DgusTFT::send_temperature_hotend(const uint16_t address) { + sendTxtToTFT(MString<16>(uint16_t(getActualTemp_celsius(E0)), '/', uint16_t(getTargetTemp_celsius(E0))), address); } #endif #if HAS_HEATED_BED - void DgusTFT::send_temperature_bed(uint32_t addr) { - char str_buf[16]; - sprintf(str_buf, "%u/%u", uint16_t(getActualTemp_celsius(BED)), uint16_t(getTargetTemp_celsius(BED))); - sendTxtToTFT(str_buf, addr); + void DgusTFT::send_temperature_bed(const uint16_t address) { + sendTxtToTFT(MString<16>(uint16_t(getActualTemp_celsius(BED)), '/', uint16_t(getTargetTemp_celsius(BED))), address); } #endif void DgusTFT::page1() { - #if ACDEBUG(AC_ALL) - if (page_index_saved != page_index_now || key_value_saved != key_value) { - DEBUG_ECHOLNPGM("page1 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(1); switch (key_value) { case 0: break; @@ -1209,13 +1186,6 @@ namespace Anycubic { break; } - #if 0 - if (message_index < 30) { - sendTxtToTFT(p_mesage[message_index], TXT_MAIN_MESSAGE); - message_index = 30; - } - #endif - #if HAS_HOTEND || HAS_HEATED_BED static millis_t flash_time = 0; const millis_t ms = millis(); @@ -1228,13 +1198,7 @@ namespace Anycubic { } void DgusTFT::page2() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page2 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(2); char file_index = 0; switch (key_value) { @@ -1292,9 +1256,7 @@ namespace Anycubic { TERN_(CASE_LIGHT_ENABLE, setCaseLightState(true)); - char str_buf[20]; - strlcpy_P(str_buf, filenavigator.filelist.longFilename(), 18); - sendTxtToTFT(str_buf, TXT_PRINT_NAME); + sendTxtToTFT(MString<17>(filenavigator.filelist.longFilename()), TXT_PRINT_NAME); #if ENABLED(POWER_LOSS_RECOVERY) if (printer_state == AC_printer_resuming_from_power_outage) { @@ -1330,20 +1292,10 @@ namespace Anycubic { TERN_(CASE_LIGHT_ENABLE, setCaseLightState(true)); printFile(filenavigator.filelist.shortFilename()); - char str_buf[20]; - strlcpy_P(str_buf, filenavigator.filelist.longFilename(), 18); - sendTxtToTFT(str_buf, TXT_PRINT_NAME); - - sprintf(str_buf, "%5.2f", getFeedrate_percent()); - sendTxtToTFT(str_buf, TXT_PRINT_SPEED); - - sprintf(str_buf, "%u", uint16_t(getProgress_percent())); - sendTxtToTFT(str_buf, TXT_PRINT_PROGRESS); - - uint32_t time = 0; - sprintf(str_buf, "%s H ", utostr3(time / 60)); - sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60)); - sendTxtToTFT(str_buf, TXT_PRINT_TIME); + sendTxtToTFT(MString<17>(filenavigator.filelist.longFilename()), TXT_PRINT_NAME); + sendTxtToTFT(MString<6>(uint16_t(getFeedrate_percent())), TXT_PRINT_SPEED); + sendTxtToTFT(MString<6>(uint16_t(getProgress_percent())), TXT_PRINT_PROGRESS); + sendTimeToTFT(0, TXT_PRINT_TIME); changePageOfTFT(PAGE_STATUS2); } @@ -1376,18 +1328,10 @@ namespace Anycubic { } void DgusTFT::page3() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page3 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(3); static millis_t flash_time = 0; const millis_t ms = millis(); - char str_buf[20]; - static uint8_t progress_last = 0; switch (key_value) { case 0: break; @@ -1435,47 +1379,35 @@ namespace Anycubic { if (PENDING(ms, flash_time)) return; flash_time = ms + 1500; - if (feedrate_back != getFeedrate_percent()) { - if (getFeedrate_percent() != 0) - sprintf(str_buf, "%5.2f", getFeedrate_percent()); + const uint16_t ifeedrate = uint16_t(getFeedrate_percent()); + if (feedrate_back != ifeedrate) { + if (ifeedrate != 0) + sendTxtToTFT(MString<6>(ifeedrate), TXT_PRINT_SPEED); else - sprintf(str_buf, "%d", feedrate_back); + sendTxtToTFT(MString<6>(feedrate_back), TXT_PRINT_SPEED); #if ACDEBUG(AC_MARLIN) - DEBUG_ECHOLNPGM("print speed: ", str_buf); - DEBUG_ECHOLNPGM("feedrate_back: ", feedrate_back); + DEBUG_ECHOLNPGM("print speed: ", ifeedrate, " feedrate_back: ", feedrate_back); #endif - sendTxtToTFT(str_buf, TXT_PRINT_SPEED); - feedrate_back = getFeedrate_percent(); + feedrate_back = ifeedrate; } + static uint8_t progress_last = 0; if (progress_last != getProgress_percent()) { - sprintf(str_buf, "%u", getProgress_percent()); - sendTxtToTFT(str_buf, TXT_PRINT_PROGRESS); progress_last = getProgress_percent(); + sendTxtToTFT(MString<6>(progress_last), TXT_PRINT_PROGRESS); } - // Get Printing Time - uint32_t time = getProgress_seconds_elapsed() / 60; - sprintf(str_buf, "%s H ", utostr3(time / 60)); - sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60)); - sendTxtToTFT(str_buf, TXT_PRINT_TIME); + // Report Printing Time in minutes + sendTimeToTFT(getProgress_seconds_elapsed() / 60, TXT_PRINT_TIME); TERN_(HAS_HOTEND, send_temperature_hotend(TXT_PRINT_HOTEND)); TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_PRINT_BED)); } void DgusTFT::page4() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page4 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(4); - char str_buf[20]; - static uint8_t progress_last = 0; switch (key_value) { case 0: break; @@ -1508,10 +1440,7 @@ namespace Anycubic { feedrate_back = getFeedrate_percent(); sendValueToTFT((uint16_t)feedrate_back, TXT_ADJUST_SPEED); TERN_(HAS_FAN, sendValueToTFT(uint16_t(getActualFan_percent(FAN0)), TXT_FAN_SPEED_TARGET)); - str_buf[0] = 0; - strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 3); - sendTxtToTFT(str_buf, TXT_LEVEL_OFFSET); - //sendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET); + sendTxtToTFT(ftostr52sprj(getZOffset_mm()) + 3, TXT_LEVEL_OFFSET); requestValueFromTFT(TXT_ADJUST_SPEED); // attempt to make feedrate visible on visit to this page break; } @@ -1521,39 +1450,30 @@ namespace Anycubic { if (PENDING(ms, flash_time)) return; flash_time = ms + 1500; - if (feedrate_back != getFeedrate_percent()) { - if (getFeedrate_percent() != 0) - sprintf(str_buf, "%5.2f", getFeedrate_percent()); + const uint16_t ifeedrate = uint16_t(getFeedrate_percent()); + if (feedrate_back != ifeedrate) { + if (ifeedrate != 0) + sendTxtToTFT(MString<6>(ifeedrate), TXT_PRINT_SPEED); else - sprintf(str_buf, "%d", feedrate_back); - - sendTxtToTFT(str_buf, TXT_PRINT_SPEED); - feedrate_back = getFeedrate_percent(); + sendTxtToTFT(MString<6>(feedrate_back), TXT_PRINT_SPEED); + feedrate_back = ifeedrate; } + static uint8_t progress_last = 0; if (progress_last != getProgress_percent()) { - sprintf(str_buf, "%u", getProgress_percent()); - sendTxtToTFT(str_buf, TXT_PRINT_PROGRESS); progress_last = getProgress_percent(); + sendTxtToTFT(MString<6>(progress_last), TXT_PRINT_PROGRESS); } - uint32_t time = getProgress_seconds_elapsed() / 60; - sprintf(str_buf, "%s H ", utostr3(time / 60)); - sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60)); - sendTxtToTFT(str_buf, TXT_PRINT_TIME); + // Report Printing Time in minutes + sendTimeToTFT(getProgress_seconds_elapsed() / 60, TXT_PRINT_TIME); TERN_(HAS_HOTEND, send_temperature_hotend(TXT_PRINT_HOTEND)); TERN_(HAS_HEATED_BED, send_temperature_bed(TXT_PRINT_BED)); } void DgusTFT::page5() { // print settings - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page5 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(5); static bool z_change = false; switch (key_value) { @@ -1576,11 +1496,7 @@ namespace Anycubic { z_off -= 0.05f; setZOffset_mm(z_off); - char str_buf[10]; - str_buf[0] = 0; - strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2); - sendTxtToTFT(str_buf, TXT_LEVEL_OFFSET); - //sendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET); + sendTxtToTFT(ftostr52sprj(getZOffset_mm()) + 2, TXT_LEVEL_OFFSET); //if (isAxisPositionKnown(Z)) { // Move Z axis // SERIAL_ECHOLNPGM("Z now:", getAxisPosition_mm(Z)); @@ -1617,11 +1533,7 @@ namespace Anycubic { z_off += 0.05f; setZOffset_mm(z_off); - char str_buf[10]; - str_buf[0] = '\0'; - strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2); - sendTxtToTFT(str_buf, TXT_LEVEL_OFFSET); - //sendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET); + sendTxtToTFT(ftostr52sprj(getZOffset_mm()) + 2, TXT_LEVEL_OFFSET); //int16_t steps = mmToWholeSteps(constrain(Zshift,-0.05,0.05), Z); @@ -1688,13 +1600,7 @@ namespace Anycubic { } void DgusTFT::page6() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page6 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(6); switch (key_value) { case 0: break; case 1: break; @@ -1702,13 +1608,7 @@ namespace Anycubic { } void DgusTFT::page7() { // tools - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page7 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(7); switch (key_value) { case 0: break; @@ -1732,15 +1632,16 @@ namespace Anycubic { #endif break; - case 4: + case 4: { changePageOfTFT(PAGE_SPEED); #if HAS_FAN sendValueToTFT(uint16_t(getActualFan_percent(FAN0)), TXT_FAN_SPEED_NOW); sendValueToTFT(uint16_t(getTargetFan_percent(FAN0)), TXT_FAN_SPEED_TARGET); #endif - sendValueToTFT(uint16_t(getFeedrate_percent()), TXT_PRINT_SPEED_NOW); - sendValueToTFT(uint16_t(getFeedrate_percent()), TXT_PRINT_SPEED_TARGET); - break; + const uint16_t ifeedrate = uint16_t(getFeedrate_percent()); + sendValueToTFT(ifeedrate, TXT_PRINT_SPEED_NOW); + sendValueToTFT(ifeedrate, TXT_PRINT_SPEED_TARGET); + } break; case 5: // turn off the xyz motor if (!isMoving()) @@ -1758,13 +1659,7 @@ namespace Anycubic { } void DgusTFT::page8() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page8 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(8); //static uint16_t movespeed = 50; static float move_dis = 1.0f; @@ -1864,13 +1759,7 @@ namespace Anycubic { } void DgusTFT::page9() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page9 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(9); switch (key_value) { case 0: break; @@ -1907,13 +1796,7 @@ namespace Anycubic { } void DgusTFT::page10() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page10 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(10); switch (key_value) { case 0: break; @@ -1943,13 +1826,7 @@ namespace Anycubic { } void DgusTFT::page11() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page11 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(11); switch (key_value) { case 0: break; @@ -1969,13 +1846,9 @@ namespace Anycubic { toggle_audio(); break; - case 5: { // about - char str_ver[32]; - //sprintf(str_ver, "%04d-%02d-%02d %02d:%02d:%02d\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY, BUILD_HOUR, BUILD_MIN, BUILD_SEC); - sprintf(str_ver, MAIN_BOARD_FIRMWARE_VER); - sendTxtToTFT(str_ver, TXT_VERSION); - changePageOfTFT(PAGE_ABOUT); - } break; + case 5: // about + showAboutPage(); + break; case 6: changePageOfTFT(PAGE_RECORD); @@ -1984,13 +1857,7 @@ namespace Anycubic { } void DgusTFT::page12() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page12 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(12); switch (key_value) { case 0: break; case 1: // return @@ -2000,13 +1867,7 @@ namespace Anycubic { } void DgusTFT::page13() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page13 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(13); switch (key_value) { case 0: break; @@ -2019,13 +1880,7 @@ namespace Anycubic { } void DgusTFT::page14() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page14 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(14); switch (key_value) { case 0: break; case 1: break; // return @@ -2036,13 +1891,7 @@ namespace Anycubic { } void DgusTFT::page15() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page15 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(15); switch (key_value) { case 0: break; @@ -2073,13 +1922,7 @@ namespace Anycubic { } void DgusTFT::page16() { // AUTO LEVELING - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page16 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(16); switch (key_value) { case 0: break; case 1: // return @@ -2094,11 +1937,7 @@ namespace Anycubic { break; case 3: { - char str_buf[10]; - str_buf[0] = '\0'; - strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2); - sendTxtToTFT(str_buf, TXT_LEVEL_OFFSET); - //sendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET); + sendTxtToTFT(ftostr52sprj(getZOffset_mm()) + 2, TXT_LEVEL_OFFSET); changePageOfTFT(PAGE_LEVEL_ADVANCE); } break; @@ -2109,13 +1948,7 @@ namespace Anycubic { } void DgusTFT::page17() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page17 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(17); float z_off; switch (key_value) { case 0: break; @@ -2124,16 +1957,15 @@ namespace Anycubic { changePageOfTFT(PAGE_PreLEVEL); break; - case 2: { - setSoftEndstopState(false); + case 2: { // Babystep Z Offset - if (getZOffset_mm() <= -5) return; + + setSoftEndstopState(false); + z_off = getZOffset_mm() - 0.01f; setZOffset_mm(z_off); - char str_buf[10]; - strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2); - sendTxtToTFT(str_buf, TXT_LEVEL_OFFSET); - //sendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET); + sendTxtToTFT(ftostr52sprj(getZOffset_mm()) + 2, TXT_LEVEL_OFFSET); if (isAxisPositionKnown(Z)) { const float currZpos = getAxisPosition_mm(Z); @@ -2143,16 +1975,15 @@ namespace Anycubic { setSoftEndstopState(true); } break; - case 3: { - setSoftEndstopState(false); + case 3: { // Babystep Z Offset + if (getZOffset_mm() >= 5) return; + + setSoftEndstopState(false); + z_off = getZOffset_mm() + 0.01f; setZOffset_mm(z_off); - char str_buf[10]; - strcat(str_buf, ftostr52sprj(getZOffset_mm()) + 2); - sendTxtToTFT(str_buf, TXT_LEVEL_OFFSET); - //sendTxtToTFT(ftostr52sprj(getZOffset_mm()), TXT_LEVEL_OFFSET); + sendTxtToTFT(ftostr52sprj(getZOffset_mm()) + 2, TXT_LEVEL_OFFSET); if (isAxisPositionKnown(Z)) { // Move Z axis const float currZpos = getAxisPosition_mm(Z); @@ -2182,13 +2013,7 @@ namespace Anycubic { #if HAS_HOTEND || HAS_HEATED_BED void DgusTFT::page18() { // preheat - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page18 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(18); switch (key_value) { case 0: break; @@ -2224,13 +2049,7 @@ namespace Anycubic { #if HAS_EXTRUDERS void DgusTFT::page19() { // Filament - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page19 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(19); static char filament_status = 0; static millis_t flash_time = 0; switch (key_value) { @@ -2291,13 +2110,7 @@ namespace Anycubic { #endif // HAS_EXTRUDERS void DgusTFT::page20() { // confirm - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page20 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(20); switch (key_value) { case 0: break; @@ -2313,13 +2126,7 @@ namespace Anycubic { } void DgusTFT::page21() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page21 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(21); switch (key_value) { case 0: break; @@ -2338,13 +2145,7 @@ namespace Anycubic { } void DgusTFT::page22() { // print finish - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page22 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(22); switch (key_value) { case 0: break; @@ -2364,13 +2165,7 @@ namespace Anycubic { } void DgusTFT::page23() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page23 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(23); switch (key_value) { case 0: break; @@ -2385,13 +2180,7 @@ namespace Anycubic { } void DgusTFT::page24() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page24 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(24); switch (key_value) { case 0: break; @@ -2406,13 +2195,7 @@ namespace Anycubic { } void DgusTFT::page25() { // lack filament - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page25 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(25); switch (key_value) { case 0: break; @@ -2438,13 +2221,7 @@ namespace Anycubic { } void DgusTFT::page26() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page26 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(26); switch (key_value) { case 0: break; @@ -2459,13 +2236,7 @@ namespace Anycubic { } void DgusTFT::page27() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page27 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(27); switch (key_value) { case 0: break; @@ -2474,7 +2245,6 @@ namespace Anycubic { if (isPrintingFromMedia()) { printer_state = AC_printer_stopping; stopPrint(); - message_index = 6; changePageOfTFT(PAGE_MAIN); } else { @@ -2499,13 +2269,7 @@ namespace Anycubic { } void DgusTFT::page28() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page28 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(28); switch (key_value) { case 0: break; @@ -2520,13 +2284,7 @@ namespace Anycubic { } void DgusTFT::page29() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page29 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(29); switch (key_value) { case 0: break; @@ -2546,13 +2304,7 @@ namespace Anycubic { } void DgusTFT::page30() { // Auto heat filament - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page30 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(30); switch (key_value) { case 0: break; @@ -2570,13 +2322,7 @@ namespace Anycubic { } void DgusTFT::page31() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page31 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(31); switch (key_value) { case 0: break; @@ -2591,13 +2337,7 @@ namespace Anycubic { } void DgusTFT::page32() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page32 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(32); static millis_t flash_time = 0; const millis_t ms = millis(); @@ -2608,12 +2348,7 @@ namespace Anycubic { #if HAS_LEVELING void DgusTFT::page33() { - #if ACDEBUG(AC_ALL) - if (page_index_saved != page_index_now) { - DEBUG_ECHOLNPGM("page33 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - } - #endif + debugPage(33); switch (key_value) { case 0: break; @@ -2655,13 +2390,7 @@ namespace Anycubic { } void DgusTFT::page34() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page34 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(34); #if HAS_HOTEND || HAS_HEATED_BED static millis_t flash_time = 0; @@ -2682,13 +2411,7 @@ namespace Anycubic { #endif // HAS_LEVELING void DgusTFT::page115() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page115 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(115); switch (key_value) { @@ -2715,13 +2438,7 @@ namespace Anycubic { } void DgusTFT::page117() { // Page CHS Mute handler - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page117 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(117); switch (key_value) { case 0: break; @@ -2742,11 +2459,7 @@ namespace Anycubic { break; case 5: // about - char str_ver[32]; - //sprintf(str_ver, "%04d-%02d-%02d %02d:%02d:%02d\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY, BUILD_HOUR, BUILD_MIN, BUILD_SEC); - sprintf(str_ver, MAIN_BOARD_FIRMWARE_VER); - sendTxtToTFT(str_ver, TXT_VERSION); - changePageOfTFT(PAGE_ABOUT); + showAboutPage(); break; case 6: @@ -2756,37 +2469,17 @@ namespace Anycubic { } void DgusTFT::page124() { // first time into page 124 the feedrate percent is not set - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page124 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now); - page_index_saved = page_index_now; - key_value_saved = key_value; - //DEBUG_ECHOLNPGM("update feedrate percent"); - } - #endif + debugPage(124); sendValueToTFT(uint16_t(getFeedrate_percent()), TXT_PRINT_SPEED_NOW); } void DgusTFT::page125() { // first time into page 125 the feedrate percent is not set - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page125 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now); - page_index_saved = page_index_now; - key_value_saved = key_value; - //DEBUG_ECHOLNPGM("update feedrate percent"); - } - #endif + debugPage(125); sendValueToTFT(uint16_t(getFeedrate_percent()), TXT_PRINT_SPEED_NOW); } void DgusTFT::page170() { // ENG Mute handler - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page170 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(170); switch (key_value) { case 0: break; @@ -2807,11 +2500,7 @@ namespace Anycubic { break; case 5: // about - char str_ver[32]; - //sprintf(str_ver, "%04d-%02d-%02d %02d:%02d:%02d\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY, BUILD_HOUR, BUILD_MIN, BUILD_SEC); - sprintf(str_ver, MAIN_BOARD_FIRMWARE_VER); - sendTxtToTFT(str_ver, TXT_VERSION); - changePageOfTFT(PAGE_ABOUT); + showAboutPage(); break; case 6: @@ -2823,12 +2512,7 @@ namespace Anycubic { #if ENABLED(POWER_LOSS_RECOVERY) void DgusTFT::page171() { // CHS power outage resume handler - #if ACDEBUG(AC_ALL) - if (page_index_saved != page_index_now) { - DEBUG_ECHOLNPGM("page171 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - } - #endif + debugPage(171); #if ENABLED(LONG_FILENAME_HOST_SUPPORT) char filename[64] = { '\0' }; #endif @@ -2846,12 +2530,8 @@ namespace Anycubic { sendTxtToTFT(recovery.info.sd_filename, TXT_OUTAGE_RECOVERY_FILE); #endif - char str_buf[20] = { '\0' }; - sprintf(str_buf, "%u", uint16_t(getFeedrate_percent())); - sendTxtToTFT(str_buf, TXT_PRINT_SPEED); - - sprintf(str_buf, "%u", uint16_t(getProgress_percent())); - sendTxtToTFT(str_buf, TXT_PRINT_PROGRESS); + sendTxtToTFT(MString<6>(uint16_t(getFeedrate_percent())), TXT_PRINT_SPEED); + sendTxtToTFT(MString<6>(uint16_t(getProgress_percent())), TXT_PRINT_PROGRESS); changePageOfTFT(PAGE_STATUS2); // show pause injectCommands(F("M355 S1\nM1000")); // case light on, home and start recovery @@ -2866,12 +2546,7 @@ namespace Anycubic { } void DgusTFT::page173() { // ENG power outage resume handler - #if ACDEBUG(AC_ALL) - if (page_index_saved != page_index_now) { - DEBUG_ECHOLNPGM("page173 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - } - #endif + debugPage(173); #if ENABLED(LONG_FILENAME_HOST_SUPPORT) char filename[64] = { '\0' }; #endif @@ -2889,12 +2564,8 @@ namespace Anycubic { sendTxtToTFT(recovery.info.sd_filename, TXT_OUTAGE_RECOVERY_FILE); #endif - char str_buf[20] = { '\0' }; - sprintf(str_buf, "%u", uint16_t(getFeedrate_percent())); - sendTxtToTFT(str_buf, TXT_PRINT_SPEED); - - sprintf(str_buf, "%u", uint16_t(getProgress_percent())); - sendTxtToTFT(str_buf, TXT_PRINT_PROGRESS); + sendTxtToTFT(MString<6>(uint16_t(getFeedrate_percent())), TXT_PRINT_SPEED); + sendTxtToTFT(MString<6>(uint16_t(getProgress_percent())), TXT_PRINT_PROGRESS); changePageOfTFT(PAGE_STATUS2); // show pause injectCommands(F("M355 S1\nM1000")); // case light on, home and start recovery @@ -2913,12 +2584,7 @@ namespace Anycubic { #if HAS_LEVELING void DgusTFT::page175() { // CHS probe preheating handler - #if ACDEBUG(AC_ALL) - if (page_index_saved != page_index_now) { - DEBUG_ECHOLNPGM("page175 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now); - page_index_saved = page_index_now; - } - #endif + debugPage(175); #if HAS_HOTEND || HAS_HEATED_BED static millis_t flash_time = 0; @@ -2932,12 +2598,7 @@ namespace Anycubic { } void DgusTFT::page176() { // ENG probe preheating handler - #if ACDEBUG(AC_ALL) - if (page_index_saved != page_index_now) { - DEBUG_ECHOLNPGM("page176 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now); - page_index_saved = page_index_now; - } - #endif + debugPage(176); #if HAS_HOTEND || HAS_HEATED_BED static millis_t flash_time = 0; @@ -2953,13 +2614,7 @@ namespace Anycubic { #endif // HAS_LEVELING void DgusTFT::page177_to_198() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page177_to_198 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(); switch (key_value) { case 1: // return #if ACDEBUG(AC_MARLIN) @@ -2997,6 +2652,7 @@ namespace Anycubic { #if 0 void DgusTFT::page178_to_181_190_to_193() { // temperature abnormal + debugPage(); #if ACDEBUG(AC_ALL) if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { DEBUG_ECHOLNPGM("page178_to_181_190_to_193 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); @@ -3027,13 +2683,7 @@ namespace Anycubic { #endif void DgusTFT::page199_to_200() { - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page199_to_200 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now, " key: ", key_value); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(); switch (key_value) { case 1: // return #if ACDEBUG(AC_MARLIN) @@ -3061,13 +2711,7 @@ namespace Anycubic { inline bool getProbeState() { return PROBE_TRIGGERED(); } void DgusTFT::page201() { // probe precheck - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page201 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(201); static millis_t probe_check_time = 0; static millis_t temperature_time = 0; static uint8_t probe_check_counter = 0; @@ -3123,13 +2767,7 @@ namespace Anycubic { } void DgusTFT::page202() { // probe precheck ok - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page202 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(202); //static millis_t flash_time = 0; //static millis_t probe_check_counter = 0; @@ -3143,13 +2781,7 @@ namespace Anycubic { } void DgusTFT::page203() { // probe precheck failed - #if ACDEBUG(AC_ALL) - if ((page_index_saved != page_index_now) || (key_value_saved != key_value)) { - DEBUG_ECHOLNPGM("page203 page_index_last_2: ", page_index_last_2, " page_index_last: ", page_index_last, " page_index_now: ", page_index_now); - page_index_saved = page_index_now; - key_value_saved = key_value; - } - #endif + debugPage(203); //static millis_t probe_check_counter = 0; //static uint8_t probe_state_last = 0; @@ -3166,6 +2798,7 @@ namespace Anycubic { void DgusTFT::pop_up_manager() { #if ACDEBUG(AC_ALL) + static uint8_t pop_up_index_saved; // = 0 if (pop_up_index_saved != pop_up_index) { DEBUG_ECHOLNPGM("pop_up_manager pop_up_index: ", pop_up_index); pop_up_index_saved = pop_up_index; @@ -3196,12 +2829,9 @@ namespace Anycubic { pop_up_index = 100; break; - case 24: { // - uint32_t time = getProgress_seconds_elapsed() / 60; - char str_buf[20]; - sprintf(str_buf, "%s H ", utostr3(time / 60)); - sprintf(str_buf + strlen(str_buf), "%s M", utostr3(time % 60)); - sendTxtToTFT(str_buf, TXT_FINISH_TIME); + case 24: { + // Report Printing Time in minutes + sendTimeToTFT(getProgress_seconds_elapsed() / 60, TXT_FINISH_TIME); changePageOfTFT(PAGE_PRINT_FINISH); //tftSendLn(AC_msg_print_complete); // no idea why this causes a compile error pop_up_index = 100; diff --git a/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.h b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.h index 514e8c7303..26564b981b 100644 --- a/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.h +++ b/Marlin/src/lcd/extui/anycubic_vyper/dgus_tft.h @@ -29,8 +29,6 @@ #include "../../../inc/MarlinConfigPre.h" #include "../ui_api.h" -#define MAIN_BOARD_FIRMWARE_VER "V2.4.5" - #define DATA_BUF_SIZE 64 /****************** PAGE INDEX***********************/ @@ -124,29 +122,29 @@ /****************** TXT **************************/ // MAIN PAGE TXT -#define TXT_MAIN_BED 0x2000 -#define TXT_MAIN_HOTEND 0x2030 -#define TXT_MAIN_MESSAGE 0x2060 +#define TXT_MAIN_BED (0x2000+0*0x30) +#define TXT_MAIN_HOTEND (0x2000+1*0x30) +#define TXT_MAIN_MESSAGE (0x2000+2*0x30) // FILE TXT -#define TXT_FILE_0 (0x2000+3*0x30) -#define TXT_DESCRIPT_0 0x5000 // DESCRIBE ADDRESS -#define TXT_FILE_1 (0x2000+4*0x30) -#define TXT_DESCRIPT_1 0x5030 -#define TXT_FILE_2 (0x2000+5*0x30) -#define TXT_DESCRIPT_2 0x5060 -#define TXT_FILE_3 (0x2000+6*0x30) -#define TXT_DESCRIPT_3 0x5090 -#define TXT_FILE_4 (0x2000+7*0x30) -#define TXT_DESCRIPT_4 0x50C0 +#define TXT_FILE_0 (0x2000+3*0x30) +#define TXT_DESCRIPT_0 0x5000 // DESCRIBE ADDRESS +#define TXT_FILE_1 (0x2000+4*0x30) +#define TXT_DESCRIPT_1 0x5030 +#define TXT_FILE_2 (0x2000+5*0x30) +#define TXT_DESCRIPT_2 0x5060 +#define TXT_FILE_3 (0x2000+6*0x30) +#define TXT_DESCRIPT_3 0x5090 +#define TXT_FILE_4 (0x2000+7*0x30) +#define TXT_DESCRIPT_4 0x50C0 // PRINT TXT -#define TXT_PRINT_NAME 0x2000+8*0x30 -#define TXT_PRINT_SPEED 0x2000+9*0x30 -#define TXT_PRINT_TIME 0x2000+10*0x30 -#define TXT_PRINT_PROGRESS 0x2000+11*0x30 -#define TXT_PRINT_HOTEND 0x2000+12*0x30 -#define TXT_PRINT_BED 0x2000+13*0x30 +#define TXT_PRINT_NAME (0x2000+8*0x30) +#define TXT_PRINT_SPEED (0x2000+9*0x30) +#define TXT_PRINT_TIME (0x2000+10*0x30) +#define TXT_PRINT_PROGRESS (0x2000+11*0x30) +#define TXT_PRINT_HOTEND (0x2000+12*0x30) +#define TXT_PRINT_BED (0x2000+13*0x30) // PRINT ADJUST TXT @@ -158,8 +156,8 @@ #define TXT_BED_NOW (0x2000+17*0x30) #define TXT_BED_TARGET (0x2000+18*0x30) -#define TXT_HOTEND_NOW (0x2000+19*0x30) -#define TXT_HOTEND_TARGET (0x2000+20*0x30) +#define TXT_HOTEND_NOW (0x2000+19*0x30) +#define TXT_HOTEND_TARGET (0x2000+20*0x30) // SPEED SET TXT #define TXT_FAN_SPEED_NOW (0x2000+21*0x30) @@ -171,23 +169,23 @@ #define TXT_ABOUT (0x2000+25*0x30) // RECORT TXT -#define TXT_RECORT_0 (0x2000+26*0x30) -#define TXT_RECORT_1 (0x2000+27*0x30) -#define TXT_RECORT_2 (0x2000+28*0x30) -#define TXT_RECORT_3 (0x2000+29*0x30) -#define TXT_RECORT_4 (0x2000+30*0x30) -#define TXT_RECORT_5 (0x2000+31*0x30) +#define TXT_RECORT_0 (0x2000+26*0x30) +#define TXT_RECORT_1 (0x2000+27*0x30) +#define TXT_RECORT_2 (0x2000+28*0x30) +#define TXT_RECORT_3 (0x2000+29*0x30) +#define TXT_RECORT_4 (0x2000+30*0x30) +#define TXT_RECORT_5 (0x2000+31*0x30) // ADVANCE LEVEL TXT -#define TXT_LEVEL_OFFSET (0x2000+32*0x30) +#define TXT_LEVEL_OFFSET (0x2000+32*0x30) // FILAMENT TXT -#define TXT_FILAMENT_TEMP (0x2000+33*0x30) +#define TXT_FILAMENT_TEMP (0x2000+33*0x30) -#define TXT_FINISH_TIME (0x2000+34*0x30) -#define TXT_VERSION (0x2000+35*0x30) -#define TXT_PREHEAT_HOTEND (0x2000+36*0x30) -#define TXT_PREHEAT_BED (0x2000+37*0x30) +#define TXT_FINISH_TIME (0x2000+34*0x30) +#define TXT_VERSION (0x2000+35*0x30) +#define TXT_PREHEAT_HOTEND (0x2000+36*0x30) +#define TXT_PREHEAT_BED (0x2000+37*0x30) #define TXT_OUTAGE_RECOVERY_FILE 0x2180 @@ -341,12 +339,11 @@ namespace Anycubic { static uint8_t data_buf[DATA_BUF_SIZE]; static uint8_t data_index; static uint16_t page_index_last, page_index_last_2; - static uint8_t message_index; static uint8_t pop_up_index; static uint32_t key_value; static uint8_t lcd_txtbox_index; static uint8_t lcd_txtbox_page; - static int16_t feedrate_back; + static uint16_t feedrate_back; static language_t ui_language; public: @@ -364,7 +361,6 @@ namespace Anycubic { static void filamentRunout(); static void confirmationRequest(const char * const); static void statusChange(const char * const); - static void powerLoss(); static void powerLossRecovery(); static void homingStart(); static void homingComplete(); @@ -377,12 +373,16 @@ namespace Anycubic { static void store_changes(); #if HAS_HOTEND - static void send_temperature_hotend(uint32_t addr); + static void send_temperature_hotend(const uint16_t address); #endif #if HAS_HEATED_BED - static void send_temperature_bed(uint32_t addr); + static void send_temperature_bed(const uint16_t address); #endif + static void changePageOfTFT(const uint16_t page_index, const bool no_send=false); + static void fakeChangePageOfTFT(const uint16_t page_index); + static void debugPage(int page=0); + typedef void (*p_fun)(); static void page1(); static void page2(); @@ -457,18 +457,25 @@ namespace Anycubic { static void sendFileList(int8_t); static void selectFile(); static void processPanelRequest(); - static void panelInfo(uint8_t); - static void panelAction(uint8_t); - static void panelProcess(uint8_t); static void sendValueToTFT(const uint16_t value, const uint16_t address); static void requestValueFromTFT(const uint16_t address); + static void sendTxtToTFT(const char *pdata, const uint16_t address); + static void sendTxtToTFT_P(PGM_P const pstr, const uint16_t address) { + char cstr[32]; + strlcpy_P(cstr, pstr, sizeof(cstr)); + sendTxtToTFT(cstr, address); + } + static void sendTxtToTFT(FSTR_P const fstr, const uint16_t address) { + sendTxtToTFT_P(FTOP(fstr), address); + } + static void sendColorToTFT(const uint16_t color, const uint16_t address); + static void sendTimeToTFT(const uint32_t minutes, const uint16_t address); static void sendReadNumOfTxtToTFT(const uint8_t number, const uint16_t address); - static void changePageOfTFT(const uint16_t page_index, const bool no_send=false); - static void fakeChangePageOfTFT(const uint16_t page_index); static void lcdAudioSet(const bool audio_on); + static void showAboutPage(); private: diff --git a/Marlin/src/lcd/extui/anycubic_vyper/vyper_extui.cpp b/Marlin/src/lcd/extui/anycubic_vyper/vyper_extui.cpp index 4b18b0a380..5fbe813446 100644 --- a/Marlin/src/lcd/extui/anycubic_vyper/vyper_extui.cpp +++ b/Marlin/src/lcd/extui/anycubic_vyper/vyper_extui.cpp @@ -121,7 +121,6 @@ namespace ExtUI { void onPostprocessSettings() { // Called after loading or resetting stored settings dgus.paramInit(); - dgus.powerLoss(); } void onSettingsStored(const bool success) { @@ -160,7 +159,7 @@ namespace ExtUI { #if ENABLED(POWER_LOSS_RECOVERY) // Called when power-loss is enabled/disabled - void onSetPowerLoss(const bool) { dgus.powerLoss(); } + void onSetPowerLoss(const bool) { /* nothing to do */ } // Called when power-loss state is detected void onPowerLoss() { /* handled internally */ } // Called on resume from power-loss diff --git a/Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp b/Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp index d78364cb3b..8e2b1bb8e4 100644 --- a/Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp +++ b/Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp @@ -69,7 +69,7 @@ void MKS_reset_settings() { { 20, 20 }, { 20, 20 }, { X_CENTER, Y_CENTER } }; - mks_language_index = MKS_SimpleChinese; + mks_language_index = MKS_English; COPY(mks_corner_offsets, init_dgus_level_offsets); mks_park_pos.set(20, 20, 10); mks_min_extrusion_temp = 0; diff --git a/Marlin/src/lcd/extui/mks_ui/draw_change_speed.cpp b/Marlin/src/lcd/extui/mks_ui/draw_change_speed.cpp index 6b07d4b719..e5d0f4244f 100644 --- a/Marlin/src/lcd/extui/mks_ui/draw_change_speed.cpp +++ b/Marlin/src/lcd/extui/mks_ui/draw_change_speed.cpp @@ -51,42 +51,22 @@ static void event_handler(lv_obj_t *obj, lv_event_t event) { if (event != LV_EVENT_RELEASED) return; switch (obj->mks_obj_id) { case ID_C_ADD: - if (!editingFlowrate) { - if (feedrate_percentage < MAX_EXT_SPEED_PERCENT - uiCfg.stepPrintSpeed) - feedrate_percentage += uiCfg.stepPrintSpeed; - else - feedrate_percentage = MAX_EXT_SPEED_PERCENT; - } + if (!editingFlowrate) + feedrate_percentage = _MIN(MAX_EXT_SPEED_PERCENT, feedrate_percentage + uiCfg.stepPrintSpeed); else { - if (planner.flow_percentage[0] < MAX_EXT_SPEED_PERCENT - uiCfg.stepPrintSpeed) - planner.flow_percentage[0] += uiCfg.stepPrintSpeed; - else - planner.flow_percentage[0] = MAX_EXT_SPEED_PERCENT; - planner.refresh_e_factor(0); - #if HAS_MULTI_EXTRUDER - planner.flow_percentage[1] = planner.flow_percentage[0]; - planner.refresh_e_factor(1); - #endif + const int16_t new_flow = _MIN(MAX_EXT_SPEED_PERCENT, planner.flow_percentage[0] + uiCfg.stepPrintSpeed); + planner.set_flow(0, new_flow); + TERN_(HAS_MULTI_EXTRUDER, planner.set_flow(1, new_flow)); } disp_print_speed(); break; case ID_C_DEC: - if (!editingFlowrate) { - if (feedrate_percentage > MIN_EXT_SPEED_PERCENT + uiCfg.stepPrintSpeed) - feedrate_percentage -= uiCfg.stepPrintSpeed; - else - feedrate_percentage = MIN_EXT_SPEED_PERCENT; - } + if (!editingFlowrate) + feedrate_percentage = _MAX(MIN_EXT_SPEED_PERCENT, feedrate_percentage + uiCfg.stepPrintSpeed); else { - if (planner.flow_percentage[0] > MIN_EXT_SPEED_PERCENT + uiCfg.stepPrintSpeed) - planner.flow_percentage[0] -= uiCfg.stepPrintSpeed; - else - planner.flow_percentage[0] = MIN_EXT_SPEED_PERCENT; - planner.refresh_e_factor(0); - #if HAS_MULTI_EXTRUDER - planner.flow_percentage[1] = planner.flow_percentage[0]; - planner.refresh_e_factor(1); - #endif + const int16_t new_flow = _MAX(MIN_EXT_SPEED_PERCENT, planner.flow_percentage[0] - uiCfg.stepPrintSpeed); + planner.set_flow(0, new_flow); + TERN_(HAS_MULTI_EXTRUDER, planner.set_flow(1, new_flow)); } disp_print_speed(); break; @@ -101,12 +81,7 @@ static void event_handler(lv_obj_t *obj, lv_event_t event) { disp_print_speed(); break; case ID_C_STEP: - if (uiCfg.stepPrintSpeed == 1) - uiCfg.stepPrintSpeed = 5; - else if (uiCfg.stepPrintSpeed == 5) - uiCfg.stepPrintSpeed = 10; - else - uiCfg.stepPrintSpeed = 1; + uiCfg.stepPrintSpeed = (uiCfg.stepPrintSpeed == 5) ? 10 : (uiCfg.stepPrintSpeed == 1) ? 5 : 1; disp_speed_step(); break; case ID_C_RETURN: diff --git a/Marlin/src/lcd/extui/mks_ui/draw_dialog.cpp b/Marlin/src/lcd/extui/mks_ui/draw_dialog.cpp index 32eb7e77d7..4b2474a8e6 100644 --- a/Marlin/src/lcd/extui/mks_ui/draw_dialog.cpp +++ b/Marlin/src/lcd/extui/mks_ui/draw_dialog.cpp @@ -102,12 +102,8 @@ static void btn_ok_event_cb(lv_obj_t *btn, lv_event_t event) { card.openFileRead(cur_name); if (card.isFileOpen()) { feedrate_percentage = 100; - planner.flow_percentage[0] = 100; - planner.e_factor[0] = planner.flow_percentage[0] * 0.01f; - #if HAS_MULTI_EXTRUDER - planner.flow_percentage[1] = 100; - planner.e_factor[1] = planner.flow_percentage[1] * 0.01f; - #endif + TERN_(HAS_EXTRUDERS, planner.set_flow(0, 100)); + TERN_(HAS_MULTI_EXTRUDER, planner.set_flow(1, 100)); card.startOrResumeFilePrinting(); TERN_(POWER_LOSS_RECOVERY, recovery.prepare()); once_flag = false; diff --git a/Marlin/src/lcd/extui/mks_ui/draw_printing.cpp b/Marlin/src/lcd/extui/mks_ui/draw_printing.cpp index 345c5dd732..ee913d6465 100644 --- a/Marlin/src/lcd/extui/mks_ui/draw_printing.cpp +++ b/Marlin/src/lcd/extui/mks_ui/draw_printing.cpp @@ -294,7 +294,7 @@ void setProBarRate() { lv_label_set_text(bar1ValueText, public_buf_l); lv_obj_align(bar1ValueText, bar1, LV_ALIGN_CENTER, 0, 0); - if (marlin_state == MF_SD_COMPLETE) { + if (marlin_state == MarlinState::MF_SD_COMPLETE) { if (once_flag == 0) { stop_print_time(); @@ -309,7 +309,7 @@ void setProBarRate() { if (gCfgItems.finish_power_off) { gcode.process_subcommands_now(F("M1001")); queue.inject(F("M81")); - marlin_state = MF_RUNNING; + marlin_state = MarlinState::MF_RUNNING; } #endif } diff --git a/Marlin/src/lcd/extui/mks_ui/draw_ui.cpp b/Marlin/src/lcd/extui/mks_ui/draw_ui.cpp index 61ab345dd7..bd06e6c1f4 100644 --- a/Marlin/src/lcd/extui/mks_ui/draw_ui.cpp +++ b/Marlin/src/lcd/extui/mks_ui/draw_ui.cpp @@ -660,12 +660,8 @@ char *creat_title_text() { card.openFileRead(cur_name); if (card.isFileOpen()) { feedrate_percentage = 100; - planner.flow_percentage[0] = 100; - planner.e_factor[0] = planner.flow_percentage[0] * 0.01; - #if HAS_MULTI_EXTRUDER - planner.flow_percentage[1] = 100; - planner.e_factor[1] = planner.flow_percentage[1] * 0.01; - #endif + TERN_(HAS_EXTRUDERS, planner.set_flow(0, 100)); + TERN_(HAS_MULTI_EXTRUDER, planner.set_flow(1, 100)); card.startOrResumeFilePrinting(); TERN_(POWER_LOSS_RECOVERY, recovery.prepare()); once_flag = false; @@ -770,7 +766,7 @@ void GUI_RefreshPage() { disp_print_time(); disp_fan_Zpos(); } - if (printing_rate_update_flag || marlin_state == MF_SD_COMPLETE) { + if (printing_rate_update_flag || marlin_state == MarlinState::MF_SD_COMPLETE) { printing_rate_update_flag = false; if (!gcode_preview_over) setProBarRate(); } diff --git a/Marlin/src/lcd/extui/mks_ui/wifi_module.cpp b/Marlin/src/lcd/extui/mks_ui/wifi_module.cpp index 46ba860239..19b2cd8597 100644 --- a/Marlin/src/lcd/extui/mks_ui/wifi_module.cpp +++ b/Marlin/src/lcd/extui/mks_ui/wifi_module.cpp @@ -1011,14 +1011,8 @@ static void wifi_gcode_exec(uint8_t * const cmd_line) { if (card.isFileOpen()) { //saved_feedrate_percentage = feedrate_percentage; feedrate_percentage = 100; - #if HAS_EXTRUDERS - planner.flow_percentage[0] = 100; - planner.e_factor[0] = planner.flow_percentage[0] * 0.01f; - #endif - #if HAS_MULTI_EXTRUDER - planner.flow_percentage[1] = 100; - planner.e_factor[1] = planner.flow_percentage[1] * 0.01f; - #endif + TERN_(HAS_EXTRUDERS, planner.set_flow(0, 100)); + TERN_(HAS_MULTI_EXTRUDER, planner.set_flow(1, 100)); card.startOrResumeFilePrinting(); TERN_(POWER_LOSS_RECOVERY, recovery.prepare()); once_flag = false; diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index 5c7246d4cd..d89a09d8ad 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -765,6 +765,24 @@ namespace ExtUI { } #endif + #if HAS_SHAPING + float getShapingZeta(const axis_t axis) { + return stepper.get_shaping_damping_ratio(AxisEnum(axis)); + } + void setShapingZeta(const float zeta, const axis_t axis) { + if (!WITHIN(zeta, 0, 1)) return; + stepper.set_shaping_damping_ratio(AxisEnum(axis), zeta); + } + float getShapingFrequency(const axis_t axis) { + return stepper.get_shaping_frequency(AxisEnum(axis)); + } + void setShapingFrequency(const float freq, const axis_t axis) { + constexpr float min_freq = float(uint32_t(STEPPER_TIMER_RATE) / 2) / shaping_time_t(-2); + if (freq == 0.0f || freq > min_freq) + stepper.set_shaping_frequency(AxisEnum(axis), freq); + } + #endif + #if HAS_JUNCTION_DEVIATION float getJunctionDeviation_mm() { return planner.junction_deviation_mm; } @@ -933,6 +951,7 @@ namespace ExtUI { #if HAS_BED_PROBE float getProbeOffset_mm(const axis_t axis) { return probe.offset.pos[axis]; } void setProbeOffset_mm(const_float_t val, const axis_t axis) { probe.offset.pos[axis] = val; } + probe_limits_t getBedProbeLimits() { return probe_limits_t({ probe.min_x(), probe.min_y(), probe.max_x(), probe.max_y() }); } #endif #if ENABLED(BACKLASH_GCODE) @@ -1200,7 +1219,7 @@ namespace ExtUI { void onSurviveInKilled() { thermalManager.disable_all_heaters(); flags.printer_killed = 0; - marlin_state = MF_RUNNING; + marlin_state = MarlinState::MF_RUNNING; //SERIAL_ECHOLNPGM("survived at: ", millis()); } @@ -1260,6 +1279,9 @@ namespace ExtUI { #if DISABLED(HAS_DWIN_E3V2) void MarlinUI::init_lcd() { ExtUI::onStartup(); } + void MarlinUI::clear_lcd() {} + void MarlinUI::clear_for_drawing() {} + void MarlinUI::update() { ExtUI::onIdle(); } void MarlinUI::kill_screen(FSTR_P const error, FSTR_P const component) { diff --git a/Marlin/src/lcd/extui/ui_api.h b/Marlin/src/lcd/extui/ui_api.h index 7065e21f8f..638f8d88b8 100644 --- a/Marlin/src/lcd/extui/ui_api.h +++ b/Marlin/src/lcd/extui/ui_api.h @@ -74,6 +74,7 @@ namespace ExtUI { #if ENABLED(MPC_AUTOTUNE) enum mpcresult_t : uint8_t { MPC_STARTED, MPC_TEMP_ERROR, MPC_INTERRUPTED, MPC_DONE }; #endif + struct probe_limits_t { float xmin, ymin, xmax, ymax; }; constexpr uint8_t extruderCount = EXTRUDERS; constexpr uint8_t hotendCount = HOTENDS; @@ -327,6 +328,13 @@ namespace ExtUI { void setLinearAdvance_mm_mm_s(const_float_t, const extruder_t); #endif + #if HAS_SHAPING + float getShapingZeta(const axis_t); + void setShapingZeta(const float, const axis_t); + float getShapingFrequency(const axis_t); + void setShapingFrequency(const float, const axis_t); + #endif + // JD or Jerk Control #if HAS_JUNCTION_DEVIATION float getJunctionDeviation_mm(); @@ -367,6 +375,7 @@ namespace ExtUI { #if HAS_BED_PROBE float getProbeOffset_mm(const axis_t); void setProbeOffset_mm(const_float_t, const axis_t); + probe_limits_t getBedProbeLimits(); #endif // Backlash Control diff --git a/Marlin/src/lcd/marlinui.cpp b/Marlin/src/lcd/marlinui.cpp index 5b83f0c6bf..8b24cd26eb 100644 --- a/Marlin/src/lcd/marlinui.cpp +++ b/Marlin/src/lcd/marlinui.cpp @@ -25,7 +25,7 @@ #include "../MarlinCore.h" // for printingIsPaused #include "../gcode/parser.h" // for axis_is_rotational, using_inch_units -#if LED_POWEROFF_TIMEOUT > 0 || ALL(HAS_WIRED_LCD, PRINTER_EVENT_LEDS) || (HAS_BACKLIGHT_TIMEOUT && defined(NEOPIXEL_BKGD_INDEX_FIRST)) +#if HAS_LED_POWEROFF_TIMEOUT || ALL(HAS_WIRED_LCD, PRINTER_EVENT_LEDS) || (HAS_BACKLIGHT_TIMEOUT && defined(NEOPIXEL_BKGD_INDEX_FIRST)) #include "../feature/leds/leds.h" #endif @@ -226,6 +226,7 @@ void MarlinUI::init() { #endif init_lcd(); + clear_lcd(); #if BUTTON_EXISTS(EN1) SET_INPUT_PULLUP(BTN_EN1); @@ -318,7 +319,7 @@ void MarlinUI::init() { #include "../feature/power_monitor.h" #endif - #if LED_POWEROFF_TIMEOUT > 0 + #if HAS_LED_POWEROFF_TIMEOUT #include "../feature/power.h" #endif @@ -942,9 +943,7 @@ void MarlinUI::init() { static uint16_t max_display_update_time = 0; const millis_t ms = millis(); - #if LED_POWEROFF_TIMEOUT > 0 - leds.update_timeout(powerManager.psu_on); - #endif + TERN_(HAS_LED_POWEROFF_TIMEOUT, leds.update_timeout(powerManager.psu_on)); #if HAS_MARLINUI_MENU @@ -1084,10 +1083,8 @@ void MarlinUI::init() { refresh(LCDVIEW_REDRAW_NOW); - #if LED_POWEROFF_TIMEOUT > 0 - if (!powerManager.psu_on) leds.reset_timeout(ms); - #endif - } // encoder activity + TERN_(HAS_LED_POWEROFF_TIMEOUT, if (!powerManager.psu_on) leds.reset_timeout(ms)); + } // encoder or click #endif // HAS_ENCODER_ACTION @@ -1204,7 +1201,7 @@ void MarlinUI::init() { // Change state of drawing flag between screen updates if (!drawing_screen) switch (lcdDrawUpdate) { case LCDVIEW_CLEAR_CALL_REDRAW: - clear_lcd(); break; + clear_for_drawing(); break; case LCDVIEW_REDRAW_NOW: refresh(LCDVIEW_NONE); case LCDVIEW_NONE: @@ -1827,13 +1824,14 @@ void MarlinUI::host_notify(const char * const cstr) { #endif void MarlinUI::media_changed(const uint8_t old_status, const uint8_t status) { + TERN_(HAS_DISPLAY_SLEEP, refresh_screen_timeout()); if (old_status == status) { TERN_(EXTENSIBLE_UI, ExtUI::onMediaError()); // Failed to mount/unmount return; } - if (status) { - if (old_status < 2) { + if (old_status < 2) { // Skip this section on first boot check + if (status) { // Media Mounted #if ENABLED(EXTENSIBLE_UI) ExtUI::onMediaMounted(); #elif ENABLED(BROWSE_MEDIA_ON_INSERT) @@ -1844,16 +1842,16 @@ void MarlinUI::host_notify(const char * const cstr) { LCD_MESSAGE(MSG_MEDIA_INSERTED); #endif } - } - else { - if (old_status < 2) { + else { // Media Removed #if ENABLED(EXTENSIBLE_UI) ExtUI::onMediaRemoved(); - #elif HAS_SD_DETECT + #elif HAS_SD_DETECT // Q: Does "Media Removed" need to be shown for manual release too? LCD_MESSAGE(MSG_MEDIA_REMOVED); #if HAS_MARLINUI_MENU - if (!defer_return_to_status) return_to_status(); + if (ENABLED(HAS_WIRED_LCD) || !defer_return_to_status) return_to_status(); #endif + #elif HAS_WIRED_LCD + return_to_status(); #endif } } @@ -1862,14 +1860,10 @@ void MarlinUI::host_notify(const char * const cstr) { refresh(); - #if HAS_WIRED_LCD || LED_POWEROFF_TIMEOUT > 0 + #if HAS_WIRED_LCD || HAS_LED_POWEROFF_TIMEOUT const millis_t ms = millis(); - #endif - - TERN_(HAS_WIRED_LCD, next_lcd_update_ms = ms + LCD_UPDATE_INTERVAL); // Delay LCD update for SD activity - - #if LED_POWEROFF_TIMEOUT > 0 - leds.reset_timeout(ms); + TERN_(HAS_WIRED_LCD, next_lcd_update_ms = ms + LCD_UPDATE_INTERVAL); // Delay LCD update for SD activity + TERN_(HAS_LED_POWEROFF_TIMEOUT, leds.reset_timeout(ms)); #endif } diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h index 835102546d..14bf42700f 100644 --- a/Marlin/src/lcd/marlinui.h +++ b/Marlin/src/lcd/marlinui.h @@ -207,8 +207,11 @@ public: #if HAS_DISPLAY || HAS_DWIN_E3V2 static void init_lcd(); + // Erase the LCD contents. Do the lowest-level thing required to clear the LCD. + static void clear_lcd(); #else static void init_lcd() {} + static void clear_lcd() {} #endif static void reinit_lcd() { TERN_(REINIT_NOISY_LCD, init_lcd()); } @@ -246,9 +249,6 @@ public: static void update_indicators(); #endif - // LCD implementations - static void clear_lcd(); - #if ALL(HAS_MARLINUI_MENU, TOUCH_SCREEN_CALIBRATION) static void check_touch_calibration() { if (touch_calibration.need_calibration()) currentScreen = touch_calibration_screen; @@ -304,6 +304,7 @@ public: static void refresh_screen_timeout(); #endif + // Sleep or wake the display (e.g., by turning the backlight off/on). static void sleep_display(const bool=true) IF_DISABLED(HAS_DISPLAY_SLEEP, {}); static void wake_display() { sleep_display(false); } @@ -520,6 +521,9 @@ public: #if HAS_DISPLAY + // Clear the LCD before new drawing. Some LCDs do nothing because they redraw frequently. + static void clear_for_drawing(); + static void abort_print(); static void pause_print(); static void resume_print(); @@ -630,6 +634,7 @@ public: #else // No LCD + static void clear_for_drawing() {} static void kill_screen(FSTR_P const, FSTR_P const) {} #endif @@ -739,7 +744,7 @@ public: static void draw_select_screen_prompt(FSTR_P const fpre, const char * const string=nullptr, FSTR_P const fsuf=nullptr); - #else + #else // !HAS_MARLINUI_MENU static void return_to_status() {} @@ -749,7 +754,7 @@ public: FORCE_INLINE static void run_current_screen() { status_screen(); } #endif - #endif + #endif // !HAS_MARLINUI_MENU #if ANY(HAS_MARLINUI_MENU, EXTENSIBLE_UI) static bool lcd_clicked; diff --git a/Marlin/src/lcd/menu/menu.cpp b/Marlin/src/lcd/menu/menu.cpp index 892af5dbab..f939452143 100644 --- a/Marlin/src/lcd/menu/menu.cpp +++ b/Marlin/src/lcd/menu/menu.cpp @@ -209,7 +209,7 @@ void MarlinUI::goto_screen(screenFunc_t screen, const uint16_t encoder/*=0*/, co TERN_(AUTO_BED_LEVELING_UBL, bedlevel.lcd_map_control = false); } - clear_lcd(); + clear_for_drawing(); // Re-initialize custom characters that may be re-used #if HAS_MARLINUI_HD44780 diff --git a/Marlin/src/lcd/menu/menu_item.h b/Marlin/src/lcd/menu/menu_item.h index 47cd7d5cf3..07aa59675a 100644 --- a/Marlin/src/lcd/menu/menu_item.h +++ b/Marlin/src/lcd/menu/menu_item.h @@ -426,7 +426,7 @@ class MenuItem_bool : public MenuEditItemBase { // Predefined menu item types // -#if DISABLED(DISABLE_ENCODER) +#if DISABLED(NO_BACK_MENU_ITEM) #define BACK_ITEM_F(FLABEL) MENU_ITEM_F(back, FLABEL) #define BACK_ITEM(LABEL) MENU_ITEM(back, LABEL) #else diff --git a/Marlin/src/lcd/menu/menu_one_click_print.cpp b/Marlin/src/lcd/menu/menu_one_click_print.cpp index f1ed92d0d5..c739964bce 100644 --- a/Marlin/src/lcd/menu/menu_one_click_print.cpp +++ b/Marlin/src/lcd/menu/menu_one_click_print.cpp @@ -25,6 +25,13 @@ #if ENABLED(ONE_CLICK_PRINT) #include "menu.h" +#include "../../gcode/queue.h" + +static void one_click_print_done() { + ui.return_to_status(); + ui.reset_status(); + queue.enqueue_one_now(F("M1003")); // Make sure SD card browsing doesn't break! +} void one_click_print() { ui.goto_screen([]{ @@ -33,9 +40,9 @@ void one_click_print() { GET_TEXT_F(MSG_BUTTON_PRINT), GET_TEXT_F(MSG_BUTTON_CANCEL), []{ card.openAndPrintFile(card.filename); - ui.return_to_status(); - ui.reset_status(); - }, nullptr, + one_click_print_done(); + }, + one_click_print_done, GET_TEXT_F(MSG_START_PRINT), filename, F("?") ); }); diff --git a/Marlin/src/lcd/menu/menu_ubl.cpp b/Marlin/src/lcd/menu/menu_ubl.cpp index 2d28d44991..ff7225a166 100644 --- a/Marlin/src/lcd/menu/menu_ubl.cpp +++ b/Marlin/src/lcd/menu/menu_ubl.cpp @@ -96,7 +96,7 @@ void _lcd_mesh_fine_tune(FSTR_P const fmsg) { // To capture encoder events UBL will also call ui.capture and ui.release. // void MarlinUI::ubl_mesh_edit_start(const_float_t initial) { - TERN_(HAS_GRAPHICAL_TFT, clear_lcd()); + TERN_(HAS_GRAPHICAL_TFT, clear_for_drawing()); mesh_edit_accumulator = initial; goto_screen([]{ _lcd_mesh_fine_tune(GET_TEXT_F(MSG_MESH_EDIT_Z)); }); } diff --git a/Marlin/src/lcd/tft/touch.cpp b/Marlin/src/lcd/tft/touch.cpp index 7fc5f2fa21..e48f974536 100644 --- a/Marlin/src/lcd/tft/touch.cpp +++ b/Marlin/src/lcd/tft/touch.cpp @@ -184,7 +184,7 @@ void Touch::touch(touch_control_t *control) { case HEATER: int8_t heater; heater = control->data; - ui.clear_lcd(); + ui.clear_for_drawing(); #if HAS_HOTEND if (heater >= 0) { // HotEnd #if HOTENDS == 1 @@ -213,20 +213,20 @@ void Touch::touch(touch_control_t *control) { break; case FAN: - ui.clear_lcd(); + ui.clear_for_drawing(); static uint8_t fan, fan_speed; fan = 0; fan_speed = thermalManager.fan_speed[fan]; MenuItem_percent::action(GET_TEXT_F(MSG_FIRST_FAN_SPEED), &fan_speed, 0, 255, []{ thermalManager.set_fan_speed(fan, fan_speed); TERN_(LASER_SYNCHRONOUS_M106_M107, planner.buffer_sync_block(BLOCK_BIT_SYNC_FANS));}); break; case FEEDRATE: - ui.clear_lcd(); + ui.clear_for_drawing(); MenuItem_int3::action(GET_TEXT_F(MSG_SPEED), &feedrate_percentage, SPEED_EDIT_MIN, SPEED_EDIT_MAX); break; #if HAS_EXTRUDERS case FLOWRATE: - ui.clear_lcd(); + ui.clear_for_drawing(); MenuItemBase::itemIndex = control->data; #if EXTRUDERS == 1 MenuItem_int3::action(GET_TEXT_F(MSG_FLOW), &planner.flow_percentage[MenuItemBase::itemIndex], FLOW_EDIT_MIN, FLOW_EDIT_MAX, []{ planner.refresh_e_factor(MenuItemBase::itemIndex); }); diff --git a/Marlin/src/lcd/tft/ui_color_ui.cpp b/Marlin/src/lcd/tft/ui_color_ui.cpp index 279ea9715a..9861cbc1f6 100644 --- a/Marlin/src/lcd/tft/ui_color_ui.cpp +++ b/Marlin/src/lcd/tft/ui_color_ui.cpp @@ -79,7 +79,7 @@ void MarlinUI::tft_idle() { void MarlinUI::bootscreen_completion(const millis_t sofar) { if ((BOOTSCREEN_TIMEOUT) > sofar) safe_delay((BOOTSCREEN_TIMEOUT) - sofar); - clear_lcd(); + clear_for_drawing(); } #endif diff --git a/Marlin/src/lcd/tft/ui_common.cpp b/Marlin/src/lcd/tft/ui_common.cpp index 23f276349b..e42ca7e689 100644 --- a/Marlin/src/lcd/tft/ui_common.cpp +++ b/Marlin/src/lcd/tft/ui_common.cpp @@ -199,7 +199,7 @@ void moveAxis(const AxisEnum axis, const int8_t direction) { tft.queue.reset(); if (!sleepCleared) { sleepCleared = true; - ui.clear_lcd(); + ui.clear_for_drawing(); tft.queue.async(); } touch.idle(); @@ -407,7 +407,7 @@ void MarlinUI::init_lcd() { tft.add_glyphs(EXTRA_FONT_NAME); #endif TERN_(TOUCH_SCREEN, touch.init()); - clear_lcd(); + clear_for_drawing(); } void MarlinUI::clear_lcd() { @@ -421,6 +421,8 @@ void MarlinUI::clear_lcd() { cursor.set(0, 0); } +void MarlinUI::clear_for_drawing() { clear_lcd(); } + #if HAS_LCD_BRIGHTNESS void MarlinUI::_set_brightness() { @@ -441,7 +443,7 @@ void MarlinUI::clear_lcd() { if (stage == CALIBRATION_NONE) { defer_status_screen(true); - clear_lcd(); + clear_for_drawing(); stage = touch_calibration.calibration_start(); } else { diff --git a/Marlin/src/lcd/tft/ui_move_axis_screen_1024.cpp b/Marlin/src/lcd/tft/ui_move_axis_screen_1024.cpp index a68752c9dd..a15c05d25e 100644 --- a/Marlin/src/lcd/tft/ui_move_axis_screen_1024.cpp +++ b/Marlin/src/lcd/tft/ui_move_axis_screen_1024.cpp @@ -133,7 +133,7 @@ void MarlinUI::move_axis_screen() { motionAxisState.blocked = false; TERN_(TOUCH_SCREEN, touch.enable()); - ui.clear_lcd(); + ui.clear_for_drawing(); TERN_(TOUCH_SCREEN, touch.clear()); diff --git a/Marlin/src/lcd/tft/ui_move_axis_screen_320.cpp b/Marlin/src/lcd/tft/ui_move_axis_screen_320.cpp index 54a65c17bf..5b1fbaf958 100644 --- a/Marlin/src/lcd/tft/ui_move_axis_screen_320.cpp +++ b/Marlin/src/lcd/tft/ui_move_axis_screen_320.cpp @@ -146,7 +146,7 @@ void MarlinUI::move_axis_screen() { motionAxisState.blocked = false; TERN_(TOUCH_SCREEN, touch.enable()); - ui.clear_lcd(); + ui.clear_for_drawing(); TERN_(TOUCH_SCREEN, touch.clear()); diff --git a/Marlin/src/lcd/tft/ui_move_axis_screen_480.cpp b/Marlin/src/lcd/tft/ui_move_axis_screen_480.cpp index e311c7e8ec..9e42411580 100644 --- a/Marlin/src/lcd/tft/ui_move_axis_screen_480.cpp +++ b/Marlin/src/lcd/tft/ui_move_axis_screen_480.cpp @@ -146,7 +146,7 @@ void MarlinUI::move_axis_screen() { motionAxisState.blocked = false; TERN_(TOUCH_SCREEN, touch.enable()); - ui.clear_lcd(); + ui.clear_for_drawing(); TERN_(TOUCH_SCREEN, touch.clear()); diff --git a/Marlin/src/module/endstops.cpp b/Marlin/src/module/endstops.cpp index d0ad234a7f..e9aafa49c8 100644 --- a/Marlin/src/module/endstops.cpp +++ b/Marlin/src/module/endstops.cpp @@ -87,6 +87,11 @@ Endstops::endstop_mask_t Endstops::live_state = 0; volatile bool Endstops::z_probe_enabled = false; #endif +#if ENABLED(CALIBRATION_GCODE) + volatile bool Endstops::calibration_probe_enabled = false; + volatile bool Endstops::calibration_stop_state; +#endif + // Initialized by settings.load() #if ENABLED(X_DUAL_ENDSTOPS) float Endstops::x2_endstop_adj; @@ -203,7 +208,7 @@ void Endstops::init() { _INIT_ENDSTOP(MAX,W,); #endif - #if PIN_EXISTS(CALIBRATION) + #if USE_CALIBRATION #if ENABLED(CALIBRATION_PIN_PULLUP) SET_INPUT_PULLUP(CALIBRATION_PIN); #elif ENABLED(CALIBRATION_PIN_PULLDOWN) @@ -283,6 +288,17 @@ void Endstops::not_homing() { } #endif +// Enable / disable calibration probe checking +#if ENABLED(CALIBRATION_GCODE) + void Endstops::enable_calibration_probe(const bool onoff, const bool stop_state) { + // Avoid race condition by setting stop state first + if (onoff) calibration_stop_state = stop_state; + calibration_probe_enabled = onoff; + + resync(); + } +#endif + // Get the stable endstop states when enabled void Endstops::resync() { if (!abort_enabled()) return; // If endstops/probes are disabled the loop below can hang @@ -485,6 +501,9 @@ void __O2 Endstops::report_states() { #if USE_Z_MIN_PROBE print_es_state(PROBE_TRIGGERED(), F(STR_Z_PROBE)); #endif + #if USE_CALIBRATION + print_es_state(READ(CALIBRATION_PIN) != CALIBRATION_PIN_INVERTING, F(STR_CALIBRATION)); + #endif #if MULTI_FILAMENT_SENSOR #define _CASE_RUNOUT(N) case N: pin = FIL_RUNOUT##N##_PIN; state = FIL_RUNOUT##N##_STATE; break; for (uint8_t i = 1; i <= NUM_RUNOUT_SENSORS; ++i) { @@ -530,6 +549,16 @@ void Endstops::update() { if (G38_move) UPDATE_LIVE_STATE(Z, TERN(USE_Z_MIN_PROBE, MIN_PROBE, MIN)); #endif + #if ENABLED(CALIBRATION_GCODE) + if (calibration_probe_enabled) { + #if HAS_CALIBRATION_STATE + SET_BIT_TO(live_state, CALIBRATION, READ(CALIBRATION_PIN) != CALIBRATION_PIN_INVERTING); + #else + UPDATE_LIVE_STATE(Z, TERN(USE_Z_MIN_PROBE, MIN_PROBE, MIN)); + #endif + } + #endif + // With Dual X, endstops are only checked in the homing direction for the active extruder #define X_MIN_TEST() TERN1(DUAL_X_CARRIAGE, stepper.last_moved_extruder == 0) // Check min for the left carriage #define X_MAX_TEST() TERN1(DUAL_X_CARRIAGE, stepper.last_moved_extruder != 0) // Check max for the right carriage @@ -786,7 +815,6 @@ void Endstops::update() { #define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_DUAL_ENDSTOP(Z, MINMAX) #endif - #if ENABLED(G38_PROBE_TARGET) // For G38 moves check the probe's pin for ALL movement if (G38_move && TEST_ENDSTOP(Z_MIN_PROBE) == TERN1(G38_PROBE_AWAY, (G38_move < 4))) { @@ -798,20 +826,30 @@ void Endstops::update() { } #endif + #if ENABLED(CALIBRATION_GCODE) + if (calibration_probe_enabled) { + #if HAS_CALIBRATION_STATE + if (TEST(live_state, CALIBRATION) == calibration_stop_state) stepper.quick_stop(); + #else + if (TEST(live_state, Z_MIN_PROBE) == calibration_stop_state) stepper.quick_stop(); + #endif + } + #endif // Signal, after validation, if an endstop limit is pressed or not - #if HAS_X_AXIS + bool moving_neg; + auto axis_moving_info = [](const AxisEnum axis, const AxisEnum head, bool &neg) -> bool { #if ENABLED(FT_MOTION) - const bool x_moving_pos = ftMotion.axis_moving_pos(X_AXIS_HEAD), - x_moving_neg = ftMotion.axis_moving_neg(X_AXIS_HEAD); - #define X_MOVE_TEST x_moving_pos || x_moving_neg - #define X_NEG_DIR_TEST x_moving_neg - #else - #define X_MOVE_TEST stepper.axis_is_moving(X_AXIS) - #define X_NEG_DIR_TEST !stepper.motor_direction(X_AXIS_HEAD) + if (ftMotion.cfg.mode != ftMotionMode_DISABLED) + return (neg = ftMotion.axis_moving_neg(head)) || ftMotion.axis_moving_pos(head); #endif - if (X_MOVE_TEST) { - if (X_NEG_DIR_TEST) { // -direction + neg = !stepper.motor_direction(head); + return stepper.axis_is_moving(axis); + }; + + #if HAS_X_AXIS + if (axis_moving_info(X_AXIS, X_AXIS_HEAD, moving_neg)) { + if (moving_neg) { // -direction #if HAS_X_MIN_STATE PROCESS_ENDSTOP_X(MIN); #if CORE_DIAG(XY, Y, MIN) @@ -843,17 +881,8 @@ void Endstops::update() { #endif // HAS_X_AXIS #if HAS_Y_AXIS - #if ENABLED(FT_MOTION) - const bool y_moving_pos = ftMotion.axis_moving_pos(Y_AXIS_HEAD), - y_moving_neg = ftMotion.axis_moving_neg(Y_AXIS_HEAD); - #define Y_MOVE_TEST y_moving_pos || y_moving_neg - #define Y_NEG_DIR_TEST y_moving_neg - #else - #define Y_MOVE_TEST stepper.axis_is_moving(Y_AXIS) - #define Y_NEG_DIR_TEST !stepper.motor_direction(Y_AXIS_HEAD) - #endif - if (Y_MOVE_TEST) { - if (Y_NEG_DIR_TEST) { // -direction + if (axis_moving_info(Y_AXIS, Y_AXIS_HEAD, moving_neg)) { + if (moving_neg) { // -direction #if HAS_Y_MIN_STATE PROCESS_ENDSTOP_Y(MIN); #if CORE_DIAG(XY, X, MIN) @@ -885,17 +914,8 @@ void Endstops::update() { #endif // HAS_Y_AXIS #if HAS_Z_AXIS - #if ENABLED(FT_MOTION) - const bool z_moving_pos = ftMotion.axis_moving_pos(Z_AXIS_HEAD), - z_moving_neg = ftMotion.axis_moving_neg(Z_AXIS_HEAD); - #define Z_MOVE_TEST z_moving_pos || z_moving_neg - #define Z_NEG_DIR_TEST z_moving_neg - #else - #define Z_MOVE_TEST stepper.axis_is_moving(Z_AXIS) - #define Z_NEG_DIR_TEST !stepper.motor_direction(Z_AXIS_HEAD) - #endif - if (Z_MOVE_TEST) { - if (Z_NEG_DIR_TEST) { // Z -direction. Gantry down, bed up. + if (axis_moving_info(Z_AXIS, Z_AXIS_HEAD, moving_neg)) { + if (moving_neg) { // Z -direction. Gantry down, bed up. #if HAS_Z_MIN_STATE // If the Z_MIN_PIN is being used for the probe there's no // separate Z_MIN endstop. But a Z endstop could be wired @@ -939,9 +959,8 @@ void Endstops::update() { #endif // HAS_Z_AXIS #if HAS_I_AXIS - // TODO: FT_Motion logic. - if (stepper.axis_is_moving(I_AXIS)) { - if (!stepper.motor_direction(I_AXIS_HEAD)) { // -direction + if (axis_moving_info(I_AXIS, I_AXIS_HEAD, moving_neg)) { + if (moving_neg) { // -direction #if HAS_I_MIN_STATE PROCESS_ENDSTOP(I, MIN); #endif @@ -955,8 +974,8 @@ void Endstops::update() { #endif // HAS_I_AXIS #if HAS_J_AXIS - if (stepper.axis_is_moving(J_AXIS)) { - if (!stepper.motor_direction(J_AXIS_HEAD)) { // -direction + if (axis_moving_info(J_AXIS, J_AXIS_HEAD, moving_neg)) { + if (moving_neg) { // -direction #if HAS_J_MIN_STATE PROCESS_ENDSTOP(J, MIN); #endif @@ -970,8 +989,8 @@ void Endstops::update() { #endif // HAS_J_AXIS #if HAS_K_AXIS - if (stepper.axis_is_moving(K_AXIS)) { - if (!stepper.motor_direction(K_AXIS_HEAD)) { // -direction + if (axis_moving_info(K_AXIS, K_AXIS_HEAD, moving_neg)) { + if (moving_neg) { // -direction #if HAS_K_MIN_STATE PROCESS_ENDSTOP(K, MIN); #endif @@ -985,8 +1004,8 @@ void Endstops::update() { #endif // HAS_K_AXIS #if HAS_U_AXIS - if (stepper.axis_is_moving(U_AXIS)) { - if (!stepper.motor_direction(U_AXIS_HEAD)) { // -direction + if (axis_moving_info(U_AXIS, U_AXIS_HEAD, moving_neg)) { + if (moving_neg) { // -direction #if HAS_U_MIN_STATE PROCESS_ENDSTOP(U, MIN); #endif @@ -1000,8 +1019,8 @@ void Endstops::update() { #endif // HAS_U_AXIS #if HAS_V_AXIS - if (stepper.axis_is_moving(V_AXIS)) { - if (!stepper.motor_direction(V_AXIS_HEAD)) { // -direction + if (axis_moving_info(V_AXIS, V_AXIS_HEAD, moving_neg)) { + if (moving_neg) { // -direction #if HAS_V_MIN_STATE PROCESS_ENDSTOP(V, MIN); #endif @@ -1015,8 +1034,8 @@ void Endstops::update() { #endif // HAS_V_AXIS #if HAS_W_AXIS - if (stepper.axis_is_moving(W_AXIS)) { - if (!stepper.motor_direction(W_AXIS_HEAD)) { // -direction + if (axis_moving_info(W_AXIS, W_AXIS_HEAD, moving_neg)) { + if (moving_neg) { // -direction #if HAS_W_MIN_STATE PROCESS_ENDSTOP(W, MIN); #endif @@ -1192,6 +1211,9 @@ void Endstops::update() { #if USE_Z_MIN_PROBE ES_GET_STATE(Z_MIN_PROBE); #endif + #if USE_CALIBRATION + ES_GET_STATE(CALIBRATION); + #endif #if USE_X2_MIN ES_GET_STATE(X2_MIN); #endif @@ -1284,6 +1306,9 @@ void Endstops::update() { #if USE_Z_MIN_PROBE ES_REPORT_CHANGE(Z_MIN_PROBE); #endif + #if USE_CALIBRATION + ES_REPORT_CHANGE(CALIBRATION); + #endif #if USE_X2_MIN ES_REPORT_CHANGE(X2_MIN); #endif diff --git a/Marlin/src/module/endstops.h b/Marlin/src/module/endstops.h index bbdb0bc77b..c6788330f0 100644 --- a/Marlin/src/module/endstops.h +++ b/Marlin/src/module/endstops.h @@ -66,6 +66,9 @@ enum EndstopEnum : char { // Extra Endstops for XYZ ES_MINMAX(X2) ES_MINMAX(Y2) ES_MINMAX(Z2) ES_MINMAX(Z3) ES_MINMAX(Z4) + // Calibration pin state + ES_ITEM(HAS_CALIBRATION_STATE, CALIBRATION) + // Bed Probe state is distinct or shared with Z_MIN (i.e., when the probe is the only Z endstop) ES_ITEM(HAS_Z_PROBE_STATE, Z_MIN_PROBE IF_DISABLED(USE_Z_MIN_PROBE, = Z_MIN)) @@ -165,10 +168,10 @@ class Endstops { static void init(); /** - * Are endstops or the probe set to abort the move? + * Are endstops or the Z min probe or the CALIBRATION probe set to abort the move? */ FORCE_INLINE static bool abort_enabled() { - return enabled || TERN0(HAS_BED_PROBE, z_probe_enabled); + return enabled || TERN0(HAS_BED_PROBE, z_probe_enabled) || TERN0(CALIBRATION_GCODE, calibration_probe_enabled); } static bool global_enabled() { return enabled_globally; } @@ -251,6 +254,13 @@ class Endstops { static void enable_z_probe(const bool onoff=true); #endif + // Enable / disable calibration probe checking + #if ENABLED(CALIBRATION_GCODE) + static volatile bool calibration_probe_enabled; + static volatile bool calibration_stop_state; + static void enable_calibration_probe(const bool onoff, const bool stop_state=true); + #endif + static void resync(); // Debugging of endstops diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index 473d54cc38..4bbb182bc3 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -257,7 +257,7 @@ void report_current_position_projected() { AutoReporter position_auto_reporter; #endif -#if ANY(FULL_REPORT_TO_HOST_FEATURE, REALTIME_REPORTING_COMMANDS) +#if ENABLED(REALTIME_REPORTING_COMMANDS) M_StateEnum M_State_grbl = M_INIT; @@ -299,18 +299,18 @@ void report_current_position_projected() { */ M_StateEnum grbl_state_for_marlin_state() { switch (marlin_state) { - case MF_INITIALIZING: return M_INIT; - case MF_SD_COMPLETE: return M_ALARM; - case MF_WAITING: return M_IDLE; - case MF_STOPPED: return M_END; - case MF_RUNNING: return M_RUNNING; - case MF_PAUSED: return M_HOLD; - case MF_KILLED: return M_ERROR; - default: return M_IDLE; + case MarlinState::MF_INITIALIZING: return M_INIT; + case MarlinState::MF_SD_COMPLETE: return M_ALARM; + case MarlinState::MF_WAITING: return M_IDLE; + case MarlinState::MF_STOPPED: return M_END; + case MarlinState::MF_RUNNING: return M_RUNNING; + case MarlinState::MF_PAUSED: return M_HOLD; + case MarlinState::MF_KILLED: return M_ERROR; + default: return M_IDLE; } } -#endif +#endif // REALTIME_REPORTING_COMMANDS #if IS_KINEMATIC diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index f9748871f5..bb8f36446b 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -272,7 +272,7 @@ void report_current_position_projected(); extern AutoReporter position_auto_reporter; #endif -#if ANY(FULL_REPORT_TO_HOST_FEATURE, REALTIME_REPORTING_COMMANDS) +#if ENABLED(REALTIME_REPORTING_COMMANDS) #define HAS_GRBL_STATE 1 /** * Machine states for GRBL or TinyG @@ -305,11 +305,9 @@ void report_current_position_projected(); } #endif - #if ENABLED(REALTIME_REPORTING_COMMANDS) - void quickpause_stepper(); - void quickresume_stepper(); - #endif -#endif + void quickpause_stepper(); + void quickresume_stepper(); +#endif // REALTIME_REPORTING_COMMANDS float get_move_distance(const xyze_pos_t &diff OPTARG(HAS_ROTATIONAL_AXES, bool &is_cartesian_move)); diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 8f11f4ec18..892258ff3b 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -128,7 +128,6 @@ Planner planner; block_t Planner::block_buffer[BLOCK_BUFFER_SIZE]; volatile uint8_t Planner::block_buffer_head, // Index of the next block to be pushed Planner::block_buffer_nonbusy, // Index of the first non-busy block - Planner::block_buffer_planned, // Index of the optimally planned block Planner::block_buffer_tail; // Index of the busy block, if any uint16_t Planner::cleaning_buffer_counter; // A counter to disable queuing of blocks uint8_t Planner::delay_before_delivering; // Delay block delivery so initial blocks in an empty queue may merge @@ -768,10 +767,6 @@ block_t* Planner::get_current_block() { // As this block is busy, advance the nonbusy block pointer block_buffer_nonbusy = next_block_index(block_buffer_tail); - // Push block_buffer_planned pointer, if encountered. - if (block_buffer_tail == block_buffer_planned) - block_buffer_planned = block_buffer_nonbusy; - // Return the block return block; } @@ -784,29 +779,30 @@ block_t* Planner::get_current_block() { /** * Calculate trapezoid parameters, multiplying the entry- and exit-speeds - * by the provided factors. Requires that initial_rate and final_rate are - * no less than sqrt(block->acceleration_steps_per_s2 / 2), which is ensured - * through minimum_planner_speed_sqr in _populate_block(). + * by the provided factors. If entry_factor is 0 don't change the initial_rate. + * Assumes that the implied initial_rate and final_rate are no less than + * sqrt(block->acceleration_steps_per_s2 / 2). This is ensured through + * minimum_planner_speed_sqr / min_entry_speed_sqr though note there's one + * exception in recalculate_trapezoids(). ** * ############ VERY IMPORTANT ############ * NOTE that the PRECONDITION to call this function is that the block is * NOT BUSY and it is marked as RECALCULATE. That WARRANTIES the Stepper ISR - * is not and will not use the block while we modify it, so it is safe to - * alter its values. + * is not and will not use the block while we modify it. */ -void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t entry_factor, const_float_t exit_factor) { +void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t entry_speed, const_float_t exit_speed) { - uint32_t initial_rate = LROUND(block->nominal_rate * entry_factor), - final_rate = LROUND(block->nominal_rate * exit_factor); // (steps per second) + const float spmm = block->steps_per_mm; + uint32_t initial_rate = entry_speed ? LROUND(entry_speed * spmm) : block->initial_rate, + final_rate = LROUND(exit_speed * spmm); - // Legacy check against supposed timer overflow. However Stepper::calc_timer_interval() already - // should protect against it. But removing this code produces judder in direction-switching - // moves. This is because the current discrete stepping math diverges from physical motion under - // constant acceleration when acceleration_steps_per_s2 is large compared to initial/final_rate. - NOLESS(initial_rate, uint32_t(MINIMAL_STEP_RATE)); // Enforce the minimum speed - NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE)); - NOMORE(initial_rate, block->nominal_rate); // NOTE: The nominal rate may be less than MINIMAL_STEP_RATE! - NOMORE(final_rate, block->nominal_rate); + // Removing code to constrain values produces judder in direction-switching moves because the + // current discrete stepping math diverges from physical motion under constant acceleration + // when acceleration_steps_per_s2 is large compared to initial/final_rate. + NOLESS(initial_rate, uint32_t(MINIMAL_STEP_RATE)); + NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE)); + NOMORE(initial_rate, block->nominal_rate); // NOTE: The nominal rate may be less than MINIMAL_STEP_RATE! + NOMORE(final_rate, block->nominal_rate); #if ANY(S_CURVE_ACCELERATION, LIN_ADVANCE) // If we have some plateau time, the cruise rate will be the nominal rate @@ -942,16 +938,16 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t * * Recalculates the motion plan according to the following basic guidelines: * - * 1. Go over every feasible block sequentially in reverse order and calculate the junction speeds - * (i.e. current->entry_speed) such that: - * a. No junction speed exceeds the pre-computed maximum junction speed limit or nominal speeds of - * neighboring blocks. - * b. A block entry speed cannot exceed one reverse-computed from its exit speed (next->entry_speed) - * with a maximum allowable deceleration over the block travel distance. - * c. The last (or newest appended) block is planned from safe_exit_speed_sqr. - * 2. Go over every block in chronological (forward) order and dial down junction speed values if - * a. The exit speed exceeds the one forward-computed from its entry speed with the maximum allowable - * acceleration over the block travel distance. + * 1. Go over blocks sequentially in reverse order and maximize the entry junction speed: + * a. Entry speed should stay below/at the pre-computed maximum junction speed limit + * b. Aim for the maximum entry speed which is the one reverse-computed from its exit speed + * (next->entry_speed) if assuming maximum deceleration over the full block travel distance + * c. The last (newest appended) block uses safe_exit_speed exit speed (there's no 'next') + * 2. Go over blocks in chronological (forward) order and fix the exit junction speed: + * a. Exit speed (next->entry_speed) must be below/at the maximum exit speed forward-computed + * from its entry speed if assuming maximum acceleration over the full block travel distance + * b. Exit speed should stay above/at the pre-computed minimum junction speed limit + * 3. Convert entry / exit speeds (mm/s) into final/initial steps/s * * When these stages are complete, the planner will have maximized the velocity profiles throughout the all * of the planner blocks, where every block is operating at its maximum allowable acceleration limits. In @@ -959,28 +955,22 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t * are possible. If a new block is added to the buffer, the plan is recomputed according to the said * guidelines for a new optimal plan. * - * To increase computational efficiency of these guidelines, a set of planner block pointers have been - * created to indicate stop-compute points for when the planner guidelines cannot logically make any further - * changes or improvements to the plan when in normal operation and new blocks are streamed and added to the - * planner buffer. For example, if a subset of sequential blocks in the planner have been planned and are - * bracketed by junction velocities at their maximums (or by the first planner block as well), no new block - * added to the planner buffer will alter the velocity profiles within them. So we no longer have to compute - * them. Or, if a set of sequential blocks from the first block in the planner (or a optimal stop-compute - * point) are all accelerating, they are all optimal and can not be altered by a new block added to the - * planner buffer, as this will only further increase the plan speed to chronological blocks until a maximum - * junction velocity is reached. However, if the operational conditions of the plan changes from infrequently - * used feed holds or feedrate overrides, the stop-compute pointers will be reset and the entire plan is - * recomputed as stated in the general guidelines. + * To increase computational efficiency of these guidelines: + * 1. We keep track of which blocks need calculation (block->flag.recalculate) + * 2. We stop the reverse pass on the first block whose entry_speed == max_entry_speed. As soon + * as that happens, there can be no further increases (ensured by the previous recalculate) + * 3. On the forward pass we skip through to the first block with a modified exit speed + * (next->entry_speed) + * 4. On the forward pass if we encounter a full acceleration block that limits its exit speed + * (next->entry_speed) we also update the maximum for that junction (next->max_entry_speed) + * so it's never updated again + * 5. We use speed squared (ex: entry_speed_sqr in mm^2/s^2) in acceleration limit computations + * 6. We don't recompute sqrt(entry_speed_sqr) if the block's entry speed didn't change * * Planner buffer index mapping: * - block_buffer_tail: Points to the beginning of the planner buffer. First to be executed or being executed. * - block_buffer_head: Points to the buffer block after the last block in the buffer. Used to indicate whether * the buffer is full or empty. As described for standard ring buffers, this block is always empty. - * - block_buffer_planned: Points to the first buffer block after the last optimally planned block for normal - * streaming operating conditions. Use for planning optimizations by avoiding recomputing parts of the - * planner buffer that don't change with the addition of a new block, as describe above. In addition, - * this block can never be less than block_buffer_tail and will always be pushed forward and maintain - * this requirement when encountered by the Planner::release_current_block() routine during a cycle. * * NOTE: Since the planner only computes on what's in the planner buffer, some motions with many short * segments (e.g., complex curves) may seem to move slowly. This is because there simply isn't @@ -1003,7 +993,8 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t */ // The kernel called by recalculate() when scanning the plan from last to first entry. -void Planner::reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr) { +// Returns true if it could increase the current block's entry speed. +bool Planner::reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr) { // We need to recalculate only for the last block added or if next->entry_speed_sqr changed. if (!next || next->flag.recalculate) { // And only if we're not already at max entry speed. @@ -1021,196 +1012,136 @@ void Planner::reverse_pass_kernel(block_t * const current, const block_t * const // become BUSY just before being marked RECALCULATE, so check for that! if (stepper.is_block_busy(current)) { // Block became busy. Clear the RECALCULATE flag (no point in - // recalculating BUSY blocks). And don't set its speed, as it can't - // be updated at this time. + // recalculating BUSY blocks). current->flag.recalculate = false; } else { // Block is not BUSY so this is ahead of the Stepper ISR: - // Just Set the new entry speed. + current->entry_speed_sqr = new_entry_speed_sqr; + return true; } } } } + return false; } /** * recalculate() needs to go over the current plan twice. - * Once in reverse and once forward. This implements the reverse pass. + * Once in reverse and once forward. This implements the reverse pass that + * coarsely maximizes the entry speeds starting from last block. + * Requires there's at least one block with flag.recalculate in the buffer. */ void Planner::reverse_pass(const_float_t safe_exit_speed_sqr) { // Initialize block index to the last block in the planner buffer. + // This last block will have flag.recalculate set. uint8_t block_index = prev_block_index(block_buffer_head); - // Read the index of the last buffer planned block. - // The ISR may change it so get a stable local copy. - uint8_t planned_block_index = block_buffer_planned; + // The ISR may change block_buffer_nonbusy so get a stable local copy. + uint8_t nonbusy_block_index = block_buffer_nonbusy; - // If there was a race condition and block_buffer_planned was incremented - // or was pointing at the head (queue empty) break loop now and avoid - // planning already consumed blocks - if (planned_block_index == block_buffer_head) return; - - // Reverse Pass: Coarsely maximize all possible deceleration curves back-planning from the last - // block in buffer. Cease planning when the last optimal planned or tail pointer is reached. - // NOTE: Forward pass will later refine and correct the reverse pass to create an optimal plan. const block_t *next = nullptr; - while (block_index != planned_block_index) { - - // Perform the reverse pass + // Don't try to change the entry speed of the first non-busy block. + while (block_index != nonbusy_block_index) { block_t *current = &block_buffer[block_index]; // Only process movement blocks if (current->is_move()) { - reverse_pass_kernel(current, next, safe_exit_speed_sqr); + // If no entry speed increase was possible we end the reverse pass. + if (!reverse_pass_kernel(current, next, safe_exit_speed_sqr)) return; next = current; } - // Advance to the next block_index = prev_block_index(block_index); - // The ISR could advance the block_buffer_planned while we were doing the reverse pass. + // The ISR could advance block_buffer_nonbusy while we were doing the reverse pass. // We must try to avoid using an already consumed block as the last one - So follow // changes to the pointer and make sure to limit the loop to the currently busy block - while (planned_block_index != block_buffer_planned) { + while (nonbusy_block_index != block_buffer_nonbusy) { // If we reached the busy block or an already processed block, break the loop now - if (block_index == planned_block_index) return; + if (block_index == nonbusy_block_index) return; // Advance the pointer, following the busy block - planned_block_index = next_block_index(planned_block_index); + nonbusy_block_index = next_block_index(nonbusy_block_index); } } } -// The kernel called by recalculate() when scanning the plan from first to last entry. -void Planner::forward_pass_kernel(const block_t * const previous, block_t * const current, const uint8_t block_index) { - // Check against previous speed only on current->entry_speed_sqr changes (or if first time). - if (current->flag.recalculate) { - // If the previous block is accelerating check if it's too short to complete the full speed - // change then adjust the entry speed accordingly. Entry speeds have already been maximized. - if (previous->entry_speed_sqr < current->entry_speed_sqr) { - float new_entry_speed_sqr = max_allowable_speed_sqr(-previous->acceleration, previous->entry_speed_sqr, previous->millimeters); +// The kernel called during the forward pass. Assumes current->flag.recalculate. +void Planner::forward_pass_kernel(const block_t * const previous, block_t * const current) { + // Check if the previous block is accelerating. + if (previous->entry_speed_sqr < current->entry_speed_sqr) { + // Compute the maximum achievable speed if the previous block was fully accelerating. + float new_exit_speed_sqr = max_allowable_speed_sqr(-previous->acceleration, previous->entry_speed_sqr, previous->millimeters); - // If true, previous block is full-acceleration and we can move the planned pointer forward. - if (new_entry_speed_sqr < current->entry_speed_sqr) { - // Current entry speed limited by full acceleration from previous entry speed. - // Make sure entry speed not lower than minimum_planner_speed_sqr. - NOLESS(new_entry_speed_sqr, current->min_entry_speed_sqr); - current->entry_speed_sqr = new_entry_speed_sqr; + if (new_exit_speed_sqr < current->entry_speed_sqr) { + // Current entry speed limited by full acceleration from previous entry speed. - // Set optimal plan pointer. - block_buffer_planned = block_index; - } - else { - // Previous entry speed has been maximized. - block_buffer_planned = prev_block_index(block_index); - } + // Make sure entry speed not lower than minimum_planner_speed_sqr. + NOLESS(new_exit_speed_sqr, current->min_entry_speed_sqr); + current->entry_speed_sqr = new_exit_speed_sqr; + // Ensure we don't try updating entry_speed_sqr again. + current->max_entry_speed_sqr = new_exit_speed_sqr; } - - // Any block set at its maximum entry speed also creates an optimal plan up to this - // point in the buffer. When the plan is bracketed by either the beginning of the - // buffer and a maximum entry speed or two maximum entry speeds, every block in between - // cannot logically be further improved. Hence, we don't have to recompute them anymore. - if (current->entry_speed_sqr == current->max_entry_speed_sqr) - block_buffer_planned = block_index; } + + // The fully optimized entry speed is our new minimum speed. + current->min_entry_speed_sqr = current->entry_speed_sqr; } /** - * recalculate() needs to go over the current plan twice. - * Once in reverse and once forward. This implements the forward pass. - */ -void Planner::forward_pass() { - - // Forward Pass: Forward plan the acceleration curve from the planned pointer onward. - // Also scans for optimal plan breakpoints and appropriately updates the planned pointer. - - // Begin at buffer planned pointer. Note that block_buffer_planned can be modified - // by the stepper ISR, so read it ONCE. It it guaranteed that block_buffer_planned - // will never lead head, so the loop is safe to execute. Also note that the forward - // pass will never modify the values at the tail. - uint8_t block_index = block_buffer_planned; - - block_t *block; - const block_t * previous = nullptr; - while (block_index != block_buffer_head) { - - // Perform the forward pass - block = &block_buffer[block_index]; - - // Only process movement blocks - if (block->is_move()) { - // If there's no previous block or the previous block is not - // BUSY (thus, modifiable) run the forward_pass_kernel. Otherwise, - // the previous block became BUSY, so assume the current block's - // entry speed can't be altered (since that would also require - // updating the exit speed of the previous block). - if (previous && !stepper.is_block_busy(previous)) - forward_pass_kernel(previous, block, block_index); - previous = block; - } - // Advance to the previous - block_index = next_block_index(block_index); - } -} - -/** - * Recalculate the trapezoid speed profiles for all blocks in the plan - * according to the entry_factor for each junction. Must be called by - * recalculate() after updating the blocks. + * Do the forward pass and recalculate the trapezoid speed profiles for all blocks in the plan + * according to entry/exit speeds. */ void Planner::recalculate_trapezoids(const_float_t safe_exit_speed_sqr) { - // The tail may be changed by the ISR so get a local copy. + // Start with the block that's about to execute or is executing. uint8_t block_index = block_buffer_tail, head_block_index = block_buffer_head; - // Since there could be a sync block in the head of the queue, and the - // next loop must not recalculate the head block (as it needs to be - // specially handled), scan backwards to the first non-SYNC block. - while (head_block_index != block_index) { - // Go back (head always point to the first free block) - const uint8_t prev_index = prev_block_index(head_block_index); - - // Get the pointer to the block - block_t *prev = &block_buffer[prev_index]; - - // It the block is a move, we're done with this loop - if (prev->is_move()) break; - - // Examine the previous block. This and all following are SYNC blocks - head_block_index = prev_index; - } - - // Go from the tail (currently executed block) to the first block, without including it) block_t *block = nullptr, *next = nullptr; - float current_entry_speed = 0.0f, next_entry_speed = 0.0f; + float next_entry_speed = 0.0f; while (block_index != head_block_index) { next = &block_buffer[block_index]; - // Only process movement blocks if (next->is_move()) { - next_entry_speed = SQRT(next->entry_speed_sqr); + // Check if the next block's entry speed changed + if (next->flag.recalculate) { + if (!block) { + // 'next' is the first move due to either being the first added move or due to the planner + // having completely fallen behind. Revert any reverse pass change. + next->entry_speed_sqr = next->min_entry_speed_sqr; + next_entry_speed = SQRT(next->min_entry_speed_sqr); + } + else { + // Try to fix exit speed which requires trapezoid recalculation + block->flag.recalculate = true; - if (block) { + // But there is an inherent race condition here, as the block may have + // become BUSY just before being marked RECALCULATE, so check for that! + if (stepper.is_block_busy(block)) { + // Block is BUSY so we can't change the exit speed. Revert any reverse pass change. + next->entry_speed_sqr = next->min_entry_speed_sqr; + if (!next->initial_rate) { + // 'next' was never calculated. Planner is falling behind so for maximum efficiency + // set next's stepping speed directly and forgo checking against min_entry_speed_sqr. + // calculate_trapezoid_for_block() can handle it, albeit sub-optimally. + next->initial_rate = block->final_rate; + } + // Note that at this point next_entry_speed is (still) 0. + } + else { + // Block is not BUSY: we won the race against the ISR or recalculate was already set - // If the next block is marked to RECALCULATE, also mark the previously-fetched one - if (next->flag.recalculate) block->flag.recalculate = true; + if (next->entry_speed_sqr != next->min_entry_speed_sqr) + forward_pass_kernel(block, next); - // Recalculate if current block entry or exit junction speed has changed. - if (block->flag.recalculate) { + const float current_entry_speed = next_entry_speed; + next_entry_speed = SQRT(next->entry_speed_sqr); - // But there is an inherent race condition here, as the block maybe - // became BUSY, just before it was marked as RECALCULATE, so check - // if that is the case! - if (!stepper.is_block_busy(block)) { - // Block is not BUSY, we won the race against the Stepper ISR: - - // NOTE: Entry and exit factors always > 0 by all previous logic operations. - const float nomr = 1.0f / block->nominal_speed; - calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr); + calculate_trapezoid_for_block(block, current_entry_speed, next_entry_speed); } // Reset current only to ensure next trapezoid is computed - The @@ -1220,30 +1151,17 @@ void Planner::recalculate_trapezoids(const_float_t safe_exit_speed_sqr) { } block = next; - current_entry_speed = next_entry_speed; } block_index = next_block_index(block_index); } - // Last/newest block in buffer. Always recalculated. - if (block) { + // Last/newest block in buffer. The above guarantees it's a move block. + if (block && block->flag.recalculate) { + const float current_entry_speed = next_entry_speed; next_entry_speed = SQRT(safe_exit_speed_sqr); - // Mark the next(last) block as RECALCULATE, to prevent the Stepper ISR running it. - // As the last block is always recalculated here, there is a chance the block isn't - // marked as RECALCULATE yet. That's the reason for the following line. - block->flag.recalculate = true; - - // But there is an inherent race condition here, as the block maybe - // became BUSY, just before it was marked as RECALCULATE, so check - // if that is the case! - if (!stepper.is_block_busy(block)) { - // Block is not BUSY, we won the race against the Stepper ISR: - - const float nomr = 1.0f / block->nominal_speed; - calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr); - } + calculate_trapezoid_for_block(block, current_entry_speed, next_entry_speed); // Reset block to ensure its trapezoid is computed - The stepper is free to use // the block from now on. @@ -1251,14 +1169,10 @@ void Planner::recalculate_trapezoids(const_float_t safe_exit_speed_sqr) { } } +// Requires there's at least one block with flag.recalculate in the buffer void Planner::recalculate(const_float_t safe_exit_speed_sqr) { - // Initialize block index to the last block in the planner buffer. - const uint8_t block_index = prev_block_index(block_buffer_head); - // If there is just one block, no planning can be done. Avoid it! - if (block_index != block_buffer_planned) { - reverse_pass(safe_exit_speed_sqr); - forward_pass(); - } + reverse_pass(safe_exit_speed_sqr); + // The forward pass is done as part of recalculate_trapezoids() recalculate_trapezoids(safe_exit_speed_sqr); } @@ -1287,16 +1201,20 @@ void Planner::recalculate(const_float_t safe_exit_speed_sqr) { void Planner::kickstart_fan(uint8_t (&fan_speed)[FAN_COUNT], const millis_t &ms, const uint8_t f) { static millis_t fan_kick_end[FAN_COUNT] = { 0 }; + #if ENABLED(FAN_KICKSTART_LINEAR) + static uint8_t set_fan_speed[FAN_COUNT] = { 0 }; + #endif if (fan_speed[f] > FAN_OFF_PWM) { - if (fan_kick_end[f] == 0) { - fan_kick_end[f] = ms + FAN_KICKSTART_TIME; + const bool first_kick = fan_kick_end[f] == 0 && TERN1(FAN_KICKSTART_LINEAR, fan_speed[f] > set_fan_speed[f]); + if (first_kick) + fan_kick_end[f] = ms + (FAN_KICKSTART_TIME) TERN_(FAN_KICKSTART_LINEAR, * (fan_speed[f] - set_fan_speed[f]) / 255); + if (first_kick || PENDING(ms, fan_kick_end[f])) { fan_speed[f] = FAN_KICKSTART_POWER; + return; } - else if (PENDING(ms, fan_kick_end[f])) - fan_speed[f] = FAN_KICKSTART_POWER; } - else - fan_kick_end[f] = 0; + fan_kick_end[f] = 0; + TERN_(FAN_KICKSTART_LINEAR, set_fan_speed[f] = fan_speed[f]); } #endif @@ -1667,7 +1585,7 @@ void Planner::quick_stop() { const bool was_enabled = stepper.suspend(); // Drop all queue entries - block_buffer_nonbusy = block_buffer_planned = block_buffer_head = block_buffer_tail; + block_buffer_nonbusy = block_buffer_head = block_buffer_tail; // Restart the block delay for the first movement - As the queue was // forced to empty, there's no risk the ISR will touch this. @@ -2436,6 +2354,7 @@ bool Planner::_populate_block( // Compute and limit the acceleration rate for the trapezoid generator. const float steps_per_mm = block->step_event_count * inverse_millimeters; + block->steps_per_mm = steps_per_mm; uint32_t accel; #if ENABLED(LIN_ADVANCE) bool use_advance_lead = false; @@ -2829,6 +2748,8 @@ bool Planner::_populate_block( block->entry_speed_sqr = minimum_planner_speed_sqr; // Set min entry speed. Rarely it could be higher than the previous nominal speed but that's ok. block->min_entry_speed_sqr = minimum_planner_speed_sqr; + // Zero the initial_rate to indicate that calculate_trapezoid_for_block() hasn't been called yet. + block->initial_rate = 0; block->flag.recalculate = true; diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index fd26b4340e..1053a27688 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -219,6 +219,7 @@ typedef struct PlannerBlock { min_entry_speed_sqr, // Minimum allowable junction entry speed in (mm/sec)^2 max_entry_speed_sqr, // Maximum allowable junction entry speed in (mm/sec)^2 millimeters, // The total travel of this block in mm + steps_per_mm, // steps/mm acceleration; // acceleration mm/sec^2 union { @@ -442,7 +443,6 @@ class Planner { static block_t block_buffer[BLOCK_BUFFER_SIZE]; static volatile uint8_t block_buffer_head, // Index of the next block to be pushed block_buffer_nonbusy, // Index of the first non busy block - block_buffer_planned, // Index of the optimally planned block block_buffer_tail; // Index of the busy block, if any static uint16_t cleaning_buffer_counter; // A counter to disable queuing of blocks static uint8_t delay_before_delivering; // This counter delays delivery of blocks when queue becomes empty to allow the opportunity of merging blocks @@ -804,7 +804,7 @@ class Planner { FORCE_INLINE static uint8_t nonbusy_movesplanned() { return block_dec_mod(block_buffer_head, block_buffer_nonbusy); } // Remove all blocks from the buffer - FORCE_INLINE static void clear_block_buffer() { block_buffer_nonbusy = block_buffer_planned = block_buffer_head = block_buffer_tail = 0; } + FORCE_INLINE static void clear_block_buffer() { block_buffer_nonbusy = block_buffer_head = block_buffer_tail = 0; } // Check if movement queue is full FORCE_INLINE static bool is_full() { return block_buffer_tail == next_block_index(block_buffer_head); } @@ -1081,13 +1081,12 @@ class Planner { } #endif - static void calculate_trapezoid_for_block(block_t * const block, const_float_t entry_factor, const_float_t exit_factor); + static void calculate_trapezoid_for_block(block_t * const block, const_float_t entry_speed, const_float_t exit_speed); - static void reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr); - static void forward_pass_kernel(const block_t * const previous, block_t * const current, uint8_t block_index); + static bool reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr); + static void forward_pass_kernel(const block_t * const previous, block_t * const current); static void reverse_pass(const_float_t safe_exit_speed_sqr); - static void forward_pass(); static void recalculate_trapezoids(const_float_t safe_exit_speed_sqr); diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index a9f2f888bf..d4467b7687 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -778,11 +778,13 @@ void MarlinSettings::postprocess() { #define TWO_BYTE_HASH(A,B) uint16_t((uint16_t(A ^ 0xC3) << 4) ^ (uint16_t(B ^ 0xC3) << 12)) + #define EEPROM_OFFSETOF(FIELD) (EEPROM_OFFSET + offsetof(SettingsData, FIELD)) + #if ENABLED(DEBUG_EEPROM_READWRITE) #define _FIELD_TEST(FIELD) \ SERIAL_ECHOLNPGM("Field: " STRINGIFY(FIELD)); \ EEPROM_ASSERT( \ - eeprom_error || eeprom_index == offsetof(SettingsData, FIELD) + EEPROM_OFFSET, \ + eeprom_error || eeprom_index == EEPROM_OFFSETOF(FIELD), \ "Field " STRINGIFY(FIELD) " mismatch." \ ) #else @@ -797,7 +799,7 @@ void MarlinSettings::postprocess() { #define EEPROM_READ_ALWAYS(V...) EEPROM_READ_ALWAYS_(V) #endif - const char version[4] = EEPROM_VERSION; + constexpr char version_str[4] = EEPROM_VERSION; #if ENABLED(EEPROM_INIT_NOW) constexpr uint32_t strhash32(const char *s, const uint32_t h=0) { @@ -827,14 +829,14 @@ void MarlinSettings::postprocess() { */ bool MarlinSettings::save() { float dummyf = 0; - MString<3> ver(F("ERR")); if (!EEPROM_START(EEPROM_OFFSET)) return false; EEPROM_Error eeprom_error = ERR_EEPROM_NOERR; // Write or Skip version. (Flash doesn't allow rewrite without erase.) - TERN(FLASH_EEPROM_EMULATION, EEPROM_SKIP, EEPROM_WRITE)(ver); + constexpr char dummy_version[] = "ERR"; + TERN(FLASH_EEPROM_EMULATION, EEPROM_SKIP, EEPROM_WRITE)(dummy_version); #if ENABLED(EEPROM_INIT_NOW) EEPROM_SKIP(build_hash); // Skip the hash slot which will be written later @@ -1765,7 +1767,7 @@ void MarlinSettings::postprocess() { // Write the EEPROM header eeprom_index = EEPROM_OFFSET; - EEPROM_WRITE(version); + EEPROM_WRITE(version_str); #if ENABLED(EEPROM_INIT_NOW) EEPROM_WRITE(build_hash); #endif @@ -1797,29 +1799,39 @@ void MarlinSettings::postprocess() { return success; } + EEPROM_Error MarlinSettings::check_version() { + if (!EEPROM_START(EEPROM_OFFSET)) return ERR_EEPROM_NOPROM; + char stored_ver[4]; + EEPROM_READ_ALWAYS(stored_ver); + + // Version has to match or defaults are used + if (strncmp(stored_ver, version_str, 3) != 0) { + if (stored_ver[3] != '\0') { + stored_ver[0] = '?'; + stored_ver[1] = '\0'; + } + DEBUG_ECHO_MSG("EEPROM version mismatch (EEPROM=", stored_ver, " Marlin=" EEPROM_VERSION ")"); + return ERR_EEPROM_VERSION; + } + return ERR_EEPROM_NOERR; + } + /** * M501 - Retrieve Configuration */ EEPROM_Error MarlinSettings::_load() { EEPROM_Error eeprom_error = ERR_EEPROM_NOERR; - if (!EEPROM_START(EEPROM_OFFSET)) return eeprom_error; - - char stored_ver[4]; - EEPROM_READ_ALWAYS(stored_ver); + const EEPROM_Error check = check_version(); + if (check == ERR_EEPROM_VERSION) return eeprom_error; uint16_t stored_crc; do { // A block to break out of on error // Version has to match or defaults are used - if (strncmp(version, stored_ver, 3) != 0) { - if (stored_ver[3] != '\0') { - stored_ver[0] = '?'; - stored_ver[1] = '\0'; - } - DEBUG_ECHO_MSG("EEPROM version mismatch (EEPROM=", stored_ver, " Marlin=" EEPROM_VERSION ")"); - eeprom_error = ERR_EEPROM_VERSION; + if (check == ERR_EEPROM_VERSION) { + eeprom_error = check; break; } @@ -2880,8 +2892,7 @@ void MarlinSettings::postprocess() { } else if (!validating) { DEBUG_ECHO_START(); - DEBUG_ECHO(version); - DEBUG_ECHOLNPGM(" stored settings retrieved (", eeprom_total, " bytes; crc ", working_crc, ")"); + DEBUG_ECHOLN(version_str, F(" stored settings retrieved ("), eeprom_total, F(" bytes; crc "), working_crc, ')'); TERN_(HOST_EEPROM_CHITCHAT, hostui.notify(F("Stored settings retrieved"))); } @@ -2967,6 +2978,26 @@ void MarlinSettings::postprocess() { return (err == ERR_EEPROM_NOERR); } + #if HAS_EARLY_LCD_SETTINGS + + #if HAS_LCD_CONTRAST + void MarlinSettings::load_contrast() { + uint8_t lcd_contrast; EEPROM_START(EEPROM_OFFSETOF(lcd_contrast)); EEPROM_READ(lcd_contrast); + DEBUG_ECHOLNPGM("LCD Contrast: ", lcd_contrast); + ui.contrast = lcd_contrast; + } + #endif + + #if HAS_LCD_BRIGHTNESS + void MarlinSettings::load_brightness() { + uint8_t lcd_brightness; EEPROM_START(EEPROM_OFFSETOF(lcd_brightness)); EEPROM_READ(lcd_brightness); + DEBUG_ECHOLNPGM("LCD Brightness: ", lcd_brightness); + ui.brightness = lcd_brightness; + } + #endif + + #endif // HAS_EARLY_LCD_SETTINGS + bool MarlinSettings::load() { if (validate()) { const EEPROM_Error err = _load(); @@ -3117,6 +3148,25 @@ void MarlinSettings::postprocess() { #endif // !EEPROM_SETTINGS +#if HAS_EARLY_LCD_SETTINGS + + void MarlinSettings::load_lcd_state() { + if (TERN0(EEPROM_SETTINGS, check_version() == ERR_EEPROM_NOERR)) { + #if ENABLED(EEPROM_SETTINGS) + TERN_(HAS_LCD_CONTRAST, load_contrast()); + TERN_(HAS_LCD_BRIGHTNESS, load_brightness()); + #endif + } + else { + TERN_(HAS_LCD_CONTRAST, ui.contrast = LCD_CONTRAST_DEFAULT); + TERN_(HAS_LCD_BRIGHTNESS, ui.brightness = LCD_BRIGHTNESS_DEFAULT); + } + TERN_(HAS_LCD_CONTRAST, ui.refresh_contrast()); + TERN_(HAS_LCD_BRIGHTNESS, ui.refresh_brightness()); + } + +#endif // HAS_EARLY_LCD_SETTINGS + /** * M502 - Reset Configuration */ diff --git a/Marlin/src/module/settings.h b/Marlin/src/module/settings.h index b7c5210db5..f181e4014d 100644 --- a/Marlin/src/module/settings.h +++ b/Marlin/src/module/settings.h @@ -34,7 +34,8 @@ ERR_EEPROM_VERSION, ERR_EEPROM_SIZE, ERR_EEPROM_CRC, - ERR_EEPROM_CORRUPT + ERR_EEPROM_CORRUPT, + ERR_EEPROM_NOPROM }; #endif @@ -66,11 +67,24 @@ class MarlinSettings { static bool load(); // Return 'true' if data was loaded ok static bool validate(); // Return 'true' if EEPROM data is ok + static EEPROM_Error check_version(); + static void first_load() { static bool loaded = false; if (!loaded && load()) loaded = true; } + #if HAS_EARLY_LCD_SETTINGS + // Special cases for LCD contrast and brightness, so + // some LCDs can display bootscreens earlier in setup(). + #if HAS_LCD_CONTRAST + static void load_contrast(); + #endif + #if HAS_LCD_BRIGHTNESS + static void load_brightness(); + #endif + #endif + #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system // That can store is enabled static uint16_t meshes_start_index(); @@ -93,6 +107,10 @@ class MarlinSettings { #endif // !EEPROM_SETTINGS + #if HAS_EARLY_LCD_SETTINGS + static void load_lcd_state(); + #endif + #if DISABLED(DISABLE_M503) static void report(const bool forReplay=false); #else diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 083d2019dc..f5a9f6d0a8 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -519,16 +519,15 @@ xyze_int8_t Stepper::count_direction{0}; #define E_APPLY_DIR(FWD,Q) do{ if (FWD) { FWD_E_DIR(stepper_extruder); } else { REV_E_DIR(stepper_extruder); } }while(0) #endif -#define CYCLES_TO_NS(CYC) (1000UL * (CYC) / ((F_CPU) / 1000000)) -#define NS_PER_PULSE_TIMER_TICK (1000000000UL / (STEPPER_TIMER_RATE)) +constexpr uint32_t cycles_to_ns(const uint32_t CYC) { return 1000UL * (CYC) / ((F_CPU) / 1000000); } +constexpr uint32_t ns_per_pulse_timer_tick = 1000000000UL / (STEPPER_TIMER_RATE); // Round up when converting from ns to timer ticks -#define NS_TO_PULSE_TIMER_TICKS(NS) (((NS) + (NS_PER_PULSE_TIMER_TICK) / 2) / (NS_PER_PULSE_TIMER_TICK)) +constexpr hal_timer_t ns_to_pulse_timer_ticks(const uint32_t ns) { return (ns + ns_per_pulse_timer_tick / 2) / ns_per_pulse_timer_tick; } -#define TIMER_SETUP_NS (CYCLES_TO_NS(TIMER_READ_ADD_AND_STORE_CYCLES)) - -#define PULSE_HIGH_TICK_COUNT hal_timer_t(NS_TO_PULSE_TIMER_TICKS(_MIN_PULSE_HIGH_NS - _MIN(_MIN_PULSE_HIGH_NS, TIMER_SETUP_NS))) -#define PULSE_LOW_TICK_COUNT hal_timer_t(NS_TO_PULSE_TIMER_TICKS(_MIN_PULSE_LOW_NS - _MIN(_MIN_PULSE_LOW_NS, TIMER_SETUP_NS))) +constexpr uint32_t timer_setup_ns = cycles_to_ns(timer_read_add_and_store_cycles); +constexpr hal_timer_t PULSE_HIGH_TICK_COUNT = ns_to_pulse_timer_ticks(_min_pulse_high_ns - _MIN(_min_pulse_high_ns, timer_setup_ns)); +constexpr hal_timer_t PULSE_LOW_TICK_COUNT = ns_to_pulse_timer_ticks(_min_pulse_low_ns - _MIN(_min_pulse_low_ns, timer_setup_ns)); #define USING_TIMED_PULSE() hal_timer_t start_pulse_count = 0 #define START_TIMED_PULSE() (start_pulse_count = HAL_timer_get_count(MF_TIMER_PULSE)) @@ -1720,10 +1719,10 @@ void Stepper::isr() { #endif } -#if MINIMUM_STEPPER_PULSE || MAXIMUM_STEPPER_RATE +#if MINIMUM_STEPPER_PULSE_NS || MAXIMUM_STEPPER_RATE #define ISR_PULSE_CONTROL 1 #endif -#if ISR_PULSE_CONTROL && DISABLED(I2S_STEPPER_STREAM) +#if ISR_PULSE_CONTROL && MULTISTEPPING_LIMIT > 1 && DISABLED(I2S_STEPPER_STREAM) #define ISR_MULTI_STEPS 1 #endif @@ -1772,10 +1771,11 @@ void Stepper::pulse_phase_isr() { // Just update the value we will get at the end of the loop step_events_completed += events_to_do; - // Take multiple steps per interrupt (For high speed moves) - #if ISR_MULTI_STEPS + TERN_(ISR_PULSE_CONTROL, USING_TIMED_PULSE()); + + // Take multiple steps per interrupt. For high speed moves. + #if ENABLED(ISR_MULTI_STEPS) bool firstStep = true; - USING_TIMED_PULSE(); #endif // Direct Stepping page? @@ -2080,8 +2080,8 @@ void Stepper::pulse_phase_isr() { TERN_(I2S_STEPPER_STREAM, i2s_push_sample()); - // TODO: need to deal with MINIMUM_STEPPER_PULSE over i2s - #if ISR_MULTI_STEPS + // TODO: need to deal with MINIMUM_STEPPER_PULSE_NS over i2s + #if ISR_PULSE_CONTROL START_TIMED_PULSE(); AWAIT_HIGH_PULSE(); #endif @@ -2235,7 +2235,7 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) { #if ENABLED(NONLINEAR_EXTRUSION) void Stepper::calc_nonlinear_e(uint32_t step_rate) { const uint32_t velocity = ne_scale * step_rate; // Scale step_rate first so all intermediate values stay in range of 8.24 fixed point math - int32_t vd = (((int64_t)ne_fix.A * velocity) >> 24) + (((((int64_t)ne_fix.B * velocity) >> 24) * velocity) >> 24); + int32_t vd = (((((int64_t)ne_fix.A * velocity) >> 24) * velocity) >> 24) + (((int64_t)ne_fix.B * velocity) >> 24); NOLESS(vd, 0); advance_dividend.e = (uint64_t(ne_fix.C + vd) * ne_edividend) >> 24; @@ -2256,25 +2256,25 @@ hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) { // The stepping frequency limits for each multistepping rate static const uint32_t limit[] PROGMEM = { - ( MAX_STEP_ISR_FREQUENCY_1X ) - , (((F_CPU) / ISR_EXECUTION_CYCLES(1)) >> 1) + max_step_isr_frequency_sh(0) + , max_step_isr_frequency_sh(1) #if MULTISTEPPING_LIMIT >= 4 - , (((F_CPU) / ISR_EXECUTION_CYCLES(2)) >> 2) + , max_step_isr_frequency_sh(2) #endif #if MULTISTEPPING_LIMIT >= 8 - , (((F_CPU) / ISR_EXECUTION_CYCLES(3)) >> 3) + , max_step_isr_frequency_sh(3) #endif #if MULTISTEPPING_LIMIT >= 16 - , (((F_CPU) / ISR_EXECUTION_CYCLES(4)) >> 4) + , max_step_isr_frequency_sh(4) #endif #if MULTISTEPPING_LIMIT >= 32 - , (((F_CPU) / ISR_EXECUTION_CYCLES(5)) >> 5) + , max_step_isr_frequency_sh(5) #endif #if MULTISTEPPING_LIMIT >= 64 - , (((F_CPU) / ISR_EXECUTION_CYCLES(6)) >> 6) + , max_step_isr_frequency_sh(6) #endif #if MULTISTEPPING_LIMIT >= 128 - , (((F_CPU) / ISR_EXECUTION_CYCLES(7)) >> 7) + , max_step_isr_frequency_sh(7) #endif }; @@ -2695,16 +2695,14 @@ hal_timer_t Stepper::block_phase_isr() { set_axis_moved_for_current_block(); #if ENABLED(ADAPTIVE_STEP_SMOOTHING) - // Nonlinear Extrusion needs at least 2x oversampling to permit increase of E step rate - // Otherwise assume no axis smoothing (via oversampling) - oversampling_factor = TERN0(NONLINEAR_EXTRUSION, 1); + oversampling_factor = 0; // Decide if axis smoothing is possible if (stepper.adaptive_step_smoothing_enabled) { uint32_t max_rate = current_block->nominal_rate; // Get the step event rate - while (max_rate < MIN_STEP_ISR_FREQUENCY) { // As long as more ISRs are possible... + while (max_rate < min_step_isr_frequency) { // As long as more ISRs are possible... max_rate <<= 1; // Try to double the rate - if (max_rate < MIN_STEP_ISR_FREQUENCY) // Don't exceed the estimated ISR limit + if (max_rate < min_step_isr_frequency) // Don't exceed the estimated ISR limit ++oversampling_factor; // Increase the oversampling (used for left-shift) } } @@ -3737,8 +3735,8 @@ void Stepper::report_positions() { #define _READ_DIR(AXIS) AXIS ##_DIR_READ() #define _APPLY_DIR(AXIS, FWD) AXIS ##_APPLY_DIR(FWD, true) - #if MINIMUM_STEPPER_PULSE - #define STEP_PULSE_CYCLES ((MINIMUM_STEPPER_PULSE) * CYCLES_PER_MICROSECOND) + #if MINIMUM_STEPPER_PULSE_NS + #define STEP_PULSE_CYCLES ((MINIMUM_STEPPER_PULSE_NS) * CYCLES_PER_MICROSECOND / 1000) #else #define STEP_PULSE_CYCLES 0 #endif @@ -3761,7 +3759,7 @@ void Stepper::report_positions() { #else #define _SAVE_START() NOOP #if EXTRA_CYCLES_BABYSTEP > 0 - #define _PULSE_WAIT() DELAY_NS(EXTRA_CYCLES_BABYSTEP * NANOSECONDS_PER_CYCLE) + #define _PULSE_WAIT() DELAY_CYCLES(EXTRA_CYCLES_BABYSTEP) #elif ENABLED(DELTA) #define _PULSE_WAIT() DELAY_US(2); #elif STEP_PULSE_CYCLES > 0 diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index 8cf6d39dea..3586c23e70 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -146,12 +146,12 @@ constexpr ena_mask_t enable_overlap[] = { TERN0(INPUT_SHAPING_Y, _ISDMF[Y_AXIS] * _ISDASU[Y_AXIS]) + TERN0(INPUT_SHAPING_Z, _ISDMF[Z_AXIS] * _ISDASU[Z_AXIS]); #if defined(__AVR__) || !defined(ADAPTIVE_STEP_SMOOTHING) - // MIN_STEP_ISR_FREQUENCY is known at compile time on AVRs and any reduction in SRAM is welcome + // min_step_isr_frequency is known at compile time on AVRs and any reduction in SRAM is welcome template constexpr float max_isr_rate() { return _MAX(_ISDMF[ISALIM(INDEX - 1, _ISDMF)] * _ISDASU[ISALIM(INDEX - 1, _ISDASU)], max_isr_rate()); } template<> constexpr float max_isr_rate<0>() { - return TERN0(ADAPTIVE_STEP_SMOOTHING, MIN_STEP_ISR_FREQUENCY); + return TERN0(ADAPTIVE_STEP_SMOOTHING, min_step_isr_frequency); } constexpr float max_step_rate = _MIN(max_isr_rate(), max_shaped_rate); #else diff --git a/Marlin/src/module/stepper/cycles.h b/Marlin/src/module/stepper/cycles.h index 0089124eed..b01d199cd8 100644 --- a/Marlin/src/module/stepper/cycles.h +++ b/Marlin/src/module/stepper/cycles.h @@ -40,184 +40,123 @@ * take longer, pulses will be longer. For example the SKR Pro * (stm32f407zgt6) requires ~60 cyles. */ - #define TIMER_READ_ADD_AND_STORE_CYCLES 34UL + constexpr uint32_t timer_read_add_and_store_cycles = 34UL; // The base ISR - #define ISR_BASE_CYCLES 770UL + constexpr uint32_t isr_base_cycles = 770UL; // Linear advance base time is 64 cycles - #if ENABLED(LIN_ADVANCE) - #define ISR_LA_BASE_CYCLES 64UL - #else - #define ISR_LA_BASE_CYCLES 0UL - #endif + constexpr uint32_t isr_la_base_cycles = TERN0(LIN_ADVANCE, 64UL); // S curve interpolation adds 40 cycles - #if ENABLED(S_CURVE_ACCELERATION) - #ifdef STM32G0B1xx - #define ISR_S_CURVE_CYCLES 500UL - #else - #define ISR_S_CURVE_CYCLES 40UL - #endif - #else - #define ISR_S_CURVE_CYCLES 0UL - #endif + constexpr uint32_t isr_s_curve_cycles = TERN0(S_CURVE_ACCELERATION, TERN(STM32G0B1xx, 500UL, 40UL)); // Input shaping base time - #if HAS_ZV_SHAPING - #define ISR_SHAPING_BASE_CYCLES 180UL - #else - #define ISR_SHAPING_BASE_CYCLES 0UL - #endif + constexpr uint32_t isr_shaping_base_cycles = TERN0(HAS_ZV_SHAPING, 180UL); // Stepper Loop base cycles - #define ISR_LOOP_BASE_CYCLES 4UL + constexpr uint32_t isr_loop_base_cycles = 4UL; // And each stepper (start + stop pulse) takes in worst case - #define ISR_STEPPER_CYCLES 100UL + constexpr uint32_t isr_stepper_cycles = 100UL; #else // Cycles to perform actions in START_TIMED_PULSE - #define TIMER_READ_ADD_AND_STORE_CYCLES 13UL + constexpr uint32_t timer_read_add_and_store_cycles = 13UL; // The base ISR - #define ISR_BASE_CYCLES 882UL + constexpr uint32_t isr_base_cycles = 882UL; // Linear advance base time is 32 cycles - #if ENABLED(LIN_ADVANCE) - #define ISR_LA_BASE_CYCLES 30UL - #else - #define ISR_LA_BASE_CYCLES 0UL - #endif + constexpr uint32_t isr_la_base_cycles = TERN0(LIN_ADVANCE, 30UL); // S curve interpolation adds 160 cycles - #if ENABLED(S_CURVE_ACCELERATION) - #define ISR_S_CURVE_CYCLES 160UL - #else - #define ISR_S_CURVE_CYCLES 0UL - #endif + constexpr uint32_t isr_s_curve_cycles = TERN0(S_CURVE_ACCELERATION, 160UL); // Input shaping base time - #if HAS_ZV_SHAPING - #define ISR_SHAPING_BASE_CYCLES 290UL - #else - #define ISR_SHAPING_BASE_CYCLES 0UL - #endif + constexpr uint32_t isr_shaping_base_cycles = TERN0(HAS_ZV_SHAPING, 290UL); // Stepper Loop base cycles - #define ISR_LOOP_BASE_CYCLES 32UL + constexpr uint32_t isr_loop_base_cycles = 32UL; // And each stepper (start + stop pulse) takes in worst case - #define ISR_STEPPER_CYCLES 60UL + constexpr uint32_t isr_stepper_cycles = 60UL; #endif // If linear advance is disabled, the loop also handles them -#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER) - #define ISR_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES)) -#else - #define ISR_MIXING_STEPPER_CYCLES 0UL -#endif +constexpr uint32_t isr_mixing_stepper_cycles = (0UL + #if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER) + + (MIXING_STEPPERS) * isr_stepper_cycles + #endif +); -// Add time for each stepper -#if HAS_X_STEP - #define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES -#endif -#if HAS_Y_STEP - #define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES -#endif -#if HAS_Z_STEP - #define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES -#endif -#if HAS_I_STEP - #define ISR_I_STEPPER_CYCLES ISR_STEPPER_CYCLES -#endif -#if HAS_J_STEP - #define ISR_J_STEPPER_CYCLES ISR_STEPPER_CYCLES -#endif -#if HAS_K_STEP - #define ISR_K_STEPPER_CYCLES ISR_STEPPER_CYCLES -#endif -#if HAS_U_STEP - #define ISR_U_STEPPER_CYCLES ISR_STEPPER_CYCLES -#endif -#if HAS_V_STEP - #define ISR_V_STEPPER_CYCLES ISR_STEPPER_CYCLES -#endif -#if HAS_W_STEP - #define ISR_W_STEPPER_CYCLES ISR_STEPPER_CYCLES -#endif -#if HAS_EXTRUDERS - #define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES // E is always interpolated, even for mixing extruders -#endif - -// And the total minimum loop time, not including the base -#define _PLUS_AXIS_CYCLES(A) + (ISR_##A##_STEPPER_CYCLES) -#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_MAP(_PLUS_AXIS_CYCLES)) - -// Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate -#define _MIN_STEPPER_PULSE_CYCLES(N) _MAX(uint32_t((F_CPU) / (MAXIMUM_STEPPER_RATE)), ((F_CPU) / 500000UL) * (N)) -#if MINIMUM_STEPPER_PULSE - #define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(uint32_t(MINIMUM_STEPPER_PULSE)) -#elif HAS_DRIVER(LV8729) - #define MIN_STEPPER_PULSE_CYCLES uint32_t((((F_CPU) - 1) / 2000000) + 1) // 0.5µs, aka 500ns -#else - #define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(1UL) -#endif +// And the total minimum loop time, for all steppers, not including the base +constexpr uint32_t min_isr_loop_cycles = isr_mixing_stepper_cycles + LOGICAL_AXES * isr_stepper_cycles; // Calculate the minimum pulse times (high and low) -#if MINIMUM_STEPPER_PULSE && MAXIMUM_STEPPER_RATE - constexpr uint32_t _MIN_STEP_PERIOD_NS = 1000000000UL / MAXIMUM_STEPPER_RATE; - constexpr uint32_t _MIN_PULSE_HIGH_NS = 1000UL * MINIMUM_STEPPER_PULSE; - constexpr uint32_t _MIN_PULSE_LOW_NS = _MAX((_MIN_STEP_PERIOD_NS - _MIN(_MIN_STEP_PERIOD_NS, _MIN_PULSE_HIGH_NS)), _MIN_PULSE_HIGH_NS); -#elif MINIMUM_STEPPER_PULSE - // Assume 50% duty cycle - constexpr uint32_t _MIN_PULSE_HIGH_NS = 1000UL * MINIMUM_STEPPER_PULSE; - constexpr uint32_t _MIN_PULSE_LOW_NS = _MIN_PULSE_HIGH_NS; -#elif MAXIMUM_STEPPER_RATE - // Assume 50% duty cycle - constexpr uint32_t _MIN_PULSE_HIGH_NS = 500000000UL / MAXIMUM_STEPPER_RATE; - constexpr uint32_t _MIN_PULSE_LOW_NS = _MIN_PULSE_HIGH_NS; +#if defined(MINIMUM_STEPPER_PULSE_NS) && defined(MAXIMUM_STEPPER_RATE) + constexpr uint32_t _min_step_period_ns = 1000000000UL / (MAXIMUM_STEPPER_RATE), + _min_pulse_high_ns = MINIMUM_STEPPER_PULSE_NS, + _min_pulse_low_ns = _MAX(_min_step_period_ns - _MIN(_min_step_period_ns, _min_pulse_high_ns), _min_pulse_high_ns); +#elif defined(MINIMUM_STEPPER_PULSE_NS) + // Assume equal high and low pulse durations + constexpr uint32_t _min_pulse_high_ns = MINIMUM_STEPPER_PULSE_NS, + _min_pulse_low_ns = _min_pulse_high_ns; +#elif defined(MAXIMUM_STEPPER_RATE) + // Assume equal high and low pulse durations + constexpr uint32_t _min_pulse_high_ns = 500000000UL / MAXIMUM_STEPPER_RATE, + _min_pulse_low_ns = _min_pulse_high_ns; #else - #error "Expected at least one of MINIMUM_STEPPER_PULSE or MAXIMUM_STEPPER_RATE to be defined" + #error "At least one of MINIMUM_STEPPER_PULSE_NS or MAXIMUM_STEPPER_RATE must be defined" #endif +// Calculate the minimum MPU cycles needed per pulse to enforce +constexpr uint32_t min_stepper_pulse_cycles = _min_pulse_high_ns * CYCLES_PER_MICROSECOND / 1000; + // The loop takes the base time plus the time for all the bresenham logic for 1 << R pulses plus the time // between pulses for ((1 << R) - 1) pulses. But the user could be enforcing a minimum time so the loop time is: -#define ISR_LOOP_CYCLES(R) ((ISR_LOOP_BASE_CYCLES + MIN_ISR_LOOP_CYCLES + MIN_STEPPER_PULSE_CYCLES) * ((1UL << R) - 1) + _MAX(MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES)) +constexpr uint32_t isr_loop_cycles(const int R) { return ((isr_loop_base_cycles + min_isr_loop_cycles + min_stepper_pulse_cycles) * ((1UL << R) - 1) + _MAX(min_isr_loop_cycles, min_stepper_pulse_cycles)); } // Model input shaping as an extra loop call -#define ISR_SHAPING_LOOP_CYCLES(R) (TERN0(HAS_ZV_SHAPING, (ISR_LOOP_BASE_CYCLES + TERN0(INPUT_SHAPING_X, ISR_X_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Y, ISR_Y_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Z, ISR_Z_STEPPER_CYCLES)) << R)) +constexpr uint32_t isr_shaping_loop_cycles(const int R) { + return ( + #if HAS_ZV_SHAPING + isr_loop_base_cycles + + isr_stepper_cycles * COUNT_ENABLED(INPUT_SHAPING_X, INPUT_SHAPING_Y, INPUT_SHAPING_Z) + #else + 0 + #endif + ) << R; +} // If linear advance is enabled, then it is handled separately #if ENABLED(LIN_ADVANCE) // Estimate the minimum LA loop time - #if ENABLED(MIXING_EXTRUDER) // ToDo: ??? + constexpr uint32_t min_isr_la_loop_cycles = (isr_stepper_cycles + // ToDo: ??? // HELP ME: What is what? // Directions are set up for MIXING_STEPPERS - like before. // Finding the right stepper may last up to MIXING_STEPPERS loops in get_next_stepper(). // These loops are a bit faster than advancing a bresenham counter. // Always only one E stepper is stepped. - #define MIN_ISR_LA_LOOP_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES)) - #else - #define MIN_ISR_LA_LOOP_CYCLES ISR_STEPPER_CYCLES - #endif + * TERN1(MIXING_EXTRUDER, (MIXING_STEPPERS)) + ); - // And the real loop time - #define ISR_LA_LOOP_CYCLES _MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LA_LOOP_CYCLES) - -#else - #define ISR_LA_LOOP_CYCLES 0UL #endif +// The real LA loop time will be the larger minimum (pulse or loop) +constexpr uint32_t isr_la_loop_cycles = TERN0(LIN_ADVANCE, _MAX(min_stepper_pulse_cycles, min_isr_la_loop_cycles)); + // Estimate the total ISR execution time in cycles given a step-per-ISR shift multiplier -#define ISR_EXECUTION_CYCLES(R) ((ISR_BASE_CYCLES + ISR_S_CURVE_CYCLES + ISR_SHAPING_BASE_CYCLES + ISR_LOOP_CYCLES(R) + ISR_SHAPING_LOOP_CYCLES(R) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES) >> R) +constexpr uint32_t isr_execution_cycles(const int R) { return (isr_base_cycles + isr_s_curve_cycles + isr_shaping_base_cycles + isr_loop_cycles(R) + isr_shaping_loop_cycles(R) + isr_la_base_cycles + isr_la_loop_cycles) >> R; } // The maximum allowable stepping frequency when doing 1x stepping (in Hz) -#define MAX_STEP_ISR_FREQUENCY_1X ((F_CPU) / ISR_EXECUTION_CYCLES(0)) +constexpr uint32_t max_step_isr_frequency_1x = (F_CPU) / isr_execution_cycles(0); +constexpr uint32_t max_step_isr_frequency_sh(const int S) { return ((F_CPU) / isr_execution_cycles(S)) >> S; } // The minimum step ISR rate used by ADAPTIVE_STEP_SMOOTHING to target 50% CPU usage // This does not account for the possibility of multi-stepping. -#define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X >> 1) +constexpr uint32_t min_step_isr_frequency = max_step_isr_frequency_1x >> 1; diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 16b43f62f0..1b8ebeea69 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -1430,7 +1430,7 @@ int16_t Temperature::getHeaterPower(const heater_id_t heater_id) { // inline void loud_kill(FSTR_P const lcd_msg, const heater_id_t heater_id) { - marlin_state = MF_KILLED; + marlin_state = MarlinState::MF_KILLED; thermalManager.disable_all_heaters(); #if HAS_BEEPER for (uint8_t i = 20; i--;) { @@ -2077,7 +2077,7 @@ void Temperature::mintemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_T * - Update the heated bed PID output value */ void Temperature::task() { - if (marlin_state == MF_INITIALIZING) return hal.watchdog_refresh(); // If Marlin isn't started, at least reset the watchdog! + if (marlin_state == MarlinState::MF_INITIALIZING) return hal.watchdog_refresh(); // If Marlin isn't started, at least reset the watchdog! static bool no_reentry = false; // Prevent recursion if (no_reentry) return; diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h index b03f77fa51..d5051ab6dc 100644 --- a/Marlin/src/pins/pins.h +++ b/Marlin/src/pins/pins.h @@ -571,15 +571,15 @@ #elif MB(BTT_SKR_MINI_E3_V3_0) #include "stm32g0/pins_BTT_SKR_MINI_E3_V3_0.h" // STM32G0 env:STM32G0B1RE_btt env:STM32G0B1RE_btt_xfer #elif MB(BTT_MANTA_M4P_V2_1) - #include "stm32g0/pins_BTT_MANTA_M4P_V2_1.h" // STM32G0 env:STM32G0B1RE_manta_btt env:STM32G0B1RE_manta_btt_xfer + #include "stm32g0/pins_BTT_MANTA_M4P_V2_1.h" // STM32G0 env:STM32G0B1RE_manta_btt #elif MB(BTT_MANTA_M5P_V1_0) - #include "stm32g0/pins_BTT_MANTA_M5P_V1_0.h" // STM32G0 env:STM32G0B1RE_manta_btt env:STM32G0B1RE_manta_btt_xfer + #include "stm32g0/pins_BTT_MANTA_M5P_V1_0.h" // STM32G0 env:STM32G0B1RE_manta_btt #elif MB(BTT_MANTA_E3_EZ_V1_0) - #include "stm32g0/pins_BTT_MANTA_E3_EZ_V1_0.h" // STM32G0 env:STM32G0B1RE_manta_btt env:STM32G0B1RE_manta_btt_xfer + #include "stm32g0/pins_BTT_MANTA_E3_EZ_V1_0.h" // STM32G0 env:STM32G0B1RE_manta_btt #elif MB(BTT_MANTA_M8P_V1_0) - #include "stm32g0/pins_BTT_MANTA_M8P_V1_0.h" // STM32G0 env:STM32G0B1VE_btt env:STM32G0B1VE_btt_xfer + #include "stm32g0/pins_BTT_MANTA_M8P_V1_0.h" // STM32G0 env:STM32G0B1VE_btt #elif MB(BTT_MANTA_M8P_V1_1) - #include "stm32g0/pins_BTT_MANTA_M8P_V1_1.h" // STM32G0 env:STM32G0B1VE_btt env:STM32G0B1VE_btt_xfer + #include "stm32g0/pins_BTT_MANTA_M8P_V1_1.h" // STM32G0 env:STM32G0B1VE_btt // // STM32 ARM Cortex-M3 @@ -987,8 +987,6 @@ #error "BOARD_BIQU_SKR_V1_1 is now BOARD_BTT_SKR_V1_1. Please update your configuration." #elif MB(BIGTREE_SKR_V1_1) #error "BOARD_BIGTREE_SKR_V1_1 is now BOARD_BTT_SKR_V1_1. Please update your configuration." - #elif MB(BIGTREE_SKR_V1_2) - #error "BOARD_BIGTREE_SKR_V1_2 is now BOARD_BTT_SKR_V1_2. Please update your configuration." #elif MB(BIGTREE_SKR_V1_3) #error "BOARD_BIGTREE_SKR_V1_3 is now BOARD_BTT_SKR_V1_3. Please update your configuration." #elif MB(BIGTREE_SKR_V1_4) diff --git a/Marlin/src/pins/pins_postprocess.h b/Marlin/src/pins/pins_postprocess.h index e2db01e27e..40d457cb10 100644 --- a/Marlin/src/pins/pins_postprocess.h +++ b/Marlin/src/pins/pins_postprocess.h @@ -556,20 +556,20 @@ #elif Z_HOME_TO_MAX #define Z_MAX_PIN Z_STOP_PIN #endif - #elif Z_HOME_TO_MIN - #define Z_STOP_PIN Z_MIN_PIN - #elif Z_HOME_TO_MAX - #define Z_STOP_PIN Z_MAX_PIN #endif - #if ENABLED(Z_MULTI_ENDSTOPS) && PIN_EXISTS(Z_STOP) - #ifndef Z2_STOP_PIN - #define Z2_STOP_PIN Z_STOP_PIN + #if ENABLED(Z_MULTI_ENDSTOPS) + #if ((Z_HOME_TO_MIN && !defined(Z2_MIN_PIN)) || (Z_HOME_TO_MAX && !defined(Z2_MAX_PIN))) && !defined(Z2_STOP_PIN) + #error "Z2_STOP_PIN is required for Z_MULTI_ENDSTOPS. Define Z2_STOP_PIN in Configuration_adv.h." #endif - #if NUM_Z_STEPPERS >= 3 && !defined(Z3_STOP_PIN) - #define Z3_STOP_PIN Z_STOP_PIN + #if NUM_Z_STEPPERS >= 3 + #if ((Z_HOME_TO_MIN && !defined(Z3_MIN_PIN)) || (Z_HOME_TO_MAX && !defined(Z3_MAX_PIN))) && !defined(Z3_STOP_PIN) + #error "Z3_STOP_PIN is required for Z_MULTI_ENDSTOPS with NUM_Z_STEPPERS >= 3. Define Z3_STOP_PIN in Configuration_adv.h." + #endif #endif - #if NUM_Z_STEPPERS >= 4 && !defined(Z4_STOP_PIN) - #define Z4_STOP_PIN Z_STOP_PIN + #if NUM_Z_STEPPERS >= 4 + #if ((Z_HOME_TO_MIN && !defined(Z4_MIN_PIN)) || (Z_HOME_TO_MAX && !defined(Z4_MAX_PIN))) && !defined(Z4_STOP_PIN) + #error "Z4_STOP_PIN is required for Z_MULTI_ENDSTOPS with NUM_Z_STEPPERS == 4. Define Z4_STOP_PIN in Configuration_adv.h." + #endif #endif #endif #endif diff --git a/Marlin/src/pins/ramps/pins_RAMPS_CREALITY.h b/Marlin/src/pins/ramps/pins_RAMPS_CREALITY.h index 49a8c196d0..09a1608aa1 100644 --- a/Marlin/src/pins/ramps/pins_RAMPS_CREALITY.h +++ b/Marlin/src/pins/ramps/pins_RAMPS_CREALITY.h @@ -29,17 +29,57 @@ #define BOARD_INFO_NAME "Creality3D RAMPS" +//#define CR2020_INDUSTRIAL_SERIES // Use layout specific to CR2020 + +// +// 4-pin expansion header +// +#define EXP1_PIN 65 // A11 - Used by CR2020 Industrial series for case +#define EXP2_PIN 66 // A12 +#define EXP3_PIN 11 // RAMPS: SERVO0_PIN +#define EXP4_PIN 12 // RAMPS: PS_ON_PIN + +// +// Servos +// +#define SERVO1_PIN 12 + // // Heaters / Fans // #define MOSFET_B_PIN 7 #define FAN0_PIN 9 +// +// Filament Runout Sensor +// #define FIL_RUNOUT_PIN 2 #if NUM_RUNOUT_SENSORS >= 2 #define FIL_RUNOUT2_PIN 15 // Creality CR-X can use dual runout sensors #endif +// +// Misc. Functions +// +#ifdef CR2020_INDUSTRIAL_SERIES + #if ENABLED(PSU_CONTROL) && !defined(PS_ON_PIN) + #define PS_ON_PIN 40 // Used by CR2020 Industrial series + #endif + #ifndef SUICIDE_PIN + #define SUICIDE_PIN 12 // Used by CR2020 Industrial series + #endif + #ifndef SUICIDE_PIN_STATE + #define SUICIDE_PIN_STATE HIGH + #endif +#endif + +#if ENABLED(CASE_LIGHT_ENABLE) && !defined(CASE_LIGHT_PIN) + #define CASE_LIGHT_PIN 65 +#endif + +// +// SD Card +// #ifndef SD_DETECT_PIN #if SD_CONNECTION_IS(ONBOARD) //#define HAS_ONBOARD_SD_DETECT // If the SD_DETECT_PIN is wired up @@ -49,28 +89,14 @@ #endif #endif -#ifndef PS_ON_PIN - #define PS_ON_PIN 40 // Used by CR2020 Industrial series -#endif - -#if ENABLED(CASE_LIGHT_ENABLE) && !defined(CASE_LIGHT_PIN) - #define CASE_LIGHT_PIN 65 -#endif - -#define SERVO1_PIN 12 - +// +// Based on RAMPS 1.4 +// #include "pins_RAMPS.h" +// +// LCD / Controller +// #ifndef BEEPER_PIN #define BEEPER_PIN 37 // Always define beeper pin so Play Tone works with ExtUI #endif - -#define EXP1_PIN 65 // A11 - Used by CR2020 Industrial series for case -#define EXP2_PIN 66 // A12 -#define EXP3_PIN 11 // SERVO0_PIN -#define EXP4_PIN 12 // PS_ON_PIN - -#define SUICIDE_PIN 12 // Used by CR2020 Industrial series -#ifndef SUICIDE_PIN_STATE - #define SUICIDE_PIN_STATE HIGH -#endif diff --git a/Marlin/src/pins/sam/pins_ARCHIM1.h b/Marlin/src/pins/sam/pins_ARCHIM1.h index e7530f981b..1d8a77ba36 100644 --- a/Marlin/src/pins/sam/pins_ARCHIM1.h +++ b/Marlin/src/pins/sam/pins_ARCHIM1.h @@ -26,10 +26,10 @@ * * The Archim 1.0 board requires Arduino Archim addons installed. * - * - Add the following URL to Arduino IDE's Additional Board Manager URLs: + * - Add the following URL to Arduino IDE's Additional Boards Manager URLs: * https://raw.githubusercontent.com/ultimachine/ArduinoAddons/master/package_ultimachine_index.json * - * - In the Arduino IDE Board Manager search for Archim and install the package. + * - In the Arduino IDE Boards Manager search for Archim and install the package. * * - Change your target board to "Archim". * diff --git a/Marlin/src/pins/sam/pins_ARCHIM2.h b/Marlin/src/pins/sam/pins_ARCHIM2.h index 31ed50194c..cd8527c727 100644 --- a/Marlin/src/pins/sam/pins_ARCHIM2.h +++ b/Marlin/src/pins/sam/pins_ARCHIM2.h @@ -26,10 +26,10 @@ * * The Archim 2.0 board requires Arduino Archim addons installed. * - * - Add the following URL to Arduino IDE's Additional Board Manager URLs: + * - Add the following URL to Arduino IDE's Additional Boards Manager URLs: * https://raw.githubusercontent.com/ultimachine/ArduinoAddons/master/package_ultimachine_index.json * - * - In the Arduino IDE Board Manager search for Archim and install the package. + * - In the Arduino IDE Boards Manager search for Archim and install the package. * * - Change your target board to "Archim". * diff --git a/Marlin/src/pins/sanguino/pins_ANET_10.h b/Marlin/src/pins/sanguino/pins_ANET_10.h index ee9fa32774..323154fc35 100644 --- a/Marlin/src/pins/sanguino/pins_ANET_10.h +++ b/Marlin/src/pins/sanguino/pins_ANET_10.h @@ -34,7 +34,7 @@ */ /** - * The standard Arduino IDE extension (board manager) for this board + * The standard Arduino IDE extension (Boards Manager) for this board * is located at https://github.com/SkyNet3D/anet-board. * * Installation instructions are on that page. @@ -51,7 +51,7 @@ */ /** - * Another usable Arduino IDE extension (board manager) can be found at + * Another usable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_GEN3_MONOLITHIC.h b/Marlin/src/pins/sanguino/pins_GEN3_MONOLITHIC.h index a5afc30187..2fa407d07e 100644 --- a/Marlin/src/pins/sanguino/pins_GEN3_MONOLITHIC.h +++ b/Marlin/src/pins/sanguino/pins_GEN3_MONOLITHIC.h @@ -33,7 +33,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_GEN3_PLUS.h b/Marlin/src/pins/sanguino/pins_GEN3_PLUS.h index 7cab1bd762..2340bb5040 100644 --- a/Marlin/src/pins/sanguino/pins_GEN3_PLUS.h +++ b/Marlin/src/pins/sanguino/pins_GEN3_PLUS.h @@ -32,7 +32,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_GEN6.h b/Marlin/src/pins/sanguino/pins_GEN6.h index 3fb1671b73..8ccb311ce3 100644 --- a/Marlin/src/pins/sanguino/pins_GEN6.h +++ b/Marlin/src/pins/sanguino/pins_GEN6.h @@ -35,7 +35,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_GEN6_DELUXE.h b/Marlin/src/pins/sanguino/pins_GEN6_DELUXE.h index 476375203c..caf395fd94 100644 --- a/Marlin/src/pins/sanguino/pins_GEN6_DELUXE.h +++ b/Marlin/src/pins/sanguino/pins_GEN6_DELUXE.h @@ -32,7 +32,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_GEN7_12.h b/Marlin/src/pins/sanguino/pins_GEN7_12.h index 5030666245..10b9780ab3 100644 --- a/Marlin/src/pins/sanguino/pins_GEN7_12.h +++ b/Marlin/src/pins/sanguino/pins_GEN7_12.h @@ -38,7 +38,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_GEN7_13.h b/Marlin/src/pins/sanguino/pins_GEN7_13.h index 55881aaff5..a7c513cbcd 100644 --- a/Marlin/src/pins/sanguino/pins_GEN7_13.h +++ b/Marlin/src/pins/sanguino/pins_GEN7_13.h @@ -32,7 +32,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_GEN7_14.h b/Marlin/src/pins/sanguino/pins_GEN7_14.h index 10e5784966..b4e6a5eac9 100644 --- a/Marlin/src/pins/sanguino/pins_GEN7_14.h +++ b/Marlin/src/pins/sanguino/pins_GEN7_14.h @@ -36,7 +36,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_GEN7_CUSTOM.h b/Marlin/src/pins/sanguino/pins_GEN7_CUSTOM.h index 154e26725f..6b4f2b8231 100644 --- a/Marlin/src/pins/sanguino/pins_GEN7_CUSTOM.h +++ b/Marlin/src/pins/sanguino/pins_GEN7_CUSTOM.h @@ -37,7 +37,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_OMCA.h b/Marlin/src/pins/sanguino/pins_OMCA.h index 65f9006adb..223002a6cf 100644 --- a/Marlin/src/pins/sanguino/pins_OMCA.h +++ b/Marlin/src/pins/sanguino/pins_OMCA.h @@ -59,7 +59,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_OMCA_A.h b/Marlin/src/pins/sanguino/pins_OMCA_A.h index aa7f79d602..73a678bff6 100644 --- a/Marlin/src/pins/sanguino/pins_OMCA_A.h +++ b/Marlin/src/pins/sanguino/pins_OMCA_A.h @@ -57,7 +57,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h b/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h index 74d2b5549b..838208d8e5 100644 --- a/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h +++ b/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h @@ -39,7 +39,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sanguino/pins_SETHI.h b/Marlin/src/pins/sanguino/pins_SETHI.h index 31d5585cc8..9a21e2d236 100644 --- a/Marlin/src/pins/sanguino/pins_SETHI.h +++ b/Marlin/src/pins/sanguino/pins_SETHI.h @@ -33,7 +33,7 @@ */ /** - * A useable Arduino IDE extension (board manager) can be found at + * A useable Arduino IDE extension (Boards Manager) can be found at * https://github.com/Lauszus/Sanguino * * This extension has been tested on Arduino 1.6.12 & 1.8.0 diff --git a/Marlin/src/pins/sensitive_pins.h b/Marlin/src/pins/sensitive_pins.h index 7264a26539..0c6592ea93 100644 --- a/Marlin/src/pins/sensitive_pins.h +++ b/Marlin/src/pins/sensitive_pins.h @@ -21,1003 +21,588 @@ */ #pragma once -// -// Prepare a list of protected pins for M42/M43 -// -#if HAS_X_AXIS - - #if PIN_EXISTS(X_MIN) - #define _X_MIN X_MIN_PIN, - #else - #define _X_MIN - #endif - #if PIN_EXISTS(X_MAX) - #define _X_MAX X_MAX_PIN, - #else - #define _X_MAX - #endif - #if PIN_EXISTS(X_CS) && AXIS_HAS_SPI(X) - #define _X_CS X_CS_PIN, - #else - #define _X_CS - #endif - #if PIN_EXISTS(X_MS1) - #define _X_MS1 X_MS1_PIN, - #else - #define _X_MS1 - #endif - #if PIN_EXISTS(X_MS2) - #define _X_MS2 X_MS2_PIN, - #else - #define _X_MS2 - #endif - #if PIN_EXISTS(X_MS3) - #define _X_MS3 X_MS3_PIN, - #else - #define _X_MS3 - #endif - #if PIN_EXISTS(X_ENABLE) - #define _X_ENABLE_PIN X_ENABLE_PIN, - #else - #define _X_ENABLE_PIN - #endif - - #define _X_PINS X_STEP_PIN, X_DIR_PIN, _X_ENABLE_PIN _X_MIN _X_MAX _X_MS1 _X_MS2 _X_MS3 _X_CS - -#else - - #define _X_PINS - -#endif - -#if HAS_Y_AXIS - - #if PIN_EXISTS(Y_MIN) - #define _Y_MIN Y_MIN_PIN, - #else - #define _Y_MIN - #endif - #if PIN_EXISTS(Y_MAX) - #define _Y_MAX Y_MAX_PIN, - #else - #define _Y_MAX - #endif - #if PIN_EXISTS(Y_CS) && AXIS_HAS_SPI(Y) - #define _Y_CS Y_CS_PIN, - #else - #define _Y_CS - #endif - #if PIN_EXISTS(Y_MS1) - #define _Y_MS1 Y_MS1_PIN, - #else - #define _Y_MS1 - #endif - #if PIN_EXISTS(Y_MS2) - #define _Y_MS2 Y_MS2_PIN, - #else - #define _Y_MS2 - #endif - #if PIN_EXISTS(Y_MS3) - #define _Y_MS3 Y_MS3_PIN, - #else - #define _Y_MS3 - #endif - #if PIN_EXISTS(Y_ENABLE) - #define _Y_ENABLE_PIN Y_ENABLE_PIN, - #else - #define _Y_ENABLE_PIN - #endif - - #define _Y_PINS Y_STEP_PIN, Y_DIR_PIN, _Y_ENABLE_PIN _Y_MIN _Y_MAX _Y_MS1 _Y_MS2 _Y_MS3 _Y_CS - -#else - - #define _Y_PINS - -#endif - -#if HAS_Z_AXIS - - #if PIN_EXISTS(Z_MIN) - #define _Z_MIN Z_MIN_PIN, - #else - #define _Z_MIN - #endif - #if PIN_EXISTS(Z_MAX) - #define _Z_MAX Z_MAX_PIN, - #else - #define _Z_MAX - #endif - #if PIN_EXISTS(Z_CS) && AXIS_HAS_SPI(Z) - #define _Z_CS Z_CS_PIN, - #else - #define _Z_CS - #endif - #if PIN_EXISTS(Z_MS1) - #define _Z_MS1 Z_MS1_PIN, - #else - #define _Z_MS1 - #endif - #if PIN_EXISTS(Z_MS2) - #define _Z_MS2 Z_MS2_PIN, - #else - #define _Z_MS2 - #endif - #if PIN_EXISTS(Z_MS3) - #define _Z_MS3 Z_MS3_PIN, - #else - #define _Z_MS3 - #endif - #if PIN_EXISTS(Z_ENABLE) - #define _Z_ENABLE_PIN Z_ENABLE_PIN, - #else - #define _Z_ENABLE_PIN - #endif - - #define _Z_PINS Z_STEP_PIN, Z_DIR_PIN, _Z_ENABLE_PIN _Z_MIN _Z_MAX _Z_MS1 _Z_MS2 _Z_MS3 _Z_CS - -#else - - #define _Z_PINS - -#endif - -#if HAS_I_AXIS - - #if PIN_EXISTS(I_MIN) - #define _I_MIN I_MIN_PIN, - #else - #define _I_MIN - #endif - #if PIN_EXISTS(I_MAX) - #define _I_MAX I_MAX_PIN, - #else - #define _I_MAX - #endif - #if PIN_EXISTS(I_CS) && AXIS_HAS_SPI(I) - #define _I_CS I_CS_PIN, - #else - #define _I_CS - #endif - #if PIN_EXISTS(I_MS1) - #define _I_MS1 I_MS1_PIN, - #else - #define _I_MS1 - #endif - #if PIN_EXISTS(I_MS2) - #define _I_MS2 I_MS2_PIN, - #else - #define _I_MS2 - #endif - #if PIN_EXISTS(I_MS3) - #define _I_MS3 I_MS3_PIN, - #else - #define _I_MS3 - #endif - #if PIN_EXISTS(I_ENABLE) - #define _I_ENABLE_PIN I_ENABLE_PIN, - #else - #define _I_ENABLE_PIN - #endif - - #define _I_PINS I_STEP_PIN, I_DIR_PIN, _I_ENABLE_PIN _I_MIN _I_MAX _I_MS1 _I_MS2 _I_MS3 _I_CS - -#else - - #define _I_PINS - -#endif - -#if HAS_J_AXIS - - #if PIN_EXISTS(J_MIN) - #define _J_MIN J_MIN_PIN, - #else - #define _J_MIN - #endif - #if PIN_EXISTS(J_MAX) - #define _J_MAX J_MAX_PIN, - #else - #define _J_MAX - #endif - #if PIN_EXISTS(J_CS) && AXIS_HAS_SPI(J) - #define _J_CS J_CS_PIN, - #else - #define _J_CS - #endif - #if PIN_EXISTS(J_MS1) - #define _J_MS1 J_MS1_PIN, - #else - #define _J_MS1 - #endif - #if PIN_EXISTS(J_MS2) - #define _J_MS2 J_MS2_PIN, - #else - #define _J_MS2 - #endif - #if PIN_EXISTS(J_MS3) - #define _J_MS3 J_MS3_PIN, - #else - #define _J_MS3 - #endif - #if PIN_EXISTS(J_ENABLE) - #define _J_ENABLE_PIN J_ENABLE_PIN, - #else - #define _J_ENABLE_PIN - #endif - - #define _J_PINS J_STEP_PIN, J_DIR_PIN, _J_ENABLE_PIN _J_MIN _J_MAX _J_MS1 _J_MS2 _J_MS3 _J_CS - -#else - - #define _J_PINS - -#endif - -#if HAS_K_AXIS - - #if PIN_EXISTS(K_MIN) - #define _K_MIN K_MIN_PIN, - #else - #define _K_MIN - #endif - #if PIN_EXISTS(K_MAX) - #define _K_MAX K_MAX_PIN, - #else - #define _K_MAX - #endif - #if PIN_EXISTS(K_CS) && AXIS_HAS_SPI(K) - #define _K_CS K_CS_PIN, - #else - #define _K_CS - #endif - #if PIN_EXISTS(K_MS1) - #define _K_MS1 K_MS1_PIN, - #else - #define _K_MS1 - #endif - #if PIN_EXISTS(K_MS2) - #define _K_MS2 K_MS2_PIN, - #else - #define _K_MS2 - #endif - #if PIN_EXISTS(K_MS3) - #define _K_MS3 K_MS3_PIN, - #else - #define _K_MS3 - #endif - #if PIN_EXISTS(K_ENABLE) - #define _K_ENABLE_PIN K_ENABLE_PIN, - #else - #define _K_ENABLE_PIN - #endif - - #define _K_PINS K_STEP_PIN, K_DIR_PIN, _K_ENABLE_PIN _K_MIN _K_MAX _K_MS1 _K_MS2 _K_MS3 _K_CS - -#else - - #define _K_PINS - -#endif - -#if HAS_U_AXIS - #if PIN_EXISTS(U_MIN) - #define _U_MIN U_MIN_PIN, - #else - #define _U_MIN - #endif - #if PIN_EXISTS(U_MAX) - #define _U_MAX U_MAX_PIN, - #else - #define _U_MAX - #endif - #if PIN_EXISTS(U_CS) && AXIS_HAS_SPI(U) - #define _U_CS U_CS_PIN, - #else - #define _U_CS - #endif - #if PIN_EXISTS(U_MS1) - #define _U_MS1 U_MS1_PIN, - #else - #define _U_MS1 - #endif - #if PIN_EXISTS(U_MS2) - #define _U_MS2 U_MS2_PIN, - #else - #define _U_MS2 - #endif - #if PIN_EXISTS(U_MS3) - #define _U_MS3 U_MS3_PIN, - #else - #define _U_MS3 - #endif - - #define _U_PINS U_STEP_PIN, U_DIR_PIN, U_ENABLE_PIN, _U_MIN _U_MAX _U_MS1 _U_MS2 _U_MS3 _U_CS - -#else - - #define _U_PINS - -#endif - -#if HAS_V_AXIS - #if PIN_EXISTS(V_MIN) - #define _V_MIN V_MIN_PIN, - #else - #define _V_MIN - #endif - #if PIN_EXISTS(V_MAX) - #define _V_MAX V_MAX_PIN, - #else - #define _V_MAX - #endif - #if PIN_EXISTS(V_CS) && AXIS_HAS_SPI(V) - #define _V_CS V_CS_PIN, - #else - #define _V_CS - #endif - #if PIN_EXISTS(V_MS1) - #define _V_MS1 V_MS1_PIN, - #else - #define _V_MS1 - #endif - #if PIN_EXISTS(V_MS2) - #define _V_MS2 V_MS2_PIN, - #else - #define _V_MS2 - #endif - #if PIN_EXISTS(V_MS3) - #define _V_MS3 V_MS3_PIN, - #else - #define _V_MS3 - #endif - - #define _V_PINS V_STEP_PIN, V_DIR_PIN, V_ENABLE_PIN, _V_MIN _V_MAX _V_MS1 _V_MS2 _V_MS3 _V_CS - -#else - - #define _V_PINS - -#endif - -#if HAS_W_AXIS - #if PIN_EXISTS(W_MIN) - #define _W_MIN W_MIN_PIN, - #else - #define _W_MIN - #endif - #if PIN_EXISTS(W_MAX) - #define _W_MAX W_MAX_PIN, - #else - #define _W_MAX - #endif - #if PIN_EXISTS(W_CS) && AXIS_HAS_SPI(W) - #define _W_CS W_CS_PIN, - #else - #define _W_CS - #endif - #if PIN_EXISTS(W_MS1) - #define _W_MS1 W_MS1_PIN, - #else - #define _W_MS1 - #endif - #if PIN_EXISTS(W_MS2) - #define _W_MS2 W_MS2_PIN, - #else - #define _W_MS2 - #endif - #if PIN_EXISTS(W_MS3) - #define _W_MS3 W_MS3_PIN, - #else - #define _W_MS3 - #endif - - #define _W_PINS W_STEP_PIN, W_DIR_PIN, W_ENABLE_PIN, _W_MIN _W_MAX _W_MS1 _W_MS2 _W_MS3 _W_CS - -#else - - #define _W_PINS - -#endif +#include // -// Extruder Chip Select, Digital Micro-steps +// Define unsorted and arrays of pins which may have duplicstes, +// but don't allocate any runtime memory for these arrays. +// We'll use constexpr functions to get the Nth distinct value, +// and return -1 if we go past the end of the array. // +constexpr pin_t sensitive_dio[] PROGMEM = { -// Mixing stepper, Switching stepper, or regular stepper -#define E_NEEDED(N) (ENABLED(MIXING_EXTRUDER) && MIXING_STEPPERS > N) \ - || (HAS_SWITCHING_EXTRUDER && E_STEPPERS > N) \ - || (NONE(SWITCHING_EXTRUDER, MIXING_EXTRUDER) && EXTRUDERS > N) - -#define _E0_CS -#define _E0_MS1 -#define _E0_MS2 -#define _E0_MS3 - -#if E_NEEDED(0) - #if PIN_EXISTS(E0_CS) && AXIS_HAS_SPI(E0) - #undef _E0_CS - #define _E0_CS E0_CS_PIN, - #endif - #if PIN_EXISTS(E0_MS1) - #undef _E0_MS1 - #define _E0_MS1 E0_MS1_PIN, - #endif - #if PIN_EXISTS(E0_MS2) - #undef _E0_MS2 - #define _E0_MS2 E0_MS2_PIN, - #endif - #if PIN_EXISTS(E0_MS3) - #undef _E0_MS3 - #define _E0_MS3 E0_MS3_PIN, - #endif -#endif - -#define _E1_CS -#define _E1_MS1 -#define _E1_MS2 -#define _E1_MS3 - -#if E_NEEDED(1) - #if PIN_EXISTS(E1_CS) && AXIS_HAS_SPI(E1) - #undef _E1_CS - #define _E1_CS E1_CS_PIN, - #endif - #if PIN_EXISTS(E1_MS1) - #undef _E1_MS1 - #define _E1_MS1 E1_MS1_PIN, - #endif - #if PIN_EXISTS(E1_MS2) - #undef _E1_MS2 - #define _E1_MS2 E1_MS2_PIN, - #endif - #if PIN_EXISTS(E1_MS3) - #undef _E1_MS3 - #define _E1_MS3 E1_MS3_PIN, - #endif -#endif - -#define _E2_CS -#define _E2_MS1 -#define _E2_MS2 -#define _E2_MS3 - -#if E_NEEDED(2) - #if PIN_EXISTS(E2_CS) && AXIS_HAS_SPI(E2) - #undef _E2_CS - #define _E2_CS E2_CS_PIN, - #endif - #if PIN_EXISTS(E2_MS1) - #undef _E2_MS1 - #define _E2_MS1 E2_MS1_PIN, - #endif - #if PIN_EXISTS(E2_MS2) - #undef _E2_MS2 - #define _E2_MS2 E2_MS2_PIN, - #endif - #if PIN_EXISTS(E2_MS3) - #undef _E2_MS3 - #define _E2_MS3 E2_MS3_PIN, - #endif -#endif - -#define _E3_CS -#define _E3_MS1 -#define _E3_MS2 -#define _E3_MS3 - -#if E_NEEDED(3) - #if PIN_EXISTS(E3_CS) && AXIS_HAS_SPI(E3) - #undef _E3_CS - #define _E3_CS E3_CS_PIN, - #endif - #if PIN_EXISTS(E3_MS1) - #undef _E3_MS1 - #define _E3_MS1 E3_MS1_PIN, - #endif - #if PIN_EXISTS(E3_MS2) - #undef _E3_MS2 - #define _E3_MS2 E3_MS2_PIN, - #endif - #if PIN_EXISTS(E3_MS3) - #undef _E3_MS3 - #define _E3_MS3 E3_MS3_PIN, - #endif -#endif - -#define _E4_CS -#define _E4_MS1 -#define _E4_MS2 -#define _E4_MS3 - -#if E_NEEDED(4) - #if PIN_EXISTS(E4_CS) && AXIS_HAS_SPI(E4) - #undef _E4_CS - #define _E4_CS E4_CS_PIN, - #endif - #if PIN_EXISTS(E4_MS1) - #undef _E4_MS1 - #define _E4_MS1 E4_MS1_PIN, - #endif - #if PIN_EXISTS(E4_MS2) - #undef _E4_MS2 - #define _E4_MS2 E4_MS2_PIN, - #endif - #if PIN_EXISTS(E4_MS3) - #undef _E4_MS3 - #define _E4_MS3 E4_MS3_PIN, - #endif -#endif - -#define _E5_CS -#define _E5_MS1 -#define _E5_MS2 -#define _E5_MS3 - -#if E_NEEDED(5) - #if PIN_EXISTS(E5_CS) && AXIS_HAS_SPI(E5) - #undef _E5_CS - #define _E5_CS E5_CS_PIN, - #endif - #if PIN_EXISTS(E5_MS1) - #undef _E5_MS1 - #define _E5_MS1 E5_MS1_PIN, - #endif - #if PIN_EXISTS(E5_MS2) - #undef _E5_MS2 - #define _E5_MS2 E5_MS2_PIN, - #endif - #if PIN_EXISTS(E5_MS3) - #undef _E5_MS3 - #define _E5_MS3 E5_MS3_PIN, - #endif -#endif - -#define _E6_CS -#define _E6_MS1 -#define _E6_MS2 -#define _E6_MS3 - -#if E_NEEDED(6) - #if PIN_EXISTS(E6_CS) && AXIS_HAS_SPI(E6) - #undef _E6_CS - #define _E6_CS E6_CS_PIN, - #endif - #if PIN_EXISTS(E6_MS2) - #undef _E6_MS2 - #define _E6_MS2 E6_MS2_PIN, - #endif - #if PIN_EXISTS(E6_MS3) - #undef _E6_MS3 - #define _E6_MS3 E6_MS3_PIN, - #endif - #if PIN_EXISTS(E6_MS4) - #undef _E6_MS4 - #define _E6_MS4 E6_MS4_PIN, - #endif -#endif - -#define _E7_CS -#define _E7_MS1 -#define _E7_MS2 -#define _E7_MS3 - -#if E_NEEDED(7) - #if PIN_EXISTS(E7_CS) && AXIS_HAS_SPI(E7) - #undef _E7_CS - #define _E7_CS E7_CS_PIN, - #endif - #if PIN_EXISTS(E7_MS3) - #undef _E7_MS3 - #define _E7_MS3 E7_MS3_PIN, - #endif - #if PIN_EXISTS(E7_MS4) - #undef _E7_MS4 - #define _E7_MS4 E7_MS4_PIN, - #endif - #if PIN_EXISTS(E7_MS5) - #undef _E7_MS5 - #define _E7_MS5 E7_MS5_PIN, - #endif -#endif - -// -// E Steppers -// - -#define _E0_PINS -#define _E1_PINS -#define _E2_PINS -#define _E3_PINS -#define _E4_PINS -#define _E5_PINS -#define _E6_PINS -#define _E7_PINS - -#if HAS_EXTRUDERS - #undef _E0_PINS - #define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, _E0_CS _E0_MS1 _E0_MS2 _E0_MS3 -#endif - -#if HAS_SWITCHING_EXTRUDER - // Tools 0 and 1 use E0 - #if EXTRUDERS > 2 // Tools 2 and 3 use E1 - #undef _E1_PINS - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, _E1_CS _E1_MS1 _E1_MS2 _E1_MS3 - #if EXTRUDERS > 4 // Tools 4 and 5 use E2 - #undef _E2_PINS - #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, _E2_CS _E2_MS1 _E2_MS2 _E2_MS3 + #if HAS_X_AXIS + #if PIN_EXISTS(X_MIN) + X_MIN_PIN, + #endif + #if PIN_EXISTS(X_MAX) + X_MAX_PIN, + #endif + #if PIN_EXISTS(X_CS) && AXIS_HAS_SPI(X) + X_CS_PIN, + #endif + #if PIN_EXISTS(X_MS1) + X_MS1_PIN, + #endif + #if PIN_EXISTS(X_MS2) + X_MS2_PIN, + #endif + #if PIN_EXISTS(X_MS3) + X_MS3_PIN, + #endif + #if PIN_EXISTS(X_ENABLE) + X_ENABLE_PIN, #endif #endif -#elif ANY(HAS_MULTI_EXTRUDER, MIXING_EXTRUDER) + #if HAS_Y_AXIS + #if PIN_EXISTS(Y_MIN) + Y_MIN_PIN, + #endif + #if PIN_EXISTS(Y_MAX) + Y_MAX_PIN, + #endif + #if PIN_EXISTS(Y_CS) && AXIS_HAS_SPI(Y) + Y_CS_PIN, + #endif + #if PIN_EXISTS(Y_MS1) + Y_MS1_PIN, + #endif + #if PIN_EXISTS(Y_MS2) + Y_MS2_PIN, + #endif + #if PIN_EXISTS(Y_MS3) + Y_MS3_PIN, + #endif + #if PIN_EXISTS(Y_ENABLE) + Y_ENABLE_PIN, + #endif + #endif - #undef _E1_PINS - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, _E1_CS _E1_MS1 _E1_MS2 _E1_MS3 - #if EXTRUDERS > 2 || (ENABLED(MIXING_EXTRUDER) && MIXING_STEPPERS > 2) - #undef _E2_PINS - #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, _E2_CS _E2_MS1 _E2_MS2 _E2_MS3 - #if EXTRUDERS > 3 || (ENABLED(MIXING_EXTRUDER) && MIXING_STEPPERS > 3) - #undef _E3_PINS - #define _E3_PINS E3_STEP_PIN, E3_DIR_PIN, E3_ENABLE_PIN, _E3_CS _E3_MS1 _E3_MS2 _E3_MS3 - #if EXTRUDERS > 4 || (ENABLED(MIXING_EXTRUDER) && MIXING_STEPPERS > 4) - #undef _E4_PINS - #define _E4_PINS E4_STEP_PIN, E4_DIR_PIN, E4_ENABLE_PIN, _E4_CS _E4_MS1 _E4_MS2 _E4_MS3 - #if EXTRUDERS > 5 || (ENABLED(MIXING_EXTRUDER) && MIXING_STEPPERS > 5) - #undef _E5_PINS - #define _E5_PINS E5_STEP_PIN, E5_DIR_PIN, E5_ENABLE_PIN, _E5_CS _E5_MS1 _E5_MS2 _E5_MS3 - #if EXTRUDERS > 6 || (ENABLED(MIXING_EXTRUDER) && MIXING_STEPPERS > 6) - #undef _E6_PINS - #define _E6_PINS E6_STEP_PIN, E6_DIR_PIN, E6_ENABLE_PIN, _E6_CS _E6_MS1 _E6_MS2 _E6_MS3 - #if EXTRUDERS > 7 || (ENABLED(MIXING_EXTRUDER) && MIXING_STEPPERS > 7) - #undef _E7_PINS - #define _E7_PINS E7_STEP_PIN, E7_DIR_PIN, E7_ENABLE_PIN, _E7_CS _E7_MS1 _E7_MS2 _E7_MS3 - #endif // EXTRUDERS > 7 || MIXING_EXTRUDER > 7 - #endif // EXTRUDERS > 6 || MIXING_EXTRUDER > 6 - #endif // EXTRUDERS > 5 || MIXING_EXTRUDER > 5 - #endif // EXTRUDERS > 4 || MIXING_EXTRUDER > 4 - #endif // EXTRUDERS > 3 || MIXING_EXTRUDER > 3 - #endif // EXTRUDERS > 2 || MIXING_EXTRUDER > 2 + #if HAS_Z_AXIS + #if PIN_EXISTS(Z_MIN) + Z_MIN_PIN, + #endif + #if PIN_EXISTS(Z_MAX) + Z_MAX_PIN, + #endif + #if PIN_EXISTS(Z_CS) && AXIS_HAS_SPI(Z) + Z_CS_PIN, + #endif + #if PIN_EXISTS(Z_MS1) + Z_MS1_PIN, + #endif + #if PIN_EXISTS(Z_MS2) + Z_MS2_PIN, + #endif + #if PIN_EXISTS(Z_MS3) + Z_MS3_PIN, + #endif + #if PIN_EXISTS(Z_ENABLE) + Z_ENABLE_PIN, + #endif + #endif -#endif // HAS_MULTI_EXTRUDER || MIXING_EXTRUDER + #if HAS_I_AXIS + #if PIN_EXISTS(I_MIN) + I_MIN_PIN, + #endif + #if PIN_EXISTS(I_MAX) + I_MAX_PIN, + #endif + #if PIN_EXISTS(I_CS) && AXIS_HAS_SPI(I) + I_CS_PIN, + #endif + #if PIN_EXISTS(I_MS1) + I_MS1_PIN, + #endif + #if PIN_EXISTS(I_MS2) + I_MS2_PIN, + #endif + #if PIN_EXISTS(I_MS3) + I_MS3_PIN, + #endif + #if PIN_EXISTS(I_ENABLE) + I_ENABLE_PIN, + #endif + #endif -// -// Heaters, Fans, Temp Sensors -// + #if HAS_J_AXIS + #if PIN_EXISTS(J_MIN) + J_MIN_PIN, + #endif + #if PIN_EXISTS(J_MAX) + J_MAX_PIN, + #endif + #if PIN_EXISTS(J_CS) && AXIS_HAS_SPI(J) + J_CS_PIN, + #endif + #if PIN_EXISTS(J_MS1) + J_MS1_PIN, + #endif + #if PIN_EXISTS(J_MS2) + J_MS2_PIN, + #endif + #if PIN_EXISTS(J_MS3) + J_MS3_PIN, + #endif + #if PIN_EXISTS(J_ENABLE) + J_ENABLE_PIN, + #endif + #endif -#ifndef E0_AUTO_FAN_PIN - #define E0_AUTO_FAN_PIN -1 -#endif -#ifndef E1_AUTO_FAN_PIN - #define E1_AUTO_FAN_PIN -1 -#endif -#ifndef E2_AUTO_FAN_PIN - #define E2_AUTO_FAN_PIN -1 -#endif -#ifndef E3_AUTO_FAN_PIN - #define E3_AUTO_FAN_PIN -1 -#endif -#ifndef E4_AUTO_FAN_PIN - #define E4_AUTO_FAN_PIN -1 -#endif -#ifndef E5_AUTO_FAN_PIN - #define E5_AUTO_FAN_PIN -1 -#endif -#ifndef E6_AUTO_FAN_PIN - #define E6_AUTO_FAN_PIN -1 -#endif -#ifndef E7_AUTO_FAN_PIN - #define E7_AUTO_FAN_PIN -1 -#endif + #if HAS_K_AXIS + #if PIN_EXISTS(K_MIN) + K_MIN_PIN, + #endif + #if PIN_EXISTS(K_MAX) + K_MAX_PIN, + #endif + #if PIN_EXISTS(K_CS) && AXIS_HAS_SPI(K) + K_CS_PIN, + #endif + #if PIN_EXISTS(K_MS1) + K_MS1_PIN, + #endif + #if PIN_EXISTS(K_MS2) + K_MS2_PIN, + #endif + #if PIN_EXISTS(K_MS3) + K_MS3_PIN, + #endif + #if PIN_EXISTS(K_ENABLE) + K_ENABLE_PIN, + #endif + #endif -#define _H0_PINS -#define _H1_PINS -#define _H2_PINS -#define _H3_PINS -#define _H4_PINS -#define _H5_PINS -#define _H6_PINS -#define _H7_PINS + #if HAS_U_AXIS + #if PIN_EXISTS(U_MIN) + U_MIN_PIN, + #endif + #if PIN_EXISTS(U_MAX) + U_MAX_PIN, + #endif + #if PIN_EXISTS(U_CS) && AXIS_HAS_SPI(U) + U_CS_PIN, + #endif + #if PIN_EXISTS(U_MS1) + U_MS1_PIN, + #endif + #if PIN_EXISTS(U_MS2) + U_MS2_PIN, + #endif + #if PIN_EXISTS(U_MS3) + U_MS3_PIN, + #endif + #endif -#define DIO_PIN(P) TERN(TARGET_LPC1768, P, analogInputToDigitalPin(P)) + #if HAS_V_AXIS + #if PIN_EXISTS(V_MIN) + V_MIN_PIN, + #endif + #if PIN_EXISTS(V_MAX) + V_MAX_PIN, + #endif + #if PIN_EXISTS(V_CS) && AXIS_HAS_SPI(V) + V_CS_PIN, + #endif + #if PIN_EXISTS(V_MS1) + V_MS1_PIN, + #endif + #if PIN_EXISTS(V_MS2) + V_MS2_PIN, + #endif + #if PIN_EXISTS(V_MS3) + V_MS3_PIN, + #endif + #endif -#if HAS_HOTEND - #undef _H0_PINS - #define _H0_PINS HEATER_0_PIN, E0_AUTO_FAN_PIN, DIO_PIN(TEMP_0_PIN), + #if HAS_W_AXIS + #if PIN_EXISTS(W_MIN) + W_MIN_PIN, + #endif + #if PIN_EXISTS(W_MAX) + W_MAX_PIN, + #endif + #if PIN_EXISTS(W_CS) && AXIS_HAS_SPI(W) + W_CS_PIN, + #endif + #if PIN_EXISTS(W_MS1) + W_MS1_PIN, + #endif + #if PIN_EXISTS(W_MS2) + W_MS2_PIN, + #endif + #if PIN_EXISTS(W_MS3) + W_MS3_PIN, + #endif + #endif + + // + // Extruder Chip Select, Digital Micro-steps + // + + // Mixing stepper, Switching stepper, or regular stepper + #define E_NEEDED(N) (ENABLED(MIXING_EXTRUDER) && MIXING_STEPPERS > N) \ + || (HAS_SWITCHING_EXTRUDER && E_STEPPERS > N) \ + || (NONE(SWITCHING_EXTRUDER, MIXING_EXTRUDER) && EXTRUDERS > N) + + #if E_NEEDED(0) + E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, + #if PIN_EXISTS(E0_CS) && AXIS_HAS_SPI(E0) + E0_CS_PIN, + #endif + #if PIN_EXISTS(E0_MS1) + E0_MS1_PIN, + #endif + #if PIN_EXISTS(E0_MS2) + E0_MS2_PIN, + #endif + #if PIN_EXISTS(E0_MS3) + E0_MS3_PIN, + #endif + #endif + + #if E_NEEDED(1) + E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, + #if PIN_EXISTS(E1_CS) && AXIS_HAS_SPI(E1) + E1_CS_PIN, + #endif + #if PIN_EXISTS(E1_MS1) + E1_MS1_PIN, + #endif + #if PIN_EXISTS(E1_MS2) + E1_MS2_PIN, + #endif + #if PIN_EXISTS(E1_MS3) + E1_MS3_PIN, + #endif + #endif + + #if E_NEEDED(2) + E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, + #if PIN_EXISTS(E2_CS) && AXIS_HAS_SPI(E2) + E2_CS_PIN, + #endif + #if PIN_EXISTS(E2_MS1) + E2_MS1_PIN, + #endif + #if PIN_EXISTS(E2_MS2) + E2_MS2_PIN, + #endif + #if PIN_EXISTS(E2_MS3) + E2_MS3_PIN, + #endif + #endif + + #if E_NEEDED(3) + E3_STEP_PIN, E3_DIR_PIN, E3_ENABLE_PIN, + #if PIN_EXISTS(E3_CS) && AXIS_HAS_SPI(E3) + E3_CS_PIN, + #endif + #if PIN_EXISTS(E3_MS1) + E3_MS1_PIN, + #endif + #if PIN_EXISTS(E3_MS2) + E3_MS2_PIN, + #endif + #if PIN_EXISTS(E3_MS3) + E3_MS3_PIN, + #endif + #endif + + #if E_NEEDED(4) + E4_STEP_PIN, E4_DIR_PIN, E4_ENABLE_PIN, + #if PIN_EXISTS(E4_CS) && AXIS_HAS_SPI(E4) + E4_CS_PIN, + #endif + #if PIN_EXISTS(E4_MS1) + E4_MS1_PIN, + #endif + #if PIN_EXISTS(E4_MS2) + E4_MS2_PIN, + #endif + #if PIN_EXISTS(E4_MS3) + E4_MS3_PIN, + #endif + #endif + + #if E_NEEDED(5) + E5_STEP_PIN, E5_DIR_PIN, E5_ENABLE_PIN, + #if PIN_EXISTS(E5_CS) && AXIS_HAS_SPI(E5) + E5_CS_PIN, + #endif + #if PIN_EXISTS(E5_MS1) + E5_MS1_PIN, + #endif + #if PIN_EXISTS(E5_MS2) + E5_MS2_PIN, + #endif + #if PIN_EXISTS(E5_MS3) + E5_MS3_PIN, + #endif + #endif + + #if E_NEEDED(6) + E6_STEP_PIN, E6_DIR_PIN, E6_ENABLE_PIN, + #if PIN_EXISTS(E6_CS) && AXIS_HAS_SPI(E6) + E6_CS_PIN, + #endif + #if PIN_EXISTS(E6_MS2) + E6_MS2_PIN, + #endif + #if PIN_EXISTS(E6_MS3) + E6_MS3_PIN, + #endif + #if PIN_EXISTS(E6_MS4) + E6_MS4_PIN, + #endif + #endif + + #if E_NEEDED(7) + E7_STEP_PIN, E7_DIR_PIN, E7_ENABLE_PIN, + #if PIN_EXISTS(E7_CS) && AXIS_HAS_SPI(E7) + E7_CS_PIN, + #endif + #if PIN_EXISTS(E7_MS3) + E7_MS3_PIN, + #endif + #if PIN_EXISTS(E7_MS4) + E7_MS4_PIN, + #endif + #if PIN_EXISTS(E7_MS5) + E7_MS5_PIN, + #endif + #endif + + // + // Hotend Heaters and Fans + // + + #if HAS_HOTEND + HEATER_0_PIN, + #if PIN_EXISTS(E0_AUTO_FAN) + E0_AUTO_FAN_PIN, + #endif + #endif #if HAS_MULTI_HOTEND - #undef _H1_PINS - #define _H1_PINS HEATER_1_PIN, E1_AUTO_FAN_PIN, DIO_PIN(TEMP_1_PIN), - #if HOTENDS > 2 - #undef _H2_PINS - #define _H2_PINS HEATER_2_PIN, E2_AUTO_FAN_PIN, DIO_PIN(TEMP_2_PIN), - #if HOTENDS > 3 - #undef _H3_PINS - #define _H3_PINS HEATER_3_PIN, E3_AUTO_FAN_PIN, DIO_PIN(TEMP_3_PIN), - #if HOTENDS > 4 - #undef _H4_PINS - #define _H4_PINS HEATER_4_PIN, E4_AUTO_FAN_PIN, DIO_PIN(TEMP_4_PIN), - #if HOTENDS > 5 - #undef _H5_PINS - #define _H5_PINS HEATER_5_PIN, E5_AUTO_FAN_PIN, DIO_PIN(TEMP_5_PIN), - #if HOTENDS > 6 - #undef _H6_PINS - #define _H6_PINS HEATER_6_PIN, E6_AUTO_FAN_PIN, DIO_PIN(TEMP_6_PIN), - #if HOTENDS > 7 - #undef _H7_PINS - #define _H7_PINS HEATER_7_PIN, E7_AUTO_FAN_PIN, DIO_PIN(TEMP_7_PIN), - #endif // HOTENDS > 7 - #endif // HOTENDS > 6 - #endif // HOTENDS > 5 - #endif // HOTENDS > 4 - #endif // HOTENDS > 3 - #endif // HOTENDS > 2 - #endif // HAS_MULTI_HOTEND -#endif // HOTENDS + HEATER_1_PIN, + #if PIN_EXISTS(E1_AUTO_FAN) + E1_AUTO_FAN_PIN, + #endif + #endif + #if HOTENDS > 2 + HEATER_2_PIN, + #if PIN_EXISTS(E2_AUTO_FAN) + E2_AUTO_FAN_PIN, + #endif + #endif + #if HOTENDS > 3 + HEATER_3_PIN, + #if PIN_EXISTS(E3_AUTO_FAN) + E3_AUTO_FAN_PIN, + #endif + #endif + #if HOTENDS > 4 + HEATER_4_PIN, + #if PIN_EXISTS(E4_AUTO_FAN) + E4_AUTO_FAN_PIN, + #endif + #endif + #if HOTENDS > 5 + HEATER_5_PIN, + #if PIN_EXISTS(E5_AUTO_FAN) + E5_AUTO_FAN_PIN, + #endif + #endif + #if HOTENDS > 6 + HEATER_6_PIN, + #if PIN_EXISTS(E6_AUTO_FAN) + E6_AUTO_FAN_PIN, + #endif + #endif + #if HOTENDS > 7 + HEATER_7_PIN, + #if PIN_EXISTS(E7_AUTO_FAN) + E7_AUTO_FAN_PIN, + #endif + #endif -// -// Dual X, Dual Y, Multi-Z -// Chip Select and Digital Micro-stepping -// + // + // Dual X, Dual Y, Multi-Z + // Chip Select and Digital Micro-stepping + // -#if HAS_X2_STEPPER - #if PIN_EXISTS(X2_CS) && AXIS_HAS_SPI(X2) - #define _X2_CS X2_CS_PIN, - #else - #define _X2_CS + #if HAS_X2_STEPPER + #if PIN_EXISTS(X2_CS) && AXIS_HAS_SPI(X2) + X2_CS_PIN, + #endif + #if PIN_EXISTS(X2_MS1) + X2_MS1_PIN, + #endif + #if PIN_EXISTS(X2_MS2) + X2_MS2_PIN, + #endif + #if PIN_EXISTS(X2_MS3) + X2_MS3_PIN, + #endif #endif - #if PIN_EXISTS(X2_MS1) - #define _X2_MS1 X2_MS1_PIN, - #else - #define _X2_MS1 - #endif - #if PIN_EXISTS(X2_MS2) - #define _X2_MS2 X2_MS2_PIN, - #else - #define _X2_MS2 - #endif - #if PIN_EXISTS(X2_MS3) - #define _X2_MS3 X2_MS3_PIN, - #else - #define _X2_MS3 - #endif - #define _X2_PINS X2_STEP_PIN, X2_DIR_PIN, X2_ENABLE_PIN, _X2_CS _X2_MS1 _X2_MS2 _X2_MS3 -#else - #define _X2_PINS -#endif -#if HAS_Y2_STEPPER - #if PIN_EXISTS(Y2_CS) && AXIS_HAS_SPI(Y2) - #define _Y2_CS Y2_CS_PIN, - #else - #define _Y2_CS + #if HAS_Y2_STEPPER + #if PIN_EXISTS(Y2_CS) && AXIS_HAS_SPI(Y2) + Y2_CS_PIN, + #endif + #if PIN_EXISTS(Y2_MS1) + Y2_MS1_PIN, + #endif + #if PIN_EXISTS(Y2_MS2) + Y2_MS2_PIN, + #endif + #if PIN_EXISTS(Y2_MS3) + Y2_MS3_PIN, + #endif #endif - #if PIN_EXISTS(Y2_MS1) - #define _Y2_MS1 Y2_MS1_PIN, - #else - #define _Y2_MS1 + + #if NUM_Z_STEPPERS >= 2 + #if PIN_EXISTS(Z2_CS) && AXIS_HAS_SPI(Z2) + Z2_CS_PIN, + #endif + #if PIN_EXISTS(Z2_MS1) + Z2_MS1_PIN, + #endif + #if PIN_EXISTS(Z2_MS2) + Z2_MS2_PIN, + #endif + #if PIN_EXISTS(Z2_MS3) + Z2_MS3_PIN, + #endif #endif - #if PIN_EXISTS(Y2_MS2) - #define _Y2_MS2 Y2_MS2_PIN, - #else - #define _Y2_MS2 + + #if NUM_Z_STEPPERS >= 3 + #if PIN_EXISTS(Z3_CS) && AXIS_HAS_SPI(Z3) + Z3_CS_PIN, + #endif + #if PIN_EXISTS(Z3_MS1) + Z3_MS1_PIN, + #endif + #if PIN_EXISTS(Z3_MS2) + Z3_MS2_PIN, + #endif + #if PIN_EXISTS(Z3_MS3) + Z3_MS3_PIN, + #endif #endif - #if PIN_EXISTS(Y2_MS3) - #define _Y2_MS3 Y2_MS3_PIN, - #else - #define _Y2_MS3 + + #if NUM_Z_STEPPERS >= 4 + #if PIN_EXISTS(Z4_CS) && AXIS_HAS_SPI(Z4) + Z4_CS_PIN, + #endif + #if PIN_EXISTS(Z4_MS1) + Z4_MS1_PIN, + #endif + #if PIN_EXISTS(Z4_MS2) + Z4_MS2_PIN, + #endif + #if PIN_EXISTS(Z4_MS3) + Z4_MS3_PIN, + #endif #endif - #define _Y2_PINS Y2_STEP_PIN, Y2_DIR_PIN, Y2_ENABLE_PIN, _Y2_CS _Y2_MS1 _Y2_MS2 _Y2_MS3 -#else - #define _Y2_PINS -#endif -#if NUM_Z_STEPPERS >= 2 - #if PIN_EXISTS(Z2_CS) && AXIS_HAS_SPI(Z2) - #define _Z2_CS Z2_CS_PIN, - #else - #define _Z2_CS + #if PIN_EXISTS(PS_ON) + PS_ON_PIN, #endif - #if PIN_EXISTS(Z2_MS1) - #define _Z2_MS1 Z2_MS1_PIN, - #else - #define _Z2_MS1 + + #if HAS_BED_PROBE && PIN_EXISTS(Z_MIN_PROBE) + Z_MIN_PROBE_PIN, #endif - #if PIN_EXISTS(Z2_MS2) - #define _Z2_MS2 Z2_MS2_PIN, - #else - #define _Z2_MS2 + + #if PIN_EXISTS(FAN0) + FAN0_PIN, #endif - #if PIN_EXISTS(Z2_MS3) - #define _Z2_MS3 Z2_MS3_PIN, - #else - #define _Z2_MS3 + #if PIN_EXISTS(FAN1) + FAN1_PIN, #endif - #define _Z2_PINS Z2_STEP_PIN, Z2_DIR_PIN, Z2_ENABLE_PIN, _Z2_CS _Z2_MS1 _Z2_MS2 _Z2_MS3 -#else - #define _Z2_PINS -#endif - -#if NUM_Z_STEPPERS >= 3 - #if PIN_EXISTS(Z3_CS) && AXIS_HAS_SPI(Z3) - #define _Z3_CS Z3_CS_PIN, - #else - #define _Z3_CS + #if PIN_EXISTS(FAN2) + FAN2_PIN, #endif - #if PIN_EXISTS(Z3_MS1) - #define _Z3_MS1 Z3_MS1_PIN, - #else - #define _Z3_MS1 + #if PIN_EXISTS(FAN3) + FAN3_PIN, #endif - #if PIN_EXISTS(Z3_MS2) - #define _Z3_MS2 Z3_MS2_PIN, - #else - #define _Z3_MS2 + #if PIN_EXISTS(FAN4) + FAN4_PIN, #endif - #if PIN_EXISTS(Z3_MS3) - #define _Z3_MS3 Z3_MS3_PIN, - #else - #define _Z3_MS3 + #if PIN_EXISTS(FAN5) + FAN5_PIN, #endif - #define _Z3_PINS Z3_STEP_PIN, Z3_DIR_PIN, Z3_ENABLE_PIN, _Z3_CS _Z3_MS1 _Z3_MS2 _Z3_MS3 -#else - #define _Z3_PINS -#endif - -#if NUM_Z_STEPPERS >= 4 - #if PIN_EXISTS(Z4_CS) && AXIS_HAS_SPI(Z4) - #define _Z4_CS Z4_CS_PIN, - #else - #define _Z4_CS + #if PIN_EXISTS(FAN6) + FAN6_PIN, #endif - #if PIN_EXISTS(Z4_MS1) - #define _Z4_MS1 Z4_MS1_PIN, - #else - #define _Z4_MS1 + #if PIN_EXISTS(FAN7) + FAN7_PIN, #endif - #if PIN_EXISTS(Z4_MS2) - #define _Z4_MS2 Z4_MS2_PIN, - #else - #define _Z4_MS2 + #if PIN_EXISTS(CONTROLLER_FAN) + CONTROLLER_FAN_PIN, #endif - #if PIN_EXISTS(Z4_MS3) - #define _Z4_MS3 Z4_MS3_PIN, - #else - #define _Z4_MS3 + + #if TEMP_SENSOR_BED && PINS_EXIST(TEMP_BED, HEATER_BED) + HEATER_BED_PIN, #endif - #define _Z4_PINS Z4_STEP_PIN, Z4_DIR_PIN, Z4_ENABLE_PIN, _Z4_CS _Z4_MS1 _Z4_MS2 _Z4_MS3 -#else - #define _Z4_PINS -#endif -// -// Generate the final Sensitive Pins array, -// keeping the array as small as possible. -// + #if TEMP_SENSOR_CHAMBER && PIN_EXISTS(TEMP_CHAMBER) + #if PIN_EXISTS(HEATER_CHAMBER) + HEATER_CHAMBER_PIN, + #endif + #if PIN_EXISTS(CHAMBER_AUTO_FAN) + CHAMBER_AUTO_FAN_PIN, + #endif + #endif -#if PIN_EXISTS(PS_ON) - #define _PS_ON PS_ON_PIN, -#else - #define _PS_ON -#endif + #if TEMP_SENSOR_COOLER && PIN_EXISTS(TEMP_COOLER) + #if PIN_EXISTS(COOLER_AUTO_FAN) + COOLER_AUTO_FAN_PIN, + #endif + #if PIN_EXISTS(COOLER) + COOLER_PIN, + #endif + #endif -#if HAS_BED_PROBE && PIN_EXISTS(Z_MIN_PROBE) - #define _Z_PROBE Z_MIN_PROBE_PIN, -#else - #define _Z_PROBE -#endif + #ifdef HAL_SENSITIVE_PINS + HAL_SENSITIVE_PINS + #endif +}; -#if PIN_EXISTS(FAN0) - #define _FAN0 FAN0_PIN, -#else - #define _FAN0 -#endif -#if PIN_EXISTS(FAN1) - #define _FAN1 FAN1_PIN, -#else - #define _FAN1 -#endif -#if PIN_EXISTS(FAN2) - #define _FAN2 FAN2_PIN, -#else - #define _FAN2 -#endif -#if PIN_EXISTS(FAN3) - #define _FAN3 FAN3_PIN, -#else - #define _FAN3 -#endif -#if PIN_EXISTS(FAN4) - #define _FAN4 FAN4_PIN, -#else - #define _FAN4 -#endif -#if PIN_EXISTS(FAN5) - #define _FAN5 FAN5_PIN, -#else - #define _FAN5 -#endif -#if PIN_EXISTS(FAN6) - #define _FAN6 FAN6_PIN, -#else - #define _FAN6 -#endif -#if PIN_EXISTS(FAN7) - #define _FAN7 FAN7_PIN, -#else - #define _FAN7 -#endif -#if PIN_EXISTS(CONTROLLER_FAN) - #define _FANC CONTROLLER_FAN_PIN, -#else - #define _FANC -#endif - -#if TEMP_SENSOR_BED && PINS_EXIST(TEMP_BED, HEATER_BED) - #define _BED_PINS HEATER_BED_PIN, DIO_PIN(TEMP_BED_PIN), -#else - #define _BED_PINS -#endif - -#if TEMP_SENSOR_CHAMBER && PIN_EXISTS(TEMP_CHAMBER) - #define _CHAMBER_TEMP DIO_PIN(TEMP_CHAMBER_PIN), -#else - #define _CHAMBER_TEMP -#endif -#if TEMP_SENSOR_CHAMBER && PINS_EXIST(TEMP_CHAMBER, HEATER_CHAMBER) - #define _CHAMBER_HEATER HEATER_CHAMBER_PIN, -#else - #define _CHAMBER_HEATER -#endif -#if TEMP_SENSOR_CHAMBER && PINS_EXIST(TEMP_CHAMBER, CHAMBER_AUTO_FAN) - #define _CHAMBER_FAN CHAMBER_AUTO_FAN_PIN, -#else - #define _CHAMBER_FAN -#endif - -#if TEMP_SENSOR_COOLER && PIN_EXISTS(TEMP_COOLER) - #define _COOLER_TEMP DIO_PIN(TEMP_COOLER_PIN), -#else - #define _COOLER_TEMP -#endif -#if TEMP_SENSOR_COOLER && PIN_EXISTS(COOLER) - #define _COOLER COOLER_PIN, -#else - #define _COOLER -#endif -#if TEMP_SENSOR_COOLER && PINS_EXIST(TEMP_COOLER, COOLER_AUTO_FAN) - #define _COOLER_FAN COOLER_AUTO_FAN_PIN, -#else - #define _COOLER_FAN -#endif - -#ifndef HAL_SENSITIVE_PINS - #define HAL_SENSITIVE_PINS -#endif - -#ifdef RUNTIME_ONLY_ANALOG_TO_DIGITAL - #define _SP_END -#else - #define _SP_END -2 - - // Move a regular pin in front to the end - template - struct OnlyPins : OnlyPins { }; - - // Remove a -1 from the front - template - struct OnlyPins<-1, D...> : OnlyPins { }; - - // Remove -2 from the front, emit the rest, cease propagation - template - struct OnlyPins<_SP_END, D...> { static constexpr size_t size = sizeof...(D); static constexpr pin_t table[sizeof...(D)] PROGMEM = { D... }; }; -#endif - -#define SENSITIVE_PINS \ - _X_PINS _Y_PINS _Z_PINS _I_PINS _J_PINS _K_PINS _U_PINS _V_PINS _W_PINS \ - _X2_PINS _Y2_PINS _Z2_PINS _Z3_PINS _Z4_PINS _Z_PROBE \ - _E0_PINS _E1_PINS _E2_PINS _E3_PINS _E4_PINS _E5_PINS _E6_PINS _E7_PINS \ - _H0_PINS _H1_PINS _H2_PINS _H3_PINS _H4_PINS _H5_PINS _H6_PINS _H7_PINS \ - _PS_ON _FAN0 _FAN1 _FAN2 _FAN3 _FAN4 _FAN5 _FAN6 _FAN7 _FANC \ - _BED_PINS _CHAMBER_TEMP _CHAMBER_HEATER _CHAMBER_FAN \ - _COOLER_TEMP _COOLER _COOLER_FAN HAL_SENSITIVE_PINS \ - _SP_END +constexpr pin_t sensitive_aio[] PROGMEM = { + #if HAS_HOTEND + TEMP_0_PIN, + #endif + #if HAS_MULTI_HOTEND + TEMP_1_PIN, + #endif + #if HOTENDS > 2 + TEMP_2_PIN, + #endif + #if HOTENDS > 3 + TEMP_3_PIN, + #endif + #if HOTENDS > 4 + TEMP_4_PIN, + #endif + #if HOTENDS > 5 + TEMP_5_PIN, + #endif + #if HOTENDS > 6 + TEMP_6_PIN, + #endif + #if HOTENDS > 7 + TEMP_7_PIN, + #endif + #if TEMP_SENSOR_BED && PINS_EXIST(TEMP_BED, HEATER_BED) + TEMP_BED_PIN, + #endif + #if TEMP_SENSOR_CHAMBER && PIN_EXISTS(TEMP_CHAMBER) + TEMP_CHAMBER_PIN, + #endif + #if TEMP_SENSOR_COOLER && PIN_EXISTS(TEMP_COOLER) + TEMP_COOLER_PIN, + #endif +}; diff --git a/Marlin/src/pins/stm32f0/pins_MALYAN_M300.h b/Marlin/src/pins/stm32f0/pins_MALYAN_M300.h index c55c63aa29..ba6263cd74 100644 --- a/Marlin/src/pins/stm32f0/pins_MALYAN_M300.h +++ b/Marlin/src/pins/stm32f0/pins_MALYAN_M300.h @@ -90,4 +90,6 @@ #define HEATER_0_PIN PA1 // HOTEND0 MOSFET #define HEATER_BED_PIN PA5 // BED MOSFET -#define AUTO_FAN_PIN PA8 +#ifndef E0_AUTO_FAN_PIN + #define E0_AUTO_FAN_PIN PA8 +#endif diff --git a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_common.h b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_common.h index 4c5cccfab1..a01833db03 100644 --- a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_common.h +++ b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_common.h @@ -334,7 +334,7 @@ #define LCD_BACKLIGHT_PIN -1 #define NEOPIXEL_PIN EXP1_07_PIN - #define LCD_CONTRAST 255 + #define LCD_CONTRAST_INIT 255 #define DOGLCD_CS EXP1_03_PIN #define DOGLCD_A0 EXP1_01_PIN diff --git a/Marlin/src/pins/stm32f1/pins_LONGER3D_LK.h b/Marlin/src/pins/stm32f1/pins_LONGER3D_LK.h index 2c1fdf1d76..76e60b4226 100644 --- a/Marlin/src/pins/stm32f1/pins_LONGER3D_LK.h +++ b/Marlin/src/pins/stm32f1/pins_LONGER3D_LK.h @@ -158,7 +158,8 @@ #define LCD_BRIGHTNESS_DEFAULT TFT_BACKLIGHT_PWM #endif -#if ENABLED(ONBOARD_SDIO) +#if SD_CONNECTION_IS(ONBOARD) + #define ONBOARD_SDIO #define SD_SS_PIN -1 // else SDSS set to PA4 in M43 (spi_pins.h) #endif diff --git a/Marlin/src/pins/stm32f4/pins_BLACKBEEZMINI.h b/Marlin/src/pins/stm32f4/pins_BLACKBEEZMINI.h index ead1ee5e05..64cce56302 100644 --- a/Marlin/src/pins/stm32f4/pins_BLACKBEEZMINI.h +++ b/Marlin/src/pins/stm32f4/pins_BLACKBEEZMINI.h @@ -166,7 +166,7 @@ // // GLCD features // - //#define LCD_CONTRAST 190 + //#define LCD_CONTRAST_INIT 190 // // Dcreen orientation diff --git a/Marlin/src/sd/Sd2Card.h b/Marlin/src/sd/Sd2Card.h index dd021364e0..ad015f1f96 100644 --- a/Marlin/src/sd/Sd2Card.h +++ b/Marlin/src/sd/Sd2Card.h @@ -78,7 +78,7 @@ uint8_t const SD_CARD_TYPE_SD1 = 1, // Standard capacity V1 SD card /** * Define SOFTWARE_SPI to use bit-bang SPI */ -#if ANY(MEGA_SOFT_SPI, USE_SOFTWARE_SPI) +#if ANY(MEGA_SOFT_SPI, SDFAT_USE_SOFTWARE_SPI) #define SOFTWARE_SPI #endif diff --git a/Marlin/src/sd/SdFatConfig.h b/Marlin/src/sd/SdFatConfig.h index 0979a592a3..674737c102 100644 --- a/Marlin/src/sd/SdFatConfig.h +++ b/Marlin/src/sd/SdFatConfig.h @@ -88,8 +88,8 @@ */ #define MEGA_SOFT_SPI 0 -// Set USE_SOFTWARE_SPI nonzero to ALWAYS use Software SPI. -#define USE_SOFTWARE_SPI 0 +// Set SDFAT_USE_SOFTWARE_SPI nonzero to ALWAYS use Software SPI. +#define SDFAT_USE_SOFTWARE_SPI 0 /** * The __cxa_pure_virtual function is an error handler that is invoked when diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp index 25a30585f8..c13ba37a96 100644 --- a/Marlin/src/sd/cardreader.cpp +++ b/Marlin/src/sd/cardreader.cpp @@ -497,7 +497,7 @@ void CardReader::mount() { cdroot(); else { #if ANY(HAS_SD_DETECT, USB_FLASH_DRIVE_SUPPORT) - if (marlin_state != MF_INITIALIZING) LCD_ALERTMESSAGE(MSG_MEDIA_INIT_FAIL); + if (marlin_state != MarlinState::MF_INITIALIZING) LCD_ALERTMESSAGE(MSG_MEDIA_INIT_FAIL); #endif } @@ -902,11 +902,11 @@ void CardReader::write_command(char * const buf) { * Select the newest file and ask the user if they want to print it. */ bool CardReader::one_click_check() { - const bool found = selectNewestFile(); + const bool found = selectNewestFile(); // Changes the current workDir if found if (found) { //SERIAL_ECHO_MSG(" OCP File: ", longest_filename(), "\n"); //ui.init(); - one_click_print(); + one_click_print(); // Restores workkDir to root (eventually) } return found; } @@ -1412,8 +1412,8 @@ void CardReader::fileHasFinished() { endFilePrintNow(TERN_(SD_RESORT, true)); - flag.sdprintdone = true; // Stop getting bytes from the SD card - marlin_state = MF_SD_COMPLETE; // Tell Marlin to enqueue M1001 soon + flag.sdprintdone = true; // Stop getting bytes from the SD card + marlin_state = MarlinState::MF_SD_COMPLETE; // Tell Marlin to enqueue M1001 soon } #if ENABLED(AUTO_REPORT_SD_STATUS) diff --git a/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.h b/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.h index f722c873ae..3c7e7b4a56 100644 --- a/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.h +++ b/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.h @@ -33,7 +33,7 @@ /** * Define SOFTWARE_SPI to use bit-bang SPI */ - #if ANY(MEGA_SOFT_SPI, USE_SOFTWARE_SPI) + #if ANY(MEGA_SOFT_SPI, SDFAT_USE_SOFTWARE_SPI) #define SOFTWARE_SPI #endif diff --git a/README.md b/README.md index b11a1193b9..77a23eaf2f 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Every new HAL opens up a world of hardware. At this time we need HALs for RP2040 [Teensy 4.0](https://www.pjrc.com/store/teensy40.html)|ARM® Cortex-M7| [Teensy 4.1](https://www.pjrc.com/store/teensy41.html)|ARM® Cortex-M7| Linux Native|x86/ARM/etc.|Raspberry Pi + [All supported boards](https://marlinfw.org/docs/hardware/boards.html#boards-list)|All platforms|All boards ## Marlin Support diff --git a/buildroot/share/PlatformIO/scripts/SAMD21_minitronics20.py b/buildroot/share/PlatformIO/scripts/SAMD21_minitronics20.py index 81099f58cc..79097d5198 100644 --- a/buildroot/share/PlatformIO/scripts/SAMD21_minitronics20.py +++ b/buildroot/share/PlatformIO/scripts/SAMD21_minitronics20.py @@ -6,8 +6,7 @@ import pioutil if pioutil.is_pio_build(): from os.path import join, isfile import shutil - - Import("env") + env = pioutil.env mf = env["MARLIN_FEATURES"] rxBuf = mf["RX_BUFFER_SIZE"] if "RX_BUFFER_SIZE" in mf else "0" diff --git a/buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py b/buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py index 4cd553a3da..5395371699 100644 --- a/buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py +++ b/buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py @@ -6,8 +6,7 @@ import pioutil if pioutil.is_pio_build(): from os.path import join, isfile import shutil - - Import("env") + env = pioutil.env mf = env["MARLIN_FEATURES"] rxBuf = mf["RX_BUFFER_SIZE"] if "RX_BUFFER_SIZE" in mf else "0" diff --git a/buildroot/share/PlatformIO/scripts/STM32F103RC_MEEB_3DP.py b/buildroot/share/PlatformIO/scripts/STM32F103RC_MEEB_3DP.py index 4f2da9cdc0..76b65ac021 100644 --- a/buildroot/share/PlatformIO/scripts/STM32F103RC_MEEB_3DP.py +++ b/buildroot/share/PlatformIO/scripts/STM32F103RC_MEEB_3DP.py @@ -3,8 +3,7 @@ # import pioutil if pioutil.is_pio_build(): - - Import("env", "projenv") + env = pioutil.env flash_size = 0 vect_tab_addr = 0 diff --git a/buildroot/share/PlatformIO/scripts/STM32F103RC_fysetc.py b/buildroot/share/PlatformIO/scripts/STM32F103RC_fysetc.py index ecb0cc145c..a12bfd04f5 100644 --- a/buildroot/share/PlatformIO/scripts/STM32F103RC_fysetc.py +++ b/buildroot/share/PlatformIO/scripts/STM32F103RC_fysetc.py @@ -3,9 +3,8 @@ # import pioutil if pioutil.is_pio_build(): - from os.path import join - from os.path import expandvars - Import("env") + from os.path import join, expandvars + env = pioutil.env # Custom HEX from ELF env.AddPostAction( diff --git a/buildroot/share/PlatformIO/scripts/STM32F1_build_flags.py b/buildroot/share/PlatformIO/scripts/STM32F1_build_flags.py new file mode 100755 index 0000000000..dfce215348 --- /dev/null +++ b/buildroot/share/PlatformIO/scripts/STM32F1_build_flags.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# +# STM32F1_build_flags.py +# Add build_flags for the base STM32F1_maple environment (stm32f1-maple.ini) +# +from __future__ import print_function +import sys + +# Dynamic build flags for generic compile options +if __name__ == "__main__": + + # Print these plus the given args when running directly on the command-line + args = [ + "-std=gnu++14", + "-Os", + "-mcpu=cortex-m3", + "-mthumb", + + "-fsigned-char", + "-fno-move-loop-invariants", + "-fno-strict-aliasing", + "-fsingle-precision-constant", + + "--specs=nano.specs", + "--specs=nosys.specs", + + "-MMD", "-MP", + + "-IMarlin/src/HAL/STM32F1", + + "-DTARGET_STM32F1", + "-DARDUINO_ARCH_STM32", + "-DPLATFORM_M997_SUPPORT" + ] + sys.argv[1:] + + print(" ".join(args)) + +else: + + # Extra script for stm32f1-maple.ini build_flags + + import pioutil + if pioutil.is_pio_build(): + pioutil.env.Append( + ARFLAGS=["rcs"], + + ASFLAGS=["-x", "assembler-with-cpp"], + + CXXFLAGS=[ + "-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", + ], + ) diff --git a/buildroot/share/PlatformIO/scripts/STM32F1_create_variant.py b/buildroot/share/PlatformIO/scripts/STM32F1_create_variant.py index 4189cb5899..1ded5b4b8a 100644 --- a/buildroot/share/PlatformIO/scripts/STM32F1_create_variant.py +++ b/buildroot/share/PlatformIO/scripts/STM32F1_create_variant.py @@ -3,10 +3,9 @@ # import pioutil if pioutil.is_pio_build(): - import shutil,marlin + import shutil, marlin from pathlib import Path - - Import("env") + env = pioutil.env platform = env.PioPlatform() board = env.BoardConfig() diff --git a/buildroot/share/PlatformIO/scripts/add_nanolib.py b/buildroot/share/PlatformIO/scripts/add_nanolib.py deleted file mode 100644 index f5166d7d84..0000000000 --- a/buildroot/share/PlatformIO/scripts/add_nanolib.py +++ /dev/null @@ -1,6 +0,0 @@ -# -# add_nanolib.py -# -Import("env") - -env.Append(LINKFLAGS=["--specs=nano.specs"]) diff --git a/buildroot/share/PlatformIO/scripts/chitu_crypt.py b/buildroot/share/PlatformIO/scripts/chitu_crypt.py index 1458e5f850..71b1153f82 100644 --- a/buildroot/share/PlatformIO/scripts/chitu_crypt.py +++ b/buildroot/share/PlatformIO/scripts/chitu_crypt.py @@ -4,9 +4,9 @@ # import pioutil if pioutil.is_pio_build(): - import struct,uuid,marlin + import struct, uuid, marlin - board = marlin.env.BoardConfig() + board = pioutil.env.BoardConfig() def calculate_crc(contents, seed): accumulating_xor_value = seed diff --git a/buildroot/share/PlatformIO/scripts/collect-code-tests.py b/buildroot/share/PlatformIO/scripts/collect-code-tests.py index a0e0e86b11..576e3dd06d 100644 --- a/buildroot/share/PlatformIO/scripts/collect-code-tests.py +++ b/buildroot/share/PlatformIO/scripts/collect-code-tests.py @@ -7,8 +7,7 @@ import pioutil if pioutil.is_pio_build(): import os, re - Import("env") - Import("projenv") + env = pioutil.env os.environ['PATH'] = f"./buildroot/bin/:./buildroot/tests/:{os.environ['PATH']}" diff --git a/buildroot/share/PlatformIO/scripts/common-cxxflags.py b/buildroot/share/PlatformIO/scripts/common-cxxflags.py index 22a0665e05..6e740eb4ff 100644 --- a/buildroot/share/PlatformIO/scripts/common-cxxflags.py +++ b/buildroot/share/PlatformIO/scripts/common-cxxflags.py @@ -5,7 +5,7 @@ import pioutil if pioutil.is_pio_build(): - Import("env") + env = pioutil.env cxxflags = [ # "-Wno-incompatible-pointer-types", diff --git a/buildroot/share/PlatformIO/scripts/common-dependencies-post.py b/buildroot/share/PlatformIO/scripts/common-dependencies-post.py index 78fa071da6..52dcde475c 100644 --- a/buildroot/share/PlatformIO/scripts/common-dependencies-post.py +++ b/buildroot/share/PlatformIO/scripts/common-dependencies-post.py @@ -4,7 +4,9 @@ # import pioutil if pioutil.is_pio_build(): - Import("env", "projenv") + env = pioutil.env + projenv = env + Import("projenv") # src_dir environment. Only for post: scripts! def apply_board_build_flags(): if not 'BOARD_CUSTOM_BUILD_FLAGS' in env['MARLIN_FEATURES']: diff --git a/buildroot/share/PlatformIO/scripts/common-dependencies.py b/buildroot/share/PlatformIO/scripts/common-dependencies.py index faa44292a8..6c76cb8c5e 100644 --- a/buildroot/share/PlatformIO/scripts/common-dependencies.py +++ b/buildroot/share/PlatformIO/scripts/common-dependencies.py @@ -5,10 +5,10 @@ import pioutil if pioutil.is_pio_build(): - import subprocess,os,re,fnmatch,glob + import os, re, fnmatch, glob srcfilepattern = re.compile(r".*[.](cpp|c)$") marlinbasedir = os.path.join(os.getcwd(), "Marlin/") - Import("env") + env = pioutil.env from platformio.package.meta import PackageSpec from platformio.project.config import ProjectConfig diff --git a/buildroot/share/PlatformIO/scripts/configuration.py b/buildroot/share/PlatformIO/scripts/configuration.py index e0387a219d..85fe8ec0bf 100755 --- a/buildroot/share/PlatformIO/scripts/configuration.py +++ b/buildroot/share/PlatformIO/scripts/configuration.py @@ -11,7 +11,7 @@ def blab(str,level=1): if verbose >= level: print(f"[config] {str}") def config_path(cpath): - return Path("Marlin", cpath, encoding='utf-8') + return Path("Marlin", cpath) # Apply a single name = on/off ; name = value ; etc. # TODO: Limit to the given (optional) configuration @@ -223,7 +223,7 @@ def apply_config_ini(cp): sect = 'base' if '@' in ckey: sect, ckey = map(str.strip, ckey.split('@')) cp2 = configparser.ConfigParser() - cp2.read(config_path(ckey)) + cp2.read(config_path(ckey), encoding='utf-8') apply_sections(cp2, sect) ckey = 'base' @@ -270,7 +270,7 @@ if __name__ == "__main__": if ini_file: user_ini = configparser.ConfigParser() - user_ini.read(ini_file) + user_ini.read(ini_file, encoding='utf-8') apply_config_ini(user_ini) else: @@ -279,11 +279,8 @@ else: # import pioutil if pioutil.is_pio_build(): - - Import("env") - try: - verbose = int(env.GetProjectOption('custom_verbose')) + verbose = int(pioutil.env.GetProjectOption('custom_verbose')) except: pass diff --git a/buildroot/share/PlatformIO/scripts/custom_board.py b/buildroot/share/PlatformIO/scripts/custom_board.py index 7a8fe91be0..f25254b20c 100644 --- a/buildroot/share/PlatformIO/scripts/custom_board.py +++ b/buildroot/share/PlatformIO/scripts/custom_board.py @@ -7,7 +7,7 @@ import pioutil if pioutil.is_pio_build(): import marlin - board = marlin.env.BoardConfig() + board = pioutil.env.BoardConfig() address = board.get("build.address", "") if address: diff --git a/buildroot/share/PlatformIO/scripts/download_mks_assets.py b/buildroot/share/PlatformIO/scripts/download_mks_assets.py index 0186f59896..de4ff41a58 100644 --- a/buildroot/share/PlatformIO/scripts/download_mks_assets.py +++ b/buildroot/share/PlatformIO/scripts/download_mks_assets.py @@ -4,10 +4,10 @@ # import pioutil if pioutil.is_pio_build(): - Import("env") - import requests,zipfile,tempfile,shutil + import requests, zipfile, tempfile, shutil from pathlib import Path + env = pioutil.env url = "https://github.com/makerbase-mks/Mks-Robin-Nano-Marlin2.0-Firmware/archive/0263cdaccf.zip" deps_path = Path(env.Dictionary("PROJECT_LIBDEPS_DIR")) zip_path = deps_path / "mks-assets.zip" diff --git a/buildroot/share/PlatformIO/scripts/fix_framework_weakness.py b/buildroot/share/PlatformIO/scripts/fix_framework_weakness.py index e149d1d62b..fd8934abbf 100644 --- a/buildroot/share/PlatformIO/scripts/fix_framework_weakness.py +++ b/buildroot/share/PlatformIO/scripts/fix_framework_weakness.py @@ -8,8 +8,7 @@ if pioutil.is_pio_build(): from os.path import join, isfile from pprint import pprint - Import("env") - + env = pioutil.env if env.MarlinHas("POSTMORTEM_DEBUGGING"): FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoststm32-maple") patchflag_path = join(FRAMEWORK_DIR, ".exc-patching-done") diff --git a/buildroot/share/PlatformIO/scripts/generic_create_variant.py b/buildroot/share/PlatformIO/scripts/generic_create_variant.py index 54aeed5d1d..db7f2e89e7 100644 --- a/buildroot/share/PlatformIO/scripts/generic_create_variant.py +++ b/buildroot/share/PlatformIO/scripts/generic_create_variant.py @@ -8,14 +8,14 @@ import pioutil, re marlin_variant_pattern = re.compile("marlin_.*") if pioutil.is_pio_build(): - import shutil,marlin + import shutil, marlin from pathlib import Path # # Get the platform name from the 'platform_packages' option, # or look it up by the platform.class.name. # - env = marlin.env + env = pioutil.env platform = env.PioPlatform() from platformio.package.meta import PackageSpec diff --git a/buildroot/share/PlatformIO/scripts/lerdge.py b/buildroot/share/PlatformIO/scripts/lerdge.py index 607fe312ac..856ca611c9 100644 --- a/buildroot/share/PlatformIO/scripts/lerdge.py +++ b/buildroot/share/PlatformIO/scripts/lerdge.py @@ -7,7 +7,7 @@ # import pioutil if pioutil.is_pio_build(): - import os,marlin + import os, marlin board = marlin.env.BoardConfig() diff --git a/buildroot/share/PlatformIO/scripts/mc-apply.py b/buildroot/share/PlatformIO/scripts/mc-apply.py index b42ba12f7a..0cfabab0f5 100755 --- a/buildroot/share/PlatformIO/scripts/mc-apply.py +++ b/buildroot/share/PlatformIO/scripts/mc-apply.py @@ -2,9 +2,7 @@ # # Create a Configuration from marlin_config.json # -import json -import sys -import shutil +import json, sys, shutil opt_output = '--opt' in sys.argv output_suffix = '.sh' if opt_output else '' if '--bare-output' in sys.argv else '.gen' diff --git a/buildroot/share/PlatformIO/scripts/openblt.py b/buildroot/share/PlatformIO/scripts/openblt.py index 6db8727ce4..35b9a19486 100644 --- a/buildroot/share/PlatformIO/scripts/openblt.py +++ b/buildroot/share/PlatformIO/scripts/openblt.py @@ -4,8 +4,7 @@ import pioutil if pioutil.is_pio_build(): from os.path import join - - Import("env") + env = pioutil.env board = env.BoardConfig() board_keys = board.get("build").keys() diff --git a/buildroot/share/PlatformIO/scripts/pioutil.py b/buildroot/share/PlatformIO/scripts/pioutil.py index 18e6dba928..8a882d94bf 100644 --- a/buildroot/share/PlatformIO/scripts/pioutil.py +++ b/buildroot/share/PlatformIO/scripts/pioutil.py @@ -2,10 +2,11 @@ # pioutil.py # +from SCons.Script import DefaultEnvironment +env = DefaultEnvironment() + # Make sure 'vscode init' is not the current command def is_pio_build(): - from SCons.Script import DefaultEnvironment - env = DefaultEnvironment() if "IsCleanTarget" in dir(env) and env.IsCleanTarget(): return False return not env.IsIntegrationDump() diff --git a/buildroot/share/PlatformIO/scripts/preflight-checks.py b/buildroot/share/PlatformIO/scripts/preflight-checks.py index 2a5f98dbbf..731537f3ed 100644 --- a/buildroot/share/PlatformIO/scripts/preflight-checks.py +++ b/buildroot/share/PlatformIO/scripts/preflight-checks.py @@ -5,9 +5,9 @@ import pioutil if pioutil.is_pio_build(): - import re,sys + import re, sys from pathlib import Path - Import("env") + env = pioutil.env def get_envs_for_board(board): ppath = Path("Marlin/src/pins/pins.h") diff --git a/buildroot/share/PlatformIO/scripts/simulator.py b/buildroot/share/PlatformIO/scripts/simulator.py index 608258c4d1..2b30ec32c0 100644 --- a/buildroot/share/PlatformIO/scripts/simulator.py +++ b/buildroot/share/PlatformIO/scripts/simulator.py @@ -6,7 +6,7 @@ import pioutil if pioutil.is_pio_build(): # Get the environment thus far for the build - Import("env") + env = pioutil.env #print(env.Dump()) @@ -17,37 +17,53 @@ if pioutil.is_pio_build(): env['PROGNAME'] = "MarlinSimulator" # - # If Xcode is installed add the path to its Frameworks folder, - # or if Mesa is installed try to use its GL/gl.h. + # Check for a valid GCC and available OpenGL on macOS # - + emsg = '' + fatal = 0 import sys if sys.platform == 'darwin': - # - # Silence half of the ranlib warnings. (No equivalent for 'ARFLAGS') - # - env['RANLIBFLAGS'] += [ "-no_warning_for_no_symbols" ] - - # Default paths for Xcode and a lucky GL/gl.h dropped by Mesa - xcode_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" - mesa_path = "/opt/local/include/GL/gl.h" - - import os.path - - if os.path.exists(xcode_path): - - env['BUILD_FLAGS'] += [ "-F" + xcode_path ] - print("Using OpenGL framework headers from Xcode.app") - - elif os.path.exists(mesa_path): - - env['BUILD_FLAGS'] += [ '-D__MESA__' ] - print("Using OpenGL header from", mesa_path) + import shutil + gcc = shutil.which('gcc') + if gcc == '' or gcc == '/usr/bin/gcc': + if gcc == '': + emsg = "\u001b[31mNo GCC found in your configured shell PATH." + elif gcc == '/usr/bin/gcc': + emsg = "\u001b[31mCan't build Marlin Native on macOS using the included version of GCC (clang)." + emsg += "\n\u001b[31mSee 'native.ini' for instructions to install GCC with MacPorts or Homebrew." + fatal = 1 else: - print("\n\nNo OpenGL headers found. Install Xcode for matching headers, or use 'sudo port install mesa' to get a GL/gl.h.\n\n") + # + # Silence half of the ranlib warnings. (No equivalent for 'ARFLAGS') + # + env['RANLIBFLAGS'] += [ "-no_warning_for_no_symbols" ] - # Break out of the PIO build immediately - sys.exit(1) + # Default paths for Xcode and a lucky GL/gl.h dropped by Mesa + xcode_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" + mesa_path = "/opt/local/include/GL/gl.h" + + import os.path + + if os.path.exists(xcode_path): + + env['BUILD_FLAGS'] += [ "-F" + xcode_path ] + emsg = "\u001b[33mUsing OpenGL framework headers from Xcode.app" + + elif os.path.exists(mesa_path): + + env['BUILD_FLAGS'] += [ '-D__MESA__' ] + emsg = f"\u001b[33mUsing OpenGL header from {mesa_path}" + + else: + + emsg = "\u001b[31mNo OpenGL headers found. Install Xcode for matching headers, or use 'sudo port install mesa' to get a GL/gl.h." + fatal = 1 + + # Print error message, if any + if emsg: print(f"\n\n{emsg}\n\n") + + # Break out of the PIO build immediately + if fatal: sys.exit(1) diff --git a/buildroot/share/PlatformIO/scripts/stm32_serialbuffer.py b/buildroot/share/PlatformIO/scripts/stm32_serialbuffer.py index 1f5f6eec78..f02e1b579d 100644 --- a/buildroot/share/PlatformIO/scripts/stm32_serialbuffer.py +++ b/buildroot/share/PlatformIO/scripts/stm32_serialbuffer.py @@ -3,7 +3,7 @@ # import pioutil if pioutil.is_pio_build(): - Import("env") + env = pioutil.env # Get a build flag's value or None def getBuildFlagValue(name): diff --git a/buildroot/share/PlatformIO/scripts/tronxy_cxy_446_v10.py b/buildroot/share/PlatformIO/scripts/tronxy_cxy_446_v10.py index f3cb94a062..4cbbf375f6 100644 --- a/buildroot/share/PlatformIO/scripts/tronxy_cxy_446_v10.py +++ b/buildroot/share/PlatformIO/scripts/tronxy_cxy_446_v10.py @@ -7,9 +7,7 @@ if pioutil.is_pio_build(): import marlin, os - from SCons.Script import DefaultEnvironment - - env = DefaultEnvironment() + env = pioutil.env # Check whether the "update" folder exists outpath = "update" diff --git a/buildroot/share/dwin/bin/DWIN_ICO.py b/buildroot/share/dwin/bin/DWIN_ICO.py index 4594e55017..a13437a8bb 100644 --- a/buildroot/share/dwin/bin/DWIN_ICO.py +++ b/buildroot/share/dwin/bin/DWIN_ICO.py @@ -206,12 +206,12 @@ class Entry(): ''' __slots__ = ('width', 'height', 'offset', 'length', 'filename') - def __init__(self, w=0, h=0, length=0, offset=0): + def __init__(self, w=0, h=0, length=0, offset=0, filename=None): self.width = w self.height = h self.offset = offset self.length = length - self.filename = None + self.filename = filename def parseRawData(self, rawEntryBytes): if len(rawEntryBytes) != 16: diff --git a/buildroot/share/scripts/MarlinBinaryProtocol.py b/buildroot/share/scripts/MarlinBinaryProtocol.py index 6d902dbeeb..5ec83b1503 100644 --- a/buildroot/share/scripts/MarlinBinaryProtocol.py +++ b/buildroot/share/scripts/MarlinBinaryProtocol.py @@ -181,7 +181,7 @@ class Protocol(object): except ReadTimeout: self.errors += 1 #print("Packetloss detected..") - except serial.serialutil.SerialException: + except serial.SerialException: return self.packet_transit = None @@ -201,7 +201,7 @@ class Protocol(object): def transmit_packet(self, packet): packet = bytearray(packet) - if(self.simulate_errors > 0 and random.random() > (1.0 - self.simulate_errors)): + if (self.simulate_errors > 0 and random.random() > (1.0 - self.simulate_errors)): if random.random() > 0.9: #random data drop start = random.randint(0, len(packet)) diff --git a/buildroot/share/scripts/createTemperatureLookupMarlin.py b/buildroot/share/scripts/createTemperatureLookupMarlin.py index 5902e91a87..e2441f5d89 100755 --- a/buildroot/share/scripts/createTemperatureLookupMarlin.py +++ b/buildroot/share/scripts/createTemperatureLookupMarlin.py @@ -22,7 +22,7 @@ from __future__ import print_function from __future__ import division from math import * -import sys,getopt +import sys, getopt "Constants" ZERO = 273.15 # zero point of Kelvin scale diff --git a/buildroot/share/scripts/gen-tft-image.py b/buildroot/share/scripts/gen-tft-image.py index f3786aef70..d00f980fb0 100644 --- a/buildroot/share/scripts/gen-tft-image.py +++ b/buildroot/share/scripts/gen-tft-image.py @@ -22,7 +22,7 @@ # Generate Marlin TFT Images from bitmaps/PNG/JPG -import sys,struct +import sys, struct from PIL import Image def image2bin(image, output_file): diff --git a/buildroot/share/scripts/languageImport.py b/buildroot/share/scripts/languageImport.py index a535040ad0..c0bbd5951c 100755 --- a/buildroot/share/scripts/languageImport.py +++ b/buildroot/share/scripts/languageImport.py @@ -17,7 +17,7 @@ TODO: Use the defines and comments above the namespace from existing language fi """ import sys, re, requests, csv, datetime -from languageUtil import namebyid +#from languageUtil import namebyid LANGHOME = "Marlin/src/lcd/language" OUTDIR = 'out-language' @@ -76,10 +76,10 @@ for row in reader: # Add the named string for all the included languages name = row[0] for i in range(1, numcols): - str = row[i] - if str: + str_key = row[i] + if str_key: col = columns[i] - strings_per_lang[col['lang']][col['style']][name] = str + strings_per_lang[col['lang']][col['style']][name] = str_key # Create a folder for the imported language outfiles from pathlib import Path @@ -199,11 +199,11 @@ for i in range(1, numcols): comm = '' if lang != 'en' and 'en' in strings_per_lang: en = strings_per_lang['en'] - if name in en[style]: str = en[style][name] - elif name in en['Narrow']: str = en['Narrow'][name] - if str: + if name in en[style]: str_key = en[style][name] + elif name in en['Narrow']: str_key = en['Narrow'][name] + if str_key: cfmt = '%%%ss// %%s' % (50 - len(val) if len(val) < 50 else 1) - comm = cfmt % (' ', str) + comm = cfmt % (' ', str_key) # Write out the string definition f.write(lstr_fmt % (name, val, comm)) diff --git a/buildroot/share/scripts/languageUtil.py b/buildroot/share/scripts/languageUtil.py index 789561e7b9..996db5dd31 100755 --- a/buildroot/share/scripts/languageUtil.py +++ b/buildroot/share/scripts/languageUtil.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# marlang.py +# languageUtil.py # # A dictionary to contain language names diff --git a/buildroot/share/scripts/rle16_compress_cpp_image_data.py b/buildroot/share/scripts/rle16_compress_cpp_image_data.py index aeb7e65d3a..60681ee57a 100755 --- a/buildroot/share/scripts/rle16_compress_cpp_image_data.py +++ b/buildroot/share/scripts/rle16_compress_cpp_image_data.py @@ -5,7 +5,7 @@ # # Usage: rle16_compress_cpp_image_data.py INPUT_FILE.cpp OUTPUT_FILE.cpp # -import sys,struct +import sys, struct import re def addCompressedData(input_file, output_file): diff --git a/buildroot/share/scripts/rle_compress_bitmap.py b/buildroot/share/scripts/rle_compress_bitmap.py index 12d25a7e4a..8c25204919 100755 --- a/buildroot/share/scripts/rle_compress_bitmap.py +++ b/buildroot/share/scripts/rle_compress_bitmap.py @@ -6,7 +6,7 @@ # # Usage: rle_compress_bitmap.py INPUT_FILE OUTPUT_FILE # -import sys,struct +import sys, struct import re def addCompressedData(input_file, output_file): diff --git a/buildroot/share/scripts/upload.py b/buildroot/share/scripts/upload.py index ae7f7e6261..a20c2701fe 100644 --- a/buildroot/share/scripts/upload.py +++ b/buildroot/share/scripts/upload.py @@ -1,11 +1,6 @@ -import argparse -import sys -import os -import time -import random -import serial - -Import("env") +import argparse, sys, os, time, random, serial +from SCons.Script import DefaultEnvironment +env = DefaultEnvironment() import MarlinBinaryProtocol diff --git a/buildroot/share/vscode/auto_build.py b/buildroot/share/vscode/auto_build.py index 80b8b2e6c1..dcbf119d49 100644 --- a/buildroot/share/vscode/auto_build.py +++ b/buildroot/share/vscode/auto_build.py @@ -72,7 +72,7 @@ from __future__ import print_function from __future__ import division -import sys,os,re +import sys, os, re pwd = os.getcwd() # make sure we're executing from the correct directory level pwd = pwd.replace('\\', '/') @@ -103,7 +103,7 @@ current_OS = platform.system() target_env = '' board_name = '' -from datetime import datetime, date, time +from datetime import datetime ######### # Python 2 error messages: @@ -151,8 +151,6 @@ def get_answer(board_name, question_txt, options, default_value=1): root_get_answer.protocol("WM_DELETE_WINDOW", disable_event) root_get_answer.resizable(False, False) - root_get_answer.radio_state = default_value # declare variables used by TK and enable - global get_answer_val get_answer_val = default_value # return get_answer_val, set default to match radio_state default @@ -880,7 +878,6 @@ def run_PIO(dummy): print('build_type: ', build_type) import subprocess - import sys print('starting platformio') @@ -965,7 +962,6 @@ def run_PIO(dummy): ######################################################################## -import time import threading if python_ver == 2: import Tkinter as tk @@ -978,7 +974,6 @@ else: import tkinter as tk import queue as queue from tkinter import ttk, Tk, Frame, Text, Menu -import subprocess import sys que = queue.Queue() #IO_queue = queue.Queue() diff --git a/buildroot/share/vscode/create_custom_upload_command_CDC.py b/buildroot/share/vscode/create_custom_upload_command_CDC.py index 4926faf06a..b2d4d5715a 100644 --- a/buildroot/share/vscode/create_custom_upload_command_CDC.py +++ b/buildroot/share/vscode/create_custom_upload_command_CDC.py @@ -13,7 +13,7 @@ from __future__ import print_function from __future__ import division -import subprocess,os,platform +import subprocess, os, platform from SCons.Script import DefaultEnvironment current_OS = platform.system() diff --git a/buildroot/share/vscode/create_custom_upload_command_DFU.py b/buildroot/share/vscode/create_custom_upload_command_DFU.py index 27c5a34802..22809e177f 100644 --- a/buildroot/share/vscode/create_custom_upload_command_DFU.py +++ b/buildroot/share/vscode/create_custom_upload_command_DFU.py @@ -9,9 +9,9 @@ # Will continue on if a COM port isn't found so that the compilation can be done. # -import os +import os, platform from SCons.Script import DefaultEnvironment -import platform + current_OS = platform.system() env = DefaultEnvironment() diff --git a/buildroot/tests/BIGTREE_GTR_V1_0 b/buildroot/tests/BIGTREE_GTR_V1_0 index 9323175986..dcfd2b3eef 100755 --- a/buildroot/tests/BIGTREE_GTR_V1_0 +++ b/buildroot/tests/BIGTREE_GTR_V1_0 @@ -25,7 +25,8 @@ restore_configs opt_set MOTHERBOARD BOARD_BTT_GTR_V1_0 SERIAL_PORT -1 \ EXTRUDERS 5 TEMP_SENSOR_1 1 TEMP_SENSOR_2 1 TEMP_SENSOR_3 1 TEMP_SENSOR_4 1 \ Z_DRIVER_TYPE A4988 Z2_DRIVER_TYPE A4988 Z3_DRIVER_TYPE A4988 Z4_DRIVER_TYPE A4988 \ - DEFAULT_Kp_LIST '{ 22.2, 20.0, 21.0, 19.0, 18.0 }' DEFAULT_Ki_LIST '{ 1.08 }' DEFAULT_Kd_LIST '{ 114.0, 112.0, 110.0, 108.0 }' + DEFAULT_Kp_LIST '{ 22.2, 20.0, 21.0, 19.0, 18.0 }' DEFAULT_Ki_LIST '{ 1.08 }' DEFAULT_Kd_LIST '{ 114.0, 112.0, 110.0, 108.0 }' \ + Z3_STOP_PIN PI7 Z4_STOP_PIN PF6 opt_enable TOOLCHANGE_FILAMENT_SWAP TOOLCHANGE_MIGRATION_FEATURE TOOLCHANGE_FS_SLOW_FIRST_PRIME TOOLCHANGE_FS_PRIME_FIRST_USED \ REPRAP_DISCOUNT_SMART_CONTROLLER PID_PARAMS_PER_HOTEND Z_MULTI_ENDSTOPS TC_GCODE_USE_GLOBAL_X TC_GCODE_USE_GLOBAL_Y exec_test $1 $2 "BigTreeTech GTR | 6 Extruders | Quad Z + Endstops" "$3" diff --git a/buildroot/tests/STM32F103RC_btt_USB b/buildroot/tests/STM32F103RC_btt_USB index 3981466c46..c8ee4f7814 100755 --- a/buildroot/tests/STM32F103RC_btt_USB +++ b/buildroot/tests/STM32F103RC_btt_USB @@ -10,7 +10,7 @@ set -e # Build with the default configurations # restore_configs -opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_V1_1 SERIAL_PORT 1 SERIAL_PORT_2 -1 TEMP_SENSOR_SOC 1 +opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_V1_1 SERIAL_PORT 1 SERIAL_PORT_2 -1 TEMP_SENSOR_SOC 100 exec_test $1 $2 "BigTreeTech SKR Mini v1.1 - SOC Temperature" "$3" # clean up diff --git a/buildroot/tests/rambo b/buildroot/tests/rambo index 0701a5c4c7..a7deb02c9f 100755 --- a/buildroot/tests/rambo +++ b/buildroot/tests/rambo @@ -29,7 +29,7 @@ opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER LCD_PROGRESS_BAR LCD_PROGRESS_BAR_TE ADVANCED_PAUSE_FEATURE FILAMENT_LOAD_UNLOAD_GCODES FILAMENT_UNLOAD_ALL_EXTRUDERS \ PASSWORD_FEATURE PASSWORD_ON_STARTUP PASSWORD_ON_SD_PRINT_MENU PASSWORD_AFTER_SD_PRINT_END PASSWORD_AFTER_SD_PRINT_ABORT \ AUTO_BED_LEVELING_BILINEAR Z_MIN_PROBE_REPEATABILITY_TEST DISTINCT_E_FACTORS \ - SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE \ + SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE ONE_CLICK_PRINT NO_SD_AUTOSTART \ BACKLASH_COMPENSATION BACKLASH_GCODE BAUD_RATE_GCODE BEZIER_CURVE_SUPPORT \ FWRETRACT ARC_P_CIRCLES CNC_WORKSPACE_PLANES CNC_COORDINATE_SYSTEMS \ PSU_CONTROL LED_POWEROFF_TIMEOUT PS_OFF_CONFIRM PS_OFF_SOUND POWER_OFF_WAIT_FOR_COOLDOWN \ diff --git a/ini/features.ini b/ini/features.ini index cb3b96c402..d60bdcc6cf 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -12,7 +12,7 @@ # The order of the features matters for source-filter resolution inside of common-dependencies.py. [features] -YHCB2004 = red-scorp/LiquidCrystal_AIP31068@^1.0.4, red-scorp/SoftSPIB@^1.1.1 +YHCB2004 = LiquidCrystal_AIP31068=https://github.com/ellensp/LiquidCrystal_AIP31068/archive/3fc43b7.zip, red-scorp/SoftSPIB@^1.1.1 HAS_TFT_LVGL_UI = lvgl=https://github.com/makerbase-mks/LVGL-6.1.1-MKS/archive/a3ebe98bc6.zip build_src_filter=+ extra_scripts=download_mks_assets.py @@ -183,7 +183,7 @@ HAS_MENU_LED = build_src_filter=+ HAS_MENU_MIXER = build_src_filter=+ HAS_MENU_MMU2 = build_src_filter=+ -HAS_MENU_ONE_CLICK_PRINT = build_src_filter=+ +HAS_MENU_ONE_CLICK_PRINT = build_src_filter=+ + HAS_MENU_PASSWORD = build_src_filter=+ HAS_MENU_POWER_MONITOR = build_src_filter=+ HAS_MENU_CUTTER = build_src_filter=+ diff --git a/ini/renamed.ini b/ini/renamed.ini index 85f2df2862..5540374c68 100644 --- a/ini/renamed.ini +++ b/ini/renamed.ini @@ -98,3 +98,9 @@ extends = renamed [env:STM32F446_tronxy] ;=> TRONXY_CXY_446_V10 extends = renamed + +[env:STM32G0B1RE_manta_btt_xfer] ;=> STM32G0B1RE_manta_btt +extends = renamed + +[env:STM32G0B1VE_btt_xfer] ;=> STM32G0B1VE_btt +extends = renamed diff --git a/ini/samd51.ini b/ini/samd51.ini index 70bda9ca52..cf1f9ed8c0 100644 --- a/ini/samd51.ini +++ b/ini/samd51.ini @@ -15,11 +15,12 @@ [env:SAMD51_grandcentral_m4] platform = atmelsam board = adafruit_grandcentral_m4 -build_flags = ${common.build_flags} -std=gnu++17 +build_flags = ${common.build_flags} -std=gnu++17 -DUSE_TINYUSB build_unflags = -std=gnu++11 build_src_filter = ${common.default_src_filter} + lib_deps = ${common.lib_deps} SoftwareSerialM + Adafruit TinyUSB Library extra_scripts = ${common.extra_scripts} pre:buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py custom_marlin.HAS_MEDIA = SdFat - Adafruit Fork, Adafruit SPIFlash diff --git a/ini/stm32f1-maple.ini b/ini/stm32f1-maple.ini index 16563fcc91..94b7ebb585 100644 --- a/ini/stm32f1-maple.ini +++ b/ini/stm32f1-maple.ini @@ -25,13 +25,13 @@ [STM32F1_maple] platform = ststm32@~12.1 board_build.core = maple -build_flags = !python Marlin/src/HAL/STM32F1/build_flags.py +build_flags = !python buildroot/share/PlatformIO/scripts/STM32F1_build_flags.py ${common.build_flags} -DARDUINO_ARCH_STM32 -DMAPLE_STM32F1 -DPLATFORM_M997_SUPPORT build_unflags = -std=gnu11 -std=gnu++11 build_src_filter = ${common.default_src_filter} + - lib_ignore = SPI, FreeRTOS701, FreeRTOS821 lib_deps = ${common.lib_deps} - SoftwareSerialM + SoftwareSerialM platform_packages = tool-stm32duino extra_scripts = ${common.extra_scripts} pre:buildroot/share/PlatformIO/scripts/fix_framework_weakness.py diff --git a/ini/stm32f1.ini b/ini/stm32f1.ini index b164615c89..3a74b6caf7 100644 --- a/ini/stm32f1.ini +++ b/ini/stm32f1.ini @@ -177,6 +177,7 @@ board_upload.offset_address = 0x08010000 extends = env:STM32F103RE_creality board_build.offset = 0x8000 board_upload.offset_address = 0x08008000 +board_build.rename = main_board_{date}_{time}.bin # # Creality 256K (STM32F103RC) diff --git a/ini/stm32g0.ini b/ini/stm32g0.ini index 77bdde7438..40493b3ff1 100644 --- a/ini/stm32g0.ini +++ b/ini/stm32g0.ini @@ -88,21 +88,6 @@ extends = env:STM32G0B1RE_btt build_flags = ${env:STM32G0B1RE_btt.build_flags} -DPIN_SERIAL3_RX=PD_9 -DPIN_SERIAL3_TX=PD_8 -DENABLE_HWSERIAL3 -# -# BigTreeTech Manta M4P V2.1 (STM32G0B0RET6 ARM Cortex-M0+) -# BigTreeTech Manta E3 EZ V1.0 / Manta M5P V1.0 (STM32G0B1RET6 ARM Cortex-M0+) -# Custom upload to SD via Marlin with Binary Protocol -# Requires Marlin with BINARY_FILE_TRANSFER already installed on the target board. -# If CUSTOM_FIRMWARE_UPLOAD is also installed, Marlin will reboot the board to install the firmware. -# Currently CUSTOM_FIRMWARE_UPLOAD must also be enabled to use 'xfer' build envs. -# -[env:STM32G0B1RE_manta_btt_xfer] -extends = env:STM32G0B1RE_manta_btt -build_flags = ${env:STM32G0B1RE_manta_btt.build_flags} -DXFER_BUILD -extra_scripts = ${env:STM32G0B1RE_manta_btt.extra_scripts} - pre:buildroot/share/scripts/upload.py -upload_protocol = custom - # # BigTreeTech Manta M8P V1.x (STM32G0B1VET6 ARM Cortex-M0+) # @@ -123,14 +108,3 @@ build_flags = ${stm32_variant.build_flags} -Wl,--no-warn-rwx-segment upload_protocol = stlink debug_tool = stlink - -# -# BigTreeTech Manta M8P V1.x (STM32G0B1VET6 ARM Cortex-M0+) -# Custom upload to SD via Marlin with Binary Protocol -# -[env:STM32G0B1VE_btt_xfer] -extends = env:STM32G0B1VE_btt -build_flags = ${env:STM32G0B1VE_btt.build_flags} -DXFER_BUILD -extra_scripts = ${env:STM32G0B1VE_btt.extra_scripts} - pre:buildroot/share/scripts/upload.py -upload_protocol = custom