Displays

Important

The basic concept of display in LittlevGL is explained in the [Porting](/porting/display) section. So before reading further, please read the [Porting](/porting/display) section first.

In LittlevGL, you can have multiple displays, each with their own driver and objects.

Creating more displays is easy: just initialize more display buffers and register another driver for every display. When you create the UI, use lv_disp_set_default(disp) to tell the library which display to create objects on.

Why would you want multi-display support? Here are some examples:

  • Have a “normal” TFT display with local UI and create “virtual” screens on VNC on demand. (You need to add your VNC driver).

  • Have a large TFT display and a small monochrome display.

  • Have some smaller and simple displays in a large instrument or technology.

  • Have two large TFT displays: one for a customer and one for the shop assistant.

Using only one display

Using more displays can be useful, but in most cases, it’s not required. Therefore, the whole concept of multi-display is completely hidden if you register only one display. By default, the lastly created (the only one) display is used as default.

lv_scr_act(), lv_scr_load(scr), lv_layer_top(), lv_layer_sys(), LV_HOR_RES and LV_VER_RES are always applied on the lastly created (default) screen. If you pass NULL as disp parameter to display related function, usually the default display will be used. E.g. lv_disp_trig_activity(NULL) will trigger a user activity on the default screen. (See below in Inactivity).

Mirror display

To mirror the image of the display to another display, you don’t need to use the multi-display support. Just transfer the buffer received in drv.flush_cb to another display too.

Split image

You can create a larger display from smaller ones. You can create it as below:

  1. Set the resolution of the displays to the large display’s resolution.

  2. In drv.flush_cb, truncate and modify the area parameter for each display.

  3. Send the buffer’s content to each display with the truncated area.

Screens

Every display has each set of Screens and the object on the screens.

Be sure not to confuse displays and screens:

  • Displays are the physical hardware drawing the pixels.

  • Screens are the high-level root objects associated with a particular display. One display can have multiple screens associated with it, but not vice versa.

Screens can be considered the highest level containers which have no parent. The screen’s size is always equal to its display and size their position is (0;0). Therefore, the screens coordinates can’t be changed, i.e. lv_obj_set_pos(), lv_obj_set_size() or similar functions can’t be used on screens.

A screen can be created from any object type but, the two most typical types are the Base object and the Image (to create a wallpaper).

To create a screen, use lv_obj_t * scr = lv_<type>_create(NULL, copy). copy can be an other screen to copy it.

To load a screen, use lv_scr_load(scr). To get the active screen, use lv_scr_act(). These functions works on the default display. If you want to to specify which display to work on, use lv_disp_get_scr_act(disp) and lv_disp_load_scr(disp, scr).

Screens can be deleted with lv_obj_del(scr), but ensure that you do not delete the currently loaded screen.

Opaque screen

Usually, the opacity of the screen is LV_OPA_COVER to provide a solid background for its children.

However, in some special cases, you might want a transparent screen. For example, if you have a video player that renders video frames on a lower layer, you want to create an OSD menu on the upper layer (over the video) using LittlevGL.

To do this, the screen should have a style that sets body.opa or image.opa to LV_OPA_TRANSP (or another non-opaque value) to make the screen opaque.

Also, LV_COLOR_SCREEN_TRANSP needs to be enabled. Please note that it only works with LV_COLOR_DEPTH = 32.

The Alpha channel of 32-bit colors will be 0 where there are no objects and will be 255 where there are solid objects.

Features of displays

Inactivity

The user’s inactivity is measured on each display. Every use of an Input device (if associated with the display) counts as an activity. To get time elapsed since the last activity, use lv_disp_get_inactive_time(disp). If NULL is passed, the overall smallest inactivity time will be returned from all displays (not the default display).

You can manually trigger an activity using lv_disp_trig_activity(disp). If disp is NULL, the default screen will be used (and not all displays).

Colors

The color module handles all color-related functions like changing color depth, creating colors from hex code, converting between color depths, mixing colors, etc.

The following variable types are defined by the color module:

  • lv_color1_t Store monochrome color. For compatibility, it also has R, G, B fields but they are always the same value (1 byte)

  • lv_color8_t A structure to store R (3 bit),G (3 bit),B (2 bit) components for 8-bit colors (1 byte)

  • lv_color16_t A structure to store R (5 bit),G (6 bit),B (5 bit) components for 16-bit colors (2 byte)

  • lv_color32_t A structure to store R (8 bit),G (8 bit), B (8 bit) components for 24-bit colors (4 byte)

  • lv_color_t Equal to lv_color1/8/16/24_t according to color depth settings

  • lv_color_int_t uint8_t, uint16_t or uint32_t according to color depth setting. Used to build color arrays from plain numbers.

  • lv_opa_t A simple uint8_t type to describe opacity.

