Merge pull request #5067 from tonhuisman/feature/P123-add-support-for-more-touchscreen-types

[P123] Add support for GT911, CST820, CST226, AXS15231 and CHSC5816 touch screens
This commit is contained in:
TD-er
2024-06-30 22:34:39 +02:00
committed by GitHub
25 changed files with 1417 additions and 545 deletions
+22 -2
View File
@@ -232,17 +232,37 @@
:red:`Internal`","
Run I2C scanner to find connected I2C chips. Output will be sent to the serial port.
``I2Cscanner``
``I2Cscanner[,1]``
Added: 2024-06-14:
With the optional debug argument ``1`` provided, the returned I2C status (error) code will be listed for *all* tested I2C addresses.
Added: 2024-06-14:
Scan is performed at the Low I2C speed configured (default 100 kHz). When having an I2C multiplexer configured, all channels of the multiplexer will also be scanned.
Example output:
.. code-block:: none
4500043 : Info : Command: i2cscanner
>i2cscanner
Standard I2C bus
I2C : Found 0x3c
I2C : Found 0x40
I2C : Found 0x5a
>i2cscanner,1
Standard I2C bus
I2C : Error 2 at 0x01
I2C : Error 2 at 0x02
I2C : Error 2 at 0x03
...
I2C : Error 2 at 0x3f
I2C : Found 0x40
I2C : Error 2 at 0x41
...
I2C : Error 2 at 0x7e
I2C : Error 2 at 0x7f
"
"
Inc","
+36 -5
View File
@@ -24,9 +24,9 @@ Used libraries: |P123_usedlibraries|
Supported hardware
------------------
Some displays are available with a touch overlay mounted on top of the visible side of the display. There's a choice of resistive and capacitive touch overlays. The FT62x6 series of touch overlays are of the Capacitive kind, being very easy to interact with, comparable to modern smartphones, where you can use a finger for the interaction. (Resistive touch overlays usually require a special pen to be used, or pressed with a finger-nail, to get a response.)
Some displays are available with a touch overlay mounted on top of the visible side of the display. There's a choice of resistive and capacitive touch overlays. The I2C touch overlays supported in this plugin are of the Capacitive kind, being very easy to interact with, comparable to modern smartphones, where you can use a finger for the interaction. (Resistive touch overlays usually require a special pen to be used, or pressed with a finger-nail, to get a response.)
The FT62x6 touch overlay (or touch screen), can be found on several displays, f.e. some M5Stack devices and the WT32-SC01 display unit.
The supported touch overlays (or touch screens), can be found on several displays, f.e. some M5Stack devices, the WT32-SC01 display unit and the LilyGO LILY Pi ESP32 unit.
Device configuration
--------------------
@@ -59,7 +59,39 @@ The configured display will be used to draw the objects, if any, that can be con
* **Display Color-depth**: If the display settings have been retrieved successfully, this setting can not be changed, but will be used from the display. This value is used to select the correct color mappings for displaying the Objects.
* **Touch minimum pressure**: This setting determines the relative pressure or sensitivity of the touch display. Lower values make it more sensitive. The range is 0 to 255.
* **Touch minimum pressure**: This setting determines the relative pressure or sensitivity of the FT62x6 touch displays. Lower values make it more sensitive. The range is 0 to 255. Only applicable for the FT62x6 controller.
* **Touchscreen Type (Address)**: Select the type of touchscreen installed, available options:
.. image:: P123_TouchscreenTypeOptions.png
* *FT62x6 (0x38)*: Focaltech FT62x6/FT63x6/FT52x6 touchscreen controller family. Default selection.
* *GT911 (0x5D)*: GT911 touchscreen controller, default address.
* *GT911 (0x14)*: GT911 touchscreen controller, alternate address.
* *CST820 (0x15)*: CST816/CST820 touchscreen controller family.
* *CST226 (0x5A)*: CST226 touchscreen controller. (Not yet tested on real hardware)
* *AXS15231 (0x3B)*: AXS15231 touchscreen controller. (Not yet tested on real hardware)
* *CHSC5816 (0x2E)*: CHSC5816 touchscreen controller. (Not yet tested on real hardware)
* *Auto-detect*: Select this option to have the plugin auto-detect the used touchscreen controller. This auto-detect is mostly based on an I2C device being available at the shown addresses, so might get confused if a non-touchscreen I2C device at one of these addresses is installed.
|
* **Interrupt pin**: Select the GPIO that is connected to the IRQ connection of a GT911 touchscreen controller. The IRQ pin is only used for detection & address configuration, combined with the **Reset pin**, if available and configured. Only used for GT911 controller.
* **Reset pin**: Select the GPIO that is connected to the Reset connection of the touchscreen controller. When set, this will be used to reset the controller during initialization. (See the Warning below). Do not set this GPIO setting if the RST pin is shared with another device, like on a WT32 SC01 Plus, where the display and touch controllers use the same GPIO pin. **Only** set the RST pin on the display configuration, and give that Display task a **lower task number** than the touch screen, as the touchscreen task will try to display defined objects on the connected Display device!
.. note:: The **Interrupt** and **Reset** GPIO pins are optional. Interrupt is only used by the GT911 controller during initialization.
.. warning:: Some devices that have the reset pin connected, initially set that GPIO to low/0, causing the touch controller not to start, and it won't even show up on the I2C Scan. This can be solved by setting the involved GPIO pin to **Output High** on the :ref:`Hardware_page`.
.. warning:: During testing we found that specifically the CST816 touchscreen controller, whiel working as expected, **doesn't** show up in an I2C Scan. This also implies they can't be auto-detected, and have to be set explicitly.
.. include:: Touch_Configuration.repl
@@ -70,8 +102,7 @@ Change log
.. versionadded:: 2.0
...
|added|
Initial release version.
|added| 2024-06-05 Initial release version.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

