F("") и русский язык, как сэкономить память?

Память МК (флеш) забита впритык, пытаюсь оптимизировать. На дисплей библиотекой GyverOLED выводятся русские сообщения. Трабл в том, что в памяти МК русская буква хранится в UTF-8 если выводить через oled.print(F(“текст”)). Разбивать на символы не получается с F(“”).

  • пробовал определять строки как const char имястроки PROGMEM = {‘т’,‘е’,‘к’,‘с’,‘т’}; - тогда через .print этот const char вывести не могу. Приходится вводить буфер strcpy_P (буфер char, имястроки); и потом .print буфер. - занимает больше флеш чем при .print (F(“”)). компилятор вываливает warningи, но все-таки компилит и текст выводится норм…Символы действительно занимают ОДИН байт, пробовал заменять их на английские - тот же обьем.

  • пробовал сделать .print (F("\однобайтный код символа т\однобайтный код символа е .… ")). НО! не пойму как символы кодируются - подстановкой кодов не нашел большей части строчных русских букв (и часть кодов например 80…100DEC компилятор отрыгивает).

Подскажите пож как __Flash_Helperу скормить подобие {‘т’,‘е’,‘к’,‘с’,‘т’} - оно ж хранится по 1 байту и срабатывает через strcpy_P. Или какие еще варианты? для .print F(“\xxx.…”) не могу подобрать коды символов в диапазоне 0…255 для букв а,б…п. Остальное есть, разбросано хз как по таблице, но выводить можно.

Ну, если хочется “сэкономить”, не пробовал в другой (однобайтовой) кодировке?

так как IDE указать чтобы его родной метод .print () работал в однобайтной? Например Win1251. Библиотеки дисплеев используют встроенный .print, как минимум OLED от Gyver… Ну или принимал массив символов не из __FlashStringHelper * а из указателя на PROGMEM.

Так сделайте свой print, если этот Вас не устраивает. Хотя (скажу по секрету) print тут не при делах, Вы вполне можете пользоваться всеми его (print) наворотами, переписав единственный метод write. А write в гиверовской библиотеке как раз свой (он именно так и поступил, чтобы пользоваться всеми наворотами print).

И вообще, вывод русских символов на OLED – это чисто вопрос OLED’овской библиотеки. Если гиверовская Вас не устраивает, так чего Вы на неё молитесь?

Вижу ЕвгенийП отвечает.)
Как я понимаю, для удобства, сам ваш редактор должен поддерживать нужную кодировку. Ну а дальше, как её отобразить, уже дело техники.)

print же перекодирует UTF-8 перед тем как на write передать, не? Ну и меня не библиотека не устраивает - ей же передается уже 1-байтный код?, а то, что в флеш МК русская буква 2 байта занимает. И НЕ занимает если я ее определяю как {‘т’,‘е’,‘к’,‘с’,‘т’}.

С какого перепою? Он не может этого делать, даже если бы и захотел.

Специально сейчас посмотрел на текст гиверолед, вся работа с русскими буквами, разумеется, там в функции write, как и положено. начинается со строки №264.

Вам бы разобраться, как там всё устроено, а то Вы “не с теми мельницами воюете”. Будете понимать что откуда торчит, и проблема решится.

стоп, так где там с 264 строки что-нибудь про 2 байтовые UTF-8? Получили uint8_t data на входе и распечатали, заменив коды 4 букв. Т.е. на вход write уже приходит 1-байтовый символ (русские выше 0x80 лежат). А во флешь они ложаться совершенно в другой кодировке при записи const char text = “русский текст”. по 2 байта/букву.

Указатель на прогмем к типу флешстрингхелпер приводили?

не, не могу вкурить как указатель привести (вместо этого просто делал strcpy_P в буферную строку в ОЗУ). Ну и второй небольшой трабл (на который и забить можно) — warning: narrowing conversion of ‘-12112’ from ‘int’ to ‘char’ inside { } [-Wnarrowing]
Типа компилятор ужимает как-то UTF-8 в один байт… НО КАК??? Собственно пусть и ужимает, раз .print потом нормально понимает его, но без матюков желательно

reinterpret_cast<const __FlashStringHelper *>(ptrToProgmemArray);

Вы решили со мною поспорить? Мило. Да, нет уж, write получает ВСЕ символы, включая и служебные префиксы юникода (типа 0xD0, 0xD1 и т.п.), читайте код внимательнее.

