Skip to content

Replace all LVGL driver I2C code with I2C Manager #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 "lvgl_i2c/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()
Expand Down
16 changes: 14 additions & 2 deletions Kconfig
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
rsource "lvgl_tft/Kconfig"
rsource "lvgl_touch/Kconfig"
menu "LVGL ESP Drivers"

rsource "lvgl_tft/Kconfig"

rsource "lvgl_touch/Kconfig"

endmenu

menu "I2C Port Settings"
depends on LV_I2C && !HAVE_I2C_MANAGER

rsource "lvgl_i2c/Kconfig"

endmenu
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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)

Expand All @@ -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 |
Expand All @@ -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.
6 changes: 4 additions & 2 deletions component.mk
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -44,4 +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)
$(call compile_only_if,$(and $(CONFIG_LV_TOUCH_CONTROLLER),$(CONFIG_LV_TOUCH_DRIVER_PROTOCOL_I2C)), lvgl_touch/tp_i2c.o)

# I2C Manager
$(call compile_only_if,$(CONFIG_LV_I2C), lvgl_i2c/i2c_manager.o)
86 changes: 12 additions & 74 deletions lvgl_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 "lvgl_i2c/i2c_manager.h"

#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
Expand Down Expand Up @@ -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();

Expand All @@ -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"
Expand All @@ -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();
Expand All @@ -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
*
Expand Down
4 changes: 2 additions & 2 deletions lvgl_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
96 changes: 96 additions & 0 deletions lvgl_i2c/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
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
Loading