Skip to content

Commit

Permalink
Misc updates..
Browse files Browse the repository at this point in the history
1. Update code to ignore bits_per_pixel as this driver only supports 18-bit output.
2. Update example to provide option for not having double buffering, use lv timers, for animations, remove unused methods, additional logging.
  • Loading branch information
atanisoft committed Nov 11, 2022
1 parent a6cf491 commit e12b792
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 151 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
examples/**/build
examples/**/sdkconfig
examples/**/dependencies.lock
examples/**/managed_components
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ At this time testing is limited to ESP32 and ESP32-S3, other ESP32 variants shou

## Required sdkconfig entries

Since the ILI9488 display uses 18 bit color values it is required to set `CONFIG_LV_COLOR_DEPTH_32=y` in your sdkconfig.
This driver converts the color data from 16-bit to 18-bit as part of the `draw_bitmap` callback.
Therefore it is required to set `CONFIG_LV_COLOR_DEPTH_16=y` in your sdkconfig. In the future other
color depths may be supported.
186 changes: 84 additions & 102 deletions esp_lcd_ili9488.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ typedef struct
int x_gap;
int y_gap;
uint8_t madctl_val;
uint8_t colmod_cal;
} ili9488_panel_t;

enum ILI9488_CONSTANTS
enum ili9488_constants
{
ILI9488_INTRFC_MODE_CTL = 0xB0,
ILI9488_FRAME_RATE_NORMAL_CTL = 0xB1,
Expand All @@ -66,41 +65,9 @@ enum ILI9488_CONSTANTS
ILI9488_FRAME_RATE_60HZ = 0xA0,

ILI9488_INIT_LENGTH_MASK = 0x1F,
ILI9488_INIT_DELAY_FLAG = 0x80,
ILI9488_INIT_DONE_FLAG = 0xFF
};

static const lcd_init_cmd_t ili9488_init[] =
{
{ ILI9488_POSITIVE_GAMMA_CTL,
{ 0x00, 0x03, 0x09, 0x08, 0x16,
0x0A, 0x3F, 0x78, 0x4C, 0x09,
0x0A, 0x08, 0x16, 0x1A, 0x0F },
15
},
{ ILI9488_NEGATIVE_GAMMA_CTL,
{ 0x00, 0x16, 0x19, 0x03, 0x0F,
0x05, 0x32, 0x45, 0x46, 0x04,
0x0E, 0x0D, 0x35, 0x37, 0x0F},
15
},
{ ILI9488_POWER_CTL_ONE, { 0x17, 0x15 }, 2 },
{ ILI9488_POWER_CTL_TWO, { 0x41 }, 1 },
{ ILI9488_POWER_CTL_THREE, { 0x00, 0x12, 0x80 }, 3 },
{ LCD_CMD_MADCTL, { LCD_CMD_MX_BIT | LCD_CMD_BGR_BIT }, 1 },
{ LCD_CMD_COLMOD, { ILI9488_COLOR_MODE_18BIT }, 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 },
{ ILI9488_FUNCTION_CTL, { 0x02, 0x02, 0x3B }, 3},
{ ILI9488_ENTRY_MODE_CTL, { 0xC6 }, 1 },
{ ILI9488_ADJUST_CTL_THREE, { 0xA9, 0x51, 0x2C, 0x02 }, 4 },
{ LCD_CMD_SLPOUT, { 0x00 }, ILI9488_INIT_DELAY_FLAG },
{ LCD_CMD_DISPON, { 0x00 }, ILI9488_INIT_DELAY_FLAG },

{ LCD_CMD_NOP, { 0 }, ILI9488_INIT_DONE_FLAG },
};

static esp_err_t panel_ili9488_del(esp_lcd_panel_t *panel)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
Expand Down Expand Up @@ -146,11 +113,35 @@ static esp_err_t panel_ili9488_init(esp_lcd_panel_t *panel)
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
esp_lcd_panel_io_handle_t io = ili9488->io;

