esp-arduino-libs / ESP32_Display_Panel

Arduino library of driving display panel for the ESP SoCs
Apache License 2.0
57 stars 13 forks source link

How to correctly add other I2C component libraries? #38

Closed jerryliugithub closed 2 weeks ago

jerryliugithub commented 1 month ago

When adding additional components such as RTC and Sensor to the same I2C BUS, they have their own independent arduino libraries (using wire.h). Any suggestions when integrating into this library? Thanks !

Lzw655 commented 4 weeks ago

Hi @jerryliugithub,

Sorry, this is indeed a problem that has been troubling us, and currently, there is no ideal solution. However, the underlying I2C driver used by this library is the same as the one used by the Wire library, so theoretically, you can try the following steps:

  1. Initialize the I2C bus using Wire before using the Display_Panel in your program.
  2. Set ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST to 1 in the Display_Panel, which means touch will not initialize the I2C bus.
  3. Implement mutual exclusion using a semaphore in your program when reading the coordinates or interacting with other I2C devices.
jerryliugithub commented 3 weeks ago

I successfully used Arduino wire.h to initialize I2C, and it works properly (with ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST set to 1).

Next, I plan to add a semaphore in the bool ESP_PanelTouch::readRawData(uint8_t max_points_num, int timeout_ms) function in ESP_PanelTouch.cpp. Is this the correct approach?

I encountered some issues with the expander IO. In my project, besides using it for SPI+RGB, I will also use it to operate some GPIO functions. However, I'm not sure where to start in the library. Any suggestions would be greatly appreciated.

Lzw655 commented 3 weeks ago

Hi @jerryliugithub,

I think you can just add a semaphore in the project instead of changing the code in the library. Here is a simple example:

// file: test.ino

// Create a semaphore
i2c_sem = xSemaphoreCreateBinary();

...

// Take it before operating the same i2c bus
if (xSemaphoreTake(i2c_sem , timeout_ticks) == pdTRUE) {
    // Read touch point or operate expander IO
    ESP_PanelTouchPoint point;
    int read_touch_result = touch->readPoints(&point, 1);
    if (read_touch_result > 0) {
        Serial.printf("Touch point(%d): x %d, y %d, strength %d\n", i, point.x, point.y, point.strength);
    }

    ...

    // Release it after operation
    xSemaphoreGive(i2c_sem);
}

...

To use the expander with the library, there are two methods:

  1. If you set the macro ESP_PANEL_USE_EXPANDER to 1, the library will handle the initialization internally. You can then call the function panel->getExpander() to access it externally.

  2. If you set the macro ESP_PANEL_USE_EXPANDER to 0, you need to initialize the expander externally and then use the function panel->configExpander() to install it in the library.

jerryliugithub commented 3 weeks ago

Thank you for your quick response and detailed explanation. I am currently trying to extend the example SquareLine/v8/WiFiClock.ino. Since the underlying implementation already includes I2C Touch functionality, as shown in the following code, it would conflict with the additional I2C that I am planning to add. This is why I intend to modify the library. Thank you for the further explanation about the Expander. I will try to understand it.

lvgl_port_v8.cpp

static lv_indev_t indev_init(ESP_PanelTouch tp) -> indev_drv_tp.read_cb = touchpad_read;

static void touchpad_read(lv_indev_drv_t indev_drv, lv_indev_data_t data) -> int read_touch_result = tp->readPoints(&point, 1);

ESP_PanelTouch.cpp

int ESP_PanelTouch::readPoints(ESP_PanelTouchPoint points[], uint8_t num, int timeout_ms) -> ESP_PANEL_CHECK_FALSE_RET(readRawData(num, timeout_ms), -1, "Read raw data failed");

bool ESP_PanelTouch::readRawData(uint8_t max_points_num, int timeout_ms) -> ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_read_data(handle), false, "Read data failed"); esp_lcd_touch_get_coordinates(handle, x, y, strength, &_tp_points_num, max_points_num);