Touch, you say?
I might have made just a few modifications to this sketch. I believe I got the original out of the Kuman_TFTLCD library.
I know I had to do some wholesale changes in the XPT2046_Touchscreen library to get it work with a SPI connected ILI9488 on the R4, but I don't believe I made any changes to the TouchScreen library used here. I can't guarantee that I didn't; I'm rather shameless about altering libraries on the fly.
Anyhow, give this sketch a try and see how it does for you.
(Oh, and it should work with all rotations.)
///////////////
// Sketch: Calibrate - Calibrate TFT ILI9341 Touch
// Author: Joao Lopes F. - joaolopesf@gmail.com
//
// Versions:
// - 0.9.0 First beta - July 2015
// - 0.9.1 Rotation for Mega
// - ?.?.? Mod'd to work on the R4
// Comments:
// Show the calibration parameters to put in your code
// Please use a small like the eraser on a pencil for best results
//
// Code for buttons, based on Adafruit arduin_o_phone example
///////////////
// library ILI9341
#include <Adafruit_GFX.h> // Core graphics library
#include <MCUFRIEND_kbv.h>
#include <TouchScreen.h> // Touch library
// Calibrates value
#define SENSIBILITY 300
#define MINPRESSURE 10
#define MAXPRESSURE 1000
//These are the pins for the shield!
#define YP A3 // must be an analog pin, use "An" notation!
#define XM A2 // must be an analog pin, use "An" notation!
#define YM 9 // can be a digital pin
#define XP 8 // can be a digital pin
const static short TS_MINX = 150;
const static short TS_MINY = 120;
const static short TS_MAXX = 920;
const static short TS_MAXY = 940;
const static short crosshairLng = 4;
bool portrait;
// Init TouchScreen:
TouchScreen ts = TouchScreen(XP, YP, XM, YM, SENSIBILITY);
// LCD Pin
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4 // Optional : otherwise connect to Arduino's reset pin
// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
// Init LCD
MCUFRIEND_kbv tft;
// Dimensions
uint16_t width = 0;
uint16_t height = 0;
// Buttons
#define BUTTONS 3
#define BUTTON_CLEAR 0
#define BUTTON_SHOW 1
#define BUTTON_RESET 2
Adafruit_GFX_Button buttons[BUTTONS];
uint16_t buttons_y = 0;
uint16_t tsLeft, tsRight, tsTop, tsBottom;
uint16_t pxLeft, pxRight, pxTop, pxBottom;
//-- Setup
void setup(void) {
char buf[20];
// Serial for for debug, not works if shield is plugged in arduino
Serial.begin(115200);
// Initialize the controller
uint16_t identifier = tft.readID();
if( identifier == 0x0D3D3 ) {
identifier = 0x9481;
}
switch( identifier ) {
case 0x9341:
Serial.println(F("Found ILI9341 LCD driver"));
tft.begin(identifier);
break;
case 0x9325:
Serial.println(F("Found ILI9325 LCD driver"));
tft.begin(identifier);
break;
case 0x9328:
Serial.println(F("Found ILI9328 LCD driver"));
tft.begin(identifier);
break;
case 0x4535:
Serial.println(F("Found LGDP4535 LCD driver"));
tft.begin(identifier);
break;
case 0x7575:
Serial.println(F("Found HX8347G LCD driver"));
tft.begin(identifier);
break;
case 0x8357:
Serial.println(F("Found HX8357D LCD driver"));
tft.begin(identifier);
break;
default:
Serial.printf(F("Unknown LCD driver chip: %04X\n"), identifier);
tft.begin(0x9341);
break;
}
tft.setRotation(0); // Need for the Mega, please changed for your choice or rotation initial
portrait = tft.getRotation() % 2 == 0;
width = tft.width() - 1;
height = tft.height() - 1;
// Debug
Serial.printf(F("TFT LCD calibration setup\n"));
Serial.printf("TFT size is %ux%u\n", tft.width(), tft.height());
initializeButtons();
drawBorder();
// Initial screen
tft.setCursor(65, 50);
tft.setTextSize(3);
tft.setTextColor(RED);
int16_t y = 10 * height / 64;
switch( identifier ) {
case 0x9341:
tft.drawCentredText(y, "ILI9341");
break;
case 0x9325:
tft.drawCentredText(y, "ILI9325");
break;
case 0x9328:
tft.drawCentredText(y, "ILI9328");
break;
case 0x4535:
tft.drawCentredText(y, "LGDP4535");
break;
case 0x7575:
tft.drawCentredText(y, "HX8347G");
break;
case 0x8357:
tft.drawCentredText(y, "HX8357D");
break;
default:
snprintf(buf, sizeof buf, "? %04X", identifier);
tft.drawCentredText(y, buf);
break;
}
tft.drawCentredText(10 * height / 38, "Library");
tft.setTextSize(2);
tft.setTextColor(BLACK);
tft.drawCentredText( 10 * height / 21, "Calibration");
tft.setTextSize(1);
tft.setTextColor(BLACK);
tft.drawCentredText( 10 * height / 13, "Touch to proceed");
waitOneTouch(); // Wait touch
calibrate_TS(); // Calibrate it
waitOneTouch(); // Wait touch
showCalibration(); // Calibration
}
// -- Loop
void loop()
{
int16_t x,y;
// Test of calibration
TSPoint p;
p = waitOneTouch();
// Map of values
x = mapXValue(p);
y = mapYValue(p);
if( y >= 10 ) {
tft.fillCircle(x, y, 1, BLUE); // Draw a point
}
showTouched(p); // Show touch screen point (TSPOINT)
// Go thru all the buttons, checking if they were pressed
for( uint8_t b=0; b<BUTTONS; ++b ) {
if( buttons[b].contains(x, y) ) {
switch( b ) {
case BUTTON_CLEAR:
showCalibration(); // Clear
break;
case BUTTON_SHOW:
showResults();
tft.printf(F("\nTouch to proceed"));
waitOneTouch();
showCalibration();
break;
case BUTTON_RESET:
// New calibration
calibrate_TS();
waitOneTouch();
showCalibration();
break;
}
}
}
}
// Calibration of Touch Screen (resistive)
void calibrate_TS(void) {
// Based in code posted in https://forum.arduino.cc/index.php?topic=223769.15
TSPoint p1, p2;
pxLeft = 0;
pxTop = 0;
pxRight = width;
pxBottom = height;
switch( tft.getRotation() ) {
case 0:
tsLeft = TS_MAXX;
tsTop = TS_MINY;
tsRight = TS_MINX;
tsBottom = TS_MAXY;
break;
case 1:
tsLeft = TS_MINY;
tsTop = TS_MINX;
tsRight = TS_MAXY;
tsBottom = TS_MAXX;
break;
case 2:
tsLeft = TS_MINX;
tsTop = TS_MAXY;
tsRight = TS_MAXX;
tsBottom = TS_MINY;
break;
case 3:
tsLeft = TS_MAXY;
tsTop = TS_MAXX;
tsRight = TS_MINY;
tsBottom = TS_MINX;
break;
}
tft.fillScreen(BLACK);
tft.drawLine(0,crosshairLng,crosshairLng*2,crosshairLng,WHITE); //show the first point
tft.drawLine(crosshairLng,0,crosshairLng,crosshairLng*2,WHITE);
tft.setCursor(5, 30);
tft.setTextColor(WHITE);
tft.setTextSize(1);
tft.print(F("Touch the crosshair centre"));
const uint16_t limit = 40;
do {
p1 = waitOneTouch();
} while (!(mapXValue(p1) < limit && mapYValue(p1) < limit));
tft.fillScreen(BLACK);
tft.drawLine(width-crosshairLng*2,height-crosshairLng,width,height-crosshairLng,WHITE);//show the 2nd point
tft.drawLine(width-crosshairLng,height-crosshairLng*2,width-crosshairLng,height,WHITE);
tft.setCursor(width - 26 * 6 - 5, height - 30 - 8);
tft.print(F("Touch the crosshair centre"));
delay(500); // debounce
do {
p2 = waitOneTouch();
} while (!(mapXValue(p2) > (width - limit) && mapYValue(p2) > (height - limit)));
tft.fillScreen(BLACK);
delay(300);
Serial.printf(F("\nRaw points: \n"));
Serial.printf(F("Pt 1: %u : %u\n"), p1.x, p1.y);
Serial.printf(F("Pt 2: %u : %u\n"), p2.x, p2.y);
if( portrait ) {
tsLeft = p1.x;
tsTop = p1.y;
tsRight = p2.x;
tsBottom = p2.y;
} else {
tsLeft = p1.y;
tsTop = p1.x;
tsRight = p2.y;
tsBottom = p2.x;
}
pxLeft = crosshairLng;
pxTop = crosshairLng;
pxRight = width - crosshairLng;
pxBottom = height - crosshairLng;
// Show results
showResults();
tft.printf(F("\nLast touched points: \n"));
tft.printf(F("Pt 1: %d : %d\n"), mapXValue(p1), mapYValue(p1));
tft.printf(F("Pt 2: %d : %d\n"), mapXValue(p2), mapYValue(p2));
// Wait a touch
tft.printf(F("\nTouch to proceed"));
waitOneTouch();
}
// wait 1 touch to return the point
TSPoint waitOneTouch() {
TSPoint p;
do {
p= ts.getPoint();
pinMode(XM, OUTPUT); //Pins configures again for TFT control
pinMode(YP, OUTPUT);
} while( p.z < MINPRESSURE || p.z > MAXPRESSURE );
return p;
}
// Draw a border
void drawBorder () {
uint8_t border = 10;
tft.fillScreen(RED);
tft.fillRect(border, border, (width - border * 2), (height - border * 2), WHITE);
}
// Show a screen of calibration
void showCalibration() {
// Clear
tft.fillScreen(BLACK);
tft.setTextSize (1);
// Header
tft.fillRect(0, 0, width, 10, RED);
tft.setTextColor(WHITE);
tft.drawCentredText(0, "*** Test of calibration ***");
// Footer
TSPoint p; // Only for show initial values
p.x=0;
p.y=0;
p.z=0;
showTouched(p);
// Buttons
for( uint8_t i=0; i<3; ++i ) {
buttons[i].drawButton();
}
}
// Show the coordinates
void showTouched(TSPoint p) {
uint8_t w = 40; // Width
uint8_t h = 10; // Heigth
uint8_t x = (width - (w*2)); // X
uint8_t y = 11; // Y
tft.fillRect(x, y, w*2, h, WHITE); // For cleanup
tft.drawRect(x, y, w, h, RED); // For X
tft.drawRect(x+w+2, y, w*2, h, RED); // For Y
tft.setTextColor(BLACK);
tft.setCursor(x+2, y + 1);
tft.printf(F("X: %03u"), p.x);
tft.setCursor(x+2+w+2, y + 1);
tft.printf(F("Y: %03u"), p.y);
}
// Show results of calibration
void showResults() {
tft.fillScreen(BLACK);
// Header
tft.fillRect(0, 0, width, 10, RED);
tft.setCursor (40, 0);
tft.setTextColor(WHITE);
tft.print(F("*** Results of calibration ***"));
// Results
tft.setCursor(5, 30);
tft.setTextSize(2);
tft.println(F("After calibration: "));
tft.printf(F("tsLeft = %d\n"), tsLeft);
tft.printf(F("tsTop = %d\n\n"), tsTop);
tft.printf(F("tsRight = %d\n"), tsRight);
tft.printf(F("tsBottom= %d\n"), tsBottom);
}
// Initialize buttons
void initializeButtons() {
uint16_t w = 75;
uint16_t h = 20;
uint16_t x;
uint16_t y;
uint8_t spacing_x = 5;
uint8_t textSize = 1;
static char buttonlabels[BUTTONS][9] = {
"Clear", "Show", "Recalib."
};
static uint16_t buttoncolors[BUTTONS] = {
RED, BLUE, RED
};
x = (width + 1) / 2 - spacing_x - w;
y = height + 1 - h / 2;
for( uint8_t b=0; b<BUTTONS; ++b ) {
buttons[b].initButton(
&tft, // TFT object
x+b*(w+spacing_x), y, // x, y,
w, h, WHITE, buttoncolors[b], WHITE,// w, h, outline, fill,
buttonlabels[b], textSize); // text
}
// Save the y position to avoid draws
buttons_y = y;
}
// Map the coordinate X
uint16_t mapXValue(TSPoint p) {
if( portrait ) {
return map(p.x, tsLeft, tsRight, pxLeft, pxRight );
}
return map(p.y, tsLeft, tsRight, pxLeft, pxRight );
}
// Map the coordinate Y
uint16_t mapYValue(TSPoint p) {
if( portrait ) {
return map(p.y, tsTop, tsBottom, pxTop, pxBottom );
}
return map(p.x, tsTop, tsBottom, pxTop, pxBottom );
}