lcd_init_cmd_t ili9488_init[] =
{
{ ILI9488_POSITIVE_GAMMA_CTL,
{ 0x00, 0x03, 0x09, 0x08, 0x16,
0x0A, 0x3F, 0x78, 0x4C, 0x09,
0x0A, 0x08, 0x16, 0x1A, 0x0F },
15
},
{ ILI9488_NEGATIVE_GAMMA_CTL,
{ 0x00, 0x16, 0x19, 0x03, 0x0F,
0x05, 0x32, 0x45, 0x46, 0x04,
0x0E, 0x0D, 0x35, 0x37, 0x0F},
15
},
{ 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 },
{ 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 },
{ ILI9488_FUNCTION_CTL, { 0x02, 0x02, 0x3B }, 3},
{ ILI9488_ENTRY_MODE_CTL, { 0xC6 }, 1 },
{ ILI9488_ADJUST_CTL_THREE, { 0xA9, 0x51, 0x2C, 0x02 }, 4 },
{ LCD_CMD_NOP, { 0 }, ILI9488_INIT_DONE_FLAG },
};

ESP_LOGI(TAG, "Initializing ILI9488");
esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0);
vTaskDelay(pdMS_TO_TICKS(100));
esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, &ili9488->madctl_val, 1);
esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, &ili9488->colmod_cal, 1);
int cmd = 0;
while ( ili9488_init[cmd].data_bytes != ILI9488_INIT_DONE_FLAG )
{
Expand All @@ -159,19 +150,30 @@ static esp_err_t panel_ili9488_init(esp_lcd_panel_t *panel)
esp_lcd_panel_io_tx_param(
io, ili9488_init[cmd].cmd, ili9488_init[cmd].data,
ili9488_init[cmd].data_bytes & ILI9488_INIT_LENGTH_MASK);
if (ili9488_init[cmd].data_bytes & ILI9488_INIT_DELAY_FLAG)
{
ESP_LOGI(TAG, "Delaying 100ms");
vTaskDelay(pdMS_TO_TICKS(100));
}
cmd++;
}

// Take the display out of sleep mode.
esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0);
vTaskDelay(pdMS_TO_TICKS(100));

// Turn on the display.
esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, NULL, 0);
vTaskDelay(pdMS_TO_TICKS(100));

ESP_LOGI(TAG, "Initialization complete");

return ESP_OK;
}

#define SEND_COORDS(start, end, io, cmd) \
esp_lcd_panel_io_tx_param(io, cmd, (uint8_t[]) { \
(start >> 8) & 0xFF, \
start & 0xFF, \
((end - 1) >> 8) & 0xFF, \
(end - 1) & 0xFF, \
}, 4)

static esp_err_t panel_ili9488_draw_bitmap(
esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end,
const void *color_data)
Expand All @@ -186,67 +188,53 @@ static esp_err_t panel_ili9488_draw_bitmap(
y_start += ili9488->y_gap;
y_end += ili9488->y_gap;

size_t len = (x_end - x_start) * (y_end - y_start);

esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) {
(x_start >> 8) & 0xFF,
x_start & 0xFF,
((x_end - 1) >> 8) & 0xFF,
(x_end - 1) & 0xFF,
}, 4);
esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) {
(y_start >> 8) & 0xFF,
y_start & 0xFF,
((y_end - 1) >> 8) & 0xFF,
(y_end - 1) & 0xFF,
}, 4);

if (ili9488->colmod_cal == ILI9488_COLOR_MODE_18BIT)
{
uint32_t *buffer_32bit = (uint32_t *) color_data;
uint8_t *mybuf = NULL;
while (mybuf == NULL)
{
mybuf = (uint8_t *) heap_caps_malloc(len * 3, MALLOC_CAP_DMA);
if (mybuf == NULL)
{
ESP_LOGW(TAG, "Could not allocate enough DMA memory!");
}
}
size_t color_data_len = (x_end - x_start) * (y_end - y_start);

uint32_t pixel_color = 0;
uint32_t pixel_index = 0;
SEND_COORDS(x_start, x_end, io, LCD_CMD_CASET);
SEND_COORDS(y_start, y_end, io, LCD_CMD_RASET);

for (uint32_t i = 0; i < len; i++) {
pixel_color = buffer_32bit[i];
mybuf[pixel_index++] = (uint8_t) (((pixel_color & 0xF800) >> 8) |
((pixel_color & 0x8000) >> 13));
mybuf[pixel_index++] = (uint8_t) ((pixel_color & 0x07E0) >> 3);
mybuf[pixel_index++] = (uint8_t) (((pixel_color & 0x001F) << 3) |
((pixel_color & 0x0010) >> 2));
uint8_t *buf = NULL;
while (buf == NULL)
{
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!");
}
esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, mybuf, len * 3);
heap_caps_free(mybuf);
}
else
{
esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len * 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);

