feat(st7789): драйвер TFT-панелей ST7789V поверх SPI

Перенесён из KONOR_ds18b20/lib/st7789; в OpticalTester лежала побайтово
такая же копия.

Ядро не включает заголовки МК и не заводит кадрового буфера: примитивы
пишут пиксели потоком, поэтому драйвер работает на МК с единицами
килобайт ОЗУ. Платформа подключается через ST7789_Io: обязательны
write, set_command и delay_ms, остальное — по разводке платы.
This commit is contained in:
2026-08-23 01:15:11 +03:00
parent fe6598ca60
commit c7798c02db
5 changed files with 1106 additions and 0 deletions

280
c/st7789/st7789.h Normal file
View File

@@ -0,0 +1,280 @@
/**
* @file st7789.h
* @brief Портируемый драйвер TFT-дисплеев ST7789V (SPI, RGB565).
*
* Библиотека не включает заголовки микроконтроллера и не обращается к
* регистрам: весь обмен идёт через таблицу обратных вызовов ST7789_Io,
* которую заполняет порт платы. Кадрового буфера нет — примитивы пишут
* пиксели в контроллер потоком, поэтому драйвер работает на МК с единицами
* килобайт ОЗУ.
*
* Порядок использования: заполнить ST7789_Io, взять ST7789_ConfigDefault(),
* поправить геометрию и поворот, вызвать ST7789_Init(), далее рисовать.
*/
#ifndef ST7789_H
#define ST7789_H
#include <stdint.h>
/** Ширина знакоместа встроенного шрифта при масштабе 1, пикселей. */
#define ST7789_FONT_WIDTH 6U
/** Высота знакоместа встроенного шрифта при масштабе 1, пикселей. */
#define ST7789_FONT_HEIGHT 8U
/** Максимальный целочисленный масштаб шрифта. */
#define ST7789_FONT_MAX_SCALE 4U
/** Код знака градуса во встроенном шрифте. */
#define ST7789_CHAR_DEGREE 0x7FU
/** Размер потокового буфера в пикселях; определяет расход ОЗУ (по 2 байта). */
#ifndef ST7789_CHUNK_PIXELS
#define ST7789_CHUNK_PIXELS 64U
#endif
/**
* @brief Собирает цвет RGB565 из восьмибитных компонент.
*
* @param r Красная компонента 0..255.
* @param g Зелёная компонента 0..255.
* @param b Синяя компонента 0..255.
* @return Значение цвета для примитивов драйвера.
*/
#define ST7789_RGB(r, g, b) ((uint16_t)((((uint16_t)(r) & 0xF8U) << 8) \
| (((uint16_t)(g) & 0xFCU) << 3) \
| ((uint16_t)(b) >> 3)))
#define ST7789_BLACK 0x0000U /**< Чёрный. */
#define ST7789_WHITE 0xFFFFU /**< Белый. */
#define ST7789_RED 0xF800U /**< Красный. */
#define ST7789_GREEN 0x07E0U /**< Зелёный. */
#define ST7789_BLUE 0x001FU /**< Синий. */
#define ST7789_YELLOW 0xFFE0U /**< Жёлтый. */
#define ST7789_CYAN 0x07FFU /**< Голубой. */
#define ST7789_MAGENTA 0xF81FU /**< Пурпурный. */
#define ST7789_GRAY 0x8410U /**< Серый 50 %. */
#define ST7789_DARKGRAY 0x4208U /**< Тёмно-серый. */
#define ST7789_ORANGE 0xFD20U /**< Оранжевый. */
#define ST7789_NAVY 0x000FU /**< Тёмно-синий. */
/**
* @brief Обратные вызовы платы, через которые драйвер работает с дисплеем.
*
* Обязательны только @c write, @c set_command и @c delay_ms. Остальные поля
* допускают значение 0, если сигнал на плате не разведён: без @c set_reset
* драйвер выполняет программный сброс командой SWRESET, без @c set_select
* дисплей считается постоянно выбранным (вывод CS посажен на общий провод).
*/
typedef struct {
/** Передаёт блок байтов по SPI: 8 бит, старший бит первым. */
void (*write)(void *context, const uint8_t *data, uint32_t size);
/** Задаёт уровень линии DC: 1 — команда, 0 — данные. */
void (*set_command)(void *context, uint8_t is_command);
/** Управляет выбором кристалла: 1 — выбран (CS низкий). */
void (*set_select)(void *context, uint8_t selected);
/** Управляет линией RES: 1 — сброс активен (низкий уровень). */
void (*set_reset)(void *context, uint8_t asserted);
/** Включает и выключает подсветку. */
void (*set_backlight)(void *context, uint8_t on);
/** Задержка в миллисекундах на время инициализации панели. */
void (*delay_ms)(void *context, uint32_t milliseconds);
/** Указатель платы, передаваемый во все обратные вызовы. */
void *context;
} ST7789_Io;
/** @brief Ориентация растра относительно нулевого поворота панели. */
typedef enum {
ST7789_ROTATION_0 = 0, /**< Портрет, шлейф снизу. */
ST7789_ROTATION_90, /**< Ландшафт, поворот на 90 градусов. */
ST7789_ROTATION_180, /**< Портрет, перевёрнутый. */
ST7789_ROTATION_270 /**< Ландшафт, поворот на 270 градусов. */
} ST7789_Rotation;
/**
* @brief Параметры конкретной панели.
*
* Модули на ST7789V отличаются видимой областью и её положением в растре
* контроллера 240x320: у панелей 240x240 и 240x320 смещений нет, у 135x240
* видимая область сдвинута. Значения берутся из документации модуля.
*/
typedef struct {
uint16_t width; /**< Видимая ширина при нулевом повороте, пикселей. */
uint16_t height; /**< Видимая высота при нулевом повороте, пикселей. */
uint16_t offset_x; /**< Смещение видимой области по X при повороте 0. */
uint16_t offset_y; /**< Смещение видимой области по Y при повороте 0. */
ST7789_Rotation rotation; /**< Требуемая ориентация изображения. */
uint8_t invert; /**< 1 — инверсия (обычные IPS-модули ST7789V). */
uint8_t bgr; /**< 1 — порядок субпикселей BGR вместо RGB. */
} ST7789_Config;
/**
* @brief Состояние дисплея; принадлежит вызывающему коду.
*
* Поля @c width и @c height учитывают поворот, поэтому примитивы принимают
* координаты в системе видимого изображения.
*/
typedef struct {
ST7789_Io io; /**< Копия обратных вызовов платы. */
ST7789_Config config; /**< Копия параметров панели. */
uint16_t width; /**< Ширина изображения с учётом поворота. */
uint16_t height; /**< Высота изображения с учётом поворота. */
uint16_t offset_x; /**< Смещение окна по X с учётом поворота. */
uint16_t offset_y; /**< Смещение окна по Y с учётом поворота. */
uint8_t ready; /**< 1 после успешной инициализации. */
} ST7789_Display;
/**
* @brief Заполняет конфигурацию значениями типового модуля на ST7789V.
*
* Инверсия включена, порядок RGB, смещения нулевые, поворот нулевой.
*
* @param config Конфигурация, принадлежащая вызывающему коду.
* @param width Видимая ширина панели при нулевом повороте.
* @param height Видимая высота панели при нулевом повороте.
*/
void ST7789_ConfigDefault(ST7789_Config *config, uint16_t width, uint16_t height);
/**
* @brief Инициализирует панель и включает вывод изображения.
*
* Выполняет аппаратный либо программный сброс, задаёт формат пикселя RGB565,
* гамму, ориентацию и включает подсветку, если её вывод разведён.
*
* @param display Состояние дисплея.
* @param io Обратные вызовы платы; копируются внутрь состояния.
* @param config Параметры панели; копируются внутрь состояния.
* @return 1 при успешной инициализации, 0 при неполной таблице вызовов.
*/
uint8_t ST7789_Init(ST7789_Display *display, const ST7789_Io *io,
const ST7789_Config *config);
/**
* @brief Меняет ориентацию изображения без повторной инициализации.
*
* @param display Инициализированный дисплей.
* @param rotation Требуемая ориентация.
*/
void ST7789_SetRotation(ST7789_Display *display, ST7789_Rotation rotation);
/**
* @brief Включает или выключает подсветку панели.
*
* @param display Инициализированный дисплей.
* @param on 1 — включить, 0 — выключить.
* @note При отсутствии обратного вызова платы функция ничего не делает.
*/
void ST7789_Backlight(ST7789_Display *display, uint8_t on);
/**
* @brief Переводит панель в спящий режим и обратно.
*
* @param display Инициализированный дисплей.
* @param sleep 1 — сон (SLPIN), 0 — рабочий режим (SLPOUT).
*/
void ST7789_Sleep(ST7789_Display *display, uint8_t sleep);
/**
* @brief Заливает весь экран одним цветом.
*
* @param display Инициализированный дисплей.
* @param color Цвет RGB565.
*/
void ST7789_FillScreen(ST7789_Display *display, uint16_t color);
/**
* @brief Заливает прямоугольник одним цветом.
*
* Область обрезается по границам экрана; нулевые размеры игнорируются.
*
* @param display Инициализированный дисплей.
* @param x Левая граница.
* @param y Верхняя граница.
* @param width Ширина области.
* @param height Высота области.
* @param color Цвет RGB565.
*/
void ST7789_FillRect(ST7789_Display *display, int16_t x, int16_t y,
uint16_t width, uint16_t height, uint16_t color);
/**
* @brief Рисует рамку прямоугольника толщиной один пиксель.
*
* @param display Инициализированный дисплей.
* @param x Левая граница.
* @param y Верхняя граница.
* @param width Ширина области.
* @param height Высота области.
* @param color Цвет RGB565.
*/
void ST7789_DrawRect(ST7789_Display *display, int16_t x, int16_t y,
uint16_t width, uint16_t height, uint16_t color);
/**
* @brief Закрашивает один пиксель.
*
* @param display Инициализированный дисплей.
* @param x Координата по горизонтали.
* @param y Координата по вертикали.
* @param color Цвет RGB565.
*/
void ST7789_DrawPixel(ST7789_Display *display, int16_t x, int16_t y, uint16_t color);
/**
* @brief Выводит готовый растр RGB565 построчно.
*
* @param display Инициализированный дисплей.
* @param x Левая граница области.
* @param y Верхняя граница области.
* @param width Ширина растра.
* @param height Высота растра.
* @param pixels Массив width*height пикселей, порядок — строками.
* @note Область должна целиком попадать на экран, иначе вывод отменяется.
*/
void ST7789_DrawBitmap(ST7789_Display *display, int16_t x, int16_t y,
uint16_t width, uint16_t height, const uint16_t *pixels);
/**
* @brief Выводит один символ встроенного шрифта с непрозрачным фоном.
*
* @param display Инициализированный дисплей.
* @param x Левая граница знакоместа.
* @param y Верхняя граница знакоместа.
* @param symbol Код символа 0x20..0x7F; прочие выводятся как пробел.
* @param color Цвет штриха.
* @param background Цвет фона знакоместа.
* @param scale Целочисленный масштаб 1..ST7789_FONT_MAX_SCALE.
*/
void ST7789_DrawChar(ST7789_Display *display, int16_t x, int16_t y, char symbol,
uint16_t color, uint16_t background, uint8_t scale);
/**
* @brief Выводит строку встроенным шрифтом с непрозрачным фоном.
*
* Символы за правой границей экрана отбрасываются, перевод строки не
* обрабатывается.
*
* @param display Инициализированный дисплей.
* @param x Левая граница первого знакоместа.
* @param y Верхняя граница строки.
* @param text Строка, завершённая нулём.
* @param color Цвет штриха.
* @param background Цвет фона знакомест.
* @param scale Целочисленный масштаб 1..ST7789_FONT_MAX_SCALE.
* @return Координата X сразу за последним выведенным знакоместом.
*/
int16_t ST7789_DrawString(ST7789_Display *display, int16_t x, int16_t y,
const char *text, uint16_t color, uint16_t background,
uint8_t scale);
/**
* @brief Считает ширину строки в пикселях для заданного масштаба.
*
* @param text Строка, завершённая нулём.
* @param scale Масштаб шрифта.
* @return Ширина в пикселях.
*/
uint16_t ST7789_TextWidth(const char *text, uint8_t scale);
#endif /* ST7789_H */