Последние события показывают, что предпоследние события были лучше.

Меню навигации для мобильных

Матричные шрифты вывести на экранчик. Проблема?

Автор Slabovik, 19 Фев., 2024, 17:45

« предыдущая - следующая »

Slabovik

Добрый день.
Интересный момент. Оказывается, процедуру вывода матричных шрифтов на экранчик, чуть ли не каждый раз приходится писать по-новой. Привык - нормально, но поначалу эти битовые перестановку могут показаться кошмаром.
Предлагаю устроить здесь разборки на тему "кто и как выводит".

Вообще, матричный шрифт относится к моноширным шрифтам с фиксированным размером и, как понятно из названия, представляет собой просто битовую матрицу, в которой закодированы пиксели символов, точнее, светятся они, или погашены.

Символ-ДВА.png

Вот так они кодируются. На картинке символ с размером 12x18. 12 точек в ширину, 18 в высоту.
Точки кодируем битами. Значением '1', а погашенные -'0', но это чистая условность - можно и наоборот и даже зашифровать  ;) Но не будем - такая вот форма логически проста и, что немаловажно, визуально проста - можно весь шрифт набрать вручную.
Биты собираются в байты, байты собираются в массив.

Поскольку ширина шрифта-примера больше 8 бит байта, но не дотягивает 16 бит двух байт, каждая строчка всё-равно представлена двумя байтами. Просто 4 бита не используются, а потому в принципе могут содержать абсолютно любую информацию. Но пока не засовывам туда ничего и просто игнорируем.

В самом простом случае запись с данными шрифта представляет собой байтовый массив, типа

const unsigned char MyFont[] { // ... здесь байты символов, идущих перед нашей '2'

0,0,0x1F,0x80,0x30,0xC0,0x60,0x60,0x60,0x60,0x20,0x60,0,0x60,0,0xC0,1,0x80,7,0,0xC,0,0x18,0,0x30,0,0x60,0,0x60,0x60,0x7F,0xE0,0,0,0,0, // это байты нашей '2'
 // ... дальше байты других символов
};