The lv_color_t, lv_color1_t, lv_color8_t, lv_color16_t and lv_color32_t types have got four fields:

  • ch.red red channel

  • ch.green green channel

  • ch.blue blue channel

  • full red + green + blue as one number

You can set the current color depth in lv_conf.h, by setting the LV_COLOR_DEPTH define to 1 (monochrome), 8, 16 or 32.

Convert color

You can convert a color from the current color depth to another. The converter functions return with a number, so you have to use the full field:

lv_color_t c;
c.red   = 0x38;
c.green = 0x70;
c.blue  = 0xCC;

lv_color1_t c1;
c1.full = lv_color_to1(c);	/*Return 1 for light colors, 0 for dark colors*/

lv_color8_t c8;
c8.full = lv_color_to8(c);	/*Give a 8 bit number with the converted color*/

lv_color16_t c16;
c16.full = lv_color_to16(c); /*Give a 16 bit number with the converted color*/

lv_color32_t c24;
c32.full = lv_color_to32(c);	/*Give a 32 bit number with the converted color*/

Swap 16 colors

You may set LV_COLOR_16_SWAP in lv_conf.h to swap the bytes of RGB565 colors. It’s useful if you send the 16-bit colors via a byte-oriented interface like SPI.

As 16-bit numbers are stored in Little Endian format (lower byte on the lower address), the interface will send the lower byte first. However, displays usually need the higher byte first. A mismatch in the byte order will result in highly distorted colors.

Create and mix colors

You can create colors with the current color depth using the LV_COLOR_MAKE macro. It takes 3 arguments (red, green, blue) as 8-bit numbers. For example to create light red color: my_color = COLOR_MAKE(0xFF,0x80,0x80).

Colors can be created from HEX codes too: my_color = lv_color_hex(0x288ACF) or my_color = lv_folro_hex3(0x28C).

Mixing two colors is possible with mixed_color = lv_color_mix(color1, color2, ratio). Ration can be 0..255. 0 results fully color2, 255 result fully color1.

Colors can be created with from HSV space too using lv_color_hsv_to_rgb(hue, saturation, value) . hue should be in 0..360 range, saturation and value in 0..100 range.

Opacity

To describe opacity the lv_opa_t type is created as a wrapper to uint8_t. Some defines are also introduced:

  • LV_OPA_TRANSP Value: 0, means the opacity makes the color completely transparent

  • LV_OPA_10 Value: 25, means the color covers only a little

  • LV_OPA_20 … OPA_80 come logically

  • LV_OPA_90 Value: 229, means the color near completely covers

  • LV_OPA_COVER Value: 255, means the color completely covers

You can also use the LV_OPA_* defines in lv_color_mix() as a ratio.

Built-in colors

The color module defines the most basic colors such as:

  • https://placehold.it/15/ffffff/ffffff?text=+#FFFFFF LV_COLOR_WHITE

  • https://placehold.it/15/000000/000000?text=+#000000 LV_COLOR_BLACK

  • https://placehold.it/15/808080/000000?text=+#808080 LV_COLOR_GRAY

  • https://placehold.it/15/c0c0c0/000000?text=+#c0c0c0 LV_COLOR_SILVER

  • https://placehold.it/15/ff0000/000000?text=+#ff0000 LV_COLOR_RED

  • https://placehold.it/15/800000/000000?text=+#800000 LV_COLOR_MAROON

  • https://placehold.it/15/00ff00/000000?text=+#00ff00 LV_COLOR_LIME

  • https://placehold.it/15/008000/000000?text=+#008000 LV_COLOR_GREEN

  • https://placehold.it/15/808000/000000?text=+#808000 LV_COLOR_OLIVE

  • https://placehold.it/15/0000ff/000000?text=+#0000ff LV_COLOR_BLUE

  • https://placehold.it/15/000080/000000?text=+#000080 LV_COLOR_NAVY

  • https://placehold.it/15/008080/000000?text=+#008080 LV_COLOR_TAIL

  • https://placehold.it/15/00ffff/000000?text=+#00ffff LV_COLOR_CYAN

  • https://placehold.it/15/00ffff/000000?text=+#00ffff LV_COLOR_AQUA

  • https://placehold.it/15/800080/000000?text=+#800080 LV_COLOR_PURPLE

  • https://placehold.it/15/ff00ff/000000?text=+#ff00ff LV_COLOR_MAGENTA

  • https://placehold.it/15/ffa500/000000?text=+#ffa500 LV_COLOR_ORANGE

  • https://placehold.it/15/ffff00/000000?text=+#ffff00 LV_COLOR_YELLOW

as well as LV_COLOR_WHITE (fully white).

API

Display

Functions

lv_obj_t *lv_disp_get_scr_act(lv_disp_t *disp)

Return with a pointer to the active screen

Return

pointer to the active screen object (loaded by ‘lv_scr_load()’)

