Add Touch Calibration screen (#20049)
This commit is contained in:
@ -48,17 +48,12 @@ millis_t Touch::last_touch_ms = 0,
|
||||
Touch::repeat_delay,
|
||||
Touch::touch_time;
|
||||
TouchControlType Touch::touch_control_type = NONE;
|
||||
touch_calibration_t Touch::calibration;
|
||||
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
|
||||
calibrationState Touch::calibration_state = CALIBRATION_NONE;
|
||||
touch_calibration_point_t Touch::calibration_points[4];
|
||||
#endif
|
||||
#if HAS_RESUME_CONTINUE
|
||||
extern bool wait_for_user;
|
||||
#endif
|
||||
|
||||
void Touch::init() {
|
||||
calibration_reset();
|
||||
TERN_(TOUCH_SCREEN_CALIBRATION, touch_calibration.calibration_reset());
|
||||
reset();
|
||||
io.Init();
|
||||
enable();
|
||||
@ -155,52 +150,7 @@ void Touch::touch(touch_control_t *control) {
|
||||
switch (control->type) {
|
||||
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
|
||||
case CALIBRATE:
|
||||
ui.refresh();
|
||||
|
||||
if (calibration_state < CALIBRATION_SUCCESS) {
|
||||
calibration_points[calibration_state].x = int16_t(control->data >> 16);
|
||||
calibration_points[calibration_state].y = int16_t(control->data & 0xFFFF);
|
||||
calibration_points[calibration_state].raw_x = x;
|
||||
calibration_points[calibration_state].raw_y = y;
|
||||
}
|
||||
|
||||
switch (calibration_state) {
|
||||
case CALIBRATION_POINT_1: calibration_state = CALIBRATION_POINT_2; break;
|
||||
case CALIBRATION_POINT_2: calibration_state = CALIBRATION_POINT_3; break;
|
||||
case CALIBRATION_POINT_3: calibration_state = CALIBRATION_POINT_4; break;
|
||||
case CALIBRATION_POINT_4:
|
||||
if (validate_precision_x(0, 1) && validate_precision_x(2, 3) && validate_precision_y(0, 2) && validate_precision_y(1, 3)) {
|
||||
calibration_state = CALIBRATION_SUCCESS;
|
||||
calibration.x = ((calibration_points[2].x - calibration_points[0].x) << 17) / (calibration_points[3].raw_x + calibration_points[2].raw_x - calibration_points[1].raw_x - calibration_points[0].raw_x);
|
||||
calibration.y = ((calibration_points[1].y - calibration_points[0].y) << 17) / (calibration_points[3].raw_y - calibration_points[2].raw_y + calibration_points[1].raw_y - calibration_points[0].raw_y);
|
||||
calibration.offset_x = calibration_points[0].x - int16_t(((calibration_points[0].raw_x + calibration_points[1].raw_x) * calibration.x) >> 17);
|
||||
calibration.offset_y = calibration_points[0].y - int16_t(((calibration_points[0].raw_y + calibration_points[2].raw_y) * calibration.y) >> 17);
|
||||
calibration.orientation = TOUCH_LANDSCAPE;
|
||||
}
|
||||
else if (validate_precision_y(0, 1) && validate_precision_y(2, 3) && validate_precision_x(0, 2) && validate_precision_x(1, 3)) {
|
||||
calibration_state = CALIBRATION_SUCCESS;
|
||||
calibration.x = ((calibration_points[2].x - calibration_points[0].x) << 17) / (calibration_points[3].raw_y + calibration_points[2].raw_y - calibration_points[1].raw_y - calibration_points[0].raw_y);
|
||||
calibration.y = ((calibration_points[1].y - calibration_points[0].y) << 17) / (calibration_points[3].raw_x - calibration_points[2].raw_x + calibration_points[1].raw_x - calibration_points[0].raw_x);
|
||||
calibration.offset_x = calibration_points[0].x - int16_t(((calibration_points[0].raw_y + calibration_points[1].raw_y) * calibration.x) >> 17);
|
||||
calibration.offset_y = calibration_points[0].y - int16_t(((calibration_points[0].raw_x + calibration_points[2].raw_x) * calibration.y) >> 17);
|
||||
calibration.orientation = TOUCH_PORTRAIT;
|
||||
}
|
||||
else {
|
||||
calibration_state = CALIBRATION_FAIL;
|
||||
calibration_reset();
|
||||
}
|
||||
|
||||
if (calibration_state == CALIBRATION_SUCCESS) {
|
||||
SERIAL_ECHOLNPGM("Touch screen calibration completed");
|
||||
SERIAL_ECHOLNPAIR("TOUCH_CALIBRATION_X ", calibration.x);
|
||||
SERIAL_ECHOLNPAIR("TOUCH_CALIBRATION_Y ", calibration.y);
|
||||
SERIAL_ECHOLNPAIR("TOUCH_OFFSET_X ", calibration.offset_x);
|
||||
SERIAL_ECHOLNPAIR("TOUCH_OFFSET_Y ", calibration.offset_y);
|
||||
SERIAL_ECHOPGM("TOUCH_ORIENTATION "); if (calibration.orientation == TOUCH_LANDSCAPE) SERIAL_ECHOLNPGM("TOUCH_LANDSCAPE"); else SERIAL_ECHOLNPGM("TOUCH_PORTRAIT");
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (touch_calibration.handleTouch(x, y)) ui.refresh();
|
||||
break;
|
||||
#endif // TOUCH_SCREEN_CALIBRATION
|
||||
|
||||
@ -298,12 +248,18 @@ void Touch::hold(touch_control_t *control, millis_t delay) {
|
||||
}
|
||||
|
||||
bool Touch::get_point(int16_t *x, int16_t *y) {
|
||||
bool is_touched = (calibration.orientation == TOUCH_PORTRAIT ? io.getRawPoint(y, x) : io.getRawPoint(x, y));
|
||||
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
|
||||
bool is_touched = (touch_calibration.calibration.orientation == TOUCH_PORTRAIT ? io.getRawPoint(y, x) : io.getRawPoint(x, y));
|
||||
|
||||
if (is_touched && calibration.orientation != TOUCH_ORIENTATION_NONE) {
|
||||
*x = int16_t((int32_t(*x) * calibration.x) >> 16) + calibration.offset_x;
|
||||
*y = int16_t((int32_t(*y) * calibration.y) >> 16) + calibration.offset_y;
|
||||
}
|
||||
if (is_touched && touch_calibration.calibration.orientation != TOUCH_ORIENTATION_NONE) {
|
||||
*x = int16_t((int32_t(*x) * touch_calibration.calibration.x) >> 16) + touch_calibration.calibration.offset_x;
|
||||
*y = int16_t((int32_t(*y) * touch_calibration.calibration.y) >> 16) + touch_calibration.calibration.offset_y;
|
||||
}
|
||||
#else
|
||||
bool is_touched = (TOUCH_ORIENTATION == TOUCH_PORTRAIT ? io.getRawPoint(y, x) : io.getRawPoint(x, y));
|
||||
*x = uint16_t((uint32_t(*x) * TOUCH_CALIBRATION_X) >> 16) + TOUCH_OFFSET_X;
|
||||
*y = uint16_t((uint32_t(*y) * TOUCH_CALIBRATION_Y) >> 16) + TOUCH_OFFSET_Y;
|
||||
#endif
|
||||
return is_touched;
|
||||
}
|
||||
Touch touch;
|
||||
|
@ -23,42 +23,16 @@
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(TOUCH_SCREEN)
|
||||
|
||||
#include "tft_color.h"
|
||||
#include "tft_image.h"
|
||||
|
||||
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
|
||||
#include "../tft_io/touch_calibration.h"
|
||||
#endif
|
||||
|
||||
#include HAL_PATH(../../HAL, tft/xpt2046.h)
|
||||
#define TOUCH_DRIVER XPT2046
|
||||
|
||||
#ifndef TOUCH_SCREEN_CALIBRATION_PRECISION
|
||||
#define TOUCH_SCREEN_CALIBRATION_PRECISION 80
|
||||
#endif
|
||||
|
||||
#ifndef TOUCH_SCREEN_HOLD_TO_CALIBRATE_MS
|
||||
#define TOUCH_SCREEN_HOLD_TO_CALIBRATE_MS 2500
|
||||
#endif
|
||||
|
||||
#define TOUCH_ORIENTATION_NONE 0
|
||||
#define TOUCH_LANDSCAPE 1
|
||||
#define TOUCH_PORTRAIT 2
|
||||
|
||||
#if !(defined(TOUCH_CALIBRATION_X) || defined(TOUCH_CALIBRATION_Y) || defined(TOUCH_OFFSET_X) || defined(TOUCH_OFFSET_Y) || defined(TOUCH_ORIENTATION))
|
||||
#if defined(XPT2046_X_CALIBRATION) && defined(XPT2046_Y_CALIBRATION) && defined(XPT2046_X_OFFSET) && defined(XPT2046_Y_OFFSET)
|
||||
#define TOUCH_CALIBRATION_X XPT2046_X_CALIBRATION
|
||||
#define TOUCH_CALIBRATION_Y XPT2046_Y_CALIBRATION
|
||||
#define TOUCH_OFFSET_X XPT2046_X_OFFSET
|
||||
#define TOUCH_OFFSET_Y XPT2046_Y_OFFSET
|
||||
#define TOUCH_ORIENTATION TOUCH_LANDSCAPE
|
||||
#else
|
||||
#define TOUCH_CALIBRATION_X 0
|
||||
#define TOUCH_CALIBRATION_Y 0
|
||||
#define TOUCH_OFFSET_X 0
|
||||
#define TOUCH_OFFSET_Y 0
|
||||
#define TOUCH_ORIENTATION TOUCH_ORIENTATION_NONE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Menu Navigation
|
||||
extern int8_t encoderTopLine, encoderLine, screen_items;
|
||||
|
||||
@ -101,31 +75,6 @@ typedef struct __attribute__((__packed__)) {
|
||||
intptr_t data;
|
||||
} touch_control_t;
|
||||
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int16_t offset_x;
|
||||
int16_t offset_y;
|
||||
uint8_t orientation;
|
||||
} touch_calibration_t;
|
||||
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
int16_t raw_x;
|
||||
int16_t raw_y;
|
||||
} touch_calibration_point_t;
|
||||
|
||||
enum calibrationState : uint8_t {
|
||||
CALIBRATION_POINT_1 = 0x00,
|
||||
CALIBRATION_POINT_2,
|
||||
CALIBRATION_POINT_3,
|
||||
CALIBRATION_POINT_4,
|
||||
CALIBRATION_SUCCESS,
|
||||
CALIBRATION_FAIL,
|
||||
CALIBRATION_NONE,
|
||||
};
|
||||
|
||||
#define MAX_CONTROLS 16
|
||||
#define MINIMUM_HOLD_TIME 15
|
||||
#define TOUCH_REPEAT_DELAY 75
|
||||
@ -150,15 +99,6 @@ class Touch {
|
||||
static void touch(touch_control_t *control);
|
||||
static void hold(touch_control_t *control, millis_t delay = 0);
|
||||
|
||||
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
|
||||
static calibrationState calibration_state;
|
||||
static touch_calibration_point_t calibration_points[4];
|
||||
|
||||
static bool validate_precision(int32_t a, int32_t b) { return (a > b ? (100 * b) / a : (100 * a) / b) > TOUCH_SCREEN_CALIBRATION_PRECISION; }
|
||||
static bool validate_precision_x(uint8_t a, uint8_t b) { return validate_precision(calibration_points[a].raw_x, calibration_points[b].raw_x); }
|
||||
static bool validate_precision_y(uint8_t a, uint8_t b) { return validate_precision(calibration_points[a].raw_y, calibration_points[b].raw_y); }
|
||||
#endif // TOUCH_SCREEN_CALIBRATION
|
||||
|
||||
public:
|
||||
static void init();
|
||||
static void reset() { controls_count = 0; touch_time = 0; current_control = NULL; }
|
||||
@ -175,17 +115,6 @@ class Touch {
|
||||
static void enable() { enabled = true; }
|
||||
|
||||
static void add_control(TouchControlType type, uint16_t x, uint16_t y, uint16_t width, uint16_t height, intptr_t data = 0);
|
||||
|
||||
static touch_calibration_t calibration;
|
||||
static void calibration_reset() { calibration = {TOUCH_CALIBRATION_X, TOUCH_CALIBRATION_Y, TOUCH_OFFSET_X, TOUCH_OFFSET_Y, TOUCH_ORIENTATION}; }
|
||||
|
||||
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
|
||||
static calibrationState calibration_start() { calibration = {0, 0, 0, 0, TOUCH_ORIENTATION_NONE}; return calibration_state = CALIBRATION_POINT_1; }
|
||||
static void calibration_end() { calibration_state = CALIBRATION_NONE; }
|
||||
static calibrationState get_calibration_state() { return calibration_state; }
|
||||
#endif // TOUCH_SCREEN_CALIBRATION
|
||||
};
|
||||
|
||||
extern Touch touch;
|
||||
|
||||
#endif // TOUCH_SCREEN
|
||||
|
@ -584,33 +584,37 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const
|
||||
#endif // AUTO_BED_LEVELING_UBL
|
||||
|
||||
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
|
||||
void MarlinUI::touch_calibration() {
|
||||
static uint16_t x, y;
|
||||
void MarlinUI::touch_calibration_screen() {
|
||||
uint16_t x, y;
|
||||
|
||||
calibrationState calibration_stage = touch.get_calibration_state();
|
||||
calibrationState calibration_stage = touch_calibration.get_calibration_state();
|
||||
|
||||
if (calibration_stage == CALIBRATION_NONE) {
|
||||
defer_status_screen(true);
|
||||
clear_lcd();
|
||||
calibration_stage = touch.calibration_start();
|
||||
calibration_stage = touch_calibration.calibration_start();
|
||||
}
|
||||
else {
|
||||
x = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].x;
|
||||
y = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].y;
|
||||
tft.canvas(x - 15, y - 15, 31, 31);
|
||||
tft.set_background(COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
x = 20; y = 20;
|
||||
touch.clear();
|
||||
|
||||
if (calibration_stage < CALIBRATION_SUCCESS) {
|
||||
switch (calibration_stage) {
|
||||
case CALIBRATION_POINT_1: tft_string.set("Top Left"); break;
|
||||
case CALIBRATION_POINT_2: y = TFT_HEIGHT - 21; tft_string.set("Bottom Left"); break;
|
||||
case CALIBRATION_POINT_3: x = TFT_WIDTH - 21; tft_string.set("Top Right"); break;
|
||||
case CALIBRATION_POINT_4: x = TFT_WIDTH - 21; y = TFT_HEIGHT - 21; tft_string.set("Bottom Right"); break;
|
||||
case CALIBRATION_TOP_LEFT: tft_string.set(GET_TEXT(MSG_TOP_LEFT)); break;
|
||||
case CALIBRATION_BOTTOM_LEFT: tft_string.set(GET_TEXT(MSG_BOTTOM_LEFT)); break;
|
||||
case CALIBRATION_TOP_RIGHT: tft_string.set(GET_TEXT(MSG_TOP_RIGHT)); break;
|
||||
case CALIBRATION_BOTTOM_RIGHT: tft_string.set(GET_TEXT(MSG_BOTTOM_RIGHT)); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
x = touch_calibration.calibration_points[calibration_stage].x;
|
||||
y = touch_calibration.calibration_points[calibration_stage].y;
|
||||
|
||||
tft.canvas(x - 15, y - 15, 31, 31);
|
||||
tft.set_background(COLOR_BACKGROUND);
|
||||
tft.add_bar(0, 15, 31, 1, COLOR_TOUCH_CALIBRATION);
|
||||
@ -619,9 +623,9 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const
|
||||
touch.add_control(CALIBRATE, 0, 0, TFT_WIDTH, TFT_HEIGHT, uint32_t(x) << 16 | uint32_t(y));
|
||||
}
|
||||
else {
|
||||
tft_string.set(calibration_stage == CALIBRATION_SUCCESS ? "Calibration Completed" : "Calibration Failed");
|
||||
tft_string.set(calibration_stage == CALIBRATION_SUCCESS ? GET_TEXT(MSG_CALIBRATION_COMPLETED) : GET_TEXT(MSG_CALIBRATION_FAILED));
|
||||
defer_status_screen(false);
|
||||
touch.calibration_end();
|
||||
touch_calibration.calibration_end();
|
||||
touch.add_control(BACK, 0, 0, TFT_WIDTH, TFT_HEIGHT);
|
||||
}
|
||||
|
||||
|
@ -589,33 +589,37 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const
|
||||
#endif // AUTO_BED_LEVELING_UBL
|
||||
|
||||
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
|
||||
void MarlinUI::touch_calibration() {
|
||||
static uint16_t x, y;
|
||||
void MarlinUI::touch_calibration_screen() {
|
||||
uint16_t x, y;
|
||||
|
||||
calibrationState calibration_stage = touch.get_calibration_state();
|
||||
calibrationState calibration_stage = touch_calibration.get_calibration_state();
|
||||
|
||||
if (calibration_stage == CALIBRATION_NONE) {
|
||||
defer_status_screen(true);
|
||||
clear_lcd();
|
||||
calibration_stage = touch.calibration_start();
|
||||
calibration_stage = touch_calibration.calibration_start();
|
||||
}
|
||||
else {
|
||||
x = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].x;
|
||||
y = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].y;
|
||||
tft.canvas(x - 15, y - 15, 31, 31);
|
||||
tft.set_background(COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
x = 20; y = 20;
|
||||
touch.clear();
|
||||
|
||||
if (calibration_stage < CALIBRATION_SUCCESS) {
|
||||
switch (calibration_stage) {
|
||||
case CALIBRATION_POINT_1: tft_string.set("Top Left"); break;
|
||||
case CALIBRATION_POINT_2: y = TFT_HEIGHT - 21; tft_string.set("Bottom Left"); break;
|
||||
case CALIBRATION_POINT_3: x = TFT_WIDTH - 21; tft_string.set("Top Right"); break;
|
||||
case CALIBRATION_POINT_4: x = TFT_WIDTH - 21; y = TFT_HEIGHT - 21; tft_string.set("Bottom Right"); break;
|
||||
case CALIBRATION_TOP_LEFT: tft_string.set(GET_TEXT(MSG_TOP_LEFT)); break;
|
||||
case CALIBRATION_BOTTOM_LEFT: tft_string.set(GET_TEXT(MSG_BOTTOM_LEFT)); break;
|
||||
case CALIBRATION_TOP_RIGHT: tft_string.set(GET_TEXT(MSG_TOP_RIGHT)); break;
|
||||
case CALIBRATION_BOTTOM_RIGHT: tft_string.set(GET_TEXT(MSG_BOTTOM_RIGHT)); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
x = touch_calibration.calibration_points[calibration_stage].x;
|
||||
y = touch_calibration.calibration_points[calibration_stage].y;
|
||||
|
||||
tft.canvas(x - 15, y - 15, 31, 31);
|
||||
tft.set_background(COLOR_BACKGROUND);
|
||||
tft.add_bar(0, 15, 31, 1, COLOR_TOUCH_CALIBRATION);
|
||||
@ -624,9 +628,9 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const
|
||||
touch.add_control(CALIBRATE, 0, 0, TFT_WIDTH, TFT_HEIGHT, uint32_t(x) << 16 | uint32_t(y));
|
||||
}
|
||||
else {
|
||||
tft_string.set(calibration_stage == CALIBRATION_SUCCESS ? "Calibration Completed" : "Calibration Failed");
|
||||
tft_string.set(calibration_stage == CALIBRATION_SUCCESS ? GET_TEXT(MSG_CALIBRATION_COMPLETED) : GET_TEXT(MSG_CALIBRATION_FAILED));
|
||||
defer_status_screen(false);
|
||||
touch.calibration_end();
|
||||
touch_calibration.calibration_end();
|
||||
touch.add_control(BACK, 0, 0, TFT_WIDTH, TFT_HEIGHT);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user