Кстати, кроме этого надо бы определиться с организацией структуры, например, если уж замахиваться на более-менее универсальную процедуру, надо бы ей давать информацию о том, какого размера шрифт она будет выводить, какие символы у нас там есть и т.п.
Щас, подумаем....
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Некоторые шифты можно найти тут:
UTFT Fonts (http://rinkydinkelectronics.com/r_fonts.php)

Программа для создания и редактирования матричных шрифтов:
matrixFont (https://gitlab.com/riva-lab/matrixFont)

Тема на easyelectronics (https://forum.easyelectronics.ru/viewtopic.php?f=35&t=13281&sid=74aee0c483d96c5c102e5900a9f5e650), от которой оттолкнулся.

Ну и count-zero (https://count-zero.ru/2023/st7735/).

Для F0 свои эксперементы сложил сюда (https://github.com/minamonra/my_stm_snippets/tree/main/F0/st7735) (пока не всё допилено).

По поводу структуры, не знаю есть ли какие-то стандарты, но, например шрифты по первой ссылке содержат как раз такую иформацию в первых 4-х байтах.
Программа matrixFont на выходе даёт только массив символов.
Вот сейчас точно не вспомню, но была какая-то программа, которая на выходе давала массив из uint16_t, вот тут не понятно, но мне кажется в таком случае надо раскладывать на два байта.
https://github.com/minamonra/

Slabovik

#2
Оу, MatrixFont ещё живая! С удовольствием стырил себе  8)

Ладно, продолжим.
Получается, каждый набор байт изображения символа, представляется как массив.
Кодов символов обычно 256, часто символы до 20h (32dec) не используются (хотя imho это не совсем правильно).
Если вот такие массивы байт каждого символа располагать один за другим в общем массиве, можно, зная адрес начала всего массива и количество байт, приходящихся на один символ, вычислять адрес начала каждого символа. Это просто.

Но гораздо лучше иметь таблицу адресов символов как массив указателей :: https://metanit.com/c/tutorial/5.6.php
const int *FontSym[] = { &FontSym_x00, &FontSym_x01, &FontSym_x02, ...etc... &FontSym_xFF }; // тут тип int должен полностью вмещать адрес ячейки. Если размер int не достаточен, нужен тип побольше.
Перед этим FontSym_x## должны быть определены как массивы, содержащие коды рисовки конкретных символов.
... ...
const unsigned char FontSym_x2F[] = { ... }; // слэш прямой
const unsigned char FontSym_x30[] = { ... }; // ноль
const unsigned char FontSym_x31[] = { ... }; // единичка
const unsigned char FontSym_x32[] = { 0, 0, 0x1F, 0x80, 0x30, 0xC0, 0x60, 0x60, 0x60, 0x60, 0x20, 0x60, 0, 0x60, 0, 0xC0, 1, 0x80, 7, 0, 0xC, 0, 0x18, 0, 0x30, 0, 0x60, 0, 0x60, 0x60, 0x7F, 0xE0, 0, 0, 0, 0 }; // это наша двоечка из прошлого поста
const unsigned char FontSym_x33[] = { ... }; // тройка
... ...
При такой организации есть сразу несколько фишек.
Первая фишка в том, что сами массивы символов не обязаны идти друг за другом по порядку.
Вторая фишка - символов может быть нарисовано меньше (например, только нужные).
Третья фишка - экономим место за счёт того, что часть символов латиницы и русского выглядят одинаково.
Например, для ASCII CP1251 на месте ссылки на символ xC0 ставим ссылку на x41 (А-A), на месте ссылки на xC2 ставим ссылку на x42 (В-B) и т.д. На местах ссылок отсутствующих (не нарисованных) символов ставим ссылку на какой-нибудь x20 ('пробел') или ещё что-нибудь, чтобы было видно, что "не попал"...

Да, FontSym - это указатель. Его прописываем как константу, чтобы он лёг в ПЗУ.

Как работать.

В функцию вывода нам "прилетает" код символа. Пусть будет это SymCode
используем этот код как индекс для массива : FontSym[SymCode]
Надо иметь указатель в ОЗУ, куда мы достанем адрес матрицы символа с прилетевшим кодом :
Функция вывода символа (SymCode, координаты, цвет, etc...) {
 var int *SymMatrixPtr; // локальная переменная-указатель на матрицу рисуемого символа, про размер int см.выше...
 var unsigned char MatrixCode;
... ...
 SymMatrixPtr = FontSym[SymCode];

По-идее, SymMatrixPtr после этого действия должен содержать адрес самого первого (нулевого) байта массива изображения символа (который на картинке +00 обозначен)
Далее, уже в цикле "разворачивания" битов изображения в байты для посылания на экран, будем читать данные, находящиеся по указателю SymMatrixPtr

MatrixCode = *SymMatrixPtr;

По-идеее, это операция чтения байта кода матрицы символа из памяти ROM в переменную MatrixCode.

После чтения делаем

SymMatrixPtr++; // сдвигаем указатель на следующую ячейку матрицы

Кстати, указателю вообще пофиг на тип данных, на которые он показывает, попадает ли он на те данные, что мы подразумеваем и т.п. Это просто адрес.

зы: просьба меня поправлять, если я где-то ошибся. А ещё очень большая просьба эти функции аккуратно проверять в отладчике. Ибо я и так не силён в Си, дак ещё и по памяти фантазирую без какой-либо проверки...

Ну а следующим этапом пойдёт как раз превращение битов матрицы в байты, посылаемые на экран.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#3
Ну вот я позанудствую, зачем нам создавать кучу констант FontSym_xXX, если у нас и так есть массив констант?
Если используем толко цифры, соответственно массив кромсаем.
А если целиком, то очень удобно строки выводить, задав смещение -0x20.


----
Есть ещё Adafruit gfx font generator, формат немного другой на выходе, присутствует второй массив с описанием каждого глифа.
Онлай версия тут https://rop.nl/truetype2gfx/
Приложение прицепил.
https://github.com/minamonra/

Slabovik

#4
Таблица констант-ссылок - Это унификация.
А ещё экономия места за счёт одинаково выглядящих символов с разными кодами. Например, символы от 0 до 31 (dec) можно легко откусить вычитанием, но что делать, когда какие-то из них надо всё-таки нарисовать? Устраивать case? Причём для каждого шрифта своё собственное? Проще сделать таблицу, несуществующие символы направить на символ-пустышку, остальные на реальные изображения.
А экономия за счёт одинаковых. Два одинаковых символа можно нарисовать по одному разу. Вот такой список:

A-А
B-В
C-С
E-Е
P-Р
H-Н
X-Х
O-О
M-М
T-Т
a-а
c-с
e-е
p-р
o-о
x-х
y-у

Это минимум 17 символов. Если рассматривать в рамках шрифта из примера, то 17*36=612 байт долой только за счёт этого.

Далее идут дырки в таблицах. Например, в таблице 1251 их много со 128 кода. Всё выкидывать плохо - там есть нужные символы, и они не подряд. А все подряд в русском языке точно не нужны.

А ещё быстрее. Для получения адреса надо только прочитать из таблицы. Если рассчитывать, то уже понадобится умножать. Впрочем, сейчас операция умножения в процах есть., без неё надо биты поперекладывать, а это долго (привет от старичка 8080 :) )

Согласен, можно сделать по-другому. Входящий код просто сопоставить другому коду через таблицу перекодировки. Это может быть актуально для процессоров с широкой шиной, например таблица перекодировки займёт один на символ, т.е. будет 256 байт. Таблица 16-разрядных ссылок займёт 512 байт. 32-разрядные ссылки, соответственно, килобайт.

Да, давай тогда так и сделаем - будет экономия места. Тогда вся структура будет выглядеть примерно так
const unsigned char SymPosition[255] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... // первые 32 символа - это пустышки. Сама "пустышка" у нас нарисована в позиции 0
 1, // символ с индексом 32 (0x20)- пробел, в таблице это второй по счёту (индекс 1)
 2, // символ '!' (0x21) - индекс 2.
// ... и так далее
В этом случае символы не обязательно должны идти по порядку, поэтому легко сделать на входе ASCII 866, 1251, КОИ - только их направить на свою таблицу соответственно коду. Каких-то символов может не быть, причём в произвольном порядке - на их месте просто прописывается код символа-заглушки.

А дальше

  SymMatrixPtr = &FontSym + SymPosition[SymCode]*SymLength;

здесь SymLength - тоже константа, определённая рядом с шрифтом, определяющая, сколько байт занимает один символ. Хорошо было бы, чтобы она со шрифтом лежала в одной структуре. Это для того, чтобы процедуре дать только ссылку на начало структуры шрифта, а процедура сама бы прочитала нужные константы.

Можешь пояснить, что там четыре байта означают в тех шрифтах?

По-идее, шрифт надо сопровождать такими константами:
SymWidth - количество столбцов (ширина)
SymHeight - количество строк (высота)
SymLenght - длина в байтах одного символа. Причём её можно и вычислять, но взять из таблицы просто быстрее.

блин... тут уже впору шрифт заводить как структуру :: https://prog-cpp.ru/c-struct/

и процедуре вывода скармливать указатель на структуру. Оттуда она всё сама прочитает.
Указатель на шрифт (структуру) можно сделать глобальным, типа переключил шрифт - с ним работаем. А можно в качестве входных данных. Тут от конструкции программы больше зависит.

Что получается

struct Font_12x18 {
    const unsigned char Position[255] = { ... ...}; // должно быть обязательно заполнено
    const unsigned char Width = 12; // количество столбцов (ширина) - это пример в ширину 12-точечного
    const unsigned char Height = 18; // количество строк (высота) - наш 18-строчный
    const unsigned char Lenght = 2; длина в байтах одного символа.
// здесь можно вставить один байт для выравнивания. Мало ли...
    const unsigned char Matrix_00[36] = {.. .. .. ...}; символ на позиции 0 'заглушка'
    const unsigned char Matrix_01[36] = {.. .. .. ...}; символ на позиции 1 'пробел'
    ... ...
    const unsigned char Matrix_xx[36] = {.. .. .. ...}; символ на позиции xx
}; // конец структуры
Вот я никак не понял, перед struct нужно ли указать, что она const? Можно ли написать
const struct Font_12x18 .... и не писать внутри у каждого значения const. Попробуй найти...

В общем, получается структура. У ней первые 256 (с 0 по 255) таблица перекодировки. Ещё 4 байта - данные о шрифте. Далее изображения букв.

зы: щас самое неприятное - структура может быть просто массивом.


В процедуре на входе получается {код_символа, позиция, цвета, указатель_на_структуру}

//считаем данные
SymMatrixPtr = указатель_на_структуру + код_символа;
MatrixNum = *SymMatrixPtr; считали номер матрицы, соответствующий коду символа;

SymMatrixPtr = указатель_на_структуру + 256; // Засунули в локальную переменную указатель. Он сейчас показывает на байт с шириной

CharWidth = *SymMatrixPtr; // считали ширину

SymMatrixPtr++;
CharHeight = *SymMatrixPtr; // считали высоту

SymMatrixPtr++;
CharLength = *SymMatrixPtr; // считали длину символа

SymMatrixPtr = указатель_на_структуру + 260 + MatrixNum*CharLength; // вот здесь умножение всплыло

Теперь у нас заполнены локальные переменные и SymMatrixPtr показывает на первый байт матрицы символа.


эх, на деле рассказывать сложнее, чем писать самому. Потому что чуть изменил условия - и всё начинай сначала...
Вообще, по-простому, я бы не структурой делал, а индексным байтовым монолитным массивом. Структуры становятся интересны, когда они переменные.

Если объявлять монолитный массив, то его длина будет получаться (260 + кол-во_символов*длина_символов)
При этом индексы от 0 до 255 - это перекодировка (соответствие),
256 - щирина,
257 - высота,
258 - кол-во байт,
259 - резерв на выравнивание (может нужен будет)
260... матрицы символов.

Тут проще, т.к. можно через индекс доставать данные:

MatrixNum = Font12x18[код_символа];
CharWidth = Font12x18[256];
CharHeight = Font12x18[257];
CharLength = Font12x18[258];
MatrixIndex = 260 + MatrixNum*CharLength; // MatrixIndex содержит индекс первого (нулевого) байта содержащего изображение символа.
Далее достаём байты и превращаем из в поток фон-символ.

А если через указатели - будет также, как выше. Через указатели универсально, т.к. указатель может показывать на любой фонт. Указатель можно с индексом делать, а можно его самого корректировать. По-идее, корректировать указатель код должен быть даже короче, хотя с точки зрения написания выглядит хуже...

Что-то мне подсказывает, что правильно вначале объявить структуру:

struct Font_12x18 { .. описание};

а затем сделать

const Font_12x18 FontName = {и здесь заполнить};


Т.е. struct - это вроде определения типа, а затем этот тип заполняем. Но это не точно... Проверишь?  ;)
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#5
Так, минутучку, всё это хорошо, можно и нужно свой велосипед изобретать (чем мы частенько и занимаемся).
Но задача, от которой всё пошло - интерфейс под 1,77" TFT дисплей, в часности шрифты, причём такие, чтобы нравились.
Одним из лучших считаю SevenSegment, но размеры готовых, которые нашёл это 32х50 и 32х46 для упомянутого дисплея годятся только в случае отображения одной строкой основного значения, например частоты, или времени, двумя строками уже выглядит не очень.
Понравились два шрифта (оттуда же) Ubuntu и Inconsola, их выводить у меня получилось, а вот строчку из функции печати символа я так и не распарсил.
Конкретно эту:
d1 = CH * 96 + ((b - 1) * 3 + i );
такая она, когда вывожу шрифт Inconsola, для шрифта Ubuntu она такая:
d1 = CH * 96 + ((b - 1) * 3 + i + 4);
Функция:
↓ спойлер ↓
#include "Ubuntu.h"
#include "Inconsola.h"

void print_char_24x32_land(uint8_t CH, uint8_t X, uint8_t Y, uint16_t fcolor, uint16_t bcolor)
{
  uint8_t j, i, b, d;
  uint16_t d1, color;
  CS_DN;
  lcd7735_at(X, Y, X + 31, Y + 23); // Ширина и высота шрифта от 0
  lcd7735_sendCmd(0x2C);
  SPI2SIXTEEN;
  DC_UP;
  for (i = 0; i < 3; i++) { // 3 байта в строке матрици 3*8 = 24 FONTWIDTH
    for (j = 8; j > 0; j--) { 
      for (b = 32; b > 0; b--) { // 32 строки в матрице FONTHEIGHT
        //d1 = CHP + ((b - 1) * 3 + i );
        d1 = (CH * 96 + ((b - 1) * 3 + i + 4);
        d = Ubuntu[d1];
        //d = Inconsola[d1];
        if (d & (1 << (j - 1))) color = fcolor; else color = bcolor;
        while (!(SPI1->SR & SPI_SR_TXE)){};
        SPI1->DR = color;
      }
    }
  }
  while (!(SPI1->SR & SPI_SR_TXE) || (SPI1->SR & SPI_SR_BSY)){};
  CS_UP;
  SPI2EIGHT;
}
[свернуть]
---
Дальше, вчера пробовал вывести шрифт созданный в MatrixFont, причём условие - строки слева-направо, сверху-вниз соблюдено, но опять како-то непопадание.
Вот тестовый вариант этого шрифта
https://github.com/minamonra/my_stm_snippets/blob/main/F0/st7735/st7735v01_sevensegfont/consolas_20_font.h

---
Те, думаю сначала надо понять как выводить уже готовые шрифты, а потом браться за свой, ну или параллельно.
---
ЦитатаМожешь пояснить, что там четыре байта означают в тех шрифтах?
Вот тит объяснение есть:
http://rinkydinkelectronics.com/h_utft_fonts_101.php
Первые два байта размер, вторые начала в таблице ASCII и количество символов, если я правильно понял иностранный. :)
---
Ещё шрифты на подумать:
https://github.com/immortalserg/AdafruitGFXRusFonts/tree/master/FontsRus
---
Ну и наконец варианты с count-zero, там есть компрессия и процедура создания своих шрифтов тоже описана.
---
ЦитатаНо это не точно... Проверишь?
Да, чуть позже, тут то танцы у дочки, то в разъездах... :)
ы. Ещё ссылочка на шрифты, правда только картинки, но для этого тоже видел способ преобразования
https://github.com/RichardBsolut/GT24L24A2Y
https://github.com/minamonra/

Slabovik

Отрицание - Торг - Гнев - Депрессия - Принятие

Мы щас где-то в начальной стадии :)
На деле очень трудно при изучении программирования, когда волшебство значков уже освоено, заставить себя писать более понятно. Но... надо.
На первом этапе пишешь i, j, k ,l...
На втором они всё-таки превращаются в StringCounter, RowCounter, SkipCounter....
И только потом, когда ты окончательно запутываешься, начинаешь писать

var int SkipCounter; // счётчик выведенных вверх за позицию окна строк от начала текста
...

Как-то так ;)

Сейчас задача стоит таким образом:
Придти к осмысленной структуре шрифта. Уже я настаиваю, чтобы у шрифта был более-менее универсальный заголовок, одинаковой структуры для всех и не ограничивающих возможности в рамках всех 256 байт-кодов символов. Только наличие этого свойства уже даст возможность сделать процедуру вывода универсальной - ей будет всё-равно, какие символы есть у выводимого шрифта и какого они размера - это процедура просто возьмёт из заголовка.
Если этого не сделать, к каждому шрифту вынужденно будет тащиться его собственная процедура вывода, работающая только с этим шрифтом. Конечно, когда шрифт один - это пофиг, а когда четыре-пять?

Так что на данный момент задача из двух частей:

а) составить пару-тройку шрифтов по такой структуре в виде .h файлов, скажем, шрифт 8x14, 12x20, 24x40 (по вкусу, но как минимум ширина одного шрифта ровно в байты попадает, одного шрифта - не кратна байтам).

б) добиться от написуемой процедуры вывода считывания CharWidth, CharHeight, CharLength и правильной постановки указателя на первый байт (левый верхний) матрицы символа. Всё это делать в отладчике, ну или в CОМ-порт плевать можно, чтобы в компе на терминале результат смотреть. На производство вывода непосредственно на экран настоятельно рекомендую на данном этапе установить табу, как бы ни хотелось смотреть именно на нём...

