qspi_lcd_display
Overview
The display functions abstract drivers for different screen interfaces. Users create a handle according to the screen type. Refer to bk_display.h for interface descriptions.
This section explains how the display module drives QSPI LCDs, including API usage, parameter descriptions, and notes.
Development Intro
1. Backlight
In the BK7258 SDK, the default LCD backlight pin is GPIO7. If your IO differs, configure it in your solution. Backlight control is user-managed; you can wrap open/close functions as in the SDK examples.
2. LCD Device
The BK7258 SDK already includes several QSPI LCD devices. If your device differs, add a new device per the section below.
Code Flow
1. Create LCD Controller
Parameters:
- handle: Output parameter that stores the created display controller handle
- config: Controller configuration containing LCD device info and GPIO pins
Example:
bk_display_qspi_ctlr_config_t qspi_ctlr_config = {
.lcd_device = &lcd_device_st77903_h0165y008t,
.qspi_id = 0,
.reset_pin = GPIO_40,
.te_pin = 0,
};
static bk_display_ctlr_handle_t lcd_display_handle = NULL;
avdk_err_t ret = bk_display_qspi_new(&lcd_display_handle, &qspi_ctlr_config);
if (ret != AVDK_ERR_OK) {
// error handling
}
Attention
If the TE feature is unused, te_pin can be set to any value. lcd_device is the panel descriptor pointer that provides resolution, interface type, etc. It is mandatory.
2. Open LCD Display
Parameters:
- handle: display controller handle
Description: Open LCD display and initialize the controller.
Example:
// Turn on backlight
lcd_backlight_open(GPIO_7);
// Open display controller
ret = bk_display_open(lcd_display_handle);
if (ret != AVDK_ERR_OK) {
// error handling
}
Attention
Due to hardware differences, backlight must be configured by the user.
3. Flush LCD Display
Parameters:
- handle: display controller handle
- frame: pointer to the frame to display
- free_t: callback to release the frame
Description: Refresh the LCD with the frame data.
Example:
// Frame release callback
static avdk_err_t display_frame_free_cb(void *frame)
{
frame_buffer_display_free((frame_buffer_t *)frame);
return AVDK_ERR_OK;
}
// Flush display
ret = bk_display_flush(lcd_display_handle, (void *)disp_frame, display_frame_free_cb);
if (ret != AVDK_ERR_OK) {
// error handling; manually free frame
display_frame_free_cb(disp_frame);
}
Attention
1: display_frame_free_cb releases the frame after refresh completes. If you do not need to free the frame, set free_t to NULL. 2: Supported source formats are RGB formats; refer to the panel spec for exact formats.
4. Close LCD Display
Parameters:
- handle: display controller handle
Description: Close LCD display and stop the controller.
Example:
// Close display controller
ret = bk_display_close(lcd_display_handle);
if (ret != AVDK_ERR_OK) {
// error handling
}
// Turn off backlight
lcd_backlight_close(GPIO_7);
5. Delete LCD Controller
Parameters:
- handle: display controller handle
Description: Delete the LCD controller and free resources.
Example:
// Delete display controller
ret = bk_display_delete(lcd_display_handle);
if (ret != AVDK_ERR_OK) {
// error handling
}
lcd_display_handle = NULL; // reset handle
6. Add a new lcd device
#define LCD_QSPI_GC9C01_REGISTER_WRITE_COMMAND 0x02
#define LCD_QSPI_GC9C01_REGISTER_READ_COMMAND 0x03
static const lcd_qspi_init_cmd_t gc9c01_init_cmds[] =
{
{0xfe, {0x00}, 0},
{0xef, {0x00}, 0},
{0x80, {0x11}, 1},
{0x81, {0x70}, 1},
{0x82, {0x09}, 1},
{0x83, {0x03}, 1},
{0x84, {0x70}, 1},
{0x89, {0x10}, 1},
{0x8a, {0x4f}, 1},
{0x8b, {0x08}, 1},
{0x8c, {0x59}, 1},
{0x8d, {0x51}, 1},
{0x36, {0x40}, 1},//RGB, 0x48 - BGR
{0x3a, {0x05}, 1},
{0xec, {0x87}, 1},
{0x74, {0x01, 0x80, 0x00, 0x00, 0x00, 0x00}, 6},
{0x98, {0x3e}, 1},
{0x99, {0x3e}, 1},
{0xc3, {0x3a}, 1},
{0xc4, {0x16}, 1},
{0xa1, {0x01, 0x04}, 2},
{0xa2, {0x01, 0x04}, 2},
{0xcb, {0x02}, 1},
{0x7c, {0xB6, 0x26}, 2},
{0xac, {0x24}, 1},
{0xf6, {0x80}, 1},
{0xb5, {0x09, 0x09}, 2},
{0xb6, {0x00, 0x40}, 2},
{0x60, {0x38, 0x0B, 0x5B, 0x56}, 4},
{0x63, {0x3A, 0xE0, 0x5B, 0x56}, 4},
{0x64, {0x38, 0x0D, 0x72, 0xDD, 0x5B, 0x56}, 6},
{0x66, {0x38, 0x11, 0x72, 0xE1, 0x5B, 0x56}, 6},
{0x68, {0x3B, 0x08, 0x08, 0x00, 0x08, 0x29, 0x5B}, 7},
{0x6E, {0x00, 0x00, 0x00, 0x07, 0x01, 0x13, 0x11, 0x0B, 0x09, 0x16, 0x15, 0x1D, 0x1E, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1E, 0x1D, 0x15, 0x16, 0x0A, 0x0C, 0x12, 0x14, 0x02, 0x08, 0x00, 0x00, 0x00}, 32},
{0xBE, {0x11}, 1},
{0x6C, {0xCC, 0x0C, 0xCC, 0x84, 0xCC, 0x04, 0x50}, 7},
{0x7d, {0x72}, 1},
{0x7e, {0x38}, 1},
{0x70, {0x02, 0x03, 0x09, 0x05, 0x0C, 0x06, 0x09, 0x05, 0x0C, 0x06}, 10},
{0x90, {0x06, 0x06, 0x05, 0x06}, 4},
{0x93, {0x45, 0xFF, 0x00}, 3},
{0xF0, {0x46, 0x0B, 0x0F, 0x0A, 0x10, 0x3F}, 6},
{0xF1, {0x52, 0x9A, 0x4F, 0x36, 0x37, 0xFF}, 6},
{0xF2, {0x46, 0x0B, 0x0F, 0x0A, 0x10, 0x3F}, 6},
{0xF3, {0x52, 0x9A, 0x4F, 0x36, 0x37, 0xFF}, 6},
{0XFB, {0X00, 0x00}, 2},
{0xb4, {0x0A}, 1},
{0x35, {0x00}, 1},
{0x44, {0x00, 0x01}, 2},
{0xa3, {0x4F}, 1},
{0x78, {0x01, 0x80}, 2},
{0x11, {0x00}, 0},
{0x00, {0xC8}, 0xFF},
{0xfe, {0x00}, 0},
{0xee, {0x00}, 0},
{0x29, {0x00}, 0},
};
static uint8_t gc9c01_cmd[4] = {0x32, 0x00, 0x2c, 0x00};
static const lcd_qspi_t lcd_qspi_gc9c01_config =
{
.clk = LCD_QSPI_48M,
.refresh_method = LCD_QSPI_REFRESH_BY_FRAME,
.reg_write_cmd = LCD_QSPI_GC9C01_REGISTER_WRITE_COMMAND,
.reg_read_cmd = LCD_QSPI_GC9C01_REGISTER_READ_COMMAND,
.reg_read_config.dummy_clk = 0,
.reg_read_config.dummy_mode = LCD_QSPI_NO_INSERT_DUMMMY_CLK,
.pixel_write_config.cmd = gc9c01_cmd,
.pixel_write_config.cmd_len = sizeof(gc9c01_cmd),
.init_cmd = gc9c01_init_cmds,
.device_init_cmd_len = sizeof(gc9c01_init_cmds) / sizeof(lcd_qspi_init_cmd_t),
.refresh_config = {0},
#if (CONFIG_LCD_QSPI_COLOR_DEPTH_BYTE == 3)
.frame_len = (PPI_360X360 >> 16) * (PPI_360X360 & 0xFFFF) * 3,
#else
.frame_len = (PPI_360X360 >> 16) * (PPI_360X360 & 0xFFFF) * 2,
#endif
};
const lcd_device_t lcd_device_gc9c01 =
{
.id = LCD_DEVICE_GC9C01,
.name = "gc9c01",
.type = LCD_TYPE_QSPI,
.ppi = PPI_360X360,
.qspi = &lcd_qspi_gc9c01_config,
.init = NULL,
.lcd_off = NULL,
};
Reference Project
QSPI LCD Example:
./projects/qspi_lcd_example
Notes
Ensure the display controller is created and opened successfully before calling flush
The frame release callback must be implemented correctly to avoid memory leaks
Different LCD devices require correct GPIO configuration
Frame buffer size should be calculated based on actual resolution and pixel format
Close and delete the controller promptly after operations to release resources