Битовые операции — различия между версиями
(Новая страница: «123») |
(Отметить эту версию для перевода) |
||
(не показано 6 промежуточных версий этого же участника) | |||
Строка 1: | Строка 1: | ||
− | + | <languages/> | |
+ | <translate> | ||
+ | === Битовые операции === <!--T:1--> | ||
+ | |||
+ | ==== Удобные битовые операции ==== <!--T:2--> | ||
+ | Можно определить несколько удобных битовых операций, помня о том что в lua биты нумеруются с 1. Ссылка взята [http://lua-users.org/wiki/BitwiseOperators отсюда], там же есть и другие полезные функции. | ||
+ | |||
+ | <!--T:3--> | ||
+ | <syntaxhighlight lang = lua> | ||
+ | |||
+ | <!--T:4--> | ||
+ | function bit(n) | ||
+ | return 2 ^ (n - 1) -- возвращает число - вес разряда номер n | ||
+ | end | ||
+ | |||
+ | <!--T:5--> | ||
+ | function hasbit(x, p) | ||
+ | return x % (p + p) >= p -- возвращает состояние бита p как true/false; if hasbit(value, bit(2)) then ... | ||
+ | end | ||
+ | |||
+ | <!--T:6--> | ||
+ | function setbit(x, p) | ||
+ | return hasbit(x, p) and x or x + p -- установить бит № p в х Пример использования: х = setbit(х, bit(p)) | ||
+ | end | ||
+ | |||
+ | <!--T:7--> | ||
+ | function clearbit(x, p) | ||
+ | return hasbit(x, p) and x - p or x -- тоже только снять бит | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Преобразование битовой таблички в число ==== <!--T:8--> | ||
+ | Данная функция может быть полезна для нестандартных преобразований, когда число хранится в специфичном формате и его необходимо обработать по частям, используя заданную позицию 1-го бита и длину поля значения. | ||
+ | |||
+ | <!--T:9--> | ||
+ | <syntaxhighlight lang = "lua"> | ||
+ | |||
+ | <!--T:10--> | ||
+ | function getNumberFromTab(tab,start,length) -- получить число из таблички | ||
+ | local result_str = ""; | ||
+ | |||
+ | for i=start,(start+length-1) do | ||
+ | result_str = result_str..tostring(tab[i]); | ||
+ | end | ||
+ | return tonumber(result_str,2); | ||
+ | end -- getNumberFromTab | ||
+ | |||
+ | <!--T:11--> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Преобразование числа в битовую табличку ==== <!--T:12--> | ||
+ | |||
+ | <!--T:13--> | ||
+ | В lua (в версии, используемой в WebHMI) нет встроенной операции получения строкового представления двоичного числа. | ||
+ | Однако эта функция очень полезна в пользовательсиких протоколах и др. задачах, где требуется перераспределить или каким то образом обработать отдельные биты числа. | ||
+ | Текст варианта такой функции: | ||
+ | |||
+ | <!--T:14--> | ||
+ | <syntaxhighlight lang = "lua"> | ||
+ | |||
+ | |||
+ | |||
+ | <!--T:15--> | ||
+ | function getBits(input_num,length) -- работает с заданной длиной | ||
+ | |||
+ | local tab = {}; -- пустая табличка для ответа | ||
+ | local max_i = length - 1; | ||
+ | local remainder = input_num; -- остаток порязрядного взешивания | ||
+ | |||
+ | for i=max_i,0,-1 do | ||
+ | if remainder - 2^i >= 0 then | ||
+ | table.insert(tab, "1") ; | ||
+ | remainder = remainder - 2^i; | ||
+ | else | ||
+ | table.insert(tab, "0") ; | ||
+ | end | ||
+ | end | ||
+ | return tab; | ||
+ | end -- getBits | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <!--T:16--> | ||
+ | Далее можно переставить нужные биты местами и т.п. и получить нужное число. Ниже приведен пример перестановки битов 31 и 23 битов (при нумерации битов с 0) в ответе счетчика расходомера ВЛР 2301/2304 производства Асвега-У | ||
+ | |||
+ | <!--T:17--> | ||
+ | <syntaxhighlight lang = "lua"> | ||
+ | function main (userId) | ||
+ | |||
+ | local input_num = GetReg(3); -- прочитать регистр с числом | ||
+ | local bitTable = getBits(input_num,32); -- таблица для обработки результата | ||
+ | local tmp_bit = ""; -- вспомогательный бит | ||
+ | |||
+ | tmp_bit = bitTable[1]; | ||
+ | bitTable[1] = bitTable[9]; -- 31 бит это 1 элемент так как таблица развернута слева-направо, номера элементов табл.в lua c 1 | ||
+ | bitTable[9] = tmp_bit; | ||
+ | -- конкатенация готовой таблицы в строку и преобразование в число из строки двоичного представления | ||
+ | WriteReg(1, tonumber(table.concat(bitTable),2)); | ||
+ | |||
+ | <!--T:18--> | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Обработка чисел с плавающей точкой двойной точности ==== <!--T:19--> | ||
+ | |||
+ | <!--T:20--> | ||
+ | Некоторые устройства могут хранить данные в формате с повышенной точностью double float. В WebHMI текущей версии поддерживаются только 32 битные регистры, поэтому чтобы обработать 64 битное число необходимо будет использовать скрипт, которые "сцепит" два регистра в исходное число, а затем преобразует и запишет в обратно в float. Регистры должны быть типа double uint. | ||
+ | Для "сцепки" чисел можно использовать описанную выше функцию getBits чтобы получить 2 таблицы, а затем дополнить первую таблицу битами из второй используя table.insert. В этом примере в качестве проверочного числа для простоты используется константа. | ||
+ | |||
+ | <!--T:21--> | ||
+ | <syntaxhighlight lang = "lua"> | ||
+ | -------------------------------------- | ||
+ | local test_var = 0xC1D312D000000000; | ||
+ | local NaN = tonumber("11111111111111111111111111111111",2); | ||
+ | -------------------------------------- | ||
+ | |||
+ | <!--T:22--> | ||
+ | function main (userId) | ||
+ | -- получить результирующую табличку "0" "1" | ||
+ | local result_tab = getBits(test_var,64); | ||
+ | |||
+ | <!--T:23--> | ||
+ | WriteReg(11,table.concat(result_tab)); -- отладочная печать в регстр - строку | ||
+ | |||
+ | <!--T:24--> | ||
+ | local result_num = 0.0; -- для хранения результата | ||
+ | |||
+ | <!--T:25--> | ||
+ | local sign,exp,mantissa = 0,0,0; | ||
+ | local fraction_table = {}; -- табл. для дробной части | ||
+ | |||
+ | <!--T:26--> | ||
+ | -- определить знак | ||
+ | if result_tab[1] == "1" then | ||
+ | sign = -1; | ||
+ | else | ||
+ | sign = 1; | ||
+ | end | ||
+ | -- экспоненту | ||
+ | exp = getNumberFromTab(result_tab,2,11); | ||
+ | DEBUG("exp = "..tostring(exp)); -- отл. печать | ||
+ | -- мантиссу | ||
+ | for i=13,64 do | ||
+ | table.insert(fraction_table,result_tab[i]); | ||
+ | end | ||
+ | -- посчитать мантиссу по-разрядно !!! | ||
+ | for j=1,52 do | ||
+ | if fraction_table[j]=="1" then | ||
+ | mantissa = mantissa +(2^(-1*j)); | ||
+ | end | ||
+ | end | ||
+ | |||
+ | <!--T:27--> | ||
+ | mantissa = mantissa +1; | ||
+ | DEBUG("m = "..tostring(mantissa)); -- отл. печать | ||
+ | result_num = sign*(2^(exp - 1023))*mantissa; | ||
+ | |||
+ | <!--T:28--> | ||
+ | -- Обработка исключений | ||
+ | if exp == 0 then -- subnormals | ||
+ | result_num = sign*(2^(-1022))*(mantissa-1); | ||
+ | end | ||
+ | |||
+ | <!--T:29--> | ||
+ | if exp == 0x7ff then -- nan | ||
+ | result_num = NaN; | ||
+ | end | ||
+ | -- Вывод результата в регистр типа float | ||
+ | WriteReg(10, result_num); | ||
+ | |||
+ | <!--T:30--> | ||
+ | end -- main | ||
+ | |||
+ | <!--T:31--> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Формирование общего регистра аварий по разным условиям ==== <!--T:32--> | ||
+ | |||
+ | <!--T:33--> | ||
+ | В WebHMI есть механизм аварий. Т.е. по состоянию бита в регистре можно автоматически генерировать записи в журнале о моменте возникновения, снятия аварии, квитировании ее оператором. | ||
+ | |||
+ | <!--T:34--> | ||
+ | Однако в некоторых случаях использовать данный механизм непосредственно, как есть, может не совсем быть удобно. Например - аварийным считается определенный бит или их комбинация, разные коды ошибок (и их надо отличать друг от друга), значение больше или меньше порога и т.д. Если регистр имеет уже настроенные состояния для аварийной ситуации, используемое для отображения, то его нужно просто продублировать, выставив бит в общем аварийном регистре. Также может потребоваться введение задержки на срабатывание аварии, так как значение может иметь "дребезг" который надо фильтровать, прежде чем генерировать аварию в журнале. | ||
+ | Кроме этого удобнее, когда все аварии описаны в одном месте, а не разбросаны по сотням регистров. Т.е. рациональнее использовать один или несколько несколько 32-битных регистров для описания всех возможных аварий, и скрипт в котором эти аварии будут записываться в этот регистр по разным условиям. Ниже приведен пример такого скрипта: | ||
+ | |||
+ | <!--T:35--> | ||
+ | Допустим, есть некая функциональная единица, например приточная вентиляционная установка, в которой есть некий общий признак аварии, есть несколько регистров с кодами текущих ошибок от частотных преобразователей и ситуация, когда один из регистров (влажность, СО2 и др.) вышел за допустимый диапазон, что является также аварийной ситуацией. | ||
+ | [[Файл:Alerts.png | 800px | left]] | ||
+ | <br clear = all> | ||
+ | |||
+ | <!--T:36--> | ||
+ | Тогда скрипт, который обработает все эти ситуации и сформирует нужные флаги на своих местах может выглядеть так: | ||
+ | <syntaxhighlight lang = lua> | ||
+ | allAlerts = { -- регистр бит - код ошибки тип операции | ||
+ | {srcAlias = "pv1Status", bits = {[1] = 1}, checktype = "bit9"}, | ||
+ | {srcAlias = "vfdStatus_1", bits = {[2] = 10, [3] = 20, [4] = 30, [5] = 40}, checktype = "=="}, | ||
+ | {srcAlias = "vfdStatus_2", bits = {[6] = 10, [7] = 20, [8] = 30, [9] = 40}, checktype = "=="}, | ||
+ | {srcAlias = "pv1ZoneHumidity", bits = {[10] = 90}, checktype = ">="} | ||
+ | } | ||
+ | |||
+ | <!--T:51--> | ||
+ | intAlertReg = "alertsReg" -- ОБЩИЙ РЕГИСТР АВАРИЙ | ||
+ | |||
+ | <!--T:52--> | ||
+ | function main (userId) | ||
+ | |||
+ | <!--T:53--> | ||
+ | DEBUG("Entered script") | ||
+ | local alertInput, alertOut = 0,0 -- временные переменные для чтения аварий и формирования результата | ||
+ | local digit = 0 -- номер бита в исходном регистре, указывающий на аварию.. | ||
+ | --[[ | ||
+ | Если назвать единообразно все параметры, | ||
+ | из которых надо формировать аварии и сложить их в одну структуру, | ||
+ | тогда можно использовать только один цикл for, например так: | ||
+ | --]] | ||
+ | for i,v in pairs(allAlerts) do | ||
+ | alertInput = GetReg(v.srcAlias) -- читаем регистр | ||
+ | DEBUG("Регистр для анализа = ".." "..v.srcAlias.." = "..alertInput) | ||
+ | for j,k in pairs(v.bits) do -- выполнится по числу элементов в под-табличке bits | ||
+ | -- проверяем тип операции - точное совпадение или другое условие | ||
+ | if (v.checktype == "==") then | ||
+ | DEBUG("Тип сравнения - точное совпадение") | ||
+ | -- проверяем регистр на один из кодов ошибок | ||
+ | if (alertInput == k) then | ||
+ | alertOut = setbit(alertOut, bit(j)) | ||
+ | else | ||
+ | alertOut = clearbit(alertOut, bit(j)) | ||
+ | end | ||
+ | -- проверяем определенный бит | ||
+ | elseif (string.find(v.checktype, "bit%d+") ~= nil) then | ||
+ | -- %d+ паттерн любая последовательность цифр | ||
+ | DEBUG("Тип сравнения - проверка бита") | ||
+ | _, _, digit = string.find(v.checktype,"(%d+)") | ||
+ | digit = tonumber(digit) | ||
+ | DEBUG("digit = "..digit) | ||
+ | if hasbit(alertInput, bit(digit)) then -- если заданный бит установлен во входном регистре | ||
+ | alertOut = setbit(alertOut, bit(j)) | ||
+ | else | ||
+ | alertOut = clearbit(alertOut, bit(j)) | ||
+ | end | ||
+ | elseif (v.checktype == ">=") then | ||
+ | -- параметр больше чем значение | ||
+ | if (alertInput >= k) then | ||
+ | alertOut = setbit(alertOut, bit(j)) | ||
+ | else | ||
+ | alertOut = clearbit(alertOut, bit(j)) | ||
+ | end | ||
+ | else | ||
+ | --- другие операции | ||
+ | end -- if checktype | ||
+ | end -- for bits inside | ||
+ | |||
+ | <!--T:54--> | ||
+ | end -- for allAlerts | ||
+ | -- теперь просто записать то что получилось в общий регистр аварий | ||
+ | WriteReg(intAlertReg, alertOut) | ||
+ | |||
+ | <!--T:55--> | ||
+ | end -- main | ||
+ | |||
+ | |||
+ | <!--T:56--> | ||
+ | ----------------- ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ ---------------------------------- | ||
+ | |||
+ | <!--T:57--> | ||
+ | function bit(n) | ||
+ | return 2 ^ (n - 1) -- возвращает число - вес разряда номер n | ||
+ | end | ||
+ | |||
+ | <!--T:58--> | ||
+ | function hasbit(x, p) | ||
+ | return x % (p + p) >= p -- возвращает состояние бита p как true/false; if hasbit(value, bit(2)) then ... | ||
+ | end | ||
+ | |||
+ | <!--T:59--> | ||
+ | function setbit(x, p) | ||
+ | return hasbit(x, p) and x or x + p -- установить бит № p в х Пример использования: х = setbit(х, bit(p)) | ||
+ | end | ||
+ | |||
+ | <!--T:60--> | ||
+ | function clearbit(x, p) | ||
+ | return hasbit(x, p) and x - p or x -- тоже только снять бит | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | Если различных операций над значениями много: не только сравнение, но и например проверка конкретного бита и т.п. то можно детали реализации спрятать в функцию, которая получит на вход табличку с типом операции (установлен ли конкретный бит, код ошибки, параметр в границах и т.п.) и входным значением и поставит или сбросит нужный бит. | ||
+ | |||
+ | |||
+ | <!--T:49--> | ||
+ | <syntaxhighlight lang = lua> | ||
+ | |||
+ | |||
+ | <!--T:50--> | ||
+ | for i,v in pairs(allAlerts) do | ||
+ | alertInput = GetReg(v.srcAlias) -- читаем регистр | ||
+ | alertOut = MyGetAlerts(alertInput, alertOut, v) -- вызываем функцию, которая посмотрит что надо сделать по полю v[3], т.е. allAlerts[3] | ||
+ | end -- for | ||
+ | </syntaxhighlight> | ||
+ | </translate> |
Текущая версия на 12:36, 31 мая 2018
Содержание
Битовые операции
Удобные битовые операции
Можно определить несколько удобных битовых операций, помня о том что в lua биты нумеруются с 1. Ссылка взята отсюда, там же есть и другие полезные функции.
function bit(n)
return 2 ^ (n - 1) -- возвращает число - вес разряда номер n
end
function hasbit(x, p)
return x % (p + p) >= p -- возвращает состояние бита p как true/false; if hasbit(value, bit(2)) then ...
end
function setbit(x, p)
return hasbit(x, p) and x or x + p -- установить бит № p в х Пример использования: х = setbit(х, bit(p))
end
function clearbit(x, p)
return hasbit(x, p) and x - p or x -- тоже только снять бит
end
Преобразование битовой таблички в число
Данная функция может быть полезна для нестандартных преобразований, когда число хранится в специфичном формате и его необходимо обработать по частям, используя заданную позицию 1-го бита и длину поля значения.
function getNumberFromTab(tab,start,length) -- получить число из таблички
local result_str = "";
for i=start,(start+length-1) do
result_str = result_str..tostring(tab[i]);
end
return tonumber(result_str,2);
end -- getNumberFromTab
Преобразование числа в битовую табличку
В lua (в версии, используемой в WebHMI) нет встроенной операции получения строкового представления двоичного числа. Однако эта функция очень полезна в пользовательсиких протоколах и др. задачах, где требуется перераспределить или каким то образом обработать отдельные биты числа. Текст варианта такой функции:
function getBits(input_num,length) -- работает с заданной длиной
local tab = {}; -- пустая табличка для ответа
local max_i = length - 1;
local remainder = input_num; -- остаток порязрядного взешивания
for i=max_i,0,-1 do
if remainder - 2^i >= 0 then
table.insert(tab, "1") ;
remainder = remainder - 2^i;
else
table.insert(tab, "0") ;
end
end
return tab;
end -- getBits
Далее можно переставить нужные биты местами и т.п. и получить нужное число. Ниже приведен пример перестановки битов 31 и 23 битов (при нумерации битов с 0) в ответе счетчика расходомера ВЛР 2301/2304 производства Асвега-У
function main (userId)
local input_num = GetReg(3); -- прочитать регистр с числом
local bitTable = getBits(input_num,32); -- таблица для обработки результата
local tmp_bit = ""; -- вспомогательный бит
tmp_bit = bitTable[1];
bitTable[1] = bitTable[9]; -- 31 бит это 1 элемент так как таблица развернута слева-направо, номера элементов табл.в lua c 1
bitTable[9] = tmp_bit;
-- конкатенация готовой таблицы в строку и преобразование в число из строки двоичного представления
WriteReg(1, tonumber(table.concat(bitTable),2));
end
Обработка чисел с плавающей точкой двойной точности
Некоторые устройства могут хранить данные в формате с повышенной точностью double float. В WebHMI текущей версии поддерживаются только 32 битные регистры, поэтому чтобы обработать 64 битное число необходимо будет использовать скрипт, которые "сцепит" два регистра в исходное число, а затем преобразует и запишет в обратно в float. Регистры должны быть типа double uint. Для "сцепки" чисел можно использовать описанную выше функцию getBits чтобы получить 2 таблицы, а затем дополнить первую таблицу битами из второй используя table.insert. В этом примере в качестве проверочного числа для простоты используется константа.
--------------------------------------
local test_var = 0xC1D312D000000000;
local NaN = tonumber("11111111111111111111111111111111",2);
--------------------------------------
function main (userId)
-- получить результирующую табличку "0" "1"
local result_tab = getBits(test_var,64);
WriteReg(11,table.concat(result_tab)); -- отладочная печать в регстр - строку
local result_num = 0.0; -- для хранения результата
local sign,exp,mantissa = 0,0,0;
local fraction_table = {}; -- табл. для дробной части
-- определить знак
if result_tab[1] == "1" then
sign = -1;
else
sign = 1;
end
-- экспоненту
exp = getNumberFromTab(result_tab,2,11);
DEBUG("exp = "..tostring(exp)); -- отл. печать
-- мантиссу
for i=13,64 do
table.insert(fraction_table,result_tab[i]);
end
-- посчитать мантиссу по-разрядно !!!
for j=1,52 do
if fraction_table[j]=="1" then
mantissa = mantissa +(2^(-1*j));
end
end
mantissa = mantissa +1;
DEBUG("m = "..tostring(mantissa)); -- отл. печать
result_num = sign*(2^(exp - 1023))*mantissa;
-- Обработка исключений
if exp == 0 then -- subnormals
result_num = sign*(2^(-1022))*(mantissa-1);
end
if exp == 0x7ff then -- nan
result_num = NaN;
end
-- Вывод результата в регистр типа float
WriteReg(10, result_num);
end -- main
Формирование общего регистра аварий по разным условиям
В WebHMI есть механизм аварий. Т.е. по состоянию бита в регистре можно автоматически генерировать записи в журнале о моменте возникновения, снятия аварии, квитировании ее оператором.
Однако в некоторых случаях использовать данный механизм непосредственно, как есть, может не совсем быть удобно. Например - аварийным считается определенный бит или их комбинация, разные коды ошибок (и их надо отличать друг от друга), значение больше или меньше порога и т.д. Если регистр имеет уже настроенные состояния для аварийной ситуации, используемое для отображения, то его нужно просто продублировать, выставив бит в общем аварийном регистре. Также может потребоваться введение задержки на срабатывание аварии, так как значение может иметь "дребезг" который надо фильтровать, прежде чем генерировать аварию в журнале. Кроме этого удобнее, когда все аварии описаны в одном месте, а не разбросаны по сотням регистров. Т.е. рациональнее использовать один или несколько несколько 32-битных регистров для описания всех возможных аварий, и скрипт в котором эти аварии будут записываться в этот регистр по разным условиям. Ниже приведен пример такого скрипта:
Допустим, есть некая функциональная единица, например приточная вентиляционная установка, в которой есть некий общий признак аварии, есть несколько регистров с кодами текущих ошибок от частотных преобразователей и ситуация, когда один из регистров (влажность, СО2 и др.) вышел за допустимый диапазон, что является также аварийной ситуацией.
Тогда скрипт, который обработает все эти ситуации и сформирует нужные флаги на своих местах может выглядеть так:
allAlerts = { -- регистр бит - код ошибки тип операции
{srcAlias = "pv1Status", bits = {[1] = 1}, checktype = "bit9"},
{srcAlias = "vfdStatus_1", bits = {[2] = 10, [3] = 20, [4] = 30, [5] = 40}, checktype = "=="},
{srcAlias = "vfdStatus_2", bits = {[6] = 10, [7] = 20, [8] = 30, [9] = 40}, checktype = "=="},
{srcAlias = "pv1ZoneHumidity", bits = {[10] = 90}, checktype = ">="}
}
intAlertReg = "alertsReg" -- ОБЩИЙ РЕГИСТР АВАРИЙ
function main (userId)
DEBUG("Entered script")
local alertInput, alertOut = 0,0 -- временные переменные для чтения аварий и формирования результата
local digit = 0 -- номер бита в исходном регистре, указывающий на аварию..
--[[
Если назвать единообразно все параметры,
из которых надо формировать аварии и сложить их в одну структуру,
тогда можно использовать только один цикл for, например так:
--]]
for i,v in pairs(allAlerts) do
alertInput = GetReg(v.srcAlias) -- читаем регистр
DEBUG("Регистр для анализа = ".." "..v.srcAlias.." = "..alertInput)
for j,k in pairs(v.bits) do -- выполнится по числу элементов в под-табличке bits
-- проверяем тип операции - точное совпадение или другое условие
if (v.checktype == "==") then
DEBUG("Тип сравнения - точное совпадение")
-- проверяем регистр на один из кодов ошибок
if (alertInput == k) then
alertOut = setbit(alertOut, bit(j))
else
alertOut = clearbit(alertOut, bit(j))
end
-- проверяем определенный бит
elseif (string.find(v.checktype, "bit%d+") ~= nil) then
-- %d+ паттерн любая последовательность цифр
DEBUG("Тип сравнения - проверка бита")
_, _, digit = string.find(v.checktype,"(%d+)")
digit = tonumber(digit)
DEBUG("digit = "..digit)
if hasbit(alertInput, bit(digit)) then -- если заданный бит установлен во входном регистре
alertOut = setbit(alertOut, bit(j))
else
alertOut = clearbit(alertOut, bit(j))
end
elseif (v.checktype == ">=") then
-- параметр больше чем значение
if (alertInput >= k) then
alertOut = setbit(alertOut, bit(j))
else
alertOut = clearbit(alertOut, bit(j))
end
else
--- другие операции
end -- if checktype
end -- for bits inside
end -- for allAlerts
-- теперь просто записать то что получилось в общий регистр аварий
WriteReg(intAlertReg, alertOut)
end -- main
----------------- ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ ----------------------------------
function bit(n)
return 2 ^ (n - 1) -- возвращает число - вес разряда номер n
end
function hasbit(x, p)
return x % (p + p) >= p -- возвращает состояние бита p как true/false; if hasbit(value, bit(2)) then ...
end
function setbit(x, p)
return hasbit(x, p) and x or x + p -- установить бит № p в х Пример использования: х = setbit(х, bit(p))
end
function clearbit(x, p)
return hasbit(x, p) and x - p or x -- тоже только снять бит
end
Если различных операций над значениями много: не только сравнение, но и например проверка конкретного бита и т.п. то можно детали реализации спрятать в функцию, которая получит на вход табличку с типом операции (установлен ли конкретный бит, код ошибки, параметр в границах и т.п.) и входным значением и поставит или сбросит нужный бит.
for i,v in pairs(allAlerts) do
alertInput = GetReg(v.srcAlias) -- читаем регистр
alertOut = MyGetAlerts(alertInput, alertOut, v) -- вызываем функцию, которая посмотрит что надо сделать по полю v[3], т.е. allAlerts[3]
end -- for