Как будут правильно выставляться эти данные для любого символа любого шрифта (с нашим заголовком), перейдём к процедуре превращения байтов в битовый поток и уже его превращение в байты для пикселей экрана.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Те, что-то типа этого:
↓ спойлер ↓
const unsigned char inconsola24x32bitmaps[] = {
// 16 символов
// В строке 96 байт
0x00,0x10,0x00,0x00,0xFC,0x00,0x01,0xFE,0x00,0x03,0xC7,0x00,0x03,0x83,0x80,0x07,0x01,0x80,0x06,0x01,0xC0,0x06,0x03,0xC0,0x0E,0x07,0xC0,0x0E,0x0E,0xC0,0x0E,0x1C,0xE0,0x0C,0x18,0xE0,0x0C,0x38,0xE0,0x0E,0x70,0xE0,0x0E,0xE0,0xE0,0x0E,0xC0,0xC0,0x0F,0xC0,0xC0,0x07,0x80,0xC0,0x07,0x01,0xC0,0x07,0x01,0x80,0x03,0x83,0x80,0x03,0xC7,0x00,0x00,0xFE,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 0
0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x3E,0x00,0x01,0xFE,0x00,0x00,0xC6,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 1
0x00,0x10,0x00,0x00,0xFE,0x00,0x01,0xFF,0x00,0x03,0x87,0x80,0x07,0x01,0xC0,0x02,0x01,0xC0,0x00,0x01,0xC0,0x00,0x00,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x07,0x00,0x20,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 2
0x00,0x00,0x00,0x00,0xFC,0x00,0x03,0xFF,0x00,0x07,0x07,0x00,0x02,0x03,0x80,0x00,0x01,0x80,0x00,0x01,0x80,0x00,0x01,0x80,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x1E,0x00,0x00,0x7C,0x00,0x00,0x7F,0x00,0x00,0x07,0x80,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x02,0x01,0xC0,0x02,0x03,0x80,0x07,0x87,0x80,0x03,0xFF,0x00,0x01,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 3
0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x0F,0x00,0x00,0x0F,0x00,0x00,0x1F,0x00,0x00,0x3F,0x00,0x00,0x37,0x00,0x00,0x67,0x00,0x00,0x67,0x00,0x00,0xC7,0x00,0x01,0xC7,0x00,0x01,0x87,0x00,0x03,0x07,0x00,0x07,0x07,0x00,0x06,0x07,0x00,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 4
0x00,0x00,0x00,0x03,0xFF,0xC0,0x03,0xFF,0xC0,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x07,0x00,0x00,0x07,0xFE,0x00,0x07,0xFF,0x00,0x07,0x87,0x80,0x07,0x01,0xC0,0x00,0x01,0xC0,0x00,0x00,0xC0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xC0,0x02,0x01,0xC0,0x0E,0x01,0xC0,0x07,0x87,0x80,0x03,0xFF,0x00,0x01,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 5
0x00,0x08,0x00,0x00,0x7F,0x00,0x00,0xFF,0xC0,0x01,0xC1,0x80,0x03,0x80,0x80,0x03,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x06,0x00,0x00,0x06,0x3E,0x00,0x06,0xFF,0x00,0x07,0xC7,0x80,0x07,0x81,0x80,0x07,0x01,0xC0,0x06,0x00,0xC0,0x06,0x00,0xC0,0x06,0x00,0xC0,0x06,0x00,0xC0,0x07,0x00,0xC0,0x03,0x01,0xC0,0x03,0x81,0xC0,0x01,0xC3,0x80,0x00,0xFF,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 6
0x00,0x00,0x00,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 7
0x00,0x18,0x00,0x00,0xFE,0x00,0x01,0xFF,0x00,0x03,0x83,0x80,0x03,0x01,0x80,0x07,0x01,0xC0,0x07,0x01,0xC0,0x03,0x01,0xC0,0x03,0x83,0x80,0x01,0xC7,0x00,0x00,0xFE,0x00,0x00,0x7C,0x00,0x01,0xFF,0x00,0x03,0xC7,0x80,0x07,0x03,0x80,0x07,0x01,0xC0,0x06,0x00,0xC0,0x0E,0x00,0xE0,0x0E,0x00,0xC0,0x06,0x00,0xC0,0x07,0x01,0xC0,0x07,0x83,0x80,0x03,0xFF,0x80,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 8
0x00,0x10,0x00,0x00,0xFE,0x00,0x01,0xFF,0x00,0x03,0x87,0x80,0x07,0x03,0x80,0x07,0x01,0xC0,0x06,0x01,0xC0,0x06,0x00,0xC0,0x06,0x00,0xC0,0x06,0x00,0xC0,0x07,0x00,0xC0,0x07,0x01,0xC0,0x03,0x83,0xC0,0x03,0xFE,0xC0,0x00,0xFC,0xC0,0x00,0x20,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x02,0x03,0x80,0x03,0x0F,0x00,0x07,0xFE,0x00,0x01,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 9
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // <space>
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // :
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // .
0x00,0x20,0x00,0x00,0x30,0x00,0x00,0x30,0x00,0x00,0x30,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0xFC,0x00,0x00,0xCC,0x00,0x00,0xCE,0x00,0x01,0x86,0x00,0x01,0x86,0x00,0x01,0x87,0x00,0x03,0x03,0x00,0x03,0x03,0x80,0x03,0xFF,0x80,0x07,0xFF,0x80,0x06,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x00,0xC0,0x0C,0x00,0xE0,0x1C,0x00,0xE0,0x1C,0x00,0x70,0x18,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // A
0x00,0x00,0x00,0x1C,0x00,0x70,0x0C,0x00,0x60,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x06,0x00,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x03,0x01,0x80,0x03,0x81,0x80,0x03,0x83,0x80,0x01,0x83,0x00,0x01,0xC3,0x00,0x01,0xC7,0x00,0x00,0xC6,0x00,0x00,0xE6,0x00,0x00,0xEE,0x00,0x00,0x6C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // V
0x00,0x00,0x00,0x18,0x00,0x30,0x18,0x10,0x30,0x1C,0x10,0x30,0x1C,0x18,0x30,0x1C,0x18,0x70,0x0C,0x38,0x60,0x0C,0x3C,0x60,0x0C,0x3C,0x60,0x0C,0x6C,0x60,0x0E,0x6C,0x60,0x0E,0x6E,0x60,0x06,0x66,0xC0,0x06,0xC6,0xC0,0x06,0xC6,0xC0,0x06,0xC7,0xC0,0x07,0x83,0xC0,0x07,0x83,0xC0,0x07,0x83,0x80,0x03,0x83,0x80,0x03,0x01,0x80,0x03,0x01,0x80,0x03,0x01,0x80,0x03,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // W
};

typedef struct {
  unsigned int offset;
  unsigned char width, height;

} Font;

const Font inconsola24x32numfont[] = {
  { 0, 24, 32},
  {96, 24, 32}
}
[свернуть]
https://github.com/minamonra/

Slabovik

Да, именно.
Только надо засунуть в начало заголовок с таблицей соответствия кодов символов и данные с размерами.
Таблица соответствия решит вопрос о фильтрации - о ней уже не надо будет задумываться.
Данные о размерах дадут возможность их не высчитывать, а просто брать и грузить по мере надобности.

Если не хочется структуру (я сам не могу чётко сделать описание, потому как просто нифига не помню, как правильно), можно просто обойтись массивом. В принципе, проблем не доставит т.к. эта структура по факту константа и нам реально надо, чтобы это был байтовый массив.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

↓ спойлер ↓
Цитатапотому как просто нифига не помню
А я нифига не знаю, так как учил-то паскаль. :)
[свернуть]
Так, ладно вот напридумывал, шрифт не весь, для упрощения.
Как только теперь этим пользоваться... ?
Особенно указателями.
https://github.com/minamonra/font_test/blob/main/matr_font_sl_01/main.c
Проект в segger, можно скачать и открыть.
https://github.com/minamonra/

Slabovik

Указателями пользоваться просто. В Паскале без них тоже трудно - все динамические данные на указателях работают.

Указатель - это такая же переменная, просто содержащая физический адрес.

var char Sign ; // Sign - переменная. Понятие абстрактное, но удобное.
    int *CharPointer ; // это указатель. Тип int - четыре байта - это как раз размер 32-битного адреса.
    char BytesArray[255] ; // это массив (без const он попадёт в ОЗУ, но для примера это не важно)


Фактически, если указывать CharPointer, то такая штука работает как переменная. Её можно читать, подсчитывать, складывать, делить и т.п.

Чтобы указатель стал иметь смысл, он должен куда-то показывать. Т.е. ему надо присвоить значение.

CharPointer = &Sign ; & - это операция взятия адреса. &Sign означает "адрес Sign".

Таким образом, CharPointer теперь содержит адрес ячейки, в которой лежит значение переменной Sign.

Сейчас интересное.
Взять данные из ячейки (байта), куда показывает указатель

  Temp = *CharPointer ; // в Temp попадёт значение переменной Sign - это потому что CharPointer туда "смотрит"

а если вот так

  Temp = CharPointer ; // в Temp попадёт значение переменной-указателя CharPointer (размерность Temp пока опустим).

И ставим указатель на массив, на его начало

  CharPointer = *BytesArray ; вот так просто.

Если надо на какой-то элемент массива (вдруг там не char, а набор строк неопределённой длины)

  CharPointer = *BytesArray[j] ; указатель смотри на ячейку с элементом под номером j массива BytesArray

Удобство указателей в том, что имея какую-то структуру, её можно двигать по памяти динамически. Она перестаёт быть привязанной к конкретному месту, структур можно заводить много, просто выделяя для них память. Причём ка ОЗУ, так и ПЗУ.

И фишка в том, что структура имеет определённое месторасположение своди данные относительно её начала. Таким образом, зная структуру и её расположение (адрес первого байта), легко достаём из неё данные, где бы они ни находились.

