#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
|
@ -11,9 +11,7 @@ list(APPEND SOURCES "lvgl_tft/disp_driver.c")
|
||||||
if(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341)
|
if(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341)
|
||||||
list(APPEND SOURCES "lvgl_tft/ili9341.c")
|
list(APPEND SOURCES "lvgl_tft/ili9341.c")
|
||||||
elseif(CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER)
|
elseif(CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER)
|
||||||
list(APPEND SOURCES "lvgl_tft/epdiy_epaper.cpp")
|
list(APPEND SOURCES "lvgl_tft/epdiy_epaper.c")
|
||||||
elseif(CONFIG_LV_EPAPER_CALEPD_DISPLAY_CONTROLLER)
|
|
||||||
list(APPEND SOURCES "lvgl_tft/calepd_epaper.cpp")
|
|
||||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481)
|
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481)
|
||||||
list(APPEND SOURCES "lvgl_tft/ili9481.c")
|
list(APPEND SOURCES "lvgl_tft/ili9481.c")
|
||||||
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486)
|
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486)
|
||||||
|
@ -67,6 +65,7 @@ if(CONFIG_LV_TOUCH_CONTROLLER)
|
||||||
elseif(CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
|
elseif(CONFIG_LV_TOUCH_CONTROLLER_FT6X06)
|
||||||
list(APPEND SOURCES "lvgl_touch/ft6x36.c")
|
list(APPEND SOURCES "lvgl_touch/ft6x36.c")
|
||||||
elseif(CONFIG_LV_TOUCH_CONTROLLER_L58)
|
elseif(CONFIG_LV_TOUCH_CONTROLLER_L58)
|
||||||
|
list(APPEND SOURCES "lvgl_touch/L58/L58Touch.cpp")
|
||||||
list(APPEND SOURCES "lvgl_touch/l58.cpp")
|
list(APPEND SOURCES "lvgl_touch/l58.cpp")
|
||||||
elseif(CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
|
elseif(CONFIG_LV_TOUCH_CONTROLLER_STMPE610)
|
||||||
list(APPEND SOURCES "lvgl_touch/stmpe610.c")
|
list(APPEND SOURCES "lvgl_touch/stmpe610.c")
|
||||||
|
|
|
@ -33,8 +33,10 @@ swap of RGB565 color on the LVGL configuration menuconfig (it's not handled auto
|
||||||
| FitiPower JD79653A/ GoodDisplay GDEW0154M09 | e-Paper | SPI | 1: 1byte per pixel | No |
|
| FitiPower JD79653A/ GoodDisplay GDEW0154M09 | e-Paper | SPI | 1: 1byte per pixel | No |
|
||||||
| EPDiy supported epaper (needs PCB) | e-Paper | Parallel | 4: RGB232 16 grayscales | No
|
| EPDiy supported epaper (needs PCB) | e-Paper | Parallel | 4: RGB232 16 grayscales | No
|
||||||
|
|
||||||
Please note that EPDiy supported epapers include also the Lilygo EPD47 that comes with it's own PCB and ESP32 WROVER. Is possible also to build your own EPDiy PCB, please find the [project KiCad source files, schematics, and documentation here](https://github.com/vroland/epdiy/tree/master/hardware/epaper-breakout)
|
Please note that EPDiy supported epapers include also the Lilygo EPD47 that comes with it's own PCB and ESP32 WROVER. Is possible also to build your own EPDiy PCB, please find the [project KiCad source files, schematics, and documentation here](https://github.com/vroland/epdiy/tree/master/hardware/epaper-breakout).
|
||||||
To use an EPDiy supported epaper you need to add it [as a component](https://github.com/martinberlin/lv_port_esp32-epaper/tree/master/components) and also update the CMakeLists of lvgl component to [REQUIRE that library](https://github.com/martinberlin/lv_port_esp32-epaper/wiki).
|
To use an EPDiy supported epaper you need to add it [as a component using git submodules](https://github.com/martinberlin/lv_port_esp32-epaper/tree/master/components) and also update the CMakeLists of lvgl component to [REQUIRE that library](https://github.com/martinberlin/lv_port_esp32-epaper/wiki).
|
||||||
|
|
||||||
|
git submodule add https://github.com/martinberlin/epdiy-rotation.git components/epd_driver
|
||||||
|
|
||||||
## Supported indev controllers
|
## Supported indev controllers
|
||||||
|
|
||||||
|
@ -43,6 +45,7 @@ To use an EPDiy supported epaper you need to add it [as a component](https://git
|
||||||
- other FT6X36 or the FT6206 controllers should work as well (not tested)
|
- other FT6X36 or the FT6206 controllers should work as well (not tested)
|
||||||
- STMPE610
|
- STMPE610
|
||||||
- FT81x (Single, Dual, and Quad SPI)
|
- FT81x (Single, Dual, and Quad SPI)
|
||||||
|
- L58 touch component hook (Used in Lilygo EPD47 parallel with EPDiy driver)
|
||||||
|
|
||||||
If your display or input device (touch) controller is not supported consider contributing to this repo by
|
If your display or input device (touch) controller is not supported consider contributing to this repo by
|
||||||
adding support to it! [Contribute controller support](CONTRIBUTE_CONTROLLER_SUPPORT.md)
|
adding support to it! [Contribute controller support](CONTRIBUTE_CONTROLLER_SUPPORT.md)
|
||||||
|
|
|
@ -45,7 +45,7 @@ extern "C" {
|
||||||
// IMPORTANT: This will render the screen in 10 times:
|
// IMPORTANT: This will render the screen in 10 times:
|
||||||
#elif defined (CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER)
|
#elif defined (CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER)
|
||||||
#define DISP_BUF_SIZE LV_HOR_RES_MAX*(LV_VER_RES_MAX/10)
|
#define DISP_BUF_SIZE LV_HOR_RES_MAX*(LV_VER_RES_MAX/10)
|
||||||
#elif defined (CONFIG_LV_EPAPER_CALEPD_DISPLAY_CONTROLLER)
|
#elif defined ()
|
||||||
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 90)
|
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 90)
|
||||||
|
|
||||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357
|
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357
|
||||||
|
|
|
@ -93,10 +93,7 @@ menu "LVGL TFT/Epaper Display controller"
|
||||||
bool
|
bool
|
||||||
help
|
help
|
||||||
EPDIY parallel epaper controller.
|
EPDIY parallel epaper controller.
|
||||||
config LV_EPAPER_CALEPD_DISPLAY_CONTROLLER
|
|
||||||
bool
|
|
||||||
help
|
|
||||||
CalEPD SPI epaper controller.
|
|
||||||
config LV_TFT_DISPLAY_CONTROLLER_ILI9341
|
config LV_TFT_DISPLAY_CONTROLLER_ILI9341
|
||||||
bool
|
bool
|
||||||
help
|
help
|
||||||
|
@ -283,12 +280,6 @@ menu "LVGL TFT/Epaper Display controller"
|
||||||
bool "EPDIY_GENERIC"
|
bool "EPDIY_GENERIC"
|
||||||
select LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
select LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
||||||
select LV_EPAPER_DISPLAY_PROTOCOL_PARALLEL
|
select LV_EPAPER_DISPLAY_PROTOCOL_PARALLEL
|
||||||
|
|
||||||
config LV_EPAPER_DISPLAY_USER_CONTROLLER_CALEPD
|
|
||||||
bool "CALEPD_GENERIC"
|
|
||||||
# Use also Parallel to avoid LGVL SPI instantiation
|
|
||||||
select LV_EPAPER_CALEPD_DISPLAY_CONTROLLER
|
|
||||||
select LV_EPAPER_DISPLAY_PROTOCOL_PARALLEL
|
|
||||||
config LV_TFT_DISPLAY_USER_CONTROLLER_ILI9341
|
config LV_TFT_DISPLAY_USER_CONTROLLER_ILI9341
|
||||||
bool "ILI9341"
|
bool "ILI9341"
|
||||||
select LV_TFT_DISPLAY_CONTROLLER_ILI9341
|
select LV_TFT_DISPLAY_CONTROLLER_ILI9341
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
#include "esp_log.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
|
|
||||||
#include "calepd_epaper.h"
|
|
||||||
|
|
||||||
// NOTE: This needs Epdiy component https://github.com/vroland/epdiy
|
|
||||||
// Run idf.py menuconfig-> Component Config -> E-Paper driver and select:
|
|
||||||
// Display type: LILIGO 4.7 ED047TC1
|
|
||||||
// Board: LILIGO T5-4.7 Epaper
|
|
||||||
// In the same section Component Config -> ESP32 Specifics -> Enable PSRAM
|
|
||||||
//#include "parallel/ED047TC1.h"
|
|
||||||
//Ed047TC1 display;
|
|
||||||
|
|
||||||
// SPI Generic epapers (Goodisplay/ Waveshare)
|
|
||||||
// Select the right class for your SPI epaper: https://github.com/martinberlin/cale-idf/wiki
|
|
||||||
//#include <gdew0583t7.h>
|
|
||||||
#include <gdew027w3.h>
|
|
||||||
Gdew027w3 display(io);
|
|
||||||
EpdSpi io;
|
|
||||||
//Gdew0583T7 display(io);
|
|
||||||
|
|
||||||
/** test Display dimensions
|
|
||||||
* Do not forget to set: menuconfig -> Components -> LVGL configuration
|
|
||||||
* Max. Horizontal resolution 264 -> WIDTH of your epaper
|
|
||||||
* Max. Vertical resolution 176 -> HEIGHT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*********************
|
|
||||||
* DEFINES
|
|
||||||
*********************/
|
|
||||||
#define TAG "EPDIY"
|
|
||||||
|
|
||||||
uint16_t flushcalls = 0;
|
|
||||||
|
|
||||||
/* Display initialization routine */
|
|
||||||
void calepd_init(void)
|
|
||||||
{
|
|
||||||
printf("calepd_init\n");
|
|
||||||
display.init();
|
|
||||||
display.setRotation(0);
|
|
||||||
// Clear screen
|
|
||||||
//display.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Required by LVGL */
|
|
||||||
void calepd_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
|
||||||
{
|
|
||||||
++flushcalls;
|
|
||||||
printf("flush %d x:%d y:%d w:%d h:%d\n", flushcalls,area->x1,area->y1,lv_area_get_width(area),lv_area_get_height(area));
|
|
||||||
|
|
||||||
// Full update
|
|
||||||
if (lv_area_get_width(area)==display.width() && lv_area_get_height(area)==display.height()) {
|
|
||||||
display.update();
|
|
||||||
} else {
|
|
||||||
// Partial update:
|
|
||||||
display.update(); // Uncomment to disable partial update
|
|
||||||
//display.updateWindow(area->x1,area->y1,lv_area_get_width(area),lv_area_get_height(area), true);
|
|
||||||
//display.updateWindow(area->x1,area->y1,lv_area_get_width(area),lv_area_get_height(area));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IMPORTANT!!!
|
|
||||||
* Inform the graphics library that you are ready with the flushing */
|
|
||||||
lv_disp_flush_ready(drv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Called for each pixel */
|
|
||||||
void calepd_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t* buf,
|
|
||||||
lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
|
||||||
lv_color_t color, lv_opa_t opa)
|
|
||||||
{
|
|
||||||
//If not drawing anything: Debug to see if this function is called:
|
|
||||||
//printf("set_px %d %d\n",(int16_t)x,(int16_t)y);
|
|
||||||
|
|
||||||
// Test using RGB232
|
|
||||||
int16_t epd_color = EPD_WHITE;
|
|
||||||
|
|
||||||
// Color setting use: RGB232
|
|
||||||
// Only monochrome:All what is not white, turn black
|
|
||||||
if ((int16_t)color.full<254) {
|
|
||||||
epd_color = EPD_BLACK;
|
|
||||||
}
|
|
||||||
display.drawPixel((int16_t)x, (int16_t)y, epd_color);
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/**
|
|
||||||
* Display class for generic e-Paper driven by EPDiy class
|
|
||||||
*/
|
|
||||||
#ifndef CALEPD_H
|
|
||||||
#define CALEPD_H
|
|
||||||
|
|
||||||
#define EPDIY_COLUMNS (LV_HOR_RES_MAX / 8)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
|
||||||
#include "lvgl.h"
|
|
||||||
#else
|
|
||||||
#include "lvgl/lvgl.h"
|
|
||||||
#endif
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
/* Configure your display */
|
|
||||||
void calepd_init(void);
|
|
||||||
|
|
||||||
/* LVGL callbacks */
|
|
||||||
void calepd_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
|
|
||||||
|
|
||||||
/* Only for monochrome displays. But we use epdiy_set_px also for epapers */
|
|
||||||
//void epdiy_rounder(lv_disp_drv_t *disp_drv, lv_area_t *area);
|
|
||||||
void calepd_set_px_cb(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* EPDIY_H */
|
|
|
@ -12,8 +12,6 @@ void disp_driver_init(void)
|
||||||
ili9341_init();
|
ili9341_init();
|
||||||
#elif defined CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
#elif defined CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
||||||
epdiy_init();
|
epdiy_init();
|
||||||
#elif defined CONFIG_LV_EPAPER_CALEPD_DISPLAY_CONTROLLER
|
|
||||||
calepd_init();
|
|
||||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
||||||
ili9481_init();
|
ili9481_init();
|
||||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
||||||
|
@ -55,8 +53,6 @@ void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t *
|
||||||
ili9341_flush(drv, area, color_map);
|
ili9341_flush(drv, area, color_map);
|
||||||
#elif defined CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
#elif defined CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
||||||
epdiy_flush(drv, area, color_map);
|
epdiy_flush(drv, area, color_map);
|
||||||
#elif defined CONFIG_LV_EPAPER_CALEPD_DISPLAY_CONTROLLER
|
|
||||||
calepd_flush(drv, area, color_map);
|
|
||||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
||||||
ili9481_flush(drv, area, color_map);
|
ili9481_flush(drv, area, color_map);
|
||||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
||||||
|
@ -115,8 +111,6 @@ void disp_driver_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_
|
||||||
ssd1306_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
ssd1306_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
||||||
#elif defined CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
#elif defined CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
||||||
epdiy_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
epdiy_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
||||||
#elif defined CONFIG_LV_EPAPER_CALEPD_DISPLAY_CONTROLLER
|
|
||||||
calepd_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
|
||||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
|
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
|
||||||
sh1107_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
sh1107_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
|
||||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820
|
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820
|
||||||
|
|
|
@ -22,8 +22,6 @@ extern "C" {
|
||||||
#include "ili9341.h"
|
#include "ili9341.h"
|
||||||
#elif defined CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
#elif defined CONFIG_LV_EPAPER_EPDIY_DISPLAY_CONTROLLER
|
||||||
#include "lvgl_tft/epdiy_epaper.h"
|
#include "lvgl_tft/epdiy_epaper.h"
|
||||||
#elif defined CONFIG_LV_EPAPER_CALEPD_DISPLAY_CONTROLLER
|
|
||||||
#include "lvgl_tft/calepd_epaper.h"
|
|
||||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9481
|
||||||
#include "ili9481.h"
|
#include "ili9481.h"
|
||||||
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
#include "esp_log.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
|
|
||||||
#include "epdiy_epaper.h"
|
|
||||||
|
|
||||||
#include "epd_driver.h"
|
|
||||||
#include "epd_highlevel.h"
|
|
||||||
|
|
||||||
/**************************************************************************************************
|
|
||||||
* NOTE: This file iis the first version that writes directly on the set_px callback
|
|
||||||
* each pixel into the epaper display buffer. The second version is not epdiy_epaper.cpp
|
|
||||||
* It writes *buf and then it comes as *color_map on the flush callback.
|
|
||||||
* Feel free to experiment with this 2. epdiy_epaper.cpp works better to make a small UX
|
|
||||||
**************************************************************************************************/
|
|
||||||
#define TAG "EPDIY"
|
|
||||||
EpdiyHighlevelState hl;
|
|
||||||
uint16_t flushcalls = 0;
|
|
||||||
uint8_t * framebuffer;
|
|
||||||
uint8_t temperature = 25;
|
|
||||||
|
|
||||||
/* Display initialization routine */
|
|
||||||
void epdiy_init(void)
|
|
||||||
{
|
|
||||||
epd_init(EPD_OPTIONS_DEFAULT);
|
|
||||||
hl = epd_hl_init(EPD_BUILTIN_WAVEFORM);
|
|
||||||
framebuffer = epd_hl_get_framebuffer(&hl);
|
|
||||||
epd_poweron();
|
|
||||||
//Clear all always in init?
|
|
||||||
//epd_fullclear(&hl, temperature);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t xo = 0;
|
|
||||||
uint16_t yo = 0;
|
|
||||||
|
|
||||||
/* Required by LVGL */
|
|
||||||
void epdiy_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
|
||||||
{
|
|
||||||
++flushcalls;
|
|
||||||
xo = area->x1;
|
|
||||||
yo = area->y1;
|
|
||||||
uint16_t w = lv_area_get_width(area);
|
|
||||||
uint16_t h = lv_area_get_height(area);
|
|
||||||
|
|
||||||
EpdRect update_area = {
|
|
||||||
.x = xo,
|
|
||||||
.y = yo,
|
|
||||||
.width = w,
|
|
||||||
.height = h,
|
|
||||||
};
|
|
||||||
|
|
||||||
epd_hl_update_area(&hl, MODE_GC16, temperature, update_area); //update_area
|
|
||||||
|
|
||||||
printf("epdiy_flush %d x:%d y:%d w:%d h:%d\n", flushcalls,xo,yo,w,h);
|
|
||||||
/* Inform the graphics library that you are ready with the flushing */
|
|
||||||
lv_disp_flush_ready(drv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called for each pixel. Designed with the idea to fill the buffer directly, not to set each pixel, see:
|
|
||||||
* https://forum.lvgl.io/t/lvgl-port-to-be-used-with-epaper-displays/5630/3
|
|
||||||
*/
|
|
||||||
void epdiy_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t* buf,
|
|
||||||
lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
|
||||||
lv_color_t color, lv_opa_t opa)
|
|
||||||
{
|
|
||||||
// Debug where x y is printed, not all otherwise is too much Serial
|
|
||||||
/* if ((int16_t)y%10==0 && flushcalls>0){
|
|
||||||
if ((int16_t)x%2==0){
|
|
||||||
printf("x%d y%d\n", (int16_t)x, (int16_t)y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Test using RGB232
|
|
||||||
int16_t epd_color = 255;
|
|
||||||
if ((int16_t)color.full<250) {
|
|
||||||
epd_color = (int16_t)color.full/3;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t x1 = (int16_t)x;
|
|
||||||
int16_t y1 = (int16_t)y;
|
|
||||||
|
|
||||||
//Instead of using epd_draw_pixel: Set pixel directly in buffer
|
|
||||||
//epd_draw_pixel(x1, y1, epd_color, framebuffer);
|
|
||||||
uint8_t *buf_ptr = &framebuffer[y1 * buf_w / 2 + x1 / 2];
|
|
||||||
if (x % 2) {
|
|
||||||
*buf_ptr = (*buf_ptr & 0x0F) | (epd_color & 0xF0);
|
|
||||||
} else {
|
|
||||||
*buf_ptr = (*buf_ptr & 0xF0) | (epd_color >> 4);
|
|
||||||
}
|
|
||||||
}
|
|
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…
Reference in a new issue