Bump to head with panner and ubl fixes
This commit is contained in:
+25
-17
@@ -380,12 +380,6 @@
|
||||
|
||||
#define HAS_DEBUG_MENU (ENABLED(ULTIPANEL) && ENABLED(LCD_PROGRESS_BAR_TEST))
|
||||
|
||||
// MK2 Multiplexer forces SINGLENOZZLE and kills DISABLE_INACTIVE_EXTRUDER
|
||||
#if ENABLED(MK2_MULTIPLEXER)
|
||||
#define SINGLENOZZLE
|
||||
#undef DISABLE_INACTIVE_EXTRUDER
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Extruders have some combination of stepper motors and hotends
|
||||
* so we separate these concepts into the defines:
|
||||
@@ -396,25 +390,17 @@
|
||||
* E_MANUAL - Number of E steppers for LCD move options
|
||||
*
|
||||
*/
|
||||
#if ENABLED(SINGLENOZZLE) || ENABLED(MIXING_EXTRUDER) // One hotend, one thermistor, no XY offset
|
||||
#define HOTENDS 1
|
||||
#undef TEMP_SENSOR_1_AS_REDUNDANT
|
||||
#undef HOTEND_OFFSET_X
|
||||
#undef HOTEND_OFFSET_Y
|
||||
#else // Two hotends
|
||||
#define HOTENDS EXTRUDERS
|
||||
#endif
|
||||
|
||||
#if ENABLED(SWITCHING_EXTRUDER) // One stepper for every two EXTRUDERS
|
||||
#if EXTRUDERS > 4
|
||||
#define E_STEPPERS 3
|
||||
#define E_MANUAL 3
|
||||
#elif EXTRUDERS > 2
|
||||
#define E_STEPPERS 2
|
||||
#define E_MANUAL 2
|
||||
#else
|
||||
#define E_STEPPERS 1
|
||||
#endif
|
||||
#if DISABLED(SWITCHING_NOZZLE)
|
||||
#define HOTENDS E_STEPPERS
|
||||
#endif
|
||||
#define E_MANUAL EXTRUDERS
|
||||
#elif ENABLED(MIXING_EXTRUDER)
|
||||
#define E_STEPPERS MIXING_STEPPERS
|
||||
@@ -424,6 +410,28 @@
|
||||
#define E_MANUAL EXTRUDERS
|
||||
#endif
|
||||
|
||||
// No inactive extruders with MK2_MULTIPLEXER or SWITCHING_NOZZLE
|
||||
#if ENABLED(MK2_MULTIPLEXER) || ENABLED(SWITCHING_NOZZLE)
|
||||
#undef DISABLE_INACTIVE_EXTRUDER
|
||||
#endif
|
||||
|
||||
// MK2 Multiplexer forces SINGLENOZZLE
|
||||
#if ENABLED(MK2_MULTIPLEXER)
|
||||
#define SINGLENOZZLE
|
||||
#endif
|
||||
|
||||
#if ENABLED(SINGLENOZZLE) || ENABLED(MIXING_EXTRUDER) // One hotend, one thermistor, no XY offset
|
||||
#undef HOTENDS
|
||||
#define HOTENDS 1
|
||||
#undef TEMP_SENSOR_1_AS_REDUNDANT
|
||||
#undef HOTEND_OFFSET_X
|
||||
#undef HOTEND_OFFSET_Y
|
||||
#endif
|
||||
|
||||
#ifndef HOTENDS
|
||||
#define HOTENDS EXTRUDERS
|
||||
#endif
|
||||
|
||||
#define DO_SWITCH_EXTRUDER (ENABLED(SWITCHING_EXTRUDER) && (DISABLED(SWITCHING_NOZZLE) || SWITCHING_EXTRUDER_SERVO_NR != SWITCHING_NOZZLE_SERVO_NR))
|
||||
|
||||
/**
|
||||
|
||||
@@ -205,15 +205,6 @@
|
||||
#define MAX_AUTORETRACT 99
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MAX_STEP_FREQUENCY differs for TOSHIBA
|
||||
*/
|
||||
#if ENABLED(CONFIG_STEPPERS_TOSHIBA)
|
||||
#define MAX_STEP_FREQUENCY 10000 // Max step frequency for Toshiba Stepper Controllers
|
||||
#else
|
||||
#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step)
|
||||
#endif
|
||||
|
||||
// MS1 MS2 Stepper Driver Microstepping mode table
|
||||
#define MICROSTEP1 LOW,LOW
|
||||
#if ENABLED(HEROIC_STEPPER_DRIVERS)
|
||||
@@ -616,24 +607,27 @@
|
||||
#define HAS_X2_ENABLE (PIN_EXISTS(X2_ENABLE))
|
||||
#define HAS_X2_DIR (PIN_EXISTS(X2_DIR))
|
||||
#define HAS_X2_STEP (PIN_EXISTS(X2_STEP))
|
||||
#define HAS_Y_MICROSTEPS (PIN_EXISTS(Y_MS1))
|
||||
#define HAS_X2_MICROSTEPS (PIN_EXISTS(X2_MS1))
|
||||
|
||||
#define HAS_Y_ENABLE (PIN_EXISTS(Y_ENABLE))
|
||||
#define HAS_Y_DIR (PIN_EXISTS(Y_DIR))
|
||||
#define HAS_Y_STEP (PIN_EXISTS(Y_STEP))
|
||||
#define HAS_Z_MICROSTEPS (PIN_EXISTS(Z_MS1))
|
||||
#define HAS_Y_MICROSTEPS (PIN_EXISTS(Y_MS1))
|
||||
|
||||
#define HAS_Y2_ENABLE (PIN_EXISTS(Y2_ENABLE))
|
||||
#define HAS_Y2_DIR (PIN_EXISTS(Y2_DIR))
|
||||
#define HAS_Y2_STEP (PIN_EXISTS(Y2_STEP))
|
||||
#define HAS_Y2_MICROSTEPS (PIN_EXISTS(Y2_MS1))
|
||||
|
||||
#define HAS_Z_ENABLE (PIN_EXISTS(Z_ENABLE))
|
||||
#define HAS_Z_DIR (PIN_EXISTS(Z_DIR))
|
||||
#define HAS_Z_STEP (PIN_EXISTS(Z_STEP))
|
||||
#define HAS_Z_MICROSTEPS (PIN_EXISTS(Z_MS1))
|
||||
|
||||
#define HAS_Z2_ENABLE (PIN_EXISTS(Z2_ENABLE))
|
||||
#define HAS_Z2_DIR (PIN_EXISTS(Z2_DIR))
|
||||
#define HAS_Z2_STEP (PIN_EXISTS(Z2_STEP))
|
||||
#define HAS_Z2_MICROSTEPS (PIN_EXISTS(Z2_MS1))
|
||||
|
||||
// Extruder steppers and solenoids
|
||||
#define HAS_E0_ENABLE (PIN_EXISTS(E0_ENABLE))
|
||||
@@ -984,6 +978,7 @@
|
||||
#define PLANNER_LEVELING (OLDSCHOOL_ABL || ENABLED(MESH_BED_LEVELING) || UBL_SEGMENTED || ENABLED(SKEW_CORRECTION))
|
||||
#define HAS_PROBING_PROCEDURE (HAS_ABL || ENABLED(Z_MIN_PROBE_REPEATABILITY_TEST))
|
||||
#define HAS_UBL_AND_CURVES (ENABLED(AUTO_BED_LEVELING_UBL) && !PLANNER_LEVELING && (ENABLED(ARC_SUPPORT) || ENABLED(BEZIER_CURVE_SUPPORT)))
|
||||
#define HAS_FEEDRATE_SCALING (ENABLED(SCARA_FEEDRATE_SCALING) || ENABLED(DELTA_FEEDRATE_SCALING))
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
#undef LCD_BED_LEVELING
|
||||
@@ -1247,9 +1242,6 @@
|
||||
#define MANUAL_PROBE_HEIGHT Z_HOMING_HEIGHT
|
||||
#endif
|
||||
|
||||
// Stepper pulse duration, in cycles
|
||||
#define STEP_PULSE_CYCLES ((MINIMUM_STEPPER_PULSE) * CYCLES_PER_MICROSECOND)
|
||||
|
||||
// Updated G92 behavior shifts the workspace
|
||||
#define HAS_POSITION_SHIFT DISABLED(NO_WORKSPACE_OFFSETS)
|
||||
// The home offset also shifts the coordinate space
|
||||
|
||||
@@ -722,7 +722,7 @@
|
||||
#if ENABLED(BABYSTEPPING)
|
||||
//#define BABYSTEP_XY // Also enable X/Y Babystepping. Not supported on DELTA!
|
||||
#define BABYSTEP_INVERT_Z false // Change if Z babysteps should go the other way
|
||||
#define BABYSTEP_MULTIPLICATOR 1 // Babysteps are very small. Increase for faster motion.
|
||||
#define BABYSTEP_MULTIPLICATOR 25 // Babysteps are very small. Increase for faster motion.
|
||||
#define BABYSTEP_ZPROBE_OFFSET // Enable to combine M851 and Babystepping
|
||||
#define DOUBLECLICK_FOR_Z_BABYSTEPPING // Double-click on the Status Screen for Z Babystepping.
|
||||
#define DOUBLECLICK_MAX_INTERVAL 1250 // Maximum interval between clicks, in milliseconds.
|
||||
|
||||
+50
-17
@@ -48,10 +48,14 @@
|
||||
|
||||
// Bracket code that shouldn't be interrupted
|
||||
#ifndef CRITICAL_SECTION_START
|
||||
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
|
||||
#define CRITICAL_SECTION_END SREG = _sreg;
|
||||
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli()
|
||||
#define CRITICAL_SECTION_END SREG = _sreg
|
||||
#endif
|
||||
|
||||
#define ISRS_ENABLED() TEST(SREG, SREG_I)
|
||||
#define ENABLE_ISRS() sei()
|
||||
#define DISABLE_ISRS() cli()
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Types
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -89,22 +93,17 @@ inline uint8_t HAL_get_reset_source(void) { return MCUSR; }
|
||||
|
||||
#define STEP_TIMER_NUM 1
|
||||
#define TEMP_TIMER_NUM 0
|
||||
#define PULSE_TIMER_NUM TEMP_TIMER_NUM
|
||||
|
||||
#define HAL_STEPPER_TIMER_RATE HAL_TIMER_RATE
|
||||
#define HAL_TICKS_PER_US ((HAL_STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
|
||||
#define STEPPER_TIMER_PRESCALE 8
|
||||
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
|
||||
#define PULSE_TIMER_NUM STEP_TIMER_NUM
|
||||
|
||||
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
|
||||
|
||||
#define TIMER_OCR_1 OCR1A
|
||||
#define TIMER_COUNTER_1 TCNT1
|
||||
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
|
||||
#define STEPPER_TIMER_PRESCALE 8
|
||||
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
|
||||
|
||||
#define TIMER_OCR_0 OCR0A
|
||||
#define TIMER_COUNTER_0 TCNT0
|
||||
|
||||
#define PULSE_TIMER_PRESCALE 8
|
||||
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
|
||||
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
|
||||
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
|
||||
|
||||
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
|
||||
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
|
||||
@@ -114,7 +113,42 @@ inline uint8_t HAL_get_reset_source(void) { return MCUSR; }
|
||||
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0B)
|
||||
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0B)
|
||||
|
||||
#define HAL_timer_start(timer_num, frequency)
|
||||
FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
||||
UNUSED(frequency);
|
||||
switch (timer_num) {
|
||||
case STEP_TIMER_NUM:
|
||||
// waveform generation = 0100 = CTC
|
||||
SET_WGM(1, CTC_OCRnA);
|
||||
|
||||
// output mode = 00 (disconnected)
|
||||
SET_COMA(1, NORMAL);
|
||||
|
||||
// Set the timer pre-scaler
|
||||
// Generally we use a divider of 8, resulting in a 2MHz timer
|
||||
// frequency on a 16MHz MCU. If you are going to change this, be
|
||||
// sure to regenerate speed_lookuptable.h with
|
||||
// create_speed_lookuptable.py
|
||||
SET_CS(1, PRESCALER_8); // CS 2 = 1/8 prescaler
|
||||
|
||||
// Init Stepper ISR to 122 Hz for quick starting
|
||||
// (F_CPU) / (STEPPER_TIMER_PRESCALE) / frequency
|
||||
OCR1A = 0x4000;
|
||||
TCNT1 = 0;
|
||||
break;
|
||||
|
||||
case TEMP_TIMER_NUM:
|
||||
// Use timer0 for temperature measurement
|
||||
// Interleave temperature interrupt with millies interrupt
|
||||
OCR0B = 128;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define TIMER_OCR_1 OCR1A
|
||||
#define TIMER_COUNTER_1 TCNT1
|
||||
|
||||
#define TIMER_OCR_0 OCR0A
|
||||
#define TIMER_COUNTER_0 TCNT0
|
||||
|
||||
#define _CAT(a, ...) a ## __VA_ARGS__
|
||||
#define HAL_timer_set_compare(timer, compare) (_CAT(TIMER_OCR_, timer) = compare)
|
||||
@@ -148,7 +182,6 @@ void TIMER1_COMPA_vect (void) { \
|
||||
A("lds r16, %[timsk1]") /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
|
||||
A("andi r16,~%[msk1]") /* 1 Disable the stepper ISR */ \
|
||||
A("sts %[timsk1], r16") /* 2 And set the new value */ \
|
||||
A("sei") /* 1 Enable global interrupts - stepper and temperature ISRs are disabled, so no risk of reentry or being preempted by the temperature ISR */ \
|
||||
A("push r16") /* 2 Save TIMSK1 into stack */ \
|
||||
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
|
||||
A("push r16") /* 2 Save RAMPZ into stack */ \
|
||||
@@ -258,7 +291,7 @@ void TIMER0_COMPB_vect (void) { \
|
||||
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
|
||||
A("pop r16") /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
|
||||
A("ori r16,%[msk0]") /* 1 Enable temperature ISR */ \
|
||||
A("cli") /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don´t want to reenter this handler until the current one is done */ \
|
||||
A("cli") /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don't want to reenter this handler until the current one is done */ \
|
||||
A("sts %[timsk0], r16") /* 2 And restore the old value */ \
|
||||
A("pop r16") /* 2 Get the old SREG */ \
|
||||
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
if (errPrstIdx >= I2CPE_ERR_PRST_ARRAY_SIZE) {
|
||||
float sumP = 0;
|
||||
LOOP_L_N(i, I2CPE_ERR_PRST_ARRAY_SIZE) sumP += errPrst[i];
|
||||
const int32_t errorP = int32_t(sumP * (1.0 / (I2CPE_ERR_PRST_ARRAY_SIZE)));
|
||||
const int32_t errorP = int32_t(sumP * (1.0f / (I2CPE_ERR_PRST_ARRAY_SIZE)));
|
||||
SERIAL_ECHO(axis_codes[encoderAxis]);
|
||||
SERIAL_ECHOPAIR(" - err detected: ", errorP * planner.steps_to_mm[encoderAxis]);
|
||||
SERIAL_ECHOLNPGM("mm; correcting!");
|
||||
|
||||
@@ -134,16 +134,12 @@
|
||||
nextErrorCountTime = 0,
|
||||
lastErrorTime;
|
||||
|
||||
//double positionMm; //calculate
|
||||
|
||||
#if ENABLED(I2CPE_ERR_ROLLING_AVERAGE)
|
||||
uint8_t errIdx = 0, errPrstIdx = 0;
|
||||
int err[I2CPE_ERR_ARRAY_SIZE] = { 0 },
|
||||
errPrst[I2CPE_ERR_PRST_ARRAY_SIZE] = { 0 };
|
||||
#endif
|
||||
|
||||
//float positionMm; //calculate
|
||||
|
||||
public:
|
||||
void init(const uint8_t address, const AxisEnum axis);
|
||||
void reset();
|
||||
|
||||
+25
-32
@@ -60,10 +60,10 @@ extern const char axis_codes[XYZE];
|
||||
|
||||
#if HAS_X2_ENABLE
|
||||
#define enable_X() do{ X_ENABLE_WRITE( X_ENABLE_ON); X2_ENABLE_WRITE( X_ENABLE_ON); }while(0)
|
||||
#define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); X2_ENABLE_WRITE(!X_ENABLE_ON); axis_known_position[X_AXIS] = false; }while(0)
|
||||
#define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); X2_ENABLE_WRITE(!X_ENABLE_ON); CBI(axis_known_position, X_AXIS); }while(0)
|
||||
#elif HAS_X_ENABLE
|
||||
#define enable_X() X_ENABLE_WRITE( X_ENABLE_ON)
|
||||
#define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); axis_known_position[X_AXIS] = false; }while(0)
|
||||
#define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); CBI(axis_known_position, X_AXIS); }while(0)
|
||||
#else
|
||||
#define enable_X() NOOP
|
||||
#define disable_X() NOOP
|
||||
@@ -71,10 +71,10 @@ extern const char axis_codes[XYZE];
|
||||
|
||||
#if HAS_Y2_ENABLE
|
||||
#define enable_Y() do{ Y_ENABLE_WRITE( Y_ENABLE_ON); Y2_ENABLE_WRITE(Y_ENABLE_ON); }while(0)
|
||||
#define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); Y2_ENABLE_WRITE(!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }while(0)
|
||||
#define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); Y2_ENABLE_WRITE(!Y_ENABLE_ON); CBI(axis_known_position, Y_AXIS); }while(0)
|
||||
#elif HAS_Y_ENABLE
|
||||
#define enable_Y() Y_ENABLE_WRITE( Y_ENABLE_ON)
|
||||
#define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }while(0)
|
||||
#define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); CBI(axis_known_position, Y_AXIS); }while(0)
|
||||
#else
|
||||
#define enable_Y() NOOP
|
||||
#define disable_Y() NOOP
|
||||
@@ -82,10 +82,10 @@ extern const char axis_codes[XYZE];
|
||||
|
||||
#if HAS_Z2_ENABLE
|
||||
#define enable_Z() do{ Z_ENABLE_WRITE( Z_ENABLE_ON); Z2_ENABLE_WRITE(Z_ENABLE_ON); }while(0)
|
||||
#define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); Z2_ENABLE_WRITE(!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }while(0)
|
||||
#define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); Z2_ENABLE_WRITE(!Z_ENABLE_ON); CBI(axis_known_position, Z_AXIS); }while(0)
|
||||
#elif HAS_Z_ENABLE
|
||||
#define enable_Z() Z_ENABLE_WRITE( Z_ENABLE_ON)
|
||||
#define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }while(0)
|
||||
#define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); CBI(axis_known_position, Z_AXIS); }while(0)
|
||||
#else
|
||||
#define enable_Z() NOOP
|
||||
#define disable_Z() NOOP
|
||||
@@ -220,11 +220,16 @@ inline void reset_stepper_timeout() { previous_move_ms = millis(); }
|
||||
extern float feedrate_mm_s;
|
||||
extern int16_t feedrate_percentage;
|
||||
|
||||
#define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01)
|
||||
#define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01f)
|
||||
|
||||
extern bool axis_relative_modes[XYZE];
|
||||
|
||||
extern uint8_t axis_homed, axis_known_position;
|
||||
|
||||
constexpr uint8_t xyz_bits = _BV(X_AXIS) | _BV(Y_AXIS) | _BV(Z_AXIS);
|
||||
FORCE_INLINE bool all_axes_homed() { return (axis_homed & xyz_bits) == xyz_bits; }
|
||||
FORCE_INLINE bool all_axes_known() { return (axis_known_position & xyz_bits) == xyz_bits; }
|
||||
|
||||
extern bool axis_relative_modes[];
|
||||
extern bool axis_known_position[XYZ];
|
||||
extern bool axis_homed[XYZ];
|
||||
extern volatile bool wait_for_heatup;
|
||||
|
||||
#if HAS_RESUME_CONTINUE
|
||||
@@ -316,22 +321,15 @@ void report_current_position();
|
||||
void recalc_delta_settings();
|
||||
float delta_safe_distance_from_top();
|
||||
|
||||
#if ENABLED(DELTA_FAST_SQRT)
|
||||
float Q_rsqrt(const float number);
|
||||
#define _SQRT(n) (1.0f / Q_rsqrt(n))
|
||||
#else
|
||||
#define _SQRT(n) SQRT(n)
|
||||
#endif
|
||||
|
||||
// Macro to obtain the Z position of an individual tower
|
||||
#define DELTA_Z(V,T) V[Z_AXIS] + _SQRT( \
|
||||
#define DELTA_Z(V,T) V[Z_AXIS] + SQRT( \
|
||||
delta_diagonal_rod_2_tower[T] - HYPOT2( \
|
||||
delta_tower[T][X_AXIS] - V[X_AXIS], \
|
||||
delta_tower[T][Y_AXIS] - V[Y_AXIS] \
|
||||
) \
|
||||
)
|
||||
|
||||
#define DELTA_IK(V) do { \
|
||||
#define DELTA_IK(V) do { \
|
||||
delta[A_AXIS] = DELTA_Z(V, A_AXIS); \
|
||||
delta[B_AXIS] = DELTA_Z(V, B_AXIS); \
|
||||
delta[C_AXIS] = DELTA_Z(V, C_AXIS); \
|
||||
@@ -370,11 +368,6 @@ void report_current_position();
|
||||
void print_2d_array(const uint8_t sx, const uint8_t sy, const uint8_t precision, const element_2d_fn fn);
|
||||
#endif
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
typedef struct { double A, B, D; } linear_fit;
|
||||
linear_fit* lsf_linear_fit(double x[], double y[], double z[], const int);
|
||||
#endif
|
||||
|
||||
#if HAS_LEVELING
|
||||
bool leveling_is_valid();
|
||||
void set_bed_leveling_enabled(const bool enable=true);
|
||||
@@ -468,10 +461,10 @@ void prepare_move_to_destination();
|
||||
/**
|
||||
* Blocking movement and shorthand functions
|
||||
*/
|
||||
void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s=0.0);
|
||||
void do_blocking_move_to_x(const float &rx, const float &fr_mm_s=0.0);
|
||||
void do_blocking_move_to_z(const float &rz, const float &fr_mm_s=0.0);
|
||||
void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s=0.0);
|
||||
void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s=0);
|
||||
void do_blocking_move_to_x(const float &rx, const float &fr_mm_s=0);
|
||||
void do_blocking_move_to_z(const float &rz, const float &fr_mm_s=0);
|
||||
void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s=0);
|
||||
|
||||
#if ENABLED(ARC_SUPPORT)
|
||||
void plan_arc(const float(&cart)[XYZE], const float(&offset)[2], const bool clockwise);
|
||||
@@ -531,8 +524,8 @@ void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm
|
||||
// Return true if the given position is within the machine bounds.
|
||||
inline bool position_is_reachable(const float &rx, const float &ry) {
|
||||
// Add 0.001 margin to deal with float imprecision
|
||||
return WITHIN(rx, X_MIN_POS - 0.001, X_MAX_POS + 0.001)
|
||||
&& WITHIN(ry, Y_MIN_POS - 0.001, Y_MAX_POS + 0.001);
|
||||
return WITHIN(rx, X_MIN_POS - 0.001f, X_MAX_POS + 0.001f)
|
||||
&& WITHIN(ry, Y_MIN_POS - 0.001f, Y_MAX_POS + 0.001f);
|
||||
}
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
@@ -545,8 +538,8 @@ void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm
|
||||
*/
|
||||
inline bool position_is_reachable_by_probe(const float &rx, const float &ry) {
|
||||
return position_is_reachable(rx - (X_PROBE_OFFSET_FROM_EXTRUDER), ry - (Y_PROBE_OFFSET_FROM_EXTRUDER))
|
||||
&& WITHIN(rx, MIN_PROBE_X - 0.001, MAX_PROBE_X + 0.001)
|
||||
&& WITHIN(ry, MIN_PROBE_Y - 0.001, MAX_PROBE_Y + 0.001);
|
||||
&& WITHIN(rx, MIN_PROBE_X - 0.001f, MAX_PROBE_X + 0.001f)
|
||||
&& WITHIN(ry, MIN_PROBE_Y - 0.001f, MAX_PROBE_Y + 0.001f);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+380
-209
@@ -28,6 +28,7 @@
|
||||
* Modified 28 September 2010 by Mark Sproul
|
||||
* Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
|
||||
* Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
|
||||
* Modified 10 June 2018 by Eduardo José Tagle (See #10991)
|
||||
*/
|
||||
|
||||
// Disable HardwareSerial.cpp to support chips without a UART (Attiny, etc.)
|
||||
@@ -55,140 +56,312 @@
|
||||
ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
|
||||
static bool _written;
|
||||
#endif
|
||||
static bool _written;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80; // XON / XOFF Character was sent
|
||||
constexpr uint8_t XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
|
||||
constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
|
||||
XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
|
||||
// XON / XOFF character definitions
|
||||
constexpr uint8_t XON_CHAR = 17;
|
||||
constexpr uint8_t XOFF_CHAR = 19;
|
||||
constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
|
||||
uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
|
||||
#endif
|
||||
|
||||
void clear_command_queue();
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
uint8_t rx_dropped_bytes = 0;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
uint8_t rx_buffer_overruns = 0;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
uint8_t rx_framing_errors = 0;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
ring_buffer_pos_t rx_max_enqueued = 0;
|
||||
#endif
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() asm volatile("": : :"memory");
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#include "emergency_parser.h"
|
||||
#endif
|
||||
|
||||
// "Atomically" read the RX head index value without disabling interrupts:
|
||||
// This MUST be called with RX interrupts enabled, and CAN'T be called
|
||||
// from the RX ISR itself!
|
||||
FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head() {
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
// Keep reading until 2 consecutive reads return the same value,
|
||||
// meaning there was no update in-between caused by an interrupt.
|
||||
// This works because serial RX interrupts happen at a slower rate
|
||||
// than successive reads of a variable, so 2 consecutive reads with
|
||||
// the same value means no interrupt updated it.
|
||||
ring_buffer_pos_t vold, vnew = rx_buffer.head;
|
||||
sw_barrier();
|
||||
do {
|
||||
vold = vnew;
|
||||
vnew = rx_buffer.head;
|
||||
sw_barrier();
|
||||
} while (vold != vnew);
|
||||
return vnew;
|
||||
#else
|
||||
// With an 8bit index, reads are always atomic. No need for special handling
|
||||
return rx_buffer.head;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
static volatile bool rx_tail_value_not_stable = false;
|
||||
static volatile uint16_t rx_tail_value_backup = 0;
|
||||
#endif
|
||||
|
||||
// Set RX tail index, taking into account the RX ISR could interrupt
|
||||
// the write to this variable in the middle - So a backup strategy
|
||||
// is used to ensure reads of the correct values.
|
||||
// -Must NOT be called from the RX ISR -
|
||||
FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value) {
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
// Store the new value in the backup
|
||||
rx_tail_value_backup = value;
|
||||
sw_barrier();
|
||||
// Flag we are about to change the true value
|
||||
rx_tail_value_not_stable = true;
|
||||
sw_barrier();
|
||||
// Store the new value
|
||||
rx_buffer.tail = value;
|
||||
sw_barrier();
|
||||
// Signal the new value is completely stored into the value
|
||||
rx_tail_value_not_stable = false;
|
||||
sw_barrier();
|
||||
#else
|
||||
rx_buffer.tail = value;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get the RX tail index, taking into account the read could be
|
||||
// interrupting in the middle of the update of that index value
|
||||
// -Called from the RX ISR -
|
||||
FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail() {
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
// If the true index is being modified, return the backup value
|
||||
if (rx_tail_value_not_stable) return rx_tail_value_backup;
|
||||
#endif
|
||||
// The true index is stable, return it
|
||||
return rx_buffer.tail;
|
||||
}
|
||||
|
||||
// (called with RX interrupts disabled)
|
||||
FORCE_INLINE void store_rxd_char() {
|
||||
const ring_buffer_pos_t h = rx_buffer.head,
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
// Get the tail - Nothing can alter its value while this ISR is executing, but there's
|
||||
// a chance that this ISR interrupted the main process while it was updating the index.
|
||||
// The backup mechanism ensures the correct value is always returned.
|
||||
const ring_buffer_pos_t t = atomic_read_rx_tail();
|
||||
|
||||
// Get the head pointer - This ISR is the only one that modifies its value, so it's safe to read here
|
||||
ring_buffer_pos_t h = rx_buffer.head;
|
||||
|
||||
// Get the next element
|
||||
ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
|
||||
// This must read the M_UCSRxA register before reading the received byte to detect error causes
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
if (TEST(M_UCSRxA, M_DORx) && !++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
if (TEST(M_UCSRxA, M_DORx) && !++rx_buffer_overruns) --rx_buffer_overruns;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
if (TEST(M_UCSRxA, M_FEx) && !++rx_framing_errors) --rx_framing_errors;
|
||||
#endif
|
||||
|
||||
// Read the character from the USART
|
||||
uint8_t c = M_UDRx;
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
emergency_parser.update(c);
|
||||
#endif
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the buffer is
|
||||
// critical, so don't write the character or advance the head.
|
||||
const char c = M_UDRx;
|
||||
if (i != rx_buffer.tail) {
|
||||
// (such that the head would advance to the current tail), the RX FIFO is
|
||||
// full, so don't write the character or advance the head.
|
||||
if (i != t) {
|
||||
rx_buffer.buffer[h] = c;
|
||||
rx_buffer.head = i;
|
||||
}
|
||||
else {
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
if (!++rx_dropped_bytes) ++rx_dropped_bytes;
|
||||
#endif
|
||||
h = i;
|
||||
}
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
else if (!++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
// calculate count of bytes stored into the RX buffer
|
||||
ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(rx_buffer.head - rx_buffer.tail) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
// Calculate count of bytes stored into the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
|
||||
// Keep track of the maximum count of enqueued bytes
|
||||
NOLESS(rx_max_enqueued, rx_count);
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
|
||||
// for high speed transfers, we can use XON/XOFF protocol to do
|
||||
// software handshake and avoid overruns.
|
||||
// If the last char that was sent was an XON
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
|
||||
|
||||
// calculate count of bytes stored into the RX buffer
|
||||
ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(rx_buffer.head - rx_buffer.tail) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
// Bytes stored into the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
|
||||
// if we are above 12.5% of RX buffer capacity, send XOFF before
|
||||
// we run out of RX buffer space .. We need 325 bytes @ 250kbits/s to
|
||||
// let the host react and stop sending bytes. This translates to 13mS
|
||||
// propagation time.
|
||||
// If over 12.5% of RX buffer capacity, send XOFF before running out of
|
||||
// RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
|
||||
// and stop sending bytes. This translates to 13mS propagation time.
|
||||
if (rx_count >= (RX_BUFFER_SIZE) / 8) {
|
||||
// If TX interrupts are disabled and data register is empty,
|
||||
// just write the byte to the data register and be done. This
|
||||
// shortcut helps significantly improve the effective datarate
|
||||
// at high (>500kbit/s) bitrates, where interrupt overhead
|
||||
// becomes a slowdown.
|
||||
if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
|
||||
// Send an XOFF character
|
||||
M_UDRx = XOFF_CHAR;
|
||||
// clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
// And remember it was sent
|
||||
xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
|
||||
|
||||
// At this point, definitely no TX interrupt was executing, since the TX ISR can't be preempted.
|
||||
// Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
|
||||
// to be in the middle of trying to disable the RX interrupt in the main program, eventually the
|
||||
// enabling of the TX interrupt could be undone. The ONLY reliable thing this can do to ensure
|
||||
// the sending of the XOFF char is to send it HERE AND NOW.
|
||||
|
||||
// About to send the XOFF char
|
||||
xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
|
||||
|
||||
// Wait until the TX register becomes empty and send it - Here there could be a problem
|
||||
// - While waiting for the TX register to empty, the RX register could receive a new
|
||||
// character. This must also handle that situation!
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) {
|
||||
|
||||
if (TEST(M_UCSRxA,M_RXCx)) {
|
||||
// A char arrived while waiting for the TX buffer to be empty - Receive and process it!
|
||||
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
|
||||
// Read the character from the USART
|
||||
c = M_UDRx;
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
emergency_parser.update(c);
|
||||
#endif
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the FIFO is
|
||||
// full, so don't write the character or advance the head.
|
||||
if (i != t) {
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
else if (!++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
#endif
|
||||
}
|
||||
sw_barrier();
|
||||
}
|
||||
else {
|
||||
// TX interrupts disabled, but buffer still not empty ... or
|
||||
// TX interrupts enabled. Reenable TX ints and schedule XOFF
|
||||
// character to be sent
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
SBI(M_UCSRxB, M_UDRIEx);
|
||||
xon_xoff_state = XOFF_CHAR;
|
||||
#else
|
||||
// We are not using TX interrupts, we will have to send this manually
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) {/* nada */}
|
||||
M_UDRx = XOFF_CHAR;
|
||||
// And remember we already sent it
|
||||
xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
|
||||
#endif
|
||||
|
||||
M_UDRx = XOFF_CHAR;
|
||||
|
||||
// Clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
|
||||
// At this point there could be a race condition between the write() function
|
||||
// and this sending of the XOFF char. This interrupt could happen between the
|
||||
// wait to be empty TX buffer loop and the actual write of the character. Since
|
||||
// the TX buffer is full because it's sending the XOFF char, the only way to be
|
||||
// sure the write() function will succeed is to wait for the XOFF char to be
|
||||
// completely sent. Since an extra character could be received during the wait
|
||||
// it must also be handled!
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) {
|
||||
|
||||
if (TEST(M_UCSRxA,M_RXCx)) {
|
||||
// A char arrived while waiting for the TX buffer to be empty - Receive and process it!
|
||||
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
|
||||
// Read the character from the USART
|
||||
c = M_UDRx;
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
emergency_parser.update(c);
|
||||
#endif
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the FIFO is
|
||||
// full, so don't write the character or advance the head.
|
||||
if (i != t) {
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
else if (!++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
#endif
|
||||
}
|
||||
sw_barrier();
|
||||
}
|
||||
|
||||
// At this point everything is ready. The write() function won't
|
||||
// have any issues writing to the UART TX register if it needs to!
|
||||
}
|
||||
}
|
||||
#endif // SERIAL_XON_XOFF
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
emergency_parser.update(c);
|
||||
#endif
|
||||
// Store the new head value - The main loop will retry until the value is stable
|
||||
rx_buffer.head = h;
|
||||
}
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
|
||||
// (called with TX irqs disabled)
|
||||
FORCE_INLINE void _tx_udr_empty_irq(void) {
|
||||
// If interrupts are enabled, there must be more data in the output
|
||||
// buffer.
|
||||
|
||||
// Read positions
|
||||
uint8_t t = tx_buffer.tail;
|
||||
const uint8_t h = tx_buffer.head;
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
// Do a priority insertion of an XON/XOFF char, if needed.
|
||||
const uint8_t state = xon_xoff_state;
|
||||
if (!(state & XON_XOFF_CHAR_SENT)) {
|
||||
M_UDRx = state & XON_XOFF_CHAR_MASK;
|
||||
xon_xoff_state = state | XON_XOFF_CHAR_SENT;
|
||||
// If an XON char is pending to be sent, do it now
|
||||
if (xon_xoff_state == XON_CHAR) {
|
||||
|
||||
// Send the character
|
||||
M_UDRx = XON_CHAR;
|
||||
|
||||
// clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
|
||||
// Remember we sent it.
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
|
||||
// If nothing else to transmit, just disable TX interrupts.
|
||||
if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{ // Send the next byte
|
||||
const uint8_t t = tx_buffer.tail, c = tx_buffer.buffer[t];
|
||||
tx_buffer.tail = (t + 1) & (TX_BUFFER_SIZE - 1);
|
||||
M_UDRx = c;
|
||||
|
||||
// If nothing to transmit, just disable TX interrupts. This could
|
||||
// happen as the result of the non atomicity of the disabling of RX
|
||||
// interrupts that could end reenabling TX interrupts as a side effect.
|
||||
if (h == t) {
|
||||
CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
return;
|
||||
}
|
||||
|
||||
// clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
// There is something to TX, Send the next byte
|
||||
const uint8_t c = tx_buffer.buffer[t];
|
||||
t = (t + 1) & (TX_BUFFER_SIZE - 1);
|
||||
M_UDRx = c;
|
||||
tx_buffer.tail = t;
|
||||
|
||||
// Clear the TXC bit (by writing a one to its bit location).
|
||||
// Ensures flush() won't return until the bytes are actually written/
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
|
||||
// Disable interrupts if the buffer is empty
|
||||
if (tx_buffer.head == tx_buffer.tail)
|
||||
CBI(M_UCSRxB, M_UDRIEx);
|
||||
// Disable interrupts if there is nothing to transmit following this byte
|
||||
if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
}
|
||||
|
||||
#ifdef M_USARTx_UDRE_vect
|
||||
@@ -232,8 +405,8 @@
|
||||
SBI(M_UCSRxB, M_RXCIEx);
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
CBI(M_UCSRxB, M_UDRIEx);
|
||||
_written = false;
|
||||
#endif
|
||||
_written = false;
|
||||
}
|
||||
|
||||
void MarlinSerial::end() {
|
||||
@@ -243,177 +416,179 @@
|
||||
CBI(M_UCSRxB, M_UDRIEx);
|
||||
}
|
||||
|
||||
void MarlinSerial::checkRx(void) {
|
||||
if (TEST(M_UCSRxA, M_RXCx)) {
|
||||
CRITICAL_SECTION_START;
|
||||
store_rxd_char();
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
}
|
||||
|
||||
int MarlinSerial::peek(void) {
|
||||
CRITICAL_SECTION_START;
|
||||
const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
|
||||
CRITICAL_SECTION_END;
|
||||
return v;
|
||||
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
|
||||
return h == t ? -1 : rx_buffer.buffer[t];
|
||||
}
|
||||
|
||||
int MarlinSerial::read(void) {
|
||||
int v;
|
||||
CRITICAL_SECTION_START;
|
||||
const ring_buffer_pos_t t = rx_buffer.tail;
|
||||
if (rx_buffer.head == t)
|
||||
v = -1;
|
||||
else {
|
||||
v = rx_buffer.buffer[t];
|
||||
rx_buffer.tail = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
|
||||
const ring_buffer_pos_t h = atomic_read_rx_head();
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
|
||||
// Get count of bytes in the RX buffer
|
||||
ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(rx_buffer.head - rx_buffer.tail) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
// When below 10% of RX buffer capacity, send XON before
|
||||
// running out of RX buffer bytes
|
||||
if (rx_count < (RX_BUFFER_SIZE) / 10) {
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
CRITICAL_SECTION_END; // End critical section before returning!
|
||||
writeNoHandshake(XON_CHAR);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Read the tail. Main thread owns it, so it is safe to directly read it
|
||||
ring_buffer_pos_t t = rx_buffer.tail;
|
||||
|
||||
// If nothing to read, return now
|
||||
if (h == t) return -1;
|
||||
|
||||
// Get the next char
|
||||
const int v = rx_buffer.buffer[t];
|
||||
t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
|
||||
|
||||
// Advance tail - Making sure the RX ISR will always get an stable value, even
|
||||
// if it interrupts the writing of the value of that variable in the middle.
|
||||
atomic_set_rx_tail(t);
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
// If the XOFF char was sent, or about to be sent...
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
|
||||
// Get count of bytes in the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
if (rx_count < (RX_BUFFER_SIZE) / 10) {
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
// Signal we want an XON character to be sent.
|
||||
xon_xoff_state = XON_CHAR;
|
||||
// Enable TX ISR. Non atomic, but it will eventually enable them
|
||||
SBI(M_UCSRxB, M_UDRIEx);
|
||||
#else
|
||||
// If not using TX interrupts, we must send the XON char now
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
|
||||
M_UDRx = XON_CHAR;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
CRITICAL_SECTION_END;
|
||||
#endif
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
ring_buffer_pos_t MarlinSerial::available(void) {
|
||||
CRITICAL_SECTION_START;
|
||||
const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
|
||||
CRITICAL_SECTION_END;
|
||||
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
|
||||
return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
|
||||
}
|
||||
|
||||
void MarlinSerial::flush(void) {
|
||||
// Don't change this order of operations. If the RX interrupt occurs between
|
||||
// reading rx_buffer_head and updating rx_buffer_tail, the previous rx_buffer_head
|
||||
// may be written to rx_buffer_tail, making the buffer appear full rather than empty.
|
||||
CRITICAL_SECTION_START;
|
||||
rx_buffer.head = rx_buffer.tail = 0;
|
||||
clear_command_queue();
|
||||
CRITICAL_SECTION_END;
|
||||
|
||||
// Set the tail to the head:
|
||||
// - Read the RX head index in a safe way. (See atomic_read_rx_head.)
|
||||
// - Set the tail, making sure the RX ISR will always get a stable value, even
|
||||
// if it interrupts the writing of the value of that variable in the middle.
|
||||
atomic_set_rx_tail(atomic_read_rx_head());
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
// If the XOFF char was sent, or about to be sent...
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
writeNoHandshake(XON_CHAR);
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
// Signal we want an XON character to be sent.
|
||||
xon_xoff_state = XON_CHAR;
|
||||
// Enable TX ISR. Non atomic, but it will eventually enable it.
|
||||
SBI(M_UCSRxB, M_UDRIEx);
|
||||
#else
|
||||
// If not using TX interrupts, we must send the XON char now
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
|
||||
M_UDRx = XON_CHAR;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
uint8_t MarlinSerial::availableForWrite(void) {
|
||||
CRITICAL_SECTION_START;
|
||||
const uint8_t h = tx_buffer.head, t = tx_buffer.tail;
|
||||
CRITICAL_SECTION_END;
|
||||
return (uint8_t)(TX_BUFFER_SIZE + h - t) & (TX_BUFFER_SIZE - 1);
|
||||
}
|
||||
|
||||
void MarlinSerial::write(const uint8_t c) {
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
const uint8_t state = xon_xoff_state;
|
||||
if (!(state & XON_XOFF_CHAR_SENT)) {
|
||||
// Send 2 chars: XON/XOFF, then a user-specified char
|
||||
writeNoHandshake(state & XON_XOFF_CHAR_MASK);
|
||||
xon_xoff_state = state | XON_XOFF_CHAR_SENT;
|
||||
}
|
||||
#endif
|
||||
writeNoHandshake(c);
|
||||
}
|
||||
|
||||
void MarlinSerial::writeNoHandshake(const uint8_t c) {
|
||||
_written = true;
|
||||
CRITICAL_SECTION_START;
|
||||
bool emty = (tx_buffer.head == tx_buffer.tail);
|
||||
CRITICAL_SECTION_END;
|
||||
|
||||
// If the buffer and the data register is empty, just write the byte
|
||||
// to the data register and be done. This shortcut helps
|
||||
// significantly improve the effective datarate at high (>
|
||||
// 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
|
||||
if (emty && TEST(M_UCSRxA, M_UDREx)) {
|
||||
CRITICAL_SECTION_START;
|
||||
M_UDRx = c;
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
CRITICAL_SECTION_END;
|
||||
// If the TX interrupts are disabled and the data register
|
||||
// is empty, just write the byte to the data register and
|
||||
// be done. This shortcut helps significantly improve the
|
||||
// effective datarate at high (>500kbit/s) bitrates, where
|
||||
// interrupt overhead becomes a slowdown.
|
||||
// Yes, there is a race condition between the sending of the
|
||||
// XOFF char at the RX ISR, but it is properly handled there
|
||||
if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
|
||||
M_UDRx = c;
|
||||
|
||||
// clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
SBI(M_UCSRxA, M_TXCx);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
|
||||
|
||||
// If the output buffer is full, there's nothing for it other than to
|
||||
// wait for the interrupt handler to empty it a bit
|
||||
while (i == tx_buffer.tail) {
|
||||
if (!TEST(SREG, SREG_I)) {
|
||||
// Interrupts are disabled, so we'll have to poll the data
|
||||
// register empty flag ourselves. If it is set, pretend an
|
||||
// interrupt has happened and call the handler to free up
|
||||
// space for us.
|
||||
if (TEST(M_UCSRxA, M_UDREx))
|
||||
_tx_udr_empty_irq();
|
||||
}
|
||||
else {
|
||||
// nop, the interrupt handler will free up space for us
|
||||
// If global interrupts are disabled (as the result of being called from an ISR)...
|
||||
if (!ISRS_ENABLED()) {
|
||||
|
||||
// Make room by polling if it is possible to transmit, and do so!
|
||||
while (i == tx_buffer.tail) {
|
||||
|
||||
// If we can transmit another byte, do it.
|
||||
if (TEST(M_UCSRxA, M_UDREx)) _tx_udr_empty_irq();
|
||||
|
||||
// Make sure compiler rereads tx_buffer.tail
|
||||
sw_barrier();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Interrupts are enabled, just wait until there is space
|
||||
while (i == tx_buffer.tail) { sw_barrier(); }
|
||||
}
|
||||
|
||||
// Store new char. head is always safe to move
|
||||
tx_buffer.buffer[tx_buffer.head] = c;
|
||||
{ CRITICAL_SECTION_START;
|
||||
tx_buffer.head = i;
|
||||
SBI(M_UCSRxB, M_UDRIEx);
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
return;
|
||||
tx_buffer.head = i;
|
||||
|
||||
// Enable TX ISR - Non atomic, but it will eventually enable TX ISR
|
||||
SBI(M_UCSRxB, M_UDRIEx);
|
||||
}
|
||||
|
||||
void MarlinSerial::flushTX(void) {
|
||||
// TX
|
||||
// If we have never written a byte, no need to flush. This special
|
||||
// case is needed since there is no way to force the TXC (transmit
|
||||
// complete) bit to 1 during initialization
|
||||
if (!_written)
|
||||
return;
|
||||
// No bytes written, no need to flush. This special case is needed since there's
|
||||
// no way to force the TXC (transmit complete) bit to 1 during initialization.
|
||||
if (!_written) return;
|
||||
|
||||
while (TEST(M_UCSRxB, M_UDRIEx) || !TEST(M_UCSRxA, M_TXCx)) {
|
||||
if (!TEST(SREG, SREG_I) && TEST(M_UCSRxB, M_UDRIEx))
|
||||
// Interrupts are globally disabled, but the DR empty
|
||||
// interrupt should be enabled, so poll the DR empty flag to
|
||||
// prevent deadlock
|
||||
// If global interrupts are disabled (as the result of being called from an ISR)...
|
||||
if (!ISRS_ENABLED()) {
|
||||
|
||||
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
|
||||
while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) {
|
||||
|
||||
// If there is more space, send an extra character
|
||||
if (TEST(M_UCSRxA, M_UDREx))
|
||||
_tx_udr_empty_irq();
|
||||
|
||||
sw_barrier();
|
||||
}
|
||||
|
||||
}
|
||||
// If we get here, nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished tranmission (TXC is set).
|
||||
else {
|
||||
// Wait until everything was transmitted
|
||||
while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) sw_barrier();
|
||||
}
|
||||
|
||||
// At this point nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished transmission (TXC is set).
|
||||
}
|
||||
|
||||
#else // TX_BUFFER_SIZE == 0
|
||||
|
||||
void MarlinSerial::write(const uint8_t c) {
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
// Do a priority insertion of an XON/XOFF char, if needed.
|
||||
const uint8_t state = xon_xoff_state;
|
||||
if (!(state & XON_XOFF_CHAR_SENT)) {
|
||||
writeNoHandshake(state & XON_XOFF_CHAR_MASK);
|
||||
xon_xoff_state = state | XON_XOFF_CHAR_SENT;
|
||||
}
|
||||
#endif
|
||||
writeNoHandshake(c);
|
||||
}
|
||||
|
||||
void MarlinSerial::writeNoHandshake(uint8_t c) {
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) {/* nada */}
|
||||
_written = true;
|
||||
while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
|
||||
M_UDRx = c;
|
||||
}
|
||||
|
||||
void MarlinSerial::flushTX(void) {
|
||||
// No bytes written, no need to flush. This special case is needed since there's
|
||||
// no way to force the TXC (transmit complete) bit to 1 during initialization.
|
||||
if (!_written) return;
|
||||
|
||||
// Wait until everything was transmitted
|
||||
while (!TEST(M_UCSRxA, M_TXCx)) sw_barrier();
|
||||
|
||||
// At this point nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished transmission (TXC is set).
|
||||
}
|
||||
#endif // TX_BUFFER_SIZE == 0
|
||||
|
||||
/**
|
||||
@@ -437,13 +612,9 @@
|
||||
}
|
||||
|
||||
void MarlinSerial::print(long n, int base) {
|
||||
if (base == 0)
|
||||
write(n);
|
||||
if (base == 0) write(n);
|
||||
else if (base == 10) {
|
||||
if (n < 0) {
|
||||
print('-');
|
||||
n = -n;
|
||||
}
|
||||
if (n < 0) { print('-'); n = -n; }
|
||||
printNumber(n, 10);
|
||||
}
|
||||
else
|
||||
|
||||
+30
-15
@@ -26,10 +26,11 @@
|
||||
*
|
||||
* Modified 28 September 2010 by Mark Sproul
|
||||
* Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
|
||||
* Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
|
||||
*/
|
||||
|
||||
#ifndef MARLINSERIAL_H
|
||||
#define MARLINSERIAL_H
|
||||
#ifndef _MARLINSERIAL_H_
|
||||
#define _MARLINSERIAL_H_
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
@@ -59,6 +60,9 @@
|
||||
#define M_TXCx SERIAL_REGNAME(TXC,SERIAL_PORT,)
|
||||
#define M_RXCIEx SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
|
||||
#define M_UDREx SERIAL_REGNAME(UDRE,SERIAL_PORT,)
|
||||
#define M_FEx SERIAL_REGNAME(FE,SERIAL_PORT,)
|
||||
#define M_DORx SERIAL_REGNAME(DOR,SERIAL_PORT,)
|
||||
#define M_UPEx SERIAL_REGNAME(UPE,SERIAL_PORT,)
|
||||
#define M_UDRIEx SERIAL_REGNAME(UDRIE,SERIAL_PORT,)
|
||||
#define M_UDRx SERIAL_REGNAME(UDR,SERIAL_PORT,)
|
||||
#define M_UBRRxH SERIAL_REGNAME(UBRR,SERIAL_PORT,H)
|
||||
@@ -97,11 +101,19 @@
|
||||
extern uint8_t rx_dropped_bytes;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
extern uint8_t rx_buffer_overruns;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
extern uint8_t rx_framing_errors;
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
extern ring_buffer_pos_t rx_max_enqueued;
|
||||
#endif
|
||||
|
||||
class MarlinSerial { //: public Stream
|
||||
class MarlinSerial {
|
||||
|
||||
public:
|
||||
MarlinSerial() {};
|
||||
@@ -111,27 +123,25 @@
|
||||
static int read(void);
|
||||
static void flush(void);
|
||||
static ring_buffer_pos_t available(void);
|
||||
static void checkRx(void);
|
||||
static void write(const uint8_t c);
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
static uint8_t availableForWrite(void);
|
||||
static void flushTX(void);
|
||||
#endif
|
||||
static void writeNoHandshake(const uint8_t c);
|
||||
static void flushTX(void);
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
|
||||
FORCE_INLINE static uint32_t buffer_overruns() { return rx_buffer_overruns; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
|
||||
FORCE_INLINE static uint32_t framing_errors() { return rx_framing_errors; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
static void printNumber(unsigned long, const uint8_t);
|
||||
static void printFloat(double, uint8_t);
|
||||
|
||||
public:
|
||||
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
|
||||
FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
|
||||
FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
|
||||
@@ -155,6 +165,11 @@
|
||||
static void println(unsigned long, int = DEC);
|
||||
static void println(double, int = 2);
|
||||
static void println(void);
|
||||
operator bool() { return true; }
|
||||
|
||||
private:
|
||||
static void printNumber(unsigned long, const uint8_t);
|
||||
static void printFloat(double, uint8_t);
|
||||
};
|
||||
|
||||
extern MarlinSerial customizedSerial;
|
||||
@@ -166,4 +181,4 @@
|
||||
extern HardwareSerial bluetoothSerial;
|
||||
#endif
|
||||
|
||||
#endif // MARLINSERIAL_H
|
||||
#endif // _MARLINSERIAL_H_
|
||||
|
||||
+507
-308
File diff suppressed because it is too large
Load Diff
+304
-208
@@ -22,11 +22,9 @@
|
||||
|
||||
/**
|
||||
* This module is off by default, but can be enabled to facilitate the display of
|
||||
* extra debug information during code development. It assumes the existence of a
|
||||
* Max7219 LED Matrix. A suitable device can be obtained on eBay similar to this:
|
||||
* http://www.ebay.com/itm/191781645249 for under $2.00 including shipping.
|
||||
* extra debug information during code development.
|
||||
*
|
||||
* Just connect up +5v and GND to give it power, then connect up the pins assigned
|
||||
* Just connect up 5V and GND to give it power, then connect up the pins assigned
|
||||
* in Configuration_adv.h. For example, on the Re-ARM you could use:
|
||||
*
|
||||
* #define MAX7219_CLK_PIN 77
|
||||
@@ -35,26 +33,14 @@
|
||||
*
|
||||
* Max7219_init() is called automatically at startup, and then there are a number of
|
||||
* support functions available to control the LEDs in the 8x8 grid.
|
||||
*
|
||||
* void Max7219_init();
|
||||
* void Max7219_PutByte(uint8_t data);
|
||||
* void Max7219(uint8_t reg, uint8_t data);
|
||||
* void Max7219_LED_On(uint8_t col, uint8_t row);
|
||||
* void Max7219_LED_Off(uint8_t col, uint8_t row);
|
||||
* void Max7219_LED_Toggle(uint8_t col, uint8_t row);
|
||||
* void Max7219_Clear_Row(uint8_t row);
|
||||
* void Max7219_Clear_Column(uint8_t col);
|
||||
* void Max7219_Set_Row(uint8_t row, uint8_t val);
|
||||
* void Max7219_Set_2_Rows(uint8_t row, uint16_t val);
|
||||
* void Max7219_Set_4_Rows(uint8_t row, uint32_t val);
|
||||
* void Max7219_Set_Column(uint8_t col, uint8_t val);
|
||||
* void Max7219_idle_tasks();
|
||||
*/
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
#if ENABLED(MAX7219_DEBUG)
|
||||
|
||||
#define MAX7219_ERRORS // Disable to save 406 bytes of Program Memory
|
||||
|
||||
#include "Max7219_Debug_LEDs.h"
|
||||
|
||||
#include "planner.h"
|
||||
@@ -64,11 +50,43 @@
|
||||
|
||||
static uint8_t LEDs[8] = { 0 };
|
||||
|
||||
#ifndef MAX7219_ROTATE
|
||||
#define MAX7219_ROTATE 0
|
||||
#endif
|
||||
#define _ROT ((MAX7219_ROTATE + 360) % 360)
|
||||
#if _ROT == 0
|
||||
#define _ROW_ y
|
||||
#define _COL_ x
|
||||
#define XOR_7219(x, y) LEDs[y] ^= _BV(7 - x)
|
||||
#define BIT_7219(x, y) TEST(LEDs[y], 7 - x)
|
||||
#define SEND_7219(R,V) Max7219(max7219_reg_digit0 + R, V)
|
||||
#elif _ROT == 90
|
||||
#define _ROW_ x
|
||||
#define _COL_ y
|
||||
#define XOR_7219(x, y) LEDs[x] ^= _BV(y)
|
||||
#define BIT_7219(x, y) TEST(LEDs[x], y)
|
||||
#define SEND_7219(R,V) Max7219(max7219_reg_digit0 + R, V)
|
||||
#elif _ROT == 180
|
||||
#define _ROW_ y
|
||||
#define _COL_ x
|
||||
#define XOR_7219(x, y) LEDs[y] ^= _BV(x)
|
||||
#define BIT_7219(x, y) TEST(LEDs[y], x)
|
||||
#define SEND_7219(R,V) Max7219(max7219_reg_digit7 - R, V)
|
||||
#elif _ROT == 270
|
||||
#define _ROW_ x
|
||||
#define _COL_ y
|
||||
#define XOR_7219(x, y) LEDs[x] ^= _BV(7 - y)
|
||||
#define BIT_7219(x, y) TEST(LEDs[x], 7 - y)
|
||||
#define SEND_7219(R,V) Max7219(max7219_reg_digit7 - R, V)
|
||||
#else
|
||||
#error "MAX7219_ROTATE must be a multiple of +/- 90°."
|
||||
#endif
|
||||
|
||||
// Delay for 0.1875µs (16MHz AVR) or 0.15µs (20MHz AVR)
|
||||
#define SIG_DELAY() DELAY_NS(188)
|
||||
|
||||
void Max7219_PutByte(uint8_t data) {
|
||||
CRITICAL_SECTION_START
|
||||
CRITICAL_SECTION_START;
|
||||
for (uint8_t i = 8; i--;) {
|
||||
SIG_DELAY();
|
||||
WRITE(MAX7219_CLK_PIN, LOW); // tick
|
||||
@@ -79,12 +97,12 @@ void Max7219_PutByte(uint8_t data) {
|
||||
SIG_DELAY();
|
||||
data <<= 1;
|
||||
}
|
||||
CRITICAL_SECTION_END
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
void Max7219(const uint8_t reg, const uint8_t data) {
|
||||
SIG_DELAY();
|
||||
CRITICAL_SECTION_START
|
||||
CRITICAL_SECTION_START;
|
||||
WRITE(MAX7219_LOAD_PIN, LOW); // begin
|
||||
SIG_DELAY();
|
||||
Max7219_PutByte(reg); // specify register
|
||||
@@ -94,126 +112,170 @@ void Max7219(const uint8_t reg, const uint8_t data) {
|
||||
WRITE(MAX7219_LOAD_PIN, LOW); // and tell the chip to load the data
|
||||
SIG_DELAY();
|
||||
WRITE(MAX7219_LOAD_PIN, HIGH);
|
||||
CRITICAL_SECTION_END
|
||||
CRITICAL_SECTION_END;
|
||||
SIG_DELAY();
|
||||
}
|
||||
|
||||
void Max7219_LED_Set(const uint8_t col, const uint8_t row, const bool on) {
|
||||
if (row > 7 || col > 7) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_LED_Set(", (int)row);
|
||||
SERIAL_ECHOPAIR(",", (int)col);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
#if ENABLED(MAX7219_NUMERIC)
|
||||
|
||||
// Draw an integer with optional leading zeros and optional decimal point
|
||||
void Max7219_Print(const uint8_t start, int16_t value, uint8_t size, const bool leadzero=false, bool dec=false) {
|
||||
constexpr uint8_t led_numeral[10] = { 0x7E, 0x60, 0x6D, 0x79, 0x63, 0x5B, 0x5F, 0x70, 0x7F, 0x7A },
|
||||
led_decimal = 0x80, led_minus = 0x01;
|
||||
|
||||
bool blank = false, neg = value < 0;
|
||||
if (neg) value *= -1;
|
||||
while (size--) {
|
||||
const bool minus = neg && blank;
|
||||
if (minus) neg = false;
|
||||
Max7219(
|
||||
max7219_reg_digit0 + start + size,
|
||||
minus ? led_minus : blank ? 0x00 : led_numeral[value % 10] | (dec ? led_decimal : 0x00)
|
||||
);
|
||||
value /= 10;
|
||||
if (!value && !leadzero) blank = true;
|
||||
dec = false;
|
||||
}
|
||||
}
|
||||
if (TEST(LEDs[col], row) == on) return; // if LED is already on/off, leave alone
|
||||
if (on) SBI(LEDs[col], row); else CBI(LEDs[col], row);
|
||||
Max7219(8 - col, LEDs[col]);
|
||||
|
||||
// Draw a float with a decimal point and optional digits
|
||||
void Max7219_Print(const uint8_t start, const float value, const uint8_t pre_size, const uint8_t post_size, const bool leadzero=false) {
|
||||
if (pre_size) Max7219_Print(start, value, pre_size, leadzero, !!post_size);
|
||||
if (post_size) {
|
||||
const int16_t after = ABS(value) * (10 ^ post_size);
|
||||
Max7219_Print(start + pre_size, after, post_size, true);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MAX7219_NUMERIC
|
||||
|
||||
inline void Max7219_Error(const char * const func, const int32_t v1, const int32_t v2=-1) {
|
||||
#if ENABLED(MAX7219_ERRORS)
|
||||
SERIAL_ECHOPGM("??? ");
|
||||
serialprintPGM(func);
|
||||
SERIAL_CHAR('(');
|
||||
SERIAL_ECHO(v1);
|
||||
if (v2 > 0) SERIAL_ECHOPAIR(", ", v2);
|
||||
SERIAL_CHAR(')');
|
||||
SERIAL_EOL();
|
||||
#else
|
||||
UNUSED(func); UNUSED(v1); UNUSED(v2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Max7219_LED_On(const uint8_t col, const uint8_t row) {
|
||||
if (row > 7 || col > 7) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_LED_On(", (int)col);
|
||||
SERIAL_ECHOPAIR(",", (int)row);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
}
|
||||
Max7219_LED_Set(col, row, true);
|
||||
inline uint8_t flipped(const uint8_t bits) {
|
||||
uint8_t outbits = 0;
|
||||
for (uint8_t b = 0; b < 8; b++)
|
||||
if (bits & _BV(b)) outbits |= _BV(7 - b);
|
||||
return outbits;
|
||||
}
|
||||
|
||||
void Max7219_LED_Off(const uint8_t col, const uint8_t row) {
|
||||
if (row > 7 || col > 7) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_LED_Off(", (int)row);
|
||||
SERIAL_ECHOPAIR(",", (int)col);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
}
|
||||
Max7219_LED_Set(col, row, false);
|
||||
// Modify a single LED bit and send the changed line
|
||||
void Max7219_LED_Set(const uint8_t x, const uint8_t y, const bool on) {
|
||||
if (x > 7 || y > 7) return Max7219_Error(PSTR("Max7219_LED_Set"), x, y);
|
||||
if (BIT_7219(x, y) == on) return;
|
||||
XOR_7219(x, y);
|
||||
SEND_7219(_ROW_, LEDs[_ROW_]);
|
||||
}
|
||||
|
||||
void Max7219_LED_Toggle(const uint8_t col, const uint8_t row) {
|
||||
if (row > 7 || col > 7) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_LED_Toggle(", (int)row);
|
||||
SERIAL_ECHOPAIR(",", (int)col);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
}
|
||||
if (TEST(LEDs[row], col))
|
||||
Max7219_LED_Off(col, row);
|
||||
else
|
||||
Max7219_LED_On(col, row);
|
||||
void Max7219_LED_On(const uint8_t x, const uint8_t y) {
|
||||
if (x > 7 || y > 7) return Max7219_Error(PSTR("Max7219_LED_On"), x, y);
|
||||
Max7219_LED_Set(x, y, true);
|
||||
}
|
||||
|
||||
void Max7219_Clear_Column(const uint8_t col) {
|
||||
if (col > 7) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_Clear_Column(", (int)col);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
}
|
||||
LEDs[col] = 0;
|
||||
Max7219(8 - col, LEDs[col]);
|
||||
void Max7219_LED_Off(const uint8_t x, const uint8_t y) {
|
||||
if (x > 7 || y > 7) return Max7219_Error(PSTR("Max7219_LED_Off"), x, y);
|
||||
Max7219_LED_Set(x, y, false);
|
||||
}
|
||||
|
||||
void Max7219_Clear_Row(const uint8_t row) {
|
||||
if (row > 7) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_Clear_Row(", (int)row);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
}
|
||||
for (uint8_t c = 0; c <= 7; c++)
|
||||
Max7219_LED_Off(c, row);
|
||||
void Max7219_LED_Toggle(const uint8_t x, const uint8_t y) {
|
||||
if (x > 7 || y > 7) return Max7219_Error(PSTR("Max7219_LED_Toggle"), x, y);
|
||||
Max7219_LED_Set(x, y, !BIT_7219(x, y));
|
||||
}
|
||||
|
||||
void Max7219_Set_Row(const uint8_t row, const uint8_t val) {
|
||||
if (row > 7) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_Set_Row(", (int)row);
|
||||
SERIAL_ECHOPAIR(",", (int)val);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
}
|
||||
for (uint8_t b = 0; b <= 7; b++)
|
||||
if (TEST(val, b))
|
||||
Max7219_LED_On(7 - b, row);
|
||||
else
|
||||
Max7219_LED_Off(7 - b, row);
|
||||
inline void _Max7219_Set_Reg(const uint8_t reg, const uint8_t val) {
|
||||
LEDs[reg] = val;
|
||||
SEND_7219(reg, val);
|
||||
}
|
||||
|
||||
void Max7219_Set_2_Rows(const uint8_t row, const uint16_t val) {
|
||||
if (row > 6) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_Set_2_Rows(", (int)row);
|
||||
SERIAL_ECHOPAIR(",", (int)val);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
}
|
||||
Max7219_Set_Row(row + 1, (val >> 8) & 0xFF);
|
||||
Max7219_Set_Row(row + 0, (val ) & 0xFF);
|
||||
void Max7219_Set_Row(const uint8_t _ROW_, const uint8_t val) {
|
||||
if (_ROW_ > 7) return Max7219_Error(PSTR("Max7219_Set_Row"), _ROW_);
|
||||
#if _ROT == 90
|
||||
for (uint8_t _COL_ = 0; _COL_ <= 7; _COL_++) Max7219_LED_Set(7 - _COL_, _ROW_, TEST(val, _COL_));
|
||||
#elif _ROT == 180
|
||||
_Max7219_Set_Reg(_ROW_, flipped(val));
|
||||
#elif _ROT == 270
|
||||
for (uint8_t _COL_ = 0; _COL_ <= 7; _COL_++) Max7219_LED_Set(_COL_, _ROW_, TEST(val, _COL_));
|
||||
#else
|
||||
_Max7219_Set_Reg(_ROW_, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Max7219_Set_4_Rows(const uint8_t row, const uint32_t val) {
|
||||
if (row > 4) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_Set_4_Rows(", (int)row);
|
||||
SERIAL_ECHOPAIR(",", (long)val);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
}
|
||||
Max7219_Set_Row(row + 3, (val >> 24) & 0xFF);
|
||||
Max7219_Set_Row(row + 2, (val >> 16) & 0xFF);
|
||||
Max7219_Set_Row(row + 1, (val >> 8) & 0xFF);
|
||||
Max7219_Set_Row(row + 0, (val ) & 0xFF);
|
||||
void Max7219_Clear_Row(const uint8_t _ROW_) {
|
||||
if (_ROW_ > 7) return Max7219_Error(PSTR("Max7219_Clear_Row"), _ROW_);
|
||||
#if _ROT == 90 || _ROT == 270
|
||||
for (uint8_t _COL_ = 0; _COL_ <= 7; _COL_++) Max7219_LED_Off(_COL_, _ROW_);
|
||||
#else
|
||||
_Max7219_Set_Reg(_ROW_, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Max7219_Set_Column(const uint8_t col, const uint8_t val) {
|
||||
if (col > 7) {
|
||||
SERIAL_ECHOPAIR("??? Max7219_Column(", (int)col);
|
||||
SERIAL_ECHOPAIR(",", (int)val);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
return;
|
||||
}
|
||||
LEDs[col] = val;
|
||||
Max7219(8 - col, LEDs[col]);
|
||||
void Max7219_Set_Column(const uint8_t _COL_, const uint8_t val) {
|
||||
if (_COL_ > 7) return Max7219_Error(PSTR("Max7219_Set_Column"), _COL_);
|
||||
#if _ROT == 90
|
||||
_Max7219_Set_Reg(_COL_, val);
|
||||
#elif _ROT == 180
|
||||
for (uint8_t _ROW_ = 0; _ROW_ <= 7; _ROW_++) Max7219_LED_Set(_COL_, _ROW_, TEST(val, _ROW_));
|
||||
#elif _ROT == 270
|
||||
_Max7219_Set_Reg(_COL_, flipped(val));
|
||||
#else
|
||||
for (uint8_t _ROW_ = 0; _ROW_ <= 7; _ROW_++) Max7219_LED_Set(_COL_, _ROW_, TEST(val, _ROW_));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Max7219_Clear_Column(const uint8_t _COL_) {
|
||||
if (_COL_ > 7) return Max7219_Error(PSTR("Max7219_Clear_Column"), _COL_);
|
||||
#if _ROT == 90 || _ROT == 270
|
||||
_Max7219_Set_Reg(_COL_, 0);
|
||||
#else
|
||||
for (uint8_t _ROW_ = 0; _ROW_ <= 7; _ROW_++) Max7219_LED_Off(_COL_, _ROW_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Max7219_Clear() {
|
||||
for (uint8_t r = 0; r < 8; r++) _Max7219_Set_Reg(r, 0);
|
||||
}
|
||||
|
||||
void Max7219_Set_2_Rows(const uint8_t y, uint16_t val) {
|
||||
if (y > 6) return Max7219_Error(PSTR("Max7219_Set_2_Rows"), y, val);
|
||||
Max7219_Set_Row(y + 0, val & 0xFF); val >>= 8;
|
||||
Max7219_Set_Row(y + 1, val & 0xFF);
|
||||
}
|
||||
|
||||
void Max7219_Set_4_Rows(const uint8_t y, uint32_t val) {
|
||||
if (y > 4) return Max7219_Error(PSTR("Max7219_Set_4_Rows"), y, val);
|
||||
Max7219_Set_Row(y + 0, val & 0xFF); val >>= 8;
|
||||
Max7219_Set_Row(y + 1, val & 0xFF); val >>= 8;
|
||||
Max7219_Set_Row(y + 2, val & 0xFF); val >>= 8;
|
||||
Max7219_Set_Row(y + 3, val & 0xFF);
|
||||
}
|
||||
|
||||
void Max7219_Set_2_Columns(const uint8_t x, uint16_t val) {
|
||||
if (x > 6) return Max7219_Error(PSTR("Max7219_Set_2_Columns"), x, val);
|
||||
Max7219_Set_Column(x + 0, val & 0xFF); val >>= 8;
|
||||
Max7219_Set_Column(x + 1, val & 0xFF);
|
||||
}
|
||||
|
||||
void Max7219_Set_4_Columns(const uint8_t x, uint32_t val) {
|
||||
if (x > 4) return Max7219_Error(PSTR("Max7219_Set_4_Columns"), x, val);
|
||||
Max7219_Set_Column(x + 0, val & 0xFF); val >>= 8;
|
||||
Max7219_Set_Column(x + 1, val & 0xFF); val >>= 8;
|
||||
Max7219_Set_Column(x + 2, val & 0xFF); val >>= 8;
|
||||
Max7219_Set_Column(x + 3, val & 0xFF);
|
||||
}
|
||||
|
||||
void Max7219_register_setup() {
|
||||
//initiation of the max 7219
|
||||
// Initialize the Max7219
|
||||
Max7219(max7219_reg_scanLimit, 0x07);
|
||||
Max7219(max7219_reg_decodeMode, 0x00); // using an led matrix (not digits)
|
||||
Max7219(max7219_reg_shutdown, 0x01); // not in shutdown mode
|
||||
@@ -222,135 +284,169 @@ void Max7219_register_setup() {
|
||||
// range: 0x00 to 0x0F
|
||||
}
|
||||
|
||||
void Max7219_init() {
|
||||
uint8_t i, x, y;
|
||||
#ifdef MAX7219_INIT_TEST
|
||||
#if (MAX7219_INIT_TEST + 0) == 2
|
||||
|
||||
inline void Max7219_spiral(const bool on, const uint16_t del) {
|
||||
constexpr int8_t way[] = { 1, 0, 0, 1, -1, 0, 0, -1 };
|
||||
int8_t px = 0, py = 0, dir = 0;
|
||||
for (uint8_t i = 64; i--;) {
|
||||
Max7219_LED_Set(px, py, on);
|
||||
delay(del);
|
||||
const int8_t x = px + way[dir], y = py + way[dir + 1];
|
||||
if (!WITHIN(x, 0, 7) || !WITHIN(y, 0, 7) || BIT_7219(x, y) == on) dir = (dir + 2) & 0x7;
|
||||
px += way[dir]; py += way[dir + 1];
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void Max7219_colset(const uint8_t x, const bool on) {
|
||||
for (uint8_t y = 0; y <= 7; y++) Max7219_LED_Set(x, y, on);
|
||||
}
|
||||
inline void Max7219_sweep(const int8_t dir, const uint16_t ms, const bool on) {
|
||||
uint8_t x = dir > 0 ? 0 : 7;
|
||||
for (uint8_t i = 8; i--; x += dir) {
|
||||
Max7219_Set_Column(x, on ? 0xFF : 0x00);
|
||||
delay(ms);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // MAX7219_INIT_TEST
|
||||
|
||||
void Max7219_init() {
|
||||
SET_OUTPUT(MAX7219_DIN_PIN);
|
||||
SET_OUTPUT(MAX7219_CLK_PIN);
|
||||
|
||||
OUT_WRITE(MAX7219_LOAD_PIN, HIGH);
|
||||
delay(1);
|
||||
|
||||
Max7219_register_setup();
|
||||
|
||||
for (i = 0; i <= 7; i++) { // empty registers, turn all LEDs off
|
||||
for (uint8_t i = 0; i <= 7; i++) { // Empty registers to turn all LEDs off
|
||||
LEDs[i] = 0x00;
|
||||
Max7219(i + 1, 0);
|
||||
Max7219(max7219_reg_digit0 + i, 0);
|
||||
}
|
||||
|
||||
for (x = 0; x <= 7; x++) // Do an aesthetically pleasing pattern to fully test
|
||||
for (y = 0; y <= 7; y++) { // the Max7219 module and LEDs. First, turn them
|
||||
Max7219_LED_On(y, x); // all on.
|
||||
delay(3);
|
||||
}
|
||||
|
||||
for (x = 0; x <= 7; x++) // Now, turn them all off.
|
||||
for (y = 0; y <= 7; y++) {
|
||||
Max7219_LED_Off(y, x);
|
||||
delay(3); // delay() is OK here. Max7219_init() is only called from
|
||||
} // setup() and nothing is running yet.
|
||||
|
||||
delay(150);
|
||||
|
||||
for (x = 8; x--;) // Now, do the same thing from the opposite direction
|
||||
for (y = 0; y <= 7; y++) {
|
||||
Max7219_LED_On(y, x);
|
||||
delay(2);
|
||||
}
|
||||
|
||||
for (x = 8; x--;)
|
||||
for (y = 0; y <= 7; y++) {
|
||||
Max7219_LED_Off(y, x);
|
||||
delay(2);
|
||||
}
|
||||
#ifdef MAX7219_INIT_TEST
|
||||
#if (MAX7219_INIT_TEST + 0) == 2
|
||||
Max7219_spiral(true, 8);
|
||||
delay(150);
|
||||
Max7219_spiral(false, 8);
|
||||
#else
|
||||
// Do an aesthetically-pleasing pattern to fully test the Max7219 module and LEDs.
|
||||
// Light up and turn off columns, both forward and backward.
|
||||
Max7219_sweep(1, 20, true);
|
||||
Max7219_sweep(1, 20, false);
|
||||
delay(150);
|
||||
Max7219_sweep(-1, 20, true);
|
||||
Max7219_sweep(-1, 20, false);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* These are sample debug features to demonstrate the usage of the 8x8 LED Matrix for debug purposes.
|
||||
* There is very little CPU burden added to the system by displaying information within the idle()
|
||||
* task.
|
||||
*
|
||||
* But with that said, if your debugging can be facilitated by making calls into the library from
|
||||
* other places in the code, feel free to do it. The CPU burden for a few calls to toggle an LED
|
||||
* or clear a row is not very significant.
|
||||
* This code demonstrates some simple debugging using a single 8x8 LED Matrix. If your feature could
|
||||
* benefit from matrix display, add its code here. Very little processing is required, so the 7219 is
|
||||
* ideal for debugging when realtime feedback is important but serial output can't be used.
|
||||
*/
|
||||
|
||||
// Apply changes to update a marker
|
||||
inline void Max7219_Mark16(const uint8_t y, const uint8_t v1, const uint8_t v2) {
|
||||
Max7219_LED_Off(v1 & 0x7, y + (v1 >= 8));
|
||||
Max7219_LED_On(v2 & 0x7, y + (v2 >= 8));
|
||||
}
|
||||
|
||||
// Apply changes to update a tail-to-head range
|
||||
inline void Max7219_Range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh) {
|
||||
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
|
||||
Max7219_LED_Off(n & 0x7, y + (n >= 8));
|
||||
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
|
||||
Max7219_LED_On(n & 0x7, y + (n >= 8));
|
||||
}
|
||||
|
||||
// Apply changes to update a quantity
|
||||
inline void Max7219_Quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv) {
|
||||
for (uint8_t i = MIN(nv, ov); i < MAX(nv, ov); i++)
|
||||
Max7219_LED_Set(i >> 1, y + (i & 1), nv >= ov);
|
||||
}
|
||||
|
||||
void Max7219_idle_tasks() {
|
||||
#if MAX7219_DEBUG_STEPPER_HEAD || MAX7219_DEBUG_STEPPER_TAIL || MAX7219_DEBUG_STEPPER_QUEUE
|
||||
CRITICAL_SECTION_START
|
||||
#if MAX7219_DEBUG_STEPPER_HEAD || MAX7219_DEBUG_STEPPER_QUEUE
|
||||
#define MAX7219_USE_HEAD (defined(MAX7219_DEBUG_PLANNER_HEAD) || defined(MAX7219_DEBUG_PLANNER_QUEUE))
|
||||
#define MAX7219_USE_TAIL (defined(MAX7219_DEBUG_PLANNER_TAIL) || defined(MAX7219_DEBUG_PLANNER_QUEUE))
|
||||
#if MAX7219_USE_HEAD || MAX7219_USE_TAIL
|
||||
CRITICAL_SECTION_START;
|
||||
#if MAX7219_USE_HEAD
|
||||
const uint8_t head = planner.block_buffer_head;
|
||||
#endif
|
||||
#if MAX7219_DEBUG_STEPPER_TAIL || MAX7219_DEBUG_STEPPER_QUEUE
|
||||
#if MAX7219_USE_TAIL
|
||||
const uint8_t tail = planner.block_buffer_tail;
|
||||
#endif
|
||||
CRITICAL_SECTION_END
|
||||
CRITICAL_SECTION_END;
|
||||
#endif
|
||||
|
||||
static uint16_t refresh_cnt = 0; // The Max7219 circuit boards available for several dollars on eBay
|
||||
if (refresh_cnt++ > 50000) { // are vulnerable to electrical noise, especially with long wires
|
||||
Max7219_register_setup(); // next to high current wires. If the display becomes corrupted due
|
||||
Max7219_LED_Toggle(7, 0); // to electrical noise, this will fix it within a couple of seconds.
|
||||
#if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
|
||||
static uint8_t refresh_cnt; // = 0
|
||||
constexpr uint16_t refresh_limit = 5;
|
||||
static millis_t next_blink = 0;
|
||||
const millis_t ms = millis();
|
||||
const bool do_blink = ELAPSED(ms, next_blink);
|
||||
#else
|
||||
static uint16_t refresh_cnt; // = 0
|
||||
constexpr bool do_blink = true;
|
||||
constexpr uint16_t refresh_limit = 50000;
|
||||
#endif
|
||||
|
||||
// Some Max7219 units are vulnerable to electrical noise, especially
|
||||
// with long wires next to high current wires. If the display becomes
|
||||
// corrupted, this will fix it within a couple seconds.
|
||||
if (do_blink && ++refresh_cnt >= refresh_limit) {
|
||||
refresh_cnt = 0;
|
||||
Max7219_register_setup();
|
||||
}
|
||||
|
||||
#if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
|
||||
static millis_t next_blink = 0;
|
||||
if (ELAPSED(millis(), next_blink)) {
|
||||
if (do_blink) {
|
||||
Max7219_LED_Toggle(7, 7);
|
||||
next_blink = millis() + 750;
|
||||
next_blink = ms + 1000;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAX7219_DEBUG_STEPPER_HEAD
|
||||
static int16_t last_head_cnt = 0;
|
||||
if (last_head_cnt != head) {
|
||||
if (last_head_cnt < 8)
|
||||
Max7219_LED_Off(MAX7219_DEBUG_STEPPER_HEAD, last_head_cnt);
|
||||
else
|
||||
Max7219_LED_Off(MAX7219_DEBUG_STEPPER_HEAD + 1, last_head_cnt - 8);
|
||||
#if defined(MAX7219_DEBUG_PLANNER_HEAD) && defined(MAX7219_DEBUG_PLANNER_TAIL) && MAX7219_DEBUG_PLANNER_HEAD == MAX7219_DEBUG_PLANNER_TAIL
|
||||
|
||||
static int16_t last_head_cnt = 0xF, last_tail_cnt = 0xF;
|
||||
|
||||
if (last_head_cnt != head || last_tail_cnt != tail) {
|
||||
Max7219_Range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head);
|
||||
last_head_cnt = head;
|
||||
if (head < 8)
|
||||
Max7219_LED_On(MAX7219_DEBUG_STEPPER_HEAD, head);
|
||||
else
|
||||
Max7219_LED_On(MAX7219_DEBUG_STEPPER_HEAD + 1, head - 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAX7219_DEBUG_STEPPER_TAIL
|
||||
static int16_t last_tail_cnt = 0;
|
||||
if (last_tail_cnt != tail) {
|
||||
if (last_tail_cnt < 8)
|
||||
Max7219_LED_Off(MAX7219_DEBUG_STEPPER_TAIL, last_tail_cnt);
|
||||
else
|
||||
Max7219_LED_Off(MAX7219_DEBUG_STEPPER_TAIL + 1, last_tail_cnt - 8);
|
||||
|
||||
last_tail_cnt = tail;
|
||||
if (tail < 8)
|
||||
Max7219_LED_On(MAX7219_DEBUG_STEPPER_TAIL, tail);
|
||||
else
|
||||
Max7219_LED_On(MAX7219_DEBUG_STEPPER_TAIL + 1, tail - 8);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef MAX7219_DEBUG_PLANNER_HEAD
|
||||
static int16_t last_head_cnt = 0x1;
|
||||
if (last_head_cnt != head) {
|
||||
Max7219_Mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head);
|
||||
last_head_cnt = head;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAX7219_DEBUG_PLANNER_TAIL
|
||||
static int16_t last_tail_cnt = 0x1;
|
||||
if (last_tail_cnt != tail) {
|
||||
Max7219_Mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail);
|
||||
last_tail_cnt = tail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MAX7219_DEBUG_STEPPER_QUEUE
|
||||
#ifdef MAX7219_DEBUG_PLANNER_QUEUE
|
||||
static int16_t last_depth = 0;
|
||||
int16_t current_depth = head - tail;
|
||||
if (current_depth != last_depth) { // usually, no update will be needed.
|
||||
if (current_depth < 0) current_depth += BLOCK_BUFFER_SIZE;
|
||||
NOMORE(current_depth, BLOCK_BUFFER_SIZE);
|
||||
NOMORE(current_depth, 16); // if the BLOCK_BUFFER_SIZE is greater than 16, two lines
|
||||
// of LEDs is enough to see if the buffer is draining
|
||||
|
||||
const uint8_t st = MIN(current_depth, last_depth),
|
||||
en = MAX(current_depth, last_depth);
|
||||
if (current_depth < last_depth)
|
||||
for (uint8_t i = st; i <= en; i++) // clear the highest order LEDs
|
||||
Max7219_LED_Off(MAX7219_DEBUG_STEPPER_QUEUE + (i & 1), i / 2);
|
||||
else
|
||||
for (uint8_t i = st; i <= en; i++) // set the LEDs to current depth
|
||||
Max7219_LED_On(MAX7219_DEBUG_STEPPER_QUEUE + (i & 1), i / 2);
|
||||
|
||||
const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF;
|
||||
if (current_depth != last_depth) {
|
||||
Max7219_Quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth);
|
||||
last_depth = current_depth;
|
||||
}
|
||||
#endif
|
||||
|
||||
+25
-29
@@ -22,11 +22,9 @@
|
||||
|
||||
/**
|
||||
* This module is off by default, but can be enabled to facilitate the display of
|
||||
* extra debug information during code development. It assumes the existence of a
|
||||
* Max7219 LED Matrix. A suitable device can be obtained on eBay similar to this:
|
||||
* http://www.ebay.com/itm/191781645249 for under $2.00 including shipping.
|
||||
* extra debug information during code development.
|
||||
*
|
||||
* Just connect up +5v and GND to give it power, then connect up the pins assigned
|
||||
* Just connect up 5V and GND to give it power, then connect up the pins assigned
|
||||
* in Configuration_adv.h. For example, on the Re-ARM you could use:
|
||||
*
|
||||
* #define MAX7219_CLK_PIN 77
|
||||
@@ -35,28 +33,13 @@
|
||||
*
|
||||
* Max7219_init() is called automatically at startup, and then there are a number of
|
||||
* support functions available to control the LEDs in the 8x8 grid.
|
||||
*
|
||||
* void Max7219_init();
|
||||
* void Max7219_PutByte(uint8_t data);
|
||||
* void Max7219(uint8_t reg, uint8_t data);
|
||||
* void Max7219_LED_Set(uint8_t row, uint8_t col, bool on);
|
||||
* void Max7219_LED_On(uint8_t col, uint8_t row);
|
||||
* void Max7219_LED_Off(uint8_t col, uint8_t row);
|
||||
* void Max7219_LED_Toggle(uint8_t row, uint8_t col);
|
||||
* void Max7219_Clear_Row(uint8_t row);
|
||||
* void Max7219_Clear_Column(uint8_t col);
|
||||
* void Max7219_Set_Row(uint8_t row, uint8_t val);
|
||||
* void Max7219_Set_2_Rows(uint8_t row, uint16_t val);
|
||||
* void Max7219_Set_4_Rows(uint8_t row, uint32_t val);
|
||||
* void Max7219_Set_Column(uint8_t col, uint8_t val);
|
||||
* void Max7219_idle_tasks();
|
||||
*/
|
||||
|
||||
#ifndef __MAX7219_DEBUG_LEDS_H__
|
||||
#define __MAX7219_DEBUG_LEDS_H__
|
||||
|
||||
//
|
||||
// define max7219 registers
|
||||
// MAX7219 registers
|
||||
//
|
||||
#define max7219_reg_noop 0x00
|
||||
#define max7219_reg_digit0 0x01
|
||||
@@ -68,23 +51,36 @@
|
||||
#define max7219_reg_digit6 0x07
|
||||
#define max7219_reg_digit7 0x08
|
||||
|
||||
#define max7219_reg_intensity 0x0A
|
||||
#define max7219_reg_displayTest 0x0F
|
||||
#define max7219_reg_decodeMode 0x09
|
||||
#define max7219_reg_intensity 0x0A
|
||||
#define max7219_reg_scanLimit 0x0B
|
||||
#define max7219_reg_shutdown 0x0C
|
||||
#define max7219_reg_displayTest 0x0F
|
||||
|
||||
void Max7219_init();
|
||||
void Max7219_PutByte(uint8_t data);
|
||||
|
||||
// Set a single register (e.g., a whole native row)
|
||||
void Max7219(const uint8_t reg, const uint8_t data);
|
||||
void Max7219_LED_Set(const uint8_t row, const uint8_t col, const bool on);
|
||||
void Max7219_LED_On(const uint8_t row, const uint8_t col);
|
||||
void Max7219_LED_Off(const uint8_t row, const uint8_t col);
|
||||
void Max7219_LED_Toggle(const uint8_t row, const uint8_t col);
|
||||
void Max7219_Clear_Row(const uint8_t row);
|
||||
void Max7219_Clear_Column(const uint8_t col);
|
||||
void Max7219_Set_Row(const uint8_t row, const uint8_t val);
|
||||
|
||||
// Set a single LED by XY coordinate
|
||||
void Max7219_LED_Set(const uint8_t x, const uint8_t y, const bool on);
|
||||
void Max7219_LED_On(const uint8_t x, const uint8_t y);
|
||||
void Max7219_LED_Off(const uint8_t x, const uint8_t y);
|
||||
void Max7219_LED_Toggle(const uint8_t x, const uint8_t y);
|
||||
|
||||
// Set all 8 LEDs in a single column
|
||||
void Max7219_Set_Column(const uint8_t col, const uint8_t val);
|
||||
void Max7219_Clear_Column(const uint8_t col);
|
||||
|
||||
// Set all 8 LEDs in a single row
|
||||
void Max7219_Set_Row(const uint8_t row, const uint8_t val);
|
||||
void Max7219_Clear_Row(const uint8_t row);
|
||||
|
||||
// Quickly clear the whole matrix
|
||||
void Max7219_Clear();
|
||||
|
||||
// Apply custom code to update the matrix
|
||||
void Max7219_idle_tasks();
|
||||
|
||||
#endif // __MAX7219_DEBUG_LEDS_H__
|
||||
|
||||
+23
-9
@@ -54,7 +54,9 @@
|
||||
/**
|
||||
* Warnings for old configurations
|
||||
*/
|
||||
#if !defined(X_BED_SIZE) || !defined(Y_BED_SIZE)
|
||||
#ifndef MOTHERBOARD
|
||||
#error "MOTHERBOARD is required. Please update your configuration."
|
||||
#elif !defined(X_BED_SIZE) || !defined(Y_BED_SIZE)
|
||||
#error "X_BED_SIZE and Y_BED_SIZE are now required! Please update your configuration."
|
||||
#elif WATCH_TEMP_PERIOD > 500
|
||||
#error "WATCH_TEMP_PERIOD now uses seconds instead of milliseconds."
|
||||
@@ -273,6 +275,20 @@
|
||||
#error "FILAMENT_CHANGE_LOAD_LENGTH is now FILAMENT_CHANGE_FAST_LOAD_LENGTH. Please update your configuration."
|
||||
#elif ENABLED(LEVEL_BED_CORNERS) && !defined(LEVEL_CORNERS_INSET)
|
||||
#error "LEVEL_BED_CORNERS requires a LEVEL_CORNERS_INSET value. Please update your Configuration.h."
|
||||
#elif defined(BEZIER_JERK_CONTROL)
|
||||
#error "BEZIER_JERK_CONTROL is now S_CURVE_ACCELERATION. Please update your configuration."
|
||||
#elif defined(JUNCTION_DEVIATION_FACTOR)
|
||||
#error "JUNCTION_DEVIATION_FACTOR is now JUNCTION_DEVIATION_MM. Please update your configuration."
|
||||
#elif defined(JUNCTION_ACCELERATION_FACTOR)
|
||||
#error "JUNCTION_ACCELERATION_FACTOR is obsolete. Delete it from Configuration_adv.h."
|
||||
#elif defined(JUNCTION_ACCELERATION)
|
||||
#error "JUNCTION_ACCELERATION is obsolete. Delete it from Configuration_adv.h."
|
||||
#elif defined(MAX7219_DEBUG_STEPPER_HEAD)
|
||||
#error "MAX7219_DEBUG_STEPPER_HEAD is now MAX7219_DEBUG_PLANNER_HEAD. Please update your configuration."
|
||||
#elif defined(MAX7219_DEBUG_STEPPER_TAIL)
|
||||
#error "MAX7219_DEBUG_STEPPER_TAIL is now MAX7219_DEBUG_PLANNER_TAIL. Please update your configuration."
|
||||
#elif defined(MAX7219_DEBUG_STEPPER_QUEUE)
|
||||
#error "MAX7219_DEBUG_STEPPER_QUEUE is now MAX7219_DEBUG_PLANNER_QUEUE. Please update your configuration."
|
||||
#endif
|
||||
|
||||
#define BOARD_MKS_13 -47
|
||||
@@ -920,15 +936,11 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE && Y_MAX_LENGTH >= Y_BED_SIZE,
|
||||
*/
|
||||
#if ENABLED(Z_SAFE_HOMING)
|
||||
#if HAS_BED_PROBE
|
||||
static_assert(WITHIN(Z_SAFE_HOMING_X_POINT, MIN_PROBE_X, MAX_PROBE_X),
|
||||
"Z_SAFE_HOMING_X_POINT is outside the probe region.");
|
||||
static_assert(WITHIN(Z_SAFE_HOMING_Y_POINT, MIN_PROBE_Y, MAX_PROBE_Y),
|
||||
"Z_SAFE_HOMING_Y_POINT is outside the probe region.");
|
||||
static_assert(WITHIN(Z_SAFE_HOMING_X_POINT, MIN_PROBE_X, MAX_PROBE_X), "Z_SAFE_HOMING_X_POINT is outside the probe region.");
|
||||
static_assert(WITHIN(Z_SAFE_HOMING_Y_POINT, MIN_PROBE_Y, MAX_PROBE_Y), "Z_SAFE_HOMING_Y_POINT is outside the probe region.");
|
||||
#else
|
||||
static_assert(WITHIN(Z_SAFE_HOMING_X_POINT, X_MIN_POS, X_MAX_POS),
|
||||
"Z_SAFE_HOMING_X_POINT can't be reached by the nozzle.");
|
||||
static_assert(WITHIN(Z_SAFE_HOMING_Y_POINT, Y_MIN_POS, Y_MAX_POS),
|
||||
"Z_SAFE_HOMING_Y_POINT can't be reached by the nozzle.");
|
||||
static_assert(WITHIN(Z_SAFE_HOMING_X_POINT, X_MIN_POS, X_MAX_POS), "Z_SAFE_HOMING_X_POINT can't be reached by the nozzle.");
|
||||
static_assert(WITHIN(Z_SAFE_HOMING_Y_POINT, Y_MIN_POS, Y_MAX_POS), "Z_SAFE_HOMING_Y_POINT can't be reached by the nozzle.");
|
||||
#endif
|
||||
#endif // Z_SAFE_HOMING
|
||||
|
||||
@@ -1482,6 +1494,8 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE && Y_MAX_LENGTH >= Y_BED_SIZE,
|
||||
#error "SENSORLESS_HOMING requires Z_MIN_ENDSTOP_INVERTING and ENDSTOPPULLUP_ZMIN when homing to Z_MIN."
|
||||
#elif Z_SENSORLESS && Z_HOME_DIR == 1 && (DISABLED(Z_MAX_ENDSTOP_INVERTING) || DISABLED(ENDSTOPPULLUP_ZMAX))
|
||||
#error "SENSORLESS_HOMING requires Z_MAX_ENDSTOP_INVERTING and ENDSTOPPULLUP_ZMAX when homing to Z_MAX."
|
||||
#elif ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
#error "SENSORLESS_HOMING is incompatible with ENDSTOP_NOISE_FILTER."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
+2
-2
@@ -35,7 +35,7 @@
|
||||
/**
|
||||
* Marlin release version identifier
|
||||
*/
|
||||
#define SHORT_BUILD_VERSION "1.1.8-R6"
|
||||
#define SHORT_BUILD_VERSION "1.1.8-R7"
|
||||
|
||||
/**
|
||||
* Verbose version identifier which should contain a reference to the location
|
||||
@@ -48,7 +48,7 @@
|
||||
* here we define this default string as the date where the latest release
|
||||
* version was tagged.
|
||||
*/
|
||||
#define STRING_DISTRIBUTION_DATE "2018-05-26"
|
||||
#define STRING_DISTRIBUTION_DATE "2018-07-07"
|
||||
|
||||
/**
|
||||
* Required minimum Configuration.h and Configuration_adv.h file versions.
|
||||
|
||||
+1
-1
@@ -156,6 +156,6 @@
|
||||
#define BOARD_TEENSY2 84 // Teensy++2.0 (AT90USB1286) - CLI compile: HARDWARE_MOTHERBOARD=84 make
|
||||
#define BOARD_5DPRINT 88 // 5DPrint D8 Driver Board
|
||||
|
||||
#define MB(board) (MOTHERBOARD==BOARD_##board)
|
||||
#define MB(board) (defined(BOARD_##board) && MOTHERBOARD==BOARD_##board)
|
||||
|
||||
#endif // __BOARDS_H
|
||||
|
||||
+26
-18
@@ -98,8 +98,8 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
||||
createFilename(dosFilename, p);
|
||||
|
||||
// Allocate enough stack space for the full path to a folder, trailing slash, and nul
|
||||
bool prepend_is_empty = (prepend[0] == '\0');
|
||||
int len = (prepend_is_empty ? 1 : strlen(prepend)) + strlen(dosFilename) + 1 + 1;
|
||||
const bool prepend_is_empty = (!prepend || prepend[0] == '\0');
|
||||
const int len = (prepend_is_empty ? 1 : strlen(prepend)) + strlen(dosFilename) + 1 + 1;
|
||||
char path[len];
|
||||
|
||||
// Append the FOLDERNAME12/ to the passed string.
|
||||
@@ -501,9 +501,13 @@ void CardReader::checkautostart() {
|
||||
|
||||
if (!cardOK) initsd();
|
||||
|
||||
if (cardOK) {
|
||||
if (cardOK
|
||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||
&& !jobRecoverFileExists() // Don't run auto#.g when a resume file exists
|
||||
#endif
|
||||
) {
|
||||
char autoname[10];
|
||||
sprintf_P(autoname, PSTR("auto%i.g"), autostart_index);
|
||||
sprintf_P(autoname, PSTR("auto%i.g"), int(autostart_index));
|
||||
dir_t p;
|
||||
root.rewind();
|
||||
while (root.readDir(&p, NULL) > 0) {
|
||||
@@ -582,9 +586,8 @@ const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, con
|
||||
while (dirname_start) {
|
||||
char * const dirname_end = strchr(dirname_start, '/');
|
||||
if (dirname_end <= dirname_start) break;
|
||||
|
||||
char dosSubdirname[FILENAME_LENGTH];
|
||||
const uint8_t len = dirname_end - dirname_start;
|
||||
char dosSubdirname[len + 1];
|
||||
strncpy(dosSubdirname, dirname_start, len);
|
||||
dosSubdirname[len] = 0;
|
||||
|
||||
@@ -898,11 +901,7 @@ void CardReader::printingHasFinished() {
|
||||
sdprinting = false;
|
||||
|
||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||
openJobRecoveryFile(false);
|
||||
job_recovery_info.valid_head = job_recovery_info.valid_foot = 0;
|
||||
(void)saveJobRecoveryInfo();
|
||||
closeJobRecoveryFile();
|
||||
job_recovery_commands_count = 0;
|
||||
removeJobRecoveryFile();
|
||||
#endif
|
||||
|
||||
#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
|
||||
@@ -948,20 +947,24 @@ void CardReader::printingHasFinished() {
|
||||
SERIAL_PROTOCOLCHAR('.');
|
||||
SERIAL_EOL();
|
||||
}
|
||||
else
|
||||
else if (!read)
|
||||
SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, job_recovery_file_name);
|
||||
}
|
||||
|
||||
void CardReader::closeJobRecoveryFile() { jobRecoveryFile.close(); }
|
||||
|
||||
bool CardReader::jobRecoverFileExists() {
|
||||
return jobRecoveryFile.open(&root, job_recovery_file_name, O_READ);
|
||||
const bool exists = jobRecoveryFile.open(&root, job_recovery_file_name, O_READ);
|
||||
if (exists) jobRecoveryFile.close();
|
||||
return exists;
|
||||
}
|
||||
|
||||
int16_t CardReader::saveJobRecoveryInfo() {
|
||||
jobRecoveryFile.seekSet(0);
|
||||
const int16_t ret = jobRecoveryFile.write(&job_recovery_info, sizeof(job_recovery_info));
|
||||
if (ret == -1) SERIAL_PROTOCOLLNPGM("Power-loss file write failed.");
|
||||
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
|
||||
if (ret == -1) SERIAL_PROTOCOLLNPGM("Power-loss file write failed.");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -970,10 +973,15 @@ void CardReader::printingHasFinished() {
|
||||
}
|
||||
|
||||
void CardReader::removeJobRecoveryFile() {
|
||||
if (jobRecoveryFile.remove(&root, job_recovery_file_name))
|
||||
SERIAL_PROTOCOLLNPGM("Power-loss file deleted.");
|
||||
else
|
||||
SERIAL_PROTOCOLLNPGM("Power-loss file delete failed.");
|
||||
job_recovery_info.valid_head = job_recovery_info.valid_foot = job_recovery_commands_count = 0;
|
||||
if (jobRecoverFileExists()) {
|
||||
closefile();
|
||||
removeFile(job_recovery_file_name);
|
||||
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
|
||||
SERIAL_PROTOCOLPGM("Power-loss file delete");
|
||||
serialprintPGM(jobRecoverFileExists() ? PSTR(" failed.\n") : PSTR("d.\n"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif // POWER_LOSS_RECOVERY
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ public:
|
||||
public:
|
||||
bool saving, logging, sdprinting, cardOK, filenameIsDir;
|
||||
char filename[FILENAME_LENGTH], longFilename[LONG_FILENAME_LENGTH];
|
||||
int autostart_index;
|
||||
int8_t autostart_index;
|
||||
private:
|
||||
SdFile root, workDir, workDirParents[MAX_DIR_DEPTH];
|
||||
uint8_t workDirDepth;
|
||||
|
||||
+180
-119
@@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
// Change EEPROM version if the structure changes
|
||||
#define EEPROM_VERSION "V54"
|
||||
#define EEPROM_VERSION "V55"
|
||||
#define EEPROM_OFFSET 100
|
||||
|
||||
// Check the integrity of data offsets.
|
||||
@@ -97,16 +97,17 @@ typedef struct SettingsDataStruct {
|
||||
//
|
||||
uint8_t esteppers; // XYZE_N - XYZ
|
||||
|
||||
uint32_t planner_max_acceleration_mm_per_s2[XYZE_N], // M201 XYZE planner.max_acceleration_mm_per_s2[XYZE_N]
|
||||
planner_min_segment_time_us; // M205 B planner.min_segment_time_us
|
||||
float planner_axis_steps_per_mm[XYZE_N], // M92 XYZE planner.axis_steps_per_mm[XYZE_N]
|
||||
planner_max_feedrate_mm_s[XYZE_N]; // M203 XYZE planner.max_feedrate_mm_s[XYZE_N]
|
||||
uint32_t planner_max_acceleration_mm_per_s2[XYZE_N]; // M201 XYZE planner.max_acceleration_mm_per_s2[XYZE_N]
|
||||
float planner_acceleration, // M204 P planner.acceleration
|
||||
planner_max_feedrate_mm_s[XYZE_N], // M203 XYZE planner.max_feedrate_mm_s[XYZE_N]
|
||||
planner_acceleration, // M204 P planner.acceleration
|
||||
planner_retract_acceleration, // M204 R planner.retract_acceleration
|
||||
planner_travel_acceleration, // M204 T planner.travel_acceleration
|
||||
planner_min_feedrate_mm_s, // M205 S planner.min_feedrate_mm_s
|
||||
planner_min_travel_feedrate_mm_s; // M205 T planner.min_travel_feedrate_mm_s
|
||||
uint32_t planner_min_segment_time_us; // M205 B planner.min_segment_time_us
|
||||
float planner_max_jerk[XYZE]; // M205 XYZE planner.max_jerk[XYZE]
|
||||
planner_min_travel_feedrate_mm_s, // M205 T planner.min_travel_feedrate_mm_s
|
||||
planner_max_jerk[XYZE], // M205 XYZE planner.max_jerk[XYZE]
|
||||
planner_junction_deviation_mm; // M205 J planner.junction_deviation_mm
|
||||
|
||||
float home_offset[XYZ]; // M206 XYZ
|
||||
|
||||
@@ -318,6 +319,10 @@ void MarlinSettings::postprocess() {
|
||||
fwretract.refresh_autoretract();
|
||||
#endif
|
||||
|
||||
#if ENABLED(JUNCTION_DEVIATION) && ENABLED(LIN_ADVANCE)
|
||||
planner.recalculate_max_e_jerk();
|
||||
#endif
|
||||
|
||||
// Refresh steps_to_mm with the reciprocal of axis_steps_per_mm
|
||||
// and init stepper.count[], planner.position[] with current_position
|
||||
planner.refresh_positioning();
|
||||
@@ -397,7 +402,7 @@ void MarlinSettings::postprocess() {
|
||||
* M500 - Store Configuration
|
||||
*/
|
||||
bool MarlinSettings::save() {
|
||||
float dummy = 0.0f;
|
||||
float dummy = 0;
|
||||
char ver[4] = "ERR";
|
||||
|
||||
uint16_t working_crc = 0;
|
||||
@@ -416,17 +421,25 @@ void MarlinSettings::postprocess() {
|
||||
const uint8_t esteppers = COUNT(planner.axis_steps_per_mm) - XYZ;
|
||||
EEPROM_WRITE(esteppers);
|
||||
|
||||
EEPROM_WRITE(planner.max_acceleration_mm_per_s2);
|
||||
EEPROM_WRITE(planner.min_segment_time_us);
|
||||
EEPROM_WRITE(planner.axis_steps_per_mm);
|
||||
EEPROM_WRITE(planner.max_feedrate_mm_s);
|
||||
EEPROM_WRITE(planner.max_acceleration_mm_per_s2);
|
||||
|
||||
EEPROM_WRITE(planner.acceleration);
|
||||
EEPROM_WRITE(planner.retract_acceleration);
|
||||
EEPROM_WRITE(planner.travel_acceleration);
|
||||
EEPROM_WRITE(planner.min_feedrate_mm_s);
|
||||
EEPROM_WRITE(planner.min_travel_feedrate_mm_s);
|
||||
EEPROM_WRITE(planner.min_segment_time_us);
|
||||
EEPROM_WRITE(planner.max_jerk);
|
||||
|
||||
#if ENABLED(JUNCTION_DEVIATION)
|
||||
const float planner_max_jerk[] = { float(DEFAULT_XJERK), float(DEFAULT_YJERK), float(DEFAULT_ZJERK), float(DEFAULT_EJERK) };
|
||||
EEPROM_WRITE(planner_max_jerk);
|
||||
EEPROM_WRITE(planner.junction_deviation_mm);
|
||||
#else
|
||||
EEPROM_WRITE(planner.max_jerk);
|
||||
dummy = 0.02f;
|
||||
EEPROM_WRITE(dummy);
|
||||
#endif
|
||||
|
||||
_FIELD_TEST(home_offset);
|
||||
|
||||
@@ -468,7 +481,7 @@ void MarlinSettings::postprocess() {
|
||||
EEPROM_WRITE(mesh_num_y);
|
||||
EEPROM_WRITE(mbl.z_values);
|
||||
#else // For disabled MBL write a default mesh
|
||||
dummy = 0.0f;
|
||||
dummy = 0;
|
||||
const uint8_t mesh_num_x = 3, mesh_num_y = 3;
|
||||
EEPROM_WRITE(dummy); // z_offset
|
||||
EEPROM_WRITE(mesh_num_x);
|
||||
@@ -490,7 +503,7 @@ void MarlinSettings::postprocess() {
|
||||
#if ABL_PLANAR
|
||||
EEPROM_WRITE(planner.bed_level_matrix);
|
||||
#else
|
||||
dummy = 0.0;
|
||||
dummy = 0;
|
||||
for (uint8_t q = 9; q--;) EEPROM_WRITE(dummy);
|
||||
#endif
|
||||
|
||||
@@ -514,7 +527,7 @@ void MarlinSettings::postprocess() {
|
||||
// For disabled Bilinear Grid write an empty 3x3 grid
|
||||
const uint8_t grid_max_x = 3, grid_max_y = 3;
|
||||
const int bilinear_start[2] = { 0 }, bilinear_grid_spacing[2] = { 0 };
|
||||
dummy = 0.0f;
|
||||
dummy = 0;
|
||||
EEPROM_WRITE(grid_max_x);
|
||||
EEPROM_WRITE(grid_max_y);
|
||||
EEPROM_WRITE(bilinear_grid_spacing);
|
||||
@@ -552,7 +565,7 @@ void MarlinSettings::postprocess() {
|
||||
_FIELD_TEST(x_endstop_adj);
|
||||
|
||||
// Write dual endstops in X, Y, Z order. Unused = 0.0
|
||||
dummy = 0.0f;
|
||||
dummy = 0;
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
EEPROM_WRITE(endstops.x_endstop_adj); // 1 float
|
||||
#else
|
||||
@@ -604,7 +617,7 @@ void MarlinSettings::postprocess() {
|
||||
{
|
||||
dummy = DUMMY_PID_VALUE; // When read, will not change the existing value
|
||||
EEPROM_WRITE(dummy); // Kp
|
||||
dummy = 0.0f;
|
||||
dummy = 0;
|
||||
for (uint8_t q = 3; q--;) EEPROM_WRITE(dummy); // Ki, Kd, Kc
|
||||
}
|
||||
|
||||
@@ -850,7 +863,7 @@ void MarlinSettings::postprocess() {
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
EEPROM_WRITE(planner.extruder_advance_K);
|
||||
#else
|
||||
dummy = 0.0f;
|
||||
dummy = 0;
|
||||
EEPROM_WRITE(dummy);
|
||||
#endif
|
||||
|
||||
@@ -872,7 +885,7 @@ void MarlinSettings::postprocess() {
|
||||
#if ENABLED(CNC_COORDINATE_SYSTEMS)
|
||||
EEPROM_WRITE(coordinate_system); // 27 floats
|
||||
#else
|
||||
dummy = 0.0f;
|
||||
dummy = 0;
|
||||
for (uint8_t q = MAX_COORDINATE_SYSTEMS * XYZ; q--;) EEPROM_WRITE(dummy);
|
||||
#endif
|
||||
|
||||
@@ -887,7 +900,7 @@ void MarlinSettings::postprocess() {
|
||||
EEPROM_WRITE(planner.xz_skew_factor);
|
||||
EEPROM_WRITE(planner.yz_skew_factor);
|
||||
#else
|
||||
dummy = 0.0f;
|
||||
dummy = 0;
|
||||
for (uint8_t q = 3; q--;) EEPROM_WRITE(dummy);
|
||||
#endif
|
||||
|
||||
@@ -907,7 +920,7 @@ void MarlinSettings::postprocess() {
|
||||
EEPROM_WRITE(dummy);
|
||||
}
|
||||
#else
|
||||
dummy = 0.0f;
|
||||
dummy = 0;
|
||||
for (uint8_t q = MAX_EXTRUDERS * 2; q--;) EEPROM_WRITE(dummy);
|
||||
#endif
|
||||
|
||||
@@ -994,17 +1007,20 @@ void MarlinSettings::postprocess() {
|
||||
|
||||
// Get only the number of E stepper parameters previously stored
|
||||
// Any steppers added later are set to their defaults
|
||||
const float def1[] = DEFAULT_AXIS_STEPS_PER_UNIT, def2[] = DEFAULT_MAX_FEEDRATE;
|
||||
const uint32_t def3[] = DEFAULT_MAX_ACCELERATION;
|
||||
float tmp1[XYZ + esteppers], tmp2[XYZ + esteppers];
|
||||
uint32_t tmp3[XYZ + esteppers];
|
||||
EEPROM_READ(tmp1);
|
||||
EEPROM_READ(tmp2);
|
||||
EEPROM_READ(tmp3);
|
||||
const uint32_t def1[] = DEFAULT_MAX_ACCELERATION;
|
||||
const float def2[] = DEFAULT_AXIS_STEPS_PER_UNIT, def3[] = DEFAULT_MAX_FEEDRATE;
|
||||
|
||||
uint32_t tmp1[XYZ + esteppers];
|
||||
EEPROM_READ(tmp1); // max_acceleration_mm_per_s2
|
||||
EEPROM_READ(planner.min_segment_time_us);
|
||||
|
||||
float tmp2[XYZ + esteppers], tmp3[XYZ + esteppers];
|
||||
EEPROM_READ(tmp2); // axis_steps_per_mm
|
||||
EEPROM_READ(tmp3); // max_feedrate_mm_s
|
||||
if (!validating) LOOP_XYZE_N(i) {
|
||||
planner.axis_steps_per_mm[i] = i < XYZ + esteppers ? tmp1[i] : def1[i < COUNT(def1) ? i : COUNT(def1) - 1];
|
||||
planner.max_feedrate_mm_s[i] = i < XYZ + esteppers ? tmp2[i] : def2[i < COUNT(def2) ? i : COUNT(def2) - 1];
|
||||
planner.max_acceleration_mm_per_s2[i] = i < XYZ + esteppers ? tmp3[i] : def3[i < COUNT(def3) ? i : COUNT(def3) - 1];
|
||||
planner.max_acceleration_mm_per_s2[i] = i < XYZ + esteppers ? tmp1[i] : def1[i < COUNT(def1) ? i : COUNT(def1) - 1];
|
||||
planner.axis_steps_per_mm[i] = i < XYZ + esteppers ? tmp2[i] : def2[i < COUNT(def2) ? i : COUNT(def2) - 1];
|
||||
planner.max_feedrate_mm_s[i] = i < XYZ + esteppers ? tmp3[i] : def3[i < COUNT(def3) ? i : COUNT(def3) - 1];
|
||||
}
|
||||
|
||||
EEPROM_READ(planner.acceleration);
|
||||
@@ -1012,8 +1028,14 @@ void MarlinSettings::postprocess() {
|
||||
EEPROM_READ(planner.travel_acceleration);
|
||||
EEPROM_READ(planner.min_feedrate_mm_s);
|
||||
EEPROM_READ(planner.min_travel_feedrate_mm_s);
|
||||
EEPROM_READ(planner.min_segment_time_us);
|
||||
EEPROM_READ(planner.max_jerk);
|
||||
|
||||
#if ENABLED(JUNCTION_DEVIATION)
|
||||
for (uint8_t q = 4; q--;) EEPROM_READ(dummy);
|
||||
EEPROM_READ(planner.junction_deviation_mm);
|
||||
#else
|
||||
EEPROM_READ(planner.max_jerk);
|
||||
EEPROM_READ(dummy);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Home Offset (M206)
|
||||
@@ -1596,7 +1618,7 @@ void MarlinSettings::postprocess() {
|
||||
}
|
||||
#endif
|
||||
|
||||
int16_t MarlinSettings::meshes_start_index() {
|
||||
uint16_t MarlinSettings::meshes_start_index() {
|
||||
return (datasize() + EEPROM_OFFSET + 32) & 0xFFF8; // Pad the end of configuration data so it can float up
|
||||
// or down a little bit without disrupting the mesh data
|
||||
}
|
||||
@@ -1699,16 +1721,21 @@ void MarlinSettings::reset() {
|
||||
planner.max_acceleration_mm_per_s2[i] = pgm_read_dword_near(&tmp3[i < COUNT(tmp3) ? i : COUNT(tmp3) - 1]);
|
||||
}
|
||||
|
||||
planner.min_segment_time_us = DEFAULT_MINSEGMENTTIME;
|
||||
planner.acceleration = DEFAULT_ACCELERATION;
|
||||
planner.retract_acceleration = DEFAULT_RETRACT_ACCELERATION;
|
||||
planner.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION;
|
||||
planner.min_feedrate_mm_s = DEFAULT_MINIMUMFEEDRATE;
|
||||
planner.min_travel_feedrate_mm_s = DEFAULT_MINTRAVELFEEDRATE;
|
||||
planner.min_segment_time_us = DEFAULT_MINSEGMENTTIME;
|
||||
planner.max_jerk[X_AXIS] = DEFAULT_XJERK;
|
||||
planner.max_jerk[Y_AXIS] = DEFAULT_YJERK;
|
||||
planner.max_jerk[Z_AXIS] = DEFAULT_ZJERK;
|
||||
planner.max_jerk[E_AXIS] = DEFAULT_EJERK;
|
||||
|
||||
#if ENABLED(JUNCTION_DEVIATION)
|
||||
planner.junction_deviation_mm = float(JUNCTION_DEVIATION_MM);
|
||||
#else
|
||||
planner.max_jerk[X_AXIS] = DEFAULT_XJERK;
|
||||
planner.max_jerk[Y_AXIS] = DEFAULT_YJERK;
|
||||
planner.max_jerk[Z_AXIS] = DEFAULT_ZJERK;
|
||||
planner.max_jerk[E_AXIS] = DEFAULT_EJERK;
|
||||
#endif
|
||||
|
||||
#if HAS_HOME_OFFSET
|
||||
ZERO(home_offset);
|
||||
@@ -1804,7 +1831,7 @@ void MarlinSettings::reset() {
|
||||
HOTEND_LOOP()
|
||||
#endif
|
||||
{
|
||||
PID_PARAM(Kp, e) = DEFAULT_Kp;
|
||||
PID_PARAM(Kp, e) = float(DEFAULT_Kp);
|
||||
PID_PARAM(Ki, e) = scalePID_i(DEFAULT_Ki);
|
||||
PID_PARAM(Kd, e) = scalePID_d(DEFAULT_Kd);
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
@@ -1873,7 +1900,7 @@ void MarlinSettings::reset() {
|
||||
#endif
|
||||
|
||||
#if ENABLED(ADVANCED_PAUSE_FEATURE)
|
||||
for (uint8_t e = 0; e < E_STEPPERS; e++) {
|
||||
for (uint8_t e = 0; e < EXTRUDERS; e++) {
|
||||
filament_change_unload_length[e] = FILAMENT_CHANGE_UNLOAD_LENGTH;
|
||||
filament_change_load_length[e] = FILAMENT_CHANGE_FAST_LOAD_LENGTH;
|
||||
}
|
||||
@@ -1892,12 +1919,12 @@ void MarlinSettings::reset() {
|
||||
#define CONFIG_ECHO_START do{ if (!forReplay) SERIAL_ECHO_START(); }while(0)
|
||||
|
||||
#if HAS_TRINAMIC
|
||||
void say_M906() { SERIAL_ECHOPGM(" M906 "); }
|
||||
void say_M906() { SERIAL_ECHOPGM(" M906"); }
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
void say_M913() { SERIAL_ECHOPGM(" M913 "); }
|
||||
void say_M913() { SERIAL_ECHOPGM(" M913"); }
|
||||
#endif
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
void say_M914() { SERIAL_ECHOPGM(" M914 "); }
|
||||
void say_M914() { SERIAL_ECHOPGM(" M914"); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -2077,16 +2104,32 @@ void MarlinSettings::reset() {
|
||||
|
||||
if (!forReplay) {
|
||||
CONFIG_ECHO_START;
|
||||
SERIAL_ECHOLNPGM("Advanced: S<min_feedrate> T<min_travel_feedrate> B<min_segment_time_us> X<max_xy_jerk> Z<max_z_jerk> E<max_e_jerk>");
|
||||
SERIAL_ECHOPGM("Advanced: B<min_segment_time_us> S<min_feedrate> T<min_travel_feedrate>");
|
||||
#if ENABLED(JUNCTION_DEVIATION)
|
||||
SERIAL_ECHOPGM(" J<junc_dev>");
|
||||
#else
|
||||
SERIAL_ECHOPGM(" X<max_x_jerk> Y<max_y_jerk> Z<max_z_jerk>");
|
||||
#endif
|
||||
#if DISABLED(JUNCTION_DEVIATION) || ENABLED(LIN_ADVANCE)
|
||||
SERIAL_ECHOPGM(" E<max_e_jerk>");
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
}
|
||||
CONFIG_ECHO_START;
|
||||
SERIAL_ECHOPAIR(" M205 S", LINEAR_UNIT(planner.min_feedrate_mm_s));
|
||||
SERIAL_ECHOPAIR(" M205 B", LINEAR_UNIT(planner.min_segment_time_us));
|
||||
SERIAL_ECHOPAIR(" S", LINEAR_UNIT(planner.min_feedrate_mm_s));
|
||||
SERIAL_ECHOPAIR(" T", LINEAR_UNIT(planner.min_travel_feedrate_mm_s));
|
||||
SERIAL_ECHOPAIR(" B", planner.min_segment_time_us);
|
||||
SERIAL_ECHOPAIR(" X", LINEAR_UNIT(planner.max_jerk[X_AXIS]));
|
||||
SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(planner.max_jerk[Y_AXIS]));
|
||||
SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(planner.max_jerk[Z_AXIS]));
|
||||
SERIAL_ECHOLNPAIR(" E", LINEAR_UNIT(planner.max_jerk[E_AXIS]));
|
||||
|
||||
#if ENABLED(JUNCTION_DEVIATION)
|
||||
SERIAL_ECHOPAIR(" J", LINEAR_UNIT(planner.junction_deviation_mm));
|
||||
#else
|
||||
SERIAL_ECHOPAIR(" X", LINEAR_UNIT(planner.max_jerk[X_AXIS]));
|
||||
SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(planner.max_jerk[Y_AXIS]));
|
||||
SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(planner.max_jerk[Z_AXIS]));
|
||||
SERIAL_ECHOPAIR(" E", LINEAR_UNIT(planner.max_jerk[E_AXIS]));
|
||||
#endif
|
||||
|
||||
SERIAL_EOL();
|
||||
|
||||
#if HAS_M206_COMMAND
|
||||
if (!forReplay) {
|
||||
@@ -2161,7 +2204,7 @@ void MarlinSettings::reset() {
|
||||
SERIAL_ECHOPAIR(" G29 S3 X", (int)px + 1);
|
||||
SERIAL_ECHOPAIR(" Y", (int)py + 1);
|
||||
SERIAL_ECHOPGM(" Z");
|
||||
SERIAL_PROTOCOL_F(LINEAR_UNIT(mbl.z_values[px][py]), 5);
|
||||
SERIAL_ECHO_F(LINEAR_UNIT(mbl.z_values[px][py]), 5);
|
||||
SERIAL_EOL();
|
||||
}
|
||||
}
|
||||
@@ -2185,10 +2228,10 @@ void MarlinSettings::reset() {
|
||||
for (uint8_t py = 0; py < GRID_MAX_POINTS_Y; py++) {
|
||||
for (uint8_t px = 0; px < GRID_MAX_POINTS_X; px++) {
|
||||
CONFIG_ECHO_START;
|
||||
SERIAL_ECHOPAIR(" G29 W I", (int)px + 1);
|
||||
SERIAL_ECHOPAIR(" J", (int)py + 1);
|
||||
SERIAL_ECHOPAIR(" G29 W I", (int)px);
|
||||
SERIAL_ECHOPAIR(" J", (int)py);
|
||||
SERIAL_ECHOPGM(" Z");
|
||||
SERIAL_PROTOCOL_F(LINEAR_UNIT(z_values[px][py]), 5);
|
||||
SERIAL_ECHO_F(LINEAR_UNIT(z_values[px][py]), 5);
|
||||
SERIAL_EOL();
|
||||
}
|
||||
}
|
||||
@@ -2392,49 +2435,56 @@ void MarlinSettings::reset() {
|
||||
SERIAL_ECHOLNPGM("Stepper driver current:");
|
||||
}
|
||||
CONFIG_ECHO_START;
|
||||
#if X_IS_TRINAMIC
|
||||
#if X_IS_TRINAMIC || Y_IS_TRINAMIC || Z_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("X", stepperX.getCurrent());
|
||||
#endif
|
||||
#if X2_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("I1 X", stepperX2.getCurrent());
|
||||
#if X_IS_TRINAMIC
|
||||
SERIAL_ECHOPAIR(" X", stepperX.getCurrent());
|
||||
#endif
|
||||
#if Y_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("Y", stepperY.getCurrent());
|
||||
#endif
|
||||
#if Y2_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("I1 Y", stepperY2.getCurrent());
|
||||
SERIAL_ECHOPAIR(" Y", stepperY.getCurrent());
|
||||
#endif
|
||||
#if Z_IS_TRINAMIC
|
||||
SERIAL_ECHOPAIR(" Z", stepperZ.getCurrent());
|
||||
#endif
|
||||
#if X_IS_TRINAMIC || Y_IS_TRINAMIC || Z_IS_TRINAMIC
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
#if X2_IS_TRINAMIC || Y2_IS_TRINAMIC || Z2_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("Z", stepperZ.getCurrent());
|
||||
SERIAL_ECHOPGM(" I1");
|
||||
#endif
|
||||
#if X2_IS_TRINAMIC
|
||||
SERIAL_ECHOPAIR(" X", stepperX2.getCurrent());
|
||||
#endif
|
||||
#if Y2_IS_TRINAMIC
|
||||
SERIAL_ECHOPAIR(" Y", stepperY2.getCurrent());
|
||||
#endif
|
||||
#if Z2_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("I1 Z", stepperZ2.getCurrent());
|
||||
SERIAL_ECHOPAIR(" Z", stepperZ2.getCurrent());
|
||||
#endif
|
||||
#if X2_IS_TRINAMIC || Y2_IS_TRINAMIC || Z2_IS_TRINAMIC
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
#if E0_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("T0 E", stepperE0.getCurrent());
|
||||
SERIAL_ECHOLNPAIR(" T0 E", stepperE0.getCurrent());
|
||||
#endif
|
||||
#if E_STEPPERS > 1 && E1_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("T1 E", stepperE1.getCurrent());
|
||||
SERIAL_ECHOLNPAIR(" T1 E", stepperE1.getCurrent());
|
||||
#endif
|
||||
#if E_STEPPERS > 2 && E2_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("T2 E", stepperE2.getCurrent());
|
||||
SERIAL_ECHOLNPAIR(" T2 E", stepperE2.getCurrent());
|
||||
#endif
|
||||
#if E_STEPPERS > 3 && E3_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("T3 E", stepperE3.getCurrent());
|
||||
SERIAL_ECHOLNPAIR(" T3 E", stepperE3.getCurrent());
|
||||
#endif
|
||||
#if E_STEPPERS > 4 && E4_IS_TRINAMIC
|
||||
say_M906();
|
||||
SERIAL_ECHOLNPAIR("T4 E", stepperE4.getCurrent());
|
||||
SERIAL_ECHOLNPAIR(" T4 E", stepperE4.getCurrent());
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
|
||||
@@ -2447,49 +2497,56 @@ void MarlinSettings::reset() {
|
||||
SERIAL_ECHOLNPGM("Hybrid Threshold:");
|
||||
}
|
||||
CONFIG_ECHO_START;
|
||||
#if X_IS_TRINAMIC
|
||||
#if X_IS_TRINAMIC || Y_IS_TRINAMIC || Z_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("X", TMC_GET_PWMTHRS(X, X));
|
||||
#endif
|
||||
#if X2_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("I1 X", TMC_GET_PWMTHRS(X, X2));
|
||||
#if X_IS_TRINAMIC
|
||||
SERIAL_ECHOPAIR(" X", TMC_GET_PWMTHRS(X, X));
|
||||
#endif
|
||||
#if Y_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("Y", TMC_GET_PWMTHRS(Y, Y));
|
||||
#endif
|
||||
#if Y2_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("I1 Y", TMC_GET_PWMTHRS(Y, Y2));
|
||||
SERIAL_ECHOPAIR(" Y", TMC_GET_PWMTHRS(Y, Y));
|
||||
#endif
|
||||
#if Z_IS_TRINAMIC
|
||||
SERIAL_ECHOPAIR(" Z", TMC_GET_PWMTHRS(Z, Z));
|
||||
#endif
|
||||
#if X_IS_TRINAMIC || Y_IS_TRINAMIC || Z_IS_TRINAMIC
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
#if X2_IS_TRINAMIC || Y2_IS_TRINAMIC || Z2_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("Z", TMC_GET_PWMTHRS(Z, Z));
|
||||
SERIAL_ECHOPGM(" I1");
|
||||
#endif
|
||||
#if X2_IS_TRINAMIC
|
||||
SERIAL_ECHOPAIR(" X", TMC_GET_PWMTHRS(X, X2));
|
||||
#endif
|
||||
#if Y2_IS_TRINAMIC
|
||||
SERIAL_ECHOPAIR(" Y", TMC_GET_PWMTHRS(Y, Y2));
|
||||
#endif
|
||||
#if Z2_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("I1 Z", TMC_GET_PWMTHRS(Z, Z2));
|
||||
SERIAL_ECHOPAIR(" Z", TMC_GET_PWMTHRS(Z, Z2));
|
||||
#endif
|
||||
#if X2_IS_TRINAMIC || Y2_IS_TRINAMIC || Z2_IS_TRINAMIC
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
#if E0_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("T0 E", TMC_GET_PWMTHRS(E, E0));
|
||||
SERIAL_ECHOLNPAIR(" T0 E", TMC_GET_PWMTHRS(E, E0));
|
||||
#endif
|
||||
#if E_STEPPERS > 1 && E1_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("T1 E", TMC_GET_PWMTHRS(E, E1));
|
||||
SERIAL_ECHOLNPAIR(" T1 E", TMC_GET_PWMTHRS(E, E1));
|
||||
#endif
|
||||
#if E_STEPPERS > 2 && E2_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("T2 E", TMC_GET_PWMTHRS(E, E2));
|
||||
SERIAL_ECHOLNPAIR(" T2 E", TMC_GET_PWMTHRS(E, E2));
|
||||
#endif
|
||||
#if E_STEPPERS > 3 && E3_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("T3 E", TMC_GET_PWMTHRS(E, E3));
|
||||
SERIAL_ECHOLNPAIR(" T3 E", TMC_GET_PWMTHRS(E, E3));
|
||||
#endif
|
||||
#if E_STEPPERS > 4 && E4_IS_TRINAMIC
|
||||
say_M913();
|
||||
SERIAL_ECHOLNPAIR("T4 E", TMC_GET_PWMTHRS(E, E4));
|
||||
SERIAL_ECHOLNPAIR(" T4 E", TMC_GET_PWMTHRS(E, E4));
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
#endif // HYBRID_THRESHOLD
|
||||
@@ -2503,38 +2560,42 @@ void MarlinSettings::reset() {
|
||||
SERIAL_ECHOLNPGM("Sensorless homing threshold:");
|
||||
}
|
||||
CONFIG_ECHO_START;
|
||||
#ifdef X_HOMING_SENSITIVITY
|
||||
#if ENABLED(X_IS_TMC2130) || ENABLED(IS_TRAMS)
|
||||
say_M914();
|
||||
SERIAL_ECHOLNPAIR("X", stepperX.sgt());
|
||||
#define HAS_X_SENSORLESS (defined(X_HOMING_SENSITIVITY) && (ENABLED(X_IS_TMC2130) || ENABLED(IS_TRAMS)))
|
||||
#define HAS_Y_SENSORLESS (defined(Y_HOMING_SENSITIVITY) && (ENABLED(Y_IS_TMC2130) || ENABLED(IS_TRAMS)))
|
||||
#define HAS_Z_SENSORLESS (defined(Z_HOMING_SENSITIVITY) && (ENABLED(Z_IS_TMC2130) || ENABLED(IS_TRAMS)))
|
||||
#if HAS_X_SENSORLESS || HAS_Y_SENSORLESS || HAS_Z_SENSORLESS
|
||||
say_M914();
|
||||
#if HAS_X_SENSORLESS
|
||||
SERIAL_ECHOPAIR(" X", stepperX.sgt());
|
||||
#endif
|
||||
#if ENABLED(X2_IS_TMC2130)
|
||||
say_M914();
|
||||
SERIAL_ECHOLNPAIR("I1 X", stepperX2.sgt());
|
||||
#if HAS_Y_SENSORLESS
|
||||
SERIAL_ECHOPAIR(" Y", stepperY.sgt());
|
||||
#endif
|
||||
#if HAS_Z_SENSORLESS
|
||||
SERIAL_ECHOPAIR(" Z", stepperZ.sgt());
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
#ifdef Y_HOMING_SENSITIVITY
|
||||
#if ENABLED(Y_IS_TMC2130) || ENABLED(IS_TRAMS)
|
||||
say_M914();
|
||||
SERIAL_ECHOLNPAIR("Y", stepperY.sgt());
|
||||
|
||||
#define HAS_X2_SENSORLESS (defined(X_HOMING_SENSITIVITY) && ENABLED(X2_IS_TMC2130))
|
||||
#define HAS_Y2_SENSORLESS (defined(Y_HOMING_SENSITIVITY) && ENABLED(Y2_IS_TMC2130))
|
||||
#define HAS_Z2_SENSORLESS (defined(Z_HOMING_SENSITIVITY) && ENABLED(Z2_IS_TMC2130))
|
||||
#if HAS_X2_SENSORLESS || HAS_Y2_SENSORLESS || HAS_Z2_SENSORLESS
|
||||
say_M914();
|
||||
SERIAL_ECHOPGM(" I1");
|
||||
#if HAS_X2_SENSORLESS
|
||||
SERIAL_ECHOPAIR(" X", stepperX2.sgt());
|
||||
#endif
|
||||
#if ENABLED(Y2_IS_TMC2130)
|
||||
say_M914();
|
||||
SERIAL_ECHOLNPAIR("I1 Y", stepperY2.sgt());
|
||||
#if HAS_Y2_SENSORLESS
|
||||
SERIAL_ECHOPAIR(" Y", stepperY2.sgt());
|
||||
#endif
|
||||
#if HAS_Z2_SENSORLESS
|
||||
SERIAL_ECHOPAIR(" Z", stepperZ2.sgt());
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
#ifdef Z_HOMING_SENSITIVITY
|
||||
#if ENABLED(Z_IS_TMC2130) || ENABLED(IS_TRAMS)
|
||||
say_M914();
|
||||
SERIAL_ECHOLNPAIR("Z", stepperZ.sgt());
|
||||
#endif
|
||||
#if ENABLED(Z2_IS_TMC2130)
|
||||
say_M914();
|
||||
SERIAL_ECHOLNPAIR("I1 Z", stepperZ2.sgt());
|
||||
#endif
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
|
||||
#endif // SENSORLESS_HOMING
|
||||
|
||||
#endif // HAS_TRINAMIC
|
||||
|
||||
|
||||
@@ -53,8 +53,8 @@ class MarlinSettings {
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
|
||||
// That can store is enabled
|
||||
static int16_t meshes_start_index();
|
||||
FORCE_INLINE static int16_t meshes_end_index() { return meshes_end; }
|
||||
static uint16_t meshes_start_index();
|
||||
FORCE_INLINE static uint16_t meshes_end_index() { return meshes_end; }
|
||||
static uint16_t calc_num_meshes();
|
||||
static int mesh_slot_offset(const int8_t slot);
|
||||
static void store_mesh(const int8_t slot);
|
||||
@@ -84,8 +84,8 @@ class MarlinSettings {
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
|
||||
// That can store is enabled
|
||||
static constexpr int16_t meshes_end = E2END - 128; // 128 is a placeholder for the size of the MAT; the MAT will always
|
||||
// live at the very end of the eeprom
|
||||
static constexpr uint16_t meshes_end = E2END - 128; // 128 is a placeholder for the size of the MAT; the MAT will always
|
||||
// live at the very end of the eeprom
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ static void i2c_send(const uint8_t channel, const byte v) {
|
||||
|
||||
// This is for the MCP4018 I2C based digipot
|
||||
void digipot_i2c_set_current(uint8_t channel, float current) {
|
||||
i2c_send(channel, current_to_wiper(MIN(MAX(current, 0.0f), float(DIGIPOT_A4988_MAX_CURRENT))));
|
||||
i2c_send(channel, current_to_wiper(MIN(MAX(current, 0), float(DIGIPOT_A4988_MAX_CURRENT))));
|
||||
}
|
||||
|
||||
void digipot_i2c_init() {
|
||||
|
||||
@@ -50,7 +50,7 @@ static void i2c_send(const byte addr, const byte a, const byte b) {
|
||||
|
||||
// This is for the MCP4451 I2C based digipot
|
||||
void digipot_i2c_set_current(uint8_t channel, float current) {
|
||||
current = MIN((float) MAX(current, 0.0f), DIGIPOT_I2C_MAX_CURRENT);
|
||||
current = MIN((float) MAX(current, 0), DIGIPOT_I2C_MAX_CURRENT);
|
||||
// these addresses are specific to Azteeg X3 Pro, can be set to others,
|
||||
// In this case first digipot is at address A0=0, A1= 0, second one is at A0=0, A1= 1
|
||||
byte addr = 0x2C; // channel 0-3
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "macros.h"
|
||||
|
||||
// One ISR for all EXT-Interrupts
|
||||
void endstop_ISR(void) { endstops.check_possible_change(); }
|
||||
void endstop_ISR(void) { endstops.update(); }
|
||||
|
||||
/**
|
||||
* Patch for pins_arduino.h (...\Arduino\hardware\arduino\avr\variants\mega\pins_arduino.h)
|
||||
|
||||
+131
-148
@@ -35,12 +35,6 @@
|
||||
#include "endstop_interrupts.h"
|
||||
#endif
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
#define ENDSTOPS_ENABLED (enabled || z_probe_enabled)
|
||||
#else
|
||||
#define ENDSTOPS_ENABLED enabled
|
||||
#endif
|
||||
|
||||
Endstops endstops;
|
||||
|
||||
// public:
|
||||
@@ -49,9 +43,9 @@ bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.l
|
||||
volatile uint8_t Endstops::hit_state;
|
||||
|
||||
Endstops::esbits_t Endstops::live_state = 0;
|
||||
|
||||
#if ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
Endstops::esbits_t Endstops::old_live_state,
|
||||
Endstops::validated_live_state;
|
||||
Endstops::esbits_t Endstops::validated_live_state;
|
||||
uint8_t Endstops::endstop_poll_count;
|
||||
#endif
|
||||
|
||||
@@ -195,9 +189,6 @@ void Endstops::init() {
|
||||
|
||||
} // Endstops::init
|
||||
|
||||
// Called from ISR. A change was detected. Find out what happened!
|
||||
void Endstops::check_possible_change() { if (ENDSTOPS_ENABLED) update(); }
|
||||
|
||||
// Called from ISR: Poll endstop state if required
|
||||
void Endstops::poll() {
|
||||
|
||||
@@ -205,8 +196,10 @@ void Endstops::poll() {
|
||||
run_monitor(); // report changes in endstop status
|
||||
#endif
|
||||
|
||||
#if DISABLED(ENDSTOP_INTERRUPTS_FEATURE) || ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
if (ENDSTOPS_ENABLED) update();
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE) && ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
if (endstop_poll_count) update();
|
||||
#elif DISABLED(ENDSTOP_INTERRUPTS_FEATURE) || ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
update();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -214,7 +207,7 @@ void Endstops::enable_globally(const bool onoff) {
|
||||
enabled_globally = enabled = onoff;
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
if (onoff) update(); // If enabling, update state now
|
||||
update();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -223,7 +216,7 @@ void Endstops::enable(const bool onoff) {
|
||||
enabled = onoff;
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
if (onoff) update(); // If enabling, update state now
|
||||
update();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -232,17 +225,23 @@ void Endstops::not_homing() {
|
||||
enabled = enabled_globally;
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
if (enabled) update(); // If enabling, update state now
|
||||
update();
|
||||
#endif
|
||||
}
|
||||
|
||||
// If the last move failed to trigger an endstop, call kill
|
||||
void Endstops::validate_homing_move() {
|
||||
if (!trigger_state()) kill(PSTR(MSG_ERR_HOMING_FAILED));
|
||||
hit_on_purpose();
|
||||
}
|
||||
|
||||
// Enable / disable endstop z-probe checking
|
||||
#if HAS_BED_PROBE
|
||||
void Endstops::enable_z_probe(bool onoff) {
|
||||
void Endstops::enable_z_probe(const bool onoff) {
|
||||
z_probe_enabled = onoff;
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
if (enabled) update(); // If enabling, update state now
|
||||
update();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -369,10 +368,12 @@ void Endstops::M119() {
|
||||
// Check endstops - Could be called from ISR!
|
||||
void Endstops::update() {
|
||||
|
||||
// UPDATE_ENDSTOP_BIT: set the current endstop bits for an endstop to its status
|
||||
#if DISABLED(ENDSTOP_NOISE_FILTER)
|
||||
if (!abort_enabled()) return;
|
||||
#endif
|
||||
|
||||
#define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
|
||||
// COPY_BIT: copy the value of SRC_BIT to DST_BIT in DST
|
||||
#define COPY_BIT(DST, SRC_BIT, DST_BIT) SET_BIT_TO(DST, DST_BIT, TEST(DST, SRC_BIT))
|
||||
#define COPY_LIVE_STATE(SRC_BIT, DST_BIT) SET_BIT_TO(live_state, DST_BIT, TEST(live_state, SRC_BIT))
|
||||
|
||||
#if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
|
||||
// If G38 command is active check Z_MIN_PROBE for ALL movement
|
||||
@@ -407,162 +408,142 @@ void Endstops::update() {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check and update endstops according to conditions
|
||||
* Check and update endstops
|
||||
*/
|
||||
if (stepper.axis_is_moving(X_AXIS)) {
|
||||
if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
|
||||
#if HAS_X_MIN
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(X, MIN);
|
||||
#if HAS_X2_MIN
|
||||
UPDATE_ENDSTOP_BIT(X2, MIN);
|
||||
#else
|
||||
COPY_BIT(live_state, X_MIN, X2_MIN);
|
||||
#endif
|
||||
#else
|
||||
if (X_MIN_TEST) UPDATE_ENDSTOP_BIT(X, MIN);
|
||||
#endif
|
||||
#if HAS_X_MIN
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(X, MIN);
|
||||
#if HAS_X2_MIN
|
||||
UPDATE_ENDSTOP_BIT(X2, MIN);
|
||||
#else
|
||||
COPY_LIVE_STATE(X_MIN, X2_MIN);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_X_MAX
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(X, MAX);
|
||||
#if HAS_X2_MAX
|
||||
UPDATE_ENDSTOP_BIT(X2, MAX);
|
||||
#else
|
||||
COPY_BIT(live_state, X_MAX, X2_MAX);
|
||||
#endif
|
||||
#else
|
||||
if (X_MAX_TEST) UPDATE_ENDSTOP_BIT(X, MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(X, MIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (stepper.axis_is_moving(Y_AXIS)) {
|
||||
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
|
||||
#if HAS_Y_MIN
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Y, MIN);
|
||||
#if HAS_Y2_MIN
|
||||
UPDATE_ENDSTOP_BIT(Y2, MIN);
|
||||
#else
|
||||
COPY_BIT(live_state, Y_MIN, Y2_MIN);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(Y, MIN);
|
||||
#endif
|
||||
#if HAS_X_MAX
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(X, MAX);
|
||||
#if HAS_X2_MAX
|
||||
UPDATE_ENDSTOP_BIT(X2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(X_MAX, X2_MAX);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_Y_MAX
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Y, MAX);
|
||||
#if HAS_Y2_MAX
|
||||
UPDATE_ENDSTOP_BIT(Y2, MAX);
|
||||
#else
|
||||
COPY_BIT(live_state, Y_MAX, Y2_MAX);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(Y, MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(X, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (stepper.axis_is_moving(Z_AXIS)) {
|
||||
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
|
||||
#if HAS_Z_MIN
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#if HAS_Z2_MIN
|
||||
UPDATE_ENDSTOP_BIT(Z2, MIN);
|
||||
#else
|
||||
COPY_BIT(live_state, Z_MIN, Z2_MIN);
|
||||
#endif
|
||||
#else
|
||||
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
if (z_probe_enabled) UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_Y_MIN
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Y, MIN);
|
||||
#if HAS_Y2_MIN
|
||||
UPDATE_ENDSTOP_BIT(Y2, MIN);
|
||||
#else
|
||||
COPY_LIVE_STATE(Y_MIN, Y2_MIN);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(Y, MIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// When closing the gap check the enabled probe
|
||||
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
|
||||
if (z_probe_enabled) UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
|
||||
#if HAS_Y_MAX
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Y, MAX);
|
||||
#if HAS_Y2_MAX
|
||||
UPDATE_ENDSTOP_BIT(Y2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(Y_MAX, Y2_MAX);
|
||||
#endif
|
||||
}
|
||||
else { // Z +direction. Gantry up, bed down.
|
||||
#if HAS_Z_MAX
|
||||
// Check both Z dual endstops
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Z, MAX);
|
||||
#if HAS_Z2_MAX
|
||||
UPDATE_ENDSTOP_BIT(Z2, MAX);
|
||||
#else
|
||||
COPY_BIT(live_state, Z_MAX, Z2_MAX);
|
||||
#endif
|
||||
// If this pin is not hijacked for the bed probe
|
||||
// then it belongs to the Z endstop
|
||||
#elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
|
||||
UPDATE_ENDSTOP_BIT(Z, MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(Y, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_Z_MIN
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#if HAS_Z2_MIN
|
||||
UPDATE_ENDSTOP_BIT(Z2, MIN);
|
||||
#else
|
||||
COPY_LIVE_STATE(Z_MIN, Z2_MIN);
|
||||
#endif
|
||||
#elif ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#elif Z_HOME_DIR < 0
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// When closing the gap check the enabled probe
|
||||
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
|
||||
#endif
|
||||
|
||||
#if HAS_Z_MAX
|
||||
// Check both Z dual endstops
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Z, MAX);
|
||||
#if HAS_Z2_MAX
|
||||
UPDATE_ENDSTOP_BIT(Z2, MAX);
|
||||
#else
|
||||
COPY_LIVE_STATE(Z_MAX, Z2_MAX);
|
||||
#endif
|
||||
#elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
|
||||
// If this pin isn't the bed probe it's the Z endstop
|
||||
UPDATE_ENDSTOP_BIT(Z, MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// All endstops were updated.
|
||||
#if ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
if (old_live_state != live_state) { // We detected a change. Reinit the timeout
|
||||
/**
|
||||
* Filtering out noise on endstops requires a delayed decision. Let's assume, due to noise,
|
||||
* that 50% of endstop signal samples are good and 50% are bad (assuming normal distribution
|
||||
* of random noise). Then the first sample has a 50% chance to be good or bad. The 2nd sample
|
||||
* also has a 50% chance to be good or bad. The chances of 2 samples both being bad becomes
|
||||
* 50% of 50%, or 25%. That was the previous implementation of Marlin endstop handling. It
|
||||
* reduces chances of bad readings in half, at the cost of 1 extra sample period, but chances
|
||||
* still exist. The only way to reduce them further is to increase the number of samples.
|
||||
* To reduce the chance to 1% (1/128th) requires 7 samples (adding 7ms of delay).
|
||||
*/
|
||||
/**
|
||||
* Filtering out noise on endstops requires a delayed decision. Let's assume, due to noise,
|
||||
* that 50% of endstop signal samples are good and 50% are bad (assuming normal distribution
|
||||
* of random noise). Then the first sample has a 50% chance to be good or bad. The 2nd sample
|
||||
* also has a 50% chance to be good or bad. The chances of 2 samples both being bad becomes
|
||||
* 50% of 50%, or 25%. That was the previous implementation of Marlin endstop handling. It
|
||||
* reduces chances of bad readings in half, at the cost of 1 extra sample period, but chances
|
||||
* still exist. The only way to reduce them further is to increase the number of samples.
|
||||
* To reduce the chance to 1% (1/128th) requires 7 samples (adding 7ms of delay).
|
||||
*/
|
||||
static esbits_t old_live_state;
|
||||
if (old_live_state != live_state) {
|
||||
endstop_poll_count = 7;
|
||||
old_live_state = live_state;
|
||||
}
|
||||
else if (endstop_poll_count && !--endstop_poll_count)
|
||||
validated_live_state = live_state;
|
||||
|
||||
#else
|
||||
|
||||
// Lets accept the new endstop values as valid - We assume hardware filtering of lines
|
||||
esbits_t validated_live_state = live_state;
|
||||
if (!abort_enabled()) return;
|
||||
|
||||
#endif
|
||||
|
||||
// Endstop readings are validated in validated_live_state
|
||||
|
||||
// Test the current status of an endstop
|
||||
#define TEST_ENDSTOP(ENDSTOP) (TEST(validated_live_state, ENDSTOP))
|
||||
#define TEST_ENDSTOP(ENDSTOP) (TEST(state(), ENDSTOP))
|
||||
|
||||
// Record endstop was hit
|
||||
#define _ENDSTOP_HIT(AXIS, MINMAX) SBI(hit_state, _ENDSTOP(AXIS, MINMAX))
|
||||
|
||||
// Call the endstop triggered routine for single endstops
|
||||
#define PROCESS_ENDSTOP(AXIS,MINMAX) do { \
|
||||
if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
|
||||
_ENDSTOP_HIT(AXIS, MINMAX); \
|
||||
planner.endstop_triggered(_AXIS(AXIS)); \
|
||||
} \
|
||||
}while(0)
|
||||
if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
|
||||
_ENDSTOP_HIT(AXIS, MINMAX); \
|
||||
planner.endstop_triggered(_AXIS(AXIS)); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
// Call the endstop triggered routine for single endstops
|
||||
// Call the endstop triggered routine for dual endstops
|
||||
#define PROCESS_DUAL_ENDSTOP(AXIS1, AXIS2, MINMAX) do { \
|
||||
if (TEST_ENDSTOP(_ENDSTOP(AXIS1, MINMAX)) || TEST_ENDSTOP(_ENDSTOP(AXIS2, MINMAX))) { \
|
||||
_ENDSTOP_HIT(AXIS1, MINMAX); \
|
||||
const byte dual_hit = TEST_ENDSTOP(_ENDSTOP(AXIS1, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(AXIS2, MINMAX)) << 1); \
|
||||
if (dual_hit) { \
|
||||
_ENDSTOP_HIT(AXIS1, MINMAX); \
|
||||
/* if not performing home or if both endstops were trigged during homing... */ \
|
||||
if (!stepper.homing_dual_axis || dual_hit == 0x3) \
|
||||
planner.endstop_triggered(_AXIS(AXIS1)); \
|
||||
} \
|
||||
}while(0)
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
#if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
|
||||
// If G38 command is active check Z_MIN_PROBE for ALL movement
|
||||
@@ -627,6 +608,8 @@ void Endstops::update() {
|
||||
#else
|
||||
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN);
|
||||
#elif ENABLED(Z_MIN_PROBE_ENDSTOP)
|
||||
if (!z_probe_enabled) PROCESS_ENDSTOP(Z, MIN);
|
||||
#else
|
||||
PROCESS_ENDSTOP(Z, MIN);
|
||||
#endif
|
||||
|
||||
+26
-8
@@ -69,9 +69,9 @@ class Endstops {
|
||||
private:
|
||||
static esbits_t live_state;
|
||||
static volatile uint8_t hit_state; // Use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT index
|
||||
|
||||
#if ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
static esbits_t old_live_state, // Old endstop value for debouncing and denoising
|
||||
validated_live_state; // The validated (accepted as true) endstop bits
|
||||
static esbits_t validated_live_state;
|
||||
static uint8_t endstop_poll_count; // Countdown from threshold for polling
|
||||
#endif
|
||||
|
||||
@@ -84,10 +84,15 @@ class Endstops {
|
||||
static void init();
|
||||
|
||||
/**
|
||||
* A change was detected or presumed to be in endstops pins. Find out what
|
||||
* changed, if anything. Called from ISR contexts
|
||||
* Are endstops or the probe set to abort the move?
|
||||
*/
|
||||
static void check_possible_change();
|
||||
FORCE_INLINE static bool abort_enabled() {
|
||||
return (enabled
|
||||
#if HAS_BED_PROBE
|
||||
|| z_probe_enabled
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic call to poll endstops if required. Called from temperature ISR
|
||||
@@ -95,7 +100,9 @@ class Endstops {
|
||||
static void poll();
|
||||
|
||||
/**
|
||||
* Update the endstops bits from the pins
|
||||
* Update endstops bits from the pins. Apply filtering to get a verified state.
|
||||
* If abort_enabled() and moving towards a triggered switch, abort the current move.
|
||||
* Called from ISR contexts.
|
||||
*/
|
||||
static void update();
|
||||
|
||||
@@ -107,7 +114,15 @@ class Endstops {
|
||||
/**
|
||||
* Get current endstops state
|
||||
*/
|
||||
FORCE_INLINE static esbits_t state() { return live_state; }
|
||||
FORCE_INLINE static esbits_t state() {
|
||||
return
|
||||
#if ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
validated_live_state
|
||||
#else
|
||||
live_state
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report endstop hits to serial. Called from loop().
|
||||
@@ -128,13 +143,16 @@ class Endstops {
|
||||
// Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
|
||||
static void not_homing();
|
||||
|
||||
// If the last move failed to trigger an endstop, call kill
|
||||
static void validate_homing_move();
|
||||
|
||||
// Clear endstops (i.e., they were hit intentionally) to suppress the report
|
||||
FORCE_INLINE static void hit_on_purpose() { hit_state = 0; }
|
||||
|
||||
// Enable / disable endstop z-probe checking
|
||||
#if HAS_BED_PROBE
|
||||
static volatile bool z_probe_enabled;
|
||||
static void enable_z_probe(bool onoff=true);
|
||||
static void enable_z_probe(const bool onoff=true);
|
||||
#endif
|
||||
|
||||
// Debugging of endstops
|
||||
|
||||
@@ -153,7 +153,8 @@ void FWRetract::retract(const bool retracting
|
||||
else {
|
||||
// If a hop was done and Z hasn't changed, undo the Z hop
|
||||
if (hop_amount) {
|
||||
destination[Z_AXIS] -= hop_amount; // Move back down by the total hop amount
|
||||
current_position[Z_AXIS] += hop_amount; // Restore the actual Z position
|
||||
SYNC_PLAN_POSITION_KINEMATIC(); // Unspoof the position planner
|
||||
feedrate_mm_s = planner.max_feedrate_mm_s[Z_AXIS]; // Z feedrate to max
|
||||
prepare_move_to_destination(); // Lower Z, set_current_to_destination
|
||||
hop_amount = 0.0; // Clear the hop amount
|
||||
|
||||
@@ -146,8 +146,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("UBL Postupne")
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("LED Nastaveni")
|
||||
#define MSG_LEDS_ON _UxGT("Svetla Zap")
|
||||
#define MSG_LEDS_OFF _UxGT("Svetla Vyp")
|
||||
#define MSG_LEDS _UxGT("Svetla")
|
||||
#define MSG_LED_PRESETS _UxGT("Svetla Predvolby")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Cervena")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Oranzova")
|
||||
|
||||
@@ -149,8 +149,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("UBL Postupně")
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("LED Nastavení")
|
||||
#define MSG_LEDS_ON _UxGT("Světla Zap")
|
||||
#define MSG_LEDS_OFF _UxGT("Světla Vyp")
|
||||
#define MSG_LEDS _UxGT("Světla")
|
||||
#define MSG_LED_PRESETS _UxGT("Světla Předvolby")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Červená")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Oranžová")
|
||||
|
||||
@@ -311,8 +311,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("Schrittweises UBL")
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("LED Kontrolle")
|
||||
#define MSG_LEDS_ON _UxGT("Licht an")
|
||||
#define MSG_LEDS_OFF _UxGT("Licht aus")
|
||||
#define MSG_LEDS _UxGT("Licht")
|
||||
#define MSG_LED_PRESETS _UxGT("Licht Einstellungen")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Rot")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Orange")
|
||||
|
||||
@@ -371,11 +371,8 @@
|
||||
#ifndef MSG_LED_CONTROL
|
||||
#define MSG_LED_CONTROL _UxGT("LED Control")
|
||||
#endif
|
||||
#ifndef MSG_LEDS_ON
|
||||
#define MSG_LEDS_ON _UxGT("Lights On")
|
||||
#endif
|
||||
#ifndef MSG_LEDS_OFF
|
||||
#define MSG_LEDS_OFF _UxGT("Lights Off")
|
||||
#ifndef MSG_LEDS
|
||||
#define MSG_LEDS _UxGT("Lights")
|
||||
#endif
|
||||
#ifndef MSG_LED_PRESETS
|
||||
#define MSG_LED_PRESETS _UxGT("Light Presets")
|
||||
@@ -540,6 +537,9 @@
|
||||
#ifndef MSG_VE_JERK
|
||||
#define MSG_VE_JERK _UxGT("Ve-jerk")
|
||||
#endif
|
||||
#ifndef MSG_JUNCTION_DEVIATION
|
||||
#define MSG_JUNCTION_DEVIATION _UxGT("Junction Dev")
|
||||
#endif
|
||||
#ifndef MSG_VELOCITY
|
||||
#define MSG_VELOCITY _UxGT("Velocity")
|
||||
#endif
|
||||
@@ -666,6 +666,9 @@
|
||||
#ifndef MSG_STOP_PRINT
|
||||
#define MSG_STOP_PRINT _UxGT("Stop print")
|
||||
#endif
|
||||
#ifndef MSG_POWER_LOSS_RECOVERY
|
||||
#define MSG_POWER_LOSS_RECOVERY _UxGT("Power-Loss Recovery")
|
||||
#endif
|
||||
#ifndef MSG_CARD_MENU
|
||||
#define MSG_CARD_MENU _UxGT("Print from SD")
|
||||
#endif
|
||||
|
||||
@@ -142,8 +142,7 @@
|
||||
//#define MSG_UBL_Z_OFFSET_STOPPED _UxGT("Z-Offset Stopped")
|
||||
//#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("Step-By-Step UBL")
|
||||
#define MSG_LED_CONTROL _UxGT("LED ezarpenak")
|
||||
#define MSG_LEDS_ON _UxGT("Argiak piztu")
|
||||
#define MSG_LEDS_OFF _UxGT("Argiak itzali")
|
||||
#define MSG_LEDS _UxGT("Argiak")
|
||||
#define MSG_LED_PRESETS _UxGT("Argi aurrehautaketak")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Gorria")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Laranja")
|
||||
|
||||
@@ -144,8 +144,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("UBL Pas a pas")
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("Controle LED")
|
||||
#define MSG_LEDS_ON _UxGT("Lumiere ON")
|
||||
#define MSG_LEDS_OFF _UxGT("Lumiere OFF")
|
||||
#define MSG_LEDS _UxGT("Lumiere")
|
||||
#define MSG_LED_PRESETS _UxGT("Preregl. LED.")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Rouge")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Orange")
|
||||
|
||||
@@ -145,8 +145,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("UBL Pas à pas")
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("Contrôle LED")
|
||||
#define MSG_LEDS_ON _UxGT("Lumière ON")
|
||||
#define MSG_LEDS_OFF _UxGT("Lumière OFF")
|
||||
#define MSG_LEDS _UxGT("Lumière")
|
||||
#define MSG_LED_PRESETS _UxGT("Préregl. LED")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Rouge")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Orange")
|
||||
|
||||
@@ -56,13 +56,13 @@
|
||||
#define MSG_HOME_OFFSETS_APPLIED _UxGT("Offset applicato")
|
||||
#define MSG_SET_ORIGIN _UxGT("Imposta Origine")
|
||||
#define MSG_PREHEAT_1 _UxGT("Preriscalda PLA")
|
||||
#define MSG_PREHEAT_1_N _UxGT("Prerisc.PLA ")
|
||||
#define MSG_PREHEAT_1_N _UxGT("Preris.PLA ")
|
||||
#define MSG_PREHEAT_1_ALL MSG_PREHEAT_1_N _UxGT("Tutto")
|
||||
#define MSG_PREHEAT_1_END MSG_PREHEAT_1_N _UxGT("Ugello")
|
||||
#define MSG_PREHEAT_1_BEDONLY MSG_PREHEAT_1_N _UxGT("Piatto")
|
||||
#define MSG_PREHEAT_1_SETTINGS MSG_PREHEAT_1_N _UxGT("conf")
|
||||
#define MSG_PREHEAT_2 _UxGT("Preriscalda ABS")
|
||||
#define MSG_PREHEAT_2_N _UxGT("Prerisc.ABS ")
|
||||
#define MSG_PREHEAT_2_N _UxGT("Preris.ABS ")
|
||||
#define MSG_PREHEAT_2_ALL MSG_PREHEAT_2_N _UxGT("Tutto")
|
||||
#define MSG_PREHEAT_2_END MSG_PREHEAT_2_N _UxGT("Ugello")
|
||||
#define MSG_PREHEAT_2_BEDONLY MSG_PREHEAT_2_N _UxGT("Piatto")
|
||||
@@ -144,8 +144,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("UBL passo passo")
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("Controllo LED")
|
||||
#define MSG_LEDS_ON _UxGT("Luci On")
|
||||
#define MSG_LEDS_OFF _UxGT("Luci Off")
|
||||
#define MSG_LEDS _UxGT("Luci")
|
||||
#define MSG_LED_PRESETS _UxGT("Preset luci")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Rosso")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Arancione")
|
||||
|
||||
@@ -145,8 +145,7 @@
|
||||
#define MSG_UBL_Z_OFFSET_STOPPED _UxGT("Compensacao Z parou")
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("UBL passo a passo")
|
||||
#define MSG_LED_CONTROL _UxGT("Controle do LED")
|
||||
#define MSG_LEDS_ON _UxGT("Luz Acesa")
|
||||
#define MSG_LEDS_OFF _UxGT("Luz Apagada")
|
||||
#define MSG_LEDS _UxGT("Luz")
|
||||
#define MSG_LED_PRESETS _UxGT("Configuracao da Luz")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Luz Vermelha")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Luz Laranja")
|
||||
|
||||
@@ -147,8 +147,7 @@
|
||||
#define MSG_UBL_Z_OFFSET_STOPPED _UxGT("Compensação Z parou")
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("UBL passo a passo")
|
||||
#define MSG_LED_CONTROL _UxGT("Controle do LED")
|
||||
#define MSG_LEDS_ON _UxGT("Luz Acesa")
|
||||
#define MSG_LEDS_OFF _UxGT("Luz Apagada")
|
||||
#define MSG_LEDS _UxGT("Luz")
|
||||
#define MSG_LED_PRESETS _UxGT("Configuração da Luz")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Luz Vermelha")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Luz Laranja")
|
||||
|
||||
@@ -145,8 +145,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("Пошаговое UBL")
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("Настройки LED")
|
||||
#define MSG_LEDS_ON _UxGT("Включить подсветку")
|
||||
#define MSG_LEDS_OFF _UxGT("Выключить подсветку")
|
||||
#define MSG_LEDS _UxGT("Подсветку")
|
||||
#define MSG_LED_PRESETS _UxGT("Предустановки света")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Красный свет")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Оранжевый свет")
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#define MSG_SD_INSERTED _UxGT("Karta vložená")
|
||||
#define MSG_SD_REMOVED _UxGT("Karta vybratá")
|
||||
#define MSG_LCD_ENDSTOPS _UxGT("Endstopy") // max 8 znakov
|
||||
#define MSG_LCD_SOFT_ENDSTOPS _UxGT("Soft.endstopy")
|
||||
#define MSG_MAIN _UxGT("Hlavná ponuka")
|
||||
#define MSG_AUTOSTART _UxGT("Autoštart")
|
||||
#define MSG_DISABLE_STEPPERS _UxGT("Uvolniť motory")
|
||||
@@ -148,8 +149,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("UBL Postupne")
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("Nastavenie LED")
|
||||
#define MSG_LEDS_ON _UxGT("Zapnúť svetlo")
|
||||
#define MSG_LEDS_OFF _UxGT("Vypnúť svetlo")
|
||||
#define MSG_LEDS _UxGT("Svetlo")
|
||||
#define MSG_LED_PRESETS _UxGT("Prednastavené farby")
|
||||
#define MSG_SET_LEDS_RED _UxGT("Červená")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("Oranžová")
|
||||
@@ -208,6 +208,7 @@
|
||||
#define MSG_VC_JERK _UxGT("Vz-skok")
|
||||
#endif
|
||||
#define MSG_VE_JERK _UxGT("Ve-skok")
|
||||
#define MSG_JUNCTION_DEVIATION _UxGT("Junction Dev")
|
||||
#define MSG_VELOCITY _UxGT("Rýchlosť")
|
||||
#define MSG_VMAX _UxGT("Vmax ")
|
||||
#define MSG_VMIN _UxGT("Vmin")
|
||||
@@ -255,8 +256,9 @@
|
||||
#define MSG_CARD_MENU _UxGT("Tlačiť z SD")
|
||||
#define MSG_NO_CARD _UxGT("Žiadna SD karta")
|
||||
#define MSG_DWELL _UxGT("Spím...")
|
||||
#define MSG_USERWAIT _UxGT("Čakám...")
|
||||
#define MSG_USERWAIT _UxGT("Kliknutím pokrač.")
|
||||
#define MSG_PRINT_PAUSED _UxGT("Tlač pozastavená")
|
||||
#define MSG_PRINTING _UxGT("Tlačím...")
|
||||
#define MSG_PRINT_ABORTED _UxGT("Tlač zrušená")
|
||||
#define MSG_NO_MOVE _UxGT("Žiadny pohyb.")
|
||||
#define MSG_KILLED _UxGT("PRERUŠENÉ. ")
|
||||
@@ -318,6 +320,7 @@
|
||||
#define MSG_DELTA_SETTINGS _UxGT("Delta nastavenia")
|
||||
#define MSG_DELTA_AUTO_CALIBRATE _UxGT("Autokalibrácia")
|
||||
#define MSG_DELTA_HEIGHT_CALIBRATE _UxGT("Nast.výšku delty")
|
||||
#define MSG_DELTA_Z_OFFSET_CALIBRATE _UxGT("Offset sondy Z")
|
||||
#define MSG_DELTA_DIAG_ROD _UxGT("Diag rameno")
|
||||
#define MSG_DELTA_HEIGHT _UxGT("Výška")
|
||||
#define MSG_DELTA_RADIUS _UxGT("Polomer")
|
||||
|
||||
@@ -141,8 +141,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("一步步UBL") // "Step-By-Step UBL"
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("灯管控制") // "LED Control")
|
||||
#define MSG_LEDS_ON _UxGT("灯亮") // "Lights On")
|
||||
#define MSG_LEDS_OFF _UxGT("灯灭") // "Lights Off")
|
||||
#define MSG_LEDS _UxGT("灯") // "Lights")
|
||||
#define MSG_LED_PRESETS _UxGT("灯预置") // "Light Presets")
|
||||
#define MSG_SET_LEDS_RED _UxGT("红") // "Red")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("橙") // "Orange")
|
||||
|
||||
@@ -141,8 +141,7 @@
|
||||
#define MSG_UBL_STEP_BY_STEP_MENU _UxGT("一步步UBL") // "Step-By-Step UBL"
|
||||
|
||||
#define MSG_LED_CONTROL _UxGT("灯管控制") // "LED Control")
|
||||
#define MSG_LEDS_ON _UxGT("灯亮") // "Lights On")
|
||||
#define MSG_LEDS_OFF _UxGT("灯灭") // "Lights Off")
|
||||
#define MSG_LEDS _UxGT("灯") // "Lights")
|
||||
#define MSG_LED_PRESETS _UxGT("灯预置") // "Light Presets")
|
||||
#define MSG_SET_LEDS_RED _UxGT("红") // "Red")
|
||||
#define MSG_SET_LEDS_ORANGE _UxGT("橙") // "Orange")
|
||||
|
||||
+20
-20
@@ -81,15 +81,14 @@
|
||||
#define IS_POWER_OF_2(x) ((x) && !((x) & ((x) - 1)))
|
||||
|
||||
// Macros for maths shortcuts
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
#define RADIANS(d) ((d)*M_PI/180.0)
|
||||
#define DEGREES(r) ((r)*180.0/M_PI)
|
||||
#undef M_PI
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#define RADIANS(d) ((d)*M_PI/180.0f)
|
||||
#define DEGREES(r) ((r)*180.0f/M_PI)
|
||||
#define HYPOT2(x,y) (sq(x)+sq(y))
|
||||
|
||||
#define CIRCLE_AREA(R) (M_PI * sq(R))
|
||||
#define CIRCLE_CIRC(R) (2.0 * M_PI * (R))
|
||||
#define CIRCLE_AREA(R) (M_PI * sq(float(R)))
|
||||
#define CIRCLE_CIRC(R) (2 * M_PI * (float(R)))
|
||||
|
||||
#define SIGN(a) ((a>0)-(a<0))
|
||||
#define IS_POWER_OF_2(x) ((x) && !((x) & ((x) - 1)))
|
||||
@@ -162,8 +161,8 @@
|
||||
#define PENDING(NOW,SOON) ((long)(NOW-(SOON))<0)
|
||||
#define ELAPSED(NOW,SOON) (!PENDING(NOW,SOON))
|
||||
|
||||
#define MMM_TO_MMS(MM_M) ((MM_M)/60.0)
|
||||
#define MMS_TO_MMM(MM_S) ((MM_S)*60.0)
|
||||
#define MMM_TO_MMS(MM_M) ((MM_M)/60.0f)
|
||||
#define MMS_TO_MMM(MM_S) ((MM_S)*60.0f)
|
||||
|
||||
#define NOOP do{} while(0)
|
||||
|
||||
@@ -212,23 +211,24 @@
|
||||
#define MAX4(a, b, c, d) MAX(MAX3(a, b, c), d)
|
||||
#define MAX5(a, b, c, d, e) MAX(MAX4(a, b, c, d), e)
|
||||
|
||||
#define UNEAR_ZERO(x) ((x) < 0.000001)
|
||||
#define NEAR_ZERO(x) WITHIN(x, -0.000001, 0.000001)
|
||||
#define UNEAR_ZERO(x) ((x) < 0.000001f)
|
||||
#define NEAR_ZERO(x) WITHIN(x, -0.000001f, 0.000001f)
|
||||
#define NEAR(x,y) NEAR_ZERO((x)-(y))
|
||||
|
||||
#define RECIPROCAL(x) (NEAR_ZERO(x) ? 0.0 : 1.0 / (x))
|
||||
#define FIXFLOAT(f) (f + (f < 0.0 ? -0.00005 : 0.00005))
|
||||
#define RECIPROCAL(x) (NEAR_ZERO(x) ? 0.0f : 1.0f / (x))
|
||||
#define FIXFLOAT(f) (f + (f < 0.0f ? -0.00005f : 0.00005f))
|
||||
|
||||
//
|
||||
// Maths macros that can be overridden by HAL
|
||||
//
|
||||
#define ATAN2(y, x) atan2(y, x)
|
||||
#define POW(x, y) pow(x, y)
|
||||
#define SQRT(x) sqrt(x)
|
||||
#define CEIL(x) ceil(x)
|
||||
#define FLOOR(x) floor(x)
|
||||
#define LROUND(x) lround(x)
|
||||
#define FMOD(x, y) fmod(x, y)
|
||||
#define ATAN2(y, x) atan2f(y, x)
|
||||
#define POW(x, y) powf(x, y)
|
||||
#define SQRT(x) sqrtf(x)
|
||||
#define RSQRT(x) (1 / sqrtf(x))
|
||||
#define CEIL(x) ceilf(x)
|
||||
#define FLOOR(x) floorf(x)
|
||||
#define LROUND(x) lroundf(x)
|
||||
#define FMOD(x, y) fmodf(x, y)
|
||||
#define HYPOT(x,y) SQRT(HYPOT2(x,y))
|
||||
|
||||
#endif //__MACROS_H
|
||||
|
||||
@@ -72,22 +72,22 @@ public:
|
||||
}
|
||||
|
||||
static int8_t cell_index_x(const float &x) {
|
||||
int8_t cx = (x - (MESH_MIN_X)) * (1.0 / (MESH_X_DIST));
|
||||
int8_t cx = (x - (MESH_MIN_X)) * (1.0f / (MESH_X_DIST));
|
||||
return constrain(cx, 0, (GRID_MAX_POINTS_X) - 2);
|
||||
}
|
||||
|
||||
static int8_t cell_index_y(const float &y) {
|
||||
int8_t cy = (y - (MESH_MIN_Y)) * (1.0 / (MESH_Y_DIST));
|
||||
int8_t cy = (y - (MESH_MIN_Y)) * (1.0f / (MESH_Y_DIST));
|
||||
return constrain(cy, 0, (GRID_MAX_POINTS_Y) - 2);
|
||||
}
|
||||
|
||||
static int8_t probe_index_x(const float &x) {
|
||||
int8_t px = (x - (MESH_MIN_X) + 0.5 * (MESH_X_DIST)) * (1.0 / (MESH_X_DIST));
|
||||
int8_t px = (x - (MESH_MIN_X) + 0.5f * (MESH_X_DIST)) * (1.0f / (MESH_X_DIST));
|
||||
return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1;
|
||||
}
|
||||
|
||||
static int8_t probe_index_y(const float &y) {
|
||||
int8_t py = (y - (MESH_MIN_Y) + 0.5 * (MESH_Y_DIST)) * (1.0 / (MESH_Y_DIST));
|
||||
int8_t py = (y - (MESH_MIN_Y) + 0.5f * (MESH_Y_DIST)) * (1.0f / (MESH_Y_DIST));
|
||||
return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -39,6 +39,8 @@
|
||||
#include "serial.h"
|
||||
#endif
|
||||
|
||||
#define strtof strtod
|
||||
|
||||
/**
|
||||
* GCode parser
|
||||
*
|
||||
@@ -194,15 +196,15 @@ public:
|
||||
if (c == '\0' || c == ' ') break;
|
||||
if (c == 'E' || c == 'e') {
|
||||
*e = '\0';
|
||||
const float ret = strtod(value_ptr, NULL);
|
||||
const float ret = strtof(value_ptr, NULL);
|
||||
*e = c;
|
||||
return ret;
|
||||
}
|
||||
++e;
|
||||
}
|
||||
return strtod(value_ptr, NULL);
|
||||
return strtof(value_ptr, NULL);
|
||||
}
|
||||
return 0.0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Code value as a long or ulong
|
||||
|
||||
@@ -132,7 +132,9 @@
|
||||
#define HEATER_0_PIN 15 // C5
|
||||
#define HEATER_BED_PIN 14 // C4
|
||||
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -133,7 +133,10 @@
|
||||
//
|
||||
#define HEATER_0_PIN 13 // (extruder)
|
||||
#define HEATER_BED_PIN 12 // (bed)
|
||||
#define FAN_PIN 4
|
||||
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 4
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
+15
-11
@@ -24,22 +24,29 @@
|
||||
* AZTEEG_X3_PRO (Arduino Mega) pin assignments
|
||||
*/
|
||||
|
||||
#ifndef __AVR_ATmega2560__
|
||||
#error "Oops! Make sure you have 'Arduino Mega 2560' selected from the 'Tools -> Boards' menu."
|
||||
#endif
|
||||
|
||||
#if HOTENDS > 5 || E_STEPPERS > 5
|
||||
#error "Azteeg X3 Pro supports up to 5 hotends / E-steppers. Comment out this line to continue."
|
||||
#endif
|
||||
|
||||
#if ENABLED(CASE_LIGHT_ENABLE) && !PIN_EXISTS(CASE_LIGHT)
|
||||
#define CASE_LIGHT_PIN 44 // Define before RAMPS pins include
|
||||
#endif
|
||||
|
||||
#define BOARD_NAME "Azteeg X3 Pro"
|
||||
|
||||
#include "pins_RAMPS.h"
|
||||
|
||||
#ifndef __AVR_ATmega2560__
|
||||
#error "Oops! Make sure you have 'Arduino Mega 2560' selected from the 'Tools -> Boards' menu."
|
||||
//
|
||||
// RAMPS pins overrides
|
||||
//
|
||||
#if ENABLED(CASE_LIGHT_ENABLE) && !PIN_EXISTS(CASE_LIGHT)
|
||||
#define CASE_LIGHT_PIN 44
|
||||
#endif
|
||||
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 6
|
||||
#endif
|
||||
|
||||
#include "pins_RAMPS.h"
|
||||
|
||||
// DIGIPOT slave addresses
|
||||
#define DIGIPOT_I2C_ADDRESS_A 0x2C // unshifted slave address for first DIGIPOT 0x2C (0x58 <- 0x2C << 1)
|
||||
#define DIGIPOT_I2C_ADDRESS_B 0x2E // unshifted slave address for second DIGIPOT 0x2E (0x5C <- 0x2E << 1)
|
||||
@@ -116,9 +123,6 @@
|
||||
#define HEATER_6_PIN 6
|
||||
#define HEATER_7_PIN 11
|
||||
|
||||
#undef FAN_PIN
|
||||
#define FAN_PIN 6 // Part Cooling System
|
||||
|
||||
#ifndef CONTROLLER_FAN_PIN
|
||||
#define CONTROLLER_FAN_PIN 4 // Pin used for the fan to cool motherboard (-1 to disable)
|
||||
#endif
|
||||
|
||||
@@ -115,7 +115,9 @@
|
||||
#define HEATER_0_PIN 32 // A4 Extruder
|
||||
#define HEATER_BED_PIN 18 // E6 Bed
|
||||
|
||||
#define FAN_PIN 31 // A3 Fan
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 31 // A3 Fan
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -125,7 +125,9 @@
|
||||
//
|
||||
#define HEATER_0_PIN 27 // B7
|
||||
#define HEATER_BED_PIN 26 // B6 Bed
|
||||
#define FAN_PIN 16 // C6 Fan, PWM3A
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 16 // C6 Fan, PWM3A
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -69,8 +69,8 @@
|
||||
//
|
||||
// Heaters / Fans
|
||||
//
|
||||
#define HEATER_0_PIN 19 // EXTRUDER 1
|
||||
#define HEATER_1_PIN 23 // EXTRUDER 2
|
||||
#define HEATER_0_PIN 19 // EXTRUDER 1
|
||||
#define HEATER_1_PIN 23 // EXTRUDER 2
|
||||
#define HEATER_BED_PIN 22
|
||||
|
||||
//
|
||||
|
||||
+27
-24
@@ -31,6 +31,7 @@
|
||||
#endif
|
||||
|
||||
#define BOARD_NAME "Cheaptronic v2.0"
|
||||
|
||||
//
|
||||
// Limit Switches
|
||||
//
|
||||
@@ -80,10 +81,32 @@
|
||||
//
|
||||
// Heaters / Fans
|
||||
//
|
||||
#define HEATER_0_PIN 6
|
||||
#define HEATER_1_PIN 7
|
||||
#define HEATER_2_PIN 8
|
||||
#define HEATER_BED_PIN 9
|
||||
#define HEATER_0_PIN 6
|
||||
#define HEATER_1_PIN 7
|
||||
#define HEATER_2_PIN 8
|
||||
#define HEATER_BED_PIN 9
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 3
|
||||
#endif
|
||||
#define FAN2_PIN 58 // additional fan or light control output
|
||||
|
||||
//
|
||||
// Other board specific pins
|
||||
//
|
||||
#ifndef FIL_RUNOUT_PIN
|
||||
#define FIL_RUNOUT_PIN 37 // board input labeled as F-DET
|
||||
#endif
|
||||
#define Z_MIN_PROBE_PIN 36 // additional external board input labeled as E-SENS (should be used for Z-probe)
|
||||
#define LED_PIN 13
|
||||
#define SPINDLE_ENABLE_PIN 4 // additional PWM pin 1 at JP1 connector - should be used for laser control too
|
||||
#define EXT_2 5 // additional PWM pin 2 at JP1 connector
|
||||
#define EXT_3 2 // additional PWM pin 3 at JP1 connector
|
||||
#define PS_ON_PIN 45
|
||||
#define KILL_PIN 46
|
||||
|
||||
#ifndef FILWIDTH_PIN
|
||||
#define FILWIDTH_PIN 11 // shared with TEMP_3 analog input
|
||||
#endif
|
||||
|
||||
//
|
||||
// LCD
|
||||
@@ -105,23 +128,3 @@
|
||||
#define BTN_EN1 11
|
||||
#define BTN_EN2 12
|
||||
#define BTN_ENC 43
|
||||
|
||||
//
|
||||
// Other board specific pins
|
||||
//
|
||||
#ifndef FIL_RUNOUT_PIN
|
||||
#define FIL_RUNOUT_PIN 37 // board input labeled as F-DET
|
||||
#endif
|
||||
#define Z_MIN_PROBE_PIN 36 // additional external board input labeled as E-SENS (should be used for Z-probe)
|
||||
#define LED_PIN 13
|
||||
#define SPINDLE_ENABLE_PIN 4 // additional PWM pin 1 at JP1 connector - should be used for laser control too
|
||||
#define EXT_2 5 // additional PWM pin 2 at JP1 connector
|
||||
#define EXT_3 2 // additional PWM pin 3 at JP1 connector
|
||||
#define FAN_PIN 3
|
||||
#define FAN2_PIN 58 // additional fan or light control output
|
||||
#define PS_ON_PIN 45
|
||||
#define KILL_PIN 46
|
||||
|
||||
#ifndef FILWIDTH_PIN
|
||||
#define FILWIDTH_PIN 11 // shared with TEMP_3 analog input
|
||||
#endif
|
||||
|
||||
@@ -65,7 +65,9 @@
|
||||
#define HEATER_3_PIN 46
|
||||
#define HEATER_BED_PIN 2
|
||||
|
||||
//#define FAN_PIN 7 // common PWM pin for all tools
|
||||
#ifndef FAN_PIN
|
||||
//#define FAN_PIN 7 // common PWM pin for all tools
|
||||
#endif
|
||||
|
||||
#define ORIG_E0_AUTO_FAN_PIN 7
|
||||
#define ORIG_E1_AUTO_FAN_PIN 7
|
||||
|
||||
@@ -65,7 +65,9 @@
|
||||
#define HEATER_3_PIN 3
|
||||
#define HEATER_BED_PIN 24
|
||||
|
||||
#define FAN_PIN 5 // 5 is PWMtool3 -> 7 is common PWM pin for all tools
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 5 // 5 is PWMtool3 -> 7 is common PWM pin for all tools
|
||||
#endif
|
||||
|
||||
#define ORIG_E0_AUTO_FAN_PIN 7
|
||||
#define ORIG_E1_AUTO_FAN_PIN 7
|
||||
@@ -124,4 +126,4 @@
|
||||
//#define UI2 37
|
||||
|
||||
#define STAT_LED_BLUE_PIN -1
|
||||
#define STAT_LED_RED_PIN 10 // TOOL_0_PWM_PIN
|
||||
#define STAT_LED_RED_PIN 10 // TOOL_0_PWM_PIN
|
||||
|
||||
@@ -117,7 +117,9 @@
|
||||
#define HEATER_0_PIN 3
|
||||
#define HEATER_BED_PIN 4
|
||||
|
||||
#define FAN_PIN 8
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 8
|
||||
#endif
|
||||
#define FAN1_PIN 6
|
||||
|
||||
//
|
||||
|
||||
@@ -134,7 +134,9 @@
|
||||
#define HEATER_0_PIN 3
|
||||
#define HEATER_BED_PIN 4
|
||||
|
||||
#define FAN_PIN 8
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 8
|
||||
#endif
|
||||
#define FAN1_PIN 6
|
||||
|
||||
//
|
||||
|
||||
@@ -90,7 +90,9 @@
|
||||
#define HEATER_2_PIN 17 // 12V PWM3
|
||||
#define HEATER_BED_PIN 44 // DOUBLE 12V PWM
|
||||
|
||||
#define FAN_PIN 16 // 5V PWM
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 16 // 5V PWM
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -68,11 +68,11 @@
|
||||
//
|
||||
#define X_STEP_PIN 15
|
||||
#define X_DIR_PIN 18
|
||||
#define X_ENABLE_PIN 24 // actually uses Y_enable_pin
|
||||
#define X_ENABLE_PIN 24 // actually uses Y_enable_pin
|
||||
|
||||
#define Y_STEP_PIN 23
|
||||
#define Y_DIR_PIN 22
|
||||
#define Y_ENABLE_PIN 24 // shared with X_enable_pin
|
||||
#define Y_ENABLE_PIN 24 // shared with X_enable_pin
|
||||
|
||||
#define Z_STEP_PIN 27
|
||||
#define Z_DIR_PIN 28
|
||||
@@ -95,7 +95,6 @@
|
||||
//
|
||||
// Misc. Functions
|
||||
//
|
||||
#define PS_ON_PIN 14 // Alex, does this work on the card?
|
||||
#define PS_ON_PIN 14 // Alex, does this work on the card?
|
||||
|
||||
// Alex extras from Gen3+
|
||||
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
#define HEATER_0_PIN 4
|
||||
#define HEATER_BED_PIN 3
|
||||
|
||||
#if GEN7_VERSION < 13 // Gen7 v1.3 removed the fan pin
|
||||
#define FAN_PIN 31
|
||||
#if !defined(FAN_PIN) && GEN7_VERSION < 13 // Gen7 v1.3 removed the fan pin
|
||||
#define FAN_PIN 31
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
@@ -81,7 +81,9 @@
|
||||
#define HEATER_0_PIN 2
|
||||
#define HEATER_1_PIN 3
|
||||
#define HEATER_BED_PIN 4
|
||||
#define FAN_PIN 7
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 7
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
+14
-14
@@ -47,21 +47,21 @@
|
||||
#define X_DIR_PIN 63
|
||||
#define X_ENABLE_PIN 29
|
||||
|
||||
#define Y_STEP_PIN 14 // A6
|
||||
#define Y_DIR_PIN 15 // A0
|
||||
#define Y_STEP_PIN 14 // A6
|
||||
#define Y_DIR_PIN 15 // A0
|
||||
#define Y_ENABLE_PIN 39
|
||||
|
||||
#define Z_STEP_PIN 31 // A2
|
||||
#define Z_DIR_PIN 32 // A6
|
||||
#define Z_ENABLE_PIN 30 // A1
|
||||
#define Z_STEP_PIN 31 // A2
|
||||
#define Z_DIR_PIN 32 // A6
|
||||
#define Z_ENABLE_PIN 30 // A1
|
||||
|
||||
#define E0_STEP_PIN 34 // 34
|
||||
#define E0_DIR_PIN 35 // 35
|
||||
#define E0_ENABLE_PIN 33 // 33
|
||||
#define E0_STEP_PIN 34 // 34
|
||||
#define E0_DIR_PIN 35 // 35
|
||||
#define E0_ENABLE_PIN 33 // 33
|
||||
|
||||
#define E1_STEP_PIN 37 // 37
|
||||
#define E1_DIR_PIN 40 // 40
|
||||
#define E1_ENABLE_PIN 36 // 36
|
||||
#define E1_STEP_PIN 37 // 37
|
||||
#define E1_DIR_PIN 40 // 40
|
||||
#define E1_ENABLE_PIN 36 // 36
|
||||
|
||||
//
|
||||
// Temperature Sensors
|
||||
@@ -74,9 +74,9 @@
|
||||
// Heaters / Fans
|
||||
//
|
||||
#define HEATER_0_PIN 9
|
||||
#define HEATER_1_PIN 8 // 12
|
||||
#define HEATER_2_PIN 11 // 13
|
||||
#define HEATER_BED_PIN 10 // 14/15
|
||||
#define HEATER_1_PIN 8 // 12
|
||||
#define HEATER_2_PIN 11 // 13
|
||||
#define HEATER_BED_PIN 10 // 14/15
|
||||
|
||||
#define FAN_PIN 7
|
||||
|
||||
|
||||
@@ -62,17 +62,17 @@
|
||||
//
|
||||
// Steppers
|
||||
//
|
||||
#define X_STEP_PIN 62 // A8
|
||||
#define X_DIR_PIN 63 // A9
|
||||
#define X_ENABLE_PIN 61 // A7
|
||||
#define X_STEP_PIN 62 // A8
|
||||
#define X_DIR_PIN 63 // A9
|
||||
#define X_ENABLE_PIN 61 // A7
|
||||
|
||||
#define Y_STEP_PIN 65 // A11
|
||||
#define Y_DIR_PIN 66 // A12
|
||||
#define Y_ENABLE_PIN 64 // A10
|
||||
#define Y_STEP_PIN 65 // A11
|
||||
#define Y_DIR_PIN 66 // A12
|
||||
#define Y_ENABLE_PIN 64 // A10
|
||||
|
||||
#define Z_STEP_PIN 68 // A14
|
||||
#define Z_DIR_PIN 69 // A15
|
||||
#define Z_ENABLE_PIN 67 // A13
|
||||
#define Z_STEP_PIN 68 // A14
|
||||
#define Z_DIR_PIN 69 // A15
|
||||
#define Z_ENABLE_PIN 67 // A13
|
||||
|
||||
#define E0_STEP_PIN 23
|
||||
#define E0_DIR_PIN 24
|
||||
@@ -112,7 +112,9 @@
|
||||
#define HEATER_1_PIN 34
|
||||
#define HEATER_BED_PIN 28
|
||||
|
||||
#define FAN_PIN 39
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 39
|
||||
#endif
|
||||
#define FAN1_PIN 35
|
||||
#define FAN2_PIN 36
|
||||
|
||||
|
||||
@@ -53,13 +53,13 @@
|
||||
#define X_DIR_PIN 28
|
||||
#define X_ENABLE_PIN 24
|
||||
|
||||
#define Y_STEP_PIN 60 // A6
|
||||
#define Y_DIR_PIN 61 // A7
|
||||
#define Y_STEP_PIN 60 // A6
|
||||
#define Y_DIR_PIN 61 // A7
|
||||
#define Y_ENABLE_PIN 22
|
||||
|
||||
#define Z_STEP_PIN 54 // A0
|
||||
#define Z_DIR_PIN 55 // A1
|
||||
#define Z_ENABLE_PIN 56 // A2
|
||||
#define Z_STEP_PIN 54 // A0
|
||||
#define Z_DIR_PIN 55 // A1
|
||||
#define Z_ENABLE_PIN 56 // A2
|
||||
|
||||
#define E0_STEP_PIN 31
|
||||
#define E0_DIR_PIN 32
|
||||
@@ -87,7 +87,9 @@
|
||||
#define HEATER_1_PIN 8
|
||||
#define HEATER_BED_PIN 10
|
||||
|
||||
#define FAN_PIN 7 // IO pin. Buffer needed
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 7 // IO pin. Buffer needed
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -101,7 +101,9 @@
|
||||
#define HEATER_1_PIN 8
|
||||
#define HEATER_BED_PIN 10
|
||||
|
||||
#define FAN_PIN 7
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 7
|
||||
#endif
|
||||
#define FAN1_PIN 6
|
||||
|
||||
//
|
||||
|
||||
@@ -118,7 +118,9 @@
|
||||
#define HEATER_2_PIN 8
|
||||
#define HEATER_BED_PIN 10
|
||||
|
||||
#define FAN_PIN 6
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 6
|
||||
#endif
|
||||
#define FAN1_PIN 7
|
||||
|
||||
//
|
||||
|
||||
@@ -134,14 +134,14 @@
|
||||
// 2 E4 CS2
|
||||
// 78 E2 SCK
|
||||
//
|
||||
#define THERMO_SCK_PIN 78 // E2
|
||||
#define THERMO_DO_PIN 3 // E5
|
||||
#define THERMO_CS1 5 // E3
|
||||
#define THERMO_CS2 2 // E4
|
||||
#define THERMO_SCK_PIN 78 // E2
|
||||
#define THERMO_DO_PIN 3 // E5
|
||||
#define THERMO_CS1 5 // E3
|
||||
#define THERMO_CS2 2 // E4
|
||||
|
||||
#define MAX6675_SS THERMO_CS1
|
||||
#define MAX6675_SCK_PIN THERMO_SCK_PIN
|
||||
#define MAX6675_DO_PIN THERMO_DO_PIN
|
||||
#define MAX6675_SS THERMO_CS1
|
||||
#define MAX6675_SCK_PIN THERMO_SCK_PIN
|
||||
#define MAX6675_DO_PIN THERMO_DO_PIN
|
||||
//
|
||||
// Augmentation for auto-assigning plugs
|
||||
//
|
||||
@@ -149,10 +149,10 @@
|
||||
// 2 extruders or 1 extruder and a heated bed.
|
||||
// With no heated bed, an additional 24V fan is possible.
|
||||
//
|
||||
#define MOSFET_A_PIN 6 // H3
|
||||
#define MOSFET_B_PIN 11 // B5 - Rev A of this file had this pin assigned to 9
|
||||
#define MOSFET_C_PIN 45 // L4
|
||||
#define MOSFET_D_PIN 44 // L5
|
||||
#define MOSFET_A_PIN 6 // H3
|
||||
#define MOSFET_B_PIN 11 // B5 - Rev A of this file had this pin assigned to 9
|
||||
#define MOSFET_C_PIN 45 // L4
|
||||
#define MOSFET_D_PIN 44 // L5
|
||||
|
||||
#if HOTENDS > 1
|
||||
#if TEMP_SENSOR_BED
|
||||
@@ -172,23 +172,24 @@
|
||||
#define HEATER_0_PIN MOSFET_A_PIN
|
||||
|
||||
#if ENABLED(IS_EFB) // Hotend, Fan, Bed
|
||||
#define FAN_PIN MOSFET_B_PIN
|
||||
#define HEATER_BED_PIN MOSFET_C_PIN
|
||||
#define HEATER_BED_PIN MOSFET_C_PIN
|
||||
#elif ENABLED(IS_EEF) // Hotend, Hotend, Fan
|
||||
#define HEATER_1_PIN MOSFET_B_PIN
|
||||
#define FAN_PIN MOSFET_C_PIN
|
||||
#define HEATER_1_PIN MOSFET_B_PIN
|
||||
#elif ENABLED(IS_EEB) // Hotend, Hotend, Bed
|
||||
#define HEATER_1_PIN MOSFET_B_PIN
|
||||
#define HEATER_BED_PIN MOSFET_C_PIN
|
||||
#define HEATER_1_PIN MOSFET_B_PIN
|
||||
#define HEATER_BED_PIN MOSFET_C_PIN
|
||||
#elif ENABLED(IS_EFF) // Hotend, Fan, Fan
|
||||
#define FAN_PIN MOSFET_B_PIN
|
||||
#define FAN1_PIN MOSFET_C_PIN
|
||||
#elif ENABLED(IS_SF) // Spindle, Fan
|
||||
#define FAN_PIN MOSFET_C_PIN
|
||||
#define FAN1_PIN MOSFET_C_PIN
|
||||
#endif
|
||||
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN MOSFET_D_PIN
|
||||
#if ENABLED(IS_EFB) || ENABLED(IS_EFF) // Hotend, Fan, Bed or Hotend, Fan, Fan
|
||||
#define FAN_PIN MOSFET_B_PIN
|
||||
#elif ENABLED(IS_EEF) || ENABLED(IS_SF) // Hotend, Hotend, Fan or Spindle, Fan
|
||||
#define FAN_PIN MOSFET_C_PIN
|
||||
#else
|
||||
#define FAN_PIN MOSFET_D_PIN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -200,37 +201,37 @@
|
||||
//
|
||||
// Misc. Functions
|
||||
//
|
||||
#define LED_PIN 13 // B7
|
||||
#define CUTOFF_RESET_PIN 16 // H1
|
||||
#define CUTOFF_TEST_PIN 17 // H0
|
||||
#define CASE_LIGHT_PIN 44 // L5 MUST BE HARDWARE PWM
|
||||
#define LED_PIN 13 // B7
|
||||
#define CUTOFF_RESET_PIN 16 // H1
|
||||
#define CUTOFF_TEST_PIN 17 // H0
|
||||
#define CASE_LIGHT_PIN 44 // L5 MUST BE HARDWARE PWM
|
||||
|
||||
//
|
||||
// LCD / Controller
|
||||
//
|
||||
#ifdef REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
|
||||
#define LCD_PINS_RS 33 // C4: LCD-STROBE
|
||||
#define LCD_PINS_ENABLE 72 // J2: LEFT
|
||||
#define LCD_PINS_D4 35 // C2: LCD-CLK
|
||||
#define LCD_PINS_D5 32 // C5: RLED
|
||||
#define LCD_PINS_D6 34 // C3: LCD-DATA
|
||||
#define LCD_PINS_D7 31 // C6: GLED
|
||||
#define LCD_PINS_RS 33 // C4: LCD-STROBE
|
||||
#define LCD_PINS_ENABLE 72 // J2: LEFT
|
||||
#define LCD_PINS_D4 35 // C2: LCD-CLK
|
||||
#define LCD_PINS_D5 32 // C5: RLED
|
||||
#define LCD_PINS_D6 34 // C3: LCD-DATA
|
||||
#define LCD_PINS_D7 31 // C6: GLED
|
||||
|
||||
#define BTN_EN2 75 // J4, UP
|
||||
#define BTN_EN1 73 // J3, DOWN
|
||||
#define BTN_EN2 75 // J4, UP
|
||||
#define BTN_EN1 73 // J3, DOWN
|
||||
//STOP button connected as KILL_PIN
|
||||
#define KILL_PIN 14 // J1, RIGHT
|
||||
#define KILL_PIN 14 // J1, RIGHT
|
||||
//KILL - not connected
|
||||
|
||||
#define BEEPER_PIN 8 // H5, SD_WP
|
||||
#define BEEPER_PIN 8 // H5, SD_WP
|
||||
|
||||
#define BTN_CENTER 15 // J0
|
||||
#define BTN_ENC BTN_CENTER
|
||||
#define BTN_CENTER 15 // J0
|
||||
#define BTN_ENC BTN_CENTER
|
||||
|
||||
//on board leds
|
||||
#define STAT_LED_RED_LED SERVO0_PIN // C1 (1280-EX1, DEBUG2)
|
||||
#define STAT_LED_BLUE_PIN SERVO1_PIN // C0 (1280-EX2, DEBUG3)
|
||||
#define STAT_LED_RED_LED SERVO0_PIN // C1 (1280-EX1, DEBUG2)
|
||||
#define STAT_LED_BLUE_PIN SERVO1_PIN // C0 (1280-EX2, DEBUG3)
|
||||
|
||||
#else
|
||||
// Replicator uses a 3-wire SR controller with HD44780
|
||||
@@ -238,18 +239,18 @@
|
||||
//
|
||||
|
||||
#define SAV_3DLCD
|
||||
#define SR_DATA_PIN 34 // C3
|
||||
#define SR_CLK_PIN 35 // C2
|
||||
#define SR_STROBE_PIN 33 // C4
|
||||
#define SR_DATA_PIN 34 // C3
|
||||
#define SR_CLK_PIN 35 // C2
|
||||
#define SR_STROBE_PIN 33 // C4
|
||||
|
||||
#define BTN_UP 75 // J4
|
||||
#define BTN_DOWN 73 // J3
|
||||
#define BTN_LEFT 72 // J2
|
||||
#define BTN_RIGHT 14 // J1
|
||||
#define BTN_CENTER 15 // J0
|
||||
#define BTN_ENC BTN_CENTER
|
||||
#define BTN_UP 75 // J4
|
||||
#define BTN_DOWN 73 // J3
|
||||
#define BTN_LEFT 72 // J2
|
||||
#define BTN_RIGHT 14 // J1
|
||||
#define BTN_CENTER 15 // J0
|
||||
#define BTN_ENC BTN_CENTER
|
||||
|
||||
#define BEEPER_PIN 4 // G5
|
||||
#define BEEPER_PIN 4 // G5
|
||||
|
||||
#define STAT_LED_RED_PIN 32 // C5
|
||||
#define STAT_LED_BLUE_PIN 31 // C6 (Actually green)
|
||||
@@ -259,8 +260,8 @@
|
||||
//
|
||||
// SD Card
|
||||
//
|
||||
#define SDSS 53 // B0
|
||||
#define SD_DETECT_PIN 9 // H6
|
||||
#define SDSS 53 // B0
|
||||
#define SD_DETECT_PIN 9 // H6
|
||||
|
||||
#define MAX_PIN THERMO_SCK_PIN
|
||||
|
||||
@@ -272,8 +273,6 @@
|
||||
#define SPINDLE_DIR_PIN 67 // K5
|
||||
|
||||
|
||||
|
||||
|
||||
// Check if all pins are defined in mega/pins_arduino.h
|
||||
#include <Arduino.h>
|
||||
static_assert(NUM_DIGITAL_PINS > MAX_PIN, "add missing pins to [arduino dir]/hardware/arduino/avr/variants/mega/pins_arduino.h based on fastio.h"
|
||||
|
||||
@@ -106,7 +106,9 @@
|
||||
#endif
|
||||
#define HEATER_BED_PIN 4
|
||||
|
||||
#define FAN_PIN 8
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 8
|
||||
#endif
|
||||
#define FAN1_PIN 6
|
||||
|
||||
//
|
||||
|
||||
+12
-10
@@ -57,13 +57,13 @@
|
||||
#define X_DIR_PIN 47
|
||||
#define X_ENABLE_PIN 49
|
||||
|
||||
#define Y_STEP_PIN 39 // A6
|
||||
#define Y_DIR_PIN 40 // A0
|
||||
#define Y_STEP_PIN 39 // A6
|
||||
#define Y_DIR_PIN 40 // A0
|
||||
#define Y_ENABLE_PIN 38
|
||||
|
||||
#define Z_STEP_PIN 42 // A2
|
||||
#define Z_DIR_PIN 43 // A6
|
||||
#define Z_ENABLE_PIN 41 // A1
|
||||
#define Z_STEP_PIN 42 // A2
|
||||
#define Z_DIR_PIN 43 // A6
|
||||
#define Z_ENABLE_PIN 41 // A1
|
||||
|
||||
#define E0_STEP_PIN 45
|
||||
#define E0_DIR_PIN 44
|
||||
@@ -83,11 +83,13 @@
|
||||
//
|
||||
// Heaters / Fans
|
||||
//
|
||||
#define HEATER_0_PIN 7 // EXTRUDER 1
|
||||
#define HEATER_1_PIN 8 // EXTRUDER 2
|
||||
#define HEATER_BED_PIN 3 // BED
|
||||
#define HEATER_0_PIN 7 // EXTRUDER 1
|
||||
#define HEATER_1_PIN 8 // EXTRUDER 2
|
||||
#define HEATER_BED_PIN 3 // BED
|
||||
|
||||
#define FAN_PIN 9
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 9
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
@@ -122,7 +124,7 @@
|
||||
#define BTN_EN2 -1
|
||||
#define BTN_ENC -1
|
||||
|
||||
#define SD_DETECT_PIN -1 // Minitronics doesn't use this
|
||||
#define SD_DETECT_PIN -1 // Minitronics doesn't use this
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#error "MKS GEN 1.3/1.4 supports up to 2 hotends / E-steppers. Comment out this line to continue."
|
||||
#endif
|
||||
|
||||
#define BOARD_NAME "MKS GEN > v1.3"
|
||||
#define BOARD_NAME "MKS GEN >= v1.3"
|
||||
|
||||
//
|
||||
// Heaters / Fans
|
||||
|
||||
@@ -36,4 +36,17 @@
|
||||
// Power outputs EFBF or EFBE
|
||||
#define MOSFET_D_PIN 7
|
||||
|
||||
//
|
||||
// CS Pins wired to avoid conflict with the LCD
|
||||
// See https://www.thingiverse.com/asset:66604
|
||||
//
|
||||
|
||||
#ifndef X_CS_PIN
|
||||
#define X_CS_PIN 59
|
||||
#endif
|
||||
|
||||
#ifndef Y_CS_PIN
|
||||
#define Y_CS_PIN 63
|
||||
#endif
|
||||
|
||||
#include "pins_RAMPS.h"
|
||||
|
||||
+11
-9
@@ -108,13 +108,13 @@
|
||||
#define E0_DIR_PIN 21
|
||||
#define E0_ENABLE_PIN 10
|
||||
|
||||
#define E1_STEP_PIN -1 // 21
|
||||
#define E1_DIR_PIN -1 // 20
|
||||
#define E1_ENABLE_PIN -1 // 19
|
||||
#define E1_STEP_PIN -1 // 21
|
||||
#define E1_DIR_PIN -1 // 20
|
||||
#define E1_ENABLE_PIN -1 // 19
|
||||
|
||||
#define E2_STEP_PIN -1 // 21
|
||||
#define E2_DIR_PIN -1 // 20
|
||||
#define E2_ENABLE_PIN -1 // 18
|
||||
#define E2_STEP_PIN -1 // 21
|
||||
#define E2_DIR_PIN -1 // 20
|
||||
#define E2_ENABLE_PIN -1 // 18
|
||||
|
||||
//
|
||||
// Temperature Sensors
|
||||
@@ -126,10 +126,12 @@
|
||||
//
|
||||
// Heaters / Fans
|
||||
//
|
||||
#define HEATER_0_PIN 3 // DONE PWM on RIGHT connector
|
||||
#define HEATER_0_PIN 3 // DONE PWM on RIGHT connector
|
||||
#define HEATER_BED_PIN 4
|
||||
|
||||
#define FAN_PIN 14 // PWM on MIDDLE connector
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 14 // PWM on MIDDLE connector
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
@@ -145,4 +147,4 @@
|
||||
#define __GS 18
|
||||
#define __GD 13
|
||||
|
||||
#define UNUSED_PWM 14 // PWM on LEFT connector
|
||||
#define UNUSED_PWM 14 // PWM on LEFT connector
|
||||
|
||||
@@ -107,12 +107,12 @@
|
||||
#define E0_DIR_PIN 27
|
||||
#define E0_ENABLE_PIN 24
|
||||
|
||||
#define E1_STEP_PIN -1 // 19
|
||||
#define E1_DIR_PIN -1 // 18
|
||||
#define E1_STEP_PIN -1 // 19
|
||||
#define E1_DIR_PIN -1 // 18
|
||||
#define E1_ENABLE_PIN 24
|
||||
|
||||
#define E2_STEP_PIN -1 // 17
|
||||
#define E2_DIR_PIN -1 // 16
|
||||
#define E2_STEP_PIN -1 // 17
|
||||
#define E2_DIR_PIN -1 // 16
|
||||
#define E2_ENABLE_PIN 24
|
||||
|
||||
//
|
||||
@@ -125,7 +125,9 @@
|
||||
//
|
||||
#define HEATER_0_PIN 4
|
||||
|
||||
#define FAN_PIN 3
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 3
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -110,8 +110,9 @@
|
||||
#define HEATER_2_PIN 45 // F7
|
||||
#define HEATER_BED_PIN 14 // C4 PWM3C
|
||||
|
||||
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -190,7 +190,9 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#endif
|
||||
|
||||
//
|
||||
// LCD / Controller
|
||||
|
||||
+3
-1
@@ -127,7 +127,9 @@
|
||||
#define HEATER_2_PIN 6
|
||||
#define HEATER_BED_PIN 3
|
||||
|
||||
#define FAN_PIN 8
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 8
|
||||
#endif
|
||||
#define FAN1_PIN 6
|
||||
#define FAN2_PIN 2
|
||||
|
||||
|
||||
@@ -88,11 +88,15 @@
|
||||
#if ENABLED(RAMPS_V_1_0)
|
||||
#define HEATER_0_PIN 12
|
||||
#define HEATER_BED_PIN -1
|
||||
#define FAN_PIN 11
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 11
|
||||
#endif
|
||||
#else // RAMPS_V_1_1 or RAMPS_V_1_2
|
||||
#define HEATER_0_PIN 10
|
||||
#define HEATER_BED_PIN 8
|
||||
#define FAN_PIN 9
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 9
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
//
|
||||
// MOSFET changes
|
||||
//
|
||||
#define RAMPS_D10_PIN 9 // EXTRUDER 1
|
||||
#define MOSFET_D_PIN 12 // EXTRUDER 2 or FAN
|
||||
#define RAMPS_D10_PIN 9 // EXTRUDER 1
|
||||
#define MOSFET_D_PIN 12 // EXTRUDER 2 or FAN
|
||||
|
||||
#include "pins_RAMPS.h"
|
||||
|
||||
@@ -74,9 +74,9 @@
|
||||
// SPI for Max6675 or Max31855 Thermocouple
|
||||
#undef MAX6675_SS
|
||||
#if DISABLED(SDSUPPORT)
|
||||
#define MAX6675_SS 53 // Don't use pin 53 if there is even the remote possibility of using Display/SD card
|
||||
#define MAX6675_SS 53 // Don't use pin 53 if there is even the remote possibility of using Display/SD card
|
||||
#else
|
||||
#define MAX6675_SS 49 // Don't use pin 49 as this is tied to the switch inside the SD card socket to detect if there is an SD card present
|
||||
#define MAX6675_SS 49 // Don't use pin 49 as this is tied to the switch inside the SD card socket to detect if there is an SD card present
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -85,8 +85,9 @@
|
||||
#undef HEATER_BED_PIN
|
||||
#define HEATER_BED_PIN 10
|
||||
|
||||
#undef FAN_PIN
|
||||
#define FAN_PIN 8 // Same as RAMPS_13_EEF
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 8 // Same as RAMPS_13_EEF
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -39,12 +39,12 @@
|
||||
// Channels available for DAC, For Rigidboard there are 4
|
||||
#define DAC_STEPPER_ORDER { 0, 1, 2, 3 }
|
||||
|
||||
#define DAC_STEPPER_SENSE 0.05 // sense resistors on rigidboard stepper chips are .05 value
|
||||
#define DAC_STEPPER_SENSE 0.05 // sense resistors on rigidboard stepper chips are .05 value
|
||||
#define DAC_STEPPER_ADDRESS 0
|
||||
#define DAC_STEPPER_MAX 4096 // was 5000 but max allowable value is actually 4096
|
||||
#define DAC_STEPPER_VREF 1 // internal Vref, gain 2x = 4.096V
|
||||
#define DAC_STEPPER_GAIN 1 // value of 1 here sets gain of 2
|
||||
#define DAC_DISABLE_PIN 42 // set low to enable DAC
|
||||
#define DAC_STEPPER_MAX 4096 // was 5000 but max allowable value is actually 4096
|
||||
#define DAC_STEPPER_VREF 1 // internal Vref, gain 2x = 4.096V
|
||||
#define DAC_STEPPER_GAIN 1 // value of 1 here sets gain of 2
|
||||
#define DAC_DISABLE_PIN 42 // set low to enable DAC
|
||||
#define DAC_OR_ADDRESS 0x01
|
||||
|
||||
#ifndef DAC_MOTOR_CURRENT_DEFAULT
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
#define Z_ENABLE_PIN 26
|
||||
#define E0_ENABLE_PIN 14
|
||||
|
||||
#if ENABLED(LCD_I2C_PANELOLU2)
|
||||
#if !defined(FAN_PIN) && ENABLED(LCD_I2C_PANELOLU2)
|
||||
#define FAN_PIN 4 // Uses Transistor1 (PWM) on Panelolu2's Sanguino Adapter Board to drive the fan
|
||||
#endif
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if MB(AZTEEG_X1) || MB(STB_11) || ENABLED(IS_MELZI)
|
||||
#if !defined(FAN_PIN) && (MB(AZTEEG_X1) || MB(STB_11) || ENABLED(IS_MELZI))
|
||||
#define FAN_PIN 4 // Works for Panelolu2 too
|
||||
#endif
|
||||
|
||||
|
||||
@@ -114,7 +114,9 @@
|
||||
#define HEATER_0_PIN 15 // C5 PWM3B - Extruder
|
||||
#define HEATER_BED_PIN 14 // C4 PWM3C - Bed
|
||||
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
#define E1_MS2_PIN 64
|
||||
|
||||
#define DIGIPOTSS_PIN 38
|
||||
#define DIGIPOT_CHANNELS {4,5,3,0,1} // X Y Z E0 E1 digipot channels to stepper driver mapping
|
||||
#define DIGIPOT_CHANNELS {4,5,3,0,1} // X Y Z E0 E1 digipot channels to stepper driver mapping
|
||||
|
||||
//
|
||||
// Temperature Sensors
|
||||
@@ -106,7 +106,9 @@
|
||||
#define HEATER_1_PIN 7
|
||||
#define HEATER_BED_PIN 3
|
||||
|
||||
#define FAN_PIN 8
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 8
|
||||
#endif
|
||||
#define FAN1_PIN 6
|
||||
#define FAN2_PIN 2
|
||||
|
||||
|
||||
+7
-6
@@ -98,12 +98,13 @@
|
||||
#define HEATER_0_PIN 4
|
||||
#define HEATER_BED_PIN 3
|
||||
|
||||
|
||||
#if GEN7_VERSION >= 13
|
||||
// Gen7 v1.3 removed the fan pin
|
||||
#define FAN_PIN -1
|
||||
#else
|
||||
#define FAN_PIN 31
|
||||
#ifndef FAN_PIN
|
||||
#if GEN7_VERSION >= 13
|
||||
// Gen7 v1.3 removed the fan pin
|
||||
#define FAN_PIN -1
|
||||
#else
|
||||
#define FAN_PIN 31
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
@@ -56,7 +56,9 @@
|
||||
#define FIL_RUNOUT_PIN 34 // X_MAX unless overridden
|
||||
#endif
|
||||
|
||||
#define FAN_PIN 5
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 5
|
||||
#endif
|
||||
|
||||
#define HEATER_0_PIN 7
|
||||
|
||||
|
||||
@@ -149,7 +149,9 @@
|
||||
//
|
||||
#define HEATER_0_PIN 15 // C5 PWM3B Extruder
|
||||
#define HEATER_BED_PIN 14 // C4 PWM3C
|
||||
#define FAN_PIN 16 // C6 PWM3A Fan
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 16 // C6 PWM3A Fan
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -127,7 +127,9 @@
|
||||
#define HEATER_0_PIN 15 // C5 PWM3B - Extruder
|
||||
#define HEATER_BED_PIN 14 // C4 PWM3C
|
||||
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 16 // C6 PWM3A
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
#endif
|
||||
|
||||
#define IS_RAMPS_EFB
|
||||
#define RAMPS_D9_PIN 44
|
||||
#define ORIG_E0_AUTO_FAN_PIN RAMPS_D9_PIN
|
||||
#define RAMPS_D9_PIN 44
|
||||
#define FAN2_PIN 9
|
||||
#define ORIG_E0_AUTO_FAN_PIN 9
|
||||
|
||||
#include "pins_RAMPS_13.h"
|
||||
|
||||
|
||||
@@ -30,11 +30,7 @@
|
||||
|
||||
#define IS_RAMPS_EFB
|
||||
|
||||
#include "pins_RAMPS_13.h"
|
||||
#define FAN2_PIN 44
|
||||
#define ORIG_E0_AUTO_FAN_PIN 44
|
||||
|
||||
#define FAN2_PIN 44
|
||||
|
||||
#undef E1_STEP_PIN
|
||||
#undef E1_DIR_PIN
|
||||
#undef E1_ENABLE_PIN
|
||||
#undef E1_CS_PIN
|
||||
#include "pins_RAMPS.h"
|
||||
|
||||
@@ -93,7 +93,9 @@
|
||||
#define HEATER_1_PIN 3
|
||||
#define HEATER_BED_PIN 4
|
||||
|
||||
#define FAN_PIN 7
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 7
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
@@ -99,7 +99,9 @@
|
||||
#define HEATER_1_PIN 3
|
||||
#define HEATER_BED_PIN 4
|
||||
|
||||
#define FAN_PIN 7
|
||||
#ifndef FAN_PIN
|
||||
#define FAN_PIN 7
|
||||
#endif
|
||||
|
||||
//
|
||||
// Misc. Functions
|
||||
|
||||
+357
-309
File diff suppressed because it is too large
Load Diff
+91
-55
@@ -49,9 +49,6 @@ enum BlockFlagBit : char {
|
||||
// from a safe speed (in consideration of jerking from zero speed).
|
||||
BLOCK_BIT_NOMINAL_LENGTH,
|
||||
|
||||
// The block is busy, being interpreted by the stepper ISR
|
||||
BLOCK_BIT_BUSY,
|
||||
|
||||
// The block is segment 2+ of a longer move
|
||||
BLOCK_BIT_CONTINUED,
|
||||
|
||||
@@ -62,7 +59,6 @@ enum BlockFlagBit : char {
|
||||
enum BlockFlag : char {
|
||||
BLOCK_FLAG_RECALCULATE = _BV(BLOCK_BIT_RECALCULATE),
|
||||
BLOCK_FLAG_NOMINAL_LENGTH = _BV(BLOCK_BIT_NOMINAL_LENGTH),
|
||||
BLOCK_FLAG_BUSY = _BV(BLOCK_BIT_BUSY),
|
||||
BLOCK_FLAG_CONTINUED = _BV(BLOCK_BIT_CONTINUED),
|
||||
BLOCK_FLAG_SYNC_POSITION = _BV(BLOCK_BIT_SYNC_POSITION)
|
||||
};
|
||||
@@ -78,7 +74,7 @@ enum BlockFlag : char {
|
||||
*/
|
||||
typedef struct {
|
||||
|
||||
uint8_t flag; // Block flags (See BlockFlag enum above)
|
||||
volatile uint8_t flag; // Block flags (See BlockFlag enum above) - Modified by ISR and main thread!
|
||||
|
||||
// Fields used by the motion planner to manage acceleration
|
||||
float nominal_speed_sqr, // The nominal speed for this block in (mm/sec)^2
|
||||
@@ -103,18 +99,18 @@ typedef struct {
|
||||
uint8_t active_extruder; // The extruder to move (if E move)
|
||||
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
uint32_t mix_event_count[MIXING_STEPPERS]; // Scaled step_event_count for the mixing steppers
|
||||
uint32_t mix_steps[MIXING_STEPPERS]; // Scaled steps[E_AXIS] for the mixing steppers
|
||||
#endif
|
||||
|
||||
// Settings for the trapezoid generator
|
||||
uint32_t accelerate_until, // The index of the step event on which to stop acceleration
|
||||
decelerate_after; // The index of the step event on which to start decelerating
|
||||
|
||||
#if ENABLED(BEZIER_JERK_CONTROL)
|
||||
uint32_t cruise_rate; // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase
|
||||
uint32_t acceleration_time, // Acceleration time and deceleration time in STEP timer counts
|
||||
deceleration_time;
|
||||
uint32_t acceleration_time_inverse, // Inverse of acceleration and deceleration periods, expressed as integer. Scale depends on CPU being used
|
||||
#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
|
||||
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; // The acceleration rate used for acceleration calculation
|
||||
@@ -125,7 +121,7 @@ typedef struct {
|
||||
// Advance extrusion
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
bool use_advance_lead;
|
||||
uint16_t advance_speed, // Timer value for extruder speed offset
|
||||
uint16_t advance_speed, // STEP timer value for extruder speed offset ISR
|
||||
max_adv_steps, // max. advance steps to get cruising speed pressure (not always nominal_speed!)
|
||||
final_adv_steps; // advance steps due to exit speed
|
||||
float e_D_ratio;
|
||||
@@ -148,7 +144,7 @@ typedef struct {
|
||||
|
||||
} block_t;
|
||||
|
||||
#define HAS_POSITION_FLOAT (ENABLED(LIN_ADVANCE) || ENABLED(SCARA_FEEDRATE_SCALING))
|
||||
#define HAS_POSITION_FLOAT (ENABLED(LIN_ADVANCE) || HAS_FEEDRATE_SCALING)
|
||||
|
||||
#define BLOCK_MOD(n) ((n)&(BLOCK_BUFFER_SIZE-1))
|
||||
|
||||
@@ -170,11 +166,12 @@ 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
|
||||
block_buffer_planned; // Index of the optimally planned block
|
||||
|
||||
static uint8_t delay_before_delivering; // This counter delays delivery of blocks when queue becomes empty to allow the opportunity of merging blocks
|
||||
|
||||
|
||||
#if ENABLED(DISTINCT_E_FACTORS)
|
||||
static uint8_t last_extruder; // Respond to extruder change
|
||||
@@ -191,19 +188,30 @@ class Planner {
|
||||
// May be auto-adjusted by a filament width sensor
|
||||
#endif
|
||||
|
||||
static float max_feedrate_mm_s[XYZE_N], // Max speeds in mm per second
|
||||
axis_steps_per_mm[XYZE_N],
|
||||
steps_to_mm[XYZE_N];
|
||||
static uint32_t max_acceleration_steps_per_s2[XYZE_N],
|
||||
max_acceleration_mm_per_s2[XYZE_N]; // Use M201 to override
|
||||
static uint32_t max_acceleration_mm_per_s2[XYZE_N], // (mm/s^2) M201 XYZE
|
||||
max_acceleration_steps_per_s2[XYZE_N], // (steps/s^2) Derived from mm_per_s2
|
||||
min_segment_time_us; // (µs) M205 B
|
||||
static float max_feedrate_mm_s[XYZE_N], // (mm/s) M203 XYZE - Max speeds
|
||||
axis_steps_per_mm[XYZE_N], // (steps) M92 XYZE - Steps per millimeter
|
||||
steps_to_mm[XYZE_N], // (mm) Millimeters per step
|
||||
min_feedrate_mm_s, // (mm/s) M205 S - Minimum linear feedrate
|
||||
acceleration, // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
|
||||
retract_acceleration, // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
|
||||
travel_acceleration, // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
|
||||
min_travel_feedrate_mm_s; // (mm/s) M205 T - Minimum travel feedrate
|
||||
|
||||
static uint32_t min_segment_time_us; // Use 'M205 B<µs>' to override
|
||||
static float min_feedrate_mm_s,
|
||||
acceleration, // Normal acceleration mm/s^2 DEFAULT ACCELERATION for all printing moves. M204 SXXXX
|
||||
retract_acceleration, // Retract acceleration mm/s^2 filament pull-back and push-forward while standing still in the other axes M204 TXXXX
|
||||
travel_acceleration, // Travel acceleration mm/s^2 DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX
|
||||
max_jerk[XYZE], // The largest speed change requiring no acceleration
|
||||
min_travel_feedrate_mm_s;
|
||||
#if ENABLED(JUNCTION_DEVIATION)
|
||||
static float junction_deviation_mm; // (mm) M205 J
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
#if ENABLED(DISTINCT_E_FACTORS)
|
||||
static float max_e_jerk[EXTRUDERS]; // Calculated from junction_deviation_mm
|
||||
#else
|
||||
static float max_e_jerk;
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
static float max_jerk[XYZE]; // (mm/s^2) M205 XYZE - The largest speed change requiring no acceleration.
|
||||
#endif
|
||||
|
||||
#if HAS_LEVELING
|
||||
static bool leveling_active; // Flag that bed leveling is enabled
|
||||
@@ -311,7 +319,7 @@ class Planner {
|
||||
static void refresh_positioning();
|
||||
|
||||
FORCE_INLINE static void refresh_e_factor(const uint8_t e) {
|
||||
e_factor[e] = (flow_percentage[e] * 0.01
|
||||
e_factor[e] = (flow_percentage[e] * 0.01f
|
||||
#if DISABLED(NO_VOLUMETRICS)
|
||||
* volumetric_multiplier[e]
|
||||
#endif
|
||||
@@ -349,19 +357,19 @@ class Planner {
|
||||
* Returns 0.0 if Z is past the specified 'Fade Height'.
|
||||
*/
|
||||
inline static float fade_scaling_factor_for_z(const float &rz) {
|
||||
static float z_fade_factor = 1.0;
|
||||
static float z_fade_factor = 1;
|
||||
if (z_fade_height) {
|
||||
if (rz >= z_fade_height) return 0.0;
|
||||
if (rz >= z_fade_height) return 0;
|
||||
if (last_fade_z != rz) {
|
||||
last_fade_z = rz;
|
||||
z_fade_factor = 1.0 - rz * inverse_z_fade_height;
|
||||
z_fade_factor = 1 - rz * inverse_z_fade_height;
|
||||
}
|
||||
return z_fade_factor;
|
||||
}
|
||||
return 1.0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE static void force_fade_recalc() { last_fade_z = -999.999; }
|
||||
FORCE_INLINE static void force_fade_recalc() { last_fade_z = -999.999f; }
|
||||
|
||||
FORCE_INLINE static void set_z_fade_height(const float &zfh) {
|
||||
z_fade_height = zfh > 0 ? zfh : 0;
|
||||
@@ -377,7 +385,7 @@ class Planner {
|
||||
|
||||
FORCE_INLINE static float fade_scaling_factor_for_z(const float &rz) {
|
||||
UNUSED(rz);
|
||||
return 1.0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE static bool leveling_active_at_z(const float &rz) { UNUSED(rz); return true; }
|
||||
@@ -428,11 +436,14 @@ class Planner {
|
||||
#define ARG_Z const float &rz
|
||||
#endif
|
||||
|
||||
// Number of moves currently in the planner
|
||||
// Number of moves currently in the planner including the busy block, if any
|
||||
FORCE_INLINE static uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail); }
|
||||
|
||||
// Number of nonbusy moves currently in the planner
|
||||
FORCE_INLINE static uint8_t nonbusy_movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_nonbusy); }
|
||||
|
||||
// Remove all blocks from the buffer
|
||||
FORCE_INLINE static void clear_block_buffer() { block_buffer_head = block_buffer_tail = 0; }
|
||||
FORCE_INLINE static void clear_block_buffer() { block_buffer_nonbusy = block_buffer_planned = 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); }
|
||||
@@ -634,7 +645,7 @@ class Planner {
|
||||
static block_t* get_current_block() {
|
||||
|
||||
// Get the number of moves in the planner queue so far
|
||||
uint8_t nr_moves = movesplanned();
|
||||
const uint8_t nr_moves = movesplanned();
|
||||
|
||||
// If there are any moves queued ...
|
||||
if (nr_moves) {
|
||||
@@ -658,8 +669,14 @@ class Planner {
|
||||
block_buffer_runtime_us -= block->segment_time_us; // We can't be sure how long an active block will take, so don't count it.
|
||||
#endif
|
||||
|
||||
// Mark the block as busy, so the planner does not attempt to replan it
|
||||
SBI(block->flag, BLOCK_BIT_BUSY);
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -677,27 +694,18 @@ class Planner {
|
||||
* NB: There MUST be a current block to call this function!!
|
||||
*/
|
||||
FORCE_INLINE static void discard_current_block() {
|
||||
if (has_blocks_queued()) { // Discard non-empty buffer.
|
||||
uint8_t block_index = next_block_index( block_buffer_tail );
|
||||
|
||||
// Push block_buffer_planned pointer, if encountered.
|
||||
if (!has_blocks_queued()) block_buffer_planned = block_index;
|
||||
|
||||
block_buffer_tail = block_index;
|
||||
}
|
||||
if (has_blocks_queued())
|
||||
block_buffer_tail = next_block_index(block_buffer_tail);
|
||||
}
|
||||
|
||||
#if ENABLED(ULTRA_LCD)
|
||||
|
||||
static uint16_t block_buffer_runtime() {
|
||||
// Protect the access to the variable. Only required for AVR, as
|
||||
// any 32bit CPU offers atomic access to 32bit variables
|
||||
bool was_enabled = STEPPER_ISR_ENABLED();
|
||||
if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
millis_t bbru = block_buffer_runtime_us;
|
||||
|
||||
// Reenable Stepper ISR
|
||||
if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
// To translate µs to ms a division by 1000 would be required.
|
||||
@@ -710,14 +718,11 @@ class Planner {
|
||||
}
|
||||
|
||||
static void clear_block_buffer_runtime() {
|
||||
// Protect the access to the variable. Only required for AVR, as
|
||||
// any 32bit CPU offers atomic access to 32bit variables
|
||||
bool was_enabled = STEPPER_ISR_ENABLED();
|
||||
if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
block_buffer_runtime_us = 0;
|
||||
|
||||
// Reenable Stepper ISR
|
||||
if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
}
|
||||
|
||||
@@ -730,6 +735,20 @@ class Planner {
|
||||
static void autotemp_M104_M109();
|
||||
#endif
|
||||
|
||||
#if ENABLED(JUNCTION_DEVIATION)
|
||||
FORCE_INLINE static void recalculate_max_e_jerk() {
|
||||
#define GET_MAX_E_JERK(N) SQRT(SQRT(0.5) * junction_deviation_mm * (N) * RECIPROCAL(1.0 - SQRT(0.5)))
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
#if ENABLED(DISTINCT_E_FACTORS)
|
||||
for (uint8_t i = 0; i < EXTRUDERS; i++)
|
||||
max_e_jerk[i] = GET_MAX_E_JERK(max_acceleration_mm_per_s2[E_AXIS + i]);
|
||||
#else
|
||||
max_e_jerk = GET_MAX_E_JERK(max_acceleration_mm_per_s2[E_AXIS]);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
@@ -769,7 +788,7 @@ class Planner {
|
||||
return target_velocity_sqr - 2 * accel * distance;
|
||||
}
|
||||
|
||||
#if ENABLED(BEZIER_JERK_CONTROL)
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
/**
|
||||
* Calculate the speed reached given initial speed, acceleration and distance
|
||||
*/
|
||||
@@ -790,6 +809,23 @@ class Planner {
|
||||
|
||||
static void recalculate();
|
||||
|
||||
#if ENABLED(JUNCTION_DEVIATION)
|
||||
|
||||
FORCE_INLINE static void normalize_junction_vector(float (&vector)[XYZE]) {
|
||||
float magnitude_sq = 0;
|
||||
LOOP_XYZE(idx) if (vector[idx]) magnitude_sq += sq(vector[idx]);
|
||||
const float inv_magnitude = RSQRT(magnitude_sq);
|
||||
LOOP_XYZE(idx) vector[idx] *= inv_magnitude;
|
||||
}
|
||||
|
||||
FORCE_INLINE static float limit_value_by_axis_maximum(const float &max_value, float (&unit_vec)[XYZE]) {
|
||||
float limit_value = max_value;
|
||||
LOOP_XYZE(idx) if (unit_vec[idx]) // Avoid divide by zero
|
||||
NOMORE(limit_value, ABS(max_acceleration_mm_per_s2[idx] / unit_vec[idx]));
|
||||
return limit_value;
|
||||
}
|
||||
|
||||
#endif // JUNCTION_DEVIATION
|
||||
};
|
||||
|
||||
#define PLANNER_XY_FEEDRATE() (MIN(planner.max_feedrate_mm_s[X_AXIS], planner.max_feedrate_mm_s[Y_AXIS]))
|
||||
|
||||
+14
-14
@@ -37,12 +37,12 @@
|
||||
#include "Marlin.h"
|
||||
|
||||
// See the meaning in the documentation of cubic_b_spline().
|
||||
#define MIN_STEP 0.002
|
||||
#define MAX_STEP 0.1
|
||||
#define SIGMA 0.1
|
||||
#define MIN_STEP 0.002f
|
||||
#define MAX_STEP 0.1f
|
||||
#define SIGMA 0.1f
|
||||
|
||||
// Compute the linear interpolation between two real numbers.
|
||||
inline static float interp(float a, float b, float t) { return (1.0 - t) * a + t * b; }
|
||||
inline static float interp(float a, float b, float t) { return (1.0f - t) * a + t * b; }
|
||||
|
||||
/**
|
||||
* Compute a Bézier curve using the De Casteljau's algorithm (see
|
||||
@@ -111,7 +111,7 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
|
||||
first1 = position[Y_AXIS] + offset[1],
|
||||
second0 = target[X_AXIS] + offset[2],
|
||||
second1 = target[Y_AXIS] + offset[3];
|
||||
float t = 0.0;
|
||||
float t = 0;
|
||||
|
||||
float bez_target[4];
|
||||
bez_target[X_AXIS] = position[X_AXIS];
|
||||
@@ -120,7 +120,7 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
|
||||
|
||||
millis_t next_idle_ms = millis() + 200UL;
|
||||
|
||||
while (t < 1.0) {
|
||||
while (t < 1) {
|
||||
|
||||
thermalManager.manage_heater();
|
||||
millis_t now = millis();
|
||||
@@ -133,16 +133,16 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
|
||||
// close to a linear interpolation.
|
||||
bool did_reduce = false;
|
||||
float new_t = t + step;
|
||||
NOMORE(new_t, 1.0);
|
||||
NOMORE(new_t, 1);
|
||||
float new_pos0 = eval_bezier(position[X_AXIS], first0, second0, target[X_AXIS], new_t),
|
||||
new_pos1 = eval_bezier(position[Y_AXIS], first1, second1, target[Y_AXIS], new_t);
|
||||
for (;;) {
|
||||
if (new_t - t < (MIN_STEP)) break;
|
||||
const float candidate_t = 0.5 * (t + new_t),
|
||||
const float candidate_t = 0.5f * (t + new_t),
|
||||
candidate_pos0 = eval_bezier(position[X_AXIS], first0, second0, target[X_AXIS], candidate_t),
|
||||
candidate_pos1 = eval_bezier(position[Y_AXIS], first1, second1, target[Y_AXIS], candidate_t),
|
||||
interp_pos0 = 0.5 * (bez_target[X_AXIS] + new_pos0),
|
||||
interp_pos1 = 0.5 * (bez_target[Y_AXIS] + new_pos1);
|
||||
interp_pos0 = 0.5f * (bez_target[X_AXIS] + new_pos0),
|
||||
interp_pos1 = 0.5f * (bez_target[Y_AXIS] + new_pos1);
|
||||
if (dist1(candidate_pos0, candidate_pos1, interp_pos0, interp_pos1) <= (SIGMA)) break;
|
||||
new_t = candidate_t;
|
||||
new_pos0 = candidate_pos0;
|
||||
@@ -153,12 +153,12 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
|
||||
// If we did not reduce the step, maybe we should enlarge it.
|
||||
if (!did_reduce) for (;;) {
|
||||
if (new_t - t > MAX_STEP) break;
|
||||
const float candidate_t = t + 2.0 * (new_t - t);
|
||||
if (candidate_t >= 1.0) break;
|
||||
const float candidate_t = t + 2 * (new_t - t);
|
||||
if (candidate_t >= 1) break;
|
||||
const float candidate_pos0 = eval_bezier(position[X_AXIS], first0, second0, target[X_AXIS], candidate_t),
|
||||
candidate_pos1 = eval_bezier(position[Y_AXIS], first1, second1, target[Y_AXIS], candidate_t),
|
||||
interp_pos0 = 0.5 * (bez_target[X_AXIS] + candidate_pos0),
|
||||
interp_pos1 = 0.5 * (bez_target[Y_AXIS] + candidate_pos1);
|
||||
interp_pos0 = 0.5f * (bez_target[X_AXIS] + candidate_pos0),
|
||||
interp_pos1 = 0.5f * (bez_target[Y_AXIS] + candidate_pos1);
|
||||
if (dist1(new_pos0, new_pos1, interp_pos0, interp_pos1) > (SIGMA)) break;
|
||||
new_t = candidate_t;
|
||||
new_pos0 = candidate_pos0;
|
||||
|
||||
@@ -42,58 +42,76 @@ job_recovery_info_t job_recovery_info;
|
||||
JobRecoveryPhase job_recovery_phase = JOB_RECOVERY_IDLE;
|
||||
uint8_t job_recovery_commands_count; //=0
|
||||
char job_recovery_commands[BUFSIZE + APPEND_CMD_COUNT][MAX_CMD_SIZE];
|
||||
|
||||
// Extern
|
||||
extern uint8_t commands_in_queue, cmd_queue_index_r;
|
||||
|
||||
// Private
|
||||
static char sd_filename[MAXPATHNAMELENGTH];
|
||||
extern uint8_t active_extruder, commands_in_queue, cmd_queue_index_r;
|
||||
|
||||
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
|
||||
void debug_print_job_recovery(const bool recovery) {
|
||||
SERIAL_PROTOCOLPAIR("valid_head:", (int)job_recovery_info.valid_head);
|
||||
SERIAL_PROTOCOLLNPAIR(" valid_foot:", (int)job_recovery_info.valid_foot);
|
||||
SERIAL_PROTOCOLLNPGM("---- Job Recovery Info ----");
|
||||
SERIAL_PROTOCOLPAIR("valid_head:", int(job_recovery_info.valid_head));
|
||||
SERIAL_PROTOCOLLNPAIR(" valid_foot:", int(job_recovery_info.valid_foot));
|
||||
if (job_recovery_info.valid_head) {
|
||||
if (job_recovery_info.valid_head == job_recovery_info.valid_foot) {
|
||||
SERIAL_PROTOCOLPGM("current_position");
|
||||
LOOP_XYZE(i) SERIAL_PROTOCOLPAIR(": ", job_recovery_info.current_position[i]);
|
||||
SERIAL_PROTOCOLPGM("current_position: ");
|
||||
LOOP_XYZE(i) {
|
||||
SERIAL_PROTOCOL(job_recovery_info.current_position[i]);
|
||||
if (i < E_AXIS) SERIAL_CHAR(',');
|
||||
}
|
||||
SERIAL_EOL();
|
||||
SERIAL_PROTOCOLLNPAIR("feedrate: ", job_recovery_info.feedrate);
|
||||
SERIAL_PROTOCOLPGM("target_temperature");
|
||||
HOTEND_LOOP() SERIAL_PROTOCOLPAIR(": ", job_recovery_info.target_temperature[e]);
|
||||
SERIAL_EOL();
|
||||
SERIAL_PROTOCOLPGM("fanSpeeds");
|
||||
for(uint8_t i = 0; i < FAN_COUNT; i++) SERIAL_PROTOCOLPAIR(": ", job_recovery_info.fanSpeeds[i]);
|
||||
|
||||
#if HOTENDS > 1
|
||||
SERIAL_PROTOCOLLNPAIR("active_hotend: ", int(job_recovery_info.active_hotend));
|
||||
#endif
|
||||
|
||||
SERIAL_PROTOCOLPGM("target_temperature: ");
|
||||
HOTEND_LOOP() {
|
||||
SERIAL_PROTOCOL(job_recovery_info.target_temperature[e]);
|
||||
if (e < HOTENDS - 1) SERIAL_CHAR(',');
|
||||
}
|
||||
SERIAL_EOL();
|
||||
|
||||
#if HAS_HEATED_BED
|
||||
SERIAL_PROTOCOLLNPAIR("target_temperature_bed: ", job_recovery_info.target_temperature_bed);
|
||||
#endif
|
||||
|
||||
#if FAN_COUNT
|
||||
SERIAL_PROTOCOLPGM("fanSpeeds: ");
|
||||
for (int8_t i = 0; i < FAN_COUNT; i++) {
|
||||
SERIAL_PROTOCOL(job_recovery_info.fanSpeeds[i]);
|
||||
if (i < FAN_COUNT - 1) SERIAL_CHAR(',');
|
||||
}
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
|
||||
#if HAS_LEVELING
|
||||
SERIAL_PROTOCOLPAIR("leveling: ", int(job_recovery_info.leveling));
|
||||
SERIAL_PROTOCOLLNPAIR(" fade: ", int(job_recovery_info.fade));
|
||||
#endif
|
||||
#if HAS_HEATED_BED
|
||||
SERIAL_PROTOCOLLNPAIR("target_temperature_bed: ", job_recovery_info.target_temperature_bed);
|
||||
#endif
|
||||
SERIAL_PROTOCOLLNPAIR("cmd_queue_index_r: ", job_recovery_info.cmd_queue_index_r);
|
||||
SERIAL_PROTOCOLLNPAIR("commands_in_queue: ", job_recovery_info.commands_in_queue);
|
||||
SERIAL_PROTOCOLLNPAIR("cmd_queue_index_r: ", int(job_recovery_info.cmd_queue_index_r));
|
||||
SERIAL_PROTOCOLLNPAIR("commands_in_queue: ", int(job_recovery_info.commands_in_queue));
|
||||
if (recovery)
|
||||
for (uint8_t i = 0; i < job_recovery_commands_count; i++) SERIAL_PROTOCOLLNPAIR("> ", job_recovery_commands[i]);
|
||||
else
|
||||
for (uint8_t i = 0; i < job_recovery_info.commands_in_queue; i++) SERIAL_PROTOCOLLNPAIR("> ", job_recovery_info.command_queue[i]);
|
||||
SERIAL_PROTOCOLLNPAIR("sd_filename: ", sd_filename);
|
||||
SERIAL_PROTOCOLLNPAIR("sd_filename: ", job_recovery_info.sd_filename);
|
||||
SERIAL_PROTOCOLLNPAIR("sdpos: ", job_recovery_info.sdpos);
|
||||
SERIAL_PROTOCOLLNPAIR("print_job_elapsed: ", job_recovery_info.print_job_elapsed);
|
||||
}
|
||||
else
|
||||
SERIAL_PROTOCOLLNPGM("INVALID DATA");
|
||||
}
|
||||
SERIAL_PROTOCOLLNPGM("---------------------------");
|
||||
}
|
||||
#endif // DEBUG_POWER_LOSS_RECOVERY
|
||||
|
||||
/**
|
||||
* Check for Print Job Recovery
|
||||
* If the file has a saved state, populate the job_recovery_commands queue
|
||||
* Check for Print Job Recovery during setup()
|
||||
*
|
||||
* If a saved state exists, populate job_recovery_commands with
|
||||
* commands to restore the machine state and continue the file.
|
||||
*/
|
||||
void do_print_job_recovery() {
|
||||
//if (job_recovery_commands_count > 0) return;
|
||||
void check_print_job_recovery() {
|
||||
memset(&job_recovery_info, 0, sizeof(job_recovery_info));
|
||||
ZERO(job_recovery_commands);
|
||||
|
||||
@@ -102,7 +120,7 @@ void do_print_job_recovery() {
|
||||
if (card.cardOK) {
|
||||
|
||||
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
|
||||
SERIAL_PROTOCOLLNPAIR("Init job recovery info. Size: ", (int)sizeof(job_recovery_info));
|
||||
SERIAL_PROTOCOLLNPAIR("Init job recovery info. Size: ", int(sizeof(job_recovery_info)));
|
||||
#endif
|
||||
|
||||
if (card.jobRecoverFileExists()) {
|
||||
@@ -122,7 +140,9 @@ void do_print_job_recovery() {
|
||||
strcpy_P(job_recovery_commands[ind++], PSTR("G92.0 Z0")); // Ensure Z is equal to 0
|
||||
strcpy_P(job_recovery_commands[ind++], PSTR("G1 Z2")); // Raise Z by 2mm (we hope!)
|
||||
strcpy_P(job_recovery_commands[ind++], PSTR("G28 R0"
|
||||
#if !IS_KINEMATIC
|
||||
#if ENABLED(MARLIN_DEV_MODE)
|
||||
" S"
|
||||
#elif !IS_KINEMATIC
|
||||
" X Y" // Home X and Y for Cartesian
|
||||
#endif
|
||||
));
|
||||
@@ -130,10 +150,12 @@ void do_print_job_recovery() {
|
||||
char str_1[16], str_2[16];
|
||||
|
||||
#if HAS_LEVELING
|
||||
// Restore leveling state before G92 sets Z
|
||||
// This ensures the steppers correspond to the native Z
|
||||
dtostrf(job_recovery_info.fade, 1, 1, str_1);
|
||||
sprintf_P(job_recovery_commands[ind++], PSTR("M420 S%i Z%s"), int(job_recovery_info.leveling), str_1);
|
||||
if (job_recovery_info.fade || job_recovery_info.leveling) {
|
||||
// Restore leveling state before G92 sets Z
|
||||
// This ensures the steppers correspond to the native Z
|
||||
dtostrf(job_recovery_info.fade, 1, 1, str_1);
|
||||
sprintf_P(job_recovery_commands[ind++], PSTR("M420 S%i Z%s"), int(job_recovery_info.leveling), str_1);
|
||||
}
|
||||
#endif
|
||||
|
||||
dtostrf(job_recovery_info.current_position[Z_AXIS] + 2, 1, 3, str_1);
|
||||
@@ -145,23 +167,21 @@ void do_print_job_recovery() {
|
||||
);
|
||||
sprintf_P(job_recovery_commands[ind++], PSTR("G92.0 Z%s E%s"), str_1, str_2); // Current Z + 2 and E
|
||||
|
||||
strcpy_P(job_recovery_commands[ind++], PSTR("M117 Continuing..."));
|
||||
|
||||
uint8_t r = job_recovery_info.cmd_queue_index_r;
|
||||
while (job_recovery_info.commands_in_queue) {
|
||||
uint8_t r = job_recovery_info.cmd_queue_index_r, c = job_recovery_info.commands_in_queue;
|
||||
while (c--) {
|
||||
strcpy(job_recovery_commands[ind++], job_recovery_info.command_queue[r]);
|
||||
job_recovery_info.commands_in_queue--;
|
||||
r = (r + 1) % BUFSIZE;
|
||||
}
|
||||
|
||||
if (job_recovery_info.sd_filename[0] == '/') job_recovery_info.sd_filename[0] = ' ';
|
||||
sprintf_P(job_recovery_commands[ind++], PSTR("M23 %s"), job_recovery_info.sd_filename);
|
||||
sprintf_P(job_recovery_commands[ind++], PSTR("M24 S%ld T%ld"), job_recovery_info.sdpos, job_recovery_info.print_job_elapsed);
|
||||
|
||||
job_recovery_commands_count = ind;
|
||||
|
||||
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
|
||||
debug_print_job_recovery(true);
|
||||
#endif
|
||||
|
||||
card.openFile(sd_filename, true);
|
||||
card.setIndex(job_recovery_info.sdpos);
|
||||
}
|
||||
else {
|
||||
if (job_recovery_info.valid_head != job_recovery_info.valid_foot)
|
||||
@@ -173,7 +193,7 @@ void do_print_job_recovery() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current machine state to the "bin" file
|
||||
* Save the current machine state to the power-loss recovery file
|
||||
*/
|
||||
void save_job_recovery_info() {
|
||||
#if SAVE_INFO_INTERVAL_MS > 0
|
||||
@@ -201,11 +221,20 @@ void save_job_recovery_info() {
|
||||
// Machine state
|
||||
COPY(job_recovery_info.current_position, current_position);
|
||||
job_recovery_info.feedrate = feedrate_mm_s;
|
||||
|
||||
#if HOTENDS > 1
|
||||
job_recovery_info.active_hotend = active_extruder;
|
||||
#endif
|
||||
|
||||
COPY(job_recovery_info.target_temperature, thermalManager.target_temperature);
|
||||
|
||||
#if HAS_HEATED_BED
|
||||
job_recovery_info.target_temperature_bed = thermalManager.target_temperature_bed;
|
||||
#endif
|
||||
COPY(job_recovery_info.fanSpeeds, fanSpeeds);
|
||||
|
||||
#if FAN_COUNT
|
||||
COPY(job_recovery_info.fanSpeeds, fanSpeeds);
|
||||
#endif
|
||||
|
||||
#if HAS_LEVELING
|
||||
job_recovery_info.leveling = planner.leveling_active;
|
||||
@@ -224,14 +253,14 @@ void save_job_recovery_info() {
|
||||
COPY(job_recovery_info.command_queue, command_queue);
|
||||
|
||||
// Elapsed print job time
|
||||
job_recovery_info.print_job_elapsed = print_job_timer.duration() * 1000UL;
|
||||
job_recovery_info.print_job_elapsed = print_job_timer.duration();
|
||||
|
||||
// SD file position
|
||||
card.getAbsFilename(sd_filename);
|
||||
card.getAbsFilename(job_recovery_info.sd_filename);
|
||||
job_recovery_info.sdpos = card.getIndex();
|
||||
|
||||
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
|
||||
SERIAL_PROTOCOLLNPGM("Saving job_recovery_info");
|
||||
SERIAL_PROTOCOLLNPGM("Saving...");
|
||||
debug_print_job_recovery(false);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -40,13 +40,21 @@ typedef struct {
|
||||
|
||||
// Machine state
|
||||
float current_position[NUM_AXIS], feedrate;
|
||||
int16_t target_temperature[HOTENDS],
|
||||
fanSpeeds[FAN_COUNT];
|
||||
|
||||
#if HOTENDS > 1
|
||||
uint8_t active_hotend;
|
||||
#endif
|
||||
|
||||
int16_t target_temperature[HOTENDS];
|
||||
|
||||
#if HAS_HEATED_BED
|
||||
int16_t target_temperature_bed;
|
||||
#endif
|
||||
|
||||
#if FAN_COUNT
|
||||
int16_t fanSpeeds[FAN_COUNT];
|
||||
#endif
|
||||
|
||||
#if HAS_LEVELING
|
||||
bool leveling;
|
||||
float fade;
|
||||
@@ -56,7 +64,8 @@ typedef struct {
|
||||
uint8_t cmd_queue_index_r, commands_in_queue;
|
||||
char command_queue[BUFSIZE][MAX_CMD_SIZE];
|
||||
|
||||
// SD File position
|
||||
// SD Filename and position
|
||||
char sd_filename[MAXPATHNAMELENGTH];
|
||||
uint32_t sdpos;
|
||||
|
||||
// Job elapsed time
|
||||
@@ -70,20 +79,21 @@ extern job_recovery_info_t job_recovery_info;
|
||||
enum JobRecoveryPhase : unsigned char {
|
||||
JOB_RECOVERY_IDLE,
|
||||
JOB_RECOVERY_MAYBE,
|
||||
JOB_RECOVERY_YES
|
||||
JOB_RECOVERY_YES,
|
||||
JOB_RECOVERY_DONE
|
||||
};
|
||||
extern JobRecoveryPhase job_recovery_phase;
|
||||
|
||||
#if HAS_LEVELING
|
||||
#define APPEND_CMD_COUNT 7
|
||||
#define APPEND_CMD_COUNT 9
|
||||
#else
|
||||
#define APPEND_CMD_COUNT 5
|
||||
#define APPEND_CMD_COUNT 7
|
||||
#endif
|
||||
|
||||
extern char job_recovery_commands[BUFSIZE + APPEND_CMD_COUNT][MAX_CMD_SIZE];
|
||||
extern uint8_t job_recovery_commands_count;
|
||||
|
||||
void do_print_job_recovery();
|
||||
void check_print_job_recovery();
|
||||
void save_job_recovery_info();
|
||||
|
||||
#endif // _POWER_LOSS_RECOVERY_H_
|
||||
|
||||
@@ -60,7 +60,7 @@ millis_t PrintCounter::deltaDuration() {
|
||||
return lastDuration - tmp;
|
||||
}
|
||||
|
||||
void PrintCounter::incFilamentUsed(double const &amount) {
|
||||
void PrintCounter::incFilamentUsed(float const &amount) {
|
||||
#if ENABLED(DEBUG_PRINTCOUNTER)
|
||||
debug(PSTR("incFilamentUsed"));
|
||||
#endif
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
#include "stopwatch.h"
|
||||
#include <avr/eeprom.h>
|
||||
|
||||
struct printStatistics { // 16 bytes (20 with real doubles)
|
||||
struct printStatistics { // 16 bytes
|
||||
//const uint8_t magic; // Magic header, it will always be 0x16
|
||||
uint16_t totalPrints; // Number of prints
|
||||
uint16_t finishedPrints; // Number of complete prints
|
||||
uint32_t printTime; // Accumulated printing time
|
||||
uint32_t longestPrint; // Longest successful print job
|
||||
double filamentUsed; // Accumulated filament consumed in mm
|
||||
float filamentUsed; // Accumulated filament consumed in mm
|
||||
};
|
||||
|
||||
class PrintCounter: public Stopwatch {
|
||||
@@ -122,7 +122,7 @@ class PrintCounter: public Stopwatch {
|
||||
*
|
||||
* @param amount The amount of filament used in mm
|
||||
*/
|
||||
static void incFilamentUsed(double const &amount);
|
||||
static void incFilamentUsed(float const &amount);
|
||||
|
||||
/**
|
||||
* @brief Reset the Print Statistics
|
||||
|
||||
@@ -62,7 +62,7 @@ FORCE_INLINE void _draw_heater_status(const uint8_t x, const int8_t heater, cons
|
||||
|
||||
if (blink || !is_idle)
|
||||
#endif
|
||||
_draw_centered_temp(0.5 + (
|
||||
_draw_centered_temp(0.5f + (
|
||||
#if HAS_HEATED_BED
|
||||
isBed ? thermalManager.degTargetBed() :
|
||||
#endif
|
||||
@@ -72,7 +72,7 @@ FORCE_INLINE void _draw_heater_status(const uint8_t x, const int8_t heater, cons
|
||||
}
|
||||
|
||||
if (PAGE_CONTAINS(21, 28)) {
|
||||
_draw_centered_temp(0.5 + (
|
||||
_draw_centered_temp(0.5f + (
|
||||
#if HAS_HEATED_BED
|
||||
isBed ? thermalManager.degBed() :
|
||||
#endif
|
||||
@@ -108,11 +108,11 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
|
||||
if (blink)
|
||||
lcd_print(value);
|
||||
else {
|
||||
if (!axis_homed[axis])
|
||||
if (!TEST(axis_homed, axis))
|
||||
while (const char c = *value++) lcd_print(c <= '.' ? c : '?');
|
||||
else {
|
||||
#if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
|
||||
if (!axis_known_position[axis])
|
||||
if (!TEST(axis_known_position, axis))
|
||||
lcd_printPGM(axis == Z_AXIS ? PSTR(" ") : PSTR(" "));
|
||||
else
|
||||
#endif
|
||||
@@ -124,7 +124,7 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
|
||||
inline void lcd_implementation_status_message(const bool blink) {
|
||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||
static bool last_blink = false;
|
||||
|
||||
|
||||
// Get the UTF8 character count of the string
|
||||
uint8_t slen = lcd_strlen(lcd_status_message);
|
||||
|
||||
@@ -162,10 +162,8 @@ inline void lcd_implementation_status_message(const bool blink) {
|
||||
u8g.print('.'); // Always at 1+ spaces left, draw a dot
|
||||
if (--chars) { // Draw a second dot if there's space
|
||||
u8g.print('.');
|
||||
if (--chars) {
|
||||
// Print a second copy of the message
|
||||
lcd_print_utf(lcd_status_message, LCD_WIDTH - (rlen+2));
|
||||
}
|
||||
if (--chars) // Print a second copy of the message
|
||||
lcd_print_utf(lcd_status_message, LCD_WIDTH - (rlen + 2));
|
||||
}
|
||||
}
|
||||
if (last_blink != blink) {
|
||||
|
||||
@@ -617,7 +617,7 @@ void ST7920_Lite_Status_Screen::draw_status_message(const char *str) {
|
||||
begin_data();
|
||||
const uint8_t lcd_len = 16;
|
||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||
|
||||
|
||||
uint8_t slen = lcd_strlen(str);
|
||||
|
||||
// If the string fits into the LCD, just print it and do not scroll it
|
||||
@@ -868,9 +868,7 @@ void ST7920_Lite_Status_Screen::update_status_or_position(bool forceUpdate) {
|
||||
#if ENABLED(DISABLE_REDUCED_ACCURACY_WARNING)
|
||||
true
|
||||
#else
|
||||
axis_known_position[X_AXIS] &&
|
||||
axis_known_position[Y_AXIS] &&
|
||||
axis_known_position[Z_AXIS]
|
||||
all_axes_known()
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define STATUS_SCREEN_LITE_ST7920_CLASS_H
|
||||
|
||||
#include "macros.h"
|
||||
#include "duration.h"
|
||||
#include "duration_t.h"
|
||||
|
||||
typedef const __FlashStringHelper *progmem_str;
|
||||
|
||||
|
||||
+541
-587
File diff suppressed because it is too large
Load Diff
+261
-80
@@ -43,15 +43,158 @@
|
||||
#ifndef STEPPER_H
|
||||
#define STEPPER_H
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
// Disable multiple steps per ISR
|
||||
//#define DISABLE_MULTI_STEPPING
|
||||
|
||||
//
|
||||
// Estimate the amount of time the Stepper ISR will take to execute
|
||||
//
|
||||
|
||||
#ifndef MINIMUM_STEPPER_PULSE
|
||||
#define MINIMUM_STEPPER_PULSE 0UL
|
||||
#endif
|
||||
|
||||
#ifndef MAXIMUM_STEPPER_RATE
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
#define MAXIMUM_STEPPER_RATE (1000000UL / (2UL * (unsigned long)(MINIMUM_STEPPER_PULSE)))
|
||||
#else
|
||||
#define MAXIMUM_STEPPER_RATE 500000UL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The base ISR takes 752 cycles
|
||||
#define ISR_BASE_CYCLES 752UL
|
||||
|
||||
// Linear advance base time is 32 cycles
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
#define ISR_LA_BASE_CYCLES 32UL
|
||||
#else
|
||||
#define ISR_LA_BASE_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// S curve interpolation adds 160 cycles
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
#define ISR_S_CURVE_CYCLES 160UL
|
||||
#else
|
||||
#define ISR_S_CURVE_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// Stepper Loop base cycles
|
||||
#define ISR_LOOP_BASE_CYCLES 32UL
|
||||
|
||||
// To start the step pulse, in the worst case takes
|
||||
#define ISR_START_STEPPER_CYCLES 57UL
|
||||
|
||||
// And each stepper (start + stop pulse) takes in worst case
|
||||
#define ISR_STEPPER_CYCLES 88UL
|
||||
|
||||
// Add time for each stepper
|
||||
#ifdef HAS_X_STEP
|
||||
#define ISR_START_X_STEPPER_CYCLES ISR_START_STEPPER_CYCLES
|
||||
#define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#else
|
||||
#define ISR_START_X_STEPPER_CYCLES 0UL
|
||||
#define ISR_X_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
#ifdef HAS_Y_STEP
|
||||
#define ISR_START_Y_STEPPER_CYCLES ISR_START_STEPPER_CYCLES
|
||||
#define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#else
|
||||
#define ISR_START_Y_STEPPER_CYCLES 0UL
|
||||
#define ISR_Y_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
#ifdef HAS_Z_STEP
|
||||
#define ISR_START_Z_STEPPER_CYCLES ISR_START_STEPPER_CYCLES
|
||||
#define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
#else
|
||||
#define ISR_START_Z_STEPPER_CYCLES 0UL
|
||||
#define ISR_Z_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// E is always interpolated, even for mixing extruders
|
||||
#define ISR_START_E_STEPPER_CYCLES ISR_START_STEPPER_CYCLES
|
||||
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES
|
||||
|
||||
// If linear advance is disabled, then the loop also handles them
|
||||
#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER)
|
||||
#define ISR_START_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * (ISR_START_STEPPER_CYCLES))
|
||||
#define ISR_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
|
||||
#else
|
||||
#define ISR_START_MIXING_STEPPER_CYCLES 0UL
|
||||
#define ISR_MIXING_STEPPER_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// Calculate the minimum time to start all stepper pulses in the ISR loop
|
||||
#define MIN_ISR_START_LOOP_CYCLES (ISR_START_X_STEPPER_CYCLES + ISR_START_Y_STEPPER_CYCLES + ISR_START_Z_STEPPER_CYCLES + ISR_START_E_STEPPER_CYCLES + ISR_START_MIXING_STEPPER_CYCLES)
|
||||
|
||||
// And the total minimum loop time, not including the base
|
||||
#define MIN_ISR_LOOP_CYCLES (ISR_X_STEPPER_CYCLES + ISR_Y_STEPPER_CYCLES + ISR_Z_STEPPER_CYCLES + ISR_E_STEPPER_CYCLES + ISR_MIXING_STEPPER_CYCLES)
|
||||
|
||||
// Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate
|
||||
#define _MIN_STEPPER_PULSE_CYCLES(N) MAX((unsigned long)((F_CPU) / (MAXIMUM_STEPPER_RATE)), ((F_CPU) / 500000UL) * (N))
|
||||
#if MINIMUM_STEPPER_PULSE
|
||||
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES((unsigned long)(MINIMUM_STEPPER_PULSE))
|
||||
#else
|
||||
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(1UL)
|
||||
#endif
|
||||
|
||||
// Calculate the minimum ticks of the PULSE timer that must elapse with the step pulse enabled
|
||||
// adding the "start stepper pulse" code section execution cycles to account for that not all
|
||||
// pulses start at the beginning of the loop, so an extra time must be added to compensate so
|
||||
// the last generated pulse (usually the extruder stepper) has the right length
|
||||
#define MIN_PULSE_TICKS (((PULSE_TIMER_TICKS_PER_US) * (unsigned long)(MINIMUM_STEPPER_PULSE)) + ((MIN_ISR_START_LOOP_CYCLES) / (unsigned long)(PULSE_TIMER_PRESCALE)))
|
||||
|
||||
// Calculate the extra ticks of the PULSE timer between step pulses
|
||||
#define ADDED_STEP_TICKS (((MIN_STEPPER_PULSE_CYCLES) / (PULSE_TIMER_PRESCALE)) - (MIN_PULSE_TICKS))
|
||||
|
||||
// But the user could be enforcing a minimum time, so the loop time is
|
||||
#define ISR_LOOP_CYCLES (ISR_LOOP_BASE_CYCLES + MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LOOP_CYCLES))
|
||||
|
||||
// If linear advance is enabled, then it is handled separately
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
|
||||
// Estimate the minimum LA loop time
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
#define MIN_ISR_LA_LOOP_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
|
||||
#else
|
||||
#define MIN_ISR_LA_LOOP_CYCLES ISR_STEPPER_CYCLES
|
||||
#endif
|
||||
|
||||
// And the real loop time
|
||||
#define ISR_LA_LOOP_CYCLES MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LA_LOOP_CYCLES)
|
||||
|
||||
#else
|
||||
#define ISR_LA_LOOP_CYCLES 0UL
|
||||
#endif
|
||||
|
||||
// Now estimate the total ISR execution time in cycles given a step per ISR multiplier
|
||||
#define ISR_EXECUTION_CYCLES(R) (((ISR_BASE_CYCLES + ISR_S_CURVE_CYCLES + (ISR_LOOP_CYCLES) * (R) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES)) / (R))
|
||||
|
||||
// The maximum allowable stepping frequency when doing x128-x1 stepping (in Hz)
|
||||
#define MAX_STEP_ISR_FREQUENCY_128X ((F_CPU) / ISR_EXECUTION_CYCLES(128))
|
||||
#define MAX_STEP_ISR_FREQUENCY_64X ((F_CPU) / ISR_EXECUTION_CYCLES(64))
|
||||
#define MAX_STEP_ISR_FREQUENCY_32X ((F_CPU) / ISR_EXECUTION_CYCLES(32))
|
||||
#define MAX_STEP_ISR_FREQUENCY_16X ((F_CPU) / ISR_EXECUTION_CYCLES(16))
|
||||
#define MAX_STEP_ISR_FREQUENCY_8X ((F_CPU) / ISR_EXECUTION_CYCLES(8))
|
||||
#define MAX_STEP_ISR_FREQUENCY_4X ((F_CPU) / ISR_EXECUTION_CYCLES(4))
|
||||
#define MAX_STEP_ISR_FREQUENCY_2X ((F_CPU) / ISR_EXECUTION_CYCLES(2))
|
||||
#define MAX_STEP_ISR_FREQUENCY_1X ((F_CPU) / ISR_EXECUTION_CYCLES(1))
|
||||
|
||||
// The minimum allowable frequency for step smoothing will be 1/10 of the maximum nominal frequency (in Hz)
|
||||
#define MIN_STEP_ISR_FREQUENCY MAX_STEP_ISR_FREQUENCY_1X
|
||||
|
||||
//
|
||||
// Stepper class definition
|
||||
//
|
||||
|
||||
#include "planner.h"
|
||||
#include "speed_lookuptable.h"
|
||||
#include "stepper_indirection.h"
|
||||
#include "language.h"
|
||||
#include "types.h"
|
||||
|
||||
class Stepper;
|
||||
extern Stepper stepper;
|
||||
|
||||
// intRes = intIn1 * intIn2 >> 16
|
||||
// uses:
|
||||
// r26 to store 0
|
||||
@@ -83,10 +226,8 @@ class Stepper {
|
||||
|
||||
public:
|
||||
|
||||
static block_t* current_block; // A pointer to the block currently being traced
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
|
||||
static bool performing_homing;
|
||||
static bool homing_dual_axis;
|
||||
#endif
|
||||
|
||||
#if HAS_MOTOR_CURRENT_PWM
|
||||
@@ -98,26 +239,57 @@ class Stepper {
|
||||
|
||||
private:
|
||||
|
||||
static block_t* current_block; // A pointer to the block currently being traced
|
||||
|
||||
static uint8_t last_direction_bits, // The next stepping-bits to be output
|
||||
last_movement_extruder, // Last movement extruder, as computed when the last movement was fetched from planner
|
||||
axis_did_move; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
|
||||
|
||||
static bool abort_current_block; // Signals to the stepper that current block should be aborted
|
||||
|
||||
#if DISABLED(MIXING_EXTRUDER)
|
||||
static uint8_t last_moved_extruder; // Last-moved extruder, as set when the last movement was fetched from planner
|
||||
#endif
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
static bool locked_x_motor, locked_x2_motor;
|
||||
static bool locked_X_motor, locked_X2_motor;
|
||||
#endif
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
static bool locked_y_motor, locked_y2_motor;
|
||||
static bool locked_Y_motor, locked_Y2_motor;
|
||||
#endif
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
static bool locked_z_motor, locked_z2_motor;
|
||||
static bool locked_Z_motor, locked_Z2_motor;
|
||||
#endif
|
||||
|
||||
// Counter variables for the Bresenham line tracer
|
||||
static int32_t counter_X, counter_Y, counter_Z, counter_E;
|
||||
static uint32_t step_events_completed; // The number of step events executed in the current block
|
||||
static uint32_t acceleration_time, deceleration_time; // time measured in Stepper Timer ticks
|
||||
static uint8_t steps_per_isr; // Count of steps to perform per Stepper ISR call
|
||||
|
||||
#if ENABLED(BEZIER_JERK_CONTROL)
|
||||
#if ENABLED(ADAPTIVE_STEP_SMOOTHING)
|
||||
static uint8_t oversampling_factor; // Oversampling factor (log2(multiplier)) to increase temporal resolution of axis
|
||||
#else
|
||||
static constexpr uint8_t oversampling_factor = 0;
|
||||
#endif
|
||||
|
||||
// Delta error variables for the Bresenham line tracer
|
||||
static int32_t delta_error[XYZE];
|
||||
static uint32_t advance_dividend[XYZE],
|
||||
advance_divisor,
|
||||
step_events_completed, // The number of step events executed in the current block
|
||||
accelerate_until, // The point from where we need to stop acceleration
|
||||
decelerate_after, // The point from where we need to start decelerating
|
||||
step_event_count; // The total event count for the current block
|
||||
|
||||
// Mixing extruder mix delta_errors for bresenham tracing
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
static int32_t delta_error_m[MIXING_STEPPERS];
|
||||
static uint32_t advance_dividend_m[MIXING_STEPPERS],
|
||||
advance_divisor_m;
|
||||
#define MIXING_STEPPERS_LOOP(VAR) \
|
||||
for (uint8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++)
|
||||
#else
|
||||
static int8_t active_extruder; // Active extruder
|
||||
#endif
|
||||
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
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
|
||||
@@ -128,33 +300,19 @@ class Stepper {
|
||||
#endif
|
||||
|
||||
static uint32_t nextMainISR; // time remaining for the next Step ISR
|
||||
static bool all_steps_done; // all steps done
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
|
||||
static uint32_t LA_decelerate_after; // Copy from current executed block. Needed because current_block is set to NULL "too early".
|
||||
static uint32_t nextAdvanceISR, eISR_Rate;
|
||||
static uint16_t current_adv_steps, final_adv_steps, max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early".
|
||||
static int8_t e_steps;
|
||||
static bool use_advance_lead;
|
||||
#if E_STEPPERS > 1
|
||||
static int8_t LA_active_extruder; // Copy from current executed block. Needed because current_block is set to NULL "too early".
|
||||
#else
|
||||
static constexpr int8_t LA_active_extruder = 0;
|
||||
#endif
|
||||
|
||||
static uint32_t nextAdvanceISR, LA_isr_rate;
|
||||
static uint16_t LA_current_adv_steps, LA_final_adv_steps, LA_max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early".
|
||||
static int8_t LA_steps;
|
||||
static bool LA_use_advance_lead;
|
||||
#endif // LIN_ADVANCE
|
||||
|
||||
static uint32_t acceleration_time, deceleration_time;
|
||||
static uint8_t step_loops, step_loops_nominal;
|
||||
|
||||
static uint32_t ticks_nominal;
|
||||
#if DISABLED(BEZIER_JERK_CONTROL)
|
||||
static int32_t ticks_nominal;
|
||||
#if DISABLED(S_CURVE_ACCELERATION)
|
||||
static uint32_t acc_step_rate; // needed for deceleration start point
|
||||
#endif
|
||||
|
||||
static volatile int32_t endstops_trigsteps[XYZ];
|
||||
static volatile int32_t endstops_stepsTotal, endstops_stepsDone;
|
||||
|
||||
//
|
||||
// Positions of stepper motors, in step units
|
||||
@@ -164,17 +322,7 @@ class Stepper {
|
||||
//
|
||||
// Current direction of stepper motors (+1 or -1)
|
||||
//
|
||||
static volatile signed char count_direction[NUM_AXIS];
|
||||
|
||||
//
|
||||
// Mixing extruder mix counters
|
||||
//
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
static int32_t counter_m[MIXING_STEPPERS];
|
||||
#define MIXING_STEPPERS_LOOP(VAR) \
|
||||
for (uint8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++) \
|
||||
if (current_block->mix_event_count[VAR])
|
||||
#endif
|
||||
static int8_t count_direction[NUM_AXIS];
|
||||
|
||||
public:
|
||||
|
||||
@@ -189,7 +337,7 @@ class Stepper {
|
||||
// Interrupt Service Routines
|
||||
|
||||
// The ISR scheduler
|
||||
static hal_timer_t isr_scheduler();
|
||||
static void isr();
|
||||
|
||||
// The stepper pulse phase ISR
|
||||
static void stepper_pulse_phase_isr();
|
||||
@@ -202,6 +350,9 @@ class Stepper {
|
||||
static uint32_t advance_isr();
|
||||
#endif
|
||||
|
||||
// Check if the given block is busy or not - Must not be called from ISR contexts
|
||||
static bool is_block_busy(const block_t* const block);
|
||||
|
||||
// Get the position of a stepper, in steps
|
||||
static int32_t position(const AxisEnum axis);
|
||||
|
||||
@@ -222,7 +373,15 @@ class Stepper {
|
||||
FORCE_INLINE static bool axis_is_moving(const AxisEnum axis) { return TEST(axis_did_move, axis); }
|
||||
|
||||
// The extruder associated to the last movement
|
||||
FORCE_INLINE static uint8_t movement_extruder() { return last_movement_extruder; }
|
||||
FORCE_INLINE static uint8_t movement_extruder() {
|
||||
return
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
0
|
||||
#else
|
||||
last_moved_extruder
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
// Handle a triggered endstop
|
||||
static void endstop_triggered(const AxisEnum axis);
|
||||
@@ -241,20 +400,20 @@ class Stepper {
|
||||
static void microstep_readings();
|
||||
#endif
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
|
||||
FORCE_INLINE static void set_homing_dual_axis(const bool state) { homing_dual_axis = state; }
|
||||
#endif
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
FORCE_INLINE static void set_homing_flag_x(const bool state) { performing_homing = state; }
|
||||
FORCE_INLINE static void set_x_lock(const bool state) { locked_x_motor = state; }
|
||||
FORCE_INLINE static void set_x2_lock(const bool state) { locked_x2_motor = state; }
|
||||
FORCE_INLINE static void set_x_lock(const bool state) { locked_X_motor = state; }
|
||||
FORCE_INLINE static void set_x2_lock(const bool state) { locked_X2_motor = state; }
|
||||
#endif
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
FORCE_INLINE static void set_homing_flag_y(const bool state) { performing_homing = state; }
|
||||
FORCE_INLINE static void set_y_lock(const bool state) { locked_y_motor = state; }
|
||||
FORCE_INLINE static void set_y2_lock(const bool state) { locked_y2_motor = state; }
|
||||
FORCE_INLINE static void set_y_lock(const bool state) { locked_Y_motor = state; }
|
||||
FORCE_INLINE static void set_y2_lock(const bool state) { locked_Y2_motor = state; }
|
||||
#endif
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
FORCE_INLINE static void set_homing_flag_z(const bool state) { performing_homing = state; }
|
||||
FORCE_INLINE static void set_z_lock(const bool state) { locked_z_motor = state; }
|
||||
FORCE_INLINE static void set_z2_lock(const bool state) { locked_z2_motor = state; }
|
||||
FORCE_INLINE static void set_z_lock(const bool state) { locked_Z_motor = state; }
|
||||
FORCE_INLINE static void set_z2_lock(const bool state) { locked_Z2_motor = state; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(BABYSTEPPING)
|
||||
@@ -268,16 +427,21 @@ class Stepper {
|
||||
// Set the current position in steps
|
||||
inline static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
|
||||
planner.synchronize();
|
||||
CRITICAL_SECTION_START;
|
||||
const bool was_enabled = STEPPER_ISR_ENABLED();
|
||||
if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
_set_position(a, b, c, e);
|
||||
CRITICAL_SECTION_END;
|
||||
if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
}
|
||||
|
||||
inline static void set_position(const AxisEnum a, const int32_t &v) {
|
||||
planner.synchronize();
|
||||
CRITICAL_SECTION_START;
|
||||
|
||||
const bool was_enabled = STEPPER_ISR_ENABLED();
|
||||
if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
count_position[a] = v;
|
||||
CRITICAL_SECTION_END;
|
||||
|
||||
if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -288,25 +452,42 @@ class Stepper {
|
||||
// Set direction bits for all steppers
|
||||
static void set_directions();
|
||||
|
||||
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate) {
|
||||
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t scale, uint8_t* loops) {
|
||||
uint32_t timer;
|
||||
|
||||
NOMORE(step_rate, uint32_t(MAX_STEP_FREQUENCY));
|
||||
// Scale the frequency, as requested by the caller
|
||||
step_rate <<= scale;
|
||||
|
||||
if (step_rate > 20000) { // If steprate > 20kHz >> step 4 times
|
||||
step_rate >>= 2;
|
||||
step_loops = 4;
|
||||
}
|
||||
else if (step_rate > 10000) { // If steprate > 10kHz >> step 2 times
|
||||
step_rate >>= 1;
|
||||
step_loops = 2;
|
||||
}
|
||||
else {
|
||||
step_loops = 1;
|
||||
}
|
||||
uint8_t multistep = 1;
|
||||
#if DISABLED(DISABLE_MULTI_STEPPING)
|
||||
|
||||
NOLESS(step_rate, uint32_t(F_CPU / 500000U));
|
||||
step_rate -= F_CPU / 500000; // Correct for minimal speed
|
||||
// The stepping frequency limits for each multistepping rate
|
||||
static const uint32_t limit[] PROGMEM = {
|
||||
( MAX_STEP_ISR_FREQUENCY_1X ),
|
||||
( MAX_STEP_ISR_FREQUENCY_2X >> 1),
|
||||
( MAX_STEP_ISR_FREQUENCY_4X >> 2),
|
||||
( MAX_STEP_ISR_FREQUENCY_8X >> 3),
|
||||
( MAX_STEP_ISR_FREQUENCY_16X >> 4),
|
||||
( MAX_STEP_ISR_FREQUENCY_32X >> 5),
|
||||
( MAX_STEP_ISR_FREQUENCY_64X >> 6),
|
||||
(MAX_STEP_ISR_FREQUENCY_128X >> 7)
|
||||
};
|
||||
|
||||
// Select the proper multistepping
|
||||
uint8_t idx = 0;
|
||||
while (idx < 7 && step_rate > (uint32_t)pgm_read_dword(&limit[idx])) {
|
||||
step_rate >>= 1;
|
||||
multistep <<= 1;
|
||||
++idx;
|
||||
};
|
||||
#else
|
||||
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
|
||||
#endif
|
||||
*loops = multistep;
|
||||
|
||||
constexpr uint32_t min_step_rate = F_CPU / 500000U;
|
||||
NOLESS(step_rate, min_step_rate);
|
||||
step_rate -= min_step_rate; // Correct for minimal speed
|
||||
if (step_rate >= (8 * 256)) { // higher step rate
|
||||
const uint8_t tmp_step_rate = (step_rate & 0x00FF);
|
||||
const uint16_t table_address = (uint16_t)&speed_lookuptable_fast[(uint8_t)(step_rate >> 8)][0],
|
||||
@@ -320,15 +501,13 @@ class Stepper {
|
||||
timer = (uint16_t)pgm_read_word_near(table_address)
|
||||
- (((uint16_t)pgm_read_word_near(table_address + 2) * (uint8_t)(step_rate & 0x0007)) >> 3);
|
||||
}
|
||||
if (timer < 100) { // (20kHz - this should never happen)
|
||||
timer = 100;
|
||||
SERIAL_ECHOLNPAIR(MSG_STEPPER_TOO_HIGH, step_rate);
|
||||
}
|
||||
// (there is no need to limit the timer value here. All limits have been
|
||||
// applied above, and AVR is able to keep up at 30khz Stepping ISR rate)
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
#if ENABLED(BEZIER_JERK_CONTROL)
|
||||
#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);
|
||||
#endif
|
||||
@@ -343,4 +522,6 @@ class Stepper {
|
||||
|
||||
};
|
||||
|
||||
extern Stepper stepper;
|
||||
|
||||
#endif // STEPPER_H
|
||||
|
||||
@@ -91,8 +91,8 @@
|
||||
mcp4728_simpleCommand(UPDATE);
|
||||
}
|
||||
|
||||
static float dac_perc(int8_t n) { return 100.0 * mcp4728_getValue(dac_order[n]) * (1.0 / (DAC_STEPPER_MAX)); }
|
||||
static float dac_amps(int8_t n) { return mcp4728_getDrvPct(dac_order[n]) * (DAC_STEPPER_MAX) * 0.125 * (1.0 / (DAC_STEPPER_SENSE)); }
|
||||
static float dac_perc(int8_t n) { return 100.0f * mcp4728_getValue(dac_order[n]) * (1.0f / (DAC_STEPPER_MAX)); }
|
||||
static float dac_amps(int8_t n) { return mcp4728_getDrvPct(dac_order[n]) * (DAC_STEPPER_MAX) * 0.125 * (1.0f / (DAC_STEPPER_SENSE)); }
|
||||
|
||||
uint8_t dac_current_get_percent(const AxisEnum axis) { return mcp4728_getDrvPct(dac_order[axis]); }
|
||||
void dac_current_set_percents(const uint8_t pct[XYZE]) {
|
||||
|
||||
@@ -201,8 +201,6 @@
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
st.stealth_max_speed(12650000UL*microsteps/(256*thrs*spmm));
|
||||
#endif
|
||||
#elif ENABLED(SENSORLESS_HOMING)
|
||||
st.coolstep_min_speed(1024UL * 1024UL - 1UL);
|
||||
#endif
|
||||
st.GSTAT(); // Clear GSTAT
|
||||
}
|
||||
@@ -246,7 +244,7 @@
|
||||
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
#define TMC_INIT_SGT(P,Q) stepper##Q.sgt(P##_HOMING_SENSITIVITY);
|
||||
#ifdef X_HOMING_SENSITIVITY
|
||||
#if X_SENSORLESS
|
||||
#if ENABLED(X_IS_TMC2130) || ENABLED(IS_TRAMS)
|
||||
stepperX.sgt(X_HOMING_SENSITIVITY);
|
||||
#endif
|
||||
@@ -254,7 +252,7 @@
|
||||
stepperX2.sgt(X_HOMING_SENSITIVITY);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef Y_HOMING_SENSITIVITY
|
||||
#if Y_SENSORLESS
|
||||
#if ENABLED(Y_IS_TMC2130) || ENABLED(IS_TRAMS)
|
||||
stepperY.sgt(Y_HOMING_SENSITIVITY);
|
||||
#endif
|
||||
@@ -262,7 +260,7 @@
|
||||
stepperY2.sgt(Y_HOMING_SENSITIVITY);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef Z_HOMING_SENSITIVITY
|
||||
#if Z_SENSORLESS
|
||||
#if ENABLED(Z_IS_TMC2130) || ENABLED(IS_TRAMS)
|
||||
stepperZ.sgt(Z_HOMING_SENSITIVITY);
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user