Что касается нашей структуры, уже повторю, что нет острой необходимости её определять как структуру (хотя надо бы).
Мне запись в matr_font_sl_01 пока не видится правильной, ну просто из-за того, что нырок слишком глубокий. Берём помельче (пока побольше работы руками)

Простой массив

const unsigned char Font12x18[] = {  // первые 256 байт - перекодировка

по принципу: входящий код символа является индексом для таблицы, данные по которому соответствуют порядковому номеру (позиции в общем нашем массиве) матрицы изображения этого символа. Тут только 256, без вариантов. Если первые 32 символа отсутствуют - эти указатели должны всё-равно показать на какой-то символ, на пробел, или вон квадрат часто используют, видел поди.

Затем продолжаем заполнять массив.
Надо заполнить данные: Ширина символа, Высота символа, Длина символа в байтах, и пустышка 0 (уже говорил, что не придумал, что сюда засунуть, но 4 байта - это ровно. Пока только поэтому.)

   12, 18, 36, 0, // всё.

/* позиция 0 -- символ "ПРОБЕЛ" */
   и здесь 36 байтов матрицы символа "пробел"

/* позиция 1 -- символ "!" */
   и здесь 36 байтов матрицы символа "!"

и так далее.

Важно! Нужна хотя бы одна матрица символа. Обычно это символ-заглушка, либо пробел.

 Первые 256 байт должны показывать только на существующие позиции. Если символа, соответствующего входящему коду, нет, то он должен показывать на символ-заглушку.

И в конце }

Длина массива - какая получится, т.е. не определяем сразу, но следим за количеством байт в каждом её участке.

 
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#11
Ну ты меня с массивом окончательно запутал, какой массив делаем?
Про основы указателей я конечно знаю (местами недопонимаю), уж передачу в функции указателя и возвращение значений делал, а вот их использование в структурах пока нет.

:: добавлено 21 Фев., 2024, 16:24
И что-то не понимаю, как тут перемещаться по массиву:
typedef struct {
  unsigned char charcode;
  unsigned int offset;
  unsigned char width, height;
} Glythmap;

const Glythmap inconsola24x32numfont[] = {
  //charcode offset   width  height
  {48,            0,     24,     32}, // 0
  {49,          192,     24,     32}, // 1
  {50,  288, 24, 32}, // 2
  {51,  384, 24, 32}, // 3
  {52,  480, 24, 32}, // 4
  {53,  576, 24, 32}, // 5
  {54,  672, 24, 32}, // 6
  {55,  768, 24, 32}, // 7
  {56,  864, 24, 32}, // 8
  {57,  960, 24, 32}, // 9
  {32, 1056, 24, 32}, // space
  {58, 1152, 24, 32}, // :
  {46, 1248, 24, 32}, // .
  {65, 1344, 24, 32}, // A
  {86, 1440, 24, 32}, // V
};



///
ааа.
Вот так же
Glythmap MyGlyth;
MyGlyth = inconsola24x32numfont[1];
charcode = MyGlyth.charcode;


---
ы.
unsigned int Temp = CharPointer;
incompatible pointer to integer conversion initializing 'unsigned int' with an expression of type 'unsigned int *'; dereference with * [-Wint-conversion]

CharPointer = *BytesArray[1];  //вот так просто.
indirection requires pointer operand ('int' invalid)

---
↓ спойлер ↓
unsigned int Sign = 999;    // Sign - переменная. Понятие абстрактное, но удобное.
unsigned int *CharPointer ; // это указатель. Тип int - четыре байта - это как раз размер 32-битного адреса.
char BytesArray[255] ;      // это массив (без const он попадёт в ОЗУ, но для примера это не важно)
CharPointer = &Sign;
unsigned int Temp = *CharPointer;
// Temp = CharPointer ; // в Temp попадёт значение переменной-указателя CharPointer (размерность Temp пока опустим). 
// И ставим указатель на массив, на его начало
CharPointer = *BytesArray[1];  //вот так просто.
на последней строчке
indirection requires pointer operand ('int' invalid)

[свернуть]
https://github.com/minamonra/

Slabovik

#12
Да, тут поди ошибка

CharPointer = &BytesArray[1];

Потому что взятие адреса - это &

По-моему здесь написано: https://stackoverflow.com/questions/38237355/error-indirection-requires-pointer-operand-int-invalid

гы... я дам точный код только тогда, когда сам его отлажу. А пока могу только пнуть в нужном направлении  ::)

И... я не зря упрощаю и прошу так сделать. Объясню любое колено. Однако, если ты делаешь что-то иначе, я прошу тоже объяснять, что именно ты делаешь и что ожидаешь получить (ну или получается). Потому что откатываться на 0, когда уже есть план, достаточно затратно...

Массив же давай сделаем самый простой, как описал выше. 256 байт - индексы, 4 байта - размеры, далее посимвольные матрицы.
Матрицы не обязательно по порядку кодов, главное, чтобы индексы сопоставления кодов с матрицами были верными.

Если он получится структурой - пусть будет структурой. Но его содержание должно быть идентично и точно в том же порядке..
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Цитата: Slabovik от 21 Фев., 2024, 18:54Массив же давай сделаем самый простой, как описал выше. 256 байт - индексы, 4 байта - размеры, далее посимвольные матрицы.
Матрицы не обязательно по порядку кодов, главное, чтобы индексы сопоставления кодов с матрицами были верными.
Так вот я и не пойму, какой массив, вначале массива 4-ре байта служебные, а остальное одинаковые по размеру битмапы?
Или на каждый битмап свой размер, что мне кажется более удачным вариантом, тогда не все символы могут быть одинаковыми, но тут тогда усложнение будет, начало XY для каждого символа.

---
https://github.com/minamonra/

Slabovik

Тот массив, который надо сделать, про который я рассказывал.
Чужие массивы - это отдельно, сейчас не надо на них смотреть. Можно из них стырить сами матрицы. А структуру массива делаем такую:
Цитата: Slabovik от 21 Фев., 2024, 15:30Простой массив

const unsigned char Font12x18[] = {  // первые 256 байт - перекодировка

по принципу: входящий код символа является индексом для таблицы, данные по которому соответствуют порядковому номеру (позиции в общем нашем массиве) матрицы изображения этого символа. Тут только 256, без вариантов. Если первые 32 символа отсутствуют - эти указатели должны всё-равно показать на какой-то символ, на пробел, или вон квадрат часто используют, видел поди.

Затем продолжаем заполнять массив.
Надо заполнить данные: Ширина символа, Высота символа, Длина символа в байтах, и пустышка 0 (уже говорил, что не придумал, что сюда засунуть, но 4 байта - это ровно. Пока только поэтому.)

  12, 18, 36, 0, // всё.

/* позиция 0 -- символ "ПРОБЕЛ" */
  и здесь 36 байтов матрицы символа "пробел"

/* позиция 1 -- символ "!" */
  и здесь 36 байтов матрицы символа "!"

и так далее.

Важно! Нужна хотя бы одна матрица символа. Обычно это символ-заглушка, либо пробел.

 Первые 256 байт должны показывать только на существующие позиции. Если символа, соответствующего входящему коду, нет, то он должен показывать на символ-заглушку.

И в конце }

Длина массива - какая получится, т.е. не определяем сразу, но следим за количеством байт в каждом её участке.

Свой размер на каждый битмап - это потом, к тому же только ширину можно, потому что высота одинакова для всех битмапов шрифта. Сейчас задача - попасть правильно на битмап и разложить его, независимо от размеров.

Индексы - вот это отсебятина, но потом поймёшь, насколько они жизнь облегчат...
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

А charcode (позиция в таблице ASCII) тогда куда?
ы.
Если же с такой структурой:
const Glythmap inconsola24x32numfont[] = {
  //charcode offset   width  height   length
  {48,            0,     24,     32,      96 }, // 0
  {49,          192,     24,     32,      96 }, // 1
То, при моноширном шрифте три крайние константы будут одинаковы для всех, и по сути тут не нужны.
Не, ну ещё больше меня запутал, давай так, используем мои битмапы 24x32, там их 15 штук, и дальше на них уже накручиваем, добавить другие не проблема.
С индексами не понял.
https://github.com/minamonra/

Slabovik

Charcode, который получает процедура, работает индексом для получения номера позиции матрицы в массиве. Более она не нужна. Потому индексы и занимают первые 256 байт, чтобы не надо было ничего пересчитывать. Они нужны таблицей потому что номер позиции математически не определяется - это просто список.

Такая таблица будет ничем не лучше таблицы указателей, которая не понравилась. Она получится большая. Offset - длинное, минимум 16 бит. length - тоже минимум 16 бит. Лишнее.

Пока а) моноширный шрифт б) индексированный массив.

С индексированный массивом можно и через любимое i работать, код слегка больше, а так то же самое.

Новое пока что - только индексная таблица.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#17
Так и где эта индексная таблица? В основном массиве? А сопоставление индекса и битмапа (если битмапов меньше чем 255)?
ы. Сделай уже массив на Си, хотя бы часть, а то жуть какая-то весь день друг-друга понять не можем...  :)  :)  :)  ;D

:: добавлено 21 Фев., 2024, 19:52
А, есть идея, щас.
https://github.com/minamonra/

Slabovik

Гм. Создалось впечатление, что я ничего не писал и мы друг друга абсолютно не понимаем...  :-\

Индексов 256. Потому что Charcode на входе может быть любой из диапазона 0~255

Идём в массив. Первые 0..255 его ячеек - указатели на матрицы.

берём MatrixNumber = FontArray[CharCode];

У нас есть номер матрицы, связывающий CharCode c её реальным положением в массиве.

MatrixNumber всегда показывает на матрицу, которая есть.

Разные CharCode могут показывать через MatrixNumber на одну и ту же матрицу.
Это для того, чтобы одинаково выглядящим символам не рисовать индивидуальные матрицы, а также направлять CharCode, матрицы для которых не определены, на матрицу, используемую в качестве "заглушки".

Это освобождает от необходимости математических вычислений при определении "рисуем этот символ или нет" потому что в общем случае эта математике не определена и для разных шрифтов могут быть определены разные наборы символов.

Это что касается массива. Можно работать так. Но если перейти на указатели, появится возможность эти массивы (т.е. шрифты) менять как перчатки без переписывания процедуры вывода.

