From a44f6102a8a611068054f12438eb856e0e081f1a Mon Sep 17 00:00:00 2001 From: Mike Dunston Date: Mon, 21 Nov 2022 06:31:12 -0800 Subject: [PATCH] Adding support for parallel IO mode using 16-bit color Fixes: https://github.com/atanisoft/esp_lcd_ili9488/issues/2 --- CHANGELOG.md | 6 +++ esp_lcd_ili9488.c | 78 ++++++++++++++++++++++++--------------- idf_component.yml | 2 +- include/esp_lcd_ili9488.h | 10 ++++- 4 files changed, 65 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e364b74..30649e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change log for esp_lcd_ili9488 +## v1.0.5 - Add 16-bit support for parallel IO interface support + +Parallel IO mode (Intel 8080 interface) should use 16-bit color mode instead +of being forced into 18-bit color mode that is required for use when the SPI +interface is used. + ## v1.0.4 - License tagging fixes This release only updates the SPDX license tagging of source files. diff --git a/esp_lcd_ili9488.c b/esp_lcd_ili9488.c index ce73824..eb8b46f 100644 --- a/esp_lcd_ili9488.c +++ b/esp_lcd_ili9488.c @@ -36,7 +36,8 @@ typedef struct bool reset_level; int x_gap; int y_gap; - uint8_t madctl_val; + uint8_t memory_access_control; + uint8_t color_mode; } ili9488_panel_t; enum ili9488_constants @@ -130,8 +131,8 @@ static esp_err_t panel_ili9488_init(esp_lcd_panel_t *panel) { ILI9488_POWER_CTL_ONE, { 0x17, 0x15 }, 2 }, { ILI9488_POWER_CTL_TWO, { 0x41 }, 1 }, { ILI9488_POWER_CTL_THREE, { 0x00, 0x12, 0x80 }, 3 }, - { LCD_CMD_MADCTL, { ili9488->madctl_val }, 1 }, - { LCD_CMD_COLMOD, { ILI9488_COLOR_MODE_18BIT }, 1 }, + { LCD_CMD_MADCTL, { ili9488->memory_access_control }, 1 }, + { LCD_CMD_COLMOD, { ili9488->color_mode }, 1 }, { ILI9488_INTRFC_MODE_CTL, { ILI9488_INTERFACE_MODE_USE_SDO }, 1 }, { ILI9488_FRAME_RATE_NORMAL_CTL, { ILI9488_FRAME_RATE_60HZ }, 1 }, { ILI9488_INVERSION_CTL, { 0x02 }, 1 }, @@ -193,27 +194,40 @@ static esp_err_t panel_ili9488_draw_bitmap( SEND_COORDS(x_start, x_end, io, LCD_CMD_CASET); SEND_COORDS(y_start, y_end, io, LCD_CMD_RASET); - uint8_t *buf = NULL; - while (buf == NULL) + // When the ILI9488 is used in 18-bit color mode we need to convert the + // incoming color data from RGB565 (16-bit) to RGB666. This unfortunately + // requires a buffer to be allocated. + // + // NOTE: 16-bit color does not work via SPI interface :( + if (ili9488->color_mode == ILI9488_COLOR_MODE_18BIT) { - buf = (uint8_t *) heap_caps_malloc(color_data_len * 3, MALLOC_CAP_DMA); - if (buf == NULL) + uint8_t *buf = NULL; + while (buf == NULL) { - ESP_LOGW(TAG, "Could not allocate enough DMA memory!"); + buf = (uint8_t *) heap_caps_malloc(color_data_len * 3, MALLOC_CAP_DMA); + if (buf == NULL) + { + ESP_LOGW(TAG, "Could not allocate enough DMA memory!"); + } } - } - uint16_t *raw_color_data = (uint16_t *) color_data; - for (uint32_t i = 0, pixel_index = 0; i < color_data_len; i++) { - buf[pixel_index++] = (uint8_t) (((raw_color_data[i] & 0xF800) >> 8) | - ((raw_color_data[i] & 0x8000) >> 13)); - buf[pixel_index++] = (uint8_t) ((raw_color_data[i] & 0x07E0) >> 3); - buf[pixel_index++] = (uint8_t) (((raw_color_data[i] & 0x001F) << 3) | - ((raw_color_data[i] & 0x0010) >> 2)); - } + uint16_t *raw_color_data = (uint16_t *) color_data; + for (uint32_t i = 0, pixel_index = 0; i < color_data_len; i++) { + buf[pixel_index++] = (uint8_t) (((raw_color_data[i] & 0xF800) >> 8) | + ((raw_color_data[i] & 0x8000) >> 13)); + buf[pixel_index++] = (uint8_t) ((raw_color_data[i] & 0x07E0) >> 3); + buf[pixel_index++] = (uint8_t) (((raw_color_data[i] & 0x001F) << 3) | + ((raw_color_data[i] & 0x0010) >> 2)); + } - esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, buf, color_data_len * 3); - heap_caps_free(buf); + esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, buf, color_data_len * 3); + heap_caps_free(buf); + } + else + { + // 16-bit color we can transmit as-is to the display. + esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, color_data_len * 2); + } return ESP_OK; } @@ -245,21 +259,21 @@ static esp_err_t panel_ili9488_mirror( esp_lcd_panel_io_handle_t io = ili9488->io; if (mirror_x) { - ili9488->madctl_val |= LCD_CMD_MX_BIT; + ili9488->memory_access_control |= LCD_CMD_MX_BIT; } else { - ili9488->madctl_val &= ~LCD_CMD_MX_BIT; + ili9488->memory_access_control &= ~LCD_CMD_MX_BIT; } if (mirror_y) { - ili9488->madctl_val |= LCD_CMD_MY_BIT; + ili9488->memory_access_control |= LCD_CMD_MY_BIT; } else { - ili9488->madctl_val &= ~LCD_CMD_MY_BIT; + ili9488->memory_access_control &= ~LCD_CMD_MY_BIT; } - esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, &ili9488->madctl_val, 1); + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, &ili9488->memory_access_control, 1); return ESP_OK; } @@ -269,13 +283,13 @@ static esp_err_t panel_ili9488_swap_xy(esp_lcd_panel_t *panel, bool swap_axes) esp_lcd_panel_io_handle_t io = ili9488->io; if (swap_axes) { - ili9488->madctl_val |= LCD_CMD_MV_BIT; + ili9488->memory_access_control |= LCD_CMD_MV_BIT; } else { - ili9488->madctl_val &= ~LCD_CMD_MV_BIT; + ili9488->memory_access_control &= ~LCD_CMD_MV_BIT; } - esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, &ili9488->madctl_val, 1); + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, &ili9488->memory_access_control, 1); return ESP_OK; } @@ -337,12 +351,18 @@ esp_err_t esp_lcd_new_panel_ili9488( "configure GPIO for RESET line failed"); } - ili9488->madctl_val = LCD_CMD_MX_BIT | LCD_CMD_BGR_BIT; + ili9488->color_mode = ILI9488_COLOR_MODE_18BIT; + if (panel_dev_config->bits_per_pixel == 16) + { + ili9488->color_mode = ILI9488_COLOR_MODE_16BIT; + } + + ili9488->memory_access_control = LCD_CMD_MX_BIT | LCD_CMD_BGR_BIT; switch (panel_dev_config->color_space) { case ESP_LCD_COLOR_SPACE_RGB: ESP_LOGI(TAG, "Configuring for RGB color order"); - ili9488->madctl_val &= ~LCD_CMD_BGR_BIT; + ili9488->memory_access_control &= ~LCD_CMD_BGR_BIT; break; case ESP_LCD_COLOR_SPACE_BGR: ESP_LOGI(TAG, "Configuring for BGR color order"); diff --git a/idf_component.yml b/idf_component.yml index 1f34c58..dfe1abe 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -2,4 +2,4 @@ dependencies: idf: '>=4.4.2' description: esp_lcd driver for ILI9488 displays url: https://github.com/atanisoft/esp_lcd_ili9488 -version: 1.0.4 +version: 1.0.5 diff --git a/include/esp_lcd_ili9488.h b/include/esp_lcd_ili9488.h index 479b1f1..64a2463 100644 --- a/include/esp_lcd_ili9488.h +++ b/include/esp_lcd_ili9488.h @@ -22,8 +22,16 @@ extern "C" { * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_ERR_NO_MEM if out of memory * - ESP_OK on success + * + * NOTE: If you are using the SPI interface you *MUST* 18-bit color mode + * in @param panel_dev_config field bits_per_pixel. + * + * NOTE: For parallel IO (Intel 8080) interface 16-bit color mode should + * be used. */ -esp_err_t esp_lcd_new_panel_ili9488(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel); +esp_err_t esp_lcd_new_panel_ili9488(const esp_lcd_panel_io_handle_t io, + const esp_lcd_panel_dev_config_t *panel_dev_config, + esp_lcd_panel_handle_t *ret_panel); #ifdef __cplusplus }