From a387e799e14926bf2bff931f551afdec7a019165 Mon Sep 17 00:00:00 2001 From: C47D Date: Mon, 7 Jun 2021 21:57:00 -0500 Subject: [PATCH 01/27] Print LV_HOR_RES_MAX and LV_VER_RES_MAX only when using LVGL v7 or below --- lvgl_helpers.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lvgl_helpers.c b/lvgl_helpers.c index 4125330..2a904b1 100644 --- a/lvgl_helpers.c +++ b/lvgl_helpers.c @@ -53,7 +53,12 @@ /* Interface and driver initialization */ void lvgl_driver_init(void) { + /* Since LVGL v8 LV_HOR_RES_MAX and LV_VER_RES_MAX are not defined, so + * print it only if they are defined. */ +#if (LVGL_VERSION_MAJOR < 8) ESP_LOGI(TAG, "Display hor size: %d, ver size: %d", LV_HOR_RES_MAX, LV_VER_RES_MAX); +#endif + ESP_LOGI(TAG, "Display buffer size: %d", DISP_BUF_SIZE); #if defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) From 8b65d3547cee38e765a0580d4957c9dd9aa5b7c6 Mon Sep 17 00:00:00 2001 From: C47D Date: Mon, 7 Jun 2021 22:00:17 -0500 Subject: [PATCH 02/27] Fix path when using LVGL v8 --- lvgl_helpers.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lvgl_helpers.c b/lvgl_helpers.c index 2a904b1..5cc82c0 100644 --- a/lvgl_helpers.c +++ b/lvgl_helpers.c @@ -19,9 +19,17 @@ #include "driver/i2c.h" #ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "src/lv_core/lv_refr.h" +#if (LVGL_VERSION_MAJOR < 8) + #include "src/lv_core/lv_refr.h" #else -#include "lvgl/src/lv_core/lv_refr.h" + #include "src/core/lv_refr.h" +#endif +#else +#if (LVGL_VERSION_MAJOR < 8) + #include "lvgl/src/lv_core/lv_refr.h" +#else + #include "lvgl/src/core/lv_refr.h" +#endif #endif /********************* From 1af29975e95fb66b1bf7f32b0080f83a017e4657 Mon Sep 17 00:00:00 2001 From: C47D Date: Tue, 8 Jun 2021 10:26:03 -0500 Subject: [PATCH 03/27] Add support for ESP32C3 SPI hosts --- lvgl_helpers.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lvgl_helpers.c b/lvgl_helpers.c index 5cc82c0..41f0213 100644 --- a/lvgl_helpers.c +++ b/lvgl_helpers.c @@ -227,6 +227,13 @@ bool lvgl_spi_driver_init(int host, const char *spi_names[] = { "SPI_HOST", "", "" }; +#elif defined (CONFIG_IDF_TARGET_ESP32C3) + assert((SPI1_HOST <= host) && (SPI3_HOST >= host)); + const char *spi_names[] = { + "SPI1_HOST", "SPI2_HOST", "SPI3_HOST" + }; +#else +#error "Target chip not selected" #endif ESP_LOGI(TAG, "Configuring SPI host %s (%d)", spi_names[host], host); From 696b6ff46328e66783cbf4f120b2d9a53a43dcd6 Mon Sep 17 00:00:00 2001 From: C47D Date: Thu, 10 Jun 2021 22:22:44 -0500 Subject: [PATCH 04/27] lvgl_helpers: Set spi dma channel to SPI_DMA_CH_AUTO when using ESP32C3 --- lvgl_helpers.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lvgl_helpers.c b/lvgl_helpers.c index 41f0213..56c9183 100644 --- a/lvgl_helpers.c +++ b/lvgl_helpers.c @@ -217,21 +217,29 @@ bool lvgl_spi_driver_init(int host, int dma_channel, int quadwp_pin, int quadhd_pin) { + spi_dma_chan_t dma_chan = SPI_DMA_DISABLED; + #if defined (CONFIG_IDF_TARGET_ESP32) assert((SPI_HOST <= host) && (VSPI_HOST >= host)); const char *spi_names[] = { "SPI_HOST", "HSPI_HOST", "VSPI_HOST" }; + + dma_chan = dma_channel; #elif defined (CONFIG_IDF_TARGET_ESP32S2) assert((SPI_HOST <= host) && (HSPI_HOST >= host)); const char *spi_names[] = { "SPI_HOST", "", "" }; + + dma_chan = dma_channel; #elif defined (CONFIG_IDF_TARGET_ESP32C3) assert((SPI1_HOST <= host) && (SPI3_HOST >= host)); const char *spi_names[] = { "SPI1_HOST", "SPI2_HOST", "SPI3_HOST" }; + + dma_chan = SPI_DMA_CH_AUTO; #else #error "Target chip not selected" #endif @@ -252,7 +260,7 @@ bool lvgl_spi_driver_init(int host, }; ESP_LOGI(TAG, "Initializing SPI bus..."); - esp_err_t ret = spi_bus_initialize(host, &buscfg, dma_channel); + esp_err_t ret = spi_bus_initialize(host, &buscfg, dma_chan); assert(ret == ESP_OK); return ESP_OK != ret; From d09fd59869ef0c33c0fa4a960c45374035e88000 Mon Sep 17 00:00:00 2001 From: C47D Date: Thu, 10 Jun 2021 22:31:09 -0500 Subject: [PATCH 05/27] Add ESP32C3 support on Kconfig files --- lvgl_tft/Kconfig | 15 ++++++++++++++- lvgl_touch/Kconfig | 11 +++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lvgl_tft/Kconfig b/lvgl_tft/Kconfig index b622146..7059a6c 100644 --- a/lvgl_tft/Kconfig +++ b/lvgl_tft/Kconfig @@ -772,6 +772,7 @@ menu "LVGL TFT Display controller" int "GPIO for MOSI (Master Out Slave In)" if LV_TFT_DISPLAY_PROTOCOL_SPI range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 23 if LV_PREDEFINED_DISPLAY_WROVER4 default 23 if LV_PREDEFINED_DISPLAY_ATAG @@ -801,6 +802,7 @@ menu "LVGL TFT Display controller" depends on LV_DISPLAY_USE_SPI_MISO range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 19 if LV_PREDEFINED_PINS_TKOALA default 38 if LV_PREDEFINED_DISPLAY_M5CORE2 @@ -823,6 +825,7 @@ menu "LVGL TFT Display controller" depends on LV_TFT_DISPLAY_SPI_TRANS_MODE_QIO range -1 39 if IDF_TARGET_ESP32 range -1 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 22 if LV_PREDEFINED_PINS_TKOALA && LV_TFT_DISPLAY_SPI_TRANS_MODE_QIO default -1 @@ -834,6 +837,7 @@ menu "LVGL TFT Display controller" depends on LV_TFT_DISPLAY_SPI_TRANS_MODE_QIO range -1 39 if IDF_TARGET_ESP32 range -1 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 21 if LV_PREDEFINED_PINS_TKOALA && LV_TFT_DISPLAY_SPI_TRANS_MODE_QIO default -1 @@ -844,6 +848,7 @@ menu "LVGL TFT Display controller" int "GPIO for CLK (SCK / Serial Clock)" if LV_TFT_DISPLAY_PROTOCOL_SPI range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 18 if LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_M5STICK default 18 if LV_PREDEFINED_DISPLAY_M5CORE2 @@ -872,6 +877,7 @@ menu "LVGL TFT Display controller" depends on LV_DISPLAY_USE_SPI_CS range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 5 if LV_PREDEFINED_PINS_38V1 default 14 if LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_M5STICK @@ -900,6 +906,7 @@ menu "LVGL TFT Display controller" int "GPIO for DC (Data / Command)" if LV_TFT_DISPLAY_PROTOCOL_SPI range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 depends on LV_DISPLAY_USE_DC default 19 if LV_PREDEFINED_PINS_38V1 @@ -937,6 +944,7 @@ menu "LVGL TFT Display controller" depends on LV_DISP_USE_RST range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 18 if LV_PREDEFINED_PINS_38V1 default 25 if LV_PREDEFINED_PINS_38V4 @@ -958,9 +966,11 @@ menu "LVGL TFT Display controller" int "GPIO for Busy" if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 35 if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D - default 35 + default 35 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 + default 21 if IDF_TARGET_ESP32C3 help Configure the display Busy pin here. @@ -997,6 +1007,7 @@ menu "LVGL TFT Display controller" depends on LV_ENABLE_BACKLIGHT_CONTROL range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 23 if LV_PREDEFINED_PINS_38V1 default 26 if LV_PREDEFINED_PINS_38V4 @@ -1017,6 +1028,7 @@ menu "LVGL TFT Display controller" int "GPIO for I2C SDA" if LV_TFT_DISPLAY_PROTOCOL_I2C range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 5 if LV_PREDEFINED_DISPLAY_WEMOS_LOLIN default 5 @@ -1028,6 +1040,7 @@ menu "LVGL TFT Display controller" int "GPIO for I2C SCL" if LV_TFT_DISPLAY_PROTOCOL_I2C range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 4 if LV_PREDEFINED_DISPLAY_WEMOS_LOLIN default 4 diff --git a/lvgl_touch/Kconfig b/lvgl_touch/Kconfig index edd1dab..7f6e995 100644 --- a/lvgl_touch/Kconfig +++ b/lvgl_touch/Kconfig @@ -98,6 +98,7 @@ menu "LVGL Touch controller" prompt "GPIO for MISO (Master In Slave Out)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 35 if LV_PREDEFINED_PINS_38V1 default 19 @@ -109,6 +110,7 @@ menu "LVGL Touch controller" prompt "GPIO for MOSI (Master Out Slave In)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 32 if LV_PREDEFINED_PINS_38V1 default 23 @@ -119,6 +121,7 @@ menu "LVGL Touch controller" int "GPIO for CLK (SCK / Serial Clock)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 26 if LV_PREDEFINED_PINS_38V1 default 18 @@ -139,6 +142,7 @@ menu "LVGL Touch controller" int "GPIO for IRQ (Interrupt Request)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 27 if LV_PREDEFINED_PINS_38V4 default 25 @@ -211,6 +215,7 @@ menu "LVGL Touch controller" prompt "GPIO for SDA (I2C)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 21 help @@ -220,6 +225,7 @@ menu "LVGL Touch controller" int "GPIO for clock signal SCL (I2C)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 22 help @@ -254,6 +260,7 @@ menu "LVGL Touch controller" prompt "GPIO for MISO (Master In Slave Out)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 35 if LV_PREDEFINED_PINS_38V1 default 19 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING @@ -263,10 +270,12 @@ menu "LVGL Touch controller" Configure the touchpanel MISO pin here. config LV_TOUCH_SPI_MOSI + # TODO Fix default for ESP32C3 int prompt "GPIO for MOSI (Master Out Slave In)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 32 if LV_PREDEFINED_PINS_38V1 default 18 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING @@ -279,6 +288,7 @@ menu "LVGL Touch controller" int "GPIO for CLK (SCK / Serial Clock)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 26 if LV_PREDEFINED_PINS_38V1 default 5 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING @@ -290,6 +300,7 @@ menu "LVGL Touch controller" int "GPIO for CS (Slave Select)" range 0 39 if IDF_TARGET_ESP32 range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 default 33 if LV_PREDEFINED_PINS_38V1 default 32 if LV_PREDEFINED_DISPLAY_ADA_FEATHERWING From d379a4e8514d041dbeb1c146f2ae0a9a8142c367 Mon Sep 17 00:00:00 2001 From: C47D Date: Thu, 10 Jun 2021 22:36:01 -0500 Subject: [PATCH 06/27] Handle ESP32C3 when using ESP32C3 --- lvgl_spi_conf.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lvgl_spi_conf.h b/lvgl_spi_conf.h index b5e7901..240090d 100644 --- a/lvgl_spi_conf.h +++ b/lvgl_spi_conf.h @@ -65,11 +65,15 @@ extern "C" { #define ENABLE_TOUCH_INPUT CONFIG_LV_ENABLE_TOUCH #if defined (CONFIG_LV_TFT_DISPLAY_SPI_HSPI) -#define TFT_SPI_HOST HSPI_HOST +#if defined (CONFIG_IDF_TARGET_ESP32C3) +#define TFT_SPI_HOST SPI2_HOST +#else +#define TFT_SPI_HOST HSPI_HOST +#endif #elif defined (CONFIG_LV_TFT_DISPLAY_SPI_VSPI) -#define TFT_SPI_HOST VSPI_HOST +#define TFT_SPI_HOST VSPI_HOST #elif defined (CONFIG_LV_TFT_DISPLAY_SPI_FSPI) -#define TFT_SPI_HOST FSPI_HOST +#define TFT_SPI_HOST FSPI_HOST #endif #if defined (CONFIG_LV_TFT_DISPLAY_SPI_HALF_DUPLEX) From f726311525474489a409f4cdb1a6a7ae315f2c05 Mon Sep 17 00:00:00 2001 From: C47D Date: Thu, 10 Jun 2021 22:49:56 -0500 Subject: [PATCH 07/27] Indev: Add support for GT911 touch driver by @dastarling --- CMakeLists.txt | 2 ++ lvgl_touch/Kconfig | 49 +++++++++++++++++++++++++++++++++++++++ lvgl_touch/touch_driver.c | 4 ++++ lvgl_touch/touch_driver.h | 2 ++ 4 files changed, 57 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5832233..10262c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,8 @@ if(CONFIG_LV_TOUCH_CONTROLLER) list(APPEND SOURCES "lvgl_touch/FT81x.c") elseif(CONFIG_LV_TOUCH_CONTROLLER_RA8875) list(APPEND SOURCES "lvgl_touch/ra8875_touch.c") + elseif(CONFIG_LV_TOUCH_CONTROLLER_GT911) + list(APPEND SOURCES "lvgl_touch/gt911.c") endif() if(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) diff --git a/lvgl_touch/Kconfig b/lvgl_touch/Kconfig index 7f6e995..9942e0a 100644 --- a/lvgl_touch/Kconfig +++ b/lvgl_touch/Kconfig @@ -9,6 +9,7 @@ menu "LVGL Touch controller" default 4 if LV_TOUCH_CONTROLLER_ADCRAW default 5 if LV_TOUCH_CONTROLLER_FT81X default 6 if LV_TOUCH_CONTROLLER_RA8875 + default 7 if LV_TOUCH_CONTROLLER_GT911 choice prompt "Select a touch panel controller model." @@ -36,6 +37,9 @@ menu "LVGL Touch controller" config LV_TOUCH_CONTROLLER_RA8875 select LV_TOUCH_DRIVER_DISPLAY bool "RA8875" + config LV_TOUCH_CONTROLLER_GT911 + select LV_TOUCH_DRIVER_PROTOCOL_I2C + bool "GT911" endchoice config LV_TOUCH_DRIVER_PROTOCOL_SPI @@ -498,5 +502,50 @@ menu "LVGL Touch controller" default y endmenu + + menu "Touchpanel (GT911) Pin Assignments" + depends on LV_TOUCH_CONTROLLER_GT911 + + config LV_TOUCH_I2C_SDA + int + prompt "GPIO for SDA (I2C)" + range 0 39 if IDF_TARGET_ESP32 + range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 + + default 2 + help + Configure the I2C touchpanel SDA pin here. + + config LV_TOUCH_I2C_SCL + int "GPIO for clock signal SCL (I2C)" + range 0 39 if IDF_TARGET_ESP32 + range 0 43 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 + + default 3 + help + Configure the I2C touchpanel SCL pin here. + endmenu + + menu "Touchpanel Configuration (GT911)" + depends on LV_TOUCH_CONTROLLER_GT911 + + config LV_GT911_SWAPXY + bool + prompt "Swap X with Y coordinate." + default y + + config LV_GT911_INVERT_X + bool + prompt "Invert X coordinate value." + default n + + config LV_GT911_INVERT_Y + bool + prompt "Invert Y coordinate value." + default y + + endmenu endmenu diff --git a/lvgl_touch/touch_driver.c b/lvgl_touch/touch_driver.c index b0aed88..6a7afb3 100644 --- a/lvgl_touch/touch_driver.c +++ b/lvgl_touch/touch_driver.c @@ -21,6 +21,8 @@ void touch_driver_init(void) /* nothing to do */ #elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875) ra8875_touch_init(); +#elif defined (CONFIG_LV_TOUCH_CONTROLLER_GT911) + gt911_init(GT911_I2C_SLAVE_ADDR); #endif } @@ -40,6 +42,8 @@ bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data) res = FT81x_read(drv, data); #elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875) res = ra8875_touch_read(drv, data); +#elif defined (CONFIG_LV_TOUCH_CONTROLLER_GT911) + res = gt911_read(drv, data); #endif return res; diff --git a/lvgl_touch/touch_driver.h b/lvgl_touch/touch_driver.h index bc92f4f..44378db 100644 --- a/lvgl_touch/touch_driver.h +++ b/lvgl_touch/touch_driver.h @@ -32,6 +32,8 @@ extern "C" { #include "FT81x.h" #elif defined (CONFIG_LV_TOUCH_CONTROLLER_RA8875) #include "ra8875_touch.h" +#elif defined (CONFIG_LV_TOUCH_CONTROLLER_GT911) +#include "gt911.h" #endif /********************* From 0d32432f4c05a6294f03532e7d7d94c10c436f81 Mon Sep 17 00:00:00 2001 From: C47D Date: Sun, 13 Jun 2021 15:06:22 -0500 Subject: [PATCH 08/27] touch driver: Add LVGL v8 compatibility --- lvgl_touch/gt911.c | 168 ++++++++++++++++++++++++++++++++++++++ lvgl_touch/gt911.h | 94 +++++++++++++++++++++ lvgl_touch/touch_driver.c | 8 ++ lvgl_touch/touch_driver.h | 5 ++ 4 files changed, 275 insertions(+) create mode 100644 lvgl_touch/gt911.c create mode 100644 lvgl_touch/gt911.h diff --git a/lvgl_touch/gt911.c b/lvgl_touch/gt911.c new file mode 100644 index 0000000..e6cb972 --- /dev/null +++ b/lvgl_touch/gt911.c @@ -0,0 +1,168 @@ +/* +* Copyright © 2021 Sturnus Inc. + +* 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 +#include +#ifdef LV_LVGL_H_INCLUDE_SIMPLE +#include +#else +#include +#endif +#include "gt911.h" +#include "tp_i2c.h" +#include "../lvgl_i2c_conf.h" + +#define TAG "GT911" + +gt911_status_t gt911_status; + +//TODO: handle multibyte read and refactor to just one read transaction +esp_err_t gt911_i2c_read(uint8_t slave_addr, uint16_t register_addr, uint8_t *data_buf, uint8_t len) { + 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 >> 8), I2C_MASTER_ACK); + i2c_master_write_byte(i2c_cmd, (register_addr & 0xFF), 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(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(i2c_cmd); + return ret; +} + +esp_err_t gt911_i2c_write8(uint8_t slave_addr, uint16_t register_addr, uint8_t data) { + 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 >> 8), I2C_MASTER_ACK); + i2c_master_write_byte(i2c_cmd, (register_addr & 0xFF), I2C_MASTER_ACK); + i2c_master_write_byte(i2c_cmd, data, I2C_MASTER_ACK); + i2c_master_stop(i2c_cmd); + esp_err_t ret = i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(i2c_cmd); + return ret; +} + +/** + * @brief Initialize for GT911 communication via I2C + * @param dev_addr: Device address on communication Bus (I2C slave address of GT911). + * @retval None + */ +void gt911_init(uint8_t dev_addr) { + if (!gt911_status.inited) { + gt911_status.i2c_dev_addr = dev_addr; + uint8_t data_buf; + esp_err_t ret; + + ESP_LOGI(TAG, "Checking for GT911 Touch Controller"); + if ((ret = gt911_i2c_read(dev_addr, GT911_PRODUCT_ID1, &data_buf, 1) != ESP_OK)) { + ESP_LOGE(TAG, "Error reading from device: %s", + esp_err_to_name(ret)); // Only show error the first time + return; + } + + // Read 4 bytes for Product ID in ASCII + for (int i = 0; i < GT911_PRODUCT_ID_LEN; i++) { + gt911_i2c_read(dev_addr, (GT911_PRODUCT_ID1 + i), (uint8_t *)&(gt911_status.product_id[i]), 1); + } + ESP_LOGI(TAG, "\tProduct ID: %s", gt911_status.product_id); + + gt911_i2c_read(dev_addr, GT911_VENDOR_ID, &data_buf, 1); + ESP_LOGI(TAG, "\tVendor ID: 0x%02x", data_buf); + + gt911_i2c_read(dev_addr, GT911_X_COORD_RES_L, &data_buf, 1); + gt911_status.max_x_coord = data_buf; + gt911_i2c_read(dev_addr, GT911_X_COORD_RES_H, &data_buf, 1); + gt911_status.max_x_coord |= ((uint16_t)data_buf << 8); + ESP_LOGI(TAG, "\tX Resolution: %d", gt911_status.max_x_coord); + + gt911_i2c_read(dev_addr, GT911_Y_COORD_RES_L, &data_buf, 1); + gt911_status.max_y_coord = data_buf; + gt911_i2c_read(dev_addr, GT911_Y_COORD_RES_H, &data_buf, 1); + gt911_status.max_y_coord |= ((uint16_t)data_buf << 8); + ESP_LOGI(TAG, "\tY Resolution: %d", gt911_status.max_y_coord); + gt911_status.inited = true; + } +} + +/** + * @brief Get the touch screen X and Y positions values. Ignores multi touch + * @param drv: + * @param data: Store data here + * @retval Always false + */ +bool gt911_read(lv_indev_drv_t *drv, lv_indev_data_t *data) { + 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 + uint8_t data_buf; + uint8_t status_reg; + + gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_STATUS_REG, &status_reg, 1); +// ESP_LOGI(TAG, "\tstatus: 0x%02x", status_reg); + touch_pnt_cnt = status_reg & 0x0F; + if ((status_reg & 0x80) || (touch_pnt_cnt < 6)) { + //Reset Status Reg Value + gt911_i2c_write8(gt911_status.i2c_dev_addr, GT911_STATUS_REG, 0x00); + } + 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; + } + +// gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_TRACK_ID1, &data_buf, 1); +// ESP_LOGI(TAG, "\ttrack_id: %d", data_buf); + + gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_X_COORD_L, &data_buf, 1); + last_x = data_buf; + gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_X_COORD_H, &data_buf, 1); + last_x |= ((uint16_t)data_buf << 8); + + gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_Y_COORD_L, &data_buf, 1); + last_y = data_buf; + gt911_i2c_read(gt911_status.i2c_dev_addr, GT911_PT1_Y_COORD_H, &data_buf, 1); + last_y |= ((uint16_t)data_buf << 8); + +#if CONFIG_LV_GT911_INVERT_X + last_x = gt911_status.max_x_coord - last_x; +#endif +#if CONFIG_LV_GT911_INVERT_Y + last_y = gt911_status.max_y_coord - last_y; +#endif +#if CONFIG_LV_GT911_SWAPXY + int16_t swap_buf = last_x; + last_x = last_y; + last_y = swap_buf; +#endif + data->point.x = last_x; + data->point.y = last_y; + data->state = LV_INDEV_STATE_PR; + ESP_LOGI(TAG, "X=%u Y=%u", data->point.x, data->point.y); + ESP_LOGV(TAG, "X=%u Y=%u", data->point.x, data->point.y); + return false; +} diff --git a/lvgl_touch/gt911.h b/lvgl_touch/gt911.h new file mode 100644 index 0000000..6a110bd --- /dev/null +++ b/lvgl_touch/gt911.h @@ -0,0 +1,94 @@ +#ifndef __GT911_H +/* +* Copyright © 2021 Sturnus Inc. + +* 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 __GT911_H + +#include +#include +#ifdef LV_LVGL_H_INCLUDE_SIMPLE +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define GT911_I2C_SLAVE_ADDR 0x5D + +#define GT911_PRODUCT_ID_LEN 4 + +/* Register Map of GT911 */ +#define GT911_PRODUCT_ID1 0x8140 +#define GT911_PRODUCT_ID2 0x8141 +#define GT911_PRODUCT_ID3 0x8142 +#define GT911_PRODUCT_ID4 0x8143 +#define GT911_FIRMWARE_VER_L 0x8144 +#define GT911_FIRMWARE_VER_H 0x8145 +#define GT911_X_COORD_RES_L 0x8146 +#define GT911_X_COORD_RES_H 0x8147 +#define GT911_Y_COORD_RES_L 0x8148 +#define GT911_Y_COORD_RES_H 0x8149 +#define GT911_VENDOR_ID 0x814A + +#define GT911_STATUS_REG 0x814E +#define GT911_STATUS_REG_BUF 0x80 +#define GT911_STATUS_REG_LARGE 0x40 +#define GT911_STATUS_REG_PROX_VALID 0x20 +#define GT911_STATUS_REG_HAVEKEY 0x10 +#define GT911_STATUS_REG_PT_MASK 0x0F + +#define GT911_TRACK_ID1 0x814F +#define GT911_PT1_X_COORD_L 0x8150 +#define GT911_PT1_X_COORD_H 0x8151 +#define GT911_PT1_Y_COORD_L 0x8152 +#define GT911_PT1_Y_COORD_H 0x8153 +#define GT911_PT1_X_SIZE_L 0x8154 +#define GT911_PT1_X_SIZE_H 0x8155 + +typedef struct { + bool inited; + char product_id[GT911_PRODUCT_ID_LEN]; + uint16_t max_x_coord; + uint16_t max_y_coord; + uint8_t i2c_dev_addr; +} gt911_status_t; + +/** + * @brief Initialize for GT911 communication via I2C + * @param dev_addr: Device address on communication Bus (I2C slave address of GT911). + * @retval None + */ +void gt911_init(uint8_t dev_addr); + +/** + * @brief Get the touch screen X and Y positions values. Ignores multi touch + * @param drv: + * @param data: Store data here + * @retval Always false + */ +bool gt911_read(lv_indev_drv_t *drv, lv_indev_data_t *data); + +#ifdef __cplusplus +} +#endif +#endif /* __GT911_H */ diff --git a/lvgl_touch/touch_driver.c b/lvgl_touch/touch_driver.c index 6a7afb3..1212543 100644 --- a/lvgl_touch/touch_driver.c +++ b/lvgl_touch/touch_driver.c @@ -26,7 +26,11 @@ void touch_driver_init(void) #endif } +#if LVGL_VERSION_MAJOR >= 8 +void touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data) +#else bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data) +#endif { bool res = false; @@ -46,6 +50,10 @@ bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data) res = gt911_read(drv, data); #endif +#if LVGL_VERSION_MAJOR >= 8 + data->continue_reading = res; +#else return res; +#endif } diff --git a/lvgl_touch/touch_driver.h b/lvgl_touch/touch_driver.h index 44378db..0d014e2 100644 --- a/lvgl_touch/touch_driver.h +++ b/lvgl_touch/touch_driver.h @@ -44,7 +44,12 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ void touch_driver_init(void); + +#if LVGL_VERSION_MAJOR >= 8 +void touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data); +#else bool touch_driver_read(lv_indev_drv_t *drv, lv_indev_data_t *data); +#endif #ifdef __cplusplus } /* extern "C" */ From b9cccc342fa509c0dedec75e863d572baaa17b25 Mon Sep 17 00:00:00 2001 From: C47D Date: Tue, 15 Jun 2021 21:01:36 -0500 Subject: [PATCH 09/27] Include lv_refr more easily --- lvgl_helpers.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lvgl_helpers.c b/lvgl_helpers.c index 56c9183..a215c43 100644 --- a/lvgl_helpers.c +++ b/lvgl_helpers.c @@ -19,17 +19,9 @@ #include "driver/i2c.h" #ifdef LV_LVGL_H_INCLUDE_SIMPLE -#if (LVGL_VERSION_MAJOR < 8) - #include "src/lv_core/lv_refr.h" +#include "lvgl.h" #else - #include "src/core/lv_refr.h" -#endif -#else -#if (LVGL_VERSION_MAJOR < 8) - #include "lvgl/src/lv_core/lv_refr.h" -#else - #include "lvgl/src/core/lv_refr.h" -#endif +#include "lvgl/lvgl.h" #endif /********************* From b70d2dc151db61ec44cb5b7a2a043917a1d181a9 Mon Sep 17 00:00:00 2001 From: C47D Date: Tue, 22 Jun 2021 13:05:58 -0500 Subject: [PATCH 10/27] lvgl_helpers: Fix compilation error when using ESP-IDF v4.3 or below --- lvgl_helpers.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lvgl_helpers.c b/lvgl_helpers.c index a215c43..2e78fef 100644 --- a/lvgl_helpers.c +++ b/lvgl_helpers.c @@ -202,14 +202,21 @@ bool lvgl_i2c_driver_init(int port, int sda_pin, int scl_pin, int speed_hz) return ESP_OK != err; } -/* Initialize spi bus master */ +/* Initialize spi bus master + * + * NOTE: dma_chan type and value changed to int instead of spi_dma_chan_t + * for backwards compatibility with ESP-IDF versions prior v4.3. + * + * We could use the ESP_IDF_VERSION_VAL macro available in the "esp_idf_version.h" + * header available since ESP-IDF v4. + */ bool lvgl_spi_driver_init(int host, int miso_pin, int mosi_pin, int sclk_pin, int max_transfer_sz, int dma_channel, int quadwp_pin, int quadhd_pin) { - spi_dma_chan_t dma_chan = SPI_DMA_DISABLED; + int dma_chan = 0 /* SPI_DMA_DISABLED */; #if defined (CONFIG_IDF_TARGET_ESP32) assert((SPI_HOST <= host) && (VSPI_HOST >= host)); @@ -231,7 +238,7 @@ bool lvgl_spi_driver_init(int host, "SPI1_HOST", "SPI2_HOST", "SPI3_HOST" }; - dma_chan = SPI_DMA_CH_AUTO; + dma_chan = 3 /* SPI_DMA_CH_AUTO */; #else #error "Target chip not selected" #endif From 55dd527e1074f90b9216507b8fe4d28817c23420 Mon Sep 17 00:00:00 2001 From: Justin Smestad Date: Sat, 26 Jun 2021 17:44:59 -0600 Subject: [PATCH 11/27] Update KConfig to remove LV_ prefix on orientation checks --- lvgl_tft/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lvgl_tft/Kconfig b/lvgl_tft/Kconfig index 7059a6c..7c1bd60 100644 --- a/lvgl_tft/Kconfig +++ b/lvgl_tft/Kconfig @@ -222,15 +222,15 @@ menu "LVGL TFT Display controller" config LV_TFT_DISPLAY_X_OFFSET depends on LV_TFT_DISPLAY_OFFSETS int - default 40 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) - default 53 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED) + default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) + default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED) default 0 config LV_TFT_DISPLAY_Y_OFFSET depends on LV_TFT_DISPLAY_OFFSETS int - default 53 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) - default 40 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED) + default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) + default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED) default 0 From 19087aeb06fb18487c45ef063ff12d2cc3871656 Mon Sep 17 00:00:00 2001 From: Justin Smestad Date: Sat, 26 Jun 2021 17:50:28 -0600 Subject: [PATCH 12/27] Remove SPI guard for TTGO configuration Fixes remaining part of #50 --- lvgl_tft/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lvgl_tft/Kconfig b/lvgl_tft/Kconfig index 7c1bd60..709ca5a 100644 --- a/lvgl_tft/Kconfig +++ b/lvgl_tft/Kconfig @@ -413,7 +413,7 @@ menu "LVGL TFT Display controller" config LV_FT81X_CONFIG_EVE_EVE2_50G bool "EVE_EVE2_50G" config LV_FT81X_CONFIG_EVE_EVE2_70 - bool "EVE_EVE2_70" + bool "EVE_EVE2_70"/ config LV_FT81X_CONFIG_EVE_EVE2_70G bool "EVE_EVE2_70G" config LV_FT81X_CONFIG_EVE_EVE3_35 @@ -459,8 +459,7 @@ menu "LVGL TFT Display controller" endchoice choice - prompt "TFT SPI Bus." if LV_TFT_DISPLAY_PROTOCOL_SPI && \ - !LV_PREDEFINED_DISPLAY_TTGO + prompt "TFT SPI Bus." if LV_TFT_DISPLAY_PROTOCOL_SPI default LV_TFT_DISPLAY_SPI_VSPI if LV_PREDEFINED_DISPLAY_TTGO && \ !IDF_TARGET_ESP32S2 default LV_TFT_DISPLAY_SPI_FSPI if IDF_TARGET_ESP32S2 From 82ba726199723b53c7aef30bb02fc01d28c676c0 Mon Sep 17 00:00:00 2001 From: Justin Smestad Date: Sat, 26 Jun 2021 17:50:56 -0600 Subject: [PATCH 13/27] Revert lvgl_tft/Kconfig --- lvgl_tft/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lvgl_tft/Kconfig b/lvgl_tft/Kconfig index 709ca5a..580ca54 100644 --- a/lvgl_tft/Kconfig +++ b/lvgl_tft/Kconfig @@ -413,7 +413,7 @@ menu "LVGL TFT Display controller" config LV_FT81X_CONFIG_EVE_EVE2_50G bool "EVE_EVE2_50G" config LV_FT81X_CONFIG_EVE_EVE2_70 - bool "EVE_EVE2_70"/ + bool "EVE_EVE2_70" config LV_FT81X_CONFIG_EVE_EVE2_70G bool "EVE_EVE2_70G" config LV_FT81X_CONFIG_EVE_EVE3_35 From 613787b340793716b340db68470cfda1d48fd110 Mon Sep 17 00:00:00 2001 From: Debian Date: Sun, 27 Jun 2021 11:50:19 -0500 Subject: [PATCH 14/27] enable the X and Y offset options whith TTGO TDisplay --- lvgl_tft/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lvgl_tft/Kconfig b/lvgl_tft/Kconfig index 580ca54..0535580 100644 --- a/lvgl_tft/Kconfig +++ b/lvgl_tft/Kconfig @@ -221,14 +221,14 @@ menu "LVGL TFT Display controller" config LV_TFT_DISPLAY_X_OFFSET depends on LV_TFT_DISPLAY_OFFSETS - int + int "X offset" default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED) default 0 config LV_TFT_DISPLAY_Y_OFFSET depends on LV_TFT_DISPLAY_OFFSETS - int + int "Y offset" default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED) default 0 From fa86e1d0926c3bf531442354c8d84cb6f07c330b Mon Sep 17 00:00:00 2001 From: C47D Date: Wed, 30 Jun 2021 23:02:00 -0500 Subject: [PATCH 15/27] Remove & operator when passing display driver to lv_disp_flush_ready Closes #81 --- lvgl_tft/disp_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lvgl_tft/disp_spi.c b/lvgl_tft/disp_spi.c index 0e4e548..00e91a6 100644 --- a/lvgl_tft/disp_spi.c +++ b/lvgl_tft/disp_spi.c @@ -310,7 +310,7 @@ static void IRAM_ATTR spi_ready(spi_transaction_t *trans) disp = lv_refr_get_disp_refreshing(); #endif - lv_disp_flush_ready(&disp->driver); + lv_disp_flush_ready(disp->driver); } if (chained_post_cb) { From f32a6f57fc231f4280ec697885ae11c4a9409efe Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Wed, 7 Jul 2021 20:40:15 +0200 Subject: [PATCH 16/27] FT6X36 touch: fixed axis-swap, Kconfig defaults. --- lvgl_touch/Kconfig | 16 ++++++++-------- lvgl_touch/ft6x36.c | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lvgl_touch/Kconfig b/lvgl_touch/Kconfig index 9942e0a..d4b71fc 100644 --- a/lvgl_touch/Kconfig +++ b/lvgl_touch/Kconfig @@ -239,20 +239,20 @@ menu "LVGL Touch controller" 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_SWAPXY + bool + prompt "Swap X with Y coordinate." + default n 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 + config LV_FT6X36_INVERT_Y + bool + prompt "Invert Y coordinate value." + default n endmenu diff --git a/lvgl_touch/ft6x36.c b/lvgl_touch/ft6x36.c index 6e67d29..a4d74ef 100644 --- a/lvgl_touch/ft6x36.c +++ b/lvgl_touch/ft6x36.c @@ -182,20 +182,20 @@ bool ft6x36_read(lv_indev_drv_t *drv, lv_indev_data_t *data) { 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 +#if CONFIG_LV_FT6X36_SWAPXY + int16_t swap_buf = last_x; + last_x = last_y; + last_y = swap_buf; #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); + ESP_LOGD(TAG, "X=%u Y=%u", data->point.x, data->point.y); return false; } From e52112376f614f9a910e9c44ea51856855ef33b1 Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Thu, 8 Jul 2021 11:04:07 +0200 Subject: [PATCH 17/27] Replace allLVGL driver I2C code with I2C Manager For discussion see #70 --- CMakeLists.txt | 8 +- Kconfig | 11 +- README.md | 20 ++- component.mk | 1 - i2c_manager/Kconfig | 116 ++++++++++++ i2c_manager/README.md | 71 ++++++++ i2c_manager/i2c_manager.c | 368 ++++++++++++++++++++++++++++++++++++++ i2c_manager/i2c_manager.h | 76 ++++++++ lvgl_helpers.c | 86 ++------- lvgl_helpers.h | 4 +- lvgl_i2c_conf.h | 116 ------------ lvgl_tft/Kconfig | 120 +++++-------- lvgl_tft/ili9341.h | 3 +- lvgl_tft/ssd1306.c | 46 ++--- lvgl_tft/ssd1306.h | 2 - lvgl_tft/st7735s.c | 87 ++++----- lvgl_tft/st7735s.h | 3 - lvgl_touch/Kconfig | 145 ++++++--------- lvgl_touch/ft6x36.c | 156 +++++----------- lvgl_touch/ft6x36.h | 22 +-- lvgl_touch/gt911.c | 34 +--- lvgl_touch/touch_driver.c | 1 - lvgl_touch/tp_i2c.c | 43 ----- lvgl_touch/tp_i2c.h | 36 ---- 24 files changed, 896 insertions(+), 679 deletions(-) create mode 100644 i2c_manager/Kconfig create mode 100644 i2c_manager/README.md create mode 100644 i2c_manager/i2c_manager.c create mode 100644 i2c_manager/i2c_manager.h delete mode 100644 lvgl_i2c_conf.h delete mode 100644 lvgl_touch/tp_i2c.c delete mode 100644 lvgl_touch/tp_i2c.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 10262c1..678c894 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,15 +76,17 @@ if(CONFIG_LV_TOUCH_CONTROLLER) if(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) list(APPEND SOURCES "lvgl_touch/tp_spi.c") - elseif(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C) - list(APPEND SOURCES "lvgl_touch/tp_i2c.c") endif() endif() +if(CONFIG_LV_I2C) + list(APPEND SOURCES "i2c_manager/i2c_manager.c") +endif() + idf_component_register(SRCS ${SOURCES} INCLUDE_DIRS ${LVGL_INCLUDE_DIRS} REQUIRES lvgl) - + target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLV_LVGL_H_INCLUDE_SIMPLE") else() diff --git a/Kconfig b/Kconfig index ae11925..42c3c66 100644 --- a/Kconfig +++ b/Kconfig @@ -1,2 +1,9 @@ -rsource "lvgl_tft/Kconfig" -rsource "lvgl_touch/Kconfig" +menu "LVGL ESP Drivers" + + rsource "lvgl_tft/Kconfig" + + rsource "lvgl_touch/Kconfig" + + rsource "i2c_manager/Kconfig" + +endmenu diff --git a/README.md b/README.md index 89659a6..1908417 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ For a ready to use ESP32 project take look at the [lv_port_esp32](https://github - [Supported display controllers](#supported-display-controllers) - [Supported indev controllers](#supported-indev-controllers) - [Support for predefined development kits](#support-for-predefined-development-kits) +- [Thread-safe I2C with I2C Manager](#thread-safe-i2c-with-i2c-manager) **NOTE:** You need to set the display horizontal and vertical size, color depth and swap of RGB565 color on the LVGL configuration menuconfig (it's not handled automatically). @@ -35,8 +36,8 @@ swap of RGB565 color on the LVGL configuration menuconfig (it's not handled auto ## Supported indev controllers - XPT2046 -- FT3236 -- other FT6X36 or the FT6206 controllers should work as well (not tested) +- FT3236, FT6X36 +- FT6206 controllers should work as well (not tested) - STMPE610 - FT81x (Single, Dual, and Quad SPI) @@ -52,7 +53,7 @@ and sets the gpio numbers for the interface. |---------------------------|-----------------------|-----------|-----------|-----------| | ESP Wrover Kit v4.1 | ILI9341 | SPI | 240 | 320 | | M5Stack | ILI9341 | SPI | 240 | 320 | -| M5Core2 | ILI9341 | SPI | 240 | 320 | +| M5Stack Core2 | ILI9341 | SPI | 240 | 320 | | M5Stick | SH1107 | SPI | - | - | | M5StickC | ST7735S | SPI | 80 | 160 | | Adafruit 3.5 Featherwing | HX8357 | SPI | 480 | 320 | @@ -65,3 +66,16 @@ and sets the gpio numbers for the interface. **NOTE:** See [Supported display controllers](#supported-display-controllers) for more information on display configuration. **NOTE:** See [Supported indev controllers](#supported-indev-controllers) for more information about indev configuration. + + +## Thread-safe I2C with I2C Manager + +LVGL can use I2C to read from a touch sensor or write to a display, possibly +many times a second. Meanwhile, other tasks may also want to read from i2c +devices on the same bus. I2C using the ESP-IDF is not thread-safe. + +I2C Manager (`i2c_manager`) is a component that will let code in multiple threads +talk to devices on the I2C ports without getting in each other's way. These drivers +use a built-in copy of I2C Manager to talk to the I2C port, but you can also use +the I2C Manager component itself and have others play nice with LVGL and vice-versa. +[Click here](i2c_manager/README.md) for details. diff --git a/component.mk b/component.mk index dbd1105..c01caba 100644 --- a/component.mk +++ b/component.mk @@ -44,4 +44,3 @@ $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CON $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CONTROLLER_RA8875)), lvgl_touch/ra8875_touch.o) $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI)), lvgl_touch/tp_spi.o) -$(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C)), lvgl_touch/tp_i2c.o) diff --git a/i2c_manager/Kconfig b/i2c_manager/Kconfig new file mode 100644 index 0000000..0c11ab1 --- /dev/null +++ b/i2c_manager/Kconfig @@ -0,0 +1,116 @@ +menu "I2C Port Settings" + depends on LV_I2C && !HAVE_I2C_MANAGER + + menu "I2C Port 0" + + config I2C_MANAGER_0_ENABLED + bool "Enable I2C port 0" + + if I2C_MANAGER_0_ENABLED + config I2C_MANAGER_0_SDA + int "SDA (GPIO pin)" + range 0 39 if IDF_TARGET_ESP32 + range 0 46 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 + config I2C_MANAGER_0_SCL + int "SCL (GPIO pin)" + range 0 39 if IDF_TARGET_ESP32 + range 0 46 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 + config I2C_MANAGER_0_FREQ_HZ + int "Frequency (Hz)" + default 400000 + range 100000 5000000 + help + The clock speed in Hz. Ranges from 100000 (100 kHz) to + 5000000 (5 Mhz). I2C busses that involve external wires may + have to be slower, and the real maximum speed the bus will + support depends on the value of the pullup resistors and the + design of the overall circuit. + config I2C_MANAGER_0_TIMEOUT + int "R/W timeout (ms)" + default 20 + range 10 1000 + help + Timeout for I2C read and write operations. This does not + include the time waiting for a lock. + config I2C_MANAGER_0_LOCK_TIMEOUT + int "Stale lock override (ms)" + default 50 + range 10 1000 + help + Timeout at which point an operation waiting for its turn on + the port will assume that whatever set the lock has died and + overrides it. Set this somewhat larger than the previous + timeout. + config I2C_MANAGER_0_PULLUPS + bool "Use ESP32 built-in bus pull-up resistors" + help + The I2C bus needs resistors to make sure it's in a defined + state when nobody is talking. Many circuits have external + pullup resistors already and turning these on will increase + power consumption slightly and may limit the speed your bus + can attain. Try with these off first if you don't know. + endif + + endmenu + + + menu "I2C Port 1" + + config I2C_MANAGER_1_ENABLED + bool "Enable I2C port 1" + + if I2C_MANAGER_1_ENABLED + config I2C_MANAGER_1_SDA + int "SDA (GPIO pin)" + default 32 + range 0 39 if IDF_TARGET_ESP32 + range 0 46 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 + config I2C_MANAGER_1_SCL + int "SCL (GPIO pin)" + default 33 + range 0 39 if IDF_TARGET_ESP32 + range 0 46 if IDF_TARGET_ESP32S2 + range 0 21 if IDF_TARGET_ESP32C3 + config I2C_MANAGER_1_FREQ_HZ + int "Frequency (Hz)" + default 1000000 + range 100000 5000000 + help + The clock speed in Hz. Ranges from 100000 (100 kHz) to + 5000000 (5 Mhz). I2C busses that involve external wires may + have to be slower, and the real maximum speed the bus will + support depends on the value of the pullup resistors and the + design of the overall circuit. + config I2C_MANAGER_1_TIMEOUT + int "R/W timeout (ms)" + default 20 + range 10 1000 + help + Timeout for I2C read and write operations. This does not + include the time waiting for a lock. Default should be fine. + config I2C_MANAGER_1_LOCK_TIMEOUT + int "Stale lock override (ms)" + default 50 + help + Timeout at which point an operation waiting for its turn on + the port will assume that whatever set the lock has died and + overrides it. Set this somewhat larger than the previous + timeout. Default should be fine. + range 30 1000 + config I2C_MANAGER_1_PULLUPS + bool "Use ESP32 built-in bus pull-up resistors" + help + The I2C bus needs resistors to make sure it's in a defined + state when nobody is talking. Many circuits have external + pullup resistors already and turning these on will increase + power consumption slightly and may limit the speed your bus + can attain. Try with these off first if you don't know. + endif + + endmenu + +endmenu + diff --git a/i2c_manager/README.md b/i2c_manager/README.md new file mode 100644 index 0000000..f9a368b --- /dev/null +++ b/i2c_manager/README.md @@ -0,0 +1,71 @@ +# I2C in `lvgl_esp32_drivers` + +  + + + +## Information for users + +### I2C Manager support + +`lvgl_esp32_drivers` comes with built-in I2C support by integrating I2C Manager, which is used in case your touch interface or screen uses the I2C bus. The native I2C support offered by ESP-IDF is not thread-safe. Maybe you use LVGL with a touch sensor that has an i2c port, and maybe your device also has another i2c device that needs to be read frequently, such as a 3D-accelerometer. If you read that from another task than the lvgl uses to read the touch data, you need some kind of mechanism to keep these communications from interfering. + +If you have other components that can use I2C Manager (or Mika Tuupola's I2C HAL abstraction that I2C Manager is compatible with) then put I2C Manager in your components directory by cloning the repository from below and in your main program do: + +```c +#include "i2c_manager.h" +#include "lvgl_helpers.h" + +[...] + +lvgl_locking(i2c_manager_locking()); +lv_init(); +lvgl_driver_init(); +``` + +The `lvgl_locking` part will cause the LVGL I2C driver to play nice with anything else that uses the I2C port(s) through I2C Manager. + +See the [I2C Manager GitHub repository](https://github.com/ropg/i2c_manager) for much more information. + + +  + + + +## Information for driver developers + +I2C support in the LVGL ESP drivers is provided exclusively by the files in this directory. Code from all over the project that was talking to the I2C hardware directly has been replaced by code that communicates through the functions provided in `lvgl_i2c.h`. I2C is handled by the I2C Manager that was built into lvlg_esp32_drivers, but the code would be the same if it was routed through I2C Manager as a separate component. If you are providing a driver, you need not worry about any of this. + +### Using I2C in a driver, a multi-step guide + +#### Step 1 + +The Kconfig entries for your driver only need to specify that you will be using I2C. This is done by `select LV_I2C_DISPLAY` or `select LV_I2C_TOUCH`. + +#### Step 2 + +To use the I2C port in your code you would do something like: + +```c +#include "i2c_manager/i2c_manager.h" + +uint8_t data[2]; +lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, 0x23, 0x42, &data, 2); +``` + +This causes a touch driver to read two bytes at register `0x42` from the IC at address `0x23`. Replace `CONFIG_LV_I2C_TOUCH_PORT` by `CONFIG_LV_I2C_DISPLAY_PORT` when this is a display instead of a touch driver. `lvgl_i2c_write` works much the same way, except writing the bytes from the buffer instead of reading them. + +> The example above ignores it but these functions return `esp_err_t` so you can check if the i2c communication worked. + +#### Step 3 + +There is no step 3, you are already done. + +### Behind the scenes + +If anything in `lvgl_esp32_drivers` uses I2C, the config system will pop up an extra menu. This will allow you to select an I2C port for screen and one for the touch driver, if applicable. An extra menu allows you to set the GPIO pins and bus speed of any port you have selected for use. It's perfectly fine for a display and a touch driver to use the same I2C port or different ones. + + +## More information + +If you need more documentation, please refer to the [I2C Manager GitHub repository](https://github.com/ropg/i2c_manager) for more detailed information on how I2C manager works. diff --git a/i2c_manager/i2c_manager.c b/i2c_manager/i2c_manager.c new file mode 100644 index 0000000..d301aff --- /dev/null +++ b/i2c_manager/i2c_manager.c @@ -0,0 +1,368 @@ +/* + +SPDX-License-Identifier: MIT + +MIT License + +Copyright (c) 2021 Rop Gonggrijp. Based on esp_i2c_helper by Mika Tuupola. + +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 +#include + +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#include + +#include "sdkconfig.h" + +#include "i2c_manager.h" + + +#if defined __has_include + #if __has_include ("esp_idf_version.h") + #include "esp_idf_version.h" + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0) + #define HAS_CLK_FLAGS + #endif + #endif +#endif + + +static const char* TAG = I2C_TAG; + +static SemaphoreHandle_t I2C_FN(_local_mutex)[2] = { NULL, NULL }; +static SemaphoreHandle_t* I2C_FN(_mutex) = &I2C_FN(_local_mutex)[0]; + +static const uint8_t ACK_CHECK_EN = 1; + +#if defined (I2C_NUM_0) && defined (CONFIG_I2C_MANAGER_0_ENABLED) + #define I2C_ZERO I2C_NUM_0 + #if defined (CONFIG_I2C_MANAGER_0_PULLUPS) + #define I2C_MANAGER_0_PULLUPS true + #else + #define I2C_MANAGER_0_PULLUPS false + #endif + + #define I2C_MANAGER_0_TIMEOUT CONFIG_I2C_MANAGER_0_TIMEOUT / portTICK_RATE_MS + #define I2C_MANAGER_0_LOCK_TIMEOUT CONFIG_I2C_MANAGER_0_LOCK_TIMEOUT / portTICK_RATE_MS +#endif + + +#if defined (I2C_NUM_1) && defined (CONFIG_I2C_MANAGER_1_ENABLED) + #define I2C_ONE I2C_NUM_1 + #if defined (CONFIG_I2C_MANAGER_1_PULLUPS) + #define I2C_MANAGER_1_PULLUPS true + #else + #define I2C_MANAGER_1_PULLUPS false + #endif + + #define I2C_MANAGER_1_TIMEOUT CONFIG_I2C_MANAGER_1_TIMEOUT / portTICK_RATE_MS + #define I2C_MANAGER_1_LOCK_TIMEOUT CONFIG_I2C_MANAGER_1_LOCK_TIMEOUT / portTICK_RATE_MS +#endif + +#define ERROR_PORT(port, fail) { \ + ESP_LOGE(TAG, "Invalid port or not configured for I2C Manager: %d", (int)port); \ + return fail; \ +} + +#if defined(I2C_ZERO) && defined (I2C_ONE) + #define I2C_PORT_CHECK(port, fail) \ + if (port != I2C_NUM_0 && port != I2C_NUM_1) ERROR_PORT(port, fail); +#else + #if defined(I2C_ZERO) + #define I2C_PORT_CHECK(port, fail) \ + if (port != I2C_NUM_0) ERROR_PORT(port, fail); + #elif defined(I2C_ONE) + #define I2C_PORT_CHECK(port, fail) \ + if (port != I2C_NUM_1) ERROR_PORT(port, fail); + #else + #define I2C_PORT_CHECK(port, fail) \ + ERROR_PORT(port, fail); + #endif +#endif + +static void i2c_send_address(i2c_cmd_handle_t cmd, uint16_t addr, i2c_rw_t rw) { + if (addr & I2C_ADDR_10) { + i2c_master_write_byte(cmd, 0xF0 | ((addr & 0x3FF) >> 7) | rw, ACK_CHECK_EN); + i2c_master_write_byte(cmd, addr & 0xFF, ACK_CHECK_EN); + } else { + i2c_master_write_byte(cmd, (addr << 1) | rw, ACK_CHECK_EN); + } +} + +static void i2c_send_register(i2c_cmd_handle_t cmd, uint32_t reg) { + if (reg & I2C_REG_16) { + i2c_master_write_byte(cmd, (reg & 0xFF00) >> 8, ACK_CHECK_EN); + } + i2c_master_write_byte(cmd, reg & 0xFF, ACK_CHECK_EN); +} + +esp_err_t I2C_FN(_init)(i2c_port_t port) { + + I2C_PORT_CHECK(port, ESP_FAIL); + + esp_err_t ret = ESP_OK; + + if (I2C_FN(_mutex)[port] == 0) { + + ESP_LOGI(TAG, "Starting I2C master at port %d.", (int)port); + + I2C_FN(_mutex)[port] = xSemaphoreCreateMutex(); + + i2c_config_t conf = {0}; + + #ifdef HAS_CLK_FLAGS + conf.clk_flags = 0; + #endif + + #if defined (I2C_ZERO) + if (port == I2C_NUM_0) { + conf.sda_io_num = CONFIG_I2C_MANAGER_0_SDA; + conf.scl_io_num = CONFIG_I2C_MANAGER_0_SCL; + conf.sda_pullup_en = I2C_MANAGER_0_PULLUPS ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE; + conf.scl_pullup_en = conf.sda_pullup_en; + conf.master.clk_speed = CONFIG_I2C_MANAGER_0_FREQ_HZ; + } + #endif + + #if defined (I2C_ONE) + if (port == I2C_NUM_1) { + conf.sda_io_num = CONFIG_I2C_MANAGER_1_SDA; + conf.scl_io_num = CONFIG_I2C_MANAGER_1_SCL; + conf.sda_pullup_en = I2C_MANAGER_1_PULLUPS ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE; + conf.scl_pullup_en = conf.sda_pullup_en; + conf.master.clk_speed = CONFIG_I2C_MANAGER_1_FREQ_HZ; + } + #endif + + conf.mode = I2C_MODE_MASTER; + + ret = i2c_param_config(port, &conf); + ret |= i2c_driver_install(port, conf.mode, 0, 0, 0); + + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialise I2C port %d.", (int)port); + ESP_LOGW(TAG, "If it was already open, we'll use it with whatever settings were used " + "to open it. See I2C Manager README for details."); + } else { + ESP_LOGI(TAG, "Initialised port %d (SDA: %d, SCL: %d, speed: %d Hz.)", + port, conf.sda_io_num, conf.scl_io_num, conf.master.clk_speed); + } + + } + + return ret; +} + +esp_err_t I2C_FN(_read)(i2c_port_t port, uint16_t addr, uint32_t reg, uint8_t *buffer, uint16_t size) { + + I2C_PORT_CHECK(port, ESP_FAIL); + + esp_err_t result; + + // May seem weird, but init starts with a check if it's needed, no need for that check twice. + I2C_FN(_init)(port); + + ESP_LOGV(TAG, "Reading port %d, addr 0x%03x, reg 0x%04x", port, addr, reg); + + TickType_t timeout = 0; + #if defined (I2C_ZERO) + if (port == I2C_NUM_0) { + timeout = (CONFIG_I2C_MANAGER_0_TIMEOUT) / portTICK_RATE_MS; + } + #endif + #if defined (I2C_ONE) + if (port == I2C_NUM_1) { + timeout = (CONFIG_I2C_MANAGER_1_TIMEOUT) / portTICK_RATE_MS; + } + #endif + + if (I2C_FN(_lock)((int)port) == ESP_OK) { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + if (!(reg & I2C_NO_REG)) { + /* When reading specific register set the addr pointer first. */ + i2c_master_start(cmd); + i2c_send_address(cmd, addr, I2C_MASTER_WRITE); + i2c_send_register(cmd, reg); + } + /* Read size bytes from the current pointer. */ + i2c_master_start(cmd); + i2c_send_address(cmd, addr, I2C_MASTER_READ); + i2c_master_read(cmd, buffer, size, I2C_MASTER_LAST_NACK); + i2c_master_stop(cmd); + result = i2c_master_cmd_begin(port, cmd, timeout); + i2c_cmd_link_delete(cmd); + I2C_FN(_unlock)((int)port); + } else { + ESP_LOGE(TAG, "Lock could not be obtained for port %d.", (int)port); + return ESP_ERR_TIMEOUT; + } + + if (result != ESP_OK) { + ESP_LOGW(TAG, "Error: %d", result); + } + + ESP_LOG_BUFFER_HEX_LEVEL(TAG, buffer, size, ESP_LOG_VERBOSE); + + return result; +} + +esp_err_t I2C_FN(_write)(i2c_port_t port, uint16_t addr, uint32_t reg, const uint8_t *buffer, uint16_t size) { + + I2C_PORT_CHECK(port, ESP_FAIL); + + esp_err_t result; + + // May seem weird, but init starts with a check if it's needed, no need for that check twice. + I2C_FN(_init)(port); + + ESP_LOGV(TAG, "Writing port %d, addr 0x%03x, reg 0x%04x", port, addr, reg); + + TickType_t timeout = 0; + #if defined (I2C_ZERO) + if (port == I2C_NUM_0) { + timeout = (CONFIG_I2C_MANAGER_0_TIMEOUT) / portTICK_RATE_MS; + } + #endif + #if defined (I2C_ONE) + if (port == I2C_NUM_1) { + timeout = (CONFIG_I2C_MANAGER_1_TIMEOUT) / portTICK_RATE_MS; + } + #endif + + if (I2C_FN(_lock)((int)port) == ESP_OK) { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_send_address(cmd, addr, I2C_MASTER_WRITE); + if (!(reg & I2C_NO_REG)) { + i2c_send_register(cmd, reg); + } + i2c_master_write(cmd, (uint8_t *)buffer, size, ACK_CHECK_EN); + i2c_master_stop(cmd); + result = i2c_master_cmd_begin( port, cmd, timeout); + i2c_cmd_link_delete(cmd); + I2C_FN(_unlock)((int)port); + } else { + ESP_LOGE(TAG, "Lock could not be obtained for port %d.", (int)port); + return ESP_ERR_TIMEOUT; + } + + if (result != ESP_OK) { + ESP_LOGW(TAG, "Error: %d", result); + } + + ESP_LOG_BUFFER_HEX_LEVEL(TAG, buffer, size, ESP_LOG_VERBOSE); + + return result; +} + +esp_err_t I2C_FN(_close)(i2c_port_t port) { + I2C_PORT_CHECK(port, ESP_FAIL); + vSemaphoreDelete(I2C_FN(_mutex)[port]); + I2C_FN(_mutex)[port] = NULL; + ESP_LOGI(TAG, "Closing I2C master at port %d", port); + return i2c_driver_delete(port); +} + +esp_err_t I2C_FN(_lock)(i2c_port_t port) { + I2C_PORT_CHECK(port, ESP_FAIL); + ESP_LOGV(TAG, "Mutex lock set for %d.", (int)port); + + TickType_t timeout; + #if defined (I2C_ZERO) + if (port == I2C_NUM_0) { + timeout = (CONFIG_I2C_MANAGER_0_LOCK_TIMEOUT) / portTICK_RATE_MS; + } + #endif + #if defined (I2C_ONE) + if (port == I2C_NUM_1) { + timeout = (CONFIG_I2C_MANAGER_1_LOCK_TIMEOUT) / portTICK_RATE_MS; + } + #endif + + if (xSemaphoreTake(I2C_FN(_mutex)[port], timeout) == pdTRUE) { + return ESP_OK; + } else { + ESP_LOGE(TAG, "Removing stale mutex lock from port %d.", (int)port); + I2C_FN(_force_unlock)(port); + return (xSemaphoreTake(I2C_FN(_mutex)[port], timeout) == pdTRUE ? ESP_OK : ESP_FAIL); + } +} + +esp_err_t I2C_FN(_unlock)(i2c_port_t port) { + I2C_PORT_CHECK(port, ESP_FAIL); + ESP_LOGV(TAG, "Mutex lock removed for %d.", (int)port); + return (xSemaphoreGive(I2C_FN(_mutex)[port]) == pdTRUE) ? ESP_OK : ESP_FAIL; +} + +esp_err_t I2C_FN(_force_unlock)(i2c_port_t port) { + I2C_PORT_CHECK(port, ESP_FAIL); + if (I2C_FN(_mutex)[port]) { + vSemaphoreDelete(I2C_FN(_mutex)[port]); + } + I2C_FN(_mutex)[port] = xSemaphoreCreateMutex(); + return ESP_OK; +} + + + +#ifdef I2C_OEM + + void I2C_FN(_locking)(void* leader) { + if (leader) { + ESP_LOGI(TAG, "Now following I2C Manager for locking"); + I2C_FN(_mutex) = (SemaphoreHandle_t*)leader; + } + } + +#else + + void* i2c_manager_locking() { + return (void*)i2c_manager_mutex; + } + + int32_t i2c_hal_read(void *handle, uint8_t address, uint8_t reg, uint8_t *buffer, uint16_t size) { + return i2c_manager_read(*(i2c_port_t*)handle, address, reg, buffer, size); + } + + int32_t i2c_hal_write(void *handle, uint8_t address, uint8_t reg, const uint8_t *buffer, uint16_t size) { + return i2c_manager_write(*(i2c_port_t*)handle, address, reg, buffer, size); + } + + static i2c_port_t port_zero = (i2c_port_t)0; + static i2c_port_t port_one = (i2c_port_t)1; + + static i2c_hal_t _i2c_hal[2] = { + {&i2c_hal_read, &i2c_hal_write, &port_zero}, + {&i2c_hal_read, &i2c_hal_write, &port_one} + }; + + void* i2c_hal(i2c_port_t port) { + I2C_PORT_CHECK(port, NULL); + return (void*)&_i2c_hal[port]; + } + +#endif diff --git a/i2c_manager/i2c_manager.h b/i2c_manager/i2c_manager.h new file mode 100644 index 0000000..f9ce585 --- /dev/null +++ b/i2c_manager/i2c_manager.h @@ -0,0 +1,76 @@ +#ifndef _I2C_MANAGER_H +#define _I2C_MANAGER_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + + If you copy the i2c_manager files to your own component instead of + depending on i2c_manager, you MUST uncomment the define below + and put in some short string that identifies your component (such + as 'xyz'). This will cause i2c_manager to create functions named + xyz_i2c_* instead of i2c_manager_*. See README.md for details. + +*/ + +#define I2C_OEM lvgl + + +// Only here to get the I2C_NUM_0 and I2C_NUM_1 defines. +#include + +#define CONCATX(A, B) A ## B +#define CONCAT(A, B) CONCATX(A, B) +#define STR_LITERAL(s) # s +#define STR_EXPAND(s) STR_LITERAL(s) +#define STR_QUOTE(s) STR_EXPAND(STR_EXPAND(s)) + +#ifdef I2C_OEM + #define I2C_NAME_PREFIX CONCAT(I2C_OEM, _i2c) +#else + #define I2C_NAME_PREFIX i2c_manager +#endif +#define I2C_TAG STR_EXPAND(I2C_NAME_PREFIX) + +#define I2C_FN(s) CONCAT(I2C_NAME_PREFIX, s) + + +#define I2C_ADDR_10 ( 1 << 15 ) +#define I2C_REG_16 ( 1 << 31 ) +#define I2C_NO_REG ( 1 << 30 ) + +esp_err_t I2C_FN(_init)(i2c_port_t port); +esp_err_t I2C_FN(_read)(i2c_port_t port, uint16_t addr, uint32_t reg, uint8_t *buffer, uint16_t size); +esp_err_t I2C_FN(_write)(i2c_port_t port, uint16_t addr, uint32_t reg, const uint8_t *buffer, uint16_t size); +esp_err_t I2C_FN(_close)(i2c_port_t port); +esp_err_t I2C_FN(_lock)(i2c_port_t port); +esp_err_t I2C_FN(_unlock)(i2c_port_t port); +esp_err_t I2C_FN(_force_unlock)(i2c_port_t port); + + +#ifdef I2C_OEM + + void I2C_FN(_locking)(void* leader); + +#else + + void* i2c_manager_locking(); + + typedef struct { + int32_t (* read)(void *handle, uint8_t address, uint8_t reg, uint8_t *buffer, uint16_t size); + int32_t (* write)(void *handle, uint8_t address, uint8_t reg, const uint8_t *buffer, uint16_t size); + void *handle; + } i2c_hal_t; + + void* i2c_hal(i2c_port_t port); + +#endif + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lvgl_helpers.c b/lvgl_helpers.c index 2e78fef..dc98720 100644 --- a/lvgl_helpers.c +++ b/lvgl_helpers.c @@ -14,9 +14,8 @@ #include "lvgl_touch/tp_spi.h" #include "lvgl_spi_conf.h" -#include "lvgl_i2c_conf.h" -#include "driver/i2c.h" +#include "i2c_manager/i2c_manager.h" #ifdef LV_LVGL_H_INCLUDE_SIMPLE #include "lvgl.h" @@ -68,7 +67,7 @@ void lvgl_driver_init(void) DISP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK, SPI_BUS_MAX_TRANSFER_SZ, 1, DISP_SPI_IO2, DISP_SPI_IO3); - + disp_spi_add_device(TFT_SPI_HOST); disp_driver_init(); @@ -86,48 +85,29 @@ void lvgl_driver_init(void) TP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK, SPI_BUS_MAX_TRANSFER_SZ, 1, -1, -1); - + disp_spi_add_device(TFT_SPI_HOST); tp_spi_add_device(TOUCH_SPI_HOST); - + disp_driver_init(); touch_driver_init(); return; #endif -#if defined (SHARED_I2C_BUS) - ESP_LOGI(TAG, "Initializing shared I2C master"); - - lvgl_i2c_driver_init(DISP_I2C_PORT, - DISP_I2C_SDA, DISP_I2C_SCL, - DISP_I2C_SPEED_HZ); - - disp_driver_init(); - touch_driver_init(); - - return; -#endif - /* Display controller initialization */ #if defined CONFIG_LV_TFT_DISPLAY_PROTOCOL_SPI ESP_LOGI(TAG, "Initializing SPI master for display"); - + lvgl_spi_driver_init(TFT_SPI_HOST, DISP_SPI_MISO, DISP_SPI_MOSI, DISP_SPI_CLK, SPI_BUS_MAX_TRANSFER_SZ, 1, DISP_SPI_IO2, DISP_SPI_IO3); - + disp_spi_add_device(TFT_SPI_HOST); - + disp_driver_init(); -#elif defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_I2C) - ESP_LOGI(TAG, "Initializing I2C master for display"); - /* Init the i2c master on the display driver code */ - lvgl_i2c_driver_init(DISP_I2C_PORT, - DISP_I2C_SDA, DISP_I2C_SCL, - DISP_I2C_SPEED_HZ); - +#elif defined (CONFIG_LV_I2C_DISPLAY) disp_driver_init(); #else #error "No protocol defined for display controller" @@ -137,22 +117,16 @@ void lvgl_driver_init(void) #if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE #if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI) ESP_LOGI(TAG, "Initializing SPI master for touch"); - + lvgl_spi_driver_init(TOUCH_SPI_HOST, TP_SPI_MISO, TP_SPI_MOSI, TP_SPI_CLK, 0 /* Defaults to 4094 */, 2, -1, -1); - + tp_spi_add_device(TOUCH_SPI_HOST); - + touch_driver_init(); - #elif defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C) - ESP_LOGI(TAG, "Initializing I2C master for touch"); - - lvgl_i2c_driver_init(TOUCH_I2C_PORT, - TOUCH_I2C_SDA, TOUCH_I2C_SCL, - TOUCH_I2C_SPEED_HZ); - + #elif defined (CONFIG_LV_I2C_TOUCH) touch_driver_init(); #elif defined (CONFIG_LV_TOUCH_DRIVER_ADC) touch_driver_init(); @@ -165,42 +139,6 @@ void lvgl_driver_init(void) #endif } -/* Config the i2c master - * - * This should init the i2c master to be used on display and touch controllers. - * So we should be able to know if the display and touch controllers shares the - * same i2c master. - */ -bool lvgl_i2c_driver_init(int port, int sda_pin, int scl_pin, int speed_hz) -{ - esp_err_t err; - - ESP_LOGI(TAG, "Initializing I2C master port %d...", port); - ESP_LOGI(TAG, "SDA pin: %d, SCL pin: %d, Speed: %d (Hz)", - sda_pin, scl_pin, speed_hz); - - i2c_config_t conf = { - .mode = I2C_MODE_MASTER, - .sda_io_num = sda_pin, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_io_num = scl_pin, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master.clk_speed = speed_hz, - }; - - ESP_LOGI(TAG, "Setting I2C master configuration..."); - err = i2c_param_config(port, &conf); - assert(ESP_OK == err); - - ESP_LOGI(TAG, "Installing I2C master driver..."); - err = i2c_driver_install(port, - I2C_MODE_MASTER, - 0, 0 /*I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE */, - 0 /* intr_alloc_flags */); - assert(ESP_OK == err); - - return ESP_OK != err; -} /* Initialize spi bus master * diff --git a/lvgl_helpers.h b/lvgl_helpers.h index 081a843..8c599fe 100644 --- a/lvgl_helpers.h +++ b/lvgl_helpers.h @@ -88,14 +88,14 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ +void lvgl_i2c_locking(void* leader); + /* Initialize detected SPI and I2C bus and devices */ void lvgl_driver_init(void); /* Initialize SPI master */ bool lvgl_spi_driver_init(int host, int miso_pin, int mosi_pin, int sclk_pin, int max_transfer_sz, int dma_channel, int quadwp_pin, int quadhd_pin); -/* Initialize I2C master */ -bool lvgl_i2c_driver_init(int port, int sda_pin, int scl_pin, int speed); /********************** * MACROS diff --git a/lvgl_i2c_conf.h b/lvgl_i2c_conf.h deleted file mode 100644 index cf8ac45..0000000 --- a/lvgl_i2c_conf.h +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @file lvgl_i2c_config.h - */ - -#ifndef LVGL_I2C_CONF_H -#define LVGL_I2C_CONF_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -/********************* - * DEFINES - *********************/ - -/* TODO: Define the I2C bus clock based on the selected display or touch - * controllers. */ - -/* Do both display and touch controllers uses I2C? */ -#if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C) && \ - defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_I2C) - -#if defined (CONFIG_LV_DISPLAY_I2C_PORT_0) && \ - defined (CONFIG_LV_TOUCH_I2C_PORT_0) -#define SHARED_I2C_PORT -#define DISP_I2C_PORT I2C_NUM_0 -#endif - -#if defined (CONFIG_LV_DISPLAY_I2C_PORT_1) && \ - defined (CONFIG_LV_TOUCH_I2C_PORT_1) -#define SHARED_I2C_PORT -#define DISP_I2C_PORT I2C_NUM_1 -#endif - -#if !defined (SHARED_I2C_PORT) -#endif -#endif - -#if defined (SHARED_I2C_PORT) -/* If the port is shared the display and touch controllers must use the same - * SCL and SDA pins, otherwise let the user know with an error. */ -#if (CONFIG_LV_DISP_PIN_SDA != CONFIG_LV_TOUCH_I2C_SDA) || \ - (CONFIG_LV_DISP_PIN_SCL != CONFIG_LV_TOUCH_I2C_SCL) -#error "To share I2C port you need to choose the same SDA and SCL pins on both display and touch configurations" -#endif - -#define DISP_I2C_SDA CONFIG_LV_DISP_PIN_SDA -#define DISP_I2C_SCL CONFIG_LV_DISP_PIN_SCL -#define DISP_I2C_ORIENTATION TFT_ORIENTATION_LANDSCAPE - -/* Setting the I2C speed to the slowest one */ -#if DISP_I2C_SPEED_HZ < TOUCH_I2C_SPEED_HZ -#define DISP_I2C_SPEED_HZ 400000 /* DISP_I2C_SPEED_HZ */ -#else -#define DISP_I2C_SPEED_HZ 400000 /* DISP_I2C_SPEED_HZ */ -#endif - -#else - -/* lets check if the touch controller uses I2C... */ -#if defined (CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C) -#if defined (CONFIG_LV_TOUCH_I2C_PORT_0) -#define TOUCH_I2C_PORT I2C_NUM_0 -#else -#define TOUCH_I2C_PORT I2C_NUM_1 -#endif -#define TOUCH_I2C_SDA CONFIG_LV_TOUCH_I2C_SDA -#define TOUCH_I2C_SCL CONFIG_LV_TOUCH_I2C_SCL -#define TOUCH_I2C_SPEED_HZ 400000 -#endif - -/* lets check if the display controller uses I2C... */ -#if defined (CONFIG_LV_TFT_DISPLAY_PROTOCOL_I2C) -#if defined (CONFIG_LV_DISPLAY_I2C_PORT_0) -#define DISP_I2C_PORT I2C_NUM_0 -#else -#define DISP_I2C_PORT I2C_NUM_1 -#endif - -#define DISP_I2C_SDA CONFIG_LV_DISP_PIN_SDA -#define DISP_I2C_SCL CONFIG_LV_DISP_PIN_SCL -#define DISP_I2C_ORIENTATION TFT_ORIENTATION_LANDSCAPE -#define DISP_I2C_SPEED_HZ 400000 -#endif - -#endif - -/********************** - * TYPEDEFS - **********************/ - - -/********************** - * GLOBAL PROTOTYPES - **********************/ - - -/********************** - * MACROS - **********************/ - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LVGL_I2C_CONF_H*/ diff --git a/lvgl_tft/Kconfig b/lvgl_tft/Kconfig index 0535580..19138af 100644 --- a/lvgl_tft/Kconfig +++ b/lvgl_tft/Kconfig @@ -50,7 +50,7 @@ menu "LVGL TFT Display controller" config LV_PREDEFINED_DISPLAY_WEMOS_LOLIN bool "Wemos Lolin OLED" select LV_TFT_DISPLAY_CONTROLLER_SSD1306 - select LV_TFT_DISPLAY_PROTOCOL_I2C + select LV_I2C_DISPLAY select LV_TFT_DISPLAY_MONOCHROME select LV_THEME_MONO config LV_PREDEFINED_DISPLAY_ATAG @@ -187,7 +187,7 @@ menu "LVGL TFT Display controller" help Display controller protocol SPI - config LV_TFT_DISPLAY_PROTOCOL_I2C + config LV_I2C_DISPLAY bool help Display controller protocol I2C @@ -311,7 +311,7 @@ menu "LVGL TFT Display controller" config LV_TFT_DISPLAY_USER_CONTROLLER_SSD1306 bool "SSD1306" select LV_TFT_DISPLAY_CONTROLLER_SSD1306 - select LV_TFT_DISPLAY_PROTOCOL_I2C + select LV_I2C_DISPLAY select LV_TFT_DISPLAY_MONOCHROME config LV_TFT_DISPLAY_USER_CONTROLLER_FT81X bool "FT81X" @@ -502,18 +502,6 @@ menu "LVGL TFT Display controller" depends on LV_TFT_DISPLAY_SPI_TRANS_MODE_SIO endchoice - choice - prompt "Display I2C port" if LV_TFT_DISPLAY_PROTOCOL_I2C - default LV_DISPLAY_I2C_PORT_0 - help - Select the I2C port used by the display controller. - - config LV_DISPLAY_I2C_PORT_0 - bool "I2C PORT 0" - config LV_DISPLAY_I2C_PORT_1 - bool "I2C PORT 1" - endchoice - config LV_TFT_USE_CUSTOM_SPI_CLK_DIVIDER bool "Use custom SPI clock frequency." if LV_TFT_DISPLAY_PROTOCOL_SPI default n @@ -591,6 +579,16 @@ menu "LVGL TFT Display controller" default 80 if LV_TFT_SPI_CLK_DIVIDER_80 default 2 + config LV_M5STICKC_HANDLE_AXP192 + bool "Handle Backlight and TFT power for M5StickC using AXP192." if LV_PREDEFINED_DISPLAY_M5STICKC || LV_TFT_DISPLAY_CONTROLLER_ST7735S + default y if LV_PREDEFINED_DISPLAY_M5STICKC + select LV_I2C_DISPLAY + help + Display and TFT power supply on M5StickC is controlled using an + AXP192 Power Mangerment IC. Select yes if you want to enable TFT IC + (LDO3) and backlight power using AXP192 by LVGL, or select no if you + want to take care of power management in your own code. + config LV_INVERT_DISPLAY bool "IN DEPRECATION - Invert display." if LV_TFT_DISPLAY_CONTROLLER_RA8875 default n @@ -604,31 +602,6 @@ menu "LVGL TFT Display controller" If the colors look inverted on your display, try enabling this. If it didn't help try LVGL configuration -> Swap the 2 bytes of RGB565 color. - config LV_M5STICKC_HANDLE_AXP192 - bool "Handle Backlight and TFT power for M5StickC using AXP192." if LV_PREDEFINED_DISPLAY_M5STICKC || LV_TFT_DISPLAY_CONTROLLER_ST7735S - default y if LV_PREDEFINED_DISPLAY_M5STICKC - help - Display and TFT power supply on M5StickC is controlled using an AXP192 Power Mangerment IC. - Select yes if you want to enable TFT IC (LDO3) and backlight power using AXP192 by LVGL, or select no if you want to take care of - power management in your own code. - - config LV_AXP192_PIN_SDA - int "GPIO for AXP192 I2C SDA" - depends on LV_M5STICKC_HANDLE_AXP192 - range 0 39 - default 21 if LV_PREDEFINED_DISPLAY_M5STICKC - default 21 - help - Configure the AXP192 I2C SDA pin here. - - config LV_AXP192_PIN_SCL - int "GPIO for AXP192 I2C SCL" - depends on LV_M5STICKC_HANDLE_AXP192 - range 0 39 - default 22 if LV_PREDEFINED_DISPLAY_M5STICKC - default 22 - help - Configure the AXP192 I2C SDA pin here. # menu will be visible only when LV_PREDEFINED_DISPLAY_NONE is y menu "Display RA8875 Configuration" @@ -770,7 +743,7 @@ menu "LVGL TFT Display controller" config LV_DISP_SPI_MOSI int "GPIO for MOSI (Master Out Slave In)" if LV_TFT_DISPLAY_PROTOCOL_SPI range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 23 if LV_PREDEFINED_DISPLAY_WROVER4 @@ -800,7 +773,7 @@ menu "LVGL TFT Display controller" int "GPIO for MISO (Master In Slave Out)" if LV_TFT_DISPLAY_PROTOCOL_SPI depends on LV_DISPLAY_USE_SPI_MISO range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 19 if LV_PREDEFINED_PINS_TKOALA @@ -846,7 +819,7 @@ menu "LVGL TFT Display controller" config LV_DISP_SPI_CLK int "GPIO for CLK (SCK / Serial Clock)" if LV_TFT_DISPLAY_PROTOCOL_SPI range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 18 if LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_M5STICK @@ -875,7 +848,7 @@ menu "LVGL TFT Display controller" int "GPIO for CS (Slave Select)" if LV_TFT_DISPLAY_PROTOCOL_SPI depends on LV_DISPLAY_USE_SPI_CS range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 5 if LV_PREDEFINED_PINS_38V1 @@ -904,7 +877,7 @@ menu "LVGL TFT Display controller" config LV_DISP_PIN_DC int "GPIO for DC (Data / Command)" if LV_TFT_DISPLAY_PROTOCOL_SPI range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 depends on LV_DISPLAY_USE_DC @@ -942,7 +915,7 @@ menu "LVGL TFT Display controller" int "GPIO for Reset" if LV_TFT_DISPLAY_PROTOCOL_SPI && !LV_DISP_ST7789_SOFT_RESET depends on LV_DISP_USE_RST range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 18 if LV_PREDEFINED_PINS_38V1 @@ -964,7 +937,7 @@ menu "LVGL TFT Display controller" config LV_DISP_PIN_BUSY int "GPIO for Busy" if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 35 if LV_TFT_DISPLAY_CONTROLLER_IL3820 || LV_TFT_DISPLAY_CONTROLLER_JD79653A || LV_TFT_DISPLAY_CONTROLLER_UC8151D @@ -1005,7 +978,7 @@ menu "LVGL TFT Display controller" int "GPIO for Backlight Control" depends on LV_ENABLE_BACKLIGHT_CONTROL range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 23 if LV_PREDEFINED_PINS_38V1 @@ -1023,30 +996,33 @@ menu "LVGL TFT Display controller" help Configure the display BCLK (LED) pin here. - config LV_DISP_PIN_SDA - int "GPIO for I2C SDA" if LV_TFT_DISPLAY_PROTOCOL_I2C - range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 - - default 5 if LV_PREDEFINED_DISPLAY_WEMOS_LOLIN - default 5 - - help - Configure the I2C SDA pin here. - - config LV_DISP_PIN_SCL - int "GPIO for I2C SCL" if LV_TFT_DISPLAY_PROTOCOL_I2C - range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 - - default 4 if LV_PREDEFINED_DISPLAY_WEMOS_LOLIN - default 4 - - help - Configure the I2C SCL pin here. - endmenu + choice + prompt "Select an I2C port for the display" + default LV_I2C_DISPLAY_PORT_0 + depends on LV_I2C_DISPLAY + + config LV_I2C_DISPLAY_PORT_0 + bool + prompt "I2C port 0" + + config LV_I2C_DISPLAY_PORT_1 + bool + prompt "I2C port 1" + + endchoice + + config LV_I2C + bool + default y if LV_I2C_DISPLAY + + config LV_I2C_DISPLAY_PORT + int + default 1 if LV_I2C_DISPLAY_PORT_1 + default 0 + endmenu + + + diff --git a/lvgl_tft/ili9341.h b/lvgl_tft/ili9341.h index 5768fbe..e0058b1 100644 --- a/lvgl_tft/ili9341.h +++ b/lvgl_tft/ili9341.h @@ -20,7 +20,8 @@ extern "C" { #else #include "lvgl/lvgl.h" #endif -#include "../lvgl_helpers.h" + +#include "sdkconfig.h" /********************* * DEFINES diff --git a/lvgl_tft/ssd1306.c b/lvgl_tft/ssd1306.c index 43e5966..459cd00 100644 --- a/lvgl_tft/ssd1306.c +++ b/lvgl_tft/ssd1306.c @@ -13,10 +13,9 @@ /********************* * INCLUDES *********************/ -#include "driver/i2c.h" #include "assert.h" -#include "lvgl_i2c_conf.h" +#include "i2c_manager/i2c_manager.h" #include "ssd1306.h" @@ -25,6 +24,7 @@ *********************/ #define TAG "SSD1306" +#define OLED_I2C_PORT (CONFIG_LV_I2C_DISPLAY_PORT) // SLA (0x3C) + WRITE_MODE (0x00) = 0x78 (0b01111000) #define OLED_I2C_ADDRESS 0x3C #define OLED_WIDTH 128 @@ -70,8 +70,6 @@ // Charge Pump (pg.62) #define OLED_CMD_SET_CHARGE_PUMP 0x8D // follow with 0x14 -#define OLED_IIC_FREQ_HZ 400000 // I2C colock frequency - /********************** * TYPEDEFS **********************/ @@ -217,20 +215,22 @@ static uint8_t send_data(lv_disp_drv_t *disp_drv, void *bytes, size_t bytes_len) uint8_t *data = (uint8_t *) bytes; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + err = lvgl_i2c_write(OLED_I2C_PORT, OLED_I2C_ADDRESS, data[0], data + 1, bytes_len - 1 ); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true); - - for (size_t idx = 0; idx < bytes_len; idx++) { - i2c_master_write_byte(cmd, data[idx], true); - } - - i2c_master_stop(cmd); - - /* Send queued commands */ - err = i2c_master_cmd_begin(DISP_I2C_PORT, cmd, 10 / portTICK_PERIOD_MS); - i2c_cmd_link_delete(cmd); +// i2c_cmd_handle_t cmd = i2c_cmd_link_create(); +// +// i2c_master_start(cmd); +// i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true); +// +// for (size_t idx = 0; idx < bytes_len; idx++) { +// i2c_master_write_byte(cmd, data[idx], true); +// } +// +// i2c_master_stop(cmd); +// +// /* Send queued commands */ +// err = i2c_master_cmd_begin(DISP_I2C_PORT, cmd, 10 / portTICK_PERIOD_MS); +// i2c_cmd_link_delete(cmd); return ESP_OK == err ? 0 : 1; } @@ -240,17 +240,7 @@ static uint8_t send_pixels(lv_disp_drv_t *disp_drv, void *color_buffer, size_t b (void) disp_drv; esp_err_t err; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true); - - i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true); - i2c_master_write(cmd, (uint8_t *) color_buffer, buffer_len, true); - i2c_master_stop(cmd); - - /* Send queued commands */ - err = i2c_master_cmd_begin(DISP_I2C_PORT, cmd, 10 / portTICK_PERIOD_MS); - i2c_cmd_link_delete(cmd); + err = lvgl_i2c_write(OLED_I2C_PORT, OLED_I2C_ADDRESS, OLED_CONTROL_BYTE_DATA_STREAM, color_buffer, buffer_len); return ESP_OK == err ? 0 : 1; } diff --git a/lvgl_tft/ssd1306.h b/lvgl_tft/ssd1306.h index 2145493..62bd0e6 100644 --- a/lvgl_tft/ssd1306.h +++ b/lvgl_tft/ssd1306.h @@ -25,8 +25,6 @@ extern "C" { /********************* * DEFINES *********************/ -#define SSD1306_SDA CONFIG_LV_DISP_PIN_SDA -#define SSD1306_SCL CONFIG_LV_DISP_PIN_SCL #define SSD1306_DISPLAY_ORIENTATION TFT_ORIENTATION_LANDSCAPE /********************** diff --git a/lvgl_tft/st7735s.c b/lvgl_tft/st7735s.c index 2507118..d57def5 100644 --- a/lvgl_tft/st7735s.c +++ b/lvgl_tft/st7735s.c @@ -8,12 +8,15 @@ *********************/ #include "st7735s.h" #include "disp_spi.h" -#include "driver/i2c.h" #include "driver/gpio.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192 + #include "i2c_manager/i2c_manager.h" +#endif + /********************* * DEFINES *********************/ @@ -38,7 +41,6 @@ static void st7735s_send_cmd(uint8_t cmd); static void st7735s_send_data(void * data, uint16_t length); static void st7735s_send_color(void * data, uint16_t length); static void st7735s_set_orientation(uint8_t orientation); -static void i2c_master_init(); static void axp192_write_byte(uint8_t addr, uint8_t data); static void axp192_init(); static void axp192_sleep_in(); @@ -60,7 +62,6 @@ uint8_t st7735s_portrait_mode = 0; void st7735s_init(void) { #ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192 - i2c_master_init(); axp192_init(); #endif @@ -163,12 +164,16 @@ void st7735s_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * col void st7735s_sleep_in() { st7735s_send_cmd(0x10); - axp192_sleep_in(); + #ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192 + axp192_sleep_in(); + #endif } void st7735s_sleep_out() { - axp192_sleep_out(); + #ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192 + axp192_sleep_out(); + #endif st7735s_send_cmd(0x11); } @@ -218,55 +223,35 @@ static void st7735s_set_orientation(uint8_t orientation) st7735s_send_data((void *) &data[orientation], 1); } -static void i2c_master_init() -{ - i2c_config_t i2c_config = { - .mode = I2C_MODE_MASTER, - .sda_io_num = AXP192_SDA, - .scl_io_num = AXP192_SCL, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master.clk_speed = 400000 - }; - i2c_param_config(I2C_NUM_0, &i2c_config); - i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0); -} +#ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192 -static void axp192_write_byte(uint8_t addr, uint8_t data) -{ - esp_err_t ret; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + static void axp192_write_byte(uint8_t addr, uint8_t data) + { + err = lvgl_i2c_write(CONFIG_LV_I2C_DISPLAY_PORT, AXP192_I2C_ADDRESS, addr, &data, 1); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "AXP192 send failed. code: 0x%.2X", ret); + } + } - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (AXP192_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true); - i2c_master_write_byte(cmd, addr, true); - i2c_master_write_byte(cmd, data, true); - i2c_master_stop(cmd); + static void axp192_init() + { + // information on how to init and use AXP192 ifor M5StickC taken from + // https://forum.m5stack.com/topic/1025/m5stickc-turn-off-screen-completely - ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "AXP192 send failed. code: 0x%.2X", ret); - } - i2c_cmd_link_delete(cmd); -} + axp192_write_byte(0x10, 0xFF); // OLED_VPP Enable + axp192_write_byte(0x28, 0xCC); // Enable LDO2&LDO3, LED&TFT 3.0V + axp192_sleep_out(); + ESP_LOGI(TAG, "AXP192 initialized, power enabled for LDO2 and LDO3"); + } -static void axp192_init() -{ - // information on how to init and use AXP192 ifor M5StickC taken from - // https://forum.m5stack.com/topic/1025/m5stickc-turn-off-screen-completely + static void axp192_sleep_in() + { + axp192_write_byte(0x12, 0x4b); + } - axp192_write_byte(0x10, 0xFF); // OLED_VPP Enable - axp192_write_byte(0x28, 0xCC); // Enable LDO2&LDO3, LED&TFT 3.0V - axp192_sleep_out(); - ESP_LOGI(TAG, "AXP192 initialized, power enabled for LDO2 and LDO3"); -} + static void axp192_sleep_out() + { + axp192_write_byte(0x12, 0x4d); + } -static void axp192_sleep_in() -{ - axp192_write_byte(0x12, 0x4b); -} - -static void axp192_sleep_out() -{ - axp192_write_byte(0x12, 0x4d); -} +#endif diff --git a/lvgl_tft/st7735s.h b/lvgl_tft/st7735s.h index 71924bf..7422be6 100644 --- a/lvgl_tft/st7735s.h +++ b/lvgl_tft/st7735s.h @@ -29,9 +29,6 @@ extern "C" { #define ST7735S_RST CONFIG_LV_DISP_PIN_RST #define ST7735S_USE_RST CONFIG_LV_DISP_USE_RST -#define AXP192_SDA CONFIG_LV_AXP192_PIN_SDA -#define AXP192_SCL CONFIG_LV_AXP192_PIN_SCL - #define ST7735S_INVERT_COLORS CONFIG_LV_INVERT_COLORS // Defines are taken from diff --git a/lvgl_touch/Kconfig b/lvgl_touch/Kconfig index d4b71fc..da4b661 100644 --- a/lvgl_touch/Kconfig +++ b/lvgl_touch/Kconfig @@ -23,7 +23,7 @@ menu "LVGL Touch controller" select LV_TOUCH_DRIVER_PROTOCOL_SPI bool "XPT2046" config LV_TOUCH_CONTROLLER_FT6X06 - select LV_TOUCH_DRIVER_PROTOCOL_I2C + select LV_I2C_TOUCH bool "FT6X06" config LV_TOUCH_CONTROLLER_STMPE610 select LV_TOUCH_DRIVER_PROTOCOL_SPI @@ -38,16 +38,16 @@ menu "LVGL Touch controller" select LV_TOUCH_DRIVER_DISPLAY bool "RA8875" config LV_TOUCH_CONTROLLER_GT911 - select LV_TOUCH_DRIVER_PROTOCOL_I2C + select LV_I2C_TOUCH bool "GT911" endchoice - + config LV_TOUCH_DRIVER_PROTOCOL_SPI bool help Touch controller protocol SPI - config LV_TOUCH_DRIVER_PROTOCOL_I2C + config LV_I2C_TOUCH bool help Touch controller protocol I2C @@ -62,30 +62,16 @@ menu "LVGL Touch controller" 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 @@ -93,7 +79,7 @@ menu "LVGL Touch controller" config LV_TOUCH_CONTROLLER_SPI_FSPI bool "FSPI" if IDF_TARGET_ESP32S2 endchoice - + menu "Touchpanel (XPT2046) Pin Assignments" depends on LV_TOUCH_CONTROLLER_XPT2046 @@ -101,7 +87,7 @@ menu "LVGL Touch controller" int prompt "GPIO for MISO (Master In Slave Out)" range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 35 if LV_PREDEFINED_PINS_38V1 @@ -113,7 +99,7 @@ menu "LVGL Touch controller" int prompt "GPIO for MOSI (Master Out Slave In)" range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 32 if LV_PREDEFINED_PINS_38V1 @@ -124,7 +110,7 @@ menu "LVGL Touch controller" config LV_TOUCH_SPI_CLK int "GPIO for CLK (SCK / Serial Clock)" range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 26 if LV_PREDEFINED_PINS_38V1 @@ -135,8 +121,8 @@ menu "LVGL Touch controller" config LV_TOUCH_SPI_CS int "GPIO for CS (Slave Select)" range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 - + range 0 46 if IDF_TARGET_ESP32S2 + default 33 if LV_PREDEFINED_PINS_38V1 default 5 help @@ -145,7 +131,7 @@ menu "LVGL Touch controller" config LV_TOUCH_PIN_IRQ int "GPIO for IRQ (Interrupt Request)" range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 27 if LV_PREDEFINED_PINS_38V4 @@ -153,7 +139,7 @@ menu "LVGL Touch controller" help Configure the touchpanel IRQ pin here. endmenu - + menu "Touchpanel Configuration (XPT2046)" depends on LV_TOUCH_CONTROLLER_XPT2046 @@ -180,7 +166,7 @@ menu "LVGL Touch controller" prompt "Maximum Y coordinate value." default 4095 if LV_PREDEFINED_PINS_38V4 default 1900 - + config LV_TOUCH_XY_SWAP bool prompt "Swap XY." @@ -211,31 +197,6 @@ menu "LVGL Touch controller" endchoice 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 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 - - 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 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 - - default 22 - help - Configure the I2C touchpanel SCL pin here. - endmenu - menu "Touchpanel Configuration (FT6X06)" depends on LV_TOUCH_CONTROLLER_FT6X06 @@ -249,13 +210,13 @@ menu "LVGL Touch controller" prompt "Invert X coordinate value." default n - config LV_FT6X36_INVERT_Y - bool - prompt "Invert Y coordinate value." - default n + config LV_FT6X36_INVERT_Y + bool + prompt "Invert Y coordinate value." + default n endmenu - + menu "Touchpanel (STMPE610) Pin Assignments" depends on LV_TOUCH_CONTROLLER_STMPE610 @@ -263,7 +224,7 @@ menu "LVGL Touch controller" int prompt "GPIO for MISO (Master In Slave Out)" range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 35 if LV_PREDEFINED_PINS_38V1 @@ -278,7 +239,7 @@ menu "LVGL Touch controller" int prompt "GPIO for MOSI (Master Out Slave In)" range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 32 if LV_PREDEFINED_PINS_38V1 @@ -291,7 +252,7 @@ menu "LVGL Touch controller" config LV_TOUCH_SPI_CLK int "GPIO for CLK (SCK / Serial Clock)" range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 26 if LV_PREDEFINED_PINS_38V1 @@ -303,7 +264,7 @@ menu "LVGL Touch controller" config LV_TOUCH_SPI_CS int "GPIO for CS (Slave Select)" range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 + range 0 46 if IDF_TARGET_ESP32S2 range 0 21 if IDF_TARGET_ESP32C3 default 33 if LV_PREDEFINED_PINS_38V1 @@ -335,7 +296,7 @@ menu "LVGL Touch controller" int prompt "Maximum Y coordinate value." default 3800 - + config LV_TOUCH_XY_SWAP bool prompt "Swap XY." @@ -351,7 +312,7 @@ menu "LVGL Touch controller" prompt "Invert Y coordinate value." default y endmenu - + menu "Touchpanel (ADCRAW) Pin Assignments" depends on LV_TOUCH_CONTROLLER_ADCRAW @@ -372,7 +333,7 @@ menu "LVGL Touch controller" help Configure the touchpanel Y- pin. Must be ADC input. - + config LV_TOUCHSCREEN_RESISTIVE_PIN_XL int prompt "GPIO X-" @@ -502,31 +463,6 @@ menu "LVGL Touch controller" default y endmenu - - menu "Touchpanel (GT911) Pin Assignments" - depends on LV_TOUCH_CONTROLLER_GT911 - - config LV_TOUCH_I2C_SDA - int - prompt "GPIO for SDA (I2C)" - range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 - - default 2 - help - Configure the I2C touchpanel SDA pin here. - - config LV_TOUCH_I2C_SCL - int "GPIO for clock signal SCL (I2C)" - range 0 39 if IDF_TARGET_ESP32 - range 0 43 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 - - default 3 - help - Configure the I2C touchpanel SCL pin here. - endmenu menu "Touchpanel Configuration (GT911)" depends on LV_TOUCH_CONTROLLER_GT911 @@ -548,4 +484,31 @@ menu "LVGL Touch controller" endmenu + choice + prompt "Select an I2C port for the touch panel" + default LV_I2C_TOUCH_PORT_0 + depends on LV_I2C_TOUCH + + config LV_I2C_TOUCH_PORT_0 + bool + prompt "I2C port 0" + + config LV_I2C_TOUCH_PORT_1 + bool + prompt "I2C port 1" + + endchoice + + config LV_I2C + bool + default y if LV_I2C_TOUCH + + config LV_I2C_TOUCH_PORT + int + default 1 if LV_I2C_TOUCH_PORT_1 + default 0 + endmenu + + + diff --git a/lvgl_touch/ft6x36.c b/lvgl_touch/ft6x36.c index a4d74ef..c7c2f9e 100644 --- a/lvgl_touch/ft6x36.c +++ b/lvgl_touch/ft6x36.c @@ -1,33 +1,32 @@ /* * 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 +* 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 +* 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 +* +* 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 -#include #ifdef LV_LVGL_H_INCLUDE_SIMPLE #include #else #include #endif #include "ft6x36.h" -#include "tp_i2c.h" -#include "../lvgl_i2c_conf.h" + +#include "i2c_manager/i2c_manager.h" #define TAG "FT6X36" @@ -36,22 +35,10 @@ 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(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(i2c_cmd); - return ret; + return lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, slave_addr, register_addr, data_buf, 1); } + /** * @brief Read the FT6x36 gesture ID. Initialize first! * @param dev_addr: I2C FT6x36 Slave address. @@ -75,42 +62,29 @@ uint8_t ft6x36_get_gesture_id() { * @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 + 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); - 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_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_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_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); - ft6x06_i2c_read8(dev_addr, FT6X36_RELEASECODE_REG, &data_buf); - ESP_LOGI(TAG, "\tRelease code: 0x%02x", data_buf); - } - } } /** @@ -120,67 +94,29 @@ void ft6x06_init(uint16_t dev_addr) { * @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 + if (!ft6x36_status.inited) { + ESP_LOGE(TAG, "Init first!"); + return 0x00; + } + uint8_t data_buf[5]; // 1 byte status, 2 bytes X, 2 bytes Y 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 + esp_err_t ret = lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, current_dev_addr, FT6X36_TD_STAT_REG, &data_buf[0], 5); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error talking to touch IC: %s", esp_err_to_name(ret)); + } + uint8_t touch_pnt_cnt = data_buf[0]; // Number of detected touch points + + if (ret != ESP_OK || 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(TOUCH_I2C_PORT, 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(TOUCH_I2C_PORT, 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); + last_x = ((data_buf[1] & FT6X36_MSB_MASK) << 8) | (data_buf[2] & FT6X36_LSB_MASK); + last_y = ((data_buf[3] & FT6X36_MSB_MASK) << 8) | (data_buf[4] & FT6X36_LSB_MASK); #if CONFIG_LV_FT6X36_INVERT_X last_x = LV_HOR_RES - last_x; diff --git a/lvgl_touch/ft6x36.h b/lvgl_touch/ft6x36.h index da466b6..ace2997 100644 --- a/lvgl_touch/ft6x36.h +++ b/lvgl_touch/ft6x36.h @@ -2,20 +2,20 @@ /* * 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 +* 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 +* 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 +* +* 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. */ diff --git a/lvgl_touch/gt911.c b/lvgl_touch/gt911.c index e6cb972..9974571 100644 --- a/lvgl_touch/gt911.c +++ b/lvgl_touch/gt911.c @@ -19,15 +19,14 @@ */ #include -#include #ifdef LV_LVGL_H_INCLUDE_SIMPLE #include #else #include #endif #include "gt911.h" -#include "tp_i2c.h" -#include "../lvgl_i2c_conf.h" + +#include "i2c_manager/i2c_manager.h" #define TAG "GT911" @@ -35,35 +34,12 @@ gt911_status_t gt911_status; //TODO: handle multibyte read and refactor to just one read transaction esp_err_t gt911_i2c_read(uint8_t slave_addr, uint16_t register_addr, uint8_t *data_buf, uint8_t len) { - 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 >> 8), I2C_MASTER_ACK); - i2c_master_write_byte(i2c_cmd, (register_addr & 0xFF), 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(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(i2c_cmd); - return ret; + return lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, slave_addr, register_addr | I2C_REG_16, data_buf, len); } esp_err_t gt911_i2c_write8(uint8_t slave_addr, uint16_t register_addr, uint8_t data) { - 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 >> 8), I2C_MASTER_ACK); - i2c_master_write_byte(i2c_cmd, (register_addr & 0xFF), I2C_MASTER_ACK); - i2c_master_write_byte(i2c_cmd, data, I2C_MASTER_ACK); - i2c_master_stop(i2c_cmd); - esp_err_t ret = i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(i2c_cmd); - return ret; + uint8_t buffer = data; + return lvgl_i2c_write(CONFIG_LV_I2C_TOUCH_PORT, slave_addr, register_addr | I2C_REG_16, &buffer, 1); } /** diff --git a/lvgl_touch/touch_driver.c b/lvgl_touch/touch_driver.c index 1212543..35fcc6b 100644 --- a/lvgl_touch/touch_driver.c +++ b/lvgl_touch/touch_driver.c @@ -4,7 +4,6 @@ #include "touch_driver.h" #include "tp_spi.h" -#include "tp_i2c.h" void touch_driver_init(void) diff --git a/lvgl_touch/tp_i2c.c b/lvgl_touch/tp_i2c.c deleted file mode 100644 index dc3371c..0000000 --- a/lvgl_touch/tp_i2c.c +++ /dev/null @@ -1,43 +0,0 @@ -/* -* 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 -#include - -#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); -} diff --git a/lvgl_touch/tp_i2c.h b/lvgl_touch/tp_i2c.h deleted file mode 100644 index 5c1eb55..0000000 --- a/lvgl_touch/tp_i2c.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -* 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 - -esp_err_t i2c_master_init(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __TS_H */ From 8f661270be9f01666c0ee8400e8a8e0e675f972a Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Thu, 8 Jul 2021 18:08:29 +0200 Subject: [PATCH 18/27] Make it work with v7 and v8 Makes the change from #83 dependent on major version number so things work with v7 and v8. --- lvgl_tft/disp_spi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lvgl_tft/disp_spi.c b/lvgl_tft/disp_spi.c index 00e91a6..9b70806 100644 --- a/lvgl_tft/disp_spi.c +++ b/lvgl_tft/disp_spi.c @@ -310,7 +310,12 @@ static void IRAM_ATTR spi_ready(spi_transaction_t *trans) disp = lv_refr_get_disp_refreshing(); #endif +#if LVGL_VERSION_MAJOR < 8 + lv_disp_flush_ready(&disp->driver); +#else lv_disp_flush_ready(disp->driver); +#endif + } if (chained_post_cb) { From 048438738c7e74e40ec90d210e9b249ad6e1b1d8 Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Mon, 12 Jul 2021 10:18:20 +0200 Subject: [PATCH 19/27] Things noted by @tore-espressif See https://github.com/lvgl/lvgl_esp32_drivers/pull/70#pullrequestreview-703588587 --- i2c_manager/Kconfig | 14 -------------- i2c_manager/i2c_manager.c | 8 ++++---- lvgl_tft/ssd1306.c | 25 ++----------------------- 3 files changed, 6 insertions(+), 41 deletions(-) diff --git a/i2c_manager/Kconfig b/i2c_manager/Kconfig index 0c11ab1..72cbec2 100644 --- a/i2c_manager/Kconfig +++ b/i2c_manager/Kconfig @@ -9,14 +9,8 @@ menu "I2C Port Settings" if I2C_MANAGER_0_ENABLED config I2C_MANAGER_0_SDA int "SDA (GPIO pin)" - range 0 39 if IDF_TARGET_ESP32 - range 0 46 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 config I2C_MANAGER_0_SCL int "SCL (GPIO pin)" - range 0 39 if IDF_TARGET_ESP32 - range 0 46 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 config I2C_MANAGER_0_FREQ_HZ int "Frequency (Hz)" default 400000 @@ -64,16 +58,8 @@ menu "I2C Port Settings" if I2C_MANAGER_1_ENABLED config I2C_MANAGER_1_SDA int "SDA (GPIO pin)" - default 32 - range 0 39 if IDF_TARGET_ESP32 - range 0 46 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 config I2C_MANAGER_1_SCL int "SCL (GPIO pin)" - default 33 - range 0 39 if IDF_TARGET_ESP32 - range 0 46 if IDF_TARGET_ESP32S2 - range 0 21 if IDF_TARGET_ESP32C3 config I2C_MANAGER_1_FREQ_HZ int "Frequency (Hz)" default 1000000 diff --git a/i2c_manager/i2c_manager.c b/i2c_manager/i2c_manager.c index d301aff..095143d 100644 --- a/i2c_manager/i2c_manager.c +++ b/i2c_manager/i2c_manager.c @@ -66,8 +66,8 @@ static const uint8_t ACK_CHECK_EN = 1; #define I2C_MANAGER_0_PULLUPS false #endif - #define I2C_MANAGER_0_TIMEOUT CONFIG_I2C_MANAGER_0_TIMEOUT / portTICK_RATE_MS - #define I2C_MANAGER_0_LOCK_TIMEOUT CONFIG_I2C_MANAGER_0_LOCK_TIMEOUT / portTICK_RATE_MS + #define I2C_MANAGER_0_TIMEOUT ( CONFIG_I2C_MANAGER_0_TIMEOUT / portTICK_RATE_MS ) + #define I2C_MANAGER_0_LOCK_TIMEOUT ( CONFIG_I2C_MANAGER_0_LOCK_TIMEOUT / portTICK_RATE_MS ) #endif @@ -79,8 +79,8 @@ static const uint8_t ACK_CHECK_EN = 1; #define I2C_MANAGER_1_PULLUPS false #endif - #define I2C_MANAGER_1_TIMEOUT CONFIG_I2C_MANAGER_1_TIMEOUT / portTICK_RATE_MS - #define I2C_MANAGER_1_LOCK_TIMEOUT CONFIG_I2C_MANAGER_1_LOCK_TIMEOUT / portTICK_RATE_MS + #define I2C_MANAGER_1_TIMEOUT ( CONFIG_I2C_MANAGER_1_TIMEOUT / portTICK_RATE_MS ) + #define I2C_MANAGER_1_LOCK_TIMEOUT ( CONFIG_I2C_MANAGER_1_LOCK_TIMEOUT / portTICK_RATE_MS ) #endif #define ERROR_PORT(port, fail) { \ diff --git a/lvgl_tft/ssd1306.c b/lvgl_tft/ssd1306.c index 459cd00..811f164 100644 --- a/lvgl_tft/ssd1306.c +++ b/lvgl_tft/ssd1306.c @@ -211,36 +211,15 @@ void ssd1306_sleep_out(void) static uint8_t send_data(lv_disp_drv_t *disp_drv, void *bytes, size_t bytes_len) { (void) disp_drv; - esp_err_t err; uint8_t *data = (uint8_t *) bytes; - err = lvgl_i2c_write(OLED_I2C_PORT, OLED_I2C_ADDRESS, data[0], data + 1, bytes_len - 1 ); - -// i2c_cmd_handle_t cmd = i2c_cmd_link_create(); -// -// i2c_master_start(cmd); -// i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true); -// -// for (size_t idx = 0; idx < bytes_len; idx++) { -// i2c_master_write_byte(cmd, data[idx], true); -// } -// -// i2c_master_stop(cmd); -// -// /* Send queued commands */ -// err = i2c_master_cmd_begin(DISP_I2C_PORT, cmd, 10 / portTICK_PERIOD_MS); -// i2c_cmd_link_delete(cmd); - - return ESP_OK == err ? 0 : 1; + return lvgl_i2c_write(OLED_I2C_PORT, OLED_I2C_ADDRESS, data[0], data + 1, bytes_len - 1 ); } static uint8_t send_pixels(lv_disp_drv_t *disp_drv, void *color_buffer, size_t buffer_len) { (void) disp_drv; - esp_err_t err; - err = lvgl_i2c_write(OLED_I2C_PORT, OLED_I2C_ADDRESS, OLED_CONTROL_BYTE_DATA_STREAM, color_buffer, buffer_len); - - return ESP_OK == err ? 0 : 1; + return lvgl_i2c_write(OLED_I2C_PORT, OLED_I2C_ADDRESS, OLED_CONTROL_BYTE_DATA_STREAM, color_buffer, buffer_len); } From ef76fd1056bcc4a25b1f0e7d7b757d0725ba5b51 Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Mon, 12 Jul 2021 10:24:11 +0200 Subject: [PATCH 20/27] I2C Manager Kconfig now generic --- Kconfig | 7 +- i2c_manager/Kconfig | 190 +++++++++++++++++++++----------------------- 2 files changed, 98 insertions(+), 99 deletions(-) diff --git a/Kconfig b/Kconfig index 42c3c66..370ad6e 100644 --- a/Kconfig +++ b/Kconfig @@ -4,6 +4,11 @@ menu "LVGL ESP Drivers" rsource "lvgl_touch/Kconfig" - rsource "i2c_manager/Kconfig" + menu "I2C Port Settings" + depends on LV_I2C && !HAVE_I2C_MANAGER + + rsource "i2c_manager/Kconfig" + + endmenu endmenu diff --git a/i2c_manager/Kconfig b/i2c_manager/Kconfig index 72cbec2..4011bcf 100644 --- a/i2c_manager/Kconfig +++ b/i2c_manager/Kconfig @@ -1,102 +1,96 @@ -menu "I2C Port Settings" - depends on LV_I2C && !HAVE_I2C_MANAGER +menu "I2C Port 0" - menu "I2C Port 0" - - config I2C_MANAGER_0_ENABLED - bool "Enable I2C port 0" - - if I2C_MANAGER_0_ENABLED - config I2C_MANAGER_0_SDA - int "SDA (GPIO pin)" - config I2C_MANAGER_0_SCL - int "SCL (GPIO pin)" - config I2C_MANAGER_0_FREQ_HZ - int "Frequency (Hz)" - default 400000 - range 100000 5000000 - help - The clock speed in Hz. Ranges from 100000 (100 kHz) to - 5000000 (5 Mhz). I2C busses that involve external wires may - have to be slower, and the real maximum speed the bus will - support depends on the value of the pullup resistors and the - design of the overall circuit. - config I2C_MANAGER_0_TIMEOUT - int "R/W timeout (ms)" - default 20 - range 10 1000 - help - Timeout for I2C read and write operations. This does not - include the time waiting for a lock. - config I2C_MANAGER_0_LOCK_TIMEOUT - int "Stale lock override (ms)" - default 50 - range 10 1000 - help - Timeout at which point an operation waiting for its turn on - the port will assume that whatever set the lock has died and - overrides it. Set this somewhat larger than the previous - timeout. - config I2C_MANAGER_0_PULLUPS - bool "Use ESP32 built-in bus pull-up resistors" - help - The I2C bus needs resistors to make sure it's in a defined - state when nobody is talking. Many circuits have external - pullup resistors already and turning these on will increase - power consumption slightly and may limit the speed your bus - can attain. Try with these off first if you don't know. - endif - - endmenu - - - menu "I2C Port 1" - - config I2C_MANAGER_1_ENABLED - bool "Enable I2C port 1" - - if I2C_MANAGER_1_ENABLED - config I2C_MANAGER_1_SDA - int "SDA (GPIO pin)" - config I2C_MANAGER_1_SCL - int "SCL (GPIO pin)" - config I2C_MANAGER_1_FREQ_HZ - int "Frequency (Hz)" - default 1000000 - range 100000 5000000 - help - The clock speed in Hz. Ranges from 100000 (100 kHz) to - 5000000 (5 Mhz). I2C busses that involve external wires may - have to be slower, and the real maximum speed the bus will - support depends on the value of the pullup resistors and the - design of the overall circuit. - config I2C_MANAGER_1_TIMEOUT - int "R/W timeout (ms)" - default 20 - range 10 1000 - help - Timeout for I2C read and write operations. This does not - include the time waiting for a lock. Default should be fine. - config I2C_MANAGER_1_LOCK_TIMEOUT - int "Stale lock override (ms)" - default 50 - help - Timeout at which point an operation waiting for its turn on - the port will assume that whatever set the lock has died and - overrides it. Set this somewhat larger than the previous - timeout. Default should be fine. - range 30 1000 - config I2C_MANAGER_1_PULLUPS - bool "Use ESP32 built-in bus pull-up resistors" - help - The I2C bus needs resistors to make sure it's in a defined - state when nobody is talking. Many circuits have external - pullup resistors already and turning these on will increase - power consumption slightly and may limit the speed your bus - can attain. Try with these off first if you don't know. - endif - - endmenu + config I2C_MANAGER_0_ENABLED + bool "Enable I2C port 0" + + if I2C_MANAGER_0_ENABLED + config I2C_MANAGER_0_SDA + int "SDA (GPIO pin)" + config I2C_MANAGER_0_SCL + int "SCL (GPIO pin)" + config I2C_MANAGER_0_FREQ_HZ + int "Frequency (Hz)" + default 400000 + range 100000 5000000 + help + The clock speed in Hz. Ranges from 100000 (100 kHz) to + 5000000 (5 Mhz). I2C busses that involve external wires may + have to be slower, and the real maximum speed the bus will + support depends on the value of the pullup resistors and the + design of the overall circuit. + config I2C_MANAGER_0_TIMEOUT + int "R/W timeout (ms)" + default 20 + range 10 1000 + help + Timeout for I2C read and write operations. This does not + include the time waiting for a lock. + config I2C_MANAGER_0_LOCK_TIMEOUT + int "Stale lock override (ms)" + default 50 + range 10 1000 + help + Timeout at which point an operation waiting for its turn on + the port will assume that whatever set the lock has died and + overrides it. Set this somewhat larger than the previous + timeout. + config I2C_MANAGER_0_PULLUPS + bool "Use ESP32 built-in bus pull-up resistors" + help + The I2C bus needs resistors to make sure it's in a defined + state when nobody is talking. Many circuits have external + pullup resistors already and turning these on will increase + power consumption slightly and may limit the speed your bus + can attain. Try with these off first if you don't know. + endif endmenu + +menu "I2C Port 1" + + config I2C_MANAGER_1_ENABLED + bool "Enable I2C port 1" + + if I2C_MANAGER_1_ENABLED + config I2C_MANAGER_1_SDA + int "SDA (GPIO pin)" + config I2C_MANAGER_1_SCL + int "SCL (GPIO pin)" + config I2C_MANAGER_1_FREQ_HZ + int "Frequency (Hz)" + default 1000000 + range 100000 5000000 + help + The clock speed in Hz. Ranges from 100000 (100 kHz) to + 5000000 (5 Mhz). I2C busses that involve external wires may + have to be slower, and the real maximum speed the bus will + support depends on the value of the pullup resistors and the + design of the overall circuit. + config I2C_MANAGER_1_TIMEOUT + int "R/W timeout (ms)" + default 20 + range 10 1000 + help + Timeout for I2C read and write operations. This does not + include the time waiting for a lock. Default should be fine. + config I2C_MANAGER_1_LOCK_TIMEOUT + int "Stale lock override (ms)" + default 50 + help + Timeout at which point an operation waiting for its turn on + the port will assume that whatever set the lock has died and + overrides it. Set this somewhat larger than the previous + timeout. Default should be fine. + range 30 1000 + config I2C_MANAGER_1_PULLUPS + bool "Use ESP32 built-in bus pull-up resistors" + help + The I2C bus needs resistors to make sure it's in a defined + state when nobody is talking. Many circuits have external + pullup resistors already and turning these on will increase + power consumption slightly and may limit the speed your bus + can attain. Try with these off first if you don't know. + endif + +endmenu From 6f2ce1307cf6ae5993675d432a6582d41af866a6 Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Mon, 12 Jul 2021 10:24:24 +0200 Subject: [PATCH 21/27] Better LVGL I2C README --- i2c_manager/README.md | 57 ++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/i2c_manager/README.md b/i2c_manager/README.md index f9a368b..12b9ca7 100644 --- a/i2c_manager/README.md +++ b/i2c_manager/README.md @@ -1,16 +1,18 @@ # I2C in `lvgl_esp32_drivers` -  +  ## Information for users ### I2C Manager support -`lvgl_esp32_drivers` comes with built-in I2C support by integrating I2C Manager, which is used in case your touch interface or screen uses the I2C bus. The native I2C support offered by ESP-IDF is not thread-safe. Maybe you use LVGL with a touch sensor that has an i2c port, and maybe your device also has another i2c device that needs to be read frequently, such as a 3D-accelerometer. If you read that from another task than the lvgl uses to read the touch data, you need some kind of mechanism to keep these communications from interfering. +`lvgl_esp32_drivers` comes with built-in I2C support by integrating I2C Manager, which is used in case you select a touch sensor or screen that uses the I2C bus. If you're just using LVGL you don't need to do anyting special. -If you have other components that can use I2C Manager (or Mika Tuupola's I2C HAL abstraction that I2C Manager is compatible with) then put I2C Manager in your components directory by cloning the repository from below and in your main program do: +I2C Manager can help if you are in a situation where you want to avoid "bus conflicts" on teh I2C bus. Suppose you use LVGL with a touch sensor that uses I2C, and your device also has another I2C device that needs to be read frequently, such as a 3D-accelerometer. ESP-IDF is not inherently "thread-safe". So if you read that from another task than the one LVGL uses to read the touch data, you need some kind of mechanism to keep these communications from interfering. + +If you have (or write) a driver for that 3D-accelerometer that can use I2C Manager (or the I2C HAL and i2cdev abstraction layers that I2C Manager is compatible with) then put I2C Manager in your components directory by cloning the repository from below and in your main program do: ```c #include "i2c_manager.h" @@ -18,54 +20,59 @@ If you have other components that can use I2C Manager (or Mika Tuupola's I2C HAL [...] -lvgl_locking(i2c_manager_locking()); +lvgl_i2c_locking(i2c_manager_locking()); lv_init(); lvgl_driver_init(); ``` -The `lvgl_locking` part will cause the LVGL I2C driver to play nice with anything else that uses the I2C port(s) through I2C Manager. +The `lvgl_i2c_locking` part will cause the LVGL I2C driver to play nice with anything else that uses the I2C port(s) through I2C Manager. -See the [I2C Manager GitHub repository](https://github.com/ropg/i2c_manager) for much more information. +Refer to the [I2C Manager GitHub repository](https://github.com/ropg/i2c_manager) for much more information.   +## Information for LVGL driver developers -## Information for driver developers +I2C support in the LVGL ESP drivers is provided exclusively by the files in this directory. Code from all over the project that was talking to the I2C hardware directly has been replaced by code that communicates through the functions provided in `i2c_manager.h`. I2C is handled by the I2C Manager that was built into `lvlg_esp32_drivers`, but the code would be the same if it was routed through I2C Manager as a separate component. If you are providing a driver, you need not worry about any of this. -I2C support in the LVGL ESP drivers is provided exclusively by the files in this directory. Code from all over the project that was talking to the I2C hardware directly has been replaced by code that communicates through the functions provided in `lvgl_i2c.h`. I2C is handled by the I2C Manager that was built into lvlg_esp32_drivers, but the code would be the same if it was routed through I2C Manager as a separate component. If you are providing a driver, you need not worry about any of this. -### Using I2C in a driver, a multi-step guide +  -#### Step 1 -The Kconfig entries for your driver only need to specify that you will be using I2C. This is done by `select LV_I2C_DISPLAY` or `select LV_I2C_TOUCH`. +### Using I2C in an LVGL driver, a multi-step guide -#### Step 2 +Step 1 -To use the I2C port in your code you would do something like: +: The Kconfig entries for your driver only need to specify that you will be using I2C. This is done by adding `select LV_I2C_DISPLAY` or `select LV_I2C_TOUCH`. -```c -#include "i2c_manager/i2c_manager.h" +Step 2 -uint8_t data[2]; -lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, 0x23, 0x42, &data, 2); -``` +: To use the I2C port in your code you would do something like: -This causes a touch driver to read two bytes at register `0x42` from the IC at address `0x23`. Replace `CONFIG_LV_I2C_TOUCH_PORT` by `CONFIG_LV_I2C_DISPLAY_PORT` when this is a display instead of a touch driver. `lvgl_i2c_write` works much the same way, except writing the bytes from the buffer instead of reading them. + ```c + #include "i2c_manager/i2c_manager.h" -> The example above ignores it but these functions return `esp_err_t` so you can check if the i2c communication worked. + uint8_t data[2]; + lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, 0x23, 0x42, &data, 2); + ``` -#### Step 3 + This causes a touch driver to read two bytes at register `0x42` from the IC at address `0x23`. Replace `CONFIG_LV_I2C_TOUCH_PORT` by `CONFIG_LV_I2C_DISPLAY_PORT` when this is a display instead of a touch driver. `lvgl_i2c_write` works much the same way, except it writes the bytes from the buffer instead of reading them. _(It's ignored above but these functions return `esp_err_t` so you can check if the I2C communication worked.)_ -There is no step 3, you are already done. +Step 3 -### Behind the scenes +: There is no step 3, you are already done. -If anything in `lvgl_esp32_drivers` uses I2C, the config system will pop up an extra menu. This will allow you to select an I2C port for screen and one for the touch driver, if applicable. An extra menu allows you to set the GPIO pins and bus speed of any port you have selected for use. It's perfectly fine for a display and a touch driver to use the same I2C port or different ones. + +### Meanwhile, behind the scenes ... + +If any of the drivers selected by the user uses I2C, the menuconfig system will show an extra menu to select I2C port(s) for screen and/or touch sensor. An additional menu allows for setting of GPIO pins and bus speed of any port selected for use with LVGL. It's perfectly fine for a display and a touch sensor to be on the same I2C port or different ones. + + +  ## More information -If you need more documentation, please refer to the [I2C Manager GitHub repository](https://github.com/ropg/i2c_manager) for more detailed information on how I2C manager works. +If you need more documentation, please refer to the [I2C Manager GitHub repository](https://github.com/ropg/i2c_manager) for more detailed information on how I2C manager works. There are features not in the simple example above, such as reads and writes without specifying a register, 16-bit registers, 10-bit I2C addressing and more. From 5739934d1437b23018c4a8593ab3d2938b65e3ce Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Mon, 12 Jul 2021 13:00:46 +0200 Subject: [PATCH 22/27] Fix README render on GitHub --- i2c_manager/README.md | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/i2c_manager/README.md b/i2c_manager/README.md index 12b9ca7..00a70c8 100644 --- a/i2c_manager/README.md +++ b/i2c_manager/README.md @@ -43,26 +43,38 @@ I2C support in the LVGL ESP drivers is provided exclusively by the files in this ### Using I2C in an LVGL driver, a multi-step guide -Step 1 +
-: The Kconfig entries for your driver only need to specify that you will be using I2C. This is done by adding `select LV_I2C_DISPLAY` or `select LV_I2C_TOUCH`. +
Step 1
-Step 2 +
+The Kconfig entries for your driver only need to specify that you will be using I2C. This is done by adding `select LV_I2C_DISPLAY` or `select LV_I2C_TOUCH`. +
-: To use the I2C port in your code you would do something like: - ```c - #include "i2c_manager/i2c_manager.h" +
Step 2
- uint8_t data[2]; - lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, 0x23, 0x42, &data, 2); - ``` +
+To use the I2C port in your code you would do something like: - This causes a touch driver to read two bytes at register `0x42` from the IC at address `0x23`. Replace `CONFIG_LV_I2C_TOUCH_PORT` by `CONFIG_LV_I2C_DISPLAY_PORT` when this is a display instead of a touch driver. `lvgl_i2c_write` works much the same way, except it writes the bytes from the buffer instead of reading them. _(It's ignored above but these functions return `esp_err_t` so you can check if the I2C communication worked.)_ + +```c +#include "i2c_manager/i2c_manager.h" -Step 3 +uint8_t data[2]; +lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, 0x23, 0x42, &data, 2); +``` -: There is no step 3, you are already done. +This causes a touch driver to read two bytes at register `0x42` from the IC at address `0x23`. Replace `CONFIG_LV_I2C_TOUCH_PORT` by `CONFIG_LV_I2C_DISPLAY_PORT` when this is a display instead of a touch driver. `lvgl_i2c_write` works much the same way, except it writes the bytes from the buffer instead of reading them. _(It's ignored above but these functions return `esp_err_t` so you can check if the I2C communication worked.)_ +
+ +
Step 3
+ +
+There is no step 3, you are already done. +
+ +
### Meanwhile, behind the scenes ... From f7b7c99cf053ac3c475f2aabca4367945528f02a Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Mon, 12 Jul 2021 18:28:25 +0200 Subject: [PATCH 23/27] timeout duplicate division removed --- i2c_manager/i2c_manager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i2c_manager/i2c_manager.c b/i2c_manager/i2c_manager.c index 095143d..080d81a 100644 --- a/i2c_manager/i2c_manager.c +++ b/i2c_manager/i2c_manager.c @@ -191,12 +191,12 @@ esp_err_t I2C_FN(_read)(i2c_port_t port, uint16_t addr, uint32_t reg, uint8_t *b TickType_t timeout = 0; #if defined (I2C_ZERO) if (port == I2C_NUM_0) { - timeout = (CONFIG_I2C_MANAGER_0_TIMEOUT) / portTICK_RATE_MS; + timeout = I2C_MANAGER_0_TIMEOUT; } #endif #if defined (I2C_ONE) if (port == I2C_NUM_1) { - timeout = (CONFIG_I2C_MANAGER_1_TIMEOUT) / portTICK_RATE_MS; + timeout = I2C_MANAGER_1_TIMEOUT; } #endif From 2a34dec70ae971d71be436606101ac41dd07ac82 Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Mon, 12 Jul 2021 18:28:32 +0200 Subject: [PATCH 24/27] typo --- i2c_manager/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i2c_manager/README.md b/i2c_manager/README.md index 00a70c8..a0501c0 100644 --- a/i2c_manager/README.md +++ b/i2c_manager/README.md @@ -10,7 +10,7 @@ `lvgl_esp32_drivers` comes with built-in I2C support by integrating I2C Manager, which is used in case you select a touch sensor or screen that uses the I2C bus. If you're just using LVGL you don't need to do anyting special. -I2C Manager can help if you are in a situation where you want to avoid "bus conflicts" on teh I2C bus. Suppose you use LVGL with a touch sensor that uses I2C, and your device also has another I2C device that needs to be read frequently, such as a 3D-accelerometer. ESP-IDF is not inherently "thread-safe". So if you read that from another task than the one LVGL uses to read the touch data, you need some kind of mechanism to keep these communications from interfering. +I2C Manager can help if you are in a situation where you want to avoid "bus conflicts" on the I2C bus. Suppose you use LVGL with a touch sensor that uses I2C, and your device also has another I2C device that needs to be read frequently, such as a 3D-accelerometer. ESP-IDF is not inherently "thread-safe". So if you read that from another task than the one LVGL uses to read the touch data, you need some kind of mechanism to keep these communications from interfering. If you have (or write) a driver for that 3D-accelerometer that can use I2C Manager (or the I2C HAL and i2cdev abstraction layers that I2C Manager is compatible with) then put I2C Manager in your components directory by cloning the repository from below and in your main program do: From 93125f3e006c1cfc9ef9538a790f6817a3acccfa Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Tue, 13 Jul 2021 14:33:54 +0200 Subject: [PATCH 25/27] another typo --- i2c_manager/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i2c_manager/README.md b/i2c_manager/README.md index a0501c0..b602327 100644 --- a/i2c_manager/README.md +++ b/i2c_manager/README.md @@ -8,7 +8,7 @@ ### I2C Manager support -`lvgl_esp32_drivers` comes with built-in I2C support by integrating I2C Manager, which is used in case you select a touch sensor or screen that uses the I2C bus. If you're just using LVGL you don't need to do anyting special. +`lvgl_esp32_drivers` comes with built-in I2C support by integrating I2C Manager, which is used in case you select a touch sensor or screen that uses the I2C bus. If you're just using LVGL you don't need to do anything special. I2C Manager can help if you are in a situation where you want to avoid "bus conflicts" on the I2C bus. Suppose you use LVGL with a touch sensor that uses I2C, and your device also has another I2C device that needs to be read frequently, such as a 3D-accelerometer. ESP-IDF is not inherently "thread-safe". So if you read that from another task than the one LVGL uses to read the touch data, you need some kind of mechanism to keep these communications from interfering. From befa5d0730e9bc5af1250ce9504e49cf833455f3 Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Wed, 14 Jul 2021 12:43:19 +0200 Subject: [PATCH 26/27] directory i2c_manager -> lvgl_i2c --- CMakeLists.txt | 2 +- Kconfig | 2 +- component.mk | 5 ++++- lvgl_helpers.c | 2 +- {i2c_manager => lvgl_i2c}/Kconfig | 0 {i2c_manager => lvgl_i2c}/README.md | 2 +- {i2c_manager => lvgl_i2c}/i2c_manager.c | 0 {i2c_manager => lvgl_i2c}/i2c_manager.h | 0 lvgl_tft/ssd1306.c | 2 +- lvgl_tft/st7735s.c | 2 +- lvgl_touch/ft6x36.c | 2 +- lvgl_touch/gt911.c | 2 +- 12 files changed, 12 insertions(+), 9 deletions(-) rename {i2c_manager => lvgl_i2c}/Kconfig (100%) rename {i2c_manager => lvgl_i2c}/README.md (99%) rename {i2c_manager => lvgl_i2c}/i2c_manager.c (100%) rename {i2c_manager => lvgl_i2c}/i2c_manager.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 678c894..b1ebffe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,7 @@ if(CONFIG_LV_TOUCH_CONTROLLER) endif() if(CONFIG_LV_I2C) - list(APPEND SOURCES "i2c_manager/i2c_manager.c") + list(APPEND SOURCES "lvgl_i2c/i2c_manager.c") endif() idf_component_register(SRCS ${SOURCES} diff --git a/Kconfig b/Kconfig index 370ad6e..48c3ce0 100644 --- a/Kconfig +++ b/Kconfig @@ -7,7 +7,7 @@ menu "LVGL ESP Drivers" menu "I2C Port Settings" depends on LV_I2C && !HAVE_I2C_MANAGER - rsource "i2c_manager/Kconfig" + rsource "lvgl_i2c/Kconfig" endmenu diff --git a/component.mk b/component.mk index c01caba..0017d0b 100644 --- a/component.mk +++ b/component.mk @@ -1,7 +1,7 @@ # LVGL ESP32 drivers # Define sources and include dirs -COMPONENT_SRCDIRS := . lvgl_tft lvgl_touch +COMPONENT_SRCDIRS := . lvgl_tft lvgl_touch lvgl_i2c COMPONENT_ADD_INCLUDEDIRS := . # LVGL is supposed to be used as a ESP-IDF component @@ -44,3 +44,6 @@ $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CON $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_CONTROLLER_RA8875)), lvgl_touch/ra8875_touch.o) $(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_SPI)), lvgl_touch/tp_spi.o) + +# I2C Manager +$(call compile_only_if,$(CONFIG_LV_I2C), lvgl_i2c/i2c_manager.o) diff --git a/lvgl_helpers.c b/lvgl_helpers.c index dc98720..edc522f 100644 --- a/lvgl_helpers.c +++ b/lvgl_helpers.c @@ -15,7 +15,7 @@ #include "lvgl_spi_conf.h" -#include "i2c_manager/i2c_manager.h" +#include "lvgl_i2c/i2c_manager.h" #ifdef LV_LVGL_H_INCLUDE_SIMPLE #include "lvgl.h" diff --git a/i2c_manager/Kconfig b/lvgl_i2c/Kconfig similarity index 100% rename from i2c_manager/Kconfig rename to lvgl_i2c/Kconfig diff --git a/i2c_manager/README.md b/lvgl_i2c/README.md similarity index 99% rename from i2c_manager/README.md rename to lvgl_i2c/README.md index b602327..890f8da 100644 --- a/i2c_manager/README.md +++ b/lvgl_i2c/README.md @@ -59,7 +59,7 @@ To use the I2C port in your code you would do something like: ```c -#include "i2c_manager/i2c_manager.h" +#include "lvgl_i2c/i2c_manager.h" uint8_t data[2]; lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, 0x23, 0x42, &data, 2); diff --git a/i2c_manager/i2c_manager.c b/lvgl_i2c/i2c_manager.c similarity index 100% rename from i2c_manager/i2c_manager.c rename to lvgl_i2c/i2c_manager.c diff --git a/i2c_manager/i2c_manager.h b/lvgl_i2c/i2c_manager.h similarity index 100% rename from i2c_manager/i2c_manager.h rename to lvgl_i2c/i2c_manager.h diff --git a/lvgl_tft/ssd1306.c b/lvgl_tft/ssd1306.c index 811f164..5953d44 100644 --- a/lvgl_tft/ssd1306.c +++ b/lvgl_tft/ssd1306.c @@ -15,7 +15,7 @@ *********************/ #include "assert.h" -#include "i2c_manager/i2c_manager.h" +#include "lvgl_i2c/i2c_manager.h" #include "ssd1306.h" diff --git a/lvgl_tft/st7735s.c b/lvgl_tft/st7735s.c index d57def5..8be725b 100644 --- a/lvgl_tft/st7735s.c +++ b/lvgl_tft/st7735s.c @@ -14,7 +14,7 @@ #include "freertos/task.h" #ifdef CONFIG_LV_M5STICKC_HANDLE_AXP192 - #include "i2c_manager/i2c_manager.h" + #include "lvgl_i2c/i2c_manager.h" #endif /********************* diff --git a/lvgl_touch/ft6x36.c b/lvgl_touch/ft6x36.c index c7c2f9e..9e34845 100644 --- a/lvgl_touch/ft6x36.c +++ b/lvgl_touch/ft6x36.c @@ -26,7 +26,7 @@ #endif #include "ft6x36.h" -#include "i2c_manager/i2c_manager.h" +#include "lvgl_i2c/i2c_manager.h" #define TAG "FT6X36" diff --git a/lvgl_touch/gt911.c b/lvgl_touch/gt911.c index 9974571..03c3d9d 100644 --- a/lvgl_touch/gt911.c +++ b/lvgl_touch/gt911.c @@ -26,7 +26,7 @@ #endif #include "gt911.h" -#include "i2c_manager/i2c_manager.h" +#include "lvgl_i2c/i2c_manager.h" #define TAG "GT911" From 93a44492fc5184846b5a39221020e94ed110ca95 Mon Sep 17 00:00:00 2001 From: Rop Gonggrijp Date: Wed, 14 Jul 2021 13:12:49 +0200 Subject: [PATCH 27/27] Things suggested by @tore-espressif See [here](https://github.com/lvgl/lvgl_esp32_drivers/pull/70#pullrequestreview-704302765) in #70 --- Kconfig | 10 +++++----- lvgl_i2c/README.md | 6 ++---- lvgl_tft/Kconfig | 6 ++++++ lvgl_touch/Kconfig | 6 ++++++ 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Kconfig b/Kconfig index 48c3ce0..36b4526 100644 --- a/Kconfig +++ b/Kconfig @@ -4,11 +4,11 @@ menu "LVGL ESP Drivers" rsource "lvgl_touch/Kconfig" - menu "I2C Port Settings" - depends on LV_I2C && !HAVE_I2C_MANAGER +endmenu - rsource "lvgl_i2c/Kconfig" - - endmenu +menu "I2C Port Settings" + depends on LV_I2C && !HAVE_I2C_MANAGER + + rsource "lvgl_i2c/Kconfig" endmenu diff --git a/lvgl_i2c/README.md b/lvgl_i2c/README.md index 890f8da..fb74e27 100644 --- a/lvgl_i2c/README.md +++ b/lvgl_i2c/README.md @@ -8,7 +8,7 @@ ### I2C Manager support -`lvgl_esp32_drivers` comes with built-in I2C support by integrating I2C Manager, which is used in case you select a touch sensor or screen that uses the I2C bus. If you're just using LVGL you don't need to do anything special. +`lvgl_esp32_drivers` integrates [I2C Manager](https://github.com/ropg/i2c_manager), which is used in case you select a touch sensor or screen that uses the I2C bus. If you're just using LVGL you don't need to do anything special. I2C Manager can help if you are in a situation where you want to avoid "bus conflicts" on the I2C bus. Suppose you use LVGL with a touch sensor that uses I2C, and your device also has another I2C device that needs to be read frequently, such as a 3D-accelerometer. ESP-IDF is not inherently "thread-safe". So if you read that from another task than the one LVGL uses to read the touch data, you need some kind of mechanism to keep these communications from interfering. @@ -27,15 +27,13 @@ lvgl_driver_init(); The `lvgl_i2c_locking` part will cause the LVGL I2C driver to play nice with anything else that uses the I2C port(s) through I2C Manager. -Refer to the [I2C Manager GitHub repository](https://github.com/ropg/i2c_manager) for much more information. -   ## Information for LVGL driver developers -I2C support in the LVGL ESP drivers is provided exclusively by the files in this directory. Code from all over the project that was talking to the I2C hardware directly has been replaced by code that communicates through the functions provided in `i2c_manager.h`. I2C is handled by the I2C Manager that was built into `lvlg_esp32_drivers`, but the code would be the same if it was routed through I2C Manager as a separate component. If you are providing a driver, you need not worry about any of this. +I2C support in the LVGL ESP drivers is provided exclusively by the files in this directory. Driver code that uses I2C communicates through the functions provided in `i2c_manager.h`.   diff --git a/lvgl_tft/Kconfig b/lvgl_tft/Kconfig index 19138af..f92351b 100644 --- a/lvgl_tft/Kconfig +++ b/lvgl_tft/Kconfig @@ -1006,10 +1006,16 @@ menu "LVGL TFT Display controller" config LV_I2C_DISPLAY_PORT_0 bool prompt "I2C port 0" + help + I2C is shared peripheral managed by I2C Manager. In order to configure I2C Manager (pinout, etc.) see menu + Component config->I2C Port Settings. config LV_I2C_DISPLAY_PORT_1 bool prompt "I2C port 1" + help + I2C is shared peripheral managed by I2C Manager. In order to configure I2C Manager (pinout, etc.) see menu + Component config->I2C Port Settings. endchoice diff --git a/lvgl_touch/Kconfig b/lvgl_touch/Kconfig index da4b661..031cfc9 100644 --- a/lvgl_touch/Kconfig +++ b/lvgl_touch/Kconfig @@ -492,10 +492,16 @@ menu "LVGL Touch controller" config LV_I2C_TOUCH_PORT_0 bool prompt "I2C port 0" + help + I2C is shared peripheral managed by I2C Manager. In order to configure I2C Manager (pinout, etc.) see menu + Component config->I2C Port Settings. config LV_I2C_TOUCH_PORT_1 bool prompt "I2C port 1" + help + I2C is shared peripheral managed by I2C Manager. In order to configure I2C Manager (pinout, etc.) see menu + Component config->I2C Port Settings. endchoice