Далее, имея MatrixNumber, считаем на основе MatrixLength (т.е. длины в байтах матрицы одного символа) индекс (ну или указатель) на первый байт этой матрицы.
  указатель = matrixNumber * MatrixLength + 260 ; // где 260 - это постоянное смещение из-за индексов и записанных параметров шрифта.

Задача сейчас - прописать контрольный FontArray и добиться правильной постановки указателей соответственно входящему CharCode и имеющихся матриц.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#19
Говорю же, есть идея. :)
https://github.com/minamonra/font_test/blob/main/matr_font_sl_01/myfont.h
Похоже на правду? Там только offset использовать можно пока.
--
Главное надо было сказать, что индексы это второй массив, плнятно что можно без структур, но структуры можно использовать для расширения.
В один массив наверное не надо, его тогда весь надо делать unsigned int.
А вот размером в 255 его делать не обязательно, можно же начать с 32 (пробел).
https://github.com/minamonra/

Slabovik

Glythmap - код, оффсет.

На деле нехорошо т.к. для сопоставления оффсета коду придётся прогонять записи с начала таблицы, проверяя на соответствие.

В самом начале я так и предлагал, только для экономии ресурса не просто оффсет, а сразу адрес матрицы. Но это килобайт для 256 символов.

Немного скукожившись, килобайт меняем на один байт, но добавляем одно умножение и сложение для получения адреса. Умножение... долго, где его нет, но у Меги и STM32 они есть, проблемы не должно быть.

Тут ещё проблема в том, что вот эта таблица оффсетов и сами матрицы символов должны быть единой структурой. Ну чтобы оффсеты-то работали.

Что касается 32... ну глянь ради прикола, там символы есть. Нужные, кстати. Например ← (27) или ♀ (11) + ♂ (12)  = ▲▼ )
Поставив -32 полностью обрежешь возможность их использовать. Поставив в индексах "заглушку" - возможность сохранишь, хотя в каких-нибудь шрифтах хватит и 16 символов, а в каких-то 224 реально мало... И математически  это определить - где какие - невозможно...
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Зачем прогонять, там попорядку всё.
Загоняем в Charcode 32 в
offset = inconsola24x32index[Charcode].offset;
на выходе offset пробела.
Я просто не поубирал оттуда коды символов, они там не нужны по стути, но структуру бы оставить для расширения.
https://github.com/minamonra/

Slabovik

Ок, надо "пояснить по переменным" в том смысле, чтобы путаницы не было, и завтра процедурку осилим :)
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#23
Завтра день нагруженный, но вечером подключусь.  ;)

:: добавлено 21 Фев., 2024, 21:47
На счёт символов до 32-го и других, в конкретном случае, для дисплея 1.77" не вижу в них вообще никакого смысла, даже скобки бы убрал, тк занимают "лишнее" пространство, а некоторые символы можно ручками попиксельно поправить.
Вот пример, в MatrixFont преобразовал шрифт Consolas размером 22pt, на выходе получились матрицы 18x31, скрин ноля:
0-18x31.jpg
Куча пустого места сверху и снизу, если поубирать ненужные, то можно сильно сократить матрицу.

:: добавлено 22 Фев., 2024, 01:39
ыы. Для того же вольтметра достаточно массива из 10-15 символов.
Расположить в порядке цифр, а 10 сделать пробелом, 11 точкой, ну и пару символов V A...
Тогда вывод можно и без индекса делать.

:: добавлено 22 Фев., 2024, 01:45
ыыы. Сконвертированный Consolas шрифт как есть тут.
https://github.com/minamonra/font_test/tree/main/matr_font_sl_01
Ну и myfont.h для экспериментов, только цифры и индексный массив.
https://github.com/minamonra/

Slabovik

Бодаться на тему "а мне это не надо" можно до бесконечности. В вольтметре вообще не стоит проблема шрифтов...

В итоге процедура вывода символа на входе должна иметь:
 - код символа
 - указатель на структуру шрифта (на начало её таблицы индексов/смещений)
 - позиция на экране, куда должен быть выведен символ.
 
Первое, что делает процедура - читает размер шрифта и организует (даёт команду в дисплей) окно для вывода символа

Далее, для вывода любого символа нужны следующие данные:

var unsigned char SymbolWidth - ширина символа в пикселях
var unsigned char MatrixLength - длина матрицы в байтах
var int *MatrixPointer - указатель на первый байт матрицы

Как будет получаться MatrixPointer - дело третье, через номер или через смещение. У каждого способа есть недостатки и преимущества.
Преимущество номера - краткость. 256 байт на всю таблицу.
Недостаток - требуется целочисленное умножение для расчёта смещения.

Преимущество смещения - быстрота. Кроме чтения и сложения никаких действий не требуется. (при этом если указывать не смещение, а абсолютный адрес - int для этого достаточен - и сложения не нужно. Однако это было отвергнуто в самом начале разговора)
Недостатков два. Первый - под таблицу требуется килобайт места. В 4 раза больше, чем для номеров. Второй - его нужно рассчитывать и легко ошибиться. (для ассемблера расчёт, наоборот, прост т.к. делается автоматом по меткам. Для Си я даже не знаю, как такое провернуть).

Резюме: если в процессоре есть операция умножения, по совокупности предпочтительнее номера. Особенно, когда размер шрифта небольшой обидно тратить много места на индексы. Если же операции умножения нет, для сохранения скорости обработки смещения имеют преимущество.

Если шрифт один или пара, без необходимости иметь полный диапазон символов (вольтметры всякие, индикаторы погоды и т.п.), то в этом случае речь об универсальности не идёт и буквы этого шрифта каждый располагает как хочет и выводит как хочет.

/* потребуются ещё вот эти локальные переменные */

var unsigned char MatrixByte; // временная для обработки байта матрицы
var unsigned char BitMask; // маска, накладываемая на байт для получения значения одного бита
var unsigned char BitWidth; // счётчик выведенных по горизонтали точек

/* начало алгоритма вывода. Вывод без поворота
   x матрицы = x символа (ширина)
   y матрицы = y символа (высота)
*/

BitWidth = SymbolWidth ; // начальная установка счётчика

do { MatrixByte = *MatrixPointer ; // чтение очередного байта матрицы
     MatrixPointer = MatrixPointer + 1; // после чтения передвинем указатель на следующий байт матрицы
     MatrixLength = MatrixLength - 1 ; // можно писать просто MatrixLength--; но мне так не нравится...
     BitMask = 0b10000000 ; // предустановка маски и ширины символа на начало для каждого прочитанного байта

     do { if (MatrixByte & BitMask)>0
               { вывод в поток точки цвета символа };
          else { вывод в поток точки цвета фона };

          BitMask = BitMask >> 1 ; // как только бит выедет вправо, BitMask станет равен 0. Значит, вывели все 8 битов в поток
          BitWidth = BitWidth - 1 ; // как только значение станет равным 0. Значит, все биты строки вывели в поток

        } while (BitWidth >0) & (BitMask >0); // если хоть что-то стало 0, надо читать следующий байт - выходим из этого цикла
   
     if BitWidth = 0 { BitWidth = SymbolWidth }; // если выход был по окончании вывода строки - снова предустановим счётчик
                                                 // один раз на символ предустановка лишняя, но организовывать проверку
                                                 // окажется много дороже, чем один лишний раз присвоить значение
   } while MatrixLength >0 ;

Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

Slabovik

#25
Сдвиг вправо. Может быть проблема - надо проверить.
По умолчанию понимаем, что при логическом сдвиге вправо (и влево) на место "освободившегося" бита вписывается '0'. Однако слегка сомневаюсь, что при сдвиге вправо, если старший (знаковый) бит равен 1, в конце концов байт станет 0. При сдвиге с учётом знака, он станет 0xFF.

Здесь конечно явно указано, что байт BitMask беззнаковый, что подразумевает заполнение нулями, но просьба убедиться в этом в отладчике.
BitMask должен принимать значения:
128 - при инициализации
64 - после первого сдвига
32 - после второго
16 - после третьего
8 - после четвёртого
4 - после пятого
2 - после шестого
1 - после седьмого
0 - после восьмого. 0 и вызовет выход из цикла (если он не будет вызван прежде обнулением BitWidth)

Максимальная частота тактирования ST7735 при записи информации 15 МГц
Получается, в режиме RGB (24 бита), в секунду можно перезаписать максимум 625 тыс пикселей. Если дисплей 640x400, то на его перезапись уйдёт 0,4 секунды (без учёта всяких вычислений). В принципе, приемлемо (всё-равно это только гипотетически т.к. чип для дисплеев помельче) :)

Удобнее наверное режим 16 бит/пиксель, хотя бы ровно получается.

Поворот на 90° лучше всего делать командой на дисплей, а не корячиться с подпрограммами
ЦитатаIn vertical addressing mode (MV=1), the Y-address increments after each byte, after the last Y-address (Y=YE), Y wraps around to YS and X increments to address the next column.

In horizontal addressing mode (V=0), the X-address increments after each byte, after the last X-address (X=XE), X wraps around to XS and Y increments to address the next row. After the every last address (X=XE and Y=YE) the address pointers wrap around to address (X=XS and Y=YS).
Впрочем, бывают случаи необходимости текста под 90° к другому тексту...
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#26
Никаких "боданий" нет и в помине, мысли озвучиваю.
Освободился пораньше, для понимания наконец массива и указателя накидал вот такой код:
  const unsigned char Array[] = { 55, 77, 101, 0, 88, 155, 254, 99};
  unsigned char MatrixByte;
  unsigned char *MatrixPointer = Array;
  do 
  { 
    MatrixByte = *MatrixPointer;
    MatrixPointer++;  
  } while (1);
и смотрел в дебаггере (segger позволяет запустить симуляцию без подключенного мк).
Всё норм, толко предупреждение напрягает:
initializing 'unsigned char *' with an expression of type 'const unsigned char[8]' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]


:: добавлено 22 Фев., 2024, 16:41
Аааа.
Надо *MatrixPointer объявлять как const.


