Merge remote-tracking branch 'upstream/Development' into Development

master
CONSULitAS 10 years ago
commit 703f3b38c4

@ -225,6 +225,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@ -372,6 +374,23 @@ const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o
//const bool FIL_RUNOUT_INVERTING = true; // Should be uncommented and true or false should assigned
//#define ENDSTOPPULLUP_FIL_RUNOUT // Uncomment to use internal pullup for filament runout pins if the sensor is defined.
//===========================================================================
//============================ Manual Bed Leveling ==========================
//===========================================================================
// #define MANUAL_BED_LEVELING // Add display menu option for bed leveling
// #define MESH_BED_LEVELING // Enable mesh bed leveling
#if defined(MESH_BED_LEVELING)
#define MESH_MIN_X 10
#define MESH_MAX_X (X_MAX_POS - MESH_MIN_X)
#define MESH_MIN_Y 10
#define MESH_MAX_Y (Y_MAX_POS - MESH_MIN_Y)
#define MESH_NUM_X_POINTS 3 // Don't use more than 7 points per axis, implementation limited
#define MESH_NUM_Y_POINTS 3
#define MESH_HOME_SEARCH_Z 4 // Z after Home, bed somewhere below but above 0.0
#endif // MESH_BED_LEVELING
//===========================================================================
//============================= Bed Auto Leveling ===========================
//===========================================================================
@ -398,12 +417,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// The edges of the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define FRONT_PROBE_BED_POSITION 20

