389 lines
9.0 KiB
C++
389 lines
9.0 KiB
C++
/*!
|
|
*
|
|
* @file Adafruit_STMPE610.cpp
|
|
*
|
|
* @mainpage Adafruit STMPE610 Resistive Touch Screen Controller
|
|
*
|
|
* @section intro_sec Introduction
|
|
*
|
|
* This is a library for the Adafruit STMPE610 Resistive
|
|
* touch screen controller breakout
|
|
* ----> http://www.adafruit.com/products/1571
|
|
*
|
|
* Check out the links above for our tutorials and wiring diagrams
|
|
* These breakouts use SPI or I2C to communicate
|
|
*
|
|
* Adafruit invests time and resources providing this open source code,
|
|
* please support Adafruit and open-source hardware by purchasing
|
|
* products from Adafruit!
|
|
*
|
|
* @section author Author
|
|
*
|
|
* Written by Limor Fried/Ladyada for Adafruit Industries.
|
|
*
|
|
* @section license License
|
|
*
|
|
* MIT license, all text above must be included in any redistribution
|
|
*/
|
|
|
|
#include "Arduino.h"
|
|
|
|
#include <SPI.h>
|
|
#include <Wire.h>
|
|
|
|
#include "Adafruit_STMPE610.h"
|
|
|
|
static SPISettings mySPISettings;
|
|
|
|
/*!
|
|
* @brief Instantiates a new STMPE610 class using bitbang SPI
|
|
* @param cspin
|
|
* CS pin
|
|
* @param mosipin
|
|
* MOSI pin
|
|
* @param misopin
|
|
* MISO pin
|
|
* @param clkpin
|
|
* CLK pin
|
|
*/
|
|
Adafruit_STMPE610::Adafruit_STMPE610(uint8_t cspin, uint8_t mosipin,
|
|
uint8_t misopin, uint8_t clkpin) {
|
|
_CS = cspin;
|
|
_MOSI = mosipin;
|
|
_MISO = misopin;
|
|
_CLK = clkpin;
|
|
}
|
|
|
|
/*!
|
|
* @brief Instantiates a new STMPE610 using provided SPI
|
|
* @param cspin
|
|
* CS pin
|
|
* @param *theSPI
|
|
* spi object
|
|
*/
|
|
Adafruit_STMPE610::Adafruit_STMPE610(uint8_t cspin, SPIClass *theSPI) {
|
|
_CS = cspin;
|
|
_MOSI = _MISO = _CLK = -1;
|
|
_spi = theSPI;
|
|
}
|
|
|
|
/*!
|
|
* @brief Instantiates a new STMPE610 using provided Wire
|
|
* @param *theWire
|
|
* wire object
|
|
*/
|
|
Adafruit_STMPE610::Adafruit_STMPE610(TwoWire *theWire) {
|
|
_CS = _MISO = _MOSI = _CLK = -1;
|
|
_wire = theWire;
|
|
}
|
|
|
|
/*!
|
|
* @brief Setups the HW
|
|
* @param i2caddr
|
|
* I2C address (defaults to STMPE_ADDR)
|
|
* @return True if process is successful
|
|
*/
|
|
boolean Adafruit_STMPE610::begin(uint8_t i2caddr) {
|
|
if (_CS != -1 && _CLK == -1) {
|
|
// hardware SPI
|
|
pinMode(_CS, OUTPUT);
|
|
digitalWrite(_CS, HIGH);
|
|
|
|
_spi->begin();
|
|
mySPISettings = SPISettings(1000000, MSBFIRST, SPI_MODE0);
|
|
m_spiMode = SPI_MODE0;
|
|
} else if (_CS != -1) {
|
|
// software SPI
|
|
pinMode(_CLK, OUTPUT);
|
|
pinMode(_CS, OUTPUT);
|
|
pinMode(_MOSI, OUTPUT);
|
|
pinMode(_MISO, INPUT);
|
|
} else {
|
|
_wire->begin();
|
|
_i2caddr = i2caddr;
|
|
}
|
|
|
|
// try mode0
|
|
if (getVersion() != 0x811) {
|
|
if (_CS != -1 && _CLK == -1) {
|
|
// Serial.println("try MODE1");
|
|
mySPISettings = SPISettings(1000000, MSBFIRST, SPI_MODE1);
|
|
m_spiMode = SPI_MODE1;
|
|
|
|
if (getVersion() != 0x811) {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
writeRegister8(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET);
|
|
delay(10);
|
|
|
|
for (uint8_t i = 0; i < 65; i++) {
|
|
readRegister8(i);
|
|
}
|
|
|
|
writeRegister8(STMPE_SYS_CTRL2, 0x0); // turn on clocks!
|
|
writeRegister8(STMPE_TSC_CTRL,
|
|
STMPE_TSC_CTRL_XYZ | STMPE_TSC_CTRL_EN); // XYZ and enable!
|
|
// Serial.println(readRegister8(STMPE_TSC_CTRL), HEX);
|
|
writeRegister8(STMPE_INT_EN, STMPE_INT_EN_TOUCHDET);
|
|
writeRegister8(STMPE_ADC_CTRL1, STMPE_ADC_CTRL1_10BIT |
|
|
(0x6 << 4)); // 96 clocks per conversion
|
|
writeRegister8(STMPE_ADC_CTRL2, STMPE_ADC_CTRL2_6_5MHZ);
|
|
writeRegister8(STMPE_TSC_CFG, STMPE_TSC_CFG_4SAMPLE |
|
|
STMPE_TSC_CFG_DELAY_1MS |
|
|
STMPE_TSC_CFG_SETTLE_5MS);
|
|
writeRegister8(STMPE_TSC_FRACTION_Z, 0x6);
|
|
writeRegister8(STMPE_FIFO_TH, 1);
|
|
writeRegister8(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET);
|
|
writeRegister8(STMPE_FIFO_STA, 0); // unreset
|
|
writeRegister8(STMPE_TSC_I_DRIVE, STMPE_TSC_I_DRIVE_50MA);
|
|
writeRegister8(STMPE_INT_STA, 0xFF); // reset all ints
|
|
writeRegister8(STMPE_INT_CTRL,
|
|
STMPE_INT_CTRL_POL_HIGH | STMPE_INT_CTRL_ENABLE);
|
|
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
* @brief Returns true if touched, false otherwise
|
|
* @return True if if touched, false otherwise
|
|
*/
|
|
boolean Adafruit_STMPE610::touched() {
|
|
return (readRegister8(STMPE_TSC_CTRL) & 0x80);
|
|
}
|
|
|
|
/*!
|
|
* @brief Checks if buffer is empty
|
|
* @return True if empty, false otherwise
|
|
*/
|
|
boolean Adafruit_STMPE610::bufferEmpty() {
|
|
return (readRegister8(STMPE_FIFO_STA) & STMPE_FIFO_STA_EMPTY);
|
|
}
|
|
|
|
/*!
|
|
* @brief Returns the FIFO buffer size
|
|
* @return The FIFO buffer size
|
|
*/
|
|
uint8_t Adafruit_STMPE610::bufferSize() {
|
|
return readRegister8(STMPE_FIFO_SIZE);
|
|
}
|
|
|
|
/*!
|
|
* @brief Returns the STMPE610 version number
|
|
* @return The STMPE610 version number
|
|
*/
|
|
uint16_t Adafruit_STMPE610::getVersion() {
|
|
uint16_t v;
|
|
// Serial.print("get version");
|
|
v = readRegister8(0);
|
|
v <<= 8;
|
|
v |= readRegister8(1);
|
|
// Serial.print("Version: 0x"); Serial.println(v, HEX);
|
|
return v;
|
|
}
|
|
|
|
/*!
|
|
* @brief Reads touchscreen data
|
|
* @param *x
|
|
* The x coordinate
|
|
* @param *y
|
|
* The y coordinate
|
|
* @param *z
|
|
* The z coordinate
|
|
*/
|
|
void Adafruit_STMPE610::readData(uint16_t *x, uint16_t *y, uint8_t *z) {
|
|
uint8_t data[4];
|
|
|
|
for (uint8_t i = 0; i < 4; i++) {
|
|
data[i] = readRegister8(0xD7); // _spi->transfer(0x00);
|
|
// Serial.print("0x"); Serial.print(data[i], HEX); Serial.print(" / ");
|
|
}
|
|
*x = data[0];
|
|
*x <<= 4;
|
|
*x |= (data[1] >> 4);
|
|
*y = data[1] & 0x0F;
|
|
*y <<= 8;
|
|
*y |= data[2];
|
|
*z = data[3];
|
|
}
|
|
|
|
/*!
|
|
* @brief Returns point for touchscreen data
|
|
* @return The touch point using TS_Point
|
|
*/
|
|
TS_Point Adafruit_STMPE610::getPoint() {
|
|
uint16_t x = 0, y = 0;
|
|
uint8_t z;
|
|
|
|
/* Making sure that we are reading all data before leaving */
|
|
while (!bufferEmpty()) {
|
|
readData(&x, &y, &z);
|
|
}
|
|
|
|
if (bufferEmpty())
|
|
writeRegister8(STMPE_INT_STA, 0xFF); // reset all ints
|
|
|
|
return TS_Point(x, y, z);
|
|
}
|
|
|
|
/*!
|
|
* @brief Reads SPI data
|
|
*/
|
|
uint8_t Adafruit_STMPE610::spiIn() {
|
|
if (_CLK == -1) {
|
|
uint8_t d = _spi->transfer(0);
|
|
return d;
|
|
} else
|
|
return shiftIn(_MISO, _CLK, MSBFIRST);
|
|
}
|
|
|
|
/*!
|
|
* @brief Sends data through SPI
|
|
* @param x
|
|
* Data to send (one byte)
|
|
*/
|
|
void Adafruit_STMPE610::spiOut(uint8_t x) {
|
|
if (_CLK == -1) {
|
|
_spi->transfer(x);
|
|
} else
|
|
shiftOut(_MOSI, _CLK, MSBFIRST, x);
|
|
}
|
|
|
|
/*!
|
|
* @brief Reads 8bit of data from specified register
|
|
* @param reg
|
|
* The register
|
|
* @return Data in the register
|
|
*/
|
|
uint8_t Adafruit_STMPE610::readRegister8(uint8_t reg) {
|
|
uint8_t x;
|
|
if (_CS == -1) {
|
|
// use i2c
|
|
_wire->beginTransmission(_i2caddr);
|
|
_wire->write((byte)reg);
|
|
_wire->endTransmission();
|
|
_wire->requestFrom(_i2caddr, (byte)1);
|
|
x = _wire->read();
|
|
|
|
// Serial.print("$"); Serial.print(reg, HEX);
|
|
// Serial.print(": 0x"); Serial.println(x, HEX);
|
|
} else {
|
|
if (_CLK == -1)
|
|
_spi->beginTransaction(mySPISettings);
|
|
|
|
digitalWrite(_CS, LOW);
|
|
spiOut(0x80 | reg);
|
|
spiOut(0x00);
|
|
x = spiIn();
|
|
digitalWrite(_CS, HIGH);
|
|
|
|
if (_CLK == -1)
|
|
_spi->endTransaction();
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
/*!
|
|
* @brief Reads 16 bits of data from specified register
|
|
* @param reg
|
|
* The register
|
|
* @return Data in the register
|
|
*/
|
|
uint16_t Adafruit_STMPE610::readRegister16(uint8_t reg) {
|
|
uint16_t x = 0;
|
|
if (_CS == -1) {
|
|
// use i2c
|
|
_wire->beginTransmission(_i2caddr);
|
|
_wire->write((byte)reg);
|
|
_wire->endTransmission();
|
|
_wire->requestFrom(_i2caddr, (byte)2);
|
|
x = _wire->read();
|
|
x <<= 8;
|
|
x |= _wire->read();
|
|
}
|
|
if (_CLK == -1) {
|
|
// hardware SPI
|
|
if (_CLK == -1)
|
|
_spi->beginTransaction(mySPISettings);
|
|
digitalWrite(_CS, LOW);
|
|
spiOut(0x80 | reg);
|
|
spiOut(0x00);
|
|
x = spiIn();
|
|
x <<= 8;
|
|
x |= spiIn();
|
|
digitalWrite(_CS, HIGH);
|
|
if (_CLK == -1)
|
|
_spi->endTransaction();
|
|
}
|
|
|
|
// Serial.print("$"); Serial.print(reg, HEX);
|
|
// Serial.print(": 0x"); Serial.println(x, HEX);
|
|
return x;
|
|
}
|
|
|
|
/*!
|
|
* @brief Writes 8 bit of data to specified register
|
|
* @param reg
|
|
* The register
|
|
* @param val
|
|
* Value to write
|
|
*/
|
|
void Adafruit_STMPE610::writeRegister8(uint8_t reg, uint8_t val) {
|
|
if (_CS == -1) {
|
|
// use i2c
|
|
_wire->beginTransmission(_i2caddr);
|
|
_wire->write((byte)reg);
|
|
_wire->write(val);
|
|
_wire->endTransmission();
|
|
} else {
|
|
if (_CLK == -1)
|
|
_spi->beginTransaction(mySPISettings);
|
|
digitalWrite(_CS, LOW);
|
|
spiOut(reg);
|
|
spiOut(val);
|
|
digitalWrite(_CS, HIGH);
|
|
if (_CLK == -1)
|
|
_spi->endTransaction();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* @brief TS_Point constructor
|
|
*/
|
|
TS_Point::TS_Point() { x = y = 0; }
|
|
|
|
/*!
|
|
* @brief TS_Point constructor
|
|
* @param x0
|
|
* Initial x
|
|
* @param y0
|
|
* Initial y
|
|
* @param z0
|
|
* Initial z
|
|
*/
|
|
TS_Point::TS_Point(int16_t x0, int16_t y0, int16_t z0) {
|
|
x = x0;
|
|
y = y0;
|
|
z = z0;
|
|
}
|
|
|
|
/*!
|
|
* @brief Equality operator for TS_Point
|
|
* @return True if points are equal
|
|
*/
|
|
bool TS_Point::operator==(TS_Point p1) {
|
|
return ((p1.x == x) && (p1.y == y) && (p1.z == z));
|
|
}
|
|
|
|
/*!
|
|
* @brief Non-equality operator for TS_Point
|
|
* @return True if points are not equal
|
|
*/
|
|
bool TS_Point::operator!=(TS_Point p1) {
|
|
return ((p1.x != x) || (p1.y != y) || (p1.z != z));
|
|
}
|