Сделан русский текст

This commit is contained in:
2026-08-08 11:15:20 +03:00
parent c952c165f8
commit 70fe3566b4
9 changed files with 300 additions and 69 deletions

View File

@@ -1,10 +1,26 @@
#include "Display.h"
#include "Config.h"
#include "Font_Cyrillic.h"
#include "Log.h"
#include <Wire.h>
#include <esp_log.h>
#include <string.h>
namespace {
uint32_t nextUtf8Codepoint(const char *&text) {
const uint8_t first = static_cast<uint8_t>(*text++);
if (first < 0x80U) return first;
if ((first & 0xE0U) == 0xC0U) {
const uint8_t second = static_cast<uint8_t>(*text);
if ((second & 0xC0U) == 0x80U) {
++text;
return ((first & 0x1FU) << 6) | (second & 0x3FU);
}
}
return '?';
}
}
Display::Display() : oled_(128, 32, &Wire, -1) {}
bool Display::begin() {
@@ -37,25 +53,38 @@ void Display::setPower(bool enabled) {
Log::printf("OLED", "display power %s", enabled ? "ON" : "OFF");
}
void Display::fit(char *s) {
int16_t x, y; uint16_t w, h;
while (*s) {
oled_.getTextBounds(s, 0, 0, &x, &y, &w, &h);
if (w <= 128) break;
s[strlen(s) - 1] = '\0';
void Display::drawTextLine(const char *text, int16_t y) {
int16_t x = 0;
while (text && *text && x + CyrillicFont::WIDTH <= oled_.width()) {
const uint32_t codepoint = nextUtf8Codepoint(text);
const uint8_t *glyph = CyrillicFont::glyph(codepoint);
if (glyph) {
for (uint8_t row = 0; row < CyrillicFont::HEIGHT; ++row) {
const uint8_t pixels = pgm_read_byte(glyph + row);
for (uint8_t column = 0; column < CyrillicFont::WIDTH; ++column)
if (pixels & (1U << (CyrillicFont::WIDTH - 1U - column)))
oled_.drawPixel(x + column, y + row, SSD1306_WHITE);
}
} else if (codepoint < 0x100U) {
oled_.drawChar(x, y, static_cast<unsigned char>(codepoint),
SSD1306_WHITE, SSD1306_BLACK, 1);
} else {
oled_.drawChar(x, y, '?', SSD1306_WHITE, SSD1306_BLACK, 1);
}
x += CyrillicFont::ADVANCE;
}
}
void Display::show(const char *a, const char *b, uint32_t progress, uint32_t progressTotal) {
char one[32], two[32];
char one[64], two[64];
snprintf(one, sizeof(one), "%s", a ? a : ""); snprintf(two, sizeof(two), "%s", b ? b : "");
// Serial is the primary UI mirror and remains available when OLED is absent.
Log::printf("UI", "%s | %s", one, two);
if (!ok_) return;
setPower(true);
fit(one); fit(two);
oled_.clearDisplay(); oled_.setCursor(0, 3); oled_.print(one);
oled_.setCursor(0, 19); oled_.print(two);
oled_.clearDisplay();
drawTextLine(one, 3);
drawTextLine(two, 19);
if (progressTotal) {
if (progress > progressTotal) progress = progressTotal;
const uint16_t width = static_cast<uint16_t>(