Как собрать библиотеку, настроить её, прогнать desktop simulator и вывести первый экран.
Исходный контент этой страницы берётся напрямую из API.md: требования к сборке, build-time флаги, desktop simulator, инициализация, подсветка и логотип.
Этот файл описывает актуальный публичный API PipGUI и PipCore, который есть в коде проекта.
Требования к компиляции (PlatformIO)
PipKit использует C++17. Для PlatformIO добавьте в platformio.ini:
build_unflags =
-std=gnu++11
build_flags =
-std=gnu++17
1. Build-time флаги
Низкий слой PipCore выбирает платформу, драйвер дисплея и optional backend-модули на этапе компиляции. Эти флаги задаются в include/config.hpp.
PIPCORE_DISPLAY- пример:
#define PIPCORE_DISPLAY ST7789 - поддерживаемые дисплеи:
ST7789,ILI9488,SIMULATOR PIPCORE_PLATFORM- пример:
#define PIPCORE_PLATFORM ESP32 - поддерживаемые платформы:
ESP32,DESKTOP PIPCORE_ENABLE_PREFS0или1PIPCORE_ENABLE_WIFI0или1PIPCORE_ENABLE_OTA0или1PIPCORE_OTA_PROJECT_URL- базовый OTA URL для core-level OTA backend
Пример через include/config.hpp:
#define PIPCORE_PLATFORM ESP32
#define PIPCORE_DISPLAY ST7789
#define PIPCORE_ENABLE_PREFS 1
#define PIPCORE_ENABLE_WIFI 1
#define PIPCORE_ENABLE_OTA 1
#define PIPCORE_OTA_PROJECT_URL "https://example.com/fw/PipGUI"
Пример для ILI9488:
#define PIPCORE_PLATFORM ESP32
#define PIPCORE_DISPLAY ILI9488
#define PIPCORE_ENABLE_PREFS 1
#define PIPCORE_ENABLE_WIFI 1
#define PIPCORE_ENABLE_OTA 1
#define PIPCORE_OTA_PROJECT_URL "https://example.com/fw/PipGUI"
Что важно:
- по умолчанию optional-модули
PipCoreвыключены - если внешний код использует
pipcore::net::*приPIPCORE_ENABLE_WIFI=0, сборка падает на этапе компиляции - если внешний код использует
pipcore::ota::*приPIPCORE_ENABLE_OTA=0, сборка тоже падает на этапе компиляции - это намеренное поведение: выключенный модуль нельзя использовать "молча"
PIPGUI_*иPIPCORE_*это разные слои конфигурации: GUI и Core соответственно- если
PipGUIреально использует Wi-Fi / OTA, соответствующиеPIPCORE_ENABLE_*тоже должны быть включены явно
2. Desktop simulator
Симулятор нужен для локального прогона GUI на Windows без ESP32 и физического дисплея. Он собирает проект в desktop-конфигурации и подменяет platform/display layer на DESKTOP + SIMULATOR.
Запуск:
powershell -ExecutionPolicy Bypass -File .\tools\sim-run.ps1
Полезные варианты:
powershell -ExecutionPolicy Bypass -File .\tools\sim-run.ps1 -Debug
powershell -ExecutionPolicy Bypass -File .\tools\sim-run.ps1 -NoRun
Что делает script:
- собирает native desktop-версию в
.sim/ - по умолчанию сразу запускает
pipgui-sim.exe - при
-Debugсобирает debug-вариантpipgui-sim-debug.exe - при
-NoRunтолько собирает exe без запуска - если симулятор уже запущен, script сначала останавливает прошлый процесс и потом пересобирает новый
Что важно по окружению:
- сейчас simulator-tooling рассчитан на Windows
- нужен установленный Visual Studio C++ toolchain (
Desktop development with C++) - для simulator build
PipCoreсначала пытается подключитьconfig_sim.hpp, а если его нет, использует обычныйconfig.hpp - host-обвязка simulator-а живёт внутри
PipCore/Host/Desktop/
2.1. Build-time флаги simulator
PIPGUI_SIM_SCALE- масштаб окна simulator относительно логического framebuffer
- по умолчанию
1 PIPGUI_SIM_DEFAULT_WIDTH- fallback-ширина simulator display, если проект не вызвал
configDisplay().size(...) - по умолчанию
320 PIPGUI_SIM_DEFAULT_HEIGHT- fallback-высота simulator display, если проект не вызвал
configDisplay().size(...) - по умолчанию
240 PIPGUI_SIM_BTN_PREV_PIN- какой virtual pin считать кнопкой
Prev - по умолчанию
4 PIPGUI_SIM_BTN_NEXT_PIN- какой virtual pin считать кнопкой
Next - по умолчанию
20 PIPGUI_SIM_BTN_SELECT_PIN- какой virtual pin считать кнопкой
Select - по умолчанию
21
Пример:
#define PIPCORE_PLATFORM DESKTOP
#define PIPCORE_DISPLAY SIMULATOR
#define PIPGUI_SIM_SCALE 2
#define PIPGUI_SIM_DEFAULT_WIDTH 320
#define PIPGUI_SIM_DEFAULT_HEIGHT 240
#define PIPGUI_SIM_BTN_PREV_PIN 4
#define PIPGUI_SIM_BTN_NEXT_PIN 20
#define PIPGUI_SIM_BTN_SELECT_PIN 21
2.2. Управление в окне simulator
LeftилиA- кнопкаPrevRightилиD- кнопкаNextEnterилиSpace- кнопкаSelectF1- перезапуск simulator-процессаF2- сохранить PNG-скриншот в.sim/shots/F3- начать/остановить запись видео в.sim/videos/- клавиши
0..3отправляются в serial input simulator-а как обычные символы
Ограничения и отличия от железа:
- это desktop runtime, а не cycle-accurate эмулятор ESP32
- timing, ввод и системные backend-ы могут отличаться от реального устройства
- screenshot/video hotkeys simulator-а работают отдельно от встроенной screenshot-системы
PipGUI - в simulator config по умолчанию выключены
PIPGUI_WIFI,PIPGUI_OTAи built-in screenshots, даже если core-level backend оставлен включённым для совместимости сборки
2.3. Структура host-layer
Desktop simulator сейчас состоит из трёх частей:
PipCore/Platforms/Desktop- desktop platform/runtime backendPipCore/Displays/Simulator- display driver, который рисует framebuffer в desktop runtimePipCore/Host/Desktop- host-обвязка для запуска Arduino-style app на ПК
Что лежит в PipCore/Host/Desktop:
include/Compat.hpp- основной desktop compat-layer для Arduino-style API (String,Serial,millis(),delay()и т.д.)include/Arduino.h- тонкий wrapper для совместимости с обычным#include <Arduino.h>src/Globals.cpp- desktop-глобалы compat-layer (Serial,ESP)src/Runner.cpp- desktop entrypoint, который вызываетsetup()и потом крутитloop()
2.4. Что нужно проекту для симуляции
Если проект пишет графику через PipCore / PipGUI, для simulator обычно достаточно следующего:
config_sim.hpp, где выбраныPIPCORE_PLATFORM DESKTOPиPIPCORE_DISPLAY SIMULATOR- host include path, чтобы компилятор видел
PipCore/Host/Desktopcompat-layer - desktop build script или CMake, который собирает:
- код
PipCore - код самого проекта
PipCore/Host/Desktop/src/Runner.cppPipCore/Host/Desktop/src/Globals.cpp
Что важно:
- если UI-код опирается только на
PipCore/PipGUI, этого достаточно для графической симуляции - если проект использует прямые ESP32-only вызовы, для них всё равно нужны desktop stub/compat-реализации или абстракция через
PipCore
3. Инициализация
3.1. Конфигурация дисплея
Полный пример:
ui.configDisplay()
.pins(11, 12, 10, 9, -1) // mosi, sclk, cs, dc, rst
.size(240, 320) // width, height
.hz(80000000) // частота SPI
.order("RGB") // "RGB" или "BGR"
.invert(true) // инверсия панели
.swap(false) // swap байтов RGB565
.offset(0, 0); // смещение активной области
Минимальный пример:
ui.configDisplay()
.pins(11, 12, 10, 9, -1)
.size(240, 320);
Можно не писать и оставить display-specific дефолты core/drivers:
hz(freq):ST7789по умолчанию80000000ILI9488по умолчанию60000000order("RGB"):ST7789по умолчаниюRGBILI9488по умолчаниюBGRinvert(bool)по умолчаниюtrueswap(bool)по умолчаниюfalseoffset(x, y)по умолчанию(0, 0)
Что важно:
- если
hz(...)илиorder(...)не заданы, используются именно дефолты выбранного драйвера вPipCore - это особенно важно для
ILI9488, потому что его рабочие дефолты отличаются отST7789
Обязательно указать:
pins(...)задаёт пины SPI и управляющие пины дисплея.size(width, height)задаёт логический размер панели.
Пример для ILI9488:
ui.configDisplay()
.pins(11, 12, 10, 9, 14)
.size(320, 480);
3.2. Запуск GUI
После конфигурации дисплея вызывается begin():
ui.begin(0); // rotation: 0..3
// ui.begin(0, true); // forceTiles: принудительно включить tiled-mode (2 горизонтальных тайла)
rotationпринимает значения0..3.forceTiles=trueвключает tiled-mode даже если хватает памяти на полный screen-buffer.- если полный screen-buffer выделить не получилось, библиотека автоматически включает tiled-mode: выделяет буфер
screenWidth × ceil(screenHeight/2)и рисует кадр в 2 прохода (верх/низ). - стартовый фон GUI фиксированно чёрный (
0x0000).
Ограничения tiled-mode:
- screen-transition анимации отключены (требуют полного screen-buffer).
- rotation-transition анимация отключена.
Проверить текущий режим можно через ui.tiledMode().
Runtime-поворот экрана
ui.setRotation(0); // повернуть экран сразу или с анимацией по умолчанию
ui.setRotation(1, 620); // тот же поворот, но со своей длительностью
ui.screenRotation(); // текущая ориентация 0..3
ui.rotationTransitionActive(); // идёт ли сейчас анимация переворота
setRotation(...)меняет ориентацию уже послеbegin(), без повторногоconfigDisplay()- библиотека держит физическую конфигурацию дисплея как есть и поворачивает GUI логически, пересобирая внутренний sprite под новый размер
- если GUI сейчас в обычном steady-state, поворот идёт с анимацией как у телефона: текущий кадр схлопывается, в середине меняется ориентация, затем новый кадр раскрывается
- если в этот момент активны boot, error, screen transition или overlay-состояния, библиотека делает безопасный мгновенный поворот без анимации
screenRotation()возвращает текущий runtime rotation0..3rotationTransitionActive()позволяет не запускать свой второй переход поверх уже идущего переворота
3.3. Подсветка и яркость
ui.setBacklight()
.pin(48) // pin
.channel(0) // PWM channel
.freq(5000) // PWM frequency
.resolution(12); // PWM resolution bits
Что важно:
pin- обязательныйchannel,frequencyиresolutionможно не указывать- после
setBacklight(...)boot-анимацияLightFadeуже сама управляет яркостью - если backlight не настроен,
LightFadeуправлять нечем
Максимальная яркость
ui.setMaxBrightness(70); // ограничить максимум 70%
- диапазон
0..100 - это верхний лимит яркости, библиотека использует этот лимит, когда сама меняет яркость
- на текущей ESP32-платформе значение сохраняется и потом подгружается автоматически
Текущая яркость
ui.setBrightness(35);
- диапазон
0..100 - сразу отправляет новое значение в текущий backlight runtime, то есть эффект виден без перезапуска GUI
- если backlight настроен через
setBacklight(...)илиsetBacklightHandler(...), библиотека сразу применяет новый уровень к активной подсветке - значение всегда clamp-ится сверху через
maxBrightness(), поэтомуsetBrightness(90)приsetMaxBrightness(70)даст фактические70
ui.brightness();
- возвращает именно текущее runtime-значение, а не сохранённый лимит
- это временное пользовательское состояние на текущую сессию: после reboot оно не восстанавливается из prefs автоматически
- если нужен сохраняемый предел яркости, для этого используется
setMaxBrightness(...)
Низкоуровневые helpers
void myBacklight(uint16_t level) {
// свой способ применить яркость
}
ui.setBacklightHandler(myBacklight);
setBacklightHandler(...)позволяет подставить свой handler для управления подсветкой- callback имеет сигнатуру
void (*)(uint16_t level) levelэто целевой уровень яркости, который библиотека хочет применить- это low-level хук для своего драйвера подсветки, если стандартного
setBacklight()недостаточно - обычно этот API не нужен, если хватает
setBacklight()
4. Логотип
ui.showLogo()
.text("PISPPUS", "Digital Thermometer")
.anim(FadeIn);
showLogo() запускает полноэкранную boot-анимацию с логотипом. Размер текста библиотека подбирает сама под текущее разрешение экрана.
Параметры:
text(title, subtitle)— две строки логотипа;anim(...)—None,FadeIn,LightFade;
Что делают анимации:
None- просто сразу показывает логотип без анимацииFadeIn- плавно проявляет текст из цвета фонаLightFade- плавно поднимает яркость подсветки; для неё backlight должен быть заранее настроен