Driver improvements (#226)

- Created driver subprojects: `FT5x06`, `FT6x36`, `CST816S`.
- Refactored existing projects to use new drivers.
- Improve `PwmBacklight` driver: expose frequency, channel id and timer id
- Update `build-and-release-all.sh` for recent board addition
This commit is contained in:
Ken Van Hoeylandt
2025-02-20 22:41:56 +01:00
committed by GitHub
parent 6e8fbae62b
commit 933bc5fb97
49 changed files with 429 additions and 413 deletions
+1 -1
View File
@@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port esp_lcd ILI934x driver vfs fatfs
REQUIRES Tactility esp_lvgl_port esp_lcd ILI934x FT6x36 driver vfs fatfs
)
@@ -1,378 +0,0 @@
#include "FT6X36.h"
#include "freertos/FreeRTOS.h"
#define CONFIG_FT6X36_DEBUG false
FT6X36 *FT6X36::_instance = nullptr;
static const char *TAG = "i2c-touch";
//Handle indicating I2C is ready to read the touch
SemaphoreHandle_t TouchSemaphore = xSemaphoreCreateBinary();
FT6X36::FT6X36(i2c_port_t port, gpio_num_t interruptPin)
{
_instance = this;
_port = port;
_intPin = interruptPin;
}
// Destructor should detach interrupt to the pin
FT6X36::~FT6X36()
{
if (_intPin >= 0)
gpio_isr_handler_remove((gpio_num_t)_intPin);
}
bool FT6X36::begin(uint8_t threshold, 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");
}
uint8_t data_panel_id;
readRegister8(FT6X36_REG_PANEL_ID, &data_panel_id);
if (data_panel_id != FT6X36_VENDID) {
ESP_LOGE(TAG,"FT6X36_VENDID does not match. Received:0x%x Expected:0x%x\n",data_panel_id,FT6X36_VENDID);
return false;
}
ESP_LOGI(TAG, "\tDevice ID: 0x%02x", data_panel_id);
uint8_t chip_id;
readRegister8(FT6X36_REG_CHIPID, &chip_id);
if (chip_id != FT6206_CHIPID && chip_id != FT6236_CHIPID && chip_id != FT6336_CHIPID) {
ESP_LOGE(TAG,"FT6206_CHIPID does not match. Received:0x%x\n",chip_id);
return false;
}
ESP_LOGI(TAG, "\tFound touch controller with Chip ID: 0x%02x", chip_id);
if (_intPin >= 0)
{
// INT pin triggers the callback function on the Falling edge of the GPIO
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_NEGEDGE; // GPIO_INTR_NEGEDGE repeats always interrupt
io_conf.pin_bit_mask = 1ULL<<_intPin;
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);
esp_err_t isr_service = gpio_install_isr_service(0);
printf("ISR trigger install response: 0x%x %s\n", isr_service, (isr_service==0)?"ESP_OK":"");
gpio_isr_handler_add((gpio_num_t)_intPin, isr, (void*) 1);
}
writeRegister8(FT6X36_REG_DEVICE_MODE, 0x00);
writeRegister8(FT6X36_REG_THRESHHOLD, threshold);
writeRegister8(FT6X36_REG_TOUCHRATE_ACTIVE, 0x0E);
return true;
}
void FT6X36::registerTouchHandler(void (*fn)(TPoint point, TEvent e))
{
_touchHandler = fn;
if (CONFIG_FT6X36_DEBUG) printf("Touch handler function registered\n");
}
uint8_t FT6X36::touched()
{
uint8_t data_buf;
esp_err_t ret = readRegister8(FT6X36_REG_NUM_TOUCHES, &data_buf);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Error reading from device: %s", esp_err_to_name(ret));
}
if (data_buf > 2)
{
data_buf = 0;
}
return data_buf;
}
void FT6X36::loop()
{
processTouch();
}
void IRAM_ATTR FT6X36::isr(void* arg)
{
/* Un-block the interrupt processing task now */
xSemaphoreGive(TouchSemaphore);
//xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
void FT6X36::processTouch()
{
/* Task move to Block state to wait for interrupt event */
if (_intPin >= 0)
{
if (xSemaphoreTake(TouchSemaphore, portMAX_DELAY) == false) return;
}
readData();
uint8_t n = 0;
TRawEvent event = (TRawEvent)_touchEvent[n];
TPoint point{_touchX[n], _touchY[n]};
switch (event) {
case TRawEvent::PressDown:
_points[0] = point;
_dragMode = false;
// Note: Is in microseconds. Ref https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html
_touchStartTime = esp_timer_get_time()/1000;
fireEvent(point, TEvent::TouchStart);
break;
case TRawEvent::Contact:
// Dragging makes no sense IMHO. Since the X & Y are not getting updated while dragging
// Dragging && _points[0].aboutEqual(point) - Not used IDEA 2: && (lastEvent == 2)
if (!_dragMode &&
(abs(lastX-_touchX[n]) <= maxDeviation || abs(lastY-_touchY[n])<=maxDeviation) &&
esp_timer_get_time()/1000 - _touchStartTime > 300) {
_dragMode = true;
fireEvent(point, TEvent::DragStart);
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
printf("EV: DragStart\n");
#endif
} else if (_dragMode) {
fireEvent(point, TEvent::DragMove);
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
printf("EV: DragMove\n");
#endif
}
fireEvent(point, TEvent::TouchMove);
// For me the _touchStartTime shouold be set in both PressDown & Contact events, but after Drag detection
_touchStartTime = esp_timer_get_time()/1000;
break;
case TRawEvent::LiftUp:
_points[9] = point;
_touchEndTime = esp_timer_get_time()/1000;
//printf("TIMEDIFF: %lu End: %lu\n", _touchEndTime - _touchStartTime, _touchEndTime);
fireEvent(point, TEvent::TouchEnd);
if (_dragMode) {
fireEvent(point, TEvent::DragEnd);
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
printf("EV: DragEnd\n");
#endif
_dragMode = false;
}
if ( _touchEndTime - _touchStartTime <= 900) {
// Do not get why this: _points[0].aboutEqual(point) (Original library)
fireEvent(point, TEvent::Tap);
_points[0] = {0, 0};
_touchStartTime = 0;
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
printf("EV: Tap\n");
#endif
_dragMode = false;
}
break;
case TRawEvent::NoEvent:
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
printf("EV: NoEvent\n");
#endif
break;
}
// Store lastEvent
lastEvent = (int) event;
lastX = _touchX[0];
lastY = _touchY[0];
}
void FT6X36::poll(TPoint * point, TEvent * e)
{
readData();
// TPoint point{_touchX[0], _touchY[0]};
TRawEvent event = (TRawEvent)_touchEvent[0];
if (point != NULL)
{
point->x = _touchX[0];
point->y = _touchY[0];
}
if (e != NULL)
{
switch (event)
{
case TRawEvent::PressDown:
*e = TEvent::TouchStart;
break;
case TRawEvent::Contact:
*e = TEvent::TouchMove;
break;
case TRawEvent::LiftUp:
default:
*e = TEvent::TouchEnd;
break;
}
}
}
uint8_t FT6X36::read8(uint8_t regName) {
uint8_t buf;
readRegister8(regName, &buf);
return buf;
}
#define data_size 16 // Discarding last 2: 0x0E & 0x0F as not relevant
bool FT6X36::readData(void)
{
esp_err_t ret;
uint8_t data[data_size];
uint8_t touch_pnt_cnt; // Number of detected touch points
readRegister8(FT6X36_REG_NUM_TOUCHES, &touch_pnt_cnt);
// Read data
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (FT6X36_ADDR<<1), ACK_CHECK_EN);
i2c_master_write_byte(cmd, 0, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
return ret;
}
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (FT6X36_ADDR<<1)|1, ACK_CHECK_EN);
i2c_master_read(cmd, data, data_size, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (CONFIG_FT6X36_DEBUG) {
//printf("REGISTERS:\n");
for (int16_t i = 0; i < data_size; i++)
{
printf("%x:%x ", i, data[i]);
}
printf("\n");
}
const uint8_t addrShift = 6;
// READ X, Y and Touch events (X 2)
for (uint8_t i = 0; i < 2; i++)
{
_touchX[i] = data[FT6X36_REG_P1_XH + i * addrShift] & 0x0F;
_touchX[i] <<= 8;
_touchX[i] |= data[FT6X36_REG_P1_XL + i * addrShift];
_touchY[i] = data[FT6X36_REG_P1_YH + i * addrShift] & 0x0F;
_touchY[i] <<= 8;
_touchY[i] |= data[FT6X36_REG_P1_YL + i * addrShift];
_touchEvent[i] = data[FT6X36_REG_P1_XH + i * addrShift] >> 6;
}
// Make _touchX[idx] and _touchY[idx] rotation aware
switch (_rotation)
{
case 1:
swap(_touchX[0], _touchY[0]);
swap(_touchX[1], _touchY[1]);
_touchY[0] = _touch_width - _touchY[0] -1;
_touchY[1] = _touch_width - _touchY[1] -1;
break;
case 2:
_touchX[0] = _touch_width - _touchX[0] - 1;
_touchX[1] = _touch_width - _touchX[1] - 1;
_touchY[0] = _touch_height - _touchY[0] - 1;
_touchY[1] = _touch_height - _touchY[1] - 1;
break;
case 3:
swap(_touchX[0], _touchY[0]);
swap(_touchX[1], _touchY[1]);
_touchX[0] = _touch_height - _touchX[0] - 1;
_touchX[1] = _touch_height - _touchX[1] - 1;
break;
}
if (CONFIG_FT6X36_DEBUG) {
printf("X0:%d Y0:%d EVENT:%d\n", _touchX[0], _touchY[0], _touchEvent[0]);
//printf("X1:%d Y1:%d EVENT:%d\n", _touchX[1], _touchY[1], _touchEvent[1]);
}
return true;
}
void FT6X36::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, FT6X36_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(_port, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
}
uint8_t FT6X36::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, FT6X36_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, (FT6X36_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(_port, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
//FT6X36_REG_GESTURE_ID. Check if it can be read!
#if defined(FT6X36_DEBUG) && FT6X36_DEBUG==1
printf("REG 0x%x: 0x%x\n",reg,ret);
#endif
return ret;
}
void FT6X36::fireEvent(TPoint point, TEvent e)
{
if (_touchHandler)
_touchHandler(point, e);
}
void FT6X36::debugInfo()
{
printf(" TH_DIFF: %d CTRL: %d\n", read8(FT6X36_REG_FILTER_COEF), read8(FT6X36_REG_CTRL));
printf(" TIMEENTERMONITOR: %d PERIODACTIVE: %d\n", read8(FT6X36_REG_TIME_ENTER_MONITOR), read8(FT6X36_REG_TOUCHRATE_ACTIVE));
printf(" PERIODMONITOR: %d RADIAN_VALUE: %d\n", read8(FT6X36_REG_TOUCHRATE_MONITOR), read8(FT6X36_REG_RADIAN_VALUE));
printf(" OFFSET_LEFT_RIGHT: %d OFFSET_UP_DOWN: %d\n", read8(FT6X36_REG_OFFSET_LEFT_RIGHT), read8(FT6X36_REG_OFFSET_UP_DOWN));
printf("DISTANCE_LEFT_RIGHT: %d DISTANCE_UP_DOWN: %d\n", read8(FT6X36_REG_DISTANCE_LEFT_RIGHT), read8(FT6X36_REG_DISTANCE_UP_DOWN));
printf(" DISTANCE_ZOOM: %d CIPHER: %d\n", read8(FT6X36_REG_DISTANCE_ZOOM), read8(FT6X36_REG_CHIPID));
printf(" G_MODE: %d PWR_MODE: %d\n", read8(FT6X36_REG_INTERRUPT_MODE), read8(FT6X36_REG_POWER_MODE));
printf(" FIRMID: %d FOCALTECH_ID: %d STATE: %d\n", read8(FT6X36_REG_FIRMWARE_VERSION), read8(FT6X36_REG_PANEL_ID), read8(FT6X36_REG_STATE));
}
void FT6X36::setRotation(uint8_t rotation) {
_rotation = rotation;
}
void FT6X36::setTouchWidth(uint16_t width) {
printf("touch w:%d\n",width);
_touch_width = width;
}
void FT6X36::setTouchHeight(uint16_t height) {
printf("touch h:%d\n",height);
_touch_height = height;
}
-184
View File
@@ -1,184 +0,0 @@
#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_timer.h>
#ifndef ft6x36_h
#define ft6x36_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 */
//SemaphoreHandle_t print_mux = NULL;
#define FT6X36_ADDR 0x38
#define FT6X36_REG_DEVICE_MODE 0x00
#define FT6X36_REG_GESTURE_ID 0x01
#define FT6X36_REG_NUM_TOUCHES 0x02
#define FT6X36_REG_P1_XH 0x03
#define FT6X36_REG_P1_XL 0x04
#define FT6X36_REG_P1_YH 0x05
#define FT6X36_REG_P1_YL 0x06
#define FT6X36_REG_P1_WEIGHT 0x07
#define FT6X36_REG_P1_MISC 0x08
#define FT6X36_REG_P2_XH 0x09
#define FT6X36_REG_P2_XL 0x0A
#define FT6X36_REG_P2_YH 0x0B
#define FT6X36_REG_P2_YL 0x0C
#define FT6X36_REG_P2_WEIGHT 0x0D
#define FT6X36_REG_P2_MISC 0x0E
#define FT6X36_REG_THRESHHOLD 0x80
#define FT6X36_REG_FILTER_COEF 0x85
#define FT6X36_REG_CTRL 0x86
#define FT6X36_REG_TIME_ENTER_MONITOR 0x87
#define FT6X36_REG_TOUCHRATE_ACTIVE 0x88
#define FT6X36_REG_TOUCHRATE_MONITOR 0x89 // value in ms
#define FT6X36_REG_RADIAN_VALUE 0x91
#define FT6X36_REG_OFFSET_LEFT_RIGHT 0x92
#define FT6X36_REG_OFFSET_UP_DOWN 0x93
#define FT6X36_REG_DISTANCE_LEFT_RIGHT 0x94
#define FT6X36_REG_DISTANCE_UP_DOWN 0x95
#define FT6X36_REG_DISTANCE_ZOOM 0x96
#define FT6X36_REG_LIB_VERSION_H 0xA1
#define FT6X36_REG_LIB_VERSION_L 0xA2
#define FT6X36_REG_CHIPID 0xA3
#define FT6X36_REG_INTERRUPT_MODE 0xA4
#define FT6X36_REG_POWER_MODE 0xA5
#define FT6X36_REG_FIRMWARE_VERSION 0xA6
#define FT6X36_REG_PANEL_ID 0xA8
#define FT6X36_REG_STATE 0xBC
#define FT6X36_PMODE_ACTIVE 0x00
#define FT6X36_PMODE_MONITOR 0x01
#define FT6X36_PMODE_STANDBY 0x02
#define FT6X36_PMODE_HIBERNATE 0x03
/* 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
#define FT6X36_VENDID 0x11
#define FT6206_CHIPID 0x06
#define FT6236_CHIPID 0x36
#define FT6336_CHIPID 0x64
#define FT6X36_DEFAULT_THRESHOLD 22
// From: https://github.com/lvgl/lv_port_esp32/blob/master/components/lvgl_esp32_drivers/lvgl_touch/ft6x36.h
#define FT6X36_MSB_MASK 0x0F
#define FT6X36_LSB_MASK 0xFF
enum class TRawEvent
{
PressDown,
LiftUp,
Contact,
NoEvent
};
enum class TEvent
{
None,
TouchStart,
TouchMove,
TouchEnd,
Tap,
DragStart,
DragMove,
DragEnd
};
struct TPoint
{
uint16_t x;
uint16_t y;
/**
* This is being used in the original library but I'm not using it in this implementation
*/
bool aboutEqual(const TPoint point)
{
return abs(x - point.x) <= 5 && abs(y - point.y) <= 5;
}
};
class FT6X36
{
static void IRAM_ATTR isr(void* arg);
public:
// TwoWire * wire will be replaced by ESP-IDF https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2c.html
FT6X36(i2c_port_t = I2C_NUM_0, gpio_num_t interruptPin = GPIO_NUM_NC);
~FT6X36();
bool begin(uint8_t threshold = FT6X36_DEFAULT_THRESHOLD, uint16_t width = 0, uint16_t height = 0);
void registerTouchHandler(void(*fn)(TPoint point, TEvent e));
uint8_t touched();
void loop();
void processTouch();
void debugInfo();
void poll(TPoint * point, TEvent * event);
// 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);
// 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;
bool readData(void);
private:
void writeRegister8(uint8_t reg, uint8_t val);
uint8_t readRegister8(uint8_t reg, uint8_t *data_buf);
void fireEvent(TPoint point, TEvent e);
uint8_t read8(uint8_t regName);
static FT6X36 * _instance;
i2c_port_t _port;
int8_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];
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
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019 strange_v
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.
@@ -1,8 +0,0 @@
This project is an adaption of the code at https://github.com/martinberlin/FT6X36-IDF which is an adaptation of https://github.com/strange-v/FT6X36
The original license is an MIT license and is included in this directory.
Changes:
- Remove Kconfig-based configuratio
- Removed I2C init code
- Allow for passing a different I2C port
@@ -1,10 +1,19 @@
#include "Core2Display.h"
#include "Core2Touch.h"
#include <Ft6x36Touch.h>
#include <Ili934xDisplay.h>
std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
auto configuration = std::make_unique<Ft6x36Touch::Configuration>(
I2C_NUM_0,
GPIO_NUM_39
);
return std::make_shared<Ft6x36Touch>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto touch = std::make_shared<Core2Touch>();
auto touch = createTouch();
auto configuration = std::make_unique<Ili934xDisplay::Configuration>(
CORE2_LCD_SPI_HOST,
@@ -12,10 +21,12 @@ std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
CORE2_LCD_PIN_DC,
CORE2_LCD_HORIZONTAL_RESOLUTION,
CORE2_LCD_VERTICAL_RESOLUTION,
touch
touch,
false,
false,
false,
true
);
configuration->mirrorX = true;
return std::make_shared<Ili934xDisplay>(std::move(configuration));
}
@@ -1,94 +0,0 @@
#include "Core2Touch.h"
#include <esp_lvgl_port.h>
#define TAG "core2_touch"
static void touchReadCallback(lv_indev_t* indev, lv_indev_data_t* data) {
auto* touch = (Core2Touch*)lv_indev_get_driver_data(indev);
touch->readLast(data);
}
static int32_t threadCallback(void* context) {
auto* touch = (Core2Touch*)context;
touch->driverThreadMain();
return 0;
}
Core2Touch::Core2Touch() :
driverThread(tt::Thread("core2_touch", 4096, threadCallback, this))
{ }
void Core2Touch::driverThreadMain() {
TPoint point = { .x = 0, .y = 0 };
TEvent event = TEvent::None;
while (!shouldInterruptDriverThread()) {
driver.processTouch();
driver.poll(&point, &event);
if (mutex.lock(100)) {
switch (event) {
case TEvent::TouchStart:
case TEvent::TouchMove:
case TEvent::DragStart:
case TEvent::DragMove:
case TEvent::DragEnd:
lastState = LV_INDEV_STATE_PR;
lastPoint.x = point.x;
lastPoint.y = point.y;
break;
case TEvent::TouchEnd:
lastState = LV_INDEV_STATE_REL;
lastPoint.x = point.x;
lastPoint.y = point.y;
break;
case TEvent::Tap:
case TEvent::None:
break;
}
mutex.unlock();
}
}
}
bool Core2Touch::shouldInterruptDriverThread() {
bool interrupt = false;
if (mutex.lock(50 / portTICK_PERIOD_MS)) {
interrupt = interruptDriverThread;
mutex.unlock();
}
return interrupt;
}
bool Core2Touch::start(lv_display_t* display) {
TT_LOG_I(TAG, "start");
driverThread.start();
uint16_t width = lv_display_get_horizontal_resolution(display);
uint16_t height = lv_display_get_vertical_resolution(display);
if (!driver.begin(FT6X36_DEFAULT_THRESHOLD, width, height)) {
TT_LOG_E(TAG, "driver.begin() failed");
return false;
}
deviceHandle = lv_indev_create();
lv_indev_set_type(deviceHandle, LV_INDEV_TYPE_POINTER);
lv_indev_set_driver_data(deviceHandle, this);
lv_indev_set_read_cb(deviceHandle, touchReadCallback);
TT_LOG_I(TAG, "start success");
return true;
}
bool Core2Touch::stop() {
lv_indev_delete(deviceHandle);
interruptDriverThread = true;
driverThread.join();
return true;
}
void Core2Touch::readLast(lv_indev_data_t* data) {
data->point = lastPoint;
data->state = lastState;
}
@@ -1,35 +0,0 @@
#pragma once
#include "Tactility/hal/touch/TouchDevice.h"
#include "ft6x36/FT6X36.h"
#include <Tactility/TactilityCore.h>
class Core2Touch : public tt::hal::touch::TouchDevice {
private:
lv_indev_t* _Nullable deviceHandle = nullptr;
FT6X36 driver = FT6X36(I2C_NUM_0, GPIO_NUM_39);
tt::Thread driverThread;
bool interruptDriverThread = false;
tt::Mutex mutex;
lv_point_t lastPoint = { .x = 0, .y = 0 };
lv_indev_state_t lastState = LV_INDEV_STATE_RELEASED;
bool shouldInterruptDriverThread();
public:
Core2Touch();
std::string getName() const final { return "FT6336U"; }
std::string getDescription() const final { return "I2C touch driver"; }
bool start(lv_display_t* display) override;
bool stop() override;
void readLast(lv_indev_data_t* data);
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
void driverThreadMain();
};