@ -18,7 +18,13 @@
* max_xy_jerk
* max_z_jerk
* max_e_jerk
* add_homing (x3)
* home_offset (x3)
*
* Mesh bed leveling:
* active
* mesh_num_x
* mesh_num_y
* z_values[][]
*
* DELTA:
* endstop_adj (x3)
@ -69,6 +75,10 @@
#include "ultralcd.h"
#include "ConfigurationStore.h"
#if defined(MESH_BED_LEVELING)
#include "mesh_bed_leveling.h"
#endif // MESH_BED_LEVELING
void _EEPROM_writeData(int &pos, uint8_t* value, uint8_t size) {
uint8_t c;
while(size--) {
@ -105,7 +115,7 @@ void _EEPROM_readData(int &pos, uint8_t* value, uint8_t size) {
// wrong data being written to the variables.
// ALSO: always make sure the variables in the Store and retrieve sections are in the same order.
#define EEPROM_VERSION "V16"
#define EEPROM_VERSION "V17"
#ifdef EEPROM_SETTINGS
@ -126,7 +136,29 @@ void Config_StoreSettings() {
EEPROM_WRITE_VAR(i, max_xy_jerk);
EEPROM_WRITE_VAR(i, max_z_jerk);
EEPROM_WRITE_VAR(i, max_e_jerk);
EEPROM_WRITE_VAR(i, add_homing);
EEPROM_WRITE_VAR(i, home_offset);
uint8_t mesh_num_x = 3;
uint8_t mesh_num_y = 3;
#if defined(MESH_BED_LEVELING)
// Compile time test that sizeof(mbl.z_values) is as expected
typedef char c_assert[(sizeof(mbl.z_values) == MESH_NUM_X_POINTS*MESH_NUM_Y_POINTS*sizeof(dummy)) ? 1 : -1];
mesh_num_x = MESH_NUM_X_POINTS;
mesh_num_y = MESH_NUM_Y_POINTS;
EEPROM_WRITE_VAR(i, mbl.active);
EEPROM_WRITE_VAR(i, mesh_num_x);
EEPROM_WRITE_VAR(i, mesh_num_y);
EEPROM_WRITE_VAR(i, mbl.z_values);
#else
uint8_t dummy_uint8 = 0;
EEPROM_WRITE_VAR(i, dummy_uint8);
EEPROM_WRITE_VAR(i, mesh_num_x);
EEPROM_WRITE_VAR(i, mesh_num_y);
dummy = 0.0f;
for (int q=0; q<mesh_num_x*mesh_num_y; q++) {
EEPROM_WRITE_VAR(i, dummy);
}
#endif // MESH_BED_LEVELING
#ifdef DELTA
EEPROM_WRITE_VAR(i, endstop_adj); // 3 floats
@ -250,7 +282,7 @@ void Config_RetrieveSettings() {
EEPROM_READ_VAR(i, max_feedrate);
EEPROM_READ_VAR(i, max_acceleration_units_per_sq_second);
// steps per sq second need to be updated to agree with the units per sq second (as they are what is used in the planner)
// steps per sq second need to be updated to agree with the units per sq second (as they are what is used in the planner)
reset_acceleration_rates();
EEPROM_READ_VAR(i, acceleration);
@ -262,7 +294,32 @@ void Config_RetrieveSettings() {
EEPROM_READ_VAR(i, max_xy_jerk);
EEPROM_READ_VAR(i, max_z_jerk);
EEPROM_READ_VAR(i, max_e_jerk);
EEPROM_READ_VAR(i, add_homing);
EEPROM_READ_VAR(i, home_offset);
uint8_t mesh_num_x = 0;
uint8_t mesh_num_y = 0;
#if defined(MESH_BED_LEVELING)
EEPROM_READ_VAR(i, mbl.active);
EEPROM_READ_VAR(i, mesh_num_x);
EEPROM_READ_VAR(i, mesh_num_y);
if (mesh_num_x != MESH_NUM_X_POINTS ||
mesh_num_y != MESH_NUM_Y_POINTS) {
mbl.reset();
for (int q=0; q<mesh_num_x*mesh_num_y; q++) {
EEPROM_READ_VAR(i, dummy);
}
} else {
EEPROM_READ_VAR(i, mbl.z_values);
}
#else
uint8_t dummy_uint8 = 0;
EEPROM_READ_VAR(i, dummy_uint8);
EEPROM_READ_VAR(i, mesh_num_x);
EEPROM_READ_VAR(i, mesh_num_y);
for (int q=0; q<mesh_num_x*mesh_num_y; q++) {
EEPROM_READ_VAR(i, dummy);
}
#endif // MESH_BED_LEVELING
#ifdef DELTA
EEPROM_READ_VAR(i, endstop_adj); // 3 floats
@ -390,7 +447,11 @@ void Config_ResetDefault() {
max_xy_jerk = DEFAULT_XYJERK;
max_z_jerk = DEFAULT_ZJERK;
max_e_jerk = DEFAULT_EJERK;
add_homing[X_AXIS] = add_homing[Y_AXIS] = add_homing[Z_AXIS] = 0;
home_offset[X_AXIS] = home_offset[Y_AXIS] = home_offset[Z_AXIS] = 0;
#if defined(MESH_BED_LEVELING)
mbl.active = 0;
#endif // MESH_BED_LEVELING
#ifdef DELTA
endstop_adj[X_AXIS] = endstop_adj[Y_AXIS] = endstop_adj[Z_AXIS] = 0;
@ -546,9 +607,9 @@ void Config_PrintSettings(bool forReplay) {
SERIAL_ECHOLNPGM("Home offset (mm):");
SERIAL_ECHO_START;
}
SERIAL_ECHOPAIR(" M206 X", add_homing[X_AXIS] );
SERIAL_ECHOPAIR(" Y", add_homing[Y_AXIS] );
SERIAL_ECHOPAIR(" Z", add_homing[Z_AXIS] );
SERIAL_ECHOPAIR(" M206 X", home_offset[X_AXIS] );
SERIAL_ECHOPAIR(" Y", home_offset[Y_AXIS] );
SERIAL_ECHOPAIR(" Z", home_offset[Z_AXIS] );
SERIAL_EOL;
#ifdef DELTA

@ -240,7 +240,7 @@ extern int extruder_multiply[EXTRUDERS]; // sets extrude multiply factor (in per
extern float filament_size[EXTRUDERS]; // cross-sectional area of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder.
extern float volumetric_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner
extern float current_position[NUM_AXIS] ;
extern float add_homing[3];
extern float home_offset[3];
#ifdef DELTA
extern float endstop_adj[3];
extern float delta_radius;

@ -41,6 +41,10 @@
#define SERVO_LEVELING defined(ENABLE_AUTO_BED_LEVELING) && PROBE_SERVO_DEACTIVATION_DELAY > 0
#if defined(MESH_BED_LEVELING)
#include "mesh_bed_leveling.h"
#endif // MESH_BED_LEVELING
#include "ultralcd.h"
#include "planner.h"
#include "stepper.h"
@ -244,7 +248,7 @@ float volumetric_multiplier[EXTRUDERS] = {1.0
#endif
};
float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 };
float add_homing[3] = { 0, 0, 0 };
float home_offset[3] = { 0, 0, 0 };
#ifdef DELTA
float endstop_adj[3] = { 0, 0, 0 };
#endif
@ -980,7 +984,7 @@ static int dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
static float x_home_pos(int extruder) {
if (extruder == 0)
return base_home_pos(X_AXIS) + add_homing[X_AXIS];
return base_home_pos(X_AXIS) + home_offset[X_AXIS];
else
// In dual carriage mode the extruder offset provides an override of the
// second X-carriage offset when homed - otherwise X2_HOME_POS is used.
@ -1012,9 +1016,9 @@ static void axis_is_at_home(int axis) {
return;
}
else if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && active_extruder == 0) {
current_position[X_AXIS] = base_home_pos(X_AXIS) + add_homing[X_AXIS];
min_pos[X_AXIS] = base_min_pos(X_AXIS) + add_homing[X_AXIS];
max_pos[X_AXIS] = min(base_max_pos(X_AXIS) + add_homing[X_AXIS],
current_position[X_AXIS] = base_home_pos(X_AXIS) + home_offset[X_AXIS];
min_pos[X_AXIS] = base_min_pos(X_AXIS) + home_offset[X_AXIS];
max_pos[X_AXIS] = min(base_max_pos(X_AXIS) + home_offset[X_AXIS],
max(extruder_offset[X_AXIS][1], X2_MAX_POS) - duplicate_extruder_x_offset);
return;
}
@ -1042,11 +1046,11 @@ static void axis_is_at_home(int axis) {
for (i=0; i<2; i++)
{
delta[i] -= add_homing[i];
delta[i] -= home_offset[i];
}
// SERIAL_ECHOPGM("addhome X="); SERIAL_ECHO(add_homing[X_AXIS]);
// SERIAL_ECHOPGM(" addhome Y="); SERIAL_ECHO(add_homing[Y_AXIS]);
// SERIAL_ECHOPGM("addhome X="); SERIAL_ECHO(home_offset[X_AXIS]);
// SERIAL_ECHOPGM(" addhome Y="); SERIAL_ECHO(home_offset[Y_AXIS]);
// SERIAL_ECHOPGM(" addhome Theta="); SERIAL_ECHO(delta[X_AXIS]);
// SERIAL_ECHOPGM(" addhome Psi+Theta="); SERIAL_ECHOLN(delta[Y_AXIS]);
@ -1064,14 +1068,14 @@ static void axis_is_at_home(int axis) {
}
else
{
current_position[axis] = base_home_pos(axis) + add_homing[axis];
min_pos[axis] = base_min_pos(axis) + add_homing[axis];
max_pos[axis] = base_max_pos(axis) + add_homing[axis];
current_position[axis] = base_home_pos(axis) + home_offset[axis];
min_pos[axis] = base_min_pos(axis) + home_offset[axis];
max_pos[axis] = base_max_pos(axis) + home_offset[axis];
}
#else
current_position[axis] = base_home_pos(axis) + add_homing[axis];
min_pos[axis] = base_min_pos(axis) + add_homing[axis];
max_pos[axis] = base_max_pos(axis) + add_homing[axis];
current_position[axis] = base_home_pos(axis) + home_offset[axis];
min_pos[axis] = base_min_pos(axis) + home_offset[axis];
max_pos[axis] = base_max_pos(axis) + home_offset[axis];
#endif
}
@ -1305,7 +1309,13 @@ static void engage_z_probe() {
static void retract_z_probe() {
// Retract Z Servo endstop if enabled
#ifdef SERVO_ENDSTOPS
if (servo_endstops[Z_AXIS] > -1) {
if (servo_endstops[Z_AXIS] > -1)
{
#if Z_RAISE_AFTER_PROBING > 0
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_RAISE_AFTER_PROBING);
st_synchronize();
#endif
#if SERVO_LEVELING
servos[servo_endstops[Z_AXIS]].attach(0);
#endif
@ -1318,7 +1328,7 @@ static void retract_z_probe() {
#elif defined(Z_PROBE_ALLEN_KEY)
// Move up for safety
feedrate = homing_feedrate[X_AXIS];
destination[Z_AXIS] = current_position[Z_AXIS] + 20;
destination[Z_AXIS] = current_position[Z_AXIS] + Z_RAISE_AFTER_PROBING;
prepare_move_raw();
// Move to the start position to initiate retraction
@ -1360,10 +1370,15 @@ static void retract_z_probe() {
}
enum ProbeAction { ProbeStay, ProbeEngage, ProbeRetract, ProbeEngageRetract };
enum ProbeAction {
ProbeStay = 0,
ProbeEngage = BIT(0),
ProbeRetract = BIT(1),
ProbeEngageAndRetract = (ProbeEngage | ProbeRetract)
};
/// Probe bed height at position (x,y), returns the measured z value
static float probe_pt(float x, float y, float z_before, ProbeAction retract_action=ProbeEngageRetract, int verbose_level=1) {
static float probe_pt(float x, float y, float z_before, ProbeAction retract_action=ProbeEngageAndRetract, int verbose_level=1) {
// move to right place
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], z_before);
do_blocking_move_to(x - X_PROBE_OFFSET_FROM_EXTRUDER, y - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[Z_AXIS]);
@ -1737,6 +1752,11 @@ inline void gcode_G28() {
#endif
#endif
#if defined(MESH_BED_LEVELING)
uint8_t mbl_was_active = mbl.active;
mbl.active = 0;
#endif // MESH_BED_LEVELING
saved_feedrate = feedrate;
saved_feedmultiply = feedmultiply;
feedmultiply = 100;
@ -1849,7 +1869,7 @@ inline void gcode_G28() {
if (code_value_long() != 0) {
current_position[X_AXIS] = code_value()
#ifndef SCARA
+ add_homing[X_AXIS]
+ home_offset[X_AXIS]
#endif
;
}
@ -1858,7 +1878,7 @@ inline void gcode_G28() {
if (code_seen(axis_codes[Y_AXIS]) && code_value_long() != 0) {
current_position[Y_AXIS] = code_value()
#ifndef SCARA
+ add_homing[Y_AXIS]
+ home_offset[Y_AXIS]
#endif
;
}
@ -1932,7 +1952,7 @@ inline void gcode_G28() {
if (code_seen(axis_codes[Z_AXIS]) && code_value_long() != 0)
current_position[Z_AXIS] = code_value() + add_homing[Z_AXIS];
current_position[Z_AXIS] = code_value() + home_offset[Z_AXIS];
#ifdef ENABLE_AUTO_BED_LEVELING
if (home_all_axis || code_seen(axis_codes[Z_AXIS]))
@ -1951,12 +1971,112 @@ inline void gcode_G28() {
enable_endstops(false);
#endif
#if defined(MESH_BED_LEVELING)
if (mbl_was_active) {
current_position[X_AXIS] = mbl.get_x(0);
current_position[Y_AXIS] = mbl.get_y(0);
destination[X_AXIS] = current_position[X_AXIS];
destination[Y_AXIS] = current_position[Y_AXIS];
destination[Z_AXIS] = current_position[Z_AXIS];
destination[E_AXIS] = current_position[E_AXIS];
feedrate = homing_feedrate[X_AXIS];
plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate, active_extruder);
st_synchronize();
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
mbl.active = 1;
}
#endif
feedrate = saved_feedrate;
feedmultiply = saved_feedmultiply;
previous_millis_cmd = millis();
endstops_hit_on_purpose();
}
#if defined(MESH_BED_LEVELING)
inline void gcode_G29() {
static int probe_point = -1;
int state = 0;
if (code_seen('S') || code_seen('s')) {
state = code_value_long();
if (state < 0 || state > 2) {
SERIAL_PROTOCOLPGM("S out of range (0-2).\n");
return;
}
}
if (state == 0) { // Dump mesh_bed_leveling
if (mbl.active) {
SERIAL_PROTOCOLPGM("Num X,Y: ");
SERIAL_PROTOCOL(MESH_NUM_X_POINTS);
SERIAL_PROTOCOLPGM(",");
SERIAL_PROTOCOL(MESH_NUM_Y_POINTS);
SERIAL_PROTOCOLPGM("\nZ search height: ");
SERIAL_PROTOCOL(MESH_HOME_SEARCH_Z);
SERIAL_PROTOCOLPGM("\nMeasured points:\n");
for (int y=0; y<MESH_NUM_Y_POINTS; y++) {
for (int x=0; x<MESH_NUM_X_POINTS; x++) {
SERIAL_PROTOCOLPGM(" ");
SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5);
}
SERIAL_EOL;
}
} else {
SERIAL_PROTOCOLPGM("Mesh bed leveling not active.\n");
}
} else if (state == 1) { // Begin probing mesh points
mbl.reset();
probe_point = 0;
enquecommands_P(PSTR("G28"));
enquecommands_P(PSTR("G29 S2"));
} else if (state == 2) { // Goto next point
if (probe_point < 0) {
SERIAL_PROTOCOLPGM("Mesh probing not started.\n");
return;
}
int ix, iy;
if (probe_point == 0) {
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
} else {
ix = (probe_point-1) % MESH_NUM_X_POINTS;
iy = (probe_point-1) / MESH_NUM_X_POINTS;
if (iy&1) { // Zig zag
ix = (MESH_NUM_X_POINTS - 1) - ix;
}
mbl.set_z(ix, iy, current_position[Z_AXIS]);
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], homing_feedrate[X_AXIS]/60, active_extruder);
st_synchronize();
}
if (probe_point == MESH_NUM_X_POINTS*MESH_NUM_Y_POINTS) {
SERIAL_PROTOCOLPGM("Mesh done.\n");
probe_point = -1;
mbl.active = 1;
enquecommands_P(PSTR("G28"));
return;
}
ix = probe_point % MESH_NUM_X_POINTS;
iy = probe_point / MESH_NUM_X_POINTS;
if (iy&1) { // Zig zag
ix = (MESH_NUM_X_POINTS - 1) - ix;
}
current_position[X_AXIS] = mbl.get_x(ix);
current_position[Y_AXIS] = mbl.get_y(iy);
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], homing_feedrate[X_AXIS]/60, active_extruder);
st_synchronize();
probe_point++;
}
}
#endif
#ifdef ENABLE_AUTO_BED_LEVELING
// Define the possible boundaries for probing based on set limits
@ -2057,7 +2177,7 @@ inline void gcode_G28() {
#ifdef AUTO_BED_LEVELING_GRID
#ifndef DELTA
bool topo_flag = verbose_level > 2 || code_seen('T') || code_seen('t');
bool do_topography_map = verbose_level > 2 || code_seen('T') || code_seen('t');
#endif
if (verbose_level > 0)
@ -2112,15 +2232,16 @@ inline void gcode_G28() {
#ifdef Z_PROBE_SLED
dock_sled(false); // engage (un-dock) the probe
#elif not defined(SERVO_ENDSTOPS)
#elif defined(Z_PROBE_ALLEN_KEY)
engage_z_probe();
#endif
st_synchronize();
#ifdef DELTA
reset_bed_level();
#else
#ifdef DELTA
reset_bed_level();
#else
// make sure the bed_level_rotation_matrix is identity or the planner will get it incorectly
//vector_3 corrected_position = plan_get_position_mm();
//corrected_position.debug("position before G29");
@ -2161,42 +2282,36 @@ inline void gcode_G28() {
delta_grid_spacing[1] = yGridSpacing;
float z_offset = Z_PROBE_OFFSET_FROM_EXTRUDER;
if (code_seen(axis_codes[Z_AXIS])) {
z_offset += code_value();
}
if (code_seen(axis_codes[Z_AXIS])) z_offset += code_value();
#endif
int probePointCounter = 0;
bool zig = true;
for (int yCount=0; yCount < auto_bed_leveling_grid_points; yCount++)
{
for (int yCount = 0; yCount < auto_bed_leveling_grid_points; yCount++) {
double yProbe = front_probe_bed_position + yGridSpacing * yCount;
int xStart, xStop, xInc;
if (zig)
{
if (zig) {
xStart = 0;
xStop = auto_bed_leveling_grid_points;
xInc = 1;
zig = false;
}
else
{
else {
xStart = auto_bed_leveling_grid_points - 1;
xStop = -1;
xInc = -1;
zig = true;
}
#ifndef DELTA
// If topo_flag is set then don't zig-zag. Just scan in one direction.
// This gets the probe points in more readable order.
if (!topo_flag) zig = !zig;
#endif
#ifndef DELTA
// If do_topography_map is set then don't zig-zag. Just scan in one direction.
// This gets the probe points in more readable order.
if (!do_topography_map) zig = !zig;
#endif
for (int xCount=xStart; xCount != xStop; xCount += xInc)
{
for (int xCount = xStart; xCount != xStop; xCount += xInc) {
double xProbe = left_probe_bed_position + xGridSpacing * xCount;
// raise extruder
@ -2221,7 +2336,7 @@ inline void gcode_G28() {
act = ProbeStay;
}
else
act = ProbeEngageRetract;
act = ProbeEngageAndRetract;
measured_z = probe_pt(xProbe, yProbe, z_before, act, verbose_level);
@ -2263,49 +2378,31 @@ inline void gcode_G28() {
}
}
if (topo_flag) {
int xx, yy;
// Show the Topography map if enabled
if (do_topography_map) {
SERIAL_PROTOCOLPGM(" \nBed Height Topography: \n");
#if TOPO_ORIGIN == OriginFrontLeft
SERIAL_PROTOCOLPGM("+-----------+\n");
SERIAL_PROTOCOLPGM("|...Back....|\n");
SERIAL_PROTOCOLPGM("|Left..Right|\n");
SERIAL_PROTOCOLPGM("|...Front...|\n");
SERIAL_PROTOCOLPGM("+-----------+\n");
for (yy = auto_bed_leveling_grid_points - 1; yy >= 0; yy--)
#else
for (yy = 0; yy < auto_bed_leveling_grid_points; yy++)
#endif
{
#if TOPO_ORIGIN == OriginBackRight
for (xx = 0; xx < auto_bed_leveling_grid_points; xx++)
#else
for (xx = auto_bed_leveling_grid_points - 1; xx >= 0; xx--)
#endif
{
int ind =
#if TOPO_ORIGIN == OriginBackRight || TOPO_ORIGIN == OriginFrontLeft
yy * auto_bed_leveling_grid_points + xx
#elif TOPO_ORIGIN == OriginBackLeft
xx * auto_bed_leveling_grid_points + yy
#elif TOPO_ORIGIN == OriginFrontRight
abl2 - xx * auto_bed_leveling_grid_points - yy - 1
#endif
;
float diff = eqnBVector[ind] - mean;
if (diff >= 0.0)
SERIAL_PROTOCOLPGM(" +"); // Include + for column alignment
else
SERIAL_PROTOCOLPGM(" ");
SERIAL_PROTOCOL_F(diff, 5);
} // xx
SERIAL_EOL;
} // yy
SERIAL_PROTOCOLPGM("+-----------+\n");
SERIAL_PROTOCOLPGM("|...Back....|\n");
SERIAL_PROTOCOLPGM("|Left..Right|\n");
SERIAL_PROTOCOLPGM("|...Front...|\n");
SERIAL_PROTOCOLPGM("+-----------+\n");
for (int yy = auto_bed_leveling_grid_points - 1; yy >= 0; yy--) {
for (int xx = auto_bed_leveling_grid_points - 1; xx >= 0; xx--) {
int ind = yy * auto_bed_leveling_grid_points + xx;
float diff = eqnBVector[ind] - mean;
if (diff >= 0.0)
SERIAL_PROTOCOLPGM(" +"); // Include + for column alignment
else
SERIAL_PROTOCOLPGM(" ");
SERIAL_PROTOCOL_F(diff, 5);
} // xx
SERIAL_EOL;
} // yy
SERIAL_EOL;
} //topo_flag
} //do_topography_map
set_bed_level_equation_lsq(plane_equation_coefficients);
@ -2327,18 +2424,15 @@ inline void gcode_G28() {
z_at_pt_3 = probe_pt(ABL_PROBE_PT_3_X, ABL_PROBE_PT_3_Y, current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS, ProbeRetract, verbose_level);
}
else {
z_at_pt_1 = probe_pt(ABL_PROBE_PT_1_X, ABL_PROBE_PT_1_Y, Z_RAISE_BEFORE_PROBING, verbose_level=verbose_level);
z_at_pt_2 = probe_pt(ABL_PROBE_PT_2_X, ABL_PROBE_PT_2_Y, current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS, verbose_level=verbose_level);
z_at_pt_3 = probe_pt(ABL_PROBE_PT_3_X, ABL_PROBE_PT_3_Y, current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS, verbose_level=verbose_level);
z_at_pt_1 = probe_pt(ABL_PROBE_PT_1_X, ABL_PROBE_PT_1_Y, Z_RAISE_BEFORE_PROBING, ProbeEngageAndRetract, verbose_level);
z_at_pt_2 = probe_pt(ABL_PROBE_PT_2_X, ABL_PROBE_PT_2_Y, current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS, ProbeEngageAndRetract, verbose_level);
z_at_pt_3 = probe_pt(ABL_PROBE_PT_3_X, ABL_PROBE_PT_3_Y, current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS, ProbeEngageAndRetract, verbose_level);
}
clean_up_after_endstop_move();
set_bed_level_equation_3pts(z_at_pt_1, z_at_pt_2, z_at_pt_3);
#endif // !AUTO_BED_LEVELING_GRID
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_RAISE_AFTER_PROBING);
st_synchronize();
#ifndef DELTA
if (verbose_level > 0)
plan_bed_level_matrix.debug(" \n\nBed Level Correction Matrix:");
@ -2358,7 +2452,7 @@ inline void gcode_G28() {
#ifdef Z_PROBE_SLED
dock_sled(true, -SLED_DOCKING_OFFSET); // dock the probe, correcting for over-travel
#elif not defined(SERVO_ENDSTOPS)
#elif defined(Z_PROBE_ALLEN_KEY)
retract_z_probe();
#endif
@ -2403,22 +2497,13 @@ inline void gcode_G92() {
if (!code_seen(axis_codes[E_AXIS]))
st_synchronize();
for (int i=0;i<NUM_AXIS;i++) {
for (int i = 0; i < NUM_AXIS; i++) {
if (code_seen(axis_codes[i])) {
if (i == E_AXIS) {
current_position[i] = code_value();
current_position[i] = code_value();
if (i == E_AXIS)
plan_set_e_position(current_position[E_AXIS]);
}
else {
current_position[i] = code_value() +
#ifdef SCARA
((i != X_AXIS && i != Y_AXIS) ? add_homing[i] : 0)
#else
add_homing[i]
#endif
;
else
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
}
}
}
}
@ -2562,13 +2647,13 @@ inline void gcode_M17() {
*/
inline void gcode_M28() {
char* codepos = strchr_pointer + 4;
char* starpos = strchr(strchr_pointer + 4, '*');
char* starpos = strchr(codepos, '*');
if (starpos) {
char* npos = strchr(cmdbuffer[bufindr], 'N');
strchr_pointer = strchr(npos, ' ') + 1;
*(starpos) = '\0';
}
card.openFile(strchr_pointer + 4, false);
card.openFile(codepos, false);
}
/**
@ -3355,9 +3440,9 @@ inline void gcode_M114() {
SERIAL_PROTOCOLLN("");
SERIAL_PROTOCOLPGM("SCARA Cal - Theta:");
SERIAL_PROTOCOL(delta[X_AXIS]+add_homing[X_AXIS]);
SERIAL_PROTOCOL(delta[X_AXIS]+home_offset[X_AXIS]);
SERIAL_PROTOCOLPGM(" Psi+Theta (90):");
SERIAL_PROTOCOL(delta[Y_AXIS]-delta[X_AXIS]-90+add_homing[Y_AXIS]);
SERIAL_PROTOCOL(delta[Y_AXIS]-delta[X_AXIS]-90+home_offset[Y_AXIS]);
SERIAL_PROTOCOLLN("");
SERIAL_PROTOCOLPGM("SCARA step Cal - Theta:");
@ -3575,12 +3660,12 @@ inline void gcode_M205() {
inline void gcode_M206() {
for (int8_t i=X_AXIS; i <= Z_AXIS; i++) {
if (code_seen(axis_codes[i])) {
add_homing[i] = code_value();
home_offset[i] = code_value();
}
}
#ifdef SCARA
if (code_seen('T')) add_homing[X_AXIS] = code_value(); // Theta
if (code_seen('P')) add_homing[Y_AXIS] = code_value(); // Psi
if (code_seen('T')) home_offset[X_AXIS] = code_value(); // Theta
if (code_seen('P')) home_offset[Y_AXIS] = code_value(); // Psi
#endif
}
@ -3967,18 +4052,13 @@ inline void gcode_M303() {
}
#ifdef SCARA
/**
* M360: SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
*/
inline bool gcode_M360() {
SERIAL_ECHOLN(" Cal: Theta 0 ");
bool SCARA_move_to_cal(uint8_t delta_x, uint8_t delta_y) {
//SoftEndsEnabled = false; // Ignore soft endstops during calibration
//SERIAL_ECHOLN(" Soft endstops disabled ");
if (! Stopped) {
//get_coordinates(); // For X Y Z E F
delta[X_AXIS] = 0;
delta[Y_AXIS] = 120;
delta[X_AXIS] = delta_x;
delta[Y_AXIS] = delta_y;
calculate_SCARA_forward_Transform(delta);
destination[X_AXIS] = delta[X_AXIS]/axis_scaling[X_AXIS];
destination[Y_AXIS] = delta[Y_AXIS]/axis_scaling[Y_AXIS];
@ -3989,25 +4069,20 @@ inline void gcode_M303() {
return false;
}
/**
* M360: SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
*/
inline bool gcode_M360() {
SERIAL_ECHOLN(" Cal: Theta 0 ");
return SCARA_move_to_cal(0, 120);
}
/**
* M361: SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
*/
inline bool gcode_M361() {
SERIAL_ECHOLN(" Cal: Theta 90 ");
//SoftEndsEnabled = false; // Ignore soft endstops during calibration
//SERIAL_ECHOLN(" Soft endstops disabled ");
if (! Stopped) {
//get_coordinates(); // For X Y Z E F
delta[X_AXIS] = 90;
delta[Y_AXIS] = 130;
calculate_SCARA_forward_Transform(delta);
destination[X_AXIS] = delta[X_AXIS]/axis_scaling[X_AXIS];
destination[Y_AXIS] = delta[Y_AXIS]/axis_scaling[Y_AXIS];
prepare_move();
//ClearToSend();
return true;
}
return false;
return SCARA_move_to_cal(90, 130);
}
/**
@ -4015,20 +4090,7 @@ inline void gcode_M303() {
*/
inline bool gcode_M362() {
SERIAL_ECHOLN(" Cal: Psi 0 ");
//SoftEndsEnabled = false; // Ignore soft endstops during calibration
//SERIAL_ECHOLN(" Soft endstops disabled ");
if (! Stopped) {
//get_coordinates(); // For X Y Z E F
delta[X_AXIS] = 60;
delta[Y_AXIS] = 180;
calculate_SCARA_forward_Transform(delta);
destination[X_AXIS] = delta[X_AXIS]/axis_scaling[X_AXIS];
destination[Y_AXIS] = delta[Y_AXIS]/axis_scaling[Y_AXIS];
prepare_move();
//ClearToSend();
return true;
}
return false;
return SCARA_move_to_cal(60, 180);
}
/**
@ -4036,20 +4098,7 @@ inline void gcode_M303() {
*/
inline bool gcode_M363() {
SERIAL_ECHOLN(" Cal: Psi 90 ");
//SoftEndsEnabled = false; // Ignore soft endstops during calibration
//SERIAL_ECHOLN(" Soft endstops disabled ");
if (! Stopped) {
//get_coordinates(); // For X Y Z E F
delta[X_AXIS] = 50;
delta[Y_AXIS] = 90;
calculate_SCARA_forward_Transform(delta);
destination[X_AXIS] = delta[X_AXIS]/axis_scaling[X_AXIS];
destination[Y_AXIS] = delta[Y_AXIS]/axis_scaling[Y_AXIS];
prepare_move();
//ClearToSend();
return true;
}
return false;
return SCARA_move_to_cal(50, 90);
}
/**
@ -4057,20 +4106,7 @@ inline void gcode_M303() {
*/
inline bool gcode_M364() {
SERIAL_ECHOLN(" Cal: Theta-Psi 90 ");
// SoftEndsEnabled = false; // Ignore soft endstops during calibration
//SERIAL_ECHOLN(" Soft endstops disabled ");
if (! Stopped) {
//get_coordinates(); // For X Y Z E F
delta[X_AXIS] = 45;
delta[Y_AXIS] = 135;
calculate_SCARA_forward_Transform(delta);
destination[X_AXIS] = delta[X_AXIS] / axis_scaling[X_AXIS];
destination[Y_AXIS] = delta[Y_AXIS] / axis_scaling[Y_AXIS];
prepare_move();
//ClearToSend();
return true;
}
return false;
return SCARA_move_to_cal(45, 135);
}
/**
@ -4661,6 +4697,12 @@ void process_commands() {
gcode_G28();
break;
#if defined(MESH_BED_LEVELING)
case 29: // G29 Handle mesh based leveling
gcode_G29();
break;
#endif
#ifdef ENABLE_AUTO_BED_LEVELING
case 29: // G29 Detailed Z-Probe, probes the bed at 3 or more points.
@ -5172,7 +5214,7 @@ void clamp_to_software_endstops(float target[3])
float negative_z_offset = 0;
#ifdef ENABLE_AUTO_BED_LEVELING
if (Z_PROBE_OFFSET_FROM_EXTRUDER < 0) negative_z_offset = negative_z_offset + Z_PROBE_OFFSET_FROM_EXTRUDER;
if (add_homing[Z_AXIS] < 0) negative_z_offset = negative_z_offset + add_homing[Z_AXIS];
if (home_offset[Z_AXIS] < 0) negative_z_offset = negative_z_offset + home_offset[Z_AXIS];
#endif
if (target[Z_AXIS] < min_pos[Z_AXIS]+negative_z_offset) target[Z_AXIS] = min_pos[Z_AXIS]+negative_z_offset;
@ -5280,6 +5322,81 @@ void prepare_move_raw()
}
#endif //DELTA
#if defined(MESH_BED_LEVELING)
#if !defined(MIN)
#define MIN(_v1, _v2) (((_v1) < (_v2)) ? (_v1) : (_v2))
#endif // ! MIN
// This function is used to split lines on mesh borders so each segment is only part of one mesh area
void mesh_plan_buffer_line(float x, float y, float z, const float e, float feed_rate, const uint8_t &extruder, uint8_t x_splits=0xff, uint8_t y_splits=0xff)
{
if (!mbl.active) {
plan_buffer_line(x, y, z, e, feed_rate, extruder);
for(int8_t i=0; i < NUM_AXIS; i++) {
current_position[i] = destination[i];
}
return;
}
int pix = mbl.select_x_index(current_position[X_AXIS]);
int piy = mbl.select_y_index(current_position[Y_AXIS]);
int ix = mbl.select_x_index(x);
int iy = mbl.select_y_index(y);
pix = MIN(pix, MESH_NUM_X_POINTS-2);
piy = MIN(piy, MESH_NUM_Y_POINTS-2);
ix = MIN(ix, MESH_NUM_X_POINTS-2);
iy = MIN(iy, MESH_NUM_Y_POINTS-2);
if (pix == ix && piy == iy) {
// Start and end on same mesh square
plan_buffer_line(x, y, z, e, feed_rate, extruder);
for(int8_t i=0; i < NUM_AXIS; i++) {
current_position[i] = destination[i];
}
return;
}
float nx, ny, ne, normalized_dist;
if (ix > pix && (x_splits) & BIT(ix)) {
nx = mbl.get_x(ix);
normalized_dist = (nx - current_position[X_AXIS])/(x - current_position[X_AXIS]);
ny = current_position[Y_AXIS] + (y - current_position[Y_AXIS]) * normalized_dist;
ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
x_splits ^= BIT(ix);
} else if (ix < pix && (x_splits) & BIT(pix)) {
nx = mbl.get_x(pix);
normalized_dist = (nx - current_position[X_AXIS])/(x - current_position[X_AXIS]);
ny = current_position[Y_AXIS] + (y - current_position[Y_AXIS]) * normalized_dist;
ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
x_splits ^= BIT(pix);
} else if (iy > piy && (y_splits) & BIT(iy)) {
ny = mbl.get_y(iy);
normalized_dist = (ny - current_position[Y_AXIS])/(y - current_position[Y_AXIS]);
nx = current_position[X_AXIS] + (x - current_position[X_AXIS]) * normalized_dist;
ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
y_splits ^= BIT(iy);
} else if (iy < piy && (y_splits) & BIT(piy)) {
ny = mbl.get_y(piy);
normalized_dist = (ny - current_position[Y_AXIS])/(y - current_position[Y_AXIS]);
nx = current_position[X_AXIS] + (x - current_position[X_AXIS]) * normalized_dist;
ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
y_splits ^= BIT(piy);
} else {
// Already split on a border
plan_buffer_line(x, y, z, e, feed_rate, extruder);
for(int8_t i=0; i < NUM_AXIS; i++) {
current_position[i] = destination[i];
}
return;
}
// Do the split and look for more borders
destination[X_AXIS] = nx;
destination[Y_AXIS] = ny;
destination[E_AXIS] = ne;
mesh_plan_buffer_line(nx, ny, z, ne, feed_rate, extruder, x_splits, y_splits);
destination[X_AXIS] = x;
destination[Y_AXIS] = y;
destination[E_AXIS] = e;
mesh_plan_buffer_line(x, y, z, e, feed_rate, extruder, x_splits, y_splits);
}
#endif // MESH_BED_LEVELING
void prepare_move()
{
clamp_to_software_endstops(destination);
@ -5395,10 +5512,14 @@ for (int s = 1; s <= steps; s++) {
#if ! (defined DELTA || defined SCARA)
// Do not use feedmultiply for E or Z only moves
if( (current_position[X_AXIS] == destination [X_AXIS]) && (current_position[Y_AXIS] == destination [Y_AXIS])) {
plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
}
else {
plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
} else {
#if defined(MESH_BED_LEVELING)
mesh_plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder);
return;
#else
plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder);
#endif // MESH_BED_LEVELING
}
#endif // !(DELTA || SCARA)

@ -171,9 +171,9 @@ static inline uint8_t FAT_SECOND(uint16_t fatTime) {
return 2*(fatTime & 0X1F);
}
/** Default date for file timestamps is 1 Jan 2000 */
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | BIT(5) | 1;
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
/** Default time for file timestamp is 1 am */
uint16_t const FAT_DEFAULT_TIME = BIT(11);
uint16_t const FAT_DEFAULT_TIME = (1 << 11);
//------------------------------------------------------------------------------
/**
* \class SdBaseFile

@ -234,6 +234,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@ -438,12 +440,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// The edges of the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define FRONT_PROBE_BED_POSITION 20

@ -139,7 +139,7 @@ static void lcd_implementation_init()
u8g.drawStr(txt1X, u8g.getHeight() - DOG_CHAR_HEIGHT*3/2, STRING_SPLASH_LINE1);
u8g.drawStr(txt2X, u8g.getHeight() - DOG_CHAR_HEIGHT*1/2, STRING_SPLASH_LINE2);
#endif
} while(u8g.nextPage());
} while (u8g.nextPage());
}
static void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
@ -197,7 +197,7 @@ static void lcd_implementation_status_screen() {
u8g.drawBox(55, 50, (unsigned int)(71.f * card.percentDone() / 100.f), 2);
}
u8g.setPrintPos(80,47);
u8g.setPrintPos(80,48);
if (starttime != 0) {
uint16_t time = (millis() - starttime) / 60000;
u8g.print(itostr2(time/60));
@ -222,7 +222,7 @@ static void lcd_implementation_status_screen() {
int per = ((fanSpeed + 1) * 100) / 256;
if (per) {
u8g.print(itostr3(per));
u8g.print("%");
u8g.print('%');
}
else
#endif
@ -231,26 +231,27 @@ static void lcd_implementation_status_screen() {
}
// X, Y, Z-Coordinates
#define XYZ_BASELINE 38
u8g.setFont(FONT_STATUSMENU);
u8g.drawBox(0,29,128,10);
u8g.drawBox(0,30,128,9);
u8g.setColorIndex(0); // white on black
u8g.setPrintPos(2,37);
u8g.print("X");
u8g.drawPixel(8,33);
u8g.drawPixel(8,35);
u8g.setPrintPos(10,37);
u8g.setPrintPos(2,XYZ_BASELINE);
u8g.print('X');
u8g.drawPixel(8,XYZ_BASELINE - 5);
u8g.drawPixel(8,XYZ_BASELINE - 3);
u8g.setPrintPos(10,XYZ_BASELINE);
u8g.print(ftostr31ns(current_position[X_AXIS]));
u8g.setPrintPos(43,37);
lcd_printPGM(PSTR("Y"));
u8g.drawPixel(49,33);
u8g.drawPixel(49,35);
u8g.setPrintPos(51,37);
u8g.setPrintPos(43,XYZ_BASELINE);
u8g.print('Y');
u8g.drawPixel(49,XYZ_BASELINE - 5);
u8g.drawPixel(49,XYZ_BASELINE - 3);
u8g.setPrintPos(51,XYZ_BASELINE);
u8g.print(ftostr31ns(current_position[Y_AXIS]));
u8g.setPrintPos(83,37);
u8g.print("Z");
u8g.drawPixel(89,33);
u8g.drawPixel(89,35);
u8g.setPrintPos(91,37);
u8g.setPrintPos(83,XYZ_BASELINE);
u8g.print('Z');
u8g.drawPixel(89,XYZ_BASELINE - 5);
u8g.drawPixel(89,XYZ_BASELINE - 3);
u8g.setPrintPos(91,XYZ_BASELINE);
u8g.print(ftostr31(current_position[Z_AXIS]));
u8g.setColorIndex(1); // black on white
@ -259,13 +260,13 @@ static void lcd_implementation_status_screen() {
u8g.setPrintPos(3,49);
u8g.print(LCD_STR_FEEDRATE[0]);
u8g.setFont(FONT_STATUSMENU);
u8g.setPrintPos(12,48);
u8g.setPrintPos(12,49);
u8g.print(itostr3(feedmultiply));
u8g.print('%');
// Status line
u8g.setFont(FONT_STATUSMENU);
u8g.setPrintPos(0,61);
u8g.setPrintPos(0,63);
#ifndef FILAMENT_LCD_DISPLAY
u8g.print(lcd_status_message);
#else
@ -282,10 +283,10 @@ static void lcd_implementation_status_screen() {
#endif
}
static void lcd_implementation_mark_as_selected(uint8_t row, char pr_char) {
if ((pr_char == '>') || (pr_char == LCD_STR_UPLEVEL[0] )) {
static void lcd_implementation_mark_as_selected(uint8_t row, bool isSelected) {
if (isSelected) {
u8g.setColorIndex(1); // black on white
u8g.drawBox (0, row*DOG_CHAR_HEIGHT + 3, 128, DOG_CHAR_HEIGHT);
u8g.drawBox(0, row * DOG_CHAR_HEIGHT + 3, 128, DOG_CHAR_HEIGHT);
u8g.setColorIndex(0); // following text must be white on black
}
else {
@ -294,98 +295,80 @@ static void lcd_implementation_mark_as_selected(uint8_t row, char pr_char) {
u8g.setPrintPos(START_ROW * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT);
}
static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char) {
static void lcd_implementation_drawmenu_generic(bool isSelected, uint8_t row, const char* pstr, char pre_char, char post_char) {
char c;
uint8_t n = LCD_WIDTH - 2;
lcd_implementation_mark_as_selected(row, pre_char);
lcd_implementation_mark_as_selected(row, isSelected);
while((c = pgm_read_byte(pstr))) {
while ((c = pgm_read_byte(pstr))) {
u8g.print(c);
pstr++;
n--;
}
while(n--) u8g.print(' ');
while (n--) u8g.print(' ');
u8g.print(post_char);
u8g.print(' ');
}
static void _drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, const char* data, bool pgm) {
static void _drawmenu_setting_edit_generic(bool isSelected, uint8_t row, const char* pstr, const char* data, bool pgm) {
char c;
uint8_t n = LCD_WIDTH - 2 - (pgm ? lcd_strlen_P(data) : (lcd_strlen((char*)data)));
lcd_implementation_mark_as_selected(row, pre_char);
lcd_implementation_mark_as_selected(row, isSelected);
while( (c = pgm_read_byte(pstr))) {
while ((c = pgm_read_byte(pstr))) {
u8g.print(c);
pstr++;
n--;
}
u8g.print(':');
while(n--) u8g.print(' ');
while (n--) u8g.print(' ');
if (pgm) { lcd_printPGM(data); } else { u8g.print(data); }
}
#define lcd_implementation_drawmenu_setting_edit_generic(row, pstr, pre_char, data) _drawmenu_setting_edit_generic(row, pstr, pre_char, data, false)
#define lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, pre_char, data) _drawmenu_setting_edit_generic(row, pstr, pre_char, data, true)
#define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float43_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float43(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#define lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, false)
#define lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, true)
#define lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
//Add version for callback functions
#define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float43_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float43(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
void lcd_implementation_drawedit(const char* pstr, char* value) {
uint8_t rows = 1;
uint8_t lcd_width = LCD_WIDTH;
uint8_t char_width = DOG_CHAR_WIDTH;
uint8_t lcd_width = LCD_WIDTH, char_width = DOG_CHAR_WIDTH;
uint8_t vallen = lcd_strlen(value);
#ifdef USE_BIG_EDIT_FONT
if (lcd_strlen_P(pstr) <= LCD_WIDTH_EDIT - 1) {
u8g.setFont(FONT_MENU_EDIT);
lcd_width = LCD_WIDTH_EDIT + 1;
char_width = DOG_CHAR_WIDTH_EDIT;
if (lcd_strlen_P(pstr) >= LCD_WIDTH_EDIT - lcd_strlen(value)) rows = 2;
if (lcd_strlen_P(pstr) >= LCD_WIDTH_EDIT - vallen) rows = 2;
}
else {
u8g.setFont(FONT_MENU);
}
#endif
if (lcd_strlen_P(pstr) > LCD_WIDTH - 2 - lcd_strlen(value)) rows = 2;
if (lcd_strlen_P(pstr) > LCD_WIDTH - 2 - vallen) rows = 2;
const float kHalfChar = DOG_CHAR_HEIGHT_EDIT / 2;
float rowHeight = u8g.getHeight() / (rows + 1); // 1/(rows+1) = 1/2 or 1/3
@ -393,43 +376,37 @@ void lcd_implementation_drawedit(const char* pstr, char* value) {
u8g.setPrintPos(0, rowHeight + kHalfChar);
lcd_printPGM(pstr);
u8g.print(':');
u8g.setPrintPos((lcd_width-1-lcd_strlen(value)) * char_width, rows * rowHeight + kHalfChar);
u8g.setPrintPos((lcd_width - 1 - vallen) * char_width, rows * rowHeight + kHalfChar);
u8g.print(value);
}
static void _drawmenu_sd(uint8_t row, const char* pstr, const char* filename, char * const longFilename, bool isDir, bool isSelected) {
static void _drawmenu_sd(bool isSelected, uint8_t row, const char* pstr, const char* filename, char * const longFilename, bool isDir) {
char c;
uint8_t n = LCD_WIDTH - 1;
if (longFilename[0] != '\0') {
if (longFilename[0]) {
filename = longFilename;
longFilename[n] = '\0';
}
lcd_implementation_mark_as_selected(row, ((isSelected) ? '>' : ' '));
lcd_implementation_mark_as_selected(row, isSelected);
if (isDir) u8g.print(LCD_STR_FOLDER[0]);
while((c = *filename) != '\0') {
while ((c = *filename)) {
u8g.print(c);
filename++;
n--;
}
while(n--) u8g.print(' ');
while (n--) u8g.print(' ');
}
#define lcd_implementation_drawmenu_sdfile_selected(row, pstr, filename, longFilename) _drawmenu_sd(row, pstr, filename, longFilename, false, true)
#define lcd_implementation_drawmenu_sdfile(row, pstr, filename, longFilename) _drawmenu_sd(row, pstr, filename, longFilename, false, false)
#define lcd_implementation_drawmenu_sddirectory_selected(row, pstr, filename, longFilename) _drawmenu_sd(row, pstr, filename, longFilename, true, true)
#define lcd_implementation_drawmenu_sddirectory(row, pstr, filename, longFilename) _drawmenu_sd(row, pstr, filename, longFilename, true, false)
#define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
#define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0])
#define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
#define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0])
#define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
#define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
#define lcd_implementation_drawmenu_sdfile(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, false)
#define lcd_implementation_drawmenu_sddirectory(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, true)
#define lcd_implementation_drawmenu_back(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
#define lcd_implementation_drawmenu_submenu(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
#define lcd_implementation_drawmenu_gcode(sel, row, pstr, gcode) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
#define lcd_implementation_drawmenu_function(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
static void lcd_implementation_quick_feedback() {
#if BEEPER > -1

@ -215,6 +215,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
// Felix Foil Heater
#define DEFAULT_bedKp 103.37
@ -384,12 +386,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
// Note: this feature occupies 10'206 byte
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// set the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define BACK_PROBE_BED_POSITION 180

@ -215,6 +215,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
// Felix Foil Heater
#define DEFAULT_bedKp 103.37
@ -384,12 +386,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
// Note: this feature occupies 10'206 byte
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// set the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define BACK_PROBE_BED_POSITION 180

@ -231,6 +231,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@ -408,12 +410,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// The edges of the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define FRONT_PROBE_BED_POSITION 20

@ -230,6 +230,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@ -413,12 +415,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// The edges of the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define FRONT_PROBE_BED_POSITION 20

@ -254,6 +254,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@ -437,12 +439,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// The edges of the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define FRONT_PROBE_BED_POSITION 20

@ -230,6 +230,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@ -407,12 +409,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// The edges of the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define FRONT_PROBE_BED_POSITION 20

@ -258,6 +258,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)

@ -259,6 +259,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)

@ -228,6 +228,8 @@ Here are some standard links for getting your machine calibrated:
// to increase the heat up rate. However, if changed, user must be aware of the safety concerns
// of drawing too much current from the power supply.
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@ -405,12 +407,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// The edges of the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define FRONT_PROBE_BED_POSITION 20

@ -230,6 +230,8 @@ Here are some standard links for getting your machine calibrated:
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
//#define PID_BED_DEBUG // Sends debug data to the serial port.
#ifdef PIDTEMPBED
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@ -407,12 +409,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
#ifdef AUTO_BED_LEVELING_GRID
// Use one of these defines to specify the origin
// for a topographical map to be printed for your bed.
enum { OriginBackLeft, OriginFrontLeft, OriginBackRight, OriginFrontRight };
#define TOPO_ORIGIN OriginFrontLeft
// The edges of the rectangle in which to probe
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define FRONT_PROBE_BED_POSITION 20

@ -95,6 +95,9 @@
#ifndef MSG_MOVE_AXIS
#define MSG_MOVE_AXIS "Move axis"
#endif
#ifndef MSG_LEVEL_BED
#define MSG_LEVEL_BED "Level bed"
#endif
#ifndef MSG_MOVE_X
#define MSG_MOVE_X "Move X"
#endif

@ -0,0 +1,20 @@
#include "mesh_bed_leveling.h"
#if defined(MESH_BED_LEVELING)
mesh_bed_leveling mbl;
mesh_bed_leveling::mesh_bed_leveling() {
reset();
}
void mesh_bed_leveling::reset() {
for (int y=0; y<MESH_NUM_Y_POINTS; y++) {
for (int x=0; x<MESH_NUM_X_POINTS; x++) {
z_values[y][x] = 0;
}
}
active = 0;
}
#endif // MESH_BED_LEVELING

@ -0,0 +1,61 @@
#include "Marlin.h"
#if defined(MESH_BED_LEVELING)
#define MESH_X_DIST ((MESH_MAX_X - MESH_MIN_X)/(MESH_NUM_X_POINTS - 1))
#define MESH_Y_DIST ((MESH_MAX_Y - MESH_MIN_Y)/(MESH_NUM_Y_POINTS - 1))
class mesh_bed_leveling {
public:
uint8_t active;
float z_values[MESH_NUM_Y_POINTS][MESH_NUM_X_POINTS];
mesh_bed_leveling();
void reset();
float get_x(int i) { return MESH_MIN_X + MESH_X_DIST*i; }
float get_y(int i) { return MESH_MIN_Y + MESH_Y_DIST*i; }
void set_z(int ix, int iy, float z) { z_values[iy][ix] = z; }
int select_x_index(float x) {
int i = 1;
while (x > get_x(i) && i < MESH_NUM_X_POINTS-1) {
i++;
}
return i-1;
}
int select_y_index(float y) {
int i = 1;
while (y > get_y(i) && i < MESH_NUM_Y_POINTS-1) {
i++;
}
return i-1;
}
float calc_z0(float a0, float a1, float z1, float a2, float z2) {
float delta_z = (z2 - z1)/(a2 - a1);
float delta_a = a0 - a1;
return z1 + delta_a * delta_z;
}
float get_z(float x0, float y0) {
int x_index = select_x_index(x0);
int y_index = select_y_index(y0);
float z1 = calc_z0(x0,
get_x(x_index), z_values[y_index][x_index],
get_x(x_index+1), z_values[y_index][x_index+1]);
float z2 = calc_z0(x0,
get_x(x_index), z_values[y_index+1][x_index],
get_x(x_index+1), z_values[y_index+1][x_index+1]);
float z0 = calc_z0(y0,
get_y(y_index), z1,
get_y(y_index+1), z2);
return z0;
}
};
extern mesh_bed_leveling mbl;
#endif // MESH_BED_LEVELING

@ -58,6 +58,10 @@
#include "ultralcd.h"
#include "language.h"
#if defined(MESH_BED_LEVELING)
#include "mesh_bed_leveling.h"
#endif // MESH_BED_LEVELING
//===========================================================================
//============================= public variables ============================
//===========================================================================
@ -530,7 +534,7 @@ float junction_deviation = 0.1;
// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in
// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration
// calculation the caller must also provide the physical length of the line in millimeters.
#ifdef ENABLE_AUTO_BED_LEVELING
#if defined(ENABLE_AUTO_BED_LEVELING) || defined(MESH_BED_LEVELING)
void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, const uint8_t &extruder)
#else
void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder)
@ -548,6 +552,12 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa
lcd_update();
}
#if defined(MESH_BED_LEVELING)
if (mbl.active) {
z += mbl.get_z(x, y);
}
#endif // MESH_BED_LEVELING
#ifdef ENABLE_AUTO_BED_LEVELING
apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
#endif // ENABLE_AUTO_BED_LEVELING
@ -1078,14 +1088,19 @@ vector_3 plan_get_position() {
}
#endif // ENABLE_AUTO_BED_LEVELING
#ifdef ENABLE_AUTO_BED_LEVELING
#if defined(ENABLE_AUTO_BED_LEVELING) || defined(MESH_BED_LEVELING)
void plan_set_position(float x, float y, float z, const float &e)
{
apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
#else
void plan_set_position(const float &x, const float &y, const float &z, const float &e)
#endif // ENABLE_AUTO_BED_LEVELING || MESH_BED_LEVELING
{
#endif // ENABLE_AUTO_BED_LEVELING
#if defined(ENABLE_AUTO_BED_LEVELING)
apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
#elif defined(MESH_BED_LEVELING)
if (mbl.active) {
z += mbl.get_z(x, y);
}
#endif // ENABLE_AUTO_BED_LEVELING
position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]);
position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]);

@ -82,23 +82,24 @@ void plan_init();
// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in
// millimaters. Feed rate specifies the speed of the motion.
#ifdef ENABLE_AUTO_BED_LEVELING
#if defined(ENABLE_AUTO_BED_LEVELING) || defined(MESH_BED_LEVELING)
void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, const uint8_t &extruder);
#if defined(ENABLE_AUTO_BED_LEVELING)
#ifndef DELTA
// Get the position applying the bed level matrix if enabled
vector_3 plan_get_position();
#endif
#endif // ENABLE_AUTO_BED_LEVELING
#else
void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder);
#endif // ENABLE_AUTO_BED_LEVELING
#endif // ENABLE_AUTO_BED_LEVELING || MESH_BED_LEVELING
// Set position. Used for G92 instructions.
#ifdef ENABLE_AUTO_BED_LEVELING
#if defined(ENABLE_AUTO_BED_LEVELING) || defined(MESH_BED_LEVELING)
void plan_set_position(float x, float y, float z, const float &e);
#else
void plan_set_position(const float &x, const float &y, const float &z, const float &e);
#endif // ENABLE_AUTO_BED_LEVELING
#endif // ENABLE_AUTO_BED_LEVELING || MESH_BED_LEVELING
void plan_set_e_position(const float &e);

@ -89,7 +89,7 @@ static bool old_x_min_endstop = false,
static bool check_endstops = true;
volatile long count_position[NUM_AXIS] = { 0 };
volatile signed char count_direction[NUM_AXIS] = { 1 };
volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1 };
//===========================================================================
@ -102,11 +102,8 @@ volatile signed char count_direction[NUM_AXIS] = { 1 };
X_DIR_WRITE(v); \
X2_DIR_WRITE(v); \
} \
else{ \
if (current_block->active_extruder) \
X2_DIR_WRITE(v); \
else \
X_DIR_WRITE(v); \
else { \
if (current_block->active_extruder) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \
}
#define X_APPLY_STEP(v,ALWAYS) \
if (extruder_duplication_enabled || ALWAYS) { \
@ -114,10 +111,7 @@ volatile signed char count_direction[NUM_AXIS] = { 1 };
X2_STEP_WRITE(v); \
} \
else { \
if (current_block->active_extruder != 0) \
X2_STEP_WRITE(v); \
else \
X_STEP_WRITE(v); \
if (current_block->active_extruder != 0) X2_STEP_WRITE(v); else X_STEP_WRITE(v); \
}
#else
#define X_APPLY_DIR(v,Q) X_DIR_WRITE(v)
@ -125,16 +119,16 @@ volatile signed char count_direction[NUM_AXIS] = { 1 };
#endif
#ifdef Y_DUAL_STEPPER_DRIVERS
#define Y_APPLY_DIR(v,Q) Y_DIR_WRITE(v), Y2_DIR_WRITE((v) != INVERT_Y2_VS_Y_DIR)
#define Y_APPLY_STEP(v,Q) Y_STEP_WRITE(v), Y2_STEP_WRITE(v)
#define Y_APPLY_DIR(v,Q) { Y_DIR_WRITE(v); Y2_DIR_WRITE((v) != INVERT_Y2_VS_Y_DIR); }
#define Y_APPLY_STEP(v,Q) { Y_STEP_WRITE(v); Y2_STEP_WRITE(v); }
#else
#define Y_APPLY_DIR(v,Q) Y_DIR_WRITE(v)
#define Y_APPLY_STEP(v,Q) Y_STEP_WRITE(v)
#endif
#ifdef Z_DUAL_STEPPER_DRIVERS
#define Z_APPLY_DIR(v,Q) Z_DIR_WRITE(v), Z2_DIR_WRITE(v)
#define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v), Z2_STEP_WRITE(v)
#define Z_APPLY_DIR(v,Q) { Z_DIR_WRITE(v); Z2_DIR_WRITE(v); }
#define Z_APPLY_STEP(v,Q) { Z_STEP_WRITE(v); Z2_STEP_WRITE(v); }
#else
#define Z_APPLY_DIR(v,Q) Z_DIR_WRITE(v)
#define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v)

@ -145,7 +145,7 @@ static volatile bool temp_meas_ready = false;
static float temp_iState_min_bed;
static float temp_iState_max_bed;
#else //PIDTEMPBED
static unsigned long previous_millis_bed_heater;
static unsigned long previous_millis_bed_heater;
#endif //PIDTEMPBED
static unsigned char soft_pwm[EXTRUDERS];
@ -636,6 +636,21 @@ float get_pid_output(int e) {
pid_output = constrain(target_temperature_bed, 0, MAX_BED_POWER);
#endif // PID_OPENLOOP
#ifdef PID_BED_DEBUG
SERIAL_ECHO_START;
SERIAL_ECHO(" PID_BED_DEBUG ");
SERIAL_ECHO(": Input ");
SERIAL_ECHO(current_temperature_bed);
SERIAL_ECHO(" Output ");
SERIAL_ECHO(pid_output);
SERIAL_ECHO(" pTerm ");
SERIAL_ECHO(pTerm_bed);
SERIAL_ECHO(" iTerm ");
SERIAL_ECHO(iTerm_bed);
SERIAL_ECHO(" dTerm ");
SERIAL_ECHOLN(dTerm_bed);
#endif //PID_BED_DEBUG
return pid_output;
}
#endif
@ -740,7 +755,7 @@ void manage_heater() {
#ifdef FILAMENT_SENSOR
if (filament_sensor) {
meas_shift_index = delay_index1 - meas_delay_cm;
if (meas_shift_index < 0) meas_shift_index += MAX_MEASUREMENT_DELAY + 1; //loop around buffer if needed
if (meas_shift_index < 0) meas_shift_index += MAX_MEASUREMENT_DELAY + 1; //loop around buffer if needed
// Get the delayed info and add 100 to reconstitute to a percent of
// the nominal filament diameter then square it to get an area
@ -1244,10 +1259,7 @@ enum TempState {
ISR(TIMER0_COMPB_vect) {
//these variables are only accesible from the ISR, but static, so they don't lose their value
static unsigned char temp_count = 0;
static unsigned long raw_temp_0_value = 0;
static unsigned long raw_temp_1_value = 0;
static unsigned long raw_temp_2_value = 0;
static unsigned long raw_temp_3_value = 0;
static unsigned long raw_temp_value[EXTRUDERS] = { 0 };
static unsigned long raw_temp_bed_value = 0;
static TempState temp_state = StartupDelay;
static unsigned char pwm_count = BIT(SOFT_PWM_SCALE);
@ -1459,7 +1471,7 @@ ISR(TIMER0_COMPB_vect) {
break;
case MeasureTemp_0:
#if HAS_TEMP_0
raw_temp_0_value += ADC;
raw_temp_value[0] += ADC;
#endif
temp_state = PrepareTemp_BED;
break;
@ -1485,7 +1497,7 @@ ISR(TIMER0_COMPB_vect) {
break;
case MeasureTemp_1:
#if HAS_TEMP_1
raw_temp_1_value += ADC;
raw_temp_value[1] += ADC;
#endif
temp_state = PrepareTemp_2;
break;
@ -1498,7 +1510,7 @@ ISR(TIMER0_COMPB_vect) {
break;
case MeasureTemp_2:
#if HAS_TEMP_2
raw_temp_2_value += ADC;
raw_temp_value[2] += ADC;
#endif
temp_state = PrepareTemp_3;
break;
@ -1511,7 +1523,7 @@ ISR(TIMER0_COMPB_vect) {
break;
case MeasureTemp_3:
#if HAS_TEMP_3
raw_temp_3_value += ADC;
raw_temp_value[3] += ADC;
#endif
temp_state = Prepare_FILWIDTH;
break;
@ -1546,19 +1558,19 @@ ISR(TIMER0_COMPB_vect) {
if (temp_count >= OVERSAMPLENR) { // 10 * 16 * 1/(16000000/64/256) = 164ms.
if (!temp_meas_ready) { //Only update the raw values if they have been read. Else we could be updating them during reading.
#ifndef HEATER_0_USES_MAX6675
current_temperature_raw[0] = raw_temp_0_value;
current_temperature_raw[0] = raw_temp_value[0];
#endif
#if EXTRUDERS > 1
current_temperature_raw[1] = raw_temp_1_value;
current_temperature_raw[1] = raw_temp_value[1];
#if EXTRUDERS > 2
current_temperature_raw[2] = raw_temp_2_value;
current_temperature_raw[2] = raw_temp_value[2];
#if EXTRUDERS > 3
current_temperature_raw[3] = raw_temp_3_value;
current_temperature_raw[3] = raw_temp_value[3];
#endif
#endif
#endif
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
redundant_temperature_raw = raw_temp_1_value;
redundant_temperature_raw = raw_temp_value[1];
#endif
current_temperature_bed_raw = raw_temp_bed_value;
} //!temp_meas_ready
@ -1570,31 +1582,67 @@ ISR(TIMER0_COMPB_vect) {
temp_meas_ready = true;
temp_count = 0;
raw_temp_0_value = 0;
raw_temp_1_value = 0;
raw_temp_2_value = 0;
raw_temp_3_value = 0;
for (int i = 0; i < EXTRUDERS; i++) raw_temp_value[i] = 0;
raw_temp_bed_value = 0;
#if HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP
#define MAXTEST <=
#define MINTEST >=
#define GE0 <=
#define LE0 >=
#else
#define MAXTEST >=
#define MINTEST <=
#define GE0 >=
#define LE0 <=
#endif
if (current_temperature_raw[0] GE0 maxttemp_raw[0]) max_temp_error(0);
if (current_temperature_raw[0] LE0 minttemp_raw[0]) min_temp_error(0);
#if EXTRUDERS > 1
#if HEATER_1_RAW_LO_TEMP > HEATER_1_RAW_HI_TEMP
#define GE1 <=
#define LE1 >=
#else
#define GE1 >=
#define LE1 <=
#endif
if (current_temperature_raw[1] GE1 maxttemp_raw[1]) max_temp_error(1);
if (current_temperature_raw[1] LE1 minttemp_raw[1]) min_temp_error(1);
#if EXTRUDERS > 2
#if HEATER_2_RAW_LO_TEMP > HEATER_2_RAW_HI_TEMP
#define GE2 <=
#define LE2 >=
#else
#define GE2 >=
#define LE2 <=
#endif
if (current_temperature_raw[2] GE2 maxttemp_raw[2]) max_temp_error(2);
if (current_temperature_raw[2] LE2 minttemp_raw[2]) min_temp_error(2);
#if EXTRUDERS > 3
#if HEATER_3_RAW_LO_TEMP > HEATER_3_RAW_HI_TEMP
#define GE3 <=
#define LE3 >=
#else
#define GE3 >=
#define LE3 <=
#endif
if (current_temperature_raw[3] GE3 maxttemp_raw[3]) max_temp_error(3);
if (current_temperature_raw[3] LE3 minttemp_raw[3]) min_temp_error(3);
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
#endif // EXTRUDERS > 1
for (int i=0; i<EXTRUDERS; i++) {
if (current_temperature_raw[i] MAXTEST maxttemp_raw[i]) max_temp_error(i);
else if (current_temperature_raw[i] MINTEST minttemp_raw[i]) min_temp_error(i);
}
/* No bed MINTEMP error? */
#if defined(BED_MAXTEMP) && (TEMP_SENSOR_BED != 0)
if (current_temperature_bed_raw MAXTEST bed_maxttemp_raw) {
target_temperature_bed = 0;
bed_max_temp_error();
}
#if HEATER_BED_RAW_LO_TEMP > HEATER_BED_RAW_HI_TEMP
#define GEBED <=
#define LEBED >=
#else
#define GEBED >=
#define LEBED <=
#endif
if (current_temperature_bed_raw GEBED bed_maxttemp_raw) {
target_temperature_bed = 0;
bed_max_temp_error();
}
#endif
} // temp_count >= OVERSAMPLENR
#ifdef BABYSTEPPING

@ -70,6 +70,13 @@ static void lcd_sdcard_menu();
static void lcd_delta_calibrate_menu();
#endif // DELTA_CALIBRATION_MENU
#if defined(MANUAL_BED_LEVELING)
#include "mesh_bed_leveling.h"
static void _lcd_level_bed();
static void _lcd_level_bed_homing();
static void lcd_level_bed();
#endif // MANUAL_BED_LEVELING
static void lcd_quick_feedback();//Cause an LCD refresh, and give the user visual or audible feedback that something has happened
/* Different types of actions that can be used in menu items. */
@ -118,68 +125,88 @@ static void menu_action_setting_edit_callback_long5(const char* pstr, unsigned l
/* Helper macros for menus */
/**
* START_MENU generates the init code for a menu function
*/
#define START_MENU() do { \
encoderRateMultiplierEnabled = false; \
if (encoderPosition > 0x8000) encoderPosition = 0; \
if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM < currentMenuViewOffset) currentMenuViewOffset = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM;\
uint8_t _lineNr = currentMenuViewOffset, _menuItemNr; \
bool wasClicked = LCD_CLICKED;\
for(uint8_t _drawLineNr = 0; _drawLineNr < LCD_HEIGHT; _drawLineNr++, _lineNr++) { \
_menuItemNr = 0;
encoderRateMultiplierEnabled = false; \
if (encoderPosition > 0x8000) encoderPosition = 0; \
uint8_t encoderLine = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM; \
if (encoderLine < currentMenuViewOffset) currentMenuViewOffset = encoderLine; \
uint8_t _lineNr = currentMenuViewOffset, _menuItemNr; \
bool wasClicked = LCD_CLICKED, itemSelected; \
if (wasClicked) lcd_quick_feedback(); \
for (uint8_t _drawLineNr = 0; _drawLineNr < LCD_HEIGHT; _drawLineNr++, _lineNr++) { \
_menuItemNr = 0;
/**
* MENU_ITEM generates draw & handler code for a menu item, potentially calling:
*
* lcd_implementation_drawmenu_[type](sel, row, label, arg3...)
* menu_action_[type](arg3...)
*
* Examples:
* MENU_ITEM(back, MSG_WATCH, lcd_status_screen)
* lcd_implementation_drawmenu_back(sel, row, PSTR(MSG_WATCH), lcd_status_screen)
* menu_action_back(lcd_status_screen)
*
* MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause)
* lcd_implementation_drawmenu_function(sel, row, PSTR(MSG_PAUSE_PRINT), lcd_sdcard_pause)
* menu_action_function(lcd_sdcard_pause)
*
* MENU_ITEM_EDIT(int3, MSG_SPEED, &feedmultiply, 10, 999)
* MENU_ITEM(setting_edit_int3, MSG_SPEED, PSTR(MSG_SPEED), &feedmultiply, 10, 999)
* lcd_implementation_drawmenu_setting_edit_int3(sel, row, PSTR(MSG_SPEED), PSTR(MSG_SPEED), &feedmultiply, 10, 999)
* menu_action_setting_edit_int3(PSTR(MSG_SPEED), &feedmultiply, 10, 999)
*
*/
#define MENU_ITEM(type, label, args...) do { \
if (_menuItemNr == _lineNr) { \
if (lcdDrawUpdate) { \
const char* _label_pstr = PSTR(label); \
if ((encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) { \
lcd_implementation_drawmenu_ ## type ## _selected (_drawLineNr, _label_pstr , ## args ); \
}else{\
lcd_implementation_drawmenu_ ## type (_drawLineNr, _label_pstr , ## args ); \
}\
}\
if (wasClicked && (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) {\
lcd_quick_feedback(); \
menu_action_ ## type ( args ); \
return;\
}\
}\
_menuItemNr++;\
if (_menuItemNr == _lineNr) { \
itemSelected = encoderLine == _menuItemNr; \
if (lcdDrawUpdate) \
lcd_implementation_drawmenu_ ## type(itemSelected, _drawLineNr, PSTR(label), ## args); \
if (wasClicked && itemSelected) { \
menu_action_ ## type(args); \
return; \
} \
} \
_menuItemNr++; \
} while(0)
#ifdef ENCODER_RATE_MULTIPLIER
/**
* MENU_MULTIPLIER_ITEM generates drawing and handling code for a multiplier menu item
*/
#define MENU_MULTIPLIER_ITEM(type, label, args...) do { \
if (_menuItemNr == _lineNr) { \
if (lcdDrawUpdate) { \
const char* _label_pstr = PSTR(label); \
if ((encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) { \
lcd_implementation_drawmenu_ ## type ## _selected (_drawLineNr, _label_pstr , ## args ); \
} \
else { \
lcd_implementation_drawmenu_ ## type (_drawLineNr, _label_pstr , ## args ); \
} \
} \
if (wasClicked && (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) { \
lcd_quick_feedback(); \
itemSelected = encoderLine == _menuItemNr; \
if (lcdDrawUpdate) \
lcd_implementation_drawmenu_ ## type(itemSelected, _drawLineNr, PSTR(label), ## args); \
if (wasClicked && itemSelected) { \
encoderRateMultiplierEnabled = true; \
lastEncoderMovementMillis = 0; \
menu_action_ ## type ( args ); \
menu_action_ ## type(args); \
return; \
} \
} \
_menuItemNr++; \
} while(0)
#endif //ENCODER_RATE_MULTIPLIER
#define MENU_ITEM_DUMMY() do { _menuItemNr++; } while(0)
#define MENU_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label) , ## args )
#define MENU_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, PSTR(label) , ## args )
#define MENU_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label), ## args)
#define MENU_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, PSTR(label), ## args)
#ifdef ENCODER_RATE_MULTIPLIER
#define MENU_MULTIPLIER_ITEM_EDIT(type, label, args...) MENU_MULTIPLIER_ITEM(setting_edit_ ## type, label, PSTR(label) , ## args )
#define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(type, label, args...) MENU_MULTIPLIER_ITEM(setting_edit_callback_ ## type, label, PSTR(label) , ## args )
#define MENU_MULTIPLIER_ITEM_EDIT(type, label, args...) MENU_MULTIPLIER_ITEM(setting_edit_ ## type, label, PSTR(label), ## args)
#define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(type, label, args...) MENU_MULTIPLIER_ITEM(setting_edit_callback_ ## type, label, PSTR(label), ## args)
#else //!ENCODER_RATE_MULTIPLIER
#define MENU_MULTIPLIER_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label) , ## args )
#define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, PSTR(label) , ## args )
#define MENU_MULTIPLIER_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label), ## args)
#define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, PSTR(label), ## args)
#endif //!ENCODER_RATE_MULTIPLIER
#define END_MENU() \
if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM >= _menuItemNr) encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1; \
if ((uint8_t)(encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) >= currentMenuViewOffset + LCD_HEIGHT) { currentMenuViewOffset = (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) - LCD_HEIGHT + 1; lcdDrawUpdate = 1; _lineNr = currentMenuViewOffset - 1; _drawLineNr = -1; } \
if (encoderLine >= _menuItemNr) encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1; encoderLine = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM;\
if (encoderLine >= currentMenuViewOffset + LCD_HEIGHT) { currentMenuViewOffset = encoderLine - LCD_HEIGHT + 1; lcdDrawUpdate = 1; _lineNr = currentMenuViewOffset - 1; _drawLineNr = -1; } \
} } while(0)
/** Used variables to keep track of the menu */
@ -410,7 +437,7 @@ static void lcd_main_menu() {
void lcd_set_home_offsets() {
for(int8_t i=0; i < NUM_AXIS; i++) {
if (i != E_AXIS) {
add_homing[i] -= current_position[i];
home_offset[i] -= current_position[i];
current_position[i] = 0.0;
}
}
@ -458,9 +485,9 @@ static void lcd_tune_menu() {
#if TEMP_SENSOR_BED != 0
MENU_MULTIPLIER_ITEM_EDIT(int3, MSG_BED, &target_temperature_bed, 0, BED_MAXTEMP - 15);
#endif
MENU_MULTIPLIER_ITEM_EDIT(int3, MSG_FAN_SPEED, &fanSpeed, 0, 255);
MENU_ITEM_EDIT(int3, MSG_FLOW, &extrudemultiply, 10, 999);
MENU_ITEM_EDIT(int3, MSG_FLOW MSG_F0, &extruder_multiply[0], 10, 999);
MENU_MULTIPLIER_ITEM_EDIT(int3, MSG_FAN_SPEED, &fanSpeed, 0, 255);
MENU_ITEM_EDIT(int3, MSG_FLOW, &extrudemultiply, 10, 999);
MENU_ITEM_EDIT(int3, MSG_FLOW MSG_F0, &extruder_multiply[0], 10, 999);
#if TEMP_SENSOR_1 != 0
MENU_ITEM_EDIT(int3, MSG_FLOW MSG_F1, &extruder_multiply[1], 10, 999);
#endif
@ -611,6 +638,10 @@ static void lcd_prepare_menu() {
#endif
MENU_ITEM(submenu, MSG_MOVE_AXIS, lcd_move_menu);
#if defined(MANUAL_BED_LEVELING)
MENU_ITEM(submenu, MSG_LEVEL_BED, lcd_level_bed);
#endif
END_MENU();
}
@ -1321,7 +1352,12 @@ void lcd_update() {
#endif
#ifdef ULTIPANEL
if (currentMenu != lcd_status_screen && millis() > timeoutToStatus) {
if (currentMenu != lcd_status_screen &&
#if defined(MANUAL_BED_LEVELING)
currentMenu != _lcd_level_bed &&
currentMenu != _lcd_level_bed_homing &&
#endif // MANUAL_BED_LEVELING
millis() > timeoutToStatus) {
lcd_return_to_status();
lcdDrawUpdate = 2;
}
@ -1740,4 +1776,75 @@ char *ftostr52(const float &x)
return conv;
}
#if defined(MANUAL_BED_LEVELING)
static int _lcd_level_bed_position;
static void _lcd_level_bed()
{
if (encoderPosition != 0) {
refresh_cmd_timeout();
current_position[Z_AXIS] += float((int)encoderPosition) * 0.05;
if (min_software_endstops && current_position[Z_AXIS] < Z_MIN_POS) current_position[Z_AXIS] = Z_MIN_POS;
if (max_software_endstops && current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
encoderPosition = 0;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[Z_AXIS]/60, active_extruder);
lcdDrawUpdate = 1;
}
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR("Z"), ftostr32(current_position[Z_AXIS]));
static bool debounce_click = false;
if (LCD_CLICKED) {
if (!debounce_click) {
debounce_click = true;
int ix = _lcd_level_bed_position % MESH_NUM_X_POINTS;
int iy = _lcd_level_bed_position / MESH_NUM_X_POINTS;
mbl.set_z(ix, iy, current_position[Z_AXIS]);
_lcd_level_bed_position++;
if (_lcd_level_bed_position == MESH_NUM_X_POINTS*MESH_NUM_Y_POINTS) {
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[X_AXIS]/60, active_extruder);
mbl.active = 1;
enquecommands_P(PSTR("G28"));
lcd_return_to_status();
} else {
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[X_AXIS]/60, active_extruder);
ix = _lcd_level_bed_position % MESH_NUM_X_POINTS;
iy = _lcd_level_bed_position / MESH_NUM_X_POINTS;
if (iy&1) { // Zig zag
ix = (MESH_NUM_X_POINTS - 1) - ix;
}
current_position[X_AXIS] = mbl.get_x(ix);
current_position[Y_AXIS] = mbl.get_y(iy);
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[X_AXIS]/60, active_extruder);
lcdDrawUpdate = 1;
}
}
} else {
debounce_click = false;
}
}
static void _lcd_level_bed_homing()
{
if (axis_known_position[X_AXIS] &&
axis_known_position[Y_AXIS] &&
axis_known_position[Z_AXIS]) {
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
current_position[X_AXIS] = MESH_MIN_X;
current_position[Y_AXIS] = MESH_MIN_Y;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[X_AXIS]/60, active_extruder);
_lcd_level_bed_position = 0;
lcd_goto_menu(_lcd_level_bed);
}
}
static void lcd_level_bed()
{
axis_known_position[X_AXIS] = false;
axis_known_position[Y_AXIS] = false;
axis_known_position[Z_AXIS] = false;
mbl.reset();
enquecommands_P(PSTR("G28"));
lcd_goto_menu(_lcd_level_bed_homing);
}
#endif // MANUAL_BED_LEVELING
#endif //ULTRA_LCD

@ -610,214 +610,104 @@ static void lcd_implementation_status_screen()
lcd.print(lcd_status_message);
}
static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char)
{
char c;
//Use all characters in narrow LCDs
#if LCD_WIDTH < 20
uint8_t n = LCD_WIDTH - 1 - 1;
#else
uint8_t n = LCD_WIDTH - 1 - 2;
#endif
lcd.setCursor(0, row);
lcd.print(pre_char);
while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
{
lcd.print(c);
pstr++;
if ((pgm_read_byte(pstr) & 0xc0) != 0x80) n--;
}
while(n--)
lcd.print(' ');
lcd.print(post_char);
lcd.print(' ');
static void lcd_implementation_drawmenu_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char post_char) {
char c;
uint8_t n = LCD_WIDTH - 1 - (LCD_WIDTH < 20 ? 1 : 2);
lcd.setCursor(0, row);
lcd.print(sel ? pre_char : ' ');
while ((c = pgm_read_byte(pstr)) && n > 0) {
lcd.print(c);
pstr++;
if ((pgm_read_byte(pstr) & 0xc0) != 0x80) n--;
}
while(n--) lcd.print(' ');
lcd.print(post_char);
lcd.print(' ');
}
static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, char* data)
{
char c;
//Use all characters in narrow LCDs
#if LCD_WIDTH < 20
uint8_t n = LCD_WIDTH - 1 - 1 - lcd_strlen(data);
#else
uint8_t n = LCD_WIDTH - 1 - 2 - lcd_strlen(data);
#endif
lcd.setCursor(0, row);
lcd.print(pre_char);
while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
{
lcd.print(c);
pstr++;
if ((pgm_read_byte(pstr) & 0xc0) != 0x80) n--;
}
lcd.print(':');
while(n--)
lcd.print(' ');
lcd.print(data);
static void lcd_implementation_drawmenu_setting_edit_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char* data) {
char c;
uint8_t n = LCD_WIDTH - 1 - (LCD_WIDTH < 20 ? 1 : 2) - lcd_strlen(data);
lcd.setCursor(0, row);
lcd.print(sel ? pre_char : ' ');
while ((c = pgm_read_byte(pstr)) && n > 0) {
lcd.print(c);
pstr++;
if ((pgm_read_byte(pstr) & 0xc0) != 0x80) n--;
}
lcd.print(':');
while (n--) lcd.print(' ');
lcd.print(data);
}
static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, const char* pstr, char pre_char, const char* data)
{
char c;
//Use all characters in narrow LCDs
#if LCD_WIDTH < 20
uint8_t n = LCD_WIDTH - 1 - 1 - lcd_strlen_P(data);
#else
uint8_t n = LCD_WIDTH - 1 - 2 - lcd_strlen_P(data);
#endif
lcd.setCursor(0, row);
lcd.print(pre_char);
while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
{
lcd.print(c);
pstr++;
if ((pgm_read_byte(pstr) & 0xc0) != 0x80) n--;
}
lcd.print(':');
while(n--)
lcd.print(' ');
lcd_printPGM(data);
static void lcd_implementation_drawmenu_setting_edit_generic_P(bool sel, uint8_t row, const char* pstr, char pre_char, const char* data) {
char c;
uint8_t n = LCD_WIDTH - 1 - (LCD_WIDTH < 20 ? 1 : 2) - lcd_strlen_P(data);
lcd.setCursor(0, row);
lcd.print(sel ? pre_char : ' ');
while ((c = pgm_read_byte(pstr)) && n > 0) {
lcd.print(c);
pstr++;
if ((pgm_read_byte(pstr) & 0xc0) != 0x80) n--;
}
lcd.print(':');
while (n--) lcd.print(' ');
lcd_printPGM(data);
}
#define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float43_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float43(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#define lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
//Add version for callback functions
#define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float43_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float43(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
void lcd_implementation_drawedit(const char* pstr, char* value)
{
lcd.setCursor(1, 1);
lcd_printPGM(pstr);
lcd.print(':');
#if LCD_WIDTH < 20
lcd.setCursor(LCD_WIDTH - lcd_strlen(value), 1);
#else
lcd.setCursor(LCD_WIDTH -1 - lcd_strlen(value), 1);
#endif
lcd.print(value);
}
static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
{
char c;
uint8_t n = LCD_WIDTH - 1;
lcd.setCursor(0, row);
lcd.print('>');
if (longFilename[0] != '\0')
{
filename = longFilename;
longFilename[LCD_WIDTH-1] = '\0';
}
while( ((c = *filename) != '\0') && (n>0) )
{
lcd.print(c);
filename++;
n--;
}
while(n--)
lcd.print(' ');
#define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5(*(data)))
#define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
void lcd_implementation_drawedit(const char* pstr, char* value) {
lcd.setCursor(1, 1);
lcd_printPGM(pstr);
lcd.print(':');
lcd.setCursor(LCD_WIDTH - (LCD_WIDTH < 20 ? 0 : 1) - lcd_strlen(value), 1);
lcd.print(value);
}
static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename)
{
char c;
uint8_t n = LCD_WIDTH - 1;
lcd.setCursor(0, row);
lcd.print(' ');
if (longFilename[0] != '\0')
{
filename = longFilename;
longFilename[LCD_WIDTH-1] = '\0';
}
while( ((c = *filename) != '\0') && (n>0) )
{
lcd.print(c);
filename++;
n--;
}
while(n--)
lcd.print(' ');
static void lcd_implementation_drawmenu_sd(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename, uint8_t concat) {
char c;
uint8_t n = LCD_WIDTH - concat;
lcd.setCursor(0, row);
lcd.print(sel ? '>' : ' ');
if (longFilename[0]) {
filename = longFilename;
longFilename[n] = '\0';
}
while ((c = *filename) && n > 0) {
lcd.print(c);
filename++;
n--;
}
while (n--) lcd.print(' ');
}
static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
{
char c;
uint8_t n = LCD_WIDTH - 2;
lcd.setCursor(0, row);
lcd.print('>');
lcd.print(LCD_STR_FOLDER[0]);
if (longFilename[0] != '\0')
{
filename = longFilename;
longFilename[LCD_WIDTH-2] = '\0';
}
while( ((c = *filename) != '\0') && (n>0) )
{
lcd.print(c);
filename++;
n--;
}
while(n--)
lcd.print(' ');
static void lcd_implementation_drawmenu_sdfile(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) {
lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 1);
}
static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename)
{
char c;
uint8_t n = LCD_WIDTH - 2;
lcd.setCursor(0, row);
lcd.print(' ');
lcd.print(LCD_STR_FOLDER[0]);
if (longFilename[0] != '\0')
{
filename = longFilename;
longFilename[LCD_WIDTH-2] = '\0';
}
while( ((c = *filename) != '\0') && (n>0) )
{
lcd.print(c);
filename++;
n--;
}
while(n--)
lcd.print(' ');
static void lcd_implementation_drawmenu_sddirectory(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) {
lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 2);
}
#define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
#define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0])
#define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
#define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0])
#define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
#define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
#define lcd_implementation_drawmenu_back(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
#define lcd_implementation_drawmenu_submenu(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
#define lcd_implementation_drawmenu_gcode(sel, row, pstr, gcode) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
#define lcd_implementation_drawmenu_function(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
static void lcd_implementation_quick_feedback()
{

Loading…
Cancel
Save