Move drivers from the lv_port_esp32 to here

This commit is contained in:
C47D 2020-12-17 00:02:55 -06:00
parent 5a32d98f83
commit 08384030b0
69 changed files with 14977 additions and 2 deletions

34
lvgl_touch/CMakeLists.txt Normal file
View file

@ -0,0 +1,34 @@
if(ESP_PLATFORM)
set(SOURCES "touch_driver.c")
# Include only the source file of the selected
# display controller.
if(CONFIG_LV_TOUCH_CONTROLLER_XPT2046)
list(APPEND SOURCES "xpt2046.c")
elseif(CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
list(APPEND SOURCES "ft6x36.c")
elseif(CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
list(APPEND SOURCES "stmpe610")
elseif(CONFIG_LV_TOUCH_CONTROLLER_ADCRAW)
list(APPEND SOURCES "adcraw.c")
elseif(CONFIG_LV_TOUCH_CONTROLLER_FT81X)
list(APPEND SOURCES "FT81x.c")
elseif(CONFIG_LV_TOUCH_CONTROLLER_RA8875)
list(APPEND SOURCES "ra8875_touch.c")
endif()
if(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI)
list(APPEND SOURCES "tp_spi.c")
elseif(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C)
list(APPEND SOURCES "tp_i2c.c")
endif()
# Print the included source files
message("SOURCES contents: " "${SOURCES}")
idf_component_register(SRCS ${SOURCES}
INCLUDE_DIRS .
REQUIRES lvgl)
endif()

85
lvgl_touch/FT81x.c Normal file
View file

@ -0,0 +1,85 @@
/**
* @file FT81x.c
*/
/*********************
* INCLUDES
*********************/
#include "esp_system.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include <stddef.h>
#include "FT81x.h"
#include "../lvgl_tft/EVE.h"
#include "../lvgl_tft/EVE_commands.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* 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 FT81x_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
static int16_t last_x = 0;
static int16_t last_y = 0;
bool touched = true;
uint32_t XY = EVE_memRead32(REG_TOUCH_SCREEN_XY);
uint16_t Y = XY & 0xffff;
uint16_t X = XY >> 16;
// is it not touched (or invalid because of calibration range)
if(X == 0x8000 || Y == 0x8000 || X > LV_HOR_RES_MAX || Y > LV_VER_RES_MAX)
{
touched = false;
X = last_x;
Y = last_y;
}
else
{
last_x = X;
last_y = Y;
}
data->point.x = X;
data->point.y = Y;
data->state = (touched == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR);
return false;
}
/**********************
* STATIC FUNCTIONS
**********************/

46
lvgl_touch/FT81x.h Normal file
View file

@ -0,0 +1,46 @@
/**
* @file STMPE610.h
*/
#ifndef FT81X_TOUCH__H
#define FT81X_TOUCH__H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdint.h>
#include <stdbool.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
;
bool FT81x_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FT81X_TOUCH__H */

458
lvgl_touch/Kconfig Normal file
View file

@ -0,0 +1,458 @@
menu "LVGL Touch controller"
config LV_TOUCH_CONTROLLER
int
default 0 if LV_TOUCH_CONTROLLER_NONE
default 1 if LV_TOUCH_CONTROLLER_XPT2046
default 2 if LV_TOUCH_CONTROLLER_FT6X06
default 3 if LV_TOUCH_CONTROLLER_STMPE610
default 4 if LV_TOUCH_CONTROLLER_ADCRAW
default 5 if LV_TOUCH_CONTROLLER_FT81X
default 6 if LV_TOUCH_CONTROLLER_RA8875
choice
prompt "Select a touch panel controller model."
default LV_TOUCH_CONTROLLER_NONE
help
Select the controller for your touch panel.
config LV_TOUCH_CONTROLLER_NONE
bool "None"
config LV_TOUCH_CONTROLLER_XPT2046
select LV_TOUCH_DRIVER_PROTOCOL_SPI
bool "XPT2046"
config LV_TOUCH_CONTROLLER_FT6X06
select LV_TOUCH_DRIVER_PROTOCOL_I2C
bool "FT6X06"
config LV_TOUCH_CONTROLLER_STMPE610
select LV_TOUCH_DRIVER_PROTOCOL_SPI
bool "STMPE610"
config LV_TOUCH_CONTROLLER_ADCRAW
select LV_TOUCH_DRIVER_ADC
bool "ADCRAW"
config LV_TOUCH_CONTROLLER_FT81X
select LV_TOUCH_DRIVER_PROTOCOL_SPI
bool "FT81X"
config LV_TOUCH_CONTROLLER_RA8875
select LV_TOUCH_DRIVER_DISPLAY
bool "RA8875"
endchoice
config LV_TOUCH_DRIVER_PROTOCOL_SPI
bool
help
Touch controller protocol SPI
config LV_TOUCH_DRIVER_PROTOCOL_I2C
bool
help
Touch controller protocol I2C
config LV_TOUCH_DRIVER_ADC
bool
help
Touch controller via ADC
config LV_TOUCH_DRIVER_DISPLAY
bool
help
Touch controller uses same interface/device as display
(Note: Display must be initialized before touch)
choice
prompt "Touch I2C port"
depends on LV_TOUCH_DRIVER_PROTOCOL_I2C
default LV_TOUCH_I2C_PORT_0
help
Select the I2C port used by the touch controller.
config LV_TOUCH_I2C_PORT_0
bool "I2C PORT 0"
config LV_TOUCH_I2C_PORT_1
bool "I2C PORT 1"
endchoice
choice
prompt "Touch Controller SPI Bus."
depends on LV_TOUCH_DRIVER_PROTOCOL_SPI
default LV_TOUCH_CONTROLLER_SPI_VSPI if !IDF_TARGET_ESP32S2
default LV_TOUCH_CONTROLLER_SPI_FSPI if IDF_TARGET_ESP32S2
help
Select the SPI Bus the TFT Display is attached to.
config LV_TOUCH_CONTROLLER_SPI_HSPI
bool "HSPI"
config LV_TOUCH_CONTROLLER_SPI_VSPI
bool "VSPI" if !IDF_TARGET_ESP32S2
config LV_TOUCH_CONTROLLER_SPI_FSPI
bool "FSPI" if IDF_TARGET_ESP32S2
endchoice
menu "Touchpanel (XPT2046) Pin Assignments"
depends on LV_TOUCH_CONTROLLER_XPT2046
config LV_TOUCH_SPI_MISO
int
prompt "GPIO for MISO (Master In Slave Out)"
range 0 39
default 35 if LV_PREDEFINED_PINS_38V1
default 19
help
Configure the touchpanel MISO pin here.
config LV_TOUCH_SPI_MOSI
int
prompt "GPIO for MOSI (Master Out Slave In)"
range 0 39
default 32 if LV_PREDEFINED_PINS_38V1
default 23
help
Configure the touchpanel MOSI pin here.
config LV_TOUCH_SPI_CLK
int "GPIO for CLK (SCK / Serial Clock)"
range 0 39
default 26 if LV_PREDEFINED_PINS_38V1
default 18
help
Configure the touchpanel CLK pin here.
config LV_TOUCH_SPI_CS
int "GPIO for CS (Slave Select)"
range 0 39
default 33 if LV_PREDEFINED_PINS_38V1
default 5
help
Configure the touchpanel CS pin here.
config LV_TOUCH_PIN_IRQ
int "GPIO for IRQ (Interrupt Request)"
range 0 39
default 27 if LV_PREDEFINED_PINS_38V4
default 25
help
Configure the touchpanel CS pin here.
endmenu
menu "Touchpanel Configuration (XPT2046)"
depends on LV_TOUCH_CONTROLLER_XPT2046
config LV_TOUCH_X_MIN
int
prompt "Minimum X coordinate value."
default 0 if LV_PREDEFINED_PINS_38V4
default 200
config LV_TOUCH_Y_MIN
int
prompt "Minimum Y coordinate value."
default 0 if LV_PREDEFINED_PINS_38V4
default 120
config LV_TOUCH_X_MAX
int
prompt "Maximum X coordinate value."
default 4095 if LV_PREDEFINED_PINS_38V4
default 1900
config LV_TOUCH_Y_MAX
int
prompt "Maximum Y coordinate value."
default 4095 if LV_PREDEFINED_PINS_38V4
default 1900
config LV_TOUCH_XY_SWAP
bool
prompt "Swap XY."
default y
config LV_TOUCH_INVERT_X
bool
prompt "Invert X coordinate value."
default y
config LV_TOUCH_INVERT_Y
bool
prompt "Invert Y coordinate value."
default y
endmenu
menu "Touchpanel (FT6X06) Pin Assignments"
depends on LV_TOUCH_CONTROLLER_FT6X06
config LV_TOUCH_I2C_SDA
int
prompt "GPIO for SDA (I2C)"
range 0 39
default 21
help
Configure the I2C touchpanel SDA pin here.
config LV_TOUCH_I2C_SCL
int "GPIO for clock signal SCL (I2C)"
range 0 39
default 22
help
Configure the I2C touchpanel SCL pin here.
endmenu
menu "Touchpanel Configuration (FT6X06)"
depends on LV_TOUCH_CONTROLLER_FT6X06
config LV_FT6X36_SWAPXY
bool
prompt "Swap X with Y coordinate."
default y
config LV_FT6X36_INVERT_X
bool
prompt "Invert X coordinate value."
default n
config LV_FT6X36_INVERT_Y
bool
prompt "Invert Y coordinate value."
default y
endmenu
menu "Touchpanel (STMPE610) Pin Assignments"
depends on LV_TOUCH_CONTROLLER_STMPE610
config LV_TOUCH_SPI_MISO
int
prompt "GPIO for MISO (Master In Slave Out)"
range 0 39
default 35 if LV_PREDEFINED_PINS_38V1
default 19 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
default 19
help
Configure the touchpanel MISO pin here.
config LV_TOUCH_SPI_MOSI
int
prompt "GPIO for MOSI (Master Out Slave In)"
range 0 39
default 32 if LV_PREDEFINED_PINS_38V1
default 18 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
default 23
help
Configure the touchpanel MOSI pin here.
config LV_TOUCH_SPI_CLK
int "GPIO for CLK (SCK / Serial Clock)"
range 0 39
default 26 if LV_PREDEFINED_PINS_38V1
default 5 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
default 18
help
Configure the touchpanel CLK pin here.
config LV_TOUCH_SPI_CS
int "GPIO for CS (Slave Select)"
range 0 39
default 33 if LV_PREDEFINED_PINS_38V1
default 32 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING
default 5
help
Configure the touchpanel CS pin here.
endmenu
menu "Touchpanel Configuration (STMPE610)"
depends on LV_TOUCH_CONTROLLER_STMPE610
config LV_TOUCH_X_MIN
int
prompt "Minimum X coordinate value."
default 160
config LV_TOUCH_Y_MIN
int
prompt "Minimum Y coordinate value."
default 230
config LV_TOUCH_X_MAX
int
prompt "Maximum X coordinate value."
default 3800
config LV_TOUCH_Y_MAX
int
prompt "Maximum Y coordinate value."
default 3800
config LV_TOUCH_XY_SWAP
bool
prompt "Swap XY."
default n
config LV_TOUCH_INVERT_X
bool
prompt "Invert X coordinate value."
default y
config LV_TOUCH_INVERT_Y
bool
prompt "Invert Y coordinate value."
default y
endmenu
menu "Touchpanel (ADCRAW) Pin Assignments"
depends on LV_TOUCH_CONTROLLER_ADCRAW
config LV_TOUCHSCREEN_RESISTIVE_PIN_YU
int
prompt "GPIO Y+"
default 26 if CONFIG_LV_PREDEFINED_DISPLAY_WROVER4
default 26
help
Configure the touchpanel Y+ pin. Can be a regular GPIO.
config LV_TOUCHSCREEN_RESISTIVE_PIN_YD
int
prompt "GPIO/ADC Y-"
default 32 if CONFIG_LV_PREDEFINED_DISPLAY_WROVER4
default 32
help
Configure the touchpanel Y- pin. Must be ADC input.
config LV_TOUCHSCREEN_RESISTIVE_PIN_XL
int
prompt "GPIO X-"
default 27 if CONFIG_LV_PREDEFINED_DISPLAY_WROVER4
default 27
help
Configure the touchpanel X- pin. Can be a regular GPIO.
config LV_TOUCHSCREEN_RESISTIVE_PIN_XR
int
prompt "GPIO/ADC X+"
default 33 if CONFIG_LV_PREDEFINED_DISPLAY_WROVER4
default 33
help
Configure the touchpanel X- pin. Must be ADC input.
endmenu
menu "Touchpanel Configuration (ADCRAW)"
depends on LV_TOUCH_CONTROLLER_ADCRAW
config LV_TOUCH_X_MIN
int
prompt "Minimum X coordinate value."
default 160
config LV_TOUCH_Y_MIN
int
prompt "Minimum Y coordinate value."
default 230
config LV_TOUCH_X_MAX
int
prompt "Maximum X coordinate value."
default 3800
config LV_TOUCH_Y_MAX
int
prompt "Maximum Y coordinate value."
default 3800
config LV_TOUCH_XY_SWAP
bool
prompt "Swap XY."
default n
config LV_TOUCH_INVERT_X
bool
prompt "Invert X coordinate value."
default y
config LV_TOUCH_INVERT_Y
bool
prompt "Invert Y coordinate value."
default y
endmenu
menu "Touchpanel Configuration (RA8875)"
depends on LV_TOUCH_CONTROLLER_RA8875
config LV_TOUCH_X_MIN
int
prompt "Minimum X coordinate ADC value"
range 0 1023
default 0
config LV_TOUCH_Y_MIN
int
prompt "Minimum Y coordinate ADC value"
range 0 1023
default 0
config LV_TOUCH_X_MAX
int
prompt "Maximum X coordinate ADC value"
range 0 1023
default 1023
config LV_TOUCH_Y_MAX
int
prompt "Maximum Y coordinate ADC value"
range 0 1023
default 1023
config LV_TOUCH_XY_SWAP
bool
prompt "Swap XY"
default n
config LV_TOUCH_INVERT_X
bool
prompt "Invert X coordinate value"
default n
config LV_TOUCH_INVERT_Y
bool
prompt "Invert Y coordinate value"
default n
config LV_TOUCH_RA8875_SAMPLE_TIME
int
prompt "TP Sample Time Adjusting"
range 0 7
default 0
config LV_TOUCH_RA8875_ADC_CLOCK
int
prompt "ADC Clock Setting"
range 0 7
default 0
config LV_TOUCH_RA8875_WAKEUP_ENABLE
bool
prompt "Touch Panel Wakeup Enable"
default n
config LV_TOUCH_RA8875_EXTERNAL_VREF
bool
prompt "TP ADC Use External Reference Voltage Source"
default n
config LV_TOUCH_RA8875_DEBOUNCE_ENABLE
bool
prompt "De-bounce Circuit Enable for Touch Panel Interrupt"
default y
endmenu
endmenu

324
lvgl_touch/adcraw.c Normal file
View file

@ -0,0 +1,324 @@
/**
* @file ADCRAW.c
*/
#include "adcraw.h"
#include "esp_system.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include <stddef.h>
#if CONFIG_LV_TOUCH_CONTROLLER_ADCRAW
#define TAG "ADCRAW"
#define CALIBRATIONINSET 1 // range 0 <= CALIBRATIONINSET <= 40
#define SAMPLE_CALIBRATION_POINTS 4
// use this scale factor to avoid working in floating point numbers
#define TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR 8
#define SCALE_FACTOR (1 << TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR)
#define CAL_X_INSET (((GetMaxX() + 1) * (CALIBRATIONINSET >> 1)) / 100)
#define CAL_Y_INSET (((GetMaxY() + 1) * (CALIBRATIONINSET >> 1)) / 100)
#define NUMSAMPLES 8
static void ad_touch_handler(void *arg);
static const esp_timer_create_args_t periodic_timer_args = {
.callback = &ad_touch_handler,
};
static esp_timer_handle_t periodic_timer;
// Current ADC values for X and Y channels
int16_t adcX, adcY = 0;
int16_t temp_x, temp_y, temp_z1, temp_z2;
// coefficient values
int _trA, _trB, _trC, _trD;
int16_t xRawTouch[SAMPLE_CALIBRATION_POINTS];
int16_t yRawTouch[SAMPLE_CALIBRATION_POINTS];
TOUCH_STATES state;
const gpio_num_t yu = TOUCHSCREEN_RESISTIVE_PIN_YU;
const gpio_num_t xl = TOUCHSCREEN_RESISTIVE_PIN_XL;
const gpio_num_t yd = TOUCHSCREEN_RESISTIVE_PIN_YD;
const gpio_num_t xr = TOUCHSCREEN_RESISTIVE_PIN_XR;
static const int gpio_to_adc[] = {
GPIO_TO_ADC_ELEMENT(TOUCHSCREEN_RESISTIVE_PIN_YD),
GPIO_TO_ADC_ELEMENT(TOUCHSCREEN_RESISTIVE_PIN_XR)
};
static void TouchCalculateCalPoints(void)
{
int32_t trA, trB, trC, trD; // variables for the coefficients
int32_t trAhold, trBhold, trChold, trDhold;
int32_t test1, test2; // temp variables (must be signed type)
int16_t xPoint[SAMPLE_CALIBRATION_POINTS], yPoint[SAMPLE_CALIBRATION_POINTS];
yPoint[0] = yPoint[1] = CAL_Y_INSET;
yPoint[2] = yPoint[3] = (GetMaxY() - CAL_Y_INSET);
xPoint[0] = xPoint[3] = CAL_X_INSET;
xPoint[1] = xPoint[2] = (GetMaxX() - CAL_X_INSET);
// calculate points transfer function
// based on two simultaneous equations solve for the constants
// use sample points 1 and 4
// Dy1 = aTy1 + b; Dy4 = aTy4 + b
// Dx1 = cTx1 + d; Dy4 = aTy4 + b
test1 = (int32_t)yPoint[0] - (int32_t)yPoint[3];
test2 = (int32_t)yRawTouch[0] - (int32_t)yRawTouch[3];
trA = ((int32_t)((int32_t)test1 * SCALE_FACTOR) / test2);
trB = ((int32_t)((int32_t)yPoint[0] * SCALE_FACTOR) - (trA * (int32_t)yRawTouch[0]));
test1 = (int32_t)xPoint[0] - (int32_t)xPoint[2];
test2 = (int32_t)xRawTouch[0] - (int32_t)xRawTouch[2];
trC = ((int32_t)((int32_t)test1 * SCALE_FACTOR) / test2);
trD = ((int32_t)((int32_t)xPoint[0] * SCALE_FACTOR) - (trC * (int32_t)xRawTouch[0]));
trAhold = trA;
trBhold = trB;
trChold = trC;
trDhold = trD;
// use sample points 2 and 3
// Dy2 = aTy2 + b; Dy3 = aTy3 + b
// Dx2 = cTx2 + d; Dy3 = aTy3 + b
test1 = (int32_t)yPoint[1] - (int32_t)yPoint[2];
test2 = (int32_t)yRawTouch[1] - (int32_t)yRawTouch[2];
trA = ((int32_t)(test1 * SCALE_FACTOR) / test2);
trB = ((int32_t)((int32_t)yPoint[1] * SCALE_FACTOR) - (trA * (int32_t)yRawTouch[1]));
test1 = (int32_t)xPoint[1] - (int32_t)xPoint[3];
test2 = (int32_t)xRawTouch[1] - (int32_t)xRawTouch[3];
trC = ((int32_t)((int32_t)test1 * SCALE_FACTOR) / test2);
trD = ((int32_t)((int32_t)xPoint[1] * SCALE_FACTOR) - (trC * (int32_t)xRawTouch[1]));
// get the average and use it
_trA = (trA + trAhold) >> 1;
_trB = (trB + trBhold) >> 1;
_trC = (trC + trChold) >> 1;
_trD = (trD + trDhold) >> 1;
}
void adcraw_init(void)
{
state = IDLE; // set the state of the state machine to start the sampling
gpio_set_drive_capability(yu, GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(yd, GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(xl, GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(xr, GPIO_DRIVE_CAP_3);
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 5 * 1000)); //5ms (expressed as microseconds)
/*Load calibration data*/
xRawTouch[0] = TOUCHCAL_ULX;
yRawTouch[0] = TOUCHCAL_ULY;
xRawTouch[1] = TOUCHCAL_URX;
yRawTouch[1] = TOUCHCAL_URY;
xRawTouch[3] = TOUCHCAL_LLX;
yRawTouch[3] = TOUCHCAL_LLY;
xRawTouch[2] = TOUCHCAL_LRX;
yRawTouch[2] = TOUCHCAL_LRY;
TouchCalculateCalPoints();
}
static void setup_axis(gpio_num_t plus, gpio_num_t minus, gpio_num_t measure, gpio_num_t ignore)
{
// Set GPIOs:
// - Float "ignore" and "measure"
gpio_pad_select_gpio(ignore);
gpio_set_direction(ignore, GPIO_MODE_DISABLE);
gpio_set_pull_mode(ignore, GPIO_FLOATING);
gpio_pad_select_gpio(measure);
gpio_set_direction(measure, GPIO_MODE_DISABLE);
gpio_set_pull_mode(measure, GPIO_FLOATING);
// - Set "plus" to 1, "minus" to 0
gpio_config(&(gpio_config_t) {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = (1ULL << plus) | (1ULL << minus)
});
gpio_set_level(plus, 1);
gpio_set_level(minus, 0);
}
static void setup_adc(gpio_num_t measure)
{
// Init ADC
adc1_channel_t channel = gpio_to_adc[measure];
adc_gpio_init(ADC_UNIT_1, channel);
adc1_config_width(ADC_WIDTH_BIT_10);
adc1_config_channel_atten(channel, ADC_ATTEN_DB_11);
}
static void insert_sort(int16_t array[], uint8_t size) {
uint8_t j;
int16_t save;
for (int i = 1; i < size; i++) {
save = array[i];
for (j = i; j >= 1 && save < array[j - 1]; j--)
array[j] = array[j - 1];
array[j] = save;
}
}
static void ad_touch_handler(void *arg)
{
(void) arg;
uint8_t i;
int16_t samples[NUMSAMPLES];
switch (state) {
case IDLE:
adcX = 0;
adcY = 0;
case SET_X :
setup_axis(yd, yu, xr, xl);
setup_adc(xr);
state = READ_X;
break;
case READ_X:
for (i = 0; i < NUMSAMPLES; i++)
samples[i] = adc1_get_raw(gpio_to_adc[xr]);
insert_sort(samples, NUMSAMPLES);
temp_x = samples[NUMSAMPLES / 2];
case SET_Y :
setup_axis(xl, xr, yd, yu);
setup_adc(yd);
state = READ_Y;
break;
case READ_Y:
for (i = 0; i < NUMSAMPLES; i++)
samples[i] = adc1_get_raw(gpio_to_adc[yd]);
insert_sort(samples, NUMSAMPLES);
temp_y = samples[NUMSAMPLES / 2];
case SET_Z1 :
setup_axis(yu, xl, yd, xr);
setup_adc(yd);
state = READ_Z1;
break;
case READ_Z1:
temp_z1 = adc1_get_raw(gpio_to_adc[yd]);
case SET_Z2 :
setup_axis(yu, xl, xr, yd);
setup_adc(yd);
state = READ_Z2;
break;
case READ_Z2:
temp_z2 = adc1_get_raw(gpio_to_adc[xr]);
if (temp_z1 < TOUCHSCREEN_RESISTIVE_PRESS_THRESHOLD) {
#if CONFIG_LV_TOUCH_XY_SWAP
adcX = temp_y;
adcY = temp_x;
#else
adcX = temp_x;
adcY = temp_y;
#endif
}
else {
adcX = -1;
adcY = -1;
}
state = SET_X;
//printf("x: %d y: %d z: %d\n", adcX, adcY, temp_z1 - temp_z2);
break;
}
return;
}
static int16_t TouchGetRawX(void)
{
int16_t x = adcX;
#if CONFIG_LV_TOUCH_INVERT_X
x = 1023 - x;
#endif
return x;
}
static int16_t TouchGetX(void)
{
int16_t result = TouchGetRawX();
if (result > 0) {
result = (int16_t)((((int32_t)_trC * result) + _trD) >> TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR);
}
printf("x: %d\n", result);
return (result);
}
static int16_t TouchGetRawY(void)
{
int16_t y = adcY;
#if CONFIG_LV_TOUCH_INVERT_Y
y = 1023 - y;
#endif
return y;
}
static int16_t TouchGetY(void)
{
int16_t result = TouchGetRawY();
if (result > 0) {
result = (int16_t)((((int32_t)_trA * result) + (int32_t)_trB) >> TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR);
}
printf("y: %d\n", result);
return (result);
}
/**
* 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 adcraw_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
static int16_t last_x = 0;
static int16_t last_y = 0;
int16_t x, y;
x = TouchGetX();
y = TouchGetY();
if ((x > 0) && (y > 0)) {
data->point.x = x;
data->point.y = y;
last_x = data->point.x;
last_y = data->point.y;
data->state = LV_INDEV_STATE_PR;
}
else {
data->point.x = last_x;
data->point.y = last_y;
data->state = LV_INDEV_STATE_REL;
}
return false;
}
#endif //CONFIG_LV_TOUCH_CONTROLLER_ADCRAW

79
lvgl_touch/adcraw.h Normal file
View file

@ -0,0 +1,79 @@
/**
* @file ADCRAW.h
*/
#ifndef ADCRAW_H
#define ADCRAW_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include "driver/gpio.h"
#include "driver/adc.h"
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#define TOUCHSCREEN_RESISTIVE_PIN_YU CONFIG_LV_TOUCHSCREEN_RESSITIVE_PIN_YU // Y+ any gpio
#define TOUCHSCREEN_RESISTIVE_PIN_YD CONFIG_LV_TOUCHSCREEN_RESISTIVE_PIN_YD // Y- also ADC
#define TOUCHSCREEN_RESISTIVE_PIN_XL CONFIG_LV_TOUCHSCREEN_RESISTIVE_PIN_XL // X- any gpio
#define TOUCHSCREEN_RESISTIVE_PIN_XR CONFIG_LV_TOUCHSCREEN_RESISTIVE_PIN_XR // X+ also ADC
// Default calibration points
#define TOUCHCAL_ULX 29 // Upper Left X
#define TOUCHCAL_ULY 84 // Upper Left Y
#define TOUCHCAL_URX 828 // Upper Right X
#define TOUCHCAL_URY 60 // Upper Right Y
#define TOUCHCAL_LLX 29 // Lower Left X
#define TOUCHCAL_LLY 928 // Lower Left Y
#define TOUCHCAL_LRX 828 // Lower Right X
#define TOUCHCAL_LRY 928 // Lower Right Y
#define TOUCHSCREEN_RESISTIVE_PRESS_THRESHOLD 1023
/*GetMaxX Macro*/
#if CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
#define GetMaxX() (CONFIG_LV_DISPLAY_WIDTH - 1)
#else
#define GetMaxX() (CONFIG_LV_DISPLAY_HEIGHT - 1)
#endif
/*GetMaxY Macro*/
#if CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE
#define GetMaxY() (CONFIG_LV_DISPLAY_HEIGHT - 1)
#else
#define GetMaxY() (CONFIG_LV_DISPLAY_WIDTH - 1)
#endif
#ifndef CONCAT3
#define _CONCAT3(a,b,c) a ## b ## c
#define CONCAT3(a,b,c) _CONCAT3(a,b,c)
#endif
#define GPIO_TO_ADC_ELEMENT(x) [x] = CONCAT3(ADC1_GPIO, x, _CHANNEL)
typedef enum {
IDLE,
SET_X,
SET_Y,
SET_Z1,
SET_Z2,
READ_X,
READ_Y,
READ_Z1,
READ_Z2
} TOUCH_STATES;
void adcraw_init(void);
bool adcraw_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* ADCRAW_H */

4
lvgl_touch/component.mk Normal file
View file

@ -0,0 +1,4 @@
# Touch drivers
COMPONENT_SRCDIRS := .
COMPONENT_ADD_INCLUDEDIRS := .

200
lvgl_touch/ft6x36.c Normal file
View file

@ -0,0 +1,200 @@
/*
* Copyright © 2020 Wolfgang Christl
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the Software), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
* to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <esp_log.h>
#include <driver/i2c.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include <lvgl.h>
#else
#include <lvgl/lvgl.h>
#endif
#include "ft6x36.h"
#include "tp_i2c.h"
#define TAG "FT6X36"
ft6x36_status_t ft6x36_status;
uint8_t current_dev_addr; // set during init
esp_err_t ft6x06_i2c_read8(uint8_t slave_addr, uint8_t register_addr, uint8_t *data_buf) {
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
i2c_master_start(i2c_cmd);
i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(i2c_cmd, register_addr, I2C_MASTER_ACK);
i2c_master_start(i2c_cmd);
i2c_master_write_byte(i2c_cmd, (slave_addr << 1) | I2C_MASTER_READ, true);
i2c_master_read_byte(i2c_cmd, data_buf, I2C_MASTER_NACK);
i2c_master_stop(i2c_cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, i2c_cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(i2c_cmd);
return ret;
}
/**
* @brief Read the FT6x36 gesture ID. Initialize first!
* @param dev_addr: I2C FT6x36 Slave address.
* @retval The gesture ID or 0x00 in case of failure
*/
uint8_t ft6x36_get_gesture_id() {
if (!ft6x36_status.inited) {
ESP_LOGE(TAG, "Init first!");
return 0x00;
}
uint8_t data_buf;
esp_err_t ret;
if ((ret = ft6x06_i2c_read8(current_dev_addr, FT6X36_GEST_ID_REG, &data_buf) != ESP_OK))
ESP_LOGE(TAG, "Error reading from device: %s", esp_err_to_name(ret));
return data_buf;
}
/**
* @brief Initialize for FT6x36 communication via I2C
* @param dev_addr: Device address on communication Bus (I2C slave address of FT6X36).
* @retval None
*/
void ft6x06_init(uint16_t dev_addr) {
if (!ft6x36_status.inited) {
/* I2C master is initialized before calling this function */
#if 0
esp_err_t code = i2c_master_init();
#else
esp_err_t code = ESP_OK;
#endif
if (code != ESP_OK) {
ft6x36_status.inited = false;
ESP_LOGE(TAG, "Error during I2C init %s", esp_err_to_name(code));
} else {
ft6x36_status.inited = true;
current_dev_addr = dev_addr;
uint8_t data_buf;
esp_err_t ret;
ESP_LOGI(TAG, "Found touch panel controller");
if ((ret = ft6x06_i2c_read8(dev_addr, FT6X36_PANEL_ID_REG, &data_buf) != ESP_OK))
ESP_LOGE(TAG, "Error reading from device: %s",
esp_err_to_name(ret)); // Only show error the first time
ESP_LOGI(TAG, "\tDevice ID: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_CHIPSELECT_REG, &data_buf);
ESP_LOGI(TAG, "\tChip ID: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_DEV_MODE_REG, &data_buf);
ESP_LOGI(TAG, "\tDevice mode: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_FIRMWARE_ID_REG, &data_buf);
ESP_LOGI(TAG, "\tFirmware ID: 0x%02x", data_buf);
ft6x06_i2c_read8(dev_addr, FT6X36_RELEASECODE_REG, &data_buf);
ESP_LOGI(TAG, "\tRelease code: 0x%02x", data_buf);
}
}
}
/**
* @brief Get the touch screen X and Y positions values. Ignores multi touch
* @param drv:
* @param data: Store data here
* @retval Always false
*/
bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
uint8_t data_xy[4]; // 2 bytes X | 2 bytes Y
uint8_t touch_pnt_cnt; // Number of detected touch points
static int16_t last_x = 0; // 12bit pixel value
static int16_t last_y = 0; // 12bit pixel value
ft6x06_i2c_read8(current_dev_addr, FT6X36_TD_STAT_REG, &touch_pnt_cnt);
if (touch_pnt_cnt != 1) { // ignore no touch & multi touch
data->point.x = last_x;
data->point.y = last_y;
data->state = LV_INDEV_STATE_REL;
return false;
}
// Read X value
i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
i2c_master_start(i2c_cmd);
i2c_master_write_byte(i2c_cmd, (current_dev_addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(i2c_cmd, FT6X36_P1_XH_REG, I2C_MASTER_ACK);
i2c_master_start(i2c_cmd);
i2c_master_write_byte(i2c_cmd, (current_dev_addr << 1) | I2C_MASTER_READ, true);
i2c_master_read_byte(i2c_cmd, &data_xy[0], I2C_MASTER_ACK); // reads FT6X36_P1_XH_REG
i2c_master_read_byte(i2c_cmd, &data_xy[1], I2C_MASTER_NACK); // reads FT6X36_P1_XL_REG
i2c_master_stop(i2c_cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, i2c_cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(i2c_cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Error getting X coordinates: %s", esp_err_to_name(ret));
data->point.x = last_x;
data->point.y = last_y;
data->state = LV_INDEV_STATE_REL; // no touch detected
return false;
}
// Read Y value
i2c_cmd = i2c_cmd_link_create();
i2c_master_start(i2c_cmd);
i2c_master_write_byte(i2c_cmd, (current_dev_addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(i2c_cmd, FT6X36_P1_YH_REG, I2C_MASTER_ACK);
i2c_master_start(i2c_cmd);
i2c_master_write_byte(i2c_cmd, (current_dev_addr << 1) | I2C_MASTER_READ, true);
i2c_master_read_byte(i2c_cmd, &data_xy[2], I2C_MASTER_ACK); // reads FT6X36_P1_YH_REG
i2c_master_read_byte(i2c_cmd, &data_xy[3], I2C_MASTER_NACK); // reads FT6X36_P1_YL_REG
i2c_master_stop(i2c_cmd);
ret = i2c_master_cmd_begin(I2C_NUM_0, i2c_cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(i2c_cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Error getting Y coordinates: %s", esp_err_to_name(ret));
data->point.x = last_x;
data->point.y = last_y;
data->state = LV_INDEV_STATE_REL; // no touch detected
return false;
}
last_x = ((data_xy[0] & FT6X36_MSB_MASK) << 8) | (data_xy[1] & FT6X36_LSB_MASK);
last_y = ((data_xy[2] & FT6X36_MSB_MASK) << 8) | (data_xy[3] & FT6X36_LSB_MASK);
#if CONFIG_LV_FT6X36_SWAPXY
int16_t swap_buf = last_x;
last_x = last_y;
last_y = swap_buf;
#endif
#if CONFIG_LV_FT6X36_INVERT_X
last_x = LV_HOR_RES - last_x;
#endif
#if CONFIG_LV_FT6X36_INVERT_Y
last_y = LV_VER_RES - last_y;
#endif
data->point.x = last_x;
data->point.y = last_y;
data->state = LV_INDEV_STATE_PR;
ESP_LOGV(TAG, "X=%u Y=%u", data->point.x, data->point.y);
return false;
}

162
lvgl_touch/ft6x36.h Normal file
View file

@ -0,0 +1,162 @@
#ifndef __FT6X06_H
/*
* Copyright © 2020 Wolfgang Christl
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the Software), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
* to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define __FT6X06_H
#include <lvgl/src/lv_hal/lv_hal.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FT6236_I2C_SLAVE_ADDR 0x38
/* Maximum border values of the touchscreen pad that the chip can handle */
#define FT6X36_MAX_WIDTH ((uint16_t)800)
#define FT6X36_MAX_HEIGHT ((uint16_t)480)
/* Max detectable simultaneous touch points */
#define FT6X36_MAX_TOUCH_PNTS 2
/* Register of the current mode */
#define FT6X36_DEV_MODE_REG 0x00
/* Possible modes as of FT6X36_DEV_MODE_REG */
#define FT6X36_DEV_MODE_WORKING 0x00
#define FT6X36_DEV_MODE_FACTORY 0x04
#define FT6X36_DEV_MODE_MASK 0x70
#define FT6X36_DEV_MODE_SHIFT 4
/* Gesture ID register */
#define FT6X36_GEST_ID_REG 0x01
/* Possible values returned by FT6X36_GEST_ID_REG */
#define FT6X36_GEST_ID_NO_GESTURE 0x00
#define FT6X36_GEST_ID_MOVE_UP 0x10
#define FT6X36_GEST_ID_MOVE_RIGHT 0x14
#define FT6X36_GEST_ID_MOVE_DOWN 0x18
#define FT6X36_GEST_ID_MOVE_LEFT 0x1C
#define FT6X36_GEST_ID_ZOOM_IN 0x48
#define FT6X36_GEST_ID_ZOOM_OUT 0x49
/* Status register: stores number of active touch points (0, 1, 2) */
#define FT6X36_TD_STAT_REG 0x02
#define FT6X36_TD_STAT_MASK 0x0F
#define FT6X36_TD_STAT_SHIFT 0x00
/* Touch events */
#define FT6X36_TOUCH_EVT_FLAG_PRESS_DOWN 0x00
#define FT6X36_TOUCH_EVT_FLAG_LIFT_UP 0x01
#define FT6X36_TOUCH_EVT_FLAG_CONTACT 0x02
#define FT6X36_TOUCH_EVT_FLAG_NO_EVENT 0x03
#define FT6X36_TOUCH_EVT_FLAG_SHIFT 6
#define FT6X36_TOUCH_EVT_FLAG_MASK (3 << FT6X36_TOUCH_EVT_FLAG_SHIFT)
#define FT6X36_MSB_MASK 0x0F
#define FT6X36_MSB_SHIFT 0
#define FT6X36_LSB_MASK 0xFF
#define FT6X36_LSB_SHIFT 0
#define FT6X36_P1_XH_REG 0x03
#define FT6X36_P1_XL_REG 0x04
#define FT6X36_P1_YH_REG 0x05
#define FT6X36_P1_YL_REG 0x06
#define FT6X36_P1_WEIGHT_REG 0x07 /* Register reporting touch pressure - read only */
#define FT6X36_TOUCH_WEIGHT_MASK 0xFF
#define FT6X36_TOUCH_WEIGHT_SHIFT 0
#define FT6X36_P1_MISC_REG 0x08 /* Touch area register */
#define FT6X36_TOUCH_AREA_MASK (0x04 << 4) /* Values related to FT6X36_Pn_MISC_REG */
#define FT6X36_TOUCH_AREA_SHIFT 0x04
#define FT6X36_P2_XH_REG 0x09
#define FT6X36_P2_XL_REG 0x0A
#define FT6X36_P2_YH_REG 0x0B
#define FT6X36_P2_YL_REG 0x0C
#define FT6X36_P2_WEIGHT_REG 0x0D
#define FT6X36_P2_MISC_REG 0x0E
/* Threshold for touch detection */
#define FT6X36_TH_GROUP_REG 0x80
#define FT6X36_THRESHOLD_MASK 0xFF /* Values FT6X36_TH_GROUP_REG : threshold related */
#define FT6X36_THRESHOLD_SHIFT 0
#define FT6X36_TH_DIFF_REG 0x85 /* Filter function coefficients */
#define FT6X36_CTRL_REG 0x86 /* Control register */
#define FT6X36_CTRL_KEEP_ACTIVE_MODE 0x00 /* Will keep the Active mode when there is no touching */
#define FT6X36_CTRL_KEEP_AUTO_SWITCH_MONITOR_MODE 0x01 /* Switching from Active mode to Monitor mode automatically when there is no touching */
#define FT6X36_TIME_ENTER_MONITOR_REG 0x87 /* The time period of switching from Active mode to Monitor mode when there is no touching */
#define FT6X36_PERIOD_ACTIVE_REG 0x88 /* Report rate in Active mode */
#define FT6X36_PERIOD_MONITOR_REG 0x89 /* Report rate in Monitor mode */
#define FT6X36_RADIAN_VALUE_REG 0x91 /* The value of the minimum allowed angle while Rotating gesture mode */
#define FT6X36_OFFSET_LEFT_RIGHT_REG 0x92 /* Maximum offset while Moving Left and Moving Right gesture */
#define FT6X36_OFFSET_UP_DOWN_REG 0x93 /* Maximum offset while Moving Up and Moving Down gesture */
#define FT6X36_DISTANCE_LEFT_RIGHT_REG 0x94 /* Minimum distance while Moving Left and Moving Right gesture */
#define FT6X36_DISTANCE_UP_DOWN_REG 0x95 /* Minimum distance while Moving Up and Moving Down gesture */
#define FT6X36_LIB_VER_H_REG 0xA1 /* High 8-bit of LIB Version info */
#define FT6X36_LIB_VER_L_REG 0xA2 /* Low 8-bit of LIB Version info */
#define FT6X36_CHIPSELECT_REG 0xA3 /* 0x36 for ft6236; 0x06 for ft6206 */
#define FT6X36_POWER_MODE_REG 0xA5
#define FT6X36_FIRMWARE_ID_REG 0xA6
#define FT6X36_RELEASECODE_REG 0xAF
#define FT6X36_PANEL_ID_REG 0xA8
#define FT6X36_OPMODE_REG 0xBC
typedef struct {
bool inited;
} ft6x36_status_t;
/**
* @brief Initialize for FT6x36 communication via I2C
* @param dev_addr: Device address on communication Bus (I2C slave address of FT6X36).
* @retval None
*/
void ft6x06_init(uint16_t dev_addr);
uint8_t ft6x36_get_gesture_id();
/**
* @brief Get the touch screen X and Y positions values. Ignores multi touch
* @param drv:
* @param data: Store data here
* @retval Always false
*/
bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data);
#ifdef __cplusplus
}
#endif
#endif /* __FT6X06_H */

181
lvgl_touch/ra8875_touch.c Normal file
View file

@ -0,0 +1,181 @@
/**
* @file RA8875_TOUCH.c
*/
/*********************
* INCLUDES
*********************/
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <stddef.h>
#include "ra8875_touch.h"
#include "../lvgl_tft/ra8875.h"
#ifndef CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875
#error "Display controller must be RA8875"
#endif
/*********************
* DEFINES
*********************/
#define DEBUG false
#define TAG "RA8875-Touch"
#define DIV_ROUND_UP(n, d) (((n)+(d)-1)/(d))
#define INTC2_TP_INT (0x04)
#define TPCR0_ADC_TIMING ((CONFIG_LV_TOUCH_RA8875_SAMPLE_TIME << 4) | CONFIG_LV_TOUCH_RA8875_ADC_CLOCK)
#if LVGL_TOUCH_RA8875_WAKEUP_ENABLE
#define TPCR0_VAL (0x08 | TPCR0_ADC_TIMING)
#else
#define TPCR0_VAL (TPCR0_ADC_TIMING)
#endif
#if LVGL_TOUCH_RA8875_EXTERNAL_VREF
#if LVGL_TOUCH_RA8875_DEBOUNCE_ENABLE
#define TPCR1_VAL (0x24)
#else
#define TPCR1_VAL (0x20)
#endif
#else
#if LVGL_TOUCH_RA8875_DEBOUNCE_ENABLE
#define TPCR1_VAL (0x04)
#else
#define TPCR1_VAL (0x00)
#endif
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void ra8875_corr(int * x, int * y);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void ra8875_touch_init(void)
{
struct {
uint8_t cmd; // Register address of command
uint8_t data; // Value to write to register
} init_cmds[] = {
{RA8875_REG_TPCR0, TPCR0_VAL}, // Touch Panel Control Register 0 (TPCR0)
{RA8875_REG_TPCR1, TPCR1_VAL}, // Touch Panel Control Register 1 (TPCR1)
};
#define INIT_CMDS_SIZE (sizeof(init_cmds)/sizeof(init_cmds[0]))
ESP_LOGI(TAG, "Initializing RA8875 Touch...");
// Send all the commands
for (unsigned int i = 0; i < INIT_CMDS_SIZE; i++) {
ra8875_write_cmd(init_cmds[i].cmd, init_cmds[i].data);
}
ra8875_touch_enable(true);
}
void ra8875_touch_enable(bool enable)
{
ESP_LOGI(TAG, "%s touch.", enable ? "Enabling" : "Disabling");
uint8_t val = enable ? (0x80 | TPCR0_VAL) : (TPCR0_VAL);
ra8875_write_cmd(RA8875_REG_TPCR0, val);
}
/**
* Get the current position and state of the touchscreen
* @param data store the read data here
* @return false: because no more data to be read
*/
bool ra8875_touch_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
static int x = 0;
static int y = 0;
int intr = ra8875_read_cmd(RA8875_REG_INTC2); // Interrupt Control Register2 (INTC2)
data->state = (intr & INTC2_TP_INT) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
if (data->state == LV_INDEV_STATE_PR) {
x = ra8875_read_cmd(RA8875_REG_TPXH); // Touch Panel X High Byte Data Register (TPXH)
y = ra8875_read_cmd(RA8875_REG_TPYH); // Touch Panel Y High Byte Data Register (TPYH)
int xy = ra8875_read_cmd(RA8875_REG_TPXYL); // Touch Panel X/Y Low Byte Data Register (TPXYL)
x = (x << 2) | (xy & 0x03);
y = (y << 2) | ((xy >> 2) & 0x03);
#if DEBUG
ESP_LOGI(TAG, "Touch Poll Raw: %d,%d", x, y);
#endif
// Convert to display coordinates
ra8875_corr(&x, &y);
// Clear interrupt
ra8875_write_cmd(RA8875_REG_INTC2, INTC2_TP_INT); // Interrupt Control Register2 (INTC2)
}
data->point.x = x;
data->point.y = y;
#if DEBUG
ESP_LOGI(TAG, "Touch Poll - Event: %d; %d,%d", data->state, data->point.x, data->point.y);
#endif
return false;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void ra8875_corr(int * x, int * y)
{
#if RA8875_XY_SWAP != 0
int tmp = *x;
*x = *y;
*y = tmp;
#endif
if ((*x) <= RA8875_X_MIN) {
(*x) = 0;
} else if ((*x) >= RA8875_X_MAX) {
(*x) = LV_HOR_RES-1;
} else {
(*x) = (((*x) - RA8875_X_MIN) * (LV_HOR_RES-1)) / (RA8875_X_MAX - RA8875_X_MIN);
}
if ((*y) <= RA8875_Y_MIN) {
(*y) = 0;
} else if ((*y) >= RA8875_Y_MAX) {
(*y) = LV_VER_RES-1;
} else {
(*y) = (((*y) - RA8875_Y_MIN) * (LV_VER_RES-1)) / (RA8875_Y_MAX - RA8875_Y_MIN);
}
#if RA8875_X_INV != 0
(*x) = (LV_HOR_RES-1) - (*x);
#endif
#if RA8875_Y_INV != 0
(*y) = (LV_VER_RES-1) - (*y);
#endif
}

56
lvgl_touch/ra8875_touch.h Normal file
View file

@ -0,0 +1,56 @@
/**
* @file RA8875_TOUCH.h
*/
#ifndef RA8875X_TOUCH__H
#define RA8875X_TOUCH__H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdint.h>
#include <stdbool.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
/*********************
* DEFINES
*********************/
#define RA8875_X_MIN CONFIG_LV_TOUCH_X_MIN
#define RA8875_Y_MIN CONFIG_LV_TOUCH_Y_MIN
#define RA8875_X_MAX CONFIG_LV_TOUCH_X_MAX
#define RA8875_Y_MAX CONFIG_LV_TOUCH_Y_MAX
#define RA8875_X_INV CONFIG_LV_TOUCH_INVERT_X
#define RA8875_Y_INV CONFIG_LV_TOUCH_INVERT_Y
#define RA8875_XY_SWAP CONFIG_LV_TOUCH_XY_SWAP
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void ra8875_touch_init(void);
void ra8875_touch_enable(bool enable);
bool ra8875_touch_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* RA8875_TOUCH__H */

242
lvgl_touch/stmpe610.c Normal file
View file

@ -0,0 +1,242 @@
/**
* @file STMPE610.c
*/
/*********************
* INCLUDES
*********************/
#include "stmpe610.h"
#include "esp_system.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "tp_spi.h"
#include <stddef.h>
/*********************
* DEFINES
*********************/
#define TAG "STMPE610"
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void write_8bit_reg(uint8_t reg, uint8_t val);
static uint16_t read_16bit_reg(uint8_t reg);
static uint8_t read_8bit_reg(uint8_t reg);
static void read_data(int16_t *x, int16_t *y, uint8_t *z);
static bool buffer_empty();
static void adjust_data(int16_t * x, int16_t * y);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Initialize the STMPE610
*/
void stmpe610_init(void)
{
uint8_t u8;
uint16_t u16;
ESP_LOGI(TAG, "Initialization.");
// Get the initial SPI configuration
//u8 = read_8bit_reg(STMPE_SPI_CFG);
//ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8);
// Attempt a software reset
write_8bit_reg(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET);
vTaskDelay(10 / portTICK_RATE_MS);
// Reset the SPI configuration, making sure auto-increment is set
u8 = read_8bit_reg(STMPE_SPI_CFG);
write_8bit_reg(STMPE_SPI_CFG, u8 | STMPE_SPI_CFG_AA);
u8 = read_8bit_reg(STMPE_SPI_CFG);
ESP_LOGI(TAG, "SPI_CFG = 0x%x", u8);
// Verify SPI communication
u16 = read_16bit_reg(STMPE_CHIP_ID);
if (u16 != 0x811) {
ESP_LOGE(TAG, "Incorrect version: 0x%x", u16);
}
write_8bit_reg(STMPE_SYS_CTRL2, 0x00); // Disable clocks
write_8bit_reg(STMPE_TSC_CTRL, 0); // Disable to allow writing
write_8bit_reg(STMPE_TSC_CTRL,
STEMP_TSC_CTRL_TRACK_0 |
STMPE_TSC_CTRL_XYZ |
STMPE_TSC_CTRL_EN);
write_8bit_reg(STMPE_TSC_CFG, STMPE_TSC_CFG_4SAMPLE |
STMPE_TSC_CFG_DELAY_1MS |
STMPE_TSC_CFG_SETTLE_1MS);
write_8bit_reg(STMPE_TSC_FRACTION_Z, 0x7);
write_8bit_reg(STMPE_TSC_I_DRIVE, STMPE_TSC_I_DRIVE_50MA);
write_8bit_reg(STMPE_SYS_CTRL2, 0x04); // GPIO clock off, TSC clock on, ADC clock on
write_8bit_reg(STMPE_ADC_CTRL1, STMPE_ADC_CTRL1_12BIT | STMPE_ADC_CTRL1_80CLK);
write_8bit_reg(STMPE_ADC_CTRL2, STMPE_ADC_CTRL2_3_25MHZ);
write_8bit_reg(STMPE_GPIO_ALT_FUNCT, 0x00); // Disable GPIO
write_8bit_reg(STMPE_FIFO_TH, 1); // Set FIFO threshold
write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET); // Assert FIFO reset
write_8bit_reg(STMPE_FIFO_STA, 0); // Deassert FIFO reset
write_8bit_reg(STMPE_INT_EN, 0x00); // No interrupts
write_8bit_reg(STMPE_INT_STA, 0xFF); // reset all ints
}
/**
* 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 stmpe610_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 = true;
int c = 0;
int16_t x = 0;
int16_t y = 0;
uint8_t z;
if ((read_8bit_reg(STMPE_TSC_CTRL) & STMPE_TSC_TOUCHED) == STMPE_TSC_TOUCHED) {
// Making sure that we read all data and return the latest point
while (!buffer_empty()) {
read_data(&x, &y, &z);
c++;
}
if (c > 0) {
//ESP_LOGI(TAG, "%d: %d %d %d", c, x, y, z);
adjust_data(&x, &y);
last_x = x;
last_y = y;
//ESP_LOGI(TAG, " ==> %d %d", x, y);
}
z = read_8bit_reg(STMPE_INT_STA); // Clear interrupts
z = read_8bit_reg(STMPE_FIFO_STA);
if ((z & STMPE_FIFO_STA_OFLOW) == STMPE_FIFO_STA_OFLOW) {
// Clear the FIFO if we discover an overflow
write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET);
write_8bit_reg(STMPE_FIFO_STA, 0); // unreset
ESP_LOGE(TAG, "Fifo overflow");
}
}
if (c == 0) {
x = last_x;
y = last_y;
valid = false;
}
data->point.x = (int16_t) x;
data->point.y = (int16_t) y;
data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR;
return false;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void write_8bit_reg(uint8_t reg, uint8_t val)
{
uint8_t data_send[2];
data_send[0] = reg;
data_send[1] = val;
tp_spi_write_reg(data_send, 2);
}
static uint16_t read_16bit_reg(uint8_t reg)
{
uint8_t data_recv[2];
tp_spi_read_reg(0x80 | reg, data_recv, 2);
return data_recv[0] << 8 | data_recv[1];
}
static uint8_t read_8bit_reg(uint8_t reg)
{
uint8_t data_recv;
tp_spi_read_reg(0x80 | reg, &data_recv, 1);
return data_recv;
}
static void read_data(int16_t *x, int16_t *y, uint8_t *z)
{
*x = read_16bit_reg(STMPE_TSC_DATA_X);
*y = read_16bit_reg(STMPE_TSC_DATA_Y);
*z = read_8bit_reg(STMPE_TSC_DATA_Z);
}
static bool buffer_empty()
{
return ((read_8bit_reg(STMPE_FIFO_STA) & STMPE_FIFO_STA_EMPTY) == STMPE_FIFO_STA_EMPTY);
}
static void adjust_data(int16_t * x, int16_t * y)
{
#if STMPE610_XY_SWAP != 0
int16_t swap_tmp;
swap_tmp = *x;
*x = *y;
*y = swap_tmp;
#endif
if((*x) > STMPE610_X_MIN)(*x) -= STMPE610_X_MIN;
else(*x) = 0;
if((*y) > STMPE610_Y_MIN)(*y) -= STMPE610_Y_MIN;
else(*y) = 0;
(*x) = (uint32_t)((uint32_t)(*x) * LV_HOR_RES) /
(STMPE610_X_MAX - STMPE610_X_MIN);
(*y) = (uint32_t)((uint32_t)(*y) * LV_VER_RES) /
(STMPE610_Y_MAX - STMPE610_Y_MIN);
#if STMPE610_X_INV != 0
(*x) = LV_HOR_RES - (*x);
#endif
#if STMPE610_Y_INV != 0
(*y) = LV_VER_RES - (*y);
#endif
}

185
lvgl_touch/stmpe610.h Normal file
View file

@ -0,0 +1,185 @@
/**
* @file STMPE610.h
*/
#ifndef STMPE610_H
#define STMPE610_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdint.h>
#include <stdbool.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
/*********************
* DEFINES
*********************/
/** 16-bit Chip Version **/
#define STMPE_CHIP_ID 0x00
/** Reset Control **/
#define STMPE_SYS_CTRL1 0x03
#define STMPE_SYS_CTRL1_RESET 0x02
/** Clock Contrl **/
#define STMPE_SYS_CTRL2 0x04
/** SPI Config **/
#define STMPE_SPI_CFG 0x08
#define STMPE_SPI_CFG_MODE0 0x00
#define STMPE_SPI_CFG_MODE1 0x01
#define STMPE_SPI_CFG_MODE2 0x02
#define STMPE_SPI_CFG_MODE3 0x03
#define STMPE_SPI_CFG_AA 0x04
/** Touchscreen controller setup **/
#define STMPE_TSC_CTRL 0x40
#define STMPE_TSC_CTRL_EN 0x01
#define STMPE_TSC_CTRL_XYZ 0x00
#define STMPE_TSC_CTRL_XY 0x02
#define STEMP_TSC_CTRL_TRACK_0 0x00
#define STEMP_TSC_CTRL_TRACK_4 0x10
#define STEMP_TSC_CTRL_TRACK_8 0x20
#define STEMP_TSC_CTRL_TRACK_16 0x30
#define STEMP_TSC_CTRL_TRACK_32 0x40
#define STEMP_TSC_CTRL_TRACK_64 0x50
#define STEMP_TSC_CTRL_TRACK_92 0x60
#define STEMP_TSC_CTRL_TRACK_127 0x70
#define STMPE_TSC_TOUCHED 0x80
/** Interrupt control **/
#define STMPE_INT_CTRL 0x09
#define STMPE_INT_CTRL_POL_HIGH 0x04
#define STMPE_INT_CTRL_POL_LOW 0x00
#define STMPE_INT_CTRL_EDGE 0x02
#define STMPE_INT_CTRL_LEVEL 0x00
#define STMPE_INT_CTRL_ENABLE 0x01
#define STMPE_INT_CTRL_DISABLE 0x00
/** Interrupt enable **/
#define STMPE_INT_EN 0x0A
#define STMPE_INT_EN_TOUCHDET 0x01
#define STMPE_INT_EN_FIFOTH 0x02
#define STMPE_INT_EN_FIFOOF 0x04
#define STMPE_INT_EN_FIFOFULL 0x08
#define STMPE_INT_EN_FIFOEMPTY 0x10
#define STMPE_INT_EN_ADC 0x40
#define STMPE_INT_EN_GPIO 0x80
/** Interrupt status **/
#define STMPE_INT_STA 0x0B
#define STMPE_INT_STA_TOUCHDET 0x01
/** ADC control **/
#define STMPE_ADC_CTRL1 0x20
#define STMPE_ADC_CTRL1_INT 0x00
#define STMPE_ADC_CTRL1_EXT 0x02
#define STMPE_ADC_CTRL1_12BIT 0x08
#define STMPE_ADC_CTRL1_10BIT 0x00
#define STMPE_ADC_CTRL1_36CLK 0x00
#define STMPE_ADC_CTRL1_44CLK 0x10
#define STMPE_ADC_CTRL1_56CLK 0x20
#define STMPE_ADC_CTRL1_64CLK 0x30
#define STMPE_ADC_CTRL1_80CLK 0x40
#define STMPE_ADC_CTRL1_96CLK 0x50
#define STMPE_ADC_CTRL1_124CLK 0x60
/** ADC control **/
#define STMPE_ADC_CTRL2 0x21
#define STMPE_ADC_CTRL2_1_625MHZ 0x00
#define STMPE_ADC_CTRL2_3_25MHZ 0x01
#define STMPE_ADC_CTRL2_6_5MHZ 0x02
/** Touchscreen controller configuration **/
#define STMPE_TSC_CFG 0x41
#define STMPE_TSC_CFG_1SAMPLE 0x00
#define STMPE_TSC_CFG_2SAMPLE 0x40
#define STMPE_TSC_CFG_4SAMPLE 0x80
#define STMPE_TSC_CFG_8SAMPLE 0xC0
#define STMPE_TSC_CFG_DELAY_10US 0x00
#define STMPE_TSC_CFG_DELAY_50US 0x08
#define STMPE_TSC_CFG_DELAY_100US 0x10
#define STMPE_TSC_CFG_DELAY_500US 0x18
#define STMPE_TSC_CFG_DELAY_1MS 0x20
#define STMPE_TSC_CFG_DELAY_5MS 0x28
#define STMPE_TSC_CFG_DELAY_10MS 0x30
#define STMPE_TSC_CFG_DELAY_50MS 0x38
#define STMPE_TSC_CFG_SETTLE_10US 0x00
#define STMPE_TSC_CFG_SETTLE_100US 0x01
#define STMPE_TSC_CFG_SETTLE_500US 0x02
#define STMPE_TSC_CFG_SETTLE_1MS 0x03
#define STMPE_TSC_CFG_SETTLE_5MS 0x04
#define STMPE_TSC_CFG_SETTLE_10MS 0x05
#define STMPE_TSC_CFG_SETTLE_50MS 0x06
#define STMPE_TSC_CFG_SETTLE_100MS 0x07
/** FIFO level to generate interrupt **/
#define STMPE_FIFO_TH 0x4A
/** Current filled level of FIFO **/
#define STMPE_FIFO_SIZE 0x4C
/** Current status of FIFO **/
#define STMPE_FIFO_STA 0x4B
#define STMPE_FIFO_STA_RESET 0x01
#define STMPE_FIFO_STA_OFLOW 0x80
#define STMPE_FIFO_STA_FULL 0x40
#define STMPE_FIFO_STA_EMPTY 0x20
#define STMPE_FIFO_STA_THTRIG 0x10
/** Touchscreen controller drive I **/
#define STMPE_TSC_I_DRIVE 0x58
#define STMPE_TSC_I_DRIVE_20MA 0x00
#define STMPE_TSC_I_DRIVE_50MA 0x01
/** Data port for TSC data address **/
#define STMPE_TSC_DATA_X 0x4D
#define STMPE_TSC_DATA_Y 0x4F
#define STMPE_TSC_DATA_Z 0x51
#define STMPE_TSC_FRACTION_Z 0x56
/** GPIO **/
#define STMPE_GPIO_SET_PIN 0x10
#define STMPE_GPIO_CLR_PIN 0x11
#define STMPE_GPIO_DIR 0x13
#define STMPE_GPIO_ALT_FUNCT 0x17
/** Calibration Constants **/
#define STMPE610_X_MIN CONFIG_LV_TOUCH_X_MIN
#define STMPE610_Y_MIN CONFIG_LV_TOUCH_Y_MIN
#define STMPE610_X_MAX CONFIG_LV_TOUCH_X_MAX
#define STMPE610_Y_MAX CONFIG_LV_TOUCH_Y_MAX
#define STMPE610_XY_SWAP CONFIG_LV_TOUCH_XY_SWAP
#define STMPE610_X_INV CONFIG_LV_TOUCH_INVERT_X
#define STMPE610_Y_INV CONFIG_LV_TOUCH_INVERT_Y
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void stmpe610_init(void);
bool stmpe610_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* STMPE610_H */

47
lvgl_touch/touch_driver.c Normal file
View file

@ -0,0 +1,47 @@
/**
* @file touch_driver.c
*/
#include "touch_driver.h"
#include "tp_spi.h"
#include "tp_i2c.h"
void touch_driver_init(void)
{
#if defined (CONFIG_LV_TOUCH_CONTROLLER_XPT2046)
xpt2046_init();
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
ft6x06_init(FT6236_I2C_SLAVE_ADDR);
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
stmpe610_init();
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_ADCRAW)
adcraw_init();
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
/* nothing to do */
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875)
ra8875_touch_init();
#endif
}
bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
bool res = false;
#if defined (CONFIG_LV_TOUCH_CONTROLLER_XPT2046)
res = xpt2046_read(drv, data);
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
res = ft6x36_read(drv, data);
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
res = stmpe610_read(drv, data);
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_ADCRAW)
res = adcraw_read(drv, data);
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
res = FT81x_read(drv, data);
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875)
res = ra8875_touch_read(drv, data);
#endif
return res;
}

52
lvgl_touch/touch_driver.h Normal file
View file

@ -0,0 +1,52 @@
/**
* @file touch_driver.h
*/
#ifndef TOUCH_DRIVER_H
#define TOUCH_DRIVER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdint.h>
#include <stdbool.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#if defined (CONFIG_LV_TOUCH_CONTROLLER_XPT2046)
#include "xpt2046.h"
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
#include "ft6x36.h"
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
#include "stmpe610.h"
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_ADCRAW)
#include "adcraw.h"
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X)
#include "FT81x.h"
#elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875)
#include "ra8875_touch.h"
#endif
/*********************
* DEFINES
*********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void touch_driver_init(void);
bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* TOUCH_DRIVER_H */

43
lvgl_touch/tp_i2c.c Normal file
View file

@ -0,0 +1,43 @@
/*
* Copyright © 2020 Wolfgang Christl
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the Software), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
* to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <driver/i2c.h>
#include <esp_log.h>
#define I2C_MASTER_FREQ_HZ 100000 /* 100kHz*/
#define I2C_MASTER_TX_BUF_DISABLE 0 /* I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /* I2C master doesn't need buffer */
/**
* @brief ESP32 I2C init as master
* @ret ESP32 error code
*/
esp_err_t i2c_master_init(void) {
int i2c_master_port = I2C_NUM_0;
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = CONFIG_LV_TOUCH_I2C_SDA;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = CONFIG_LV_TOUCH_I2C_SCL;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
i2c_param_config(i2c_master_port, &conf);
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

36
lvgl_touch/tp_i2c.h Normal file
View file

@ -0,0 +1,36 @@
/*
* Copyright © 2020 Wolfgang Christl
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the Software), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
* to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __TS_H
#define __TS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
esp_err_t i2c_master_init(void);
#ifdef __cplusplus
}
#endif
#endif /* __TS_H */

109
lvgl_touch/tp_spi.c Normal file
View file

@ -0,0 +1,109 @@
/**
* @file tp_spi.c
*
*/
/*********************
* INCLUDES
*********************/
#include "tp_spi.h"
#include "touch_driver.h"
#include "esp_system.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include <string.h>
#include "../lvgl_helpers.h"
#include "../lvgl_spi_conf.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static spi_device_handle_t spi;
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void tp_spi_add_device_config(spi_host_device_t host, spi_device_interface_config_t *devcfg)
{
esp_err_t ret=spi_bus_add_device(host, devcfg, &spi);
assert(ret==ESP_OK);
}
void tp_spi_add_device(spi_host_device_t host)
{
spi_device_interface_config_t devcfg={
.clock_speed_hz = SPI_TOUCH_CLOCK_SPEED_HZ,
.mode = SPI_TOUCH_SPI_MODE,
.spics_io_num=TP_SPI_CS, //CS pin
.queue_size=1,
.pre_cb=NULL,
.post_cb=NULL,
.command_bits = 8,
.address_bits = 0,
.dummy_bits = 0,
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_DUMMY,
};
//Attach the Touch controller to the SPI bus
tp_spi_add_device_config(host, &devcfg);
}
void tp_spi_xchg(uint8_t* data_send, uint8_t* data_recv, uint8_t byte_count)
{
spi_transaction_t t = {
.length = byte_count * 8, // SPI transaction length is in bits
.tx_buffer = data_send,
.rx_buffer = data_recv};
esp_err_t ret = spi_device_transmit(spi, &t);
assert(ret == ESP_OK);
}
void tp_spi_write_reg(uint8_t* data, uint8_t byte_count)
{
spi_transaction_t t = {
.length = byte_count * 8,
.tx_buffer = data,
.flags = 0
};
esp_err_t ret = spi_device_transmit(spi, &t);
assert(ret == ESP_OK);
}
void tp_spi_read_reg(uint8_t reg, uint8_t* data, uint8_t byte_count)
{
spi_transaction_t t = {
.length = (byte_count + sizeof(reg)) * 8,
.rxlength = byte_count * 8,
.cmd = reg,
.rx_buffer = data,
.flags = 0
};
// Read - send first byte as command
esp_err_t ret = spi_device_transmit(spi, &t);
assert(ret == ESP_OK);
}
/**********************
* STATIC FUNCTIONS
**********************/

45
lvgl_touch/tp_spi.h Normal file
View file

@ -0,0 +1,45 @@
/**
* @file tp_spi.h
*
*/
#ifndef TP_SPI_H
#define TP_SPI_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdint.h>
#include <driver/spi_master.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void tp_spi_add_device(spi_host_device_t host);
void tp_spi_add_device_config(spi_host_device_t host, spi_device_interface_config_t *config);
void tp_spi_xchg(uint8_t* data_send, uint8_t* data_recv, uint8_t byte_count);
void tp_spi_write_reg(uint8_t* data, uint8_t byte_count);
void tp_spi_read_reg(uint8_t reg, uint8_t* data, uint8_t byte_count);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*TP_SPI_H*/

180
lvgl_touch/xpt2046.c Normal file
View file

@ -0,0 +1,180 @@
/**
* @file XPT2046.c
*
*/
/*********************
* INCLUDES
*********************/
#include "xpt2046.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "tp_spi.h"
#include <stddef.h>
/*********************
* DEFINES
*********************/
#define TAG "XPT2046"
#define CMD_X_READ 0b10010000
#define CMD_Y_READ 0b11010000
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void xpt2046_corr(int16_t * x, int16_t * y);
static void xpt2046_avg(int16_t * x, int16_t * y);
/**********************
* 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)
{
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_LOGI(TAG, "XPT2046 Initialization");
esp_err_t ret = gpio_config(&irq_config);
assert(ret == ESP_OK);
}
/**
* 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 = true;
int16_t x = 0;
int16_t y = 0;
uint8_t irq = gpio_get_level(XPT2046_IRQ);
if (irq == 0) {
uint8_t data[2];
tp_spi_read_reg(CMD_X_READ, data, 2);
x = (data[0] << 8) | data[1];
tp_spi_read_reg(CMD_Y_READ, data, 2);
y = (data[0] << 8) | data[1];
ESP_LOGI(TAG, "P(%d,%d)", x, y);
/*Normalize Data back to 12-bits*/
x = x >> 4;
y = y >> 4;
ESP_LOGI(TAG, "P_norm(%d,%d)", x, y);
xpt2046_corr(&x, &y);
xpt2046_avg(&x, &y);
last_x = x;
last_y = y;
ESP_LOGI(TAG, "x = %d, y = %d", x, y);
} else {
x = last_x;
y = last_y;
avg_last = 0;
valid = false;
}
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 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;
}

57
lvgl_touch/xpt2046.h Normal file
View file

@ -0,0 +1,57 @@
/**
* @file XPT2046.h
*
*/
#ifndef XPT2046_H
#define XPT2046_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdint.h>
#include <stdbool.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
/*********************
* DEFINES
*********************/
#define XPT2046_IRQ CONFIG_LV_TOUCH_PIN_IRQ
#define XPT2046_AVG 4
#define XPT2046_X_MIN CONFIG_LV_TOUCH_X_MIN
#define XPT2046_Y_MIN CONFIG_LV_TOUCH_Y_MIN
#define XPT2046_X_MAX CONFIG_LV_TOUCH_X_MAX
#define XPT2046_Y_MAX CONFIG_LV_TOUCH_Y_MAX
#define XPT2046_X_INV CONFIG_LV_TOUCH_INVERT_X
#define XPT2046_Y_INV CONFIG_LV_TOUCH_INVERT_Y
#define XPT2046_XY_SWAP CONFIG_LV_TOUCH_XY_SWAP
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void xpt2046_init(void);
bool xpt2046_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* XPT2046_H */