@@ -90,20 +90,26 @@ Build set: :yellow:`COLLECTION A`
":ref:`P004_page`","P004"
":ref:`P005_page`","P005"
":ref:`P006_page`","P006"
":ref:`P007_page`","P007"
":ref:`P008_page`","P008"
":ref:`P009_page`","P009"
":ref:`P010_page`","P010"
":ref:`P011_page`","P011"
":ref:`P012_page`","P012"
":ref:`P013_page`","P013"
":ref:`P014_page`","P014"
":ref:`P015_page`","P015"
":ref:`P017_page`","P017"
":ref:`P018_page`","P018"
":ref:`P019_page`","P019"
":ref:`P020_page`","P020"
":ref:`P021_page`","P021"
":ref:`P022_page`","P022"
":ref:`P023_page`","P023"
":ref:`P024_page`","P024"
":ref:`P025_page`","P025"
":ref:`P026_page`","P026"
":ref:`P027_page`","P027"
":ref:`P028_page`","P028"
":ref:`P029_page`","P029"
":ref:`P031_page`","P031"
@@ -114,6 +120,9 @@ Build set: :yellow:`COLLECTION A`
":ref:`P037_page`","P037"
":ref:`P038_page`","P038"
":ref:`P039_page`","P039"
":ref:`P040_page`","P040"
":ref:`P041_page`","P041"
":ref:`P042_page`","P042"
":ref:`P043_page`","P043"
":ref:`P044_page`","P044"
":ref:`P045_page`","P045"
@@ -522,20 +531,26 @@ Build set: :yellow:`COLLECTION E`
":ref:`P004_page`","P004"
":ref:`P005_page`","P005"
":ref:`P006_page`","P006"
":ref:`P007_page`","P007"
":ref:`P008_page`","P008"
":ref:`P009_page`","P009"
":ref:`P010_page`","P010"
":ref:`P011_page`","P011"
":ref:`P012_page`","P012"
":ref:`P013_page`","P013"
":ref:`P014_page`","P014"
":ref:`P015_page`","P015"
":ref:`P017_page`","P017"
":ref:`P018_page`","P018"
":ref:`P019_page`","P019"
":ref:`P020_page`","P020"
":ref:`P021_page`","P021"
":ref:`P022_page`","P022"
":ref:`P023_page`","P023"
":ref:`P024_page`","P024"
":ref:`P025_page`","P025"
":ref:`P026_page`","P026"
":ref:`P027_page`","P027"
":ref:`P028_page`","P028"
":ref:`P029_page`","P029"
":ref:`P031_page`","P031"
@@ -546,6 +561,9 @@ Build set: :yellow:`COLLECTION E`
":ref:`P037_page`","P037"
":ref:`P038_page`","P038"
":ref:`P039_page`","P039"
":ref:`P040_page`","P040"
":ref:`P041_page`","P041"
":ref:`P042_page`","P042"
":ref:`P043_page`","P043"
":ref:`P044_page`","P044"
":ref:`P045_page`","P045"
@@ -976,6 +994,7 @@ Build set: :yellow:`DISPLAY`
":ref:`P104_page`","P104"
":ref:`P109_page`","P109"
":ref:`P116_page`","P116"
":ref:`P123_page`","P123"
":ref:`P137_page`","P137"
":ref:`P138_page`","P138"
":ref:`P141_page`","P141"
@@ -1096,6 +1115,9 @@ Build set: :yellow:`IR`
":ref:`P004_page`","P004"
":ref:`P005_page`","P005"
":ref:`P006_page`","P006"
":ref:`P007_page`","P007"
":ref:`P008_page`","P008"
":ref:`P009_page`","P009"
":ref:`P010_page`","P010"
":ref:`P011_page`","P011"
":ref:`P012_page`","P012"
@@ -1103,14 +1125,17 @@ Build set: :yellow:`IR`
":ref:`P014_page`","P014"
":ref:`P015_page`","P015"
":ref:`P016_page`","P016"
":ref:`P017_page`","P017"
":ref:`P018_page`","P018"
":ref:`P019_page`","P019"
":ref:`P020_page`","P020"
":ref:`P021_page`","P021"
":ref:`P022_page`","P022"
":ref:`P023_page`","P023"
":ref:`P024_page`","P024"
":ref:`P025_page`","P025"
":ref:`P026_page`","P026"
":ref:`P027_page`","P027"
":ref:`P028_page`","P028"
":ref:`P029_page`","P029"
":ref:`P031_page`","P031"
@@ -1122,6 +1147,9 @@ Build set: :yellow:`IR`
":ref:`P037_page`","P037"
":ref:`P038_page`","P038"
":ref:`P039_page`","P039"
":ref:`P040_page`","P040"
":ref:`P041_page`","P041"
":ref:`P042_page`","P042"
":ref:`P043_page`","P043"
":ref:`P044_page`","P044"
":ref:`P049_page`","P049"
@@ -1236,20 +1264,26 @@ Build set: :yellow:`NEOPIXEL`
":ref:`P004_page`","P004"
":ref:`P005_page`","P005"
":ref:`P006_page`","P006"
":ref:`P007_page`","P007"
":ref:`P008_page`","P008"
":ref:`P009_page`","P009"
":ref:`P010_page`","P010"
":ref:`P011_page`","P011"
":ref:`P012_page`","P012"
":ref:`P013_page`","P013"
":ref:`P014_page`","P014"
":ref:`P015_page`","P015"
":ref:`P017_page`","P017"
":ref:`P018_page`","P018"
":ref:`P019_page`","P019"
":ref:`P020_page`","P020"
":ref:`P021_page`","P021"
":ref:`P022_page`","P022"
":ref:`P023_page`","P023"
":ref:`P024_page`","P024"
":ref:`P025_page`","P025"
":ref:`P026_page`","P026"
":ref:`P027_page`","P027"
":ref:`P028_page`","P028"
":ref:`P029_page`","P029"
":ref:`P031_page`","P031"
@@ -1260,6 +1294,7 @@ Build set: :yellow:`NEOPIXEL`
":ref:`P037_page`","P037"
":ref:`P038_page`","P038"
":ref:`P039_page`","P039"
":ref:`P040_page`","P040"
":ref:`P041_page`","P041"
":ref:`P042_page`","P042"
":ref:`P043_page`","P043"
@@ -1421,6 +1456,7 @@ Build set: :yellow:`MAX`
":ref:`P120_page`","P120"
":ref:`P121_page`","P121"
":ref:`P122_page`","P122"
":ref:`P123_page`","P123"
":ref:`P124_page`","P124"
":ref:`P125_page`","P125"
":ref:`P126_page`","P126"
@@ -37,18 +37,18 @@
.. |P122_compileinfo| replace:: `.`
.. |P122_usedlibraries| replace:: `I2C`
.. |P123_name| replace:: :cyan:`FT62x6`
.. |P123_name| replace:: :cyan:`I2C Touchscreens`
.. |P123_type| replace:: :cyan:`Touch`
.. |P123_typename| replace:: :cyan:`Touch - FT62x6`
.. |P123_typename| replace:: :cyan:`Touch - I2C Touchscreens`
.. |P123_porttype| replace:: `.`
.. |P123_status| replace:: :yellow:`DISPLAY`
.. |P123_github| replace:: P123_FT62x6Touch.ino
.. _P123_github: https://github.com/letscontrolit/ESPEasy/blob/mega/src/_P123_FT62x6Touch.ino
.. |P123_github| replace:: P123_I2CTouch.ino
.. _P123_github: https://github.com/letscontrolit/ESPEasy/blob/mega/src/_P123_I2CTouch.ino
.. |P123_usedby| replace:: `.`
.. |P123_shortinfo| replace:: `FT62x6 Display capacitive touch overlay`
.. |P123_shortinfo| replace:: `I2C capacitive touchscreen overlays`
.. |P123_maintainer| replace:: `tonhuisman`
.. |P123_compileinfo| replace:: `.`
.. |P123_usedlibraries| replace:: `Adafruit_FT6206_Library (modified)`
.. |P123_usedlibraries| replace:: `BitBank bb_captouch library (modified)`
.. |P124_name| replace:: :cyan:`MultiRelay`
.. |P124_type| replace:: :cyan:`Output`
@@ -1,313 +0,0 @@
/*!
* @file Adafruit_FT6206.cpp
*
* @mainpage Adafruit FT2606 Library
*
* @section intro_sec Introduction
*
* This is a library for the Adafruit Capacitive Touch Screens
*
* ----> http://www.adafruit.com/products/1947
*
* Adjustment: To avoid a conflict with the XPT2048 library, TS_Point struct is renamed to FT_Point
*
* Check out the links above for our tutorials and wiring diagrams
* This chipset uses 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 <Adafruit_FT6206.h>
#include <Wire.h>
#if defined(__SAM3X8E__)
#define Wire Wire1
#endif
//#define FT6206_DEBUG
//#define I2C_DEBUG
/**************************************************************************/
/*!
@brief Instantiates a new FT6206 class
*/
/**************************************************************************/
// I2C, no address adjustments or pins
Adafruit_FT6206::Adafruit_FT6206() { touches = 0; }
/**************************************************************************/
/*!
@brief Setups the I2C interface and hardware, identifies if chip is found
@param thresh Optional threshhold-for-touch value, default is
FT6206_DEFAULT_THRESSHOLD but you can try changing it if your screen is
too/not sensitive.
@returns True if an FT6206 is found, false on any failure
*/
/**************************************************************************/
boolean Adafruit_FT6206::begin(uint8_t thresh) {
// Wire.begin();
#ifdef FT6206_DEBUG
Serial.print("Vend ID: 0x");
Serial.println(readRegister8(FT62XX_REG_VENDID), HEX);
Serial.print("Chip ID: 0x");
Serial.println(readRegister8(FT62XX_REG_CHIPID), HEX);
Serial.print("Firm V: ");
Serial.println(readRegister8(FT62XX_REG_FIRMVERS));
Serial.print("Point Rate Hz: ");
Serial.println(readRegister8(FT62XX_REG_POINTRATE));
Serial.print("Thresh: ");
Serial.println(readRegister8(FT62XX_REG_THRESHHOLD));
// dump all registers
for (int16_t i = 0; i < 0x10; i++) {
Serial.print("I2C $");
Serial.print(i, HEX);
Serial.print(" = 0x");
Serial.println(readRegister8(i), HEX);
}
#endif
// change threshhold to be higher/lower
writeRegister8(FT62XX_REG_THRESHHOLD, thresh);
if (readRegister8(FT62XX_REG_VENDID) != FT62XX_VENDID) {
return false;
}
_id = readRegister8(FT62XX_REG_CHIPID);
if ((_id != FT6206_CHIPID) && (_id != FT6236_CHIPID) &&
(_id != FT6236U_CHIPID) && (_id != FT5316_CHIPID)) {
return false;
}
return true;
}
/**************************************************************************/
/*!
@brief Determines if there are any touches detected
@returns Number of touches detected, can be 0, 1 or 2
*/
/**************************************************************************/
uint8_t Adafruit_FT6206::touched(void) {
if (_id == FT5316_CHIPID) {
uint8_t val = readRegister8(FT62XX_REG_MODE);
if (val) {
// wrong mode
val = 0;
writeRegister8(FT62XX_REG_MODE, val);
}
}
uint8_t n = readRegister8(FT62XX_REG_NUMTOUCHES);
if (n > 2) {
n = 0;
}
return n;
}
/**************************************************************************/
/*!
@brief Queries the chip and retrieves a point data
@param n The # index (0 or 1) to the points we can detect. In theory we can
detect 2 points but we've found that you should only use this for
single-touch since the two points cant share the same half of the screen.
@returns {@link FT_Point} object that has the x and y coordinets set. If the
z coordinate is 0 it means the point is not touched. If z is 1, it is
currently touched.
*/
/**************************************************************************/
FT_Point Adafruit_FT6206::getPoint(uint8_t n) {
readData();
if ((touches == 0) || (n > 1)) {
return FT_Point(0, 0, 0);
} else {
return FT_Point(touchX[n], touchY[n], 1);
}
}
/************ lower level i/o **************/
/**************************************************************************/
/*!
@brief Reads the bulk of data from captouch chip. Fill in {@link touches},
{@link touchX}, {@link touchY} and {@link touchID} with results
*/
/**************************************************************************/
void Adafruit_FT6206::readData(void) {
uint8_t i2cdat[16];
Wire.beginTransmission(FT62XX_ADDR);
Wire.write((byte)0);
Wire.endTransmission();
Wire.requestFrom((byte)FT62XX_ADDR, (byte)16);
for (uint8_t i = 0; i < 16; i++)
i2cdat[i] = Wire.read();
#ifdef FT6206_DEBUG
for (int16_t i = 0; i < 16; i++) {
Serial.print("I2C $");
Serial.print(i, HEX);
Serial.print(" = 0x");
Serial.println(i2cdat[i], HEX);
}
#endif
touches = i2cdat[0x02];
if ((touches > 2) || (touches == 0)) {
touches = 0;
}
#ifdef FT6206_DEBUG
Serial.print("# Touches: ");
Serial.println(touches);
for (uint8_t i = 0; i < 16; i++) {
Serial.print("0x");
Serial.print(i2cdat[i], HEX);
Serial.print(" ");
}
Serial.println();
if (i2cdat[0x01] != 0x00) {
Serial.print("Gesture #");
Serial.println(i2cdat[0x01]);
}
#endif
for (uint8_t i = 0; i < 2; i++) {
touchX[i] = i2cdat[0x03 + i * 6] & 0x0F;
touchX[i] <<= 8;
touchX[i] |= i2cdat[0x04 + i * 6];
touchY[i] = i2cdat[0x05 + i * 6] & 0x0F;
touchY[i] <<= 8;
touchY[i] |= i2cdat[0x06 + i * 6];
touchID[i] = i2cdat[0x05 + i * 6] >> 4;
}
#ifdef FT6206_DEBUG
Serial.println();
for (uint8_t i = 0; i < touches; i++) {
Serial.print("ID #");
Serial.print(touchID[i]);
Serial.print("\t(");
Serial.print(touchX[i]);
Serial.print(", ");
Serial.print(touchY[i]);
Serial.print(") ");
}
Serial.println();
#endif
}
uint8_t Adafruit_FT6206::readRegister8(uint8_t reg) {
uint8_t x;
// use i2c
Wire.beginTransmission(FT62XX_ADDR);
Wire.write((byte)reg);
Wire.endTransmission();
Wire.requestFrom((byte)FT62XX_ADDR, (byte)1);
x = Wire.read();
#ifdef I2C_DEBUG
Serial.print("$");
Serial.print(reg, HEX);
Serial.print(": 0x");
Serial.println(x, HEX);
#endif
return x;
}
void Adafruit_FT6206::writeRegister8(uint8_t reg, uint8_t val) {
// use i2c
Wire.beginTransmission(FT62XX_ADDR);
Wire.write((byte)reg);
Wire.write((byte)val);
Wire.endTransmission();
}
/*
// DONT DO THIS - REALLY - IT DOESNT WORK
void Adafruit_FT6206::autoCalibrate(void) {
writeRegister8(FT06_REG_MODE, FT6206_REG_FACTORYMODE);
delay(100);
//Serial.println("Calibrating...");
writeRegister8(FT6206_REG_CALIBRATE, 4);
delay(300);
for (uint8_t i = 0; i < 100; i++) {
uint8_t temp;
temp = readRegister8(FT6206_REG_MODE);
Serial.println(temp, HEX);
//return to normal mode, calibration finish
if (0x0 == ((temp & 0x70) >> 4))
break;
}
delay(200);
//Serial.println("Calibrated");
delay(300);
writeRegister8(FT6206_REG_MODE, FT6206_REG_FACTORYMODE);
delay(100);
writeRegister8(FT6206_REG_CALIBRATE, 5);
delay(300);
writeRegister8(FT6206_REG_MODE, FT6206_REG_WORKMODE);
delay(300);
}
*/
/****************/
/**************************************************************************/
/*!
@brief Instantiates a new FT6206 class with x, y and z set to 0 by default
*/
/**************************************************************************/
FT_Point::FT_Point(void) { x = y = z = 0; }
/**************************************************************************/
/*!
@brief Instantiates a new FT6206 class with x, y and z set by params.
@param _x The X coordinate
@param _y The Y coordinate
@param _z The Z coordinate
*/
/**************************************************************************/
FT_Point::FT_Point(int16_t _x, int16_t _y, int16_t _z) {
x = _x;
y = _y;
z = _z;
}
/**************************************************************************/
/*!
@brief Simple == comparator for two FT_Point objects
@returns True if x, y and z are the same for both points, False otherwise.
*/
/**************************************************************************/
bool FT_Point::operator==(FT_Point p1) {
return ((p1.x == x) && (p1.y == y) && (p1.z == z));
}
/**************************************************************************/
/*!
@brief Simple != comparator for two FT_Point objects
@returns False if x, y and z are the same for both points, True otherwise.
*/
/**************************************************************************/
bool FT_Point::operator!=(FT_Point p1) {
return ((p1.x != x) || (p1.y != y) || (p1.z != z));
}
@@ -1,81 +0,0 @@
/*!
* @file Adafruit_FT6206.h
*/
#ifndef ADAFRUIT_FT6206_LIBRARY
#define ADAFRUIT_FT6206_LIBRARY
#include "Arduino.h"
#include <Wire.h>
#define FT62XX_ADDR 0x38 //!< I2C address
#define FT62XX_G_FT5201ID 0xA8 //!< FocalTech's panel ID
#define FT62XX_REG_NUMTOUCHES 0x02 //!< Number of touch points
#define FT62XX_NUM_X 0x33 //!< Touch X position
#define FT62XX_NUM_Y 0x34 //!< Touch Y position
#define FT62XX_REG_MODE 0x00 //!< Device mode, either WORKING or FACTORY
#define FT62XX_REG_CALIBRATE 0x02 //!< Calibrate mode
#define FT62XX_REG_WORKMODE 0x00 //!< Work mode
#define FT62XX_REG_FACTORYMODE 0x40 //!< Factory mode
#define FT62XX_REG_THRESHHOLD 0x80 //!< Threshold for touch detection
#define FT62XX_REG_POINTRATE 0x88 //!< Point rate
#define FT62XX_REG_FIRMVERS 0xA6 //!< Firmware version
#define FT62XX_REG_CHIPID 0xA3 //!< Chip selecting
#define FT62XX_REG_VENDID 0xA8 //!< FocalTech's panel ID
#define FT62XX_VENDID 0x11 //!< FocalTech's vendor ID
#define FT6206_CHIPID 0x06 //!< Chip selecting
#define FT6236_CHIPID 0x36 //!< Chip selecting
#define FT6236U_CHIPID 0x64 //!< Chip selecting
#define FT5316_CHIPID 0x0A //!< Chip selecting
// calibrated for Adafruit 2.8" ctp screen
#define FT62XX_DEFAULT_THRESHOLD 128 //!< Default threshold for touch detection
/**************************************************************************/
/*!
@brief Helper class that stores a TouchScreen Point with x, y, and z
coordinates, for easy math/comparison
*/
/**************************************************************************/
class FT_Point {
public:
FT_Point(void);
FT_Point(int16_t x, int16_t y, int16_t z);
bool operator==(FT_Point);
bool operator!=(FT_Point);
int16_t x; /*!< X coordinate */
int16_t y; /*!< Y coordinate */
int16_t z; /*!< Z coordinate (often used for pressure) */
};
/**************************************************************************/
/*!
@brief Class that stores state and functions for interacting with FT6206
capacitive touch chips
*/
/**************************************************************************/
class Adafruit_FT6206 {
public:
Adafruit_FT6206(void);
boolean begin(uint8_t thresh = FT62XX_DEFAULT_THRESHOLD);
uint8_t touched(void);
FT_Point getPoint(uint8_t n = 0);
// void autoCalibrate(void);
private:
void writeRegister8(uint8_t reg, uint8_t val);
uint8_t readRegister8(uint8_t reg);
void readData(void);
uint8_t touches;
uint8_t _id = 0;
uint16_t touchX[2], touchY[2], touchID[2];
};
#endif // ADAFRUIT_FT6206_LIBRARY
-17
View File
@@ -1,17 +0,0 @@
# Adafruit_FT6206 Library [![Build Status](https://github.com/adafruit/Adafruit_FT6206_Library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_FT6206_Library/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_FT6206_Library/html/index.html)
<img src="https://cdn-shop.adafruit.com/970x728/1947-05.jpg" height="300"/>
This is a library for the Adafruit FT6206-Based capacitive touch screens and displays:
* https://www.adafruit.com/products/1947
* https://www.adafruit.com/product/1651
Also supports FT6236 chips (and maybe other compatible chips!)
Check out the links above for our tutorials and wiring diagrams. This chip uses 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!
Written by Limor Fried/Ladyada for Adafruit Industries.
MIT license, all text above must be included in any redistribution
@@ -1,10 +0,0 @@
name=Adafruit FT6206 ESPEasy
version=1.0.6
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for FT6206-based Capacitive touch screen adjusted for use in ESPEasy
paragraph=Arduino library for FT6206-based Capacitive touch screen adjusted for use in ESPEasy
category=Display
url=https://github.com/adafruit/Adafruit_FT6206_Library
architectures=*
depends=Adafruit GFX Library
+204
View File
@@ -0,0 +1,204 @@
Copyright 2020 BitBank Software, Inc. All rights reserved.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+27
View File
@@ -0,0 +1,27 @@
BitBank Capacitive Touch Sensor Library<br>
---------------------------------------
Copyright (c) 2023 BitBank Software, Inc.<br>
Written by Larry Bank<br>
email: bitbank@pobox.com<br>
<br>
There are a growing list of development boards which include LCDs with capacitive touch plates on them. These are overwhelmingly controlled by different versions of the ESP32 MCU. The boards normally only utilize GOODiX and FocalTech capacitive touch controllers and this library supports the CST820, GT911 and FT6x36 in a generic way. Each has different capabilities and usually come pre-programmed for the specific pixel width and height of the target application. A feature supported by this library that may not be present in the device you're using is the touch area and pressure values. Some of their controllers also have built-in gesture detection. The common features of the controllers is that they will generate an interrupt signal when a touch event is occurring. This library allows you to request the latest touch information and it returns the number of active touch points (0-5) along with the coordinates (and pressure/area of each if available). The sensor type and address is auto-detected when calling the init() method. The only info that must be correctly supplied to the library are the GPIO pins used for the SDA/SCL/INT/RESET signals. Once initialized, repeatedly call getSamples() to test for and read any touch samples available.<br>
There are only 3 methods exposed by the class:<br>
init() - detects if a supported CT controller is available and initializes it<br>
getSamples() - returns touch points if available<br>
sensorType() - returns an enumerated value of the sensor detected<>
Here is the TOUCHINFO structure filled by the getSamples() method:<br>
```
typedef struct _fttouchinfo
{
int count;
uint16_t x[5], y[5];
uint8_t pressure[5], area[5];
} TOUCHINFO;
```
If you find this code useful, please consider becoming a sponsor or sending a donation.
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SR4F44J2UR8S4)
@@ -0,0 +1,138 @@
#include <bb_captouch.h>
//#include <OneBitDisplay.h>
#include <bb_spi_lcd.h>
#include <bb_scd41.h>
#include <Wire.h>
//ONE_BIT_DISPLAY obd;
SCD41 co2;
//#define CYD_128C
//#define LILYGO_S3_PRO
#define LILYGO_S3_LONG
#ifdef LILYGO_S3_LONG
#define TOUCH_SDA 15
#define TOUCH_SCL 10
#define TOUCH_INT 11
// reset is 16, but it's shared with the LCD
#define TOUCH_RST -1
#define LCD DISPLAY_T_DISPLAY_S3_LONG
#endif
#ifdef LILYGO_S3_PRO
#define TOUCH_SDA 5
#define TOUCH_SCL 6
#define TOUCH_INT 7
#define TOUCH_RST 13
#define LCD DISPLAY_T_DISPLAY_S3_PRO
#endif
#ifdef CYD_28C
// These defines are for a low cost 2.8" ESP32 LCD board with the GT911 touch controller
#define TOUCH_SDA 33
#define TOUCH_SCL 32
#define TOUCH_INT 21
#define TOUCH_RST 25
#define LCD DISPLAY_CYD
#endif
#ifdef CYD_128C
// These defines are for a low cost 1.28" ESP32-C3 round LCD board with the CST816D touch controller
#define TOUCH_SDA 4
#define TOUCH_SCL 5
#define TOUCH_INT 0
#define TOUCH_RST 1
#define QWIIC_SDA 21
#define QWIIC_SCL 20
#define LCD DISPLAY_CYD_128
#endif
#ifdef ARDUINO_M5STACK_CORES3
#define TOUCH_SDA 12
#define TOUCH_SCL 11
#define TOUCH_INT -1
#define TOUCH_RST -1
#define LCD DISPLAY_M5STACK_CORES3
#endif // CORES3
BBCapTouch bbct;
BB_SPI_LCD lcd;
int iWidth, iHeight;
const char *szNames[] = {"Unknown", "FT6x36", "GT911", "CST820", "CST226", "AXS15231"};
void setup() {
Serial.begin(115200);
while (!Serial) {};
lcd.begin(LCD);
Serial.println("Starting...");
// obd.setI2CPins(QWIIC_SDA, QWIIC_SCL);
// obd.setBitBang(true);
// obd.I2Cbegin(OLED_128x64);
// obd.fillScreen(OBD_WHITE);
// obd.setFont(FONT_12x16);
// obd.println("QWIIC OLED");
iWidth = lcd.width();
iHeight = lcd.height();
Serial.printf("LCD size = %dx%d\n", iWidth, iHeight);
lcd.fillScreen(TFT_BLACK);
lcd.setTextColor(TFT_GREEN, TFT_BLACK);
lcd.setFont(FONT_8x8);
lcd.setCursor(0, 0);
lcd.println("CYD Touch Test");
delay(1000);
Wire.end();
//Wire1.end();
bbct.init(TOUCH_SDA, TOUCH_SCL, TOUCH_RST, TOUCH_INT);
int iType = bbct.sensorType();
Serial.printf("Sensor type = %s\n", szNames[iType]);
#ifdef OLD_STUFF
if (co2.init(QWIIC_SDA, QWIIC_SCL, 1, 100000) == SCD41_SUCCESS) {
// Serial.println("Found SCD41 sensor!");
co2.start(); // start sampling mode
lcd.println("SCD41 found!");
} else { // can't find the sensor, stop
lcd.println("SCD41 sensor not found");
lcd.println("Check your connections");
lcd.println("\nstopping...");
while (1) {};
} // no sensor connected or some error
#endif
} /* setup() */
void loop() {
#ifndef OLD_STUFF
int i;
TOUCHINFO ti;
while (1) {
if (bbct.getSamples(&ti)) {
for (int i=0; i<ti.count; i++){
Serial.print("Touch ");Serial.print(i+1);Serial.print(": ");;
Serial.print(" x: ");Serial.print(ti.x[i]);
Serial.print(" y: ");Serial.print(ti.y[i]);
Serial.print(" size: ");Serial.println(ti.area[i]);
Serial.println(' ');
lcd.fillCircle(iWidth-1-ti.y[i], ti.x[i], 3, (i == 0) ? TFT_BLUE : TFT_RED);
} // for each touch point
} // if touch event happened
} // while (1)
#else
char szTemp[64];
int i, iCO2;
delay(5000); // 5 seconds per reading
// The SCD41 takes 5 seconds to return a sample in this mode
co2.getSample();
iCO2 = co2.co2();
lcd.setCursor(0, 100);
lcd.println(iCO2);
sprintf(szTemp, "Temperature %dC ", co2.temperature());
lcd.println(co2.temperature());
lcd.println(szTemp);
sprintf(szTemp, "Humidity %d%%", co2.humidity());
lcd.println(co2.humidity());
lcd.println(szTemp);
#endif
} /* loop() */
+11
View File
@@ -0,0 +1,11 @@
name=bb_captouch
version=1.1.1
author=Larry Bank
maintainer=Larry Bank, Ton Huisman
sentence=Capacitive touch sensor library for FT6x36 and GT911 I2C devices. Adjusted for ESPEasy use.
paragraph=ESP32 specific code supports 1 to 5 point touch on the FT6x36 and GT911 sensors. It auto-detects the address and sensor type.
category=Communication
url=https://github.com/bitbank2/bb_captouch
architectures=esp32,esp8266
includes=bb_captouch.h
depends=
+454
View File
@@ -0,0 +1,454 @@
//
// BitBank Capactive Touch Sensor Library
// Written by Larry Bank
//
// Copyright 2023 BitBank Software, Inc. All Rights Reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ===========================================================================
#include "bb_captouch.h"
void BBCapTouch::reset(int iRST) {
pinMode(iRST, OUTPUT);
digitalWrite(iRST, LOW);
delay(100);
digitalWrite(iRST, HIGH);
delay(100);
} /* reset() */
//
// Initialize the library
// It only needs to initialize the I2C interface; the chip is ready // ESPEasy: I2C is already ready
//
int BBCapTouch::init(int iSDA, int iSCL, int iRST, int iINT, uint32_t u32Speed) {
if (_iType != CT_TYPE_UNKNOWN) { return CT_SUCCESS; } // Already set, exit
// Wire.begin(iSDA, iSCL); // this is specific to ESP32 MCUs // ESPEasy doesn't allow this
// Wire.setClock(u32Speed);
#ifdef ESP32
unsigned long orgTimeout = Wire.getTimeout();
Wire.setTimeout(100);
#endif // ifdef ESP32
_iType = CT_TYPE_UNKNOWN;
if (I2CTest(AXS15231_ADDR)) {
_iType = CT_TYPE_AXS15231;
_iAddr = AXS15231_ADDR;
if (iRST != -1) {
reset(iRST);
}
} // AXS15231
else if (I2CTest(CST226_ADDR)) { // CST226
_iType = CT_TYPE_CST226;
_iAddr = CST226_ADDR;
if (iINT != -1) {
pinMode(iINT, INPUT);
}
if (iRST != -1) {
reset(iRST);
}
} // CST226
if (I2CTest(GT911_ADDR1) || I2CTest(GT911_ADDR2)) { // GT911
_iType = CT_TYPE_GT911;
}
if (_iType == CT_TYPE_GT911) { // reset the sensor to start it
if ((-1 != iRST) && (-1 != iINT)) {
pinMode(iRST, OUTPUT);
pinMode(iINT, OUTPUT);
digitalWrite(iINT, LOW);
digitalWrite(iRST, LOW);
delay(5);
digitalWrite(iINT, LOW); // set I2C addr to ADDR1
delay(1);
digitalWrite(iRST, HIGH); // when it comes out of reset, it samples INT
delay(10);
digitalWrite(iINT, LOW);
delay(50);
pinMode(iINT, INPUT);
}
// double check the I2C addr in case it changed
if (I2CTest(GT911_ADDR1)) {
_iAddr = GT911_ADDR1;
} else if (I2CTest(GT911_ADDR2)) {
_iAddr = GT911_ADDR2;
}
} // GT911
else if (I2CTest(FT6X36_ADDR)) { // FT62x6
// Check Vendor ID and get Chip ID
uint8_t ucTemp[1]{};
I2CReadRegister(FT6X36_ADDR, TOUCH_REG_VENDID, ucTemp, 1); // Check the Vendor ID reg
if (ucTemp[0] != FT62XX_VENDID) {
return CT_ERROR;
}
I2CReadRegister(FT6X36_ADDR, TOUCH_REG_CHIPID, ucTemp, 1); // read the Chip ID reg
_id = ucTemp[0]; // Chip ID only read to be used for FT5316
_iType = CT_TYPE_FT6X36;
_iAddr = FT6X36_ADDR;
if (iRST != -1) {
reset(iRST);
}
if (_thresh > -1) {
uint8_t ucsetThresh[2] = { 0x80, (uint8_t)_thresh }; // 0x80 = FT62XX_REG_THRESHOLD
I2CWrite(_iAddr, (uint8_t *)ucsetThresh, 2);
}
} // FT62x6
else if (I2CTest(CST820_ADDR)) { // CST820
_iType = CT_TYPE_CST820;
_iAddr = CST820_ADDR;
if (iRST != -1) {
reset(iRST);
}
} // CST820
else if (I2CTest(CHSC5816_ADDR)) { // CHSC5816
_iType = CT_TYPE_CHSC5816;
_iAddr = CHSC5816_ADDR;
if (iRST != -1) {
reset(iRST);
}
} // CHSC5816
#ifdef ESP32
Wire.setTimeout(orgTimeout); // ESPEasy: Restore original I2C timeout
#endif // ifdef ESP32
if (CT_TYPE_UNKNOWN == _iType) {
return CT_ERROR; // no device found
}
return CT_SUCCESS;
} /* init() */
//
// Test if an I2C device is monitoring an address
// return true if it responds, false if no response
//
bool BBCapTouch::I2CTest(uint8_t u8Addr) {
// Check if a device acknowledges the address.
Wire.beginTransmission(u8Addr);
return Wire.endTransmission(true) == 0;
} /* I2CTest() */
//
// Write I2C data
// quits if a NACK is received and returns 0
// otherwise returns the number of bytes written
//
int BBCapTouch::I2CWrite(uint8_t u8Addr, uint8_t *pData, int iLen) {
int rc = 0;
Wire.beginTransmission(u8Addr);
Wire.write(pData, (uint8_t)iLen);
rc = !Wire.endTransmission();
return rc;
} /* I2CWrite() */
//
// Read N bytes starting at a specific 16-bit I2C register
//
int BBCapTouch::I2CReadRegister16(uint8_t u8Addr, uint16_t u16Register, uint8_t *pData, int iLen) {
int i = 0;
Wire.beginTransmission(u8Addr);
Wire.write((uint8_t)(u16Register >> 8)); // high byte
Wire.write((uint8_t)u16Register); // low byte
Wire.endTransmission();
Wire.requestFrom(u8Addr, (uint8_t)iLen);
while (Wire.available() && i < iLen) {
pData[i++] = Wire.read();
}
return i;
} /* I2CReadRegister16() */
//
// Read N bytes starting at a specific I2C internal register
// returns 1 for success, 0 for error
//
int BBCapTouch::I2CReadRegister(uint8_t u8Addr, uint8_t u8Register, uint8_t *pData, int iLen) {
int i = 0;
Wire.beginTransmission(u8Addr);
Wire.write(u8Register);
Wire.endTransmission();
Wire.requestFrom(u8Addr, (uint8_t)iLen);
// i = Wire.readBytes(pData, iLen);
while (Wire.available() && i < iLen) {
pData[i++] = Wire.read();
}
return i;
} /* I2CReadRegister() */
//
// Read N bytes
//
int BBCapTouch::I2CRead(uint8_t u8Addr, uint8_t *pData, int iLen) {
int i = 0;
Wire.requestFrom(u8Addr, (uint8_t)iLen);
while (Wire.available() && i < iLen) {
pData[i++] = Wire.read();
}
return i;
} /* I2CRead() */
//
// Private function to rotate touch samples if the user
// specified a new display orientation
//
void BBCapTouch::fixSamples(TOUCHINFO *pTI) {
int i, x, y;
for (i = 0; i < pTI->count; ++i) {
switch (_iOrientation) {
case 90:
x = pTI->y[i];
y = _iWidth - 1 - pTI->x[i];
pTI->x[i] = x;
pTI->y[i] = y;
break;
case 180:
pTI->x[i] = _iWidth - 1 - pTI->x[i];
pTI->y[i] = _iHeight - 1 - pTI->y[i];
break;
case 270:
x = _iHeight - 1 - pTI->y[i];
y = pTI->x[i];
pTI->x[i] = x;
pTI->y[i] = y;
break;
default: // do nothing
break;
}
}
} /* fixSamples() */
//
// Read the touch points
// returns 0 (none), 1 if touch points are available
// The point count and info is returned in the TOUCHINFO structure
//
int BBCapTouch::getSamples(TOUCHINFO *pTI) {
uint8_t c, *s, ucTemp[32];
int i, j, rc;
if (!pTI) {
return 0;
}
pTI->count = 0;
if (_iType == CT_TYPE_AXS15231) { // AXS15231
uint8_t ucReadCMD[8] = { 0xb5, 0xab, 0xa5, 0x5a, 0, 0, 0, 0x8 };
I2CWrite(_iAddr, (uint8_t *)ucReadCMD, 8);
I2CRead(_iAddr, ucTemp, 14); // read up to 2 touch points
c = ucTemp[1]; // number of touch points
if ((c == 0) || (c > 2) || (ucTemp[0] != 0)) { return 0; }
pTI->count = c;
j = 0; // buffer offset
for (i = 0; i < c; i++) {
pTI->x[i] = ((ucTemp[j + 2] & 0xf) << 8) + ucTemp[j + 3];
pTI->y[i] = ((ucTemp[j + 4] & 0xf) << 8) + ucTemp[j + 5];
pTI->area[i] = 1;
j += 6;
}
if (_iOrientation != 0) { fixSamples(pTI); }
return c > 0;
} // AXS15231
if (_iType == CT_TYPE_CST226) { // CST226
i = I2CReadRegister(_iAddr, 0, ucTemp, 28); // read the whole block of regs
if ((ucTemp[0] == 0x83) && (ucTemp[1] == 0x17) && (ucTemp[5] == 0x80)) {
// home button pressed
return 0;
}
if (ucTemp[6] != 0xab) { return 0; }
if (ucTemp[0] == 0xab) { return 0; }
if (ucTemp[5] == 0x80) { return 0; }
c = ucTemp[5] & 0x7f;
if ((c > 5) || (c == 0)) { // invalid point count
ucTemp[0] = 0;
ucTemp[1] = 0xab;
I2CWrite(_iAddr, ucTemp, 2); // reset
return 0;
}
pTI->count = c;
j = 0;
for (i = 0; i < c; i++) {
pTI->x[i] = (uint16_t)((ucTemp[j + 1] << 4) | ((ucTemp[j + 3] >> 4) & 0xf));
pTI->y[i] = (uint16_t)((ucTemp[j + 2] << 4) | (ucTemp[j + 3] & 0xf));
pTI->pressure[i] = ucTemp[j + 4];
j = (i == 0) ? (j + 7) : (j + 5);
}
if (_iOrientation != 0) { fixSamples(pTI); }
return c > 0;
} // CST226
if (_iType == CT_TYPE_CST820) { // CST820
I2CReadRegister(_iAddr, CST820_TOUCH_REGS + 1, ucTemp, 1); // read touch count
if ((ucTemp[0] < 1) || (ucTemp[0] > 5)) { // something went wrong
return 0;
}
pTI->count = ucTemp[0];
I2CReadRegister(_iAddr, CST820_TOUCH_REGS + 2, ucTemp, pTI->count * 6);
s = ucTemp;
for (i = 0; i < pTI->count; i++) {
pTI->x[i] = ((s[0] & 0xf) << 8) | s[1];
pTI->y[i] = ((s[2] & 0xf) << 8) | s[3];
pTI->area[i] = 1; // no data available
s += 6;
}
if (_iOrientation != 0) { fixSamples(pTI); }
return 1;
} // CST820
if (_iType == CT_TYPE_FT6X36) { // FT62x6
if (_id == FT5316_CHIPID) {
I2CReadRegister(_iAddr, TOUCH_REG_MODE, ucTemp, 1); // Handle specific issue
if (ucTemp[0]) {
// wrong mode
ucTemp[0] = TOUCH_REG_MODE;
ucTemp[1] = 0;
I2CWrite(_iAddr, ucTemp, 2);
}
}
rc = I2CReadRegister(_iAddr, TOUCH_REG_STATUS, ucTemp, 1); // read touch status
if (rc == 0) { // something went wrong
return 0;
}
i = ucTemp[0]; // number of touch points available
if (i > 0) { // get data, max. 2 points
rc = I2CReadRegister(_iAddr, TOUCH_REG_XH, ucTemp, 6 * i); // read X+Y position(s)
if (((ucTemp[0] & 0x40) == 0) && ((ucTemp[2] & 0xf0) != 0xf0)) { // finger is down
pTI->x[0] = ((ucTemp[0] & 0xf) << 8) | ucTemp[1];
pTI->y[0] = ((ucTemp[2] & 0xf) << 8) | ucTemp[3];
// get touch pressure and area
pTI->pressure[0] = ucTemp[4];
pTI->area[0] = ucTemp[5];
pTI->count++;
}
if (i > 1) { // get second point
if (((ucTemp[6] & 0x40) == 0) && ((ucTemp[8] & 0xf0) != 0xf0)) { // finger is down
pTI->x[1] = ((ucTemp[6] & 0xf) << 8) | ucTemp[7];
pTI->y[1] = ((ucTemp[8] & 0xf) << 8) | ucTemp[9];
// get touch pressure and area
pTI->pressure[1] = ucTemp[10];
pTI->area[1] = ucTemp[11];
pTI->count++;
}
}
} // if touch points available
if (_iOrientation != 0) { fixSamples(pTI); }
return i > 0;
} // FT62x6
else if (_iType == CT_TYPE_GT911) { // GT911
I2CReadRegister16(_iAddr, GT911_POINT_INFO, ucTemp, 1); // get number of touch points
i = ucTemp[0] & 0xf; // number of touches
if ((i <= 5) && ucTemp[0] & 0x80) { // if buffer status is good + >= 1 touch points
ucTemp[0] = (uint8_t)(GT911_POINT_INFO >> 8);
ucTemp[1] = (uint8_t)GT911_POINT_INFO;
ucTemp[2] = 0; // clear touch info for next time
I2CWrite(_iAddr, ucTemp, 3);
pTI->count = i;
for (int j = 0; j < i; j++) { // read each touch point block
I2CReadRegister16(_iAddr, GT911_POINT_1 + (j * 8), ucTemp, 7);
pTI->x[j] = ucTemp[1] + (ucTemp[2] << 8);
pTI->y[j] = ucTemp[3] + (ucTemp[4] << 8);
pTI->area[j] = ucTemp[5] + (ucTemp[6] << 8);
pTI->pressure[j] = 0;
}
if (i && (_iOrientation != 0)) { fixSamples(pTI); }
return i > 0;
}
} // GT911
else if (_iType == CT_TYPE_CHSC5816) { // CHSC5816
__CHSC5816_PointReg touch;
// CHSC5816_REG_POINT
uint8_t write_buffer[] = { 0x20, 0x00, 0x00, 0x2c };
I2CWrite(_iAddr, write_buffer, 4);
I2CRead(_iAddr, touch.data, 8);
if ((touch.rp.status == 0xFF) && (touch.rp.fingerNumber == 0)) {
return 0;
}
pTI->x[0] = static_cast<uint16_t>(touch.rp.x_h4 << 8) | touch.rp.x_l8;
pTI->y[0] = static_cast<uint16_t>(touch.rp.y_h4 << 8) | touch.rp.y_l8;
if (_iOrientation != 0) { fixSamples(pTI); }
return 1;
} // CHSC5816
return 0;
} /* getSamples() */
int BBCapTouch::setOrientation(int iOrientation, int iWidth, int iHeight) {
if ((iOrientation != 0) && (iOrientation != 90) && (iOrientation != 180) && (iOrientation != 270)) {
return CT_ERROR;
}
_iOrientation = iOrientation;
_iWidth = iWidth;
_iHeight = iHeight;
return CT_SUCCESS;
} /* setOrientation() */
void BBCapTouch::sensorType(int iType) {
_iType = iType;
}
void BBCapTouch::setI2CAddress(int i2caddr) {
_iAddr = i2caddr;
}
/**
* Threashold is used _during_ init() so should be set before init() is called.
*/
void BBCapTouch::setThreshold(int thresh) {
_thresh = thresh;
}
+187
View File
@@ -0,0 +1,187 @@
//
// BitBank Capacitive Touch Sensor Library
// written by Larry Bank
//
// Copyright 2023 BitBank Software, Inc. All Rights Reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ===========================================================================
//
// Written for the many variants of ESP32 + Capacitive touch LCDs on the market
//
// 2024-06-10 tonhuisman: Add support for CHSC5816 touchscreen, code borrowed from Lewis He SensorLib at
// https://github.com/lewisxhe/SensorLib
// 2024-06-02 tonhuisman: Fix FT62x6 to not return true when no data is read
// Formatted source using Uncrustify
// Adjust I2C handling so ESPEasy stays happy, ignoring SDA/SCL pins and I2C enable/disable
// ===========================================================================
#include <Arduino.h>
#include <Wire.h>
#ifndef __BB_CAPTOUCH__
# define __BB_CAPTOUCH__
# define CT_SUCCESS 0
# define CT_ERROR -1
enum {
CT_TYPE_UNKNOWN = 0,
CT_TYPE_FT6X36,
CT_TYPE_GT911,
CT_TYPE_CST820,
CT_TYPE_CST226,
CT_TYPE_AXS15231,
CT_TYPE_CHSC5816,
CT_TYPE_COUNT
};
# define GT911_ADDR1 0x5D
# define GT911_ADDR2 0x14
# define FT6X36_ADDR 0x38
# define CST820_ADDR 0x15
# define CST226_ADDR 0x5A
# define AXS15231_ADDR 0x3B
# define CHSC5816_ADDR 0x2E
// CST8xx gestures
enum {
GESTURE_NONE = 0,
GESTURE_SWIPE_UP,
GESTURE_SWIPE_DOWN,
GESTURE_SWIPE_LEFT,
GESTURE_SWIPE_RIGHT,
GESTURE_SINGLE_CLICK,
GESTURE_DOUBLE_CLICK = 0x0B,
GESTURE_LONG_PRESS = 0x0C
};
// CST820 registers
# define CST820_TOUCH_REGS 1
// GT911 registers
# define GT911_POINT_INFO 0x814E
# define GT911_POINT_1 0x814F
# define GT911_CONFIG_FRESH 0x8100
# define GT911_CONFIG_SIZE 0xb9
# define GT911_CONFIG_START 0x8047
// FT6x36 registers
# define TOUCH_REG_MODE 0x00
# define TOUCH_REG_STATUS 0x02
# define TOUCH_REG_XH 0x03
# define TOUCH_REG_XL 0x04
# define TOUCH_REG_YH 0x05
# define TOUCH_REG_YL 0x06
# define TOUCH_REG_WEIGHT 0x07
# define TOUCH_REG_AREA 0x08
# define TOUCH_REG_CHIPID 0xA3 // !< Chip selecting
# define TOUCH_REG_VENDID 0xA8 // !< FocalTech's panel ID
// FT62x6 Vendor and Chip IDs
# define FT62XX_VENDID 0x11 // !< FocalTech's vendor ID
# define FT6206_CHIPID 0x06 // !< Chip selecting
# define FT6236_CHIPID 0x36 // !< Chip selecting
# define FT6236U_CHIPID 0x64 // !< Chip selecting
# define FT5316_CHIPID 0x0A // !< Chip selecting
// register offset to info for the second touch point
# define PT2_OFFSET 6
union __CHSC5816_PointReg {
struct {
uint8_t status;
uint8_t fingerNumber;
uint8_t x_l8;
uint8_t y_l8;
uint8_t z;
uint8_t x_h4 : 4;
uint8_t y_h4 : 4;
uint8_t id : 4;
uint8_t event : 4;
uint8_t p2;
} rp;
unsigned char data[8];
};
# ifndef __TOUCHINFO_STRUCT__
# define __TOUCHINFO_STRUCT__
typedef struct _fttouchinfo {
int count;
uint16_t x[5], y[5];
uint8_t pressure[5], area[5];
} TOUCHINFO;
# endif // ifndef __TOUCHINFO_STRUCT__
class BBCapTouch {
public:
BBCapTouch() {
_iOrientation = 0;
}
~BBCapTouch() { /*Wire.end();*/
} // ESPEasy doesn't allow this
int init(int iSDA,
int iSCL,
int iRST = -1,
int iINT = -1,
uint32_t u32Speed = 400000);
int getSamples(TOUCHINFO *pTI);
void sensorType(int iType);
int sensorType(void) const {
return _iType;
}
void setI2CAddress(int i2caddr);
int getI2CAddress(void) const {
return _iAddr;
}
int setOrientation(int iOrientation,
int iWidth,
int iHeight);
void setThreshold(int tresh);
uint8_t getChipId(void) const {
return _id; // Only set for FT62x6 family
}
protected:
void reset(int iResetPin);
private:
int _iAddr;
int _iType = CT_TYPE_UNKNOWN;
int _iOrientation, _iWidth{}, _iHeight{};
int _thresh = -1;
uint8_t _id = 0;
void fixSamples(TOUCHINFO *pTI);
bool I2CTest(uint8_t u8Addr);
int I2CRead(uint8_t u8Addr,
uint8_t *pData,
int iLen);
int I2CReadRegister(uint8_t u8Addr,
uint8_t u8Register,
uint8_t *pData,
int iLen);
int I2CReadRegister16(uint8_t u8Addr,
uint16_t u16Register,
uint8_t *pData,
int iLen);
int I2CWrite(uint8_t u8Addr,
uint8_t *pData,
int iLen);
}; // class BBCapTouch
#endif // __BB_CAPTOUCH__
+1 -1
View File
@@ -492,7 +492,7 @@ static const char DATA_ESPEASY_DEFAULT_MIN_CSS[] PROGMEM = {
// #define USES_P120 // ADXL345 I2C Acceleration / Gravity
// #define USES_P121 // HMC5883L
// #define USES_P122 // SHT2x
// #define USES_P123 // FT6206
// #define USES_P123 // I2C Touchscreens
// #define USES_P124 // I2C Multi Relay
// #define USES_P125 // ADXL345 SPI Acceleration / Gravity
// #define USES_P126 // 74HC595 Shift register
@@ -2,11 +2,19 @@
#ifdef USES_P123
// #######################################################################################################
// #################################### Plugin 123: FT62x6 Touchscreen ###################################
// ###################################### Plugin 123: I2C Touchscreens ###################################
// #######################################################################################################
/**
* Changelog:
* 2024-06-10 tonhuisman: Add support for CHSC5816, as found in https://github.com/lewisxhe/SensorLib by Lewis He (added to bb_captouch)
* 2024-06-02 tonhuisman: Renamed to I2C Touchscreens
* Refactor to use modified bb_captouch library https://github.com/bitbank2/bb_captouch to add support for
* FT62x6 and GT911 (tested), CST820, CST226 and AXS15231 (untested)
* The library supports auto-configure, but that only checks if an I2C device is available at certain addresses
* so that's not really reliable. Added methods to override the used touchscreen with the known device
* Only single-point support for now.
* For the auto-configure option the I2C device check is disabled for this plugin.
* 2024-03-21 tonhuisman: Refactor increment/decrement to next/prevButtonGroup/Page functions, to align with ESPEasy_TouchHandler
* 2023-12-31 tonhuisman: Code optimizations
* 2023-10-01 tonhuisman: Re-implement (fix) switching of X/Y/Z vs X/Y output values using PLUGIN_GET_DEVICEVALUECOUNT, store (also) in task
@@ -47,7 +55,7 @@
# define PLUGIN_123
# define PLUGIN_ID_123 123
# define PLUGIN_NAME_123 "Touch - FT62x6 touchscreen"
# define PLUGIN_NAME_123 "Touch - I2C Touchscreens"
# define PLUGIN_VALUENAME1_123 "X"
# define PLUGIN_VALUENAME2_123 "Y"
# define PLUGIN_VALUENAME3_123 "Z"
@@ -74,6 +82,7 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string)
Device[deviceCount].SendDataOption = false;
Device[deviceCount].TimerOption = false;
Device[deviceCount].ExitTaskBeforeSave = false;
Device[deviceCount].I2CNoDeviceCheck = true;
success = true;
break;
}
@@ -96,7 +105,7 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string)
case PLUGIN_I2C_HAS_ADDRESS:
{
success = (event->Par1 == P123_I2C_ADDRESS); // Fixed I2C address
success = P123_data_struct::plugin_i2c_has_address(event->Par1);
break;
}
@@ -107,6 +116,10 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string)
P123_CONFIG_ROTATION = P123_TS_ROTATION;
P123_CONFIG_X_RES = P123_TS_X_RES;
P123_CONFIG_Y_RES = P123_TS_Y_RES;
P123_I2C_ADDRESS = 0x38; // Former default was FT62x6
P123_SET_TOUCH_TYPE(static_cast<int>(P123_TouchType_e::FT62x6));
P123_INTERRUPTPIN = -1; // No interrupt
P123_RESETPIN = -1; // No reset
success = true;
break;
@@ -167,13 +180,49 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string)
AdaGFXFormColorDepth(F("colordepth"), P123_COLOR_DEPTH, (colorDepth_ == 0));
addFormNumericBox(F("Touch minimum pressure"), F("threshold"), P123_CONFIG_THRESHOLD, 0, 255);
addUnit(F("Only used for FT62x6"));
{
P123_data_struct *P123_data = static_cast<P123_data_struct *>(getPluginTaskData(event->TaskIndex));
bool deleteP123_data = false;
{
const __FlashStringHelper *touchTypes[] = {
toString(P123_TouchType_e::FT62x6),
toString(P123_TouchType_e::GT911_1),
toString(P123_TouchType_e::GT911_2),
toString(P123_TouchType_e::CST820),
toString(P123_TouchType_e::CST226),
toString(P123_TouchType_e::AXS15231),
toString(P123_TouchType_e::CHSC5816),
toString(P123_TouchType_e::Automatic),
};
const int touchTypeOptions[] = {
static_cast<int>(P123_TouchType_e::FT62x6),
static_cast<int>(P123_TouchType_e::GT911_1),
static_cast<int>(P123_TouchType_e::GT911_2),
static_cast<int>(P123_TouchType_e::CST820),
static_cast<int>(P123_TouchType_e::CST226),
static_cast<int>(P123_TouchType_e::AXS15231),
static_cast<int>(P123_TouchType_e::CHSC5816),
static_cast<int>(P123_TouchType_e::Automatic),
};
addFormSelector(F("Touchscreen type (address)"),
F("ttype"),
NR_ELEMENTS(touchTypeOptions),
touchTypes,
touchTypeOptions,
P123_GET_TOUCH_TYPE);
if (nullptr != P123_data) {
addUnit(concat(F("Detected: "), toString(P123_data->getTouchType())));
}
}
addFormPinSelect(PinSelectPurpose::Generic_bidir, F("Interrupt pin"), F("taskdevicepin1"), P123_INTERRUPTPIN);
addFormPinSelect(PinSelectPurpose::Generic_bidir, F("Reset pin"), F("taskdevicepin2"), P123_RESETPIN);
addFormNote(F("Interrupt and Reset pins are optional. Interrupt is only used by GT911."));
if (nullptr == P123_data) {
P123_data = new (std::nothrow) P123_data_struct();
P123_data = new (std::nothrow) P123_data_struct(static_cast<P123_TouchType_e>(P123_GET_TOUCH_TYPE));
deleteP123_data = true;
}
@@ -200,6 +249,10 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string)
P123_CONFIG_ROTATION = getFormItemInt(F("rotate"));
P123_CONFIG_X_RES = getFormItemInt(F("xres"));
P123_CONFIG_Y_RES = getFormItemInt(F("yres"));
P123_SET_TOUCH_TYPE(getFormItemInt(F("ttype")));
P123_I2C_ADDRESS = P123_data_struct::plugin_i2c_address(static_cast<P123_TouchType_e>(P123_GET_TOUCH_TYPE));
// taskdevicepin1/taskdevicepin2 are saved automatically
const int colorDepth = getFormItemInt(F("colordepth"), -1);
@@ -212,7 +265,7 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string)
bool deleteP123_data = false;
if (nullptr == P123_data) {
P123_data = new (std::nothrow) P123_data_struct();
P123_data = new (std::nothrow) P123_data_struct(static_cast<P123_TouchType_e>(P123_GET_TOUCH_TYPE));
deleteP123_data = true;
}
@@ -233,7 +286,12 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string)
# ifdef PLUGIN_123_DEBUG
addLogMove(LOG_LEVEL_INFO, F("P123 PLUGIN_INIT"));
# endif // ifdef PLUGIN_123_DEBUG
initPluginTaskData(event->TaskIndex, new (std::nothrow) P123_data_struct());
if (0 == P123_I2C_ADDRESS) {
P123_I2C_ADDRESS = 0x38; // Former default was FT62x6
P123_SET_TOUCH_TYPE(static_cast<int>(P123_TouchType_e::FT62x6));
}
initPluginTaskData(event->TaskIndex, new (std::nothrow) P123_data_struct(static_cast<P123_TouchType_e>(P123_GET_TOUCH_TYPE)));
P123_data_struct *P123_data = static_cast<P123_data_struct *>(getPluginTaskData(event->TaskIndex));
if (nullptr == P123_data) {
+42 -11
View File
@@ -6,25 +6,56 @@
#include "../Globals/I2Cdev.h"
#include "../Globals/Settings.h"
#include "../Helpers/Hardware_I2C.h"
#include "../Helpers/StringConverter.h"
#include "../../ESPEasy_common.h"
void i2c_scanI2Cbus(bool dbg, int8_t channel) {
uint8_t error, address;
#if FEATURE_I2CMULTIPLEXER
if (-1 == channel) {
serialPrintln(F("Standard I2C bus"));
} else {
serialPrintln(concat(F("Multiplexer channel "), channel));
}
#endif // if FEATURE_I2CMULTIPLEXER
for (address = 1; address <= 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
serialPrintln(strformat(F("I2C : Found 0x%02x"), address));
} else if ((error == 4) || dbg) {
serialPrintln(strformat(F("I2C : Error %d at 0x%02x"), error, address));
}
}
}
const __FlashStringHelper* Command_i2c_Scanner(struct EventStruct *event, const char *Line)
{
uint8_t error, address;
if (Settings.isI2CEnabled()) {
for (address = 1; address <= 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
const bool dbg = equals(parseString(Line, 2), F("1"));
I2CSelect_Max100kHz_ClockSpeed(); // Scan bus using low speed
if (error == 0) {
serialPrint(F("I2C : Found 0x"));
serialPrintln(String(address, HEX));
} else if (error == 4) {
serialPrint(F("I2C : Error at 0x"));
serialPrintln(String(address, HEX));
i2c_scanI2Cbus(dbg, -1); // Base I2C bus
#if FEATURE_I2CMULTIPLEXER
if (isI2CMultiplexerEnabled()) {
uint8_t mux_max = I2CMultiplexerMaxChannels();
for (int8_t channel = 0; channel < mux_max; ++channel) {
I2CMultiplexerSelect(channel);
i2c_scanI2Cbus(dbg, channel); // Multiplexer I2C bus
}
I2CMultiplexerOff();
}
#endif // if FEATURE_I2CMULTIPLEXER
I2CSelectHighClockSpeed(); // By default the bus is in standard speed
} else {
serialPrintln(F("I2C : Not enabled."));
}
+5 -1
View File
@@ -3,6 +3,10 @@
#include "../../ESPEasy_common.h"
const __FlashStringHelper * Command_i2c_Scanner(struct EventStruct *event, const char* Line);
void i2c_scanI2Cbus(bool dbg,
int8_t channel);
const __FlashStringHelper* Command_i2c_Scanner(struct EventStruct *event,
const char *Line);
#endif // COMMAND_I2C_H
+2 -2
View File
@@ -1789,7 +1789,7 @@ To create/register a plugin, you have to :
#define USES_P116 // ST77xx
#endif
#if !defined(USES_P123) && defined(ESP32)
#define USES_P123 // FT6206
#define USES_P123 // I2C Touchscreens
#endif
#if !defined(USES_P137) && defined(ESP32)
#define USES_P137 // AXP192
@@ -2258,7 +2258,7 @@ To create/register a plugin, you have to :
#define USES_P122 // SHT2x
#endif
#ifndef USES_P123
#define USES_P123 // FT6206
#define USES_P123 // I2C Touchscreens
#endif
#ifndef USES_P124
#define USES_P124 // I2C Multi relay
+6 -6
View File
@@ -123,12 +123,12 @@
# define TOUCH_FLAGS_SWAP_LEFT_RIGHT 19 // Swaps Left and Right, Up and Down swipe directions for menu actions
# define TOUCH_FLAGS_IGNORE_TOUCH 20 // Disable touch, use for object/button features only
# define TOUCH_GET_VALUE_X UserVar.getInt32(event->TaskIndex, 0)
# define TOUCH_GET_VALUE_Y UserVar.getInt32(event->TaskIndex, 1)
# define TOUCH_GET_VALUE_Z UserVar.getInt32(event->TaskIndex, 2)
# define TOUCH_SET_VALUE_X(N) UserVar.setInt32(event->TaskIndex, 0, N)
# define TOUCH_SET_VALUE_Y(N) UserVar.setInt32(event->TaskIndex, 1, N)
# define TOUCH_SET_VALUE_Z(N) UserVar.setInt32(event->TaskIndex, 2, N)
# define TOUCH_GET_VALUE_X UserVar.getFloat(event->TaskIndex, 0)
# define TOUCH_GET_VALUE_Y UserVar.getFloat(event->TaskIndex, 1)
# define TOUCH_GET_VALUE_Z UserVar.getFloat(event->TaskIndex, 2)
# define TOUCH_SET_VALUE_X(N) UserVar.setFloat(event->TaskIndex, 0, N)
# define TOUCH_SET_VALUE_Y(N) UserVar.setFloat(event->TaskIndex, 1, N)
# define TOUCH_SET_VALUE_Z(N) UserVar.setFloat(event->TaskIndex, 2, N)
# define TOUCH_TS_ROTATION 0 // Rotation 0-3 = 0/90/180/270 degrees
# define TOUCH_TS_SEND_XY true // Enable/Disable X/Y events
+101 -54
View File
@@ -4,12 +4,81 @@
# include "../Helpers/AdafruitGFX_helper.h"
const __FlashStringHelper* toString(P123_TouchType_e tType) {
switch (tType) {
case P123_TouchType_e::FT62x6: return F("FT62x6 (0x38)");
case P123_TouchType_e::GT911_1: return F("GT911 (0x5D)");
case P123_TouchType_e::GT911_2: return F("GT911 (0x14)");
case P123_TouchType_e::CST820: return F("CST820 (0x15)");
case P123_TouchType_e::CST226: return F("CST226 (0x5A)");
case P123_TouchType_e::AXS15231: return F("AXS15231 (0x3B)");
case P123_TouchType_e::CHSC5816: return F("CHSC5816 (0x2E)");
case P123_TouchType_e::Automatic: return F("Auto-detect");
}
return F("");
}
/**
* Order must match enum P123_TouchType_e, with Automatic (-1) ignored
*/
const uint8_t P123_i2cAddressValues[] = { FT6X36_ADDR, GT911_ADDR1, GT911_ADDR2, CST820_ADDR, CST226_ADDR, AXS15231_ADDR, CHSC5816_ADDR };
bool P123_data_struct::plugin_i2c_has_address(const int Par1) {
return intArrayContains(NR_ELEMENTS(P123_i2cAddressValues), P123_i2cAddressValues, Par1);
}
uint8_t P123_data_struct::plugin_i2c_address(P123_TouchType_e touchType) {
const int tType = static_cast<int>(touchType);
if ((tType >= 0) && (tType < NR_ELEMENTS(P123_i2cAddressValues))) {
return P123_i2cAddressValues[tType];
}
return 0u;
}
P123_TouchType_e P123_data_struct::getTouchType() {
if (nullptr != touchscreen) {
const int stype = touchscreen->sensorType();
switch (stype) {
case CT_TYPE_FT6X36: return P123_TouchType_e::FT62x6;
case CT_TYPE_GT911:
if (GT911_ADDR1 == touchscreen->getI2CAddress()) {
return P123_TouchType_e::GT911_1;
} else {
return P123_TouchType_e::GT911_2;
}
case CT_TYPE_CST820: return P123_TouchType_e::CST820;
case CT_TYPE_CST226: return P123_TouchType_e::CST226;
case CT_TYPE_AXS15231: return P123_TouchType_e::AXS15231;
case CT_TYPE_CHSC5816: return P123_TouchType_e::CHSC5816;
}
}
return P123_TouchType_e::Automatic;
}
int P123_data_struct::getBBCapTouchType(P123_TouchType_e touchType) {
switch (touchType) {
case P123_TouchType_e::Automatic: return CT_TYPE_UNKNOWN;
case P123_TouchType_e::FT62x6: return CT_TYPE_FT6X36;
case P123_TouchType_e::GT911_1: // Fall through
case P123_TouchType_e::GT911_2: return CT_TYPE_GT911;
case P123_TouchType_e::CST820: return CT_TYPE_CST820;
case P123_TouchType_e::CST226: return CT_TYPE_CST226;
case P123_TouchType_e::AXS15231: return CT_TYPE_AXS15231;
case P123_TouchType_e::CHSC5816: return CT_TYPE_CHSC5816;
}
return CT_TYPE_UNKNOWN;
}
/**
* Constructor
*/
P123_data_struct::P123_data_struct()
: touchscreen(nullptr) {
P123_data_struct::P123_data_struct(P123_TouchType_e touchType)
: _touchType(touchType) {
touchHandler = new (std::nothrow) ESPEasy_TouchHandler(); // Temporary object to be able to call loadTouchObjects
_i2caddr = plugin_i2c_address(_touchType);
}
/**
@@ -50,12 +119,23 @@ bool P123_data_struct::init(struct EventStruct *event) {
touchHandler->init(event);
if (touchHandler->touchEnabled()) {
touchscreen = new (std::nothrow) Adafruit_FT6206();
touchscreen = new (std::nothrow) BBCapTouch();
if (nullptr != touchscreen) {
if (!touchscreen->begin(P123_CONFIG_THRESHOLD)) {
touchscreen->setThreshold(P123_CONFIG_THRESHOLD);
P123_TouchType_e touchType = static_cast<P123_TouchType_e>(P123_GET_TOUCH_TYPE);
if (P123_TouchType_e::Automatic != touchType) { // Manual override
touchscreen->sensorType(getBBCapTouchType(touchType));
touchscreen->setI2CAddress(plugin_i2c_address(touchType));
}
if (touchscreen->init(-1, -1, P123_RESETPIN, P123_INTERRUPTPIN) != CT_SUCCESS) {
delete touchscreen;
touchscreen = nullptr;
} else {
setRotation(_rotation);
}
}
}
@@ -213,7 +293,7 @@ void P123_data_struct::loadTouchObjects(struct EventStruct *event) {
*/
bool P123_data_struct::touched() {
if (isInitialized()) {
return touchscreen->touched();
return touchscreen->getSamples(&touchInfo) > 0; // 1 or more points touched
}
return false;
}
@@ -227,55 +307,11 @@ void P123_data_struct::readData(int16_t& x,
int16_t& ox,
int16_t& oy) {
if (isInitialized()) {
FT_Point p = touchscreen->getPoint();
int16_t _x = p.x;
int16_t _y = p.y;
// Rotate, as the driver doesn't provide that, use native touch-panel resolution
switch (_rotation) {
case P123_ROTATION_90:
if (touchHandler->_flipped) {
p.x = map(_y, 0, P123_TOUCH_Y_NATIVE, P123_TOUCH_Y_NATIVE, 0);
p.y = _x;
} else {
p.x = _y;
p.y = map(_x, 0, P123_TOUCH_X_NATIVE, P123_TOUCH_X_NATIVE, 0);
}
break;
case P123_ROTATION_180:
if (!touchHandler->_flipped) { // Change only when not flipped
p.x = map(_x, 0, P123_TOUCH_X_NATIVE, P123_TOUCH_X_NATIVE, 0);
p.y = map(_y, 0, P123_TOUCH_Y_NATIVE, P123_TOUCH_Y_NATIVE, 0);
}
break;
case P123_ROTATION_270:
if (touchHandler->_flipped) {
p.x = _y;
p.y = map(_x, 0, P123_TOUCH_X_NATIVE, P123_TOUCH_X_NATIVE, 0);
} else {
p.x = map(_y, 0, P123_TOUCH_Y_NATIVE, P123_TOUCH_Y_NATIVE, 0);
p.y = _x;
}
break;
case P123_ROTATION_0:
default:
if (touchHandler->_flipped) {
p.x = map(p.x, 0, P123_TOUCH_X_NATIVE, P123_TOUCH_X_NATIVE, 0);
p.y = map(p.y, 0, P123_TOUCH_Y_NATIVE, P123_TOUCH_Y_NATIVE, 0);
}
break;
}
x = p.x;
y = p.y;
z = p.z;
ox = _x;
oy = _y;
x = touchInfo.x[0]; // Only 1 point used for now.
y = touchInfo.y[0];
z = touchInfo.pressure[0];
ox = touchInfo.x[0]; // Change of touch driver has made these arguments obsolete, but in use for touchHandler...
oy = touchInfo.y[0];
}
}
@@ -284,6 +320,17 @@ void P123_data_struct::readData(int16_t& x,
*/
void P123_data_struct::setRotation(uint8_t n) {
_rotation = n;
if (isInitialized()) {
const bool fl = touchHandler->_flipped;
switch (_rotation) { // Rotation is handled by touch driver, flipped handled here
case 0: touchscreen->setOrientation(fl ? 180 : 0, _ts_x_res, _ts_y_res); break;
case 1: touchscreen->setOrientation(fl ? 270 : 90, _ts_x_res, _ts_y_res); break;
case 2: touchscreen->setOrientation(fl ? 0 : 180, _ts_x_res, _ts_y_res); break;
case 3: touchscreen->setOrientation(fl ? 90 : 270, _ts_x_res, _ts_y_res); break;
}
}
# ifdef PLUGIN_123_DEBUG
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
+61 -25
View File
@@ -7,7 +7,7 @@
# include "../Helpers/ESPEasy_TouchHandler.h"
# include <Adafruit_FT6206.h>
# include <bb_captouch.h>
# ifndef LIMIT_BUILD_SIZE
# define PLUGIN_123_DEBUG // Additional debugging information
@@ -21,9 +21,19 @@
# undef PLUGIN_123_DEBUG
# endif // if defined(BUILD_NO_DEBUG) && defined(PLUGIN_123_DEBUG)
# define P123_I2C_ADDRESS (0x38) // Fixed value
# define P123_I2C_ADDRESS PCONFIG(6)
# define P123_CONFIG_DISPLAY_TASK PCONFIG(0)
# define P123_CONFIG_FLAGS PCONFIG_ULONG(0) // All flags
# define P123_CONFIG_FLAG_TOUCHTYPE 0 // Flag indexes
// We're storing an int8_t in range -128..127 in an uin8_t
# define P123_GET_TOUCH_TYPE (get8BitFromUL(P123_CONFIG_FLAGS, P123_CONFIG_FLAG_TOUCHTYPE) - 128)
# define P123_SET_TOUCH_TYPE(T) (set8BitToUL(P123_CONFIG_FLAGS, P123_CONFIG_FLAG_TOUCHTYPE, T + 128))
# define P123_INTERRUPTPIN (CONFIG_PIN1)
# define P123_RESETPIN (CONFIG_PIN2)
# define P123_COLOR_DEPTH PCONFIG_LONG(1)
# define P123_CONFIG_THRESHOLD PCONFIG(1)
# define P123_CONFIG_ROTATION PCONFIG(2)
@@ -47,31 +57,50 @@
# define P123_ROTATION_180 2
# define P123_ROTATION_270 3
enum class P123_TouchType_e : int8_t {
Automatic = -1,
FT62x6 = 0, // Also used as offset in I2C address array
GT911_1 = 1,
GT911_2 = 2,
CST820 = 3,
CST226 = 4,
AXS15231 = 5,
CHSC5816 = 6,
};
const __FlashStringHelper* toString(P123_TouchType_e tType);
// Data structure
struct P123_data_struct : public PluginTaskData_base
{
P123_data_struct();
P123_data_struct(P123_TouchType_e touchType);
~P123_data_struct();
void reset();
bool init(struct EventStruct *event);
bool isInitialized() const;
static bool plugin_i2c_has_address(int Par1);
static uint8_t plugin_i2c_address(P123_TouchType_e touchType);
bool plugin_webform_load(struct EventStruct *event);
bool plugin_webform_save(struct EventStruct *event);
bool plugin_write(struct EventStruct *event,
const String & string);
bool plugin_fifty_per_second(struct EventStruct *event);
bool plugin_get_config_value(struct EventStruct *event,
String & string);
P123_TouchType_e getTouchType();
int getBBCapTouchType(P123_TouchType_e touchType);
void loadTouchObjects(struct EventStruct *event);
bool touched();
void readData(int16_t& x,
int16_t& y,
int16_t& z,
int16_t& ox,
int16_t& oy);
void reset();
bool init(struct EventStruct *event);
bool isInitialized() const;
bool plugin_webform_load(struct EventStruct *event);
bool plugin_webform_save(struct EventStruct *event);
bool plugin_write(struct EventStruct *event,
const String & string);
bool plugin_fifty_per_second(struct EventStruct *event);
bool plugin_get_config_value(struct EventStruct *event,
String & string);
void loadTouchObjects(struct EventStruct *event);
bool touched();
void readData(int16_t& x,
int16_t& y,
int16_t& z,
int16_t& ox,
int16_t& oy);
void setRotation(uint8_t n);
void setRotationFlipped(bool _flipped);
@@ -111,13 +140,20 @@ struct P123_data_struct : public PluginTaskData_base
private:
// This is initialized by calling init()
Adafruit_FT6206 *touchscreen = nullptr;
uint8_t _rotation = 0u;
uint16_t _ts_x_res = 0u;
uint16_t _ts_y_res = 0u;
BBCapTouch *touchscreen = nullptr;
uint8_t _rotation = 0u;
uint16_t _ts_x_res = 0u;
uint16_t _ts_y_res = 0u;
int16_t _i2caddr{};
int16_t _resetPin = -1;
int16_t _interruptPin = -1;
P123_TouchType_e _touchType;
TOUCHINFO touchInfo;
ESPEasy_TouchHandler *touchHandler = nullptr;
};
#endif // ifdef USED_P123
#endif // ifdef USES_P123
#endif // ifndef PLUGINSTRUCTS_P123_DATA_STRUCT_H
+14 -5
View File
@@ -187,13 +187,17 @@ String getKnownI2Cdevice(uint8_t address) {
break;
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
case 0x18:
result += F("I2C_MultiRelay");
break;
case 0x14:
result += F("I2C_MultiRelay,GT911");
break;
case 0x15:
result += F("I2C_MultiRelay,CST820");
break;
case 0x1D:
result += F("ADXL345");
break;
@@ -217,6 +221,9 @@ String getKnownI2Cdevice(uint8_t address) {
case 0x29:
result += F("TSL2561,TSL2591,TCS34725,VL53L0X,VL53L1X");
break;
case 0x2E:
result += F("CHSC5816");
break;
case 0x30:
result += F("VL53L0X,VL53L1X");
break;
@@ -236,9 +243,11 @@ String getKnownI2Cdevice(uint8_t address) {
result += F("LCD,PCF8574A,TSL2561,APDS9960,AHT10,Adafruit Rotary enc,Adafruit Soil moisture");
break;
case 0x3A:
case 0x3B:
result += F("LCD,PCF8574A,Adafruit Rotary enc");
break;
case 0x3B:
result += F("LCD,PCF8574A,Adafruit Rotary enc,AXS15231");
break;
case 0x3C:
case 0x3D:
result += F("LCD,PCF8574A,OLED,Adafruit Rotary enc");
@@ -299,7 +308,7 @@ String getKnownI2Cdevice(uint8_t address) {
result += F("SGP4x,GP8403");
break;
case 0x5A:
result += F("MLX90614,MPR121,CCS811,GP8403");
result += F("MLX90614,MPR121,CCS811,GP8403,CST226");
break;
case 0x5B:
result += F("MPR121,CCS811,GP8403");
@@ -308,7 +317,7 @@ String getKnownI2Cdevice(uint8_t address) {
result += F("DHT12,AM2320,BH1750,MPR121,GP8403");
break;
case 0x5D:
result += F("MPR121,GP8403");
result += F("MPR121,GP8403,GT911");
break;
case 0x5E:
case 0x5F: