diff --git a/examples/lvgl_example/lvgl_example.ino b/examples/lvgl_example/lvgl_example.ino new file mode 100644 index 0000000..93b3fb8 --- /dev/null +++ b/examples/lvgl_example/lvgl_example.ino @@ -0,0 +1,267 @@ +#include +#include +#include +#define TOUCH_MODULES_GT911 +#include "TouchLib.h" +#include "utilities.h" + +static void slider_event_cb(lv_event_t *e); +static lv_obj_t *slider_label; + +TouchLib touch = TouchLib(Wire, BOARD_I2C_SDA, BOARD_I2C_SCL, GT911_SLAVE_ADDRESS1); +TFT_eSPI tft; + + +// LilyGo T-Deck control backlight chip has 16 levels of adjustment range +// The adjustable range is 0~15, 0 is the minimum brightness, 15 is the maximum brightness +void setBrightness(uint8_t value) +{ + static uint8_t level = 0; + static uint8_t steps = 16; + if (value == 0) { + digitalWrite(BOARD_BL_PIN, 0); + delay(3); + level = 0; + return; + } + if (level == 0) { + digitalWrite(BOARD_BL_PIN, 1); + level = steps; + delayMicroseconds(30); + } + int from = steps - level; + int to = steps - value; + int num = (steps + to - from) % steps; + for (int i = 0; i < num; i++) { + digitalWrite(BOARD_BL_PIN, 0); + digitalWrite(BOARD_BL_PIN, 1); + } + level = value; +} + + +// !!! LVGL !!! +// !!! LVGL !!! +// !!! LVGL !!! +static void disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ) +{ + uint32_t w = ( area->x2 - area->x1 + 1 ); + uint32_t h = ( area->y2 - area->y1 + 1 ); + tft.startWrite(); + tft.setAddrWindow( area->x1, area->y1, w, h ); + tft.pushColors( ( uint16_t * )&color_p->full, w * h, false ); + tft.endWrite(); + lv_disp_flush_ready( disp ); +} + +static volatile bool touch_irq = false; + +static bool getTouch(int16_t &x, int16_t &y) +{ + uint8_t rotation = tft.getRotation(); + if (!touch.read()) { + return false; + } + TP_Point t = touch.getPoint(0); + switch (rotation) { + case 1: + x = t.y; + y = tft.height() - t.x; + break; + case 2: + x = tft.width() - t.x; + y = tft.height() - t.y; + break; + case 3: + x = tft.width() - t.y; + y = t.x; + break; + case 0: + default: + x = t.x; + y = t.y; + } + Serial.printf("R:%d X:%d Y:%d\n", rotation, x, y); + return true; +} + +/*Read the touchpad*/ +static void touchpad_read( lv_indev_drv_t *indev_driver, lv_indev_data_t *data ) +{ + data->state = getTouch(data->point.x, data->point.y) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; +} + + +void setupLvgl() +{ +#define LVGL_BUFFER_SIZE (TFT_WIDTH * TFT_HEIGHT * sizeof(lv_color_t)) + + static lv_disp_draw_buf_t draw_buf; + static lv_color_t *buf = (lv_color_t *)ps_malloc(LVGL_BUFFER_SIZE); + if (!buf) { + Serial.println("menory alloc failed!"); + delay(5000); + assert(buf); + } + String LVGL_Arduino = "Hello Arduino! "; + LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch(); + Serial.println( LVGL_Arduino ); + Serial.println( "I am LVGL_Arduino" ); + + lv_init(); + + lv_group_set_default(lv_group_create()); + + lv_disp_draw_buf_init( &draw_buf, buf, NULL, LVGL_BUFFER_SIZE ); + + /*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 = TFT_HEIGHT; + disp_drv.ver_res = TFT_WIDTH; + disp_drv.flush_cb = disp_flush; + disp_drv.draw_buf = &draw_buf; + disp_drv.full_refresh = 1; + lv_disp_drv_register( &disp_drv ); + + /*Initialize the input device driver*/ + + /*Register a touchscreen input device*/ + static lv_indev_drv_t indev_touchpad; + lv_indev_drv_init( &indev_touchpad ); + indev_touchpad.type = LV_INDEV_TYPE_POINTER; + indev_touchpad.read_cb = touchpad_read; + lv_indev_drv_register( &indev_touchpad ); +} + +static void slider_event_cb(lv_event_t *e) +{ + lv_obj_t *slider = lv_event_get_target(e); + char buf[8]; + lv_snprintf(buf, sizeof(buf), "%d%%", (int)lv_slider_get_value(slider)); + lv_label_set_text(slider_label, buf); + lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); +} + +static void set_angle(void *obj, int32_t v) +{ + lv_arc_set_value((lv_obj_t *)obj, v); +} + + +void setup() +{ + Serial.begin(115200); + + Serial.println("lvgl example"); + + //! The board peripheral power control pin needs to be set to HIGH when using the peripheral + pinMode(BOARD_POWERON, OUTPUT); + digitalWrite(BOARD_POWERON, HIGH); + + //! Set CS on all SPI buses to high level during initialization + pinMode(BOARD_SDCARD_CS, OUTPUT); + pinMode(RADIO_CS_PIN, OUTPUT); + pinMode(BOARD_TFT_CS, OUTPUT); + + digitalWrite(BOARD_SDCARD_CS, HIGH); + digitalWrite(RADIO_CS_PIN, HIGH); + digitalWrite(BOARD_TFT_CS, HIGH); + + pinMode(BOARD_SPI_MISO, INPUT_PULLUP); + SPI.begin(BOARD_SPI_SCK, BOARD_SPI_MISO, BOARD_SPI_MOSI); //SD + + pinMode(BOARD_BOOT_PIN, INPUT_PULLUP); + pinMode(BOARD_TBOX_G02, INPUT_PULLUP); + pinMode(BOARD_TBOX_G01, INPUT_PULLUP); + pinMode(BOARD_TBOX_G04, INPUT_PULLUP); + pinMode(BOARD_TBOX_G03, INPUT_PULLUP); + + //Wakeup touch chip + pinMode(BOARD_TOUCH_INT, OUTPUT); + digitalWrite(BOARD_TOUCH_INT, HIGH); + + Serial.print("Init display id:"); + Serial.println(USER_SETUP_ID); + + tft.begin(); + tft.setRotation( 1 ); + tft.fillScreen(TFT_BLACK); + + // Set touch int input + pinMode(BOARD_TOUCH_INT, INPUT); delay(20); + + touch.init(); + + setupLvgl(); + + lv_obj_t *tv = lv_tileview_create(lv_scr_act()); + + /*Tile1: just a label*/ + lv_obj_t *tile1 = lv_tileview_add_tile(tv, 0, 0, LV_DIR_BOTTOM | LV_DIR_HOR); + lv_obj_t *label = lv_label_create(tile1); + lv_label_set_text(label, "Scroll down"); + lv_obj_center(label); + + + /*Tile2: a slider*/ + lv_obj_t *tile2 = lv_tileview_add_tile(tv, 0, 1, LV_DIR_TOP | LV_DIR_RIGHT); + + /*Create a slider in the center of the display*/ + lv_obj_t *slider = lv_slider_create(tile2); + lv_obj_center(slider); + lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL); + /*Create a label below the slider*/ + slider_label = lv_label_create(tile2); + lv_label_set_text(slider_label, "0%"); + lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); + + /*Tile3: a list*/ + lv_obj_t *tile3 = lv_tileview_add_tile(tv, 1, 1, LV_DIR_LEFT); + lv_obj_t *list = lv_list_create(tile3); + lv_obj_set_size(list, LV_PCT(100), LV_PCT(100)); + + lv_list_add_btn(list, NULL, "One"); + lv_list_add_btn(list, NULL, "Two"); + lv_list_add_btn(list, NULL, "Three"); + lv_list_add_btn(list, NULL, "Four"); + lv_list_add_btn(list, NULL, "Five"); + lv_list_add_btn(list, NULL, "Six"); + lv_list_add_btn(list, NULL, "Seven"); + lv_list_add_btn(list, NULL, "Eight"); + lv_list_add_btn(list, NULL, "Nine"); + lv_list_add_btn(list, NULL, "Ten"); + + /*Tile4: a arc*/ + lv_obj_t *tile4 = lv_tileview_add_tile(tv, 1, 0, LV_DIR_HOR); + + /*Create an Arc*/ + lv_obj_t *arc = lv_arc_create(tile4); + lv_arc_set_rotation(arc, 270); + lv_arc_set_bg_angles(arc, 0, 360); + lv_obj_remove_style(arc, NULL, LV_PART_KNOB); /*Be sure the knob is not displayed*/ + lv_obj_clear_flag(arc, LV_OBJ_FLAG_CLICKABLE); /*To not allow adjusting by click*/ + lv_obj_center(arc); + + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, arc); + lv_anim_set_exec_cb(&a, set_angle); + lv_anim_set_time(&a, 1000); + lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); /*Just for the demo*/ + lv_anim_set_repeat_delay(&a, 500); + lv_anim_set_values(&a, 0, 100); + lv_anim_start(&a); + + // Adjust backlight + pinMode(BOARD_BL_PIN, OUTPUT); + setBrightness(16); +} + +void loop() +{ + lv_timer_handler(); + delay(5); +} \ No newline at end of file diff --git a/examples/lvgl_example/utilities.h b/examples/lvgl_example/utilities.h new file mode 100644 index 0000000..de79d6a --- /dev/null +++ b/examples/lvgl_example/utilities.h @@ -0,0 +1,55 @@ +/** + * @file utilities.h + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2023 Shenzhen Xin Yuan Electronic Technology Co., Ltd + * @date 2023-04-11 + * + */ +#pragma once + + + +//! The board peripheral power control pin needs to be set to HIGH when using the peripheral +#define BOARD_POWERON 10 + +#define BOARD_I2S_WS 5 +#define BOARD_I2S_BCK 7 +#define BOARD_I2S_DOUT 6 + +#define BOARD_I2C_SDA 18 +#define BOARD_I2C_SCL 8 + +#define BOARD_BAT_ADC 4 + +#define BOARD_TOUCH_INT 16 +#define BOARD_KEYBOARD_INT 46 + +#define BOARD_SDCARD_CS 39 +#define BOARD_TFT_CS 12 +#define RADIO_CS_PIN 9 + +#define BOARD_TFT_DC 11 +#define BOARD_TFT_BACKLIGHT 42 + +#define BOARD_SPI_MOSI 41 +#define BOARD_SPI_MISO 38 +#define BOARD_SPI_SCK 40 + +#define BOARD_TBOX_G02 2 +#define BOARD_TBOX_G01 3 +#define BOARD_TBOX_G04 1 +#define BOARD_TBOX_G03 15 + +#define BOARD_ES7210_MCLK 48 +#define BOARD_ES7210_LRCK 21 +#define BOARD_ES7210_SCK 47 +#define BOARD_ES7210_DIN 14 + +#define RADIO_BUSY_PIN 13 +#define RADIO_RST_PIN 17 +#define RADIO_DIO1_PIN 45 + +#define BOARD_BOOT_PIN 0 + +#define BOARD_BL_PIN 42 \ No newline at end of file