Skip to content

Support ILI9163c #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_RA8875)
list(APPEND SOURCES "lvgl_tft/ra8875.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01)
list(APPEND SOURCES "lvgl_tft/GC9A01.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
list(APPEND SOURCES "lvgl_tft/ili9163c.c")
else()
message(WARNING "LVGL ESP32 drivers: Display controller not defined.")
endif()
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ swap of RGB565 color on the LVGL configuration menuconfig (it's not handled auto
| Display Controller | Type | Interface | Color depth (LV_COLOR_DEPTH) | Swap RGB565 color (LV_COLOR_16_SWAP) |
|---------------------------------------------|------------|------------------------|------------------------------|----------------------------------------|
| ILI9341 | TFT | SPI | 16: RGB565 | Yes |
| ILI9163C | TFT | SPI | 16: RGB565 | Yes |
| ILI9486 | TFT | SPI | 16: RGB565 | Yes |
| ILI9488 | TFT | SPI | 16: RGB565 | No |
| HX8357B/HX8357D | TFT | SPI | 16: RGB565 | Yes |
Expand Down
2 changes: 2 additions & 0 deletions lvgl_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ extern "C" {
#define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 5KB
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D)
#define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 2888 bytes
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#else
#error "No display controller selected"
#endif
Expand Down
7 changes: 5 additions & 2 deletions lvgl_spi_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ extern "C" {
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A)
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A) || \
defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)

#define SPI_BUS_MAX_TRANSFER_SZ (DISP_BUF_SIZE * 2)

Expand All @@ -157,7 +158,9 @@ extern "C" {
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341)
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
#elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
#define SPI_TFT_CLOCK_SPEED_HZ (40 * 1000 * 1000)
#elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
#define SPI_TFT_CLOCK_SPEED_HZ (32*1000*1000)
#else
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
Expand Down
11 changes: 10 additions & 1 deletion lvgl_tft/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ menu "LVGL TFT Display controller"
help
ST7796S display controller.

config LV_TFT_DISPLAY_CONTROLLER_ILI9163C
bool
help
ILI9163C display controller.

# Display controller communication protocol
#
# This symbols define the communication protocol used by the
Expand Down Expand Up @@ -331,6 +336,10 @@ menu "LVGL TFT Display controller"
bool "RA8875"
select LV_TFT_DISPLAY_CONTROLLER_RA8875
select LV_TFT_DISPLAY_PROTOCOL_SPI
config LV_TFT_DISPLAY_USER_CONTROLLER_ILI9163C
bool "ILI9163C"
select LV_TFT_DISPLAY_CONTROLLER_ILI9163C
select LV_TFT_DISPLAY_PROTOCOL_SPI
endchoice

config CUSTOM_DISPLAY_BUFFER_SIZE
Expand Down Expand Up @@ -590,7 +599,7 @@ menu "LVGL TFT Display controller"
If text is backwards on your display, try enabling this.

config LV_INVERT_COLORS
bool "Invert colors in display" if LV_TFT_DISPLAY_CONTROLLER_ILI9341 || LV_TFT_DISPLAY_CONTROLLER_ST7735S || LV_TFT_DISPLAY_CONTROLLER_ILI9481 || LV_TFT_DISPLAY_CONTROLLER_ST7789 || LV_TFT_DISPLAY_CONTROLLER_SSD1306 || LV_TFT_DISPLAY_CONTROLLER_SH1107 || LV_TFT_DISPLAY_CONTROLLER_HX8357 || LV_TFT_DISPLAY_CONTROLLER_GC9A01
bool "Invert colors in display" if LV_TFT_DISPLAY_CONTROLLER_ILI9341 || LV_TFT_DISPLAY_CONTROLLER_ST7735S || LV_TFT_DISPLAY_CONTROLLER_ILI9481 || LV_TFT_DISPLAY_CONTROLLER_ST7789 || LV_TFT_DISPLAY_CONTROLLER_SSD1306 || LV_TFT_DISPLAY_CONTROLLER_SH1107 || LV_TFT_DISPLAY_CONTROLLER_HX8357 || LV_TFT_DISPLAY_CONTROLLER_GC9A01 || LV_TFT_DISPLAY_CONTROLLER_ILI9163C
default y if LV_PREDEFINED_DISPLAY_M5STACK || LV_PREDEFINED_DISPLAY_M5STICKC
help
If the colors look inverted on your display, try enabling this.
Expand Down
8 changes: 6 additions & 2 deletions lvgl_tft/disp_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void disp_driver_init(void)
st7735s_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_HX8357
hx8357_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9486
ili9486_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SH1107
sh1107_init();
Expand All @@ -39,6 +39,8 @@ void disp_driver_init(void)
jd79653a_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
uc8151d_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
ili9163c_init();
#endif
}

