lvgl_esp32_drivers/lvgl_touch/xpt2046.c
C47D ea37784f08 Remove TAG from LVGL log API in touch drivers
The filename is appended at the beginning of the log output by default, we don't need to do it.
2021-10-22 18:45:52 -05:00

218 lines
4.9 KiB
C

/**
* @file XPT2046.c
*
*/
/*********************
* INCLUDES
*********************/
#include "xpt2046.h"
#include "esp_system.h"
#include "driver/gpio.h"
#include "tp_spi.h"
#include <stddef.h>
/*********************
* DEFINES
*********************/
#define CMD_X_READ 0b10010000 // NOTE: XPT2046 data sheet says this is actually Y
#define CMD_Y_READ 0b11010000 // NOTE: XPT2046 data sheet says this is actually X
#define CMD_Z1_READ 0b10110000
#define CMD_Z2_READ 0b11000000
/**********************
* TYPEDEFS
**********************/
typedef enum {
TOUCH_NOT_DETECTED = 0,
TOUCH_DETECTED = 1,
} xpt2046_touch_detect_t;
/**********************
* STATIC PROTOTYPES
**********************/
static void xpt2046_corr(int16_t * x, int16_t * y);
static void xpt2046_avg(int16_t * x, int16_t * y);
static int16_t xpt2046_cmd(uint8_t cmd);
static xpt2046_touch_detect_t xpt2048_is_touch_detected();
/**********************
* STATIC VARIABLES
**********************/
int16_t avg_buf_x[XPT2046_AVG];
int16_t avg_buf_y[XPT2046_AVG];
uint8_t avg_last;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Initialize the XPT2046
*/
void xpt2046_init(void)
{
LV_LOG_INFO("Initialization");
#if XPT2046_TOUCH_IRQ || XPT2046_TOUCH_IRQ_PRESS
gpio_config_t irq_config = {
.pin_bit_mask = BIT64(XPT2046_IRQ),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
esp_err_t ret = gpio_config(&irq_config);
assert(ret == ESP_OK);
#endif
}
/**
* Get the current position and state of the touchpad
* @param data store the read data here
* @return false: because no more data to be read
*/
bool xpt2046_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
static int16_t last_x = 0;
static int16_t last_y = 0;
bool valid = false;
int16_t x = last_x;
int16_t y = last_y;
if (xpt2048_is_touch_detected() == TOUCH_DETECTED)
{
valid = true;
x = xpt2046_cmd(CMD_X_READ);
y = xpt2046_cmd(CMD_Y_READ);
LV_LOG_INFO("P(%d,%d)", x, y);
/*Normalize Data back to 12-bits*/
x = x >> 4;
y = y >> 4;
LV_LOG_INFO("P_norm(%d,%d)", x, y);
xpt2046_corr(&x, &y);
xpt2046_avg(&x, &y);
last_x = x;
last_y = y;
LV_LOG_INFO("x = %d, y = %d", x, y);
}
else
{
avg_last = 0;
}
data->point.x = x;
data->point.y = y;
data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR;
return false;
}
/**********************
* STATIC FUNCTIONS
**********************/
static xpt2046_touch_detect_t xpt2048_is_touch_detected()
{
// check IRQ pin if we IRQ or IRQ and preessure
#if XPT2046_TOUCH_IRQ || XPT2046_TOUCH_IRQ_PRESS
uint8_t irq = gpio_get_level(XPT2046_IRQ);
if (irq != 0) {
return TOUCH_NOT_DETECTED;
}
#endif
// check pressure if we are pressure or IRQ and pressure
#if XPT2046_TOUCH_PRESS || XPT2046_TOUCH_IRQ_PRESS
int16_t z1 = xpt2046_cmd(CMD_Z1_READ) >> 3;
int16_t z2 = xpt2046_cmd(CMD_Z2_READ) >> 3;
// this is not what the confusing datasheet says but it seems to
// be enough to detect real touches on the panel
int16_t z = z1 + 4096 - z2;
if (z < XPT2046_TOUCH_THRESHOLD)
{
return TOUCH_NOT_DETECTED;
}
#endif
return TOUCH_DETECTED;
}
static int16_t xpt2046_cmd(uint8_t cmd)
{
uint8_t data[2];
tp_spi_read_reg(cmd, data, 2);
int16_t val = (data[0] << 8) | data[1];
return val;
}
static void xpt2046_corr(int16_t * x, int16_t * y)
{
#if XPT2046_XY_SWAP != 0
int16_t swap_tmp;
swap_tmp = *x;
*x = *y;
*y = swap_tmp;
#endif
if((*x) > XPT2046_X_MIN)(*x) -= XPT2046_X_MIN;
else(*x) = 0;
if((*y) > XPT2046_Y_MIN)(*y) -= XPT2046_Y_MIN;
else(*y) = 0;
(*x) = (uint32_t)((uint32_t)(*x) * LV_HOR_RES) /
(XPT2046_X_MAX - XPT2046_X_MIN);
(*y) = (uint32_t)((uint32_t)(*y) * LV_VER_RES) /
(XPT2046_Y_MAX - XPT2046_Y_MIN);
#if XPT2046_X_INV != 0
(*x) = LV_HOR_RES - (*x);
#endif
#if XPT2046_Y_INV != 0
(*y) = LV_VER_RES - (*y);
#endif
}
static void xpt2046_avg(int16_t * x, int16_t * y)
{
/*Shift out the oldest data*/
uint8_t i;
for(i = XPT2046_AVG - 1; i > 0 ; i--) {
avg_buf_x[i] = avg_buf_x[i - 1];
avg_buf_y[i] = avg_buf_y[i - 1];
}
/*Insert the new point*/
avg_buf_x[0] = *x;
avg_buf_y[0] = *y;
if(avg_last < XPT2046_AVG) avg_last++;
/*Sum the x and y coordinates*/
int32_t x_sum = 0;
int32_t y_sum = 0;
for(i = 0; i < avg_last ; i++) {
x_sum += avg_buf_x[i];
y_sum += avg_buf_y[i];
}
/*Normalize the sums*/
(*x) = (int32_t)x_sum / avg_last;
(*y) = (int32_t)y_sum / avg_last;
}