1===
2NXP
3===
4
5NXP has integrated LVGL into the MCUXpresso SDK packages for several of our
6microcontrollers as an optional software component, allowing easy evaluation and
7migration into your product design. LVGL is a free and open-source embedded
8graphic library with features that enable you to create embedded GUIs with
9intuitive graphical elements, beautiful visual effects and a low memory
10footprint. The complete graphic framework includes a variety of widgets for you
11to use in the creation of your GUI, and supports more advanced functions such as
12animations and anti-aliasing.
13
14LVGL enables graphics in our free GUI Guider UI tool. It's available for use
15with NXP’s general purpose and crossover microcontrollers, providing developers
16with a tool for creating complete, high quality GUI applications with LVGL.
17
18Creating new project with LVGL
19------------------------------
20
21`Download an SDK for a supported board <https://www.nxp.com/design/software/embedded-software/littlevgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY?&tid=vanLITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY>`__
22today and get started with your next GUI application. It comes fully configured
23with LVGL (and with PXP/VGLite support if the modules are present), no
24additional integration work is required.
25
26HW acceleration for NXP iMX RT platforms
27----------------------------------------
28
29Depending on the RT platform used, the acceleration can be done by NXP PXP
30(PiXel Pipeline) and/or the Verisilicon GPU through an API named VGLite. Each
31accelerator has its own context that allows them to be used individually as well
32simultaneously (in LVGL multithreading mode).
33
34PXP accelerator
35~~~~~~~~~~~~~~~
36Basic configuration:
37^^^^^^^^^^^^^^^^^^^^
38
39- Select NXP PXP engine in "lv_conf.h": Set :c:macro:`LV_USE_PXP` to `1`.
40- In order to use PXP as a draw unit, select in "lv_conf.h": Set :c:macro:`LV_USE_DRAW_PXP` to `1`.
41- In order to use PXP to rotate the screen, select in "lv_conf.h": Set :c:macro:`LV_USE_ROTATE_PXP` to `1`.
42- Enable PXP asserts in "lv_conf.h": Set :c:macro: `LV_USE_PXP_ASSERT` to `1`.
43  There are few PXP assertions that can stop the program execution in case the
44  c:macro:`LV_ASSERT_HANDLER` is set to `while(1);` (Halt by default). Else,
45  there will be logged just an error message via `LV_LOG_ERROR`.
46- If :c:macro:`SDK_OS_FREE_RTOS` symbol is defined, FreeRTOS implementation
47  will be used, otherwise bare metal code will be included.
48
49Basic initialization:
50^^^^^^^^^^^^^^^^^^^^^
51
52PXP draw initialization is done automatically in :cpp:func:`lv_init()` once the
53PXP is enabled as a draw unit or to rotate the screen, no user code is required:
54
55.. code-block:: c
56
57  #if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
58    lv_draw_pxp_init();
59  #endif
60
61During PXP initialization, a new draw unit `lv_draw_pxp_unit_t` will be created
62with the additional callbacks, if :c:macro:`LV_USE_DRAW_PXP` is set to `1`:
63
64.. code-block:: c
65
66    lv_draw_pxp_unit_t * draw_pxp_unit = lv_draw_create_unit(sizeof(lv_draw_pxp_unit_t));
67    draw_pxp_unit->base_unit.evaluate_cb = _pxp_evaluate;
68    draw_pxp_unit->base_unit.dispatch_cb = _pxp_dispatch;
69    draw_pxp_unit->base_unit.delete_cb = _pxp_delete;
70
71
72and an addition thread `_pxp_render_thread_cb()` will be spawned in order to
73handle the supported draw tasks.
74
75.. code-block:: c
76
77    #if LV_USE_PXP_DRAW_THREAD
78        lv_thread_init(&draw_pxp_unit->thread, "pxpdraw", LV_THREAD_PRIO_HIGH, _pxp_render_thread_cb, 2 * 1024, draw_pxp_unit);
79    #endif
80
81If `LV_USE_PXP_DRAW_THREAD` is not defined, then no additional draw thread will be created
82and the PXP drawing task will get executed on the same LVGL main thread.
83
84`_pxp_evaluate()` will get called after each task is being created and will
85analyze if the task is supported by PXP or not. If it is supported, then an
86preferred score and the draw unit id will be set to the task. An `score` equal
87to `100` is the default CPU score. Smaller score means that PXP is capable of
88drawing it faster.
89
90`_pxp_dispatch()` is the PXP dispatcher callback, it will take a ready to draw
91task (having the `DRAW_UNIT_ID_PXP` set) and will pass the task to the PXP draw
92unit for processing.
93
94`_pxp_delete()` will cleanup the PXP draw unit.
95
96
97Features supported:
98^^^^^^^^^^^^^^^^^^^
99
100Several drawing features in LVGL can be offloaded to the PXP engine. The CPU is
101available for other operations while the PXP is running. A RTOS is required to
102block the LVGL drawing thread and switch to another task or suspend the CPU for
103power savings.
104
105Supported draw tasks are available in "src/draw/nxp/pxp/lv_draw_pxp.c":
106
107.. code-block:: c
108
109    switch(t->type) {
110        case LV_DRAW_TASK_TYPE_FILL:
111            lv_draw_pxp_fill(draw_unit, t->draw_dsc, &t->area);
112            break;
113        case LV_DRAW_TASK_TYPE_IMAGE:
114            lv_draw_pxp_img(draw_unit, t->draw_dsc, &t->area);
115            break;
116        case LV_DRAW_TASK_TYPE_LAYER:
117            lv_draw_pxp_layer(draw_unit, t->draw_dsc, &t->area);
118            break;
119        default:
120            break;
121    }
122
123Additionally, the screen rotation can be handled by the PXP:
124
125.. code-block::c
126
127  void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height,
128                          int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation,
129                          lv_color_format_t cf);
130
131- Fill area with color (w/o radius, w/o gradient) + optional opacity.
132- Blit source image RGB565/ARGB888/XRGB8888 over destination.
133  RGB565/RGB888/ARGB888/XRGB8888 + optional opacity.
134- Recolor source image RGB565.
135- Scale and rotate (90, 180, 270 degree) source image RGB565.
136- Blending layers (w/ same supported formats as blitting).
137- Rotate screen (90, 180, 270 degree).
138
139
140Known limitations:
141^^^^^^^^^^^^^^^^^^
142
143- PXP can only rotate the frames in angles that are multiple of 90 degrees.
144- Rotation is not supported for images unaligned to blocks of 16x16 pixels. PXP
145  is set to process 16x16 blocks to optimize the system for memory bandwidth and
146  image processing time. The output engine essentially truncates any output
147  pixels after the desired number of pixels has been written. When rotating a
148  source image and the output is not divisible by the block size, the incorrect
149  pixels could be truncated and the final output image can look shifted.
150- Recolor or transformation for images w/ opacity or alpha channel can't be
151  obtained in a single PXP pipeline configuration. Two or multiple steps would
152  be required.
153- Buffer address must be aligned to 64 bytes: set :c:macro:`LV_DRAW_BUF_ALIGN`
154  to `64` in "lv_conf.h".
155  No stride alignment is required: set :c:macro:`LV_DRAW_BUF_STRIDE_ALIGN` to
156  `1` in "lv_conf.h".
157
158Project setup:
159^^^^^^^^^^^^^^
160
161- Add PXP related source files (and corresponding headers if available) to
162  project:
163
164   - "src/draw/nxp/pxp/lv_draw_buf_pxp.c": draw buffer callbacks
165   - "src/draw/nxp/pxp/lv_draw_pxp_fill.c": fill area
166   - "src/draw/nxp/pxp/lv_draw_pxp_img.c": blit image (w/ optional recolor or
167     transformation)
168   - "src/draw/nxp/pxp/lv_draw_pxp_layer.c": layer blending
169   - "src/draw/nxp/pxp/lv_draw_pxp.c": draw unit initialization
170   - "src/draw/nxp/pxp/lv_pxp_cfg.c": init, deinit, run/wait PXP device
171   - "src/draw/nxp/pxp/lv_pxp_osa.c": OS abstraction (FreeRTOS or bare metal)
172   - "src/draw/nxp/pxp/lv_pxp_utils.c": function helpers
173
174- PXP related code depends on two drivers provided by MCU SDK. These drivers
175  need to be added to project:
176
177   - fsl_pxp.c: PXP driver
178   - fsl_cache.c: CPU cache handling functions
179
180
181PXP default configuration:
182^^^^^^^^^^^^^^^^^^^^^^^^^^
183
184- Implementation depends on multiple OS-specific functions. The struct
185  :cpp:struct:`pxp_cfg_t` with callback pointers is used as a parameter for the
186  :cpp:func:`lv_pxp_init()` function. Default implementation for
187  FreeRTOS in lv_pxp_osa.c.
188
189   - :cpp:func:`pxp_interrupt_init()`: Initialize PXP interrupt (HW setup,
190     OS setup)
191   - :cpp:func:`pxp_interrupt_deinit()`: Deinitialize PXP interrupt (HW setup,
192     OS setup)
193   - :cpp:func:`pxp_run()`: Start PXP job. Use OS-specific mechanism to block
194     drawing thread.
195   - :cpp:func:`pxp_wait()`: Wait for PXP completion.
196
197
198VGLite accelerator
199~~~~~~~~~~~~~~~~~~
200
201Extra drawing features in LVGL can be handled by the VGLite engine. The
202CPU is available for other operations while the VGLite is running. A
203RTOS is required to block the LVGL drawing thread and switch to another
204task or suspend the CPU for power savings.
205
206
207Basic configuration:
208^^^^^^^^^^^^^^^^^^^^
209
210- Select NXP VGLite engine in "lv_conf.h": Set :c:macro:`LV_USE_DRAW_VGLITE` to
211  `1`. :c:macro:`SDK_OS_FREE_RTOS` symbol needs to be defined so that FreeRTOS
212  driver osal implementation will be enabled.
213- Enable VGLite asserts in "lv_conf.h": Set :c:macro: `LV_USE_VGLITE_ASSERT` to
214  `1`.
215  VGLite assertions will verify the driver API status code and in any error, it
216  can stop the program execution in case the c:macro: `LV_ASSERT_HANDLER` is set
217  to `while(1);` (Halt by default). Else, there will be logged just an error
218  message via `LV_LOG_ERROR`.
219
220Basic initialization:
221^^^^^^^^^^^^^^^^^^^^^
222
223Initialize VGLite GPU before calling :cpp:func:`lv_init()` by specifying the
224width/height of tessellation window. The default values for tessellation width
225and height, and command buffer size are in the SDK file "vglite_support.h".
226
227.. code-block:: c
228
229    #if LV_USE_DRAW_VGLITE
230        #include "vg_lite.h"
231        #include "vglite_support.h"
232    #endif
233    ...
234    #if LV_USE_DRAW_VGLITE
235    if(vg_lite_init(DEFAULT_VG_LITE_TW_WIDTH, DEFAULT_VG_LITE_TW_HEIGHT) != VG_LITE_SUCCESS)
236    {
237        PRINTF("VGLite init error. STOP.");
238        vg_lite_close();
239        while (1)
240            ;
241    }
242
243    if (vg_lite_set_command_buffer_size(VG_LITE_COMMAND_BUFFER_SIZE) != VG_LITE_SUCCESS)
244    {
245        PRINTF("VGLite set command buffer. STOP.");
246        vg_lite_close();
247        while (1)
248            ;
249    }
250    #endif
251
252VGLite draw initialization is done automatically in :cpp:func:`lv_init()` once
253the VGLite is enabled, no user code is required:
254
255.. code-block:: c
256
257    #if LV_USE_DRAW_VGLITE
258        lv_draw_vglite_init();
259    #endif
260
261During VGLite initialization, a new draw unit `lv_draw_vglite_unit_t` will be
262created with the additional callbacks:
263
264.. code-block:: c
265
266    lv_draw_vglite_unit_t * draw_vglite_unit = lv_draw_create_unit(sizeof(lv_draw_vglite_unit_t));
267    draw_vglite_unit->base_unit.evaluate_cb = _vglite_evaluate;
268    draw_vglite_unit->base_unit.dispatch_cb = _vglite_dispatch;
269    draw_vglite_unit->base_unit.delete_cb = _vglite_delete;
270
271and an addition thread `_vglite_render_thread_cb()` will be spawned in order to
272handle the supported draw tasks.
273
274.. code-block:: c
275
276    #if LV_USE_VGLITE_DRAW_THREAD
277        lv_thread_init(&draw_vglite_unit->thread, "vglitedraw", LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 2 * 1024, draw_vglite_unit);
278    #endif
279
280If `LV_USE_VGLITE_DRAW_THREAD` is not defined, then no additional draw thread will be created
281and the VGLite drawing task will get executed on the same LVGL main thread.
282
283`_vglite_evaluate()` will get called after each task is being created and will
284analyze if the task is supported by VGLite or not. If it is supported, then an
285preferred score and the draw unit id will be set to the task. An `score` equal
286to `100` is the default CPU score. Smaller score means that VGLite is capable of
287drawing it faster.
288
289`_vglite_dispatch()` is the VGLite dispatcher callback, it will take a ready to
290draw task (having the `DRAW_UNIT_ID_VGLITE` set) and will pass the task to the
291VGLite draw unit for processing.
292
293`_vglite_delete()` will cleanup the VGLite draw unit.
294
295
296Advanced configuration:
297^^^^^^^^^^^^^^^^^^^^^^^
298
299- Enable VGLite blit split in "lv_conf.h":
300  Set :c:macro: `LV_USE_VGLITE_BLIT_SPLIT` to `1`.
301  Enabling the blit split workaround will mitigate any quality degradation issue
302  on screen's dimension > 352 pixels.
303
304  .. code-block:: c
305
306      #define VGLITE_BLIT_SPLIT_THR 352
307
308- By default, the blit split threshold is set to 352. Blits with width or height
309  higher than this value will be done in multiple steps. Value must be multiple
310  of stride alignment in px. For most color formats, the alignment is 16px
311  (except the index formats). Transformation will not be supported once with
312  the blit split.
313
314- Enable VGLite draw task synchronously in "lv_conf.h":
315  Set :c:macro: `LV_USE_VGLITE_DRAW_ASYNC` to `1`.
316  Multiple draw tasks can be queued and flushed them once to the GPU based on
317  the GPU idle status. If GPU is busy, the task will be queued, and the VGLite
318  dispatcher will ask for a new available task. If GPU is idle, the queue with
319  any pending tasks will be flushed to the GPU. The completion status of draw
320  task will be sent to the main LVGL thread asynchronously.
321
322Features supported:
323^^^^^^^^^^^^^^^^^^^
324
325Several drawing features in LVGL can be offloaded to the VGLite engine. The CPU
326is available for other operations while the GPU is running. RTOS is required to
327block the LVGL drawing thread and switch to another task or suspend the CPU for
328power savings.
329
330Supported draw tasks are available in "src/draw/nxp/pxp/lv_draw_vglite.c":
331
332.. code-block:: c
333
334    switch(t->type) {
335        case LV_DRAW_TASK_TYPE_LABEL:
336            lv_draw_vglite_label(draw_unit, t->draw_dsc, &t->area);
337            break;
338        case LV_DRAW_TASK_TYPE_FILL:
339            lv_draw_vglite_fill(draw_unit, t->draw_dsc, &t->area);
340            break;
341        case LV_DRAW_TASK_TYPE_BORDER:
342            lv_draw_vglite_border(draw_unit, t->draw_dsc, &t->area);
343            break;
344        case LV_DRAW_TASK_TYPE_IMAGE:
345            lv_draw_vglite_img(draw_unit, t->draw_dsc, &t->area);
346            break;
347        case LV_DRAW_TASK_TYPE_ARC:
348            lv_draw_vglite_arc(draw_unit, t->draw_dsc, &t->area);
349            break;
350        case LV_DRAW_TASK_TYPE_LINE:
351            lv_draw_vglite_line(draw_unit, t->draw_dsc);
352            break;
353        case LV_DRAW_TASK_TYPE_LAYER:
354            lv_draw_vglite_layer(draw_unit, t->draw_dsc, &t->area);
355            break;
356        case LV_DRAW_TASK_TYPE_TRIANGLE:
357            lv_draw_vglite_triangle(draw_unit, t->draw_dsc);
358            break;
359        default:
360            break;
361    }
362
363
364All the below operation can be done in addition with optional opacity.
365
366- Fill area with color (w/ radius or gradient).
367- Blit source image (any format from ``_vglite_src_cf_supported()``) over
368  destination (any format from ``_vglite_dest_cf_supported()``).
369- Recolor source image.
370- Scale and rotate (any decimal degree) source image.
371- Blending layers (w/ same supported formats as blitting).
372- Draw letters (blit bitmap letters / raster font).
373- Draw full borders (LV_BORDER_SIDE_FULL).
374- Draw arcs (w/ rounded edges).
375- Draw lines (w/ dash or rounded edges).
376- Draw triangles with color (w/ gradient).
377
378
379Known limitations:
380^^^^^^^^^^^^^^^^^^
381
382- Source image alignment: The byte alignment requirement for a pixel depends on
383  the specific pixel format. Both buffer address and buffer stride must be
384  aligned. As general rule, the alignment is set to 16 pixels. This makes the
385  buffer address alignment to be 32 bytes for RGB565 and 64 bytes for ARGB8888.
386- For pixel engine (PE) destination, the alignment should be 64 bytes for all
387  tiled (4x4) buffer layouts. The pixel engine has no additional alignment
388  requirement for linear buffer layouts (:c:macro:`VG_LITE_LINEAR`).
389
390
391Project setup:
392^^^^^^^^^^^^^^
393
394- Add VGLite related source files (and corresponding headers if available) to
395  project:
396
397   - "src/draw/nxp/vglite/lv_draw_buf_vglite.c": draw buffer callbacks
398   - "src/draw/nxp/vglite/lv_draw_vglite_arc.c": draw arc
399   - "src/draw/nxp/vglite/lv_draw_vglite_border.c": draw border
400   - "src/draw/nxp/vglite/lv_draw_vglite_fill.c": fill area
401   - "src/draw/nxp/vglite/lv_draw_vglite_img.c": blit image (w/ optional recolor or transformation)
402   - "src/draw/nxp/vglite/lv_draw_vglite_label.c": draw label
403   - "src/draw/nxp/vglite/lv_draw_vglite_layer.c": layer blending
404   - "src/draw/nxp/vglite/lv_draw_vglite_line.c": draw line
405   - "src/draw/nxp/vglite/lv_draw_vglite_triangle.c": draw triangle
406   - "src/draw/nxp/vglite/lv_draw_vglite.c": draw unit initialization
407   - "src/draw/nxp/vglite/lv_vglite_buf.c": init/get vglite buffer
408   - "src/draw/nxp/vglite/lv_vglite_matrix.c": set vglite matrix
409   - "src/draw/nxp/vglite/lv_vglite_path.c": create vglite path data
410   - "src/draw/nxp/vglite/lv_vglite_utils.c": function helpers
411