MakiseGUI — бесплатная библиотека графического интерфейса для микроконтроллеров

от автора

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

Назвал я её MakiseGui.

Перед началом разработки я поставил себе цели:

  • Простота конечной разработки. Писать интерфейс не должно быть сложнее, чем используя WindowsForms и тп
  • Простота интеграции. Встроить и запустить интерфейс в приложении должно быть максимально просто на любом железе или ПО.
  • Чистый Си. Был использован только gnu-c99 и из библиотек только stdlib
  • Минимальное потребление RAM. Возможность использования на средних микроконтроллерах без внешней памяти(примерно 40kb с цветным дисплеем 320х240).
  • Достаточное количество графических элементов для комфортной разработки. Простое добавление новых.
  • opensource лицензия и бесплатное использование даже в коммерческих проектах

Пример без объяснений.

В качестве демонстрации возможностей библиотеки и примеров использования может быть использован проект созданный специально для этих целей: https://github.com/SL-RU/MakiseSDLTest

Он использует SDL2 для отрисовки и ввода и имеет примеры использования всех элементов и почти всех функций системы. Может быть скомпиллирован и запущен на любом linux дистрибутиве. На windows тоже, но лишь теоретически — сам не пробовал.

Видео работы:

Структура

image

Библиотека состоит из трёх чётко разделённых частей:

1) Ядро. Ядро состоит из интерфейса к драйверу, функций отрисовки в драйвер и функций отрисовки примитивов в буфер.
2) Драйвер. Драйвер обеспечивает всё общение с железом и с ПО, поэтому под каждую задачу придётся писать обычно свой, чтобы учесть все моменты(DMA, прерывания и тд). Драйвер лишь обеспечивает передачу изображения из буфера на железо и очищает буфер изображения. Как примеры, в проекте есть драйверы для дисплея на ili9340, а так же SDL2 для отладки библиотеки на компьютере. Ядро и драйвер могут работать отдельно, без GUI.
3) Сам GUI. Занимает бОльшую часть системы, тут воплощены все необходимые функции для работы интерфейса: контейнеры, элементы, системы отрисовки, фокуса, ввода, обработки событий и прочего.

GUI

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

Простейший пример, создающий кнопку на экране:

MHost host; //базовая структура системы, root-контейнер, содержащий все другие контейнеры и элементы.  //метод будет вызыван при нажатии на кнопку void click(MButton *b) {     printf("Button was clicked"); //выводим сообщение в стандартный поток     b->text = "Clicked!"; //меняем текст кнопки  } MButton button; //структура, содержащая всю информацию о кнопке void create_gui() {     //создаём кнопку     m_create_button(&button, //указатель на структуру кнопки         host->host, //контейнер, в который будет добавлена кнопка после создания. В данном случае это контейнер MHost'a         mp_rel(20, 20, //координаты элемента относительно левого верхнего угла                90, 30), //ширина, высота         "Click me",   //текст кнопки         //События         &click, //Вызывается при нажатии на кнопку         0, //Вызывается до обработки нажатия, может прервать обработку нажатия         0, //Вызывается при действиях с фокусом кнопки         &ts_button //стиль кнопки     ); }  void main() {     //тут была инициализация MakiseGui, драйвера, MakiseBuffer и MHost. Запуск драйвера.     create_gui();     while(1)     {         //драйвер вызывает функции рисовки         //совершается ввод         //и логика     } } 

Итого, этот пример создаёт на экране кнопку при нажатии на которую в стандартном потоке вывода появится надпись "Button was clicked" и текст кнопки изменится.

Инициализация

Инициализация предполагает только лишь запуск драйвера, задание размеров и выделение памяти для структур и буфферов элементов. Чисто формальная операция. Как инициализировать систему можно поглядеть тут: https://github.com/SL-RU/MakiseSDLTest/blob/master/src/main.c в методе start_m();

Для начала использования GUI нужно создать makise_config.h и сконфигурировать его. В этом файле задаются системные дефайны и выбираются нужные драйверы дисплея. https://github.com/SL-RU/MakiseSDLTest/blob/master/makise_config.h

