Screen Module Framework Introduction

Introduction

Sicher’s display framework is based on the rt_device framework, and has the following features:

  • The same screen driver, TP driver, and backlight driver can be reused across different development boards.

  • The same development board can select different screen modules through menuconfig.

  • It supports multiple screen drivers and TP drivers simultaneously, distinguishing them by ID.



This design indeed improves reusability, but it also brings about the issue of dispersed configuration for screen module drivers:
  • The power-on/off, reset interfaces, pinmux settings, and PWM for backlight are all associated with the development board (similar to the BIOS of a screen driver module).

  • The screen driver, TP driver, and backlight driver must be implemented based on the macro definitions and IO interfaces provided above.

  • The implemented screen driver, TP driver, and backlight driver are eventually integrated into a menuconfig menu for the development board to select.



Screen Section

Screen Framework Diagram

alt text

Explanation of items in the diagram:

  • Driver layer (drv_lcd.c) — Implements an rt_device named “lcd” for upper-layer screen operations.

  • The specific driver code in the middle green part (main code for adding screen drivers by customers)

  • Board-level IO interface file (bsp_lcd_tp.c, or drv_io.c) — Provides a unified power-on, power-off, and reset interface for the screen driver.

  • Backlight device “lcdlight” — Provides a unified backlight control interface for the screen driver.

  • HAL layer (bf0_hal_lcdc.c) — Provides basic unified parameter configuration, LCD register read/write, and other interfaces for the screen driver.





Registering Screen Driver to the System

Sicher’s screen driver framework supports registering multiple screen drivers to the system simultaneously. This is achieved by generating a variable with a special section name using the macro LCD_DRIVER_EXPORT2, which links them together.

In nv3051f1.c, the screen driver’s callback functions are registered to the system using LCD_DRIVER_EXPORT2. For detailed explanations of each function, please refer to Screen Driver Callback Functions:

static const LCD_DrvOpsDef LCD_drv =
{
	LCD_Init,    			  //【Required】Screen driver initialization function (including reset, initialization procedures, etc.)
	LCD_ReadID,    			  //【Required】Screen presence detection function
	LCD_DisplayOn,   		  //【Required】Screen on
	LCD_DisplayOff,  		  //【Required】Screen off
	LCD_SetRegion,    		  //【Required】Set the area for screen data reception (2A, 2B area)
	LCD_WritePixel,   		  // Optional, Write a pixel to the screen
	LCD_WriteMultiplePixels,  //【Required】Write multiple pixels to the screen
	LCD_ReadPixel,    		  // Optional, Read a pixel data from the screen, return the RGB value
	LCD_SetColorMode,    	  // Optional, Switch the color format output to the screen
	LCD_SetBrightness,   	  // Optional, Set the screen brightness
	LCD_IdleModeOn,    		  // Optional, Enter standby display mode (low-power mode)
	LCD_IdleModeOff,   		  // Optional, Exit standby display mode (low-power mode)
	LCD_Rotate,  			  // Optional, Rotate the screen by a certain angle
	LCD_TimeoutDbg, 		  // Optional, Screen self-check after batch data transfer timeout
	LCD_TimeoutReset,  		  // Optional, Screen reset after batch data transfer timeout
	LCD_ESDCheck,  		      // Optional, Periodic ESD detection for the screen
};

LCD_DRIVER_EXPORT2(nv3051f1, LCD_ID, &lcdc_int_cfg, &LCD_drv,2);




Screen Presence Detection

When the system registers multiple screen drivers, how to determine which screen driver to use to drive the current screen requires screen presence detection. The method is to first call the LCD_Init function of each screen driver to initialize it, then call the LCD_ReadID function. If the value returned by LCD_ReadID matches the LCD_ID value, it is considered that the screen is present, and the corresponding screen driver is used. Otherwise, continue to call the LCD_Init and LCD_ReadID functions of the next screen driver.

  • LCD_Init and LCD_ReadID are the callback functions registered by each screen driver

  • LCD_ID is a parameter passed through LCD_DRIVER_EXPORT2

  • You can directly return LCD_ID if you force the use of this screen driver. This is applicable when there is only one screen driver or the screen does not support reading the ID.

Pixel Alignment for Screen Refresh

Some screen drivers have pixel alignment requirements for the refresh area. Sicher’s screen driver framework supports setting pixel alignment (if the row and column alignment requirements are different, the larger value is used. For example, if a screen requires 2-pixel alignment for rows and 4-pixel alignment for columns, 4 is used).

The pixel alignment requirement for the screen driver IC’s update area is generally described in the 0x2A (start and end columns) and 0x2B (start and end rows) registers. For example, the IC in the following diagram requires 2-pixel alignment for both rows and columns:

../../_images/LCD_IC_pixel_alignment.png




Touch Section

Touch (TP) Framework Diagram

alt text





TP Driver Registration Interface

In gt911.c, the initialization function rt_tp_device_init is registered using INIT_COMPONENT_EXPORT. Inside rt_tp_device_init, the TP driver is registered to the system using the function rt_touch_drivers_register.

static struct touch_drivers driver;
static struct touch_ops ops =
{
    read_point, // TP data read callback function
    init,       // TP initialization callback function
    deinit      // TP deinitialization callback function
};



static int rt_tp_device_init(void)
{

    driver.probe = probe;  // TP presence detection callback function
    driver.ops = &ops;
    driver.user_data = RT_NULL;
    driver.isr_sem = rt_sem_create("gt911", 0, RT_IPC_FLAG_FIFO); // TP data read semaphore

    rt_touch_drivers_register(&driver);  // Register to the system TP driver framework
    return 0;

}
INIT_COMPONENT_EXPORT(rt_tp_device_init); // Register initialization function

Backlight Section

Non-self-emitting screens generally require backlighting. Currently, backlight drivers for screens are implemented in various ways to create an “lcdlight” rt_device, which is then uniformly used in the screen driver’s callback function LCD_SetBrightness.

Currently, two modes are supported:

  • Direct PWM backlighting, where the chip directly outputs a PWM waveform to drive the backlight

  • External backlight driver, where a GPIO controls an external backlight driver chip to output a PWM waveform to drive the backlight

Direct PWM Backlighting

This device is registered as an “lcdlight” rt_device in drv_lcd.c, see the rt_hw_lcd_backlight_init function.

The default PWM frequency used is 1KHz.

It uses two macros LCD_PWM_BACKLIGHT_INTERFACE_NAME and LCD_PWM_BACKLIGHT_CHANEL_NUM, which specify the PWM device name and channel number, respectively. These two macros are typically defined in Kconfig.board.

Note: The PWM rt_device specified by LCD_PWM_BACKLIGHT_INTERFACE_NAME needs to be enabled in menuconfig. For example, if “pwm2” is specified, you need to select: alt text

This type of backlighting can be used by selecting the macro LCD_USING_PWM_AS_BACKLIGHT in the screen module.

External Backlight Driver

For example, in aw9364.c, the “lcdlight” rt_device is registered in the sif_aw9364_init function.

The macro LCD_BACKLIGHT_CONTROL_PIN is used to specify which GPIO controls the aw9364. This macro is also defined in Kconfig.board.

This type of backlighting can be used by selecting the macro BL_USING_AW9364 in the screen module.