Add board: Waveshare S3 Touch LCD 1.47 (#328)
Touch isn't working yet. Fixed a SPI lock issue.
This commit is contained in:
committed by
GitHub
parent
84049658db
commit
980b115f1d
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "esp_lcd_touch_axs5106.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES "esp_lcd" "driver" "espressif__esp_lcd_touch")
|
||||
@@ -0,0 +1,7 @@
|
||||
# AXS5106
|
||||
|
||||
I2C touch driver.
|
||||
|
||||
Source: https://files.waveshare.com/wiki/1.47inch%20Touch%20LCD/1.47inch_Touch_LCD_Demo_ESP32.zip
|
||||
|
||||
License: Apache 2.0
|
||||
@@ -0,0 +1,260 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_lcd_touch_axs5106.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 "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_touch.h"
|
||||
|
||||
static const char *TAG = "esp_lcd_touch_axs5106";
|
||||
|
||||
#define TOUCH_AXS5106_TOUCH_POINTS_REG (0X01)
|
||||
#define TOUCH_AXS5106_TOUCH_P1_XH_REG (0x03)
|
||||
#define TOUCH_AXS5106_TOUCH_P1_XL_REG (0x04)
|
||||
#define TOUCH_AXS5106_TOUCH_P1_YH_REG (0x05)
|
||||
#define TOUCH_AXS5106_TOUCH_P1_YL_REG (0x06)
|
||||
|
||||
#define TOUCH_AXS5106_TOUCH_ID_REG (0x08)
|
||||
#define TOUCH_AXS5106_TOUCH_P2_XH_REG (0x09)
|
||||
#define TOUCH_AXS5106_TOUCH_P2_XL_REG (0x0A)
|
||||
#define TOUCH_AXS5106_TOUCH_P2_YH_REG (0x0B)
|
||||
#define TOUCH_AXS5106_TOUCH_P2_YL_REG (0x0C)
|
||||
|
||||
/*******************************************************************************
|
||||
* Function definitions
|
||||
*******************************************************************************/
|
||||
static esp_err_t esp_lcd_touch_axs5106_read_data(esp_lcd_touch_handle_t tp);
|
||||
static bool esp_lcd_touch_axs5106_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_axs5106_del(esp_lcd_touch_handle_t tp);
|
||||
|
||||
/* I2C read */
|
||||
static esp_err_t touch_axs5106_i2c_write(esp_lcd_touch_handle_t tp, uint8_t reg, uint8_t *data, uint8_t len);
|
||||
static esp_err_t touch_axs5106_i2c_read(esp_lcd_touch_handle_t tp, uint8_t reg, uint8_t *data, uint8_t len);
|
||||
|
||||
/* AXS5106 init */
|
||||
static esp_err_t touch_axs5106_init(esp_lcd_touch_handle_t tp);
|
||||
/* AXS5106 reset */
|
||||
static esp_err_t touch_axs5106_reset(esp_lcd_touch_handle_t tp);
|
||||
|
||||
esp_err_t esp_lcd_touch_new_i2c_axs5106(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);
|
||||
|
||||
/* Prepare main structure */
|
||||
esp_lcd_touch_handle_t esp_lcd_touch_axs5106 = heap_caps_calloc(1, sizeof(esp_lcd_touch_t), MALLOC_CAP_DEFAULT);
|
||||
ESP_GOTO_ON_FALSE(esp_lcd_touch_axs5106, ESP_ERR_NO_MEM, err, TAG, "no mem for AXS5106 controller");
|
||||
|
||||
/* Communication interface */
|
||||
esp_lcd_touch_axs5106->io = io;
|
||||
|
||||
/* Only supported callbacks are set */
|
||||
esp_lcd_touch_axs5106->read_data = esp_lcd_touch_axs5106_read_data;
|
||||
esp_lcd_touch_axs5106->get_xy = esp_lcd_touch_axs5106_get_xy;
|
||||
esp_lcd_touch_axs5106->del = esp_lcd_touch_axs5106_del;
|
||||
|
||||
/* Mutex */
|
||||
esp_lcd_touch_axs5106->data.lock.owner = portMUX_FREE_VAL;
|
||||
|
||||
/* Save config */
|
||||
memcpy(&esp_lcd_touch_axs5106->config, config, sizeof(esp_lcd_touch_config_t));
|
||||
|
||||
/* Prepare pin for touch interrupt */
|
||||
if (esp_lcd_touch_axs5106->config.int_gpio_num != GPIO_NUM_NC)
|
||||
{
|
||||
const gpio_config_t int_gpio_config = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.intr_type = (esp_lcd_touch_axs5106->config.levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE),
|
||||
.pin_bit_mask = BIT64(esp_lcd_touch_axs5106->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_axs5106->config.interrupt_callback)
|
||||
{
|
||||
esp_lcd_touch_register_interrupt_callback(esp_lcd_touch_axs5106, esp_lcd_touch_axs5106->config.interrupt_callback);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare pin for touch controller reset */
|
||||
if (esp_lcd_touch_axs5106->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_axs5106->config.rst_gpio_num)};
|
||||
ret = gpio_config(&rst_gpio_config);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "GPIO config failed");
|
||||
}
|
||||
|
||||
/* Reset controller */
|
||||
ret = touch_axs5106_reset(esp_lcd_touch_axs5106);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "AXS5106 reset failed");
|
||||
|
||||
/* Init controller */
|
||||
ret = touch_axs5106_init(esp_lcd_touch_axs5106);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "AXS5106 init failed");
|
||||
|
||||
uint8_t data[3] = { 0 };
|
||||
if (touch_axs5106_i2c_read(esp_lcd_touch_axs5106, TOUCH_AXS5106_TOUCH_ID_REG, data, 3) == ESP_OK) {
|
||||
if (data[0] != 0x00) {
|
||||
ESP_LOGI(TAG, "Read: %02x %02x %02x", data[0], data[1], data[2]);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Failed to read id: received zeroes");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to read id: receive failed");
|
||||
}
|
||||
|
||||
err:
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Error (0x%x)! Touch controller AXS5106 initialization failed!", ret);
|
||||
if (esp_lcd_touch_axs5106)
|
||||
{
|
||||
esp_lcd_touch_axs5106_del(esp_lcd_touch_axs5106);
|
||||
}
|
||||
}
|
||||
|
||||
*out_touch = esp_lcd_touch_axs5106;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_lcd_touch_axs5106_read_data(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
uint8_t data[30] = {0};
|
||||
size_t i = 0;
|
||||
|
||||
assert(tp != NULL);
|
||||
|
||||
esp_err_t err = touch_axs5106_i2c_read(tp, TOUCH_AXS5106_TOUCH_POINTS_REG, data, 14);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "I2C read error: %s", esp_err_to_name(err));
|
||||
|
||||
uint8_t points = data[1];
|
||||
points = points & 0x0F;
|
||||
|
||||
if (points == 0)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Number of touched points */
|
||||
points = (points > 2 ? 2 : points);
|
||||
|
||||
// err = touch_axs5106_i2c_read(tp, TOUCH_AXS5106_TOUCH_P1_XH_REG, 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].y = (((uint16_t)(data[4 + i * 6] & 0x0f)) << 8);
|
||||
tp->data.coords[i].y |= data[5 + i * 6];
|
||||
tp->data.coords[i].x = ((uint16_t)(data[2 + i * 6] & 0x0f)) << 8;
|
||||
tp->data.coords[i].x |= data[3 + i * 6];
|
||||
}
|
||||
portEXIT_CRITICAL(&tp->data.lock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool esp_lcd_touch_axs5106_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_axs5106_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;
|
||||
}
|
||||
|
||||
static esp_err_t touch_axs5106_i2c_write(esp_lcd_touch_handle_t tp, uint8_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
return esp_lcd_panel_io_tx_param(tp->io, reg, data, len);
|
||||
}
|
||||
|
||||
static esp_err_t touch_axs5106_i2c_read(esp_lcd_touch_handle_t tp, uint8_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
assert(tp != NULL);
|
||||
assert(data != NULL);
|
||||
return esp_lcd_panel_io_rx_param(tp->io, reg, data, len);
|
||||
}
|
||||
|
||||
static esp_err_t touch_axs5106_init(esp_lcd_touch_handle_t tp)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t touch_axs5106_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;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD touch: AXS5106
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_touch.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Create a new AXS5106 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_axs5106(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 AXS5106 controller
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_AXS5106_ADDRESS (0x63)
|
||||
|
||||
/**
|
||||
* @brief Touch IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ESP_LCD_TOUCH_IO_I2C_AXS5106_CONFIG() \
|
||||
{ \
|
||||
.dev_addr = ESP_LCD_TOUCH_IO_I2C_AXS5106_ADDRESS, \
|
||||
.control_phase_bytes = 1, \
|
||||
.dc_bit_offset = 0, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.flags = \
|
||||
{ \
|
||||
.disable_control_phase = 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user