Refactor Hilbert curve. Enhance Touch UI Bed Level Screen. (#21453)
This commit is contained in:
parent
5d0e6c21aa
commit
c45b91aa94
112
Marlin/src/feature/bedlevel/hilbert_curve.cpp
Normal file
112
Marlin/src/feature/bedlevel/hilbert_curve.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*********************
|
||||
* hilbert_curve.cpp *
|
||||
*********************/
|
||||
|
||||
/****************************************************************************
|
||||
* Written By Marcio Teixeira 2021 - SynDaver Labs, Inc. *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* To view a copy of the GNU General Public License, go to the following *
|
||||
* location: <https://www.gnu.org/licenses/>. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(UBL_HILBERT_CURVE)
|
||||
|
||||
#include "bedlevel.h"
|
||||
#include "hilbert_curve.h"
|
||||
|
||||
constexpr int8_t to_fix(int8_t v) { return v * 2; }
|
||||
constexpr int8_t to_int(int8_t v) { return v / 2; }
|
||||
constexpr uint8_t log2(uint8_t n) { return (n > 1) ? 1 + log2(n >> 1) : 0; }
|
||||
constexpr uint8_t order(uint8_t n) { return uint8_t(log2(n - 1)) + 1; }
|
||||
constexpr uint8_t ord = order(_MAX(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y));
|
||||
constexpr uint8_t dim = _BV(ord);
|
||||
|
||||
static inline bool eval_candidate(int8_t x, int8_t y, hilbert_curve::callback_ptr func, void *data) {
|
||||
// The print bed likely has fewer points than the full Hilbert
|
||||
// curve, so cull unecessary points
|
||||
return x < GRID_MAX_POINTS_X && y < GRID_MAX_POINTS_Y ? func(x, y, data) : false;
|
||||
}
|
||||
|
||||
bool hilbert_curve::hilbert(int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n, hilbert_curve::callback_ptr func, void *data) {
|
||||
/**
|
||||
* Hilbert space-filling curve implementation
|
||||
*
|
||||
* x and y : coordinates of the bottom left corner
|
||||
* xi and xj : i and j components of the unit x vector of the frame
|
||||
* yi and yj : i and j components of the unit y vector of the frame
|
||||
*
|
||||
* From: http://www.fundza.com/algorithmic/space_filling/hilbert/basics/index.html
|
||||
*/
|
||||
if (n)
|
||||
return hilbert(x, y, yi/2, yj/2, xi/2, xj/2, n-1, func, data) ||
|
||||
hilbert(x+xi/2, y+xj/2, xi/2, xj/2, yi/2, yj/2, n-1, func, data) ||
|
||||
hilbert(x+xi/2+yi/2, y+xj/2+yj/2, xi/2, xj/2, yi/2, yj/2, n-1, func, data) ||
|
||||
hilbert(x+xi/2+yi, y+xj/2+yj, -yi/2, -yj/2, -xi/2, -xj/2, n-1, func, data);
|
||||
else
|
||||
return eval_candidate(to_int(x+(xi+yi)/2), to_int(y+(xj+yj)/2), func, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls func(x, y, data) for all points in the Hilbert curve.
|
||||
* If that function returns true, the search is terminated.
|
||||
*/
|
||||
bool hilbert_curve::search(hilbert_curve::callback_ptr func, void *data) {
|
||||
return hilbert(to_fix(0), to_fix(0),to_fix(dim), to_fix(0), to_fix(0), to_fix(dim), ord, func, data);
|
||||
}
|
||||
|
||||
/* Helper function for starting the search at a particular point */
|
||||
|
||||
typedef struct {
|
||||
uint8_t x, y;
|
||||
bool found_1st;
|
||||
hilbert_curve::callback_ptr func;
|
||||
void *data;
|
||||
} search_from_t;
|
||||
|
||||
static bool search_from_helper(uint8_t x, uint8_t y, void *data) {
|
||||
search_from_t *d = (search_from_t *) data;
|
||||
if (d->x == x && d->y == y)
|
||||
d->found_1st = true;
|
||||
return d->found_1st ? d->func(x, y, d->data) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as search, except start at a specific grid intersection point.
|
||||
*/
|
||||
bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_ptr func, void *data) {
|
||||
search_from_t d;
|
||||
d.x = x;
|
||||
d.y = y;
|
||||
d.found_1st = false;
|
||||
d.func = func;
|
||||
d.data = data;
|
||||
// Call twice to allow search to wrap back to the beginning and picked up points prior to the start.
|
||||
return search(search_from_helper, &d) || search(search_from_helper, &d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like search_from, but takes a bed position and starts from the nearest
|
||||
* point on the Hilbert curve.
|
||||
*/
|
||||
bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) {
|
||||
// Find closest grid intersection
|
||||
uint8_t grid_x = LROUND(float(pos.x - MESH_MIN_X) / MESH_X_DIST);
|
||||
uint8_t grid_y = LROUND(float(pos.y - MESH_MIN_Y) / MESH_Y_DIST);
|
||||
LIMIT(grid_x, 0, GRID_MAX_POINTS_X);
|
||||
LIMIT(grid_y, 0, GRID_MAX_POINTS_Y);
|
||||
return search_from(grid_x, grid_y, func, data);
|
||||
}
|
||||
|
||||
#endif // UBL_HILBERT_CURVE
|
32
Marlin/src/feature/bedlevel/hilbert_curve.h
Normal file
32
Marlin/src/feature/bedlevel/hilbert_curve.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*******************
|
||||
* hilbert_curve.h *
|
||||
*******************/
|
||||
|
||||
/****************************************************************************
|
||||
* Written By Marcio Teixeira 2021 - SynDaver Labs, Inc. *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* To view a copy of the GNU General Public License, go to the following *
|
||||
* location: <https://www.gnu.org/licenses/>. *
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
class hilbert_curve {
|
||||
public:
|
||||
typedef bool (*callback_ptr)(uint8_t x, uint8_t y, void *data);
|
||||
static bool search(callback_ptr func, void *data);
|
||||
static bool search_from(uint8_t x, uint8_t y, callback_ptr func, void *data);
|
||||
static bool search_from_closest(const xy_pos_t &pos, callback_ptr func, void *data);
|
||||
private:
|
||||
static bool hilbert(int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n, callback_ptr func, void *data);
|
||||
};
|
@ -101,11 +101,6 @@ public:
|
||||
static void display_map(const int) _O0;
|
||||
static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const xy_pos_t&, const bool=false, MeshFlags *done_flags=nullptr) _O0;
|
||||
static mesh_index_pair find_furthest_invalid_mesh_point() _O0;
|
||||
#if ENABLED(UBL_HILBERT_CURVE)
|
||||
static void check_if_missing(mesh_index_pair &pt, int x, int y);
|
||||
static void hilbert(mesh_index_pair &pt, int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n);
|
||||
static mesh_index_pair find_next_mesh_point();
|
||||
#endif
|
||||
static void reset();
|
||||
static void invalidate();
|
||||
static void set_all_mesh_points_to_value(const float value);
|
||||
|
@ -49,6 +49,10 @@
|
||||
#include "../../../lcd/extui/ui_api.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(UBL_HILBERT_CURVE)
|
||||
#include "../hilbert_curve.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define UBL_G29_P31
|
||||
@ -747,11 +751,9 @@ void unified_bed_leveling::shift_mesh_height() {
|
||||
}
|
||||
#endif
|
||||
|
||||
best = do_furthest ? find_furthest_invalid_mesh_point()
|
||||
: TERN(UBL_HILBERT_CURVE,
|
||||
find_next_mesh_point(),
|
||||
find_closest_mesh_point_of_type(INVALID, nearby, true)
|
||||
);
|
||||
best = do_furthest
|
||||
? find_furthest_invalid_mesh_point()
|
||||
: find_closest_mesh_point_of_type(INVALID, nearby, true);
|
||||
|
||||
if (best.pos.x >= 0) { // mesh point found and is reachable by probe
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::PROBE_START));
|
||||
@ -1269,97 +1271,93 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
|
||||
return farthest;
|
||||
}
|
||||
|
||||
mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const MeshPointType type, const xy_pos_t &pos, const bool probe_relative/*=false*/, MeshFlags *done_flags/*=nullptr*/) {
|
||||
mesh_index_pair closest;
|
||||
closest.invalidate();
|
||||
closest.distance = -99999.9f;
|
||||
#if ENABLED(UBL_HILBERT_CURVE)
|
||||
|
||||
// Get the reference position, either nozzle or probe
|
||||
const xy_pos_t ref = probe_relative ? pos + probe.offset_xy : pos;
|
||||
typedef struct {
|
||||
MeshPointType type;
|
||||
MeshFlags *done_flags;
|
||||
bool probe_relative;
|
||||
mesh_index_pair closest;
|
||||
} find_closest_t;
|
||||
|
||||
float best_so_far = 99999.99f;
|
||||
|
||||
GRID_LOOP(i, j) {
|
||||
if ( (type == (isnan(z_values[i][j]) ? INVALID : REAL))
|
||||
|| (type == SET_IN_BITMAP && !done_flags->marked(i, j))
|
||||
static bool test_func(uint8_t i, uint8_t j, void *data) {
|
||||
find_closest_t *d = (find_closest_t*)data;
|
||||
if ( (d->type == (isnan(ubl.z_values[i][j]) ? INVALID : REAL))
|
||||
|| (d->type == SET_IN_BITMAP && !d->done_flags->marked(i, j))
|
||||
) {
|
||||
// Found a Mesh Point of the specified type!
|
||||
const xy_pos_t mpos = { mesh_index_to_xpos(i), mesh_index_to_ypos(j) };
|
||||
const xy_pos_t mpos = { ubl.mesh_index_to_xpos(i), ubl.mesh_index_to_ypos(j) };
|
||||
|
||||
// If using the probe as the reference there are some unreachable locations.
|
||||
// Also for round beds, there are grid points outside the bed the nozzle can't reach.
|
||||
// Prune them from the list and ignore them till the next Phase (manual nozzle probing).
|
||||
|
||||
if (!(probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
|
||||
continue;
|
||||
|
||||
// Reachable. Check if it's the best_so_far location to the nozzle.
|
||||
|
||||
const xy_pos_t diff = current_position - mpos;
|
||||
const float distance = (ref - mpos).magnitude() + diff.magnitude() * 0.1f;
|
||||
|
||||
// factor in the distance from the current location for the normal case
|
||||
// so the nozzle isn't running all over the bed.
|
||||
if (distance < best_so_far) {
|
||||
best_so_far = distance; // Found a closer location with the desired value type.
|
||||
closest.pos.set(i, j);
|
||||
closest.distance = best_so_far;
|
||||
}
|
||||
}
|
||||
} // GRID_LOOP
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
#if ENABLED(UBL_HILBERT_CURVE)
|
||||
|
||||
constexpr int8_t to_fix(int8_t v) { return v << 1; }
|
||||
constexpr int8_t to_int(int8_t v) { return v >> 1; }
|
||||
constexpr uint8_t log2(uint8_t n) { return (n > 1) ? 1 + log2(n >> 1) : 0; }
|
||||
constexpr uint8_t order(uint8_t n) { return uint8_t(log2(n - 1)) + 1; }
|
||||
|
||||
void unified_bed_leveling::hilbert(mesh_index_pair &pt, int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n) {
|
||||
/* Hilbert space filling curve implementation
|
||||
*
|
||||
* x and y are the coordinates of the bottom left corner
|
||||
* xi & xj are the i & j components of the unit x vector of the frame
|
||||
* similarly yi and yj
|
||||
*
|
||||
* From: http://www.fundza.com/algorithmic/space_filling/hilbert/basics/index.html
|
||||
*/
|
||||
if (n <= 0)
|
||||
check_if_missing(pt, to_int(x+(xi+yi)/2),to_int(y+(xj+yj)/2));
|
||||
else {
|
||||
hilbert(pt, x, y, yi/2, yj/2, xi/2, xj/2, n-1);
|
||||
hilbert(pt, x+xi/2, y+xj/2, xi/2, xj/2, yi/2, yj/2, n-1);
|
||||
hilbert(pt, x+xi/2+yi/2, y+xj/2+yj/2, xi/2, xj/2, yi/2, yj/2, n-1);
|
||||
hilbert(pt, x+xi/2+yi, y+xj/2+yj, -yi/2, -yj/2, -xi/2, -xj/2, n-1);
|
||||
if (!(d->probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
|
||||
return false;
|
||||
d->closest.pos.set(i, j);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void unified_bed_leveling::check_if_missing(mesh_index_pair &pt, int x, int y) {
|
||||
if ( pt.distance < 0
|
||||
&& x < GRID_MAX_POINTS_X
|
||||
&& y < GRID_MAX_POINTS_Y
|
||||
&& isnan(z_values[x][y])
|
||||
&& probe.can_reach(mesh_index_to_xpos(x), mesh_index_to_ypos(y))
|
||||
#endif
|
||||
|
||||
mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const MeshPointType type, const xy_pos_t &pos, const bool probe_relative/*=false*/, MeshFlags *done_flags/*=nullptr*/) {
|
||||
|
||||
#if ENABLED(UBL_HILBERT_CURVE)
|
||||
|
||||
find_closest_t d;
|
||||
d.type = type;
|
||||
d.done_flags = done_flags;
|
||||
d.probe_relative = probe_relative;
|
||||
d.closest.invalidate();
|
||||
hilbert_curve::search_from_closest(pos, test_func, &d);
|
||||
return d.closest;
|
||||
|
||||
#else
|
||||
|
||||
mesh_index_pair closest;
|
||||
closest.invalidate();
|
||||
closest.distance = -99999.9f;
|
||||
|
||||
// Get the reference position, either nozzle or probe
|
||||
const xy_pos_t ref = probe_relative ? pos + probe.offset_xy : pos;
|
||||
|
||||
float best_so_far = 99999.99f;
|
||||
|
||||
GRID_LOOP(i, j) {
|
||||
if ( (type == (isnan(z_values[i][j]) ? INVALID : REAL))
|
||||
|| (type == SET_IN_BITMAP && !done_flags->marked(i, j))
|
||||
) {
|
||||
pt.pos.set(x, y);
|
||||
pt.distance = 1;
|
||||
// Found a Mesh Point of the specified type!
|
||||
const xy_pos_t mpos = { mesh_index_to_xpos(i), mesh_index_to_ypos(j) };
|
||||
|
||||
// If using the probe as the reference there are some unreachable locations.
|
||||
// Also for round beds, there are grid points outside the bed the nozzle can't reach.
|
||||
// Prune them from the list and ignore them till the next Phase (manual nozzle probing).
|
||||
|
||||
if (!(probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
|
||||
continue;
|
||||
|
||||
// Reachable. Check if it's the best_so_far location to the nozzle.
|
||||
|
||||
const xy_pos_t diff = current_position - mpos;
|
||||
const float distance = (ref - mpos).magnitude() + diff.magnitude() * 0.1f;
|
||||
|
||||
// factor in the distance from the current location for the normal case
|
||||
// so the nozzle isn't running all over the bed.
|
||||
if (distance < best_so_far) {
|
||||
best_so_far = distance; // Found a closer location with the desired value type.
|
||||
closest.pos.set(i, j);
|
||||
closest.distance = best_so_far;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // GRID_LOOP
|
||||
|
||||
mesh_index_pair unified_bed_leveling::find_next_mesh_point() {
|
||||
mesh_index_pair pt;
|
||||
pt.invalidate();
|
||||
pt.distance = -99999.9f;
|
||||
constexpr uint8_t ord = order(_MAX(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y));
|
||||
constexpr uint8_t dim = _BV(ord);
|
||||
hilbert(pt, to_fix(0), to_fix(0), to_fix(dim), to_fix(0), to_fix(0), to_fix(dim), ord);
|
||||
return pt;
|
||||
}
|
||||
return closest;
|
||||
|
||||
#endif // UBL_HILBERT_CURVE
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Smart Fill': Scan from the outward edges of the mesh towards the center.
|
||||
|
@ -30,25 +30,28 @@
|
||||
#define INC_POS SUB_POS(6,1), SUB_SIZE(2,1)
|
||||
#define DEC_POS SUB_POS(8,1), SUB_SIZE(2,1)
|
||||
|
||||
void draw_adjuster(CommandProcessor& cmd, int16_t x, int16_t y, int16_t w, int16_t h, uint8_t tag, float value, progmem_str units, int8_t width, uint8_t precision, draw_mode_t what) {
|
||||
if (what & BACKGROUND)
|
||||
cmd.tag(0).button(VAL_POS, F(""), FTDI::OPT_FLAT);
|
||||
void draw_adjuster_value(CommandProcessor& cmd, int16_t x, int16_t y, int16_t w, int16_t h, float value, progmem_str units, int8_t width, uint8_t precision) {
|
||||
char str[width + precision + 10 + (units ? strlen_P((const char*) units) : 0)];
|
||||
if (isnan(value))
|
||||
strcpy_P(str, PSTR("-"));
|
||||
else
|
||||
dtostrf(value, width, precision, str);
|
||||
|
||||
if (what & FOREGROUND) {
|
||||
char str[width + precision + 10 + (units ? strlen_P((const char*) units) : 0)];
|
||||
if (isnan(value))
|
||||
strcpy_P(str, PSTR("-"));
|
||||
else
|
||||
dtostrf(value, width, precision, str);
|
||||
if (units) {
|
||||
strcat_P(str, PSTR(" "));
|
||||
strcat_P(str, (const char*) units);
|
||||
}
|
||||
|
||||
if (units) {
|
||||
strcat_P(str, PSTR(" "));
|
||||
strcat_P(str, (const char*) units);
|
||||
}
|
||||
|
||||
cmd.tag(0)
|
||||
.text(VAL_POS, str)
|
||||
.tag(tag ).button(INC_POS, F("-"))
|
||||
.tag(tag+1).button(DEC_POS, F("+"));
|
||||
}
|
||||
cmd.text(VAL_POS, str);
|
||||
}
|
||||
|
||||
void draw_adjuster(CommandProcessor& cmd, int16_t x, int16_t y, int16_t w, int16_t h, uint8_t tag, float value, progmem_str units, int8_t width, uint8_t precision, draw_mode_t what) {
|
||||
if (what & BACKGROUND)
|
||||
cmd.tag(0).button(VAL_POS, F(""), FTDI::OPT_FLAT);
|
||||
|
||||
if (what & FOREGROUND) {
|
||||
draw_adjuster_value(cmd, x, y, w, h, value, units, width, precision);
|
||||
cmd.tag(tag ).button(INC_POS, F("-"))
|
||||
.tag(tag+1).button(DEC_POS, F("+"));
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,13 @@
|
||||
#pragma once
|
||||
#include "../extended/screen_types.h"
|
||||
|
||||
void draw_adjuster_value(
|
||||
CommandProcessor& cmd,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
float value, progmem_str units = nullptr,
|
||||
int8_t width = 5, uint8_t precision = 1
|
||||
);
|
||||
|
||||
void draw_adjuster(
|
||||
CommandProcessor& cmd,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
|
@ -140,10 +140,13 @@ namespace Language_en {
|
||||
|
||||
PROGMEM Language_Str MSG_TOUCH_CALIBRATION_START = u8"Release to begin screen calibration";
|
||||
PROGMEM Language_Str MSG_TOUCH_CALIBRATION_PROMPT = u8"Touch the dots to calibrate";
|
||||
PROGMEM Language_Str MSG_AUTOLEVEL_X_AXIS = u8"Level X Axis";
|
||||
PROGMEM Language_Str MSG_BED_MAPPING_DONE = u8"Bed mapping finished";
|
||||
PROGMEM Language_Str MSG_BED_MAPPING_INCOMPLETE = u8"Not all points probed";
|
||||
PROGMEM Language_Str MSG_LEVELING = u8"Leveling";
|
||||
PROGMEM Language_Str MSG_AXIS_LEVELING = u8"Axis Leveling";
|
||||
PROGMEM Language_Str MSG_PROBE_BED = u8"Probe Mesh";
|
||||
PROGMEM Language_Str MSG_SHOW_MESH = u8"View Mesh";
|
||||
PROGMEM Language_Str MSG_PRINT_TEST = u8"Print Test";
|
||||
|
||||
#if ENABLED(TOUCH_UI_LULZBOT_BIO)
|
||||
PROGMEM Language_Str MSG_MOVE_TO_HOME = u8"Move to Home";
|
||||
|
@ -225,6 +225,7 @@ bool BedMeshScreen::tagToPoint(uint8_t tag, xy_uint8_t &pt) {
|
||||
}
|
||||
|
||||
void BedMeshScreen::onEntry() {
|
||||
mydata.allowEditing = true;
|
||||
mydata.highlightedTag = 0;
|
||||
mydata.zAdjustment = 0;
|
||||
mydata.count = GRID_MAX_POINTS;
|
||||
@ -259,16 +260,16 @@ void BedMeshScreen::adjustHighlightedValue(float increment) {
|
||||
}
|
||||
|
||||
void BedMeshScreen::saveAdjustedHighlightedValue() {
|
||||
if(mydata.zAdjustment) {
|
||||
if (mydata.zAdjustment) {
|
||||
BedMeshScreen::setHighlightedValue(BedMeshScreen::getHighlightedValue(true) + mydata.zAdjustment);
|
||||
mydata.zAdjustment = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BedMeshScreen::changeHighlightedValue(uint8_t tag) {
|
||||
saveAdjustedHighlightedValue();
|
||||
if (mydata.allowEditing) saveAdjustedHighlightedValue();
|
||||
mydata.highlightedTag = tag;
|
||||
moveToHighlightedValue();
|
||||
if (mydata.allowEditing) moveToHighlightedValue();
|
||||
}
|
||||
|
||||
void BedMeshScreen::drawHighlightedPointValue() {
|
||||
@ -277,7 +278,12 @@ void BedMeshScreen::drawHighlightedPointValue() {
|
||||
.colors(normal_btn)
|
||||
.text(Z_LABEL_POS, GET_TEXT_F(MSG_MESH_EDIT_Z))
|
||||
.font(font_small);
|
||||
draw_adjuster(cmd, Z_VALUE_POS, 2, getHighlightedValue(true) + mydata.zAdjustment, GET_TEXT_F(MSG_UNITS_MM), 4, 3);
|
||||
|
||||
if (mydata.allowEditing)
|
||||
draw_adjuster(cmd, Z_VALUE_POS, 2, getHighlightedValue(true) + mydata.zAdjustment, GET_TEXT_F(MSG_UNITS_MM), 4, 3);
|
||||
else
|
||||
draw_adjuster_value(cmd, Z_VALUE_POS, getHighlightedValue(true) + mydata.zAdjustment, GET_TEXT_F(MSG_UNITS_MM), 4, 3);
|
||||
|
||||
cmd.colors(action_btn)
|
||||
.tag(1).button(OKAY_POS, GET_TEXT_F(MSG_BUTTON_OKAY))
|
||||
.tag(0);
|
||||
@ -347,6 +353,7 @@ void BedMeshScreen::onMeshUpdate(const int8_t, const int8_t, const float) {
|
||||
void BedMeshScreen::onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t state) {
|
||||
switch (state) {
|
||||
case ExtUI::MESH_START:
|
||||
mydata.allowEditing = false;
|
||||
mydata.count = 0;
|
||||
mydata.message = mydata.MSG_NONE;
|
||||
break;
|
||||
@ -369,10 +376,16 @@ void BedMeshScreen::onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::pr
|
||||
|
||||
void BedMeshScreen::startMeshProbe() {
|
||||
GOTO_SCREEN(BedMeshScreen);
|
||||
mydata.allowEditing = false;
|
||||
mydata.count = 0;
|
||||
injectCommands_P(PSTR(BED_LEVELING_COMMANDS));
|
||||
}
|
||||
|
||||
void BedMeshScreen::showMesh() {
|
||||
GOTO_SCREEN(BedMeshScreen);
|
||||
mydata.allowEditing = false;
|
||||
}
|
||||
|
||||
void BedMeshScreen::showMeshEditor() {
|
||||
SpinnerDialogBox::enqueueAndWait_P(ExtUI::isMachineHomed() ? F("M420 S1") : F("G28\nM420 S1"));
|
||||
// After the spinner, go to this screen.
|
||||
|
@ -33,6 +33,7 @@ struct BedMeshScreenData {
|
||||
uint8_t count;
|
||||
uint8_t highlightedTag;
|
||||
float zAdjustment;
|
||||
bool allowEditing;
|
||||
};
|
||||
|
||||
class BedMeshScreen : public BaseScreen, public CachedScreen<BED_MESH_SCREEN_CACHE> {
|
||||
@ -63,5 +64,6 @@ class BedMeshScreen : public BaseScreen, public CachedScreen<BED_MESH_SCREEN_CAC
|
||||
static bool onTouchEnd(uint8_t tag);
|
||||
|
||||
static void startMeshProbe();
|
||||
static void showMesh();
|
||||
static void showMeshEditor();
|
||||
};
|
||||
|
@ -34,27 +34,33 @@ using namespace ExtUI;
|
||||
using namespace Theme;
|
||||
|
||||
#if ENABLED(TOUCH_UI_PORTRAIT)
|
||||
#define GRID_ROWS 9
|
||||
#define GRID_ROWS 8
|
||||
#define GRID_COLS 2
|
||||
#define TITLE_POS BTN_POS(1,1), BTN_SIZE(2,1)
|
||||
#define LEVELING_TITLE_POS BTN_POS(1,1), BTN_SIZE(2,1)
|
||||
#define LEVEL_AXIS_POS BTN_POS(1,2), BTN_SIZE(2,1)
|
||||
#define LEVEL_BED_POS BTN_POS(1,3), BTN_SIZE(2,1)
|
||||
#define EDIT_MESH_POS BTN_POS(1,4), BTN_SIZE(2,1)
|
||||
#define BED_MESH_TITLE_POS BTN_POS(1,3), BTN_SIZE(2,1)
|
||||
#define PROBE_BED_POS BTN_POS(1,4), BTN_SIZE(1,1)
|
||||
#define TEST_MESH_POS BTN_POS(2,4), BTN_SIZE(1,1)
|
||||
#define SHOW_MESH_POS BTN_POS(1,5), BTN_SIZE(1,1)
|
||||
#define EDIT_MESH_POS BTN_POS(2,5), BTN_SIZE(1,1)
|
||||
#define BLTOUCH_TITLE_POS BTN_POS(1,6), BTN_SIZE(2,1)
|
||||
#define BLTOUCH_RESET_POS BTN_POS(1,7), BTN_SIZE(1,1)
|
||||
#define BLTOUCH_TEST_POS BTN_POS(2,7), BTN_SIZE(1,1)
|
||||
#define BACK_POS BTN_POS(1,9), BTN_SIZE(2,1)
|
||||
#define BACK_POS BTN_POS(1,8), BTN_SIZE(2,1)
|
||||
#else
|
||||
#define GRID_ROWS 7
|
||||
#define GRID_COLS 2
|
||||
#define TITLE_POS BTN_POS(1,1), BTN_SIZE(2,1)
|
||||
#define LEVEL_AXIS_POS BTN_POS(1,2), BTN_SIZE(2,1)
|
||||
#define LEVEL_BED_POS BTN_POS(1,3), BTN_SIZE(2,1)
|
||||
#define EDIT_MESH_POS BTN_POS(1,4), BTN_SIZE(2,1)
|
||||
#define BLTOUCH_TITLE_POS BTN_POS(1,5), BTN_SIZE(2,1)
|
||||
#define BLTOUCH_RESET_POS BTN_POS(1,6), BTN_SIZE(1,1)
|
||||
#define BLTOUCH_TEST_POS BTN_POS(2,6), BTN_SIZE(1,1)
|
||||
#define BACK_POS BTN_POS(1,7), BTN_SIZE(2,1)
|
||||
#define GRID_ROWS 6
|
||||
#define GRID_COLS 3
|
||||
#define LEVELING_TITLE_POS BTN_POS(1,1), BTN_SIZE(3,1)
|
||||
#define LEVEL_AXIS_POS BTN_POS(1,2), BTN_SIZE(3,1)
|
||||
#define BED_MESH_TITLE_POS BTN_POS(1,3), BTN_SIZE(2,1)
|
||||
#define PROBE_BED_POS BTN_POS(1,4), BTN_SIZE(1,1)
|
||||
#define TEST_MESH_POS BTN_POS(2,4), BTN_SIZE(1,1)
|
||||
#define SHOW_MESH_POS BTN_POS(1,5), BTN_SIZE(1,1)
|
||||
#define EDIT_MESH_POS BTN_POS(2,5), BTN_SIZE(1,1)
|
||||
#define BLTOUCH_TITLE_POS BTN_POS(3,3), BTN_SIZE(1,1)
|
||||
#define BLTOUCH_RESET_POS BTN_POS(3,4), BTN_SIZE(1,1)
|
||||
#define BLTOUCH_TEST_POS BTN_POS(3,5), BTN_SIZE(1,1)
|
||||
#define BACK_POS BTN_POS(1,6), BTN_SIZE(3,1)
|
||||
#endif
|
||||
|
||||
void LevelingMenu::onRedraw(draw_mode_t what) {
|
||||
@ -69,20 +75,25 @@ void LevelingMenu::onRedraw(draw_mode_t what) {
|
||||
CommandProcessor cmd;
|
||||
cmd.font(font_large)
|
||||
.cmd(COLOR_RGB(bg_text_enabled))
|
||||
.text(TITLE_POS, GET_TEXT_F(MSG_LEVELING))
|
||||
.text(LEVELING_TITLE_POS, GET_TEXT_F(MSG_AXIS_LEVELING))
|
||||
.text(BED_MESH_TITLE_POS, GET_TEXT_F(MSG_BED_LEVELING))
|
||||
#if ENABLED(BLTOUCH)
|
||||
.text(BLTOUCH_TITLE_POS, GET_TEXT_F(MSG_BLTOUCH))
|
||||
#endif
|
||||
.font(font_medium).colors(normal_btn)
|
||||
#if EITHER(Z_STEPPER_AUTO_ALIGN,MECHANICAL_GANTRY_CALIBRATION)
|
||||
.tag(2).button(LEVEL_AXIS_POS, GET_TEXT_F(MSG_AUTOLEVEL_X_AXIS))
|
||||
.tag(2).button(LEVEL_AXIS_POS, GET_TEXT_F(MSG_LEVEL_X_AXIS))
|
||||
#endif
|
||||
.tag(3).button(LEVEL_BED_POS, GET_TEXT_F(MSG_LEVEL_BED))
|
||||
.tag(3).button(PROBE_BED_POS, GET_TEXT_F(MSG_PROBE_BED))
|
||||
.enabled(ENABLED(HAS_MESH))
|
||||
.tag(4).button(EDIT_MESH_POS, GET_TEXT_F(MSG_EDIT_MESH))
|
||||
.tag(4).button(SHOW_MESH_POS, GET_TEXT_F(MSG_SHOW_MESH))
|
||||
.enabled(ENABLED(HAS_MESH))
|
||||
.tag(5).button(EDIT_MESH_POS, GET_TEXT_F(MSG_EDIT_MESH))
|
||||
.enabled(ENABLED(G26_MESH_VALIDATION))
|
||||
.tag(6).button(TEST_MESH_POS, GET_TEXT_F(MSG_PRINT_TEST))
|
||||
#if ENABLED(BLTOUCH)
|
||||
.tag(5).button(BLTOUCH_RESET_POS, GET_TEXT_F(MSG_BLTOUCH_RESET))
|
||||
.tag(6).button(BLTOUCH_TEST_POS, GET_TEXT_F(MSG_BLTOUCH_SELFTEST))
|
||||
.tag(7).button(BLTOUCH_RESET_POS, GET_TEXT_F(MSG_BLTOUCH_RESET))
|
||||
.tag(8).button(BLTOUCH_TEST_POS, GET_TEXT_F(MSG_BLTOUCH_SELFTEST))
|
||||
#endif
|
||||
.colors(action_btn)
|
||||
.tag(1).button(BACK_POS, GET_TEXT_F(MSG_BACK));
|
||||
@ -106,11 +117,18 @@ bool LevelingMenu::onTouchEnd(uint8_t tag) {
|
||||
#endif
|
||||
break;
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
case 4: BedMeshScreen::showMeshEditor(); break;
|
||||
case 4: BedMeshScreen::showMesh(); break;
|
||||
case 5: BedMeshScreen::showMeshEditor(); break;
|
||||
#endif
|
||||
#if ENABLED(G26_MESH_VALIDATION)
|
||||
case 6:
|
||||
GOTO_SCREEN(StatusScreen);
|
||||
injectCommands_P(PSTR("M117 Printing Test Pattern\nG28 O\nG26 R"));
|
||||
break;
|
||||
#endif
|
||||
#if ENABLED(BLTOUCH)
|
||||
case 5: injectCommands_P(PSTR("M280 P0 S60")); break;
|
||||
case 6: SpinnerDialogBox::enqueueAndWait_P(F("M280 P0 S90\nG4 P100\nM280 P0 S120")); break;
|
||||
case 7: injectCommands_P(PSTR("M280 P0 S60")); break;
|
||||
case 8: SpinnerDialogBox::enqueueAndWait_P(F("M280 P0 S90\nG4 P100\nM280 P0 S120")); break;
|
||||
#endif
|
||||
default: return false;
|
||||
}
|
||||
@ -118,3 +136,4 @@ bool LevelingMenu::onTouchEnd(uint8_t tag) {
|
||||
}
|
||||
|
||||
#endif // FTDI_LEVELING_MENU
|
||||
|
||||
|
@ -62,7 +62,7 @@ void TuneMenu::onRedraw(draw_mode_t what) {
|
||||
#define FILAMENT_POS BTN_POS(1,4), BTN_SIZE(1,1)
|
||||
#define CASE_LIGHT_POS BTN_POS(2,4), BTN_SIZE(1,1)
|
||||
#define ADVANCED_SETTINGS_POS BTN_POS(1,5), BTN_SIZE(1,1)
|
||||
#define BACK_POS BTN_POS(2,5), BTN_SIZE(2,1)
|
||||
#define BACK_POS BTN_POS(2,5), BTN_SIZE(1,1)
|
||||
#endif
|
||||
|
||||
if (what & FOREGROUND) {
|
||||
|
@ -849,10 +849,13 @@ namespace ExtUI {
|
||||
}
|
||||
|
||||
#if HAS_LEVELING
|
||||
|
||||
bool getLevelingActive() { return planner.leveling_active; }
|
||||
void setLevelingActive(const bool state) { set_bed_leveling_enabled(state); }
|
||||
bool getMeshValid() { return leveling_is_valid(); }
|
||||
|
||||
#if HAS_MESH
|
||||
|
||||
bed_mesh_t& getMeshArray() { return Z_VALUES_ARR; }
|
||||
float getMeshPoint(const xy_uint8_t &pos) { return Z_VALUES(pos.x, pos.y); }
|
||||
void setMeshPoint(const xy_uint8_t &pos, const float &zoff) {
|
||||
@ -861,17 +864,23 @@ namespace ExtUI {
|
||||
TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());
|
||||
}
|
||||
}
|
||||
|
||||
void moveToMeshPoint(const xy_uint8_t &pos, const float &z) {
|
||||
#if EITHER(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL)
|
||||
const feedRate_t old_feedrate = feedrate_mm_s;
|
||||
feedrate_mm_s = Z_PROBE_FEEDRATE_FAST;
|
||||
destination = current_position;
|
||||
destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES;
|
||||
prepare_line_to_destination();
|
||||
feedrate_mm_s = XY_PROBE_FEEDRATE;
|
||||
destination[X_AXIS] = MESH_MIN_X + pos.x * MESH_X_DIST;
|
||||
destination[Y_AXIS] = MESH_MIN_Y + pos.y * MESH_Y_DIST;
|
||||
prepare_line_to_destination();
|
||||
const float x_target = MESH_MIN_X + pos.x * (MESH_X_DIST),
|
||||
y_target = MESH_MIN_Y + pos.y * (MESH_Y_DIST);
|
||||
if (x_target != current_position[X_AXIS] || y_target != current_position[Y_AXIS]) {
|
||||
// If moving across bed, raise nozzle to safe height over bed
|
||||
feedrate_mm_s = Z_PROBE_FEEDRATE_FAST;
|
||||
destination = current_position;
|
||||
destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES;
|
||||
prepare_line_to_destination();
|
||||
feedrate_mm_s = XY_PROBE_FEEDRATE;
|
||||
destination[X_AXIS] = x_target;
|
||||
destination[Y_AXIS] = y_target;
|
||||
prepare_line_to_destination();
|
||||
}
|
||||
feedrate_mm_s = Z_PROBE_FEEDRATE_FAST;
|
||||
destination[Z_AXIS] = z;
|
||||
prepare_line_to_destination();
|
||||
@ -881,8 +890,10 @@ namespace ExtUI {
|
||||
UNUSED(z);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // HAS_MESH
|
||||
|
||||
#endif // HAS_LEVELING
|
||||
|
||||
#if ENABLED(HOST_PROMPT_SUPPORT)
|
||||
void setHostResponse(const uint8_t response) { host_response_handler(response); }
|
||||
|
@ -75,6 +75,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
|
||||
-<src/feature/bedlevel/abl> -<src/gcode/bedlevel/abl>
|
||||
-<src/feature/bedlevel/mbl> -<src/gcode/bedlevel/mbl>
|
||||
-<src/feature/bedlevel/ubl> -<src/gcode/bedlevel/ubl>
|
||||
-<src/feature/bedlevel/hilbert_curve.cpp>
|
||||
-<src/feature/binary_stream.cpp> -<src/libs/heatshrink>
|
||||
-<src/feature/bltouch.cpp>
|
||||
-<src/feature/cancel_object.cpp> -<src/gcode/feature/cancel>
|
||||
@ -306,6 +307,7 @@ AUTO_BED_LEVELING_BILINEAR = src_filter=+<src/feature/bedlevel/abl>
|
||||
AUTO_BED_LEVELING_(3POINT|(BI)?LINEAR) = src_filter=+<src/gcode/bedlevel/abl>
|
||||
MESH_BED_LEVELING = src_filter=+<src/feature/bedlevel/mbl> +<src/gcode/bedlevel/mbl>
|
||||
AUTO_BED_LEVELING_UBL = src_filter=+<src/feature/bedlevel/ubl> +<src/gcode/bedlevel/ubl>
|
||||
UBL_HILBERT_CURVE = src_filter=+<src/feature/bedlevel/hilbert_curve.cpp>
|
||||
BACKLASH_COMPENSATION = src_filter=+<src/feature/backlash.cpp>
|
||||
BARICUDA = src_filter=+<src/feature/baricuda.cpp> +<src/gcode/feature/baricuda>
|
||||
BINARY_FILE_TRANSFER = src_filter=+<src/feature/binary_stream.cpp> +<src/libs/heatshrink>
|
||||
|
Loading…
Reference in New Issue
Block a user