:: добавлено 22 Фев., 2024, 17:08
Функция (пока без вывода) у меня получается такой:
// InconsolaNum24x32 массив битмапов символов
// InconsolaNum24x32index его индексы
void print_char(unsigned char CH, uint8_t X, uint8_t Y) {
  unsigned char MatrixByte; // временная для обработки байта матрицы
  unsigned char BitMask;    // маска, накладываемая на байт для получения значения одного бита
  unsigned char BitWidth;   // счётчик выведенных по горизонтали точек
  
  unsigned char SymbolWidth = 24, MatrixLength = 96;
  const unsigned char *MatrixPointer = InconsolaNum24x32;
  BitWidth = SymbolWidth;   // начальная установка счётчика
  MatrixPointer += InconsolaNum24x32index[CH];  // перемещаем указатель на начало символа CH

  // начало алгоритма вывода. Вывод без поворота
  // x матрицы = x символа (ширина)
  // y матрицы = y символа (высота)

  do {
    MatrixByte = *MatrixPointer;       // чтение очередного байта матрицы
    MatrixPointer = MatrixPointer + 1; // после чтения передвинем указатель на следующий байт матрицы
    MatrixLength = MatrixLength - 1;   // можно писать просто MatrixLength--; но мне так не нравится...
    BitMask = 0b10000000;              // предустановка маски и ширины символа на начало для каждого прочитанного байта

    do {
      if ((MatrixByte & BitMask) > 0) {

      } // вывод в поток точки цвета символа
      else {

      }; // вывод в поток точки цвета фона

      BitMask = BitMask >> 1;  // как только бит выедет вправо, BitMask станет равен 0. Значит, вывели все 8 битов в поток
      BitWidth = BitWidth - 1; // как только значение станет равным 0. Значит, все биты строки вывели в поток

    } while ((BitWidth > 0) && (BitMask > 0)); // если хоть что-то стало 0, надо читать следующий байт - выходим из этого цикла

    if (BitWidth == 0)
      BitWidth = SymbolWidth; // если выход был по окончании вывода строки - снова предустановим счётчик
                              // один раз на символ предустановка лишняя, но организовывать проверку
                              // окажется много дороже, чем один лишний раз присвоить значение
  } while (MatrixLength > 0);
}


:: добавлено 22 Фев., 2024, 19:08
Обновил на гитхабе, всё крутится-вертится, осталось координаты прикрутить.

:: добавлено 22 Фев., 2024, 21:07
Записал отладку
https://youtu.be/rYf1KOmkLg4

:: добавлено 23 Фев., 2024, 00:35
Прикрутил координаты.
Всё арбайтн гут!  :D
Не пойму только у 0, 2, 6, 8, 9 вверху точка проскакивает, или это сливается с краем?
https://www.youtube.com/shorts/6CSE6p1n5r0
Код от видео на гитхабе.
https://github.com/minamonra/

Slabovik

Эти точки сверху - они в шрифте есть. Второй байт у нолика - 10h, второй байт у двойки 10h, у восьмёрки 18h, у девятки 10h. Так что выводит так, как нарисовано.

Честно говоря, не понял, почему он требует, чтобы указатель был типа "указатель на массив" и обязательно константа. Тут я... мнэээ... Потому что указатель - это такая фигня, которому должно быть пофиг. Возможно, компилятор перестраховывается и проверяет соответствие типов.

В отладке тоже слегка не понял. Ладно, регистры он показывает (не особо и надо для Си), но главное - это следить за состоянием переменных. Уж год сеггер в руки не брал, но должна быть возможность "вытащить" переменные в окошечко, где и следить за их состоянием по мере шагания по программе.

Поворачивать на 90 будем? Но это будет другая подпрограмма (или просто вторая ветка этой процедуры, но тогда на её входе нужен ещё флаг "поворот"). В эту (в эти циклы) засовывать не хочется ввиду потери быстродействия (даже несмотря на то, что быстродействие и так благодаря SPI не особо).

Да, кстати, на уровне совета.
В циклах ожидания состояния готовности того же SPI, надо бы предусматривать ситуацию, когда готовность (или ещё чего, чего ожидается), не наступает. По-идее, должен быть выход из цикла по таймауту, в какую-нибудь процедуру обработки-вывода (в лог) ошибок.
Но для мелкого применения (не универсального) можно и так.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Цитатано главное - это следить за состоянием переменных
Так в правом верхнем углу как-раз все нужные переменные и есть.
Верхняя как раз BitMask, в двоичном виде за ней наблюдать как раз удобнее, но я в десятичном отобразил, там понятно, только дла записи экрана какую-то софтину нашел, а она пожала сильно видео.
ЦитатаДа, кстати, на уровне совета.
Да, на будущее надо какой-то обработчик ошибок сделать.
Пока не придумал как, советуй. :)
ЦитатаПоворачивать на 90 будем?
Можно попробовать другой функцией.
---
Попробовал шрифт из MatrixFont, - выводит мусор.
Шрифт с индексом тут:
https://github.com/minamonra/font_test/blob/main/matr_font_sl_01/consolas_22_font.h
Не пойму откуда берётся значение дефайна:
#define FONT_CONSOLAS_22_LENGTH         224
---
ы. С праздником!
https://github.com/minamonra/

zenon

Со шрифтами rinkydinkelectronics всё отлично, ещё некоторые попробовал.

Отправил в сниппеты, там же скриншоты (https://github.com/minamonra/my_stm_snippets/tree/main/F0/st7735/st7735sl).
А вот consolas_22 от MatrixFont:
↓ спойлер ↓
1708778487709.jpg
[свернуть]
https://github.com/minamonra/

Slabovik

MatrixFont закодирован в другую сторону. У нас сейчас сдвиг влево, MatrixFont должен сдвигаться вправо.

А вот... я смотрю, так и не попробовал какой-нибудь шрифт не кратной 8 шириной. Или я опять просмотрел, как и режим отладки  ::)

Но тут главное - въехать в алгоритм.

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

Ширину в байтах моно упаковать (если байт экономить) в ширину в пикселях. Отдать под это два старших бита. В шести младших битах хранить ширину в пикселях.

Но, щас подумалось, если делать так, удобнее сделать сложнее: под байты отдать пять старших бит, под биты три младших.
Битов в байте может быть не больше 8, но и 0 тоже не бывает. Поэтом 0 соответствует 1 биту, 1 - двум и т.д.

С байтами та же ерунда. 0 байтов не бывает, значит, это 1 байт и значит, он последний в строке. Количество битов в последнем байте - это записали выше.
Если здесь будет записано

0b 0000 0111 - это значит шрифт шириной 8 пикселей. Длина строки в байтах = ((0b 0000 0111) >> 3) +1 = 1

0b 0001 0011 -  это значит шрифт шириной 2 байта и 4 пикселя. Длина строки = ((0b 0001 0011) >> 3) +1 = 3

Но на самом деле, если надо быстрее - быстрее будет прочитать готовый байт. Тут уже извечный антагонизм компактности и быстроты.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Мне кажется более интересно в индексный файл добавить хотя-бы ширину каждого символа, будет уже веселее.
---
ЦитатаMatrixFont закодирован в другую сторону. У нас сейчас сдвиг влево, MatrixFont должен сдвигаться вправо.
Для проверки сделал так:
↓ спойлер ↓
unsigned char reverse(unsigned char b) 
{
  b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
  b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
  b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
  return b;
}

...
...
MatrixByte    = reverse(*MatrixPointer);     // чтение очередного байта матрицы
...
...
[свернуть]
Результат:
↓ спойлер ↓
1708790881484.jpg
[свернуть]


А как правильно его в другую сторону толкать?
ы. Нет, не пропустил, сделаю какой-нибудь 17х25 и попробую.

https://github.com/minamonra/

Slabovik

В другую сторону толкать точно также, только в другую  ;D
Начальная маска назначается не 0b10000000, а 0b00000001
и после прочтения бита сдвигается влево, а не вправо, как сейчас.

Но такой шрифт надо будет и рисовать перевёрнутым. Ибо по умолчанию считают, что развёртка слева направо и первым идёт старший бит, а байты наоборот - первым младший (интеловская нотация).

Ширину каждого символа - это можно конечно. Но тогда надо эту ширину возвращать в процедуру выше (которая вызывала рисовку символа), чтобы она могла определить, на сколько сместить курсор (т.е. место рисовки) для следующего символа. Решаемо.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Сделал из Gost Type A 18pt 17x23, правда сильно его почекрыжил.
↓ спойлер ↓
[свернуть]
https://github.com/minamonra/

Slabovik

Чисто эстетически автомат слегка лажает. Надо-бы руками пиксели подправлять, а то буквы лохматые какие-то. Дело наживное.
А так, похоже, всё работает.

Хитрость в алгоритме заметил?
Не использовался отдельный счётчик битов в байте. Его роль выполняла маска, чисто по совместительству.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Да, про маску понял.
Вот ещё один шрифт попробовал, ну и в динамике, снял не на телефон, фокус немного промазал. :)
↓ спойлер ↓
[свернуть]
Обновление цифр 10 раз в секунду.
https://github.com/minamonra/

Slabovik

Сейчас присматриваюсь. Это ведь этот экранчик: https://www.winstar.com.tw/products/tft-lcd/module/tft-st7735.html  ?
Начинаю понимать запрос на шрифты большого размера. Уж подумал его в качестве индикатора лабораторника применить, но сейчас вижу, что даже два таких индикатора (один на вольты, второй на амперы) будут мелковаты...
А есть такие же, но побольше?  ::)

Обработка ошибок... Тут в первую очередь надо сообразить, надо ли оно в имеющейся конструкции. По-хорошему, когда программа становится сложной - надо.

Классический обработчик представляет собой набор процедур, к которому обращаются по определённому адресу. Можно через прерывание, генерируемое софтверно или даже хардверно (хардверно работают WatchDog, BrownOut и ещё бывает экзотика на основе таймеров, уровней и т.п.)

Код ошибки передаётся каким-то параметром (в ассемблере удобно пользоваться регистром).
В самом простом случае представляет собой заглушку, которая ничего не делает и возвращает бег процессора обратно в программу.

Для случаев посложнее, ошибки надо поделить на критические - это после которых программа останавливается (навечно закольцовывается в обработчике, либо, если продакшн, производится "холодный старт" после обработки и записи в логи), и не критические - это типа "warning", который можно записать в лог, но потом возвратить управление в основную программу.

