add Calibration sketch with native GFX, local TouchScreen_kbv

This commit is contained in:
prenticedavid
2017-09-16 11:05:04 +01:00
parent d65fd674c4
commit e89afeb7f8
3 changed files with 605 additions and 0 deletions

View File

@@ -0,0 +1,385 @@
// TouchScreen_Calibr_native for MCUFRIEND UNO Display Shields
// adapted by David Prentice
// for Adafruit's <TouchScreen.h> Resistive Touch Screen Library
// from Henning Karlsen's original UTouch_Calibration program.
// Many Thanks.
#define PORTRAIT 0
#define LANDSCAPE 1
#define TOUCH_ORIENTATION PORTRAIT
#define TITLE "TouchScreen.h GFX Calibration"
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
// MCUFRIEND UNO shield shares pins with the TFT.
int XP = 6, YP = A1, XM = A2, YM = 7; //most common configuration
//int XP = 7, YP = A2, XM = A1, YM = 6; //most common configuration
#include <TouchScreen.h> //Adafruit Library
TouchScreen ts(XP, YP, XM, YM, 300); //re-initialised after diagnose
//#include "TouchScreen_kbv.h" //my hacked version
//TouchScreen_kbv ts(XP, YP, XM, YM, 300); //re-initialised after diagnose
TSPoint tp; //global point
#define WHITE 0xFFFF
#define RED 0xF800
#define GRAY 0x8410
#define BLACK 0x0000
void readResistiveTouch(void)
{
tp = ts.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 > 180 && tp.z < 1000;
if (state == oldstate) count++;
else count = 0;
oldstate = state;
delay(5);
}
return oldstate;
}
uint32_t cx, cy, cz;
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;
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.println(F("Making all control and bus pins INPUT_PULLUP"));
Serial.println(F("Typical 30k Analog pullup with corresponding pin"));
Serial.println(F("would read low when digital is written LOW"));
Serial.println(F("e.g. reads ~25 for 300R X direction"));
Serial.println(F("e.g. reads ~30 for 500R Y direction"));
Serial.println(F(""));
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++) {
pinMode(i, INPUT_PULLUP);
for (j = 5; j < 10; j++) {
pinMode(j, OUTPUT);
digitalWrite(j, LOW);
value = analogRead(i); // ignore first reading
value = analogRead(i);
if (value < 100 && value > 0) {
showpins(i, j, value, "Testing :");
if (found < 2) {
Apins[found] = i;
Dpins[found] = j;
Values[found] = value;
}
found++;
}
pinMode(j, INPUT_PULLUP);
}
pinMode(i, INPUT_PULLUP);
}
if (found == 2) {
Serial.println(F("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];
ts = TouchScreen(XP, YP, XM, YM, 300); //re-initialise with pins
// ts = TouchScreen_kbv(XP, YP, XM, YM, 300); //re-initialise with pins
return true; //success
}
Serial.println(F("BROKEN TOUCHSCREEN"));
return false;
}
void setup()
{
Serial.begin(9600);
Serial.println(TITLE);
bool ret = true;
#if defined(__arm__)
Serial.println(F("Not possible to diagnose Touch pins on ARM"));
#else
ret = diagnose_pins();
#endif
uint16_t ID = tft.readID();
Serial.print("ID = 0x");
Serial.println(ID, HEX);
tft.begin(ID);
tft.setRotation(TOUCH_ORIENTATION);
dispx = tft.width();
dispy = tft.height();
text_y_center = (dispy / 2) - 6;
if (ret == false) {
centerprint("BROKEN TOUCHSCREEN", text_y_center);
while (true); //just tread water
}
}
void loop()
{
startup();
tft.fillScreen(BLACK);
drawCrossHair(dispx - 11, 10, GRAY);
drawCrossHair(dispx / 2, 10, GRAY);
drawCrossHair(10, 10, GRAY);
drawCrossHair(dispx - 11, dispy / 2, GRAY);
drawCrossHair(10, dispy / 2, GRAY);
drawCrossHair(dispx - 11, dispy - 11, GRAY);
drawCrossHair(dispx / 2, dispy - 11, GRAY);
drawCrossHair(10, dispy - 11, GRAY);
centerprint("***********", text_y_center - 12);
centerprint("***********", 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);
report(); // report results
while (true) {} // tread water
}
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)
{
centerprint("* PRESS *", text_y_center);
while (ISPRESSED() == false) {}
centerprint("* HOLD! *", text_y_center);
cnt = 0;
iter = 400;
do
{
readResistiveTouch();
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;
cz = tp.z;
}
void calibrate(int x, int y, int i)
{
drawCrossHair(x, y, WHITE);
readCoordinates();
centerprint("* RELEASE *", text_y_center);
drawCrossHair(x, y, GRAY);
rx[i] = cx;
ry[i] = cy;
Serial.print("\r\ncx="); Serial.print(cx);
Serial.print(" cy="); Serial.print(cy);
Serial.print(" cz="); Serial.print(cz);
while (ISPRESSED() == true) {}
}
void report()
{
uint16_t TS_LEFT, TS_RT, TS_TOP, TS_BOT, TS_WID, TS_HT, TS_SWAP;
int16_t tmp;
char buf[60];
centertitle(TITLE);
tft.println(F("To use the new calibration"));
tft.println(F("settings you must map the values"));
tft.println(F("from Point p = ts.getPoint() e.g. "));
tft.println(F("x = map(p.x, LEFT, RT, 0, tft.width());"));
tft.println(F("y = map(p.y, TOP, BOT, 0, tft.height());"));
tft.println(F("swap p.x and p.y if diff ORIENTATION"));
//.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);
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;
}
tft.setCursor(0, 120);
Serial.println("");
sprintf(buf, "MCUFRIEND_kbv ID=0x%04X %d x %d",
tft.readID(), TS_WID, TS_HT);
tft.println(buf);
Serial.println(buf);
sprintf(buf, "PORTRAIT CALIBRATION %d x %d", TS_WID, TS_HT);
tft.println("");
tft.println(buf);
Serial.println(buf);
sprintf(buf, "x = map(p.x, LEFT=%d, RT=%d, 0, %d)", TS_LEFT, TS_RT, TS_WID);
tft.println(buf);
Serial.println(buf);
sprintf(buf, "y = map(p.y, TOP=%d, BOT=%d, 0, %d)", TS_TOP, TS_BOT, TS_HT);
tft.println(buf);
Serial.println(buf);
sprintf(buf, "Touch Pin Wiring XP=%d XM=A%d YP=A%d YM=%d",
XP, XM - A0, YP - A0, YM);
tft.println("");
tft.println(buf);
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);
tft.println("");
tft.println(buf);
Serial.println(buf);
sprintf(buf, "x = map(p.y, LEFT=%d, RT=%d, 0, %d)", TS_LEFT, TS_RT, TS_WID);
tft.println(buf);
Serial.println(buf);
sprintf(buf, "y = map(p.x, TOP=%d, BOT=%d, 0, %d)", TS_TOP, TS_BOT, TS_HT);
tft.println(buf);
Serial.println(buf);
}
void drawCrossHair(int x, int y, uint16_t color)
{
tft.drawRect(x - 10, y - 10, 20, 20, color);
tft.drawLine(x - 5, y, x + 5, y, color);
tft.drawLine(x, y - 5, x, y + 5, color);
}
void centerprint(const char *s, int y)
{
int len = strlen(s) * 6;
tft.setTextColor(WHITE, RED);
tft.setCursor((dispx - len) / 2, y);
tft.print(s);
}
void centertitle(const char *s)
{
tft.fillScreen(BLACK);
tft.fillRect(0, 0, dispx, 14, RED);
tft.fillRect(0, 14, dispx, 1, WHITE);
centerprint(s, 1);
tft.setCursor(0, 30);
tft.setTextColor(WHITE, BLACK);
}
void startup()
{
centertitle(TITLE);
tft.println(F("#define NUMSAMPLES 3 in Library\n"));
tft.println(F("Use a stylus or something"));
tft.println(F("similar to touch as close"));
tft.println(F("to the center of the"));
tft.println(F("highlighted crosshair as"));
tft.println(F("possible. Keep as still as"));
tft.println(F("possible and keep holding"));
tft.println(F("until the highlight is"));
tft.println(F("removed. Repeat for all"));
tft.println(F("crosshairs in sequence.\n"));
tft.println(F("Report can be pasted from Serial\n"));
tft.println(F("Touch screen to continue"));
while (ISPRESSED() == false) {}
while (ISPRESSED() == true) {}
// waitForTouch();
}
void fail()
{
centertitle("Touch Calibration FAILED");
tft.println(F("Unable to read the position"));
tft.println(F("of the press. This is a"));
tft.println(F("hardware issue and can"));
tft.println(F("not be corrected in"));
tft.println(F("software."));
tft.println(F("check XP, XM pins with a multimeter"));
tft.println(F("check YP, YM pins with a multimeter"));
tft.println(F("should be about 300 ohms"));
while (true) {};
}

