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