Files
MCUFRIEND_kbv/examples/TouchScreen_Calibr_new/TouchScreen_Calibr_new.ino
2017-05-24 15:57:56 +01:00

439 lines
13 KiB
C++

// https://forum.arduino.cc/index.php?topic=473885.msg3245748#msg3245748
// file attached 03 May 2017 21:15 BST
// TouchScreen_Calibr_kbv for MCUFRIEND UNO Display Shields
// adapted by David Prentice
// for Adafruit's <TouchScreen.h> Resistive Touch Screen Library
// from Henning Karlsen's original program. Many Thanks.
// UTouch_Calibration (C)2013-2014 Henning Karlsen
// web: http://www.henningkarlsen.com/electronics
//
// This program can be used to calibrate the touchscreen
// of the display modules.
//
// It is assumed that the display module is connected to an
// appropriate shield or that you know how to change the pin
// numbers in the setup.
//
// Instructions will be given on the display.
//#define TOUCH_ORIENTATION LANDSCAPE
#define TOUCH_ORIENTATION PORTRAIT
#define TITLE "TouchScreen.h Calibration"
#include <Adafruit_GFX.h>
#include <UTFTGLUE.h> //we are using UTFT display methods
UTFTGLUE myGLCD(0x9341, A2, A1, A3, A4, A0);
#include <TouchScreen.h> //Adafruit Library
// MCUFRIEND UNO shield shares pins with the TFT. Due does NOT work
int YP = A1, YM = 7, XM = A2, XP = 7; //most comon configuration
TouchScreen myTouch(XP, YP, XM, YM, 300);
TSPoint tp; //Touchscreen_due branch uses Point
void readResistiveTouch(void)
{
tp = myTouch.getPoint();
pinMode(YP, OUTPUT); //restore shared pins
pinMode(XM, OUTPUT);
digitalWrite(YP, HIGH); //because TFT control pins
digitalWrite(XM, HIGH);
}
bool ISPRESSED(void)
{
// .kbv this was too sensitive !!
// now touch has to be stable for 50ms
int count = 0;
bool state, oldstate;
while (count < 10) {
readResistiveTouch();
state = tp.z > 20 && tp.z < 1000;
if (state == oldstate) count++;
else count = 0;
oldstate = state;
delay(5);
}
return oldstate;
}
void showpoint(void)
{
Serial.print("\r\nx="); Serial.print(tp.x);
Serial.print(" y="); Serial.print(tp.y);
Serial.print(" z="); Serial.print(tp.z);
}
// ************************************
// DO NOT EDIT ANYTHING BELOW THIS LINE
// ************************************
// Declare which fonts we will be using
#if defined(SmallFont) //.kbv new GLUE defines FreeSmallFont
#undef SmallFont //.kbv lose it
#define SmallFont NULL //.kbv use System Font
#else
extern uint8_t SmallFont[]; //.kbv
#endif
uint32_t cx, cy;
uint32_t rx[8], ry[8];
int32_t clx, crx, cty, cby;
float px, py;
int dispx, dispy, text_y_center, swapxy;
uint32_t calx, caly, cals;
char buf[13];
void showpins(int A, int D, int value, const char *msg)
{
char buf[40];
sprintf(buf, "%s (A%d, D%d) = %d", msg, A - A0, D, value);
Serial.println(buf);
}
boolean diagnose_pins()
{
int i, j, value, Apins[2], Dpins[2], Values[2], found = 0;
// Serial.begin(9600);
Serial.println("Making all control and bus pins INPUT_PULLUP");
Serial.println("Typical 30k Analog pullup with corresponding pin");
Serial.println("would read low when digital is written LOW");
Serial.println("e.g. reads ~25 for 300R X direction");
Serial.println("e.g. reads ~30 for 500R Y direction");
Serial.println("");
for (i = A0; i < A5; i++) pinMode(i, INPUT_PULLUP);
for (i = 2; i < 10; i++) pinMode(i, INPUT_PULLUP);
for (i = A0; i < A4; i++) {
for (j = 5; j < 10; j++) {
pinMode(j, OUTPUT);
digitalWrite(j, LOW);
value = analogRead(i); // ignore first reading
value = analogRead(i);
if (value < 100) {
showpins(i, j, value, "Testing :");
if (found < 2) {
Apins[found] = i;
Dpins[found] = j;
Values[found] = value;
found++;
}
}
pinMode(j, INPUT_PULLUP);
}
}
if (found == 2) {
Serial.println("Diagnosing as:-");
int idx = Values[0] < Values[1];
for (i = 0; i < 2; i++) {
showpins(Apins[i], Dpins[i], Values[i],
(Values[i] < Values[!i]) ? "XM,XP: " : "YP,YM: ");
}
XM = Apins[!idx]; XP = Dpins[!idx]; YP = Apins[idx]; YM = Dpins[idx];
myTouch = TouchScreen(XP, YP, XM, YM, 300);
return true;
}
Serial.println("BROKEN TOUCHSCREEN");
return false;
}
void setup()
{
Serial.begin(9600);
Serial.println(TITLE);
bool ret = diagnose_pins();
digitalWrite(A0, HIGH);
pinMode(A0, OUTPUT);
myGLCD.InitLCD(TOUCH_ORIENTATION);
myGLCD.clrScr();
myGLCD.setFont(SmallFont);
dispx = myGLCD.getDisplayXSize();
dispy = myGLCD.getDisplayYSize();
text_y_center = (dispy / 2) - 6;
if (ret == false) {
myGLCD.print("BROKEN TOUCHSCREEN", CENTER, dispy / 2);
while (1);
}
}
void drawCrossHair(int x, int y)
{
myGLCD.drawRect(x - 10, y - 10, x + 10, y + 10);
myGLCD.drawLine(x - 5, y, x + 5, y);
myGLCD.drawLine(x, y - 5, x, y + 5);
}
void readCoordinates()
{
int iter = 5000;
int failcount = 0;
int cnt = 0;
uint32_t tx = 0;
uint32_t ty = 0;
boolean OK = false;
while (OK == false)
{
myGLCD.setColor(255, 255, 255);
myGLCD.print("* PRESS *", CENTER, text_y_center);
while (ISPRESSED() == false) {}
myGLCD.print("* HOLD! *", CENTER, text_y_center);
cnt = 0;
iter = 400;
do
{
readResistiveTouch();
// showpoint(tp);
if (tp.z > 20 && tp.z < 1000)
{
tx += tp.x;
ty += tp.y;
cnt++;
}
else
failcount++;
} while ((cnt < iter) && (failcount < 10000));
if (cnt >= iter)
{
OK = true;
}
else
{
tx = 0;
ty = 0;
cnt = 0;
}
if (failcount >= 10000)
fail();
}
cx = tx / iter;
cy = ty / iter;
}
void calibrate(int x, int y, int i)
{
myGLCD.setColor(255, 255, 255);
drawCrossHair(x, y);
myGLCD.setBackColor(255, 0, 0);
readCoordinates();
myGLCD.setColor(255, 255, 255);
myGLCD.print("* RELEASE *", CENTER, text_y_center);
myGLCD.setColor(80, 80, 80);
drawCrossHair(x, y);
rx[i] = cx;
ry[i] = cy;
Serial.print("\r\ncx="); Serial.print(cx);
Serial.print(" cy="); Serial.print(cy);
while (ISPRESSED() == true) {}
}
void waitForTouch()
{
while (ISPRESSED() == true) {}
while (ISPRESSED() == false) {}
while (ISPRESSED() == true) {}
}
void toHex(uint32_t num)
{
buf[0] = '0';
buf[1] = 'x';
buf[10] = 'U';
buf[11] = 'L';
buf[12] = 0;
for (int zz = 9; zz > 1; zz--)
{
if ((num & 0xF) > 9)
buf[zz] = (num & 0xF) + 55;
else
buf[zz] = (num & 0xF) + 48;
num = num >> 4;
}
}
void startup()
{
myGLCD.setColor(255, 0, 0);
myGLCD.fillRect(0, 0, dispx - 1, 13);
myGLCD.setColor(255, 255, 255);
myGLCD.setBackColor(255, 0, 0);
myGLCD.drawLine(0, 14, dispx - 1, 14);
myGLCD.print(TITLE, CENTER, 1);
myGLCD.setBackColor(0, 0, 0);
myGLCD.print("#define NUMSAMPLES 3 in Library", LEFT, 18);
myGLCD.print("Use a stylus or something", LEFT, 30);
myGLCD.print("similar to touch as close", LEFT, 42);
myGLCD.print("to the center of the", LEFT, 54);
myGLCD.print("highlighted crosshair as", LEFT, 66);
myGLCD.print("possible. Keep as still as", LEFT, 78);
myGLCD.print("possible and keep holding", LEFT, 90);
myGLCD.print("until the highlight is", LEFT, 102);
myGLCD.print("removed. Repeat for all", LEFT, 114);
myGLCD.print("crosshairs in sequence.", LEFT, 126);
myGLCD.print("Touch screen to continue", CENTER, 162);
waitForTouch();
myGLCD.clrScr();
}
void showNumI(char *msg, uint32_t val, int x, int y)
{
myGLCD.print(msg, x, y);
myGLCD.printNumI(val, x + 50, y);
}
void done()
{
uint16_t TS_LEFT, TS_RT, TS_TOP, TS_BOT, TS_WID, TS_HT, TS_SWAP;
int16_t tmp;
char buf[60];
myGLCD.clrScr();
myGLCD.setColor(255, 0, 0);
myGLCD.fillRect(0, 0, dispx - 1, 13);
myGLCD.setColor(255, 255, 255);
myGLCD.setBackColor(255, 0, 0);
myGLCD.drawLine(0, 14, dispx - 1, 14);
myGLCD.print(TITLE, CENTER, 1);
myGLCD.setBackColor(0, 0, 0);
myGLCD.print("To use the new calibration", LEFT, 30);
myGLCD.print("settings you must map the values", LEFT, 42);
myGLCD.print("from Point p = ts.getPoint() e.g. ", LEFT, 54);
myGLCD.print("x = map(p.x, LEFT, RT, 0, tft.width());", LEFT, 66);
myGLCD.print("y = map(p.y, TOP, BOT, 0, tft.height());", LEFT, 78);
myGLCD.print("swap p.x and p.y if diff ORIENTATION", LEFT, 90);
//.kbv show human values
TS_LEFT = (calx >> 14) & 0x3FFF;
TS_RT = (calx >> 0) & 0x3FFF;
TS_TOP = (caly >> 14) & 0x3FFF;
TS_BOT = (caly >> 0) & 0x3FFF;
TS_WID = ((cals >> 12) & 0x0FFF) + 1;
TS_HT = ((cals >> 0) & 0x0FFF) + 1;
TS_SWAP = (cals >> 31);
int y = 120;
Serial.println("");
sprintf(buf, "Sketch is %s %d x %d",
TOUCH_ORIENTATION ? "LANDSCAPE" : "PORTRAIT", TS_WID, TS_HT);
myGLCD.print(buf, 0, y);
Serial.println(buf);
if (TOUCH_ORIENTATION == LANDSCAPE) { //always show PORTRAIT first
tmp = TS_LEFT, TS_LEFT = TS_BOT, TS_BOT = TS_RT, TS_RT = TS_TOP, TS_TOP = tmp;
tmp = TS_WID, TS_WID = TS_HT, TS_HT = tmp;
}
sprintf(buf, "PORTRAIT CALIBRATION %d x %d", TS_WID, TS_HT);
myGLCD.print(buf, 0, y += 24);
Serial.println(buf);
sprintf(buf, "x = map(p.x, LEFT=%d, RT=%d, 0, %d)", TS_LEFT, TS_RT, TS_WID);
myGLCD.print(buf, 0, y += 12);
Serial.println(buf);
sprintf(buf, "y = map(p.y, TOP=%d, BOT=%d, 0, %d)", TS_TOP, TS_BOT, TS_HT);
myGLCD.print(buf, 0, y += 12);
Serial.println(buf);
sprintf(buf, "Touch Pin Wiring XP=%d XM=A%d YP=A%d YM=%d",
XP, XM - A0, YP - A0, YM);
myGLCD.print(buf, 0, y += 24);
Serial.println(buf);
tmp = TS_LEFT, TS_LEFT = TS_TOP, TS_TOP = TS_RT, TS_RT = TS_BOT, TS_BOT = tmp;
tmp = TS_WID, TS_WID = TS_HT, TS_HT = tmp;
sprintf(buf, "LANDSCAPE CALIBRATION %d x %d", TS_WID, TS_HT);
myGLCD.print(buf, 0, y += 24);
Serial.println(buf);
sprintf(buf, "x = map(p.y, LEFT=%d, RT=%d, 0, %d)", TS_LEFT, TS_RT, TS_WID);
myGLCD.print(buf, 0, y += 12);
Serial.println(buf);
sprintf(buf, "y = map(p.x, TOP=%d, BOT=%d, 0, %d)", TS_TOP, TS_BOT, TS_HT);
myGLCD.print(buf, 0, y += 12);
Serial.println(buf);
}
void fail()
{
myGLCD.clrScr();
myGLCD.setColor(255, 0, 0);
myGLCD.fillRect(0, 0, dispx - 1, 13);
myGLCD.setColor(255, 255, 255);
myGLCD.setBackColor(255, 0, 0);
myGLCD.drawLine(0, 14, dispx - 1, 14);
myGLCD.print("Touch Calibration FAILED", CENTER, 1);
myGLCD.setBackColor(0, 0, 0);
myGLCD.print("Unable to read the position", LEFT, 30);
myGLCD.print("of the press. This is a", LEFT, 42);
myGLCD.print("hardware issue and can", LEFT, 54);
myGLCD.print("not be corrected in", LEFT, 66);
myGLCD.print("software.", LEFT, 78);
myGLCD.print("check XP, XM pins with a multimeter", LEFT, 102);
myGLCD.print("check YP, YM pins with a multimeter", LEFT, 114);
myGLCD.print("should be about 300 ohms", LEFT, 126);
while (true) {};
}
void loop()
{
startup();
myGLCD.setColor(80, 80, 80);
drawCrossHair(dispx - 11, 10);
drawCrossHair(dispx / 2, 10);
drawCrossHair(10, 10);
drawCrossHair(dispx - 11, dispy / 2);
drawCrossHair(10, dispy / 2);
drawCrossHair(dispx - 11, dispy - 11);
drawCrossHair(dispx / 2, dispy - 11);
drawCrossHair(10, dispy - 11);
myGLCD.setColor(255, 255, 255);
myGLCD.setBackColor(255, 0, 0);
myGLCD.print("***********", CENTER, text_y_center - 12);
myGLCD.print("***********", CENTER, text_y_center + 12);
calibrate(10, 10, 0);
calibrate(10, dispy / 2, 1);
calibrate(10, dispy - 11, 2);
calibrate(dispx / 2, 10, 3);
calibrate(dispx / 2, dispy - 11, 4);
calibrate(dispx - 11, 10, 5);
calibrate(dispx - 11, dispy / 2, 6);
calibrate(dispx - 11, dispy - 11, 7);
cals = (long(dispx - 1) << 12) + (dispy - 1);
if (TOUCH_ORIENTATION == PORTRAIT) swapxy = rx[2] - rx[0];
else swapxy = ry[2] - ry[0];
swapxy = (swapxy < -500 || swapxy > 500);
if ((TOUCH_ORIENTATION == PORTRAIT) ^ (swapxy != 0)) {
clx = (rx[0] + rx[1] + rx[2]) / 3;
crx = (rx[5] + rx[6] + rx[7]) / 3;
cty = (ry[0] + ry[3] + ry[5]) / 3;
cby = (ry[2] + ry[4] + ry[7]) / 3;
} else {
clx = (ry[0] + ry[1] + ry[2]) / 3;
crx = (ry[5] + ry[6] + ry[7]) / 3;
cty = (rx[0] + rx[3] + rx[5]) / 3;
cby = (rx[2] + rx[4] + rx[7]) / 3;
}
px = float(crx - clx) / (dispx - 20);
py = float(cby - cty) / (dispy - 20);
// px = 0;
clx -= px * 10;
crx += px * 10;
cty -= py * 10;
cby += py * 10;
calx = (long(clx) << 14) + long(crx);
caly = (long(cty) << 14) + long(cby);
if (swapxy)
cals |= (1L << 31);
done();
while (true) {}
}