Fix and improve FTDI Eve Touch UI (#17426)

This commit is contained in:
Marcio T 2020-04-09 15:00:25 -06:00 committed by GitHub
parent 397fa59eee
commit dbdfe61644
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 56 deletions

View File

@ -43,41 +43,33 @@ using namespace ExtUI;
#define GRID_COLS 5 #define GRID_COLS 5
#define GRID_ROWS 5 #define GRID_ROWS 5
#define MESH_POS BTN_POS(2,1), BTN_SIZE(4,5) #define MESH_POS BTN_POS(1,1), BTN_SIZE(3,5)
#define Z_LABEL_POS BTN_POS(1,3), BTN_SIZE(1,1) #define Z_LABEL_POS BTN_POS(4,2), BTN_SIZE(2,1)
#define Z_VALUE_POS BTN_POS(1,4), BTN_SIZE(2,1) #define Z_VALUE_POS BTN_POS(4,3), BTN_SIZE(2,1)
#define WAIT_POS BTN_POS(1,3), BTN_SIZE(2,2) #define WAIT_POS BTN_POS(4,2), BTN_SIZE(2,2)
#define BACK_POS BTN_POS(1,5), BTN_SIZE(2,1) #define BACK_POS BTN_POS(4,5), BTN_SIZE(2,1)
#endif #endif
void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts) { void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts, float autoscale_max) {
CommandProcessor cmd;
#define TRANSFORM_2(X,Y,Z) (X), (Y) // No transform
#define TRANSFORM_1(X,Y,Z) TRANSFORM_2((X) + (Y) * slant, (Y) - (Z), 0) // Perspective
#define TRANSFORM(X,Y,Z) TRANSFORM_1(float(X)/(cols-1) - 0.5, float(Y)/(rows-1) - 0.5, (Z)) // Normalize
constexpr uint8_t rows = GRID_MAX_POINTS_Y; constexpr uint8_t rows = GRID_MAX_POINTS_Y;
constexpr uint8_t cols = GRID_MAX_POINTS_X; constexpr uint8_t cols = GRID_MAX_POINTS_X;
const float slant = 0.5;
const float bounds_min[] = {TRANSFORM(0 ,0 ,0)}; #define VALUE(X,Y) (data ? data[X][Y] : 0)
const float bounds_max[] = {TRANSFORM(cols,rows,0)}; #define ISVAL(X,Y) (data ? !isnan(VALUE(X,Y)) : true)
const float scale_x = float(w)/(bounds_max[0] - bounds_min[0]); #define HEIGHT(X,Y) (ISVAL(X,Y) ? (VALUE(X,Y) - val_min) * scale_z : 0)
const float scale_y = float(h)/(bounds_max[1] - bounds_min[1]);
const float center_x = x + w/2; // Compute the mean, min and max for the points
const float center_y = y + h/2;
float val_mean = 0; float val_mean = 0;
float val_max = -INFINITY; float val_max = -INFINITY;
float val_min = INFINITY; float val_min = INFINITY;
uint8_t val_cnt = 0; uint8_t val_cnt = 0;
if (opts & USE_AUTOSCALE) { if (data && (opts & USE_AUTOSCALE)) {
// Compute the mean
for (uint8_t y = 0; y < rows; y++) { for (uint8_t y = 0; y < rows; y++) {
for (uint8_t x = 0; x < cols; x++) { for (uint8_t x = 0; x < cols; x++) {
const float val = data[x][y]; if (ISVAL(x,y)) {
if (!isnan(val)) { const float val = VALUE(x,y);
val_mean += val; val_mean += val;
val_max = max(val_max, val); val_max = max(val_max, val);
val_min = min(val_min, val); val_min = min(val_min, val);
@ -85,27 +77,56 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::
} }
} }
} }
}
if (val_cnt) { if (val_cnt) {
val_mean /= val_cnt; val_mean /= val_cnt;
val_min -= val_mean;
val_max -= val_mean;
} else { } else {
val_mean = 0; val_mean = 0;
val_min = 0; val_min = 0;
val_max = 0; val_max = 0;
} }
}
const float scale_z = ((val_max == val_min) ? 1 : 1/(val_max - val_min)) * 0.1; const float scale_z = ((val_max == val_min) ? 1 : 1/(val_max - val_min)) * autoscale_max;
#undef TRANSFORM_2 // These equations determine the appearance of the grid on the screen.
#define TRANSFORM_2(X,Y,Z) center_x + (X) * scale_x, center_y + (Y) * scale_y // Scale and position
#define VALUE(X,Y) ((data && ISVAL(X,Y)) ? data[X][Y] : 0)
#define ISVAL(X,Y) (data ? !isnan(data[X][Y]) : true)
#define HEIGHT(X,Y) (VALUE(X,Y) * scale_z)
uint16_t basePointSize = min(scale_x,scale_y) / max(cols,rows); #define TRANSFORM_5(X,Y,Z) (X), (Y) // No transform
#define TRANSFORM_4(X,Y,Z) TRANSFORM_5((X)/(Z),(Y)/-(Z), 0) // Perspective
#define TRANSFORM_3(X,Y,Z) TRANSFORM_4((X), (Z), (Y)) // Swap Z and Y
#define TRANSFORM_2(X,Y,Z) TRANSFORM_3((X), (Y) + 2.5, (Z) - 1) // Translate
#define TRANSFORM(X,Y,Z) TRANSFORM_2(float(X)/(cols-1) - 0.5, float(Y)/(rows-1) - 0.5, (Z)) // Normalize
// Compute the bounding box for the grid prior to scaling. Do this at compile-time by
// transforming the four corner points via the transformation equations and finding
// the min and max for each axis.
constexpr float bounds[][3] = {{TRANSFORM(0 , 0 , 0)},
{TRANSFORM(cols-1, 0 , 0)},
{TRANSFORM(0 , rows-1, 0)},
{TRANSFORM(cols-1, rows-1, 0)}};
#define APPLY(FUNC, AXIS) FUNC(FUNC(bounds[0][AXIS], bounds[1][AXIS]), FUNC(bounds[2][AXIS], bounds[3][AXIS]))
constexpr float grid_x = APPLY(min,0);
constexpr float grid_y = APPLY(min,1);
constexpr float grid_w = APPLY(max,0) - grid_x;
constexpr float grid_h = APPLY(max,1) - grid_y;
constexpr float grid_cx = grid_x + grid_w/2;
constexpr float grid_cy = grid_y + grid_h/2;
// Figure out scale and offset such that the grid fits within the rectangle given by (x,y,w,h)
const float scale_x = float(w)/grid_w;
const float scale_y = float(h)/grid_h;
const float center_x = x + w/2;
const float center_y = y + h/2;
#undef TRANSFORM_5
#define TRANSFORM_5(X,Y,Z) center_x + (X - grid_cx) * scale_x, center_y + (Y - grid_cy) * scale_y // Fit to bounds
// Draw the grid
const uint16_t basePointSize = min(w,h) / max(cols,rows);
CommandProcessor cmd;
cmd.cmd(SAVE_CONTEXT()) cmd.cmd(SAVE_CONTEXT())
.cmd(VERTEX_FORMAT(0)) .cmd(VERTEX_FORMAT(0))
.cmd(TAG_MASK(false)) .cmd(TAG_MASK(false))
@ -126,13 +147,15 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::
} }
if (opts & USE_POINTS) { if (opts & USE_POINTS) {
const float sq_min = sq(val_min - val_mean);
const float sq_max = sq(val_max - val_mean);
cmd.cmd(POINT_SIZE(basePointSize * 2)); cmd.cmd(POINT_SIZE(basePointSize * 2));
cmd.cmd(BEGIN(POINTS)); cmd.cmd(BEGIN(POINTS));
for (uint8_t x = 0; x < cols; x++) { for (uint8_t x = 0; x < cols; x++) {
if (ISVAL(x,y)) { if (ISVAL(x,y)) {
if (opts & USE_COLORS) { if (opts & USE_COLORS) {
const float val_dev = VALUE(x, y) - val_mean; const float val_dev = VALUE(x, y) - val_mean;
const uint8_t neg_byte = sq(val_dev) / sq(val_dev < 0 ? val_min : val_max) * 0xFF; const uint8_t neg_byte = sq(val_dev) / (val_dev < 0 ? sq_min : sq_max) * 0xFF;
const uint8_t pos_byte = 255 - neg_byte; const uint8_t pos_byte = 255 - neg_byte;
cmd.cmd(COLOR_RGB(pos_byte, pos_byte, 0xFF)); cmd.cmd(COLOR_RGB(pos_byte, pos_byte, 0xFF));
} }
@ -164,12 +187,13 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::
if (opts & USE_HIGHLIGHT) { if (opts & USE_HIGHLIGHT) {
const uint8_t tag = screen_data.BedMeshScreen.highlightedTag; const uint8_t tag = screen_data.BedMeshScreen.highlightedTag;
uint8_t x, y; uint8_t x, y;
tagToPoint(tag, x, y); if (tagToPoint(tag, x, y)) {
cmd.cmd(COLOR_A(128)) cmd.cmd(COLOR_A(128))
.cmd(POINT_SIZE(basePointSize * 6)) .cmd(POINT_SIZE(basePointSize * 6))
.cmd(BEGIN(POINTS)) .cmd(BEGIN(POINTS))
.tag(tag).cmd(VERTEX2F(TRANSFORM(x, y, HEIGHT(x, y)))); .tag(tag).cmd(VERTEX2F(TRANSFORM(x, y, HEIGHT(x, y))));
} }
}
cmd.cmd(END()); cmd.cmd(END());
cmd.cmd(RESTORE_CONTEXT()); cmd.cmd(RESTORE_CONTEXT());
} }
@ -178,9 +202,11 @@ uint8_t BedMeshScreen::pointToTag(uint8_t x, uint8_t y) {
return y * (GRID_MAX_POINTS_X) + x + 10; return y * (GRID_MAX_POINTS_X) + x + 10;
} }
void BedMeshScreen::tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y) { bool BedMeshScreen::tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y) {
if (tag < 10) return false;
x = (tag - 10) % (GRID_MAX_POINTS_X); x = (tag - 10) % (GRID_MAX_POINTS_X);
y = (tag - 10) / (GRID_MAX_POINTS_X); y = (tag - 10) / (GRID_MAX_POINTS_X);
return true;
} }
void BedMeshScreen::onEntry() { void BedMeshScreen::onEntry() {
@ -217,6 +243,9 @@ void BedMeshScreen::drawHighlightedPointValue() {
} }
void BedMeshScreen::onRedraw(draw_mode_t what) { void BedMeshScreen::onRedraw(draw_mode_t what) {
#define _INSET_POS(x,y,w,h) x + min(w,h)/10, y + min(w,h)/10, w - min(w,h)/5, h - min(w,h)/5
#define INSET_POS(pos) _INSET_POS(pos)
if (what & BACKGROUND) { if (what & BACKGROUND) {
CommandProcessor cmd; CommandProcessor cmd;
cmd.cmd(CLEAR_COLOR_RGB(bg_color)) cmd.cmd(CLEAR_COLOR_RGB(bg_color))
@ -224,16 +253,20 @@ void BedMeshScreen::onRedraw(draw_mode_t what) {
// Draw the shadow and tags // Draw the shadow and tags
cmd.cmd(COLOR_RGB(0x444444)); cmd.cmd(COLOR_RGB(0x444444));
BedMeshScreen::drawMesh(MESH_POS, nullptr, USE_POINTS | USE_TAGS); BedMeshScreen::drawMesh(INSET_POS(MESH_POS), nullptr, USE_POINTS | USE_TAGS);
cmd.cmd(COLOR_RGB(bg_text_enabled)); cmd.cmd(COLOR_RGB(bg_text_enabled));
} }
if (what & FOREGROUND) { if (what & FOREGROUND) {
constexpr float autoscale_max_amplitude = 0.03;
const bool levelingFinished = screen_data.BedMeshScreen.count >= GRID_MAX_POINTS; const bool levelingFinished = screen_data.BedMeshScreen.count >= GRID_MAX_POINTS;
const float levelingProgress = sq(float(screen_data.BedMeshScreen.count) / GRID_MAX_POINTS);
if (levelingFinished) drawHighlightedPointValue(); if (levelingFinished) drawHighlightedPointValue();
BedMeshScreen::drawMesh(MESH_POS, ExtUI::getMeshArray(), BedMeshScreen::drawMesh(INSET_POS(MESH_POS), ExtUI::getMeshArray(),
USE_POINTS | USE_HIGHLIGHT | USE_AUTOSCALE | (levelingFinished ? USE_COLORS : 0)); USE_POINTS | USE_HIGHLIGHT | USE_AUTOSCALE | (levelingFinished ? USE_COLORS : 0),
autoscale_max_amplitude * levelingProgress
);
} }
} }

View File

@ -68,10 +68,10 @@ void BootScreen::onIdle() {
InterfaceSettingsScreen::failSafeSettings(); InterfaceSettingsScreen::failSafeSettings();
StatusScreen::loadBitmaps(); StatusScreen::loadBitmaps();
StatusScreen::setStatusMessage(GET_TEXT_F(WELCOME_MSG));
GOTO_SCREEN(TouchCalibrationScreen); GOTO_SCREEN(TouchCalibrationScreen);
current_screen.forget(); current_screen.forget();
PUSH_SCREEN(StatusScreen); PUSH_SCREEN(StatusScreen);
StatusScreen::setStatusMessage(GET_TEXT_F(WELCOME_MSG));
} else { } else {
if (!UIFlashStorage::is_valid()) { if (!UIFlashStorage::is_valid()) {
StatusScreen::loadBitmaps(); StatusScreen::loadBitmaps();

View File

@ -145,10 +145,10 @@ class BedMeshScreen : public BaseScreen, public CachedScreen<BED_MESH_SCREEN_CAC
}; };
static uint8_t pointToTag(uint8_t x, uint8_t y); static uint8_t pointToTag(uint8_t x, uint8_t y);
static void tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y); static bool tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y);
static float getHightlightedValue(); static float getHightlightedValue();
static void drawHighlightedPointValue(); static void drawHighlightedPointValue();
static void drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts); static void drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts, float autoscale_max = 0.1);
public: public:
static void onMeshUpdate(const int8_t x, const int8_t y, const float val); static void onMeshUpdate(const int8_t x, const int8_t y, const float val);

