Added GC9B71 driver.
Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
parent
651efeb648
commit
b5b0a042da
|
@ -5,10 +5,12 @@ project(epd-spi)
|
|||
set(EPD_SOURCES
|
||||
"src/epd_common.c"
|
||||
"src/driver/oled_ssd1327.c"
|
||||
"src/driver/lcd_gc9b71.c"
|
||||
"src/driver/lcd_st7789.c"
|
||||
"src/panel/epd_wfh0420cz35.c"
|
||||
"src/panel/epd_gdew042t2.c"
|
||||
"src/panel/lcd_h144c121d.c"
|
||||
"src/panel/lcd_h189s001.c"
|
||||
"src/panel/lcd_hp32030d.c"
|
||||
"src/panel/lcd_jlx256128g_920.c"
|
||||
"src/panel/lcd_tk0096f611.c"
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef LCD_GC9B71_H
|
||||
#define LCD_GC9B71_H
|
||||
|
||||
#include "epd-spi/epd_common.h"
|
||||
|
||||
typedef enum {
|
||||
LCD_GC9B71_DIR_0 = 0x48U,
|
||||
LCD_GC9B71_DIR_90 = 0x28U,
|
||||
LCD_GC9B71_DIR_180 = 0x88U,
|
||||
LCD_GC9B71_DIR_270 = 0xE8U,
|
||||
} lcd_gc9b71_direction_t;
|
||||
|
||||
typedef enum {
|
||||
LCD_GC9B71_GS256 = 0,
|
||||
LCD_GC9B71_RGB111 = 1,
|
||||
LCD_GC9B71_RGB444 = 3,
|
||||
LCD_GC9B71_RGB565 = 5,
|
||||
LCD_GC9B71_RGB666 = 6,
|
||||
LCD_GC9B71_RGB888 = 7,
|
||||
} lcd_gc9b71_pixel_format_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *init_struct;
|
||||
uint32_t init_struct_length;
|
||||
|
||||
uint16_t ram_size_x;
|
||||
uint16_t ram_size_y;
|
||||
|
||||
uint16_t ram_offset_x;
|
||||
uint16_t ram_offset_y;
|
||||
|
||||
uint16_t size_x;
|
||||
uint16_t size_y;
|
||||
|
||||
bool inversion;
|
||||
bool bgr_filter;
|
||||
} gc9b71_panel_config_t;
|
||||
|
||||
typedef struct {
|
||||
void *user_data;
|
||||
epd_cb_t cb;
|
||||
|
||||
const gc9b71_panel_config_t *panel_config;
|
||||
lcd_gc9b71_direction_t direction;
|
||||
lcd_gc9b71_pixel_format_t pixel_format;
|
||||
} lcd_gc9b71_t;
|
||||
|
||||
epd_ret_t lcd_gc9b71_init(lcd_gc9b71_t *lcd, const gc9b71_panel_config_t *config);
|
||||
epd_ret_t lcd_gc9b71_enable_display(lcd_gc9b71_t *lcd, bool on);
|
||||
epd_ret_t lcd_gc9b71_set_pixel_format(lcd_gc9b71_t *lcd, lcd_gc9b71_pixel_format_t format);
|
||||
epd_ret_t lcd_gc9b71_set_direction(lcd_gc9b71_t *lcd, lcd_gc9b71_direction_t direction);
|
||||
epd_ret_t lcd_gc9b71_set_inversion(lcd_gc9b71_t *lcd, bool invert);
|
||||
epd_ret_t lcd_gc9b71_load(lcd_gc9b71_t *lcd, epd_coord_t *coord, const uint8_t *data);
|
||||
|
||||
#endif // LCD_GC9B71_H
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef LCD_H189S001_H
|
||||
#define LCD_H189S001_H
|
||||
|
||||
#include "epd-spi/driver/lcd_gc9b71.h"
|
||||
|
||||
extern const gc9b71_panel_config_t lcd_h189s001_panel_config;
|
||||
|
||||
#endif //LCD_H189S001_H
|
|
@ -1,7 +1,3 @@
|
|||
//
|
||||
// Created by imi415 on 23/10/21.
|
||||
//
|
||||
|
||||
#ifndef LCD_HP32030D_H
|
||||
#define LCD_HP32030D_H
|
||||
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
#include "driver/lcd_gc9b71.h"
|
||||
|
||||
#include "epd_private.h"
|
||||
|
||||
/* TODO: Summarize MIPI DCS common commands into a separate file. */
|
||||
#define GC9B71_CMD_SWRESET (0x01U)
|
||||
#define GC9B71_CMD_SLPIN (0x10U)
|
||||
#define GC9B71_CMD_SLPOUT (0x11U)
|
||||
#define GC9B71_CMD_INVOFF (0x20U)
|
||||
#define GC9B71_CMD_INVON (0x21U)
|
||||
#define GC9B71_CMD_DISPOFF (0x28U)
|
||||
#define GC9B71_CMD_DISPON (0x29U)
|
||||
#define GC9B71_CMD_CASET (0x2AU)
|
||||
#define GC9B71_CMD_RASET (0x2BU)
|
||||
#define GC9B71_CMD_RAMWR (0x2CU)
|
||||
#define GC9B71_CMD_MADCTL (0x36U)
|
||||
#define GC9B71_CMD_COLMOD (0x3AU)
|
||||
|
||||
static epd_ret_t lcd_gc9b71_reset(lcd_gc9b71_t *lcd);
|
||||
static epd_ret_t lcd_gc9b71_sleep(lcd_gc9b71_t *lcd, bool sleep_mode);
|
||||
static epd_ret_t lcd_gc9b71_panel_config(lcd_gc9b71_t *lcd, const gc9b71_panel_config_t *config);
|
||||
static epd_ret_t lcd_gc9b71_set_window(lcd_gc9b71_t *lcd, epd_coord_t *coord);
|
||||
|
||||
epd_ret_t lcd_gc9b71_init(lcd_gc9b71_t *lcd, const gc9b71_panel_config_t *config) {
|
||||
EPD_ERROR_CHECK(lcd_gc9b71_reset(lcd));
|
||||
EPD_ERROR_CHECK(lcd->cb.delay_cb(lcd->user_data, 5));
|
||||
EPD_ERROR_CHECK(lcd_gc9b71_panel_config(lcd, config));
|
||||
EPD_ERROR_CHECK(lcd_gc9b71_set_pixel_format(lcd, LCD_GC9B71_RGB565));
|
||||
EPD_ERROR_CHECK(lcd_gc9b71_set_direction(lcd, LCD_GC9B71_DIR_0));
|
||||
EPD_ERROR_CHECK(lcd_gc9b71_set_inversion(lcd, false));
|
||||
EPD_ERROR_CHECK(lcd_gc9b71_sleep(lcd, false));
|
||||
EPD_ERROR_CHECK(lcd->cb.delay_cb(lcd->user_data, 120));
|
||||
|
||||
if (lcd->cb.backlight_cb) {
|
||||
EPD_ERROR_CHECK(lcd->cb.backlight_cb(lcd, 1));
|
||||
}
|
||||
|
||||
return EPD_OK;
|
||||
}
|
||||
|
||||
epd_ret_t lcd_gc9b71_load(lcd_gc9b71_t *lcd, epd_coord_t *coord, const uint8_t *data) {
|
||||
uint32_t pixel_count = (coord->y_end - coord->y_start + 1) * (coord->x_end - coord->x_start + 1);
|
||||
|
||||
uint32_t data_len = 0;
|
||||
|
||||
switch (lcd->pixel_format) {
|
||||
case LCD_GC9B71_RGB444:
|
||||
data_len = pixel_count * 3 / 2;
|
||||
break;
|
||||
case LCD_GC9B71_RGB565:
|
||||
data_len = pixel_count * 2;
|
||||
break;
|
||||
case LCD_GC9B71_RGB666:
|
||||
case LCD_GC9B71_RGB888:
|
||||
data_len = pixel_count * 3;
|
||||
break;
|
||||
default:
|
||||
data_len = pixel_count;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set cursor
|
||||
EPD_ERROR_CHECK(lcd_gc9b71_set_window(lcd, coord));
|
||||
|
||||
// Write pixel data
|
||||
EPD_ERROR_CHECK(lcd->cb.write_data_cb(lcd->user_data, data, data_len));
|
||||
|
||||
return EPD_OK;
|
||||
}
|
||||
|
||||
epd_ret_t lcd_gc9b71_set_pixel_format(lcd_gc9b71_t *lcd, lcd_gc9b71_pixel_format_t format) {
|
||||
lcd->pixel_format = format;
|
||||
|
||||
uint8_t command[2] = {GC9B71_CMD_COLMOD, format};
|
||||
EPD_ERROR_CHECK(lcd->cb.write_command_cb(lcd->user_data, command, 0x02));
|
||||
|
||||
return EPD_OK;
|
||||
}
|
||||
|
||||
epd_ret_t lcd_gc9b71_set_direction(lcd_gc9b71_t *lcd, lcd_gc9b71_direction_t direction) {
|
||||
lcd->direction = direction;
|
||||
|
||||
uint8_t command[2] = {GC9B71_CMD_MADCTL, direction};
|
||||
|
||||
if (!lcd->panel_config->bgr_filter) {
|
||||
command[1] &= ~0x08U;
|
||||
}
|
||||
|
||||
EPD_ERROR_CHECK(lcd->cb.write_command_cb(lcd->user_data, command, 0x02));
|
||||
|
||||
return EPD_OK;
|
||||
}
|
||||
|
||||
epd_ret_t lcd_gc9b71_set_inversion(lcd_gc9b71_t *lcd, bool invert) {
|
||||
uint8_t command[1];
|
||||
|
||||
if (lcd->panel_config->inversion) {
|
||||
command[0] = invert ? GC9B71_CMD_INVOFF : GC9B71_CMD_INVON;
|
||||
} else {
|
||||
command[0] = invert ? GC9B71_CMD_INVON : GC9B71_CMD_INVOFF;
|
||||
}
|
||||
|
||||
EPD_ERROR_CHECK(lcd->cb.write_command_cb(lcd->user_data, command, 0x01));
|
||||
|
||||
return EPD_OK;
|
||||
}
|
||||
|
||||
epd_ret_t lcd_gc9b71_enable_display(lcd_gc9b71_t *lcd, bool on) {
|
||||
uint8_t command[1];
|
||||
|
||||
if (on) {
|
||||
command[0] = GC9B71_CMD_DISPON;
|
||||
} else {
|
||||
command[0] = GC9B71_CMD_DISPOFF;
|
||||
}
|
||||
|
||||
EPD_ERROR_CHECK(lcd->cb.write_command_cb(lcd->user_data, command, 0x01));
|
||||
|
||||
return EPD_OK;
|
||||
}
|
||||
|
||||
static epd_ret_t lcd_gc9b71_reset(lcd_gc9b71_t *lcd) {
|
||||
uint8_t cmd_buf[1] = {GC9B71_CMD_SWRESET};
|
||||
|
||||
if (lcd->cb.reset_cb) {
|
||||
return lcd->cb.reset_cb(lcd->user_data);
|
||||
}
|
||||
|
||||
return lcd->cb.write_command_cb(lcd->user_data, cmd_buf, 1U);
|
||||
}
|
||||
|
||||
static epd_ret_t lcd_gc9b71_sleep(lcd_gc9b71_t *lcd, bool sleep_mode) {
|
||||
uint8_t cmd_buf[1] = {GC9B71_CMD_SLPOUT};
|
||||
|
||||
if (sleep_mode) {
|
||||
cmd_buf[0] = GC9B71_CMD_SLPIN;
|
||||
}
|
||||
|
||||
return lcd->cb.write_command_cb(lcd->user_data, cmd_buf, 1U);
|
||||
}
|
||||
|
||||
static epd_ret_t lcd_gc9b71_panel_config(lcd_gc9b71_t *lcd, const gc9b71_panel_config_t *config) {
|
||||
EPD_ERROR_CHECK(
|
||||
epd_common_execute_sequence(&lcd->cb, lcd->user_data, config->init_struct, config->init_struct_length));
|
||||
|
||||
lcd->panel_config = config;
|
||||
return EPD_OK;
|
||||
}
|
||||
|
||||
static epd_ret_t lcd_gc9b71_set_window(lcd_gc9b71_t *lcd, epd_coord_t *coord) {
|
||||
uint16_t real_x_start, real_x_end, real_y_start, real_y_end;
|
||||
uint16_t x_offset, y_offset;
|
||||
|
||||
switch (lcd->direction) {
|
||||
case LCD_GC9B71_DIR_0:
|
||||
x_offset = lcd->panel_config->ram_offset_x;
|
||||
y_offset = lcd->panel_config->ram_offset_y;
|
||||
break;
|
||||
case LCD_GC9B71_DIR_90:
|
||||
x_offset = lcd->panel_config->ram_offset_y;
|
||||
y_offset = lcd->panel_config->ram_offset_x;
|
||||
break;
|
||||
case LCD_GC9B71_DIR_180:
|
||||
x_offset = lcd->panel_config->ram_size_x - (lcd->panel_config->ram_offset_x + lcd->panel_config->size_x);
|
||||
y_offset = lcd->panel_config->ram_size_y - (lcd->panel_config->ram_offset_y + lcd->panel_config->size_y);
|
||||
break;
|
||||
case LCD_GC9B71_DIR_270:
|
||||
x_offset = lcd->panel_config->ram_size_y - (lcd->panel_config->ram_offset_y + lcd->panel_config->size_y);
|
||||
y_offset = lcd->panel_config->ram_size_x - (lcd->panel_config->ram_offset_x + lcd->panel_config->size_x);
|
||||
break;
|
||||
default:
|
||||
x_offset = 0;
|
||||
y_offset = 0;
|
||||
}
|
||||
|
||||
real_x_start = coord->x_start + x_offset;
|
||||
real_x_end = coord->x_end + x_offset;
|
||||
real_y_start = coord->y_start + y_offset;
|
||||
real_y_end = coord->y_end + y_offset;
|
||||
|
||||
uint8_t tx_buf[5] = {
|
||||
GC9B71_CMD_CASET, ((uint8_t)(real_x_start >> 0x08U) & 0xFFU),
|
||||
(real_x_start & 0xFFU), ((uint8_t)(real_x_end >> 0x08U) & 0xFFU),
|
||||
(real_x_end & 0xFFU),
|
||||
};
|
||||
|
||||
EPD_ERROR_CHECK(lcd->cb.write_command_cb(lcd->user_data, tx_buf, 0x05));
|
||||
|
||||
tx_buf[0] = GC9B71_CMD_RASET;
|
||||
tx_buf[1] = ((uint8_t)(real_y_start >> 0x08U) & 0xFFU);
|
||||
tx_buf[2] = (real_y_start & 0xFFU);
|
||||
tx_buf[3] = ((uint8_t)(real_y_end >> 0x08U) & 0xFFU);
|
||||
tx_buf[4] = (real_y_end & 0xFFU);
|
||||
|
||||
EPD_ERROR_CHECK(lcd->cb.write_command_cb(lcd->user_data, tx_buf, 0x05));
|
||||
return EPD_OK;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
#include "panel/lcd_h189s001.h"
|
||||
|
||||
static uint8_t panel_init_struct[] = {
|
||||
0x00, 0xFE, // ??
|
||||
0x00, 0xEF, // ??
|
||||
0x01, 0x80, 0x11, // ??
|
||||
0x01, 0x81, 0x70, // ??
|
||||
0x01, 0x82, 0x09, // ??
|
||||
0x01, 0x83, 0x03, // ??
|
||||
0x01, 0x84, 0x62, // ??
|
||||
0x01, 0x89, 0x18, // ??
|
||||
0x01, 0x8A, 0x40, // ??
|
||||
0x01, 0x8B, 0x0A, // ??
|
||||
0x01, 0x3A, 0x05, // ??
|
||||
0x01, 0x36, 0x40, // ??
|
||||
0x01, 0xEC, 0x07, // ??
|
||||
0x06, 0x74, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, // ??
|
||||
0x01, 0x98, 0x3E, // ??
|
||||
0x01, 0x99, 0x3E, // ??
|
||||
0x02, 0xA1, 0x01, 0x04, // ??
|
||||
0x02, 0xA2, 0x01, 0x04, // ??
|
||||
0x01, 0xCB, 0x02, // ??
|
||||
0x02, 0x7C, 0xB6, 0x24, // ??
|
||||
0x01, 0xAC, 0x74, // ??
|
||||
0x01, 0xF6, 0x80, // ??
|
||||
0x02, 0xB5, 0x09, 0x09, // ??
|
||||
0x02, 0xEB, 0x01, 0x81, // ??
|
||||
0x04, 0x60, 0x38, 0x06, 0x13, 0x56, // ??
|
||||
0x04, 0x63, 0x38, 0x08, 0x13, 0x56, // ??
|
||||
0x04, 0x61, 0x3B, 0x1B, 0x58, 0x38, // ??
|
||||
0x04, 0x62, 0x3B, 0x1B, 0x58, 0x38, // ??
|
||||
0x06, 0x64, 0x38, 0x0A, 0x73, 0x16, 0x13, 0x56, // ??
|
||||
0x06, 0x66, 0x38, 0x0B, 0x73, 0x17, 0x13, 0x56, // ??
|
||||
0x07, 0x68, 0x00, 0x0B, 0x22, 0x0B, 0x22, 0x1C, 0x1C, // ??
|
||||
0x07, 0x69, 0x00, 0x0B, 0x26, 0x0B, 0x26, 0x1C, 0x1C, // ??
|
||||
0x02, 0x6A, 0x15, 0x00, // ??
|
||||
0x20, 0x6E, 0x08, 0x02, 0x1a, 0x00, 0x12, 0x12, 0x11, 0x11, 0x14, 0x14, 0x13, 0x13, 0x04, 0x19, 0x1E,
|
||||
0x1D, 0x1D, 0x1E, 0x19, 0x04, 0x0B, 0x0B, 0x0C, 0x0C, 0x09, 0x09, 0x0A, 0x0A, 0x00, 0x1A, 0x01, 0x07, // ??
|
||||
0x07, 0x6C, 0xCC, 0x0C, 0xCC, 0x84, 0xCC, 0x04, 0x50, // ??
|
||||
0x01, 0x7D, 0x72, // ??
|
||||
0x0A, 0x70, 0x02, 0x03, 0x09, 0x07, 0x09, 0x03, 0x09, 0x07, 0x09, 0x03, // ??
|
||||
0x04, 0x90, 0x06, 0x06, 0x05, 0x06, // ??
|
||||
0x03, 0x93, 0x45, 0xFF, 0x00, // ??
|
||||
0x05, 0xC3, 0x15, 0xC4, 0x36, 0xC9, 0x3D, // ??
|
||||
0x06, 0xF0, 0x47, 0x07, 0x0A, 0x0A, 0x00, 0x29, // ??
|
||||
0x06, 0xF2, 0x47, 0x07, 0x0A, 0x0A, 0x00, 0x29, // ??
|
||||
0x06, 0xF1, 0x42, 0x91, 0x10, 0x2D, 0x2F, 0x6F, // ??
|
||||
0x06, 0xF3, 0x42, 0x91, 0x10, 0x2D, 0x2F, 0x6F, // ??
|
||||
0x01, 0xF9, 0x30, // ??
|
||||
0x01, 0xBE, 0x11, // ??
|
||||
0x02, 0xFB, 0x00, 0x00, // ??
|
||||
};
|
||||
|
||||
const gc9b71_panel_config_t lcd_h189s001_panel_config = {
|
||||
.init_struct = panel_init_struct,
|
||||
.init_struct_length = sizeof(panel_init_struct),
|
||||
.ram_size_x = 320,
|
||||
.ram_size_y = 390,
|
||||
.ram_offset_x = 0,
|
||||
.ram_offset_y = 0,
|
||||
.size_x = 320,
|
||||
.size_y = 386,
|
||||
.bgr_filter = false,
|
||||
.inversion = false,
|
||||
};
|
Loading…
Reference in New Issue