Ты думаешь, если я берусь за написание библиотенки, я этого не видел.
Статья, кстати, просто безграмотная. Автор, похоже, не представляет себе, как устроена utf-8, если допускает утверждения вроде "работаем в UTF-8. Берем таблицу кодировки и получается что:
диапазону 0x80 — 0x8F соответствуют маленькие буквы от «р» до «я»...".
Велосипед, велосипед, велосипед. Если втискивать все это в мегу 8, да согласен, надо экономить память програм. Если писать серьезное приложение и спользовать мегу 256 то увеличение таблицы знакогенератора в два раза не как не отразится. даже место останется. Сейчас изучаю stm32. Начал с простого, hd44780. Посмотрел множество решений перекодирования кирилицы. В результате анализа упростил код из 12 строк в 5. Результат тот же, на индикатор уверенно выводятся русские фразы. Вы грузите процессор бесполезными вычеслениями знакоместа символа, куда гараздо проще понять какой код присвоен символу, создать таблицу и обращаться к ней через указатели. Заметьте, большая часть символов уже существует в английском алфавите и схожа по написанию, в таблицу знакогенератора надо просто прописать недостающие русские символы. Вот мой рецепт простого решения проблеммы.....
Вот так выглядит функция вывода строки или массива символов:
код написан для ARM, но думаю что подкорректировав можно использовать и для AVR.
Конечно это не 128х64 и темболее не tft, но идеология знакогенератора эдентична. Предвидя вопрос об объеме используемой памяти предлогаю подсчетать побайтно сколько занимает места полный знакогенератор и предлогаемый вариант с подменой русских символов схожих по написанию с латинскими плюс таблица указателей.
И чем этот метод лучше моего? Добавляется функция и таблица перекодировки. А в моём методе добавляется только функция (таблица перекодировки не нужна).
Кроме того, данный метод уже реализован в библиотеке LiquidCrystalRus. Но данная библиотека мне не помогла, так как в дисплее типа hd44780 у меня вместо русских шрифтов прошиты иероглифы.
diger67 пишет:
Конечно это не 128х64 и темболее не tft, но идеология знакогенератора эдентична.
hd44780 - текстовый дисплей с заложенными в него шрифтами, а OLED Display 0.96 128x64 - графический дисплей и аппаратного знакогенератора там нет.
И чем этот метод лучше моего? Добавляется функция и таблица перекодировки. А в моём методе добавляется только функция (таблица перекодировки не нужна).
Кроме того, данный метод уже реализован в библиотеке LiquidCrystalRus. Но данная библиотека мне не помогла, так как в дисплее типа hd44780 у меня вместо русских шрифтов прошиты иероглифы.
diger67 пишет:
Конечно это не 128х64 и темболее не tft, но идеология знакогенератора эдентична.
hd44780 - текстовый дисплей с заложенными в него шрифтами, а OLED Display 0.96 128x64 - графический дисплей и аппаратного знакогенератора там нет.
вопрос не в том что есть, а чего нет. Вопрос в подходе решения вопроса. Размере кода и объема занимаемым им кода. Если надо разжевывать, то пожалуйста. Создаем файл знакогенератора, зная коды букв и цыфр создаем функцию обращения через указатели к таблице знакогенератора. Пользуясь одинаковым написанием некоторх русских и латинских букв экономим ресурсы памяти програм. Не пишим бесполезных сложных функций, пытаясь удивить весь мир.
Лично мне не нравится перекодировка в 1251. Мне кажется, это лишнее. Кроме того, кодировка ограничена русским и латинским алфавитами, сделать надпись по-украниски, по-белорусски или по-маекдонски не получится. И, на мой взгляд, спорное решение - вводить в знакогенератор псевдографику. Во-первых, на асех не угодишь - каких-то пиктограмм кому-нибудь яано будет не хватать. Во вторых, в большинстве случаев заданные в знакогенераторе пиктограммы не будут востребованы, следовательно, имеем нерправданное увеличение объема знакогенератора. И в-третьих, мне кажется, вывоить пиктограммы как текст неудобно, минимум, по трем причинам:
- трудно запоминать, каким символам какие пиктограммы соответствуют,
- непонятно, как вводить с класиатуры нужные "символы" в код программы,
- размер пиктограммы жестко задан, причем не является удобным.
В заключение напомню, что, на мой взгляд, моя библиотека занимает несколько иную нишу, нежели библиотека Adafruit. В первую очередь потому, что не использует экранный буфер, который сразу "отжирает" две трети доступной оперативной памяти. Такое растчительство допустимо лишь в системах, в которых экран занимает центральное место. Мою же библиотеку разумно использовать тогда, когда экран играет вспомогательную роль, а оперативная память нужна для других задач.
вопрос не в том что есть, а чего нет. Вопрос в подходе решения вопроса. Размере кода и объема занимаемым им кода. Если надо разжевывать, то пожалуйста. Создаем файл знакогенератора, зная коды букв и цыфр создаем функцию обращения через указатели к таблице знакогенератора. Пользуясь одинаковым написанием некоторх русских и латинских букв экономим ресурсы памяти програм. Не пишим бесполезных сложных функций, пытаясь удивить весь мир.
А можно привести оценку, сколько именно мы сэкономили?
По моим прикидкам, совпадающих букв - около 10. Если считать как строчные, так и пнрописные - около 20. При 5 байтах на символ "экономим" 100 байт. Но при этом появляется дополнительная таблица указателей. Укащзатель - это 2 байта. Если у нас 66 строчных и прописных символа (считаем, что таблицу мы используем не для всех символов, а только для кириллицы), это минимум 132 байта. + немножко байтов за счет усложнения алгоритма (часть символов перекодируем, часть - нет).
вопрос не в том что есть, а чего нет. Вопрос в подходе решения вопроса. Размере кода и объема занимаемым им кода. Если надо разжевывать, то пожалуйста. Создаем файл знакогенератора, зная коды букв и цыфр создаем функцию обращения через указатели к таблице знакогенератора. Пользуясь одинаковым написанием некоторх русских и латинских букв экономим ресурсы памяти програм. Не пишим бесполезных сложных функций, пытаясь удивить весь мир.
А можно привести оценку, сколько именно мы сэкономили?
По моим прикидкам, совпадающих букв - около 10. Если считать как строчные, так и пнрописные - около 20. При 5 байтах на символ "экономим" 100 байт. Но при этом появляется дополнительная таблица указателей. Укащзатель - это 2 байта. Если у нас 66 строчных и прописных символа (считаем, что таблицу мы используем не для всех символов, а только для кириллицы), это минимум 132 байта. + немножко байтов за счет усложнения алгоритма (часть символов перекодируем, часть - нет).
Так где экономия?
Указатель это 1 байт если вы внимательно читали текст кода все указатели char, значит всего 32 байта. В stm 32 в одном слове храниться 4 указателя(байта). Каждая буква кирилицы 33 * 5 = 155 байт. Если вы считаете что несовпадающих букв 13 это 65 байт. 155-(65+ 32) = 58 байта. Уверен что функция обращения через указатель займет две трети памяти от вашего решения. вот и считайте до 30% экономии по конкретному вопросу. Посчитайте еще более точно ;-))
Можно конечно скомпилировать вашу версию и мой метод применимо к вашему решению, но сильно занят пониманием логики работы 32 разрядных процессоров stm. Выбор остается за вами.
Указатель это 1 байт если вы внимательно читали текст кода все указатели char ...
Не надо путать указатель и значение, на которое он указывает. В стандартном Си указатель имеет размер 4 байта (независимо от размера указываемого значения).
Указатель это 1 байт если вы внимательно читали текст кода все указатели char ...
Не надо путать указатель и значение, на которое он указывает. В стандартном Си указатель имеет размер 4 байта (независимо от размера указываемого значения).
Если вы указываете переменную как char, то в int храниться два , в double четыре char. Купите JTAG debager и посмотрите что и где в реале храниться в памяти процессора. При попытке поместить в char значение int или double компилятор выдаст ошибку. Специально посмотрел hex файл, значения указателей храняться одно за другим и занимают один байт. Выделил пробелом начало и конец массива указателей.
Прочитайте еще раз, там речь идет о 32 разрядной системе и к томуже об ОЗУ. Вы путаете адрес по которому лежит указатель и значение указателя.Не зная архитиктуры процессора, принципов адресации и передачи данных сложно писать программы. Я начинал писать программы с ассемблера. Изучайте мат часть.
Указатель это 1 байт если вы внимательно читали текст кода все указатели char ...
Не надо путать указатель и значение, на которое он указывает. В стандартном Си указатель имеет размер 4 байта (независимо от размера указываемого значения).
Если вы указываете переменную как char, то в int храниться два , в double четыре char.
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
diger67 пишет:
Вы путаете адрес по которому лежит указатель и значение указателя.
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
Он такого не утверждает.
Просто он не совсем верно назвал смещение указателем. А смещение у него в коде действительно однобайтовое.
Собственно, я, когда отвечал ему, код не смотрел, а в 8-разрядной архитектуре указатель, как правило, 2 байта, поэтому я и в подсчетах использовал эту величину.
Совершенно верно в общении с hd44780 значение в массиве указателей есть адрес знака который необходимо отобразить . А вот утверждать что указатель однозначно double могут только ламеры.
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
Он такого не утверждает.
Просто он не совсем верно назвал смещение указателем. А смещение у него в коде действительно однобайтовое.
Собственно, я, когда отвечал ему, код не смотрел, а в 8-разрядной архитектуре указатель, как правило, 2 байта, поэтому я и в подсчетах использовал эту величину.
Значение указателя определется его объявлением. Как хотите, char-ЭТО 8БАЙТ! и так далее. Теперь я понимаю почему наши програмные продукты нужны ограниченому кругу российских пользователей. Смещение - это когда есть сдвиг с постоянным значением, т.е. address + const. УЧИТЕ МАТ ЧАСТЬ!!!!! И излогать свои мысли стоит проанализировав предоставленную информацию. В целом я удовлеторен результатом общения. Да и dou для начала ARM ядро, конкретнее 32 разрядный процессор. По сути тоже самое что и stm32. Удачи парни.
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
Он такого не утверждает.
Он как раз это и утверждает.
diger67 пишет:
Значение указателя определется его объявлением.
Специально для специалиста по матчасти diger67 набросал небольшой пример:
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
Он такого не утверждает.
Он как раз это и утверждает.
diger67 пишет:
Значение указателя определется его объявлением.
Специально для специалиста по матчасти diger67 набросал небольшой пример:
Число вполне конкретное и зависит от исходных данных. На основании своего многолетнего опыта программирования на Си и Ассемблере для разных процессоров и контроллеров, я могу его сосчитать без запуска программы на компиляцию. Сможет ли так специалист по матчасти diger67?
Число вполне конкретное и зависит от исходных данных. На основании своего многолетнего опыта программирования на Си и Ассемблере для разных процессоров и контроллеров, я могу его сосчитать без запуска программы на компиляцию. Сможет ли так специалист по матчасти diger67?
Можете расчитывать все с карандашиком на бумажке, это очень полезно. Сам иногда так делаю в поиске ошибок. Реже прогуливаясь с внуком в парке анализирую в уме алгоритм, прихожу домой правлю программу на основе пришедших мыслей. Хотя используя дебагер в пошаговом режиме проще найти ошибку, потому как видишь что в реале происходит в кишках камня. Речь не об этом. Говорилось о том, что через указатели можно работать с таблицей знакогенератора немного сэкономив память программ. Но вы так увлеклись самолюбованием и попыткой донести до всех какой вы классный, что перевели разговор в иную плоскость. Да и под матчастью подразумевалось понимание архитектуры камня. Саркастичный вы наш.
Но вы так увлеклись самолюбованием и попыткой донести до всех какой вы классный, что перевели разговор в иную плоскость. Да и под матчастью подразумевалось понимание архитектуры камня. Саркастичный вы наш.
По себе людей не судят. Вы назвали меня лузером и направили на изучение матчасти в том вопросе, в котором сами не разбираетесь. С карандашиком не удалось сосчитать?
При объявлении указателя типа char *c или long int *l соответственно char и long int указывают компилятору какого типа и размера данные по адресу указателя надо брать. А размер самого указателя зависит от процессора и адресуемой памяти и одинаков для всех переменных, что и показано в примерах.
Как специалист по архитектуре камня diger67 должен знать, что большие целочисленные переменные типа long int размещаются в памяти начиная с младшего разряда. Этот младший разряд через указатель *uc (в последнам принте) мы и вынимаем. У числа 1026 младший разряд будет 2 и к нему мы прибавляем 1. Получаем ответ: 3
Но вы так увлеклись самолюбованием и попыткой донести до всех какой вы классный, что перевели разговор в иную плоскость. Да и под матчастью подразумевалось понимание архитектуры камня. Саркастичный вы наш.
По себе людей не судят. Вы назвали меня лузером и направили на изучение матчасти в том вопросе, в котором сами не разбираетесь. С карандашиком не удалось сосчитать?
При объявлении указателя типа char *c или long int *l соответственно char и long int указывают компилятору какого типа и размера данные по адресу указателя надо брать. А размер самого указателя зависит от процессора и адресуемой памяти и одинаков для всех переменных, что и показано в примерах.
Как специалист по архитектуре камня diger67 должен знать, что большие целочисленные переменные типа long int размещаются в памяти начиная с младшего разряда. Этот младший разряд через указатель *uc (в последнам принте) мы и вынимаем. У числа 1026 младший разряд будет 2 и к нему мы прибавляем 1. Получаем ответ: 3
Читайте внимательнее, был создан массив указателей в PROM, которое чаще называют смещением, используя указатели они использовались для перекодировки символов и их корректного вывода. Сначала ознакомтесь с темой обсуждения. А потом начинайте мериться у кого длиннее. Может я не так силен в использовании указателей. Что же, не всем быть такими гениальными как вы. Для решения моих задач мне моих знаний хватает. Продолхайте трясти своим ..... только слюной не надо брызгать.
С помощью выражений типа *(uc+1) получаем следующие разряды long int, а в последнем printf мы распечатываем число long int как строку.
Должен предупредить, что компилятор (Borland C++ 5.5.1 for Win32) предупреждает о подозрительном преобразовании uc=ul, но компиляцию проводит. В Arduino компилятор более строгий и на операции uc=ul выдаёт ошибку.
С помощью выражений типа *(uc+1) получаем следующие разряды long int, а в последнем printf мы распечатываем число long int как строку.
Должен предупредить, что компилятор (Borland C++ 5.5.1 for Win32) предупреждает о подозрительном преобразовании uc=ul, но компиляцию проводит. В Arduino компилятор более строгий и на операции uc=ul выдаёт ошибку.
Что и требовалось доказать, восми разрядный процессор координально отличается от 32-х и выше. О чем я и предупреждал давая код под stm32, что его нужно рехтовать под AVR. Иначе компилятор выдаст ошибку.
Все бы ничего, только одна прблемма. У andriano не получается спользовать данную адресацию. При использовании стандартных настроек компилятора IDE Arduino, корректно отображается только латиница. Русский шрифт начинается с адреса 0xC0. Вот и надо заниматься перекодированием или городить массив масок с учетом сдвига.
Еще раз: в этой статье автор пишет откровенный бред. Цитирую:
Цитата:
Оговорюсь сразу: В данной заметке я рассмотрю создание (а точнее — модификацию) шрифта содержащего символы фиксированной ширины.
...
Меня осенила здравая идея — проверить в какой кодировке работает Arduino IDE.
Выяснилось — работаем в UTF-8. Берем таблицу кодировки и получается что:
диапазону 0x80 — 0x8F соответствуют маленькие буквы от «р» до «я»
с 0x90 и до 0xAF идут заглавные по порядку «А» — «Я» исключая «Ё»
и в хвосте с 0xB0 до 0xBF маленькие от «а» до «п».
Для тех, кто не в курсе, поясняю:
1. utf-8 - является кодировкой с символами переменной ширины.
2. в utf-8 не используется диапазон номеров символов с 0х80 по 0xff.
Как то плавненько разговор сместился от конструктива к болтовне. Предлагаю вернуться к конструктиву. К сожалению сейчас совершенно нет времени заняться любимым и полезным, а потому поделюсь как делаю значки 8х5 в програмке LCD1602 v1.1
1. Сначала надо загрузить таблицу символов через File -> Load Table.
Загружаем Epson.chr. И получаем таблицу символов как на первом изображении.
2. Если мы отим отредактировать любой символ из таблицы, или нарисовать свой неповторный элемент, то щелкаем правой кнопкой мыши на любом прямоугольнике в таблице символов справа и получаем возможность редактирования данного символа через контекстное меню Edit Char.
3. Увлеченно щелкая левой кнопкой мышки по желтым квадратикам, окрашиваем их в черный цвет, а щелкая правой кнопкой мышки по черным квадратикам, возращаем им первозданную желтизну, одновременно наблюдая в окошечке Data изменение в реальном времени кода данного шедевра. Дополнительные кнопки позволяют нам очистить все, или инвертировать все. И в итоге код данного символа можно скопировать в текст программы, что очень подходит для создания небольших значков, когда они так нужны.
С уважением ко всем участникам. Пользуйтесь.
Не знаю как добавлять файлы для скачивания, а потому загрузил файл программы в архиве zip как изображение jpg. Может получится скачать. Файл называется lcd1602.zip_.jpg
Нужен I2C, это не так сложно, напишите библиотеку передачи по I2C и прикрутите к ней adafruit. Я например перенес библиотеку adafruit на ядро stm32arduino. Правда большинство компиляторов не поддерживают C++. Но получилось и на C. Библиотека позволяет рисовать все приметивы. контуры и заполненные поля, выводить текстовую информацию, при этом используется шина FSMC 16 bit, что снижает нагрузку на ядро процессора, т.е. управление передачей данных происходит на уровне железа. Сейчас решаю проблемму использования DMA для вывода с SD на TFT графических изображений. AVR конечно более оброс примерами и библиотеками, но возможности ARM процессоров гараздо выше и по частоте ядра, и по перефирии, и по разрядности внутренней шины.
первая ссылка сдохла, во второй архив запакован не по правилам Arduino (это поправимо).
Но главное - при компиляции ругается:
In file included from Test_ASOLED_2.ino:3:
F:\Arduino\libraries\ASOLED/ASOLED.h:64: error: ISO C++ forbids initialization of member 'CurrFont'
F:\Arduino\libraries\ASOLED/ASOLED.h:64: error: making 'CurrFont' static
F:\Arduino\libraries\ASOLED/ASOLED.h:64: error: ISO C++ forbids in-class initialization of non-const static member 'CurrFont'
F:\Arduino\libraries\ASOLED/ASOLED.h:66: error: ISO C++ forbids initialization of member 'LenString'
F:\Arduino\libraries\ASOLED/ASOLED.h:66: error: making 'LenString' static
F:\Arduino\libraries\ASOLED/ASOLED.h:66: error: ISO C++ forbids in-class initialization of non-const static member 'LenString'
F:\Arduino\libraries\ASOLED/ASOLED.h:67: error: ISO C++ forbids initialization of member 'CurrX'
F:\Arduino\libraries\ASOLED/ASOLED.h:67: error: making 'CurrX' static
F:\Arduino\libraries\ASOLED/ASOLED.h:67: error: ISO C++ forbids in-class initialization of non-const static member 'CurrX'
F:\Arduino\libraries\ASOLED/ASOLED.h:68: error: ISO C++ forbids initialization of member 'CurrY'
F:\Arduino\libraries\ASOLED/ASOLED.h:68: error: making 'CurrY' static
F:\Arduino\libraries\ASOLED/ASOLED.h:68: error: ISO C++ forbids in-class initialization of non-const static member 'CurrY'
Tomasina, я вообще-то не С-шник, но, насколко я понимаю, я использовал здесь некоторое расширенме синтаксиса по сравнению со стандартом. При моих настройках IDE (настройки по умолчанию) компилятор это пропускает, при Ваших - нет.
Могу предложить в декларации класса (файл *.h) отказаться от присвоения значений:
char CurrFont; // font size [Font_6x8 | Font_12x16]
char NumberString[16]; // 4 print numbers
byte LenString; // current length of NumberString
byte CurrX; // current position
byte CurrY;
А в конструкторе либо в методе init() - присваимвать нужные значения (файл *.cpp):
void ASOLED::init(){
Wire.begin();
...
LD.setNormalDisplay();
LD.setPowerOn();
CurrFont = 1; // font size [Font_6x8 | Font_12x16]
LenString = 0; // current length of NumberString
CurrX = 0; // current position
CurrY = 0;
}
Не плохо бы добавить описание уже имеющихся функций библы. А то новичкам тяжко разобратся... Я вот например не могу понять как нарисовать прямоугольник... Подскажите пожалуйста...
Не плохо бы добавить описание уже имеющихся функций библы. А то новичкам тяжко разобратся... Я вот например не могу понять как нарисовать прямоугольник... Подскажите пожалуйста...
Никак. Библиотека для этого не предназначена.
Ту альтернатива простая: либо ты жертвуешь 2/3 всей доступной оперативной памяти под экранный буфер и рисуешь, что хочешь, либо экономишь память ценой отказа от графики. В данной библиотеке (в отличие от Adafruit) выбран второй вариант.
Вывести можно только готовый битмап, причем, если ширина битмапа произвольна, то высота должна быть кратна 8 пикселям.
// the most basic function, set a single pixel
void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) {
if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
return;
// check rotation, move pixel around if necessary
switch (getRotation()) {
case 1:
swap(x, y);
x = WIDTH - x - 1;
break;
case 2:
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
break;
case 3:
swap(x, y);
y = HEIGHT - y - 1;
break;
}
// x is which column
switch (color)
{
case WHITE: buffer[x+ (y/8)*SSD1306_LCDWIDTH] |= (1 << (y&7)); break;
case BLACK: buffer[x+ (y/8)*SSD1306_LCDWIDTH] &= ~(1 << (y&7)); break;
case INVERSE: buffer[x+ (y/8)*SSD1306_LCDWIDTH] ^= (1 << (y&7)); break;
}
}
А, ну да. Я совсем упустил из вида, что мы говорим о разных концепциях. В адафрут виртуал используется для определения функции, котора в последствии может быть переопределена в конкретном классе. Это делается для снятия конфликтов при наследовании. Где вы видили там виртуальные переменные. Все вычесленные значения пишутся непосредственно в GGC TFT. Ваш метод работает только если используются заранее готовые кластеры и корректно они будут работать только если их размеры строго одинаковы. Думаю что описание пазлов из кластеров разных размеров и конфигураций займет куда больше памяти и времени на обработку, чем пиксельная графика. Вывод, библиотек удобна только в случае вывода текста.
Посмотрти вот эту статью по руссификации
http://robocraft.ru/blog/892.html .
Ошибка: 404
К сожалению, такой страницы не существует. Вероятно, она была удалена с сервера, либо ее здесь никогда не было.
Вернуться назад, перейти на главную
Точку в адресной строки убери и будет тебе счастье.
Посмотрти вот эту статью по руссификации
http://robocraft.ru/blog/892.html .
Ошибка: 404
К сожалению, такой страницы не существует. Вероятно, она была удалена с сервера, либо ее здесь никогда не было.
Вернуться назад, перейти на главную
Точку в адресной строки убери и будет тебе счастье.
Нафига тогда ее надо было вставлять?
Еслиб ты ее сам убрал, то всем, кто пошел бы по ссылке стало бы легче.
Посмотрти вот эту статью по руссификации
http://robocraft.ru/blog/892.html .
Статья, кстати, просто безграмотная. Автор, похоже, не представляет себе, как устроена utf-8, если допускает утверждения вроде "работаем в UTF-8. Берем таблицу кодировки и получается что:
диапазону 0x80 — 0x8F соответствуют маленькие буквы от «р» до «я»...".
Может моё решение позволит решить вышеуказанные проблемы:
http://arduino.ru/forum/programmirovanie/rusifikatsiya-biblioteki-adafruit-gfx-i-vyvod-russkikh-bukv-na-displei-v-kodi
Может моё решение позволит решить вышеуказанные проблемы:
http://arduino.ru/forum/programmirovanie/rusifikatsiya-biblioteki-adafruit-gfx-i-vyvod-russkikh-bukv-na-displei-v-kodi
Велосипед, велосипед, велосипед. Если втискивать все это в мегу 8, да согласен, надо экономить память програм. Если писать серьезное приложение и спользовать мегу 256 то увеличение таблицы знакогенератора в два раза не как не отразится. даже место останется. Сейчас изучаю stm32. Начал с простого, hd44780. Посмотрел множество решений перекодирования кирилицы. В результате анализа упростил код из 12 строк в 5. Результат тот же, на индикатор уверенно выводятся русские фразы. Вы грузите процессор бесполезными вычеслениями знакоместа символа, куда гараздо проще понять какой код присвоен символу, создать таблицу и обращаться к ней через указатели. Заметьте, большая часть символов уже существует в английском алфавите и схожа по написанию, в таблицу знакогенератора надо просто прописать недостающие русские символы. Вот мой рецепт простого решения проблеммы.....
Вот так выглядит функция вывода строки или массива символов:
а так список указателей на русские символы, с поправкой что массив находится уже в памяти hd44780
код написан для ARM, но думаю что подкорректировав можно использовать и для AVR.
Конечно это не 128х64 и темболее не tft, но идеология знакогенератора эдентична. Предвидя вопрос об объеме используемой памяти предлогаю подсчетать побайтно сколько занимает места полный знакогенератор и предлогаемый вариант с подменой русских символов схожих по написанию с латинскими плюс таблица указателей.
Может моё решение позволит решить вышеуказанные проблемы:
http://arduino.ru/forum/programmirovanie/rusifikatsiya-biblioteki-adafruit-gfx-i-vyvod-russkikh-bukv-na-displei-v-kodi
Вот мой рецепт простого решения проблеммы.....
И чем этот метод лучше моего? Добавляется функция и таблица перекодировки. А в моём методе добавляется только функция (таблица перекодировки не нужна).
Кроме того, данный метод уже реализован в библиотеке LiquidCrystalRus. Но данная библиотека мне не помогла, так как в дисплее типа hd44780 у меня вместо русских шрифтов прошиты иероглифы.
Конечно это не 128х64 и темболее не tft, но идеология знакогенератора эдентична.
hd44780 - текстовый дисплей с заложенными в него шрифтами, а OLED Display 0.96 128x64 - графический дисплей и аппаратного знакогенератора там нет.
Может моё решение позволит решить вышеуказанные проблемы:
http://arduino.ru/forum/programmirovanie/rusifikatsiya-biblioteki-adafruit-gfx-i-vyvod-russkikh-bukv-na-displei-v-kodi
Вот мой рецепт простого решения проблеммы.....
И чем этот метод лучше моего? Добавляется функция и таблица перекодировки. А в моём методе добавляется только функция (таблица перекодировки не нужна).
Кроме того, данный метод уже реализован в библиотеке LiquidCrystalRus. Но данная библиотека мне не помогла, так как в дисплее типа hd44780 у меня вместо русских шрифтов прошиты иероглифы.
Конечно это не 128х64 и темболее не tft, но идеология знакогенератора эдентична.
hd44780 - текстовый дисплей с заложенными в него шрифтами, а OLED Display 0.96 128x64 - графический дисплей и аппаратного знакогенератора там нет.
вопрос не в том что есть, а чего нет. Вопрос в подходе решения вопроса. Размере кода и объема занимаемым им кода. Если надо разжевывать, то пожалуйста. Создаем файл знакогенератора, зная коды букв и цыфр создаем функцию обращения через указатели к таблице знакогенератора. Пользуясь одинаковым написанием некоторх русских и латинских букв экономим ресурсы памяти програм. Не пишим бесполезных сложных функций, пытаясь удивить весь мир.
Может моё решение позволит решить вышеуказанные проблемы:
http://arduino.ru/forum/programmirovanie/rusifikatsiya-biblioteki-adafruit-gfx-i-vyvod-russkikh-bukv-na-displei-v-kodi
Такое решение также имеет право на существование.
Лично мне не нравится перекодировка в 1251. Мне кажется, это лишнее. Кроме того, кодировка ограничена русским и латинским алфавитами, сделать надпись по-украниски, по-белорусски или по-маекдонски не получится. И, на мой взгляд, спорное решение - вводить в знакогенератор псевдографику. Во-первых, на асех не угодишь - каких-то пиктограмм кому-нибудь яано будет не хватать. Во вторых, в большинстве случаев заданные в знакогенераторе пиктограммы не будут востребованы, следовательно, имеем нерправданное увеличение объема знакогенератора. И в-третьих, мне кажется, вывоить пиктограммы как текст неудобно, минимум, по трем причинам:
- трудно запоминать, каким символам какие пиктограммы соответствуют,
- непонятно, как вводить с класиатуры нужные "символы" в код программы,
- размер пиктограммы жестко задан, причем не является удобным.
В заключение напомню, что, на мой взгляд, моя библиотека занимает несколько иную нишу, нежели библиотека Adafruit. В первую очередь потому, что не использует экранный буфер, который сразу "отжирает" две трети доступной оперативной памяти. Такое растчительство допустимо лишь в системах, в которых экран занимает центральное место. Мою же библиотеку разумно использовать тогда, когда экран играет вспомогательную роль, а оперативная память нужна для других задач.
вопрос не в том что есть, а чего нет. Вопрос в подходе решения вопроса. Размере кода и объема занимаемым им кода. Если надо разжевывать, то пожалуйста. Создаем файл знакогенератора, зная коды букв и цыфр создаем функцию обращения через указатели к таблице знакогенератора. Пользуясь одинаковым написанием некоторх русских и латинских букв экономим ресурсы памяти програм. Не пишим бесполезных сложных функций, пытаясь удивить весь мир.
А можно привести оценку, сколько именно мы сэкономили?
По моим прикидкам, совпадающих букв - около 10. Если считать как строчные, так и пнрописные - около 20. При 5 байтах на символ "экономим" 100 байт. Но при этом появляется дополнительная таблица указателей. Укащзатель - это 2 байта. Если у нас 66 строчных и прописных символа (считаем, что таблицу мы используем не для всех символов, а только для кириллицы), это минимум 132 байта. + немножко байтов за счет усложнения алгоритма (часть символов перекодируем, часть - нет).
Так где экономия?
вопрос не в том что есть, а чего нет. Вопрос в подходе решения вопроса. Размере кода и объема занимаемым им кода. Если надо разжевывать, то пожалуйста. Создаем файл знакогенератора, зная коды букв и цыфр создаем функцию обращения через указатели к таблице знакогенератора. Пользуясь одинаковым написанием некоторх русских и латинских букв экономим ресурсы памяти програм. Не пишим бесполезных сложных функций, пытаясь удивить весь мир.
А можно привести оценку, сколько именно мы сэкономили?
По моим прикидкам, совпадающих букв - около 10. Если считать как строчные, так и пнрописные - около 20. При 5 байтах на символ "экономим" 100 байт. Но при этом появляется дополнительная таблица указателей. Укащзатель - это 2 байта. Если у нас 66 строчных и прописных символа (считаем, что таблицу мы используем не для всех символов, а только для кириллицы), это минимум 132 байта. + немножко байтов за счет усложнения алгоритма (часть символов перекодируем, часть - нет).
Так где экономия?
Указатель это 1 байт если вы внимательно читали текст кода все указатели char, значит всего 32 байта. В stm 32 в одном слове храниться 4 указателя(байта). Каждая буква кирилицы 33 * 5 = 155 байт. Если вы считаете что несовпадающих букв 13 это 65 байт. 155-(65+ 32) = 58 байта. Уверен что функция обращения через указатель займет две трети памяти от вашего решения. вот и считайте до 30% экономии по конкретному вопросу. Посчитайте еще более точно ;-))
Можно конечно скомпилировать вашу версию и мой метод применимо к вашему решению, но сильно занят пониманием логики работы 32 разрядных процессоров stm. Выбор остается за вами.
Указатель это 1 байт если вы внимательно читали текст кода все указатели char ...
Не надо путать указатель и значение, на которое он указывает. В стандартном Си указатель имеет размер 4 байта (независимо от размера указываемого значения).
http://prog-cpp.ru/c-pointers/
Указатель это 1 байт если вы внимательно читали текст кода все указатели char ...
Не надо путать указатель и значение, на которое он указывает. В стандартном Си указатель имеет размер 4 байта (независимо от размера указываемого значения).
http://prog-cpp.ru/c-pointers/
Если вы указываете переменную как char, то в int храниться два , в double четыре char. Купите JTAG debager и посмотрите что и где в реале храниться в памяти процессора. При попытке поместить в char значение int или double компилятор выдаст ошибку. Специально посмотрел hex файл, значения указателей храняться одно за другим и занимают один байт. Выделил пробелом начало и конец массива указателей.
Прочитайте еще раз, там речь идет о 32 разрядной системе и к томуже об ОЗУ. Вы путаете адрес по которому лежит указатель и значение указателя.Не зная архитиктуры процессора, принципов адресации и передачи данных сложно писать программы. Я начинал писать программы с ассемблера. Изучайте мат часть.
Указатель это 1 байт если вы внимательно читали текст кода все указатели char ...
Не надо путать указатель и значение, на которое он указывает. В стандартном Си указатель имеет размер 4 байта (независимо от размера указываемого значения).
http://prog-cpp.ru/c-pointers/
Если вы указываете переменную как char, то в int храниться два , в double четыре char.
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
Вы путаете адрес по которому лежит указатель и значение указателя.
Значение указателя - это и есть адрес.
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
Он такого не утверждает.
Просто он не совсем верно назвал смещение указателем. А смещение у него в коде действительно однобайтовое.
Собственно, я, когда отвечал ему, код не смотрел, а в 8-разрядной архитектуре указатель, как правило, 2 байта, поэтому я и в подсчетах использовал эту величину.
Совершенно верно в общении с hd44780 значение в массиве указателей есть адрес знака который необходимо отобразить . А вот утверждать что указатель однозначно double могут только ламеры.
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
Он такого не утверждает.
Просто он не совсем верно назвал смещение указателем. А смещение у него в коде действительно однобайтовое.
Собственно, я, когда отвечал ему, код не смотрел, а в 8-разрядной архитектуре указатель, как правило, 2 байта, поэтому я и в подсчетах использовал эту величину.
Значение указателя определется его объявлением. Как хотите, char-ЭТО 8БАЙТ! и так далее. Теперь я понимаю почему наши програмные продукты нужны ограниченому кругу российских пользователей. Смещение - это когда есть сдвиг с постоянным значением, т.е. address + const. УЧИТЕ МАТ ЧАСТЬ!!!!! И излогать свои мысли стоит проанализировав предоставленную информацию. В целом я удовлеторен результатом общения. Да и dou для начала ARM ядро, конкретнее 32 разрядный процессор. По сути тоже самое что и stm32. Удачи парни.
Как хотите, char-ЭТО 8БАЙТ! и так далее.
блин! где ты раньше был?
[ушёл делать переучёт в имперском хранилище байтов]
*привет всем.
Как хотите, char-ЭТО 8БАЙТ! и так далее.
блин! где ты раньше был?
[ушёл делать переучёт в имперском хранилище байтов]
*привет всем.
Косяк, совсем запарили, конечно char 1 байт, имелось в виду 8 бит. Пообщаешся с чудо програмистами и терабайта памяти будет мало для проги blink ))))
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
Он такого не утверждает.
Он как раз это и утверждает.
Значение указателя определется его объявлением.
Специально для специалиста по матчасти diger67 набросал небольшой пример:
Вопрос к diger67:
Выполнится ли выражение uc=ud; ?
Как хотите, char-ЭТО 8БАЙТ! и так далее.
блин! где ты раньше был?
[ушёл делать переучёт в имперском хранилище байтов]
*привет всем.
Косяк, совсем запарили, конечно char 1 байт, имелось в виду 8 бит.
блин! блин!
[разбивает кувалдой в дребезги ещё горячие глиняные таблички переучёта и отсылает рабов за клеем для старых-проверенных временем]
То есть diger67 утверждает, что указатель на char имеет размер 1 байт, указатель на int = 2 байта, указатель на double = 4 байта (а в Arduino Duo 8 байт).
Он такого не утверждает.
Он как раз это и утверждает.
Значение указателя определется его объявлением.
Специально для специалиста по матчасти diger67 набросал небольшой пример:
Вопрос к diger67:
Выполнится ли выражение uc=ud; ?
По сути да, с потерей старшего байта.
По сути да, с потерей старшего байта.
Какого старшего байта? В данном примере char имеет размер 1 байт, а double = 8 байт, но указатели на них имеют одинаковый размер (4 байта).
Немного изменим задачу:
Вопрос к diger67:
Какое число напечатает последний printf?
Число вполне конкретное и зависит от исходных данных. На основании своего многолетнего опыта программирования на Си и Ассемблере для разных процессоров и контроллеров, я могу его сосчитать без запуска программы на компиляцию. Сможет ли так специалист по матчасти diger67?
По сути да, с потерей старшего байта.
Какого старшего байта? В данном примере char имеет размер 1 байт, а double = 8 байт, но указатели на них имеют одинаковый размер (4 байта).
Немного изменим задачу:
Вопрос к diger67:
Какое число напечатает последний printf?
Число вполне конкретное и зависит от исходных данных. На основании своего многолетнего опыта программирования на Си и Ассемблере для разных процессоров и контроллеров, я могу его сосчитать без запуска программы на компиляцию. Сможет ли так специалист по матчасти diger67?
Можете расчитывать все с карандашиком на бумажке, это очень полезно. Сам иногда так делаю в поиске ошибок. Реже прогуливаясь с внуком в парке анализирую в уме алгоритм, прихожу домой правлю программу на основе пришедших мыслей. Хотя используя дебагер в пошаговом режиме проще найти ошибку, потому как видишь что в реале происходит в кишках камня. Речь не об этом. Говорилось о том, что через указатели можно работать с таблицей знакогенератора немного сэкономив память программ. Но вы так увлеклись самолюбованием и попыткой донести до всех какой вы классный, что перевели разговор в иную плоскость. Да и под матчастью подразумевалось понимание архитектуры камня. Саркастичный вы наш.
Но вы так увлеклись самолюбованием и попыткой донести до всех какой вы классный, что перевели разговор в иную плоскость. Да и под матчастью подразумевалось понимание архитектуры камня. Саркастичный вы наш.
По себе людей не судят. Вы назвали меня лузером и направили на изучение матчасти в том вопросе, в котором сами не разбираетесь. С карандашиком не удалось сосчитать?
При объявлении указателя типа char *c или long int *l соответственно char и long int указывают компилятору какого типа и размера данные по адресу указателя надо брать. А размер самого указателя зависит от процессора и адресуемой памяти и одинаков для всех переменных, что и показано в примерах.
Как специалист по архитектуре камня diger67 должен знать, что большие целочисленные переменные типа long int размещаются в памяти начиная с младшего разряда. Этот младший разряд через указатель *uc (в последнам принте) мы и вынимаем. У числа 1026 младший разряд будет 2 и к нему мы прибавляем 1. Получаем ответ: 3
Но вы так увлеклись самолюбованием и попыткой донести до всех какой вы классный, что перевели разговор в иную плоскость. Да и под матчастью подразумевалось понимание архитектуры камня. Саркастичный вы наш.
По себе людей не судят. Вы назвали меня лузером и направили на изучение матчасти в том вопросе, в котором сами не разбираетесь. С карандашиком не удалось сосчитать?
При объявлении указателя типа char *c или long int *l соответственно char и long int указывают компилятору какого типа и размера данные по адресу указателя надо брать. А размер самого указателя зависит от процессора и адресуемой памяти и одинаков для всех переменных, что и показано в примерах.
Как специалист по архитектуре камня diger67 должен знать, что большие целочисленные переменные типа long int размещаются в памяти начиная с младшего разряда. Этот младший разряд через указатель *uc (в последнам принте) мы и вынимаем. У числа 1026 младший разряд будет 2 и к нему мы прибавляем 1. Получаем ответ: 3
Читайте внимательнее, был создан массив указателей в PROM, которое чаще называют смещением, используя указатели они использовались для перекодировки символов и их корректного вывода. Сначала ознакомтесь с темой обсуждения. А потом начинайте мериться у кого длиннее. Может я не так силен в использовании указателей. Что же, не всем быть такими гениальными как вы. Для решения моих задач мне моих знаний хватает. Продолхайте трясти своим ..... только слюной не надо брызгать.
Ещё один пример уже для всех (может кому пригодиться):
После выполнения программы получаем:
С помощью выражений типа *(uc+1) получаем следующие разряды long int, а в последнем printf мы распечатываем число long int как строку.
Должен предупредить, что компилятор (Borland C++ 5.5.1 for Win32) предупреждает о подозрительном преобразовании uc=ul, но компиляцию проводит. В Arduino компилятор более строгий и на операции uc=ul выдаёт ошибку.
Ещё один пример уже для всех (может кому пригодиться):
После выполнения программы получаем:
С помощью выражений типа *(uc+1) получаем следующие разряды long int, а в последнем printf мы распечатываем число long int как строку.
Должен предупредить, что компилятор (Borland C++ 5.5.1 for Win32) предупреждает о подозрительном преобразовании uc=ul, но компиляцию проводит. В Arduino компилятор более строгий и на операции uc=ul выдаёт ошибку.
Что и требовалось доказать, восми разрядный процессор координально отличается от 32-х и выше. О чем я и предупреждал давая код под stm32, что его нужно рехтовать под AVR. Иначе компилятор выдаст ошибку.
упс, промахнулся со ссылкой http://robocraft.ru/blog/892.html
упс, промахнулся со ссылкой http://robocraft.ru/blog/892.html
Все бы ничего, только одна прблемма. У andriano не получается спользовать данную адресацию. При использовании стандартных настроек компилятора IDE Arduino, корректно отображается только латиница. Русский шрифт начинается с адреса 0xC0. Вот и надо заниматься перекодированием или городить массив масок с учетом сдвига.
упс, промахнулся со ссылкой http://robocraft.ru/blog/892.html
Еще раз: в этой статье автор пишет откровенный бред. Цитирую:
...
Меня осенила здравая идея — проверить в какой кодировке работает Arduino IDE.
Выяснилось — работаем в UTF-8. Берем таблицу кодировки и получается что:
диапазону 0x80 — 0x8F соответствуют маленькие буквы от «р» до «я»
с 0x90 и до 0xAF идут заглавные по порядку «А» — «Я» исключая «Ё»
и в хвосте с 0xB0 до 0xBF маленькие от «а» до «п».
Для тех, кто не в курсе, поясняю:
1. utf-8 - является кодировкой с символами переменной ширины.
2. в utf-8 не используется диапазон номеров символов с 0х80 по 0xff.
Как то плавненько разговор сместился от конструктива к болтовне. Предлагаю вернуться к конструктиву. К сожалению сейчас совершенно нет времени заняться любимым и полезным, а потому поделюсь как делаю значки 8х5 в програмке LCD1602 v1.1
1. Сначала надо загрузить таблицу символов через File -> Load Table.
Загружаем Epson.chr. И получаем таблицу символов как на первом изображении.
2. Если мы отим отредактировать любой символ из таблицы, или нарисовать свой неповторный элемент, то щелкаем правой кнопкой мыши на любом прямоугольнике в таблице символов справа и получаем возможность редактирования данного символа через контекстное меню Edit Char.
3. Увлеченно щелкая левой кнопкой мышки по желтым квадратикам, окрашиваем их в черный цвет, а щелкая правой кнопкой мышки по черным квадратикам, возращаем им первозданную желтизну, одновременно наблюдая в окошечке Data изменение в реальном времени кода данного шедевра. Дополнительные кнопки позволяют нам очистить все, или инвертировать все. И в итоге код данного символа можно скопировать в текст программы, что очень подходит для создания небольших значков, когда они так нужны.
С уважением ко всем участникам. Пользуйтесь.
Не знаю как добавлять файлы для скачивания, а потому загрузил файл программы в архиве zip как изображение jpg. Может получится скачать. Файл называется lcd1602.zip_.jpg
Даже и не понятно что-то..как воспользоваться?
Добрый день!
подскажите "легкую" библиотеку для вывода текста для 1306 по I2C
типа такой:
https://github.com/stanleyseow/ArduinoTracker-MicroAPRS/tree/master/libraries/SSD1306_text
А чем не устраивает та, что опубликована в этой теме?
Не запустилась(
похоже, при копировании - вставке "портится"
Arduino 1.5.8 - вываливается с ошибками
1.6.5 ошибка out of memory
Выложите пожалуйста библиотеку в виде архива
а ты для какой платы компилируешь?
Uno | nano
ssd1306 i2c
подскажите "легкую" библиотеку для вывода текста для 1306 по I2C
Adafruit_SSD1306: https://github.com/adafruit/Adafruit_SSD1306
Руссификация её здесь: http://arduino.ru/forum/programmirovanie/rusifikatsiya-biblioteki-adafru...
Спасибо, но это немного не то.
Adafrut занимает слишком много памяти,
по моей ссылке adafrut без графики, занимающий мало места, но он под SPI
А мне нужен I2C
Русский необязателен
Нужен I2C, это не так сложно, напишите библиотеку передачи по I2C и прикрутите к ней adafruit. Я например перенес библиотеку adafruit на ядро stm32arduino. Правда большинство компиляторов не поддерживают C++. Но получилось и на C. Библиотека позволяет рисовать все приметивы. контуры и заполненные поля, выводить текстовую информацию, при этом используется шина FSMC 16 bit, что снижает нагрузку на ядро процессора, т.е. управление передачей данных происходит на уровне железа. Сейчас решаю проблемму использования DMA для вывода с SD на TFT графических изображений. AVR конечно более оброс примерами и библиотеками, но возможности ARM процессоров гараздо выше и по частоте ядра, и по перефирии, и по разрядности внутренней шины.
Не запустилась(
похоже, при копировании - вставке "портится"
Arduino 1.5.8 - вываливается с ошибками
1.6.5 ошибка out of memory
Выложите пожалуйста библиотеку в виде архива
http://my-files.ru/y220un
мой антивирус на приведенную выше ссылку ругается, вот в другом месте:
https://cloud.mail.ru/public/BcsP/oQKUneR7U
Спасибо Большое, все заработало!
Подскажите, как почистить содержимое строки или символа, не трогая другие элементы?
Спасибо Большое, все заработало!
Подскажите, как почистить содержимое строки или символа, не трогая другие элементы?
Записать туда строку из пробелов.
первая ссылка сдохла, во второй архив запакован не по правилам Arduino (это поправимо).
Но главное - при компиляции ругается:
Tomasina, я вообще-то не С-шник, но, насколко я понимаю, я использовал здесь некоторое расширенме синтаксиса по сравнению со стандартом. При моих настройках IDE (настройки по умолчанию) компилятор это пропускает, при Ваших - нет.
Могу предложить в декларации класса (файл *.h) отказаться от присвоения значений:
А в конструкторе либо в методе init() - присваимвать нужные значения (файл *.cpp):
Не плохо бы добавить описание уже имеющихся функций библы. А то новичкам тяжко разобратся... Я вот например не могу понять как нарисовать прямоугольник... Подскажите пожалуйста...
Не плохо бы добавить описание уже имеющихся функций библы. А то новичкам тяжко разобратся... Я вот например не могу понять как нарисовать прямоугольник... Подскажите пожалуйста...
Никак. Библиотека для этого не предназначена.
Ту альтернатива простая: либо ты жертвуешь 2/3 всей доступной оперативной памяти под экранный буфер и рисуешь, что хочешь, либо экономишь память ценой отказа от графики. В данной библиотеке (в отличие от Adafruit) выбран второй вариант.
Вывести можно только готовый битмап, причем, если ширина битмапа произвольна, то высота должна быть кратна 8 пикселям.
В Adafruit и UTFT вся графика пишется непосредственно в RAM TFT контроллера в реальном времени.....
В Adafruit и UTFT вся графика пишется непосредственно в RAM TFT контроллера в реальном времени.....
Отнюдь.
В Adafruit_GPX реализация самого доступа к экрану отсутствует, объявлена как virtual.
А в конкретной библиотеке Adafruit_SSD1306 объявлен буфер:
И весь вывод осуществляется именно в буфер:
А, ну да. Я совсем упустил из вида, что мы говорим о разных концепциях. В адафрут виртуал используется для определения функции, котора в последствии может быть переопределена в конкретном классе. Это делается для снятия конфликтов при наследовании. Где вы видили там виртуальные переменные. Все вычесленные значения пишутся непосредственно в GGC TFT. Ваш метод работает только если используются заранее готовые кластеры и корректно они будут работать только если их размеры строго одинаковы. Думаю что описание пазлов из кластеров разных размеров и конфигураций займет куда больше памяти и времени на обработку, чем пиксельная графика. Вывод, библиотек удобна только в случае вывода текста.