13#ifdef TOUCH_CALIBRATION_ENABLE
26const int CALIBRATION_ATTEMPTS = 3;
29const uint16_t TARGET_RADIUS = 5;
32const uint32_t HOLD_MS = 300;
35const uint32_t SETTLE_MS = 100;
38const uint32_t RELEASE_GAP_MS = 100;
75 const uint32_t pressStart = HAL_GetTick();
76 uint32_t lastReading = pressStart;
80 bool accepted =
false;
83 while ((HAL_GetTick() - lastReading) < RELEASE_GAP_MS) {
86 const uint32_t now = HAL_GetTick();
88 if ((rx != 0 || ry != 0) && (now - pressStart) >= SETTLE_MS) {
93 if (!accepted && (now - pressStart) >= HOLD_MS) {
95 display->
drawCircle(x, y, radius + 4, ACCEPTED_COLOUR);
96 display->
drawCircle(x, y, radius + 5, ACCEPTED_COLOUR);
103 if (accepted && count > 0) {
104 point->
x = (int32_t) (sumX / count);
105 point->
y = (int32_t) (sumY / count);
113const uint8_t KEY_ESC = 0x1B;
130bool waitForSpaceOrEsc(UART_HandleTypeDef *uart) {
134 HAL_UART_AbortReceive(uart);
135 __HAL_UART_FLUSH_DRREGISTER(uart);
137 printf(
" Press the space bar to show the next target, or Esc to redo this one\r\n");
139 const HAL_StatusTypeDef status = HAL_UART_Receive_IT(uart, (uint8_t *) &
uartRxChar, 1);
140 if (status != HAL_OK) {
141 printf(
"Could not start receiving from the UART (HAL status %d)\r\n", (
int) status);
163 display->
drawCircle(x, y, radius + 2, 0x8410);
166 capturePress(display, x, y, radius, &point);
173 if (display ==
nullptr || screen ==
nullptr || matrix ==
nullptr) {
177 matrix->
Divider = ((screen[0].
x - screen[2].
x) * (screen[1].y - screen[2].y)) -
178 ((screen[1].x - screen[2].x) * (screen[0].
y - screen[2].
y));
184 matrix->
An = ((display[0].
x - display[2].
x) * (screen[1].y - screen[2].y)) -
185 ((display[1].x - display[2].x) * (screen[0].
y - screen[2].
y));
187 matrix->
Bn = ((screen[0].
x - screen[2].
x) * (display[1].x - display[2].x)) -
188 ((display[0].x - display[2].x) * (screen[1].
x - screen[2].
x));
190 matrix->
Cn = (screen[2].
x * display[1].
x - screen[1].
x * display[2].
x) * screen[0].y +
191 (screen[0].x * display[2].x - screen[2].x * display[0].x) * screen[1].
y +
192 (screen[1].
x * display[0].
x - screen[0].
x * display[1].
x) * screen[2].y;
194 matrix->
Dn = ((display[0].
y - display[2].
y) * (screen[1].y - screen[2].y)) -
195 ((display[1].y - display[2].y) * (screen[0].
y - screen[2].
y));
197 matrix->
En = ((screen[0].
x - screen[2].
x) * (display[1].y - display[2].y)) -
198 ((display[0].y - display[2].y) * (screen[1].
x - screen[2].
x));
200 matrix->
Fn = (screen[2].
x * display[1].
y - screen[1].
x * display[2].
y) * screen[0].y +
201 (screen[0].x * display[2].y - screen[2].x * display[0].y) * screen[1].
y +
202 (screen[1].
x * display[0].
y - screen[0].
x * display[1].
y) * screen[2].y;
208 if (matrix ==
nullptr || raw ==
nullptr || display ==
nullptr || matrix->
Divider == 0) {
212 display->
x = ((matrix->
An * raw->
x) + (matrix->
Bn * raw->
y) + matrix->
Cn) / matrix->
Divider;
213 display->
y = ((matrix->
Dn * raw->
x) + (matrix->
En * raw->
y) + matrix->
Fn) / matrix->
Divider;
218 if (display ==
nullptr || uart ==
nullptr || matrix ==
nullptr) {
222 const int32_t w = display->
width();
223 const int32_t h = display->
height();
226 tsPoint_t displayPoints[3] = { { w / 10, h / 10 }, { w / 2, h - h / 10 }, { w - w / 10, h / 2 } };
229 for (
int attempt = 1; attempt <= CALIBRATION_ATTEMPTS; attempt++) {
230 printf(
"Touch calibration, attempt %d of %d\r\n", attempt, CALIBRATION_ATTEMPTS);
232 for (
int i = 0; i < 3; i++) {
233 touchPoints[i] = renderCalibrationScreen(display, (uint16_t) displayPoints[i].x,
234 (uint16_t) displayPoints[i].y, TARGET_RADIUS);
235 printf(
" point %d: display %ld,%ld raw %ld,%ld\r\n", i + 1, (
long) displayPoints[i].x,
236 (
long) displayPoints[i].y, (
long) touchPoints[i].x, (
long) touchPoints[i].y);
237 if (i < 2 && !waitForSpaceOrEsc(uart)) {
239 printf(
" point %d discarded, touch it again\r\n", i + 1);
249 printf(
" the three touches lie on one line, calibration is not usable\r\n");
#define RA8875_GREEN
Green Color.
#define RA8875_WHITE
White Color.
#define RA8875_RED
Red Color.
Class that stores state and functions for interacting with the RA8875 display controller.
boolean touchRead(uint16_t *x, uint16_t *y)
void fillScreen(uint16_t color)
void drawCircle(int16_t x, int16_t y, int16_t r, uint16_t color)
: Header for main.c file. This file contains the common defines of the application.
volatile uint8_t uartRxChar
The one character the interrupt receive waits for (see main.c).
bool touchCalibrationRun(Adafruit_RA8875 *display, UART_HandleTypeDef *uart, tsMatrix_t *matrix)
Runs the interactive calibration: draws three targets one at a time, waits for the user to touch each...
volatile uint8_t uartKeyPressed
Set by HAL_UART_RxCpltCallback() in main.c: 0 = none yet, otherwise ' ' or 0x1B (Esc).
bool touchCalibrationApply(const tsMatrix_t *matrix, const tsPoint_t *raw, tsPoint_t *display)
Converts one raw touch reading into a display pixel position.
bool touchCalibrationCompute(const tsPoint_t *display, const tsPoint_t *screen, tsMatrix_t *matrix)
Calculates the calibration matrix from three known display points and the raw touch readings taken at...
Three-point touch-screen calibration for the RA8875's resistive panel.