И да, кстати, Вы говорите, что

компилятор должен был Вас предупредить, что так делать не стоит. Вы не видели? Или решили забить на него? Если второе, то так себе идея :frowning:

Можно, если хотите приключений на пятую точку. Если не хотите – то ни хрена не можно :slight_smile:

суйте так!!!)))

char i[] = "\320\237\321\200\320\270\320\262\320\265\321\202"; // текст "Привет" в кодировке UTF-8. 13 байт, в других кодировках можно и меньше!

void setup() { Serial.begin(9600); }

void loop() { Serial.println(i); delay(5000);}

в методе .write в упор не вижу обработки префиксов уникода или какого-либо перекодирования символов из двухбайтовых. Щаз напишу маленький скетч и напрямую выпихну в oled.write байты от 32 до 255… Думаю там все символы русские обнаружатся без префиксов и двухбайтовости коды символов будут соответствовать символам в charMap.h. Гиде там двубайтовые UTF-8? ИМХО на вход write уже приходит однобайтовый код символа из charMap.h (не скажу что это за кодировка по виду, может Win1251?)

char i = “\320\237\321\200\320\270\320\262\320\265\321\202”
это я понимаю, но как блин 320 что больше 1 байта превращается в 1 байт? Или то не совсем = коду символов?

char у нас хранится в озу же ?
и если так вам не надо париться, про то что озу у вас не хватает вы не писали!

в том то и дело, что при обычной записи char text = “привет” каждую русскую букву компилятор хранит в UTF-8 в двух байтах в памяти МК! а запись char i = “\320\237\321\200\320\270\320\262\320\265\321\202” хранит тот же привет по 1 байту уже в win1251. А метод .print как я понял перекодирует UTF-8 или оставляет без изменений Win1251 и отправляет методу .write. .write уже от графической библиотеки выпихивает Win1251 на экран. Собственно цель красиво описать русские строки чтобы они в памяти МК лежали НЕ в UTF-8, а в Win1251.

вот ответ ИИ

Переменная char в Arduino хранится в оперативной памяти (ОЗУ). [
ОЗУ — энергозависимая память, которая используется для хранения переменных в процессе выполнения программы

В Arduino данные типа char хранятся в EEPROM (энергонезависимая память).
EEPROM позволяет сохранять информацию даже при выключении устройства или перезагрузке микроконтроллера

как это понимать хз))) я думаю тот пример что скинул хранится в озу! но лучше уточните этот момент у кого то еще… нет времени))) а еще лучше сами переведите то что вам надо в такие строки и посмотрите сами… я думаю в озу хранится…

В строках №№ 296-299 Вас не смущают числа 208, 299? А ведь это и есть префиксы UTF 0xD0, 0xD1, не заметили?

Сами по себе эти префиксы поступают в функцию write (как я Вам и говорил), но никуда не печатаются (см. строку №295). А вот символы, которые идут после этих префиксов, частично уходят на печать как есть (там так шрифт устроен), а частично подрабатываются (как раз в строках №№ 296-299).

Стало быть, если Вы хотите что-то там экономить, Вам нужно избавиться от этих префиксов во всех символах, кроме тех которые нуждаются в подработке. Тогда Вы сможете в полной мере использовать все возможности библиотеки (с буквой “ё” и т.п.).

Я же говорю, Вы разберитесь сначала, тогда Вам станет понятно, что нужно сделать. И только после этого можно поднимать вопрос как это сделать. Разумеется, делается это не так, как Вы делали, насилуя компилятор и не восьмеричными кодами, как Вам тут слово “привет” написали. Можно, конечно, и так, но лучше уж один раз сделать по уму, чем каждый раз так трахаться и таблицу кодов искать . Вы не согласны?

И, это, Вы бы поменьше агрессии. Есть вопросы спрашивайте, но спорить со мною – не смешно.

Не знаю, почему, но мне реально захотелось довести эту задачу с Вами до ума, но … я Вам уже трижды говорил, что метод print не занимается перекодировкой, этим занимается метод write. Советовал посмотреть на него внимательно, Вы этого не сделали, но продолжаете спорить! Ещё раз увижу вот такой бред:

дальше разбирайтесь без меня. К ИИ обращайтесь или ещё к кому, но без меня. Не шучу.

1 лайк