======
Zephyr
======

What is Zephyr?
---------------

`Zephyr <https://zephyrproject.org/>`__ is an `open
source <https://github.com/zephyrproject-rtos/zephyr>`__ real-time operating
system (RTOS) that is easy to deploy, secure, connect and manage.
It has a growing set of software libraries that can be used
across various applications and industry sectors such as
Industrial IoT, wearables, machine learning and more.
Zephyr is built with an emphasis on broad chipset support,
security, dependability, longterm support releases and a
growing open source ecosystem.

Highlights of Zephyr
~~~~~~~~~~~~~~~~~~~~

-  **Small** - Runs on microcontrollers as small as 8 kB Flash
   and 5 kB of RAM.
-  **Scalable** - Usable for complex multicore systems.
-  **Customizable** - Out-of-the-box support for 500+ boards
   and high portability.
-  **Secure** - Built with safety and security in mind,
   offers Long-term support.
-  **Ecosystem** - Zephyr not only provides the RTOS kernel but
   also developer tooling, device drivers, connectivity, logging,
   tracing, power management and much more.
-  **Decoupling** - Leverages devicetree to describe and
   configure the target system.
-  **Compliant** - Apps are runnable as native Linux applications,
   which simplifies debugging and profiling.

How to run LVGL on Zephyr?
--------------------------

To setup your development environment refer to the
`getting started guide <https://docs.zephyrproject.org/latest/develop/getting_started/index.html>`__.

After you completed the setup above you can check out all of the `provided samples <https://docs.zephyrproject.org/latest/samples/>`__ for various boards.
You can check the list of available boards using:

.. code-block:: shell

   $ west boards

After you chose a board you can build one of the LVGL demos for it. Here we are using the :code:`native_posix`
board, which allows for running the application on your posix compliant host system:

.. code-block:: shell

   $ west build -b native_posix samples/modules/lvgl/demos

To run the application on your host:

.. code-block:: shell

   $ west build -t run

In case you chose any of the other supported boards you can flash to the device with:

.. code-block:: shell

    $ west flash

If you want to build any of the other demo applications check out the samples
`README <https://docs.zephyrproject.org/latest/samples/modules/lvgl/demos/README.html>`__.

Leveraging Zephyr Features
--------------------------

Shell
~~~~~

Zephyr includes a powerful shell implementation that can be enabled with the Kconfig symbols
:code:`CONFIG_SHELL` and :code:`CONFIG_LV_Z_SHELL` (the demos from above have it enabled by default).

The shell offers enabling/disabling of LVGL monkeys:

.. code-block:: shell

    # Create a new monkey with the given indev type
    uart$ lvgl monkey create [pointer|keypad|button|encoder]

    # Enable/Disable a monkey
    uart$ lvgl monkey set <index> <inactive/active>

This is useful for checking your application for memory leaks and other bugs.
Speaking of memory leaks, you can also acquire stats of the memory used by LVGL

.. code-block:: shell

    uart$ lvgl stats memory

For more details refer to the `shell documentation <https://docs.zephyrproject.org/latest/services/shell/index.html>`__.

Devicetree
~~~~~~~~~~

Zephyr uses the devicetree description language to create and manage LVGL input devices.

The pseudo device binding descriptions can be found at:

- `button input <https://docs.zephyrproject.org/latest/build/dts/api/bindings/input/zephyr,lvgl-button-input.html>`__
- `pointer input <https://docs.zephyrproject.org/latest/build/dts/api/bindings/input/zephyr,lvgl-pointer-input.html>`__
- `encoder input <https://docs.zephyrproject.org/latest/build/dts/api/bindings/input/zephyr,lvgl-encoder-input.html>`__
- `keypad input <https://docs.zephyrproject.org/latest/build/dts/api/bindings/input/zephyr,lvgl-keypad-input.html>`__

Essentially those buffer the :code:`input_event` generated by the device pointed to by the :code:`input` phandle or if left
empty the binding captures all events regardless of the source. You do not have to instantiate or manage the devices yourself,
they are created at application start up before :code:`main()` is executed.

Most boards or shields that have a display or display connector have the pointer input device already declared:

.. code-block::

    lvgl_pointer {
        compatible = "zephyr,lvgl-pointer-input";
        input = <&ft5336_touch>;
    };

You can access the underlying lvgl :code:`lv_indev_t` for configuration.
Example with the encoder device to assign a :code:`lv_group_t`:

.. code-block:: c

    const struct device *lvgl_encoder = DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_lvgl_encoder_input));

    lv_obj_t *arc;
    lv_group_t *arc_group;

    arc = lv_arc_create(lv_screen_active());
    lv_obj_align(arc, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_size(arc, 150, 150);

    arc_group = lv_group_create();
    lv_group_add_obj(arc_group, arc);
    lv_indev_set_group(lvgl_input_get_indev(lvgl_encoder), arc_group);


Kconfig
~~~~~~~~

Aside from enabling the shell you can also use Kconfig to finetune
the footprint of your application.

.. code-block::

    # Size of the memory region from which lvgl memory is allocated
    CONFIG_LV_Z_MEM_POOL_SIZE=8192

    # Do not include every widget/theme by default, enable them as needed.
    CONFIG_LV_CONF_MINIMAL=y

Overlays can be used to enable/disable features for specific boards or build
targets. For more information refer to the
`application development guide <https://docs.zephyrproject.org/latest/develop/application/index.html#application-configuration>`__.

Performance Tuning in LVGL
~~~~~~~~~~~~~~~~~~~~~~~~~~

To optimize LVGL's performance, several `kconfig` options can be configured:

- **CONFIG_LV_Z_VDB_SIZE**: Sets the rendering buffer size as a percentage of the display area, adjustable from 1% to 100%. Larger buffers can enhance performance, especially when used with **CONFIG_LV_Z_FULL_REFRESH**.

- **CONFIG_LV_Z_DOUBLE_VDB**: Enables the use of two rendering buffers, allowing for parallel rendering and data flushing, thus improving responsiveness and reducing latency.

- **CONFIG_LV_Z_VDB_ALIGN**: Ensures that the rendering buffer is properly aligned, which is critical for efficient memory access based on the color depth.

- **CONFIG_LV_Z_VBD_CUSTOM_SECTION**: Allows rendering buffers to be placed in a custom memory section (e.g., `.lvgl_buf`), useful for leveraging specific memory types like tightly coupled or external memory to enhance performance.

Zephyr ≤ 3.7.0 Specific Options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For Zephyr versions 3.7.0 and below, additional options are available to manage LVGL's frame flushing:

- **CONFIG_LV_Z_FLUSH_THREAD**: Enables flushing LVGL frames in a separate thread, allowing the main thread to continue rendering the next frame simultaneously. This option can be disabled if the performance gain is not needed.

  - **CONFIG_LV_Z_FLUSH_THREAD_STACK_SIZE**: Specifies the stack size for the flush thread, with a default of 1024 bytes.

  - **CONFIG_LV_Z_FLUSH_THREAD_PRIO**: Sets the priority of the flush thread, with a default priority of 0, indicating cooperative priority.

For newer versions of Zephyr, the OSAL (Operating System Abstraction Layer) can be utilized, which takes care of the flushing.

Where can I find more information?
----------------------------------

-  Zephyr Documentation: `Zephyr Documentation <https://docs.zephyrproject.org/latest/index.html>`__
-  Zephyr mailing list: `Zepyhr Mailing
   List <https://lists.zephyrproject.org/g/main>`__
-  Zephyr Discord server: `Zepyhr Discord
   server <https://chat.zephyrproject.org/>`__