Ввод

Ввод приспособлен для работы в мультипоточных приложениях — он имеет очередь событий, которые посылаются интерфейсу при вызове makise_gui_input_perform(host);

Любое событие ввода представлено структурой MInputData.

Возможен ввод кнопок(список стандартных в makise_gui_input.h MInputKeyEnum), символов(пока нигде не используется) и ввод курсора(сенсорный экран или мышь). В примере с SDL используется ввод с клавиатуры и ввод мышью.

Контейнеры.

MContainer — структура контейнера.

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

Позиция элемента в контейнере прямо влияет на очередь отрисовки и ввода.

Линкованый список осуществляется при помощи указателей на первый и последний элемент списка MElement и в структуре MElement имеются указатели на следующий и предыдущий элемент.

Элементы.

Любой элемент представлен ввиде структуры MElement, которая содержит в себе информацию о элементе, указатели на функции отрисовки, ввода, фокуса и тд элемента и указатель на его содержимое.

На данный момент существуют следующие элементы:

  • MButton — кнопка. Которая отображает текст посылает события при нажатии
  • MCanvas — простейший контейнер, который просто содержит элементы.
  • MLable — простейшее текстовое поле
  • MTextField — текстовое поле, поддерживающее перенос слов и переносы
  • MSlider — слайдер
  • MToggle — кнопка имеющая два состояния.
  • MSlist — список. Может быть как просто списком, так и radioкнопками, так и чекбосками. Поддерживает обычные списки и динамические линкованные.
  • MTabs — вкладки. Несколько переключаемых контейнеров.

Лучшей документацией являются примеры, поэтому для каждого элемента есть свои примеры использования. Как сложные, так и простые.

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

Стили

Стиль элемента определяет его внешний вид. Cтиль задаёт цвета элемента в определённом состоянии. За это отвечают структуры MakiseStyle и MakiseStyleTheme. MakiseStyle содержит несколько MakiseStyleTheme для определённых состояний, а так же параметры шрифта.

Для кнопки стиль может выглядеть так:

MakiseStyle ts_button = {     MC_White,  //основной цвет. Не несёт никакого значения     &F_Arial24,//Шрифт стиля     0, //межстрочное расстояние     //цвет заднего фона | шрифта   бортик    есть лидвойной бортик     {MC_Black,           MC_Gray,  MC_Gray,  0     }, //когда кнопка не активна     {MC_Black,           MC_White, MC_White, 0     }, //нормальное состояние     {MC_White,           MC_Green, MC_White, 0     }, //в фокусе     {MC_Green,           MC_White, MC_White, 0     }, //когда была кликнута };

Фокус

Фокус определяет к какому элементу пойдёт ввод. Для управления фокусом существуют следующие функции:

MFocusEnum makise_g_focus(MElement *el, MFocusEnum event); //фокусирует или расфокусирует нужный элемент MFocusEnum makise_g_host_focus_next(MHost *host);//переведёт фокус на следующий по очереди элемент MFocusEnum makise_g_host_focus_prev(MHost *host);//на предыдущий

Пример работы на микроконтроллере

Так же был написан пример библиотеки для STM32 микроконтроллеров. Был использован МК STM32f437VGT6 с тактовой частотой 180МГц и 2.2" дисплей 230х320 пикселей на контроллере ILI9341.

Код примера: https://github.com/SL-RU/MakiseILI9341Test

Видео примера:

Немножко документации есть в репозитории. Но вся основная документация находиться в комментариях к функциям и в примерах. Задавайте вопросы! На основе них я буду дописывать документацию. Много моментов не было затронуто в статье или затронуто мимоходом. Если статья найдёт популярность, то с удовольствием напишу ещё несколько, например про создание драйвера для STM32 + tft дисплей, подключенный по FSMC для данного GUI.

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

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

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

Буду рад вопросам и пожеланиям!

ссылка на оригинал статьи https://habrahabr.ru/post/325692/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *