Как перестать бояться и полюбить mbed [Часть 5]

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

    Сегодня я наконец-то заканчиваю описание программной части — остались вопросы связанные с выводом на TFT-дисплей изображений и кириллицы. Сделаем всё красиво.



    Содержание цикла публикаций:


    Напомню, что речь идет о разработке прототипа устройства с сенсорным экраном, которое служит для высокоскоростного измерения относительной влажности и (заодно) температуры. Для написания программы для микроконтроллера используется онлайн IDE mbed, позволяющая создавать железонезависимый код, который одинаково работает на отладочных платах от SiLabs, Atmel, Wiznet, STM32, NXP и других производителей.

    1. Вывод изображений на TFT



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

    Графические контроллеры серии FT8xx позволяют работать с изображениями формата .jpeg или .png. Изображение можно не только выводить на экран, но и трансформировать — изменять размер, вращать или перемещать по экрану, а также использовать как заставку. Все эти операции выполняются на графическом контроллере по приходу соответствующих команд от управляющего МК.

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



    В первом случае файл .jpeg берется из памяти управляющего МК или с внешнего носителя и сразу записывается в память графического контроллера FT8xx. В этом случае для загрузки используется команда CMD_LOADIMAGE. После загрузки изображения в память FT8xx становятся доступны все функции для работы с изображением — трансформации картинки и её вывод на дисплей. Такой подход является оптимальным, если вам есть где хранить изображения, то есть используется USB Flash-память или SD-карта.

    Во втором случае изображение предварительно сжимается по алгоритму Deflate. Полученный в результате кодирования bitmap занимает гораздо меньше места, поэтому может храниться не только на внешнем носителе, но во встроенной памяти управляющего МК. Изображение загружается на графический контроллер FT8xx в сжатом виде, а распаковка данных выполняется уже графическим контроллером. Для загрузки сжатого изображения служит команда CMD_INFLATE. После того как изображение распаковано, с ним можно работать точно так же, как и в первом случае.

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





    1.1. Форматирование изображения, компрессия



    Алгоритм Deflate изначально создавался для zip-архивов, но благодаря отсутствию патентов успешно используется и для других целей, в том числе для сжатия изображений. Вот, кстати, отличная статья о Deflate и png.

    Для преобразования изображения FTDI предлагает несколько консольных утилит, например img_cvt. Также доступны графические оболочки вроде EVE Screen Editor, которые не только позволяют конвертировать изображения, но и вообще сильно упрощают жизнь при создании программ для графического контроллера. По сути, EVE Screen Editor — это эмулятор TFT-модулей Riverdi.



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

    Используемый мной контроллер FT801 позволяет выводить на TFT-дисплей изображения девяти форматов: черно-белые L1, L4 и L8, а также RGB332, ARGB2, ARGB4, RGB565, PALETTED и ARGB1555, о них можно подробнее почитать в документации проивзодителя. Разные форматы позволяют получить разное соотношение качества изображений и размера кодирующего изображение бинарного файла.


    (на рисунке слева направо L1, L4, L8, RGB332, ARGB2, ARGB4, RGB565, PALETTED, ARGB1555)

    По идее, наилучшее качество можно получить при использовании формата ARGB1555, однако на практике лучше попробовать разные варианты и подобрать наиболее подходящий. Фотография датчика действительно лучше всего выглядит после преобразования в ARGB1555 или RGB565, однако в какой-то момент мне не хватило встроенной памяти МК и пришлось отказаться от этих форматов в пользу RGB332. Смотрится более-менее прилично, а занимает 1865 байт вместо 7067 и 7816 у ARGB1555 и RGB565 соответственно.

    С иконками получилось интереснее. Исходные файлы — .png с прозрачным фоном размером 37x77 и 53x67 точек. Прозрачность иконок можно сохранить только с кодированием типа ARGB, т.е. выбирать приходится из форматов ARGB2, ARGB4, и ARGB1555. Из них наиболее симпатичное сглаженное изображение дает не ARGB2, и, к моему удивлению, не ARGB1555, а ARGB4.


    (на рисунке слева направо ARGB2, ARGB4, ARGB1555)

    После того как выбран подходящий формат, нужно сохранить проект в Screen Editor. В папке, куда Screen Editor был установлен, появится директория images, где для каждого из использованных изображений создан файл .binh. Он то нам и нужен.

    1.2. Загрузка изображения в память графического контроллера



    Получив бинарное представление изображения, возвращаемся из Screen Editor в mbed IDE, где в коде программы сохраняем все полученные bitmap как массивы. Иконка для влажности, например, выглядит вот так.

    const unsigned char hum_icon[]={
    120,156,165,86,203,109,195,48,12,205,177,40,250,25,193,35,120,4,141,160,17,60,130,71,200,181,55,143,224,123,46,26,193,11,20,208,4,133,54,168,71,96,31,165,248,43,74,145,82,18,8,20,138,79,228,35,41,193,244,73,117,218,86,250,175,250,251,65,243,115,200,203,133,88,236,83,232,153,130,92,171,145,29,109,82,135,108,214,168,44,117,172,29,209,1,59,22,35,21,197,82,91,165,125,100,45,121,254,188,147,33,131,94,110,255,37,17,177,52,248,189,149,209,247,155,136,85,2,82,195,238,124,109,186,213,102,132,156,83,189,80,152,91,222,111,130,213,207,226,94,92,60,93,152,186,137,150,185,185,98,53,193,178,229,51,223,53,194,121,237,217,255,235,133,215,248,229,115,250,195,126,11,109,68,228,33,79,159,63,75,251,184,135,224,228,162,202,247,167,188,83,58,238,251,178,106,156,119,162,51,219,60,36,121,164,59,35,237,113,189,77,6,107,40,121,163,49,85,46,121,110,200,215,194,39,199,199,74,59,152,116,247,176,19,83,34,242,85,172,111,28,57,226,140,76,185,74,185,58,6,117,130,151,46,136,186,100,215,9,54,93,128,85,240,27,78,182,49,83,255,189,54,2,227,255,96,37,30,146,106,33,103,85,88,171,49,142,113,123,45,234,145,191,17,194,228,249,59,138,233,74,34,113,187,172,204,236,254,182,76,194,253,91,170,100,211,188,128,154,252,219,167,197,26,49,39,147,190,41,216,9,239,185,5,131,150,253,192,65,161,7,206,91,135,240,250,101,84,249,232,103,49,197,95,24,13,226,26,68,183,56,103,196,58,91,255,63,65,221,118,198,
    };
    


    Чтобы загрузить это изображение в память графического контроллера FT801, понадобится отправить с управляющего МК три команды:

    #define IMAGE_ADDR_HUMIDITY 29696
    ...
        (*_TFT).WrCmd32(CMD_INFLATE);
        (*_TFT).WrCmd32(IMAGE_ADDR_HUMIDITY);
        (*_TFT).WrCmdBufFromFlash(hum_icon, sizeof(hum_icon));
    

    CMD_INFLATE — команда, сообщающая FT801, что в его память будет записано сжатое по алгоритму Deflate изображение.
    IMAGE_ADDR_HUMIDITY — начальный адрес в памяти графического контроллера RAM_G, по которому будет доступно изображение.
    hum_icon — массив, хранящий изображение.

    После такой операции иконка «Влажность» будет доступна для вывода на экран пока память графического контроллера не будет очищена программно или в результате сброса.

    1.3. Захват изображения



    Следующий шаг после загрузки — «захват» изображения.

    StartDL();
    ...
        (*_TFT).DL(BITMAP_HANDLE(0));
        (*_TFT).DL(BITMAP_SOURCE(IMAGE_ADDR_HUMIDITY));
        (*_TFT).DL(BITMAP_LAYOUT(ARGB4, 60, 38));
        (*_TFT).DL(BITMAP_SIZE(NEAREST, BORDER, BORDER, 30, 38));
    ...
    FinishDL();
    

    Командой BITMAP_HANDLE мы присваиваем каждому изображению (объекту Bitmap) указатель — номер от 0 до 31, по которому в дальнейшем можно будет обратиться к изображению.
    Команда BITMAP_SOURCE указывает на адрес в памяти RAM_G графического контроллера FT8xx (см. п. Загрузка изображения).
    Команда BITMAP_LAYOUT сообщает графическому контроллеру формат изображения и его размеры, а команда BITMAP_SIZE определяет размер выводимого изображения. Изменяя её аргументы можно, например, обрезать картинку справа или слева.

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

    1.4. Вывод изображения



    После того как выполнены загрузка и захват изображения, его можно вывести на TFT-дисплей. Для этого используются команды группы BITMAP, например для вывода иконки «Влажность» поверх одной из кнопок главного меню я выполняю три команды:

    StartDL();
    ...
    // отрисовка прямоугольника (кнопки)
    ...
        (*_TFT).DL(BEGIN(BITMAPS));
        (*_TFT).DL(VERTEX2II(12 + 255, 62 + 10, 0, 0));
        (*_TFT).DL(END());
    ...
    FinishDL();
    

    В первых двух аргументах команды VERTEX2II указываются координаты для вывода на экран, а третий аргумент является указателем на иконку «Влажность», который был задан в BITMAP_SOURCE и BITMAP_HANDLE — «0».

    Вывод иконки Температура и фотографии датчика выполняются абсолютно так же
    StartDL();
    ...
        (*_TFT).DL(BEGIN(BITMAPS));
        (*_TFT).DL(VERTEX2II(12 + 260, 62 + 93 + 12 + 10, 1, 0));
        (*_TFT).DL(END());
    ...
    FinishDL();
    

    StartDL();
    ...
        (*_TFT).DL(BEGIN(BITMAPS));
        (*_TFT).DL(VERTEX2II(360, 140, 2, 0));
        (*_TFT).DL(END());
    ...
    FinishDL();
    


    Ссылка на полный исходный код проекта приводится ниже.

    Использование пользовательских шрифтов



    В статье, посвященной началу работы с графическим контроллером серии FT8xx, упоминалась поддержка стандартных виджетов — процедур для вывода относительно сложных графических объектов, которые аппаратно реализованы на графических контроллерах от FTDI. Среди виджетов есть текстовая строка, в mbed-библиотеке FT800_2 выводу строки на дисплей соответствует функция Text().

        (*_TFT).Text(22, 67, 27, 0, "Current humidity (rH)");
    

    Аргументы функции — координаты первого символа строки (22, 67), номер используемого шрифта (27), дополнительные опции (0) и, собственно, текстовая строка. С координатами всё понятно, дополнительные опции также относятся только к положению строки на экране, поэтому поговорим о шрифтах.

    Номер используемого шрифта — это число от 0 до 31, причем номера с 0 до 15 зарезервированы под пользовательские шрифты, а номера с 16 по 31 соответствуют шестнадцати встроенным шрифтам. Если в вашем приложении достаточно выводить только первые 128 ASCII символов и вам достаточно стандартного начертания этих символов, то можно остановиться на этом месте и не читать статью дальше — просто используйте шрифты с номерами 16-31.



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

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

    2.1. Форматирование шрифта, компрессия



    На первом этапе нужно скачать или создать нужный шрифт (формат .ttf вполне подойдет) и получить бинарный файл для загрузки в графический контроллер FT8xxx. Для этого можно использовать либо консольную утилиту, либо тот же EVE Screen Editor.



    В Screen Editor шрифт импортируется также, как файлы изображений — в окно Content добавляется файл шрифта, а в окне Properties устанавливаются параметры его компрессии: формат, размер и charset.

    Формат выбирается из трех опций — L1, L4 и L8. Разница, как и при конвертации изображений, в соотношении качества отрисовки и размера бинарного файла. Размер шрифта просто определяет ширину символов в пикселях, а наибольшего внимания заслуживает поле charset.

    Для графических контроллеров FTDI шрифты по умолчанию состоят из 128 ASCII символов.

     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
    // отсчет не с нулевого, а с 32-го символа
    

    Если вы используете только эти символы и добавляете новый шрифт только чтобы изменить их начертание — отлично, конвертируйте шрифт не изменяя charset. А если нужно добавить кириллицу или какой-то другой не входящий в ASCII символ, то charset придется заменить. В моём приложении понадобится вся кириллица, цифры, некоторые знаки препинания и математические символы, знаки градуса и процента, а также несколько латинских букв. В итоге измененный charset выглядит следующим образом:

     0123456789АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя.,:-°±%<>rHYTICS
    // отсчет не с нулевого, а с 32-го символа
    

    Теперь, также как при работе с изображением, сохраняем проект Screen Editor, заходим в папку, где установлен EVE Screen Editor и в директории /fonts находим бинарный файл .binh.

    2.2. Загрузка в память графического контроллера



    Загрузка нового шрифта повторяет процесс загрузки изображения — сохраняем бинарное представление шрифта как массив и загружаем на FT8xx по определенному заранее начальному адресу в память графического контроллера с помощью команды CMD_INFLATE.

    #define FONT_ADDR_ROBOTO_REGULAR_30   16992
    ...
        (*_TFT).WrCmd32(CMD_INFLATE);
        (*_TFT).WrCmd32(FONT_SET_ROBOTO_REGULAR_30);
        (*_TFT).WrCmdBufFromFlash(font_RobotoRegular30, sizeof(font_RobotoRegular30));
    


    2.3. Захват и установка шрифта



    «Захват» пользовательского шрифта выполняется теми же командами, что и захват изображения, разница заключается в том что после команд BITMAP_HANDLE, BITMAP_SOURCE, BITMAP_LAYOUT и BITMAP_SIZE нужно ещё установить новый шрифт через вызов SetFont().

        (*_TFT).DL(BITMAP_HANDLE(3));
        (*_TFT).DL(BITMAP_SOURCE(FONT_ADDR_ROBOTO_REGULAR_30));
        (*_TFT).DL(BITMAP_LAYOUT(L4, 16, 33));
        (*_TFT).DL(BITMAP_SIZE(NEAREST, BORDER, BORDER, 32, 33));
    
        (*_TFT).SetFont(3, FONT_SET_ROBOTO_REGULAR_30);
    

    2.4. Использование шрифта



    Теперь среди пользовательских шрифтов под номером 3 значится загруженный нами шрифт Roboto Regular. Если бы при конвертации не был изменен charset этого шрифта, то для смены встроенного шрифта номер 27 на Roboto Regular нужно было бы всего лишь сменить

        (*_TFT).Text(22, 67, 27, 0, "Current humidity (rH)");
    

    на

        (*_TFT).Text(22, 67, 3, 0, "Current humidity (rH)"); // выведет на экран ерунду
    

    Однако мы собираемся выводить нестандартные для контроллера FT8xx символы, поэтому вместо явного указания строки («Current humidity (rH)») придется каждый раз лепить эту строку из отельных символов.

    Рассмотрим строку «Относительная влажность». Задача состоит в том, чтобы каждому символу этой строки поставить в соответствие его номер в charset.

    Если компилятор поддерживает кириллицу, то каждому символу начиная с прописных букв АБВ и заканчивая строчными эюя (с пропуском букв ё и Ё) будет соответствовать значение от 0xC0 до 0xFF. Значит чтобы сопоставить символы строки с номерами этих символов в charset нужно вычесть из кода каждого символа фиксированное значение. Например, если буква А в charlist занимает 32-ую позицию (0x20), а следующие за А буквы идут в том же порядке что и в таблице CP1251, то из кода каждого символа строки «Относительная влажность» (кроме пробела) нужно будет вычесть значение 0xA0.

    Кодировка кириллицы CP1251
    image

    Однако компилятор может и не поддерживать кириллицу, mbed-овский как раз не поддерживает. Это значит, что компилятор не воспринимает кириллицу как коды с 0xC0 до 0xFF, поэтому мне не остается ничего кроме как использовать юникод, точнее UTF-8.

    Каждый символ, не входящий в основную ASCII таблицу — кириллица, знаки ° и ± — представляется как двухбайтный код UTF-8. Я беру код каждого символа и ставлю ему в соответствие номер в своём charset.

    Для латинских букв, которые тоже есть в charlist, нужно также заменить юникод на номер в charset, разница лишь в том что код латинских букв и других знаков ASCII типа точки, запятой и процента состоит из одного, а не двух байт.
    Символ конвертируемой строки Код UTF-8 Порядковый номер в моём charset
    АБВ… ноп 0xD090… 0xD0BF 43… 90
    рст… эюя 0xD180… 0xD18F 91… 96
    ° 0xC2B0 112
    ± 0xC2B1 113
    пробел 0x20 32
    0… 9 0x30… 0x39 33… 43
    . 0x2E 108
    , 0x2C 109
    : 0x3A 110
    и так далее

    Для выполнения такого преобразования строки создана соответствующая функция.

    Функция преобразования строки CreateStringRussian
    void Display::CreateStringRussian(const string rustext)
    {
    // CHANGED ASCII:
    //  0123456789АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя.,:-°±%<>rHYTICS
        int len = rustext.length();
        int j = 0;
        for (int i = 0; i < len; i ++) {
            uint16_t res = uint8_t(rustext[i]);
            if (res > 0x7F) {
                res = res << 8 | uint8_t(rustext[i + 1]);
                // АБВ ... ноп
                if ((res >= 0xD090) && (res <= 0xD0BF)) {
                    char offset = (char)(res - 0xD090);
                    russianStr[j] = 32 + 11 + offset;
                // рст ... эюя
                } else if ((res >= 0xD180) && (res <= 0xD18F)) {
                    char offset = (char)(res - 0xD180);
                    russianStr[j] = 32 + 59 + offset;
                }
                // Degree sign
                else if (res == 0xC2B0) {
                    russianStr[j] = 32 + 79;
                }
                // Plus-minus sign
                else if (res == 0xC2B1) {
                    russianStr[j] = 32 + 80;
                }
                i++;
            } else {
                // Space
                if (res == 0x20) {
                    russianStr[j] = 32;
                } 
                // Numbers
                else if (res >= 0x30 && res <= 0x39) {  
                    russianStr[j] = 32 + 1 + (res - 0x30);
                } 
                // .
                else if (res == 0x2E) {
                    russianStr[j] = 32 + 75;
                }
                // ,
                else if (res == 0x2C) {
                    russianStr[j] = 32 + 76;
                }
                // :
                else if (res == 0x3A) {
                    russianStr[j] = 32 + 77;
                }
                // -
                else if (res == 0x2D) {
                    russianStr[j] = 32 + 78;
                }
                // %
                else if (res == 0x25) {
                    russianStr[j] = 32 + 81;
                } 
                // <
                else if (res == 0x3C) {
                    russianStr[j] = 32 + 82;
                }
                // >
                else if (res == 0x3C) {
                    russianStr[j] = 32 + 83;
                }
                // "r"
                else if (res == 0x72) {
                    russianStr[j] = 32 + 84;
                }
                // "H"
                else if (res == 0x48) {
                    russianStr[j] = 32 + 85;
                }
                // "Y"
                else if (res == 0x59) {
                    russianStr[j] = 32 + 86;
                }
                // "T"
                else if (res == 0x54) {
                    russianStr[j] = 32 + 87;
                }
                // "I"
                else if (res == 0x49) {
                    russianStr[j] = 32 + 88;
                }
                // "C"
                else if (res == 0x43) {
                    russianStr[j] = 32 + 89;
                }
                // "S"
                else if (res == 0x53) {
                    russianStr[j] = 32 + 90;
                }
            }
            j++;
        }
        russianStr[j] = 0;
    }
    


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

        CreateStringRussian("Относительная влажность");
        (*_TFT).Text(15, 15, 3, 0, russianStr);
    

    3. Итоговый результат



    Исходный код готового проекта доступен на developer.mbed.org. К теме сегодняшней статьи относятся следующие файлы проекта:

    • /pictures.h — конвертированные изображения и шрифты
    • /TFT/display.ImagesAndFonts.cpp — загрузка и захват изображений и шрифтов, установка шрифтов
    • /TFT/display.StringsTransform.cpp — преобразования строк
    • /TFT/display.Draw_MainMenu.cpp — формирование экрана главного меню, где выводятся иконки Температура и Влажность
    • /TFT/display.Draw_AboutSensor.cpp — формирование экрана с описанием датчика, где выводится его фото

    Таким образом я наконец-то заканчиваю описание создания проекта в онлайн IDE ARM mbed. Мы рассмотрели всё начиная с написания mbed-овского Hello Word до довольно объемной программы, использующей две библиотеки периферийных устройств — HYT для одноименного датчика и FT800_2 для TFT-модуля от Riverdi.

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



    В последней статье данного цикла поделюсь историей создания корпуса для этого девайса.

    Заключение



    В заключении традиционно благодарю читателя за внимание и напоминаю, что вопросы по применению продукции, о которой мы пишем на хабре, можно смело задавать на email, указанный в моем профиле.
    • +15
    • 6,2k
    • 8
    ЭФО
    58,00
    Поставки электронных компонентов
    Поделиться публикацией

    Комментарии 8

      0
      Неплохо, расскажите как к этому чипу подбирали дисплей, что у него с интеграцией в плане кода, как быть с тачем, что там настройкой внутреннего IPU для соответствующих сигналов и формата дисплея. Как обстоит дело с калибровкой на касание и есть ли поддержка емкостных тач. экранов.
      0
      А кто собственно настроил контроллер на дисплей? Производитель? Что будет когда он передумает заниматься этим, закроется, наложит на Россию санкции? Там все прозрачно в плане использования этого максимально фундаментально на компонентах по отдельности? Какая лицензия на код? Можно ли его потом использоваться кастомно?
        –1
        Вы же не переходили по моим ссылкам, да?))
          0
          А по ссылкам всё это, конечно, описано. Но я могу по вашим вопросам кратко пробежаться:

          >> А кто собственно настроил контроллер на дисплей? Производитель?
          Да, производитель. Более того, контроллеры FT8xx изначально предназначены именно для управления такими TFT-дисплеями

          >> Что будет когда он передумает заниматься этим, закроется, наложит на Россию санкции?
          Будет ровно то же самое, как если бы любой другой производитель передумал чем-то заниматься / закрылся / наложил санкции — очевидно возникнут проблемы с поставками. Но вы, наверное, всё равно используете в своей работе импортные компоненты? Или отечественные TFT уже подъехали, а я не в курсе?

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

          >> Какая лицензия на код? Можно ли его потом использоваться кастомно?
          Какой код имеете в виду? Библиотеку для работы с графическим контроллером? Код для устройства, о котором я пишу в своих статьях? Код, вшитый в графический контроллер?

          Спасибо.
            0
            Я не зря задал эти вопросы, потому что вы делаете распространенную ошибку — подсаживаете кого-то на сторонние решения без осознания ответственности, которую несете в плане производства и поддержки. Люди, которые выберут этот относительно простой путь, в будущем могут остаться без результата. Что касается кода, речь о библиотеках и примерах. Едем далее, вы говорите намного сложнее, хотя сложность — это тоже код. Гораздо лучше иметь больше кода, чем чье-то частично кастомизированное железно решение, не говоря уже о результате, который можно достичь, имея все максимально по отдельности и на уровне кода.
              0
              Я не зря задал эти вопросы, потому что вы делаете распространенную ошибку — подсаживаете кого-то на сторонние решения без осознания ответственности, которую несете в плане производства и поддержки.
              Я пишу эти статьи в блоге крупного поставщика электронных компонентов и мы официально представляем в РФ всех производителей, о применении продукции которых я пишу — Riverdi, FTDI, Silicon Labs и IST-AG и т.д.
              То есть речь не о взятых с потолка сторонних решениях, а о наших целевых продуктах — о компонентах, которые мы продвигаем, которые мы поставляем, и за поставки которых несем ответственность как перед клиентом, так и перед производителем.

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

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

              Едем далее, вы говорите намного сложнее, хотя сложность — это тоже код. Гораздо лучше иметь больше кода, чем чье-то частично кастомизированное железно решение, не говоря уже о результате, который можно достичь, имея все максимально по отдельности и на уровне кода.
              Перечитываю раз за разом, а ваша мысль всё равно от меня ускользает. Надеюсь вы не имеете в виду, что разработка встроенной системы будет эффективнее, если взять кучу дискретных компонентов и строить на их базе систему, где каждая связка будет вашим собственным софтовым велосипедом?

              P.S. Извините за такой длинный текст, но мне правда хочется понять вашу точку зрения и донести свою.
          0
          TFT-дисплей может поставляться с интегрированным графическим контроллером или без него. С точки зрения разработчика разница в том, что управлять «голым» дисплеем значительно сложнее, чем когда многие операции уже аппаратно реализованы на встроенном контроллере.

          Библиотеки для работы с графическим контроллером лежат в открытом доступе. Естественно, Riverdi (производитель модулей) предоставляет и библиотеки для работы со своими моделями, и примеры программ, и разные утилиты типа упомянутого в статье Screen Editor. Как иначе то, простите?

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое