SHA256
Перенёс основной ESP32-скетч в main-device
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# Test Sketches
|
||||
|
||||
Набор старых отдельных диагностических скетчей для `Waveshare ESP32-S3-Touch-AMOLED-2.16`.
|
||||
|
||||
Скетчи в этой папке нужны для быстрой проверки конкретных гипотез и не являются основным UI проекта.
|
||||
Основной скетч сейчас лежит в `main-device/shine_homeserver_main/`.
|
||||
|
||||
## Список
|
||||
|
||||
- `gfx_text_render_test/` - проверка рендера текста через `Arduino_GFX` и сравнение с `U8g2`
|
||||
- `gfx_button_layout_test/` - проверка геометрии кнопок, особенно нижних рядов и широких кнопок
|
||||
- `lvgl_basic_test/` - минимальный тест `LVGL` с заголовком, текстом и кнопками
|
||||
- `lvgl_interaction_test/` - расширенный тест `LVGL` с 9 кнопками, touch-вводом и статусом нажатия
|
||||
- `lvgl_touch_debug_test/` - диагностика touch: сырые координаты, точка касания и одна большая кнопка `LVGL`
|
||||
- `lvgl_official_based_test/` - минимальный наш экран поверх максимально близкой к официальному `05_LVGL_Widgets` инициализации
|
||||
- `lvgl_subserver_touch_test/` - старый гибридный тест: `LVGL`-экран с инициализацией дисплея и чтением touch из старого `shine_homeserver_ui`; подтверждён на реальном устройстве
|
||||
- `lvgl_russian_font_test/` - тест кастомного кириллического `LVGL`-шрифта с русскими кнопками, длинными строками и рабочим touch
|
||||
- `lvgl_nav_minimal_test/` - старое тестовое имя, этот скетч перенесён в `shine_homeserver_main/` и теперь является основным
|
||||
|
||||
## Запуск
|
||||
|
||||
Использовать через `burn.sh`:
|
||||
|
||||
- `./burn.sh gfx-text-test`
|
||||
- `./burn.sh gfx-layout-test`
|
||||
- `./burn.sh lvgl-basic-test`
|
||||
- `./burn.sh lvgl-interaction-test`
|
||||
- `./burn.sh lvgl-touch-debug-test`
|
||||
- `./burn.sh lvgl-official-based-test`
|
||||
- `./burn.sh lvgl-subserver-touch-test`
|
||||
- `./burn.sh lvgl-russian-font-test`
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <Arduino_GFX_Library.h>
|
||||
|
||||
#define PIN_LCD_CS 12
|
||||
#define PIN_LCD_SCLK 38
|
||||
#define PIN_LCD_D0 4
|
||||
#define PIN_LCD_D1 5
|
||||
#define PIN_LCD_D2 6
|
||||
#define PIN_LCD_D3 7
|
||||
#define PIN_LCD_RST 2
|
||||
#define PIN_I2C_SDA 15
|
||||
#define PIN_I2C_SCL 14
|
||||
|
||||
#define DISP_W 480
|
||||
#define DISP_H 480
|
||||
|
||||
#define C_BG 0x0841u
|
||||
#define C_PANEL 0x1082u
|
||||
#define C_CARD 0x18C3u
|
||||
#define C_BORDER 0x39C7u
|
||||
#define C_TEXT 0xFFFFu
|
||||
#define C_OK 0x3666u
|
||||
#define C_WARN 0xECA0u
|
||||
#define C_BUTTON 0x2145u
|
||||
#define C_BUTTON2 0x3186u
|
||||
|
||||
Arduino_DataBus *gBus = new Arduino_ESP32QSPI(
|
||||
PIN_LCD_CS, PIN_LCD_SCLK, PIN_LCD_D0, PIN_LCD_D1, PIN_LCD_D2, PIN_LCD_D3);
|
||||
Arduino_CO5300 *gfx = new Arduino_CO5300(
|
||||
gBus, PIN_LCD_RST, 0, DISP_W, DISP_H, 0, 0, 0, 0);
|
||||
|
||||
static void drawPanel(int x, int y, int w, int h, uint16_t fill, uint16_t border, int radius = 10) {
|
||||
gfx->fillRoundRect(x, y, w, h, radius, fill);
|
||||
gfx->drawRoundRect(x, y, w, h, radius, border);
|
||||
}
|
||||
|
||||
static void drawText(int x, int y, const char *text, uint16_t color, uint8_t size = 2) {
|
||||
gfx->setFont();
|
||||
gfx->setTextSize(size);
|
||||
gfx->setTextColor(color);
|
||||
gfx->setCursor(x, y);
|
||||
gfx->print(text);
|
||||
}
|
||||
|
||||
static void drawButton(int x, int y, int w, int h, uint16_t fill, const char *label, uint8_t size = 2) {
|
||||
drawPanel(x, y, w, h, fill, C_BORDER, 12);
|
||||
gfx->setFont();
|
||||
gfx->setTextSize(size);
|
||||
gfx->setTextColor(C_TEXT);
|
||||
int textW = strlen(label) * 6 * size;
|
||||
int textX = x + (w - textW) / 2;
|
||||
if (textX < x + 8) {
|
||||
textX = x + 8;
|
||||
}
|
||||
int textY = y + (h + 8 * size) / 2 - 2;
|
||||
gfx->setCursor(textX, textY);
|
||||
gfx->print(label);
|
||||
}
|
||||
|
||||
static void drawScreen() {
|
||||
gfx->fillScreen(C_BG);
|
||||
drawPanel(12, 12, 456, 456, C_PANEL, C_BORDER, 16);
|
||||
drawText(24, 42, "BUTTON LAYOUT TEST", C_TEXT, 2);
|
||||
drawText(24, 70, "Check bottom and wide buttons", C_WARN, 1);
|
||||
|
||||
drawButton(20, 110, 136, 52, C_BUTTON, "STATUS");
|
||||
drawButton(172, 110, 136, 52, C_BUTTON, "CONNECT");
|
||||
drawButton(324, 110, 136, 52, C_BUTTON, "ACCOUNT");
|
||||
|
||||
drawButton(20, 180, 136, 52, C_BUTTON, "WALLET");
|
||||
drawButton(172, 180, 136, 52, C_BUTTON, "REQUESTS");
|
||||
drawButton(324, 180, 136, 52, C_BUTTON, "SETTINGS");
|
||||
|
||||
drawButton(20, 270, 212, 48, C_BUTTON2, "BACK");
|
||||
drawButton(248, 270, 212, 48, C_OK, "REFRESH");
|
||||
|
||||
drawButton(20, 338, 440, 40, C_BUTTON2, "FULL WIDTH BUTTON", 2);
|
||||
drawButton(20, 390, 440, 56, C_OK, "REGISTER DEVICE", 2);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL);
|
||||
gfx->begin();
|
||||
gBus->writeC8D8(0x36, 0xA0);
|
||||
gfx->setBrightness(220);
|
||||
drawScreen();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(1000);
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <Arduino_GFX_Library.h>
|
||||
#include <U8g2lib.h>
|
||||
|
||||
#define PIN_LCD_CS 12
|
||||
#define PIN_LCD_SCLK 38
|
||||
#define PIN_LCD_D0 4
|
||||
#define PIN_LCD_D1 5
|
||||
#define PIN_LCD_D2 6
|
||||
#define PIN_LCD_D3 7
|
||||
#define PIN_LCD_RST 2
|
||||
#define PIN_I2C_SDA 15
|
||||
#define PIN_I2C_SCL 14
|
||||
|
||||
#define DISP_W 480
|
||||
#define DISP_H 480
|
||||
|
||||
#define C_BG 0x0841u
|
||||
#define C_PANEL 0x1082u
|
||||
#define C_CARD 0x18C3u
|
||||
#define C_BORDER 0x39C7u
|
||||
#define C_TEXT 0xFFFFu
|
||||
#define C_MUTE 0xBDF7u
|
||||
#define C_OK 0x3666u
|
||||
#define C_WARN 0xECA0u
|
||||
#define C_BUTTON 0x2145u
|
||||
#define C_BUTTON2 0x3186u
|
||||
|
||||
#define FONT_BODY u8g2_font_9x15_t_cyrillic
|
||||
#define FONT_SMALL u8g2_font_6x13_t_cyrillic
|
||||
|
||||
Arduino_DataBus *gBus = new Arduino_ESP32QSPI(
|
||||
PIN_LCD_CS, PIN_LCD_SCLK, PIN_LCD_D0, PIN_LCD_D1, PIN_LCD_D2, PIN_LCD_D3);
|
||||
Arduino_CO5300 *gfx = new Arduino_CO5300(
|
||||
gBus, PIN_LCD_RST, 0, DISP_W, DISP_H, 0, 0, 0, 0);
|
||||
|
||||
static void drawPanel(int x, int y, int w, int h, uint16_t fill, uint16_t border, int radius = 10) {
|
||||
gfx->fillRoundRect(x, y, w, h, radius, fill);
|
||||
gfx->drawRoundRect(x, y, w, h, radius, border);
|
||||
}
|
||||
|
||||
static void drawDefaultText(int x, int y, const char *text, uint16_t color, uint8_t size = 1) {
|
||||
gfx->setFont();
|
||||
gfx->setTextSize(size);
|
||||
gfx->setTextColor(color);
|
||||
gfx->setCursor(x, y);
|
||||
gfx->print(text);
|
||||
}
|
||||
|
||||
static void drawU8Text(int x, int y, const String &text, uint16_t color, const uint8_t *font) {
|
||||
gfx->setTextSize(1);
|
||||
gfx->setFont(font);
|
||||
gfx->setTextColor(color);
|
||||
gfx->setCursor(x, y);
|
||||
gfx->print(text);
|
||||
}
|
||||
|
||||
static void drawButton(int x, int y, int w, int h, uint16_t fill, const String &label, const uint8_t *font, bool useDefaultFont = false) {
|
||||
drawPanel(x, y, w, h, fill, C_BORDER, 12);
|
||||
if (useDefaultFont) {
|
||||
drawDefaultText(x + 14, y + 30, label.c_str(), C_TEXT, 2);
|
||||
return;
|
||||
}
|
||||
drawU8Text(x + 14, y + 32, label, C_TEXT, font);
|
||||
}
|
||||
|
||||
static void drawScreen() {
|
||||
gfx->fillScreen(C_BG);
|
||||
|
||||
drawPanel(12, 12, 456, 456, C_PANEL, C_BORDER, 16);
|
||||
drawDefaultText(28, 42, "TEXT TEST 123", C_TEXT, 2);
|
||||
drawU8Text(28, 72, "Default ASCII above", C_MUTE, (const uint8_t *)FONT_SMALL);
|
||||
|
||||
drawPanel(24, 90, 432, 72, C_CARD, C_BORDER, 12);
|
||||
drawDefaultText(38, 118, "A: Default font ABC123", C_TEXT, 2);
|
||||
drawDefaultText(38, 146, "Visible? then base path OK", C_WARN, 1);
|
||||
|
||||
drawPanel(24, 174, 432, 84, C_CARD, C_BORDER, 12);
|
||||
drawU8Text(38, 204, "B: U8g2 ASCII abc123", C_TEXT, (const uint8_t *)FONT_BODY);
|
||||
drawU8Text(38, 230, "C: Русский текст 123", C_OK, (const uint8_t *)FONT_BODY);
|
||||
|
||||
drawPanel(24, 270, 432, 84, C_CARD, C_BORDER, 12);
|
||||
drawU8Text(38, 298, "D: Мелкий шрифт кнопок", C_TEXT, (const uint8_t *)FONT_SMALL);
|
||||
drawU8Text(38, 320, "Если это видно, FONT_SMALL жив", C_MUTE, (const uint8_t *)FONT_SMALL);
|
||||
|
||||
drawButton(24, 368, 128, 72, C_BUTTON, "BTN 1", nullptr, true);
|
||||
drawButton(176, 368, 128, 72, C_OK, "abc123", (const uint8_t *)FONT_BODY);
|
||||
drawButton(328, 368, 128, 72, C_BUTTON2, "Русский", (const uint8_t *)FONT_BODY);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL);
|
||||
gfx->begin();
|
||||
gBus->writeC8D8(0x36, 0xA0);
|
||||
gfx->setBrightness(220);
|
||||
gfx->setUTF8Print(true);
|
||||
drawScreen();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(1000);
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <lvgl.h>
|
||||
#include <Arduino_GFX_Library.h>
|
||||
#include "pin_config.h"
|
||||
|
||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||
|
||||
static lv_disp_draw_buf_t gDrawBuf;
|
||||
static lv_color_t *gBuf1 = nullptr;
|
||||
static lv_color_t *gBuf2 = nullptr;
|
||||
|
||||
Arduino_DataBus *gBus = new Arduino_ESP32QSPI(
|
||||
LCD_CS, LCD_SCLK, LCD_SDIO0, LCD_SDIO1, LCD_SDIO2, LCD_SDIO3);
|
||||
Arduino_CO5300 *gfx = new Arduino_CO5300(
|
||||
gBus, LCD_RESET, 0, LCD_WIDTH, LCD_HEIGHT, 0, 0, 0, 0);
|
||||
|
||||
static void lvglRounderCb(lv_disp_drv_t *dispDrv, lv_area_t *area) {
|
||||
LV_UNUSED(dispDrv);
|
||||
if (area->x1 % 2 != 0) area->x1--;
|
||||
if (area->y1 % 2 != 0) area->y1--;
|
||||
if (area->x2 % 2 == 0) area->x2++;
|
||||
if (area->y2 % 2 == 0) area->y2++;
|
||||
}
|
||||
|
||||
static void lvglFlushCb(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *colorP) {
|
||||
uint32_t w = area->x2 - area->x1 + 1;
|
||||
uint32_t h = area->y2 - area->y1 + 1;
|
||||
#if (LV_COLOR_16_SWAP != 0)
|
||||
gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#else
|
||||
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#endif
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
||||
|
||||
static void lvglTick(void *arg) {
|
||||
LV_UNUSED(arg);
|
||||
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static void createUi() {
|
||||
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex(0x0B1320), 0);
|
||||
lv_obj_set_style_bg_opa(lv_scr_act(), LV_OPA_COVER, 0);
|
||||
|
||||
lv_obj_t *title = lv_label_create(lv_scr_act());
|
||||
lv_label_set_text(title, "LVGL BASIC TEST");
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_set_style_text_font(title, &lv_font_montserrat_22, 0);
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 18);
|
||||
|
||||
lv_obj_t *subtitle = lv_label_create(lv_scr_act());
|
||||
lv_label_set_text(subtitle, "If this text is visible, LVGL path works.");
|
||||
lv_obj_set_width(subtitle, 420);
|
||||
lv_label_set_long_mode(subtitle, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_color(subtitle, lv_color_hex(0xD5DCE5), 0);
|
||||
lv_obj_set_style_text_font(subtitle, &lv_font_montserrat_16, 0);
|
||||
lv_obj_align(subtitle, LV_ALIGN_TOP_MID, 0, 58);
|
||||
|
||||
const char *labels[3] = {"Button One", "Second Button", "Bottom Action"};
|
||||
const lv_color_t colors[3] = {
|
||||
lv_color_hex(0x2B4C7E),
|
||||
lv_color_hex(0x2E8B57),
|
||||
lv_color_hex(0xB45F06),
|
||||
};
|
||||
const lv_coord_t ys[3] = {150, 236, 340};
|
||||
const lv_coord_t hs[3] = {58, 58, 64};
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
lv_obj_t *btn = lv_btn_create(lv_scr_act());
|
||||
lv_obj_set_size(btn, 360, hs[i]);
|
||||
lv_obj_align(btn, LV_ALIGN_TOP_MID, 0, ys[i]);
|
||||
lv_obj_set_style_radius(btn, 14, 0);
|
||||
lv_obj_set_style_bg_color(btn, colors[i], 0);
|
||||
lv_obj_set_style_border_width(btn, 2, 0);
|
||||
lv_obj_set_style_border_color(btn, lv_color_hex(0x7F96B0), 0);
|
||||
|
||||
lv_obj_t *label = lv_label_create(btn);
|
||||
lv_label_set_text(label, labels[i]);
|
||||
lv_obj_set_style_text_font(label, &lv_font_montserrat_20, 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_center(label);
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin(IIC_SDA, IIC_SCL);
|
||||
|
||||
gfx->begin();
|
||||
gBus->writeC8D8(0x36, 0xA0);
|
||||
gfx->setBrightness(220);
|
||||
|
||||
lv_init();
|
||||
|
||||
uint32_t screenWidth = gfx->width();
|
||||
uint32_t screenHeight = gfx->height();
|
||||
gBuf1 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
gBuf2 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
lv_disp_draw_buf_init(&gDrawBuf, gBuf1, gBuf2, screenWidth * screenHeight / 4);
|
||||
|
||||
static lv_disp_drv_t dispDrv;
|
||||
lv_disp_drv_init(&dispDrv);
|
||||
dispDrv.hor_res = screenWidth;
|
||||
dispDrv.ver_res = screenHeight;
|
||||
dispDrv.flush_cb = lvglFlushCb;
|
||||
dispDrv.rounder_cb = lvglRounderCb;
|
||||
dispDrv.draw_buf = &gDrawBuf;
|
||||
lv_disp_drv_register(&dispDrv);
|
||||
|
||||
const esp_timer_create_args_t lvglTickTimerArgs = {
|
||||
.callback = &lvglTick,
|
||||
.name = "lvgl_tick"};
|
||||
esp_timer_handle_t lvglTickTimer = nullptr;
|
||||
esp_timer_create(&lvglTickTimerArgs, &lvglTickTimer);
|
||||
esp_timer_start_periodic(lvglTickTimer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000);
|
||||
|
||||
createUi();
|
||||
Serial.println("LVGL basic test ready");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
lv_timer_handler();
|
||||
delay(5);
|
||||
}
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <lvgl.h>
|
||||
#include <Arduino_GFX_Library.h>
|
||||
#include "pin_config.h"
|
||||
#include "TouchDrvCSTXXX.hpp"
|
||||
|
||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||
|
||||
static lv_disp_draw_buf_t gDrawBuf;
|
||||
static lv_color_t *gBuf1 = nullptr;
|
||||
static lv_color_t *gBuf2 = nullptr;
|
||||
static lv_obj_t *gStatusLabel = nullptr;
|
||||
static uint32_t gPressCount = 0;
|
||||
|
||||
static TouchDrvCST92xx gTouch;
|
||||
static int16_t gTouchX[5];
|
||||
static int16_t gTouchY[5];
|
||||
|
||||
Arduino_DataBus *gBus = new Arduino_ESP32QSPI(
|
||||
LCD_CS, LCD_SCLK, LCD_SDIO0, LCD_SDIO1, LCD_SDIO2, LCD_SDIO3);
|
||||
Arduino_CO5300 *gfx = new Arduino_CO5300(
|
||||
gBus, LCD_RESET, 0, LCD_WIDTH, LCD_HEIGHT, 0, 0, 0, 0);
|
||||
|
||||
static void lvglFlushCb(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *colorP) {
|
||||
uint32_t w = area->x2 - area->x1 + 1;
|
||||
uint32_t h = area->y2 - area->y1 + 1;
|
||||
#if (LV_COLOR_16_SWAP != 0)
|
||||
gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#else
|
||||
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#endif
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
||||
|
||||
static void lvglTick(void *arg) {
|
||||
LV_UNUSED(arg);
|
||||
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static void lvglTouchRead(lv_indev_drv_t *indevDrv, lv_indev_data_t *data) {
|
||||
LV_UNUSED(indevDrv);
|
||||
uint8_t touched = gTouch.getPoint(gTouchX, gTouchY, gTouch.getSupportTouchPoint());
|
||||
if (touched > 0) {
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
data->point.x = gTouchX[0];
|
||||
data->point.y = gTouchY[0];
|
||||
return;
|
||||
}
|
||||
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
}
|
||||
|
||||
static void buttonEventCb(lv_event_t *event) {
|
||||
if (lv_event_get_code(event) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_t *btn = lv_event_get_target(event);
|
||||
const char *name = (const char *)lv_event_get_user_data(event);
|
||||
gPressCount++;
|
||||
|
||||
lv_obj_set_style_outline_width(btn, 4, 0);
|
||||
lv_obj_set_style_outline_color(btn, lv_color_hex(0xFFF3B0), 0);
|
||||
lv_obj_set_style_outline_pad(btn, 2, 0);
|
||||
|
||||
String status = "Pressed: ";
|
||||
status += name;
|
||||
status += " (#";
|
||||
status += String(gPressCount);
|
||||
status += ")";
|
||||
lv_label_set_text(gStatusLabel, status.c_str());
|
||||
|
||||
Serial.println(status);
|
||||
}
|
||||
|
||||
static void createButton(lv_obj_t *parent, const char *labelText, lv_coord_t col, lv_coord_t row, uint32_t colorHex) {
|
||||
static const lv_coord_t kStartX = 22;
|
||||
static const lv_coord_t kStartY = 122;
|
||||
static const lv_coord_t kButtonW = 134;
|
||||
static const lv_coord_t kButtonH = 64;
|
||||
static const lv_coord_t kGapX = 18;
|
||||
static const lv_coord_t kGapY = 16;
|
||||
|
||||
lv_obj_t *btn = lv_btn_create(parent);
|
||||
lv_obj_set_size(btn, kButtonW, kButtonH);
|
||||
lv_obj_set_pos(btn, kStartX + col * (kButtonW + kGapX), kStartY + row * (kButtonH + kGapY));
|
||||
lv_obj_set_style_radius(btn, 16, 0);
|
||||
lv_obj_set_style_bg_color(btn, lv_color_hex(colorHex), 0);
|
||||
lv_obj_set_style_border_width(btn, 2, 0);
|
||||
lv_obj_set_style_border_color(btn, lv_color_hex(0x7F96B0), 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, 0);
|
||||
lv_obj_add_event_cb(btn, buttonEventCb, LV_EVENT_CLICKED, (void *)labelText);
|
||||
|
||||
lv_obj_t *label = lv_label_create(btn);
|
||||
lv_label_set_text(label, labelText);
|
||||
lv_obj_set_style_text_font(label, &lv_font_montserrat_18, 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_center(label);
|
||||
}
|
||||
|
||||
static void createUi() {
|
||||
lv_obj_t *screen = lv_scr_act();
|
||||
lv_obj_set_style_bg_color(screen, lv_color_hex(0x0B1320), 0);
|
||||
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0);
|
||||
|
||||
lv_obj_t *title = lv_label_create(screen);
|
||||
lv_label_set_text(title, "LVGL INTERACTION TEST");
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_set_style_text_font(title, &lv_font_montserrat_22, 0);
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 14);
|
||||
|
||||
lv_obj_t *subtitle = lv_label_create(screen);
|
||||
lv_label_set_text(subtitle, "Tap buttons. Bottom label must change on every press.");
|
||||
lv_obj_set_width(subtitle, 420);
|
||||
lv_label_set_long_mode(subtitle, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_color(subtitle, lv_color_hex(0xD5DCE5), 0);
|
||||
lv_obj_set_style_text_font(subtitle, &lv_font_montserrat_14, 0);
|
||||
lv_obj_align(subtitle, LV_ALIGN_TOP_MID, 0, 48);
|
||||
|
||||
createButton(screen, "Status", 0, 0, 0x355C7D);
|
||||
createButton(screen, "Connect", 1, 0, 0x2A9D8F);
|
||||
createButton(screen, "Wallet", 2, 0, 0x457B9D);
|
||||
createButton(screen, "Requests", 0, 1, 0xE76F51);
|
||||
createButton(screen, "Settings", 1, 1, 0x8D5A97);
|
||||
createButton(screen, "Register", 2, 1, 0x6A994E);
|
||||
createButton(screen, "Approve", 0, 2, 0xBC6C25);
|
||||
createButton(screen, "Reject", 1, 2, 0xB56576);
|
||||
createButton(screen, "Back", 2, 2, 0x6C757D);
|
||||
|
||||
lv_obj_t *statusPanel = lv_obj_create(screen);
|
||||
lv_obj_set_size(statusPanel, 436, 56);
|
||||
lv_obj_align(statusPanel, LV_ALIGN_BOTTOM_MID, 0, -16);
|
||||
lv_obj_set_style_radius(statusPanel, 14, 0);
|
||||
lv_obj_set_style_bg_color(statusPanel, lv_color_hex(0x162033), 0);
|
||||
lv_obj_set_style_border_width(statusPanel, 2, 0);
|
||||
lv_obj_set_style_border_color(statusPanel, lv_color_hex(0x415A77), 0);
|
||||
lv_obj_set_style_pad_all(statusPanel, 10, 0);
|
||||
|
||||
gStatusLabel = lv_label_create(statusPanel);
|
||||
lv_label_set_text(gStatusLabel, "Pressed: none");
|
||||
lv_obj_set_style_text_font(gStatusLabel, &lv_font_montserrat_18, 0);
|
||||
lv_obj_set_style_text_color(gStatusLabel, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_center(gStatusLabel);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin(IIC_SDA, IIC_SCL);
|
||||
|
||||
pinMode(TP_RST, OUTPUT);
|
||||
pinMode(TP_INT, INPUT);
|
||||
digitalWrite(TP_RST, LOW);
|
||||
delay(30);
|
||||
digitalWrite(TP_RST, HIGH);
|
||||
delay(50);
|
||||
delay(1000);
|
||||
|
||||
gTouch.setPins(TP_RST, TP_INT);
|
||||
bool touchOk = gTouch.begin(Wire, 0x5A, IIC_SDA, IIC_SCL);
|
||||
if (!touchOk) {
|
||||
Serial.println("Touch init failed");
|
||||
} else {
|
||||
Serial.print("Touch model: ");
|
||||
Serial.println(gTouch.getModelName());
|
||||
gTouch.sleep();
|
||||
gTouch.reset();
|
||||
gTouch.setMaxCoordinates(480, 480);
|
||||
gTouch.setSwapXY(true);
|
||||
gTouch.setMirrorXY(true, false);
|
||||
}
|
||||
|
||||
gfx->begin();
|
||||
gBus->writeC8D8(0x36, 0xA0);
|
||||
gfx->setBrightness(220);
|
||||
gfx->fillScreen(0x0000);
|
||||
|
||||
lv_init();
|
||||
|
||||
uint32_t screenWidth = gfx->width();
|
||||
uint32_t screenHeight = gfx->height();
|
||||
gBuf1 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
gBuf2 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
lv_disp_draw_buf_init(&gDrawBuf, gBuf1, gBuf2, screenWidth * screenHeight / 4);
|
||||
|
||||
static lv_disp_drv_t dispDrv;
|
||||
lv_disp_drv_init(&dispDrv);
|
||||
dispDrv.hor_res = screenWidth;
|
||||
dispDrv.ver_res = screenHeight;
|
||||
dispDrv.flush_cb = lvglFlushCb;
|
||||
dispDrv.draw_buf = &gDrawBuf;
|
||||
lv_disp_drv_register(&dispDrv);
|
||||
|
||||
static lv_indev_drv_t indevDrv;
|
||||
lv_indev_drv_init(&indevDrv);
|
||||
indevDrv.type = LV_INDEV_TYPE_POINTER;
|
||||
indevDrv.read_cb = lvglTouchRead;
|
||||
lv_indev_drv_register(&indevDrv);
|
||||
|
||||
const esp_timer_create_args_t lvglTickTimerArgs = {
|
||||
.callback = &lvglTick,
|
||||
.name = "lvgl_tick"};
|
||||
esp_timer_handle_t lvglTickTimer = nullptr;
|
||||
esp_timer_create(&lvglTickTimerArgs, &lvglTickTimer);
|
||||
esp_timer_start_periodic(lvglTickTimer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000);
|
||||
|
||||
createUi();
|
||||
Serial.println("LVGL interaction test ready");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
lv_timer_handler();
|
||||
delay(5);
|
||||
}
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
#include <lvgl.h>
|
||||
#include "Arduino_GFX_Library.h"
|
||||
#include "pin_config.h"
|
||||
#include "TouchDrvCSTXXX.hpp"
|
||||
#include "lv_conf.h"
|
||||
#include "HWCDC.h"
|
||||
#include <Wire.h>
|
||||
|
||||
HWCDC USBSerial;
|
||||
|
||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||
|
||||
static lv_disp_draw_buf_t draw_buf;
|
||||
static lv_color_t *buf1 = nullptr;
|
||||
static lv_color_t *buf2 = nullptr;
|
||||
static lv_obj_t *status_label = nullptr;
|
||||
static uint32_t click_count = 0;
|
||||
|
||||
Arduino_DataBus *bus = new Arduino_ESP32QSPI(
|
||||
LCD_CS, LCD_SCLK, LCD_SDIO0, LCD_SDIO1, LCD_SDIO2, LCD_SDIO3);
|
||||
|
||||
Arduino_CO5300 *gfx = new Arduino_CO5300(
|
||||
bus, LCD_RESET, 0, LCD_WIDTH, LCD_HEIGHT, 0, 0, 0, 0);
|
||||
|
||||
TouchDrvCST92xx touch;
|
||||
int16_t touch_x[5], touch_y[5];
|
||||
bool isPressed = false;
|
||||
uint32_t screenWidth = 0;
|
||||
uint32_t screenHeight = 0;
|
||||
|
||||
#if LV_USE_LOG != 0
|
||||
void my_print(const char *buf) {
|
||||
USBSerial.printf(buf);
|
||||
USBSerial.flush();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void example_lvgl_rounder_cb(struct _lv_disp_drv_t *disp_drv, lv_area_t *area) {
|
||||
LV_UNUSED(disp_drv);
|
||||
if (area->x1 % 2 != 0) area->x1--;
|
||||
if (area->y1 % 2 != 0) area->y1--;
|
||||
if (area->x2 % 2 == 0) area->x2++;
|
||||
if (area->y2 % 2 == 0) area->y2++;
|
||||
}
|
||||
|
||||
static void my_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);
|
||||
|
||||
#if (LV_COLOR_16_SWAP != 0)
|
||||
gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
|
||||
#else
|
||||
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
|
||||
#endif
|
||||
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
||||
|
||||
static void example_increase_lvgl_tick(void *arg) {
|
||||
LV_UNUSED(arg);
|
||||
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
|
||||
LV_UNUSED(indev_driver);
|
||||
if (isPressed) {
|
||||
uint8_t touched = touch.getPoint(touch_x, touch_y, touch.getSupportTouchPoint());
|
||||
if (touched) {
|
||||
isPressed = false;
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
data->point.x = touch_x[0];
|
||||
data->point.y = touch_y[0];
|
||||
USBSerial.print("Touch x=");
|
||||
USBSerial.print(touch_x[0]);
|
||||
USBSerial.print(" y=");
|
||||
USBSerial.println(touch_y[0]);
|
||||
} else {
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
}
|
||||
} else {
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
}
|
||||
}
|
||||
|
||||
static void button_event_cb(lv_event_t *event) {
|
||||
if (lv_event_get_code(event) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = (const char *)lv_event_get_user_data(event);
|
||||
click_count++;
|
||||
String text = "Pressed: ";
|
||||
text += name;
|
||||
text += " (#";
|
||||
text += String(click_count);
|
||||
text += ")";
|
||||
lv_label_set_text(status_label, text.c_str());
|
||||
USBSerial.println(text);
|
||||
}
|
||||
|
||||
static lv_obj_t *make_button(lv_obj_t *parent, const char *label_text, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h, lv_color_t bg) {
|
||||
lv_obj_t *btn = lv_btn_create(parent);
|
||||
lv_obj_set_size(btn, w, h);
|
||||
lv_obj_set_pos(btn, x, y);
|
||||
lv_obj_set_style_radius(btn, 16, 0);
|
||||
lv_obj_set_style_bg_color(btn, bg, 0);
|
||||
lv_obj_set_style_border_width(btn, 2, 0);
|
||||
lv_obj_set_style_border_color(btn, lv_color_hex(0x8AA4BF), 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, 0);
|
||||
lv_obj_add_event_cb(btn, button_event_cb, LV_EVENT_CLICKED, (void *)label_text);
|
||||
|
||||
lv_obj_t *label = lv_label_create(btn);
|
||||
lv_label_set_text(label, label_text);
|
||||
lv_obj_set_style_text_font(label, &lv_font_montserrat_18, 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_center(label);
|
||||
return btn;
|
||||
}
|
||||
|
||||
static void create_ui() {
|
||||
lv_obj_t *screen = lv_scr_act();
|
||||
lv_obj_set_style_bg_color(screen, lv_color_hex(0x0B1320), 0);
|
||||
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0);
|
||||
|
||||
lv_obj_t *title = lv_label_create(screen);
|
||||
lv_label_set_text(title, "LVGL OFFICIAL BASED TEST");
|
||||
lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 14);
|
||||
|
||||
lv_obj_t *hint = lv_label_create(screen);
|
||||
lv_label_set_text(hint, "Based on official LVGL_Widgets init. Tap buttons and watch the status.");
|
||||
lv_obj_set_width(hint, 430);
|
||||
lv_label_set_long_mode(hint, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_font(hint, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(hint, lv_color_hex(0xD4DDE7), 0);
|
||||
lv_obj_align(hint, LV_ALIGN_TOP_MID, 0, 44);
|
||||
|
||||
make_button(screen, "Status", 22, 120, 136, 60, lv_color_hex(0x355C7D));
|
||||
make_button(screen, "Connect", 174, 120, 136, 60, lv_color_hex(0x2A9D8F));
|
||||
make_button(screen, "Wallet", 326, 120, 132, 60, lv_color_hex(0x457B9D));
|
||||
|
||||
make_button(screen, "Requests", 22, 196, 136, 60, lv_color_hex(0xE76F51));
|
||||
make_button(screen, "Settings",174, 196, 136, 60, lv_color_hex(0x8D5A97));
|
||||
make_button(screen, "Register",326, 196, 132, 60, lv_color_hex(0x6A994E));
|
||||
|
||||
make_button(screen, "Approve", 22, 272, 136, 60, lv_color_hex(0xBC6C25));
|
||||
make_button(screen, "Reject", 174, 272, 136, 60, lv_color_hex(0xB56576));
|
||||
make_button(screen, "Back", 326, 272, 132, 60, lv_color_hex(0x6C757D));
|
||||
|
||||
lv_obj_t *bottom_btn = make_button(screen, "Bottom Action", 22, 350, 436, 64, lv_color_hex(0x1D6F42));
|
||||
lv_obj_set_style_text_font(lv_obj_get_child(bottom_btn, 0), &lv_font_montserrat_20, 0);
|
||||
|
||||
lv_obj_t *status_panel = lv_obj_create(screen);
|
||||
lv_obj_set_size(status_panel, 436, 42);
|
||||
lv_obj_set_pos(status_panel, 22, 426);
|
||||
lv_obj_set_style_radius(status_panel, 12, 0);
|
||||
lv_obj_set_style_bg_color(status_panel, lv_color_hex(0x17263A), 0);
|
||||
lv_obj_set_style_border_width(status_panel, 2, 0);
|
||||
lv_obj_set_style_border_color(status_panel, lv_color_hex(0x496582), 0);
|
||||
lv_obj_set_style_pad_all(status_panel, 6, 0);
|
||||
|
||||
status_label = lv_label_create(status_panel);
|
||||
lv_label_set_text(status_label, "Pressed: none");
|
||||
lv_obj_set_style_text_font(status_label, &lv_font_montserrat_16, 0);
|
||||
lv_obj_set_style_text_color(status_label, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_center(status_label);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
USBSerial.begin(115200);
|
||||
|
||||
Wire.begin(IIC_SDA, IIC_SCL);
|
||||
|
||||
digitalWrite(TP_RST, LOW);
|
||||
delay(30);
|
||||
digitalWrite(TP_RST, HIGH);
|
||||
delay(50);
|
||||
delay(1000);
|
||||
|
||||
Wire.begin(IIC_SDA, IIC_SCL);
|
||||
|
||||
touch.setPins(TP_RST, TP_INT);
|
||||
bool result = touch.begin(Wire, 0x5A, IIC_SDA, IIC_SCL);
|
||||
if (result == false) {
|
||||
USBSerial.println("touch is not online...");
|
||||
while (1) delay(1000);
|
||||
}
|
||||
USBSerial.print("Touch model: ");
|
||||
USBSerial.println(touch.getModelName());
|
||||
touch.sleep();
|
||||
touch.reset();
|
||||
touch.setMaxCoordinates(480, 480);
|
||||
touch.setSwapXY(true);
|
||||
touch.setMirrorXY(true, false);
|
||||
attachInterrupt(
|
||||
TP_INT, []() {
|
||||
isPressed = true;
|
||||
},
|
||||
FALLING);
|
||||
|
||||
gfx->begin();
|
||||
gfx->setBrightness(200);
|
||||
bus->writeC8D8(0x36, 0xA0);
|
||||
|
||||
screenWidth = gfx->width();
|
||||
screenHeight = gfx->height();
|
||||
|
||||
lv_init();
|
||||
|
||||
buf1 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
buf2 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
|
||||
#if LV_USE_LOG != 0
|
||||
lv_log_register_print_cb(my_print);
|
||||
#endif
|
||||
|
||||
lv_disp_draw_buf_init(&draw_buf, buf1, buf2, screenWidth * screenHeight / 4);
|
||||
|
||||
static lv_disp_drv_t disp_drv;
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.hor_res = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.rounder_cb = example_lvgl_rounder_cb;
|
||||
disp_drv.draw_buf = &draw_buf;
|
||||
disp_drv.sw_rotate = 1;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
static lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = my_touchpad_read;
|
||||
lv_indev_drv_register(&indev_drv);
|
||||
|
||||
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);
|
||||
|
||||
create_ui();
|
||||
USBSerial.println("LVGL official based test ready");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
lv_timer_handler();
|
||||
delay(5);
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <lvgl.h>
|
||||
LV_FONT_DECLARE(lv_font_ru_18);
|
||||
LV_FONT_DECLARE(lv_font_ru_24);
|
||||
+1553
File diff suppressed because it is too large
Load Diff
+2048
File diff suppressed because it is too large
Load Diff
+264
@@ -0,0 +1,264 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <lvgl.h>
|
||||
#include <Arduino_GFX_Library.h>
|
||||
#include <TouchDrvCSTXXX.hpp>
|
||||
#include "lv_font_ru.h"
|
||||
|
||||
#define PIN_LCD_CS 12
|
||||
#define PIN_LCD_SCLK 38
|
||||
#define PIN_LCD_D0 4
|
||||
#define PIN_LCD_D1 5
|
||||
#define PIN_LCD_D2 6
|
||||
#define PIN_LCD_D3 7
|
||||
#define PIN_LCD_RST 2
|
||||
#define PIN_I2C_SDA 15
|
||||
#define PIN_I2C_SCL 14
|
||||
#define PIN_TP_INT 11
|
||||
|
||||
#define DISP_W 480
|
||||
#define DISP_H 480
|
||||
#define LVGL_TICK_MS 2
|
||||
#define TEST_VERSION "v1-ru-font"
|
||||
|
||||
static lv_disp_draw_buf_t gDrawBuf;
|
||||
static lv_color_t *gBuf1 = nullptr;
|
||||
static lv_color_t *gBuf2 = nullptr;
|
||||
static lv_obj_t *gStatusLabel = nullptr;
|
||||
static lv_obj_t *gTouchLabel = nullptr;
|
||||
static uint32_t gClickCount = 0;
|
||||
static bool gTouchActive = false;
|
||||
static int16_t gLastX = -1;
|
||||
static int16_t gLastY = -1;
|
||||
|
||||
Arduino_DataBus *gBus = new Arduino_ESP32QSPI(
|
||||
PIN_LCD_CS, PIN_LCD_SCLK, PIN_LCD_D0, PIN_LCD_D1, PIN_LCD_D2, PIN_LCD_D3);
|
||||
Arduino_CO5300 *gfx = new Arduino_CO5300(
|
||||
gBus, PIN_LCD_RST, 0, DISP_W, DISP_H, 0, 0, 0, 0);
|
||||
TouchDrvCST92xx gTouch;
|
||||
|
||||
static void lvglFlushCb(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *colorP) {
|
||||
uint32_t w = area->x2 - area->x1 + 1;
|
||||
uint32_t h = area->y2 - area->y1 + 1;
|
||||
#if (LV_COLOR_16_SWAP != 0)
|
||||
gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#else
|
||||
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#endif
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
||||
|
||||
static void lvglTick(void *arg) {
|
||||
LV_UNUSED(arg);
|
||||
lv_tick_inc(LVGL_TICK_MS);
|
||||
}
|
||||
|
||||
static void updateTouchLabel() {
|
||||
if (!gTouchLabel) {
|
||||
return;
|
||||
}
|
||||
|
||||
char text[96];
|
||||
if (gTouchActive) {
|
||||
snprintf(text, sizeof(text), "Касание: x=%d y=%d", gLastX, gLastY);
|
||||
} else {
|
||||
snprintf(text, sizeof(text), "Касание: нет x=%d y=%d", gLastX, gLastY);
|
||||
}
|
||||
lv_label_set_text(gTouchLabel, text);
|
||||
}
|
||||
|
||||
static void lvglTouchRead(lv_indev_drv_t *indevDrv, lv_indev_data_t *data) {
|
||||
LV_UNUSED(indevDrv);
|
||||
int16_t x = 0;
|
||||
int16_t y = 0;
|
||||
bool touching = gTouch.getPoint(&x, &y, 1) > 0;
|
||||
|
||||
if (touching) {
|
||||
gTouchActive = true;
|
||||
gLastX = x;
|
||||
gLastY = y;
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
data->point.x = x;
|
||||
data->point.y = y;
|
||||
} else {
|
||||
gTouchActive = false;
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
data->point.x = gLastX >= 0 ? gLastX : 0;
|
||||
data->point.y = gLastY >= 0 ? gLastY : 0;
|
||||
}
|
||||
|
||||
updateTouchLabel();
|
||||
}
|
||||
|
||||
static void buttonEventCb(lv_event_t *event) {
|
||||
if (lv_event_get_code(event) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = (const char *)lv_event_get_user_data(event);
|
||||
gClickCount++;
|
||||
|
||||
char text[128];
|
||||
snprintf(text, sizeof(text), "Нажато: %s (%lu)", name, (unsigned long)gClickCount);
|
||||
lv_label_set_text(gStatusLabel, text);
|
||||
Serial.println(text);
|
||||
}
|
||||
|
||||
static lv_obj_t *makeButton(lv_obj_t *parent,
|
||||
const char *labelText,
|
||||
lv_coord_t x,
|
||||
lv_coord_t y,
|
||||
lv_coord_t w,
|
||||
lv_coord_t h,
|
||||
uint32_t bgColor) {
|
||||
lv_obj_t *btn = lv_btn_create(parent);
|
||||
lv_obj_set_size(btn, w, h);
|
||||
lv_obj_set_pos(btn, x, y);
|
||||
lv_obj_set_style_radius(btn, 16, 0);
|
||||
lv_obj_set_style_bg_color(btn, lv_color_hex(bgColor), 0);
|
||||
lv_obj_set_style_bg_opa(btn, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(btn, 2, 0);
|
||||
lv_obj_set_style_border_color(btn, lv_color_hex(0x6F8BA4), 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, 0);
|
||||
lv_obj_set_style_pad_all(btn, 4, 0);
|
||||
lv_obj_add_event_cb(btn, buttonEventCb, LV_EVENT_CLICKED, (void *)labelText);
|
||||
|
||||
lv_obj_t *label = lv_label_create(btn);
|
||||
lv_label_set_text(label, labelText);
|
||||
lv_obj_set_width(label, w - 12);
|
||||
lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_set_style_text_font(label, &lv_font_ru_18, 0);
|
||||
lv_obj_center(label);
|
||||
return btn;
|
||||
}
|
||||
|
||||
static void createUi() {
|
||||
lv_obj_t *screen = lv_scr_act();
|
||||
lv_obj_set_style_bg_color(screen, lv_color_hex(0x08131E), 0);
|
||||
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_pad_all(screen, 0, 0);
|
||||
lv_obj_set_scrollbar_mode(screen, LV_SCROLLBAR_MODE_OFF);
|
||||
|
||||
lv_obj_t *title = lv_label_create(screen);
|
||||
lv_label_set_text(title, "Русский тест LVGL");
|
||||
lv_obj_set_style_text_font(title, &lv_font_ru_24, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 10);
|
||||
|
||||
lv_obj_t *version = lv_label_create(screen);
|
||||
lv_label_set_text(version, "Версия: " TEST_VERSION);
|
||||
lv_obj_set_style_text_font(version, &lv_font_ru_18, 0);
|
||||
lv_obj_set_style_text_color(version, lv_color_hex(0xD8E0EA), 0);
|
||||
lv_obj_align(version, LV_ALIGN_TOP_MID, 0, 42);
|
||||
|
||||
lv_obj_t *hint = lv_label_create(screen);
|
||||
lv_label_set_text(hint, "Проверка кириллицы, длинных слов, кнопок и нажатий.");
|
||||
lv_obj_set_width(hint, 436);
|
||||
lv_label_set_long_mode(hint, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_font(hint, &lv_font_ru_18, 0);
|
||||
lv_obj_set_style_text_color(hint, lv_color_hex(0xD8E0EA), 0);
|
||||
lv_obj_align(hint, LV_ALIGN_TOP_MID, 0, 72);
|
||||
|
||||
makeButton(screen, "Статус", 22, 126, 136, 62, 0x355C7D);
|
||||
makeButton(screen, "Подключение", 172, 126, 136, 62, 0x2A9D8F);
|
||||
makeButton(screen, "Кошелёк", 322, 126, 136, 62, 0x457B9D);
|
||||
|
||||
makeButton(screen, "Запросы", 22, 204, 136, 62, 0xE76F51);
|
||||
makeButton(screen, "Настройки", 172, 204, 136, 62, 0x8D5A97);
|
||||
makeButton(screen, "Регистрация", 322, 204, 136, 62, 0x6A994E);
|
||||
|
||||
makeButton(screen, "Разрешить", 22, 282, 136, 62, 0xBC6C25);
|
||||
makeButton(screen, "Отклонить", 172, 282, 136, 62, 0xB56576);
|
||||
makeButton(screen, "Назад", 322, 282, 136, 62, 0x6C757D);
|
||||
|
||||
makeButton(screen, "Проверка переноса русского текста", 22, 360, 436, 64, 0x1D6F42);
|
||||
|
||||
lv_obj_t *statusPanel = lv_obj_create(screen);
|
||||
lv_obj_set_size(statusPanel, 436, 24);
|
||||
lv_obj_set_pos(statusPanel, 22, 428);
|
||||
lv_obj_set_style_radius(statusPanel, 10, 0);
|
||||
lv_obj_set_style_bg_color(statusPanel, lv_color_hex(0x162435), 0);
|
||||
lv_obj_set_style_bg_opa(statusPanel, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(statusPanel, 1, 0);
|
||||
lv_obj_set_style_border_color(statusPanel, lv_color_hex(0x4D6986), 0);
|
||||
lv_obj_set_style_pad_all(statusPanel, 2, 0);
|
||||
|
||||
gStatusLabel = lv_label_create(statusPanel);
|
||||
lv_label_set_text(gStatusLabel, "Нажато: ничего");
|
||||
lv_obj_set_style_text_font(gStatusLabel, &lv_font_ru_18, 0);
|
||||
lv_obj_set_style_text_color(gStatusLabel, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_center(gStatusLabel);
|
||||
|
||||
lv_obj_t *touchPanel = lv_obj_create(screen);
|
||||
lv_obj_set_size(touchPanel, 436, 24);
|
||||
lv_obj_set_pos(touchPanel, 22, 454);
|
||||
lv_obj_set_style_radius(touchPanel, 10, 0);
|
||||
lv_obj_set_style_bg_color(touchPanel, lv_color_hex(0x162435), 0);
|
||||
lv_obj_set_style_bg_opa(touchPanel, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(touchPanel, 1, 0);
|
||||
lv_obj_set_style_border_color(touchPanel, lv_color_hex(0x4D6986), 0);
|
||||
lv_obj_set_style_pad_all(touchPanel, 2, 0);
|
||||
|
||||
gTouchLabel = lv_label_create(touchPanel);
|
||||
lv_label_set_text(gTouchLabel, "Касание: нет x=-1 y=-1");
|
||||
lv_obj_set_style_text_font(gTouchLabel, &lv_font_ru_18, 0);
|
||||
lv_obj_set_style_text_color(gTouchLabel, lv_color_hex(0xD8E0EA), 0);
|
||||
lv_obj_center(gTouchLabel);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL);
|
||||
|
||||
gfx->begin();
|
||||
gBus->writeC8D8(0x36, 0xA0);
|
||||
gfx->setBrightness(220);
|
||||
gfx->fillScreen(0x0000);
|
||||
|
||||
gTouch.setPins(PIN_TP_INT, -1);
|
||||
gTouch.begin(Wire, CST92XX_SLAVE_ADDRESS, PIN_I2C_SDA, PIN_I2C_SCL);
|
||||
gTouch.setMaxCoordinates(DISP_W, DISP_H);
|
||||
gTouch.setSwapXY(true);
|
||||
gTouch.setMirrorXY(true, false);
|
||||
|
||||
lv_init();
|
||||
|
||||
uint32_t screenWidth = gfx->width();
|
||||
uint32_t screenHeight = gfx->height();
|
||||
uint32_t bufPixels = screenWidth * 40;
|
||||
gBuf1 = (lv_color_t *)heap_caps_malloc(bufPixels * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
gBuf2 = (lv_color_t *)heap_caps_malloc(bufPixels * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
|
||||
lv_disp_draw_buf_init(&gDrawBuf, gBuf1, gBuf2, bufPixels);
|
||||
|
||||
static lv_disp_drv_t dispDrv;
|
||||
lv_disp_drv_init(&dispDrv);
|
||||
dispDrv.hor_res = screenWidth;
|
||||
dispDrv.ver_res = screenHeight;
|
||||
dispDrv.flush_cb = lvglFlushCb;
|
||||
dispDrv.draw_buf = &gDrawBuf;
|
||||
lv_disp_drv_register(&dispDrv);
|
||||
|
||||
static lv_indev_drv_t indevDrv;
|
||||
lv_indev_drv_init(&indevDrv);
|
||||
indevDrv.type = LV_INDEV_TYPE_POINTER;
|
||||
indevDrv.read_cb = lvglTouchRead;
|
||||
lv_indev_drv_register(&indevDrv);
|
||||
|
||||
const esp_timer_create_args_t tickArgs = {
|
||||
.callback = &lvglTick,
|
||||
.name = "lvgl_tick"};
|
||||
esp_timer_handle_t tickTimer = nullptr;
|
||||
esp_timer_create(&tickArgs, &tickTimer);
|
||||
esp_timer_start_periodic(tickTimer, LVGL_TICK_MS * 1000);
|
||||
|
||||
createUi();
|
||||
Serial.println("Русский LVGL font test ready: " TEST_VERSION);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
lv_timer_handler();
|
||||
delay(5);
|
||||
}
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <lvgl.h>
|
||||
#include <Arduino_GFX_Library.h>
|
||||
#include <TouchDrvCSTXXX.hpp>
|
||||
|
||||
// Подтверждено на устройстве: LVGL-рендер работает вместе с touch-путём из shine_homeserver_ui.
|
||||
|
||||
#define PIN_LCD_CS 12
|
||||
#define PIN_LCD_SCLK 38
|
||||
#define PIN_LCD_D0 4
|
||||
#define PIN_LCD_D1 5
|
||||
#define PIN_LCD_D2 6
|
||||
#define PIN_LCD_D3 7
|
||||
#define PIN_LCD_RST 2
|
||||
#define PIN_I2C_SDA 15
|
||||
#define PIN_I2C_SCL 14
|
||||
#define PIN_TP_INT 11
|
||||
|
||||
#define DISP_W 480
|
||||
#define DISP_H 480
|
||||
#define LVGL_TICK_MS 2
|
||||
#define TEST_VERSION "v1-subtouch"
|
||||
|
||||
static lv_disp_draw_buf_t gDrawBuf;
|
||||
static lv_color_t *gBuf1 = nullptr;
|
||||
static lv_color_t *gBuf2 = nullptr;
|
||||
static lv_obj_t *gStatusLabel = nullptr;
|
||||
static lv_obj_t *gTouchLabel = nullptr;
|
||||
static lv_obj_t *gVersionLabel = nullptr;
|
||||
static uint32_t gClickCount = 0;
|
||||
static bool gTouchActive = false;
|
||||
static int16_t gLastX = -1;
|
||||
static int16_t gLastY = -1;
|
||||
|
||||
Arduino_DataBus *gBus = new Arduino_ESP32QSPI(
|
||||
PIN_LCD_CS, PIN_LCD_SCLK, PIN_LCD_D0, PIN_LCD_D1, PIN_LCD_D2, PIN_LCD_D3);
|
||||
Arduino_CO5300 *gfx = new Arduino_CO5300(
|
||||
gBus, PIN_LCD_RST, 0, DISP_W, DISP_H, 0, 0, 0, 0);
|
||||
TouchDrvCST92xx gTouch;
|
||||
|
||||
static void lvglFlushCb(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *colorP) {
|
||||
uint32_t w = area->x2 - area->x1 + 1;
|
||||
uint32_t h = area->y2 - area->y1 + 1;
|
||||
#if (LV_COLOR_16_SWAP != 0)
|
||||
gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#else
|
||||
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#endif
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
||||
|
||||
static void lvglTick(void *arg) {
|
||||
LV_UNUSED(arg);
|
||||
lv_tick_inc(LVGL_TICK_MS);
|
||||
}
|
||||
|
||||
static void updateTouchLabel() {
|
||||
if (!gTouchLabel) {
|
||||
return;
|
||||
}
|
||||
|
||||
char text[96];
|
||||
if (gTouchActive) {
|
||||
snprintf(text, sizeof(text), "Touch: pressed x=%d y=%d", gLastX, gLastY);
|
||||
} else {
|
||||
snprintf(text, sizeof(text), "Touch: released x=%d y=%d", gLastX, gLastY);
|
||||
}
|
||||
lv_label_set_text(gTouchLabel, text);
|
||||
}
|
||||
|
||||
static void lvglTouchRead(lv_indev_drv_t *indevDrv, lv_indev_data_t *data) {
|
||||
LV_UNUSED(indevDrv);
|
||||
int16_t x = 0;
|
||||
int16_t y = 0;
|
||||
bool touching = gTouch.getPoint(&x, &y, 1) > 0;
|
||||
|
||||
if (touching) {
|
||||
gTouchActive = true;
|
||||
gLastX = x;
|
||||
gLastY = y;
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
data->point.x = x;
|
||||
data->point.y = y;
|
||||
} else {
|
||||
gTouchActive = false;
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
data->point.x = gLastX >= 0 ? gLastX : 0;
|
||||
data->point.y = gLastY >= 0 ? gLastY : 0;
|
||||
}
|
||||
|
||||
updateTouchLabel();
|
||||
}
|
||||
|
||||
static void buttonEventCb(lv_event_t *event) {
|
||||
if (lv_event_get_code(event) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = (const char *)lv_event_get_user_data(event);
|
||||
gClickCount++;
|
||||
|
||||
char text[96];
|
||||
snprintf(text, sizeof(text), "Pressed: %s (#%lu)", name, (unsigned long)gClickCount);
|
||||
lv_label_set_text(gStatusLabel, text);
|
||||
Serial.println(text);
|
||||
}
|
||||
|
||||
static lv_obj_t *makeButton(lv_obj_t *parent,
|
||||
const char *labelText,
|
||||
lv_coord_t x,
|
||||
lv_coord_t y,
|
||||
lv_coord_t w,
|
||||
lv_coord_t h,
|
||||
uint32_t bgColor) {
|
||||
lv_obj_t *btn = lv_btn_create(parent);
|
||||
lv_obj_set_size(btn, w, h);
|
||||
lv_obj_set_pos(btn, x, y);
|
||||
lv_obj_set_style_radius(btn, 16, 0);
|
||||
lv_obj_set_style_bg_color(btn, lv_color_hex(bgColor), 0);
|
||||
lv_obj_set_style_bg_opa(btn, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(btn, 2, 0);
|
||||
lv_obj_set_style_border_color(btn, lv_color_hex(0x6F8BA4), 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, 0);
|
||||
lv_obj_add_event_cb(btn, buttonEventCb, LV_EVENT_CLICKED, (void *)labelText);
|
||||
|
||||
lv_obj_t *label = lv_label_create(btn);
|
||||
lv_label_set_text(label, labelText);
|
||||
lv_obj_set_style_text_color(label, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_set_style_text_font(label, &lv_font_montserrat_18, 0);
|
||||
lv_obj_center(label);
|
||||
return btn;
|
||||
}
|
||||
|
||||
static void createUi() {
|
||||
lv_obj_t *screen = lv_scr_act();
|
||||
lv_obj_set_style_bg_color(screen, lv_color_hex(0x07111C), 0);
|
||||
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_pad_all(screen, 0, 0);
|
||||
lv_obj_set_scrollbar_mode(screen, LV_SCROLLBAR_MODE_OFF);
|
||||
|
||||
gVersionLabel = lv_label_create(screen);
|
||||
lv_label_set_text(gVersionLabel, "LVGL + subserver touch " TEST_VERSION);
|
||||
lv_obj_set_style_text_font(gVersionLabel, &lv_font_montserrat_18, 0);
|
||||
lv_obj_set_style_text_color(gVersionLabel, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_align(gVersionLabel, LV_ALIGN_TOP_MID, 0, 12);
|
||||
|
||||
lv_obj_t *subtitle = lv_label_create(screen);
|
||||
lv_label_set_text(subtitle, "Touch path comes from shine_homeserver_ui. Tap buttons and watch status.");
|
||||
lv_obj_set_width(subtitle, 436);
|
||||
lv_label_set_long_mode(subtitle, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_font(subtitle, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(subtitle, lv_color_hex(0xD6DEE7), 0);
|
||||
lv_obj_align(subtitle, LV_ALIGN_TOP_MID, 0, 42);
|
||||
|
||||
makeButton(screen, "Status", 22, 110, 136, 62, 0x355C7D);
|
||||
makeButton(screen, "Connect", 172, 110, 136, 62, 0x2A9D8F);
|
||||
makeButton(screen, "Wallet", 322, 110, 136, 62, 0x457B9D);
|
||||
|
||||
makeButton(screen, "Requests", 22, 188, 136, 62, 0xE76F51);
|
||||
makeButton(screen, "Settings", 172, 188, 136, 62, 0x8D5A97);
|
||||
makeButton(screen, "Register", 322, 188, 136, 62, 0x6A994E);
|
||||
|
||||
makeButton(screen, "Approve", 22, 266, 136, 62, 0xBC6C25);
|
||||
makeButton(screen, "Reject", 172, 266, 136, 62, 0xB56576);
|
||||
makeButton(screen, "Back", 322, 266, 136, 62, 0x6C757D);
|
||||
|
||||
makeButton(screen, "Bottom Action", 22, 346, 436, 68, 0x1D6F42);
|
||||
|
||||
lv_obj_t *statusPanel = lv_obj_create(screen);
|
||||
lv_obj_set_size(statusPanel, 436, 26);
|
||||
lv_obj_set_pos(statusPanel, 22, 420);
|
||||
lv_obj_set_style_radius(statusPanel, 10, 0);
|
||||
lv_obj_set_style_bg_color(statusPanel, lv_color_hex(0x162435), 0);
|
||||
lv_obj_set_style_bg_opa(statusPanel, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(statusPanel, 1, 0);
|
||||
lv_obj_set_style_border_color(statusPanel, lv_color_hex(0x4D6986), 0);
|
||||
lv_obj_set_style_pad_all(statusPanel, 2, 0);
|
||||
|
||||
gStatusLabel = lv_label_create(statusPanel);
|
||||
lv_label_set_text(gStatusLabel, "Pressed: none");
|
||||
lv_obj_set_style_text_font(gStatusLabel, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(gStatusLabel, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_center(gStatusLabel);
|
||||
|
||||
lv_obj_t *touchPanel = lv_obj_create(screen);
|
||||
lv_obj_set_size(touchPanel, 436, 26);
|
||||
lv_obj_set_pos(touchPanel, 22, 450);
|
||||
lv_obj_set_style_radius(touchPanel, 10, 0);
|
||||
lv_obj_set_style_bg_color(touchPanel, lv_color_hex(0x162435), 0);
|
||||
lv_obj_set_style_bg_opa(touchPanel, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(touchPanel, 1, 0);
|
||||
lv_obj_set_style_border_color(touchPanel, lv_color_hex(0x4D6986), 0);
|
||||
lv_obj_set_style_pad_all(touchPanel, 2, 0);
|
||||
|
||||
gTouchLabel = lv_label_create(touchPanel);
|
||||
lv_label_set_text(gTouchLabel, "Touch: released x=-1 y=-1");
|
||||
lv_obj_set_style_text_font(gTouchLabel, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(gTouchLabel, lv_color_hex(0xD6DEE7), 0);
|
||||
lv_obj_center(gTouchLabel);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL);
|
||||
|
||||
gfx->begin();
|
||||
gBus->writeC8D8(0x36, 0xA0);
|
||||
gfx->setBrightness(220);
|
||||
gfx->fillScreen(0x0000);
|
||||
|
||||
gTouch.setPins(PIN_TP_INT, -1);
|
||||
gTouch.begin(Wire, CST92XX_SLAVE_ADDRESS, PIN_I2C_SDA, PIN_I2C_SCL);
|
||||
gTouch.setMaxCoordinates(DISP_W, DISP_H);
|
||||
gTouch.setSwapXY(true);
|
||||
gTouch.setMirrorXY(true, false);
|
||||
|
||||
lv_init();
|
||||
|
||||
uint32_t screenWidth = gfx->width();
|
||||
uint32_t screenHeight = gfx->height();
|
||||
uint32_t bufPixels = screenWidth * 40;
|
||||
gBuf1 = (lv_color_t *)heap_caps_malloc(bufPixels * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
gBuf2 = (lv_color_t *)heap_caps_malloc(bufPixels * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
|
||||
lv_disp_draw_buf_init(&gDrawBuf, gBuf1, gBuf2, bufPixels);
|
||||
|
||||
static lv_disp_drv_t dispDrv;
|
||||
lv_disp_drv_init(&dispDrv);
|
||||
dispDrv.hor_res = screenWidth;
|
||||
dispDrv.ver_res = screenHeight;
|
||||
dispDrv.flush_cb = lvglFlushCb;
|
||||
dispDrv.draw_buf = &gDrawBuf;
|
||||
lv_disp_drv_register(&dispDrv);
|
||||
|
||||
static lv_indev_drv_t indevDrv;
|
||||
lv_indev_drv_init(&indevDrv);
|
||||
indevDrv.type = LV_INDEV_TYPE_POINTER;
|
||||
indevDrv.read_cb = lvglTouchRead;
|
||||
lv_indev_drv_register(&indevDrv);
|
||||
|
||||
const esp_timer_create_args_t tickArgs = {
|
||||
.callback = &lvglTick,
|
||||
.name = "lvgl_tick"};
|
||||
esp_timer_handle_t tickTimer = nullptr;
|
||||
esp_timer_create(&tickArgs, &tickTimer);
|
||||
esp_timer_start_periodic(tickTimer, LVGL_TICK_MS * 1000);
|
||||
|
||||
createUi();
|
||||
Serial.println("LVGL + subserver touch test ready: " TEST_VERSION);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
lv_timer_handler();
|
||||
delay(5);
|
||||
}
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <lvgl.h>
|
||||
#include <Arduino_GFX_Library.h>
|
||||
#include "pin_config.h"
|
||||
#include "TouchDrvCSTXXX.hpp"
|
||||
|
||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||
|
||||
static lv_disp_draw_buf_t gDrawBuf;
|
||||
static lv_color_t *gBuf1 = nullptr;
|
||||
static lv_color_t *gBuf2 = nullptr;
|
||||
static lv_obj_t *gRawLabel = nullptr;
|
||||
static lv_obj_t *gEventLabel = nullptr;
|
||||
static lv_obj_t *gMarker = nullptr;
|
||||
|
||||
static TouchDrvCST92xx gTouch;
|
||||
static int16_t gTouchX[5];
|
||||
static int16_t gTouchY[5];
|
||||
static bool gTouchPressed = false;
|
||||
static uint32_t gRawTouchCount = 0;
|
||||
static uint32_t gLvglButtonCount = 0;
|
||||
|
||||
Arduino_DataBus *gBus = new Arduino_ESP32QSPI(
|
||||
LCD_CS, LCD_SCLK, LCD_SDIO0, LCD_SDIO1, LCD_SDIO2, LCD_SDIO3);
|
||||
Arduino_CO5300 *gfx = new Arduino_CO5300(
|
||||
gBus, LCD_RESET, 0, LCD_WIDTH, LCD_HEIGHT, 0, 0, 0, 0);
|
||||
|
||||
static void lvglFlushCb(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *colorP) {
|
||||
uint32_t w = area->x2 - area->x1 + 1;
|
||||
uint32_t h = area->y2 - area->y1 + 1;
|
||||
#if (LV_COLOR_16_SWAP != 0)
|
||||
gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#else
|
||||
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&colorP->full, w, h);
|
||||
#endif
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
||||
|
||||
static void lvglTick(void *arg) {
|
||||
LV_UNUSED(arg);
|
||||
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static void lvglTouchRead(lv_indev_drv_t *indevDrv, lv_indev_data_t *data) {
|
||||
LV_UNUSED(indevDrv);
|
||||
uint8_t touched = gTouch.getPoint(gTouchX, gTouchY, gTouch.getSupportTouchPoint());
|
||||
if (touched > 0) {
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
data->point.x = gTouchX[0];
|
||||
data->point.y = gTouchY[0];
|
||||
return;
|
||||
}
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
}
|
||||
|
||||
static void bigButtonEventCb(lv_event_t *event) {
|
||||
if (lv_event_get_code(event) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
gLvglButtonCount++;
|
||||
String status = "LVGL button clicked: ";
|
||||
status += String(gLvglButtonCount);
|
||||
lv_label_set_text(gEventLabel, status.c_str());
|
||||
Serial.println(status);
|
||||
}
|
||||
|
||||
static void updateRawTouchState() {
|
||||
uint8_t touched = gTouch.getPoint(gTouchX, gTouchY, gTouch.getSupportTouchPoint());
|
||||
if (touched > 0) {
|
||||
gTouchPressed = true;
|
||||
gRawTouchCount++;
|
||||
|
||||
String line1 = "RAW pressed";
|
||||
String line2 = "x=" + String(gTouchX[0]) + " y=" + String(gTouchY[0]) + " n=" + String(gRawTouchCount);
|
||||
String text = line1 + "\n" + line2;
|
||||
lv_label_set_text(gRawLabel, text.c_str());
|
||||
|
||||
int markerX = gTouchX[0] - 8;
|
||||
int markerY = gTouchY[0] - 8;
|
||||
if (markerX < 0) markerX = 0;
|
||||
if (markerY < 0) markerY = 0;
|
||||
lv_obj_set_pos(gMarker, markerX, markerY);
|
||||
lv_obj_clear_flag(gMarker, LV_OBJ_FLAG_HIDDEN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gTouchPressed) {
|
||||
gTouchPressed = false;
|
||||
lv_label_set_text(gRawLabel, "RAW released\nTouch ended");
|
||||
lv_obj_add_flag(gMarker, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
static void createUi() {
|
||||
lv_obj_t *screen = lv_scr_act();
|
||||
lv_obj_set_style_bg_color(screen, lv_color_hex(0x000000), 0);
|
||||
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0);
|
||||
|
||||
lv_obj_t *title = lv_label_create(screen);
|
||||
lv_label_set_text(title, "LVGL TOUCH DEBUG");
|
||||
lv_obj_set_style_text_font(title, &lv_font_montserrat_22, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 12);
|
||||
|
||||
gRawLabel = lv_label_create(screen);
|
||||
lv_label_set_text(gRawLabel, "RAW released\nTouch not seen yet");
|
||||
lv_obj_set_style_text_font(gRawLabel, &lv_font_montserrat_18, 0);
|
||||
lv_obj_set_style_text_color(gRawLabel, lv_color_hex(0x9EE493), 0);
|
||||
lv_obj_align(gRawLabel, LV_ALIGN_TOP_LEFT, 16, 56);
|
||||
|
||||
gEventLabel = lv_label_create(screen);
|
||||
lv_label_set_text(gEventLabel, "LVGL button clicked: 0");
|
||||
lv_obj_set_style_text_font(gEventLabel, &lv_font_montserrat_18, 0);
|
||||
lv_obj_set_style_text_color(gEventLabel, lv_color_hex(0xFFD166), 0);
|
||||
lv_obj_align(gEventLabel, LV_ALIGN_TOP_LEFT, 16, 118);
|
||||
|
||||
lv_obj_t *btn = lv_btn_create(screen);
|
||||
lv_obj_set_size(btn, 360, 110);
|
||||
lv_obj_align(btn, LV_ALIGN_CENTER, 0, 36);
|
||||
lv_obj_set_style_radius(btn, 18, 0);
|
||||
lv_obj_set_style_bg_color(btn, lv_color_hex(0x2A9D8F), 0);
|
||||
lv_obj_set_style_border_width(btn, 3, 0);
|
||||
lv_obj_set_style_border_color(btn, lv_color_hex(0xBDE0FE), 0);
|
||||
lv_obj_add_event_cb(btn, bigButtonEventCb, LV_EVENT_CLICKED, nullptr);
|
||||
|
||||
lv_obj_t *btnLabel = lv_label_create(btn);
|
||||
lv_label_set_text(btnLabel, "Tap Here");
|
||||
lv_obj_set_style_text_font(btnLabel, &lv_font_montserrat_24, 0);
|
||||
lv_obj_set_style_text_color(btnLabel, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_center(btnLabel);
|
||||
|
||||
lv_obj_t *hint = lv_label_create(screen);
|
||||
lv_label_set_text(hint, "Need both: RAW coords change and LVGL button click.");
|
||||
lv_obj_set_width(hint, 430);
|
||||
lv_label_set_long_mode(hint, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_font(hint, &lv_font_montserrat_16, 0);
|
||||
lv_obj_set_style_text_color(hint, lv_color_hex(0xD9D9D9), 0);
|
||||
lv_obj_align(hint, LV_ALIGN_BOTTOM_MID, 0, -34);
|
||||
|
||||
gMarker = lv_obj_create(screen);
|
||||
lv_obj_set_size(gMarker, 16, 16);
|
||||
lv_obj_set_style_radius(gMarker, LV_RADIUS_CIRCLE, 0);
|
||||
lv_obj_set_style_bg_color(gMarker, lv_color_hex(0xFF4D6D), 0);
|
||||
lv_obj_set_style_border_width(gMarker, 2, 0);
|
||||
lv_obj_set_style_border_color(gMarker, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_add_flag(gMarker, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin(IIC_SDA, IIC_SCL);
|
||||
|
||||
pinMode(TP_RST, OUTPUT);
|
||||
pinMode(TP_INT, INPUT);
|
||||
digitalWrite(TP_RST, LOW);
|
||||
delay(30);
|
||||
digitalWrite(TP_RST, HIGH);
|
||||
delay(50);
|
||||
delay(1000);
|
||||
|
||||
gTouch.setPins(TP_RST, TP_INT);
|
||||
bool touchOk = gTouch.begin(Wire, 0x5A, IIC_SDA, IIC_SCL);
|
||||
if (!touchOk) {
|
||||
Serial.println("Touch init failed");
|
||||
} else {
|
||||
Serial.print("Touch model: ");
|
||||
Serial.println(gTouch.getModelName());
|
||||
gTouch.sleep();
|
||||
gTouch.reset();
|
||||
gTouch.setMaxCoordinates(480, 480);
|
||||
gTouch.setSwapXY(true);
|
||||
gTouch.setMirrorXY(true, false);
|
||||
}
|
||||
|
||||
gfx->begin();
|
||||
gBus->writeC8D8(0x36, 0xA0);
|
||||
gfx->setBrightness(220);
|
||||
gfx->fillScreen(0x0000);
|
||||
|
||||
lv_init();
|
||||
|
||||
uint32_t screenWidth = gfx->width();
|
||||
uint32_t screenHeight = gfx->height();
|
||||
gBuf1 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
gBuf2 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
lv_disp_draw_buf_init(&gDrawBuf, gBuf1, gBuf2, screenWidth * screenHeight / 4);
|
||||
|
||||
static lv_disp_drv_t dispDrv;
|
||||
lv_disp_drv_init(&dispDrv);
|
||||
dispDrv.hor_res = screenWidth;
|
||||
dispDrv.ver_res = screenHeight;
|
||||
dispDrv.flush_cb = lvglFlushCb;
|
||||
dispDrv.draw_buf = &gDrawBuf;
|
||||
lv_disp_drv_register(&dispDrv);
|
||||
|
||||
static lv_indev_drv_t indevDrv;
|
||||
lv_indev_drv_init(&indevDrv);
|
||||
indevDrv.type = LV_INDEV_TYPE_POINTER;
|
||||
indevDrv.read_cb = lvglTouchRead;
|
||||
lv_indev_drv_register(&indevDrv);
|
||||
|
||||
const esp_timer_create_args_t lvglTickTimerArgs = {
|
||||
.callback = &lvglTick,
|
||||
.name = "lvgl_tick"};
|
||||
esp_timer_handle_t lvglTickTimer = nullptr;
|
||||
esp_timer_create(&lvglTickTimerArgs, &lvglTickTimer);
|
||||
esp_timer_start_periodic(lvglTickTimer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000);
|
||||
|
||||
createUi();
|
||||
Serial.println("LVGL touch debug test ready");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
updateRawTouchState();
|
||||
lv_timer_handler();
|
||||
delay(5);
|
||||
}
|
||||
Reference in New Issue
Block a user