Merge branch 'tfry-git-work/xpt2046'
This commit is contained in:
commit
1c48f1aaa7
|
@ -8,72 +8,89 @@
|
|||
#include "Arduino.h"
|
||||
#include "XPT2046_touch.h"
|
||||
|
||||
XPT2046_touch::XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan) : cs_pin(_cs_pin), my_SPI(_spiChan){
|
||||
setOversampling();
|
||||
setThreshold();
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
XPT2046_touch::XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan) : cs_pin(_cs_pin), my_SPI(_spiChan){
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void XPT2046_touch::begin(){
|
||||
void XPT2046_touch::begin(){
|
||||
pinMode(cs_pin, OUTPUT);
|
||||
digitalWrite(cs_pin, HIGH);
|
||||
my_SPI.begin();
|
||||
}
|
||||
|
||||
uint16_t XPT2046_touch::gatherSamples(uint8_t command) {
|
||||
uint32_t sample_sum = 0;
|
||||
uint16_t samples[MAX_OVERSAMPLING];
|
||||
|
||||
my_SPI.transfer16(command); // discard first reading after switching MUX
|
||||
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;
|
||||
}
|
||||
|
||||
boolean XPT2046_touch::read_XY(uint16_t *xy){
|
||||
int z1, z2, tmpH, tmpL;
|
||||
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);
|
||||
TS_Point ret;
|
||||
|
||||
//Check if touch screen is pressed.
|
||||
SPI.transfer(B10110011); // Z1
|
||||
delay(10);
|
||||
tmpH = (my_SPI.transfer(0) << 5);
|
||||
tmpL = (my_SPI.transfer(0) >> 3);
|
||||
z1 = tmpH | tmpL;
|
||||
my_SPI.transfer(B10110011); // trigger Z1 reading
|
||||
z1 = my_SPI.transfer16(B11000011) >> 3; // read Z1, and trigger Z2 reading
|
||||
z2 = my_SPI.transfer16(B10010011) >> 3; // read Z2, and trigger Y reading
|
||||
ret.z = z1 + 4095 - z2;
|
||||
|
||||
SPI.transfer(B11000011); // Z2
|
||||
delay(10);
|
||||
tmpH = (my_SPI.transfer(0) << 5);
|
||||
tmpL = (my_SPI.transfer(0) >> 3);
|
||||
z2 = tmpH | tmpL;
|
||||
|
||||
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;
|
||||
}
|
||||
digitalWrite(cs_pin, HIGH);
|
||||
return false;
|
||||
if(ret.z >= threshold){ //If the touch screen is pressed, read the X,Y coordinates from XPT2046.
|
||||
ret.x = gatherSamples(B10010011);
|
||||
ret.y = gatherSamples(B11010011);
|
||||
} else {
|
||||
ret.z = 0;
|
||||
}
|
||||
my_SPI.transfer(B00000000); // enter power saving (and IRQ enable)
|
||||
|
||||
/****************************************************************************/
|
||||
void XPT2046_touch::setButtonsNumber(byte columnButtons, byte rowButtons ){
|
||||
digitalWrite(cs_pin, HIGH);
|
||||
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 ){
|
||||
_rowButtons = rowButtons;
|
||||
_columnButtons = columnButtons;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
uint8_t XPT2046_touch::getButtonNumber(){
|
||||
uint8_t XPT2046_touch::getButtonNumber(){
|
||||
uint16_t xy[2];
|
||||
uint8_t tmp, buttonNum;
|
||||
int div;
|
||||
|
||||
if(read_XY(xy)){
|
||||
|
||||
div = (X_MAX + X_MIN) / (_columnButtons + 1);
|
||||
buttonNum = ((xy[1] / div));
|
||||
|
||||
|
@ -84,5 +101,4 @@
|
|||
}
|
||||
|
||||
return 0; //Touch screen is not pressed.
|
||||
}
|
||||
/****************************************************************************/
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
#include <Arduino.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
|
||||
#define X_MIN 830
|
||||
|
@ -19,23 +20,54 @@
|
|||
#define Y_MIN 550
|
||||
#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:
|
||||
uint8_t cs_pin;
|
||||
SPIClass my_SPI;
|
||||
uint8_t _rowButtons = 1;
|
||||
uint8_t _columnButtons = 1;
|
||||
uint8_t oversampling;
|
||||
uint16_t threshold;
|
||||
uint16_t gatherSamples(uint8_t command);
|
||||
|
||||
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 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();
|
||||
boolean read_XY(uint16_t *xy);
|
||||
TS_Point getPoint();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue