Platform — точка входа

Базовый платформенный слой PipCore: системные сервисы, ввод-вывод и конфигурация устройства.

4. Platform - точка входа

Platform - единственный объект, через который прошивка получает доступ к «железу» и ко всем включённым сервисам. Это абстрактный интерфейс: конкретную реализацию (ESP32 или симулятор) возвращает GetPlatform().

Platform *plat = GetPlatform();

GetPlatform() - синглтон, вызывать можно откуда угодно и сколько угодно раз.

Время и задержки

Метод Описание
uint32_t nowMs() Монотонное время с запуска, мс.
uint64_t nowUs() Монотонное время, мкс
void delayMs(uint32_t ms) Пауза без нагрузки на CPU (уступает планировщику FreeRTOS)
bool shouldQuit() const Запрос на выход: в симуляторе - закрытие окна, на ESP32 всегда false

GPIO

Метод Описание
void pinModeInput(uint8_t pin, InputMode mode) Настроить пин как вход: InputMode::Floating / Pullup / Pulldown
bool digitalRead(uint8_t pin) Цифровое чтение входа
int16_t analogRead(uint8_t pin) Чтение АЦП (сырой код, 0…4095). ADC-юнит и канал выбираются автоматически по номеру пина (при неверном пине вернёт 0)

Память

Метод Описание
void *alloc(size_t bytes, AllocCaps caps) Аллокация. Вернёт nullptr при нехватке памяти. AllocCaps::PreferInternal - сначала внутренняя RAM (нужно для DMA-буферов), при нехватке - внешняя
void free(void *ptr) Освобождение памяти из alloc. nullptr безопасен
void *allocAligned(size_t bytes, size_t align, AllocCaps caps) Аллокация с выравниванием (align меньше sizeof(void*) поднимается до него)
void freeAligned(void *ptr) Освобождение памяти из allocAligned
uint32_t freeHeapTotal() Свободно всего, байт
uint32_t freeHeapInternal() Свободно во внутренней RAM, байт
uint32_t largestFreeBlock() Крупнейший непрерывный блок, байт
uint32_t minFreeHeap() Исторический минимум свободной кучи, байт

Память, выделенную alloc, освобождайте только free, а из allocAligned - только freeAligned. Смешивать их нельзя.

void *buf = plat->alloc(4096, AllocCaps::PreferInternal); // DMA-буфер
if (!buf)
    return;
// ...
plat->free(buf);

Дисплей

Метод Описание
bool configDisplay(const DisplayConfig &cfg) Сконфигурировать SPI-транспорт и драйвер панели. Можно вызывать повторно (смена параметров). false - если width/height нулевые или конфигурация не принята драйвером
bool beginDisplay(uint8_t rotation) Инициализировать панель, поворот 0..3. Вызывается после успешного configDisplay
bool setDisplayRotation(uint8_t rotation) Сменить поворот на лету, без повторной инициализации
Display *display() Интерфейс дисплея; nullptr, если дисплей не сконфигурирован или не запущен

Ошибки

if (!plat->configDisplay(cfg))
{
    PlatformError code = plat->lastError();     // enum
    const char *text   = plat->lastErrorText(); // "invalid display config", ...
}
PlatformError Текст Когда возникает
None ok Ошибок нет
InvalidDisplayConfig invalid display config Нулевое разрешение; вызов beginDisplay/setDisplayRotation до успешной конфигурации
DisplayConfigureFailed display configure failed Драйвер не принял параметры
DisplayBeginFailed display begin failed Не удалось выполнить инициализацию панели
DisplayIoFailed display io failed Ошибка SPI-передачи (в т. ч. при смене поворота)

lastError() также возвращает DisplayIoFailed, если драйвер панели зафиксировал сбой ввода-вывода, даже когда последняя операция платформы прошла успешно. platformErrorText(PlatformError) даёт текст для любого значения.

Сервисы

Метод Возвращает
net::Backend *network() WiFi-бэкенд или nullptr, если модуль выключен
ota::Backend *update() OTA-бэкенд или nullptr
Touch *touch() Тач или nullptr
Audio *audio() Микшер или nullptr
prefs::Backend *prefs() Хранилище настроек или nullptr

Для WiFi, OTA, Prefs и Storage обычно удобнее свободные функции (net::wifiService(), prefs::setU8(...), storage::open(...)) - они сами достают бэкенд из платформы. Прямые указатели нужны, когда хочется хранить интерфейс у себя.

DisplayConfig

struct DisplayConfig
{
    int8_t   mosi = -1;       // пины SPI; -1 = не используется
    int8_t   sclk = -1;
    int8_t   cs   = -1;       // chip select
    int8_t   dc   = -1;       // data/command
    int8_t   rst  = -1;       // аппаратный reset; -1 - не подключён
    uint16_t width  = 0;      // разрешение панели в пикселях (обязательно)
    uint16_t height = 0;
    uint32_t hz = 0;          // частота SPI, Гц
    uint8_t  order = 0;       // порядок каналов в MADCTL: 0 = RGB, 1 = BGR
    bool     invert = true;   // инверсия цвета (нужна большинству IPS-панелей)
    bool     swap = false;    // байтовый своп RGB565 перед отправкой
    int16_t  xOffset = 0;     // сдвиг окна для панелей, у которых контроллер
    int16_t  yOffset = 0;     // больше стекла (например, 240×320 внутри)
};