Лог - это что угодно. Какие-то записи. Для микроконтроллеров удобно в COM-порт. Это для того, чтобы можно было подсоединить, запустить и посмотреть, что там происходит. Правда, чтобы передача по COM не мешала работе основной программы (он ведь тормозной), надо организовывать очередь, куда программа могла бы быстро "бросить" запись, а порт уже самостоятельно (системой прерываний) выводил бы записанное.

Применительно к ожиданию готовности (индикатора), это скорее критическая ошибка. Нет готовности - невозможно выводить данные в него. Обычно делается счётчик опросов и если после N опросов (это надо по времени смотреть, чтобы не принять решение слишком рано) готовность не наступила, передать управление (вызвать функцию) обработчика ошибок.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Да, экранчик этот.
Побольше есть, 2,4 дюйма например, 1,77 и 1.8 практически одинаковые.
Для лабараторника, при условии что отображаться будет напряжение и ток 1,77 мне кажется достаточным, не такой он и маленький.
Вот Oled 0,96 - этот да - мелочь та ещё. Плюс выгорают сильно.
На фото Oled 1,2 дюйма правый, по центру 2,4.
---
Самое интересное, до конца не мог понять, что после установки SetWin (CASET RASET) надо всего лишь посылать байты подряд, перевод на следующую строку происходит сам, просто ограниченное поле, которое надо просто заполнить.
Доходила слишком долго почему-то такая простая вещь... :)
Отсюда и моё непонимание.


https://github.com/minamonra/

Slabovik

#38
2,4" ещё более-менее.
Мысль была о том (хотел делать хардверно, но пока некогда, да и прошлый измеритель я по юзабилити не довёл до ума - сделал только основные функции), чтобы одновременно отображать напряжение и ток на выходе крупными цифрами и рядом с ними (эстетично подобрать размер и положение) установленные напряжение и ток. Т.е. четыре значения сразу. Формат 4:3 в положении "портрет" вроде нормально подходит для этого. Плюс ещё индикация туда...


Ладно. Надо придумать вывод с поворотом

Символ-ЧЕТЫРЕ.png

Тут есть проблема. Поворот можно делать вправо, а можно делать влево. И это разные повороты.
При повороте вправо, вывод должен начинаться с левого нижнего угла символа, разворачиваться вверх (это будет отображаться на координате X) и вправо (координата Y).