View File

@ -272,8 +272,8 @@ void StatusScreen::draw_interaction_buttons(draw_mode_t what) {
CommandProcessor cmd; CommandProcessor cmd;
cmd.colors(normal_btn) cmd.colors(normal_btn)
.font(Theme::font_medium) .font(Theme::font_medium)
.enabled(has_media)
.colors(has_media ? action_btn : normal_btn) .colors(has_media ? action_btn : normal_btn)
.enabled(has_media)
.tag(3).button(MEDIA_BTN_POS, isPrintingFromMedia() ? GET_TEXT_F(MSG_PRINTING) : GET_TEXT_F(MSG_BUTTON_MEDIA)) .tag(3).button(MEDIA_BTN_POS, isPrintingFromMedia() ? GET_TEXT_F(MSG_PRINTING) : GET_TEXT_F(MSG_BUTTON_MEDIA))
.colors(!has_media ? action_btn : normal_btn) .colors(!has_media ? action_btn : normal_btn)
.tag(4).button( MENU_BTN_POS, GET_TEXT_F(MSG_BUTTON_MENU)); .tag(4).button( MENU_BTN_POS, GET_TEXT_F(MSG_BUTTON_MENU));
@ -360,6 +360,7 @@ void StatusScreen::onRedraw(draw_mode_t what) {
} }
void StatusScreen::onEntry() { void StatusScreen::onEntry() {
BaseScreen::onEntry();
onRefresh(); onRefresh();
} }

View File

@ -32,6 +32,8 @@ using namespace Theme;
#define GRID_COLS 4 #define GRID_COLS 4
#define GRID_ROWS 16 #define GRID_ROWS 16
#define TEXT_POS BTN_POS(1,1), BTN_SIZE(4,12)
void TouchCalibrationScreen::onEntry() { void TouchCalibrationScreen::onEntry() {
CommandProcessor cmd; CommandProcessor cmd;
@ -45,7 +47,7 @@ void TouchCalibrationScreen::onEntry() {
.cmd(CLEAR_COLOR_RGB(bg_color)) .cmd(CLEAR_COLOR_RGB(bg_color))
.cmd(CLEAR(true,true,true)) .cmd(CLEAR(true,true,true))
.cmd(COLOR_RGB(bg_text_enabled)); .cmd(COLOR_RGB(bg_text_enabled));
draw_text_box(cmd, BTN_POS(1,1), BTN_SIZE(4,16), GET_TEXT_F(MSG_TOUCH_CALIBRATION_START), OPT_CENTER, font_large); draw_text_box(cmd, TEXT_POS, GET_TEXT_F(MSG_TOUCH_CALIBRATION_START), OPT_CENTER, font_large);
cmd.cmd(DL::DL_DISPLAY) cmd.cmd(DL::DL_DISPLAY)
.cmd(CMD_SWAP) .cmd(CMD_SWAP)
.execute(); .execute();
@ -76,7 +78,7 @@ void TouchCalibrationScreen::onRedraw(draw_mode_t) {
.cmd(CLEAR(true,true,true)) .cmd(CLEAR(true,true,true))
.cmd(COLOR_RGB(bg_text_enabled)); .cmd(COLOR_RGB(bg_text_enabled));
draw_text_box(cmd, BTN_POS(1,1), BTN_SIZE(4,16), GET_TEXT_F(MSG_TOUCH_CALIBRATION_PROMPT), OPT_CENTER, font_large); draw_text_box(cmd, TEXT_POS, GET_TEXT_F(MSG_TOUCH_CALIBRATION_PROMPT), OPT_CENTER, font_large);
cmd.cmd(CMD_CALIBRATE); cmd.cmd(CMD_CALIBRATE);
} }