esp_lcd: Add support for rx_param on I2C transport.

This commit is contained in:
Vilem Zavodny
2022-05-06 09:41:54 +02:00
parent 0eafe4d326
commit 4a2766d906
4 changed files with 98 additions and 3 deletions

View File

@@ -26,6 +26,7 @@ static const char *TAG = "lcd_panel.io.i2c";
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
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);
@@ -35,6 +36,7 @@ typedef struct {
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
@@ -59,10 +61,12 @@ esp_err_t esp_lcd_new_panel_io_i2c(esp_lcd_i2c_bus_handle_t bus, const esp_lcd_p
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;
*ret_io = &(i2c_panel_io->base);
@@ -83,6 +87,47 @@ static esp_err_t panel_io_i2c_del(esp_lcd_panel_io_t *io)
return ret;
}
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);
i2c_cmd_handle_t cmd_link = i2c_cmd_link_create_static(i2c_panel_io->cmdlink_buffer, CMD_HANDLER_BUFFER_SIZE);
ESP_GOTO_ON_FALSE(cmd_link, ESP_ERR_NO_MEM, err, TAG, "no mem for i2c cmd link");
ESP_GOTO_ON_ERROR(i2c_master_start(cmd_link), err, TAG, "issue start failed"); // start phase
ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, (i2c_panel_io->dev_addr << 1) | I2C_MASTER_WRITE, true), err, TAG, "write address failed"); // address phase
if (send_param) {
if (i2c_panel_io->control_phase_enabled) {
ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, i2c_panel_io->control_phase_cmd, true),
err, TAG, "write control phase failed"); // control phase
}
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)) {
ESP_GOTO_ON_ERROR(i2c_master_write(cmd_link, cmds + (sizeof(cmds) - cmds_size), cmds_size, true), err, TAG, "write LCD cmd failed");
}
}
if (buffer) {
ESP_GOTO_ON_ERROR(i2c_master_start(cmd_link), err, TAG, "issue start failed"); // start phase
ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, (i2c_panel_io->dev_addr << 1) | I2C_MASTER_READ, true), err, TAG, "write address failed"); // address phase
ESP_GOTO_ON_ERROR(i2c_master_read(cmd_link, buffer, buffer_size, I2C_MASTER_LAST_NACK), err, TAG, "read data failed");
}
ESP_GOTO_ON_ERROR(i2c_master_stop(cmd_link), err, TAG, "issue stop failed"); // stop phase
ESP_GOTO_ON_ERROR(i2c_master_cmd_begin(i2c_panel_io->i2c_bus_id, cmd_link, portMAX_DELAY), err, TAG, "i2c transaction failed");
i2c_cmd_link_delete_static(cmd_link);
return ESP_OK;
err:
if (cmd_link) {
i2c_cmd_link_delete_static(cmd_link);
}
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;
@@ -92,8 +137,10 @@ static esp_err_t panel_io_i2c_tx_buffer(esp_lcd_panel_io_t *io, int lcd_cmd, con
ESP_GOTO_ON_FALSE(cmd_link, ESP_ERR_NO_MEM, err, TAG, "no mem for i2c cmd link");
ESP_GOTO_ON_ERROR(i2c_master_start(cmd_link), err, TAG, "issue start failed"); // start phase
ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, (i2c_panel_io->dev_addr << 1) | I2C_MASTER_WRITE, true), err, TAG, "write address failed"); // address phase
ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, is_param ? i2c_panel_io->control_phase_cmd : i2c_panel_io->control_phase_data, true),
err, TAG, "write control phase failed"); // control phase
if (i2c_panel_io->control_phase_enabled) {
ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, is_param ? i2c_panel_io->control_phase_cmd : i2c_panel_io->control_phase_data, true),
err, TAG, "write control phase failed"); // control phase
}
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)) {
@@ -123,6 +170,11 @@ err:
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);