forked from espressif/esp-idf
feat(lcd): Add new version LCD implementation to adapt new I2C APIs
This commit is contained in:
@@ -8,6 +8,13 @@ components/esp_lcd/test_apps/i2c_lcd:
|
||||
temporary: true
|
||||
reason: insufficient runners
|
||||
|
||||
components/esp_lcd/test_apps/i2c_lcd_legacy:
|
||||
disable:
|
||||
- if: SOC_I2C_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET not in ["esp32c3"]
|
||||
temporary: true
|
||||
reason: insufficient runners
|
||||
|
||||
components/esp_lcd/test_apps/i80_lcd:
|
||||
disable:
|
||||
|
@@ -1,13 +1,14 @@
|
||||
set(srcs "src/esp_lcd_common.c"
|
||||
"src/esp_lcd_panel_io.c"
|
||||
"src/esp_lcd_panel_io_i2c.c"
|
||||
"src/esp_lcd_panel_io_i2c_v1.c"
|
||||
"src/esp_lcd_panel_io_i2c_v2.c"
|
||||
"src/esp_lcd_panel_io_spi.c"
|
||||
"src/esp_lcd_panel_nt35510.c"
|
||||
"src/esp_lcd_panel_ssd1306.c"
|
||||
"src/esp_lcd_panel_st7789.c"
|
||||
"src/esp_lcd_panel_ops.c")
|
||||
set(includes "include" "interface")
|
||||
set(priv_requires "driver" "esp_mm" "esp_psram")
|
||||
set(priv_requires "esp_mm" "esp_psram")
|
||||
|
||||
if(CONFIG_SOC_I2S_LCD_I80_VARIANT)
|
||||
list(APPEND srcs "src/esp_lcd_panel_io_i2s.c")
|
||||
@@ -20,4 +21,5 @@ endif()
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${includes}
|
||||
PRIV_REQUIRES ${priv_requires}
|
||||
REQUIRES driver
|
||||
LDFRAGMENTS linker.lf)
|
||||
|
@@ -10,13 +10,15 @@
|
||||
#include "esp_lcd_types.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/lcd_types.h"
|
||||
#include "hal/i2c_types.h"
|
||||
#include "driver/i2c_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void *esp_lcd_spi_bus_handle_t; /*!< Type of LCD SPI bus handle */
|
||||
typedef void *esp_lcd_i2c_bus_handle_t; /*!< Type of LCD I2C bus handle */
|
||||
typedef uint32_t esp_lcd_i2c_bus_handle_t; /*!< Type of LCD I2C bus handle */
|
||||
typedef struct esp_lcd_i80_bus_t *esp_lcd_i80_bus_handle_t; /*!< Type of LCD intel 8080 bus handle */
|
||||
|
||||
/**
|
||||
@@ -171,10 +173,43 @@ typedef struct {
|
||||
unsigned int dc_low_on_data: 1; /*!< If this flag is enabled, DC line = 0 means transfer data, DC line = 1 means transfer command; vice versa */
|
||||
unsigned int disable_control_phase: 1; /*!< If this flag is enabled, the control phase isn't used */
|
||||
} flags; /*!< Extra flags to fine-tune the I2C device */
|
||||
uint32_t scl_speed_hz; /*!< I2C LCD SCL frequency (hz) */
|
||||
} esp_lcd_panel_io_i2c_config_t;
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel IO handle, for I2C interface
|
||||
* @brief Create LCD panel IO handle, for I2C interface in legacy implementation
|
||||
*
|
||||
* @param[in] bus I2C bus handle, (in uint32_t)
|
||||
* @param[in] io_config IO configuration, for I2C interface
|
||||
* @param[out] ret_io Returned IO handle
|
||||
*
|
||||
* @note Please don't call this function in your project directly. Please call `esp_lcd_new_panel_to_i2c` instead.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_io_i2c_v1(uint32_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io);
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel IO handle, for I2C interface in new implementation
|
||||
*
|
||||
* @param[in] bus I2C bus handle, (in i2c_master_dev_handle_t)
|
||||
* @param[in] io_config IO configuration, for I2C interface
|
||||
* @param[out] ret_io Returned IO handle
|
||||
*
|
||||
* @note Please don't call this function in your project directly. Please call `esp_lcd_new_panel_to_i2c` instead.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_io_i2c_v2(i2c_master_bus_handle_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io);
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel IO handle
|
||||
*
|
||||
* @param[in] bus I2C bus handle
|
||||
* @param[in] io_config IO configuration, for I2C interface
|
||||
@@ -184,7 +219,9 @@ typedef struct {
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_io_i2c(esp_lcd_i2c_bus_handle_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io);
|
||||
#define esp_lcd_new_panel_io_i2c(bus, io_config, ret_io) _Generic((bus), \
|
||||
i2c_master_bus_handle_t : esp_lcd_new_panel_io_i2c_v2, \
|
||||
default : esp_lcd_new_panel_io_i2c_v1) (bus, io_config, ret_io) \
|
||||
|
||||
#if SOC_LCD_I80_SUPPORTED
|
||||
/**
|
||||
|
@@ -45,7 +45,7 @@ typedef struct {
|
||||
uint8_t cmdlink_buffer[]; // pre-alloc I2C command link buffer, to be reused in all transactions
|
||||
} lcd_panel_io_i2c_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_io_i2c(esp_lcd_i2c_bus_handle_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io)
|
||||
esp_err_t esp_lcd_new_panel_io_i2c_v1(uint32_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io)
|
||||
{
|
||||
#if CONFIG_LCD_ENABLE_DEBUG_LOG
|
||||
esp_log_level_set(TAG, ESP_LOG_DEBUG);
|
||||
@@ -54,10 +54,11 @@ esp_err_t esp_lcd_new_panel_io_i2c(esp_lcd_i2c_bus_handle_t bus, const esp_lcd_p
|
||||
lcd_panel_io_i2c_t *i2c_panel_io = NULL;
|
||||
ESP_GOTO_ON_FALSE(io_config && ret_io, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
ESP_GOTO_ON_FALSE(io_config->control_phase_bytes * 8 > io_config->dc_bit_offset, ESP_ERR_INVALID_ARG, err, TAG, "D/C bit exceeds control bytes");
|
||||
ESP_GOTO_ON_FALSE(io_config->scl_speed_hz == 0, ESP_ERR_INVALID_ARG, err, TAG, "scl_speed_hz is not need to set in legacy i2c_lcd driver");
|
||||
i2c_panel_io = calloc(1, sizeof(lcd_panel_io_i2c_t) + CMD_HANDLER_BUFFER_SIZE); // expand zero-length array cmdlink_buffer
|
||||
ESP_GOTO_ON_FALSE(i2c_panel_io, ESP_ERR_NO_MEM, err, TAG, "no mem for i2c panel io");
|
||||
|
||||
i2c_panel_io->i2c_bus_id = (uint32_t)bus;
|
||||
i2c_panel_io->i2c_bus_id = bus;
|
||||
i2c_panel_io->lcd_cmd_bits = io_config->lcd_cmd_bits;
|
||||
i2c_panel_io->lcd_param_bits = io_config->lcd_param_bits;
|
||||
i2c_panel_io->on_color_trans_done = io_config->on_color_trans_done;
|
||||
@@ -84,7 +85,7 @@ static esp_err_t panel_io_i2c_del(esp_lcd_panel_io_t *io)
|
||||
esp_err_t ret = ESP_OK;
|
||||
lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base);
|
||||
|
||||
ESP_LOGD(TAG, "del lcd panel io spi @%p", i2c_panel_io);
|
||||
ESP_LOGD(TAG, "del lcd panel i2c @%p", i2c_panel_io);
|
||||
free(i2c_panel_io);
|
||||
return ret;
|
||||
}
|
207
components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c
Normal file
207
components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_LCD_ENABLE_DEBUG_LOG
|
||||
// The local log level must be defined before including esp_log.h
|
||||
// Set the maximum log level for this source file
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#endif
|
||||
#include "esp_lcd_panel_io_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_heap_caps.h"
|
||||
static const char *TAG = "lcd_panel.io.i2c";
|
||||
|
||||
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
|
||||
#define CONTROL_PHASE_LENGTH (1)
|
||||
#define CMD_LENGTH (4)
|
||||
|
||||
static esp_err_t panel_io_i2c_del(esp_lcd_panel_io_t *io);
|
||||
static esp_err_t panel_io_i2c_rx_param(esp_lcd_panel_io_t *io, int lcd_cmd, void *param, size_t param_size);
|
||||
static esp_err_t panel_io_i2c_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size);
|
||||
static esp_err_t panel_io_i2c_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size);
|
||||
static esp_err_t panel_io_i2c_register_event_callbacks(esp_lcd_panel_io_handle_t io, const esp_lcd_panel_io_callbacks_t *cbs, void *user_ctx);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_io_t base; // Base class of generic lcd panel io
|
||||
i2c_master_dev_handle_t i2c_handle; // I2C master driver handle.
|
||||
uint32_t dev_addr; // Device address
|
||||
int lcd_cmd_bits; // Bit width of LCD command
|
||||
int lcd_param_bits; // Bit width of LCD parameter
|
||||
bool control_phase_enabled; // Is control phase enabled
|
||||
uint32_t control_phase_cmd; // control byte when transferring command
|
||||
uint32_t control_phase_data; // control byte when transferring data
|
||||
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; // User register's callback, invoked when color data trans done
|
||||
void *user_ctx; // User's private data, passed directly to callback on_color_trans_done()
|
||||
} lcd_panel_io_i2c_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_io_i2c_v2(i2c_master_bus_handle_t bus, const esp_lcd_panel_io_i2c_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io)
|
||||
{
|
||||
#if CONFIG_LCD_ENABLE_DEBUG_LOG
|
||||
esp_log_level_set(TAG, ESP_LOG_DEBUG);
|
||||
#endif
|
||||
esp_err_t ret = ESP_OK;
|
||||
lcd_panel_io_i2c_t *i2c_panel_io = NULL;
|
||||
i2c_master_dev_handle_t i2c_handle = NULL;
|
||||
ESP_GOTO_ON_FALSE(io_config && ret_io, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
ESP_GOTO_ON_FALSE(io_config->control_phase_bytes * 8 > io_config->dc_bit_offset, ESP_ERR_INVALID_ARG, err, TAG, "D/C bit exceeds control bytes");
|
||||
i2c_panel_io = calloc(1, sizeof(lcd_panel_io_i2c_t));
|
||||
ESP_GOTO_ON_FALSE(i2c_panel_io, ESP_ERR_NO_MEM, err, TAG, "no mem for i2c panel io");
|
||||
|
||||
i2c_device_config_t i2c_lcd_cfg = {
|
||||
.device_address = io_config->dev_addr,
|
||||
.scl_speed_hz = io_config->scl_speed_hz,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(i2c_master_bus_add_device(bus, &i2c_lcd_cfg, &i2c_handle), err, TAG, "i2c add device fail");
|
||||
|
||||
i2c_panel_io->i2c_handle = i2c_handle;
|
||||
i2c_panel_io->lcd_cmd_bits = io_config->lcd_cmd_bits;
|
||||
i2c_panel_io->lcd_param_bits = io_config->lcd_param_bits;
|
||||
i2c_panel_io->on_color_trans_done = io_config->on_color_trans_done;
|
||||
i2c_panel_io->user_ctx = io_config->user_ctx;
|
||||
i2c_panel_io->control_phase_enabled = (!io_config->flags.disable_control_phase);
|
||||
i2c_panel_io->control_phase_data = (!io_config->flags.dc_low_on_data) << (io_config->dc_bit_offset);
|
||||
i2c_panel_io->control_phase_cmd = (io_config->flags.dc_low_on_data) << (io_config->dc_bit_offset);
|
||||
i2c_panel_io->dev_addr = io_config->dev_addr;
|
||||
i2c_panel_io->base.del = panel_io_i2c_del;
|
||||
i2c_panel_io->base.rx_param = panel_io_i2c_rx_param;
|
||||
i2c_panel_io->base.tx_param = panel_io_i2c_tx_param;
|
||||
i2c_panel_io->base.tx_color = panel_io_i2c_tx_color;
|
||||
i2c_panel_io->base.register_event_callbacks = panel_io_i2c_register_event_callbacks;
|
||||
*ret_io = &(i2c_panel_io->base);
|
||||
ESP_LOGD(TAG, "new i2c lcd panel io @%p", i2c_panel_io);
|
||||
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (i2c_panel_io) {
|
||||
free(i2c_panel_io);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_io_i2c_del(esp_lcd_panel_io_t *io)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base);
|
||||
|
||||
ESP_LOGD(TAG, "del lcd panel io i2c @%p", i2c_panel_io);
|
||||
ESP_ERROR_CHECK(i2c_master_bus_rm_device(i2c_panel_io->i2c_handle));
|
||||
free(i2c_panel_io);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_io_i2c_register_event_callbacks(esp_lcd_panel_io_handle_t io, const esp_lcd_panel_io_callbacks_t *cbs, void *user_ctx)
|
||||
{
|
||||
lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base);
|
||||
|
||||
if(i2c_panel_io->on_color_trans_done != NULL) {
|
||||
ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was owerwritten!");
|
||||
}
|
||||
|
||||
i2c_panel_io->on_color_trans_done = cbs->on_color_trans_done;
|
||||
i2c_panel_io->user_ctx = user_ctx;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_io_i2c_rx_buffer(esp_lcd_panel_io_t *io, int lcd_cmd, void *buffer, size_t buffer_size)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base);
|
||||
bool send_param = (lcd_cmd >= 0);
|
||||
|
||||
int write_size = 0;
|
||||
uint8_t write_buffer[CONTROL_PHASE_LENGTH + CMD_LENGTH] = {0};
|
||||
|
||||
if (send_param) {
|
||||
if (i2c_panel_io->control_phase_enabled) {
|
||||
write_buffer[0] = i2c_panel_io->control_phase_cmd;
|
||||
write_size += 1;
|
||||
|
||||
}
|
||||
uint8_t cmds[4] = {BYTESHIFT(lcd_cmd, 3), BYTESHIFT(lcd_cmd, 2), BYTESHIFT(lcd_cmd, 1), BYTESHIFT(lcd_cmd, 0)};
|
||||
size_t cmds_size = i2c_panel_io->lcd_cmd_bits / 8;
|
||||
if (cmds_size > 0 && cmds_size <= sizeof(cmds)) {
|
||||
memcpy(write_buffer + write_size, cmds + (sizeof(cmds) - cmds_size), cmds_size);
|
||||
write_size += cmds_size;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_GOTO_ON_ERROR(i2c_master_transmit_receive(i2c_panel_io->i2c_handle, write_buffer, write_size, buffer, buffer_size, -1), err, TAG, "i2c transaction failed");
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_io_i2c_tx_buffer(esp_lcd_panel_io_t *io, int lcd_cmd, const void *buffer, size_t buffer_size, bool is_param)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base);
|
||||
bool send_param = (lcd_cmd >= 0);
|
||||
int write_size = 0;
|
||||
uint8_t *write_buffer = (uint8_t*)heap_caps_malloc(CONTROL_PHASE_LENGTH + CMD_LENGTH + buffer_size, MALLOC_CAP_8BIT);
|
||||
ESP_GOTO_ON_FALSE(write_buffer, ESP_ERR_NO_MEM, err, TAG, "no mem for write buffer");
|
||||
|
||||
if (i2c_panel_io->control_phase_enabled) {
|
||||
write_buffer[0] = is_param ? i2c_panel_io->control_phase_cmd : i2c_panel_io->control_phase_data;
|
||||
write_size += 1;
|
||||
}
|
||||
|
||||
// some displays don't want any additional commands on data transfers
|
||||
if (send_param)
|
||||
{
|
||||
uint8_t cmds[4] = {BYTESHIFT(lcd_cmd, 3), BYTESHIFT(lcd_cmd, 2), BYTESHIFT(lcd_cmd, 1), BYTESHIFT(lcd_cmd, 0)};
|
||||
size_t cmds_size = i2c_panel_io->lcd_cmd_bits / 8;
|
||||
if (cmds_size > 0 && cmds_size <= sizeof(cmds)) {
|
||||
memcpy(write_buffer + write_size, cmds + (sizeof(cmds) - cmds_size), cmds_size);
|
||||
write_size += cmds_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
memcpy(write_buffer + write_size, buffer, buffer_size);
|
||||
write_size += buffer_size;
|
||||
}
|
||||
|
||||
ESP_GOTO_ON_ERROR(i2c_master_transmit(i2c_panel_io->i2c_handle, write_buffer, write_size, -1), err, TAG, "i2c transaction failed");
|
||||
free(write_buffer);
|
||||
if (!is_param) {
|
||||
// trans done callback
|
||||
if (i2c_panel_io->on_color_trans_done) {
|
||||
i2c_panel_io->on_color_trans_done(&(i2c_panel_io->base), NULL, i2c_panel_io->user_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (write_buffer) {
|
||||
free(write_buffer);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_io_i2c_rx_param(esp_lcd_panel_io_t *io, int lcd_cmd, void *param, size_t param_size)
|
||||
{
|
||||
return panel_io_i2c_rx_buffer(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t panel_io_i2c_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
return panel_io_i2c_tx_buffer(io, lcd_cmd, param, param_size, true);
|
||||
}
|
||||
|
||||
static esp_err_t panel_io_i2c_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size)
|
||||
{
|
||||
return panel_io_i2c_tx_buffer(io, lcd_cmd, color, color_size, false);
|
||||
}
|
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
@@ -26,26 +26,27 @@ TEST_CASE("lcd_panel_with_i2c_interface_(ssd1306)", "[lcd]")
|
||||
}
|
||||
};
|
||||
|
||||
i2c_config_t conf = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
i2c_master_bus_config_t i2c_bus_conf = {
|
||||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||
.sda_io_num = TEST_I2C_SDA_GPIO,
|
||||
.scl_io_num = TEST_I2C_SCL_GPIO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = TEST_LCD_PIXEL_CLOCK_HZ,
|
||||
.i2c_port = -1,
|
||||
};
|
||||
TEST_ESP_OK(i2c_param_config(TEST_I2C_HOST_ID, &conf));
|
||||
TEST_ESP_OK(i2c_driver_install(TEST_I2C_HOST_ID, I2C_MODE_MASTER, 0, 0, 0));
|
||||
|
||||
i2c_master_bus_handle_t bus_handle;
|
||||
TEST_ESP_OK(i2c_new_master_bus(&i2c_bus_conf, &bus_handle));
|
||||
|
||||
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||
esp_lcd_panel_io_i2c_config_t io_config = {
|
||||
.dev_addr = TEST_I2C_DEV_ADDR,
|
||||
.scl_speed_hz = TEST_LCD_PIXEL_CLOCK_HZ,
|
||||
.control_phase_bytes = 1, // According to SSD1306 datasheet
|
||||
.dc_bit_offset = 6, // According to SSD1306 datasheet
|
||||
.lcd_cmd_bits = 8, // According to SSD1306 datasheet
|
||||
.lcd_param_bits = 8, // According to SSD1306 datasheet
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)TEST_I2C_HOST_ID, &io_config, &io_handle));
|
||||
|
||||
TEST_ESP_OK(esp_lcd_new_panel_io_i2c(bus_handle, &io_config, &io_handle));
|
||||
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
@@ -66,5 +67,5 @@ TEST_CASE("lcd_panel_with_i2c_interface_(ssd1306)", "[lcd]")
|
||||
|
||||
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
|
||||
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
|
||||
TEST_ESP_OK(i2c_driver_delete(TEST_I2C_HOST_ID));
|
||||
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
|
||||
}
|
||||
|
@@ -0,0 +1,5 @@
|
||||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(legacy_i2c_lcd_panel_test)
|
4
components/esp_lcd/test_apps/i2c_lcd_legacy/README.md
Normal file
4
components/esp_lcd/test_apps/i2c_lcd_legacy/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
This test app is used to test LCDs with I2C interface.
|
@@ -0,0 +1,7 @@
|
||||
set(srcs "test_app_main.c"
|
||||
"test_i2c_lcd_legacy_panel.c")
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRCS ${srcs}
|
||||
WHOLE_ARCHIVE)
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "unity_test_runner.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
// Some resources are lazy allocated in the LCD driver, the threadhold is left for that case
|
||||
#define TEST_MEMORY_LEAK_THRESHOLD (-300)
|
||||
|
||||
static size_t before_free_8bit;
|
||||
static size_t before_free_32bit;
|
||||
|
||||
static void check_leak(size_t before_free, size_t after_free, const char *type)
|
||||
{
|
||||
ssize_t delta = after_free - before_free;
|
||||
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
|
||||
TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
|
||||
}
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||
check_leak(before_free_8bit, after_free_8bit, "8BIT");
|
||||
check_leak(before_free_32bit, after_free_32bit, "32BIT");
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// ___ ____ ____ _ ____ ____ _____ _
|
||||
// |_ _|___ \ / ___| | | / ___| _ \ |_ _|__ ___| |_
|
||||
// | | __) | | | | | | | | | | | |/ _ \/ __| __|
|
||||
// | | / __/| |___ | |__| |___| |_| | | | __/\__ \ |_
|
||||
// |___|_____|\____| |_____\____|____/ |_|\___||___/\__|
|
||||
printf(" ___ ____ ____ _ ____ ____ _____ _\r\n");
|
||||
printf("|_ _|___ \\ / ___| | | / ___| _ \\ |_ _|__ ___| |_\r\n");
|
||||
printf(" | | __) | | | | | | | | | | | |/ _ \\/ __| __|\r\n");
|
||||
printf(" | | / __/| |___ | |__| |___| |_| | | | __/\\__ \\ |_\r\n");
|
||||
printf("|___|_____|\\____| |_____\\____|____/ |_|\\___||___/\\__|\r\n");
|
||||
unity_run_menu();
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TEST_LCD_H_RES 128
|
||||
#define TEST_LCD_V_RES 64
|
||||
|
||||
#define TEST_I2C_SDA_GPIO 0
|
||||
#define TEST_I2C_SCL_GPIO 2
|
||||
|
||||
#define TEST_I2C_HOST_ID 0
|
||||
|
||||
#define TEST_I2C_DEV_ADDR 0x3C
|
||||
|
||||
#define TEST_LCD_PIXEL_CLOCK_HZ (400 * 1000)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_system.h"
|
||||
#include "test_i2c_board.h"
|
||||
|
||||
TEST_CASE("lcd_panel_with_i2c_interface legacy_(ssd1306)", "[lcd]")
|
||||
{
|
||||
const uint8_t pattern[][16] = {{
|
||||
0x00, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x00,
|
||||
0x00, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x00
|
||||
},
|
||||
{
|
||||
0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81,
|
||||
0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81
|
||||
}
|
||||
};
|
||||
|
||||
i2c_config_t conf = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = TEST_I2C_SDA_GPIO,
|
||||
.scl_io_num = TEST_I2C_SCL_GPIO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = TEST_LCD_PIXEL_CLOCK_HZ,
|
||||
};
|
||||
TEST_ESP_OK(i2c_param_config(TEST_I2C_HOST_ID, &conf));
|
||||
TEST_ESP_OK(i2c_driver_install(TEST_I2C_HOST_ID, I2C_MODE_MASTER, 0, 0, 0));
|
||||
|
||||
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||
esp_lcd_panel_io_i2c_config_t io_config = {
|
||||
.dev_addr = TEST_I2C_DEV_ADDR,
|
||||
.control_phase_bytes = 1, // According to SSD1306 datasheet
|
||||
.dc_bit_offset = 6, // According to SSD1306 datasheet
|
||||
.lcd_cmd_bits = 8, // According to SSD1306 datasheet
|
||||
.lcd_param_bits = 8, // According to SSD1306 datasheet
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)TEST_I2C_HOST_ID, &io_config, &io_handle));
|
||||
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.bits_per_pixel = 1,
|
||||
.reset_gpio_num = -1,
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_panel_ssd1306(io_handle, &panel_config, &panel_handle));
|
||||
TEST_ESP_OK(esp_lcd_panel_reset(panel_handle));
|
||||
TEST_ESP_OK(esp_lcd_panel_init(panel_handle));
|
||||
// turn on display
|
||||
TEST_ESP_OK(esp_lcd_panel_disp_on_off(panel_handle, true));
|
||||
|
||||
for (int i = 0; i < TEST_LCD_H_RES / 16; i++) {
|
||||
for (int j = 0; j < TEST_LCD_V_RES / 8; j++) {
|
||||
TEST_ESP_OK(esp_lcd_panel_draw_bitmap(panel_handle, i * 16, j * 8, i * 16 + 16, j * 8 + 8, pattern[i & 0x01]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
|
||||
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
|
||||
TEST_ESP_OK(i2c_driver_delete(TEST_I2C_HOST_ID));
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32c3
|
||||
@pytest.mark.i2c_oled
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
'release',
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
def test_i2c_lcd_legacy(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases()
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
@@ -0,0 +1,5 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
# CONFIG_ESP_TASK_WDT_INIT is not set
|
||||
CONFIG_FREERTOS_HZ=1000
|
Reference in New Issue
Block a user