Expand Down Expand Up @@ -76,6 +78,8 @@ void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t *
jd79653a_lv_fb_flush(drv, area, color_map);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
uc8151d_lv_fb_flush(drv, area, color_map);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
ili9163c_flush(drv, area, color_map);
#endif
}

Expand All @@ -95,7 +99,7 @@ void disp_driver_rounder(lv_disp_drv_t * disp_drv, lv_area_t * area)
}

void disp_driver_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa)
lv_color_t color, lv_opa_t opa)
{
#if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306
ssd1306_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
Expand Down
2 changes: 2 additions & 0 deletions lvgl_tft/disp_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ extern "C" {
#include "jd79653a.h"
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
#include "uc8151d.h"
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
#include "ili9163c.h"
#endif

/*********************
Expand Down
270 changes: 270 additions & 0 deletions lvgl_tft/ili9163c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
/**
* @file ILI9163C.c
*
*/

/*********************
* INCLUDES
*********************/
#include "ili9163c.h"
#include "disp_spi.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "assert.h"

/*********************
* DEFINES
*********************/
#define TAG "ILI9163C"

// ILI9163C specific commands used in init
#define ILI9163C_NOP 0x00
#define ILI9163C_SWRESET 0x01
#define ILI9163C_RDDID 0x04
#define ILI9163C_RDDST 0x09

#define ILI9163C_SLPIN 0x10
#define ILI9163C_SLPOUT 0x11
#define ILI9163C_PTLON 0x12
#define ILI9163C_NORON 0x13

#define ILI9163C_INVOFF 0x20
#define ILI9163C_INVON 0x21
#define ILI9163C_CMD_GAMST 0x26
#define ILI9163C_DISPOFF 0x28
#define ILI9163C_DISPON 0x29
#define ILI9163C_CASET 0x2A
#define ILI9163C_RASET 0x2B
#define ILI9163C_RAMWR 0x2C
#define ILI9163C_COLORSET 0x2D
#define ILI9163C_RAMRD 0x2E

#define ILI9163C_PTLAR 0x30
#define ILI9163C_VSCRDEF 0x33
#define ILI9163C_COLMOD 0x3A
#define ILI9163C_MADCTL 0x36
#define ILI9163C_VSCRSADD 0x37

#define ILI9163C_FRMCTR1 0xB1
#define ILI9163C_FRMCTR2 0xB2
#define ILI9163C_FRMCTR3 0xB3
#define ILI9163C_INVCTR 0xB4
#define ILI9163C_DISSET5 0xB6
#define ILI9163C_SDDC 0xB7

#define ILI9163C_PWCTR1 0xC0
#define ILI9163C_PWCTR2 0xC1
#define ILI9163C_PWCTR3 0xC2
#define ILI9163C_PWCTR4 0xC3
#define ILI9163C_PWCTR5 0xC4
#define ILI9163C_VMCTR1 0xC5
#define ILI9163C_VMCOFFS 0xC7

#define ILI9163C_GAMCTL 0xF2

#define ILI9163C_GMCTRP1 0xE0
#define ILI9163C_GMCTRN1 0xE1

#define ST77XX_MADCTL_MY 0x80
#define ST77XX_MADCTL_MX 0x40
#define ST77XX_MADCTL_MV 0x20 #define
#define ST77XX_MADCTL_ML 0x10
#define ST77XX_MADCTL_RGB 0x00
#define ST77XX_MADCTL_BGR 0x08

/**********************
* TYPEDEFS
**********************/

/*The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct. */
typedef struct
{
uint8_t cmd;
uint8_t data[16];
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
} lcd_init_cmd_t;

/**********************
* STATIC PROTOTYPES
**********************/
static void ili9163c_set_orientation(uint8_t orientation);

static void ili9163c_send_cmd(uint8_t cmd);
static void ili9163c_send_data(void *data, uint16_t length);
static void ili9163c_send_color(void *data, uint16_t length);

/**********************
* STATIC VARIABLES
**********************/

/**********************
* MACROS
**********************/

/**********************
* GLOBAL FUNCTIONS
**********************/

void ili9163c_init(void)
{
ESP_LOGD(TAG, "Init");

lcd_init_cmd_t ili_init_cmds[] = {
{ILI9163C_SWRESET, {0}, 0x80}, // Software reset, 0 args, w/delay 120ms
{ILI9163C_SLPOUT, {0}, 0x80}, // Out of sleep mode, 0 args, w/delay 5ms
{ILI9163C_CMD_GAMST, {0x04}, 1}, // Gamma Curve
{ILI9163C_FRMCTR1, {0x0C, 0x14}, 2}, // Frame rate ctrl - normal mode
{ILI9163C_INVCTR, {0x07}, 1}, // Display inversion ctrl, 1 arg, no delay:No inversion
{ILI9163C_PWCTR1, {0x0C, 0x05}, 2}, // Power control, 2 args, no delay
{ILI9163C_PWCTR2, {0x02}, 1}, // Power control, 1 arg
{ILI9163C_PWCTR3, {0x02}, 1}, // Power control, 1 arg
{ILI9163C_VMCTR1, {0x20, 0x55}, 2}, // Power control, 1 arg, no delay:
{ILI9163C_VMCOFFS, {0x40}, 1}, // VCOM Offset
#if ILI9163C_INVERT_COLORS == 1
{ILI9163C_INVON, {0}, 0}, // set inverted mode
#else
{ILI9163C_INVOFF, {0}, 0}, // set non-inverted mode
#endif
{ILI9163C_COLMOD, {0x5}, 1}, // set color mode, 1 arg, no delay: 16-bit color
{ILI9163C_SDDC, {0}, 1}, // set source driver direction control
{ILI9163C_GAMCTL, {0x01}, 1}, // set source driver direction control
{ILI9163C_GMCTRP1, {0x36, 0x29, 0x12, 0x22, 0x1C, 0x15, 0x42, 0xB7, 0x2F, 0x13, 0x12, 0x0A, 0x11, 0x0B, 0x06}, 16}, // 16 args, no delay:
{ILI9163C_GMCTRN1, {0x09, 0x16, 0x2D, 0x0D, 0x13, 0x15, 0x40, 0x48, 0x53, 0x0C, 0x1D, 0x25, 0x2E, 0x34, 0x39}, 16}, // 16 args, no delay:
{ILI9163C_NORON, {0}, 0x80}, // Normal display on, no args, w/delay 10 ms delay
{ILI9163C_DISPON, {0}, 0x80}, // Main screen turn on, no args w/delay 100 ms delay
{0, {0}, 0xff}
};

//Initialize non-SPI GPIOs
gpio_pad_select_gpio(ILI9163C_DC);
gpio_set_direction(ILI9163C_DC, GPIO_MODE_OUTPUT);
gpio_pad_select_gpio(ILI9163C_RST);
gpio_set_direction(ILI9163C_RST, GPIO_MODE_OUTPUT);

#if ILI9163C_ENABLE_BACKLIGHT_CONTROL
gpio_pad_select_gpio(ILI9163C_BCKL);
gpio_set_direction(ILI9163C_BCKL, GPIO_MODE_OUTPUT);
#endif
//Reset the display
gpio_set_level(ILI9163C_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(ILI9163C_RST, 1);
vTaskDelay(150 / portTICK_RATE_MS);

//Send all the commands
uint16_t cmd = 0;
while (ili_init_cmds[cmd].databytes != 0xff)
{
ili9163c_send_cmd(ili_init_cmds[cmd].cmd);
ili9163c_send_data(ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes & 0x1F);
if (ili_init_cmds[cmd].databytes & 0x80)
{
vTaskDelay(150 / portTICK_RATE_MS);
}
cmd++;
}

ili9163c_enable_backlight(true);

ili9163c_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION);
}

void ili9163c_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{
uint8_t data[4];

/*Column addresses*/
ili9163c_send_cmd(ILI9163C_CASET);
data[0] = (area->x1 >> 8) & 0xFF;
data[1] = area->x1 & 0xFF;
data[2] = (area->x2 >> 8) & 0xFF;
data[3] = area->x2 & 0xFF;
ili9163c_send_data(data, 4);

/*Page addresses*/
ili9163c_send_cmd(ILI9163C_RASET);
data[0] = (area->y1 >> 8) & 0xFF;
data[1] = area->y1 & 0xFF;
data[2] = (area->y2 >> 8) & 0xFF;
data[3] = area->y2 & 0xFF;
ili9163c_send_data(data, 4);

/*Memory write*/
ili9163c_send_cmd(ILI9163C_RAMWR);

uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);

ili9163c_send_color((void *)color_map, size * 2);
}

void ili9163c_enable_backlight(bool backlight)
{
#if ILI9163C_ENABLE_BACKLIGHT_CONTROL
ESP_LOGD(TAG, "%s backlight.", backlight ? "Enabling" : "Disabling");
uint32_t tmp = 0;

#if (ILI9163C_BCKL_ACTIVE_LVL == 1)
tmp = backlight ? 1 : 0;
#else
tmp = backlight ? 0 : 1;
#endif

gpio_set_level(ILI9163C_BCKL, tmp);
#endif
}

void ili9163c_sleep_in()
{
uint8_t data[] = {0x08};
ili9163c_send_cmd(ILI9163C_SLPIN);
ili9163c_send_data(&data, 1);
}

void ili9163c_sleep_out()
{
uint8_t data[] = {0x08};
ili9163c_send_cmd(ILI9163C_SLPOUT);
ili9163c_send_data(&data, 1);
}

/**********************
* STATIC FUNCTIONS
**********************/

static void ili9163c_send_cmd(uint8_t cmd)
{
disp_wait_for_pending_transactions();
gpio_set_level(ILI9163C_DC, 0); /*Command mode*/
disp_spi_send_data(&cmd, 1);
}

static void ili9163c_send_data(void *data, uint16_t length)
{
disp_wait_for_pending_transactions();
gpio_set_level(ILI9163C_DC, 1); /*Data mode*/
disp_spi_send_data(data, length);
}

static void ili9163c_send_color(void *data, uint16_t length)
{
disp_wait_for_pending_transactions();
gpio_set_level(ILI9163C_DC, 1); /*Data mode*/
disp_spi_send_colors(data, length);
}

static void ili9163c_set_orientation(uint8_t orientation)
{
assert(orientation < 4);

const char *orientation_str[] = {
"PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED"};

ESP_LOGD(TAG, "Display orientation: %s", orientation_str[orientation]);

uint8_t data[] = {0x48, 0x88, 0xA8, 0x68};

ili9163c_send_cmd(ILI9163C_MADCTL);
ili9163c_send_data((void *)&data[orientation], 1);
}
Loading