diff --git a/.gitignore b/.gitignore index bc603ba38b..72fd117bd2 100755 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,16 @@ # Generated files _Version.h bdf2u8g +marlin_config.json +mczip.h +*.gen +*.sublime-workspace # # OS # applet/ -*.DS_Store +.DS_Store # # Misc @@ -146,11 +150,13 @@ vc-fileutils.settings #Simulation imgui.ini eeprom.dat +spi_flash.bin #cmake CMakeLists.txt src/CMakeLists.txt CMakeListsPrivate.txt +build/ # CLion cmake-build-* @@ -167,7 +173,3 @@ __pycache__ # IOLogger logs *_log.csv - -# Simulation / Native -eeprom.dat -imgui.ini diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 303acd5a39..29f2d8a148 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -35,7 +35,7 @@ * * Advanced settings can be found in Configuration_adv.h */ -#define CONFIGURATION_H_VERSION 02000902 +#define CONFIGURATION_H_VERSION 02000903 //=========================================================================== //============================= Getting Started ============================= @@ -94,6 +94,11 @@ // @section machine +// Choose the name from boards.h that matches your setup +#ifndef MOTHERBOARD + #define MOTHERBOARD BOARD_MKS_ROBIN_NANO +#endif + /** * Select the serial port on the board to use for communication with the host. * This allows the connection of wireless adapters (for instance) to non-default port pins. @@ -137,12 +142,6 @@ // Enable the Bluetooth serial interface on AT90USB devices //#define BLUETOOTH -// Choose the name from boards.h that matches your setup -#ifndef MOTHERBOARD -// #define MOTHERBOARD BOARD_MKS_ROBIN_NANO_V1_3_F4 - #define MOTHERBOARD BOARD_MKS_ROBIN_NANO -#endif - // Name displayed in the LCD "Ready" message and Info menu #define CUSTOM_MACHINE_NAME "FBGhost 4s/5" @@ -756,6 +755,7 @@ //#define COREZX //#define COREZY //#define MARKFORGED_XY // MarkForged. See https://reprap.org/forum/read.php?152,504042 +//#define MARKFORGED_YX // Enable for a belt style printer with endless "Z" motion //#define BELTPRINTER @@ -1013,7 +1013,7 @@ * * See https://github.com/synthetos/TinyG/wiki/Jerk-Controlled-Motion-Explained */ -#define S_CURVE_ACCELERATION +//#define S_CURVE_ACCELERATION //=========================================================================== //============================= Z Probe Options ============================= @@ -1220,6 +1220,15 @@ #endif #endif +/** + * Probe Enable / Disable + * The probe only provides a triggered signal when enabled. + */ +//#define PROBE_ENABLE_DISABLE +#if ENABLED(PROBE_ENABLE_DISABLE) + //#define PROBE_ENABLE_PIN -1 // Override the default pin here +#endif + /** * Multiple Probing * @@ -1925,6 +1934,7 @@ EEPROM_W25Q #endif #define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors. +//#define EEPROM_INIT_NOW // Init EEPROM on first boot after a new build. #endif // @@ -2471,6 +2481,11 @@ EEPROM_W25Q //#define VIKI2 //#define miniVIKI +// +// Alfawise Ex8 printer LCD marked as WYH L12864 COG +// +//#define WYH_L12864 + // // MakerLab Mini Panel with graphic // controller and SD support - https://reprap.org/wiki/Mini_panel @@ -2540,6 +2555,11 @@ EEPROM_W25Q //#define FYSETC_MINI_12864_2_1 // Type A/B. NeoPixel RGB Backlight //#define FYSETC_GENERIC_12864_1_1 // Larger display with basic ON/OFF backlight. +// +// BigTreeTech Mini 12864 V1.0 is an alias for FYSETC_MINI_12864_2_1. Type A/B. NeoPixel RGB Backlight. +// +//#define BTT_MINI_12864_V1 + // // Factory display for Creality CR-10 // https://www.aliexpress.com/item/32833148327.html @@ -2732,32 +2752,32 @@ EEPROM_W25Q */ // -// 480x320, 3.5", SPI Display From MKS -// Normally used in MKS Robin Nano V2 +// 480x320, 3.5", SPI Display with Rotary Encoder from MKS +// Usually paired with MKS Robin Nano V2 & V3 // //#define MKS_TS35_V2_0 // // 320x240, 2.4", FSMC Display From MKS -// Normally used in MKS Robin Nano V1.2 +// Usually paired with MKS Robin Nano V1.2 // //#define MKS_ROBIN_TFT24 // // 320x240, 2.8", FSMC Display From MKS -// Normally used in MKS Robin Nano V1.2 +// Usually paired with MKS Robin Nano V1.2 // //#define MKS_ROBIN_TFT28 // // 320x240, 3.2", FSMC Display From MKS -// Normally used in MKS Robin Nano V1.2 +// Usually paired with MKS Robin Nano V1.2 // //#define MKS_ROBIN_TFT32 // // 480x320, 3.5", FSMC Display From MKS -// Normally used in MKS Robin Nano V1.2 +// Usually paired with MKS Robin Nano V1.2 // #define MKS_ROBIN_TFT35 @@ -2768,7 +2788,7 @@ EEPROM_W25Q // // 320x240, 3.2", FSMC Display From MKS -// Normally used in MKS Robin +// Usually paired with MKS Robin // //#define MKS_ROBIN_TFT_V1_1R @@ -2798,10 +2818,15 @@ EEPROM_W25Q //#define ANET_ET5_TFT35 // -// 1024x600, 7", RGB Stock Display from BIQU-BX +// 1024x600, 7", RGB Stock Display with Rotary Encoder from BIQU-BX // //#define BIQU_BX_TFT70 +// +// 480x320, 3.5", SPI Stock Display with Rotary Encoder from BIQU B1 SE Series +// +//#define BTT_TFT35_SPI_V1_0 + // // Generic TFT with detailed options // @@ -2856,23 +2881,11 @@ EEPROM_W25Q // // Ender-3 v2 OEM display. A DWIN display with Rotary Encoder. // -//#define DWIN_CREALITY_LCD - -// -// Ender-3 v2 OEM display, enhanced. -// -//#define DWIN_CREALITY_LCD_ENHANCED - -// -// Ender-3 v2 OEM display with enhancements by Jacob Myers -// -//#define DWIN_CREALITY_LCD_JYERSUI - -// -// MarlinUI for Creality's DWIN display (and others) -// -//#define DWIN_MARLINUI_PORTRAIT -//#define DWIN_MARLINUI_LANDSCAPE +//#define DWIN_CREALITY_LCD // Creality UI +//#define DWIN_CREALITY_LCD_ENHANCED // Enhanced UI +//#define DWIN_CREALITY_LCD_JYERSUI // Jyers UI by Jacob Myers +//#define DWIN_MARLINUI_PORTRAIT // MarlinUI (portrait orientation) +//#define DWIN_MARLINUI_LANDSCAPE // MarlinUI (landscape orientation) // // Touch Screen Settings @@ -2908,6 +2921,11 @@ EEPROM_W25Q //#define REPRAPWORLD_KEYPAD //#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0 // (mm) Distance to move per key-press +// +// EasyThreeD ET-4000+ with button input and status LED +// +//#define EASYTHREED_UI + //============================================================================= //=============================== Extra Features ============================== //============================================================================= @@ -2918,9 +2936,6 @@ EEPROM_W25Q // :[1,2,3,4,5,6,7,8] //#define NUM_M106_FANS 1 -// Increase the FAN PWM frequency. Removes the PWM noise but increases heating in the FET/Arduino -//#define FAST_PWM_FAN - // Use software PWM to drive the fan, as for the heaters. This uses a very low frequency // which is not as annoying as with the hardware PWM. On the other hand, if this frequency // is too low, you should also increment SOFT_PWM_SCALE. diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index e80fd28507..42928a8b2c 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -30,7 +30,7 @@ * * Basic settings can be found in Configuration.h */ -#define CONFIGURATION_ADV_H_VERSION 02000902 +#define CONFIGURATION_ADV_H_VERSION 02000903 //=========================================================================== //============================= Thermal Settings ============================ @@ -142,11 +142,20 @@ * FORCE_HW_SPI: Ignore SCK/MOSI/MISO pins and just use the CS pin & default SPI bus. * MAX31865_WIRES: Set the number of wires for the probe connected to a MAX31865 board, 2-4. Default: 2 * MAX31865_50HZ: Enable 50Hz filter instead of the default 60Hz. + * MAX31865_USE_READ_ERROR_DETECTION: Detects random read errors from value spikes (a 20°C difference in less than 1sec) + * MAX31865_USE_AUTO_MODE: Faster and more frequent reads than 1-shot, but bias voltage always on, slightly affecting RTD temperature. + * MAX31865_MIN_SAMPLING_TIME_MSEC: in 1-shot mode, the minimum time between subsequent reads. This reduces the effect of bias voltage by leaving the sensor unpowered for longer intervals. + * MAX31865_WIRE_OHMS: In 2-wire configurations, manually set the wire resistance for more accurate readings */ //#define TEMP_SENSOR_FORCE_HW_SPI //#define MAX31865_SENSOR_WIRES_0 2 //#define MAX31865_SENSOR_WIRES_1 2 //#define MAX31865_50HZ_FILTER +//#define MAX31865_USE_READ_ERROR_DETECTION +//#define MAX31865_USE_AUTO_MODE +//#define MAX31865_MIN_SAMPLING_TIME_MSEC 100 +//#define MAX31865_WIRE_OHMS_0 0.0f +//#define MAX31865_WIRE_OHMS_1 0.0f /** * Hephestos 2 24V heated bed upgrade kit. @@ -186,7 +195,8 @@ //#define CHAMBER_FAN // Enable a fan on the chamber #if ENABLED(CHAMBER_FAN) - #define CHAMBER_FAN_MODE 2 // Fan control mode: 0=Static; 1=Linear increase when temp is higher than target; 2=V-shaped curve; 3=similar to 1 but fan is always on. + //#define CHAMBER_FAN_INDEX 2 // Index of a fan to repurpose as the chamber fan. (Default: first unused fan) + #define CHAMBER_FAN_MODE 2 // Fan control mode: 0=Static; 1=Linear increase when temp is higher than target; 2=V-shaped curve; 3=similar to 1 but fan is always on. #if CHAMBER_FAN_MODE == 0 #define CHAMBER_FAN_BASE 255 // Chamber fan PWM (0-255) #elif CHAMBER_FAN_MODE == 1 @@ -329,14 +339,14 @@ * Thermal Protection parameters for the laser cooler. */ #if ENABLED(THERMAL_PROTECTION_COOLER) - #define THERMAL_PROTECTION_COOLER_PERIOD 10 // Seconds - #define THERMAL_PROTECTION_COOLER_HYSTERESIS 3 // Degrees Celsius + #define THERMAL_PROTECTION_COOLER_PERIOD 10 // Seconds + #define THERMAL_PROTECTION_COOLER_HYSTERESIS 3 // Degrees Celsius /** * Laser cooling watch settings (M143/M193). */ - #define WATCH_COOLER_TEMP_PERIOD 60 // Seconds - #define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius + #define WATCH_COOLER_TEMP_PERIOD 60 // Seconds + #define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius #endif #if ENABLED(PIDTEMP) @@ -414,7 +424,7 @@ */ #define AUTOTEMP #if ENABLED(AUTOTEMP) - #define AUTOTEMP_OLDWEIGHT 0.98 + #define AUTOTEMP_OLDWEIGHT 0.98 // Factor used to weight previous readings (0.0 < value < 1.0) // Turn on AUTOTEMP on M104/M109 by default using proportions set here //#define AUTOTEMP_PROPORTIONAL #if ENABLED(AUTOTEMP_PROPORTIONAL) @@ -539,18 +549,21 @@ //#define FAN_MAX_PWM 128 /** - * FAST PWM FAN Settings + * Fan Fast PWM * - * Use to change the FAST FAN PWM frequency (if enabled in Configuration.h) - * Combinations of PWM Modes, prescale values and TOP resolutions are used internally to produce a - * frequency as close as possible to the desired frequency. + * Combinations of PWM Modes, prescale values and TOP resolutions are used internally + * to produce a frequency as close as possible to the desired frequency. * - * FAST_PWM_FAN_FREQUENCY [undefined by default] + * FAST_PWM_FAN_FREQUENCY * Set this to your desired frequency. - * If left undefined this defaults to F = F_CPU/(2*255*1) - * i.e., F = 31.4kHz on 16MHz microcontrollers or F = 39.2kHz on 20MHz microcontrollers. - * These defaults are the same as with the old FAST_PWM_FAN implementation - no migration is required + * For AVR, if left undefined this defaults to F = F_CPU/(2*255*1) + * i.e., F = 31.4kHz on 16MHz microcontrollers or F = 39.2kHz on 20MHz microcontrollers. + * For non AVR, if left undefined this defaults to F = 1Khz. + * This F value is only to protect the hardware from an absence of configuration + * and not to complete it when users are not aware that the frequency must be specifically set to support the target board. + * * NOTE: Setting very low frequencies (< 10 Hz) may result in unexpected timer behavior. + * Setting very high frequencies can damage your hardware. * * USE_OCR2A_AS_TOP [undefined by default] * Boards that use TIMER2 for PWM have limitations resulting in only a few possible frequencies on TIMER2: @@ -560,9 +573,17 @@ * PWM on pin OC2A. Only use this option if you don't need PWM on 0C2A. (Check your schematic.) * USE_OCR2A_AS_TOP sacrifices duty cycle control resolution to achieve this broader range of frequencies. */ +//#define FAST_PWM_FAN // Increase the fan PWM frequency. Removes the PWM noise but increases heating in the FET/Arduino #if ENABLED(FAST_PWM_FAN) - //#define FAST_PWM_FAN_FREQUENCY 31400 + //#define FAST_PWM_FAN_FREQUENCY 31400 // Define here to override the defaults below //#define USE_OCR2A_AS_TOP + #ifndef FAST_PWM_FAN_FREQUENCY + #ifdef __AVR__ + #define FAST_PWM_FAN_FREQUENCY ((F_CPU) / (2 * 255 * 1)) + #else + #define FAST_PWM_FAN_FREQUENCY 1000U + #endif + #endif #endif /** @@ -603,6 +624,40 @@ #define COOLER_AUTO_FAN_TEMPERATURE 18 #define COOLER_AUTO_FAN_SPEED 255 +/** + * Hotend Cooling Fans tachometers + * + * Define one or more tachometer pins to enable fan speed + * monitoring, and reporting of fan speeds with M123. + * + * NOTE: Only works with fans up to 7000 RPM. + */ +//#define FOURWIRES_FANS // Needed with AUTO_FAN when 4-wire PWM fans are installed +//#define E0_FAN_TACHO_PIN -1 +//#define E0_FAN_TACHO_PULLUP +//#define E0_FAN_TACHO_PULLDOWN +//#define E1_FAN_TACHO_PIN -1 +//#define E1_FAN_TACHO_PULLUP +//#define E1_FAN_TACHO_PULLDOWN +//#define E2_FAN_TACHO_PIN -1 +//#define E2_FAN_TACHO_PULLUP +//#define E2_FAN_TACHO_PULLDOWN +//#define E3_FAN_TACHO_PIN -1 +//#define E3_FAN_TACHO_PULLUP +//#define E3_FAN_TACHO_PULLDOWN +//#define E4_FAN_TACHO_PIN -1 +//#define E4_FAN_TACHO_PULLUP +//#define E4_FAN_TACHO_PULLDOWN +//#define E5_FAN_TACHO_PIN -1 +//#define E5_FAN_TACHO_PULLUP +//#define E5_FAN_TACHO_PULLDOWN +//#define E6_FAN_TACHO_PIN -1 +//#define E6_FAN_TACHO_PULLUP +//#define E6_FAN_TACHO_PULLDOWN +//#define E7_FAN_TACHO_PIN -1 +//#define E7_FAN_TACHO_PULLUP +//#define E7_FAN_TACHO_PULLDOWN + /** * Part-Cooling Fan Multiplexer * @@ -853,12 +908,14 @@ //#define BLTOUCH_FORCE_MODE_SET /** - * Use "HIGH SPEED" mode for probing. + * Enable "HIGH SPEED" option for probing. * Danger: Disable if your probe sometimes fails. Only suitable for stable well-adjusted systems. * This feature was designed for Deltabots with very fast Z moves; however, higher speed Cartesians * might be able to use it. If the machine can't raise Z fast enough the BLTouch may go into ALARM. + * + * Set the default state here, change with 'M401 S' or UI, use M500 to save, M502 to reset. */ - //#define BLTOUCH_HS_MODE + //#define BLTOUCH_HS_MODE true // Safety: Enable voltage mode settings in the LCD menu. //#define BLTOUCH_LCD_VOLTAGE_MENU @@ -1235,6 +1292,22 @@ // Set a convenient position to do the calibration (probing point and nozzle/bed-distance) //#define PROBE_OFFSET_WIZARD_XY_POS { X_CENTER, Y_CENTER } #endif + + #if ENABLED(AUTO_BED_LEVELING_BILINEAR) + // Add a calibration procedure in the Probe Offsets menu + // to compensate for twist in the X-axis. + //#define X_AXIS_TWIST_COMPENSATION + #if ENABLED(X_AXIS_TWIST_COMPENSATION) + /** + * Enable to init the Probe Z-Offset when starting the Wizard. + * Use a height slightly above the estimated nozzle-to-probe Z offset. + * For example, with an offset of -5, consider a starting height of -4. + */ + #define XATC_START_Z 0.0 + #define XATC_MAX_POINTS 3 // Number of points to probe in the wizard + #define XATC_Y_POSITION Y_CENTER // (mm) Y position to probe + #endif + #endif #endif // Include a page of printer information in the LCD Main Menu @@ -1246,9 +1319,6 @@ // BACK menu items keep the highlight at the top //#define TURBO_BACK_MENU_ITEM - // Add a mute option to the LCD menu - #define SOUND_MENU_ITEM - /** * LED Control Menu * Add LED Control to the LCD menu @@ -1280,7 +1350,11 @@ #endif // HAS_LCD_MENU -#if HAS_DISPLAY +#if ANY(HAS_DISPLAY, DWIN_CREALITY_LCD_ENHANCED, DWIN_CREALITY_LCD_JYERSUI) + #define SOUND_MENU_ITEM // Add a mute option to the LCD menu +#endif + +#if EITHER(HAS_DISPLAY, DWIN_CREALITY_LCD_ENHANCED) // The timeout (in ms) to return to the status screen from sub-menus //#define LCD_TIMEOUT_TO_STATUS 15000 @@ -1306,7 +1380,7 @@ // LCD Print Progress options #if EITHER(SDSUPPORT, LCD_SET_PROGRESS_MANUALLY) - #if ANY(HAS_MARLINUI_U8GLIB, EXTENSIBLE_UI, HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL, IS_DWIN_MARLINUI) + #if CAN_SHOW_REMAINING_TIME //#define SHOW_REMAINING_TIME // Display estimated time to completion #if ENABLED(SHOW_REMAINING_TIME) //#define USE_M73_REMAINING_TIME // Use remaining time from M73 command instead of estimation @@ -1534,6 +1608,14 @@ #define SD_FIRMWARE_UPDATE_INACTIVE_VALUE 0xFF #endif + /** + * Enable this option if you have more than ~3K of unused flash space. + * Marlin will embed all settings in the firmware binary as compressed data. + * Use 'M503 C' to write the settings out to the SD Card as 'mc.zip'. + * See docs/ConfigEmbedding.md for details on how to use 'mc-apply.py'. + */ + //#define CONFIGURATION_EMBEDDING + // Add an optimized binary file transfer mode, initiated with 'M28 B1' //#define BINARY_FILE_TRANSFER @@ -1605,7 +1687,7 @@ * Set STATUS_EXPIRE_SECONDS to zero to never clear the status. * This will prevent position updates from being displayed. */ - #if ENABLED(U8GLIB_ST7920) + #if IS_U8GLIB_ST7920 // Enable this option and reduce the value to optimize screen updates. // The normal delay is 10µs. Use the lowest value that still gives a reliable display. //#define DOGM_SPI_DELAY_US 5 @@ -1634,7 +1716,7 @@ //#define STATUS_ALT_FAN_BITMAP // Use the alternative fan bitmap //#define STATUS_FAN_FRAMES 3 // :[0,1,2,3,4] Number of fan animation frames //#define STATUS_HEAT_PERCENT // Show heating in a progress bar - //#define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~‭3260 (or ~940) bytes of PROGMEM. + //#define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~3260 (or ~940) bytes of PROGMEM. // Frivolous Game Options //#define MARLIN_BRICKOUT @@ -1915,6 +1997,7 @@ #define LIN_ADVANCE_K 0 // Unit: mm compression per 1mm/s extruder speed //#define LA_DEBUG // If enabled, this will generate debug information output over USB. #define EXPERIMENTAL_SCURVE // Enable this option to permit S-Curve Acceleration + //#define ALLOW_LOW_EJERK // Allow a DEFAULT_EJERK value of <10. Recommended for direct drive hotends. #endif // @section leveling @@ -1990,59 +2073,69 @@ /** * Thermal Probe Compensation - * Probe measurements are adjusted to compensate for temperature distortion. - * Use G76 to calibrate this feature. Use M871 to set values manually. - * For a more detailed explanation of the process see G76_M871.cpp. + * + * Adjust probe measurements to compensate for distortion associated with the temperature + * of the probe, bed, and/or hotend. + * Use G76 to automatically calibrate this feature for probe and bed temperatures. + * (Extruder temperature/offset values must be calibrated manually.) + * Use M871 to set temperature/offset values manually. + * For more details see https://marlinfw.org/docs/features/probe_temp_compensation.html */ -#if HAS_BED_PROBE && TEMP_SENSOR_PROBE && TEMP_SENSOR_BED - // Enable thermal first layer compensation using bed and probe temperatures - #define PROBE_TEMP_COMPENSATION +//#define PTC_PROBE // Compensate based on probe temperature +//#define PTC_BED // Compensate based on bed temperature +//#define PTC_HOTEND // Compensate based on hotend temperature - // Add additional compensation depending on hotend temperature - // Note: this values cannot be calibrated and have to be set manually - #if ENABLED(PROBE_TEMP_COMPENSATION) +#if ANY(PTC_PROBE, PTC_BED, PTC_HOTEND) + /** + * If the probe is outside the defined range, use linear extrapolation with the closest + * point and the point with index PTC_LINEAR_EXTRAPOLATION. e.g., If set to 4 it will use the + * linear extrapolation between data[0] and data[4] for values below PTC_PROBE_START. + */ + //#define PTC_LINEAR_EXTRAPOLATION 4 + + #if ENABLED(PTC_PROBE) + // Probe temperature calibration generates a table of values starting at PTC_PROBE_START + // (e.g., 30), in steps of PTC_PROBE_RES (e.g., 5) with PTC_PROBE_COUNT (e.g., 10) samples. + #define PTC_PROBE_START 30 // (°C) + #define PTC_PROBE_RES 5 // (°C) + #define PTC_PROBE_COUNT 10 + #define PTC_PROBE_ZOFFS { 0 } // (µm) Z adjustments per sample + #endif + + #if ENABLED(PTC_BED) + // Bed temperature calibration builds a similar table. + #define PTC_BED_START 60 // (°C) + #define PTC_BED_RES 5 // (°C) + #define PTC_BED_COUNT 10 + #define PTC_BED_ZOFFS { 0 } // (µm) Z adjustments per sample + #endif + + #if ENABLED(PTC_HOTEND) + // Note: There is no automatic calibration for the hotend. Use M871. + #define PTC_HOTEND_START 180 // (°C) + #define PTC_HOTEND_RES 5 // (°C) + #define PTC_HOTEND_COUNT 20 + #define PTC_HOTEND_ZOFFS { 0 } // (µm) Z adjustments per sample + #endif + + // G76 options + #if BOTH(PTC_PROBE, PTC_BED) // Park position to wait for probe cooldown #define PTC_PARK_POS { 0, 0, 100 } // Probe position to probe and wait for probe to reach target temperature + //#define PTC_PROBE_POS { 12.0f, 7.3f } // Example: MK52 magnetic heatbed #define PTC_PROBE_POS { 90, 100 } - // Enable additional compensation using hotend temperature - // Note: this values cannot be calibrated automatically but have to be set manually - //#define USE_TEMP_EXT_COMPENSATION - - // Probe temperature calibration generates a table of values starting at PTC_SAMPLE_START - // (e.g., 30), in steps of PTC_SAMPLE_RES (e.g., 5) with PTC_SAMPLE_COUNT (e.g., 10) samples. - - //#define PTC_SAMPLE_START 30 // (°C) - //#define PTC_SAMPLE_RES 5 // (°C) - //#define PTC_SAMPLE_COUNT 10 - - // Bed temperature calibration builds a similar table. - - //#define BTC_SAMPLE_START 60 // (°C) - //#define BTC_SAMPLE_RES 5 // (°C) - //#define BTC_SAMPLE_COUNT 10 - - // The temperature the probe should be at while taking measurements during bed temperature - // calibration. - //#define BTC_PROBE_TEMP 30 // (°C) + // The temperature the probe should be at while taking measurements during + // bed temperature calibration. + #define PTC_PROBE_TEMP 30 // (°C) // Height above Z=0.0 to raise the nozzle. Lowering this can help the probe to heat faster. - // Note: the Z=0.0 offset is determined by the probe offset which can be set using M851. - //#define PTC_PROBE_HEATING_OFFSET 0.5 - - // Height to raise the Z-probe between heating and taking the next measurement. Some probes - // may fail to untrigger if they have been triggered for a long time, which can be solved by - // increasing the height the probe is raised to. - //#define PTC_PROBE_RAISE 15 - - // If the probe is outside of the defined range, use linear extrapolation using the closest - // point and the PTC_LINEAR_EXTRAPOLATION'th next point. E.g. if set to 4 it will use data[0] - // and data[4] to perform linear extrapolation for values below PTC_SAMPLE_START. - //#define PTC_LINEAR_EXTRAPOLATION 4 + // Note: The Z=0.0 offset is determined by the probe Z offset (e.g., as set with M851 Z). + #define PTC_PROBE_HEATING_OFFSET 0.5 #endif -#endif +#endif // PTC_PROBE || PTC_BED || PTC_HOTEND // @section extras @@ -2175,13 +2268,13 @@ // For debug-echo: 128 bytes for the optimal speed. // Other output doesn't need to be that speedy. // :[0, 2, 4, 8, 16, 32, 64, 128, 256] -#define TX_BUFFER_SIZE 256 +#define TX_BUFFER_SIZE 64 // Host Receive Buffer Size // Without XON/XOFF flow control (see SERIAL_XON_XOFF below) 32 bytes should be enough. // To use flow control, set this buffer size to at least 1024 bytes. // :[0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] -#define RX_BUFFER_SIZE 2048 +#define RX_BUFFER_SIZE 512 #if RX_BUFFER_SIZE >= 1024 // Enable to have the controller send XON/XOFF control characters to @@ -2338,7 +2431,7 @@ // Longer prime to clean out a SINGLENOZZLE #define TOOLCHANGE_FS_EXTRA_PRIME 0 // (mm) Extra priming length #define TOOLCHANGE_FS_PRIME_SPEED (4.6*60) // (mm/min) Extra priming feedrate - #define TOOLCHANGE_FS_WIPE_RETRACT 0 // (mm/min) Retract before cooling for less stringing, better wipe, etc. + #define TOOLCHANGE_FS_WIPE_RETRACT 0 // (mm) Retract before cooling for less stringing, better wipe, etc. // Cool after prime to reduce stringing #define TOOLCHANGE_FS_FAN -1 // Fan index or -1 to skip @@ -2599,6 +2692,7 @@ #define X_RSENSE 0.11 #define X_CHAIN_POS -1 // -1..0: Not chained. 1: MCU MOSI connected. 2: Next in chain, ... //#define X_INTERPOLATE true // Enable to override 'INTERPOLATE' for the X axis + //#define X_HOLD_MULTIPLIER 0.5 // Enable to override 'HOLD_MULTIPLIER' for the X axis #endif #if AXIS_IS_TMC(X2) @@ -2608,6 +2702,7 @@ #define X2_RSENSE 0.11 #define X2_CHAIN_POS -1 //#define X2_INTERPOLATE true + //#define X2_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(Y) @@ -2617,6 +2712,7 @@ #define Y_RSENSE 0.11 #define Y_CHAIN_POS -1 //#define Y_INTERPOLATE true + //#define Y_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(Y2) @@ -2626,6 +2722,7 @@ #define Y2_RSENSE 0.11 #define Y2_CHAIN_POS -1 //#define Y2_INTERPOLATE true + //#define Y2_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(Z) @@ -2635,6 +2732,7 @@ #define Z_RSENSE 0.11 #define Z_CHAIN_POS -1 //#define Z_INTERPOLATE true + //#define Z_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(Z2) @@ -2644,6 +2742,7 @@ #define Z2_RSENSE 0.11 #define Z2_CHAIN_POS -1 //#define Z2_INTERPOLATE true + //#define Z2_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(Z3) @@ -2653,6 +2752,7 @@ #define Z3_RSENSE 0.11 #define Z3_CHAIN_POS -1 //#define Z3_INTERPOLATE true + //#define Z3_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(Z4) @@ -2662,6 +2762,7 @@ #define Z4_RSENSE 0.11 #define Z4_CHAIN_POS -1 //#define Z4_INTERPOLATE true + //#define Z4_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(I) @@ -2671,6 +2772,7 @@ #define I_RSENSE 0.11 #define I_CHAIN_POS -1 //#define I_INTERPOLATE true + //#define I_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(J) @@ -2680,6 +2782,7 @@ #define J_RSENSE 0.11 #define J_CHAIN_POS -1 //#define J_INTERPOLATE true + //#define J_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(K) @@ -2689,6 +2792,7 @@ #define K_RSENSE 0.11 #define K_CHAIN_POS -1 //#define K_INTERPOLATE true + //#define K_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(E0) @@ -2697,6 +2801,7 @@ #define E0_RSENSE 0.11 #define E0_CHAIN_POS -1 //#define E0_INTERPOLATE true + //#define E0_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(E1) @@ -2705,6 +2810,7 @@ #define E1_RSENSE 0.11 #define E1_CHAIN_POS -1 //#define E1_INTERPOLATE true + //#define E1_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(E2) @@ -2713,6 +2819,7 @@ #define E2_RSENSE 0.11 #define E2_CHAIN_POS -1 //#define E2_INTERPOLATE true + //#define E2_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(E3) @@ -2721,6 +2828,7 @@ #define E3_RSENSE 0.11 #define E3_CHAIN_POS -1 //#define E3_INTERPOLATE true + //#define E3_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(E4) @@ -2729,6 +2837,7 @@ #define E4_RSENSE 0.11 #define E4_CHAIN_POS -1 //#define E4_INTERPOLATE true + //#define E4_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(E5) @@ -2737,6 +2846,7 @@ #define E5_RSENSE 0.11 #define E5_CHAIN_POS -1 //#define E5_INTERPOLATE true + //#define E5_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(E6) @@ -2745,6 +2855,7 @@ #define E6_RSENSE 0.11 #define E6_CHAIN_POS -1 //#define E6_INTERPOLATE true + //#define E6_HOLD_MULTIPLIER 0.5 #endif #if AXIS_IS_TMC(E7) @@ -2753,6 +2864,7 @@ #define E7_RSENSE 0.11 #define E7_CHAIN_POS -1 //#define E7_INTERPOLATE true + //#define E7_HOLD_MULTIPLIER 0.5 #endif /** @@ -3597,6 +3709,12 @@ */ //#define CNC_COORDINATE_SYSTEMS +/** + * Auto-report fan speed with M123 S + * Requires fans with tachometer pins + */ +//#define AUTO_REPORT_FANS + /** * Auto-report temperatures with M155 S */ @@ -3840,7 +3958,8 @@ #if ENABLED(HOST_ACTION_COMMANDS) //#define HOST_PAUSE_M76 //#define HOST_PROMPT_SUPPORT - //#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start + //#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start + //#define HOST_SHUTDOWN_MENU_ITEM // Add a menu item that tells the host to shut down #endif /** @@ -4214,3 +4333,6 @@ */ //#define SOFT_RESET_VIA_SERIAL // 'KILL' and '^X' commands will soft-reset the controller //#define SOFT_RESET_ON_KILL // Use a digital button to soft-reset the controller after KILL + +// Report uncleaned reset reason from register r2 instead of MCUSR. Supported by Optiboot on AVR. +//#define OPTIBOOT_RESET_REASON diff --git a/Marlin/Makefile b/Marlin/Makefile index d09e5828f5..eee1403b53 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -191,6 +191,134 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1034) # RAMPS Derivatives - ATmega1280, ATmega2560 # +# 3Drag Controller +else ifeq ($(HARDWARE_MOTHERBOARD),1100) +# Velleman K8200 Controller (derived from 3Drag Controller) +else ifeq ($(HARDWARE_MOTHERBOARD),1101) +# Velleman K8400 Controller (derived from 3Drag Controller) +else ifeq ($(HARDWARE_MOTHERBOARD),1102) +# Velleman K8600 Controller (Vertex Nano) +else ifeq ($(HARDWARE_MOTHERBOARD),1103) +# Velleman K8800 Controller (Vertex Delta) +else ifeq ($(HARDWARE_MOTHERBOARD),1104) +# 2PrintBeta BAM&DICE with STK drivers +else ifeq ($(HARDWARE_MOTHERBOARD),1105) +# 2PrintBeta BAM&DICE Due with STK drivers +else ifeq ($(HARDWARE_MOTHERBOARD),1106) +# MKS BASE v1.0 +else ifeq ($(HARDWARE_MOTHERBOARD),1107) +# MKS BASE v1.4 with Allegro A4982 stepper drivers +else ifeq ($(HARDWARE_MOTHERBOARD),1108) +# MKS BASE v1.5 with Allegro A4982 stepper drivers +else ifeq ($(HARDWARE_MOTHERBOARD),1109) +# MKS BASE v1.6 with Allegro A4982 stepper drivers +else ifeq ($(HARDWARE_MOTHERBOARD),1110) +# MKS BASE 1.0 with Heroic HR4982 stepper drivers +else ifeq ($(HARDWARE_MOTHERBOARD),1111) +# MKS GEN v1.3 or 1.4 +else ifeq ($(HARDWARE_MOTHERBOARD),1112) +# MKS GEN L +else ifeq ($(HARDWARE_MOTHERBOARD),1113) +# BigTreeTech or BIQU KFB2.0 +else ifeq ($(HARDWARE_MOTHERBOARD),1114) +# zrib V2.0 (Chinese RAMPS replica) +else ifeq ($(HARDWARE_MOTHERBOARD),1115) +# zrib V5.2 (Chinese RAMPS replica) +else ifeq ($(HARDWARE_MOTHERBOARD),1116) +# Felix 2.0+ Electronics Board (RAMPS like) +else ifeq ($(HARDWARE_MOTHERBOARD),1117) +# Invent-A-Part RigidBoard +else ifeq ($(HARDWARE_MOTHERBOARD),1118) +# Invent-A-Part RigidBoard V2 +else ifeq ($(HARDWARE_MOTHERBOARD),1119) +# Sainsmart 2-in-1 board +else ifeq ($(HARDWARE_MOTHERBOARD),1120) +# Ultimaker +else ifeq ($(HARDWARE_MOTHERBOARD),1121) +# Ultimaker (Older electronics. Pre 1.5.4. This is rare) +else ifeq ($(HARDWARE_MOTHERBOARD),1122) + MCU ?= atmega1280 + PROG_MCU ?= m1280 +# Azteeg X3 +else ifeq ($(HARDWARE_MOTHERBOARD),1123) +# Azteeg X3 Pro +else ifeq ($(HARDWARE_MOTHERBOARD),1124) +# Ultimainboard 2.x (Uses TEMP_SENSOR 20) +else ifeq ($(HARDWARE_MOTHERBOARD),1125) +# Rumba +else ifeq ($(HARDWARE_MOTHERBOARD),1126) +# Raise3D N series Rumba derivative +else ifeq ($(HARDWARE_MOTHERBOARD),1127) +# Rapide Lite 200 (v1, low-cost RUMBA clone with drv) +else ifeq ($(HARDWARE_MOTHERBOARD),1128) +# Formbot T-Rex 2 Plus +else ifeq ($(HARDWARE_MOTHERBOARD),1129) +# Formbot T-Rex 3 +else ifeq ($(HARDWARE_MOTHERBOARD),1130) +# Formbot Raptor +else ifeq ($(HARDWARE_MOTHERBOARD),1131) +# Formbot Raptor 2 +else ifeq ($(HARDWARE_MOTHERBOARD),1132) +# bq ZUM Mega 3D +else ifeq ($(HARDWARE_MOTHERBOARD),1133) +# MakeBoard Mini v2.1.2 by MicroMake +else ifeq ($(HARDWARE_MOTHERBOARD),1134) +# TriGorilla Anycubic version 1.3-based on RAMPS EFB +else ifeq ($(HARDWARE_MOTHERBOARD),1135) +# ... Ver 1.4 +else ifeq ($(HARDWARE_MOTHERBOARD),1136) +# ... Rev 1.1 (new servo pin order) +else ifeq ($(HARDWARE_MOTHERBOARD),1137) +# Creality: Ender-4, CR-8 +else ifeq ($(HARDWARE_MOTHERBOARD),1138) +# Creality: CR10S, CR20, CR-X +else ifeq ($(HARDWARE_MOTHERBOARD),1139) +# Dagoma F5 +else ifeq ($(HARDWARE_MOTHERBOARD),1140) +# FYSETC F6 1.3 +else ifeq ($(HARDWARE_MOTHERBOARD),1141) +# FYSETC F6 1.4 +else ifeq ($(HARDWARE_MOTHERBOARD),1142) +# Wanhao Duplicator i3 Plus +else ifeq ($(HARDWARE_MOTHERBOARD),1143) +# VORON Design +else ifeq ($(HARDWARE_MOTHERBOARD),1144) +# Tronxy TRONXY-V3-1.0 +else ifeq ($(HARDWARE_MOTHERBOARD),1145) +# Z-Bolt X Series +else ifeq ($(HARDWARE_MOTHERBOARD),1146) +# TT OSCAR +else ifeq ($(HARDWARE_MOTHERBOARD),1147) +# Overlord/Overlord Pro +else ifeq ($(HARDWARE_MOTHERBOARD),1148) +# ADIMLab Gantry v1 +else ifeq ($(HARDWARE_MOTHERBOARD),1149) +# ADIMLab Gantry v2 +else ifeq ($(HARDWARE_MOTHERBOARD),1150) +# BIQU Tango V1 +else ifeq ($(HARDWARE_MOTHERBOARD),1151) +# MKS GEN L V2 +else ifeq ($(HARDWARE_MOTHERBOARD),1152) +# MKS GEN L V2.1 +else ifeq ($(HARDWARE_MOTHERBOARD),1153) +# Copymaster 3D +else ifeq ($(HARDWARE_MOTHERBOARD),1154) +# Ortur 4 +else ifeq ($(HARDWARE_MOTHERBOARD),1155) +# Tenlog D3 Hero IDEX printer +else ifeq ($(HARDWARE_MOTHERBOARD),1156) +# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Fan, Bed) +else ifeq ($(HARDWARE_MOTHERBOARD),1157) +# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Hotend2, Bed) +else ifeq ($(HARDWARE_MOTHERBOARD),1158) +# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend, Fan0, Fan1, Bed) +else ifeq ($(HARDWARE_MOTHERBOARD),1159) +# Longer LK1 PRO / Alfawise U20 Pro (PRO version) +else ifeq ($(HARDWARE_MOTHERBOARD),1160) +# Longer LKx PRO / Alfawise Uxx Pro (PRO version) +else ifeq ($(HARDWARE_MOTHERBOARD),1161) + + # 3Drag Controller else ifeq ($(HARDWARE_MOTHERBOARD),1100) # Velleman K8200 Controller (derived from 3Drag Controller) @@ -358,20 +486,38 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1311) else ifeq ($(HARDWARE_MOTHERBOARD),1312) # Mega controller else ifeq ($(HARDWARE_MOTHERBOARD),1313) -# Geeetech GT2560 Rev B for Mecreator2 +# Geeetech GT2560 Rev A else ifeq ($(HARDWARE_MOTHERBOARD),1314) -# Geeetech GT2560 Rev. A +# Geeetech GT2560 Rev A+ (with auto level probe) else ifeq ($(HARDWARE_MOTHERBOARD),1315) -# Geeetech GT2560 Rev. A+ (with auto level probe) +# Geeetech GT2560 Rev B else ifeq ($(HARDWARE_MOTHERBOARD),1316) -# Geeetech GT2560 Rev B for A10(M/D) +# Geeetech GT2560 Rev B for A10(M/T/D) else ifeq ($(HARDWARE_MOTHERBOARD),1317) -# Geeetech GT2560 Rev B for A20(M/D) +# Geeetech GT2560 Rev B for A10(M/T/D) else ifeq ($(HARDWARE_MOTHERBOARD),1318) -# Einstart retrofit +# Geeetech GT2560 Rev B for Mecreator2 else ifeq ($(HARDWARE_MOTHERBOARD),1319) -# Wanhao 0ne+ i3 Mini +# Geeetech GT2560 Rev B for A20(M/T/D) else ifeq ($(HARDWARE_MOTHERBOARD),1320) +# Einstart retrofit +else ifeq ($(HARDWARE_MOTHERBOARD),1321) +# Wanhao 0ne+ i3 Mini +else ifeq ($(HARDWARE_MOTHERBOARD),1322) +# Leapfrog Xeed 2015 +else ifeq ($(HARDWARE_MOTHERBOARD),1323) +# PICA Shield (original version) +else ifeq ($(HARDWARE_MOTHERBOARD),1324) +# PICA Shield (rev C or later) +else ifeq ($(HARDWARE_MOTHERBOARD),1325) +# Intamsys 4.0 (Funmat HT) +else ifeq ($(HARDWARE_MOTHERBOARD),1326) +# Malyan M180 Mainboard Version 2 (no display function, direct gcode only) +else ifeq ($(HARDWARE_MOTHERBOARD),1327) +# Geeetech GT2560 Rev B for A20(M/T/D) +else ifeq ($(HARDWARE_MOTHERBOARD),1328) +# Mega controller & Protoneer CNC Shield V3.00 +else ifeq ($(HARDWARE_MOTHERBOARD),1329) # # ATmega1281, ATmega2561 @@ -445,6 +591,11 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1510) HARDWARE_VARIANT ?= Sanguino MCU ?= atmega1284p PROG_MCU ?= m1284p +# ZoneStar ZMIB V2 +else ifeq ($(HARDWARE_MOTHERBOARD),1511) + HARDWARE_VARIANT ?= Sanguino + MCU ?= atmega1284p + PROG_MCU ?= m1284p # # Other ATmega644P, ATmega644, ATmega1284P diff --git a/Marlin/Version.h b/Marlin/Version.h index bd3bb0ae5f..40136a3684 100644 --- a/Marlin/Version.h +++ b/Marlin/Version.h @@ -28,7 +28,7 @@ /** * Marlin release version identifier */ -//#define SHORT_BUILD_VERSION "2.0.9.2" +//#define SHORT_BUILD_VERSION "2.0.9.3" /** * Verbose version identifier which should contain a reference to the location @@ -41,7 +41,7 @@ * here we define this default string as the date where the latest release * version was tagged. */ -//#define STRING_DISTRIBUTION_DATE "2021-09-03" +//#define STRING_DISTRIBUTION_DATE "2021-12-25" /** * Defines a generic printer name to be output to the LCD after booting Marlin. diff --git a/Marlin/src/HAL/AVR/HAL.cpp b/Marlin/src/HAL/AVR/HAL.cpp index 708583b262..d7bf2a6f6f 100644 --- a/Marlin/src/HAL/AVR/HAL.cpp +++ b/Marlin/src/HAL/AVR/HAL.cpp @@ -35,12 +35,31 @@ // Public Variables // ------------------------ -//uint8_t MCUSR; +// Don't initialize/override variable (which would happen in .init4) +uint8_t reset_reason __attribute__((section(".noinit"))); // ------------------------ // Public functions // ------------------------ +__attribute__((naked)) // Don't output function pro- and epilogue +__attribute__((used)) // Output the function, even if "not used" +__attribute__((section(".init3"))) // Put in an early user definable section +void HAL_save_reset_reason() { + #if ENABLED(OPTIBOOT_RESET_REASON) + __asm__ __volatile__( + A("STS %0, r2") + : "=m"(reset_reason) + ); + #else + reset_reason = MCUSR; + #endif + + // Clear within 16ms since WDRF bit enables a 16ms watchdog timer -> Boot loop + MCUSR = 0; + wdt_disable(); +} + void HAL_init() { // Init Servo Pins #define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW) diff --git a/Marlin/src/HAL/AVR/HAL.h b/Marlin/src/HAL/AVR/HAL.h index a22daf9b5c..2217f239d6 100644 --- a/Marlin/src/HAL/AVR/HAL.h +++ b/Marlin/src/HAL/AVR/HAL.h @@ -91,7 +91,7 @@ typedef int8_t pin_t; // Public Variables // ------------------------ -//extern uint8_t MCUSR; +extern uint8_t reset_reason; // Serial ports #ifdef USBCON @@ -152,21 +152,19 @@ void HAL_init(); //void _delay_ms(const int delay); -inline void HAL_clear_reset_source() { MCUSR = 0; } -inline uint8_t HAL_get_reset_source() { return MCUSR; } +inline void HAL_clear_reset_source() { } +inline uint8_t HAL_get_reset_source() { return reset_reason; } void HAL_reboot(); +#pragma GCC diagnostic push #if GCC_VERSION <= 50000 - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif extern "C" int freeMemory(); -#if GCC_VERSION <= 50000 - #pragma GCC diagnostic pop -#endif +#pragma GCC diagnostic pop // ADC #ifdef DIDR2 @@ -223,7 +221,7 @@ void set_pwm_frequency(const pin_t pin, int f_desired); /** * set_pwm_duty - * Sets the PWM duty cycle of the provided pin to the provided value + * Set the PWM duty cycle of the provided pin to the provided value * Optionally allows inverting the duty cycle [default = false] * Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255] */ diff --git a/Marlin/src/HAL/AVR/fast_pwm.cpp b/Marlin/src/HAL/AVR/fast_pwm.cpp index 238c1124ad..804e5fad30 100644 --- a/Marlin/src/HAL/AVR/fast_pwm.cpp +++ b/Marlin/src/HAL/AVR/fast_pwm.cpp @@ -22,11 +22,10 @@ #ifdef __AVR__ #include "../../inc/MarlinConfigPre.h" +#include "HAL.h" #if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM -#include "HAL.h" - struct Timer { volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer volatile uint16_t* OCRnQ[3]; // max 3 OCR registers per timer @@ -55,8 +54,8 @@ Timer get_pwm_timer(const pin_t pin) { case TIMER1A: case TIMER1B: #endif break; - #if defined(TCCR2) || defined(TCCR2A) - #ifdef TCCR2 + #if HAS_TCCR2 || defined(TCCR2A) + #if HAS_TCCR2 case TIMER2: { Timer timer = { /*TCCRnQ*/ { &TCCR2, nullptr, nullptr }, @@ -153,7 +152,7 @@ Timer get_pwm_timer(const pin_t pin) { void set_pwm_frequency(const pin_t pin, int f_desired) { Timer timer = get_pwm_timer(pin); - if (timer.n == 0) return; // Don't proceed if protected timer or not recognised + if (timer.n == 0) return; // Don't proceed if protected timer or not recognized uint16_t size; if (timer.n == 2) size = 255; else size = 65535; @@ -201,16 +200,10 @@ void set_pwm_frequency(const pin_t pin, int f_desired) { res = res_temp_fast; j = i; // Set the Wave Generation Mode to FAST PWM - if (timer.n == 2) { - wgm = ( - #if ENABLED(USE_OCR2A_AS_TOP) - WGM2_FAST_PWM_OCR2A - #else - WGM2_FAST_PWM - #endif - ); - } - else wgm = WGM_FAST_PWM_ICRn; + if (timer.n == 2) + wgm = TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM); + else + wgm = WGM_FAST_PWM_ICRn; } // If PHASE CORRECT values are closes to desired f else if (f_phase_diff < f_diff) { @@ -218,16 +211,10 @@ void set_pwm_frequency(const pin_t pin, int f_desired) { res = res_temp_phase_correct; j = i; // Set the Wave Generation Mode to PWM PHASE CORRECT - if (timer.n == 2) { - wgm = ( - #if ENABLED(USE_OCR2A_AS_TOP) - WGM2_PWM_PC_OCR2A - #else - WGM2_PWM_PC - #endif - ); - } - else wgm = WGM_PWM_PC_ICRn; + if (timer.n == 2) + wgm = TERN(USE_OCR2A_AS_TOP, WGM2_PWM_PC_OCR2A, WGM2_FAST_PWM); + else + wgm = WGM_PWM_PC_ICRn; } } } @@ -235,48 +222,39 @@ void set_pwm_frequency(const pin_t pin, int f_desired) { _SET_CSn(timer.TCCRnQ, j); if (timer.n == 2) { - #if ENABLED(USE_OCR2A_AS_TOP) - _SET_OCRnQ(timer.OCRnQ, 0, res); // Set OCR2A value (TOP) = res - #endif + TERN_(USE_OCR2A_AS_TOP, _SET_OCRnQ(timer.OCRnQ, 0, res)); // Set OCR2A value (TOP) = res } else _SET_ICRn(timer.ICRn, res); // Set ICRn value (TOP) = res } +#endif // NEEDS_HARDWARE_PWM + void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { - // If v is 0 or v_size (max), digitalWrite to LOW or HIGH. - // Note that digitalWrite also disables pwm output for us (sets COM bit to 0) - if (v == 0) - digitalWrite(pin, invert); - else if (v == v_size) - digitalWrite(pin, !invert); - else { - Timer timer = get_pwm_timer(pin); - if (timer.n == 0) return; // Don't proceed if protected timer or not recognised - // Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted) - _SET_COMnQ(timer.TCCRnQ, (timer.q - #ifdef TCCR2 - + (timer.q == 2) // COM20 is on bit 4 of TCCR2, thus requires q + 1 in the macro - #endif - ), COM_CLEAR_SET + invert - ); + #if NEEDS_HARDWARE_PWM - uint16_t top; - if (timer.n == 2) { // if TIMER2 - top = ( - #if ENABLED(USE_OCR2A_AS_TOP) - *timer.OCRnQ[0] // top = OCR2A - #else - 255 // top = 0xFF (max) - #endif - ); + // If v is 0 or v_size (max), digitalWrite to LOW or HIGH. + // Note that digitalWrite also disables pwm output for us (sets COM bit to 0) + if (v == 0) + digitalWrite(pin, invert); + else if (v == v_size) + digitalWrite(pin, !invert); + else { + Timer timer = get_pwm_timer(pin); + if (timer.n == 0) return; // Don't proceed if protected timer or not recognized + // Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted) + _SET_COMnQ(timer.TCCRnQ, timer.q TERN_(HAS_TCCR2, + (timer.q == 2)), COM_CLEAR_SET + invert); // COM20 is on bit 4 of TCCR2, so +1 for q==2 + const uint16_t top = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn; + _SET_OCRnQ(timer.OCRnQ, timer.q, uint16_t(uint32_t(v) * top / v_size)); // Scale 8/16-bit v to top value } - else - top = *timer.ICRn; // top = ICRn - _SET_OCRnQ(timer.OCRnQ, timer.q, v * float(top) / float(v_size)); // Scale 8/16-bit v to top value - } + #else + + analogWrite(pin, v); + UNUSED(v_size); + UNUSED(invert); + + #endif } -#endif // NEEDS_HARDWARE_PWM #endif // __AVR__ diff --git a/Marlin/src/HAL/AVR/fastio.h b/Marlin/src/HAL/AVR/fastio.h index f77d4f666c..db6e598b86 100644 --- a/Marlin/src/HAL/AVR/fastio.h +++ b/Marlin/src/HAL/AVR/fastio.h @@ -211,32 +211,32 @@ enum ClockSource2 : char { // Set Clock Select bits // Ex: SET_CS3(PRESCALER_64); +#ifdef TCCR2 + #define HAS_TCCR2 1 +#endif #define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0)) #define _SET_CS0(V) _SET_CS(0,V) #define _SET_CS1(V) _SET_CS(1,V) -#ifdef TCCR2 - #define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20)) -#else - #define _SET_CS2(V) _SET_CS(2,V) -#endif #define _SET_CS3(V) _SET_CS(3,V) #define _SET_CS4(V) _SET_CS(4,V) #define _SET_CS5(V) _SET_CS(5,V) #define SET_CS0(V) _SET_CS0(CS_##V) #define SET_CS1(V) _SET_CS1(CS_##V) -#ifdef TCCR2 + +#if HAS_TCCR2 + #define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20)) #define SET_CS2(V) _SET_CS2(CS2_##V) #else + #define _SET_CS2(V) _SET_CS(2,V) #define SET_CS2(V) _SET_CS2(CS_##V) #endif + #define SET_CS3(V) _SET_CS3(CS_##V) #define SET_CS4(V) _SET_CS4(CS_##V) #define SET_CS5(V) _SET_CS5(CS_##V) #define SET_CS(T,V) SET_CS##T(V) // Runtime (see set_pwm_frequency) -#define _SET_CSn(TCCRnQ, V) do{ \ - (*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0)); \ - }while(0) +#define _SET_CSn(TCCRnQ, V) (*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0)) // Set Compare Mode bits // Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET); @@ -247,21 +247,15 @@ enum ClockSource2 : char { #define SET_COMC(T,V) SET_COM(T,C,V) #define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0) // Runtime (see set_pwm_duty) -#define _SET_COMnQ(TCCRnQ, Q, V) do{ \ - (*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q)))); \ - }while(0) +#define _SET_COMnQ(TCCRnQ, Q, V) (*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q)))) // Set OCRnQ register // Runtime (see set_pwm_duty): -#define _SET_OCRnQ(OCRnQ, Q, V) do{ \ - (*(OCRnQ)[(Q)] = (0x0000) | (int(V) & 0xFFFF)); \ - }while(0) +#define _SET_OCRnQ(OCRnQ, Q, V) (*(OCRnQ)[Q] = int(V) & 0xFFFF) // Set ICRn register (one per timer) // Runtime (see set_pwm_frequency) -#define _SET_ICRn(ICRn, V) do{ \ - (*(ICRn) = (0x0000) | (int(V) & 0xFFFF)); \ - }while(0) +#define _SET_ICRn(ICRn, V) (*(ICRn) = int(V) & 0xFFFF) // Set Noise Canceler bit // Ex: SET_ICNC(2,1) diff --git a/Marlin/src/HAL/AVR/inc/SanityCheck.h b/Marlin/src/HAL/AVR/inc/SanityCheck.h index 79809b8f61..2f80d1fee1 100644 --- a/Marlin/src/HAL/AVR/inc/SanityCheck.h +++ b/Marlin/src/HAL/AVR/inc/SanityCheck.h @@ -28,7 +28,7 @@ /** * Checks for FAST PWM */ -#if ENABLED(FAST_PWM_FAN) && (ENABLED(USE_OCR2A_AS_TOP) && defined(TCCR2)) +#if ALL(FAST_PWM_FAN, USE_OCR2A_AS_TOP, HAS_TCCR2) #error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2" #endif diff --git a/Marlin/src/HAL/AVR/pinsDebug.h b/Marlin/src/HAL/AVR/pinsDebug.h index fcbb7af3e1..0f564df987 100644 --- a/Marlin/src/HAL/AVR/pinsDebug.h +++ b/Marlin/src/HAL/AVR/pinsDebug.h @@ -102,7 +102,7 @@ void PRINT_ARRAY_NAME(uint8_t x) { return true; \ } else return false - +#define ABTEST(N) defined(TCCR##N##A) && defined(COM##N##A1) /** * Print a pin's PWM status. @@ -113,7 +113,7 @@ static bool pwm_status(uint8_t pin) { switch (digitalPinToTimer_DEBUG(pin)) { - #if defined(TCCR0A) && defined(COM0A1) + #if ABTEST(0) #ifdef TIMER0A #if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs PWM_CASE(0, A); @@ -122,20 +122,20 @@ static bool pwm_status(uint8_t pin) { PWM_CASE(0, B); #endif - #if defined(TCCR1A) && defined(COM1A1) + #if ABTEST(1) PWM_CASE(1, A); PWM_CASE(1, B); - #if defined(COM1C1) && defined(TIMER1C) - PWM_CASE(1, C); - #endif + #if defined(COM1C1) && defined(TIMER1C) + PWM_CASE(1, C); + #endif #endif - #if defined(TCCR2A) && defined(COM2A1) + #if ABTEST(2) PWM_CASE(2, A); PWM_CASE(2, B); #endif - #if defined(TCCR3A) && defined(COM3A1) + #if ABTEST(3) PWM_CASE(3, A); PWM_CASE(3, B); #ifdef COM3C1 @@ -149,7 +149,7 @@ static bool pwm_status(uint8_t pin) { PWM_CASE(4, C); #endif - #if defined(TCCR5A) && defined(COM5A1) + #if ABTEST(5) PWM_CASE(5, A); PWM_CASE(5, B); PWM_CASE(5, C); @@ -166,16 +166,16 @@ static bool pwm_status(uint8_t pin) { const volatile uint8_t* const PWM_other[][3] PROGMEM = { { &TCCR0A, &TCCR0B, &TIMSK0 }, { &TCCR1A, &TCCR1B, &TIMSK1 }, - #if defined(TCCR2A) && defined(COM2A1) + #if ABTEST(2) { &TCCR2A, &TCCR2B, &TIMSK2 }, #endif - #if defined(TCCR3A) && defined(COM3A1) + #if ABTEST(3) { &TCCR3A, &TCCR3B, &TIMSK3 }, #endif #ifdef TCCR4A { &TCCR4A, &TCCR4B, &TIMSK4 }, #endif - #if defined(TCCR5A) && defined(COM5A1) + #if ABTEST(5) { &TCCR5A, &TCCR5B, &TIMSK5 }, #endif }; @@ -195,11 +195,11 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = { { (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 }, #endif - #if defined(TCCR2A) && defined(COM2A1) + #if ABTEST(2) { &OCR2A, &OCR2B, 0 }, #endif - #if defined(TCCR3A) && defined(COM3A1) + #if ABTEST(3) #ifdef COM3C1 { (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C }, #else @@ -211,7 +211,7 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = { { (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C }, #endif - #if defined(TCCR5A) && defined(COM5A1) + #if ABTEST(5) { (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C }, #endif }; @@ -281,7 +281,7 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N - static void pwm_details(uint8_t pin) { switch (digitalPinToTimer_DEBUG(pin)) { - #if defined(TCCR0A) && defined(COM0A1) + #if ABTEST(0) #ifdef TIMER0A #if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs case TIMER0A: timer_prefix(0, 'A', 3); break; @@ -290,7 +290,7 @@ static void pwm_details(uint8_t pin) { case TIMER0B: timer_prefix(0, 'B', 3); break; #endif - #if defined(TCCR1A) && defined(COM1A1) + #if ABTEST(1) case TIMER1A: timer_prefix(1, 'A', 4); break; case TIMER1B: timer_prefix(1, 'B', 4); break; #if defined(COM1C1) && defined(TIMER1C) @@ -298,12 +298,12 @@ static void pwm_details(uint8_t pin) { #endif #endif - #if defined(TCCR2A) && defined(COM2A1) + #if ABTEST(2) case TIMER2A: timer_prefix(2, 'A', 3); break; case TIMER2B: timer_prefix(2, 'B', 3); break; #endif - #if defined(TCCR3A) && defined(COM3A1) + #if ABTEST(3) case TIMER3A: timer_prefix(3, 'A', 4); break; case TIMER3B: timer_prefix(3, 'B', 4); break; #ifdef COM3C1 @@ -317,7 +317,7 @@ static void pwm_details(uint8_t pin) { case TIMER4C: timer_prefix(4, 'C', 4); break; #endif - #if defined(TCCR5A) && defined(COM5A1) + #if ABTEST(5) case TIMER5A: timer_prefix(5, 'A', 4); break; case TIMER5B: timer_prefix(5, 'B', 4); break; case TIMER5C: timer_prefix(5, 'C', 4); break; @@ -351,7 +351,6 @@ static void pwm_details(uint8_t pin) { #endif } // pwm_details - #ifndef digitalRead_mod // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs int digitalRead_mod(const int8_t pin) { // same as digitalRead except the PWM stop section has been removed const uint8_t port = digitalPinToPort_DEBUG(pin); @@ -397,3 +396,5 @@ static void pwm_details(uint8_t pin) { #define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0) #define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0) + +#undef ABTEST diff --git a/Marlin/src/HAL/AVR/timers.h b/Marlin/src/HAL/AVR/timers.h index 82eb8b14b1..36b04eae0d 100644 --- a/Marlin/src/HAL/AVR/timers.h +++ b/Marlin/src/HAL/AVR/timers.h @@ -34,14 +34,14 @@ typedef uint16_t hal_timer_t; #define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 1 +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 1 #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 0 +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 0 #endif #define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0) @@ -64,7 +64,7 @@ typedef uint16_t hal_timer_t; FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) { switch (timer_num) { - case STEP_TIMER_NUM: + case MF_TIMER_STEP: // waveform generation = 0100 = CTC SET_WGM(1, CTC_OCRnA); @@ -84,7 +84,7 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) { TCNT1 = 0; break; - case TEMP_TIMER_NUM: + case MF_TIMER_TEMP: // Use timer0 for temperature measurement // Interleave temperature interrupt with millies interrupt OCR0B = 128; @@ -109,8 +109,8 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) { * (otherwise, characters will be lost due to UART overflow). * Then: Stepper, Endstops, Temperature, and -finally- all others. */ -#define HAL_timer_isr_prologue(TIMER_NUM) -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_prologue(T) +#define HAL_timer_isr_epilogue(T) /* 18 cycles maximum latency */ #ifndef HAL_STEP_TIMER_ISR diff --git a/Marlin/src/HAL/DUE/HAL.h b/Marlin/src/HAL/DUE/HAL.h index 92e26bcf43..96ab5d9808 100644 --- a/Marlin/src/HAL/DUE/HAL.h +++ b/Marlin/src/HAL/DUE/HAL.h @@ -144,6 +144,11 @@ inline void HAL_adc_init() {}//todo void HAL_adc_start_conversion(const uint8_t ch); uint16_t HAL_adc_get_result(); +// +// PWM +// +inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); } + // // Pin Map // @@ -168,16 +173,14 @@ void HAL_init(); // void _delay_ms(const int delay); +#pragma GCC diagnostic push #if GCC_VERSION <= 50000 - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif int freeMemory(); -#if GCC_VERSION <= 50000 - #pragma GCC diagnostic pop -#endif +#pragma GCC diagnostic pop #ifdef __cplusplus extern "C" { diff --git a/Marlin/src/HAL/DUE/Tone.cpp b/Marlin/src/HAL/DUE/Tone.cpp index 9beb602223..1ac81faaf0 100644 --- a/Marlin/src/HAL/DUE/Tone.cpp +++ b/Marlin/src/HAL/DUE/Tone.cpp @@ -38,17 +38,17 @@ volatile static int32_t toggles; void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) { tone_pin = _pin; toggles = 2 * frequency * duration / 1000; - HAL_timer_start(TONE_TIMER_NUM, 2 * frequency); + HAL_timer_start(MF_TIMER_TONE, 2 * frequency); } void noTone(const pin_t _pin) { - HAL_timer_disable_interrupt(TONE_TIMER_NUM); + HAL_timer_disable_interrupt(MF_TIMER_TONE); extDigitalWrite(_pin, LOW); } HAL_TONE_TIMER_ISR() { static uint8_t pin_state = 0; - HAL_timer_isr_prologue(TONE_TIMER_NUM); + HAL_timer_isr_prologue(MF_TIMER_TONE); if (toggles) { toggles--; diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp index 65bfd4f4e2..8268cf307e 100644 --- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp +++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp @@ -57,7 +57,7 @@ #include "../../../inc/MarlinConfigPre.h" -#if ENABLED(U8GLIB_ST7920) +#if IS_U8GLIB_ST7920 #include "../../../inc/MarlinConfig.h" #include "../../shared/Delay.h" @@ -182,5 +182,5 @@ uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va } #endif // LIGHTWEIGHT_UI -#endif // U8GLIB_ST7920 +#endif // IS_U8GLIB_ST7920 #endif // ARDUINO_ARCH_SAM diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp index 2b13c182d0..68e3e74a45 100644 --- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp +++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp @@ -57,7 +57,7 @@ #include "../../../inc/MarlinConfigPre.h" -#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920) +#if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920 #include "u8g_com_HAL_DUE_sw_spi_shared.h" @@ -141,5 +141,5 @@ uint8_t u8g_com_HAL_DUE_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void return 1; } -#endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920 +#endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920 #endif // ARDUINO_ARCH_SAM diff --git a/Marlin/src/HAL/DUE/timers.cpp b/Marlin/src/HAL/DUE/timers.cpp index 65073c510d..a7bf7fbd6d 100644 --- a/Marlin/src/HAL/DUE/timers.cpp +++ b/Marlin/src/HAL/DUE/timers.cpp @@ -42,7 +42,7 @@ // Private Variables // ------------------------ -const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = { +const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = { { TC0, 0, TC0_IRQn, 3}, // 0 - [servo timer5] { TC0, 1, TC1_IRQn, 0}, // 1 { TC0, 2, TC2_IRQn, 2}, // 2 - stepper @@ -66,9 +66,9 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = { */ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { - Tc *tc = TimerConfig[timer_num].pTimerRegs; - IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; - uint32_t channel = TimerConfig[timer_num].channel; + Tc *tc = timer_config[timer_num].pTimerRegs; + IRQn_Type irq = timer_config[timer_num].IRQ_Id; + uint32_t channel = timer_config[timer_num].channel; // Disable interrupt, just in case it was already enabled NVIC_DisableIRQ(irq); @@ -86,7 +86,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { pmc_set_writeprotect(false); pmc_enable_periph_clk((uint32_t)irq); - NVIC_SetPriority(irq, TimerConfig [timer_num].priority); + NVIC_SetPriority(irq, timer_config[timer_num].priority); // wave mode, reset counter on match with RC, TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); @@ -105,12 +105,12 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { } void HAL_timer_enable_interrupt(const uint8_t timer_num) { - IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; + IRQn_Type irq = timer_config[timer_num].IRQ_Id; NVIC_EnableIRQ(irq); } void HAL_timer_disable_interrupt(const uint8_t timer_num) { - IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; + IRQn_Type irq = timer_config[timer_num].IRQ_Id; NVIC_DisableIRQ(irq); // We NEED memory barriers to ensure Interrupts are actually disabled! @@ -125,7 +125,7 @@ static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) { } bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { - IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; + IRQn_Type irq = timer_config[timer_num].IRQ_Id; return NVIC_GetEnabledIRQ(irq); } diff --git a/Marlin/src/HAL/DUE/timers.h b/Marlin/src/HAL/DUE/timers.h index 0e1ea07cc2..e2932ff36f 100644 --- a/Marlin/src/HAL/DUE/timers.h +++ b/Marlin/src/HAL/DUE/timers.h @@ -37,35 +37,35 @@ typedef uint32_t hal_timer_t; #define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 2 // Timer Index for Stepper +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 2 // Timer Index for Stepper #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 4 // Timer Index for Temperature +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 4 // Timer Index for Temperature #endif -#ifndef TONE_TIMER_NUM - #define TONE_TIMER_NUM 6 // index of timer to use for beeper tones +#ifndef MF_TIMER_TONE + #define MF_TIMER_TONE 6 // index of timer to use for beeper tones #endif #define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency -#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) -#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs -#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) +#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) +#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs +#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) -#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer -#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE -#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US +#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer +#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE +#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) #ifndef HAL_STEP_TIMER_ISR #define HAL_STEP_TIMER_ISR() void TC2_Handler() @@ -92,7 +92,7 @@ typedef struct { // Public Variables // ------------------------ -extern const tTimerConfig TimerConfig[]; +extern const tTimerConfig timer_config[]; // ------------------------ // Public functions @@ -101,17 +101,17 @@ extern const tTimerConfig TimerConfig[]; void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency); FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) { - const tTimerConfig * const pConfig = &TimerConfig[timer_num]; + const tTimerConfig * const pConfig = &timer_config[timer_num]; pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC = compare; } FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { - const tTimerConfig * const pConfig = &TimerConfig[timer_num]; + const tTimerConfig * const pConfig = &timer_config[timer_num]; return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC; } FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { - const tTimerConfig * const pConfig = &TimerConfig[timer_num]; + const tTimerConfig * const pConfig = &timer_config[timer_num]; return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV; } @@ -120,9 +120,9 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num); FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) { - const tTimerConfig * const pConfig = &TimerConfig[timer_num]; + const tTimerConfig * const pConfig = &timer_config[timer_num]; // Reading the status register clears the interrupt flag pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR; } -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_epilogue(T) diff --git a/Marlin/src/HAL/DUE/upload_extra_script.py b/Marlin/src/HAL/DUE/upload_extra_script.py index d52a0a3642..4f7a494512 100644 --- a/Marlin/src/HAL/DUE/upload_extra_script.py +++ b/Marlin/src/HAL/DUE/upload_extra_script.py @@ -4,15 +4,16 @@ # Windows: bossac.exe # Other: leave unchanged # +import pioutil +if pioutil.is_pio_build(): + import platform + current_OS = platform.system() -import platform -current_OS = platform.system() + if current_OS == 'Windows': -if current_OS == 'Windows': + Import("env") - Import("env") - - # Use bossac.exe on Windows - env.Replace( - UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE" - ) + # Use bossac.exe on Windows + env.Replace( + UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE" + ) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 6a66d519b3..810e386894 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -276,7 +276,7 @@ void analogWrite(pin_t pin, int value) { idx = numPWMUsed; pwmPins[idx] = pin; // Start timer on first use - if (idx == 0) HAL_timer_start(PWM_TIMER_NUM, PWM_TIMER_FREQUENCY); + if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); ++numPWMUsed; } @@ -287,7 +287,7 @@ void analogWrite(pin_t pin, int value) { // Handle PWM timer interrupt HAL_PWM_TIMER_ISR() { - HAL_timer_isr_prologue(PWM_TIMER_NUM); + HAL_timer_isr_prologue(MF_TIMER_PWM); static uint8_t count = 0; @@ -301,7 +301,7 @@ HAL_PWM_TIMER_ISR() { // 128 for 7 Bit resolution count = (count + 1) & 0x7F; - HAL_timer_isr_epilogue(PWM_TIMER_NUM); + HAL_timer_isr_epilogue(MF_TIMER_PWM); } #endif // ARDUINO_ARCH_ESP32 diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index bc0ce4e037..8473e3c4e4 100644 --- a/Marlin/src/HAL/ESP32/HAL.h +++ b/Marlin/src/HAL/ESP32/HAL.h @@ -105,16 +105,14 @@ void HAL_reboot(); void _delay_ms(int delay); +#pragma GCC diagnostic push #if GCC_VERSION <= 50000 - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif int freeMemory(); -#if GCC_VERSION <= 50000 - #pragma GCC diagnostic pop -#endif +#pragma GCC diagnostic pop void analogWrite(pin_t pin, int value); @@ -131,6 +129,10 @@ void HAL_adc_init(); void HAL_adc_start_conversion(const uint8_t adc_pin); +// PWM +inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); } + +// Pin Map #define GET_PIN_MAP_PIN(index) index #define GET_PIN_MAP_INDEX(pin) pin #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) diff --git a/Marlin/src/HAL/ESP32/Tone.cpp b/Marlin/src/HAL/ESP32/Tone.cpp index 376c0f32e1..9c16cdde80 100644 --- a/Marlin/src/HAL/ESP32/Tone.cpp +++ b/Marlin/src/HAL/ESP32/Tone.cpp @@ -38,16 +38,16 @@ volatile static int32_t toggles; void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) { tone_pin = _pin; toggles = 2 * frequency * duration / 1000; - HAL_timer_start(TONE_TIMER_NUM, 2 * frequency); + HAL_timer_start(MF_TIMER_TONE, 2 * frequency); } void noTone(const pin_t _pin) { - HAL_timer_disable_interrupt(TONE_TIMER_NUM); + HAL_timer_disable_interrupt(MF_TIMER_TONE); WRITE(_pin, LOW); } HAL_TONE_TIMER_ISR() { - HAL_timer_isr_prologue(TONE_TIMER_NUM); + HAL_timer_isr_prologue(MF_TIMER_TONE); if (toggles) { toggles--; diff --git a/Marlin/src/HAL/ESP32/i2s.cpp b/Marlin/src/HAL/ESP32/i2s.cpp index 557ea319e6..3e77b65836 100644 --- a/Marlin/src/HAL/ESP32/i2s.cpp +++ b/Marlin/src/HAL/ESP32/i2s.cpp @@ -64,12 +64,9 @@ uint32_t i2s_port_data = 0; #define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) static inline void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) { - //if pin = -1, do not need to configure - if (gpio != -1) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); - gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT); - gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv); - } + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); + gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT); + gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv); } static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num) { @@ -256,13 +253,7 @@ int i2s_init() { I2S0.fifo_conf.dscr_en = 0; - I2S0.conf_chan.tx_chan_mod = ( - #if ENABLED(I2S_STEPPER_SPLIT_STREAM) - 4 - #else - 0 - #endif - ); + I2S0.conf_chan.tx_chan_mod = TERN(I2S_STEPPER_SPLIT_STREAM, 4, 0); I2S0.fifo_conf.tx_fifo_mod = 0; I2S0.conf.tx_mono = 0; @@ -313,9 +304,16 @@ int i2s_init() { xTaskCreatePinnedToCore(stepperTask, "StepperTask", 10000, nullptr, 1, nullptr, CONFIG_ARDUINO_RUNNING_CORE); // run I2S stepper task on same core as rest of Marlin // Route the i2s pins to the appropriate GPIO - gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0); - gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0); - gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0); + // If a pin is not defined, no need to configure + #if defined(I2S_DATA) && I2S_DATA >= 0 + gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0); + #endif + #if defined(I2S_BCK) && I2S_BCK >= 0 + gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0); + #endif + #if defined(I2S_WS) && I2S_WS >= 0 + gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0); + #endif // Start the I2S peripheral return i2s_start(I2S_NUM_0); diff --git a/Marlin/src/HAL/ESP32/timers.cpp b/Marlin/src/HAL/ESP32/timers.cpp index 57662a6658..df0065f453 100644 --- a/Marlin/src/HAL/ESP32/timers.cpp +++ b/Marlin/src/HAL/ESP32/timers.cpp @@ -41,7 +41,7 @@ static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1}; -const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = { +const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = { { TIMER_GROUP_0, TIMER_0, STEPPER_TIMER_PRESCALE, stepTC_Handler }, // 0 - Stepper { TIMER_GROUP_0, TIMER_1, TEMP_TIMER_PRESCALE, tempTC_Handler }, // 1 - Temperature { TIMER_GROUP_1, TIMER_0, PWM_TIMER_PRESCALE, pwmTC_Handler }, // 2 - PWM @@ -53,7 +53,7 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = { // ------------------------ void IRAM_ATTR timer_isr(void *para) { - const tTimerConfig& timer = TimerConfig[(int)para]; + const tTimerConfig& timer = timer_config[(int)para]; // Retrieve the interrupt status and the counter value // from the timer that reported the interrupt @@ -82,7 +82,7 @@ void IRAM_ATTR timer_isr(void *para) { * @param frequency frequency of the timer */ void HAL_timer_start(const uint8_t timer_num, uint32_t frequency) { - const tTimerConfig timer = TimerConfig[timer_num]; + const tTimerConfig timer = timer_config[timer_num]; timer_config_t config; config.divider = timer.divider; @@ -115,7 +115,7 @@ void HAL_timer_start(const uint8_t timer_num, uint32_t frequency) { * @param count threshold at which the interrupt is triggered */ void HAL_timer_set_compare(const uint8_t timer_num, hal_timer_t count) { - const tTimerConfig timer = TimerConfig[timer_num]; + const tTimerConfig timer = timer_config[timer_num]; timer_set_alarm_value(timer.group, timer.idx, count); } @@ -125,7 +125,7 @@ void HAL_timer_set_compare(const uint8_t timer_num, hal_timer_t count) { * @return the timer current threshold for the alarm to be triggered */ hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { - const tTimerConfig timer = TimerConfig[timer_num]; + const tTimerConfig timer = timer_config[timer_num]; uint64_t alarm_value; timer_get_alarm_value(timer.group, timer.idx, &alarm_value); @@ -139,7 +139,7 @@ hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { * @return the current counter of the alarm */ hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { - const tTimerConfig timer = TimerConfig[timer_num]; + const tTimerConfig timer = timer_config[timer_num]; uint64_t counter_value; timer_get_counter_value(timer.group, timer.idx, &counter_value); return counter_value; @@ -150,7 +150,7 @@ hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { * @param timer_num timer number to enable interrupts on */ void HAL_timer_enable_interrupt(const uint8_t timer_num) { - //const tTimerConfig timer = TimerConfig[timer_num]; + //const tTimerConfig timer = timer_config[timer_num]; //timer_enable_intr(timer.group, timer.idx); } @@ -159,12 +159,12 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num) { * @param timer_num timer number to disable interrupts on */ void HAL_timer_disable_interrupt(const uint8_t timer_num) { - //const tTimerConfig timer = TimerConfig[timer_num]; + //const tTimerConfig timer = timer_config[timer_num]; //timer_disable_intr(timer.group, timer.idx); } bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { - const tTimerConfig timer = TimerConfig[timer_num]; + const tTimerConfig timer = timer_config[timer_num]; return TG[timer.group]->int_ena.val | BIT(timer_num); } diff --git a/Marlin/src/HAL/ESP32/timers.h b/Marlin/src/HAL/ESP32/timers.h index a47697113d..266169848d 100644 --- a/Marlin/src/HAL/ESP32/timers.h +++ b/Marlin/src/HAL/ESP32/timers.h @@ -32,20 +32,20 @@ typedef uint64_t hal_timer_t; #define HAL_TIMER_TYPE_MAX 0xFFFFFFFFFFFFFFFFULL -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 0 // Timer Index for Stepper +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 0 // Timer Index for Stepper #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 1 // Timer Index for Temperature +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 1 // Timer Index for Temperature #endif -#ifndef PWM_TIMER_NUM - #define PWM_TIMER_NUM 2 // index of timer to use for PWM outputs +#ifndef MF_TIMER_PWM + #define MF_TIMER_PWM 2 // index of timer to use for PWM outputs #endif -#ifndef TONE_TIMER_NUM - #define TONE_TIMER_NUM 3 // index of timer for beeper tones +#ifndef MF_TIMER_TONE + #define MF_TIMER_TONE 3 // index of timer for beeper tones #endif #define HAL_TIMER_RATE APB_CLK_FREQ // frequency of timer peripherals @@ -79,12 +79,12 @@ typedef uint64_t hal_timer_t; #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) #ifndef HAL_TEMP_TIMER_ISR #define HAL_TEMP_TIMER_ISR() extern "C" void tempTC_Handler() @@ -121,7 +121,7 @@ typedef struct { // Public Variables // ------------------------ -extern const tTimerConfig TimerConfig[]; +extern const tTimerConfig timer_config[]; // ------------------------ // Public functions @@ -136,5 +136,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num); void HAL_timer_disable_interrupt(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num); -#define HAL_timer_isr_prologue(TIMER_NUM) -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_prologue(T) +#define HAL_timer_isr_epilogue(T) diff --git a/Marlin/src/HAL/LINUX/HAL.h b/Marlin/src/HAL/LINUX/HAL.h index 79639f4993..d7d3a92b73 100644 --- a/Marlin/src/HAL/LINUX/HAL.h +++ b/Marlin/src/HAL/LINUX/HAL.h @@ -79,16 +79,14 @@ extern MSerialT usb_serial; inline void HAL_init() {} // Utility functions +#pragma GCC diagnostic push #if GCC_VERSION <= 50000 - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif int freeMemory(); -#if GCC_VERSION <= 50000 - #pragma GCC diagnostic pop -#endif +#pragma GCC diagnostic pop // ADC #define HAL_ADC_VREF 5.0 @@ -103,6 +101,9 @@ void HAL_adc_enable_channel(const uint8_t ch); void HAL_adc_start_conversion(const uint8_t ch); uint16_t HAL_adc_get_result(); +// PWM +inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); } + // Reset source inline void HAL_clear_reset_source(void) {} inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; } diff --git a/Marlin/src/HAL/LINUX/timers.h b/Marlin/src/HAL/LINUX/timers.h index 1beaea95ab..a98ceb6f39 100644 --- a/Marlin/src/HAL/LINUX/timers.h +++ b/Marlin/src/HAL/LINUX/timers.h @@ -37,14 +37,14 @@ typedef uint32_t hal_timer_t; #define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 0 // Timer Index for Stepper +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 0 // Timer Index for Stepper #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 1 // Timer Index for Temperature +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 1 // Timer Index for Temperature #endif #define TEMP_TIMER_RATE 1000000 @@ -58,12 +58,12 @@ typedef uint32_t hal_timer_t; #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) #ifndef HAL_STEP_TIMER_ISR #define HAL_STEP_TIMER_ISR() extern "C" void TIMER0_IRQHandler() @@ -77,7 +77,6 @@ typedef uint32_t hal_timer_t; #define HAL_PWM_TIMER_ISR() extern "C" void TIMER3_IRQHandler() #define HAL_PWM_TIMER_IRQn - void HAL_timer_init(); void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency); @@ -93,5 +92,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num); void HAL_timer_disable_interrupt(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num); -#define HAL_timer_isr_prologue(TIMER_NUM) -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_prologue(T) +#define HAL_timer_isr_epilogue(T) diff --git a/Marlin/src/HAL/LPC1768/HAL.h b/Marlin/src/HAL/LPC1768/HAL.h index f241249804..348ea6b21a 100644 --- a/Marlin/src/HAL/LPC1768/HAL.h +++ b/Marlin/src/HAL/LPC1768/HAL.h @@ -123,16 +123,14 @@ extern DefaultSerial1 USBSerial; // // Utility functions // +#pragma GCC diagnostic push #if GCC_VERSION <= 50000 - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif int freeMemory(); -#if GCC_VERSION <= 50000 - #pragma GCC diagnostic pop -#endif +#pragma GCC diagnostic pop // // ADC API diff --git a/Marlin/src/HAL/LPC1768/eeprom_sdcard.cpp b/Marlin/src/HAL/LPC1768/eeprom_sdcard.cpp index 6570a599a4..1991d79719 100644 --- a/Marlin/src/HAL/LPC1768/eeprom_sdcard.cpp +++ b/Marlin/src/HAL/LPC1768/eeprom_sdcard.cpp @@ -90,15 +90,15 @@ bool PersistentStore::access_finish() { // to see errors that are happening in read_data / write_data static void debug_rw(const bool write, int &pos, const uint8_t *value, const size_t size, const FRESULT s, const size_t total=0) { #if ENABLED(DEBUG_SD_EEPROM_EMULATION) - PGM_P const rw_str = write ? PSTR("write") : PSTR("read"); + FSTR_P const rw_str = write ? F("write") : F("read"); SERIAL_CHAR(' '); - SERIAL_ECHOPGM_P(rw_str); + SERIAL_ECHOF(rw_str); SERIAL_ECHOLNPGM("_data(", pos, ",", *value, ",", size, ", ...)"); if (total) { SERIAL_ECHOPGM(" f_"); - SERIAL_ECHOPGM_P(rw_str); + SERIAL_ECHOF(rw_str); SERIAL_ECHOPGM("()=", s, "\n size=", size, "\n bytes_"); - SERIAL_ECHOLNPGM_P(write ? PSTR("written=") : PSTR("read="), total); + SERIAL_ECHOLNF(write ? F("written=") : F("read="), total); } else SERIAL_ECHOLNPGM(" f_lseek()=", s); diff --git a/Marlin/src/HAL/LPC1768/fast_pwm.cpp b/Marlin/src/HAL/LPC1768/fast_pwm.cpp index dd440b5e77..eae0e36b0b 100644 --- a/Marlin/src/HAL/LPC1768/fast_pwm.cpp +++ b/Marlin/src/HAL/LPC1768/fast_pwm.cpp @@ -22,18 +22,20 @@ #ifdef TARGET_LPC1768 #include "../../inc/MarlinConfigPre.h" - -#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM - #include -void set_pwm_frequency(const pin_t pin, int f_desired) { - LPC176x::pwm_set_frequency(pin, f_desired); -} - void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { - LPC176x::pwm_write_ratio(pin, invert ? 1.0f - (float)v / v_size : (float)v / v_size); + 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 } -#endif // NEEDS_HARDWARE_PWM +#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM + + void set_pwm_frequency(const pin_t pin, int f_desired) { + LPC176x::pwm_set_frequency(pin, f_desired); + } + +#endif + #endif // TARGET_LPC1768 diff --git a/Marlin/src/HAL/LPC1768/timers.cpp b/Marlin/src/HAL/LPC1768/timers.cpp index a7a40584da..bbb13f81da 100644 --- a/Marlin/src/HAL/LPC1768/timers.cpp +++ b/Marlin/src/HAL/LPC1768/timers.cpp @@ -40,7 +40,7 @@ void HAL_timer_init() { void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { switch (timer_num) { - case 0: + case MF_TIMER_STEP: LPC_TIM0->MCR = _BV(SBIT_MR0I) | _BV(SBIT_MR0R); // Match on MR0, reset on MR0, interrupts when NVIC enables them LPC_TIM0->MR0 = uint32_t(STEPPER_TIMER_RATE) / frequency; // Match value (period) to set frequency LPC_TIM0->TCR = _BV(SBIT_CNTEN); // Counter Enable @@ -49,7 +49,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { NVIC_EnableIRQ(TIMER0_IRQn); break; - case 1: + case MF_TIMER_TEMP: LPC_TIM1->MCR = _BV(SBIT_MR0I) | _BV(SBIT_MR0R); // Match on MR0, reset on MR0, interrupts when NVIC enables them LPC_TIM1->MR0 = uint32_t(TEMP_TIMER_RATE) / frequency; LPC_TIM1->TCR = _BV(SBIT_CNTEN); // Counter Enable diff --git a/Marlin/src/HAL/LPC1768/timers.h b/Marlin/src/HAL/LPC1768/timers.h index 4b63854685..78e856db28 100644 --- a/Marlin/src/HAL/LPC1768/timers.h +++ b/Marlin/src/HAL/LPC1768/timers.h @@ -60,17 +60,17 @@ typedef uint32_t hal_timer_t; #define HAL_TIMER_RATE ((F_CPU) / 4) // frequency of timers peripherals -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 0 // Timer Index for Stepper +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 0 // Timer Index for Stepper #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 1 // Timer Index for Temperature +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 1 // Timer Index for Temperature #endif -#ifndef PWM_TIMER_NUM - #define PWM_TIMER_NUM 3 // Timer Index for PWM +#ifndef MF_TIMER_PWM + #define MF_TIMER_PWM 3 // Timer Index for PWM #endif #define TEMP_TIMER_RATE 1000000 @@ -84,23 +84,23 @@ typedef uint32_t hal_timer_t; #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) #ifndef HAL_STEP_TIMER_ISR - #define HAL_STEP_TIMER_ISR() _HAL_TIMER_ISR(STEP_TIMER_NUM) + #define HAL_STEP_TIMER_ISR() _HAL_TIMER_ISR(MF_TIMER_STEP) #endif #ifndef HAL_TEMP_TIMER_ISR - #define HAL_TEMP_TIMER_ISR() _HAL_TIMER_ISR(TEMP_TIMER_NUM) + #define HAL_TEMP_TIMER_ISR() _HAL_TIMER_ISR(MF_TIMER_TEMP) #endif // Timer references by index -#define STEP_TIMER_PTR _HAL_TIMER(STEP_TIMER_NUM) -#define TEMP_TIMER_PTR _HAL_TIMER(TEMP_TIMER_NUM) +#define STEP_TIMER_PTR _HAL_TIMER(MF_TIMER_STEP) +#define TEMP_TIMER_PTR _HAL_TIMER(MF_TIMER_TEMP) // ------------------------ // Public functions @@ -110,38 +110,38 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency); FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) { switch (timer_num) { - case 0: STEP_TIMER_PTR->MR0 = compare; break; // Stepper Timer Match Register 0 - case 1: TEMP_TIMER_PTR->MR0 = compare; break; // Temp Timer Match Register 0 + case MF_TIMER_STEP: STEP_TIMER_PTR->MR0 = compare; break; // Stepper Timer Match Register 0 + case MF_TIMER_TEMP: TEMP_TIMER_PTR->MR0 = compare; break; // Temp Timer Match Register 0 } } FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { switch (timer_num) { - case 0: return STEP_TIMER_PTR->MR0; // Stepper Timer Match Register 0 - case 1: return TEMP_TIMER_PTR->MR0; // Temp Timer Match Register 0 + case MF_TIMER_STEP: return STEP_TIMER_PTR->MR0; // Stepper Timer Match Register 0 + case MF_TIMER_TEMP: return TEMP_TIMER_PTR->MR0; // Temp Timer Match Register 0 } return 0; } FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { switch (timer_num) { - case 0: return STEP_TIMER_PTR->TC; // Stepper Timer Count - case 1: return TEMP_TIMER_PTR->TC; // Temp Timer Count + case MF_TIMER_STEP: return STEP_TIMER_PTR->TC; // Stepper Timer Count + case MF_TIMER_TEMP: return TEMP_TIMER_PTR->TC; // Temp Timer Count } return 0; } FORCE_INLINE static void HAL_timer_enable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case 0: NVIC_EnableIRQ(TIMER0_IRQn); break; // Enable interrupt handler - case 1: NVIC_EnableIRQ(TIMER1_IRQn); break; // Enable interrupt handler + case MF_TIMER_STEP: NVIC_EnableIRQ(TIMER0_IRQn); break; // Enable interrupt handler + case MF_TIMER_TEMP: NVIC_EnableIRQ(TIMER1_IRQn); break; // Enable interrupt handler } } FORCE_INLINE static void HAL_timer_disable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case 0: NVIC_DisableIRQ(TIMER0_IRQn); break; // Disable interrupt handler - case 1: NVIC_DisableIRQ(TIMER1_IRQn); break; // Disable interrupt handler + case MF_TIMER_STEP: NVIC_DisableIRQ(TIMER0_IRQn); break; // Disable interrupt handler + case MF_TIMER_TEMP: NVIC_DisableIRQ(TIMER1_IRQn); break; // Disable interrupt handler } // We NEED memory barriers to ensure Interrupts are actually disabled! @@ -157,17 +157,17 @@ FORCE_INLINE static bool NVIC_GetEnableIRQ(IRQn_Type IRQn) { FORCE_INLINE static bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { switch (timer_num) { - case 0: return NVIC_GetEnableIRQ(TIMER0_IRQn); // Check if interrupt is enabled or not - case 1: return NVIC_GetEnableIRQ(TIMER1_IRQn); // Check if interrupt is enabled or not + case MF_TIMER_STEP: return NVIC_GetEnableIRQ(TIMER0_IRQn); // Check if interrupt is enabled or not + case MF_TIMER_TEMP: return NVIC_GetEnableIRQ(TIMER1_IRQn); // Check if interrupt is enabled or not } return false; } FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) { switch (timer_num) { - case 0: SBI(STEP_TIMER_PTR->IR, SBIT_CNTEN); break; - case 1: SBI(TEMP_TIMER_PTR->IR, SBIT_CNTEN); break; + case MF_TIMER_STEP: SBI(STEP_TIMER_PTR->IR, SBIT_CNTEN); break; + case MF_TIMER_TEMP: SBI(TEMP_TIMER_PTR->IR, SBIT_CNTEN); break; } } -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_epilogue(T) diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp index 039fa6769b..e159ebaa0c 100644 --- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp +++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp @@ -57,7 +57,7 @@ #include "../../../inc/MarlinConfigPre.h" -#if ENABLED(U8GLIB_ST7920) +#if IS_U8GLIB_ST7920 #include #include @@ -143,5 +143,5 @@ uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t ar return 1; } -#endif // U8GLIB_ST7920 +#endif // IS_U8GLIB_ST7920 #endif // TARGET_LPC1768 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 3308d03e79..f116a9b80a 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 @@ -57,7 +57,7 @@ #include "../../../inc/MarlinConfigPre.h" -#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920) +#if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920 #include #include "../../shared/HAL_SPI.h" @@ -205,5 +205,5 @@ uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, return 1; } -#endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920 +#endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920 #endif // TARGET_LPC1768 diff --git a/Marlin/src/HAL/LPC1768/upload_extra_script.py b/Marlin/src/HAL/LPC1768/upload_extra_script.py index fb3aaef7cd..7975f151f7 100755 --- a/Marlin/src/HAL/LPC1768/upload_extra_script.py +++ b/Marlin/src/HAL/LPC1768/upload_extra_script.py @@ -1,123 +1,127 @@ # -# sets output_port +# upload_extra_script.py +# set the output_port # if target_filename is found then that drive is used # else if target_drive is found then that drive is used # from __future__ import print_function -target_filename = "FIRMWARE.CUR" -target_drive = "REARM" +import pioutil +if pioutil.is_pio_build(): -import os,getpass,platform + target_filename = "FIRMWARE.CUR" + target_drive = "REARM" -current_OS = platform.system() -Import("env") + import os,getpass,platform -def print_error(e): - print('\nUnable to find destination disk (%s)\n' \ - 'Please select it in platformio.ini using the upload_port keyword ' \ - '(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \ - 'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \ - %(e, env.get('PIOENV'))) + current_OS = platform.system() + Import("env") -def before_upload(source, target, env): - try: - # - # Find a disk for upload - # - upload_disk = 'Disk not found' - target_file_found = False - target_drive_found = False - if current_OS == 'Windows': + def print_error(e): + print('\nUnable to find destination disk (%s)\n' \ + 'Please select it in platformio.ini using the upload_port keyword ' \ + '(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \ + 'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \ + %(e, env.get('PIOENV'))) + + def before_upload(source, target, env): + try: + # + # Find a disk for upload # - # platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:' - # Windows - doesn't care about the disk's name, only cares about the drive letter - import subprocess,string - from ctypes import windll + upload_disk = 'Disk not found' + target_file_found = False + target_drive_found = False + if current_OS == 'Windows': + # + # platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:' + # Windows - doesn't care about the disk's name, only cares about the drive letter + import subprocess,string + from ctypes import windll - # getting list of drives - # https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python - drives = [] - bitmask = windll.kernel32.GetLogicalDrives() - for letter in string.ascii_uppercase: - if bitmask & 1: - drives.append(letter) - bitmask >>= 1 + # getting list of drives + # https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python + drives = [] + bitmask = windll.kernel32.GetLogicalDrives() + for letter in string.ascii_uppercase: + if bitmask & 1: + drives.append(letter) + bitmask >>= 1 - for drive in drives: - final_drive_name = drive + ':\\' - # print ('disc check: {}'.format(final_drive_name)) - try: - volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT)) - except Exception as e: - print ('error:{}'.format(e)) - continue - else: - if target_drive in volume_info and not target_file_found: # set upload if not found target file yet - target_drive_found = True - upload_disk = final_drive_name - if target_filename in volume_info: - if not target_file_found: + for drive in drives: + final_drive_name = drive + ':\\' + # print ('disc check: {}'.format(final_drive_name)) + try: + volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT)) + except Exception as e: + print ('error:{}'.format(e)) + continue + else: + if target_drive in volume_info and not target_file_found: # set upload if not found target file yet + target_drive_found = True upload_disk = final_drive_name - target_file_found = True + if target_filename in volume_info: + if not target_file_found: + upload_disk = final_drive_name + target_file_found = True - elif current_OS == 'Linux': - # - # platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive' - # - drives = os.listdir(os.path.join(os.sep, 'media', getpass.getuser())) - if target_drive in drives: # If target drive is found, use it. - target_drive_found = True - upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), target_drive) + os.sep - else: + elif current_OS == 'Linux': + # + # platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive' + # + drives = os.listdir(os.path.join(os.sep, 'media', getpass.getuser())) + if target_drive in drives: # If target drive is found, use it. + target_drive_found = True + upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), target_drive) + os.sep + else: + for drive in drives: + try: + files = os.listdir(os.path.join(os.sep, 'media', getpass.getuser(), drive)) + except: + continue + else: + if target_filename in files: + upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), drive) + os.sep + target_file_found = True + break + # + # set upload_port to drive if found + # + + if target_file_found or target_drive_found: + env.Replace( + UPLOAD_FLAGS="-P$UPLOAD_PORT" + ) + + elif current_OS == 'Darwin': # MAC + # + # platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive' + # + drives = os.listdir('/Volumes') # human readable names + if target_drive in drives and not target_file_found: # set upload if not found target file yet + target_drive_found = True + upload_disk = '/Volumes/' + target_drive + '/' for drive in drives: try: - files = os.listdir(os.path.join(os.sep, 'media', getpass.getuser(), drive)) + filenames = os.listdir('/Volumes/' + drive + '/') # will get an error if the drive is protected except: continue else: - if target_filename in files: - upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), drive) + os.sep + if target_filename in filenames: + if not target_file_found: + upload_disk = '/Volumes/' + drive + '/' target_file_found = True - break - # - # set upload_port to drive if found - # - if target_file_found or target_drive_found: - env.Replace( - UPLOAD_FLAGS="-P$UPLOAD_PORT" - ) - - elif current_OS == 'Darwin': # MAC # - # platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive' + # Set upload_port to drive if found # - drives = os.listdir('/Volumes') # human readable names - if target_drive in drives and not target_file_found: # set upload if not found target file yet - target_drive_found = True - upload_disk = '/Volumes/' + target_drive + '/' - for drive in drives: - try: - filenames = os.listdir('/Volumes/' + drive + '/') # will get an error if the drive is protected - except: - continue - else: - if target_filename in filenames: - if not target_file_found: - upload_disk = '/Volumes/' + drive + '/' - target_file_found = True - - # - # Set upload_port to drive if found - # - if target_file_found or target_drive_found: - env.Replace(UPLOAD_PORT=upload_disk) - print('\nUpload disk: ', upload_disk, '\n') - else: - print_error('Autodetect Error') + if target_file_found or target_drive_found: + env.Replace(UPLOAD_PORT=upload_disk) + print('\nUpload disk: ', upload_disk, '\n') + else: + print_error('Autodetect Error') - except Exception as e: - print_error(str(e)) + except Exception as e: + print_error(str(e)) -env.AddPreAction("upload", before_upload) + env.AddPreAction("upload", before_upload) diff --git a/Marlin/src/HAL/NATIVE_SIM/HAL.h b/Marlin/src/HAL/NATIVE_SIM/HAL.h index 235c24808c..436b4b4daa 100644 --- a/Marlin/src/HAL/NATIVE_SIM/HAL.h +++ b/Marlin/src/HAL/NATIVE_SIM/HAL.h @@ -133,10 +133,15 @@ void HAL_adc_enable_channel(const uint8_t ch); void HAL_adc_start_conversion(const uint8_t ch); uint16_t HAL_adc_get_result(); +// PWM +inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); } + // Reset source inline void HAL_clear_reset_source(void) {} inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; } +void HAL_reboot(); + /* ---------------- Delay in cycles */ #define DELAY_CYCLES(x) Kernel::delayCycles(x) diff --git a/Marlin/src/HAL/NATIVE_SIM/timers.h b/Marlin/src/HAL/NATIVE_SIM/timers.h index c61eb29e76..cedfdb62d6 100644 --- a/Marlin/src/HAL/NATIVE_SIM/timers.h +++ b/Marlin/src/HAL/NATIVE_SIM/timers.h @@ -37,17 +37,17 @@ typedef uint64_t hal_timer_t; #define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 0 // Timer Index for Stepper +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 0 // Timer Index for Stepper #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 1 // Timer Index for Temperature +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 1 // Timer Index for Temperature #endif -#ifndef SYSTICK_TIMER_NUM - #define SYSTICK_TIMER_NUM 2 // Timer Index for Systick +#ifndef MF_TIMER_SYSTICK + #define MF_TIMER_SYSTICK 2 // Timer Index for Systick #endif #define SYSTICK_TIMER_FREQUENCY 1000 @@ -62,12 +62,12 @@ typedef uint64_t hal_timer_t; #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) #ifndef HAL_STEP_TIMER_ISR #define HAL_STEP_TIMER_ISR() extern "C" void TIMER0_IRQHandler() @@ -87,5 +87,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num); void HAL_timer_disable_interrupt(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num); -#define HAL_timer_isr_prologue(TIMER_NUM) -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_prologue(T) +#define HAL_timer_isr_epilogue(T) diff --git a/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_st7920_sw_spi.cpp b/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_st7920_sw_spi.cpp index c77c3d30f0..c384cdd751 100644 --- a/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_st7920_sw_spi.cpp +++ b/Marlin/src/HAL/NATIVE_SIM/u8g/u8g_com_st7920_sw_spi.cpp @@ -57,7 +57,7 @@ #include "../../../inc/MarlinConfig.h" -#if ENABLED(U8GLIB_ST7920) +#if IS_U8GLIB_ST7920 #include #include "../../shared/Delay.h" @@ -167,5 +167,5 @@ uint8_t u8g_com_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void } #endif -#endif // U8GLIB_ST7920 +#endif // IS_U8GLIB_ST7920 #endif // TARGET_LPC1768 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 085954803c..7be84580b1 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 @@ -57,7 +57,7 @@ #include "../../../inc/MarlinConfig.h" -#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920) +#if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920 #undef SPI_SPEED #define SPI_SPEED 2 // About 2 MHz @@ -208,8 +208,11 @@ uint8_t u8g_com_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_pt } #endif -#elif !ANY(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI, HAS_MARLINUI_HD44780) && HAS_MARLINUI_U8GLIB +#elif NONE(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI, HAS_MARLINUI_HD44780) && HAS_MARLINUI_U8GLIB + #include uint8_t u8g_com_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {return 0;} -#endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920 + +#endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920 + #endif // __PLAT_NATIVE_SIM__ diff --git a/Marlin/src/HAL/SAMD51/HAL.h b/Marlin/src/HAL/SAMD51/HAL.h index 491c3f82c4..c262752a8d 100644 --- a/Marlin/src/HAL/SAMD51/HAL.h +++ b/Marlin/src/HAL/SAMD51/HAL.h @@ -127,6 +127,11 @@ void HAL_adc_init(); void HAL_adc_start_conversion(const uint8_t adc_pin); +// +// PWM +// +inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); } + // // Pin Map // @@ -153,16 +158,14 @@ void HAL_idletask(); // FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); } +#pragma GCC diagnostic push #if GCC_VERSION <= 50000 - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif int freeMemory(); -#if GCC_VERSION <= 50000 - #pragma GCC diagnostic pop -#endif +#pragma GCC diagnostic pop #ifdef __cplusplus extern "C" { diff --git a/Marlin/src/HAL/SAMD51/Servo.cpp b/Marlin/src/HAL/SAMD51/Servo.cpp index 9bab8e89be..23ab21c615 100644 --- a/Marlin/src/HAL/SAMD51/Servo.cpp +++ b/Marlin/src/HAL/SAMD51/Servo.cpp @@ -53,7 +53,7 @@ static volatile int8_t currentServoIndex[_Nbr_16timers]; // index for the servo being pulsed for each timer (or -1 if refresh interval) FORCE_INLINE static uint16_t getTimerCount() { - Tc * const tc = TimerConfig[SERVO_TC].pTc; + Tc * const tc = timer_config[SERVO_TC].pTc; tc->COUNT16.CTRLBSET.reg = TC_CTRLBCLR_CMD_READSYNC; SYNC(tc->COUNT16.SYNCBUSY.bit.CTRLB || tc->COUNT16.SYNCBUSY.bit.COUNT); @@ -65,7 +65,7 @@ FORCE_INLINE static uint16_t getTimerCount() { // Interrupt handler for the TC // ---------------------------- HAL_SERVO_TIMER_ISR() { - Tc * const tc = TimerConfig[SERVO_TC].pTc; + Tc * const tc = timer_config[SERVO_TC].pTc; const timer16_Sequence_t timer = #ifndef _useTimer1 _timer2 @@ -125,7 +125,7 @@ HAL_SERVO_TIMER_ISR() { } void initISR(timer16_Sequence_t timer) { - Tc * const tc = TimerConfig[SERVO_TC].pTc; + Tc * const tc = timer_config[SERVO_TC].pTc; const uint8_t tcChannel = TIMER_TCCHANNEL(timer); static bool initialized = false; // Servo TC has been initialized @@ -202,7 +202,7 @@ void initISR(timer16_Sequence_t timer) { } void finISR(timer16_Sequence_t timer) { - Tc * const tc = TimerConfig[SERVO_TC].pTc; + Tc * const tc = timer_config[SERVO_TC].pTc; const uint8_t tcChannel = TIMER_TCCHANNEL(timer); // Disable the match channel interrupt request diff --git a/Marlin/src/HAL/SAMD51/inc/SanityCheck.h b/Marlin/src/HAL/SAMD51/inc/SanityCheck.h index 38c6dd9e08..1b876c947d 100644 --- a/Marlin/src/HAL/SAMD51/inc/SanityCheck.h +++ b/Marlin/src/HAL/SAMD51/inc/SanityCheck.h @@ -36,7 +36,7 @@ #error "OnBoard SPI BUS can't be shared with other devices." #endif -#if SERVO_TC == RTC_TIMER_NUM +#if SERVO_TC == MF_TIMER_RTC #error "Servos can't use RTC timer" #endif diff --git a/Marlin/src/HAL/SAMD51/timers.cpp b/Marlin/src/HAL/SAMD51/timers.cpp index 7a535299db..ce13dd231e 100644 --- a/Marlin/src/HAL/SAMD51/timers.cpp +++ b/Marlin/src/HAL/SAMD51/timers.cpp @@ -31,13 +31,13 @@ // Local defines // -------------------------------------------------------------------------- -#define NUM_HARDWARE_TIMERS 8 +#define NUM_HARDWARE_TIMERS 9 // -------------------------------------------------------------------------- // Private Variables // -------------------------------------------------------------------------- -const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS+1] = { +const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = { { {.pTc=TC0}, TC0_IRQn, TC_PRIORITY(0) }, // 0 - stepper (assigned priority 2) { {.pTc=TC1}, TC1_IRQn, TC_PRIORITY(1) }, // 1 - stepper (needed by 32 bit timers) { {.pTc=TC2}, TC2_IRQn, 5 }, // 2 - tone (reserved by framework and fixed assigned priority 5) @@ -67,13 +67,13 @@ FORCE_INLINE void Disable_Irq(IRQn_Type irq) { // -------------------------------------------------------------------------- void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { - IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; + IRQn_Type irq = timer_config[timer_num].IRQ_Id; // Disable interrupt, just in case it was already enabled Disable_Irq(irq); - if (timer_num == RTC_TIMER_NUM) { - Rtc * const rtc = TimerConfig[timer_num].pRtc; + if (timer_num == MF_TIMER_RTC) { + Rtc * const rtc = timer_config[timer_num].pRtc; // Disable timer interrupt rtc->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0; @@ -101,7 +101,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { SYNC(rtc->MODE0.SYNCBUSY.bit.ENABLE); } else { - Tc * const tc = TimerConfig[timer_num].pTc; + Tc * const tc = timer_config[timer_num].pTc; // Disable timer interrupt tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt @@ -141,17 +141,17 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { } // Finally, enable IRQ - NVIC_SetPriority(irq, TimerConfig[timer_num].priority); + NVIC_SetPriority(irq, timer_config[timer_num].priority); NVIC_EnableIRQ(irq); } void HAL_timer_enable_interrupt(const uint8_t timer_num) { - const IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; + const IRQn_Type irq = timer_config[timer_num].IRQ_Id; NVIC_EnableIRQ(irq); } void HAL_timer_disable_interrupt(const uint8_t timer_num) { - const IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; + const IRQn_Type irq = timer_config[timer_num].IRQ_Id; Disable_Irq(irq); } @@ -161,7 +161,7 @@ static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) { } bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { - const IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; + const IRQn_Type irq = timer_config[timer_num].IRQ_Id; return NVIC_GetEnabledIRQ(irq); } diff --git a/Marlin/src/HAL/SAMD51/timers.h b/Marlin/src/HAL/SAMD51/timers.h index dc6e38b730..86e980c566 100644 --- a/Marlin/src/HAL/SAMD51/timers.h +++ b/Marlin/src/HAL/SAMD51/timers.h @@ -25,21 +25,22 @@ // -------------------------------------------------------------------------- // Defines // -------------------------------------------------------------------------- -#define RTC_TIMER_NUM 8 // This is not a TC but a RTC typedef uint32_t hal_timer_t; #define HAL_TIMER_TYPE_MAX 0xFFFFFFFF #define HAL_TIMER_RATE F_CPU // frequency of timers peripherals -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 0 // Timer Index for Stepper +#define MF_TIMER_RTC 8 // This is not a TC but a RTC + +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 0 // Timer Index for Stepper #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM RTC_TIMER_NUM // Timer Index for Temperature +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP MF_TIMER_RTC // Timer Index for Temperature #endif #define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency @@ -52,30 +53,29 @@ typedef uint32_t hal_timer_t; #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) -#define TC_PRIORITY(t) t == SERVO_TC ? 1 \ - : (t == STEP_TIMER_NUM || t == PULSE_TIMER_NUM) ? 2 \ - : (t == TEMP_TIMER_NUM) ? 6 \ - : 7 +#define TC_PRIORITY(t) ( t == SERVO_TC ? 1 \ + : (t == MF_TIMER_STEP || t == MF_TIMER_PULSE) ? 2 \ + : (t == MF_TIMER_TEMP) ? 6 : 7 ) #define _TC_HANDLER(t) void TC##t##_Handler() #define TC_HANDLER(t) _TC_HANDLER(t) #ifndef HAL_STEP_TIMER_ISR - #define HAL_STEP_TIMER_ISR() TC_HANDLER(STEP_TIMER_NUM) + #define HAL_STEP_TIMER_ISR() TC_HANDLER(MF_TIMER_STEP) #endif -#if STEP_TIMER_NUM != PULSE_TIMER_NUM - #define HAL_PULSE_TIMER_ISR() TC_HANDLER(PULSE_TIMER_NUM) +#if MF_TIMER_STEP != MF_TIMER_PULSE + #define HAL_PULSE_TIMER_ISR() TC_HANDLER(MF_TIMER_PULSE) #endif -#if TEMP_TIMER_NUM == RTC_TIMER_NUM +#if MF_TIMER_TEMP == MF_TIMER_RTC #define HAL_TEMP_TIMER_ISR() void RTC_Handler() #else - #define HAL_TEMP_TIMER_ISR() TC_HANDLER(TEMP_TIMER_NUM) + #define HAL_TEMP_TIMER_ISR() TC_HANDLER(MF_TIMER_TEMP) #endif // -------------------------------------------------------------------------- @@ -95,7 +95,7 @@ typedef struct { // Public Variables // -------------------------------------------------------------------------- -extern const tTimerConfig TimerConfig[]; +extern const tTimerConfig timer_config[]; // -------------------------------------------------------------------------- // Public functions @@ -104,20 +104,20 @@ extern const tTimerConfig TimerConfig[]; void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency); FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) { - // Should never be called with timer RTC_TIMER_NUM - Tc * const tc = TimerConfig[timer_num].pTc; + // Should never be called with timer MF_TIMER_RTC + Tc * const tc = timer_config[timer_num].pTc; tc->COUNT32.CC[0].reg = compare; } FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { - // Should never be called with timer RTC_TIMER_NUM - Tc * const tc = TimerConfig[timer_num].pTc; + // Should never be called with timer MF_TIMER_RTC + Tc * const tc = timer_config[timer_num].pTc; return (hal_timer_t)tc->COUNT32.CC[0].reg; } FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { - // Should never be called with timer RTC_TIMER_NUM - Tc * const tc = TimerConfig[timer_num].pTc; + // Should never be called with timer MF_TIMER_RTC + Tc * const tc = timer_config[timer_num].pTc; tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_CMD_READSYNC; SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB || tc->COUNT32.SYNCBUSY.bit.COUNT); return tc->COUNT32.COUNT.reg; @@ -128,13 +128,13 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num); FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) { - if (timer_num == RTC_TIMER_NUM) { - Rtc * const rtc = TimerConfig[timer_num].pRtc; + if (timer_num == MF_TIMER_RTC) { + Rtc * const rtc = timer_config[timer_num].pRtc; // Clear interrupt flag rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0; } else { - Tc * const tc = TimerConfig[timer_num].pTc; + Tc * const tc = timer_config[timer_num].pTc; // Clear interrupt flag tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF; } diff --git a/Marlin/src/HAL/STM32/HAL.cpp b/Marlin/src/HAL/STM32/HAL.cpp index a04a24c112..0920a72ec1 100644 --- a/Marlin/src/HAL/STM32/HAL.cpp +++ b/Marlin/src/HAL/STM32/HAL.cpp @@ -154,7 +154,7 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) { HAL_adc_result = analogRe uint16_t HAL_adc_get_result() { return HAL_adc_result; } // Reset the system to initiate a firmware flash -void flashFirmware(const int16_t) { HAL_reboot(); } +WEAK void flashFirmware(const int16_t) { HAL_reboot(); } // Maple Compatibility volatile uint32_t systick_uptime_millis = 0; diff --git a/Marlin/src/HAL/STM32/HAL.h b/Marlin/src/HAL/STM32/HAL.h index a68e8a8c0e..adaf14223f 100644 --- a/Marlin/src/HAL/STM32/HAL.h +++ b/Marlin/src/HAL/STM32/HAL.h @@ -130,7 +130,11 @@ // Types // ------------------------ -typedef int16_t pin_t; +#ifdef STM32G0B1xx + typedef int32_t pin_t; +#else + typedef int16_t pin_t; +#endif #define HAL_SERVO_LIB libServo #define PAUSE_SERVO_OUTPUT() libServo::pause_all_servos() diff --git a/Marlin/src/HAL/STM32/HAL_MinSerial.cpp b/Marlin/src/HAL/STM32/HAL_MinSerial.cpp index 29826a890d..b6e86b72da 100644 --- a/Marlin/src/HAL/STM32/HAL_MinSerial.cpp +++ b/Marlin/src/HAL/STM32/HAL_MinSerial.cpp @@ -135,7 +135,7 @@ void install_min_serial() { HAL_min_serial_out = &TX; } -#if DISABLED(DYNAMIC_VECTORTABLE) && DISABLED(STM32F0xx) // Cortex M0 can't jump to a symbol that's too far from the current function, so we work around this in exception_arm.cpp +#if NONE(DYNAMIC_VECTORTABLE, STM32F0xx, STM32G0xx) // Cortex M0 can't jump to a symbol that's too far from the current function, so we work around this in exception_arm.cpp extern "C" { __attribute__((naked)) void JumpHandler_ASM() { __asm__ __volatile__ ( diff --git a/Marlin/src/HAL/STM32/MarlinSPI.cpp b/Marlin/src/HAL/STM32/MarlinSPI.cpp index 7078d210dc..f7c603d77e 100644 --- a/Marlin/src/HAL/STM32/MarlinSPI.cpp +++ b/Marlin/src/HAL/STM32/MarlinSPI.cpp @@ -114,16 +114,19 @@ byte MarlinSPI::transfer(uint8_t _data) { return rxData; } +__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); } +__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); } + uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) { const uint8_t ff = 0xFF; - //if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) //only enable if disabled + //if (!LL_SPI_IsEnabled(_spi.handle)) // only enable if disabled __HAL_SPI_ENABLE(&_spi.handle); if (receiveBuf) { setupDma(_spi.handle, _dmaRx, DMA_PERIPH_TO_MEMORY, true); HAL_DMA_Start(&_dmaRx, (uint32_t)&(_spi.handle.Instance->DR), (uint32_t)receiveBuf, length); - SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_RXDMAEN); /* Enable Rx DMA Request */ + LL_SPI_EnableDMAReq_RX(_spi.handle.Instance); // Enable Rx DMA Request } // check for 2 lines transfer @@ -136,7 +139,7 @@ uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16 if (transmitBuf) { setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, mincTransmit); HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length); - SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */ + LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request } if (transmitBuf) { @@ -160,7 +163,7 @@ uint8_t MarlinSPI::dmaSend(const void * transmitBuf, uint16_t length, bool minc) setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, minc); HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length); __HAL_SPI_ENABLE(&_spi.handle); - SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */ + LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY); HAL_DMA_Abort(&_dmaTx); // DeInit objects diff --git a/Marlin/src/HAL/STM32/fast_pwm.cpp b/Marlin/src/HAL/STM32/fast_pwm.cpp index 917e12615f..b1bea5ce20 100644 --- a/Marlin/src/HAL/STM32/fast_pwm.cpp +++ b/Marlin/src/HAL/STM32/fast_pwm.cpp @@ -24,39 +24,60 @@ #ifdef HAL_STM32 -#include "../../inc/MarlinConfigPre.h" +#include "../../inc/MarlinConfig.h" -#if NEEDS_HARDWARE_PWM +// Array to support sticky frequency sets per timer +static uint16_t timer_freq[TIMER_NUM]; -#include "HAL.h" -#include "timers.h" +void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { + if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer + const PinName pin_name = digitalPinToPinName(pin); + TIM_TypeDef * const Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); -void set_pwm_frequency(const pin_t pin, int f_desired) { - if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer + const timer_index_t index = get_timer_index(Instance); + const bool needs_freq = (HardwareTimer_Handle[index] == nullptr); + if (needs_freq) // A new instance must be set to the default frequency of PWM_FREQUENCY + HardwareTimer_Handle[index]->__this = new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM)); - PinName pin_name = digitalPinToPinName(pin); - TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance + HardwareTimer * const HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this); + const uint32_t channel = STM_PIN_CHANNEL(pinmap_function(pin_name, PinMap_PWM)); + const TimerModes_t previousMode = HT->getMode(channel); + if (previousMode != TIMER_OUTPUT_COMPARE_PWM1) + HT->setMode(channel, TIMER_OUTPUT_COMPARE_PWM1, pin); - LOOP_S_L_N(i, 0, NUM_HARDWARE_TIMERS) // Protect used timers - if (timer_instance[i] && timer_instance[i]->getHandle()->Instance == Instance) - return; + if (needs_freq && timer_freq[index] == 0) // If the timer is unconfigured and no freq is set then default PWM_FREQUENCY + set_pwm_frequency(pin_name, PWM_FREQUENCY); // Set the frequency and save the value to the assigned index no. - pwm_start(pin_name, f_desired, 0, RESOLUTION_8B_COMPARE_FORMAT); + // Note the resolution is sticky here, the input can be upto 16 bits and that would require RESOLUTION_16B_COMPARE_FORMAT (16) + // If such a need were to manifest then we would need to calc the resolution based on the v_size parameter and add code for it. + const uint16_t value = invert ? v_size - v : v; + HT->setCaptureCompare(channel, value, RESOLUTION_8B_COMPARE_FORMAT); // Sets the duty, the calc is done in the library :) + pinmap_pinout(pin_name, PinMap_PWM); // Make sure the pin output state is set. + if (previousMode != TIMER_OUTPUT_COMPARE_PWM1) HT->resume(); } -void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { - PinName pin_name = digitalPinToPinName(pin); - TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); - uint16_t adj_val = Instance->ARR * v / v_size; - if (invert) adj_val = Instance->ARR - adj_val; - - switch (get_pwm_channel(pin_name)) { - case TIM_CHANNEL_1: LL_TIM_OC_SetCompareCH1(Instance, adj_val); break; - case TIM_CHANNEL_2: LL_TIM_OC_SetCompareCH2(Instance, adj_val); break; - case TIM_CHANNEL_3: LL_TIM_OC_SetCompareCH3(Instance, adj_val); break; - case TIM_CHANNEL_4: LL_TIM_OC_SetCompareCH4(Instance, adj_val); break; - } +void set_pwm_frequency(const pin_t pin, int f_desired) { + if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer + const PinName pin_name = digitalPinToPinName(pin); + TIM_TypeDef * const Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance + const timer_index_t index = get_timer_index(Instance); + + // Protect used timers. + #ifdef STEP_TIMER + if (index == TIMER_INDEX(STEP_TIMER)) return; + #endif + #ifdef TEMP_TIMER + if (index == TIMER_INDEX(TEMP_TIMER)) return; + #endif + #if defined(PULSE_TIMER) && MF_TIMER_PULSE != MF_TIMER_STEP + if (index == TIMER_INDEX(PULSE_TIMER)) return; + #endif + + if (HardwareTimer_Handle[index] == nullptr) // If frequency is set before duty we need to create a handle here. + HardwareTimer_Handle[index]->__this = new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM)); + HardwareTimer * const HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this); + HT->setOverflow(f_desired, HERTZ_FORMAT); + timer_freq[index] = f_desired; // Save the last frequency so duty will not set the default for this timer number. } -#endif // NEEDS_HARDWARE_PWM #endif // HAL_STM32 diff --git a/Marlin/src/HAL/STM32/tft/tft_spi.cpp b/Marlin/src/HAL/STM32/tft/tft_spi.cpp index 790513e7ed..4ad35cee8b 100644 --- a/Marlin/src/HAL/STM32/tft/tft_spi.cpp +++ b/Marlin/src/HAL/STM32/tft/tft_spi.cpp @@ -161,11 +161,11 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) { for (i = 0; i < 4; i++) { #if TFT_MISO_PIN != TFT_MOSI_PIN //if (hspi->Init.Direction == SPI_DIRECTION_2LINES) { - while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {} + while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {} SPIx.Instance->DR = 0; //} #endif - while ((SPIx.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {} + while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_RXNE)) {} Data = (Data << 8) | SPIx.Instance->DR; } @@ -195,8 +195,8 @@ bool TFT_SPI::isBusy() { void TFT_SPI::Abort() { // Wait for any running spi - while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {} - while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {} + while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {} + while ( __HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY)) {} // First, abort any running dma HAL_DMA_Abort(&DMAtx); // DeInit objects @@ -214,8 +214,8 @@ void TFT_SPI::Transmit(uint16_t Data) { SPIx.Instance->DR = Data; - while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {} - while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {} + while (!__HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_TXE)) {} + while ( __HAL_SPI_GET_FLAG(&SPIx, SPI_FLAG_BSY)) {} if (TFT_MISO_PIN != TFT_MOSI_PIN) __HAL_SPI_CLEAR_OVRFLAG(&SPIx); // Clear overrun flag in 2 Lines communication mode because received is not read diff --git a/Marlin/src/HAL/STM32/timers.cpp b/Marlin/src/HAL/STM32/timers.cpp index 9b69323ef5..fe27ca1016 100644 --- a/Marlin/src/HAL/STM32/timers.cpp +++ b/Marlin/src/HAL/STM32/timers.cpp @@ -67,7 +67,7 @@ #endif #endif -#ifdef STM32F0xx +#if defined(STM32F0xx) || defined(STM32G0xx) #define MCU_STEP_TIMER 16 #define MCU_TEMP_TIMER 17 #elif defined(STM32F1xx) @@ -97,9 +97,15 @@ #define STEP_TIMER_DEV _TIMER_DEV(STEP_TIMER) #define TEMP_TIMER_DEV _TIMER_DEV(TEMP_TIMER) -// ------------------------ +// -------------------------------------------------------------------------- +// Local defines +// -------------------------------------------------------------------------- + +#define NUM_HARDWARE_TIMERS 2 + +// -------------------------------------------------------------------------- // Private Variables -// ------------------------ +// -------------------------------------------------------------------------- HardwareTimer *timer_instance[NUM_HARDWARE_TIMERS] = { nullptr }; @@ -110,7 +116,7 @@ HardwareTimer *timer_instance[NUM_HARDWARE_TIMERS] = { nullptr }; uint32_t GetStepperTimerClkFreq() { // Timer input clocks vary between devices, and in some cases between timers on the same device. // Retrieve at runtime to ensure device compatibility. Cache result to avoid repeated overhead. - static uint32_t clkfreq = timer_instance[STEP_TIMER_NUM]->getTimerClkFreq(); + static uint32_t clkfreq = timer_instance[MF_TIMER_STEP]->getTimerClkFreq(); return clkfreq; } @@ -118,7 +124,7 @@ uint32_t GetStepperTimerClkFreq() { void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { if (!HAL_timer_initialized(timer_num)) { switch (timer_num) { - case STEP_TIMER_NUM: // STEPPER TIMER - use a 32bit timer if possible + case MF_TIMER_STEP: // STEPPER TIMER - use a 32bit timer if possible timer_instance[timer_num] = new HardwareTimer(STEP_TIMER_DEV); /* Set the prescaler to the final desired value. * This will change the effective ISR callback frequency but when @@ -137,7 +143,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { timer_instance[timer_num]->setPrescaleFactor(STEPPER_TIMER_PRESCALE); //the -1 is done internally timer_instance[timer_num]->setOverflow(_MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE) /* /frequency */), TICK_FORMAT); break; - case TEMP_TIMER_NUM: // TEMP TIMER - any available 16bit timer + case MF_TIMER_TEMP: // TEMP TIMER - any available 16bit timer timer_instance[timer_num] = new HardwareTimer(TEMP_TIMER_DEV); // The prescale factor is computed automatically for HERTZ_FORMAT timer_instance[timer_num]->setOverflow(frequency, HERTZ_FORMAT); @@ -157,10 +163,10 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { // These calls can be removed and replaced with // timer_instance[timer_num]->setInterruptPriority switch (timer_num) { - case STEP_TIMER_NUM: + case MF_TIMER_STEP: timer_instance[timer_num]->setInterruptPriority(STEP_TIMER_IRQ_PRIO, 0); break; - case TEMP_TIMER_NUM: + case MF_TIMER_TEMP: timer_instance[timer_num]->setInterruptPriority(TEMP_TIMER_IRQ_PRIO, 0); break; } @@ -170,10 +176,10 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { void HAL_timer_enable_interrupt(const uint8_t timer_num) { if (HAL_timer_initialized(timer_num) && !timer_instance[timer_num]->hasInterrupt()) { switch (timer_num) { - case STEP_TIMER_NUM: + case MF_TIMER_STEP: timer_instance[timer_num]->attachInterrupt(Step_Handler); break; - case TEMP_TIMER_NUM: + case MF_TIMER_TEMP: timer_instance[timer_num]->attachInterrupt(Temp_Handler); break; } diff --git a/Marlin/src/HAL/STM32/timers.h b/Marlin/src/HAL/STM32/timers.h index 7a35e43210..aad543229e 100644 --- a/Marlin/src/HAL/STM32/timers.h +++ b/Marlin/src/HAL/STM32/timers.h @@ -40,17 +40,13 @@ #define hal_timer_t uint32_t #define HAL_TIMER_TYPE_MAX UINT16_MAX -#define NUM_HARDWARE_TIMERS 2 +// Marlin timer_instance[] content (unrelated to timer selection) +#define MF_TIMER_STEP 0 // Timer Index for Stepper +#define MF_TIMER_TEMP 1 // Timer Index for Temperature +#define MF_TIMER_PULSE MF_TIMER_STEP -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 0 // Timer Index for Stepper -#endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM -#endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 1 // Timer Index for Temperature -#endif +#define TIMER_INDEX_(T) TIMER##T##_INDEX // TIMER#_INDEX enums (timer_index_t) depend on TIM#_BASE defines. +#define TIMER_INDEX(T) TIMER_INDEX_(T) // Convert Timer ID to HardwareTimer_Handle index. #define TEMP_TIMER_FREQUENCY 1000 // Temperature::isr() is expected to be called at around 1kHz @@ -64,12 +60,12 @@ extern uint32_t GetStepperTimerClkFreq(); #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) extern void Step_Handler(); extern void Temp_Handler(); @@ -120,5 +116,5 @@ FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const ha } } -#define HAL_timer_isr_prologue(TIMER_NUM) -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_prologue(T) +#define HAL_timer_isr_epilogue(T) diff --git a/Marlin/src/HAL/STM32F1/HAL.cpp b/Marlin/src/HAL/STM32F1/HAL.cpp index df1ba33d4a..f29b305361 100644 --- a/Marlin/src/HAL/STM32F1/HAL.cpp +++ b/Marlin/src/HAL/STM32F1/HAL.cpp @@ -449,8 +449,7 @@ uint16_t analogRead(pin_t pin) { // Wrapper to maple unprotected analogWrite void analogWrite(pin_t pin, int pwm_val8) { - if (PWM_PIN(pin)) - analogWrite(uint8_t(pin), pwm_val8); + if (PWM_PIN(pin)) analogWrite(uint8_t(pin), pwm_val8); } void HAL_reboot() { nvic_sys_reset(); } diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h index 3bdfb9703c..153cfe8ac8 100644 --- a/Marlin/src/HAL/STM32F1/HAL.h +++ b/Marlin/src/HAL/STM32F1/HAL.h @@ -264,7 +264,10 @@ void analogWrite(pin_t pin, int pwm_val8); // PWM only! mul by 257 in maple!? #define PLATFORM_M997_SUPPORT void flashFirmware(const int16_t); -#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment +#ifndef PWM_FREQUENCY + #define PWM_FREQUENCY 1000 // Default PWM Frequency +#endif +#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment /** * set_pwm_frequency @@ -278,5 +281,6 @@ void set_pwm_frequency(const pin_t pin, int f_desired); * Set the PWM duty cycle of the provided pin to the provided value * Optionally allows inverting the duty cycle [default = false] * Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255] + * The timer must be pre-configured with set_pwm_frequency() if the default frequency is not desired. */ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false); diff --git a/Marlin/src/HAL/STM32F1/Servo.cpp b/Marlin/src/HAL/STM32F1/Servo.cpp index 36f7c6d512..8dc1ef7b6a 100644 --- a/Marlin/src/HAL/STM32F1/Servo.cpp +++ b/Marlin/src/HAL/STM32F1/Servo.cpp @@ -60,7 +60,7 @@ uint8_t ServoCount = 0; #define US_TO_ANGLE(us) int16_t(map((us), SERVO_DEFAULT_MIN_PW, SERVO_DEFAULT_MAX_PW, minAngle, maxAngle)) void libServo::servoWrite(uint8_t inPin, uint16_t duty_cycle) { - #ifdef SERVO0_TIMER_NUM + #ifdef MF_TIMER_SERVO0 if (servoIndex == 0) { pwmSetDuty(duty_cycle); return; @@ -74,7 +74,7 @@ void libServo::servoWrite(uint8_t inPin, uint16_t duty_cycle) { libServo::libServo() { servoIndex = ServoCount < MAX_SERVOS ? ServoCount++ : INVALID_SERVO; - timer_set_interrupt_priority(SERVO0_TIMER_NUM, SERVO0_TIMER_IRQ_PRIO); + HAL_timer_set_interrupt_priority(MF_TIMER_SERVO0, SERVO0_TIMER_IRQ_PRIO); } bool libServo::attach(const int32_t inPin, const int32_t inMinAngle, const int32_t inMaxAngle) { @@ -85,7 +85,7 @@ bool libServo::attach(const int32_t inPin, const int32_t inMinAngle, const int32 maxAngle = inMaxAngle; angle = -1; - #ifdef SERVO0_TIMER_NUM + #ifdef MF_TIMER_SERVO0 if (servoIndex == 0 && setupSoftPWM(inPin)) { pin = inPin; // set attached() return true; @@ -119,7 +119,7 @@ bool libServo::detach() { int32_t libServo::read() const { if (attached()) { - #ifdef SERVO0_TIMER_NUM + #ifdef MF_TIMER_SERVO0 if (servoIndex == 0) return angle; #endif timer_dev *tdev = PIN_MAP[pin].timer_device; @@ -141,9 +141,9 @@ void libServo::move(const int32_t value) { } } -#ifdef SERVO0_TIMER_NUM +#ifdef MF_TIMER_SERVO0 extern "C" void Servo_IRQHandler() { - static timer_dev *tdev = get_timer_dev(SERVO0_TIMER_NUM); + static timer_dev *tdev = HAL_get_timer_dev(MF_TIMER_SERVO0); uint16_t SR = timer_get_status(tdev); if (SR & TIMER_SR_CC1IF) { // channel 1 off #ifdef SERVO0_PWM_OD @@ -164,7 +164,7 @@ void libServo::move(const int32_t value) { } bool libServo::setupSoftPWM(const int32_t inPin) { - timer_dev *tdev = get_timer_dev(SERVO0_TIMER_NUM); + timer_dev *tdev = HAL_get_timer_dev(MF_TIMER_SERVO0); if (!tdev) return false; #ifdef SERVO0_PWM_OD OUT_WRITE_OD(inPin, 1); @@ -189,7 +189,7 @@ void libServo::move(const int32_t value) { } void libServo::pwmSetDuty(const uint16_t duty_cycle) { - timer_dev *tdev = get_timer_dev(SERVO0_TIMER_NUM); + timer_dev *tdev = HAL_get_timer_dev(MF_TIMER_SERVO0); timer_set_compare(tdev, 1, duty_cycle); timer_generate_update(tdev); if (duty_cycle) { @@ -208,7 +208,7 @@ void libServo::move(const int32_t value) { } void libServo::pauseSoftPWM() { // detach - timer_dev *tdev = get_timer_dev(SERVO0_TIMER_NUM); + timer_dev *tdev = HAL_get_timer_dev(MF_TIMER_SERVO0); timer_pause(tdev); pwmSetDuty(0); } diff --git a/Marlin/src/HAL/STM32F1/build_flags.py b/Marlin/src/HAL/STM32F1/build_flags.py index d0848d1c64..970ca8b767 100755 --- a/Marlin/src/HAL/STM32F1/build_flags.py +++ b/Marlin/src/HAL/STM32F1/build_flags.py @@ -30,25 +30,27 @@ if __name__ == "__main__": # extra script for linker options else: - from SCons.Script import DefaultEnvironment - env = DefaultEnvironment() - env.Append( + import pioutil + if pioutil.is_pio_build(): + from SCons.Script import DefaultEnvironment + env = DefaultEnvironment() + env.Append( ARFLAGS=["rcs"], ASFLAGS=["-x", "assembler-with-cpp"], CXXFLAGS=[ - "-fabi-version=0", - "-fno-use-cxa-atexit", - "-fno-threadsafe-statics" + "-fabi-version=0", + "-fno-use-cxa-atexit", + "-fno-threadsafe-statics" ], LINKFLAGS=[ - "-Os", - "-mcpu=cortex-m3", - "-ffreestanding", - "-mthumb", - "--specs=nano.specs", - "--specs=nosys.specs", - "-u_printf_float", + "-Os", + "-mcpu=cortex-m3", + "-ffreestanding", + "-mthumb", + "--specs=nano.specs", + "--specs=nosys.specs", + "-u_printf_float", ], - ) + ) diff --git a/Marlin/src/HAL/STM32F1/fast_pwm.cpp b/Marlin/src/HAL/STM32F1/fast_pwm.cpp index 884d482af5..98d56bc5e9 100644 --- a/Marlin/src/HAL/STM32F1/fast_pwm.cpp +++ b/Marlin/src/HAL/STM32F1/fast_pwm.cpp @@ -23,30 +23,54 @@ #include "../../inc/MarlinConfigPre.h" -#if NEEDS_HARDWARE_PWM - #include #include "HAL.h" #include "timers.h" +#define NR_TIMERS TERN(STM32_XL_DENSITY, 14, 8) // Maple timers, 14 for STM32_XL_DENSITY (F/G chips), 8 for HIGH density (C D E) + +static uint16_t timer_freq[NR_TIMERS]; + +inline uint8_t timer_and_index_for_pin(const pin_t pin, timer_dev **timer_ptr) { + *timer_ptr = PIN_MAP[pin].timer_device; + for (uint8_t i = 0; i < NR_TIMERS; i++) if (*timer_ptr == HAL_get_timer_dev(i)) + return i; + return 0; +} + +void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { + if (!PWM_PIN(pin)) return; + + timer_dev *timer; UNUSED(timer); + if (timer_freq[timer_and_index_for_pin(pin, &timer)] == 0) + set_pwm_frequency(pin, PWM_FREQUENCY); + + const uint8_t channel = PIN_MAP[pin].timer_channel; + const uint16_t duty = invert ? v_size - v : v; + timer_set_compare(timer, channel, duty); + timer_set_mode(timer, channel, TIMER_PWM); // PWM Output Mode +} + void set_pwm_frequency(const pin_t pin, int f_desired) { if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer - timer_dev *timer = PIN_MAP[pin].timer_device; - uint8_t channel = PIN_MAP[pin].timer_channel; + timer_dev *timer; UNUSED(timer); + timer_freq[timer_and_index_for_pin(pin, &timer)] = f_desired; // Protect used timers - if (timer == get_timer_dev(TEMP_TIMER_NUM)) return; - if (timer == get_timer_dev(STEP_TIMER_NUM)) return; - #if PULSE_TIMER_NUM != STEP_TIMER_NUM - if (timer == get_timer_dev(PULSE_TIMER_NUM)) return; + if (timer == HAL_get_timer_dev(MF_TIMER_TEMP)) return; + if (timer == HAL_get_timer_dev(MF_TIMER_STEP)) return; + #if MF_TIMER_PULSE != MF_TIMER_STEP + if (timer == HAL_get_timer_dev(MF_TIMER_PULSE)) return; #endif if (!(timer->regs.bas->SR & TIMER_CR1_CEN)) // Ensure the timer is enabled timer_init(timer); + const uint8_t channel = PIN_MAP[pin].timer_channel; timer_set_mode(timer, channel, TIMER_PWM); - uint16_t preload = 255; // Lock 255 PWM resolution for high frequencies + // Preload (resolution) cannot be equal to duty of 255 otherwise it may not result in digital off or on. + uint16_t preload = 254; int32_t prescaler = (HAL_TIMER_RATE) / (preload + 1) / f_desired - 1; if (prescaler > 65535) { // For low frequencies increase prescaler prescaler = 65535; @@ -57,12 +81,4 @@ void set_pwm_frequency(const pin_t pin, int f_desired) { timer_set_prescaler(timer, prescaler); } -void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { - timer_dev *timer = PIN_MAP[pin].timer_device; - uint16_t max_val = timer->regs.bas->ARR * v / v_size; - if (invert) max_val = v_size - max_val; - pwmWrite(pin, max_val); -} - -#endif // NEEDS_HARDWARE_PWM #endif // __STM32F1__ diff --git a/Marlin/src/HAL/STM32F1/inc/SanityCheck.h b/Marlin/src/HAL/STM32F1/inc/SanityCheck.h index 2846155c35..fe8f6e0ec2 100644 --- a/Marlin/src/HAL/STM32F1/inc/SanityCheck.h +++ b/Marlin/src/HAL/STM32F1/inc/SanityCheck.h @@ -39,7 +39,7 @@ #error "SERIAL_STATS_DROPPED_RX is not supported on the STM32F1 platform." #endif -#if ENABLED(NEOPIXEL_LED) && DISABLED(MKS_MINI_12864_V3) +#if ENABLED(NEOPIXEL_LED) && DISABLED(FYSETC_MINI_12864_2_1) #error "NEOPIXEL_LED (Adafruit NeoPixel) is not supported for HAL/STM32F1. Comment out this line to proceed at your own risk!" #endif diff --git a/Marlin/src/HAL/STM32F1/onboard_sd.cpp b/Marlin/src/HAL/STM32F1/onboard_sd.cpp index 3986b81e00..177acc7609 100644 --- a/Marlin/src/HAL/STM32F1/onboard_sd.cpp +++ b/Marlin/src/HAL/STM32F1/onboard_sd.cpp @@ -280,7 +280,7 @@ DSTATUS disk_initialize ( if (drv) return STA_NOINIT; // Supports only drive 0 sd_power_on(); // Initialize SPI - if (Stat & STA_NODISK) return Stat; // Is a card existing in the soket? + if (Stat & STA_NODISK) return Stat; // Is a card existing in the socket? FCLK_SLOW(); for (n = 10; n; n--) xchg_spi(0xFF); // Send 80 dummy clocks diff --git a/Marlin/src/HAL/STM32F1/timers.cpp b/Marlin/src/HAL/STM32F1/timers.cpp index 8c2df1e216..112c730b9a 100644 --- a/Marlin/src/HAL/STM32F1/timers.cpp +++ b/Marlin/src/HAL/STM32F1/timers.cpp @@ -47,10 +47,7 @@ * TODO: Calculate Timer prescale value, so we get the 32bit to adjust */ - - - -void timer_set_interrupt_priority(uint_fast8_t timer_num, uint_fast8_t priority) { +void HAL_timer_set_interrupt_priority(uint_fast8_t timer_num, uint_fast8_t priority) { nvic_irq_num irq_num; switch (timer_num) { case 1: irq_num = NVIC_TIMER1_CC; break; @@ -73,7 +70,6 @@ void timer_set_interrupt_priority(uint_fast8_t timer_num, uint_fast8_t priority) nvic_irq_set_priority(irq_num, priority); } - void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { /** * Give the Stepper ISR a higher priority (lower number) @@ -81,7 +77,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { */ switch (timer_num) { - case STEP_TIMER_NUM: + case MF_TIMER_STEP: timer_pause(STEP_TIMER_DEV); timer_set_mode(STEP_TIMER_DEV, STEP_TIMER_CHAN, TIMER_OUTPUT_COMPARE); // counter timer_set_count(STEP_TIMER_DEV, 0); @@ -91,11 +87,11 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { timer_set_compare(STEP_TIMER_DEV, STEP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (STEPPER_TIMER_RATE) / frequency)); timer_no_ARR_preload_ARPE(STEP_TIMER_DEV); // Need to be sure no preload on ARR register timer_attach_interrupt(STEP_TIMER_DEV, STEP_TIMER_CHAN, stepTC_Handler); - timer_set_interrupt_priority(STEP_TIMER_NUM, STEP_TIMER_IRQ_PRIO); + HAL_timer_set_interrupt_priority(MF_TIMER_STEP, STEP_TIMER_IRQ_PRIO); timer_generate_update(STEP_TIMER_DEV); timer_resume(STEP_TIMER_DEV); break; - case TEMP_TIMER_NUM: + case MF_TIMER_TEMP: timer_pause(TEMP_TIMER_DEV); timer_set_mode(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, TIMER_OUTPUT_COMPARE); timer_set_count(TEMP_TIMER_DEV, 0); @@ -103,7 +99,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { timer_set_reload(TEMP_TIMER_DEV, 0xFFFF); timer_set_compare(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (F_CPU) / (TEMP_TIMER_PRESCALE) / frequency)); timer_attach_interrupt(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, tempTC_Handler); - timer_set_interrupt_priority(TEMP_TIMER_NUM, TEMP_TIMER_IRQ_PRIO); + HAL_timer_set_interrupt_priority(MF_TIMER_TEMP, TEMP_TIMER_IRQ_PRIO); timer_generate_update(TEMP_TIMER_DEV); timer_resume(TEMP_TIMER_DEV); break; @@ -112,31 +108,31 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { void HAL_timer_enable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case STEP_TIMER_NUM: ENABLE_STEPPER_DRIVER_INTERRUPT(); break; - case TEMP_TIMER_NUM: ENABLE_TEMPERATURE_INTERRUPT(); break; + case MF_TIMER_STEP: ENABLE_STEPPER_DRIVER_INTERRUPT(); break; + case MF_TIMER_TEMP: ENABLE_TEMPERATURE_INTERRUPT(); break; } } void HAL_timer_disable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case STEP_TIMER_NUM: DISABLE_STEPPER_DRIVER_INTERRUPT(); break; - case TEMP_TIMER_NUM: DISABLE_TEMPERATURE_INTERRUPT(); break; + case MF_TIMER_STEP: DISABLE_STEPPER_DRIVER_INTERRUPT(); break; + case MF_TIMER_TEMP: DISABLE_TEMPERATURE_INTERRUPT(); break; } } -static inline bool timer_irq_enabled(const timer_dev * const dev, const uint8_t interrupt) { +static inline bool HAL_timer_irq_enabled(const timer_dev * const dev, const uint8_t interrupt) { return bool(*bb_perip(&(dev->regs).gen->DIER, interrupt)); } bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { switch (timer_num) { - case STEP_TIMER_NUM: return timer_irq_enabled(STEP_TIMER_DEV, STEP_TIMER_CHAN); - case TEMP_TIMER_NUM: return timer_irq_enabled(TEMP_TIMER_DEV, TEMP_TIMER_CHAN); + case MF_TIMER_STEP: return HAL_timer_irq_enabled(STEP_TIMER_DEV, STEP_TIMER_CHAN); + case MF_TIMER_TEMP: return HAL_timer_irq_enabled(TEMP_TIMER_DEV, TEMP_TIMER_CHAN); } return false; } -timer_dev* get_timer_dev(int number) { +timer_dev* HAL_get_timer_dev(int number) { switch (number) { #if STM32_HAVE_TIMER(1) case 1: return &timer1; diff --git a/Marlin/src/HAL/STM32F1/timers.h b/Marlin/src/HAL/STM32F1/timers.h index c89d55a134..f9ab6d13d3 100644 --- a/Marlin/src/HAL/STM32F1/timers.h +++ b/Marlin/src/HAL/STM32F1/timers.h @@ -65,30 +65,30 @@ typedef uint16_t hal_timer_t; * - Otherwise it uses Timer 8 on boards with STM32_HIGH_DENSITY * or Timer 4 on other boards. */ -#ifndef STEP_TIMER_NUM +#ifndef MF_TIMER_STEP #if defined(MCU_STM32F103CB) || defined(MCU_STM32F103C8) - #define STEP_TIMER_NUM 4 // For C8/CB boards, use timer 4 + #define MF_TIMER_STEP 4 // For C8/CB boards, use timer 4 #else - #define STEP_TIMER_NUM 5 // for other boards, five is fine. + #define MF_TIMER_STEP 5 // for other boards, five is fine. #endif #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 2 // Timer Index for Temperature - //#define TEMP_TIMER_NUM 4 // 2->4, Timer 2 for Stepper Current PWM +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 2 // Timer Index for Temperature + //#define MF_TIMER_TEMP 4 // 2->4, Timer 2 for Stepper Current PWM #endif #if MB(BTT_SKR_MINI_E3_V1_0, BTT_SKR_E3_DIP, BTT_SKR_MINI_E3_V1_2, MKS_ROBIN_LITE, MKS_ROBIN_E3D, MKS_ROBIN_E3) // SKR Mini E3 boards use PA8 as FAN_PIN, so TIMER 1 is used for Fan PWM. #ifdef STM32_HIGH_DENSITY - #define SERVO0_TIMER_NUM 8 // tone.cpp uses Timer 4 + #define MF_TIMER_SERVO0 8 // tone.cpp uses Timer 4 #else - #define SERVO0_TIMER_NUM 3 // tone.cpp uses Timer 8 + #define MF_TIMER_SERVO0 3 // tone.cpp uses Timer 8 #endif #else - #define SERVO0_TIMER_NUM 1 // SERVO0 or BLTOUCH + #define MF_TIMER_SERVO0 1 // SERVO0 or BLTOUCH #endif #define STEP_TIMER_IRQ_PRIO 2 @@ -98,22 +98,22 @@ typedef uint16_t hal_timer_t; #define TEMP_TIMER_PRESCALE 1000 // prescaler for setting Temp timer, 72Khz #define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency -#define STEPPER_TIMER_PRESCALE 18 // prescaler for setting stepper timer, 4Mhz -#define STEPPER_TIMER_RATE (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) // frequency of stepper timer -#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs +#define STEPPER_TIMER_PRESCALE 18 // prescaler for setting stepper timer, 4Mhz +#define STEPPER_TIMER_RATE (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) // frequency of stepper timer +#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs -#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer -#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE -#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US +#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer +#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE +#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -timer_dev* get_timer_dev(int number); -#define TIMER_DEV(num) get_timer_dev(num) -#define STEP_TIMER_DEV TIMER_DEV(STEP_TIMER_NUM) -#define TEMP_TIMER_DEV TIMER_DEV(TEMP_TIMER_NUM) +timer_dev* HAL_get_timer_dev(int number); +#define TIMER_DEV(num) HAL_get_timer_dev(num) +#define STEP_TIMER_DEV TIMER_DEV(MF_TIMER_STEP) +#define TEMP_TIMER_DEV TIMER_DEV(MF_TIMER_TEMP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() timer_enable_irq(STEP_TIMER_DEV, STEP_TIMER_CHAN) #define DISABLE_STEPPER_DRIVER_INTERRUPT() timer_disable_irq(STEP_TIMER_DEV, STEP_TIMER_CHAN) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) #define ENABLE_TEMPERATURE_INTERRUPT() timer_enable_irq(TEMP_TIMER_DEV, TEMP_TIMER_CHAN) #define DISABLE_TEMPERATURE_INTERRUPT() timer_disable_irq(TEMP_TIMER_DEV, TEMP_TIMER_CHAN) @@ -138,8 +138,8 @@ extern "C" { // Public Variables // ------------------------ -//static HardwareTimer StepperTimer(STEP_TIMER_NUM); -//static HardwareTimer TempTimer(TEMP_TIMER_NUM); +//static HardwareTimer StepperTimer(MF_TIMER_STEP); +//static HardwareTimer TempTimer(MF_TIMER_TEMP); // ------------------------ // Public functions @@ -163,13 +163,13 @@ bool HAL_timer_interrupt_enabled(const uint8_t timer_num); FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) { switch (timer_num) { - case STEP_TIMER_NUM: + case MF_TIMER_STEP: // NOTE: WE have set ARPE = 0, which means the Auto reload register is not preloaded // and there is no need to use any compare, as in the timer mode used, setting ARR to the compare value // will result in exactly the same effect, ie triggering an interrupt, and on top, set counter to 0 timer_set_reload(STEP_TIMER_DEV, compare); // We reload direct ARR as needed during counting up break; - case TEMP_TIMER_NUM: + case MF_TIMER_TEMP: timer_set_compare(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, compare); break; } @@ -177,18 +177,18 @@ FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const ha FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) { switch (timer_num) { - case STEP_TIMER_NUM: - // No counter to clear - timer_generate_update(STEP_TIMER_DEV); - return; - case TEMP_TIMER_NUM: - timer_set_count(TEMP_TIMER_DEV, 0); - timer_generate_update(TEMP_TIMER_DEV); - return; + case MF_TIMER_STEP: + // No counter to clear + timer_generate_update(STEP_TIMER_DEV); + return; + case MF_TIMER_TEMP: + timer_set_count(TEMP_TIMER_DEV, 0); + timer_generate_update(TEMP_TIMER_DEV); + return; } } -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_epilogue(T) // No command is available in framework to turn off ARPE bit, which is turned on by default in libmaple. // Needed here to reset ARPE=0 for stepper timer @@ -196,6 +196,6 @@ FORCE_INLINE static void timer_no_ARR_preload_ARPE(timer_dev *dev) { bb_peri_set_bit(&(dev->regs).gen->CR1, TIMER_CR1_ARPE_BIT, 0); } -void timer_set_interrupt_priority(uint_fast8_t timer_num, uint_fast8_t priority); +void HAL_timer_set_interrupt_priority(uint_fast8_t timer_num, uint_fast8_t priority); #define TIMER_OC_NO_PRELOAD 0 // Need to disable preload also on compare registers. diff --git a/Marlin/src/HAL/TEENSY31_32/HAL.h b/Marlin/src/HAL/TEENSY31_32/HAL.h index aa195845fb..61d8b34604 100644 --- a/Marlin/src/HAL/TEENSY31_32/HAL.h +++ b/Marlin/src/HAL/TEENSY31_32/HAL.h @@ -98,16 +98,14 @@ void HAL_reboot(); FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); } +#pragma GCC diagnostic push #if GCC_VERSION <= 50000 - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif extern "C" int freeMemory(); -#if GCC_VERSION <= 50000 - #pragma GCC diagnostic pop -#endif +#pragma GCC diagnostic pop // ADC @@ -124,6 +122,12 @@ void HAL_adc_init(); void HAL_adc_start_conversion(const uint8_t adc_pin); uint16_t HAL_adc_get_result(); +// PWM + +inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); } + +// Pin Map + #define GET_PIN_MAP_PIN(index) index #define GET_PIN_MAP_INDEX(pin) pin #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) diff --git a/Marlin/src/HAL/TEENSY31_32/timers.cpp b/Marlin/src/HAL/TEENSY31_32/timers.cpp index 7e01a38f89..f217715a3f 100644 --- a/Marlin/src/HAL/TEENSY31_32/timers.cpp +++ b/Marlin/src/HAL/TEENSY31_32/timers.cpp @@ -47,7 +47,7 @@ FORCE_INLINE static void __DSB() { void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { switch (timer_num) { - case 0: + case MF_TIMER_STEP: FTM0_MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN; FTM0_SC = 0x00; // Set this to zero before changing the modulus FTM0_CNT = 0x0000; // Reset the count to zero @@ -56,7 +56,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { FTM0_SC = (FTM_SC_CLKS(0b1) & FTM_SC_CLKS_MASK) | (FTM_SC_PS(FTM0_TIMER_PRESCALE_BITS) & FTM_SC_PS_MASK); // Bus clock 60MHz divided by prescaler 8 FTM0_C0SC = FTM_CSC_CHIE | FTM_CSC_MSA | FTM_CSC_ELSA; break; - case 1: + case MF_TIMER_TEMP: FTM1_MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN; // Disable write protection, Enable FTM1 FTM1_SC = 0x00; // Set this to zero before changing the modulus FTM1_CNT = 0x0000; // Reset the count to zero @@ -70,15 +70,15 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { void HAL_timer_enable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case 0: NVIC_ENABLE_IRQ(IRQ_FTM0); break; - case 1: NVIC_ENABLE_IRQ(IRQ_FTM1); break; + case MF_TIMER_STEP: NVIC_ENABLE_IRQ(IRQ_FTM0); break; + case MF_TIMER_TEMP: NVIC_ENABLE_IRQ(IRQ_FTM1); break; } } void HAL_timer_disable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case 0: NVIC_DISABLE_IRQ(IRQ_FTM0); break; - case 1: NVIC_DISABLE_IRQ(IRQ_FTM1); break; + case MF_TIMER_STEP: NVIC_DISABLE_IRQ(IRQ_FTM0); break; + case MF_TIMER_TEMP: NVIC_DISABLE_IRQ(IRQ_FTM1); break; } // We NEED memory barriers to ensure Interrupts are actually disabled! @@ -89,20 +89,20 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num) { bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { switch (timer_num) { - case 0: return NVIC_IS_ENABLED(IRQ_FTM0); - case 1: return NVIC_IS_ENABLED(IRQ_FTM1); + case MF_TIMER_STEP: return NVIC_IS_ENABLED(IRQ_FTM0); + case MF_TIMER_TEMP: return NVIC_IS_ENABLED(IRQ_FTM1); } return false; } void HAL_timer_isr_prologue(const uint8_t timer_num) { switch (timer_num) { - case 0: + case MF_TIMER_STEP: FTM0_CNT = 0x0000; FTM0_SC &= ~FTM_SC_TOF; // Clear FTM Overflow flag FTM0_C0SC &= ~FTM_CSC_CHF; // Clear FTM Channel Compare flag break; - case 1: + case MF_TIMER_TEMP: FTM1_CNT = 0x0000; FTM1_SC &= ~FTM_SC_TOF; // Clear FTM Overflow flag FTM1_C0SC &= ~FTM_CSC_CHF; // Clear FTM Channel Compare flag diff --git a/Marlin/src/HAL/TEENSY31_32/timers.h b/Marlin/src/HAL/TEENSY31_32/timers.h index 61b8673596..3b073d63ab 100644 --- a/Marlin/src/HAL/TEENSY31_32/timers.h +++ b/Marlin/src/HAL/TEENSY31_32/timers.h @@ -46,14 +46,14 @@ typedef uint32_t hal_timer_t; #define HAL_TIMER_RATE (FTM0_TIMER_RATE) -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 0 // Timer Index for Stepper +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 0 // Timer Index for Stepper #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 1 // Timer Index for Temperature +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 1 // Timer Index for Temperature #endif #define TEMP_TIMER_FREQUENCY 1000 @@ -66,12 +66,12 @@ typedef uint32_t hal_timer_t; #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) #ifndef HAL_STEP_TIMER_ISR #define HAL_STEP_TIMER_ISR() extern "C" void ftm0_isr() //void TC3_Handler() @@ -84,23 +84,23 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency); FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) { switch (timer_num) { - case 0: FTM0_C0V = compare; break; - case 1: FTM1_C0V = compare; break; + case MF_TIMER_STEP: FTM0_C0V = compare; break; + case MF_TIMER_TEMP: FTM1_C0V = compare; break; } } FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { switch (timer_num) { - case 0: return FTM0_C0V; - case 1: return FTM1_C0V; + case MF_TIMER_STEP: return FTM0_C0V; + case MF_TIMER_TEMP: return FTM1_C0V; } return 0; } FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { switch (timer_num) { - case 0: return FTM0_CNT; - case 1: return FTM1_CNT; + case MF_TIMER_STEP: return FTM0_CNT; + case MF_TIMER_TEMP: return FTM1_CNT; } return 0; } @@ -110,4 +110,4 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num); void HAL_timer_isr_prologue(const uint8_t timer_num); -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_epilogue(T) diff --git a/Marlin/src/HAL/TEENSY35_36/HAL.h b/Marlin/src/HAL/TEENSY35_36/HAL.h index 0093294a2a..892eb2d3c5 100644 --- a/Marlin/src/HAL/TEENSY35_36/HAL.h +++ b/Marlin/src/HAL/TEENSY35_36/HAL.h @@ -105,16 +105,14 @@ void HAL_reboot(); FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); } +#pragma GCC diagnostic push #if GCC_VERSION <= 50000 - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif extern "C" int freeMemory(); -#if GCC_VERSION <= 50000 - #pragma GCC diagnostic pop -#endif +#pragma GCC diagnostic pop // ADC @@ -131,6 +129,12 @@ void HAL_adc_init(); void HAL_adc_start_conversion(const uint8_t adc_pin); uint16_t HAL_adc_get_result(); +// PWM + +inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); } + +// Pin Map + #define GET_PIN_MAP_PIN(index) index #define GET_PIN_MAP_INDEX(pin) pin #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) diff --git a/Marlin/src/HAL/TEENSY35_36/timers.cpp b/Marlin/src/HAL/TEENSY35_36/timers.cpp index 8067d091dd..39095fbd77 100644 --- a/Marlin/src/HAL/TEENSY35_36/timers.cpp +++ b/Marlin/src/HAL/TEENSY35_36/timers.cpp @@ -47,7 +47,7 @@ FORCE_INLINE static void __DSB() { void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { switch (timer_num) { - case 0: + case MF_TIMER_STEP: FTM0_MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN; FTM0_SC = 0x00; // Set this to zero before changing the modulus FTM0_CNT = 0x0000; // Reset the count to zero @@ -56,7 +56,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { FTM0_SC = (FTM_SC_CLKS(0b1) & FTM_SC_CLKS_MASK) | (FTM_SC_PS(FTM0_TIMER_PRESCALE_BITS) & FTM_SC_PS_MASK); // Bus clock 60MHz divided by prescaler 8 FTM0_C0SC = FTM_CSC_CHIE | FTM_CSC_MSA | FTM_CSC_ELSA; break; - case 1: + case MF_TIMER_TEMP: FTM1_MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN; // Disable write protection, Enable FTM1 FTM1_SC = 0x00; // Set this to zero before changing the modulus FTM1_CNT = 0x0000; // Reset the count to zero @@ -70,15 +70,15 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { void HAL_timer_enable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case 0: NVIC_ENABLE_IRQ(IRQ_FTM0); break; - case 1: NVIC_ENABLE_IRQ(IRQ_FTM1); break; + case MF_TIMER_STEP: NVIC_ENABLE_IRQ(IRQ_FTM0); break; + case MF_TIMER_TEMP: NVIC_ENABLE_IRQ(IRQ_FTM1); break; } } void HAL_timer_disable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case 0: NVIC_DISABLE_IRQ(IRQ_FTM0); break; - case 1: NVIC_DISABLE_IRQ(IRQ_FTM1); break; + case MF_TIMER_STEP: NVIC_DISABLE_IRQ(IRQ_FTM0); break; + case MF_TIMER_TEMP: NVIC_DISABLE_IRQ(IRQ_FTM1); break; } // We NEED memory barriers to ensure Interrupts are actually disabled! @@ -89,20 +89,20 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num) { bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { switch (timer_num) { - case 0: return NVIC_IS_ENABLED(IRQ_FTM0); - case 1: return NVIC_IS_ENABLED(IRQ_FTM1); + case MF_TIMER_STEP: return NVIC_IS_ENABLED(IRQ_FTM0); + case MF_TIMER_TEMP: return NVIC_IS_ENABLED(IRQ_FTM1); } return false; } void HAL_timer_isr_prologue(const uint8_t timer_num) { switch (timer_num) { - case 0: + case MF_TIMER_STEP: FTM0_CNT = 0x0000; FTM0_SC &= ~FTM_SC_TOF; // Clear FTM Overflow flag FTM0_C0SC &= ~FTM_CSC_CHF; // Clear FTM Channel Compare flag break; - case 1: + case MF_TIMER_TEMP: FTM1_CNT = 0x0000; FTM1_SC &= ~FTM_SC_TOF; // Clear FTM Overflow flag FTM1_C0SC &= ~FTM_CSC_CHF; // Clear FTM Channel Compare flag diff --git a/Marlin/src/HAL/TEENSY35_36/timers.h b/Marlin/src/HAL/TEENSY35_36/timers.h index 99269ac657..6c342bbe0d 100644 --- a/Marlin/src/HAL/TEENSY35_36/timers.h +++ b/Marlin/src/HAL/TEENSY35_36/timers.h @@ -45,14 +45,14 @@ typedef uint32_t hal_timer_t; #define HAL_TIMER_RATE (FTM0_TIMER_RATE) -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 0 // Timer Index for Stepper +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 0 // Timer Index for Stepper #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 1 // Timer Index for Temperature +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 1 // Timer Index for Temperature #endif #define TEMP_TIMER_FREQUENCY 1000 @@ -65,12 +65,12 @@ typedef uint32_t hal_timer_t; #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) #ifndef HAL_STEP_TIMER_ISR #define HAL_STEP_TIMER_ISR() extern "C" void ftm0_isr() //void TC3_Handler() @@ -83,23 +83,23 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency); FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) { switch (timer_num) { - case 0: FTM0_C0V = compare; break; - case 1: FTM1_C0V = compare; break; + case MF_TIMER_STEP: FTM0_C0V = compare; break; + case MF_TIMER_TEMP: FTM1_C0V = compare; break; } } FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { switch (timer_num) { - case 0: return FTM0_C0V; - case 1: return FTM1_C0V; + case MF_TIMER_STEP: return FTM0_C0V; + case MF_TIMER_TEMP: return FTM1_C0V; } return 0; } FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { switch (timer_num) { - case 0: return FTM0_CNT; - case 1: return FTM1_CNT; + case MF_TIMER_STEP: return FTM0_CNT; + case MF_TIMER_TEMP: return FTM1_CNT; } return 0; } @@ -109,4 +109,4 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num); void HAL_timer_isr_prologue(const uint8_t timer_num); -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_epilogue(T) diff --git a/Marlin/src/HAL/TEENSY40_41/HAL.cpp b/Marlin/src/HAL/TEENSY40_41/HAL.cpp index ccc8c2659c..270bee0dc9 100644 --- a/Marlin/src/HAL/TEENSY40_41/HAL.cpp +++ b/Marlin/src/HAL/TEENSY40_41/HAL.cpp @@ -106,17 +106,17 @@ void HAL_adc_init() { void HAL_clear_reset_source() { uint32_t reset_source = SRC_SRSR; SRC_SRSR = reset_source; - } +} uint8_t HAL_get_reset_source() { switch (SRC_SRSR & 0xFF) { case 1: return RST_POWER_ON; break; case 2: return RST_SOFTWARE; break; case 4: return RST_EXTERNAL; break; - // case 8: return RST_BROWN_OUT; break; + //case 8: return RST_BROWN_OUT; break; case 16: return RST_WATCHDOG; break; - case 64: return RST_JTAG; break; - // case 128: return RST_OVERTEMP; break; + case 64: return RST_JTAG; break; + //case 128: return RST_OVERTEMP; break; } return 0; } @@ -168,7 +168,7 @@ uint16_t HAL_adc_get_result() { return 0; } -bool is_output(uint8_t pin) { +bool is_output(pin_t pin) { const struct digital_pin_bitband_and_config_table_struct *p; p = digital_pin_to_info_PGM + pin; return (*(p->reg + 1) & p->mask); diff --git a/Marlin/src/HAL/TEENSY40_41/HAL.h b/Marlin/src/HAL/TEENSY40_41/HAL.h index ea51f15ba1..2b730768a8 100644 --- a/Marlin/src/HAL/TEENSY40_41/HAL.h +++ b/Marlin/src/HAL/TEENSY40_41/HAL.h @@ -125,16 +125,14 @@ void HAL_reboot(); FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); } +#pragma GCC diagnostic push #if GCC_VERSION <= 50000 - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif extern "C" uint32_t freeMemory(); -#if GCC_VERSION <= 50000 - #pragma GCC diagnostic pop -#endif +#pragma GCC diagnostic pop // ADC @@ -152,8 +150,14 @@ void HAL_adc_init(); void HAL_adc_start_conversion(const uint8_t adc_pin); uint16_t HAL_adc_get_result(); +// PWM + +inline void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { analogWrite(pin, v); } + +// Pin Map + #define GET_PIN_MAP_PIN(index) index #define GET_PIN_MAP_INDEX(pin) pin #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) -bool is_output(uint8_t pin); +bool is_output(pin_t pin); diff --git a/Marlin/src/HAL/TEENSY40_41/timers.cpp b/Marlin/src/HAL/TEENSY40_41/timers.cpp index 81c9b08c17..ed99f65d6e 100644 --- a/Marlin/src/HAL/TEENSY40_41/timers.cpp +++ b/Marlin/src/HAL/TEENSY40_41/timers.cpp @@ -30,7 +30,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { switch (timer_num) { - case 0: + case MF_TIMER_STEP: CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL; // turn off 24mhz mode CCM_CCGR1 |= CCM_CCGR1_GPT1_BUS(CCM_CCGR_ON); @@ -48,7 +48,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { attachInterruptVector(IRQ_GPT1, &stepTC_Handler); NVIC_SET_PRIORITY(IRQ_GPT1, 16); break; - case 1: + case MF_TIMER_TEMP: CCM_CSCMR1 &= ~CCM_CSCMR1_PERCLK_CLK_SEL; // turn off 24mhz mode CCM_CCGR0 |= CCM_CCGR0_GPT2_BUS(CCM_CCGR_ON); @@ -71,19 +71,15 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { void HAL_timer_enable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case 0: - NVIC_ENABLE_IRQ(IRQ_GPT1); - break; - case 1: - NVIC_ENABLE_IRQ(IRQ_GPT2); - break; + case MF_TIMER_STEP: NVIC_ENABLE_IRQ(IRQ_GPT1); break; + case MF_TIMER_TEMP: NVIC_ENABLE_IRQ(IRQ_GPT2); break; } } void HAL_timer_disable_interrupt(const uint8_t timer_num) { switch (timer_num) { - case 0: NVIC_DISABLE_IRQ(IRQ_GPT1); break; - case 1: NVIC_DISABLE_IRQ(IRQ_GPT2); break; + case MF_TIMER_STEP: NVIC_DISABLE_IRQ(IRQ_GPT1); break; + case MF_TIMER_TEMP: NVIC_DISABLE_IRQ(IRQ_GPT2); break; } // We NEED memory barriers to ensure Interrupts are actually disabled! @@ -93,20 +89,16 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num) { bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { switch (timer_num) { - case 0: return (NVIC_IS_ENABLED(IRQ_GPT1)); - case 1: return (NVIC_IS_ENABLED(IRQ_GPT2)); + case MF_TIMER_STEP: return (NVIC_IS_ENABLED(IRQ_GPT1)); + case MF_TIMER_TEMP: return (NVIC_IS_ENABLED(IRQ_GPT2)); } return false; } void HAL_timer_isr_prologue(const uint8_t timer_num) { switch (timer_num) { - case 0: - GPT1_SR = GPT_IR_OF1IE; // clear OF3 bit - break; - case 1: - GPT2_SR = GPT_IR_OF1IE; // clear OF3 bit - break; + case MF_TIMER_STEP: GPT1_SR = GPT_IR_OF1IE; break; // clear OF3 bit + case MF_TIMER_TEMP: GPT2_SR = GPT_IR_OF1IE; break; // clear OF3 bit } asm volatile("dsb"); } diff --git a/Marlin/src/HAL/TEENSY40_41/timers.h b/Marlin/src/HAL/TEENSY40_41/timers.h index 556333d7f4..81cf67f7bc 100644 --- a/Marlin/src/HAL/TEENSY40_41/timers.h +++ b/Marlin/src/HAL/TEENSY40_41/timers.h @@ -43,14 +43,14 @@ typedef uint32_t hal_timer_t; #define GPT1_TIMER_RATE (GPT_TIMER_RATE / GPT1_TIMER_PRESCALE) // 75MHz #define GPT2_TIMER_RATE (GPT_TIMER_RATE / GPT2_TIMER_PRESCALE) // 15MHz -#ifndef STEP_TIMER_NUM - #define STEP_TIMER_NUM 0 // Timer Index for Stepper +#ifndef MF_TIMER_STEP + #define MF_TIMER_STEP 0 // Timer Index for Stepper #endif -#ifndef PULSE_TIMER_NUM - #define PULSE_TIMER_NUM STEP_TIMER_NUM +#ifndef MF_TIMER_PULSE + #define MF_TIMER_PULSE MF_TIMER_STEP #endif -#ifndef TEMP_TIMER_NUM - #define TEMP_TIMER_NUM 1 // Timer Index for Temperature +#ifndef MF_TIMER_TEMP + #define MF_TIMER_TEMP 1 // Timer Index for Temperature #endif #define TEMP_TIMER_RATE 1000000 @@ -64,12 +64,12 @@ typedef uint32_t hal_timer_t; #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US -#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) -#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) -#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) +#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) +#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) +#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) -#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) -#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) +#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) +#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) #ifndef HAL_STEP_TIMER_ISR #define HAL_STEP_TIMER_ISR() extern "C" void stepTC_Handler() // GPT1_Handler() @@ -87,27 +87,23 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency); FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) { switch (timer_num) { - case 0: - GPT1_OCR1 = compare - 1; - break; - case 1: - GPT2_OCR1 = compare - 1; - break; + case MF_TIMER_STEP: GPT1_OCR1 = compare - 1; break; + case MF_TIMER_TEMP: GPT2_OCR1 = compare - 1; break; } } FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { switch (timer_num) { - case 0: return GPT1_OCR1; - case 1: return GPT2_OCR1; + case MF_TIMER_STEP: return GPT1_OCR1; + case MF_TIMER_TEMP: return GPT2_OCR1; } return 0; } FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { switch (timer_num) { - case 0: return GPT1_CNT; - case 1: return GPT2_CNT; + case MF_TIMER_STEP: return GPT1_CNT; + case MF_TIMER_TEMP: return GPT2_CNT; } return 0; } @@ -118,4 +114,4 @@ bool HAL_timer_interrupt_enabled(const uint8_t timer_num); void HAL_timer_isr_prologue(const uint8_t timer_num); //void HAL_timer_isr_epilogue(const uint8_t timer_num) {} -#define HAL_timer_isr_epilogue(TIMER_NUM) +#define HAL_timer_isr_epilogue(T) diff --git a/Marlin/src/HAL/shared/Delay.cpp b/Marlin/src/HAL/shared/Delay.cpp index 32543c6d0a..c64376d25d 100644 --- a/Marlin/src/HAL/shared/Delay.cpp +++ b/Marlin/src/HAL/shared/Delay.cpp @@ -108,13 +108,14 @@ #if ENABLED(MARLIN_DEV_MODE) void dump_delay_accuracy_check() { - auto report_call_time = [](PGM_P const name, PGM_P const unit, const uint32_t cycles, const uint32_t total, const bool do_flush=true) { + auto report_call_time = [](FSTR_P const name, FSTR_P const unit, const uint32_t cycles, const uint32_t total, const bool do_flush=true) { SERIAL_ECHOPGM("Calling "); - SERIAL_ECHOPGM_P(name); + SERIAL_ECHOF(name); SERIAL_ECHOLNPGM(" for ", cycles); - SERIAL_ECHOPGM_P(unit); + SERIAL_ECHOF(unit); SERIAL_ECHOLNPGM(" took: ", total); - SERIAL_ECHOPGM_P(unit); + SERIAL_CHAR(' '); + SERIAL_ECHOF(unit); if (do_flush) SERIAL_FLUSHTX(); }; @@ -126,41 +127,42 @@ constexpr uint32_t testValues[] = { 1, 5, 10, 20, 50, 100, 150, 200, 350, 500, 750, 1000 }; for (auto i : testValues) { s = micros(); DELAY_US(i); e = micros(); - report_call_time(PSTR("delay"), PSTR("us"), i, e - s); + report_call_time(F("delay"), F("us"), i, e - s); } if (HW_REG(_DWT_CTRL)) { + static FSTR_P cyc = F("cycles"); + static FSTR_P dcd = F("DELAY_CYCLES directly "); + for (auto i : testValues) { s = HW_REG(_DWT_CYCCNT); DELAY_CYCLES(i); e = HW_REG(_DWT_CYCCNT); - report_call_time(PSTR("runtime delay"), PSTR("cycles"), i, e - s); + report_call_time(F("runtime delay"), cyc, i, e - s); } // Measure the delay to call a real function compared to a function pointer s = HW_REG(_DWT_CYCCNT); delay_dwt(1); e = HW_REG(_DWT_CYCCNT); - report_call_time(PSTR("delay_dwt"), PSTR("cycles"), 1, e - s); - - static PGMSTR(dcd, "DELAY_CYCLES directly "); + report_call_time(F("delay_dwt"), cyc, 1, e - s); s = HW_REG(_DWT_CYCCNT); DELAY_CYCLES( 1); e = HW_REG(_DWT_CYCCNT); - report_call_time(dcd, PSTR("cycles"), 1, e - s, false); + report_call_time(dcd, cyc, 1, e - s, false); s = HW_REG(_DWT_CYCCNT); DELAY_CYCLES( 5); e = HW_REG(_DWT_CYCCNT); - report_call_time(dcd, PSTR("cycles"), 5, e - s, false); + report_call_time(dcd, cyc, 5, e - s, false); s = HW_REG(_DWT_CYCCNT); DELAY_CYCLES(10); e = HW_REG(_DWT_CYCCNT); - report_call_time(dcd, PSTR("cycles"), 10, e - s, false); + report_call_time(dcd, cyc, 10, e - s, false); s = HW_REG(_DWT_CYCCNT); DELAY_CYCLES(20); e = HW_REG(_DWT_CYCCNT); - report_call_time(dcd, PSTR("cycles"), 20, e - s, false); + report_call_time(dcd, cyc, 20, e - s, false); s = HW_REG(_DWT_CYCCNT); DELAY_CYCLES(50); e = HW_REG(_DWT_CYCCNT); - report_call_time(dcd, PSTR("cycles"), 50, e - s, false); + report_call_time(dcd, cyc, 50, e - s, false); s = HW_REG(_DWT_CYCCNT); DELAY_CYCLES(100); e = HW_REG(_DWT_CYCCNT); - report_call_time(dcd, PSTR("cycles"), 100, e - s, false); + report_call_time(dcd, cyc, 100, e - s, false); s = HW_REG(_DWT_CYCCNT); DELAY_CYCLES(200); e = HW_REG(_DWT_CYCCNT); - report_call_time(dcd, PSTR("cycles"), 200, e - s, false); + report_call_time(dcd, cyc, 200, e - s, false); } } #endif // MARLIN_DEV_MODE @@ -170,7 +172,7 @@ void calibrate_delay_loop() {} #if ENABLED(MARLIN_DEV_MODE) - void dump_delay_accuracy_check() { SERIAL_ECHOPGM_P(PSTR("N/A on this platform")); } + void dump_delay_accuracy_check() { SERIAL_ECHOPGM("N/A on this platform"); } #endif #endif diff --git a/Marlin/src/HAL/shared/Delay.h b/Marlin/src/HAL/shared/Delay.h index 04df35d88d..df07881f01 100644 --- a/Marlin/src/HAL/shared/Delay.h +++ b/Marlin/src/HAL/shared/Delay.h @@ -92,6 +92,12 @@ void calibrate_delay_loop(); #define DELAY_CYCLES(X) do { SmartDelay _smrtdly_X(X); } while(0) + #if GCC_VERSION <= 70000 + #define DELAY_CYCLES_VAR(X) DelayCycleFnc(X) + #else + #define DELAY_CYCLES_VAR DELAY_CYCLES + #endif + // For delay in microseconds, no smart delay selection is required, directly call the delay function // Teensy compiler is too old and does not accept smart delay compile-time / run-time selection correctly #define DELAY_US(x) DelayCycleFnc((x) * ((F_CPU) / 1000000UL)) @@ -200,9 +206,12 @@ void calibrate_delay_loop(); #endif #if ENABLED(DELAY_NS_ROUND_DOWN) - #define DELAY_NS(x) DELAY_CYCLES((x) * ((F_CPU) / 1000000UL) / 1000UL) // floor + #define _NS_TO_CYCLES(x) ( (x) * ((F_CPU) / 1000000UL) / 1000UL) // floor #elif ENABLED(DELAY_NS_ROUND_CLOSEST) - #define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 500) / 1000UL) // round + #define _NS_TO_CYCLES(x) (((x) * ((F_CPU) / 1000000UL) + 500) / 1000UL) // round #else - #define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 999) / 1000UL) // "ceil" + #define _NS_TO_CYCLES(x) (((x) * ((F_CPU) / 1000000UL) + 999) / 1000UL) // "ceil" #endif + +#define DELAY_NS(x) DELAY_CYCLES(_NS_TO_CYCLES(x)) +#define DELAY_NS_VAR(x) DELAY_CYCLES_VAR(_NS_TO_CYCLES(x)) diff --git a/Marlin/src/HAL/shared/Marduino.h b/Marlin/src/HAL/shared/Marduino.h index ddc3451fbe..0e2a021a3c 100644 --- a/Marlin/src/HAL/shared/Marduino.h +++ b/Marlin/src/HAL/shared/Marduino.h @@ -39,7 +39,7 @@ #define DISABLED(V...) DO(DIS,&&,V) #undef _BV -#define _BV(b) (1UL << (b)) +#define _BV(b) (1 << (b)) #ifndef SBI #define SBI(A,B) (A |= _BV(B)) #endif @@ -87,3 +87,10 @@ #endif #include "progmem.h" + +class __FlashStringHelper; +typedef const __FlashStringHelper* FSTR_P; +#ifndef FPSTR + #define FPSTR(S) (reinterpret_cast(S)) +#endif +#define FTOP(S) (reinterpret_cast(S)) diff --git a/Marlin/src/HAL/shared/backtrace/unwmemaccess.cpp b/Marlin/src/HAL/shared/backtrace/unwmemaccess.cpp index 2bde1e208d..a4151b38c2 100644 --- a/Marlin/src/HAL/shared/backtrace/unwmemaccess.cpp +++ b/Marlin/src/HAL/shared/backtrace/unwmemaccess.cpp @@ -41,7 +41,7 @@ #define START_FLASH_ADDR 0x00000000 #define END_FLASH_ADDR 0x00080000 -#elif defined(__STM32F1__) || defined(STM32F1xx) || defined(STM32F0xx) +#elif defined(__STM32F1__) || defined(STM32F1xx) || defined(STM32F0xx) || defined(STM32G0xx) // For STM32F103ZET6/STM32F103VET6/STM32F0xx // SRAM (0x20000000 - 0x20010000) (64kb) diff --git a/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp b/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp index 0f0f7c4807..a106ed2b05 100644 --- a/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp +++ b/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp @@ -101,7 +101,7 @@ struct __attribute__((packed)) ContextSavedFrame { uint32_t ELR; }; -#if DISABLED(STM32F0xx) +#if NONE(STM32F0xx, STM32G0xx) extern "C" __attribute__((naked)) void CommonHandler_ASM() { __asm__ __volatile__ ( diff --git a/Marlin/src/HAL/shared/progmem.h b/Marlin/src/HAL/shared/progmem.h index 539d02705e..4cd7663df9 100644 --- a/Marlin/src/HAL/shared/progmem.h +++ b/Marlin/src/HAL/shared/progmem.h @@ -38,7 +38,8 @@ #define PSTR(str) (str) #endif #ifndef F -#define F(str) (str) +class __FlashStringHelper; +#define F(str) (reinterpret_cast(PSTR(str))) #endif #ifndef _SFR_BYTE #define _SFR_BYTE(n) (n) @@ -110,7 +111,7 @@ #define strrchr_P(str, c) strrchr((str), (c)) #endif #ifndef strsep_P -#define strsep_P(strp, delim) strsep((strp), (delim)) +#define strsep_P(pstr, delim) strsep((pstr), (delim)) #endif #ifndef strspn_P #define strspn_P(str, chrs) strspn((str), (chrs)) diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index c15379329b..186b273a98 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -212,10 +212,18 @@ #include "module/tool_change.h" +#if HAS_FANCHECK + #include "feature/fancheck.h" +#endif + #if ENABLED(USE_CONTROLLER_FAN) #include "feature/controllerfan.h" #endif +#if HAS_PRUSA_MMU1 + #include "feature/mmu/mmu.h" +#endif + #if HAS_PRUSA_MMU2 #include "feature/mmu/mmu2.h" #endif @@ -240,6 +248,10 @@ #include "feature/power.h" #endif +#if ENABLED(EASYTHREED_UI) + #include "feature/easythreed_ui.h" +#endif + PGMSTR(M112_KILL_STR, "M112 Shutdown"); MarlinState marlin_state = MF_INITIALIZING; @@ -357,15 +369,15 @@ void startOrResumeJob() { TERN_(POWER_LOSS_RECOVERY, recovery.purge()); #ifdef EVENT_GCODE_SD_ABORT - queue.inject_P(PSTR(EVENT_GCODE_SD_ABORT)); + queue.inject(F(EVENT_GCODE_SD_ABORT)); #endif TERN_(PASSWORD_AFTER_SD_PRINT_ABORT, password.lock_machine()); } inline void finishSDPrinting() { - if (queue.enqueue_one_P(PSTR("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 = MF_RUNNING; // Signal to stop trying TERN_(PASSWORD_AFTER_SD_PRINT_END, password.lock_machine()); TERN_(DGUS_LCD_UI_MKS, ScreenHandler.SDPrintingFinished()); } @@ -474,7 +486,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) { if (!IS_SD_PRINTING() && !READ(HOME_PIN)) { // HOME_PIN goes LOW when pressed if (ELAPSED(ms, next_home_key_ms)) { next_home_key_ms = ms + HOME_DEBOUNCE_DELAY; - LCD_MESSAGEPGM(MSG_AUTO_HOME); + LCD_MESSAGE(MSG_AUTO_HOME); queue.inject_P(G28_STR); } } @@ -493,14 +505,14 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) { if (ELAPSED(ms, next_cub_ms_##N)) { \ next_cub_ms_##N = ms + CUB_DEBOUNCE_DELAY_##N; \ CODE; \ - queue.inject_P(PSTR(BUTTON##N##_GCODE)); \ + queue.inject(F(BUTTON##N##_GCODE)); \ TERN_(HAS_LCD_MENU, ui.quick_feedback()); \ } \ } \ }while(0) - #define CHECK_CUSTOM_USER_BUTTON(N) _CHECK_CUSTOM_USER_BUTTON(N, NOOP) - #define CHECK_BETTER_USER_BUTTON(N) _CHECK_CUSTOM_USER_BUTTON(N, if (strlen(BUTTON##N##_DESC)) LCD_MESSAGEPGM_P(PSTR(BUTTON##N##_DESC))) + #define CHECK_CUSTOM_USER_BUTTON(N) _CHECK_CUSTOM_USER_BUTTON(N, NOOP) + #define CHECK_BETTER_USER_BUTTON(N) _CHECK_CUSTOM_USER_BUTTON(N, if (strlen(BUTTON##N##_DESC)) LCD_MESSAGE_F(BUTTON##N##_DESC)) #if HAS_BETTER_USER_BUTTON(1) CHECK_BETTER_USER_BUTTON(1); @@ -629,6 +641,8 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) { #endif #endif + TERN_(EASYTHREED_UI, easythreed_ui.run()); + TERN_(USE_CONTROLLER_FAN, controllerFan.update()); // Check if fan should be turned on to cool stepper drivers down TERN_(AUTO_POWER_CONTROL, powerManager.check(!ui.on_status_screen() || printJobOngoing() || printingIsPaused())); @@ -770,7 +784,10 @@ void idle(bool no_stepper_sleep/*=false*/) { (void)check_tool_sensor_stats(active_extruder, true); // Handle filament runout sensors - TERN_(HAS_FILAMENT_SENSOR, runout.run()); + #if HAS_FILAMENT_SENSOR + if (TERN1(HAS_PRUSA_MMU2, !mmu2.enabled())) + runout.run(); + #endif // Run HAL idle tasks TERN_(HAL_IDLETASK, HAL_idletask()); @@ -825,6 +842,7 @@ void idle(bool no_stepper_sleep/*=false*/) { #if HAS_AUTO_REPORTING if (!gcode.autoreport_paused) { TERN_(AUTO_REPORT_TEMPERATURES, thermalManager.auto_reporter.tick()); + TERN_(AUTO_REPORT_FANS, fan_check.auto_reporter.tick()); TERN_(AUTO_REPORT_SD_STATUS, card.auto_reporter.tick()); TERN_(AUTO_REPORT_POSITION, position_auto_reporter.tick()); TERN_(BUFFER_MONITORING, queue.auto_report_buffer_statistics()); @@ -852,16 +870,16 @@ void idle(bool no_stepper_sleep/*=false*/) { * Kill all activity and lock the machine. * After this the machine will need to be reset. */ -void kill(PGM_P const lcd_error/*=nullptr*/, PGM_P const lcd_component/*=nullptr*/, const bool steppers_off/*=false*/) { +void kill(FSTR_P const lcd_error/*=nullptr*/, FSTR_P const lcd_component/*=nullptr*/, const bool steppers_off/*=false*/) { thermalManager.disable_all_heaters(); TERN_(HAS_CUTTER, cutter.kill()); // Full cutter shutdown including ISR control // Echo the LCD message to serial for extra context - if (lcd_error) { SERIAL_ECHO_START(); SERIAL_ECHOLNPGM_P(lcd_error); } + if (lcd_error) { SERIAL_ECHO_START(); SERIAL_ECHOLNF(lcd_error); } #if EITHER(HAS_DISPLAY, DWIN_CREALITY_LCD_ENHANCED) - ui.kill_screen(lcd_error ?: GET_TEXT(MSG_KILLED), lcd_component ?: NUL_STR); + ui.kill_screen(lcd_error ?: GET_TEXT_F(MSG_KILLED), lcd_component ?: FPSTR(NUL_STR)); #else UNUSED(lcd_error); UNUSED(lcd_component); #endif @@ -872,7 +890,7 @@ void kill(PGM_P const lcd_error/*=nullptr*/, PGM_P const lcd_component/*=nullptr SERIAL_ERROR_MSG(STR_ERR_KILLED); #ifdef ACTION_ON_KILL - host_action_kill(); + hostui.kill(); #endif minkill(steppers_off); @@ -935,7 +953,7 @@ void stop() { if (!IsStopped()) { SERIAL_ERROR_MSG(STR_ERR_STOPPED); - LCD_MESSAGEPGM(MSG_STOPPED); + LCD_MESSAGE(MSG_STOPPED); safe_delay(350); // allow enough time for messages to get out before stopping marlin_state = MF_STOPPED; } @@ -1100,6 +1118,10 @@ void setup() { tmc_standby_setup(); // TMC Low Power Standby pins must be set early or they're not usable + // Check startup - does nothing if bootloader sets MCUSR to 0 + const byte mcu = HAL_get_reset_source(); + HAL_clear_reset_source(); + #if ENABLED(MARLIN_DEV_MODE) auto log_current_ms = [&](PGM_P const msg) { SERIAL_ECHO_START(); @@ -1228,15 +1250,14 @@ void setup() { SETUP_RUN(esp_wifi_init()); - // Check startup - does nothing if bootloader sets MCUSR to 0 - const byte mcu = HAL_get_reset_source(); + // Report Reset Reason if (mcu & RST_POWER_ON) SERIAL_ECHOLNPGM(STR_POWERUP); if (mcu & RST_EXTERNAL) SERIAL_ECHOLNPGM(STR_EXTERNAL_RESET); if (mcu & RST_BROWN_OUT) SERIAL_ECHOLNPGM(STR_BROWNOUT_RESET); if (mcu & RST_WATCHDOG) SERIAL_ECHOLNPGM(STR_WATCHDOG_RESET); if (mcu & RST_SOFTWARE) SERIAL_ECHOLNPGM(STR_SOFTWARE_RESET); - HAL_clear_reset_source(); + // Identify myself as Marlin x.x.x SERIAL_ECHOLNPGM("Marlin " SHORT_BUILD_VERSION); #if defined(STRING_DISTRIBUTION_DATE) && defined(STRING_CONFIG_H_AUTHOR) SERIAL_ECHO_MSG( @@ -1268,6 +1289,8 @@ void setup() { SETUP_RUN(controllerFan.setup()); #endif + TERN_(HAS_FANCHECK, fan_check.init()); + // UI must be initialized before EEPROM // (because EEPROM code calls the UI). @@ -1346,6 +1369,9 @@ void setup() { #endif #if HAS_BED_PROBE + #if PIN_EXISTS(PROBE_ENABLE) + OUT_WRITE(PROBE_ENABLE_PIN, LOW); // Disable + #endif SETUP_RUN(endstops.enable_z_probe(false)); #endif @@ -1521,11 +1547,11 @@ void setup() { #ifdef STARTUP_COMMANDS SETUP_LOG("STARTUP_COMMANDS"); - queue.inject_P(PSTR(STARTUP_COMMANDS)); + queue.inject(F(STARTUP_COMMANDS)); #endif #if ENABLED(HOST_PROMPT_SUPPORT) - SETUP_RUN(host_action_prompt_end()); + SETUP_RUN(hostui.prompt_end()); #endif #if HAS_TRINAMIC_CONFIG && DISABLED(PSU_DEFAULT_OFF) @@ -1547,15 +1573,15 @@ void setup() { #endif #if HAS_DWIN_E3V2_BASIC + SETUP_LOG("E3V2 Init"); Encoder_Configuration(); HMI_Init(); HMI_SetLanguageCache(); HMI_StartFrame(true); - DWIN_StatusChanged_P(GET_TEXT(WELCOME_MSG)); #endif #if HAS_SERVICE_INTERVALS && !HAS_DWIN_E3V2_BASIC - ui.reset_status(true); // Show service messages or keep current status + SETUP_RUN(ui.reset_status(true)); // Show service messages or keep current status #endif #if ENABLED(MAX7219_DEBUG) @@ -1586,7 +1612,11 @@ void setup() { #endif #if BOTH(HAS_LCD_MENU, TOUCH_SCREEN_CALIBRATION) && EITHER(TFT_CLASSIC_UI, TFT_COLOR_UI) - ui.check_touch_calibration(); + SETUP_RUN(ui.check_touch_calibration()); + #endif + + #if ENABLED(EASYTHREED_UI) + SETUP_RUN(easythreed_ui.init()); #endif #if ENABLED(MKS_WIFI) mks_wifi_init(); diff --git a/Marlin/src/MarlinCore.h b/Marlin/src/MarlinCore.h index c3698d616d..7063c7e2de 100644 --- a/Marlin/src/MarlinCore.h +++ b/Marlin/src/MarlinCore.h @@ -38,7 +38,7 @@ inline void idle_no_sleep() { idle(true); } extern bool G38_did_trigger; // Flag from the ISR to indicate the endstop changed #endif -void kill(PGM_P const lcd_error=nullptr, PGM_P const lcd_component=nullptr, const bool steppers_off=false); +void kill(FSTR_P const lcd_error=nullptr, FSTR_P const lcd_component=nullptr, const bool steppers_off=false); void minkill(const bool steppers_off=false); // Global State of the firmware diff --git a/Marlin/src/core/boards.h b/Marlin/src/core/boards.h index 82c68f3171..aee9b3c492 100644 --- a/Marlin/src/core/boards.h +++ b/Marlin/src/core/boards.h @@ -324,39 +324,41 @@ #define BOARD_BTT_SKR_MINI_E3_V1_0 4024 // BigTreeTech SKR Mini E3 (STM32F103RC) #define BOARD_BTT_SKR_MINI_E3_V1_2 4025 // BigTreeTech SKR Mini E3 V1.2 (STM32F103RC) #define BOARD_BTT_SKR_MINI_E3_V2_0 4026 // BigTreeTech SKR Mini E3 V2.0 (STM32F103RC / STM32F103RE) -#define BOARD_BTT_SKR_MINI_MZ_V1_0 4027 // BigTreeTech SKR Mini MZ V1.0 (STM32F103RC) -#define BOARD_BTT_SKR_E3_DIP 4028 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / STM32F103RE) -#define BOARD_BTT_SKR_CR6 4029 // BigTreeTech SKR CR6 v1.0 (STM32F103RE) -#define BOARD_JGAURORA_A5S_A1 4030 // JGAurora A5S A1 (STM32F103ZET6) -#define BOARD_FYSETC_AIO_II 4031 // FYSETC AIO_II -#define BOARD_FYSETC_CHEETAH 4032 // FYSETC Cheetah -#define BOARD_FYSETC_CHEETAH_V12 4033 // FYSETC Cheetah V1.2 -#define BOARD_LONGER3D_LK 4034 // Alfawise U20/U20+/U30 (Longer3D LK1/2) / STM32F103VET6 -#define BOARD_CCROBOT_MEEB_3DP 4035 // ccrobot-online.com MEEB_3DP (STM32F103RC) -#define BOARD_CHITU3D_V5 4036 // Chitu3D TronXY X5SA V5 Board -#define BOARD_CHITU3D_V6 4037 // Chitu3D TronXY X5SA V6 Board -#define BOARD_CHITU3D_V9 4038 // Chitu3D TronXY X5SA V9 Board -#define BOARD_CREALITY_V4 4039 // Creality v4.x (STM32F103RE) -#define BOARD_CREALITY_V427 4040 // Creality v4.2.7 (STM32F103RE) -#define BOARD_CREALITY_V4210 4041 // Creality v4.2.10 (STM32F103RE) as found in the CR-30 -#define BOARD_CREALITY_V431 4042 // Creality v4.3.1 (STM32F103RE) -#define BOARD_CREALITY_V431_A 4043 // Creality v4.3.1a (STM32F103RE) -#define BOARD_CREALITY_V431_B 4044 // Creality v4.3.1b (STM32F103RE) -#define BOARD_CREALITY_V431_C 4045 // Creality v4.3.1c (STM32F103RE) -#define BOARD_CREALITY_V431_D 4046 // Creality v4.3.1d (STM32F103RE) -#define BOARD_CREALITY_V452 4047 // Creality v4.5.2 (STM32F103RE) -#define BOARD_CREALITY_V453 4048 // Creality v4.5.3 (STM32F103RE) -#define BOARD_CREALITY_V24S1 4049 // Creality v2.4.S1 (STM32F103RE) v101 as found in the Ender 7 -#define BOARD_TRIGORILLA_PRO 4050 // Trigorilla Pro (STM32F103ZET6) -#define BOARD_FLY_MINI 4051 // FLYmaker FLY MINI (STM32F103RCT6) -#define BOARD_FLSUN_HISPEED 4052 // FLSUN HiSpeedV1 (STM32F103VET6) -#define BOARD_BEAST 4053 // STM32F103RET6 Libmaple-based controller -#define BOARD_MINGDA_MPX_ARM_MINI 4054 // STM32F103ZET6 Mingda MD-16 -#define BOARD_GTM32_PRO_VD 4055 // STM32F103VET6 controller -#define BOARD_ZONESTAR_ZM3E2 4056 // Zonestar ZM3E2 (STM32F103RCT6) -#define BOARD_ZONESTAR_ZM3E4 4057 // Zonestar ZM3E4 V1 (STM32F103VCT6) -#define BOARD_ZONESTAR_ZM3E4V2 4058 // Zonestar ZM3E4 V2 (STM32F103VCT6) -#define BOARD_ERYONE_ERY32_MINI 4059 // Eryone Ery32 mini (STM32F103VET6) +#define BOARD_BTT_SKR_MINI_E3_V3_0 4027 // BigTreeTech SKR Mini E3 V3.0 (STM32G0B1RE) +#define BOARD_BTT_SKR_MINI_MZ_V1_0 4028 // BigTreeTech SKR Mini MZ V1.0 (STM32F103RC) +#define BOARD_BTT_SKR_E3_DIP 4029 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / STM32F103RE) +#define BOARD_BTT_SKR_CR6 4030 // BigTreeTech SKR CR6 v1.0 (STM32F103RE) +#define BOARD_JGAURORA_A5S_A1 4031 // JGAurora A5S A1 (STM32F103ZET6) +#define BOARD_FYSETC_AIO_II 4032 // FYSETC AIO_II +#define BOARD_FYSETC_CHEETAH 4033 // FYSETC Cheetah +#define BOARD_FYSETC_CHEETAH_V12 4034 // FYSETC Cheetah V1.2 +#define BOARD_LONGER3D_LK 4035 // Alfawise U20/U20+/U30 (Longer3D LK1/2) / STM32F103VET6 +#define BOARD_CCROBOT_MEEB_3DP 4036 // ccrobot-online.com MEEB_3DP (STM32F103RC) +#define BOARD_CHITU3D_V5 4037 // Chitu3D TronXY X5SA V5 Board +#define BOARD_CHITU3D_V6 4038 // Chitu3D TronXY X5SA V6 Board +#define BOARD_CHITU3D_V9 4039 // Chitu3D TronXY X5SA V9 Board +#define BOARD_CREALITY_V4 4040 // Creality v4.x (STM32F103RE) +#define BOARD_CREALITY_V423 4041 // Creality v4.2.3 (STM32F103RE) +#define BOARD_CREALITY_V427 4042 // Creality v4.2.7 (STM32F103RE) +#define BOARD_CREALITY_V4210 4043 // Creality v4.2.10 (STM32F103RE) as found in the CR-30 +#define BOARD_CREALITY_V431 4044 // Creality v4.3.1 (STM32F103RE) +#define BOARD_CREALITY_V431_A 4045 // Creality v4.3.1a (STM32F103RE) +#define BOARD_CREALITY_V431_B 4046 // Creality v4.3.1b (STM32F103RE) +#define BOARD_CREALITY_V431_C 4047 // Creality v4.3.1c (STM32F103RE) +#define BOARD_CREALITY_V431_D 4048 // Creality v4.3.1d (STM32F103RE) +#define BOARD_CREALITY_V452 4049 // Creality v4.5.2 (STM32F103RE) +#define BOARD_CREALITY_V453 4050 // Creality v4.5.3 (STM32F103RE) +#define BOARD_CREALITY_V24S1 4051 // Creality v2.4.S1 (STM32F103RE) v101 as found in the Ender 7 +#define BOARD_TRIGORILLA_PRO 4052 // Trigorilla Pro (STM32F103ZET6) +#define BOARD_FLY_MINI 4053 // FLYmaker FLY MINI (STM32F103RCT6) +#define BOARD_FLSUN_HISPEED 4054 // FLSUN HiSpeedV1 (STM32F103VET6) +#define BOARD_BEAST 4055 // STM32F103RET6 Libmaple-based controller +#define BOARD_MINGDA_MPX_ARM_MINI 4056 // STM32F103ZET6 Mingda MD-16 +#define BOARD_GTM32_PRO_VD 4057 // STM32F103VET6 controller +#define BOARD_ZONESTAR_ZM3E2 4058 // Zonestar ZM3E2 (STM32F103RCT6) +#define BOARD_ZONESTAR_ZM3E4 4059 // Zonestar ZM3E4 V1 (STM32F103VCT6) +#define BOARD_ZONESTAR_ZM3E4V2 4060 // Zonestar ZM3E4 V2 (STM32F103VCT6) +#define BOARD_ERYONE_ERY32_MINI 4061 // Eryone Ery32 mini (STM32F103VET6) // // ARM Cortex-M4F @@ -382,7 +384,7 @@ #define BOARD_BTT_BTT002_V1_0 4210 // BigTreeTech BTT002 v1.0 (STM32F407VGT6) #define BOARD_BTT_E3_RRF 4211 // BigTreeTech E3 RRF (STM32F407VGT6) #define BOARD_BTT_SKR_V2_0_REV_A 4212 // BigTreeTech SKR v2.0 Rev A (STM32F407VGT6) -#define BOARD_BTT_SKR_V2_0_REV_B 4213 // BigTreeTech SKR v2.0 Rev B (STM32F407VGT6) +#define BOARD_BTT_SKR_V2_0_REV_B 4213 // BigTreeTech SKR v2.0 Rev B (STM32F407VGT6/STM32F429VGT6) #define BOARD_BTT_GTR_V1_0 4214 // BigTreeTech GTR v1.0 (STM32F407IGT) #define BOARD_BTT_OCTOPUS_V1_0 4215 // BigTreeTech Octopus v1.0 (STM32F446ZET6) #define BOARD_BTT_OCTOPUS_V1_1 4216 // BigTreeTech Octopus v1.1 (STM32F446ZET6) @@ -402,10 +404,12 @@ #define BOARD_ANET_ET4 4230 // ANET ET4 V1.x (STM32F407VGT6) #define BOARD_ANET_ET4P 4231 // ANET ET4P V1.x (STM32F407VGT6) #define BOARD_FYSETC_CHEETAH_V20 4232 // FYSETC Cheetah V2.0 -#define BOARD_TH3D_EZBOARD_LITE_V2 4233 // TH3D EZBoard Lite v2.0 +#define BOARD_TH3D_EZBOARD_V2 4233 // TH3D EZBoard v2.0 #define BOARD_INDEX_REV03 4234 // Index PnP Controller REV03 (STM32F407VET6/VGT6) #define BOARD_MKS_ROBIN_NANO_V1_3_F4 4235 // MKS Robin Nano V1.3 and MKS Robin Nano-S V1.3 (STM32F407VET6) #define BOARD_MKS_EAGLE 4236 // MKS Eagle (STM32F407VET6) +#define BOARD_ARTILLERY_RUBY 4237 // Artillery Ruby (STM32F401RCT6) +#define BOARD_FYSETC_SPIDER_V2_2 4238 // FYSETC Spider V2.2 (STM32F446VET6) // // ARM Cortex M7 @@ -425,9 +429,11 @@ #define BOARD_MRR_ESPA 6001 // MRR ESPA based on ESP32 (native pins only) #define BOARD_MRR_ESPE 6002 // MRR ESPE based on ESP32 (with I2S stepper stream) #define BOARD_E4D_BOX 6003 // E4d@BOX -#define BOARD_FYSETC_E4 6004 // FYSETC E4 -#define BOARD_PANDA_ZHU 6005 // Panda_ZHU -#define BOARD_PANDA_M4 6006 // Panda_M4 +#define BOARD_RESP32_CUSTOM 6004 // Rutilea ESP32 custom board +#define BOARD_FYSETC_E4 6005 // FYSETC E4 +#define BOARD_PANDA_ZHU 6006 // Panda_ZHU +#define BOARD_PANDA_M4 6007 // Panda_M4 +#define BOARD_MKS_TINYBEE 6008 // MKS TinyBee based on ESP32 (with I2S stepper stream) // // SAMD51 ARM Cortex M4 diff --git a/Marlin/src/core/debug_out.h b/Marlin/src/core/debug_out.h index 4e30a5306e..eb1c91e507 100644 --- a/Marlin/src/core/debug_out.h +++ b/Marlin/src/core/debug_out.h @@ -36,6 +36,8 @@ #undef DEBUG_ECHOLN #undef DEBUG_ECHOPGM #undef DEBUG_ECHOLNPGM +#undef DEBUG_ECHOF +#undef DEBUG_ECHOLNF #undef DEBUG_ECHOPGM_P #undef DEBUG_ECHOLNPGM_P #undef DEBUG_ECHOPAIR_F @@ -54,7 +56,7 @@ #if DEBUG_OUT #include "debug_section.h" - #define DEBUG_SECTION(N,S,D) SectionLog N(PSTR(S),D) + #define DEBUG_SECTION(N,S,D) SectionLog N(F(S),D) #define DEBUG_ECHO_START SERIAL_ECHO_START #define DEBUG_ERROR_START SERIAL_ERROR_START @@ -65,6 +67,8 @@ #define DEBUG_ECHOLN SERIAL_ECHOLN #define DEBUG_ECHOPGM SERIAL_ECHOPGM #define DEBUG_ECHOLNPGM SERIAL_ECHOLNPGM + #define DEBUG_ECHOF SERIAL_ECHOF + #define DEBUG_ECHOLNF SERIAL_ECHOLNF #define DEBUG_ECHOPGM SERIAL_ECHOPGM #define DEBUG_ECHOPGM_P SERIAL_ECHOPGM_P #define DEBUG_ECHOPAIR_F SERIAL_ECHOPAIR_F @@ -94,6 +98,8 @@ #define DEBUG_ECHOLN(...) NOOP #define DEBUG_ECHOPGM(...) NOOP #define DEBUG_ECHOLNPGM(...) NOOP + #define DEBUG_ECHOF(...) NOOP + #define DEBUG_ECHOLNF(...) NOOP #define DEBUG_ECHOPGM_P(...) NOOP #define DEBUG_ECHOLNPGM_P(...) NOOP #define DEBUG_ECHOPAIR_F(...) NOOP diff --git a/Marlin/src/core/debug_section.h b/Marlin/src/core/debug_section.h index ef1511e6f0..6e23d9e4ed 100644 --- a/Marlin/src/core/debug_section.h +++ b/Marlin/src/core/debug_section.h @@ -26,22 +26,22 @@ class SectionLog { public: - SectionLog(PGM_P const msg=nullptr, bool inbug=true) { - the_msg = msg; - if ((debug = inbug)) echo_msg(PSTR(">>>")); + SectionLog(FSTR_P const fmsg=nullptr, bool inbug=true) { + the_msg = fmsg; + if ((debug = inbug)) echo_msg(F(">>>")); } - ~SectionLog() { if (debug) echo_msg(PSTR("<<<")); } + ~SectionLog() { if (debug) echo_msg(F("<<<")); } private: - PGM_P the_msg; + FSTR_P the_msg; bool debug; - void echo_msg(PGM_P const pre) { - SERIAL_ECHOPGM_P(pre); + void echo_msg(FSTR_P const fpre) { + SERIAL_ECHOF(fpre); if (the_msg) { SERIAL_CHAR(' '); - SERIAL_ECHOPGM_P(the_msg); + SERIAL_ECHOF(the_msg); } SERIAL_CHAR(' '); print_pos(current_position); diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 03bffb8bd9..0a6870af26 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -140,6 +140,7 @@ #define STR_RESEND "Resend: " #define STR_UNKNOWN_COMMAND "Unknown command: \"" #define STR_ACTIVE_EXTRUDER "Active Extruder: " +#define STR_ERR_FANSPEED "Fan speed E" #define STR_PROBE_OFFSET "Probe Offset" #define STR_SKEW_MIN "min_skew_factor: " diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index 22c3767e1d..62675d1319 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -33,6 +33,12 @@ #define _AXIS(A) (A##_AXIS) +#define _XSTOP_ 0x01 +#define _YSTOP_ 0x02 +#define _ZSTOP_ 0x03 +#define _ISTOP_ 0x04 +#define _JSTOP_ 0x05 +#define _KSTOP_ 0x06 #define _XMIN_ 0x11 #define _YMIN_ 0x12 #define _ZMIN_ 0x13 @@ -160,7 +166,7 @@ #endif -// Macros to chain up to 14 conditions +// Macros to chain up to 40 conditions #define _DO_1(W,C,A) (_##W##_1(A)) #define _DO_2(W,C,A,B) (_##W##_1(A) C _##W##_1(B)) #define _DO_3(W,C,A,V...) (_##W##_1(A) C _DO_2(W,C,V)) @@ -176,6 +182,31 @@ #define _DO_13(W,C,A,V...) (_##W##_1(A) C _DO_12(W,C,V)) #define _DO_14(W,C,A,V...) (_##W##_1(A) C _DO_13(W,C,V)) #define _DO_15(W,C,A,V...) (_##W##_1(A) C _DO_14(W,C,V)) +#define _DO_16(W,C,A,V...) (_##W##_1(A) C _DO_15(W,C,V)) +#define _DO_17(W,C,A,V...) (_##W##_1(A) C _DO_16(W,C,V)) +#define _DO_18(W,C,A,V...) (_##W##_1(A) C _DO_17(W,C,V)) +#define _DO_19(W,C,A,V...) (_##W##_1(A) C _DO_18(W,C,V)) +#define _DO_20(W,C,A,V...) (_##W##_1(A) C _DO_19(W,C,V)) +#define _DO_21(W,C,A,V...) (_##W##_1(A) C _DO_20(W,C,V)) +#define _DO_22(W,C,A,V...) (_##W##_1(A) C _DO_21(W,C,V)) +#define _DO_23(W,C,A,V...) (_##W##_1(A) C _DO_22(W,C,V)) +#define _DO_24(W,C,A,V...) (_##W##_1(A) C _DO_23(W,C,V)) +#define _DO_25(W,C,A,V...) (_##W##_1(A) C _DO_24(W,C,V)) +#define _DO_26(W,C,A,V...) (_##W##_1(A) C _DO_25(W,C,V)) +#define _DO_27(W,C,A,V...) (_##W##_1(A) C _DO_26(W,C,V)) +#define _DO_28(W,C,A,V...) (_##W##_1(A) C _DO_27(W,C,V)) +#define _DO_29(W,C,A,V...) (_##W##_1(A) C _DO_28(W,C,V)) +#define _DO_30(W,C,A,V...) (_##W##_1(A) C _DO_29(W,C,V)) +#define _DO_31(W,C,A,V...) (_##W##_1(A) C _DO_30(W,C,V)) +#define _DO_32(W,C,A,V...) (_##W##_1(A) C _DO_31(W,C,V)) +#define _DO_33(W,C,A,V...) (_##W##_1(A) C _DO_32(W,C,V)) +#define _DO_34(W,C,A,V...) (_##W##_1(A) C _DO_33(W,C,V)) +#define _DO_35(W,C,A,V...) (_##W##_1(A) C _DO_34(W,C,V)) +#define _DO_36(W,C,A,V...) (_##W##_1(A) C _DO_35(W,C,V)) +#define _DO_37(W,C,A,V...) (_##W##_1(A) C _DO_36(W,C,V)) +#define _DO_38(W,C,A,V...) (_##W##_1(A) C _DO_37(W,C,V)) +#define _DO_39(W,C,A,V...) (_##W##_1(A) C _DO_38(W,C,V)) +#define _DO_40(W,C,A,V...) (_##W##_1(A) C _DO_39(W,C,V)) #define __DO_N(W,C,N,V...) _DO_##N(W,C,V) #define _DO_N(W,C,N,V...) __DO_N(W,C,N,V) #define DO(W,C,V...) (_DO_N(W,C,NUM_ARGS(V),V)) @@ -251,6 +282,11 @@ memcpy(&a[0],&b[0],_MIN(sizeof(a),sizeof(b))); \ }while(0) +#define CODE_16( A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,...) A; B; C; D; E; F; G; H; I; J; K; L; M; N; O; P +#define CODE_15( A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,...) A; B; C; D; E; F; G; H; I; J; K; L; M; N; O +#define CODE_14( A,B,C,D,E,F,G,H,I,J,K,L,M,N,...) A; B; C; D; E; F; G; H; I; J; K; L; M; N +#define CODE_13( A,B,C,D,E,F,G,H,I,J,K,L,M,...) A; B; C; D; E; F; G; H; I; J; K; L; M +#define CODE_12( A,B,C,D,E,F,G,H,I,J,K,L,...) A; B; C; D; E; F; G; H; I; J; K; L #define CODE_11( A,B,C,D,E,F,G,H,I,J,K,...) A; B; C; D; E; F; G; H; I; J; K #define CODE_10( A,B,C,D,E,F,G,H,I,J,...) A; B; C; D; E; F; G; H; I; J #define CODE_9( A,B,C,D,E,F,G,H,I,...) A; B; C; D; E; F; G; H; I diff --git a/Marlin/src/core/serial.cpp b/Marlin/src/core/serial.cpp index 8c9f4a8e4d..9cd862df70 100644 --- a/Marlin/src/core/serial.cpp +++ b/Marlin/src/core/serial.cpp @@ -69,23 +69,23 @@ PGMSTR(SP_I_LBL, " " AXIS4_STR ":"); PGMSTR(SP_J_LBL, " " AXIS5_STR ":"); PGMSTR #endif -void serialprintPGM(PGM_P str) { +void serial_print_P(PGM_P str) { while (const char c = pgm_read_byte(str++)) SERIAL_CHAR(c); } -void serial_echo_start() { static PGMSTR(echomagic, "echo:"); serialprintPGM(echomagic); } -void serial_error_start() { static PGMSTR(errormagic, "Error:"); serialprintPGM(errormagic); } +void serial_echo_start() { static PGMSTR(echomagic, "echo:"); serial_print_P(echomagic); } +void serial_error_start() { static PGMSTR(errormagic, "Error:"); serial_print_P(errormagic); } void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); } -void serial_ternary(const bool onoff, PGM_P const pre, PGM_P const on, PGM_P const off, PGM_P const post/*=nullptr*/) { - if (pre) serialprintPGM(pre); - serialprintPGM(onoff ? on : off); - if (post) serialprintPGM(post); +void serial_ternary(const bool onoff, FSTR_P const pre, FSTR_P const on, FSTR_P const off, FSTR_P const post/*=nullptr*/) { + if (pre) serial_print(pre); + serial_print(onoff ? on : off); + if (post) serial_print(post); } -void serialprint_onoff(const bool onoff) { serialprintPGM(onoff ? PSTR(STR_ON) : PSTR(STR_OFF)); } +void serialprint_onoff(const bool onoff) { serial_print(onoff ? F(STR_ON) : F(STR_OFF)); } void serialprintln_onoff(const bool onoff) { serialprint_onoff(onoff); SERIAL_EOL(); } -void serialprint_truefalse(const bool tf) { serialprintPGM(tf ? PSTR("true") : PSTR("false")); } +void serialprint_truefalse(const bool tf) { serial_print(tf ? F("true") : F("false")); } void print_bin(uint16_t val) { for (uint8_t i = 16; i--;) { @@ -94,10 +94,10 @@ void print_bin(uint16_t val) { } } -void print_pos(LINEAR_AXIS_ARGS(const_float_t), PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/) { - if (prefix) serialprintPGM(prefix); +void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix/*=nullptr*/, FSTR_P const suffix/*=nullptr*/) { + if (prefix) serial_print(prefix); SERIAL_ECHOPGM_P( LIST_N(DOUBLE(LINEAR_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k) ); - if (suffix) serialprintPGM(suffix); else SERIAL_EOL(); + if (suffix) serial_print(suffix); else SERIAL_EOL(); } diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h index 05d80a4829..aee4d4d43d 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -87,7 +87,7 @@ extern uint8_t marlin_debug_flags; // interface with the ability to output to multiple serial ports. #if HAS_MULTI_SERIAL #define _PORT_REDIRECT(n,p) REMEMBER(n,multiSerial.portMask,p) - #define _PORT_RESTORE(n,p) RESTORE(n) + #define _PORT_RESTORE(n) RESTORE(n) #define SERIAL_ASSERT(P) if (multiSerial.portMask!=(P)) { debugger(); } // If we have a catchall, use that directly #ifdef SERIAL_CATCHALL @@ -167,13 +167,10 @@ inline void SERIAL_ECHO(serial_char_t x) { SERIAL_IMPL.write(x.c); } #define AS_CHAR(C) serial_char_t(C) #define AS_DIGIT(C) AS_CHAR('0' + (C)) -// SERIAL_ECHO_F prints a floating point value with optional precision -inline void SERIAL_ECHO_F(EnsureDouble x, int digit=2) { SERIAL_IMPL.print(x, digit); } - template void SERIAL_ECHOLN(T x) { SERIAL_IMPL.println(x); } -// SERIAL_PRINT works like SERIAL_ECHO but allow to specify the encoding base of the number printed +// SERIAL_PRINT works like SERIAL_ECHO but also takes the numeric base template void SERIAL_PRINT(T x, U y) { SERIAL_IMPL.print(x, y); } @@ -184,8 +181,20 @@ void SERIAL_PRINTLN(T x, PrintBase y) { SERIAL_IMPL.println(x, y); } inline void SERIAL_FLUSH() { SERIAL_IMPL.flush(); } inline void SERIAL_FLUSHTX() { SERIAL_IMPL.flushTX(); } -// Print a single PROGMEM string to serial -void serialprintPGM(PGM_P str); +// Serial echo and error prefixes +#define SERIAL_ECHO_START() serial_echo_start() +#define SERIAL_ERROR_START() serial_error_start() + +// Serial end-of-line +#define SERIAL_EOL() SERIAL_CHAR('\n') + +// Print a single PROGMEM, PGM_P, or PSTR() string. +void serial_print_P(PGM_P str); +inline void serial_println_P(PGM_P str) { serial_print_P(str); SERIAL_EOL(); } + +// Print a single FSTR_P, F(), or FPSTR() string. +inline void serial_print(FSTR_P const fstr) { serial_print_P(FTOP(fstr)); } +inline void serial_println(FSTR_P const fstr) { serial_println_P(FTOP(fstr)); } // // SERIAL_ECHOPGM... macros are used to output string-value pairs. @@ -195,8 +204,8 @@ void serialprintPGM(PGM_P str); #define __SEP_N(N,V...) _SEP_##N(V) #define _SEP_N(N,V...) __SEP_N(N,V) #define _SEP_N_REF() _SEP_N -#define _SEP_1(s) serialprintPGM(PSTR(s)); -#define _SEP_2(s,v) serial_echopair_PGM(PSTR(s),v); +#define _SEP_1(s) serial_print(F(s)); +#define _SEP_2(s,v) serial_echopair(F(s),v); #define _SEP_3(s,v,V...) _SEP_2(s,v); DEFER2(_SEP_N_REF)()(TWO_ARGS(V),V); #define SERIAL_ECHOPGM(V...) do{ EVAL(_SEP_N(TWO_ARGS(V),V)); }while(0) @@ -204,8 +213,8 @@ void serialprintPGM(PGM_P str); #define __SELP_N(N,V...) _SELP_##N(V) #define _SELP_N(N,V...) __SELP_N(N,V) #define _SELP_N_REF() _SELP_N -#define _SELP_1(s) serialprintPGM(PSTR(s "\n")); -#define _SELP_2(s,v) serial_echopair_PGM(PSTR(s),v); SERIAL_EOL(); +#define _SELP_1(s) serial_print(F(s "\n")); +#define _SELP_2(s,v) serial_echolnpair(F(s),v); #define _SELP_3(s,v,V...) _SEP_2(s,v); DEFER2(_SELP_N_REF)()(TWO_ARGS(V),V); #define SERIAL_ECHOLNPGM(V...) do{ EVAL(_SELP_N(TWO_ARGS(V),V)); }while(0) @@ -213,8 +222,8 @@ void serialprintPGM(PGM_P str); #define __SEP_N_P(N,V...) _SEP_##N##_P(V) #define _SEP_N_P(N,V...) __SEP_N_P(N,V) #define _SEP_N_P_REF() _SEP_N_P -#define _SEP_1_P(p) serialprintPGM(p); -#define _SEP_2_P(p,v) serial_echopair_PGM(p,v); +#define _SEP_1_P(p) serial_print_P(p); +#define _SEP_2_P(p,v) serial_echopair_P(p,v); #define _SEP_3_P(p,v,V...) _SEP_2_P(p,v); DEFER2(_SEP_N_P_REF)()(TWO_ARGS(V),V); #define SERIAL_ECHOPGM_P(V...) do{ EVAL(_SEP_N_P(TWO_ARGS(V),V)); }while(0) @@ -222,11 +231,29 @@ void serialprintPGM(PGM_P str); #define __SELP_N_P(N,V...) _SELP_##N##_P(V) #define _SELP_N_P(N,V...) __SELP_N_P(N,V) #define _SELP_N_P_REF() _SELP_N_P -#define _SELP_1_P(p) { serialprintPGM(p); SERIAL_EOL(); } -#define _SELP_2_P(p,v) { serial_echopair_PGM(p,v); SERIAL_EOL(); } +#define _SELP_1_P(p) serial_println_P(p) +#define _SELP_2_P(p,v) serial_echolnpair_P(p,v) #define _SELP_3_P(p,v,V...) { _SEP_2_P(p,v); DEFER2(_SELP_N_P_REF)()(TWO_ARGS(V),V); } #define SERIAL_ECHOLNPGM_P(V...) do{ EVAL(_SELP_N_P(TWO_ARGS(V),V)); }while(0) +// Print up to 20 pairs of values. Odd elements must be FSTR_P, F(), or FPSTR(). +#define __SEP_N_F(N,V...) _SEP_##N##_F(V) +#define _SEP_N_F(N,V...) __SEP_N_F(N,V) +#define _SEP_N_F_REF() _SEP_N_F +#define _SEP_1_F(p) serial_print(p); +#define _SEP_2_F(p,v) serial_echopair(p,v); +#define _SEP_3_F(p,v,V...) _SEP_2_F(p,v); DEFER2(_SEP_N_F_REF)()(TWO_ARGS(V),V); +#define SERIAL_ECHOF(V...) do{ EVAL(_SEP_N_F(TWO_ARGS(V),V)); }while(0) + +// Print up to 20 pairs of values followed by newline. Odd elements must be FSTR_P, F(), or FPSTR(). +#define __SELP_N_F(N,V...) _SELP_##N##_F(V) +#define _SELP_N_F(N,V...) __SELP_N_F(N,V) +#define _SELP_N_F_REF() _SELP_N_F +#define _SELP_1_F(p) serial_println(p) +#define _SELP_2_F(p,v) serial_echolnpair(p,v) +#define _SELP_3_F(p,v,V...) { _SEP_2_F(p,v); DEFER2(_SELP_N_F_REF)()(TWO_ARGS(V),V); } +#define SERIAL_ECHOLNF(V...) do{ EVAL(_SELP_N_F(TWO_ARGS(V),V)); }while(0) + #ifdef AllowDifferentTypeInList inline void SERIAL_ECHOLIST_IMPL() {} @@ -236,47 +263,49 @@ void serialprintPGM(PGM_P str); template void SERIAL_ECHOLIST_IMPL(T && t, Args && ... args) { SERIAL_IMPL.print(t); - serialprintPGM(PSTR(", ")); + serial_print(F(", ")); SERIAL_ECHOLIST_IMPL(args...); } template - void SERIAL_ECHOLIST(PGM_P const str, Args && ... args) { - SERIAL_IMPL.print(str); + void SERIAL_ECHOLIST(FSTR_P const str, Args && ... args) { + SERIAL_IMPL.print(FTOP(str)); SERIAL_ECHOLIST_IMPL(args...); } #else // Optimization if the listed type are all the same (seems to be the case in the codebase so use that instead) template - void SERIAL_ECHOLIST(PGM_P const str, Args && ... args) { - serialprintPGM(str); + void SERIAL_ECHOLIST(FSTR_P const fstr, Args && ... args) { + serial_print(fstr); typename Private::first_type_of::type values[] = { args... }; constexpr size_t argsSize = sizeof...(args); for (size_t i = 0; i < argsSize; i++) { - if (i) serialprintPGM(PSTR(", ")); + if (i) serial_print(F(", ")); SERIAL_IMPL.print(values[i]); } } #endif -#define SERIAL_ECHOPAIR_F_P(P,V...) do{ serialprintPGM(P); SERIAL_ECHO_F(V); }while(0) -#define SERIAL_ECHOLNPAIR_F_P(V...) do{ SERIAL_ECHOPAIR_F_P(V); SERIAL_EOL(); }while(0) +// SERIAL_ECHO_F prints a floating point value with optional precision +inline void SERIAL_ECHO_F(EnsureDouble x, int digit=2) { SERIAL_IMPL.print(x, digit); } + +#define SERIAL_ECHOPAIR_F_P(P,V...) do{ serial_print_P(P); SERIAL_ECHO_F(V); }while(0) +#define SERIAL_ECHOLNPAIR_F_P(P,V...) do{ SERIAL_ECHOPAIR_F_P(P,V); SERIAL_EOL(); }while(0) -#define SERIAL_ECHOPAIR_F(S,V...) SERIAL_ECHOPAIR_F_P(PSTR(S),V) -#define SERIAL_ECHOLNPAIR_F(V...) do{ SERIAL_ECHOPAIR_F(V); SERIAL_EOL(); }while(0) +#define SERIAL_ECHOPAIR_F_F(S,V...) do{ serial_print(S); SERIAL_ECHO_F(V); }while(0) +#define SERIAL_ECHOLNPAIR_F_F(S,V...) do{ SERIAL_ECHOPAIR_F_F(S,V); SERIAL_EOL(); }while(0) -#define SERIAL_ECHO_START() serial_echo_start() -#define SERIAL_ERROR_START() serial_error_start() -#define SERIAL_EOL() SERIAL_CHAR('\n') +#define SERIAL_ECHOPAIR_F(S,V...) SERIAL_ECHOPAIR_F_F(F(S),V) +#define SERIAL_ECHOLNPAIR_F(V...) do{ SERIAL_ECHOPAIR_F(V); SERIAL_EOL(); }while(0) -#define SERIAL_ECHO_MSG(V...) do{ SERIAL_ECHO_START(); SERIAL_ECHOLNPGM(V); }while(0) -#define SERIAL_ERROR_MSG(V...) do{ SERIAL_ERROR_START(); SERIAL_ECHOLNPGM(V); }while(0) +#define SERIAL_ECHO_MSG(V...) do{ SERIAL_ECHO_START(); SERIAL_ECHOLNPGM(V); }while(0) +#define SERIAL_ERROR_MSG(V...) do{ SERIAL_ERROR_START(); SERIAL_ECHOLNPGM(V); }while(0) -#define SERIAL_ECHO_SP(C) serial_spaces(C) +#define SERIAL_ECHO_SP(C) serial_spaces(C) -#define SERIAL_ECHO_TERNARY(TF, PRE, ON, OFF, POST) serial_ternary(TF, PSTR(PRE), PSTR(ON), PSTR(OFF), PSTR(POST)) +#define SERIAL_ECHO_TERNARY(TF, PRE, ON, OFF, POST) serial_ternary(TF, F(PRE), F(ON), F(OFF), F(POST)) #if SERIAL_FLOAT_PRECISION #define SERIAL_DECIMAL(V) SERIAL_PRINT(V, SERIAL_FLOAT_PRECISION) @@ -287,33 +316,42 @@ void serialprintPGM(PGM_P str); // // Functions for serial printing from PROGMEM. (Saves loads of SRAM.) // -inline void serial_echopair_PGM(PGM_P const s_P, serial_char_t v) { serialprintPGM(s_P); SERIAL_CHAR(v.c); } - -inline void serial_echopair_PGM(PGM_P const s_P, float v) { serialprintPGM(s_P); SERIAL_DECIMAL(v); } -inline void serial_echopair_PGM(PGM_P const s_P, double v) { serialprintPGM(s_P); SERIAL_DECIMAL(v); } -inline void serial_echopair_PGM(PGM_P const s_P, const char *v) { serialprintPGM(s_P); SERIAL_ECHO(v); } +inline void serial_echopair_P(PGM_P const pstr, serial_char_t v) { serial_print_P(pstr); SERIAL_CHAR(v.c); } +inline void serial_echopair_P(PGM_P const pstr, float v) { serial_print_P(pstr); SERIAL_DECIMAL(v); } +inline void serial_echopair_P(PGM_P const pstr, double v) { serial_print_P(pstr); SERIAL_DECIMAL(v); } +//inline void serial_echopair_P(PGM_P const pstr, const char *v) { serial_print_P(pstr); SERIAL_ECHO(v); } +inline void serial_echopair_P(PGM_P const pstr, FSTR_P v) { serial_print_P(pstr); SERIAL_ECHOF(v); } // Default implementation for types without a specialization. Handles integers. template -void serial_echopair_PGM(PGM_P const s_P, T v) { serialprintPGM(s_P); SERIAL_ECHO(v); } +inline void serial_echopair_P(PGM_P const pstr, T v) { serial_print_P(pstr); SERIAL_ECHO(v); } + +// Add a newline. +template +inline void serial_echolnpair_P(PGM_P const pstr, T v) { serial_echopair_P(pstr, v); SERIAL_EOL(); } + +// Catch-all for __FlashStringHelper * +template +inline void serial_echopair(FSTR_P const fstr, T v) { serial_echopair_P(FTOP(fstr), v); } -inline void serial_echopair_PGM(PGM_P const s_P, bool v) { serial_echopair_PGM(s_P, (int)v); } -inline void serial_echopair_PGM(PGM_P const s_P, void *v) { serial_echopair_PGM(s_P, (uintptr_t)v); } +// Add a newline to the serial output +template +inline void serial_echolnpair(FSTR_P const fstr, T v) { serial_echolnpair_P(FTOP(fstr), v); } void serial_echo_start(); void serial_error_start(); -void serial_ternary(const bool onoff, PGM_P const pre, PGM_P const on, PGM_P const off, PGM_P const post=nullptr); +void serial_ternary(const bool onoff, FSTR_P const pre, FSTR_P const on, FSTR_P const off, FSTR_P const post=nullptr); void serialprint_onoff(const bool onoff); void serialprintln_onoff(const bool onoff); void serialprint_truefalse(const bool tf); void serial_spaces(uint8_t count); void print_bin(const uint16_t val); -void print_pos(LINEAR_AXIS_ARGS(const_float_t), PGM_P const prefix=nullptr, PGM_P const suffix=nullptr); +void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr); -inline void print_pos(const xyz_pos_t &xyz, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr) { +inline void print_pos(const xyz_pos_t &xyz, FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr) { print_pos(LINEAR_AXIS_ELEM(xyz), prefix, suffix); } -#define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, PSTR(" " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n")); }while(0) -#define SERIAL_XYZ(PREFIX,V...) do { print_pos(V, PSTR(PREFIX), nullptr); }while(0) +#define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, F(" " STRINGIFY(VAR) "="), F(" : " SUFFIX "\n")); }while(0) +#define SERIAL_XYZ(PREFIX,V...) do { print_pos(V, F(PREFIX)); }while(0) diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index e11a6cd03e..9a5b64c22e 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -26,13 +26,6 @@ #include "../inc/MarlinConfigPre.h" -class __FlashStringHelper; -typedef const __FlashStringHelper* FSTR_P; -#ifndef FPSTR - #define FPSTR(S) (reinterpret_cast(S)) -#endif -#define FTOP(S) (reinterpret_cast(S)) - // // Conditional type assignment magic. For example... // @@ -89,7 +82,7 @@ enum AxisEnum : uint8_t { #undef _EN_ITEM // Core also keeps toolhead directions - #if EITHER(IS_CORE, MARKFORGED_XY) + #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) , X_HEAD, Y_HEAD, Z_HEAD #endif diff --git a/Marlin/src/core/utility.cpp b/Marlin/src/core/utility.cpp index 8aeec89f02..cc3b1ace2f 100644 --- a/Marlin/src/core/utility.cpp +++ b/Marlin/src/core/utility.cpp @@ -60,7 +60,8 @@ void safe_delay(millis_t ms) { TERN_(DELTA, "Delta") TERN_(IS_SCARA, "SCARA") TERN_(IS_CORE, "Core") - TERN_(MARKFORGED_XY, "MarkForged") + TERN_(MARKFORGED_XY, "MarkForgedXY") + TERN_(MARKFORGED_YX, "MarkForgedYX") TERN_(IS_CARTESIAN, "Cartesian") ); @@ -92,9 +93,9 @@ void safe_delay(millis_t ms) { SERIAL_ECHOPGM(" (Aligned With"); if (probe.offset_xy.y > 0) - SERIAL_ECHOPGM_P(ENABLED(IS_SCARA) ? PSTR("-Distal") : PSTR("-Back")); + SERIAL_ECHOF(F(TERN(IS_SCARA, "-Distal", "-Back"))); else if (probe.offset_xy.y < 0) - SERIAL_ECHOPGM_P(ENABLED(IS_SCARA) ? PSTR("-Proximal") : PSTR("-Front")); + SERIAL_ECHOF(F(TERN(IS_SCARA, "-Proximal", "-Front"))); else if (probe.offset_xy.x != 0) SERIAL_ECHOPGM("-Center"); @@ -102,7 +103,7 @@ void safe_delay(millis_t ms) { #endif - SERIAL_ECHOPGM_P(probe.offset.z < 0 ? PSTR("Below") : probe.offset.z > 0 ? PSTR("Above") : PSTR("Same Z as")); + SERIAL_ECHOF(probe.offset.z < 0 ? F("Below") : probe.offset.z > 0 ? F("Above") : F("Same Z as")); SERIAL_ECHOLNPGM(" Nozzle)"); #endif diff --git a/Marlin/src/feature/adc/adc_mcp3426.cpp b/Marlin/src/feature/adc/adc_mcp3426.cpp new file mode 100644 index 0000000000..aaddf46821 --- /dev/null +++ b/Marlin/src/feature/adc/adc_mcp3426.cpp @@ -0,0 +1,104 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * adc_mcp3426.cpp - library for MicroChip MCP3426 I2C A/D converter + * + * For implementation details, please take a look at the datasheet: + * https://www.microchip.com/en-us/product/MCP3426 + */ + +#include "../../inc/MarlinConfig.h" + +#if ENABLED(HAS_MCP3426_ADC) + +#include "adc_mcp3426.h" + +// Read the ADC value from MCP342X on a specific channel +int16_t MCP3426::ReadValue(uint8_t channel, uint8_t gain) { + Error = false; + + #if PINS_EXIST(I2C_SCL, I2C_SDA) && DISABLED(SOFT_I2C_EEPROM) + Wire.setSDA(pin_t(I2C_SDA_PIN)); + Wire.setSCL(pin_t(I2C_SCL_PIN)); + #endif + + Wire.begin(); // No address joins the BUS as the master + + Wire.beginTransmission(I2C_ADDRESS(MCP342X_ADC_I2C_ADDRESS)); + + // Continuous Conversion Mode, 16 bit, Channel 1, Gain x4 + // 26 = 0b00011000 + // RXXCSSGG + // R = Ready Bit + // XX = Channel (00=1, 01=2, 10=3 (MCP3428), 11=4 (MCP3428)) + // C = Conversion Mode Bit (1= Continuous Conversion Mode (Default)) + // SS = Sample rate, 10=15 samples per second @ 16 bits + // GG = Gain 00 =x1 + uint8_t controlRegister = 0b00011000; + + if (channel == 2) controlRegister |= 0b00100000; // Select channel 2 + + if (gain == 2) + controlRegister |= 0b00000001; + else if (gain == 4) + controlRegister |= 0b00000010; + else if (gain == 8) + controlRegister |= 0b00000011; + + Wire.write(controlRegister); + if (Wire.endTransmission() != 0) { + Error = true; + return 0; + } + + const uint8_t len = 3; + uint8_t buffer[len] = {}; + + do { + Wire.requestFrom(I2C_ADDRESS(MCP342X_ADC_I2C_ADDRESS), len); + if (Wire.available() != len) { + Error = true; + return 0; + } + + for (uint8_t i = 0; i < len; ++i) + buffer[i] = Wire.read(); + + // Is conversion ready, if not loop around again + } while ((buffer[2] & 0x80) != 0); + + union TwoBytesToInt16 { + uint8_t bytes[2]; + int16_t integervalue; + }; + TwoBytesToInt16 ConversionUnion; + + ConversionUnion.bytes[1] = buffer[0]; + ConversionUnion.bytes[0] = buffer[1]; + + return ConversionUnion.integervalue; +} + +MCP3426 mcp3426; + +#endif // HAS_MCP3426_ADC diff --git a/Marlin/src/feature/adc/adc_mcp3426.h b/Marlin/src/feature/adc/adc_mcp3426.h new file mode 100644 index 0000000000..35458716b9 --- /dev/null +++ b/Marlin/src/feature/adc/adc_mcp3426.h @@ -0,0 +1,41 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +/** + * Arduino library for MicroChip MCP3426 I2C A/D converter. + * https://www.microchip.com/en-us/product/MCP3426 + */ + +#include +#include + +// Address of MCP342X chip +#define MCP342X_ADC_I2C_ADDRESS 104 + +class MCP3426 { + public: + int16_t ReadValue(uint8_t channel, uint8_t gain); + bool Error; +}; + +extern MCP3426 mcp3426; diff --git a/Marlin/src/feature/backlash.cpp b/Marlin/src/feature/backlash.cpp index b646e19f15..24c0f2ca0c 100644 --- a/Marlin/src/feature/backlash.cpp +++ b/Marlin/src/feature/backlash.cpp @@ -64,7 +64,7 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const static axis_bits_t last_direction_bits; axis_bits_t changed_dir = last_direction_bits ^ dm; // Ignore direction change unless steps are taken in that direction - #if DISABLED(CORE_BACKLASH) || ENABLED(MARKFORGED_XY) + #if DISABLED(CORE_BACKLASH) || EITHER(MARKFORGED_XY, MARKFORGED_YX) if (!da) CBI(changed_dir, X_AXIS); if (!db) CBI(changed_dir, Y_AXIS); if (!dc) CBI(changed_dir, Z_AXIS); diff --git a/Marlin/src/feature/bedlevel/abl/x_twist.cpp b/Marlin/src/feature/bedlevel/abl/x_twist.cpp new file mode 100644 index 0000000000..c4a62c3595 --- /dev/null +++ b/Marlin/src/feature/bedlevel/abl/x_twist.cpp @@ -0,0 +1,59 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include "../../../inc/MarlinConfig.h" + +#if ENABLED(X_AXIS_TWIST_COMPENSATION) + +#include "../bedlevel.h" + +XATC xatc; + +float XATC::spacing, XATC::start; +xatc_points_t XATC::z_values; + +void XATC::print_points() { + SERIAL_ECHOLNPGM(" X-Twist Correction:"); + LOOP_L_N(x, XATC_MAX_POINTS) { + SERIAL_CHAR(' '); + if (!isnan(z_values[x])) { + if (z_values[x] >= 0) SERIAL_CHAR('+'); + SERIAL_ECHO_F(z_values[x], 3); + } + else { + LOOP_L_N(i, 6) + SERIAL_CHAR(i ? '=' : ' '); + } + } + SERIAL_EOL(); +} + +float lerp(const_float_t t, const_float_t a, const_float_t b) { return a + t * (b - a); } + +float XATC::compensation(const xy_pos_t &raw) { + float t = (raw.x - start) / spacing; + int i = FLOOR(t); + LIMIT(i, 0, XATC_MAX_POINTS - 2); + t -= i; + return lerp(t, z_values[i], z_values[i + 1]); +} + +#endif // X_AXIS_TWIST_COMPENSATION diff --git a/Marlin/src/feature/bedlevel/abl/x_twist.h b/Marlin/src/feature/bedlevel/abl/x_twist.h new file mode 100644 index 0000000000..bbad9e73ef --- /dev/null +++ b/Marlin/src/feature/bedlevel/abl/x_twist.h @@ -0,0 +1,37 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include "../../../inc/MarlinConfigPre.h" + +typedef float xatc_points_t[XATC_MAX_POINTS]; + +class XATC { +public: + static float spacing, start; + static xatc_points_t z_values; + + static float compensation(const xy_pos_t &raw); + static void print_points(); +}; + +extern XATC xatc; diff --git a/Marlin/src/feature/bedlevel/bedlevel.h b/Marlin/src/feature/bedlevel/bedlevel.h index 63f032eee8..c623c99b5c 100644 --- a/Marlin/src/feature/bedlevel/bedlevel.h +++ b/Marlin/src/feature/bedlevel/bedlevel.h @@ -63,6 +63,9 @@ class TemporaryBedLevelingState { #if ENABLED(AUTO_BED_LEVELING_BILINEAR) #include "abl/abl.h" + #if ENABLED(X_AXIS_TWIST_COMPENSATION) + #include "abl/x_twist.h" + #endif #elif ENABLED(AUTO_BED_LEVELING_UBL) #include "ubl/ubl.h" #elif ENABLED(MESH_BED_LEVELING) diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp index 00cb5ed738..964f1123fe 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl.cpp @@ -180,10 +180,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) { SERIAL_EOL(); serial_echo_column_labels(eachsp - 2); } - else { - SERIAL_ECHOPGM(" for "); - SERIAL_ECHOPGM_P(csv ? PSTR("CSV:\n") : PSTR("LCD:\n")); - } + else + SERIAL_ECHOPGM(" for ", csv ? F("CSV:\n") : F("LCD:\n")); // Add XY probe offset from extruder because probe.probe_at_point() subtracts them when // moving to the XY position to be measured. This ensures better agreement between @@ -213,7 +211,7 @@ void unified_bed_leveling::display_map(const uint8_t map_type) { // TODO: Display on Graphical LCD } else if (isnan(f)) - SERIAL_ECHOPGM_P(human ? PSTR(" . ") : PSTR("NAN")); + SERIAL_ECHOF(human ? F(" . ") : F("NAN")); else if (human || csv) { if (human && f >= 0.0) SERIAL_CHAR(f > 0 ? '+' : ' '); // Display sign also for positive numbers (' ' for 0) SERIAL_ECHO_F(f, 3); // Positive: 5 digits, Negative: 6 digits @@ -281,10 +279,10 @@ bool unified_bed_leveling::sanity_check() { } #endif - process_subcommands_now_P(G28_STR); // Home - process_subcommands_now_P(PSTR(ALIGN_GCODE "\n" // Align multi z axis if available - PROBE_GCODE "\n" // Build mesh with available hardware - "G29P3\nG29P3")); // Ensure mesh is complete by running smart fill twice + process_subcommands_now(FPSTR(G28_STR)); // Home + process_subcommands_now(F(ALIGN_GCODE "\n" // Align multi z axis if available + PROBE_GCODE "\n" // Build mesh with available hardware + "G29P3\nG29P3")); // Ensure mesh is complete by running smart fill twice if (parser.seenval('S')) { char umw_gcode[32]; @@ -292,9 +290,9 @@ bool unified_bed_leveling::sanity_check() { queue.inject(umw_gcode); } - process_subcommands_now_P(PSTR("G29A\nG29F10\n" // Set UBL Active & Fade 10 - "M140S0\nM104S0\n" // Turn off heaters - "M500")); // Store settings + process_subcommands_now(F("G29A\nG29F10\n" // Set UBL Active & Fade 10 + "M140S0\nM104S0\n" // Turn off heaters + "M500")); // Store settings } #endif // UBL_MESH_WIZARD diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index 750c63f7c6..df83923fef 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -346,13 +346,14 @@ void unified_bed_leveling::G29() { if (parser.seen('Q')) { const int16_t test_pattern = parser.has_value() ? parser.value_int() : -99; - if (!WITHIN(test_pattern, -1, 2)) { - SERIAL_ECHOLNPGM("Invalid test_pattern value. (-1 to 2)\n"); + if (!WITHIN(test_pattern, TERN0(UBL_DEVEL_DEBUGGING, -1), 2)) { + SERIAL_ECHOLNPGM("?Invalid (Q) test pattern. (" TERN(UBL_DEVEL_DEBUGGING, "-1", "0") " to 2)\n"); return; } - SERIAL_ECHOLNPGM("Loading test_pattern values.\n"); + SERIAL_ECHOLNPGM("Applying test pattern.\n"); switch (test_pattern) { + default: case -1: TERN_(UBL_DEVEL_DEBUGGING, g29_eeprom_dump()); break; case 0: @@ -656,7 +657,7 @@ void unified_bed_leveling::G29() { if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Z Probe End Script: ", Z_PROBE_END_SCRIPT); if (probe_deployed) { planner.synchronize(); - gcode.process_subcommands_now_P(PSTR(Z_PROBE_END_SCRIPT)); + gcode.process_subcommands_now(F(Z_PROBE_END_SCRIPT)); } #else UNUSED(probe_deployed); @@ -736,7 +737,7 @@ void unified_bed_leveling::shift_mesh_height() { const uint8_t point_num = (GRID_MAX_POINTS - count) + 1; SERIAL_ECHOLNPGM("Probing mesh point ", point_num, "/", GRID_MAX_POINTS, "."); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), point_num, int(GRID_MAX_POINTS))); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), point_num, int(GRID_MAX_POINTS))); #if HAS_LCD_MENU if (ui.button_pressed()) { @@ -789,12 +790,12 @@ void unified_bed_leveling::shift_mesh_height() { #endif // HAS_BED_PROBE -void set_message_with_feedback(PGM_P const msg_P) { +void set_message_with_feedback(FSTR_P const fstr) { #if HAS_LCD_MENU - ui.set_status_P(msg_P); + ui.set_status(fstr); ui.quick_feedback(); #else - UNUSED(msg_P); + UNUSED(fstr); #endif } @@ -850,7 +851,7 @@ void set_message_with_feedback(PGM_P const msg_P) { planner.synchronize(); SERIAL_ECHOPGM("Place shim under nozzle"); - LCD_MESSAGEPGM(MSG_UBL_BC_INSERT); + LCD_MESSAGE(MSG_UBL_BC_INSERT); ui.return_to_status(); echo_and_take_a_measurement(); @@ -859,7 +860,7 @@ void set_message_with_feedback(PGM_P const msg_P) { planner.synchronize(); SERIAL_ECHOPGM("Remove shim"); - LCD_MESSAGEPGM(MSG_UBL_BC_REMOVE); + LCD_MESSAGE(MSG_UBL_BC_REMOVE); echo_and_take_a_measurement(); const float z2 = measure_point_with_encoder(); @@ -905,7 +906,7 @@ void set_message_with_feedback(PGM_P const msg_P) { if (!position_is_reachable(ppos)) break; // SHOULD NOT OCCUR (find_closest_mesh_point only returns reachable points) - LCD_MESSAGEPGM(MSG_UBL_MOVING_TO_NEXT); + LCD_MESSAGE(MSG_UBL_MOVING_TO_NEXT); do_blocking_move_to(ppos); do_z_clearance(z_clearance); @@ -917,11 +918,11 @@ void set_message_with_feedback(PGM_P const msg_P) { if (parser.seen_test('B')) { SERIAL_ECHOPGM("Place Shim & Measure"); - LCD_MESSAGEPGM(MSG_UBL_BC_INSERT); + LCD_MESSAGE(MSG_UBL_BC_INSERT); } else { SERIAL_ECHOPGM("Measure"); - LCD_MESSAGEPGM(MSG_UBL_BC_INSERT2); + LCD_MESSAGE(MSG_UBL_BC_INSERT2); } const float z_step = 0.01f; // 0.01mm per encoder tick, occasionally step @@ -974,7 +975,7 @@ void set_message_with_feedback(PGM_P const msg_P) { save_ubl_active_state_and_disable(); - LCD_MESSAGEPGM(MSG_UBL_FINE_TUNE_MESH); + LCD_MESSAGE(MSG_UBL_FINE_TUNE_MESH); ui.capture(); // Take over control of the LCD encoder do_blocking_move_to_xy_z(pos, Z_CLEARANCE_BETWEEN_PROBES); // Move to the given XY with probe clearance @@ -1039,7 +1040,7 @@ void set_message_with_feedback(PGM_P const msg_P) { if (_click_and_hold([]{ ui.return_to_status(); do_z_clearance(Z_CLEARANCE_BETWEEN_PROBES); - set_message_with_feedback(GET_TEXT(MSG_EDITING_STOPPED)); + set_message_with_feedback(GET_TEXT_F(MSG_EDITING_STOPPED)); })) break; // TODO: Disable leveling here so the Z value becomes the 'native' Z value. @@ -1060,7 +1061,7 @@ void set_message_with_feedback(PGM_P const msg_P) { do_blocking_move_to_xy_z(pos, Z_CLEARANCE_BETWEEN_PROBES); - LCD_MESSAGEPGM(MSG_UBL_DONE_EDITING_MESH); + LCD_MESSAGE(MSG_UBL_DONE_EDITING_MESH); SERIAL_ECHOLNPGM("Done Editing Mesh"); if (lcd_map_control) @@ -1077,7 +1078,7 @@ void set_message_with_feedback(PGM_P const msg_P) { bool unified_bed_leveling::G29_parse_parameters() { bool err_flag = false; - set_message_with_feedback(GET_TEXT(MSG_UBL_DOING_G29)); + set_message_with_feedback(GET_TEXT_F(MSG_UBL_DOING_G29)); param.C_constant = 0; param.R_repetition = 0; @@ -1200,7 +1201,7 @@ void unified_bed_leveling::save_ubl_active_state_and_disable() { ubl_state_recursion_chk++; if (ubl_state_recursion_chk != 1) { SERIAL_ECHOLNPGM("save_ubl_active_state_and_disabled() called multiple times in a row."); - set_message_with_feedback(GET_TEXT(MSG_UBL_SAVE_ERROR)); + set_message_with_feedback(GET_TEXT_F(MSG_UBL_SAVE_ERROR)); return; } #endif @@ -1213,7 +1214,7 @@ void unified_bed_leveling::restore_ubl_active_state_and_leave() { #if ENABLED(UBL_DEVEL_DEBUGGING) if (--ubl_state_recursion_chk) { SERIAL_ECHOLNPGM("restore_ubl_active_state_and_leave() called too many times."); - set_message_with_feedback(GET_TEXT(MSG_UBL_RESTORE_ERROR)); + set_message_with_feedback(GET_TEXT_F(MSG_UBL_RESTORE_ERROR)); return; } #endif @@ -1438,7 +1439,7 @@ void unified_bed_leveling::smart_fill_mesh() { if (do_3_pt_leveling) { SERIAL_ECHOLNPGM("Tilting mesh (1/3)"); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " 1/3"), GET_TEXT(MSG_LCD_TILTING_MESH))); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " 1/3"), GET_TEXT(MSG_LCD_TILTING_MESH))); measured_z = probe.probe_at_point(points[0], PROBE_PT_RAISE, param.V_verbosity); if (isnan(measured_z)) @@ -1457,7 +1458,7 @@ void unified_bed_leveling::smart_fill_mesh() { if (!abort_flag) { SERIAL_ECHOLNPGM("Tilting mesh (2/3)"); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " 2/3"), GET_TEXT(MSG_LCD_TILTING_MESH))); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " 2/3"), GET_TEXT(MSG_LCD_TILTING_MESH))); measured_z = probe.probe_at_point(points[1], PROBE_PT_RAISE, param.V_verbosity); #ifdef VALIDATE_MESH_TILT @@ -1477,7 +1478,7 @@ void unified_bed_leveling::smart_fill_mesh() { if (!abort_flag) { SERIAL_ECHOLNPGM("Tilting mesh (3/3)"); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " 3/3"), GET_TEXT(MSG_LCD_TILTING_MESH))); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " 3/3"), GET_TEXT(MSG_LCD_TILTING_MESH))); measured_z = probe.probe_at_point(points[2], PROBE_PT_LAST_STOW, param.V_verbosity); #ifdef VALIDATE_MESH_TILT @@ -1518,7 +1519,7 @@ void unified_bed_leveling::smart_fill_mesh() { if (!abort_flag) { SERIAL_ECHOLNPGM("Tilting mesh point ", point_num, "/", total_points, "\n"); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/%i"), GET_TEXT(MSG_LCD_TILTING_MESH), point_num, total_points)); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_LCD_TILTING_MESH), point_num, total_points)); measured_z = probe.probe_at_point(rpos, parser.seen_test('E') ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity); // TODO: Needs error handling @@ -1609,7 +1610,7 @@ void unified_bed_leveling::smart_fill_mesh() { } if (DEBUGGING(LEVELING)) { - rotation.debug(PSTR("rotation matrix:\n")); + rotation.debug(F("rotation matrix:\n")); DEBUG_ECHOPAIR_F("LSF Results A=", lsf_results.A, 7); DEBUG_ECHOPAIR_F(" B=", lsf_results.B, 7); DEBUG_ECHOLNPAIR_F(" D=", lsf_results.D, 7); @@ -1636,14 +1637,14 @@ void unified_bed_leveling::smart_fill_mesh() { auto normed = [&](const xy_pos_t &pos, const_float_t zadd) { return normal.x * pos.x + normal.y * pos.y + zadd; }; - auto debug_pt = [](PGM_P const pre, const xy_pos_t &pos, const_float_t zadd) { - d_from(); SERIAL_ECHOPGM_P(pre); + auto debug_pt = [](FSTR_P const pre, const xy_pos_t &pos, const_float_t zadd) { + d_from(); SERIAL_ECHOF(pre); DEBUG_ECHO_F(normed(pos, zadd), 6); DEBUG_ECHOLNPAIR_F(" Z error = ", zadd - get_z_correction(pos), 6); }; - debug_pt(PSTR("1st point: "), probe_pt[0], normal.z * z1); - debug_pt(PSTR("2nd point: "), probe_pt[1], normal.z * z2); - debug_pt(PSTR("3rd point: "), probe_pt[2], normal.z * z3); + debug_pt(F("1st point: "), probe_pt[0], normal.z * z1); + debug_pt(F("2nd point: "), probe_pt[1], normal.z * z2); + debug_pt(F("3rd point: "), probe_pt[2], normal.z * z3); d_from(); DEBUG_ECHOPGM("safe home with Z="); DEBUG_ECHOLNPAIR_F("0 : ", normed(safe_homing_xy, 0), 6); d_from(); DEBUG_ECHOPGM("safe home with Z="); diff --git a/Marlin/src/feature/bltouch.cpp b/Marlin/src/feature/bltouch.cpp index 49a10f62b1..b1cc30bee0 100644 --- a/Marlin/src/feature/bltouch.cpp +++ b/Marlin/src/feature/bltouch.cpp @@ -28,7 +28,12 @@ BLTouch bltouch; -bool BLTouch::last_written_mode; // Initialized by settings.load, 0 = Open Drain; 1 = 5V Drain +bool BLTouch::od_5v_mode; // Initialized by settings.load, 0 = Open Drain; 1 = 5V Drain +#ifdef BLTOUCH_HS_MODE + bool BLTouch::high_speed_mode; // Initialized by settings.load, 0 = Low Speed; 1 = High Speed +#else + constexpr bool BLTouch::high_speed_mode; +#endif #include "../module/servo.h" #include "../module/probe.h" @@ -63,18 +68,17 @@ void BLTouch::init(const bool set_voltage/*=false*/) { #else - if (DEBUGGING(LEVELING)) { - DEBUG_ECHOLNPGM("last_written_mode - ", last_written_mode); - DEBUG_ECHOLNPGM("config mode - " - #if ENABLED(BLTOUCH_SET_5V_MODE) - "BLTOUCH_SET_5V_MODE" - #else - "OD" - #endif - ); - } + #ifdef DEBUG_OUT + if (DEBUGGING(LEVELING)) { + PGMSTR(mode0, "OD"); + PGMSTR(mode1, "5V"); + DEBUG_ECHOPGM("BLTouch Mode: "); + DEBUG_ECHOPGM_P(bltouch.od_5v_mode ? mode1 : mode0); + DEBUG_ECHOLNPGM(" (Default " TERN(BLTOUCH_SET_5V_MODE, "5V", "OD") ")"); + } + #endif - const bool should_set = last_written_mode != ENABLED(BLTOUCH_SET_5V_MODE); + const bool should_set = od_5v_mode != ENABLED(BLTOUCH_SET_5V_MODE); #endif @@ -193,7 +197,7 @@ void BLTouch::mode_conv_proc(const bool M5V) { _mode_store(); if (M5V) _set_5V_mode(); else _set_OD_mode(); _stow(); - last_written_mode = M5V; + od_5v_mode = M5V; } #endif // BLTOUCH diff --git a/Marlin/src/feature/bltouch.h b/Marlin/src/feature/bltouch.h index 9ecccb4256..ae3ab66300 100644 --- a/Marlin/src/feature/bltouch.h +++ b/Marlin/src/feature/bltouch.h @@ -23,10 +23,6 @@ #include "../inc/MarlinConfigPre.h" -#if DISABLED(BLTOUCH_HS_MODE) - #define BLTOUCH_SLOW_MODE 1 -#endif - // BLTouch commands are sent as servo angles typedef unsigned char BLTCommand; @@ -70,8 +66,17 @@ typedef unsigned char BLTCommand; class BLTouch { public: + static void init(const bool set_voltage=false); - static bool last_written_mode; // Initialized by settings.load, 0 = Open Drain; 1 = 5V Drain + static bool od_5v_mode; // Initialized by settings.load, 0 = Open Drain; 1 = 5V Drain + + #ifdef BLTOUCH_HS_MODE + static bool high_speed_mode; // Initialized by settings.load, 0 = Low Speed; 1 = High Speed + #else + static constexpr bool high_speed_mode = false; + #endif + + static inline float z_extra_clearance() { return high_speed_mode ? 7 : 0; } // DEPLOY and STOW are wrapped for error handling - these are used by homing and by probing static bool deploy() { return deploy_proc(); } diff --git a/Marlin/src/feature/cancel_object.cpp b/Marlin/src/feature/cancel_object.cpp index 9d50bfc0d4..bffd2bb720 100644 --- a/Marlin/src/feature/cancel_object.cpp +++ b/Marlin/src/feature/cancel_object.cpp @@ -46,7 +46,7 @@ void CancelObject::set_active_object(const int8_t obj) { #if BOTH(HAS_STATUS_MESSAGE, CANCEL_OBJECTS_REPORTING) if (active_object >= 0) - ui.status_printf_P(0, PSTR(S_FMT " %i"), GET_TEXT(MSG_PRINTING_OBJECT), int(active_object)); + ui.status_printf(0, F(S_FMT " %i"), GET_TEXT(MSG_PRINTING_OBJECT), int(active_object)); else ui.reset_status(); #endif diff --git a/Marlin/src/feature/caselight.cpp b/Marlin/src/feature/caselight.cpp index 1baef6d468..59832fd6ed 100644 --- a/Marlin/src/feature/caselight.cpp +++ b/Marlin/src/feature/caselight.cpp @@ -39,7 +39,6 @@ CaseLight caselight; bool CaseLight::on = CASE_LIGHT_DEFAULT_ON; #if CASE_LIGHT_IS_COLOR_LED - #include "leds/leds.h" constexpr uint8_t init_case_light[] = CASE_LIGHT_DEFAULT_COLOR; LEDColor CaseLight::color = { init_case_light[0], init_case_light[1], init_case_light[2] OPTARG(HAS_WHITE_LED, init_case_light[3]) }; #endif @@ -65,12 +64,12 @@ void CaseLight::update(const bool sflag) { #endif #if CASE_LIGHT_IS_COLOR_LED - leds.set_color(LEDColor(color.r, color.g, color.b OPTARG(HAS_WHITE_LED, color.w), n10ct)); + leds.set_color(LEDColor(color.r, color.g, color.b OPTARG(HAS_WHITE_LED, color.w) OPTARG(NEOPIXEL_LED, n10ct))); #else // !CASE_LIGHT_IS_COLOR_LED #if CASELIGHT_USES_BRIGHTNESS if (pin_is_pwm()) - analogWrite(pin_t(CASE_LIGHT_PIN), ( + set_pwm_duty(pin_t(CASE_LIGHT_PIN), ( #if CASE_LIGHT_MAX_PWM == 255 n10ct #else diff --git a/Marlin/src/feature/controllerfan.cpp b/Marlin/src/feature/controllerfan.cpp index 5efddbb111..59ba665e11 100644 --- a/Marlin/src/feature/controllerfan.cpp +++ b/Marlin/src/feature/controllerfan.cpp @@ -58,7 +58,7 @@ void ControllerFan::update() { // - At least one stepper driver is enabled // - The heated bed is enabled // - TEMP_SENSOR_BOARD is reporting >= CONTROLLER_FAN_MIN_BOARD_TEMP - const ena_mask_t axis_mask = TERN(CONTROLLER_FAN_USE_Z_ONLY, _BV(Z_AXIS), ~TERN0(CONTROLLER_FAN_IGNORE_Z, _BV(Z_AXIS))); + const ena_mask_t axis_mask = TERN(CONTROLLER_FAN_USE_Z_ONLY, _BV(Z_AXIS), (ena_mask_t)~TERN0(CONTROLLER_FAN_IGNORE_Z, _BV(Z_AXIS))); if ( (stepper.axis_enabled.bits & axis_mask) || TERN0(HAS_HEATED_BED, thermalManager.temp_bed.soft_pwm_amount > 0) || TERN0(HAS_CONTROLLER_FAN_MIN_BOARD_TEMP, thermalManager.wholeDegBoard() >= CONTROLLER_FAN_MIN_BOARD_TEMP) @@ -72,9 +72,14 @@ void ControllerFan::update() { ? settings.active_speed : settings.idle_speed ); - // Allow digital or PWM fan output (see M42 handling) - WRITE(CONTROLLER_FAN_PIN, speed); - analogWrite(pin_t(CONTROLLER_FAN_PIN), speed); + #if ENABLED(FAN_SOFT_PWM) + thermalManager.soft_pwm_controller_speed = speed; + #else + if (PWM_PIN(CONTROLLER_FAN_PIN)) + set_pwm_duty(pin_t(CONTROLLER_FAN_PIN), speed); + else + WRITE(CONTROLLER_FAN_PIN, speed > 0); + #endif } } diff --git a/Marlin/src/feature/direct_stepping.cpp b/Marlin/src/feature/direct_stepping.cpp index ce979145a1..b8ef04fcd9 100644 --- a/Marlin/src/feature/direct_stepping.cpp +++ b/Marlin/src/feature/direct_stepping.cpp @@ -174,7 +174,7 @@ namespace DirectStepping { template void SerialPageManager::write_responses() { if (fatal_error) { - kill(GET_TEXT(MSG_BAD_PAGE)); + kill(GET_TEXT_F(MSG_BAD_PAGE)); return; } diff --git a/Marlin/src/feature/e_parser.h b/Marlin/src/feature/e_parser.h index 3723caa35e..1dee0cf755 100644 --- a/Marlin/src/feature/e_parser.h +++ b/Marlin/src/feature/e_parser.h @@ -199,7 +199,7 @@ public: case EP_M112: killed_by_M112 = true; break; case EP_M410: quickstop_by_M410 = true; break; #if ENABLED(HOST_PROMPT_SUPPORT) - case EP_M876SN: host_response_handler(M876_reason); break; + case EP_M876SN: hostui.handle_response(M876_reason); break; #endif #if ENABLED(REALTIME_REPORTING_COMMANDS) case EP_GRBL_STATUS: report_current_position_moving(); break; diff --git a/Marlin/src/feature/easythreed_ui.cpp b/Marlin/src/feature/easythreed_ui.cpp new file mode 100644 index 0000000000..9f8af03947 --- /dev/null +++ b/Marlin/src/feature/easythreed_ui.cpp @@ -0,0 +1,236 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "../inc/MarlinConfigPre.h" + +#if ENABLED(EASYTHREED_UI) + +#include "easythreed_ui.h" +#include "pause.h" +#include "../module/temperature.h" +#include "../module/printcounter.h" +#include "../sd/cardreader.h" +#include "../gcode/queue.h" +#include "../module/motion.h" +#include "../module/planner.h" +#include "../MarlinCore.h" + +EasythreedUI easythreed_ui; + +#define BTN_DEBOUNCE_MS 20 + +void EasythreedUI::init() { + SET_INPUT_PULLUP(BTN_HOME); SET_OUTPUT(BTN_HOME_GND); + SET_INPUT_PULLUP(BTN_FEED); SET_OUTPUT(BTN_FEED_GND); + SET_INPUT_PULLUP(BTN_RETRACT); SET_OUTPUT(BTN_RETRACT_GND); + SET_INPUT_PULLUP(BTN_PRINT); + SET_OUTPUT(EASYTHREED_LED_PIN); +} + +void EasythreedUI::run() { + blinkLED(); + loadButton(); + printButton(); +} + +enum LEDInterval : uint16_t { + LED_OFF = 0, + LED_ON = 4000, + LED_BLINK_0 = 2500, + LED_BLINK_1 = 1500, + LED_BLINK_2 = 1000, + LED_BLINK_3 = 800, + LED_BLINK_4 = 500, + LED_BLINK_5 = 300, + LED_BLINK_6 = 150, + LED_BLINK_7 = 50 +}; + +uint16_t blink_interval_ms = LED_ON; // Status LED on Start button + +void EasythreedUI::blinkLED() { + static millis_t prev_blink_interval_ms = 0, blink_start_ms = 0; + + if (blink_interval_ms == LED_OFF) { WRITE(EASYTHREED_LED_PIN, HIGH); return; } // OFF + if (blink_interval_ms >= LED_ON) { WRITE(EASYTHREED_LED_PIN, LOW); return; } // ON + + const millis_t ms = millis(); + if (prev_blink_interval_ms != blink_interval_ms) { + prev_blink_interval_ms = blink_interval_ms; + blink_start_ms = ms; + } + if (PENDING(ms, blink_start_ms + blink_interval_ms)) + WRITE(EASYTHREED_LED_PIN, LOW); + else if (PENDING(ms, blink_start_ms + 2 * blink_interval_ms)) + WRITE(EASYTHREED_LED_PIN, HIGH); + else + blink_start_ms = ms; +} + +// +// Filament Load/Unload Button +// Load/Unload buttons are a 3 position switch with a common center ground. +// +void EasythreedUI::loadButton() { + if (printingIsActive()) return; + + enum FilamentStatus : uint8_t { FS_IDLE, FS_PRESS, FS_CHECK, FS_PROCEED }; + static uint8_t filament_status = FS_IDLE; + static millis_t filament_time = 0; + + switch (filament_status) { + + case FS_IDLE: + if (!READ(BTN_RETRACT) || !READ(BTN_FEED)) { // If feed/retract switch is toggled... + filament_status++; // ...proceed to next test. + filament_time = millis(); + } + break; + + case FS_PRESS: + if (ELAPSED(millis(), filament_time + BTN_DEBOUNCE_MS)) { // After a short debounce delay... + if (!READ(BTN_RETRACT) || !READ(BTN_FEED)) { // ...if switch still toggled... + thermalManager.setTargetHotend(EXTRUDE_MINTEMP + 10, 0); // Start heating up + blink_interval_ms = LED_BLINK_7; // Set the LED to blink fast + filament_status++; + } + else + filament_status = FS_IDLE; // Switch not toggled long enough + } + break; + + case FS_CHECK: + if (READ(BTN_RETRACT) && READ(BTN_FEED)) { // Switch in center position (stop) + blink_interval_ms = LED_ON; // LED on steady + filament_status = FS_IDLE; + thermalManager.disable_all_heaters(); + } + else if (thermalManager.hotEnoughToExtrude(0)) { // Is the hotend hot enough to move material? + filament_status++; // Proceed to feed / retract. + blink_interval_ms = LED_BLINK_5; // Blink ~3 times per second + } + break; + + case FS_PROCEED: { + // Feed or Retract just once. Hard abort all moves and return to idle on swicth release. + static bool flag = false; + if (READ(BTN_RETRACT) && READ(BTN_FEED)) { // Switch in center position (stop) + flag = false; // Restore flag to false + filament_status = FS_IDLE; // Go back to idle state + quickstop_stepper(); // Hard-stop all the steppers ... now! + thermalManager.disable_all_heaters(); // And disable all the heaters + blink_interval_ms = LED_ON; + } + else if (!flag) { + flag = true; + queue.inject(!READ(BTN_RETRACT) ? F("G91\nG0 E10 F180\nG0 E-120 F180\nM104 S0") : F("G91\nG0 E100 F120\nM104 S0")); + } + } break; + } + +} + +#if HAS_STEPPER_RESET + void disableStepperDrivers(); +#endif + +// +// Print Start/Pause/Resume Button +// +void EasythreedUI::printButton() { + enum KeyStatus : uint8_t { KS_IDLE, KS_PRESS, KS_PROCEED }; + static uint8_t key_status = KS_IDLE; + static millis_t key_time = 0; + + enum PrintFlag : uint8_t { PF_START, PF_PAUSE, PF_RESUME }; + static PrintFlag print_key_flag = PF_START; + + const millis_t ms = millis(); + + switch (key_status) { + case KS_IDLE: + if (!READ(BTN_PRINT)) { // Print/Pause/Resume button pressed? + key_time = ms; // Save start time + key_status++; // Go to debounce test + } + break; + + case KS_PRESS: + if (ELAPSED(ms, key_time + BTN_DEBOUNCE_MS)) // Wait for debounce interval to expire + key_status = READ(BTN_PRINT) ? KS_IDLE : KS_PROCEED; // Proceed if still pressed + break; + + case KS_PROCEED: + if (!READ(BTN_PRINT)) break; // Wait for the button to be released + key_status = KS_IDLE; // Ready for the next press + if (PENDING(ms, key_time + 1200 - BTN_DEBOUNCE_MS)) { // Register a press < 1.2 seconds + switch (print_key_flag) { + case PF_START: { // The "Print" button starts an SD card print + if (printingIsActive()) break; // Already printing? (find another line that checks for 'is planner doing anything else right now?') + blink_interval_ms = LED_BLINK_2; // Blink the indicator LED at 1 second intervals + print_key_flag = PF_PAUSE; // The "Print" button now pauses the print + card.mount(); // Force SD card to mount - now! + if (!card.isMounted) { // Failed to mount? + blink_interval_ms = LED_OFF; // Turn off LED + print_key_flag = PF_START; + return; // Bail out + } + card.ls(); // List all files to serial output + const uint16_t filecnt = card.countFilesInWorkDir(); // Count printable files in cwd + if (filecnt == 0) return; // None are printable? + card.selectFileByIndex(filecnt); // Select the last file according to current sort options + card.openAndPrintFile(card.filename); // Start printing it + break; + } + case PF_PAUSE: { // Pause printing (not currently firing) + if (!printingIsActive()) break; + blink_interval_ms = LED_ON; // Set indicator to steady ON + queue.inject(F("M25")); // Queue Pause + print_key_flag = PF_RESUME; // The "Print" button now resumes the print + break; + } + case PF_RESUME: { // Resume printing + if (printingIsActive()) break; + blink_interval_ms = LED_BLINK_2; // Blink the indicator LED at 1 second intervals + queue.inject(F("M24")); // Queue resume + print_key_flag = PF_PAUSE; // The "Print" button now pauses the print + break; + } + } + } + else { // Register a longer press + if (print_key_flag == PF_START && !printingIsActive()) { // While not printing, this moves Z up 10mm + blink_interval_ms = LED_ON; + queue.inject(F("G91\nG0 Z10 F600\nG90")); // Raise Z soon after returning to main loop + } + else { // While printing, cancel print + card.abortFilePrintSoon(); // There is a delay while the current steps play out + blink_interval_ms = LED_OFF; // Turn off LED + } + planner.synchronize(); // Wait for commands already in the planner to finish + TERN_(HAS_STEPPER_RESET, disableStepperDrivers()); // Disable all steppers - now! + print_key_flag = PF_START; // The "Print" button now starts a new print + } + break; + } +} +#endif // EASYTHREED_UI diff --git a/Marlin/src/feature/easythreed_ui.h b/Marlin/src/feature/easythreed_ui.h new file mode 100644 index 0000000000..af9ad2d090 --- /dev/null +++ b/Marlin/src/feature/easythreed_ui.h @@ -0,0 +1,35 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +class EasythreedUI { + public: + static void init(); + static void run(); + + private: + static void blinkLED(); + static void loadButton(); + static void printButton(); +}; + +extern EasythreedUI easythreed_ui; diff --git a/Marlin/src/feature/encoder_i2c.cpp b/Marlin/src/feature/encoder_i2c.cpp index bed24f0525..87e611f86c 100644 --- a/Marlin/src/feature/encoder_i2c.cpp +++ b/Marlin/src/feature/encoder_i2c.cpp @@ -153,7 +153,7 @@ void I2CPositionEncoder::update() { #ifdef I2CPE_ERR_THRESH_ABORT if (ABS(error) > I2CPE_ERR_THRESH_ABORT * planner.settings.axis_steps_per_mm[encoderAxis]) { - //kill(PSTR("Significant Error")); + //kill(F("Significant Error")); SERIAL_ECHOLNPGM("Axis error over threshold, aborting!", error); safe_delay(5000); } @@ -232,7 +232,7 @@ bool I2CPositionEncoder::passes_test(const bool report) { if (report) { if (H != I2CPE_MAG_SIG_GOOD) SERIAL_ECHOPGM("Warning. "); SERIAL_CHAR(axis_codes[encoderAxis]); - serial_ternary(H == I2CPE_MAG_SIG_BAD, PSTR(" axis "), PSTR("magnetic strip "), PSTR("encoder ")); + serial_ternary(H == I2CPE_MAG_SIG_BAD, F(" axis "), F("magnetic strip "), F("encoder ")); switch (H) { case I2CPE_MAG_SIG_GOOD: case I2CPE_MAG_SIG_MID: diff --git a/Marlin/src/feature/fancheck.cpp b/Marlin/src/feature/fancheck.cpp new file mode 100644 index 0000000000..1b47fadecc --- /dev/null +++ b/Marlin/src/feature/fancheck.cpp @@ -0,0 +1,207 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * fancheck.cpp - fan tachometer check + */ + +#include "../inc/MarlinConfig.h" + +#if HAS_FANCHECK + +#include "fancheck.h" +#include "../module/temperature.h" + +#if HAS_AUTO_FAN && EXTRUDER_AUTO_FAN_SPEED != 255 && DISABLED(FOURWIRES_FANS) + bool FanCheck::measuring = false; +#endif +bool FanCheck::tacho_state[TACHO_COUNT]; +uint16_t FanCheck::edge_counter[TACHO_COUNT]; +uint8_t FanCheck::rps[TACHO_COUNT]; +FanCheck::TachoError FanCheck::error = FanCheck::TachoError::NONE; +bool FanCheck::enabled; + +void FanCheck::init() { + #define _TACHINIT(N) TERN(E##N##_FAN_TACHO_PULLUP, SET_INPUT_PULLUP, TERN(E##N##_FAN_TACHO_PULLDOWN, SET_INPUT_PULLDOWN, SET_INPUT))(E##N##_FAN_TACHO_PIN) + #if HAS_E0_FAN_TACHO + _TACHINIT(0); + #endif + #if HAS_E1_FAN_TACHO + _TACHINIT(1); + #endif + #if HAS_E2_FAN_TACHO + _TACHINIT(2); + #endif + #if HAS_E3_FAN_TACHO + _TACHINIT(3); + #endif + #if HAS_E4_FAN_TACHO + _TACHINIT(4); + #endif + #if HAS_E5_FAN_TACHO + _TACHINIT(5); + #endif + #if HAS_E6_FAN_TACHO + _TACHINIT(6); + #endif + #if HAS_E7_FAN_TACHO + _TACHINIT(7); + #endif +} + +void FanCheck::update_tachometers() { + bool status; + + #define _TACHO_CASE(N) case N: status = READ(E##N##_FAN_TACHO_PIN); break; + LOOP_L_N(f, TACHO_COUNT) { + switch (f) { + #if HAS_E0_FAN_TACHO + _TACHO_CASE(0) + #endif + #if HAS_E1_FAN_TACHO + _TACHO_CASE(1) + #endif + #if HAS_E2_FAN_TACHO + _TACHO_CASE(2) + #endif + #if HAS_E3_FAN_TACHO + _TACHO_CASE(3) + #endif + #if HAS_E4_FAN_TACHO + _TACHO_CASE(4) + #endif + #if HAS_E5_FAN_TACHO + _TACHO_CASE(5) + #endif + #if HAS_E6_FAN_TACHO + _TACHO_CASE(6) + #endif + #if HAS_E7_FAN_TACHO + _TACHO_CASE(7) + #endif + default: continue; + } + + if (status != tacho_state[f]) { + if (measuring) ++edge_counter[f]; + tacho_state[f] = status; + } + } +} + +void FanCheck::compute_speed(uint16_t elapsedTime) { + static uint8_t errors_count[TACHO_COUNT]; + static uint8_t fan_reported_errors_msk = 0; + + uint8_t fan_error_msk = 0; + LOOP_L_N(f, TACHO_COUNT) { + switch (f) { + TERN_(HAS_E0_FAN_TACHO, case 0:) + TERN_(HAS_E1_FAN_TACHO, case 1:) + TERN_(HAS_E2_FAN_TACHO, case 2:) + TERN_(HAS_E3_FAN_TACHO, case 3:) + TERN_(HAS_E4_FAN_TACHO, case 4:) + TERN_(HAS_E5_FAN_TACHO, case 5:) + TERN_(HAS_E6_FAN_TACHO, case 6:) + TERN_(HAS_E7_FAN_TACHO, case 7:) + // Compute fan speed + rps[f] = edge_counter[f] * float(250) / elapsedTime; + edge_counter[f] = 0; + + // Check fan speed + constexpr int8_t max_extruder_fan_errors = TERN(HAS_PWMFANCHECK, 10000, 5000) / Temperature::fan_update_interval_ms; + + if (rps[f] >= 20 || TERN0(HAS_AUTO_FAN, thermalManager.autofan_speed[f] == 0)) + errors_count[f] = 0; + else if (errors_count[f] < max_extruder_fan_errors) + ++errors_count[f]; + else if (enabled) + SBI(fan_error_msk, f); + break; + } + } + + // Drop the error when all fans are ok + if (!fan_error_msk && error == TachoError::REPORTED) error = TachoError::FIXED; + + if (error == TachoError::FIXED && !printJobOngoing() && !printingIsPaused()) { + error = TachoError::NONE; // if the issue has been fixed while the printer is idle, reenable immediately + ui.reset_alert_level(); + } + + if (fan_error_msk & ~fan_reported_errors_msk) { + // Handle new faults only + LOOP_L_N(f, TACHO_COUNT) if (TEST(fan_error_msk, f)) report_speed_error(f); + } + fan_reported_errors_msk = fan_error_msk; +} + +void FanCheck::report_speed_error(uint8_t fan) { + if (printJobOngoing()) { + if (error == TachoError::NONE) { + if (thermalManager.degTargetHotend(fan) != 0) { + kill(GET_TEXT_F(MSG_FAN_SPEED_FAULT)); + error = TachoError::REPORTED; + } + else + error = TachoError::DETECTED; // Plans error for next processed command + } + } + else if (!printingIsPaused()) { + thermalManager.setTargetHotend(0, fan); // Always disable heating + if (error == TachoError::NONE) error = TachoError::REPORTED; + } + + SERIAL_ERROR_MSG(STR_ERR_FANSPEED, fan); + LCD_ALERTMESSAGE(MSG_FAN_SPEED_FAULT); +} + +void FanCheck::print_fan_states() { + LOOP_L_N(s, 2) { + LOOP_L_N(f, TACHO_COUNT) { + switch (f) { + TERN_(HAS_E0_FAN_TACHO, case 0:) + TERN_(HAS_E1_FAN_TACHO, case 1:) + TERN_(HAS_E2_FAN_TACHO, case 2:) + TERN_(HAS_E3_FAN_TACHO, case 3:) + TERN_(HAS_E4_FAN_TACHO, case 4:) + TERN_(HAS_E5_FAN_TACHO, case 5:) + TERN_(HAS_E6_FAN_TACHO, case 6:) + TERN_(HAS_E7_FAN_TACHO, case 7:) + SERIAL_ECHOPGM("E", f); + if (s == 0) + SERIAL_ECHOPGM(":", 60 * rps[f], " RPM "); + else + SERIAL_ECHOPGM("@:", TERN(HAS_AUTO_FAN, thermalManager.autofan_speed[f], 255), " "); + break; + } + } + } + SERIAL_EOL(); +} + +#if ENABLED(AUTO_REPORT_FANS) + AutoReporter FanCheck::auto_reporter; + void FanCheck::AutoReportFan::report() { print_fan_states(); } +#endif + +#endif // HAS_FANCHECK diff --git a/Marlin/src/feature/fancheck.h b/Marlin/src/feature/fancheck.h new file mode 100644 index 0000000000..6e8038b498 --- /dev/null +++ b/Marlin/src/feature/fancheck.h @@ -0,0 +1,89 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include "../inc/MarlinConfig.h" + +#if HAS_FANCHECK + +#include "../MarlinCore.h" +#include "../lcd/marlinui.h" + +#if ENABLED(AUTO_REPORT_FANS) + #include "../libs/autoreport.h" +#endif + +#if ENABLED(PARK_HEAD_ON_PAUSE) + #include "../gcode/queue.h" +#endif + +/** + * fancheck.h + */ +#define TACHO_COUNT TERN(HAS_E7_FAN_TACHO, 8, TERN(HAS_E6_FAN_TACHO, 7, TERN(HAS_E5_FAN_TACHO, 6, TERN(HAS_E4_FAN_TACHO, 5, TERN(HAS_E3_FAN_TACHO, 4, TERN(HAS_E2_FAN_TACHO, 3, TERN(HAS_E1_FAN_TACHO, 2, 1))))))) + +class FanCheck { + private: + + enum class TachoError : uint8_t { NONE, DETECTED, REPORTED, FIXED }; + + #if HAS_PWMFANCHECK + static bool measuring; // For future use (3 wires PWM controlled fans) + #else + static constexpr bool measuring = true; + #endif + static bool tacho_state[TACHO_COUNT]; + static uint16_t edge_counter[TACHO_COUNT]; + static uint8_t rps[TACHO_COUNT]; + static TachoError error; + + static inline void report_speed_error(uint8_t fan); + + public: + + static bool enabled; + + static void init(); + static void update_tachometers(); + static void compute_speed(uint16_t elapsedTime); + static void print_fan_states(); + #if HAS_PWMFANCHECK + static inline void toggle_measuring() { measuring = !measuring; } + static inline bool is_measuring() { return measuring; } + #endif + + static inline void check_deferred_error() { + if (error == TachoError::DETECTED) { + error = TachoError::REPORTED; + TERN(PARK_HEAD_ON_PAUSE, queue.inject(F("M125")), kill(GET_TEXT_F(MSG_FAN_SPEED_FAULT))); + } + } + + #if ENABLED(AUTO_REPORT_FANS) + struct AutoReportFan { static void report(); }; + static AutoReporter auto_reporter; + #endif +}; + +extern FanCheck fan_check; + +#endif // HAS_FANCHECK diff --git a/Marlin/src/feature/host_actions.cpp b/Marlin/src/feature/host_actions.cpp index 62e60320f7..be7b055b55 100644 --- a/Marlin/src/feature/host_actions.cpp +++ b/Marlin/src/feature/host_actions.cpp @@ -24,10 +24,10 @@ #if ENABLED(HOST_ACTION_COMMANDS) -#include "host_actions.h" - //#define DEBUG_HOST_ACTIONS +#include "host_actions.h" + #if ENABLED(ADVANCED_PAUSE_FEATURE) #include "pause.h" #include "../gcode/queue.h" @@ -37,37 +37,57 @@ #include "runout.h" #endif -void host_action(PGM_P const pstr, const bool eol) { +HostUI hostui; + +flag_t HostUI::flag; + +void HostUI::action(FSTR_P const fstr, const bool eol) { + if (!flag.bits) return; PORT_REDIRECT(SerialMask::All); SERIAL_ECHOPGM("//action:"); - SERIAL_ECHOPGM_P(pstr); + SERIAL_ECHOF(fstr); if (eol) SERIAL_EOL(); } #ifdef ACTION_ON_KILL - void host_action_kill() { host_action(PSTR(ACTION_ON_KILL)); } + void HostUI::kill() { action(F(ACTION_ON_KILL)); } #endif #ifdef ACTION_ON_PAUSE - void host_action_pause(const bool eol/*=true*/) { host_action(PSTR(ACTION_ON_PAUSE), eol); } + void HostUI::pause(const bool eol/*=true*/) { action(F(ACTION_ON_PAUSE), eol); } #endif #ifdef ACTION_ON_PAUSED - void host_action_paused(const bool eol/*=true*/) { host_action(PSTR(ACTION_ON_PAUSED), eol); } + void HostUI::paused(const bool eol/*=true*/) { action(F(ACTION_ON_PAUSED), eol); } #endif #ifdef ACTION_ON_RESUME - void host_action_resume() { host_action(PSTR(ACTION_ON_RESUME)); } + void HostUI::resume() { action(F(ACTION_ON_RESUME)); } #endif #ifdef ACTION_ON_RESUMED - void host_action_resumed() { host_action(PSTR(ACTION_ON_RESUMED)); } + void HostUI::resumed() { action(F(ACTION_ON_RESUMED)); } #endif #ifdef ACTION_ON_CANCEL - void host_action_cancel() { host_action(PSTR(ACTION_ON_CANCEL)); } + void HostUI::cancel() { action(F(ACTION_ON_CANCEL)); } #endif #ifdef ACTION_ON_START - void host_action_start() { host_action(PSTR(ACTION_ON_START)); } + void HostUI::start() { action(F(ACTION_ON_START)); } +#endif + +#if ENABLED(G29_RETRY_AND_RECOVER) + #ifdef ACTION_ON_G29_RECOVER + void HostUI::g29_recover() { action(F(ACTION_ON_G29_RECOVER)); } + #endif + #ifdef ACTION_ON_G29_FAILURE + void HostUI::g29_failure() { action(F(ACTION_ON_G29_FAILURE)); } + #endif +#endif + +#ifdef SHUTDOWN_ACTION + void HostUI::shutdown() { action(F(SHUTDOWN_ACTION)); } #endif #if ENABLED(HOST_PROMPT_SUPPORT) + PromptReason HostUI::host_prompt_reason = PROMPT_NOT_DEFINED; + PGMSTR(CONTINUE_STR, "Continue"); PGMSTR(DISMISS_STR, "Dismiss"); @@ -75,64 +95,69 @@ void host_action(PGM_P const pstr, const bool eol) { extern bool wait_for_user; #endif - PromptReason host_prompt_reason = PROMPT_NOT_DEFINED; - - void host_action_notify(const char * const message) { + void HostUI::notify(const char * const cstr) { + if (!flag.bits) return; PORT_REDIRECT(SerialMask::All); - host_action(PSTR("notification "), false); - SERIAL_ECHOLN(message); + action(F("notification "), false); + SERIAL_ECHOLN(cstr); } - void host_action_notify_P(PGM_P const message) { + void HostUI::notify_P(PGM_P const pstr) { + if (!flag.bits) return; PORT_REDIRECT(SerialMask::All); - host_action(PSTR("notification "), false); - SERIAL_ECHOLNPGM_P(message); + action(F("notification "), false); + SERIAL_ECHOLNPGM_P(pstr); } - void host_action_prompt(PGM_P const ptype, const bool eol=true) { + void HostUI::prompt(FSTR_P const ptype, const bool eol/*=true*/) { + if (!flag.bits) return; PORT_REDIRECT(SerialMask::All); - host_action(PSTR("prompt_"), false); - SERIAL_ECHOPGM_P(ptype); + action(F("prompt_"), false); + SERIAL_ECHOF(ptype); if (eol) SERIAL_EOL(); } - void host_action_prompt_plus(PGM_P const ptype, PGM_P const pstr, const char extra_char='\0') { - host_action_prompt(ptype, false); + void HostUI::prompt_plus(FSTR_P const ptype, FSTR_P const fstr, const char extra_char/*='\0'*/) { + if (!flag.bits) return; + prompt(ptype, false); PORT_REDIRECT(SerialMask::All); SERIAL_CHAR(' '); - SERIAL_ECHOPGM_P(pstr); + SERIAL_ECHOF(fstr); if (extra_char != '\0') SERIAL_CHAR(extra_char); SERIAL_EOL(); } - void host_action_prompt_begin(const PromptReason reason, PGM_P const pstr, const char extra_char/*='\0'*/) { - host_action_prompt_end(); + void HostUI::prompt_begin(const PromptReason reason, FSTR_P const fstr, const char extra_char/*='\0'*/) { + if (!flag.bits) return; + prompt_end(); host_prompt_reason = reason; - host_action_prompt_plus(PSTR("begin"), pstr, extra_char); + prompt_plus(F("begin"), fstr, extra_char); } - void host_action_prompt_button(PGM_P const pstr) { host_action_prompt_plus(PSTR("button"), pstr); } - void host_action_prompt_end() { host_action_prompt(PSTR("end")); } - void host_action_prompt_show() { host_action_prompt(PSTR("show")); } - - void _host_prompt_show(PGM_P const btn1/*=nullptr*/, PGM_P const btn2/*=nullptr*/) { - if (btn1) host_action_prompt_button(btn1); - if (btn2) host_action_prompt_button(btn2); - host_action_prompt_show(); + void HostUI::prompt_button(FSTR_P const fstr) { prompt_plus(F("button"), fstr); } + void HostUI::prompt_end() { prompt(F("end")); } + void HostUI::prompt_show() { prompt(F("show")); } + + void HostUI::_prompt_show(FSTR_P const btn1, FSTR_P const btn2) { + if (btn1) prompt_button(btn1); + if (btn2) prompt_button(btn2); + prompt_show(); } - void host_prompt_do(const PromptReason reason, PGM_P const pstr, PGM_P const btn1/*=nullptr*/, PGM_P const btn2/*=nullptr*/) { - host_action_prompt_begin(reason, pstr); - _host_prompt_show(btn1, btn2); + void HostUI::prompt_do(const PromptReason reason, FSTR_P const fstr, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) { + prompt_begin(reason, fstr); + _prompt_show(btn1, btn2); } - void host_prompt_do(const PromptReason reason, PGM_P const pstr, const char extra_char, PGM_P const btn1/*=nullptr*/, PGM_P const btn2/*=nullptr*/) { - host_action_prompt_begin(reason, pstr, extra_char); - _host_prompt_show(btn1, btn2); + void HostUI::prompt_do(const PromptReason reason, FSTR_P const fstr, const char extra_char, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) { + prompt_begin(reason, fstr, extra_char); + _prompt_show(btn1, btn2); } - void filament_load_host_prompt() { - const bool disable_to_continue = TERN0(HAS_FILAMENT_SENSOR, runout.filament_ran_out); - host_prompt_do(PROMPT_FILAMENT_RUNOUT, PSTR("Paused"), PSTR("PurgeMore"), - disable_to_continue ? PSTR("DisableRunout") : CONTINUE_STR - ); - } + #if ENABLED(ADVANCED_PAUSE_FEATURE) + void HostUI::filament_load_prompt() { + const bool disable_to_continue = TERN0(HAS_FILAMENT_SENSOR, runout.filament_ran_out); + prompt_do(PROMPT_FILAMENT_RUNOUT, F("Paused"), F("PurgeMore"), + disable_to_continue ? F("DisableRunout") : FPSTR(CONTINUE_STR) + ); + } + #endif // // Handle responses from the host, such as: @@ -141,7 +166,7 @@ void host_action(PGM_P const pstr, const bool eol) { // - Resume Print response // - Dismissal of info // - void host_response_handler(const uint8_t response) { + void HostUI::handle_response(const uint8_t response) { const PromptReason hpr = host_prompt_reason; host_prompt_reason = PROMPT_NOT_DEFINED; // Reset now ahead of logic switch (hpr) { diff --git a/Marlin/src/feature/host_actions.h b/Marlin/src/feature/host_actions.h index 065b59d755..45379afc29 100644 --- a/Marlin/src/feature/host_actions.h +++ b/Marlin/src/feature/host_actions.h @@ -24,34 +24,13 @@ #include "../inc/MarlinConfigPre.h" #include "../HAL/shared/Marduino.h" -void host_action(PGM_P const pstr, const bool eol=true); - -#ifdef ACTION_ON_KILL - void host_action_kill(); -#endif -#ifdef ACTION_ON_PAUSE - void host_action_pause(const bool eol=true); -#endif -#ifdef ACTION_ON_PAUSED - void host_action_paused(const bool eol=true); -#endif -#ifdef ACTION_ON_RESUME - void host_action_resume(); -#endif -#ifdef ACTION_ON_RESUMED - void host_action_resumed(); -#endif -#ifdef ACTION_ON_CANCEL - void host_action_cancel(); -#endif -#ifdef ACTION_ON_START - void host_action_start(); -#endif +typedef union { + uint8_t bits; + struct { bool info:1, errors:1, debug:1; }; +} flag_t; #if ENABLED(HOST_PROMPT_SUPPORT) - extern const char CONTINUE_STR[], DISMISS_STR[]; - enum PromptReason : uint8_t { PROMPT_NOT_DEFINED, PROMPT_FILAMENT_RUNOUT, @@ -61,21 +40,83 @@ void host_action(PGM_P const pstr, const bool eol=true); PROMPT_INFO }; - extern PromptReason host_prompt_reason; +#endif - void host_response_handler(const uint8_t response); - void host_action_notify(const char * const message); - void host_action_notify_P(PGM_P const message); - void host_action_prompt_begin(const PromptReason reason, PGM_P const pstr, const char extra_char='\0'); - void host_action_prompt_button(PGM_P const pstr); - void host_action_prompt_end(); - void host_action_prompt_show(); - void host_prompt_do(const PromptReason reason, PGM_P const pstr, PGM_P const btn1=nullptr, PGM_P const btn2=nullptr); - void host_prompt_do(const PromptReason reason, PGM_P const pstr, const char extra_char, PGM_P const btn1=nullptr, PGM_P const btn2=nullptr); - inline void host_prompt_open(const PromptReason reason, PGM_P const pstr, PGM_P const btn1=nullptr, PGM_P const btn2=nullptr) { - if (host_prompt_reason == PROMPT_NOT_DEFINED) host_prompt_do(reason, pstr, btn1, btn2); - } +class HostUI { + public: - void filament_load_host_prompt(); + static flag_t flag; + HostUI() { flag.bits = 0xFF; } -#endif + static void action(FSTR_P const fstr, const bool eol=true); + + #ifdef ACTION_ON_KILL + static void kill(); + #endif + #ifdef ACTION_ON_PAUSE + static void pause(const bool eol=true); + #endif + #ifdef ACTION_ON_PAUSED + static void paused(const bool eol=true); + #endif + #ifdef ACTION_ON_RESUME + static void resume(); + #endif + #ifdef ACTION_ON_RESUMED + static void resumed(); + #endif + #ifdef ACTION_ON_CANCEL + static void cancel(); + #endif + #ifdef ACTION_ON_START + static void start(); + #endif + #ifdef SHUTDOWN_ACTION + static void shutdown(); + #endif + + #if ENABLED(G29_RETRY_AND_RECOVER) + #ifdef ACTION_ON_G29_RECOVER + static void g29_recover(); + #endif + #ifdef ACTION_ON_G29_FAILURE + static void g29_failure(); + #endif + #endif + + #if ENABLED(HOST_PROMPT_SUPPORT) + private: + static void prompt(FSTR_P const ptype, const bool eol=true); + static void prompt_plus(FSTR_P const ptype, FSTR_P const fstr, const char extra_char='\0'); + static void prompt_show(); + static void _prompt_show(FSTR_P const btn1, FSTR_P const btn2); + + public: + static PromptReason host_prompt_reason; + + static void handle_response(const uint8_t response); + + static void notify_P(PGM_P const message); + static inline void notify(FSTR_P const fmsg) { notify_P(FTOP(fmsg)); } + static void notify(const char * const message); + + static void prompt_begin(const PromptReason reason, FSTR_P const fstr, const char extra_char='\0'); + static void prompt_button(FSTR_P const fstr); + static void prompt_end(); + static void prompt_do(const PromptReason reason, FSTR_P const pstr, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr); + static void prompt_do(const PromptReason reason, FSTR_P const pstr, const char extra_char, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr); + static inline void prompt_open(const PromptReason reason, FSTR_P const pstr, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr) { + if (host_prompt_reason == PROMPT_NOT_DEFINED) prompt_do(reason, pstr, btn1, btn2); + } + + #if ENABLED(ADVANCED_PAUSE_FEATURE) + static void filament_load_prompt(); + #endif + + #endif + +}; + +extern HostUI hostui; + +extern const char CONTINUE_STR[], DISMISS_STR[]; diff --git a/Marlin/src/feature/hotend_idle.cpp b/Marlin/src/feature/hotend_idle.cpp index b962743ed0..4b137f42da 100644 --- a/Marlin/src/feature/hotend_idle.cpp +++ b/Marlin/src/feature/hotend_idle.cpp @@ -77,7 +77,7 @@ void HotendIdleProtection::check() { void HotendIdleProtection::timed_out() { next_protect_ms = 0; SERIAL_ECHOLNPGM("Hotend Idle Timeout"); - LCD_MESSAGEPGM(MSG_HOTEND_IDLE_TIMEOUT); + LCD_MESSAGE(MSG_HOTEND_IDLE_TIMEOUT); HOTEND_LOOP() { if ((HOTEND_IDLE_NOZZLE_TARGET) < thermalManager.degTargetHotend(e)) thermalManager.setTargetHotend(HOTEND_IDLE_NOZZLE_TARGET, e); diff --git a/Marlin/src/feature/leds/leds.cpp b/Marlin/src/feature/leds/leds.cpp index 17e31afa5a..17d790b8cc 100644 --- a/Marlin/src/feature/leds/leds.cpp +++ b/Marlin/src/feature/leds/leds.cpp @@ -121,11 +121,11 @@ void LEDLights::set_color(const LEDColor &incol // This variant uses 3-4 separate pins for the RGB(W) components. // If the pins can do PWM then their intensity will be set. - #define _UPDATE_RGBW(C,c) do { \ - if (PWM_PIN(RGB_LED_##C##_PIN)) \ - analogWrite(pin_t(RGB_LED_##C##_PIN), c); \ - else \ - WRITE(RGB_LED_##C##_PIN, c ? HIGH : LOW); \ + #define _UPDATE_RGBW(C,c) do { \ + if (PWM_PIN(RGB_LED_##C##_PIN)) \ + set_pwm_duty(pin_t(RGB_LED_##C##_PIN), c); \ + else \ + WRITE(RGB_LED_##C##_PIN, c ? HIGH : LOW); \ }while(0) #define UPDATE_RGBW(C,c) _UPDATE_RGBW(C, TERN1(CASE_LIGHT_USE_RGB_LED, caselight.on) ? incol.c : 0) UPDATE_RGBW(R,r); UPDATE_RGBW(G,g); UPDATE_RGBW(B,b); diff --git a/Marlin/src/feature/leds/neopixel.cpp b/Marlin/src/feature/leds/neopixel.cpp index 2654e9a1df..3569cb180d 100644 --- a/Marlin/src/feature/leds/neopixel.cpp +++ b/Marlin/src/feature/leds/neopixel.cpp @@ -35,7 +35,7 @@ #endif Marlin_NeoPixel neo; -int8_t Marlin_NeoPixel::neoindex; +pixel_index_t Marlin_NeoPixel::neoindex; Adafruit_NeoPixel Marlin_NeoPixel::adaneo1(NEOPIXEL_PIXELS, NEOPIXEL_PIN, NEOPIXEL_TYPE + NEO_KHZ800); #if CONJOINED_NEOPIXEL @@ -116,7 +116,7 @@ void Marlin_NeoPixel::init() { Marlin_NeoPixel2 neo2; - int8_t Marlin_NeoPixel2::neoindex; + pixel_index_t Marlin_NeoPixel2::neoindex; Adafruit_NeoPixel Marlin_NeoPixel2::adaneo(NEOPIXEL2_PIXELS, NEOPIXEL2_PIN, NEOPIXEL2_TYPE); void Marlin_NeoPixel2::set_color(const uint32_t color) { diff --git a/Marlin/src/feature/leds/neopixel.h b/Marlin/src/feature/leds/neopixel.h index b2c16459f5..814ae9c8d8 100644 --- a/Marlin/src/feature/leds/neopixel.h +++ b/Marlin/src/feature/leds/neopixel.h @@ -25,6 +25,8 @@ * NeoPixel support */ +#define MAX_NEOPIXELS 127 + #ifndef _NEOPIXEL_INCLUDE_ #error "Always include 'leds.h' and not 'neopixel.h' directly." #endif @@ -63,7 +65,13 @@ #endif // ------------------------ -// Function prototypes +// Types +// ------------------------ + +typedef IF<(MAX_NEOPIXELS > 127), int16_t, int8_t>::type pixel_index_t; + +// ------------------------ +// Classes // ------------------------ class Marlin_NeoPixel { @@ -74,7 +82,7 @@ private: #endif public: - static int8_t neoindex; + static pixel_index_t neoindex; static void init(); static void set_color_startup(const uint32_t c); @@ -150,7 +158,7 @@ extern Marlin_NeoPixel neo; static Adafruit_NeoPixel adaneo; public: - static int8_t neoindex; + static pixel_index_t neoindex; static void init(); static void set_color_startup(const uint32_t c); diff --git a/Marlin/src/feature/max7219.cpp b/Marlin/src/feature/max7219.cpp index e13c6f5b97..474933aa19 100644 --- a/Marlin/src/feature/max7219.cpp +++ b/Marlin/src/feature/max7219.cpp @@ -124,11 +124,10 @@ uint8_t Max7219::suspended; // = 0; #define SIG_DELAY() DELAY_NS(250) #endif -void Max7219::error(const char * const func, const int32_t v1, const int32_t v2/*=-1*/) { +void Max7219::error(FSTR_P const func, const int32_t v1, const int32_t v2/*=-1*/) { #if ENABLED(MAX7219_ERRORS) SERIAL_ECHOPGM("??? Max7219::"); - SERIAL_ECHOPGM_P(func); - SERIAL_CHAR('('); + SERIAL_ECHOF(func, AS_CHAR('(')); SERIAL_ECHO(v1); if (v2 > 0) SERIAL_ECHOPGM(", ", v2); SERIAL_CHAR(')'); @@ -268,24 +267,24 @@ void Max7219::set(const uint8_t line, const uint8_t bits) { // Modify a single LED bit and send the changed line void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on) { - if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(PSTR("led_set"), x, y); + if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_set"), x, y); if (BIT_7219(x, y) == on) return; XOR_7219(x, y); refresh_unit_line(LED_IND(x, y)); } void Max7219::led_on(const uint8_t x, const uint8_t y) { - if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(PSTR("led_on"), x, y); + if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_on"), x, y); led_set(x, y, true); } void Max7219::led_off(const uint8_t x, const uint8_t y) { - if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(PSTR("led_off"), x, y); + if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_off"), x, y); led_set(x, y, false); } void Max7219::led_toggle(const uint8_t x, const uint8_t y) { - if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(PSTR("led_toggle"), x, y); + if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_toggle"), x, y); led_set(x, y, !BIT_7219(x, y)); } @@ -328,13 +327,13 @@ void Max7219::fill() { } void Max7219::clear_row(const uint8_t row) { - if (row >= MAX7219_Y_LEDS) return error(PSTR("clear_row"), row); + if (row >= MAX7219_Y_LEDS) return error(F("clear_row"), row); LOOP_L_N(x, MAX7219_X_LEDS) CLR_7219(x, row); send_row(row); } void Max7219::clear_column(const uint8_t col) { - if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col); + if (col >= MAX7219_X_LEDS) return error(F("set_column"), col); LOOP_L_N(y, MAX7219_Y_LEDS) CLR_7219(col, y); send_column(col); } @@ -345,7 +344,7 @@ void Max7219::clear_column(const uint8_t col) { * once with a single call to the function (if rotated 90° or 270°). */ void Max7219::set_row(const uint8_t row, const uint32_t val) { - if (row >= MAX7219_Y_LEDS) return error(PSTR("set_row"), row); + if (row >= MAX7219_Y_LEDS) return error(F("set_row"), row); uint32_t mask = _BV32(MAX7219_X_LEDS - 1); LOOP_L_N(x, MAX7219_X_LEDS) { if (val & mask) SET_7219(x, row); else CLR_7219(x, row); @@ -360,7 +359,7 @@ void Max7219::set_row(const uint8_t row, const uint32_t val) { * once with a single call to the function (if rotated 0° or 180°). */ void Max7219::set_column(const uint8_t col, const uint32_t val) { - if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col); + if (col >= MAX7219_X_LEDS) return error(F("set_column"), col); uint32_t mask = _BV32(MAX7219_Y_LEDS - 1); LOOP_L_N(y, MAX7219_Y_LEDS) { if (val & mask) SET_7219(col, y); else CLR_7219(col, y); @@ -371,56 +370,56 @@ void Max7219::set_column(const uint8_t col, const uint32_t val) { void Max7219::set_rows_16bits(const uint8_t y, uint32_t val) { #if MAX7219_X_LEDS == 8 - if (y > MAX7219_Y_LEDS - 2) return error(PSTR("set_rows_16bits"), y, val); + if (y > MAX7219_Y_LEDS - 2) return error(F("set_rows_16bits"), y, val); set_row(y + 1, val); val >>= 8; set_row(y + 0, val); #else // at least 16 bits on each row - if (y > MAX7219_Y_LEDS - 1) return error(PSTR("set_rows_16bits"), y, val); + if (y > MAX7219_Y_LEDS - 1) return error(F("set_rows_16bits"), y, val); set_row(y, val); #endif } void Max7219::set_rows_32bits(const uint8_t y, uint32_t val) { #if MAX7219_X_LEDS == 8 - if (y > MAX7219_Y_LEDS - 4) return error(PSTR("set_rows_32bits"), y, val); + if (y > MAX7219_Y_LEDS - 4) return error(F("set_rows_32bits"), y, val); set_row(y + 3, val); val >>= 8; set_row(y + 2, val); val >>= 8; set_row(y + 1, val); val >>= 8; set_row(y + 0, val); #elif MAX7219_X_LEDS == 16 - if (y > MAX7219_Y_LEDS - 2) return error(PSTR("set_rows_32bits"), y, val); + if (y > MAX7219_Y_LEDS - 2) return error(F("set_rows_32bits"), y, val); set_row(y + 1, val); val >>= 16; set_row(y + 0, val); #else // at least 24 bits on each row. In the 3 matrix case, just display the low 24 bits - if (y > MAX7219_Y_LEDS - 1) return error(PSTR("set_rows_32bits"), y, val); + if (y > MAX7219_Y_LEDS - 1) return error(F("set_rows_32bits"), y, val); set_row(y, val); #endif } void Max7219::set_columns_16bits(const uint8_t x, uint32_t val) { #if MAX7219_Y_LEDS == 8 - if (x > MAX7219_X_LEDS - 2) return error(PSTR("set_columns_16bits"), x, val); + if (x > MAX7219_X_LEDS - 2) return error(F("set_columns_16bits"), x, val); set_column(x + 0, val); val >>= 8; set_column(x + 1, val); #else // at least 16 bits in each column - if (x > MAX7219_X_LEDS - 1) return error(PSTR("set_columns_16bits"), x, val); + if (x > MAX7219_X_LEDS - 1) return error(F("set_columns_16bits"), x, val); set_column(x, val); #endif } void Max7219::set_columns_32bits(const uint8_t x, uint32_t val) { #if MAX7219_Y_LEDS == 8 - if (x > MAX7219_X_LEDS - 4) return error(PSTR("set_rows_32bits"), x, val); + if (x > MAX7219_X_LEDS - 4) return error(F("set_rows_32bits"), x, val); set_column(x + 3, val); val >>= 8; set_column(x + 2, val); val >>= 8; set_column(x + 1, val); val >>= 8; set_column(x + 0, val); #elif MAX7219_Y_LEDS == 16 - if (x > MAX7219_X_LEDS - 2) return error(PSTR("set_rows_32bits"), x, val); + if (x > MAX7219_X_LEDS - 2) return error(F("set_rows_32bits"), x, val); set_column(x + 1, val); val >>= 16; set_column(x + 0, val); #else // at least 24 bits on each row. In the 3 matrix case, just display the low 24 bits - if (x > MAX7219_X_LEDS - 1) return error(PSTR("set_rows_32bits"), x, val); + if (x > MAX7219_X_LEDS - 1) return error(F("set_rows_32bits"), x, val); set_column(x, val); #endif } diff --git a/Marlin/src/feature/max7219.h b/Marlin/src/feature/max7219.h index 3e5b62db2f..c25fef1730 100644 --- a/Marlin/src/feature/max7219.h +++ b/Marlin/src/feature/max7219.h @@ -42,6 +42,8 @@ * a Max7219_Set_Row(). The opposite is true for rotations of 0 or 180 degrees. */ +#include "../inc/MarlinConfig.h" + #ifndef MAX7219_ROTATE #define MAX7219_ROTATE 0 #endif @@ -140,7 +142,7 @@ public: private: static uint8_t suspended; - static void error(const char * const func, const int32_t v1, const int32_t v2=-1); + static void error(FSTR_P const func, const int32_t v1, const int32_t v2=-1); static void noop(); static void set(const uint8_t line, const uint8_t bits); static void send_row(const uint8_t row); diff --git a/Marlin/src/feature/meatpack.cpp b/Marlin/src/feature/meatpack.cpp index 2edcd7478a..b2899243b2 100644 --- a/Marlin/src/feature/meatpack.cpp +++ b/Marlin/src/feature/meatpack.cpp @@ -169,10 +169,9 @@ void MeatPack::handle_command(const MeatPack_Command c) { void MeatPack::report_state() { // NOTE: if any configuration vars are added below, the outgoing sync text for host plugin // should not contain the "PV' substring, as this is used to indicate protocol version - SERIAL_ECHOPGM("[MP] "); - SERIAL_ECHOPGM(MeatPack_ProtocolVersion " "); + SERIAL_ECHOPGM("[MP] " MeatPack_ProtocolVersion " "); serialprint_onoff(TEST(state, MPConfig_Bit_Active)); - SERIAL_ECHOPGM_P(TEST(state, MPConfig_Bit_NoSpaces) ? PSTR(" NSP\n") : PSTR(" ESP\n")); + SERIAL_ECHOF(TEST(state, MPConfig_Bit_NoSpaces) ? F(" NSP\n") : F(" ESP\n")); } /** diff --git a/Marlin/src/feature/mmu/mmu.cpp b/Marlin/src/feature/mmu/mmu.cpp index 6340f3c301..58c49ed224 100644 --- a/Marlin/src/feature/mmu/mmu.cpp +++ b/Marlin/src/feature/mmu/mmu.cpp @@ -24,9 +24,9 @@ #if HAS_PRUSA_MMU1 -#include "../MarlinCore.h" -#include "../module/planner.h" -#include "../module/stepper.h" +#include "../../MarlinCore.h" +#include "../../module/planner.h" +#include "../../module/stepper.h" void mmu_init() { SET_OUTPUT(E_MUX0_PIN); diff --git a/Marlin/src/feature/mmu/mmu2.cpp b/Marlin/src/feature/mmu/mmu2.cpp index 3727c8c86d..2813337c63 100644 --- a/Marlin/src/feature/mmu/mmu2.cpp +++ b/Marlin/src/feature/mmu/mmu2.cpp @@ -54,7 +54,7 @@ MMU2 mmu2; #define MMU_CMD_TIMEOUT 45000UL // 45s timeout for mmu commands (except P0) #define MMU_P0_TIMEOUT 3000UL // Timeout for P0 command: 3seconds -#define MMU2_COMMAND(S) tx_str_P(PSTR(S "\n")) +#define MMU2_COMMAND(S) tx_str(F(S "\n")) #if ENABLED(MMU_EXTRUDER_SENSOR) uint8_t mmu_idl_sens = 0; @@ -229,17 +229,17 @@ void MMU2::mmu_loop() { if (cmd) { if (WITHIN(cmd, MMU_CMD_T0, MMU_CMD_T0 + EXTRUDERS - 1)) { // tool change - int filament = cmd - MMU_CMD_T0; + const int filament = cmd - MMU_CMD_T0; DEBUG_ECHOLNPGM("MMU <= T", filament); - tx_printf_P(PSTR("T%d\n"), filament); + tx_printf(F("T%d\n"), filament); TERN_(MMU_EXTRUDER_SENSOR, mmu_idl_sens = 1); // enable idler sensor, if any state = 3; // wait for response } else if (WITHIN(cmd, MMU_CMD_L0, MMU_CMD_L0 + EXTRUDERS - 1)) { // load - int filament = cmd - MMU_CMD_L0; + const int filament = cmd - MMU_CMD_L0; DEBUG_ECHOLNPGM("MMU <= L", filament); - tx_printf_P(PSTR("L%d\n"), filament); + tx_printf(F("L%d\n"), filament); state = 3; // wait for response } else if (cmd == MMU_CMD_C0) { @@ -257,9 +257,9 @@ void MMU2::mmu_loop() { } else if (WITHIN(cmd, MMU_CMD_E0, MMU_CMD_E0 + EXTRUDERS - 1)) { // eject filament - int filament = cmd - MMU_CMD_E0; + const int filament = cmd - MMU_CMD_E0; DEBUG_ECHOLNPGM("MMU <= E", filament); - tx_printf_P(PSTR("E%d\n"), filament); + tx_printf(F("E%d\n"), filament); state = 3; // wait for response } else if (cmd == MMU_CMD_R0) { @@ -270,9 +270,9 @@ void MMU2::mmu_loop() { } else if (WITHIN(cmd, MMU_CMD_F0, MMU_CMD_F0 + EXTRUDERS - 1)) { // filament type - int filament = cmd - MMU_CMD_F0; + const int filament = cmd - MMU_CMD_F0; DEBUG_ECHOLNPGM("MMU <= F", filament, " ", cmd_arg); - tx_printf_P(PSTR("F%d %d\n"), filament, cmd_arg); + tx_printf(F("F%d %d\n"), filament, cmd_arg); state = 3; // wait for response } @@ -356,13 +356,15 @@ void MMU2::mmu_loop() { */ bool MMU2::rx_start() { // check for start message - return rx_str_P(PSTR("start\n")); + return rx_str(F("start\n")); } /** * Check if the data received ends with the given string. */ -bool MMU2::rx_str_P(const char *str) { +bool MMU2::rx_str(FSTR_P fstr) { + PGM_P pstr = FTOP(fstr); + uint8_t i = strlen(rx_buffer); while (MMU2_SERIAL.available()) { @@ -375,14 +377,14 @@ bool MMU2::rx_str_P(const char *str) { } rx_buffer[i] = '\0'; - uint8_t len = strlen_P(str); + uint8_t len = strlen_P(pstr); if (i < len) return false; - str += len; + pstr += len; while (len--) { - char c0 = pgm_read_byte(str--), c1 = rx_buffer[i--]; + char c0 = pgm_read_byte(pstr--), c1 = rx_buffer[i--]; if (c0 == c1) continue; if (c0 == '\r' && c1 == '\n') continue; // match cr as lf if (c0 == '\n' && c1 == '\r') continue; // match lf as cr @@ -394,19 +396,19 @@ bool MMU2::rx_str_P(const char *str) { /** * Transfer data to MMU, no argument */ -void MMU2::tx_str_P(const char *str) { +void MMU2::tx_str(FSTR_P fstr) { clear_rx_buffer(); - uint8_t len = strlen_P(str); - LOOP_L_N(i, len) MMU2_SERIAL.write(pgm_read_byte(str++)); + PGM_P pstr = FTOP(fstr); + while (const char c = pgm_read_byte(pstr)) { MMU2_SERIAL.write(c); pstr++; } prev_request = millis(); } /** * Transfer data to MMU, single argument */ -void MMU2::tx_printf_P(const char *format, int argument = -1) { +void MMU2::tx_printf(FSTR_P format, int argument = -1) { clear_rx_buffer(); - uint8_t len = sprintf_P(tx_buffer, format, argument); + const uint8_t len = sprintf_P(tx_buffer, FTOP(format), argument); LOOP_L_N(i, len) MMU2_SERIAL.write(tx_buffer[i]); prev_request = millis(); } @@ -414,9 +416,9 @@ void MMU2::tx_printf_P(const char *format, int argument = -1) { /** * Transfer data to MMU, two arguments */ -void MMU2::tx_printf_P(const char *format, int argument1, int argument2) { +void MMU2::tx_printf(FSTR_P format, int argument1, int argument2) { clear_rx_buffer(); - uint8_t len = sprintf_P(tx_buffer, format, argument1, argument2); + const uint8_t len = sprintf_P(tx_buffer, FTOP(format), argument1, argument2); LOOP_L_N(i, len) MMU2_SERIAL.write(tx_buffer[i]); prev_request = millis(); } @@ -433,7 +435,7 @@ void MMU2::clear_rx_buffer() { * Check if we received 'ok' from MMU */ bool MMU2::rx_ok() { - if (rx_str_P(PSTR("ok\n"))) { + if (rx_str(F("ok\n"))) { prev_P0_request = millis(); return true; } @@ -446,12 +448,12 @@ bool MMU2::rx_ok() { void MMU2::check_version() { if (buildnr < MMU_REQUIRED_FW_BUILDNR) { SERIAL_ERROR_MSG("Invalid MMU2 firmware. Version >= " STRINGIFY(MMU_REQUIRED_FW_BUILDNR) " required."); - kill(GET_TEXT(MSG_KILL_MMU2_FIRMWARE)); + kill(GET_TEXT_F(MSG_KILL_MMU2_FIRMWARE)); } } static void mmu2_not_responding() { - LCD_MESSAGEPGM(MSG_MMU2_NOT_RESPONDING); + LCD_MESSAGE(MSG_MMU2_NOT_RESPONDING); BUZZ(100, 659); BUZZ(200, 698); BUZZ(100, 659); @@ -487,7 +489,7 @@ static void mmu2_not_responding() { if (index != extruder) { stepper.disable_extruder(); - ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); + ui.status_printf(0, GET_TEXT_F(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); command(MMU_CMD_T0 + index); manage_response(true, true); @@ -573,7 +575,7 @@ static void mmu2_not_responding() { command(MMU_CMD_U0); manage_response(true, true); } - ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); + ui.status_printf(0, GET_TEXT_F(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); mmu_loading_flag = true; command(MMU_CMD_T0 + index); manage_response(true, true); @@ -671,7 +673,7 @@ static void mmu2_not_responding() { if (index != extruder) { stepper.disable_extruder(); - ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); + ui.status_printf(0, GET_TEXT_F(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); command(MMU_CMD_T0 + index); manage_response(true, true); command(MMU_CMD_C0); @@ -808,14 +810,14 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { if (turn_off_nozzle && resume_hotend_temp) { thermalManager.setTargetHotend(resume_hotend_temp, active_extruder); - LCD_MESSAGEPGM(MSG_HEATING); + LCD_MESSAGE(MSG_HEATING); BUZZ(200, 40); while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(1000); } if (move_axes && all_axes_homed()) { - LCD_MESSAGEPGM(MSG_MMU2_RESUMING); + LCD_MESSAGE(MSG_MMU2_RESUMING); BUZZ(198, 404); BUZZ(4, 0); BUZZ(198, 404); // Move XY to starting position, then Z @@ -826,7 +828,7 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { } else { BUZZ(198, 404); BUZZ(4, 0); BUZZ(198, 404); - LCD_MESSAGEPGM(MSG_MMU2_RESUMING); + LCD_MESSAGE(MSG_MMU2_RESUMING); } } } @@ -842,7 +844,7 @@ void MMU2::set_filament_type(const uint8_t index, const uint8_t filamentType) { } void MMU2::filament_runout() { - queue.inject_P(PSTR(MMU2_FILAMENT_RUNOUT_SCRIPT)); + queue.inject(F(MMU2_FILAMENT_RUNOUT_SCRIPT)); planner.synchronize(); } @@ -853,7 +855,7 @@ void MMU2::filament_runout() { if (cmd == MMU_CMD_NONE && last_cmd == MMU_CMD_C0) { if (present && !mmu2s_triggered) { DEBUG_ECHOLNPGM("MMU <= 'A'"); - tx_str_P(PSTR("A\n")); + tx_str(F("A\n")); } // Slowly spin the extruder during C0 else { @@ -908,7 +910,7 @@ bool MMU2::load_filament_to_nozzle(const uint8_t index) { if (thermalManager.tooColdToExtrude(active_extruder)) { BUZZ(200, 404); - LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD); + LCD_ALERTMESSAGE(MSG_HOTEND_TOO_COLD); return false; } @@ -944,11 +946,11 @@ bool MMU2::eject_filament(const uint8_t index, const bool recover) { if (thermalManager.tooColdToExtrude(active_extruder)) { BUZZ(200, 404); - LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD); + LCD_ALERTMESSAGE(MSG_HOTEND_TOO_COLD); return false; } - LCD_MESSAGEPGM(MSG_MMU2_EJECTING_FILAMENT); + LCD_MESSAGE(MSG_MMU2_EJECTING_FILAMENT); stepper.enable_extruder(); current_position.e -= MMU2_FILAMENTCHANGE_EJECT_FEED; @@ -958,10 +960,10 @@ bool MMU2::eject_filament(const uint8_t index, const bool recover) { manage_response(false, false); if (recover) { - LCD_MESSAGEPGM(MSG_MMU2_EJECT_RECOVER); + LCD_MESSAGE(MSG_MMU2_EJECT_RECOVER); BUZZ(200, 404); - TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("MMU2 Eject Recover"), CONTINUE_STR)); - TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("MMU2 Eject Recover"))); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, F("MMU2 Eject Recover"), FPSTR(CONTINUE_STR))); + TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(F("MMU2 Eject Recover"))); TERN_(HAS_RESUME_CONTINUE, wait_for_user_response()); BUZZ(200, 404); BUZZ(200, 404); @@ -993,7 +995,7 @@ bool MMU2::unload() { if (thermalManager.tooColdToExtrude(active_extruder)) { BUZZ(200, 404); - LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD); + LCD_ALERTMESSAGE(MSG_HOTEND_TOO_COLD); return false; } diff --git a/Marlin/src/feature/mmu/mmu2.h b/Marlin/src/feature/mmu/mmu2.h index 95338a5184..9574e2217f 100644 --- a/Marlin/src/feature/mmu/mmu2.h +++ b/Marlin/src/feature/mmu/mmu2.h @@ -57,10 +57,10 @@ public: static bool eject_filament(const uint8_t index, const bool recover); private: - static bool rx_str_P(const char *str); - static void tx_str_P(const char *str); - static void tx_printf_P(const char *format, const int argument); - static void tx_printf_P(const char *format, const int argument1, const int argument2); + static inline bool rx_str(FSTR_P fstr); + static inline void tx_str(FSTR_P fstr); + static inline void tx_printf(FSTR_P ffmt, const int argument); + static inline void tx_printf(FSTR_P ffmt, const int argument1, const int argument2); static void clear_rx_buffer(); static bool rx_ok(); diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index d54326116e..191c0e4b08 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -194,11 +194,11 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load KEEPALIVE_STATE(PAUSED_FOR_USER); wait_for_user = true; // LCD click or M108 will clear this - TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("Load Filament"))); + TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(F("Load Filament"))); #if ENABLED(HOST_PROMPT_SUPPORT) const char tool = '0' + TERN0(MULTI_FILAMENT_SENSOR, active_extruder); - host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Load Filament T"), tool, CONTINUE_STR); + hostui.prompt_do(PROMPT_USER_CONTINUE, F("Load Filament T"), tool, FPSTR(CONTINUE_STR)); #endif while (wait_for_user) { @@ -252,9 +252,8 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_PURGE); - TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(GET_TEXT(MSG_FILAMENT_CHANGE_PURGE))); - TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT(MSG_FILAMENT_CHANGE_PURGE), CONTINUE_STR)); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_Popup_Confirm(ICON_BLTouch, GET_TEXT(MSG_FILAMENT_CHANGE_PURGE), CONTINUE_STR)); + TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE))); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE), FPSTR(CONTINUE_STR))); wait_for_user = true; // A click or M108 breaks the purge_length loop for (float purge_count = purge_length; purge_count > 0 && wait_for_user; --purge_count) unscaled_e_move(1, ADVANCED_PAUSE_PURGE_FEEDRATE); @@ -271,7 +270,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load unscaled_e_move(purge_length, ADVANCED_PAUSE_PURGE_FEEDRATE); } - TERN_(HOST_PROMPT_SUPPORT, filament_load_host_prompt()); // Initiate another host prompt. + TERN_(HOST_PROMPT_SUPPORT, hostui.filament_load_prompt()); // Initiate another host prompt. #if M600_PURGE_MORE_RESUMABLE if (show_lcd) { @@ -291,7 +290,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load } while (TERN0(M600_PURGE_MORE_RESUMABLE, pause_menu_response == PAUSE_RESPONSE_EXTRUDE_MORE)); #endif - TERN_(HOST_PROMPT_SUPPORT, host_action_prompt_end()); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_end()); return true; } @@ -397,13 +396,13 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool #if ENABLED(HOST_ACTION_COMMANDS) #ifdef ACTION_ON_PAUSED - host_action_paused(); + hostui.paused(); #elif defined(ACTION_ON_PAUSE) - host_action_pause(); + hostui.pause(); #endif #endif - TERN_(HOST_PROMPT_SUPPORT, host_prompt_open(PROMPT_INFO, PSTR("Pause"), DISMISS_STR)); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_open(PROMPT_INFO, F("Pause"), FPSTR(DISMISS_STR))); // Indicate that the printer is paused ++did_pause_print; @@ -486,7 +485,7 @@ void show_continue_prompt(const bool is_reload) { ui.pause_show_message(is_reload ? PAUSE_MESSAGE_INSERT : PAUSE_MESSAGE_WAITING); SERIAL_ECHO_START(); - SERIAL_ECHOPGM_P(is_reload ? PSTR(_PMSG(STR_FILAMENT_CHANGE_INSERT) "\n") : PSTR(_PMSG(STR_FILAMENT_CHANGE_WAIT) "\n")); + SERIAL_ECHOF(is_reload ? F(_PMSG(STR_FILAMENT_CHANGE_INSERT) "\n") : F(_PMSG(STR_FILAMENT_CHANGE_WAIT) "\n")); } void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep_count/*=0*/ DXC_ARGS) { @@ -512,8 +511,8 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep // Wait for filament insert by user and press button KEEPALIVE_STATE(PAUSED_FOR_USER); - TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT(MSG_NOZZLE_PARKED), CONTINUE_STR)); - TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(GET_TEXT(MSG_NOZZLE_PARKED))); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_NOZZLE_PARKED), FPSTR(CONTINUE_STR))); + TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_NOZZLE_PARKED))); wait_for_user = true; // LCD click or M108 will clear this while (wait_for_user) { impatient_beep(max_beep_count); @@ -528,17 +527,17 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep ui.pause_show_message(PAUSE_MESSAGE_HEAT); SERIAL_ECHO_MSG(_PMSG(STR_FILAMENT_CHANGE_HEAT)); - TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT(MSG_HEATER_TIMEOUT), GET_TEXT(MSG_REHEAT))); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_HEATER_TIMEOUT), GET_TEXT_F(MSG_REHEAT))); - TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(GET_TEXT(MSG_HEATER_TIMEOUT))); + TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_HEATER_TIMEOUT))); TERN_(HAS_RESUME_CONTINUE, wait_for_user_response(0, true)); // Wait for LCD click or M108 - TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_INFO, GET_TEXT(MSG_REHEATING))); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_INFO, GET_TEXT_F(MSG_REHEATING))); - TERN_(EXTENSIBLE_UI, ExtUI::onStatusChanged_P(GET_TEXT(MSG_REHEATING))); + TERN_(EXTENSIBLE_UI, ExtUI::onStatusChanged(GET_TEXT_F(MSG_REHEATING))); - TERN_(DWIN_CREALITY_LCD_ENHANCED, ui.set_status_P(GET_TEXT(MSG_REHEATING))); + TERN_(DWIN_CREALITY_LCD_ENHANCED, LCD_MESSAGE(MSG_REHEATING)); // Re-enable the heaters if they timed out HOTEND_LOOP() thermalManager.reset_hotend_idle_timer(e); @@ -554,9 +553,9 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep HOTEND_LOOP() thermalManager.heater_idle[e].start(nozzle_timeout); - TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT(MSG_REHEATDONE), CONTINUE_STR)); - TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(GET_TEXT(MSG_REHEATDONE))); - TERN_(DWIN_CREALITY_LCD_ENHANCED, ui.set_status_P(GET_TEXT(MSG_REHEATDONE))); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_REHEATDONE), FPSTR(CONTINUE_STR))); + TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_REHEATDONE))); + TERN_(DWIN_CREALITY_LCD_ENHANCED, LCD_MESSAGE(MSG_REHEATDONE)); IF_DISABLED(PAUSE_REHEAT_FAST_RESUME, wait_for_user = true); @@ -664,14 +663,14 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_ ui.pause_show_message(PAUSE_MESSAGE_STATUS); #ifdef ACTION_ON_RESUMED - host_action_resumed(); + hostui.resumed(); #elif defined(ACTION_ON_RESUME) - host_action_resume(); + hostui.resume(); #endif --did_pause_print; - TERN_(HOST_PROMPT_SUPPORT, host_prompt_open(PROMPT_INFO, PSTR("Resuming"), DISMISS_STR)); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_open(PROMPT_INFO, F("Resuming"), FPSTR(DISMISS_STR))); // Resume the print job timer if it was running if (print_job_timer.isPaused()) print_job_timer.start(); diff --git a/Marlin/src/feature/pause.h b/Marlin/src/feature/pause.h index d2c45e44a5..134b1d1b32 100644 --- a/Marlin/src/feature/pause.h +++ b/Marlin/src/feature/pause.h @@ -73,17 +73,10 @@ extern fil_change_settings_t fc_settings[EXTRUDERS]; extern uint8_t did_pause_print; -#if ENABLED(DUAL_X_CARRIAGE) - #define DXC_PARAMS , const int8_t DXC_ext=-1 - #define DXC_ARGS , const int8_t DXC_ext - #define DXC_PASS , DXC_ext - #define DXC_SAY , " dxc:", int(DXC_ext) -#else - #define DXC_PARAMS - #define DXC_ARGS - #define DXC_PASS - #define DXC_SAY -#endif +#define DXC_PARAMS OPTARG(DUAL_X_CARRIAGE, const int8_t DXC_ext=-1) +#define DXC_ARGS OPTARG(DUAL_X_CARRIAGE, const int8_t DXC_ext) +#define DXC_PASS OPTARG(DUAL_X_CARRIAGE, DXC_ext) +#define DXC_SAY OPTARG(DUAL_X_CARRIAGE, " dxc:", int(DXC_ext)) // Pause the print. If unload_length is set, do a Filament Unload bool pause_print( diff --git a/Marlin/src/feature/power.cpp b/Marlin/src/feature/power.cpp index 8116bd2e44..fabe35b989 100644 --- a/Marlin/src/feature/power.cpp +++ b/Marlin/src/feature/power.cpp @@ -82,7 +82,7 @@ void Power::power_on() { TERN_(HAS_TRINAMIC_CONFIG, safe_delay(PSU_POWERUP_DELAY)); #ifdef PSU_POWERUP_GCODE - GcodeSuite::process_subcommands_now_P(PSTR(PSU_POWERUP_GCODE)); + gcode.process_subcommands_now(F(PSU_POWERUP_GCODE)); #endif } @@ -95,7 +95,7 @@ void Power::power_off() { if (!psu_on) return; #ifdef PSU_POWEROFF_GCODE - GcodeSuite::process_subcommands_now_P(PSTR(PSU_POWEROFF_GCODE)); + gcode.process_subcommands_now(F(PSU_POWEROFF_GCODE)); #endif #if ENABLED(PS_OFF_SOUND) diff --git a/Marlin/src/feature/powerloss.cpp b/Marlin/src/feature/powerloss.cpp index 8db31daa40..723ec1903b 100644 --- a/Marlin/src/feature/powerloss.cpp +++ b/Marlin/src/feature/powerloss.cpp @@ -109,7 +109,7 @@ void PrintJobRecovery::check() { if (card.isMounted()) { load(); if (!valid()) return cancel(); - queue.inject_P(PSTR("M1000S")); + queue.inject(F("M1000S")); } } @@ -130,7 +130,7 @@ void PrintJobRecovery::load() { (void)file.read(&info, sizeof(info)); close(); } - debug(PSTR("Load")); + debug(F("Load")); } /** @@ -244,7 +244,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW #if POWER_LOSS_RETRACT_LEN // Retract filament now - gcode.process_subcommands_now_P(PSTR("G1 F3000 E-" STRINGIFY(POWER_LOSS_RETRACT_LEN))); + gcode.process_subcommands_now(F("G1 F3000 E-" STRINGIFY(POWER_LOSS_RETRACT_LEN))); #endif #if POWER_LOSS_ZRAISE @@ -301,7 +301,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW retract_and_lift(zraise); #endif - kill(GET_TEXT(MSG_OUTAGE_RECOVERY)); + kill(GET_TEXT_F(MSG_OUTAGE_RECOVERY)); } #endif @@ -311,7 +311,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW */ void PrintJobRecovery::write() { - debug(PSTR("Write")); + debug(F("Write")); open(false); file.seekSet(0); @@ -337,7 +337,7 @@ void PrintJobRecovery::resume() { #if HAS_LEVELING // Make sure leveling is off before any G92 and G28 - gcode.process_subcommands_now_P(PSTR("M420 S0 Z0")); + gcode.process_subcommands_now(F("M420 S0 Z0")); #endif #if HAS_HEATED_BED @@ -373,7 +373,7 @@ void PrintJobRecovery::resume() { // establish the current position as best we can. // - gcode.process_subcommands_now_P(PSTR("G92.9E0")); // Reset E to 0 + gcode.process_subcommands_now(F("G92.9E0")); // Reset E to 0 #if Z_HOME_TO_MAX @@ -410,7 +410,7 @@ void PrintJobRecovery::resume() { } // Home XY with no Z raise, and also home Z here if Z isn't homing down below. - gcode.process_subcommands_now_P(PSTR("G28R0" TERN_(HOME_XY_ONLY, "XY"))); // No raise during G28 + gcode.process_subcommands_now(F("G28R0" TERN_(HOME_XY_ONLY, "XY"))); // No raise during G28 #endif @@ -513,7 +513,7 @@ void PrintJobRecovery::resume() { // Un-retract if there was a retract at outage #if ENABLED(BACKUP_POWER_SUPPLY) && POWER_LOSS_RETRACT_LEN > 0 - gcode.process_subcommands_now_P(PSTR("G1E" STRINGIFY(POWER_LOSS_RETRACT_LEN) "F3000")); + gcode.process_subcommands_now(F("G1E" STRINGIFY(POWER_LOSS_RETRACT_LEN) "F3000")); #endif // Additional purge on resume if configured @@ -523,7 +523,7 @@ void PrintJobRecovery::resume() { #endif #if ENABLED(NOZZLE_CLEAN_FEATURE) - gcode.process_subcommands_now_P(PSTR("G12")); + gcode.process_subcommands_now(F("G12")); #endif // Move back over to the saved XY @@ -575,8 +575,8 @@ void PrintJobRecovery::resume() { #if ENABLED(DEBUG_POWER_LOSS_RECOVERY) - void PrintJobRecovery::debug(PGM_P const prefix) { - DEBUG_ECHOPGM_P(prefix); + void PrintJobRecovery::debug(FSTR_P const prefix) { + DEBUG_ECHOF(prefix); DEBUG_ECHOLNPGM(" Job Recovery Info...\nvalid_head:", info.valid_head, " valid_foot:", info.valid_foot); if (info.valid_head) { if (info.valid_head == info.valid_foot) { diff --git a/Marlin/src/feature/powerloss.h b/Marlin/src/feature/powerloss.h index 6a13c92df7..76cb398af2 100644 --- a/Marlin/src/feature/powerloss.h +++ b/Marlin/src/feature/powerloss.h @@ -204,9 +204,9 @@ class PrintJobRecovery { static inline bool valid() { return info.valid() && interrupted_file_exists(); } #if ENABLED(DEBUG_POWER_LOSS_RECOVERY) - static void debug(PGM_P const prefix); + static void debug(FSTR_P const prefix); #else - static inline void debug(PGM_P const) {} + static inline void debug(FSTR_P const) {} #endif private: diff --git a/Marlin/src/feature/probe_temp_comp.cpp b/Marlin/src/feature/probe_temp_comp.cpp index deae447568..9a975d6763 100644 --- a/Marlin/src/feature/probe_temp_comp.cpp +++ b/Marlin/src/feature/probe_temp_comp.cpp @@ -22,39 +22,53 @@ #include "../inc/MarlinConfigPre.h" -#if ENABLED(PROBE_TEMP_COMPENSATION) +#if HAS_PTC //#define DEBUG_PTC // Print extra debug output with 'M871' #include "probe_temp_comp.h" #include -ProbeTempComp temp_comp; +ProbeTempComp ptc; -int16_t ProbeTempComp::z_offsets_probe[cali_info_init[TSI_PROBE].measurements], // = {0} - ProbeTempComp::z_offsets_bed[cali_info_init[TSI_BED].measurements]; // = {0} +#if ENABLED(PTC_PROBE) + constexpr int16_t z_offsets_probe_default[PTC_PROBE_COUNT] = PTC_PROBE_ZOFFS; + int16_t ProbeTempComp::z_offsets_probe[PTC_PROBE_COUNT] = PTC_PROBE_ZOFFS; +#endif -#if ENABLED(USE_TEMP_EXT_COMPENSATION) - int16_t ProbeTempComp::z_offsets_ext[cali_info_init[TSI_EXT].measurements]; // = {0} +#if ENABLED(PTC_BED) + constexpr int16_t z_offsets_bed_default[PTC_BED_COUNT] = PTC_BED_ZOFFS; + int16_t ProbeTempComp::z_offsets_bed[PTC_BED_COUNT] = PTC_BED_ZOFFS; #endif -int16_t *ProbeTempComp::sensor_z_offsets[TSI_COUNT] = { - ProbeTempComp::z_offsets_probe, ProbeTempComp::z_offsets_bed - OPTARG(USE_TEMP_EXT_COMPENSATION, ProbeTempComp::z_offsets_ext) -}; +#if ENABLED(PTC_HOTEND) + constexpr int16_t z_offsets_hotend_default[PTC_HOTEND_COUNT] = PTC_HOTEND_ZOFFS; + int16_t ProbeTempComp::z_offsets_hotend[PTC_HOTEND_COUNT] = PTC_HOTEND_ZOFFS; +#endif -const temp_calib_t ProbeTempComp::cali_info[TSI_COUNT] = { - cali_info_init[TSI_PROBE], cali_info_init[TSI_BED] - OPTARG(USE_TEMP_EXT_COMPENSATION, cali_info_init[TSI_EXT]) +int16_t *ProbeTempComp::sensor_z_offsets[TSI_COUNT] = { + #if ENABLED(PTC_PROBE) + ProbeTempComp::z_offsets_probe, + #endif + #if ENABLED(PTC_BED) + ProbeTempComp::z_offsets_bed, + #endif + #if ENABLED(PTC_HOTEND) + ProbeTempComp::z_offsets_hotend, + #endif }; -constexpr xyz_pos_t ProbeTempComp::park_point; -constexpr xy_pos_t ProbeTempComp::measure_point; -constexpr celsius_t ProbeTempComp::probe_calib_bed_temp; +constexpr temp_calib_t ProbeTempComp::cali_info[TSI_COUNT]; uint8_t ProbeTempComp::calib_idx; // = 0 float ProbeTempComp::init_measurement; // = 0.0 +void ProbeTempComp::reset() { + TERN_(PTC_PROBE, LOOP_L_N(i, PTC_PROBE_COUNT) z_offsets_probe[i] = z_offsets_probe_default[i]); + TERN_(PTC_BED, LOOP_L_N(i, PTC_BED_COUNT) z_offsets_bed[i] = z_offsets_bed_default[i]); + TERN_(PTC_HOTEND, LOOP_L_N(i, PTC_HOTEND_COUNT) z_offsets_hotend[i] = z_offsets_hotend_default[i]); +} + void ProbeTempComp::clear_offsets(const TempSensorID tsi) { LOOP_L_N(i, cali_info[tsi].measurements) sensor_z_offsets[tsi][i] = 0; @@ -71,11 +85,10 @@ void ProbeTempComp::print_offsets() { LOOP_L_N(s, TSI_COUNT) { celsius_t temp = cali_info[s].start_temp; for (int16_t i = -1; i < cali_info[s].measurements; ++i) { - SERIAL_ECHOPGM_P(s == TSI_BED ? PSTR("Bed") : - #if ENABLED(USE_TEMP_EXT_COMPENSATION) - s == TSI_EXT ? PSTR("Extruder") : - #endif - PSTR("Probe") + SERIAL_ECHOF( + TERN_(PTC_BED, s == TSI_BED ? F("Bed") :) + TERN_(PTC_HOTEND, s == TSI_EXT ? F("Extruder") :) + F("Probe") ); SERIAL_ECHOLNPGM( " temp: ", temp, @@ -100,21 +113,13 @@ void ProbeTempComp::prepare_new_calibration(const_float_t init_meas_z) { } void ProbeTempComp::push_back_new_measurement(const TempSensorID tsi, const_float_t meas_z) { - switch (tsi) { - case TSI_PROBE: - case TSI_BED: - //case TSI_EXT: - if (calib_idx >= cali_info[tsi].measurements) return; - sensor_z_offsets[tsi][calib_idx++] = static_cast(meas_z * 1000.0f - init_measurement * 1000.0f); - default: break; - } + if (calib_idx >= cali_info[tsi].measurements) return; + sensor_z_offsets[tsi][calib_idx++] = static_cast((meas_z - init_measurement) * 1000.0f); } bool ProbeTempComp::finish_calibration(const TempSensorID tsi) { - if (tsi != TSI_PROBE && tsi != TSI_BED) return false; - - if (calib_idx < 3) { - SERIAL_ECHOLNPGM("!Insufficient measurements (min. 3)."); + if (!calib_idx) { + SERIAL_ECHOLNPGM("!No measurements."); clear_offsets(tsi); return false; } @@ -130,16 +135,15 @@ bool ProbeTempComp::finish_calibration(const TempSensorID tsi) { SERIAL_ECHOLNPGM("Got ", calib_idx, " measurements. "); if (linear_regression(tsi, k, d)) { SERIAL_ECHOPGM("Applying linear extrapolation"); - calib_idx--; for (; calib_idx < measurements; ++calib_idx) { - const celsius_float_t temp = start_temp + float(calib_idx) * res_temp; + const celsius_float_t temp = start_temp + float(calib_idx + 1) * res_temp; data[calib_idx] = static_cast(k * temp + d); } } else { // Simply use the last measured value for higher temperatures SERIAL_ECHOPGM("Failed to extrapolate"); - const int16_t last_val = data[calib_idx]; + const int16_t last_val = data[calib_idx-1]; for (; calib_idx < measurements; ++calib_idx) data[calib_idx] = last_val; } @@ -157,7 +161,7 @@ bool ProbeTempComp::finish_calibration(const TempSensorID tsi) { // Restrict the max. offset difference between two probings if (calib_idx > 0 && ABS(data[calib_idx - 1] - data[calib_idx]) > 800) { SERIAL_ECHOLNPGM("!Invalid Z-offset between two probings detected (0-0.8)."); - clear_offsets(TSI_PROBE); + clear_offsets(tsi); return false; } } @@ -168,8 +172,8 @@ bool ProbeTempComp::finish_calibration(const TempSensorID tsi) { void ProbeTempComp::compensate_measurement(const TempSensorID tsi, const celsius_t temp, float &meas_z) { const uint8_t measurements = cali_info[tsi].measurements; const celsius_t start_temp = cali_info[tsi].start_temp, - end_temp = cali_info[tsi].end_temp, - res_temp = cali_info[tsi].temp_resolution; + res_temp = cali_info[tsi].temp_resolution, + end_temp = start_temp + measurements * res_temp; const int16_t * const data = sensor_z_offsets[tsi]; // Given a data index, return { celsius, zoffset } in the form { x, y } @@ -208,9 +212,7 @@ void ProbeTempComp::compensate_measurement(const TempSensorID tsi, const celsius } bool ProbeTempComp::linear_regression(const TempSensorID tsi, float &k, float &d) { - if (tsi != TSI_PROBE && tsi != TSI_BED) return false; - - if (!WITHIN(calib_idx, 2, cali_info[tsi].measurements)) return false; + if (!WITHIN(calib_idx, 1, cali_info[tsi].measurements)) return false; const celsius_t start_temp = cali_info[tsi].start_temp, res_temp = cali_info[tsi].temp_resolution; @@ -243,4 +245,4 @@ bool ProbeTempComp::linear_regression(const TempSensorID tsi, float &k, float &d return true; } -#endif // PROBE_TEMP_COMPENSATION +#endif // HAS_PTC diff --git a/Marlin/src/feature/probe_temp_comp.h b/Marlin/src/feature/probe_temp_comp.h index f24b9acd9b..4579f2187c 100644 --- a/Marlin/src/feature/probe_temp_comp.h +++ b/Marlin/src/feature/probe_temp_comp.h @@ -24,9 +24,13 @@ #include "../inc/MarlinConfig.h" enum TempSensorID : uint8_t { - TSI_PROBE, - TSI_BED, - #if ENABLED(USE_TEMP_EXT_COMPENSATION) + #if ENABLED(PTC_PROBE) + TSI_PROBE, + #endif + #if ENABLED(PTC_BED) + TSI_BED, + #endif + #if ENABLED(PTC_HOTEND) TSI_EXT, #endif TSI_COUNT @@ -35,8 +39,7 @@ enum TempSensorID : uint8_t { typedef struct { uint8_t measurements; // Max. number of measurements to be stored (35 - 80°C) celsius_t temp_resolution, // Resolution in °C between measurements - start_temp, // Base measurement; z-offset == 0 - end_temp; + start_temp; // Base measurement; z-offset == 0 } temp_calib_t; /** @@ -45,79 +48,40 @@ typedef struct { * measurement errors/shifts due to changed temperature. */ -// Probe temperature calibration constants -#ifndef PTC_SAMPLE_COUNT - #define PTC_SAMPLE_COUNT 10 -#endif -#ifndef PTC_SAMPLE_RES - #define PTC_SAMPLE_RES 5 -#endif -#ifndef PTC_SAMPLE_START - #define PTC_SAMPLE_START 30 -#endif -#define PTC_SAMPLE_END (PTC_SAMPLE_START + (PTC_SAMPLE_COUNT) * PTC_SAMPLE_RES) - -// Bed temperature calibration constants -#ifndef BTC_PROBE_TEMP - #define BTC_PROBE_TEMP 30 -#endif -#ifndef BTC_SAMPLE_COUNT - #define BTC_SAMPLE_COUNT 10 -#endif -#ifndef BTC_SAMPLE_RES - #define BTC_SAMPLE_RES 5 -#endif -#ifndef BTC_SAMPLE_START - #define BTC_SAMPLE_START 60 -#endif -#define BTC_SAMPLE_END (BTC_SAMPLE_START + (BTC_SAMPLE_COUNT) * BTC_SAMPLE_RES) - -#ifndef PTC_PROBE_HEATING_OFFSET - #define PTC_PROBE_HEATING_OFFSET 0.5f -#endif - -#ifndef PTC_PROBE_RAISE - #define PTC_PROBE_RAISE 10 -#endif - -static constexpr temp_calib_t cali_info_init[TSI_COUNT] = { - { PTC_SAMPLE_COUNT, PTC_SAMPLE_RES, PTC_SAMPLE_START, PTC_SAMPLE_END }, // Probe - { BTC_SAMPLE_COUNT, BTC_SAMPLE_RES, BTC_SAMPLE_START, BTC_SAMPLE_END }, // Bed - #if ENABLED(USE_TEMP_EXT_COMPENSATION) - { 20, 5, 180, 180 + 5 * 20 } // Extruder - #endif -}; - class ProbeTempComp { public: - static const temp_calib_t cali_info[TSI_COUNT]; - - // Where to park nozzle to wait for probe cooldown - static constexpr xyz_pos_t park_point = PTC_PARK_POS; - - // XY coordinates of nozzle for probing the bed - static constexpr xy_pos_t measure_point = PTC_PROBE_POS; // Coordinates to probe - //measure_point = { 12.0f, 7.3f }; // Coordinates for the MK52 magnetic heatbed - - static constexpr celsius_t probe_calib_bed_temp = BED_MAX_TARGET, // Bed temperature while calibrating probe - bed_calib_probe_temp = BTC_PROBE_TEMP; // Probe temperature while calibrating bed - - static int16_t *sensor_z_offsets[TSI_COUNT], - z_offsets_probe[cali_info_init[TSI_PROBE].measurements], // (µm) - z_offsets_bed[cali_info_init[TSI_BED].measurements]; // (µm) - - #if ENABLED(USE_TEMP_EXT_COMPENSATION) - static int16_t z_offsets_ext[cali_info_init[TSI_EXT].measurements]; // (µm) + static constexpr temp_calib_t cali_info[TSI_COUNT] = { + #if ENABLED(PTC_PROBE) + { PTC_PROBE_COUNT, PTC_PROBE_RES, PTC_PROBE_START }, // Probe + #endif + #if ENABLED(PTC_BED) + { PTC_BED_COUNT, PTC_BED_RES, PTC_BED_START }, // Bed + #endif + #if ENABLED(PTC_HOTEND) + { PTC_HOTEND_COUNT, PTC_HOTEND_RES, PTC_HOTEND_START }, // Extruder + #endif + }; + + static int16_t *sensor_z_offsets[TSI_COUNT]; + #if ENABLED(PTC_PROBE) + static int16_t z_offsets_probe[PTC_PROBE_COUNT]; // (µm) + #endif + #if ENABLED(PTC_BED) + static int16_t z_offsets_bed[PTC_BED_COUNT]; // (µm) + #endif + #if ENABLED(PTC_HOTEND) + static int16_t z_offsets_hotend[PTC_HOTEND_COUNT]; // (µm) #endif static inline void reset_index() { calib_idx = 0; }; static inline uint8_t get_index() { return calib_idx; } + static void reset(); static void clear_offsets(const TempSensorID tsi); static inline void clear_all_offsets() { - clear_offsets(TSI_BED); - clear_offsets(TSI_PROBE); - TERN_(USE_TEMP_EXT_COMPENSATION, clear_offsets(TSI_EXT)); + TERN_(PTC_PROBE, clear_offsets(TSI_PROBE)); + TERN_(PTC_BED, clear_offsets(TSI_BED)); + TERN_(PTC_HOTEND, clear_offsets(TSI_EXT)); } static bool set_offset(const TempSensorID tsi, const uint8_t idx, const int16_t offset); static void print_offsets(); @@ -142,4 +106,4 @@ class ProbeTempComp { static bool linear_regression(const TempSensorID tsi, float &k, float &d); }; -extern ProbeTempComp temp_comp; +extern ProbeTempComp ptc; diff --git a/Marlin/src/feature/runout.cpp b/Marlin/src/feature/runout.cpp index 1c56378359..9317e3489a 100644 --- a/Marlin/src/feature/runout.cpp +++ b/Marlin/src/feature/runout.cpp @@ -96,8 +96,7 @@ void event_filament_runout(const uint8_t extruder) { //action:out_of_filament #if ENABLED(HOST_PROMPT_SUPPORT) - host_action_prompt_begin(PROMPT_FILAMENT_RUNOUT, PSTR("FilamentRunout T"), tool); - host_action_prompt_show(); + hostui.prompt_do(PROMPT_FILAMENT_RUNOUT, F("FilamentRunout T"), tool); //action:out_of_filament #endif const bool run_runout_script = !runout.host_handling; @@ -109,18 +108,18 @@ void event_filament_runout(const uint8_t extruder) { || TERN0(ADVANCED_PAUSE_FEATURE, strstr(FILAMENT_RUNOUT_SCRIPT, "M25")) ) ) { - host_action_paused(false); + hostui.paused(false); } else { // Legacy Repetier command for use until newer version supports standard dialog // To be removed later when pause command also triggers dialog #ifdef ACTION_ON_FILAMENT_RUNOUT - host_action(PSTR(ACTION_ON_FILAMENT_RUNOUT " T"), false); + hostui.action(F(ACTION_ON_FILAMENT_RUNOUT " T"), false); SERIAL_CHAR(tool); SERIAL_EOL(); #endif - host_action_pause(false); + hostui.pause(false); } SERIAL_ECHOPGM(" " ACTION_REASON_ON_FILAMENT_RUNOUT " "); SERIAL_CHAR(tool); @@ -140,7 +139,7 @@ void event_filament_runout(const uint8_t extruder) { SERIAL_ECHOPGM("Runout Command: "); SERIAL_ECHOLNPGM(FILAMENT_RUNOUT_SCRIPT); #endif - queue.inject_P(PSTR(FILAMENT_RUNOUT_SCRIPT)); + queue.inject(F(FILAMENT_RUNOUT_SCRIPT)); #endif } } diff --git a/Marlin/src/feature/runout.h b/Marlin/src/feature/runout.h index 918e65bb22..8065e51555 100644 --- a/Marlin/src/feature/runout.h +++ b/Marlin/src/feature/runout.h @@ -317,7 +317,7 @@ class FilamentSensorBase { static uint8_t was_out; // = 0 if (out != TEST(was_out, s)) { TBI(was_out, s); - SERIAL_ECHOLNPGM_P(PSTR("Filament Sensor "), '0' + s, out ? PSTR(" OUT") : PSTR(" IN")); + SERIAL_ECHOLNF(F("Filament Sensor "), AS_DIGIT(s), out ? F(" OUT") : F(" IN")); } #endif } @@ -352,7 +352,7 @@ class FilamentSensorBase { if (ELAPSED(ms, t)) { t = millis() + 1000UL; LOOP_L_N(i, NUM_RUNOUT_SENSORS) - SERIAL_ECHOPGM_P(i ? PSTR(", ") : PSTR("Remaining mm: "), runout_mm_countdown[i]); + SERIAL_ECHOF(i ? F(", ") : F("Remaining mm: "), runout_mm_countdown[i]); SERIAL_EOL(); } #endif diff --git a/Marlin/src/feature/spindle_laser.cpp b/Marlin/src/feature/spindle_laser.cpp index ea6fc4990e..cde2b47d90 100644 --- a/Marlin/src/feature/spindle_laser.cpp +++ b/Marlin/src/feature/spindle_laser.cpp @@ -62,11 +62,11 @@ void SpindleLaser::init() { OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off #endif #if ENABLED(SPINDLE_CHANGE_DIR) - OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR ? 255 : 0); // Init rotation to clockwise (M3) + OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR); // Init rotation to clockwise (M3) #endif #if ENABLED(SPINDLE_LASER_USE_PWM) SET_PWM(SPINDLE_LASER_PWM_PIN); - analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed + set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed #endif #if ENABLED(HAL_CAN_SET_PWM_FREQ) && defined(SPINDLE_LASER_FREQUENCY) set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY); @@ -92,10 +92,8 @@ void SpindleLaser::init() { void SpindleLaser::_set_ocr(const uint8_t ocr) { #if NEEDS_HARDWARE_PWM && SPINDLE_LASER_FREQUENCY set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), TERN(MARLIN_DEV_MODE, frequency, SPINDLE_LASER_FREQUENCY)); - set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF); - #else - analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF); #endif + set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF); } void SpindleLaser::set_ocr(const uint8_t ocr) { diff --git a/Marlin/src/feature/spindle_laser.h b/Marlin/src/feature/spindle_laser.h index ba82c4d731..95d60ae486 100644 --- a/Marlin/src/feature/spindle_laser.h +++ b/Marlin/src/feature/spindle_laser.h @@ -41,18 +41,10 @@ #define PCT_TO_PWM(X) ((X) * 255 / 100) #define PCT_TO_SERVO(X) ((X) * 180 / 100) -#ifndef SPEED_POWER_INTERCEPT - #define SPEED_POWER_INTERCEPT 0 -#endif - // #define _MAP(N,S1,S2,D1,D2) ((N)*_MAX((D2)-(D1),0)/_MAX((S2)-(S1),1)+(D1)) class SpindleLaser { public: - static constexpr float - min_pct = TERN(CUTTER_POWER_RELATIVE, 0, TERN(SPINDLE_FEATURE, round(100.0f * (SPEED_POWER_MIN) / (SPEED_POWER_MAX)), SPEED_POWER_MIN)), - max_pct = TERN(SPINDLE_FEATURE, 100, SPEED_POWER_MAX); - static const inline uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); } // cpower = configured values (e.g., SPEED_POWER_MAX) @@ -158,6 +150,9 @@ public: } static inline cutter_power_t power_to_range(const cutter_power_t pwr, const uint8_t pwrUnit) { + static constexpr float + min_pct = TERN(CUTTER_POWER_RELATIVE, 0, TERN(SPINDLE_FEATURE, round(100.0f * (SPEED_POWER_MIN) / (SPEED_POWER_MAX)), SPEED_POWER_MIN)), + max_pct = TERN(SPINDLE_FEATURE, 100, SPEED_POWER_MAX); if (pwr <= 0) return 0; cutter_power_t upwr; switch (pwrUnit) { @@ -186,6 +181,7 @@ public: } return upwr; } + #endif // SPINDLE_LASER_USE_PWM /** diff --git a/Marlin/src/feature/spindle_laser_types.h b/Marlin/src/feature/spindle_laser_types.h index 0075e54819..d249a20e75 100644 --- a/Marlin/src/feature/spindle_laser_types.h +++ b/Marlin/src/feature/spindle_laser_types.h @@ -28,12 +28,34 @@ #include "../inc/MarlinConfigPre.h" +#define MSG_CUTTER(M) _MSG_CUTTER(M) + +#ifndef SPEED_POWER_INTERCEPT + #define SPEED_POWER_INTERCEPT 0 +#endif #if ENABLED(SPINDLE_FEATURE) #define _MSG_CUTTER(M) MSG_SPINDLE_##M + #ifndef SPEED_POWER_MIN + #define SPEED_POWER_MIN 5000 + #endif + #ifndef SPEED_POWER_MAX + #define SPEED_POWER_MAX 30000 + #endif + #ifndef SPEED_POWER_STARTUP + #define SPEED_POWER_STARTUP 25000 + #endif #else #define _MSG_CUTTER(M) MSG_LASER_##M + #ifndef SPEED_POWER_MIN + #define SPEED_POWER_MIN 0 + #endif + #ifndef SPEED_POWER_MAX + #define SPEED_POWER_MAX 255 + #endif + #ifndef SPEED_POWER_STARTUP + #define SPEED_POWER_STARTUP 255 + #endif #endif -#define MSG_CUTTER(M) _MSG_CUTTER(M) typedef IF<(SPEED_POWER_MAX > 255), uint16_t, uint8_t>::type cutter_cpower_t; diff --git a/Marlin/src/feature/stepper_driver_safety.cpp b/Marlin/src/feature/stepper_driver_safety.cpp index c7da5d2ff7..11b90954b4 100644 --- a/Marlin/src/feature/stepper_driver_safety.cpp +++ b/Marlin/src/feature/stepper_driver_safety.cpp @@ -28,11 +28,11 @@ static uint32_t axis_plug_backward = 0; -void stepper_driver_backward_error(PGM_P str) { +void stepper_driver_backward_error(FSTR_P const fstr) { SERIAL_ERROR_START(); - SERIAL_ECHOPGM_P(str); + SERIAL_ECHOF(fstr); SERIAL_ECHOLNPGM(" driver is backward!"); - ui.status_printf_P(2, PSTR(S_FMT S_FMT), str, GET_TEXT(MSG_DRIVER_BACKWARD)); + ui.status_printf(2, F(S_FMT S_FMT), FTOP(fstr), GET_TEXT(MSG_DRIVER_BACKWARD)); } void stepper_driver_backward_check() { @@ -45,7 +45,7 @@ void stepper_driver_backward_check() { delay(20); \ if (READ(AXIS##_ENABLE_PIN) == false) { \ SBI(axis_plug_backward, BIT); \ - stepper_driver_backward_error(PSTR(STRINGIFY(AXIS))); \ + stepper_driver_backward_error(F(STRINGIFY(AXIS))); \ } \ }while(0) @@ -82,12 +82,12 @@ void stepper_driver_backward_check() { void stepper_driver_backward_report() { if (!axis_plug_backward) return; - auto _report_if_backward = [](PGM_P axis, uint8_t bit) { + auto _report_if_backward = [](FSTR_P const axis, uint8_t bit) { if (TEST(axis_plug_backward, bit)) stepper_driver_backward_error(axis); }; - #define REPORT_BACKWARD(axis, bit) TERN_(HAS_##axis##_ENABLE, _report_if_backward(PSTR(STRINGIFY(axis)), bit)) + #define REPORT_BACKWARD(axis, bit) TERN_(HAS_##axis##_ENABLE, _report_if_backward(F(STRINGIFY(axis)), bit)) REPORT_BACKWARD(X, 0); REPORT_BACKWARD(X2, 1); diff --git a/Marlin/src/feature/tmc_util.cpp b/Marlin/src/feature/tmc_util.cpp index 97fedf13c5..82c10e6e8e 100644 --- a/Marlin/src/feature/tmc_util.cpp +++ b/Marlin/src/feature/tmc_util.cpp @@ -212,7 +212,7 @@ if (data.is_ot) SERIAL_ECHOLNPGM("overtemperature"); if (data.is_s2g) SERIAL_ECHOLNPGM("coil short circuit"); TERN_(TMC_DEBUG, tmc_report_all()); - kill(PSTR("Driver error")); + kill(F("Driver error")); } #endif @@ -561,7 +561,7 @@ }; template - static void print_vsense(TMC &st) { SERIAL_ECHOPGM_P(st.vsense() ? PSTR("1=.18") : PSTR("0=.325")); } + static void print_vsense(TMC &st) { SERIAL_ECHOF(st.vsense() ? F("1=.18") : F("0=.325")); } #if HAS_DRIVER(TMC2130) || HAS_DRIVER(TMC5130) static void _tmc_status(TMC2130Stepper &st, const TMC_debug_enum i) { @@ -732,7 +732,7 @@ SERIAL_ECHO(st.cs()); SERIAL_ECHOPGM("/31"); break; - case TMC_VSENSE: SERIAL_ECHOPGM_P(st.vsense() ? PSTR("1=.165") : PSTR("0=.310")); break; + case TMC_VSENSE: SERIAL_ECHOF(st.vsense() ? F("1=.165") : F("0=.310")); break; case TMC_MICROSTEPS: SERIAL_ECHO(st.microsteps()); break; //case TMC_OTPW: serialprint_truefalse(st.otpw()); break; //case TMC_OTPW_TRIGGERED: serialprint_truefalse(st.getOTPW()); break; @@ -1256,15 +1256,14 @@ static bool test_connection(TMC &st) { if (test_result > 0) SERIAL_ECHOPGM("Error: All "); - const char *stat; + FSTR_P stat; switch (test_result) { default: - case 0: stat = PSTR("OK"); break; - case 1: stat = PSTR("HIGH"); break; - case 2: stat = PSTR("LOW"); break; + case 0: stat = F("OK"); break; + case 1: stat = F("HIGH"); break; + case 2: stat = F("LOW"); break; } - SERIAL_ECHOPGM_P(stat); - SERIAL_EOL(); + SERIAL_ECHOLNF(stat); return test_result; } @@ -1342,7 +1341,7 @@ void test_tmc_connection(LOGICAL_AXIS_ARGS(const bool)) { #endif } - if (axis_connection) LCD_MESSAGEPGM(MSG_ERROR_TMC); + if (axis_connection) LCD_MESSAGE(MSG_ERROR_TMC); } #endif // HAS_TRINAMIC_CONFIG diff --git a/Marlin/src/feature/twibus.cpp b/Marlin/src/feature/twibus.cpp index 5f5209cdd4..9aec6b0305 100644 --- a/Marlin/src/feature/twibus.cpp +++ b/Marlin/src/feature/twibus.cpp @@ -28,13 +28,24 @@ #include +#include "../libs/hex_print.h" + TWIBus i2c; TWIBus::TWIBus() { #if I2C_SLAVE_ADDRESS == 0 - Wire.begin(); // No address joins the BUS as the master + + #if PINS_EXIST(I2C_SCL, I2C_SDA) && DISABLED(SOFT_I2C_EEPROM) + Wire.setSDA(pin_t(I2C_SDA_PIN)); + Wire.setSCL(pin_t(I2C_SCL_PIN)); + #endif + + Wire.begin(); // No address joins the BUS as the master + #else - Wire.begin(I2C_SLAVE_ADDRESS); // Join the bus as a slave + + Wire.begin(I2C_SLAVE_ADDRESS); // Join the bus as a slave + #endif reset(); } @@ -45,33 +56,32 @@ void TWIBus::reset() { } void TWIBus::address(const uint8_t adr) { - if (!WITHIN(adr, 8, 127)) { + if (!WITHIN(adr, 8, 127)) SERIAL_ECHO_MSG("Bad I2C address (8-127)"); - } addr = adr; - debug(PSTR("address"), adr); + debug(F("address"), adr); } void TWIBus::addbyte(const char c) { if (buffer_s >= COUNT(buffer)) return; buffer[buffer_s++] = c; - debug(PSTR("addbyte"), c); + debug(F("addbyte"), c); } void TWIBus::addbytes(char src[], uint8_t bytes) { - debug(PSTR("addbytes"), bytes); + debug(F("addbytes"), bytes); while (bytes--) addbyte(*src++); } void TWIBus::addstring(char str[]) { - debug(PSTR("addstring"), str); + debug(F("addstring"), str); while (char c = *str++) addbyte(c); } void TWIBus::send() { - debug(PSTR("send"), addr); + debug(F("send"), addr); Wire.beginTransmission(I2C_ADDRESS(addr)); Wire.write(buffer, buffer_s); @@ -81,21 +91,60 @@ void TWIBus::send() { } // static -void TWIBus::echoprefix(uint8_t bytes, const char pref[], uint8_t adr) { +void TWIBus::echoprefix(uint8_t bytes, FSTR_P const pref, uint8_t adr) { SERIAL_ECHO_START(); - SERIAL_ECHOPGM_P(pref); + SERIAL_ECHOF(pref); SERIAL_ECHOPGM(": from:", adr, " bytes:", bytes, " data:"); } // static -void TWIBus::echodata(uint8_t bytes, const char pref[], uint8_t adr) { +void TWIBus::echodata(uint8_t bytes, FSTR_P const pref, uint8_t adr, const uint8_t style/*=0*/) { + union TwoBytesToInt16 { uint8_t bytes[2]; int16_t integervalue; }; + TwoBytesToInt16 ConversionUnion; + echoprefix(bytes, pref, adr); - while (bytes-- && Wire.available()) SERIAL_CHAR(Wire.read()); + + while (bytes-- && Wire.available()) { + int value = Wire.read(); + switch (style) { + + // Style 1, HEX DUMP + case 1: + SERIAL_CHAR(hex_nybble((value & 0xF0) >> 4)); + SERIAL_CHAR(hex_nybble(value & 0x0F)); + if (bytes) SERIAL_CHAR(' '); + break; + + // Style 2, signed two byte integer (int16) + case 2: + if (bytes == 1) + ConversionUnion.bytes[1] = (uint8_t)value; + else if (bytes == 0) { + ConversionUnion.bytes[0] = (uint8_t)value; + // Output value in base 10 (standard decimal) + SERIAL_ECHO(ConversionUnion.integervalue); + } + break; + + // Style 3, unsigned byte, base 10 (uint8) + case 3: + SERIAL_ECHO(value); + if (bytes) SERIAL_CHAR(' '); + break; + + // Default style (zero), raw serial output + default: + // This can cause issues with some serial consoles, Pronterface is an example where things go wrong + SERIAL_CHAR(value); + break; + } + } + SERIAL_EOL(); } -void TWIBus::echobuffer(const char pref[], uint8_t adr) { - echoprefix(buffer_s, pref, adr); +void TWIBus::echobuffer(FSTR_P const prefix, uint8_t adr) { + echoprefix(buffer_s, prefix, adr); LOOP_L_N(i, buffer_s) SERIAL_CHAR(buffer[i]); SERIAL_EOL(); } @@ -103,22 +152,22 @@ void TWIBus::echobuffer(const char pref[], uint8_t adr) { bool TWIBus::request(const uint8_t bytes) { if (!addr) return false; - debug(PSTR("request"), bytes); + debug(F("request"), bytes); // requestFrom() is a blocking function if (Wire.requestFrom(I2C_ADDRESS(addr), bytes) == 0) { - debug("request fail", I2C_ADDRESS(addr)); + debug(F("request fail"), I2C_ADDRESS(addr)); return false; } return true; } -void TWIBus::relay(const uint8_t bytes) { - debug(PSTR("relay"), bytes); +void TWIBus::relay(const uint8_t bytes, const uint8_t style/*=0*/) { + debug(F("relay"), bytes); if (request(bytes)) - echodata(bytes, PSTR("i2c-reply"), addr); + echodata(bytes, F("i2c-reply"), addr, style); } uint8_t TWIBus::capture(char *dst, const uint8_t bytes) { @@ -127,7 +176,7 @@ uint8_t TWIBus::capture(char *dst, const uint8_t bytes) { while (count < bytes && Wire.available()) dst[count++] = Wire.read(); - debug(PSTR("capture"), count); + debug(F("capture"), count); return count; } @@ -140,12 +189,12 @@ void TWIBus::flush() { #if I2C_SLAVE_ADDRESS > 0 void TWIBus::receive(uint8_t bytes) { - debug(PSTR("receive"), bytes); - echodata(bytes, PSTR("i2c-receive"), 0); + debug(F("receive"), bytes); + echodata(bytes, F("i2c-receive"), 0); } void TWIBus::reply(char str[]/*=nullptr*/) { - debug(PSTR("reply"), str); + debug(F("reply"), str); if (str) { reset(); @@ -170,18 +219,16 @@ void TWIBus::flush() { #if ENABLED(DEBUG_TWIBUS) // static - void TWIBus::prefix(const char func[]) { - SERIAL_ECHOPGM("TWIBus::"); - SERIAL_ECHOPGM_P(func); - SERIAL_ECHOPGM(": "); + void TWIBus::prefix(FSTR_P const func) { + SERIAL_ECHOPGM("TWIBus::", func, ": "); } - void TWIBus::debug(const char func[], uint32_t adr) { + void TWIBus::debug(FSTR_P const func, uint32_t adr) { if (DEBUGGING(INFO)) { prefix(func); SERIAL_ECHOLN(adr); } } - void TWIBus::debug(const char func[], char c) { + void TWIBus::debug(FSTR_P const func, char c) { if (DEBUGGING(INFO)) { prefix(func); SERIAL_ECHOLN(c); } } - void TWIBus::debug(const char func[], char str[]) { + void TWIBus::debug(FSTR_P const func, char str[]) { if (DEBUGGING(INFO)) { prefix(func); SERIAL_ECHOLN(str); } } diff --git a/Marlin/src/feature/twibus.h b/Marlin/src/feature/twibus.h index 5939153482..d2c7270303 100644 --- a/Marlin/src/feature/twibus.h +++ b/Marlin/src/feature/twibus.h @@ -142,7 +142,7 @@ class TWIBus { * * @param bytes the number of bytes to request */ - static void echoprefix(uint8_t bytes, const char prefix[], uint8_t adr); + static void echoprefix(uint8_t bytes, FSTR_P const prefix, uint8_t adr); /** * @brief Echo data on the bus to serial @@ -150,8 +150,9 @@ class TWIBus { * to serial in a parser-friendly format. * * @param bytes the number of bytes to request + * @param style Output format for the bytes, 0 = Raw byte [default], 1 = Hex characters, 2 = uint16_t */ - static void echodata(uint8_t bytes, const char prefix[], uint8_t adr); + static void echodata(uint8_t bytes, FSTR_P const prefix, uint8_t adr, const uint8_t style=0); /** * @brief Echo data in the buffer to serial @@ -160,7 +161,7 @@ class TWIBus { * * @param bytes the number of bytes to request */ - void echobuffer(const char prefix[], uint8_t adr); + void echobuffer(FSTR_P const prefix, uint8_t adr); /** * @brief Request data from the slave device and wait. @@ -192,10 +193,11 @@ class TWIBus { * @brief Request data from the slave device, echo to serial. * @details Request a number of bytes from a slave device and output * the returned data to serial in a parser-friendly format. + * @style Output format for the bytes, 0 = raw byte [default], 1 = Hex characters, 2 = uint16_t * * @param bytes the number of bytes to request */ - void relay(const uint8_t bytes); + void relay(const uint8_t bytes, const uint8_t style=0); #if I2C_SLAVE_ADDRESS > 0 @@ -237,17 +239,16 @@ class TWIBus { * @brief Prints a debug message * @details Prints a simple debug message "TWIBus::function: value" */ - static void prefix(const char func[]); - static void debug(const char func[], uint32_t adr); - static void debug(const char func[], char c); - static void debug(const char func[], char adr[]); - static inline void debug(const char func[], uint8_t v) { debug(func, (uint32_t)v); } + static void prefix(FSTR_P const func); + static void debug(FSTR_P const func, uint32_t adr); + static void debug(FSTR_P const func, char c); + static void debug(FSTR_P const func, char adr[]); #else - static inline void debug(const char[], uint32_t) {} - static inline void debug(const char[], char) {} - static inline void debug(const char[], char[]) {} - static inline void debug(const char[], uint8_t) {} + static inline void debug(FSTR_P const, uint32_t) {} + static inline void debug(FSTR_P const, char) {} + static inline void debug(FSTR_P const, char[]) {} #endif + static inline void debug(FSTR_P const func, uint8_t v) { debug(func, (uint32_t)v); } }; extern TWIBus i2c; diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index ba14e6f0b4..728771d580 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -163,7 +163,7 @@ float g26_random_deviation = 0.0; */ bool user_canceled() { if (!ui.button_pressed()) return false; // Return if the button isn't pressed - ui.set_status_P(GET_TEXT(MSG_G26_CANCELED), 99); + ui.set_status(GET_TEXT_F(MSG_G26_CANCELED), 99); TERN_(HAS_LCD_MENU, ui.quick_feedback()); ui.wait_for_release(); return true; @@ -323,7 +323,7 @@ typedef struct { if (bed_temp > 25) { #if HAS_WIRED_LCD - ui.set_status_P(GET_TEXT(MSG_G26_HEATING_BED), 99); + ui.set_status(GET_TEXT_F(MSG_G26_HEATING_BED), 99); ui.quick_feedback(); TERN_(HAS_LCD_MENU, ui.capture()); #endif @@ -342,7 +342,7 @@ typedef struct { // Start heating the active nozzle #if HAS_WIRED_LCD - ui.set_status_P(GET_TEXT(MSG_G26_HEATING_NOZZLE), 99); + ui.set_status(GET_TEXT_F(MSG_G26_HEATING_NOZZLE), 99); ui.quick_feedback(); #endif thermalManager.setTargetHotend(hotend_temp, active_extruder); @@ -372,7 +372,7 @@ typedef struct { if (prime_flag == -1) { // The user wants to control how much filament gets purged ui.capture(); - ui.set_status_P(GET_TEXT(MSG_G26_MANUAL_PRIME), 99); + ui.set_status(GET_TEXT_F(MSG_G26_MANUAL_PRIME), 99); ui.chirp(); destination = current_position; @@ -399,7 +399,7 @@ typedef struct { ui.wait_for_release(); - ui.set_status_P(GET_TEXT(MSG_G26_PRIME_DONE), 99); + ui.set_status(GET_TEXT_F(MSG_G26_PRIME_DONE), 99); ui.quick_feedback(); ui.release(); } @@ -407,7 +407,7 @@ typedef struct { #endif { #if HAS_WIRED_LCD - ui.set_status_P(GET_TEXT(MSG_G26_FIXED_LENGTH), 99); + ui.set_status(GET_TEXT_F(MSG_G26_FIXED_LENGTH), 99); ui.quick_feedback(); #endif destination = current_position; @@ -520,7 +520,7 @@ void GcodeSuite::G26() { g26.keep_heaters_on = parser.boolval('K'); // Accept 'I' if temperature presets are defined - #if PREHEAT_COUNT + #if HAS_PREHEAT const uint8_t preset_index = parser.seenval('I') ? _MIN(parser.value_byte(), PREHEAT_COUNT - 1) + 1 : 0; #endif @@ -530,7 +530,7 @@ void GcodeSuite::G26() { celsius_t bedtemp = 0; // Use the 'I' index if temperature presets are defined - #if PREHEAT_COUNT + #if HAS_PREHEAT if (preset_index) bedtemp = ui.material_preset[preset_index - 1].bed_temp; #endif @@ -613,7 +613,7 @@ void GcodeSuite::G26() { celsius_t noztemp = 0; // Accept 'I' if temperature presets are defined - #if PREHEAT_COUNT + #if HAS_PREHEAT if (preset_index) noztemp = ui.material_preset[preset_index - 1].hotend_temp; #endif @@ -854,7 +854,7 @@ void GcodeSuite::G26() { } while (--g26_repeats && location.valid()); LEAVE: - ui.set_status_P(GET_TEXT(MSG_G26_LEAVING), -1); + ui.set_status(GET_TEXT_F(MSG_G26_LEAVING), -1); TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(location, ExtUI::G26_FINISH)); g26.retract_filament(destination); diff --git a/Marlin/src/gcode/bedlevel/G35.cpp b/Marlin/src/gcode/bedlevel/G35.cpp index 8d5c057361..8cabb92382 100644 --- a/Marlin/src/gcode/bedlevel/G35.cpp +++ b/Marlin/src/gcode/bedlevel/G35.cpp @@ -33,6 +33,10 @@ #include "../../module/tool_change.h" #endif +#if ENABLED(BLTOUCH) + #include "../../feature/bltouch.h" +#endif + #define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) #include "../../core/debug_out.h" @@ -92,7 +96,7 @@ void GcodeSuite::G35() { TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false)); // Home only Z axis when X and Y is trusted, otherwise all axes, if needed before this procedure - if (!all_axes_trusted()) process_subcommands_now_P(PSTR("G28Z")); + if (!all_axes_trusted()) process_subcommands_now(F("G28Z")); bool err_break = false; @@ -102,7 +106,7 @@ void GcodeSuite::G35() { // In BLTOUCH HS mode, the probe travels in a deployed state. // Users of G35 might have a badly misaligned bed, so raise Z by the // length of the deployed pin (BLTOUCH stroke < 7mm) - do_blocking_move_to_z(SUM_TERN(BLTOUCH_HS_MODE, Z_CLEARANCE_BETWEEN_PROBES, 7)); + do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES + TERN0(BLTOUCH, bltouch.z_extra_clearance())); const float z_probed_height = probe.probe_at_point(tramming_points[i], PROBE_PT_RAISE, 0, true); if (isnan(z_probed_height)) { @@ -116,7 +120,7 @@ void GcodeSuite::G35() { if (DEBUGGING(LEVELING)) { DEBUG_ECHOPGM("Probing point ", i + 1, " ("); - DEBUG_ECHOPGM_P((char *)pgm_read_ptr(&tramming_point_name[i])); + DEBUG_ECHOF(FPSTR(pgm_read_ptr(&tramming_point_name[i]))); DEBUG_CHAR(')'); DEBUG_ECHOLNPGM_P(SP_X_STR, tramming_points[i].x, SP_Y_STR, tramming_points[i].y, SP_Z_STR, z_probed_height); } diff --git a/Marlin/src/gcode/bedlevel/M420.cpp b/Marlin/src/gcode/bedlevel/M420.cpp index d76e08dee6..3c23e85a1d 100644 --- a/Marlin/src/gcode/bedlevel/M420.cpp +++ b/Marlin/src/gcode/bedlevel/M420.cpp @@ -195,7 +195,7 @@ void GcodeSuite::M420() { // V to print the matrix or mesh if (seenV) { #if ABL_PLANAR - planner.bed_level_matrix.debug(PSTR("Bed Level Correction Matrix:")); + planner.bed_level_matrix.debug(F("Bed Level Correction Matrix:")); #else if (leveling_is_valid()) { #if ENABLED(AUTO_BED_LEVELING_BILINEAR) @@ -243,15 +243,15 @@ void GcodeSuite::M420() { } void GcodeSuite::M420_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR( + report_heading_etc(forReplay, F( TERN(MESH_BED_LEVELING, "Mesh Bed Leveling", TERN(AUTO_BED_LEVELING_UBL, "Unified Bed Leveling", "Auto Bed Leveling")) )); - SERIAL_ECHOPGM_P( - PSTR(" M420 S"), planner.leveling_active + SERIAL_ECHOF( + F(" M420 S"), planner.leveling_active #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) - , SP_Z_STR, LINEAR_UNIT(planner.z_fade_height) + , FPSTR(SP_Z_STR), LINEAR_UNIT(planner.z_fade_height) #endif - , PSTR(" ; Leveling ") + , F(" ; Leveling ") ); serialprintln_onoff(planner.leveling_active); } diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index 0eb13dba96..6765ec86a6 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -36,7 +36,7 @@ #include "../../../module/probe.h" #include "../../queue.h" -#if ENABLED(PROBE_TEMP_COMPENSATION) +#if HAS_PTC #include "../../../feature/probe_temp_comp.h" #include "../../../module/temperature.h" #endif @@ -244,7 +244,7 @@ G29_TYPE GcodeSuite::G29() { // Send 'N' to force homing before G29 (internal only) if (parser.seen_test('N')) - process_subcommands_now_P(TERN(CAN_SET_LEVELING_AFTER_G28, PSTR("G28L0"), G28_STR)); + process_subcommands_now(TERN(CAN_SET_LEVELING_AFTER_G28, F("G28L0"), FPSTR(G28_STR))); // Don't allow auto-leveling without homing first if (homing_needed_error()) G29_RETURN(false); @@ -636,7 +636,7 @@ G29_TYPE GcodeSuite::G29() { if (TERN0(IS_KINEMATIC, !probe.can_reach(abl.probePos))) continue; if (abl.verbose_level) SERIAL_ECHOLNPGM("Probing mesh point ", pt_index, "/", abl.abl_points, "."); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), int(pt_index), int(abl.abl_points))); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), int(pt_index), int(abl.abl_points))); abl.measured_z = faux ? 0.001f * random(-100, 101) : probe.probe_at_point(abl.probePos, raise_after, abl.verbose_level); @@ -645,11 +645,9 @@ G29_TYPE GcodeSuite::G29() { break; // Breaks out of both loops } - #if ENABLED(PROBE_TEMP_COMPENSATION) - temp_comp.compensate_measurement(TSI_BED, thermalManager.degBed(), abl.measured_z); - temp_comp.compensate_measurement(TSI_PROBE, thermalManager.degProbe(), abl.measured_z); - TERN_(USE_TEMP_EXT_COMPENSATION, temp_comp.compensate_measurement(TSI_EXT, thermalManager.degHotend(), abl.measured_z)); - #endif + TERN_(PTC_BED, ptc.compensate_measurement(TSI_BED, thermalManager.degBed(), abl.measured_z)); + TERN_(PTC_PROBE, ptc.compensate_measurement(TSI_PROBE, thermalManager.degProbe(), abl.measured_z)); + TERN_(PTC_HOTEND, ptc.compensate_measurement(TSI_EXT, thermalManager.degHotend(0), abl.measured_z)); #if ENABLED(AUTO_BED_LEVELING_LINEAR) @@ -664,7 +662,7 @@ G29_TYPE GcodeSuite::G29() { #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) const float z = abl.measured_z + abl.Z_offset; - z_values[abl.meshCount.x][abl.meshCount.y] = z; + z_values[abl.meshCount.x][abl.meshCount.y] = z PLUS_TERN0(X_AXIS_TWIST_COMPENSATION, xatc.compensation(abl.probePos)); TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(abl.meshCount, z)); #endif @@ -681,7 +679,7 @@ G29_TYPE GcodeSuite::G29() { LOOP_L_N(i, 3) { if (abl.verbose_level) SERIAL_ECHOLNPGM("Probing point ", i + 1, "/3."); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/3"), GET_TEXT(MSG_PROBING_POINT), int(i + 1))); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/3"), GET_TEXT(MSG_PROBING_POINT), int(i + 1))); // Retain the last probe position abl.probePos = xy_pos_t(points[i]); @@ -783,8 +781,8 @@ G29_TYPE GcodeSuite::G29() { float min_diff = 999; - auto print_topo_map = [&](PGM_P const title, const bool get_min) { - SERIAL_ECHOPGM_P(title); + auto print_topo_map = [&](FSTR_P const title, const bool get_min) { + SERIAL_ECHOF(title); for (int8_t yy = abl.grid_points.y - 1; yy >= 0; yy--) { LOOP_L_N(xx, abl.grid_points.x) { const int ind = abl.indexIntoAB[xx][yy]; @@ -802,19 +800,19 @@ G29_TYPE GcodeSuite::G29() { SERIAL_EOL(); }; - print_topo_map(PSTR("\nBed Height Topography:\n" - " +--- BACK --+\n" - " | |\n" - " L | (+) | R\n" - " E | | I\n" - " F | (-) N (+) | G\n" - " T | | H\n" - " | (-) | T\n" - " | |\n" - " O-- FRONT --+\n" - " (0,0)\n"), true); + print_topo_map(F("\nBed Height Topography:\n" + " +--- BACK --+\n" + " | |\n" + " L | (+) | R\n" + " E | | I\n" + " F | (-) N (+) | G\n" + " T | | H\n" + " | (-) | T\n" + " | |\n" + " O-- FRONT --+\n" + " (0,0)\n"), true); if (abl.verbose_level > 3) - print_topo_map(PSTR("\nCorrected Bed Height vs. Bed Topology:\n"), false); + print_topo_map(F("\nCorrected Bed Height vs. Bed Topology:\n"), false); } // abl.topography_map @@ -825,7 +823,7 @@ G29_TYPE GcodeSuite::G29() { // For LINEAR and 3POINT leveling correct the current position if (abl.verbose_level > 0) - planner.bed_level_matrix.debug(PSTR("\n\nBed Level Correction Matrix:")); + planner.bed_level_matrix.debug(F("\n\nBed Level Correction Matrix:")); if (!abl.dryrun) { // @@ -882,7 +880,7 @@ G29_TYPE GcodeSuite::G29() { #ifdef Z_PROBE_END_SCRIPT if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Z Probe End Script: ", Z_PROBE_END_SCRIPT); planner.synchronize(); - process_subcommands_now_P(PSTR(Z_PROBE_END_SCRIPT)); + process_subcommands_now(F(Z_PROBE_END_SCRIPT)); #endif TERN_(HAS_DWIN_E3V2_BASIC, DWIN_CompletedLeveling()); diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp index 11e503f013..eec89f73ac 100644 --- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp @@ -103,7 +103,7 @@ void GcodeSuite::G29() { mbl.reset(); mbl_probe_index = 0; if (!ui.wait_for_move) { - queue.inject_P(parser.seen_test('N') ? PSTR("G28" TERN(CAN_SET_LEVELING_AFTER_G28, "L0", "") "\nG29S2") : PSTR("G29S2")); + queue.inject(parser.seen_test('N') ? F("G28" TERN(CAN_SET_LEVELING_AFTER_G28, "L0", "") "\nG29S2") : F("G29S2")); TERN_(EXTENSIBLE_UI, ExtUI::onMeshLevelingStart()); return; } @@ -152,7 +152,7 @@ void GcodeSuite::G29() { // After recording the last point, activate home and activate mbl_probe_index = -1; SERIAL_ECHOLNPGM("Mesh probing done."); - TERN_(HAS_STATUS_MESSAGE, ui.set_status(GET_TEXT(MSG_MESH_DONE))); + TERN_(HAS_STATUS_MESSAGE, LCD_MESSAGE(MSG_MESH_DONE)); BUZZ(100, 659); BUZZ(100, 698); @@ -214,7 +214,7 @@ void GcodeSuite::G29() { if (state == MeshNext) { SERIAL_ECHOLNPGM("MBL G29 point ", _MIN(mbl_probe_index, GRID_MAX_POINTS), " of ", GRID_MAX_POINTS); - if (mbl_probe_index > 0) TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), _MIN(mbl_probe_index, GRID_MAX_POINTS), int(GRID_MAX_POINTS))); + if (mbl_probe_index > 0) TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), _MIN(mbl_probe_index, GRID_MAX_POINTS), int(GRID_MAX_POINTS))); } report_current_position(); diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index 01c6050155..45f039c132 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -83,9 +83,7 @@ #if ENABLED(SENSORLESS_HOMING) sensorless_t stealth_states { - tmc_enable_stallguard(stepperX) - , tmc_enable_stallguard(stepperY) - , false + LINEAR_AXIS_LIST(tmc_enable_stallguard(stepperX), tmc_enable_stallguard(stepperY), false, false, false, false) , false #if AXIS_HAS_STALLGUARD(X2) || tmc_enable_stallguard(stepperX2) @@ -156,7 +154,7 @@ homeaxis(Z_AXIS); } else { - LCD_MESSAGEPGM(MSG_ZPROBE_OUT); + LCD_MESSAGE(MSG_ZPROBE_OUT); SERIAL_ECHO_MSG(STR_ZPROBE_OUT_SER); } } @@ -269,28 +267,43 @@ void GcodeSuite::G28() { #endif #if HAS_HOMING_CURRENT - auto debug_current = [](PGM_P const s, const int16_t a, const int16_t b) { - DEBUG_ECHOPGM_P(s); DEBUG_ECHOLNPGM(" current: ", a, " -> ", b); + auto debug_current = [](FSTR_P const s, const int16_t a, const int16_t b) { + DEBUG_ECHOF(s); DEBUG_ECHOLNPGM(" current: ", a, " -> ", b); }; #if HAS_CURRENT_HOME(X) const int16_t tmc_save_current_X = stepperX.getMilliamps(); stepperX.rms_current(X_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(PSTR("X"), tmc_save_current_X, X_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F("X"), tmc_save_current_X, X_CURRENT_HOME); #endif #if HAS_CURRENT_HOME(X2) const int16_t tmc_save_current_X2 = stepperX2.getMilliamps(); stepperX2.rms_current(X2_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(PSTR("X2"), tmc_save_current_X2, X2_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F("X2"), tmc_save_current_X2, X2_CURRENT_HOME); #endif #if HAS_CURRENT_HOME(Y) const int16_t tmc_save_current_Y = stepperY.getMilliamps(); stepperY.rms_current(Y_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(PSTR("Y"), tmc_save_current_Y, Y_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F("Y"), tmc_save_current_Y, Y_CURRENT_HOME); #endif #if HAS_CURRENT_HOME(Y2) const int16_t tmc_save_current_Y2 = stepperY2.getMilliamps(); stepperY2.rms_current(Y2_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(PSTR("Y2"), tmc_save_current_Y2, Y2_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F("Y2"), tmc_save_current_Y2, Y2_CURRENT_HOME); + #endif + #if HAS_CURRENT_HOME(I) + const int16_t tmc_save_current_I = stepperI.getMilliamps(); + stepperI.rms_current(I_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F(AXIS4_STR), tmc_save_current_I, I_CURRENT_HOME); + #endif + #if HAS_CURRENT_HOME(J) + const int16_t tmc_save_current_J = stepperJ.getMilliamps(); + stepperJ.rms_current(J_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F(AXIS5_STR), tmc_save_current_J, J_CURRENT_HOME); + #endif + #if HAS_CURRENT_HOME(K) + const int16_t tmc_save_current_K = stepperK.getMilliamps(); + stepperK.rms_current(K_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F(AXIS6_STR), tmc_save_current_K, K_CURRENT_HOME); #endif #if HAS_CURRENT_HOME(I) const int16_t tmc_save_current_I = stepperI.getMilliamps(); @@ -310,7 +323,7 @@ void GcodeSuite::G28() { #if HAS_CURRENT_HOME(Z) && ENABLED(DELTA) const int16_t tmc_save_current_Z = stepperZ.getMilliamps(); stepperZ.rms_current(Z_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(PSTR("Z"), tmc_save_current_Z, Z_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F("Z"), tmc_save_current_Z, Z_CURRENT_HOME); #endif #endif diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp index 24a985299f..a4b9aec01b 100644 --- a/Marlin/src/gcode/calibrate/G33.cpp +++ b/Marlin/src/gcode/calibrate/G33.cpp @@ -69,8 +69,6 @@ enum CalEnum : char { // the 7 main calibration points - float lcd_probe_pt(const xy_pos_t &xy); -float dcr; - void ac_home() { endstops.enable(true); TERN_(HAS_DELTA_SENSORLESS_PROBING, probe.set_homing_current(true)); @@ -97,10 +95,9 @@ void ac_cleanup(TERN_(HAS_MULTI_HOTEND, const uint8_t old_tool_index)) { TERN_(HAS_MULTI_HOTEND, tool_change(old_tool_index, true)); } -void print_signed_float(PGM_P const prefix, const_float_t f) { +void print_signed_float(FSTR_P const prefix, const_float_t f) { SERIAL_ECHOPGM(" "); - SERIAL_ECHOPGM_P(prefix); - SERIAL_CHAR(':'); + SERIAL_ECHOF(prefix, AS_CHAR(':')); if (f >= 0) SERIAL_CHAR('+'); SERIAL_ECHO_F(f, 2); } @@ -111,24 +108,23 @@ void print_signed_float(PGM_P const prefix, const_float_t f) { static void print_calibration_settings(const bool end_stops, const bool tower_angles) { SERIAL_ECHOPGM(".Height:", delta_height); if (end_stops) { - print_signed_float(PSTR("Ex"), delta_endstop_adj.a); - print_signed_float(PSTR("Ey"), delta_endstop_adj.b); - print_signed_float(PSTR("Ez"), delta_endstop_adj.c); + print_signed_float(F("Ex"), delta_endstop_adj.a); + print_signed_float(F("Ey"), delta_endstop_adj.b); + print_signed_float(F("Ez"), delta_endstop_adj.c); } if (end_stops && tower_angles) { - SERIAL_ECHOPGM(" Radius:", delta_radius); - SERIAL_EOL(); + SERIAL_ECHOLNPGM(" Radius:", delta_radius); SERIAL_CHAR('.'); SERIAL_ECHO_SP(13); } if (tower_angles) { - print_signed_float(PSTR("Tx"), delta_tower_angle_trim.a); - print_signed_float(PSTR("Ty"), delta_tower_angle_trim.b); - print_signed_float(PSTR("Tz"), delta_tower_angle_trim.c); + print_signed_float(F("Tx"), delta_tower_angle_trim.a); + print_signed_float(F("Ty"), delta_tower_angle_trim.b); + print_signed_float(F("Tz"), delta_tower_angle_trim.c); } - if ((!end_stops && tower_angles) || (end_stops && !tower_angles)) { // XOR + if (end_stops != tower_angles) SERIAL_ECHOPGM(" Radius:", delta_radius); - } + SERIAL_EOL(); } @@ -137,11 +133,11 @@ static void print_calibration_settings(const bool end_stops, const bool tower_an */ static void print_calibration_results(const float z_pt[NPP + 1], const bool tower_points, const bool opposite_points) { SERIAL_ECHOPGM(". "); - print_signed_float(PSTR("c"), z_pt[CEN]); + print_signed_float(F("c"), z_pt[CEN]); if (tower_points) { - print_signed_float(PSTR(" x"), z_pt[__A]); - print_signed_float(PSTR(" y"), z_pt[__B]); - print_signed_float(PSTR(" z"), z_pt[__C]); + print_signed_float(F(" x"), z_pt[__A]); + print_signed_float(F(" y"), z_pt[__B]); + print_signed_float(F(" z"), z_pt[__C]); } if (tower_points && opposite_points) { SERIAL_EOL(); @@ -149,9 +145,9 @@ static void print_calibration_results(const float z_pt[NPP + 1], const bool towe SERIAL_ECHO_SP(13); } if (opposite_points) { - print_signed_float(PSTR("yz"), z_pt[_BC]); - print_signed_float(PSTR("zx"), z_pt[_CA]); - print_signed_float(PSTR("xy"), z_pt[_AB]); + print_signed_float(F("yz"), z_pt[_BC]); + print_signed_float(F("zx"), z_pt[_CA]); + print_signed_float(F("xy"), z_pt[_AB]); } SERIAL_EOL(); } @@ -179,7 +175,7 @@ static float std_dev_points(float z_pt[NPP + 1], const bool _0p_cal, const bool */ static float calibration_probe(const xy_pos_t &xy, const bool stow, const bool probe_at_offset) { #if HAS_BED_PROBE - return probe.probe_at_point(xy, stow ? PROBE_PT_STOW : PROBE_PT_RAISE, 0, true, probe_at_offset); + return probe.probe_at_point(xy, stow ? PROBE_PT_STOW : PROBE_PT_RAISE, 0, probe_at_offset, false); #else UNUSED(stow); return lcd_probe_pt(xy); @@ -189,7 +185,7 @@ static float calibration_probe(const xy_pos_t &xy, const bool stow, const bool p /** * - Probe a grid */ -static bool probe_calibration_points(float z_pt[NPP + 1], const int8_t probe_points, const bool towers_set, const bool stow_after_each, const bool probe_at_offset) { +static bool probe_calibration_points(float z_pt[NPP + 1], const int8_t probe_points, const float dcr, const bool towers_set, const bool stow_after_each, const bool probe_at_offset) { const bool _0p_calibration = probe_points == 0, _1p_calibration = probe_points == 1 || probe_points == -1, _4p_calibration = probe_points == 2, @@ -273,7 +269,7 @@ static bool probe_calibration_points(float z_pt[NPP + 1], const int8_t probe_poi * - formulae for approximative forward kinematics in the end-stop displacement matrix * - definition of the matrix scaling parameters */ -static void reverse_kinematics_probe_points(float z_pt[NPP + 1], abc_float_t mm_at_pt_axis[NPP + 1]) { +static void reverse_kinematics_probe_points(float z_pt[NPP + 1], abc_float_t mm_at_pt_axis[NPP + 1], const float dcr) { xyz_pos_t pos{0}; LOOP_CAL_ALL(rad) { @@ -285,7 +281,7 @@ static void reverse_kinematics_probe_points(float z_pt[NPP + 1], abc_float_t mm_ } } -static void forward_kinematics_probe_points(abc_float_t mm_at_pt_axis[NPP + 1], float z_pt[NPP + 1]) { +static void forward_kinematics_probe_points(abc_float_t mm_at_pt_axis[NPP + 1], float z_pt[NPP + 1], const float dcr) { const float r_quot = dcr / delta_radius; #define ZPP(N,I,A) (((1.0f + r_quot * (N)) / 3.0f) * mm_at_pt_axis[I].A) @@ -304,19 +300,19 @@ static void forward_kinematics_probe_points(abc_float_t mm_at_pt_axis[NPP + 1], z_pt[_AB] = Zp1(_AB, a) + Zp1(_AB, b) + Zm2(_AB, c); } -static void calc_kinematics_diff_probe_points(float z_pt[NPP + 1], abc_float_t delta_e, const float delta_r, abc_float_t delta_t) { +static void calc_kinematics_diff_probe_points(float z_pt[NPP + 1], const float dcr, abc_float_t delta_e, const float delta_r, abc_float_t delta_t) { const float z_center = z_pt[CEN]; abc_float_t diff_mm_at_pt_axis[NPP + 1], new_mm_at_pt_axis[NPP + 1]; - reverse_kinematics_probe_points(z_pt, diff_mm_at_pt_axis); + reverse_kinematics_probe_points(z_pt, diff_mm_at_pt_axis, dcr); delta_radius += delta_r; delta_tower_angle_trim += delta_t; recalc_delta_settings(); - reverse_kinematics_probe_points(z_pt, new_mm_at_pt_axis); + reverse_kinematics_probe_points(z_pt, new_mm_at_pt_axis, dcr); LOOP_CAL_ALL(rad) diff_mm_at_pt_axis[rad] -= new_mm_at_pt_axis[rad] + delta_e; - forward_kinematics_probe_points(diff_mm_at_pt_axis, z_pt); + forward_kinematics_probe_points(diff_mm_at_pt_axis, z_pt, dcr); LOOP_CAL_RAD(rad) z_pt[rad] -= z_pt[CEN] - z_center; z_pt[CEN] = z_center; @@ -326,23 +322,23 @@ static void calc_kinematics_diff_probe_points(float z_pt[NPP + 1], abc_float_t d recalc_delta_settings(); } -static float auto_tune_h() { +static float auto_tune_h(const float dcr) { const float r_quot = dcr / delta_radius; return RECIPROCAL(r_quot / (2.0f / 3.0f)); // (2/3)/CR } -static float auto_tune_r() { +static float auto_tune_r(const float dcr) { constexpr float diff = 0.01f, delta_r = diff; float r_fac = 0.0f, z_pt[NPP + 1] = { 0.0f }; abc_float_t delta_e = { 0.0f }, delta_t = { 0.0f }; - calc_kinematics_diff_probe_points(z_pt, delta_e, delta_r, delta_t); + calc_kinematics_diff_probe_points(z_pt, dcr, delta_e, delta_r, delta_t); r_fac = -(z_pt[__A] + z_pt[__B] + z_pt[__C] + z_pt[_BC] + z_pt[_CA] + z_pt[_AB]) / 6.0f; r_fac = diff / r_fac / 3.0f; // 1/(3*delta_Z) return r_fac; } -static float auto_tune_a() { +static float auto_tune_a(const float dcr) { constexpr float diff = 0.01f, delta_r = 0.0f; float a_fac = 0.0f, z_pt[NPP + 1] = { 0.0f }; abc_float_t delta_e = { 0.0f }, delta_t = { 0.0f }; @@ -350,7 +346,7 @@ static float auto_tune_a() { delta_t.reset(); LOOP_LINEAR_AXES(axis) { delta_t[axis] = diff; - calc_kinematics_diff_probe_points(z_pt, delta_e, delta_r, delta_t); + calc_kinematics_diff_probe_points(z_pt, dcr, delta_e, delta_r, delta_t); delta_t[axis] = 0; a_fac += z_pt[uint8_t((axis * _4P_STEP) - _7P_STEP + NPP) % NPP + 1] / 6.0f; a_fac -= z_pt[uint8_t((axis * _4P_STEP) + 1 + _7P_STEP)] / 6.0f; @@ -372,7 +368,7 @@ static float auto_tune_a() { * P3 Probe all positions: center, towers and opposite towers. Calibrate all. * P4-P10 Probe all positions at different intermediate locations and average them. * - * Rn.nn override default calibration Radius + * Rn.nn Temporary reduce the probe grid by the specified amount (mm) * * T Don't calibrate tower angle corrections * @@ -388,7 +384,7 @@ static float auto_tune_a() { * * E Engage the probe for each point * - * O Probe at offset points (this is wrong but it seems to work) + * O Probe at offsetted probe positions (this is wrong but it seems to work) * * With SENSORLESS_PROBING: * Use these flags to calibrate stall sensitivity: (e.g., `G33 P1 Y Z` to calibrate X only.) @@ -406,27 +402,17 @@ void GcodeSuite::G33() { return; } - const bool probe_at_offset = TERN0(HAS_PROBE_XY_OFFSET, parser.boolval('O')), + const bool probe_at_offset = TERN0(HAS_PROBE_XY_OFFSET, parser.seen_test('O')), towers_set = !parser.seen_test('T'); - float max_dcr = dcr = DELTA_PRINTABLE_RADIUS; + // The calibration radius is set to a calculated value + float dcr = probe_at_offset ? DELTA_PRINTABLE_RADIUS : DELTA_PRINTABLE_RADIUS - PROBING_MARGIN; #if HAS_PROBE_XY_OFFSET - // For offset probes the calibration radius is set to a safe but non-optimal value - dcr -= HYPOT(probe.offset_xy.x, probe.offset_xy.y); - if (probe_at_offset) { - // With probe positions both probe and nozzle need to be within the printable area - max_dcr = dcr; - } - // else with nozzle positions there is a risk of the probe being outside the bed - // but as long the nozzle stays within the printable area there is no risk of - // the effector crashing into the towers. + const float total_offset = HYPOT(probe.offset_xy.x, probe.offset_xy.y); + dcr -= probe_at_offset ? _MAX(total_offset, PROBING_MARGIN) : total_offset; #endif - - if (parser.seenval('R')) dcr = parser.value_float(); - if (!WITHIN(dcr, 0, max_dcr)) { - SERIAL_ECHOLNPGM("?calibration (R)adius implausible."); - return; - } + NOMORE(dcr, DELTA_PRINTABLE_RADIUS); + if (parser.seenval('R')) dcr -= _MAX(parser.value_float(),0); const float calibration_precision = parser.floatval('C', 0.0f); if (calibration_precision < 0) { @@ -479,9 +465,10 @@ void GcodeSuite::G33() { // Report settings PGM_P const checkingac = PSTR("Checking... AC"); SERIAL_ECHOPGM_P(checkingac); + SERIAL_ECHOPGM(" at radius:", dcr); if (verbose_level == 0) SERIAL_ECHOPGM(" (DRY-RUN)"); SERIAL_EOL(); - ui.set_status_P(checkingac); + ui.set_status(checkingac); print_calibration_settings(_endstop_results, _angle_results); @@ -498,7 +485,7 @@ void GcodeSuite::G33() { // Probe the points zero_std_dev_old = zero_std_dev; - if (!probe_calibration_points(z_at_pt, probe_points, towers_set, stow_after_each, probe_at_offset)) { + if (!probe_calibration_points(z_at_pt, probe_points, dcr, towers_set, stow_after_each, probe_at_offset)) { SERIAL_ECHOLNPGM("Correct delta settings with M665 and M666"); return ac_cleanup(TERN_(HAS_MULTI_HOTEND, old_tool_index)); } @@ -538,10 +525,10 @@ void GcodeSuite::G33() { // calculate factors if (_7p_9_center) dcr *= 0.9f; - h_factor = auto_tune_h(); - r_factor = auto_tune_r(); - a_factor = auto_tune_a(); - dcr /= 0.9f; + h_factor = auto_tune_h(dcr); + r_factor = auto_tune_r(dcr); + a_factor = auto_tune_a(dcr); + if (_7p_9_center) dcr /= 0.9f; switch (probe_points) { case 0: @@ -653,13 +640,13 @@ void GcodeSuite::G33() { } } else { // dry run - PGM_P const enddryrun = PSTR("End DRY-RUN"); - SERIAL_ECHOPGM_P(enddryrun); + FSTR_P const enddryrun = F("End DRY-RUN"); + SERIAL_ECHOF(enddryrun); SERIAL_ECHO_SP(35); SERIAL_ECHOLNPAIR_F("std dev:", zero_std_dev, 3); char mess[21]; - strcpy_P(mess, enddryrun); + strcpy_P(mess, FTOP(enddryrun)); strcpy_P(&mess[11], PSTR(" sd:")); if (zero_std_dev < 1) sprintf_P(&mess[15], PSTR("0.%03i"), (int)LROUND(zero_std_dev * 1000.0f)); diff --git a/Marlin/src/gcode/calibrate/G34.cpp b/Marlin/src/gcode/calibrate/G34.cpp index f335a12311..98a0bdef88 100644 --- a/Marlin/src/gcode/calibrate/G34.cpp +++ b/Marlin/src/gcode/calibrate/G34.cpp @@ -47,7 +47,7 @@ void GcodeSuite::G34() { TemporaryGlobalEndstopsState unlock_z(false); #ifdef GANTRY_CALIBRATION_COMMANDS_PRE - gcode.process_subcommands_now_P(PSTR(GANTRY_CALIBRATION_COMMANDS_PRE)); + process_subcommands_now(F(GANTRY_CALIBRATION_COMMANDS_PRE)); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Sub Commands Processed"); #endif @@ -148,7 +148,7 @@ void GcodeSuite::G34() { #ifdef GANTRY_CALIBRATION_COMMANDS_POST if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Running Post Commands"); - gcode.process_subcommands_now_P(PSTR(GANTRY_CALIBRATION_COMMANDS_POST)); + process_subcommands_now(F(GANTRY_CALIBRATION_COMMANDS_POST)); #endif SET_SOFT_ENDSTOP_LOOSE(false); diff --git a/Marlin/src/gcode/calibrate/G34_M422.cpp b/Marlin/src/gcode/calibrate/G34_M422.cpp index dd1dd5622a..328a40dbb4 100644 --- a/Marlin/src/gcode/calibrate/G34_M422.cpp +++ b/Marlin/src/gcode/calibrate/G34_M422.cpp @@ -31,7 +31,7 @@ #include "../../module/stepper.h" #include "../../module/planner.h" #include "../../module/probe.h" -#include "../../lcd/marlinui.h" // for LCD_MESSAGEPGM +#include "../../lcd/marlinui.h" // for LCD_MESSAGE #if HAS_LEVELING #include "../../feature/bedlevel/bedlevel.h" @@ -45,6 +45,10 @@ #include "../../libs/least_squares_fit.h" #endif +#if ENABLED(BLTOUCH) + #include "../../feature/bltouch.h" +#endif + #define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) #include "../../core/debug_out.h" @@ -149,7 +153,7 @@ void GcodeSuite::G34() { // In BLTOUCH HS mode, the probe travels in a deployed state. // Users of G34 might have a badly misaligned bed, so raise Z by the // length of the deployed pin (BLTOUCH stroke < 7mm) - #define Z_BASIC_CLEARANCE (Z_CLEARANCE_BETWEEN_PROBES + 7.0f * BOTH(BLTOUCH, BLTOUCH_HS_MODE)) + #define Z_BASIC_CLEARANCE (Z_CLEARANCE_BETWEEN_PROBES + TERN0(BLTOUCH, bltouch.z_extra_clearance())) // Compute a worst-case clearance height to probe from. After the first // iteration this will be re-calculated based on the actual bed position @@ -229,7 +233,7 @@ void GcodeSuite::G34() { const float z_probed_height = probe.probe_at_point(z_stepper_align.xy[iprobe], raise_after, 0, true, false); if (isnan(z_probed_height)) { SERIAL_ECHOLNPGM("Probing failed"); - LCD_MESSAGEPGM(MSG_LCD_PROBING_FAILED); + LCD_MESSAGE(MSG_LCD_PROBING_FAILED); err_break = true; break; } @@ -328,7 +332,7 @@ void GcodeSuite::G34() { auto decreasing_accuracy = [](const_float_t v1, const_float_t v2) { if (v1 < v2 * 0.7f) { SERIAL_ECHOLNPGM("Decreasing Accuracy Detected."); - LCD_MESSAGEPGM(MSG_DECREASING_ACCURACY); + LCD_MESSAGE(MSG_DECREASING_ACCURACY); return true; } return false; @@ -411,7 +415,7 @@ void GcodeSuite::G34() { if (success_break) { SERIAL_ECHOLNPGM("Target accuracy achieved."); - LCD_MESSAGEPGM(MSG_ACCURACY_ACHIEVED); + LCD_MESSAGE(MSG_ACCURACY_ACHIEVED); break; } @@ -433,7 +437,7 @@ void GcodeSuite::G34() { // After this operation the z position needs correction set_axis_never_homed(Z_AXIS); // Home Z after the alignment procedure - process_subcommands_now_P(PSTR("G28Z")); + process_subcommands_now(F("G28Z")); #else // Use the probed height from the last iteration to determine the Z height. // z_measured_min is used, because all steppers are aligned to z_measured_min. @@ -538,7 +542,7 @@ void GcodeSuite::M422() { } void GcodeSuite::M422_report(const bool forReplay/*=true*/) { - report_heading(forReplay, PSTR(STR_Z_AUTO_ALIGN)); + report_heading(forReplay, F(STR_Z_AUTO_ALIGN)); LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) { report_echo_start(forReplay); SERIAL_ECHOLNPGM_P( diff --git a/Marlin/src/gcode/calibrate/G425.cpp b/Marlin/src/gcode/calibrate/G425.cpp index 23a66dd0c5..88c906f493 100644 --- a/Marlin/src/gcode/calibrate/G425.cpp +++ b/Marlin/src/gcode/calibrate/G425.cpp @@ -709,7 +709,7 @@ inline void calibrate_all() { void GcodeSuite::G425() { #ifdef CALIBRATION_SCRIPT_PRE - GcodeSuite::process_subcommands_now_P(PSTR(CALIBRATION_SCRIPT_PRE)); + process_subcommands_now(F(CALIBRATION_SCRIPT_PRE)); #endif if (homing_needed_error()) return; @@ -745,7 +745,7 @@ void GcodeSuite::G425() { SET_SOFT_ENDSTOP_LOOSE(false); #ifdef CALIBRATION_SCRIPT_POST - GcodeSuite::process_subcommands_now_P(PSTR(CALIBRATION_SCRIPT_POST)); + process_subcommands_now(F(CALIBRATION_SCRIPT_POST)); #endif } diff --git a/Marlin/src/gcode/calibrate/G76_M192_M871.cpp b/Marlin/src/gcode/calibrate/G76_M192_M871.cpp deleted file mode 100644 index 946701050e..0000000000 --- a/Marlin/src/gcode/calibrate/G76_M192_M871.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/** - * Marlin 3D Printer Firmware - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] - * - * Based on Sprinter and grbl. - * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -/** - * G76_M871.cpp - Temperature calibration/compensation for z-probing - */ - -#include "../../inc/MarlinConfig.h" - -#if ENABLED(PROBE_TEMP_COMPENSATION) - -#include "../gcode.h" -#include "../../module/motion.h" -#include "../../module/planner.h" -#include "../../module/probe.h" -#include "../../feature/bedlevel/bedlevel.h" -#include "../../module/temperature.h" -#include "../../module/probe.h" -#include "../../feature/probe_temp_comp.h" -#include "../../lcd/marlinui.h" - -/** - * G76: calibrate probe and/or bed temperature offsets - * Notes: - * - When calibrating probe, bed temperature is held constant. - * Compensation values are deltas to first probe measurement at probe temp. = 30°C. - * - When calibrating bed, probe temperature is held constant. - * Compensation values are deltas to first probe measurement at bed temp. = 60°C. - * - The hotend will not be heated at any time. - * - On my Průša MK3S clone I put a piece of paper between the probe and the hotend - * so the hotend fan would not cool my probe constantly. Alternatively you could just - * make sure the fan is not running while running the calibration process. - * - * Probe calibration: - * - Moves probe to cooldown point. - * - Heats up bed to 100°C. - * - Moves probe to probing point (1mm above heatbed). - * - Waits until probe reaches target temperature (30°C). - * - Does a z-probing (=base value) and increases target temperature by 5°C. - * - Waits until probe reaches increased target temperature. - * - Does a z-probing (delta to base value will be a compensation value) and increases target temperature by 5°C. - * - Repeats last two steps until max. temperature reached or timeout (i.e. probe does not heat up any further). - * - Compensation values of higher temperatures will be extrapolated (using linear regression first). - * While this is not exact by any means it is still better than simply using the last compensation value. - * - * Bed calibration: - * - Moves probe to cooldown point. - * - Heats up bed to 60°C. - * - Moves probe to probing point (1mm above heatbed). - * - Waits until probe reaches target temperature (30°C). - * - Does a z-probing (=base value) and increases bed temperature by 5°C. - * - Moves probe to cooldown point. - * - Waits until probe is below 30°C and bed has reached target temperature. - * - Moves probe to probing point and waits until it reaches target temperature (30°C). - * - Does a z-probing (delta to base value will be a compensation value) and increases bed temperature by 5°C. - * - Repeats last four points until max. bed temperature reached (110°C) or timeout. - * - Compensation values of higher temperatures will be extrapolated (using linear regression first). - * While this is not exact by any means it is still better than simply using the last compensation value. - * - * G76 [B | P] - * - no flag - Both calibration procedures will be run. - * - `B` - Run bed temperature calibration. - * - `P` - Run probe temperature calibration. - */ - -static void say_waiting_for() { SERIAL_ECHOPGM("Waiting for "); } -static void say_waiting_for_probe_heating() { say_waiting_for(); SERIAL_ECHOLNPGM("probe heating."); } -static void say_successfully_calibrated() { SERIAL_ECHOPGM("Successfully calibrated"); } -static void say_failed_to_calibrate() { SERIAL_ECHOPGM("!Failed to calibrate"); } - -void GcodeSuite::G76() { - // Check if heated bed is available and z-homing is done with probe - #if TEMP_SENSOR_BED == 0 || !(HOMING_Z_WITH_PROBE) - return; - #endif - - auto report_temps = [](millis_t &ntr, millis_t timeout=0) { - idle_no_sleep(); - const millis_t ms = millis(); - if (ELAPSED(ms, ntr)) { - ntr = ms + 1000; - thermalManager.print_heater_states(active_extruder); - } - return (timeout && ELAPSED(ms, timeout)); - }; - - auto wait_for_temps = [&](const celsius_t tb, const celsius_t tp, millis_t &ntr, const millis_t timeout=0) { - say_waiting_for(); SERIAL_ECHOLNPGM("bed and probe temperature."); - while (thermalManager.wholeDegBed() != tb || thermalManager.wholeDegProbe() > tp) - if (report_temps(ntr, timeout)) return true; - return false; - }; - - auto g76_probe = [](const TempSensorID sid, celsius_t &targ, const xy_pos_t &nozpos) { - do_z_clearance(5.0); // Raise nozzle before probing - const float measured_z = probe.probe_at_point(nozpos, PROBE_PT_STOW, 0, false); // verbose=0, probe_relative=false - if (isnan(measured_z)) - SERIAL_ECHOLNPGM("!Received NAN. Aborting."); - else { - SERIAL_ECHOLNPAIR_F("Measured: ", measured_z); - if (targ == cali_info_init[sid].start_temp) - temp_comp.prepare_new_calibration(measured_z); - else - temp_comp.push_back_new_measurement(sid, measured_z); - targ += cali_info_init[sid].temp_resolution; - } - return measured_z; - }; - - #if ENABLED(BLTOUCH) - // Make sure any BLTouch error condition is cleared - bltouch_command(BLTOUCH_RESET, BLTOUCH_RESET_DELAY); - set_bltouch_deployed(false); - #endif - - bool do_bed_cal = parser.boolval('B'), do_probe_cal = parser.boolval('P'); - if (!do_bed_cal && !do_probe_cal) do_bed_cal = do_probe_cal = true; - - // Synchronize with planner - planner.synchronize(); - - const xyz_pos_t parkpos = temp_comp.park_point, - probe_pos_xyz = xyz_pos_t(temp_comp.measure_point) + xyz_pos_t({ 0.0f, 0.0f, PTC_PROBE_HEATING_OFFSET }), - noz_pos_xyz = probe_pos_xyz - probe.offset_xy; // Nozzle position based on probe position - - if (do_bed_cal || do_probe_cal) { - // Ensure park position is reachable - bool reachable = position_is_reachable(parkpos) || WITHIN(parkpos.z, Z_MIN_POS - fslop, Z_MAX_POS + fslop); - if (!reachable) - SERIAL_ECHOLNPGM("!Park"); - else { - // Ensure probe position is reachable - reachable = probe.can_reach(probe_pos_xyz); - if (!reachable) SERIAL_ECHOLNPGM("!Probe"); - } - - if (!reachable) { - SERIAL_ECHOLNPGM(" position unreachable - aborting."); - return; - } - - process_subcommands_now_P(G28_STR); - } - - remember_feedrate_scaling_off(); - - /****************************************** - * Calibrate bed temperature offsets - ******************************************/ - - // Report temperatures every second and handle heating timeouts - millis_t next_temp_report = millis() + 1000; - - auto report_targets = [&](const celsius_t tb, const celsius_t tp) { - SERIAL_ECHOLNPGM("Target Bed:", tb, " Probe:", tp); - }; - - if (do_bed_cal) { - - celsius_t target_bed = cali_info_init[TSI_BED].start_temp, - target_probe = temp_comp.bed_calib_probe_temp; - - say_waiting_for(); SERIAL_ECHOLNPGM(" cooling."); - while (thermalManager.wholeDegBed() > target_bed || thermalManager.wholeDegProbe() > target_probe) - report_temps(next_temp_report); - - // Disable leveling so it won't mess with us - TERN_(HAS_LEVELING, set_bed_leveling_enabled(false)); - - for (;;) { - thermalManager.setTargetBed(target_bed); - - report_targets(target_bed, target_probe); - - // Park nozzle - do_blocking_move_to(parkpos); - - // Wait for heatbed to reach target temp and probe to cool below target temp - if (wait_for_temps(target_bed, target_probe, next_temp_report, millis() + MIN_TO_MS(15))) { - SERIAL_ECHOLNPGM("!Bed heating timeout."); - break; - } - - // Move the nozzle to the probing point and wait for the probe to reach target temp - do_blocking_move_to(noz_pos_xyz); - say_waiting_for_probe_heating(); - SERIAL_EOL(); - while (thermalManager.wholeDegProbe() < target_probe) - report_temps(next_temp_report); - - const float measured_z = g76_probe(TSI_BED, target_bed, noz_pos_xyz); - if (isnan(measured_z) || target_bed > (BED_MAX_TARGET)) break; - } - - SERIAL_ECHOLNPGM("Retrieved measurements: ", temp_comp.get_index()); - if (temp_comp.finish_calibration(TSI_BED)) { - say_successfully_calibrated(); - SERIAL_ECHOLNPGM(" bed."); - } - else { - say_failed_to_calibrate(); - SERIAL_ECHOLNPGM(" bed. Values reset."); - } - - // Cleanup - thermalManager.setTargetBed(0); - TERN_(HAS_LEVELING, set_bed_leveling_enabled(true)); - } // do_bed_cal - - /******************************************** - * Calibrate probe temperature offsets - ********************************************/ - - if (do_probe_cal) { - - // Park nozzle - do_blocking_move_to(parkpos); - - // Initialize temperatures - const celsius_t target_bed = temp_comp.probe_calib_bed_temp; - thermalManager.setTargetBed(target_bed); - - celsius_t target_probe = cali_info_init[TSI_PROBE].start_temp; - - report_targets(target_bed, target_probe); - - // Wait for heatbed to reach target temp and probe to cool below target temp - wait_for_temps(target_bed, target_probe, next_temp_report); - - // Disable leveling so it won't mess with us - TERN_(HAS_LEVELING, set_bed_leveling_enabled(false)); - - bool timeout = false; - for (;;) { - // Move probe to probing point and wait for it to reach target temperature - do_blocking_move_to(noz_pos_xyz); - - say_waiting_for_probe_heating(); - SERIAL_ECHOLNPGM(" Bed:", target_bed, " Probe:", target_probe); - const millis_t probe_timeout_ms = millis() + SEC_TO_MS(900UL); - while (thermalManager.degProbe() < target_probe) { - if (report_temps(next_temp_report, probe_timeout_ms)) { - SERIAL_ECHOLNPGM("!Probe heating timed out."); - timeout = true; - break; - } - } - if (timeout) break; - - const float measured_z = g76_probe(TSI_PROBE, target_probe, noz_pos_xyz); - if (isnan(measured_z) || target_probe > cali_info_init[TSI_PROBE].end_temp) break; - } - - SERIAL_ECHOLNPGM("Retrieved measurements: ", temp_comp.get_index()); - if (temp_comp.finish_calibration(TSI_PROBE)) - say_successfully_calibrated(); - else - say_failed_to_calibrate(); - SERIAL_ECHOLNPGM(" probe."); - - // Cleanup - thermalManager.setTargetBed(0); - TERN_(HAS_LEVELING, set_bed_leveling_enabled(true)); - - SERIAL_ECHOLNPGM("Final compensation values:"); - temp_comp.print_offsets(); - } // do_probe_cal - - restore_feedrate_and_scaling(); -} - -/** - * M871: Report / reset temperature compensation offsets. - * Note: This does not affect values in EEPROM until M500. - * - * M871 [ R | B | P | E ] - * - * No Parameters - Print current offset values. - * - * Select only one of these flags: - * R - Reset all offsets to zero (i.e., disable compensation). - * B - Manually set offset for bed - * P - Manually set offset for probe - * E - Manually set offset for extruder - * - * With B, P, or E: - * I[index] - Index in the array - * V[value] - Adjustment in µm - */ -void GcodeSuite::M871() { - - if (parser.seen('R')) { - // Reset z-probe offsets to factory defaults - temp_comp.clear_all_offsets(); - SERIAL_ECHOLNPGM("Offsets reset to default."); - } - else if (parser.seen("BPE")) { - if (!parser.seenval('V')) return; - const int16_t offset_val = parser.value_int(); - if (!parser.seenval('I')) return; - const int16_t idx = parser.value_int(); - const TempSensorID mod = (parser.seen('B') ? TSI_BED : - #if ENABLED(USE_TEMP_EXT_COMPENSATION) - parser.seen('E') ? TSI_EXT : - #endif - TSI_PROBE - ); - if (idx > 0 && temp_comp.set_offset(mod, idx - 1, offset_val)) - SERIAL_ECHOLNPGM("Set value: ", offset_val); - else - SERIAL_ECHOLNPGM("!Invalid index. Failed to set value (note: value at index 0 is constant)."); - - } - else // Print current Z-probe adjustments. Note: Values in EEPROM might differ. - temp_comp.print_offsets(); -} - -/** - * M192: Wait for probe temperature sensor to reach a target - * - * Select only one of these flags: - * R - Wait for heating or cooling - * S - Wait only for heating - */ -void GcodeSuite::M192() { - if (DEBUGGING(DRYRUN)) return; - - const bool no_wait_for_cooling = parser.seenval('S'); - if (!no_wait_for_cooling && ! parser.seenval('R')) { - SERIAL_ERROR_MSG("No target temperature set."); - return; - } - - const celsius_t target_temp = parser.value_celsius(); - ui.set_status_P(thermalManager.isProbeBelowTemp(target_temp) ? GET_TEXT(MSG_PROBE_HEATING) : GET_TEXT(MSG_PROBE_COOLING)); - thermalManager.wait_for_probe(target_temp, no_wait_for_cooling); -} - -#endif // PROBE_TEMP_COMPENSATION diff --git a/Marlin/src/gcode/calibrate/G76_M871.cpp b/Marlin/src/gcode/calibrate/G76_M871.cpp new file mode 100644 index 0000000000..21bb2c7590 --- /dev/null +++ b/Marlin/src/gcode/calibrate/G76_M871.cpp @@ -0,0 +1,337 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * G76_M871.cpp - Temperature calibration/compensation for z-probing + */ + +#include "../../inc/MarlinConfig.h" + +#if HAS_PTC + +#include "../gcode.h" +#include "../../module/motion.h" +#include "../../module/planner.h" +#include "../../module/probe.h" +#include "../../feature/bedlevel/bedlevel.h" +#include "../../module/temperature.h" +#include "../../module/probe.h" +#include "../../feature/probe_temp_comp.h" +#include "../../lcd/marlinui.h" + +/** + * G76: calibrate probe and/or bed temperature offsets + * Notes: + * - When calibrating probe, bed temperature is held constant. + * Compensation values are deltas to first probe measurement at probe temp. = 30°C. + * - When calibrating bed, probe temperature is held constant. + * Compensation values are deltas to first probe measurement at bed temp. = 60°C. + * - The hotend will not be heated at any time. + * - On my Průša MK3S clone I put a piece of paper between the probe and the hotend + * so the hotend fan would not cool my probe constantly. Alternatively you could just + * make sure the fan is not running while running the calibration process. + * + * Probe calibration: + * - Moves probe to cooldown point. + * - Heats up bed to 100°C. + * - Moves probe to probing point (1mm above heatbed). + * - Waits until probe reaches target temperature (30°C). + * - Does a z-probing (=base value) and increases target temperature by 5°C. + * - Waits until probe reaches increased target temperature. + * - Does a z-probing (delta to base value will be a compensation value) and increases target temperature by 5°C. + * - Repeats last two steps until max. temperature reached or timeout (i.e. probe does not heat up any further). + * - Compensation values of higher temperatures will be extrapolated (using linear regression first). + * While this is not exact by any means it is still better than simply using the last compensation value. + * + * Bed calibration: + * - Moves probe to cooldown point. + * - Heats up bed to 60°C. + * - Moves probe to probing point (1mm above heatbed). + * - Waits until probe reaches target temperature (30°C). + * - Does a z-probing (=base value) and increases bed temperature by 5°C. + * - Moves probe to cooldown point. + * - Waits until probe is below 30°C and bed has reached target temperature. + * - Moves probe to probing point and waits until it reaches target temperature (30°C). + * - Does a z-probing (delta to base value will be a compensation value) and increases bed temperature by 5°C. + * - Repeats last four points until max. bed temperature reached (110°C) or timeout. + * - Compensation values of higher temperatures will be extrapolated (using linear regression first). + * While this is not exact by any means it is still better than simply using the last compensation value. + * + * G76 [B | P] + * - no flag - Both calibration procedures will be run. + * - `B` - Run bed temperature calibration. + * - `P` - Run probe temperature calibration. + */ + +static void say_waiting_for() { SERIAL_ECHOPGM("Waiting for "); } +static void say_waiting_for_probe_heating() { say_waiting_for(); SERIAL_ECHOLNPGM("probe heating."); } +static void say_successfully_calibrated() { SERIAL_ECHOPGM("Successfully calibrated"); } +static void say_failed_to_calibrate() { SERIAL_ECHOPGM("!Failed to calibrate"); } + +#if BOTH(PTC_PROBE, PTC_BED) + + void GcodeSuite::G76() { + auto report_temps = [](millis_t &ntr, millis_t timeout=0) { + idle_no_sleep(); + const millis_t ms = millis(); + if (ELAPSED(ms, ntr)) { + ntr = ms + 1000; + thermalManager.print_heater_states(active_extruder); + } + return (timeout && ELAPSED(ms, timeout)); + }; + + auto wait_for_temps = [&](const celsius_t tb, const celsius_t tp, millis_t &ntr, const millis_t timeout=0) { + say_waiting_for(); SERIAL_ECHOLNPGM("bed and probe temperature."); + while (thermalManager.wholeDegBed() != tb || thermalManager.wholeDegProbe() > tp) + if (report_temps(ntr, timeout)) return true; + return false; + }; + + auto g76_probe = [](const TempSensorID sid, celsius_t &targ, const xy_pos_t &nozpos) { + do_z_clearance(5.0); // Raise nozzle before probing + const float measured_z = probe.probe_at_point(nozpos, PROBE_PT_STOW, 0, false); // verbose=0, probe_relative=false + if (isnan(measured_z)) + SERIAL_ECHOLNPGM("!Received NAN. Aborting."); + else { + SERIAL_ECHOLNPAIR_F("Measured: ", measured_z); + if (targ == ProbeTempComp::cali_info[sid].start_temp) + ptc.prepare_new_calibration(measured_z); + else + ptc.push_back_new_measurement(sid, measured_z); + targ += ProbeTempComp::cali_info[sid].temp_resolution; + } + return measured_z; + }; + + #if ENABLED(BLTOUCH) + // Make sure any BLTouch error condition is cleared + bltouch_command(BLTOUCH_RESET, BLTOUCH_RESET_DELAY); + set_bltouch_deployed(false); + #endif + + bool do_bed_cal = parser.boolval('B'), do_probe_cal = parser.boolval('P'); + if (!do_bed_cal && !do_probe_cal) do_bed_cal = do_probe_cal = true; + + // Synchronize with planner + planner.synchronize(); + + #ifndef PTC_PROBE_HEATING_OFFSET + #define PTC_PROBE_HEATING_OFFSET 0 + #endif + const xyz_pos_t parkpos = PTC_PARK_POS, + probe_pos_xyz = xyz_pos_t(PTC_PROBE_POS) + xyz_pos_t({ 0.0f, 0.0f, PTC_PROBE_HEATING_OFFSET }), + noz_pos_xyz = probe_pos_xyz - probe.offset_xy; // Nozzle position based on probe position + + if (do_bed_cal || do_probe_cal) { + // Ensure park position is reachable + bool reachable = position_is_reachable(parkpos) || WITHIN(parkpos.z, Z_MIN_POS - fslop, Z_MAX_POS + fslop); + if (!reachable) + SERIAL_ECHOLNPGM("!Park"); + else { + // Ensure probe position is reachable + reachable = probe.can_reach(probe_pos_xyz); + if (!reachable) SERIAL_ECHOLNPGM("!Probe"); + } + + if (!reachable) { + SERIAL_ECHOLNPGM(" position unreachable - aborting."); + return; + } + + process_subcommands_now(FPSTR(G28_STR)); + } + + remember_feedrate_scaling_off(); + + /****************************************** + * Calibrate bed temperature offsets + ******************************************/ + + // Report temperatures every second and handle heating timeouts + millis_t next_temp_report = millis() + 1000; + + auto report_targets = [&](const celsius_t tb, const celsius_t tp) { + SERIAL_ECHOLNPGM("Target Bed:", tb, " Probe:", tp); + }; + + if (do_bed_cal) { + + celsius_t target_bed = PTC_BED_START, + target_probe = PTC_PROBE_TEMP; + + say_waiting_for(); SERIAL_ECHOLNPGM(" cooling."); + while (thermalManager.wholeDegBed() > target_bed || thermalManager.wholeDegProbe() > target_probe) + report_temps(next_temp_report); + + // Disable leveling so it won't mess with us + TERN_(HAS_LEVELING, set_bed_leveling_enabled(false)); + + for (uint8_t idx = 0; idx <= PTC_BED_COUNT; idx++) { + thermalManager.setTargetBed(target_bed); + + report_targets(target_bed, target_probe); + + // Park nozzle + do_blocking_move_to(parkpos); + + // Wait for heatbed to reach target temp and probe to cool below target temp + if (wait_for_temps(target_bed, target_probe, next_temp_report, millis() + MIN_TO_MS(15))) { + SERIAL_ECHOLNPGM("!Bed heating timeout."); + break; + } + + // Move the nozzle to the probing point and wait for the probe to reach target temp + do_blocking_move_to(noz_pos_xyz); + say_waiting_for_probe_heating(); + SERIAL_EOL(); + while (thermalManager.wholeDegProbe() < target_probe) + report_temps(next_temp_report); + + const float measured_z = g76_probe(TSI_BED, target_bed, noz_pos_xyz); + if (isnan(measured_z) || target_bed > (BED_MAX_TARGET)) break; + } + + SERIAL_ECHOLNPGM("Retrieved measurements: ", ptc.get_index()); + if (ptc.finish_calibration(TSI_BED)) { + say_successfully_calibrated(); + SERIAL_ECHOLNPGM(" bed."); + } + else { + say_failed_to_calibrate(); + SERIAL_ECHOLNPGM(" bed. Values reset."); + } + + // Cleanup + thermalManager.setTargetBed(0); + TERN_(HAS_LEVELING, set_bed_leveling_enabled(true)); + } // do_bed_cal + + /******************************************** + * Calibrate probe temperature offsets + ********************************************/ + + if (do_probe_cal) { + + // Park nozzle + do_blocking_move_to(parkpos); + + // Initialize temperatures + const celsius_t target_bed = BED_MAX_TARGET; + thermalManager.setTargetBed(target_bed); + + celsius_t target_probe = PTC_PROBE_START; + + report_targets(target_bed, target_probe); + + // Wait for heatbed to reach target temp and probe to cool below target temp + wait_for_temps(target_bed, target_probe, next_temp_report); + + // Disable leveling so it won't mess with us + TERN_(HAS_LEVELING, set_bed_leveling_enabled(false)); + + bool timeout = false; + for (uint8_t idx = 0; idx <= PTC_PROBE_COUNT; idx++) { + // Move probe to probing point and wait for it to reach target temperature + do_blocking_move_to(noz_pos_xyz); + + say_waiting_for_probe_heating(); + SERIAL_ECHOLNPGM(" Bed:", target_bed, " Probe:", target_probe); + const millis_t probe_timeout_ms = millis() + SEC_TO_MS(900UL); + while (thermalManager.degProbe() < target_probe) { + if (report_temps(next_temp_report, probe_timeout_ms)) { + SERIAL_ECHOLNPGM("!Probe heating timed out."); + timeout = true; + break; + } + } + if (timeout) break; + + const float measured_z = g76_probe(TSI_PROBE, target_probe, noz_pos_xyz); + if (isnan(measured_z)) break; + } + + SERIAL_ECHOLNPGM("Retrieved measurements: ", ptc.get_index()); + if (ptc.finish_calibration(TSI_PROBE)) + say_successfully_calibrated(); + else + say_failed_to_calibrate(); + SERIAL_ECHOLNPGM(" probe."); + + // Cleanup + thermalManager.setTargetBed(0); + TERN_(HAS_LEVELING, set_bed_leveling_enabled(true)); + + SERIAL_ECHOLNPGM("Final compensation values:"); + ptc.print_offsets(); + } // do_probe_cal + + restore_feedrate_and_scaling(); + } + +#endif // PTC_PROBE && PTC_BED + +/** + * M871: Report / reset temperature compensation offsets. + * Note: This does not affect values in EEPROM until M500. + * + * M871 [ R | B | P | E ] + * + * No Parameters - Print current offset values. + * + * Select only one of these flags: + * R - Reset all offsets to zero (i.e., disable compensation). + * B - Manually set offset for bed + * P - Manually set offset for probe + * E - Manually set offset for extruder + * + * With B, P, or E: + * I[index] - Index in the array + * V[value] - Adjustment in µm + */ +void GcodeSuite::M871() { + + if (parser.seen('R')) { + // Reset z-probe offsets to factory defaults + ptc.clear_all_offsets(); + SERIAL_ECHOLNPGM("Offsets reset to default."); + } + else if (parser.seen("BPE")) { + if (!parser.seenval('V')) return; + const int16_t offset_val = parser.value_int(); + if (!parser.seenval('I')) return; + const int16_t idx = parser.value_int(); + const TempSensorID mod = TERN_(PTC_BED, parser.seen_test('B') ? TSI_BED :) + TERN_(PTC_HOTEND, parser.seen_test('E') ? TSI_EXT :) + TERN_(PTC_PROBE, parser.seen_test('P') ? TSI_PROBE :) TSI_COUNT; + if (mod == TSI_COUNT) + SERIAL_ECHOLNPGM("!Invalid sensor."); + else if (idx > 0 && ptc.set_offset(mod, idx - 1, offset_val)) + SERIAL_ECHOLNPGM("Set value: ", offset_val); + else + SERIAL_ECHOLNPGM("!Invalid index. Failed to set value (note: value at index 0 is constant)."); + } + else // Print current Z-probe adjustments. Note: Values in EEPROM might differ. + ptc.print_offsets(); +} + +#endif // HAS_PTC diff --git a/Marlin/src/gcode/calibrate/M100.cpp b/Marlin/src/gcode/calibrate/M100.cpp index 0e2d42907a..338392b597 100644 --- a/Marlin/src/gcode/calibrate/M100.cpp +++ b/Marlin/src/gcode/calibrate/M100.cpp @@ -51,7 +51,7 @@ * Also, there are two support functions that can be called from a developer's C code. * * uint16_t check_for_free_memory_corruption(PGM_P const free_memory_start); - * void M100_dump_routine(PGM_P const title, const char * const start, const uintptr_t size); + * void M100_dump_routine(FSTR_P const title, const char * const start, const uintptr_t size); * * Initial version by Roxy-3D */ @@ -182,8 +182,8 @@ inline int32_t count_test_bytes(const char * const start_free_memory) { } } - void M100_dump_routine(PGM_P const title, const char * const start, const uintptr_t size) { - SERIAL_ECHOLNPGM_P(title); + void M100_dump_routine(FSTR_P const title, const char * const start, const uintptr_t size) { + SERIAL_ECHOLNF(title); // // Round the start and end locations to produce full lines of output // @@ -196,8 +196,8 @@ inline int32_t count_test_bytes(const char * const start_free_memory) { #endif // M100_FREE_MEMORY_DUMPER -inline int check_for_free_memory_corruption(PGM_P const title) { - SERIAL_ECHOPGM_P(title); +inline int check_for_free_memory_corruption(FSTR_P const title) { + SERIAL_ECHOF(title); char *start_free_memory = free_memory_start, *end_free_memory = free_memory_end; int n = end_free_memory - start_free_memory; @@ -217,7 +217,7 @@ inline int check_for_free_memory_corruption(PGM_P const title) { // idle(); serial_delay(20); #if ENABLED(M100_FREE_MEMORY_DUMPER) - M100_dump_routine(PSTR(" Memory corruption detected with end_free_memory S T" TERN_(HAS_JUNCTION_DEVIATION, " J") TERN_(HAS_CLASSIC_JERK, " X Y Z") diff --git a/Marlin/src/gcode/config/M217.cpp b/Marlin/src/gcode/config/M217.cpp index 923a27d7df..7576272a48 100644 --- a/Marlin/src/gcode/config/M217.cpp +++ b/Marlin/src/gcode/config/M217.cpp @@ -131,15 +131,15 @@ void GcodeSuite::M217() { } void GcodeSuite::M217_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_TOOL_CHANGING)); + report_heading_etc(forReplay, F(STR_TOOL_CHANGING)); SERIAL_ECHOPGM(" M217"); #if ENABLED(TOOLCHANGE_FILAMENT_SWAP) SERIAL_ECHOPGM(" S", LINEAR_UNIT(toolchange_settings.swap_length)); SERIAL_ECHOPGM_P(SP_B_STR, LINEAR_UNIT(toolchange_settings.extra_resume), - SP_E_STR, LINEAR_UNIT(toolchange_settings.extra_prime), - SP_P_STR, LINEAR_UNIT(toolchange_settings.prime_speed)); + SP_E_STR, LINEAR_UNIT(toolchange_settings.extra_prime), + SP_P_STR, LINEAR_UNIT(toolchange_settings.prime_speed)); SERIAL_ECHOPGM(" R", LINEAR_UNIT(toolchange_settings.retract_speed), " U", LINEAR_UNIT(toolchange_settings.unretract_speed), " F", toolchange_settings.fan_speed, diff --git a/Marlin/src/gcode/config/M218.cpp b/Marlin/src/gcode/config/M218.cpp index c95cd6c1b9..c39447a28d 100644 --- a/Marlin/src/gcode/config/M218.cpp +++ b/Marlin/src/gcode/config/M218.cpp @@ -57,7 +57,7 @@ void GcodeSuite::M218() { } void GcodeSuite::M218_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_HOTEND_OFFSETS)); + report_heading_etc(forReplay, F(STR_HOTEND_OFFSETS)); LOOP_S_L_N(e, 1, HOTENDS) { report_echo_start(forReplay); SERIAL_ECHOPGM_P( diff --git a/Marlin/src/gcode/config/M281.cpp b/Marlin/src/gcode/config/M281.cpp index ac91f08cb4..b90de6be30 100644 --- a/Marlin/src/gcode/config/M281.cpp +++ b/Marlin/src/gcode/config/M281.cpp @@ -55,7 +55,7 @@ void GcodeSuite::M281() { } void GcodeSuite::M281_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_SERVO_ANGLES)); + report_heading_etc(forReplay, F(STR_SERVO_ANGLES)); LOOP_L_N(i, NUM_SERVOS) { switch (i) { default: break; diff --git a/Marlin/src/gcode/config/M301.cpp b/Marlin/src/gcode/config/M301.cpp index db882b3b65..fc9f1883d6 100644 --- a/Marlin/src/gcode/config/M301.cpp +++ b/Marlin/src/gcode/config/M301.cpp @@ -79,7 +79,7 @@ void GcodeSuite::M301() { } void GcodeSuite::M301_report(const bool forReplay/*=true*/ E_OPTARG(const int8_t eindex/*=-1*/)) { - report_heading(forReplay, PSTR(STR_HOTEND_PID)); + report_heading(forReplay, F(STR_HOTEND_PID)); IF_DISABLED(HAS_MULTI_EXTRUDER, constexpr int8_t eindex = -1); HOTEND_LOOP() { if (e == eindex || eindex == -1) { diff --git a/Marlin/src/gcode/config/M302.cpp b/Marlin/src/gcode/config/M302.cpp index 57c049e194..e271dcd469 100644 --- a/Marlin/src/gcode/config/M302.cpp +++ b/Marlin/src/gcode/config/M302.cpp @@ -55,7 +55,7 @@ void GcodeSuite::M302() { // Report current state SERIAL_ECHO_START(); SERIAL_ECHOPGM("Cold extrudes are "); - SERIAL_ECHOPGM_P(thermalManager.allow_cold_extrude ? PSTR("en") : PSTR("dis")); + SERIAL_ECHOF(thermalManager.allow_cold_extrude ? F("en") : F("dis")); SERIAL_ECHOLNPGM("abled (min temp ", thermalManager.extrude_min_temp, "C)"); } } diff --git a/Marlin/src/gcode/config/M304.cpp b/Marlin/src/gcode/config/M304.cpp index 05ee4bad80..97dc4be25e 100644 --- a/Marlin/src/gcode/config/M304.cpp +++ b/Marlin/src/gcode/config/M304.cpp @@ -42,8 +42,8 @@ void GcodeSuite::M304() { } void GcodeSuite::M304_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_BED_PID)); - SERIAL_ECHO_MSG( + report_heading_etc(forReplay, F(STR_BED_PID)); + SERIAL_ECHOLNPGM( " M304 P", thermalManager.temp_bed.pid.Kp , " I", unscalePID_i(thermalManager.temp_bed.pid.Ki) , " D", unscalePID_d(thermalManager.temp_bed.pid.Kd) diff --git a/Marlin/src/gcode/config/M309.cpp b/Marlin/src/gcode/config/M309.cpp index 01c4e62347..577023292e 100644 --- a/Marlin/src/gcode/config/M309.cpp +++ b/Marlin/src/gcode/config/M309.cpp @@ -42,7 +42,7 @@ void GcodeSuite::M309() { } void GcodeSuite::M309_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_CHAMBER_PID)); + report_heading_etc(forReplay, F(STR_CHAMBER_PID)); SERIAL_ECHOLNPGM( " M309 P", thermalManager.temp_chamber.pid.Kp , " I", unscalePID_i(thermalManager.temp_chamber.pid.Ki) diff --git a/Marlin/src/gcode/config/M43.cpp b/Marlin/src/gcode/config/M43.cpp index 08b45efa15..097aa142f0 100644 --- a/Marlin/src/gcode/config/M43.cpp +++ b/Marlin/src/gcode/config/M43.cpp @@ -65,12 +65,12 @@ inline void toggle_pins() { pin_t pin = GET_PIN_MAP_PIN_M43(i); if (!VALID_PIN(pin)) continue; if (M43_NEVER_TOUCH(i) || (!ignore_protection && pin_is_protected(pin))) { - report_pin_state_extended(pin, ignore_protection, true, PSTR("Untouched ")); + report_pin_state_extended(pin, ignore_protection, true, F("Untouched ")); SERIAL_EOL(); } else { watchdog_refresh(); - report_pin_state_extended(pin, ignore_protection, true, PSTR("Pulsing ")); + report_pin_state_extended(pin, ignore_protection, true, F("Pulsing ")); #ifdef __STM32F1__ const auto prior_mode = _GET_MODE(i); #else @@ -303,7 +303,7 @@ void GcodeSuite::M43() { if (parser.seen('E')) { endstops.monitor_flag = parser.value_bool(); SERIAL_ECHOPGM("endstop monitor "); - SERIAL_ECHOPGM_P(endstops.monitor_flag ? PSTR("en") : PSTR("dis")); + SERIAL_ECHOF(endstops.monitor_flag ? F("en") : F("dis")); SERIAL_ECHOLNPGM("abled"); return; } @@ -344,8 +344,8 @@ void GcodeSuite::M43() { #if HAS_RESUME_CONTINUE KEEPALIVE_STATE(PAUSED_FOR_USER); wait_for_user = true; - TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("M43 Wait Called"), CONTINUE_STR)); - TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("M43 Wait Called"))); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, F("M43 Wait Called"), FPSTR(CONTINUE_STR))); + TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(F("M43 Wait Called"))); #endif for (;;) { diff --git a/Marlin/src/gcode/config/M92.cpp b/Marlin/src/gcode/config/M92.cpp index ef11533114..54fe698f97 100644 --- a/Marlin/src/gcode/config/M92.cpp +++ b/Marlin/src/gcode/config/M92.cpp @@ -91,7 +91,7 @@ void GcodeSuite::M92() { } void GcodeSuite::M92_report(const bool forReplay/*=true*/, const int8_t e/*=-1*/) { - report_heading_etc(forReplay, PSTR(STR_STEPS_PER_UNIT)); + report_heading_etc(forReplay, F(STR_STEPS_PER_UNIT)); SERIAL_ECHOPGM_P(LIST_N(DOUBLE(LINEAR_AXES), PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]), SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]), diff --git a/Marlin/src/gcode/control/M108_M112_M410.cpp b/Marlin/src/gcode/control/M108_M112_M410.cpp index 309c806c8f..39f9c04e19 100644 --- a/Marlin/src/gcode/control/M108_M112_M410.cpp +++ b/Marlin/src/gcode/control/M108_M112_M410.cpp @@ -40,7 +40,7 @@ void GcodeSuite::M108() { * M112: Full Shutdown */ void GcodeSuite::M112() { - kill(M112_KILL_STR, nullptr, true); + kill(FPSTR(M112_KILL_STR), nullptr, true); } /** diff --git a/Marlin/src/gcode/control/M111.cpp b/Marlin/src/gcode/control/M111.cpp index 69d20b4c5d..08c39b762e 100644 --- a/Marlin/src/gcode/control/M111.cpp +++ b/Marlin/src/gcode/control/M111.cpp @@ -26,7 +26,7 @@ * M111: Set the debug level */ void GcodeSuite::M111() { - if (parser.seen('S')) marlin_debug_flags = parser.byteval('S'); + if (parser.seenval('S')) marlin_debug_flags = parser.value_byte(); static PGMSTR(str_debug_1, STR_DEBUG_ECHO); static PGMSTR(str_debug_2, STR_DEBUG_INFO); diff --git a/Marlin/src/gcode/control/M17_M18_M84.cpp b/Marlin/src/gcode/control/M17_M18_M84.cpp index 82df20ac45..4683786f1f 100644 --- a/Marlin/src/gcode/control/M17_M18_M84.cpp +++ b/Marlin/src/gcode/control/M17_M18_M84.cpp @@ -136,7 +136,7 @@ void GcodeSuite::M17() { } } else { - LCD_MESSAGEPGM(MSG_NO_MOVE); + LCD_MESSAGE(MSG_NO_MOVE); stepper.enable_all_steppers(); } } diff --git a/Marlin/src/gcode/control/M211.cpp b/Marlin/src/gcode/control/M211.cpp index a837d79533..95ae052a7b 100644 --- a/Marlin/src/gcode/control/M211.cpp +++ b/Marlin/src/gcode/control/M211.cpp @@ -40,15 +40,15 @@ void GcodeSuite::M211() { } void GcodeSuite::M211_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_SOFT_ENDSTOPS)); + report_heading_etc(forReplay, F(STR_SOFT_ENDSTOPS)); SERIAL_ECHOPGM(" M211 S", AS_DIGIT(soft_endstop._enabled), " ; "); serialprintln_onoff(soft_endstop._enabled); report_echo_start(forReplay); const xyz_pos_t l_soft_min = soft_endstop.min.asLogical(), l_soft_max = soft_endstop.max.asLogical(); - print_pos(l_soft_min, PSTR(STR_SOFT_MIN), PSTR(" ")); - print_pos(l_soft_max, PSTR(STR_SOFT_MAX)); + print_pos(l_soft_min, F(STR_SOFT_MIN), F(" ")); + print_pos(l_soft_max, F(STR_SOFT_MAX)); } #endif // HAS_SOFTWARE_ENDSTOPS diff --git a/Marlin/src/gcode/control/M3-M5.cpp b/Marlin/src/gcode/control/M3-M5.cpp index ecae8b06c6..ddbbc4ab68 100644 --- a/Marlin/src/gcode/control/M3-M5.cpp +++ b/Marlin/src/gcode/control/M3-M5.cpp @@ -66,21 +66,23 @@ * PWM duty cycle goes from 0 (off) to 255 (always on). */ void GcodeSuite::M3_M4(const bool is_M4) { - auto get_s_power = [] { - if (parser.seenval('S')) { - const float spwr = parser.value_float(); - #if ENABLED(SPINDLE_SERVO) - cutter.unitPower = spwr; - #else - cutter.unitPower = TERN(SPINDLE_LASER_USE_PWM, - cutter.power_to_range(cutter_power_t(round(spwr))), - spwr > 0 ? 255 : 0); - #endif - } - else - cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP); - return cutter.unitPower; - }; + #if EITHER(SPINDLE_LASER_USE_PWM, SPINDLE_SERVO) + auto get_s_power = [] { + if (parser.seenval('S')) { + const float spwr = parser.value_float(); + #if ENABLED(SPINDLE_SERVO) + cutter.unitPower = spwr; + #else + cutter.unitPower = TERN(SPINDLE_LASER_USE_PWM, + cutter.power_to_range(cutter_power_t(round(spwr))), + spwr > 0 ? 255 : 0); + #endif + } + else + cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP); + return cutter.unitPower; + }; + #endif #if ENABLED(LASER_POWER_INLINE) if (parser.seen('I') == DISABLED(LASER_POWER_INLINE_INVERT)) { diff --git a/Marlin/src/gcode/control/M42.cpp b/Marlin/src/gcode/control/M42.cpp index eead971a01..77c0ccc49b 100644 --- a/Marlin/src/gcode/control/M42.cpp +++ b/Marlin/src/gcode/control/M42.cpp @@ -126,10 +126,10 @@ void GcodeSuite::M42() { extDigitalWrite(pin, pin_status); #ifdef ARDUINO_ARCH_STM32 - // A simple I/O will be set to 0 by analogWrite() + // A simple I/O will be set to 0 by set_pwm_duty() if (pin_status <= 1 && !PWM_PIN(pin)) return; #endif - analogWrite(pin, pin_status); + set_pwm_duty(pin, pin_status); } #endif // DIRECT_PIN_CONTROL diff --git a/Marlin/src/gcode/control/M605.cpp b/Marlin/src/gcode/control/M605.cpp index 08efaab59d..788659e7e2 100644 --- a/Marlin/src/gcode/control/M605.cpp +++ b/Marlin/src/gcode/control/M605.cpp @@ -110,7 +110,7 @@ set_duplication_enabled(false); #ifdef EVENT_GCODE_IDEX_AFTER_MODECHANGE - gcode.process_subcommands_now_P(PSTR(EVENT_GCODE_IDEX_AFTER_MODECHANGE)); + process_subcommands_now(F(EVENT_GCODE_IDEX_AFTER_MODECHANGE)); #endif } else if (!parser.seen('W')) // if no S or W parameter, the DXC mode gets reset to the user's default diff --git a/Marlin/src/gcode/control/M80_M81.cpp b/Marlin/src/gcode/control/M80_M81.cpp index 149613ee15..b8be9daa40 100644 --- a/Marlin/src/gcode/control/M80_M81.cpp +++ b/Marlin/src/gcode/control/M80_M81.cpp @@ -25,7 +25,7 @@ #include "../../module/temperature.h" #include "../../module/planner.h" // for planner.finish_and_disable #include "../../module/printcounter.h" // for print_job_timer.stop -#include "../../lcd/marlinui.h" // for LCD_MESSAGEPGM_P +#include "../../lcd/marlinui.h" // for LCD_MESSAGE_F #include "../../inc/MarlinConfig.h" @@ -48,7 +48,7 @@ // S: Report the current power supply state and exit if (parser.seen('S')) { - SERIAL_ECHOPGM_P(powerManager.psu_on ? PSTR("PS:1\n") : PSTR("PS:0\n")); + SERIAL_ECHOF(powerManager.psu_on ? F("PS:1\n") : F("PS:0\n")); return; } @@ -74,13 +74,12 @@ * This code should ALWAYS be available for FULL SHUTDOWN! */ void GcodeSuite::M81() { - thermalManager.disable_all_heaters(); planner.finish_and_disable(); + thermalManager.cooldown(); print_job_timer.stop(); #if HAS_FAN - thermalManager.zero_fan_speeds(); #if ENABLED(PROBING_FANS_OFF) thermalManager.fans_paused = false; ZERO(thermalManager.saved_fan_speed); @@ -95,5 +94,5 @@ void GcodeSuite::M81() { powerManager.power_off_soon(); #endif - LCD_MESSAGEPGM_P(PSTR(MACHINE_NAME " " STR_OFF ".")); + LCD_MESSAGE_F(MACHINE_NAME " " STR_OFF "."); } diff --git a/Marlin/src/gcode/control/M999.cpp b/Marlin/src/gcode/control/M999.cpp index b7219673a3..b7d6db9f23 100644 --- a/Marlin/src/gcode/control/M999.cpp +++ b/Marlin/src/gcode/control/M999.cpp @@ -22,7 +22,7 @@ #include "../gcode.h" -#include "../../lcd/marlinui.h" // for lcd_reset_alert_level +#include "../../lcd/marlinui.h" // for ui.reset_alert_level #include "../../MarlinCore.h" // for marlin_state #include "../queue.h" // for flush_and_request_resend diff --git a/Marlin/src/gcode/eeprom/M500-M504.cpp b/Marlin/src/gcode/eeprom/M500-M504.cpp index a06e98ad1e..a1f295ebde 100644 --- a/Marlin/src/gcode/eeprom/M500-M504.cpp +++ b/Marlin/src/gcode/eeprom/M500-M504.cpp @@ -25,6 +25,11 @@ #include "../../core/serial.h" #include "../../inc/MarlinConfig.h" +#if ENABLED(CONFIGURATION_EMBEDDING) + #include "../../sd/SdBaseFile.h" + #include "../../mczip.h" +#endif + /** * M500: Store settings in EEPROM */ @@ -50,9 +55,22 @@ void GcodeSuite::M502() { /** * M503: print settings currently in memory + * + * With CONFIGURATION_EMBEDDING: + * C : Save the full Marlin configuration to SD Card as "mc.zip" */ void GcodeSuite::M503() { (void)settings.report(!parser.boolval('S', true)); + + #if ENABLED(CONFIGURATION_EMBEDDING) + if (parser.seen_test('C')) { + SdBaseFile file; + const uint16_t size = sizeof(mc_zip); + // Need to create the config size on the SD card + if (file.open("mc.zip", O_WRITE|O_CREAT) && file.write(pgm_read_ptr(mc_zip), size) != -1 && file.close()) + SERIAL_ECHO_MSG("Configuration saved as 'mc.zip'"); + } + #endif } #endif // !DISABLE_M503 diff --git a/Marlin/src/gcode/feature/L6470/M122.cpp b/Marlin/src/gcode/feature/L6470/M122.cpp index 1e5b37e4b7..4a5629b049 100644 --- a/Marlin/src/gcode/feature/L6470/M122.cpp +++ b/Marlin/src/gcode/feature/L6470/M122.cpp @@ -47,10 +47,10 @@ inline void L6470_say_status(const L64XX_axis_t axis) { } #endif SERIAL_ECHOPGM("\n...OUTPUT: "); - SERIAL_ECHOPGM_P(sh.STATUS_AXIS & STATUS_HIZ ? PSTR("OFF") : PSTR("ON ")); + SERIAL_ECHOF(sh.STATUS_AXIS & STATUS_HIZ ? F("OFF") : F("ON ")); SERIAL_ECHOPGM(" BUSY: "); echo_yes_no((sh.STATUS_AXIS & STATUS_BUSY) == 0); SERIAL_ECHOPGM(" DIR: "); - SERIAL_ECHOPGM_P((((sh.STATUS_AXIS & STATUS_DIR) >> 4) ^ L64xxManager.index_to_dir[axis]) ? PSTR("FORWARD") : PSTR("REVERSE")); + SERIAL_ECHOF((((sh.STATUS_AXIS & STATUS_DIR) >> 4) ^ L64xxManager.index_to_dir[axis]) ? F("FORWARD") : F("REVERSE")); if (sh.STATUS_AXIS_LAYOUT == L6480_STATUS_LAYOUT) { SERIAL_ECHOPGM(" Last Command: "); if (sh.STATUS_AXIS & sh.STATUS_AXIS_WRONG_CMD) SERIAL_ECHOPGM("VALID"); @@ -67,7 +67,7 @@ inline void L6470_say_status(const L64XX_axis_t axis) { SERIAL_ECHOPGM(" Last Command: "); if (!(sh.STATUS_AXIS & sh.STATUS_AXIS_WRONG_CMD)) SERIAL_ECHOPGM("IN"); SERIAL_ECHOPGM("VALID "); - SERIAL_ECHOPGM_P(sh.STATUS_AXIS & sh.STATUS_AXIS_NOTPERF_CMD ? PSTR("COMPLETED ") : PSTR("Not PERFORMED")); + SERIAL_ECHOF(sh.STATUS_AXIS & sh.STATUS_AXIS_NOTPERF_CMD ? F("COMPLETED ") : F("Not PERFORMED")); SERIAL_ECHOPGM("\n...THERMAL: ", !(sh.STATUS_AXIS & sh.STATUS_AXIS_TH_SD) ? "SHUTDOWN " : !(sh.STATUS_AXIS & sh.STATUS_AXIS_TH_WRN) ? "WARNING " : "OK "); } SERIAL_ECHOPGM(" OVERCURRENT:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_OCD) == 0); diff --git a/Marlin/src/gcode/feature/L6470/M906.cpp b/Marlin/src/gcode/feature/L6470/M906.cpp index bab355fe38..d058ce5501 100644 --- a/Marlin/src/gcode/feature/L6470/M906.cpp +++ b/Marlin/src/gcode/feature/L6470/M906.cpp @@ -107,7 +107,7 @@ void L64XX_report_current(L64XX &motor, const L64XX_axis_t axis) { SERIAL_ECHOPGM("...MicroSteps: ", MicroSteps, " ADC_OUT: ", L6470_ADC_out); SERIAL_ECHOPGM(" Vs_compensation: "); - SERIAL_ECHOPGM_P((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_EN_VSCOMP) ? PSTR("ENABLED ") : PSTR("DISABLED")); + SERIAL_ECHOF((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_EN_VSCOMP) ? F("ENABLED ") : F("DISABLED")); SERIAL_ECHOLNPGM(" Compensation coefficient: ~", comp_coef * 0.01f); SERIAL_ECHOPGM("...KVAL_HOLD: ", motor.GetParam(L6470_KVAL_HOLD), diff --git a/Marlin/src/gcode/feature/L6470/M916-918.cpp b/Marlin/src/gcode/feature/L6470/M916-918.cpp index ad0a91111d..8d614603ed 100644 --- a/Marlin/src/gcode/feature/L6470/M916-918.cpp +++ b/Marlin/src/gcode/feature/L6470/M916-918.cpp @@ -138,10 +138,10 @@ void GcodeSuite::M916() { do { // turn the motor(s) both directions sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(final_feedrate)); - gcode.process_subcommands_now_P(gcode_string); + process_subcommands_now(gcode_string); sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(final_feedrate)); - gcode.process_subcommands_now_P(gcode_string); + process_subcommands_now(gcode_string); // get the status after the motors have stopped planner.synchronize(); @@ -266,10 +266,10 @@ void GcodeSuite::M917() { DEBUG_ECHOLNPGM(" OCD threshold : ", (OCD_TH_val + 1) * 375); sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(final_feedrate)); - gcode.process_subcommands_now_P(gcode_string); + process_subcommands_now(gcode_string); sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(final_feedrate)); - gcode.process_subcommands_now_P(gcode_string); + process_subcommands_now(gcode_string); planner.synchronize(); @@ -308,7 +308,7 @@ void GcodeSuite::M917() { L64xxManager.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold); } DEBUG_ECHOLNPGM("."); - gcode.reset_stepper_timeout(); // keep steppers powered + reset_stepper_timeout(); // keep steppers powered watchdog_refresh(); safe_delay(5000); status_composite_temp = 0; @@ -615,10 +615,10 @@ void GcodeSuite::M918() { DEBUG_ECHOLNPGM("...feedrate = ", current_feedrate); sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(current_feedrate)); - gcode.process_subcommands_now_P(gcode_string); + process_subcommands_now(gcode_string); sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(current_feedrate)); - gcode.process_subcommands_now_P(gcode_string); + process_subcommands_now(gcode_string); planner.synchronize(); diff --git a/Marlin/src/gcode/feature/adc/M3426.cpp b/Marlin/src/gcode/feature/adc/M3426.cpp new file mode 100644 index 0000000000..8205fa01f2 --- /dev/null +++ b/Marlin/src/gcode/feature/adc/M3426.cpp @@ -0,0 +1,63 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "../../../inc/MarlinConfig.h" + +#if ENABLED(HAS_MCP3426_ADC) + +#include "../../gcode.h" + +#include "../../../feature/adc/adc_mcp3426.h" + +/** + * M3426: Read 16 bit (signed) value from I2C MCP3426 ADC device + * + * M3426 C channel 1 or 2 + * M3426 G gain 1, 2, 4 or 8 + * M3426 I 0 or 1, invert reply + */ +void GcodeSuite::M3426() { + uint8_t channel = parser.byteval('C', 1), // Select the channel 1 or 2 + gain = parser.byteval('G', 1); + const bool inverted = parser.byteval('I') == 1; + + if (channel <= 2 && (gain == 1 || gain == 2 || gain == 4 || gain == 8)) { + int16_t result = mcp3426.ReadValue(channel, gain); + + if (mcp3426.Error == false) { + if (inverted) { + // Should we invert the reading (32767 - ADC value) ? + // Caters to end devices that expect values to increase when in reality they decrease. + // e.g., A pressure sensor in a vacuum when the end device expects a positive pressure. + result = INT16_MAX - result; + } + //SERIAL_ECHOPGM(STR_OK); + SERIAL_ECHOLNPGM("V:", result, " C:", channel, " G:", gain, " I:", inverted ? 1 : 0); + } + else + SERIAL_ERROR_MSG("MCP342X i2c error"); + } + else + SERIAL_ERROR_MSG("MCP342X Bad request"); +} + +#endif // HAS_MCP3426_ADC diff --git a/Marlin/src/gcode/feature/advance/M900.cpp b/Marlin/src/gcode/feature/advance/M900.cpp index 4ed601bbe8..054ea3617f 100644 --- a/Marlin/src/gcode/feature/advance/M900.cpp +++ b/Marlin/src/gcode/feature/advance/M900.cpp @@ -145,7 +145,7 @@ void GcodeSuite::M900() { } void GcodeSuite::M900_report(const bool forReplay/*=true*/) { - report_heading(forReplay, PSTR(STR_LINEAR_ADVANCE)); + report_heading(forReplay, F(STR_LINEAR_ADVANCE)); #if EXTRUDERS < 2 report_echo_start(forReplay); SERIAL_ECHOLNPGM(" M900 K", planner.extruder_advance_K[0]); diff --git a/Marlin/src/gcode/feature/clean/G12.cpp b/Marlin/src/gcode/feature/clean/G12.cpp index b19932eb98..a0b87b1abc 100644 --- a/Marlin/src/gcode/feature/clean/G12.cpp +++ b/Marlin/src/gcode/feature/clean/G12.cpp @@ -50,7 +50,7 @@ void GcodeSuite::G12() { #ifdef WIPE_SEQUENCE_COMMANDS if (!parser.seen_any()) { - gcode.process_subcommands_now_P(PSTR(WIPE_SEQUENCE_COMMANDS)); + process_subcommands_now(F(WIPE_SEQUENCE_COMMANDS)); return; } #endif diff --git a/Marlin/src/gcode/feature/controllerfan/M710.cpp b/Marlin/src/gcode/feature/controllerfan/M710.cpp index eede16b5bd..b98d88845d 100644 --- a/Marlin/src/gcode/feature/controllerfan/M710.cpp +++ b/Marlin/src/gcode/feature/controllerfan/M710.cpp @@ -67,7 +67,7 @@ void GcodeSuite::M710() { } void GcodeSuite::M710_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_CONTROLLER_FAN)); + report_heading_etc(forReplay, F(STR_CONTROLLER_FAN)); SERIAL_ECHOLNPGM(" M710" " S", int(controllerFan.settings.active_speed), " I", int(controllerFan.settings.idle_speed), diff --git a/Marlin/src/gcode/feature/digipot/M907-M910.cpp b/Marlin/src/gcode/feature/digipot/M907-M910.cpp index a0b5c48e82..757cffd473 100644 --- a/Marlin/src/gcode/feature/digipot/M907-M910.cpp +++ b/Marlin/src/gcode/feature/digipot/M907-M910.cpp @@ -100,7 +100,7 @@ void GcodeSuite::M907() { #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM void GcodeSuite::M907_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_STEPPER_MOTOR_CURRENTS)); + report_heading_etc(forReplay, F(STR_STEPPER_MOTOR_CURRENTS)); #if HAS_MOTOR_CURRENT_PWM SERIAL_ECHOLNPGM_P( // PWM-based has 3 values: PSTR(" M907 X"), stepper.motor_current_setting[0] // X and Y diff --git a/Marlin/src/gcode/feature/fwretract/M207-M209.cpp b/Marlin/src/gcode/feature/fwretract/M207-M209.cpp index 040a09a8e0..173c2894dc 100644 --- a/Marlin/src/gcode/feature/fwretract/M207-M209.cpp +++ b/Marlin/src/gcode/feature/fwretract/M207-M209.cpp @@ -38,7 +38,7 @@ void GcodeSuite::M207() { fwretract.M207(); } void GcodeSuite::M207_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_RETRACT_S_F_Z)); + report_heading_etc(forReplay, F(STR_RETRACT_S_F_Z)); fwretract.M207_report(); } @@ -53,7 +53,7 @@ void GcodeSuite::M207_report(const bool forReplay/*=true*/) { void GcodeSuite::M208() { fwretract.M208(); } void GcodeSuite::M208_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_RECOVER_S_F)); + report_heading_etc(forReplay, F(STR_RECOVER_S_F)); fwretract.M208_report(); } @@ -68,7 +68,7 @@ void GcodeSuite::M208_report(const bool forReplay/*=true*/) { void GcodeSuite::M209() { fwretract.M209(); } void GcodeSuite::M209_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, PSTR(STR_AUTO_RETRACT_S)); + report_heading_etc(forReplay, F(STR_AUTO_RETRACT_S)); fwretract.M209_report(); } diff --git a/Marlin/src/gcode/feature/i2c/M260_M261.cpp b/Marlin/src/gcode/feature/i2c/M260_M261.cpp index 438d1527f5..e978fb5048 100644 --- a/Marlin/src/gcode/feature/i2c/M260_M261.cpp +++ b/Marlin/src/gcode/feature/i2c/M260_M261.cpp @@ -60,15 +60,16 @@ void GcodeSuite::M260() { /** * M261: Request X bytes from I2C slave device * - * Usage: M261 A B + * Usage: M261 A B S