Parameters
  • disp: pointer to display which active screen should be get. (NULL to use the default screen)

void lv_disp_load_scr(lv_obj_t *scr)

Make a screen active

Parameters
  • scr: pointer to a screen

lv_obj_t *lv_disp_get_layer_top(lv_disp_t *disp)

Return with the top layer. (Same on every screen and it is above the normal screen layer)

Return

pointer to the top layer object (transparent screen sized lv_obj)

Parameters
  • disp: pointer to display which top layer should be get. (NULL to use the default screen)

lv_obj_t *lv_disp_get_layer_sys(lv_disp_t *disp)

Return with the sys. layer. (Same on every screen and it is above the normal screen and the top layer)

Return

pointer to the sys layer object (transparent screen sized lv_obj)

Parameters
  • disp: pointer to display which sys. layer should be get. (NULL to use the default screen)

void lv_disp_assign_screen(lv_disp_t *disp, lv_obj_t *scr)

Assign a screen to a display.

Parameters
  • disp: pointer to a display where to assign the screen

  • scr: pointer to a screen object to assign

lv_task_t *lv_disp_get_refr_task(lv_disp_t *disp)

Get a pointer to the screen refresher task to modify its parameters with lv_task_... functions.

Return

pointer to the display refresher task. (NULL on error)

Parameters
  • disp: pointer to a display

uint32_t lv_disp_get_inactive_time(const lv_disp_t *disp)

Get elapsed time since last user activity on a display (e.g. click)

Return

elapsed ticks (milliseconds) since the last activity

Parameters
  • disp: pointer to an display (NULL to get the overall smallest inactivity)

void lv_disp_trig_activity(lv_disp_t *disp)

Manually trigger an activity on a display

Parameters
  • disp: pointer to an display (NULL to use the default display)

static lv_obj_t *lv_scr_act(void)

Get the active screen of the default display

Return

pointer to the active screen

static lv_obj_t *lv_layer_top(void)

Get the top layer of the default display

Return

pointer to the top layer

static lv_obj_t *lv_layer_sys(void)

Get the active screen of the deafult display

Return

pointer to the sys layer

static void lv_scr_load(lv_obj_t *scr)

Colors

Typedefs

typedef uint32_t lv_color_int_t
typedef lv_color32_t lv_color_t
typedef uint8_t lv_opa_t

Enums

enum [anonymous]

Opacity percentages.

Values:

LV_OPA_TRANSP = 0
LV_OPA_0 = 0
LV_OPA_10 = 25
LV_OPA_20 = 51
LV_OPA_30 = 76
LV_OPA_40 = 102
LV_OPA_50 = 127
LV_OPA_60 = 153
LV_OPA_70 = 178
LV_OPA_80 = 204
LV_OPA_90 = 229
LV_OPA_100 = 255
LV_OPA_COVER = 255

Functions

static uint8_t lv_color_to1(lv_color_t color)
static uint8_t lv_color_to8(lv_color_t color)
static uint16_t lv_color_to16(lv_color_t color)
static uint32_t lv_color_to32(lv_color_t color)
static lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
static uint8_t lv_color_brightness(lv_color_t color)

Get the brightness of a color

Return

the brightness [0..255]

Parameters
  • color: a color

static lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
static lv_color_t lv_color_hex(uint32_t c)
static lv_color_t lv_color_hex3(uint32_t c)
lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v)

Convert a HSV color to RGB

Return

the given RGB color in RGB (with LV_COLOR_DEPTH depth)

Parameters
  • h: hue [0..359]

  • s: saturation [0..100]

  • v: value [0..100]

lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8)

Convert a 32-bit RGB color to HSV

Return

the given RGB color in HSV

Parameters
  • r8: 8-bit red

  • g8: 8-bit green

  • b8: 8-bit blue

lv_color_hsv_t lv_color_to_hsv(lv_color_t color)

Convert a color to HSV

Return

the given color in HSV

Parameters
  • color: color

Variables

lv_color_t uint8_t g
lv_color_t uint8_t uint8_t b{ return LV_COLOR_MAKE(r, g, b)
union lv_color1_t

Public Members

uint8_t blue
uint8_t green
uint8_t red
struct lv_color1_t::[anonymous] ch
uint8_t full
union lv_color8_t

Public Members

uint8_t blue
uint8_t green
uint8_t red
struct lv_color8_t::[anonymous] ch
uint8_t full
union lv_color16_t

Public Members

uint16_t blue
uint16_t green
uint16_t red
uint16_t green_h
uint16_t green_l
struct lv_color16_t::[anonymous] ch
uint16_t full
union lv_color32_t

Public Members

uint8_t blue
uint8_t green
uint8_t red
uint8_t alpha
struct lv_color32_t::[anonymous] ch
uint32_t full
struct lv_color_hsv_t

Public Members

uint16_t h
uint8_t s
uint8_t v