Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1bbae4676f | |||
| 6802260626 | |||
| ed34dbb4b6 | |||
| 721209a898 | |||
| 7c6dfc4ec2 | |||
| 62008024cd | |||
| e09672edac | |||
| 825e0b800c | |||
| 0f489c6584 | |||
| 6ae43349f7 | |||
| f6b52a80d6 | |||
| 38711ed5e6 | |||
| 5a714c76b8 | |||
| 8c1a547f2a | |||
| 16be10d2f3 | |||
| d4dde255ad | |||
| b5c7712531 | |||
| 8dc8361f02 | |||
| 433f3ba3ab | |||
| 78e2aa6eac | |||
| 54da1da13f | |||
| 544765f1a1 | |||
| f261fea59a | |||
| 00785eb14e | |||
| 6713185aea | |||
| 298c3f2344 | |||
| 82c1171028 | |||
| 122b01d253 | |||
| 42e4321b6f | |||
| 87faa73bee | |||
| 666e8c0116 | |||
| 5a0332ddee | |||
| e7c9cf3e1d | |||
| 6710616a09 | |||
| 2064c83c66 | |||
| 2e97ad1f4b | |||
| 4f85f88ae3 |
+49
-46
@@ -135,18 +135,18 @@
|
||||
* Options: A4988, A5984, DRV8825, LV8729, TB6560, TB6600, TMC2100,
|
||||
* TMC2130, TMC2130_STANDALONE, TMC2160, TMC2160_STANDALONE,
|
||||
* TMC2208, TMC2208_STANDALONE, TMC2209, TMC2209_STANDALONE,
|
||||
* TMC2660, TMC2660_STANDALONE, TMC5130, TMC5130_STANDALONE,
|
||||
* TMC5160, TMC5160_STANDALONE
|
||||
* :['A4988', 'A5984', 'DRV8825', 'LV8729', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
|
||||
* TMC26X, TMC26X_STANDALONE, TMC2660, TMC2660_STANDALONE,
|
||||
* TMC5130, TMC5130_STANDALONE, TMC5160, TMC5160_STANDALONE
|
||||
* :['A4988', 'A5984', 'DRV8825', 'LV8729', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC26X', 'TMC26X_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
|
||||
*/
|
||||
#define X_DRIVER_TYPE TB6600
|
||||
#define Y_DRIVER_TYPE TB6600
|
||||
#define Z_DRIVER_TYPE TB6600
|
||||
#define X_DRIVER_TYPE TMC5160
|
||||
#define Y_DRIVER_TYPE TMC5160
|
||||
#define Z_DRIVER_TYPE TMC5160_STANDALONE
|
||||
//#define X2_DRIVER_TYPE A4988
|
||||
#define Y2_DRIVER_TYPE TB6600
|
||||
#define Z2_DRIVER_TYPE TB6600
|
||||
#define Z3_DRIVER_TYPE TB6600
|
||||
#define Z4_DRIVER_TYPE TB6600
|
||||
#define Y2_DRIVER_TYPE TMC5160
|
||||
#define Z2_DRIVER_TYPE TMC5160_STANDALONE
|
||||
#define Z3_DRIVER_TYPE TMC5160_STANDALONE
|
||||
#define Z4_DRIVER_TYPE TMC5160_STANDALONE
|
||||
//#define I_DRIVER_TYPE A4988
|
||||
//#define J_DRIVER_TYPE A4988
|
||||
//#define K_DRIVER_TYPE A4988
|
||||
@@ -401,18 +401,18 @@
|
||||
//#define PS_OFF_SOUND // Beep 1s when power off
|
||||
#define PSU_ACTIVE_STATE HIGH // Set 'LOW' for ATX, 'HIGH' for X-Box
|
||||
|
||||
//#define PSU_DEFAULT_OFF // Keep power off until enabled directly with M80
|
||||
//#define PSU_POWERUP_DELAY 250 // (ms) Delay for the PSU to warm up to full power
|
||||
//#define LED_POWEROFF_TIMEOUT 10000 // (ms) Turn off LEDs after power-off, with this amount of delay
|
||||
#define PSU_DEFAULT_OFF // Keep power off until enabled directly with M80
|
||||
#define PSU_POWERUP_DELAY 750 // (ms) Delay for the PSU to warm up to full power
|
||||
//#define LED_POWEROFF_TIMEOUT 10000 // (ms) Turn off LEDs after power-off, with this amount of delay
|
||||
|
||||
//#define PSU_OFF_REDUNDANT // Second pin for redundant power control
|
||||
//#define PSU_OFF_REDUNDANT_INVERTED // Redundant pin state is the inverse of PSU_ACTIVE_STATE
|
||||
#define PSU_OFF_REDUNDANT // Second pin for redundant power control
|
||||
//#define PSU_OFF_REDUNDANT_OPPOSING // Redundant pin works opposite standard pin
|
||||
#define PS_ON_PIN P4_28 // Redundant Pin
|
||||
#define PS_ON1_PIN P1_03 // Redundant Pin
|
||||
|
||||
//#define PS_ON1_PIN 6 // Redundant pin required to enable power in combination with PS_ON_PIN
|
||||
|
||||
//#define PS_ON_EDM_PIN 8 // External Device Monitoring pins for external power control relay feedback. Fault on mismatch.
|
||||
//#define PS_ON1_EDM_PIN 9
|
||||
#define PS_EDM_RESPONSE 250 // (ms) Time to allow for relay action
|
||||
#define PS_ON_EDM_PIN P4_29 // EDM Pins to monitor feedback on external power control relay. Fault on mismatch.
|
||||
#define PS_ON1_EDM_PIN P1_17
|
||||
#define PS_EDM_RESPONSE 1000 // Time in MS to allow for relay action
|
||||
|
||||
#define PSU_OFF_REDUNDANT // Second pin for redundant power control
|
||||
//#define PSU_OFF_REDUNDANT_OPPOSING // Redundant pin works opposite standard pin
|
||||
@@ -681,7 +681,7 @@
|
||||
* MPCTEMP : Predictive Model temperature control. (~1.8K without auto-tune)
|
||||
*/
|
||||
#define PIDTEMP // See the PID Tuning Guide at https://reprap.org/wiki/PID_Tuning
|
||||
//#define MPCTEMP // See https://marlinfw.org/docs/features/model_predictive_control.html
|
||||
//#define MPCTEMP // ** EXPERIMENTAL ** See https://marlinfw.org/docs/features/model_predictive_control.html
|
||||
|
||||
#define PID_MAX 255 // Limit hotend current while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
|
||||
#define PID_K1 0.95 // Smoothing factor within any PID loop
|
||||
@@ -1024,6 +1024,9 @@
|
||||
// Radius around the center where the arm cannot reach
|
||||
#define MIDDLE_DEAD_ZONE_R 0 // (mm)
|
||||
|
||||
#define THETA_HOMING_OFFSET 0 // Calculated from Calibration Guide and M360 / M114. See https://www.morgan3dp.com/morgan-calibration-guide/
|
||||
#define PSI_HOMING_OFFSET 0 // Calculated from Calibration Guide and M364 / M114. See https://www.morgan3dp.com/morgan-calibration-guide/
|
||||
|
||||
#elif ENABLED(MP_SCARA)
|
||||
|
||||
#define SCARA_OFFSET_THETA1 12 // degrees
|
||||
@@ -1042,19 +1045,23 @@
|
||||
#define DEFAULT_SEGMENTS_PER_SECOND 200
|
||||
|
||||
// Length of inner and outer support arms. Measure arm lengths precisely.
|
||||
#define TPARA_LINKAGE_1 120 // (mm)
|
||||
#define TPARA_LINKAGE_2 120 // (mm)
|
||||
#define TPARA_LINKAGE_1 120 // (mm)
|
||||
#define TPARA_LINKAGE_2 120 // (mm)
|
||||
|
||||
// TPARA tower offset (position of Tower relative to bed zero position)
|
||||
// This needs to be reasonably accurate as it defines the printbed position in the TPARA space.
|
||||
#define TPARA_OFFSET_X 0 // (mm)
|
||||
#define TPARA_OFFSET_Y 0 // (mm)
|
||||
#define TPARA_OFFSET_Z 0 // (mm)
|
||||
// SCARA tower offset (position of Tower relative to bed zero position)
|
||||
// This needs to be reasonably accurate as it defines the printbed position in the SCARA space.
|
||||
#define TPARA_OFFSET_X 0 // (mm)
|
||||
#define TPARA_OFFSET_Y 0 // (mm)
|
||||
#define TPARA_OFFSET_Z 0 // (mm)
|
||||
|
||||
#define FEEDRATE_SCALING // Convert XY feedrate from mm/s to degrees/s on the fly
|
||||
|
||||
// Radius around the center where the arm cannot reach
|
||||
#define MIDDLE_DEAD_ZONE_R 0 // (mm)
|
||||
|
||||
// Calculated from Calibration Guide and M360 / M114. See https://www.morgan3dp.com/morgan-calibration-guide/
|
||||
#define THETA_HOMING_OFFSET 0
|
||||
#define PSI_HOMING_OFFSET 0
|
||||
#endif
|
||||
|
||||
// @section polar
|
||||
@@ -1302,7 +1309,6 @@
|
||||
#define DEFAULT_XJERK 10.0
|
||||
#define DEFAULT_YJERK 10.0
|
||||
#define DEFAULT_ZJERK 0.3
|
||||
#define DEFAULT_EJERK 5.0
|
||||
//#define DEFAULT_IJERK 0.3
|
||||
//#define DEFAULT_JJERK 0.3
|
||||
//#define DEFAULT_KJERK 0.3
|
||||
@@ -1318,6 +1324,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DEFAULT_EJERK 5.0 // May be used by Linear Advance
|
||||
|
||||
/**
|
||||
* Junction Deviation Factor
|
||||
*
|
||||
@@ -1340,6 +1348,11 @@
|
||||
* See https://github.com/synthetos/TinyG/wiki/Jerk-Controlled-Motion-Explained
|
||||
*/
|
||||
#define S_CURVE_ACCELERATION
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
// Uncomment to use 4th instead of 6th order motion curve
|
||||
#define S_CURVE_FACTOR 0.35 // Initial and final acceleration factor, ideally 0.1 to 0.4
|
||||
// Shouldn't generally require tuning
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
//============================= Z Probe Options =============================
|
||||
@@ -1457,17 +1470,6 @@
|
||||
//#define BD_SENSOR_PROBE_NO_STOP // Probe bed without stopping at each probe point
|
||||
#endif
|
||||
|
||||
/**
|
||||
* BIQU MicroProbe
|
||||
*
|
||||
* A lightweight, solenoid-driven probe.
|
||||
* For information about this sensor https://github.com/bigtreetech/MicroProbe
|
||||
*
|
||||
* Also requires: PROBE_ENABLE_DISABLE
|
||||
*/
|
||||
//#define BIQU_MICROPROBE_V1 // Triggers HIGH
|
||||
//#define BIQU_MICROPROBE_V2 // Triggers LOW
|
||||
|
||||
// A probe that is deployed and stowed with a solenoid pin (SOL1_PIN)
|
||||
//#define SOLENOID_PROBE
|
||||
|
||||
@@ -2227,7 +2229,7 @@
|
||||
#if ENABLED(LCD_BED_TRAMMING)
|
||||
#define BED_TRAMMING_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
|
||||
#define BED_TRAMMING_HEIGHT 0.0 // (mm) Z height of nozzle at tramming points
|
||||
#define BED_TRAMMING_Z_HOP 4.0 // (mm) Z raise between tramming points
|
||||
#define BED_TRAMMING_Z_HOP 4.0 // (mm) Z height of nozzle between tramming points
|
||||
//#define BED_TRAMMING_INCLUDE_CENTER // Move to the center after the last corner
|
||||
//#define BED_TRAMMING_USE_PROBE
|
||||
#if ENABLED(BED_TRAMMING_USE_PROBE)
|
||||
@@ -2367,12 +2369,12 @@
|
||||
* M501 - Read settings from EEPROM. (i.e., Throw away unsaved changes)
|
||||
* M502 - Revert settings to "factory" defaults. (Follow with M500 to init the EEPROM.)
|
||||
*/
|
||||
//#define EEPROM_SETTINGS // Persistent storage with M500 and M501
|
||||
#define EEPROM_SETTINGS // Persistent storage with M500 and M501
|
||||
//#define DISABLE_M503 // Saves ~2700 bytes of flash. Disable for release!
|
||||
#define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save PROGMEM.
|
||||
#define EEPROM_BOOT_SILENT // Keep M503 quiet and only give errors during first load
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
//#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors.
|
||||
#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors.
|
||||
//#define EEPROM_INIT_NOW // Init EEPROM on first boot after a new build.
|
||||
#endif
|
||||
|
||||
@@ -2645,9 +2647,9 @@
|
||||
#define DISPLAY_CHARSET_HD44780 JAPANESE
|
||||
|
||||
/**
|
||||
* Info Screen Style (0:Classic, 1:Průša, 2:CNC)
|
||||
* Info Screen Style (0:Classic, 1:Průša)
|
||||
*
|
||||
* :[0:'Classic', 1:'Průša', 2:'CNC']
|
||||
* :[0:'Classic', 1:'Průša']
|
||||
*/
|
||||
#define LCD_INFO_SCREEN_STYLE 0
|
||||
|
||||
@@ -3048,7 +3050,7 @@
|
||||
|
||||
//
|
||||
// Factory display for Creality CR-10 / CR-7 / Ender-3
|
||||
// https://marlinfw.org/docs/hardware/controllers.html#cr10_stockdisplay
|
||||
// https://www.aliexpress.com/item/32833148327.html
|
||||
//
|
||||
// Connect to EXP1 on RAMPS and compatible boards.
|
||||
//
|
||||
@@ -3425,6 +3427,7 @@
|
||||
#define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus
|
||||
|
||||
//#define DISABLE_ENCODER // Disable the click encoder, if any
|
||||
//#define TOUCH_IDLE_SLEEP_MINS 5 // (minutes) Display Sleep after a period of inactivity. Set with M255 S.
|
||||
|
||||
#define TOUCH_SCREEN_CALIBRATION
|
||||
|
||||
|
||||
+55
-59
@@ -459,7 +459,7 @@
|
||||
#define PID_FAN_SCALING_LIN_FACTOR (PID_FAN_SCALING_AT_FULL_SPEED-DEFAULT_Kf)/255.0
|
||||
|
||||
#else
|
||||
#define PID_FAN_SCALING_LIN_FACTOR (0) // Power-loss due to cooling = Kf * (fan_speed)
|
||||
#define PID_FAN_SCALING_LIN_FACTOR (0) // Power loss due to cooling = Kf * (fan_speed)
|
||||
#define DEFAULT_Kf 10 // A constant value added to the PID-tuner
|
||||
#define PID_FAN_SCALING_MIN_SPEED 10 // Minimum fan speed at which to enable PID_FAN_SCALING
|
||||
#endif
|
||||
@@ -1185,32 +1185,33 @@
|
||||
* Zero Vibration (ZV) Input Shaping for X and/or Y movements.
|
||||
*
|
||||
* This option uses a lot of SRAM for the step buffer. The buffer size is
|
||||
* calculated automatically from SHAPING_FREQ_[XYZ], DEFAULT_AXIS_STEPS_PER_UNIT,
|
||||
* calculated automatically from SHAPING_FREQ_[XY], DEFAULT_AXIS_STEPS_PER_UNIT,
|
||||
* DEFAULT_MAX_FEEDRATE and ADAPTIVE_STEP_SMOOTHING. The default calculation can
|
||||
* be overridden by setting SHAPING_MIN_FREQ and/or SHAPING_MAX_FEEDRATE.
|
||||
* The higher the frequency and the lower the feedrate, the smaller the buffer.
|
||||
* If the buffer is too small at runtime, input shaping will have reduced
|
||||
* effectiveness during high speed movements.
|
||||
*
|
||||
* Tune with M593 D<factor> F<frequency>
|
||||
* Tune with M593 D<factor> F<frequency>:
|
||||
*
|
||||
* D<factor> Set the zeta/damping factor. If axes (X, Y, etc.) are not specified, set for all axes.
|
||||
* F<frequency> Set the frequency. If axes (X, Y, etc.) are not specified, set for all axes.
|
||||
* T[map] Input Shaping type, 0:ZV, 1:EI, 2:2H EI (not implemented yet)
|
||||
* X<1> Set the given parameters only for the X axis.
|
||||
* Y<1> Set the given parameters only for the Y axis.
|
||||
*/
|
||||
//#define INPUT_SHAPING_X
|
||||
//#define INPUT_SHAPING_Y
|
||||
//#define INPUT_SHAPING_Z
|
||||
#if ANY(INPUT_SHAPING_X, INPUT_SHAPING_Y, INPUT_SHAPING_Z)
|
||||
#if ANY(INPUT_SHAPING_X, INPUT_SHAPING_Y)
|
||||
#if ENABLED(INPUT_SHAPING_X)
|
||||
#define SHAPING_FREQ_X 40.0 // (Hz) The default dominant resonant frequency on the X axis.
|
||||
#define SHAPING_ZETA_X 0.15 // Damping ratio of the X axis (range: 0.0 = no damping to 1.0 = critical damping).
|
||||
#define SHAPING_FREQ_X 40 // (Hz) The default dominant resonant frequency on the X axis.
|
||||
#define SHAPING_ZETA_X 0.15f // Damping ratio of the X axis (range: 0.0 = no damping to 1.0 = critical damping).
|
||||
#endif
|
||||
#if ENABLED(INPUT_SHAPING_Y)
|
||||
#define SHAPING_FREQ_Y 40.0 // (Hz) The default dominant resonant frequency on the Y axis.
|
||||
#define SHAPING_ZETA_Y 0.15 // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping).
|
||||
#define SHAPING_FREQ_Y 40 // (Hz) The default dominant resonant frequency on the Y axis.
|
||||
#define SHAPING_ZETA_Y 0.15f // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping).
|
||||
#endif
|
||||
#if ENABLED(INPUT_SHAPING_Z)
|
||||
#define SHAPING_FREQ_Z 40.0 // (Hz) The default dominant resonant frequency on the Z axis.
|
||||
#define SHAPING_ZETA_Z 0.15 // Damping ratio of the Z axis (range: 0.0 = no damping to 1.0 = critical damping).
|
||||
#endif
|
||||
//#define SHAPING_MIN_FREQ 20.0 // (Hz) By default the minimum of the shaping frequencies. Override to affect SRAM usage.
|
||||
//#define SHAPING_MIN_FREQ 20 // By default the minimum of the shaping frequencies. Override to affect SRAM usage.
|
||||
//#define SHAPING_MAX_STEPRATE 10000 // By default the maximum total step rate of the shaped axes. Override to affect SRAM usage.
|
||||
//#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters.
|
||||
#endif
|
||||
@@ -1269,11 +1270,11 @@
|
||||
* XY Frequency limit
|
||||
* Reduce resonance by limiting the frequency of small zigzag infill moves.
|
||||
* See https://hydraraptor.blogspot.com/2010/12/frequency-limit.html
|
||||
* Use M201 F<freq> S<min%> to change limits at runtime.
|
||||
* Use M201 F<freq> G<min%> to change limits at runtime.
|
||||
*/
|
||||
//#define XY_FREQUENCY_LIMIT 10 // (Hz) Maximum frequency of small zigzag infill moves. Set with M201 F<hertz>.
|
||||
#ifdef XY_FREQUENCY_LIMIT
|
||||
#define XY_FREQUENCY_MIN_PERCENT 5 // (%) Minimum FR percentage to apply. Set with M201 S<min%>.
|
||||
#define XY_FREQUENCY_MIN_PERCENT 5 // (%) Minimum FR percentage to apply. Set with M201 G<min%>.
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -1385,7 +1386,7 @@
|
||||
* Multi-stepping sends steps in bursts to reduce MCU usage for high step-rates.
|
||||
* This allows higher feedrates than the MCU could otherwise support.
|
||||
*/
|
||||
#define MULTISTEPPING_LIMIT 16 //: [1, 2, 4, 8, 16, 32, 64, 128]
|
||||
#define MULTISTEPPING_LIMIT 32 //: [1, 2, 4, 8, 16, 32, 64, 128]
|
||||
|
||||
/**
|
||||
* Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies
|
||||
@@ -1393,7 +1394,7 @@
|
||||
* vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the
|
||||
* lowest stepping frequencies.
|
||||
*/
|
||||
//#define ADAPTIVE_STEP_SMOOTHING
|
||||
#define ADAPTIVE_STEP_SMOOTHING
|
||||
|
||||
/**
|
||||
* Custom Microstepping
|
||||
@@ -1473,7 +1474,6 @@
|
||||
#if IS_ULTIPANEL
|
||||
#define MANUAL_E_MOVES_RELATIVE // Display extruder move distance rather than "position"
|
||||
#define ULTIPANEL_FEEDMULTIPLY // Encoder sets the feedrate multiplier on the Status Screen
|
||||
//#define ULTIPANEL_FLOWPERCENT // Encoder sets the flow percentage on the Status Screen
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1539,7 +1539,6 @@
|
||||
* Axis moves <= 1/2 the axis length and Extruder moves <= EXTRUDE_MAXLENGTH
|
||||
* will be shown in the move submenus.
|
||||
*/
|
||||
|
||||
#define MANUAL_MOVE_DISTANCE_MM 10, 1.0, 0.1 // (mm)
|
||||
//#define MANUAL_MOVE_DISTANCE_MM 100, 50, 10, 1.0, 0.1 // (mm)
|
||||
//#define MANUAL_MOVE_DISTANCE_MM 500, 100, 50, 10, 1.0, 0.1 // (mm)
|
||||
@@ -1583,7 +1582,7 @@
|
||||
#if HAS_MARLINUI_U8GLIB
|
||||
#define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~3260 (or ~940) bytes of flash.
|
||||
#endif
|
||||
#if ANY(HAS_MARLINUI_U8GLIB, TOUCH_UI_FTDI_EVE, HAS_MARLINUI_HD44780)
|
||||
#if ANY(HAS_MARLINUI_U8GLIB, TOUCH_UI_FTDI_EVE)
|
||||
//#define SHOW_CUSTOM_BOOTSCREEN // Show the bitmap in Marlin/_Bootscreen.h on startup.
|
||||
#endif
|
||||
#endif
|
||||
@@ -1744,26 +1743,21 @@
|
||||
*/
|
||||
//#define POWER_LOSS_RECOVERY
|
||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||
#define PLR_ENABLED_DEFAULT false // Power-Loss Recovery enabled by default. (Set with 'M413 Sn' & M500)
|
||||
#define PLR_ENABLED_DEFAULT false // Power Loss Recovery enabled by default. (Set with 'M413 Sn' & M500)
|
||||
//#define PLR_BED_THRESHOLD BED_MAXTEMP // (°C) Skip user confirmation at or above this bed temperature (0 to disable)
|
||||
|
||||
//#define POWER_LOSS_PIN 44 // Pin to detect power-loss. Set to -1 to disable default pin on boards without module, or comment to use board default.
|
||||
//#define POWER_LOSS_STATE HIGH // State of pin indicating power-loss
|
||||
//#define BACKUP_POWER_SUPPLY // Backup power / UPS to move the steppers on power loss
|
||||
//#define POWER_LOSS_ZRAISE 2 // (mm) Z axis raise on resume (on power loss with UPS)
|
||||
//#define POWER_LOSS_PIN 44 // Pin to detect power loss. Set to -1 to disable default pin on boards without module.
|
||||
//#define POWER_LOSS_STATE HIGH // State of pin indicating power loss
|
||||
//#define POWER_LOSS_PULLUP // Set pullup / pulldown as appropriate for your sensor
|
||||
//#define POWER_LOSS_PULLDOWN
|
||||
|
||||
//#define POWER_LOSS_ZRAISE 2 // (mm) Z axis raise on resume (on power-loss with UPS)
|
||||
//#define POWER_LOSS_PURGE_LEN 20 // (mm) Length of filament to purge on resume
|
||||
//#define POWER_LOSS_PURGE_LEN 20 // (mm) Length of filament to purge on resume
|
||||
//#define POWER_LOSS_RETRACT_LEN 10 // (mm) Length of filament to retract on fail. Requires backup power.
|
||||
|
||||
// Without a POWER_LOSS_PIN the following option helps reduce wear on the SD card,
|
||||
// especially with "vase mode" printing. Set too high and vases cannot be continued.
|
||||
#define POWER_LOSS_MIN_Z_CHANGE 0.05 // (mm) Minimum Z change before saving power-loss data
|
||||
|
||||
//#define BACKUP_POWER_SUPPLY // Backup power / UPS to move the steppers on power-loss
|
||||
#if ENABLED(BACKUP_POWER_SUPPLY)
|
||||
//#define POWER_LOSS_RETRACT_LEN 10 // (mm) Length of filament to retract on fail
|
||||
#endif
|
||||
|
||||
// Enable if Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
|
||||
//#define POWER_LOSS_RECOVER_ZHOME
|
||||
#if ENABLED(POWER_LOSS_RECOVER_ZHOME)
|
||||
@@ -1969,6 +1963,17 @@
|
||||
// Western only. Not available for Cyrillic, Kana, Turkish, Greek, or Chinese.
|
||||
//#define USE_SMALL_INFOFONT
|
||||
|
||||
/**
|
||||
* Graphical Display Sleep
|
||||
*
|
||||
* The U8G library provides sleep / wake functions for SH1106, SSD1306,
|
||||
* SSD1309, and some other DOGM displays.
|
||||
* Enable this option to save energy and prevent OLED pixel burn-in.
|
||||
* Adds the menu item Configuration > LCD Timeout (m) to set a wait period
|
||||
* from 0 (disabled) to 99 minutes.
|
||||
*/
|
||||
//#define DISPLAY_SLEEP_MINUTES 2 // (minutes) Timeout before turning off the screen. Set with M255 S.
|
||||
|
||||
/**
|
||||
* ST7920-based LCDs can emulate a 16 x 4 character display using
|
||||
* the ST7920 character-generator for very fast screen updates.
|
||||
@@ -2217,20 +2222,13 @@
|
||||
//#define TFT_BTOKMENU_COLOR 0x145F // 00010 100010 11111 Cyan
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Display Sleep
|
||||
* Enable this option to save energy and prevent OLED pixel burn-in.
|
||||
*/
|
||||
//#define DISPLAY_SLEEP_MINUTES 2 // (minutes) Timeout before turning off the screen
|
||||
|
||||
/**
|
||||
* LCD Backlight Timeout
|
||||
* Requires a display with a controllable backlight
|
||||
*/
|
||||
//
|
||||
// LCD Backlight Timeout
|
||||
// Requires a display with a controllable backlight
|
||||
//
|
||||
//#define LCD_BACKLIGHT_TIMEOUT_MINS 1 // (minutes) Timeout before turning off the backlight
|
||||
|
||||
#if defined(DISPLAY_SLEEP_MINUTES) || defined(LCD_BACKLIGHT_TIMEOUT_MINS)
|
||||
#define EDITABLE_DISPLAY_TIMEOUT // Edit sleep / backlight timeout with M255 S<minutes> and a menu item
|
||||
#define EDITABLE_DISPLAY_TIMEOUT // Edit timeout with M255 S<minutes> and a menu item
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -2566,7 +2564,7 @@
|
||||
*
|
||||
* Override the default value based on the driver type set in Configuration.h.
|
||||
*/
|
||||
#define MINIMUM_STEPPER_PULSE 10
|
||||
//#define MINIMUM_STEPPER_PULSE 5
|
||||
|
||||
/**
|
||||
* Maximum stepping rate (in Hz) the stepper driver allows
|
||||
@@ -2580,7 +2578,7 @@
|
||||
*
|
||||
* Override the default value based on the driver type set in Configuration.h.
|
||||
*/
|
||||
#define MAXIMUM_STEPPER_RATE 150000
|
||||
//#define MAXIMUM_STEPPER_RATE 150000
|
||||
|
||||
// @section temperature
|
||||
|
||||
@@ -2697,7 +2695,7 @@
|
||||
* This feature is EXPERIMENTAL so use with caution and test thoroughly.
|
||||
* Enable this option to receive data on the serial ports via the onboard DMA
|
||||
* controller for more stable and reliable high-speed serial communication.
|
||||
* Support is currently limited to some STM32 MCUs and all HC32 MCUs.
|
||||
* Only some STM32 MCUs are currently supported.
|
||||
* Note: This has no effect on emulated USB serial ports.
|
||||
*/
|
||||
//#define SERIAL_DMA
|
||||
@@ -2952,12 +2950,15 @@
|
||||
* Some boards have simple jumper connections! See your board's documentation.
|
||||
* - These drivers can also be used with Hardware Serial.
|
||||
*
|
||||
* The TMC26XStepper library is required for TMC26X stepper drivers.
|
||||
* https://github.com/MarlinFirmware/TMC26XStepper
|
||||
*
|
||||
* The TMCStepper library is required for other TMC stepper drivers.
|
||||
* https://github.com/teemuatlut/TMCStepper
|
||||
*
|
||||
* @section tmc/config
|
||||
*/
|
||||
#if HAS_TRINAMIC_CONFIG
|
||||
#if HAS_TRINAMIC_CONFIG || HAS_TMC26X
|
||||
|
||||
#define HOLD_MULTIPLIER 0.7 // Scales down the holding current from run current
|
||||
|
||||
@@ -2971,7 +2972,7 @@
|
||||
#define X_CURRENT 800 // (mA) RMS current. Multiply by 1.414 for peak current.
|
||||
#define X_CURRENT_HOME X_CURRENT // (mA) RMS current for sensorless homing
|
||||
#define X_MICROSTEPS 16 // 0..256
|
||||
#define X_RSENSE 0.022
|
||||
#define X_RSENSE 0.022 // Multiplied x1000 for TMC26X
|
||||
#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
|
||||
@@ -3464,7 +3465,7 @@
|
||||
*/
|
||||
#define TMC_ADV() { }
|
||||
|
||||
#endif // HAS_TRINAMIC_CONFIG
|
||||
#endif // HAS_TRINAMIC_CONFIG || HAS_TMC26X
|
||||
|
||||
// @section i2cbus
|
||||
|
||||
@@ -3557,7 +3558,7 @@
|
||||
* Add the M3, M4, and M5 commands to turn the spindle/laser on and off, and
|
||||
* to set spindle speed, spindle direction, and laser power.
|
||||
*
|
||||
* SuperPID is a router/spindle speed controller used in the CNC milling community.
|
||||
* SuperPid is a router/spindle speed controller used in the CNC milling community.
|
||||
* Marlin can be used to turn the spindle on and off. It can also be used to set
|
||||
* the spindle speed from 5,000 to 30,000 RPM.
|
||||
*
|
||||
@@ -4260,8 +4261,7 @@
|
||||
|
||||
/**
|
||||
* Instant freeze / unfreeze functionality
|
||||
* Potentially useful for rapid stop that allows being resumed. Halts stepper movement.
|
||||
* Note this does NOT pause spindles, lasers, fans, heaters or any other auxiliary device.
|
||||
* Potentially useful for emergency stop that allows being resumed.
|
||||
* @section interface
|
||||
*/
|
||||
//#define FREEZE_FEATURE
|
||||
@@ -4308,7 +4308,6 @@
|
||||
// See class CodeProfiler.
|
||||
//#define MAX7219_DEBUG_MULTISTEPPING 6 // Show multi-stepping 1 to 128 on this LED matrix row.
|
||||
//#define MAX7219_DEBUG_SLOWDOWN 6 // Count (mod 16) how many times SLOWDOWN has reduced print speed.
|
||||
//#define MAX7219_REINIT_ON_POWERUP // Re-initialize MAX7129 when power supply turns on
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -4342,7 +4341,7 @@
|
||||
* Extras for an ESP32-based motherboard with WIFISUPPORT
|
||||
* These options don't apply to add-on WiFi modules based on ESP32 WiFi101.
|
||||
*/
|
||||
#if ANY(WIFISUPPORT, ESP3D_WIFISUPPORT)
|
||||
#if ENABLED(WIFISUPPORT)
|
||||
//#define WEBSUPPORT // Start a webserver (which may include auto-discovery) using SPIFFS
|
||||
//#define OTASUPPORT // Support over-the-air firmware updates
|
||||
//#define WIFI_CUSTOM_COMMAND // Accept feature config commands (e.g., WiFi ESP3D) from the host
|
||||
@@ -4525,6 +4524,3 @@
|
||||
|
||||
// Report uncleaned reset reason from register r2 instead of MCUSR. Supported by Optiboot on AVR.
|
||||
//#define OPTIBOOT_RESET_REASON
|
||||
|
||||
// Shrink the build for smaller boards by sacrificing some serial feedback
|
||||
//#define MARLIN_SMALL_BUILD
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@
|
||||
* here we define this default string as the date where the latest release
|
||||
* version was tagged.
|
||||
*/
|
||||
//#define STRING_DISTRIBUTION_DATE "2024-05-24"
|
||||
//#define STRING_DISTRIBUTION_DATE "2024-05-27"
|
||||
|
||||
/**
|
||||
* Defines a generic printer name to be output to the LCD after booting Marlin.
|
||||
|
||||
@@ -53,12 +53,11 @@ typedef uint64_t hal_timer_t;
|
||||
#if ENABLED(I2S_STEPPER_STREAM)
|
||||
#define STEPPER_TIMER_PRESCALE 1
|
||||
#define STEPPER_TIMER_RATE 250000 // 250khz, 4µs pulses of i2s word clock
|
||||
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs // wrong would be 0.25
|
||||
#else
|
||||
#define STEPPER_TIMER_PRESCALE 40
|
||||
#define STEPPER_TIMER_RATE ((HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE)) // frequency of stepper timer, 2MHz
|
||||
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
|
||||
#endif
|
||||
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
|
||||
|
||||
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ typedef uint32_t hal_timer_t;
|
||||
#define FTM0_TIMER_PRESCALE_BITS 0b011
|
||||
#define FTM1_TIMER_PRESCALE_BITS 0b010
|
||||
|
||||
#define FTM0_TIMER_RATE (F_BUS / (FTM0_TIMER_PRESCALE)) // 60MHz / 8 = 7500kHz
|
||||
#define FTM0_TIMER_RATE (F_BUS / (FTM0_TIMER_PRESCALE)) // 60MHz / 8 = 7.5MHz
|
||||
#define FTM1_TIMER_RATE (F_BUS / (FTM1_TIMER_PRESCALE)) // 60MHz / 4 = 15MHz
|
||||
|
||||
#define HAL_TIMER_RATE (FTM0_TIMER_RATE)
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
#define HYPOT2(x,y) (sq(x)+sq(y))
|
||||
#define NORMSQ(x,y,z) (sq(x)+sq(y)+sq(z))
|
||||
|
||||
#define FLOAT_SQ(I) sq(float(I))
|
||||
#define FLOAT_SQ(I) float(sq(I))
|
||||
#define CIRCLE_AREA(R) (float(M_PI) * FLOAT_SQ(R))
|
||||
#define CIRCLE_CIRC(R) (2 * float(M_PI) * float(R))
|
||||
|
||||
|
||||
@@ -1105,6 +1105,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
|
||||
case 1002: M1002(); break; // M1002: [INTERNAL] Tool-change and Relative E Move
|
||||
#endif
|
||||
|
||||
#if ENABLED(ONE_CLICK_PRINT)
|
||||
case 1003: M1003(); break; // M1003: [INTERNAL] Set the current dir to /
|
||||
#endif
|
||||
|
||||
#if ENABLED(UBL_MESH_WIZARD)
|
||||
case 1004: M1004(); break; // M1004: UBL Mesh Wizard
|
||||
#endif
|
||||
|
||||
@@ -1276,6 +1276,10 @@ private:
|
||||
static void M1002();
|
||||
#endif
|
||||
|
||||
#if ENABLED(ONE_CLICK_PRINT)
|
||||
static void M1003();
|
||||
#endif
|
||||
|
||||
#if ENABLED(UBL_MESH_WIZARD)
|
||||
static void M1004();
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2024 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(ONE_CLICK_PRINT)
|
||||
|
||||
#include "../gcode.h"
|
||||
#include "../../sd/cardreader.h"
|
||||
|
||||
/**
|
||||
* M1003: Set the current dir to /. Should come after 'M24'.
|
||||
* Prevents the SD menu getting stuck in the newest file's workDir.
|
||||
*/
|
||||
void GcodeSuite::M1003() { card.cdroot(); }
|
||||
|
||||
#endif // ONE_CLICK_PRINT
|
||||
@@ -833,6 +833,16 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* S_CURVE_ACCELERATION
|
||||
*/
|
||||
#if ENABLED(S_CURVE_ACCELERATION) && defined(S_CURVE_FACTOR)
|
||||
#if defined(__AVR__)
|
||||
#error "S_CURVE_FACTOR is not implemented for AVR yet"
|
||||
#endif
|
||||
static_assert(WITHIN(S_CURVE_FACTOR, 0, 1), "S_CURVE_FACTOR must be from 0 to 1");
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Nonlinear Extrusion requirements
|
||||
*/
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
* version was tagged.
|
||||
*/
|
||||
#ifndef STRING_DISTRIBUTION_DATE
|
||||
#define STRING_DISTRIBUTION_DATE "2024-05-24"
|
||||
#define STRING_DISTRIBUTION_DATE "2024-05-27"
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -1343,7 +1343,7 @@ void MarlinUI::draw_status_screen() {
|
||||
void MenuItem_sdbase::draw(const bool sel, const uint8_t row, FSTR_P const, CardReader &theCard, const bool isDir) {
|
||||
lcd_put_lchar(0, row, sel ? LCD_STR_ARROW_RIGHT[0] : ' ');
|
||||
uint8_t n = LCD_WIDTH - 2;
|
||||
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, row, sel), n);
|
||||
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, sel), n);
|
||||
for (; n; --n) lcd_put_u8str(F(" "));
|
||||
lcd_put_lchar(isDir ? LCD_STR_FOLDER[0] : ' ');
|
||||
}
|
||||
|
||||
@@ -1086,7 +1086,7 @@ void MarlinUI::draw_status_screen() {
|
||||
lcd_moveto(0, row);
|
||||
lcd.write(sel ? LCD_STR_ARROW_RIGHT[0] : ' ');
|
||||
uint8_t n = LCD_WIDTH - 2;
|
||||
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, row, sel), n);
|
||||
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, sel), n);
|
||||
for (; n; --n) lcd.write(' ');
|
||||
lcd.write(isDir ? LCD_STR_FOLDER[0] : ' ');
|
||||
lcd.print_line();
|
||||
|
||||
@@ -606,7 +606,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
|
||||
const uint8_t maxlen = LCD_WIDTH - isDir;
|
||||
if (isDir) lcd_put_lchar(LCD_STR_FOLDER[0]);
|
||||
const pixel_len_t pixw = maxlen * (MENU_FONT_WIDTH);
|
||||
pixel_len_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), pixw);
|
||||
pixel_len_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, sel), pixw);
|
||||
for (; n > MENU_FONT_WIDTH; n -= MENU_FONT_WIDTH) lcd_put_u8str(F(" "));
|
||||
}
|
||||
|
||||
|
||||
@@ -487,7 +487,7 @@ void MarlinUI::draw_status_message(const bool blink) {
|
||||
maxlen -= 2;
|
||||
}
|
||||
|
||||
dwin_string.add(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
|
||||
dwin_string.add(ui.scrolled_filename(theCard, maxlen, sel), maxlen);
|
||||
uint8_t n = maxlen - dwin_string.length;
|
||||
while (n > 0) { dwin_string.add(' '); --n; }
|
||||
lcd_moveto(1, row);
|
||||
|
||||
+23
-26
@@ -357,25 +357,21 @@ void MarlinUI::init() {
|
||||
#if HAS_MEDIA
|
||||
|
||||
#if MARLINUI_SCROLL_NAME
|
||||
uint8_t MarlinUI::filename_scroll_pos, MarlinUI::filename_scroll_max;
|
||||
static uint8_t filename_scroll_pos, filename_scroll_max;
|
||||
#endif
|
||||
|
||||
const char * MarlinUI::scrolled_filename(CardReader &theCard, const uint8_t maxlen, uint8_t hash, const bool doScroll) {
|
||||
const char * MarlinUI::scrolled_filename(CardReader &theCard, const uint8_t maxlen, const bool doScroll) {
|
||||
const char *outstr = theCard.longest_filename();
|
||||
if (theCard.longFilename[0]) {
|
||||
#if MARLINUI_SCROLL_NAME
|
||||
if (doScroll) {
|
||||
for (uint8_t l = FILENAME_LENGTH; l--;)
|
||||
hash = ((hash << 1) | (hash >> 7)) ^ theCard.filename[l]; // rotate, xor
|
||||
static uint8_t filename_scroll_hash;
|
||||
if (filename_scroll_hash != hash) { // If the hash changed...
|
||||
filename_scroll_hash = hash; // Save the new hash
|
||||
filename_scroll_max = _MAX(0, utf8_strlen(theCard.longFilename) - maxlen); // Update the scroll limit
|
||||
filename_scroll_pos = 0; // Reset scroll to the start
|
||||
lcd_status_update_delay = 8; // Don't scroll right away
|
||||
filename_scroll_max = _MAX(0, utf8_strlen(theCard.longFilename) - maxlen);
|
||||
if (filename_scroll_max) {
|
||||
// Ensure filename_scroll_pos isn't out of bounds even though it should never happen.
|
||||
if (filename_scroll_pos > filename_scroll_max) filename_scroll_pos = 0;
|
||||
// Advance byte position corresponding to filename_scroll_pos char position
|
||||
outstr += TERN(UTF_FILENAME_SUPPORT, utf8_byte_pos_by_char_num(outstr, filename_scroll_pos), filename_scroll_pos);
|
||||
}
|
||||
// Advance byte position corresponding to filename_scroll_pos char position
|
||||
outstr += TERN(UTF_FILENAME_SUPPORT, utf8_byte_pos_by_char_num(outstr, filename_scroll_pos), filename_scroll_pos);
|
||||
}
|
||||
#else
|
||||
theCard.longFilename[
|
||||
@@ -1003,22 +999,19 @@ void MarlinUI::init() {
|
||||
|
||||
#endif // HAS_MARLINUI_MENU
|
||||
|
||||
if (ELAPSED(ms, next_lcd_update_ms) || TERN0(HAS_MARLINUI_U8GLIB, drawing_screen)) {
|
||||
|
||||
const bool lcd_update_ms_elapsed = ELAPSED(ms, next_lcd_update_ms);
|
||||
if (lcd_update_ms_elapsed) {
|
||||
next_lcd_update_ms = ms + LCD_UPDATE_INTERVAL;
|
||||
|
||||
#if HAS_TOUCH_BUTTONS
|
||||
|
||||
if (on_status_screen()) next_lcd_update_ms += (LCD_UPDATE_INTERVAL) * 2;
|
||||
|
||||
TERN_(HAS_ENCODER_ACTION, touch_buttons = touchBt.read_buttons());
|
||||
|
||||
#endif
|
||||
|
||||
TERN_(LCD_HAS_STATUS_INDICATORS, update_indicators());
|
||||
|
||||
#if HAS_ENCODER_ACTION
|
||||
|
||||
TERN_(HAS_SLOW_BUTTONS, slow_buttons = read_slow_buttons()); // Buttons that take too long to read in interrupt context
|
||||
|
||||
if (TERN0(IS_RRW_KEYPAD, handle_keypad()))
|
||||
@@ -1083,12 +1076,17 @@ void MarlinUI::init() {
|
||||
#endif
|
||||
|
||||
refresh(LCDVIEW_REDRAW_NOW);
|
||||
TERN_(HAS_MARLINUI_U8GLIB, drawing_screen = false);
|
||||
#if MARLINUI_SCROLL_NAME
|
||||
filename_scroll_max = 0;
|
||||
filename_scroll_pos = 0;
|
||||
lcd_status_update_delay = 9;
|
||||
#endif
|
||||
|
||||
#if LED_POWEROFF_TIMEOUT > 0
|
||||
if (!powerManager.psu_on) leds.reset_timeout(ms);
|
||||
#endif
|
||||
} // encoder activity
|
||||
|
||||
#endif // HAS_ENCODER_ACTION
|
||||
|
||||
// This runs every ~100ms when idling often enough.
|
||||
@@ -1097,19 +1095,23 @@ void MarlinUI::init() {
|
||||
lcd_status_update_delay = TERN(HAS_MARLINUI_U8GLIB, 12, 9);
|
||||
if (max_display_update_time) max_display_update_time--; // Be sure never go to a very big number
|
||||
refresh(LCDVIEW_REDRAW_NOW);
|
||||
TERN_(HAS_MARLINUI_U8GLIB, drawing_screen = false);
|
||||
}
|
||||
|
||||
#if ALL(HAS_MARLINUI_MENU, SCROLL_LONG_FILENAMES)
|
||||
#if MARLINUI_SCROLL_NAME
|
||||
// If scrolling of long file names is enabled and we are in the sd card menu,
|
||||
// cause a refresh to occur until all the text has scrolled into view.
|
||||
if (currentScreen == menu_media && !lcd_status_update_delay--) {
|
||||
if (currentScreen == menu_media && filename_scroll_max && !lcd_status_update_delay--) {
|
||||
lcd_status_update_delay = ++filename_scroll_pos >= filename_scroll_max ? 12 : 4; // Long delay at end and start
|
||||
if (filename_scroll_pos > filename_scroll_max) filename_scroll_pos = 0;
|
||||
refresh(LCDVIEW_REDRAW_NOW);
|
||||
TERN_(HAS_MARLINUI_U8GLIB, drawing_screen = false);
|
||||
reset_status_timeout(ms);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (lcd_update_ms_elapsed || drawing_screen) {
|
||||
// Then we want to use only 50% of the time
|
||||
const uint16_t bbr2 = planner.block_buffer_runtime() >> 1;
|
||||
|
||||
@@ -1131,7 +1133,6 @@ void MarlinUI::init() {
|
||||
TERN_(HAS_ADC_BUTTONS, keypad_buttons = 0);
|
||||
|
||||
#if HAS_MARLINUI_U8GLIB
|
||||
|
||||
#if ENABLED(LIGHTWEIGHT_UI)
|
||||
const bool in_status = on_status_screen(),
|
||||
do_u8g_loop = !in_status;
|
||||
@@ -1160,14 +1161,11 @@ void MarlinUI::init() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
run_current_screen();
|
||||
|
||||
// Apply all DWIN drawing after processing
|
||||
TERN_(IS_DWIN_MARLINUI, dwinUpdateLCD());
|
||||
|
||||
#endif
|
||||
|
||||
TERN_(HAS_MARLINUI_MENU, lcd_clicked = false);
|
||||
@@ -1212,8 +1210,7 @@ void MarlinUI::init() {
|
||||
case LCDVIEW_CALL_NO_REDRAW:
|
||||
default: break;
|
||||
} // switch
|
||||
|
||||
} // ELAPSED(ms, next_lcd_update_ms)
|
||||
}
|
||||
|
||||
TERN_(HAS_GRAPHICAL_TFT, tft_idle());
|
||||
}
|
||||
|
||||
@@ -644,10 +644,7 @@ public:
|
||||
#if ALL(SCROLL_LONG_FILENAMES, HAS_MARLINUI_MENU)
|
||||
#define MARLINUI_SCROLL_NAME 1
|
||||
#endif
|
||||
#if MARLINUI_SCROLL_NAME
|
||||
static uint8_t filename_scroll_pos, filename_scroll_max;
|
||||
#endif
|
||||
static const char * scrolled_filename(CardReader &theCard, const uint8_t maxlen, uint8_t hash, const bool doScroll);
|
||||
static const char * scrolled_filename(CardReader &theCard, const uint8_t maxlen, const bool doScroll);
|
||||
#endif
|
||||
|
||||
#if HAS_PREHEAT
|
||||
|
||||
@@ -523,12 +523,12 @@ void menu_backlash();
|
||||
// M204 T Travel Acceleration
|
||||
EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel);
|
||||
|
||||
#define EDIT_AMAX(Q,L) EDIT_ITEM_FAST_N(long5_25, _AXIS(Q), MSG_AMAX_N, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.refresh_acceleration_rates(); })
|
||||
NUM_AXIS_CODE(
|
||||
EDIT_AMAX(A, 100), EDIT_AMAX(B, 100), EDIT_AMAX(C, 10),
|
||||
EDIT_AMAX(I, 10), EDIT_AMAX(J, 10), EDIT_AMAX(K, 10),
|
||||
EDIT_AMAX(U, 10), EDIT_AMAX(V, 10), EDIT_AMAX(W, 10)
|
||||
);
|
||||
//#define EDIT_AMAX(Q,L) EDIT_ITEM_FAST_N(long5_25, _AXIS(Q), MSG_AMAX_N, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.refresh_acceleration_rates(); })
|
||||
//NUM_AXIS_CODE(
|
||||
// EDIT_AMAX(A, 100), EDIT_AMAX(B, 100), EDIT_AMAX(C, 10),
|
||||
// EDIT_AMAX(I, 10), EDIT_AMAX(J, 10), EDIT_AMAX(K, 10),
|
||||
// EDIT_AMAX(U, 10), EDIT_AMAX(V, 10), EDIT_AMAX(W, 10)
|
||||
//);
|
||||
|
||||
#if ENABLED(DISTINCT_E_FACTORS)
|
||||
EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)], 100, max_accel_edit_scaled.e, []{ planner.refresh_acceleration_rates(); });
|
||||
@@ -538,7 +538,7 @@ void menu_backlash();
|
||||
planner.refresh_acceleration_rates();
|
||||
});
|
||||
#elif E_STEPPERS
|
||||
EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS], 100, max_accel_edit_scaled.e, []{ planner.refresh_acceleration_rates(); });
|
||||
//EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS], 100, max_accel_edit_scaled.e, []{ planner.refresh_acceleration_rates(); });
|
||||
#endif
|
||||
|
||||
#ifdef XY_FREQUENCY_LIMIT
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
#if ENABLED(ONE_CLICK_PRINT)
|
||||
|
||||
#include "menu.h"
|
||||
#include "../../gcode/queue.h"
|
||||
|
||||
static void one_click_print_done() {
|
||||
ui.return_to_status();
|
||||
ui.reset_status();
|
||||
queue.enqueue_one_now(F("M1003")); // Make sure SD card browsing doesn't break!
|
||||
}
|
||||
|
||||
void one_click_print() {
|
||||
ui.goto_screen([]{
|
||||
@@ -33,9 +40,9 @@ void one_click_print() {
|
||||
GET_TEXT_F(MSG_BUTTON_PRINT), GET_TEXT_F(MSG_BUTTON_CANCEL),
|
||||
[]{
|
||||
card.openAndPrintFile(card.filename);
|
||||
ui.return_to_status();
|
||||
ui.reset_status();
|
||||
}, nullptr,
|
||||
one_click_print_done();
|
||||
},
|
||||
one_click_print_done,
|
||||
GET_TEXT_F(MSG_START_PRINT), filename, F("?")
|
||||
);
|
||||
});
|
||||
|
||||
@@ -386,7 +386,7 @@ void MenuItem_static::draw(const uint8_t row, FSTR_P const ftpl, const uint8_t s
|
||||
menu_item(row, sel);
|
||||
if (isDir) tft.add_image(MENU_ITEM_ICON_X, MENU_ITEM_ICON_Y, imgDirectory, COLOR_MENU_TEXT, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND);
|
||||
uint8_t maxlen = (MENU_ITEM_HEIGHT) - (MENU_TEXT_Y) + 1;
|
||||
tft.add_text(MENU_ITEM_ICON_SPACE, MENU_TEXT_Y, COLOR_MENU_TEXT, ui.scrolled_filename(theCard, maxlen, row, sel));
|
||||
tft.add_text(MENU_ITEM_ICON_SPACE, MENU_TEXT_Y, COLOR_MENU_TEXT, ui.scrolled_filename(theCard, maxlen, sel));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+144
-227
@@ -128,7 +128,6 @@ Planner planner;
|
||||
block_t Planner::block_buffer[BLOCK_BUFFER_SIZE];
|
||||
volatile uint8_t Planner::block_buffer_head, // Index of the next block to be pushed
|
||||
Planner::block_buffer_nonbusy, // Index of the first non-busy block
|
||||
Planner::block_buffer_planned, // Index of the optimally planned block
|
||||
Planner::block_buffer_tail; // Index of the busy block, if any
|
||||
uint16_t Planner::cleaning_buffer_counter; // A counter to disable queuing of blocks
|
||||
uint8_t Planner::delay_before_delivering; // Delay block delivery so initial blocks in an empty queue may merge
|
||||
@@ -150,7 +149,7 @@ planner_settings_t Planner::settings; // Initialized by settings.load(
|
||||
const uint8_t laser_power_floor = cutter.pct_to_ocr(SPEED_POWER_MIN);
|
||||
#endif
|
||||
|
||||
uint32_t Planner::max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) Derived from mm_per_s2
|
||||
uint64_t Planner::max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) Derived from mm_per_s2
|
||||
|
||||
#if HAS_JUNCTION_DEVIATION
|
||||
float Planner::junction_deviation_mm; // (mm) M205 J
|
||||
@@ -170,7 +169,7 @@ uint32_t Planner::max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) D
|
||||
#endif
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
uint32_t Planner::last_page_step_rate = 0;
|
||||
uint64_t Planner::last_page_step_rate = 0;
|
||||
AxisBits Planner::last_page_dir; // = 0
|
||||
#endif
|
||||
|
||||
@@ -220,7 +219,7 @@ uint32_t Planner::max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) D
|
||||
|
||||
xyze_long_t Planner::position{0};
|
||||
|
||||
uint32_t Planner::acceleration_long_cutoff;
|
||||
uint64_t Planner::acceleration_long_cutoff;
|
||||
|
||||
xyze_float_t Planner::previous_speed;
|
||||
float Planner::previous_nominal_speed;
|
||||
@@ -248,7 +247,7 @@ float Planner::previous_nominal_speed;
|
||||
#endif
|
||||
|
||||
#if HAS_WIRED_LCD
|
||||
volatile uint32_t Planner::block_buffer_runtime_us = 0;
|
||||
volatile uint64_t Planner::block_buffer_runtime_us = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -338,7 +337,7 @@ void Planner::init() {
|
||||
* // Compute initial estimation of 0x1000000/x -
|
||||
* // Get most significant bit set on divider
|
||||
* uint8_t idx = 0;
|
||||
* uint32_t nr = d;
|
||||
* uint64_t nr = d;
|
||||
* if (!(nr & 0xFF0000)) {
|
||||
* nr <<= 8; idx += 8;
|
||||
* if (!(nr & 0xFF0000)) { nr <<= 8; idx += 8; }
|
||||
@@ -348,16 +347,16 @@ void Planner::init() {
|
||||
* if (!(nr & 0x800000)) { nr <<= 1; idx += 1; }
|
||||
*
|
||||
* // Isolate top 9 bits of the denominator, to be used as index into the initial estimation table
|
||||
* uint32_t tidx = nr >> 15, // top 9 bits. bit8 is always set
|
||||
* uint64_t tidx = nr >> 15, // top 9 bits. bit8 is always set
|
||||
* ie = inv_tab[tidx & 0xFF] + 256, // Get the table value. bit9 is always set
|
||||
* x = idx <= 8 ? (ie >> (8 - idx)) : (ie << (idx - 8)); // Position the estimation at the proper place
|
||||
*
|
||||
* x = uint32_t((x * uint64_t(_BV(25) - x * d)) >> 24); // Refine estimation by newton-raphson. 1 iteration is enough
|
||||
* const uint32_t r = _BV(24) - x * d; // Estimate remainder
|
||||
* x = uint64_t((x * uint64_t(_BV(25) - x * d)) >> 24); // Refine estimation by newton-raphson. 1 iteration is enough
|
||||
* const uint64_t r = _BV(24) - x * d; // Estimate remainder
|
||||
* if (r >= d) x++; // Check whether to adjust result
|
||||
* return uint32_t(x); // x holds the proper estimation
|
||||
* return uint64_t(x); // x holds the proper estimation
|
||||
*/
|
||||
static uint32_t get_period_inverse(uint32_t d) {
|
||||
static uint64_t get_period_inverse(uint64_t d) {
|
||||
|
||||
static const uint8_t inv_tab[256] PROGMEM = {
|
||||
255,253,252,250,248,246,244,242,240,238,236,234,233,231,229,227,
|
||||
@@ -381,7 +380,7 @@ void Planner::init() {
|
||||
// For small denominators, it is cheaper to directly store the result.
|
||||
// For bigger ones, just ONE Newton-Raphson iteration is enough to get
|
||||
// maximum precision we need
|
||||
static const uint32_t small_inv_tab[111] PROGMEM = {
|
||||
static const uint64_t small_inv_tab[111] PROGMEM = {
|
||||
16777216,16777216,8388608,5592405,4194304,3355443,2796202,2396745,2097152,1864135,1677721,1525201,1398101,1290555,1198372,1118481,
|
||||
1048576,986895,932067,883011,838860,798915,762600,729444,699050,671088,645277,621378,599186,578524,559240,541200,
|
||||
524288,508400,493447,479349,466033,453438,441505,430185,419430,409200,399457,390167,381300,372827,364722,356962,
|
||||
@@ -718,20 +717,18 @@ void Planner::init() {
|
||||
);
|
||||
|
||||
// Return the result
|
||||
return r11 | (uint16_t(r12) << 8) | (uint32_t(r13) << 16);
|
||||
return r11 | (uint16_t(r12) << 8) | (uint64_t(r13) << 16);
|
||||
}
|
||||
#else
|
||||
// All other 32-bit MPUs can easily do inverse using hardware division,
|
||||
// so we don't need to reduce precision or to use assembly language at all.
|
||||
// This routine, for all other archs, returns 0x100000000 / d ~= 0xFFFFFFFF / d
|
||||
FORCE_INLINE static uint32_t get_period_inverse(const uint32_t d) {
|
||||
FORCE_INLINE static uint64_t get_period_inverse(const uint64_t d) {
|
||||
return d ? 0xFFFFFFFF / d : 0xFFFFFFFF;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MINIMAL_STEP_RATE 120
|
||||
|
||||
/**
|
||||
* Get the current block for processing
|
||||
* and mark the block as busy.
|
||||
@@ -768,10 +765,6 @@ block_t* Planner::get_current_block() {
|
||||
// As this block is busy, advance the nonbusy block pointer
|
||||
block_buffer_nonbusy = next_block_index(block_buffer_tail);
|
||||
|
||||
// Push block_buffer_planned pointer, if encountered.
|
||||
if (block_buffer_tail == block_buffer_planned)
|
||||
block_buffer_planned = block_buffer_nonbusy;
|
||||
|
||||
// Return the block
|
||||
return block;
|
||||
}
|
||||
@@ -784,33 +777,37 @@ block_t* Planner::get_current_block() {
|
||||
|
||||
/**
|
||||
* Calculate trapezoid parameters, multiplying the entry- and exit-speeds
|
||||
* by the provided factors. Requires that initial_rate and final_rate are
|
||||
* no less than sqrt(block->acceleration_steps_per_s2 / 2), which is ensured
|
||||
* through minimum_planner_speed_sqr in _populate_block().
|
||||
* by the provided factors. If entry_factor is 0 don't change the initial_rate.
|
||||
* Assumes that the implied initial_rate and final_rate are no less than
|
||||
* sqrt(block->acceleration_steps_per_s2 / 2). This is ensured through
|
||||
* minimum_planner_speed_sqr / min_entry_speed_sqr though note there's one
|
||||
* exception in recalculate_trapezoids().
|
||||
**
|
||||
* ############ VERY IMPORTANT ############
|
||||
* NOTE that the PRECONDITION to call this function is that the block is
|
||||
* NOT BUSY and it is marked as RECALCULATE. That WARRANTIES the Stepper ISR
|
||||
* is not and will not use the block while we modify it, so it is safe to
|
||||
* alter its values.
|
||||
* is not and will not use the block while we modify it.
|
||||
*/
|
||||
void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t entry_factor, const_float_t exit_factor) {
|
||||
void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t entry_speed, const_float_t exit_speed) {
|
||||
|
||||
uint32_t initial_rate = LROUND(block->nominal_rate * entry_factor),
|
||||
final_rate = LROUND(block->nominal_rate * exit_factor); // (steps per second)
|
||||
const float spmm = block->steps_per_mm;
|
||||
uint64_t initial_rate = entry_speed ? _MAX(long(MINIMAL_STEP_RATE), LROUND(entry_speed * spmm)) : block->initial_rate,
|
||||
final_rate = _MAX(long(MINIMAL_STEP_RATE), LROUND(exit_speed * spmm));
|
||||
|
||||
// Legacy check against supposed timer overflow. However Stepper::calc_timer_interval() already
|
||||
// should protect against it. But removing this code produces judder in direction-switching
|
||||
// moves. This is because the current discrete stepping math diverges from physical motion under
|
||||
// constant acceleration when acceleration_steps_per_s2 is large compared to initial/final_rate.
|
||||
NOLESS(initial_rate, uint32_t(MINIMAL_STEP_RATE)); // Enforce the minimum speed
|
||||
NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE));
|
||||
NOLESS(initial_rate, uint64_t(MINIMAL_STEP_RATE)); // Enforce the minimum speed
|
||||
NOLESS(final_rate, uint64_t(MINIMAL_STEP_RATE));
|
||||
|
||||
NOLESS(block->nominal_rate, MINIMAL_STEP_RATE);
|
||||
NOMORE(initial_rate, block->nominal_rate); // NOTE: The nominal rate may be less than MINIMAL_STEP_RATE!
|
||||
NOMORE(final_rate, block->nominal_rate);
|
||||
|
||||
#if ANY(S_CURVE_ACCELERATION, LIN_ADVANCE)
|
||||
// If we have some plateau time, the cruise rate will be the nominal rate
|
||||
uint32_t cruise_rate = block->nominal_rate;
|
||||
uint64_t cruise_rate = block->nominal_rate;
|
||||
#endif
|
||||
|
||||
// Steps for acceleration, plateau and deceleration
|
||||
@@ -827,7 +824,6 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
|
||||
// Steps required for acceleration, deceleration to/from nominal rate
|
||||
decelerate_steps_float = half_inverse_accel * (nominal_rate_sq - FLOAT_SQ(final_rate)),
|
||||
accelerate_steps_float = half_inverse_accel * (nominal_rate_sq - FLOAT_SQ(initial_rate));
|
||||
// Aims to fully reach nominal and final rates
|
||||
accelerate_steps = CEIL(accelerate_steps_float);
|
||||
decelerate_steps = CEIL(decelerate_steps_float);
|
||||
|
||||
@@ -853,7 +849,7 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
const float rate_factor = inverse_accel * (STEPPER_TIMER_RATE);
|
||||
// Jerk controlled speed requires to express speed versus time, NOT steps
|
||||
uint32_t acceleration_time = rate_factor * float(cruise_rate - initial_rate),
|
||||
uint64_t acceleration_time = rate_factor * float(cruise_rate - initial_rate),
|
||||
deceleration_time = rate_factor * float(cruise_rate - final_rate),
|
||||
// And to offload calculations from the ISR, we also calculate the inverse of those times here
|
||||
acceleration_time_inverse = get_period_inverse(acceleration_time),
|
||||
@@ -942,16 +938,16 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
|
||||
*
|
||||
* Recalculates the motion plan according to the following basic guidelines:
|
||||
*
|
||||
* 1. Go over every feasible block sequentially in reverse order and calculate the junction speeds
|
||||
* (i.e. current->entry_speed) such that:
|
||||
* a. No junction speed exceeds the pre-computed maximum junction speed limit or nominal speeds of
|
||||
* neighboring blocks.
|
||||
* b. A block entry speed cannot exceed one reverse-computed from its exit speed (next->entry_speed)
|
||||
* with a maximum allowable deceleration over the block travel distance.
|
||||
* c. The last (or newest appended) block is planned from safe_exit_speed_sqr.
|
||||
* 2. Go over every block in chronological (forward) order and dial down junction speed values if
|
||||
* a. The exit speed exceeds the one forward-computed from its entry speed with the maximum allowable
|
||||
* acceleration over the block travel distance.
|
||||
* 1. Go over blocks sequentially in reverse order and maximize the entry junction speed:
|
||||
* a. Entry speed should stay below/at the pre-computed maximum junction speed limit
|
||||
* b. Aim for the maximum entry speed which is the one reverse-computed from its exit speed
|
||||
* (next->entry_speed) if assuming maximum deceleration over the full block travel distance
|
||||
* c. The last (newest appended) block uses safe_exit_speed exit speed (there's no 'next')
|
||||
* 2. Go over blocks in chronological (forward) order and fix the exit junction speed:
|
||||
* a. Exit speed (next->entry_speed) must be below/at the maximum exit speed forward-computed
|
||||
* from its entry speed if assuming maximum acceleration over the full block travel distance
|
||||
* b. Exit speed should stay above/at the pre-computed minimum junction speed limit
|
||||
* 3. Convert entry / exit speeds (mm/s) into final/initial steps/s
|
||||
*
|
||||
* When these stages are complete, the planner will have maximized the velocity profiles throughout the all
|
||||
* of the planner blocks, where every block is operating at its maximum allowable acceleration limits. In
|
||||
@@ -959,28 +955,22 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
|
||||
* are possible. If a new block is added to the buffer, the plan is recomputed according to the said
|
||||
* guidelines for a new optimal plan.
|
||||
*
|
||||
* To increase computational efficiency of these guidelines, a set of planner block pointers have been
|
||||
* created to indicate stop-compute points for when the planner guidelines cannot logically make any further
|
||||
* changes or improvements to the plan when in normal operation and new blocks are streamed and added to the
|
||||
* planner buffer. For example, if a subset of sequential blocks in the planner have been planned and are
|
||||
* bracketed by junction velocities at their maximums (or by the first planner block as well), no new block
|
||||
* added to the planner buffer will alter the velocity profiles within them. So we no longer have to compute
|
||||
* them. Or, if a set of sequential blocks from the first block in the planner (or a optimal stop-compute
|
||||
* point) are all accelerating, they are all optimal and can not be altered by a new block added to the
|
||||
* planner buffer, as this will only further increase the plan speed to chronological blocks until a maximum
|
||||
* junction velocity is reached. However, if the operational conditions of the plan changes from infrequently
|
||||
* used feed holds or feedrate overrides, the stop-compute pointers will be reset and the entire plan is
|
||||
* recomputed as stated in the general guidelines.
|
||||
* To increase computational efficiency of these guidelines:
|
||||
* 1. We keep track of which blocks need calculation (block->flag.recalculate)
|
||||
* 2. We stop the reverse pass on the first block whose entry_speed == max_entry_speed. As soon
|
||||
* as that happens, there can be no further increases (ensured by the previous recalculate)
|
||||
* 3. On the forward pass we skip through to the first block with a modified exit speed
|
||||
* (next->entry_speed)
|
||||
* 4. On the forward pass if we encounter a full acceleration block that limits its exit speed
|
||||
* (next->entry_speed) we also update the maximum for that junction (next->max_entry_speed)
|
||||
* so it's never updated again
|
||||
* 5. We use speed squared (ex: entry_speed_sqr in mm^2/s^2) in acceleration limit computations
|
||||
* 6. We don't recompute sqrt(entry_speed_sqr) if the block's entry speed didn't change
|
||||
*
|
||||
* Planner buffer index mapping:
|
||||
* - block_buffer_tail: Points to the beginning of the planner buffer. First to be executed or being executed.
|
||||
* - block_buffer_head: Points to the buffer block after the last block in the buffer. Used to indicate whether
|
||||
* the buffer is full or empty. As described for standard ring buffers, this block is always empty.
|
||||
* - block_buffer_planned: Points to the first buffer block after the last optimally planned block for normal
|
||||
* streaming operating conditions. Use for planning optimizations by avoiding recomputing parts of the
|
||||
* planner buffer that don't change with the addition of a new block, as describe above. In addition,
|
||||
* this block can never be less than block_buffer_tail and will always be pushed forward and maintain
|
||||
* this requirement when encountered by the Planner::release_current_block() routine during a cycle.
|
||||
*
|
||||
* NOTE: Since the planner only computes on what's in the planner buffer, some motions with many short
|
||||
* segments (e.g., complex curves) may seem to move slowly. This is because there simply isn't
|
||||
@@ -1003,7 +993,8 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
|
||||
*/
|
||||
|
||||
// The kernel called by recalculate() when scanning the plan from last to first entry.
|
||||
void Planner::reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr) {
|
||||
// Returns true if it could increase the current block's entry speed.
|
||||
bool Planner::reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr) {
|
||||
// We need to recalculate only for the last block added or if next->entry_speed_sqr changed.
|
||||
if (!next || next->flag.recalculate) {
|
||||
// And only if we're not already at max entry speed.
|
||||
@@ -1021,196 +1012,136 @@ void Planner::reverse_pass_kernel(block_t * const current, const block_t * const
|
||||
// become BUSY just before being marked RECALCULATE, so check for that!
|
||||
if (stepper.is_block_busy(current)) {
|
||||
// Block became busy. Clear the RECALCULATE flag (no point in
|
||||
// recalculating BUSY blocks). And don't set its speed, as it can't
|
||||
// be updated at this time.
|
||||
// recalculating BUSY blocks).
|
||||
current->flag.recalculate = false;
|
||||
}
|
||||
else {
|
||||
// Block is not BUSY so this is ahead of the Stepper ISR:
|
||||
// Just Set the new entry speed.
|
||||
|
||||
current->entry_speed_sqr = new_entry_speed_sqr;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* recalculate() needs to go over the current plan twice.
|
||||
* Once in reverse and once forward. This implements the reverse pass.
|
||||
* Once in reverse and once forward. This implements the reverse pass that
|
||||
* coarsely maximizes the entry speeds starting from last block.
|
||||
* Requires there's at least one block with flag.recalculate in the buffer.
|
||||
*/
|
||||
void Planner::reverse_pass(const_float_t safe_exit_speed_sqr) {
|
||||
// Initialize block index to the last block in the planner buffer.
|
||||
// This last block will have flag.recalculate set.
|
||||
uint8_t block_index = prev_block_index(block_buffer_head);
|
||||
|
||||
// Read the index of the last buffer planned block.
|
||||
// The ISR may change it so get a stable local copy.
|
||||
uint8_t planned_block_index = block_buffer_planned;
|
||||
// The ISR may change block_buffer_nonbusy so get a stable local copy.
|
||||
uint8_t nonbusy_block_index = block_buffer_nonbusy;
|
||||
|
||||
// If there was a race condition and block_buffer_planned was incremented
|
||||
// or was pointing at the head (queue empty) break loop now and avoid
|
||||
// planning already consumed blocks
|
||||
if (planned_block_index == block_buffer_head) return;
|
||||
|
||||
// Reverse Pass: Coarsely maximize all possible deceleration curves back-planning from the last
|
||||
// block in buffer. Cease planning when the last optimal planned or tail pointer is reached.
|
||||
// NOTE: Forward pass will later refine and correct the reverse pass to create an optimal plan.
|
||||
const block_t *next = nullptr;
|
||||
while (block_index != planned_block_index) {
|
||||
|
||||
// Perform the reverse pass
|
||||
// Don't try to change the entry speed of the first non-busy block.
|
||||
while (block_index != nonbusy_block_index) {
|
||||
block_t *current = &block_buffer[block_index];
|
||||
|
||||
// Only process movement blocks
|
||||
if (current->is_move()) {
|
||||
reverse_pass_kernel(current, next, safe_exit_speed_sqr);
|
||||
// If no entry speed increase was possible we end the reverse pass.
|
||||
if (!reverse_pass_kernel(current, next, safe_exit_speed_sqr)) return;
|
||||
next = current;
|
||||
}
|
||||
|
||||
// Advance to the next
|
||||
block_index = prev_block_index(block_index);
|
||||
|
||||
// The ISR could advance the block_buffer_planned while we were doing the reverse pass.
|
||||
// The ISR could advance block_buffer_nonbusy while we were doing the reverse pass.
|
||||
// We must try to avoid using an already consumed block as the last one - So follow
|
||||
// changes to the pointer and make sure to limit the loop to the currently busy block
|
||||
while (planned_block_index != block_buffer_planned) {
|
||||
while (nonbusy_block_index != block_buffer_nonbusy) {
|
||||
|
||||
// If we reached the busy block or an already processed block, break the loop now
|
||||
if (block_index == planned_block_index) return;
|
||||
if (block_index == nonbusy_block_index) return;
|
||||
|
||||
// Advance the pointer, following the busy block
|
||||
planned_block_index = next_block_index(planned_block_index);
|
||||
nonbusy_block_index = next_block_index(nonbusy_block_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The kernel called by recalculate() when scanning the plan from first to last entry.
|
||||
void Planner::forward_pass_kernel(const block_t * const previous, block_t * const current, const uint8_t block_index) {
|
||||
// Check against previous speed only on current->entry_speed_sqr changes (or if first time).
|
||||
if (current->flag.recalculate) {
|
||||
// If the previous block is accelerating check if it's too short to complete the full speed
|
||||
// change then adjust the entry speed accordingly. Entry speeds have already been maximized.
|
||||
if (previous->entry_speed_sqr < current->entry_speed_sqr) {
|
||||
float new_entry_speed_sqr = max_allowable_speed_sqr(-previous->acceleration, previous->entry_speed_sqr, previous->millimeters);
|
||||
// The kernel called during the forward pass. Assumes current->flag.recalculate.
|
||||
void Planner::forward_pass_kernel(const block_t * const previous, block_t * const current) {
|
||||
// Check if the previous block is accelerating.
|
||||
if (previous->entry_speed_sqr < current->entry_speed_sqr) {
|
||||
// Compute the maximum achievable speed if the previous block was fully accelerating.
|
||||
float new_exit_speed_sqr = max_allowable_speed_sqr(-previous->acceleration, previous->entry_speed_sqr, previous->millimeters);
|
||||
|
||||
// If true, previous block is full-acceleration and we can move the planned pointer forward.
|
||||
if (new_entry_speed_sqr < current->entry_speed_sqr) {
|
||||
// Current entry speed limited by full acceleration from previous entry speed.
|
||||
// Make sure entry speed not lower than minimum_planner_speed_sqr.
|
||||
NOLESS(new_entry_speed_sqr, current->min_entry_speed_sqr);
|
||||
current->entry_speed_sqr = new_entry_speed_sqr;
|
||||
if (new_exit_speed_sqr < current->entry_speed_sqr) {
|
||||
// Current entry speed limited by full acceleration from previous entry speed.
|
||||
|
||||
// Set optimal plan pointer.
|
||||
block_buffer_planned = block_index;
|
||||
}
|
||||
else {
|
||||
// Previous entry speed has been maximized.
|
||||
block_buffer_planned = prev_block_index(block_index);
|
||||
}
|
||||
// Make sure entry speed not lower than minimum_planner_speed_sqr.
|
||||
NOLESS(new_exit_speed_sqr, current->min_entry_speed_sqr);
|
||||
current->entry_speed_sqr = new_exit_speed_sqr;
|
||||
// Ensure we don't try updating entry_speed_sqr again.
|
||||
current->max_entry_speed_sqr = new_exit_speed_sqr;
|
||||
}
|
||||
|
||||
// Any block set at its maximum entry speed also creates an optimal plan up to this
|
||||
// point in the buffer. When the plan is bracketed by either the beginning of the
|
||||
// buffer and a maximum entry speed or two maximum entry speeds, every block in between
|
||||
// cannot logically be further improved. Hence, we don't have to recompute them anymore.
|
||||
if (current->entry_speed_sqr == current->max_entry_speed_sqr)
|
||||
block_buffer_planned = block_index;
|
||||
}
|
||||
|
||||
// The fully optimized entry speed is our new minimum speed.
|
||||
current->min_entry_speed_sqr = current->entry_speed_sqr;
|
||||
}
|
||||
|
||||
/**
|
||||
* recalculate() needs to go over the current plan twice.
|
||||
* Once in reverse and once forward. This implements the forward pass.
|
||||
*/
|
||||
void Planner::forward_pass() {
|
||||
|
||||
// Forward Pass: Forward plan the acceleration curve from the planned pointer onward.
|
||||
// Also scans for optimal plan breakpoints and appropriately updates the planned pointer.
|
||||
|
||||
// Begin at buffer planned pointer. Note that block_buffer_planned can be modified
|
||||
// by the stepper ISR, so read it ONCE. It it guaranteed that block_buffer_planned
|
||||
// will never lead head, so the loop is safe to execute. Also note that the forward
|
||||
// pass will never modify the values at the tail.
|
||||
uint8_t block_index = block_buffer_planned;
|
||||
|
||||
block_t *block;
|
||||
const block_t * previous = nullptr;
|
||||
while (block_index != block_buffer_head) {
|
||||
|
||||
// Perform the forward pass
|
||||
block = &block_buffer[block_index];
|
||||
|
||||
// Only process movement blocks
|
||||
if (block->is_move()) {
|
||||
// If there's no previous block or the previous block is not
|
||||
// BUSY (thus, modifiable) run the forward_pass_kernel. Otherwise,
|
||||
// the previous block became BUSY, so assume the current block's
|
||||
// entry speed can't be altered (since that would also require
|
||||
// updating the exit speed of the previous block).
|
||||
if (previous && !stepper.is_block_busy(previous))
|
||||
forward_pass_kernel(previous, block, block_index);
|
||||
previous = block;
|
||||
}
|
||||
// Advance to the previous
|
||||
block_index = next_block_index(block_index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate the trapezoid speed profiles for all blocks in the plan
|
||||
* according to the entry_factor for each junction. Must be called by
|
||||
* recalculate() after updating the blocks.
|
||||
* Do the forward pass and recalculate the trapezoid speed profiles for all blocks in the plan
|
||||
* according to entry/exit speeds.
|
||||
*/
|
||||
void Planner::recalculate_trapezoids(const_float_t safe_exit_speed_sqr) {
|
||||
// The tail may be changed by the ISR so get a local copy.
|
||||
// Start with the block that's about to execute or is executing.
|
||||
uint8_t block_index = block_buffer_tail,
|
||||
head_block_index = block_buffer_head;
|
||||
// Since there could be a sync block in the head of the queue, and the
|
||||
// next loop must not recalculate the head block (as it needs to be
|
||||
// specially handled), scan backwards to the first non-SYNC block.
|
||||
while (head_block_index != block_index) {
|
||||
|
||||
// Go back (head always point to the first free block)
|
||||
const uint8_t prev_index = prev_block_index(head_block_index);
|
||||
|
||||
// Get the pointer to the block
|
||||
block_t *prev = &block_buffer[prev_index];
|
||||
|
||||
// It the block is a move, we're done with this loop
|
||||
if (prev->is_move()) break;
|
||||
|
||||
// Examine the previous block. This and all following are SYNC blocks
|
||||
head_block_index = prev_index;
|
||||
}
|
||||
|
||||
// Go from the tail (currently executed block) to the first block, without including it)
|
||||
block_t *block = nullptr, *next = nullptr;
|
||||
float current_entry_speed = 0.0f, next_entry_speed = 0.0f;
|
||||
float next_entry_speed = 0.0f;
|
||||
while (block_index != head_block_index) {
|
||||
|
||||
next = &block_buffer[block_index];
|
||||
|
||||
// Only process movement blocks
|
||||
if (next->is_move()) {
|
||||
next_entry_speed = SQRT(next->entry_speed_sqr);
|
||||
// Check if the next block's entry speed changed
|
||||
if (next->flag.recalculate) {
|
||||
if (!block) {
|
||||
// 'next' is the first move due to either being the first added move or due to the planner
|
||||
// having completely fallen behind. Revert any reverse pass change.
|
||||
next->entry_speed_sqr = next->min_entry_speed_sqr;
|
||||
next_entry_speed = SQRT(next->min_entry_speed_sqr);
|
||||
}
|
||||
else {
|
||||
// Try to fix exit speed which requires trapezoid recalculation
|
||||
block->flag.recalculate = true;
|
||||
|
||||
if (block) {
|
||||
// But there is an inherent race condition here, as the block may have
|
||||
// become BUSY just before being marked RECALCULATE, so check for that!
|
||||
if (stepper.is_block_busy(block)) {
|
||||
// Block is BUSY so we can't change the exit speed. Revert any reverse pass change.
|
||||
next->entry_speed_sqr = next->min_entry_speed_sqr;
|
||||
if (!next->initial_rate) {
|
||||
// 'next' was never calculated. Planner is falling behind so for maximum efficiency
|
||||
// set next's stepping speed directly and forgo checking against min_entry_speed_sqr.
|
||||
// calculate_trapezoid_for_block() can handle it, albeit sub-optimally.
|
||||
next->initial_rate = block->final_rate;
|
||||
}
|
||||
// Note that at this point next_entry_speed is (still) 0.
|
||||
}
|
||||
else {
|
||||
// Block is not BUSY: we won the race against the ISR or recalculate was already set
|
||||
|
||||
// If the next block is marked to RECALCULATE, also mark the previously-fetched one
|
||||
if (next->flag.recalculate) block->flag.recalculate = true;
|
||||
if (next->entry_speed_sqr != next->min_entry_speed_sqr)
|
||||
forward_pass_kernel(block, next);
|
||||
|
||||
// Recalculate if current block entry or exit junction speed has changed.
|
||||
if (block->flag.recalculate) {
|
||||
const float current_entry_speed = next_entry_speed;
|
||||
next_entry_speed = SQRT(next->entry_speed_sqr);
|
||||
|
||||
// But there is an inherent race condition here, as the block maybe
|
||||
// became BUSY, just before it was marked as RECALCULATE, so check
|
||||
// if that is the case!
|
||||
if (!stepper.is_block_busy(block)) {
|
||||
// Block is not BUSY, we won the race against the Stepper ISR:
|
||||
|
||||
// NOTE: Entry and exit factors always > 0 by all previous logic operations.
|
||||
const float nomr = 1.0f / block->nominal_speed;
|
||||
calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr);
|
||||
calculate_trapezoid_for_block(block, current_entry_speed, next_entry_speed);
|
||||
}
|
||||
|
||||
// Reset current only to ensure next trapezoid is computed - The
|
||||
@@ -1220,30 +1151,17 @@ void Planner::recalculate_trapezoids(const_float_t safe_exit_speed_sqr) {
|
||||
}
|
||||
|
||||
block = next;
|
||||
current_entry_speed = next_entry_speed;
|
||||
}
|
||||
|
||||
block_index = next_block_index(block_index);
|
||||
}
|
||||
|
||||
// Last/newest block in buffer. Always recalculated.
|
||||
if (block) {
|
||||
// Last/newest block in buffer. The above guarantees it's a move block.
|
||||
if (block && block->flag.recalculate) {
|
||||
const float current_entry_speed = next_entry_speed;
|
||||
next_entry_speed = SQRT(safe_exit_speed_sqr);
|
||||
|
||||
// Mark the next(last) block as RECALCULATE, to prevent the Stepper ISR running it.
|
||||
// As the last block is always recalculated here, there is a chance the block isn't
|
||||
// marked as RECALCULATE yet. That's the reason for the following line.
|
||||
block->flag.recalculate = true;
|
||||
|
||||
// But there is an inherent race condition here, as the block maybe
|
||||
// became BUSY, just before it was marked as RECALCULATE, so check
|
||||
// if that is the case!
|
||||
if (!stepper.is_block_busy(block)) {
|
||||
// Block is not BUSY, we won the race against the Stepper ISR:
|
||||
|
||||
const float nomr = 1.0f / block->nominal_speed;
|
||||
calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr);
|
||||
}
|
||||
calculate_trapezoid_for_block(block, current_entry_speed, next_entry_speed);
|
||||
|
||||
// Reset block to ensure its trapezoid is computed - The stepper is free to use
|
||||
// the block from now on.
|
||||
@@ -1251,14 +1169,10 @@ void Planner::recalculate_trapezoids(const_float_t safe_exit_speed_sqr) {
|
||||
}
|
||||
}
|
||||
|
||||
// Requires there's at least one block with flag.recalculate in the buffer
|
||||
void Planner::recalculate(const_float_t safe_exit_speed_sqr) {
|
||||
// Initialize block index to the last block in the planner buffer.
|
||||
const uint8_t block_index = prev_block_index(block_buffer_head);
|
||||
// If there is just one block, no planning can be done. Avoid it!
|
||||
if (block_index != block_buffer_planned) {
|
||||
reverse_pass(safe_exit_speed_sqr);
|
||||
forward_pass();
|
||||
}
|
||||
reverse_pass(safe_exit_speed_sqr);
|
||||
// The forward pass is done as part of recalculate_trapezoids()
|
||||
recalculate_trapezoids(safe_exit_speed_sqr);
|
||||
}
|
||||
|
||||
@@ -1667,7 +1581,7 @@ void Planner::quick_stop() {
|
||||
const bool was_enabled = stepper.suspend();
|
||||
|
||||
// Drop all queue entries
|
||||
block_buffer_nonbusy = block_buffer_planned = block_buffer_head = block_buffer_tail;
|
||||
block_buffer_nonbusy = block_buffer_head = block_buffer_tail;
|
||||
|
||||
// Restart the block delay for the first movement - As the queue was
|
||||
// forced to empty, there's no risk the ISR will touch this.
|
||||
@@ -1995,9 +1909,9 @@ bool Planner::_populate_block(
|
||||
#if HAS_EXTRUDERS
|
||||
dm.e = (dist.e > 0);
|
||||
const float esteps_float = dist.e * e_factor[extruder];
|
||||
const uint32_t esteps = ABS(esteps_float);
|
||||
const uint64_t esteps = ABS(esteps_float);
|
||||
#else
|
||||
constexpr uint32_t esteps = 0;
|
||||
constexpr uint64_t esteps = 0;
|
||||
#endif
|
||||
|
||||
// Clear all flags, including the "busy" bit
|
||||
@@ -2436,7 +2350,8 @@ bool Planner::_populate_block(
|
||||
|
||||
// Compute and limit the acceleration rate for the trapezoid generator.
|
||||
const float steps_per_mm = block->step_event_count * inverse_millimeters;
|
||||
uint32_t accel;
|
||||
block->steps_per_mm = steps_per_mm;
|
||||
uint64_t accel;
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
bool use_advance_lead = false;
|
||||
#endif
|
||||
@@ -2446,7 +2361,7 @@ bool Planner::_populate_block(
|
||||
else {
|
||||
#define LIMIT_ACCEL_LONG(AXIS,INDX) do{ \
|
||||
if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS+INDX] < accel) { \
|
||||
const uint32_t max_possible = max_acceleration_steps_per_s2[AXIS+INDX] * block->step_event_count / block->steps[AXIS]; \
|
||||
const uint64_t max_possible = max_acceleration_steps_per_s2[AXIS+INDX] * block->step_event_count / block->steps[AXIS]; \
|
||||
NOMORE(accel, max_possible); \
|
||||
} \
|
||||
}while(0)
|
||||
@@ -2490,7 +2405,7 @@ bool Planner::_populate_block(
|
||||
use_advance_lead = false;
|
||||
else {
|
||||
// Scale E acceleration so that it will be possible to jump to the advance speed.
|
||||
const uint32_t max_accel_steps_per_s2 = MAX_E_JERK(extruder) / (extruder_advance_K[E_INDEX_N(extruder)] * e_D_ratio) * steps_per_mm;
|
||||
const uint64_t max_accel_steps_per_s2 = MAX_E_JERK(extruder) / (extruder_advance_K[E_INDEX_N(extruder)] * e_D_ratio) * steps_per_mm;
|
||||
if (accel > max_accel_steps_per_s2) {
|
||||
accel = max_accel_steps_per_s2;
|
||||
if (ENABLED(LA_DEBUG)) SERIAL_ECHOLNPGM("Acceleration limited.");
|
||||
@@ -2520,7 +2435,7 @@ bool Planner::_populate_block(
|
||||
block->acceleration_steps_per_s2 = accel;
|
||||
block->acceleration = accel / steps_per_mm;
|
||||
#if DISABLED(S_CURVE_ACCELERATION)
|
||||
block->acceleration_rate = (uint32_t)(accel * (float(1UL << 24) / (STEPPER_TIMER_RATE)));
|
||||
block->acceleration_rate = (uint64_t)(accel * (float(1UL << 24) / (STEPPER_TIMER_RATE)));
|
||||
#endif
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
@@ -2533,7 +2448,7 @@ bool Planner::_populate_block(
|
||||
|
||||
// reduce LA ISR frequency by calling it only often enough to ensure that there will
|
||||
// never be more than four extruder steps per call
|
||||
for (uint32_t dividend = block->steps.e << 1; dividend <= (block->step_event_count >> 2); dividend <<= 1)
|
||||
for (uint64_t dividend = block->steps.e << 1; dividend <= (block->step_event_count >> 2); dividend <<= 1)
|
||||
block->la_scaling++;
|
||||
|
||||
#if ENABLED(LA_DEBUG)
|
||||
@@ -2546,7 +2461,7 @@ bool Planner::_populate_block(
|
||||
// Formula for the average speed over a 1 step worth of distance if starting from zero and
|
||||
// accelerating at the current limit. Since we can only change the speed every step this is a
|
||||
// good lower limit for the entry and exit speeds. Note that for calculate_trapezoid_for_block()
|
||||
// to work correctly, this must be accurately set and propagated.
|
||||
// to work correctly this must be accurately set and propagated.
|
||||
minimum_planner_speed_sqr = 0.5f * block->acceleration / steps_per_mm;
|
||||
// Go straight to/from nominal speed if block->acceleration is too high for it.
|
||||
NOMORE(minimum_planner_speed_sqr, sq(block->nominal_speed));
|
||||
@@ -2772,7 +2687,7 @@ bool Planner::_populate_block(
|
||||
// Advance affects E_AXIS speed and therefore jerk. Add a speed correction whenever
|
||||
// LA is turned OFF. No correction is applied when LA is turned ON (because it didn't
|
||||
// perform well; it takes more time/effort to push/melt filament than the reverse).
|
||||
static uint32_t previous_advance_rate;
|
||||
static uint64_t previous_advance_rate;
|
||||
static float previous_e_mm_per_step;
|
||||
if (dist.e < 0 && previous_advance_rate) {
|
||||
// Retract move after a segment with LA that ended with an E speed decrease.
|
||||
@@ -2820,7 +2735,7 @@ bool Planner::_populate_block(
|
||||
#endif // CLASSIC_JERK
|
||||
|
||||
// High acceleration limits override low jerk/junction deviation limits (as fixing trapezoids
|
||||
// or reducing acceleration introduces too much complexity and/or too much compute)
|
||||
// or reducing acceleration introduces too much complexity and/or too much compute).
|
||||
NOLESS(vmax_junction_sqr, minimum_planner_speed_sqr);
|
||||
|
||||
// Max entry speed of this block equals the max exit speed of the previous block.
|
||||
@@ -2829,6 +2744,8 @@ bool Planner::_populate_block(
|
||||
block->entry_speed_sqr = minimum_planner_speed_sqr;
|
||||
// Set min entry speed. Rarely it could be higher than the previous nominal speed but that's ok.
|
||||
block->min_entry_speed_sqr = minimum_planner_speed_sqr;
|
||||
// Zero the initial_rate to indicate that calculate_trapezoid_for_block() hasn't been called yet.
|
||||
block->initial_rate = 0;
|
||||
|
||||
block->flag.recalculate = true;
|
||||
|
||||
@@ -3275,7 +3192,7 @@ void Planner::set_position_mm(const xyze_pos_t &xyze) {
|
||||
|
||||
// Recalculate the steps/s^2 acceleration rates, based on the mm/s^2
|
||||
void Planner::refresh_acceleration_rates() {
|
||||
uint32_t highest_rate = 1;
|
||||
uint64_t highest_rate = 1;
|
||||
LOOP_DISTINCT_AXES(i) {
|
||||
max_acceleration_steps_per_s2[i] = settings.max_acceleration_mm_per_s2[i] * settings.axis_steps_per_mm[i];
|
||||
if (TERN1(DISTINCT_E_FACTORS, i < E_AXIS || i == E_AXIS_N(active_extruder)))
|
||||
@@ -3388,7 +3305,7 @@ void Planner::set_max_feedrate(const AxisEnum axis, float inMaxFeedrateMMS) {
|
||||
const bool was_enabled = stepper.suspend();
|
||||
#endif
|
||||
|
||||
uint32_t bbru = block_buffer_runtime_us;
|
||||
uint64_t bbru = block_buffer_runtime_us;
|
||||
|
||||
#ifdef __AVR__
|
||||
// Reenable Stepper ISR
|
||||
|
||||
+26
-19
@@ -78,6 +78,14 @@
|
||||
#include "../feature/closedloop.h"
|
||||
#endif
|
||||
|
||||
constexpr uint64_t MINIMAL_STEP_RATE = (
|
||||
#ifdef CPU_32_BIT
|
||||
_MAX((STEPPER_TIMER_RATE) / HAL_TIMER_TYPE_MAX, 1U) // 32-bit shouldn't go below 1
|
||||
#else
|
||||
(F_CPU) / 500000U // AVR shouldn't go below 32 (16MHz) or 40 (20MHz)
|
||||
#endif
|
||||
);
|
||||
|
||||
// Feedrate for manual moves
|
||||
#ifdef MANUAL_FEEDRATE
|
||||
constexpr xyze_feedrate_t manual_feedrate_mm_m = MANUAL_FEEDRATE,
|
||||
@@ -219,13 +227,14 @@ typedef struct PlannerBlock {
|
||||
min_entry_speed_sqr, // Minimum allowable junction entry speed in (mm/sec)^2
|
||||
max_entry_speed_sqr, // Maximum allowable junction entry speed in (mm/sec)^2
|
||||
millimeters, // The total travel of this block in mm
|
||||
steps_per_mm, // steps/mm
|
||||
acceleration; // acceleration mm/sec^2
|
||||
|
||||
union {
|
||||
abce_ulong_t steps; // Step count along each axis
|
||||
abce_long_t position; // New position to force when this sync block is executed
|
||||
};
|
||||
uint32_t step_event_count; // The number of step events required to complete this block
|
||||
uint64_t step_event_count; // The number of step events required to complete this block
|
||||
|
||||
#if HAS_MULTI_EXTRUDER
|
||||
uint8_t extruder; // The extruder to move (if E move)
|
||||
@@ -238,30 +247,30 @@ typedef struct PlannerBlock {
|
||||
#endif
|
||||
|
||||
// Settings for the trapezoid generator
|
||||
uint32_t accelerate_before, // The index of the step event where cruising starts
|
||||
uint64_t accelerate_before, // The index of the step event on which to start cruising
|
||||
decelerate_start; // The index of the step event on which to start decelerating
|
||||
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
uint32_t cruise_rate, // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase
|
||||
uint64_t cruise_rate, // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase
|
||||
acceleration_time, // Acceleration time and deceleration time in STEP timer counts
|
||||
deceleration_time,
|
||||
acceleration_time_inverse, // Inverse of acceleration and deceleration periods, expressed as integer. Scale depends on CPU being used
|
||||
deceleration_time_inverse;
|
||||
#else
|
||||
uint32_t acceleration_rate; // Acceleration rate in (2^24 steps)/timer_ticks*s
|
||||
uint64_t acceleration_rate; // Acceleration rate in (2^24 steps)/timer_ticks*s
|
||||
#endif
|
||||
|
||||
AxisBits direction_bits; // Direction bits set for this block, where 1 is negative motion
|
||||
|
||||
// Advance extrusion
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
uint32_t la_advance_rate; // The rate at which steps are added whilst accelerating
|
||||
uint64_t la_advance_rate; // The rate at which steps are added whilst accelerating
|
||||
uint8_t la_scaling; // Scale ISR frequency down and step frequency up by 2 ^ la_scaling
|
||||
uint16_t max_adv_steps, // Max advance steps to get cruising speed pressure
|
||||
final_adv_steps; // Advance steps for exit speed pressure
|
||||
#endif
|
||||
|
||||
uint32_t nominal_rate, // The nominal step rate for this block in step_events/sec
|
||||
uint64_t nominal_rate, // The nominal step rate for this block in step_events/sec
|
||||
initial_rate, // The jerk-adjusted step rate at start of block
|
||||
final_rate, // The minimal rate at exit
|
||||
acceleration_steps_per_s2; // acceleration steps/sec^2
|
||||
@@ -283,11 +292,11 @@ typedef struct PlannerBlock {
|
||||
#endif
|
||||
|
||||
#if HAS_WIRED_LCD
|
||||
uint32_t segment_time_us;
|
||||
uint64_t segment_time_us;
|
||||
#endif
|
||||
|
||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||
uint32_t sdpos;
|
||||
uint64_t sdpos;
|
||||
xyze_pos_t start_position;
|
||||
#endif
|
||||
|
||||
@@ -338,7 +347,7 @@ constexpr uint8_t block_inc_mod(const uint8_t v1, const uint8_t v2) {
|
||||
#endif
|
||||
|
||||
typedef struct PlannerSettings {
|
||||
uint32_t max_acceleration_mm_per_s2[DISTINCT_AXES], // (mm/s^2) M201 XYZE
|
||||
uint64_t max_acceleration_mm_per_s2[DISTINCT_AXES], // (mm/s^2) M201 XYZE
|
||||
min_segment_time_us; // (µs) M205 B
|
||||
|
||||
// (steps) M92 XYZE - Steps per millimeter
|
||||
@@ -442,7 +451,6 @@ class Planner {
|
||||
static block_t block_buffer[BLOCK_BUFFER_SIZE];
|
||||
static volatile uint8_t block_buffer_head, // Index of the next block to be pushed
|
||||
block_buffer_nonbusy, // Index of the first non busy block
|
||||
block_buffer_planned, // Index of the optimally planned block
|
||||
block_buffer_tail; // Index of the busy block, if any
|
||||
static uint16_t cleaning_buffer_counter; // A counter to disable queuing of blocks
|
||||
static uint8_t delay_before_delivering; // This counter delays delivery of blocks when queue becomes empty to allow the opportunity of merging blocks
|
||||
@@ -452,7 +460,7 @@ class Planner {
|
||||
#endif
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
static uint32_t last_page_step_rate; // Last page step rate given
|
||||
static uint64_t last_page_step_rate; // Last page step rate given
|
||||
static AxisBits last_page_dir; // Last page direction given, where 1 represents forward or positive motion
|
||||
#endif
|
||||
|
||||
@@ -479,7 +487,7 @@ class Planner {
|
||||
static laser_state_t laser_inline;
|
||||
#endif
|
||||
|
||||
static uint32_t max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) Derived from mm_per_s2
|
||||
static uint64_t max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) Derived from mm_per_s2
|
||||
|
||||
#if ENABLED(EDITABLE_STEPS_PER_UNIT)
|
||||
static float mm_per_step[DISTINCT_AXES]; // Millimeters per step
|
||||
@@ -569,7 +577,7 @@ class Planner {
|
||||
/**
|
||||
* Limit where 64bit math is necessary for acceleration calculation
|
||||
*/
|
||||
static uint32_t acceleration_long_cutoff;
|
||||
static uint64_t acceleration_long_cutoff;
|
||||
|
||||
#ifdef MAX7219_DEBUG_SLOWDOWN
|
||||
friend class Max7219;
|
||||
@@ -586,7 +594,7 @@ class Planner {
|
||||
#endif
|
||||
|
||||
#if HAS_WIRED_LCD
|
||||
volatile static uint32_t block_buffer_runtime_us; // Theoretical block buffer runtime in µs
|
||||
volatile static uint64_t block_buffer_runtime_us; // Theoretical block buffer runtime in µs
|
||||
#endif
|
||||
|
||||
public:
|
||||
@@ -804,7 +812,7 @@ class Planner {
|
||||
FORCE_INLINE static uint8_t nonbusy_movesplanned() { return block_dec_mod(block_buffer_head, block_buffer_nonbusy); }
|
||||
|
||||
// Remove all blocks from the buffer
|
||||
FORCE_INLINE static void clear_block_buffer() { block_buffer_nonbusy = block_buffer_planned = block_buffer_head = block_buffer_tail = 0; }
|
||||
FORCE_INLINE static void clear_block_buffer() { block_buffer_nonbusy = block_buffer_head = block_buffer_tail = 0; }
|
||||
|
||||
// Check if movement queue is full
|
||||
FORCE_INLINE static bool is_full() { return block_buffer_tail == next_block_index(block_buffer_head); }
|
||||
@@ -1081,13 +1089,12 @@ class Planner {
|
||||
}
|
||||
#endif
|
||||
|
||||
static void calculate_trapezoid_for_block(block_t * const block, const_float_t entry_factor, const_float_t exit_factor);
|
||||
static void calculate_trapezoid_for_block(block_t * const block, const_float_t entry_speed, const_float_t exit_speed);
|
||||
|
||||
static void reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr);
|
||||
static void forward_pass_kernel(const block_t * const previous, block_t * const current, uint8_t block_index);
|
||||
static bool reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr);
|
||||
static void forward_pass_kernel(const block_t * const previous, block_t * const current);
|
||||
|
||||
static void reverse_pass(const_float_t safe_exit_speed_sqr);
|
||||
static void forward_pass();
|
||||
|
||||
static void recalculate_trapezoids(const_float_t safe_exit_speed_sqr);
|
||||
|
||||
|
||||
+227
-99
@@ -58,16 +58,10 @@
|
||||
*
|
||||
* time ----->
|
||||
*
|
||||
* The speed over time graph forms a TRAPEZOID. The slope of acceleration is calculated by
|
||||
* v = u + t
|
||||
* where 't' is the accumulated timer values of the steps so far.
|
||||
*
|
||||
* The Stepper ISR dynamically executes acceleration, deceleration, and cruising according to the block parameters.
|
||||
* - Start at block->initial_rate.
|
||||
* - Accelerate while step_events_completed < block->accelerate_before.
|
||||
* - Cruise while step_events_completed < block->decelerate_start.
|
||||
* - Decelerate after that, until all steps are completed.
|
||||
* - Reset the trapezoid generator.
|
||||
* The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates
|
||||
* while step_events_completed < block->accelerate_before, then starts cruising at constant speed while
|
||||
* step_events_completed < block->decelerate_start, then it decelerates until the trapezoid generator is reset.
|
||||
* The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -160,9 +154,9 @@ Stepper stepper; // Singleton
|
||||
|
||||
#if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
|
||||
bool Stepper::initialized; // = false
|
||||
uint32_t Stepper::motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
|
||||
uint64_t Stepper::motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
|
||||
#if HAS_MOTOR_CURRENT_SPI
|
||||
constexpr uint32_t Stepper::digipot_count[];
|
||||
constexpr uint64_t Stepper::digipot_count[];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -200,7 +194,7 @@ bool Stepper::abort_current_block;
|
||||
#endif
|
||||
|
||||
// In timer_ticks
|
||||
uint32_t Stepper::acceleration_time, Stepper::deceleration_time;
|
||||
uint64_t Stepper::acceleration_time, Stepper::deceleration_time;
|
||||
|
||||
#if MULTISTEPPING_LIMIT > 1
|
||||
uint8_t Stepper::steps_per_isr = 1; // Count of steps to perform per Stepper ISR call
|
||||
@@ -229,7 +223,7 @@ uint32_t Stepper::acceleration_time, Stepper::deceleration_time;
|
||||
xyze_long_t Stepper::delta_error{0};
|
||||
|
||||
xyze_long_t Stepper::advance_dividend{0};
|
||||
uint32_t Stepper::advance_divisor = 0,
|
||||
uint64_t Stepper::advance_divisor = 0,
|
||||
Stepper::step_events_completed = 0, // The number of step events executed in the current block
|
||||
Stepper::accelerate_before, // The count at which to start cruising
|
||||
Stepper::decelerate_start, // The count at which to start decelerating
|
||||
@@ -245,8 +239,8 @@ uint32_t Stepper::advance_divisor = 0,
|
||||
int32_t __attribute__((used)) Stepper::bezier_A __asm__("bezier_A"); // A coefficient in Bézier speed curve with alias for assembler
|
||||
int32_t __attribute__((used)) Stepper::bezier_B __asm__("bezier_B"); // B coefficient in Bézier speed curve with alias for assembler
|
||||
int32_t __attribute__((used)) Stepper::bezier_C __asm__("bezier_C"); // C coefficient in Bézier speed curve with alias for assembler
|
||||
uint32_t __attribute__((used)) Stepper::bezier_F __asm__("bezier_F"); // F coefficient in Bézier speed curve with alias for assembler
|
||||
uint32_t __attribute__((used)) Stepper::bezier_AV __asm__("bezier_AV"); // AV coefficient in Bézier speed curve with alias for assembler
|
||||
uint64_t __attribute__((used)) Stepper::bezier_F __asm__("bezier_F"); // F coefficient in Bézier speed curve with alias for assembler
|
||||
uint64_t __attribute__((used)) Stepper::bezier_AV __asm__("bezier_AV"); // AV coefficient in Bézier speed curve with alias for assembler
|
||||
#ifdef __AVR__
|
||||
bool __attribute__((used)) Stepper::A_negative __asm__("A_negative"); // If A coefficient was negative
|
||||
#endif
|
||||
@@ -266,7 +260,7 @@ uint32_t Stepper::advance_divisor = 0,
|
||||
ne_coeff_t Stepper::ne;
|
||||
ne_fix_t Stepper::ne_fix;
|
||||
int32_t Stepper::ne_edividend;
|
||||
uint32_t Stepper::ne_scale;
|
||||
uint64_t Stepper::ne_scale;
|
||||
#endif
|
||||
|
||||
#if HAS_ZV_SHAPING
|
||||
@@ -303,7 +297,7 @@ uint32_t Stepper::advance_divisor = 0,
|
||||
|
||||
hal_timer_t Stepper::ticks_nominal = 0;
|
||||
#if DISABLED(S_CURVE_ACCELERATION)
|
||||
uint32_t Stepper::acc_step_rate; // needed for deceleration start point
|
||||
uint64_t Stepper::acc_step_rate; // needed for deceleration start point
|
||||
#endif
|
||||
|
||||
xyz_long_t Stepper::endstops_trigsteps;
|
||||
@@ -691,7 +685,7 @@ void Stepper::apply_directions() {
|
||||
* a "linear pop" velocity curve; with pop being the sixth derivative of position:
|
||||
* velocity - 1st, acceleration - 2nd, jerk - 3rd, snap - 4th, crackle - 5th, pop - 6th
|
||||
*
|
||||
* The Bézier curve takes the form:
|
||||
* The 6th order Bézier curve takes the form:
|
||||
*
|
||||
* V(t) = P_0 * B_0(t) + P_1 * B_1(t) + P_2 * B_2(t) + P_3 * B_3(t) + P_4 * B_4(t) + P_5 * B_5(t)
|
||||
*
|
||||
@@ -711,7 +705,10 @@ void Stepper::apply_directions() {
|
||||
* Unfortunately, we cannot use forward-differencing to calculate each position through
|
||||
* the curve, as Marlin uses variable timer periods. So, we require a formula of the form:
|
||||
*
|
||||
* 6th order:
|
||||
* V_f(t) = A*t^5 + B*t^4 + C*t^3 + D*t^2 + E*t + F
|
||||
* 4th order:
|
||||
* V_f(t) = A*t^3 + B*t^2 + C*t + F
|
||||
*
|
||||
* Looking at the above B_0(t) through B_5(t) expanded forms, if we take the coefficients of t^5
|
||||
* through t of the Bézier form of V(t), we can determine that:
|
||||
@@ -734,15 +731,27 @@ void Stepper::apply_directions() {
|
||||
* E = 0
|
||||
* F = P_i
|
||||
*
|
||||
* For 4th order we want the initial and final acceleration to be a fixed S_CURVE_FACTOR fraction
|
||||
* and solving gives us:
|
||||
*
|
||||
* A = 2*(1 - S_CURVE_FACTOR)*(P_i - P_t)
|
||||
* B = 3*(1 - S_CURVE_FACTOR)*(P_t - P_i)
|
||||
* C = S_CURVE_FACTOR*(P_t - P_i)
|
||||
* F = P_i
|
||||
*
|
||||
* As the t is evaluated in non uniform steps here, there is no other way rather than evaluating
|
||||
* the Bézier curve at each point:
|
||||
*
|
||||
* 6th order:
|
||||
* V_f(t) = A*t^5 + B*t^4 + C*t^3 + F [0 <= t <= 1]
|
||||
* 4th order:
|
||||
* V_f(t) = A*t^3 + B*t^2 + C*t + F [0 <= t <= 1]
|
||||
*
|
||||
* Floating point arithmetic execution time cost is prohibitive, so we will transform the math to
|
||||
* use fixed point values to be able to evaluate it in realtime. Assuming a maximum of 250000 steps
|
||||
* per second (driver pulses should at least be 2µS hi/2µS lo), and allocating 2 bits to avoid
|
||||
* overflows on the evaluation of the Bézier curve, means we can use
|
||||
* use fixed point values to be able to evaluate it in realtime.
|
||||
*
|
||||
* 6th order: Assumes a maximum of 250000 steps/s (driver pulses down to 2µS hi/2µS lo),
|
||||
* and allocates 2 bits to avoid overflows on the evaluation of the Bézier curve:
|
||||
*
|
||||
* t: unsigned Q0.32 (0 <= t < 1) |range 0 to 0xFFFFFFFF unsigned
|
||||
* A: signed Q24.7 , |range = +/- 250000 * 6 * 128 = +/- 192000000 = 0x0B71B000 | 28 bits + sign
|
||||
@@ -750,6 +759,8 @@ void Stepper::apply_directions() {
|
||||
* C: signed Q24.7 , |range = +/- 250000 *10 * 128 = +/- 320000000 = 0x1312D000 | 29 bits + sign
|
||||
* F: signed Q24.7 , |range = +/- 250000 * 128 = 32000000 = 0x01E84800 | 25 bits + sign
|
||||
*
|
||||
* 4th order: With B coefficient at least 5x smaller the maximum will be ~1250000 steps/s.
|
||||
*
|
||||
* The trapezoid generator state contains the following information, that we will use to create and evaluate
|
||||
* the Bézier curve:
|
||||
*
|
||||
@@ -764,42 +775,48 @@ void Stepper::apply_directions() {
|
||||
*
|
||||
* At the start of each trapezoid, calculate the coefficients A,B,C,F and Advance [AV], as follows:
|
||||
*
|
||||
* 6th order:
|
||||
* A = 6*128*(VF - VI) = 768*(VF - VI)
|
||||
* B = 15*128*(VI - VF) = 1920*(VI - VF)
|
||||
* C = 10*128*(VF - VI) = 1280*(VF - VI)
|
||||
* 4th order:
|
||||
* A = 2*(1-S_CURVE_FACTOR)*128*(VI - VF)
|
||||
* B = 3*(1-S_CURVE_FACTOR)*128*(VF - VI)
|
||||
* C = S_CURVE_FACTOR*128*(VF - VI)
|
||||
* both:
|
||||
* F = 128*VI = 128*VI
|
||||
* AV = (1<<32)/TS ~= 0xFFFFFFFF / TS (To use ARM UDIV, that is 32 bits) (this is computed at the planner, to offload expensive calculations from the ISR)
|
||||
*
|
||||
* And for each point, evaluate the curve with the following sequence:
|
||||
*
|
||||
* void lsrs(uint32_t& d, uint32_t s, int cnt) {
|
||||
* void lsrs(uint64_t& d, uint64_t s, int cnt) {
|
||||
* d = s >> cnt;
|
||||
* }
|
||||
* void lsls(uint32_t& d, uint32_t s, int cnt) {
|
||||
* void lsls(uint64_t& d, uint64_t s, int cnt) {
|
||||
* d = s << cnt;
|
||||
* }
|
||||
* void lsrs(int32_t& d, uint32_t s, int cnt) {
|
||||
* d = uint32_t(s) >> cnt;
|
||||
* void lsrs(int32_t& d, uint64_t s, int cnt) {
|
||||
* d = uint64_t(s) >> cnt;
|
||||
* }
|
||||
* void lsls(int32_t& d, uint32_t s, int cnt) {
|
||||
* d = uint32_t(s) << cnt;
|
||||
* void lsls(int32_t& d, uint64_t s, int cnt) {
|
||||
* d = uint64_t(s) << cnt;
|
||||
* }
|
||||
* void umull(uint32_t& rlo, uint32_t& rhi, uint32_t op1, uint32_t op2) {
|
||||
* void umull(uint64_t& rlo, uint64_t& rhi, uint64_t op1, uint64_t op2) {
|
||||
* uint64_t res = uint64_t(op1) * op2;
|
||||
* rlo = uint32_t(res & 0xFFFFFFFF);
|
||||
* rhi = uint32_t((res >> 32) & 0xFFFFFFFF);
|
||||
* rlo = uint64_t(res & 0xFFFFFFFF);
|
||||
* rhi = uint64_t((res >> 32) & 0xFFFFFFFF);
|
||||
* }
|
||||
* void smlal(int32_t& rlo, int32_t& rhi, int32_t op1, int32_t op2) {
|
||||
* int64_t mul = int64_t(op1) * op2;
|
||||
* int64_t s = int64_t(uint32_t(rlo) | ((uint64_t(uint32_t(rhi)) << 32U)));
|
||||
* int64_t s = int64_t(uint64_t(rlo) | ((uint64_t(uint64_t(rhi)) << 32U)));
|
||||
* mul += s;
|
||||
* rlo = int32_t(mul & 0xFFFFFFFF);
|
||||
* rhi = int32_t((mul >> 32) & 0xFFFFFFFF);
|
||||
* }
|
||||
* int32_t _eval_bezier_curve_arm(uint32_t curr_step) {
|
||||
* uint32_t flo = 0;
|
||||
* uint32_t fhi = bezier_AV * curr_step;
|
||||
* uint32_t t = fhi;
|
||||
* int32_t _eval_bezier_curve_arm(uint64_t curr_step) {
|
||||
* uint64_t flo = 0;
|
||||
* uint64_t fhi = bezier_AV * curr_step;
|
||||
* uint64_t t = fhi;
|
||||
* int32_t alo = bezier_F;
|
||||
* int32_t ahi = 0;
|
||||
* int32_t A = bezier_A;
|
||||
@@ -849,7 +866,7 @@ void Stepper::apply_directions() {
|
||||
*
|
||||
* And for each curve, estimate its coefficients with:
|
||||
*
|
||||
* void _calc_bezier_curve_coeffs(int32_t v0, int32_t v1, uint32_t av) {
|
||||
* void _calc_bezier_curve_coeffs(int32_t v0, int32_t v1, uint64_t av) {
|
||||
* // Calculate the Bézier coefficients
|
||||
* if (v1 < v0) {
|
||||
* A_negative = true;
|
||||
@@ -874,14 +891,14 @@ void Stepper::apply_directions() {
|
||||
* }
|
||||
* // unsigned multiplication of 16 bits x 16bits, return upper 16 bits
|
||||
* void umul16x16to16hi(uint16_t& r, uint16_t op1, uint16_t op2) {
|
||||
* r = (uint32_t(op1) * op2) >> 16;
|
||||
* r = (uint64_t(op1) * op2) >> 16;
|
||||
* }
|
||||
* // unsigned multiplication of 16 bits x 24bits, return upper 24 bits
|
||||
* void umul16x24to24hi(uint24_t& r, uint16_t op1, uint24_t op2) {
|
||||
* r = uint24_t((uint64_t(op1) * op2) >> 16);
|
||||
* }
|
||||
*
|
||||
* int32_t _eval_bezier_curve(uint32_t curr_step) {
|
||||
* int32_t _eval_bezier_curve(uint64_t curr_step) {
|
||||
* // To save computing, the first step is always the initial speed
|
||||
* if (!curr_step)
|
||||
* return bezier_F;
|
||||
@@ -923,7 +940,7 @@ void Stepper::apply_directions() {
|
||||
#ifdef __AVR__
|
||||
|
||||
// For AVR we use assembly to maximize speed
|
||||
void Stepper::_calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint32_t av) {
|
||||
void Stepper::_calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint64_t av) {
|
||||
|
||||
// Store advance
|
||||
bezier_AV = av;
|
||||
@@ -1025,7 +1042,7 @@ void Stepper::apply_directions() {
|
||||
);
|
||||
}
|
||||
|
||||
FORCE_INLINE int32_t Stepper::_eval_bezier_curve(const uint32_t curr_step) {
|
||||
FORCE_INLINE int32_t Stepper::_eval_bezier_curve(const uint64_t curr_step) {
|
||||
|
||||
// If dealing with the first step, save expensive computing and return the initial speed
|
||||
if (!curr_step)
|
||||
@@ -1407,28 +1424,36 @@ void Stepper::apply_directions() {
|
||||
:
|
||||
:"cc","r0","r1"
|
||||
);
|
||||
return (r2 | (uint16_t(r3) << 8)) | (uint32_t(r4) << 16);
|
||||
return (r2 | (uint16_t(r3) << 8)) | (uint64_t(r4) << 16);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// For all the other 32bit CPUs
|
||||
FORCE_INLINE void Stepper::_calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint32_t av) {
|
||||
FORCE_INLINE void Stepper::_calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint64_t av) {
|
||||
// Calculate the Bézier coefficients
|
||||
bezier_A = 768 * (v1 - v0);
|
||||
bezier_B = 1920 * (v0 - v1);
|
||||
bezier_C = 1280 * (v1 - v0);
|
||||
#ifndef S_CURVE_FACTOR
|
||||
bezier_A = 768 * (v1 - v0);
|
||||
bezier_B = 1920 * (v0 - v1);
|
||||
bezier_C = 1280 * (v1 - v0);
|
||||
#else
|
||||
// Must convert from S_CURVE_FACTOR to int only once.
|
||||
constexpr int FACTOR128 = S_CURVE_FACTOR * 128;
|
||||
bezier_A = (2 * (128 - FACTOR128)) * (v0 - v1);
|
||||
bezier_B = (3 * (128 - FACTOR128)) * (v1 - v0);
|
||||
bezier_C = FACTOR128 * (v1 - v0);
|
||||
#endif
|
||||
bezier_F = 128 * v0;
|
||||
bezier_AV = av;
|
||||
}
|
||||
|
||||
FORCE_INLINE int32_t Stepper::_eval_bezier_curve(const uint32_t curr_step) {
|
||||
FORCE_INLINE int32_t Stepper::_eval_bezier_curve(const uint64_t curr_step) {
|
||||
#if (defined(__arm__) || defined(__thumb__)) && __ARM_ARCH >= 6 && !defined(STM32G0B1xx) // TODO: Test define STM32G0xx versus STM32G0B1xx
|
||||
|
||||
// For ARM Cortex M3/M4 CPUs, we have the optimized assembler version, that takes 43 cycles to execute
|
||||
uint32_t flo = 0;
|
||||
uint32_t fhi = bezier_AV * curr_step;
|
||||
uint32_t t = fhi;
|
||||
uint64_t flo = 0;
|
||||
uint64_t fhi = bezier_AV * curr_step;
|
||||
uint64_t t = fhi;
|
||||
int32_t alo = bezier_F;
|
||||
int32_t ahi = 0;
|
||||
int32_t A = bezier_A;
|
||||
@@ -1439,8 +1464,10 @@ void Stepper::apply_directions() {
|
||||
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
|
||||
A("lsrs %[ahi],%[alo],#1") // a = F << 31 1 cycles
|
||||
A("lsls %[alo],%[alo],#31") // 1 cycles
|
||||
A("umull %[flo],%[fhi],%[fhi],%[t]") // f *= t 5 cycles [fhi:flo=64bits]
|
||||
A("umull %[flo],%[fhi],%[fhi],%[t]") // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
|
||||
#ifndef S_CURVE_FACTOR
|
||||
A("umull %[flo],%[fhi],%[fhi],%[t]") // f *= t 5 cycles [fhi:flo=64bits]
|
||||
A("umull %[flo],%[fhi],%[fhi],%[t]") // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
|
||||
#endif
|
||||
A("lsrs %[flo],%[fhi],#1") // 1 cycles [31bits]
|
||||
A("smlal %[alo],%[ahi],%[flo],%[C]") // a+=(f>>33)*C; 5 cycles
|
||||
A("umull %[flo],%[fhi],%[fhi],%[t]") // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
|
||||
@@ -1468,20 +1495,22 @@ void Stepper::apply_directions() {
|
||||
// For non ARM targets, we provide a fallback implementation. Really doubt it
|
||||
// will be useful, unless the processor is fast and 32bit
|
||||
|
||||
uint32_t t = bezier_AV * curr_step; // t: Range 0 - 1^32 = 32 bits
|
||||
uint64_t t = bezier_AV * curr_step; // t: Range 32 bits
|
||||
uint64_t f = t;
|
||||
f *= t; // Range 32*2 = 64 bits (unsigned)
|
||||
f >>= 32; // Range 32 bits (unsigned)
|
||||
f *= t; // Range 32*2 = 64 bits (unsigned)
|
||||
f >>= 32; // Range 32 bits : f = t^3 (unsigned)
|
||||
#ifndef S_CURVE_FACTOR
|
||||
f *= t; // Range 32*2 = 64 bits (unsigned)
|
||||
f >>= 32; // Range 32 bits (unsigned)
|
||||
f *= t; // Range 32*2 = 64 bits (unsigned)
|
||||
f >>= 32; // Range 32 bits : f = t^3 (unsigned)
|
||||
#endif
|
||||
int64_t acc = (int64_t) bezier_F << 31; // Range 63 bits (signed)
|
||||
acc += ((uint32_t) f >> 1) * (int64_t) bezier_C; // Range 29bits + 31 = 60bits (plus sign)
|
||||
acc += ((uint64_t) f >> 1) * (int64_t) bezier_C; // Range 29bits + 31 = 60bits (plus sign)
|
||||
f *= t; // Range 32*2 = 64 bits
|
||||
f >>= 32; // Range 32 bits : f = t^3 (unsigned)
|
||||
acc += ((uint32_t) f >> 1) * (int64_t) bezier_B; // Range 29bits + 31 = 60bits (plus sign)
|
||||
acc += ((uint64_t) f >> 1) * (int64_t) bezier_B; // Range 29bits + 31 = 60bits (plus sign)
|
||||
f *= t; // Range 32*2 = 64 bits
|
||||
f >>= 32; // Range 32 bits : f = t^3 (unsigned)
|
||||
acc += ((uint32_t) f >> 1) * (int64_t) bezier_A; // Range 28bits + 31 = 59bits (plus sign)
|
||||
acc += ((uint64_t) f >> 1) * (int64_t) bezier_A; // Range 28bits + 31 = 59bits (plus sign)
|
||||
acc >>= (31 + 7); // Range 24bits (plus sign)
|
||||
return (int32_t) acc;
|
||||
|
||||
@@ -1496,7 +1525,14 @@ void Stepper::apply_directions() {
|
||||
* Directly pulses the stepper motors at high frequency.
|
||||
*/
|
||||
|
||||
HAL_STEP_TIMER_ISR() {
|
||||
|
||||
extern "C" [[gnu::section(".ramcode")]] void TIMER0_IRQHandler() {
|
||||
#ifndef __AVR__
|
||||
// Disable interrupts, to avoid ISR preemption while we reprogram the period
|
||||
// (AVR enters the ISR with global interrupts disabled, so no need to do it here)
|
||||
hal.isr_off();
|
||||
#endif
|
||||
|
||||
HAL_timer_isr_prologue(MF_TIMER_STEP);
|
||||
|
||||
Stepper::isr();
|
||||
@@ -1514,12 +1550,6 @@ void Stepper::isr() {
|
||||
|
||||
static hal_timer_t nextMainISR = 0; // Interval until the next main Stepper Pulse phase (0 = Now)
|
||||
|
||||
#ifndef __AVR__
|
||||
// Disable interrupts, to avoid ISR preemption while we reprogram the period
|
||||
// (AVR enters the ISR with global interrupts disabled, so no need to do it here)
|
||||
hal.isr_off();
|
||||
#endif
|
||||
|
||||
// Program timer compare for the maximum period, so it does NOT
|
||||
// flag an interrupt while this ISR is running - So changes from small
|
||||
// periods to big periods are respected and the timer does not reset to 0
|
||||
@@ -1540,8 +1570,6 @@ void Stepper::isr() {
|
||||
// We need this variable here to be able to use it in the following loop
|
||||
hal_timer_t min_ticks;
|
||||
do {
|
||||
// Enable ISRs to reduce USART processing latency
|
||||
hal.isr_on();
|
||||
|
||||
hal_timer_t interval = 0;
|
||||
|
||||
@@ -1562,6 +1590,9 @@ void Stepper::isr() {
|
||||
NOLESS(nextBabystepISR, nextMainISR / 2); // TODO: Only look at axes enabled for baby-stepping
|
||||
#endif
|
||||
|
||||
// Enable ISRs to reduce latency for higher priority ISRs, or all ISRs if no prioritization.
|
||||
hal.isr_on();
|
||||
|
||||
interval = nextMainISR; // Interval is either some old nextMainISR or FTM_MIN_TICKS
|
||||
TERN_(BABYSTEPPING, NOMORE(interval, nextBabystepISR)); // Come back early for Babystepping?
|
||||
|
||||
@@ -1590,6 +1621,9 @@ void Stepper::isr() {
|
||||
if (is_babystep) nextBabystepISR = babystepping_isr();
|
||||
#endif
|
||||
|
||||
// Enable ISRs to reduce latency for higher priority ISRs, or all ISRs if no prioritization.
|
||||
hal.isr_on();
|
||||
|
||||
// ^== Time critical. NOTHING besides pulse generation should be above here!!!
|
||||
|
||||
if (!nextMainISR) nextMainISR = block_phase_isr(); // Manage acc/deceleration, get next block
|
||||
@@ -1603,7 +1637,7 @@ void Stepper::isr() {
|
||||
#endif
|
||||
|
||||
// Get the interval to the next ISR call
|
||||
interval = _MIN(nextMainISR, uint32_t(HAL_TIMER_TYPE_MAX)); // Time until the next Pulse / Block phase
|
||||
interval = _MIN(nextMainISR, uint64_t(HAL_TIMER_TYPE_MAX)); // Time until the next Pulse / Block phase
|
||||
TERN_(INPUT_SHAPING_X, NOMORE(interval, ShapingQueue::peek_x())); // Time until next input shaping echo for X
|
||||
TERN_(INPUT_SHAPING_Y, NOMORE(interval, ShapingQueue::peek_y())); // Time until next input shaping echo for Y
|
||||
TERN_(INPUT_SHAPING_Z, NOMORE(interval, ShapingQueue::peek_z())); // Time until next input shaping echo for Z
|
||||
@@ -1723,7 +1757,7 @@ void Stepper::isr() {
|
||||
#if MINIMUM_STEPPER_PULSE || MAXIMUM_STEPPER_RATE
|
||||
#define ISR_PULSE_CONTROL 1
|
||||
#endif
|
||||
#if ISR_PULSE_CONTROL && DISABLED(I2S_STEPPER_STREAM)
|
||||
#if ISR_PULSE_CONTROL && MULTISTEPPING_LIMIT > 1 && DISABLED(I2S_STEPPER_STREAM)
|
||||
#define ISR_MULTI_STEPS 1
|
||||
#endif
|
||||
|
||||
@@ -1766,17 +1800,15 @@ void Stepper::pulse_phase_isr() {
|
||||
if (TERN0(FREEZE_FEATURE, frozen)) return;
|
||||
|
||||
// Count of pending loops and events for this iteration
|
||||
const uint32_t pending_events = step_event_count - step_events_completed;
|
||||
const uint64_t pending_events = step_event_count - step_events_completed;
|
||||
uint8_t events_to_do = _MIN(pending_events, steps_per_isr);
|
||||
|
||||
// Just update the value we will get at the end of the loop
|
||||
step_events_completed += events_to_do;
|
||||
|
||||
TERN_(ISR_PULSE_CONTROL, USING_TIMED_PULSE());
|
||||
// Take multiple steps per interrupt (For high speed moves)
|
||||
#if ISR_MULTI_STEPS
|
||||
bool firstStep = true;
|
||||
USING_TIMED_PULSE();
|
||||
#endif
|
||||
TERN_(ISR_MULTI_STEPS, bool firstStep = true);
|
||||
|
||||
// Direct Stepping page?
|
||||
const bool is_page = current_block->is_page();
|
||||
@@ -1965,7 +1997,7 @@ void Stepper::pulse_phase_isr() {
|
||||
|
||||
if (!is_page) {
|
||||
// Give the compiler a clue to store advance_divisor in registers for what follows
|
||||
const uint32_t advance_divisor_cached = advance_divisor;
|
||||
const uint64_t advance_divisor_cached = advance_divisor;
|
||||
|
||||
// Determine if pulses are needed
|
||||
#if HAS_X_STEP
|
||||
@@ -2081,7 +2113,7 @@ void Stepper::pulse_phase_isr() {
|
||||
TERN_(I2S_STEPPER_STREAM, i2s_push_sample());
|
||||
|
||||
// TODO: need to deal with MINIMUM_STEPPER_PULSE over i2s
|
||||
#if ISR_MULTI_STEPS
|
||||
#if ISR_PULSE_CONTROL
|
||||
START_TIMED_PULSE();
|
||||
AWAIT_HIGH_PULSE();
|
||||
#endif
|
||||
@@ -2196,24 +2228,24 @@ void Stepper::pulse_phase_isr() {
|
||||
#endif // HAS_ZV_SHAPING
|
||||
|
||||
// Calculate timer interval, with all limits applied.
|
||||
hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
|
||||
hal_timer_t Stepper::calc_timer_interval(uint64_t step_rate) {
|
||||
|
||||
constexpr uint64_t min_step_rate = MINIMAL_STEP_RATE;
|
||||
|
||||
#ifdef CPU_32_BIT
|
||||
|
||||
// A fast processor can just do integer division
|
||||
constexpr uint32_t min_step_rate = uint32_t(STEPPER_TIMER_RATE) / HAL_TIMER_TYPE_MAX;
|
||||
return step_rate > min_step_rate ? uint32_t(STEPPER_TIMER_RATE) / step_rate : HAL_TIMER_TYPE_MAX;
|
||||
return step_rate > min_step_rate ? uint64_t(STEPPER_TIMER_RATE) / step_rate : HAL_TIMER_TYPE_MAX;
|
||||
|
||||
#else
|
||||
|
||||
constexpr uint32_t min_step_rate = (F_CPU) / 500000U; // i.e., 32 or 40
|
||||
if (step_rate >= 0x0800) { // higher step rate
|
||||
// AVR is able to keep up at around 65kHz Stepping ISR rate at most.
|
||||
// So values for step_rate > 65535 might as well be truncated.
|
||||
// Handle it as quickly as possible. i.e., assume highest byte is zero
|
||||
// because non-zero would represent a step rate far beyond AVR capabilities.
|
||||
if (uint8_t(step_rate >> 16))
|
||||
return uint32_t(STEPPER_TIMER_RATE) / 0x10000;
|
||||
return uint64_t(STEPPER_TIMER_RATE) / 0x10000;
|
||||
|
||||
const uintptr_t table_address = uintptr_t(&speed_lookuptable_fast[uint8_t(step_rate >> 8)]);
|
||||
const uint16_t base = uint16_t(pgm_read_word(table_address));
|
||||
@@ -2233,8 +2265,8 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
|
||||
}
|
||||
|
||||
#if ENABLED(NONLINEAR_EXTRUSION)
|
||||
void Stepper::calc_nonlinear_e(uint32_t step_rate) {
|
||||
const uint32_t velocity = ne_scale * step_rate; // Scale step_rate first so all intermediate values stay in range of 8.24 fixed point math
|
||||
void Stepper::calc_nonlinear_e(uint64_t step_rate) {
|
||||
const uint64_t velocity = ne_scale * step_rate; // Scale step_rate first so all intermediate values stay in range of 8.24 fixed point math
|
||||
int32_t vd = (((int64_t)ne_fix.A * velocity) >> 24) + (((((int64_t)ne_fix.B * velocity) >> 24) * velocity) >> 24);
|
||||
NOLESS(vd, 0);
|
||||
|
||||
@@ -2243,19 +2275,19 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
|
||||
#endif
|
||||
|
||||
// Get the timer interval and the number of loops to perform per tick
|
||||
hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) {
|
||||
hal_timer_t Stepper::calc_multistep_timer_interval(uint64_t step_rate) {
|
||||
|
||||
#if ENABLED(OLD_ADAPTIVE_MULTISTEPPING)
|
||||
|
||||
#if MULTISTEPPING_LIMIT == 1
|
||||
|
||||
// Just make sure the step rate is doable
|
||||
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
|
||||
NOMORE(step_rate, uint64_t(MAX_STEP_ISR_FREQUENCY_1X));
|
||||
|
||||
#else
|
||||
|
||||
// The stepping frequency limits for each multistepping rate
|
||||
static const uint32_t limit[] PROGMEM = {
|
||||
static const uint64_t limit[] PROGMEM = {
|
||||
( MAX_STEP_ISR_FREQUENCY_1X )
|
||||
, (((F_CPU) / ISR_EXECUTION_CYCLES(1)) >> 1)
|
||||
#if MULTISTEPPING_LIMIT >= 4
|
||||
@@ -2280,7 +2312,7 @@ hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) {
|
||||
|
||||
// Find a doable step rate using multistepping
|
||||
uint8_t multistep = 1;
|
||||
for (uint8_t i = 0; i < COUNT(limit) && step_rate > uint32_t(pgm_read_dword(&limit[i])); ++i) {
|
||||
for (uint8_t i = 0; i < COUNT(limit) && step_rate > uint64_t(pgm_read_dword(&limit[i])); ++i) {
|
||||
step_rate >>= 1;
|
||||
multistep <<= 1;
|
||||
}
|
||||
@@ -2439,7 +2471,7 @@ hal_timer_t Stepper::block_phase_isr() {
|
||||
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
// Get the next speed to use (Jerk limited!)
|
||||
uint32_t acc_step_rate = acceleration_time < current_block->acceleration_time
|
||||
uint64_t acc_step_rate = acceleration_time < current_block->acceleration_time
|
||||
? _eval_bezier_curve(acceleration_time)
|
||||
: current_block->cruise_rate;
|
||||
#else
|
||||
@@ -2460,7 +2492,7 @@ hal_timer_t Stepper::block_phase_isr() {
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
if (la_active) {
|
||||
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
|
||||
const uint64_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
|
||||
la_interval = calc_timer_interval((acc_step_rate + la_step_rate) >> current_block->la_scaling);
|
||||
}
|
||||
#endif
|
||||
@@ -2490,7 +2522,7 @@ hal_timer_t Stepper::block_phase_isr() {
|
||||
}
|
||||
// Are we in Deceleration phase ?
|
||||
else if (step_events_completed >= decelerate_start) {
|
||||
uint32_t step_rate;
|
||||
uint64_t step_rate;
|
||||
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
// If this is the 1st time we process the 2nd half of the trapezoid...
|
||||
@@ -2525,7 +2557,7 @@ hal_timer_t Stepper::block_phase_isr() {
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
if (la_active) {
|
||||
const uint32_t la_step_rate = la_advance_steps > current_block->final_adv_steps ? current_block->la_advance_rate : 0;
|
||||
const uint64_t la_step_rate = la_advance_steps > current_block->final_adv_steps ? current_block->la_advance_rate : 0;
|
||||
if (la_step_rate != step_rate) {
|
||||
const bool forward_e = la_step_rate < step_rate;
|
||||
la_interval = calc_timer_interval((forward_e ? step_rate - la_step_rate : la_step_rate - step_rate) >> current_block->la_scaling);
|
||||
@@ -2600,6 +2632,25 @@ hal_timer_t Stepper::block_phase_isr() {
|
||||
// The timer interval is just the nominal value for the nominal speed
|
||||
interval = ticks_nominal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust Laser Power - Cruise
|
||||
* power - direct or floor adjusted active laser power.
|
||||
*/
|
||||
#if ENABLED(LASER_POWER_TRAP)
|
||||
if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS) {
|
||||
if (step_events_completed + 1 == accelerate_before) {
|
||||
if (planner.laser_inline.status.isPowered && planner.laser_inline.status.isEnabled) {
|
||||
if (current_block->laser.trap_ramp_entry_incr > 0) {
|
||||
current_block->laser.trap_ramp_active_pwr = current_block->laser.power;
|
||||
cutter.apply_power(current_block->laser.power);
|
||||
}
|
||||
}
|
||||
// Not a powered move.
|
||||
else cutter.apply_power(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLED(LASER_FEATURE)
|
||||
@@ -2691,8 +2742,85 @@ hal_timer_t Stepper::block_phase_isr() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set flags for all moving axes, accounting for kinematics
|
||||
set_axis_moved_for_current_block();
|
||||
// Flag all moving axes for proper endstop handling
|
||||
|
||||
#if IS_CORE
|
||||
// Define conditions for checking endstops
|
||||
#define S_(N) current_block->steps[CORE_AXIS_##N]
|
||||
#define D_(N) current_block->direction_bits[CORE_AXIS_##N]
|
||||
#endif
|
||||
|
||||
#if CORE_IS_XY || CORE_IS_XZ
|
||||
/**
|
||||
* Head direction in -X axis for CoreXY and CoreXZ bots.
|
||||
*
|
||||
* If steps differ, both axes are moving.
|
||||
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z, handled below)
|
||||
* If DeltaA == DeltaB, the movement is only in the 1st axis (X)
|
||||
*/
|
||||
#if ANY(COREXY, COREXZ)
|
||||
#define X_CMP(A,B) ((A)==(B))
|
||||
#else
|
||||
#define X_CMP(A,B) ((A)!=(B))
|
||||
#endif
|
||||
#define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && X_CMP(D_(1),D_(2))) )
|
||||
#elif ENABLED(MARKFORGED_XY)
|
||||
#define X_MOVE_TEST (current_block->steps.a != current_block->steps.b)
|
||||
#else
|
||||
#define X_MOVE_TEST !!current_block->steps.a
|
||||
#endif
|
||||
|
||||
#if CORE_IS_XY || CORE_IS_YZ
|
||||
/**
|
||||
* Head direction in -Y axis for CoreXY / CoreYZ bots.
|
||||
*
|
||||
* If steps differ, both axes are moving
|
||||
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y)
|
||||
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z)
|
||||
*/
|
||||
#if ANY(COREYX, COREYZ)
|
||||
#define Y_CMP(A,B) ((A)==(B))
|
||||
#else
|
||||
#define Y_CMP(A,B) ((A)!=(B))
|
||||
#endif
|
||||
#define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Y_CMP(D_(1),D_(2))) )
|
||||
#elif ENABLED(MARKFORGED_YX)
|
||||
#define Y_MOVE_TEST (current_block->steps.a != current_block->steps.b)
|
||||
#else
|
||||
#define Y_MOVE_TEST !!current_block->steps.b
|
||||
#endif
|
||||
|
||||
#if CORE_IS_XZ || CORE_IS_YZ
|
||||
/**
|
||||
* Head direction in -Z axis for CoreXZ or CoreYZ bots.
|
||||
*
|
||||
* If steps differ, both axes are moving
|
||||
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y, already handled above)
|
||||
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Z)
|
||||
*/
|
||||
#if ANY(COREZX, COREZY)
|
||||
#define Z_CMP(A,B) ((A)==(B))
|
||||
#else
|
||||
#define Z_CMP(A,B) ((A)!=(B))
|
||||
#endif
|
||||
#define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Z_CMP(D_(1),D_(2))) )
|
||||
#else
|
||||
#define Z_MOVE_TEST !!current_block->steps.c
|
||||
#endif
|
||||
|
||||
AxisBits didmove;
|
||||
NUM_AXIS_CODE(
|
||||
if (X_MOVE_TEST) didmove.a = true,
|
||||
if (Y_MOVE_TEST) didmove.b = true,
|
||||
if (Z_MOVE_TEST) didmove.c = true,
|
||||
if (!!current_block->steps.i) didmove.i = true,
|
||||
if (!!current_block->steps.j) didmove.j = true,
|
||||
if (!!current_block->steps.k) didmove.k = true,
|
||||
if (!!current_block->steps.u) didmove.u = true,
|
||||
if (!!current_block->steps.v) didmove.v = true,
|
||||
if (!!current_block->steps.w) didmove.w = true
|
||||
);
|
||||
axis_did_move = didmove;
|
||||
|
||||
#if ENABLED(ADAPTIVE_STEP_SMOOTHING)
|
||||
// Nonlinear Extrusion needs at least 2x oversampling to permit increase of E step rate
|
||||
@@ -2701,7 +2829,7 @@ hal_timer_t Stepper::block_phase_isr() {
|
||||
|
||||
// Decide if axis smoothing is possible
|
||||
if (stepper.adaptive_step_smoothing_enabled) {
|
||||
uint32_t max_rate = current_block->nominal_rate; // Get the step event rate
|
||||
uint64_t max_rate = current_block->nominal_rate; // Get the step event rate
|
||||
while (max_rate < MIN_STEP_ISR_FREQUENCY) { // As long as more ISRs are possible...
|
||||
max_rate <<= 1; // Try to double the rate
|
||||
if (max_rate < MIN_STEP_ISR_FREQUENCY) // Don't exceed the estimated ISR limit
|
||||
@@ -2852,7 +2980,7 @@ hal_timer_t Stepper::block_phase_isr() {
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
if (la_active) {
|
||||
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
|
||||
const uint64_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
|
||||
la_interval = calc_timer_interval((current_block->initial_rate + la_step_rate) >> current_block->la_scaling);
|
||||
}
|
||||
#endif
|
||||
@@ -3272,7 +3400,7 @@ void Stepper::init() {
|
||||
const bool was_on = hal.isr_state();
|
||||
hal.isr_off();
|
||||
|
||||
const shaping_time_t delay = freq ? float(uint32_t(STEPPER_TIMER_RATE) / 2) / freq : shaping_time_t(-1);
|
||||
const shaping_time_t delay = freq ? float(uint64_t(STEPPER_TIMER_RATE) / 2) / freq : shaping_time_t(-1);
|
||||
#define SHAPING_SET_FREQ_FOR_AXIS(AXISN, AXISL) \
|
||||
if (axis == AXISN) { \
|
||||
ShapingQueue::set_delay(AXISN, delay); \
|
||||
@@ -3757,7 +3885,7 @@ void Stepper::report_positions() {
|
||||
|
||||
#if EXTRA_CYCLES_BABYSTEP > 20
|
||||
#define _SAVE_START() const hal_timer_t pulse_start = HAL_timer_get_count(MF_TIMER_PULSE)
|
||||
#define _PULSE_WAIT() while (EXTRA_CYCLES_BABYSTEP > uint32_t(HAL_timer_get_count(MF_TIMER_PULSE) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ }
|
||||
#define _PULSE_WAIT() while (EXTRA_CYCLES_BABYSTEP > uint64_t(HAL_timer_get_count(MF_TIMER_PULSE) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ }
|
||||
#else
|
||||
#define _SAVE_START() NOOP
|
||||
#if EXTRA_CYCLES_BABYSTEP > 0
|
||||
|
||||
+19
-19
@@ -309,11 +309,11 @@ class Stepper {
|
||||
#endif
|
||||
#define MOTOR_CURRENT_COUNT 3
|
||||
#elif HAS_MOTOR_CURRENT_SPI
|
||||
static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT;
|
||||
static constexpr uint64_t digipot_count[] = DIGIPOT_MOTOR_CURRENT;
|
||||
#define MOTOR_CURRENT_COUNT COUNT(Stepper::digipot_count)
|
||||
#endif
|
||||
static bool initialized;
|
||||
static uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
|
||||
static uint64_t motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
|
||||
#endif
|
||||
|
||||
// Last-moved extruder, as set when the last movement was fetched from planner
|
||||
@@ -363,7 +363,7 @@ class Stepper {
|
||||
;
|
||||
#endif
|
||||
|
||||
static uint32_t acceleration_time, deceleration_time; // time measured in Stepper Timer ticks
|
||||
static uint64_t acceleration_time, deceleration_time; // time measured in Stepper Timer ticks
|
||||
|
||||
#if MULTISTEPPING_LIMIT == 1
|
||||
static constexpr uint8_t steps_per_isr = 1; // Count of steps to perform per Stepper ISR call
|
||||
@@ -384,10 +384,10 @@ class Stepper {
|
||||
// Delta error variables for the Bresenham line tracer
|
||||
static xyze_long_t delta_error;
|
||||
static xyze_long_t advance_dividend;
|
||||
static uint32_t advance_divisor,
|
||||
static uint64_t advance_divisor,
|
||||
step_events_completed, // The number of step events executed in the current block
|
||||
accelerate_before, // The count at which to start cruising
|
||||
decelerate_start, // The count at which to start decelerating
|
||||
accelerate_before, // The point from where we need to stop acceleration
|
||||
decelerate_start, // The point from where we need to start decelerating
|
||||
step_event_count; // The total event count for the current block
|
||||
|
||||
#if ANY(HAS_MULTI_EXTRUDER, MIXING_EXTRUDER)
|
||||
@@ -400,7 +400,7 @@ class Stepper {
|
||||
static int32_t bezier_A, // A coefficient in Bézier speed curve
|
||||
bezier_B, // B coefficient in Bézier speed curve
|
||||
bezier_C; // C coefficient in Bézier speed curve
|
||||
static uint32_t bezier_F, // F coefficient in Bézier speed curve
|
||||
static uint64_t bezier_F, // F/free coefficient in Bézier speed curve
|
||||
bezier_AV; // AV coefficient in Bézier speed curve
|
||||
#ifdef __AVR__
|
||||
static bool A_negative; // If A coefficient was negative
|
||||
@@ -432,7 +432,7 @@ class Stepper {
|
||||
|
||||
#if ENABLED(NONLINEAR_EXTRUSION)
|
||||
static int32_t ne_edividend;
|
||||
static uint32_t ne_scale;
|
||||
static uint64_t ne_scale;
|
||||
static ne_fix_t ne_fix;
|
||||
#endif
|
||||
|
||||
@@ -447,7 +447,7 @@ class Stepper {
|
||||
|
||||
static hal_timer_t ticks_nominal;
|
||||
#if DISABLED(S_CURVE_ACCELERATION)
|
||||
static uint32_t acc_step_rate; // needed for deceleration start point
|
||||
static uint64_t acc_step_rate; // needed for deceleration start point
|
||||
#endif
|
||||
|
||||
// Exact steps at which an endstop was triggered
|
||||
@@ -478,21 +478,21 @@ class Stepper {
|
||||
}
|
||||
|
||||
// The ISR scheduler
|
||||
static void isr();
|
||||
FORCE_INLINE static void isr();
|
||||
|
||||
// The stepper pulse ISR phase
|
||||
static void pulse_phase_isr();
|
||||
FORCE_INLINE static void pulse_phase_isr();
|
||||
|
||||
// The stepper block processing ISR phase
|
||||
static hal_timer_t block_phase_isr();
|
||||
FORCE_INLINE static hal_timer_t block_phase_isr();
|
||||
|
||||
#if HAS_ZV_SHAPING
|
||||
static void shaping_isr();
|
||||
FORCE_INLINE static void shaping_isr();
|
||||
#endif
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
// The Linear advance ISR phase
|
||||
static void advance_isr();
|
||||
FORCE_INLINE static void advance_isr();
|
||||
#endif
|
||||
|
||||
#if ENABLED(BABYSTEPPING)
|
||||
@@ -677,21 +677,21 @@ class Stepper {
|
||||
static void _set_position(const abce_long_t &spos);
|
||||
|
||||
// Calculate the timing interval for the given step rate
|
||||
static hal_timer_t calc_timer_interval(uint32_t step_rate);
|
||||
static hal_timer_t calc_timer_interval(uint64_t step_rate);
|
||||
|
||||
// Calculate timing interval and steps-per-ISR for the given step rate
|
||||
static hal_timer_t calc_multistep_timer_interval(uint32_t step_rate);
|
||||
static hal_timer_t calc_multistep_timer_interval(uint64_t step_rate);
|
||||
|
||||
// Evaluate axis motions and set bits in axis_did_move
|
||||
static void set_axis_moved_for_current_block();
|
||||
|
||||
#if ENABLED(NONLINEAR_EXTRUSION)
|
||||
static void calc_nonlinear_e(uint32_t step_rate);
|
||||
static void calc_nonlinear_e(uint64_t step_rate);
|
||||
#endif
|
||||
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
static void _calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint32_t av);
|
||||
static int32_t _eval_bezier_curve(const uint32_t curr_step);
|
||||
static void _calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint64_t av);
|
||||
static int32_t _eval_bezier_curve(const uint64_t curr_step);
|
||||
#endif
|
||||
|
||||
#if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
|
||||
|
||||
@@ -22,11 +22,31 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Native with a RAMPS like board with additional pins
|
||||
* Arduino Mega with RAMPS v1.4 (or v1.3) pin assignments
|
||||
*
|
||||
* Applies to the following boards:
|
||||
*
|
||||
* RAMPS_14_EFB (Hotend, Fan, Bed)
|
||||
* RAMPS_14_EEB (Hotend0, Hotend1, Bed)
|
||||
* RAMPS_14_EFF (Hotend, Fan0, Fan1)
|
||||
* RAMPS_14_EEF (Hotend0, Hotend1, Fan)
|
||||
* RAMPS_14_SF (Spindle, Controller Fan)
|
||||
*
|
||||
* RAMPS_13_EFB (Hotend, Fan, Bed)
|
||||
* RAMPS_13_EEB (Hotend0, Hotend1, Bed)
|
||||
* RAMPS_13_EFF (Hotend, Fan0, Fan1)
|
||||
* RAMPS_13_EEF (Hotend0, Hotend1, Fan)
|
||||
* RAMPS_13_SF (Spindle, Controller Fan)
|
||||
*
|
||||
* Other pins_MYBOARD.h files may override these defaults
|
||||
*
|
||||
* Differences between
|
||||
* RAMPS_13 | RAMPS_14
|
||||
* 7 | 11
|
||||
*/
|
||||
|
||||
#ifndef BOARD_INFO_NAME
|
||||
#define BOARD_INFO_NAME "RAMPS Native"
|
||||
#define BOARD_INFO_NAME "RAMPS 1.4"
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_MACHINE_NAME
|
||||
@@ -40,24 +60,28 @@
|
||||
//
|
||||
// Servos
|
||||
//
|
||||
#define SERVO0_PIN 151
|
||||
#define SERVO1_PIN 152
|
||||
#define SERVO2_PIN 153
|
||||
#ifdef IS_RAMPS_13
|
||||
#define SERVO0_PIN 7 // RAMPS_13 // Will conflict with BTN_EN2 on LCD_I2C_VIKI
|
||||
#else
|
||||
#define SERVO0_PIN 11
|
||||
#endif
|
||||
#define SERVO1_PIN 6
|
||||
#define SERVO2_PIN 5
|
||||
#ifndef SERVO3_PIN
|
||||
#define SERVO3_PIN 154
|
||||
#define SERVO3_PIN 4
|
||||
#endif
|
||||
|
||||
//
|
||||
// Limit Switches
|
||||
//
|
||||
#define X_MIN_PIN 155
|
||||
#define X_MIN_PIN 3
|
||||
#ifndef X_MAX_PIN
|
||||
#define X_MAX_PIN 156
|
||||
#define X_MAX_PIN 2
|
||||
#endif
|
||||
#define Y_MIN_PIN 157
|
||||
#define Y_MAX_PIN 158
|
||||
#define Z_MIN_PIN 159
|
||||
#define Z_MAX_PIN 160
|
||||
#define Y_MIN_PIN 14
|
||||
#define Y_MAX_PIN 15
|
||||
#define Z_MIN_PIN 18
|
||||
#define Z_MAX_PIN 19
|
||||
|
||||
//
|
||||
// Z Probe (when not Z_MIN_PIN)
|
||||
@@ -104,60 +128,24 @@
|
||||
#define E1_CS_PIN 44
|
||||
#endif
|
||||
|
||||
#define E2_STEP_PIN 100
|
||||
#define E2_DIR_PIN 101
|
||||
#define E2_ENABLE_PIN 102
|
||||
#ifndef E2_CS_PIN
|
||||
#define E2_CS_PIN 103
|
||||
#endif
|
||||
#define Z4_STEP_PIN 13
|
||||
#define Z4_DIR_PIN 71
|
||||
#define Z4_ENABLE_PIN 12
|
||||
|
||||
#define E3_STEP_PIN 104
|
||||
#define E3_DIR_PIN 105
|
||||
#define E3_ENABLE_PIN 106
|
||||
#ifndef E3_CS_PIN
|
||||
#define E3_CS_PIN 107
|
||||
#endif
|
||||
#define Z2_STEP_PIN 4
|
||||
#define Z2_DIR_PIN 5
|
||||
#define Z2_ENABLE_PIN 6
|
||||
|
||||
#define E4_STEP_PIN 108
|
||||
#define E4_DIR_PIN 109
|
||||
#define E4_ENABLE_PIN 110
|
||||
#ifndef E4_CS_PIN
|
||||
#define E4_CS_PIN 111
|
||||
#endif
|
||||
|
||||
#define E5_STEP_PIN 112
|
||||
#define E5_DIR_PIN 113
|
||||
#define E5_ENABLE_PIN 114
|
||||
#ifndef E5_CS_PIN
|
||||
#define E5_CS_PIN 115
|
||||
#endif
|
||||
|
||||
#define E6_STEP_PIN 116
|
||||
#define E6_DIR_PIN 117
|
||||
#define E6_ENABLE_PIN 118
|
||||
#ifndef E6_CS_PIN
|
||||
#define E6_CS_PIN 119
|
||||
#endif
|
||||
|
||||
#define E7_STEP_PIN 120
|
||||
#define E7_DIR_PIN 121
|
||||
#define E7_ENABLE_PIN 122
|
||||
#ifndef E7_CS_PIN
|
||||
#define E7_CS_PIN 123
|
||||
#endif
|
||||
#define Z3_STEP_PIN 12
|
||||
#define Z3_DIR_PIN 40
|
||||
#define Z3_ENABLE_PIN 44
|
||||
|
||||
//
|
||||
// Temperature Sensors
|
||||
//
|
||||
#define TEMP_0_PIN 0 // Analog Input
|
||||
#define TEMP_1_PIN 1 // Analog Input
|
||||
#define TEMP_2_PIN 2 // Analog Input
|
||||
#define TEMP_3_PIN 3 // Analog Input
|
||||
#define TEMP_4_PIN 4 // Analog Input
|
||||
#define TEMP_5_PIN 5 // Analog Input
|
||||
#define TEMP_6_PIN 6 // Analog Input
|
||||
#define TEMP_7_PIN 7 // Analog Input
|
||||
#define TEMP_BED_PIN 8 // Analog Input
|
||||
#define TEMP_BED_PIN 2 // Analog Input
|
||||
|
||||
// SPI for MAX Thermocouple
|
||||
#if !HAS_MEDIA
|
||||
@@ -169,33 +157,55 @@
|
||||
//
|
||||
// Heaters / Fans
|
||||
//
|
||||
#define HEATER_0_PIN 10
|
||||
#define HEATER_1_PIN 9
|
||||
#define HEATER_2_PIN 8
|
||||
#define HEATER_3_PIN 125
|
||||
#define HEATER_4_PIN 126
|
||||
#define HEATER_5_PIN 127
|
||||
#define HEATER_6_PIN 128
|
||||
#define HEATER_7_PIN 129
|
||||
#define HEATER_BED_PIN 108
|
||||
#ifndef MOSFET_A_PIN
|
||||
#define MOSFET_A_PIN 10
|
||||
#endif
|
||||
#ifndef MOSFET_B_PIN
|
||||
#define MOSFET_B_PIN 9
|
||||
#endif
|
||||
#ifndef MOSFET_C_PIN
|
||||
#define MOSFET_C_PIN 8
|
||||
#endif
|
||||
#ifndef MOSFET_D_PIN
|
||||
#define MOSFET_D_PIN -1
|
||||
#endif
|
||||
|
||||
#define HEATER_0_PIN MOSFET_A_PIN
|
||||
|
||||
#if FET_ORDER_EFB // Hotend, Fan, Bed
|
||||
#define FAN0_PIN MOSFET_B_PIN
|
||||
#define HEATER_BED_PIN MOSFET_C_PIN
|
||||
#elif FET_ORDER_EEF // Hotend, Hotend, Fan
|
||||
#define HEATER_1_PIN MOSFET_B_PIN
|
||||
#define FAN0_PIN MOSFET_C_PIN
|
||||
#elif FET_ORDER_EEB // Hotend, Hotend, Bed
|
||||
#define HEATER_1_PIN MOSFET_B_PIN
|
||||
#define HEATER_BED_PIN MOSFET_C_PIN
|
||||
#elif FET_ORDER_EFF // Hotend, Fan, Fan
|
||||
#define FAN0_PIN MOSFET_B_PIN
|
||||
#define FAN1_PIN MOSFET_C_PIN
|
||||
#elif FET_ORDER_SF // Spindle, Fan
|
||||
#define FAN0_PIN MOSFET_C_PIN
|
||||
#else // Non-specific are "EFB" (i.e., "EFBF" or "EFBE")
|
||||
#define FAN0_PIN MOSFET_B_PIN
|
||||
#define HEATER_BED_PIN MOSFET_C_PIN
|
||||
#if HOTENDS == 1 && DISABLED(HEATERS_PARALLEL)
|
||||
#define FAN1_PIN MOSFET_D_PIN
|
||||
#else
|
||||
#define HEATER_1_PIN MOSFET_D_PIN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef FAN0_PIN
|
||||
#define FAN0_PIN 161 // IO pin. Buffer needed
|
||||
#define FAN0_PIN 4 // IO pin. Buffer needed
|
||||
#endif
|
||||
#define FAN1_PIN 162 // IO pin. Buffer needed
|
||||
#define FAN2_PIN 163 // IO pin. Buffer needed
|
||||
#define FAN3_PIN 164 // IO pin. Buffer needed
|
||||
#define FAN4_PIN 165 // IO pin. Buffer needed
|
||||
#define FAN5_PIN 166 // IO pin. Buffer needed
|
||||
#define FAN6_PIN 167 // IO pin. Buffer needed
|
||||
#define FAN7_PIN 168 // IO pin. Buffer needed
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
//
|
||||
#define SDSS 53
|
||||
#define LED_PIN 13
|
||||
#define BOARD_NEOPIXEL_PIN 71
|
||||
#define NEOPIXEL_PIN 71
|
||||
|
||||
#ifndef FILWIDTH_PIN
|
||||
#define FILWIDTH_PIN 5 // Analog Input on AUX2
|
||||
@@ -373,37 +383,9 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Faux Expansion Headers
|
||||
* ------ ------
|
||||
* (BEEP) 37 | 1 2 | 35 (ENC) (MISO) 50 | 1 2 | 52 (SCK)
|
||||
* (LCD_EN) 17 | 3 4 | 16 (LCD_RS) (EN1) 31 | 3 4 | 53 (SDSS)
|
||||
* (LCD_D4) 23 5 6 | 25 (LCD_D5) (EN2) 33 5 6 | 51 (MOSI)
|
||||
* (LCD_D6) 27 | 7 8 | 29 (LCD_D7) (SD_DET) 49 | 7 8 | 41 (KILL)
|
||||
* -- | 9 10 | -- -- | 9 10 | --
|
||||
* ------ ------
|
||||
* EXP1 EXP2
|
||||
*/
|
||||
#define EXP1_01_PIN 37 // BEEPER
|
||||
#define EXP1_02_PIN 35 // ENC
|
||||
#define EXP1_03_PIN 17 // LCD_EN
|
||||
#define EXP1_04_PIN 16 // LCD_RS
|
||||
#define EXP1_05_PIN 23 // LCD_D4
|
||||
#define EXP1_06_PIN 25 // LCD_D5
|
||||
#define EXP1_07_PIN 27 // LCD_D6
|
||||
#define EXP1_08_PIN 29 // LCD_D7
|
||||
|
||||
#define EXP2_01_PIN 50 // MISO
|
||||
#define EXP2_02_PIN 52 // SCK
|
||||
#define EXP2_03_PIN 31 // EN1
|
||||
#define EXP2_04_PIN 53 // SDSS
|
||||
#define EXP2_05_PIN 33 // EN2
|
||||
#define EXP2_06_PIN 51 // MOSI
|
||||
#define EXP2_07_PIN 49 // SD_DET
|
||||
#define EXP2_08_PIN 41 // KILL
|
||||
|
||||
//
|
||||
// LCD / Controller
|
||||
//
|
||||
//////////////////////////
|
||||
// LCDs and Controllers //
|
||||
//////////////////////////
|
||||
|
||||
#if ANY(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI)
|
||||
|
||||
@@ -415,11 +397,10 @@
|
||||
#define TFT_MOSI_PIN SD_MOSI_PIN
|
||||
#define LCD_USE_DMA_SPI
|
||||
|
||||
#define BEEPER_PIN 42
|
||||
|
||||
#define BTN_ENC 59
|
||||
#define BTN_EN1 40
|
||||
#define BTN_EN2 63
|
||||
#define BTN_ENC 59
|
||||
#define BEEPER_PIN 42
|
||||
|
||||
#define TOUCH_CS_PIN 33
|
||||
|
||||
@@ -504,9 +485,9 @@
|
||||
//
|
||||
#if ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
|
||||
|
||||
#define LCD_PINS_RS EXP2_07_PIN // CS chip select /SS chip slave select
|
||||
#define LCD_PINS_EN EXP2_06_PIN // SID (MOSI)
|
||||
#define LCD_PINS_D4 EXP2_02_PIN // SCK (CLK) clock
|
||||
#define LCD_PINS_RS 49 // CS chip select /SS chip slave select
|
||||
#define LCD_PINS_EN 51 // SID (MOSI)
|
||||
#define LCD_PINS_D4 52 // SCK (CLK) clock
|
||||
|
||||
#elif ALL(IS_NEWPANEL, PANEL_ONE)
|
||||
|
||||
@@ -521,12 +502,12 @@
|
||||
|
||||
#if ENABLED(CR10_STOCKDISPLAY)
|
||||
|
||||
#define LCD_PINS_RS EXP1_07_PIN
|
||||
#define LCD_PINS_EN EXP1_08_PIN
|
||||
#define LCD_PINS_D4 EXP1_06_PIN
|
||||
#define LCD_PINS_RS 27
|
||||
#define LCD_PINS_EN 29
|
||||
#define LCD_PINS_D4 25
|
||||
|
||||
#if !IS_NEWPANEL
|
||||
#define BEEPER_PIN EXP1_01_PIN
|
||||
#define BEEPER_PIN 37
|
||||
#endif
|
||||
|
||||
#elif ENABLED(ZONESTAR_LCD)
|
||||
@@ -541,28 +522,38 @@
|
||||
#else
|
||||
|
||||
#if ANY(MKS_12864OLED, MKS_12864OLED_SSD1306)
|
||||
#define LCD_PINS_DC EXP1_06_PIN // Set as output on init
|
||||
#define LCD_PINS_RS EXP1_07_PIN // Pull low for 1s to init
|
||||
#define LCD_PINS_DC 25 // Set as output on init
|
||||
#define LCD_PINS_RS 27 // Pull low for 1s to init
|
||||
// DOGM SPI LCD Support
|
||||
#define DOGLCD_CS EXP1_04_PIN
|
||||
#define DOGLCD_MOSI EXP1_03_PIN
|
||||
#define DOGLCD_SCK EXP1_05_PIN
|
||||
#define DOGLCD_CS 16
|
||||
#define DOGLCD_MOSI 17
|
||||
#define DOGLCD_SCK 23
|
||||
#define DOGLCD_A0 LCD_PINS_DC
|
||||
#else
|
||||
#define LCD_PINS_RS EXP1_04_PIN
|
||||
#define LCD_PINS_EN EXP1_03_PIN
|
||||
#define LCD_PINS_D4 EXP1_05_PIN
|
||||
#define LCD_PINS_D5 EXP1_06_PIN
|
||||
#define LCD_PINS_D6 EXP1_07_PIN
|
||||
#define LCD_PINS_RS 16
|
||||
#define LCD_PINS_EN 17
|
||||
#define LCD_PINS_D4 23
|
||||
#define LCD_PINS_D5 25
|
||||
#define LCD_PINS_D6 27
|
||||
#endif
|
||||
|
||||
#define LCD_PINS_D7 EXP1_08_PIN
|
||||
#define LCD_PINS_D7 29
|
||||
|
||||
#if !IS_NEWPANEL
|
||||
#define BEEPER_PIN EXP2_05_PIN
|
||||
#define BEEPER_PIN 33
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if !IS_NEWPANEL
|
||||
// Buttons attached to a shift register
|
||||
// Not wired yet
|
||||
//#define SHIFT_CLK_PIN 38
|
||||
//#define SHIFT_LD_PIN 42
|
||||
//#define SHIFT_OUT_PIN 40
|
||||
//#define SHIFT_EN_PIN 17
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -572,19 +563,19 @@
|
||||
|
||||
#if ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER)
|
||||
|
||||
#define BEEPER_PIN EXP1_01_PIN
|
||||
#define BEEPER_PIN 37
|
||||
|
||||
#if ENABLED(CR10_STOCKDISPLAY)
|
||||
#define BTN_EN1 EXP1_03_PIN
|
||||
#define BTN_EN2 EXP1_05_PIN
|
||||
#define BTN_EN1 17
|
||||
#define BTN_EN2 23
|
||||
#else
|
||||
#define BTN_EN1 EXP2_03_PIN
|
||||
#define BTN_EN2 EXP2_05_PIN
|
||||
#define BTN_EN1 31
|
||||
#define BTN_EN2 33
|
||||
#endif
|
||||
|
||||
#define BTN_ENC EXP1_02_PIN
|
||||
#define SD_DETECT_PIN EXP2_07_PIN
|
||||
#define KILL_PIN EXP2_08_PIN
|
||||
#define BTN_ENC 35
|
||||
#define SD_DETECT_PIN 49
|
||||
#define KILL_PIN 41
|
||||
|
||||
#if ENABLED(BQ_LCD_SMART_CONTROLLER)
|
||||
#define LCD_BACKLIGHT_PIN 39
|
||||
@@ -634,34 +625,34 @@
|
||||
|
||||
#elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
|
||||
|
||||
#define DOGLCD_CS EXP1_08_PIN
|
||||
#define DOGLCD_A0 EXP1_07_PIN
|
||||
#define DOGLCD_CS 29
|
||||
#define DOGLCD_A0 27
|
||||
|
||||
#define BEEPER_PIN EXP1_05_PIN
|
||||
#define LCD_BACKLIGHT_PIN EXP2_05_PIN
|
||||
#define BEEPER_PIN 23
|
||||
#define LCD_BACKLIGHT_PIN 33
|
||||
|
||||
#define BTN_EN1 EXP1_02_PIN
|
||||
#define BTN_EN2 EXP1_01_PIN
|
||||
#define BTN_ENC EXP2_03_PIN
|
||||
#define BTN_EN1 35
|
||||
#define BTN_EN2 37
|
||||
#define BTN_ENC 31
|
||||
|
||||
#define LCD_SDSS SDSS
|
||||
#define SD_DETECT_PIN EXP2_07_PIN
|
||||
#define KILL_PIN EXP2_08_PIN
|
||||
#define SD_DETECT_PIN 49
|
||||
#define KILL_PIN 41
|
||||
|
||||
#elif ENABLED(MKS_MINI_12864)
|
||||
|
||||
#define DOGLCD_A0 EXP1_07_PIN
|
||||
#define DOGLCD_CS EXP1_06_PIN
|
||||
#define DOGLCD_A0 27
|
||||
#define DOGLCD_CS 25
|
||||
|
||||
#define BEEPER_PIN EXP1_01_PIN
|
||||
#define BEEPER_PIN 37
|
||||
// not connected to a pin
|
||||
#define LCD_BACKLIGHT_PIN 65 // backlight LED on A11/D65
|
||||
|
||||
#define BTN_EN1 EXP2_03_PIN
|
||||
#define BTN_EN2 EXP2_05_PIN
|
||||
#define BTN_ENC EXP1_02_PIN
|
||||
#define BTN_EN1 31
|
||||
#define BTN_EN2 33
|
||||
#define BTN_ENC 35
|
||||
|
||||
#define SD_DETECT_PIN EXP2_07_PIN
|
||||
#define SD_DETECT_PIN 49
|
||||
#define KILL_PIN 64
|
||||
|
||||
//#define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270
|
||||
@@ -694,6 +685,7 @@
|
||||
|
||||
#else
|
||||
|
||||
// Beeper on AUX-4
|
||||
#define BEEPER_PIN 33
|
||||
|
||||
// Buttons are directly attached to AUX-2
|
||||
@@ -709,15 +701,15 @@
|
||||
#define BTN_EN2 63 // AUX2 PIN 4
|
||||
#define BTN_ENC 49 // AUX3 PIN 7
|
||||
#else
|
||||
#define BTN_EN1 EXP1_01_PIN
|
||||
#define BTN_EN2 EXP1_02_PIN
|
||||
#define BTN_ENC EXP2_03_PIN
|
||||
#define SD_DETECT_PIN EXP2_08_PIN
|
||||
#define BTN_EN1 37
|
||||
#define BTN_EN2 35
|
||||
#define BTN_ENC 31
|
||||
#define SD_DETECT_PIN 41
|
||||
#endif
|
||||
|
||||
#if ENABLED(G3D_PANEL)
|
||||
#define SD_DETECT_PIN EXP2_07_PIN
|
||||
#define KILL_PIN EXP2_08_PIN
|
||||
#define SD_DETECT_PIN 49
|
||||
#define KILL_PIN 41
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -727,7 +719,3 @@
|
||||
#endif // IS_NEWPANEL
|
||||
|
||||
#endif // HAS_WIRED_LCD
|
||||
|
||||
#ifndef KILL_PIN
|
||||
#define KILL_PIN EXP2_08_PIN
|
||||
#endif
|
||||
|
||||
@@ -158,7 +158,8 @@
|
||||
#define LCD_BRIGHTNESS_DEFAULT TFT_BACKLIGHT_PWM
|
||||
#endif
|
||||
|
||||
#if ENABLED(ONBOARD_SDIO)
|
||||
#if SD_CONNECTION_IS(ONBOARD)
|
||||
#define ONBOARD_SDIO
|
||||
#define SD_SS_PIN -1 // else SDSS set to PA4 in M43 (spi_pins.h)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -902,11 +902,11 @@ void CardReader::write_command(char * const buf) {
|
||||
* Select the newest file and ask the user if they want to print it.
|
||||
*/
|
||||
bool CardReader::one_click_check() {
|
||||
const bool found = selectNewestFile();
|
||||
const bool found = selectNewestFile(); // Changes the current workDir if found
|
||||
if (found) {
|
||||
//SERIAL_ECHO_MSG(" OCP File: ", longest_filename(), "\n");
|
||||
//ui.init();
|
||||
one_click_print();
|
||||
one_click_print(); // Restores workkDir to root (eventually)
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER LCD_PROGRESS_BAR LCD_PROGRESS_BAR_TE
|
||||
ADVANCED_PAUSE_FEATURE FILAMENT_LOAD_UNLOAD_GCODES FILAMENT_UNLOAD_ALL_EXTRUDERS \
|
||||
PASSWORD_FEATURE PASSWORD_ON_STARTUP PASSWORD_ON_SD_PRINT_MENU PASSWORD_AFTER_SD_PRINT_END PASSWORD_AFTER_SD_PRINT_ABORT \
|
||||
AUTO_BED_LEVELING_BILINEAR Z_MIN_PROBE_REPEATABILITY_TEST DISTINCT_E_FACTORS \
|
||||
SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE \
|
||||
SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE ONE_CLICK_PRINT NO_SD_AUTOSTART \
|
||||
BACKLASH_COMPENSATION BACKLASH_GCODE BAUD_RATE_GCODE BEZIER_CURVE_SUPPORT \
|
||||
FWRETRACT ARC_P_CIRCLES CNC_WORKSPACE_PLANES CNC_COORDINATE_SYSTEMS \
|
||||
PSU_CONTROL LED_POWEROFF_TIMEOUT PS_OFF_CONFIRM PS_OFF_SOUND POWER_OFF_WAIT_FOR_COOLDOWN \
|
||||
|
||||
+1
-1
@@ -183,7 +183,7 @@ HAS_MENU_LED = build_src_filter=+<src/lcd/menu/menu_le
|
||||
HAS_MENU_MEDIA = build_src_filter=+<src/lcd/menu/menu_media.cpp>
|
||||
HAS_MENU_MIXER = build_src_filter=+<src/lcd/menu/menu_mixer.cpp>
|
||||
HAS_MENU_MMU2 = build_src_filter=+<src/lcd/menu/menu_mmu2.cpp>
|
||||
HAS_MENU_ONE_CLICK_PRINT = build_src_filter=+<src/lcd/menu/menu_one_click_print.cpp>
|
||||
HAS_MENU_ONE_CLICK_PRINT = build_src_filter=+<src/lcd/menu/menu_one_click_print.cpp> +<src/gcode/sd/M1003.cpp>
|
||||
HAS_MENU_PASSWORD = build_src_filter=+<src/lcd/menu/menu_password.cpp>
|
||||
HAS_MENU_POWER_MONITOR = build_src_filter=+<src/lcd/menu/menu_power_monitor.cpp>
|
||||
HAS_MENU_CUTTER = build_src_filter=+<src/lcd/menu/menu_spindle_laser.cpp>
|
||||
|
||||
Reference in New Issue
Block a user