### Build and install the SDK Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/os/buildroot/quick_setup.rst Builds the SDK and installs it to ~/sdk. ```bash cd output make sdk mkdir -p ~/sdk tar -xzf images/aarch64-buildroot-linux-gnu_sdk-buildroot.tar.gz -C ~/sdk ``` -------------------------------- ### Install documentation prerequisites with pip Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/README.md Run this command after installing Python to install all required packages for building the documentation. ```bash pip install -r requirements.txt ``` -------------------------------- ### f_getfree usage example Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/FatFs/documents/doc/getfree.html Example showing how to call f_getfree to get free clusters and compute total and free space in sectors, then print the free space in KiB assuming 512-byte sectors. ```c FATFS *fs; DWORD fre_clust, fre_sect, tot_sect; /* Get volume information and free clusters of drive 1 */ res = f_getfree("1:", &fre_clust, &fs); if (res) die(res); /* Get total sectors and free sectors */ tot_sect = (fs->n_fatent - 2) * fs->csize; fre_sect = fre_clust * fs->csize; /* Print the free space (assuming 512 bytes/sector) */ printf("%10lu KiB total drive space.\n%10lu KiB available.\n", tot_sect / 2, fre_sect / 2); ``` -------------------------------- ### Install LVGL with bitbake lvgl -c install Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/os/yocto/lvgl_recipe.rst Runs the install task to copy built files into the holding area ${D}. It creates necessary directories, installs lv_conf.h into the include directory, and prepares the .so files for the final image. ```bash bitbake lvgl -c install ``` -------------------------------- ### Create application directory and setup script Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/os/buildroot/lvgl_app.rst Creates the application directory and an empty setup script, then makes it executable. The script will set up the cross-compilation environment. ```bash mkdir application && cd application touch setup-build-env.sh && chmod +x setup-build-env.sh ``` -------------------------------- ### Clone the LVGL Buildroot repository Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/os/buildroot/quick_setup.rst Clones the LVGL Buildroot repository with all submodules to get a ready-to-test setup. ```bash git clone --recurse-submodules https://github.com/lvgl/lv_buildroot.git ``` -------------------------------- ### Initialize a brand-new disk drive with f_fdisk and f_mkfs Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/FatFs/documents/doc/fdisk.html Example showing how to divide a physical drive into two partitions using f_fdisk and then create FAT volumes on the logical drives with f_mkfs. ```c /* Initialize a brand-new disk drive mapped to physical drive 0 */ BYTE work[FF_MAX_SS]; /* Working buffer */ LBA_t plist[] = {50, 50, 0}; /* Divide the drive by 2 */ /* {0x10000000, 100}; 256M sectors for the 1st partition and the remaining for the 2nd partition */ /* {20, 20, 20, 0}; 20% for 3 partitions each and remaing space is left not allocated */ f_fdisk(0, plist, work); /* Divide the physical drive 0 */ f_mkfs("0:", 0, work, sizeof work); /* Create FAT volume on the logical drive 0 */ f_mkfs("1:", 0, work, sizeof work); /* Create FAT volume on the logical drive 1 */ ``` -------------------------------- ### C formatting example for LVGL functions Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/contributing/coding_style.rst Shows the required bracket placement and whitespace for LVGL C functions. Main brackets of functions go on a new line, while statement brackets start on the same line. Comments before sections are placed on their own line. The example includes a Doxygen comment block with @param tags. ```c /** * Set new text for a label. Memory will be allocated by label to store text. * * @param label pointer to label Widget * @param text '\0' terminated character string. * NULL to refresh with current text. */ void lv_label_set_text(lv_obj_t * label, const char * text) { /* Main brackets of functions in new line */ if(label == NULL) return; /* No bracket only if command is inline with if statement */ lv_obj_inv(label); lv_label_ext_t * ext = lv_obj_get_ext(label); /* Comment before a section */ if(text == ext->txt || text == NULL) { /* Bracket of statements starts on same line */ lv_label_refr_text(label); return; } ... } ``` -------------------------------- ### UEFI driver usage example Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/driver/uefi.rst Complete example of initializing the UEFI driver, creating a display, input devices, and running the main loop for about 10 seconds. Requires the UEFI protocols listed in the prerequisites. ```c #include "lvgl/lvgl.h" #include "lvgl/examples/lv_examples.h" #include "lvgl/demos/lv_demos.h" EFI_STATUS EFIAPI EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE * SystemTable) { lv_uefi_init(ImageHandle, SystemTable); lv_init(); if(!lv_is_initialized()) return EFI_NOT_READY; EFI_HANDLE handle = NULL; lv_display_t* display = NULL; lv_indev_t* indev = NULL; lv_group_t* group = NULL; lv_obj_t* cursor = NULL; // used to get out of the main loop size_t counter; // Init the display handle = lv_uefi_display_get_active(); if(handle == NULL) { handle = lv_uefi_display_get_any(); } if(handle == NULL) { lv_deinit(); return EFI_UNSUPPORTED; } display = lv_uefi_display_create(handle); lv_display_set_default(display); // Create the group group = lv_group_create(); lv_group_set_default(group); // Create an image that can be used as cursor cursor = lv_image_create(lv_layer_top()); lv_image_set_src(cursor, "E:cursor.png"); // Create the input devices indev = lv_uefi_simple_text_input_indev_create(); lv_indev_set_group(indev, lv_group_get_default()); lv_uefi_simple_text_input_indev_add_all(indev); indev = lv_uefi_simple_pointer_indev_create(NULL); lv_uefi_simple_pointer_indev_add_all(indev); lv_indev_set_cursor(indev, cursor); indev = lv_uefi_absolute_pointer_indev_create(NULL); lv_uefi_absolute_pointer_indev_add_all(indev); lv_demo_widgets(); // Run main loop for ~ 10 seconds counter = 0; while(counter < 10000) { counter ++; gBS->Stall(1000); lv_tick_inc(1); lv_timer_handler(); } return EFI_SUCCESS; } ``` -------------------------------- ### Create Linux framebuffer display Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/driver/touchpad/evdev.rst Creates an lv_display_t using the Linux framebuffer driver and sets the framebuffer file. This is an example of creating the display object required by the evdev setup. ```c lv_display_t * disp = lv_linux_fbdev lv_linux_fbdev_set_file(disp, "/dev/fb0");_create(); ``` -------------------------------- ### Show object style with GDB plugin Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/debugging/gdb_plugin.rst Example GDB session showing the 'info style' command. It displays the object's local style in all possible formats because the style value is a union. The example also shows using the 'p' command to get the active screen pointer and then passing it to 'info style'. ```bash (gdb) info style 0x60700000dd10 32 = {num = 90, ptr = 0x5a, color = {blue = 90 'Z', green = 0 '\000', red = 0 '\000'}} 158 = {num = 32767, ptr = 0x7fff, color = {blue = 255 '\377', green = 127 '\177', red = 0 '\000'}} (gdb) p lv_global->disp_default->act_scr $4 = (lv_obj_t *) 0x60700000dd10 (gdb) info style $4 32 = {num = 90, ptr = 0x5a, color = {blue = 90 'Z', green = 0 '\000', red = 0 '\000'}} 158 = {num = 32767, ptr = 0x7fff, color = {blue = 255 '\377', green = 127 '\177', red = 0 '\000'}} (gdb) ``` -------------------------------- ### Basic SDL driver usage in main.c Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/driver/sdl.rst Complete example of initializing LVGL with the SDL driver, creating a display and input devices (mouse, mousewheel, keyboard), and running the main loop. Includes a workaround for SDL2 `-m32` crash and a log callback registration. ```c #include #define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/ #include #include "drivers/sdl/lv_sdl_mouse.h" #include "drivers/sdl/lv_sdl_mousewheel.h" #include "drivers/sdl/lv_sdl_keyboard.h" static lv_display_t *lvDisplay; static lv_indev_t *lvMouse; static lv_indev_t *lvMouseWheel; static lv_indev_t *lvKeyboard; #if LV_USE_LOG != 0 static void lv_log_print_g_cb(lv_log_level_t level, const char * buf) { LV_UNUSED(level); LV_UNUSED(buf); } #endif int main() { /* initialize lvgl */ lv_init(); // Workaround for sdl2 `-m32` crash // https://bugs.launchpad.net/ubuntu/+source/libsdl2/+bug/1775067/comments/7 #ifndef WIN32 setenv("DBUS_FATAL_WARNINGS", "0", 1); #endif /* Register the log print callback */ #if LV_USE_LOG != 0 lv_log_register_print_cb(lv_log_print_g_cb); #endif /* Add a display * Use the 'monitor' driver which creates window on PC's monitor to simulate a display*/ lvDisplay = lv_sdl_window_create(SDL_HOR_RES, SDL_VER_RES); lvMouse = lv_sdl_mouse_create(); lvMouseWheel = lv_sdl_mousewheel_create(); lvKeyboard = lv_sdl_keyboard_create(); /* create Widgets on the screen */ lv_demo_widgets(); Uint32 lastTick = SDL_GetTicks(); while(1) { SDL_Delay(5); Uint32 current = SDL_GetTicks(); lv_tick_inc(current - lastTick); // Update the tick timer. Tick is new for LVGL 9 lastTick = current; lv_timer_handler(); // Update the UI- } return 0; } ``` -------------------------------- ### Read a text file and display it Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/FatFs/documents/doc/open.html This example demonstrates how to mount a filesystem, open a text file, read it line by line using f_gets, and close the file. ```APIDOC ## f_mount, f_open, f_gets, f_close - Read a text file ### Description This example shows how to mount a default drive, open a text file, read each line, and close the file. ### Functions Used - `f_mount(&FatFs, "", 0)` - Mounts the default drive. - `f_open(&fil, "message.txt", FA_READ)` - Opens a file for reading. - `f_gets(line, sizeof line, &fil)` - Reads a line from the file. - `f_close(&fil)` - Closes the file. ### Example Code ```c /* Read a text file and display it */ FATFS FatFs; /* Work area (filesystem object) for logical drive */ int main (void) { FIL fil; /* File object */ char line[100]; /* Line buffer */ FRESULT fr; /* FatFs return code */ /* Give a work area to the default drive */ f_mount(&FatFs, "", 0); /* Open a text file */ fr = f_open(&fil, "message.txt", FA_READ); if (fr) return (int)fr; /* Read every line and display it */ while (f_gets(line, sizeof line, &fil)) { printf(line); } /* Close the file */ f_close(&fil); return 0; } ``` ### See Also - [f_read](read.html) - [f_write](write.html) - [f_close](close.html) - [FIL](sfile.html) - [FATFS](sfatfs.html) ``` -------------------------------- ### Implement my_flush_cb callback Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/chip/stm32.rst Example flush callback that sets the drawing region and performs an SPI write to send the display buffer to the LCD panel. The implementation will vary depending on the hardware setup. ```c void my_flush_cb(lv_display_t * disp, const lv_area_t * area, lv_color_t * color_p) { //Set the drawing region set_draw_window(area->x1, area->y1, area->x2, area->y2); int height = area->y2 - area->y1 + 1; int width = area->x2 - area->x1 + 1; //We will do the SPI write manually here for speed HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_SET); //CS low to begin data HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET); ``` -------------------------------- ### Create a button with LVGL in Berry Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/framework/tasmota-berry.rst A minimal Berry script that starts LVGL, gets the default screen, creates a button, centers it, and adds a label with text. This is the basic pattern for building LVGL interfaces in Tasmota's Berry environment. ```python lv.start() # start LVGL scr = lv.screen_active() # get default screen btn = lv.btn(scr) # create button btn.center() label = lv.label(btn) # create a label in the button label.set_text("Button") # set a label to the button ``` -------------------------------- ### Format default drive and create a file with f_mkfs Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/FatFs/documents/doc/mkfs.html Example from the f_mkfs documentation showing how to format the default drive with default parameters, mount it, create a file, write data, close it, and unregister the work area. Requires FF_FS_READONLY == 0 and FF_USE_MKFS == 1. ```c /* Format default drive and create a file */ int main (void) { FATFS fs; /* Filesystem object */ FIL fil; /* File object */ FRESULT res; /* API result code */ UINT bw; /* Bytes written */ BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */ /* Format the default drive with default parameters */ res = f_mkfs("", 0, work, sizeof work); if (res) ... /* Give a work area to the default drive */ f_mount(&fs, "", 0); /* Create a file as new */ res = f_open(&fil, "hello.txt", FA_CREATE_NEW | FA_WRITE); if (res) ... /* Write a message */ f_write(&fil, "Hello, World!\r\n", 15, &bw); if (bw != 15) ... /* Close the file */ f_close(&fil); /* Unregister work area */ f_mount(0, "", 0); ... } ``` -------------------------------- ### Example: Get volume label of default drive and drive 2 Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/FatFs/documents/doc/getlabel.html Shows how to call f_getlabel to retrieve the volume label of the default drive (empty string) and drive 2 ("2:"). The buffer 'str' must be at least 12 characters to hold the label. ```c char str[12]; /* Get volume label of the default drive */ f_getlabel("", str, 0); /* Get volume label of the drive 2 */ f_getlabel("2:", str, 0); ``` -------------------------------- ### Configure and mount littlefs Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/libs/lfs.rst This example demonstrates defining the lfs_config structure with block device operations and configuration parameters, followed by mounting the filesystem and handling reformatting if the mount fails. ```c #include "lfs.h" // configuration of the filesystem is provided by this struct const struct lfs_config cfg = { // block device operations .read = user_provided_block_device_read, .prog = user_provided_block_device_prog, .erase = user_provided_block_device_erase, .sync = user_provided_block_device_sync, // block device configuration .read_size = 16, .prog_size = 16, .block_size = 4096, .block_count = 128, .cache_size = 16, .lookahead_size = 16, .block_cycles = 500, }; // mount the filesystem int err = lfs_mount(&lfs, &cfg); // reformat if we can't mount the filesystem // this should only happen on the first boot if (err) { lfs_format(&lfs, &cfg); lfs_mount(&lfs, &cfg); } lv_littlefs_set_handler(&lfs); ``` -------------------------------- ### Preview the site with ./preview.sh Source: https://github.com/xiphonics/picotracker/blob/master/usermanual/Readme.md Run this command while developing to start a local preview server. It serves the site at http://localhost:8080 and watches for file changes to rebuild automatically. ```bash ./preview.sh ``` -------------------------------- ### HOP - Complex Envelope Source: https://github.com/xiphonics/picotracker/blob/master/usermanual/advance-edition/content/pages/tables.md Hopping to self is particularly useful for creating complex envelopes. This example starts a short volume decay, holds enough ticks for VOL to complete, raises volume to 60, then holds for a long time to allow VOL to complete and hold volume at 60. ```plaintext 00 VOL 0400 ; starts short volume decay to zero 01 HOP 0110 ; holds enough ticks for VOL to complete 02 VOL 0560 ; raise volume to 60 03 HOP 0303 ; hold for a long time to allow VOL to complete and hold volume at 60 ``` -------------------------------- ### Handle gesture events with LV_EVENT_GESTURE Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/main-modules/indev.rst Example event handler for detecting gestures on a screen. Uses lv_indev_get_gesture_dir() to get the direction and switches on LV_DIR_LEFT, LV_DIR_RIGHT, LV_DIR_TOP, LV_DIR_BOTTOM. The event callback is added with LV_EVENT_GESTURE. To prevent gesture bubbling, remove the LV_OBJ_FLAG_GESTURE_BUBBLE flag. Gestures are not triggered while scrolling. ```c void my_event(lv_event_t * e) { lv_obj_t * screen = lv_event_get_current_target(e); lv_dir_t dir = lv_indev_get_gesture_dir(lv_indev_active()); switch(dir) { case LV_DIR_LEFT: ... break; case LV_DIR_RIGHT: ... break; case LV_DIR_TOP: ... break; case LV_DIR_BOTTOM: ... break; } } ... lv_obj_add_event_cb(screen1, my_event, LV_EVENT_GESTURE, NULL); ``` -------------------------------- ### Minimal X11 initialization with lv_x11_window_create and lv_x11_inputs_create Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/driver/X11.rst Minimal initialization that opens a window and enables keyboard/mouse support. Requires LV_X11_DIRECT_EXIT to be 1. ```c int main(int argc, char ** argv) { ... /* initialize X11 display driver */ lv_display_t * disp = lv_x11_window_create("LVGL X11 Simulation", monitor_hor_res, monitor_ver_res); /* initialize X11 input drivers (for keyboard, mouse & mousewheel) */ lv_x11_inputs_create(disp, NULL); ... while(true) { ... /* Periodically call the lv_timer handler */ lv_timer_handler(); } } ``` -------------------------------- ### LVGL initialization and display setup Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/chip/stm32.rst Initializes LVGL, creates a display driver, sets a flush callback, and registers the frame buffers. The touch controller registration is omitted for brevity. ```c /* Initialise LVGL UI library */ lv_init(); lv_display_t *display = lv_display_create(WIDTH, HEIGHT); /* Create the display */ lv_display_set_flush_cb(display, my_flush_cb); /* Set a flush callback to draw to the display */ lv_display_set_buffers(disp, buf_1, buf_2, sizeof(buf_1), LV_DISPLAY_RENDER_MODE_PARTIAL); /* Set an initialized buffer */ /* Register the touch controller with LVGL - Not included here for brevity. */ ``` -------------------------------- ### f_chdir usage examples Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/FatFs/documents/doc/chdir.html Examples showing how to change the current directory using different path formats, including relative, drive-relative, and volume ID styles. ```c /* Change current direcoty of the current drive ("dir1" under root directory) */ f_chdir("/dir1"); /* Change current direcoty of current drive (parent directory of drive 2) */ f_chdir("2:.."); /* Change current direcoty of the drive "sdcard" (at DOS/Windows style volume ID) */ f_chdir("sdcard:/dir1"); /* Change current direcoty of the drive "flash" and set it as current drive (at Unix style volume ID) */ f_chdir("/flash/dir1"); ``` -------------------------------- ### Install Yocto SDK script output Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/os/yocto/lvgl_recipe.rst Shows the output when running the SDK installer script. It prompts for a target directory and confirmation before installing. ```bash $ ./sdk/poky-glibc-x86_64-core-image-base-cortexa53-raspberrypi3-64-toolchain-5.0.4.sh Poky (Yocto Project Reference Distro) SDK installer version 5.0.4 ================================================================= Enter target directory for SDK (default: /opt/poky/5.0.4): /opt/poky/sdk-with-lvgl You are about to install the SDK to "/opt/poky/sdk-with-lvgl". Proceed [Y/n]? y ``` -------------------------------- ### Install libjpeg-turbo8-dev Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/libs/libjpeg_turbo.rst Install the libjpeg-turbo development package on Debian-based systems. ```bash sudo apt install libjpeg-turbo8-dev ``` -------------------------------- ### Hello World LVGL application for QNX Source: https://github.com/xiphonics/picotracker/blob/master/sources/Externals/lvgl/docs/src/details/integration/os/qnx.rst A complete minimal LVGL application for QNX. It initializes the library, creates an 800x480 window, adds keyboard and pointer devices, sets a background color, creates a label, and runs the event loop. ```c #include int main(int argc, char **argv) { /* Initialize the library. */ lv_init(); /* Create a 800x480 window. */ lv_display_t *disp = lv_qnx_window_create(800, 480); lv_qnx_window_set_title(disp, "LVGL Example"); /* Add keyboard and mouse devices. */ lv_qnx_add_keyboard_device(disp); lv_qnx_add_pointer_device(disp); /* Generate the UI. */ lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN); lv_obj_t * label = lv_label_create(lv_screen_active()); lv_label_set_text(label, "Hello world"); lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); /* Run the event loop until it exits. */ return lv_qnx_event_loop(disp); } ```