Snapshot of JC3636W518EN kit before demo folder cleanup
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
9ee85bfd86
1862 files changed
+668877
No files matched your search
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "CST816S.h"
|
||||
|
||||
static const char *TAG = "CST816S_CPP";
|
||||
|
||||
ESP_PanelTouch_CST816S::ESP_PanelTouch_CST816S(ESP_PanelBus *bus, uint16_t width, uint16_t height,
|
||||
int rst_io, int int_io):
|
||||
ESP_PanelTouch(bus, width, height, rst_io, int_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_CST816S::ESP_PanelTouch_CST816S(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
ESP_PanelTouch(bus, config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_CST816S::~ESP_PanelTouch_CST816S()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch_CST816S::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_new_i2c_cst816s(bus->getHandle(), &config, &handle), false, "New driver failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/esp_lcd_touch_cst816s.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
/**
|
||||
* @brief CST816S touch device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelTouch`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelTouch_CST816S : public ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch_CST816S(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io = -1, int int_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch_CST816S(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelTouch_CST816S() override;
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
};
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
static const char *TAG = "ESP_PanelTouch";
|
||||
|
||||
#define CALLBACK_DATA_DEFAULT() \
|
||||
{ \
|
||||
.tp_ptr = this, \
|
||||
.user_data = NULL, \
|
||||
}
|
||||
|
||||
ESP_PanelTouchPoint::ESP_PanelTouchPoint(void):
|
||||
x(0),
|
||||
y(0),
|
||||
strength(0)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouchPoint::ESP_PanelTouchPoint(uint16_t x, uint16_t y, uint16_t strength):
|
||||
x(x),
|
||||
y(y),
|
||||
strength(strength)
|
||||
{
|
||||
}
|
||||
|
||||
bool ESP_PanelTouchPoint::operator==(ESP_PanelTouchPoint p)
|
||||
{
|
||||
return ((p.x == x) && (p.y == y));
|
||||
}
|
||||
|
||||
bool ESP_PanelTouchPoint::operator!=(ESP_PanelTouchPoint p)
|
||||
{
|
||||
return ((p.x != x) || (p.y != y));
|
||||
}
|
||||
|
||||
ESP_PanelTouch::ESP_PanelTouch(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io, int int_io):
|
||||
bus(bus),
|
||||
config((esp_lcd_touch_config_t)ESP_PANEL_TOUCH_CONFIG_DEFAULT(width, height, rst_io, int_io)),
|
||||
handle(NULL),
|
||||
_swap_xy(false),
|
||||
_mirror_x(false),
|
||||
_mirror_y(false),
|
||||
_tp_points_num(0),
|
||||
_tp_buttons_state{0},
|
||||
onTouchInterruptCallback(NULL),
|
||||
_isr_sem(NULL),
|
||||
callback_data(CALLBACK_DATA_DEFAULT())
|
||||
{
|
||||
if (int_io >= 0) {
|
||||
config.interrupt_callback = onTouchInterrupt;
|
||||
config.user_data = &callback_data;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_PanelTouch::ESP_PanelTouch(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
bus(bus),
|
||||
config(config),
|
||||
handle(NULL),
|
||||
_swap_xy(false),
|
||||
_mirror_x(false),
|
||||
_mirror_y(false),
|
||||
_tp_points_num(0),
|
||||
_tp_buttons_state{0},
|
||||
onTouchInterruptCallback(NULL),
|
||||
_isr_sem(NULL),
|
||||
callback_data(CALLBACK_DATA_DEFAULT())
|
||||
{
|
||||
if ((config.int_gpio_num != GPIO_NUM_NC) && (config.interrupt_callback == NULL) && (config.user_data == NULL)) {
|
||||
this->config.interrupt_callback = onTouchInterrupt;
|
||||
this->config.user_data = &callback_data;
|
||||
}
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::attachInterruptCallback(std::function<bool (void *)> callback, void *user_data)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET((config.interrupt_callback == onTouchInterrupt), false, "Interruption is not enabled");
|
||||
|
||||
onTouchInterruptCallback = callback;
|
||||
callback_data.user_data = user_data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::init(void)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (config.interrupt_callback == onTouchInterrupt) {
|
||||
_isr_sem = xSemaphoreCreateBinary();
|
||||
ESP_PANEL_CHECK_NULL_RET(_isr_sem, false, "Create semaphore failed");
|
||||
|
||||
ESP_LOGD(TAG, "Enable interruption");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Disable interruption");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::del(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(handle, false, "Invalid handle");
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_del(handle), false, "Delete touch panel failed");
|
||||
|
||||
ESP_LOGD(TAG, "Touch panel @%p deleted", handle);
|
||||
handle = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::swapXY(bool en)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(handle, false, "Invalid handle");
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_set_swap_xy(handle, en), false, "Swap axes failed");
|
||||
_swap_xy = en;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::mirrorX(bool en)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(handle, false, "Invalid handle");
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_set_mirror_x(handle, en), false, "Mirror X failed");
|
||||
_mirror_x = en;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::mirrorY(bool en)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(handle, false, "Invalid handle");
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_set_mirror_y(handle, en), false, "Mirror Y failed");
|
||||
_mirror_y = en;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::readRawData(uint8_t max_points_num, int timeout_ms)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(handle, false, "Invalid handle");
|
||||
|
||||
uint16_t x[CONFIG_ESP_LCD_TOUCH_MAX_POINTS] = {0};
|
||||
uint16_t y[CONFIG_ESP_LCD_TOUCH_MAX_POINTS] = {0};
|
||||
uint16_t strength[CONFIG_ESP_LCD_TOUCH_MAX_POINTS] = {0};
|
||||
_tp_points_num = 0;
|
||||
if (max_points_num > CONFIG_ESP_LCD_TOUCH_MAX_POINTS) {
|
||||
max_points_num = CONFIG_ESP_LCD_TOUCH_MAX_POINTS;
|
||||
ESP_LOGE(TAG, "The max points number out of range [%d/%d]", max_points_num, CONFIG_ESP_LCD_TOUCH_MAX_POINTS);
|
||||
}
|
||||
|
||||
if (_isr_sem != NULL) {
|
||||
BaseType_t timeout_ticks = (timeout_ms < 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
|
||||
if (xSemaphoreTake(_isr_sem, timeout_ticks) != pdTRUE) {
|
||||
ESP_LOGD(TAG, "Touch panel @%p wait for isr timeout", handle);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_read_data(handle), false, "Read data failed");
|
||||
esp_lcd_touch_get_coordinates(handle, x, y, strength, &_tp_points_num, max_points_num);
|
||||
|
||||
for (int i = 0; i < _tp_points_num; i++) {
|
||||
_tp_points[i].x = x[i];
|
||||
_tp_points[i].y = y[i];
|
||||
_tp_points[i].strength = strength[i];
|
||||
ESP_LOGD(TAG, "Touch panel @%p touched (%d, %d, %d)", handle, _tp_points[i].x, _tp_points[i].y,
|
||||
_tp_points[i].strength);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int ESP_PanelTouch::getPoints(ESP_PanelTouchPoint points[], uint8_t num)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET((num == 0) || (points != NULL), -1, "Invalid points or num");
|
||||
|
||||
int i = 0;
|
||||
for (; (i < num) && (i < _tp_points_num); i++) {
|
||||
points[i] = _tp_points[i];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int ESP_PanelTouch::getButtonState(uint8_t n)
|
||||
{
|
||||
uint8_t button_state = 0;
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_get_button_state(handle, n, &button_state), -1, "Get button state failed");
|
||||
|
||||
return button_state;
|
||||
}
|
||||
|
||||
int ESP_PanelTouch::readPoints(ESP_PanelTouchPoint points[], uint8_t num, int timeout_ms)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET(readRawData(num, timeout_ms), -1, "Read raw data failed");
|
||||
|
||||
return getPoints(points, num);
|
||||
}
|
||||
|
||||
int ESP_PanelTouch::readButtonState(uint8_t n, int timeout_ms)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET(readRawData(0, timeout_ms), -1, "Read raw data failed");
|
||||
|
||||
return getButtonState(n);
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::isInterruptEnabled(void)
|
||||
{
|
||||
return (config.interrupt_callback == onTouchInterrupt);
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::getSwapXYFlag(void)
|
||||
{
|
||||
return _swap_xy;
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::getMirrorXFlag(void)
|
||||
{
|
||||
return _mirror_x;
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch::getMirrorYFlag(void)
|
||||
{
|
||||
return _mirror_y;
|
||||
}
|
||||
|
||||
esp_lcd_touch_handle_t ESP_PanelTouch::getHandle(void)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
ESP_LOGD(TAG, "Get invalid handle");
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
ESP_PanelBus *ESP_PanelTouch::getBus(void)
|
||||
{
|
||||
if (bus == NULL) {
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
ESP_LOGD(TAG, "Get invalid bus");
|
||||
}
|
||||
|
||||
return bus;
|
||||
}
|
||||
|
||||
void ESP_PanelTouch::onTouchInterrupt(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
if ((tp == NULL) || (tp->config.user_data == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_PanelTouch *panel = (ESP_PanelTouch *)((ESP_PanelTouchCallbackData_t *)tp->config.user_data)->tp_ptr;
|
||||
if (panel == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BaseType_t need_yield = pdFALSE;
|
||||
if (panel->onTouchInterruptCallback != NULL) {
|
||||
need_yield = panel->onTouchInterruptCallback(panel->callback_data.user_data) ? pdTRUE : need_yield;
|
||||
}
|
||||
if (panel->_isr_sem != NULL) {
|
||||
xSemaphoreGiveFromISR(panel->_isr_sem, &need_yield);
|
||||
}
|
||||
if (need_yield == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include "touch/base/esp_lcd_touch.h"
|
||||
#include "bus/ESP_PanelBus.h"
|
||||
|
||||
/**
|
||||
* @brief Touch device default configuration macro
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_CONFIG_DEFAULT(width, height, rst_io, int_io) \
|
||||
{ \
|
||||
.x_max = width, \
|
||||
.y_max = height, \
|
||||
.rst_gpio_num = (gpio_num_t)rst_io, \
|
||||
.int_gpio_num = (gpio_num_t)int_io, \
|
||||
.levels = { \
|
||||
.reset = 0, \
|
||||
.interrupt = 0, \
|
||||
}, \
|
||||
.flags = { \
|
||||
.swap_xy = 0, \
|
||||
.mirror_x = 0, \
|
||||
.mirror_y = 0, \
|
||||
}, \
|
||||
.process_coordinates = NULL, \
|
||||
.interrupt_callback = NULL, \
|
||||
.user_data = NULL, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The class used for storing touch points
|
||||
*
|
||||
*/
|
||||
class ESP_PanelTouchPoint {
|
||||
public:
|
||||
ESP_PanelTouchPoint();
|
||||
ESP_PanelTouchPoint(uint16_t x, uint16_t y, uint16_t strength);
|
||||
|
||||
bool operator==(ESP_PanelTouchPoint p);
|
||||
bool operator!=(ESP_PanelTouchPoint p);
|
||||
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t strength;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The touch device objdec class
|
||||
*
|
||||
* @note This class is a base class for all Touchs. Due to it is a virtual class, users cannot use it directly
|
||||
*/
|
||||
class ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io, int int_io);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
virtual ~ESP_PanelTouch() = default;
|
||||
|
||||
/**
|
||||
* @brief Attach a callback function, which will be called when the refreshing is finished
|
||||
*
|
||||
* @param callback The callback function
|
||||
* @param user_data The user data which will be passed to the callback function
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool attachInterruptCallback(std::function<bool (void *)> callback, void *user_data = NULL);
|
||||
|
||||
/**
|
||||
* @brief Initialize the touch device, the `begin()` function should be called after this function.
|
||||
*
|
||||
* @note This function intends to create a semaphore for the interrupt if the interrupt pin is set and the
|
||||
* `interrupt_callback` is not used by the users. If successful, the driver will enable the functionality of
|
||||
* blocking reads.
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void);
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
virtual bool begin(void) = 0;
|
||||
|
||||
/**
|
||||
* @brief Delete the touch device, release the resources
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_touch_del()` to delete the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool del(void);
|
||||
|
||||
/**
|
||||
* @brief Swap the X and Y axis
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_touch_set_swap_xy()` to mirror the axises
|
||||
*
|
||||
* @param en true: enable, false: disable
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool swapXY(bool en);
|
||||
|
||||
/**
|
||||
* @brief Mirror the X axis
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_touch_set_mirror_x()` to mirror the axis
|
||||
*
|
||||
* @param en true: enable, false: disable
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool mirrorX(bool en);
|
||||
|
||||
/**
|
||||
* @brief Mirror the Y axis
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_touch_set_mirror_y()` to mirror the axis
|
||||
*
|
||||
* @param en true: enable, false: disable
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool mirrorY(bool en);
|
||||
|
||||
/**
|
||||
* @brief Read the raw data from the touch device, then users should call `getPoints()` to get the points, or call
|
||||
* `getButtonState()` to get the button state
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_touch_read_data()` and `esp_lcd_touch_get_coordinates()` to read
|
||||
* the raw data
|
||||
* @note If the interrupt pin is set, this function will be blocked until either the interrupt occurs or a timeout
|
||||
* is triggered
|
||||
*
|
||||
* @param max_points_num The max number of the points to read
|
||||
* @param timeout_ms The timeout of waiting for the interrupt, it is only used when the interrupt pin is set. Set to
|
||||
* `-1` if waiting forever
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool readRawData(uint8_t max_points_num = CONFIG_ESP_LCD_TOUCH_MAX_POINTS, int timeout_ms = 0);
|
||||
|
||||
/**
|
||||
* @brief Get the touch points. This function should be called immediately after the `readRawData()` function
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
*
|
||||
* @param points The buffer to store the points
|
||||
* @param num The number of the points to read
|
||||
*
|
||||
* @return The number of the points read, `-1` if failed
|
||||
*/
|
||||
int getPoints(ESP_PanelTouchPoint points[], uint8_t num = 1);
|
||||
|
||||
/**
|
||||
* @brief Get the button state. This function should be called immediately after the `readRawData()` function
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
*
|
||||
* @param index The index of the button
|
||||
*
|
||||
* @return The state of the button, `-1` if failed
|
||||
*/
|
||||
int getButtonState(uint8_t index = 0);
|
||||
|
||||
/**
|
||||
* @brief Read the points from the touch device. This function is a combination of `readRawData()` and `getPoints()`
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note If the interrupt pin is set, this function will be blocked until either the interrupt occurs or a timeout
|
||||
* is triggered
|
||||
*
|
||||
* @param points The buffer to store the points
|
||||
* @param num The number of the points to read
|
||||
* @param timeout_ms The timeout of waiting for the interrupt, it is only used when the interrupt pin is set. Set to
|
||||
* `-1` if waiting forever
|
||||
*
|
||||
* @return The number of the points read, `-1` if failed
|
||||
*/
|
||||
int readPoints(ESP_PanelTouchPoint points[], uint8_t num = 1, int timeout_ms = 0);
|
||||
|
||||
/**
|
||||
* @brief Read the button state from the touch device. This function is a combination of `readRawData()` and
|
||||
* `getButtonState()`
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note If the interrupt pin is set, this function will be blocked until either the interrupt occurs or a timeout
|
||||
* is triggered
|
||||
*
|
||||
* @param index The index of the button
|
||||
* @param timeout_ms The timeout of waiting for the interrupt, it is only used when the interrupt pin is set. Set to
|
||||
* `-1` if waiting forever
|
||||
*
|
||||
* @return The state of the button, `-1` if failed
|
||||
*/
|
||||
int readButtonState(uint8_t index = 0, int timeout_ms = 0);
|
||||
|
||||
/**
|
||||
* @brief Check if the interrupt function is enabled
|
||||
*
|
||||
* @return true if enabled, otherwise false
|
||||
*/
|
||||
bool isInterruptEnabled(void);
|
||||
|
||||
/**
|
||||
* @brief Get the flag of the X and Y axis swap
|
||||
*
|
||||
* @return true if swap, otherwise not swap
|
||||
*/
|
||||
bool getSwapXYFlag(void);
|
||||
|
||||
/**
|
||||
* @brief Get the flag of the X axis mirror
|
||||
*
|
||||
* @return true if mirror, otherwise not mirror
|
||||
*/
|
||||
bool getMirrorXFlag(void);
|
||||
|
||||
/**
|
||||
* @brief Get the flag of the Y axis mirror
|
||||
*
|
||||
* @return true if mirror, otherwise not mirror
|
||||
*/
|
||||
bool getMirrorYFlag(void);
|
||||
|
||||
/**
|
||||
* @brief Get the panel handle of LCD device
|
||||
*
|
||||
* @return The handle of the LCD panel, or NULL if fail
|
||||
*/
|
||||
esp_lcd_touch_handle_t getHandle(void);
|
||||
|
||||
/**
|
||||
* @brief Get the panel bus
|
||||
*
|
||||
* @return The pointer of the LCD Bus, or NULL if fail
|
||||
*/
|
||||
ESP_PanelBus *getBus(void);
|
||||
|
||||
protected:
|
||||
ESP_PanelBus *bus;
|
||||
esp_lcd_touch_config_t config;
|
||||
esp_lcd_touch_handle_t handle;
|
||||
|
||||
private:
|
||||
static void onTouchInterrupt(esp_lcd_touch_handle_t tp);
|
||||
|
||||
bool _swap_xy;
|
||||
bool _mirror_x;
|
||||
bool _mirror_y;
|
||||
uint8_t _tp_points_num;
|
||||
uint8_t _tp_buttons_state[CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS];
|
||||
ESP_PanelTouchPoint _tp_points[CONFIG_ESP_LCD_TOUCH_MAX_POINTS];
|
||||
|
||||
std::function<bool (void *)> onTouchInterruptCallback;
|
||||
SemaphoreHandle_t _isr_sem;
|
||||
typedef struct {
|
||||
void *tp_ptr;
|
||||
void *user_data;
|
||||
} ESP_PanelTouchCallbackData_t;
|
||||
ESP_PanelTouchCallbackData_t callback_data;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "FT5x06.h"
|
||||
|
||||
static const char *TAG = "FT5x06_CPP";
|
||||
|
||||
ESP_PanelTouch_FT5x06::ESP_PanelTouch_FT5x06(ESP_PanelBus *bus, uint16_t width, uint16_t height,
|
||||
int rst_io, int int_io):
|
||||
ESP_PanelTouch(bus, width, height, rst_io, int_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_FT5x06::ESP_PanelTouch_FT5x06(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
ESP_PanelTouch(bus, config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_FT5x06::~ESP_PanelTouch_FT5x06()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch_FT5x06::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_new_i2c_ft5x06(bus->getHandle(), &config, &handle), false, "New driver failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/esp_lcd_touch_ft5x06.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
/**
|
||||
* @brief FT5x06 touch device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelTouch`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelTouch_FT5x06 : public ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch_FT5x06(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io = -1, int int_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch_FT5x06(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelTouch_FT5x06() override;
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "GT1151.h"
|
||||
|
||||
static const char *TAG = "GT1151_CPP";
|
||||
|
||||
ESP_PanelTouch_GT1151::ESP_PanelTouch_GT1151(ESP_PanelBus *bus, uint16_t width, uint16_t height,
|
||||
int rst_io, int int_io):
|
||||
ESP_PanelTouch(bus, width, height, rst_io, int_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_GT1151::ESP_PanelTouch_GT1151(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
ESP_PanelTouch(bus, config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_GT1151::~ESP_PanelTouch_GT1151()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch_GT1151::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_new_i2c_gt1151(bus->getHandle(), &config, &handle), false, "New driver failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/esp_lcd_touch_gt1151.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
/**
|
||||
* @brief TT21100 touch device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelTouch`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelTouch_GT1151 : public ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch_GT1151(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io = -1, int int_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch_GT1151(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelTouch_GT1151() override;
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "GT911.h"
|
||||
|
||||
static const char *TAG = "GT911_CPP";
|
||||
|
||||
ESP_PanelTouch_GT911::ESP_PanelTouch_GT911(ESP_PanelBus *bus, uint16_t width, uint16_t height,
|
||||
int rst_io, int int_io):
|
||||
ESP_PanelTouch(bus, width, height, rst_io, int_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_GT911::ESP_PanelTouch_GT911(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
ESP_PanelTouch(bus, config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_GT911::~ESP_PanelTouch_GT911()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch_GT911::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_new_i2c_gt911(bus->getHandle(), &config, &handle), false, "New driver failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/esp_lcd_touch_gt911.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
/**
|
||||
* @brief GT911 touch device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelTouch`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelTouch_GT911 : public ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch_GT911(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io = -1, int int_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch_GT911(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelTouch_GT911() override;
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
# Touch Controllers
|
||||
|
||||
| **Name** | **Version** |
|
||||
| -------------------------------------------------------------------------------------- | ----------- |
|
||||
| [esp_lcd_touch](https://components.espressif.com/components/espressif/esp_lcd_touch) | 1.1.1 |
|
||||
| [CST816S](https://components.espressif.com/components/espressif/esp_lcd_touch_cst816s) | 1.0.3 |
|
||||
| [FT5x06](https://components.espressif.com/components/espressif/esp_lcd_touch_ft5x06) | 1.0.6 |
|
||||
| [GT911](https://components.espressif.com/components/espressif/esp_lcd_touch_gt911) | 1.1.0 |
|
||||
| [GT1151](https://components.espressif.com/components/espressif/esp_lcd_touch_gt1151) | 1.0.5~1 |
|
||||
| ST1633 | 0.1.0 |
|
||||
| [ST7123](https://components.espressif.com/components/espressif/esp_lcd_touch_st7123) | 0.0.1 |
|
||||
| [TT21100](https://components.espressif.com/components/espressif/esp_lcd_touch_tt21100) | 1.1.0 |
|
||||
| [XPT2046](https://components.espressif.com/components/atanisoft/esp_lcd_touch_xpt2046) | 1.0.4 |
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ST1633.h"
|
||||
|
||||
static const char *TAG = "ST1633_CPP";
|
||||
|
||||
ESP_PanelTouch_ST1633::ESP_PanelTouch_ST1633(ESP_PanelBus *bus, uint16_t width, uint16_t height,
|
||||
int rst_io, int int_io):
|
||||
ESP_PanelTouch(bus, width, height, rst_io, int_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_ST1633::ESP_PanelTouch_ST1633(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
ESP_PanelTouch(bus, config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_ST1633::~ESP_PanelTouch_ST1633()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch_ST1633::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_new_i2c_st1633(bus->getHandle(), &config, &handle), false, "New driver failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/esp_lcd_touch_st1633.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
/**
|
||||
* @brief ST1633 touch device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelTouch`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelTouch_ST1633 : public ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch_ST1633(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io = -1, int int_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch_ST1633(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelTouch_ST1633() override;
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ST7123.h"
|
||||
|
||||
static const char *TAG = "ST7123_CPP";
|
||||
|
||||
ESP_PanelTouch_ST7123::ESP_PanelTouch_ST7123(ESP_PanelBus *bus, uint16_t width, uint16_t height,
|
||||
int rst_io, int int_io):
|
||||
ESP_PanelTouch(bus, width, height, rst_io, int_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_ST7123::ESP_PanelTouch_ST7123(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
ESP_PanelTouch(bus, config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_ST7123::~ESP_PanelTouch_ST7123()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch_ST7123::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_new_i2c_st7123(bus->getHandle(), &config, &handle), false, "New driver failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/esp_lcd_touch_st7123.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
/**
|
||||
* @brief ST7123 touch device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelTouch`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelTouch_ST7123 : public ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch_ST7123(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io = -1, int int_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch_ST7123(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelTouch_ST7123() override;
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "TT21100.h"
|
||||
|
||||
static const char *TAG = "TT21100_CPP";
|
||||
|
||||
ESP_PanelTouch_TT21100::ESP_PanelTouch_TT21100(ESP_PanelBus *bus, uint16_t width, uint16_t height,
|
||||
int rst_io, int int_io):
|
||||
ESP_PanelTouch(bus, width, height, rst_io, int_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_TT21100::ESP_PanelTouch_TT21100(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
ESP_PanelTouch(bus, config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_TT21100::~ESP_PanelTouch_TT21100()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch_TT21100::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_new_i2c_tt21100(bus->getHandle(), &config, &handle), false, "New driver failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/esp_lcd_touch_tt21100.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
/**
|
||||
* @brief TT21100 touch device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelTouch`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelTouch_TT21100 : public ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch_TT21100(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io = -1, int int_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch_TT21100(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelTouch_TT21100() override;
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "XPT2046.h"
|
||||
|
||||
static const char *TAG = "XPT2046_CPP";
|
||||
|
||||
ESP_PanelTouch_XPT2046::ESP_PanelTouch_XPT2046(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io, int int_io):
|
||||
ESP_PanelTouch(bus, width, height, rst_io, int_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_XPT2046::ESP_PanelTouch_XPT2046(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
ESP_PanelTouch(bus, config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_XPT2046::~ESP_PanelTouch_XPT2046()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch_XPT2046::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_new_spi_xpt2046(bus->getHandle(), &config, &handle), false, "New driver failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/esp_lcd_touch_xpt2046.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
/**
|
||||
* @brief XPT2046 touch device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelTouch`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelTouch_XPT2046 : public ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch_XPT2046(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io = -1, int int_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch_XPT2046(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelTouch_XPT2046() override;
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
};
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
static const char *TAG = "TP";
|
||||
|
||||
/*******************************************************************************
|
||||
* Function definitions
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variables
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Public API functions
|
||||
*******************************************************************************/
|
||||
|
||||
esp_err_t esp_lcd_touch_enter_sleep(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
if (tp->enter_sleep == NULL) {
|
||||
ESP_LOGE(TAG, "Sleep mode not supported!");
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
return tp->enter_sleep(tp);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_exit_sleep(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
if (tp->exit_sleep == NULL) {
|
||||
ESP_LOGE(TAG, "Sleep mode not supported!");
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
return tp->exit_sleep(tp);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(tp->read_data != NULL);
|
||||
|
||||
return tp->read_data(tp);
|
||||
}
|
||||
|
||||
bool esp_lcd_touch_get_coordinates(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
|
||||
{
|
||||
bool touched = false;
|
||||
|
||||
assert(tp != NULL);
|
||||
assert(x != NULL);
|
||||
assert(y != NULL);
|
||||
assert(tp->get_xy != NULL);
|
||||
|
||||
touched = tp->get_xy(tp, x, y, strength, point_num, max_point_num);
|
||||
if (!touched) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Process coordinates by user */
|
||||
if (tp->config.process_coordinates != NULL) {
|
||||
tp->config.process_coordinates(tp, x, y, strength, point_num, max_point_num);
|
||||
}
|
||||
|
||||
/* Software coordinates adjustment needed */
|
||||
bool sw_adj_needed = ((tp->config.flags.mirror_x && (tp->set_mirror_x == NULL)) ||
|
||||
(tp->config.flags.mirror_y && (tp->set_mirror_y == NULL)) ||
|
||||
(tp->config.flags.swap_xy && (tp->set_swap_xy == NULL)));
|
||||
|
||||
/* Adjust all coordinates */
|
||||
for (int i = 0; (sw_adj_needed && i < *point_num); i++) {
|
||||
|
||||
/* Mirror X coordinates (if not supported by HW) */
|
||||
if (tp->config.flags.mirror_x && tp->set_mirror_x == NULL) {
|
||||
x[i] = tp->config.x_max - x[i];
|
||||
}
|
||||
|
||||
/* Mirror Y coordinates (if not supported by HW) */
|
||||
if (tp->config.flags.mirror_y && tp->set_mirror_y == NULL) {
|
||||
y[i] = tp->config.y_max - y[i];
|
||||
}
|
||||
|
||||
/* Swap X and Y coordinates (if not supported by HW) */
|
||||
if (tp->config.flags.swap_xy && tp->set_swap_xy == NULL) {
|
||||
uint16_t tmp = x[i];
|
||||
x[i] = y[i];
|
||||
y[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return touched;
|
||||
}
|
||||
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
esp_err_t esp_lcd_touch_get_button_state(esp_lcd_touch_handle_t tp, uint8_t n, uint8_t *state)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(state != NULL);
|
||||
|
||||
*state = 0;
|
||||
|
||||
if (tp->get_button_state) {
|
||||
return tp->get_button_state(tp, n, state);
|
||||
} else {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_lcd_touch_set_swap_xy(esp_lcd_touch_handle_t tp, bool swap)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
tp->config.flags.swap_xy = swap;
|
||||
|
||||
/* Is swap supported by HW? */
|
||||
if (tp->set_swap_xy) {
|
||||
return tp->set_swap_xy(tp, swap);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_get_swap_xy(esp_lcd_touch_handle_t tp, bool *swap)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(swap != NULL);
|
||||
|
||||
/* Is swap supported by HW? */
|
||||
if (tp->get_swap_xy) {
|
||||
return tp->get_swap_xy(tp, swap);
|
||||
} else {
|
||||
*swap = tp->config.flags.swap_xy;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_set_mirror_x(esp_lcd_touch_handle_t tp, bool mirror)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
tp->config.flags.mirror_x = mirror;
|
||||
|
||||
/* Is mirror supported by HW? */
|
||||
if (tp->set_mirror_x) {
|
||||
return tp->set_mirror_x(tp, mirror);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_get_mirror_x(esp_lcd_touch_handle_t tp, bool *mirror)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(mirror != NULL);
|
||||
|
||||
/* Is swap supported by HW? */
|
||||
if (tp->get_mirror_x) {
|
||||
return tp->get_mirror_x(tp, mirror);
|
||||
} else {
|
||||
*mirror = tp->config.flags.mirror_x;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_set_mirror_y(esp_lcd_touch_handle_t tp, bool mirror)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
tp->config.flags.mirror_y = mirror;
|
||||
|
||||
/* Is mirror supported by HW? */
|
||||
if (tp->set_mirror_y) {
|
||||
return tp->set_mirror_y(tp, mirror);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_get_mirror_y(esp_lcd_touch_handle_t tp, bool *mirror)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(mirror != NULL);
|
||||
|
||||
/* Is swap supported by HW? */
|
||||
if (tp->get_mirror_y) {
|
||||
return tp->get_mirror_y(tp, mirror);
|
||||
} else {
|
||||
*mirror = tp->config.flags.mirror_y;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_del(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
if (tp->del != NULL) {
|
||||
return tp->del(tp);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_register_interrupt_callback(esp_lcd_touch_handle_t tp, esp_lcd_touch_interrupt_callback_t callback)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
assert(tp != NULL);
|
||||
|
||||
/* Interrupt pin is not selected */
|
||||
if (tp->config.int_gpio_num == GPIO_NUM_NC) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
tp->config.interrupt_callback = callback;
|
||||
|
||||
if (callback != NULL) {
|
||||
ret = gpio_install_isr_service(0);
|
||||
/* ISR service can be installed from user before, then it returns invalid state */
|
||||
if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) {
|
||||
ESP_LOGE(TAG, "GPIO ISR install failed");
|
||||
return ret;
|
||||
}
|
||||
/* Add GPIO ISR handler */
|
||||
ret = gpio_intr_enable(tp->config.int_gpio_num);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "GPIO ISR install failed");
|
||||
ret = gpio_isr_handler_add(tp->config.int_gpio_num, (gpio_isr_t)tp->config.interrupt_callback, tp);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "GPIO ISR install failed");
|
||||
} else {
|
||||
/* Remove GPIO ISR handler */
|
||||
ret = gpio_isr_handler_remove(tp->config.int_gpio_num);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "GPIO ISR remove handler failed");
|
||||
ret = gpio_intr_disable(tp->config.int_gpio_num);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "GPIO ISR disable failed");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_register_interrupt_callback_with_data(esp_lcd_touch_handle_t tp, esp_lcd_touch_interrupt_callback_t callback, void *user_data)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
tp->config.user_data = user_data;
|
||||
return esp_lcd_touch_register_interrupt_callback(tp, callback);
|
||||
}
|
||||
+436
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD touch
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "ESP_Panel_Conf_Internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_TOUCH_VER_MAJOR (1)
|
||||
#define ESP_LCD_TOUCH_VER_MINOR (1)
|
||||
#define ESP_LCD_TOUCH_VER_PATCH (1)
|
||||
|
||||
#define CONFIG_ESP_LCD_TOUCH_MAX_POINTS (ESP_PANEL_TOUCH_MAX_POINTS)
|
||||
#define CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS (ESP_PANEL_TOUCH_MAX_BUTTONS)
|
||||
|
||||
/**
|
||||
* @brief Touch controller type
|
||||
*
|
||||
*/
|
||||
typedef struct esp_lcd_touch_s esp_lcd_touch_t;
|
||||
typedef esp_lcd_touch_t *esp_lcd_touch_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Touch controller interrupt callback type
|
||||
*
|
||||
*/
|
||||
typedef void (*esp_lcd_touch_interrupt_callback_t)(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/**
|
||||
* @brief Touch Configuration Type
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t x_max; /*!< X coordinates max (for mirroring) */
|
||||
uint16_t y_max; /*!< Y coordinates max (for mirroring) */
|
||||
|
||||
gpio_num_t rst_gpio_num; /*!< GPIO number of reset pin */
|
||||
gpio_num_t int_gpio_num; /*!< GPIO number of interrupt pin */
|
||||
|
||||
struct {
|
||||
unsigned int reset: 1; /*!< Level of reset pin in reset */
|
||||
unsigned int interrupt: 1;/*!< Active Level of interrupt pin */
|
||||
} levels;
|
||||
|
||||
struct {
|
||||
unsigned int swap_xy: 1; /*!< Swap X and Y after read coordinates */
|
||||
unsigned int mirror_x: 1; /*!< Mirror X after read coordinates */
|
||||
unsigned int mirror_y: 1; /*!< Mirror Y after read coordinates */
|
||||
} flags;
|
||||
|
||||
/*!< User callback called after get coordinates from touch controller for apply user adjusting */
|
||||
void (*process_coordinates)(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
/*!< User callback called after the touch interrupt occured */
|
||||
esp_lcd_touch_interrupt_callback_t interrupt_callback;
|
||||
/*!< User data passed to callback */
|
||||
void *user_data;
|
||||
} esp_lcd_touch_config_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t points; /*!< Count of touch points saved */
|
||||
|
||||
struct {
|
||||
uint16_t x; /*!< X coordinate */
|
||||
uint16_t y; /*!< Y coordinate */
|
||||
uint16_t strength; /*!< Strength */
|
||||
} coords[CONFIG_ESP_LCD_TOUCH_MAX_POINTS];
|
||||
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
uint8_t buttons; /*!< Count of buttons states saved */
|
||||
|
||||
struct {
|
||||
uint8_t status; /*!< Status of button */
|
||||
} button[CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS];
|
||||
#endif
|
||||
|
||||
portMUX_TYPE lock; /*!< Lock for read/write */
|
||||
} esp_lcd_touch_data_t;
|
||||
|
||||
/**
|
||||
* @brief Declare of Touch Type
|
||||
*
|
||||
*/
|
||||
struct esp_lcd_touch_s {
|
||||
|
||||
/**
|
||||
* @brief set touch controller into sleep mode
|
||||
*
|
||||
* @note This function is usually blocking.
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*enter_sleep)(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/**
|
||||
* @brief set touch controller into normal mode
|
||||
*
|
||||
* @note This function is usually blocking.
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*exit_sleep)(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/**
|
||||
* @brief Read data from touch controller (mandatory)
|
||||
*
|
||||
* @note This function is usually blocking.
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*read_data)(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/**
|
||||
* @brief Get coordinates from touch controller (mandatory)
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param x: Array of X coordinates
|
||||
* @param y: Array of Y coordinates
|
||||
* @param strength: Array of strengths
|
||||
* @param point_num: Count of points touched (equals with count of items in x and y array)
|
||||
* @param max_point_num: Maximum count of touched points to return (equals with max size of x and y array)
|
||||
*
|
||||
* @return
|
||||
* - Returns true, when touched and coordinates readed. Otherwise returns false.
|
||||
*/
|
||||
bool (*get_xy)(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
|
||||
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
/**
|
||||
* @brief Get button state (optional)
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param n: Button index
|
||||
* @param state: Button state
|
||||
*
|
||||
* @return
|
||||
* - Returns true, when touched and coordinates readed. Otherwise returns false.
|
||||
*/
|
||||
esp_err_t (*get_button_state)(esp_lcd_touch_handle_t tp, uint8_t n, uint8_t *state);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Swap X and Y after read coordinates (optional)
|
||||
* If set, then not used SW swapping.
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param swap: Set swap value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*set_swap_xy)(esp_lcd_touch_handle_t tp, bool swap);
|
||||
|
||||
/**
|
||||
* @brief Are X and Y coordinates swapped (optional)
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param swap: Get swap value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*get_swap_xy)(esp_lcd_touch_handle_t tp, bool *swap);
|
||||
|
||||
/**
|
||||
* @brief Mirror X after read coordinates
|
||||
* If set, then not used SW mirroring.
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param mirror: Set X mirror value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*set_mirror_x)(esp_lcd_touch_handle_t tp, bool mirror);
|
||||
|
||||
/**
|
||||
* @brief Is mirrored X (optional)
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param mirror: Get X mirror value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*get_mirror_x)(esp_lcd_touch_handle_t tp, bool *mirror);
|
||||
|
||||
/**
|
||||
* @brief Mirror Y after read coordinates
|
||||
* If set, then not used SW mirroring.
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param mirror: Set Y mirror value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*set_mirror_y)(esp_lcd_touch_handle_t tp, bool mirror);
|
||||
|
||||
/**
|
||||
* @brief Is mirrored Y (optional)
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param mirror: Get Y mirror value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*get_mirror_y)(esp_lcd_touch_handle_t tp, bool *mirror);
|
||||
|
||||
/**
|
||||
* @brief Delete Touch
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t (*del)(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/**
|
||||
* @brief Configuration structure
|
||||
*/
|
||||
esp_lcd_touch_config_t config;
|
||||
|
||||
/**
|
||||
* @brief Communication interface
|
||||
*/
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
|
||||
/**
|
||||
* @brief Data structure
|
||||
*/
|
||||
esp_lcd_touch_data_t data;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read data from touch controller
|
||||
*
|
||||
* @note This function is usually blocking.
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG parameter error
|
||||
* - ESP_FAIL sending command error, slave hasn't ACK the transfer
|
||||
* - ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode
|
||||
* - ESP_ERR_TIMEOUT operation timeout because the bus is busy
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_read_data(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/**
|
||||
* @brief Read coordinates from touch controller
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param x: Array of X coordinates
|
||||
* @param y: Array of Y coordinates
|
||||
* @param strength: Array of the strengths (can be NULL)
|
||||
* @param point_num: Count of points touched (equals with count of items in x and y array)
|
||||
* @param max_point_num: Maximum count of touched points to return (equals with max size of x and y array)
|
||||
*
|
||||
* @return
|
||||
* - Returns true, when touched and coordinates readed. Otherwise returns false.
|
||||
*/
|
||||
bool esp_lcd_touch_get_coordinates(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
|
||||
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
/**
|
||||
* @brief Get button state
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param n: Button index
|
||||
* @param state: Button state
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NOT_SUPPORTED if this function is not supported by controller
|
||||
* - ESP_ERR_INVALID_ARG if bad button index
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_get_button_state(esp_lcd_touch_handle_t tp, uint8_t n, uint8_t *state);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Swap X and Y after read coordinates
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param swap: Set swap value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_set_swap_xy(esp_lcd_touch_handle_t tp, bool swap);
|
||||
|
||||
/**
|
||||
* @brief Are X and Y coordinates swapped
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param swap: Get swap value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_get_swap_xy(esp_lcd_touch_handle_t tp, bool *swap);
|
||||
|
||||
/**
|
||||
* @brief Mirror X after read coordinates
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param mirror: Set X mirror value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_set_mirror_x(esp_lcd_touch_handle_t tp, bool mirror);
|
||||
|
||||
/**
|
||||
* @brief Is mirrored X
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param mirror: Get X mirror value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_get_mirror_x(esp_lcd_touch_handle_t tp, bool *mirror);
|
||||
|
||||
/**
|
||||
* @brief Mirror Y after read coordinates
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param mirror: Set Y mirror value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_set_mirror_y(esp_lcd_touch_handle_t tp, bool mirror);
|
||||
|
||||
/**
|
||||
* @brief Is mirrored Y
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param mirror: Get Y mirror value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_get_mirror_y(esp_lcd_touch_handle_t tp, bool *mirror);
|
||||
|
||||
/**
|
||||
* @brief Delete touch (free all allocated memory and restart HW)
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_del(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/**
|
||||
* @brief Register user callback called after the touch interrupt occured
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param callback: Interrupt callback
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_register_interrupt_callback(esp_lcd_touch_handle_t tp, esp_lcd_touch_interrupt_callback_t callback);
|
||||
|
||||
/**
|
||||
* @brief Register user callback called after the touch interrupt occured with user data
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
* @param callback: Interrupt callback
|
||||
* @param user_data: User data passed to callback
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_register_interrupt_callback_with_data(esp_lcd_touch_handle_t tp, esp_lcd_touch_interrupt_callback_t callback, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Enter sleep mode
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_enter_sleep(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/**
|
||||
* @brief Exit sleep mode
|
||||
*
|
||||
* @param tp: Touch handler
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_exit_sleep(esp_lcd_touch_handle_t tp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#include "esp_lcd_touch_cst816s.h"
|
||||
|
||||
#define POINT_NUM_MAX (1)
|
||||
|
||||
#define DATA_START_REG (0x02)
|
||||
#define CHIP_ID_REG (0xA7)
|
||||
|
||||
static const char *TAG = "CST816S";
|
||||
|
||||
static esp_err_t read_data(esp_lcd_touch_handle_t tp);
|
||||
static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
static esp_err_t del(esp_lcd_touch_handle_t tp);
|
||||
|
||||
static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len);
|
||||
|
||||
static esp_err_t reset(esp_lcd_touch_handle_t tp);
|
||||
static esp_err_t read_id(esp_lcd_touch_handle_t tp);
|
||||
|
||||
esp_err_t esp_lcd_touch_new_i2c_cst816s(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_ARG, TAG, "Invalid io");
|
||||
ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "Invalid config");
|
||||
ESP_RETURN_ON_FALSE(tp, ESP_ERR_INVALID_ARG, TAG, "Invalid touch handle");
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
/* Prepare main structure */
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_lcd_touch_handle_t cst816s = calloc(1, sizeof(esp_lcd_touch_t));
|
||||
ESP_GOTO_ON_FALSE(cst816s, ESP_ERR_NO_MEM, err, TAG, "Touch handle malloc failed");
|
||||
|
||||
/* Communication interface */
|
||||
cst816s->io = io;
|
||||
/* Only supported callbacks are set */
|
||||
cst816s->read_data = read_data;
|
||||
cst816s->get_xy = get_xy;
|
||||
cst816s->del = del;
|
||||
/* Mutex */
|
||||
cst816s->data.lock.owner = portMUX_FREE_VAL;
|
||||
/* Save config */
|
||||
memcpy(&cst816s->config, config, sizeof(esp_lcd_touch_config_t));
|
||||
|
||||
/* Prepare pin for touch interrupt */
|
||||
if (cst816s->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t int_gpio_config = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.intr_type = (cst816s->config.levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE),
|
||||
.pin_bit_mask = BIT64(cst816s->config.int_gpio_num)
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&int_gpio_config), err, TAG, "GPIO intr config failed");
|
||||
|
||||
/* Register interrupt callback */
|
||||
if (cst816s->config.interrupt_callback) {
|
||||
esp_lcd_touch_register_interrupt_callback(cst816s, cst816s->config.interrupt_callback);
|
||||
}
|
||||
}
|
||||
/* Prepare pin for touch controller reset */
|
||||
if (cst816s->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t rst_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(cst816s->config.rst_gpio_num)
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&rst_gpio_config), err, TAG, "GPIO reset config failed");
|
||||
}
|
||||
/* Reset controller */
|
||||
ESP_GOTO_ON_ERROR(reset(cst816s), err, TAG, "Reset failed");
|
||||
/* Read product id */
|
||||
ESP_GOTO_ON_ERROR(read_id(cst816s), err, TAG, "Read version failed");
|
||||
*tp = cst816s;
|
||||
|
||||
ESP_LOGI(TAG, "LCD touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_CST816S_VER_MAJOR, ESP_LCD_TOUCH_CST816S_VER_MINOR,
|
||||
ESP_LCD_TOUCH_CST816S_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (cst816s) {
|
||||
del(cst816s);
|
||||
}
|
||||
ESP_LOGE(TAG, "Initialization failed!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t num;
|
||||
uint8_t x_h : 4;
|
||||
uint8_t : 4;
|
||||
uint8_t x_l;
|
||||
uint8_t y_h : 4;
|
||||
uint8_t : 4;
|
||||
uint8_t y_l;
|
||||
} data_t;
|
||||
|
||||
data_t point;
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, DATA_START_REG, (uint8_t *)&point, sizeof(data_t)), TAG, "I2C read failed");
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
point.num = (point.num > POINT_NUM_MAX ? POINT_NUM_MAX : point.num);
|
||||
tp->data.points = point.num;
|
||||
/* Fill all coordinates */
|
||||
for (int i = 0; i < point.num; i++) {
|
||||
tp->data.coords[i].x = point.x_h << 8 | point.x_l;
|
||||
tp->data.coords[i].y = point.y_h << 8 | point.y_l;
|
||||
}
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
|
||||
{
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
/* Count of points */
|
||||
*point_num = (tp->data.points > max_point_num ? max_point_num : tp->data.points);
|
||||
for (size_t i = 0; i < *point_num; i++) {
|
||||
x[i] = tp->data.coords[i].x;
|
||||
y[i] = tp->data.coords[i].y;
|
||||
|
||||
if (strength) {
|
||||
strength[i] = tp->data.coords[i].strength;
|
||||
}
|
||||
}
|
||||
/* Invalidate */
|
||||
tp->data.points = 0;
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return (*point_num > 0);
|
||||
}
|
||||
|
||||
static esp_err_t del(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.int_gpio_num);
|
||||
if (tp->config.interrupt_callback) {
|
||||
gpio_isr_handler_remove(tp->config.int_gpio_num);
|
||||
}
|
||||
}
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.rst_gpio_num);
|
||||
}
|
||||
/* Release memory */
|
||||
free(tp);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t reset(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_id(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
uint8_t id;
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, CHIP_ID_REG, &id, 1), TAG, "I2C read failed");
|
||||
ESP_LOGI(TAG, "IC id: %d", id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(data, ESP_ERR_INVALID_ARG, TAG, "Invalid data");
|
||||
|
||||
return esp_lcd_panel_io_rx_param(tp->io, reg, data, len);
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD touch: CST816S
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_TOUCH_CST816S_VER_MAJOR (1)
|
||||
#define ESP_LCD_TOUCH_CST816S_VER_MINOR (0)
|
||||
#define ESP_LCD_TOUCH_CST816S_VER_PATCH (3)
|
||||
|
||||
/**
|
||||
* @brief Create a new CST816S touch driver
|
||||
*
|
||||
* @note The I2C communication should be initialized before use this function.
|
||||
*
|
||||
* @param io LCD panel IO handle, it should be created by `esp_lcd_new_panel_io_i2c()`
|
||||
* @param config Touch panel configuration
|
||||
* @param tp Touch panel handle
|
||||
* @return
|
||||
* - ESP_OK: on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_new_i2c_cst816s(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp);
|
||||
|
||||
/**
|
||||
* @brief I2C address of the CST816S controller
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS (0x15)
|
||||
|
||||
/**
|
||||
* @brief Touch IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG() \
|
||||
{ \
|
||||
.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS, \
|
||||
.control_phase_bytes = 1, \
|
||||
.dc_bit_offset = 0, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.flags = \
|
||||
{ \
|
||||
.disable_control_phase = 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+340
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#include "esp_lcd_touch_ft5x06.h"
|
||||
|
||||
static const char *TAG = "FT5x06";
|
||||
|
||||
/* Registers */
|
||||
#define FT5x06_DEVICE_MODE (0x00)
|
||||
#define FT5x06_GESTURE_ID (0x01)
|
||||
#define FT5x06_TOUCH_POINTS (0x02)
|
||||
|
||||
#define FT5x06_TOUCH1_EV_FLAG (0x03)
|
||||
#define FT5x06_TOUCH1_XH (0x03)
|
||||
#define FT5x06_TOUCH1_XL (0x04)
|
||||
#define FT5x06_TOUCH1_YH (0x05)
|
||||
#define FT5x06_TOUCH1_YL (0x06)
|
||||
|
||||
#define FT5x06_TOUCH2_EV_FLAG (0x09)
|
||||
#define FT5x06_TOUCH2_XH (0x09)
|
||||
#define FT5x06_TOUCH2_XL (0x0A)
|
||||
#define FT5x06_TOUCH2_YH (0x0B)
|
||||
#define FT5x06_TOUCH2_YL (0x0C)
|
||||
|
||||
#define FT5x06_TOUCH3_EV_FLAG (0x0F)
|
||||
#define FT5x06_TOUCH3_XH (0x0F)
|
||||
#define FT5x06_TOUCH3_XL (0x10)
|
||||
#define FT5x06_TOUCH3_YH (0x11)
|
||||
#define FT5x06_TOUCH3_YL (0x12)
|
||||
|
||||
#define FT5x06_TOUCH4_EV_FLAG (0x15)
|
||||
#define FT5x06_TOUCH4_XH (0x15)
|
||||
#define FT5x06_TOUCH4_XL (0x16)
|
||||
#define FT5x06_TOUCH4_YH (0x17)
|
||||
#define FT5x06_TOUCH4_YL (0x18)
|
||||
|
||||
#define FT5x06_TOUCH5_EV_FLAG (0x1B)
|
||||
#define FT5x06_TOUCH5_XH (0x1B)
|
||||
#define FT5x06_TOUCH5_XL (0x1C)
|
||||
#define FT5x06_TOUCH5_YH (0x1D)
|
||||
#define FT5x06_TOUCH5_YL (0x1E)
|
||||
|
||||
#define FT5x06_ID_G_THGROUP (0x80)
|
||||
#define FT5x06_ID_G_THPEAK (0x81)
|
||||
#define FT5x06_ID_G_THCAL (0x82)
|
||||
#define FT5x06_ID_G_THWATER (0x83)
|
||||
#define FT5x06_ID_G_THTEMP (0x84)
|
||||
#define FT5x06_ID_G_THDIFF (0x85)
|
||||
#define FT5x06_ID_G_CTRL (0x86)
|
||||
#define FT5x06_ID_G_TIME_ENTER_MONITOR (0x87)
|
||||
#define FT5x06_ID_G_PERIODACTIVE (0x88)
|
||||
#define FT5x06_ID_G_PERIODMONITOR (0x89)
|
||||
#define FT5x06_ID_G_AUTO_CLB_MODE (0xA0)
|
||||
#define FT5x06_ID_G_LIB_VERSION_H (0xA1)
|
||||
#define FT5x06_ID_G_LIB_VERSION_L (0xA2)
|
||||
#define FT5x06_ID_G_CIPHER (0xA3)
|
||||
#define FT5x06_ID_G_MODE (0xA4)
|
||||
#define FT5x06_ID_G_PMODE (0xA5)
|
||||
#define FT5x06_ID_G_FIRMID (0xA6)
|
||||
#define FT5x06_ID_G_STATE (0xA7)
|
||||
#define FT5x06_ID_G_FT5201ID (0xA8)
|
||||
#define FT5x06_ID_G_ERR (0xA9)
|
||||
|
||||
/*******************************************************************************
|
||||
* Function definitions
|
||||
*******************************************************************************/
|
||||
static esp_err_t esp_lcd_touch_ft5x06_read_data(esp_lcd_touch_handle_t tp);
|
||||
static bool esp_lcd_touch_ft5x06_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
static esp_err_t esp_lcd_touch_ft5x06_del(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/* I2C read */
|
||||
static esp_err_t touch_ft5x06_i2c_write(esp_lcd_touch_handle_t tp, uint8_t reg, uint8_t data);
|
||||
static esp_err_t touch_ft5x06_i2c_read(esp_lcd_touch_handle_t tp, uint8_t reg, uint8_t *data, uint8_t len);
|
||||
|
||||
/* FT5x06 init */
|
||||
static esp_err_t touch_ft5x06_init(esp_lcd_touch_handle_t tp);
|
||||
/* FT5x06 reset */
|
||||
static esp_err_t touch_ft5x06_reset(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/*******************************************************************************
|
||||
* Public API functions
|
||||
*******************************************************************************/
|
||||
|
||||
esp_err_t esp_lcd_touch_new_i2c_ft5x06(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *out_touch)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
assert(config != NULL);
|
||||
assert(out_touch != NULL);
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
/* Prepare main structure */
|
||||
esp_lcd_touch_handle_t esp_lcd_touch_ft5x06 = heap_caps_calloc(1, sizeof(esp_lcd_touch_t), MALLOC_CAP_DEFAULT);
|
||||
ESP_GOTO_ON_FALSE(esp_lcd_touch_ft5x06, ESP_ERR_NO_MEM, err, TAG, "no mem for FT5x06 controller");
|
||||
|
||||
/* Communication interface */
|
||||
esp_lcd_touch_ft5x06->io = io;
|
||||
|
||||
/* Only supported callbacks are set */
|
||||
esp_lcd_touch_ft5x06->read_data = esp_lcd_touch_ft5x06_read_data;
|
||||
esp_lcd_touch_ft5x06->get_xy = esp_lcd_touch_ft5x06_get_xy;
|
||||
esp_lcd_touch_ft5x06->del = esp_lcd_touch_ft5x06_del;
|
||||
|
||||
/* Mutex */
|
||||
esp_lcd_touch_ft5x06->data.lock.owner = portMUX_FREE_VAL;
|
||||
|
||||
/* Save config */
|
||||
memcpy(&esp_lcd_touch_ft5x06->config, config, sizeof(esp_lcd_touch_config_t));
|
||||
|
||||
/* Prepare pin for touch interrupt */
|
||||
if (esp_lcd_touch_ft5x06->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t int_gpio_config = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.intr_type = (esp_lcd_touch_ft5x06->config.levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE),
|
||||
.pin_bit_mask = BIT64(esp_lcd_touch_ft5x06->config.int_gpio_num)
|
||||
};
|
||||
ret = gpio_config(&int_gpio_config);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "GPIO config failed");
|
||||
|
||||
/* Register interrupt callback */
|
||||
if (esp_lcd_touch_ft5x06->config.interrupt_callback) {
|
||||
esp_lcd_touch_register_interrupt_callback(esp_lcd_touch_ft5x06, esp_lcd_touch_ft5x06->config.interrupt_callback);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare pin for touch controller reset */
|
||||
if (esp_lcd_touch_ft5x06->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t rst_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(esp_lcd_touch_ft5x06->config.rst_gpio_num)
|
||||
};
|
||||
ret = gpio_config(&rst_gpio_config);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "GPIO config failed");
|
||||
}
|
||||
|
||||
/* Reset controller */
|
||||
ret = touch_ft5x06_reset(esp_lcd_touch_ft5x06);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "FT5x06 reset failed");
|
||||
|
||||
/* Init controller */
|
||||
ret = touch_ft5x06_init(esp_lcd_touch_ft5x06);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "FT5x06 init failed");
|
||||
|
||||
err:
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (0x%x)! Touch controller FT5x06 initialization failed!", ret);
|
||||
if (esp_lcd_touch_ft5x06) {
|
||||
esp_lcd_touch_ft5x06_del(esp_lcd_touch_ft5x06);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
*out_touch = esp_lcd_touch_ft5x06;
|
||||
|
||||
ESP_LOGI(TAG, "LCD touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_FT5x06_VER_MAJOR, ESP_LCD_TOUCH_FT5x06_VER_MINOR,
|
||||
ESP_LCD_TOUCH_FT5x06_VER_PATCH);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_lcd_touch_ft5x06_read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint8_t data[30];
|
||||
uint8_t points;
|
||||
size_t i = 0;
|
||||
|
||||
assert(tp != NULL);
|
||||
|
||||
err = touch_ft5x06_i2c_read(tp, FT5x06_TOUCH_POINTS, &points, 1);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C read error!");
|
||||
|
||||
if (points > 5 || points == 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Number of touched points */
|
||||
points = (points > CONFIG_ESP_LCD_TOUCH_MAX_POINTS ? CONFIG_ESP_LCD_TOUCH_MAX_POINTS : points);
|
||||
|
||||
err = touch_ft5x06_i2c_read(tp, FT5x06_TOUCH1_XH, data, 6 * points);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C read error!");
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
|
||||
/* Number of touched points */
|
||||
tp->data.points = points;
|
||||
|
||||
/* Fill all coordinates */
|
||||
for (i = 0; i < points; i++) {
|
||||
tp->data.coords[i].x = (((uint16_t)data[(i * 6) + 0] & 0x0f) << 8) + data[(i * 6) + 1];
|
||||
tp->data.coords[i].y = (((uint16_t)data[(i * 6) + 2] & 0x0f) << 8) + data[(i * 6) + 3];
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool esp_lcd_touch_ft5x06_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(x != NULL);
|
||||
assert(y != NULL);
|
||||
assert(point_num != NULL);
|
||||
assert(max_point_num > 0);
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
|
||||
/* Count of points */
|
||||
*point_num = (tp->data.points > max_point_num ? max_point_num : tp->data.points);
|
||||
|
||||
for (size_t i = 0; i < *point_num; i++) {
|
||||
x[i] = tp->data.coords[i].x;
|
||||
y[i] = tp->data.coords[i].y;
|
||||
|
||||
if (strength) {
|
||||
strength[i] = tp->data.coords[i].strength;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalidate */
|
||||
tp->data.points = 0;
|
||||
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return (*point_num > 0);
|
||||
}
|
||||
|
||||
static esp_err_t esp_lcd_touch_ft5x06_del(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.int_gpio_num);
|
||||
if (tp->config.interrupt_callback) {
|
||||
gpio_isr_handler_remove(tp->config.int_gpio_num);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.rst_gpio_num);
|
||||
}
|
||||
|
||||
free(tp);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Private API function
|
||||
*******************************************************************************/
|
||||
|
||||
static esp_err_t touch_ft5x06_init(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
// Valid touching detect threshold
|
||||
ret |= touch_ft5x06_i2c_write(tp, FT5x06_ID_G_THGROUP, 70);
|
||||
|
||||
// valid touching peak detect threshold
|
||||
ret |= touch_ft5x06_i2c_write(tp, FT5x06_ID_G_THPEAK, 60);
|
||||
|
||||
// Touch focus threshold
|
||||
ret |= touch_ft5x06_i2c_write(tp, FT5x06_ID_G_THCAL, 16);
|
||||
|
||||
// threshold when there is surface water
|
||||
ret |= touch_ft5x06_i2c_write(tp, FT5x06_ID_G_THWATER, 60);
|
||||
|
||||
// threshold of temperature compensation
|
||||
ret |= touch_ft5x06_i2c_write(tp, FT5x06_ID_G_THTEMP, 10);
|
||||
|
||||
// Touch difference threshold
|
||||
ret |= touch_ft5x06_i2c_write(tp, FT5x06_ID_G_THDIFF, 20);
|
||||
|
||||
// Delay to enter 'Monitor' status (s)
|
||||
ret |= touch_ft5x06_i2c_write(tp, FT5x06_ID_G_TIME_ENTER_MONITOR, 2);
|
||||
|
||||
// Period of 'Active' status (ms)
|
||||
ret |= touch_ft5x06_i2c_write(tp, FT5x06_ID_G_PERIODACTIVE, 12);
|
||||
|
||||
// Timer to enter 'idle' when in 'Monitor' (ms)
|
||||
ret |= touch_ft5x06_i2c_write(tp, FT5x06_ID_G_PERIODMONITOR, 40);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset controller */
|
||||
static esp_err_t touch_ft5x06_reset(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level error!");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level error!");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t touch_ft5x06_i2c_write(esp_lcd_touch_handle_t tp, uint8_t reg, uint8_t data)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
// *INDENT-OFF*
|
||||
/* Write data */
|
||||
return esp_lcd_panel_io_tx_param(tp->io, reg, (uint8_t[]){data}, 1);
|
||||
// *INDENT-ON*
|
||||
}
|
||||
|
||||
static esp_err_t touch_ft5x06_i2c_read(esp_lcd_touch_handle_t tp, uint8_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(data != NULL);
|
||||
|
||||
/* Read data */
|
||||
return esp_lcd_panel_io_rx_param(tp->io, reg, data, len);
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD touch: FT5x06
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_TOUCH_FT5x06_VER_MAJOR (1)
|
||||
#define ESP_LCD_TOUCH_FT5x06_VER_MINOR (0)
|
||||
#define ESP_LCD_TOUCH_FT5x06_VER_PATCH (6)
|
||||
|
||||
/**
|
||||
* @brief Create a new FT5x06 touch driver
|
||||
*
|
||||
* @note The I2C communication should be initialized before use this function.
|
||||
*
|
||||
* @param io LCD/Touch panel IO handle
|
||||
* @param config: Touch configuration
|
||||
* @param out_touch: Touch instance handle
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM if there is no memory for allocating main structure
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_new_i2c_ft5x06(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *out_touch);
|
||||
|
||||
/**
|
||||
* @brief I2C address of the FT5x06 controller
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_FT5x06_ADDRESS (0x38)
|
||||
|
||||
/**
|
||||
* @brief Touch IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG() \
|
||||
{ \
|
||||
.dev_addr = ESP_LCD_TOUCH_IO_I2C_FT5x06_ADDRESS, \
|
||||
.control_phase_bytes = 1, \
|
||||
.dc_bit_offset = 0, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.flags = \
|
||||
{ \
|
||||
.disable_control_phase = 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#include "esp_lcd_touch_gt1151.h"
|
||||
|
||||
static const char *TAG = "gt1151";
|
||||
|
||||
#define READ_XY_REG (0x814E)
|
||||
#define PRODUCT_ID_REG (0x8140)
|
||||
|
||||
#define MAX_TOUCH_NUM (10)
|
||||
/* Buffer Length = StatusReg(1) + TouchData(8 * TouchNum) + KeyValue(1) + Checksum(1) */
|
||||
#define DATA_BUFF_LEN(touch_num) (1 + 8 * (touch_num) + 2)
|
||||
#define IS_NUM_OR_CHAR(x) (((x) >= 'A' && (x) <= 'Z') || ((x) >= '0' && (x) <= '9'))
|
||||
|
||||
static esp_err_t read_data(esp_lcd_touch_handle_t tp);
|
||||
static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
static esp_err_t del(esp_lcd_touch_handle_t tp);
|
||||
|
||||
static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len);
|
||||
static esp_err_t i2c_write_byte(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t data);
|
||||
|
||||
static esp_err_t reset(esp_lcd_touch_handle_t tp);
|
||||
static esp_err_t read_product_id(esp_lcd_touch_handle_t tp);
|
||||
|
||||
esp_err_t esp_lcd_touch_new_i2c_gt1151(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_ARG, TAG, "Invalid io");
|
||||
ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "Invalid config");
|
||||
ESP_RETURN_ON_FALSE(tp, ESP_ERR_INVALID_ARG, TAG, "Invalid touch handle");
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
/* Prepare main structure */
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_lcd_touch_handle_t gt1151 = calloc(1, sizeof(esp_lcd_touch_t));
|
||||
ESP_GOTO_ON_FALSE(gt1151, ESP_ERR_NO_MEM, err, TAG, "Touch handle malloc failed");
|
||||
|
||||
/* Communication interface */
|
||||
gt1151->io = io;
|
||||
/* Only supported callbacks are set */
|
||||
gt1151->read_data = read_data;
|
||||
gt1151->get_xy = get_xy;
|
||||
gt1151->del = del;
|
||||
/* Mutex */
|
||||
gt1151->data.lock.owner = portMUX_FREE_VAL;
|
||||
/* Save config */
|
||||
memcpy(>1151->config, config, sizeof(esp_lcd_touch_config_t));
|
||||
|
||||
/* Prepare pin for touch interrupt */
|
||||
if (gt1151->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t int_gpio_config = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.intr_type = (gt1151->config.levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE),
|
||||
.pin_bit_mask = BIT64(gt1151->config.int_gpio_num)
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&int_gpio_config), err, TAG, "GPIO intr config failed");
|
||||
|
||||
/* Register interrupt callback */
|
||||
if (gt1151->config.interrupt_callback) {
|
||||
esp_lcd_touch_register_interrupt_callback(gt1151, gt1151->config.interrupt_callback);
|
||||
}
|
||||
}
|
||||
/* Prepare pin for touch controller reset */
|
||||
if (gt1151->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t rst_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(gt1151->config.rst_gpio_num)
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&rst_gpio_config), err, TAG, "GPIO reset config failed");
|
||||
}
|
||||
/* Reset controller */
|
||||
ESP_GOTO_ON_ERROR(reset(gt1151), err, TAG, "Reset failed");
|
||||
/* Read product id */
|
||||
ESP_GOTO_ON_ERROR(read_product_id(gt1151), err, TAG, "Read product id failed");
|
||||
*tp = gt1151;
|
||||
|
||||
ESP_LOGI(TAG, "LCD touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_GT1151_VER_MAJOR, ESP_LCD_TOUCH_GT1151_VER_MINOR,
|
||||
ESP_LCD_TOUCH_GT1151_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (gt1151) {
|
||||
del(gt1151);
|
||||
}
|
||||
ESP_LOGE(TAG, "Initialization failed!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t touch_id : 4;
|
||||
uint8_t : 4;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t strength;
|
||||
uint8_t useless;
|
||||
} __attribute__((packed)) touch_record_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t touch_cnt : 4;
|
||||
uint8_t : 4;
|
||||
touch_record_t touch_record[0];
|
||||
} __attribute__((packed)) touch_report_t;
|
||||
|
||||
uint8_t touch_cnt;
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, READ_XY_REG, &touch_cnt, sizeof(touch_cnt)), TAG, "I2C read failed!");
|
||||
touch_cnt &= 0x0f;
|
||||
/* Any touch data? */
|
||||
if (touch_cnt > MAX_TOUCH_NUM || touch_cnt == 0) {
|
||||
i2c_write_byte(tp, READ_XY_REG, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t buf[DATA_BUFF_LEN(MAX_TOUCH_NUM)];
|
||||
/* Read all points */
|
||||
ESP_RETURN_ON_ERROR( i2c_read_bytes(tp, READ_XY_REG, buf, DATA_BUFF_LEN(touch_cnt)), TAG, "I2C read failed");
|
||||
/* Clear all */
|
||||
i2c_write_byte(tp, READ_XY_REG, 0);
|
||||
/* Caculate checksum */
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < DATA_BUFF_LEN(touch_cnt); i++) {
|
||||
checksum += buf[i];
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(!checksum, ESP_ERR_INVALID_CRC, TAG, "Checksum error");
|
||||
|
||||
touch_report_t *touch_report = (touch_report_t *)buf;
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
/* Expect Number of touched points */
|
||||
touch_cnt = (touch_cnt > CONFIG_ESP_LCD_TOUCH_MAX_POINTS ? CONFIG_ESP_LCD_TOUCH_MAX_POINTS : touch_cnt);
|
||||
tp->data.points = touch_cnt;
|
||||
|
||||
/* Fill all coordinates */
|
||||
for (int i = 0; i < touch_cnt; i++) {
|
||||
tp->data.coords[i].x = touch_report->touch_record[i].x;
|
||||
tp->data.coords[i].y = touch_report->touch_record[i].y;
|
||||
tp->data.coords[i].strength = touch_report->touch_record[i].strength;
|
||||
}
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
|
||||
{
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
/* Count of points */
|
||||
*point_num = (tp->data.points > max_point_num ? max_point_num : tp->data.points);
|
||||
for (size_t i = 0; i < *point_num; i++) {
|
||||
x[i] = tp->data.coords[i].x;
|
||||
y[i] = tp->data.coords[i].y;
|
||||
|
||||
if (strength) {
|
||||
strength[i] = tp->data.coords[i].strength;
|
||||
}
|
||||
}
|
||||
/* Invalidate */
|
||||
tp->data.points = 0;
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return (*point_num > 0);
|
||||
}
|
||||
|
||||
static esp_err_t del(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.int_gpio_num);
|
||||
if (tp->config.interrupt_callback) {
|
||||
gpio_isr_handler_remove(tp->config.int_gpio_num);
|
||||
}
|
||||
}
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.rst_gpio_num);
|
||||
}
|
||||
/* Release memory */
|
||||
free(tp);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t reset(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_product_id(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
uint8_t buf[11] = {0};
|
||||
uint8_t checksum = 0;
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, PRODUCT_ID_REG, buf, sizeof(buf)), TAG, "I2C read failed");
|
||||
for (int i = 0; i < sizeof(buf); i++) {
|
||||
checksum += buf[i];
|
||||
}
|
||||
/* First 3 bytes must be number or char, and sensor id != 0xFF */
|
||||
ESP_RETURN_ON_FALSE(checksum, ESP_ERR_INVALID_CRC, TAG, "Checksum error");
|
||||
ESP_RETURN_ON_FALSE(
|
||||
IS_NUM_OR_CHAR(buf[0]) && IS_NUM_OR_CHAR(buf[1]) && IS_NUM_OR_CHAR(buf[2]) && buf[10] != 0xFF,
|
||||
ESP_ERR_INVALID_CRC, TAG, "Product id format error");
|
||||
|
||||
uint32_t mask_id, patch_id, sensor_id;
|
||||
char product_id[5] = {0};
|
||||
mask_id = (uint32_t) ((buf[7] << 16) | (buf[8] << 8) | buf[9]);
|
||||
patch_id = (uint32_t) ((buf[4] << 16) | (buf[5] << 8) | buf[6]);
|
||||
memcpy(product_id, buf, 4);
|
||||
sensor_id = buf[10] & 0x0F;
|
||||
ESP_LOGI(
|
||||
TAG, "IC version: GT%s_%06" PRIX32 "(Patch)_%04" PRIX32 "(Mask)_%02" PRIX32 "(SensorID)",
|
||||
product_id, patch_id, mask_id >> 8, sensor_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(data, ESP_ERR_INVALID_ARG, TAG, "Invalid data");
|
||||
|
||||
return esp_lcd_panel_io_rx_param(tp->io, reg, data, len);
|
||||
}
|
||||
|
||||
static esp_err_t i2c_write_byte(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t data)
|
||||
{
|
||||
// *INDENT-OFF*
|
||||
return esp_lcd_panel_io_tx_param(tp->io, reg, (uint8_t[]){data}, 1);
|
||||
// *INDENT-ON*
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD touch: GT1151
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_TOUCH_GT1151_VER_MAJOR (1)
|
||||
#define ESP_LCD_TOUCH_GT1151_VER_MINOR (0)
|
||||
#define ESP_LCD_TOUCH_GT1151_VER_PATCH (5)
|
||||
|
||||
/**
|
||||
* @brief Create a new GT1151 touch driver
|
||||
*
|
||||
* @note The I2C communication should be initialized before use this function.
|
||||
*
|
||||
* @param io LCD panel IO handle, it should be created by `esp_lcd_new_panel_io_i2c()`
|
||||
* @param config Touch panel configuration
|
||||
* @param tp Touch panel handle
|
||||
* @return
|
||||
* - ESP_OK: on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_new_i2c_gt1151(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp);
|
||||
|
||||
/**
|
||||
* @brief I2C address of the GT1151 controller
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_GT1151_ADDRESS (0x14)
|
||||
|
||||
/**
|
||||
* @brief Touch IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_GT1151_CONFIG() \
|
||||
{ \
|
||||
.dev_addr = ESP_LCD_TOUCH_IO_I2C_GT1151_ADDRESS, \
|
||||
.control_phase_bytes = 1, \
|
||||
.dc_bit_offset = 0, \
|
||||
.lcd_cmd_bits = 16, \
|
||||
.flags = \
|
||||
{ \
|
||||
.disable_control_phase = 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+388
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#include "esp_lcd_touch_gt911.h"
|
||||
|
||||
static const char *TAG = "GT911";
|
||||
|
||||
/* GT911 registers */
|
||||
#define ESP_LCD_TOUCH_GT911_READ_KEY_REG (0x8093)
|
||||
#define ESP_LCD_TOUCH_GT911_READ_XY_REG (0x814E)
|
||||
#define ESP_LCD_TOUCH_GT911_CONFIG_REG (0x8047)
|
||||
#define ESP_LCD_TOUCH_GT911_PRODUCT_ID_REG (0x8140)
|
||||
#define ESP_LCD_TOUCH_GT911_ENTER_SLEEP (0x8040)
|
||||
|
||||
/* GT911 support key num */
|
||||
#define ESP_GT911_TOUCH_MAX_BUTTONS (4)
|
||||
|
||||
/*******************************************************************************
|
||||
* Function definitions
|
||||
*******************************************************************************/
|
||||
static esp_err_t esp_lcd_touch_gt911_read_data(esp_lcd_touch_handle_t tp);
|
||||
static bool esp_lcd_touch_gt911_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
static esp_err_t esp_lcd_touch_gt911_get_button_state(esp_lcd_touch_handle_t tp, uint8_t n, uint8_t *state);
|
||||
#endif
|
||||
static esp_err_t esp_lcd_touch_gt911_del(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/* I2C read/write */
|
||||
static esp_err_t touch_gt911_i2c_read(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len);
|
||||
static esp_err_t touch_gt911_i2c_write(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t data);
|
||||
|
||||
/* GT911 reset */
|
||||
static esp_err_t touch_gt911_reset(esp_lcd_touch_handle_t tp);
|
||||
/* Read status and config register */
|
||||
static esp_err_t touch_gt911_read_cfg(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/* GT911 enter/exit sleep mode */
|
||||
static esp_err_t esp_lcd_touch_gt911_enter_sleep(esp_lcd_touch_handle_t tp);
|
||||
static esp_err_t esp_lcd_touch_gt911_exit_sleep(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/*******************************************************************************
|
||||
* Public API functions
|
||||
*******************************************************************************/
|
||||
|
||||
esp_err_t esp_lcd_touch_new_i2c_gt911(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *out_touch)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
assert(io != NULL);
|
||||
assert(config != NULL);
|
||||
assert(out_touch != NULL);
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
/* Prepare main structure */
|
||||
esp_lcd_touch_handle_t esp_lcd_touch_gt911 = heap_caps_calloc(1, sizeof(esp_lcd_touch_t), MALLOC_CAP_DEFAULT);
|
||||
ESP_GOTO_ON_FALSE(esp_lcd_touch_gt911, ESP_ERR_NO_MEM, err, TAG, "no mem for GT911 controller");
|
||||
|
||||
/* Communication interface */
|
||||
esp_lcd_touch_gt911->io = io;
|
||||
|
||||
/* Only supported callbacks are set */
|
||||
esp_lcd_touch_gt911->read_data = esp_lcd_touch_gt911_read_data;
|
||||
esp_lcd_touch_gt911->get_xy = esp_lcd_touch_gt911_get_xy;
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
esp_lcd_touch_gt911->get_button_state = esp_lcd_touch_gt911_get_button_state;
|
||||
#endif
|
||||
esp_lcd_touch_gt911->del = esp_lcd_touch_gt911_del;
|
||||
esp_lcd_touch_gt911->enter_sleep = esp_lcd_touch_gt911_enter_sleep;
|
||||
esp_lcd_touch_gt911->exit_sleep = esp_lcd_touch_gt911_exit_sleep;
|
||||
|
||||
/* Mutex */
|
||||
esp_lcd_touch_gt911->data.lock.owner = portMUX_FREE_VAL;
|
||||
|
||||
/* Save config */
|
||||
memcpy(&esp_lcd_touch_gt911->config, config, sizeof(esp_lcd_touch_config_t));
|
||||
|
||||
/* Prepare pin for touch interrupt */
|
||||
if (esp_lcd_touch_gt911->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t int_gpio_config = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.intr_type = (esp_lcd_touch_gt911->config.levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE),
|
||||
.pin_bit_mask = BIT64(esp_lcd_touch_gt911->config.int_gpio_num)
|
||||
};
|
||||
ret = gpio_config(&int_gpio_config);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "GPIO config failed");
|
||||
|
||||
/* Register interrupt callback */
|
||||
if (esp_lcd_touch_gt911->config.interrupt_callback) {
|
||||
esp_lcd_touch_register_interrupt_callback(esp_lcd_touch_gt911, esp_lcd_touch_gt911->config.interrupt_callback);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare pin for touch controller reset */
|
||||
if (esp_lcd_touch_gt911->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t rst_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(esp_lcd_touch_gt911->config.rst_gpio_num)
|
||||
};
|
||||
ret = gpio_config(&rst_gpio_config);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "GPIO config failed");
|
||||
}
|
||||
|
||||
/* Reset controller */
|
||||
ret = touch_gt911_reset(esp_lcd_touch_gt911);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "GT911 reset failed");
|
||||
|
||||
/* Read status and config info */
|
||||
ret = touch_gt911_read_cfg(esp_lcd_touch_gt911);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "GT911 init failed");
|
||||
|
||||
err:
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (0x%x)! Touch controller GT911 initialization failed!", ret);
|
||||
if (esp_lcd_touch_gt911) {
|
||||
esp_lcd_touch_gt911_del(esp_lcd_touch_gt911);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
*out_touch = esp_lcd_touch_gt911;
|
||||
|
||||
ESP_LOGI(TAG, "LCD touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_GT911_VER_MAJOR, ESP_LCD_TOUCH_GT911_VER_MINOR,
|
||||
ESP_LCD_TOUCH_GT911_VER_PATCH);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_lcd_touch_gt911_enter_sleep(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
esp_err_t err = touch_gt911_i2c_write(tp, ESP_LCD_TOUCH_GT911_ENTER_SLEEP, 0x05);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "Enter Sleep failed!");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_lcd_touch_gt911_exit_sleep(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
esp_err_t ret;
|
||||
esp_lcd_touch_handle_t esp_lcd_touch_gt911 = tp;
|
||||
|
||||
if (esp_lcd_touch_gt911->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t int_gpio_config_high = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(esp_lcd_touch_gt911->config.int_gpio_num)
|
||||
};
|
||||
ret = gpio_config(&int_gpio_config_high);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "High GPIO config failed");
|
||||
gpio_set_level(esp_lcd_touch_gt911->config.int_gpio_num, 1);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(5));
|
||||
|
||||
const gpio_config_t int_gpio_config_float = {
|
||||
.mode = GPIO_MODE_OUTPUT_OD,
|
||||
.pin_bit_mask = BIT64(esp_lcd_touch_gt911->config.int_gpio_num)
|
||||
};
|
||||
ret = gpio_config(&int_gpio_config_float);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Float GPIO config failed");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_lcd_touch_gt911_read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint8_t buf[41];
|
||||
uint8_t touch_cnt = 0;
|
||||
uint8_t clear = 0;
|
||||
size_t i = 0;
|
||||
|
||||
assert(tp != NULL);
|
||||
|
||||
err = touch_gt911_i2c_read(tp, ESP_LCD_TOUCH_GT911_READ_XY_REG, buf, 1);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C read error!");
|
||||
|
||||
/* Any touch data? */
|
||||
if ((buf[0] & 0x80) == 0x00) {
|
||||
touch_gt911_i2c_write(tp, ESP_LCD_TOUCH_GT911_READ_XY_REG, clear);
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
} else if ((buf[0] & 0x10) == 0x10) {
|
||||
/* Read all keys */
|
||||
uint8_t key_max = ((ESP_GT911_TOUCH_MAX_BUTTONS < CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS) ? \
|
||||
(ESP_GT911_TOUCH_MAX_BUTTONS) : (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS));
|
||||
err = touch_gt911_i2c_read(tp, ESP_LCD_TOUCH_GT911_READ_KEY_REG, &buf[0], key_max);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C read error!");
|
||||
|
||||
/* Clear all */
|
||||
touch_gt911_i2c_write(tp, ESP_LCD_TOUCH_GT911_READ_XY_REG, clear);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C write error!");
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
|
||||
/* Buttons count */
|
||||
tp->data.buttons = key_max;
|
||||
for (i = 0; i < key_max; i++) {
|
||||
tp->data.button[i].status = buf[0] ? 1 : 0;
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
#endif
|
||||
} else if ((buf[0] & 0x80) == 0x80) {
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
for (i = 0; i < CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS; i++) {
|
||||
tp->data.button[i].status = 0;
|
||||
}
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
#endif
|
||||
/* Count of touched points */
|
||||
touch_cnt = buf[0] & 0x0f;
|
||||
if (touch_cnt > 5 || touch_cnt == 0) {
|
||||
touch_gt911_i2c_write(tp, ESP_LCD_TOUCH_GT911_READ_XY_REG, clear);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Read all points */
|
||||
err = touch_gt911_i2c_read(tp, ESP_LCD_TOUCH_GT911_READ_XY_REG + 1, &buf[1], touch_cnt * 8);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C read error!");
|
||||
|
||||
/* Clear all */
|
||||
err = touch_gt911_i2c_write(tp, ESP_LCD_TOUCH_GT911_READ_XY_REG, clear);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C read error!");
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
|
||||
/* Number of touched points */
|
||||
touch_cnt = (touch_cnt > CONFIG_ESP_LCD_TOUCH_MAX_POINTS ? CONFIG_ESP_LCD_TOUCH_MAX_POINTS : touch_cnt);
|
||||
tp->data.points = touch_cnt;
|
||||
|
||||
/* Fill all coordinates */
|
||||
for (i = 0; i < touch_cnt; i++) {
|
||||
tp->data.coords[i].x = ((uint16_t)buf[(i * 8) + 3] << 8) + buf[(i * 8) + 2];
|
||||
tp->data.coords[i].y = (((uint16_t)buf[(i * 8) + 5] << 8) + buf[(i * 8) + 4]);
|
||||
tp->data.coords[i].strength = (((uint16_t)buf[(i * 8) + 7] << 8) + buf[(i * 8) + 6]);
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool esp_lcd_touch_gt911_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(x != NULL);
|
||||
assert(y != NULL);
|
||||
assert(point_num != NULL);
|
||||
assert(max_point_num > 0);
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
|
||||
/* Count of points */
|
||||
*point_num = (tp->data.points > max_point_num ? max_point_num : tp->data.points);
|
||||
|
||||
for (size_t i = 0; i < *point_num; i++) {
|
||||
x[i] = tp->data.coords[i].x;
|
||||
y[i] = tp->data.coords[i].y;
|
||||
|
||||
if (strength) {
|
||||
strength[i] = tp->data.coords[i].strength;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalidate */
|
||||
tp->data.points = 0;
|
||||
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return (*point_num > 0);
|
||||
}
|
||||
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
static esp_err_t esp_lcd_touch_gt911_get_button_state(esp_lcd_touch_handle_t tp, uint8_t n, uint8_t *state)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
assert(tp != NULL);
|
||||
assert(state != NULL);
|
||||
|
||||
*state = 0;
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
|
||||
if (n > tp->data.buttons) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
*state = tp->data.button[n].status;
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_err_t esp_lcd_touch_gt911_del(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.int_gpio_num);
|
||||
if (tp->config.interrupt_callback) {
|
||||
gpio_isr_handler_remove(tp->config.int_gpio_num);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.rst_gpio_num);
|
||||
}
|
||||
|
||||
free(tp);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Private API function
|
||||
*******************************************************************************/
|
||||
|
||||
/* Reset controller */
|
||||
static esp_err_t touch_gt911_reset(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level error!");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level error!");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t touch_gt911_read_cfg(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
|
||||
assert(tp != NULL);
|
||||
|
||||
ESP_RETURN_ON_ERROR(touch_gt911_i2c_read(tp, ESP_LCD_TOUCH_GT911_PRODUCT_ID_REG, (uint8_t *)&buf[0], 3), TAG, "GT911 read error!");
|
||||
ESP_RETURN_ON_ERROR(touch_gt911_i2c_read(tp, ESP_LCD_TOUCH_GT911_CONFIG_REG, (uint8_t *)&buf[3], 1), TAG, "GT911 read error!");
|
||||
|
||||
ESP_LOGI(TAG, "TouchPad_ID:0x%02x,0x%02x,0x%02x", buf[0], buf[1], buf[2]);
|
||||
ESP_LOGI(TAG, "TouchPad_Config_Version:%d", buf[3]);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t touch_gt911_i2c_read(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(data != NULL);
|
||||
|
||||
/* Read data */
|
||||
return esp_lcd_panel_io_rx_param(tp->io, reg, data, len);
|
||||
}
|
||||
|
||||
static esp_err_t touch_gt911_i2c_write(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t data)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
// *INDENT-OFF*
|
||||
/* Write data */
|
||||
return esp_lcd_panel_io_tx_param(tp->io, reg, (uint8_t[]){data}, 1);
|
||||
// *INDENT-ON*
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD touch: GT911
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_TOUCH_GT911_VER_MAJOR (1)
|
||||
#define ESP_LCD_TOUCH_GT911_VER_MINOR (1)
|
||||
#define ESP_LCD_TOUCH_GT911_VER_PATCH (0)
|
||||
|
||||
/**
|
||||
* @brief Create a new GT911 touch driver
|
||||
*
|
||||
* @note The I2C communication should be initialized before use this function.
|
||||
*
|
||||
* @param io LCD/Touch panel IO handle
|
||||
* @param config: Touch configuration
|
||||
* @param out_touch: Touch instance handle
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM if there is no memory for allocating main structure
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_new_i2c_gt911(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *out_touch);
|
||||
|
||||
/**
|
||||
* @brief I2C address of the GT911 controller
|
||||
*
|
||||
* @note When power-on detects low level of the interrupt gpio, address is 0x5D.
|
||||
* @note Interrupt gpio is high level, address is 0x14.
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS (0x5D)
|
||||
#define ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP (0x14)
|
||||
|
||||
/**
|
||||
* @brief Touch IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG() \
|
||||
{ \
|
||||
.dev_addr = ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS, \
|
||||
.control_phase_bytes = 1, \
|
||||
.dc_bit_offset = 0, \
|
||||
.lcd_cmd_bits = 16, \
|
||||
.flags = \
|
||||
{ \
|
||||
.disable_control_phase = 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#include "esp_lcd_touch_st1633.h"
|
||||
|
||||
#define FW_VERSION_REG (0x00)
|
||||
#define XY_RES_H_REG (0x04)
|
||||
#define FW_REVISION_REG (0x0C)
|
||||
#define ADVANCED_INFO_REG (0x10)
|
||||
|
||||
#define MAX_TOUCH_NUM (10)
|
||||
#define MAX_READ_TOUCH_NUM (MAX(MAX_TOUCH_NUM, CONFIG_ESP_LCD_TOUCH_MAX_POINTS))
|
||||
|
||||
static const char *TAG = "ST1633";
|
||||
|
||||
static esp_err_t read_data(esp_lcd_touch_handle_t tp);
|
||||
static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
static esp_err_t del(esp_lcd_touch_handle_t tp);
|
||||
static esp_err_t reset(esp_lcd_touch_handle_t tp);
|
||||
|
||||
static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len);
|
||||
static esp_err_t read_fw_info(esp_lcd_touch_handle_t tp);
|
||||
|
||||
esp_err_t esp_lcd_touch_new_i2c_st1633(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_ARG, TAG, "Invalid io");
|
||||
ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "Invalid config");
|
||||
ESP_RETURN_ON_FALSE(tp, ESP_ERR_INVALID_ARG, TAG, "Invalid touch handle");
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
/* Prepare main structure */
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_lcd_touch_handle_t st1633 = (esp_lcd_touch_handle_t)calloc(1, sizeof(esp_lcd_touch_t));
|
||||
ESP_GOTO_ON_FALSE(st1633, ESP_ERR_NO_MEM, err, TAG, "Touch handle malloc failed");
|
||||
|
||||
/* Communication interface */
|
||||
st1633->io = io;
|
||||
/* Only supported callbacks are set */
|
||||
st1633->read_data = read_data;
|
||||
st1633->get_xy = get_xy;
|
||||
st1633->del = del;
|
||||
/* Mutex */
|
||||
st1633->data.lock.owner = portMUX_FREE_VAL;
|
||||
/* Save config */
|
||||
memcpy(&st1633->config, config, sizeof(esp_lcd_touch_config_t));
|
||||
|
||||
/* Prepare pin for touch interrupt */
|
||||
if (config->int_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t int_gpio_config = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.intr_type = (config->levels.interrupt) ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE,
|
||||
.pin_bit_mask = BIT64(config->int_gpio_num)
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&int_gpio_config), err, TAG, "GPIO intr config failed");
|
||||
|
||||
/* Register interrupt callback */
|
||||
if (config->interrupt_callback) {
|
||||
esp_lcd_touch_register_interrupt_callback(st1633, config->interrupt_callback);
|
||||
}
|
||||
}
|
||||
/* Prepare pin for touch controller reset */
|
||||
if (config->rst_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t rst_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(config->rst_gpio_num)
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&rst_gpio_config), err, TAG, "GPIO reset config failed");
|
||||
}
|
||||
/* Reset controller */
|
||||
ESP_GOTO_ON_ERROR(reset(st1633), err, TAG, "Reset failed");
|
||||
ESP_GOTO_ON_ERROR(read_fw_info(st1633), err, TAG, "Read version failed");
|
||||
|
||||
ESP_LOGI(TAG, "Touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_ST1633_VER_MAJOR,
|
||||
ESP_LCD_TOUCH_ST1633_VER_MINOR, ESP_LCD_TOUCH_ST1633_VER_PATCH);
|
||||
|
||||
*tp = st1633;
|
||||
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (st1633) {
|
||||
del(st1633);
|
||||
}
|
||||
ESP_LOGE(TAG, "Initialization failed!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t y_h: 3;
|
||||
uint8_t reserved_3: 1;
|
||||
uint8_t x_h: 3;
|
||||
uint8_t valid: 1;
|
||||
uint8_t x_l;
|
||||
uint8_t y_l;
|
||||
uint8_t reserved_24_31;
|
||||
} xy_coord_t;
|
||||
typedef struct {
|
||||
uint8_t gesture_type: 4;
|
||||
uint8_t reserved_4: 1;
|
||||
uint8_t water_flag: 1;
|
||||
uint8_t prox_flag: 1;
|
||||
uint8_t reserved_7: 1;
|
||||
uint8_t keys;
|
||||
xy_coord_t xy_coord[MAX_READ_TOUCH_NUM];
|
||||
} tp_report_t;
|
||||
static_assert((sizeof(xy_coord_t) == 4) && (sizeof(tp_report_t) == 42), "Invalid size of tp xy_coord_t or_report_t");
|
||||
|
||||
tp_report_t tp_report = { 0 };
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, ADVANCED_INFO_REG, (uint8_t *)&tp_report, sizeof(tp_report)), TAG, "Read advanced info failed");
|
||||
|
||||
uint16_t x = 0;
|
||||
uint16_t y = 0;
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
int j = 0;
|
||||
/* Fill all coordinates */
|
||||
for (int i = 0; i < MAX_READ_TOUCH_NUM; i++) {
|
||||
x = (((uint16_t)tp_report.xy_coord[i].x_h) << 8) | tp_report.xy_coord[i].x_l;
|
||||
y = (((uint16_t)tp_report.xy_coord[i].y_h) << 8) | tp_report.xy_coord[i].y_l;
|
||||
if (((x == 0) && (y == 0)) || (x > tp->config.x_max) || (y > tp->config.y_max)) {
|
||||
continue;
|
||||
}
|
||||
tp->data.coords[j].x = x;
|
||||
tp->data.coords[j].y = y;
|
||||
j++;
|
||||
}
|
||||
/* Expect Number of touched points */
|
||||
tp->data.points = j;
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
|
||||
{
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
/* Count of points */
|
||||
*point_num = (tp->data.points > max_point_num ? max_point_num : tp->data.points);
|
||||
for (size_t i = 0; i < *point_num; i++) {
|
||||
x[i] = tp->data.coords[i].x;
|
||||
y[i] = tp->data.coords[i].y;
|
||||
|
||||
if (strength) {
|
||||
strength[i] = tp->data.coords[i].strength;
|
||||
}
|
||||
}
|
||||
/* Clear available touch points count */
|
||||
tp->data.points = 0;
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return (*point_num > 0);
|
||||
}
|
||||
|
||||
static esp_err_t del(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.int_gpio_num);
|
||||
}
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.rst_gpio_num);
|
||||
if (tp->config.interrupt_callback) {
|
||||
gpio_isr_handler_remove(tp->config.int_gpio_num);
|
||||
}
|
||||
}
|
||||
/* Release memory */
|
||||
free(tp);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t reset(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((len == 0) || (data != NULL), ESP_ERR_INVALID_ARG, TAG, "Invalid data");
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_rx_param(tp->io, reg, data, len), TAG, "Read param failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_fw_info(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
uint8_t version = 0;
|
||||
uint8_t revision[4] = { 0 };
|
||||
struct {
|
||||
uint8_t y_res_h: 3;
|
||||
uint8_t reserved_3: 1;
|
||||
uint8_t x_res_h: 3;
|
||||
uint8_t reserved_7: 1;
|
||||
uint8_t x_res_l;
|
||||
uint8_t y_res_l;
|
||||
} xy_res;
|
||||
static_assert(sizeof(xy_res) == 3, "Invalid size of info");
|
||||
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, FW_VERSION_REG, &version, 1), TAG, "Read version failed");
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, FW_REVISION_REG, (uint8_t *)&revision[0], sizeof(revision)), TAG, "Read revision failed");
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, XY_RES_H_REG, (uint8_t *)&xy_res, sizeof(xy_res)), TAG, "Read XY Resolution failed");
|
||||
|
||||
ESP_LOGI(TAG, "Firmware version: %d(%d.%d.%d.%d), Max.X: %d, Max.Y: %d", version, revision[3], revision[2],
|
||||
revision[1], revision[0], (((uint16_t)xy_res.x_res_h) << 8) | xy_res.x_res_l,
|
||||
(((uint16_t)xy_res.y_res_h) << 8) | xy_res.y_res_l);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_TOUCH_ST1633_VER_MAJOR (0)
|
||||
#define ESP_LCD_TOUCH_ST1633_VER_MINOR (1)
|
||||
#define ESP_LCD_TOUCH_ST1633_VER_PATCH (0)
|
||||
|
||||
/**
|
||||
* @brief Create a new ST1633 touch driver
|
||||
*
|
||||
* @note The I2C communication should be initialized before use this function.
|
||||
*
|
||||
* @param io LCD panel IO handle, it should be created by `esp_lcd_new_panel_io_i2c()`
|
||||
* @param config Touch panel configuration
|
||||
* @param tp Touch panel handle
|
||||
* @return
|
||||
* - ESP_OK: on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_new_i2c_st1633(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp);
|
||||
|
||||
/**
|
||||
* @brief I2C address of the ST1633 controller
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_ST1633_ADDRESS (0x55)
|
||||
|
||||
/**
|
||||
* @brief Touch IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_ST1633_CONFIG() \
|
||||
{ \
|
||||
.dev_addr = ESP_LCD_TOUCH_IO_I2C_ST1633_ADDRESS, \
|
||||
.control_phase_bytes = 1, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.flags = \
|
||||
{ \
|
||||
.disable_control_phase = 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#include "esp_lcd_touch_st7123.h"
|
||||
|
||||
#define FW_VERSION_REG (0x0000)
|
||||
#define FW_REVISION_REG (0x000C)
|
||||
#define MAX_X_COORD_H_REG (0x0005)
|
||||
#define MAX_X_COORD_L_REG (0x0006)
|
||||
#define MAX_Y_COORD_H_REG (0x0007)
|
||||
#define MAX_Y_COORD_L_REG (0x0008)
|
||||
#define MAX_TOUCHES_REG (0x0009)
|
||||
#define REPORT_COORD_0_REG (0x0014)
|
||||
|
||||
static const char *TAG = "ST7123";
|
||||
|
||||
static esp_err_t read_data(esp_lcd_touch_handle_t tp);
|
||||
static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
static esp_err_t del(esp_lcd_touch_handle_t tp);
|
||||
static esp_err_t reset(esp_lcd_touch_handle_t tp);
|
||||
|
||||
static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len);
|
||||
static esp_err_t read_fw_info(esp_lcd_touch_handle_t tp);
|
||||
|
||||
esp_err_t esp_lcd_touch_new_i2c_st7123(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_ARG, TAG, "Invalid io");
|
||||
ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "Invalid config");
|
||||
ESP_RETURN_ON_FALSE(tp, ESP_ERR_INVALID_ARG, TAG, "Invalid touch handle");
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
/* Prepare main structure */
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_lcd_touch_handle_t st7123 = (esp_lcd_touch_handle_t)calloc(1, sizeof(esp_lcd_touch_t));
|
||||
ESP_GOTO_ON_FALSE(st7123, ESP_ERR_NO_MEM, err, TAG, "Touch handle malloc failed");
|
||||
|
||||
/* Communication interface */
|
||||
st7123->io = io;
|
||||
/* Only supported callbacks are set */
|
||||
st7123->read_data = read_data;
|
||||
st7123->get_xy = get_xy;
|
||||
st7123->del = del;
|
||||
/* Mutex */
|
||||
st7123->data.lock.owner = portMUX_FREE_VAL;
|
||||
/* Save config */
|
||||
memcpy(&st7123->config, config, sizeof(esp_lcd_touch_config_t));
|
||||
|
||||
/* Prepare pin for touch interrupt */
|
||||
if (config->int_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t int_gpio_config = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.intr_type = (config->levels.interrupt) ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE,
|
||||
.pin_bit_mask = BIT64(config->int_gpio_num)
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&int_gpio_config), err, TAG, "GPIO intr config failed");
|
||||
|
||||
/* Register interrupt callback */
|
||||
if (config->interrupt_callback) {
|
||||
esp_lcd_touch_register_interrupt_callback(st7123, config->interrupt_callback);
|
||||
}
|
||||
}
|
||||
/* Prepare pin for touch controller reset */
|
||||
if (config->rst_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t rst_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(config->rst_gpio_num)
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&rst_gpio_config), err, TAG, "GPIO reset config failed");
|
||||
}
|
||||
/* Reset controller */
|
||||
ESP_GOTO_ON_ERROR(reset(st7123), err, TAG, "Reset failed");
|
||||
ESP_GOTO_ON_ERROR(read_fw_info(st7123), err, TAG, "Read version failed");
|
||||
|
||||
ESP_LOGI(TAG, "Touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_ST7123_VER_MAJOR,
|
||||
ESP_LCD_TOUCH_ST7123_VER_MINOR, ESP_LCD_TOUCH_ST7123_VER_PATCH);
|
||||
|
||||
*tp = st7123;
|
||||
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (st7123) {
|
||||
del(st7123);
|
||||
}
|
||||
ESP_LOGE(TAG, "Initialization failed!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t x_h: 6;
|
||||
uint8_t reserved_6: 1;
|
||||
uint8_t valid: 1;
|
||||
uint8_t x_l;
|
||||
uint8_t y_h;
|
||||
uint8_t y_l;
|
||||
uint8_t area;
|
||||
uint8_t intensity;
|
||||
uint8_t reserved_49_55;
|
||||
} touch_report_t;
|
||||
typedef struct {
|
||||
uint8_t reserved_0_1: 2;
|
||||
uint8_t with_prox: 1;
|
||||
uint8_t with_coord: 1;
|
||||
uint8_t prox_status: 3;
|
||||
uint8_t rst_chip: 1;
|
||||
} adv_info_t;
|
||||
|
||||
touch_report_t touch_report[10];
|
||||
adv_info_t adv_info = { 0 };
|
||||
uint8_t max_touches = 0;
|
||||
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, 0x0010, (uint8_t *)&adv_info, 1), TAG, "Read advanced info failed");
|
||||
if (adv_info.with_coord) {
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, MAX_TOUCHES_REG, &max_touches, 1), TAG, "Read max touches failed");
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, REPORT_COORD_0_REG, (uint8_t *)&touch_report[0],
|
||||
sizeof(touch_report_t) * max_touches), TAG, "Read report failed");
|
||||
}
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
/* Fill all coordinates */
|
||||
int j = 0;
|
||||
for (int i = 0; (i < max_touches) && (j < CONFIG_ESP_LCD_TOUCH_MAX_POINTS); i++) {
|
||||
if (!touch_report[i].valid) {
|
||||
continue;
|
||||
}
|
||||
tp->data.coords[j].x = touch_report[i].x_h << 8 | touch_report[i].x_l;
|
||||
tp->data.coords[j].y = touch_report[i].y_h << 8 | touch_report[i].y_l;
|
||||
tp->data.coords[j++].strength = touch_report[i].area;
|
||||
}
|
||||
/* Expect Number of touched points */
|
||||
tp->data.points = j;
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
|
||||
{
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
/* Count of points */
|
||||
*point_num = (tp->data.points > max_point_num ? max_point_num : tp->data.points);
|
||||
for (size_t i = 0; i < *point_num; i++) {
|
||||
x[i] = tp->data.coords[i].x;
|
||||
y[i] = tp->data.coords[i].y;
|
||||
|
||||
if (strength) {
|
||||
strength[i] = tp->data.coords[i].strength;
|
||||
}
|
||||
}
|
||||
/* Clear available touch points count */
|
||||
tp->data.points = 0;
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return (*point_num > 0);
|
||||
}
|
||||
|
||||
static esp_err_t del(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.int_gpio_num);
|
||||
}
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.rst_gpio_num);
|
||||
if (tp->config.interrupt_callback) {
|
||||
gpio_isr_handler_remove(tp->config.int_gpio_num);
|
||||
}
|
||||
}
|
||||
/* Release memory */
|
||||
free(tp);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t reset(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((len == 0) || (data != NULL), ESP_ERR_INVALID_ARG, TAG, "Invalid data");
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_rx_param(tp->io, reg, data, len), TAG, "Read param failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_fw_info(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
uint8_t version = 0;
|
||||
uint8_t revision[4] = { 0 };
|
||||
struct {
|
||||
uint8_t max_x_h;
|
||||
uint8_t max_x_l;
|
||||
uint8_t max_y_h;
|
||||
uint8_t max_y_l;
|
||||
uint8_t max_touches;
|
||||
} info;
|
||||
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, FW_VERSION_REG, &version, 1), TAG, "Read version failed");
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, FW_REVISION_REG, (uint8_t *)&revision[0], 4), TAG, "Read revision failed");
|
||||
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, MAX_X_COORD_H_REG, (uint8_t *)&info, sizeof(info)), TAG, "Read info failed");
|
||||
|
||||
ESP_LOGI(TAG, "Firmware version: %d(%d.%d.%d.%d), Max.X: %d, Max.Y: %d, Max.Touchs: %d",
|
||||
version, revision[0], revision[1], revision[2], revision[3], ((uint16_t)info.max_x_h << 8) | info.max_x_l,
|
||||
((uint16_t)info.max_y_h << 8) | info.max_y_l, info.max_touches);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_TOUCH_ST7123_VER_MAJOR (0)
|
||||
#define ESP_LCD_TOUCH_ST7123_VER_MINOR (0)
|
||||
#define ESP_LCD_TOUCH_ST7123_VER_PATCH (1)
|
||||
|
||||
/**
|
||||
* @brief Create a new ST7123 touch driver
|
||||
*
|
||||
* @note The I2C communication should be initialized before use this function.
|
||||
*
|
||||
* @param io LCD panel IO handle, it should be created by `esp_lcd_new_panel_io_i2c()`
|
||||
* @param config Touch panel configuration
|
||||
* @param tp Touch panel handle
|
||||
* @return
|
||||
* - ESP_OK: on success
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_new_i2c_st7123(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp);
|
||||
|
||||
/**
|
||||
* @brief I2C address of the ST7123 controller
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_ST7123_ADDRESS (0x55)
|
||||
|
||||
/**
|
||||
* @brief Touch IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_ST7123_CONFIG() \
|
||||
{ \
|
||||
.dev_addr = ESP_LCD_TOUCH_IO_I2C_ST7123_ADDRESS, \
|
||||
.control_phase_bytes = 1, \
|
||||
.lcd_cmd_bits = 16, \
|
||||
.flags = \
|
||||
{ \
|
||||
.disable_control_phase = 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+369
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#include "esp_lcd_touch_tt21100.h"
|
||||
|
||||
static const char *TAG = "TT21100";
|
||||
|
||||
#define ESP_LCD_TOUCH_TT21100_MAX_DATA_LEN (7+CONFIG_ESP_LCD_TOUCH_MAX_POINTS*10) /* 7 Header + (Points * 10 data bytes) */
|
||||
|
||||
/*******************************************************************************
|
||||
* Function definitions
|
||||
*******************************************************************************/
|
||||
static esp_err_t esp_lcd_touch_tt21100_read_data(esp_lcd_touch_handle_t tp);
|
||||
static bool esp_lcd_touch_tt21100_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num);
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
static esp_err_t esp_lcd_touch_tt21100_get_button_state(esp_lcd_touch_handle_t tp, uint8_t n, uint8_t *state);
|
||||
#endif
|
||||
static esp_err_t esp_lcd_touch_tt21100_del(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/* I2C read */
|
||||
static esp_err_t touch_tt21100_i2c_read(esp_lcd_touch_handle_t tp, uint8_t *data, uint8_t len);
|
||||
|
||||
/* TT21100 reset */
|
||||
static esp_err_t touch_tt21100_reset(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/* TT21100 write */
|
||||
static esp_err_t touch_tt21100_i2c_write(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint16_t len);
|
||||
|
||||
static esp_err_t esp_lcd_touch_tt21100_enter_sleep(esp_lcd_touch_handle_t tp);
|
||||
|
||||
static esp_err_t esp_lcd_touch_tt21100_exit_sleep(esp_lcd_touch_handle_t tp);
|
||||
/*******************************************************************************
|
||||
* Public API functions
|
||||
*******************************************************************************/
|
||||
|
||||
esp_err_t esp_lcd_touch_new_i2c_tt21100(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *out_touch)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
assert(config != NULL);
|
||||
assert(out_touch != NULL);
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
/* Prepare main structure */
|
||||
esp_lcd_touch_handle_t esp_lcd_touch_tt21100 = heap_caps_calloc(1, sizeof(esp_lcd_touch_t), MALLOC_CAP_DEFAULT);
|
||||
ESP_GOTO_ON_FALSE(esp_lcd_touch_tt21100, ESP_ERR_NO_MEM, err, TAG, "no mem for TT21100 controller");
|
||||
|
||||
/* Communication interface */
|
||||
esp_lcd_touch_tt21100->io = io;
|
||||
|
||||
/* Only supported callbacks are set */
|
||||
esp_lcd_touch_tt21100->read_data = esp_lcd_touch_tt21100_read_data;
|
||||
esp_lcd_touch_tt21100->get_xy = esp_lcd_touch_tt21100_get_xy;
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
esp_lcd_touch_tt21100->get_button_state = esp_lcd_touch_tt21100_get_button_state;
|
||||
#endif
|
||||
esp_lcd_touch_tt21100->del = esp_lcd_touch_tt21100_del;
|
||||
esp_lcd_touch_tt21100->enter_sleep = esp_lcd_touch_tt21100_enter_sleep;
|
||||
esp_lcd_touch_tt21100->exit_sleep = esp_lcd_touch_tt21100_exit_sleep;
|
||||
/* Mutex */
|
||||
esp_lcd_touch_tt21100->data.lock.owner = portMUX_FREE_VAL;
|
||||
|
||||
/* Save config */
|
||||
memcpy(&esp_lcd_touch_tt21100->config, config, sizeof(esp_lcd_touch_config_t));
|
||||
|
||||
/* Prepare pin for touch interrupt */
|
||||
if (esp_lcd_touch_tt21100->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t int_gpio_config = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.intr_type = (esp_lcd_touch_tt21100->config.levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE),
|
||||
.pin_bit_mask = BIT64(esp_lcd_touch_tt21100->config.int_gpio_num)
|
||||
};
|
||||
ret = gpio_config(&int_gpio_config);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "GPIO config failed");
|
||||
|
||||
/* Register interrupt callback */
|
||||
if (esp_lcd_touch_tt21100->config.interrupt_callback) {
|
||||
esp_lcd_touch_register_interrupt_callback(esp_lcd_touch_tt21100, esp_lcd_touch_tt21100->config.interrupt_callback);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare pin for touch controller reset */
|
||||
if (esp_lcd_touch_tt21100->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
const gpio_config_t rst_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(esp_lcd_touch_tt21100->config.rst_gpio_num)
|
||||
};
|
||||
ret = gpio_config(&rst_gpio_config);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "GPIO config failed");
|
||||
}
|
||||
|
||||
/* Reset controller */
|
||||
ret = touch_tt21100_reset(esp_lcd_touch_tt21100);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "TT21100 reset failed");
|
||||
|
||||
/* Initial read */
|
||||
ret = esp_lcd_touch_tt21100_read_data(esp_lcd_touch_tt21100);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "TT21100 init failed");
|
||||
|
||||
err:
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (0x%x)! Touch controller TT21100 initialization failed!", ret);
|
||||
if (esp_lcd_touch_tt21100) {
|
||||
esp_lcd_touch_tt21100_del(esp_lcd_touch_tt21100);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
*out_touch = esp_lcd_touch_tt21100;
|
||||
|
||||
ESP_LOGI(TAG, "LCD touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_TT21100_VER_MAJOR, ESP_LCD_TOUCH_TT21100_VER_MINOR,
|
||||
ESP_LCD_TOUCH_TT21100_VER_PATCH);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_lcd_touch_tt21100_enter_sleep(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
uint8_t power_save_cmd[2] = {0x01, 0x08};
|
||||
esp_err_t err = touch_tt21100_i2c_write(tp, 0x0500, power_save_cmd, sizeof(power_save_cmd));
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "Enter Sleep failed!");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_lcd_touch_tt21100_exit_sleep(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
uint8_t power_save_cmd[2] = {0x00, 0x08};
|
||||
esp_err_t err = touch_tt21100_i2c_write(tp, 0x0500, power_save_cmd, sizeof(power_save_cmd));
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "Exit Sleep failed!");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_lcd_touch_tt21100_read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t : 5;
|
||||
uint8_t touch_type: 3;
|
||||
uint8_t tip: 1;
|
||||
uint8_t event_id: 2;
|
||||
uint8_t touch_id: 5;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint8_t pressure;
|
||||
uint16_t major_axis_length;
|
||||
uint8_t orientation;
|
||||
} __attribute__((packed)) touch_record_struct_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t data_len;
|
||||
uint8_t report_id;
|
||||
uint16_t time_stamp;
|
||||
uint8_t : 2;
|
||||
uint8_t large_object : 1;
|
||||
uint8_t record_num : 5;
|
||||
uint8_t report_counter: 2;
|
||||
uint8_t : 3;
|
||||
uint8_t noise_efect: 3;
|
||||
touch_record_struct_t touch_record[0];
|
||||
} __attribute__((packed)) touch_report_struct_t;
|
||||
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
typedef struct {
|
||||
uint16_t length; /*!< Always 14(0x000E) */
|
||||
uint8_t report_id; /*!< Always 03h */
|
||||
uint16_t time_stamp; /*!< Number in units of 100 us */
|
||||
uint8_t btn_val; /*!< Only use bit[0..3] */
|
||||
uint16_t btn_signal[4];
|
||||
} __attribute__((packed)) button_record_struct_t;
|
||||
#endif
|
||||
|
||||
touch_report_struct_t *p_report_data = NULL;
|
||||
touch_record_struct_t *p_touch_data = NULL;
|
||||
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
button_record_struct_t *p_btn_data = NULL;
|
||||
#endif
|
||||
|
||||
esp_err_t err;
|
||||
static uint16_t data_len;
|
||||
static uint8_t data[ESP_LCD_TOUCH_TT21100_MAX_DATA_LEN];
|
||||
uint8_t tp_num = 0;
|
||||
size_t i = 0;
|
||||
|
||||
assert(tp != NULL);
|
||||
|
||||
/* Get report data length */
|
||||
err = touch_tt21100_i2c_read(tp, (uint8_t *)&data_len, sizeof(data_len));
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C read error!");
|
||||
|
||||
/* Read report data if length */
|
||||
if (data_len > 0 && data_len < sizeof(data)) {
|
||||
touch_tt21100_i2c_read(tp, data, data_len);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C read error!");
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
|
||||
if (data_len == 14) {
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
/* Button event */
|
||||
p_btn_data = (button_record_struct_t *) data;
|
||||
|
||||
/* Buttons count */
|
||||
tp->data.buttons = (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS < 4 ? CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS : 4);
|
||||
|
||||
for (i = 0; i < tp->data.buttons; i++) {
|
||||
tp->data.button[i].status = p_btn_data->btn_signal[i];
|
||||
}
|
||||
|
||||
// ESP_LOGD(TAG, "Len : %04Xh. ID : %02Xh. Time : %5u. Val : [%u] - [%04X][%04X][%04X][%04X]",
|
||||
// p_btn_data->length, p_btn_data->report_id, p_btn_data->time_stamp, p_btn_data->btn_val,
|
||||
// p_btn_data->btn_signal[0], p_btn_data->btn_signal[1], p_btn_data->btn_signal[2], p_btn_data->btn_signal[3]);
|
||||
#endif
|
||||
} else if (data_len >= 7) {
|
||||
/* Touch point event */
|
||||
p_report_data = (touch_report_struct_t *) data;
|
||||
tp_num = (data_len - sizeof(touch_report_struct_t)) / sizeof(touch_record_struct_t);
|
||||
|
||||
/* Number of touched points */
|
||||
tp_num = (tp_num > CONFIG_ESP_LCD_TOUCH_MAX_POINTS ? CONFIG_ESP_LCD_TOUCH_MAX_POINTS : tp_num);
|
||||
tp->data.points = tp_num;
|
||||
|
||||
/* Fill all coordinates */
|
||||
for (i = 0; i < tp_num; i++) {
|
||||
p_touch_data = &p_report_data->touch_record[i];
|
||||
|
||||
tp->data.coords[i].x = p_touch_data->x;
|
||||
tp->data.coords[i].y = p_touch_data->y;
|
||||
tp->data.coords[i].strength = p_touch_data->pressure;
|
||||
|
||||
// ESP_LOGD(TAG, "(%zu) [%3u][%3u]", i, p_touch_data->x, p_touch_data->y);
|
||||
}
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool esp_lcd_touch_tt21100_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(x != NULL);
|
||||
assert(y != NULL);
|
||||
assert(point_num != NULL);
|
||||
assert(max_point_num > 0);
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
|
||||
/* Count of points */
|
||||
*point_num = (tp->data.points > max_point_num ? max_point_num : tp->data.points);
|
||||
|
||||
for (size_t i = 0; i < *point_num; i++) {
|
||||
x[i] = tp->data.coords[i].x;
|
||||
y[i] = tp->data.coords[i].y;
|
||||
|
||||
if (strength) {
|
||||
strength[i] = tp->data.coords[i].strength;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalidate */
|
||||
tp->data.points = 0;
|
||||
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return (*point_num > 0);
|
||||
}
|
||||
|
||||
#if (CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS > 0)
|
||||
static esp_err_t esp_lcd_touch_tt21100_get_button_state(esp_lcd_touch_handle_t tp, uint8_t n, uint8_t *state)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
assert(tp != NULL);
|
||||
assert(state != NULL);
|
||||
|
||||
*state = 0;
|
||||
|
||||
portENTER_CRITICAL(&tp->data.lock);
|
||||
|
||||
if (n > tp->data.buttons) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
*state = tp->data.button[n].status;
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_err_t esp_lcd_touch_tt21100_del(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.int_gpio_num);
|
||||
if (tp->config.interrupt_callback) {
|
||||
gpio_isr_handler_remove(tp->config.int_gpio_num);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset GPIO pin settings */
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.rst_gpio_num);
|
||||
}
|
||||
|
||||
free(tp);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Private API function
|
||||
*******************************************************************************/
|
||||
|
||||
/* Reset controller */
|
||||
static esp_err_t touch_tt21100_reset(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
|
||||
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level error!");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level error!");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t touch_tt21100_i2c_read(esp_lcd_touch_handle_t tp, uint8_t *data, uint8_t len)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(data != NULL);
|
||||
|
||||
/* Read data */
|
||||
return esp_lcd_panel_io_rx_param(tp->io, -1, data, len);
|
||||
}
|
||||
|
||||
static esp_err_t touch_tt21100_i2c_write(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint16_t len)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(data != NULL);
|
||||
|
||||
return esp_lcd_panel_io_tx_param(tp->io, reg, data, len);
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD touch: TT21100
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_TOUCH_TT21100_VER_MAJOR (1)
|
||||
#define ESP_LCD_TOUCH_TT21100_VER_MINOR (1)
|
||||
#define ESP_LCD_TOUCH_TT21100_VER_PATCH (6)
|
||||
|
||||
/**
|
||||
* @brief Create a new TT21100 touch driver
|
||||
*
|
||||
* @note The I2C communication should be initialized before use this function.
|
||||
*
|
||||
* @param io LCD/Touch panel IO handle
|
||||
* @param config: Touch configuration
|
||||
* @param out_touch: Touch instance handle
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM if there is no memory for allocating main structure
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_new_i2c_tt21100(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *out_touch);
|
||||
|
||||
/**
|
||||
* @brief I2C address of the TT21100 controller
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_TT21100_ADDRESS (0x24)
|
||||
|
||||
/**
|
||||
* @brief Touch IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_TT21100_CONFIG() \
|
||||
{ \
|
||||
.dev_addr = ESP_LCD_TOUCH_IO_I2C_TT21100_ADDRESS, \
|
||||
.control_phase_bytes = 1, \
|
||||
.dc_bit_offset = 0, \
|
||||
.lcd_cmd_bits = 16, \
|
||||
.flags = \
|
||||
{ \
|
||||
.disable_control_phase = 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+395
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 atanisoft (github.com/atanisoft)
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include <esp_check.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include <esp_rom_gpio.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
// This must be included after FreeRTOS includes due to missing include
|
||||
// for portMUX_TYPE
|
||||
#include "esp_lcd_touch.h"
|
||||
#include <memory.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_lcd_touch_xpt2046.h"
|
||||
|
||||
static const char *TAG = "xpt2046";
|
||||
|
||||
#ifdef CONFIG_XPT2046_INTERRUPT_MODE
|
||||
#define XPT2046_PD0_BIT (0x00)
|
||||
#else
|
||||
#define XPT2046_PD0_BIT (0x01)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XPT2046_VREF_ON_MODE
|
||||
#define XPT2046_PD1_BIT (0x02)
|
||||
#else
|
||||
#define XPT2046_PD1_BIT (0x00)
|
||||
#endif
|
||||
|
||||
#define XPT2046_PD_BITS (XPT2046_PD1_BIT | XPT2046_PD0_BIT)
|
||||
|
||||
enum xpt2046_registers {
|
||||
// START ADDR MODE SER/ VREF ADC (PENIRQ)
|
||||
// 12/8b DFR INT/EXT ENA
|
||||
Z_VALUE_1 = 0xB0 | XPT2046_PD_BITS, // 1 011 0 0 X X
|
||||
Z_VALUE_2 = 0xC0 | XPT2046_PD_BITS, // 1 100 0 0 X X
|
||||
Y_POSITION = 0x90 | XPT2046_PD_BITS, // 1 001 0 0 X X
|
||||
X_POSITION = 0xD0 | XPT2046_PD_BITS, // 1 101 0 0 X X
|
||||
BATTERY = 0xA6 | XPT2046_PD_BITS, // 1 010 0 1 1 X
|
||||
AUX_IN = 0xE6 | XPT2046_PD_BITS, // 1 110 0 1 1 X
|
||||
TEMP0 = 0x86 | XPT2046_PD_BITS, // 1 000 0 1 1 X
|
||||
TEMP1 = 0xF6 | XPT2046_PD_BITS, // 1 111 0 1 1 X
|
||||
};
|
||||
|
||||
#if CONFIG_XPT2046_ENABLE_LOCKING
|
||||
#define XPT2046_LOCK(lock) portENTER_CRITICAL(lock)
|
||||
#define XPT2046_UNLOCK(lock) portEXIT_CRITICAL(lock)
|
||||
#else
|
||||
#define XPT2046_LOCK(lock)
|
||||
#define XPT2046_UNLOCK(lock)
|
||||
#endif
|
||||
|
||||
static const uint16_t XPT2046_ADC_LIMIT = 4096;
|
||||
// refer the TSC2046 datasheet https://www.ti.com/lit/ds/symlink/tsc2046.pdf rev F 2008
|
||||
// TEMP0 reads approx 599.5 mV at 25C (Refer p8 TEMP0 diode voltage vs Vcc chart)
|
||||
// Vref is approx 2.507V = 2507mV at moderate temperatures (refer p8 Vref vs Temperature chart)
|
||||
// counts@25C = TEMP0_mV / Vref_mv * XPT2046_ADC_LIMIT
|
||||
static const float XPT2046_TEMP0_COUNTS_AT_25C = (599.5 / 2507 * XPT2046_ADC_LIMIT);
|
||||
static esp_err_t xpt2046_read_data(esp_lcd_touch_handle_t tp);
|
||||
static bool xpt2046_get_xy(esp_lcd_touch_handle_t tp,
|
||||
uint16_t *x, uint16_t *y,
|
||||
uint16_t *strength,
|
||||
uint8_t *point_num,
|
||||
uint8_t max_point_num);
|
||||
static esp_err_t xpt2046_del(esp_lcd_touch_handle_t tp);
|
||||
|
||||
esp_err_t esp_lcd_touch_new_spi_xpt2046(const esp_lcd_panel_io_handle_t io,
|
||||
const esp_lcd_touch_config_t *config,
|
||||
esp_lcd_touch_handle_t *out_touch)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_lcd_touch_handle_t handle = NULL;
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_GOTO_ON_FALSE(io, ESP_ERR_INVALID_ARG, err, TAG,
|
||||
"esp_lcd_panel_io_handle_t must not be NULL");
|
||||
ESP_GOTO_ON_FALSE(config, ESP_ERR_INVALID_ARG, err, TAG,
|
||||
"esp_lcd_touch_config_t must not be NULL");
|
||||
|
||||
handle = (esp_lcd_touch_handle_t)calloc(1, sizeof(esp_lcd_touch_t));
|
||||
ESP_GOTO_ON_FALSE(handle, ESP_ERR_NO_MEM, err, TAG,
|
||||
"No memory available for XPT2046 state");
|
||||
handle->io = io;
|
||||
handle->read_data = xpt2046_read_data;
|
||||
handle->get_xy = xpt2046_get_xy;
|
||||
handle->del = xpt2046_del;
|
||||
handle->data.lock.owner = portMUX_FREE_VAL;
|
||||
memcpy(&handle->config, config, sizeof(esp_lcd_touch_config_t));
|
||||
|
||||
// this is not yet supported by esp_lcd_touch.
|
||||
if (config->int_gpio_num != GPIO_NUM_NC) {
|
||||
ESP_GOTO_ON_FALSE(GPIO_IS_VALID_GPIO(config->int_gpio_num),
|
||||
ESP_ERR_INVALID_ARG, err, TAG, "Invalid GPIO Interrupt Pin");
|
||||
gpio_config_t cfg;
|
||||
memset(&cfg, 0, sizeof(gpio_config_t));
|
||||
esp_rom_gpio_pad_select_gpio(config->int_gpio_num);
|
||||
cfg.pin_bit_mask = BIT64(config->int_gpio_num);
|
||||
cfg.mode = GPIO_MODE_INPUT;
|
||||
|
||||
// If the user has provided a callback routine for the interrupt enable
|
||||
// the interrupt mode on the negative edge.
|
||||
if (config->interrupt_callback) {
|
||||
cfg.intr_type = GPIO_INTR_NEGEDGE;
|
||||
}
|
||||
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&cfg), err, TAG,
|
||||
"Configure GPIO for Interrupt failed");
|
||||
|
||||
// Connect the user interrupt callback routine.
|
||||
if (config->interrupt_callback) {
|
||||
esp_lcd_touch_register_interrupt_callback(handle, config->interrupt_callback);
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
if (ret != ESP_OK) {
|
||||
if (handle) {
|
||||
xpt2046_del(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*out_touch = handle;
|
||||
|
||||
ESP_LOGI(TAG, "LCD touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_XPT2046_VER_MAJOR,
|
||||
ESP_LCD_TOUCH_XPT2046_VER_MINOR, ESP_LCD_TOUCH_XPT2046_VER_PATCH);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t xpt2046_del(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
if (tp != NULL) {
|
||||
if (tp->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
gpio_reset_pin(tp->config.int_gpio_num);
|
||||
}
|
||||
}
|
||||
free(tp);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t xpt2046_read_register(esp_lcd_touch_handle_t tp, uint8_t reg, uint16_t *value)
|
||||
{
|
||||
uint8_t buf[2] = {0, 0};
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_rx_param(tp->io, reg, buf, 2), TAG, "XPT2046 read error!");
|
||||
*value = ((buf[0] << 8) | (buf[1]));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t xpt2046_read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
uint16_t z1 = 0, z2 = 0, z = 0;
|
||||
uint32_t x = 0, y = 0;
|
||||
uint8_t point_count = 0;
|
||||
|
||||
#ifdef CONFIG_XPT2046_INTERRUPT_MODE
|
||||
if (tp->config.int_gpio_num != GPIO_NUM_NC) {
|
||||
// Check the PENIRQ pin to see if there is a touch
|
||||
if (gpio_get_level(tp->config.int_gpio_num)) {
|
||||
XPT2046_LOCK(&tp->data.lock);
|
||||
tp->data.coords[0].x = 0;
|
||||
tp->data.coords[0].y = 0;
|
||||
tp->data.coords[0].strength = 0;
|
||||
tp->data.points = 0;
|
||||
XPT2046_UNLOCK(&tp->data.lock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(tp, Z_VALUE_1, &z1), TAG, "XPT2046 read error!");
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(tp, Z_VALUE_2, &z2), TAG, "XPT2046 read error!");
|
||||
|
||||
// Convert the received values into a Z value.
|
||||
z = (z1 >> 3) + (XPT2046_ADC_LIMIT - (z2 >> 3));
|
||||
|
||||
// If the Z (pressure) exceeds the threshold it is likely the user has
|
||||
// pressed the screen, read in and average the positions.
|
||||
if (z >= CONFIG_XPT2046_Z_THRESHOLD) {
|
||||
uint16_t discard_buf = 0;
|
||||
|
||||
// read and discard a value as it is usually not reliable.
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(tp, X_POSITION, &discard_buf),
|
||||
TAG, "XPT2046 read error!");
|
||||
|
||||
for (uint8_t idx = 0; idx < CONFIG_ESP_LCD_TOUCH_MAX_POINTS; idx++) {
|
||||
uint16_t x_temp = 0;
|
||||
uint16_t y_temp = 0;
|
||||
// Read X position and convert returned data to 12bit value
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(tp, X_POSITION, &x_temp),
|
||||
TAG, "XPT2046 read error!");
|
||||
// drop lowest three bits to convert to 12-bit position
|
||||
x_temp >>= 3;
|
||||
|
||||
// Read Y position and convert returned data to 12bit value
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(tp, Y_POSITION, &y_temp),
|
||||
TAG, "XPT2046 read error!");
|
||||
// drop lowest three bits to convert to 12-bit position
|
||||
y_temp >>= 3;
|
||||
|
||||
// Test if the readings are valid (50 < reading < max - 50)
|
||||
if ((x_temp >= 50) && (x_temp <= XPT2046_ADC_LIMIT - 50) && (y_temp >= 50) && (y_temp <= XPT2046_ADC_LIMIT - 50)) {
|
||||
#if CONFIG_XPT2046_CONVERT_ADC_TO_COORDS
|
||||
// Convert the raw ADC value into a screen coordinate and store it
|
||||
// for averaging.
|
||||
x += ((x_temp / (double)XPT2046_ADC_LIMIT) * tp->config.x_max);
|
||||
y += ((y_temp / (double)XPT2046_ADC_LIMIT) * tp->config.y_max);
|
||||
#else
|
||||
// store the raw ADC values and let the user convert them to screen
|
||||
// coordinates.
|
||||
x += x_temp;
|
||||
y += y_temp;
|
||||
#endif // CONFIG_XPT2046_CONVERT_ADC_TO_COORDS
|
||||
point_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Check we had enough valid values
|
||||
const int minimum_count = (1 == CONFIG_ESP_LCD_TOUCH_MAX_POINTS ? 1 : CONFIG_ESP_LCD_TOUCH_MAX_POINTS / 2);
|
||||
if (point_count >= minimum_count) {
|
||||
// Average the accumulated coordinate data points.
|
||||
x /= point_count;
|
||||
y /= point_count;
|
||||
point_count = 1;
|
||||
} else {
|
||||
z = 0;
|
||||
point_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
XPT2046_LOCK(&tp->data.lock);
|
||||
tp->data.coords[0].x = x;
|
||||
tp->data.coords[0].y = y;
|
||||
tp->data.coords[0].strength = z;
|
||||
tp->data.points = point_count;
|
||||
XPT2046_UNLOCK(&tp->data.lock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool xpt2046_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y,
|
||||
uint16_t *strength, uint8_t *point_num,
|
||||
uint8_t max_point_num)
|
||||
{
|
||||
XPT2046_LOCK(&tp->data.lock);
|
||||
|
||||
// Determine how many touch points that are available.
|
||||
if (tp->data.points > max_point_num) {
|
||||
*point_num = max_point_num;
|
||||
} else {
|
||||
*point_num = tp->data.points;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < *point_num; i++) {
|
||||
x[i] = tp->data.coords[i].x;
|
||||
y[i] = tp->data.coords[i].y;
|
||||
|
||||
if (strength) {
|
||||
strength[i] = tp->data.coords[i].strength;
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate stored touch data.
|
||||
tp->data.points = 0;
|
||||
|
||||
XPT2046_UNLOCK(&tp->data.lock);
|
||||
|
||||
if (*point_num) {
|
||||
ESP_LOGD(TAG, "Touch point: %dx%d", x[0], y[0]);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "No touch points");
|
||||
}
|
||||
|
||||
return (*point_num > 0);
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_xpt2046_read_battery_level(const esp_lcd_touch_handle_t handle, float *output)
|
||||
{
|
||||
uint16_t level;
|
||||
#ifndef CONFIG_XPT2046_VREF_ON_MODE
|
||||
// First read is to turn on the Vref, so it has extra time to stabilise before we read it for real
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, BATTERY, &level), TAG, "XPT2046 read error!");
|
||||
#endif
|
||||
// Read the battery voltage
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, BATTERY, &level), TAG, "XPT2046 read error!");
|
||||
// drop lowest three bits to convert to 12-bit value
|
||||
level >>= 3;
|
||||
|
||||
// battery voltage is reported as 1/4 the actual voltage due to logic in
|
||||
// the chip.
|
||||
*output = level * 4.0;
|
||||
|
||||
// adjust for internal vref of 2.5v
|
||||
*output *= 2.507f;
|
||||
|
||||
// adjust for ADC bit count
|
||||
*output /= 4096.0f;
|
||||
|
||||
#ifndef CONFIG_XPT2046_VREF_ON_MODE
|
||||
// Final read is to turn the Vref off
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, Z_VALUE_1, &level), TAG, "XPT2046 read error!");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_xpt2046_read_aux_level(const esp_lcd_touch_handle_t handle, float *output)
|
||||
{
|
||||
uint16_t level;
|
||||
#ifndef CONFIG_XPT2046_VREF_ON_MODE
|
||||
// First read is to turn on the Vref, so it has extra time to stabilise before we read it for real
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, AUX_IN, &level), TAG, "XPT2046 read error!");
|
||||
#endif
|
||||
// Read the aux input voltage
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, AUX_IN, &level), TAG, "XPT2046 read error!");
|
||||
// drop lowest three bits to convert to 12-bit value
|
||||
level >>= 3;
|
||||
*output = level;
|
||||
|
||||
// adjust for internal vref of 2.5v
|
||||
*output *= 2.507f;
|
||||
|
||||
// adjust for ADC bit count
|
||||
*output /= 4096.0f;
|
||||
|
||||
#ifndef CONFIG_XPT2046_VREF_ON_MODE
|
||||
// Final read is to turn on the ADC and the Vref off
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, Z_VALUE_1, &level), TAG, "XPT2046 read error!");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_xpt2046_read_temp0_level(const esp_lcd_touch_handle_t handle, float *output)
|
||||
{
|
||||
uint16_t temp0;
|
||||
#ifndef CONFIG_XPT2046_VREF_ON_MODE
|
||||
// First read is to turn on the Vref, so it has extra time to stabilise before we read it for real
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, TEMP0, &temp0), TAG, "XPT2046 read error!");
|
||||
#endif
|
||||
// Read the temp0 value
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, TEMP0, &temp0), TAG, "XPT2046 read error!");
|
||||
// drop lowest three bits to convert to 12-bit value
|
||||
temp0 >>= 3;
|
||||
*output = temp0;
|
||||
// Convert to temperature in degrees C
|
||||
*output = (XPT2046_TEMP0_COUNTS_AT_25C - *output) * (2.507 / 4096.0) / 0.0021 + 25.0;
|
||||
|
||||
#ifndef CONFIG_XPT2046_VREF_ON_MODE
|
||||
// Final read is to turn on the ADC and the Vref off
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, Z_VALUE_1, &temp0), TAG, "XPT2046 read error!");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_lcd_touch_xpt2046_read_temp1_level(const esp_lcd_touch_handle_t handle, float *output)
|
||||
{
|
||||
uint16_t temp0;
|
||||
uint16_t temp1;
|
||||
#ifndef CONFIG_XPT2046_VREF_ON_MODE
|
||||
// First read is to turn on the Vref, so it has extra time to stabilise before we read it for real
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, TEMP0, &temp0), TAG, "XPT2046 read error!");
|
||||
#endif
|
||||
// Read the temp0 value
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, TEMP0, &temp0), TAG, "XPT2046 read error!");
|
||||
// Read the temp1 value
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, TEMP1, &temp1), TAG, "XPT2046 read error!");
|
||||
// drop lowest three bits to convert to 12-bit value
|
||||
temp0 >>= 3;
|
||||
temp1 >>= 3;
|
||||
*output = temp1 - temp0;
|
||||
*output = *output * 1000.0 * (2.507 / 4096.0) * 2.573 - 273.0;
|
||||
|
||||
#ifndef CONFIG_XPT2046_VREF_ON_MODE
|
||||
// Final read is to turn on the ADC and the Vref off
|
||||
ESP_RETURN_ON_ERROR(xpt2046_read_register(handle, Z_VALUE_1, &temp0), TAG, "XPT2046 read error!");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 atanisoft (github.com/atanisoft)
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_idf_version.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
|
||||
#include "ESP_Panel_Conf_Internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_TOUCH_XPT2046_VER_MAJOR (1)
|
||||
#define ESP_LCD_TOUCH_XPT2046_VER_MINOR (0)
|
||||
#define ESP_LCD_TOUCH_XPT2046_VER_PATCH (4)
|
||||
|
||||
#define CONFIG_XPT2046_Z_THRESHOLD (ESP_PANEL_TOUCH_XPT2046_Z_THRESHOLD)
|
||||
#define CONFIG_XPT2046_INTERRUPT_MODE (ESP_PANEL_TOUCH_XPT2046_INTERRUPT_MODE)
|
||||
#define CONFIG_XPT2046_VREF_ON_MODE (ESP_PANEL_TOUCH_XPT2046_XPT2046_VREF_ON_MODE)
|
||||
#define CONFIG_XPT2046_CONVERT_ADC_TO_COORDS (ESP_PANEL_TOUCH_XPT2046_CONVERT_ADC_TO_COORDS)
|
||||
|
||||
/**
|
||||
* @brief Recommended clock for SPI read of the XPT2046
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_SPI_CLOCK_HZ (1 * 1000 * 1000)
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5,0,0)
|
||||
|
||||
/**
|
||||
* @brief Communication SPI device IO structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_SPI_XPT2046_CONFIG(touch_cs) \
|
||||
{ \
|
||||
.cs_gpio_num = (gpio_num_t)touch_cs, \
|
||||
.dc_gpio_num = GPIO_NUM_NC, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = ESP_LCD_TOUCH_SPI_CLOCK_HZ, \
|
||||
.trans_queue_depth = 3, \
|
||||
.on_color_trans_done = NULL, \
|
||||
.user_ctx = NULL, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = \
|
||||
{ \
|
||||
.dc_as_cmd_phase = 0, \
|
||||
.dc_low_on_data = 0, \
|
||||
.octal_mode = 0, \
|
||||
.lsb_first = 0 \
|
||||
} \
|
||||
}
|
||||
#elif ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5,1,0)
|
||||
|
||||
/**
|
||||
* @brief Communication SPI device IO structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_SPI_XPT2046_CONFIG(touch_cs) \
|
||||
{ \
|
||||
.cs_gpio_num = (gpio_num_t)touch_cs, \
|
||||
.dc_gpio_num = GPIO_NUM_NC, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = ESP_LCD_TOUCH_SPI_CLOCK_HZ, \
|
||||
.trans_queue_depth = 3, \
|
||||
.on_color_trans_done = NULL, \
|
||||
.user_ctx = NULL, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = \
|
||||
{ \
|
||||
.dc_low_on_data = 0, \
|
||||
.octal_mode = 0, \
|
||||
.lsb_first = 0 \
|
||||
} \
|
||||
}
|
||||
#elif ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5,1,2)
|
||||
|
||||
/**
|
||||
* @brief Communication SPI device IO structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_SPI_XPT2046_CONFIG(touch_cs) \
|
||||
{ \
|
||||
.cs_gpio_num = (gpio_num_t)touch_cs, \
|
||||
.dc_gpio_num = GPIO_NUM_NC, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = ESP_LCD_TOUCH_SPI_CLOCK_HZ, \
|
||||
.trans_queue_depth = 3, \
|
||||
.on_color_trans_done = NULL, \
|
||||
.user_ctx = NULL, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = \
|
||||
{ \
|
||||
.dc_low_on_data = 0, \
|
||||
.octal_mode = 0, \
|
||||
.sio_mode = 0, \
|
||||
.lsb_first = 0, \
|
||||
.cs_high_active = 0 \
|
||||
} \
|
||||
}
|
||||
#elif ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5,1,3)
|
||||
|
||||
/**
|
||||
* @brief Communication SPI device IO structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_SPI_XPT2046_CONFIG(touch_cs) \
|
||||
{ \
|
||||
.cs_gpio_num = (gpio_num_t)touch_cs, \
|
||||
.dc_gpio_num = GPIO_NUM_NC, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = ESP_LCD_TOUCH_SPI_CLOCK_HZ, \
|
||||
.trans_queue_depth = 3, \
|
||||
.on_color_trans_done = NULL, \
|
||||
.user_ctx = NULL, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = \
|
||||
{ \
|
||||
.dc_low_on_data = 0, \
|
||||
.octal_mode = 0, \
|
||||
.quad_mode = 0, \
|
||||
.sio_mode = 0, \
|
||||
.lsb_first = 0, \
|
||||
.cs_high_active = 0 \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
|
||||
/**
|
||||
* @brief Communication SPI device IO structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_SPI_XPT2046_CONFIG(touch_cs) \
|
||||
{ \
|
||||
.cs_gpio_num = (gpio_num_t)touch_cs, \
|
||||
.dc_gpio_num = GPIO_NUM_NC, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = ESP_LCD_TOUCH_SPI_CLOCK_HZ, \
|
||||
.trans_queue_depth = 3, \
|
||||
.on_color_trans_done = NULL, \
|
||||
.user_ctx = NULL, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = \
|
||||
{ \
|
||||
.dc_high_on_cmd = 0, \
|
||||
.dc_low_on_data = 0, \
|
||||
.dc_low_on_param = 0, \
|
||||
.octal_mode = 0, \
|
||||
.quad_mode = 0, \
|
||||
.sio_mode = 0, \
|
||||
.lsb_first = 0, \
|
||||
.cs_high_active = 0 \
|
||||
} \
|
||||
}
|
||||
#endif // IDF v5.1.3
|
||||
|
||||
/**
|
||||
* @brief Create a new XPT2046 touch driver
|
||||
*
|
||||
* @note The SPI communication should be initialized before use this function.
|
||||
*
|
||||
* @param io: LCD/Touch panel IO handle.
|
||||
* @param config: Touch configuration.
|
||||
* @param out_touch: XPT2046 instance handle.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM if there is insufficient memory for allocating main structure.
|
||||
* - ESP_ERR_INVALID_ARG if @param io or @param config are null.
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_new_spi_xpt2046(const esp_lcd_panel_io_handle_t io,
|
||||
const esp_lcd_touch_config_t *config,
|
||||
esp_lcd_touch_handle_t *out_touch);
|
||||
|
||||
/**
|
||||
* @brief Reads the voltage from the v-bat pin of the XPT2046.
|
||||
*
|
||||
* @param handle: XPT2046 instance handle.
|
||||
* @param out_level: Approximate voltage read in from the v-bat pin.
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*
|
||||
* @note The v-bat pin has a voltage range of 0.0 to 6.0 volts.
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_xpt2046_read_battery_level(const esp_lcd_touch_handle_t handle, float *out_level);
|
||||
|
||||
/**
|
||||
* @brief Reads the voltage from the aux pin of the XPT2046.
|
||||
*
|
||||
* @param handle: XPT2046 instance handle.
|
||||
* @param out_level: Approximate voltage read in from the aux pin.
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*
|
||||
* @note The aux pin has a voltage range of 0.0 to 2.5 volts.
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_xpt2046_read_aux_level(const esp_lcd_touch_handle_t handle, float *out_level);
|
||||
|
||||
/**
|
||||
* @brief Reads the temperature from the XPT2046 using a one-point reading.
|
||||
* High precision (0.3 degrees C) but low accuracy requires a
|
||||
* calibration offset for accurate results.
|
||||
*
|
||||
* @param handle: XPT2046 instance handle.
|
||||
* @param out_level: Approximate tempreature of the TSC2046 in degrees C
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_xpt2046_read_temp0_level(const esp_lcd_touch_handle_t handle, float *output);
|
||||
|
||||
/**
|
||||
* @brief Reads the temperature from the XPT2046 using a two-point reading.
|
||||
* Low precision (1.6 degrees C) but high accuracy requires no calibration.
|
||||
*
|
||||
* @param handle: XPT2046 instance handle.
|
||||
* @param out_level: Approximate tempreature of the TSC2046 in degrees C
|
||||
* @return
|
||||
* - ESP_OK on success, otherwise returns ESP_ERR_xxx
|
||||
*/
|
||||
esp_err_t esp_lcd_touch_xpt2046_read_temp1_level(const esp_lcd_touch_handle_t handle, float *output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in new issue
Block a user