Merge branch 'tfry-git-work/xpt2046'

This commit is contained in:
Roger Clark 2018-04-01 16:18:13 +10:00
commit 1c48f1aaa7
2 changed files with 110 additions and 62 deletions

View File

@ -8,72 +8,89 @@
#include "Arduino.h" #include "Arduino.h"
#include "XPT2046_touch.h" #include "XPT2046_touch.h"
/****************************************************************************/
XPT2046_touch::XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan) : cs_pin(_cs_pin), my_SPI(_spiChan){ XPT2046_touch::XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan) : cs_pin(_cs_pin), my_SPI(_spiChan){
setOversampling();
setThreshold();
} }
/****************************************************************************/
void XPT2046_touch::begin(){ void XPT2046_touch::begin(){
pinMode(cs_pin, OUTPUT); pinMode(cs_pin, OUTPUT);
digitalWrite(cs_pin, HIGH); digitalWrite(cs_pin, HIGH);
my_SPI.begin(); my_SPI.begin();
} }
/****************************************************************************/ uint16_t XPT2046_touch::gatherSamples(uint8_t command) {
uint32_t sample_sum = 0;
uint16_t samples[MAX_OVERSAMPLING];
boolean XPT2046_touch::read_XY(uint16_t *xy){ my_SPI.transfer16(command); // discard first reading after switching MUX
int z1, z2, tmpH, tmpL; for (int i = 0; i < oversampling; ++i) {
samples[i] = my_SPI.transfer16(command);
sample_sum += samples[i];
}
int32_t avg = sample_sum / oversampling;
if (oversampling < 3) {
return avg >> 3;
}
// occasionally, we get a reading that is a _far_ outlier.
// checking for, and removing those improves quality a lot.
uint8_t n = oversampling;
for (int i = 0; i < oversampling; ++i) {
if (abs(avg - samples[i]) > 80) { // NOTE: data is left shifted by 3 at this point. I.e. the test is for 10+ pixels deviation from average
sample_sum -= samples[i];
--n;
}
}
if (n < 2) return avg >> 3;
else return (sample_sum / n) >> 3;
}
TS_Point XPT2046_touch::getPoint() {
uint16_t z1, z2;
my_SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0)); // max clock freq for XPT2046
digitalWrite(cs_pin, LOW); digitalWrite(cs_pin, LOW);
TS_Point ret;
//Check if touch screen is pressed. //Check if touch screen is pressed.
SPI.transfer(B10110011); // Z1 my_SPI.transfer(B10110011); // trigger Z1 reading
delay(10); z1 = my_SPI.transfer16(B11000011) >> 3; // read Z1, and trigger Z2 reading
tmpH = (my_SPI.transfer(0) << 5); z2 = my_SPI.transfer16(B10010011) >> 3; // read Z2, and trigger Y reading
tmpL = (my_SPI.transfer(0) >> 3); ret.z = z1 + 4095 - z2;
z1 = tmpH | tmpL;
SPI.transfer(B11000011); // Z2 if(ret.z >= threshold){ //If the touch screen is pressed, read the X,Y coordinates from XPT2046.
delay(10); ret.x = gatherSamples(B10010011);
tmpH = (my_SPI.transfer(0) << 5); ret.y = gatherSamples(B11010011);
tmpL = (my_SPI.transfer(0) >> 3); } else {
z2 = tmpH | tmpL; ret.z = 0;
if((z2 - z1) < Z_THRESHOLD){ //If the touch screen is pressed, read the X,Y coordinates from XPT2046.
my_SPI.transfer(B11010011); // X
delay(10);
tmpH = (my_SPI.transfer(0) << 5);
tmpL = (my_SPI.transfer(0) >> 3);
xy[0] = tmpH | tmpL;
my_SPI.transfer(B10010011); // Y
delay(10);
tmpH = (my_SPI.transfer(0) << 5);
tmpL = (my_SPI.transfer(0) >> 3);
xy[1] = tmpH | tmpL;
digitalWrite(cs_pin, HIGH);
return true;
} }
my_SPI.transfer(B00000000); // enter power saving (and IRQ enable)
digitalWrite(cs_pin, HIGH); digitalWrite(cs_pin, HIGH);
return false; my_SPI.endTransaction();
return ret;
} }
/****************************************************************************/ boolean XPT2046_touch::read_XY(uint16_t *xy) {
TS_Point p = getPoint();
xy[0] = p.x;
xy[1] = p.y;
return p.z > 0;
}
////////////////// Buttons ////////////////
void XPT2046_touch::setButtonsNumber(byte columnButtons, byte rowButtons ){ void XPT2046_touch::setButtonsNumber(byte columnButtons, byte rowButtons ){
_rowButtons = rowButtons; _rowButtons = rowButtons;
_columnButtons = columnButtons; _columnButtons = columnButtons;
} }
/****************************************************************************/
uint8_t XPT2046_touch::getButtonNumber(){ uint8_t XPT2046_touch::getButtonNumber(){
uint16_t xy[2]; uint16_t xy[2];
uint8_t tmp, buttonNum; uint8_t tmp, buttonNum;
int div; int div;
if(read_XY(xy)){ if(read_XY(xy)){
div = (X_MAX + X_MIN) / (_columnButtons + 1); div = (X_MAX + X_MIN) / (_columnButtons + 1);
buttonNum = ((xy[1] / div)); buttonNum = ((xy[1] / div));
@ -85,4 +102,3 @@
return 0; //Touch screen is not pressed. return 0; //Touch screen is not pressed.
} }
/****************************************************************************/

View File

@ -11,7 +11,8 @@
#include <Arduino.h> #include <Arduino.h>
#include <SPI.h> #include <SPI.h>
#define Z_THRESHOLD 3000 #define Z_THRESHOLD 3500 // Note: reversed for backwards compatiblity: 4095-x
#define MAX_OVERSAMPLING 32
// Pre-defined touch screen calibration for using the 2.4" ILI9341 LCD // Pre-defined touch screen calibration for using the 2.4" ILI9341 LCD
#define X_MIN 830 #define X_MIN 830
@ -19,23 +20,54 @@
#define Y_MIN 550 #define Y_MIN 550
#define Y_MAX 3550 #define Y_MAX 3550
class TS_Point {
public:
TS_Point(void) : x(0), y(0), z(0) {}
TS_Point(int16_t x, int16_t y, int16_t z) : x(x), y(y), z(z) {}
bool operator==(TS_Point p) { return ((p.x == x) && (p.y == y) && (p.z == z)); }
bool operator!=(TS_Point p) { return ((p.x != x) || (p.y != y) || (p.z != z)); }
int16_t x, y, z;
};
/** /**
* *
*/ */
class XPT2046_touch { class XPT2046_touch {
private: private:
uint8_t cs_pin; uint8_t cs_pin;
SPIClass my_SPI; SPIClass my_SPI;
uint8_t _rowButtons = 1; uint8_t _rowButtons = 1;
uint8_t _columnButtons = 1; uint8_t _columnButtons = 1;
uint8_t oversampling;
uint16_t threshold;
uint16_t gatherSamples(uint8_t command);
public: public:
XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan); //Contructor. /** c'tor. Note that no IRQ pin is supported, here. You can easily do that yourself:
* \code if(digitalRead(irq_pin)) {
* // no press: skip
* } else {
* // _may_ be touched, but not necessarily reach the threshold
* TS_Point p = ts.getPoint();
* if (p.z > 0) {
* // do something
* }
* }
* \endcode */
XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan); //Contructor
void begin(); void begin();
void setButtonsNumber(byte rowButtons, byte columnButtons); void setButtonsNumber(byte rowButtons, byte columnButtons);
/** Number of samples to average per point 0..32 */
void setOversampling(uint8_t num_readings = 7) {
oversampling = max(1, min(num_readings, MAX_OVERSAMPLING));
}
void setThreshold(uint16_t threshold = 4095 - Z_THRESHOLD) {
XPT2046_touch::threshold = threshold;
}
uint8_t getButtonNumber(); uint8_t getButtonNumber();
boolean read_XY(uint16_t *xy); boolean read_XY(uint16_t *xy);
TS_Point getPoint();
}; };
#endif #endif