return ESP_OK;
}

#undef SEND_COORDS

static esp_err_t panel_ili9488_invert_color(
esp_lcd_panel_t *panel, bool invert_color_data)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
esp_lcd_panel_io_handle_t io = ili9488->io;
int command = LCD_CMD_INVOFF;

if (invert_color_data)
{
command = LCD_CMD_INVON;
esp_lcd_panel_io_tx_param(io, LCD_CMD_INVON, NULL, 0);
}
else
{
esp_lcd_panel_io_tx_param(io, LCD_CMD_INVOFF, NULL, 0);
}
esp_lcd_panel_io_tx_param(io, command, NULL, 0);

return ESP_OK;
}

Expand Down Expand Up @@ -304,21 +292,25 @@ static esp_err_t panel_ili9488_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
{
ili9488_panel_t *ili9488 = __containerof(panel, ili9488_panel_t, base);
esp_lcd_panel_io_handle_t io = ili9488->io;
int command = 0;

#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
// In ESP-IDF v4.x the API used false for "on" and true for "off"
// invert the logic to be consistent with IDF v5.x.
on_off = !on_off;
#endif

if (on_off)
{
command = LCD_CMD_DISPON;
esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, NULL, 0);
}
else
{
command = LCD_CMD_DISPOFF;
esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPOFF, NULL, 0);
}
esp_lcd_panel_io_tx_param(io, command, NULL, 0);

// give time for the ILI9488 to recover after an on/off command
vTaskDelay(pdMS_TO_TICKS(100));

return ESP_OK;
}

Expand Down Expand Up @@ -360,16 +352,6 @@ esp_err_t esp_lcd_new_panel_ili9488(
"Unsupported color mode!");
}

if (panel_dev_config->bits_per_pixel == 16)
{
ili9488->colmod_cal = ILI9488_COLOR_MODE_16BIT;
ESP_LOGI(TAG, "Configuring for 16-bit colors");
}
else
{
ili9488->colmod_cal = ILI9488_COLOR_MODE_18BIT;
ESP_LOGI(TAG, "Configuring for 18-bit colors");
}

ili9488->io = io;
ili9488->reset_gpio_num = panel_dev_config->reset_gpio_num;
Expand Down Expand Up @@ -402,4 +384,4 @@ esp_err_t esp_lcd_new_panel_ili9488(
free(ili9488);
}
return ret;
}
}
21 changes: 21 additions & 0 deletions examples/lvgl/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ menu "Pin Configuration"
range -1 48 if IDF_TARGET_ESP32S3
default 3 if IDF_TARGET_ESP32S3
default 16

config TFT_RESET_PIN
int
range -1 33 if IDF_TARGET_ESP32
range -1 48 if IDF_TARGET_ESP32S3
default 46 if IDF_TARGET_ESP32S3
default -1

config TFT_DC_PIN
int
Expand All @@ -42,3 +49,17 @@ menu "Pin Configuration"
default 18
endmenu
endmenu

choice DISPLAY_COLOR_MODE
bool "Color Mode"
default DISPLAY_COLOR_MODE_BGR
config DISPLAY_COLOR_MODE_BGR
bool "Blue,Green,Red"
config DISPLAY_COLOR_MODE_RGB
bool "Red,Green,Blue"
endchoice

config DISPLAY_COLOR_MODE
int
default 1 if DISPLAY_COLOR_MODE_BGR
default 0 if DISPLAY_COLOR_MODE_RGB
Loading

0 comments on commit e12b792

Please sign in to comment.