inital commit
@@ -0,0 +1,391 @@
|
|||||||
|
#include "Display_ST77916.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "driver/spi_master.h"
|
||||||
|
#include "esp_lcd_panel_io.h"
|
||||||
|
#include "esp_lcd_st77916.h"
|
||||||
|
|
||||||
|
#include "esp_lcd_panel_io_interface.h"
|
||||||
|
#include "esp_lcd_panel_ops.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define LCD_OPCODE_WRITE_CMD (0x02ULL)
|
||||||
|
#define LCD_OPCODE_READ_CMD (0x0BULL)
|
||||||
|
#define LCD_OPCODE_WRITE_COLOR (0x32ULL)
|
||||||
|
|
||||||
|
static const st77916_lcd_init_cmd_t vendor_specific_init_new[] = {
|
||||||
|
{0xF0, (uint8_t []){0x28}, 1, 0},
|
||||||
|
{0xF2, (uint8_t []){0x28}, 1, 0},
|
||||||
|
{0x73, (uint8_t []){0xF0}, 1, 0},
|
||||||
|
{0x7C, (uint8_t []){0xD1}, 1, 0},
|
||||||
|
{0x83, (uint8_t []){0xE0}, 1, 0},
|
||||||
|
{0x84, (uint8_t []){0x61}, 1, 0},
|
||||||
|
{0xF2, (uint8_t []){0x82}, 1, 0},
|
||||||
|
{0xF0, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xF0, (uint8_t []){0x01}, 1, 0},
|
||||||
|
{0xF1, (uint8_t []){0x01}, 1, 0},
|
||||||
|
{0xB0, (uint8_t []){0x56}, 1, 0},
|
||||||
|
{0xB1, (uint8_t []){0x4D}, 1, 0},
|
||||||
|
{0xB2, (uint8_t []){0x24}, 1, 0},
|
||||||
|
{0xB4, (uint8_t []){0x87}, 1, 0},
|
||||||
|
{0xB5, (uint8_t []){0x44}, 1, 0},
|
||||||
|
{0xB6, (uint8_t []){0x8B}, 1, 0},
|
||||||
|
{0xB7, (uint8_t []){0x40}, 1, 0},
|
||||||
|
{0xB8, (uint8_t []){0x86}, 1, 0},
|
||||||
|
{0xBA, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xBB, (uint8_t []){0x08}, 1, 0},
|
||||||
|
{0xBC, (uint8_t []){0x08}, 1, 0},
|
||||||
|
{0xBD, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xC0, (uint8_t []){0x80}, 1, 0},
|
||||||
|
{0xC1, (uint8_t []){0x10}, 1, 0},
|
||||||
|
{0xC2, (uint8_t []){0x37}, 1, 0},
|
||||||
|
{0xC3, (uint8_t []){0x80}, 1, 0},
|
||||||
|
{0xC4, (uint8_t []){0x10}, 1, 0},
|
||||||
|
{0xC5, (uint8_t []){0x37}, 1, 0},
|
||||||
|
{0xC6, (uint8_t []){0xA9}, 1, 0},
|
||||||
|
{0xC7, (uint8_t []){0x41}, 1, 0},
|
||||||
|
{0xC8, (uint8_t []){0x01}, 1, 0},
|
||||||
|
{0xC9, (uint8_t []){0xA9}, 1, 0},
|
||||||
|
{0xCA, (uint8_t []){0x41}, 1, 0},
|
||||||
|
{0xCB, (uint8_t []){0x01}, 1, 0},
|
||||||
|
{0xD0, (uint8_t []){0x91}, 1, 0},
|
||||||
|
{0xD1, (uint8_t []){0x68}, 1, 0},
|
||||||
|
{0xD2, (uint8_t []){0x68}, 1, 0},
|
||||||
|
{0xF5, (uint8_t []){0x00, 0xA5}, 2, 0},
|
||||||
|
{0xDD, (uint8_t []){0x4F}, 1, 0},
|
||||||
|
{0xDE, (uint8_t []){0x4F}, 1, 0},
|
||||||
|
{0xF1, (uint8_t []){0x10}, 1, 0},
|
||||||
|
{0xF0, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xF0, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0xE0, (uint8_t []){0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0},
|
||||||
|
{0xE1, (uint8_t []){0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0},
|
||||||
|
{0xF0, (uint8_t []){0x10}, 1, 0},
|
||||||
|
{0xF3, (uint8_t []){0x10}, 1, 0},
|
||||||
|
{0xE0, (uint8_t []){0x07}, 1, 0},
|
||||||
|
{0xE1, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xE2, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xE3, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xE4, (uint8_t []){0xE0}, 1, 0},
|
||||||
|
{0xE5, (uint8_t []){0x06}, 1, 0},
|
||||||
|
{0xE6, (uint8_t []){0x21}, 1, 0},
|
||||||
|
{0xE7, (uint8_t []){0x01}, 1, 0},
|
||||||
|
{0xE8, (uint8_t []){0x05}, 1, 0},
|
||||||
|
{0xE9, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0xEA, (uint8_t []){0xDA}, 1, 0},
|
||||||
|
{0xEB, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xEC, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xED, (uint8_t []){0x0F}, 1, 0},
|
||||||
|
{0xEE, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xEF, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xF8, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xF9, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xFA, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xFB, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xFC, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xFD, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xFE, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xFF, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x60, (uint8_t []){0x40}, 1, 0},
|
||||||
|
{0x61, (uint8_t []){0x04}, 1, 0},
|
||||||
|
{0x62, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x63, (uint8_t []){0x42}, 1, 0},
|
||||||
|
{0x64, (uint8_t []){0xD9}, 1, 0},
|
||||||
|
{0x65, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x66, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x67, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x68, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x69, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x6A, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x6B, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x70, (uint8_t []){0x40}, 1, 0},
|
||||||
|
{0x71, (uint8_t []){0x03}, 1, 0},
|
||||||
|
{0x72, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x73, (uint8_t []){0x42}, 1, 0},
|
||||||
|
{0x74, (uint8_t []){0xD8}, 1, 0},
|
||||||
|
{0x75, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x76, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x77, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x78, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x79, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x7A, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x7B, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x80, (uint8_t []){0x48}, 1, 0},
|
||||||
|
{0x81, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x82, (uint8_t []){0x06}, 1, 0},
|
||||||
|
{0x83, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0x84, (uint8_t []){0xD6}, 1, 0},
|
||||||
|
{0x85, (uint8_t []){0x04}, 1, 0},
|
||||||
|
{0x86, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x87, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x88, (uint8_t []){0x48}, 1, 0},
|
||||||
|
{0x89, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x8A, (uint8_t []){0x08}, 1, 0},
|
||||||
|
{0x8B, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0x8C, (uint8_t []){0xD8}, 1, 0},
|
||||||
|
{0x8D, (uint8_t []){0x04}, 1, 0},
|
||||||
|
{0x8E, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x8F, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x90, (uint8_t []){0x48}, 1, 0},
|
||||||
|
{0x91, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x92, (uint8_t []){0x0A}, 1, 0},
|
||||||
|
{0x93, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0x94, (uint8_t []){0xDA}, 1, 0},
|
||||||
|
{0x95, (uint8_t []){0x04}, 1, 0},
|
||||||
|
{0x96, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x97, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x98, (uint8_t []){0x48}, 1, 0},
|
||||||
|
{0x99, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x9A, (uint8_t []){0x0C}, 1, 0},
|
||||||
|
{0x9B, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0x9C, (uint8_t []){0xDC}, 1, 0},
|
||||||
|
{0x9D, (uint8_t []){0x04}, 1, 0},
|
||||||
|
{0x9E, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x9F, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xA0, (uint8_t []){0x48}, 1, 0},
|
||||||
|
{0xA1, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xA2, (uint8_t []){0x05}, 1, 0},
|
||||||
|
{0xA3, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0xA4, (uint8_t []){0xD5}, 1, 0},
|
||||||
|
{0xA5, (uint8_t []){0x04}, 1, 0},
|
||||||
|
{0xA6, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xA7, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xA8, (uint8_t []){0x48}, 1, 0},
|
||||||
|
{0xA9, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xAA, (uint8_t []){0x07}, 1, 0},
|
||||||
|
{0xAB, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0xAC, (uint8_t []){0xD7}, 1, 0},
|
||||||
|
{0xAD, (uint8_t []){0x04}, 1, 0},
|
||||||
|
{0xAE, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xAF, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xB0, (uint8_t []){0x48}, 1, 0},
|
||||||
|
{0xB1, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xB2, (uint8_t []){0x09}, 1, 0},
|
||||||
|
{0xB3, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0xB4, (uint8_t []){0xD9}, 1, 0},
|
||||||
|
{0xB5, (uint8_t []){0x04}, 1, 0},
|
||||||
|
{0xB6, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xB7, (uint8_t []){0x00}, 1, 0},
|
||||||
|
|
||||||
|
{0xB8, (uint8_t []){0x48}, 1, 0},
|
||||||
|
{0xB9, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xBA, (uint8_t []){0x0B}, 1, 0},
|
||||||
|
{0xBB, (uint8_t []){0x02}, 1, 0},
|
||||||
|
{0xBC, (uint8_t []){0xDB}, 1, 0},
|
||||||
|
{0xBD, (uint8_t []){0x04}, 1, 0},
|
||||||
|
{0xBE, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xBF, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0xC0, (uint8_t []){0x10}, 1, 0},
|
||||||
|
{0xC1, (uint8_t []){0x47}, 1, 0},
|
||||||
|
{0xC2, (uint8_t []){0x56}, 1, 0},
|
||||||
|
{0xC3, (uint8_t []){0x65}, 1, 0},
|
||||||
|
{0xC4, (uint8_t []){0x74}, 1, 0},
|
||||||
|
{0xC5, (uint8_t []){0x88}, 1, 0},
|
||||||
|
{0xC6, (uint8_t []){0x99}, 1, 0},
|
||||||
|
{0xC7, (uint8_t []){0x01}, 1, 0},
|
||||||
|
{0xC8, (uint8_t []){0xBB}, 1, 0},
|
||||||
|
{0xC9, (uint8_t []){0xAA}, 1, 0},
|
||||||
|
{0xD0, (uint8_t []){0x10}, 1, 0},
|
||||||
|
{0xD1, (uint8_t []){0x47}, 1, 0},
|
||||||
|
{0xD2, (uint8_t []){0x56}, 1, 0},
|
||||||
|
{0xD3, (uint8_t []){0x65}, 1, 0},
|
||||||
|
{0xD4, (uint8_t []){0x74}, 1, 0},
|
||||||
|
{0xD5, (uint8_t []){0x88}, 1, 0},
|
||||||
|
{0xD6, (uint8_t []){0x99}, 1, 0},
|
||||||
|
{0xD7, (uint8_t []){0x01}, 1, 0},
|
||||||
|
{0xD8, (uint8_t []){0xBB}, 1, 0},
|
||||||
|
{0xD9, (uint8_t []){0xAA}, 1, 0},
|
||||||
|
{0xF3, (uint8_t []){0x01}, 1, 0},
|
||||||
|
{0xF0, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x21, (uint8_t []){0x00}, 1, 0},
|
||||||
|
{0x11, (uint8_t []){0x00}, 1, 120},
|
||||||
|
{0x29, (uint8_t []){0x00}, 1, 0},
|
||||||
|
};
|
||||||
|
void ST7701_Reset(){
|
||||||
|
Set_EXIO(EXIO_PIN2,Low);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
Set_EXIO(EXIO_PIN2,High);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(50));
|
||||||
|
}
|
||||||
|
void LCD_Init() {
|
||||||
|
ST77916_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_draw_bitmap(esp_lcd_panel_handle_t panel_handle)
|
||||||
|
{
|
||||||
|
uint16_t row_line = ((EXAMPLE_LCD_WIDTH / EXAMPLE_LCD_COLOR_BITS) << 1) >> 1;
|
||||||
|
uint8_t byte_per_pixel = EXAMPLE_LCD_COLOR_BITS / 8;
|
||||||
|
uint8_t *color = (uint8_t *)heap_caps_calloc(1, row_line * EXAMPLE_LCD_HEIGHT * byte_per_pixel, MALLOC_CAP_DMA);
|
||||||
|
|
||||||
|
|
||||||
|
for (int j = 0; j < EXAMPLE_LCD_COLOR_BITS; j++) {
|
||||||
|
for (int i = 0; i < row_line * EXAMPLE_LCD_HEIGHT; i++) {
|
||||||
|
for (int k = 0; k < byte_per_pixel; k++) {
|
||||||
|
color[i * byte_per_pixel + k] = (SPI_SWAP_DATA_TX(BIT(j), EXAMPLE_LCD_COLOR_BITS) >> (k * 8)) & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
esp_lcd_panel_draw_bitmap(panel_handle, 0, j * row_line, EXAMPLE_LCD_HEIGHT, (j + 1) * row_line, color);
|
||||||
|
}
|
||||||
|
free(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||||
|
int QSPI_Init(void){
|
||||||
|
static const spi_bus_config_t host_config = {
|
||||||
|
.data0_io_num = ESP_PANEL_LCD_SPI_IO_DATA0,
|
||||||
|
.data1_io_num = ESP_PANEL_LCD_SPI_IO_DATA1,
|
||||||
|
.sclk_io_num = ESP_PANEL_LCD_SPI_IO_SCK,
|
||||||
|
.data2_io_num = ESP_PANEL_LCD_SPI_IO_DATA2,
|
||||||
|
.data3_io_num = ESP_PANEL_LCD_SPI_IO_DATA3,
|
||||||
|
.data4_io_num = -1,
|
||||||
|
.data5_io_num = -1,
|
||||||
|
.data6_io_num = -1,
|
||||||
|
.data7_io_num = -1,
|
||||||
|
.max_transfer_sz = ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE,
|
||||||
|
.flags = SPICOMMON_BUSFLAG_MASTER,
|
||||||
|
.intr_flags = 0,
|
||||||
|
};
|
||||||
|
if(spi_bus_initialize(ESP_PANEL_HOST_SPI_ID_DEFAULT, &host_config, SPI_DMA_CH_AUTO) != ESP_OK){
|
||||||
|
printf("The SPI initialization failed.\r\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf("The SPI initialization succeeded.\r\n");
|
||||||
|
|
||||||
|
esp_lcd_panel_io_spi_config_t io_config ={
|
||||||
|
.cs_gpio_num = ESP_PANEL_LCD_SPI_IO_CS,
|
||||||
|
.dc_gpio_num = -1,
|
||||||
|
.spi_mode = ESP_PANEL_LCD_SPI_MODE,
|
||||||
|
.pclk_hz = 5 * 1000 * 1000,
|
||||||
|
.trans_queue_depth = ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ,
|
||||||
|
.on_color_trans_done = NULL,
|
||||||
|
.user_ctx = NULL,
|
||||||
|
.lcd_cmd_bits = ESP_PANEL_LCD_SPI_CMD_BITS,
|
||||||
|
.lcd_param_bits = ESP_PANEL_LCD_SPI_PARAM_BITS,
|
||||||
|
.flags = {
|
||||||
|
.dc_low_on_data = 0,
|
||||||
|
.octal_mode = 0,
|
||||||
|
.quad_mode = 1,
|
||||||
|
.sio_mode = 0,
|
||||||
|
.lsb_first = 0,
|
||||||
|
.cs_high_active = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||||
|
if(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)ESP_PANEL_HOST_SPI_ID_DEFAULT, &io_config, &io_handle) != ESP_OK){
|
||||||
|
printf("Failed to set LCD communication parameters -- SPI\r\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf("LCD communication parameters are set successfully -- SPI\r\n");
|
||||||
|
|
||||||
|
printf("Install LCD driver of st77916\r\n");
|
||||||
|
st77916_vendor_config_t vendor_config={
|
||||||
|
.flags = {
|
||||||
|
.use_qspi_interface = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n");
|
||||||
|
esp_err_t ret;
|
||||||
|
int lcd_cmd = 0x04;
|
||||||
|
uint8_t register_data[4];
|
||||||
|
size_t param_size = sizeof(register_data);
|
||||||
|
lcd_cmd &= 0xff;
|
||||||
|
lcd_cmd <<= 8;
|
||||||
|
lcd_cmd |= LCD_OPCODE_READ_CMD << 24; // Use the read opcode instead of write
|
||||||
|
ret = esp_lcd_panel_io_rx_param(io_handle, lcd_cmd, register_data, param_size);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
printf("Register 0x04 data: %02x %02x %02x %02x\n", register_data[0], register_data[1], register_data[2], register_data[3]);
|
||||||
|
} else {
|
||||||
|
printf("Failed to read register 0x04, error code: %d\n", ret);
|
||||||
|
}
|
||||||
|
// panel_io_spi_del(io_handle);
|
||||||
|
io_config.pclk_hz = ESP_PANEL_LCD_SPI_CLK_HZ;
|
||||||
|
if(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)ESP_PANEL_HOST_SPI_ID_DEFAULT, &io_config, &io_handle) != ESP_OK){
|
||||||
|
printf("Failed to set LCD communication parameters -- SPI\r\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf("LCD communication parameters are set successfully -- SPI\r\n");
|
||||||
|
|
||||||
|
// Check register values and configure accordingly
|
||||||
|
if (register_data[0] == 0x00 && register_data[1] == 0x7F && register_data[2] == 0x7F && register_data[3] == 0x7F) {
|
||||||
|
// Handle the case where the register data matches this pattern
|
||||||
|
printf("Vendor-specific initialization for case 1.\n");
|
||||||
|
}
|
||||||
|
else if (register_data[0] == 0x00 && register_data[1] == 0x02 && register_data[2] == 0x7F && register_data[3] == 0x7F) {
|
||||||
|
// Provide vendor-specific initialization commands if register data matches this pattern
|
||||||
|
vendor_config.init_cmds = vendor_specific_init_new;
|
||||||
|
vendor_config.init_cmds_size = sizeof(vendor_specific_init_new) / sizeof(st77916_lcd_init_cmd_t);
|
||||||
|
printf("Vendor-specific initialization for case 2.\n");
|
||||||
|
}
|
||||||
|
printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n");
|
||||||
|
|
||||||
|
esp_lcd_panel_dev_config_t panel_config={
|
||||||
|
.reset_gpio_num = EXAMPLE_LCD_PIN_NUM_RST,
|
||||||
|
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||||
|
.data_endian = LCD_RGB_DATA_ENDIAN_BIG,
|
||||||
|
.bits_per_pixel = EXAMPLE_LCD_COLOR_BITS,
|
||||||
|
.flags = {
|
||||||
|
.reset_active_high = 0,
|
||||||
|
},
|
||||||
|
.vendor_config = (void *) &vendor_config,
|
||||||
|
};
|
||||||
|
esp_lcd_new_panel_st77916(io_handle, &panel_config, &panel_handle);
|
||||||
|
|
||||||
|
esp_lcd_panel_reset(panel_handle);
|
||||||
|
esp_lcd_panel_init(panel_handle);
|
||||||
|
// esp_lcd_panel_invert_color(panel_handle,false);
|
||||||
|
|
||||||
|
esp_lcd_panel_disp_on_off(panel_handle, true);
|
||||||
|
test_draw_bitmap(panel_handle);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST77916_Init() {
|
||||||
|
ST7701_Reset();
|
||||||
|
pinMode(ESP_PANEL_LCD_SPI_IO_TE, OUTPUT);
|
||||||
|
if(!QSPI_Init()){
|
||||||
|
printf("ST77916 Failed to be initialized\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LCD_addWindow(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,uint16_t* color)
|
||||||
|
{
|
||||||
|
uint32_t size = (Xend - Xstart +1 ) * (Yend - Ystart + 1);
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
color[i] = (((color[i] >> 8) & 0xFF) | ((color[i] << 8) & 0xFF00));
|
||||||
|
}
|
||||||
|
// for (size_t i = 0; i < size; i++) {
|
||||||
|
// color[i] = 0xFFFF;
|
||||||
|
// }
|
||||||
|
Xend = Xend + 1; // esp_lcd_panel_draw_bitmap: x_end End index on x-axis (x_end not included)
|
||||||
|
Yend = Yend + 1; // esp_lcd_panel_draw_bitmap: y_end End index on y-axis (y_end not included)
|
||||||
|
if (Xend > EXAMPLE_LCD_WIDTH)
|
||||||
|
Xend = EXAMPLE_LCD_WIDTH;
|
||||||
|
if (Yend > EXAMPLE_LCD_HEIGHT)
|
||||||
|
Yend = EXAMPLE_LCD_HEIGHT;
|
||||||
|
|
||||||
|
// printf("Xstart = %d Ystart = %d Xend = %d Yend = %d \r\n",Xstart, Ystart, Xend, Yend);
|
||||||
|
esp_lcd_panel_draw_bitmap(panel_handle, Xstart, Ystart, Xend, Yend, color); // x_end End index on x-axis (x_end not included)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t LCD_Backlight = 50;
|
||||||
|
// backlight
|
||||||
|
void Backlight_Init()
|
||||||
|
{
|
||||||
|
ledcAttach(LCD_Backlight_PIN, Frequency, Resolution);
|
||||||
|
ledcWrite(LCD_Backlight_PIN, Dutyfactor);
|
||||||
|
Set_Backlight(LCD_Backlight); //0~100
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set_Backlight(uint8_t Light)
|
||||||
|
{
|
||||||
|
if(Light > Backlight_MAX || Light < 0)
|
||||||
|
printf("Set Backlight parameters in the range of 0 to 100 \r\n");
|
||||||
|
else{
|
||||||
|
uint32_t Backlight = Light*10;
|
||||||
|
if(Backlight == 1000)
|
||||||
|
Backlight = 1024;
|
||||||
|
ledcWrite(LCD_Backlight_PIN, Backlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TCA9554PWR.h"
|
||||||
|
|
||||||
|
#define LCD_Backlight_PIN 5
|
||||||
|
#define PWM_Channel 1 // PWM Channel
|
||||||
|
#define Frequency 20000 // PWM frequencyconst
|
||||||
|
#define Resolution 10 // PWM resolution ratio MAX:13
|
||||||
|
#define Dutyfactor 500 // PWM Dutyfactor
|
||||||
|
#define Backlight_MAX 100
|
||||||
|
|
||||||
|
#define EXAMPLE_LCD_WIDTH (360)
|
||||||
|
#define EXAMPLE_LCD_HEIGHT (360)
|
||||||
|
#define EXAMPLE_LCD_COLOR_BITS (16)
|
||||||
|
|
||||||
|
#define ESP_PANEL_HOST_SPI_ID_DEFAULT (SPI2_HOST)
|
||||||
|
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||||
|
#define ESP_PANEL_LCD_SPI_CLK_HZ (80 * 1000 * 1000) // Should be an integer divisor of 80M, typically set to 40M
|
||||||
|
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||||
|
#define ESP_PANEL_LCD_SPI_CMD_BITS (32) // Typically set to 32
|
||||||
|
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||||
|
|
||||||
|
#define ESP_PANEL_LCD_SPI_IO_TE (18)
|
||||||
|
#define ESP_PANEL_LCD_SPI_IO_SCK (40)
|
||||||
|
#define ESP_PANEL_LCD_SPI_IO_DATA0 (46)
|
||||||
|
#define ESP_PANEL_LCD_SPI_IO_DATA1 (45)
|
||||||
|
#define ESP_PANEL_LCD_SPI_IO_DATA2 (42)
|
||||||
|
#define ESP_PANEL_LCD_SPI_IO_DATA3 (41)
|
||||||
|
#define ESP_PANEL_LCD_SPI_IO_CS (21)
|
||||||
|
#define EXAMPLE_LCD_PIN_NUM_RST (-1) // EXIO2
|
||||||
|
#define EXAMPLE_LCD_PIN_NUM_BK_LIGHT (-1)
|
||||||
|
|
||||||
|
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL (1)
|
||||||
|
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
|
||||||
|
|
||||||
|
#define ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE (2048)
|
||||||
|
|
||||||
|
extern uint8_t LCD_Backlight;
|
||||||
|
|
||||||
|
void ST77916_Init();
|
||||||
|
|
||||||
|
void LCD_Init();
|
||||||
|
void LCD_addWindow(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,uint16_t* color);
|
||||||
|
|
||||||
|
// backlight
|
||||||
|
void Backlight_Init();
|
||||||
|
void Set_Backlight(uint8_t Light);
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#include "I2C_Driver.h"
|
||||||
|
|
||||||
|
|
||||||
|
void I2C_Init(void) {
|
||||||
|
Wire.begin( I2C_SDA_PIN, I2C_SCL_PIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool I2C_Read(uint8_t Driver_addr, uint8_t Reg_addr, uint8_t *Reg_data, uint32_t Length)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(Driver_addr);
|
||||||
|
Wire.write(Reg_addr);
|
||||||
|
if ( Wire.endTransmission(true)){
|
||||||
|
printf("The I2C transmission fails. - I2C Read\r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Wire.requestFrom(Driver_addr, Length);
|
||||||
|
for (int i = 0; i < Length; i++) {
|
||||||
|
*Reg_data++ = Wire.read();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool I2C_Write(uint8_t Driver_addr, uint8_t Reg_addr, const uint8_t *Reg_data, uint32_t Length)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(Driver_addr);
|
||||||
|
Wire.write(Reg_addr);
|
||||||
|
for (int i = 0; i < Length; i++) {
|
||||||
|
Wire.write(*Reg_data++);
|
||||||
|
}
|
||||||
|
if ( Wire.endTransmission(true))
|
||||||
|
{
|
||||||
|
printf("The I2C transmission fails. - I2C Write\r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
#define I2C_SCL_PIN 10
|
||||||
|
#define I2C_SDA_PIN 11
|
||||||
|
|
||||||
|
void I2C_Init(void);
|
||||||
|
|
||||||
|
bool I2C_Read(uint8_t Driver_addr, uint8_t Reg_addr, uint8_t *Reg_data, uint32_t Length);
|
||||||
|
bool I2C_Write(uint8_t Driver_addr, uint8_t Reg_addr, const uint8_t *Reg_data, uint32_t Length);
|
||||||
@@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
| File : LVGL_Driver.c
|
||||||
|
|
||||||
|
| help :
|
||||||
|
The provided LVGL library file must be installed first
|
||||||
|
******************************************************************************/
|
||||||
|
#include "LVGL_Driver.h"
|
||||||
|
|
||||||
|
static lv_disp_draw_buf_t draw_buf;
|
||||||
|
static lv_color_t buf1[ LVGL_BUF_LEN ];
|
||||||
|
static lv_color_t buf2[ LVGL_BUF_LEN];
|
||||||
|
// static lv_color_t* buf1 = (lv_color_t*) heap_caps_malloc(LVGL_BUF_LEN , MALLOC_CAP_SPIRAM);
|
||||||
|
// static lv_color_t* buf2 = (lv_color_t*) heap_caps_malloc(LVGL_BUF_LEN , MALLOC_CAP_SPIRAM);
|
||||||
|
|
||||||
|
/* Display flushing
|
||||||
|
Displays LVGL content on the LCD
|
||||||
|
This function implements associating LVGL data to the LCD screen
|
||||||
|
*/
|
||||||
|
void Lvgl_Display_LCD( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p )
|
||||||
|
{
|
||||||
|
LCD_addWindow(area->x1, area->y1, area->x2, area->y2, ( uint16_t *)&color_p->full);
|
||||||
|
lv_disp_flush_ready( disp_drv );
|
||||||
|
}
|
||||||
|
/*Read the touchpad*/
|
||||||
|
//void Lvgl_Touchpad_Read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
|
||||||
|
//{
|
||||||
|
|
||||||
|
void example_increase_lvgl_tick(void *arg)
|
||||||
|
{
|
||||||
|
/* Tell LVGL how many milliseconds has elapsed */
|
||||||
|
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
void example_increase_lvgl_Loop_tick(void *arg)
|
||||||
|
{
|
||||||
|
lv_timer_handler(); /* let the GUI do its work */
|
||||||
|
}
|
||||||
|
void Lvgl_Init(void)
|
||||||
|
{
|
||||||
|
lv_init();
|
||||||
|
lv_disp_draw_buf_init( &draw_buf, buf1, buf2, LVGL_BUF_LEN);
|
||||||
|
|
||||||
|
/*Initialize the display*/
|
||||||
|
static lv_disp_drv_t disp_drv;
|
||||||
|
lv_disp_drv_init( &disp_drv );
|
||||||
|
/*Change the following line to your display resolution*/
|
||||||
|
disp_drv.hor_res = LCD_WIDTH;
|
||||||
|
disp_drv.ver_res = LCD_HEIGHT;
|
||||||
|
disp_drv.flush_cb = Lvgl_Display_LCD;
|
||||||
|
disp_drv.full_refresh = 1; /**< 1: Always make the whole screen redrawn*/
|
||||||
|
disp_drv.draw_buf = &draw_buf;
|
||||||
|
lv_disp_drv_register( &disp_drv );
|
||||||
|
|
||||||
|
/*Initialize the (dummy) input device driver*/
|
||||||
|
//static lv_indev_drv_t indev_drv;
|
||||||
|
//lv_indev_drv_init( &indev_drv );
|
||||||
|
//indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||||
|
//indev_drv.read_cb = Lvgl_Touchpad_Read;
|
||||||
|
//lv_indev_drv_register( &indev_drv );
|
||||||
|
|
||||||
|
/* Create simple label */
|
||||||
|
lv_obj_t *label = lv_label_create( lv_scr_act() );
|
||||||
|
lv_label_set_text( label, "Hello Ardino and LVGL!");
|
||||||
|
lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
|
||||||
|
|
||||||
|
const esp_timer_create_args_t lvgl_tick_timer_args = {
|
||||||
|
.callback = &example_increase_lvgl_tick,
|
||||||
|
.name = "lvgl_tick"
|
||||||
|
};
|
||||||
|
esp_timer_handle_t lvgl_tick_timer = NULL;
|
||||||
|
esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer);
|
||||||
|
esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
void Lvgl_Loop(void)
|
||||||
|
{
|
||||||
|
lv_timer_handler(); /* let the GUI do its work */
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "src/lvgl/lvgl.h"
|
||||||
|
#include "lv_conf.h"
|
||||||
|
//#include <demos/lv_demos.h>
|
||||||
|
#include <esp_heap_caps.h>
|
||||||
|
#include "Display_ST77916.h"
|
||||||
|
//#include "Simulated_Gesture.h"
|
||||||
|
|
||||||
|
#define LCD_WIDTH EXAMPLE_LCD_WIDTH
|
||||||
|
#define LCD_HEIGHT EXAMPLE_LCD_HEIGHT
|
||||||
|
#define LVGL_BUF_LEN (LCD_WIDTH * LCD_HEIGHT / 20)
|
||||||
|
|
||||||
|
#define EXAMPLE_LVGL_TICK_PERIOD_MS 10
|
||||||
|
|
||||||
|
|
||||||
|
void Lvgl_print(const char * buf);
|
||||||
|
void Lvgl_Display_LCD( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p ); // Displays LVGL content on the LCD. This function implements associating LVGL data to the LCD screen
|
||||||
|
//void Lvgl_Touchpad_Read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data ); // Read the touchpad
|
||||||
|
void example_increase_lvgl_tick(void *arg);
|
||||||
|
|
||||||
|
void Lvgl_Init(void);
|
||||||
|
void Lvgl_Loop(void);
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Turbo Gauge
|
||||||
|
This is a custom-built digital boost gauge for my car. It runs on the **Waveshare 1.85" LCD Dev Board** and talks to my car over Bluetooth using a **V-LINK OBD2 adapter**.
|
||||||
|
|
||||||
|
I built this because I wanted something that looked more modern and "futuristic" than a standard needle gauge, but still gave me the data I actually care about.
|
||||||
|
|
||||||
|
### What it shows
|
||||||
|
* **Boost/Vacuum**
|
||||||
|
* **Peak pressure**
|
||||||
|
* **Stats Hub**
|
||||||
|
|
||||||
|
|
||||||
|
### Hardware
|
||||||
|
* **Brain/Screen:** [Waveshare 1.85" LCD Dev Board](https://www.waveshare.com/esp32-s3-lcd-1.85.htm)
|
||||||
|
* **Link:** V-LINK OBDII Bluetooth adapter (MUST BE BLE VERSION).
|
||||||
|
|
||||||
|
### How it works
|
||||||
|
The code is split up so it doesn't lag. One core of the ESP32 handles the Bluetooth data from the car, and the other core handles the graphics. I’ve optimized the drawing so the needle moves at a high frame rate, while the background text only updates every 10 frames to save power and keep things snappy.
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
1. Plug the V-LINK into your car's OBDII port.
|
||||||
|
2. Flash this code to the Waveshare board using the Arduino IDE or PlatformIO.
|
||||||
|
3. Turn the car on.
|
||||||
|
4. The gauge will scan, find the adapter, and start sweeping.
|
||||||
|
|
||||||
|
**Note:** If your adapter has a different Bluetooth name (not "V-LINK" or "OBDII"), you'll need to tweak the `connect_to_vlink()` function in the code.
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
#include "TCA9554PWR.h"
|
||||||
|
|
||||||
|
/***************************************************** Operation register REG ****************************************************/
|
||||||
|
uint8_t Read_REG(uint8_t REG) // Read the value of the TCA9554PWR register REG
|
||||||
|
{
|
||||||
|
Wire1.beginTransmission(TCA9554_ADDRESS);
|
||||||
|
Wire1.write(REG);
|
||||||
|
uint8_t result = Wire1.endTransmission();
|
||||||
|
if (result != 0) {
|
||||||
|
printf("Data Transfer Failure !!!\r\n");
|
||||||
|
}
|
||||||
|
Wire1.requestFrom(TCA9554_ADDRESS, 1);
|
||||||
|
uint8_t bitsStatus = Wire1.read();
|
||||||
|
return bitsStatus;
|
||||||
|
}
|
||||||
|
uint8_t Write_REG(uint8_t REG,uint8_t Data) // Write Data to the REG register of the TCA9554PWR
|
||||||
|
{
|
||||||
|
Wire1.beginTransmission(TCA9554_ADDRESS);
|
||||||
|
Wire1.write(REG);
|
||||||
|
Wire1.write(Data);
|
||||||
|
uint8_t result = Wire1.endTransmission();
|
||||||
|
if (result != 0) {
|
||||||
|
printf("Data write failure!!!\r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/********************************************************** Set EXIO mode **********************************************************/
|
||||||
|
void Mode_EXIO(uint8_t Pin,uint8_t State) // Set the mode of the TCA9554PWR Pin. The default is Output mode (output mode or input mode). State: 0= Output mode 1= input mode
|
||||||
|
{
|
||||||
|
uint8_t bitsStatus = Read_REG(TCA9554_CONFIG_REG);
|
||||||
|
uint8_t Data = (0x01 << (Pin-1)) | bitsStatus;
|
||||||
|
uint8_t result = Write_REG(TCA9554_CONFIG_REG,Data);
|
||||||
|
if (result != 0) {
|
||||||
|
printf("I/O Configuration Failure !!!\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Mode_EXIOS(uint8_t PinState) // Set the mode of the 7 pins from the TCA9554PWR with PinState
|
||||||
|
{
|
||||||
|
uint8_t result = Write_REG(TCA9554_CONFIG_REG,PinState);
|
||||||
|
if (result != 0) {
|
||||||
|
printf("I/O Configuration Failure !!!\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/********************************************************** Read EXIO status **********************************************************/
|
||||||
|
uint8_t Read_EXIO(uint8_t Pin) // Read the level of the TCA9554PWR Pin
|
||||||
|
{
|
||||||
|
uint8_t inputBits = Read_REG(TCA9554_INPUT_REG);
|
||||||
|
uint8_t bitStatus = (inputBits >> (Pin-1)) & 0x01;
|
||||||
|
return bitStatus;
|
||||||
|
}
|
||||||
|
uint8_t Read_EXIOS(uint8_t REG = TCA9554_INPUT_REG) // Read the level of all pins of TCA9554PWR, the default read input level state, want to get the current IO output state, pass the parameter TCA9554_OUTPUT_REG, such as Read_EXIOS(TCA9554_OUTPUT_REG);
|
||||||
|
{
|
||||||
|
uint8_t inputBits = Read_REG(REG);
|
||||||
|
return inputBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************** Set the EXIO output status **********************************************************/
|
||||||
|
void Set_EXIO(uint8_t Pin,uint8_t State) // Sets the level state of the Pin without affecting the other pins
|
||||||
|
{
|
||||||
|
uint8_t Data;
|
||||||
|
if(State < 2 && Pin < 9 && Pin > 0){
|
||||||
|
uint8_t bitsStatus = Read_EXIOS(TCA9554_OUTPUT_REG);
|
||||||
|
if(State == 1)
|
||||||
|
Data = (0x01 << (Pin-1)) | bitsStatus;
|
||||||
|
else if(State == 0)
|
||||||
|
Data = (~(0x01 << (Pin-1))) & bitsStatus;
|
||||||
|
uint8_t result = Write_REG(TCA9554_OUTPUT_REG,Data);
|
||||||
|
if (result != 0) {
|
||||||
|
printf("Failed to set GPIO!!!\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("Parameter error, please enter the correct parameter!\r\n");
|
||||||
|
}
|
||||||
|
void Set_EXIOS(uint8_t PinState) // Set 7 pins to the PinState state such as :PinState=0x23, 0010 0011 state (the highest bit is not used)
|
||||||
|
{
|
||||||
|
uint8_t result = Write_REG(TCA9554_OUTPUT_REG,PinState);
|
||||||
|
if (result != 0) {
|
||||||
|
printf("Failed to set GPIO!!!\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/********************************************************** Flip EXIO state **********************************************************/
|
||||||
|
void Set_Toggle(uint8_t Pin) // Flip the level of the TCA9554PWR Pin
|
||||||
|
{
|
||||||
|
uint8_t bitsStatus = Read_EXIO(Pin);
|
||||||
|
Set_EXIO(Pin,(bool)!bitsStatus);
|
||||||
|
}
|
||||||
|
/********************************************************* TCA9554PWR Initializes the device ***********************************************************/
|
||||||
|
void TCA9554PWR_Init(uint8_t PinState) // Set the seven pins to PinState state, for example :PinState=0x23, 0010 0011 State (Output mode or input mode) 0= Output mode 1= Input mode. The default value is output mode
|
||||||
|
{
|
||||||
|
Mode_EXIOS(PinState);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "I2C_Driver.h"
|
||||||
|
|
||||||
|
/****************************************************** The macro defines the TCA9554PWR information ******************************************************/
|
||||||
|
|
||||||
|
#define TCA9554_ADDRESS 0x20 // TCA9554PWR I2C address
|
||||||
|
|
||||||
|
#define TCA9554_INPUT_REG 0x00 // Input register,input level
|
||||||
|
#define TCA9554_OUTPUT_REG 0x01 // Output register, high and low level output
|
||||||
|
#define TCA9554_Polarity_REG 0x02 // The Polarity Inversion register (register 2) allows polarity inversion of pins defined as inputs by the Configuration register.
|
||||||
|
#define TCA9554_CONFIG_REG 0x03 // Configuration register, mode configuration
|
||||||
|
|
||||||
|
|
||||||
|
#define Low 0
|
||||||
|
#define High 1
|
||||||
|
#define EXIO_PIN1 1
|
||||||
|
#define EXIO_PIN2 2
|
||||||
|
#define EXIO_PIN3 3
|
||||||
|
#define EXIO_PIN4 4
|
||||||
|
#define EXIO_PIN5 5
|
||||||
|
#define EXIO_PIN6 6
|
||||||
|
#define EXIO_PIN7 7
|
||||||
|
#define EXIO_PIN8 8
|
||||||
|
|
||||||
|
/***************************************************** Operation register REG ****************************************************/
|
||||||
|
uint8_t Read_REG(uint8_t REG); // Read the value of the TCA9554PWR register REG
|
||||||
|
uint8_t Write_REG(uint8_t REG,uint8_t Data); // Write Data to the REG register of the TCA9554PWR
|
||||||
|
/********************************************************** Set EXIO mode **********************************************************/
|
||||||
|
void Mode_EXIO(uint8_t Pin,uint8_t State); // Set the mode of the TCA9554PWR Pin. The default is Output mode (output mode or input mode). State: 0= Output mode 1= input mode
|
||||||
|
void Mode_EXIOS(uint8_t PinState); // Set the mode of the 7 pins from the TCA9554PWR with PinState
|
||||||
|
/********************************************************** Read EXIO status **********************************************************/
|
||||||
|
uint8_t Read_EXIO(uint8_t Pin); // Read the level of the TCA9554PWR Pin
|
||||||
|
uint8_t Read_EXIOS(uint8_t REG); // Read the level of all pins of TCA9554PWR, the default read input level state, want to get the current IO output state, pass the parameter TCA9554_OUTPUT_REG, such as Read_EXIOS(TCA9554_OUTPUT_REG);
|
||||||
|
/********************************************************** Set the EXIO output status **********************************************************/
|
||||||
|
void Set_EXIO(uint8_t Pin,uint8_t State); // Sets the level state of the Pin without affecting the other pins
|
||||||
|
void Set_EXIOS(uint8_t PinState); // Set 7 pins to the PinState state such as :PinState=0x23, 0010 0011 state (the highest bit is not used)
|
||||||
|
/********************************************************** Flip EXIO state **********************************************************/
|
||||||
|
void Set_Toggle(uint8_t Pin); // Flip the level of the TCA9554PWR Pin
|
||||||
|
/********************************************************* TCA9554PWR Initializes the device ***********************************************************/
|
||||||
|
void TCA9554PWR_Init(uint8_t PinState = 0x00); // Set the seven pins to PinState state, for example :PinState=0x23, 0010 0011 State (the highest bit is not used) (Output mode or input mode) 0= Output mode 1= Input mode. The default value is output mode
|
||||||
@@ -0,0 +1,328 @@
|
|||||||
|
#include "Display_ST77916.h"
|
||||||
|
#include "LVGL_Driver.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// BLE and OBD Libraries
|
||||||
|
#include <NimBLEDevice.h>
|
||||||
|
#include "ELMduino.h"
|
||||||
|
|
||||||
|
// ── Gauge Geometry ────────────────────────────────────────────────
|
||||||
|
#define CX 180
|
||||||
|
#define CY 180
|
||||||
|
#define SCREEN_W 360
|
||||||
|
#define SCREEN_H 360
|
||||||
|
|
||||||
|
#define ANGLE_START 120.0f
|
||||||
|
#define ANGLE_END 380.0f
|
||||||
|
#define GAUGE_MIN -1.0f
|
||||||
|
#define GAUGE_MAX 3.0f
|
||||||
|
|
||||||
|
#define R_OUTER_TICK 172
|
||||||
|
#define R_INNER_ORANGE 150
|
||||||
|
#define R_TICK_MAJOR 150
|
||||||
|
#define R_TICK_MINOR 160
|
||||||
|
#define R_LABELS 125
|
||||||
|
#define R_NEEDLE_TIP 160
|
||||||
|
#define R_HUB 22
|
||||||
|
|
||||||
|
// -- Engine Load Position (Top Middle) --
|
||||||
|
#define LOAD_W 100
|
||||||
|
#define LOAD_X (CX - (LOAD_W / 2))
|
||||||
|
#define LOAD_Y (CY - 70)
|
||||||
|
|
||||||
|
// ── State & OBD Variables ─────────────────────────────────────────
|
||||||
|
static float boost_target = 0.0f;
|
||||||
|
static float boost_current = -1.0f;
|
||||||
|
static float peak_boost = -1.0f;
|
||||||
|
static uint32_t peak_time = 0;
|
||||||
|
|
||||||
|
static float clt_temp = 0.0f;
|
||||||
|
static float iat_temp = 0.0f;
|
||||||
|
static float engine_load = 0.0f;
|
||||||
|
|
||||||
|
// Buffers for strings (moved out of draw calls for speed)
|
||||||
|
static char pbuf[16] = "0.00 bar";
|
||||||
|
static char clt_buf[24] = "COOLANT: 0 °C";
|
||||||
|
static char iat_buf[24] = "INTAKE: 0 °C";
|
||||||
|
|
||||||
|
// Animation State
|
||||||
|
static bool startup_anim = true;
|
||||||
|
static int anim_stage = 0;
|
||||||
|
static float anim_speed = 0.35f;
|
||||||
|
|
||||||
|
// BLE Status
|
||||||
|
static int ble_status = 1;
|
||||||
|
static lv_obj_t *face_obj;
|
||||||
|
static lv_obj_t *needle_obj;
|
||||||
|
|
||||||
|
// OBD Hardware Objects
|
||||||
|
NimBLEClient* pClient = nullptr;
|
||||||
|
ELM327 myELM327;
|
||||||
|
|
||||||
|
// ── Helpers ───────────────────────────────────────────────────────
|
||||||
|
static float bar_to_rad(float bar) {
|
||||||
|
float pct = (bar - GAUGE_MIN) / (GAUGE_MAX - GAUGE_MIN);
|
||||||
|
float deg = ANGLE_START + pct * (ANGLE_END - ANGLE_START);
|
||||||
|
return deg * (float)M_PI / 180.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_coord_t px(float r, float rad) { return (lv_coord_t)(CX + cosf(rad) * r); }
|
||||||
|
static lv_coord_t py(float r, float rad) { return (lv_coord_t)(CY + sinf(rad) * r); }
|
||||||
|
|
||||||
|
// ── Drawing Functions ─────────────────────────────────────────────
|
||||||
|
static void draw_gauge_face(lv_event_t *e) {
|
||||||
|
lv_draw_ctx_t *draw_ctx = lv_event_get_draw_ctx(e);
|
||||||
|
lv_point_t center = {CX, CY};
|
||||||
|
|
||||||
|
// 1. Inner Orange Arc
|
||||||
|
lv_draw_arc_dsc_t orange_arc;
|
||||||
|
lv_draw_arc_dsc_init(&orange_arc);
|
||||||
|
orange_arc.color = lv_color_make(0xFF, 0x44, 0x00);
|
||||||
|
orange_arc.width = 2;
|
||||||
|
lv_draw_arc(draw_ctx, &orange_arc, ¢er, R_INNER_ORANGE, (int)ANGLE_START, (int)ANGLE_END);
|
||||||
|
|
||||||
|
// 2. Ticks
|
||||||
|
for (int i = 0; i <= 40; i++) {
|
||||||
|
float val = GAUGE_MIN + (i * 0.1f);
|
||||||
|
float rad = bar_to_rad(val);
|
||||||
|
bool is_major = (fmod(val + 0.01f, 0.5f) < 0.05f);
|
||||||
|
lv_draw_line_dsc_t tick_dsc;
|
||||||
|
lv_draw_line_dsc_init(&tick_dsc);
|
||||||
|
tick_dsc.color = lv_color_white();
|
||||||
|
tick_dsc.width = is_major ? 3 : 1;
|
||||||
|
lv_point_t p_out = {px(R_OUTER_TICK, rad), py(R_OUTER_TICK, rad)};
|
||||||
|
lv_point_t p_in = {px(is_major ? R_TICK_MAJOR : R_TICK_MINOR, rad), py(is_major ? R_TICK_MAJOR : R_TICK_MINOR, rad)};
|
||||||
|
lv_draw_line(draw_ctx, &tick_dsc, &p_in, &p_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Scale Labels
|
||||||
|
lv_draw_label_dsc_t label_dsc;
|
||||||
|
lv_draw_label_dsc_init(&label_dsc);
|
||||||
|
label_dsc.color = lv_color_white();
|
||||||
|
label_dsc.font = &lv_font_montserrat_14;
|
||||||
|
float labels[] = {-1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0};
|
||||||
|
for (float l : labels) {
|
||||||
|
float rad = bar_to_rad(l);
|
||||||
|
char l_buf[8];
|
||||||
|
sprintf(l_buf, "%g", (l < 0 ? fabsf(l) : l));
|
||||||
|
int lx = px(R_LABELS, rad) - 15;
|
||||||
|
int ly = py(R_LABELS, rad) - 10;
|
||||||
|
lv_area_t area = {lx, ly, lx + 40, ly + 20};
|
||||||
|
lv_draw_label(draw_ctx, &label_dsc, &area, l_buf, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. ENGINE LOAD SECTION
|
||||||
|
lv_draw_rect_dsc_t load_bg_dsc;
|
||||||
|
lv_draw_rect_dsc_init(&load_bg_dsc);
|
||||||
|
load_bg_dsc.bg_color = lv_color_make(0x1A, 0x1A, 0x1A);
|
||||||
|
load_bg_dsc.radius = 2;
|
||||||
|
lv_area_t load_bg_area = {LOAD_X, LOAD_Y, LOAD_X + LOAD_W, LOAD_Y + 5};
|
||||||
|
lv_draw_rect(draw_ctx, &load_bg_dsc, &load_bg_area);
|
||||||
|
|
||||||
|
lv_draw_rect_dsc_t load_fill_dsc;
|
||||||
|
lv_draw_rect_dsc_init(&load_fill_dsc);
|
||||||
|
load_fill_dsc.bg_color = lv_color_make(0x00, 0xFF, 0x00);
|
||||||
|
int fill_w = (int)((engine_load / 100.0f) * LOAD_W);
|
||||||
|
if(fill_w > LOAD_W) fill_w = LOAD_W;
|
||||||
|
lv_area_t load_fill_area = {LOAD_X, LOAD_Y, LOAD_X + fill_w, LOAD_Y + 5};
|
||||||
|
lv_draw_rect(draw_ctx, &load_fill_dsc, &load_fill_area);
|
||||||
|
|
||||||
|
lv_draw_label_dsc_t load_lbl_dsc;
|
||||||
|
lv_draw_label_dsc_init(&load_lbl_dsc);
|
||||||
|
load_lbl_dsc.color = lv_color_make(150, 150, 150);
|
||||||
|
load_lbl_dsc.font = &lv_font_montserrat_10;
|
||||||
|
lv_area_t load_txt_area = {LOAD_X, LOAD_Y + 8, LOAD_X + LOAD_W, LOAD_Y + 20};
|
||||||
|
lv_draw_label(draw_ctx, &load_lbl_dsc, &load_txt_area, "ENGINE LOAD", NULL);
|
||||||
|
|
||||||
|
// 5. FUTURISTIC DATA HUB
|
||||||
|
lv_draw_rect_dsc_t box_dsc;
|
||||||
|
lv_draw_rect_dsc_init(&box_dsc);
|
||||||
|
box_dsc.bg_color = lv_color_make(0x1A, 0x1A, 0x1A);
|
||||||
|
box_dsc.bg_opa = 200;
|
||||||
|
box_dsc.radius = 4;
|
||||||
|
lv_area_t data_box = {CX - 35, CY + 55, CX + 115, CY + 145};
|
||||||
|
lv_draw_rect(draw_ctx, &box_dsc, &data_box);
|
||||||
|
|
||||||
|
lv_draw_rect_dsc_t accent_dsc;
|
||||||
|
lv_draw_rect_dsc_init(&accent_dsc);
|
||||||
|
accent_dsc.bg_color = lv_color_make(0xFF, 0x44, 0x00);
|
||||||
|
accent_dsc.bg_opa = (ble_status != 2 && !startup_anim) ? (150 + 100 * sin(millis() / 200.0)) : 255;
|
||||||
|
lv_area_t accent_bar = {CX - 33, CY + 60, CX - 30, CY + 140};
|
||||||
|
lv_draw_rect(draw_ctx, &accent_dsc, &accent_bar);
|
||||||
|
|
||||||
|
label_dsc.color = lv_color_make(180, 180, 180);
|
||||||
|
label_dsc.font = &lv_font_montserrat_12;
|
||||||
|
lv_area_t pk_label_area = {CX - 20, CY + 62, CX + 100, CY + 75};
|
||||||
|
lv_draw_label(draw_ctx, &label_dsc, &pk_label_area, "PEAK BOOST", NULL);
|
||||||
|
|
||||||
|
label_dsc.color = lv_color_make(0xFF, 0xAA, 0x00);
|
||||||
|
label_dsc.font = &lv_font_montserrat_22;
|
||||||
|
lv_area_t peak_val_area = {CX - 20, CY + 76, CX + 110, CY + 102};
|
||||||
|
lv_draw_label(draw_ctx, &label_dsc, &peak_val_area, pbuf, NULL);
|
||||||
|
|
||||||
|
lv_draw_line_dsc_t line_dsc;
|
||||||
|
lv_draw_line_dsc_init(&line_dsc);
|
||||||
|
line_dsc.color = lv_color_make(0x33, 0x33, 0x33);
|
||||||
|
line_dsc.width = 1;
|
||||||
|
lv_point_t lp1 = {CX - 20, CY + 105}, lp2 = {CX + 100, CY + 105};
|
||||||
|
lv_draw_line(draw_ctx, &line_dsc, &lp1, &lp2);
|
||||||
|
|
||||||
|
label_dsc.font = &lv_font_montserrat_14;
|
||||||
|
label_dsc.color = lv_color_make(220, 220, 220);
|
||||||
|
lv_area_t clt_area = {CX - 20, CY + 110, CX + 110, CY + 125};
|
||||||
|
lv_draw_label(draw_ctx, &label_dsc, &clt_area, clt_buf, NULL);
|
||||||
|
lv_area_t iat_area = {CX - 20, CY + 127, CX + 110, CY + 142};
|
||||||
|
lv_draw_label(draw_ctx, &label_dsc, &iat_area, iat_buf, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_needle(lv_event_t *e) {
|
||||||
|
lv_draw_ctx_t *draw_ctx = lv_event_get_draw_ctx(e);
|
||||||
|
float rad = bar_to_rad(boost_current);
|
||||||
|
lv_draw_line_dsc_t needle_dsc;
|
||||||
|
lv_draw_line_dsc_init(&needle_dsc);
|
||||||
|
needle_dsc.color = lv_color_make(0xFF, 0x22, 0x00);
|
||||||
|
needle_dsc.width = 5;
|
||||||
|
needle_dsc.round_end = 1;
|
||||||
|
lv_point_t p0 = {px(R_HUB - 5, rad), py(R_HUB - 5, rad)};
|
||||||
|
lv_point_t p1 = {px(R_NEEDLE_TIP, rad), py(R_NEEDLE_TIP, rad)};
|
||||||
|
lv_draw_line(draw_ctx, &needle_dsc, &p0, &p1);
|
||||||
|
|
||||||
|
lv_draw_rect_dsc_t hub_dsc;
|
||||||
|
lv_draw_rect_dsc_init(&hub_dsc);
|
||||||
|
hub_dsc.bg_color = lv_color_make(0x11, 0x11, 0x11);
|
||||||
|
hub_dsc.radius = LV_RADIUS_CIRCLE;
|
||||||
|
hub_dsc.border_width = 2;
|
||||||
|
hub_dsc.border_color = lv_color_make(0x66, 0x66, 0x66);
|
||||||
|
lv_area_t hub_area = {CX - R_HUB, CY - R_HUB, CX + R_HUB, CY + R_HUB};
|
||||||
|
lv_draw_rect(draw_ctx, &hub_dsc, &hub_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect_to_vlink() {
|
||||||
|
NimBLEScan* pScan = NimBLEDevice::getScan();
|
||||||
|
pScan->setActiveScan(true);
|
||||||
|
pScan->start(1, false);
|
||||||
|
auto results = pScan->getResults();
|
||||||
|
for (auto it = results.begin(); it != results.end(); ++it) {
|
||||||
|
NimBLEAdvertisedDevice* device = *it;
|
||||||
|
if (device->getName().find("V-LINK") != std::string::npos || device->getName().find("OBDII") != std::string::npos) {
|
||||||
|
pClient = NimBLEDevice::createClient();
|
||||||
|
if (pClient->connect(device)) {
|
||||||
|
if (myELM327.begin(Serial1, false, 2000)) {
|
||||||
|
ble_status = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gauge_create(void) {
|
||||||
|
lv_obj_t *scr = lv_scr_act();
|
||||||
|
lv_obj_clean(scr);
|
||||||
|
lv_obj_set_style_bg_color(scr, lv_color_black(), 0);
|
||||||
|
|
||||||
|
// Background Layer (Labels, Ticks)
|
||||||
|
face_obj = lv_obj_create(scr);
|
||||||
|
lv_obj_set_size(face_obj, SCREEN_W, SCREEN_H);
|
||||||
|
lv_obj_set_style_bg_opa(face_obj, 0, 0);
|
||||||
|
lv_obj_set_style_border_width(face_obj, 0, 0);
|
||||||
|
lv_obj_add_event_cb(face_obj, draw_gauge_face, LV_EVENT_DRAW_MAIN, NULL);
|
||||||
|
|
||||||
|
// Foreground Layer (Needle)
|
||||||
|
needle_obj = lv_obj_create(scr);
|
||||||
|
lv_obj_set_size(needle_obj, SCREEN_W, SCREEN_H);
|
||||||
|
lv_obj_set_style_bg_opa(needle_obj, 0, 0);
|
||||||
|
lv_obj_set_style_border_width(needle_obj, 0, 0);
|
||||||
|
lv_obj_add_event_cb(needle_obj, draw_needle, LV_EVENT_DRAW_MAIN, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DriverTask(void *parameter) {
|
||||||
|
while (1) {
|
||||||
|
if (!startup_anim) {
|
||||||
|
if (ble_status != 2) {
|
||||||
|
connect_to_vlink();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
} else {
|
||||||
|
float t_clt = myELM327.engineCoolantTemp();
|
||||||
|
if (myELM327.nb_rx_state == ELM_SUCCESS) clt_temp = t_clt;
|
||||||
|
float t_iat = myELM327.intakeAirTemp();
|
||||||
|
if (myELM327.nb_rx_state == ELM_SUCCESS) iat_temp = t_iat;
|
||||||
|
float t_load = myELM327.engineLoad();
|
||||||
|
if (myELM327.nb_rx_state == ELM_SUCCESS) engine_load = t_load;
|
||||||
|
|
||||||
|
float map_kpa = myELM327.manifoldPressure();
|
||||||
|
if (myELM327.nb_rx_state == ELM_SUCCESS) {
|
||||||
|
boost_target = (map_kpa / 100.0f) - 1.01f;
|
||||||
|
}
|
||||||
|
if (boost_target > peak_boost) {
|
||||||
|
peak_boost = boost_target;
|
||||||
|
peak_time = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update text buffers outside of drawing thread
|
||||||
|
sprintf(pbuf, "%.2f bar", peak_boost < 0 ? 0.00 : peak_boost);
|
||||||
|
sprintf(clt_buf, "COOLANT: %.0f °C", clt_temp);
|
||||||
|
sprintf(iat_buf, "INTAKE: %.0f °C", iat_temp);
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(50));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial1.begin(38400);
|
||||||
|
TCA9554PWR_Init(0x00);
|
||||||
|
Backlight_Init(); LCD_Init(); Lvgl_Init();
|
||||||
|
NimBLEDevice::init("ESP32_Gauge");
|
||||||
|
gauge_create();
|
||||||
|
xTaskCreatePinnedToCore(DriverTask, "DriverTask", 8192, NULL, 2, NULL, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
static uint32_t last_face_update = 0;
|
||||||
|
|
||||||
|
if (startup_anim) {
|
||||||
|
if (anim_stage == 0) {
|
||||||
|
boost_current += anim_speed;
|
||||||
|
if (boost_current >= GAUGE_MAX) {
|
||||||
|
boost_current = GAUGE_MAX;
|
||||||
|
anim_stage = 1;
|
||||||
|
}
|
||||||
|
} else if (anim_stage == 1) {
|
||||||
|
float diff = boost_current - 0.0f;
|
||||||
|
float step = diff * 0.07f;
|
||||||
|
if (step < 0.01f) step = 0.01f;
|
||||||
|
boost_current -= step;
|
||||||
|
if (boost_current <= 0.01f) {
|
||||||
|
boost_current = 0.0f;
|
||||||
|
boost_target = 0.0f;
|
||||||
|
startup_anim = false;
|
||||||
|
anim_stage = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
} else {
|
||||||
|
boost_current += (boost_target - boost_current) * 0.15f;
|
||||||
|
if (millis() - peak_time > 10000) {
|
||||||
|
peak_boost = boost_current;
|
||||||
|
peak_time = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRITICAL OPTIMIZATION:
|
||||||
|
// Always update the needle (fast)
|
||||||
|
lv_obj_invalidate(needle_obj);
|
||||||
|
|
||||||
|
// Update the face (labels/load) only every 100ms (10Hz) to save FPS
|
||||||
|
if (millis() - last_face_update > 100) {
|
||||||
|
lv_obj_invalidate(face_obj);
|
||||||
|
last_face_update = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
Lvgl_Loop();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(16)); // Target ~60 FPS
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "esp_lcd_panel_vendor.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief LCD panel initialization commands.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int cmd; /*<! The specific LCD command */
|
||||||
|
const void *data; /*<! Buffer that holds the command specific data */
|
||||||
|
size_t data_bytes; /*<! Size of `data` in memory, in bytes */
|
||||||
|
unsigned int delay_ms; /*<! Delay in milliseconds after this command */
|
||||||
|
} st77916_lcd_init_cmd_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief LCD panel vendor configuration.
|
||||||
|
*
|
||||||
|
* @note This structure can be used to select interface type and override default initialization commands.
|
||||||
|
* @note This structure needs to be passed to the `vendor_config` field in `esp_lcd_panel_dev_config_t`.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
const st77916_lcd_init_cmd_t *init_cmds; /*!< Pointer to initialization commands array.
|
||||||
|
* The array should be declared as `static const` and positioned outside the function.
|
||||||
|
* Please refer to `vendor_specific_init_default` in source file
|
||||||
|
*/
|
||||||
|
uint16_t init_cmds_size; /*<! Number of commands in above array */
|
||||||
|
struct {
|
||||||
|
unsigned int use_qspi_interface: 1; /*<! Set to 1 if use QSPI interface, default is SPI interface */
|
||||||
|
} flags;
|
||||||
|
} st77916_vendor_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create LCD panel for model ST77916
|
||||||
|
*
|
||||||
|
* @param[in] io LCD panel IO handle
|
||||||
|
* @param[in] panel_dev_config General panel device configuration (Use `vendor_config` to select QSPI interface or override default initialization commands)
|
||||||
|
* @param[out] ret_panel Returned LCD panel handle
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Success
|
||||||
|
* - Otherwise: Fail
|
||||||
|
*/
|
||||||
|
esp_err_t esp_lcd_new_panel_st77916(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief LCD panel bus configuration structure
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ST77916_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||||
|
{ \
|
||||||
|
.sclk_io_num = sclk, \
|
||||||
|
.mosi_io_num = mosi, \
|
||||||
|
.miso_io_num = -1, \
|
||||||
|
.quadhd_io_num = -1, \
|
||||||
|
.quadwp_io_num = -1, \
|
||||||
|
.max_transfer_sz = max_trans_sz, \
|
||||||
|
}
|
||||||
|
#define ST77916_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz)\
|
||||||
|
{ \
|
||||||
|
.sclk_io_num = sclk, \
|
||||||
|
.data0_io_num = d0, \
|
||||||
|
.data1_io_num = d1, \
|
||||||
|
.data2_io_num = d2, \
|
||||||
|
.data3_io_num = d3, \
|
||||||
|
.max_transfer_sz = max_trans_sz, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief LCD panel IO configuration structure
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ST77916_PANEL_IO_SPI_CONFIG(cs, dc, cb, cb_ctx) \
|
||||||
|
{ \
|
||||||
|
.cs_gpio_num = cs, \
|
||||||
|
.dc_gpio_num = dc, \
|
||||||
|
.spi_mode = 0, \
|
||||||
|
.pclk_hz = 40 * 1000 * 1000, \
|
||||||
|
.trans_queue_depth = 10, \
|
||||||
|
.on_color_trans_done = cb, \
|
||||||
|
.user_ctx = cb_ctx, \
|
||||||
|
.lcd_cmd_bits = 8, \
|
||||||
|
.lcd_param_bits = 8, \
|
||||||
|
}
|
||||||
|
#define ST77916_PANEL_IO_QSPI_CONFIG(cs, cb, cb_ctx) \
|
||||||
|
{ \
|
||||||
|
.cs_gpio_num = cs, \
|
||||||
|
.dc_gpio_num = -1, \
|
||||||
|
.spi_mode = 0, \
|
||||||
|
.pclk_hz = 40 * 1000 * 1000, \
|
||||||
|
.trans_queue_depth = 10, \
|
||||||
|
.on_color_trans_done = cb, \
|
||||||
|
.user_ctx = cb_ctx, \
|
||||||
|
.lcd_cmd_bits = 32, \
|
||||||
|
.lcd_param_bits = 8, \
|
||||||
|
.flags = { \
|
||||||
|
.quad_mode = true, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,761 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_conf.h
|
||||||
|
* Configuration file for v8.2.0 and v8.3.2
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy this file as `lv_conf.h`
|
||||||
|
* 1. simply next to the `lvgl` folder
|
||||||
|
* 2. or any other places and
|
||||||
|
* - define `LV_CONF_INCLUDE_SIMPLE`
|
||||||
|
* - add the path as include path
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
#if 1 /*Set it to "1" to enable content*/
|
||||||
|
|
||||||
|
#ifndef LV_CONF_H
|
||||||
|
#define LV_CONF_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*Helper*/
|
||||||
|
#define __LVGL_V8_3 (8 == 8 && 3 == 3)
|
||||||
|
|
||||||
|
/*====================
|
||||||
|
COLOR SETTINGS
|
||||||
|
*====================*/
|
||||||
|
/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
|
||||||
|
#define LV_COLOR_DEPTH 16
|
||||||
|
|
||||||
|
/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/
|
||||||
|
#define LV_COLOR_16_SWAP 0
|
||||||
|
|
||||||
|
/*Enable features to draw on transparent background.
|
||||||
|
*It's required if opa, and transform_* style properties are used.
|
||||||
|
*Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/
|
||||||
|
#define LV_COLOR_SCREEN_TRANSP (__LVGL_V8_3 ? 1 : 0)
|
||||||
|
|
||||||
|
/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently.
|
||||||
|
* 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */
|
||||||
|
#define LV_COLOR_MIX_ROUND_OFS 0
|
||||||
|
|
||||||
|
/*Images pixels with this color will not be drawn if they are chroma keyed)*/
|
||||||
|
#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/
|
||||||
|
|
||||||
|
/*=========================
|
||||||
|
MEMORY SETTINGS
|
||||||
|
*=========================*/
|
||||||
|
|
||||||
|
/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
|
||||||
|
#define LV_MEM_CUSTOM 0
|
||||||
|
#if LV_MEM_CUSTOM == 0
|
||||||
|
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
|
||||||
|
#define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/
|
||||||
|
|
||||||
|
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
|
||||||
|
#define LV_MEM_ADR 0 /*0: unused*/
|
||||||
|
/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/
|
||||||
|
#if LV_MEM_ADR == 0
|
||||||
|
#undef LV_MEM_POOL_INCLUDE
|
||||||
|
#undef LV_MEM_POOL_ALLOC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /*LV_MEM_CUSTOM*/
|
||||||
|
#define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/
|
||||||
|
#define LV_MEM_CUSTOM_ALLOC malloc
|
||||||
|
#define LV_MEM_CUSTOM_FREE free
|
||||||
|
#define LV_MEM_CUSTOM_REALLOC realloc
|
||||||
|
#endif /*LV_MEM_CUSTOM*/
|
||||||
|
|
||||||
|
/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms.
|
||||||
|
*You will see an error log message if there wasn't enough buffers. */
|
||||||
|
#define LV_MEM_BUF_MAX_NUM 16
|
||||||
|
|
||||||
|
/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/
|
||||||
|
#define LV_MEMCPY_MEMSET_STD 0
|
||||||
|
|
||||||
|
/*====================
|
||||||
|
HAL SETTINGS
|
||||||
|
*====================*/
|
||||||
|
|
||||||
|
/*Default display refresh period. LVG will redraw changed areas with this period time*/
|
||||||
|
#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/
|
||||||
|
|
||||||
|
/*Input device read period in milliseconds*/
|
||||||
|
#define LV_INDEV_DEF_READ_PERIOD 30 //10 //30 /*[ms]*/ //Can't be less than display refresh-period otherwise Roller will lag behind finger-movement
|
||||||
|
|
||||||
|
/*Use a custom tick source that tells the elapsed time in milliseconds.
|
||||||
|
*It removes the need to manually update the tick with `lv_tick_inc()`)*/
|
||||||
|
#define LV_TICK_CUSTOM 1
|
||||||
|
#if LV_TICK_CUSTOM
|
||||||
|
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
|
||||||
|
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
|
||||||
|
#endif /*LV_TICK_CUSTOM*/
|
||||||
|
|
||||||
|
/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.
|
||||||
|
*(Not so important, you can adjust it to modify default sizes and spaces)*/
|
||||||
|
#define LV_DPI_DEF 130 /*[px/inch]*/
|
||||||
|
|
||||||
|
/*=======================
|
||||||
|
* FEATURE CONFIGURATION
|
||||||
|
*=======================*/
|
||||||
|
|
||||||
|
/*-------------
|
||||||
|
* Drawing
|
||||||
|
*-----------*/
|
||||||
|
|
||||||
|
/*Enable complex draw engine.
|
||||||
|
*Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/
|
||||||
|
#define LV_DRAW_COMPLEX 1
|
||||||
|
#if LV_DRAW_COMPLEX != 0
|
||||||
|
|
||||||
|
/*Allow buffering some shadow calculation.
|
||||||
|
*LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
|
||||||
|
*Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/
|
||||||
|
#define LV_SHADOW_CACHE_SIZE 0
|
||||||
|
|
||||||
|
/* Set number of maximally cached circle data.
|
||||||
|
* The circumference of 1/4 circle are saved for anti-aliasing
|
||||||
|
* radius * 4 bytes are used per circle (the most often used radiuses are saved)
|
||||||
|
* 0: to disable caching */
|
||||||
|
#define LV_CIRCLE_CACHE_SIZE 4
|
||||||
|
#endif /*LV_DRAW_COMPLEX*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer
|
||||||
|
* and blend it as an image with the given opacity.
|
||||||
|
* Note that `bg_opa`, `text_opa` etc don't require buffering into layer)
|
||||||
|
* The widget can be buffered in smaller chunks to avoid using large buffers.
|
||||||
|
*
|
||||||
|
* - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it
|
||||||
|
* - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated.
|
||||||
|
*
|
||||||
|
* Both buffer sizes are in bytes.
|
||||||
|
* "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers
|
||||||
|
* and can't be drawn in chunks. So these settings affects only widgets with opacity.
|
||||||
|
*/
|
||||||
|
#define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024)
|
||||||
|
#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024)
|
||||||
|
|
||||||
|
/*Default image cache size. Image caching keeps the images opened.
|
||||||
|
*If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added)
|
||||||
|
*With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
|
||||||
|
*However the opened images might consume additional RAM.
|
||||||
|
*0: to disable caching*/
|
||||||
|
#define LV_IMG_CACHE_DEF_SIZE 0
|
||||||
|
|
||||||
|
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||||
|
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||||
|
#define LV_GRADIENT_MAX_STOPS 2
|
||||||
|
|
||||||
|
/*Default gradient buffer size.
|
||||||
|
*When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again.
|
||||||
|
*LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes.
|
||||||
|
*If the cache is too small the map will be allocated only while it's required for the drawing.
|
||||||
|
*0 mean no caching.*/
|
||||||
|
#define LV_GRAD_CACHE_DEF_SIZE 0
|
||||||
|
|
||||||
|
/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display)
|
||||||
|
*LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface
|
||||||
|
*The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */
|
||||||
|
#define LV_DITHER_GRADIENT 0
|
||||||
|
#if LV_DITHER_GRADIENT
|
||||||
|
/*Add support for error diffusion dithering.
|
||||||
|
*Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing.
|
||||||
|
*The increase in memory consumption is (24 bits * object's width)*/
|
||||||
|
#define LV_DITHER_ERROR_DIFFUSION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Maximum buffer size to allocate for rotation.
|
||||||
|
*Only used if software rotation is enabled in the display driver.*/
|
||||||
|
#define LV_DISP_ROT_MAX_BUF (10*1024)
|
||||||
|
|
||||||
|
/*-------------
|
||||||
|
* GPU
|
||||||
|
*-----------*/
|
||||||
|
|
||||||
|
/*Use Arm's 2D acceleration library Arm-2D */
|
||||||
|
#define LV_USE_GPU_ARM2D 0
|
||||||
|
|
||||||
|
/*Use STM32's DMA2D (aka Chrom Art) GPU*/
|
||||||
|
#define LV_USE_GPU_STM32_DMA2D 0
|
||||||
|
#if LV_USE_GPU_STM32_DMA2D
|
||||||
|
/*Must be defined to include path of CMSIS header of target processor
|
||||||
|
e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
|
||||||
|
#define LV_GPU_DMA2D_CMSIS_INCLUDE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Use SWM341's DMA2D GPU*/
|
||||||
|
#define LV_USE_GPU_SWM341_DMA2D 0
|
||||||
|
#if LV_USE_GPU_SWM341_DMA2D
|
||||||
|
#define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Use NXP's PXP GPU iMX RTxxx platforms*/
|
||||||
|
#define LV_USE_GPU_NXP_PXP 0
|
||||||
|
#if LV_USE_GPU_NXP_PXP
|
||||||
|
/*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c)
|
||||||
|
* and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS
|
||||||
|
* has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected.
|
||||||
|
*0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init()
|
||||||
|
*/
|
||||||
|
#define LV_USE_GPU_NXP_PXP_AUTO_INIT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/
|
||||||
|
#define LV_USE_GPU_NXP_VG_LITE 0
|
||||||
|
|
||||||
|
/*Use SDL renderer API*/
|
||||||
|
#define LV_USE_GPU_SDL 0
|
||||||
|
#if LV_USE_GPU_SDL
|
||||||
|
#define LV_GPU_SDL_INCLUDE_PATH <SDL2/SDL.h>
|
||||||
|
/*Texture cache size, 8MB by default*/
|
||||||
|
#define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8)
|
||||||
|
/*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/
|
||||||
|
#define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------
|
||||||
|
* Logging
|
||||||
|
*-----------*/
|
||||||
|
|
||||||
|
/*Enable the log module*/
|
||||||
|
#define LV_USE_LOG 0
|
||||||
|
#if LV_USE_LOG
|
||||||
|
|
||||||
|
/*How important log should be added:
|
||||||
|
*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 logs added by the user
|
||||||
|
*LV_LOG_LEVEL_NONE Do not log anything*/
|
||||||
|
#define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||||
|
|
||||||
|
/*1: Print the log with 'printf';
|
||||||
|
*0: User need to register a callback with `lv_log_register_print_cb()`*/
|
||||||
|
#define LV_LOG_PRINTF 0
|
||||||
|
|
||||||
|
/*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
|
||||||
|
#define LV_LOG_TRACE_MEM 1
|
||||||
|
#define LV_LOG_TRACE_TIMER 1
|
||||||
|
#define LV_LOG_TRACE_INDEV 1
|
||||||
|
#define LV_LOG_TRACE_DISP_REFR 1
|
||||||
|
#define LV_LOG_TRACE_EVENT 1
|
||||||
|
#define LV_LOG_TRACE_OBJ_CREATE 1
|
||||||
|
#define LV_LOG_TRACE_LAYOUT 1
|
||||||
|
#define LV_LOG_TRACE_ANIM 1
|
||||||
|
|
||||||
|
#endif /*LV_USE_LOG*/
|
||||||
|
|
||||||
|
/*-------------
|
||||||
|
* Asserts
|
||||||
|
*-----------*/
|
||||||
|
|
||||||
|
/*Enable asserts if an operation is failed or an invalid data is found.
|
||||||
|
*If LV_USE_LOG is enabled an error message will be printed on failure*/
|
||||||
|
#define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/
|
||||||
|
#define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/
|
||||||
|
#define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/
|
||||||
|
#define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/
|
||||||
|
#define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/
|
||||||
|
|
||||||
|
/*Add a custom handler when assert happens e.g. to restart the MCU*/
|
||||||
|
#define LV_ASSERT_HANDLER_INCLUDE <stdint.h>
|
||||||
|
#define LV_ASSERT_HANDLER while(1); /*Halt by default*/
|
||||||
|
|
||||||
|
/*-------------
|
||||||
|
* Others
|
||||||
|
*-----------*/
|
||||||
|
|
||||||
|
/*1: Show CPU usage and FPS count*/
|
||||||
|
#define LV_USE_PERF_MONITOR 0
|
||||||
|
#if LV_USE_PERF_MONITOR
|
||||||
|
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*1: Show the used memory and the memory fragmentation
|
||||||
|
* Requires LV_MEM_CUSTOM = 0*/
|
||||||
|
#define LV_USE_MEM_MONITOR 0
|
||||||
|
#if LV_USE_MEM_MONITOR
|
||||||
|
#define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*1: Draw random colored rectangles over the redrawn areas*/
|
||||||
|
#define LV_USE_REFR_DEBUG 0
|
||||||
|
|
||||||
|
/*Change the built in (v)snprintf functions*/
|
||||||
|
#define LV_SPRINTF_CUSTOM 0
|
||||||
|
#if LV_SPRINTF_CUSTOM
|
||||||
|
#define LV_SPRINTF_INCLUDE <stdio.h>
|
||||||
|
#define lv_snprintf snprintf
|
||||||
|
#define lv_vsnprintf vsnprintf
|
||||||
|
#else /*LV_SPRINTF_CUSTOM*/
|
||||||
|
#define LV_SPRINTF_USE_FLOAT 0
|
||||||
|
#endif /*LV_SPRINTF_CUSTOM*/
|
||||||
|
|
||||||
|
#define LV_USE_USER_DATA 1
|
||||||
|
|
||||||
|
/*Garbage Collector settings
|
||||||
|
*Used if lvgl is bound to higher level language and the memory is managed by that language*/
|
||||||
|
#define LV_ENABLE_GC 0
|
||||||
|
#if LV_ENABLE_GC != 0
|
||||||
|
#define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
|
||||||
|
#endif /*LV_ENABLE_GC*/
|
||||||
|
|
||||||
|
/*=====================
|
||||||
|
* COMPILER SETTINGS
|
||||||
|
*====================*/
|
||||||
|
|
||||||
|
/*For big endian systems set to 1*/
|
||||||
|
#define LV_BIG_ENDIAN_SYSTEM 0
|
||||||
|
|
||||||
|
/*Define a custom attribute to `lv_tick_inc` function*/
|
||||||
|
#define LV_ATTRIBUTE_TICK_INC
|
||||||
|
|
||||||
|
/*Define a custom attribute to `lv_timer_handler` function*/
|
||||||
|
#define LV_ATTRIBUTE_TIMER_HANDLER
|
||||||
|
|
||||||
|
/*Define a custom attribute to `lv_disp_flush_ready` function*/
|
||||||
|
#define LV_ATTRIBUTE_FLUSH_READY
|
||||||
|
|
||||||
|
/*Required alignment size for buffers*/
|
||||||
|
#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1
|
||||||
|
|
||||||
|
/*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default).
|
||||||
|
* E.g. __attribute__((aligned(4)))*/
|
||||||
|
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||||
|
|
||||||
|
/*Attribute to mark large constant arrays for example font's bitmaps*/
|
||||||
|
#define LV_ATTRIBUTE_LARGE_CONST
|
||||||
|
|
||||||
|
/*Compiler prefix for a big array declaration in RAM*/
|
||||||
|
#define LV_ATTRIBUTE_LARGE_RAM_ARRAY
|
||||||
|
|
||||||
|
/*Place performance critical functions into a faster memory (e.g RAM)*/
|
||||||
|
#define LV_ATTRIBUTE_FAST_MEM
|
||||||
|
|
||||||
|
/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/
|
||||||
|
#define LV_ATTRIBUTE_DMA
|
||||||
|
|
||||||
|
/*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that
|
||||||
|
*should also appear on LVGL binding API such as Micropython.*/
|
||||||
|
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/
|
||||||
|
|
||||||
|
/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/
|
||||||
|
#define LV_USE_LARGE_COORD 0
|
||||||
|
|
||||||
|
/*==================
|
||||||
|
* FONT USAGE
|
||||||
|
*===================*/
|
||||||
|
|
||||||
|
/*Montserrat fonts with ASCII range and some symbols using bpp = 4
|
||||||
|
*https://fonts.google.com/specimen/Montserrat*/
|
||||||
|
#define LV_FONT_MONTSERRAT_8 0
|
||||||
|
#define LV_FONT_MONTSERRAT_10 1
|
||||||
|
#define LV_FONT_MONTSERRAT_12 0
|
||||||
|
#define LV_FONT_MONTSERRAT_14 1
|
||||||
|
#define LV_FONT_MONTSERRAT_16 1
|
||||||
|
#define LV_FONT_MONTSERRAT_18 1
|
||||||
|
#define LV_FONT_MONTSERRAT_20 0
|
||||||
|
#define LV_FONT_MONTSERRAT_22 1
|
||||||
|
#define LV_FONT_MONTSERRAT_24 0
|
||||||
|
#define LV_FONT_MONTSERRAT_26 0
|
||||||
|
#define LV_FONT_MONTSERRAT_28 0
|
||||||
|
#define LV_FONT_MONTSERRAT_30 0
|
||||||
|
#define LV_FONT_MONTSERRAT_32 0
|
||||||
|
#define LV_FONT_MONTSERRAT_34 0
|
||||||
|
#define LV_FONT_MONTSERRAT_36 1
|
||||||
|
#define LV_FONT_MONTSERRAT_38 0
|
||||||
|
#define LV_FONT_MONTSERRAT_40 0
|
||||||
|
#define LV_FONT_MONTSERRAT_42 0
|
||||||
|
#define LV_FONT_MONTSERRAT_44 0
|
||||||
|
#define LV_FONT_MONTSERRAT_46 0
|
||||||
|
#define LV_FONT_MONTSERRAT_48 0
|
||||||
|
|
||||||
|
/*Demonstrate special features*/
|
||||||
|
#define LV_FONT_MONTSERRAT_12_SUBPX 0
|
||||||
|
#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/
|
||||||
|
#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/
|
||||||
|
#define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/
|
||||||
|
|
||||||
|
/*Pixel perfect monospace fonts*/
|
||||||
|
#define LV_FONT_UNSCII_8 0
|
||||||
|
#define LV_FONT_UNSCII_16 0
|
||||||
|
|
||||||
|
/*Optionally declare custom fonts here.
|
||||||
|
*You can use these fonts as default font too and they will be available globally.
|
||||||
|
*E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/
|
||||||
|
#define LV_FONT_CUSTOM_DECLARE
|
||||||
|
|
||||||
|
/*Always set a default font*/
|
||||||
|
#define LV_FONT_DEFAULT &lv_font_montserrat_14
|
||||||
|
|
||||||
|
/*Enable handling large font and/or fonts with a lot of characters.
|
||||||
|
*The limit depends on the font size, font face and bpp.
|
||||||
|
*Compiler error will be triggered if a font needs it.*/
|
||||||
|
#define LV_FONT_FMT_TXT_LARGE 0
|
||||||
|
|
||||||
|
/*Enables/disables support for compressed fonts.*/
|
||||||
|
#define LV_USE_FONT_COMPRESSED 0
|
||||||
|
|
||||||
|
/*Enable subpixel rendering*/
|
||||||
|
#define LV_USE_FONT_SUBPX 0
|
||||||
|
#if LV_USE_FONT_SUBPX
|
||||||
|
/*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/
|
||||||
|
#define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Enable drawing placeholders when glyph dsc is not found*/
|
||||||
|
#define LV_USE_FONT_PLACEHOLDER 1
|
||||||
|
|
||||||
|
/*=================
|
||||||
|
* TEXT SETTINGS
|
||||||
|
*=================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a character encoding for strings.
|
||||||
|
* Your IDE or editor should have the same character encoding
|
||||||
|
* - LV_TXT_ENC_UTF8
|
||||||
|
* - LV_TXT_ENC_ASCII
|
||||||
|
*/
|
||||||
|
#define LV_TXT_ENC LV_TXT_ENC_UTF8
|
||||||
|
|
||||||
|
/*Can break (wrap) texts on these chars*/
|
||||||
|
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||||
|
|
||||||
|
/*If a word is at least this long, will break wherever "prettiest"
|
||||||
|
*To disable, set to a value <= 0*/
|
||||||
|
#define LV_TXT_LINE_BREAK_LONG_LEN 0
|
||||||
|
|
||||||
|
/*Minimum number of characters in a long word to put on a line before a break.
|
||||||
|
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||||
|
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||||
|
|
||||||
|
/*Minimum number of characters in a long word to put on a line after a break.
|
||||||
|
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||||
|
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||||
|
|
||||||
|
/*The control character to use for signalling text recoloring.*/
|
||||||
|
#define LV_TXT_COLOR_CMD "#"
|
||||||
|
|
||||||
|
/*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts.
|
||||||
|
*The direction will be processed according to the Unicode Bidirectional Algorithm:
|
||||||
|
*https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||||
|
#define LV_USE_BIDI 0
|
||||||
|
#if LV_USE_BIDI
|
||||||
|
/*Set the default direction. Supported values:
|
||||||
|
*`LV_BASE_DIR_LTR` Left-to-Right
|
||||||
|
*`LV_BASE_DIR_RTL` Right-to-Left
|
||||||
|
*`LV_BASE_DIR_AUTO` detect texts base direction*/
|
||||||
|
#define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Enable Arabic/Persian processing
|
||||||
|
*In these languages characters should be replaced with an other form based on their position in the text*/
|
||||||
|
#define LV_USE_ARABIC_PERSIAN_CHARS 0
|
||||||
|
|
||||||
|
/*==================
|
||||||
|
* WIDGET USAGE
|
||||||
|
*================*/
|
||||||
|
|
||||||
|
/*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/
|
||||||
|
|
||||||
|
#define LV_USE_ARC 1
|
||||||
|
|
||||||
|
#define LV_USE_BAR 1
|
||||||
|
|
||||||
|
#define LV_USE_BTN 1
|
||||||
|
|
||||||
|
#define LV_USE_BTNMATRIX 1
|
||||||
|
|
||||||
|
#define LV_USE_CANVAS 1
|
||||||
|
|
||||||
|
#define LV_USE_CHECKBOX 1
|
||||||
|
|
||||||
|
#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/
|
||||||
|
|
||||||
|
#define LV_USE_IMG 1 /*Requires: lv_label*/
|
||||||
|
|
||||||
|
#define LV_USE_LABEL 1
|
||||||
|
#if LV_USE_LABEL
|
||||||
|
#define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/
|
||||||
|
#define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LV_USE_LINE 1
|
||||||
|
|
||||||
|
#define LV_USE_ROLLER 1 /*Requires: lv_label*/
|
||||||
|
#if LV_USE_ROLLER
|
||||||
|
#define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LV_USE_SLIDER 1 /*Requires: lv_bar*/
|
||||||
|
|
||||||
|
#define LV_USE_SWITCH 1
|
||||||
|
|
||||||
|
#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/
|
||||||
|
#if LV_USE_TEXTAREA != 0
|
||||||
|
#define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LV_USE_TABLE 1
|
||||||
|
|
||||||
|
/*==================
|
||||||
|
* EXTRA COMPONENTS
|
||||||
|
*==================*/
|
||||||
|
|
||||||
|
/*-----------
|
||||||
|
* Widgets
|
||||||
|
*----------*/
|
||||||
|
#define LV_USE_ANIMIMG 1
|
||||||
|
|
||||||
|
#define LV_USE_CALENDAR 1
|
||||||
|
#if LV_USE_CALENDAR
|
||||||
|
#define LV_CALENDAR_WEEK_STARTS_MONDAY 0
|
||||||
|
#if LV_CALENDAR_WEEK_STARTS_MONDAY
|
||||||
|
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
|
||||||
|
#else
|
||||||
|
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
|
||||||
|
#define LV_USE_CALENDAR_HEADER_ARROW 1
|
||||||
|
#define LV_USE_CALENDAR_HEADER_DROPDOWN 1
|
||||||
|
#endif /*LV_USE_CALENDAR*/
|
||||||
|
|
||||||
|
#define LV_USE_CHART 1
|
||||||
|
|
||||||
|
#define LV_USE_COLORWHEEL 1
|
||||||
|
|
||||||
|
#define LV_USE_IMGBTN 1
|
||||||
|
|
||||||
|
#define LV_USE_KEYBOARD 1
|
||||||
|
|
||||||
|
#define LV_USE_LED 1
|
||||||
|
|
||||||
|
#define LV_USE_LIST 1
|
||||||
|
|
||||||
|
#define LV_USE_MENU 1
|
||||||
|
|
||||||
|
#define LV_USE_METER 1
|
||||||
|
|
||||||
|
#define LV_USE_MSGBOX 1
|
||||||
|
|
||||||
|
#define LV_USE_SPAN 1
|
||||||
|
#if LV_USE_SPAN
|
||||||
|
/*A line text can contain maximum num of span descriptor */
|
||||||
|
#define LV_SPAN_SNIPPET_STACK_SIZE 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LV_USE_SPINBOX 1
|
||||||
|
|
||||||
|
#define LV_USE_SPINNER 1
|
||||||
|
|
||||||
|
#define LV_USE_TABVIEW 1
|
||||||
|
|
||||||
|
#define LV_USE_TILEVIEW 1
|
||||||
|
|
||||||
|
#define LV_USE_WIN 1
|
||||||
|
|
||||||
|
/*-----------
|
||||||
|
* Themes
|
||||||
|
*----------*/
|
||||||
|
|
||||||
|
/*A simple, impressive and very complete theme*/
|
||||||
|
#define LV_USE_THEME_DEFAULT 1
|
||||||
|
#if LV_USE_THEME_DEFAULT
|
||||||
|
|
||||||
|
/*0: Light mode; 1: Dark mode*/
|
||||||
|
#define LV_THEME_DEFAULT_DARK 0
|
||||||
|
|
||||||
|
/*1: Enable grow on press*/
|
||||||
|
#define LV_THEME_DEFAULT_GROW 1
|
||||||
|
|
||||||
|
/*Default transition time in [ms]*/
|
||||||
|
#define LV_THEME_DEFAULT_TRANSITION_TIME 80
|
||||||
|
#endif /*LV_USE_THEME_DEFAULT*/
|
||||||
|
|
||||||
|
/*A very simple theme that is a good starting point for a custom theme*/
|
||||||
|
#define LV_USE_THEME_BASIC 1
|
||||||
|
|
||||||
|
/*A theme designed for monochrome displays*/
|
||||||
|
#define LV_USE_THEME_MONO 1
|
||||||
|
|
||||||
|
/*-----------
|
||||||
|
* Layouts
|
||||||
|
*----------*/
|
||||||
|
|
||||||
|
/*A layout similar to Flexbox in CSS.*/
|
||||||
|
#define LV_USE_FLEX 1
|
||||||
|
|
||||||
|
/*A layout similar to Grid in CSS.*/
|
||||||
|
#define LV_USE_GRID 0 //1
|
||||||
|
|
||||||
|
/*---------------------
|
||||||
|
* 3rd party libraries
|
||||||
|
*--------------------*/
|
||||||
|
|
||||||
|
/*File system interfaces for common APIs */
|
||||||
|
|
||||||
|
/*API for fopen, fread, etc*/
|
||||||
|
#define LV_USE_FS_STDIO 0
|
||||||
|
#if LV_USE_FS_STDIO
|
||||||
|
#define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||||
|
#define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||||
|
#define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*API for open, read, etc*/
|
||||||
|
#define LV_USE_FS_POSIX 0
|
||||||
|
#if LV_USE_FS_POSIX
|
||||||
|
#define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||||
|
#define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||||
|
#define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*API for CreateFile, ReadFile, etc*/
|
||||||
|
#define LV_USE_FS_WIN32 0
|
||||||
|
#if LV_USE_FS_WIN32
|
||||||
|
#define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||||
|
#define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||||
|
#define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
|
||||||
|
#define LV_USE_FS_FATFS 0
|
||||||
|
#if LV_USE_FS_FATFS
|
||||||
|
#define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||||
|
#define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*PNG decoder library*/
|
||||||
|
#define LV_USE_PNG 0
|
||||||
|
|
||||||
|
/*BMP decoder library*/
|
||||||
|
#define LV_USE_BMP 0
|
||||||
|
|
||||||
|
/* JPG + split JPG decoder library.
|
||||||
|
* Split JPG is a custom format optimized for embedded systems. */
|
||||||
|
#define LV_USE_SJPG 0
|
||||||
|
|
||||||
|
/*GIF decoder library*/
|
||||||
|
#define LV_USE_GIF 0
|
||||||
|
|
||||||
|
/*QR code library*/
|
||||||
|
#define LV_USE_QRCODE 0
|
||||||
|
|
||||||
|
/*FreeType library*/
|
||||||
|
#define LV_USE_FREETYPE 0
|
||||||
|
#if LV_USE_FREETYPE
|
||||||
|
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
|
||||||
|
#define LV_FREETYPE_CACHE_SIZE (16 * 1024)
|
||||||
|
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||||
|
/* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
|
||||||
|
/* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
|
||||||
|
/* if font size >= 256, must be configured as image cache */
|
||||||
|
#define LV_FREETYPE_SBIT_CACHE 0
|
||||||
|
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
|
||||||
|
/* (0:use system defaults) */
|
||||||
|
#define LV_FREETYPE_CACHE_FT_FACES 0
|
||||||
|
#define LV_FREETYPE_CACHE_FT_SIZES 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Rlottie library*/
|
||||||
|
#define LV_USE_RLOTTIE 0
|
||||||
|
|
||||||
|
/*FFmpeg library for image decoding and playing videos
|
||||||
|
*Supports all major image formats so do not enable other image decoder with it*/
|
||||||
|
#define LV_USE_FFMPEG 0
|
||||||
|
#if LV_USE_FFMPEG
|
||||||
|
/*Dump input information to stderr*/
|
||||||
|
#define LV_FFMPEG_DUMP_FORMAT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------
|
||||||
|
* Others
|
||||||
|
*----------*/
|
||||||
|
|
||||||
|
/*1: Enable API to take snapshot for object*/
|
||||||
|
#define LV_USE_SNAPSHOT 0
|
||||||
|
|
||||||
|
/*1: Enable Monkey test*/
|
||||||
|
#define LV_USE_MONKEY 0
|
||||||
|
|
||||||
|
/*1: Enable grid navigation*/
|
||||||
|
#define LV_USE_GRIDNAV 0
|
||||||
|
|
||||||
|
/*1: Enable lv_obj fragment*/
|
||||||
|
#define LV_USE_FRAGMENT 0
|
||||||
|
|
||||||
|
/*1: Support using images as font in label or span widgets */
|
||||||
|
#define LV_USE_IMGFONT 0
|
||||||
|
|
||||||
|
/*1: Enable a published subscriber based messaging system */
|
||||||
|
#define LV_USE_MSG 0
|
||||||
|
|
||||||
|
/*1: Enable Pinyin input method*/
|
||||||
|
/*Requires: lv_keyboard*/
|
||||||
|
#define LV_USE_IME_PINYIN 0
|
||||||
|
#if LV_USE_IME_PINYIN
|
||||||
|
/*1: Use default thesaurus*/
|
||||||
|
/*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
|
||||||
|
#define LV_IME_PINYIN_USE_DEFAULT_DICT 1
|
||||||
|
/*Set the maximum number of candidate panels that can be displayed*/
|
||||||
|
/*This needs to be adjusted according to the size of the screen*/
|
||||||
|
#define LV_IME_PINYIN_CAND_TEXT_NUM 6
|
||||||
|
|
||||||
|
/*Use 9 key input(k9)*/
|
||||||
|
#define LV_IME_PINYIN_USE_K9_MODE 1
|
||||||
|
#if LV_IME_PINYIN_USE_K9_MODE == 1
|
||||||
|
#define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3
|
||||||
|
#endif // LV_IME_PINYIN_USE_K9_MODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*==================
|
||||||
|
* EXAMPLES
|
||||||
|
*==================*/
|
||||||
|
|
||||||
|
/*Enable the examples to be built with the library*/
|
||||||
|
#define LV_BUILD_EXAMPLES 0 //1
|
||||||
|
|
||||||
|
/*===================
|
||||||
|
* DEMO USAGE
|
||||||
|
====================*/
|
||||||
|
|
||||||
|
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */
|
||||||
|
#define LV_USE_DEMO_WIDGETS 0
|
||||||
|
#if LV_USE_DEMO_WIDGETS
|
||||||
|
#define LV_DEMO_WIDGETS_SLIDESHOW 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Demonstrate the usage of encoder and keyboard*/
|
||||||
|
#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0
|
||||||
|
|
||||||
|
/*Benchmark your system*/
|
||||||
|
#define LV_USE_DEMO_BENCHMARK 0
|
||||||
|
#if LV_USE_DEMO_BENCHMARK
|
||||||
|
/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/
|
||||||
|
#define LV_DEMO_BENCHMARK_RGB565A8 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*Stress test for LVGL*/
|
||||||
|
#define LV_USE_DEMO_STRESS 0
|
||||||
|
|
||||||
|
/*Music player demo*/
|
||||||
|
#define LV_USE_DEMO_MUSIC 0
|
||||||
|
#if LV_USE_DEMO_MUSIC
|
||||||
|
#define LV_DEMO_MUSIC_SQUARE 0
|
||||||
|
#define LV_DEMO_MUSIC_LANDSCAPE 0
|
||||||
|
#define LV_DEMO_MUSIC_ROUND 0
|
||||||
|
#define LV_DEMO_MUSIC_LARGE 0
|
||||||
|
#define LV_DEMO_MUSIC_AUTO_PLAY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*--END OF LV_CONF_H--*/
|
||||||
|
|
||||||
|
#endif /*LV_CONF_H*/
|
||||||
|
|
||||||
|
#endif /*End of "Content enable"*/
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.12.4)
|
||||||
|
|
||||||
|
if(NOT ESP_PLATFORM)
|
||||||
|
project(lvgl HOMEPAGE_URL https://github.com/lvgl/lvgl)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(LVGL_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
|
if(ESP_PLATFORM)
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/env_support/cmake/esp.cmake)
|
||||||
|
elseif(ZEPHYR_BASE)
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/env_support/cmake/zephyr.cmake)
|
||||||
|
elseif(MICROPY_DIR)
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/env_support/cmake/micropython.cmake)
|
||||||
|
else()
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/env_support/cmake/custom.cmake)
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
MIT licence
|
||||||
|
Copyright (c) 2021 LVGL Kft
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
<h1 align="center"> LVGL - Light and Versatile Graphics Library</h1>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://lvgl.io/assets/images/lvgl_widgets_demo.gif">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
LVGL provides everything you need to create an embedded GUI with easy-to-use graphical elements, beautiful visual effects and a low memory footprint.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 align="center">
|
||||||
|
<a href="https://lvgl.io">Website </a> ·
|
||||||
|
<a href="https://docs.lvgl.io/">Docs</a> ·
|
||||||
|
<a href="https://forum.lvgl.io">Forum</a> ·
|
||||||
|
<a href="https://lvgl.io/services">Services</a> ·
|
||||||
|
<a href="https://docs.lvgl.io/master/examples.html">Interactive examples</a>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
|
||||||
|
**English** | [中文](./README_zh.md) | [Português do Brasil](./README_pt_BR.md)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Table of content
|
||||||
|
- [Overview](#overview)
|
||||||
|
- [Get started](#get-started)
|
||||||
|
- [Examples](#examples)
|
||||||
|
- [Services](#services)
|
||||||
|
- [Contributing](#contributing)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
### Features
|
||||||
|
* Powerful [building blocks](https://docs.lvgl.io/master/widgets/index.html): buttons, charts, lists, sliders, images, etc.
|
||||||
|
* Advanced graphics engine: animations, anti-aliasing, opacity, smooth scrolling, blending modes, etc
|
||||||
|
* Supports [various input devices](https://docs.lvgl.io/master/overview/indev.html): touchscreen, mouse, keyboard, encoder, buttons, etc.
|
||||||
|
* Supports [multiple displays](https://docs.lvgl.io/master/overview/display.html)
|
||||||
|
* Hardware independent, can be use with any microcontroller and display
|
||||||
|
* Scalable to operate with little memory (64 kB Flash, 16 kB RAM)
|
||||||
|
* Multi-language support with UTF-8 handling, CJK, Bidirectional and Arabic script support
|
||||||
|
* Fully customizable graphical elements via [CSS-like styles](https://docs.lvgl.io/master/overview/style.html)
|
||||||
|
* Powerful layouts inspired by CSS: [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) and [Grid](https://docs.lvgl.io/master/layouts/grid.html)
|
||||||
|
* OS, External memory and GPU are supported but not required. (built in support for STM32 DMA2D, SWM341 DMA2D, and NXP PXP and VGLite)
|
||||||
|
* Smooth rendering even with a [single frame buffer](https://docs.lvgl.io/master/porting/display.html)
|
||||||
|
* Written in C and compatible with C++
|
||||||
|
* Micropython Binding exposes [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings)
|
||||||
|
* [Simulator](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) to develop on PC without embedded hardware
|
||||||
|
* 100+ simple [Examples](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||||
|
* [Documentation](http://docs.lvgl.io/) and API references online and in PDF
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
Basically, every modern controller (which is able to drive a display) is suitable to run LVGL. The minimal requirements are:
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td> <strong>Name</strong> </td>
|
||||||
|
<td><strong>Minimal</strong></td>
|
||||||
|
<td><strong>Recommended</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Architecture</strong></td>
|
||||||
|
<td colspan="2">16, 32 or 64 bit microcontroller or processor</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> <strong>Clock</strong></td>
|
||||||
|
<td> > 16 MHz </td>
|
||||||
|
<td> > 48 MHz</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <strong>Flash/ROM</strong></td>
|
||||||
|
<td> > 64 kB </td>
|
||||||
|
<td> > 180 kB</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <strong>Static RAM</strong></td>
|
||||||
|
<td> > 16 kB </td>
|
||||||
|
<td> > 48 kB</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <strong>Draw buffer</strong></td>
|
||||||
|
<td> > 1 × <em>hor. res.</em> pixels </td>
|
||||||
|
<td> > 1/10 screen size </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <strong>Compiler</strong></td>
|
||||||
|
<td colspan="2"> C99 or newer </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
*Note that the memory usage might vary depending on the architecture, compiler and build options.*
|
||||||
|
|
||||||
|
### Supported platforms
|
||||||
|
LVGL is completely platform independent and can be used with any MCU that fulfills the requirements.
|
||||||
|
Just to mention some platforms:
|
||||||
|
- NXP: Kinetis, LPC, iMX, iMX RT
|
||||||
|
- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7
|
||||||
|
- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ
|
||||||
|
- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb)
|
||||||
|
- [Raspberry Pi](https://github.com/lvgl/lv_port_linux_frame_buffer)
|
||||||
|
- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32)
|
||||||
|
- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix)
|
||||||
|
- Nordic NRF52 Bluetooth modules
|
||||||
|
- Quectel modems
|
||||||
|
- [SYNWIT SWM341](http://www.synwit.cn/)
|
||||||
|
|
||||||
|
LVGL is also available as:
|
||||||
|
- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html)
|
||||||
|
- [PlatformIO package](https://registry.platformio.org/libraries/lvgl/lvgl)
|
||||||
|
- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html)
|
||||||
|
- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html)
|
||||||
|
- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY)
|
||||||
|
- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html)
|
||||||
|
- [RT-Thread RTOS](https://docs.lvgl.io/master/get-started/os/rt-thread.html)
|
||||||
|
|
||||||
|
|
||||||
|
## Get started
|
||||||
|
This list shows the recommended way of learning the library:
|
||||||
|
1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes)
|
||||||
|
2. Read the [Introduction](https://docs.lvgl.io/master/intro/index.html) page of the documentation (5 minutes)
|
||||||
|
3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/master/get-started/quick-overview.html) page (15 minutes)
|
||||||
|
4. Set up a [Simulator](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) (10 minutes)
|
||||||
|
5. Try out some [Examples](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||||
|
6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/master/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_)
|
||||||
|
7. Read the [Overview](https://docs.lvgl.io/master/overview/index.html) page to get a better understanding of the library (2-3 hours)
|
||||||
|
8. Check the documentation of the [Widgets](https://docs.lvgl.io/master/widgets/index.html) to see their features and usage
|
||||||
|
9. If you have questions go to the [Forum](http://forum.lvgl.io/)
|
||||||
|
10. Read the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) guide to see how you can help to improve LVGL (15 minutes)
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
For more examples see the [examples](https://github.com/lvgl/lvgl/tree/master/examples) folder.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### C
|
||||||
|
```c
|
||||||
|
lv_obj_t * btn = lv_btn_create(lv_scr_act()); /*Add a button to the current screen*/
|
||||||
|
lv_obj_set_pos(btn, 10, 10); /*Set its position*/
|
||||||
|
lv_obj_set_size(btn, 100, 50); /*Set its size*/
|
||||||
|
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/
|
||||||
|
|
||||||
|
lv_obj_t * label = lv_label_create(btn); /*Add a label to the button*/
|
||||||
|
lv_label_set_text(label, "Button"); /*Set the labels text*/
|
||||||
|
lv_obj_center(label); /*Align the label to the center*/
|
||||||
|
...
|
||||||
|
|
||||||
|
void btn_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
printf("Clicked\n");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Micropython
|
||||||
|
Learn more about [Micropython](https://docs.lvgl.io/master/get-started/bindings/micropython.html).
|
||||||
|
```python
|
||||||
|
def btn_event_cb(e):
|
||||||
|
print("Clicked")
|
||||||
|
|
||||||
|
# Create a Button and a Label
|
||||||
|
btn = lv.btn(lv.scr_act())
|
||||||
|
btn.set_pos(10, 10)
|
||||||
|
btn.set_size(100, 50)
|
||||||
|
btn.add_event_cb(btn_event_cb, lv.EVENT.CLICKED, None)
|
||||||
|
|
||||||
|
label = lv.label(btn)
|
||||||
|
label.set_text("Button")
|
||||||
|
label.center()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Services
|
||||||
|
LVGL Kft was established to provide a solid background for LVGL library. We offer several type of services to help you in UI development:
|
||||||
|
- Graphics design
|
||||||
|
- UI implementation
|
||||||
|
- Consulting/Support
|
||||||
|
|
||||||
|
For more information see https://lvgl.io/services
|
||||||
|
Feel free to contact us if you have any questions.
|
||||||
|
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
LVGL is an open project and contribution is very welcome. There are many ways to contribute from simply speaking about your project, through writing examples, improving the documentation, fixing bugs to hosting your own project under the LVGL organization.
|
||||||
|
|
||||||
|
For a detailed description of contribution opportunities visit the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) section of the documentation.
|
||||||
|
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
<h1 align="center"> LVGL - Biblioteca gráfica leve e versátil</h1>
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://lvgl.io/assets/images/lvgl_widgets_demo.gif">
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
O LVGL fornece tudo o que você precisa para criar uma GUI incorporada com elementos gráficos fáceis de usar, belos efeitos visuais e um baixo consumo de memória.
|
||||||
|
</p>
|
||||||
|
<h4 align="center">
|
||||||
|
<a href="https://lvgl.io">Site</a> ·
|
||||||
|
<a href="https://docs.lvgl.io/">Documentação</a> ·
|
||||||
|
<a href="https://forum.lvgl.io">Fórum</a> ·
|
||||||
|
<a href="https://lvgl.io/services">Serviços</a> ·
|
||||||
|
<a href="https://docs.lvgl.io/master/examples.html">Exemplos interativos</a>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
[English](./README.md) | [中文](./README_zh.md) | **Português do Brasil**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Tabela de conteúdo
|
||||||
|
|
||||||
|
- [Visão Geral](#visão-geral)
|
||||||
|
- [Iniciando](#iniciando)
|
||||||
|
- [Exemplos](#exemplos)
|
||||||
|
- [Serviços](#serviços)
|
||||||
|
- [Contribuindo](#contribuindo)
|
||||||
|
|
||||||
|
## Visão Geral
|
||||||
|
|
||||||
|
### Recursos
|
||||||
|
* Poderosos [widgets](https://docs.lvgl.io/master/widgets/index.html): botões, gráficos, listas, controles deslizantes (sliders), imagens, etc.
|
||||||
|
* Mecanismo gráfico avançado: animações, anti-aliasing, opacidade, rolagem suave, modos de mesclagem (blending modes), etc.
|
||||||
|
* Suporte à [vários dispositivos de entrada](https://docs.lvgl.io/master/overview/indev.html): tela sensível ao toque, mouse, teclado, codificador, botões, etc.
|
||||||
|
* Suporte à [vários monitores](https://docs.lvgl.io/master/overview/display.html)
|
||||||
|
* Pode ser usado com qualquer microcontrolador e display, independente do hardware
|
||||||
|
* Escalável para operar com pouca memória (64 kB Flash, 16 kB RAM)
|
||||||
|
* Suporte multilíngue com manipulação UTF-8, suporte ao alfabeto bidirecional, árabe e CJK (Chinês, Japonês e Coreano)
|
||||||
|
* Elementos gráficos totalmente personalizáveis por meio de [CSS](https://docs.lvgl.io/master/overview/style.html)
|
||||||
|
* Layouts poderosos inspirados em CSS: [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) e [Grid](https://docs.lvgl.io/master/layouts/grid.html)
|
||||||
|
* SO, memória externa e GPU são suportados, mas não obrigatórios. (suporte integrado para STM32 DMA2D, SWM341 DMA2D e NXP PXP e VGLite)
|
||||||
|
* Renderização suave mesmo com um [buffer de quadro único](https://docs.lvgl.io/master/porting/display.html) (single frame buffer)
|
||||||
|
* Escrito em C e compatível com C++
|
||||||
|
* Uso do LittlevGL com Micropython simplificado com [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings)
|
||||||
|
* [Simulador](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) para desenvolver no PC sem hardware embutido
|
||||||
|
* Mais de 100 [exemplos simples](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||||
|
* [Documentação](http://docs.lvgl.io/) e referências de API online e em PDF
|
||||||
|
|
||||||
|
### Requerimentos
|
||||||
|
Basicamente, todo controlador moderno (que é capaz de acionar um display) é adequado para executar LVGL. Os requisitos mínimos são:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Nome</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>Minímo</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>Recomendado</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Arquitetura</strong>
|
||||||
|
</td>
|
||||||
|
<td colspan="2">Microcontrolador ou processador de 16, 32 ou 64 bits</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Clock</strong>
|
||||||
|
</td>
|
||||||
|
<td>> 16 MHz</td>
|
||||||
|
<td>> 48 MHz</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Flash/ROM</strong>
|
||||||
|
</td>
|
||||||
|
<td>> 64 kB</td>
|
||||||
|
<td>> 180 kB</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>RAM estática</strong>
|
||||||
|
</td>
|
||||||
|
<td>> 16 kB</td>
|
||||||
|
<td>> 48 kB</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Draw buffer</strong>
|
||||||
|
</td>
|
||||||
|
<td>> 1 × <em>hor. res.</em> pixels</td>
|
||||||
|
<td>> tamanho da tela de 1/10</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Compilador</strong>
|
||||||
|
</td>
|
||||||
|
<td colspan="2">Padrão C99 ou mais recente</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
*Observe que o uso de memória pode variar dependendo da arquitetura, do compilador e das opções de compilação.*
|
||||||
|
|
||||||
|
### Plataformas suportadas
|
||||||
|
O LVGL é completamente independente de plataforma e pode ser usado com qualquer MCU que atenda aos requisitos.
|
||||||
|
Apenas para citar algumas plataformas:
|
||||||
|
|
||||||
|
- NXP: Kinetis, LPC, iMX, iMX RT
|
||||||
|
- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7
|
||||||
|
- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ
|
||||||
|
- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb)
|
||||||
|
- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl)
|
||||||
|
- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32)
|
||||||
|
- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix)
|
||||||
|
- Nordic NRF52 Bluetooth modules
|
||||||
|
- Quectel modems
|
||||||
|
- [SYNWIT SWM341](https://www.synwit.cn/)
|
||||||
|
|
||||||
|
LVGL também está disponível para:
|
||||||
|
- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html)
|
||||||
|
- [PlatformIO package](https://registry.platformio.org/libraries/lvgl/lvgl)
|
||||||
|
- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html)
|
||||||
|
- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html)
|
||||||
|
- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY)
|
||||||
|
- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html)
|
||||||
|
- [RT-Thread RTOS](https://docs.lvgl.io/master/get-started/os/rt-thread.html)
|
||||||
|
|
||||||
|
## Iniciando
|
||||||
|
Esta lista mostra a maneira recomendada de aprender sobre a biblioteca:
|
||||||
|
|
||||||
|
1. Confira as [demos on-line](https://lvgl.io/demos) para ver o LVGL em ação (3 minutos)
|
||||||
|
2. Leia a [introdução](https://docs.lvgl.io/master/intro/index.html) da documentação (5 minutos)
|
||||||
|
3. Familiarize-se com o básico da [Visão geral rápida](https://docs.lvgl.io/master/get-started/quick-overview.html) (15 minutos)
|
||||||
|
4. Configure um [simulador](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) (10 minutos)
|
||||||
|
5. Experimente alguns [Exemplos](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||||
|
6. Placa para porta LVGL. Veja o guia [porting](https://docs.lvgl.io/master/porting/index.html) ou verifique o pronto para usar [Projects](https://github.com/lvgl?q=lv_port_)
|
||||||
|
7. Leia a [visão geral](https://docs.lvgl.io/master/overview/index.html) para entender melhor a biblioteca (2-3 horas)
|
||||||
|
8. Verifique a documentação dos [widgets](https://docs.lvgl.io/master/widgets/index.html) para ver seus recursos e como utilizá-los
|
||||||
|
9. Se você tiver dúvidas, acesse o [fórum](http://forum.lvgl.io/)
|
||||||
|
10. Leia o guia de [contribuição](https://docs.lvgl.io/master/CONTRIBUTING.html) para ver como você pode ajudar a melhorar o LVGL (15 minutos)
|
||||||
|
|
||||||
|
## Exemplos
|
||||||
|
Para mais exemplos, veja a pasta [examples](https://github.com/lvgl/lvgl/tree/master/examples).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### C
|
||||||
|
|
||||||
|
```c
|
||||||
|
lv_obj_t * button = lv_btn_create(lv_scr_act()); /* Adiciona um botão à tela atual */
|
||||||
|
lv_obj_set_pos(button, 10, 10); /* Define uma posição ao botão na tela */
|
||||||
|
lv_obj_set_size(button, 100, 50); /* Define o tamanho */
|
||||||
|
lv_obj_add_event_cb(button, button_event_callback, LV_EVENT_CLICKED, NULL); /* Atribui um retorno de chamada (callback) */
|
||||||
|
|
||||||
|
lv_obj_t * label = lv_label_create(button); /* Adiciona um rótulo (label) */
|
||||||
|
lv_label_set_text(label, "Clique aqui"); /* Define o texto do rótulo (label) */
|
||||||
|
lv_obj_center(label); /* Alinha o texto ao centro */
|
||||||
|
...
|
||||||
|
|
||||||
|
void button_event_callback(lv_event_t * e)
|
||||||
|
{
|
||||||
|
printf("Clicado\n");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Micropython
|
||||||
|
Saiba mais em [Micropython](https://docs.lvgl.io/master/get-started/bindings/micropython.html)
|
||||||
|
|
||||||
|
```python
|
||||||
|
def button_event_callback(event):
|
||||||
|
print("Clicado")
|
||||||
|
|
||||||
|
# Cria um botão e um rótulo (label)
|
||||||
|
button = lv.btn(lv.scr_act())
|
||||||
|
button.set_pos(10, 10)
|
||||||
|
button.set_size(100, 50)
|
||||||
|
button.add_event_cb(button_event_callback, lv.EVENT.CLICKED, None)
|
||||||
|
|
||||||
|
label = lv.label(button)
|
||||||
|
label.set_text("Cliquq aqui")
|
||||||
|
label.center()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Serviços
|
||||||
|
O LVGL Kft foi estabelecido para fornecer uma base sólida para a biblioteca LVGL. Oferecemos vários tipos de serviços
|
||||||
|
para ajudá-lo no desenvolvimento da interface do usuário:
|
||||||
|
|
||||||
|
- Design gráfico
|
||||||
|
- Implementação de IU
|
||||||
|
- Consultoria/Suporte
|
||||||
|
|
||||||
|
Para mais informações, consulte [LVGL Serviços](https://lvgl.io/services). Sinta-se à vontade para entrar em contato
|
||||||
|
conosco se tiver alguma dúvida.
|
||||||
|
|
||||||
|
## Contribuindo
|
||||||
|
O LVGL é um projeto aberto e sua contribuição é muito bem-vinda. Há muitas maneiras de contribuir, desde simplesmente
|
||||||
|
falando sobre seu projeto, escrevendo exemplos, melhorando a documentação, corrigindo bugs até hospedar seu próprio
|
||||||
|
projeto sob a organização LVGL.
|
||||||
|
|
||||||
|
Para obter uma descrição detalhada das oportunidades de contribuição, visite a seção de [contribuição](https://docs.lvgl.io/master/CONTRIBUTING.html) da documentação.
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
<h1 align="center"> LVGL - Light and Versatile Graphics Library</h1>
|
||||||
|
<h2 align="center"> LVGL - 轻量级通用型图形库</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://lvgl.io/assets/images/lvgl_widgets_demo.gif">
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
LVGL是一个高度可裁剪、低资源占用、界面美观且易用的嵌入式系统图形库
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h4 align="center">
|
||||||
|
<a href="https://lvgl.io">官网</a> ·
|
||||||
|
<a href="https://docs.lvgl.io/">文档</a> ·
|
||||||
|
<a href="https://forum.lvgl.io">论坛</a> ·
|
||||||
|
<a href="https://lvgl.io/services">服务</a> ·
|
||||||
|
<a href="https://docs.lvgl.io/master/examples.html">例程</a>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
|
||||||
|
[English](./README.md) | **中文** | [Português do Brasil](./README_pt_BR.md)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 目录
|
||||||
|
- [概况与总览](#概况与总览)
|
||||||
|
- [如何入门](#如何入门)
|
||||||
|
- [例程](#例程)
|
||||||
|
- [服务](#服务)
|
||||||
|
- [如何向社区贡献](#如何向社区贡献)
|
||||||
|
|
||||||
|
## 概况与总览
|
||||||
|
### 特性
|
||||||
|
* 丰富且强大的模块化[图形组件](https://docs.lvgl.io/master/widgets/index.html):按钮 (buttons)、图表 (charts)、列表 (lists)、滑动条 (sliders)、图片 (images) 等
|
||||||
|
* 高级的图形引擎:动画、抗锯齿、透明度、平滑滚动、图层混合等效果
|
||||||
|
* 支持多种[输入设备](https://docs.lvgl.io/master/overview/indev.html):触摸屏、 键盘、编码器、按键等
|
||||||
|
* 支持[多显示设备](https://docs.lvgl.io/master/overview/display.html)
|
||||||
|
* 不依赖特定的硬件平台,可以在任何显示屏上运行
|
||||||
|
* 配置可裁剪(最低资源占用:64 kB Flash,16 kB RAM)
|
||||||
|
* 基于UTF-8的多语种支持,例如中文、日文、韩文、阿拉伯文等
|
||||||
|
* 可以通过[类CSS](https://docs.lvgl.io/master/overview/style.html)的方式来设计、布局图形界面(例如:[Flexbox](https://docs.lvgl.io/master/layouts/flex.html)、[Grid](https://docs.lvgl.io/master/layouts/grid.html))
|
||||||
|
* 支持操作系统、外置内存、以及硬件加速(LVGL已内建支持STM32 DMA2D、SWM341 DMA2D、NXP PXP和VGLite)
|
||||||
|
* 即便仅有[单缓冲区(frame buffer)](https://docs.lvgl.io/master/porting/display.html)的情况下,也可保证渲染如丝般顺滑
|
||||||
|
* 全部由C编写完成,并支持C++调用
|
||||||
|
* 支持Micropython编程,参见:[LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings)
|
||||||
|
* 支持[模拟器](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html)仿真,可以无硬件依托进行开发
|
||||||
|
* 丰富详实的[例程](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||||
|
* 详尽的[文档](http://docs.lvgl.io/)以及API参考手册,可线上查阅或可下载为PDF格式
|
||||||
|
|
||||||
|
### 硬件要求
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td> <strong>要求</strong> </td>
|
||||||
|
<td><strong>最低要求</strong></td>
|
||||||
|
<td><strong>建议要求</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>架构</strong></td>
|
||||||
|
<td colspan="2">16、32、64位微控制器或微处理器</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> <strong>时钟</strong></td>
|
||||||
|
<td> > 16 MHz</td>
|
||||||
|
<td> > 48 MHz</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <strong>Flash/ROM</strong></td>
|
||||||
|
<td> > 64 kB </td>
|
||||||
|
<td> > 180 kB</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <strong>Static RAM</strong></td>
|
||||||
|
<td> > 16 kB </td>
|
||||||
|
<td> > 48 kB</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <strong>Draw buffer</strong></td>
|
||||||
|
<td> > 1 × <em>hor. res.</em> pixels </td>
|
||||||
|
<td> > 1/10屏幕大小 </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <strong>编译器</strong></td>
|
||||||
|
<td colspan="2"> C99或更新 </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
*注意:资源占用情况与具体硬件平台、编译器等因素有关,上表中仅给出参考值*
|
||||||
|
|
||||||
|
### 已经支持的平台
|
||||||
|
LVGL本身并不依赖特定的硬件平台,任何满足LVGL硬件配置要求的微控制器均可运行LVGL。
|
||||||
|
如下仅列举其中一部分:
|
||||||
|
|
||||||
|
- NXP: Kinetis, LPC, iMX, iMX RT
|
||||||
|
- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7
|
||||||
|
- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ
|
||||||
|
- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb)
|
||||||
|
- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl)
|
||||||
|
- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32)
|
||||||
|
- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix)
|
||||||
|
- Nordic NRF52 Bluetooth modules
|
||||||
|
- Quectel modems
|
||||||
|
- [SYNWIT SWM341](https://www.synwit.cn/)
|
||||||
|
|
||||||
|
LVGL也支持:
|
||||||
|
- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html)
|
||||||
|
- [PlatformIO package](https://platformio.org/lib/show/12440/lvgl)
|
||||||
|
- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html)
|
||||||
|
- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html)
|
||||||
|
- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY)
|
||||||
|
- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html)
|
||||||
|
- [RT-Thread RTOS](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/packages-manual/lvgl-docs/introduction)
|
||||||
|
|
||||||
|
|
||||||
|
## 如何入门
|
||||||
|
请按照如下顺序来学习LVGL:
|
||||||
|
1. 使用[网页在线例程](https://lvgl.io/demos)来体验LVGL(3分钟)
|
||||||
|
2. 阅读文档[简介](https://docs.lvgl.io/master/intro/index.html)章节来初步了解LVGL(5分钟)
|
||||||
|
3. 再来阅读一下文档快速[快速概览](https://docs.lvgl.io/master/get-started/quick-overview.html)章节来了解LVGL的基本知识(15分钟)
|
||||||
|
4. 学习如何使用[模拟器](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html)来在电脑上仿真LVGL(10分钟)
|
||||||
|
5. 试着动手实践一些[例程](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||||
|
6. 参考[移植指南](https://docs.lvgl.io/master/porting/index.html)尝试将LVGL移植到一块开发板上,LVGL也已经提供了一些移植好的[工程](https://github.com/lvgl?q=lv_port_)
|
||||||
|
7. 仔细阅读文档[总览](https://docs.lvgl.io/master/overview/index.html)章节来更加深入的了解和熟悉LVGL(2-3小时)
|
||||||
|
8. 浏览文档[组件(Widgets)](https://docs.lvgl.io/master/widgets/index.html)章节来了解如何使用它们
|
||||||
|
9. 如果你有问题可以到LVGL[论坛](http://forum.lvgl.io/)提问
|
||||||
|
10. 阅读文档[如何向社区贡献](https://docs.lvgl.io/master/CONTRIBUTING.html)章节来看看你能帮LVGL社区做些什么,以促进LVGL软件质量的不断提高(15分钟)
|
||||||
|
|
||||||
|
## 例程
|
||||||
|
|
||||||
|
更多例程请参见 [examples](https://github.com/lvgl/lvgl/tree/master/examples) 文件夹。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### C
|
||||||
|
```c
|
||||||
|
lv_obj_t * btn = lv_btn_create(lv_scr_act()); /*Add a button to the current screen*/
|
||||||
|
lv_obj_set_pos(btn, 10, 10); /*Set its position*/
|
||||||
|
lv_obj_set_size(btn, 100, 50); /*Set its size*/
|
||||||
|
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/
|
||||||
|
|
||||||
|
lv_obj_t * label = lv_label_create(btn); /*Add a label to the button*/
|
||||||
|
lv_label_set_text(label, "Button"); /*Set the labels text*/
|
||||||
|
lv_obj_center(label); /*Align the label to the center*/
|
||||||
|
...
|
||||||
|
|
||||||
|
void btn_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
printf("Clicked\n");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Micropython
|
||||||
|
更多信息请到 [Micropython官网](https://docs.lvgl.io/master/get-started/bindings/micropython.html) 查询.
|
||||||
|
```python
|
||||||
|
def btn_event_cb(e):
|
||||||
|
print("Clicked")
|
||||||
|
|
||||||
|
# Create a Button and a Label
|
||||||
|
btn = lv.btn(lv.scr_act())
|
||||||
|
btn.set_pos(10, 10)
|
||||||
|
btn.set_size(100, 50)
|
||||||
|
btn.add_event_cb(btn_event_cb, lv.EVENT.CLICKED, None)
|
||||||
|
|
||||||
|
label = lv.label(btn)
|
||||||
|
label.set_text("Button")
|
||||||
|
label.center()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 服务
|
||||||
|
LVGL 责任有限公司成立的目的是为了给用户使用LVGL图形库提供额外的技术支持,我们致力于提供以下服务:
|
||||||
|
|
||||||
|
- 图形设计
|
||||||
|
- UI设计
|
||||||
|
- 技术咨询以及技术支持
|
||||||
|
|
||||||
|
更多信息请参见 https://lvgl.io/services ,如果有任何问题请随时联系我们。
|
||||||
|
|
||||||
|
|
||||||
|
## 如何向社区贡献
|
||||||
|
LVGL是一个开源项目,非常欢迎您参与到社区贡献当中。您有很多种方式来为提高LVGL贡献您的一份力量,包括但不限于:
|
||||||
|
|
||||||
|
- 介绍你基于LVGL设计的作品或项目
|
||||||
|
- 写一些例程
|
||||||
|
- 修改以及完善文档
|
||||||
|
- 修复bug
|
||||||
|
|
||||||
|
请参见文档[如何向社区贡献](https://docs.lvgl.io/master/CONTRIBUTING.html)章节来获取更多信息。
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# RT-Thread building script for bridge
|
||||||
|
|
||||||
|
import os
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
objs = []
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
|
||||||
|
objs = objs + SConscript(cwd + '/env_support/rt-thread/SConscript')
|
||||||
|
|
||||||
|
Return('objs')
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# ESP-IDF component file for make based commands
|
||||||
|
|
||||||
|
COMPONENT_SRCDIRS := . \
|
||||||
|
src \
|
||||||
|
src/core \
|
||||||
|
src/draw \
|
||||||
|
src/extra \
|
||||||
|
src/font \
|
||||||
|
src/gpu \
|
||||||
|
src/hal \
|
||||||
|
src/misc \
|
||||||
|
src/widgets \
|
||||||
|
src/extra/layouts \
|
||||||
|
src/extra/layouts/flex \
|
||||||
|
src/extra/layouts/grid \
|
||||||
|
src/extra/themes \
|
||||||
|
src/extra/themes/basic \
|
||||||
|
src/extra/themes/default \
|
||||||
|
src/extra/widgets/calendar \
|
||||||
|
src/extra/widgets/colorwheel \
|
||||||
|
src/extra/widgets \
|
||||||
|
src/extra/widgets/imgbtn \
|
||||||
|
src/extra/widgets/keyboard \
|
||||||
|
src/extra/widgets/led \
|
||||||
|
src/extra/widgets/list \
|
||||||
|
src/extra/widgets/msgbox \
|
||||||
|
src/extra/widgets/spinbox \
|
||||||
|
src/extra/widgets/spinner \
|
||||||
|
src/extra/widgets/tabview \
|
||||||
|
src/extra/widgets/tileview \
|
||||||
|
src/extra/widgets/win
|
||||||
|
|
||||||
|
|
||||||
|
COMPONENT_ADD_INCLUDEDIRS := $(COMPONENT_SRCDIRS) .
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team using the [contact form](https://lvgl.io/about). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
# Coding style
|
||||||
|
|
||||||
|
## File format
|
||||||
|
Use [misc/lv_templ.c](https://github.com/lvgl/lvgl/blob/master/src/misc/lv_templ.c) and [misc/lv_templ.h](https://github.com/lvgl/lvgl/blob/master/src/misc/lv_templ.h)
|
||||||
|
|
||||||
|
## Naming conventions
|
||||||
|
* Words are separated by '_'
|
||||||
|
* In variable and function names use only lower case letters (e.g. *height_tmp*)
|
||||||
|
* In enums and defines use only upper case letters (e.g. *e.g. MAX_LINE_NUM*)
|
||||||
|
* Global names (API):
|
||||||
|
* start with *lv*
|
||||||
|
* followed by module name: *btn*, *label*, *style* etc.
|
||||||
|
* followed by the action (for functions): *set*, *get*, *refr* etc.
|
||||||
|
* closed with the subject: *name*, *size*, *state* etc.
|
||||||
|
* Typedefs
|
||||||
|
* prefer `typedef struct` and `typedef enum` instead of `struct name` and `enum name`
|
||||||
|
* always end `typedef struct` and `typedef enum` type names with `_t`
|
||||||
|
* Abbreviations:
|
||||||
|
* Only words longer or equal than 6 characters can be abbreviated.
|
||||||
|
* Abbreviate only if it makes the word at least half as long
|
||||||
|
* Use only very straightforward and well-known abbreviations (e.g. pos: position, def: default, btn: button)
|
||||||
|
|
||||||
|
## Coding guide
|
||||||
|
* Functions:
|
||||||
|
* Try to write function shorter than is 50 lines
|
||||||
|
* Always shorter than 200 lines (except very straightforwards)
|
||||||
|
* Variables:
|
||||||
|
* One line, one declaration (BAD: char x, y;)
|
||||||
|
* Use `<stdint.h>` (*uint8_t*, *int32_t* etc)
|
||||||
|
* Declare variables where needed (not all at function start)
|
||||||
|
* Use the smallest required scope
|
||||||
|
* Variables in a file (outside functions) are always *static*
|
||||||
|
* Do not use global variables (use functions to set/get static variables)
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
Before every function have a comment like this:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/**
|
||||||
|
* Return with the screen of an object
|
||||||
|
* @param obj pointer to an object
|
||||||
|
* @return pointer to a screen
|
||||||
|
*/
|
||||||
|
lv_obj_t * lv_obj_get_scr(lv_obj_t * obj);
|
||||||
|
```
|
||||||
|
|
||||||
|
Always use `/*Something*/` format and NOT `//Something`
|
||||||
|
|
||||||
|
Write readable code to avoid descriptive comments like:
|
||||||
|
`x++; /*Add 1 to x*/`.
|
||||||
|
The code should show clearly what you are doing.
|
||||||
|
|
||||||
|
You should write **why** have you done this:
|
||||||
|
`x++; /*Because of closing '\0' of the string*/`
|
||||||
|
|
||||||
|
Short "code summaries" of a few lines are accepted. E.g. `/*Calculate the new coordinates*/`
|
||||||
|
|
||||||
|
In comments use \` \` when referring to a variable. E.g. ``/*Update the value of `x_act`*/``
|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
Here is example to show bracket placing and using of white spaces:
|
||||||
|
```c
|
||||||
|
/**
|
||||||
|
* Set a new text for a label. Memory will be allocated to store the text by the label.
|
||||||
|
* @param label pointer to a label object
|
||||||
|
* @param text '\0' terminated character string. NULL to refresh with the 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 the command is inline with the 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 start inline*/
|
||||||
|
lv_label_refr_text(label);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Use 4 spaces indentation instead of tab.
|
||||||
|
|
||||||
|
You can use **astyle** to format the code. Run `code-formatter.sh` from the `scrips` folder.
|
||||||
|
|
||||||
|
#### pre-commit
|
||||||
|
|
||||||
|
[pre-commit](https://pre-commit.com/) is a multi-language package manager for pre-commit hooks.
|
||||||
|
See the [instalation guide](https://pre-commit.com/#installation) to get pre-commit python package
|
||||||
|
installed into your development machine.
|
||||||
|
|
||||||
|
Once you have `pre-commit` installed you will need to [set up the git hook scripts](https://pre-commit.com/#3-install-the-git-hook-scripts) with:
|
||||||
|
```console
|
||||||
|
pre-commit install
|
||||||
|
```
|
||||||
|
|
||||||
|
now `pre-commit` will run automatically on `git commit`!
|
||||||
|
|
||||||
|
##### Hooks
|
||||||
|
|
||||||
|
The `format-source` local hook (see `.pre-commit-config.yaml`) runs **astyle** on all the staged source and header
|
||||||
|
files (that are not excluded, see `exclude` key of the hook configuration) before entering the commit message,
|
||||||
|
if any file gets formatted by **astyle** you will need to add the change to the staging area and run `git commit` again.
|
||||||
|
|
||||||
|
The `trailing-whitespace` hook fixes trailing whitespaces on all of the files.
|
||||||
|
|
||||||
|
##### Skipping hooks
|
||||||
|
|
||||||
|
If you want to skip any particular hook you can do so with:
|
||||||
|
```console
|
||||||
|
SKIP=name-of-the-hook git commit
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Testing hooks
|
||||||
|
|
||||||
|
It's no necessary to do a commit to test the hooks, you can test hooks by adding the files into the staging area and run:
|
||||||
|
```console
|
||||||
|
pre-commit run name-of-the-hook
|
||||||
|
```
|
||||||
@@ -0,0 +1,296 @@
|
|||||||
|
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Join LVGL's community and leave your footprint in the library!
|
||||||
|
|
||||||
|
There are a lot of ways to contribute to LVGL even if you are new to the library or even new to programming.
|
||||||
|
|
||||||
|
It might be scary to make the first step but you have nothing to be afraid of.
|
||||||
|
A friendly and helpful community is waiting for you. Get to know like-minded people and make something great together.
|
||||||
|
|
||||||
|
So let's find which contribution option fits you the best and help you join the development of LVGL!
|
||||||
|
|
||||||
|
Before getting started here are some guidelines to make contribution smoother:
|
||||||
|
- Be kind and friendly.
|
||||||
|
- Be sure to read the relevant part of the documentation before posting a question.
|
||||||
|
- Ask questions in the [Forum](https://forum.lvgl.io/) and use [GitHub](https://github.com/lvgl/) for development-related discussions.
|
||||||
|
- Always fill out the post or issue templates in the Forum or GitHub (or at least provide equivalent information). It makes understanding your contribution or issue easier and you will get a useful response faster.
|
||||||
|
- If possible send an absolute minimal but buildable code example in order to reproduce the issue. Be sure it contains all the required variable declarations, constants, and assets (images, fonts).
|
||||||
|
- Use [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) to format your posts. You can learn it in 10 minutes.
|
||||||
|
- Speak about one thing in one issue or topic. It makes your post easier to find later for someone with the same question.
|
||||||
|
- Give feedback and close the issue or mark the topic as solved if your question is answered.
|
||||||
|
- For non-trivial fixes and features, it's better to open an issue first to discuss the details instead of sending a pull request directly.
|
||||||
|
- Please read and follow the <a href="https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md">Coding style</a> guide.
|
||||||
|
|
||||||
|
## Pull request
|
||||||
|
|
||||||
|
Merging new code into the lvgl, documentation, blog, examples, and other repositories happen via *Pull requests* (PR for short).
|
||||||
|
A PR is a notification like "Hey, I made some updates to your project. Here are the changes, you can add them if you want."
|
||||||
|
To do this you need a copy (called fork) of the original project under your account, make some changes there, and notify the original repository about your updates.
|
||||||
|
You can see what it looks like on GitHub for LVGL here: [https://github.com/lvgl/lvgl/pulls](https://github.com/lvgl/lvgl/pulls).
|
||||||
|
|
||||||
|
To add your changes you can edit files online on GitHub and send a new Pull request from there (recommended for small changes) or
|
||||||
|
add the updates in your favorite editor/IDE and use git to publish the changes (recommended for more complex updates).
|
||||||
|
|
||||||
|
### From GitHub
|
||||||
|
1. Navigate to the file you want to edit.
|
||||||
|
2. Click the Edit button in the top right-hand corner.
|
||||||
|
3. Add your changes to the file.
|
||||||
|
4. Add a commit message on the bottom of the page.
|
||||||
|
5. Click the *Propose changes* button.
|
||||||
|
|
||||||
|
### From command line
|
||||||
|
|
||||||
|
The instructions describe the main `lvgl` repository but it works the same way for the other repositories.
|
||||||
|
1. Fork the [lvgl repository](https://github.com/lvgl/lvgl). To do this click the "Fork" button in the top right corner.
|
||||||
|
It will "copy" the `lvgl` repository to your GitHub account (`https://github.com/<YOUR_NAME>?tab=repositories`)
|
||||||
|
2. Clone your forked repository.
|
||||||
|
3. Add your changes. You can create a *feature branch* from *master* for the updates: `git checkout -b the-new-feature`
|
||||||
|
4. Commit and push your changes to the forked `lvgl` repository.
|
||||||
|
5. Create a PR on GitHub from the page of your `lvgl` repository (`https://github.com/<YOUR_NAME>/lvgl`) by clicking the *"New pull request"* button. Don't forget to select the branch where you added your changes.
|
||||||
|
7. Set the base branch. It means where you want to merge your update. In the `lvgl` repo both the fixes and new features go to `master` branch.
|
||||||
|
8. Describe what is in the update. An example code is welcome if applicable.
|
||||||
|
9. If you need to make more changes, just update your forked `lvgl` repo with new commits. They will automatically appear in the PR.
|
||||||
|
|
||||||
|
### Commit message format
|
||||||
|
The commit messages format is inspired by [Angular Commit Format](https://gist.github.com/brianclements/841ea7bffdb01346392c).
|
||||||
|
|
||||||
|
The following structure should be used:
|
||||||
|
```
|
||||||
|
<type>(<scope>): <subject>
|
||||||
|
<BLANK LINE>
|
||||||
|
<body>
|
||||||
|
<BLANK LINE>
|
||||||
|
<footer>
|
||||||
|
```
|
||||||
|
|
||||||
|
Possible `<type>`s:
|
||||||
|
- `fix` bugfix in the source code.
|
||||||
|
- `feat` new feature
|
||||||
|
- `arch` architectural changes
|
||||||
|
- `perf` changes that affect the performance
|
||||||
|
- `example` anything related to examples (even fixes and new examples)
|
||||||
|
- `docs` anything related to the documentation (even fixes, formatting, and new pages)
|
||||||
|
- `test` anything related to tests (new and updated tests or CI actions)
|
||||||
|
- `chore` any minor formatting or style changes that would make the changelog noisy
|
||||||
|
|
||||||
|
`<scope>` is the module, file, or sub-system that is affected by the commit. It's usually one word and can be chosen freely.
|
||||||
|
For example `img`, `layout`, `txt`, `anim`. The scope can be omitted.
|
||||||
|
|
||||||
|
`<subject>` contains a short description of the change:
|
||||||
|
- use the imperative, present tense: "change" not "changed" nor "changes"
|
||||||
|
- don't capitalize the first letter
|
||||||
|
- no dot (.) at the end
|
||||||
|
- max 90 characters
|
||||||
|
|
||||||
|
`<body>` optional and can be used to describe the details of this change.
|
||||||
|
|
||||||
|
`<footer>` shall contain
|
||||||
|
- the words "BREAKING CHANGE" if the changes break the API
|
||||||
|
- reference to the GitHub issue or Pull Request if applicable.
|
||||||
|
|
||||||
|
Some examples:
|
||||||
|
```
|
||||||
|
fix(img): update size if a new source is set
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
fix(bar): fix memory leak
|
||||||
|
|
||||||
|
The animations weren't deleted in the destructor.
|
||||||
|
|
||||||
|
Fixes: #1234
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
feat: add span widget
|
||||||
|
|
||||||
|
The span widget allows mixing different font sizes, colors and styles.
|
||||||
|
It's similar to HTML <span>
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
docs(porting): fix typo
|
||||||
|
```
|
||||||
|
|
||||||
|
## Developer Certification of Origin (DCO)
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
|
||||||
|
To ensure all licensing criteria are met for every repository of the LVGL project, we apply a process called DCO (Developer's Certificate of Origin).
|
||||||
|
|
||||||
|
The text of DCO can be read here: [https://developercertificate.org/](https://developercertificate.org/).
|
||||||
|
|
||||||
|
By contributing to any repositories of the LVGL project you agree that your contribution complies with the DCO.
|
||||||
|
|
||||||
|
If your contribution fulfills the requirements of the DCO no further action is needed. If you are unsure feel free to ask us in a comment.
|
||||||
|
|
||||||
|
### Accepted licenses and copyright notices
|
||||||
|
|
||||||
|
To make the DCO easier to digest, here are some practical guides about specific cases:
|
||||||
|
|
||||||
|
#### Your own work
|
||||||
|
|
||||||
|
The simplest case is when the contribution is solely your own work.
|
||||||
|
In this case you can just send a Pull Request without worrying about any licensing issues.
|
||||||
|
|
||||||
|
#### Use code from online source
|
||||||
|
|
||||||
|
If the code you would like to add is based on an article, post or comment on a website (e.g. StackOverflow) the license and/or rules of that site should be followed.
|
||||||
|
|
||||||
|
For example in case of StackOverflow a notice like this can be used:
|
||||||
|
```
|
||||||
|
/* The original version of this code-snippet was published on StackOverflow.
|
||||||
|
* Post: http://stackoverflow.com/questions/12345
|
||||||
|
* Author: http://stackoverflow.com/users/12345/username
|
||||||
|
* The following parts of the snippet were changed:
|
||||||
|
* - Check this or that
|
||||||
|
* - Optimize performance here and there
|
||||||
|
*/
|
||||||
|
... code snippet here ...
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Use MIT licensed code
|
||||||
|
As LVGL is MIT licensed, other MIT licensed code can be integrated without issues.
|
||||||
|
The MIT license requires a copyright notice be added to the derived work. Any derivative work based on MIT licensed code must copy the original work's license file or text.
|
||||||
|
|
||||||
|
#### Use GPL licensed code
|
||||||
|
The GPL license is not compatible with the MIT license. Therefore, LVGL can not accept GPL licensed code.
|
||||||
|
|
||||||
|
## Ways to contribute
|
||||||
|
|
||||||
|
Even if you're just getting started with LVGL there are plenty of ways to get your feet wet.
|
||||||
|
Most of these options don't even require knowing a single line of LVGL code.
|
||||||
|
|
||||||
|
Below we have collected some opportunities about the ways you can contribute to LVGL.
|
||||||
|
|
||||||
|
### Give LVGL a Star
|
||||||
|
|
||||||
|
Show that you like LVGL by giving it star on GitHub!
|
||||||
|
<!-- Place this tag in your head or just before your close body tag. -->
|
||||||
|
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||||
|
<!-- Place this tag where you want the button to render. -->
|
||||||
|
<a class="github-button" href="https://github.com/lvgl/lvgl" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star lvgl/lvgl on GitHub">Star</a>
|
||||||
|
|
||||||
|
This simple click makes LVGL more visible on GitHub and makes it more attractive to other people.
|
||||||
|
So with this, you already helped a lot!
|
||||||
|
|
||||||
|
### Tell what you have achieved
|
||||||
|
|
||||||
|
Have you already started using LVGL in a [Simulator](/get-started/platforms/pc-simulator), a development board, or on your custom hardware?
|
||||||
|
Was it easy or were there some obstacles? Are you happy with the result?
|
||||||
|
Showing your project to others is a win-win situation because it increases your and LVGL's reputation at the same time.
|
||||||
|
|
||||||
|
You can post about your project on Twitter, Facebook, LinkedIn, create a YouTube video, and so on.
|
||||||
|
Only one thing: On social media don't forget to add a link to `https://lvgl.io` or `https://github.com/lvgl` and use the hashtag `#lvgl`. Thank you! :)
|
||||||
|
|
||||||
|
You can also open a new topic in the [My projects](https://forum.lvgl.io/c/my-projects/10) category of the Forum.
|
||||||
|
|
||||||
|
The [LVGL Blog](https://blog.lvgl.io) welcomes posts from anyone.
|
||||||
|
It's a good place to talk about a project you created with LVGL, write a tutorial, or share some nice tricks.
|
||||||
|
The latest blog posts are shown on the [homepage of LVGL](https://lvgl.io) to make your work more visible.
|
||||||
|
|
||||||
|
The blog is hosted on GitHub. If you add a post GitHub automatically turns it into a website.
|
||||||
|
See the [README](https://github.com/lvgl/blog) of the blog repo to see how to add your post.
|
||||||
|
|
||||||
|
Any of these help to spread the word and familiarize new developers with LVGL.
|
||||||
|
|
||||||
|
If you don't want to speak about your project publicly, feel free to use [Contact form](https://lvgl.io/#contact) on lvgl.io to private message to us.
|
||||||
|
|
||||||
|
### Write examples
|
||||||
|
As you learn LVGL you will probably play with the features of widgets. Why not publish your experiments?
|
||||||
|
|
||||||
|
Each widgets' documentation contains examples. For instance, here are the examples of the [Drop-down list](/widgets/core/dropdown#examples) widget.
|
||||||
|
The examples are directly loaded from the [lvgl/examples](https://github.com/lvgl/lvgl/tree/master/examples) folder.
|
||||||
|
|
||||||
|
So all you need to do is send a [Pull request](#pull-request) to the [lvgl](https://github.com/lvgl/lvgl) repository and follow some conventions:
|
||||||
|
- Name the examples like `lv_example_<widget_name>_<index>`.
|
||||||
|
- Make the example as short and simple as possible.
|
||||||
|
- Add comments to explain what the example does.
|
||||||
|
- Use 320x240 resolution.
|
||||||
|
- Update `index.rst` in the example's folder with your new example. To see how other examples are added, look in the [lvgl/examples/widgets](https://github.com/lvgl/lvgl/tree/master/examples/widgets) folder.
|
||||||
|
|
||||||
|
### Improve the docs
|
||||||
|
|
||||||
|
As you read the documentation you might see some typos or unclear sentences. All the documentation is located in the [lvgl/docs](https://github.com/lvgl/lvgl/tree/master/docs) folder.
|
||||||
|
For typos and straightforward fixes, you can simply edit the file on GitHub.
|
||||||
|
|
||||||
|
Note that the documentation is also formatted in [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
|
||||||
|
|
||||||
|
### Report bugs
|
||||||
|
As you use LVGL you might find bugs. Before reporting them be sure to check the relevant parts of the documentation.
|
||||||
|
|
||||||
|
If it really seems like a bug feel free to open an [issue on GitHub](https://github.com/lvgl/lvgl/issues).
|
||||||
|
|
||||||
|
When filing the issue be sure to fill out the template. It helps find the root of the problem while avoiding extensive questions and exchanges with other developers.
|
||||||
|
|
||||||
|
### Send fixes
|
||||||
|
The beauty of open-source software is you can easily dig in to it to understand how it works. You can also fix or adjust it as you wish.
|
||||||
|
|
||||||
|
If you found and fixed a bug don't hesitate to send a [Pull request](#pull-request) with the fix.
|
||||||
|
|
||||||
|
In your Pull request please also add a line to [`CHANGELOG.md`](https://github.com/lvgl/lvgl/blob/master/CHANGELOG.md).
|
||||||
|
|
||||||
|
### Join the conversations in the Forum
|
||||||
|
It feels great to know you are not alone if something is not working. It's even better to help others when they struggle with something.
|
||||||
|
|
||||||
|
While you were learning LVGL you might have had questions and used the Forum to get answers. As a result, you probably have more knowledge about how LVGL works.
|
||||||
|
|
||||||
|
One of the best ways to give back is to use the Forum and answer the questions of newcomers - like you were once.
|
||||||
|
|
||||||
|
Just read the titles and if you are familiar with the topic don't hesitate to share your thoughts and suggestions.
|
||||||
|
|
||||||
|
Participating in the discussions is one of the best ways to become part of the project and get to know like-minded people!
|
||||||
|
|
||||||
|
### Add features
|
||||||
|
If you have created a cool widget, or added useful feature to LVGL feel free to open a new PR for it.
|
||||||
|
We collect the optional features (a.k.a. plugins) in [lvgl/src/extra](https://github.com/lvgl/lvgl/tree/master/src/extra) folder so if you are interested in adding a new features please use this folder.
|
||||||
|
The [README](https://github.com/lvgl/lvgl/blob/master/src/extra/README.md) file describes the basics rules of contribution and also lists some ideas.
|
||||||
|
|
||||||
|
For further ideas take a look at the [Roadmap](/ROADMAP) page. If you are interested in any of them feel free to share your opinion and/or participate in the implementation.
|
||||||
|
|
||||||
|
Other features which are (still) not on the road map are listed in the [Feature request](https://forum.lvgl.io/c/feature-request/9) category of the Forum.
|
||||||
|
|
||||||
|
When adding a new features the followings also needs to be updated:
|
||||||
|
- Update [lv_conf_template.h](https://github.com/lvgl/lvgl/blob/master/lv_conf_template.h)
|
||||||
|
- Add description in the [docs](https://github.com/lvgl/lvgl/tree/master/docs)
|
||||||
|
- Add [examples](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||||
|
- Update the [changelog](https://github.com/lvgl/lvgl/tree/master/docs/CHANGELOG.md)
|
||||||
|
|
||||||
|
### Become a maintainer
|
||||||
|
|
||||||
|
If you want to become part of the core development team, you can become a maintainer of a repository.
|
||||||
|
|
||||||
|
By becoming a maintainer:
|
||||||
|
- You get write access to that repo:
|
||||||
|
- Add code directly without sending a pull request
|
||||||
|
- Accept pull requests
|
||||||
|
- Close/reopen/edit issues
|
||||||
|
- Your input has higher impact when we are making decisions
|
||||||
|
|
||||||
|
You can become a maintainer by invitation, however the following conditions need to met
|
||||||
|
1. Have > 50 replies in the Forum. You can look at your stats [here](https://forum.lvgl.io/u?period=all)
|
||||||
|
2. Send > 5 non-trivial pull requests to the repo where you would like to be a maintainer
|
||||||
|
|
||||||
|
|
||||||
|
If you are interested, just send a message (e.g. from the Forum) to the current maintainers of the repository. They will check if the prerequisites are met.
|
||||||
|
Note that meeting the prerequisites is not a guarantee of acceptance, i.e. if the conditions are met you won't automatically become a maintainer.
|
||||||
|
It's up to the current maintainers to make the decision.
|
||||||
|
|
||||||
|
### Move your project repository under LVGL organization
|
||||||
|
Besides the core `lvgl` repository there are other repos for ports to development boards, IDEs or other environment.
|
||||||
|
If you ported LVGL to a new platform we can host it under the LVGL organization among the other repos.
|
||||||
|
|
||||||
|
This way your project will become part of the whole LVGL project and can get more visibility.
|
||||||
|
If you are interested in this opportunity just open an [issue in lvgl repo](https://github.com/lvgl/lvgl/issues) and tell what you have!
|
||||||
|
|
||||||
|
If we agree that your port fit well into the LVGL organization, we will open a repository for your project where you will have admin rights.
|
||||||
|
|
||||||
|
To make this concept sustainable there a few rules to follow:
|
||||||
|
- You need to add a README to your repo.
|
||||||
|
- We expect to maintain the repo to some extent:
|
||||||
|
- Follow at least the major versions of LVGL
|
||||||
|
- Respond to the issues (in a reasonable time)
|
||||||
|
- If there is no activity in a repo for 1 year it will be archived
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Roadmap
|
||||||
|
|
||||||
|
This is a summary for planned new features and a collection of ideas.
|
||||||
|
This list indicates only the current intention and it can be changed.
|
||||||
|
|
||||||
|
## v8.2
|
||||||
|
See [#2790](https://github.com/lvgl/lvgl/issues/2790)
|
||||||
|
|
||||||
|
## Ideas
|
||||||
|
- Reconsider color format management for run time color format setting, and custom color format usage. (Also [RGB888](https://github.com/lvgl/lvgl/issues/1722))
|
||||||
|
- Make gradients more versatile
|
||||||
|
- Image transformations matrix
|
||||||
|
- Switch to RGBA colors in styles
|
||||||
|
- Consider direct binary font format support
|
||||||
|
- Simplify `group`s. Discussion is [here](https://forum.lvgl.io/t/lv-group-tabindex/2927/3).
|
||||||
|
- lv_mem_alloc_aligned(size, align)
|
||||||
|
- Text node. See [#1701](https://github.com/lvgl/lvgl/issues/1701#issuecomment-699479408)
|
||||||
|
- CPP binding. See [Forum](https://forum.lvgl.io/t/is-it-possible-to-officially-support-optional-cpp-api/2736)
|
||||||
|
- Optimize font decompression
|
||||||
|
- Need static analyze (via coverity.io or something else)
|
||||||
|
- Support dot_begin and dot_middle long modes for labels
|
||||||
|
- Add new label alignment modes. [#1656](https://github.com/lvgl/lvgl/issues/1656)
|
||||||
|
- Support larger images: [#1892](https://github.com/lvgl/lvgl/issues/1892)
|
||||||
|
- Curved text on path
|
||||||
|
- Variable binding improvements like Redux?
|
||||||
|
- Functional programming support, pure view? See [here](https://www.freecodecamp.org/news/the-revolution-of-pure-views-aed339db7da4/)
|
||||||
|
- Circle layout. See [#2871](https://github.com/lvgl/lvgl/issues/2871)
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from docutils import nodes
|
||||||
|
from docutils.parsers.rst import Directive, directives
|
||||||
|
from docutils.parsers.rst.directives.images import Image
|
||||||
|
from sphinx.directives.code import LiteralInclude
|
||||||
|
|
||||||
|
|
||||||
|
def excluded_list(argument):
|
||||||
|
return argument.split(',')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class LvExample(Directive):
|
||||||
|
required_arguments = 1
|
||||||
|
option_spec = {
|
||||||
|
'excluded_languages': excluded_list,
|
||||||
|
'language': directives.unchanged,
|
||||||
|
'description': directives.unchanged
|
||||||
|
}
|
||||||
|
def get_example_code_path(self, example_path, language):
|
||||||
|
return os.path.abspath("../examples/" + example_path + "." + language)
|
||||||
|
def human_language_name(self, language):
|
||||||
|
if language == 'py':
|
||||||
|
return 'MicroPython'
|
||||||
|
elif language == 'c':
|
||||||
|
return 'C'
|
||||||
|
else:
|
||||||
|
return language
|
||||||
|
def github_path(self, example_path, language):
|
||||||
|
env = self.state.document.settings.env
|
||||||
|
return f"https://github.com/lvgl/lvgl/blob/{env.config.repo_commit_hash}/examples/{example_path}.{language}"
|
||||||
|
def embed_code(self, example_file, example_path, language, buttons={}):
|
||||||
|
toggle = nodes.container('', literal_block=False, classes=['toggle'])
|
||||||
|
header = nodes.container('', literal_block=False, classes=['header'])
|
||||||
|
toggle.append(header)
|
||||||
|
try:
|
||||||
|
with open(example_file) as f:
|
||||||
|
contents = f.read()
|
||||||
|
except FileNotFoundError:
|
||||||
|
contents = 'Error encountered while trying to open ' + example_file
|
||||||
|
literal_list = nodes.literal_block(contents, contents)
|
||||||
|
literal_list['language'] = language
|
||||||
|
toggle.append(literal_list)
|
||||||
|
paragraph_node = nodes.raw(text=f"<p>{self.human_language_name(language)} code </p>", format='html')
|
||||||
|
for text, url in buttons.items():
|
||||||
|
paragraph_node.append(nodes.raw(text=f"<a class='lv-example-link-button' onclick=\"event.stopPropagation();\" href='{url}'>{text}</a>", format='html'))
|
||||||
|
header.append(paragraph_node)
|
||||||
|
return toggle
|
||||||
|
def run(self):
|
||||||
|
example_path = self.arguments[0]
|
||||||
|
example_name = os.path.split(example_path)[1]
|
||||||
|
excluded_languages = self.options.get('excluded_languages', [])
|
||||||
|
node_list = []
|
||||||
|
|
||||||
|
env = self.state.document.settings.env
|
||||||
|
|
||||||
|
iframe_html = ""
|
||||||
|
|
||||||
|
c_path = self.get_example_code_path(example_path, 'c')
|
||||||
|
py_path = self.get_example_code_path(example_path, 'py')
|
||||||
|
|
||||||
|
c_code = self.embed_code(c_path, example_path, 'c', buttons={
|
||||||
|
'<i class="fa fa-github"></i> GitHub': self.github_path(example_path, 'c')
|
||||||
|
})
|
||||||
|
py_code = self.embed_code(py_path, example_path, 'py', buttons={
|
||||||
|
'<i class="fa fa-github"></i> GitHub': self.github_path(example_path, 'py'),
|
||||||
|
'<i class="fa fa-play"></i> Simulator': f"https://sim.lvgl.io/v{env.config.version}/micropython/ports/javascript/index.html?script_startup=https://raw.githubusercontent.com/lvgl/lvgl/{env.config.repo_commit_hash}/examples/header.py&script=https://raw.githubusercontent.com/lvgl/lvgl/{env.config.repo_commit_hash}/examples/{example_path}.py"
|
||||||
|
})
|
||||||
|
|
||||||
|
if not 'c' in excluded_languages:
|
||||||
|
if env.app.tags.has('html'):
|
||||||
|
iframe_html = f"<div class='lv-example' data-real-src='/{env.config.version}/_static/built_lv_examples/index.html?example={example_name}&w=320&h=240'></div>"
|
||||||
|
|
||||||
|
description_html = f"<div class='lv-example-description'>{self.options.get('description', '')}</div>"
|
||||||
|
layout_node = nodes.raw(text=f"<div class='lv-example-container'>{iframe_html}{description_html}</div>", format='html')
|
||||||
|
|
||||||
|
node_list.append(layout_node)
|
||||||
|
if not 'c' in excluded_languages:
|
||||||
|
node_list.append(c_code)
|
||||||
|
if not 'py' in excluded_languages:
|
||||||
|
node_list.append(py_code)
|
||||||
|
|
||||||
|
trailing_node = nodes.raw(text=f"<hr/>", format='html')
|
||||||
|
node_list.append(trailing_node)
|
||||||
|
|
||||||
|
return node_list
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.add_directive("lv_example", LvExample)
|
||||||
|
app.add_config_value("repo_commit_hash", "", "env")
|
||||||
|
|
||||||
|
return {
|
||||||
|
'version': '0.1',
|
||||||
|
'parallel_read_safe': True,
|
||||||
|
'parallel_write_safe': True,
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
table, th, td {
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
span.pre
|
||||||
|
{
|
||||||
|
padding-right:8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.pre:first-child
|
||||||
|
{
|
||||||
|
padding-right:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
code.sig-name
|
||||||
|
{
|
||||||
|
/*margin-left:8px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle .header {
|
||||||
|
display: block;
|
||||||
|
clear: both;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle .header:before {
|
||||||
|
font-family: FontAwesome, "Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;
|
||||||
|
content: "\f0da \00a0 Show ";
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle .header.open:before {
|
||||||
|
content: "\f0d7 \00a0 Hide ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.header p {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.1em;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-side-nav-search {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.wy-side-nav-search>div.version {
|
||||||
|
color: #333;
|
||||||
|
display: none; /*replaced by dropdown*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.home-img {
|
||||||
|
width:32%;
|
||||||
|
transition: transform .3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-img:hover {
|
||||||
|
transform: translate(0, -10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Let `code` wrap*/
|
||||||
|
.rst-content code, .rst-content tt, code {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lv-example, .lv-example > iframe {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
padding: none;
|
||||||
|
display: block;
|
||||||
|
width: 320px;
|
||||||
|
height: 240px;
|
||||||
|
flex: none;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lv-example > iframe {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lv-example-container {
|
||||||
|
display: flex;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
.lv-example-description {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lv-example-link-button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #2980b9;
|
||||||
|
color: white;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
.lv-example-link-button:hover {
|
||||||
|
color: white;
|
||||||
|
filter: brightness(120%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lv-example-link-button:visited {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.cpp.unexpanded dd {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lv-api-expansion-button {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
.lv-api-expansion-button::before {
|
||||||
|
font-family: FontAwesome, "Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.1em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.unexpanded .lv-api-expansion-button::before {
|
||||||
|
content: "\f0da \00a0";
|
||||||
|
}
|
||||||
|
.expanded .lv-api-expansion-button::before {
|
||||||
|
content: "\f0d7 \00a0";
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 186 KiB |
@@ -0,0 +1,18 @@
|
|||||||
|
/* API collapsing */
|
||||||
|
document.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
document.querySelectorAll("dl.cpp").forEach(cppListing => {
|
||||||
|
const dt = cppListing.querySelector("dt");
|
||||||
|
let shouldBeExpanded = false;
|
||||||
|
if(dt.id == document.location.hash.substring(1))
|
||||||
|
shouldBeExpanded = true;
|
||||||
|
cppListing.classList.add(shouldBeExpanded ? "expanded" : "unexpanded");
|
||||||
|
const button = document.createElement("span");
|
||||||
|
button.classList.add("lv-api-expansion-button");
|
||||||
|
button.addEventListener("click", () => {
|
||||||
|
cppListing.classList.toggle("unexpanded");
|
||||||
|
cppListing.classList.toggle("expanded");
|
||||||
|
});
|
||||||
|
|
||||||
|
dt.insertBefore(button, dt.firstChild);
|
||||||
|
});
|
||||||
|
})
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{% extends "!layout.html" %}
|
||||||
|
|
||||||
|
{%- block extrahead %}
|
||||||
|
{{ super() }}
|
||||||
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-78811084-3"></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){dataLayer.push(arguments);}
|
||||||
|
gtag('js', new Date());
|
||||||
|
|
||||||
|
gtag('config', 'UA-78811084-3', { 'anonymize_ip': true });
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block footer %}
|
||||||
|
{{ super() }}
|
||||||
|
<div class="footer">This page uses <a href="https://analytics.google.com/">
|
||||||
|
Google Analytics</a> to collect statistics. You can disable it by blocking
|
||||||
|
the JavaScript coming from www.google-analytics.com.
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function() {
|
||||||
|
var ga = document.createElement('script');
|
||||||
|
ga.src = ('https:' == document.location.protocol ?
|
||||||
|
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||||
|
ga.setAttribute('async', 'true');
|
||||||
|
document.documentElement.firstChild.appendChild(ga);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
{% extends "!page.html" %}
|
||||||
|
|
||||||
|
{% block footer %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wy-side-nav-search > div[role="search"] {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$(".toggle > *").hide();
|
||||||
|
$(".toggle .header").show();
|
||||||
|
$(".toggle .header").click(function() {
|
||||||
|
$(this).parent().children().not(".header").toggle(400);
|
||||||
|
$(this).parent().children(".header").toggleClass("open");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function add_version_selector()
|
||||||
|
{
|
||||||
|
return fetch("https://raw.githubusercontent.com/lvgl/docs_compiled/gh-pages/versionlist.txt")
|
||||||
|
.then(res => res.text())
|
||||||
|
.then(text => {
|
||||||
|
const versions = text.split("\n").filter(version => version.trim().length > 0);
|
||||||
|
let p = document.getElementById("rtd-search-form").parentElement;
|
||||||
|
p.innerHTML = `
|
||||||
|
<select name="versions" id="versions" onchange="ver_sel()" style="border-radius:5px; margin-bottom:15px">
|
||||||
|
${versions.map(version => {
|
||||||
|
let versionName = "";
|
||||||
|
if(version == "master") versionName = "master (latest)";
|
||||||
|
else versionName = "v" + ((version.indexOf(".") != -1) ? version : (version + " (latest minor)"));
|
||||||
|
return `<option value="${version}">${versionName}</option>`;
|
||||||
|
})}
|
||||||
|
</select>` + p.innerHTML;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function ver_sel()
|
||||||
|
{
|
||||||
|
var x = document.getElementById("versions").value;
|
||||||
|
window.location.href = window.location.protocol + "//" + window.location.host + "/" + x + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
add_version_selector().then(() => {
|
||||||
|
var value = window.location.pathname.split('/')[1];
|
||||||
|
document.getElementById("versions").value = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
|
document.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
function onIntersection(entries) {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
let currentlyLoaded = entry.target.getAttribute("data-is-loaded") == "true";
|
||||||
|
let shouldBeLoaded = entry.intersectionRatio > 0;
|
||||||
|
if(currentlyLoaded != shouldBeLoaded) {
|
||||||
|
entry.target.setAttribute("data-is-loaded", shouldBeLoaded);
|
||||||
|
if(shouldBeLoaded) {
|
||||||
|
let iframe = document.createElement("iframe");
|
||||||
|
iframe.src = entry.target.getAttribute("data-real-src");
|
||||||
|
entry.target.appendChild(iframe);
|
||||||
|
} else {
|
||||||
|
let iframe = entry.target.querySelector("iframe");
|
||||||
|
iframe.parentNode.removeChild(iframe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const config = {
|
||||||
|
rootMargin: '600px 0px',
|
||||||
|
threshold: 0.01
|
||||||
|
};
|
||||||
|
let observer = new IntersectionObserver(onIntersection, config);
|
||||||
|
document.querySelectorAll(".lv-example").forEach(iframe => {
|
||||||
|
observer.observe(iframe);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import re
|
||||||
|
import example_list as ex
|
||||||
|
|
||||||
|
langs = ['en']
|
||||||
|
|
||||||
|
# Change to script directory for consistency
|
||||||
|
abspath = os.path.abspath(__file__)
|
||||||
|
dname = os.path.dirname(abspath)
|
||||||
|
os.chdir(dname)
|
||||||
|
|
||||||
|
def cmd(s):
|
||||||
|
print("")
|
||||||
|
print(s)
|
||||||
|
print("-------------------------------------")
|
||||||
|
r = os.system(s)
|
||||||
|
if r != 0:
|
||||||
|
print("Exit build due to previous error")
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
# Get the current branch name
|
||||||
|
status, br = subprocess.getstatusoutput("git branch | grep '*'")
|
||||||
|
_, gitcommit = subprocess.getstatusoutput("git rev-parse HEAD")
|
||||||
|
br = re.sub('\* ', '', br)
|
||||||
|
|
||||||
|
# Generate the list of examples
|
||||||
|
ex.exec()
|
||||||
|
|
||||||
|
urlpath = re.sub('release/', '', br)
|
||||||
|
|
||||||
|
os.environ['LVGL_URLPATH'] = urlpath
|
||||||
|
os.environ['LVGL_GITCOMMIT'] = gitcommit
|
||||||
|
|
||||||
|
clean = 0
|
||||||
|
trans = 0
|
||||||
|
skip_latex = False
|
||||||
|
args = sys.argv[1:]
|
||||||
|
if len(args) >= 1:
|
||||||
|
if "clean" in args: clean = 1
|
||||||
|
if "skip_latex" in args: skip_latex = True
|
||||||
|
|
||||||
|
lang = "en"
|
||||||
|
print("")
|
||||||
|
print("****************")
|
||||||
|
print("Building")
|
||||||
|
print("****************")
|
||||||
|
if clean:
|
||||||
|
cmd("rm -rf " + lang)
|
||||||
|
cmd("mkdir " + lang)
|
||||||
|
|
||||||
|
|
||||||
|
print("Running doxygen")
|
||||||
|
cmd("cd ../scripts && doxygen Doxyfile")
|
||||||
|
# BUILD PDF
|
||||||
|
|
||||||
|
if not skip_latex:
|
||||||
|
# Silly workaround to include the more or less correct PDF download link in the PDF
|
||||||
|
#cmd("cp -f " + lang +"/latex/LVGL.pdf LVGL.pdf | true")
|
||||||
|
cmd("sphinx-build -b latex . out_latex")
|
||||||
|
|
||||||
|
# Generate PDF
|
||||||
|
cmd("cd out_latex && latexmk -pdf 'LVGL.tex'")
|
||||||
|
# Copy the result PDF to the main directory to make it available for the HTML build
|
||||||
|
cmd("cd out_latex && cp -f LVGL.pdf ../LVGL.pdf")
|
||||||
|
else:
|
||||||
|
print("skipping latex build as requested")
|
||||||
|
|
||||||
|
# BUILD HTML
|
||||||
|
cmd("sphinx-build -b html . ../out_html")
|
||||||
|
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# LVGL documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Wed Jun 12 16:38:40 2019.
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its
|
||||||
|
# containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.abspath('./_ext'))
|
||||||
|
|
||||||
|
from subprocess import PIPE, Popen
|
||||||
|
|
||||||
|
import recommonmark
|
||||||
|
from recommonmark.transform import AutoStructify
|
||||||
|
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||||
|
|
||||||
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
#
|
||||||
|
# needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = ['sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
|
'sphinx.ext.todo',
|
||||||
|
'recommonmark',
|
||||||
|
'sphinx_markdown_tables',
|
||||||
|
'breathe',
|
||||||
|
'sphinx_sitemap',
|
||||||
|
'lv_example'
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The default language to highlight source code in. The default is 'python'.
|
||||||
|
# The value should be a valid Pygments lexer name, see Showing code examples for more details.
|
||||||
|
|
||||||
|
|
||||||
|
highlight_language = 'c'
|
||||||
|
|
||||||
|
# The suffix(es) of source filenames.
|
||||||
|
# You can specify multiple suffix as a list of string:
|
||||||
|
#
|
||||||
|
source_suffix = ['.rst', '.md']
|
||||||
|
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = 'LVGL'
|
||||||
|
copyright = '2021, LVGL Kft'
|
||||||
|
author = 'LVGL community'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The short X.Y version.
|
||||||
|
# embeddedt: extract using scripts/find_version.sh
|
||||||
|
|
||||||
|
version = subprocess.run(["../scripts/find_version.sh"], capture_output=True).stdout.decode("utf-8").strip()
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#
|
||||||
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
|
# Usually you set "language" from the command line for these cases.
|
||||||
|
language = None
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This patterns also effect to html_static_path and html_extra_path
|
||||||
|
exclude_patterns = ['_build', 'doxygen_html', 'Thumbs.db', '.DS_Store',
|
||||||
|
'README.md', 'lv_examples', 'out_html', 'env' ]
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
#
|
||||||
|
html_theme_options = {
|
||||||
|
'collapse_navigation' : False,
|
||||||
|
'logo_only': True,
|
||||||
|
}
|
||||||
|
# For site map generation
|
||||||
|
html_baseurl = f"https://docs.lvgl.io/{os.environ['LVGL_URLPATH']}/en/html/"
|
||||||
|
|
||||||
|
sitemap_url_scheme = "{link}"
|
||||||
|
|
||||||
|
#lvgl_github_url = f"https://github.com/lvgl/lvgl/blob/{os.environ['LVGL_GITCOMMIT']}/docs"
|
||||||
|
|
||||||
|
#extlinks = {'github_link_base': (github_url + '%s', github_url)}
|
||||||
|
|
||||||
|
html_context = {
|
||||||
|
'github_version': os.environ['LVGL_GITCOMMIT'],
|
||||||
|
'github_user': 'lvgl',
|
||||||
|
'github_repo': 'lvgl',
|
||||||
|
'display_github': True,
|
||||||
|
'conf_py_path': '/docs/'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Custom sidebar templates, must be a dictionary that maps document names
|
||||||
|
# to template names.
|
||||||
|
#
|
||||||
|
# This is required for the alabaster theme
|
||||||
|
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
|
||||||
|
html_sidebars = {
|
||||||
|
'**': [
|
||||||
|
'relations.html', # needs 'show_related': True theme option to display
|
||||||
|
'searchbox.html',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
html_js_files = [
|
||||||
|
'js/custom.js'
|
||||||
|
]
|
||||||
|
|
||||||
|
html_favicon = 'favicon.png'
|
||||||
|
html_logo = 'logo_lvgl.png'
|
||||||
|
|
||||||
|
# -- Options for HTMLHelp output ------------------------------------------
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'LVGLdoc'
|
||||||
|
|
||||||
|
html_last_updated_fmt = ''
|
||||||
|
|
||||||
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
|
latex_engine = 'xelatex'
|
||||||
|
latex_use_xindy = False
|
||||||
|
latex_elements = {
|
||||||
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
|
#
|
||||||
|
# 'papersize': 'letterpaper',
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
#
|
||||||
|
# 'pointsize': '10pt',
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#
|
||||||
|
# 'preamble': '',
|
||||||
|
|
||||||
|
# Latex figure (float) alignment
|
||||||
|
#
|
||||||
|
# 'figure_align': 'htbp',
|
||||||
|
|
||||||
|
'inputenc': '',
|
||||||
|
'utf8extra': '',
|
||||||
|
'classoptions': ',openany,oneside',
|
||||||
|
'babel': '\\usepackage{babel}',
|
||||||
|
'passoptionstopackages': r'''
|
||||||
|
\PassOptionsToPackage{bookmarksdepth=5}{hyperref}% depth of pdf bookmarks
|
||||||
|
''',
|
||||||
|
'preamble': r'''
|
||||||
|
\usepackage{fontspec}
|
||||||
|
\setmonofont{DejaVu Sans Mono}
|
||||||
|
\usepackage{silence}
|
||||||
|
\WarningsOff*
|
||||||
|
''',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title,
|
||||||
|
# author, documentclass [howto, manual, or own class]).
|
||||||
|
latex_documents = [
|
||||||
|
(master_doc, 'LVGL.tex', 'LVGL Documentation ' + version,
|
||||||
|
'LVGL community', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for manual page output ---------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
(master_doc, 'lvgl', 'LVGL Documentation ' + version,
|
||||||
|
[author], 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Texinfo output -------------------------------------------
|
||||||
|
|
||||||
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
|
# (source start file, target name, title, author,
|
||||||
|
# dir menu entry, description, category)
|
||||||
|
texinfo_documents = [
|
||||||
|
(master_doc, 'LVGL', 'LVGL Documentation ' + version,
|
||||||
|
author, 'Contributors of LVGL', 'One line description of project.',
|
||||||
|
'Miscellaneous'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
breathe_projects = {
|
||||||
|
"lvgl":"xml/",
|
||||||
|
}
|
||||||
|
|
||||||
|
StandaloneHTMLBuilder.supported_image_types = [
|
||||||
|
'image/svg+xml',
|
||||||
|
'image/gif', #prefer gif over png
|
||||||
|
'image/png',
|
||||||
|
'image/jpeg'
|
||||||
|
]
|
||||||
|
|
||||||
|
smartquotes = False
|
||||||
|
|
||||||
|
_, repo_commit_hash = subprocess.getstatusoutput("git rev-parse HEAD")
|
||||||
|
|
||||||
|
|
||||||
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.add_config_value('recommonmark_config', {
|
||||||
|
'enable_eval_rst': True,
|
||||||
|
'enable_auto_toc_tree': 'True',
|
||||||
|
}, True)
|
||||||
|
app.add_transform(AutoStructify)
|
||||||
|
app.add_css_file('css/custom.css')
|
||||||
|
app.add_css_file('css/fontawesome.min.css')
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def process_index_rst(path):
|
||||||
|
# print(path)
|
||||||
|
with open(path) as fp:
|
||||||
|
last_line=""
|
||||||
|
line=""
|
||||||
|
title_tmp=""
|
||||||
|
line = fp.readline()
|
||||||
|
d = {}
|
||||||
|
while line:
|
||||||
|
if line[0:3] == '"""':
|
||||||
|
title_tmp = last_line
|
||||||
|
elif line[0:15] ==".. lv_example::":
|
||||||
|
name = line[16:].strip()
|
||||||
|
title_tmp = title_tmp.strip()
|
||||||
|
d[name] = title_tmp
|
||||||
|
last_line = line
|
||||||
|
line = fp.readline()
|
||||||
|
|
||||||
|
return(d)
|
||||||
|
|
||||||
|
h1= {
|
||||||
|
"get_started":"Get started",
|
||||||
|
"styles":"Styles",
|
||||||
|
"anim":"Animations",
|
||||||
|
"event":"Events",
|
||||||
|
"layouts":"Layouts",
|
||||||
|
"scroll":"Scrolling",
|
||||||
|
"widgets":"Widgets"
|
||||||
|
}
|
||||||
|
|
||||||
|
widgets = {
|
||||||
|
"obj":"Base object",
|
||||||
|
"arc":"Arc",
|
||||||
|
"bar":"Bar",
|
||||||
|
"btn":"Button",
|
||||||
|
"btnmatrix":"Button matrix",
|
||||||
|
"calendar":"Calendar",
|
||||||
|
"canvas":"Canvas",
|
||||||
|
"chart":"Chart",
|
||||||
|
"checkbox":"Checkbox",
|
||||||
|
"colorwheel":"Colorwheel",
|
||||||
|
"dropdown":"Dropdown",
|
||||||
|
"img":"Image",
|
||||||
|
"imgbtn":"Image button",
|
||||||
|
"keyboard":"Keyboard",
|
||||||
|
"label":"Label",
|
||||||
|
"led":"LED",
|
||||||
|
"line":"Line",
|
||||||
|
"list":"List",
|
||||||
|
"menu":"Menu",
|
||||||
|
"meter":"Meter",
|
||||||
|
"msgbox":"Message box",
|
||||||
|
"roller":"Roller",
|
||||||
|
"slider":"Slider",
|
||||||
|
"span":"Span",
|
||||||
|
"spinbox":"Spinbox",
|
||||||
|
"spinner":"Spinner",
|
||||||
|
"switch":"Switch",
|
||||||
|
"table":"Table",
|
||||||
|
"tabview":"Tabview",
|
||||||
|
"textarea":"Textarea",
|
||||||
|
"tileview":"Tabview",
|
||||||
|
"win":"Window",
|
||||||
|
}
|
||||||
|
|
||||||
|
layouts = {
|
||||||
|
"flex":"Flex",
|
||||||
|
"grid":"Grid",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def print_item(path, lvl, d, fout):
|
||||||
|
for k in d:
|
||||||
|
v = d[k]
|
||||||
|
if k.startswith(path + "/lv_example_"):
|
||||||
|
fout.write("#"*lvl + " " + v + "\n")
|
||||||
|
fout.write('```eval_rst\n')
|
||||||
|
fout.write(f".. lv_example:: {k}\n")
|
||||||
|
fout.write('```\n')
|
||||||
|
fout.write("\n")
|
||||||
|
|
||||||
|
def exec():
|
||||||
|
paths = [ "../examples/", "../demos/"]
|
||||||
|
fout = open("examples.md", "w")
|
||||||
|
filelist = []
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
for root, dirs, files in os.walk(path):
|
||||||
|
for f in files:
|
||||||
|
#append the file name to the list
|
||||||
|
filelist.append(os.path.join(root,f))
|
||||||
|
|
||||||
|
filelist = [ fi for fi in filelist if fi.endswith("index.rst") ]
|
||||||
|
|
||||||
|
d_all = {}
|
||||||
|
#print all the file names
|
||||||
|
for fn in filelist:
|
||||||
|
d_act = process_index_rst(fn)
|
||||||
|
d_all.update(d_act)
|
||||||
|
|
||||||
|
fout.write("```eval_rst\n")
|
||||||
|
fout.write(":github_url: |github_link_base|/examples.md\n")
|
||||||
|
fout.write("```\n")
|
||||||
|
fout.write("\n")
|
||||||
|
fout.write("# Examples\n")
|
||||||
|
|
||||||
|
for h in h1:
|
||||||
|
fout.write("## " + h1[h] + "\n")
|
||||||
|
|
||||||
|
if h == "widgets":
|
||||||
|
for w in widgets:
|
||||||
|
fout.write("### " + widgets[w] + "\n")
|
||||||
|
print_item(h + "/" + w, 4, d_all, fout)
|
||||||
|
elif h == "layouts":
|
||||||
|
for l in layouts:
|
||||||
|
fout.write("### " + layouts[l] + "\n")
|
||||||
|
print_item(h + "/" + l, 4, d_all, fout)
|
||||||
|
else:
|
||||||
|
print_item(h, 3, d_all, fout)
|
||||||
|
|
||||||
|
fout.write("")
|
||||||
|
After Width: | Height: | Size: 533 B |
@@ -0,0 +1,4 @@
|
|||||||
|
# Cpp
|
||||||
|
|
||||||
|
In progress: https://github.com/lvgl/lv_binding_cpp
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Bindings
|
||||||
|
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
micropython
|
||||||
|
cpp
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
# Micropython
|
||||||
|
|
||||||
|
## What is Micropython?
|
||||||
|
|
||||||
|
[Micropython](http://micropython.org/) is Python for microcontrollers.
|
||||||
|
Using Micropython, you can write Python3 code and run it even on a bare metal architecture with limited resources.
|
||||||
|
|
||||||
|
### Highlights of Micropython
|
||||||
|
|
||||||
|
- **Compact** - Fits and runs within just 256k of code space and 16k of RAM. No OS is needed, although you can also run it with an OS, if you want.
|
||||||
|
- **Compatible** - Strives to be as compatible as possible with normal Python (known as CPython).
|
||||||
|
- **Versatile** - Supports many architectures (x86, x86-64, ARM, ARM Thumb, Xtensa).
|
||||||
|
- **Interactive** - No need for the compile-flash-boot cycle. With the REPL (interactive prompt) you can type commands and execute them immediately, run scripts, etc.
|
||||||
|
- **Popular** - Many platforms are supported. The user base is growing bigger. Notable forks: [MicroPython](https://github.com/micropython/micropython), [CircuitPython](https://github.com/adafruit/circuitpython), [MicroPython_ESP32_psRAM_LoBo](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo)
|
||||||
|
- **Embedded Oriented** - Comes with modules specifically for embedded systems, such as the [machine module](https://docs.micropython.org/en/latest/library/machine.html#classes) for accessing low-level hardware (I/O pins, ADC, UART, SPI, I2C, RTC, Timers etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Why Micropython + LVGL?
|
||||||
|
|
||||||
|
Currently, Micropython [does not have a good high-level GUI library](https://forum.micropython.org/viewtopic.php?f=18&t=5543) by default. LVGL is an [Object-Oriented Component Based](https://blog.lvgl.io/2018-12-13/extend-lvgl-objects) high-level GUI library, which seems to be a natural candidate to map into a higher level language, such as Python. LVGL is implemented in C and its APIs are in C.
|
||||||
|
|
||||||
|
### Here are some advantages of using LVGL in Micropython:
|
||||||
|
|
||||||
|
- Develop GUI in Python, a very popular high level language. Use paradigms such as Object-Oriented Programming.
|
||||||
|
- Usually, GUI development requires multiple iterations to get things right. With C, each iteration consists of **`Change code` > `Build` > `Flash` > `Run`**.
|
||||||
|
In Micropython it's just **`Change code` > `Run`** ! You can even run commands interactively using the [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) (the interactive prompt)
|
||||||
|
|
||||||
|
### Micropython + LVGL could be used for:
|
||||||
|
|
||||||
|
- Fast prototyping GUI.
|
||||||
|
- Shortening the cycle of changing and fine-tuning the GUI.
|
||||||
|
- Modelling the GUI in a more abstract way by defining reusable composite objects, taking advantage of Python's language features such as Inheritance, Closures, List Comprehension, Generators, Exception Handling, Arbitrary Precision Integers and others.
|
||||||
|
- Make LVGL accessible to a larger audience. No need to know C to create a nice GUI on an embedded system.
|
||||||
|
This goes well with [CircuitPython vision](https://learn.adafruit.com/welcome-to-circuitpython/what-is-circuitpython). CircuitPython was designed with education in mind, to make it easier for new or inexperienced users to get started with embedded development.
|
||||||
|
- Creating tools to work with LVGL at a higher level (e.g. drag-and-drop designer).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## So what does it look like?
|
||||||
|
|
||||||
|
> TL;DR:
|
||||||
|
> It's very much like the C API, but Object-Oriented for LVGL components.
|
||||||
|
|
||||||
|
Let's dive right into an example!
|
||||||
|
|
||||||
|
### A simple example
|
||||||
|
|
||||||
|
```python
|
||||||
|
import lvgl as lv
|
||||||
|
lv.init()
|
||||||
|
scr = lv.obj()
|
||||||
|
btn = lv.btn(scr)
|
||||||
|
btn.align(lv.scr_act(), lv.ALIGN.CENTER, 0, 0)
|
||||||
|
label = lv.label(btn)
|
||||||
|
label.set_text("Button")
|
||||||
|
lv.scr_load(scr)
|
||||||
|
```
|
||||||
|
|
||||||
|
## How can I use it?
|
||||||
|
|
||||||
|
### Online Simulator
|
||||||
|
|
||||||
|
If you want to experiment with LVGL + Micropython without downloading anything - you can use our online simulator!
|
||||||
|
It's a fully functional LVGL + Micropython that runs entirely in the browser and allows you to edit a python script and run it.
|
||||||
|
|
||||||
|
[Click here to experiment on the online simulator](https://sim.lvgl.io/)
|
||||||
|
|
||||||
|
[Hello World](https://sim.lvgl.io/v7/micropython/ports/javascript/bundle_out/index.html?script=https://gist.githubusercontent.com/amirgon/51299ce9b6448328a855826149482ae6/raw/0f235c6d40462fd2f0e55364b874f14fe3fd613c/lvgl_hello_world.py&script_startup=https://gist.githubusercontent.com/amirgon/7bf15a66ba6d959bbf90d10f3da571be/raw/8684b5fa55318c184b1310663b187aaab5c65be6/init_lv_mp_js.py)
|
||||||
|
|
||||||
|
Note: the online simulator is available for lvgl v6 and v7.
|
||||||
|
|
||||||
|
### PC Simulator
|
||||||
|
|
||||||
|
Micropython is ported to many platforms. One notable port is "unix", which allows you to build and run Micropython (+LVGL) on a Linux machine. (On a Windows machine you might need Virtual Box or WSL or MinGW or Cygwin etc.)
|
||||||
|
|
||||||
|
[Click here to know more information about building and running the unix port](https://github.com/lvgl/lv_micropython)
|
||||||
|
|
||||||
|
### Embedded platform
|
||||||
|
|
||||||
|
In the end, the goal is to run it all on an embedded platform.
|
||||||
|
Both Micropython and LVGL can be used on many embedded architectures, such as stm32, ESP32 etc.
|
||||||
|
You would also need display and input drivers. We have some sample drivers (ESP32+ILI9341, as well as some other examples), but chances are you would want to create your own input/display drivers for your specific hardware.
|
||||||
|
Drivers can be implemented either in C as a Micropython module, or in pure Micropython!
|
||||||
|
|
||||||
|
## Where can I find more information?
|
||||||
|
|
||||||
|
- In this [Blog Post](https://blog.lvgl.io/2019-02-20/micropython-bindings)
|
||||||
|
- `lv_micropython` [README](https://github.com/lvgl/lv_micropython)
|
||||||
|
- `lv_binding_micropython` [README](https://github.com/lvgl/lv_binding_micropython)
|
||||||
|
- The [LVGL micropython forum](https://forum.lvgl.io/c/micropython) (Feel free to ask anything!)
|
||||||
|
- At Micropython: [docs](http://docs.micropython.org/en/latest/) and [forum](https://forum.micropython.org/)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Get started
|
||||||
|
|
||||||
|
There are several ways to get your feet wet with LVGL. Here is one recommended order of documents to read and things to play with when you are learning to use LVGL:
|
||||||
|
1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes)
|
||||||
|
2. Read the [Introduction](https://docs.lvgl.io/latest/en/html/intro/index.html) page of the documentation (5 minutes)
|
||||||
|
3. Read the [Quick overview](https://docs.lvgl.io/master/get-started/quick-overview.html) page of the documentation (15 minutes)
|
||||||
|
4. Set up a [Simulator](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) (10 minutes)
|
||||||
|
5. Try out some [Examples](https://docs.lvgl.io/master/examples.html)
|
||||||
|
6. Check out the Platform-specific tutorials. (in this section below). (10 minutes)
|
||||||
|
7. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/master/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_&type=&language=)
|
||||||
|
8. Read the [Overview](https://docs.lvgl.io/master/overview/index.html) page to get a better understanding of the library. (2-3 hours)
|
||||||
|
9. Check the documentation of the [Widgets](https://docs.lvgl.io/master/widgets/index.html) to see their features and usage
|
||||||
|
10. If you have questions got to the [Forum](http://forum.lvgl.io/)
|
||||||
|
11. Read the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) guide to see how you can help to improve LVGL (15 minutes)
|
||||||
|
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
quick-overview
|
||||||
|
platforms/index
|
||||||
|
os/index
|
||||||
|
bindings/index
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# FreeRTOS
|
||||||
|
|
||||||
|
TODO
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# (RT)OS
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
nuttx
|
||||||
|
rt-thread
|
||||||
|
freertos
|
||||||
|
zephyr
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
# NuttX RTOS
|
||||||
|
|
||||||
|
## What is NuttX?
|
||||||
|
|
||||||
|
[NuttX](https://nuttx.apache.org/) is a mature and secure real-time operating system (RTOS) with an emphasis on technical standards compliance and small size.
|
||||||
|
It is scalable from 8-bit to 64-bit microcontrollers and microprocessors and compliant with the Portable Operating System Interface (POSIX) and the American National Standards Institute (ANSI) standards and with many Linux-like subsystems.
|
||||||
|
The best way to think about NuttX is to think of it as a small Unix/Linux for microcontrollers.
|
||||||
|
|
||||||
|
### Highlights of NuttX
|
||||||
|
|
||||||
|
- **Small** - Fits and runs in microcontrollers as small as 32 kB Flash and 8 kB of RAM.
|
||||||
|
- **Compliant** - Strives to be as compatible as possible with POSIX and Linux.
|
||||||
|
- **Versatile** - Supports many architectures (ARM, ARM Thumb, AVR, MIPS, OpenRISC, RISC-V 32-bit and 64-bit, RX65N, x86-64, Xtensa, Z80/Z180, etc.).
|
||||||
|
- **Modular** - Its modular design allows developers to select only what really matters and use modules to include new features.
|
||||||
|
- **Popular** - NuttX is used by many companies around the world. Probably you already used a product with NuttX without knowing it was running NuttX.
|
||||||
|
- **Predictable** - NuttX is a preemptible Realtime kernel, so you can use it to create predictable applications for realtime control.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Why NuttX + LVGL?
|
||||||
|
|
||||||
|
Although NuttX has its own graphic library called [NX](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=139629474), LVGL is a good alternative because users could find more eye-candy demos and they can reuse code from previous projects.
|
||||||
|
LVGL is an [Object-Oriented Component Based](https://blog.lvgl.io/2018-12-13/extend-lvgl-objects) high-level GUI library, that could fit very well for a RTOS with advanced features like NuttX.
|
||||||
|
LVGL is implemented in C and its APIs are in C.
|
||||||
|
|
||||||
|
### Here are some advantages of using LVGL in NuttX
|
||||||
|
|
||||||
|
- Develop GUI in Linux first and when it is done just compile it for NuttX. Nothing more, no wasting of time.
|
||||||
|
- Usually, GUI development for low level RTOS requires multiple iterations to get things right, where each iteration consists of **`Change code` > `Build` > `Flash` > `Run`**.
|
||||||
|
Using LVGL, Linux and NuttX you can reduce this process and just test everything on your computer and when it is done, compile it on NuttX and that is it.
|
||||||
|
|
||||||
|
### NuttX + LVGL could be used for
|
||||||
|
|
||||||
|
- GUI demos to demonstrate your board graphics capacities.
|
||||||
|
- Fast prototyping GUI for MVP (Minimum Viable Product) presentation.
|
||||||
|
- visualize sensor data directly and easily on the board without using a computer.
|
||||||
|
- Final products with a GUI without a touchscreen (i.e. 3D Printer Interface using Rotary Encoder to Input data).
|
||||||
|
- Final products with a touchscreen (and all sorts of bells and whistles).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to get started with NuttX and LVGL?
|
||||||
|
|
||||||
|
There are many boards in the [NuttX mainline](https://github.com/apache/incubator-nuttx) with support for LVGL.
|
||||||
|
Let's use the [STM32F429IDISCOVERY](https://www.st.com/en/evaluation-tools/32f429idiscovery.html) as an example because it is a very popular board.
|
||||||
|
|
||||||
|
### First you need to install the pre-requisites on your system
|
||||||
|
|
||||||
|
Let's use the [Windows Subsystem for Linux](https://acassis.wordpress.com/2018/01/10/how-to-build-nuttx-on-windows-10/)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ sudo apt-get install automake bison build-essential flex gcc-arm-none-eabi gperf git libncurses5-dev libtool libusb-dev libusb-1.0.0-dev pkg-config kconfig-frontends openocd
|
||||||
|
```
|
||||||
|
|
||||||
|
### Now let's create a workspace to save our files
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ mkdir ~/nuttxspace
|
||||||
|
$ cd ~/nuttxspace
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clone the NuttX and Apps repositories:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ git clone https://github.com/apache/incubator-nuttx nuttx
|
||||||
|
$ git clone https://github.com/apache/incubator-nuttx-apps apps
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure NuttX to use the stm32f429i-disco board and the LVGL Demo
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ ./tools/configure.sh stm32f429i-disco:lvgl
|
||||||
|
$ make
|
||||||
|
```
|
||||||
|
|
||||||
|
If everything went fine you should have now the file `nuttx.bin` to flash on your board:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ ls -l nuttx.bin
|
||||||
|
-rwxrwxr-x 1 alan alan 287144 Jun 27 09:26 nuttx.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flashing the firmware in the board using OpenOCD:
|
||||||
|
```shell
|
||||||
|
$ sudo openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg -c init -c "reset halt" -c "flash write_image erase nuttx.bin 0x08000000"
|
||||||
|
```
|
||||||
|
|
||||||
|
Reset the board and using the 'NSH>' terminal start the LVGL demo:
|
||||||
|
```shell
|
||||||
|
nsh> lvgldemo
|
||||||
|
```
|
||||||
|
|
||||||
|
## Where can I find more information?
|
||||||
|
|
||||||
|
- This blog post: [LVGL on LPCXpresso54628](https://acassis.wordpress.com/2018/07/19/running-nuttx-on-lpcxpresso54628-om13098/)
|
||||||
|
- NuttX mailing list: [Apache NuttX Mailing List](http://nuttx.incubator.apache.org/community/)
|
||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# RT-Thread RTOS
|
||||||
|
|
||||||
|
<img src="https://raw.githubusercontent.com/RT-Thread/rt-thread/master/documentation/figures/logo.png" width=40% style="float: center;" >
|
||||||
|
|
||||||
|
## What is RT-Thread?
|
||||||
|
|
||||||
|
[Introduce about RT-Thread and how to run LVGL on RT-Thread in simulators](https://www.youtube.com/watch?v=k7QYk6hSwnc)
|
||||||
|
|
||||||
|
[**RT-Thread**](https://www.rt-thread.io/) is an [open source](https://github.com/RT-Thread/rt-thread), neutral, and community-based real-time operating system (RTOS). RT-Thread has **Standard version** and **Nano version**. For resource-constrained microcontroller (MCU) systems, the Nano version that requires only 3 KB Flash and 1.2 KB RAM memory resources can be tailored with easy-to-use tools. For resource-rich IoT devices, RT-Thread can use the **online software package** management tool, together with system configuration tools, to achieve intuitive and rapid modular cutting, seamlessly import rich software packages; thus, achieving complex functions like Android's graphical interface and touch sliding effects, smart voice interaction effects, and so on.
|
||||||
|
|
||||||
|
### Key features
|
||||||
|
|
||||||
|
- Designed for resource-constrained devices, the minimum kernel requires only 1.2KB of RAM and 3 KB of Flash.
|
||||||
|
- A variety of standard interfaces, such as POSIX, CMSIS, C++ application environment.
|
||||||
|
- Has rich components and a prosperous and fast growing <a href="https://packages.rt-thread.org/en/">package ecosystem</a>
|
||||||
|
- Elegant code style, easy to use, read and master.
|
||||||
|
- High Scalability. RT-Thread has high-quality scalable software architecture, loose coupling, modularity, is easy to tailor and expand.
|
||||||
|
- Supports high-performance applications.
|
||||||
|
- Supports all mainstream compiling tools such as GCC, Keil and IAR.
|
||||||
|
- Supports a wide range of <a href="https://www.rt-thread.io/board.html">architectures and chips</a>.
|
||||||
|
|
||||||
|
|
||||||
|
## How to run LVGL on RT-Thread?
|
||||||
|
|
||||||
|
[中文文档](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/packages-manual/lvgl-docs/introduction)
|
||||||
|
|
||||||
|
LVGL has registered as a [software package](https://packages.rt-thread.org/en/detail.html?package=LVGL) of RT-Thread. By using [Env tool](https://www.rt-thread.io/download.html?download=Env) or [RT-Thread Studio IDE](https://www.rt-thread.io/download.html?download=Studio), RT-Thread users can easily download LVGL source code and combine with RT-Thread project. RT-Thread community has port LVGL to several BSPs:
|
||||||
|
|
||||||
|
| BSP | Note |
|
||||||
|
| ------------------------------------------------------------ | ---- |
|
||||||
|
| [QEMU simulator](https://github.com/RT-Thread/rt-thread/tree/master/bsp/qemu-vexpress-a9/applications/lvgl) | |
|
||||||
|
| [Visual Studio simulator](https://github.com/RT-Thread/rt-thread/tree/master/bsp/simulator/applications/lvgl) | |
|
||||||
|
| [Nuvoton numaker-iot-m487](https://github.com/RT-Thread/rt-thread/tree/master/bsp/nuvoton/numaker-iot-m487/applications/lvgl) | |
|
||||||
|
| [Nuvoton numaker-pfm-m487](https://github.com/RT-Thread/rt-thread/tree/master/bsp/nuvoton/numaker-pfm-m487/applications/lvgl) | |
|
||||||
|
| [Nuvoton nk-980iot](https://github.com/RT-Thread/rt-thread/tree/master/bsp/nuvoton/nk-980iot/applications/lvgl) | |
|
||||||
|
| [Nuvoton numaker-m2354](https://github.com/RT-Thread/rt-thread/tree/master/bsp/nuvoton/numaker-m2354/applications/lvgl) | |
|
||||||
|
| [Nuvoton nk-n9h30](https://github.com/RT-Thread/rt-thread/tree/master/bsp/nuvoton/nk-n9h30/applications/lvgl) | |
|
||||||
|
| [Nuvoton numaker-m032ki](https://github.com/RT-Thread/rt-thread/tree/master/bsp/nuvoton/numaker-m032ki/applications/lvgl) | |
|
||||||
|
| [NXP imxrt1060-evk](https://github.com/RT-Thread/rt-thread/tree/master/bsp/imxrt/imxrt1060-nxp-evk/applications/lvgl) | |
|
||||||
|
| [STM32L475 pandora](https://github.com/RT-Thread/rt-thread/tree/master/bsp/stm32/stm32l475-atk-pandora/applications/lvgl) | |
|
||||||
|
| [STM32F407 explorer](https://github.com/RT-Thread/rt-thread/tree/master/bsp/stm32/stm32f407-atk-explorer/applications/lvgl) | |
|
||||||
|
| [STM32F469 Discovery](https://github.com/RT-Thread/rt-thread/tree/master/bsp/stm32/stm32f469-st-disco/applications/lvgl) | |
|
||||||
|
| [Raspberry PICO](https://github.com/RT-Thread/rt-thread/tree/master/bsp/raspberry-pico/applications/lvgl) | |
|
||||||
|
|
||||||
|
|
||||||
|
### Import a BSP project into RT-Thread Studio
|
||||||
|
|
||||||
|
Clone the latest code from RT-Thread official repository. Open the RT-Thread Studio and select `File -> Import`. In the Import menu, please select `RT-Thread BSP Project into Workspace`, and click `next` button. In the `BSP location area`, please select the root path of the BSP which you prefer to import, such as `C:\Users\xxx\Desktop\rt-thread\bsp\stm32\stm32l475-atk-pandora`. In the `Project Name area`, please type a name for this project, then, press `Finish` button.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Zephyr
|
||||||
|
|
||||||
|
TODO
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
|
||||||
|
# Arduino
|
||||||
|
|
||||||
|
The [LVGL library](https://github.com/lvgl/lvgl) is directly available as Arduino libraries.
|
||||||
|
|
||||||
|
Note that you need to choose a board powerful enough to run LVGL and your GUI. See the [requirements of LVGL](https://docs.lvgl.io/master/intro/index.html#requirements).
|
||||||
|
|
||||||
|
For example ESP32 is a good candidate to create UI's with LVGL.
|
||||||
|
|
||||||
|
## Get the LVGL Arduino library
|
||||||
|
|
||||||
|
LVGL can be installed via the Arduino IDE Library Manager or as a .ZIP library.
|
||||||
|
|
||||||
|
You can [Download](https://github.com/lvgl/lvgl/archive/refs/heads/master.zip) the latest version of LVGL from GitHub and simply copy it to Arduino's library folder.
|
||||||
|
|
||||||
|
## Set up drivers
|
||||||
|
|
||||||
|
To get started it's recommended to use [TFT_eSPI](https://github.com/Bodmer/TFT_eSPI) library as a TFT driver to simplify testing.
|
||||||
|
To make it work, setup `TFT_eSPI` according to your TFT display type via editing either
|
||||||
|
- `User_Setup.h`
|
||||||
|
- or by selecting a configuration in the `User_Setup_Select.h`
|
||||||
|
|
||||||
|
Both files are located in `TFT_eSPI` library's folder.
|
||||||
|
|
||||||
|
## Configure LVGL
|
||||||
|
|
||||||
|
LVGL has its own configuration file called `lv_conf.h`. When LVGL is installed, follow these configuration steps:
|
||||||
|
1. Go to the directory of the installed Arduino libraries
|
||||||
|
2. Go to `lvgl` and copy `lv_conf_template.h` as `lv_conf.h` into the Arduino Libraries directory next to the `lvgl` library folder.
|
||||||
|
3. Open `lv_conf.h` and change the first `#if 0` to `#if 1` to enable the content of the file
|
||||||
|
4. Set the color depth of you display in `LV_COLOR_DEPTH`
|
||||||
|
5. Set `LV_TICK_CUSTOM 1`
|
||||||
|
|
||||||
|
Finally the layout with `lv_conf.h` should look like this:
|
||||||
|
```
|
||||||
|
arduino
|
||||||
|
|-libraries
|
||||||
|
|-lvgl
|
||||||
|
|-other_lib_1
|
||||||
|
|-other_lib_2
|
||||||
|
|-lv_conf.h
|
||||||
|
```
|
||||||
|
|
||||||
|
## Initialize and run LVGL
|
||||||
|
|
||||||
|
Take a look at [LVGL_Arduino.ino](https://github.com/lvgl/lvgl/blob/master/examples/arduino/LVGL_Arduino/LVGL_Arduino.ino) to see how to initialize LVGL.
|
||||||
|
`TFT_eSPI` is used as the display driver.
|
||||||
|
|
||||||
|
In the INO file you can see how to register a display and a touchpad for LVGL and call an example.
|
||||||
|
|
||||||
|
## Use the examples and demos
|
||||||
|
|
||||||
|
Note that, there is no dedicated INO file for every example. Instead, you can load an example by calling an `lv_example_...` function. For example `lv_example_btn_1()`.
|
||||||
|
|
||||||
|
**IMPORTANT NOTE 1**
|
||||||
|
Due to some the limitations of Arduino's build system you need to copy `lvgl/examples` to `lvgl/src/examples`. Similarly for the demos `lvgl/demos` to `lvgl/src/demos`.
|
||||||
|
|
||||||
|
|
||||||
|
**IMPORTANT NOTE 2**
|
||||||
|
Note that the `lv_examples` library is for LVGL v7 and you shouldn't install it for this version (since LVGL v8)
|
||||||
|
as the examples and demos are now part of the main LVGL library.
|
||||||
|
|
||||||
|
## Debugging and logging
|
||||||
|
|
||||||
|
LVGL can display debug information in case of trouble.
|
||||||
|
In the `LVGL_Arduino.ino` example there is a `my_print` method, which sends this debug information to the serial interface.
|
||||||
|
To enable this feature you have to edit the `lv_conf.h` file and enable logging in the section `log settings`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/*Log settings*/
|
||||||
|
#define USE_LV_LOG 1 /*Enable/disable the log module*/
|
||||||
|
#if LV_USE_LOG
|
||||||
|
/* How important log should be added:
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||||
|
```
|
||||||
|
|
||||||
|
After enabling the log module and setting LV_LOG_LEVEL accordingly, the output log is sent to the `Serial` port @ 115200 bps.
|
||||||
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
# CMake
|
||||||
|
LVGL supports integrating with [CMake](https://cmake.org/). It comes with preconfigured targets for:
|
||||||
|
- [Espressif (ESP32)](https://docs.espressif.com/projects/esp-idf/en/v3.3/get-started-cmake/index.html)
|
||||||
|
- [MicroPython](https://docs.micropython.org/en/v1.15/develop/cmodules.html)
|
||||||
|
- [Zephyr](https://docs.zephyrproject.org/latest/guides/zephyr_cmake_package.html)
|
||||||
|
|
||||||
|
On top of the preconfigured targets you can also use "plain" CMake to integrate LVGL into any custom C/C++ project.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
- CMake ( >= 3.12.4 )
|
||||||
|
- Compatible build tool e.g.
|
||||||
|
- [Make](https://www.gnu.org/software/make/)
|
||||||
|
- [Ninja](https://ninja-build.org/)
|
||||||
|
|
||||||
|
## Building LVGL with CMake
|
||||||
|
There are many ways to include external CMake projects into your own. A modern one also used in this example is the CMake [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) module. This module conveniently allows us to download dependencies directly at configure time from e.g. [GitHub](https://github.com/). Here is an example how we might include LVGL into our own project.
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
project(MyProject LANGUAGES C CXX)
|
||||||
|
|
||||||
|
# Build an executable called "MyFirmware"
|
||||||
|
add_executable(MyFirmware src/main.c)
|
||||||
|
|
||||||
|
# Specify path to own LVGL config header
|
||||||
|
set(LV_CONF_PATH
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/lv_conf.h
|
||||||
|
CACHE STRING "" FORCE)
|
||||||
|
|
||||||
|
# Fetch LVGL from GitHub
|
||||||
|
FetchContent_Declare(lvgl URL https://github.com/lvgl/lvgl.git)
|
||||||
|
FetchContent_MakeAvailable(lvgl)
|
||||||
|
|
||||||
|
# The target "MyFirmware" depends on LVGL
|
||||||
|
target_link_libraries(MyFirmware PRIVATE lvgl::lvgl)
|
||||||
|
```
|
||||||
|
|
||||||
|
This configuration declares a dependency between the two targets **MyFirmware** and **lvgl**. Upon building the target **MyFirmware** this dependency will be resolved and **lvgl** will be built and linked with it. Since LVGL requires a config header called [lv_conf.h](https://github.com/lvgl/lvgl/blob/master/lv_conf_template.h) to be includable by its sources we also set the option `LV_CONF_PATH` to point to our own copy of it.
|
||||||
|
|
||||||
|
### Additional CMake options
|
||||||
|
Besides `LV_CONF_PATH` there are two additional CMake options to specify include paths.
|
||||||
|
|
||||||
|
`LV_LVGL_H_INCLUDE_SIMPLE` which specifies whether to `#include "lvgl.h"` absolut or relative
|
||||||
|
|
||||||
|
| ON (default) | OFF |
|
||||||
|
| ------------ | -------------- |
|
||||||
|
| "lvgl.h" | "../../lvgl.h" |
|
||||||
|
|
||||||
|
`LV_CONF_INCLUDE_SIMPLE` which specifies whether to `#include "lv_conf.h"` and `"lv_drv_conf.h"` absolut or relative
|
||||||
|
|
||||||
|
| ON (default) | OFF |
|
||||||
|
| --------------- | --------------------- |
|
||||||
|
| "lv_conf.h" | "../../lv_conf.h" |
|
||||||
|
| "lv_drv_conf.h" | "../../lv_drv_conf.h" |
|
||||||
|
|
||||||
|
I do not recommend disabling those options unless your folder layout makes it absolutely necessary.
|
||||||
|
|
||||||
|
## Building LVGL examples with CMake
|
||||||
|
LVGL [examples](https://docs.lvgl.io/master/examples.html) have their own CMake target. If you want to build the examples simply add them to your dependencies.
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# The target "MyFirmware" depends on LVGL and examples
|
||||||
|
target_link_libraries(MyFirmware PRIVATE lvgl::lvgl lvgl::examples)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building LVGL drivers and demos with CMake
|
||||||
|
Exactly the same goes for the [drivers](https://github.com/lvgl/lv_drivers) and the [demos](https://github.com/lvgl/lvgl/demos).
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
FetchContent_Declare(lv_drivers
|
||||||
|
GIT_REPOSITORY https://github.com/lvgl/lv_drivers)
|
||||||
|
FetchContent_MakeAvailable(lv_drivers)
|
||||||
|
|
||||||
|
# The target "MyFirmware" depends on LVGL, drivers and demos
|
||||||
|
target_link_libraries(MyFirmware PRIVATE lvgl::lvgl lvgl::drivers lvgl::examples)
|
||||||
|
```
|
||||||
|
|
||||||
|
# Build shared libraries with CMake
|
||||||
|
By default, LVGL will be built as a static library (archive). CMake can instead be instructed to build LVGL as shared library (.so/.dll/etc.):
|
||||||
|
```cmake
|
||||||
|
set(BUILD_SHARED_LIBS ON)
|
||||||
|
```
|
||||||
|
OR
|
||||||
|
```
|
||||||
|
$ cmake "-DBUILD_SHARED_LIBS=ON" .
|
||||||
|
```
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
|
||||||
|
# Espressif (ESP32 chip series)
|
||||||
|
LVGL can be used and configured as a standard [ESP-IDF](https://github.com/espressif/esp-idf) component.
|
||||||
|
|
||||||
|
More information about ESP-IDF build system can be found [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html).
|
||||||
|
|
||||||
|
## LVGL demo project for ESP32
|
||||||
|
|
||||||
|
We've created [lv_port_esp32](https://github.com/lvgl/lv_port_esp32), a project using ESP-IDF and LVGL to show one of the demos from [demos](https://github.com/lvgl/lvgl/demos).
|
||||||
|
You can configure the project to use one of the many supported display controllers and targets (chips).
|
||||||
|
|
||||||
|
See [lvgl_esp32_drivers](https://github.com/lvgl/lvgl_esp32_drivers) repository for a complete list
|
||||||
|
of supported display and indev (touch) controllers and targets.
|
||||||
|
|
||||||
|
## Using LVGL in your ESP-IDF project
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
* ESP-IDF v4.1 and above
|
||||||
|
* ESP evaluation board with a display
|
||||||
|
|
||||||
|
### Obtaining LVGL
|
||||||
|
|
||||||
|
__Option 1:__ git submodule
|
||||||
|
|
||||||
|
Simply clone LVGL into your `project_root/components` directory and it will be automatically integrated into the project.
|
||||||
|
If the project is a git repository you can include LVGL as a git submodule:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git submodule add https://github.com/lvgl/lvgl.git components/lvgl
|
||||||
|
```
|
||||||
|
|
||||||
|
The above command will clone LVGL's main repository into the `components/lvgl` directory. LVGL includes a `CMakeLists.txt` file that sets some configuration options so you can use LVGL right away.
|
||||||
|
|
||||||
|
__Option 2:__ IDF Component Manager
|
||||||
|
|
||||||
|
LVGL is also distributed through [IDF Component Manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html).
|
||||||
|
It allows users to seamlessly integrate [LVGL component](https://components.espressif.com/component/lvgl/lvgl) into their project with following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
idf.py add-dependency lvgl/lvgl>=8.*
|
||||||
|
```
|
||||||
|
|
||||||
|
During next project build, LVGL component will be fetched from the component registry and added to project build.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
When you are ready to configure LVGL, launch the configuration menu with `idf.py menuconfig` in your project root directory, go to `Component config` and then `LVGL configuration`.
|
||||||
|
|
||||||
|
## Using lvgl_esp32_drivers in ESP-IDF project
|
||||||
|
|
||||||
|
You can also add `lvgl_esp32_drivers` as a "component". This component should be located inside a directory named "components" in your project root directory.
|
||||||
|
|
||||||
|
When your project is a git repository you can include `lvgl_esp32_drivers` as a git submodule:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git submodule add https://github.com/lvgl/lvgl_esp32_drivers.git components/lvgl_esp32_drivers
|
||||||
|
```
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Platforms
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
pc-simulator
|
||||||
|
nxp
|
||||||
|
stm32
|
||||||
|
espressif
|
||||||
|
renesas
|
||||||
|
arduino
|
||||||
|
tasmota-berry
|
||||||
|
cmake
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
# NXP
|
||||||
|
NXP has integrated LVGL into the MCUXpresso SDK packages for general purpose and crossover microcontrollers, allowing
|
||||||
|
easy evaluation and migration into your product design.
|
||||||
|
[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)
|
||||||
|
today and get started with your next GUI application.
|
||||||
|
|
||||||
|
## Creating new project with LVGL
|
||||||
|
Downloading the MCU SDK example project is recommended as a starting point. It comes fully configured with LVGL (and
|
||||||
|
with PXP/VGLite support if the modules are present), no additional integration work is required.
|
||||||
|
|
||||||
|
## HW acceleration for NXP iMX RT platforms
|
||||||
|
Depending on the RT platform used, the acceleration can be done by NXP PXP (PiXel Pipeline) and/or the Verisilicon GPU
|
||||||
|
through an API named VGLite. Each accelerator has its own context that allows them to be used individually as well
|
||||||
|
simultaneously (in LVGL multithreading mode).
|
||||||
|
|
||||||
|
### PXP accelerator
|
||||||
|
Several drawing features in LVGL can be offloaded to the PXP engine. The CPU is available for other operations while the
|
||||||
|
PXP is running. RTOS is required to block the LVGL drawing thread and switch to another task or suspend the CPU for
|
||||||
|
power savings.
|
||||||
|
|
||||||
|
Supported draw callbacks are available in "src/draw/nxp/pxp/lv_draw_pxp.c":
|
||||||
|
```c
|
||||||
|
pxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_pxp_img_decoded;
|
||||||
|
pxp_draw_ctx->blend = lv_draw_pxp_blend;
|
||||||
|
pxp_draw_ctx->base_draw.wait_for_finish = lv_draw_pxp_wait_for_finish;
|
||||||
|
pxp_draw_ctx->base_draw.buffer_copy = lv_draw_pxp_buffer_copy;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Features supported:
|
||||||
|
All operations can be used in conjunction with optional transparency.
|
||||||
|
|
||||||
|
- RGB565 and ARGB8888 color formats
|
||||||
|
- Area fill with color
|
||||||
|
- BLIT (BLock Image Transfer)
|
||||||
|
- Screen Rotation (90, 180, 270 degree)
|
||||||
|
- Color keying
|
||||||
|
- Recoloring (color tint)
|
||||||
|
- Image Rotation (90, 180, 270 degree)
|
||||||
|
- Buffer copy
|
||||||
|
- RTOS integration layer
|
||||||
|
- Default FreeRTOS and bare metal code provided
|
||||||
|
|
||||||
|
- Combination of recolor and/or rotation + color key/alpha blend/transparency is supported.
|
||||||
|
That is achieved by PXP in two steps:
|
||||||
|
- First step is to recolor/rotate the image to a temporary buffer (statically allocated)
|
||||||
|
- Second step is required to handle color keying, alpha channel or to apply transparency
|
||||||
|
|
||||||
|
#### Known limitations:
|
||||||
|
- Rotation is not supported for images unaligned to blocks of 16x16 pixels.
|
||||||
|
PXP is set to process 16x16 blocks to optimize the system for memory bandwidth and image processing time.
|
||||||
|
The output engine essentially truncates any output pixels after the desired number of pixels has been written.
|
||||||
|
When rotating a source image and the output is not divisible by the block size, the incorrect pixels could be truncated
|
||||||
|
and the final output image can look shifted.
|
||||||
|
|
||||||
|
#### Basic configuration:
|
||||||
|
- Select NXP PXP engine in lv_conf.h: Set `LV_USE_GPU_NXP_PXP` to 1
|
||||||
|
- Enable default implementation for interrupt handling, PXP start function and automatic initialization:
|
||||||
|
Set `LV_USE_GPU_NXP_PXP_AUTO_INIT` to 1
|
||||||
|
- If `SDK_OS_FREE_RTOS` symbol is defined, FreeRTOS implementation will be used, otherwise bare metal code will be
|
||||||
|
included
|
||||||
|
|
||||||
|
#### Basic initialization:
|
||||||
|
- If `LV_USE_GPU_NXP_PXP_AUTO_INIT` is enabled, no user code is required; PXP is initialized automatically in
|
||||||
|
`lv_init()`
|
||||||
|
- For manual PXP initialization, default configuration structure for callbacks can be used. Initialize PXP before
|
||||||
|
calling `lv_init()`
|
||||||
|
```c
|
||||||
|
#if LV_USE_GPU_NXP_PXP
|
||||||
|
#include "src/draw/nxp/pxp/lv_gpu_nxp_pxp.h"
|
||||||
|
#endif
|
||||||
|
. . .
|
||||||
|
#if LV_USE_GPU_NXP_PXP
|
||||||
|
PXP_COND_STOP(!lv_gpu_nxp_pxp_init(), "PXP init failed.");
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Project setup:
|
||||||
|
- Add PXP related files to project:
|
||||||
|
- src/draw/nxp/pxp/lv_draw_pxp.c[.h]: draw context callbacks
|
||||||
|
- src/draw/nxp/pxp/lv_draw_pxp_blend.c[.h]: fill and blit (with optional transformation)
|
||||||
|
- src/draw/nxp/pxp/lv_gpu_nxp_pxp.c[.h]: init, uninit, run/wait PXP device
|
||||||
|
- src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c[.h]: OS abstraction (FreeRTOS or bare metal)
|
||||||
|
- optional, required only if `LV_USE_GPU_NXP_PXP_AUTO_INIT` is set to 1
|
||||||
|
- PXP related code depends on two drivers provided by MCU SDK. These drivers need to be added to project:
|
||||||
|
- fsl_pxp.c[.h]: PXP driver
|
||||||
|
- fsl_cache.c[.h]: CPU cache handling functions
|
||||||
|
|
||||||
|
#### Logging:
|
||||||
|
- By default, `LV_GPU_NXP_PXP_LOG_ERRORS` is enabled so that any PXP error will be seen on SDK debug console
|
||||||
|
- By default, `LV_GPU_NXP_PXP_LOG_TRACES` is disabled. Enable it for tracing logs (like PXP limitations)
|
||||||
|
|
||||||
|
#### Advanced configuration:
|
||||||
|
- Implementation depends on multiple OS-specific functions. The struct `lv_nxp_pxp_cfg_t` with callback pointers is
|
||||||
|
used as a parameter for the `lv_gpu_nxp_pxp_init()` function. Default implementation for FreeRTOS and bare metal is
|
||||||
|
provided in lv_gpu_nxp_pxp_osa.c
|
||||||
|
- `pxp_interrupt_init()`: Initialize PXP interrupt (HW setup, OS setup)
|
||||||
|
- `pxp_interrupt_deinit()`: Deinitialize PXP interrupt (HW setup, OS setup)
|
||||||
|
- `pxp_run()`: Start PXP job. Use OS-specific mechanism to block drawing thread. PXP must finish drawing before
|
||||||
|
leaving this function.
|
||||||
|
- Area threshold (size limit) is configurable and used to decide whether the area will be processed by PXP or not.
|
||||||
|
Areas smaller than the defined value will be processed by CPU and those bigger than the threshold will be processed by
|
||||||
|
PXP. The threshold is defined as a macro in lv_draw_pxp.c
|
||||||
|
- `LV_GPU_NXP_PXP_SIZE_LIMIT`: size threshold for fill/blit (with optional transformation)
|
||||||
|
|
||||||
|
### VGLite accelerator
|
||||||
|
Extra drawing features in LVGL can be handled by the VGLite engine. The CPU is available for other operations while the
|
||||||
|
VGLite is running. An RTOS is required to block the LVGL drawing thread and switch to another task or suspend the CPU
|
||||||
|
for power savings.
|
||||||
|
|
||||||
|
Supported draw callbacks are available in "src/draw/nxp/vglite/lv_draw_vglite.c":
|
||||||
|
```c
|
||||||
|
vglite_draw_ctx->base_draw.init_buf = lv_draw_vglite_init_buf;
|
||||||
|
vglite_draw_ctx->base_draw.draw_line = lv_draw_vglite_line;
|
||||||
|
vglite_draw_ctx->base_draw.draw_arc = lv_draw_vglite_arc;
|
||||||
|
vglite_draw_ctx->base_draw.draw_rect = lv_draw_vglite_rect;
|
||||||
|
vglite_draw_ctx->base_draw.draw_img_decoded = lv_draw_vglite_img_decoded;
|
||||||
|
vglite_draw_ctx->blend = lv_draw_vglite_blend;
|
||||||
|
vglite_draw_ctx->base_draw.wait_for_finish = lv_draw_vglite_wait_for_finish;
|
||||||
|
vglite_draw_ctx->base_draw.buffer_copy = lv_draw_vglite_buffer_copy;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Features supported:
|
||||||
|
All operations can be used in conjunction with optional transparency.
|
||||||
|
|
||||||
|
- RGB565 and ARGB8888 color formats
|
||||||
|
- Area fill with color
|
||||||
|
- BLIT (BLock Image Transfer)
|
||||||
|
- Image Rotation (any degree with decimal)
|
||||||
|
- Image Scale
|
||||||
|
- Draw rectangle background with optional radius or gradient
|
||||||
|
- Blit rectangle background image
|
||||||
|
- Draw rectangle border/outline with optional rounded corners
|
||||||
|
- Draw arc with optional rounded ending
|
||||||
|
- Draw line or dashed line with optional rounded ending
|
||||||
|
- Buffer copy
|
||||||
|
|
||||||
|
#### Known limitations:
|
||||||
|
- Source image alignment:
|
||||||
|
The byte alignment requirement for a pixel depends on the specific pixel format. Both buffer address and buffer stride
|
||||||
|
must be aligned. As general rule, the alignment is set to 16 pixels. This makes the buffer address alignment to be
|
||||||
|
32 bytes for RGB565 and 64 bytes for ARGB8888.
|
||||||
|
- For pixel engine (PE) destination, the alignment should be 64 bytes for all tiled (4x4) buffer layouts.
|
||||||
|
The pixel engine has no additional alignment requirement for linear buffer layouts (`VG_LITE_LINEAR`).
|
||||||
|
|
||||||
|
#### Basic configuration:
|
||||||
|
- Select NXP VGLite engine in lv_conf.h: Set `LV_USE_GPU_NXP_VG_LITE` to 1
|
||||||
|
- `SDK_OS_FREE_RTOS` symbol needs to be defined so that the FreeRTOS implementation will be used
|
||||||
|
|
||||||
|
#### Basic initialization:
|
||||||
|
- Initialize VGLite before calling `lv_init()` by specifying the width/height of tessellation window. Value should be
|
||||||
|
a multiple of 16; minimum value is 16 pixels, maximum cannot be greater than the frame width. If less than or equal
|
||||||
|
to 0, then no tessellation buffer is created, in which case VGLite is initialized only for blitting.
|
||||||
|
```c
|
||||||
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
#include "vg_lite.h"
|
||||||
|
#endif
|
||||||
|
. . .
|
||||||
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
VG_LITE_COND_STOP(vg_lite_init(64, 64) != VG_LITE_SUCCESS, "VGLite init failed.");
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Project setup:
|
||||||
|
- Add VGLite related files to project:
|
||||||
|
- src/draw/nxp/vglite/lv_draw_vglite.c[.h]: draw context callbacks
|
||||||
|
- src/draw/nxp/vglite/lv_draw_vglite_blend.c[.h]: fill and blit (with optional transformation)
|
||||||
|
- src/draw/nxp/vglite/lv_draw_vglite_rect.c[.h]: draw rectangle
|
||||||
|
- src/draw/nxp/vglite/lv_draw_vglite_arc.c[.h]: draw arc
|
||||||
|
- src/draw/nxp/vglite/lv_draw_vglite_line.c[.h]: draw line
|
||||||
|
- src/draw/nxp/vglite/lv_vglite_buf.c[.h]: init/get vglite buffer
|
||||||
|
- src/draw/nxp/vglite/lv_vglite_utils.c[.h]: function helpers
|
||||||
|
|
||||||
|
#### Logging:
|
||||||
|
- By default, `LV_GPU_NXP_VG_LITE_LOG_ERRORS` is enabled so that any VGLite error will be seen on SDK debug console
|
||||||
|
- By default, `LV_GPU_NXP_VG_LITE_LOG_TRACES` is disabled. Enable it for tracing logs (like blit split workaround or
|
||||||
|
VGLite fallback to CPU due to any error on the driver)
|
||||||
|
|
||||||
|
#### Advanced configuration:
|
||||||
|
- Area threshold (size limit) is configurable and used to decide whether the area will be processed by VGLite or not.
|
||||||
|
Areas smaller than the defined value will be processed by CPU and those bigger than the threshold will be processed by
|
||||||
|
VGLite. The threshold is defined as a macro in lv_draw_vglite.c
|
||||||
|
- `LV_GPU_NXP_VG_LITE_SIZE_LIMIT`: size threshold for fill/blit (with optional transformation)
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# Simulator on PC
|
||||||
|
|
||||||
|
|
||||||
|
You can try out LVGL **using only your PC** (i.e. without any development boards). LVGL will run on a simulator environment on the PC where anyone can write and experiment with real LVGL applications.
|
||||||
|
|
||||||
|
Using the simulator on a PC has the following advantages:
|
||||||
|
- Hardware independent - Write code, run it on the PC and see the result on a monitor.
|
||||||
|
- Cross-platform - Any Windows, Linux or macOS system can run the PC simulator.
|
||||||
|
- Portability - The written code is portable, which means you can simply copy it when migrating to embedded hardware.
|
||||||
|
- Easy Validation - The simulator is also very useful to report bugs because it provides a common platform for every user. So it's a good idea to reproduce a bug in the simulator and use that code snippet in the [Forum](https://forum.lvgl.io).
|
||||||
|
|
||||||
|
## Select an IDE
|
||||||
|
|
||||||
|
The simulator is ported to various IDEs (Integrated Development Environments). Choose your favorite IDE, read its README on GitHub, download the project, and load it to the IDE.
|
||||||
|
|
||||||
|
- [Eclipse with SDL driver](https://github.com/lvgl/lv_sim_eclipse_sdl): Recommended on Linux and Mac
|
||||||
|
- [CodeBlocks](https://github.com/lvgl/lv_sim_codeblocks_win): Recommended on Windows
|
||||||
|
- [VisualStudio](https://github.com/lvgl/lv_sim_visual_studio_sdl): For Windows
|
||||||
|
- [VSCode with SDL driver](https://github.com/lvgl/lv_sim_vscode_sdl): Recommended on Linux and Mac
|
||||||
|
- [PlatformIO with SDL driver](https://github.com/lvgl/lv_platformio): Recommended on Linux and Mac
|
||||||
|
- [MDK with FastModel](https://github.com/lvgl/lv_port_an547_cm55_sim): For Windows
|
||||||
|
|
||||||
|
External project not maintained by the LVGL organization:
|
||||||
|
- [QT Creator](https://github.com/Varanda-Labs/lvgl-qt-sim): Cross platform
|
||||||
|
|
||||||
|
You can use any IDE for development but, for simplicity, the configuration for Eclipse CDT is what we'll focus on in this tutorial.
|
||||||
|
The following section describes the set-up guide of Eclipse CDT in more detail.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note: If you are on Windows, it's usually better to use the Visual Studio or CodeBlocks projects instead. They work out of the box without requiring extra steps.**
|
||||||
|
|
||||||
|
## Set-up Eclipse CDT
|
||||||
|
|
||||||
|
### Install Eclipse CDT
|
||||||
|
|
||||||
|
[Eclipse CDT](https://eclipse.org/cdt/) is a C/C++ IDE.
|
||||||
|
|
||||||
|
Eclipse is a Java-based tool so be sure **Java Runtime Environment** is installed on your system.
|
||||||
|
|
||||||
|
On Debian-based distros (e.g. Ubuntu): `sudo apt-get install default-jre`
|
||||||
|
|
||||||
|
Note: If you are using other distros, then please install a 'Java Runtime Environment' suitable to your distro.
|
||||||
|
Note: If you are using macOS and get a "Failed to create the Java Virtual Machine" error, uninstall any other Java JDK installs and install Java JDK 8u. This should fix the problem.
|
||||||
|
|
||||||
|
You can download Eclipse's CDT from: [https://www.eclipse.org/cdt/downloads.php](https://www.eclipse.org/cdt/downloads.php). Start the installer and choose *Eclipse CDT* from the list.
|
||||||
|
|
||||||
|
### Install SDL 2
|
||||||
|
|
||||||
|
The PC simulator uses the [SDL 2](https://www.libsdl.org/download-2.0.php) cross-platform library to simulate a TFT display and a touchpad.
|
||||||
|
|
||||||
|
#### Linux
|
||||||
|
On **Linux** you can easily install SDL2 using a terminal:
|
||||||
|
|
||||||
|
1. Find the current version of SDL2: `apt-cache search libsdl2 (e.g. libsdl2-2.0-0)`
|
||||||
|
2. Install SDL2: `sudo apt-get install libsdl2-2.0-0` (replace with the found version)
|
||||||
|
3. Install SDL2 development package: `sudo apt-get install libsdl2-dev`
|
||||||
|
4. If build essentials are not installed yet: `sudo apt-get install build-essential`
|
||||||
|
|
||||||
|
#### Windows
|
||||||
|
If you are using **Windows** firstly you need to install MinGW ([64 bit version](http://mingw-w64.org/doku.php/download)). After installing MinGW, do the following steps to add SDL2:
|
||||||
|
|
||||||
|
1. Download the development libraries of SDL.
|
||||||
|
Go to [https://www.libsdl.org/download-2.0.php](https://www.libsdl.org/download-2.0.php) and download _Development Libraries: SDL2-devel-2.0.5-mingw.tar.gz_
|
||||||
|
2. Decompress the file and go to _x86_64-w64-mingw32_ directory (for 64 bit MinGW) or to _i686-w64-mingw32_ (for 32 bit MinGW)
|
||||||
|
3. Copy _..._mingw32/include/SDL2_ folder to _C:/MinGW/.../x86_64-w64-mingw32/include_
|
||||||
|
4. Copy _..._mingw32/lib/_ content to _C:/MinGW/.../x86_64-w64-mingw32/lib_
|
||||||
|
5. Copy _..._mingw32/bin/SDL2.dll_ to _{eclipse_workspace}/pc_simulator/Debug/_. Do it later when Eclipse is installed.
|
||||||
|
|
||||||
|
Note: If you are using **Microsoft Visual Studio** instead of Eclipse then you don't have to install MinGW.
|
||||||
|
|
||||||
|
#### OSX
|
||||||
|
On **OSX** you can easily install SDL2 with brew: `brew install sdl2`
|
||||||
|
|
||||||
|
If something is not working, then please refer [this tutorial](http://lazyfoo.net/tutorials/SDL/01_hello_SDL/index.php) to get started with SDL.
|
||||||
|
|
||||||
|
### Pre-configured project
|
||||||
|
|
||||||
|
A pre-configured graphics library project (based on the latest release) is always available to get started easily.
|
||||||
|
You can find the latest one on [GitHub](https://github.com/lvgl/lv_sim_eclipse_sdl).
|
||||||
|
(Please note that, the project is configured for Eclipse CDT).
|
||||||
|
|
||||||
|
### Add the pre-configured project to Eclipse CDT
|
||||||
|
|
||||||
|
Run Eclipse CDT. It will show a dialogue about the **workspace path**. Before accepting the path, check that path and copy (and unzip) the downloaded pre-configured project there. After that, you can accept the workspace path. Of course you can modify this path but in that case copy the project to the corresponding location.
|
||||||
|
|
||||||
|
Close the start-up window and go to **File->Import** and choose **General->Existing project into Workspace**. **Browse the root directory** of the project and click **Finish**
|
||||||
|
|
||||||
|
On **Windows** you have to do two additional things:
|
||||||
|
|
||||||
|
- Copy the **SDL2.dll** into the project's Debug folder
|
||||||
|
- Right-click on the project -> Project properties -> C/C++ Build -> Settings -> Libraries -> Add ... and add _mingw32_ above SDLmain and SDL. (The order is important: mingw32, SDLmain, SDL)
|
||||||
|
|
||||||
|
### Compile and Run
|
||||||
|
|
||||||
|
Now you are ready to run LVGL on your PC. Click on the Hammer Icon on the top menu bar to Build the project. If you have done everything right, then you will not get any errors. Note that on some systems additional steps might be required to "see" SDL 2 from Eclipse but in most cases the configuration in the downloaded project is enough.
|
||||||
|
|
||||||
|
After a successful build, click on the Play button on the top menu bar to run the project. Now a window should appear in the middle of your screen.
|
||||||
|
|
||||||
|
Now you are ready to use LVGL and begin development on your PC.
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
# Renesas
|
||||||
|
The [HMI-Board](https://bit.ly/3I9nfUo) development board SDK now comes with LVGL integration for quick evaluation. Simply download the [SDK](https://github.com/RT-Thread-Studio/sdk-bsp-ra6m3-hmi-board/tree/main/projects/hmi-board-lvgl) for the supported motherboard and you’ll be on your way to creating your next GUI application in no time. For more information, check out the [Software design description](https://github.com/RT-Thread-Studio/sdk-bsp-ra6m3-hmi-board/blob/main/projects/hmi-board-lvgl/README.md).
|
||||||
|
|
||||||
|
## Creating new project with LVGL
|
||||||
|
It is recommended to start your project by downloading the HMI-Board SDK example project. It comes fully equipped with LVGL and dave-2d support (if the modules are present), so you won’t need to do any additional integration work.
|
||||||
|
|
||||||
|
## HW acceleration for Renesas RA6M3 platforms
|
||||||
|
For RA6M3 platforms, hardware acceleration can be achieved using the dave-2d GPU, depending on the platform used. Each accelerator has its own context, allowing them to be used individually or simultaneously in LVGL’s multithreading mode.
|
||||||
|
|
||||||
|
### Dave-2d accelerator
|
||||||
|
LVGL can offload several drawing features to the dave-2d engine, freeing up the CPU for other operations while dave-2d runs. An RTOS is required to block the LVGL drawing thread and switch to another task or suspend the CPU for power savings. Supported draw callbacks can be found in “src/draw/renesas/lv_gpu_d2_ra6m3.c”.
|
||||||
|
|
||||||
|
LVGL can offload several drawing features to the dave-2d engine, freeing up the CPU for other operations while dave-2d runs. An RTOS is required to block the LVGL drawing thread and switch to another task or suspend the CPU for power savings. Supported draw callbacks can be found in “src/draw/renesas/lv_gpu_d2_ra6m3.c”.
|
||||||
|
|
||||||
|
```c
|
||||||
|
ra_2d_draw_ctx->blend = lv_draw_ra6m3_2d_blend;
|
||||||
|
ra_2d_draw_ctx->base_draw.draw_img_decoded = lv_port_gpu_img_decoded;
|
||||||
|
ra_2d_draw_ctx->base_draw.wait_for_finish = lv_port_gpu_wait;
|
||||||
|
ra_2d_draw_ctx->base_draw.draw_letter = lv_draw_gpu_letter;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Features supported:
|
||||||
|
All operations can be used in conjunction with optional transparency.
|
||||||
|
|
||||||
|
- RGB565 and ARGB8888 color formats
|
||||||
|
- Area fill with color
|
||||||
|
- BLIT (BLock Image Transfer)
|
||||||
|
- Color conversion
|
||||||
|
- Rotate and scale
|
||||||
|
- Alpha blending
|
||||||
|
- Bilinear filtering
|
||||||
|
- RTOS integration layer
|
||||||
|
- Default RT-Thread code provided
|
||||||
|
- Subpixel exact placement
|
||||||
|
|
||||||
|
### Basic configuration:
|
||||||
|
- Select Renesas dave-2d engine in lv_conf.h: Set `LV_USE_GPU_RA6M3_G2D` to 1
|
||||||
|
- Set referenced header file in lv_conf.h: `#define LV_GPU_RA6M3_G2D_INCLUDE "hal_data.h"`
|
||||||
|
|
||||||
|
### RT-Thread Example:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define COLOR_BUFFER (LV_HOR_RES_MAX * LV_VER_RES_MAX)
|
||||||
|
|
||||||
|
static lv_disp_drv_t disp_drv;
|
||||||
|
|
||||||
|
/*A static or global variable to store the buffers*/
|
||||||
|
static lv_color_t buf_1[COLOR_BUFFER];
|
||||||
|
```
|
||||||
|
|
||||||
|
- After initializing your peripherals (such as SPI, GPIOs, and LCD) in the `lv_port_disp_init()` function, you can initialize LVGL using [`lv_init()`.](https://docs.lvgl.io/master/API/core/lv_obj.html#_CPPv47lv_initv) Next, register the frame buffers using `lv_disp_draw_buf_init()` and create a new display driver using `lv_disp_drv_init()`.
|
||||||
|
|
||||||
|
```c
|
||||||
|
/*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, RT_NULL, COLOR_BUFFER);
|
||||||
|
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
|
||||||
|
|
||||||
|
/*Set the resolution of the display*/
|
||||||
|
disp_drv.hor_res = LV_HOR_RES_MAX;
|
||||||
|
disp_drv.ver_res = LV_VER_RES_MAX;
|
||||||
|
|
||||||
|
/*Set a display buffer*/
|
||||||
|
disp_drv.draw_buf = &disp_buf;
|
||||||
|
|
||||||
|
/*Used to copy the buffer's content to the display*/
|
||||||
|
disp_drv.flush_cb = disp_flush;
|
||||||
|
|
||||||
|
/* Initialize GPU module */
|
||||||
|
lv_port_gpu_hw_init();
|
||||||
|
|
||||||
|
/*Finally register the driver*/
|
||||||
|
lv_disp_drv_register(&disp_drv);
|
||||||
|
```
|
||||||
|
|
||||||
|
* To run LVGL, you’ll need to create a thread. You can find examples of how to do this using RT-Thread in the `env_support/rt-thread/lv_rt_thread_port.c` file.
|
||||||
|
|
||||||
|
```c
|
||||||
|
static void lvgl_thread_entry(void *parameter)
|
||||||
|
{
|
||||||
|
#if LV_USE_LOG
|
||||||
|
lv_log_register_print_cb(lv_rt_log);
|
||||||
|
#endif /* LV_USE_LOG */
|
||||||
|
lv_init();
|
||||||
|
lv_port_disp_init();
|
||||||
|
lv_port_indev_init();
|
||||||
|
lv_user_gui_init();
|
||||||
|
|
||||||
|
/* handle the tasks of LVGL */
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
lv_task_handler();
|
||||||
|
rt_thread_mdelay(LV_DISP_DEF_REFR_PERIOD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lvgl_thread_init(void)
|
||||||
|
{
|
||||||
|
rt_err_t err;
|
||||||
|
|
||||||
|
/* create lvgl thread */
|
||||||
|
err = rt_thread_init(&lvgl_thread, "LVGL", lvgl_thread_entry, RT_NULL,
|
||||||
|
&lvgl_thread_stack[0], sizeof(lvgl_thread_stack), PKG_LVGL_THREAD_PRIO, 10);
|
||||||
|
if(err != RT_EOK)
|
||||||
|
{
|
||||||
|
LOG_E("Failed to create LVGL thread");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rt_thread_startup(&lvgl_thread);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
INIT_ENV_EXPORT(lvgl_thread_init);
|
||||||
|
```
|
||||||
|
|
||||||
|
- The last step is to create a function to output the frame buffer to your LCD. The specifics of this function will depend on the features of your MCU. Here’s an example for a typical MCU interface: `my_flush_cb`.
|
||||||
|
|
||||||
|
```c
|
||||||
|
static void my_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
|
||||||
|
{
|
||||||
|
#ifdef PKG_USING_ILI9341
|
||||||
|
lcd_fill_array_spi(area->x1, area->y1, area->x2, area->y2, color_p);
|
||||||
|
#elif LV_USE_GPU_RA6M3_G2D
|
||||||
|
lv_port_gpu_blit(area->x1, area->y1, color_p, area);
|
||||||
|
#else
|
||||||
|
......
|
||||||
|
#endif
|
||||||
|
lv_disp_flush_ready(disp_drv);
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
# STM32
|
||||||
|
|
||||||
|
TODO
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Tasmota and berry
|
||||||
|
|
||||||
|
## What is Tasmota?
|
||||||
|
|
||||||
|
[Tasmota](https://github.com/arendst/Tasmota) is a widely used open-source firmware for ESP8266 and EPS32 based devices. It supports a wide variety of devices, sensors and integrations to Home Automation and Cloud services. Tasmota firmware is downloaded more than 200,000 times each month, and has an active and growing community.
|
||||||
|
|
||||||
|
Tasmota provides access to hundreds of supported devices, full support of MQTT, HTTP(S), integration with major Home Automation systems, myriad of sensors, IR, RF, Zigbee, Bluetooth, AWS IoT, Azure IoT, Alexa and many more.
|
||||||
|
|
||||||
|
## What is Berry?
|
||||||
|
|
||||||
|
[Berry](https://github.com/berry-lang/berry) is a ultra-lightweight dynamically typed embedded scripting language. It is designed for lower-performance embedded devices. The interpreter of Berry include a one-pass compiler and register-based VM, all the code is written in ANSI C99. Berry offers a syntax very similar to Python, and is inspired from LUA VM. It is fully integrated in Tasmota
|
||||||
|
|
||||||
|
### Highlights of Berry
|
||||||
|
|
||||||
|
Berry has the following advantages:
|
||||||
|
|
||||||
|
- Lightweight: A well-optimized interpreter with very little resources. Ideal for use in microprocessors.
|
||||||
|
- Fast: optimized one-pass bytecode compiler and register-based virtual machine.
|
||||||
|
- Powerful: supports imperative programming, object-oriented programming, functional programming.
|
||||||
|
- Flexible: Berry is a dynamic type script, and it's intended for embedding in applications. It can provide good dynamic scalability for the host system.
|
||||||
|
- Simple: simple and natural syntax, support garbage collection, and easy to use FFI (foreign function interface).
|
||||||
|
- RAM saving: With compile-time object construction, most of the constant objects are stored in read-only code data segments, so the RAM usage of the interpreter is very low when it starts.
|
||||||
|
|
||||||
|
All features are detailed in the [Berry Reference Manual](https://github.com/berry-lang/berry/wiki/Reference)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Why LVGL + Tasmota + Berry?
|
||||||
|
|
||||||
|
In 2021, Tasmota added full support of LVGL for ESP32 based devices. It also introduced the Berry scripting language, a small-footprint language similar to Python and fully integrated in Tasmota.
|
||||||
|
|
||||||
|
A comprehensive mapping of LVGL in Berry language is now available, similar to the mapping of Micropython. It allows to use +98% of all LVGL features. It is also possible to write custom widgets in Berry.
|
||||||
|
|
||||||
|
Versions supported: LVGL v8.3.0, LodePNG v20201017, Freetype 2.10.4
|
||||||
|
|
||||||
|
### Tasmota + Berry + LVGL could be used for:
|
||||||
|
|
||||||
|
- Fast prototyping GUI.
|
||||||
|
- Shortening the cycle of changing and fine-tuning the GUI.
|
||||||
|
- Modelling the GUI in a more abstract way by defining reusable composite objects, taking advantage of Berry's language features such as Inheritance, Closures, Exception Handling...
|
||||||
|
- Make LVGL accessible to a larger audience. No need to know C to create a nice GUI on an embedded system.
|
||||||
|
|
||||||
|
A higher level interface compatible with [OpenHASP](https://github.com/HASwitchPlate/openHASP) is also under development.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## So what does it look like?
|
||||||
|
|
||||||
|
> TL;DR:
|
||||||
|
> Similar to MicroPython, it's very much like the C API, but Object-Oriented for LVGL components.
|
||||||
|
|
||||||
|
Let's dive right into an example!
|
||||||
|
|
||||||
|
### A simple example
|
||||||
|
|
||||||
|
```python
|
||||||
|
lv.start() # start LVGL
|
||||||
|
scr = lv.scr_act() # 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
|
||||||
|
```
|
||||||
|
|
||||||
|
## How can I use it?
|
||||||
|
|
||||||
|
You can start in less than 10 minutes on a M5Stack or equivalent device in less than 10 minutes in this [short tutorial](https://tasmota.github.io/docs/LVGL_in_10_minutes/)
|
||||||
|
|
||||||
|
## Where can I find more information?
|
||||||
|
|
||||||
|
- [Tasmota Documentation](https://tasmota.github.io/docs/)
|
||||||
|
- [Berry Documentation](https://github.com/berry-lang/berry/wiki/Reference)
|
||||||
|
- [Tasmota LVGL Berry documentation](https://tasmota.github.io/docs/LVGL/)
|
||||||
@@ -0,0 +1,266 @@
|
|||||||
|
|
||||||
|
# Quick overview
|
||||||
|
|
||||||
|
Here you can learn the most important things about LVGL.
|
||||||
|
You should read this first to get a general impression and read the detailed [Porting](/porting/index) and [Overview](/overview/index) sections after that.
|
||||||
|
|
||||||
|
## Get started in a simulator
|
||||||
|
|
||||||
|
Instead of porting LVGL to embedded hardware straight away, it's highly recommended to get started in a simulator first.
|
||||||
|
|
||||||
|
LVGL is ported to many IDEs to be sure you will find your favorite one.
|
||||||
|
Go to the [Simulators](/get-started/pc-simulator) section to get ready-to-use projects that can be run on your PC.
|
||||||
|
This way you can save the time of porting for now and get some experience with LVGL immediately.
|
||||||
|
|
||||||
|
## Add LVGL into your project
|
||||||
|
If you would rather try LVGL on your own project follow these steps:
|
||||||
|
|
||||||
|
- [Download](https://github.com/lvgl/lvgl/archive/master.zip) or clone the library from GitHub with `git clone https://github.com/lvgl/lvgl.git`.
|
||||||
|
- Copy the `lvgl` folder into your project.
|
||||||
|
- Copy `lvgl/lv_conf_template.h` as `lv_conf.h` next to the `lvgl` folder, change the first `#if 0` to `1` to enable the file's content and set the `LV_COLOR_DEPTH` defines.
|
||||||
|
- Include `lvgl/lvgl.h` in files where you need to use LVGL related functions.
|
||||||
|
- Call `lv_tick_inc(x)` every `x` milliseconds in a Timer or Task (`x` should be between 1 and 10). It is required for the internal timing of LVGL.
|
||||||
|
Alternatively, configure `LV_TICK_CUSTOM` (see `lv_conf.h`) so that LVGL can retrieve the current time directly.
|
||||||
|
- Call `lv_init()`
|
||||||
|
- Create a draw buffer: LVGL will render the graphics here first, and send the rendered image to the display.
|
||||||
|
The buffer size can be set freely but 1/10 screen size is a good starting point.
|
||||||
|
```c
|
||||||
|
static lv_disp_draw_buf_t draw_buf;
|
||||||
|
static lv_color_t buf1[DISP_HOR_RES * DISP_VER_RES / 10]; /*Declare a buffer for 1/10 screen size*/
|
||||||
|
lv_disp_draw_buf_init(&draw_buf, buf1, NULL, MY_DISP_HOR_RES * MY_DISP_VER_SER / 10); /*Initialize the display buffer.*/
|
||||||
|
```
|
||||||
|
- Implement and register a function which can copy the rendered image to an area of your display:
|
||||||
|
```c
|
||||||
|
static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
|
||||||
|
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
|
||||||
|
disp_drv.flush_cb = my_disp_flush; /*Set your driver function*/
|
||||||
|
disp_drv.draw_buf = &draw_buf; /*Assign the buffer to the display*/
|
||||||
|
disp_drv.hor_res = MY_DISP_HOR_RES; /*Set the horizontal resolution of the display*/
|
||||||
|
disp_drv.ver_res = MY_DISP_VER_RES; /*Set the vertical resolution of the display*/
|
||||||
|
lv_disp_drv_register(&disp_drv); /*Finally register the driver*/
|
||||||
|
|
||||||
|
void my_disp_flush(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p)
|
||||||
|
{
|
||||||
|
int32_t x, y;
|
||||||
|
/*It's a very slow but simple implementation.
|
||||||
|
*`set_pixel` needs to be written by you to a set pixel on the screen*/
|
||||||
|
for(y = area->y1; y <= area->y2; y++) {
|
||||||
|
for(x = area->x1; x <= area->x2; x++) {
|
||||||
|
set_pixel(x, y, *color_p);
|
||||||
|
color_p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_disp_flush_ready(disp); /* Indicate you are ready with the flushing*/
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
- Implement and register a function which can read an input device. E.g. for a touchpad:
|
||||||
|
```c
|
||||||
|
static lv_indev_drv_t indev_drv; /*Descriptor of a input device driver*/
|
||||||
|
lv_indev_drv_init(&indev_drv); /*Basic initialization*/
|
||||||
|
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
|
||||||
|
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
|
||||||
|
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
|
||||||
|
|
||||||
|
void my_touchpad_read(lv_indev_t * indev, lv_indev_data_t * data)
|
||||||
|
{
|
||||||
|
/*`touchpad_is_pressed` and `touchpad_get_xy` needs to be implemented by you*/
|
||||||
|
if(touchpad_is_pressed()) {
|
||||||
|
data->state = LV_INDEV_STATE_PRESSED;
|
||||||
|
touchpad_get_xy(&data->point.x, &data->point.y);
|
||||||
|
} else {
|
||||||
|
data->state = LV_INDEV_STATE_RELEASED;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Call `lv_timer_handler()` periodically every few milliseconds in the main `while(1)` loop or in an operating system task.
|
||||||
|
It will redraw the screen if required, handle input devices, animation etc.
|
||||||
|
|
||||||
|
For a more detailed guide go to the [Porting](/porting/index) section.
|
||||||
|
|
||||||
|
## Learn the basics
|
||||||
|
|
||||||
|
### Widgets
|
||||||
|
|
||||||
|
The graphical elements like Buttons, Labels, Sliders, Charts etc. are called objects or widgets. Go to [Widgets](/widgets/index) to see the full list of available widgets.
|
||||||
|
|
||||||
|
Every object has a parent object where it is created. For example, if a label is created on a button, the button is the parent of label.
|
||||||
|
|
||||||
|
The child object moves with the parent and if the parent is deleted the children will be deleted too.
|
||||||
|
|
||||||
|
Children can be visible only within their parent's bounding area. In other words, the parts of the children outside the parent are clipped.
|
||||||
|
|
||||||
|
A Screen is the "root" parent. You can have any number of screens.
|
||||||
|
|
||||||
|
To get the current screen call `lv_scr_act()`, and to load a screen use `lv_scr_load(scr1)`.
|
||||||
|
|
||||||
|
You can create a new object with `lv_<type>_create(parent)`. It will return an `lv_obj_t *` variable that can be used as a reference to the object to set its parameters.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
```c
|
||||||
|
lv_obj_t * slider1 = lv_slider_create(lv_scr_act());
|
||||||
|
```
|
||||||
|
|
||||||
|
To set some basic attributes `lv_obj_set_<parameter_name>(obj, <value>)` functions can be used. For example:
|
||||||
|
```c
|
||||||
|
lv_obj_set_x(btn1, 30);
|
||||||
|
lv_obj_set_y(btn1, 10);
|
||||||
|
lv_obj_set_size(btn1, 200, 50);
|
||||||
|
```
|
||||||
|
|
||||||
|
Along with the basic attributes, widgets can have type specific parameters which are set by `lv_<widget_type>_set_<parameter_name>(obj, <value>)` functions. For example:
|
||||||
|
```c
|
||||||
|
lv_slider_set_value(slider1, 70, LV_ANIM_ON);
|
||||||
|
```
|
||||||
|
|
||||||
|
To see the full API visit the documentation of the widgets or the related header file (e.g. [lvgl/src/widgets/lv_slider.h](https://github.com/lvgl/lvgl/blob/master/src/widgets/lv_slider.h)).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Events
|
||||||
|
Events are used to inform the user that something has happened with an object.
|
||||||
|
You can assign one or more callbacks to an object which will be called if the object is clicked, released, dragged, being deleted, etc.
|
||||||
|
|
||||||
|
A callback is assigned like this:
|
||||||
|
|
||||||
|
```c
|
||||||
|
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
void btn_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
printf("Clicked\n");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`LV_EVENT_ALL` can be used instead of `LV_EVENT_CLICKED` to invoke the callback for any event.
|
||||||
|
|
||||||
|
From `lv_event_t * e` the current event code can be retrieved with:
|
||||||
|
```c
|
||||||
|
lv_event_code_t code = lv_event_get_code(e);
|
||||||
|
```
|
||||||
|
|
||||||
|
The object that triggered the event can be retrieved with:
|
||||||
|
```c
|
||||||
|
lv_obj_t * obj = lv_event_get_target(e);
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn all features of the events go to the [Event overview](/overview/event) section.
|
||||||
|
|
||||||
|
### Parts
|
||||||
|
Widgets might be built from one or more *parts*. For example, a button has only one part called `LV_PART_MAIN`.
|
||||||
|
However, a [Slider](/widgets/core/slider) has `LV_PART_MAIN`, `LV_PART_INDICATOR` and `LV_PART_KNOB`.
|
||||||
|
|
||||||
|
By using parts you can apply different styles to sub-elements of a widget. (See below)
|
||||||
|
|
||||||
|
Read the widgets' documentation to learn which parts each uses.
|
||||||
|
|
||||||
|
### States
|
||||||
|
LVGL objects can be in a combination of the following states:
|
||||||
|
- `LV_STATE_DEFAULT` Normal, released state
|
||||||
|
- `LV_STATE_CHECKED` Toggled or checked state
|
||||||
|
- `LV_STATE_FOCUSED` Focused via keypad or encoder or clicked via touchpad/mouse
|
||||||
|
- `LV_STATE_FOCUS_KEY` Focused via keypad or encoder but not via touchpad/mouse
|
||||||
|
- `LV_STATE_EDITED` Edit by an encoder
|
||||||
|
- `LV_STATE_HOVERED` Hovered by mouse (not supported now)
|
||||||
|
- `LV_STATE_PRESSED` Being pressed
|
||||||
|
- `LV_STATE_SCROLLED` Being scrolled
|
||||||
|
- `LV_STATE_DISABLED` Disabled
|
||||||
|
|
||||||
|
For example, if you press an object it will automatically go to the `LV_STATE_FOCUSED` and `LV_STATE_PRESSED` states and when you release it the `LV_STATE_PRESSED` state will be removed while focus remains active.
|
||||||
|
|
||||||
|
To check if an object is in a given state use `lv_obj_has_state(obj, LV_STATE_...)`. It will return `true` if the object is currently in that state.
|
||||||
|
|
||||||
|
To manually add or remove states use:
|
||||||
|
```c
|
||||||
|
lv_obj_add_state(obj, LV_STATE_...);
|
||||||
|
lv_obj_clear_state(obj, LV_STATE_...);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Styles
|
||||||
|
A style instance contains properties such as background color, border width, font, etc. that describe the appearance of objects.
|
||||||
|
|
||||||
|
Styles are represented with `lv_style_t` variables. Only their pointer is saved in the objects so they need to be defined as static or global.
|
||||||
|
Before using a style it needs to be initialized with `lv_style_init(&style1)`. After that, properties can be added to configure the style. For example:
|
||||||
|
```
|
||||||
|
static lv_style_t style1;
|
||||||
|
lv_style_init(&style1);
|
||||||
|
lv_style_set_bg_color(&style1, lv_color_hex(0xa03080))
|
||||||
|
lv_style_set_border_width(&style1, 2))
|
||||||
|
```
|
||||||
|
See the full list of properties [here](/overview/style.html#properties).
|
||||||
|
|
||||||
|
|
||||||
|
Styles are assigned using the ORed combination of an object's part and state. For example to use this style on the slider's indicator when the slider is pressed:
|
||||||
|
```c
|
||||||
|
lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR | LV_STATE_PRESSED);
|
||||||
|
```
|
||||||
|
|
||||||
|
If the *part* is `LV_PART_MAIN` it can be omitted:
|
||||||
|
```c
|
||||||
|
lv_obj_add_style(btn1, &style1, LV_STATE_PRESSED); /*Equal to LV_PART_MAIN | LV_STATE_PRESSED*/
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly, `LV_STATE_DEFAULT` can be omitted too:
|
||||||
|
```c
|
||||||
|
lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR); /*Equal to LV_PART_INDICATOR | LV_STATE_DEFAULT*/
|
||||||
|
```
|
||||||
|
|
||||||
|
For `LV_STATE_DEFAULT` and `LV_PART_MAIN` simply write `0`:
|
||||||
|
```c
|
||||||
|
lv_obj_add_style(btn1, &style1, 0); /*Equal to LV_PART_MAIN | LV_STATE_DEFAULT*/
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Styles can be cascaded (similarly to CSS). It means you can add more styles to a part of an object.
|
||||||
|
For example `style_btn` can set a default button appearance, and `style_btn_red` can overwrite the background color to make the button red:
|
||||||
|
```c
|
||||||
|
lv_obj_add_style(btn1, &style_btn, 0);
|
||||||
|
lv_obj_add_style(btn1, &style1_btn_red, 0);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
If a property is not set on for the current state, the style with `LV_STATE_DEFAULT` will be used. A default value is used if the property is not defined in the default state.
|
||||||
|
|
||||||
|
Some properties (typically the text-related ones) can be inherited. This means if a property is not set in an object it will be searched for in its parents too.
|
||||||
|
For example, you can set the font once in the screen's style and all text on that screen will inherit it by default.
|
||||||
|
|
||||||
|
|
||||||
|
Local style properties also can be added to objects. This creates a style which resides inside the object and is used only by the object:
|
||||||
|
```c
|
||||||
|
lv_obj_set_style_bg_color(slider1, lv_color_hex(0x2080bb), LV_PART_INDICATOR | LV_STATE_PRESSED);
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn all the features of styles see the [Style overview](/overview/style) section.
|
||||||
|
|
||||||
|
|
||||||
|
### Themes
|
||||||
|
|
||||||
|
Themes are the default styles for objects. Styles from a theme are applied automatically when objects are created.
|
||||||
|
|
||||||
|
The theme for your application is a compile time configuration set in `lv_conf.h`.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/get_started/index.rst
|
||||||
|
```
|
||||||
|
|
||||||
|
## Micropython
|
||||||
|
Learn more about [Micropython](/get-started/micropython).
|
||||||
|
```python
|
||||||
|
# Create a Button and a Label
|
||||||
|
scr = lv.obj()
|
||||||
|
btn = lv.btn(scr)
|
||||||
|
btn.align(lv.scr_act(), lv.ALIGN.CENTER, 0, 0)
|
||||||
|
label = lv.label(btn)
|
||||||
|
label.set_text("Button")
|
||||||
|
|
||||||
|
# Load the screen
|
||||||
|
lv.scr_load(scr)
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
PDF version: :download:`LVGL.pdf <LVGL.pdf>`
|
||||||
|
```
|
||||||
|
|
||||||
|
# Welcome to the documentation of LVGL!
|
||||||
|
|
||||||
|
<img src="_static/img/home_banner.jpg" style="width:100%">
|
||||||
|
|
||||||
|
|
||||||
|
<div style="margin-bottom:48px">
|
||||||
|
<a href="intro/index.html"><img class="home-img" src="_static/img/home_1.png" alt="Get familiar with the LVGL project"></a>
|
||||||
|
<a href="get-started/index.html"><img class="home-img" src="_static/img/home_2.png" alt="Learn the basic of LVGL and its usage on various platforms"></a>
|
||||||
|
<a href="porting/index.html"><img class="home-img" src="_static/img/home_3.png" alt="See how to port LVGL to any platform"></a>
|
||||||
|
<a href="overview/index.html"><img class="home-img" src="_static/img/home_4.png" alt="Learn the how LVGL works in more detail"></a>
|
||||||
|
<a href="widgets/index.html"><img class="home-img" src="_static/img/home_5.png" alt="Take a look at the description of the available widgets"></a>
|
||||||
|
<a href="CONTRIBUTING.html"><img class="home-img" src="_static/img/home_6.png" alt="Be part of the development of LVGL"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
intro/index
|
||||||
|
examples
|
||||||
|
get-started/index
|
||||||
|
porting/index
|
||||||
|
overview/index
|
||||||
|
widgets/index
|
||||||
|
layouts/index
|
||||||
|
libs/index
|
||||||
|
others/index
|
||||||
|
CONTRIBUTING
|
||||||
|
CHANGELOG
|
||||||
|
ROADMAP
|
||||||
|
```
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
LVGL (Light and Versatile Graphics Library) is a free and open-source graphics library providing everything you need to create an embedded GUI with easy-to-use graphical elements, beautiful visual effects and a low memory footprint.
|
||||||
|
|
||||||
|
|
||||||
|
## Key features
|
||||||
|
- Powerful building blocks such as buttons, charts, lists, sliders, images, etc.
|
||||||
|
- Advanced graphics with animations, anti-aliasing, opacity, smooth scrolling
|
||||||
|
- Various input devices such as touchpad, mouse, keyboard, encoder, etc.
|
||||||
|
- Multi-language support with UTF-8 encoding
|
||||||
|
- Multi-display support, i.e. use multiple TFT, monochrome displays simultaneously
|
||||||
|
- Fully customizable graphic elements with CSS-like styles
|
||||||
|
- Hardware independent: use with any microcontroller or display
|
||||||
|
- Scalable: able to operate with little memory (64 kB Flash, 16 kB RAM)
|
||||||
|
- OS, external memory and GPU are supported but not required
|
||||||
|
- Single frame buffer operation even with advanced graphic effects
|
||||||
|
- Written in C for maximal compatibility (C++ compatible)
|
||||||
|
- Simulator to start embedded GUI design on a PC without embedded hardware
|
||||||
|
- Binding to MicroPython
|
||||||
|
- Tutorials, examples, themes for rapid GUI design
|
||||||
|
- Documentation is available online and as PDF
|
||||||
|
- Free and open-source under MIT license
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
Basically, every modern controller which is able to drive a display is suitable to run LVGL. The minimal requirements are:
|
||||||
|
<ul>
|
||||||
|
<li> 16, 32 or 64 bit microcontroller or processor</li>
|
||||||
|
<li>> 16 MHz clock speed is recommended</li>
|
||||||
|
<li> Flash/ROM: > 64 kB for the very essential components (> 180 kB is recommended)</li>
|
||||||
|
<li> RAM:
|
||||||
|
<ul>
|
||||||
|
<li> Static RAM usage: ~2 kB depending on the used features and object types</li>
|
||||||
|
<li> Stack: > 2kB (> 8 kB is recommended)</li>
|
||||||
|
<li> Dynamic data (heap): > 4 KB (> 48 kB is recommended if using several objects).
|
||||||
|
Set by <em>LV_MEM_SIZE</em> in <em>lv_conf.h</em>. </li>
|
||||||
|
<li> Display buffer: > <em>"Horizontal resolution"</em> pixels (> 10 × <em>"Horizontal resolution"</em> is recommended) </li>
|
||||||
|
<li> One frame buffer in the MCU or in an external display controller</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li> C99 or newer compiler</li>
|
||||||
|
<li> Basic C (or C++) knowledge:
|
||||||
|
<a href="https://www.tutorialspoint.com/cprogramming/c_pointers.htm">pointers</a>,
|
||||||
|
<a href="https://www.tutorialspoint.com/cprogramming/c_structures.htm">structs</a>,
|
||||||
|
<a href="https://www.geeksforgeeks.org/callbacks-in-c/">callbacks</a>.</li>
|
||||||
|
</ul>
|
||||||
|
<em>Note that memory usage may vary depending on architecture, compiler and build options.</em>
|
||||||
|
|
||||||
|
## License
|
||||||
|
The LVGL project (including all repositories) is licensed under [MIT license](https://github.com/lvgl/lvgl/blob/master/LICENCE.txt).
|
||||||
|
This means you can use it even in commercial projects.
|
||||||
|
|
||||||
|
It's not mandatory, but we highly appreciate it if you write a few words about your project in the [My projects](https://forum.lvgl.io/c/my-projects/10) category of the forum or a private message to [lvgl.io](https://lvgl.io/#contact).
|
||||||
|
|
||||||
|
Although you can get LVGL for free there is a massive amount of work behind it. It's created by a group of volunteers who made it available for you in their free time.
|
||||||
|
|
||||||
|
To make the LVGL project sustainable, please consider [contributing](/CONTRIBUTING) to the project.
|
||||||
|
You can choose from [many different ways of contributing](/CONTRIBUTING) such as simply writing a tweet about you using LVGL, fixing bugs, translating the documentation, or even becoming a maintainer.
|
||||||
|
|
||||||
|
## Repository layout
|
||||||
|
All repositories of the LVGL project are hosted on GitHub: https://github.com/lvgl
|
||||||
|
|
||||||
|
You will find these repositories there:
|
||||||
|
- [lvgl](https://github.com/lvgl/lvgl) The library itself with many [examples](https://github.com/lvgl/lvgl/blob/master/examples/) and [demos](https://github.com/lvgl/lvgl/blob/master/demos/).
|
||||||
|
- [lv_drivers](https://github.com/lvgl/lv_drivers) Display and input device drivers
|
||||||
|
- [blog](https://github.com/lvgl/blog) Source of the blog's site (https://blog.lvgl.io)
|
||||||
|
- [sim](https://github.com/lvgl/sim) Source of the online simulator's site (https://sim.lvgl.io)
|
||||||
|
- [lv_port_...](https://github.com/lvgl?q=lv_port&type=&language=) LVGL ports to development boards or environments
|
||||||
|
- [lv_binding_..](https://github.com/lvgl?q=lv_binding&type=&language=l) Bindings to other languages
|
||||||
|
|
||||||
|
## Release policy
|
||||||
|
|
||||||
|
The core repositories follow the rules of [Semantic versioning](https://semver.org/):
|
||||||
|
- Major versions for incompatible API changes. E.g. v5.0.0, v6.0.0
|
||||||
|
- Minor version for new but backward-compatible functionalities. E.g. v6.1.0, v6.2.0
|
||||||
|
- Patch version for backward-compatible bug fixes. E.g. v6.1.1, v6.1.2
|
||||||
|
|
||||||
|
Tags like `vX.Y.Z` are created for every release.
|
||||||
|
|
||||||
|
### Release cycle
|
||||||
|
- Bug fixes: Released on demand even weekly
|
||||||
|
- Minor releases: Every 3-4 months
|
||||||
|
- Major releases: Approximately yearly
|
||||||
|
|
||||||
|
### Branches
|
||||||
|
The core repositories have at least the following branches:
|
||||||
|
- `master` latest version, patches are merged directly here.
|
||||||
|
- `release/vX.Y` stable versions of the minor releases
|
||||||
|
- `fix/some-description` temporary branches for bug fixes
|
||||||
|
- `feat/some-description` temporary branches for features
|
||||||
|
|
||||||
|
|
||||||
|
### Changelog
|
||||||
|
|
||||||
|
The changes are recorded in [CHANGELOG.md](/CHANGELOG).
|
||||||
|
|
||||||
|
### Version support
|
||||||
|
Before v8 the last minor release of each major series was supported for 1 year.
|
||||||
|
Starting from v8, every minor release is supported for 1 year.
|
||||||
|
|
||||||
|
| Version | Release date | Support end | Active |
|
||||||
|
|---------|--------------|-------------|--------|
|
||||||
|
| v5.3 | Feb 1, 2019 |Feb 1, 2020 | No |
|
||||||
|
| v6.1 | Nov 26, 2019 |Nov 26, 2020 | No |
|
||||||
|
| v7.11 | Mar 16, 2021 |Mar 16, 2022 | No |
|
||||||
|
| v8.0 | 1 Jun, 2021 |1 Jun, 2022 | Yes |
|
||||||
|
| v8.1 | 10 Nov, 2021 |10 Nov, 2022 | Yes |
|
||||||
|
| v8.2 | 31 Jan, 2022 |31 Jan, 2023 | Yes |
|
||||||
|
| v8.3 | In progress | | |
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### Where can I ask questions?
|
||||||
|
You can ask questions in the forum: [https://forum.lvgl.io/](https://forum.lvgl.io/).
|
||||||
|
|
||||||
|
We use [GitHub issues](https://github.com/lvgl/lvgl/issues) for development related discussion.
|
||||||
|
You should use them only if your question or issue is tightly related to the development of the library.
|
||||||
|
|
||||||
|
Before posting a question, please ready this FAQ section as you might find answer to your issue here too.
|
||||||
|
|
||||||
|
### Is my MCU/hardware supported?
|
||||||
|
Every MCU which is capable of driving a display via parallel port, SPI, RGB interface or anything else and fulfills the [Requirements](#requirements) is supported by LVGL.
|
||||||
|
|
||||||
|
This includes:
|
||||||
|
- "Common" MCUs like STM32F, STM32H, NXP Kinetis, LPC, iMX, dsPIC33, PIC32, SWM341 etc.
|
||||||
|
- Bluetooth, GSM, Wi-Fi modules like Nordic NRF and Espressif ESP32
|
||||||
|
- Linux with frame buffer device such as /dev/fb0. This includes Single-board computers like the Raspberry Pi
|
||||||
|
- Anything else with a strong enough MCU and a peripheral to drive a display
|
||||||
|
|
||||||
|
### Is my display supported?
|
||||||
|
LVGL needs just one simple driver function to copy an array of pixels into a given area of the display.
|
||||||
|
If you can do this with your display then you can use it with LVGL.
|
||||||
|
|
||||||
|
Some examples of the supported display types:
|
||||||
|
- TFTs with 16 or 32 bit color depth
|
||||||
|
- Monitors with an HDMI port
|
||||||
|
- Small monochrome displays
|
||||||
|
- Gray-scale displays
|
||||||
|
- even LED matrices
|
||||||
|
- or any other display where you can control the color/state of the pixels
|
||||||
|
|
||||||
|
See the [Porting](/porting/display) section to learn more.
|
||||||
|
|
||||||
|
### LVGL doesn't start, randomly crashes or nothing is drawn on the display. What can be the problem?
|
||||||
|
- Try increasing `LV_MEM_SIZE`.
|
||||||
|
- Be sure `lv_disp_drv_t`, `lv_indev_drv_t` and `lv_fs_drv_t` are global or `static`.
|
||||||
|
- Be sure your display works without LVGL. E.g. paint it to red on start up.
|
||||||
|
- Enable [Logging](porting/log)
|
||||||
|
- Enable asserts in `lv_conf.h` (`LV_USE_ASSERT_...`)
|
||||||
|
- If you use an RTOS
|
||||||
|
- increase the stack size of the task which calls `lv_timer_handler()`
|
||||||
|
- Be sure you used a mutex as [described here](/porting/os)
|
||||||
|
|
||||||
|
### My display driver is not called. What have I missed?
|
||||||
|
Be sure you are calling `lv_tick_inc(x)` in an interrupt and `lv_timer_handler()` in your main `while(1)`.
|
||||||
|
|
||||||
|
Learn more in the [Tick](/porting/tick) and [Timer handler](/porting/timer-handler) sections.
|
||||||
|
|
||||||
|
### Why is the display driver called only once? Only the upper part of the display is refreshed.
|
||||||
|
Be sure you are calling `lv_disp_flush_ready(drv)` at the end of your "*display flush callback*".
|
||||||
|
|
||||||
|
### Why do I see only garbage on the screen?
|
||||||
|
Probably there a bug in your display driver. Try the following code without using LVGL. You should see a square with red-blue gradient.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define BUF_W 20
|
||||||
|
#define BUF_H 10
|
||||||
|
|
||||||
|
lv_color_t buf[BUF_W * BUF_H];
|
||||||
|
lv_color_t * buf_p = buf;
|
||||||
|
uint16_t x, y;
|
||||||
|
for(y = 0; y < BUF_H; y++) {
|
||||||
|
lv_color_t c = lv_color_mix(LV_COLOR_BLUE, LV_COLOR_RED, (y * 255) / BUF_H);
|
||||||
|
for(x = 0; x < BUF_W; x++){
|
||||||
|
(*buf_p) = c;
|
||||||
|
buf_p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_area_t a;
|
||||||
|
a.x1 = 10;
|
||||||
|
a.y1 = 40;
|
||||||
|
a.x2 = a.x1 + BUF_W - 1;
|
||||||
|
a.y2 = a.y1 + BUF_H - 1;
|
||||||
|
my_flush_cb(NULL, &a, buf);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Why do I see nonsense colors on the screen?
|
||||||
|
Probably LVGL's color format is not compatible with your display's color format. Check `LV_COLOR_DEPTH` in *lv_conf.h*.
|
||||||
|
|
||||||
|
If you are using 16-bit colors with SPI (or another byte-oriented interface) you probably need to set `LV_COLOR_16_SWAP 1` in *lv_conf.h*.
|
||||||
|
It swaps the upper and lower bytes of the pixels.
|
||||||
|
|
||||||
|
### How to speed up my UI?
|
||||||
|
- Turn on compiler optimization and enable cache if your MCU has it
|
||||||
|
- Increase the size of the display buffer
|
||||||
|
- Use two display buffers and flush the buffer with DMA (or similar peripheral) in the background
|
||||||
|
- Increase the clock speed of the SPI or parallel port if you use them to drive the display
|
||||||
|
- If your display has an SPI port consider changing to a model with a parallel interface because it has much higher throughput
|
||||||
|
- Keep the display buffer in internal RAM (not in external SRAM) because LVGL uses it a lot and it should have a fast access time
|
||||||
|
|
||||||
|
### How to reduce flash/ROM usage?
|
||||||
|
You can disable all the unused features (such as animations, file system, GPU etc.) and object types in *lv_conf.h*.
|
||||||
|
|
||||||
|
If you are using GCC/CLANG you can add `-fdata-sections -ffunction-sections` compiler flags and `--gc-sections` linker flag to remove unused functions and variables from the final binary. If possible, add the `-flto` compiler flag to enable link-time-optimisation together with `-Os` for GCC or `-Oz` for CLANG.
|
||||||
|
|
||||||
|
### How to reduce the RAM usage
|
||||||
|
- Lower the size of the *Display buffer*
|
||||||
|
- Reduce `LV_MEM_SIZE` in *lv_conf.h*. This memory is used when you create objects like buttons, labels, etc.
|
||||||
|
- To work with lower `LV_MEM_SIZE` you can create objects only when required and delete them when they are not needed anymore
|
||||||
|
|
||||||
|
### How to work with an operating system?
|
||||||
|
|
||||||
|
To work with an operating system where tasks can interrupt each other (preemptively) you should protect LVGL related function calls with a mutex.
|
||||||
|
See the [Operating system and interrupts](/porting/os) section to learn more.
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
|
||||||
|
# Flex
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Flexbox (or Flex for short) is a subset of [CSS Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/).
|
||||||
|
|
||||||
|
It can arrange items into rows or columns (tracks), handle wrapping, adjust the spacing between the items and tracks, handle *grow* to make the item(s) fill the remaining space with respect to min/max width and height.
|
||||||
|
|
||||||
|
To make an object flex container call `lv_obj_set_layout(obj, LV_LAYOUT_FLEX)`.
|
||||||
|
|
||||||
|
Note that the flex layout feature of LVGL needs to be globally enabled with `LV_USE_FLEX` in `lv_conf.h`.
|
||||||
|
|
||||||
|
## Terms
|
||||||
|
- tracks: the rows or columns
|
||||||
|
- main direction: row or column, the direction in which the items are placed
|
||||||
|
- cross direction: perpendicular to the main direction
|
||||||
|
- wrap: if there is no more space in the track a new track is started
|
||||||
|
- grow: if set on an item it will grow to fill the remaining space on the track.
|
||||||
|
The available space will be distributed among items respective to their grow value (larger value means more space)
|
||||||
|
- gap: the space between the rows and columns or the items on a track
|
||||||
|
|
||||||
|
## Simple interface
|
||||||
|
|
||||||
|
With the following functions you can set a Flex layout on any parent.
|
||||||
|
|
||||||
|
### Flex flow
|
||||||
|
|
||||||
|
`lv_obj_set_flex_flow(obj, flex_flow)`
|
||||||
|
|
||||||
|
The possible values for `flex_flow` are:
|
||||||
|
- `LV_FLEX_FLOW_ROW` Place the children in a row without wrapping
|
||||||
|
- `LV_FLEX_FLOW_COLUMN` Place the children in a column without wrapping
|
||||||
|
- `LV_FLEX_FLOW_ROW_WRAP` Place the children in a row with wrapping
|
||||||
|
- `LV_FLEX_FLOW_COLUMN_WRAP` Place the children in a column with wrapping
|
||||||
|
- `LV_FLEX_FLOW_ROW_REVERSE` Place the children in a row without wrapping but in reversed order
|
||||||
|
- `LV_FLEX_FLOW_COLUMN_REVERSE` Place the children in a column without wrapping but in reversed order
|
||||||
|
- `LV_FLEX_FLOW_ROW_WRAP_REVERSE` Place the children in a row with wrapping but in reversed order
|
||||||
|
- `LV_FLEX_FLOW_COLUMN_WRAP_REVERSE` Place the children in a column with wrapping but in reversed order
|
||||||
|
|
||||||
|
### Flex align
|
||||||
|
To manage the placement of the children use `lv_obj_set_flex_align(obj, main_place, cross_place, track_cross_place)`
|
||||||
|
|
||||||
|
- `main_place` determines how to distribute the items in their track on the main axis. E.g. flush the items to the right on `LV_FLEX_FLOW_ROW_WRAP`. (It's called `justify-content` in CSS)
|
||||||
|
- `cross_place` determines how to distribute the items in their track on the cross axis. E.g. if the items have different height place them to the bottom of the track. (It's called `align-items` in CSS)
|
||||||
|
- `track_cross_place` determines how to distribute the tracks (It's called `align-content` in CSS)
|
||||||
|
|
||||||
|
The possible values are:
|
||||||
|
- `LV_FLEX_ALIGN_START` means left on a horizontally and top vertically. (default)
|
||||||
|
- `LV_FLEX_ALIGN_END` means right on a horizontally and bottom vertically
|
||||||
|
- `LV_FLEX_ALIGN_CENTER` simply center
|
||||||
|
- `LV_FLEX_ALIGN_SPACE_EVENLY` items are distributed so that the spacing between any two items (and the space to the edges) is equal. Does not apply to `track_cross_place`.
|
||||||
|
- `LV_FLEX_ALIGN_SPACE_AROUND` items are evenly distributed in the track with equal space around them.
|
||||||
|
Note that visually the spaces aren’t equal, since all the items have equal space on both sides.
|
||||||
|
The first item will have one unit of space against the container edge, but two units of space between the next item because that next item has its own spacing that applies. Not applies to `track_cross_place`.
|
||||||
|
- `LV_FLEX_ALIGN_SPACE_BETWEEN` items are evenly distributed in the track: first item is on the start line, last item on the end line. Not applies to `track_cross_place`.
|
||||||
|
|
||||||
|
|
||||||
|
### Flex grow
|
||||||
|
|
||||||
|
Flex grow can be used to make one or more children fill the available space on the track. When more children have grow parameters, the available space will be distributed proportionally to the grow values.
|
||||||
|
For example, there is 400 px remaining space and 4 objects with grow:
|
||||||
|
- `A` with grow = 1
|
||||||
|
- `B` with grow = 1
|
||||||
|
- `C` with grow = 2
|
||||||
|
|
||||||
|
`A` and `B` will have 100 px size, and `C` will have 200 px size.
|
||||||
|
|
||||||
|
Flex grow can be set on a child with `lv_obj_set_flex_grow(child, value)`. `value` needs to be > 1 or 0 to disable grow on the child.
|
||||||
|
|
||||||
|
|
||||||
|
## Style interface
|
||||||
|
|
||||||
|
All the Flex-related values are style properties under the hood and you can use them similarly to any other style property. The following flex related style properties exist:
|
||||||
|
|
||||||
|
- `FLEX_FLOW`
|
||||||
|
- `FLEX_MAIN_PLACE`
|
||||||
|
- `FLEX_CROSS_PLACE`
|
||||||
|
- `FLEX_TRACK_PLACE`
|
||||||
|
- `FLEX_GROW`
|
||||||
|
|
||||||
|
### Internal padding
|
||||||
|
|
||||||
|
To modify the minimum space flexbox inserts between objects, the following properties can be set on the flex container style:
|
||||||
|
|
||||||
|
- `pad_row` Sets the padding between the rows.
|
||||||
|
|
||||||
|
- `pad_column` Sets the padding between the columns.
|
||||||
|
|
||||||
|
These can for example be used if you don't want any padding between your objects: `lv_style_set_pad_column(&row_container_style,0)`
|
||||||
|
|
||||||
|
## Other features
|
||||||
|
|
||||||
|
### RTL
|
||||||
|
If the base direction of the container is set the `LV_BASE_DIR_RTL` the meaning of `LV_FLEX_ALIGN_START` and `LV_FLEX_ALIGN_END` is swapped on `ROW` layouts. I.e. `START` will mean right.
|
||||||
|
|
||||||
|
The items on `ROW` layouts, and tracks of `COLUMN` layouts will be placed from right to left.
|
||||||
|
|
||||||
|
### New track
|
||||||
|
|
||||||
|
You can force Flex to put an item into a new line with `lv_obj_add_flag(child, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK)`.
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/layouts/flex/index.rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. doxygenfile:: lv_flex.h
|
||||||
|
:project: lvgl
|
||||||
|
|
||||||
|
```
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
|
||||||
|
# Grid
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Grid layout is a subset of [CSS Flexbox](https://css-tricks.com/snippets/css/complete-guide-grid/).
|
||||||
|
|
||||||
|
It can arrange items into a 2D "table" that has rows or columns (tracks). The item can span through multiple columns or rows.
|
||||||
|
The track's size can be set in pixel, to the largest item (`LV_GRID_CONTENT`) or in "Free unit" (FR) to distribute the free space proportionally.
|
||||||
|
|
||||||
|
To make an object a grid container call `lv_obj_set_layout(obj, LV_LAYOUT_GRID)`.
|
||||||
|
|
||||||
|
Note that the grid layout feature of LVGL needs to be globally enabled with `LV_USE_GRID` in `lv_conf.h`.
|
||||||
|
|
||||||
|
## Terms
|
||||||
|
- tracks: the rows or columns
|
||||||
|
- free unit (FR): if set on track's size is set in `FR` it will grow to fill the remaining space on the parent.
|
||||||
|
- gap: the space between the rows and columns or the items on a track
|
||||||
|
|
||||||
|
## Simple interface
|
||||||
|
|
||||||
|
With the following functions you can easily set a Grid layout on any parent.
|
||||||
|
|
||||||
|
### Grid descriptors
|
||||||
|
|
||||||
|
First you need to describe the size of rows and columns. It can be done by declaring 2 arrays and the track sizes in them. The last element must be `LV_GRID_TEMPLATE_LAST`.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
```
|
||||||
|
static lv_coord_t column_dsc[] = {100, 400, LV_GRID_TEMPLATE_LAST}; /*2 columns with 100 and 400 ps width*/
|
||||||
|
static lv_coord_t row_dsc[] = {100, 100, 100, LV_GRID_TEMPLATE_LAST}; /*3 100 px tall rows*/
|
||||||
|
```
|
||||||
|
|
||||||
|
To set the descriptors on a parent use `lv_obj_set_grid_dsc_array(obj, col_dsc, row_dsc)`.
|
||||||
|
|
||||||
|
Besides simple settings the size in pixel you can use two special values:
|
||||||
|
- `LV_GRID_CONTENT` set the width to the largest children on this track
|
||||||
|
- `LV_GRID_FR(X)` tell what portion of the remaining space should be used by this track. Larger value means larger space.
|
||||||
|
|
||||||
|
### Grid items
|
||||||
|
By default, the children are not added to the grid. They need to be added manually to a cell.
|
||||||
|
|
||||||
|
To do this call `lv_obj_set_grid_cell(child, column_align, column_pos, column_span, row_align, row_pos, row_span)`.
|
||||||
|
|
||||||
|
`column_align` and `row_align` determine how to align the children in its cell. The possible values are:
|
||||||
|
- `LV_GRID_ALIGN_START` means left on a horizontally and top vertically. (default)
|
||||||
|
- `LV_GRID_ALIGN_END` means right on a horizontally and bottom vertically
|
||||||
|
- `LV_GRID_ALIGN_CENTER` simply center
|
||||||
|
|
||||||
|
`colum_pos` and `row_pos` means the zero based index of the cell into the item should be placed.
|
||||||
|
|
||||||
|
`colum_span` and `row_span` means how many tracks should the item involve from the start cell. Must be > 1.
|
||||||
|
|
||||||
|
### Grid align
|
||||||
|
|
||||||
|
If there are some empty space the track can be aligned several ways:
|
||||||
|
- `LV_GRID_ALIGN_START` means left on a horizontally and top vertically. (default)
|
||||||
|
- `LV_GRID_ALIGN_END` means right on a horizontally and bottom vertically
|
||||||
|
- `LV_GRID_ALIGN_CENTER` simply center
|
||||||
|
- `LV_GRID_ALIGN_SPACE_EVENLY` items are distributed so that the spacing between any two items (and the space to the edges) is equal. Not applies to `track_cross_place`.
|
||||||
|
- `LV_GRID_ALIGN_SPACE_AROUND` items are evenly distributed in the track with equal space around them.
|
||||||
|
Note that visually the spaces aren’t equal, since all the items have equal space on both sides.
|
||||||
|
The first item will have one unit of space against the container edge, but two units of space between the next item because that next item has its own spacing that applies. Not applies to `track_cross_place`.
|
||||||
|
- `LV_GRID_ALIGN_SPACE_BETWEEN` items are evenly distributed in the track: first item is on the start line, last item on the end line. Not applies to `track_cross_place`.
|
||||||
|
|
||||||
|
To set the track's alignment use `lv_obj_set_grid_align(obj, column_align, row_align)`.
|
||||||
|
|
||||||
|
## Style interface
|
||||||
|
|
||||||
|
All the Grid related values are style properties under the hood and you can use them similarly to any other style properties. The following Grid related style properties exist:
|
||||||
|
|
||||||
|
- `GRID_COLUMN_DSC_ARRAY`
|
||||||
|
- `GRID_ROW_DSC_ARRAY`
|
||||||
|
- `GRID_COLUMN_ALIGN`
|
||||||
|
- `GRID_ROW_ALIGN`
|
||||||
|
- `GRID_CELL_X_ALIGN`
|
||||||
|
- `GRID_CELL_COLUMN_POS`
|
||||||
|
- `GRID_CELL_COLUMN_SPAN`
|
||||||
|
- `GRID_CELL_Y_ALIGN`
|
||||||
|
- `GRID_CELL_ROW_POS`
|
||||||
|
- `GRID_CELL_ROW_SPAN`
|
||||||
|
|
||||||
|
### Internal padding
|
||||||
|
|
||||||
|
To modify the minimum space Grid inserts between objects, the following properties can be set on the Grid container style:
|
||||||
|
|
||||||
|
- `pad_row` Sets the padding between the rows.
|
||||||
|
- `pad_column` Sets the padding between the columns.
|
||||||
|
|
||||||
|
## Other features
|
||||||
|
|
||||||
|
### RTL
|
||||||
|
If the base direction of the container is set to `LV_BASE_DIR_RTL`, the meaning of `LV_GRID_ALIGN_START` and `LV_GRID_ALIGN_END` is swapped. I.e. `START` will mean right-most.
|
||||||
|
|
||||||
|
The columns will be placed from right to left.
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/layouts/grid/index.rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. doxygenfile:: lv_grid.h
|
||||||
|
:project: lvgl
|
||||||
|
|
||||||
|
```
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
# Layouts
|
||||||
|
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
flex
|
||||||
|
grid
|
||||||
|
```
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
# BMP decoder
|
||||||
|
|
||||||
|
This extension allows the use of BMP images in LVGL.
|
||||||
|
This implementation uses [bmp-decoder](https://github.com/caj-johnson/bmp-decoder) library.
|
||||||
|
The pixels are read on demand (not the whole image is loaded) so using BMP images requires very little RAM.
|
||||||
|
|
||||||
|
If enabled in `lv_conf.h` by `LV_USE_BMP` LVGL will register a new image decoder automatically so BMP files can be directly used as image sources. For example:
|
||||||
|
```
|
||||||
|
lv_img_set_src(my_img, "S:path/to/picture.bmp");
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that, a file system driver needs to registered to open images from files. Read more about it [here](https://docs.lvgl.io/master/overview/file-system.html) or just enable one in `lv_conf.h` with `LV_USE_FS_...`
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
- Only BMP files are supported and BMP images as C array (`lv_img_dsc_t`) are not. It's because there is no practical differences between how the BMP files and LVGL's image format stores the image data.
|
||||||
|
- BMP files can be loaded only from file. If you want to store them in flash it's better to convert them to C array with [LVGL's image converter](https://lvgl.io/tools/imageconverter).
|
||||||
|
- The BMP files color format needs to match with `LV_COLOR_DEPTH`. Use GIMP to save the image in the required format.
|
||||||
|
Both RGB888 and ARGB888 works with `LV_COLOR_DEPTH 32`
|
||||||
|
- Palette is not supported.
|
||||||
|
- Because not the whole image is read in can not be zoomed or rotated.
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/libs/bmp/index.rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. doxygenfile:: lv_bmp.h
|
||||||
|
:project: lvgl
|
||||||
|
|
||||||
|
```
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
# FFmpeg support
|
||||||
|
[FFmpeg](https://www.ffmpeg.org/) A complete, cross-platform solution to record, convert and stream audio and video.
|
||||||
|
|
||||||
|
## Install FFmpeg
|
||||||
|
- Download FFmpeg from [here](https://www.ffmpeg.org/download.html)
|
||||||
|
- `./configure --disable-all --disable-autodetect --disable-podpages --disable-asm --enable-avcodec --enable-avformat --enable-decoders --enable-encoders --enable-demuxers --enable-parsers --enable-protocol='file' --enable-swscale --enable-zlib`
|
||||||
|
- `make`
|
||||||
|
- `sudo make install`
|
||||||
|
|
||||||
|
## Add FFmpeg to your project
|
||||||
|
- Add library: `FFmpeg` (for GCC: `-lavformat -lavcodec -lavutil -lswscale -lm -lz -lpthread`)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Enable `LV_USE_FFMPEG` in `lv_conf.h`.
|
||||||
|
|
||||||
|
See the examples below.
|
||||||
|
|
||||||
|
Note that, the FFmpeg extension doesn't use LVGL's file system.
|
||||||
|
You can simply pass the path to the image or video as usual on your operating system or platform.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/libs/ffmpeg/index.rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. doxygenfile:: lv_ffmpeg.h
|
||||||
|
:project: lvgl
|
||||||
|
|
||||||
|
```
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
# FreeType support
|
||||||
|
Interface to [FreeType](https://www.freetype.org/) to generate font bitmaps run time.
|
||||||
|
|
||||||
|
## Install FreeType
|
||||||
|
- Download Freetype from [here](https://sourceforge.net/projects/freetype/files/)
|
||||||
|
- `make`
|
||||||
|
- `sudo make install`
|
||||||
|
|
||||||
|
## Add FreeType to your project
|
||||||
|
- Add include path: `/usr/include/freetype2` (for GCC: `-I/usr/include/freetype2 -L/usr/local/lib`)
|
||||||
|
- Add library: `freetype` (for GCC: `-L/usr/local/lib -lfreetype`)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Enable `LV_USE_FREETYPE` in `lv_conf.h`.
|
||||||
|
|
||||||
|
To cache the glyphs from the opened fonts, set `LV_FREETYPE_CACHE_SIZE >= 0` and then use the following macros for detailed configuration:
|
||||||
|
1. `LV_FREETYPE_CACHE_SIZE`:maximum memory(bytes) used to cache font bitmap, outline, character maps, etc. 0 means use the system default value, less than 0 means disable cache. Note: that this value does not account for managed FT_Face and FT_Size objects.
|
||||||
|
1. `LV_FREETYPE_CACHE_FT_FACES`:maximum number of opened FT_Face objects managed by this cache instance.0 means use the system default value. Only useful when LV_FREETYPE_CACHE_SIZE >= 0.
|
||||||
|
1. `LV_FREETYPE_CACHE_FT_SIZES`:maximum number of opened FT_Size objects managed by this cache instance. 0 means use the system default value. Only useful when LV_FREETYPE_CACHE_SIZE >= 0.
|
||||||
|
|
||||||
|
When you are sure that all the used font sizes will not be greater than 256, you can enable `LV_FREETYPE_SBIT_CACHE`, which is much more memory efficient for small bitmaps.
|
||||||
|
|
||||||
|
You can use `lv_ft_font_init()` to create FreeType fonts. It returns `true` to indicate success, at the same time, the `font` member of `lv_ft_info_t` will be filled with a pointer to an LVGL font, and you can use it like any LVGL font.
|
||||||
|
|
||||||
|
Font style supports bold and italic, you can use the following macros to set:
|
||||||
|
1. `FT_FONT_STYLE_NORMAL`:default style.
|
||||||
|
1. `FT_FONT_STYLE_ITALIC`:Italic style
|
||||||
|
1. `FT_FONT_STYLE_BOLD`:bold style
|
||||||
|
|
||||||
|
They can be combined.eg:`FT_FONT_STYLE_BOLD | FT_FONT_STYLE_ITALIC`.
|
||||||
|
|
||||||
|
Note that, the FreeType extension doesn't use LVGL's file system.
|
||||||
|
You can simply pass the path to the font as usual on your operating system or platform.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
```eval_rst
|
||||||
|
.. include:: ../../examples/libs/freetype/index.rst
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Learn more
|
||||||
|
- FreeType [tutorial](https://www.freetype.org/freetype2/docs/tutorial/step1.html)
|
||||||
|
- LVGL's [font interface](https://docs.lvgl.io/v7/en/html/overview/font.html#add-a-new-font-engine)
|
||||||
|
|
||||||
|
|
||||||
|
## API
|
||||||
|
```eval_rst
|
||||||
|
.. doxygenfile:: lv_freetype.h
|
||||||
|
:project: lvgl
|
||||||
|
```
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
# File System Interfaces
|
||||||
|
|
||||||
|
LVGL has a [File system](https://docs.lvgl.io/master/overview/file-system.html) module to provide an abstraction layer for various file system drivers.
|
||||||
|
|
||||||
|
LVG has built in support for:
|
||||||
|
- [FATFS](http://elm-chan.org/fsw/ff/00index_e.html)
|
||||||
|
- STDIO (Linux and Windows using C standard function .e.g fopen, fread)
|
||||||
|
- POSIX (Linux and Windows using POSIX function .e.g open, read)
|
||||||
|
- WIN32 (Windows using Win32 API function .e.g CreateFileA, ReadFile)
|
||||||
|
|
||||||
|
You still need to provide the drivers and libraries, this extension provides only the bridge between FATFS, STDIO, POSIX, WIN32 and LVGL.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
In `lv_conf.h` enable `LV_USE_FS_...` and assign an upper cased letter to `LV_FS_..._LETTER` (e.g. `'S'`).
|
||||||
|
After that you can access files using that driver letter. E.g. `"S:path/to/file.txt"`.
|
||||||
|
|
||||||
|
The work directory can be set with `LV_FS_..._PATH`. E.g. `"/home/joe/projects/"` The actual file/directory paths will be appended to it.
|
||||||
|
|
||||||
|
Cached reading is also supported if `LV_FS_..._CACHE_SIZE` is set to not `0` value. `lv_fs_read` caches this size of data to lower the number of actual reads from the storage.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
# GIF decoder
|
||||||
|
Allow using GIF images in LVGL. Based on https://github.com/lecram/gifdec
|
||||||
|
|
||||||
|
When enabled in `lv_conf.h` with `LV_USE_GIF` `lv_gif_create(parent)` can be used to create a gif widget.
|
||||||
|
|
||||||
|
`lv_gif_set_src(obj, src)` works very similarly to `lv_img_set_src`. As source, it also accepts images as variables (`lv_img_dsc_t`) or files.
|
||||||
|
|
||||||
|
|
||||||
|
## Convert GIF files to C array
|
||||||
|
To convert a GIF file to byte values array use [LVGL's online converter](https://lvgl.io/tools/imageconverter). Select "Raw" color format and "C array" Output format.
|
||||||
|
|
||||||
|
|
||||||
|
## Use GIF images from file
|
||||||
|
For example:
|
||||||
|
```c
|
||||||
|
lv_gif_set_src(obj, "S:path/to/example.gif");
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that, a file system driver needs to be registered to open images from files. Read more about it [here](https://docs.lvgl.io/master/overview/file-system.html) or just enable one in `lv_conf.h` with `LV_USE_FS_...`
|
||||||
|
|
||||||
|
|
||||||
|
## Memory requirements
|
||||||
|
To decode and display a GIF animation the following amount of RAM is required:
|
||||||
|
- `LV_COLOR_DEPTH 8`: 3 x image width x image height
|
||||||
|
- `LV_COLOR_DEPTH 16`: 4 x image width x image height
|
||||||
|
- `LV_COLOR_DEPTH 32`: 5 x image width x image height
|
||||||
|
|
||||||
|
## Example
|
||||||
|
```eval_rst
|
||||||
|
.. include:: ../../examples/libs/gif/index.rst
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
.. doxygenfile:: lv_gif.h
|
||||||
|
:project: lvgl
|
||||||
|
```
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# 3rd party libraries
|
||||||
|
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
fsdrv
|
||||||
|
bmp
|
||||||
|
sjpg
|
||||||
|
png
|
||||||
|
gif
|
||||||
|
freetype
|
||||||
|
qrcode
|
||||||
|
rlottie
|
||||||
|
ffmpeg
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
# PNG decoder
|
||||||
|
|
||||||
|
Allow the use of PNG images in LVGL. This implementation uses [lodepng](https://github.com/lvandeve/lodepng) library.
|
||||||
|
|
||||||
|
If enabled in `lv_conf.h` by `LV_USE_PNG` LVGL will register a new image decoder automatically so PNG files can be directly used as any other image sources.
|
||||||
|
|
||||||
|
Note that, a file system driver needs to registered to open images from files. Read more about it [here](https://docs.lvgl.io/master/overview/file-system.html) or just enable one in `lv_conf.h` with `LV_USE_FS_...`
|
||||||
|
|
||||||
|
The whole PNG image is decoded so during decoding RAM equals to `image width x image height x 4` bytes are required.
|
||||||
|
|
||||||
|
As it might take significant time to decode PNG images LVGL's [images caching](https://docs.lvgl.io/master/overview/image.html#image-caching) feature can be useful.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/libs/png/index.rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. doxygenfile:: lv_png.h
|
||||||
|
:project: lvgl
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
# QR code
|
||||||
|
|
||||||
|
QR code generation with LVGL. Uses [QR-Code-generator](https://github.com/nayuki/QR-Code-generator) by [nayuki](https://github.com/nayuki).
|
||||||
|
|
||||||
|
## Get started
|
||||||
|
- Download or clone this repository
|
||||||
|
- [Download](https://github.com/lvgl/lv_lib_qrcode.git) from GitHub
|
||||||
|
- Clone: git clone https://github.com/lvgl/lv_lib_qrcode.git
|
||||||
|
- Include the library: `#include "lv_lib_qrcode/lv_qrcode.h"`
|
||||||
|
- Test with the following code:
|
||||||
|
```c
|
||||||
|
const char * data = "Hello world";
|
||||||
|
|
||||||
|
/*Create a 100x100 QR code*/
|
||||||
|
lv_obj_t * qr = lv_qrcode_create(lv_scr_act(), 100, lv_color_hex3(0x33f), lv_color_hex3(0xeef));
|
||||||
|
|
||||||
|
/*Set data*/
|
||||||
|
lv_qrcode_update(qr, data, strlen(data));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
- QR codes with less data are smaller, but they scaled by an integer number to best fit to the given size.
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/libs/qrcode/index.rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. doxygenfile:: lv_qrcode.h
|
||||||
|
:project: lvgl
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# Lottie player
|
||||||
|
Allows to use Lottie animations in LVGL. Taken from this [base repository](https://github.com/ValentiWorkLearning/lv_rlottie)
|
||||||
|
|
||||||
|
LVGL provides the interface to [Samsung/rlottie](https://github.com/Samsung/rlottie) library's C API. That is the actual Lottie player is not part of LVGL, it needs to be built separately.
|
||||||
|
|
||||||
|
## Build Rlottie
|
||||||
|
To build Samsung's Rlottie C++14-compatible compiler and optionally CMake 3.14 or higher is required.
|
||||||
|
|
||||||
|
To build on desktop you can follow the instructions from Rlottie's [README](https://github.com/Samsung/rlottie/blob/master/README.md). In the most basic case it looks like this:
|
||||||
|
```
|
||||||
|
mkdir rlottie_workdir
|
||||||
|
cd rlottie_workdir
|
||||||
|
git clone https://github.com/Samsung/rlottie.git
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ../rlottie
|
||||||
|
make -j
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
And finally add the `-lrlottie` flag to your linker.
|
||||||
|
|
||||||
|
On embedded systems you need to take care of integrating Rlottie to the given build system.
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
You can use animation from files or raw data (text). In either case first you need to enable `LV_USE_RLOTTIE` in `lv_conf.h`.
|
||||||
|
|
||||||
|
|
||||||
|
The `width` and `height` of the object be set in the *create* function and the animation will be scaled accordingly.
|
||||||
|
|
||||||
|
### Use Rlottie from file
|
||||||
|
|
||||||
|
To create a Lottie animation from file use:
|
||||||
|
```c
|
||||||
|
lv_obj_t * lottie = lv_rlottie_create_from_file(parent, width, height, "path/to/lottie.json");
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that, Rlottie uses the standard STDIO C file API, so you can use the path "normally" and no LVGL specific driver letter is required.
|
||||||
|
|
||||||
|
|
||||||
|
### Use Rlottie from raw string data
|
||||||
|
|
||||||
|
`lv_example_rlottie_approve.c` contains an example animation in raw format. Instead storing the JSON string a hex array is stored for the following reasons:
|
||||||
|
- avoid escaping `"` in the JSON file
|
||||||
|
- some compilers don't support very long strings
|
||||||
|
|
||||||
|
`lvgl/scripts/filetohex.py` can be used to convert a Lottie file a hex array. E.g.:
|
||||||
|
```
|
||||||
|
./filetohex.py path/to/lottie.json > out.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
To create an animation from raw data:
|
||||||
|
|
||||||
|
```c
|
||||||
|
extern const uint8_t lottie_data[];
|
||||||
|
lv_obj_t* lottie = lv_rlottie_create_from_raw(parent, width, height, (const char *)lottie_data);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Getting animations
|
||||||
|
|
||||||
|
Lottie is standard and popular format so you can find many animation files on the web.
|
||||||
|
For example: https://lottiefiles.com/
|
||||||
|
|
||||||
|
You can also create your own animations with Adobe After Effects or similar software.
|
||||||
|
|
||||||
|
## Controlling animations
|
||||||
|
|
||||||
|
LVGL provides two functions to control the animation mode: `lv_rlottie_set_play_mode` and `lv_rlottie_set_current_frame`.
|
||||||
|
You'll combine your intentions when calling the first method, like in these examples:
|
||||||
|
```c
|
||||||
|
lv_obj_t * lottie = lv_rlottie_create_from_file(scr, 128, 128, "test.json");
|
||||||
|
lv_obj_center(lottie);
|
||||||
|
// Pause to a specific frame
|
||||||
|
lv_rlottie_set_current_frame(lottie, 50);
|
||||||
|
lv_rlottie_set_play_mode(lottie, LV_RLOTTIE_CTRL_PAUSE); // The specified frame will be displayed and then the animation will pause
|
||||||
|
|
||||||
|
// Play backward and loop
|
||||||
|
lv_rlottie_set_play_mode(lottie, LV_RLOTTIE_CTRL_PLAY | LV_RLOTTIE_CTRL_BACKWARD | LV_RLOTTIE_CTRL_LOOP);
|
||||||
|
|
||||||
|
// Play forward once (no looping)
|
||||||
|
lv_rlottie_set_play_mode(lottie, LV_RLOTTIE_CTRL_PLAY | LV_RLOTTIE_CTRL_FORWARD);
|
||||||
|
```
|
||||||
|
|
||||||
|
The default animation mode is **play forward with loop**.
|
||||||
|
|
||||||
|
If you don't enable looping, a `LV_EVENT_READY` is sent when the animation can not make more progress without looping.
|
||||||
|
|
||||||
|
To get the number of frames in an animation or the current frame index, you can cast the `lv_obj_t` instance to a `lv_rlottie_t` instance and inspect the `current_frame` and `total_frames` members.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/libs/rlottie/index.rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. doxygenfile:: lv_rlottie.h
|
||||||
|
:project: lvgl
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
# JPG decoder
|
||||||
|
|
||||||
|
Allow the use of JPG images in LVGL. Besides that it also allows the use of a custom format, called Split JPG (SJPG), which can be decoded in more optimal way on embedded systems.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
- Supports both normal JPG and the custom SJPG formats.
|
||||||
|
- Decoding normal JPG consumes RAM with the size fo the whole uncompressed image (recommended only for devices with more RAM)
|
||||||
|
- SJPG is a custom format based on "normal" JPG and specially made for LVGL.
|
||||||
|
- SJPG is 'split-jpeg' which is a bundle of small jpeg fragments with an sjpg header.
|
||||||
|
- SJPG size will be almost comparable to the jpg file or might be a slightly larger.
|
||||||
|
- File read from file and c-array are implemented.
|
||||||
|
- SJPEG frame fragment cache enables fast fetching of lines if available in cache.
|
||||||
|
- By default the sjpg image cache will be image width * 2 * 16 bytes (can be modified)
|
||||||
|
- Currently only 16 bit image format is supported (TODO)
|
||||||
|
- Only the required partion of the JPG and SJPG images are decoded, therefore they can't be zoomed or rotated.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
If enabled in `lv_conf.h` by `LV_USE_SJPG` LVGL will register a new image decoder automatically so JPG and SJPG files can be directly used as image sources. For example:
|
||||||
|
```
|
||||||
|
lv_img_set_src(my_img, "S:path/to/picture.jpg");
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that, a file system driver needs to registered to open images from files. Read more about it [here](https://docs.lvgl.io/master/overview/file-system.html) or just enable one in `lv_conf.h` with `LV_USE_FS_...`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Converter
|
||||||
|
|
||||||
|
### Converting JPG to C array
|
||||||
|
- Use lvgl online tool https://lvgl.io/tools/imageconverter
|
||||||
|
- Color format = RAW, output format = C Array
|
||||||
|
|
||||||
|
### Converting JPG to SJPG
|
||||||
|
python3 and the PIL library required. (PIL can be installed with `pip3 install pillow`)
|
||||||
|
|
||||||
|
To create SJPG from JPG:
|
||||||
|
- Copy the image to convert into `lvgl/scripts`
|
||||||
|
- `cd lvgl/scripts`
|
||||||
|
- `python3 jpg_to_sjpg.py image_to_convert.jpg`. It creates both a C files and an SJPG image.
|
||||||
|
|
||||||
|
The expected result is:
|
||||||
|
```sh
|
||||||
|
Conversion started...
|
||||||
|
|
||||||
|
Input:
|
||||||
|
image_to_convert.jpg
|
||||||
|
RES = 640 x 480
|
||||||
|
|
||||||
|
Output:
|
||||||
|
Time taken = 1.66 sec
|
||||||
|
bin size = 77.1 KB
|
||||||
|
walpaper.sjpg (bin file)
|
||||||
|
walpaper.c (c array)
|
||||||
|
|
||||||
|
All good!
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/libs/sjpg/index.rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. doxygenfile:: lv_sjpg.h
|
||||||
|
:project: lvgl
|
||||||
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 973 B |
|
After Width: | Height: | Size: 993 B |
|
After Width: | Height: | Size: 990 B |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
@@ -0,0 +1,77 @@
|
|||||||
|
|
||||||
|
# Fragment
|
||||||
|
|
||||||
|
Fragment is a concept copied from [Android](https://developer.android.com/guide/fragments).
|
||||||
|
|
||||||
|
It represents a reusable portion of your app's UI. A fragment defines and manages its own layout, has its own lifecycle,
|
||||||
|
and can handle its own events. Like Android's Fragment that must be hosted by an activity or another fragment, Fragment
|
||||||
|
in LVGL needs to be hosted by an object, or another fragment. The fragment’s view hierarchy becomes part of, or attaches
|
||||||
|
to, the host’s view hierarchy.
|
||||||
|
|
||||||
|
Such concept also has some similarities
|
||||||
|
to [UiViewController on iOS](https://developer.apple.com/documentation/uikit/uiviewcontroller).
|
||||||
|
|
||||||
|
Fragment Manager is a manager holding references to fragments attached to it, and has an internal stack to achieve
|
||||||
|
navigation. You can use fragment manager to build navigation stack, or multi pane application easily.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Enable `LV_USE_FRAGMENT` in `lv_conf.h`.
|
||||||
|
|
||||||
|
### Create Fragment Class
|
||||||
|
|
||||||
|
```c
|
||||||
|
struct sample_fragment_t {
|
||||||
|
/* IMPORTANT: don't miss this part */
|
||||||
|
lv_fragment_t base;
|
||||||
|
/* States, object references and data fields for this fragment */
|
||||||
|
const char *title;
|
||||||
|
};
|
||||||
|
|
||||||
|
const lv_fragment_class_t sample_cls = {
|
||||||
|
/* Initialize something needed */
|
||||||
|
.constructor_cb = sample_fragment_ctor,
|
||||||
|
/* Create view objects */
|
||||||
|
.create_obj_cb = sample_fragment_create_obj,
|
||||||
|
/* IMPORTANT: size of your fragment struct */
|
||||||
|
.instance_size = sizeof(struct sample_fragment_t)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use `lv_fragment_manager`
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* Create fragment instance, and objects will be added to container */
|
||||||
|
lv_fragment_manager_t *manager = lv_fragment_manager_create(container, NULL);
|
||||||
|
/* Replace current fragment with instance of sample_cls, and init_argument is user defined pointer */
|
||||||
|
lv_fragment_manager_replace(manager, &sample_cls, init_argument);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fragment Based Navigation
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* Add one instance into manager stack. View object of current fragment will be destroyed,
|
||||||
|
* but instances created in class constructor will be kept.
|
||||||
|
*/
|
||||||
|
lv_fragment_manager_push(manager, &sample_cls, NULL);
|
||||||
|
|
||||||
|
/* Remove the top most fragment from the stack, and bring back previous one. */
|
||||||
|
lv_fragment_manager_pop(manager);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. include:: ../../examples/others/fragment/index.rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. doxygenfile:: lv_fragment.h
|
||||||
|
:project: lvgl
|
||||||
|
|
||||||
|
```
|
||||||