View File

@@ -0,0 +1,181 @@
// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// adapted from (c) ladyada / adafruit
#include "Arduino.h"
#include "TouchScreen_kbv.h"
#define NUMSAMPLES 3 //.kbv
#if defined(__STM32F1__) //Maple core
#define ADC_ADJUST >>2
#else
#define ADC_ADJUST
#endif
TSPoint::TSPoint(void) {
x = y = 0;
}
TSPoint::TSPoint(int16_t x0, int16_t y0, int16_t z0) {
x = x0;
y = y0;
z = z0;
}
bool TSPoint::operator==(TSPoint p1) {
return ((p1.x == x) && (p1.y == y) && (p1.z == z));
}
bool TSPoint::operator!=(TSPoint p1) {
return ((p1.x != x) || (p1.y != y) || (p1.z != z));
}
static void insert_sort(int array[], uint8_t size) {
uint8_t j;
int save;
for (int i = 1; i < size; i++) {
save = array[i];
for (j = i; j >= 1 && save < array[j - 1]; j--)
array[j] = array[j - 1];
array[j] = save;
}
}
TSPoint TouchScreen_kbv::getPoint(void) {
int x, y, z;
int samples[NUMSAMPLES];
uint8_t i, valid;
valid = 1;
pinMode(_yp, INPUT);
pinMode(_ym, INPUT);
digitalWrite(_yp, LOW);
digitalWrite(_ym, LOW);
pinMode(_xp, OUTPUT);
pinMode(_xm, OUTPUT);
digitalWrite(_xp, HIGH);
digitalWrite(_xm, LOW);
for (i = 0; i < NUMSAMPLES; i++) {
samples[i] = analogRead(_yp) ADC_ADJUST;
}
insert_sort(samples, NUMSAMPLES);
x = (1023 - samples[NUMSAMPLES / 2]); //choose median
pinMode(_xp, INPUT);
pinMode(_xm, INPUT);
digitalWrite(_xp, LOW);
digitalWrite(_xm, LOW); //.kbv for Due
pinMode(_yp, OUTPUT);
digitalWrite(_yp, HIGH);
pinMode(_ym, OUTPUT);
digitalWrite(_ym, LOW); //.kbv for Due
for (i = 0; i < NUMSAMPLES; i++) {
samples[i] = analogRead(_xm) ADC_ADJUST;
}
insert_sort(samples, NUMSAMPLES);
y = (1023 - samples[NUMSAMPLES / 2]);
// Set X+ to ground
pinMode(_xp, OUTPUT);
digitalWrite(_xp, LOW);
// Set Y- to VCC
pinMode(_ym, OUTPUT); //.kbv
digitalWrite(_ym, HIGH);
// Hi-Z X- and Y+
digitalWrite(_xm, LOW); //.kbv
pinMode(_xm, INPUT); //.kbv
digitalWrite(_yp, LOW);
pinMode(_yp, INPUT);
int z1 = analogRead(_xm) ADC_ADJUST;
int z2 = analogRead(_yp) ADC_ADJUST;
z = (1023 - (z2 - z1));
return TSPoint(x, y, z); //XM, YP still in ANALOG mode
}
TouchScreen_kbv::TouchScreen_kbv(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym) {
_yp = yp;
_xm = xm;
_ym = ym;
_xp = xp;
_rxplate = 0;
pressureThreshhold = 10;
}
TouchScreen_kbv::TouchScreen_kbv(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym,
uint16_t rxplate) {
_yp = yp;
_xm = xm;
_ym = ym;
_xp = xp;
_rxplate = rxplate;
pressureThreshhold = 10;
}
int TouchScreen_kbv::readTouchX(void) {
pinMode(_yp, INPUT);
pinMode(_ym, INPUT);
digitalWrite(_yp, LOW);
digitalWrite(_ym, LOW);
pinMode(_xp, OUTPUT);
digitalWrite(_xp, HIGH);
pinMode(_xm, OUTPUT);
digitalWrite(_xm, LOW);
return (1023 - (analogRead(_yp)) ADC_ADJUST);
}
int TouchScreen_kbv::readTouchY(void) {
pinMode(_xp, INPUT);
pinMode(_xm, INPUT);
digitalWrite(_xp, LOW);
digitalWrite(_xm, LOW);
pinMode(_yp, OUTPUT);
digitalWrite(_yp, HIGH);
pinMode(_ym, OUTPUT);
digitalWrite(_ym, LOW);
return (1023 - (analogRead(_xm)) ADC_ADJUST);
}
uint16_t TouchScreen_kbv::pressure(void) {
// Set X+ to ground
pinMode(_xp, OUTPUT);
digitalWrite(_xp, LOW);
// Set Y- to VCC
pinMode(_ym, OUTPUT);
digitalWrite(_ym, HIGH);
// Hi-Z X- and Y+
digitalWrite(_xm, LOW);
pinMode(_xm, INPUT);
digitalWrite(_yp, LOW);
pinMode(_yp, INPUT);
int z1 = analogRead(_xm) ADC_ADJUST;
int z2 = analogRead(_yp) ADC_ADJUST;
return (1023 - (z2 - z1));
}

View File

@@ -0,0 +1,39 @@
// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// (c) ladyada / adafruit
// Code under MIT License
#ifndef _TOUCHSCREEN_KBV_H_
#define _TOUCHSCREEN_KBV_H_
#include <stdint.h>
class TSPoint {
public:
TSPoint(void);
TSPoint(int16_t x, int16_t y, int16_t z);
bool operator==(TSPoint);
bool operator!=(TSPoint);
int16_t x, y, z;
};
class TouchScreen_kbv {
public:
TouchScreen_kbv(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym);
TouchScreen_kbv(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym, uint16_t rx);
// bool isTouching(void);
uint16_t pressure(void);
int readTouchY();
int readTouchX();
TSPoint getPoint();
int16_t pressureThreshhold;
private:
uint8_t _yp, _ym, _xm, _xp;
uint16_t _rxplate;
};
#endif