mirror of
https://github.com/lvgl/lvgl.git
synced 2026-09-28 16:10:54 +08:00
docs minor fixes
This commit is contained in:
+24
-23
@@ -4,7 +4,7 @@
|
||||
```
|
||||
# Display interface
|
||||
|
||||
To set up a display an `lv_disp_draw_buf_t` and an `lv_disp_drv_t` variables have to be initialized.
|
||||
To register a display for LVGL an `lv_disp_draw_buf_t` and an `lv_disp_drv_t` variables have to be initialized.
|
||||
- `lv_disp_draw_buf_t` contains internal graphic buffer(s), called draw buffer(s).
|
||||
- `lv_disp_drv_t` contains callback functions to interact with the display and manipulate drawing related things.
|
||||
|
||||
@@ -22,23 +22,23 @@ static lv_disp_draw_buf_t disp_buf;
|
||||
static lv_color_t buf_1[MY_DISP_HOR_RES * 10];
|
||||
static lv_color_t buf_2[MY_DISP_HOR_RES * 10];
|
||||
|
||||
/*Initialize `disp_buf` with the buffer(s) */
|
||||
/*Initialize `disp_buf` with the buffer(s). With only one buffer use NULL instead buf_2 */
|
||||
lv_disp_draw_buf_init(&disp_buf, buf_1, buf_2, MY_DISP_HOR_RES*10);
|
||||
```
|
||||
|
||||
Note that `lv_disp_draw_buf_t` needs to be static, global or dynamically allocated and not a local variable destroyed if goes out of the scope.
|
||||
|
||||
|
||||
As you can see the draw buffer can be smaller than the screen. In this case, the larger areas will be redrawn in smaller parts that fit into the draw buffer(s).
|
||||
If only a small area changes (e.g. a button is pressed) then only that area will be refreshed.
|
||||
|
||||
A larger buffer results in better performance but above 1/10 screen sized buffer(s) there is no significant performance improvement.
|
||||
Therefore it's recommended to choose the size of the draw buffer(s) to at least 1/10 screen sized.
|
||||
|
||||
If only **one buffer** is used LVGL draws the content of the screen into that draw buffer and sends it to the display.
|
||||
If only **one buffer** is used LVGL draws the content of the screen into that draw buffer and sends it to the display.
|
||||
This way LVGL needs to wait until the content of the buffer is sent to the display before drawing something new in it.
|
||||
|
||||
If **two buffers** are used LVGL can draw into one buffer while the content of the other buffer is sent to display in the background.
|
||||
DMA or other hardware should be used to transfer the data to the display to let the CPU draw meanwhile.
|
||||
DMA or other hardware should be used to transfer the data to the display to let the MCU draw meanwhile.
|
||||
This way, the rendering and refreshing of the display become parallel.
|
||||
|
||||
In the display driver (`lv_disp_drv_t`) the `full_refresh` bit can be enabled to force LVGL always redraw the whole screen. It works in both *one buffer* and *two buffers* modes.
|
||||
@@ -47,43 +47,43 @@ If `full_refresh` is enabled and 2 screen sized draw buffers are provided, LVGL
|
||||
It means in `flush_cb` only the address of the frame buffer needs to be changed to provided pointer (`color_p` parameter).
|
||||
This configuration should be used if the MCU has LCD controller periphery and not with an external display controller (e.g. ILI9341 or SSD1963).
|
||||
|
||||
You can measure the performance of different draw buffer configurations using the [benchmark example](https://github.com/lvgl/lv_examples/tree/master/src/lv_demo_benchmark).
|
||||
You can measure the performance of different draw buffer configurations using the [benchmark example](https://github.com/lvgl/lv_demos/tree/master/src/lv_demo_benchmark).
|
||||
|
||||
## Display driver
|
||||
|
||||
Once the buffer initialization is ready a `lv_disp_drv_t` display drivers need to be
|
||||
1. initialized with `lv_disp_drv_init(&disp_drv)`
|
||||
2. its fields needs to be set and
|
||||
2. its fields needs to be set
|
||||
3. registered in LVGL with `lv_disp_drv_register(&disp_drv)`
|
||||
|
||||
Note that `lv_disp_drv_t` needs to be static, global or dynamically allocated and not a local variable destroyed if goes out of the scope.
|
||||
Note that `lv_disp_drv_t` also needs to be static, global or dynamically allocated and not a local variable destroyed if goes out of the scope.
|
||||
|
||||
### Mandatory fields
|
||||
In the most simple case only the following fields of `lv_disp_drv_t` needs to be set:
|
||||
- `draw_buf` pointer to an initialized `lv_disp_draw_buf_t` variable.
|
||||
- `hor_res` horizontal resolution of the display in pixels.
|
||||
- `ver_res` vertical resolution of the display in pixels.
|
||||
- `flush_cb` a callback function to copy a buffer's content to a specific area of the display.
|
||||
`lv_disp_flush_ready(&disp_drv)` needs to be called when flushing is ready.
|
||||
LVGL might render the screen in multiple chunks and therefore call `flush_cb` multiple times. To see which is the last chunk of rendering use `lv_disp_flush_is_last(&disp_drv)`.
|
||||
- `hor_res` horizontal resolution of the display in pixels.
|
||||
- `ver_res` vertical resolution of the display in pixels.
|
||||
|
||||
### Optional fields
|
||||
There are some optional data fields:
|
||||
- `color_chroma_key` A color which will be drawn as transparent on chrome keyed images. Set to `LV_COLOR_CHROMA_KEY` by default from `lv_conf.h`.
|
||||
- `user_data` A custom `void `user data for the driver..
|
||||
- `anti_aliasing` use anti-aliasing (edge smoothing). Enabled by default if `LV_COLOR_DEPTH` is set to at least 16 in `lv_conf.h`.
|
||||
- `rotated` and `sw_rotate` See the [rotation](#rotation) section below.
|
||||
- `rotated` and `sw_rotate` See the [Rotation](#rotation) section below.
|
||||
- `screen_transp` if `1` the screen itself can have transparency as well. `LV_COLOR_SCREEN_TRANSP` needs to enabled in `lv_conf.h` and requires `LV_COLOR_DEPTH 32`.
|
||||
- `user_data` A custom `void `user data for the driver..
|
||||
|
||||
Some other optional callbacks to make easier and more optimal to work with monochrome, grayscale or other non-standard RGB displays:
|
||||
- `rounder_cb` Round the coordinates of areas to redraw. E.g. a 2x2 px can be converted to 2x8.
|
||||
It can be used if the display controller can refresh only areas with specific height or width (usually 8 px height with monochrome displays).
|
||||
- `set_px_cb` a custom function to write the draw buffer. It can be used to store the pixels more compactly i nthe draw buffer if the display has a special color format. (e.g. 1-bit monochrome, 2-bit grayscale etc.)
|
||||
This way the buffers used in `lv_disp_draw_buf_t` can be smaller to hold only the required number of bits for the given area size. Rendering with `set_px_cb` is slower than normal rendering.
|
||||
- `monitor_cb` A callback function that tells how many pixels were refreshed in how much time.
|
||||
- `set_px_cb` a custom function to write the draw buffer. It can be used to store the pixels more compactly in the draw buffer if the display has a special color format. (e.g. 1-bit monochrome, 2-bit grayscale etc.)
|
||||
This way the buffers used in `lv_disp_draw_buf_t` can be smaller to hold only the required number of bits for the given area size. Note that, rendering with `set_px_cb` is slower than normal rendering.
|
||||
- `monitor_cb` A callback function that tells how many pixels were refreshed in how much time. Called when the last chunk is rendered and sent to the display.
|
||||
- `clean_dcache_cb` A callback for cleaning any caches related to the display.
|
||||
|
||||
To use a GPU the following callbacks can be used:
|
||||
LVGL has built-in support to several GPUs (see `lv_conf.h`) but if something else is required these functions can be used to make LVGL use a GPU:
|
||||
- `gpu_fill_cb` fill an area in the memory with a color.
|
||||
- `gpu_wait_cb` if any GPU function return, while the GPU is still working, LVGL will use this function when required the be sure GPU rendering is ready.
|
||||
|
||||
@@ -105,7 +105,8 @@ Here are some simple examples of the callbacks:
|
||||
```c
|
||||
void my_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
|
||||
{
|
||||
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
|
||||
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one
|
||||
*`put_px` is just an example, it needs to implemented by you.*/
|
||||
int32_t x, y;
|
||||
for(y = area->y1; y <= area->y2; y++) {
|
||||
for(x = area->x1; x <= area->x2; x++) {
|
||||
@@ -137,15 +138,15 @@ void my_gpu_fill_cb(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, const lv_ar
|
||||
void my_rounder_cb(lv_disp_drv_t * disp_drv, lv_area_t * area)
|
||||
{
|
||||
/* Update the areas as needed.
|
||||
* For example make the area to start only on 8th rows and have Nx8 pixel height:*/
|
||||
* For example it makes the area to start only on 8th rows and have Nx8 pixel height.*/
|
||||
area->y1 = area->y1 & 0x07;
|
||||
area->y2 = (area->y2 & 0x07) + 8;
|
||||
}
|
||||
|
||||
void my_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
/* Write to the buffer as required for the display.
|
||||
* Write only 1-bit for monochrome displays mapped vertically:*/
|
||||
/* Write to the buffer as required for the display.
|
||||
* For example it writes only 1-bit for monochrome displays mapped vertically.*/
|
||||
buf += buf_w * (y >> 3) + x;
|
||||
if(lv_color_brightness(color) > 128) (*buf) |= (1 << (y % 8));
|
||||
else (*buf) &= ~(1 << (y % 8));
|
||||
@@ -181,9 +182,9 @@ Support for software rotation is a new feature, so there may be some glitches/bu
|
||||
|
||||
## Further reading
|
||||
|
||||
See [lv_port_disp_template.c](https://github.com/lvgl/lvgl/blob/master/examples/porting/lv_port_disp_template.c) for a template for your own driver.
|
||||
|
||||
Check out the [Drawing](/overview/drawing) section to learn more about how rendering works in LVGL.
|
||||
- [lv_port_disp_template.c](https://github.com/lvgl/lvgl/blob/master/examples/porting/lv_port_disp_template.c) for a template for your own driver.
|
||||
- [Drawing](/overview/drawing) to learn more about how rendering works in LVGL.
|
||||
- [Display features](/overview/display) to learn more about higher level display features.
|
||||
|
||||
## API
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
## Types of input devices
|
||||
|
||||
To set up an input device an `lv_indev_drv_t` variable has to be initialized:
|
||||
To register an input device an `lv_indev_drv_t` variable has to be initialized:
|
||||
|
||||
```c
|
||||
lv_indev_drv_t indev_drv;
|
||||
@@ -188,11 +188,16 @@ Besides `read_cb` a `feedback_cb` callback can be also specified in `lv_indev_dr
|
||||
Every Input device is associated with a display. By default, a new input device is added to the lastly created or the explicitly selected (using `lv_disp_set_default()`) display.
|
||||
The associated display is stored and can be changed in `disp` field of the driver.
|
||||
|
||||
### Event driven reading
|
||||
### Buffered reading
|
||||
By default LVGL calls `read_cb` periodically. This way there is a chance that some user gestures are missed.
|
||||
|
||||
To solve this you write an event driven driver for your input device that buffers measured data. In `read_cb` you can set the buffered data instead of reading the input device.
|
||||
You can set the `data->continue_reding` flag to LVGL there is more data to read and call `read_cb` again.
|
||||
To solve this you can write an event driven driver for your input device that buffers measured data. In `read_cb` you can set the buffered data instead of reading the input device.
|
||||
You can set the `data->continue_reding` flag to tell that LVGL there is more data to read and it should call the `read_cb` again.
|
||||
|
||||
## Further reading
|
||||
|
||||
- [lv_port_indev_template.c](https://github.com/lvgl/lvgl/blob/master/examples/porting/lv_port_indev_template.c) for a template for your own driver.
|
||||
- [INdev features](/overview/display) to learn more about higher level input device features.
|
||||
|
||||
## API
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
sys
|
||||
project
|
||||
display
|
||||
indev
|
||||
|
||||
+17
-32
@@ -4,49 +4,34 @@
|
||||
```
|
||||
# Logging
|
||||
|
||||
LVGL has built-in *log* module to inform the user about what is happening in the library.
|
||||
LVGL has built-in *Log* module to inform the user about what is happening in the library.
|
||||
|
||||
## Log level
|
||||
To enable logging, set `LV_USE_LOG 1` in *lv_conf.h* and set `LV_LOG_LEVEL` to one of the following values:
|
||||
- **LV_LOG_LEVEL_TRACE** A lot of logs to give detailed information
|
||||
- **LV_LOG_LEVEL_INFO** Log important events
|
||||
- **LV_LOG_LEVEL_WARN** Log if something unwanted happened but didn't cause a problem
|
||||
- **LV_LOG_LEVEL_ERROR** Only critical issue, when the system may fail
|
||||
- **LV_LOG_LEVEL_NONE** Do not log anything
|
||||
To enable logging, set `LV_USE_LOG 1` in `lv_conf.h` and set `LV_LOG_LEVEL` to one of the following values:
|
||||
- `LV_LOG_LEVEL_TRACE` A lot of logs to give detailed information
|
||||
- `LV_LOG_LEVEL_INFO` Log important events
|
||||
- `LV_LOG_LEVEL_WARN` Log if something unwanted happened but didn't cause a problem
|
||||
- `LV_LOG_LEVEL_ERROR` Only critical issue, when the system may fail
|
||||
- `LV_LOG_LEVEL_USER` Only user messages
|
||||
- `LV_LOG_LEVEL_NONE` Do not log anything
|
||||
|
||||
The events which have a higher level than the set log level will be logged too. E.g. if you `LV_LOG_LEVEL_WARN`, *errors* will be also logged.
|
||||
The events which have a higher level than the set log level will be logged too. E.g. if you `LV_LOG_LEVEL_WARN`, errors will be also logged.
|
||||
|
||||
## Logging with printf
|
||||
If your system supports `printf`, you just need to enable `LV_LOG_PRINTF` in *lv_conf.h* to send the logs with `printf`.
|
||||
## Printing logs
|
||||
|
||||
### Logging with printf
|
||||
If your system supports `printf`, you just need to enable `LV_LOG_PRINTF` in `lv_conf.h` to send the logs with `printf`.
|
||||
|
||||
|
||||
## Custom log function
|
||||
### Custom log function
|
||||
If you can't use `printf` or want to use a custom function to log, you can register a "logger" callback with `lv_log_register_print_cb()`.
|
||||
|
||||
For example:
|
||||
|
||||
```c
|
||||
void my_log_cb(lv_log_level_t level, const char * file, uint32_t line, const char * fn_name, const char * dsc)
|
||||
void my_log_cb(const char * buf)
|
||||
{
|
||||
/*Send the logs via serial port*/
|
||||
if(level == LV_LOG_LEVEL_ERROR) serial_send("ERROR: ");
|
||||
if(level == LV_LOG_LEVEL_WARN) serial_send("WARNING: ");
|
||||
if(level == LV_LOG_LEVEL_INFO) serial_send("INFO: ");
|
||||
if(level == LV_LOG_LEVEL_TRACE) serial_send("TRACE: ");
|
||||
|
||||
serial_send("File: ");
|
||||
serial_send(file);
|
||||
|
||||
char line_str[8];
|
||||
sprintf(line_str,"%d", line);
|
||||
serial_send("#");
|
||||
serial_send(line_str);
|
||||
|
||||
serial_send(": ");
|
||||
serial_send(fn_name);
|
||||
serial_send(": ");
|
||||
serial_send(dsc);
|
||||
serial_send("\n");
|
||||
serial_send(buf, strlen(buf));
|
||||
}
|
||||
|
||||
...
|
||||
@@ -58,4 +43,4 @@ lv_log_register_print_cb(my_log_cb);
|
||||
|
||||
## Add logs
|
||||
|
||||
You can also use the log module via the `LV_LOG_TRACE/INFO/WARN/ERROR(description)` functions.
|
||||
You can also use the log module via the `LV_LOG_TRACE/INFO/WARN/ERROR/USER(text)` functions.
|
||||
|
||||
@@ -15,23 +15,21 @@ The graphics library is the **lvgl** directory which should be copied into your
|
||||
|
||||
## Configuration file
|
||||
|
||||
There is a configuration header file for LVGL called **lv_conf.h**. It sets the library's basic behaviour, disables unused modules and features, adjusts the size of memory buffers in compile-time, etc.
|
||||
There is a configuration header file for LVGL called **lv_conf.h**. In this you can set the library's basic behaviour, disable unused modules and features, adjusts the size of memory buffers in compile-time, etc.
|
||||
|
||||
Copy **lvgl/lv_conf_template.h** next to the *lvgl* directory and rename it to *lv_conf.h*. Open the file and change the `#if 0` at the beginning to `#if 1` to enable its content.
|
||||
|
||||
*lv_conf.h* can be copied other places as well but then you should add `LV_CONF_INCLUDE_SIMPLE` define to your compiler options (e.g. `-DLV_CONF_INCLUDE_SIMPLE` for gcc compiler) and set the include path manually.
|
||||
*lv_conf.h* can be copied other places as well but then you should add `LV_CONF_INCLUDE_SIMPLE` define to your compiler options (e.g. `-DLV_CONF_INCLUDE_SIMPLE` for gcc compiler) and set the include path manually.
|
||||
In this case LVGL will attempt to include `lv_conf.h` simply with `#include "lv_conf.h"`.
|
||||
|
||||
In the config file comments explain the meaning of the options. Check at least these three configuration options and modify them according to your hardware:
|
||||
1. **LV_HOR_RES_MAX** Your display's horizontal resolution.
|
||||
2. **LV_VER_RES_MAX** Your display's vertical resolution.
|
||||
3. **LV_COLOR_DEPTH** 8 for (RG332), 16 for (RGB565) or 32 for (RGB888 and ARGB8888).
|
||||
In the config file comments explain the meaning of the options. Be sure to set at least `LV_COLOR_DEPTH` according to your display's colro depth.
|
||||
|
||||
## Initialization
|
||||
|
||||
To use the graphics library you have to initialize it and the other components too. The order of the initialization is:
|
||||
|
||||
1. Call *lv_init()*.
|
||||
1. Call `lv_init()`.
|
||||
2. Initialize your drivers.
|
||||
3. Register the display and input devices drivers in LVGL. More about [Display](/porting/display) and [Input device](/porting/indev) registration.
|
||||
3. Register the display and input devices drivers in LVGL. Lear more about [Display](/porting/display) and [Input device](/porting/indev) registration.
|
||||
4. Call `lv_tick_inc(x)` in every `x` milliseconds in an interrupt to tell the elapsed time. [Learn more](/porting/tick).
|
||||
5. Call `lv_task_handler()` periodically in every few milliseconds to handle LVGL related tasks. [Learn more](/porting/task-handler).
|
||||
5. Call `lv_timer_handler()` periodically in every few milliseconds to handle LVGL related tasks. [Learn more](/porting/task-handler).
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
```eval_rst
|
||||
.. include:: /header.rst
|
||||
:github_url: |github_link_base|/porting/sys.md
|
||||
```
|
||||
# System overview
|
||||
|
||||
")
|
||||
|
||||
**Application**
|
||||
Your application which creates the GUI and handles the specific tasks.
|
||||
|
||||
**LVGL**
|
||||
The graphics library itself. Your application can communicate with the library to create a GUI. It contains a HAL (Hardware Abstraction Layer) interface to register your display and input device drivers.
|
||||
|
||||
**Driver**
|
||||
Besides your specific drivers, it contains functions to drive your display, optionally to a GPU and to read the touchpad or buttons.
|
||||
|
||||
* * *
|
||||
|
||||
Depending on the MCU, there are two typical hardware set-ups. One with built-in LCD/TFT driver periphery and another without it. In both cases, a frame buffer will be required to store the current image of the screen.
|
||||
|
||||
1. **MCU with TFT/LCD driver**
|
||||
If your MCU has a TFT/LCD driver periphery then you can connect a display directly via RGB interface.
|
||||
In this case, the frame buffer can be in the internal RAM (if the MCU has enough RAM) or in the external RAM (if the MCU has a memory interface).
|
||||
|
||||
2. **External display controller**
|
||||
If the MCU doesn't have TFT/LCD driver interface then an external display controller (E.g. SSD1963, SSD1306, ILI9341) has to be used.
|
||||
In this case, the MCU can communicate with the display controller via Parallel port, SPI or sometimes I2C.
|
||||
The frame buffer is usually located in the display controller which saves a lot of RAM for the MCU.
|
||||
Reference in New Issue
Block a user