При повороте влево наоборот - развертка должна начаться с правого верхнего угла символа и разворачиваться вниз, сдвигаясь влево с каждой строкой.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#39
Захотел перекинуть SixteenSegment16x24 в программу MatrixFont, там можно из Си файла импортировать.
Тут две засады
#define FONT_CONSOLAS_18_LENGTH        224
Что это никак не пойму?
Файл тут (https://github.com/minamonra/font_test/blob/main/matr_font_sl_01/consolas_18_font.h).
Вторая - отреверсить байты, сходу не понял как осуществить, потом решил printf использовать, крутилку массива послал в Online C Compiler, всё вышло хорошо.
#include <stdio.h>

unsigned char reverse(unsigned char b) 
{
  b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
  b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
  b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
  return b;
}

char W[] = 
{
// 288
    0x00, 0x00, 0x3E, 0x7C, 0x3E, 0x7C, 0x40, 0x06, 0x60, 0x0E, 0x60, 0x1A, 0x60, 0x32, 0x60, 0x36, 0x60, 0x66, 0x60, 0x66, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x66, 0x06, 0x66, 0x06, 0x6C, 0x06, 0x4C, 0x06, 0x58, 0x06, 0x70, 0x06, 0x60, 0x02, 0x3E, 0x7C, 0x3E, 0x7C, 0x00, 0x00, // 0
    0x00, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x1F, 0xF8, 0x3E, 0x7C, 0x00, 0x00, // 1
    0x00, 0x00, 0x3E, 0x7C, 0x1E, 0x7C, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x3E, 0x7C, 0x3E, 0x7C, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x3E, 0x78, 0x3E, 0x7C, 0x00, 0x00, // 2
    0x00, 0x00, 0x3E, 0x7C, 0x1E, 0x7C, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x3E, 0x7C, 0x3E, 0x7C, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x1E, 0x7C, 0x3E, 0x7C, 0x00, 0x00, // 3
    0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x40, 0x02, 0x3E, 0x7C, 0x3E, 0x7C, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, // 4
    0x00, 0x00, 0x3E, 0x7C, 0x3E, 0x78, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x3E, 0x7C, 0x3E, 0x7C, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x1E, 0x7C, 0x3E, 0x7C, 0x00, 0x00, // 5
    0x00, 0x00, 0x3E, 0x7C, 0x3E, 0x78, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x3E, 0x7C, 0x3E, 0x7C, 0x40, 0x02, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x40, 0x02, 0x3E, 0x7C, 0x3E, 0x7C, 0x00, 0x00, // 6
    0x00, 0x00, 0x3E, 0x7C, 0x1E, 0x7C, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, // 7
    0x00, 0x00, 0x3E, 0x7C, 0x3E, 0x7C, 0x40, 0x02, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x40, 0x02, 0x3E, 0x7C, 0x3E, 0x7C, 0x40, 0x02, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x40, 0x02, 0x3E, 0x7C, 0x3E, 0x7C, 0x00, 0x00, // 8
    0x00, 0x00, 0x3E, 0x7C, 0x3E, 0x7C, 0x40, 0x02, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x40, 0x02, 0x3E, 0x7C, 0x3E, 0x7C, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x1E, 0x7C, 0x3E, 0x7C, 0x00, 0x00, // 9

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, // . // 10
    0x00, 0x00, 0x3E, 0x7C, 0x3E, 0x7C, 0x40, 0x02, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x40, 0x02, 0x3E, 0x7C, 0x3E, 0x7C, 0x40, 0x02, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, // A // 11
    0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x08, 0x60, 0x08, 0x60, 0x18, 0x60, 0x30, 0x60, 0x30, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x66, 0x00, 0x66, 0x00, 0x6C, 0x00, 0x4C, 0x00, 0x58, 0x00, 0x70, 0x00, 0x60, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // V // 12
    0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x41, 0x82, 0x3F, 0xFC, 0x3E, 0x7C, 0x00, 0x00, // W // 13
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <space> 14
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // : // 15
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // a // 16
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x88, 0x11, 0x88, 0x19, 0x98, 0x0D, 0xB0, 0x0D, 0xB0, 0x07, 0xE0, 0x07, 0xE0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // v // 17
    0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x41, 0x82, 0x3E, 0x7C, 0x3E, 0x7C, 0x41, 0x82, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, // w // 18
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x1F, 0xF8, 0x3E, 0x7C, 0x00, 0x00, // c // 19
    0x00, 0x00, 0x3E, 0x7C, 0x3E, 0x78, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x3E, 0x78, 0x3E, 0x7C, 0x00, 0x00, // C // 20    
};

int i = 1;
int main()
{
  do {
    printf("0x%02hhx", reverse(W[i-1]));
    printf(",");
    if ((i % 48 == 0) && (i>0)) printf("\n");
    i++;
  } while (i < sizeof(W)+1);
  return 0;
}

---
Оборотные стороны дисплеев. Тача на моём 2.4" нет.
ы. Как цифровой этот шрифт мне нравиться, чуть бы его пожирнее, хотя не знаю.
↓ спойлер ↓
[свернуть]

:: добавлено 26 Фев., 2024, 20:49
Импорт удался, длина, о которой спрашивал оказалась количеством символов.
Код шрифта для импорта:
↓ спойлер ↓
#ifndef FONT_SIXSEG_H
#define FONT_SIXSEG_H

#ifndef FONT_TYPE_MONOSPACED
#define FONT_TYPE_MONOSPACED                0
#endif

#ifndef FONT_TYPE_PROPORTIONAL
#define FONT_TYPE_PROPORTIONAL              1
#endif

#define FONT_SIXSEG_LENGTH        21
#define FONT_SIXSEG_START_CHAR    32
#define FONT_SIXSEG_CHAR_WIDTH    16
#define FONT_SIXSEG_CHAR_HEIGHT   24
#define FONT_SIXSEG_FONT_TYPE     (FONT_TYPE_MONOSPACED)
#define FONT_SIXSEG_ARRAY_LENGTH  (FONT_SIXSEG_LENGTH * FONT_SIXSEG_CHAR_HEIGHT * 3)

const unsigned char  font_seven_segment_30[FONT_SEVEN_SEGMENT_30_ARRAY_LENGTH] =


const unsigned char font_sixseg[] = {
0x00,0x00,0x7c,0x3e,0x7c,0x3e,0x02,0x60,0x06,0x70,0x06,0x58,0x06,0x4c,0x06,0x6c,0x06,0x66,0x06,0x66,0x06,0x60,0x00,0x00,0x00,0x00,0x06,0x60,0x66,0x60,0x66,0x60,0x36,0x60,0x32,0x60,0x1a,0x60,0x0e,0x60,0x06,0x40,0x7c,0x3e,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x7c,0x00,0xf8,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x00,0x00,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xf8,0x1f,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x7c,0x3e,0x78,0x3e,0x00,0x40,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x40,0x7c,0x3e,0x7c,0x3e,0x02,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x02,0x00,0x7c,0x1e,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x7c,0x3e,0x78,0x3e,0x00,0x40,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x40,0x7c,0x3e,0x7c,0x3e,0x00,0x40,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x40,0x78,0x3e,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x00,0x00,0x02,0x40,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x02,0x40,0x7c,0x3e,0x7c,0x3e,0x00,0x40,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x40,0x00,0x00,0x00,0x00,
0x00,0x00,0x7c,0x3e,0x7c,0x1e,0x02,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x02,0x00,0x7c,0x3e,0x7c,0x3e,0x00,0x40,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x40,0x78,0x3e,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x7c,0x3e,0x7c,0x1e,0x02,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x02,0x00,0x7c,0x3e,0x7c,0x3e,0x02,0x40,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x02,0x40,0x7c,0x3e,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x7c,0x3e,0x78,0x3e,0x00,0x40,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x40,0x00,0x00,0x00,0x00,
0x00,0x00,0x7c,0x3e,0x7c,0x3e,0x02,0x40,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x02,0x40,0x7c,0x3e,0x7c,0x3e,0x02,0x40,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x02,0x40,0x7c,0x3e,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x7c,0x3e,0x7c,0x3e,0x02,0x40,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x02,0x40,0x7c,0x3e,0x7c,0x3e,0x00,0x40,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x40,0x78,0x3e,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x80,0x01,0x00,0x00,
0x00,0x00,0x7c,0x3e,0x7c,0x3e,0x02,0x40,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x02,0x40,0x7c,0x3e,0x7c,0x3e,0x02,0x40,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x02,0x40,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x02,0x00,0x06,0x10,0x06,0x10,0x06,0x18,0x06,0x0c,0x06,0x0c,0x06,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x66,0x00,0x66,0x00,0x36,0x00,0x32,0x00,0x1a,0x00,0x0e,0x00,0x06,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x02,0x40,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x00,0x00,0x00,0x00,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x82,0x41,0xfc,0x3f,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0xc0,0x03,0xc0,0x03,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x11,0x88,0x11,0x98,0x19,0xb0,0x0d,0xb0,0x0d,0xe0,0x07,0xe0,0x07,0x80,0x01,0x00,0x00,0x00,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x02,0x40,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x82,0x41,0x7c,0x3e,0x7c,0x3e,0x82,0x41,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x02,0x40,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x00,0x00,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xf8,0x1f,0x7c,0x3e,0x00,0x00,
0x00,0x00,0x7c,0x3e,0x7c,0x1e,0x02,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x02,0x00,0x7c,0x1e,0x7c,0x3e,0x00,0x00,
};
[свернуть]
https://github.com/minamonra/

Slabovik

Что-то не пойму. Матрица 16x24, а на экране 15x23.

Дефайны... Они конечно имеют смысл как подставляемые куда-то константы, но если эти константы не используются, зачем из держать? Там много интересных констант, но которые я вот пока не придумаю, куда вообще прикрутить...
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#41
А это она автоматом холст оптимизировала.
вот правильный:
↓ спойлер ↓
// Название шрифта          font_sixseg
// Автор шрифта             HOME-PC / john
// Дата и время генерации   27.02.2024 10:19:01
// Сгенерировано            matrixFont v1.4.7.64
// Кодовая страница         ANSI (ASCII 7-битная)
// https://gitlab.com/riva-lab/matrixFont 

#ifndef FONT_FONT_SIXSEG_H
#define FONT_FONT_SIXSEG_H

#ifndef FONT_TYPE_MONOSPACED
#define FONT_TYPE_MONOSPACED            0
#endif

#ifndef FONT_TYPE_PROPORTIONAL
#define FONT_TYPE_PROPORTIONAL          1
#endif

#define FONT_FONT_SIXSEG_LENGTH         21
#define FONT_FONT_SIXSEG_START_CHAR     32
#define FONT_FONT_SIXSEG_CHAR_WIDTH     16
#define FONT_FONT_SIXSEG_CHAR_HEIGHT    24
#define FONT_FONT_SIXSEG_FONT_TYPE      (FONT_TYPE_MONOSPACED)
#define FONT_FONT_SIXSEG_ARRAY_LENGTH   (FONT_FONT_SIXSEG_LENGTH * FONT_FONT_SIXSEG_CHAR_HEIGHT * 2)

const unsigned char  font_font_sixseg[FONT_FONT_SIXSEG_ARRAY_LENGTH] =
{
    0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x60, 0x06, 0x70, 0x06, 0x58, 0x06, 0x4C, 0x06, 0x6C, 0x06, 0x66, 0x06, 0x66, 0x06, 0x63, 0x86, 0x61, 0x86, 0x61, 0xC6, 0x60, 0x66, 0x60, 0x66, 0x60, 0x36, 0x60, 0x32, 0x60, 0x1A, 0x60, 0x0E, 0x60, 0x06, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 32  < > 
    0x00, 0x00, 0x7C, 0x00, 0xF8, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xF8, 0x1F, 0xFC, 0x3F, 0x00, 0x00, // Символ 33  <!> 
    0x00, 0x00, 0xFC, 0x3F, 0xF8, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0xFC, 0x1F, 0xFC, 0x3F, 0x00, 0x00, // Символ 34  <"> 
    0x00, 0x00, 0xFC, 0x3F, 0xF8, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xF8, 0x3F, 0xF8, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xF8, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 35  <#> 
    0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // Символ 36  <$> 
    0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x1F, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xF8, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 37  <%> 
    0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x1F, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 38  <&> 
    0x00, 0x00, 0xFC, 0x3F, 0xF8, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // Символ 39  <'> 
    0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 40  <(> 
    0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xF8, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 41  <)> 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, // Символ 42  <*> 
    0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, // Символ 43  <+> 
    0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0E, 0x70, 0x1C, 0x38, 0x18, 0x18, 0x30, 0x0C, 0x30, 0x0C, 0x60, 0x06, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, // Символ 44  <,> 
    0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x82, 0x41, 0xFC, 0x3F, 0x7C, 0x3E, 0x00, 0x00, // Символ 45  <-> 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 46  <.> 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 47  </> 

        // Digits / Цифры 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 48  <0> 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x11, 0x88, 0x11, 0x98, 0x19, 0xB0, 0x0D, 0xB0, 0x0D, 0xE0, 0x07, 0xE0, 0x07, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 49  <1> 
    0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x82, 0x41, 0x7C, 0x3E, 0x7C, 0x3E, 0x82, 0x41, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, // Символ 50  <2> 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xF8, 0x1F, 0x7C, 0x3E, 0x00, 0x00, // Символ 51  <3> 
    0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x1F, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0xFC, 0x1F, 0xFC, 0x3F, 0x00, 0x00  // Символ 52  <4> 
};

#endif // FONT_FONT_SIXSEG_H 
[свернуть]
Другой формат получается, если указать в настройках пропорциональный шрифт:
↓ спойлер ↓
// Название шрифта          font_sixseg
// Автор шрифта             HOME-PC / john
// Дата и время генерации   27.02.2024 10:21:56
// Сгенерировано            matrixFont v1.4.7.64
// Кодовая страница         ANSI (ASCII 7-битная)
// https://gitlab.com/riva-lab/matrixFont 

#ifndef FONT_FONT_SIXSEG_H
#define FONT_FONT_SIXSEG_H

#ifndef FONT_TYPE_MONOSPACED
#define FONT_TYPE_MONOSPACED            0
#endif

#ifndef FONT_TYPE_PROPORTIONAL
#define FONT_TYPE_PROPORTIONAL          1
#endif

#define FONT_FONT_SIXSEG_LENGTH         21
#define FONT_FONT_SIXSEG_START_CHAR     32
#define FONT_FONT_SIXSEG_CHAR_WIDTH     16
#define FONT_FONT_SIXSEG_CHAR_HEIGHT    24
#define FONT_FONT_SIXSEG_FONT_TYPE      (FONT_TYPE_PROPORTIONAL)
#define FONT_FONT_SIXSEG_ARRAY_LENGTH   (FONT_FONT_SIXSEG_LENGTH * (1 + FONT_FONT_SIXSEG_CHAR_HEIGHT * 2))

const unsigned char  font_font_sixseg[FONT_FONT_SIXSEG_ARRAY_LENGTH] =
{
     15, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x60, 0x06, 0x70, 0x06, 0x58, 0x06, 0x4C, 0x06, 0x6C, 0x06, 0x66, 0x06, 0x66, 0x06, 0x63, 0x86, 0x61, 0x86, 0x61, 0xC6, 0x60, 0x66, 0x60, 0x66, 0x60, 0x36, 0x60, 0x32, 0x60, 0x1A, 0x60, 0x0E, 0x60, 0x06, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 32  < > 
     14, /*N*/ 0x00, 0x00, 0x7C, 0x00, 0xF8, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xF8, 0x1F, 0xFC, 0x3F, 0x00, 0x00, // Символ 33  <!> 
     15, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xF8, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0xFC, 0x1F, 0xFC, 0x3F, 0x00, 0x00, // Символ 34  <"> 
     15, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xF8, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xF8, 0x3F, 0xF8, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xF8, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 35  <#> 
     15, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // Символ 36  <$> 
     15, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x1F, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xF8, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 37  <%> 
     15, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x1F, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 38  <&> 
     15, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xF8, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, // Символ 39  <'> 
     15, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 40  <(> 
     15, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0xF8, 0x3F, 0xFC, 0x3F, 0x00, 0x00, // Символ 41  <)> 
      9, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, // Символ 42  <*> 
     15, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0xFC, 0x3F, 0xFC, 0x3F, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, // Символ 43  <+> 
     15, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0E, 0x70, 0x1C, 0x38, 0x18, 0x18, 0x30, 0x0C, 0x30, 0x0C, 0x60, 0x06, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, // Символ 44  <,> 
     15, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x82, 0x41, 0xFC, 0x3F, 0x7C, 0x3E, 0x00, 0x00, // Символ 45  <-> 
      9, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 46  <.> 
      9, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 47  </> 

        // Digits / Цифры 
     10, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 48  <0> 
     13, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x11, 0x88, 0x11, 0x98, 0x19, 0xB0, 0x0D, 0xB0, 0x0D, 0xE0, 0x07, 0xE0, 0x07, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 49  <1> 
     15, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x82, 0x41, 0x7C, 0x3E, 0x7C, 0x3E, 0x82, 0x41, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, // Символ 50  <2> 
     14, /*N*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xF8, 0x1F, 0x7C, 0x3E, 0x00, 0x00, // Символ 51  <3> 
     14, /*N*/ 0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x1F, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0xFC, 0x1F, 0xFC, 0x3F, 0x00, 0x00  // Символ 52  <4> 
};

#endif // FONT_FONT_SIXSEG_H 
[свернуть]
Те для каждого символа сначала ширина, потом данные, выстота остаётся неизменной.

:: добавлено 27 Фев., 2024, 15:44
А, да, про дефайны, в коде они конечно же не нужны, но для импорта шрифта в программу без них не получится.
https://github.com/minamonra/