Предоставляет основанные на java подобном языке вычислитель и движок библиотек. Пользователь может создавать и модифицировать функции и их библиотеки.
Лицензия:
GPL
Введение
Модуль контроллера JavaLikeCalc предоставляет в систему OpenSCADA механизм создания функций и их библиотек на Java-подобном языке. Описание функции на Java-подобном языке сводится к обвязке параметров функции алгоритмом. Кроме этого модуль наделен функциями непосредственных вычислений путём создания вычислительных контроллеров.
Непосредственные вычисления обеспечиваются созданием контроллера и связыванием его с функцией этого же модуля. Для связанной функции создаётся кадр значений, над которым и выполняются периодические вычисления.
Модулем реализуются функции горизонтального резервирования, а именно — совместной работы с удалённой станцией этого-же уровня. Кроме синхронизации значений и архивов атрибутов параметров модулем осуществляется синхронизация значений вычислительной функции, с целью безударного "подхвата" алгоритмов.
Параметры функции могут свободно создаваться, удаляться или модифицироваться. Текущая версия модуля поддерживает до 65535 параметров функции в сумме с внутренними переменными. Вид редактора функций показан на рис.1.
Рис.1. Вид редактора функций.
После любого изменения программы или конфигурации параметров выполняется перекомпиляция программы с уведомлением связанных с функцией объектов значений TValCfg. Компилятор языка построен с использованием известного генератора грамматики "Bison", который совместим с не менее известной утилитой "Yacc".
Язык использует неявное определение локальных переменных, которое заключается в определении новой переменной в случае присваивания ей значения. Причём тип локальной переменной устанавливается в соответствии с типом присваиваемого значения. Например, выражение Qr=Q0*Pi+0.01; определит переменную Qr с типом переменной Q0.
В работе с различными типами данных язык использует механизм автоматического приведения типов в местах, где подобное приведение является целесообразным.
Для комментирования участков кода в языке предусмотрены символы "//" и "/* ... */". Всё, что идёт после "//" до конца строки и между "/* ... */", игнорируется компилятором.
В процессе генерации кода компилятор языка производит оптимизацию по константам и приведение типов констант к требуемому типу. Под оптимизацией констант подразумевается выполнение вычислений в процессе построения байт-кода над двумя константами и вставка результата в код. Например, выражение y=pi*10; свернётся в простое присваивание y=31.4159;. Под приведением типов констант к требуемому типу подразумевается формирования в коде константы, которая исключает приведение типа в процессе исполнения. Например, выражение y=x*10, в случае вещественного типа переменной x, преобразуется в y=x*10.0.
Выражения присваивания могут записываться через символ ',', например:
Язык поддерживает вызовы внешних и внутренних функций. Имя любой функции вообще воспринимается как символ, проверка на принадлежность которого к той или иной категории производится в следующем порядке:
не начинается с точки:
ключевые слова (if, else, while, ...);
параметры-атрибуты данной функции;
именованные-встроенные постоянные (EVAL, pi, e, ...) и постоянные-объекты (SYS, arguments)
встроенные функции (sin, cos, ...);
внутренние, внешние функции, функции объекта и системных узлов OpenSCADA (DOM);
зарегистрированные ранее автоматические переменные;
глобальные атрибуты параметров DAQ и свойства переменных;
ключевые слова (in, var);
новая автоматическая переменная.
начинается с точки:
элементы пути к свойству и функции объекта.
Вызов внешней функции, как и атрибута системного параметра, записывается как адрес к объекту динамического дерева объектной модели системы OpenSCADA в виде: "DAQ.JavaLikeCalc.lib_techApp.klapNotLin". Для статических функций Вы можете осуществлять динамическое подключение, следующим образом:
Для предоставления возможности написания пользовательских процедур управления различными компонентами OpenSCADA этим модулем предоставляется реализация API прекомпиляции пользовательских процедур отдельных компонентов OpenSCADA на реализации Java-подобного языка. Такими компонентами, например, являются: Шаблоны параметров подсистемы "Сбор данных" и Среда визуализации и управления (СВУ).
строка: последовательность символов-байтов (0...255) любой длины, ограниченной объёмом памяти и хранилищем в БД; EVAL_STR("<EVAL>").
Встроенные константы: pi = 3.14159265, e = 2.71828182, EVAL_BOOL(2), EVAL_INT(-9223372036854775807), EVAL_REAL,EVAL(-1.79E308), EVAL_STR("<EVAL>") Атрибуты параметров системы OpenSCADA (начиная с подсистемы DAQ, в виде "{Тип модуля DAQ}.{Контроллер}.{Параметр}.{Атрибут}"). Функции объектной модели системы OpenSCADA.
1.2. Операции языка
Операции, поддерживаемые языком, представлены в таблице ниже. Приоритет операций уменьшается сверху вниз. Операции с одинаковым приоритетом входят в одну цветовую группу.
Символ
Описание
()
Вызов функции.
{}
Программные блоки.
++
Инкремент (пост и пре).
--
Декремент (пост и пре).
-
Унарный минус.
!
Логическое отрицание.
~
Побитовое отрицание.
*
Умножение.
/
Деление.
%
Остаток от целочисленного деления.
+
Сложение
-
Вычитание
<<
Поразрядный сдвиг влево
>>
Поразрядный сдвиг вправо
>
Больше
>=
Больше или равно
<
Меньше
<=
Меньше или равно
==
Равно
!=
Не равно
|
Поразрядное "ИЛИ"
&
Поразрядное "И"
^
Поразрядное "Исключающее ИЛИ"
&&
Логический "И"
||
Логический "ИЛИ"
?:
Условная операция "i=(i<0)?0:i;"
=
Присваивание.
+=
Присваивание со сложением.
-=
Присваивание с вычитанием.
*=
Присваивание с умножением.
/=
Присваивание с делением.
1.3. Встроенные функции языка
Виртуальной машиной языка предусматривается следующий набор встроенных функций общего назначения:
double max(double x, double x1) — максимальное значение из x и x1;
double min(double x, double x1) — минимальное значение из x и x1;
string typeof(ElTp vl) — тип значения vl;
string tr(string base) — перевод базового base сообщения.
Для обеспечения высокой скорости работы в математических вычислениях модуль предоставляет встроенные математические функции, которые вызываются на уровне команд виртуальной машины:
double sin(double x) — синус x;
double cos(double x) — косинус x;
double tan(double x) — тангенс x;
double sinh(double x) — синус гиперболический от x;
double cosh(double x) — косинус гиперболический от x;
double tanh(double x) — тангенс гиперболический от x;
double asin(double x) — арксинус от x;
double acos(double x) — арккосинус от x;
double atan(double x) — арктангенс от x;
double rand(double x) — случайное число от 0 до x;
double lg(double x) — десятичный логарифм от x;
double ln(double x) — натуральный логарифм от x;
double exp(double x) — экспонента от x;
double pow(double x, double x1) — возведение x в степень x1;
double sqrt(double x) — корень квадратный от x;
double abs(double x) — абсолютное значение от x;
double sign(double x) — знак числа x;
double ceil(double x) — округление числа x до большего целого;
double floor(double x) — округление числа x до меньшего целого.
1.4. Операторы языка
Общий перечень операторов языка:
var — оператор инициализации переменной; указание переменной без присваивания значения резервирует её со значением EVAL, что позволяет осуществлять единоразовую инициализацию сложных типов данных вроде объекта, через проверку на "isEVal()";
if — оператор условия "Если";
else — оператор условия "Иначе";
while — описание цикла "Пока";
for — описание цикла "Для";
in — разделитель цикла "Для" для перебора свойств объекта;
break — прерывание выполнения цикла;
continue — продолжить выполнение цикла с начала;
function — определение внутренней функции;
using — позволяет установить область видимости функций часто используемой библиотеки (using Special.FLibSYS;) для последующего обращения только по имени функции, не имеет эффекта для объектного доступа;
return — прерывание функции и возврат результата, который копируется в атрибут с флагом возврата (return 123;); в середине внутренней функции осуществляется её завершение с указанным результатом;
new — создание объекта, реализованы: объект "Object", массив "Array" и регулярные выражения "RegExp";
delete — удаление/освобождение объекта или его свойств, при этом: внутренние переменные устанавливаются в EVAL_REAL, внешние заменяются пустым объектом, а свойства объекта очищаются.
1.4.1. Условные операторы
Языком модуля поддерживаются два типа условий. Первый — это операции условия для использования внутри выражения, второй — глобальный, основанный на условных операторах.
Условие внутри выражения строится на операциях '?' и ':'. В качестве примера можно записать следующее практическое выражение st_open=(pos>=100)?true:false;, что читается как "Если переменная pos больше или равна 100, то переменной st_open присваивается значение true, иначе — false".
Глобальное условие строится на основе условных операторов "if" и "else". В качестве примера можно привести тоже выражение, но записанное другим способом if(pos>100) st_open=true; else st_open=false;. Как видно, выражение записано по другому, но читается также.
1.4.2. Циклы
Поддерживаются три типа циклов: while, for и for-in. Синтаксис циклов соответствует языкам программирования: C++, Java и JavaScript.
Цикл while, в общем, записывается следующим образом: while({условие}) {тело цикла};
Цикл for записывается следующим образом: for({пре-инициализ};{условие};{пост-вычисление}) {тело цикла};
Цикл for-in записывается следующим образом: for({переменная} in {объект}) {тело цикла};
Где:
{условие} — выражение, определяющее условие; {тело цикла} — тело цикла множественного исполнения; {пре-инициализ} — выражение предварительной инициализации переменных цикла; {пост-вычисление} — выражение модификации параметров цикла после очередной итерации; {переменная} — переменная, которая будет содержать имя свойства объекта при переборе; {объект} — объект для которого осуществляется перебор свойств.
1.4.3. Внутренние функции
Данный язык поддерживает определение и вызов внутренних функций. Для определения внутренней функции используется ключевое слово "function" и в целом определение имеет синтаксис: function {имяФ} ({пер1}, {пер2}, ... {перN}) { {тело функции} }. Определение внутренней функции внутри другой недопустимо однако допустим вызов ранее определённой.
Вызов внутренней функции осуществляется в типовой способ, как процедура {имяФ}({var1}, {var2}, ... {varN}); или как функция {перРез} = {имяФ}({пер1}, {пер2}, ... {перN});. Вызов внутренних функций допустим только после их декларации выше!
Все переменные, определённые в основном теле, недоступны в середине внутренних функций и могут быть переданы только через двухсторонние аргументы вызываемой внутренней функции. Все переменные, определённые в середине внутренней функции, имеют собственную область имён и недоступны из основного тела или любой другой внутренней функции и могут быть переданы только в основное тело через двухсторонние аргументы или результат вызываемой внутренней функции.
Оператор "return" в середине внутренней функции осуществляет контролируемое её завершение и помещение указанной переменной или результата выражения как результат вызываемой внутренней функции.
Пример типового определения и использования внутренней функции представлено ниже:
1.4.4. Специальные символы строковых переменных
Языком предусмотрена поддержка следующих специальных символов строковых переменных:
"\n" — перевод строки;
"\t" — символ табуляции;
"\b" — забой;
"\f" — перевод страницы;
"\r" — возврат каретки;
"\\" — сам символ '\';
"\041" — символ '!' записанный восьмеричным числом;
"\x21" — символ '!' записанный шестнадцатеричным числом.
1.5. Объект
Языком предоставляется поддержка типа данных объект "Object". Объект представляет собой ассоциативный контейнер свойств и функций. Свойства могут содержать как данные четырёх базовых типов, так и другие объекты. Доступ к свойствам объекта может осуществляться посредством записи имён свойств через точку к объекту obj.prop, а также посредством заключения имени свойства в квадратные скобки obj["prop"]. Очевидно, что первый механизм статичен, а второй позволяет указывать имя свойства через переменную. Удалить свойство объекта можно директивой "delete". Создание объекта осуществляется посредством ключевого слова new: varO = new Object(). Базовое определение объекта не содержит функций. Операции копирования объекта на самом деле делают ссылку на исходный объект. При удалении объекта осуществляется уменьшение счётчика ссылок, а при достижении счётчика ссылок нуля объект удаляется физически.
Разные компоненты могут доопределять базовый объект особыми свойствами и функциями. Стандартным расширением объекта является массив "Array", который создаётся командой varO = new Array(prm1,prm2,prm3,...,prmN). Перечисленные через запятую параметры помещаются в массив в исходном порядке. Если параметр только один то массив инициируется указанным количеством пустых элементов. Особенностью массива является то, что он работает со свойствами как с индексами и основным механизмом обращения является заключение индекса в квадратные скобки arr[1]. Массив хранит свойства в собственном контейнере одномерного массива. Цифровые свойства массива используются для доступа непосредственно к массиву, а символьные работают как свойства объекта. Детальнее про свойства и функции массива можно прочитать по ссылке.
Объект регулярного выражения "RegExp" создаётся командой varO = new RegExp(pat,flg), где pat — шаблон регулярного выражения, а flg — флаги поиска. Объект работы с регулярными выражениями основан на библиотеке "PCRE". При глобальном поиске устанавливается атрибут объекта "lastIndex", что позволяет продолжить поиск при следующем вызове функции. В случае неудачного поиска атрибут "lastIndex" сбрасывается в ноль. Детальнее про свойства и функции объекта регулярного выражения можно прочитать по ссылке.
Для произвольного доступа к аргументам функции предусмотрен объект аргументов, обратиться к которому можно посредством символа "arguments". Этот объект содержит свойство "length" с количеством аргументов у функции и позволяет обратиться к значению аргумента посредством его номера или идентификатора. Рассмотрим перебор аргументов по циклу:
args = new Array();
for(var i=0; i < arguments.length; i++)
args[i] = arguments[i];
Частичными свойствами объекта обладают и базовые типы. Свойства и функции базовых типов приведены ниже:
Нулевой тип, функции:
bool isEVal(); — Возвращает "true".
Логический тип, функции:
bool isEVal(); — Проверка значения на "EVAL".
string toString(); — Представление значения в виде строки "true" или "false".
Целое и вещественное число:
Свойства:
MAX_VALUE — максимальное значение;
MIN_VALUE — минимальное значение;
NaN — недостоверное значение.
Функции:
bool isEVal(); — Проверка значения на "EVAL".
string toExponential( int numbs = -1 ); — Возврат строки, отформатированного числа в экспоненциальной нотации и количеством значащих цифр numbs. Если numbs отсутствует то цифр будет столько сколько необходимо.
string toFixed( int numbs = 0, int len = 0, bool sign = false ); — Возврат строки отформатированного числа в нотации с фиксированной точкой и количеством цифр после десятичной точки numbs с минимальной длиной len и обязательным знаком sign. Если numbs отсутствует то количество цифр после десятичной точки равно нулю.
string toPrecision( int prec = -1 ); — Возврат строки отформатированного числа с количеством значащих цифр prec.
string toString( int base = 10, int len = -1, bool sign = false ); — Возврат строки отформатированного числа целого типа с базой представления base (2-36) с минимальной длиной len и обязательным знаком sign.
Строка:
Свойства:
int length — длина строки.
Функции:
bool isEVal(); — Проверка значения на "EVAL".
string charAt( int symb ); — Извлекает из строки символ номер symb, нумерация символов с нуля.
int charCodeAt( int symb ); — Извлекает из строки код символа symb.
string concat( string val1, string val2, ... ); — Возвращает новую строку сформированную путём присоединения значений val1 и т.д. к исходной.
int indexOf( string substr, int start ); — Возвращает позицию искомой строки substr в исходной строке начиная с позиции start. Если исходная позиция не указана то поиск начинается с начала. Если искомой строки не найдено то возвращается "-1".
int lastIndexOf( string substr, int start ); — Возвращает позицию искомой строки substr в исходной строке начиная с позиции start, при поиске с конца. Если исходная позиция не указана то поиск начинается с конца. Если искомой строки не найдено то возвращается "-1".
int search( string pat, string flg = "" ); — Поиск в строке по шаблону pat и флагами шаблона flg. Возвращает положение найденной подстроки иначе "-1".
var rez = "Java123Script".search("script","i"); // rez = 7
int search( RegExp pat ); — Поиск в строке по шаблону "RegExp" pat. Возвращает положение найденной подстроки иначе "-1".
var rez = "Java123Script".search(new RegExp("script","i")); // rez = 7
Array match( string pat, string flg = "" ); — Поиск в строке по шаблону pat и флагами шаблона flg. Возвращает массив с найденной подстрокой (0) и подвыражениями (>1). Атрибут "index" массива устанавливается в позицию найденной подстроки. Атрибут "input" устанавливается в исходную строку.
Array match( TRegExp pat ); — Поиск в строке по шаблону "RegExp" pat. Возвращает массив с найденной подстрокой (0) и подвыражениями (>1). Атрибут "index" массива устанавливается в позицию найденной подстроки. Атрибут "input" устанавливается в исходную строку.
string slice( int beg, int end ); string substring( int beg, int end ); — Возврат подстроки извлечённой из исходной начиная с позиции beg и заканчивая end, нумерация с нуля. Если значение начала или конца отрицательно, то отсчёт ведётся с конца строки. Если конец не указан, то концом является конец строки. Например, конструкция substring(-2) вернет последние два символа строки.
Array split( string sep, int limit ); — Возврат массива элементов строки разделённых sep с ограничением количества элементов limit.
Array split( RegExp pat, int limit ); — Возврат массива элементов строки разделённых шаблоном "RegExp" pat с ограничением количества элементов limit.
real toReal(); — Преобразование текущей строки в вещественное число.
int toInt( int base = 0 ); — Преобразование текущей строки в целое число, в соответствии с основанием base (от 2 до 36). Если основание равно 0 то будет учитываться префиксная запись для определения основания (123-десятичное; 0123-восьмеричное; 0x123-шестнадцатиричное).
string parse( int pos, string sep = ".", int off = 0 ); — Выделение из исходной строки элемента pos для разделителя элементов sep от смещения off. Результирующее смещение помещается назад в off.
string parseLine( int pos, int off = 0 ); — Выделение строки с номером pos от смещения off. Результирующее смещение помещается назад в off.
string parsePath( int pos, int off = 0 ); — Выделение из исходного пути элемента pos от смещения off. Результирующее смещение помещается назад в off.
string path2sep( string sep = "." ); — Преобразование пути в текущей строке в строку с разделителем sep.
string trim( string cfg = " \n\t\r" ); — Обрезка строки с начала и конца для символов cfg.
Для доступа к системным объектам(узлам) OpenSCADA предусмотрен соответствующий объект, который создаётся путём простого указания точки входа "SYS" корневого объекта OpenSCADA, а затем, через точку указываются вложенные объекты в соответствии с иерархией. Например, вызов функции запроса через исходящий транспорт осуществляется следующим образом: SYS.Transport.Sockets.out_testModBus.messIO(Special.FLibSYS.strEnc2Bin("15 01 00 00 00 06 01 03 00 00 00 05"));.
1.6. Примеры программы на языке
Приведём несколько примеров программ на Java-подобном языке:
//Модель клапана
Qr = Q0 + Q0*Kpr*(Pi-1) + 0.01;
Sr = (S_kl1*l_kl1+S_kl2*l_kl2)/100;
Ftmp = (Pi>2*Po) ? Pi*pow(Q0*0.75/Ti,0.5) : (Po>2*Pi) ? Po*pow(Q0*0.75/To,0.5) : pow(abs(Q0*(pow(Pi,2)-pow(Po,2))/Ti),0.5);
Fi -= (Fi-7260*Sr*sign(Pi-Po)*Ftmp)/(0.01*lo*frq);
Po += 0.27*(Fi-Fo)/(So*lo*Q0*frq);
Po = (Po<0) ? 0 : (Po>100) ? 100 : Po;
To += (abs(Fi)*(Ti*pow(Po/Pi,0.02)-To)+(Fwind+1)*(Twind-To)/Riz)/(Ct*So*lo*Qr*frq);
2. Контроллер и его конфигурация
Контроллер этого модуля связывается с функциями из библиотек, построенных с его помощью, для обеспечения непосредственных вычислений. Для предоставления вычисленных данных в систему OpenSCADA в контроллере могут создаваться параметры. Пример вкладки конфигурации контроллера данного типа изображен на рис.2.
Рис.2. Вкладка конфигурации контроллера.
С помощью этой вкладки можно установить:
Состояние контроллера, а именно: Статус, "Включен", "Запущен" и имя БД, содержащей конфигурацию.
Идентификатор, имя и описание контроллера.
Состояние, в которое переводить контроллер при загрузке: "Включен" и "Запущен".
Имя таблицы для хранения параметров.
Адрес вычислительной функции.
Политика планирования вычисления, приоритет и число итераций в одном цикле задачи вычисления.
Вкладка "Вычисления" контроллера(Рис. 3) содержит параметры и текст программы, непосредственно выполняемой контроллером. Модулем предусмотрена обработка ряда специальных параметров, доступных в программе контроллера:
f_frq — Частота вычисления программы контроллера, только чтение.
f_start — Флаг первого выполнения программы контроллера, запуск, только чтение.
f_stop — Флаг последнего выполнения программы контроллера, останов, только чтение.
this — Объект данного контроллера.
Рис.3. Вкладка "Вычисления" контроллера.
3. Параметр контроллера и его конфигурация
Параметр контроллера данного модуля выполняет функцию предоставления доступа к результатам вычисления контроллера в систему OpenSCADA посредством атрибутов параметров. Из специфических полей вкладка конфигурации параметра контроллера содержит только поле перечисления параметров вычисляемой функции, которые необходимо отразить.
4. Библиотеки функций модуля
Модуль предоставляет механизм для создания библиотек пользовательских функций на Java-подобном языке. Пример вкладки конфигурации библиотеки изображен на Рис.4. Вкладка содержит базовые поля: доступность, адрес таблицы БД библиотеки, дата и время модификации, идентификатор, имя и описание.
Рис.4. Вкладка конфигурации библиотеки.
5. Пользовательские функции модуля
Функция, также как и библиотека, содержит базовую вкладку конфигурации, вкладку формирования программы и параметров функции (Рис.1), а также вкладку исполнения созданной функции.
6. API пользовательского программирования
Некоторые объекты модуля предоставляют функции пользовательского программирования.
Объект "Библиотека функций" (SYS.DAQ.JavaLikeCalc["lib_Lfunc"])
ElTp {funcID}(ElTp prm1, ...) — вызов функции "funcID" библиотеки "Lfunc". Возвращает результат вызываемой функции. Префикс "lib_" перед идентификатором библиотеки обязателен!
Объект "Пользовательская функция" (SYS.DAQ.JavaLikeCalc["lib_Lfunc"]["func"])
ElTp call(ElTp prm1, ...) — вызов функции "func" библиотеки "Lfunc" с параметрами "prm{N}". Возвращает результат вызываемой функции. Префикс "lib_" перед идентификатором библиотеки обязателен!
7. Производительность
Исходный текст процедур на языке этого модуля компилируются в байт-код виртуальной машины, который впоследствии вычисляется виртуальной машиной. Байт-код это не машинный код и достичь производительности самой аппаратной архитектуры в виртуальной машине его исполняющего теоретически нереально, если конечно код этой виртуальной машины не исполняет сам процессор. Т.е. производительность выполнения байт-кода примерно на порядок ниже аппаратной производительности за счёт накладных расходов команд виртуальной машины, разделения многопоточного доступа к данным, прозрачного приведения типов и отсутствия жёсткой типизации, а так-же динамической природы языка и наличия сложных типов "Строка" и "Объект".
28.01.2006: Основание: Первичная оценка производительности виртуальной машины системы OpenSCADA на основе выражения "y=x1+x2", где все переменные глобальные вещественного типа.
Стадия
Действие
K7_1G-0, мкс
1
Инициализация списка регистров
2.3
2
Вход в функцию exec()
3
3
Обход команд
4.4
4
Чтение
9
5
Полное время
10.2
17.07.2013: Основание: Обоснование текущей производительности, оценка и оптимизация. Измерения проводились выборкой минимального времени из пяти вызовов по 1000 исполнений формулы "a -= b*(a-c)" и её сокращений в каждом вызове. Все переменные глобальные вещественного типа.
!> use unified TVariant function setVal() and getVal() = 7.6 (2.7 write only) => fix to 5.0 by prevent default set to string EVAL.
=> full call: 2.5 (0.33)
=> only write const: 2.17 (0.47)
=> only check for type: 1.7 (0.3)
=> pass code: 1.4 (0.11)
Write to function IO is longer then read from local register by other context call and additional checking for NAN and real modification.
Empty
1.29
Infrastructure and measurement method utilization time.
24.04.2016: Reason: Estimate performance of access to low level IO lines on Raspberry Pi GPIO in different ways of JavaLikeCalc language of OpenSCADA. Conditions:Raspberry Pi 3, GPIO40, DAQ.BCM2835 (based on library bcm2835)
Operation
Result, us
Sleep. Lag on sleep in 1ms measured, which mostly limited by the realtime reaction about 100us.
SYS.sleep();
+110
Special.FLibSYS.fnc_tmSleep();
+70
Sleep. Lag on sleep in 100us measured, which performs in the measuring cycle.
SYS.sleep();
+17
Special.FLibSYS.fnc_tmSleep();
+2
Get GPIO pin's level
From an attribute res = BCM2835.pi2.pi2.gpio17;
5.4
By the static accessing function res = DAQ.BCM2835.pi2.pi2.fnc_get(17);
1.6
By the static accessing function with prepare the link function get = "DAQ.BCM2835.pi2.pi2.fnc_get"; for(i = 0; i < 10000; i++) res = get(17);
1.7
By the dynamic accessing function res = SYS.DAQ.BCM2835.pi2.pi2.fnc_get.call(17);
80
By the dynamic accessing function with prepare the end object tO = SYS.DAQ.BCM2835.pi2.pi2.fnc_get; for(i = 0; i < 1000; i++) res = tO.call(17);
14.3
Put GPIO pin's level
To an attribute BCM2835.pi2.pi2.gpio18 = true;
2.1
By the static accessing function DAQ.BCM2835.pi2.pi2.fnc_put(18, true);
1.4
By the static accessing function with prepare the link function put = "DAQ.BCM2835.pi2.pi2.fnc_put"; for(i = 0; i < 10000; i++) put(17, false);
1.5
By the dynamic accessing function SYS.DAQ.BCM2835.pi2.pi2.fnc_put.call(18, true);
79
By the dynamic accessing function with prepare the end object tO = SYS.DAQ.BCM2835.pi2.pi2.fnc_put; for(i = 0; i < 1000; i++) tO.call(18, true);