Files
ESP8266lib/ext/sens/XPT2046.h
kazu 5cb02880b3 many updates..
new sensors.. display.. led.. drawing.. stuff..
2019-01-17 23:12:01 +01:00

133 lines
2.9 KiB
C++

#ifndef XPT2046_H
#define XPT2046_H
#include "../../Platforms.h"
#include "../../io/HardSPI.h"
#include "../../io/SoftSPI.h"
// https://www.buydisplay.com/download/ic/XPT2046.pdf
/** SPI-like touch controller */
//template <int PIN_CS, int PIN_MISO, int PIN_MOSI, int PIN_CLK> class XPT2046 {
template <int PIN_CS, typename SPI> class XPT2046 {
//SoftSPI<PIN_MISO, PIN_MOSI, PIN_CLK, true> spi;
//HardSPI<PIN_MISO, PIN_MOSI, PIN_CLK> spi;
static constexpr int PD0 = 0;
static constexpr int PD1 = 1;
static constexpr int SER_DFR = 2;
static constexpr int MODE = 3;
static constexpr int ADDR = 4;
static constexpr int START = 7;
SPI& spi;
public:
XPT2046(SPI& spi) : spi(spi) {
//spi.init();
GPIO::setOutput(PIN_CS);
}
struct Result {
bool valid;
uint16_t x;
uint16_t y;
};
Result read() {
GPIO::clear(PIN_CS);
//vTaskDelay(1 / portTICK_PERIOD_MS);
Result res;
if (!isTouched()) {
res.valid = false;
} else {
const uint16_t y = readAvg(1);
const uint16_t x = readAvg(5);
res.y = y;
res.x = x;
res.valid = (x != 0xFFFF) && (y != 0xFFFF);
}
GPIO::set(PIN_CS);
return res;
}
private:
/** read 12-bit result from the given input-address using either differential mode or not */
uint16_t read(const int inp, const bool differential) {
//uint8_t buf[2];
const uint8_t diff = differential ? 0 : 1;
const uint8_t cmd = (1 << START) | (inp << ADDR) | (0 << MODE) | (diff << SER_DFR) | (1 << PD1) | (1 << PD0);
//printf("touch cmd: %d\n", cmd);
// spi.writeByte(cmd);
// uint8_t v1 = spi.readByte();
// uint8_t v2 = spi.readByte();
// spi.read(buf, 2);
// mainly needed for hardware SPI, where send8+read8+read8 does not work as expected
// output: cccccccc 00000000 00000000 00000000
// input: -------- -rrrrrrr rrrrr--- --------
const uint32_t tmp = spi.readWriteQuad(cmd << 24);
const uint8_t v1 = (tmp >> 16) & 0xFF;
const uint8_t v2 = (tmp >> 8) & 0xFF;
const uint16_t res = (v1 << 8 | v2) >> 3;
//printf("res: %d\n", res);
return res;
}
bool isTouched() {
// read Y-axis in non-differential mode. if result is close to 4095, screen is not touched
for (int i = 0; i < 4; ++i) {
if (read(1,false) > 3900) {return false;}
}
// read X-axis in non-differential mode. if result is close to 4095, screen is not touched
for (int i = 0; i < 4; ++i) {
if (read(5,false) > 3900) {return false;}
}
return true;
}
uint16_t readAvg(const int inp) {
// dummy-reads to stabilize the result
for (int i = 0; i < 4; ++i) {read(inp, true);}
// perform several reads and estimate std-dev
static constexpr uint8_t cnt = 12;
uint32_t sum = 0;
uint32_t sum2 = 0;
for (int i = 0; i < cnt; ++i) {
const uint16_t cur = read(inp, true);
sum += cur;
sum2 += cur*cur;
}
const uint32_t stdDev = (sum2/cnt) - (sum/cnt)*(sum/cnt);
//printf("%d\n", stdDev);
return (stdDev < 4096) ? ((sum/cnt)&0xFFFF) : (0xFFFF);
}
};
#endif // XPT2046_H