forked from espressif/esp-idf
feat(parlio): adapt rgb_matrix example to lvgl9
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_PIN_NUM_R1
|
||||
int "Red Pin 1"
|
||||
default 7
|
||||
|
||||
config EXAMPLE_PIN_NUM_G1
|
||||
int "Green Pin 1"
|
||||
default 4
|
||||
|
||||
config EXAMPLE_PIN_NUM_B1
|
||||
int "Blue Pin 1"
|
||||
default 1
|
||||
|
||||
config EXAMPLE_PIN_NUM_R2
|
||||
int "Red Pin 2"
|
||||
default 6
|
||||
|
||||
config EXAMPLE_PIN_NUM_G2
|
||||
int "Green Pin 2"
|
||||
default 3
|
||||
|
||||
config EXAMPLE_PIN_NUM_B2
|
||||
int "Blue Pin 2"
|
||||
default 0
|
||||
|
||||
config EXAMPLE_PIN_NUM_LATCH
|
||||
int "Latch Pin"
|
||||
default 5
|
||||
|
||||
config EXAMPLE_PIN_NUM_PCLK
|
||||
int "PCLK Pin"
|
||||
default 10
|
||||
|
||||
config EXAMPLE_PIN_NUM_OE
|
||||
int "OE Pin"
|
||||
default 2
|
||||
|
||||
config EXAMPLE_PIN_NUM_A
|
||||
int "A Pin"
|
||||
default 20
|
||||
|
||||
config EXAMPLE_PIN_NUM_B
|
||||
int "B Pin"
|
||||
default 21
|
||||
|
||||
config EXAMPLE_PIN_NUM_C
|
||||
int "C Pin"
|
||||
default 22
|
||||
|
||||
config EXAMPLE_PIN_NUM_D
|
||||
int "D Pin"
|
||||
default 23
|
||||
|
||||
endmenu
|
@@ -1,3 +1,3 @@
|
||||
dependencies:
|
||||
idf: ">=5.1"
|
||||
lvgl/lvgl: "8.3.0"
|
||||
lvgl/lvgl: "9.2.2"
|
||||
|
@@ -1,25 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
void example_lvgl_demo_ui(lv_disp_t *disp)
|
||||
void example_lvgl_demo_ui(lv_display_t *disp)
|
||||
{
|
||||
lv_obj_t *scr = lv_disp_get_scr_act(disp);
|
||||
lv_obj_t *scr = lv_display_get_screen_active(disp);
|
||||
static lv_style_t up_style;
|
||||
lv_style_init(&up_style);
|
||||
lv_obj_t *up_label = lv_label_create(scr);
|
||||
lv_label_set_recolor(up_label, true);
|
||||
lv_label_set_text(up_label, "#FF0000 Hello# #0000FF World#");
|
||||
lv_style_set_text_color(&up_style, lv_palette_main(LV_PALETTE_RED));
|
||||
lv_obj_add_style(up_label, &up_style, 0);
|
||||
lv_label_set_text(up_label, "Hello World");
|
||||
lv_label_set_long_mode(up_label, LV_LABEL_LONG_SCROLL_CIRCULAR); /* Circular scroll */
|
||||
/* Size of the screen */
|
||||
lv_obj_set_width(up_label, disp->driver->hor_res);
|
||||
lv_obj_set_width(up_label, lv_display_get_horizontal_resolution(disp));
|
||||
lv_obj_align_to(up_label, scr, LV_ALIGN_TOP_MID, 0, 0);
|
||||
|
||||
static lv_style_t low_style;
|
||||
lv_style_init(&low_style);
|
||||
lv_obj_t *low_label = lv_label_create(scr);
|
||||
lv_style_set_text_color(&low_style, lv_palette_main(LV_PALETTE_GREEN));
|
||||
lv_obj_add_style(low_label, &low_style, 0);
|
||||
lv_label_set_text(low_label, LV_SYMBOL_WIFI LV_SYMBOL_GPS LV_SYMBOL_BATTERY_2 LV_SYMBOL_AUDIO);
|
||||
/* Size of the screen */
|
||||
lv_obj_set_width(low_label, disp->driver->hor_res);
|
||||
lv_obj_set_width(low_label, lv_display_get_horizontal_resolution(disp));
|
||||
lv_obj_align_to(low_label, scr, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
}
|
||||
|
@@ -1,8 +1,9 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_attr.h"
|
||||
@@ -28,20 +29,21 @@ static const char *TAG = "example";
|
||||
#define EXAMPLE_HUB75_B1_IDX 1 // B1 bit position
|
||||
#define EXAMPLE_HUB75_B2_IDX 0 // B2 bit position
|
||||
// GPIO assignment
|
||||
#define EXAMPLE_PIN_NUM_R1 7
|
||||
#define EXAMPLE_PIN_NUM_G1 4
|
||||
#define EXAMPLE_PIN_NUM_B1 1
|
||||
#define EXAMPLE_PIN_NUM_R2 6
|
||||
#define EXAMPLE_PIN_NUM_G2 3
|
||||
#define EXAMPLE_PIN_NUM_B2 0
|
||||
#define EXAMPLE_PIN_NUM_LATCH 5
|
||||
#define EXAMPLE_PIN_NUM_OE 2
|
||||
#define EXAMPLE_PIN_NUM_PCLK 10
|
||||
#define EXAMPLE_PIN_NUM_R1 CONFIG_EXAMPLE_PIN_NUM_R1
|
||||
#define EXAMPLE_PIN_NUM_G1 CONFIG_EXAMPLE_PIN_NUM_G1
|
||||
#define EXAMPLE_PIN_NUM_B1 CONFIG_EXAMPLE_PIN_NUM_B1
|
||||
#define EXAMPLE_PIN_NUM_R2 CONFIG_EXAMPLE_PIN_NUM_R2
|
||||
#define EXAMPLE_PIN_NUM_G2 CONFIG_EXAMPLE_PIN_NUM_G2
|
||||
#define EXAMPLE_PIN_NUM_B2 CONFIG_EXAMPLE_PIN_NUM_B2
|
||||
#define EXAMPLE_PIN_NUM_LATCH CONFIG_EXAMPLE_PIN_NUM_LATCH
|
||||
#define EXAMPLE_PIN_NUM_OE CONFIG_EXAMPLE_PIN_NUM_OE
|
||||
#define EXAMPLE_PIN_NUM_PCLK CONFIG_EXAMPLE_PIN_NUM_PCLK
|
||||
// address signals are powered by fast GPIO module
|
||||
#define EXAMPLE_PIN_NUM_A 20
|
||||
#define EXAMPLE_PIN_NUM_B 21
|
||||
#define EXAMPLE_PIN_NUM_C 22
|
||||
#define EXAMPLE_PIN_NUM_D 23
|
||||
#define EXAMPLE_PIN_NUM_A CONFIG_EXAMPLE_PIN_NUM_A
|
||||
#define EXAMPLE_PIN_NUM_B CONFIG_EXAMPLE_PIN_NUM_B
|
||||
#define EXAMPLE_PIN_NUM_C CONFIG_EXAMPLE_PIN_NUM_C
|
||||
#define EXAMPLE_PIN_NUM_D CONFIG_EXAMPLE_PIN_NUM_D
|
||||
|
||||
// The pixel clock frequency
|
||||
#define EXAMPLE_LED_MATRIX_PIXEL_CLOCK_HZ (10 * 1000 * 1000) // 10MHz
|
||||
// The pixel number in horizontal and vertical
|
||||
@@ -52,42 +54,36 @@ static const char *TAG = "example";
|
||||
#define EXAMPLE_GPTIMER_RESOLUTION_HZ (1 * 1000 * 1000) // 1MHz
|
||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 5 // 5ms
|
||||
|
||||
// 0x92: we pick the first bit of each RGB element in the order of 3-3-2, that's 0b10010010
|
||||
// p1: pixel on the upper half screen
|
||||
// p2: pixel on the lower half screen
|
||||
// OE=1: disable the output
|
||||
#define MERGE_TWO_LVGL_PIXELS(p1, p2) \
|
||||
do \
|
||||
{ \
|
||||
p1->full &= 0x92; \
|
||||
p1->full |= (p2->full & 0x92) >> 1; \
|
||||
p1->full |= 1 << EXAMPLE_HUB75_OE_IDX; \
|
||||
} while (0)
|
||||
|
||||
extern void example_lvgl_demo_ui(lv_disp_t *disp);
|
||||
|
||||
// LED Matrix frame buffer, we use a dedicated task to flush this frame buffer
|
||||
static lv_color_t s_frame_buffer[EXAMPLE_LED_MATRIX_H_RES * EXAMPLE_LED_MATRIX_V_RES / 2];
|
||||
static uint8_t s_frame_buffer[EXAMPLE_LED_MATRIX_H_RES * EXAMPLE_LED_MATRIX_V_RES / 2] = {};
|
||||
|
||||
static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
||||
// upper_half: pixel on the upper half screen
|
||||
// lower_half: pixel on the lower half screen
|
||||
static void merge_two_pixels(lv_color16_t *upper_half, lv_color16_t *lower_half, int index)
|
||||
{
|
||||
lv_color_t *upper_half = color_map;
|
||||
lv_color_t *lower_half = color_map + EXAMPLE_LED_MATRIX_V_RES * EXAMPLE_LED_MATRIX_H_RES / 2;
|
||||
s_frame_buffer[index] = (upper_half->red >> 4) << EXAMPLE_HUB75_R1_IDX | (upper_half->green >> 5) << EXAMPLE_HUB75_G1_IDX | (upper_half->blue >> 4) << EXAMPLE_HUB75_B1_IDX;
|
||||
s_frame_buffer[index] |= (lower_half->red >> 4) << EXAMPLE_HUB75_R2_IDX | (lower_half->green >> 5) << EXAMPLE_HUB75_G2_IDX | (lower_half->blue >> 4) << EXAMPLE_HUB75_B2_IDX;
|
||||
// OE=1: enable the output
|
||||
s_frame_buffer[index] |= 1 << EXAMPLE_HUB75_OE_IDX;
|
||||
}
|
||||
|
||||
extern void example_lvgl_demo_ui(lv_display_t *disp);
|
||||
|
||||
static void example_lvgl_flush_cb(lv_display_t *display, const lv_area_t *area, uint8_t *color_map)
|
||||
{
|
||||
lv_color16_t *upper_half = (lv_color16_t *)color_map;
|
||||
lv_color16_t *lower_half = (lv_color16_t *)color_map + EXAMPLE_LED_MATRIX_V_RES * EXAMPLE_LED_MATRIX_H_RES / 2;
|
||||
int index = 0;
|
||||
for (int line = 0; line < EXAMPLE_LED_MATRIX_V_RES / 2; line++) {
|
||||
for (int col = 0; col < EXAMPLE_LED_MATRIX_H_RES - 1; col++) {
|
||||
MERGE_TWO_LVGL_PIXELS(upper_half, lower_half);
|
||||
upper_half++;
|
||||
lower_half++;
|
||||
merge_two_pixels(upper_half++, lower_half++, index++);
|
||||
}
|
||||
MERGE_TWO_LVGL_PIXELS(upper_half, lower_half);
|
||||
merge_two_pixels(upper_half++, lower_half++, index);
|
||||
// need special handling for the last pixel in each line
|
||||
// latch up at the end of each line
|
||||
upper_half->full |= (1 << EXAMPLE_HUB75_LATCH_IDX);
|
||||
upper_half++;
|
||||
lower_half++;
|
||||
s_frame_buffer[index++] |= (1 << EXAMPLE_HUB75_LATCH_IDX);
|
||||
}
|
||||
memcpy(s_frame_buffer, color_map, sizeof(s_frame_buffer));
|
||||
lv_disp_flush_ready(drv);
|
||||
lv_display_flush_ready(display);
|
||||
}
|
||||
|
||||
static IRAM_ATTR bool parlio_tx_line_done_cb(parlio_tx_unit_handle_t tx_unit, const parlio_tx_done_event_data_t *edata, void *user_ctx)
|
||||
@@ -107,9 +103,6 @@ static IRAM_ATTR bool gptimer_alarm_cb_lvgl_tick(gptimer_handle_t timer, const g
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
static lv_disp_draw_buf_t disp_buf;
|
||||
static lv_disp_drv_t disp_drv;
|
||||
|
||||
ESP_LOGI(TAG, "Install fast GPIO bundle for line address control");
|
||||
dedic_gpio_bundle_config_t dedic_gpio_conf = {
|
||||
.flags.out_en = true,
|
||||
@@ -144,7 +137,7 @@ void app_main(void)
|
||||
},
|
||||
.output_clk_freq_hz = EXAMPLE_LED_MATRIX_PIXEL_CLOCK_HZ,
|
||||
.trans_queue_depth = 32,
|
||||
.max_transfer_size = EXAMPLE_LED_MATRIX_H_RES * sizeof(lv_color_t) * 2, // 2 lines as the maximum transfer size
|
||||
.max_transfer_size = EXAMPLE_LED_MATRIX_H_RES * sizeof(uint8_t) * 2, // 2 lines as the maximum transfer size
|
||||
.sample_edge = PARLIO_SAMPLE_EDGE_POS,
|
||||
};
|
||||
ESP_ERROR_CHECK(parlio_new_tx_unit(&config, &tx_unit));
|
||||
@@ -158,23 +151,21 @@ void app_main(void)
|
||||
|
||||
ESP_LOGI(TAG, "Initialize LVGL library");
|
||||
lv_init();
|
||||
// allocate two full-screen draw buffers
|
||||
lv_color_t *buf1 = malloc(EXAMPLE_LED_MATRIX_H_RES * EXAMPLE_LED_MATRIX_V_RES * sizeof(lv_color_t));
|
||||
assert(buf1);
|
||||
lv_color_t *buf2 = malloc(EXAMPLE_LED_MATRIX_H_RES * EXAMPLE_LED_MATRIX_V_RES * sizeof(lv_color_t));
|
||||
assert(buf2);
|
||||
// initialize LVGL draw buffers
|
||||
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LED_MATRIX_H_RES * EXAMPLE_LED_MATRIX_V_RES);
|
||||
lv_display_t *display = lv_display_create(EXAMPLE_LED_MATRIX_H_RES, EXAMPLE_LED_MATRIX_V_RES);
|
||||
|
||||
ESP_LOGI(TAG, "Register display driver to LVGL");
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.hor_res = EXAMPLE_LED_MATRIX_H_RES;
|
||||
disp_drv.ver_res = EXAMPLE_LED_MATRIX_V_RES;
|
||||
disp_drv.flush_cb = example_lvgl_flush_cb;
|
||||
disp_drv.draw_buf = &disp_buf;
|
||||
disp_drv.user_data = NULL;
|
||||
disp_drv.full_refresh = true; // the full_refresh mode can maintain the synchronization between two adjacent frame buffers
|
||||
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
|
||||
// allocate two full-screen draw buffers
|
||||
size_t draw_buffer_sz = EXAMPLE_LED_MATRIX_H_RES * EXAMPLE_LED_MATRIX_V_RES * sizeof(lv_color16_t);
|
||||
void *buf1 = heap_caps_calloc(1, draw_buffer_sz, MALLOC_CAP_INTERNAL);
|
||||
assert(buf1);
|
||||
void *buf2 = heap_caps_calloc(1, draw_buffer_sz, MALLOC_CAP_INTERNAL);
|
||||
assert(buf2);
|
||||
// Use RGB565 because RGB332 is not supported in LVGL9.2
|
||||
lv_display_set_color_format(display, LV_COLOR_FORMAT_RGB565);
|
||||
// initialize LVGL draw buffers
|
||||
// Since the rgb matrix needs to be refreshed dynamically, use fullmode
|
||||
lv_display_set_buffers(display, buf1, buf2, draw_buffer_sz, LV_DISPLAY_RENDER_MODE_FULL);
|
||||
// set the callback which can copy the rendered image to an area of the display
|
||||
lv_display_set_flush_cb(display, example_lvgl_flush_cb);
|
||||
|
||||
ESP_LOGI(TAG, "Install LVGL tick timer");
|
||||
// increase the LVGL tick in the GPTimer alarm callback
|
||||
@@ -198,7 +189,7 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(gptimer_enable(lvgl_tick_timer));
|
||||
|
||||
ESP_LOGI(TAG, "Display LVGL UI");
|
||||
example_lvgl_demo_ui(disp);
|
||||
example_lvgl_demo_ui(display);
|
||||
|
||||
ESP_ERROR_CHECK(gptimer_start(lvgl_tick_timer));
|
||||
|
||||
@@ -210,7 +201,7 @@ void app_main(void)
|
||||
while (1) {
|
||||
for (int i = 0; i < EXAMPLE_LED_MATRIX_V_RES / 2; i++) {
|
||||
ESP_ERROR_CHECK(parlio_tx_unit_transmit(tx_unit, payload + EXAMPLE_LED_MATRIX_H_RES * i,
|
||||
EXAMPLE_LED_MATRIX_H_RES * sizeof(lv_color_t) * 8, &transmit_config));
|
||||
EXAMPLE_LED_MATRIX_H_RES * sizeof(uint8_t) * 8, &transmit_config));
|
||||
}
|
||||
ESP_ERROR_CHECK(parlio_tx_unit_wait_all_done(tx_unit, -1));
|
||||
lv_timer_handler();
|
||||
|
@@ -1,6 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
@@ -11,6 +10,5 @@ def test_simple_rgb_led_matrix_example(dut: Dut) -> None:
|
||||
dut.expect_exact('example: Install fast GPIO bundle for line address control')
|
||||
dut.expect_exact('example: Install parallel IO TX unit')
|
||||
dut.expect_exact('example: Initialize LVGL library')
|
||||
dut.expect_exact('example: Register display driver to LVGL')
|
||||
dut.expect_exact('example: Install LVGL tick timer')
|
||||
dut.expect_exact('example: Display LVGL UI')
|
||||
|
@@ -2,5 +2,4 @@
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_ESP_TASK_WDT_INIT=n
|
||||
CONFIG_LV_COLOR_DEPTH_8=y
|
||||
CONFIG_LV_THEME_DEFAULT_DARK=y
|
||||
|
@@ -0,0 +1,13 @@
|
||||
CONFIG_EXAMPLE_PIN_NUM_R1=7
|
||||
CONFIG_EXAMPLE_PIN_NUM_G1=4
|
||||
CONFIG_EXAMPLE_PIN_NUM_B1=1
|
||||
CONFIG_EXAMPLE_PIN_NUM_R2=6
|
||||
CONFIG_EXAMPLE_PIN_NUM_G2=3
|
||||
CONFIG_EXAMPLE_PIN_NUM_B2=0
|
||||
CONFIG_EXAMPLE_PIN_NUM_LATCH=5
|
||||
CONFIG_EXAMPLE_PIN_NUM_OE=2
|
||||
CONFIG_EXAMPLE_PIN_NUM_PCLK=10
|
||||
CONFIG_EXAMPLE_PIN_NUM_A=20
|
||||
CONFIG_EXAMPLE_PIN_NUM_B=21
|
||||
CONFIG_EXAMPLE_PIN_NUM_C=22
|
||||
CONFIG_EXAMPLE_PIN_NUM_D=23
|
@@ -0,0 +1,13 @@
|
||||
CONFIG_EXAMPLE_PIN_NUM_R1=12
|
||||
CONFIG_EXAMPLE_PIN_NUM_G1=0
|
||||
CONFIG_EXAMPLE_PIN_NUM_B1=22
|
||||
CONFIG_EXAMPLE_PIN_NUM_R2=2
|
||||
CONFIG_EXAMPLE_PIN_NUM_G2=1
|
||||
CONFIG_EXAMPLE_PIN_NUM_B2=3
|
||||
CONFIG_EXAMPLE_PIN_NUM_LATCH=11
|
||||
CONFIG_EXAMPLE_PIN_NUM_OE=26
|
||||
CONFIG_EXAMPLE_PIN_NUM_PCLK=27
|
||||
CONFIG_EXAMPLE_PIN_NUM_A=8
|
||||
CONFIG_EXAMPLE_PIN_NUM_B=5
|
||||
CONFIG_EXAMPLE_PIN_NUM_C=9
|
||||
CONFIG_EXAMPLE_PIN_NUM_D=10
|
Reference in New Issue
Block a user