documentation: improve frame buffer and lcd drivers documentation
This commit is contained in:
parent
6e5908cc92
commit
daa4cf7ad2
@ -2,33 +2,111 @@
|
||||
Frame Buffer Drivers
|
||||
====================
|
||||
|
||||
- ``include/nuttx/video/fb.h``. All structures and APIs
|
||||
needed to work with frame buffer drivers are provided in this
|
||||
header file.
|
||||
A framebuffer is a memory-mapped buffer that represents all the pixels necessary to drive a video display.
|
||||
|
||||
- ``struct fb_vtable_s``. Each frame buffer device driver
|
||||
must implement an instance of ``struct fb_vtable_s``. That
|
||||
structure defines a call table with the following methods:
|
||||
The Frame Buffer driver is intended to be used in the following scenarios:
|
||||
|
||||
Get information about the video controller configuration and
|
||||
the configuration of each color plane.
|
||||
#. Whenever it is necessary to hold all the pixels that would be used to drive a video display. This includes:
|
||||
|
||||
The following are provided only if the video hardware supports
|
||||
RGB color mapping:
|
||||
#. Graphics libraries that directly access the underlying framebuffer;
|
||||
#. Advanced UIs (e.g. alpha blending) that need to read back the image data;
|
||||
|
||||
The following are provided only if the video hardware supports
|
||||
a hardware cursor:
|
||||
#. Applications that expect the framebuffer to exist;
|
||||
|
||||
- **Binding Frame Buffer Drivers**. Frame buffer drivers are not
|
||||
normally directly accessed by user code, but are usually bound
|
||||
to another, higher level device driver. In general, the binding
|
||||
sequence is:
|
||||
Binding
|
||||
========
|
||||
LCD and frame buffer drivers usually are not directly accessed by user code, but are usually bound to another, higher-level device driver.
|
||||
In general, the binding sequence is:
|
||||
|
||||
#. Get an instance of ``struct fb_vtable_s`` from the
|
||||
hardware-specific frame buffer device driver, and
|
||||
#. Provide that instance to the initialization method of the
|
||||
higher level device driver.
|
||||
#. Get an instance of ``struct fb_vtable_s`` from the hardware-specific frame buffer device driver, and
|
||||
#. Provide that instance to the initialization method of the higher-level device driver.
|
||||
|
||||
- **Examples**: ``arch/sim/src/up_framebuffer.c``. See also the
|
||||
usage of the frame buffer driver in the ``graphics/``
|
||||
directory.
|
||||
.. _genericlcdfb:
|
||||
|
||||
Generic LCD Frame Buffer
|
||||
------------------------
|
||||
|
||||
This example will walk through the path from userspace to hardware-specific details on how an LCD screen is bound to a framebuffer.
|
||||
|
||||
#. ``include/nuttx/video/fb.h`` provides all structures and APIs needed to work with frame buffer drivers:
|
||||
|
||||
#. ``drivers/video/fb.c`` is the higher-level device driver. An instance of ``struct fb_vtable_s`` will be provided to it;
|
||||
#. ``fb_register`` registers the framebuffer character device at ``/dev/fbN`` where N is the display number;
|
||||
#. It also provides the prototype of ``up_fbinitialize``, which may be defined by:
|
||||
|
||||
#. An specific device into ``arch/<arch>/src/<chip>`` directory;
|
||||
#. By the LCD framebuffer adapter in ``drivers/lcd/lcd_framebuffer.c``, which provides an intermediary interface between the Frame Buffer Driver and the LCD screen drivers;
|
||||
|
||||
#. Let's consider we are using the LCD framebuffer (``CONFIG_LCD_FRAMEBUFFER = y``):
|
||||
|
||||
#. This interface implements the ``up_fbinitialize`` which:
|
||||
|
||||
#. Provides the instance of ``struct fb_vtable_s`` (a member of ``struct lcdfb_dev_s``);
|
||||
#. Calls ``board_lcd_initialize`` and ``board_lcd_getdev`` LCD-specific functions. These functions are defined in ``boards/<arch>/<chip>/<board>/src`` and prototyped in ``include/nuttx/board.h``;
|
||||
|
||||
#. Finally, the LCD screen drivers are usually available at ``drivers/lcd/`` and implement the callbacks defined at ``include/nuttx/lcd/lcd.h``:
|
||||
|
||||
#. ``include/nuttx/lcd/lcd.h`` provides structures and APIs needed to work with LCD screens, whereas using the framebuffer adapter or the :doc:`lcd`;
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Examples apply to specific cases of the :ref:`genericlcdfb`:
|
||||
|
||||
.. _ttgotdisplayesp32:
|
||||
|
||||
TTGO T-Display ESP32 board
|
||||
---------------------------
|
||||
|
||||
This board contains an ST7789 TFT Display (135x240).
|
||||
By selecting the ``ttgo_t_display_esp32:lvgl_fb`` config, the ``lvgldemo`` example will be built with the framebuffer interface.
|
||||
|
||||
* ``boards/xtensa/esp32/ttgo_t_display_esp32/src/esp32_bringup.c`` registers the framebuffer driver:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#ifdef CONFIG_VIDEO_FB
|
||||
ret = fb_register(0, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to initialize Frame Buffer Driver.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
* ``up_fbinitialize`` from the frame buffer adapter will then be called as ``CONFIG_LCD_FRAMEBUFFER = y``:
|
||||
|
||||
* ``board_lcd_initialize`` and ``board_lcd_getdev`` are defined at ``boards/xtensa/esp32/common/src/esp32_st7789.c``:
|
||||
|
||||
* ``board_lcd_initialize`` initializes the LCD hardware on the board by defining the SPI interface which is connected to the display controller;
|
||||
* ``board_lcd_getdev`` calls the ``st7789_lcdinitialize`` and returns a reference to the LCD object for the specified LCD;
|
||||
* ``st7789_lcdinitialize`` is part of the LCD screen driver at ``drivers/lcd/st7789.c``;
|
||||
|
||||
* The LVGL demo application (``lvgldemo``) makes use of the ``ioctl`` system call to trigger a ``FBIO_UPDATE`` request to the higher-level device driver to refresh the LCD screen with framebuffer data:
|
||||
.. code-block:: c
|
||||
|
||||
ioctl(state.fd, FBIO_UPDATE, (unsigned long)((uintptr_t)&fb_area));
|
||||
|
||||
NuttX Simulator
|
||||
----------------
|
||||
|
||||
:doc:`NuttX Simulator </platforms/sim/sim/index>` provides a X11-based framebuffer driver to simulate the framebuffer usage into a X11-compatible host.
|
||||
|
||||
By selecting the ``sim:lvgl_fb`` config, the ``lvgldemo`` example will be built with the framebuffer driver.
|
||||
|
||||
* ``boards/sim/sim/sim/src/sim_bringup.c`` registers the framebuffer driver the same way :ref:`ttgotdisplayesp32`;
|
||||
* ``arch/sim/src/sim/up_framebuffer.c`` and ``arch/sim/src/sim/up_x11framebuffer.c`` will be built as ``CONFIG_SIM_FRAMEBUFFER = y`` and ``CONFIG_SIM_X11FB = y`` are set, respectively;
|
||||
|
||||
* ``up_framebuffer.c`` provides ``up_fbinitialize`` and,
|
||||
* calls ``up_x11initialize`` from ``up_x11framebuffer.c`` that initializes a X11-based window as a framebuffer. This is the underlying "driver".
|
||||
|
||||
* The LVGL demo application (``lvgldemo``) makes use of the ``ioctl`` system call to trigger a ``FBIO_UPDATE`` request to the higher-level device driver in order to refresh the LCD screen with framebuffer data as usual;
|
||||
|
||||
.. warning::
|
||||
|
||||
One must consider that framebuffer requires that the entire display's pixels to be represented.
|
||||
Considering a 320x480 @RGB565 LCD screen, that would be 300KiB, which it'd be too much for a memory-constrained device.
|
||||
|
||||
However, when memory is not a constraint, framebuffer may offer applications a faster way to update display contents once writing to the RAM-mapped buffer is faster than doing multiple SPI transfers.
|
||||
|
||||
For memory-constrained devices, consider using :doc:`lcd`.
|
||||
|
@ -1,47 +1,103 @@
|
||||
===========
|
||||
LCD Drivers
|
||||
===========
|
||||
====================
|
||||
LCD Character Drivers
|
||||
====================
|
||||
|
||||
- ``include/nuttx/lcd/lcd.h``. Structures and APIs needed to
|
||||
work with LCD drivers are provided in this header file. This
|
||||
header file also depends on some of the same definitions used
|
||||
for the frame buffer driver as provided in
|
||||
``include/nuttx/video/fb.h``.
|
||||
The LCD driver exposes the LCD interface to userspace via ``ioctl()`` commands.
|
||||
|
||||
- ``struct lcd_dev_s``. Each LCD device driver must implement
|
||||
an instance of ``struct lcd_dev_s``. That structure defines a
|
||||
call table with the following methods:
|
||||
The LCD driver is intended to be used in the following scenarios:
|
||||
|
||||
Get information about the LCD video controller configuration
|
||||
and the configuration of each LCD color plane.
|
||||
#. On memory-constrained devices, as it doesn't require a buffer to represent the whole display:
|
||||
|
||||
The following are provided only if the video hardware supports
|
||||
RGB color mapping:
|
||||
#. Hence, it's an alternative to the :doc:`framebuffer`;
|
||||
|
||||
The following are provided only if the video hardware supports
|
||||
a hardware cursor:
|
||||
#. For graphics libraries that draw specific areas of the displays, like ``LVGL``;
|
||||
|
||||
Get the LCD panel power status (0: full off -
|
||||
``CONFIG_LCD_MAXPOWER``: full on). On backlit LCDs, this
|
||||
setting may correspond to the backlight setting.
|
||||
Binding
|
||||
========
|
||||
LCD drivers usually are not directly accessed by user code, but are usually bound to another, higher-level device driver.
|
||||
In general, the binding sequence is:
|
||||
|
||||
Enable/disable LCD panel power (0: full off -
|
||||
``CONFIG_LCD_MAXPOWER``: full on). On backlit LCDs, this
|
||||
setting may correspond to the backlight setting.
|
||||
#. Get an instance of ``struct lcd_dev_s`` from the hardware-specific LCD screen driver, and
|
||||
#. Provide that instance to the initialization method of the higher-level character driver.
|
||||
|
||||
Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST) \*/
|
||||
.. _genericlcdlcd:
|
||||
|
||||
Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST)
|
||||
Generic LCD Character Driver
|
||||
------------------------
|
||||
|
||||
- **Binding LCD Drivers**. LCD drivers are not normally directly
|
||||
accessed by user code, but are usually bound to another, higher
|
||||
level device driver. In general, the binding sequence is:
|
||||
This example will walk through the path from userspace to hardware-specific details on how an LCD screen is bound to an LCD character driver.
|
||||
|
||||
#. Get an instance of ``struct lcd_dev_s`` from the
|
||||
hardware-specific LCD device driver, and
|
||||
#. Provide that instance to the initialization method of the
|
||||
higher level device driver.
|
||||
#. ``include/nuttx/lcd/lcd.h`` provides all structures and APIs needed to work with LCD screens drivers:
|
||||
|
||||
- **Examples**: ``drivers/lcd/p14201.c``,
|
||||
``boards/arm/sam34/sam3u-ek/src/up_lcd.c.`` See also the usage
|
||||
of the LCD driver in the ``graphics/`` directory.
|
||||
#. This header file also depends on some of the same definitions used for the frame buffer driver as provided in ``include/nuttx/video/fb.h``;
|
||||
#. ``drivers/lcd/lcd_dev.c`` is the higher-level device driver. An instance of ``struct lcd_dev_s`` will be provided to it:
|
||||
|
||||
#. ``include/nuttx/lcd/lcd_dev.h`` prototypes public structures and functions;
|
||||
#. ``lcddev_register`` registers the LCD character driver as ``/dev/lcdN`` where N is the display number and,
|
||||
#. calls the ``board_lcd_getdev``, an LCD-specific function usually defined in ``boards/<arch>/<chip>/<board>/src`` and prototyped in ``include/nuttx/board.h``;
|
||||
|
||||
#. Finally, the LCD screen drivers are usually available at ``drivers/lcd/`` and implement the callbacks defined at ``include/nuttx/lcd/lcd.h``:
|
||||
|
||||
#. ``include/nuttx/lcd/lcd.h`` provides structures and APIs needed to work with LCD screens, whether using the framebuffer adapter or the :doc:`lcd`;
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Examples apply to specific cases of the :ref:`genericlcdlcd`:
|
||||
|
||||
.. _ttgotdisplayesp32:
|
||||
|
||||
TTGO T-Display ESP32 board
|
||||
---------------------------
|
||||
|
||||
This board contains an ST7789 TFT Display (135x240).
|
||||
By selecting the ``ttgo_t_display_esp32:lvgl_lcd`` config, the ``lvgldemo`` example will be built with the LCD character interface.
|
||||
|
||||
* ``boards/xtensa/esp32/ttgo_t_display_esp32/src/esp32_bringup.c`` registers the LCD character driver:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#ifdef CONFIG_LCD_DEV
|
||||
ret = board_lcd_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: board_lcd_initialize() failed: %d\n", ret);
|
||||
}
|
||||
|
||||
ret = lcddev_register(0);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: lcddev_register() failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
* ``board_lcd_initialize`` and ``board_lcd_getdev`` are defined at ``boards/xtensa/esp32/common/src/esp32_st7789.c``;
|
||||
|
||||
* ``board_lcd_initialize`` initializes the LCD hardware on the board by defining the SPI interface which is connected to the display controller;
|
||||
|
||||
* ``lcddev_register`` then calls ``board_lcd_getdev``:
|
||||
|
||||
* ``board_lcd_getdev`` calls the ``st7789_lcdinitialize`` and returns a reference to the LCD object for the specified LCD;
|
||||
* ``st7789_lcdinitialize`` is part of the LCD screen driver at ``drivers/lcd/st7789.c``;
|
||||
|
||||
* The LVGL demo application (``lvgldemo``) makes use of the ``ioctl`` system call to trigger an ``LCDDEVIO_PUTAREA`` request to the higher-level device driver to refresh the LCD screen with data:
|
||||
.. code-block:: c
|
||||
|
||||
ioctl(state.fd, LCDDEVIO_PUTAREA, (unsigned long)((uintptr_t)&lcd_area));;
|
||||
|
||||
NuttX Simulator
|
||||
----------------
|
||||
|
||||
:doc:`NuttX Simulator </platforms/sim/sim/index>` provides a X11-based LCD character driver to simulate the LCD character displat usage into a X11-compatible host.
|
||||
|
||||
By selecting the ``sim:lvgl_lcd`` config, the ``lvgldemo`` example will be built with the LCD character interface.
|
||||
|
||||
* ``boards/sim/sim/sim/src/sim_bringup.c`` registers the framebuffer driver the same way :ref:`ttgotdisplayesp32`;
|
||||
* ``arch/sim/src/sim/up_lcd.c`` and ``arch/sim/src/sim/up_x11framebuffer.c`` will be built as ``CONFIG_SIM_LCDDRIVER = y`` and ``CONFIG_SIM_X11FB = y`` are set, respectively;
|
||||
|
||||
* ``up_lcd.c`` provides ``board_lcd_initialize`` and ``board_lcd_getdev``:
|
||||
|
||||
* ``board_lcd_initialize`` calls ``up_x11initialize`` from ``up_x11framebuffer.c`` that initializes a X11-based window as an LCD character device. This is the underlying "driver".
|
||||
|
||||
* The LVGL demo application (``lvgldemo``) makes use of the ``ioctl`` system call to trigger an ``LCDDEVIO_PUTAREA`` request to the higher-level device driver to refresh the LCD screen with data as usual;
|
||||
|
Loading…
Reference in New Issue
Block a user