Commit f32fb713 authored by Simone Primarosa's avatar Simone Primarosa

Update 4.2.0 RC

Compilation test passed
parent 9e22582c
......@@ -52,12 +52,6 @@
// Bed Printer radius
#define PRINTER_RADIUS 75 // mm
// Radius for probe
#define DELTA_PROBABLE_RADIUS (PRINTER_RADIUS)
// Effective horizontal distance bridged by diagonal push rods.
#define DEFAULT_DELTA_RADIUS (DELTA_SMOOTH_ROD_OFFSET-DELTA_EFFECTOR_OFFSET-DELTA_CARRIAGE_OFFSET)
// Uncomment to enable autocalibration debug messages
#define DEBUG_MESSAGES
......
This diff is collapsed.
......@@ -151,6 +151,7 @@
* or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout.
* M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
* M92 - Set axis_steps_per_unit - same syntax as G92
* M100 - Watch Free Memory (For Debugging Only)
* M104 - Set extruder target temp
* M105 - Read current temp
* M106 - Fan on
......@@ -158,7 +159,6 @@
* M109 - Sxxx Wait for extruder current temp to reach target temp. Waits only when heating
* Rxxx Wait for extruder current temp to reach target temp. Waits when heating and cooling
* IF AUTOTEMP is enabled, S<mintemp> B<maxtemp> F<factor>. Exit autotemp by any M109 without F
* M100 - Watch Free Memory (For Debugging Only)
* M110 - Set the current line number
* M111 - Set debug flags with S<mask>. See flag bits defined in Marlin.h.
* M112 - Emergency stop
......@@ -496,6 +496,7 @@ unsigned long printer_usage_seconds;
//===========================================================================
//================================ Functions ================================
//===========================================================================
inline void refresh_cmd_timeout() { previous_cmd_ms = millis(); }
void process_next_command();
......@@ -531,6 +532,53 @@ bool setTargetedHotend(int code);
#endif // !SDSUPPORT
#endif
#if ENABLED(M100_FREE_MEMORY_WATCHER)
// top_of_stack() returns the location of a variable on its stack frame. The value returned is above
// the stack once the function returns to the caller.
unsigned char *top_of_stack() {
unsigned char x;
return &x + 1; // x is pulled on return;
}
//
// 3 support routines to print hex numbers. We can print a nibble, byte and word
//
void prt_hex_nibble( unsigned int n ) {
if ( n <= 9 )
ECHO_V(n);
else
ECHO_V( (char) ('A'+n-10) );
delay(2);
}
void prt_hex_byte(unsigned int b) {
prt_hex_nibble( ( b & 0xf0 ) >> 4 );
prt_hex_nibble( b & 0x0f );
}
void prt_hex_word(unsigned int w) {
prt_hex_byte( ( w & 0xff00 ) >> 8 );
prt_hex_byte( w & 0x0ff );
}
// how_many_E5s_are_here() is a utility function to easily find out how many 0xE5's are
// at the specified location. Having this logic as a function simplifies the search code.
//
int how_many_E5s_are_here( unsigned char *p) {
int n;
for(n = 0; n < 32000; n++) {
if ( *(p+n) != (unsigned char) 0xe5)
return n-1;
}
return -1;
}
#endif
/**
* Inject the next command from the command queue, when possible
* Return false only if no command was pending
......@@ -4852,6 +4900,193 @@ inline void gcode_M92() {
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
}
// M100 Free Memory Watcher
//
// This code watches the free memory block between the bottom of the heap and the top of the stack.
// This memory block is initialized and watched via the M100 command.
//
// M100 I Initializes the free memory block and prints vitals statistics about the area
// M100 F Identifies how much of the free memory block remains free and unused. It also
// detects and reports any corruption within the free memory block that may have
// happened due to errant firmware.
// M100 D Does a hex display of the free memory block along with a flag for any errant
// data that does not match the expected value.
// M100 C x Corrupts x locations within the free memory block. This is useful to check the
// correctness of the M100 F and M100 D commands.
//
// Initial version by Roxy-3DPrintBoard
//
//
#if ENABLED(M100_FREE_MEMORY_WATCHER)
inline void gcode_M100() {
static int m100_not_initialized = 1;
unsigned char *sp, *ptr;
int i, j, n;
//
// M100 D dumps the free memory block from __brkval to the stack pointer.
// malloc() eats memory from the start of the block and the stack grows
// up from the bottom of the block. Solid 0xE5's indicate nothing has
// used that memory yet. There should not be anything but 0xE5's within
// the block of 0xE5's. If there is, that would indicate memory corruption
// probably caused by bad pointers. Any unexpected values will be flagged in
// the right hand column to help spotting them.
//
#if ENABLED(M100_FREE_MEMORY_DUMPER) // Comment out to remove Dump sub-command
if ( code_seen('D') ) {
ptr = (unsigned char *) __brkval;
//
// We want to start and end the dump on a nice 16 byte boundry even though
// the values we are using are not 16 byte aligned.
//
ECHO_M("\n__brkval : ");
prt_hex_word( (unsigned int) ptr );
ptr = (unsigned char *) ((unsigned long) ptr & 0xfff0);
sp = top_of_stack();
ECHO_M("\nStack Pointer : ");
prt_hex_word( (unsigned int) sp );
ECHO_M("\n");
sp = (unsigned char *) ((unsigned long) sp | 0x000f);
n = sp - ptr;
//
// This is the main loop of the Dump command.
//
while ( ptr < sp ) {
prt_hex_word( (unsigned int) ptr); // Print the address
ECHO_M(":");
for(i = 0; i < 16; i++) { // and 16 data bytes
prt_hex_byte( *(ptr+i));
ECHO_M(" ");
delay(2);
}
ECHO_M("|"); // now show where non 0xE5's are
for(i = 0; i < 16; i++) {
delay(2);
if ( *(ptr+i)==0xe5)
ECHO_M(" ");
else
ECHO_M("?");
}
ECHO_M("\n");
ptr += 16;
delay(2);
}
ECHO_M("Done.\n");
return;
}
#endif
//
// M100 F requests the code to return the number of free bytes in the memory pool along with
// other vital statistics that define the memory pool.
//
if ( code_seen('F') ) {
int max_addr = (int) __brkval;
int max_cnt = 0;
int block_cnt = 0;
ptr = (unsigned char *) __brkval;
sp = top_of_stack();
n = sp - ptr;
// Scan through the range looking for the biggest block of 0xE5's we can find
for(i = 0; i < n; i++) {
if ( *(ptr+i) == (unsigned char) 0xe5) {
j = how_many_E5s_are_here( (unsigned char *) ptr+i );
if ( j > 8) {
ECHO_MV("Found ", j );
ECHO_M(" bytes free at 0x");
prt_hex_word( (int) ptr+i );
ECHO_M("\n");
i += j;
block_cnt++;
}
if ( j>max_cnt) { // We don't do anything with this information yet
max_cnt = j; // but we do know where the biggest free memory block is.
max_addr = (int) ptr+i;
}
}
}
if (block_cnt>1)
ECHO_EM("\nMemory Corruption detected in free memory area.\n");
ECHO_M("\nDone.\n");
return;
}
//
// M100 C x Corrupts x locations in the free memory pool and reports the locations of the corruption.
// This is useful to check the correctness of the M100 D and the M100 F commands.
//
#if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
if ( code_seen('C') ) {
int x; // x gets the # of locations to corrupt within the memory pool
x = code_value();
ECHO_EM("Corrupting free memory block.\n");
ptr = (unsigned char *) __brkval;
ECHO_MV("\n__brkval : ",(long) ptr );
ptr += 8;
sp = top_of_stack();
ECHO_MV("\nStack Pointer : ",(long) sp );
ECHO_EM("\n");
n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that
// has altered the stack.
j = n / (x+1);
for(i = 1; i <= x; i++) {
*(ptr+(i*j)) = i;
ECHO_M("\nCorrupting address: 0x");
prt_hex_word( (unsigned int) (ptr+(i*j)) );
}
ECHO_EM("\n");
return;
}
#endif
//
// M100 I Initializes the free memory pool so it can be watched and prints vital
// statistics that define the free memory pool.
//
if (m100_not_initialized || code_seen('I') ) { // If no sub-command is specified, the first time
ECHO_EM("Initializing free memory block.\n"); // this happens, it will Initialize.
ptr = (unsigned char *) __brkval; // Repeated M100 with no sub-command will not destroy the
ECHO_MV("\n__brkval : ",(long) ptr ); // state of the initialized free memory pool.
ptr += 8;
sp = top_of_stack();
ECHO_MV("\nStack Pointer : ",(long) sp );
ECHO_EM("\n");
n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that
// has altered the stack.
ECHO_V( n );
ECHO_EM(" bytes of memory initialized.\n");
for(i = 0; i < n; i++)
*(ptr+i) = (unsigned char) 0xe5;
for(i = 0; i < n; i++) {
if ( *(ptr+i) != (unsigned char) 0xe5 ) {
ECHO_MV("? address : ", (unsigned long) ptr+i );
ECHO_MV("=", *(ptr+i) );
ECHO_EM("\n");
}
}
m100_not_initialized = 0;
ECHO_EM("Done.\n");
return;
}
return;
}
#endif
/**
* M104: Set hot end temperature
*/
......@@ -7604,26 +7839,6 @@ void plan_arc(
#endif
void enable_all_steppers() {
enable_x();
enable_y();
enable_z();
enable_e0();
enable_e1();
enable_e2();
enable_e3();
}
void disable_all_steppers() {
disable_x();
disable_y();
disable_z();
disable_e0();
disable_e1();
disable_e2();
disable_e3();
}
/**
* Standard idle routine keeps the machine alive
*/
......
......@@ -4,97 +4,12 @@
#ifndef MARLIN_H
#define MARLIN_H
typedef unsigned long millis_t;
void get_command();
void idle(bool ignore_stepper_queue = false);
void manage_inactivity(bool ignore_stepper_queue=false);
#if ENABLED(DUAL_X_CARRIAGE) && HAS(X_ENABLE) && 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)
#elif HAS(X_ENABLE)
#define enable_x() X_ENABLE_WRITE( X_ENABLE_ON)
#define disable_x() { X_ENABLE_WRITE(!X_ENABLE_ON); axis_known_position[X_AXIS] = false; }
#else
#define enable_x() ;
#define disable_x() ;
#endif
#if HAS(Y_ENABLE)
#if ENABLED(Y_DUAL_STEPPER_DRIVERS)
#define enable_y() { Y_ENABLE_WRITE( Y_ENABLE_ON); Y2_ENABLE_WRITE(Y_ENABLE_ON); }
#define disable_y() { Y_ENABLE_WRITE(!Y_ENABLE_ON); Y2_ENABLE_WRITE(!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
#else
#define enable_y() Y_ENABLE_WRITE( Y_ENABLE_ON)
#define disable_y() { Y_ENABLE_WRITE(!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
#endif
#else
#define enable_y() ;
#define disable_y() ;
#endif
#if HAS(Z_ENABLE)
#if ENABLED(Z_DUAL_STEPPER_DRIVERS)
#define enable_z() { Z_ENABLE_WRITE( Z_ENABLE_ON); Z2_ENABLE_WRITE(Z_ENABLE_ON); }
#define disable_z() { Z_ENABLE_WRITE(!Z_ENABLE_ON); Z2_ENABLE_WRITE(!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
#else
#define enable_z() Z_ENABLE_WRITE( Z_ENABLE_ON)
#define disable_z() { Z_ENABLE_WRITE(!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
#endif
#else
#define enable_z() ;
#define disable_z() ;
#endif
#if HAS(E0_ENABLE)
#define enable_e0() E0_ENABLE_WRITE( E_ENABLE_ON)
#define disable_e0() E0_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_e0() /* nothing */
#define disable_e0() /* nothing */
#endif
#if (DRIVER_EXTRUDERS > 1) && HAS(E1_ENABLE)
#define enable_e1() E1_ENABLE_WRITE( E_ENABLE_ON)
#define disable_e1() E1_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_e1() /* nothing */
#define disable_e1() /* nothing */
#endif
#if (DRIVER_EXTRUDERS > 2) && HAS(E2_ENABLE)
#define enable_e2() E2_ENABLE_WRITE( E_ENABLE_ON)
#define disable_e2() E2_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_e2() /* nothing */
#define disable_e2() /* nothing */
#endif
#if (DRIVER_EXTRUDERS > 3) && HAS(E3_ENABLE)
#define enable_e3() E3_ENABLE_WRITE( E_ENABLE_ON)
#define disable_e3() E3_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_e3() /* nothing */
#define disable_e3() /* nothing */
#endif
#define disable_e() {disable_e0(); disable_e1(); disable_e2(); disable_e3();}
/**
* Axis indices as enumerated constants
*
* A_AXIS and B_AXIS are used by COREXY printers
* X_HEAD and Y_HEAD is used for systems that don't have a 1:1 relationship between X_AXIS and X Head movement, like CoreXY bots.
*/
enum AxisEnum {X_AXIS=0, A_AXIS=0, Y_AXIS=1, B_AXIS=1, Z_AXIS=2, C_AXIS=2, E_AXIS=3, X_HEAD=4, Y_HEAD=5, Z_HEAD=5};
enum EndstopEnum {X_MIN=0, Y_MIN=1, Z_MIN=2, Z_PROBE=3, X_MAX=4, Y_MAX=5, Z_MAX=6, Z2_MIN=7, Z2_MAX=8};
void enable_all_steppers();
void disable_all_steppers();
void FlushSerialRequestResend();
void ok_to_send();
......@@ -149,6 +64,9 @@ enum DebugFlags {
DEBUG_DRYRUN = BIT(3),
DEBUG_COMMUNICATION = BIT(4)
};
void clamp_to_software_endstops(float target[3]);
extern uint8_t debugLevel;
extern bool Running;
......@@ -162,7 +80,7 @@ void prepare_arc_move(char isclockwise);
void clamp_to_software_endstops(float target[3]);
extern millis_t previous_cmd_ms;
inline void refresh_cmd_timeout() { previous_cmd_ms = millis(); }
inline void refresh_cmd_timeout();
#if ENABLED(FAST_PWM_FAN)
void setPwmFrequency(uint8_t pin, int val);
......@@ -292,4 +210,26 @@ extern uint8_t active_driver;
extern void calculate_volumetric_multipliers();
#if ENABLED(M100_FREE_MEMORY_WATCHER)
extern void *__brkval;
extern size_t __heap_start, __heap_end, __flp;
//
// Declare all the functions we need from Marlin_Main.cpp to do the work!
//
float code_value();
long code_value_long();
bool code_seen(char );
//
// Utility functions used by M100 to get its work done.
//
unsigned char *top_of_stack();
void prt_hex_nibble( unsigned int );
void prt_hex_byte(unsigned int );
void prt_hex_word(unsigned int );
int how_many_E5s_are_here( unsigned char *);
#endif
#endif //MARLIN_H
......@@ -327,6 +327,9 @@
#define RIGHT_PROBE_BED_POSITION DELTA_PROBABLE_RADIUS
#define FRONT_PROBE_BED_POSITION -DELTA_PROBABLE_RADIUS
#define BACK_PROBE_BED_POSITION DELTA_PROBABLE_RADIUS
// Radius for probe
#define DELTA_PROBABLE_RADIUS (PRINTER_RADIUS)
#endif
/**
......
......@@ -1531,6 +1531,8 @@
#define N_ARC_CORRECTION 25
//#define M100_FREE_MEMORY_WATCHER // Uncomment to add the M100 Free Memory Watcher for debug purpose
#define M100_FREE_MEMORY_DUMPER // Comment out to remove Dump sub-command
#define M100_FREE_MEMORY_CORRUPTOR // Comment out to remove Corrupt sub-command
/****************************************************************************************/
......
......@@ -4,6 +4,8 @@
#include "vector_3.h"
#endif
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "temperature.h"
#include "ultralcd.h"
#include "configuration_store.h"
......
#ifndef CONFIGURATIONS_H
#define CONFIGURATIONS_H
#include "Configuration_Version.h"
#include "Configuration_Basic.h"
#if MECH(CARTESIAN)
#include "Configuration_Cartesian.h"
#elif MECH(COREXY)
#include "Configuration_Core.h"
#elif MECH(COREXZ)
#include "Configuration_Core.h"
#elif MECH(DELTA)
#include "Configuration_Delta.h"
#elif MECH(SCARA)
#include "Configuration_Scara.h"
#endif
#include "Configuration_Feature.h"
#include "Configuration_Overall.h"
#endif
\ No newline at end of file
#ifndef ELEMENTS_H
#define ELEMENTS_H
#warning called
#include "Arduino.h"
#include "pins_arduino.h"
......@@ -27,10 +27,29 @@
#include "macros.h"
#include "boards.h"
#include "mechanics.h"
#include "configurations.h"
#include "Configuration_Version.h"
#include "Configuration_Basic.h"
#include "Configuration_Overall.h"
#if MECH(CARTESIAN)
#include "Configuration_Cartesian.h"
#elif MECH(COREXY)
#include "Configuration_Core.h"
#elif MECH(COREXZ)
#include "Configuration_Core.h"
#elif MECH(DELTA)
#include "Configuration_Delta.h"
#elif MECH(SCARA)
#include "Configuration_Scara.h"
#endif
#include "Configuration_Feature.h"
#include "Configuration_Overall.h"
#include "language.h"
#include "dependencies.h"
#include "conditionals.h"
#include "dependencies.h"
#include "conflicts.h"
#include "comunication.h"
......
This diff is collapsed.
This diff is collapsed.
......@@ -63,9 +63,9 @@
#define MSG_FAN_SPEED "Ventilador"
#define MSG_FLOW "Flujo"
#define MSG_CONTROL "Control"
#define MSG_MIN STR_THERMOMETER " Min"
#define MSG_MAX STR_THERMOMETER " Max"
#define MSG_FACTOR STR_THERMOMETER " Fact"
#define MSG_MIN LCD_STR_THERMOMETER " Min"
#define MSG_MAX LCD_STR_THERMOMETER " Max"
#define MSG_FACTOR LCD_STR_THERMOMETER " Fact"
#define MSG_IDLEOOZING "Anti oozing"
#define MSG_AUTOTEMP "Autotemp"
#define MSG_ON "On "
......
......@@ -61,9 +61,9 @@
#define MSG_FAN_SPEED "Haizagailua"
#define MSG_FLOW "Fluxua"
#define MSG_CONTROL "Kontrola"
#define MSG_MIN " " STR_THERMOMETER " Min"
#define MSG_MAX " " STR_THERMOMETER " Max"
#define MSG_FACTOR " " STR_THERMOMETER " Fact"
#define MSG_MIN " " LCD_STR_THERMOMETER " Min"
#define MSG_MAX " " LCD_STR_THERMOMETER " Max"
#define MSG_FACTOR " " LCD_STR_THERMOMETER " Fact"
#define MSG_IDLEOOZING "Anti oozing"
#define MSG_AUTOTEMP "Auto tenperatura"
#define MSG_ON "On "
......
......@@ -61,9 +61,9 @@
#define MSG_FAN_SPEED "Tuul. nopeus"
#define MSG_FLOW "Virtaus"
#define MSG_CONTROL "Kontrolli"
#define MSG_MIN STR_THERMOMETER " Min"
#define MSG_MAX STR_THERMOMETER " Max"
#define MSG_FACTOR STR_THERMOMETER " Kerr"
#define MSG_MIN LCD_STR_THERMOMETER " Min"
#define MSG_MAX LCD_STR_THERMOMETER " Max"
#define MSG_FACTOR LCD_STR_THERMOMETER " Kerr"
#define MSG_IDLEOOZING "Anti oozing"
#define MSG_AUTOTEMP "Autotemp"
#define MSG_ON "On "
......
......@@ -62,9 +62,9 @@
#define MSG_FAN_SPEED "Vite. ventilateur"
#define MSG_FLOW "Flux"
#define MSG_CONTROL "Controler"
#define MSG_MIN " " STR_THERMOMETER " Min"
#define MSG_MAX " " STR_THERMOMETER " Max"
#define MSG_FACTOR " " STR_THERMOMETER " Facteur"
#define MSG_MIN " " LCD_STR_THERMOMETER " Min"
#define MSG_MAX " " LCD_STR_THERMOMETER " Max"
#define MSG_FACTOR " " LCD_STR_THERMOMETER " Facteur"
#define MSG_IDLEOOZING "Anti oozing"
#define MSG_AUTOTEMP "Temp. Auto."
#define MSG_ON "Marche "
......
......@@ -61,9 +61,9 @@
#define MSG_FAN_SPEED "Fan snelheid"
#define MSG_FLOW "Flow"
#define MSG_CONTROL "Control"
#define MSG_MIN " " STR_THERMOMETER " Min"
#define MSG_MAX " " STR_THERMOMETER " Max"
#define MSG_FACTOR " " STR_THERMOMETER " Fact"
#define MSG_MIN " " LCD_STR_THERMOMETER " Min"
#define MSG_MAX " " LCD_STR_THERMOMETER " Max"
#define MSG_FACTOR " " LCD_STR_THERMOMETER " Fact"
#define MSG_IDLEOOZING "Anti oozing"
#define MSG_AUTOTEMP "Autotemp"
#define MSG_ON "Aan "
......
......@@ -61,9 +61,9 @@
#define MSG_FAN_SPEED "Obroty wiatraka"
#define MSG_FLOW "Przeplyw"
#define MSG_CONTROL "Ustawienia"
#define MSG_MIN " " STR_THERMOMETER " Min"
#define MSG_MAX " " STR_THERMOMETER " Max"
#define MSG_FACTOR " " STR_THERMOMETER " Fact"
#define MSG_MIN " " LCD_STR_THERMOMETER " Min"
#define MSG_MAX " " LCD_STR_THERMOMETER " Max"
#define MSG_FACTOR " " LCD_STR_THERMOMETER " Fact"
#define MSG_IDLEOOZING "Anti oozing"
#define MSG_AUTOTEMP "Auto. temperatura"
#define MSG_ON "Wl. "
......
......@@ -61,9 +61,9 @@
#define MSG_FAN_SPEED "Velocidade do ar."
#define MSG_FLOW "Fluxo"
#define MSG_CONTROL "Control"
#define MSG_MIN " " STR_THERMOMETER " Min"
#define MSG_MAX " " STR_THERMOMETER " Max"
#define MSG_FACTOR " " STR_THERMOMETER " Fact"
#define MSG_MIN " " LCD_STR_THERMOMETER " Min"
#define MSG_MAX " " LCD_STR_THERMOMETER " Max"
#define MSG_FACTOR " " LCD_STR_THERMOMETER " Fact"
#define MSG_IDLEOOZING "Anti oozing"
#define MSG_AUTOTEMP "Autotemp"
#define MSG_ON "On "
......
......@@ -61,9 +61,9 @@
#define MSG_FAN_SPEED "Куллер:"
#define MSG_FLOW "Поток:"
#define MSG_CONTROL "Настройки"
#define MSG_MIN " " STR_THERMOMETER "Минимум"
#define MSG_MAX " " STR_THERMOMETER "Максимум"
#define MSG_FACTOR " " STR_THERMOMETER "Фактор"
#define MSG_MIN " " LCD_STR_THERMOMETER "Минимум"
#define MSG_MAX " " LCD_STR_THERMOMETER "Максимум"
#define MSG_FACTOR " " LCD_STR_THERMOMETER "Фактор"
#define MSG_IDLEOOZING "Anti oozing"
#define MSG_AUTOTEMP "Autotemp"
#define MSG_ON "Вкл."
......
#define M100_FREE_MEMORY_DUMPER // Comment out to remove Dump sub-command
#define M100_FREE_MEMORY_CORRUPTOR // Comment out to remove Corrupt sub-command
// M100 Free Memory Watcher
//
// This code watches the free memory block between the bottom of the heap and the top of the stack.
// This memory block is initialized and watched via the M100 command.
//
// M100 I Initializes the free memory block and prints vitals statistics about the area
// M100 F Identifies how much of the free memory block remains free and unused. It also
// detects and reports any corruption within the free memory block that may have
// happened due to errant firmware.
// M100 D Does a hex display of the free memory block along with a flag for any errant
// data that does not match the expected value.
// M100 C x Corrupts x locations within the free memory block. This is useful to check the
// correctness of the M100 F and M100 D commands.
//
// Initial version by Roxy-3DPrintBoard
//
//
#include "Marlin.h"
#if ENABLED(M100_FREE_MEMORY_WATCHER)
extern void *__brkval;
extern size_t __heap_start, __heap_end, __flp;
//
// Declare all the functions we need from Marlin_Main.cpp to do the work!
//
float code_value();
long code_value_long();
bool code_seen(char );
//
// Utility functions used by M100 to get its work done.
//
unsigned char *top_of_stack();
void prt_hex_nibble( unsigned int );
void prt_hex_byte(unsigned int );
void prt_hex_word(unsigned int );
int how_many_E5s_are_here( unsigned char *);
void gcode_M100() {
static int m100_not_initialized = 1;
unsigned char *sp, *ptr;
int i, j, n;
//
// M100 D dumps the free memory block from __brkval to the stack pointer.
// malloc() eats memory from the start of the block and the stack grows
// up from the bottom of the block. Solid 0xE5's indicate nothing has
// used that memory yet. There should not be anything but 0xE5's within
// the block of 0xE5's. If there is, that would indicate memory corruption
// probably caused by bad pointers. Any unexpected values will be flagged in
// the right hand column to help spotting them.
//
#if ENABLED(M100_FREE_MEMORY_DUMPER) // Comment out to remove Dump sub-command
if ( code_seen('D') ) {
ptr = (unsigned char *) __brkval;
//
// We want to start and end the dump on a nice 16 byte boundry even though
// the values we are using are not 16 byte aligned.
//
ECHO_M("\n__brkval : ");
prt_hex_word( (unsigned int) ptr );
ptr = (unsigned char *) ((unsigned long) ptr & 0xfff0);
sp = top_of_stack();
ECHO_M("\nStack Pointer : ");
prt_hex_word( (unsigned int) sp );
ECHO_M("\n");
sp = (unsigned char *) ((unsigned long) sp | 0x000f);
n = sp - ptr;
//
// This is the main loop of the Dump command.
//
while ( ptr < sp ) {
prt_hex_word( (unsigned int) ptr); // Print the address
ECHO_M(":");
for(i = 0; i < 16; i++) { // and 16 data bytes
prt_hex_byte( *(ptr+i));
ECHO_M(" ");
delay(2);
}
ECHO_M("|"); // now show where non 0xE5's are
for(i = 0; i < 16; i++) {
delay(2);
if ( *(ptr+i)==0xe5)
ECHO_M(" ");
else
ECHO_M("?");
}
ECHO_M("\n");
ptr += 16;
delay(2);
}
ECHO_M("Done.\n");
return;
}
#endif
//
// M100 F requests the code to return the number of free bytes in the memory pool along with
// other vital statistics that define the memory pool.
//
if ( code_seen('F') ) {
int max_addr = (int) __brkval;
int max_cnt = 0;
int block_cnt = 0;
ptr = (unsigned char *) __brkval;
sp = top_of_stack();
n = sp - ptr;
// Scan through the range looking for the biggest block of 0xE5's we can find
for(i = 0; i < n; i++) {
if ( *(ptr+i) == (unsigned char) 0xe5) {
j = how_many_E5s_are_here( (unsigned char *) ptr+i );
if ( j > 8) {
ECHO_MV("Found ", j );
ECHO_M(" bytes free at 0x");
prt_hex_word( (int) ptr+i );
ECHO_M("\n");
i += j;
block_cnt++;
}
if ( j>max_cnt) { // We don't do anything with this information yet
max_cnt = j; // but we do know where the biggest free memory block is.
max_addr = (int) ptr+i;
}
}
}
if (block_cnt>1)
ECHO_EM("\nMemory Corruption detected in free memory area.\n");
ECHO_M("\nDone.\n");
return;
}
//
// M100 C x Corrupts x locations in the free memory pool and reports the locations of the corruption.
// This is useful to check the correctness of the M100 D and the M100 F commands.
//
#if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
if ( code_seen('C') ) {
int x; // x gets the # of locations to corrupt within the memory pool
x = code_value();
ECHO_EM("Corrupting free memory block.\n");
ptr = (unsigned char *) __brkval;
ECHO_MV("\n__brkval : ",(long) ptr );
ptr += 8;
sp = top_of_stack();
ECHO_MV("\nStack Pointer : ",(long) sp );
ECHO_EM("\n");
n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that
// has altered the stack.
j = n / (x+1);
for(i = 1; i <= x; i++) {
*(ptr+(i*j)) = i;
ECHO_M("\nCorrupting address: 0x");
prt_hex_word( (unsigned int) (ptr+(i*j)) );
}
ECHO_EM("\n");
return;
}
#endif
//
// M100 I Initializes the free memory pool so it can be watched and prints vital
// statistics that define the free memory pool.
//
if (m100_not_initialized || code_seen('I') ) { // If no sub-command is specified, the first time
ECHO_EM("Initializing free memory block.\n"); // this happens, it will Initialize.
ptr = (unsigned char *) __brkval; // Repeated M100 with no sub-command will not destroy the
ECHO_MV("\n__brkval : ",(long) ptr ); // state of the initialized free memory pool.
ptr += 8;
sp = top_of_stack();
ECHO_MV("\nStack Pointer : ",(long) sp );
ECHO_EM("\n");
n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that
// has altered the stack.
ECHO_V( n );
ECHO_EM(" bytes of memory initialized.\n");
for(i = 0; i < n; i++)
*(ptr+i) = (unsigned char) 0xe5;
for(i = 0; i < n; i++) {
if ( *(ptr+i) != (unsigned char) 0xe5 ) {
ECHO_MV("? address : ", (unsigned long) ptr+i );
ECHO_MV("=", *(ptr+i) );
ECHO_EM("\n");
}
}
m100_not_initialized = 0;
ECHO_EM("Done.\n");
return;
}
return;
}
// top_of_stack() returns the location of a variable on its stack frame. The value returned is above
// the stack once the function returns to the caller.
unsigned char *top_of_stack() {
unsigned char x;
return &x + 1; // x is pulled on return;
}
//
// 3 support routines to print hex numbers. We can print a nibble, byte and word
//
void prt_hex_nibble( unsigned int n ) {
if ( n <= 9 )
ECHO_V(n);
else
ECHO_V( (char) ('A'+n-10) );
delay(2);
}
void prt_hex_byte(unsigned int b) {
prt_hex_nibble( ( b & 0xf0 ) >> 4 );
prt_hex_nibble( b & 0x0f );
}
void prt_hex_word(unsigned int w) {
prt_hex_byte( ( w & 0xff00 ) >> 8 );
prt_hex_byte( w & 0x0ff );
}
// how_many_E5s_are_here() is a utility function to easily find out how many 0xE5's are
// at the specified location. Having this logic as a function simplifies the search code.
//
int how_many_E5s_are_here( unsigned char *p) {
int n;
for(n = 0; n < 32000; n++) {
if ( *(p+n) != (unsigned char) 0xe5)
return n-1;
}
return -1;
}
#endif
#define M100_FREE_MEMORY_DUMPER // Comment out to remove Dump sub-command
#define M100_FREE_MEMORY_CORRUPTOR // Comment out to remove Corrupt sub-command
// M100 Free Memory Watcher
//
// This code watches the free memory block between the bottom of the heap and the top of the stack.
// This memory block is initialized and watched via the M100 command.
//
// M100 I Initializes the free memory block and prints vitals statistics about the area
// M100 F Identifies how much of the free memory block remains free and unused. It also
// detects and reports any corruption within the free memory block that may have
// happened due to errant firmware.
// M100 D Does a hex display of the free memory block along with a flag for any errant
// data that does not match the expected value.
// M100 C x Corrupts x locations within the free memory block. This is useful to check the
// correctness of the M100 F and M100 D commands.
//
// Initial version by Roxy-3DPrintBoard
//
//
#include "Marlin.h"
#if ENABLED(M100_FREE_MEMORY_WATCHER)
extern void *__brkval;
extern size_t __heap_start, __heap_end, __flp;
//
// Declare all the functions we need from Marlin_Main.cpp to do the work!
//
float code_value();
long code_value_long();
bool code_seen(char );
//
// Utility functions used by M100 to get its work done.
//
unsigned char *top_of_stack();
void prt_hex_nibble( unsigned int );
void prt_hex_byte(unsigned int );
void prt_hex_word(unsigned int );
int how_many_E5s_are_here( unsigned char *);
void gcode_M100() {
static int m100_not_initialized = 1;
unsigned char *sp, *ptr;
int i, j, n;
//
// M100 D dumps the free memory block from __brkval to the stack pointer.
// malloc() eats memory from the start of the block and the stack grows
// up from the bottom of the block. Solid 0xE5's indicate nothing has
// used that memory yet. There should not be anything but 0xE5's within
// the block of 0xE5's. If there is, that would indicate memory corruption
// probably caused by bad pointers. Any unexpected values will be flagged in
// the right hand column to help spotting them.
//
#if ENABLED(M100_FREE_MEMORY_DUMPER) // Comment out to remove Dump sub-command
if ( code_seen('D') ) {
ptr = (unsigned char *) __brkval;
//
// We want to start and end the dump on a nice 16 byte boundry even though
// the values we are using are not 16 byte aligned.
//
ECHO_M("\n__brkval : ");
prt_hex_word( (unsigned int) ptr );
ptr = (unsigned char *) ((unsigned long) ptr & 0xfff0);
sp = top_of_stack();
ECHO_M("\nStack Pointer : ");
prt_hex_word( (unsigned int) sp );
ECHO_M("\n");
sp = (unsigned char *) ((unsigned long) sp | 0x000f);
n = sp - ptr;
//
// This is the main loop of the Dump command.
//
while ( ptr < sp ) {
prt_hex_word( (unsigned int) ptr); // Print the address
ECHO_M(":");
for(i = 0; i < 16; i++) { // and 16 data bytes
prt_hex_byte( *(ptr+i));
ECHO_M(" ");
delay(2);
}
ECHO_M("|"); // now show where non 0xE5's are
for(i = 0; i < 16; i++) {
delay(2);
if ( *(ptr+i)==0xe5)
ECHO_M(" ");
else
ECHO_M("?");
}
ECHO_M("\n");
ptr += 16;
delay(2);
}
ECHO_M("Done.\n");
return;
}
#endif
//
// M100 F requests the code to return the number of free bytes in the memory pool along with
// other vital statistics that define the memory pool.
//
if ( code_seen('F') ) {
int max_addr = (int) __brkval;
int max_cnt = 0;
int block_cnt = 0;
ptr = (unsigned char *) __brkval;
sp = top_of_stack();
n = sp - ptr;
// Scan through the range looking for the biggest block of 0xE5's we can find
for(i = 0; i < n; i++) {
if ( *(ptr+i) == (unsigned char) 0xe5) {
j = how_many_E5s_are_here( (unsigned char *) ptr+i );
if ( j > 8) {
ECHO_MV("Found ", j );
ECHO_M(" bytes free at 0x");
prt_hex_word( (int) ptr+i );
ECHO_M("\n");
i += j;
block_cnt++;
}
if ( j>max_cnt) { // We don't do anything with this information yet
max_cnt = j; // but we do know where the biggest free memory block is.
max_addr = (int) ptr+i;
}
}
}
if (block_cnt>1)
ECHO_EM("\nMemory Corruption detected in free memory area.\n");
ECHO_M("\nDone.\n");
return;
}
//
// M100 C x Corrupts x locations in the free memory pool and reports the locations of the corruption.
// This is useful to check the correctness of the M100 D and the M100 F commands.
//
#if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
if ( code_seen('C') ) {
int x; // x gets the # of locations to corrupt within the memory pool
x = code_value();
ECHO_EM("Corrupting free memory block.\n");
ptr = (unsigned char *) __brkval;
ECHO_MV("\n__brkval : ",(long) ptr );
ptr += 8;
sp = top_of_stack();
ECHO_MV("\nStack Pointer : ",(long) sp );
ECHO_EM("\n");
n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that
// has altered the stack.
j = n / (x+1);
for(i = 1; i <= x; i++) {
*(ptr+(i*j)) = i;
ECHO_M("\nCorrupting address: 0x");
prt_hex_word( (unsigned int) (ptr+(i*j)) );
}
ECHO_EM("\n");
return;
}
#endif
//
// M100 I Initializes the free memory pool so it can be watched and prints vital
// statistics that define the free memory pool.
//
if (m100_not_initialized || code_seen('I') ) { // If no sub-command is specified, the first time
ECHO_EM("Initializing free memory block.\n"); // this happens, it will Initialize.
ptr = (unsigned char *) __brkval; // Repeated M100 with no sub-command will not destroy the
ECHO_MV("\n__brkval : ",(long) ptr ); // state of the initialized free memory pool.
ptr += 8;
sp = top_of_stack();
ECHO_MV("\nStack Pointer : ",(long) sp );
ECHO_EM("\n");
n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that
// has altered the stack.
ECHO_V( n );
ECHO_EM(" bytes of memory initialized.\n");
for(i = 0; i < n; i++)
*(ptr+i) = (unsigned char) 0xe5;
for(i = 0; i < n; i++) {
if ( *(ptr+i) != (unsigned char) 0xe5 ) {
ECHO_MV("? address : ", (unsigned long) ptr+i );
ECHO_MV("=", *(ptr+i) );
ECHO_EM("\n");
}
}
m100_not_initialized = 0;
ECHO_EM("Done.\n");
return;
}
return;
}
// top_of_stack() returns the location of a variable on its stack frame. The value returned is above
// the stack once the function returns to the caller.
unsigned char *top_of_stack() {
unsigned char x;
return &x + 1; // x is pulled on return;
}
//
// 3 support routines to print hex numbers. We can print a nibble, byte and word
//
void prt_hex_nibble( unsigned int n ) {
if ( n <= 9 )
ECHO_V(n);
else
ECHO_V( (char) ('A'+n-10) );
delay(2);
}
void prt_hex_byte(unsigned int b) {
prt_hex_nibble( ( b & 0xf0 ) >> 4 );
prt_hex_nibble( b & 0x0f );
}
void prt_hex_word(unsigned int w) {
prt_hex_byte( ( w & 0xff00 ) >> 8 );
prt_hex_byte( w & 0x0ff );
}
// how_many_E5s_are_here() is a utility function to easily find out how many 0xE5's are
// at the specified location. Having this logic as a function simplifies the search code.
//
int how_many_E5s_are_here( unsigned char *p) {
int n;
for(n = 0; n < 32000; n++) {
if ( *(p+n) != (unsigned char) 0xe5)
return n-1;
}
return -1;
}
#endif
......@@ -1136,6 +1136,27 @@ long st_get_position(uint8_t axis) {
float st_get_position_mm(AxisEnum axis) { return st_get_position(axis) / axis_steps_per_unit[axis]; }
void enable_all_steppers() {
enable_x();
enable_y();
enable_z();
enable_e0();
enable_e1();
enable_e2();
enable_e3();
}
void disable_all_steppers() {
disable_x();
disable_y();
disable_z();
disable_e0();
disable_e1();
disable_e2();
disable_e3();
}
void finishAndDisableSteppers() {
st_synchronize();
disable_all_steppers();
......
......@@ -21,6 +21,17 @@
#ifndef STEPPER_H
#define STEPPER_H
/**
* Axis indices as enumerated constants
*
* A_AXIS and B_AXIS are used by COREXY printers
* X_HEAD and Y_HEAD is used for systems that don't have a 1:1 relationship between X_AXIS and X Head movement, like CoreXY bots.
*/
enum AxisEnum {X_AXIS=0, A_AXIS=0, Y_AXIS=1, B_AXIS=1, Z_AXIS=2, C_AXIS=2, E_AXIS=3, X_HEAD=4, Y_HEAD=5, Z_HEAD=5};
enum EndstopEnum {X_MIN=0, Y_MIN=1, Z_MIN=2, Z_PROBE=3, X_MAX=4, Y_MAX=5, Z_MAX=6, Z2_MIN=7, Z2_MAX=8};
#if DRIVER_EXTRUDERS > 3
#define E_STEP_WRITE(v) { if(current_block->active_driver == 3) { E3_STEP_WRITE(v); } else { if(current_block->active_driver == 2) { E2_STEP_WRITE(v); } else { if(current_block->active_driver == 1) { E1_STEP_WRITE(v); } else { E0_STEP_WRITE(v); }}}}
#define NORM_E_DIR() { if(current_block->active_driver == 3) { E3_DIR_WRITE( !INVERT_E3_DIR); } else { if(current_block->active_driver == 2) { E2_DIR_WRITE(!INVERT_E2_DIR); } else { if(current_block->active_driver == 1) { E1_DIR_WRITE(!INVERT_E1_DIR); } else { E0_DIR_WRITE(!INVERT_E0_DIR); }}}}
......@@ -77,6 +88,8 @@ void enable_endstops(bool check); // Enable/disable endstop checking
void checkStepperErrors(); //Print errors detected by the stepper
void enable_all_steppers();
void disable_all_steppers();
void finishAndDisableSteppers();
extern block_t *current_block; // A pointer to the block currently being traced
......
......@@ -152,6 +152,77 @@
#define E3_ENABLE_WRITE(STATE) WRITE(E3_ENABLE_PIN,STATE)
#define E3_ENABLE_READ READ(E3_ENABLE_PIN)
#if ENABLED(DUAL_X_CARRIAGE) && HAS(X_ENABLE) && 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)
#elif HAS(X_ENABLE)
#define enable_x() X_ENABLE_WRITE( X_ENABLE_ON)
#define disable_x() { X_ENABLE_WRITE(!X_ENABLE_ON); axis_known_position[X_AXIS] = false; }
#else
#define enable_x() ;
#define disable_x() ;
#endif
#if HAS(Y_ENABLE)
#if ENABLED(Y_DUAL_STEPPER_DRIVERS)
#define enable_y() { Y_ENABLE_WRITE( Y_ENABLE_ON); Y2_ENABLE_WRITE(Y_ENABLE_ON); }
#define disable_y() { Y_ENABLE_WRITE(!Y_ENABLE_ON); Y2_ENABLE_WRITE(!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
#else
#define enable_y() Y_ENABLE_WRITE( Y_ENABLE_ON)
#define disable_y() { Y_ENABLE_WRITE(!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
#endif
#else
#define enable_y() ;
#define disable_y() ;
#endif
#if HAS(Z_ENABLE)
#if ENABLED(Z_DUAL_STEPPER_DRIVERS)
#define enable_z() { Z_ENABLE_WRITE( Z_ENABLE_ON); Z2_ENABLE_WRITE(Z_ENABLE_ON); }
#define disable_z() { Z_ENABLE_WRITE(!Z_ENABLE_ON); Z2_ENABLE_WRITE(!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
#else
#define enable_z() Z_ENABLE_WRITE( Z_ENABLE_ON)
#define disable_z() { Z_ENABLE_WRITE(!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
#endif
#else
#define enable_z() ;
#define disable_z() ;
#endif
#if HAS(E0_ENABLE)
#define enable_e0() E0_ENABLE_WRITE( E_ENABLE_ON)
#define disable_e0() E0_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_e0() /* nothing */
#define disable_e0() /* nothing */
#endif
#if (DRIVER_EXTRUDERS > 1) && HAS(E1_ENABLE)
#define enable_e1() E1_ENABLE_WRITE( E_ENABLE_ON)
#define disable_e1() E1_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_e1() /* nothing */
#define disable_e1() /* nothing */
#endif
#if (DRIVER_EXTRUDERS > 2) && HAS(E2_ENABLE)
#define enable_e2() E2_ENABLE_WRITE( E_ENABLE_ON)
#define disable_e2() E2_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_e2() /* nothing */
#define disable_e2() /* nothing */
#endif
#if (DRIVER_EXTRUDERS > 3) && HAS(E3_ENABLE)
#define enable_e3() E3_ENABLE_WRITE( E_ENABLE_ON)
#define disable_e3() E3_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_e3() /* nothing */
#define disable_e3() /* nothing */
#endif
#define disable_e() {disable_e0(); disable_e1(); disable_e2(); disable_e3();}
//////////////////////////////////
// Pin redefines for TMC drivers.
// TMC26X drivers have step and dir on normal pins, but everything else via SPI
......
......@@ -20,6 +20,9 @@
#include "elements.h"
#include "Marlin_main.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#endif
#include "ultralcd.h"
#include "planner.h"
#include "stepper_indirection.h"
......@@ -867,7 +870,7 @@ static void updateTemperaturesFromRawValues() {
}
#if HAS(FILAMENT_SENSOR)
#if ENABLED(FILAMENT_SENSOR)
// Convert raw Filament Width to millimeters
float analog2widthFil() {
......
......@@ -25,7 +25,7 @@
void tp_init(); //initialize the heating
void manage_heater(); //it is critical that this is called periodically.
#if HAS(FILAMENT_SENSOR)
#if ENABLED(FILAMENT_SENSOR)
// For converting raw Filament Width to milimeters
float analog2widthFil();
......
......@@ -2391,6 +2391,7 @@ char *ftostr52(const float &x) {
#include "stepper_indirection.h"
#include "stepper.h"
#include "configuration_store.h"
#include "ultralcd.h"
#include "Nextion.h"
bool NextionON = false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment