#1 Cleanup and add L58 as driver in this component
This commit is contained in:
parent
c55e32a9d4
commit
a66706d139
12 changed files with 451 additions and 237 deletions
316
lvgl_touch/L58/L58Touch.cpp
Normal file
316
lvgl_touch/L58/L58Touch.cpp
Normal file
|
@ -0,0 +1,316 @@
|
|||
// This is the first experimental Touch component for the LILYGO EPD47 touch overlay
|
||||
// Controller: L58 -> https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/files/6059098/L58.V1.0.pdf
|
||||
// Note: Rotation is only working for certain angles (0 works alright, 2 also) Others still need to be corrected
|
||||
#include "L58Touch.h"
|
||||
|
||||
#define CONFIG_L58_DEBUG 0
|
||||
|
||||
L58Touch *L58Touch::_instance = nullptr;
|
||||
static const char *TAG = "i2c-touch";
|
||||
|
||||
L58Touch::L58Touch(int8_t intPin)
|
||||
{
|
||||
_instance = this;
|
||||
printf("I2C sda:%d scl:%d int:%d\n\n",
|
||||
CONFIG_LV_TOUCH_I2C_SDA, CONFIG_LV_TOUCH_I2C_SCL, intPin);
|
||||
i2c_config_t conf;
|
||||
conf.mode = I2C_MODE_MASTER;
|
||||
conf.sda_io_num = (gpio_num_t)CONFIG_LV_TOUCH_I2C_SDA;
|
||||
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.scl_io_num = (gpio_num_t)CONFIG_LV_TOUCH_I2C_SCL;
|
||||
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||
conf.master.clk_speed = 50000;
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0)
|
||||
// !< Optional, you can use I2C_SCLK_SRC_FLAG_* flags to choose i2c source clock here.
|
||||
conf.clk_flags = 0;
|
||||
#endif
|
||||
|
||||
i2c_param_config(I2C_NUM_0, &conf);
|
||||
esp_err_t i2c_driver = i2c_driver_install(I2C_NUM_0, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
||||
if (i2c_driver == ESP_OK) {
|
||||
printf("i2c_driver started correctly\n");
|
||||
} else {
|
||||
printf("i2c_driver error: %d\n", i2c_driver);
|
||||
}
|
||||
_intPin = intPin;
|
||||
}
|
||||
|
||||
// Destructor does nothing for now
|
||||
L58Touch::~L58Touch()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool L58Touch::begin(uint16_t width, uint16_t height)
|
||||
{
|
||||
_touch_width = width;
|
||||
_touch_height = height;
|
||||
if (width == 0 || height ==0) {
|
||||
ESP_LOGE(TAG,"begin(uint8_t threshold, uint16_t width, uint16_t height) did not receive the width / height so touch cannot be rotation aware");
|
||||
}
|
||||
|
||||
// INT pin triggers the callback function on the Falling edge of the GPIO
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_INTR_POSEDGE;
|
||||
io_conf.pin_bit_mask = 1ULL<< CONFIG_LV_TOUCH_INT;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pull_down_en = (gpio_pulldown_t) 0; // disable pull-down mode
|
||||
io_conf.pull_up_en = (gpio_pullup_t) 1; // pull-up mode
|
||||
gpio_config(&io_conf);
|
||||
/* INT gpio is not declared as an interrupt PIN in this touch version since we cannot do
|
||||
blocking functions in LVGL:
|
||||
*/
|
||||
uint8_t buf[2] = {0xD1, 0X06};
|
||||
writeData(buf, sizeof(buf));
|
||||
return true;
|
||||
}
|
||||
|
||||
void L58Touch::registerTouchHandler(void (*fn)(TPoint point, TEvent e))
|
||||
{
|
||||
_touchHandler = fn;
|
||||
if (CONFIG_L58_DEBUG) printf("Touch handler function registered\n");
|
||||
}
|
||||
|
||||
TPoint L58Touch::loop()
|
||||
{
|
||||
_point = processTouch();
|
||||
return _point;
|
||||
}
|
||||
|
||||
TPoint L58Touch::processTouch()
|
||||
{
|
||||
TPoint point;
|
||||
point.x = lastX;
|
||||
point.y = lastY;
|
||||
point.event = lastEvent;
|
||||
|
||||
if (gpio_get_level((gpio_num_t)CONFIG_LV_TOUCH_INT) == 0) {
|
||||
TPoint point = scanPoint();
|
||||
lastX = point.x;
|
||||
lastY = point.y;
|
||||
lastEvent = point.event;
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
uint8_t L58Touch::read8(uint8_t regName) {
|
||||
uint8_t buf;
|
||||
readRegister8(regName, &buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
TPoint L58Touch::scanPoint()
|
||||
{
|
||||
TPoint point{0,0,0};
|
||||
uint8_t pointIdx = 0;
|
||||
uint8_t buffer[40] = {0};
|
||||
uint32_t sumL = 0, sumH = 0;
|
||||
|
||||
buffer[0] = 0xD0;
|
||||
buffer[1] = 0x00;
|
||||
readBytes(buffer, 7);
|
||||
|
||||
if (buffer[0] == 0xAB) {
|
||||
clearFlags();
|
||||
return point;
|
||||
}
|
||||
|
||||
pointIdx = buffer[5] & 0xF;
|
||||
|
||||
if (pointIdx == 1) {
|
||||
buffer[5] = 0xD0;
|
||||
buffer[6] = 0x07;
|
||||
readBytes( &buffer[5], 2);
|
||||
sumL = buffer[5] << 8 | buffer [6];
|
||||
|
||||
} else if (pointIdx > 1) {
|
||||
buffer[5] = 0xD0;
|
||||
buffer[6] = 0x07;
|
||||
readBytes( &buffer[5], 5 * (pointIdx - 1) + 3);
|
||||
sumL = buffer[5 * pointIdx + 1] << 8 | buffer[5 * pointIdx + 2];
|
||||
}
|
||||
clearFlags();
|
||||
|
||||
for (int i = 0 ; i < 5 * pointIdx; ++i) {
|
||||
sumH += buffer[i];
|
||||
}
|
||||
|
||||
if (sumH != sumL) {
|
||||
pointIdx = 0;
|
||||
}
|
||||
if (pointIdx) {
|
||||
uint8_t offset;
|
||||
for (int i = 0; i < pointIdx; ++i) {
|
||||
if (i == 0) {
|
||||
offset = 0;
|
||||
} else {
|
||||
offset = 4;
|
||||
}
|
||||
data[i].id = (buffer[i * 5 + offset] >> 4) & 0x0F;
|
||||
data[i].event = buffer[i * 5 + offset] & 0x0F;
|
||||
data[i].y = (uint16_t)((buffer[i * 5 + 1 + offset] << 4) | ((buffer[i * 5 + 3 + offset] >> 4) & 0x0F));
|
||||
data[i].x = (uint16_t)((buffer[i * 5 + 2 + offset] << 4) | (buffer[i * 5 + 3 + offset] & 0x0F));
|
||||
|
||||
//printf("X[%d]:%d Y:%d E:%d\n", i, data[i].x, data[i].y, data[i].event);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Only this one seems to be working (even pressing with 2 fingers)
|
||||
pointIdx = 1;
|
||||
data[0].id = (buffer[0] >> 4) & 0x0F;
|
||||
data[0].event = (buffer[0] & 0x0F) >>1;
|
||||
data[0].y = (uint16_t)((buffer[0 * 5 + 1] << 4) | ((buffer[0 * 5 + 3] >> 4) & 0x0F));
|
||||
data[0].x = (uint16_t)((buffer[0 * 5 + 2] << 4) | (buffer[0 * 5 + 3] & 0x0F));
|
||||
if (data[0].event == 3) { /** Press */
|
||||
_touchStartTime = esp_timer_get_time()/1000;
|
||||
}
|
||||
if (data[0].event == 0) { /** Lift up */
|
||||
_touchEndTime = esp_timer_get_time()/1000;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_L58_DEBUG) && CONFIG_L58_DEBUG==1
|
||||
printf("X:%d Y:%d E:%d\n", data[0].x, data[0].y, data[0].event);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t x = data[0].x;
|
||||
uint16_t y = data[0].y;
|
||||
|
||||
// Had some hope that state was event, but always come:
|
||||
// id:1 st:6
|
||||
// printf("id:%d st:%d\n", data[0].id, data[0].state);
|
||||
// Make touch rotation aware
|
||||
switch (_rotation)
|
||||
{
|
||||
// 0- no rotation: Works OK inverting Y axis
|
||||
case 0:
|
||||
y = _touch_height - y;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
swap(x, y);
|
||||
y = _touch_width - y;
|
||||
x = _touch_height - x;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
x = _touch_width - x;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
swap(x, y);
|
||||
break;
|
||||
}
|
||||
|
||||
point = {x, y, data[0].event};
|
||||
return point;
|
||||
}
|
||||
|
||||
void L58Touch::writeRegister8(uint8_t reg, uint8_t value)
|
||||
{
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, L58_ADDR << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, reg , ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, value , ACK_CHECK_EN);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
void L58Touch::writeData(uint8_t *data, int len)
|
||||
{
|
||||
if (len==0) return;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write(cmd, data, len, ACK_CHECK_EN);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
uint8_t L58Touch::readRegister8(uint8_t reg, uint8_t *data_buf)
|
||||
{
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, L58_ADDR << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, reg, I2C_MASTER_ACK);
|
||||
// Research: Why it's started a 2nd time here
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (L58_ADDR << 1) | I2C_MASTER_READ, true);
|
||||
|
||||
i2c_master_read_byte(cmd, data_buf, I2C_MASTER_NACK);
|
||||
i2c_master_stop(cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
#if defined(CONFIG_L58_DEBUG) && CONFIG_L58_DEBUG==1
|
||||
printf("REG 0x%x: 0x%x\n",reg,ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void L58Touch::readBytes(uint8_t *data, int len) {
|
||||
if (len==0) return;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, L58_ADDR << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write(cmd, data, 2, ACK_CHECK_EN);
|
||||
|
||||
i2c_master_start(cmd);
|
||||
|
||||
i2c_master_write_byte(cmd, L58_ADDR << 1 | I2C_MASTER_READ, ACK_CHECK_EN);
|
||||
i2c_master_read(cmd, data, len, (i2c_ack_type_t) ACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
printf("0x%02x ", data[i]);
|
||||
if ((i + 1) % 16 == 0) {
|
||||
printf("\r\n");
|
||||
}
|
||||
}
|
||||
if (len % 16) {
|
||||
printf("\r\n");
|
||||
}
|
||||
} else if (ret == ESP_ERR_TIMEOUT) {
|
||||
// Getting a lot of this!
|
||||
//ESP_LOGW(TAG, "Bus is busy");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Read failed");
|
||||
}
|
||||
}
|
||||
|
||||
void L58Touch::fireEvent(TPoint point, TEvent e)
|
||||
{
|
||||
if (_touchHandler)
|
||||
_touchHandler(point, e);
|
||||
}
|
||||
|
||||
void L58Touch::setRotation(uint8_t rotation) {
|
||||
_rotation = rotation;
|
||||
}
|
||||
|
||||
void L58Touch::setTouchWidth(uint16_t width) {
|
||||
printf("touch w:%d\n",width);
|
||||
_touch_width = width;
|
||||
}
|
||||
|
||||
void L58Touch::setTouchHeight(uint16_t height) {
|
||||
printf("touch h:%d\n",height);
|
||||
_touch_height = height;
|
||||
}
|
||||
|
||||
void L58Touch::clearFlags() {
|
||||
uint8_t buf[3] = {0xD0, 0X00, 0XAB};
|
||||
writeData(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void L58Touch::sleep() {
|
||||
uint8_t buf[2] = {0xD1, 0X05};
|
||||
writeData(buf, sizeof(buf));
|
||||
}
|
125
lvgl_touch/L58/include/L58Touch.h
Normal file
125
lvgl_touch/L58/include/L58Touch.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
// This is the first experimental Touch component for the LILYGO EPD47 touch overlay
|
||||
// NOTE: As in LVGL we cannot use blocking functions this is a variation of original library here:
|
||||
// https://github.com/martinberlin/FT6X36-IDF
|
||||
// More info about this epaper:
|
||||
// https://github.com/martinberlin/cale-idf/wiki/Model-parallel-ED047TC1.h
|
||||
#include <stdint.h>
|
||||
//#include <cstdlib>
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_idf_version.h"
|
||||
#ifndef touch_ttgo_h
|
||||
#define touch_ttgo_h
|
||||
// I2C Constants
|
||||
#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 */
|
||||
|
||||
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
||||
#define ACK_VAL 0x0 /*!< I2C ack value */
|
||||
#define NACK_VAL 0x1 /*!< I2C nack value */
|
||||
|
||||
#define L58_ADDR 0x5A
|
||||
|
||||
// Note: We still could not read proper events, so we simulate Tap
|
||||
enum class TEvent
|
||||
{
|
||||
None,
|
||||
TouchStart,
|
||||
TouchMove,
|
||||
TouchEnd,
|
||||
Tap
|
||||
};
|
||||
|
||||
struct TPoint
|
||||
{
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint8_t event;
|
||||
};
|
||||
|
||||
class L58Touch
|
||||
{
|
||||
|
||||
typedef struct {
|
||||
uint8_t id;
|
||||
uint8_t event;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
} TouchData_t;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
// TwoWire * wire will be replaced by ESP-IDF https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2c.html
|
||||
L58Touch(int8_t intPin);
|
||||
~L58Touch();
|
||||
|
||||
bool begin(uint16_t width = 0, uint16_t height = 0);
|
||||
void registerTouchHandler(void(*fn)(TPoint point, TEvent e));
|
||||
uint8_t touched();
|
||||
TPoint loop();
|
||||
TPoint processTouch();
|
||||
// Helper functions to make the touch display aware
|
||||
void setRotation(uint8_t rotation);
|
||||
void setTouchWidth(uint16_t width);
|
||||
void setTouchHeight(uint16_t height);
|
||||
// Pending implementation. How much x->touch y↓touch is placed (In case is smaller than display)
|
||||
void setXoffset(uint16_t x_offset);
|
||||
void setYoffset(uint16_t y_offset);
|
||||
void sleep();
|
||||
// Smart template from EPD to swap x,y:
|
||||
template <typename T> static inline void
|
||||
swap(T& a, T& b)
|
||||
{
|
||||
T t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
|
||||
void(*_touchHandler)(TPoint point, TEvent e) = nullptr;
|
||||
TouchData_t data[5];
|
||||
// Tap detection is enabled by default
|
||||
bool tapDetectionEnabled = true;
|
||||
// Only if the time difference between press and release is minor than this milliseconds a Tap even is triggered
|
||||
uint16_t tapDetectionMillisDiff = 100;
|
||||
|
||||
private:
|
||||
TPoint scanPoint();
|
||||
void writeRegister8(uint8_t reg, uint8_t val);
|
||||
void writeData(uint8_t *data, int len);
|
||||
void readBytes(uint8_t *data, int len);
|
||||
uint8_t readRegister8(uint8_t reg, uint8_t *data_buf);
|
||||
void fireEvent(TPoint point, TEvent e);
|
||||
uint8_t read8(uint8_t regName);
|
||||
void clearFlags();
|
||||
|
||||
static L58Touch * _instance;
|
||||
uint8_t _intPin;
|
||||
|
||||
// Make touch rotation aware:
|
||||
uint8_t _rotation = 0;
|
||||
uint16_t _touch_width = 0;
|
||||
uint16_t _touch_height = 0;
|
||||
|
||||
uint8_t _touches;
|
||||
uint16_t _touchX[2], _touchY[2], _touchEvent[2];
|
||||
TPoint _points[10];
|
||||
TPoint _point;
|
||||
uint8_t _pointIdx = 0;
|
||||
unsigned long _touchStartTime = 0;
|
||||
unsigned long _touchEndTime = 0;
|
||||
uint8_t lastEvent = 3; // No event
|
||||
uint16_t lastX = 0;
|
||||
uint16_t lastY = 0;
|
||||
bool _dragMode = false;
|
||||
const uint8_t maxDeviation = 5;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue