
Расскажу подход в оживлении цепей и функциональных блоков в своей среде разработки под ПЛК. Я не использую никаких графических фреймворков и библиотек, тут как раз случай когда самому сделать быстрее чем изучать что то новое. Все функциональные блоки программы отображающие в среде на ПК : рисуют примитивами (прямоугольниками, линиями, точками,текстом etc…) .
На этапе проектирования платформы я сразу взял за цель — максимальную гибкость: пользователь сам может нарисовать функциональный блок, обозначить его сигналы, и сделать описание поведения в цепи. Для этого я сделал шаблон:
<LD_Unit Name="SEND" Group="Message" Width="120" Height="80"> <Variables> -----Входящие сигналы/Переменные----------- </Variables> <types> SEND typedef { Структура } </types> <lists> Линия ------- Квадрат------ Текст-------- </lists> <code> <Line> ------------------------- КОД ----------------------- </Line> </code> </LD_Unit>
Главное — те примитивы которые будут анимированы, привязываются к переменным:
<Item Type="LINE" color="#ffffff" Style="onoff:#96C1FF"> <Value>this</Value>...После запуска проекта, Item Type="LINE" - конвертируется в обьект.
Style=“onoff:#96C1FF” — как раз и говорит что делать- если значение переменной больше 0, меняем цвет, положение, текст и другие эффекты.
Компилятор.
Компилятор — собственной разработки, не LLVM\Clang и подобные конструкторы. Вся логика расстановки переменных и инструкций в памяти разрабатывал сам, и вместе с программой для ПЛК создается файл на подобии .elf:
--- DISASSEMBLY & BINARY CODE ---Instruction [Offset] | Binary Representation (MSB..LSB)------------------------------------------------------------------------0] LDRI R3 Address: 818 | 00000110 00110000 00000011 001100104] LDPHY R3 R3 R0 | 00001001 00011000 11000000 000000008] SDRI R3 Address: 814 | 00001101 00110000 00000011 0010111012] MOV R0 R28 R0 | 00111100 00000111 00000000 0000000016] SDRI R0 Address: 818 | 00001101 00000000 00000011 00110010--- SYMBOLS & VARIABLES MEMORY MAP ---Address | Name | Type | Size --------------------------------------------------------------------------------------818 | system.AddrTime | dword | 4 814 | system.Time | dword | 4 778 | system.IN_phy | pointer | 4 798 | system.emodule_.DI_0 | byte | 1 800 | system.emodule_.DI_2 | byte | 1 804 | system.emodule_.DI_6 | byte | 1
--- SYMBOLS & VARIABLES MEMORY MAP ---Address | Name | Type | Size --------------------------------------------------------------------------------------818 | system.AddrTime | dword | 4 814 | system.Time | dword | 4 778 | system.IN_phy | pointer | 4 798 | system.emodule_.DI_0 | byte | 1 800 | system.emodule_.DI_2 | byte | 1 804 | system.emodule_.DI_6 | byte | 1
Вместе с человекочитамым текстом формируется файл для моей среды разработки:
#####XML_SYMBOLS_BEGIN#####<?xml version="1.0" encoding="UTF-8"?><symbols> <symbol name="system.AddrTime" type="dword" address="818" size="4"/> <symbol name="system.Time" type="dword" address="814" size="4"/> <symbol name="system.IN_phy" type="pointer" address="778" size="4"/> <symbol name="system.emodule_.DI_0" type="byte" address="798" size="1"/> <symbol name="system.emodule_.DI_2" type="byte" address="800" size="1"/>
Тут содержится имя переменной, ее тип и адрес. Это позволяет не только отправить команду чтоб записать в переменную какое то значение, но и читать:
Теперь когда компилятор вернул нам регион памяти переменных, мы отправляем команду на МК — просто прислать нам регион памяти (а память у нас виртуальная, обычный массив uint8_t meory[size] )
Получаем в среде этот регион из массива, и среда уже понимает какая переменна за что отвечает, а движок отрисовки на этих значениях знает что делать.
В целом графика выглядит так:
Очень легкая среда которая даже в режиме отрисовки занимает в ОЗУ всего 120 Мб, и может работать даже на первых версиях Raspberry PI (Среда разработана с Open JDK).
ссылка на оригинал статьи https://habr.com/ru/articles/1103196/